23 #include <boost/python/extract.hpp>
24 #include <boost/python/object.hpp>
25 #include <boost/python/tuple.hpp>
26 #include <boost/python/dict.hpp>
43 #include <boost/python/extract.hpp>
44 #include <boost/python/object.hpp>
46 #ifdef WITH_ONNX_MODELS
61 template<
typename Signature>
73 if (!wrapped.isCompiled()) {
74 logger.
warn() <<
"Could not compile " << readable <<
": " << wrapped.reason()->what();
75 wrapped.reason()->log(log4cpp::Priority::DEBUG,
logger);
80 wrapped.getTree()->visit(gv);
97 if (!wrapped.isCompiled()) {
98 logger.
warn() <<
"Could not compile " << readable <<
": " << wrapped.reason()->what();
99 wrapped.reason()->log(log4cpp::Priority::DEBUG,
logger);
104 wrapped.getTree()->visit(gv);
117 py::object py_func) {
120 if (!wrapped.isCompiled()) {
121 logger.
warn() <<
"Could not compile " << readable <<
": " << wrapped.reason()->what();
122 wrapped.reason()->log(log4cpp::Priority::DEBUG,
logger);
127 wrapped.getTree()->visit(gv);
137 ModelFittingConfig::ModelFittingConfig(
long manager_id) :
Configuration(manager_id) {
138 declareDependency<PythonConfig>();
155 catch (py::error_already_set &
e) {
161 auto coord_system = boost::any_cast<std::shared_ptr<CoordinateSystem>>(context.
at(
"coordinate_system"));
162 return coord_system->imageToWorld({
x,
y}).m_alpha;
166 auto coord_system = boost::any_cast<std::shared_ptr<CoordinateSystem>>(context.
at(
"coordinate_system"));
167 return coord_system->imageToWorld({
x,
y}).m_delta;
180 for (
auto& p : getDependency<PythonConfig>().getInterpreter().getConstantParameters()) {
182 "Constant parameter", expr_builder, p.second.attr(
"get_value")
185 m_parameters[p.first] = std::make_shared<FlexibleModelFittingConstantParameter>(
186 p.first, value_func);
190 for (
auto& p : getDependency<PythonConfig>().getInterpreter().getFreeParameters()) {
192 "Free parameter", expr_builder, p.second.attr(
"get_init_value")
195 auto py_range_obj = p.second.attr(
"get_range")();
198 std::string type_string(py::extract<char const*>(py_range_obj.attr(
"__class__").attr(
"__name__")));
200 if (type_string ==
"Unbounded") {
202 "Unbounded", expr_builder, py_range_obj.attr(
"get_normalization_factor")
204 converter = std::make_shared<FlexibleModelFittingUnboundedConverterFactory>(factor_func);
205 }
else if (type_string ==
"Range") {
207 "Range min", expr_builder, py_range_obj.attr(
"get_min")
210 "Range max", expr_builder, py_range_obj.attr(
"get_max")
214 return {min_func(init, o), max_func(init, o)};
217 bool is_exponential = py::extract<int>(py_range_obj.attr(
"get_type")().attr(
"value")) == 2;
219 if (is_exponential) {
220 converter = std::make_shared<FlexibleModelFittingExponentialRangeConverterFactory>(range_func);
222 converter = std::make_shared<FlexibleModelFittingLinearRangeConverterFactory>(range_func);
227 m_parameters[p.first] = std::make_shared<FlexibleModelFittingFreeParameter>(
228 p.first, init_value_func, converter);
232 for (
auto& p : getDependency<PythonConfig>().getInterpreter().getDependentParameters()) {
233 auto py_func = p.second.attr(
"func");
235 py::list param_ids = py::extract<py::list>(p.second.attr(
"params"));
236 for (
int i = 0; i < py::len(param_ids); ++i) {
237 int id = py::extract<int>(param_ids[i]);
242 ::get(
"Dependent parameter", expr_builder, py_func, params.size());
246 context[
"coordinate_system"] = cs;
247 return dependent(context, params);
250 m_parameters[p.first] = std::make_shared<FlexibleModelFittingDependentParameter>(
251 p.first, dependent_func, params);
254 for (
auto& p : getDependency<PythonConfig>().getInterpreter().getConstantModels()) {
255 int value_id = py::extract<int>(p.second.attr(
"value").attr(
"id"));
256 m_models[p.first] = std::make_shared<FlexibleModelFittingConstantModel>(
m_parameters[value_id]);
259 for (
auto& p : getDependency<PythonConfig>().getInterpreter().getPointSourceModels()) {
260 int x_coord_id = py::extract<int>(p.second.attr(
"x_coord").attr(
"id"));
261 int y_coord_id = py::extract<int>(p.second.attr(
"y_coord").attr(
"id"));
262 int flux_id = py::extract<int>(p.second.attr(
"flux").attr(
"id"));
263 m_models[p.first] = std::make_shared<FlexibleModelFittingPointModel>(
267 for (
auto& p : getDependency<PythonConfig>().getInterpreter().getSersicModels()) {
268 int x_coord_id = py::extract<int>(p.second.attr(
"x_coord").attr(
"id"));
269 int y_coord_id = py::extract<int>(p.second.attr(
"y_coord").attr(
"id"));
270 int flux_id = py::extract<int>(p.second.attr(
"flux").attr(
"id"));
271 int effective_radius_id = py::extract<int>(p.second.attr(
"effective_radius").attr(
"id"));
272 int aspect_ratio_id = py::extract<int>(p.second.attr(
"aspect_ratio").attr(
"id"));
273 int angle_id = py::extract<int>(p.second.attr(
"angle").attr(
"id"));
274 int n_id = py::extract<int>(p.second.attr(
"n").attr(
"id"));
275 m_models[p.first] = std::make_shared<FlexibleModelFittingSersicModel>(
281 for (
auto& p : getDependency<PythonConfig>().getInterpreter().getExponentialModels()) {
282 int x_coord_id = py::extract<int>(p.second.attr(
"x_coord").attr(
"id"));
283 int y_coord_id = py::extract<int>(p.second.attr(
"y_coord").attr(
"id"));
284 int flux_id = py::extract<int>(p.second.attr(
"flux").attr(
"id"));
285 int effective_radius_id = py::extract<int>(p.second.attr(
"effective_radius").attr(
"id"));
286 int aspect_ratio_id = py::extract<int>(p.second.attr(
"aspect_ratio").attr(
"id"));
287 int angle_id = py::extract<int>(p.second.attr(
"angle").attr(
"id"));
288 m_models[p.first] = std::make_shared<FlexibleModelFittingExponentialModel>(
293 for (
auto& p : getDependency<PythonConfig>().getInterpreter().getDeVaucouleursModels()) {
294 int x_coord_id = py::extract<int>(p.second.attr(
"x_coord").attr(
"id"));
295 int y_coord_id = py::extract<int>(p.second.attr(
"y_coord").attr(
"id"));
296 int flux_id = py::extract<int>(p.second.attr(
"flux").attr(
"id"));
297 int effective_radius_id = py::extract<int>(p.second.attr(
"effective_radius").attr(
"id"));
298 int aspect_ratio_id = py::extract<int>(p.second.attr(
"aspect_ratio").attr(
"id"));
299 int angle_id = py::extract<int>(p.second.attr(
"angle").attr(
"id"));
300 m_models[p.first] = std::make_shared<FlexibleModelFittingDevaucouleursModel>(
305 #ifdef WITH_ONNX_MODELS
306 for (
auto& p : getDependency<PythonConfig>().getInterpreter().getOnnxModels()) {
307 int x_coord_id = py::extract<int>(p.second.attr(
"x_coord").attr(
"id"));
308 int y_coord_id = py::extract<int>(p.second.attr(
"y_coord").attr(
"id"));
309 int flux_id = py::extract<int>(p.second.attr(
"flux").attr(
"id"));
310 int aspect_ratio_id = py::extract<int>(p.second.attr(
"aspect_ratio").attr(
"id"));
311 int angle_id = py::extract<int>(p.second.attr(
"angle").attr(
"id"));
312 int scale_id = py::extract<int>(p.second.attr(
"scale").attr(
"id"));
315 py::dict parameters = py::extract<py::dict>(p.second.attr(
"params"));
316 py::list names = parameters.keys();
317 for (
int i = 0; i < py::len(names); ++i) {
318 std::string name = py::extract<std::string>(names[i]);
319 params[name] =
m_parameters[py::extract<int>(parameters[names[i]].attr(
"id"))];
323 py::list models = py::extract<py::list>(p.second.attr(
"models"));
324 for (
int i = 0; i < py::len(models); ++i) {
325 std::string model_filename = py::extract<std::string>(models[i]);
326 onnx_models.
emplace_back(std::make_shared<OnnxModel>(model_filename));
328 if (onnx_models.
back()->getOutputType() != ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT ||
329 onnx_models.
back()->getOutputShape().size() != 4 ||
330 onnx_models.
back()->getOutputShape()[1] != onnx_models.
back()->getOutputShape()[2] ||
331 onnx_models.
back()->getOutputShape()[3] != 1)
333 throw Elements::Exception() <<
"ONNX models for ModelFitting must output a square array of floats";
337 m_models[p.first] = std::make_shared<FlexibleModelFittingOnnxModel>(
342 if (getDependency<PythonConfig>().getInterpreter().getOnnxModels().size() > 0) {
347 for (
auto& p : getDependency<PythonConfig>().getInterpreter().getFrameModelsMap()) {
349 for (
int x : p.second) {
352 m_frames.push_back(std::make_shared<FlexibleModelFittingFrame>(p.first, model_list));
355 for (
auto& p : getDependency<PythonConfig>().getInterpreter().
getPriors()) {
356 auto& prior = p.second;
357 int param_id = py::extract<int>(prior.attr(
"param"));
361 "Prior mean", expr_builder, prior.attr(
"value")
364 "Prior sigma", expr_builder, prior.attr(
"sigma")
367 m_priors[p.first] = std::make_shared<FlexibleModelFittingPrior>(param, value_func, sigma_func);
370 m_outputs = getDependency<PythonConfig>().getInterpreter().getModelFittingOutputColumns();
372 auto parameters = getDependency<PythonConfig>().getInterpreter().getModelFittingParams();
std::shared_ptr< DependentParameter< std::shared_ptr< EngineParameter > > > x
std::shared_ptr< DependentParameter< std::shared_ptr< EngineParameter > > > y
static Logging getLogger(const std::string &name="")
void warn(const std::string &logMessage)
void info(const std::string &logMessage)
static std::string getDefault()
const Exception & log(log4cpp::Priority::Value level, Elements::Logging &logger) const
void registerFunction(const std::string &repr, std::function< Signature > functor)
ExpressionTree< Signature > build(const boost::python::object &pyfunc, BuildParams &&... build_params) const
T emplace_back(T... args)
static Elements::Logging logger
std::map< std::string, Attribute > AttributeSet