Working with Grains
How to index grains and access shape properties.
On this page ... |
Accessing individual grains |
Indexing by a Condition |
Indexing by orientation or position |
Grain-size Analysis |
Spatial Dependencies |
Grains have several intrinsic properties, which can be used for statistical, shape as well as for spatial analysis
Let us first import some EBSD data and reconstruct grainss
plotx2east mtexdata forsterite ebsd = ebsd(inpolygon(ebsd,[5 2 10 5]*10^3)); grains = calcGrains(ebsd) plot(ebsd) hold on plot(grains.boundary,'linewidth',2) hold off
grains = grain2d Phase Grains Mineral Symmetry Crystal reference frame Phase 0 1139 notIndexed 1 242 Forsterite mmm 2 177 Enstatite mmm 3 104 Diopside 12/m1 X||a*, Y||b*, Z||c Properties: GOS, meanRotation

Accessing individual grains
The variabe grains is essentially a large vector of grains. Thus when applying a function like area to this variabe we obtain a vector of the same lenght with numbers representing the area of each grain
grain_area = grains.area;
As a first rather simple application we could colorize the grains according to their area, i.e., according to the numbers stored in grain_area
plot(grains,grain_area)

As a second application we can ask for the largest grain within our data set. The maximum value and its position within a vector is found by the Matlab command max.
[max_area,max_id] = max(grain_area)
max_area = 3.8945e+06 max_id = 1617
The number max_id is the position of the grain with maximum area within the variabe grains. We can access this specific grain by direct indexing
grains(max_id)
ans = grain2d Phase Grains Mineral Symmetry Crystal reference frame Phase 1 1 Forsterite mmm GOS meanRotation 0.0134298 96.5538
and so we can plot it
hold on plot(grains(max_id).boundary,'linecolor','red','linewidth',1.5) hold off

Note that this way of addressing individuell grains can be generalized to many grains. E.g. assume we are interested in the largest 5 grains. Then we can sort the vector grain_area and take the indices of the 5 largest grains.
[sorted_area,sorted_id] = sort(grain_area,'descend'); large_grain_id = sorted_id(1:5); hold on plot(grains(large_grain_id).boundary,'linecolor','green','linewidth',1.5) hold off

Indexing by a Condition
By the same syntax as above we can also single out grains that satisfy a certain condition. I.e., to access are grains that are at least half as large as the largest grain we can do
condition = grain_area > max_area/2; hold on plot(grains(condition).boundary,'linecolor','red','linewidth',1.5) hold off

This is a very powerfull way of accessing grains as the condition can be build up using any grain property. As an example let us consider the phase. The phase of the first five grains we get by
grains(1:5).phase
ans = 0 0 0 0 2
Now we can access or grains of the first phase Forsterite by the condition
condition = grains.phase == 1; plot(grains(condition))

To make the above more directly you can use the mineral name for indexing
grains('forsterite')
ans = grain2d Phase Grains Mineral Symmetry Crystal reference frame Phase 1 242 Forsterite mmm Properties: GOS, meanRotation
Logical indexing allows also for more complex queries, e.g. selecting all grains perimeter larger then 6000 and at least 600 measurements within
condition = grains.perimeter>6000 & grains.grainSize >= 600; selected_grains = grains(condition) plot(selected_grains)
selected_grains = grain2d Phase Grains Mineral Symmetry Crystal reference frame Phase 1 5 Forsterite mmm GOS meanRotation 0.0135449 136.039 0.00807547 73.5021 0.00780641 107.06 0.0134298 96.5538 0.0899964 94.7181

Indexing by orientation or position
One can also select a grain by its spatial coordinates using the syntax grains(x,y)
x = 12000; y = 4000; plot(grains); hold on plot(grains(x,y).boundary,'linewidth',2,'linecolor','r') plot(x,y,'marker','s','markerfacecolor','k',... 'markersize',10,'markeredgecolor','w') hold off
Error using vertcat Dimensions of matrices being concatenated are not consistent. Error in scribe.legend/init>PlotAxesChildAdded (line 527) str = [str(1:insertindex-1);{newstr};str(insertindex:length(str))];

