31 #include <boost/python/extract.hpp>
32 #include <boost/python/object.hpp>
33 #include <boost/python/tuple.hpp>
37 namespace py = boost::python;
58 template <
typename R,
typename ...T>
62 return py::extract<R>(func(args...));
64 catch (
const py::error_already_set &
e) {
87 operator const py::object&()
const {
95 py::object
attr(
const char *name) {
96 return m_obj_ptr->attr(name);
103 ModelFittingConfig::ModelFittingConfig(
long manager_id) :
Configuration(manager_id) {
104 declareDependency<PythonConfig>();
121 catch (py::error_already_set &
e) {
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 {
131 return py_call_wrapper<double>(py_value_func, oi);
133 m_parameters[p.first] = std::make_shared<FlexibleModelFittingConstantParameter>(
134 p.first, value_func);
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 {
141 return py_call_wrapper<double>(py_init_value_func, oi);
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 {
152 return py_call_wrapper<double>(py_factor_func, init, oi);
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")());
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]);
164 bool is_exponential = py::extract<int>(py_range_obj.attr(
"get_type")().attr(
"value")) == 2;
166 if (is_exponential) {
167 converter = std::make_shared<FlexibleModelFittingExponentialRangeConverterFactory>(range_func);
169 converter = std::make_shared<FlexibleModelFittingLinearRangeConverterFactory>(range_func);
174 m_parameters[p.first] = std::make_shared<FlexibleModelFittingFreeParameter>(
175 p.first, init_value_func, converter);
178 for (
auto& p : getDependency<PythonConfig>().getInterpreter().getDependentParameters()) {
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]);
191 return py::extract<double>((*py_func)(*py::tuple(params)));
193 catch (
const py::error_already_set&) {
198 m_parameters[p.first] = std::make_shared<FlexibleModelFittingDependentParameter>(
199 p.first, dependent_func, params);
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>(
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>(
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>(
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>(
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>(
255 for (
auto& p : getDependency<PythonConfig>().getInterpreter().getFrameModelsMap()) {
257 for (
int x : p.second) {
260 m_frames.push_back(std::make_shared<FlexibleModelFittingFrame>(p.first, model_list));
263 for (
auto& p : getDependency<PythonConfig>().getInterpreter().
getPriors()) {
264 auto& prior = p.second;
265 int param_id = py::extract<int>(prior.attr(
"param"));
268 auto value_func = [py_value_func] (
const SourceInterface& o) ->
double {
270 return py_call_wrapper<double>(py_value_func, oi);
273 auto sigma_func = [py_sigma_func] (
const SourceInterface& o) ->
double {
275 return py_call_wrapper<double>(py_sigma_func, oi);
277 m_priors[p.first] = std::make_shared<FlexibleModelFittingPrior>(param, value_func, sigma_func);
280 m_outputs = getDependency<PythonConfig>().getInterpreter().getModelFittingOutputColumns();
282 auto parameters = getDependency<PythonConfig>().getInterpreter().getModelFittingParams();