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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,18 @@ Result<> CAxisSegmentFeatures::operator()()
for(usize cellIdx = 0; cellIdx < numCells; ++cellIdx)
{
int32 currentPhaseIdx = m_CellPhases->getValue(cellIdx);
// Only consider valid ebsd phase values
if(currentPhaseIdx < 1)
{
continue;
}
// Only consider valid mask values
if(m_InputValues->UseMask && !m_GoodVoxelsArray->isTrue(cellIdx))
{
continue;
}
const auto crystalStructureType = crystalStructures[currentPhaseIdx];

if(crystalStructureType != ebsdlib::CrystalStructure::Hexagonal_High && crystalStructureType != ebsdlib::CrystalStructure::Hexagonal_Low)
{
return MakeErrorResult(-8363, fmt::format("Input data is using {} type crystal structures but segmenting features via c-axis mis orientation requires all phases to be either Hexagonal-Low 6/m "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,11 @@ Result<Arguments> CAxisSegmentFeaturesFilter::FromSIMPLJson(const nlohmann::json
results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::DataContainerSelectionFilterParameterConverter>(args, json, SIMPL::k_QuatsArrayPathKey, k_SelectedImageGeometryPath_Key));
results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::FloatFilterParameterConverter<float32>>(args, json, SIMPL::k_MisorientationToleranceKey, k_MisorientationTolerance_Key));
results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::LinkedBooleanFilterParameterConverter>(args, json, SIMPL::k_UseGoodVoxelsKey, k_UseMask_Key));
results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::BooleanFilterParameterConverter>(args, json, SIMPL::k_RandomizeFeatureIdsKey, k_RandomizeFeatureIds_Key));
// RandomizeFeatureIds was added to the legacy filter after 6.5.49; older pipelines omit the key.
if(json.contains(SIMPL::k_RandomizeFeatureIdsKey))
{
results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::BooleanFilterParameterConverter>(args, json, SIMPL::k_RandomizeFeatureIdsKey, k_RandomizeFeatureIds_Key));
}
results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::DataArraySelectionFilterParameterConverter>(args, json, SIMPL::k_QuatsArrayPathKey, k_QuatsArrayPath_Key));
results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::DataArraySelectionFilterParameterConverter>(args, json, SIMPL::k_CellPhasesArrayPathKey, k_CellPhasesArrayPath_Key));
results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::DataArraySelectionFilterParameterConverter>(args, json, SIMPL::k_GoodVoxelsArrayPathKey, k_MaskArrayPath_Key));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,13 +145,29 @@ Result<Arguments> ComputeAvgCAxesFilter::FromSIMPLJson(const nlohmann::json& jso

std::vector<Result<>> results;

results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::AttributeMatrixSelectionFilterParameterConverter>(args, json, SIMPL::k_QuatsArrayPathKey, k_CellFeatureAttributeMatrixPath_Key));
results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::DataArraySelectionFilterParameterConverter>(args, json, SIMPL::k_QuatsArrayPathKey, k_QuatsArrayPath_Key));
results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::AttributeMatrixSelectionFilterParameterConverter>(args, json, SIMPL::k_FeatureIdsArrayPathKey, k_CellPhasesArrayPath_Key));
results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::DataArraySelectionFilterParameterConverter>(args, json, SIMPL::k_FeatureIdsArrayPathKey, k_FeatureIdsArrayPath_Key));
results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::AttributeMatrixSelectionFilterParameterConverter>(args, json, SIMPL::k_AvgCAxesArrayPathKey, k_CrystalStructuresArrayPath_Key));
// The feature attribute matrix comes from the created AvgCAxes array (e.g. "CellFeatureData"),
// not from the cell-level Quats/FeatureIds arrays (e.g. "CellData").
results.push_back(
SIMPLConversion::ConvertParameter<SIMPLConversion::AttributeMatrixSelectionFilterParameterConverter>(args, json, SIMPL::k_AvgCAxesArrayPathKey, k_CellFeatureAttributeMatrixPath_Key));
results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::DataArrayCreationToDataObjectNameFilterParameterConverter>(args, json, SIMPL::k_AvgCAxesArrayPathKey, k_AvgCAxesArrayName_Key));

