Open Matlab File in the Editor MTEX

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)