LSST Applications g00d0e8bbd7+edbf708997,g03191d30f7+9ce8016dbd,g1955dfad08+0bd186d245,g199a45376c+5137f08352,g1fd858c14a+a888a50aa2,g262e1987ae+45f9aba685,g29ae962dfc+1c7d47a24f,g2cef7863aa+73c82f25e4,g35bb328faa+edbf708997,g3fd5ace14f+eed17d2c67,g47891489e3+6dc8069a4c,g53246c7159+edbf708997,g64539dfbff+c4107e45b5,g67b6fd64d1+6dc8069a4c,g74acd417e5+f452e9c21a,g786e29fd12+af89c03590,g7ae74a0b1c+a25e60b391,g7aefaa3e3d+2025e9ce17,g7cc15d900a+2d158402f9,g87389fa792+a4172ec7da,g89139ef638+6dc8069a4c,g8d4809ba88+c4107e45b5,g8d7436a09f+e96c132b44,g8ea07a8fe4+db21c37724,g98df359435+aae6d409c1,ga2180abaac+edbf708997,gac66b60396+966efe6077,gb632fb1845+88945a90f8,gbaa8f7a6c5+38b34f4976,gbf99507273+edbf708997,gca7fc764a6+6dc8069a4c,gd7ef33dd92+6dc8069a4c,gda68eeecaf+7d1e613a8d,gdab6d2f7ff+f452e9c21a,gdbb4c4dda9+c4107e45b5,ge410e46f29+6dc8069a4c,ge41e95a9f2+c4107e45b5,geaed405ab2+e194be0d2b,w.2025.47
LSST Data Management Base Package
Loading...
Searching...
No Matches
_calcCompensatedGaussian.cc
Go to the documentation of this file.
1#include "pybind11/pybind11.h"
2#include "pybind11/numpy.h"
4#include <math.h>
5#include <vector>
6#include <stdio.h>
7
8namespace py = pybind11;
9
10namespace lsst {
11namespace meas {
12namespace base {
13
14py::tuple compensated_gaussian_filt_inner_product(py::array_t<double, py::array::c_style | py::array::forcecast> & array,
15 py::array_t<double, py::array::c_style | py::array::forcecast> & variance_array,
16 double x_mean, double y_mean, double sig, double t) {
17 //Verify the input array is conditioned in an appropriate manner.
18 py::buffer_info buffer = array.request();
19 py::buffer_info variance_buffer = variance_array.request();
20
21 if (buffer.ndim != 2) {
22 throw std::runtime_error("Number of dimensions for array must be 2");
23 }
24 if (buffer.shape[0] != buffer.shape[1]){
25 throw std::runtime_error("Array must be square");
26 }
27 if (!(buffer.shape[0] % 2)) {
28 throw std::runtime_error("Number of pixels along array side must be odd");
29 }
30
31 if (variance_buffer.ndim != buffer.ndim) {
32 throw std::runtime_error("Variance array must have same dimensions as image array");
33 }
34 if (variance_buffer.shape[0] != buffer.shape[0] || variance_buffer.shape[1] != buffer.shape[1]) {
35 throw std::runtime_error("Variance array must have same dimensions as image array");
36 }
37
38 double sig_sq = sig*sig;
39 double t_sq_inv = 1./(t*t);
40 double t_inv = 1./t;
41
42 // fast access to array since we know all the bounds are appropriate
43 auto array_unchecked = array.unchecked<2>();
44 auto variance_array_unchecked = variance_array.unchecked<2>();
45
46 // declare most variables that will be used
47 double flux = 0;
48 double x_offset_sq;
49 double y_offset_sq;
50 double y_component;
51 double y_component_out;
52 double tmp_x_div;
53 double tmp_y_div;
54 double two_sig_sq = 2*sig_sq;
55
56 int half_domain = floor(buffer.shape[0] / 2);
57 int stop = buffer.shape[0];
58
59 // adjust the x and y center to be centered about the middle of the array
60 x_mean -= (double) half_domain;
61 y_mean -= (double) half_domain;
62
63 /*
64 create containers to store the 1 dimensional x calculations, these will be
65 accessed for each loop in y, no need to do the same calculations each time
66 */
67 std::vector<float> x_container;
68 std::vector<float> x_container_out;
69 x_container.reserve(stop);
70 x_container_out.reserve(stop);
71
72 // for weighted variance calculation
73 double variance = 0;
74 double var_norm = 0;
75
76 // calculate the x profile
77 for (int j = 0; j < stop; ++j) {
78 double x_pos = j - half_domain;
79 x_offset_sq = -1*pow(x_pos - x_mean, 2);
80 tmp_x_div = x_offset_sq / two_sig_sq;
81 x_container.push_back(exp(tmp_x_div));
82 x_container_out.push_back(t_inv * exp(tmp_x_div * t_sq_inv));
83 }
84
85 // for each y row, go over the saved x vector accumulating the inner
86 // product.
87 for (int i = 0; i < stop; ++i) {
88 double y_pos = i - half_domain;
89 y_offset_sq = -1*pow(y_pos - y_mean, 2);
90 tmp_y_div = y_offset_sq / two_sig_sq;
91 y_component = exp(tmp_y_div);
92 y_component_out = t_inv * exp(tmp_y_div * t_sq_inv);
93 for (int j = 0; j < stop; ++j){
94 double weight = (y_component*x_container[j] - y_component_out*x_container_out[j]);
95 double weighted_value = weight*array_unchecked(i, j);
96 flux += weighted_value;
97
98 variance += weight*weight*variance_array_unchecked(i, j);
99 var_norm += weight*weight;
100 }
101 }
102
103 // Normalization of the normalized Gaussian filter is 4 * pi * sig**2 * (t**2 + 1)/(t**2 - 1)
104 // We have deliberately not applied the normalization factor 1. / (2 * pi * sig**2) in the
105 // inner product, leaving the normalization term as 2 * (t**2 + 1)/(t**2 - 1) for the
106 // flux, and XXX for the variance.
107 flux *= 2 * (t*t + 1) / (t*t - 1);
108
109 // The variance has been normalized and so requires the full normalization term.
110 variance /= var_norm;
111 variance *= (4 * M_PI * sig_sq * (t*t + 1) ) / (t*t);
112
113 return py::make_tuple(flux, variance);
114}
115
117 wrappers.wrap([](auto &mod) {
118 mod.def("_compensatedGaussianFiltInnerProduct", &compensated_gaussian_filt_inner_product,
119R"doc_string(Calculates flux and variance for a Compensated Gaussian filter.
120
121Parameters
122----------
123array : `np.ndarray` (N, N)
124 Array in which the Gaussian filter will be applied, must be square and
125 odd shaped.
126variance_array : `np.ndarray` (N, N)
127 Variance array in which the Gaussian filter will be applied, must be
128 same shape as array.
129x_mean : `float`
130 The x center position of the object in the reference frame of the array
131 argument.
132y_mean : `float`
133 The y center position of the object in the reference frame of the array
134 argument.
135sig : `float`
136 The std of the Gaussian kernel
137t : `float`
138 The dilating parameter used to calculate background.
139
140Returns
141-------
142result : `tuple` of `float`
143 Compensated Gaussian flux and variance.
144
145Raises
146------
147RuntimeError
148 Raised if the input array is not properly shaped
149
150)doc_string");
151 });
152}
153
154} // namespace base
155} // namespace meas
156} // namespace lsst
#define M_PI
Definition ListMatch.cc:31
A helper class for subdividing pybind11 module across multiple translation units (i....
Definition python.h:242
void wrapCalcCompensatedGaussian(WrapperCollection &)
py::tuple compensated_gaussian_filt_inner_product(py::array_t< double, py::array::c_style|py::array::forcecast > &array, py::array_t< double, py::array::c_style|py::array::forcecast > &variance_array, double x_mean, double y_mean, double sig, double t)
T push_back(T... args)
T reserve(T... args)