Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DOC: Improve explanations for the Find Average C-Axis algorithm. #741

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/Plugins/OrientationAnalysis/docs/FindAvgCAxesFilter.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@ Statistics (Crystallographic)
This **Filter** determines the average C-axis location of each **Feature** by the following algorithm:

1. Gather all **Elements** that belong to the **Feature**
2. Determine the location of the c-axis in the sample *reference frame* for the rotated quaternions for all **Elements**
2. Determine the location of the c-axis in the sample *reference frame* for the rotated quaternions for all **Elements**. This is achieved by converting the input quaternion to
and orientation matrix (which represents a passive transform matrix), taking the transpose of the matrix to convert it from passive to active, and thne multiplying the
transposed matrix by the crystallographic C-Axis direction vector <001>.
3. Average the locations and store as the average for the **Feature**

*Note:* This **Filter** will only work properly for *Hexagonal* materials. The **Filter** does not apply any symmetry operators because there is only one c-axis (<001>) in *Hexagonal* materials and thus all symmetry operators will leave the c-axis in the same position in the sample *reference frame*. However, in *Cubic* materials, for example, the {100} family of directions are all equivalent and the <001> direction will change location in the sample *reference frame* when symmetry operators are applied.

This filter will error out if **ALL** phases are non-hexagonal. Any non-hexagonal phases will have their computed values set to NaN value.

% Auto generated parameter table will be inserted here

## Example Pipelines
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,26 +85,35 @@ Result<> FindAvgCAxes::operator()()
if(crystalStructureType == EbsdLib::CrystalStructure::Hexagonal_High || crystalStructureType == EbsdLib::CrystalStructure::Hexagonal_Low)
{
const usize quatIndex = i * 4;

// Create the 3x3 Orientation Matrix from the Quaternion. This represents a passive rotation matrix
OrientationF oMatrix = OrientationTransformation::qu2om<QuatF, OrientationF>({quats[quatIndex], quats[quatIndex + 1], quats[quatIndex + 2], quats[quatIndex + 3]});

// Convert the quaternion matrix to a transposed g matrix so when caxis is multiplied by it, it will give the sample direction that the caxis is along
// Convert the passive rotation matrix to an active rotation matrix
g1T = OrientationMatrixToGMatrixTranspose(oMatrix);

// Multiply the active transformation matrix by the C-Axis (as Miller Index). This actively rotates
// the crystallographic C-Axis (which is along the <0,0,1> direction) into the physical sample
// reference frame
c1 = g1T * cAxis;

// normalize so that the magnitude is 1
c1.normalize();

// Compute the running average c-axis and normalize the result
curCAxis[0] = avgCAxes[cAxesIndex] / counter[featureIds[i]];
curCAxis[1] = avgCAxes[cAxesIndex + 1] / counter[featureIds[i]];
curCAxis[2] = avgCAxes[cAxesIndex + 2] / counter[featureIds[i]];

curCAxis.normalize();

// Ensure that angle between the current point's sample reference frame C-Axis
// and the running average sample C-Axis is positive
w = ImageRotationUtilities::CosBetweenVectors(c1, curCAxis);
if(w < 0)
{
c1 *= -1.0f;
}
// Continue summing up the rotations
counter[featureIds[i]]++;
avgCAxes[cAxesIndex] += c1[0];
avgCAxes[cAxesIndex + 1] += c1[1];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,11 @@ Result<> FindAvgOrientations::operator()()
float32 count = counts[featureId];
QuatF curAvgQuat(avgQuats[featureIdOffset] / count, avgQuats[featureIdOffset + 1] / count, avgQuats[featureIdOffset + 2] / count, avgQuats[featureIdOffset + 3] / count);

// Get the pointer to the current voxel's Quaternion
QuatF voxQuat(quats[i * 4], quats[i * 4 + 1], quats[i * 4 + 2], quats[i * 4 + 3]); // Makes a copy into voxQuat!!!!
// Make a copy of the current quaternion from the DataArray into a QuatF object
QuatF voxQuat(quats[i * 4], quats[i * 4 + 1], quats[i * 4 + 2], quats[i * 4 + 3]);
QuatF nearestQuat = orientationOps[crystalStructures[phase]]->getNearestQuat(curAvgQuat, voxQuat);

// Add the running average quat with the current quat
curAvgQuat = curAvgQuat + nearestQuat;
// Copy the new curAvgQuat back into the output array
avgQuats[featureIdOffset] = curAvgQuat.x();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ Parameters ImportH5EspritDataFilter::parameters() const
params.insert(std::make_unique<OEMEbsdScanSelectionParameter>(k_SelectedScanNames_Key, "Scan Names", "The name of the scan in the .h5 file. EDAX can store multiple scans in a single file",
OEMEbsdScanSelectionParameter::ValueType{},
/* OEMEbsdScanSelectionParameter::AllowedManufacturers{EbsdLib::OEM::Bruker, EbsdLib::OEM::DREAM3D},*/
OEMEbsdScanSelectionParameter::EbsdReaderType::Esprit, OEMEbsdScanSelectionParameter::ExtensionsType{".h5"}));
OEMEbsdScanSelectionParameter::EbsdReaderType::Esprit, OEMEbsdScanSelectionParameter::ExtensionsType{".h5", ".hdf5"}));
params.insert(std::make_unique<Float32Parameter>(k_ZSpacing_Key, "Z Spacing (Microns)", "The spacing in microns between each layer.", 1.0f));
params.insert(std::make_unique<VectorFloat32Parameter>(k_Origin_Key, "Origin", "The origin of the volume", std::vector<float32>{0.0F, 0.0F, 0.0F}, std::vector<std::string>{"x", "y", "z"}));
params.insert(std::make_unique<BoolParameter>(k_DegreesToRadians_Key, "Convert Euler Angles to Radians", "Whether or not to convert the euler angles to radians", true));
Expand Down