Grain Graph Based Parent Grain Reconstrution
edit page
This script demonstrates the grain graph approach to parent phase reconstruction in a martensitic material. The methods are described in more detail in the publications
Grain reconstruction is guided in MTEX by a variable of type parentGrainReconstructor. During the reconstruction process this class keeps track about the relationship between the measured child grains and the recovered parent grains.
The parentGrainReconstructor guesses from the EBSD data what is the parent and what is the child phase. If this guess is not correct it might be specified explicitly by defining an initial guess for the parent to child orientation relationship first and passing it as a third argument to parentGrainReconstructor. Here we define this initial guess separately as the Kurdjumov Sachs orientation relationship
The output of the variable job tells us the amount of parent and child grains as well as the percentage of already recovered parent grains. Furthermore, it displays how well the current guess of the parent to child orientation relationship fits the child to child misorientations within our data. In our sample data set this fit is described by the 4 quintiles 2.5°, 3.5°, 4.5° and 5.5°.
Optimizing the parent child orientation relationship
It is well known that the phase transformation from austenite to martensite is not described by a fixed orientation relationship. In fact, the actual orientation relationship needs to be determined for each sample individually. Here, we used the iterative method proposed by Tuomo Nyyssönen and implemented in the function calcParent2Child that starts at our initial guess of the orientation relation ship and iterates towards a more optimal orientation relationship.
We observe that the optimized parent to child orientation relationship is 2.3° off the initial Kurdjumov Sachs orientation relationship and reduced the first quintil of the misfit with the child to child misorientations to 1.5°. These misfits are stored by the command calcParent2Child in the variable job.fit. In fact, the algorithm assumes that the majority of all boundary misorientations are child to child misorientations and finds the parent to child orientations relationship by minimizing this misfit. The following histogram displays the distribution of the misfit over all grain to grain misorientations.
We may explicitly compute the misfit for all child to child boundaries using the command calcGBFit. Beside the list fit it returns also the list of grain pairs for which these fits have been computed. Using the command selectByGrainId we can find the corresponding boundary segments and colorize them according to this misfit. In the code below we go one step further and adjust the transparency as a function of the misfit.
Graph based parent grain reconstruction
Next we set up a graph where each edge describes two neighboring grains and the value of this edge is the probability that these two grains belong to the same parent grain. This graph is computed by the function calcGraph. The probability is computed from the misfit of the misorientation between the two child grains to the theoretical child to child misorientation. More precisely, we model the probability by a cumulative Gaussian distribution with the mean value 'threshold' which describes the misfit at which the probability is exactly 50 percent and the standard deviation 'tolerance'.
We may visualize the graph adjusting the edgeAlpha of the boundaries between grains according to the edge value of the graph. This can be accomplished by the command plotGraph
The next step is to cluster the graph into components. This is done by the command clusterGraph which uses by default the Markovian clustering algorithm. The number of clusters can be controlled by the option 'inflationPower'. A smaller inflation power results in fewer but larger clusters.
Finally, we assume a single parent orientation for each cluster and use it to compute a parent orientation for each child grain being part of a cluster. This is done by the command calcParentFromGraph.
We observe that almost all child grains have been flipped into parent grains. The command calcParentFromGraph has two additional outputs. The misorientation angle between the reconstructed parent orientation of each child grain and the mean parent orientation of the corresponding parent grain is stored in job.grains.fit while job.grains.clusterSize contains the size of each cluster.
We may use these quantities to undo the parent orientation reconstruction for child grains with a misfit exceeding a certain threshold or belonging to a too small cluster. This can be done by the command job.revert
When used without any input argument job.revert will undo all reconstructed parent grain. This is helpful when experimenting with different parameters.
In order to fill the holes corresponding to the remaining child grains we inspect their misorientations to neighboring already reconstructed parent grains. Each of these misorientations votes for a certain parent orientation. We choose the parent orientation that gets the most votes. The corresponding commands job.calcGBVotes and job.calcParentFromVote can be adjusted by many options.
Merge similar grains and inclusions
We observe that we have many neighboring parent grains with similar orientations. These can be merged into big parent grains using the command mergeSimilar
We may be still a bit unsatisfied with the result as the large parent grains contain many poorly indexed inclusions where we failed to assign to a parent orientation. We may use the command mergeInclusions to merge all inclusions with fever pixels then a certain threshold into the surrounding parent grains.
Compute Child Variants
Knowing the parent grain orientations we may compute the variants and packets of each child grain using the command calcVariants. The values are stored with the properties job.transformedGrains.variantId and job.transformedGrains.packetId. The packetId is defined as the closest {111} plane in austenite to the (011) plane in martensite.
We can also directly identify the child grains belonging to the selected parent grains. Remember that the initial grains are stored in job.grainsPrior and that the vector job.mergeId stores for every initial grain the id of the corresponding parent grain. Combining these two information we do
In order to check our parent grain reconstruction we chose the single parent grain outlined in the above map and plot all child variants of its reconstructed parent orientation together with the actually measured child orientations inside the parent grain. In order to compute the variantId and packetId we use the command calcVariantId.
Parent EBSD reconstruction
So far our analysis was at the grain level. However, once parent grain orientations have been computed we may also use them to compute parent orientations of each pixel in our original EBSD map. This is done by the command calcParentEBSD
We obtain even a measure parentEBSD.fit for the correspondence between the parent orientation reconstructed from the single pixel and the parent orientation of the grain. Lets visualize this fit
Denoise the parent map
Finally, we may apply filtering to the parent map to fill non indexed or not reconstructed pixels. To this end we first run grain reconstruction on the parent map
and then use the command smooth to fill the holes in the reconstructed parent map