Skip to content

Commit 4c27e0b

Browse files
authored
Merge pull request #6240 from hjmjohnson/ingest-PrincipalComponentsAnalysis
ENH: Ingest ITKPrincipalComponentsAnalysis into Modules/Numerics
2 parents 9ea9fe6 + 79b9244 commit 4c27e0b

53 files changed

Lines changed: 995 additions & 56 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
project(PrincipalComponentsAnalysis)
2+
3+
itk_module_impl()
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# PrincipalComponentsAnalysis
2+
3+
In-tree ITK module providing a principal component analysis filter for
4+
scalar, vector, and mesh-vertex data. The flagship class is
5+
`itk::VectorFieldPCA`, which computes the principal components of an
6+
ensemble of vector fields defined on a common mesh, useful for
7+
shape-modeling and multivariate statistics workflows.
8+
9+
## Origin
10+
11+
Ingested from the standalone remote module
12+
[**InsightSoftwareConsortium/ITKPrincipalComponentsAnalysis**](https://github.com/InsightSoftwareConsortium/ITKPrincipalComponentsAnalysis)
13+
on 2026-05-08, following the v4 ingestion guidelines defined in
14+
InsightSoftwareConsortium/ITK#6204. The upstream repository will be
15+
archived read-only after this PR merges; it remains reachable at the
16+
URL above for historical reference (notably the `doc/` and
17+
`examples/` directories, which were intentionally left in the
18+
upstream archive).
19+
20+
## References
21+
22+
- Bowers M., Younes L. *Principal Components Analysis of Scalar,
23+
Vector, and Mesh Vertex Data.* The Insight Journal. August, 2013.
24+
<https://doi.org/10.54294/loekqj>
Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
/*=========================================================================
2+
*
3+
* Copyright NumFOCUS
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* https://www.apache.org/licenses/LICENSE-2.0.txt
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
=========================================================================*/
18+
19+
#ifndef itkVectorFieldPCA_h
20+
#define itkVectorFieldPCA_h
21+
22+
#include "itkObject.h"
23+
#include "itkPointSet.h"
24+
#include "itkKernelFunctionBase.h"
25+
#include "vnl/vnl_vector.h"
26+
#include "vnl/vnl_matrix.h"
27+
28+
namespace itk
29+
{
30+
31+
/** \class VectorFieldPCA
32+
* \brief Produce the principle components of a vector valued function.
33+
*
34+
* This calculator produces a set of basis functions composed of the
35+
* principal components of a set of vector valued functions.
36+
*
37+
* Specify an itk::KernelFunction for Kernel PCA. The Kernel Function
38+
* can take as input an optional point set.
39+
*
40+
* This class is templated over the types of the vector valued functions,
41+
* the output point types, and optionally the point set type.
42+
*
43+
* \author Michael Bowers, Laurent Younes
44+
*
45+
* This code was contributed in the Insight Journal paper:
46+
*
47+
* "Principal Components Analysis of Scalar, Vector, and Mesh Vertex Data"
48+
* https://www.insight-journal.org/browse/publication/878
49+
*
50+
* \ingroup ITKStatistics
51+
* \ingroup PrincipalComponentsAnalysis
52+
*/
53+
54+
template <typename TRealValueType = double>
55+
class ITK_TEMPLATE_EXPORT GaussianDistanceKernel : public KernelFunctionBase<TRealValueType>
56+
{
57+
public:
58+
/** Standard class type alias. */
59+
using Self = GaussianDistanceKernel;
60+
using Superclass = KernelFunctionBase<TRealValueType>;
61+
using Pointer = SmartPointer<Self>;
62+
using ConstPointer = SmartPointer<const Self>;
63+
64+
/** Run-time type information (and related methods). */
65+
itkTypeMacro(GaussianDistanceKernel, KernelFunction);
66+
67+
/** Method for creation through the object factory. */
68+
itkNewMacro(Self);
69+
70+
/**
71+
* \brief Set and get the Kernel sigma.
72+
*/
73+
void
74+
SetKernelSigma(double s)
75+
{
76+
m_KernelSigma = s;
77+
m_OneOverMinusTwoSigmaSqr = -1.0 / (2.0 * s * s);
78+
}
79+
itkGetMacro(KernelSigma, double);
80+
81+
/**
82+
* \brief Evaluate the function. Input is the squared distance
83+
*/
84+
inline TRealValueType
85+
Evaluate(const TRealValueType & u) const override
86+
{
87+
return (std::exp(u * m_OneOverMinusTwoSigmaSqr));
88+
}
89+
90+
protected:
91+
GaussianDistanceKernel() = default;
92+
~GaussianDistanceKernel() override = default;
93+
void
94+
PrintSelf(std::ostream & os, Indent indent) const override
95+
{
96+
Superclass::PrintSelf(os, indent);
97+
}
98+
99+
private:
100+
double m_KernelSigma{ 1.0 };
101+
double m_OneOverMinusTwoSigmaSqr{ -0.5 };
102+
};
103+
104+
template <typename TVectorFieldElementType,
105+
typename TPCType,
106+
typename TPointSetPixelType = float,
107+
typename TPointSetCoordRepType = float,
108+
typename KernelFunctionType = KernelFunctionBase<TPointSetCoordRepType>,
109+
class TPointSetType =
110+
PointSet<TPointSetPixelType, 3, DefaultStaticMeshTraits<TPointSetPixelType, 3, 3, TPointSetCoordRepType>>>
111+
class ITK_TEMPLATE_EXPORT VectorFieldPCA : public Object
112+
{
113+
public:
114+
ITK_DISALLOW_COPY_AND_MOVE(VectorFieldPCA);
115+
116+
/** Standard class type alias. */
117+
using Self = VectorFieldPCA;
118+
using Superclass = Object;
119+
using Pointer = SmartPointer<Self>;
120+
using ConstPointer = SmartPointer<const Self>;
121+
122+
/** Method for creation through the object factory. */
123+
itkNewMacro(Self);
124+
125+
/** Run-time type information (and related methods). */
126+
itkTypeMacro(VectorFieldPCA, Object);
127+
128+
/** Type definitions for the PointSet. */
129+
using InputPointSetType = TPointSetType;
130+
131+
/** Definitions for points of the PointSet. */
132+
using InputPointType = typename InputPointSetType::PointType;
133+
134+
/** Definitions for the PointsContainer. */
135+
using PointsContainer = typename InputPointSetType::PointsContainer;
136+
using PointsContainerIterator = typename PointsContainer::Iterator;
137+
138+
/** Pointer types for the PointSet. */
139+
using InputPointSetPointer = typename InputPointSetType::Pointer;
140+
141+
/** Const Pointer type for the PointSet. */
142+
using InputPointSetConstPointer = typename InputPointSetType::ConstPointer;
143+
144+
/**
145+
* \brief Input PointSet dimension
146+
*/
147+
itkStaticConstMacro(InputMeshDimension, unsigned int, TPointSetType::PointDimension);
148+
149+
/** type for the vector fields. */
150+
using VectorFieldType = vnl_matrix<TVectorFieldElementType>;
151+
using VectorFieldSetType = VectorContainer<unsigned int, VectorFieldType>;
152+
153+
using VectorFieldSetTypePointer = typename VectorFieldSetType::Pointer;
154+
using VectorFieldSetTypeConstPointer = typename VectorFieldSetType::ConstPointer;
155+
156+
/** types for the output. */
157+
using MatrixType = vnl_matrix<TPCType>;
158+
using VectorType = vnl_vector<TPCType>;
159+
160+
using BasisSetType = VectorContainer<unsigned int, MatrixType>;
161+
using ResSetType = VectorContainer<unsigned int, VectorType>;
162+
163+
using BasisSetTypePointer = typename BasisSetType::Pointer;
164+
using KernelFunctionPointer = typename KernelFunctionType::Pointer;
165+
166+
/**
167+
* \brief Set and get the input point set.
168+
*/
169+
itkSetMacro(PointSet, InputPointSetPointer);
170+
itkGetMacro(PointSet, InputPointSetPointer);
171+
172+
/**
173+
* \brief Set and get the vector fields for the analysis.
174+
*/
175+
itkSetMacro(VectorFieldSet, VectorFieldSetTypePointer);
176+
itkGetMacro(VectorFieldSet, VectorFieldSetTypePointer);
177+
178+
/**
179+
* \brief Set and get the PCA count.
180+
*/
181+
itkSetMacro(ComponentCount, unsigned int);
182+
itkGetMacro(ComponentCount, unsigned int);
183+
184+
/**
185+
* \brief Set pointer to the Kernel object.
186+
*/
187+
itkSetMacro(KernelFunction, KernelFunctionPointer);
188+
189+
/**
190+
* \brief Compute the PCA decomposition of the input point set.
191+
If a Kernel and a Kernel Sigma are set ,
192+
the calculator will perform Kernel PCA.
193+
*/
194+
void
195+
Compute();
196+
197+
/**
198+
* \brief Return the results.
199+
*/
200+
itkGetConstReferenceMacro(AveVectorField, MatrixType);
201+
itkGetConstReferenceMacro(PCAEigenValues, VectorType);
202+
itkGetConstObjectMacro(BasisVectors, BasisSetType);
203+
204+
protected:
205+
VectorFieldPCA();
206+
~VectorFieldPCA() override = default;
207+
void
208+
PrintSelf(std::ostream & os, Indent indent) const override;
209+
210+
/** Kernel PCA. */
211+
void
212+
KernelPCA();
213+
214+
/** Compute Momentum SCP. */
215+
void
216+
ComputeMomentumSCP();
217+
218+
private:
219+
VectorType m_PCAEigenValues;
220+
221+
BasisSetTypePointer m_BasisVectors;
222+
VectorFieldSetTypePointer m_VectorFieldSet;
223+
InputPointSetPointer m_PointSet;
224+
KernelFunctionPointer m_KernelFunction;
225+
226+
// Problem dimensions
227+
unsigned int m_ComponentCount{ 0 };
228+
unsigned int m_SetSize{ 0 };
229+
unsigned int m_VectorDimCount{ 0 };
230+
unsigned int m_PointDim{ 0 };
231+
232+
MatrixType m_V0;
233+
MatrixType m_AveVectorField;
234+
MatrixType m_K;
235+
236+
bool m_PCACalculated{ false };
237+
};
238+
239+
} // end namespace itk
240+
241+
#ifndef ITK_MANUAL_INSTANTIATION
242+
# include "itkVectorFieldPCA.hxx"
243+
#endif
244+
245+
#endif

0 commit comments

Comments
 (0)