GRSISort "v4.0.0.5"
An extension of the ROOT analysis Framework
Loading...
Searching...
No Matches
TDecay.cxx
Go to the documentation of this file.
1#include "TDecay.h"
2
3#include <utility>
4
5#include "Math/Minimizer.h"
6#include "Math/Factory.h"
7#include "Math/Functor.h"
8#include "TCanvas.h"
9#include "TBuffer.h"
10#include "TLMFitter.h"
11
12UInt_t TSingleDecay::fCounter = 0;
14
16{
17 /// This draws the individual components on the current canvas
18 fDecay->DrawComponents("same");
19}
20
22{
23 /// This tells the TDecayFit which TVirtualDecay it belongs to
24 fDecay = decay;
25}
26
27void TDecayFit::Print(Option_t* opt) const
28{
29 /// This prints the parameters of the fit (decay rate, intensities, etc...)
30 TF1::Print(opt);
31 std::cout << "fDecay = " << fDecay << std::endl;
32}
33
35{
36 return fDecay;
37}
38
39TFitResultPtr TDecayFit::Fit(TH1* hist, Option_t* opt)
40{
41 if(hist == nullptr) {
42 return 0;
43 }
44 TFitResultPtr tmpres = hist->Fit(this, opt);
46 // Might be able to copy the style over to the new clone for the residuals.
47 // Will take a look at this later
48 // fDecay->Update();
49 // DrawClone("same");
50 Draw("same");
51 return tmpres;
52}
53
55{
56 fResiduals.SetMarkerStyle(20); // Filled circle
57 fResiduals.SetMarkerSize(0.6);
58 fResiduals.SetTitle("Residuals");
59}
60
62{
63 const Size_t oldmarker_size = fResiduals.GetMarkerSize();
64 const Color_t oldmarker_color = fResiduals.GetMarkerColor();
65 const Style_t oldmarker_style = fResiduals.GetMarkerStyle();
66
67 // Clear the data points from the old TGraph
68 for(int i = 0; i < fResiduals.GetN(); ++i) {
69 fResiduals.RemovePoint(i);
70 }
71
72 Double_t xlow = 0.;
73 Double_t xhigh = 0.;
74 GetRange(xlow, xhigh);
75 Int_t nbins = hist->GetXaxis()->GetNbins();
76
77 for(int i = 0; i < nbins; ++i) {
78 if((hist->GetBinCenter(i) <= xlow) || (hist->GetBinCenter(i) >= xhigh)) {
79 continue;
80 }
81 // This might not be correct for Poisson statistics.
82 Double_t res = (hist->GetBinContent(i) - Eval(hist->GetBinCenter(i))) /
83 hist->GetBinError(i); /// GetHist()->GetBinError(i));// + GetParameter("Height") + 10.;
84 Double_t bin = hist->GetBinCenter(i);
85 fResiduals.SetPoint(i, bin, res);
86 }
87
88 fResiduals.SetMarkerSize(oldmarker_size);
89 fResiduals.SetMarkerColor(oldmarker_color);
90 fResiduals.SetMarkerStyle(oldmarker_style);
91}
92
94{
95 if(fResiduals.GetN() != 0) {
96 new TCanvas;
97 fResiduals.Draw("AP");
98 } else {
99 std::cout << "Residuals not set yet" << std::endl;
100 }
101}
102
103void TVirtualDecay::DrawComponents(Option_t* opt, Bool_t)
104{
105 std::cout << "Draw components has not been set in " << ClassName() << std::endl;
106 Draw(Form("same%s", opt));
107}
108
109TSingleDecay::TSingleDecay(TSingleDecay* parent, Double_t tlow, Double_t thigh)
110 : fDetectionEfficiency(1.0)
111{
112 if(parent != nullptr) {
113 fParent = parent;
115 // See if the decay chain makes sense.
116 TSingleDecay* curParent = parent;
117 UInt_t gencounter = 1;
118 while(curParent != nullptr) {
119 ++gencounter;
120 fFirstParent = curParent;
121 curParent = curParent->GetParentDecay();
122 }
123
124 fGeneration = gencounter;
125 } else {
126 fFirstParent = this;
127 fGeneration = 1;
128 }
129 // This will potentially leak with ROOT IO, shouldnt be a big deal. Might come back to this later
130 fDecayFunc = new TDecayFit(Form("decayfunc_gen%d", fGeneration), this, &TSingleDecay::ActivityFunc, 0, 10, 2,
131 "TSingleDecay", "ActivityFunc");
132 fDecayFunc->SetDecay(this);
133 fDecayFunc->SetParameters(fFirstParent->GetIntensity(), 0.0);
134 fDecayFunc->SetParNames("Intensity", "DecayRate");
135
136 fTotalDecayFunc = new TDecayFit(Form("totaldecayfunc_gen%d", fGeneration), this, &TSingleDecay::ActivityFunc, 0, 10,
137 fGeneration + 1, "TSingleDecay", "ActivityFunc");
140 if(fFirstParent != this) {
141 FixIntensity(0);
142 }
143
144 SetRange(tlow, thigh);
145 fUnId = fCounter;
146 fCounter++;
147
148 SetName("Decay");
149}
150
151TSingleDecay::TSingleDecay(UInt_t generation, TSingleDecay* parent, Double_t tlow, Double_t thigh)
152 : fDetectionEfficiency(1.0)
153{
154 if(parent != nullptr) {
155 fParent = parent;
157 // See if the decay chain makes sense.
158 TSingleDecay* curParent = parent;
159 UInt_t gencounter = 2;
160 for(UInt_t i = 0; i < generation; ++i) {
161 if(curParent->GetParentDecay() != nullptr) {
162 curParent = parent->GetParentDecay();
163 ++gencounter;
164 } else {
165 fFirstParent = curParent;
166 }
167 }
168 if(gencounter != generation) {
169 std::cout << "Generation numbers do not make sense" << std::endl;
170 }
171 }
172 if(generation == 1) {
173 fFirstParent = this;
174 }
175
176 fGeneration = generation;
177
178 fDecayFunc = new TDecayFit("tmpname", this, &TSingleDecay::ActivityFunc, 0, 10, 2, "TSingleDecay", "ActivityFunc");
179 fDecayFunc->SetDecay(this);
180 fDecayFunc->SetParameters(fFirstParent->GetIntensity(), 0.0);
181 fDecayFunc->SetParNames("Intensity", "DecayRate");
182
183 fTotalDecayFunc = new TDecayFit("tmpname", this, &TSingleDecay::ActivityFunc, 0, 10, fGeneration + 1, "TSingleDecay",
184 "ActivityFunc");
187 if(fFirstParent != this) {
188 FixIntensity(0);
189 }
190
191 SetName("");
192 SetRange(tlow, thigh);
193 fUnId = fCounter;
194 fCounter++;
195
196 SetName("Decay");
197}
198
200{
201 // if(fDecayFunc) delete fDecayFunc;
202 // if(fTotalDecayFunc) delete fTotalDecayFunc;
203
204 fDecayFunc = nullptr;
205 fTotalDecayFunc = nullptr;
206}
207
208void TSingleDecay::SetName(const char* name)
209{
210 TNamed::SetName(name);
211 fDecayFunc->SetName(Form("%s_df_gen%d", name, fGeneration));
212 fTotalDecayFunc->SetName(Form("%s_tdf_gen%d", name, fGeneration));
213}
214
216{
217 /// Sets the total fit function to know about the other parmaters in the decay chain.
218 Double_t low_limit = 0.;
219 Double_t high_limit = 0.;
220 // We need to include the fact that we have parents and use that TF1 to perform the fit.
221 fTotalDecayFunc->SetParameter(0, fFirstParent->GetIntensity());
222 fTotalDecayFunc->SetParNames("Intensity", "DecayRate1");
223 fFirstParent->GetDecayFunc()->GetParLimits(0, low_limit, high_limit);
224 fTotalDecayFunc->SetParLimits(0, low_limit, high_limit);
225 // Now we need to get the parameters for each of the parents
226 Int_t parCounter = 1;
227 TSingleDecay* curDecay = fFirstParent;
228 while(curDecay != nullptr) {
229 fTotalDecayFunc->SetParameter(parCounter, curDecay->GetDecayRate());
230 fTotalDecayFunc->SetParName(parCounter, Form("DecayRate%d", parCounter));
231 curDecay->GetDecayFunc()->GetParLimits(1, low_limit, high_limit);
232 if(low_limit != 0 && high_limit != 0) {
233 fTotalDecayFunc->SetParLimits(parCounter, low_limit, high_limit);
234 }
235 ++parCounter;
236 curDecay = curDecay->GetDaughterDecay();
237 }
238 UpdateDecays();
239}
240
242{
243 /// Updates the other decays in the chain to know that they have potential updates.
244 Double_t low_limit = 0.;
245 Double_t high_limit = 0.;
246 // The current (this) decay we are on is the one that is assumed to be the most recently changed.
247 // We will first update it's total decay function
248
249 // Now update the halflives of all the total decay functions.
250 TSingleDecay* curDecay = fFirstParent;
251 while(curDecay != nullptr) {
252 GetDecayFunc()->GetParLimits(0, low_limit, high_limit);
253 curDecay->fTotalDecayFunc->SetParameter(0, GetIntensity());
254 curDecay->fTotalDecayFunc->SetParLimits(0, low_limit, high_limit);
255 // curDecay->fDecayFunc->SetParameter(0,GetIntensity());
256 // curDecay->fDecayFunc->SetParLimits(0,low_limit,high_limit);
257 curDecay->fDecayFunc->SetParameter(0, GetIntensity());
258 curDecay->fDecayFunc->SetParLimits(0, low_limit, high_limit);
259 fDecayFunc->GetParLimits(0, low_limit, high_limit);
260 curDecay->fTotalDecayFunc->SetParLimits(0, low_limit, high_limit);
261
262 curDecay->fTotalDecayFunc->SetParameter(0, GetIntensity());
263
264 curDecay->fTotalDecayFunc->SetParameter(GetGeneration(), GetDecayRate());
265 fDecayFunc->GetParLimits(1, low_limit, high_limit);
266 curDecay->fTotalDecayFunc->SetParLimits(GetGeneration(), low_limit, high_limit);
267 curDecay = curDecay->GetDaughterDecay();
268 }
269}
270
271void TSingleDecay::SetHalfLifeLimits(const Double_t& low, const Double_t& high)
272{
273 if(low == 0) {
274 fDecayFunc->SetParLimits(1, std::log(2) / high, 1e30);
275 }
276
277 fDecayFunc->SetParLimits(1, std::log(2) / high, std::log(2) / low);
278 // Tell this info to the rest of the decays
279 UpdateDecays();
280}
281
282void TSingleDecay::SetIntensityLimits(const Double_t& low, const Double_t& high)
283{
284 fFirstParent->fDecayFunc->SetParLimits(0, low, high);
285 UpdateDecays();
286}
287
288void TSingleDecay::SetDecayRateLimits(const Double_t& low, const Double_t& high)
289{
290 fDecayFunc->SetParLimits(1, low, high);
291 UpdateDecays();
292}
293
294void TSingleDecay::GetHalfLifeLimits(Double_t& low, Double_t& high) const
295{
296 fDecayFunc->GetParLimits(1, high, low); // This gets the decay rates, not the half-life.
297 if(low == 0) {
298 low = 0.000000000001;
299 }
300 if(high == 0) {
301 high = 0.000000000001;
302 }
303 low = std::log(2) / low;
304 high = std::log(2) / high;
305}
306
307void TSingleDecay::GetIntensityLimits(Double_t& low, Double_t& high) const
308{
309 fFirstParent->fDecayFunc->GetParLimits(0, low, high);
310}
311
312void TSingleDecay::GetDecayRateLimits(Double_t& low, Double_t& high) const
313{
314 fDecayFunc->GetParLimits(1, low, high);
315}
316
321
326
327void TSingleDecay::Draw(Option_t* option)
328{
330 fTotalDecayFunc->Draw(option);
331}
332
333Double_t TSingleDecay::Eval(Double_t t)
334{
335 /// Evaluates the activity at a given time, t
337 return fTotalDecayFunc->Eval(t);
338}
339
340Double_t TSingleDecay::EvalPar(const Double_t* x, const Double_t* par)
341{
342 /// Evaluates the activity at a given time t using parameters par.
343 fTotalDecayFunc->InitArgs(x, par);
344 return fTotalDecayFunc->EvalPar(x, par);
345}
346
347Double_t TSingleDecay::ActivityFunc(Double_t* dim, Double_t* par) // NOLINT(readability-non-const-parameter)
348{
349 /// The general function for a decay chain
350 /// par[0] is the intensity
351 /// par[1*i] is the activity
352 Double_t result = 1.0;
353 UInt_t gencounter = 0;
354 Double_t tlow = 0.;
355 Double_t thigh = 0.;
356 fTotalDecayFunc->GetRange(tlow, thigh);
357 Double_t t = dim[0] - tlow;
358 TSingleDecay* curDecay = this;
359 // Compute the first multiplication
360 while(curDecay != nullptr) {
361 ++gencounter;
362 // par[Generation] gets the decay rate for that decay since the parameters are stored
363 // as [intensity, decayrate1,decayrate2,...]
364 result *= par[curDecay->GetGeneration()];
365
366 curDecay = curDecay->GetParentDecay();
367 }
368 if(gencounter != fGeneration) {
369 std::cout << "We have Problems!" << std::endl;
370 return 0.0;
371 }
372 // Multiply by the initial intensity of the initial parent.
373 result *= par[0] / par[1];
374 // Now we need to deal with the second term
375 Double_t sum = 0.0;
376 curDecay = this;
377 while(curDecay != nullptr) {
378 Double_t denom = 1.0;
379 TSingleDecay* denomDecay = this;
380 while(denomDecay != nullptr) {
381 if(denomDecay != curDecay) {
382 // This term has problems if two or more rates are very similar. Will have to put a taylor expansion in here
383 // if this problem comes up. I believe the solution to this also depends on the number of nuclei in the
384 // chain
385 // that have similar rates. I think either of these issues is fairly rare, so I'll fix it when it comes up.
386 denom *= par[denomDecay->GetGeneration()] - par[curDecay->GetGeneration()];
387 }
388 denomDecay = denomDecay->GetParentDecay();
389 }
390
391 sum += TMath::Exp(-par[curDecay->GetGeneration()] * t) / denom;
392
393 curDecay = curDecay->GetParentDecay();
394 }
395 result *= sum;
396
397 return result * GetEfficiency();
398}
399
400TFitResultPtr TSingleDecay::Fit(TH1* fithist, Option_t* opt)
401{
402 ROOT::Math::MinimizerOptions::SetDefaultMinimizer("Minuit2", "Combination");
403 TVirtualFitter::SetPrecision(1.0e-10);
404 TVirtualFitter::SetMaxIterations(10000);
405 Int_t parCounter = 1;
406 TSingleDecay* curDecay = fFirstParent;
408 // TFitResultPtr fitres = fithist->Fit(fTotalDecayFunc,Form("%sWLRS",opt));
409 TFitResultPtr fitres = fTotalDecayFunc->Fit(fithist, Form("%sWLRS", opt));
410 Double_t chi2 = fitres->Chi2();
411 Double_t ndf = fitres->Ndf(); // This ndf needs to be changed by a weighted poisson.
412
413 std::cout << "Chi2/ndf = " << chi2 / ndf << std::endl;
414
415 // Now copy the fits back to the appropriate nuclei.
416 fFirstParent->SetIntensity(fTotalDecayFunc->GetParameter(0));
418 // Now we need to set the parameters for each of the parents
419 while(curDecay != nullptr) {
420 curDecay->SetDecayRate(fTotalDecayFunc->GetParameter(parCounter));
421 curDecay->SetDecayRateError(fTotalDecayFunc->GetParError(parCounter));
422 curDecay = curDecay->GetDaughterDecay();
423 ++parCounter;
424 }
425
426 return fitres;
427}
428
430{
431 FixHalfLife();
432 FixIntensity();
433}
434
440
441void TSingleDecay::SetRange(Double_t tlow, Double_t thigh)
442{
443 fDecayFunc->SetRange(tlow, thigh);
444 fTotalDecayFunc->SetRange(tlow, thigh);
445}
446
447void TSingleDecay::Print(Option_t*) const
448{
449 std::cout << " Decay Id: " << GetDecayId() << std::endl;
450 std::cout << " Intensity: " << GetIntensity() << " +/- " << GetIntensityError() << " c/s" << std::endl;
451 std::cout << " HalfLife: " << GetHalfLife() << " +/- " << GetHalfLifeError() << " s" << std::endl;
452 std::cout << "Efficiency: " << GetEfficiency() << std::endl;
453 std::cout << "My Address: " << this << std::endl;
454 if(fParent != nullptr) {
455 std::cout << "Parent Address: %p\n"
456 << fParent << std::endl;
457 }
458 if(fDaughter != nullptr) {
459 std::cout << "Daughter Address: " << fDaughter << std::endl;
460 }
461 std::cout << "First Parent: " << fFirstParent << std::endl;
462}
463
464TDecayChain::TDecayChain(UInt_t generations)
465{
466 if(generations == 0u) {
467 generations = 1;
468 }
469 fDecayChain.clear();
470 auto* parent = new TSingleDecay(nullptr);
471 parent->SetChainId(fChainCounter);
472 fDecayChain.push_back(parent);
473 for(UInt_t i = 1; i < generations; i++) {
474 auto* curDecay = new TSingleDecay(parent);
475 curDecay->SetChainId(fChainCounter);
476 fDecayChain.push_back(curDecay);
477 parent = curDecay;
478 }
479
480 fChainFunc = new TDecayFit("tmpname", this, &TDecayChain::ChainActivityFunc, 0, 10, fDecayChain.size() + 1,
481 "TDecayChain", "ChainActivityFunc");
482 fChainFunc->SetDecay(this);
486}
487
489{
490 // Might have to think about ownership if we allow external decays to be added
491 for(auto* decay : fDecayChain) {
492 delete decay;
493 }
494 delete fChainFunc;
495}
496
498{
499 for(auto* decay : fDecayChain) {
500 decay->SetTotalDecayParameters();
501 }
502 Double_t low_limit = 0.;
503 Double_t high_limit = 0.;
504 // We need to include the fact that we have parents and use that TF1 to perform the fit.
505 for(int i = 0; i < fChainFunc->GetNpar(); ++i) {
506 fChainFunc->SetParameter(i, fDecayChain.back()->GetTotalDecayFunc()->GetParameter(i));
507 fChainFunc->SetParError(i, fDecayChain.back()->GetTotalDecayFunc()->GetParError(i));
508 fChainFunc->SetParName(i, fDecayChain.back()->GetTotalDecayFunc()->GetParName(i));
509 fDecayChain.back()->GetTotalDecayFunc()->GetParLimits(i, low_limit, high_limit);
510 fChainFunc->SetParLimits(i, low_limit, high_limit);
511 }
512}
513
514Double_t TDecayChain::ChainActivityFunc(Double_t* dim, Double_t* par)
515{
516 /// This fits the total activity caused by the entire chain.
517 Double_t result = 0.0;
518 for(size_t i = 0; i < fDecayChain.size(); ++i) {
519 result += GetDecay(i)->EvalPar(dim, par);
520 }
521
522 return result;
523}
524
525Double_t TDecayChain::Eval(Double_t t) const
526{
527 return fChainFunc->Eval(t);
528}
529
530void TDecayChain::Draw(Option_t* opt)
531{
533 fChainFunc->Draw(opt);
534}
535
536void TDecayChain::DrawComponents(Option_t* opt, Bool_t color_flag)
537{
539 fDecayChain.at(0)->SetMinimum(0);
540 fDecayChain.at(0)->SetLineColor(1);
541 fDecayChain.at(0)->Draw("Same");
542 for(size_t i = 1; i < fDecayChain.size(); ++i) {
543 if(color_flag) {
544 fDecayChain.at(i)->SetLineColor(fDecayChain.at(i)->fUnId);
545 }
546 fDecayChain.at(i)->Draw(Form("same%s", opt));
547 }
548}
549
551{
552 if(decay != nullptr) {
553 fDecayChain.push_back(decay);
554 }
555}
556
558{
559 if(generation < fDecayChain.size()) {
560 return fDecayChain.at(generation);
561 }
563
564 return nullptr;
565}
566
567void TDecayChain::Print(Option_t*) const
568{
569 std::cout << "Number of Decays in Chain: " << fDecayChain.size() << std::endl;
570 std::cout << "Chain Id " << fDecayChain.at(0)->GetChainId() << std::endl;
571 for(auto* decay : fDecayChain) {
572 std::cout << "decay ptr: " << decay << std::endl;
573 decay->Print();
574 std::cout << std::endl;
575 }
576}
577
578TFitResultPtr TDecayChain::Fit(TH1* fithist, Option_t* opt)
579{
580 ROOT::Math::MinimizerOptions::SetDefaultMinimizer("Minuit2", "Combination");
581 TVirtualFitter::SetPrecision(1.0e-10);
582 TVirtualFitter::SetMaxIterations(10000);
583 Int_t parCounter = 1;
584 TSingleDecay* curDecay = fDecayChain.at(0);
586 // TFitResultPtr fitres = fithist->Fit(fChainFunc,Form("%sWLRS",opt));
587 TFitResultPtr fitres = fChainFunc->Fit(fithist, Form("%sWLRS", opt));
588 Double_t chi2 = fitres->Chi2();
589 Double_t ndf = fitres->Ndf();
590
591 std::cout << "Chi2/ndf = " << chi2 / ndf << std::endl;
592
593 // Now copy the fits back to the appropriate nuclei.
594 curDecay->SetIntensity(fChainFunc->GetParameter(0));
595 curDecay->SetIntensityError(fChainFunc->GetParError(0));
596 // Now we need to set the parameters for each of the parents
597 while(curDecay != nullptr) {
598 curDecay->SetDecayRate(fChainFunc->GetParameter(parCounter));
599 curDecay->SetDecayRateError(fChainFunc->GetParError(parCounter));
600 curDecay = curDecay->GetDaughterDecay();
601 ++parCounter;
602 curDecay->UpdateDecays();
603 }
604
605 return fitres;
606}
607
608Double_t TDecayChain::EvalPar(const Double_t* x, const Double_t* par)
609{
610 fChainFunc->InitArgs(x, par);
612
613 return fChainFunc->EvalPar(x, par);
614}
615
616void TDecayChain::SetRange(Double_t xlow, Double_t xhigh)
617{
618 fChainFunc->SetRange(xlow, xhigh);
619 for(auto* decay : fDecayChain) {
620 decay->SetRange(xlow, xhigh);
621 }
622}
623
624TDecay::TDecay(std::vector<TDecayChain*> chainList)
625 : fChainList(std::move(chainList))
626{
627 fFitFunc = new TDecayFit("tmpfit", this, &TDecay::DecayFit, 0, 10, 1, "TDecay", "DecayFit");
628 fFitFunc->SetDecay(this);
629 RemakeMap();
631}
632
634{
635 if(idx < fChainList.size()) {
636 return fChainList.at(idx);
637 }
638
640
641 return nullptr;
642}
643
644Double_t TDecay::DecayFit(Double_t* dim, Double_t* par) // NOLINT(readability-non-const-parameter)
645{
646 /// This fits the total activity caused by the entire chain.
647 Double_t result = 0.0;
648 // Start the fit with flat background;
649 result = par[0];
650 // Parameters might be linked, so I have to sort this out here.
651 // We Must build parameter arrays for each fit.
652 for(auto* chain : fChainList) {
653 Int_t par_counter = 0;
654 auto* tmppar = new Double_t[chain->Size() + 1];
655 tmppar[par_counter++] = par[fFitFunc->GetParNumber(Form("Intensity_ChainId%d", chain->GetChainId()))];
656 for(int j = 0; j < chain->Size(); ++j) {
657 tmppar[par_counter++] = par[fFitFunc->GetParNumber(Form("DecayRate_DecayId%d", chain->GetDecay(j)->GetDecayId()))];
658 }
659 result += chain->EvalPar(dim, tmppar);
660 delete[] tmppar;
661 }
662
663 return result;
664}
665
666TFitResultPtr TDecay::Fit(TH1* fithist, Option_t* opt)
667{
668 // Use the option "G" to use Geoff's Levenberg-Marquardt algorithm to fit.
669 TString opt1 = opt;
670 opt1.ToUpper();
671
672 ROOT::Math::MinimizerOptions::SetDefaultMinimizer("Minuit2", "Combination");
673 TVirtualFitter::SetPrecision(1.0e-10);
674 TVirtualFitter::SetMaxIterations(10000);
675 if(fithist->GetSumw2N() == 0) {
676 fithist->Sumw2();
677 }
678 // Int_t parCounter = 1;
680
681 // TFitResultPtr fitres = fithist->Fit(fFitFunc,Form("%sWLRS0",opt));
682 TFitResultPtr fitres;
683 if(opt1.Contains("G")) {
684 // Fit using LMFitter..Doesn't do residuals yet
685 TLMFitter fitter;
686 fitter.Fit(fithist, fFitFunc);
687 } else {
688 fitres = fFitFunc->Fit(fithist, Form("%sRIS", opt));
689 Double_t chi2 = fitres->Chi2();
690 Double_t ndf = fitres->Ndf();
691 std::cout << "Chi2/ndf = " << chi2 / ndf << std::endl;
692 }
693
694 // Now Tell the decays about the results
695 for(auto* chain : fChainList) {
696 Int_t par_num = fFitFunc->GetParNumber(Form("Intensity_ChainId%d", chain->GetChainId()));
697 chain->GetDecay(0)->SetIntensity(fFitFunc->GetParameter(par_num));
698 chain->GetDecay(0)->SetIntensityError(fFitFunc->GetParError(par_num));
699 for(int j = 0; j < chain->Size(); ++j) {
700 par_num = fFitFunc->GetParNumber(Form("DecayRate_DecayId%d", chain->GetDecay(j)->GetDecayId()));
701 chain->GetDecay(j)->SetDecayRate(fFitFunc->GetParameter(par_num));
702 chain->GetDecay(j)->SetDecayRateError(fFitFunc->GetParError(par_num));
703 }
704 chain->GetDecay(0)->UpdateDecays();
705 chain->SetChainParameters();
706 }
707
708 return fitres;
709}
710
711void TDecay::Draw(Option_t* opt)
712{
714 fFitFunc->Draw(opt);
715}
716
718{
719 RemakeMap();
720 // Find the number of unique chains and decays.
721 Int_t unq_chains = fChainList.size();
722 Int_t unq_decays = fDecayMap.size();
723
724 Double_t xlow = 0.;
725 Double_t xhigh = 0.;
726 fFitFunc->GetRange(xlow, xhigh);
727
728 Double_t tmpbg = fFitFunc->GetParameter(0);
729 Double_t tmpbglow = 0.;
730 Double_t tmpbghigh = 0.;
731 fFitFunc->GetParLimits(0, tmpbglow, tmpbghigh);
732 Double_t tmpbgerr = fFitFunc->GetParError(0);
733 delete fFitFunc;
734 fFitFunc = new TDecayFit("tmpfit", this, &TDecay::DecayFit, xlow, xhigh, unq_chains + unq_decays + 1, "TDecay", "DecayFit");
735 fFitFunc->SetDecay(this);
736 fFitFunc->SetParName(0, "Background");
737 fFitFunc->SetParameter(0, tmpbg);
738 fFitFunc->SetParError(0, tmpbgerr);
739 fFitFunc->SetParLimits(0, tmpbglow, tmpbghigh);
740
741 Int_t par_counter = 1;
742 Double_t low = 0.;
743 Double_t high = 0.;
744 for(auto* chain : fChainList) {
745 fFitFunc->SetParName(par_counter, Form("Intensity_ChainId%d", chain->GetDecay(0)->GetChainId()));
746 chain->SetChainParameters();
747 chain->GetDecay(0)->GetIntensityLimits(low, high);
748 fFitFunc->SetParLimits(par_counter, low, high);
749 fFitFunc->SetParameter(par_counter++, chain->GetDecay(0)->GetIntensity());
750 }
751 for(auto& iter : fDecayMap) {
752 fFitFunc->SetParName(par_counter, Form("DecayRate_DecayId%d", iter.first));
753 iter.second.at(0)->GetDecayRateLimits(low, high);
754 fFitFunc->SetParLimits(par_counter, low, high);
755 fFitFunc->SetParameter(par_counter++, iter.second.at(0)->GetDecayRate());
756 }
757}
758
759Double_t TDecay::ComponentFunc(Double_t* dim, Double_t* par) // NOLINT(readability-non-const-parameter)
760{
761 /// Function for drawing summed components.
762 Double_t result = 0;
763 /// This function takes 1 parameter, the decay Id.
764 auto id = static_cast<Int_t>(par[0]);
765 auto iter = fDecayMap.find(id);
766
767 for(auto* decay : iter->second) {
768 result += decay->Eval(dim[0]);
769 }
770 return result;
771}
772
773void TDecay::DrawComponents(Option_t*, Bool_t)
774{
775 /// Loop over all of the ids and draw them seperately on the pad
776 Double_t low = 0.;
777 Double_t high = 0.;
778 fFitFunc->GetRange(low, high);
779
780 TF1* tmp_comp = new TF1("tmpname", this, &TDecay::ComponentFunc, low, high, 1, "TDecay", "ComponentFunc");
781 for(auto& iter : fDecayMap) {
782 tmp_comp->SetName(Form("Component_%d", iter.first));
783 tmp_comp->SetParameter(0, iter.first);
784 if(iter.first == kWhite) {
785 tmp_comp->SetLineColor(kOrange);
786 } else {
787 tmp_comp->SetLineColor(static_cast<Color_t>(iter.first));
788 }
789 tmp_comp->DrawClone("same");
790 }
791 delete tmp_comp;
793}
794
796{
797 Double_t low = 0.;
798 Double_t high = 0.;
799 fFitFunc->GetRange(low, high);
800 auto* bg = new TF1("bg", "pol0", low, high);
801 bg->SetParameter(0, GetBackground());
802 bg->SetLineColor(kMagenta);
803 bg->DrawClone("same");
804 delete bg;
805}
806
807void TDecay::SetHalfLife(Int_t Id, Double_t halflife)
808{
809 auto it = fDecayMap.find(Id);
810 if(it == fDecayMap.end()) {
811 std::cout << "Could not find Id = : " << Id << std::endl;
812 return;
813 }
814 for(auto& i : it->second) {
815 i->SetHalfLife(halflife);
816 i->SetTotalDecayParameters();
817 }
818}
819
820void TDecay::SetHalfLifeLimits(Int_t Id, Double_t low, Double_t high)
821{
822 auto it = fDecayMap.find(Id);
823 if(it == fDecayMap.end()) {
824 std::cout << "Could not find Id = : " << Id << std::endl;
825 return;
826 }
827 for(auto& i : it->second) {
828 i->SetHalfLifeLimits(low, high);
829 i->SetTotalDecayParameters();
830 }
831}
832
833void TDecay::SetDecayRateLimits(Int_t Id, Double_t low, Double_t high)
834{
835 auto iter = fDecayMap.find(Id);
836 if(iter == fDecayMap.end()) {
837 std::cout << "Could not find Id = : " << Id << std::endl;
838 return;
839 }
840 for(auto* decay : iter->second) {
841 decay->SetDecayRateLimits(low, high);
842 decay->SetTotalDecayParameters();
843 }
844}
845
846void TDecay::Print(Option_t*) const
847{
848 std::cout << "Background: " << GetBackground() << " +/- " << GetBackgroundError() << std::endl
849 << std::endl;
850 for(const auto& it : fDecayMap) {
851 std::cout << "ID: " << it.first << " Name: " << it.second.at(0)->GetName() << std::endl;
852 it.second.at(0)->Print();
853 std::cout << std::endl;
854 }
855}
856
858{
859 for(const auto& iter : fDecayMap) {
860 std::cout << "ID: " << iter.first << std::endl;
861 for(auto* decay : iter.second) {
862 decay->Print();
863 }
864 std::cout << std::endl;
865 }
866}
867
868void TDecay::SetRange(Double_t xlow, Double_t xhigh)
869{
870 fFitFunc->SetRange(xlow, xhigh);
871 for(auto* chain : fChainList) {
872 chain->SetRange(xlow, xhigh);
873 }
874}
875
877{
878 fDecayMap.clear();
879 for(auto* chain : fChainList) {
880 for(int j = 0; j < chain->Size(); ++j) {
881 UInt_t id = chain->GetDecay(j)->GetDecayId();
882 if(fDecayMap.count(id) == 0) {
883 fDecayMap.insert(std::make_pair(id, std::vector<TSingleDecay*>()));
884 }
885 fDecayMap.find(id)->second.push_back(chain->GetDecay(j));
886 }
887 }
888}
TH1D * hist
Definition UserFillObj.h:3
std::vector< TSingleDecay * > fDecayChain
Definition TDecay.h:309
void Print(Option_t *option="") const override
Definition TDecay.cxx:567
TDecayFit * fChainFunc
Definition TDecay.h:310
Double_t EvalPar(const Double_t *x, const Double_t *par=nullptr)
Definition TDecay.cxx:608
Double_t Eval(Double_t t) const
Definition TDecay.cxx:525
TSingleDecay * GetDecay(UInt_t generation)
Definition TDecay.cxx:557
static UInt_t fChainCounter
Definition TDecay.h:302
void AddToChain(TSingleDecay *decay)
Definition TDecay.cxx:550
void SetChainParameters()
Definition TDecay.cxx:497
Double_t ChainActivityFunc(Double_t *dim, Double_t *par)
Definition TDecay.cxx:514
TDecayChain()=default
TFitResultPtr Fit(TH1 *fithist, Option_t *opt="")
Definition TDecay.cxx:578
void DrawComponents(Option_t *opt="", Bool_t color_flag=true) override
Definition TDecay.cxx:536
Int_t fChainId
Definition TDecay.h:311
void SetRange(Double_t xlow, Double_t xhigh)
Definition TDecay.cxx:616
void Draw(Option_t *opt="") override
Definition TDecay.cxx:530
TVirtualDecay * fDecay
Definition TDecay.h:88
void DefaultGraphs()
Definition TDecay.cxx:54
void Print(Option_t *opt="") const override
Definition TDecay.cxx:27
TFitResultPtr Fit(TH1 *hist, Option_t *opt="")
Definition TDecay.cxx:39
TGraph fResiduals
Definition TDecay.h:89
void SetDecay(TVirtualDecay *decay)
Definition TDecay.cxx:21
void DrawComponents() const
Definition TDecay.cxx:15
void UpdateResiduals(TH1 *hist)
Definition TDecay.cxx:61
void DrawResiduals()
Definition TDecay.cxx:93
TVirtualDecay * GetDecay() const
Definition TDecay.cxx:34
void DrawComponents(Option_t *opt="", Bool_t color_flag=true) override
Definition TDecay.cxx:773
void PrintMap() const
Definition TDecay.cxx:857
void SetDecayRateLimits(Int_t Id, Double_t low, Double_t high)
Definition TDecay.cxx:833
Double_t DecayFit(Double_t *dim, Double_t *par)
Definition TDecay.cxx:644
Double_t GetBackgroundError() const
Definition TDecay.h:367
TDecayFit * fFitFunc
Definition TDecay.h:386
std::map< Int_t, std::vector< TSingleDecay * > > fDecayMap
Definition TDecay.h:387
TFitResultPtr Fit(TH1 *fithist, Option_t *opt="")
Definition TDecay.cxx:666
std::vector< TDecayChain * > fChainList
Definition TDecay.h:385
void Print(Option_t *opt="") const override
Definition TDecay.cxx:846
void DrawBackground(Option_t *opt="")
Definition TDecay.cxx:795
void RemakeMap()
Definition TDecay.cxx:876
Double_t GetBackground() const
Definition TDecay.h:366
void SetRange(Double_t xlow, Double_t xhigh)
Definition TDecay.cxx:868
void SetHalfLifeLimits(Int_t Id, Double_t low, Double_t high)
Definition TDecay.cxx:820
void SetHalfLife(Int_t Id, Double_t halflife)
Definition TDecay.cxx:807
TDecay()=default
Double_t ComponentFunc(Double_t *dim, Double_t *par)
Definition TDecay.cxx:759
void Draw(Option_t *opt="") override
Definition TDecay.cxx:711
void SetParameters()
Definition TDecay.cxx:717
TDecayChain * GetChain(UInt_t idx)
Definition TDecay.cxx:633
void Fit(TH1 *hist, TF1 *func)
Definition TLMFitter.cxx:35
void SetDecayRate(const Double_t &decayrate)
Definition TDecay.h:155
void Print(Option_t *option="") const override
Definition TDecay.cxx:447
void SetIntensityLimits(const Double_t &low, const Double_t &high)
Definition TDecay.cxx:282
TDecayFit * fTotalDecayFunc
Definition TDecay.h:256
TSingleDecay * GetDaughterDecay()
Definition TDecay.cxx:322
void Fix()
Definition TDecay.cxx:429
void SetDaughterDecay(TSingleDecay *daughter)
Definition TDecay.h:218
Int_t GetDecayId() const
Definition TDecay.h:222
static UInt_t fCounter
Definition TDecay.h:261
Double_t GetHalfLife() const
Definition TDecay.h:137
Double_t GetIntensityError() const
Definition TDecay.h:149
Double_t Eval(Double_t t)
Definition TDecay.cxx:333
void UpdateDecays()
Definition TDecay.cxx:241
void SetTotalDecayParameters()
Definition TDecay.cxx:215
friend class TDecayFit
Definition TDecay.h:118
void GetDecayRateLimits(Double_t &low, Double_t &high) const
Definition TDecay.cxx:312
void Draw(Option_t *option="") override
Definition TDecay.cxx:327
TSingleDecay * GetParentDecay()
Definition TDecay.cxx:317
TSingleDecay * fDaughter
Definition TDecay.h:258
void SetDecayRateLimits(const Double_t &low, const Double_t &high)
Definition TDecay.cxx:288
void SetRange(Double_t tlow, Double_t thigh)
Definition TDecay.cxx:441
Double_t ActivityFunc(Double_t *dim, Double_t *par)
Definition TDecay.cxx:347
void GetIntensityLimits(Double_t &low, Double_t &high) const
Definition TDecay.cxx:307
void FixIntensity()
Definition TDecay.h:187
Double_t GetEfficiency() const
Definition TDecay.h:143
void FixHalfLife()
Definition TDecay.h:171
const TDecayFit * GetDecayFunc() const
Definition TDecay.h:225
TSingleDecay * fFirstParent
Definition TDecay.h:259
void SetName(const char *name) override
Definition TDecay.cxx:208
void SetDecayRateError(Double_t err)
Definition TDecay.h:240
void SetIntensity(const Double_t &intens)
Definition TDecay.h:160
TSingleDecay * fParent
Definition TDecay.h:257
Double_t GetDecayRate() const
Definition TDecay.h:141
TDecayFit * fDecayFunc
Definition TDecay.h:255
void ReleaseIntensity()
Definition TDecay.h:196
TFitResultPtr Fit(TH1 *fithist, Option_t *opt="")
Definition TDecay.cxx:400
void GetHalfLifeLimits(Double_t &low, Double_t &high) const
Definition TDecay.cxx:294
Double_t GetHalfLifeError() const
Definition TDecay.h:144
Double_t GetIntensity() const
Definition TDecay.h:142
void SetIntensityError(Double_t err)
Definition TDecay.h:241
void ReleaseHalfLife()
Definition TDecay.h:194
void Release()
Definition TDecay.cxx:435
UInt_t GetGeneration() const
Definition TDecay.h:136
UInt_t fGeneration
Definition TDecay.h:253
Double_t EvalPar(const Double_t *x, const Double_t *par=nullptr)
Definition TDecay.cxx:340
Int_t fUnId
Definition TDecay.h:260
void SetHalfLifeLimits(const Double_t &low, const Double_t &high)
Definition TDecay.cxx:271
virtual void DrawComponents(Option_t *opt="", Bool_t color_flag=true)
Definition TDecay.cxx:103