MINT2
RunningWidthCalculator.cpp
Go to the documentation of this file.
1 // author: Philippe d'Argent (p.dargent@cern.ch)
2 // created: 21 Oct 2015
4 #include "TMath.h"
5 #include "TCanvas.h"
6 #include "TH1D.h"
7 #include "TF1.h"
8 #include "Mint/Utils.h"
9 #include "Mint/DalitzEventList.h"
11 #include "Mint/SignalGenerator.h"
14 #include "Mint/BW_BW.h"
16 #include <cmath>
17 #include <complex>
18 #include "Math/Integrator.h"
19 #include "Math/Functor.h"
20 #include "Math/GSLIntegrator.h"
21 #include "Mint/Minimisable.h"
22 #include "Mint/Minimiser.h"
23 
24 using namespace std;
25 using namespace MINT;
26 
27 
29  // Calculate lower phase space limit
30  double min_m = 0.;
31  for(unsigned int i= 1; i<_pat.size(); i++){
32  min_m += _pat[i].mass()/GeV;
33  }
34  _min_s_inGeV2 = min_m*min_m;
35 }
36 
38  _pat(pat)
39 {
40  cout << "RunningWidthCalculator::RunningWidthCalculator: I got called." << endl;
42 }
43 
45  _pat = pat;
47 }
48 
49 
50 TH1D* RunningWidthCalculator::makeHisto_dalitz(int nBins, double max_s_inGeV2, int nIntegrationEvents, IFastAmplitudeIntegrable* amps, string OutputFileName){
51 
52  if(_pat.size() != 4) {
53  cout << "ERROR in RunningWidthCalculator::makeHisto_dalitz: I can handle only 3 body decays but the pattern " << _pat
54  << " has " << _pat.size()-1 << " final state particles. I'll return 0." << endl;
55  return 0;
56  }
57 
58  if(amps==0) amps = new FitAmpSum(_pat);
59  //Important! Ensures everything is initialised
60  DalitzEventList eventTest;
61  eventTest.generatePhaseSpaceEvents(1,_pat);
62  amps->RealVal(eventTest[0]);
63 
64  if(OutputFileName=="")
65  OutputFileName = "RunningWidth_"+ParticlePropertiesList::getMe()->get(abs((int)_pat[0]))->name()+"_Dalitz.root";
66 
67  TFile* f= new TFile(OutputFileName.c_str(),"RECREATE");
68  TH1D* h= new TH1D("RunningWidth","RunningWidth",nBins,_min_s_inGeV2,max_s_inGeV2);
69 
72 
73  for (int b=1; b<= h->GetNbinsX(); b++) {
74  // Set mass to new value in ResonancePropertiesList
75  // and in ParticlePropertiesList !
76  // This is necessary since SignalGenerator uses the mass in ParticlePropertiesList
77  // but it should use the mass in ResonancePropertiesList. Fix some day.
78  rp->changeMassForDebug(sqrt(h->GetXaxis()->GetBinCenter(b))*GeV);
79  pp->setMass(sqrt(h->GetXaxis()->GetBinCenter(b))*GeV);
80 
81  // Generate integration events
82  SignalGenerator sg(_pat,amps);
83  sg.setWeighted();
84  sg.noPrintout();
85  DalitzEventList eventList;
86  // Maybe we should somehow scale the number of integration events with mass,
87  // i.e. the available phase space ?
88  sg.FillEventList(eventList, nIntegrationEvents);
89 
90  // Calculate the integral
91  double integral = 0.;
92  double sumw = 0.;
93  for (unsigned int i= 0; i< eventList.size(); i++) {
94  integral += amps->RealVal(eventList[i])*eventList[i].getWeight()/(eventList[i].getGeneratorPdfRelativeToPhaseSpace());
95  sumw += eventList[i].getWeight()/(eventList[i].getGeneratorPdfRelativeToPhaseSpace());
96  }
97 
99  double phaseSpace = ps.getVal(_pat);
100 
101  h->SetBinContent(b,integral*phaseSpace/sumw);
102  }
103 
104  h->Scale(h->GetNbinsX()/h->Integral());
105 
106  h->Write();
107  f->Write();
108 
109  return h;
110 }
111 
112 
113 Double_t Bl_2(double q, double r, int l){
114 
115  double z= q*r;
116  if(l==1)return (2*z*z)/(1.+z*z);
117  if(l==2)return (13*pow(z,4))/(9.+3.*z*z+pow(z,4));
118  else return 1.;
119 }
120 
121 Double_t Q(double M, double m1, double m2)
122 {
123  Double_t q2 = (M*M-(m1+m2)*(m1+m2) ) * (M*M-(m1-m2)*(m1-m2) ) / (4.*M*M) ;
124  if(q2<0){
125  cout << " q2 = " << q2 << " M = " << M << " m1 = " << m1 << " m2 = " << m2 << endl;
126  q2=0;
127 
128  }
129  return sqrt(q2);
130 }
131 
132 Double_t Gamma_2body(double M, double m1, double m2, int l, double r){
133 
134  double q = Q(M,m1,m2);
135 
136  double bl_2 = Bl_2(q,r,l);
137 
138  return q/M * bl_2;
139 }
140 
141 Double_t Gamma_2body(Double_t *x, Double_t *par){
142  if(sqrt(x[0])*GeV< (par[0]+par[1]))return 0;
143  return Gamma_2body(sqrt(x[0])*GeV,par[0],par[1],(int)par[2],par[3]);
144 }
145 
146 Double_t BW_resonance(double m12, double m1, double m2, int l, double mass , double width , double r ){
147  double gamma = Gamma_2body(m12,m1,m2,l,r);
148  double gamma0 = Gamma_2body(mass,m1,m2,l,r);
149 
150  gamma= width*gamma/gamma0;
151 
152  return m12*gamma/((mass*mass-m12*m12)*(mass*mass-m12*m12)+(mass*gamma)*(mass*gamma));
153 }
154 
155 Double_t Gamma_mother_3body_byM12(Double_t *x, Double_t *par){
156 
157  //3 body decay : X -> (R->1 2) 3
158  //par[0]: mother (X) radius
159  //x[0]: m12, to be integrated over
160  //par[i]: final state masses, i=1,2,3
161  //par[4]: angular momentum in X -> R 3
162  //par[5]: angular momentum in R -> 1 2
163  //par[6]: resonance (R) mass
164  //par[7]: resonance (R) width
165  //par[8]: resonance (X) radius
166  //par[10]: mother (X) mass
167 
168  return Gamma_2body(par[10],x[0],par[3],par[4],par[0])*BW_resonance(x[0],par[1],par[2],par[5],par[6],par[7],par[8])*x[0];
169 }
170 
171 Double_t Gamma_mother_3body(Double_t *x, Double_t *par){
172 
173  const int nPar = 10;
174  const int nPar_new = 11;
175  double min_s12 = par[1]+par[2];
176  double bachelorMass = par[3] ;
177 
178  // Copy parameters
179  Double_t par_new[nPar_new];
180  for (int i=0; i< nPar; i++) {
181  par_new[i] = par[i];
182  }
183  // Add m(1,2,3) as parameter
184  par_new[10] = sqrt(x[0])*GeV;
185 
186  if(sqrt(x[0])*GeV-bachelorMass<min_s12)return 0.;
187 
188  TF1 *gamma_byS12 = new TF1("Gamma_mother_3body_byM12",Gamma_mother_3body_byM12,min_s12,par[9],nPar_new);
189  gamma_byS12->SetParameters(par_new);
190  double gamma = gamma_byS12->Integral(min_s12, sqrt(x[0])*GeV-bachelorMass);
191 
192  return gamma;
193 }
194 
195 
196 TH1D* RunningWidthCalculator::makeHisto_3body(int nBins, double max_s_inGeV2, const DecayTree& thisDcy, string OutputFileName){
197 
198  bool dbThis=false;
199 
200  // Some safety checks
201  if(thisDcy.finalState().size() != 3){
202  cout << "ERROR in RunningWidthCalculator::makeHisto_3body: I can handle only 3 body decays but the decay " << thisDcy
203  << " has " << thisDcy.finalState().size() << " final state particles. I'll return 0." << endl;
204  return 0;
205  }
206 
207  if(thisDcy.nDgtr() != 2){
208  cout << "ERROR in RunningWidthCalculator::makeHisto_3body: "
209  << " Mother should have 2 daughters, but it says it has "
210  << thisDcy.nDgtr() << ". I'll return 0." << endl;
211  return 0;
212  }
213 
214  if( ! _pat.compatibleWith(thisDcy)){
215  cout << "ERROR in RunningWidthCalculator::makeHisto_3body:"
216  << "DalitzEventPattern and DecayTree are not compatible. I'll return 0." << endl;
217  return 0;
218  }
219 
220  // Everything is fine, now search the resonance
222  for(int i=0; i< thisDcy.nDgtr(); i++){
224  if(dgtr->nDgtr() == 2) R = dgtr;
225  else bachelor = dgtr;
226  }
227 
228  if(0==R || 0== bachelor){
229  cout << "ERROR in RunningWidthCalculator::makeHisto_3body:"
230  << " Didn't find resonance or bachelor. I'll return 0. " << endl;
231  return 0;
232  }
233 
234  // Use the BW_BW class to add resonances to ResonanceProperitiesList
235  // and to get acces to angular momentum
236  AssociatingDecayTree associatingDecayTreeX(thisDcy);
237  const AssociatedDecayTree X = associatingDecayTreeX.getTree(_pat);
238 
239  BW_BW BW_X(X);
240  BW_BW BW_R(*R);
241 
242  // Define all parameters
243  // 3 body decay : X -> (R->1 2) 3
244  const int nPar = 10;
245  Double_t par[nPar];
246 
247  // Mother (X) radius
248  par[0] = ResonancePropertiesList::getMe()->get((int)_pat[0])->radius();
249  // Final state (1,2,3) masses:
250  par[1] = ParticlePropertiesList::getMe()->get((int) R->getDgtrTreePtr(0)->getVal())->mass();
251  par[2] = ParticlePropertiesList::getMe()->get((int) R->getDgtrTreePtr(1)->getVal())->mass();
252  par[3] = ParticlePropertiesList::getMe()->get((int) bachelor->getVal())->mass();
253  // Angular momentum in X -> R 3
254  par[4] = (BW_X.twoLPlusOne()-1)/2;
255  // Angular momentum in R -> 1 2
256  par[5] = (BW_R.twoLPlusOne()-1)/2;
257  // Resonance (R) mass, width and radius
258  par[6] = ResonancePropertiesList::getMe()->get((int) R->getVal())->mass();
259  par[7] = ResonancePropertiesList::getMe()->get((int) R->getVal())->width();
260  par[8] = ResonancePropertiesList::getMe()->get((int) R->getVal())->radius();
261  // Upper limit of s(1,2,3)
262  par[9] = max_s_inGeV2 * GeV *GeV;
263 
264  if(dbThis) for(int i=0; i<nPar; i++) cout << "Parameter " << i << " = " << par[i] << endl;
265 
266  if(OutputFileName=="")
267  OutputFileName = "RunningWidth_"+ParticlePropertiesList::getMe()->get(abs((int)_pat[0]))->name()+"_3body.root";
268  TFile* f= new TFile(OutputFileName.c_str(),"RECREATE");
269 
270  TF1 *gamma = new TF1("Gamma_mother_3body",Gamma_mother_3body,0,max_s_inGeV2,nPar);
271  gamma->SetParameters(par);
272 
273  TH1D* h= new TH1D("RunningWidth",";s [GeV^2]; #Gamma (s) [a.u.]",nBins,0,max_s_inGeV2);
274  for (int i=1; i<= h->GetNbinsX(); i++) {
275  h->SetBinContent(i,gamma->Eval(h->GetXaxis()->GetBinCenter(i) ));
276  }
277 
278  //h->Scale(1./h->Integral());
279  h->Write();
280  f->Write();
281  return h;
282 }
283 
284 
285 TF1* RunningWidthCalculator::getRunningWidthFunction_3body(double max_s_inGeV2, const DecayTree& thisDcy){
286 
287  bool dbThis=false;
288 
289  // Some safety checks
290  if(thisDcy.finalState().size() != 3){
291  cout << "ERROR in RunningWidthCalculator::makeHisto_3body: I can handle only 3 body decays but the decay " << thisDcy
292  << " has " << thisDcy.finalState().size() << " final state particles. I'll return 0." << endl;
293  return 0;
294  }
295 
296  if(thisDcy.nDgtr() != 2){
297  cout << "ERROR in RunningWidthCalculator::makeHisto_3body: "
298  << " Mother should have 2 daughters, but it says it has "
299  << thisDcy.nDgtr() << ". I'll return 0." << endl;
300  return 0;
301  }
302 
303  if( ! _pat.compatibleWith(thisDcy)){
304  cout << "ERROR in RunningWidthCalculator::makeHisto_3body:"
305  << "DalitzEventPattern and DecayTree are not compatible. I'll return 0." << endl;
306  return 0;
307  }
308 
309  // Everything is fine, now search the resonance
311  for(int i=0; i< thisDcy.nDgtr(); i++){
313  if(dgtr->nDgtr() == 2) R = dgtr;
314  else bachelor = dgtr;
315  }
316 
317  if(0==R || 0== bachelor){
318  cout << "ERROR in RunningWidthCalculator::makeHisto_3body:"
319  << " Didn't find resonance or bachelor. I'll return 0. " << endl;
320  return 0;
321  }
322 
323  // Use the BW_BW class to add resonances to ResonanceProperitiesList
324  // and to get acces to angular momentum
325  AssociatingDecayTree associatingDecayTreeX(thisDcy);
326  const AssociatedDecayTree X = associatingDecayTreeX.getTree(_pat);
327 
328  BW_BW BW_X(X);
329  BW_BW BW_R(*R);
330 
331  // Define all parameters
332  // 3 body decay : X -> (R->1 2) 3
333  const int nPar = 10;
334  Double_t par[nPar];
335 
336  // Mother (X) radius
337  par[0] = ResonancePropertiesList::getMe()->get((int)_pat[0])->radius();
338  // Final state (1,2,3) masses:
339  par[1] = ParticlePropertiesList::getMe()->get((int) R->getDgtrTreePtr(0)->getVal())->mass();
340  par[2] = ParticlePropertiesList::getMe()->get((int) R->getDgtrTreePtr(1)->getVal())->mass();
341  par[3] = ParticlePropertiesList::getMe()->get((int) bachelor->getVal())->mass();
342  // Angular momentum in X -> R 3
343  par[4] = (BW_X.twoLPlusOne()-1)/2;
344  // Angular momentum in R -> 1 2
345  par[5] = (BW_R.twoLPlusOne()-1)/2;
346  // Resonance (R) mass, width and radius
347  par[6] = ResonancePropertiesList::getMe()->get((int) R->getVal())->mass();
348  par[7] = ResonancePropertiesList::getMe()->get((int) R->getVal())->width();
349  par[8] = ResonancePropertiesList::getMe()->get((int) R->getVal())->radius();
350  // Upper limit of s(1,2,3)
351  par[9] = max_s_inGeV2 * GeV *GeV;
352 
353  if(dbThis) for(int i=0; i<nPar; i++) cout << "Parameter " << i << " = " << par[i] << endl;
354 
355  TF1 *gamma = new TF1("Gamma_mother_3body",Gamma_mother_3body,_min_s_inGeV2,max_s_inGeV2,nPar);
356  gamma->SetParameters(par);
357 
358  return gamma;
359 }
360 
361 
363  int _index;
364  double _m0;
365  double _gamma0;
366  std::vector<TF1*> _partialWidths;
367  std::vector<FitParameter*> _fit_couplings;
368 
369 public:
370  BF_Integrand(std::vector<TF1*> partialWidths, std::vector<FitParameter*> fit_couplings, double m0, double gamma0):
371  _index(0),_m0(m0), _gamma0(gamma0), _partialWidths(partialWidths), _fit_couplings(fit_couplings){}
372 
373  double operator()(Double_t* x, Double_t* par=0){
374  return Eval(x[0]);
375  (void)par;
376  }
377 
378  double operator()(double x){
379  return Eval(x);
380  }
381 
382  double Eval(Double_t x){
383  double totalWidth = 0.;
384  double totalWidth_norm = 0.;
385 
386  double sum = 0.;
387  for (unsigned int i=1; i<_fit_couplings.size(); i++) {
388  sum += *_fit_couplings[i];
389  }
390 
391  for (unsigned int i=0; i<_partialWidths.size(); i++) {
392  double c;
393  if(i==0) c = *_fit_couplings[0];//* (1.-sum);
394  else c = *_fit_couplings[0]* *_fit_couplings[i];
395  totalWidth += c * _partialWidths[i]->Eval(x);
396  totalWidth_norm += c* _partialWidths[i]->Eval(_m0*_m0/(GeV*GeV));
397  }
398  totalWidth = totalWidth/totalWidth_norm * _gamma0/GeV;
399 
400  double c;
401  if(_index==0) c = *_fit_couplings[0];//* (1.-sum);
402  else c = *_fit_couplings[0]* *_fit_couplings[_index];
403 
404  return (c * _partialWidths[_index]->Eval(x))/ ( pow((x-_m0*_m0/(GeV*GeV)),2) +_m0*_m0/(GeV*GeV)*totalWidth*totalWidth);
405  }
406 
407  void setIndex(const int i){
408  _index = i;
409  }
410 };
411 
412 
413 class chi2BF : public Minimisable{
414  double _precision;
415  std::vector<double> _BF;
416  double _m0;
417  double _gamma0;
418  double _s_min;
419  double _s_max;
420  std::vector<TF1*> _partialWidths;
421  std::vector<FitParameter*> _fit_couplings;
422 
423 public:
424  chi2BF(std::vector<double> BF, std::vector<TF1*> partialWidths, std::vector<FitParameter*> fit_couplings, double m0, double gamma0, double precision = 0.001):
425  _precision(precision), _BF(BF), _m0(m0), _gamma0(gamma0), _partialWidths(partialWidths), _fit_couplings(fit_couplings)
426  {
427  _s_min= 0;
428  _s_max= pow( (_m0+10*_gamma0)/GeV , 2);
429  }
430  double getVal(){
432  double sum = 0.;
433  vector<double> integrals;
434  for (unsigned int i=0; i < _BF.size() ; i++) {
435  integrand.setIndex(i);
436  ROOT::Math::IntegratorOneDim integrator(integrand) ;
437  double integral = integrator.Integral( _s_min, _s_max );
438  integrals.push_back(integral);
439  }
440  double norm = 0.;
441  for (unsigned int i=0; i < _BF.size() ; i++) {
442  norm += integrals[i];
443  }
444  for (unsigned int i=0; i < _BF.size() ; i++) {
445  sum += pow( (_BF[i]-integrals[i]/norm) /_precision ,2);
446  }
447  return sum;
448  }
449 };
450 
451 
452 std::vector<double> RunningWidthCalculator::getPartialWidthCouplingsFromBF(std::vector<double> BF , std::vector<TF1*> partialWidths, double m0, double gamma0){
453 
454  //MinuitParameterSet mps();
455 
456  std::vector<FitParameter*> fit_couplings;
457 
458  FitParameter* scale = new FitParameter("scale",2,1,0.1);
459  fit_couplings.push_back(scale);
460 
461  for (unsigned int i=1; i < BF.size() ; i++) {
462  FitParameter* g =
463  new FitParameter(("g_"+anythingToString((int) i)).c_str(),0,1,0.1);
464  //new FitParameter(("g_"+std::to_string(i)).c_str(),0,1,0.1);
465  fit_couplings.push_back(g);
466  }
467 
468  chi2BF f(BF, partialWidths, fit_couplings, m0, gamma0);
469  Minimiser mini(&f);
470  mini.doFit();
471 
472  vector<double> couplings;
473  double norm = 0.;
474 
475 
476  double sum = 0.;
477  for (unsigned int i=1; i<fit_couplings.size(); i++) {
478  sum += *fit_couplings[i];
479  }
480 
481  for (unsigned int i=0; i<fit_couplings.size(); i++) {
482  double c;
483  if(i==0) c = 1.;//(1.-sum);
484  else c = *fit_couplings[i];
485  norm += c*partialWidths[i]->Eval(m0*m0/(GeV*GeV));
486  }
487 
488  for (unsigned int i=0; i<fit_couplings.size(); i++) {
489  double c;
490  if(i==0) c = 1;//(1.-sum);
491  else c = *fit_couplings[i];
492  couplings.push_back(c / norm * gamma0/GeV);
493  }
494 
495  return couplings;
496 
497 }
498 
499 
501  vector<TF1*> _gamma;
502  vector<double> _g;
503  double _singularity;
504 public:
505  Dispersion_Integrand(vector<TF1*> f, vector<double> g, double singularity):
506  _gamma(f), _g(g), _singularity(singularity){
507  }
508  double operator()(double x){
509  double sum = 0.;
510  for (unsigned int i=0; i<_gamma.size(); i++) sum += _g[i]*_gamma[i]->Eval(x);
511  return sum/(_singularity-x);
512  }
513 };
514 
515 TH1D* RunningWidthCalculator::makeRunningMassHisto_3body(int nBins, double max_s_inGeV2, vector<TF1*> gamma, vector<double> g, string OutputFileName){
516 
517  double absTol = 0.0001;
518  double relTol = 0.001;
519  unsigned int size = 1000;
520  int rule = 3;
521  double epsilon= 0.00001;
522 
523  if(OutputFileName=="")
524  OutputFileName = "RunningMass_"+ParticlePropertiesList::getMe()->get(abs((int)_pat[0]))->name()+"_3body.root";
525  TFile* f= new TFile(OutputFileName.c_str(),"RECREATE");
526  TH1D* h_m= new TH1D("RunningMass",";s [GeV^{2}]; m^{2} (s) [GeV^{2}]",nBins,_min_s_inGeV2,max_s_inGeV2);
527  for (int i=1; i<= h_m->GetNbinsX(); i++) {
528  double singularity = h_m->GetXaxis()->GetBinCenter(i);
529  if(singularity<_min_s_inGeV2){
530  h_m->SetBinContent(i,0);
531  continue;
532  }
533  Dispersion_Integrand integrand(gamma,g,singularity);
534  ROOT::Math::IntegratorOneDim integrator(integrand, ROOT::Math::IntegrationOneDim::kADAPTIVESINGULAR, absTol , relTol , size , rule ) ;
535  h_m->SetBinContent(i,(integrator.Integral(_min_s_inGeV2,singularity-epsilon) + integrator.Integral(singularity+epsilon,max_s_inGeV2*10000))/TMath::Pi());
536  }
537 
538  //h_m->Scale(h_m->GetNbinsX()/abs(h_m->Integral()));
539  h_m->Write();
540  f->Write();
541 
542  return h_m;
543  /*
544  double singularity = 1.4;
545 
546  Dispersion_Integrand integrand(gamma,singularity,100);
547  ROOT::Math::IntegratorOneDim integrator(integrand, ROOT::Math::IntegrationOneDim::kADAPTIVESINGULAR, absTol , relTol , size , rule ) ;
548  double singularPts[3] = {_min_m_squared,singularity,singularity};
549  std::vector<double> sp(singularPts, singularPts+3);
550 
551  cout << "Int = " << integrator.Integral(_min_m_squared,singularity-epsilon) + integrator.IntegralUp(singularity+epsilon) << endl;
552 
553 
554  Dispersion_Integrand_Subtraction integrand_sub(gamma,singularity);
555  ROOT::Math::IntegratorOneDim integrator_sub(integrand_sub, ROOT::Math::IntegrationOneDim::kADAPTIVESINGULAR, absTol , relTol , size , rule ) ;
556  double tmp = integrator_sub.Integral(_min_m_squared,3);
557 
558  cout << "Int = " << -1.*(tmp + gamma->Eval(singularity)* log( (3-singularity)/(singularity-_min_m_squared) ) ) + integrator.IntegralUp(3) << endl;
559  */
560 }
561 
562 
563 
564 TF1* RunningWidthCalculator::getRunningWidthFunction_2body(double max_s_inGeV2, const DecayTree& thisDcy){
565 
566  bool dbThis=false;
567 
568  // Some safety checks
569  if(thisDcy.finalState().size() != 2){
570  cout << "ERROR in RunningWidthCalculator::makeHisto_2body: I can handle only 2 body decays but the decay " << thisDcy
571  << " has " << thisDcy.finalState().size() << " final state particles. I'll return 0." << endl;
572  return 0;
573  }
574 
575  if(thisDcy.nDgtr() != 2){
576  cout << "ERROR in RunningWidthCalculator::makeHisto_2body: "
577  << " Mother should have 2 daughters, but it says it has "
578  << thisDcy.nDgtr() << ". I'll return 0." << endl;
579  return 0;
580  }
581 
582  if( ! _pat.compatibleWith(thisDcy)){
583  cout << "ERROR in RunningWidthCalculator::makeHisto_2body:"
584  << "DalitzEventPattern and DecayTree are not compatible. I'll return 0." << endl;
585  return 0;
586  }
587 
588  // Use the BW_BW class to add resonances to ResonanceProperitiesList
589  // and to get acces to angular momentum
590  AssociatingDecayTree associatingDecayTreeX(thisDcy);
591  const AssociatedDecayTree X = associatingDecayTreeX.getTree(_pat);
592  BW_BW BW_X(X);
593 
594  // Define all parameters
595  // 2 body decay : X -> 1 2
596  const int nPar = 4;
597  Double_t par[nPar];
598 
599  // Final state (1,2) masses:
600  par[0] = ParticlePropertiesList::getMe()->get((int) X.getDgtrTreePtr(0)->getVal())->mass();
601  par[1] = ParticlePropertiesList::getMe()->get((int) X.getDgtrTreePtr(1)->getVal())->mass();
602  // Angular momentum in X -> 1 2
603  par[2] = (BW_X.twoLPlusOne()-1)/2;
604  // Mother (X) radius
605  par[3] = ResonancePropertiesList::getMe()->get((int)_pat[0])->radius();
606 
607  TF1 *gamma = new TF1("Gamma_2body",Gamma_2body,0,max_s_inGeV2,nPar);
608  gamma->SetParameters(par);
609 
610  return gamma;
611  (void)dbThis;
612 }
613 
614 
615 TH1D* RunningWidthCalculator::makeHisto_2body(int nBins, double max_s_inGeV2, const DecayTree& thisDcy, string OutputFileName){
616 
617  bool dbThis=false;
618 
619  // Some safety checks
620  if(thisDcy.finalState().size() != 2){
621  cout << "ERROR in RunningWidthCalculator::makeHisto_2body: I can handle only 2 body decays but the decay " << thisDcy
622  << " has " << thisDcy.finalState().size() << " final state particles. I'll return 0." << endl;
623  return 0;
624  }
625 
626  if(thisDcy.nDgtr() != 2){
627  cout << "ERROR in RunningWidthCalculator::makeHisto_2body: "
628  << " Mother should have 2 daughters, but it says it has "
629  << thisDcy.nDgtr() << ". I'll return 0." << endl;
630  return 0;
631  }
632 
633  if( ! _pat.compatibleWith(thisDcy)){
634  cout << "ERROR in RunningWidthCalculator::makeHisto_2body:"
635  << "DalitzEventPattern and DecayTree are not compatible. I'll return 0." << endl;
636  return 0;
637  }
638 
639  // Use the BW_BW class to add resonances to ResonanceProperitiesList
640  // and to get acces to angular momentum
641  AssociatingDecayTree associatingDecayTreeX(thisDcy);
642  const AssociatedDecayTree X = associatingDecayTreeX.getTree(_pat);
643  BW_BW BW_X(X);
644 
645  // Define all parameters
646  // 2 body decay : X -> 1 2
647  //const int nPar = 10;
648  //Double_t par[nPar];
649 
650  // Mother (X) radius
651  double r = ResonancePropertiesList::getMe()->get((int)_pat[0])->radius();
652  // Final state (1,2) masses:
653  double m1 = ParticlePropertiesList::getMe()->get((int) X.getDgtrTreePtr(0)->getVal())->mass();
654  double m2 = ParticlePropertiesList::getMe()->get((int) X.getDgtrTreePtr(1)->getVal())->mass();
655  // Angular momentum in X -> 1 2
656  double l = (BW_X.twoLPlusOne()-1)/2;
657 
658  if(OutputFileName=="")
659  OutputFileName = "RunningWidth_"+ParticlePropertiesList::getMe()->get(abs((int)_pat[0]))->name()+"_2body.root";
660  TFile* f= new TFile(OutputFileName.c_str(),"RECREATE");
661 
662  TH1D* h= new TH1D("RunningWidth",";s [GeV^2]; #Gamma (s) [a.u.]",nBins,_min_s_inGeV2,max_s_inGeV2);
663  for (int i=1; i<= h->GetNbinsX(); i++) {
664  h->SetBinContent(i, Gamma_2body( sqrt(h->GetXaxis()->GetBinCenter(i))*GeV , m1,m2, l, r));
665  }
666 
667  //h->Scale(1./h->Integral());
668  h->Write();
669  f->Write();
670  return h;
671  (void)dbThis;
672 }
673 
674 
675 
676 Double_t phaseSpaceIntegral(Double_t *x, Double_t *par){
677 
678  //x[0]: mumsRecoMass()^2
679  //par[0]: mumsMass()
680  //par[i]: final state masses (i=1,2,3)
681 
683  double ps_val = ps.getVal(sqrt(x[0])*GeV,par[1],par[2],par[3]);
684  double ps0_val = ps.getVal(par[0],par[1],par[2],par[3]);
685 
686  double ps_ratio=0.;
687  if(ps0_val>0)ps_ratio= ps_val/ps0_val;
688 
689  return ps_ratio * par[0]/(sqrt(x[0])*GeV);
690 }
691 
692 TH1D* RunningWidthCalculator::makeHisto_phaseSpace(int nBins, double max_s_inGeV2, string OutputFileName){
693 
694  if(_pat.size() != 4) {
695  cout << "ERROR in RunningWidthCalculator::makeHisto_phaseSpace: I can handle only 3 body decays but the pattern " << _pat
696  << " has " << _pat.size()-1 << " final state particles. I'll return 0." << endl;
697  return 0;
698  }
699 
700  if(OutputFileName=="")
701  OutputFileName = "RunningWidth_"+ParticlePropertiesList::getMe()->get(abs((int)_pat[0]))->name()+"_PhaseSpace.root";
702 
703 
704  TFile* f= new TFile(OutputFileName.c_str(),"RECREATE");
705  TH1D* h= new TH1D("RunningWidth","RunningWidth",nBins,_min_s_inGeV2,max_s_inGeV2);
706 
707  const int nPar = 4;
708  Double_t par[nPar];
709  par[0] = ParticlePropertiesList::getMe()->get((int)_pat[0])->mass();
710  par[1] = ParticlePropertiesList::getMe()->get((int)_pat[1])->mass();
711  par[2] = ParticlePropertiesList::getMe()->get((int)_pat[2])->mass();
712  par[3] = ParticlePropertiesList::getMe()->get((int)_pat[3])->mass();
713 
714  TF1 *ps = new TF1("phaseSpaceIntegral",phaseSpaceIntegral,_min_s_inGeV2,max_s_inGeV2,nPar);
715  ps->SetParameters(par);
716 
717  for (int i=1; i<= h->GetNbinsX(); i++) {
718  h->SetBinContent(i,ps->Eval(h->GetXaxis()->GetBinCenter(i)));
719  }
720 
721  h->Scale(h->GetNbinsX()/h->Integral());
722  h->Write();
723  f->Write();
724 
725  return h;
726 }
727 
729 
730  if(_pat.size() != 4) {
731  cout << "ERROR in RunningWidthCalculator::makeHisto_phaseSpace: I can handle only 3 body decays but the pattern " << _pat
732  << " has " << _pat.size()-1 << " final state particles. I'll return 0." << endl;
733  return 0;
734  }
735 
736  const int nPar = 4;
737  Double_t par[nPar];
738  par[0] = ParticlePropertiesList::getMe()->get((int)_pat[0])->mass();
739  par[1] = ParticlePropertiesList::getMe()->get((int)_pat[1])->mass();
740  par[2] = ParticlePropertiesList::getMe()->get((int)_pat[2])->mass();
741  par[3] = ParticlePropertiesList::getMe()->get((int)_pat[3])->mass();
742 
743  TF1 *ps = new TF1("phaseSpaceIntegral",phaseSpaceIntegral,0,max_s_inGeV2,nPar);
744  ps->SetParameters(par);
745 
746  return ps;
747 }
748 
749 double Fermi_phaseSpace(double s, double lambda, double s0, double threshold){
750  if (s<threshold)return 0;
751  return sqrt(1.- threshold/s)/(1.+ exp(lambda * (s0-s) ) );
752 }
753 
754 Double_t Fermi_phaseSpace(Double_t *x, Double_t *par){
755  return Fermi_phaseSpace(x[0],par[0],par[1],par[2]);
756 }
757 
758 TF1* RunningWidthCalculator::getRunningWidthFunction_Fermi(double max_s_inGeV2, double lambda, double s0){
759 
760  // Define all parameters
761  const int nPar = 3;
762  Double_t par[nPar];
763  par[0] = lambda;
764  par[1] = s0;
765  par[2] = _min_s_inGeV2;
766 
767  TF1 *gamma = new TF1("Fermi_phaseSpace",Fermi_phaseSpace,0,max_s_inGeV2,nPar);
768  gamma->SetParameters(par);
769 
770  return gamma;
771 }
772 
773 
Double_t Gamma_mother_3body_byM12(Double_t *x, Double_t *par)
TH1D * makeHisto_dalitz(int nBins, double max_m_inMeV, int nIntegrationEvents, IFastAmplitudeIntegrable *amps=0, std::string OutputFileName="")
Dispersion_Integrand(vector< TF1 * > f, vector< double > g, double singularity)
void changeMassForDebug(double newVal) const
TH1D * makeHisto_phaseSpace(int nBins, double max_m_inMeV, std::string OutputFileName="")
std::vector< double > _BF
chi2BF(std::vector< double > BF, std::vector< TF1 * > partialWidths, std::vector< FitParameter * > fit_couplings, double m0, double gamma0, double precision=0.001)
virtual int twoLPlusOne() const
Definition: BW_BW.cpp:151
Double_t Gamma_mother_3body(Double_t *x, Double_t *par)
bool compatibleWith(const DecayTree &tree) const
static const double s
void noPrintout()
Definition: BaseGenerator.h:73
virtual double RealVal(EVENT_TYPE &evt)=0
TF1 * getRunningWidthFunction_2body(double max_s_inGeV2, const DecayTree &thisDcy)
void setDalitzEventPattern(const DalitzEventPattern &pat)
TF1 * getRunningWidthFunction_3body(double max_s_inGeV2, const DecayTree &thisDcy)
void setIndex(const int i)
const ResonanceProperties * get(int i) const
Double_t BW_resonance(double m12, double m1, double m2, int l, double mass, double width, double r)
const ValueType & getVal() const
Definition: DDTree.h:102
TH1D * makeHisto_3body(int nBins, double max_m_inMeV, const DecayTree &thisDcy, std::string OutputFileName="")
Definition: BW_BW.h:30
BF_Integrand(std::vector< TF1 * > partialWidths, std::vector< FitParameter * > fit_couplings, double m0, double gamma0)
static ResonancePropertiesList * getMe(const std::string &prefix="", MINT::MinuitParameterSet *mps=0)
std::vector< double > getPartialWidthCouplingsFromBF(std::vector< double > BF, std::vector< TF1 * > partialWidths, double m0, double gamma0)
double getVal(const DalitzEventPattern &_pat)
std::vector< FitParameter * > _fit_couplings
MINT::const_counted_ptr< DDTree< ValueType > > getDgtrTreePtr(int i) const
Definition: DDTree.h:114
void setWeighted(bool w=true)
Definition: BaseGenerator.h:62
void setMass(double m) const
double operator()(Double_t *x, Double_t *par=0)
TF1 * getRunningWidthFunction_phaseSpace(double max_s_inGeV2)
const AssociatedDecayTree & getTree(const DalitzEventPattern &pat) const
static const double m2
std::vector< TF1 * > _partialWidths
RunningWidthCalculator(const DalitzEventPattern &pat)
TH1D * makeHisto_2body(int nBins, double max_m_inMeV, const DecayTree &thisDcy, std::string OutputFileName="")
const ParticleProperties * get(const std::string &name) const
static const double GeV
std::vector< TF1 * > _partialWidths
double Eval(Double_t x)
unsigned int size() const
virtual unsigned int size() const
Definition: EventList.h:59
std::string anythingToString(const T &anything)
Definition: Utils.h:62
std::vector< FitParameter * > _fit_couplings
std::string name() const
Double_t Gamma_2body(double M, double m1, double m2, int l, double r)
static const ParticlePropertiesList * getMe()
double Fermi_phaseSpace(double s, double lambda, double s0, double threshold)
TF1 * getRunningWidthFunction_Fermi(double max_s_inGeV2, double lambda, double s0)
std::vector< const ValueType * > finalState() const
Definition: DDTree.h:293
int nDgtr() const
Definition: DDTree.h:96
Double_t Bl_2(double q, double r, int l)
TH1D * makeRunningMassHisto_3body(int nBins, double max_s_inGeV2, std::vector< TF1 * > gamma, std::vector< double > g, std::string OutputFileName="")
static const double g
double lambda(double x, double y, double z)
Definition: lambda.h:8
int generatePhaseSpaceEvents(int NumEvents, const DalitzEventPattern &pat, TRandom *rnd=0)
Double_t phaseSpace(Double_t *x, Double_t *par)
Definition: Histo_BW.cpp:79
Double_t phaseSpaceIntegral(Double_t *x, Double_t *par)
void FillEventList(DalitzEventList &evtList, int NEvents)
Double_t Q(double M, double m1, double m2)
double operator()(double x)