GamR  0.0.0
GammaROOT
Loading...
Searching...
No Matches
GaussianDistr.cc
Go to the documentation of this file.
1#include <TMinuit.h>
2
3#include <utils/Utilities.hh>
4#include "TDPAD.hh"
5#include "GaussianDistr.hh"
6
7namespace GamR {
8 namespace AngDist {
10 double sigma = FWHM/2.3548;
11 double start = mean - (double)Limit*sigma;
12 double stop = mean + (double)Limit*sigma;
13 Bhfs.clear();
14 RelAmps.clear();
15 for (int i=0; i<nSamples; ++i) {
16 double Bhf = start + (double)i*(stop-start)/(double)(nSamples-1.0);
17 Bhfs.push_back(Bhf);
18 RelAmps.push_back(exp(-0.5*pow(((Bhf-mean)/sigma), 2)));
19 }
20 Normalise();
21 }
22
24 double total = 0;
25 for (int i=0; i<RelAmps.size(); ++i) {
26 total += RelAmps[i];
27 }
28 for (int i=0; i<RelAmps.size(); ++i) {
29 RelAmps[i] = RelAmps[i]/total;
30 }
31 }
32
33 double GaussianDistr::RatioFunc(double x, double a, double gfac, double off) {
34 double ratio = 0;
35 for (int i=0; i<nSamples; ++i) {
36 double Bhf = Bhfs[i];
37 ratio += a*RelAmps[i]*sin(-2*Bhf*0.04789*gfac*(x-off));
38 }
39 return ratio;
40 }
41
42 double GaussianDistr::operator() (double *x, double *p) {
43 return RatioFunc(x[0], p[0], p[1], p[2]);
44 }
45
47 TF1* func = new TF1("GaussianRatio", *this, Low, High, 3);
48 func->SetParameter(0, amp);
49 func->SetParameter(1, g);
50 func->SetParameter(2, offset);
51 return func;
52 }
53
55 private:
56 static GaussianDistr *p;
57
58 public:
59 GlobalChiSquare(GaussianDistr *parent) { p = parent; }
60
61 static void minuit(int &npar, double *gin, double &f, double *par, int iflag) {
62 f = 0;
63
64 p->SetAmp(par[0]);
65 p->SetG(par[1]);
66 p->SetMean(par[2]);
67 p->SetFWHM(par[3]);
68 p->SetOffset(par[4]);
69
70 TF1 *func;
71 if (p->FixedField) {
72 func = p->FitFunc; //TF1 generated before, field does not change
73 }
74 else { //Generate new TF1, set field again
75 p->SetField();
76 func = p->GetFunc();
77 }
78 //set parameters of func
79 func->SetParameter(0, par[0]);
80 func->SetParameter(1, par[1]);
81 func->SetParameter(2, par[4]);
82
83 f = p->Hist->Chisquare(func, "R");
84
85 if (!(p->FixedField)) { delete func; }
86
87 return;
88 }
89 };
90
91 GaussianDistr *GaussianDistr::GlobalChiSquare::p = nullptr;
92 //int GaussianDistr::FixedField = 0;
93
94 void GaussianDistr::Fit(int quiet) {
95 int npars = 5;
96 auto gMinuit = new TMinuit(npars);
97 if (quiet) {
98 gMinuit->Command("SET PRINT -1");
99 }
100
101 /* check if field is fixed or not */
102 if (FixedField) {
103 SetField();
104 FitFunc = new TF1("GaussianDistr", *this, Low, High, 3);
105 }
106
107 GlobalChiSquare func(this);
108 gMinuit->SetFCN(func.minuit);
109
110 double arglist[10];
111 arglist[0] = 1;
112
113 int ierflg = 0;
114 gMinuit->mnexcm("SET ERR", arglist, 1, ierflg);
115 arglist[0] = 2;
116 gMinuit->mnexcm("SET STR", arglist, 1, ierflg);
117
118 int parnum = 0;
119
120 std::vector<std::string> parnames = {"Amp", "g", "mean", "FWHM", "offset"};
121 std::vector<double> pars = GetPars();
122 for (int i=0; i<5; ++i) {
123 double min = ParLimsLow[i];
124 double max = ParLimsHigh[i];
125 std::cout << i << " " << min << " " << max << " " << pars[i] << std::endl;
126 gMinuit->mnparm(parnum, parnames[i].c_str(), pars[i], ParErrs[i], min, max, ierflg);
127 ++parnum;
128 }
129
130 for (int i=0; i<5; ++i) {
131 if (ParFix[i]==1) {
132 gMinuit->FixParameter(i);
133 }
134 }
135
136 arglist[0] = 100000;
137 arglist[1] = 1;
138 gMinuit->mnexcm("MIGRAD", arglist, 2, ierflg);
139 gMinuit->mnimpr();
140 gMinuit->mnexcm("HESSE", arglist, 2, ierflg);
141 gMinuit->mnexcm("MINOS", arglist, 2, ierflg);
142
143 ParVals.clear();
144 ParErrs.clear();
145 for (int i=0; i<5; ++i) {
146 double parVal, parErr;
147 gMinuit->GetParameter(i, parVal, parErr);
148 ParVals.push_back(parVal);
149 ParErrs.push_back(parErr);
150 }
151 SetPars();
152
153 delete gMinuit;
154 }
155
156 /* DOUBLE GAUSSIAN */
158 double sigma = FWHM/2.3548;
159 double start = mean - (double)Limit*sigma;
160 double stop = mean + (double)Limit*sigma;
161 Bhfs.clear();
162 RelAmps.clear();
163 for (int i=0; i<nSamples; ++i) {
164 double Bhf = start + (double)i*(stop-start)/(double)(nSamples-1.0);
165 Bhfs.push_back(Bhf);
166 RelAmps.push_back(exp(-0.5*pow(((Bhf-mean)/sigma), 2)));
167 }
168 Normalise();
169 }
170
172 double total = 0;
173 for (int i=0; i<RelAmps.size(); ++i) {
174 total += RelAmps[i];
175 }
176 for (int i=0; i<RelAmps.size(); ++i) {
177 RelAmps[i] = RelAmps[i]/total;
178 }
179 }
180
181 double DoubleGaussianDistr::RatioFunc(double x, double a1, double a2, double gfac1, double gfac2, double t1, double t2, double n, double off) {
182 double ratio = 0;
183 for (int i=0; i<nSamples; ++i) {
184 double Bhf = Bhfs[i];
185 double intensity1 = n/t1*exp(-(x-off)/t1)*(1+a1*sin(-2*(x-off)*0.04789*Bhf*gfac1)) +
186 1.0/t2*exp(-(x-off)/t2)*(1+a2*sin(-2*(x-off)*0.04789*Bhf*gfac2));
187
188 double intensity2 = n/t1*exp(-(x-off)/t1)*(1+a1*sin(2*(x-off)*0.04789*Bhf*gfac1)) +
189 1.0/t2*exp(-(x-off)/t2)*(1+a2*sin(2*(x-off)*0.04789*Bhf*gfac2));
190
191 double r = 0;
192 if (intensity1 == 0 && intensity2 == 0) { continue; }
193
194 r = ((intensity1-intensity2)/(intensity1 + intensity2));
195
196 ratio += RelAmps[i]*r;
197 }
198 return ratio;
199 }
200
201 double DoubleGaussianDistr::operator() (double *x, double *p) {
202 return RatioFunc(x[0], p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
203 }
204
206 TF1* func = new TF1("DoubleGaussianRatio", *this, Low, High, 8);
207 func->SetParameter(0, amp1);
208 func->SetParameter(1, amp2);
209 func->SetParameter(2, g1);
210 func->SetParameter(3, g2);
211 func->SetParameter(4, tau1);
212 func->SetParameter(5, tau2);
213 func->SetParameter(6, n1n2);
214 func->SetParameter(7, offset);
215 return func;
216 }
217
219 private:
220 static DoubleGaussianDistr *p;
221
222 public:
223 GlobalChiSquare(DoubleGaussianDistr *parent) { p = parent; }
224
225 static void minuit(int &npar, double *gin, double &f, double *par, int iflag) {
226 f = 0;
227
228 p->SetAmp1(par[0]);
229 p->SetAmp2(par[1]);
230 p->SetG1(par[2]);
231 p->SetG2(par[3]);
232 p->SetTau1(par[4]);
233 p->SetTau2(par[5]);
234 p->SetN1N2(par[6]);
235 p->SetMean(par[7]);
236 p->SetFWHM(par[8]);
237 p->SetOffset(par[9]);
238
239 TF1 *func;
240 if (p->FixedField) {
241 func = p->FitFunc; //TF1 generated in Fit(), field does not change
242 }
243 else { //Generate new TF1
244 p->SetField();
245 func = p->GetFunc();
246 }
247 func->SetParameter(0, par[0]);
248 func->SetParameter(1, par[1]);
249 func->SetParameter(2, par[2]);
250 func->SetParameter(3, par[3]);
251 func->SetParameter(4, par[4]);
252 func->SetParameter(5, par[5]);
253 func->SetParameter(6, par[6]);
254 func->SetParameter(7, par[9]);
255
256 f = p->Hist->Chisquare(func, "R");
257
258 if (!(p->FixedField)) {delete func; }
259
260 return;
261 }
262 };
263
264 DoubleGaussianDistr *DoubleGaussianDistr::GlobalChiSquare::p = nullptr;
265
266 void DoubleGaussianDistr::Fit(int quiet) {
267 int npars = 10;
268 auto gMinuit = new TMinuit(npars);
269 if (quiet) {
270 gMinuit->Command("SET PRINT -1");
271 }
272
273 // Check if the field is fixed or not
274 if (FixedField) {
275 SetField();
276 FitFunc = new TF1("DoubleGaussianDistr", *this, Low, High, 8);
277 }
278
279 GlobalChiSquare func(this);
280 gMinuit->SetFCN(func.minuit);
281
282 double arglist[10];
283 arglist[0] = 1;
284
285 int ierflg = 0;
286
287 gMinuit->mnexcm("SET ERR", arglist, 1, ierflg);
288 arglist[0] = 2;
289 gMinuit->mnexcm("SET STR", arglist, 1, ierflg);
290
291 int parnum = 0;
292
293 std::vector<std::string> parnames = {"Amp1", "Amp2", "g1", "g2", "Tau1", "Tau2", "N1N2", "mean", "FWHM", "offset"};
294 std::vector<double> pars = GetPars();
295 for (int i=0; i<10; ++i) {
296 double min = ParLimsLow[i];
297 double max = ParLimsHigh[i];
298 gMinuit->mnparm(parnum, parnames[i].c_str(), pars[i], ParErrs[i], min, max, ierflg);
299 ++parnum;
300 }
301
302 for (int i=0; i<10; ++i) {
303 if (ParFix[i]==1) {
304 gMinuit->FixParameter(i);
305 }
306 }
307
308 arglist[0] = 100000;
309 arglist[1] = 1;
310 gMinuit->mnexcm("MINIGRAD", arglist, 2, ierflg);
311 //gMinuit->mnimpr();
312 //gMinuit->mnexcm("HESSE", arglist, 2, ierflg);
313 //gMinuit->mnexcm("MINOS", arglist, 2, ierflg);
314
315 ParVals.clear();
316 ParErrs.clear();
317 for (int i=0; i<10; ++i) {
318 double parVal, parErr;
319 gMinuit->GetParameter(i, parVal, parErr);
320 ParVals.push_back(parVal);
321 ParErrs.push_back(parErr);
322 }
323 SetPars();
324
325 delete gMinuit;
326 }
327 }
328}
static void minuit(int &npar, double *gin, double &f, double *par, int iflag)
double operator()(double *x, double *p)
std::vector< double > GetPars()
DoubleGaussianDistr(double L, double H, std::vector< double > pars)
double RatioFunc(double x, double a1, double a2, double gfac1, double gfac2, double t1, double t2, double n, double off)
static void minuit(int &npar, double *gin, double &f, double *par, int iflag)
double RatioFunc(double x, double a, double gfac, double off)
std::vector< double > GetPars()
GaussianDistr(double L, double H, std::vector< double > pars)
double operator()(double *x, double *p)
Definition Gain.cc:19