// The legacy FindAvgCAxes filter had no Cell Phases or Crystal Structures inputs, so there is nothing
// to convert. Derive the conventional locations from the legacy FeatureIds path so common pipelines
// convert to a runnable filter: "Phases" sits next to the Feature Ids array and "CrystalStructures"
// lives in the DataContainer's "CellEnsembleData" attribute matrix. Non-standard names need editing.
if(json.contains(SIMPL::k_FeatureIdsArrayPathKey))
{
Result<std::string> dcNameResult = SIMPLConversion::ReadDataContainerName(json[SIMPL::k_FeatureIdsArrayPathKey.view()], "FindAvgCAxes");
Result<std::string> amNameResult = SIMPLConversion::ReadAttributeMatrixName(json[SIMPL::k_FeatureIdsArrayPathKey.view()], "FindAvgCAxes");
if(dcNameResult.valid() && amNameResult.valid())
{
args.insertOrAssign(k_CellPhasesArrayPath_Key, std::make_any<DataPath>(DataPath({dcNameResult.value(), amNameResult.value(), "Phases"})));
args.insertOrAssign(k_CrystalStructuresArrayPath_Key, std::make_any<DataPath>(DataPath({dcNameResult.value(), "CellEnsembleData", "CrystalStructures"})));
}
}

Result<> conversionResult = MergeResults(std::move(results));

return ConvertResultTo<Arguments>(std::move(conversionResult), std::move(args));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,8 +277,10 @@ Result<Arguments> ComputeAvgOrientationsFilter::FromSIMPLJson(const nlohmann::js
std::vector<Result<>> results;

results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::DataArraySelectionFilterParameterConverter>(args, json, SIMPL::k_FeatureIdsArrayPathKey, k_CellFeatureIdsArrayPath_Key));
// The feature attribute matrix must come from the created feature arrays (e.g. AvgQuatsArrayPath -> "CellFeatureData"),
// not from FeatureIdsArrayPath, which lives in the cell attribute matrix (e.g. "CellData").
results.push_back(
SIMPLConversion::ConvertParameter<SIMPLConversion::AttributeMatrixSelectionFilterParameterConverter>(args, json, SIMPL::k_FeatureIdsArrayPathKey, k_CellFeatureAttributeMatrixPath_Key));
SIMPLConversion::ConvertParameter<SIMPLConversion::AttributeMatrixSelectionFilterParameterConverter>(args, json, SIMPL::k_AvgQuatsArrayPathKey, k_CellFeatureAttributeMatrixPath_Key));
results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::DataArraySelectionFilterParameterConverter>(args, json, SIMPL::k_CellPhasesArrayPathKey, k_CellPhasesArrayPath_Key));
results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::DataArraySelectionFilterParameterConverter>(args, json, SIMPL::k_QuatsArrayPathKey, k_CellQuatsArrayPath_Key));
results.push_back(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,9 @@ Result<Arguments> ComputeFeatureReferenceMisorientationsFilter::FromSIMPLJson(co

results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::LinkedChoicesFilterParameterConverter>(args, json, SIMPL::k_ReferenceOrientationKey, k_ReferenceOrientation_Key));
results.push_back(
SIMPLConversion::ConvertParameter<SIMPLConversion::AttributeMatrixSelectionFilterParameterConverter>(args, json, SIMPL::k_FeatureIdsArrayPathKey, k_CellFeatureAttributeMatrixPath_Key));
// The feature attribute matrix comes from the feature-level AvgQuats array (e.g. "CellFeatureData"),
// not from FeatureIdsArrayPath, which lives in the cell attribute matrix (e.g. "CellData").
SIMPLConversion::ConvertParameter<SIMPLConversion::AttributeMatrixSelectionFilterParameterConverter>(args, json, SIMPL::k_AvgQuatsArrayPathKey, k_CellFeatureAttributeMatrixPath_Key));
results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::DataArraySelectionFilterParameterConverter>(args, json, SIMPL::k_FeatureIdsArrayPathKey, k_CellFeatureIdsArrayPath_Key));
results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::DataArraySelectionFilterParameterConverter>(args, json, SIMPL::k_CellPhasesArrayPathKey, k_CellPhasesArrayPath_Key));
results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::DataArraySelectionFilterParameterConverter>(args, json, SIMPL::k_QuatsArrayPathKey, k_QuatsArrayPath_Key));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,11 @@ Result<Arguments> NeighborOrientationCorrelationFilter::FromSIMPLJson(const nloh
results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::DataArraySelectionFilterParameterConverter>(args, json, SIMPL::k_QuatsArrayPathKey, k_QuatsArrayPath_Key));
results.push_back(
SIMPLConversion::ConvertParameter<SIMPLConversion::DataArraySelectionFilterParameterConverter>(args, json, SIMPL::k_CrystalStructuresArrayPathKey, k_CrystalStructuresArrayPath_Key));
results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::MultiDataArraySelectionFilterParameterConverter>(args, json, SIMPL::k_IgnoredDataArrayPathsKey, k_IgnoredDataArrayPaths_Key));
// IgnoredDataArrayPaths was added to the legacy filter after 6.5.49; older pipelines omit the key.
if(json.contains(SIMPL::k_IgnoredDataArrayPathsKey))
{
results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::MultiDataArraySelectionFilterParameterConverter>(args, json, SIMPL::k_IgnoredDataArrayPathsKey, k_IgnoredDataArrayPaths_Key));
}

