-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
FILT: Add Oxford Channel 5 Binary file reader.
- Requires EbsdLib 1.0.34 or higher - Filter requires BOTh .cpr and .crc files to be present - Needs a unit test Signed-off-by: Michael Jackson <[email protected]>
- Loading branch information
1 parent
382861a
commit 42dc0f8
Showing
8 changed files
with
709 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
185 changes: 185 additions & 0 deletions
185
...ugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ReadChannel5Data.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
#include "ReadChannel5Data.hpp" | ||
|
||
#include "simplnx/Common/RgbColor.hpp" | ||
#include "simplnx/DataStructure/DataArray.hpp" | ||
#include "simplnx/DataStructure/Geometry/ImageGeom.hpp" | ||
#include "simplnx/DataStructure/StringArray.hpp" | ||
#include "simplnx/Utilities/Math/MatrixMath.hpp" | ||
#include "simplnx/Utilities/StringUtilities.hpp" | ||
|
||
#include "EbsdLib/Core/Orientation.hpp" | ||
|
||
using namespace nx::core; | ||
|
||
using FloatVec3Type = std::vector<float>; | ||
|
||
namespace | ||
{ | ||
template <typename T> | ||
void copyRawData(const ReadChannel5DataInputValues* m_InputValues, size_t numElements, DataStructure& m_DataStructure, CprReader& m_Reader, const std::string& name, DataPath& dataArrayPath) | ||
{ | ||
using ArrayType = DataArray<T>; | ||
auto& dataRef = m_DataStructure.getDataRefAs<ArrayType>(dataArrayPath); | ||
auto* dataStorePtr = dataRef.getDataStore(); | ||
|
||
const nonstd::span<T> rawDataPtr(reinterpret_cast<T*>(m_Reader.getPointerByName(name)), numElements); | ||
// std::copy(rawDataPtr.begin(), rawDataPtr.end(), dataStorePtr->begin() + offset); | ||
for(size_t idx = 0; idx < numElements; idx++) | ||
{ | ||
dataStorePtr->setValue(idx, rawDataPtr[idx]); | ||
} | ||
} | ||
|
||
} // namespace | ||
|
||
// ----------------------------------------------------------------------------- | ||
ReadChannel5Data::ReadChannel5Data(DataStructure& dataStructure, const IFilter::MessageHandler& msgHandler, const std::atomic_bool& shouldCancel, ReadChannel5DataInputValues* inputValues) | ||
: m_DataStructure(dataStructure) | ||
, m_MessageHandler(msgHandler) | ||
, m_ShouldCancel(shouldCancel) | ||
, m_InputValues(inputValues) | ||
{ | ||
} | ||
|
||
// ----------------------------------------------------------------------------- | ||
ReadChannel5Data::~ReadChannel5Data() noexcept = default; | ||
|
||
// ----------------------------------------------------------------------------- | ||
Result<> ReadChannel5Data::operator()() | ||
{ | ||
CprReader reader; | ||
reader.setFileName(m_InputValues->InputFile.string()); | ||
const int32_t err = reader.readFile(); | ||
if(err < 0) | ||
{ | ||
return MakeErrorResult(reader.getErrorCode(), reader.getErrorMessage()); | ||
} | ||
|
||
const auto result = loadMaterialInfo(&reader); | ||
if(result.first < 0) | ||
{ | ||
return MakeErrorResult(result.first, result.second); | ||
} | ||
|
||
copyRawEbsdData(&reader); | ||
|
||
return {}; | ||
} | ||
|
||
// ----------------------------------------------------------------------------- | ||
std::pair<int32, std::string> ReadChannel5Data::loadMaterialInfo(CprReader* reader) const | ||
{ | ||
const std::vector<CtfPhase::Pointer> phases = reader->getPhaseVector(); | ||
if(phases.empty()) | ||
{ | ||
return {reader->getErrorCode(), reader->getErrorMessage()}; | ||
} | ||
|
||
const DataPath CellEnsembleAttributeMatrixPath = m_InputValues->DataContainerName.createChildPath(m_InputValues->CellEnsembleAttributeMatrixName); | ||
|
||
auto& crystalStructures = m_DataStructure.getDataRefAs<UInt32Array>(CellEnsembleAttributeMatrixPath.createChildPath(EbsdLib::CtfFile::CrystalStructures)); | ||
|
||
auto& materialNames = m_DataStructure.getDataRefAs<StringArray>(CellEnsembleAttributeMatrixPath.createChildPath(EbsdLib::CtfFile::MaterialName)); | ||
|
||
auto& latticeConstants = m_DataStructure.getDataRefAs<Float32Array>(CellEnsembleAttributeMatrixPath.createChildPath(EbsdLib::CtfFile::LatticeConstants)); | ||
|
||
const std::string k_InvalidPhase = "Invalid Phase"; | ||
|
||
// Initialize the zero'th element to unknowns. The other elements will | ||
// be filled in based on values from the data file | ||
crystalStructures[0] = EbsdLib::CrystalStructure::UnknownCrystalStructure; | ||
materialNames[0] = k_InvalidPhase; | ||
|
||
for(size_t i = 0; i < 6; i++) | ||
{ | ||
latticeConstants.getDataStoreRef().setComponent(0, i, 0.0F); | ||
} | ||
|
||
for(const CtfPhase::Pointer& phase : phases) | ||
{ | ||
const int32_t phaseID = phase->getPhaseIndex(); | ||
crystalStructures[phaseID] = phase->determineOrientationOpsIndex(); | ||
std::string materialName = phase->getMaterialName(); | ||
materialName = nx::core::StringUtilities::replace(materialName, "MaterialName", ""); | ||
materialName = nx::core::StringUtilities::trimmed(materialName); | ||
materialNames[phaseID] = materialName; | ||
|
||
std::vector<float> lattConst = phase->getLatticeConstants(); | ||
|
||
for(size_t i = 0; i < 6; i++) | ||
{ | ||
latticeConstants.getDataStoreRef().setComponent(phaseID, i, lattConst[i]); | ||
} | ||
} | ||
return {0, ""}; | ||
} | ||
|
||
// ----------------------------------------------------------------------------- | ||
void ReadChannel5Data::copyRawEbsdData(CprReader* reader) const | ||
{ | ||
const DataPath cellAttributeMatrixPath = m_InputValues->DataContainerName.createChildPath(m_InputValues->CellAttributeMatrixName); | ||
|
||
std::vector<size_t> cDims = {1}; | ||
|
||
const auto& imageGeom = m_DataStructure.getDataRefAs<ImageGeom>(m_InputValues->DataContainerName); | ||
const size_t totalCells = imageGeom.getNumberOfCells(); | ||
|
||
// Prepare the Cell Attribute Matrix with the correct number of tuples based on the total Cells being read from the file. | ||
std::vector<size_t> tDims = {imageGeom.getNumXCells(), imageGeom.getNumYCells(), imageGeom.getNumZCells()}; | ||
|
||
std::vector<EbsdLib::CrcDataParser> fieldParsers = reader->createFieldParsers(m_InputValues->InputFile.string()); | ||
for(const auto& parser : fieldParsers) | ||
{ | ||
std::string fieldName = parser.FieldDefinition.FieldName; | ||
DataPath dataArrayPath = cellAttributeMatrixPath.createChildPath(fieldName); | ||
// if(m_DataStructure.getData(dataArrayPath) != nullptr) | ||
// { | ||
// std::cout << fieldName << " Exists in Data Structure\n"; | ||
// } | ||
|
||
if(parser.FieldDefinition.numericType == EbsdLib::NumericTypes::Type::Int32) | ||
{ | ||
copyRawData<int32_t>(m_InputValues, totalCells, m_DataStructure, *reader, fieldName, dataArrayPath); | ||
} | ||
else if(parser.FieldDefinition.numericType == EbsdLib::NumericTypes::Type::Float) | ||
{ | ||
copyRawData<float32>(m_InputValues, totalCells, m_DataStructure, *reader, fieldName, dataArrayPath); | ||
} | ||
else if(parser.FieldDefinition.numericType == EbsdLib::NumericTypes::Type::UInt8) | ||
{ | ||
copyRawData<uint8_t>(m_InputValues, totalCells, m_DataStructure, *reader, fieldName, dataArrayPath); | ||
} | ||
} | ||
|
||
// Copy the data from the 'Phase' array into the 'Phases' array | ||
if(m_InputValues->CreateCompatibleArrays) | ||
{ | ||
auto& targetArray = m_DataStructure.getDataRefAs<Int32Array>(cellAttributeMatrixPath.createChildPath(EbsdLib::CtfFile::Phases)); | ||
auto* phasePtr = reinterpret_cast<uint8_t*>(reader->getPointerByName(EbsdLib::Ctf::Phase)); | ||
for(size_t i = 0; i < totalCells; i++) | ||
{ | ||
// if(phasePtr[i] < 1) | ||
// { | ||
// phasePtr[i] = 1; | ||
// } | ||
targetArray[i] = phasePtr[i]; | ||
} | ||
} | ||
|
||
// Condense the Euler Angles from 3 separate arrays into a single 1x3 array | ||
if(m_InputValues->CreateCompatibleArrays) | ||
{ | ||
const auto* fComp0 = reinterpret_cast<float*>(reader->getPointerByName(EbsdLib::Ctf::phi1)); | ||
const auto* fComp1 = reinterpret_cast<float*>(reader->getPointerByName(EbsdLib::Ctf::Phi)); | ||
const auto* fComp2 = reinterpret_cast<float*>(reader->getPointerByName(EbsdLib::Ctf::phi2)); | ||
cDims[0] = 3; | ||
|
||
auto& cellEulerAngles = m_DataStructure.getDataRefAs<Float32Array>(cellAttributeMatrixPath.createChildPath(EbsdLib::CtfFile::EulerAngles)); | ||
for(size_t i = 0; i < totalCells; i++) | ||
{ | ||
cellEulerAngles[3 * i] = fComp0[i]; | ||
cellEulerAngles[3 * i + 1] = fComp1[i]; | ||
cellEulerAngles[3 * i + 2] = fComp2[i]; | ||
} | ||
} | ||
} |
97 changes: 97 additions & 0 deletions
97
...ugins/OrientationAnalysis/src/OrientationAnalysis/Filters/Algorithms/ReadChannel5Data.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
#pragma once | ||
|
||
#include "OrientationAnalysis/OrientationAnalysis_export.hpp" | ||
|
||
#include "simplnx/DataStructure/DataArray.hpp" | ||
#include "simplnx/DataStructure/DataPath.hpp" | ||
#include "simplnx/DataStructure/DataStructure.hpp" | ||
#include "simplnx/DataStructure/IDataArray.hpp" | ||
#include "simplnx/Filter/IFilter.hpp" | ||
#include "simplnx/Parameters/FileSystemPathParameter.hpp" | ||
|
||
#include "EbsdLib/IO/HKL/CprReader.h" | ||
|
||
#include <filesystem> | ||
namespace fs = std::filesystem; | ||
|
||
namespace nx::core | ||
{ | ||
|
||
struct ORIENTATIONANALYSIS_EXPORT ReadChannel5DataInputValues | ||
{ | ||
FileSystemPathParameter::ValueType InputFile; | ||
DataPath DataContainerName; | ||
std::string CellAttributeMatrixName; | ||
std::string CellEnsembleAttributeMatrixName; | ||
bool EdaxHexagonalAlignment; | ||
bool CreateCompatibleArrays; | ||
}; | ||
|
||
struct ORIENTATIONANALYSIS_EXPORT Ang_Private_Data | ||
{ | ||
std::array<size_t, 3> dims = {0, 0, 0}; | ||
std::array<float, 3> resolution = {0.0F, 0.0F, 0.0F}; | ||
std::array<float, 3> origin = {0.0F, 0.0F, 0.0F}; | ||
std::vector<CtfPhase::Pointer> phases; | ||
int32_t units = 0; | ||
}; | ||
|
||
/** | ||
* @brief The ReadChannel5DataPrivate class is a private implementation of the ReadChannel5Data class | ||
*/ | ||
class ORIENTATIONANALYSIS_EXPORT ReadChannel5DataPrivate | ||
{ | ||
public: | ||
ReadChannel5DataPrivate() = default; | ||
~ReadChannel5DataPrivate() = default; | ||
|
||
ReadChannel5DataPrivate(const ReadChannel5DataPrivate&) = delete; // Copy Constructor Not Implemented | ||
ReadChannel5DataPrivate(ReadChannel5DataPrivate&&) = delete; // Move Constructor Not Implemented | ||
ReadChannel5DataPrivate& operator=(const ReadChannel5DataPrivate&) = delete; // Copy Assignment Not Implemented | ||
ReadChannel5DataPrivate& operator=(ReadChannel5DataPrivate&&) = delete; // Move Assignment Not Implemented | ||
|
||
Ang_Private_Data m_Data; | ||
|
||
std::string m_InputFile_Cache; | ||
fs::file_time_type m_TimeStamp_Cache; | ||
}; | ||
|
||
/** | ||
* @class ReadChannel5Data | ||
* @brief This filter will read a single .ang file into a new Image Geometry, allowing the immediate use of Filters on the data instead of having to generate the intermediate | ||
* .h5ebsd file. | ||
*/ | ||
class ORIENTATIONANALYSIS_EXPORT ReadChannel5Data | ||
{ | ||
public: | ||
ReadChannel5Data(DataStructure& dataStructure, const IFilter::MessageHandler& msgHandler, const std::atomic_bool& shouldCancel, ReadChannel5DataInputValues* inputValues); | ||
~ReadChannel5Data() noexcept; | ||
|
||
ReadChannel5Data(const ReadChannel5Data&) = delete; // Copy Constructor Not Implemented | ||
ReadChannel5Data(ReadChannel5Data&&) = delete; // Move Constructor Not Implemented | ||
ReadChannel5Data& operator=(const ReadChannel5Data&) = delete; // Copy Assignment Not Implemented | ||
ReadChannel5Data& operator=(ReadChannel5Data&&) = delete; // Move Assignment Not Implemented | ||
|
||
Result<> operator()(); | ||
|
||
private: | ||
DataStructure& m_DataStructure; | ||
const IFilter::MessageHandler& m_MessageHandler; | ||
const std::atomic_bool& m_ShouldCancel; | ||
const ReadChannel5DataInputValues* m_InputValues = nullptr; | ||
|
||
/** | ||
* @brief | ||
* @param reader | ||
* @return Error code. | ||
*/ | ||
std::pair<int32, std::string> loadMaterialInfo(CprReader* reader) const; | ||
|
||
/** | ||
* @brief | ||
* @param reader | ||
*/ | ||
void copyRawEbsdData(CprReader* reader) const; | ||
}; | ||
|
||
} // namespace nx::core |
Oops, something went wrong.