download as script · edit page

MTEX for Python keeps the names of MATLAB MTEX: the classes (vector3d, orientation, EBSD, grain2d), the commands (calcGrains, calcDensity, plotPF) and their options. A MATLAB script translates line by line, and most lines change only in their punctuation. This page lists what does change, the rules of the Python language first and then the few places where MTEX itself behaves differently.

At a glance

  MATLAB Python
Start MTEX startup_mtex, once per session from mtex import *, in every script
Editor the MATLAB desktop VS Code with the Python and Jupyter extensions
Section of a script %%, run with Ctrl+Enter # %%, run with Shift+Enter
Comment % text # text
Suppress output ; at the end of a line not needed, only the last line of a cell prints
Option with a value calcGrains(ebsd, 'angle', 10*degree) calcGrains(ebsd, angle=10*degree)
Flag 'antipodal' antipodal=True
Select ebsd('indexed') ebsd['indexed']
First and last element x(1), x(end) x[0], x[-1]
Several outputs [grains, ebsd] = calcGrains(ebsd) grains = calcGrains(ebsd)
Copy ori2 = ori ori2 = ori.copy()
Join [ori1, ori2] cat(ori1, ori2)
Element-wise arithmetic a .* b, a .^ 2 a * b, a ** 2
Overlay plots hold on hold(True)
Import wizard import_wizard importWizard()
Open a documentation page edit EBSDTutorial openDoc('EBSDTutorial')

The sections below explain each row.

Starting MTEX

MATLAB MTEX is started once per session with startup_mtex. In Python, every script starts by importing MTEX:

from mtex import *

This makes every MTEX command available by its name. The setup of Python and of an editor is described in Installing MTEX for Python.

Comments start with # instead of %, and a cell of the editor starts with # %% instead of %%. There is no semicolon to suppress output: a line never prints anything, except the last line of a cell when it is a bare expression. Use print to show a value anywhere else.

ebsd = mtexdata('forsterite')
print(len(ebsd))
ebsd
245952
EBSD (y↓→x)
  size: 336 × 732 grid
  Phase  Orientations  Mineral     Color         Symmetry  Crystal reference frame
  0      58485 (24%)   notIndexed
  1      152345 (62%)  Forsterite  LightSkyBlue  mmm       Forsterite
  2      26058 (11%)   Enstatite   DarkSeaGreen  mmm       Enstatite
  3      9064 (3.7%)   Diopside    Goldenrod     12/m1     Diopside
  properties    : bands, bc, bs, error, mad
  scan unit     : um
  X × Y         : [0 → 3.655e+04] × [0 → 1.675e+04]
  square lattice: spacing 50

Options are keywords

A MATLAB option is a name followed by its value, a flag is a name alone. In Python both are keyword arguments: the option is name=value, the flag is name=True.

MATLAB Python
calcGrains(ebsd, 'angle', 10*degree) calcGrains(ebsd, angle=10*degree)
Miller(1,0,0, cs, 'antipodal') Miller(1, 0, 0, cs, antipodal=True)
plot(grains, 'linewidth', 2) plot(grains, lineWidth=2)
calcODF(pf, 'noGhostCorrection') calcODF(pf, ghostCorrection=False)

The keywords are spelled one way throughout: in camelCase (lineWidth, markerSize, displayName), a tolerance as tol, an iteration bound as maxIter, and a flag by what it switches on, so that MATLAB’s 'noSymmetry' is symmetry=False. Progress output is switched by verbose, where MATLAB silences it by 'silent': mtexdata(..., verbose=False).

A string that names something stays a string in the argument list: the kind of Miller indices 'uvw', an Euler convention 'ZYZ', an alignment 'X||a'.

grains = calcGrains(ebsd, angle=10 * degree, minPixel=5)
cs = ebsd['Forsterite'].CS
Miller(1, 0, 0, cs, 'uvw')
vector3d (Forsterite)
  u  v  w
  1  0  0

See Options for more.

Indexing with brackets, counting from zero

Selections use square brackets instead of round ones. Everything else about them stays: a phase name, a condition or a list of positions selects.

MATLAB Python
ebsd('indexed') ebsd['indexed']
ebsd('Forsterite') ebsd['Forsterite']
grains(grains.grainSize > 100) grains[grains.grainSize > 100]
gB('Forsterite', 'Forsterite') gB['Forsterite', 'Forsterite']

Positions count from 0, and a range a:b stops before b. MATLAB’s x(1) is x[0], x(1:10) is x[0:10], and x(end) is x[-1].

big = grains[grains.grainSize > 100]
big[0:3].grainSize
array([2550,  427,  121], dtype=int32)

