Skip to content
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
12 changes: 12 additions & 0 deletions src/Plugins/OrientationAnalysis/docs/ComputeIPFColorsFilter.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@ Processing (Crystallography)

This **Filter** will generate *inverse pole figure* (IPF) colors. The user can enter the *Reference Direction*, which defaults to [001]. The **Filter** also has the option to apply a black color to all "bad" **Elements**, as defined by a boolean *mask* array, which can be generated using the Threshold Objects **Filter** or any other filter that generates a "mask" of the data and outputs either a bool or uint8 array.

The IPF color for each **Element** is computed by [EbsdLib](https://github.com/BlueQuartzSoftware/EbsdLib) from the **Element**'s Euler angles, the reference direction, and the crystal structure (Laue class) of its phase. **Elements** whose phase has an unknown/unsupported crystal structure, and **Elements** masked as "bad", are colored black (0, 0, 0).

### Color Key

The *Color Key* parameter selects which IPF coloring scheme is used:

+ **TSL** — legacy primary-corner standard-stereographic-triangle coloring (EDAX/OIM Analysis default). This is the scheme produced by DREAM3D 6.x and is the default.
+ **PUCM** — perceptually-uniform color map (Patala / MTEX-style).
+ **Nolze-Hielscher** — MTEX HSV-style coloring.

The default (TSL) reproduces the coloring of earlier DREAM3D versions; PUCM and Nolze-Hielscher are new schemes with no DREAM3D 6.x equivalent.

### Originating Data Notes

+ TSL (.ang file)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ class ComputeIPFColorsImpl
{
public:
ComputeIPFColorsImpl(ComputeIPFColors* filter, nx::core::FloatVec3 referenceDir, nx::core::Float32Array& eulers, nx::core::Int32Array& phases, nx::core::UInt32Array& crystalStructures,
int32_t numPhases, const nx::core::IDataArray* goodVoxels, nx::core::UInt8Array& colors, ebsdlib::ColorKeyKind colorKey)
int32_t numPhases, const nx::core::IDataArray* maskArray, nx::core::UInt8Array& colors, ebsdlib::ColorKeyKind colorKey)
: m_Filter(filter)
, m_ReferenceDir(referenceDir)
, m_CellEulerAngles(eulers.getDataStoreRef())
, m_CellPhases(phases.getDataStoreRef())
, m_CrystalStructures(crystalStructures.getDataStoreRef())
, m_NumPhases(numPhases)
, m_GoodVoxels(goodVoxels)
, m_MaskArray(maskArray)
, m_CellIPFColors(colors.getDataStoreRef())
, m_ColorKey(colorKey)
{
Expand All @@ -42,9 +42,9 @@ class ComputeIPFColorsImpl
{
using MaskArrayType = DataArray<T>;
const MaskArrayType* maskArray = nullptr;
if(nullptr != m_GoodVoxels)
if(nullptr != m_MaskArray)
{
maskArray = dynamic_cast<const MaskArrayType*>(m_GoodVoxels);
maskArray = dynamic_cast<const MaskArrayType*>(m_MaskArray);
}

std::vector<ebsdlib::LaueOps::Pointer> ops = ebsdlib::LaueOps::GetAllOrientationOps();
Expand Down Expand Up @@ -93,13 +93,13 @@ class ComputeIPFColorsImpl

void run(size_t start, size_t end) const
{
if(m_GoodVoxels != nullptr)
if(m_MaskArray != nullptr)
{
if(m_GoodVoxels->getDataType() == DataType::boolean)
if(m_MaskArray->getDataType() == DataType::boolean)
{
convert<bool>(start, end);
}
else if(m_GoodVoxels->getDataType() == DataType::uint8)
else if(m_MaskArray->getDataType() == DataType::uint8)
{
convert<uint8>(start, end);
}
Expand All @@ -122,7 +122,7 @@ class ComputeIPFColorsImpl
nx::core::Int32AbstractDataStore& m_CellPhases;
nx::core::UInt32AbstractDataStore& m_CrystalStructures;
int32_t m_NumPhases = 0;
const nx::core::IDataArray* m_GoodVoxels = nullptr;
const nx::core::IDataArray* m_MaskArray = nullptr;
nx::core::UInt8AbstractDataStore& m_CellIPFColors;
ebsdlib::ColorKeyKind m_ColorKey = ebsdlib::ColorKeyKind::TSL;
};
Expand All @@ -143,9 +143,6 @@ ComputeIPFColors::~ComputeIPFColors() noexcept = default;
// -----------------------------------------------------------------------------
Result<> ComputeIPFColors::operator()()
{

std::vector<ebsdlib::LaueOps::Pointer> orientationOps = ebsdlib::LaueOps::GetAllOrientationOps();

nx::core::Float32Array& eulers = m_DataStructure.getDataRefAs<Float32Array>(m_InputValues->cellEulerAnglesArrayPath);
nx::core::Int32Array& phases = m_DataStructure.getDataRefAs<Int32Array>(m_InputValues->cellPhasesArrayPath);

Expand All @@ -168,25 +165,25 @@ Result<> ComputeIPFColors::operator()()
algArrays.push_back(&crystalStructures);
algArrays.push_back(&ipfColors);

nx::core::IDataArray* goodVoxelsArray = nullptr;
if(m_InputValues->useGoodVoxels)
nx::core::IDataArray* maskArray = nullptr;
if(m_InputValues->useMask)
{
goodVoxelsArray = m_DataStructure.getDataAs<IDataArray>(m_InputValues->goodVoxelsArrayPath);
algArrays.push_back(goodVoxelsArray);
maskArray = m_DataStructure.getDataAs<IDataArray>(m_InputValues->maskArrayPath);
algArrays.push_back(maskArray);
}

// Allow data-based parallelization
ParallelDataAlgorithm dataAlg;
dataAlg.setRange(0, totalPoints);
dataAlg.requireArraysInMemory(algArrays);

dataAlg.execute(ComputeIPFColorsImpl(this, normRefDir, eulers, phases, crystalStructures, numPhases, goodVoxelsArray, ipfColors, m_InputValues->colorKey));
dataAlg.execute(ComputeIPFColorsImpl(this, normRefDir, eulers, phases, crystalStructures, numPhases, maskArray, ipfColors, m_InputValues->colorKey));

if(m_PhaseWarningCount > 0)
{
std::string message = fmt::format("The Ensemble Phase information only references {} phase(s) but {} cell(s) had a phase value greater than {}. \
This indicates a problem with the input cell phase data. DREAM3D-NX will give INCORRECT RESULTS.",
(numPhases - 1), m_PhaseWarningCount, (numPhases - 1));
(numPhases - 1), m_PhaseWarningCount.load(), (numPhases - 1));

return nx::core::MakeErrorResult(-48000, message);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include <EbsdLib/Core/EbsdLibConstants.h>

#include <atomic>
#include <vector>

namespace nx::core
Expand All @@ -21,8 +22,8 @@ namespace nx::core
struct ORIENTATIONANALYSIS_EXPORT ComputeIPFColorsInputValues
{
std::vector<float> referenceDirection;
bool useGoodVoxels;
DataPath goodVoxelsArrayPath;
bool useMask;
DataPath maskArrayPath;
DataPath cellPhasesArrayPath;
DataPath cellEulerAnglesArrayPath;
DataPath crystalStructuresArrayPath;
Expand Down Expand Up @@ -59,7 +60,8 @@ class ORIENTATIONANALYSIS_EXPORT ComputeIPFColors
const std::atomic_bool& m_ShouldCancel;
const ComputeIPFColorsInputValues* m_InputValues = nullptr;

int32_t m_PhaseWarningCount = 0;
// Written concurrently from the ParallelDataAlgorithm worker, so it must be atomic.
std::atomic_int32_t m_PhaseWarningCount = 0;
};

} // namespace nx::core
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,10 @@ IFilter::PreflightResult ComputeIPFColorsFilter::preflightImpl(const DataStructu
{

auto pReferenceDirValue = filterArgs.value<VectorFloat32Parameter::ValueType>(k_ReferenceDir_Key);
auto pUseGoodVoxelsValue = filterArgs.value<bool>(k_UseMask_Key);
auto pUseMaskValue = filterArgs.value<bool>(k_UseMask_Key);
auto pCellEulerAnglesArrayPathValue = filterArgs.value<DataPath>(k_CellEulerAnglesArrayPath_Key);
auto pCellPhasesArrayPathValue = filterArgs.value<DataPath>(k_CellPhasesArrayPath_Key);
auto pGoodVoxelsArrayPathValue = filterArgs.value<DataPath>(k_MaskArrayPath_Key);
auto pMaskArrayPathValue = filterArgs.value<DataPath>(k_MaskArrayPath_Key);
auto pCrystalStructuresArrayPathValue = filterArgs.value<DataPath>(k_CrystalStructuresArrayPath_Key);
auto pCellIPFColorsArrayNameValue = pCellEulerAnglesArrayPathValue.replaceName(filterArgs.value<std::string>(k_CellIPFColorsArrayName_Key));

Expand All @@ -117,9 +117,9 @@ IFilter::PreflightResult ComputeIPFColorsFilter::preflightImpl(const DataStructu
dataPaths.push_back(pCellEulerAnglesArrayPathValue);
dataPaths.push_back(pCellPhasesArrayPathValue);

if(pUseGoodVoxelsValue)
if(pUseMaskValue)
{
dataPaths.push_back(pGoodVoxelsArrayPathValue);
dataPaths.push_back(pMaskArrayPathValue);
}

auto tupleValidityCheck = dataStructure.validateNumberOfTuples(dataPaths);
Expand Down Expand Up @@ -147,10 +147,10 @@ Result<> ComputeIPFColorsFilter::executeImpl(DataStructure& dataStructure, const
ComputeIPFColorsInputValues inputValues;

inputValues.referenceDirection = filterArgs.value<VectorFloat32Parameter::ValueType>(k_ReferenceDir_Key);
inputValues.useGoodVoxels = filterArgs.value<bool>(k_UseMask_Key);
inputValues.useMask = filterArgs.value<bool>(k_UseMask_Key);
inputValues.cellEulerAnglesArrayPath = filterArgs.value<DataPath>(k_CellEulerAnglesArrayPath_Key);
inputValues.cellPhasesArrayPath = filterArgs.value<DataPath>(k_CellPhasesArrayPath_Key);
inputValues.goodVoxelsArrayPath = filterArgs.value<DataPath>(k_MaskArrayPath_Key);
inputValues.maskArrayPath = filterArgs.value<DataPath>(k_MaskArrayPath_Key);
inputValues.crystalStructuresArrayPath = filterArgs.value<DataPath>(k_CrystalStructuresArrayPath_Key);
inputValues.cellIpfColorsArrayPath = inputValues.cellEulerAnglesArrayPath.replaceName(filterArgs.value<std::string>(k_CellIPFColorsArrayName_Key));

Expand Down
Loading
Loading