24#include "pybind11/pybind11.h"
25#include "pybind11/eigen.h"
26#include "pybind11/stl.h"
30#include "ndarray/pybind11.h"
31#include "ndarray/eigen.h"
37using namespace pybind11::literals;
44using PyMixtureComponent = py::class_<MixtureComponent>;
45using PyMixtureUpdateRestriction =
46 py::class_<MixtureUpdateRestriction, std::shared_ptr<MixtureUpdateRestriction>>;
47using PyMixture = py::class_<Mixture, std::shared_ptr<Mixture>>;
49static PyMixtureComponent declareMixtureComponent(
py::module &mod) {
50 PyMixtureComponent cls(mod,
"MixtureComponent");
61 cls.def(py::init<int>(),
"dim"_a);
62 cls.def(py::init<Scalar, Vector const &, Matrix const &>(),
"weight"_a,
"mu"_a,
"sigma"_a);
68static PyMixtureUpdateRestriction declareMixtureUpdateRestriction(
py::module &mod) {
69 PyMixtureUpdateRestriction cls(mod,
"MixtureUpdateRestriction");
71 cls.def(py::init<int>(),
"dim"_a);
76static PyMixture declareMixture(
py::module &mod) {
77 PyMixture cls(mod,
"Mixture");
78 afw::table::io::python::addPersistableMethods<Mixture>(cls);
79 cls.def(
"__iter__", [](Mixture &
self) {
return py::make_iterator(
self.
begin(),
self.
end()); },
80 py::keep_alive<0, 1>());
81 cls.def(
"__getitem__",
83 py::return_value_policy::reference_internal);
97 [](Mixture
const &
self, MixtureComponent
const &component,
98 ndarray::Array<Scalar, 1, 0>
const &array) ->
Scalar {
99 return self.evaluate(component, ndarray::asEigenMatrix(array));
101 "component"_a,
"x"_a);
103 [](Mixture
const &
self, ndarray::Array<Scalar, 1, 0>
const &array) ->
Scalar {
104 return self.evaluate(ndarray::asEigenMatrix(array));
107 cls.def(
"evaluate", (
void (Mixture::*)(ndarray::Array<Scalar const, 2, 1>
const &,
108 ndarray::Array<Scalar, 1, 0>
const &)
const) &
112 cls.def(
"evaluateDerivatives",
113 py::overload_cast<ndarray::Array<Scalar const, 1, 1>
const &,
114 ndarray::Array<Scalar,1,1>
const &,
116 "x"_a,
"gradient"_a,
"hessian"_a);
118 cls.def(
"updateEM", (
void (Mixture::*)(ndarray::Array<Scalar const, 2, 1>
const &,
119 ndarray::Array<Scalar const, 1, 0>
const &,
Scalar,
Scalar)) &
121 "x"_a,
"w"_a,
"tau1"_a = 0.0,
"tau2"_a = 0.5);
122 cls.def(
"updateEM", (
void (Mixture::*)(ndarray::Array<Scalar const, 2, 1>
const &,
123 ndarray::Array<Scalar const, 1, 0>
const &,
124 MixtureUpdateRestriction
const &restriction,
Scalar,
Scalar)) &
126 "x"_a,
"w"_a,
"restriction"_a,
"tau1"_a = 0.0,
"tau2"_a = 0.5);
127 cls.def(
"updateEM", (
void (Mixture::*)(ndarray::Array<Scalar const, 2, 1>
const &,
128 MixtureUpdateRestriction
const &restriction,
Scalar,
Scalar)) &
130 "x"_a,
"restriction"_a,
"tau1"_a = 0.0,
"tau2"_a = 0.5);
132 cls.def(py::init<int, Mixture::ComponentList &, Scalar>(),
"dim"_a,
"components"_a,
140 py::module::import(
"lsst.afw.math");
142 auto clsMixtureComponent = declareMixtureComponent(mod);
143 auto clsMixtureUpdateRestriction = declareMixtureUpdateRestriction(mod);
144 auto clsMixture = declareMixture(mod);
145 clsMixture.attr(
"Component") = clsMixtureComponent;
146 clsMixture.attr(
"UpdateRestriction") = clsMixtureUpdateRestriction;
MixtureComponent project(int dim) const
Project the distribution onto the given dimension (marginalize over all others)
Vector getMu() const
Get/set the location parameter (mean/median/mode) of this component.
Scalar weight
Weight of this distribution in the mixture.
void setSigma(Matrix const &sigma)
void setMu(Vector const &mu)
Matrix getSigma() const
Get/set the shape/size parameter.
int getDimension() const
Return the number of dimensions.
void updateEM(ndarray::Array< Scalar const, 2, 1 > const &x, ndarray::Array< Scalar const, 1, 0 > const &w, Scalar tau1=0.0, Scalar tau2=0.5)
Perform an Expectation-Maximization step, updating the component parameters to match the given weight...
Scalar getDegreesOfFreedom() const
Get the number of degrees of freedom in the component Student's T distributions (inf=Gaussian)
std::size_t size() const
Return the number of components.
std::shared_ptr< Mixture > project(int dim) const
Project the distribution onto the given dimensions (marginalize over all others)
Scalar evaluate(Component const &component, Eigen::MatrixBase< Derived > const &x) const
Evaluate the probability density at the given point for the given component distribution.
void normalize()
Iterate over all components, rescaling their weights so they sum to one.
void evaluateComponents(ndarray::Array< Scalar const, 2, 1 > const &x, ndarray::Array< Scalar, 2, 1 > const &p) const
Evaluate the contributions of each component to the full probability at the given points.
void evaluateDerivatives(ndarray::Array< Scalar const, 1, 1 > const &x, ndarray::Array< Scalar, 1, 1 > const &gradient, ndarray::Array< Scalar, 2, 1 > const &hessian) const
Evaluate the derivative of the distribution at the given point.
void shift(int dim, Scalar offset)
Shift the mixture in the given dimension, adding the given offset to all mu vectors.
virtual std::shared_ptr< Mixture > clone() const
Polymorphic deep copy.
virtual int getComponentCount() const
Return the number of components.
void draw(afw::math::Random &rng, ndarray::Array< Scalar, 2, 1 > const &x) const
Draw random variates from the distribution.
int getDimension() const
Return the number of dimensions.
void setDegreesOfFreedom(Scalar df=std::numeric_limits< Scalar >::infinity())
Set the number of degrees of freedom in the component Student's T distributions (inf=Gaussian)
std::size_t clip(Scalar threshold=0.0)
Iterate over all components, removing those with weight less than or equal to threshold.
PYBIND11_MODULE(_cameraGeom, mod)
void addOutputOp(PyClass &cls, std::string const &method)
Add __str__ or __repr__ method implemented by operator<<.
std::size_t cppIndex(std::ptrdiff_t size, std::ptrdiff_t i)
Compute a C++ index from a Python index (negative values count from the end) and range-check.
double Scalar
Typedefs to be used for probability and parameter values.
A base class for image defects.