eic-smear  1.0.3
A collection of ROOT classes for Monte Carlo events and a fast-smearing code simulating detector effects for the Electron-Ion Collider task force
EventFactory.cxx
Go to the documentation of this file.
1 
11 
12 #include <memory>
13 #include <stdexcept>
14 #include <string>
15 
16 #include <TClass.h>
17 #include <TProcessID.h>
18 
27 #include "eicsmear/functions.h" // For getFirstNonBlank()
31 
32 namespace erhic {
33 
34 template<typename T>
36  return !mLine.empty()
37  && mLine.find("finished") != std::string::npos;
38 }
39 
40 // Use this struct to automatically reset TProcessID object count.
42  // Initialse object with current TProcessID object count.
44  count = TProcessID::GetObjectCount();
45  }
46  // Restore object count to the value at initialisation.
47  // See example in $ROOTSYS/test/Event.cxx
48  // To save space in the table keeping track of all referenced objects
49  // we assume that our events do not address each other.
51  TProcessID::SetObjectCount(count);
52  }
53  int count;
54 };
55 
56 template<typename T>
58  // Save current object count. Will reset it when this function returns.
59  TProcessIdObjectCount objectCount;
60  mEvent.reset(new T);
61  // We use this flag to check input doesn't end mid-event.
62  // Initialised finished flag to "success" in case of no input.
63  int finished(0);
64  std::string error;
65  // Read line-by-line until the stream is not good or we break out.
66  while (std::getline(*mInput, mLine).good()) {
67  // Reached end-of-event marker
68  if (AtEndOfEvent()) {
69  // If we built a good event (i.e. no errors reading strings)
70  // perform end-of-event calculations.
71  if (!error.empty()) {
72  throw std::runtime_error(error);
73  } else {
74  finished = FinishEvent(); // 0 upon success
75  break;
76  } // if
77  } else if ('0' == getFirstNonBlank(mLine)) {
78  // '0' indicates the event header line
79  // An event started, set finished flag to "unfinished".
80  finished = -1;
81  // Parse string and check for validity.
82  if (!mEvent->Parse(mLine)) {
83  // Set error message based on bad event input.
84  // Don't break out of the loop yet, so that we continue reading
85  // lines until the end-of-event marker. That way we stay
86  // "aligned" with the input data ready for the next event.
87  error = "Bad event input: " + mLine;
88  } // if
89  } else if ('=' != getFirstNonBlank(mLine)) {
90  // Anything remaining other than a line of '=' is a particle line
91  // Don't raise an exception for a failed track, as the event in
92  // general may be OK. AddParticle will print a message though.
93  if (!AddParticle()) {
94  error = "Bad particle input in event";
95  } // if
96  } // if
97  } // if
98  // Check for events that started but did not finish.
99  // We should have ended with an end-of-event marker, meaning the finished
100  // flag is set to zero. If not, the finished flag will be non-zero.
101  if (finished != 0) {
102  mEvent.reset(NULL);
103  throw std::runtime_error("Ended mid-event");
104  } // if
105  // Return a NULL event *without* throwing an exception to indicate
106  // end-of-file. We shouldn't have hit eof if we have read a good event,
107  // as we won't have yet tried to read past the end (mLine will still be
108  // at the end-of-file marker line).
109  if (mInput->eof()) {
110  mEvent.reset(NULL);
111  } // if
112  return mEvent.release();
113 }
114 
115 template<typename T>
117  std::auto_ptr<DisKinematics> nm(
118  LeptonKinematicsComputer(*mEvent).Calculate());
119  std::auto_ptr<DisKinematics> jb(
120  JacquetBlondelComputer(*mEvent).Calculate());
121  std::auto_ptr<DisKinematics> da(
122  DoubleAngleComputer(*mEvent).Calculate());
123  if (nm.get()) {
124  mEvent->SetLeptonKinematics(*nm);
125  } // if
126  for (unsigned n(0); n < mEvent->GetNTracks(); ++n) {
127  mEvent->GetTrack(n)->ComputeEventDependentQuantities(*mEvent);
128  } // for
129  if (jb.get()) {
130  mEvent->SetJacquetBlondelKinematics(*jb);
131  } // if
132  if (da.get()) {
133  mEvent->SetDoubleAngleKinematics(*da);
134  } // if
135  // We also have to set the remaining variables not taken care of
136  // by the general DIS event kinematic computations.
137  // Find the beams, exchange boson, scattered lepton.
138  BeamParticles beams;
139  if (!ParticleIdentifier::IdentifyBeams(*mEvent, beams)) {
140  std::cerr <<
141  "EventFromAsciiFactory::FinishEvent(): failed to find beams"
142  << std::endl;
143  return 0;
144  } // if
145  const TLorentzVector h = beams.BeamHadron();
146  TLorentzVector l = beams.BeamLepton();
147  TLorentzVector s = beams.ScatteredLepton();
148  TVector3 boost = -h.BoostVector();
149  l.Boost(boost);
150  s.Boost(boost);
151  mEvent->SetELeptonInNuclearFrame(l.E());
152  mEvent->SetEScatteredInNuclearFrame(s.E());
153  return 0;
154 }
155 
156 template<typename T>
158  try {
159  if (mEvent.get()) {
160  ParticleMC particle(mLine); // Throws if the string is bad
161  particle.SetEvent(mEvent.get());
162  mEvent->AddLast(&particle);
163  } // if
164  return true;
165  } // try
166  catch(std::exception& error) {
167  std::cerr << "Exception building particle: " << error.what() << std::endl;
168  return false;
169  }
170 }
171 
172 template<typename T>
174  return T::Class()->GetName();
175 }
176 
177 } // namespace erhic
178 
179 namespace {
180 
181 // Need this to generate the CINT code for each version
189 
190 } // namespace
void SetEvent(EventMC *event)
Definition: ParticleMC.cxx:280
char getFirstNonBlank(const std::string &)
Definition: functions.cxx:31
virtual std::string EventName() const
static bool IdentifyBeams(const erhic::VirtualEvent &, BeamParticles &)