MINT2
TimeDependentGeneratorOld.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 
8 using namespace std;
9 using namespace MINT;
10 
11 // check if a file exists.
12 bool exists(const string& fname) {
13  struct stat statinfo ;
14  return stat(fname.c_str(), &statinfo) == 0 ;
15 }
16 
18  const double _integral, SignalGenerator* _generator) :
19  decaytime(_decaytime),
20  integral(_integral),
21  model(_model),
22  generator(_generator)
23 {}
24 
25 //
28 
30  map<string, unsigned> infoNames ;
33  infoNames["smeareddecaytime"] = TimeDependentGeneratorOld::GenTimeEvent::ISMEAREDDECAYTIME ;
34  return infoNames ;
35 }
36 
37 TimeDependentGeneratorOld::GenTimeEvent::GenTimeEvent(const IDalitzEvent& evt, const int tag, const double decaytime,
38  const double smeareddecaytime) :
39  DalitzEvent(evt)
40 {
41  setTag(tag) ;
42  setDecayTime(decaytime) ;
43  setSmearedDecayTime(smeareddecaytime) ;
44 }
45 
47  DalitzEvent(evt)
48 {
49  while(getVectorOfValues().size() < 3)
50  getVectorOfValues().push_back(-999.) ;
51 }
52 
54  return getValueFromVector(ITAG) ;
55 }
56 
58  setValueInVector(ITAG, tag) ;
59 }
60 
62  return getValueFromVector(IDECAYTIME) ;
63 }
64 
66  setValueInVector(IDECAYTIME, decaytime) ;
67 }
68 
70  return getValueFromVector(ISMEAREDDECAYTIME) ;
71 }
72 
74  setValueInVector(ISMEAREDDECAYTIME, decaytime) ;
75 }
76 
77 // Take the CP conjugate of the head of the decay pattern.
79  pat[0].antiThis() ;
80  return pat ;
81 }
82 
83 /* Constructor, takes:
84  name : the name of the generator and the directory in which the integrators will be saved.
85  overwrite : whether to overwrite the existing integrator files (if they exist).
86  rndm : The random number generator to use.
87  precision : The precision to which the integrals must be calculated.
88  pattern : The event pattern to be used (the CP conjugate will automatically be added).
89  width : the decay width in 1/ps.
90  deltam : the delta-mass in 1/ps.
91  deltagamma : the delta-gamma in 1/ps.
92  qoverp : the magnitude of q/p.
93  phi : the phase of q/p.
94  tmax : the maximum decay time that'll be generated.
95  ntimepoints : the number of points to sample between 0 and tmax when building the generators.
96  h_efficiency : (optional) histogram to which efficiency plot will be fitted
97 */
98 TimeDependentGeneratorOld::TimeDependentGeneratorOld(const string& name, const bool overwrite, TRandom3* rndm,
99  double precision,
100  const DalitzEventPattern& pattern, double width, double deltam,
101  double deltagamma,
102  double qoverp, double phi, double tmax, int ntimepoints,
103  const bool saveIntegEvents, const double tmin, TH1F* h_efficiency,
104  float resWidth, bool addExpEffects) :
105  m_name(name),
106  m_rndm(rndm),
107  m_pattern(pattern),
108  m_cppattern(anti(pattern)),
109  m_width(width),
110  m_deltam(deltam),
111  m_deltagamma(deltagamma),
112  m_qoverp(qoverp),
113  m_phi(phi),
114  m_tmax(tmax),
115  m_tmin(tmin),
116  m_ntimepoints(ntimepoints),
117  m_genmap(),
119  m_tagintegralfrac(0.),
120  m_precision(precision),
121  m_h_efficiency(h_efficiency),
122  m_resWidth(resWidth),
123  m_addExpEffects(addExpEffects),
125 {
126  // If overwrite is true and the integrators directory exists, delete it.
127  if(overwrite && exists(name)){
128  cout << "Deleting previous integrators in directory " << name << endl ;
129  string cmd("rm -rf " + name) ;
130  system(cmd.c_str()) ;
131  }
132 
133  if(!exists(name)){
134  string cmd("mkdir -p " + name) ;
135  system(cmd.c_str()) ;
136  }
137 
138  const DalitzEventPattern* patterns[] = {&m_cppattern, &m_pattern} ;
139  double sampleinterval = m_ntimepoints > 1 ? (m_tmax - m_tmin)/(m_ntimepoints-1) : 0. ;
140  // Loop over flavours.
141  for(int tag = -1 ; tag <= 1 ; tag += 2) {
142  m_genmap[tag] = GenList() ;
143  const DalitzEventPattern* evtpat = patterns[(tag+1)/2] ;
144  const DalitzEventPattern* antipat = patterns[((tag+1)/2 + 1) % 2] ;
145  // cout << "evtpat " ;
146  // evtpat->print() ;
147  // cout << " antipat " ;
148  // antipat->print() ;
149  // cout << endl ;
150  vector<double> times ;
151  vector<double> integrals ;
152  // Loop over decay time sample points.
153  for(int i = 0 ; i < m_ntimepoints ; ++i){
154  double decaytime = m_tmin + i * sampleinterval ;
155  AmpPair amps = amplitude_coefficients(tag, decaytime) ;
156  FitAmpSum* model(new FitAmpSum(*evtpat)) ;
157  *model *= amps.first ;
158  if(amps.second != complex<double>(0., 0.)){
159  FitAmpSum antimodel(*antipat) ;
160  antimodel *= amps.second ;
161  model->add(antimodel) ;
162  }
163  SignalGenerator* generator = new SignalGenerator(*evtpat, model) ;
164  //cout << "Time point " << i << endl ;
165  //model->print() ;
166  //auto evt = generator->newEvent() ;
167  //model->printAllAmps(*evt) ;
168  ostringstream fname ;
169  fname << m_name << "/tag_" << tag << "_decaytime_" << decaytime ;
170  double integral(0.) ;
171  // Calculate the integral if necessary.
172  if(!exists(fname.str())){
173  const string eventsFile(fname.str() + "_events.root") ;
174  DalitzPdfSaveInteg dalitz(*evtpat, model, m_precision, fname.str(),
175  eventsFile, "topUp", fname.str()) ;
176  integral = dalitz.getIntegralValue() ;
177  dalitz.saveIntegrator(fname.str()) ;
178  if(!saveIntegEvents){
179  string cmd("rm " + eventsFile) ;
180  system(cmd.c_str()) ;
181  }
182  }
183  // Else retrive the integral from a file.
184  else {
185  auto intcalc = model->makeIntegrationCalculator() ;
186  intcalc->retrieve(fname.str()) ;
187  integral = intcalc->integral() ;
188  }
189  cout << "Make generator with tag " << tag << ", decay time " << decaytime
190  << ", coeffprod " << amps.first.real()
191  << " + " << amps.first.imag() << " j, "
192  << " coeffmix " << amps.second.real() << " + " << amps.second.imag()
193  << " j, integral " << integral << endl ;
194  if(integral == 0.){
195  complex<double> coeff = amps.first + amps.second ;
196  integral = sqrt(coeff.real() * coeff.real() + coeff.imag() * coeff.imag()) ;
197  }
198  m_genmap[tag].push_back(GenTimePoint(decaytime, model, integral, generator)) ;
199  times.push_back(decaytime) ;
200  integrals.push_back(integral) ;
201  }
202  // Make a spline interpolator of the decay time distributions, to be used to generate
203  // the decay times.
204  ostringstream splinename ;
205  splinename << "timespline_tag_" << tag ;
206  string splinenamestr = splinename.str() ;
207  TSpline3 timespline(splinenamestr.c_str(), &times[0], &integrals[0], times.size()) ;
208  timespline.SetName(splinenamestr.c_str()) ;
209  m_timegenerators.insert(make_pair(tag, SplineGenerator(rndm, timespline))) ;
210  }
211  // Calculate the integrated CP asymmetry.
212  double integminus = m_timegenerators.find(-1)->second.integral() ;
213  double integplus = m_timegenerators.find(1)->second.integral() ;
214  cout << "Integrated CP asymmetry is " << (integplus - integminus)/(integplus + integminus) << endl ;
215  m_tagintegralfrac = integminus/(integminus + integplus) ;
216  double tauminus = m_timegenerators.find(-1)->second.mean() ;
217  double tauplus = m_timegenerators.find(1)->second.mean() ;
218  cout << "Tau minus: " << tauminus << endl ;
219  cout << "Tau plus: " << tauplus << endl ;
220  cout << "AGamma: " << (tauminus - tauplus)/(tauminus + tauplus) << endl ;
221 
222  if( m_h_efficiency != NULL){
223  m_efficiencyFit = TSpline3(m_h_efficiency) ;
224  }
225 }
226 
227 // Get the coefficients of the amplitudes for the produced flavour and the mixed flavour
228 // given the tag and decay time.
230 TimeDependentGeneratorOld::amplitude_coefficients(const int tag, const double decaytime) {
231  double coeff = exp(-decaytime * 0.5 * (m_width + 0.5 * m_deltagamma)) ;
232  complex<double> expterm = exp(complex<double>(0.5 * m_deltagamma * decaytime, m_deltam * decaytime)) ;
233  complex<double> plusterm = 1. + expterm ;
234  complex<double> minusterm = 1. - expterm ;
235  complex<double> coeffprod = coeff * plusterm ;
236  complex<double> coeffmix = pow(polar(m_qoverp, m_phi), tag) * coeff * minusterm ;
237  return AmpPair(coeffprod, coeffmix) ;
238 }
239 
240 // Generate a flavour.
242  double rndm = m_rndm->Rndm() ;
243  if(rndm < m_tagintegralfrac)
244  return -1 ;
245  return 1 ;
246 }
247 
248 // Generate a decay time for the given flavour.
250  double decaytime = m_tmax + 1. ;
251  while(decaytime > m_tmax)
252  decaytime = m_timegenerators.find(tag)->second.gen_random() ;
253  return decaytime ;
254 }
255 
256 // Generate a Dalitz event for the given flavour and decay time.
258  const GenList& genlist = m_genmap.find(tag)->second ;
259  GenList::const_iterator igen = genlist.begin() ;
260  while(igen->decaytime < decaytime && igen != genlist.end())
261  ++igen ;
262  if(igen == genlist.end()){
263  cerr << "TimeDependentGeneratorOld::generate_dalitz_event: ERROR: Got impossible decay time: "
264  << decaytime << " (tmax = " << m_tmax << ")" << endl ;
266  }
267  // Unlikely, but best to check.
268  if(decaytime == igen->decaytime)
269  return igen->generator->newEvent() ;
270  GenList::const_iterator igenprev(igen) ;
271  --igen ;
272  // Pick between the generators either side of the decay time according to how close they are to it.
273  double gensel = m_rndm->Rndm() ;
274  if(gensel < 1. - (decaytime - igenprev->decaytime)/(igen->decaytime - igenprev->decaytime))
275  return igenprev->generator->newEvent() ;
276  return igen->generator->newEvent() ;
277 }
278 
279 // Generate a flavour, decay time and Dalitz event.
281  int tag = generate_tag() ;
282  double decaytime = generate_decay_time(tag) ;
283  double smeareddecaytime = -999. ;
284 
285  smeareddecaytime = decaytime + m_rndm->Gaus(0, m_resWidth) ;
286 
287  if ( (m_h_efficiency != NULL) && (m_addExpEffects) ){
288  int i = 0 ;
289  float efficiency = 0 ;
290  int maxiter = 100000 ;
291  while(true){
292  if( smeareddecaytime > m_efficiencyFit.GetXmax() ){
293  efficiency = m_efficiencyFit.Eval( m_efficiencyFit.GetXmax() ) ;
294  }
295  else if( smeareddecaytime > m_efficiencyFit.GetXmin() ){
296  efficiency = m_efficiencyFit.Eval( smeareddecaytime ) ;
297  }
298  else{
299  efficiency = m_efficiencyFit.Eval( m_efficiencyFit.GetXmin() ) ;
300  }
301 
302  if(m_rndm->Rndm() < efficiency){
303  break;
304  }
305 
306  tag = generate_tag() ;
307  decaytime = generate_decay_time(tag) ;
308  smeareddecaytime = decaytime + m_rndm->Gaus(0, m_resWidth);
309 
310  i += 1 ;
311  if( i > maxiter ){
312  cout << "WARNING: Decay time generation limit exceeded." << endl ;
313  break ;
314  }
315  }
316  }
318  return MINT::counted_ptr<IDalitzEvent>(new GenTimeEvent(*evt, tag, decaytime, smeareddecaytime)) ;
319 }
320 
321 // Get the decay time generators.
322 const map<int, SplineGenerator> TimeDependentGeneratorOld::time_generators() const {
323  return m_timegenerators;
324 }
TimeDependentGeneratorOld(const std::string &name, const bool overwrite, TRandom3 *rndm, double precision, const DalitzEventPattern &pattern, double width, double deltam, double deltagamma, double qoverp, double phi, double tmax, int ntimepoints, const bool saveIntegEvents=true, double tmin=0., TH1F *h_efficiency=NULL, float resWidth=0.05, bool addExpEffects=false)
const DalitzEventPattern m_cppattern
virtual int add(const FitAmpListBase &other, double factor=1)
MINT::counted_ptr< IDalitzEvent > generate_dalitz_event(const int tag, const double decaytime) const
virtual const std::vector< double > & getVectorOfValues() const
bool exists(const string &fname)
const DalitzEventPattern m_pattern
static std::map< std::string, unsigned > infoNames
std::list< GenTimePoint > GenList
GenTimePoint(const double _decaytime, FitAmpSum *_model, const double _integral, SignalGenerator *_generator)
std::pair< std::complex< double >, std::complex< double > > AmpPair
AmpPair amplitude_coefficients(const int tag, const double decaytime)
std::map< int, SplineGenerator > m_timegenerators
virtual MINT::counted_ptr< IIntegrationCalculator > makeIntegrationCalculator()
Definition: FitAmpSum.cpp:328
double generate_decay_time(const int tag) const
GenTimeEvent(const IDalitzEvent &, const int, const double, const double smeareddecaytime=-999.)
virtual bool retrieve(const std::string &dirname)=0
const std::map< int, SplineGenerator > time_generators() const
static DalitzEventPattern anti(DalitzEventPattern pat)
static std::map< std::string, unsigned > makeInfoNames()
MINT::counted_ptr< IDalitzEvent > generate_event() const