SourceXtractorPlusPlus  0.10
Please provide a description of the project.
DataVsModelResiduals.icpp
Go to the documentation of this file.
1 /** Copyright © 2019 Université de Genève, LMU Munich - Faculty of Physics, IAP-CNRS/Sorbonne Université
2  *
3  * This library is free software; you can redistribute it and/or modify it under
4  * the terms of the GNU Lesser General Public License as published by the Free
5  * Software Foundation; either version 3.0 of the License, or (at your option)
6  * any later version.
7  *
8  * This library is distributed in the hope that it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
11  * details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this library; if not, write to the Free Software Foundation, Inc.,
15  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16  */
17 /**
18  * @file DataVsModelResiduals.icpp
19  * @date August 20, 2015
20  * @author Nikolaos Apostolakos
21  */
22 
23 namespace ModelFitting {
24 
25 template <typename DataType, typename ModelType, typename WeightType, typename Comparator>
26 DataVsModelResiduals<DataType,ModelType,WeightType,Comparator>::DataVsModelResiduals(
27  DataType data, ModelType model, WeightType weight, Comparator comparator)
28  : m_data{std::move(data)}, m_model{std::move(model)}, m_weight{std::move(weight)},
29  m_comparator(std::move(comparator)), m_residual_no{DataTraits::size(m_data)} {
30  if (DataTraits::size(m_data) != ModelTraits::size(m_model)) {
31  throw Elements::Exception() << "Data size (" << DataTraits::size(m_data)
32  << ") is different than model size (" << ModelTraits::size(m_model) << ")";
33  }
34  if (DataTraits::size(m_data) != WeightTraits::size(m_weight)) {
35  throw Elements::Exception() << "Data size (" << DataTraits::size(m_data)
36  << ") is different than weight size (" << WeightTraits::size(m_weight) << ")";
37  }
38 }
39 
40 template <typename DataType, typename ModelType, typename WeightType, typename Comparator>
41 DataVsModelResiduals<DataType,ModelType,WeightType,Comparator>::~DataVsModelResiduals() = default;
42 
43 template <typename DataType, typename ModelType, typename WeightType, typename Comparator>
44 std::size_t DataVsModelResiduals<DataType,ModelType,WeightType,Comparator>::numberOfResiduals() const {
45  return m_residual_no;
46 }
47 
48 template <typename DataType, typename ModelType, typename WeightType, typename Comparator>
49 void DataVsModelResiduals<DataType,ModelType,WeightType,Comparator>::populateResidualBlock(IterType output_iter) {
50  auto data_iter = DataTraits::begin(m_data);
51  auto model_iter = ModelTraits::begin(m_model);
52  auto weight_iter = WeightTraits::begin(m_weight);
53 // double test = 0;
54 // static double diff = 0;
55  for (; data_iter!=DataTraits::end(m_data); ++data_iter, ++model_iter, ++weight_iter, ++output_iter) {
56  *output_iter = m_comparator(*data_iter, *model_iter, *weight_iter);
57 // test += *output_iter;
58  }
59 // std::cout << test << " -- " << test-diff << "\n";
60 // diff = test;
61 }
62 
63 // NOTE TO DEVELOPERS:
64 //
65 // The following factory function looks (and is) complicated, but it greatly
66 // simplifies the code using the library. For example, using the factory method,
67 // the code for creating a DataVsModelResiduals looks like:
68 //
69 // std::vector<double> data = ...;
70 // std::vector<double> model = ...;
71 // std::vector<double> weights = ...;
72 // auto res_prov = createDataVsModelResiduals(data, model, weights, ChiSquareComparator{});
73 //
74 // The equivalent command when using directly the constructor would be:
75 //
76 // std::vector<double> data = ...;
77 // std::vector<double> model = ...;
78 // std::vector<double> weights = ...;
79 // unique_ptr<DataVsModelResiduals<std::vector<double>, std::vector<double>,
80 // std::vector<double>, ChiSquareComparator>> res_prov {
81 // new DataVsModelResiduals<std::vector<double>, std::vector<double>,
82 // std::vector<double>, ChiSquareComparator> {
83 // y_data, model, weight, ChiSquareComparator{}
84 // }
85 // };
86 //
87 // The above shows the importance of the existence of this factory. Here are
88 // some tips, to help you understand how the function works:
89 //
90 // - The function perfect-forwards its parameters to the constructor, so it can
91 // be the exact equivalent with calling the constructor, regardless the
92 // r-valueness or l-valueness of the parameters. If you don't know what the
93 // perfect forwarding is, search the internet for a good explanation before
94 // you continue trying to understand this code.
95 //
96 // - The template parameters of the factory method are NOT the same with the ones
97 // of the DataVsModelResiduals object being created. This is a result of the
98 // use of the perfect forwarding. More precisely, the template types of the
99 // factory method are lvalue or rvalue REFERENCES (which is how perfect
100 // forwarding works), when the template types of the DataVsModelResiduals are
101 // the actual types (and no references to them).
102 //
103 // - The "typename std::remove_reference<...>::type" (which is used a lot bellow)
104 // simply removes any reference from the type, creating the proper template
105 // parameter for the DataVsModelResiduals class. The keyword "typename" has to
106 // be used because, during the first passage, the compiler will fail to recognize
107 // that the "std::remove_reference<...>::type" is an existing type (because
108 // it contains a template parameter itself).
109 //
110 // I hope the above will help you to understand how the factory method works.
111 template <typename DataType, typename ModelType, typename WeightType, typename Comparator>
112 std::unique_ptr<DataVsModelResiduals<typename std::remove_reference<DataType>::type,
113  typename std::remove_reference<ModelType>::type,
114  typename std::remove_reference<WeightType>::type,
115  typename std::remove_reference<Comparator>::type>
116  > createDataVsModelResiduals(DataType&& data, ModelType&& model,
117  WeightType&& weight, Comparator&& comparator) {
118  return std::unique_ptr<DataVsModelResiduals<typename std::remove_reference<DataType>::type,
119  typename std::remove_reference<ModelType>::type,
120  typename std::remove_reference<WeightType>::type,
121  typename std::remove_reference<Comparator>::type>
122  > {
123  new DataVsModelResiduals<typename std::remove_reference<DataType>::type,
124  typename std::remove_reference<ModelType>::type,
125  typename std::remove_reference<WeightType>::type,
126  typename std::remove_reference<Comparator>::type> {
127  std::forward<DataType>(data), std::forward<ModelType>(model),
128  std::forward<WeightType>(weight), std::forward<Comparator>(comparator)
129  }
130  };
131 }
132 
133 } // end of namespace ModelFitting