In order to select all grains with a certain orientation one can do
% restrict first to Forsterite phase grains_fo = grains('fo') % the reference orientation ori = orientation('Euler',350*degree,50*degree,100*degree,grains('fo').CS) % select all grain with misorientation angle to ori less then 20 degree grains_selected = grains_fo(angle(grains_fo.meanOrientation,ori)<20*degree) plot(grains_selected)
grains_fo = grain2d Phase Grains Mineral Symmetry Crystal reference frame Phase 1 242 Forsterite mmm Properties: GOS, meanRotation ori = orientation size: 1 x 1 crystal symmetry : Forsterite (mmm) specimen symmetry: 1 Bunge Euler angles in degree phi1 Phi phi2 Inv. 350 50 100 0 grains_selected = grain2d Phase Grains Mineral Symmetry Crystal reference frame Phase 1 12 Forsterite mmm GOS meanRotation 0.0131989 146.942 0 136.656 0.00902437 127.209 0.0165523 128.344 0.0207504 145.613 0.0135449 136.039 0.0347001 152.446 0 90.4099 0.019762 144.639 0.019553 135.881 0.00839482 90.184 0.00475795 90.289

Grain-size Analysis
Lets go back to the grain size and analyze its distribution. To this end we consider the complete data set.
mtexdata forsterite % consider only indexed data for grain segmentation ebsd = ebsd('indexed'); % perform grain segmentation [grains,ebsd.grainId] = calcGrains(ebsd)
grains = grain2d Phase Grains Mineral Symmetry Crystal reference frame Phase 1 1080 Forsterite mmm 2 515 Enstatite mmm 3 1496 Diopside 12/m1 X||a*, Y||b*, Z||c Properties: GOS, meanRotation ebsd = EBSD Phase Orientations Mineral Color Symmetry Crystal reference frame 1 152345 (81%) Forsterite light blue mmm 2 26058 (14%) Enstatite light green mmm 3 9064 (4.8%) Diopside light red 12/m1 X||a*, Y||b*, Z||c Properties: bands, bc, bs, error, mad, x, y, grainId Scan unit : um
Then the following command gives you a nice overview over the grain size distributions of the grains
hist(grains)

Sometimes it is desireable to remove all boundary grains as they might distort grain statistics. To do so one should remember that each grain boundary has a property phaseId which is zero if the face has an outer boundary.
% first we get all faces that have an outer boundary face_id = grains.boundary.hasPhaseId(0); plot(grains) hold on plot(grains.boundary(face_id),'linecolor','red','linewidth',2) hold off

% next we compute the corresponding grain_id grain_id = grains.boundary(face_id).grainId; % remove all zeros grain_id(grain_id==0) = []; % and plot the boundary grains plot(grains(grain_id))

finally we can remove the boundary grains by
grains(grain_id) = [] plot(grains)
grains = grain2d Phase Grains Mineral Symmetry Crystal reference frame Phase 1 968 Forsterite mmm 2 480 Enstatite mmm 3 1467 Diopside 12/m1 X||a*, Y||b*, Z||c Properties: GOS, meanRotation

Beside the area there are various other geometric properties that can be computed for grains, e.g., the perimeter, the diameter, the equivalentRadius, the equivalentPerimeter, the aspectRatio, and the shapeFactor. The following is a simple scatter plot of shape factor against aspact ratio to check for correlation.
% the size of the dots corresponds to the area of the grains close all scatter(grains.shapeFactor, grains.aspectRatio, 70*grains.area./max(grains.area))

plot(grains,log(grains.aspectRatio))

Spatial Dependencies
One interessting question would be, wether a polyphase system has dependence in the spatial arrangement or not, therefor we can count the transitions to a neighbour grain
%[J, T, p ] = joinCount(grains,grains.phase)
MTEX 4.0.10 |