diff --git a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ReadH5EspritData.cpp b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ReadH5EspritData.cpp index 87e0e4ccff..6df380d570 100644 --- a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ReadH5EspritData.cpp +++ b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ReadH5EspritData.cpp @@ -23,10 +23,26 @@ Result<> ReadH5EspritData::operator()() return execute(); } +// ----------------------------------------------------------------------------- +Result<> ReadH5EspritData::updateOrigin(const std::string& scanName) +{ + /* + * Unfortunately, the file does not have the correct data to find an origin. + * This means that the origin will remain {0,0,0}. + * + * Down the line, if a solution crops up, look to ReadH5Oina.cpp for an example + * implementation. + */ + return {}; +} + // ----------------------------------------------------------------------------- Result<> ReadH5EspritData::copyRawEbsdData(int index) { - const auto& imageGeom = m_DataStructure.getDataRefAs(m_InputValues->ImageGeometryPath); + const DataPath imagePath(m_InputValues->ImageGeometryPath); + const DataPath cellAMPath = imagePath.createChildPath(m_InputValues->CellAttributeMatrixName); + + const auto& imageGeom = m_DataStructure.getDataRefAs(imagePath); const usize totalPoints = imageGeom.getNumXCells() * imageGeom.getNumYCells(); const usize offset = index * totalPoints; @@ -35,28 +51,28 @@ Result<> ReadH5EspritData::copyRawEbsdData(int index) const auto* phi1 = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::H5Esprit::phi1)); const auto* phi = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::H5Esprit::PHI)); const auto* phi2 = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::H5Esprit::phi2)); - auto& eulerAngles = m_DataStructure.getDataRefAs(m_InputValues->CellAttributeMatrixPath.createChildPath(EbsdLib::Esprit::EulerAngles)); + auto& eulerAngles = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::Esprit::EulerAngles)); const auto* m1 = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::H5Esprit::MAD)); - auto& mad = m_DataStructure.getDataRefAs(m_InputValues->CellAttributeMatrixPath.createChildPath(EbsdLib::H5Esprit::MAD)); + auto& mad = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::H5Esprit::MAD)); const auto* nIndBands = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::H5Esprit::NIndexedBands)); - auto& nIndexBands = m_DataStructure.getDataRefAs(m_InputValues->CellAttributeMatrixPath.createChildPath(EbsdLib::H5Esprit::NIndexedBands)); + auto& nIndexBands = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::H5Esprit::NIndexedBands)); const auto* p1 = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::H5Esprit::Phase)); - auto& phase = m_DataStructure.getDataRefAs(m_InputValues->CellAttributeMatrixPath.createChildPath(EbsdLib::H5Esprit::Phase)); + auto& phase = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::H5Esprit::Phase)); const auto* radBandCnt = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::H5Esprit::RadonBandCount)); - auto& radonBandCount = m_DataStructure.getDataRefAs(m_InputValues->CellAttributeMatrixPath.createChildPath(EbsdLib::H5Esprit::RadonBandCount)); + auto& radonBandCount = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::H5Esprit::RadonBandCount)); const auto* radQual = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::H5Esprit::RadonQuality)); - auto& radonQuality = m_DataStructure.getDataRefAs(m_InputValues->CellAttributeMatrixPath.createChildPath(EbsdLib::H5Esprit::RadonQuality)); + auto& radonQuality = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::H5Esprit::RadonQuality)); const auto* xBm = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::H5Esprit::XBEAM)); - auto& xBeam = m_DataStructure.getDataRefAs(m_InputValues->CellAttributeMatrixPath.createChildPath(EbsdLib::H5Esprit::XBEAM)); + auto& xBeam = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::H5Esprit::XBEAM)); const auto* yBm = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::H5Esprit::YBEAM)); - auto& yBeam = m_DataStructure.getDataRefAs(m_InputValues->CellAttributeMatrixPath.createChildPath(EbsdLib::H5Esprit::YBEAM)); + auto& yBeam = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::H5Esprit::YBEAM)); for(size_t i = 0; i < totalPoints; i++) { @@ -91,7 +107,7 @@ Result<> ReadH5EspritData::copyRawEbsdData(int index) std::vector pDimsV(2); pDimsV[0] = pDims[0]; pDimsV[1] = pDims[1]; - auto& patternData = m_DataStructure.getDataRefAs(m_InputValues->CellAttributeMatrixPath.createChildPath(EbsdLib::H5Esprit::RawPatterns)); + auto& patternData = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::H5Esprit::RawPatterns)); const usize numComponents = patternData.getNumberOfComponents(); for(usize i = 0; i < totalPoints; i++) { @@ -105,3 +121,88 @@ Result<> ReadH5EspritData::copyRawEbsdData(int index) return {}; } + +// ----------------------------------------------------------------------------- +Result<> ReadH5EspritData::copyRawEbsdData(const std::string& scanName) +{ + const DataPath imagePath({scanName}); + const DataPath cellAMPath = imagePath.createChildPath(m_InputValues->CellAttributeMatrixName); + + const auto& imageGeom = m_DataStructure.getDataRefAs(imagePath); + const usize totalPoints = imageGeom.getNumXCells() * imageGeom.getNumYCells(); + + { + const float32 degToRad = m_EspritInputValues->DegreesToRadians ? Constants::k_PiOver180F : 1.0f; + const auto* phi1 = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::H5Esprit::phi1)); + const auto* phi = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::H5Esprit::PHI)); + const auto* phi2 = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::H5Esprit::phi2)); + auto& eulerAngles = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::Esprit::EulerAngles)); + + const auto* m1 = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::H5Esprit::MAD)); + auto& mad = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::H5Esprit::MAD)); + + const auto* nIndBands = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::H5Esprit::NIndexedBands)); + auto& nIndexBands = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::H5Esprit::NIndexedBands)); + + const auto* p1 = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::H5Esprit::Phase)); + auto& phase = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::H5Esprit::Phase)); + + const auto* radBandCnt = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::H5Esprit::RadonBandCount)); + auto& radonBandCount = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::H5Esprit::RadonBandCount)); + + const auto* radQual = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::H5Esprit::RadonQuality)); + auto& radonQuality = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::H5Esprit::RadonQuality)); + + const auto* xBm = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::H5Esprit::XBEAM)); + auto& xBeam = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::H5Esprit::XBEAM)); + + const auto* yBm = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::H5Esprit::YBEAM)); + auto& yBeam = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::H5Esprit::YBEAM)); + + for(size_t i = 0; i < totalPoints; i++) + { + // Condense the Euler Angles from 3 separate arrays into a single 1x3 array + eulerAngles[3 * i] = phi1[i] * degToRad; + eulerAngles[3 * i + 1] = phi[i] * degToRad; + eulerAngles[3 * i + 2] = phi2[i] * degToRad; + + mad[i] = m1[i]; + + nIndexBands[i] = nIndBands[i]; + + phase[i] = p1[i]; + + radonBandCount[i] = radBandCnt[i]; + + radonQuality[i] = radQual[i]; + + xBeam[i] = xBm[i]; + + yBeam[i] = yBm[i]; + } + } + + if(m_InputValues->ReadPatternData) + { + const uint8* patternDataPtr = m_Reader->getPatternData(); + std::array pDims = {{0, 0}}; + m_Reader->getPatternDims(pDims); + if(pDims[0] != 0 && pDims[1] != 0) + { + std::vector pDimsV(2); + pDimsV[0] = pDims[0]; + pDimsV[1] = pDims[1]; + auto& patternData = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::H5Esprit::RawPatterns)); + const usize numComponents = patternData.getNumberOfComponents(); + for(usize i = 0; i < totalPoints; i++) + { + for(usize j = 0; j < numComponents; ++j) + { + patternData[numComponents * i + j] = patternDataPtr[numComponents * i + j]; + } + } + } + } + + return {}; +} diff --git a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ReadH5EspritData.hpp b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ReadH5EspritData.hpp index 6a0d9a4bca..2bce418948 100644 --- a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ReadH5EspritData.hpp +++ b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ReadH5EspritData.hpp @@ -33,7 +33,10 @@ class ORIENTATIONANALYSIS_EXPORT ReadH5EspritData : public IEbsdOemReader operator()(); + Result<> updateOrigin(const std::string& scanName) override; + Result<> copyRawEbsdData(int index) override; + Result<> copyRawEbsdData(const std::string& scanName) override; private: const ReadH5EspritDataInputValues* m_EspritInputValues = nullptr; diff --git a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ReadH5OimData.cpp b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ReadH5OimData.cpp index 4a21a0f781..987cb77840 100644 --- a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ReadH5OimData.cpp +++ b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ReadH5OimData.cpp @@ -20,33 +20,48 @@ Result<> ReadH5OimData::operator()() return execute(); } +// ----------------------------------------------------------------------------- +Result<> ReadH5OimData::updateOrigin(const std::string& scanName) +{ + /* + * This function intentionally has no logic in order to avoid extra calculations; + * The origins were set in preflight, but this file type is an outlier in that it stores + * the origin in the header. Thus, this function overrides the general need to access + * the X and Y positions data as seen in the super/baseclass. + */ + return {}; +} + // ----------------------------------------------------------------------------- Result<> ReadH5OimData::copyRawEbsdData(int index) { - const auto& imageGeom = m_DataStructure.getDataRefAs(m_InputValues->ImageGeometryPath); + const DataPath imagePath(m_InputValues->ImageGeometryPath); + const DataPath cellAMPath = imagePath.createChildPath(m_InputValues->CellAttributeMatrixName); + + const auto& imageGeom = m_DataStructure.getDataRefAs(imagePath); const usize totalPoints = imageGeom.getNumXCells() * imageGeom.getNumYCells(); const usize offset = index * totalPoints; // Adjust the values of the 'phase' data to correct for invalid values - auto& phases = m_DataStructure.getDataRefAs(m_InputValues->CellAttributeMatrixPath.createChildPath(EbsdLib::AngFile::Phases)); + auto& phases = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::AngFile::Phases)); auto* phasePtr = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::Ang::PhaseData)); const auto* phi1 = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::Ang::Phi1)); const auto* phi = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::Ang::Phi)); const auto* phi2 = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::Ang::Phi2)); - auto& eulerAngles = m_DataStructure.getDataRefAs(m_InputValues->CellAttributeMatrixPath.createChildPath(EbsdLib::AngFile::EulerAngles)); + auto& eulerAngles = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::AngFile::EulerAngles)); const auto* imageQual = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::Ang::ImageQuality)); - auto& imageQuality = m_DataStructure.getDataRefAs(m_InputValues->CellAttributeMatrixPath.createChildPath(EbsdLib::Ang::ImageQuality)); + auto& imageQuality = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::Ang::ImageQuality)); const auto* confIndex = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::Ang::ConfidenceIndex)); - auto& confidenceIndex = m_DataStructure.getDataRefAs(m_InputValues->CellAttributeMatrixPath.createChildPath(EbsdLib::Ang::ConfidenceIndex)); + auto& confidenceIndex = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::Ang::ConfidenceIndex)); const auto* semSig = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::Ang::SEMSignal)); - auto& semSignal = m_DataStructure.getDataRefAs(m_InputValues->CellAttributeMatrixPath.createChildPath(EbsdLib::Ang::SEMSignal)); + auto& semSignal = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::Ang::SEMSignal)); const auto* f1 = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::Ang::Fit)); - auto& fit = m_DataStructure.getDataRefAs(m_InputValues->CellAttributeMatrixPath.createChildPath(EbsdLib::Ang::Fit)); + auto& fit = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::Ang::Fit)); for(size_t i = 0; i < totalPoints; i++) { @@ -80,7 +95,7 @@ Result<> ReadH5OimData::copyRawEbsdData(int index) std::vector pDimsV(2); pDimsV[0] = pDims[0]; pDimsV[1] = pDims[1]; - auto& patternData = m_DataStructure.getDataRefAs(m_InputValues->CellAttributeMatrixPath.createChildPath(EbsdLib::Ang::PatternData)); + auto& patternData = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::Ang::PatternData)); const usize numComponents = patternData.getNumberOfComponents(); for(usize i = 0; i < totalPoints; i++) { @@ -94,3 +109,80 @@ Result<> ReadH5OimData::copyRawEbsdData(int index) return {}; } + +// ----------------------------------------------------------------------------- +Result<> ReadH5OimData::copyRawEbsdData(const std::string& scanName) +{ + const DataPath imagePath({scanName}); + const DataPath cellAMPath = imagePath.createChildPath(m_InputValues->CellAttributeMatrixName); + + const auto& imageGeom = m_DataStructure.getDataRefAs(imagePath); + const usize totalPoints = imageGeom.getNumXCells() * imageGeom.getNumYCells(); + + // Adjust the values of the 'phase' data to correct for invalid values + auto& phases = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::AngFile::Phases)); + auto* phasePtr = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::Ang::PhaseData)); + + const auto* phi1 = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::Ang::Phi1)); + const auto* phi = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::Ang::Phi)); + const auto* phi2 = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::Ang::Phi2)); + auto& eulerAngles = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::AngFile::EulerAngles)); + + const auto* imageQual = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::Ang::ImageQuality)); + auto& imageQuality = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::Ang::ImageQuality)); + + const auto* confIndex = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::Ang::ConfidenceIndex)); + auto& confidenceIndex = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::Ang::ConfidenceIndex)); + + const auto* semSig = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::Ang::SEMSignal)); + auto& semSignal = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::Ang::SEMSignal)); + + const auto* f1 = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::Ang::Fit)); + auto& fit = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::Ang::Fit)); + + for(usize i = 0; i < totalPoints; i++) + { + if(phasePtr[i] < 1) + { + phasePtr[i] = 1; + } + phases[i] = phasePtr[i]; + + // Condense the Euler Angles from 3 separate arrays into a single 1x3 array + eulerAngles[3 * i] = phi1[i]; + eulerAngles[3 * i + 1] = phi[i]; + eulerAngles[3 * i + 2] = phi2[i]; + + imageQuality[i] = imageQual[i]; + + confidenceIndex[i] = confIndex[i]; + + semSignal[i] = semSig[i]; + + fit[i] = f1[i]; + } + + if(m_InputValues->ReadPatternData) + { + const uint8* patternDataPtr = m_Reader->getPatternData(); + std::array pDims = {{0, 0}}; + m_Reader->getPatternDims(pDims); + if(pDims[0] != 0 && pDims[1] != 0) + { + std::vector pDimsV(2); + pDimsV[0] = pDims[0]; + pDimsV[1] = pDims[1]; + auto& patternData = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::Ang::PatternData)); + const usize numComponents = patternData.getNumberOfComponents(); + for(usize i = 0; i < totalPoints; i++) + { + for(usize j = 0; j < numComponents; ++j) + { + patternData[numComponents * i + j] = patternDataPtr[numComponents * i + j]; + } + } + } + } + + return {}; +} diff --git a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ReadH5OimData.hpp b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ReadH5OimData.hpp index 85d68fea02..9d29071f2d 100644 --- a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ReadH5OimData.hpp +++ b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ReadH5OimData.hpp @@ -25,6 +25,8 @@ class ORIENTATIONANALYSIS_EXPORT ReadH5OimData : public IEbsdOemReader operator()(); Result<> copyRawEbsdData(int index) override; + Result<> copyRawEbsdData(const std::string& scanName) override; + Result<> updateOrigin(const std::string& scanName) override; }; } // namespace nx::core diff --git a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ReadH5OinaData.cpp b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ReadH5OinaData.cpp index f071cff539..ae44b040dd 100644 --- a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ReadH5OinaData.cpp +++ b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ReadH5OinaData.cpp @@ -9,10 +9,10 @@ namespace { template -void copyRawData(const ReadH5DataInputValues* m_InputValues, size_t totalPoints, DataStructure& m_DataStructure, H5OINAReader& m_Reader, const std::string& name, usize offset) +void copyRawData(const DataPath& cellAMPath, size_t totalPoints, DataStructure& m_DataStructure, H5OINAReader& m_Reader, const std::string& name, usize offset = 0) { using ArrayType = DataArray; - auto& dataRef = m_DataStructure.getDataRefAs(m_InputValues->CellAttributeMatrixPath.createChildPath(name)); + auto& dataRef = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(name)); auto* dataStorePtr = dataRef.getDataStore(); const nonstd::span rawDataPtr(reinterpret_cast(m_Reader.getPointerByName(name)), totalPoints); @@ -20,27 +20,25 @@ void copyRawData(const ReadH5DataInputValues* m_InputValues, size_t totalPoints, } template -void convertHexEulerAngle(const ReadH5DataInputValues* m_InputValues, size_t totalPoints, DataStructure& m_DataStructure) +void convertHexEulerAngle(const DataPath& cellAMPath, const DataPath& cellEnsembleAMPath, size_t totalPoints, DataStructure& m_DataStructure) { + // If EDAX Hexagonal Alignment is checked outside call using ArrayType = DataArray; - if(m_InputValues->EdaxHexagonalAlignment) - { - auto& crystalStructuresRef = m_DataStructure.getDataRefAs(m_InputValues->CellEnsembleAttributeMatrixPath.createChildPath(EbsdLib::AngFile::CrystalStructures)); - auto& crystalStructuresDSRef = crystalStructuresRef.getDataStoreRef(); + auto& crystalStructuresRef = m_DataStructure.getDataRefAs(cellEnsembleAMPath.createChildPath(EbsdLib::AngFile::CrystalStructures)); + auto& crystalStructuresDSRef = crystalStructuresRef.getDataStoreRef(); - auto& cellPhasesRef = m_DataStructure.getDataRefAs(m_InputValues->CellAttributeMatrixPath.createChildPath(EbsdLib::H5OINA::Phase)); - auto& cellPhasesDSRef = cellPhasesRef.getDataStoreRef(); + auto& cellPhasesRef = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::H5OINA::Phase)); + auto& cellPhasesDSRef = cellPhasesRef.getDataStoreRef(); - auto& eulerRef = m_DataStructure.getDataRefAs(m_InputValues->CellAttributeMatrixPath.createChildPath(EbsdLib::H5OINA::Euler)); - auto& eulerDataStoreRef = eulerRef.getDataStoreRef(); + auto& eulerRef = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::H5OINA::Euler)); + auto& eulerDataStoreRef = eulerRef.getDataStoreRef(); - for(size_t i = 0; i < totalPoints; i++) + for(size_t i = 0; i < totalPoints; i++) + { + if(crystalStructuresDSRef[cellPhasesDSRef[i]] == EbsdLib::CrystalStructure::Hexagonal_High) { - if(crystalStructuresDSRef[cellPhasesDSRef[i]] == EbsdLib::CrystalStructure::Hexagonal_High) - { - eulerDataStoreRef[3 * i + 2] = eulerDataStoreRef[3 * i + 2] + 30.0F; // See the documentation for this correction factor - } + eulerDataStoreRef[3 * i + 2] = eulerDataStoreRef[3 * i + 2] + 30.0F; // See the documentation for this correction factor } } } @@ -62,24 +60,54 @@ Result<> ReadH5OinaData::operator()() return execute(); } +// ----------------------------------------------------------------------------- +Result<> ReadH5OinaData::updateOrigin(const std::string& scanName) +{ + const DataPath imagePath({scanName}); + + auto& imageGeom = m_DataStructure.getDataRefAs(imagePath); + const usize totalCells = imageGeom.getNumberOfCells(); + + const auto* xPos = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::Ctf::X)); + if(xPos == nullptr) + { + return MakeErrorResult(-9970, fmt::format("{}({}): Function {}: Error. Cannot find {} in supplied scan file ({})", "IEbsdOemReader", __FILE__, __LINE__, EbsdLib::Ctf::X, m_Reader->getFileName())); + } + const auto* yPos = reinterpret_cast(m_Reader->getPointerByName(EbsdLib::Ctf::Y)); + if(yPos == nullptr) + { + return MakeErrorResult(-9971, fmt::format("{}({}): Function {}: Error. Cannot find {} in supplied scan file ({})", "IEbsdOemReader", __FILE__, __LINE__, EbsdLib::Ctf::Y, m_Reader->getFileName())); + } + + float32 minX = *std::min_element(xPos, xPos + totalCells); + float32 minY = *std::min_element(yPos, yPos + totalCells); + + imageGeom.setOrigin(minX, minY, 0.0f); + + return {}; +} + // ----------------------------------------------------------------------------- Result<> ReadH5OinaData::copyRawEbsdData(int index) { - const auto& imageGeom = m_DataStructure.getDataRefAs(m_InputValues->ImageGeometryPath); + const DataPath imagePath(m_InputValues->ImageGeometryPath); + const DataPath cellAMPath = imagePath.createChildPath(m_InputValues->CellAttributeMatrixName); + + const auto& imageGeom = m_DataStructure.getDataRefAs(imagePath); const usize totalPoints = imageGeom.getNumXCells() * imageGeom.getNumYCells(); const usize offset = index * totalPoints; - copyRawData(m_InputValues, totalPoints, m_DataStructure, *m_Reader, EbsdLib::H5OINA::BandContrast, offset); - copyRawData(m_InputValues, totalPoints, m_DataStructure, *m_Reader, EbsdLib::H5OINA::BandSlope, offset); - copyRawData(m_InputValues, totalPoints, m_DataStructure, *m_Reader, EbsdLib::H5OINA::Bands, offset); - copyRawData(m_InputValues, totalPoints, m_DataStructure, *m_Reader, EbsdLib::H5OINA::Error, offset); - copyRawData(m_InputValues, totalPoints * 3, m_DataStructure, *m_Reader, EbsdLib::H5OINA::Euler, offset); - copyRawData(m_InputValues, totalPoints, m_DataStructure, *m_Reader, EbsdLib::H5OINA::MeanAngularDeviation, offset); + copyRawData(cellAMPath, totalPoints, m_DataStructure, *m_Reader, EbsdLib::H5OINA::BandContrast, offset); + copyRawData(cellAMPath, totalPoints, m_DataStructure, *m_Reader, EbsdLib::H5OINA::BandSlope, offset); + copyRawData(cellAMPath, totalPoints, m_DataStructure, *m_Reader, EbsdLib::H5OINA::Bands, offset); + copyRawData(cellAMPath, totalPoints, m_DataStructure, *m_Reader, EbsdLib::H5OINA::Error, offset); + copyRawData(cellAMPath, totalPoints * 3, m_DataStructure, *m_Reader, EbsdLib::H5OINA::Euler, offset); + copyRawData(cellAMPath, totalPoints, m_DataStructure, *m_Reader, EbsdLib::H5OINA::MeanAngularDeviation, offset); if(m_InputValues->ConvertPhaseToInt32) { const nonstd::span rawDataPtr(reinterpret_cast(m_Reader->getPointerByName(EbsdLib::H5OINA::Phase)), totalPoints); using ArrayType = DataArray; - auto& dataRef = m_DataStructure.getDataRefAs(m_InputValues->CellAttributeMatrixPath.createChildPath(EbsdLib::H5OINA::Phase)); + auto& dataRef = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::H5OINA::Phase)); auto* dataStorePtr = dataRef.getDataStore(); for(size_t i = 0; i < totalPoints; i++) { @@ -88,20 +116,21 @@ Result<> ReadH5OinaData::copyRawEbsdData(int index) } else { - copyRawData(m_InputValues, totalPoints, m_DataStructure, *m_Reader, EbsdLib::H5OINA::Phase, offset); + copyRawData(cellAMPath, totalPoints, m_DataStructure, *m_Reader, EbsdLib::H5OINA::Phase, offset); } - copyRawData(m_InputValues, totalPoints, m_DataStructure, *m_Reader, EbsdLib::H5OINA::X, offset); - copyRawData(m_InputValues, totalPoints, m_DataStructure, *m_Reader, EbsdLib::H5OINA::Y, offset); + copyRawData(cellAMPath, totalPoints, m_DataStructure, *m_Reader, EbsdLib::H5OINA::X, offset); + copyRawData(cellAMPath, totalPoints, m_DataStructure, *m_Reader, EbsdLib::H5OINA::Y, offset); if(m_InputValues->EdaxHexagonalAlignment) { + const DataPath& cellEnsembleAMPath = imagePath.createChildPath(m_InputValues->CellEnsembleAttributeMatrixName); if(m_InputValues->ConvertPhaseToInt32) { - convertHexEulerAngle(m_InputValues, totalPoints, m_DataStructure); + convertHexEulerAngle(cellAMPath, cellEnsembleAMPath, totalPoints, m_DataStructure); } else { - convertHexEulerAngle(m_InputValues, totalPoints, m_DataStructure); + convertHexEulerAngle(cellAMPath, cellEnsembleAMPath, totalPoints, m_DataStructure); } } @@ -115,7 +144,7 @@ Result<> ReadH5OinaData::copyRawEbsdData(int index) std::vector pDimsV(2); pDimsV[0] = pDims[0]; pDimsV[1] = pDims[1]; - auto& patternData = m_DataStructure.getDataRefAs(m_InputValues->CellAttributeMatrixPath.createChildPath(EbsdLib::H5OINA::UnprocessedPatterns)); + auto& patternData = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::H5OINA::UnprocessedPatterns)); const usize numComponents = patternData.getNumberOfComponents(); for(usize i = 0; i < totalPoints; i++) { @@ -129,3 +158,74 @@ Result<> ReadH5OinaData::copyRawEbsdData(int index) return {}; } + +// ----------------------------------------------------------------------------- +Result<> ReadH5OinaData::copyRawEbsdData(const std::string& scanName) +{ + const DataPath imagePath({scanName}); + const DataPath cellAMPath = imagePath.createChildPath(m_InputValues->CellAttributeMatrixName); + + const auto& imageGeom = m_DataStructure.getDataRefAs(imagePath); + const usize totalPoints = imageGeom.getNumXCells() * imageGeom.getNumYCells(); + + copyRawData(cellAMPath, totalPoints, m_DataStructure, *m_Reader, EbsdLib::H5OINA::BandContrast); + copyRawData(cellAMPath, totalPoints, m_DataStructure, *m_Reader, EbsdLib::H5OINA::BandSlope); + copyRawData(cellAMPath, totalPoints, m_DataStructure, *m_Reader, EbsdLib::H5OINA::Bands); + copyRawData(cellAMPath, totalPoints, m_DataStructure, *m_Reader, EbsdLib::H5OINA::Error); + copyRawData(cellAMPath, totalPoints * 3, m_DataStructure, *m_Reader, EbsdLib::H5OINA::Euler); + copyRawData(cellAMPath, totalPoints, m_DataStructure, *m_Reader, EbsdLib::H5OINA::MeanAngularDeviation); + if(m_InputValues->ConvertPhaseToInt32) + { + const nonstd::span rawDataPtr(reinterpret_cast(m_Reader->getPointerByName(EbsdLib::H5OINA::Phase)), totalPoints); + using ArrayType = DataArray; + auto& dataRef = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::H5OINA::Phase)); + auto* dataStorePtr = dataRef.getDataStore(); + for(size_t i = 0; i < totalPoints; i++) + { + dataStorePtr->setValue(i, static_cast(rawDataPtr[i])); + } + } + else + { + copyRawData(cellAMPath, totalPoints, m_DataStructure, *m_Reader, EbsdLib::H5OINA::Phase); + } + copyRawData(cellAMPath, totalPoints, m_DataStructure, *m_Reader, EbsdLib::H5OINA::X); + copyRawData(cellAMPath, totalPoints, m_DataStructure, *m_Reader, EbsdLib::H5OINA::Y); + + if(m_InputValues->EdaxHexagonalAlignment) + { + const DataPath& cellEnsembleAMPath = imagePath.createChildPath(m_InputValues->CellEnsembleAttributeMatrixName); + if(m_InputValues->ConvertPhaseToInt32) + { + convertHexEulerAngle(cellAMPath, cellEnsembleAMPath, totalPoints, m_DataStructure); + } + else + { + convertHexEulerAngle(cellAMPath, cellEnsembleAMPath, totalPoints, m_DataStructure); + } + } + + if(m_InputValues->ReadPatternData) + { + const uint16* patternDataPtr = m_Reader->getPatternData(); + std::array pDims = {{0, 0}}; + m_Reader->getPatternDims(pDims); + if(pDims[0] != 0 && pDims[1] != 0) + { + std::vector pDimsV(2); + pDimsV[0] = pDims[0]; + pDimsV[1] = pDims[1]; + auto& patternData = m_DataStructure.getDataRefAs(cellAMPath.createChildPath(EbsdLib::H5OINA::UnprocessedPatterns)); + const usize numComponents = patternData.getNumberOfComponents(); + for(usize i = 0; i < totalPoints; i++) + { + for(usize j = 0; j < numComponents; ++j) + { + patternData[numComponents * i + j] = patternDataPtr[numComponents * i + j]; + } + } + } + } + + return {}; +} diff --git a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ReadH5OinaData.hpp b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ReadH5OinaData.hpp index f58f4beda2..cfd8232c8d 100644 --- a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ReadH5OinaData.hpp +++ b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ReadH5OinaData.hpp @@ -25,7 +25,9 @@ class ORIENTATIONANALYSIS_EXPORT ReadH5OinaData : public IEbsdOemReader operator()(); + Result<> updateOrigin(const std::string& scanName) override; Result<> copyRawEbsdData(int index) override; + Result<> copyRawEbsdData(const std::string& scanName) override; }; } // namespace nx::core diff --git a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ReadH5EspritDataFilter.cpp b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ReadH5EspritDataFilter.cpp index 06cdb27193..3b47a09a57 100644 --- a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ReadH5EspritDataFilter.cpp +++ b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ReadH5EspritDataFilter.cpp @@ -70,6 +70,10 @@ Parameters ReadH5EspritDataFilter::parameters() const OEMEbsdScanSelectionParameter::ValueType{}, /* OEMEbsdScanSelectionParameter::AllowedManufacturers{EbsdLib::OEM::Bruker, EbsdLib::OEM::DREAM3D},*/ OEMEbsdScanSelectionParameter::EbsdReaderType::Esprit, OEMEbsdScanSelectionParameter::ExtensionsType{".h5", ".hdf5"})); + params.insertLinkableParameter( + std::make_unique(k_CombineScans_Key, "Stack Scans Along Z Axis", + "If true combines each of the multiple scans into a single image geometry along the z axis, else each will result in an individual geometry", true)); + params.insert(std::make_unique(k_ZSpacing_Key, "Z Spacing (Microns)", "The spacing in microns between each layer.", 1.0f)); params.insert(std::make_unique(k_Origin_Key, "Origin", "The origin of the volume", std::vector{0.0F, 0.0F, 0.0F}, std::vector{"x", "y", "z"})); params.insert(std::make_unique(k_ZSpacing_Key, "Z Spacing (Microns)", "The spacing in microns between each layer.", 1.0f)); params.insert(std::make_unique(k_DegreesToRadians_Key, "Convert Euler Angles to Radians", "Whether or not to convert the euler angles to radians", true)); @@ -83,13 +87,22 @@ Parameters ReadH5EspritDataFilter::parameters() const params.insert(std::make_unique(k_CellEnsembleAttributeMatrixName_Key, "Ensemble Attribute Matrix", "The Attribute Matrix where the phase information is stored.", "Cell Ensemble Data")); + // Link Parameters + params.linkParameters(k_CombineScans_Key, k_Origin_Key, true); + params.linkParameters(k_CombineScans_Key, k_CreatedImageGeometryPath_Key, true); + return params; } //------------------------------------------------------------------------------ IFilter::VersionType ReadH5EspritDataFilter::parametersVersion() const { - return 1; + return 2; + + // Version 1 -> 2 + // Change 1: + // Added - k_CombineScans_Key = "combine_scans"; + // Solution - default parameter value 'true' preserves backwards functionality; } //------------------------------------------------------------------------------ @@ -103,6 +116,7 @@ IFilter::PreflightResult ReadH5EspritDataFilter::preflightImpl(const DataStructu const std::atomic_bool& shouldCancel, const ExecutionContext& executionContext) const { auto pSelectedScanNamesValue = filterArgs.value(k_SelectedScanNames_Key); + auto pCombineScansValue = filterArgs.value(k_CombineScans_Key); // V2 Param auto pZSpacingValue = filterArgs.value(k_ZSpacing_Key); auto pOriginValue = filterArgs.value(k_Origin_Key); auto pDegreesToRadiansValue = filterArgs.value(k_DegreesToRadians_Key); @@ -111,10 +125,9 @@ IFilter::PreflightResult ReadH5EspritDataFilter::preflightImpl(const DataStructu auto pCellAttributeMatrixNameValue = filterArgs.value(k_CellAttributeMatrixName_Key); auto pCellEnsembleAttributeMatrixNameValue = filterArgs.value(k_CellEnsembleAttributeMatrixName_Key); - DataPath cellEnsembleAMPath = pImageGeometryNameValue.createChildPath(pCellEnsembleAttributeMatrixNameValue); - DataPath cellAMPath = pImageGeometryNameValue.createChildPath(pCellAttributeMatrixNameValue); + DataPath cellEnsembleAMPath = {}; + DataPath cellAMPath = {}; - PreflightResult preflightResult; nx::core::Result resultOutputActions; std::vector preflightUpdatedValues; @@ -131,81 +144,109 @@ IFilter::PreflightResult ReadH5EspritDataFilter::preflightImpl(const DataStructu H5EspritReader::Pointer reader = H5EspritReader::New(); reader->setFileName(pSelectedScanNamesValue.inputFilePath.string()); reader->setReadPatternData(pReadPatternDataValue); - reader->setHDF5Path(pSelectedScanNamesValue.scanNames.front()); - if(const int err = reader->readHeaderOnly(); err < 0) - { - return MakePreflightErrorResult(-9682, fmt::format("An error occurred while reading the header data\n{} : {}", err, reader->getErrorMessage())); - } - // create the Image Geometry and it's attribute matrices - const CreateImageGeometryAction::DimensionType dims = {static_cast(reader->getXDimension()), static_cast(reader->getYDimension()), pSelectedScanNamesValue.scanNames.size()}; - const std::vector tupleDims = {dims[2], dims[1], dims[0]}; + for(const auto& name : pSelectedScanNamesValue.scanNames) { - CreateImageGeometryAction::SpacingType spacing = {static_cast(reader->getXStep()), static_cast(reader->getYStep()), pZSpacingValue}; - for(float& value : spacing) + reader->setHDF5Path(name); + if(const int err = reader->readHeaderOnly(); err < 0) { - value = (value == 0.0f ? 1.0f : value); + return MakePreflightErrorResult(-9682, fmt::format("An error occurred while reading the header data\n{} : {}", err, reader->getErrorMessage())); } - auto createDataGroupAction = std::make_unique(pImageGeometryNameValue, dims, pOriginValue, spacing, pCellAttributeMatrixNameValue); - resultOutputActions.value().appendAction(std::move(createDataGroupAction)); - } - const auto phases = reader->getPhaseVector(); - std::vector ensembleTupleDims{phases.size() + 1}; - { - auto createAttributeMatrixAction = std::make_unique(cellEnsembleAMPath, ensembleTupleDims); - resultOutputActions.value().appendAction(std::move(createAttributeMatrixAction)); - } - // create the cell ensemble arrays : these arrays are purposely created using the AngFile constant names to match the corresponding Oim import filter! - { - auto createArrayAction = std::make_unique(DataType::uint32, ensembleTupleDims, std::vector{1}, cellEnsembleAMPath.createChildPath(EbsdLib::AngFile::CrystalStructures)); - resultOutputActions.value().appendAction(std::move(createArrayAction)); - } - { - auto createArrayAction = std::make_unique(DataType::float32, ensembleTupleDims, std::vector{6}, cellEnsembleAMPath.createChildPath(EbsdLib::AngFile::LatticeConstants)); - resultOutputActions.value().appendAction(std::move(createArrayAction)); - } - { - auto createArrayAction = std::make_unique(ensembleTupleDims, cellEnsembleAMPath.createChildPath(EbsdLib::AngFile::MaterialName)); - resultOutputActions.value().appendAction(std::move(createArrayAction)); - } + CreateImageGeometryAction::SpacingType spacing = {static_cast(reader->getXStep()), + static_cast(reader->getYStep()), pZSpacingValue}; + std::transform(spacing.cbegin(), spacing.cend(), spacing.begin(), [](CreateImageGeometryAction::SpacingType::value_type value) { return (value == 0.0f ? 1.0f : value); }); - // create the cell data arrays - H5EspritFields espritFeatures; - const auto names = espritFeatures.getFilterFeatures>(); - for(const auto& name : names) - { - if(name == EbsdLib::H5Esprit::phi1 || name == EbsdLib::H5Esprit::PHI || name == EbsdLib::H5Esprit::phi2) + CreateImageGeometryAction::DimensionType dims = {static_cast(reader->getXDimension()), + static_cast(reader->getYDimension()), + pCombineScansValue ? pSelectedScanNamesValue.scanNames.size() : static_cast(1)}; + const std::vector tupleDims = {dims[2], dims[1], dims[0]}; + + if(pCombineScansValue) { - continue; + cellEnsembleAMPath = pImageGeometryNameValue.createChildPath(pCellEnsembleAttributeMatrixNameValue); + cellAMPath = pImageGeometryNameValue.createChildPath(pCellAttributeMatrixNameValue); + + auto createDataGroupAction = std::make_unique(pImageGeometryNameValue, dims, pOriginValue, spacing, pCellAttributeMatrixNameValue); + resultOutputActions.value().appendAction(std::move(createDataGroupAction)); } + else + { + DataPath imagePath = DataPath({name}); + cellEnsembleAMPath = imagePath.createChildPath(pCellEnsembleAttributeMatrixNameValue); + cellAMPath = imagePath.createChildPath(pCellAttributeMatrixNameValue); - if(reader->getPointerType(name) == EbsdLib::NumericTypes::Type::Int32) + // Temporary origin till we read out of file in execute + CreateImageGeometryAction::OriginType origin = {0.0f, 0.0f, 0.0f}; + + auto createDataGroupAction = std::make_unique(imagePath, dims, origin, spacing, pCellAttributeMatrixNameValue); + resultOutputActions.value().appendAction(std::move(createDataGroupAction)); + } + + const auto phases = reader->getPhaseVector(); + std::vector ensembleTupleDims{phases.size() + 1}; { - auto createArrayAction = std::make_unique(DataType::int32, tupleDims, std::vector{1}, cellAMPath.createChildPath(name)); + auto createAttributeMatrixAction = std::make_unique(cellEnsembleAMPath, ensembleTupleDims); + resultOutputActions.value().appendAction(std::move(createAttributeMatrixAction)); + } + + // create the cell ensemble arrays : these arrays are purposely created using the AngFile constant names to match the corresponding Oim import filter! + { + auto createArrayAction = std::make_unique(DataType::uint32, ensembleTupleDims, std::vector{1}, cellEnsembleAMPath.createChildPath(EbsdLib::AngFile::CrystalStructures)); resultOutputActions.value().appendAction(std::move(createArrayAction)); } - else if(reader->getPointerType(name) == EbsdLib::NumericTypes::Type::Float) { - auto createArrayAction = std::make_unique(DataType::float32, tupleDims, std::vector{1}, cellAMPath.createChildPath(name)); + auto createArrayAction = std::make_unique(DataType::float32, ensembleTupleDims, std::vector{6}, cellEnsembleAMPath.createChildPath(EbsdLib::AngFile::LatticeConstants)); resultOutputActions.value().appendAction(std::move(createArrayAction)); } - } - { - auto createArrayAction = std::make_unique(DataType::float32, tupleDims, std::vector{3}, cellAMPath.createChildPath(EbsdLib::Esprit::EulerAngles)); - resultOutputActions.value().appendAction(std::move(createArrayAction)); - } - if(pReadPatternDataValue) - { - std::array patternDims = {{0, 0}}; - reader->getPatternDims(patternDims); - if(patternDims[0] == 0 || patternDims[1] == 0) { - return MakePreflightErrorResult(-9683, fmt::format("The parameter 'Read Pattern Data' has been enabled but there does not seem to be any pattern data in the file for the scan name selected")); + auto createArrayAction = std::make_unique(ensembleTupleDims, cellEnsembleAMPath.createChildPath(EbsdLib::AngFile::MaterialName)); + resultOutputActions.value().appendAction(std::move(createArrayAction)); + } + + // create the cell data arrays + H5EspritFields espritFeatures; + const auto names = espritFeatures.getFilterFeatures>(); + for(const auto& featureName : names) + { + if(featureName == EbsdLib::H5Esprit::phi1 || featureName == EbsdLib::H5Esprit::PHI || featureName == EbsdLib::H5Esprit::phi2) + { + continue; + } + + if(reader->getPointerType(featureName) == EbsdLib::NumericTypes::Type::Int32) + { + auto createArrayAction = std::make_unique(DataType::int32, tupleDims, std::vector{1}, cellAMPath.createChildPath(featureName)); + resultOutputActions.value().appendAction(std::move(createArrayAction)); + } + else if(reader->getPointerType(featureName) == EbsdLib::NumericTypes::Type::Float) + { + auto createArrayAction = std::make_unique(DataType::float32, tupleDims, std::vector{1}, cellAMPath.createChildPath(featureName)); + resultOutputActions.value().appendAction(std::move(createArrayAction)); + } + } + + { + auto createArrayAction = std::make_unique(DataType::float32, tupleDims, std::vector{3}, cellAMPath.createChildPath(EbsdLib::Esprit::EulerAngles)); + resultOutputActions.value().appendAction(std::move(createArrayAction)); + } + if(pReadPatternDataValue) + { + std::array patternDims = {{0, 0}}; + reader->getPatternDims(patternDims); + if(patternDims[0] == 0 || patternDims[1] == 0) + { + return MakePreflightErrorResult(-9683, fmt::format("The parameter 'Read Pattern Data' has been enabled but there does not seem to be any pattern data in the file for the scan name selected")); + } + auto createArrayAction = std::make_unique(DataType::uint8, tupleDims, std::vector{static_cast(patternDims[0]), static_cast(patternDims[1])}, + cellAMPath.createChildPath(EbsdLib::H5Esprit::RawPatterns)); + resultOutputActions.value().appendAction(std::move(createArrayAction)); + } + + if(pCombineScansValue) + { + break; } - auto createArrayAction = std::make_unique(DataType::uint8, tupleDims, std::vector{static_cast(patternDims[0]), static_cast(patternDims[1])}, - cellAMPath.createChildPath(EbsdLib::H5Esprit::RawPatterns)); - resultOutputActions.value().appendAction(std::move(createArrayAction)); } return {std::move(resultOutputActions), std::move(preflightUpdatedValues)}; @@ -216,13 +257,15 @@ Result<> ReadH5EspritDataFilter::executeImpl(DataStructure& dataStructure, const const std::atomic_bool& shouldCancel, const ExecutionContext& executionContext) const { ReadH5DataInputValues inputValues; - ReadH5EspritDataInputValues espritInputValues; inputValues.SelectedScanNames = filterArgs.value(k_SelectedScanNames_Key); + inputValues.CombineScans = filterArgs.value(k_CombineScans_Key); inputValues.ReadPatternData = filterArgs.value(k_ReadPatternData_Key); inputValues.ImageGeometryPath = filterArgs.value(k_CreatedImageGeometryPath_Key); - inputValues.CellEnsembleAttributeMatrixPath = inputValues.ImageGeometryPath.createChildPath(filterArgs.value(k_CellEnsembleAttributeMatrixName_Key)); - inputValues.CellAttributeMatrixPath = inputValues.ImageGeometryPath.createChildPath(filterArgs.value(k_CellAttributeMatrixName_Key)); + inputValues.CellEnsembleAttributeMatrixName = filterArgs.value(k_CellEnsembleAttributeMatrixName_Key); + inputValues.CellAttributeMatrixName = filterArgs.value(k_CellAttributeMatrixName_Key); + + ReadH5EspritDataInputValues espritInputValues; espritInputValues.DegreesToRadians = filterArgs.value(k_DegreesToRadians_Key); return ReadH5EspritData(dataStructure, messageHandler, shouldCancel, &inputValues, &espritInputValues)(); diff --git a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ReadH5EspritDataFilter.hpp b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ReadH5EspritDataFilter.hpp index 3de02574c7..958feba34c 100644 --- a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ReadH5EspritDataFilter.hpp +++ b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ReadH5EspritDataFilter.hpp @@ -24,6 +24,7 @@ class ORIENTATIONANALYSIS_EXPORT ReadH5EspritDataFilter : public IFilter ReadH5EspritDataFilter& operator=(ReadH5EspritDataFilter&&) noexcept = delete; // Parameter Keys + // V1 Keys static inline constexpr StringLiteral k_SelectedScanNames_Key = "selected_scan_names"; static inline constexpr StringLiteral k_ZSpacing_Key = "z_spacing"; static inline constexpr StringLiteral k_Origin_Key = "origin"; @@ -33,6 +34,9 @@ class ORIENTATIONANALYSIS_EXPORT ReadH5EspritDataFilter : public IFilter static inline constexpr StringLiteral k_CellAttributeMatrixName_Key = "cell_attribute_matrix_name"; static inline constexpr StringLiteral k_CellEnsembleAttributeMatrixName_Key = "cell_ensemble_attribute_matrix_name"; + // V2 Keys + static inline constexpr StringLiteral k_CombineScans_Key = "combine_scans"; + /** * @brief Reads SIMPL json and converts it simplnx Arguments. * @param json diff --git a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ReadH5OimDataFilter.cpp b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ReadH5OimDataFilter.cpp index 50415cb71a..628ecff200 100644 --- a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ReadH5OimDataFilter.cpp +++ b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ReadH5OimDataFilter.cpp @@ -25,6 +25,19 @@ namespace fs = std::filesystem; using namespace nx::core; +namespace +{ +struct ReadH5OimDataFilterCache +{ + fs::path workingPath; + std::string preflightReturnString; + fs::file_time_type lastWrite; +}; + +std::atomic_int32_t s_InstanceId = 0; +std::map s_HeaderCache; +} // namespace + namespace nx::core { //------------------------------------------------------------------------------ @@ -67,11 +80,17 @@ Parameters ReadH5OimDataFilter::parameters() const params.insert(std::make_unique(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::EbsdReaderType::Oim, OEMEbsdScanSelectionParameter::ExtensionsType{".h5"})); + params.insertLinkableParameter( + std::make_unique(k_CombineScans_Key, "Stack Scans Along Z Axis", + "If true combines each of the multiple scans into a single image geometry along the z axis, else each will result in an individual geometry", true)); + params.insert(std::make_unique(k_ZSpacing_Key, "Z Spacing (Microns)", "The spacing in microns between each layer.", 1.0f)); params.insert(std::make_unique(k_Origin_Key, "Origin", "The origin of the volume", std::vector{0.0F, 0.0F, 0.0F}, std::vector{"x", "y", "z"})); params.insert(std::make_unique(k_ZSpacing_Key, "Z Spacing (Microns)", "The spacing in microns between each layer.", 1.0f)); params.insert(std::make_unique(k_ReadPatternData_Key, "Import Pattern Data", "Whether or not to import the pattern data", false)); + params.insertSeparator(Parameters::Separator{"Output Image Geometry"}); params.insert(std::make_unique(k_CreatedImageGeometryPath_Key, "Image Geometry", "The path to the created Image Geometry", DataPath({ImageGeom::k_TypeName}))); + params.insertSeparator(Parameters::Separator{"Output Cell Attribute Matrix"}); params.insert(std::make_unique(k_CellAttributeMatrixName_Key, "Cell Attribute Matrix", "The name of the cell data attribute matrix for the created Image Geometry", ImageGeom::k_CellAttributeMatrixName)); @@ -79,13 +98,22 @@ Parameters ReadH5OimDataFilter::parameters() const params.insert(std::make_unique(k_CellEnsembleAttributeMatrixName_Key, "Ensemble Attribute Matrix", "The Attribute Matrix where the phase information is stored.", "Cell Ensemble Data")); + // Link Parameters + params.linkParameters(k_CombineScans_Key, k_Origin_Key, true); + params.linkParameters(k_CombineScans_Key, k_CreatedImageGeometryPath_Key, true); + return params; } //------------------------------------------------------------------------------ IFilter::VersionType ReadH5OimDataFilter::parametersVersion() const { - return 1; + return 2; + + // Version 1 -> 2 + // Change 1: + // Added - k_CombineScans_Key = "combine_scans"; + // Solution - default parameter value 'true' preserves backwards functionality; } //------------------------------------------------------------------------------ @@ -99,6 +127,7 @@ IFilter::PreflightResult ReadH5OimDataFilter::preflightImpl(const DataStructure& const ExecutionContext& executionContext) const { auto pSelectedScanNamesValue = filterArgs.value(k_SelectedScanNames_Key); + auto pCombineScansValue = filterArgs.value(k_CombineScans_Key); // V2 Param auto pZSpacingValue = filterArgs.value(k_ZSpacing_Key); auto pOriginValue = filterArgs.value(k_Origin_Key); auto pReadPatternDataValue = filterArgs.value(k_ReadPatternData_Key); @@ -106,10 +135,9 @@ IFilter::PreflightResult ReadH5OimDataFilter::preflightImpl(const DataStructure& auto pCellAttributeMatrixNameValue = filterArgs.value(k_CellAttributeMatrixName_Key); auto pCellEnsembleAttributeMatrixNameValue = filterArgs.value(k_CellEnsembleAttributeMatrixName_Key); - DataPath cellEnsembleAMPath = pImageGeometryNameValue.createChildPath(pCellEnsembleAttributeMatrixNameValue); - DataPath cellAMPath = pImageGeometryNameValue.createChildPath(pCellAttributeMatrixNameValue); + DataPath cellEnsembleAMPath = {}; + DataPath cellAMPath = {}; - PreflightResult preflightResult; nx::core::Result resultOutputActions; std::vector preflightUpdatedValues; @@ -126,78 +154,102 @@ IFilter::PreflightResult ReadH5OimDataFilter::preflightImpl(const DataStructure& H5OIMReader::Pointer reader = H5OIMReader::New(); reader->setFileName(pSelectedScanNamesValue.inputFilePath.string()); reader->setReadPatternData(pReadPatternDataValue); - reader->setHDF5Path(pSelectedScanNamesValue.scanNames.front()); - if(const int err = reader->readHeaderOnly(); err < 0) - { - return MakePreflightErrorResult(-9582, fmt::format("An error occurred while reading the header data\n{} : {}", err, reader->getErrorMessage())); - } - // create the Image Geometry and it's attribute matrices - const CreateImageGeometryAction::DimensionType dims = {static_cast(reader->getXDimension()), static_cast(reader->getYDimension()), pSelectedScanNamesValue.scanNames.size()}; - const std::vector tupleDims = {dims[2], dims[1], dims[0]}; + for(const auto& name : pSelectedScanNamesValue.scanNames) { + reader->setHDF5Path(name); + if(const int err = reader->readHeaderOnly(); err < 0) + { + return MakePreflightErrorResult(-9582, fmt::format("An error occurred while reading the header data\n{} : {}", err, reader->getErrorMessage())); + } + CreateImageGeometryAction::SpacingType spacing = {reader->getXStep(), reader->getYStep(), pZSpacingValue}; + CreateImageGeometryAction::DimensionType dims = {static_cast(reader->getXDimension()), static_cast(reader->getYDimension()), + pCombineScansValue ? pSelectedScanNamesValue.scanNames.size() : static_cast(1)}; + const std::vector tupleDims = {dims[2], dims[1], dims[0]}; - auto createDataGroupAction = std::make_unique(pImageGeometryNameValue, dims, pOriginValue, spacing, pCellAttributeMatrixNameValue); - resultOutputActions.value().appendAction(std::move(createDataGroupAction)); - } - const auto phases = reader->getPhaseVector(); - std::vector ensembleTupleDims{phases.size() + 1}; - { - auto createAttributeMatrixAction = std::make_unique(cellEnsembleAMPath, ensembleTupleDims); - resultOutputActions.value().appendAction(std::move(createAttributeMatrixAction)); - } + if(pCombineScansValue) + { + cellEnsembleAMPath = pImageGeometryNameValue.createChildPath(pCellEnsembleAttributeMatrixNameValue); + cellAMPath = pImageGeometryNameValue.createChildPath(pCellAttributeMatrixNameValue); - // create the cell ensemble arrays - { - auto createArrayAction = std::make_unique(DataType::uint32, ensembleTupleDims, std::vector{1}, cellEnsembleAMPath.createChildPath(EbsdLib::AngFile::CrystalStructures)); - resultOutputActions.value().appendAction(std::move(createArrayAction)); - } - { - auto createArrayAction = std::make_unique(DataType::float32, ensembleTupleDims, std::vector{6}, cellEnsembleAMPath.createChildPath(EbsdLib::AngFile::LatticeConstants)); - resultOutputActions.value().appendAction(std::move(createArrayAction)); - } - { - auto createArrayAction = std::make_unique(ensembleTupleDims, cellEnsembleAMPath.createChildPath(EbsdLib::AngFile::MaterialName)); - resultOutputActions.value().appendAction(std::move(createArrayAction)); - } + auto createDataGroupAction = std::make_unique(pImageGeometryNameValue, dims, pOriginValue, spacing, pCellAttributeMatrixNameValue); + resultOutputActions.value().appendAction(std::move(createDataGroupAction)); + } + else + { + DataPath imagePath = DataPath({name}); + cellEnsembleAMPath = imagePath.createChildPath(pCellEnsembleAttributeMatrixNameValue); + cellAMPath = imagePath.createChildPath(pCellAttributeMatrixNameValue); + CreateImageGeometryAction::OriginType origin = {reader->getXStar(), reader->getYStar(), reader->getZStar()}; - // create the cell data arrays + auto createDataGroupAction = std::make_unique(imagePath, dims, origin, spacing, pCellAttributeMatrixNameValue); + resultOutputActions.value().appendAction(std::move(createDataGroupAction)); + } - AngFields angFeatures; - const auto names = angFeatures.getFilterFeatures>(); - for(const auto& name : names) - { - if(reader->getPointerType(name) == EbsdLib::NumericTypes::Type::Int32) + const auto phases = reader->getPhaseVector(); + std::vector ensembleTupleDims{phases.size() + 1}; { - auto createArrayAction = std::make_unique(DataType::int32, tupleDims, std::vector{1}, cellAMPath.createChildPath(name)); + auto createAttributeMatrixAction = std::make_unique(cellEnsembleAMPath, ensembleTupleDims); + resultOutputActions.value().appendAction(std::move(createAttributeMatrixAction)); + } + + // create the cell ensemble arrays + { + auto createArrayAction = std::make_unique(DataType::uint32, ensembleTupleDims, std::vector{1}, cellEnsembleAMPath.createChildPath(EbsdLib::AngFile::CrystalStructures)); resultOutputActions.value().appendAction(std::move(createArrayAction)); } - else if(reader->getPointerType(name) == EbsdLib::NumericTypes::Type::Float) { - auto createArrayAction = std::make_unique(DataType::float32, tupleDims, std::vector{1}, cellAMPath.createChildPath(name)); + auto createArrayAction = std::make_unique(DataType::float32, ensembleTupleDims, std::vector{6}, cellEnsembleAMPath.createChildPath(EbsdLib::AngFile::LatticeConstants)); resultOutputActions.value().appendAction(std::move(createArrayAction)); } - } - { - auto createArrayAction = std::make_unique(DataType::float32, tupleDims, std::vector{3}, cellAMPath.createChildPath(EbsdLib::AngFile::EulerAngles)); - resultOutputActions.value().appendAction(std::move(createArrayAction)); - } - { - auto createArrayAction = std::make_unique(DataType::int32, tupleDims, std::vector{1}, cellAMPath.createChildPath(EbsdLib::AngFile::Phases)); - resultOutputActions.value().appendAction(std::move(createArrayAction)); - } - if(pReadPatternDataValue) - { - std::array patternDims = {{0, 0}}; - reader->getPatternDims(patternDims); - if(patternDims[0] == 0 || patternDims[1] == 0) { - return MakePreflightErrorResult(-9583, fmt::format("The parameter 'Read Pattern Data' has been enabled but there does not seem to be any pattern data in the file for the scan name selected")); + auto createArrayAction = std::make_unique(ensembleTupleDims, cellEnsembleAMPath.createChildPath(EbsdLib::AngFile::MaterialName)); + resultOutputActions.value().appendAction(std::move(createArrayAction)); + } + + // create the cell data arrays + AngFields angFeatures; + const auto names = angFeatures.getFilterFeatures>(); + for(const auto& angName : names) + { + if(reader->getPointerType(angName) == EbsdLib::NumericTypes::Type::Int32) + { + auto createArrayAction = std::make_unique(DataType::int32, tupleDims, std::vector{1}, cellAMPath.createChildPath(angName)); + resultOutputActions.value().appendAction(std::move(createArrayAction)); + } + else if(reader->getPointerType(angName) == EbsdLib::NumericTypes::Type::Float) + { + auto createArrayAction = std::make_unique(DataType::float32, tupleDims, std::vector{1}, cellAMPath.createChildPath(angName)); + resultOutputActions.value().appendAction(std::move(createArrayAction)); + } + } + + { + auto createArrayAction = std::make_unique(DataType::float32, tupleDims, std::vector{3}, cellAMPath.createChildPath(EbsdLib::AngFile::EulerAngles)); + resultOutputActions.value().appendAction(std::move(createArrayAction)); + } + { + auto createArrayAction = std::make_unique(DataType::int32, tupleDims, std::vector{1}, cellAMPath.createChildPath(EbsdLib::AngFile::Phases)); + resultOutputActions.value().appendAction(std::move(createArrayAction)); + } + if(pReadPatternDataValue) + { + std::array patternDims = {{0, 0}}; + reader->getPatternDims(patternDims); + if(patternDims[0] == 0 || patternDims[1] == 0) + { + return MakePreflightErrorResult(-9583, fmt::format("The parameter 'Read Pattern Data' has been enabled but there does not seem to be any pattern data in the file for the scan name selected")); + } + auto createArrayAction = std::make_unique(DataType::uint8, tupleDims, std::vector{static_cast(patternDims[0]), static_cast(patternDims[1])}, + cellAMPath.createChildPath(EbsdLib::Ang::PatternData)); + resultOutputActions.value().appendAction(std::move(createArrayAction)); + } + + if(pCombineScansValue) + { + break; } - auto createArrayAction = std::make_unique(DataType::uint8, tupleDims, std::vector{static_cast(patternDims[0]), static_cast(patternDims[1])}, - cellAMPath.createChildPath(EbsdLib::Ang::PatternData)); - resultOutputActions.value().appendAction(std::move(createArrayAction)); } return {std::move(resultOutputActions), std::move(preflightUpdatedValues)}; @@ -210,10 +262,11 @@ Result<> ReadH5OimDataFilter::executeImpl(DataStructure& dataStructure, const Ar ReadH5DataInputValues inputValues; inputValues.SelectedScanNames = filterArgs.value(k_SelectedScanNames_Key); + inputValues.CombineScans = filterArgs.value(k_CombineScans_Key); inputValues.ReadPatternData = filterArgs.value(k_ReadPatternData_Key); inputValues.ImageGeometryPath = filterArgs.value(k_CreatedImageGeometryPath_Key); - inputValues.CellEnsembleAttributeMatrixPath = inputValues.ImageGeometryPath.createChildPath(filterArgs.value(k_CellEnsembleAttributeMatrixName_Key)); - inputValues.CellAttributeMatrixPath = inputValues.ImageGeometryPath.createChildPath(filterArgs.value(k_CellAttributeMatrixName_Key)); + inputValues.CellEnsembleAttributeMatrixName = filterArgs.value(k_CellEnsembleAttributeMatrixName_Key); + inputValues.CellAttributeMatrixName = filterArgs.value(k_CellAttributeMatrixName_Key); return ReadH5OimData(dataStructure, messageHandler, shouldCancel, &inputValues)(); } diff --git a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ReadH5OimDataFilter.hpp b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ReadH5OimDataFilter.hpp index e28484a5aa..5f808d2699 100644 --- a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ReadH5OimDataFilter.hpp +++ b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ReadH5OimDataFilter.hpp @@ -25,6 +25,7 @@ class ORIENTATIONANALYSIS_EXPORT ReadH5OimDataFilter : public IFilter ReadH5OimDataFilter& operator=(ReadH5OimDataFilter&&) noexcept = delete; // Parameter Keys + // V1 Keys static inline constexpr StringLiteral k_SelectedScanNames_Key = "selected_scan_names"; static inline constexpr StringLiteral k_ZSpacing_Key = "z_spacing"; static inline constexpr StringLiteral k_Origin_Key = "origin"; @@ -33,6 +34,9 @@ class ORIENTATIONANALYSIS_EXPORT ReadH5OimDataFilter : public IFilter static inline constexpr StringLiteral k_CellAttributeMatrixName_Key = "cell_attribute_matrix_name"; static inline constexpr StringLiteral k_CellEnsembleAttributeMatrixName_Key = "cell_ensemble_attribute_matrix_name"; + // V2 Keys + static inline constexpr StringLiteral k_CombineScans_Key = "combine_scans"; + /** * @brief Reads SIMPL json and converts it simplnx Arguments. * @param json diff --git a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ReadH5OinaDataFilter.cpp b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ReadH5OinaDataFilter.cpp index b8bf0e6b9e..f6aee11341 100644 --- a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ReadH5OinaDataFilter.cpp +++ b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ReadH5OinaDataFilter.cpp @@ -66,14 +66,19 @@ Parameters ReadH5OinaDataFilter::parameters() const params.insert(std::make_unique(k_SelectedScanNames_Key, "Scan Names", "The name of the scan in the .h5oina file. Oxford can store multiple scans in a single file", OEMEbsdScanSelectionParameter::ValueType{}, OEMEbsdScanSelectionParameter::EbsdReaderType::H5Oina, OEMEbsdScanSelectionParameter::ExtensionsType{".h5oina"})); + params.insertLinkableParameter( + std::make_unique(k_CombineScans_Key, "Stack Scans Along Z Axis", + "If true combines each of the multiple scans into a single image geometry along the z axis, else each will result in an individual geometry", true)); params.insert(std::make_unique(k_EdaxHexagonalAlignment_Key, "Convert Hexagonal X-Axis to EDAX Standard", "Whether or not to convert a Hexagonal phase to the EDAX standard for x-axis alignment", true)); params.insert(std::make_unique(k_ConvertPhaseToInt32_Key, "Convert Phase Data to Int32", "Native Phases data value is uint8. Convert to Int32 for better filter compatibility", true)); params.insert(std::make_unique(k_Origin_Key, "Origin", "The origin of the volume", std::vector{0.0F, 0.0F, 0.0F}, std::vector{"x", "y", "z"})); params.insert(std::make_unique(k_ZSpacing_Key, "Z Spacing (Microns)", "The spacing in microns between each layer.", 1.0f)); params.insert(std::make_unique(k_ReadPatternData_Key, "Import Pattern Data", "Whether or not to import the pattern data", false)); + params.insertSeparator(Parameters::Separator{"Output Image Geometry"}); params.insert(std::make_unique(k_CreatedImageGeometryPath_Key, "Image Geometry", "The path to the created Image Geometry", DataPath({ImageGeom::k_TypeName}))); + params.insertSeparator(Parameters::Separator{"Output Cell Attribute Matrix"}); params.insert(std::make_unique(k_CellAttributeMatrixName_Key, "Cell Attribute Matrix", "The name of the cell data attribute matrix for the created Image Geometry", ImageGeom::k_CellAttributeMatrixName)); @@ -81,13 +86,22 @@ Parameters ReadH5OinaDataFilter::parameters() const params.insert(std::make_unique(k_CellEnsembleAttributeMatrixName_Key, "Ensemble Attribute Matrix", "The Attribute Matrix where the phase information is stored.", "Cell Ensemble Data")); + // Link Parameters + params.linkParameters(k_CombineScans_Key, k_Origin_Key, true); + params.linkParameters(k_CombineScans_Key, k_CreatedImageGeometryPath_Key, true); + return params; } //------------------------------------------------------------------------------ IFilter::VersionType ReadH5OinaDataFilter::parametersVersion() const { - return 1; + return 2; + + // Version 1 -> 2 + // Change 1: + // Added - k_CombineScans_Key = "combine_scans"; + // Solution - default parameter value 'true' preserves backwards functionality; } //------------------------------------------------------------------------------ @@ -101,6 +115,7 @@ IFilter::PreflightResult ReadH5OinaDataFilter::preflightImpl(const DataStructure const std::atomic_bool& shouldCancel, const ExecutionContext& executionContext) const { auto pSelectedScanNamesValue = filterArgs.value(k_SelectedScanNames_Key); + auto pCombineScansValue = filterArgs.value(k_CombineScans_Key); // V2 Param auto pZSpacingValue = filterArgs.value(k_ZSpacing_Key); auto pOriginValue = filterArgs.value(k_Origin_Key); auto pReadPatternDataValue = filterArgs.value(k_ReadPatternData_Key); @@ -109,10 +124,9 @@ IFilter::PreflightResult ReadH5OinaDataFilter::preflightImpl(const DataStructure auto pCellEnsembleAttributeMatrixNameValue = filterArgs.value(k_CellEnsembleAttributeMatrixName_Key); auto pConvertPhaseData = filterArgs.value(k_ConvertPhaseToInt32_Key); - DataPath cellEnsembleAMPath = pImageGeometryNameValue.createChildPath(pCellEnsembleAttributeMatrixNameValue); - DataPath cellAMPath = pImageGeometryNameValue.createChildPath(pCellAttributeMatrixNameValue); + DataPath cellEnsembleAMPath = {}; + DataPath cellAMPath = {}; - PreflightResult preflightResult; nx::core::Result resultOutputActions; std::vector preflightUpdatedValues; @@ -129,71 +143,96 @@ IFilter::PreflightResult ReadH5OinaDataFilter::preflightImpl(const DataStructure H5OINAReader reader; reader.setFileName(pSelectedScanNamesValue.inputFilePath.string()); reader.setReadPatternData(pReadPatternDataValue); - reader.setHDF5Path(pSelectedScanNamesValue.scanNames.front()); - if(const int err = reader.readHeaderOnly(); err < 0) - { - return MakePreflightErrorResult(-9582, fmt::format("An error occurred while reading the header data\n{} : {}", err, reader.getErrorMessage())); - } - // create the Image Geometry and it's attribute matrices - const CreateImageGeometryAction::DimensionType dims = {static_cast(reader.getXDimension()), static_cast(reader.getYDimension()), pSelectedScanNamesValue.scanNames.size()}; - const std::vector tupleDims = {dims[2], dims[1], dims[0]}; + for(const auto& name : pSelectedScanNamesValue.scanNames) { + reader.setHDF5Path(name); + if(const int err = reader.readHeaderOnly(); err < 0) + { + return MakePreflightErrorResult(-9582, fmt::format("An error occurred while reading the header data\n{} : {}", err, reader.getErrorMessage())); + } + CreateImageGeometryAction::SpacingType spacing = {reader.getXStep(), reader.getYStep(), pZSpacingValue}; + CreateImageGeometryAction::DimensionType dims = {static_cast(reader.getXDimension()), static_cast(reader.getYDimension()), + pCombineScansValue ? pSelectedScanNamesValue.scanNames.size() : static_cast(1)}; + const std::vector tupleDims = {dims[2], dims[1], dims[0]}; - auto createDataGroupAction = std::make_unique(pImageGeometryNameValue, dims, pOriginValue, spacing, pCellAttributeMatrixNameValue); - resultOutputActions.value().appendAction(std::move(createDataGroupAction)); - } - const auto phases = reader.getPhaseVector(); - std::vector ensembleTupleDims{phases.size() + 1}; - { - auto createAttributeMatrixAction = std::make_unique(cellEnsembleAMPath, ensembleTupleDims); - resultOutputActions.value().appendAction(std::move(createAttributeMatrixAction)); - } + if(pCombineScansValue) + { + cellEnsembleAMPath = pImageGeometryNameValue.createChildPath(pCellEnsembleAttributeMatrixNameValue); + cellAMPath = pImageGeometryNameValue.createChildPath(pCellAttributeMatrixNameValue); - // create the cell ensemble arrays - { - auto createArrayAction = std::make_unique(DataType::uint32, ensembleTupleDims, std::vector{1}, cellEnsembleAMPath.createChildPath(EbsdLib::CtfFile::CrystalStructures)); - resultOutputActions.value().appendAction(std::move(createArrayAction)); - } - { - auto createArrayAction = std::make_unique(DataType::float32, ensembleTupleDims, std::vector{6}, cellEnsembleAMPath.createChildPath(EbsdLib::CtfFile::LatticeConstants)); - resultOutputActions.value().appendAction(std::move(createArrayAction)); - } - { - auto createArrayAction = std::make_unique(ensembleTupleDims, cellEnsembleAMPath.createChildPath(EbsdLib::CtfFile::MaterialName)); - resultOutputActions.value().appendAction(std::move(createArrayAction)); - } + auto createDataGroupAction = std::make_unique(pImageGeometryNameValue, dims, pOriginValue, spacing, pCellAttributeMatrixNameValue); + resultOutputActions.value().appendAction(std::move(createDataGroupAction)); + } + else + { + DataPath imagePath = DataPath({name}); + cellEnsembleAMPath = imagePath.createChildPath(pCellEnsembleAttributeMatrixNameValue); + cellAMPath = imagePath.createChildPath(pCellAttributeMatrixNameValue); + CreateImageGeometryAction::OriginType origin = {0.0f, 0.0f, 0.0f}; // Will be set later via a min points check - // create the cell data arrays - resultOutputActions.value().appendAction(std::make_unique(DataType::uint8, tupleDims, std::vector{1}, cellAMPath.createChildPath(EbsdLib::H5OINA::BandContrast))); - resultOutputActions.value().appendAction(std::make_unique(DataType::uint8, tupleDims, std::vector{1}, cellAMPath.createChildPath(EbsdLib::H5OINA::BandSlope))); - resultOutputActions.value().appendAction(std::make_unique(DataType::uint8, tupleDims, std::vector{1}, cellAMPath.createChildPath(EbsdLib::H5OINA::Bands))); - resultOutputActions.value().appendAction(std::make_unique(DataType::uint8, tupleDims, std::vector{1}, cellAMPath.createChildPath(EbsdLib::H5OINA::Error))); - resultOutputActions.value().appendAction(std::make_unique(DataType::float32, tupleDims, std::vector{3}, cellAMPath.createChildPath(EbsdLib::H5OINA::Euler))); - resultOutputActions.value().appendAction(std::make_unique(DataType::float32, tupleDims, std::vector{1}, cellAMPath.createChildPath(EbsdLib::H5OINA::MeanAngularDeviation))); - if(pConvertPhaseData) - { - resultOutputActions.value().appendAction(std::make_unique(DataType::int32, tupleDims, std::vector{1}, cellAMPath.createChildPath(EbsdLib::H5OINA::Phase))); - } - else - { - resultOutputActions.value().appendAction(std::make_unique(DataType::uint8, tupleDims, std::vector{1}, cellAMPath.createChildPath(EbsdLib::H5OINA::Phase))); - } - resultOutputActions.value().appendAction(std::make_unique(DataType::float32, tupleDims, std::vector{1}, cellAMPath.createChildPath(EbsdLib::H5OINA::X))); - resultOutputActions.value().appendAction(std::make_unique(DataType::float32, tupleDims, std::vector{1}, cellAMPath.createChildPath(EbsdLib::H5OINA::Y))); + auto createDataGroupAction = std::make_unique(imagePath, dims, origin, spacing, pCellAttributeMatrixNameValue); + resultOutputActions.value().appendAction(std::move(createDataGroupAction)); + } - if(pReadPatternDataValue) - { - std::array patternDims = {{0, 0}}; - reader.getPatternDims(patternDims); - if(patternDims[0] == 0 || patternDims[1] == 0) + const auto phases = reader.getPhaseVector(); + std::vector ensembleTupleDims{phases.size() + 1}; + { + auto createAttributeMatrixAction = std::make_unique(cellEnsembleAMPath, ensembleTupleDims); + resultOutputActions.value().appendAction(std::move(createAttributeMatrixAction)); + } + + // create the cell ensemble arrays + { + auto createArrayAction = std::make_unique(DataType::uint32, ensembleTupleDims, std::vector{1}, cellEnsembleAMPath.createChildPath(EbsdLib::CtfFile::CrystalStructures)); + resultOutputActions.value().appendAction(std::move(createArrayAction)); + } + { + auto createArrayAction = std::make_unique(DataType::float32, ensembleTupleDims, std::vector{6}, cellEnsembleAMPath.createChildPath(EbsdLib::CtfFile::LatticeConstants)); + resultOutputActions.value().appendAction(std::move(createArrayAction)); + } + { + auto createArrayAction = std::make_unique(ensembleTupleDims, cellEnsembleAMPath.createChildPath(EbsdLib::CtfFile::MaterialName)); + resultOutputActions.value().appendAction(std::move(createArrayAction)); + } + + // create the cell data arrays + resultOutputActions.value().appendAction(std::make_unique(DataType::uint8, tupleDims, std::vector{1}, cellAMPath.createChildPath(EbsdLib::H5OINA::BandContrast))); + resultOutputActions.value().appendAction(std::make_unique(DataType::uint8, tupleDims, std::vector{1}, cellAMPath.createChildPath(EbsdLib::H5OINA::BandSlope))); + resultOutputActions.value().appendAction(std::make_unique(DataType::uint8, tupleDims, std::vector{1}, cellAMPath.createChildPath(EbsdLib::H5OINA::Bands))); + resultOutputActions.value().appendAction(std::make_unique(DataType::uint8, tupleDims, std::vector{1}, cellAMPath.createChildPath(EbsdLib::H5OINA::Error))); + resultOutputActions.value().appendAction(std::make_unique(DataType::float32, tupleDims, std::vector{3}, cellAMPath.createChildPath(EbsdLib::H5OINA::Euler))); + resultOutputActions.value().appendAction( + std::make_unique(DataType::float32, tupleDims, std::vector{1}, cellAMPath.createChildPath(EbsdLib::H5OINA::MeanAngularDeviation))); + if(pConvertPhaseData) + { + resultOutputActions.value().appendAction(std::make_unique(DataType::int32, tupleDims, std::vector{1}, cellAMPath.createChildPath(EbsdLib::H5OINA::Phase))); + } + else + { + resultOutputActions.value().appendAction(std::make_unique(DataType::uint8, tupleDims, std::vector{1}, cellAMPath.createChildPath(EbsdLib::H5OINA::Phase))); + } + resultOutputActions.value().appendAction(std::make_unique(DataType::float32, tupleDims, std::vector{1}, cellAMPath.createChildPath(EbsdLib::H5OINA::X))); + resultOutputActions.value().appendAction(std::make_unique(DataType::float32, tupleDims, std::vector{1}, cellAMPath.createChildPath(EbsdLib::H5OINA::Y))); + + if(pReadPatternDataValue) + { + std::array patternDims = {{0, 0}}; + reader.getPatternDims(patternDims); + if(patternDims[0] == 0 || patternDims[1] == 0) + { + return MakePreflightErrorResult(-9583, fmt::format("The parameter 'Read Pattern Data' has been enabled but there does not seem to be any pattern data in the file for the scan name selected")); + } + auto createArrayAction = std::make_unique(DataType::uint16, tupleDims, std::vector{static_cast(patternDims[0]), static_cast(patternDims[1])}, + cellAMPath.createChildPath(EbsdLib::H5OINA::UnprocessedPatterns)); + resultOutputActions.value().appendAction(std::move(createArrayAction)); + } + + if(pCombineScansValue) { - return MakePreflightErrorResult(-9583, fmt::format("The parameter 'Read Pattern Data' has been enabled but there does not seem to be any pattern data in the file for the scan name selected")); + break; } - auto createArrayAction = std::make_unique(DataType::uint16, tupleDims, std::vector{static_cast(patternDims[0]), static_cast(patternDims[1])}, - cellAMPath.createChildPath(EbsdLib::H5OINA::UnprocessedPatterns)); - resultOutputActions.value().appendAction(std::move(createArrayAction)); } return {std::move(resultOutputActions), std::move(preflightUpdatedValues)}; @@ -206,10 +245,11 @@ Result<> ReadH5OinaDataFilter::executeImpl(DataStructure& dataStructure, const A ReadH5DataInputValues inputValues; inputValues.SelectedScanNames = filterArgs.value(k_SelectedScanNames_Key); + inputValues.CombineScans = filterArgs.value(k_CombineScans_Key); inputValues.ReadPatternData = filterArgs.value(k_ReadPatternData_Key); inputValues.ImageGeometryPath = filterArgs.value(k_CreatedImageGeometryPath_Key); - inputValues.CellEnsembleAttributeMatrixPath = inputValues.ImageGeometryPath.createChildPath(filterArgs.value(k_CellEnsembleAttributeMatrixName_Key)); - inputValues.CellAttributeMatrixPath = inputValues.ImageGeometryPath.createChildPath(filterArgs.value(k_CellAttributeMatrixName_Key)); + inputValues.CellEnsembleAttributeMatrixName = filterArgs.value(k_CellEnsembleAttributeMatrixName_Key); + inputValues.CellAttributeMatrixName = filterArgs.value(k_CellAttributeMatrixName_Key); inputValues.ConvertPhaseToInt32 = filterArgs.value(k_ConvertPhaseToInt32_Key); inputValues.EdaxHexagonalAlignment = filterArgs.value(k_EdaxHexagonalAlignment_Key); diff --git a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ReadH5OinaDataFilter.hpp b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ReadH5OinaDataFilter.hpp index 79b3b82c6c..0a4f653d1f 100644 --- a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ReadH5OinaDataFilter.hpp +++ b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/Filters/ReadH5OinaDataFilter.hpp @@ -24,6 +24,7 @@ class ORIENTATIONANALYSIS_EXPORT ReadH5OinaDataFilter : public IFilter ReadH5OinaDataFilter& operator=(ReadH5OinaDataFilter&&) noexcept = delete; // Parameter Keys + // V1 Keys static inline constexpr StringLiteral k_SelectedScanNames_Key = "selected_scan_names"; static inline constexpr StringLiteral k_ZSpacing_Key = "z_spacing"; static inline constexpr StringLiteral k_Origin_Key = "origin"; @@ -34,6 +35,9 @@ class ORIENTATIONANALYSIS_EXPORT ReadH5OinaDataFilter : public IFilter static inline constexpr StringLiteral k_EdaxHexagonalAlignment_Key = "edax_hexagonal_alignment"; static inline constexpr StringLiteral k_ConvertPhaseToInt32_Key = "convert_phase_to_int32"; + // V2 Keys + static inline constexpr StringLiteral k_CombineScans_Key = "combine_scans"; + /** * @brief Returns the name of the filter. * @return diff --git a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/utilities/IEbsdOemReader.hpp b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/utilities/IEbsdOemReader.hpp index 2ebf3ee4d4..5178b5bc63 100644 --- a/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/utilities/IEbsdOemReader.hpp +++ b/src/Plugins/OrientationAnalysis/src/OrientationAnalysis/utilities/IEbsdOemReader.hpp @@ -19,10 +19,11 @@ namespace nx::core struct ORIENTATIONANALYSIS_EXPORT ReadH5DataInputValues { OEMEbsdScanSelectionParameter::ValueType SelectedScanNames; + bool CombineScans; bool ReadPatternData; DataPath ImageGeometryPath; - DataPath CellAttributeMatrixPath; - DataPath CellEnsembleAttributeMatrixPath; + std::string CellAttributeMatrixName; + std::string CellEnsembleAttributeMatrixName; bool EdaxHexagonalAlignment; bool ConvertPhaseToInt32; }; @@ -30,7 +31,6 @@ struct ORIENTATIONANALYSIS_EXPORT ReadH5DataInputValues /** * @class ReadH5Data */ - template class ORIENTATIONANALYSIS_EXPORT IEbsdOemReader { @@ -54,8 +54,11 @@ class ORIENTATIONANALYSIS_EXPORT IEbsdOemReader Result<> execute() { - auto& imageGeom = m_DataStructure.getDataRefAs(m_InputValues->ImageGeometryPath); - imageGeom.setUnits(IGeometry::LengthUnit::Micrometer); + if(m_InputValues->CombineScans) + { + auto& imageGeom = m_DataStructure.getDataRefAs(m_InputValues->ImageGeometryPath); + imageGeom.setUnits(IGeometry::LengthUnit::Micrometer); + } int index = 0; for(const auto& currentScanName : m_InputValues->SelectedScanNames.scanNames) @@ -68,7 +71,18 @@ class ORIENTATIONANALYSIS_EXPORT IEbsdOemReader return readResults; } - Result<> copyDataResults = copyRawEbsdData(index); + Result<> copyDataResults = {}; + if(m_InputValues->CombineScans) + { + copyDataResults = copyRawEbsdData(index); + } + else + { + auto& imageGeom = m_DataStructure.getDataRefAs(DataPath({currentScanName})); + imageGeom.setUnits(IGeometry::LengthUnit::Micrometer); + copyDataResults = copyRawEbsdData(currentScanName); + } + if(copyDataResults.invalid()) { return copyDataResults; @@ -90,6 +104,12 @@ class ORIENTATIONANALYSIS_EXPORT IEbsdOemReader // If the user has already set a Scan Name to read then we are good to go. m_Reader->setHDF5Path(scanName); + DataPath imagePath({scanName}); + if(m_InputValues->CombineScans) + { + imagePath = m_InputValues->ImageGeometryPath; + } + if(const int32 err = m_Reader->readFile(); err < 0) { return MakeErrorResult(-8970, fmt::format("Attempting to read scan '{}' from file '{}' produced an error from the '{}' class.\n Error Code: {}\n Message: {}", scanName, @@ -103,9 +123,10 @@ class ORIENTATIONANALYSIS_EXPORT IEbsdOemReader } // These arrays are purposely created using the AngFile constant names for BOTH the Oim and the Esprit readers! - auto& crystalStructures = m_DataStructure.getDataRefAs(m_InputValues->CellEnsembleAttributeMatrixPath.createChildPath(EbsdLib::AngFile::CrystalStructures)); - auto& materialNames = m_DataStructure.getDataRefAs(m_InputValues->CellEnsembleAttributeMatrixPath.createChildPath(EbsdLib::AngFile::MaterialName)); - auto& latticeConstantsArray = m_DataStructure.getDataRefAs(m_InputValues->CellEnsembleAttributeMatrixPath.createChildPath(EbsdLib::AngFile::LatticeConstants)); + const DataPath cellEnsembleAM = imagePath.createChildPath(m_InputValues->CellEnsembleAttributeMatrixName); + auto& crystalStructures = m_DataStructure.getDataRefAs(cellEnsembleAM.createChildPath(EbsdLib::AngFile::CrystalStructures)); + auto& materialNames = m_DataStructure.getDataRefAs(cellEnsembleAM.createChildPath(EbsdLib::AngFile::MaterialName)); + auto& latticeConstantsArray = m_DataStructure.getDataRefAs(cellEnsembleAM.createChildPath(EbsdLib::AngFile::LatticeConstants)); Float32Array::store_type* latticeConstants = latticeConstantsArray.getDataStore(); crystalStructures[0] = EbsdLib::CrystalStructure::UnknownCrystalStructure; @@ -131,10 +152,19 @@ class ORIENTATIONANALYSIS_EXPORT IEbsdOemReader latticeConstants->setComponent(phaseId, 5, lc[5]); } - return {}; + if(m_InputValues->CombineScans) + { + // No need to update origin + return {}; + } + + return updateOrigin(scanName); } + virtual Result<> updateOrigin(const std::string& scanName) = 0; + virtual Result<> copyRawEbsdData(int index) = 0; + virtual Result<> copyRawEbsdData(const std::string& scanName) = 0; protected: std::shared_ptr m_Reader;