NAGASH 0.9.8
Next Generation Analysis System
Loading...
Searching...
No Matches
TemplateFitter.cxx
Go to the documentation of this file.
1//***************************************************************************************
4//***************************************************************************************
5
7
8using namespace NAGASH;
9
65TemplateFitter::TemplateFitterFCN::TemplateFitterFCN(TH1D *_htarget, const std::vector<TH1D *> &vh, int _min_, int _max_)
66{
67 h_target = _htarget;
68 h_template = vh;
69 min = _min_;
70 max = _max_;
71}
72
73void TemplateFitter::TemplateFitterFCN::SetRelation(std::function<double(const std::vector<double> &, const std::vector<double> &)> cf,
74 std::function<double(const std::vector<double> &, const std::vector<double> &, const std::vector<double> &)> ef)
75{
76 contentfunction = cf;
77 errorfunction = ef;
78}
79
80double TemplateFitter::TemplateFitterFCN::operator()(const std::vector<double> &vpara) const
81{
82 double chi2 = 0;
83
84 std::vector<double> contents(h_template.size());
85 std::vector<double> errors(h_template.size());
86
87 bool use_user_defined_function = bool(contentfunction) && bool(contentfunction);
88
89 for (int i = min; i <= max; i++)
90 {
91 double BinContent = h_target->GetBinContent(i);
92 double BinError = pow(h_target->GetBinError(i), 2);
93
94 for (size_t j = 0; j < h_template.size(); j++)
95 {
96 contents[j] = h_template[j]->GetBinContent(i);
97 errors[j] = h_template[j]->GetBinError(i);
98 }
99
100 if (use_user_defined_function)
101 {
102 BinContent -= contentfunction(vpara, contents);
103 BinError += errorfunction(vpara, contents, errors);
104 }
105 else
106 {
107 for (size_t j = 0; j < h_template.size(); j++)
108 {
109 BinContent -= vpara[j] * h_template[j]->GetBinContent(i);
110 BinError += pow(vpara[j] * h_template[j]->GetBinError(i), 2);
111 }
112 }
113
114 if (BinError != 0) // avoid nan passed to chi2
115 chi2 += BinContent * BinContent / BinError;
116 }
117
118 return chi2;
119}
120
123{
124 ht = nullptr;
125 vh.clear();
126 sf.clear();
127 sferr.clear();
128 isfixed.clear();
129 chi2 = 0;
130}
131
134{
135 if (!h)
136 {
137 MSGUser()->StartTitle("TemplateFitter::SetTarget");
138 MSGUser()->MSG(MSGLevel::ERROR, "Target hist is NULL");
139 MSGUser()->EndTitle();
140 return;
141 }
142
143 ht = h;
144 FitRangeMin = 1;
145 FitRangeMax = ht->GetNbinsX();
146}
147
152void TemplateFitter::SetTemplate(TH1D *h, double SF, bool fix)
153{
154 if (!h)
155 {
156 MSGUser()->StartTitle("TemplateFitter::SetTemplate");
157 MSGUser()->MSG(MSGLevel::ERROR, "Template hist is NULL");
158 MSGUser()->EndTitle();
159 return;
160 }
161
162 vh.push_back(h);
163 sf.push_back(SF);
164 sfmin.push_back(-999);
165 sfmax.push_back(-1000);
166 sferr.push_back(0);
167 isfixed.push_back(fix);
168}
169
175void TemplateFitter::SetTemplate(TH1D *h, double SF, double SFMIN, double SFMAX)
176{
177 auto titleguard = MSGUser()->StartTitleWithGuard("TemplateFitter::SetTemplate");
178 if (!h)
179 {
180 MSGUser()->MSG(MSGLevel::ERROR, "Template hist is NULL");
181 return;
182 }
183
184 vh.push_back(h);
185 sf.push_back(SF);
186 if (SFMIN < SFMAX && SF < SFMAX && SF > SFMIN)
187 {
188 sfmin.push_back(SFMIN);
189 sfmax.push_back(SFMAX);
190 }
191 else
192 {
193 MSGUser()->MSG_WARNING("Input scale factor range is wrong, brought back to default");
194 sfmin.push_back(-999);
195 sfmax.push_back(-1000);
196 }
197 sferr.push_back(0);
198 isfixed.push_back(false);
199}
200
205void TemplateFitter::SetRelation(std::function<double(const std::vector<double> &, const std::vector<double> &)> cf,
206 std::function<double(const std::vector<double> &, const std::vector<double> &, const std::vector<double> &)> ef)
207{
208 this->contentfunction = cf;
209 this->errorfunction = ef;
210}
211
215void TemplateFitter::SetFitRange(int min, int max)
216{
217 if (min <= max && min > 0)
218 {
219 FitRangeMin = min;
220 FitRangeMax = max;
221 }
222 else
223 {
224 MSGUser()->StartTitle("TemplateFitter::SetFitRange");
225 MSGUser()->MSG(MSGLevel::ERROR, "Wrong fit range, brought back to default");
226 MSGUser()->EndTitle();
227 }
228}
229
231{
232 auto titleguard = MSGUser()->StartTitleWithGuard("TemplateFitter::Check");
233 if (!ht)
234 {
235 MSGUser()->MSG(MSGLevel::ERROR, "Target hist not set");
236 return false;
237 }
238
239 if (sf.size() < 1)
240 {
241 MSGUser()->MSG(MSGLevel::ERROR, "No template hist");
242 return false;
243 }
244
245 for (size_t i = 0; i < vh.size(); i++)
246 {
247 if (vh[i]->GetNbinsX() < FitRangeMax)
248 {
249 MSGUser()->MSG(MSGLevel::ERROR, "Wrong fit range or wrong input template hist");
250 return false;
251 }
252 }
253
254 return true;
255}
256
259{
260 auto titleguard = MSGUser()->StartTitleWithGuard("TemplateFitter::Fit");
261 if (!Check())
262 {
263 MSGUser()->MSG(MSGLevel::WARNING, "Fit won't proceed");
264 return;
265 }
266
270
271 ROOT::Minuit2::MnUserParameters upar;
272 for (size_t i = 0; i < sf.size(); i++)
273 {
274 TString name;
275 name.Form("sf_%lu", i);
276 if (sfmin[i] > sfmax[i])
277 {
278 upar.Add(name.Data(), sf[i], fabs(sf[i] / 5));
279 // upar.SetLowerLimit(i, 0);
280 }
281 else
282 {
283 upar.Add(name.Data(), sf[i], (sfmax[i] - sfmin[i]) / 5, sfmin[i], sfmax[i]);
284 }
285 if (isfixed[i])
286 upar.Fix(i);
287 }
288
289 // use simplex first
290 ROOT::Minuit2::MnSimplex simplex(fcn, upar, 2);
291 auto minsimplex = simplex(1e6);
292 // then use migrad
293 ROOT::Minuit2::MnMigrad migrad(fcn, minsimplex.UserState(), ROOT::Minuit2::MnStrategy(2));
294 auto minmigrad = migrad(1e6);
295
296 for (size_t i = 0; i < sf.size(); i++)
297 {
298 sf[i] = minmigrad.UserState().Value(i);
299 sferr[i] = minmigrad.UserState().Error(i);
300 }
301 chi2 = minmigrad.Fval();
302}
303
306double TemplateFitter::GetSF(uint64_t i)
307{
308 if (i < sf.size() && i >= 0)
309 {
310 return sf[i];
311 }
312 else
313 {
314 MSGUser()->StartTitle("TemplateFitter::GetSF");
315 MSGUser()->MSG(MSGLevel::ERROR, "No SF correspond to input number, return -1");
316 MSGUser()->EndTitle();
317 return -1;
318 }
319}
320
324{
325 if (i < sf.size() && i >= 0)
326 {
327 return sferr[i];
328 }
329 else
330 {
331 MSGUser()->StartTitle("TemplateFitter::GetSFError");
332 MSGUser()->MSG(MSGLevel::ERROR, "No SF correspond to input number, return -1");
333 MSGUser()->EndTitle();
334 return -1;
335 }
336}
337
340{
341 return chi2;
342}
double operator()(const std::vector< double > &) const override
TemplateFitterFCN(TH1D *, const std::vector< TH1D * > &, int, int)
void SetRelation(std::function< double(const std::vector< double > &, const std::vector< double > &)>, std::function< double(const std::vector< double > &, const std::vector< double > &, const std::vector< double > &)>)
void Fit()
Run the fit.
std::vector< double > sf
double GetSF(uint64_t i)
Get the scale factors for ith template.
double GetChi2()
Get the fit .
std::vector< double > sfmin
void SetFitRange(int min, int max)
Set the fit range.
std::vector< TH1D * > vh
void Clear()
Clear this tool.
double GetSFError(uint64_t i)
Get the uncertainty of the scale factors for ith template.
void SetTarget(TH1D *h)
Set the target histogram.
void SetTemplate(TH1D *h, double SF=1, bool fix=false)
Set the template histogram.
std::vector< bool > isfixed
std::function< double(const std::vector< double > &, const std::vector< double > &, const std::vector< double > &)> errorfunction
std::function< double(const std::vector< double > &, const std::vector< double > &)> contentfunction
std::vector< double > sferr
void SetRelation(std::function< double(const std::vector< double > &, const std::vector< double > &)>, std::function< double(const std::vector< double > &, const std::vector< double > &, const std::vector< double > &)>)
Set the relation between the target histogram and the template histograms. if not called,...
std::vector< double > sfmax
std::shared_ptr< MSGTool > MSGUser()
return the MSGTool inside.
Definition Tool.h:91