Skip to content

Commit ec56b7a

Browse files
authored
FILT: Compute Coordinates Image Geom (#1316)
1 parent 4e64f0d commit ec56b7a

8 files changed

+592
-0
lines changed

src/Plugins/SimplnxCore/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ set(FilterList
2525
ComputeBiasedFeaturesFilter
2626
ComputeBoundaryCellsFilter
2727
ComputeBoundaryElementFractionsFilter
28+
ComputeCoordinatesImageGeomFilter
2829
ComputeDifferencesMapFilter
2930
ComputeEuclideanDistMapFilter
3031
ComputeFeatureBoundsFilter
@@ -171,6 +172,7 @@ set(AlgorithmList
171172
ComputeArrayStatistics
172173
ComputeBiasedFeatures
173174
ComputeBoundaryCells
175+
ComputeCoordinatesImageGeom
174176
ComputeEuclideanDistMap
175177
ComputeFeatureBounds
176178
ComputeFeatureCentroids
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Compute Coordinates/Indices Array From Image Geometry
2+
3+
## Group (Subgroup)
4+
5+
Statistics
6+
7+
## Description
8+
9+
This **Filter** produces one or two arrays that stores implicit image information (indices and physical coordinates of each point) as explicit cell level data. The produced arrays are in XYZ component format and stored as X by Y by Z, starting from the origin. The intention behind this filter is primarily for output compatibility and readability.
10+
11+
The arrays follow the following cell parsing scheme: `0,0,0 -> 1,0,0 -> 2,0,0 -> ... n,0,0 -> 0,1,0 -> 1,1,0 -> 2,1,0 -> ... n,n,0 -> 0,0,1 -> 1,0,1 -> 2,0,1 -> ... n,n,n`.
12+
13+
The printed output will look something like this:
14+
15+
```console
16+
Image Indices_0,Image Indices_1,Image Indices_2,Image Physical Coordinates_0,Image Physical Coordinates_1,Image Physical Coordinates_2
17+
0,0,0,-47.125,0.125,-0.37500411
18+
1,0,0,-46.875,0.125,-0.37500411
19+
2,0,0,-46.625,0.125,-0.37500411
20+
3,0,0,-46.375,0.125,-0.37500411
21+
4,0,0,-46.125,0.125,-0.37500411
22+
5,0,0,-45.875,0.125,-0.37500411
23+
6,0,0,-45.625,0.125,-0.37500411
24+
7,0,0,-45.375,0.125,-0.37500411
25+
8,0,0,-45.125,0.125,-0.37500411
26+
```
27+
28+
% Auto generated parameter table will be inserted here
29+
30+
## Example Pipelines
31+
32+
## License & Copyright
33+
34+
Please see the description file distributed with this **Plugin**
35+
36+
## DREAM3D-NX Help
37+
38+
If you need help, need to file a bug report or want to request a new feature, please head over to the [DREAM3DNX-Issues](https://github.com/BlueQuartzSoftware/DREAM3DNX-Issues/discussions) GitHub site where the community of DREAM3D-NX users can help answer your questions.
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
#include "ComputeCoordinatesImageGeom.hpp"
2+
3+
#include "simplnx/DataStructure/DataArray.hpp"
4+
#include "simplnx/DataStructure/Geometry/ImageGeom.hpp"
5+
#include "simplnx/Utilities/ParallelDataAlgorithm.hpp"
6+
7+
using namespace nx::core;
8+
9+
namespace
10+
{
11+
class ComputeCoordsImpl
12+
{
13+
public:
14+
ComputeCoordsImpl(const ImageGeom& imageGeom, Float32AbstractDataStore& coords)
15+
: m_ImageGeom(imageGeom)
16+
, m_Coords(coords)
17+
{
18+
}
19+
~ComputeCoordsImpl() = default;
20+
21+
// -----------------------------------------------------------------------------
22+
void compute(usize start, usize end) const
23+
{
24+
usize xPoints = m_ImageGeom.getNumXCells();
25+
usize yPoints = m_ImageGeom.getNumYCells();
26+
FloatVec3 spacing = m_ImageGeom.getSpacing();
27+
FloatVec3 origin = m_ImageGeom.getOrigin();
28+
29+
usize zStride = 0, yStride = 0;
30+
for(usize i = start; i < end; i++)
31+
{
32+
zStride = i * xPoints * yPoints;
33+
for(usize j = 0; j < yPoints; j++)
34+
{
35+
yStride = j * xPoints;
36+
for(usize k = 0; k < xPoints; k++)
37+
{
38+
// We are inlining the calculations here to leverage the speed of primitives (no Point object or vector from the API)
39+
usize tup = zStride + yStride + k;
40+
m_Coords[(tup * 3) + 0] = k * spacing[0] + origin[0] + (0.5f * spacing[0]);
41+
m_Coords[(tup * 3) + 1] = j * spacing[1] + origin[1] + (0.5f * spacing[1]);
42+
m_Coords[(tup * 3) + 2] = i * spacing[2] + origin[2] + (0.5f * spacing[2]);
43+
}
44+
}
45+
}
46+
}
47+
48+
// -----------------------------------------------------------------------------
49+
void operator()(const Range& range) const
50+
{
51+
compute(range.min(), range.max());
52+
}
53+
54+
private:
55+
const ImageGeom& m_ImageGeom;
56+
Float32AbstractDataStore& m_Coords;
57+
};
58+
59+
class ComputeIndicesImpl
60+
{
61+
public:
62+
ComputeIndicesImpl(const ImageGeom& imageGeom, Int32AbstractDataStore& indices)
63+
: m_ImageGeom(imageGeom)
64+
, m_Indices(indices)
65+
{
66+
}
67+
~ComputeIndicesImpl() = default;
68+
69+
// -----------------------------------------------------------------------------
70+
void compute(usize start, usize end) const
71+
{
72+
usize xPoints = m_ImageGeom.getNumXCells();
73+
usize yPoints = m_ImageGeom.getNumYCells();
74+
75+
usize zStride = 0, yStride = 0;
76+
for(usize i = start; i < end; i++)
77+
{
78+
zStride = i * xPoints * yPoints;
79+
for(usize j = 0; j < yPoints; j++)
80+
{
81+
yStride = j * xPoints;
82+
for(usize k = 0; k < xPoints; k++)
83+
{
84+
// We are inlining the calculations here to leverage the speed of primitives (no Point object or vector from the API)
85+
usize tup = zStride + yStride + k;
86+
m_Indices[(tup * 3) + 0] = k;
87+
m_Indices[(tup * 3) + 1] = j;
88+
m_Indices[(tup * 3) + 2] = i;
89+
}
90+
}
91+
}
92+
}
93+
94+
// -----------------------------------------------------------------------------
95+
void operator()(const Range& range) const
96+
{
97+
compute(range.min(), range.max());
98+
}
99+
100+
private:
101+
const ImageGeom& m_ImageGeom;
102+
Int32AbstractDataStore& m_Indices;
103+
};
104+
} // namespace
105+
106+
// -----------------------------------------------------------------------------
107+
ComputeCoordinatesImageGeom::ComputeCoordinatesImageGeom(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel,
108+
ComputeCoordinatesImageGeomInputValues* inputValues)
109+
: m_DataStructure(dataStructure)
110+
, m_InputValues(inputValues)
111+
, m_ShouldCancel(shouldCancel)
112+
, m_MessageHandler(mesgHandler)
113+
{
114+
}
115+
116+
// -----------------------------------------------------------------------------
117+
ComputeCoordinatesImageGeom::~ComputeCoordinatesImageGeom() noexcept = default;
118+
119+
// -----------------------------------------------------------------------------
120+
Result<> ComputeCoordinatesImageGeom::operator()()
121+
{
122+
auto& imageGeom = m_DataStructure.getDataRefAs<ImageGeom>(m_InputValues->ImageGeomPath);
123+
124+
usize zPoints = imageGeom.getNumZCells();
125+
126+
ParallelDataAlgorithm dataAlg;
127+
dataAlg.setRange(0, zPoints);
128+
129+
if(m_InputValues->CoordinateOption != to_underlying(ComputeCoordinatesImageGeom::OutputType::Index))
130+
{
131+
auto& coords = m_DataStructure.getDataRefAs<Float32Array>(m_InputValues->CoordArrayPath).getDataStoreRef();
132+
dataAlg.execute(::ComputeCoordsImpl(imageGeom, coords));
133+
}
134+
if(m_InputValues->CoordinateOption != to_underlying(ComputeCoordinatesImageGeom::OutputType::Physical))
135+
{
136+
auto& indices = m_DataStructure.getDataRefAs<Int32Array>(m_InputValues->IndexArrayPath).getDataStoreRef();
137+
dataAlg.execute(::ComputeIndicesImpl(imageGeom, indices));
138+
}
139+
140+
return {};
141+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#pragma once
2+
3+
#include "SimplnxCore/SimplnxCore_export.hpp"
4+
5+
#include "simplnx/DataStructure/DataPath.hpp"
6+
#include "simplnx/DataStructure/DataStructure.hpp"
7+
#include "simplnx/Filter/IFilter.hpp"
8+
#include "simplnx/Parameters/ChoicesParameter.hpp"
9+
10+
namespace nx::core
11+
{
12+
struct SIMPLNXCORE_EXPORT ComputeCoordinatesImageGeomInputValues
13+
{
14+
ChoicesParameter::ValueType CoordinateOption;
15+
DataPath ImageGeomPath;
16+
DataPath CoordArrayPath;
17+
DataPath IndexArrayPath;
18+
};
19+
20+
/**
21+
* @class
22+
*/
23+
class SIMPLNXCORE_EXPORT ComputeCoordinatesImageGeom
24+
{
25+
public:
26+
ComputeCoordinatesImageGeom(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ComputeCoordinatesImageGeomInputValues* inputValues);
27+
~ComputeCoordinatesImageGeom() noexcept;
28+
29+
ComputeCoordinatesImageGeom(const ComputeCoordinatesImageGeom&) = delete;
30+
ComputeCoordinatesImageGeom(ComputeCoordinatesImageGeom&&) noexcept = delete;
31+
ComputeCoordinatesImageGeom& operator=(const ComputeCoordinatesImageGeom&) = delete;
32+
ComputeCoordinatesImageGeom& operator=(ComputeCoordinatesImageGeom&&) noexcept = delete;
33+
34+
enum OutputType : uint8
35+
{
36+
Physical = 0,
37+
Index = 1,
38+
Both = 2
39+
};
40+
41+
Result<> operator()();
42+
43+
private:
44+
DataStructure& m_DataStructure;
45+
const ComputeCoordinatesImageGeomInputValues* m_InputValues = nullptr;
46+
const std::atomic_bool& m_ShouldCancel;
47+
const IFilter::MessageHandler& m_MessageHandler;
48+
};
49+
50+
} // namespace nx::core
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
#include "ComputeCoordinatesImageGeomFilter.hpp"
2+
3+
#include "SimplnxCore/Filters/Algorithms/ComputeCoordinatesImageGeom.hpp"
4+
5+
#include "simplnx/Common/TypeTraits.hpp"
6+
#include "simplnx/DataStructure/DataPath.hpp"
7+
#include "simplnx/DataStructure/Geometry/ImageGeom.hpp"
8+
#include "simplnx/Filter/Actions/CreateArrayAction.hpp"
9+
#include "simplnx/Parameters/ArrayCreationParameter.hpp"
10+
#include "simplnx/Parameters/ChoicesParameter.hpp"
11+
#include "simplnx/Parameters/GeometrySelectionParameter.hpp"
12+
13+
using namespace nx::core;
14+
15+
namespace nx::core
16+
{
17+
//------------------------------------------------------------------------------
18+
std::string ComputeCoordinatesImageGeomFilter::name() const
19+
{
20+
return FilterTraits<ComputeCoordinatesImageGeomFilter>::name.str();
21+
}
22+
23+
//------------------------------------------------------------------------------
24+
std::string ComputeCoordinatesImageGeomFilter::className() const
25+
{
26+
return FilterTraits<ComputeCoordinatesImageGeomFilter>::className;
27+
}
28+
29+
//------------------------------------------------------------------------------
30+
Uuid ComputeCoordinatesImageGeomFilter::uuid() const
31+
{
32+
return FilterTraits<ComputeCoordinatesImageGeomFilter>::uuid;
33+
}
34+
35+
//------------------------------------------------------------------------------
36+
std::string ComputeCoordinatesImageGeomFilter::humanName() const
37+
{
38+
return "Compute Coordinates/Indices Array From Image Geom";
39+
}
40+
41+
//------------------------------------------------------------------------------
42+
std::vector<std::string> ComputeCoordinatesImageGeomFilter::defaultTags() const
43+
{
44+
return {className(), "stats", "statistics"};
45+
}
46+
47+
//------------------------------------------------------------------------------
48+
Parameters ComputeCoordinatesImageGeomFilter::parameters() const
49+
{
50+
Parameters params;
51+
52+
// Create the parameter descriptors that are needed for this filter
53+
params.insertSeparator(Parameters::Separator{"Input Parameter(s)"});
54+
params.insertLinkableParameter(std::make_unique<ChoicesParameter>(k_OutputType_Key, "Output Array(s) Type", "The selection here effects which arrays will be produced by the filter",
55+
to_underlying(ComputeCoordinatesImageGeom::OutputType::Physical),
56+
ChoicesParameter::Choices{"Physical Coordinates", "Indices", "Both"})); // sequence dependent DO NOT REORDER
57+
58+
params.insertSeparator(Parameters::Separator{"Input Data Objects"});
59+
params.insert(std::make_unique<GeometrySelectionParameter>(k_SelectedImageGeomPath_Key, "Selected Image Geometry",
60+
"The DataPath to the Image Geometry that produced coordinates or indices will map to", DataPath{},
61+
GeometrySelectionParameter::AllowedTypes{IGeometry::Type::Image}));
62+
63+
params.insertSeparator(Parameters::Separator{"Output Data Array(s)"});
64+
params.insert(std::make_unique<ArrayCreationParameter>(k_CoordsArrayPath_Key, "Created Physical Coordinate Array Path",
65+
"name and path of a new float32 DataArray containing the physical XYZ coordinate of the selected Image Geometry in global space",
66+
DataPath({"Image Physical Coordinates"})));
67+
params.insert(std::make_unique<ArrayCreationParameter>(k_IndicesArrayPath_Key, "Created Indices Array Path",
68+
"name and path of a new int32 DataArray containing the XYZ indices of the selected Image Geometry", DataPath({"Image Indices"})));
69+
70+
// Associate the Linkable Parameter(s) to the children parameters that they control
71+
params.linkParameters(k_OutputType_Key, k_CoordsArrayPath_Key, static_cast<ChoicesParameter::ValueType>(to_underlying(ComputeCoordinatesImageGeom::OutputType::Physical)));
72+
73+
params.linkParameters(k_OutputType_Key, k_IndicesArrayPath_Key, static_cast<ChoicesParameter::ValueType>(to_underlying(ComputeCoordinatesImageGeom::OutputType::Index)));
74+
75+
params.linkParameters(k_OutputType_Key, k_CoordsArrayPath_Key, static_cast<ChoicesParameter::ValueType>(to_underlying(ComputeCoordinatesImageGeom::OutputType::Both)));
76+
params.linkParameters(k_OutputType_Key, k_IndicesArrayPath_Key, static_cast<ChoicesParameter::ValueType>(to_underlying(ComputeCoordinatesImageGeom::OutputType::Both)));
77+
78+
return params;
79+
}
80+
81+
//------------------------------------------------------------------------------
82+
IFilter::VersionType ComputeCoordinatesImageGeomFilter::parametersVersion() const
83+
{
84+
return 1;
85+
}
86+
87+
//------------------------------------------------------------------------------
88+
IFilter::UniquePointer ComputeCoordinatesImageGeomFilter::clone() const
89+
{
90+
return std::make_unique<ComputeCoordinatesImageGeomFilter>();
91+
}
92+
93+
//------------------------------------------------------------------------------
94+
IFilter::PreflightResult ComputeCoordinatesImageGeomFilter::preflightImpl(const DataStructure& dataStructure, const Arguments& filterArgs, const MessageHandler& messageHandler,
95+
const std::atomic_bool& shouldCancel, const ExecutionContext& executionContext) const
96+
{
97+
auto pOutputTypeValue = filterArgs.value<ChoicesParameter::ValueType>(k_OutputType_Key);
98+
auto pSelectedImageGeomValue = filterArgs.value<GeometrySelectionParameter::ValueType>(k_SelectedImageGeomPath_Key);
99+
auto pCoordsArrayPathValue = filterArgs.value<ArrayCreationParameter::ValueType>(k_CoordsArrayPath_Key);
100+
auto pIndicesArrayPathValue = filterArgs.value<ArrayCreationParameter::ValueType>(k_IndicesArrayPath_Key);
101+
102+
nx::core::Result<OutputActions> resultOutputActions;
103+
104+
usize numberOfCells = dataStructure.getDataRefAs<ImageGeom>(pSelectedImageGeomValue).getNumberOfCells();
105+
106+
if(pOutputTypeValue != to_underlying(ComputeCoordinatesImageGeom::OutputType::Index))
107+
{
108+
auto createAction = std::make_unique<CreateArrayAction>(DataType::float32, std::vector<usize>{numberOfCells}, std::vector<usize>{3}, pCoordsArrayPathValue);
109+
resultOutputActions.value().appendAction(std::move(createAction));
110+
}
111+
112+
if(pOutputTypeValue != to_underlying(ComputeCoordinatesImageGeom::OutputType::Physical))
113+
{
114+
auto createAction = std::make_unique<CreateArrayAction>(DataType::int32, std::vector<usize>{numberOfCells}, std::vector<usize>{3}, pIndicesArrayPathValue);
115+
resultOutputActions.value().appendAction(std::move(createAction));
116+
}
117+
118+
// Return both the resultOutputActions and the preflightUpdatedValues via std::move()
119+
return {std::move(resultOutputActions)};
120+
}
121+
122+
//------------------------------------------------------------------------------
123+
Result<> ComputeCoordinatesImageGeomFilter::executeImpl(DataStructure& dataStructure, const Arguments& filterArgs, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler,
124+
const std::atomic_bool& shouldCancel, const ExecutionContext& executionContext) const
125+
{
126+
ComputeCoordinatesImageGeomInputValues inputValues;
127+
128+
inputValues.CoordinateOption = filterArgs.value<ChoicesParameter::ValueType>(k_OutputType_Key);
129+
inputValues.ImageGeomPath = filterArgs.value<GeometrySelectionParameter::ValueType>(k_SelectedImageGeomPath_Key);
130+
inputValues.CoordArrayPath = filterArgs.value<ArrayCreationParameter::ValueType>(k_CoordsArrayPath_Key);
131+
inputValues.IndexArrayPath = filterArgs.value<ArrayCreationParameter::ValueType>(k_IndicesArrayPath_Key);
132+
133+
return ComputeCoordinatesImageGeom(dataStructure, messageHandler, shouldCancel, &inputValues)();
134+
}
135+
} // namespace nx::core

0 commit comments

Comments
 (0)