Loading [MathJax]/extensions/tex2jax.js
LSST Applications 29.0.1,g0fba68d861+b943c38344,g1ec0fe41b4+f536777771,g1fd858c14a+a9301854fb,g35bb328faa+fcb1d3bbc8,g4af146b050+7e9a2de16a,g4d2262a081+bc578d85c1,g53246c7159+fcb1d3bbc8,g56a49b3a55+9c12191793,g5a012ec0e7+3632fc3ff3,g60b5630c4e+9fd1a614b8,g67b6fd64d1+ed4b5058f4,g78460c75b0+2f9a1b4bcd,g786e29fd12+cf7ec2a62a,g8352419a5c+fcb1d3bbc8,g87b7deb4dc+4c2feab6d7,g8852436030+e5453db6e6,g89139ef638+ed4b5058f4,g8e3bb8577d+ea375a93e1,g9125e01d80+fcb1d3bbc8,g94187f82dc+9fd1a614b8,g95f8561545+9fd1a614b8,g989de1cb63+ed4b5058f4,g9d31334357+9fd1a614b8,g9f33ca652e+aa92e8646f,gabe3b4be73+1e0a283bba,gabf8522325+fa80ff7197,gb1101e3267+9288031c14,gb58c049af0+f03b321e39,gb89ab40317+ed4b5058f4,gcf25f946ba+e5453db6e6,gcf6002c91b+87cebee2a2,gd6cbbdb0b4+bb83cc51f8,gde0f65d7ad+5b57b4d45c,ge278dab8ac+d65b3c2b70,ge410e46f29+ed4b5058f4,gf23fb2af72+b7cae620c0,gf5e32f922b+fcb1d3bbc8,gf67bdafdda+ed4b5058f4
LSST Data Management Base Package
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
_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)