Positions and ids are different things: the grain ids count from 1, as in MATLAB, so the first grain is at position 0 and has the id 1.

grains[0].id
array([1], dtype=int32)

See Lists and Indexing for the details.

Properties and methods

What MATLAB MTEX calls a property is written without parentheses, a command with them. MATLAB accepts rot.angle for angle(rot); Python needs the parentheses, and without them returns the command itself instead of its result.

ori = ebsd['Forsterite'].orientations[0:3]
ori.CS
crystalFrame (⊙c→a)
  mineral : Forsterite
  symmetry: mmm
  elements: 8
  a, b, c : 4.756, 10.21, 5.98
ori.angle() / degree
array([50.9455, 50.9184, 51.0415])

Every such command is also a function, as in MATLAB: angle(ori) is ori.angle().

Several outputs

A command with several outputs returns them together, and they are unpacked by commas instead of square brackets: MATLAB’s [ind, d] = find(...) is ind, d = find(...).

calcGrains is the exception. MATLAB also returns the updated map, [grains, ebsd] = calcGrains(ebsd). Python writes the grain ids into the input map, so grains = calcGrains(ebsd) suffices:

grains = calcGrains(ebsd, angle=10 * degree, minPixel=5)
ebsd.grainId[0:5]
array([[ 1,  1,  1, ..., 47, 47, 47],
       [ 1,  1,  1, ..., 47, 47, 47],
       [ 1,  1,  1, ...,  0, 47, 47],
       [ 1,  1,  1, ..., 46,  0,  0],
       [ 1,  1,  1, ...,  0, 58,  0]], dtype=int32)

Because the map is changed, compare two reconstructions on copies: calcGrains(ebsd.copy(), ...).

Assignment does not copy

In MATLAB, ori2 = ori makes a copy, and changing ori2 leaves ori alone. In Python both names refer to the same object, so a change through one is seen through the other. Ask for a copy when you want one:

ori2 = ori.copy()

Operations never change their input: ori2 = ori * rot or ebsd2 = rotate(ebsd, rot) return new objects, as in MATLAB.

Lists of objects

Square brackets in MATLAB concatenate: [ori1, ori2]. In Python square brackets build a plain Python list, which MTEX commands do not accept as a list of orientations. Use cat:

ori1 = orientation.byEuler(0, 0, 0, cs)
ori2 = orientation.byEuler(90 * degree, 0, 0, cs)
cat(ori1, ori2)
orientation (Forsterite → y↓→x)
  size: 2
  Bunge Euler angles in degree
  phi1  Phi  phi2
     0    0     0
    90    0     0

Arithmetic, numbers and control flow

The operations on MTEX objects keep their meaning: * applies a rotation, inv(ori) inverts. For numbers, MTEX uses NumPy, the standard Python package for arrays, whose operations apply elementwise without a dot.

MATLAB Python
a .* b, a ./ b, a .^ 2 a * b, a / b, a ** 2
a ~= b, ~a a != b, ~a
a && b, a \|\| b a and b, a or b
zeros(3, 1), mean(x), max(x) np.zeros(3), np.mean(x), np.max(x)
numel(x) len(x) or x.size
isnan(x) np.isnan(x)
pi, degree pi, degree
for i = 1:n ... end for i in range(n): and an indented block
if a > 0 ... end if a > 0: and an indented block
function y = f(x) ... end def f(x): and an indented block ending in return y
sprintf('%d grains', n) f'{n} grains'

Python has no end: the lines of a loop or a function are the ones indented below it. NumPy is imported as import numpy as np.

import numpy as np
for i in range(3):
  print(f"grain {big[i].id[0]}: {big[i].grainSize[0]} pixels")
grain 1: 2550 pixels
grain 4: 427 pixels
grain 7: 121 pixels

Plotting

The plotting commands are MATLAB MTEX’s and take the same options. Figures are drawn with matplotlib, the standard plotting package of Python.

MATLAB Python
figure newMtexFigure()
hold on, hold off hold(True), hold(False)
nextAxis nextAxis()
mtexColorbar mtexColorbar()
saveFigure('map.png') saveFigure('map.png')
plot(ebsd['Forsterite'], ebsd['Forsterite'].orientations)
hold(True)
plot(grains.boundary, lineWidth=1.5)
hold(False)

Names that changed

A few classes carry the names of the coming MATLAB release, where the MATLAB pages of MTEX 6 still use the old ones, and a few commands have a better name in Python than in MATLAB: a misnomer, a duplicate or a workaround for a limit of MATLAB. They take the same arguments.

