22
33#include " simplnx/DataStructure/DataArray.hpp"
44#include " simplnx/DataStructure/DataGroup.hpp"
5+ #include " simplnx/Utilities/ParallelDataAlgorithm.hpp"
6+
7+ #include " EbsdLib/Core/EbsdLibConstants.h"
8+ #include " EbsdLib/LaueOps/LaueOps.h"
59
610using namespace nx ::core;
711
12+ namespace
13+ {
14+ /* *
15+ * @brief The GenerateFZQuatsImpl class implements a threaded algorithm that computes the Fundamental Zone Quaternion
16+ * for a given Quaternion and Laue Class (which is based from the crystalStructures array
17+ */
18+ template <typename MaskArrayType>
19+ class GenerateFZQuatsImpl
20+ {
21+ public:
22+ GenerateFZQuatsImpl (Float32Array& quats, Int32Array& phases, UInt32Array& crystalStructures, int32_t numPhases, MaskArrayType* goodVoxels, Float32Array& fzQuats,
23+ const std::atomic_bool& shouldCancel, std::atomic_int32_t & warningCount)
24+ : m_Quats(quats)
25+ , m_CellPhases(phases)
26+ , m_CrystalStructures(crystalStructures)
27+ , m_NumPhases(numPhases)
28+ , m_GoodVoxels(goodVoxels)
29+ , m_FZQuats(fzQuats)
30+ , m_ShouldCancel(shouldCancel)
31+ , m_WarningCount(warningCount)
32+ {
33+ }
34+
35+ virtual ~GenerateFZQuatsImpl () = default ;
36+
37+ /* *
38+ * @brief convert
39+ * @param start
40+ * @param end
41+ */
42+ void convert (size_t start, size_t end) const
43+ {
44+ std::vector<LaueOps::Pointer> ops = LaueOps::GetAllOrientationOps ();
45+ int32_t phase = 0 ;
46+ bool generateFZQuat = false ;
47+ size_t index = 0 ;
48+
49+ for (size_t i = start; i < end; i++)
50+ {
51+ if (m_ShouldCancel)
52+ {
53+ break ;
54+ }
55+ phase = m_CellPhases[i];
56+
57+ generateFZQuat = true ;
58+ if (nullptr != m_GoodVoxels)
59+ {
60+ generateFZQuat = static_cast <bool >((*m_GoodVoxels)[i]);
61+ }
62+
63+ // Sanity check the phase data to make sure we do not walk off the end of the array
64+ if (phase >= m_NumPhases)
65+ {
66+ m_WarningCount++;
67+ }
68+
69+ // Initialize the output to zero. There really isn't a good value to use.
70+ index = i * 4 ;
71+ m_FZQuats[index] = 0 .0f ;
72+ m_FZQuats[index + 1 ] = 0 .0f ;
73+ m_FZQuats[index + 2 ] = 0 .0f ;
74+ m_FZQuats[index + 3 ] = 0 .0f ;
75+
76+ if (phase < m_NumPhases && generateFZQuat && m_CrystalStructures[phase] < EbsdLib::CrystalStructure::LaueGroupEnd)
77+ {
78+ QuatD quatD = QuatD (m_Quats[index], m_Quats[index + 1 ], m_Quats[index + 2 ], m_Quats[index + 3 ]); // Makes a copy into q
79+ int32_t xtal = static_cast <int32_t >(m_CrystalStructures[phase]); // get the Laue Group
80+ quatD = ops[xtal]->getFZQuat (quatD);
81+ m_FZQuats[index] = quatD.x ();
82+ m_FZQuats[index + 1 ] = quatD.y ();
83+ m_FZQuats[index + 2 ] = quatD.z ();
84+ m_FZQuats[index + 3 ] = quatD.w ();
85+ }
86+ }
87+ }
88+
89+ void operator ()(const Range& range) const
90+ {
91+ convert (range.min (), range.max ());
92+ }
93+
94+ private:
95+ Float32Array& m_Quats;
96+ Int32Array& m_CellPhases;
97+ UInt32Array& m_CrystalStructures;
98+ int32_t m_NumPhases = 0 ;
99+ MaskArrayType* m_GoodVoxels;
100+ Float32Array& m_FZQuats;
101+ const std::atomic_bool& m_ShouldCancel;
102+ std::atomic_int32_t & m_WarningCount;
103+ };
104+ } // namespace
105+
8106// -----------------------------------------------------------------------------
9107ComputeFZQuaternions::ComputeFZQuaternions (DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ComputeFZQuaternionsInputValues* inputValues)
10108: m_DataStructure(dataStructure)
@@ -21,5 +119,62 @@ ComputeFZQuaternions::~ComputeFZQuaternions() noexcept = default;
21119Result<> ComputeFZQuaternions::operator ()()
22120{
23121
122+ Int32Array& phaseArray = m_DataStructure.getDataRefAs <Int32Array>(m_InputValues->CellPhasesArrayPath );
123+ Float32Array& quatArray = m_DataStructure.getDataRefAs <Float32Array>(m_InputValues->InputQuatsArrayPath );
124+ UInt32Array& xtalArray = m_DataStructure.getDataRefAs <UInt32Array>(m_InputValues->CrystalStructuresArrayPath );
125+ IDataArray* maskArray = m_DataStructure.getDataAs <IDataArray>(m_InputValues->MaskArrayPath );
126+ Float32Array& fzQuatArray = m_DataStructure.getDataRefAs <Float32Array>(m_InputValues->InputQuatsArrayPath .replaceName (m_InputValues->OutputFzQuatsArrayName ));
127+
128+ std::atomic_int32_t warningCount = 0 ;
129+ int32_t numPhases = static_cast <int32_t >(xtalArray.getNumberOfTuples ());
130+
131+ typename IParallelAlgorithm::AlgorithmArrays algArrays;
132+ algArrays.push_back (&phaseArray);
133+ algArrays.push_back (&quatArray);
134+ algArrays.push_back (&xtalArray);
135+ algArrays.push_back (&fzQuatArray);
136+
137+ if (m_InputValues->UseMask )
138+ {
139+ algArrays.push_back (maskArray);
140+ }
141+
142+ // Parallel algorithm
143+ ParallelDataAlgorithm dataAlg;
144+ dataAlg.setRange (0ULL , static_cast <size_t >(quatArray.getNumberOfTuples ()));
145+ dataAlg.requireArraysInMemory (algArrays);
146+
147+ if (m_InputValues->UseMask )
148+ {
149+ if (maskArray->getDataType () == DataType::boolean)
150+ {
151+ BoolArray* goodVoxelsArray = m_DataStructure.getDataAs <BoolArray>(m_InputValues->MaskArrayPath );
152+ dataAlg.execute (::GenerateFZQuatsImpl<BoolArray>(quatArray, phaseArray, xtalArray, numPhases, goodVoxelsArray, fzQuatArray, m_ShouldCancel, warningCount));
153+ }
154+ else if (maskArray->getDataType () == DataType::uint8)
155+ {
156+ UInt32Array* goodVoxelsArray = m_DataStructure.getDataAs <UInt32Array>(m_InputValues->MaskArrayPath );
157+ dataAlg.execute (::GenerateFZQuatsImpl<UInt32Array>(quatArray, phaseArray, xtalArray, numPhases, goodVoxelsArray, fzQuatArray, m_ShouldCancel, warningCount));
158+ }
159+ else if (maskArray->getDataType () == DataType::int8)
160+ {
161+ Int8Array* goodVoxelsArray = m_DataStructure.getDataAs <Int8Array>(m_InputValues->MaskArrayPath );
162+ dataAlg.execute (::GenerateFZQuatsImpl<Int8Array>(quatArray, phaseArray, xtalArray, numPhases, goodVoxelsArray, fzQuatArray, m_ShouldCancel, warningCount));
163+ }
164+ }
165+ else
166+ {
167+ dataAlg.execute (::GenerateFZQuatsImpl<Int8Array>(quatArray, phaseArray, xtalArray, numPhases, nullptr , fzQuatArray, m_ShouldCancel, warningCount));
168+ }
169+
170+ if (warningCount > 0 )
171+ {
172+ std::string errorMessage = fmt::format (" The Ensemble Phase information only references {} phase(s) but {} cell(s) had a phase value greater than {}. \
173+ This indicates a problem with the input cell phase data. DREAM3D-NX may have given INCORRECT RESULTS." ,
174+ numPhases - 1 , warningCount.load (), numPhases - 1 );
175+
176+ return {MakeErrorResult<>(-49008 , errorMessage)};
177+ }
178+
24179 return {};
25180}
0 commit comments