Result<> conversionResult = MergeResults(std::move(results));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,10 @@ Result<Arguments> WritePoleFigureFilter::FromSIMPLJson(const nlohmann::json& jso
results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::DataArraySelectionFilterParameterConverter>(args, json, SIMPL::k_CellEulerAnglesArrayPathKey, k_CellEulerAnglesArrayPath_Key));
results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::DataArraySelectionFilterParameterConverter>(args, json, SIMPL::k_CellPhasesArrayPathKey, k_CellPhasesArrayPath_Key));
results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::DataArraySelectionFilterParameterConverter>(args, json, SIMPL::k_GoodVoxelsArrayPathKey, k_MaskArrayPath_Key));
results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::DataContainerSelectionFilterParameterConverter>(args, json, SIMPL::k_CrystalStructuresArrayPathKey, k_ImageGeometryPath_Key));
// Do NOT map the legacy CrystalStructuresArrayPath's DataContainer onto k_ImageGeometryPath_Key:
// that parameter creates a new ImageGeom, and the legacy filter had no output geometry. Reusing the
// input container name (e.g. "ImageDataContainer") collides with the existing geometry in preflight.
// The default from getDefaultArguments() ("PoleFigure") is the correct value.
results.push_back(
SIMPLConversion::ConvertParameter<SIMPLConversion::DataArraySelectionFilterParameterConverter>(args, json, SIMPL::k_CrystalStructuresArrayPathKey, k_CrystalStructuresArrayPath_Key));
results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::DataArraySelectionFilterParameterConverter>(args, json, SIMPL::k_MaterialNameArrayPathKey, k_MaterialNameArrayPath_Key));
Expand Down
8 changes: 6 additions & 2 deletions src/Plugins/OrientationAnalysis/test/ComputeAvgCAxesTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,12 +272,16 @@ TEST_CASE("OrientationAnalysis::ComputeAvgCAxesFilter: SIMPL Backwards Compatibi
CHECK(pipelineFilter->getComments().empty());

const Arguments args = pipelineFilter->getArguments();
// The feature attribute matrix is derived from the legacy AvgCAxesArrayPath (the created array),
// and the AvgCAxes array name comes from that same path.
CHECK(args.value<DataPath>(ComputeAvgCAxesFilter::k_CellFeatureAttributeMatrixPath_Key) == DataPath({"DataContainer", "CellData"}));
CHECK(args.value<DataPath>(ComputeAvgCAxesFilter::k_QuatsArrayPath_Key) == DataPath({"DataContainer", "CellData", "TestArray"}));
CHECK(args.value<DataPath>(ComputeAvgCAxesFilter::k_CellPhasesArrayPath_Key) == DataPath({"DataContainer", "CellData"}));
CHECK(args.value<DataPath>(ComputeAvgCAxesFilter::k_FeatureIdsArrayPath_Key) == DataPath({"DataContainer", "CellData", "TestArray"}));
CHECK(args.value<DataPath>(ComputeAvgCAxesFilter::k_CrystalStructuresArrayPath_Key) == DataPath({"DataContainer", "CellData"}));
CHECK(args.value<std::string>(ComputeAvgCAxesFilter::k_AvgCAxesArrayName_Key) == "TestArray");
// The legacy filter had no Cell Phases or Crystal Structures inputs; the conversion derives the
// conventional locations from the legacy FeatureIds path.
CHECK(args.value<DataPath>(ComputeAvgCAxesFilter::k_CellPhasesArrayPath_Key) == DataPath({"DataContainer", "CellData", "Phases"}));
CHECK(args.value<DataPath>(ComputeAvgCAxesFilter::k_CrystalStructuresArrayPath_Key) == DataPath({"DataContainer", "CellEnsembleData", "CrystalStructures"}));
}
}
}
4 changes: 3 additions & 1 deletion src/Plugins/OrientationAnalysis/test/WritePoleFigureTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,9 @@ TEST_CASE("OrientationAnalysis::WritePoleFigureFilter: SIMPL Backwards Compatibi
CHECK(args.value<DataPath>(WritePoleFigureFilter::k_CellEulerAnglesArrayPath_Key) == DataPath({"DataContainer", "CellData", "TestArray"}));
CHECK(args.value<DataPath>(WritePoleFigureFilter::k_CellPhasesArrayPath_Key) == DataPath({"DataContainer", "CellData", "TestArray"}));
CHECK(args.value<DataPath>(WritePoleFigureFilter::k_MaskArrayPath_Key) == DataPath({"DataContainer", "CellData", "TestArray"}));
CHECK(args.value<DataPath>(WritePoleFigureFilter::k_ImageGeometryPath_Key) == DataPath({"DataContainer"}));
// The legacy filter had no output geometry, so the created Image Geometry path is intentionally
// left at its default ("PoleFigure") instead of reusing the input DataContainer name.
CHECK(args.value<DataPath>(WritePoleFigureFilter::k_ImageGeometryPath_Key) == DataPath({"PoleFigure"}));
CHECK(args.value<DataPath>(WritePoleFigureFilter::k_CrystalStructuresArrayPath_Key) == DataPath({"DataContainer", "CellData", "TestArray"}));
CHECK(args.value<DataPath>(WritePoleFigureFilter::k_MaterialNameArrayPath_Key) == DataPath({"DataContainer", "CellData", "TestArray"}));
}
Expand Down
4 changes: 2 additions & 2 deletions src/Plugins/SimplnxCore/docs/WriteImageFilter.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ When *Create Color Table* is **disabled**, the filter writes the **Data Array**'

