ROOTPWA
genPhaseSpaceData.C
Go to the documentation of this file.
1 #include <iostream>
2 #include <iomanip>
3 #include <fstream>
4 #include <sstream>
5 
6 #include "TVector3.h"
7 #include "TLorentzVector.h"
8 #include "TH1D.h"
9 #include "TH2D.h"
10 #include "TH3D.h"
11 #include "TGenPhaseSpace.h"
12 //#include "../../generators/nBodyPhaseSpaceGen.h"
13 #include "TCanvas.h"
14 #include "TRandom3.h"
15 #include "TFile.h"
16 #include "TTree.h"
17 #include "TStyle.h"
18 #include "TROOT.h"
19 #include "TMath.h"
20 
21 // to run it do for example:
22 // > root -l
23 // root [0] .L genPhaseSpaceData.C+
24 // root [1] genPhaseSpaceData(-1., 5., "", "./hTheta.root", 100000);
25 
26 
27 using namespace std;
28 
29 
31 // global constants
32 
33 // particle masses PDG 2008
34 const double gProtonMass = 0.938272013;
35 const double gPionMass = 0.13957018;
36 //const double gPionMass2 = gPionMass * gPionMass;
37 const double gKaonMass = 0.493677;
38 //const double gKaonMass2 = gKaonMass * gKaonMass;
39 
40 // steering of the 3 particle decay
41 // last particle is also the beam particle
42 
43 /*
44 // decay into 3 pions
45 const string header(" *************************************\n * simulating decay into pi- pi+ pi- *\n *************************************\n");
46 const int geantIds[3] = { 8, 9, 9};
47 const int charges[3] = {+1, -1, -1};
48 Double_t daughterMasses[3] = {gPionMass, gPionMass, gPionMass};
49 */
50 
51 // K- p -> K- pi+ pi- p
52 //const int numbPart = 3;
53 const string header(" ************************************\n * simulating decay into K- pi+ pi- *\n ************************************\n");
54 const int geantIds[3] = { 8, 9, 12};
55 const int charges[3] = {+1, -1, -1};
57 
58 
60 
61 // target position
62 // simple tube distribution according to 2008 H2 target cell dimensions
63 const double gTargetZPos = -30.0; // [cm] (target cell end)
64 const double gTargetlength = -40.0; // [cm] (twards upstream)
65 
66 // beam parameters:
67 const double gBeamMomSigma = 1.2; // [GeV/c]
68 //const double gBeamMom = 189; // [GeV/c]
69 
70 // measured K- beam energy in 2008 for K pi pi diffractive processes
71 const double gBeamMom = 191; // [GeV/c]
72 // 2004 beam:
73  const double gBeamDxDz = 0.00026; // tilt from Quirin was in mrad
74  const double gBeamDxDzSigma = 0.00010;
75  const double gBeamDyDz = 0.00001; // tilt from Quirin was in mrad
76  const double gBeamDyDzSigma = 0.00018;
77 // ideal beam:
78 //const double gBeamDxDz = 0.0;
79 //const double gBeamDxDzSigma = 0.0;
80 //const double gBeamDyDz = 0.0;
81 //const double gBeamDyDzSigma = 0.0;
82 
83 // beamspot parameters [cm]
84 const double gBeamOffsetX = 0.0;
85 const double gBeamOffsetY = 0.0;
86 const double gBeamSpotSizeX = 1.5; // in terms of 3 sigma
87 const double gBeamSpotSizeY = 1.5;
88 
89 // cut on t-distribution
90 const double tMin = 0.001; // [(GeV/c)^2]
91 
92 
94 // helper functions
95 
96 // constructs beam Lorentz vector
97 TLorentzVector
99 {
100  // throw magnituide of beam momentum
101  const double pBeam = gRandom->Gaus(gBeamMom, gBeamMomSigma);
102  // throw beam inclination
103  const double dxdz = gRandom->Gaus(gBeamDxDz, gBeamDxDzSigma);
104  const double dydz = gRandom->Gaus(gBeamDyDz, gBeamDyDzSigma);
105  // construct tilted beam momentum Lorentz vector
106  const double pz = pBeam / sqrt(1 + dxdz * dxdz + dydz * dydz);
107  const double px = dxdz * pz;
108  const double py = dydz * pz;
109  const double EBeam = sqrt(pBeam * pBeam + gbeampartMass2);
110  return TLorentzVector(px, py, pz, EBeam);
111 }
112 
113 // constructs Interaction point in the target cell
114 TVector3
116 {
117  TVector3 result;
118  result.SetX(gRandom->Gaus(gBeamOffsetX, gBeamSpotSizeX/3.));
119  result.SetY(gRandom->Gaus(gBeamOffsetY, gBeamSpotSizeY/3.));
120  result.SetZ(gRandom->Uniform(gTargetZPos+gTargetlength, gTargetZPos));
121  return result;
122 }
123 
124 
125 // writes event to ascii file read by gamp
126 bool
127 writePwa2000Ascii(ostream& out,
128  const TLorentzVector& beam,
129  TGenPhaseSpace& event)
130 {
131  if (!out) {
132  cerr << "Output stream is not writable." << endl;
133  return false;
134  }
135 
136  // total number of particles
137  out << 4 << endl;
138  // beam particle: geant ID, charge, p_x, p_y, p_z, E
139  out << setprecision(numeric_limits<double>::digits10 + 1)
140  << geantIds[2] << " " << charges[2] << " " << beam.Px() << " " << beam.Py() << " " << beam.Pz() << " " << beam.E() << endl;
141  for (unsigned int i = 0; i < 3; ++i) {
142  TLorentzVector* hadron = event.GetDecay(i);
143  if (!hadron) {
144  cerr << "genbod returns NULL pointer to Lorentz vector for daughter " << i << "." << endl;
145  continue;
146  }
147  // hadron: geant ID, charge, p_x, p_y, p_z, E
148  out << setprecision(numeric_limits<double>::digits10 + 1)
149  << geantIds[i] << " " << charges[i] << " " << hadron->Px() << " " << hadron->Py() << " " << hadron->Pz() << " " << hadron->E() << endl;
150  }
151  return true;
152 }
153 
154 // writes event to ascii file read by ComGeant fort.26 interface
155 bool
156 writeComGeantAscii(ostream& out,
157  const TLorentzVector& beam,
158  TGenPhaseSpace& event,
159  const TVector3& vertexpos,
160  const TLorentzVector& recoilproton,
161  bool formated = true) // true: text file ; false: binary file
162 {
163  if (!out) {
164  cerr << "Output stream is not writable." << endl;
165  return false;
166  }
167 
168  if (formated){
169  // total number of particles
170  out << 5 << endl;
171  // vertex position in cm
172  // note that Comgeant's coordinate system is different
173  out << vertexpos.Z() << " " << vertexpos.X() << " " << vertexpos.Y() << endl;
174  // beam particle: geant ID , -p_z, -p_x, -p_y must go the opposite direction upstream and should be defined as mulike with PID 44 in Comgeant
175  out << setprecision(numeric_limits<double>::digits10 + 1)
176  << "44 " << -beam.Pz() << " " << -beam.Px() << " " << -beam.Py() << endl;// << " " << beam.E() << endl;
177  // the recoil proton
178  out << setprecision(numeric_limits<double>::digits10 + 1)
179  << "14 " << recoilproton.Pz() << " " << recoilproton.Px() << " " << recoilproton.Py() << endl;// << " " << beam.E() << endl;
180  }
181 
182  for (unsigned int i = 0; i < 3; ++i) {
183  TLorentzVector* hadron = event.GetDecay(i);
184  if (!hadron) {
185  cerr << "genbod returns NULL pointer to Lorentz vector for daughter " << i << "." << endl;
186  continue;
187  }
188  // hadron: geant ID, p_z, p_x, p_y
189  out << setprecision(numeric_limits<double>::digits10 + 1)
190  << geantIds[i] << " " << hadron->Pz() << " " << hadron->Px() << " " << hadron->Py() << endl;// << " " << hadron->E() << endl;
191  }
192  return true;
193 }
194 
195 
196 ostream&
197 progressIndicator(const long currentPos,
198  const long nmbTotal,
199  const int nmbSteps = 10,
200  ostream& out = cout)
201 {
202  const double step = nmbTotal / (double)nmbSteps;
203  if ((nmbTotal >= 0) && ((int)(currentPos / step) - (int)((currentPos - 1) / step) != 0)){
204  out << "\x1B[2K" << "\x1B[0E" << " " << setw(3) << (int)(currentPos / step) * nmbSteps << "%";
205  flush(out);
206  }
207  return out;
208 }
209 
210 // return the phi angle between the decaying system and the recoil proton
211 // test for the coplanarity
212 float
213 GetPhi( //ostream& out,
214  const TLorentzVector& beam,
215  TGenPhaseSpace& event,
216  //const TVector3& vertexpos,
217  const TLorentzVector& recoilproton){
218 
219  float result(0);
220  TLorentzVector hadrons(0.,0.,0.,0.);
221  for (unsigned int i = 0; i < 3; ++i) {
222  TLorentzVector* hadron = event.GetDecay(i);
223  if (!hadron) {
224  cerr << "genbod returns NULL pointer to Lorentz vector for daughter " << i << "." << endl;
225  continue;
226  }
227  // reconstruct the resonance to test GenPhaseSpace here, too
228  hadrons += *hadron;
229  }
230  result = fabs(recoilproton.DeltaPhi(hadrons))-TMath::Pi();
231  return result;
232 }
233 
234 float
235 Calc_t_prime(const TLorentzVector& particle_In, const TLorentzVector& particle_Out){
236  float result = 0.;
237  //cout << particle_In.M() << " " << particle_In.E() << endl;
238  result = (particle_Out.M2()-particle_In.M2());
239  //hist_t_prime_M_diff->Fill(sqrt(result));
240  result = pow(result,2);
241  result /= 4*pow(particle_In.P(),2);
242  //hist_t_prime_P_part_In->Fill(particle_In.P());
243  result = fabs((particle_In-particle_Out).M2())-fabs(result);
244  //hist_t_prime->Fill(result);
245 
246  //comparison->Fill_tprime_promme(result);
247 
248  return result;
249 }
250 
251 
252 
254 // main routine
255 void
256 genPhaseSpaceData(const double xMassMin = 2.100, // lower bound of mass bin [GeV/c^2]
257  // if -1 then the lower mass will be calculated to be the minimum
258  const double xMassMax = 2.140, // upper bound of mass bin [GeV/c^2]
259  const TString& outFileName = "2100.2140.genbod.evt",
260  // if empty filename will be generated according to mass limits
261  const TString& thetaHistFileName = "./hTheta.root", // histogram with experimental distribution of scattering angle
262  const int nmbEvent = 2000,
263  const bool plot = true,
264  const TString& outFileNameComGeant = "" // outputfilename for Comgeant output, if empty filename will be generated according to mass limits
265  )
266 {
267 
268  cout << header << endl;
269  gRandom->SetSeed(12345);
270 
271 
272  // setup histograms
273 // TH1D* ht;
274 // TH1D* hm;
275 // TH1D* hTheta;
276 // TH3D* hVertex3D;
277 // TH2D* hVertex;
278 // TH1D* hVz;
279 // TH1D* hE;
280  TFile temp("/tmp/buffer.root", "RECREATE");
281  TTree* values = new TTree("values","values");
282  double t = 0;
283  double tprime = 0;
284  double M123 = 0;
285  double M12 = 0;
286  double M13 = 0;
287  double M23 = 0;
288  double theta = 0;
289  double dphi = 0;
290  double Vx = 0;
291  double Vy = 0;
292  double Vz = 0;
293  double dxdz = 0;
294  double dydz = 0;
295  double E = 0;
296  values->Branch("t", &t, "t/D");
297  values->Branch("tprime", &tprime, "tprime/D");
298  values->Branch("M123", &M123, "M123/D");
299  values->Branch("M12", &M12, "M12/D");
300  values->Branch("M13", &M13, "M13/D");
301  values->Branch("M23", &M23, "M23/D");
302  values->Branch("theta", &theta, "theta/D");
303  values->Branch("dphi", &dphi, "dphi/D");
304  values->Branch("Vx", &Vx, "Vx/D");
305  values->Branch("Vy", &Vy, "Vy/D");
306  values->Branch("Vz", &Vz, "Vz/D");
307  values->Branch("dxdz", &dxdz, "dxdz/D");
308  values->Branch("dydz", &dydz, "dydz/D");
309  values->Branch("E", &E, "E/D");
310  /*
311  if (plot) {
312 
313  ht = new TH1D("ht", "t", 10000, -0.1, 1);
314  hm = new TH1D("hm", "3pi mass", 1000, 0.5, 2.5);
315  hTheta = new TH1D("hThetaGen", "cos theta", 100, 0.99985, 1);
316  hVertex3D = new TH3D("hVertex3D", "Vertex xyz", 100, -2, 2, 100, -2, 2, 200, gTargetZPos + gTargetlength -10 , gTargetZPos + 10);
317  hVertex = new TH2D("hVertex", "Vertex xy", 100, -2, 2, 100, -2, 2);
318  hVz = new TH1D("hVz","Vertex z", 1000, gTargetZPos + gTargetlength -10 , gTargetZPos +10);
319  hE = new TH1D("hE", "E", 100, 180, 200);
320  }*/
321 
322  double _xMassMin = xMassMin;
323  if (_xMassMin < 0){
324  _xMassMin = 0;
325  for (int i = 0; i < 3; i++){
326  _xMassMin+=daughterMasses[i];
327  }
328  cout << " calculating the invariant mass bin to be " << _xMassMin;
329  }
330 
331  // generate filename if needed
332  TString _outFileName = outFileName;
333  if (_outFileName == ""){
334  stringstream _filename;
335  _filename << trunc(_xMassMin*1e3) << "." << trunc(xMassMax*1e3) << ".genbod.26";
336  cout << " created genbot events filename: " << _filename.str() << endl;
337  _outFileName = _filename.str();
338  }
339 
340  // open output files
341  ofstream outFile(_outFileName);
342 
343  // generate filename if needed
344  TString _outFileNameComGeant = outFileNameComGeant;
345  if (_outFileNameComGeant == ""){
346  stringstream _filename;
347  _filename << trunc(_xMassMin*1e3) << "." << trunc(xMassMax*1e3) << ".genbod.fort.26";
348  cout << " created ComGeantevents filename: " << _filename.str() << endl;
349  _outFileNameComGeant = _filename.str();
350  }
351 
352  ofstream outFileComGeant(_outFileNameComGeant);//, ios::binary);
353  //cout << " Writing binary outputfile for ComGeant ! " << endl; // remove ios::binary to make a textfile (bigger)
354 
355  cout << "Writing " << nmbEvent << " events to file " << _outFileName << " and " << _outFileNameComGeant << "." << endl;
356 
357  // get theta histogram
358  TH1* thetaDist = NULL;
359  {
360  TFile* thetaHistFile = TFile::Open(thetaHistFileName, "READ");
361  if (!thetaHistFile || thetaHistFile->IsZombie()) {
362  cerr << "Cannot open histogram file '" << thetaHistFileName << "'. exiting." << endl;
363  return;
364  }
365  thetaHistFile->GetObject("h1", thetaDist);
366  if (!thetaDist) {
367  cerr << "Cannot find theta histogram in file '" << thetaHistFileName << "'. exiting." << endl;
368  return;
369  }
370  }
371 
372  int countEvent = 0;
373  int attempts = 0;
374  int tenpercent = (int)(nmbEvent * 0.1);
375  while (countEvent < nmbEvent) { // loop over events
376  ++attempts;
377 
378  // construct primary vertex and beam
379  const TVector3 vertexPos = makeVertex();// (0, 0, gTargetZPos);
380  const TLorentzVector beam = makeBeam();
381 
382  // sample theta directly:
383  /*const double*/ theta = thetaDist->GetRandom();
384  const double xMass = gRandom->Uniform(_xMassMin, xMassMax);
385  const double xMass2 = xMass * xMass;
386 
387  const double Ea = beam.E();
388  // account for recoil assume proton recoil
389  const double eps = (xMass2 - gbeampartMass2) / (2 * gProtonMass * Ea);
390  const double epso = 1 - eps;
391  const double eat = Ea * theta;
392  //eat *= eat;
393  const double mpeps = gProtonMass * eps;
394  const double e = Ea - 1 / (2 * gProtonMass * epso) * (eat * eat + mpeps * mpeps);
395  const double pw = sqrt(e * e - xMass2); // three momentum magnitude
396  const double phi= gRandom->Uniform(0., TMath::TwoPi());
397 
398  TVector3 p3(1, 0, 0);
399  p3.SetMagThetaPhi(pw, theta, phi);
400  // rotate to beamdirection:
401  p3.RotateUz(beam.Vect().Unit());
402 
403  // build resonance
404  TLorentzVector X(p3, e);
405  const TLorentzVector q = beam - X;
406 
407  // apply t cut
408  const double tGen = -q.M2();
409  if (tGen < tMin)
410  continue;
411 
412  // generate phase space distribution with root's simple generator
413  TGenPhaseSpace phaseSpace;
414 
415  bool allowed = phaseSpace.SetDecay(X, 3, daughterMasses);
416  if (!allowed) {
417  cerr << "Decay of M = " << X.M() << " into 3 particles is not allowed!" << endl;
418  continue;
419  }
420  double maxWeight = phaseSpace.GetWtMax();
421  double weight = phaseSpace.Generate();
422 
423  if (weight / maxWeight < gRandom->Uniform())
424  // rejection sampling is needed to have more events for the higher
425  // masses. For higher masses the phase space is increased and therefore
426  // more events are needed to keep the statistical error on the same level
427  continue;
428 
429  // event is accepted
430  ++countEvent;
431  progressIndicator(countEvent, nmbEvent);
432 
433  t = tGen;
434  TLorentzVector partout = (
435  *(phaseSpace.GetDecay(0)) +
436  *(phaseSpace.GetDecay(1)) +
437  *(phaseSpace.GetDecay(2)));
438  tprime = Calc_t_prime(beam,partout);
439  M123 = partout.M();
440  M12 = ( *(phaseSpace.GetDecay(0)) +
441  *(phaseSpace.GetDecay(1))).M();
442  M13 = ( *(phaseSpace.GetDecay(0)) +
443  *(phaseSpace.GetDecay(2))).M();
444  M23 = ( *(phaseSpace.GetDecay(1)) +
445  *(phaseSpace.GetDecay(2))).M();
446  theta = q.Theta();
447  dphi = GetPhi(beam, phaseSpace, q);
448  Vx = vertexPos.X();
449  Vy = vertexPos.Y();
450  Vz = vertexPos.Z();
451  dxdz = beam.X()/beam.Z();
452  dydz = beam.Y()/beam.Z();
453  E = Ea;
454 
455  values->Fill();
456 
457  writePwa2000Ascii(outFile, beam, phaseSpace);
458  writeComGeantAscii(outFileComGeant, beam, phaseSpace, vertexPos, q);
459  }
460 
461  cout << endl << "Needed " << attempts << " attempts to generate " << countEvent << " events." << endl;
462  outFile.close();
463  outFileComGeant.close();
464 
465  if (plot) {
466  gROOT->SetStyle("Plain");
467  gStyle->SetPalette(1);
468  gROOT->ForceStyle();
469  TCanvas* c = new TCanvas("c", "c", 10, 10, 1000, 1000);
470  c->Divide(4, 4);
471  c->cd(1);
472  values->Draw("M123");
473  c->cd(2);
474  values->Draw("M12");
475  c->cd(3);
476  values->Draw("M13");
477  c->cd(4);
478  values->Draw("M23");
479  c->cd(5);
480  gPad->SetLogy();
481  values->Draw("t");
482  c->cd(6);
483  gPad->SetLogy();
484  values->Draw("tprime");
485  c->cd(7);
486  values->Draw("theta");
487  c->cd(8);
488  values->Draw("dphi");
489  c->cd(9);
490  values->Draw("E");
491  c->cd(10);
492  values->Draw("Vx:Vy", "", "COLZ");
493  c->cd(11);
494  values->Draw("Vz");
495  c->cd(12);
496  values->Draw("M12:M13", "", "COLZ");
497  c->cd(13);
498  values->Draw("M12:M23", "", "COLZ");
499  c->cd(14);
500  values->Draw("M13:M23", "", "COLZ");
501  c->cd(15);
502  values->Draw("dxdz");
503  c->cd(16);
504  values->Draw("dydz");
505  c->Update();
506  c->Print("event_properties.pdf");
507  }
508 }
509 
510 
511 
512