GRSISort "v4.0.0.5"
An extension of the ROOT analysis Framework
Loading...
Searching...
No Matches
TEfficiencyCalibration.cxx
Go to the documentation of this file.
2
3#include <iostream>
4#include "Globals.h"
5#include "TMath.h"
6#include "Math/Minimizer.h"
7
9{
10 if(fRelativeEffGraph == nullptr) {
11 fRelativeEffGraph = new TMultiGraph;
12 }
13 if(fAbsEffGraph == nullptr) {
14 fAbsEffGraph = new TMultiGraph;
15 }
16 Clear();
17}
18
19TEfficiencyCalibration::TEfficiencyCalibration(const char* name, const char* title)
20 : TNamed(name, title)
21{
22 if(fRelativeEffGraph == nullptr) {
23 fRelativeEffGraph = new TMultiGraph;
24 }
25 if(fAbsEffGraph == nullptr) {
26 fAbsEffGraph = new TMultiGraph;
27 }
28}
29
37
39 : TNamed(copy)
40{
41 copy.Copy(*this);
42}
43
44void TEfficiencyCalibration::Copy(TObject& copy) const
45{
46 static_cast<TEfficiencyCalibration&>(copy).fGraphMap = fGraphMap;
47 /* if(static_cast<TEfficiencyCalibration&>(copy).fRelativeEffGraph){
48 delete static_cast<TEfficiencyCalibration&>(copy).fRelativeEffGraph;
49 static_cast<TEfficiencyCalibration&>(copy).fRelativeEffGraph = nullptr; //This will be constructed later
50 }*/
51}
52
53void TEfficiencyCalibration::Print(Option_t*) const
54{
55 std::cout << "Graphs included: " << std::endl;
56 for(const auto& it : fGraphMap) {
57 std::cout << "Name: " << it.first << " N of points: " << it.second.GetN();
58 if(it.second.IsAbsolute()) {
59 std::cout << " Absolute calibration ";
60 }
61 std::cout << std::endl;
62 }
63 if(fRelativeFit != nullptr) {
64 std::cout << "Relative Fit: " << std::endl;
65 fRelativeFit->Print();
66 }
67 if(fAbsoluteFunc != nullptr) {
68 std::cout << "Absolute Fit: " << std::endl;
69 fAbsoluteFunc->Print();
70 }
71}
72
74{
75 fGraphMap.clear();
76 if(fRelativeFit != nullptr) {
77 fRelativeFit->Clear();
78 }
79 fFitting = false;
80}
81
83{
84 auto it = fGraphMap.insert(std::make_pair(name, graph));
85 if(!it.second) {
86 std::cout << "There is already a graph with the name " << name << " in this calibration, overwriting."
87 << std::endl;
88 it.first->second = graph;
89 }
90 if(graph.IsAbsolute()) {
91 fAbsEffGraph->Add(&(it.first->second)); // fill the multigraph with an actual pointer to the graph
92 } else {
93 fRelativeEffGraph->Add(&(it.first->second)); // fill the multigraph with an actual pointer to the graph
94 }
95 if(fRelativeFit != nullptr) {
96 delete fRelativeFit;
97 fRelativeFit = nullptr; // Clear this because it is nonsense now.
98 }
99}
100
102{
103 AddEfficiencyGraph(graph, graph.GetName());
104}
105
107{
108 fRelativeEffGraph->Draw(opt);
109 if(fAbsoluteFunc != nullptr) {
110 fAbsEffGraph->Draw("P");
111 // fAbsEffGraph->Draw(Form("%ssame",opt));
112 fAbsoluteFunc->Draw("same");
113 } else if(fRelativeFit != nullptr) {
114 fRelativeFit->Draw("same");
115 }
116}
117
119{
120 fRelativeEffGraph->Draw(opt);
121 if(fRelativeFit != nullptr) {
122 fRelativeFit->Draw("same");
123 }
124}
125
127{
128 fAbsEffGraph->Draw(opt);
129 if(fAbsoluteFunc != nullptr) {
130 fAbsoluteFunc->Draw("same");
131 }
132}
133
135{
136
137 // Make an initial graph scaling guess
138 // Eventually loop over more graphs for a better guess
139
140 // We choose to not scale the first graph in the list
141 TList* graph_list = fRelativeEffGraph->GetListOfGraphs();
142
143 // We want to loop through the list and find the best scale factor
144 for(int graph_idx = 1; graph_idx < graph_list->GetSize();
145 ++graph_idx) { // Start at 1 because we don't want to change 0
146 Double_t closest_dist = 99999.;
147 Int_t closest_loop_idx = 0;
148 Int_t closest_fixed_idx = 0;
149 auto* fixed_graph = static_cast<TEfficiencyGraph*>(graph_list->At(0));
150 auto* loop_graph = static_cast<TEfficiencyGraph*>(graph_list->At(graph_idx));
151 Double_t* fixed_x = fixed_graph->GetX();
152 for(int i = 0; i < fixed_graph->GetN(); ++i) {
153 if(loop_graph->FindDistToClosestPointX(fixed_x[i]) < closest_dist) {
154 closest_dist = loop_graph->FindDistToClosestPointX(fixed_x[i]);
155 closest_fixed_idx = i;
156 closest_loop_idx = loop_graph->FindClosestPointX(fixed_x[i]);
157 }
158 }
159 // We have now found the two closest points, scale them
160 std::cout << "Scaling " << graph_idx << " graph by "
161 << fixed_graph->GetY()[closest_fixed_idx] / loop_graph->GetY()[closest_loop_idx] << std::endl;
162 loop_graph->Scale((fixed_graph->GetY()[closest_fixed_idx]) / (loop_graph->GetY()[closest_loop_idx]));
163 }
164}
165
166TFitResultPtr TEfficiencyCalibration::Fit(Option_t*)
167{
168 // This fits the relative efficiency curve
169 UInt_t n_rel_graphs = fRelativeEffGraph->GetListOfGraphs()->GetSize();
170 delete fRelativeFit;
171 fRelativeFit = new TF1("fRelativeFit", this, &TEfficiencyCalibration::PhotoPeakEfficiency, 0, 8000, 8 + n_rel_graphs, "TEfficiencyCalibration", "PhotoPeakEfficiency");
172
173 // Start by naming the parameters of the fit
174 for(int mapIdx = 0; mapIdx < static_cast<int>(fGraphMap.size()); ++mapIdx) {
175 fRelativeFit->SetParName(mapIdx, Form("Scale_%d", mapIdx));
176 if(mapIdx == 0) {
177 fRelativeFit->FixParameter(mapIdx, 1.0);
178 } else {
179 fRelativeFit->SetParameter(mapIdx, 1.0);
180 fRelativeFit->SetParLimits(mapIdx, 0.1, 10.);
181 }
182 }
183
184 ScaleGuess();
185
186 // Make initial guesses for the fit parameters
187 for(Int_t i = 0; i < 8; ++i) {
188 fRelativeFit->SetParName(i + n_rel_graphs, Form("a_%d", i));
189 fRelativeFit->SetParameter(i + n_rel_graphs, 0.00001);
190 }
191 fRelativeFit->SetParameter(n_rel_graphs, 5.0);
192 // We fix the higher order parameters to get to the real minimum more easily
193 fRelativeFit->FixParameter(n_rel_graphs + 4, 0.0);
194 fRelativeFit->FixParameter(n_rel_graphs + 5, 0.0);
195 fRelativeFit->FixParameter(n_rel_graphs + 6, 0.0);
196 fRelativeFit->FixParameter(n_rel_graphs + 7, 0.0);
197 fRelativeFit->Print();
198
199 // Turn the fitting flag on so that we scale graphs properly.
200 fFitting = true;
201
202 // Fix scaling
203 for(size_t i = 1; i < n_rel_graphs; ++i) {
204 fRelativeFit->FixParameter(i, fRelativeFit->GetParameter(i));
205 }
206
207 // Slowly Add parameters back
209 fRelativeFit->ReleaseParameter(n_rel_graphs + 5);
211 fRelativeFit->ReleaseParameter(n_rel_graphs + 6);
213 fRelativeFit->ReleaseParameter(n_rel_graphs + 7);
214
215 // Fit only the very last parameter
216 for(size_t i = 0; i < 7 + n_rel_graphs; ++i) {
217 fRelativeFit->FixParameter(i, fRelativeFit->GetParameter(i));
218 }
220
221 fRelativeFit->SetRange(200, 8000);
222 // Fit the scaling factor again, fix everything else
223 for(size_t i = n_rel_graphs; i < n_rel_graphs + 7; ++i) {
224 fRelativeFit->FixParameter(i, fRelativeFit->GetParameter(i));
225 }
227
228 fRelativeFit->SetRange(0, 8000);
229 // Fix Scale factors and redo fit of other parameters
230 for(size_t i = n_rel_graphs; i < 7 + n_rel_graphs; ++i) {
231 fRelativeFit->ReleaseParameter(i);
232 }
233
235
236 // ADDED TO MAKE WORK
237 // We fix the higher order parameters to get to the real minimum more easily
238 // fRelativeFit->FixParameter(n_rel_graphs+0,-4.16);
239 fRelativeFit->FixParameter(n_rel_graphs + 0, -4.25);
240 fRelativeFit->FixParameter(n_rel_graphs + 1, 4.92);
241 fRelativeFit->FixParameter(n_rel_graphs + 2, -6.56E-1);
242 fRelativeFit->FixParameter(n_rel_graphs + 3, 1.33E-2);
243 fRelativeFit->FixParameter(n_rel_graphs + 4, -1.54E-3);
244 fRelativeFit->FixParameter(n_rel_graphs + 5, 2.01E-4);
245 fRelativeFit->FixParameter(n_rel_graphs + 6, 8.36E-5);
246 fRelativeFit->FixParameter(n_rel_graphs + 7, -8.30E-6);
247
248 // Do the real fit with all of the parameters
249 TFitResultPtr res = fRelativeEffGraph->Fit(fRelativeFit, "SR");
250
251 // Turn fitting flag off for drawing
252 fFitting = false;
253
254 // Draw The TF1
255 fRelativeFit->Draw("same");
256
257 // Update the graphs
258 for(int i = 0; i < fRelativeEffGraph->GetListOfGraphs()->GetSize(); ++i) {
259 (static_cast<TEfficiencyGraph*>(fRelativeEffGraph->GetListOfGraphs()->At(i)))
260 ->Scale(fRelativeFit->GetParameter(i));
261 }
262
263 return res;
264}
265
266Double_t TEfficiencyCalibration::PhotoPeakEfficiency(Double_t* x, Double_t* par) // NOLINT(readability-non-const-parameter)
267{
268
269 Int_t closest_graph = 0;
270 Double_t dist_to_closest = 99999.;
271 if(fFitting) {
272 TList* gList = fRelativeEffGraph->GetListOfGraphs();
273 for(Int_t i = 0; i < gList->GetSize(); ++i) {
274 if((static_cast<TEfficiencyGraph*>(gList->At(i)))->FindDistToClosestPointX(x[0]) < dist_to_closest) {
275 dist_to_closest = (static_cast<TEfficiencyGraph*>(gList->At(i)))->FindDistToClosestPointX(x[0]);
276 closest_graph = i;
277 }
278 }
279 }
280
281 double sum = 0.0;
282 for(int i = 0; i < 9; ++i) {
283 sum += par[i + fRelativeEffGraph->GetListOfGraphs()->GetSize()] * TMath::Power(TMath::Log(x[0]), i);
284 }
285 if(fFitting) {
286 return TMath::Exp(sum) / par[closest_graph];
287 }
288 return TMath::Exp(sum);
289}
290
291Double_t TEfficiencyCalibration::AbsoluteEfficiency(Double_t* x, Double_t* par) // NOLINT(readability-non-const-parameter)
292{
293 double sum = 0.0;
294 for(int i = 0; i < 9; ++i) {
295 sum += par[i + 1] * TMath::Power(TMath::Log(x[0]), i);
296 }
297 return par[0] * TMath::Exp(sum);
298}
299
301{
302 if((fAbsEffGraph->GetListOfGraphs()->GetSize() != 0) && (fRelativeFit != nullptr)) {
303 if(fAbsoluteFunc == nullptr) {
304 fAbsoluteFunc = new TF1("fAbsoluteFunc", this, &TEfficiencyCalibration::AbsoluteEfficiency, 0, 8000, 9,
305 "TEfficiencyCalibration", "AbsoluteEfficiency");
306 }
307 fAbsoluteFunc->SetParName(0, "Scale");
308 for(int i = 0; i < 8; ++i) {
309 fAbsoluteFunc->SetParName(i + 1, Form("a%d", i));
310 fAbsoluteFunc->SetParameter(i + 1,
311 fRelativeFit->GetParameter(i + fRelativeEffGraph->GetListOfGraphs()->GetSize()));
312 fAbsoluteFunc->SetParError(i + 1,
313 fRelativeFit->GetParError(i + fRelativeEffGraph->GetListOfGraphs()->GetSize()));
314 }
315
316 // we need to find the average amount that we must scale the relative efficiency fit by in order to have it line
317 // up with the absolute efficiency data points.
318 TIter next(fAbsEffGraph->GetListOfGraphs());
319 Double_t w_avg_numer = 0.0;
320 Double_t w_avg_denom = 0.0;
321 Double_t semi_w_uncert = 0.0;
322 while(auto* abs_graph = static_cast<TEfficiencyGraph*>(next())) {
323 Double_t* y_val = abs_graph->GetY();
324 Double_t* ey_val = abs_graph->GetEY();
325 Double_t* x_val = abs_graph->GetX();
326 for(int i = 0; i < abs_graph->GetN(); ++i) {
327 Double_t scale = y_val[i] / fRelativeFit->Eval(x_val[i]);
328 w_avg_numer += scale / TMath::Power(ey_val[i], 2.0);
329 w_avg_denom += 1. / TMath::Power(ey_val[i], 2.0);
330 }
331 semi_w_uncert += 1. / TMath::Power(ey_val[0] / y_val[0], 2.0);
332 }
333
334 Double_t w_avg = w_avg_numer / w_avg_denom; // This is how much we should scale everything by
335 // Set the parameter and uncertainty based on the scale factor
336 fAbsoluteFunc->FixParameter(0, w_avg);
337 // For the error we assume that each absolute efficiency source error is entirely systematic in Activity.
338 fAbsoluteFunc->SetParError(0, TMath::Sqrt(1. / semi_w_uncert) * w_avg);
339
340 // Scale all of the data points now in the relative graph
341 for(int i = 0; i < fRelativeEffGraph->GetListOfGraphs()->GetSize(); ++i) {
342 (static_cast<TEfficiencyGraph*>(fRelativeEffGraph->GetListOfGraphs()->At(i)))->Scale(w_avg);
343 }
344
345 return true;
346 }
347
348 return false;
349}
350
351Double_t TEfficiencyCalibration::GetEfficiency(const Double_t& eng)
352{
353 if(fAbsoluteFunc != nullptr) {
354 return fAbsoluteFunc->Eval(eng);
355 }
356
357 return -1000.0;
358}
359
360Double_t TEfficiencyCalibration::GetEfficiencyErr(const Double_t& eng)
361{
362 if(fAbsoluteFunc != nullptr) {
363 // partial derivative * error all squared for each parameter
364 // Function looks like Const*exp^(a0 + a1*lnE + a2*(lnE)^2 +....)
365 // so exp term shows up in every derivative
366 Double_t exp_term = 0.0;
367 for(int i = 0; i < 8; ++i) {
368 exp_term += fAbsoluteFunc->GetParameter(i + 1) * TMath::Power(TMath::Log(eng), i);
369 }
370 exp_term = TMath::Exp(exp_term);
371 // Now do the derivatives which have a pattern, and say the error in E is negligible
372 Double_t sum = TMath::Power(exp_term * fAbsoluteFunc->GetParError(0), 2.0);
373 for(int i = 0; i < 8; ++i) {
374 sum += TMath::Power(fAbsoluteFunc->GetParameter(0) * exp_term * TMath::Power(TMath::Log(eng), i) *
375 fAbsoluteFunc->GetParError(i + 1),
376 2.0);
377 }
378 return TMath::Sqrt(sum);
379 }
380
381 return -1000.0;
382}
void AddEfficiencyGraph(const TEfficiencyGraph &graph)
Double_t GetEfficiencyErr(const Double_t &eng)
void Print(Option_t *opt="") const override
TFitResultPtr Fit(Option_t *opt="")
void Draw(Option_t *opt="") override
void DrawAbsolute(Option_t *opt="")
void Clear(Option_t *opt="") override
std::map< const char *, TEfficiencyGraph > fGraphMap
Double_t AbsoluteEfficiency(Double_t *x, Double_t *par)
Double_t GetEfficiency(const Double_t &eng)
void Copy(TObject &copy) const override
void DrawRelative(Option_t *opt="")
Double_t PhotoPeakEfficiency(Double_t *x, Double_t *par)
bool IsAbsolute() const