Grains are geometry and data at the same time, and consequently there is no single file format that captures all of them. What one wants to export is usually one of three things - the grain wise table of properties, the mean orientations, or the polygons that make up the grain boundaries. This page shows all three. Exporting the picture rather than the numbers is covered in Exporting Plots.
Throughout this page we work with the Forsterite data set.
plottingConvention.default('y↑→x');
mtexdata forsterite silent
grains = calcGrains(ebsd('indexed'),'angle',10*degree);
grains = smoothBoundary(grains,5);
% remove the very small grains
grains = grains(grains.numPixel > 10)grains = grain2d (y↑→x)
Phase Grains Pixels Mineral Symmetry Color
1 443 151150 Forsterite mmm LightSkyBlue
2 184 25465 Enstatite mmm DarkSeaGreen
3 107 6962 Diopside 12/m1 Goldenrod
boundary segments: 38616 (1.6e+06 µm)
inner boundary segments: 156 (7018 µm)
triple points: 3370
Properties: meanRotation, GOSThe grain table
Every scalar grain property can be collected into a MATLAB table and written by writetable to a spreadsheet or a csv file. This is the most useful format for further statistical analysis outside of MTEX.
T = table(grains.id, grains.phase, grains.numPixel, grains.area, ...
grains.perimeter, grains.equivalentRadius, grains.GOS./degree, ...
'VariableNames',{'id','phase','numPixel','area','perimeter',...
'equivalentRadius','GOS'});
head(T)id phase numPixel area perimeter equivalentRadius GOS
__ _____ ________ __________ _________ ________________ _______
19 1 34 91250 1462.3 170.43 0.24256
21 2 16 51473 1099.2 128 0.62956
22 1 15 50640 996.04 126.96 0.42433
27 1 19 55714 1056 133.17 0.17977
30 1 26 72940 1156.8 152.37 0.28391
44 1 51 2.0553e+05 2204.5 255.78 0.19108
53 1 49 1.4694e+05 1605.6 216.27 0.48932
54 1 23 66472 1081.2 145.46 0.4652Adding the mean orientation as three Euler angle columns makes the table self contained. Since Euler angles only make sense within one crystal symmetry we restrict ourselves to the Forsterite grains from here on.
grains = grains('Forsterite');
T = T(T.phase == grains.phase(1),:);
[phi1,Phi,phi2] = grains.meanOrientation.Euler;
T.phi1 = phi1./degree;
T.Phi = Phi./degree;
T.phi2 = phi2./degree;
% we write into the temporary folder to not pollute the MTEX folder
fname = fullfile(tempdir,'grains.csv');
writetable(T,fname)and reading it back is a one liner
head(readtable(fname))id phase numPixel area perimeter equivalentRadius GOS phi1 Phi phi2
__ _____ ________ __________ _________ ________________ _______ ______ ______ ______
19 1 34 91250 1462.3 170.43 0.24256 2.5813 161.36 269.26
22 1 15 50640 996.04 126.96 0.42433 133.37 168.62 247.12
27 1 19 55714 1056 133.17 0.17977 138.49 91.149 267.06
30 1 26 72940 1156.8 152.37 0.28391 33.863 82.646 349.95
44 1 51 2.0553e+05 2204.5 255.78 0.19108 123.16 80.504 260.91
53 1 49 1.4694e+05 1605.6 216.27 0.48932 165.83 107.25 260.95
54 1 23 66472 1081.2 145.46 0.4652 166.09 111.76 264.03
55 1 44 1.3889e+05 1615.5 210.26 0.62373 139.92 82.051 260.12Mean orientations
If only the orientations are of interest, the command export is more convenient, since it knows about the Euler angle conventions. It is described in detail in Exporting Crystal Orientations.
export(grains.meanOrientation,fullfile(tempdir,'grainOri.txt'))
export also takes a struct of additional columns, which is the natural place for the grain properties that belong to each orientation
S.area = grains.area;
S.GOS = grains.GOS ./ degree;
export(grains.meanOrientation,fullfile(tempdir,'grainOri.txt'),S)
fid = fopen(fullfile(tempdir,'grainOri.txt'));
for k = 1:3, disp(fgetl(fid)); end
fclose(fid);phi1 Phi phi2 area GOS
2.58129 161.36 269.258 91250 0.242557
133.373 168.617 247.116 50640.4 0.424334For crystal plasticity codes the command export_VPSC writes the VPSC texture format, with the grain areas as weights
export_VPSC(grains.meanOrientation,...
fullfile(tempdir,'grains.tex'),'weights',grains.area)The grain geometry
The outline of a grain is a closed polygon. The property grains.poly holds, for each grain, the list of vertex indices that walks around it. These indices refer to grains.allV, the complete vertex list - not to grains.V, which is the shorter list of vertices actually in use.
V = grains.allV;
poly = grains(1).poly{1};
size(poly)ans =
1 31Hence the coordinates of the first grain are
xy = [V(poly).x, V(poly).y];
xy(1:5,:)ans =
1.0e+04 *
0.0100 1.1800
0.0058 1.1808
0.0017 1.1817
-0.0025 1.1825
-0.0025 1.1775Writing all of them into one text file, one grain after the other, is a short loop. We use the grain id as a separator so that the file can be split up again.
fname = fullfile(tempdir,'grainPolygons.txt');
fid = fopen(fname,'w');
fprintf(fid,'%% grainId x y\n');
for k = 1:min(length(grains),50)
p = grains(k).poly{1};
fprintf(fid,'%d %f %f\n',[repmat(double(grains.id(k)),1,numel(p)); ...
V(p).x.'; V(p).y.']);
end
fclose(fid);
fid = fopen(fname);
for k = 1:4, disp(fgetl(fid)); end
fclose(fid);% grainId x y
19 100.000000 11800.000000
19 58.333333 11808.333333
19 16.666667 11816.666667The individual boundary segments, together with the ids of the two grains they separate and their misorientation, are reached through grains.boundary
gB = grains.boundary('Forsterite','Forsterite');
TB = table(gB.grainId(:,1), gB.grainId(:,2), gB.segLength, ...
gB.misorientation.angle./degree, ...
'VariableNames',{'grainA','grainB','segLength','misAngle'});
head(TB)grainA grainB segLength misAngle
______ ______ _________ ________
2675 2691 50 60.549
2159 2170 50 70.835
2450 2507 70.711 90.587
2453 2507 55.902 59.531
1768 1810 53.033 60.026
1768 1810 53.033 60.026
1599 1670 39.278 60.336
1599 1670 32.044 60.336Saving in MTEX' own format
Finally, if the data is only meant to be read back by MTEX, the ordinary MATLAB save is both lossless and by far the simplest option
save(fullfile(tempdir,'grains.mat'),'grains','ebsd')Note that a .mat file is not readable by other software and is not guaranteed to load in a future MTEX version - for archiving, prefer one of the ASCII formats above.
% clean up
delete(fullfile(tempdir,'grains.csv'))
delete(fullfile(tempdir,'grainOri.txt'))
delete(fullfile(tempdir,'grains.tex'))
delete(fullfile(tempdir,'grainPolygons.txt'))
delete(fullfile(tempdir,'grains.mat'))