MINT2
TimeDependentGenerator.cpp
Go to the documentation of this file.
2 #include <Mint/SplineGenerator.h>
3 #include <TRandom3.h>
4 #include <iostream>
5 #include <sys/stat.h>
7 #include <stdexcept>
8 
9 using namespace std;
10 using namespace MINT;
11 
12 //
15 
17  map<string, unsigned> infoNames ;
19  infoNames["decaytime"] = TimeDependentGenerator::GenTimeEvent::IDECAYTIME ;
20  infoNames["smeareddecaytime"] = TimeDependentGenerator::GenTimeEvent::ISMEAREDDECAYTIME ;
21  return infoNames ;
22 }
23 
24 TimeDependentGenerator::GenTimeEvent::GenTimeEvent(const IDalitzEvent& evt, const int tag, const double decaytime,
25  const double smeareddecaytime) :
26  DalitzEvent(evt)
27 {
28  setTag(tag) ;
29  setDecayTime(decaytime) ;
30  setSmearedDecayTime(smeareddecaytime) ;
31 }
32 
34  DalitzEvent(evt)
35 {
36  while(getVectorOfValues().size() < 3)
37  getVectorOfValues().push_back(-999.) ;
38 }
39 
41  return getValueFromVector(ITAG) ;
42 }
43 
45  setValueInVector(ITAG, tag) ;
46 }
47 
49  return getValueFromVector(IDECAYTIME) ;
50 }
51 
53  setValueInVector(IDECAYTIME, decaytime) ;
54 }
55 
57  return getValueFromVector(ISMEAREDDECAYTIME) ;
58 }
59 
61  setValueInVector(ISMEAREDDECAYTIME, decaytime) ;
62 }
63 
64 // Take the CP conjugate of the head of the decay pattern.
66  pat[0].antiThis() ;
67  return pat ;
68 }
69 
70 TimeDependentGenerator::TimeDependentGenerator(const DalitzEventPattern& pattern, double width, double deltam,
71  double deltagamma, double qoverp, double phi,
72  TRandom3* rndm, TH1F* h_efficiency,
73  float resWidth, bool addExpEffects, Eff3piSymmetric* sEfficiency) :
74  m_rndm(rndm),
75  m_pattern(pattern),
76  m_cppattern(anti(pattern)),
77  m_model(new FitAmpSum(pattern)),
81  m_width(width),
82  m_deltam(deltam),
83  m_deltagamma(deltagamma),
84  m_qoverp(polar(qoverp, phi)),
85  m_scale(1.),
86  m_ngen(0),
87  m_naccept(0),
88  m_h_efficiency(h_efficiency),
90  m_resWidth(resWidth),
91  m_addExpEffects(addExpEffects),
92  m_sEfficiency(sEfficiency)
93 {
94  init() ;
95 }
96 
97 
100  double width, double deltam,
101  double deltagamma, double qoverp, double phi,
102  TRandom3* rndm, TH1F* h_efficiency,
103  float resWidth, bool addExpEffects, Eff3piSymmetric* sEfficiency) :
104  m_rndm(rndm),
105  m_pattern(model->getAmpPtr(0)->getTreePattern()),
106  m_cppattern(cpmodel->getAmpPtr(0)->getTreePattern()),
107  m_model(model),
108  m_cpmodel(cpmodel),
109  m_bothmodel(*m_model),
110  m_generator(m_pattern, &m_bothmodel),
111  m_width(width),
112  m_deltam(deltam),
113  m_deltagamma(deltagamma),
114  m_qoverp(polar(qoverp, phi)),
115  m_scale(1.),
116  m_ngen(0),
117  m_naccept(0),
118  m_h_efficiency(h_efficiency),
119  m_efficiencyFit(),
120  m_resWidth(resWidth),
121  m_addExpEffects(addExpEffects),
122  m_sEfficiency(sEfficiency)
123 {
124  init() ;
125 }
126 
129  if( m_h_efficiency != NULL ){
130  m_efficiencyFit = TSpline3(m_h_efficiency) ;
131  }
132  if( m_sEfficiency != NULL ){
135  }
136  // Ensure the models are fully initialised.
138  m_model->getVal(evt) ;
139  m_cpmodel->getVal(evt) ;
140  m_bothmodel.getVal(evt) ;
141 }
142 
143 pair<double, double> TimeDependentGenerator::generate_decay_time() const {
144  double decaytime = m_rndm->Exp(1./m_width) ;
145  double smeareddecaytime = decaytime ;
146 
147  if ( (m_h_efficiency != NULL) && (m_addExpEffects) ){
148  int i = 0 ;
149  float efficiency = 0 ;
150  int maxiter = 100000 ;
151 
152  smeareddecaytime = decaytime + m_rndm->Gaus(0, m_resWidth);
153 
154  while(true){
155  if( smeareddecaytime > m_efficiencyFit.GetXmax() ){
156  efficiency = m_efficiencyFit.Eval( m_efficiencyFit.GetXmax() ) ;
157  }
158  else if( smeareddecaytime > m_efficiencyFit.GetXmin() ){
159  efficiency = m_efficiencyFit.Eval( smeareddecaytime ) ;
160  }
161  else{
162  efficiency = m_efficiencyFit.Eval( m_efficiencyFit.GetXmin() ) ;
163  }
164 
165  if(m_rndm->Rndm() < efficiency){
166  break;
167  }
168 
169  decaytime = m_rndm->Exp(1./m_width) ;
170  smeareddecaytime = decaytime + m_rndm->Gaus(0, m_resWidth);
171 
172  i += 1 ;
173  if( i > maxiter ){
174  cout << "WARNING: Decay time generation limit exceeded." << endl ;
175  break ;
176  }
177  }
178  }
179  return pair<double, double>(decaytime, smeareddecaytime) ;
180 }
181 
183  int tag(0) ;
184  double decaytime(0.) ;
185  double smeareddecaytime(0.) ;
186 
188 
189  unsigned i = 0 ;
190  unsigned maxattempts = 100000 ;
191  // Accept/reject using the incoherent sum in m_bothmodel as an envelope to generate
192  // events.
193  while(true) {
194  tag = m_rndm->Rndm() > 0.5 ? 1 : -1 ;
195  tie(decaytime, smeareddecaytime) = generate_decay_time() ;
196  evt = MINT::counted_ptr<IDalitzEvent>(new DalitzEvent(tag == 1 ? m_pattern : m_cppattern, s13, s23)) ;
197  if(accept_or_reject(tag, decaytime, *evt))
198  break ;
199  i += 1 ;
200  if( i >= maxattempts)
201  throw range_error("Failed to generate an event in 100000 attempts!") ;
202  }
203 
204  return MINT::counted_ptr<IDalitzEvent>(new GenTimeEvent(*evt, tag, decaytime, smeareddecaytime)) ;
205 }
206 
208  int tag(0) ;
209  double decaytime(0.) ;
210  double smeareddecaytime(0.) ;
211 
213 
214  unsigned i = 0 ;
215  unsigned maxattempts = 100000 ;
216  // Accept/reject using the incoherent sum in m_bothmodel as an envelope to generate
217  // events.
218  while(true) {
219  tag = m_rndm->Rndm() > 0.5 ? 1 : -1 ;
220  tie(decaytime, smeareddecaytime) = generate_decay_time() ;
221  evt = m_generator.newEvent() ;
222  if(accept_or_reject(tag, decaytime, *evt))
223  break ;
224  i += 1 ;
225  if( i >= maxattempts)
226  throw range_error("Failed to generate an event in 100000 attempts!") ;
227  }
228 
229  return MINT::counted_ptr<IDalitzEvent>(new GenTimeEvent(*evt, tag, decaytime, smeareddecaytime)) ;
230 }
231 
232 double TimeDependentGenerator::envelope_value(const double decaytime, IDalitzEvent& evt) {
233  return m_bothmodel.Prob(evt) * m_scale * exp(-decaytime * m_width) * m_width ;
234 }
235 
236 bool TimeDependentGenerator::accept_or_reject(const int tag, const double decaytime, IDalitzEvent& evt) {
237  ++m_ngen ;
238 
239  double pdfval = pdf_value(tag, decaytime, evt) ;
240 
241  double maxval = envelope_value(decaytime, evt) ;
242  if(pdfval > maxval){
243  cout << "pdfval " << pdfval << " maxval " << maxval << endl ;
244  //throw out_of_range("pdfval > maxval. That shouldn't happen!") ;
245  m_scale *= pdfval / maxval ;
246  cout << "scale " << m_scale << endl ;
247  ++m_naccept ;
248  return true ;
249  }
250  if(m_rndm->Rndm() * maxval < pdfval){
251  ++m_naccept ;
252  return true ;
253  }
254  return false ;
255 }
256 
258  return m_scale ;
259 }
260 
262  return m_ngen > 0 ? float(m_naccept)/m_ngen : 0. ;
263 }
264 
265 double TimeDependentGenerator::pdf_value(int tag, double decaytime, IDalitzEvent& evt) {
266  complex<double> Ap = m_model->ComplexVal(evt) ;
267  complex<double> Am = m_cpmodel->ComplexVal(evt) ;
268  if(tag == -1)
269  swap(Ap, Am) ;
270  // This is gives the same values as the below using the amplitude coefficients.
271  /*double magAp = norm(Ap) ;
272  double magAm = norm(Am) ;
273  complex<double> crossterm = pow(m_qoverp, tag) * conj(Ap) * Am ;
274  double magqoverp = pow(norm(m_qoverp), tag) ;
275  double deltamt = m_deltam * decaytime ;
276  double halfdgammat = 0.5 * m_deltagamma * decaytime ;
277  double pdfval = 0.5 * exp(-m_width * decaytime)
278  * ((magAp + magqoverp * magAm) * cosh(halfdgammat)
279  + (magAp - magqoverp * magAm) * cos(deltamt)
280  - 2 * crossterm.real() * sinh(halfdgammat)
281  + 2 * crossterm.imag() * sin(deltamt)) ;
282  return pdfval ;*/
283  AmpPair coeffs = amplitude_coefficients(tag, decaytime) ;
284  complex<double> Amp = coeffs.first * Ap + coeffs.second * Am ;
285  double ampnorm = norm(Amp) ;
286  return ampnorm ;
287 }
288 
292  evt) ;
293 }
294 
296 TimeDependentGenerator::amplitude_coefficients(const int tag, const double decaytime) {
297  double coeff = 0.5 * exp(-decaytime * 0.5 * (m_width + 0.5 * m_deltagamma)) ;
298  complex<double> expterm = exp(complex<double>(0.5 * m_deltagamma * decaytime, m_deltam * decaytime)) ;
299  complex<double> plusterm = 1. + expterm ;
300  complex<double> minusterm = 1. - expterm ;
301  complex<double> coeffprod = coeff * plusterm ;
302  complex<double> coeffmix = pow(m_qoverp, tag) * coeff * minusterm ;
303  return AmpPair(coeffprod, coeffmix) ;
304 }
305 
306 TH1F TimeDependentGenerator::draw_pdf_vs_time(IDalitzEvent& evt, unsigned nbins, float tmin, float tmax,
307  const std::string& name) {
308  TH1F histo(name.c_str(), "", nbins, tmin, tmax) ;
309  int tag = int(evt.getValueFromVector(GenTimeEvent::ITAG)) ;
310  for(unsigned i = 1 ; i < nbins + 1 ; ++i){
311  double time = histo.GetXaxis()->GetBinCenter(i) ;
312  double val = pdf_value(tag, time, evt) ;
313  histo.SetBinContent(i, val) ;
314  histo.SetBinError(i, 0.) ;
315  }
316  return histo ;
317 }
318 
319 TH1F TimeDependentGenerator::draw_envelope_vs_time(IDalitzEvent& evt, unsigned nbins, float tmin, float tmax,
320  const std::string& name) {
321  TH1F histo(name.c_str(), "", nbins, tmin, tmax) ;
322  for(unsigned i = 1 ; i < nbins + 1 ; ++i){
323  double time = histo.GetXaxis()->GetBinCenter(i) ;
324  double val = envelope_value(time, evt) ;
325  histo.SetBinContent(i, val) ;
326  histo.SetBinError(i, 0.) ;
327  }
328  return histo ;
329 }
330 
FitAmpIncoherentSum m_bothmodel
virtual const std::vector< double > & getVectorOfValues() const
virtual MINT::counted_ptr< IDalitzEvent > newEvent()
double envelope_value(const double, IDalitzEvent &)
virtual double Prob(IDalitzEvent &evt)
void setEfficiency(const MINT::counted_ptr< MINT::IReturnRealForEvent< IDalitzEvent > > &eff)
double pdf_value(int, double, IDalitzEvent &)
virtual std::complex< double > ComplexVal(IDalitzEvent &evt)
Definition: FitAmpSum.h:122
virtual std::complex< double > getVal(IDalitzEvent &evt)
Definition: FitAmpSum.cpp:182
static std::map< std::string, unsigned > infoNames
std::pair< double, double > generate_decay_time() const
Generate a decay time, optionally including experimental effects.
virtual int addAsList(const FitAmpListBase &other, double factor=1)
static DalitzEventPattern anti(DalitzEventPattern pat)
Take the CP conjugate of the head of the decay pattern.
double getVal(IDalitzEvent &evt)
TimeDependentGenerator(const DalitzEventPattern &pattern, double width, double deltam, double deltagamma, double qoverp, double phi, TRandom3 *rndm, TH1F *h_efficiency=NULL, float resWidth=0.05, bool addExpEffects=false, Eff3piSymmetric *sEfficiency=NULL)
bool accept_or_reject(const int tag, const double decaytime, IDalitzEvent &)
Decide whether the generated event should be accepted or rejected.
virtual double getValueFromVector(unsigned int i) const =0
static std::map< std::string, unsigned > makeInfoNames()
MINT::counted_ptr< FitAmpSum > m_cpmodel
TH1F draw_envelope_vs_time(IDalitzEvent &, unsigned, float, float, const std::string &name="envelope_vs_time")
TH1F draw_pdf_vs_time(IDalitzEvent &, unsigned, float, float, const std::string &name="pdf_vs_time")
MINT::counted_ptr< IDalitzEvent > generate_event()
Generate a flavour, decay time and Dalitz event.
AmpPair amplitude_coefficients(const int tag, const double decaytime)
const std::complex< double > m_qoverp
const DalitzEventPattern m_pattern
GenTimeEvent(const IDalitzEvent &, const int, const double, const double smeareddecaytime=-999.)
MINT::counted_ptr< FitAmpSum > m_model
std::pair< std::complex< double >, std::complex< double > > AmpPair
const DalitzEventPattern m_cppattern