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 grains
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 boundary segments: 10420 triple points: 903 Properties: GOS, meanRotation
The variable grains is essentially a large vector of grains. Thus when applying a function like area to this variable 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 are 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 a maximum area within the variable 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 boundary segments: 424 triple points: 70 Id Phase Pixels GOS phi1 Phi phi2 1617 1 1548 0.0129383 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 individual 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
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 powerful 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 boundary segments: 7670 triple points: 795 Properties: GOS, meanRotation
Logical indexing allows also for more complex queries, e.g. selecting all grains perimeter larger than 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 boundary segments: 1893 triple points: 244 Id Phase Pixels GOS phi1 Phi phi2 798 1 1447 0.013232 166 127 259 876 1 1075 0.00805971 153 68 237 999 1 1044 0.00753116 89 99 224 1617 1 1548 0.0129383 167 81 251 1620 1 670 0.0870135 143 78 274
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.byEuler(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 boundary segments: 7670 triple points: 795 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 boundary segments: 1603 triple points: 173 Id Phase Pixels GOS phi1 Phi phi2 359 1 63 0.0129176 177 140 250 389 1 1 0 167 128 260 622 1 352 0.00896432 153 122 252 636 1 305 0.0156453 164 115 268 680 1 331 0.0198713 152 143 247 798 1 1447 0.013232 166 127 259 1297 1 289 0.0315393 166 147 260 1549 1 1 0 1 47 279 1609 1 48 0.0169152 158 139 259 1629 1 10 0.0193004 172 125 261 1660 1 129 0.00814837 1 47 279 1662 1 3 0.00475795 1 47 279
Let's 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 boundary segments: 43912 triple points: 3417 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 desirable 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 boundary segments: 40105 triple points: 3383 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 aspect 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))
One interesting question would be, whether a polyphase system has dependence in the spatial arrangement or not, therefore, we can count the transitions to a neighbour grain
%[J, T, p ] = joinCount(grains,grains.phase)
DocHelp 0.1 beta |