KaliVeda
Toolkit for HIC analysis
Loading...
Searching...
No Matches
KVMultiGaussIsotopeFit.cpp
1#include "KVMultiGaussIsotopeFit.h"
2#include "TGraph.h"
3#include "TRandom.h"
4#include <TCanvas.h>
5
6
9
10KVMultiGaussIsotopeFit::KVMultiGaussIsotopeFit(int z, int Ngauss, double PID_min, double PID_max, const KVNumberList& alist, std::vector<double> pidlist)
11 : TF1(Form("MultiGaussIsotopeFit_Z=%d", z), this, &KVMultiGaussIsotopeFit::FitFunc, PID_min, PID_max, total_number_parameters(Ngauss)),
12 Z{z},
13 Niso{Ngauss},
14 PIDmin{PID_min}, PIDmax{PID_max},
15 Alist{alist.GetArray()},
16 PIDlist{pidlist}
17{
18 // Constructor used to initialize and prepare a new fit of isotope PID spectrum
19 FixParameter(0, Niso);
20 SetParLimits(fit_param_index::bkg_cst, -1.e+5, 1e+5);
21 SetParameter(fit_param_index::bkg_cst, 4.);
22 SetParName(fit_param_index::bkg_cst, "Norm");
23 SetParLimits(fit_param_index::bkg_slp, -10, 0);
24 SetParameter(fit_param_index::bkg_slp, -0.2);
25 SetParName(fit_param_index::bkg_slp, "Bkg. slope");
26 SetParName(fit_param_index::gauss_wid, "Sigma");
27 SetParLimits(fit_param_index::gauss_wid, min_sigma, max_sigma);
28 SetParameter(fit_param_index::gauss_wid, 0.1);
29
30 TGraph pid_vs_a;
31 for (int ig = 1; ig <= Niso; ++ig) {
32 SetParName(get_gauss_norm_index(ig), Form("Norm. A=%d", Alist[ig - 1]));
33 SetParLimits(get_gauss_norm_index(ig), 1.e-3, 1.e+06);
34 SetParameter(get_gauss_norm_index(ig), 1.);
35 SetParName(get_mass_index(ig, Niso), Form("A_%d", ig));
36 FixParameter(get_mass_index(ig, Niso), Alist[ig - 1]);
37
38#if ROOT_VERSION_CODE >= ROOT_VERSION(6,24,0)
39 pid_vs_a.AddPoint(Alist[ig - 1], PIDlist[ig - 1]);
40#else
41 pid_vs_a.SetPoint(pid_vs_a.GetN(), Alist[ig - 1], PIDlist[ig - 1]);
42#endif
43 }
44
45 // do initial fit of centroids
46 TF1 centroidFit("centroidFit", this, &KVMultiGaussIsotopeFit::centroid_fit, 0., 100., 3);
47 centroidFit.SetParLimits(0, -50, 50);
48 centroidFit.SetParameter(0, 0);
49 centroidFit.SetParLimits(1, 1.e-2, 5.);
50 centroidFit.SetParameter(1, 1.e-1);
51 centroidFit.SetParLimits(2, -2.e-2, 1.);
52 centroidFit.SetParameter(2, 1.e-3);
53 pid_vs_a.Fit(&centroidFit, "N");
54
55 for (int i = 0; i < 3; ++i) {
56 FixParameter(fit_param_index::pidvsA_a0 + i, centroidFit.GetParameter(i));
57 SetParName(fit_param_index::pidvsA_a0 + i, Form("PIDvsA_a%d", i));
58 }
59
60 SetLineColor(kBlack);
61 SetLineWidth(2);
62 SetNpx(500);
63}
64
65
66
71
72KVMultiGaussIsotopeFit::KVMultiGaussIsotopeFit(int z, int Ngauss, double PID_min, double PID_max,
73 const KVNumberList& alist, double bkg_cst, double bkg_slp,
74 double gaus_wid, double pidvsa_a0, double pidvsa_a1, double pidvsa_a2)
75 : TF1(Form("MultiGaussIsotopeFit_Z=%d", z), this, &KVMultiGaussIsotopeFit::FitFunc, PID_min, PID_max, total_number_parameters(Ngauss)),
76 Z{z},
77 Niso{Ngauss},
78 PIDmin{PID_min}, PIDmax{PID_max},
79 Alist{alist.GetArray()}
80{
81 // Constructor which can be used with existing fit results (not to perform new fits)
82 //
83 // Use SetGaussianNorm() to set the normalisation parameters for each gaussian
84
85 SetParameter(0, Niso);
86 SetParameter(fit_param_index::bkg_cst, bkg_cst);
87 SetParameter(fit_param_index::bkg_slp, bkg_slp);
88 SetParameter(fit_param_index::gauss_wid, gaus_wid);
89 SetParameter(fit_param_index::pidvsA_a0, pidvsa_a0);
90 SetParameter(fit_param_index::pidvsA_a1, pidvsa_a1);
91 SetParameter(fit_param_index::pidvsA_a2, pidvsa_a2);
92
93 SetParName(fit_param_index::bkg_cst, "Norm");
94 SetParName(fit_param_index::bkg_slp, "Bkg. slope");
95 SetParName(fit_param_index::gauss_wid, "Sigma");
96
97 for (int ig = 1; ig <= Niso; ++ig) {
98 SetParName(get_gauss_norm_index(ig), Form("Norm. A=%d", Alist[ig - 1]));
99 SetParName(get_mass_index(ig, Niso), Form("A_%d", ig));
100 FixParameter(get_mass_index(ig, Niso), Alist[ig - 1]);
101 }
102 for (int i = 0; i < 3; ++i)
103 SetParName(fit_param_index::pidvsA_a0 + i, Form("PIDvsA_a%d", i));
104
105 SetLineColor(kBlack);
106 SetLineWidth(2);
107 SetNpx(500);
108}
109
110
111
114
115KVMultiGaussIsotopeFit::KVMultiGaussIsotopeFit(int Z, const KVNameValueList& fitparams)
116 : KVMultiGaussIsotopeFit(Z, fitparams.GetIntValue("Ng"), fitparams.GetDoubleValue("PIDmin"),
117 fitparams.GetDoubleValue("PIDmax"), fitparams.GetStringValue("Alist"),
118 fitparams.GetDoubleValue("Bkg_cst"), fitparams.GetDoubleValue("Bkg_slp"),
119 fitparams.GetDoubleValue("GausWid"),
120 fitparams.GetDoubleValue("PIDvsA_a0"),
121 fitparams.GetDoubleValue("PIDvsA_a1"),
122 fitparams.GetDoubleValue("PIDvsA_a2"))
123{
124 // initialize from previous fit with parameters stored in KVNameValueList
125 for (int ig = 1; ig <= fitparams.GetIntValue("Ng"); ++ig)
126 SetGaussianNorm(ig, fitparams.GetDoubleValue(Form("Norm_%d", ig)));
127}
128
129
130
133
134void KVMultiGaussIsotopeFit::UnDraw(TVirtualPad* pad) const
135{
136 // Remove the graphical representation of this fit from the given pad
137
138 auto old_fit = pad->FindObject(get_name_of_multifit(Z));
139 if (old_fit) delete old_fit;
140 for (auto a : Alist) {
141 UnDrawGaussian(Z, a, pad);
142 }
143}
144
145
146
149
150void KVMultiGaussIsotopeFit::DrawFitWithGaussians(Option_t* opt) const
151{
152 // Draw the overall fit plus the individual gaussians for each isotope
153
154 DrawCopy(opt)->SetName(get_name_of_multifit(Z));
155
156 TF1 fgaus("fgaus", "gausn", PIDmin, PIDmax);
157 // give a different colour to each gaussian
158 auto cstep = TColor::GetPalette().GetSize() / (Niso + 1);
159 int ig = 1;
160 for (auto& a : Alist) {
161 fgaus.SetParameters(GetGaussianNorm(ig), GetCentroid(ig), GetGaussianWidth(ig));
162 fgaus.SetNpx(500);
163 fgaus.SetLineColor(TColor::GetPalette()[cstep * ig]);
164 fgaus.SetLineWidth(2);
165 fgaus.SetLineStyle(9);
166 fgaus.DrawCopy("same")->SetName(get_name_of_isotope_gaussian(Z, a));
167 ++ig;
168 }
169}
170
171
172
177
178int KVMultiGaussIsotopeFit::GetMostProbableA(double PID, double& P) const
179{
180 // For a given PID, calculate the most probable value of \f$A\f$, P is its probability.
181 //
182 // \returns most probable \f$A\f$
183
184 auto total = Eval(PID);
185 std::map<double, int> probabilities;
186 int ig = 1;
187 for (auto& a : Alist) {
188 probabilities[evaluate_gaussian(ig, PID) / total] = a;
189 ++ig;
190 }
191 // the largest probability is now the last element in the map:
192 // get a reverse iterator to the beginning of the reversed map
193 auto it = probabilities.rbegin();
194 P = it->first;
195 return it->second;
196}
197
198
199
204
205double KVMultiGaussIsotopeFit::GetMeanA(double PID) const
206{
207 // for a given PID, calculate the mean value of \f$A\f$ from the weighted sum of all gaussians
208 //
209 // \returns mean value of \f$A\f$
210
211 auto total = Eval(PID);
212 int ig = 1;
213 double amean(0), totprob(0);
214 for (auto& a : Alist) {
215 auto weight = evaluate_gaussian(ig, PID) / total;
216 amean += weight * a;
217 totprob += weight;
218 ++ig;
219 }
220 return totprob > 0 ? amean / totprob : -1.;
221}
222
223
224
230
231std::map<int, double> KVMultiGaussIsotopeFit::GetADistribution(double PID) const
232{
233 // For the given PID, the map is filled with all possible values of \f$A\f$
234 // and the associated probability.
235 //
236 // \returns std::map containing probability distribution \f$P(A|PID)\f$
237
238 auto total = Eval(PID);
239 std::map<int, double> Adist;
240 int ig = 1;
241 for (auto& a : Alist) {
242 Adist[a] = evaluate_gaussian(ig, PID) / total;
243 ++ig;
244 }
245 return Adist;
246}
247
248
249
262
263int KVMultiGaussIsotopeFit::GetA(double PID, double& P) const
264{
265 // Probabilistic method to determine \f$A\f$ from PID.
266 //
267 // The A returned will be drawn at random from the probability distribution given by the
268 // sum of all gaussians (and the background) for the given PID.
269 //
270 // The result of the draw may be that this PID is part of the background noise:
271 // in this case we return 0
272 //
273 // P is the probability of the chosen result.
274 //
275 // \returns randomly drawn \f$A\f$ for given PID
276
277 auto total = Eval(PID);
278 double p_tot = 0;
279 int ig = 1;
280 auto X = gRandom->Uniform();
281 for (auto& a : Alist) {
282 auto w = evaluate_gaussian(ig, PID) / total;
283 p_tot += w;
284 if (X < w) {
285 P = w;
286 return a;
287 }
288 X -= w;
289 ++ig;
290 }
291 P = 1. - p_tot;
292 return 0; // background noise
293}
294
295
296
302
303double KVMultiGaussIsotopeFit::GetProbability(int A, double PID) const
304{
305 // \param[in] A isotope mass number
306 // \param[in] PID value of PID associated with A
307 // \return the probability that A is the correct mass number for a given PID value
308 // \return zero if A is not associated with a Gaussian in the fit
309
310 auto it = std::find(std::begin(Alist), std::end(Alist), A);
311 if (it != std::end(Alist)) {
312 int ig = std::distance(std::begin(Alist), it);
313 return evaluate_gaussian(ig, PID) / Eval(PID);
314 }
315 return 0;
316}
317
318
319
320
321
324
325void KVMultiGaussIsotopeFit::SetFitRange(double min, double max)
326{
327 // Change range of fit
328
329 SetRange(min, max);
330 PIDmin = min;
331 PIDmax = max;
332}
333
334
336
const char Option_t
#define X(type, name)
winID w
Option_t Option_t SetLineWidth
Option_t Option_t SetLineColor
R__EXTERN TRandom * gRandom
char * Form(const char *fmt,...)
Function for fitting PID mass spectra.
double centroid_fit(double *x, double *p)
Handles lists of named parameters with different types, a list of KVNamedParameter objects.
Int_t GetIntValue(const Char_t *name) const
Double_t GetDoubleValue(const Char_t *name) const
Strings used to represent a set of ranges of values.
Int_t GetSize() const
static const TArrayI & GetPalette()
virtual void SetRange(Double_t xmin, Double_t xmax)
virtual TF1 * DrawCopy(Option_t *option="") const
virtual Double_t Eval(Double_t x, Double_t y=0, Double_t z=0, Double_t t=0) const
virtual void AddPoint(Double_t x, Double_t y)
virtual void SetPoint(Int_t i, Double_t x, Double_t y)
Int_t GetN() const
virtual TFitResultPtr Fit(const char *formula, Option_t *option="", Option_t *goption="", Axis_t xmin=0, Axis_t xmax=0)
virtual void SetName(const char *name)
virtual TObject * FindObject(const char *name) const
virtual Double_t Uniform(Double_t x1, Double_t x2)
double min(double x, double y)
double max(double x, double y)
TArc a
ClassImp(TPyArg)