32 #include <boost/python/extract.hpp>
33 #include <boost/python/object.hpp>
34 #include <boost/python/tuple.hpp>
38 namespace py = boost::python;
59 template <
typename R,
typename ...T>
63 return py::extract<R>(func(args...));
65 catch (
const py::error_already_set &
e) {
88 operator const py::object&()
const {
96 py::object
attr(
const char *name) {
97 return m_obj_ptr->attr(name);
104 ModelFittingConfig::ModelFittingConfig(
long manager_id) :
Configuration(manager_id) {
105 declareDependency<PythonConfig>();
122 catch (py::error_already_set &
e) {
128 for (
auto& p : getDependency<PythonConfig>().getInterpreter().getConstantParameters()) {
129 auto py_value_func =
PyObjectHolder(p.second.attr(
"get_value")());
130 auto value_func = [py_value_func] (
const SourceInterface& o) ->
double {
132 return py_call_wrapper<double>(py_value_func, oi);
134 m_parameters[p.first] = std::make_shared<FlexibleModelFittingConstantParameter>(
135 p.first, value_func);
138 for (
auto& p : getDependency<PythonConfig>().getInterpreter().getFreeParameters()) {
139 auto py_init_value_func =
PyObjectHolder(p.second.attr(
"get_init_value")());
140 auto init_value_func = [py_init_value_func] (
const SourceInterface& o) ->
double {
142 return py_call_wrapper<double>(py_init_value_func, oi);
148 std::string type_string(py::extract<char const*>(py_range_obj.attr(
"__class__").attr(
"__name__")));
149 if (type_string ==
"Unbounded") {
150 auto py_factor_func =
PyObjectHolder(py_range_obj.attr(
"get_normalization_factor")());
151 auto factor_func = [py_factor_func] (
double init,
const SourceInterface& o) ->
double {
153 return py_call_wrapper<double>(py_factor_func, init, oi);
155 converter = std::make_shared<FlexibleModelFittingUnboundedConverterFactory>(factor_func);
156 }
else if (type_string ==
"Range") {
157 auto py_range_func =
PyObjectHolder(py_range_obj.attr(
"get_limits")());
160 py::tuple range = py_call_wrapper<py::tuple>(py_range_func, init, oi);
161 double low = py::extract<double>(range[0]);
162 double high = py::extract<double>(range[1]);
165 bool is_exponential = py::extract<int>(py_range_obj.attr(
"get_type")().attr(
"value")) == 2;
167 if (is_exponential) {
168 converter = std::make_shared<FlexibleModelFittingExponentialRangeConverterFactory>(range_func);
170 converter = std::make_shared<FlexibleModelFittingLinearRangeConverterFactory>(range_func);
175 m_parameters[p.first] = std::make_shared<FlexibleModelFittingFreeParameter>(
176 p.first, init_value_func, converter);
179 for (
auto& p : getDependency<PythonConfig>().getInterpreter().getDependentParameters()) {
182 py::list param_ids = py::extract<py::list>(p.second.attr(
"params"));
183 for (
int i = 0; i < py::len(param_ids); ++i) {
184 int id = py::extract<int>(param_ids[i]);
192 return py::extract<double>((*py_func)(*py::tuple(params)));
194 catch (
const py::error_already_set&) {
199 m_parameters[p.first] = std::make_shared<FlexibleModelFittingDependentParameter>(
200 p.first, dependent_func, params);
203 for (
auto& p : getDependency<PythonConfig>().getInterpreter().getConstantModels()) {
204 int value_id = py::extract<int>(p.second.attr(
"value").attr(
"id"));
205 m_models[p.first] = std::make_shared<FlexibleModelFittingConstantModel>(
210 for (
auto& p : getDependency<PythonConfig>().getInterpreter().getPointSourceModels()) {
211 int x_coord_id = py::extract<int>(p.second.attr(
"x_coord").attr(
"id"));
212 int y_coord_id = py::extract<int>(p.second.attr(
"y_coord").attr(
"id"));
213 int flux_id = py::extract<int>(p.second.attr(
"flux").attr(
"id"));
214 m_models[p.first] = std::make_shared<FlexibleModelFittingPointModel>(
218 for (
auto& p : getDependency<PythonConfig>().getInterpreter().getSersicModels()) {
219 int x_coord_id = py::extract<int>(p.second.attr(
"x_coord").attr(
"id"));
220 int y_coord_id = py::extract<int>(p.second.attr(
"y_coord").attr(
"id"));
221 int flux_id = py::extract<int>(p.second.attr(
"flux").attr(
"id"));
222 int effective_radius_id = py::extract<int>(p.second.attr(
"effective_radius").attr(
"id"));
223 int aspect_ratio_id = py::extract<int>(p.second.attr(
"aspect_ratio").attr(
"id"));
224 int angle_id = py::extract<int>(p.second.attr(
"angle").attr(
"id"));
225 int n_id = py::extract<int>(p.second.attr(
"n").attr(
"id"));
226 m_models[p.first] = std::make_shared<FlexibleModelFittingSersicModel>(
232 for (
auto& p : getDependency<PythonConfig>().getInterpreter().getExponentialModels()) {
233 int x_coord_id = py::extract<int>(p.second.attr(
"x_coord").attr(
"id"));
234 int y_coord_id = py::extract<int>(p.second.attr(
"y_coord").attr(
"id"));
235 int flux_id = py::extract<int>(p.second.attr(
"flux").attr(
"id"));
236 int effective_radius_id = py::extract<int>(p.second.attr(
"effective_radius").attr(
"id"));
237 int aspect_ratio_id = py::extract<int>(p.second.attr(
"aspect_ratio").attr(
"id"));
238 int angle_id = py::extract<int>(p.second.attr(
"angle").attr(
"id"));
239 m_models[p.first] = std::make_shared<FlexibleModelFittingExponentialModel>(
244 for (
auto& p : getDependency<PythonConfig>().getInterpreter().getDeVaucouleursModels()) {
245 int x_coord_id = py::extract<int>(p.second.attr(
"x_coord").attr(
"id"));
246 int y_coord_id = py::extract<int>(p.second.attr(
"y_coord").attr(
"id"));
247 int flux_id = py::extract<int>(p.second.attr(
"flux").attr(
"id"));
248 int effective_radius_id = py::extract<int>(p.second.attr(
"effective_radius").attr(
"id"));
249 int aspect_ratio_id = py::extract<int>(p.second.attr(
"aspect_ratio").attr(
"id"));
250 int angle_id = py::extract<int>(p.second.attr(
"angle").attr(
"id"));
251 m_models[p.first] = std::make_shared<FlexibleModelFittingDevaucouleursModel>(
256 for (
auto& p : getDependency<PythonConfig>().getInterpreter().getFrameModelsMap()) {
258 for (
int x : p.second) {
261 m_frames.push_back(std::make_shared<FlexibleModelFittingFrame>(p.first, model_list));
264 for (
auto& p : getDependency<PythonConfig>().getInterpreter().
getPriors()) {
265 auto& prior = p.second;
266 int param_id = py::extract<int>(prior.attr(
"param"));
269 auto value_func = [py_value_func] (
const SourceInterface& o) ->
double {
271 return py_call_wrapper<double>(py_value_func, oi);
274 auto sigma_func = [py_sigma_func] (
const SourceInterface& o) ->
double {
276 return py_call_wrapper<double>(py_sigma_func, oi);
278 m_priors[p.first] = std::make_shared<FlexibleModelFittingPrior>(param, value_func, sigma_func);
281 m_outputs = getDependency<PythonConfig>().getInterpreter().getModelFittingOutputColumns();
283 auto parameters = getDependency<PythonConfig>().getInterpreter().getModelFittingParams();