SourceXtractorPlusPlus 0.21
SourceXtractor++, the next generation SExtractor
Loading...
Searching...
No Matches
FlexibleModelFittingModel.cpp
Go to the documentation of this file.
1
17/*
18 * FlexibleModelFittingModel.cpp
19 *
20 * Created on: Oct 9, 2018
21 * Author: mschefer
22 */
23
24#include "AlexandriaKernel/memory_tools.h"
25
27
32
36
38
41
44
46
49
50#include "Configuration/ConfigManager.h"
52
53#ifdef WITH_ONNX_MODELS
55#endif
56
58
59namespace SourceXtractor {
60
61using namespace ModelFitting;
63using namespace Euclid::Configuration;
64
65static const double MODEL_MIN_SIZE = 4.0;
66static const double MODEL_SIZE_FACTOR = 1.2;
67
68// Reference for Sersic related quantities:
69// See https://ned.ipac.caltech.edu/level5/March05/Graham/Graham2.html
70
71
72// Note about pixel coordinates:
73
74// The model fitting is made in pixel coordinates of the detection image, or if no detection image is used,
75// pixel coordinate of the "reference" image, which is usually the first measurement image
76
77// Internally we use a coordinate system with (0,0) at the center of the first pixel. But for compatibility with
78// SExtractor 2, all pixel coordinates visible to the end user need to follow the FITS convention of (1,1) being the
79// center of the coordinate system.
80
81// The ModelFitting module uses the more common standard of (0, 0) being the corner of the first pixel.
82
83// So we first convert the Python parameter to our internal coordinates, then do the transformation of coordinate,
84// subtract the offset to the image cut-out and shift the result by 0.5 pixels
85
86
89 std::vector<ModelFitting::ConstantModel>& /* constant_models */,
92 double /* model_base_size */,
96
98 [reference_coordinates, coordinates, offset](double x, double y) {
99 return coordinates->worldToImage(reference_coordinates->imageToWorld(ImageCoordinate(x-1, y-1))).m_x - offset.m_x + 0.5;
100 }, manager.getParameter(source, m_x), manager.getParameter(source, m_y));
101
102
104 [reference_coordinates, coordinates, offset](double x, double y) {
105 return coordinates->worldToImage(reference_coordinates->imageToWorld(ImageCoordinate(x-1, y-1))).m_y - offset.m_y + 0.5;
106 }, manager.getParameter(source, m_x), manager.getParameter(source, m_y));
107
108 point_models.emplace_back(pixel_x, pixel_y, manager.getParameter(source, m_flux));
109}
110
112 const SourceInterface& source,
113 std::vector<ModelFitting::ConstantModel>& /* constant_models */,
116 double model_base_size,
120
122 [reference_coordinates, coordinates, offset](double x, double y) {
123 return coordinates->worldToImage(reference_coordinates->imageToWorld(ImageCoordinate(x-1, y-1))).m_x - offset.m_x + 0.5;
124 }, manager.getParameter(source, m_x), manager.getParameter(source, m_y));
125
126
128 [reference_coordinates, coordinates, offset](double x, double y) {
129 return coordinates->worldToImage(reference_coordinates->imageToWorld(ImageCoordinate(x-1, y-1))).m_y - offset.m_y + 0.5;
130 }, manager.getParameter(source, m_x), manager.getParameter(source, m_y));
131
132 auto x_scale = std::make_shared<ManualParameter>(1); // we don't scale the x coordinate
133
134 auto i0 = createDependentParameter(
135 [](double flux, double radius, double aspect) { return flux / (2 * M_PI * 0.35513 * radius * radius * aspect); },
136 manager.getParameter(source, m_flux), manager.getParameter(source, m_effective_radius),
137 manager.getParameter(source, m_aspect_ratio));
138
140 [](double eff_radius) { return 1.678 / eff_radius; },
141 manager.getParameter(source, m_effective_radius));
142
145 2.0, i0, k, x_scale, manager.getParameter(source, m_aspect_ratio), manager.getParameter(source, m_angle),
146 size, size, pixel_x, pixel_y, manager.getParameter(source, m_flux), jacobian));
147}
148
150 const SourceInterface& source,
151 std::vector<ModelFitting::ConstantModel>& /* constant_models */,
154 double model_base_size,
158
160 [reference_coordinates, coordinates, offset](double x, double y) {
161 return coordinates->worldToImage(reference_coordinates->imageToWorld(ImageCoordinate(x-1, y-1))).m_x - offset.m_x + 0.5;
162 }, manager.getParameter(source, m_x), manager.getParameter(source, m_y));
163
164
166 [reference_coordinates, coordinates, offset](double x, double y) {
167 return coordinates->worldToImage(reference_coordinates->imageToWorld(ImageCoordinate(x-1, y-1))).m_y - offset.m_y + 0.5;
168 }, manager.getParameter(source, m_x), manager.getParameter(source, m_y));
169
170 auto n = std::make_shared<ManualParameter>(4); // Sersic index for Devaucouleurs
171 auto x_scale = std::make_shared<ManualParameter>(1); // we don't scale the x coordinate
172
173 auto i0 = createDependentParameter(
174 [](double flux, double radius, double aspect) { return flux / (2 * M_PI * 0.001684925 * radius * radius * aspect); },
175 manager.getParameter(source, m_flux), manager.getParameter(source, m_effective_radius),
176 manager.getParameter(source, m_aspect_ratio));
177
179 [](double eff_radius) { return 7.669 / pow(eff_radius, .25); },
180 manager.getParameter(source, m_effective_radius));
181
184 3.0, i0, k, n, x_scale, manager.getParameter(source, m_aspect_ratio), manager.getParameter(source, m_angle),
185 size, size, pixel_x, pixel_y, manager.getParameter(source, m_flux), jacobian));
186}
187
188static double computeBn(double n) {
189 // Using approximation from MacArthur, L.A., Courteau, S., & Holtzman, J.A. 2003, ApJ, 582, 689
190
191 // The approximation only works for n >= 0.36, so we clamp the value to avoid numerical problems
192 n = std::max(0.36, n);
193
194 return 2 * n - 1.0 / 3.0 + 4 / (405 * n)
195 + 46 / (25515 * n * n) + 131 / (1148175 * n * n * n) - 2194697 / (30690717750 * n * n * n * n);
196}
197
199 const SourceInterface& source,
200 std::vector<ModelFitting::ConstantModel>& /* constant_models */,
203 double model_base_size,
208 [reference_coordinates, coordinates, offset](double x, double y) {
209 return coordinates->worldToImage(reference_coordinates->imageToWorld(ImageCoordinate(x-1, y-1))).m_x - offset.m_x + 0.5;
210 }, manager.getParameter(source, m_x), manager.getParameter(source, m_y));
211
213 [reference_coordinates, coordinates, offset](double x, double y) {
214 return coordinates->worldToImage(reference_coordinates->imageToWorld(ImageCoordinate(x-1, y-1))).m_y - offset.m_y + 0.5;
215 }, manager.getParameter(source, m_x), manager.getParameter(source, m_y));
216
217 auto x_scale = std::make_shared<ManualParameter>(1); // we don't scale the x coordinate
218
219 auto i0 = createDependentParameter(
220 [](double flux, double radius, double aspect, double n) { return flux / (2 * M_PI * pow(computeBn(n), -2*n) * n * std::tgamma(2*n) * radius * radius * aspect); },
221 manager.getParameter(source, m_flux), manager.getParameter(source, m_effective_radius),
222 manager.getParameter(source, m_aspect_ratio), manager.getParameter(source, m_sersic_index));
223
225 [](double eff_radius, double n) { return computeBn(n) / pow(eff_radius, 1.0 / n); },
226 manager.getParameter(source, m_effective_radius), manager.getParameter(source, m_sersic_index));
227
230 3.0, i0, k, manager.getParameter(source, m_sersic_index), x_scale, manager.getParameter(source, m_aspect_ratio),
231 manager.getParameter(source, m_angle), size, size, pixel_x, pixel_y, manager.getParameter(source, m_flux), jacobian));
232}
233
245
246#ifdef WITH_ONNX_MODELS
247
248void FlexibleModelFittingOnnxModel::addForSource(FlexibleModelFittingParameterManager& manager,
249 const SourceInterface& source,
250 std::vector<ModelFitting::ConstantModel>& /* constant_models */,
253 double model_base_size,
257
259 [reference_coordinates, coordinates, offset](double x, double y) {
260 return coordinates->worldToImage(reference_coordinates->imageToWorld(ImageCoordinate(x-1, y-1))).m_x - offset.m_x + 0.5;
261 }, manager.getParameter(source, m_x), manager.getParameter(source, m_y));
262
263
264 auto pixel_y = createDependentParameter(
265 [reference_coordinates, coordinates, offset](double x, double y) {
266 return coordinates->worldToImage(reference_coordinates->imageToWorld(ImageCoordinate(x-1, y-1))).m_y - offset.m_y + 0.5;
267 }, manager.getParameter(source, m_x), manager.getParameter(source, m_y));
268
270 [](double scale, double ratio) {
271 return scale * ratio;
272 }, manager.getParameter(source, m_scale), manager.getParameter(source, m_aspect_ratio));
273
275 for (auto it : m_params) {
276 params[it.first] = manager.getParameter(source, it.second);
277 }
278
279 int size = std::max(MODEL_MIN_SIZE, MODEL_SIZE_FACTOR * model_base_size);
281 manager.getParameter(source, m_scale), y_scale, manager.getParameter(source, m_angle),
282 size, size, pixel_x, pixel_y, manager.getParameter(source, m_flux), params, jacobian));
283}
284
285FlexibleModelFittingOnnxModel::FlexibleModelFittingOnnxModel(
294 : m_x(x),
295 m_y(y),
296 m_flux(flux),
297 m_aspect_ratio(aspect_ratio),
298 m_angle(angle),
299 m_scale(scale),
300 m_params(params),
301 m_models(models){
302
303 std::sort(m_models.begin(), m_models.end(),
304 [](const std::shared_ptr<OnnxModel>& a, const std::shared_ptr<OnnxModel>& b) -> bool {
305 return a->getOutputShape()[2] < b->getOutputShape()[2];
306 });
307}
308
309#endif
310
311}
312
std::shared_ptr< DependentParameter< std::shared_ptr< EngineParameter > > > x
std::shared_ptr< DependentParameter< std::shared_ptr< EngineParameter > > > y
std::shared_ptr< FlexibleModelFittingParameter > m_value
virtual void addForSource(FlexibleModelFittingParameterManager &manager, const SourceInterface &source, std::vector< ModelFitting::ConstantModel > &constant_models, std::vector< ModelFitting::PointModel > &point_models, std::vector< std::shared_ptr< ModelFitting::ExtendedModel< ImageInterfaceTypePtr > > > &extended_models, double model_base_size, std::tuple< double, double, double, double > jacobian, std::shared_ptr< CoordinateSystem > reference_coordinates, std::shared_ptr< CoordinateSystem > coordinates, PixelCoordinate offset) const
std::shared_ptr< FlexibleModelFittingParameter > m_flux
std::shared_ptr< FlexibleModelFittingParameter > m_angle
std::shared_ptr< FlexibleModelFittingParameter > m_y
std::shared_ptr< FlexibleModelFittingParameter > m_effective_radius
std::shared_ptr< FlexibleModelFittingParameter > m_x
std::shared_ptr< FlexibleModelFittingParameter > m_aspect_ratio
virtual void addForSource(FlexibleModelFittingParameterManager &manager, const SourceInterface &source, std::vector< ModelFitting::ConstantModel > &constant_models, std::vector< ModelFitting::PointModel > &point_models, std::vector< std::shared_ptr< ModelFitting::ExtendedModel< ImageInterfaceTypePtr > > > &extended_models, double model_base_size, std::tuple< double, double, double, double > jacobian, std::shared_ptr< CoordinateSystem > reference_coordinates, std::shared_ptr< CoordinateSystem > coordinates, PixelCoordinate offset) const
std::shared_ptr< FlexibleModelFittingParameter > m_effective_radius
std::shared_ptr< FlexibleModelFittingParameter > m_angle
virtual void addForSource(FlexibleModelFittingParameterManager &manager, const SourceInterface &source, std::vector< ModelFitting::ConstantModel > &constant_models, std::vector< ModelFitting::PointModel > &point_models, std::vector< std::shared_ptr< ModelFitting::ExtendedModel< ImageInterfaceTypePtr > > > &extended_models, double model_base_size, std::tuple< double, double, double, double > jacobian, std::shared_ptr< CoordinateSystem > reference_coordinates, std::shared_ptr< CoordinateSystem > coordinates, PixelCoordinate offset) const
std::shared_ptr< FlexibleModelFittingParameter > m_y
std::shared_ptr< FlexibleModelFittingParameter > m_x
std::shared_ptr< FlexibleModelFittingParameter > m_aspect_ratio
std::shared_ptr< FlexibleModelFittingParameter > m_flux
std::shared_ptr< FlexibleModelFittingParameter > m_flux
std::shared_ptr< FlexibleModelFittingParameter > m_x
std::shared_ptr< FlexibleModelFittingParameter > m_y
virtual void addForSource(FlexibleModelFittingParameterManager &manager, const SourceInterface &source, std::vector< ModelFitting::ConstantModel > &constant_models, std::vector< ModelFitting::PointModel > &point_models, std::vector< std::shared_ptr< ModelFitting::ExtendedModel< ImageInterfaceTypePtr > > > &extended_models, double model_base_size, std::tuple< double, double, double, double > jacobian, std::shared_ptr< CoordinateSystem > reference_coordinates, std::shared_ptr< CoordinateSystem > coordinates, PixelCoordinate offset) const
std::shared_ptr< FlexibleModelFittingParameter > m_sersic_index
std::shared_ptr< FlexibleModelFittingParameter > m_x
virtual void addForSource(FlexibleModelFittingParameterManager &manager, const SourceInterface &source, std::vector< ModelFitting::ConstantModel > &constant_models, std::vector< ModelFitting::PointModel > &point_models, std::vector< std::shared_ptr< ModelFitting::ExtendedModel< ImageInterfaceTypePtr > > > &extended_models, double model_base_size, std::tuple< double, double, double, double > jacobian, std::shared_ptr< CoordinateSystem > reference_coordinates, std::shared_ptr< CoordinateSystem > coordinates, PixelCoordinate offset) const
std::shared_ptr< FlexibleModelFittingParameter > m_y
std::shared_ptr< FlexibleModelFittingParameter > m_aspect_ratio
std::shared_ptr< FlexibleModelFittingParameter > m_effective_radius
std::shared_ptr< FlexibleModelFittingParameter > m_angle
std::shared_ptr< FlexibleModelFittingParameter > m_flux
The SourceInterface is an abstract "source" that has properties attached to it.
T make_shared(T... args)
T max(T... args)
std::unique_ptr< T > make_unique(Args &&... args)
std::shared_ptr< DependentParameter< Parameters... > > createDependentParameter(typename DependentParameter< Parameters... >::ValueCalculator value_calculator, Parameters... parameters)
static const double MODEL_SIZE_FACTOR
static double computeBn(double n)
static const double MODEL_MIN_SIZE
T pow(T... args)
T sort(T... args)
A pixel coordinate made of two integers m_x and m_y.
T tgamma(T... args)