MATLAB MTEX 6 Python
crystalSymmetry('m-3m', [a b c], 'mineral', 'Iron') crystalFrame('m-3m', [a, b, c], mineral='Iron')
specimenSymmetry('222') specimenFrame('222')
ebsd.opt ebsd.meta
loadEBSD(fname) loadEBSD(fname) or EBSD.load(fname)
import_wizard importWizard(), or mtex-wizard in a terminal
plotPDF(odf, h), plotPDF(ori, h) plotPF(odf, h), plotPF(ori, h)
plotIPDF(odf, r), plotIPDF(ori, r) plotIPF(odf, r), plotIPF(ori, r)
calcPDF(odf, h, r), odf.pdf(h) odf.radon(h, r), odf.radon(h)
odf.ipdf(r) odf.radon(r=r)
hist(grains) histogram(grains, grouped=True)
angle_outer(v1, v2), dot_outer(v1, v2) angle(v1, v2, outer=True), dot(v1, v2, outer=True)
eq(v1, v2), eqTol(cs1, cs2) isclose(v1, v2), isclose(cs1, cs2)
orientation.eye(cs) orientation.id(cs)
plotSpektra(odf) plotSpectrum(odf)
textureindex(odf) textureIndex(odf)
eS.addFeature_singleStep eS.addFeature('singleStep')
project2FundamentalRegion(ori) projectIntoFundamentalRegion(ori)
project2EulerFR(ori) projectIntoEulerRegion(ori)
sR.restrict2Upper sR.restrictToUpper
SO3F.SRight, SO3F.SLeft, oR.CS1, oR.CS2 SO3F.frameA, SO3F.frameB (or CS, SS)
plotx2north plottingConvention.default(north=xvector)
quiver3(t) quiver3d(t)
loadEBSD_ang(fname) loadEBSD(fname), the format from the extension or interface='ang'
export_VPSC(ori, fname) export(ori, fname, interface='VPSC')

Behaviour that differs on purpose

  • == compares coordinates. v1 == v2 of vectors, rotations, orientations, fibres or tangent vectors is true where the coordinates are equal (for rotations up to the sign of the quaternion); MATLAB’s == compares within a tolerance and up to symmetry, which is isclose(v1, v2) or v1.isclose(v2, tol=...) here.
  • calcGrains changes the map it is given, as described above.
  • A map read on a grid keeps its grid. A map whose file stores a regular grid is a two-dimensional EBSD object at once, rows by columns, where MATLAB reads a list and builds the grid by gridify. A selection such as ebsd['indexed'] is a list.
  • Moving a gridded map keeps the order of its data. rotate, shift and transform move the positions; MATLAB stores a rotated map anew. gridify(ebsd, ...) reorders explicitly.
  • Unknown options. calcGrains and most computing commands refuse a misspelt keyword; the plotting commands pass unknown ones on to matplotlib.
print(ebsd.shape, ebsd['indexed'].shape)
(336, 732) (226906,)

Where to find help

Every page of the MTEX documentation has a MATLAB and a Python version; the switch at the top of a page changes between them. The MATLAB page is the place to look for anything this port does not describe yet, and the rules of this page translate its code. openDoc('EBSDTutorial') gives a page as a script to run section by section, as edit EBSDTutorial opens a documentation script in MATLAB. The Python Tutorial is the introduction to the language, NumPy for MATLAB users the translation table for numerical code.

Citing this page. This page is part of the documentation of MTEX, a free and open source MATLAB toolbox for analyzing and modeling crystallographic textures. It was written by The MTEX Developers and is published at https://mtex-toolbox.github.io/MATLABtoPython_py.html. If you use MTEX, or reuse text or figures from this page, in your research, please cite

F. Bachmann, R. Hielscher, H. Schaeben: Texture Analysis with MTEX - Free and Open Source Software Toolbox, Solid State Phenomena 160 (2010), 63-68. 10.4028/www.scientific.net/SSP.160.63

BibTeX
@article{bachmann2010mtex,
  author  = {F. Bachmann and R. Hielscher and H. Schaeben},
  title   = {Texture Analysis with MTEX - Free and Open Source Software Toolbox},
  journal = {Solid State Phenomena},
  volume  = {160},
  pages   = {63-68},
  year    = {2010},
  doi     = {10.4028/www.scientific.net/SSP.160.63},
  url     = {https://doi.org/10.4028/www.scientific.net/SSP.160.63}
}

Other papers describing specific MTEX methods are listed under Publications — please cite the one that best fits your application. The MTEX source code is licensed under the GNU General Public License v2.0; the text and figures of this documentation are licensed under CC BY 4.0, which permits reuse — including by automated systems — provided The MTEX Developers and this page are credited.