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 Pixels Mineral Symmetry Crystal reference frame 0 1139 4052 notIndexed 1 242 14093 Forsterite mmm 2 177 1397 Enstatite mmm 3 104 759 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 Pixels Mineral Symmetry Crystal reference frame 1 1 1548 Forsterite mmm Id Phase Pixels GOS phi1 Phi phi2 1617 1 1548 0.0134298 167 81 251
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 Pixels Mineral Symmetry Crystal reference frame 1 242 14093 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 Pixels Mineral Symmetry Crystal reference frame 1 5 5784 Forsterite mmm Id Phase Pixels GOS phi1 Phi phi2 798 1 1447 0.0135449 166 127 259 876 1 1075 0.00807547 153 68 237 999 1 1044 0.00780641 89 99 224 1617 1 1548 0.0134298 167 81 251 1620 1 670 0.0899964 145 79 273

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

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 Pixels Mineral Symmetry Crystal reference frame 1 242 14093 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 Pixels Mineral Symmetry Crystal reference frame 1 12 2979 Forsterite mmm Id Phase Pixels GOS phi1 Phi phi2 359 1 63 0.0131989 177 140 249 389 1 1 0 167 128 260 622 1 352 0.00902437 153 122 252 636 1 305 0.0165523 164 115 267 680 1 331 0.0207504 152 144 247 798 1 1447 0.0135449 166 127 259 1297 1 289 0.0347001 166 147 260 1549 1 1 0 1 47 279 1609 1 48 0.019762 158 140 259 1629 1 10 0.019553 172 125 260 1660 1 129 0.00839482 1 47 279 1662 1 3 0.00475795 1 47 279

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 Pixels Mineral Symmetry Crystal reference frame 1 1080 152345 Forsterite mmm 2 515 26058 Enstatite mmm 3 1496 9064 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 grainId which stores the ids of the neigbouring grains. In the case of an outer grain boundary one of the neighbouring grains has the id zero. We can filter out all these boundary segments by
% ids of the outer boundary segment outerBoundary_id = any(grains.boundary.grainId==0,2); plot(grains) hold on plot(grains.boundary(outerBoundary_id),'linecolor','red','linewidth',2) hold off

Now grains.boundary(outerBoundary_id).grainId is a list of grain ids where the first column is zero, indicating the outer boundary, and the second column contains the id of the boundary grain. Hence, it remains to remove all grains with these ids.
% next we compute the corresponding grain_id grain_id = grains.boundary(outerBoundary_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 Pixels Mineral Symmetry Crystal reference frame 1 968 116882 Forsterite mmm 2 480 23877 Enstatite mmm 3 1467 8871 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.3.0 |