SourceXtractorPlusPlus  0.10
Please provide a description of the project.
ModelFittingConfig.cpp
Go to the documentation of this file.
1 
17 /*
18  * @file ModelFittingConfig.cpp
19  * @author Nikolaos Apostolakos <nikoapos@gmail.com>
20  */
21 
22 #include "ElementsKernel/Logging.h"
28 #include "SEUtils/Python.h"
29 
30 #include <string>
31 #include <boost/python/extract.hpp>
32 #include <boost/python/object.hpp>
33 #include <boost/python/tuple.hpp>
34 
35 
36 using namespace Euclid::Configuration;
37 namespace py = boost::python;
38 
40 
41 namespace SourceXtractor {
42 
58 template <typename R, typename ...T>
59 R py_call_wrapper(const py::object& func, T... args) {
60  GILStateEnsure ensure;
61  try {
62  return py::extract<R>(func(args...));
63  }
64  catch (const py::error_already_set &e) {
66  }
67 }
68 
81  public:
82  PyObjectHolder(py::object&& obj): m_obj_ptr(std::make_shared<py::object>(obj)) {}
83 
84  PyObjectHolder(const PyObjectHolder&) = default;
85  PyObjectHolder(PyObjectHolder&&) = default;
86 
87  operator const py::object&() const {
88  return *m_obj_ptr;
89  }
90 
91  const py::object& operator *() const {
92  return *m_obj_ptr;
93  }
94 
95  py::object attr(const char *name) {
96  return m_obj_ptr->attr(name);
97  }
98 
99  private:
101 };
102 
103 ModelFittingConfig::ModelFittingConfig(long manager_id) : Configuration(manager_id) {
104  declareDependency<PythonConfig>();
105 }
106 
108  GILStateEnsure ensure;
109  m_parameters.clear();
110  m_models.clear();
111  m_frames.clear();
112  m_priors.clear();
113  m_outputs.clear();
114 }
115 
117  GILStateEnsure ensure;
118  try {
119  initializeInner();
120  }
121  catch (py::error_already_set &e) {
123  }
124 }
125 
127  for (auto& p : getDependency<PythonConfig>().getInterpreter().getConstantParameters()) {
128  auto py_value_func = PyObjectHolder(p.second.attr("get_value")());
129  auto value_func = [py_value_func] (const SourceInterface& o) -> double {
130  ObjectInfo oi {o};
131  return py_call_wrapper<double>(py_value_func, oi);
132  };
133  m_parameters[p.first] = std::make_shared<FlexibleModelFittingConstantParameter>(
134  p.first, value_func);
135  }
136 
137  for (auto& p : getDependency<PythonConfig>().getInterpreter().getFreeParameters()) {
138  auto py_init_value_func = PyObjectHolder(p.second.attr("get_init_value")());
139  auto init_value_func = [py_init_value_func] (const SourceInterface& o) -> double {
140  ObjectInfo oi {o};
141  return py_call_wrapper<double>(py_init_value_func, oi);
142  };
143 
144  auto py_range_obj = PyObjectHolder(p.second.attr("get_range")());
145 
147  std::string type_string(py::extract<char const*>(py_range_obj.attr("__class__").attr("__name__")));
148  if (type_string == "Unbounded") {
149  auto py_factor_func = PyObjectHolder(py_range_obj.attr("get_normalization_factor")());
150  auto factor_func = [py_factor_func] (double init, const SourceInterface& o) -> double {
151  ObjectInfo oi {o};
152  return py_call_wrapper<double>(py_factor_func, init, oi);
153  };
154  converter = std::make_shared<FlexibleModelFittingUnboundedConverterFactory>(factor_func);
155  } else if (type_string == "Range") {
156  auto py_range_func = PyObjectHolder(py_range_obj.attr("get_limits")());
157  auto range_func = [py_range_func] (double init, const SourceInterface& o) -> std::pair<double, double> {
158  ObjectInfo oi {o};
159  py::tuple range = py_call_wrapper<py::tuple>(py_range_func, init, oi);
160  double low = py::extract<double>(range[0]);
161  double high = py::extract<double>(range[1]);
162  return {low, high};
163  };
164  bool is_exponential = py::extract<int>(py_range_obj.attr("get_type")().attr("value")) == 2;
165 
166  if (is_exponential) {
167  converter = std::make_shared<FlexibleModelFittingExponentialRangeConverterFactory>(range_func);
168  } else {
169  converter = std::make_shared<FlexibleModelFittingLinearRangeConverterFactory>(range_func);
170  }
171  } else {
172  throw Elements::Exception("Unknown converter type: " + type_string);
173  }
174  m_parameters[p.first] = std::make_shared<FlexibleModelFittingFreeParameter>(
175  p.first, init_value_func, converter);
176  }
177 
178  for (auto& p : getDependency<PythonConfig>().getInterpreter().getDependentParameters()) {
179  auto py_func = PyObjectHolder(p.second.attr("func"));
181  py::list param_ids = py::extract<py::list>(p.second.attr("params"));
182  for (int i = 0; i < py::len(param_ids); ++i) {
183  int id = py::extract<int>(param_ids[i]);
184  params.push_back(m_parameters[id]);
185  }
186 
187  auto dependent_func = [py_func](const std::shared_ptr<CoordinateSystem> &cs, const std::vector<double> &params) -> double {
188  try {
189  GILStateEnsure ensure;
191  return py::extract<double>((*py_func)(*py::tuple(params)));
192  }
193  catch (const py::error_already_set&) {
195  }
196  };
197 
198  m_parameters[p.first] = std::make_shared<FlexibleModelFittingDependentParameter>(
199  p.first, dependent_func, params);
200  }
201 
202  for (auto& p : getDependency<PythonConfig>().getInterpreter().getConstantModels()) {
203  int value_id = py::extract<int>(p.second.attr("value").attr("id"));
204  m_models[p.first] = std::make_shared<FlexibleModelFittingConstantModel>(
205  m_parameters[value_id]);
206  }
207 
208 
209  for (auto& p : getDependency<PythonConfig>().getInterpreter().getPointSourceModels()) {
210  int x_coord_id = py::extract<int>(p.second.attr("x_coord").attr("id"));
211  int y_coord_id = py::extract<int>(p.second.attr("y_coord").attr("id"));
212  int flux_id = py::extract<int>(p.second.attr("flux").attr("id"));
213  m_models[p.first] = std::make_shared<FlexibleModelFittingPointModel>(
214  m_parameters[x_coord_id], m_parameters[y_coord_id], m_parameters[flux_id]);
215  }
216 
217  for (auto& p : getDependency<PythonConfig>().getInterpreter().getSersicModels()) {
218  int x_coord_id = py::extract<int>(p.second.attr("x_coord").attr("id"));
219  int y_coord_id = py::extract<int>(p.second.attr("y_coord").attr("id"));
220  int flux_id = py::extract<int>(p.second.attr("flux").attr("id"));
221  int effective_radius_id = py::extract<int>(p.second.attr("effective_radius").attr("id"));
222  int aspect_ratio_id = py::extract<int>(p.second.attr("aspect_ratio").attr("id"));
223  int angle_id = py::extract<int>(p.second.attr("angle").attr("id"));
224  int n_id = py::extract<int>(p.second.attr("n").attr("id"));
225  m_models[p.first] = std::make_shared<FlexibleModelFittingSersicModel>(
226  m_parameters[x_coord_id], m_parameters[y_coord_id], m_parameters[flux_id], m_parameters[n_id],
227  m_parameters[effective_radius_id], m_parameters[aspect_ratio_id],
228  m_parameters[angle_id]);
229  }
230 
231  for (auto& p : getDependency<PythonConfig>().getInterpreter().getExponentialModels()) {
232  int x_coord_id = py::extract<int>(p.second.attr("x_coord").attr("id"));
233  int y_coord_id = py::extract<int>(p.second.attr("y_coord").attr("id"));
234  int flux_id = py::extract<int>(p.second.attr("flux").attr("id"));
235  int effective_radius_id = py::extract<int>(p.second.attr("effective_radius").attr("id"));
236  int aspect_ratio_id = py::extract<int>(p.second.attr("aspect_ratio").attr("id"));
237  int angle_id = py::extract<int>(p.second.attr("angle").attr("id"));
238  m_models[p.first] = std::make_shared<FlexibleModelFittingExponentialModel>(
239  m_parameters[x_coord_id], m_parameters[y_coord_id], m_parameters[flux_id],
240  m_parameters[effective_radius_id], m_parameters[aspect_ratio_id], m_parameters[angle_id]);
241  }
242 
243  for (auto& p : getDependency<PythonConfig>().getInterpreter().getDeVaucouleursModels()) {
244  int x_coord_id = py::extract<int>(p.second.attr("x_coord").attr("id"));
245  int y_coord_id = py::extract<int>(p.second.attr("y_coord").attr("id"));
246  int flux_id = py::extract<int>(p.second.attr("flux").attr("id"));
247  int effective_radius_id = py::extract<int>(p.second.attr("effective_radius").attr("id"));
248  int aspect_ratio_id = py::extract<int>(p.second.attr("aspect_ratio").attr("id"));
249  int angle_id = py::extract<int>(p.second.attr("angle").attr("id"));
250  m_models[p.first] = std::make_shared<FlexibleModelFittingDevaucouleursModel>(
251  m_parameters[x_coord_id], m_parameters[y_coord_id], m_parameters[flux_id],
252  m_parameters[effective_radius_id], m_parameters[aspect_ratio_id], m_parameters[angle_id]);
253  }
254 
255  for (auto& p : getDependency<PythonConfig>().getInterpreter().getFrameModelsMap()) {
257  for (int x : p.second) {
258  model_list.push_back(m_models[x]);
259  }
260  m_frames.push_back(std::make_shared<FlexibleModelFittingFrame>(p.first, model_list));
261  }
262 
263  for (auto& p : getDependency<PythonConfig>().getInterpreter().getPriors()) {
264  auto& prior = p.second;
265  int param_id = py::extract<int>(prior.attr("param"));
266  auto param = m_parameters[param_id];
267  auto py_value_func = PyObjectHolder(prior.attr("value"));
268  auto value_func = [py_value_func] (const SourceInterface& o) -> double {
269  ObjectInfo oi {o};
270  return py_call_wrapper<double>(py_value_func, oi);
271  };
272  auto py_sigma_func = PyObjectHolder(prior.attr("sigma"));
273  auto sigma_func = [py_sigma_func] (const SourceInterface& o) -> double {
274  ObjectInfo oi {o};
275  return py_call_wrapper<double>(py_sigma_func, oi);
276  };
277  m_priors[p.first] = std::make_shared<FlexibleModelFittingPrior>(param, value_func, sigma_func);
278  }
279 
280  m_outputs = getDependency<PythonConfig>().getInterpreter().getModelFittingOutputColumns();
281 
282  auto parameters = getDependency<PythonConfig>().getInterpreter().getModelFittingParams();
283  m_least_squares_engine = py::extract<std::string>(parameters["engine"]);
285  m_least_squares_engine = "levmar";
286  }
287  m_max_iterations = py::extract<int>(parameters["max_iterations"]);
288  m_modified_chi_squared_scale = py::extract<double>(parameters["modified_chi_squared_scale"]);
289 }
290 
292  return m_parameters;
293 }
294 
296  return m_models;
297 }
298 
300  return m_frames;
301 }
302 
304  return m_priors;
305 }
306 
308  return m_outputs;
309 }
310 
311 }
SourceXtractor::ModelFittingConfig::getOutputs
const std::vector< std::pair< std::string, std::vector< int > > > & getOutputs() const
Definition: ModelFittingConfig.cpp:307
std::string
STL class.
std::shared_ptr< py::object >
SourceXtractor::ModelFittingConfig::m_models
std::map< int, std::shared_ptr< FlexibleModelFittingModel > > m_models
Definition: ModelFittingConfig.h:66
ModelFittingConfig.h
std::pair< double, double >
SourceXtractor::pyToElementsException
Elements::Exception pyToElementsException(Elements::Logging &logger)
Definition: Python.cpp:30
SourceXtractor::py_call_wrapper
R py_call_wrapper(const py::object &func, T... args)
Definition: ModelFittingConfig.cpp:59
std::make_shared
T make_shared(T... args)
SourceXtractor::ModelFittingConfig::m_priors
std::map< int, std::shared_ptr< FlexibleModelFittingPrior > > m_priors
Definition: ModelFittingConfig.h:68
Elements::Logging
std::vector
STL class.
SourceXtractor::ModelFittingConfig::~ModelFittingConfig
~ModelFittingConfig()
Definition: ModelFittingConfig.cpp:107
SourceXtractor::ModelFittingConfig::m_least_squares_engine
std::string m_least_squares_engine
Definition: ModelFittingConfig.h:61
Euclid::Configuration::logger
static Elements::Logging logger
SourceXtractor::ModelFittingConfig::m_max_iterations
unsigned int m_max_iterations
Definition: ModelFittingConfig.h:62
SourceXtractor::ObjectInfo
Definition: ObjectInfo.h:31
SourceXtractor::PyObjectHolder
Hold a reference to a Python object.
Definition: ModelFittingConfig.cpp:80
Python.h
SourceXtractor::PythonInterpreter::setCoordinateSystem
void setCoordinateSystem(std::shared_ptr< CoordinateSystem > coordinate_system)
Definition: PythonInterpreter.cpp:332
Euclid::Configuration
std::vector::clear
T clear(T... args)
SourceXtractor::ModelFittingConfig::m_parameters
std::map< int, std::shared_ptr< FlexibleModelFittingParameter > > m_parameters
Definition: ModelFittingConfig.h:65
std::vector::push_back
T push_back(T... args)
SourceXtractor::ModelFittingConfig::getModels
const std::map< int, std::shared_ptr< FlexibleModelFittingModel > > & getModels() const
Definition: ModelFittingConfig.cpp:295
SourceXtractor::ModelFittingConfig::getParameters
const std::map< int, std::shared_ptr< FlexibleModelFittingParameter > > & getParameters() const
Definition: ModelFittingConfig.cpp:291
SourceXtractor
Definition: Aperture.h:30
SourceXtractor::operator*
constexpr Flags operator*(const Flags &a, const bool b)
Definition: SourceFlags.h:58
SourceXtractor::PyObjectHolder::PyObjectHolder
PyObjectHolder(py::object &&obj)
Definition: ModelFittingConfig.cpp:82
Elements::Exception
PythonConfig.h
SourceXtractor::PyObjectHolder::attr
py::object attr(const char *name)
Definition: ModelFittingConfig.cpp:95
SourceXtractor::ModelFittingConfig::m_outputs
std::vector< std::pair< std::string, std::vector< int > > > m_outputs
Definition: ModelFittingConfig.h:69
ObjectInfo.h
std::map
STL class.
SourceXtractor::logger
static Elements::Logging logger
Definition: PluginManager.cpp:45
SourceXtractor::ModelFittingConfig::initialize
void initialize(const UserValues &args) override
Definition: ModelFittingConfig.cpp:116
SourceXtractor::ModelFittingConfig::m_modified_chi_squared_scale
double m_modified_chi_squared_scale
Definition: ModelFittingConfig.h:63
e
constexpr double e
Elements::Logging::getLogger
static Logging getLogger(const std::string &name="")
FlexibleModelFittingParameter.h
SourceXtractor::PyObjectHolder::m_obj_ptr
std::shared_ptr< py::object > m_obj_ptr
Definition: ModelFittingConfig.cpp:100
SourceXtractor::ModelFittingConfig::getPriors
const std::map< int, std::shared_ptr< FlexibleModelFittingPrior > > & getPriors() const
Definition: ModelFittingConfig.cpp:303
x
std::shared_ptr< DependentParameter< std::shared_ptr< EngineParameter > > > x
Definition: MoffatModelFittingTask.cpp:93
std
STL namespace.
std::string::empty
T empty(T... args)
Euclid::Configuration::Configuration
Logging.h
SourceXtractor::PythonInterpreter::getSingleton
static PythonInterpreter & getSingleton()
Definition: PythonInterpreter.cpp:43
SourceXtractor::ModelFittingConfig::m_frames
std::vector< std::shared_ptr< FlexibleModelFittingFrame > > m_frames
Definition: ModelFittingConfig.h:67
SourceXtractor::SourceInterface
The SourceInterface is an abstract "source" that has properties attached to it.
Definition: SourceInterface.h:46
FlexibleModelFittingConverterFactory.h
SourceXtractor::ModelFittingConfig::getFrames
const std::vector< std::shared_ptr< FlexibleModelFittingFrame > > & getFrames() const
Definition: ModelFittingConfig.cpp:299
SourceXtractor::GILStateEnsure
Definition: Python.h:45
SourceXtractor::ModelFittingConfig::initializeInner
void initializeInner()
Definition: ModelFittingConfig.cpp:126