For example, writing a float32 array directly to a `.png` file fails preflight, since PNG (via stb) only supports uint8 pixel data. The same float32 array can be written directly to a `.tif` file, or, if a PNG is required, *Create Color Table* can be enabled to normalize the array into a uint8 RGB image before writing (see below). Since color-table output is always uint8 RGB, it is compatible with every supported output format.

If the input array represents a 3D volume, the filter will output a series of slices along one of the orthogonal axes. The options are to produce XY slices along the Z axis, XZ slices along the Y axis, or YZ slices along the X axis. The output files will be numbered sequentially starting at the *Index Offset* and ending at *Index Offset + (dim - 1)* for the chosen axis. For example, if the Z axis has 117 dimensions and *Index Offset* is 0, 117 XY image files will be produced and numbered 000 through 116.
If the input array represents a 3D volume, the filter will output a series of slices along one of the orthogonal axes. The options are to produce XY slices along the Z axis, XZ slices along the Y axis, or YZ slices along the X axis. The output files will be numbered sequentially starting at the *Index Offset* and ending at *Index Offset + (dim - 1)* for the chosen axis. For example, if the Z axis has 117 dimensions and *Index Offset* is 0, 117 XY image files will be produced and numbered 000 through 116. If the volume produces only a single slice, no index is appended and the file is written with exactly the user-specified name.

Writes are performed through an `AtomicFile`, so partially-written slices from an aborted run will not corrupt existing output files.

Expand All @@ -40,7 +40,7 @@ The *Plane* parameter controls which orthogonal plane is used when writing a 3D

### Index Formatting

The *Total Number of Index Digits* and *Fill Character* parameters control the numeric suffix applied to each slice filename. For example, 3 total digits with a fill character of `0` produces `slice_000.tif`, `slice_001.tif`, etc.
The *Total Number of Index Digits* and *Fill Character* parameters control the numeric suffix applied to each slice filename. For example, 3 total digits with a fill character of `0` produces `slice_000.tif`, `slice_001.tif`, etc. These parameters have no effect when only a single slice is written, since single-slice output does not receive an index suffix.

