SourceXtractorPlusPlus  0.16
Please provide a description of the project.
FlexibleModelFittingParameter.cpp
Go to the documentation of this file.
1 
17 /*
18  * FlexibleModelFittingParameter.cpp
19  *
20  * Created on: Oct 8, 2018
21  * Author: mschefer
22  */
23 
24 #include <iostream>
25 
26 #include <boost/version.hpp>
27 #if BOOST_VERSION >= 106700
28 
29 #if BOOST_VERSION >= 107000
30 #include <boost/math/differentiation/finite_difference.hpp>
31 namespace bmd = boost::math::differentiation;
32 #else
33 #include <boost/math/tools/numerical_differentiation.hpp>
34 namespace bmd = boost::math::tools;
35 #endif
36 
37 #endif
38 
40 #include "ElementsKernel/Logging.h"
45 
52 
53 
55 
56 
57 namespace SourceXtractor {
58 
59 using namespace ModelFitting;
60 
62 
64  return m_id;
65 }
66 
68  : FlexibleModelFittingParameter(id), m_value(value) { }
69 
71  FlexibleModelFittingParameterManager& /*parameter_manager*/,
72  ModelFitting::EngineParameterManager& /*engine_manager*/,
73  const SourceInterface& source) const {
74  return std::make_shared<ManualParameter>(m_value(source));
75 }
76 
78  FlexibleModelFittingParameterManager& /*parameter_manager*/,
80  const SourceInterface& source) const {
81  double initial_value = m_initial_value(source);
82 
83  auto converter = m_converter_factory->getConverter(initial_value, source);
84  auto parameter = std::make_shared<EngineParameter>(initial_value, std::move(converter));
85  engine_manager.registerParameter(parameter);
86 
87  return parameter;
88 }
89 
91  FlexibleModelFittingParameterManager& /*parameter_manager*/,
93  const SourceInterface& source,
94  double initial_value) const {
95  auto converter = m_converter_factory->getConverter(initial_value, source);
96  auto parameter = std::make_shared<EngineParameter>(initial_value, std::move(converter));
97  engine_manager.registerParameter(parameter);
98 
99  return parameter;
100 }
101 
103  const std::vector<double>& free_parameter_sigmas) const {
104  auto modelfitting_parameter = parameter_manager.getParameter(source, shared_from_this());
105  return free_parameter_sigmas[parameter_manager.getParameterIndex(source, shared_from_this())];
106 }
107 
109  return m_initial_value(source);
110 }
111 
112 namespace {
113 
114 template <typename T>
115 double doubleResolver(const T&) {
116  return 0;
117 }
118 
119 
120 template<typename ... Parameters>
121 std::shared_ptr<ModelFitting::BasicParameter> createDependentParameterHelper(
122  FlexibleModelFittingParameterManager& parameter_manager,
123  const SourceInterface& source,
125  std::shared_ptr<Parameters>... parameters) {
126  auto coordinate_system = source.getProperty<DetectionFrameCoordinates>().getCoordinateSystem();
127 
128  auto calc = [value_calculator, coordinate_system] (decltype(doubleResolver(std::declval<Parameters>()))... params) -> double {
129  std::vector<double> materialized{params...};
130  return value_calculator(coordinate_system, materialized);
131  };
132  return createDependentParameter(calc, parameter_manager.getParameter(source, parameters)...);
133 }
134 
135 }
136 
137 
139  FlexibleModelFittingParameterManager& parameter_manager,
141  const SourceInterface& source) const {
142  switch (m_parameters.size()) {
143  case 1:
144  return createDependentParameterHelper(parameter_manager, source, m_value_calculator,
145  m_parameters[0]);
146  case 2:
147  return createDependentParameterHelper(parameter_manager, source, m_value_calculator,
148  m_parameters[0], m_parameters[1]);
149  case 3:
150  return createDependentParameterHelper(parameter_manager, source, m_value_calculator,
152  case 4:
153  return createDependentParameterHelper(parameter_manager, source, m_value_calculator,
155  case 5:
156  return createDependentParameterHelper(parameter_manager, source, m_value_calculator,
158  case 6:
159  return createDependentParameterHelper(parameter_manager, source, m_value_calculator,
161  m_parameters[5]);
162  case 7:
163  return createDependentParameterHelper(parameter_manager, source, m_value_calculator,
165  m_parameters[5], m_parameters[6]);
166  case 8:
167  return createDependentParameterHelper(parameter_manager, source, m_value_calculator,
170  case 9:
171  return createDependentParameterHelper(parameter_manager, source, m_value_calculator,
174  case 10:
175  return createDependentParameterHelper(parameter_manager, source, m_value_calculator,
178  }
179  throw Elements::Exception() << "Dependent parameters can depend on maximum 10 other parameters";
180 }
181 
183  const SourceInterface& source, const std::vector<double>& param_values) const {
184  assert(param_values.size() == m_parameters.size());
185 
186  std::vector<double> result(param_values.size());
187  auto cs = source.getProperty<DetectionFrameCoordinates>().getCoordinateSystem();
188 
189  for (unsigned int i = 0; i < result.size(); i++) {
190 
191  auto f = [&](double x) {
192  auto params = param_values;
193  params[i] = x;
194  return m_value_calculator(cs, params);
195  };
196 
197 #if BOOST_VERSION >= 106700
198  result[i] = bmd::finite_difference_derivative(f, param_values[i]);
199 #else
200  // if boost's function is unavailable use our own function
201  result[i] = NumericalDerivative::centralDifference(f, param_values[i]);
202 #endif
203  }
204 
205  return result;
206 }
207 
209  const std::vector<double>& free_parameter_sigmas) const {
210  auto dependees = getDependees();
211  std::vector<double> values;
212 
213  for (auto& dependee : dependees) {
214  values.emplace_back(parameter_manager.getParameter(source, dependee)->getValue());
215  }
216 
217  double sigma = 0.0;
218  auto partial_derivatives = getPartialDerivatives(source, values);
219 
220  assert(dependees.size() == partial_derivatives.size());
221  for (unsigned int i = 0; i < partial_derivatives.size(); i++) {
222  auto dependee_sigma = dependees[i]->getSigma(parameter_manager, source, free_parameter_sigmas);
223  sigma += partial_derivatives[i] * partial_derivatives[i] * dependee_sigma * dependee_sigma;
224  }
225  sigma = sqrt(sigma);
226 
227  return sigma;
228 }
229 
230 }
static Elements::Logging logger
std::shared_ptr< DependentParameter< std::shared_ptr< EngineParameter > > > x
static Logging getLogger(const std::string &name="")
virtual double getValue() const
Class responsible for managing the parameters the least square engine minimizes.
void registerParameter(std::shared_ptr< EngineParameter > parameter)
Registers an EngineParameter to the EngineParameterManager.
std::shared_ptr< ModelFitting::BasicParameter > create(FlexibleModelFittingParameterManager &parameter_manager, ModelFitting::EngineParameterManager &engine_manager, const SourceInterface &source) const override
std::function< double(const std::shared_ptr< CoordinateSystem > &, const std::vector< double > &)> ValueFunc
std::vector< std::shared_ptr< FlexibleModelFittingParameter > > m_parameters
double getSigma(FlexibleModelFittingParameterManager &parameter_manager, const SourceInterface &source, const std::vector< double > &free_parameter_sigmas) const override
const std::vector< std::shared_ptr< FlexibleModelFittingParameter > > & getDependees() const
std::vector< double > getPartialDerivatives(const SourceInterface &source, const std::vector< double > &param_values) const
std::shared_ptr< ModelFitting::BasicParameter > create(FlexibleModelFittingParameterManager &parameter_manager, ModelFitting::EngineParameterManager &engine_manager, const SourceInterface &source) const override
double getSigma(FlexibleModelFittingParameterManager &parameter_manager, const SourceInterface &source, const std::vector< double > &free_parameter_sigmas) const override
double getInitialValue(const SourceInterface &source) const
std::shared_ptr< FlexibleModelFittingConverterFactory > m_converter_factory
std::shared_ptr< ModelFitting::BasicParameter > create(FlexibleModelFittingParameterManager &parameter_manager, ModelFitting::EngineParameterManager &engine_manager, const SourceInterface &source) const override
std::shared_ptr< ModelFitting::BasicParameter > getParameter(const SourceInterface &source, std::shared_ptr< const FlexibleModelFittingParameter > parameter) const
int getParameterIndex(std::shared_ptr< ModelFitting::BasicParameter > engine_parameter) const
static double centralDifference(std::function< double(double)> f, double x)
The SourceInterface is an abstract "source" that has properties attached to it.
const PropertyType & getProperty(unsigned int index=0) const
Convenience template method to call getProperty() with a more user-friendly syntax.
T emplace_back(T... args)
T move(T... args)
std::shared_ptr< DependentParameter< Parameters... > > createDependentParameter(typename DependentParameter< Parameters... >::ValueCalculator value_calculator, Parameters... parameters)
T size(T... args)
T sqrt(T... args)