MTEX support the following formats for storing and importing of ODFs:
- .mat file - lossless, specific for MTEX, binary format
- MTEX file - lossless, specific for MTEX, ASCII format
- VPSC file - not lossless, ASCII format
- .txt file - not lossless, ASCII format
Importing ODF data into MTEX means to create an ODF variable from data files containing Euler angles and weights. Once such an variable has been created the data can be analyzed and processed in many ways. See e.g. ODFCalculations. The most simplest way to import ODF data is to use the import wizard, which can be started either by typing into the command line
import_wizard_old('ODF')
The import wizard provides a gui to import data of almost all ASCII data formats and allows to save the imported data as an ODF variable to the workspace or to generate a m-file loading the data automatically.
A script generated by the import wizard typically look as follows.
% define crystal and specimen symmetry
cs = crystalSymmetry('cubic');
% the file name
fname = [mtexDataPath '/ODF/odf.txt'];
% load the data
odf = SO3Fun.load(fname,'CS',cs,'Bunge',...
'ColumnNames',{'Euler 1','Euler 2','Euler 3','weights'});
% plot data
plot(odf,'sections',6,'silent')Interpolating the ODF. This might take some time...
Warning: Maximum number of iterations reached, result may not have
converged to the optimum yet.
What the weights mean
ASCII files store an ODF as a table of orientations and weights. That table is not a complete description of a function - it fixes the ODF at finitely many points and says nothing in between. Worse, the weight column is ambiguous. It may either
- give the value of the ODF at that orientation, or
- give the volume of a bell shaped component centered there.
MTEX therefore has to be told which of the two is meant, and the answer changes the resulting ODF.
Interpolation
Reading the weights as function values is requested by the flag 'interp', which is also the default. MTEX then fits a radial basis function ODF that reproduces the given values at the given orientations.
odfInterp = SO3Fun.load(fname,'CS',cs,'Bunge','interp',...
'ColumnNames',{'Euler 1','Euler 2','Euler 3','weights'});
[norm(odfInterp)^2, max(odfInterp)]Interpolating the ODF. This might take some time...
Warning: Maximum number of iterations reached, result may not have
converged to the optimum yet.
ans =
1.2053 3.4990Density Estimation
Reading them as component volumes is requested by 'density'. This is kernel density estimation and it needs a second piece of information that the file does not contain - the halfwidth of the bell shaped kernel placed at each orientation.
for hw = [5 10 20]*degree
odfDens = SO3Fun.load(fname,'CS',cs,'Bunge','density','halfwidth',hw,...
'ColumnNames',{'Euler 1','Euler 2','Euler 3','weights'});
fprintf('halfwidth %2d degree : texture index %.3f, maximum %.2f\n',...
round(hw./degree), norm(odfDens)^2, max(odfDens));
endhalfwidth 5 degree : texture index 1.177, maximum 3.12
halfwidth 10 degree : texture index 1.117, maximum 2.35
halfwidth 20 degree : texture index 1.031, maximum 1.56
The halfwidth is a genuine free parameter - a wide kernel smears the texture out and a narrow one leaves the individual components standing. There is no value that can be recovered from the file, so it has to come from knowledge about how the data were produced. The section Optimal Kernel Selection discusses how to choose it when the file holds a discrete sample of orientations.