### Flip Output Image (Optional)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -361,8 +361,14 @@ Result<> WriteImage::operator()()
// Shared per-slice writer: names the file, writes via the ImageIO layer, commits atomically.
auto writeSlice = [&](std::vector<uint8>& sliceBuffer, usize slice) -> Result<> {
m_MessageHandler(IFilter::Message::Type::Info, fmt::format("Writing slice {}/{}", slice + 1, sliceCount));
std::string indexStr = CreateIndexString(slice + m_InputValues.indexOffset, static_cast<usize>(m_InputValues.totalIndexDigits), m_InputValues.leadingDigitCharacter);
fs::path slicePath = parent / fmt::format("{}_{}{}", stem.string(), indexStr, ext.string());
// A single-slice volume writes exactly the user-specified file name; the index suffix is only
// appended when multiple slices are produced.
fs::path slicePath = parent / fmt::format("{}{}", stem.string(), ext.string());
if(sliceCount > 1)
{
std::string indexStr = CreateIndexString(slice + m_InputValues.indexOffset, static_cast<usize>(m_InputValues.totalIndexDigits), m_InputValues.leadingDigitCharacter);
slicePath = parent / fmt::format("{}_{}{}", stem.string(), indexStr, ext.string());
}

auto atomicFileResult = AtomicFile::Create(slicePath);
if(atomicFileResult.invalid())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,9 @@ Result<Arguments> ComputeSurfaceFeaturesFilter::FromSIMPLJson(const nlohmann::js

results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::DataContainerSelectionFilterParameterConverter>(args, json, SIMPL::k_FeatureIdsArrayPathKey, k_FeatureGeometryPath_Key));
results.push_back(
SIMPLConversion::ConvertParameter<SIMPLConversion::AttributeMatrixSelectionFilterParameterConverter>(args, json, SIMPL::k_FeatureIdsArrayPathKey, k_CellFeatureAttributeMatrixPath_Key));
// The feature attribute matrix comes from the created SurfaceFeatures array (e.g. "CellFeatureData"),
// not from FeatureIdsArrayPath, which lives in the cell attribute matrix (e.g. "CellData").
SIMPLConversion::ConvertParameter<SIMPLConversion::AttributeMatrixSelectionFilterParameterConverter>(args, json, SIMPL::k_SurfaceFeaturesArrayPathKey, k_CellFeatureAttributeMatrixPath_Key));
results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::DataArraySelectionFilterParameterConverter>(args, json, SIMPL::k_FeatureIdsArrayPathKey, k_CellFeatureIdsArrayPath_Key));
results.push_back(
SIMPLConversion::ConvertParameter<SIMPLConversion::DataArrayCreationToDataObjectNameFilterParameterConverter>(args, json, SIMPL::k_SurfaceFeaturesArrayPathKey, k_SurfaceFeaturesArrayName_Key));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,10 @@ Result<Arguments> CopyFeatureArrayToElementArrayFilter::FromSIMPLJson(const nloh
results.push_back(
SIMPLConversion::ConvertParameter<SIMPLConversion::SingleToMultiDataPathSelectionFilterParameterConverter>(args, json, SIMPL::k_SelectedFeatureArrayPathKey, k_SelectedFeatureArrayPath_Key));
results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::DataArraySelectionFilterParameterConverter>(args, json, SIMPL::k_FeatureIdsArrayPathKey, k_CellFeatureIdsArrayPath_Key));
results.push_back(SIMPLConversion::ConvertParameter<SIMPLConversion::LinkedPathCreationFilterParameterConverter>(args, json, SIMPL::k_CreatedArrayNameKey, k_CreatedArraySuffix_Key));
// Do NOT map the legacy CreatedArrayName onto k_CreatedArraySuffix_Key: the legacy filter converted a
// single array whose output name was CreatedArrayName, but in SIMPLNX that string would be appended to
// the input array name as a suffix (e.g. "AvgEuler" + "AvgEulerAngles"). Leave the suffix blank so the
// copied array keeps the input array's name.

Result<> conversionResult = MergeResults(std::move(results));

Expand Down
Loading
Loading