This script demonstrates the grain graph approach to parent phase reconstrution in a martensitic material. The methods are described in more detail in the publications

We shall use the following sample data set.

## Setting up the parent grain reconstructor

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 explicitely 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 seperately 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 individualy. 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 explicitely 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 th 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 neighbouring 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 th 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.

Finaly, we assume a single parent orientation for each cluster and use it to compute a parent orientation for each child grain beeing part of a cluster. This is done by the command `calcParentFromGraph`

.

We observe that almost all child grains have been fliped 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`

containes the size of each cluster.

We may use these quantities to undo the parent orientation reconstruction for child grains with a misfit exeeding 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 helpfull when experimenting with different parameters.

In order to fill the holes corresponding to the remaining child grains we inspect their misorientations to neighbouring 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 neighbouring 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. Remeber 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 corespondence between the parent orientation reconstructed from the single pixel and the parent orientation of the grain. Lets visualize this fit

## Denoise the parent map

Finaly 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