LEInjector.cc
Go to the documentation of this file.
1 #include <sstream>
2 #include <vector>
3 
4 #include <utl/config.h>
5 
6 #include <det/Detector.h>
7 
8 #include <sdet/SDetector.h>
9 #include <sdet/Station.h>
10 
11 #include <evt/Event.h>
12 
13 
14 #include <fwk/CentralConfig.h>
15 #include <fwk/RandomEngineRegistry.h>
16 #include <io/CorsikaUtilities.h>
17 
18 #include <sevt/SEvent.h>
19 #include <sevt/Header.h>
20 #include <sevt/Station.h>
21 #include <sevt/StationSimData.h>
22 
23 #include <utl/AugerCoordinateSystem.h>
24 #include <utl/AugerUnits.h>
25 #include <utl/Math.h>
26 #include <utl/MathConstants.h>
27 #include <utl/Particle.h>
28 #include <utl/PhysicalConstants.h>
29 #include <utl/Point.h>
30 #include <utl/TimeStamp.h>
31 #include <utl/ErrorLogger.h>
32 #include <utl/Reader.h>
33 #include <utl/Vector.h>
34 #include <utl/GeometryUtilities.h>
35 #include <utl/MathConstants.h>
36 
37 #include <CLHEP/Random/Randomize.h>
38 
39 #include "LEInjector.h"
40 
41 using namespace det;
42 using namespace evt;
43 using namespace fwk;
44 using namespace sevt;
45 using namespace utl;
46 using namespace utl::GeometryUtilities;
47 using namespace std;
48 using CLHEP::RandFlat;
49 using namespace LEInjectorOG;
50 
51 
52 LEInjector::LEInjector() :
53  fStationId(0),
54  fInputStream(0),
55  fVerticalMuonMode(false),
56  fRandomEngine(0)
57 { }
58 
59 
62 {
63 
64  const Branch topB =
65  CentralConfig::GetInstance()->GetTopBranch("LEInjector");
66 
67  topB.GetChild("StationId").GetData(fStationId);
68  topB.GetChild("Filename").GetData(fFileName);
69  topB.GetChild("VerticalMuonMode").GetData(fVerticalMuonMode);
70 
72  INFO("Operating LE Injector in vertical muon mode!");
73 
74 
76  &RandomEngineRegistry::GetInstance().
77  Get(RandomEngineRegistry::eDetector).GetEngine();
78 
79  fInputStream = new ifstream(fFileName.c_str());
80  if (!fInputStream->is_open()) {
81  ostringstream msg;
82  msg << "Unable to open the requested file : " << fFileName;
83  ERROR(msg);
84  throw IOFailureException("unable to open file");
85  }
86  return eSuccess;
87 }
88 
89 
92 {
93  INFO("LEInjector::Run");
94  if (!event.HasSEvent()) {
95  ERROR("No Event. giving up");
96  throw NonExistentComponentException("No SEvent present.");
97  }
98 
99 
100  SEvent& sEvent = event.GetSEvent();
101 
102  if (!sEvent.HasStation(fStationId))
103  sEvent.MakeStation(fStationId);
104 
105  Station& station = sEvent.GetStation(fStationId);
106 
107  if (!station.HasSimData())
108  station.MakeSimData();
109 
110  station.GetSimData().ClearParticleList();
111 
112  const sdet::Station& dStation =
113  det::Detector::GetInstance().GetSDetector().GetStation(station);
114  const CoordinateSystemPtr stationCS = dStation.GetLocalCoordinateSystem();
115 
116  int particleId;
117  double px;
118  double py;
119  double pz;
120  double x;
121  double y;
122  double time;
123  unsigned primaryShowerId;
124  int primaryParticleId;
125  double primaryEnergy;
126  double primaryTheta;
127  double primaryPhi;
128 
129  string line;
130 
131  do {
132 
133  if (!getline(*fInputStream, line)) {
134  fInputStream->close();
135  return eBreakLoop;
136  }
137 
138  istringstream iss(line);
139 
140  if (!(iss >> particleId
141  >> px >> py >> pz
142  >> x >> y
143  >> time
144  >> primaryShowerId
145  >> primaryParticleId
146  >> primaryEnergy
147  >> primaryTheta
148  >> primaryPhi)){
149  ERROR("Malformed line.");
150  return eFailure;
151  }
152 
153  } while (particleId == 201 || particleId == 301 || particleId == 402); // for G4's sake skip Deuterium, Tritium or Helium
154 
155  // fix up the units, particle id's
156  particleId = io::Corsika::CorsikaToPDG(particleId);
157  px *= GeV; py *= GeV; pz *= -GeV;
158  x *= cm; y *= cm;
159  time *= second;
160  primaryParticleId = io::Corsika::CorsikaToPDG(primaryParticleId);
161  primaryEnergy *= GeV;
162  primaryTheta *= degree;
163  primaryPhi *= degree;
164 
165  double pMomentum = sqrt(Sqr(px) + Sqr(py) + Sqr(pz)); // particle momentum (GeV)
166  double pTheta = acos(-pz / pMomentum); // particle's zenith angle
167  double pPhi = atan2(-py, -px); // particle's azimuth angle
168 
169 
170  /*
171  pPhi has to be modified.
172  Rotate form the Corsika coordinate system to Auger standard.
173  Auger places the x axis east and the y axis north. Corsika places
174  the x axis in the magnetic north and the y axis west. Therefore,
175  the geomagnetic field direction for the location and time of an
176  event has to be taken into account for the correct transformation.
177 
178  using io::Corsika::CorsikaAzimuthToAuger()
179  */
180 
181  // virtual cylinder dimensions (slightly bigger than actual tank to include SSD on top)
182  const double sRadius = 1800*mm + 13*mm;
183  const double sHeight = 1500*mm + 10*mm + .6*mm + 5*mm + 50*mm; //eventually will be modified to actual SSD position
184 
185  // Scintillator dimensions eventually will be replaced by actual SSD dimensions
186  double scinLength = 1800*mm;
187  int nScinBars = 27;
188  double barWidth = 80*mm;
189  double scinWidth = nScinBars*barWidth;
190 
191 
192  /*
193  We define a virtual cylinder of radius = sRadius and h = sHeight where the particles
194  will be injected.
195 
196  From the particle's point of view, the "effective" area seen by the particle is a projection
197  of the top area (circle) and a projection of the side area (cylinder)
198 
199  Then we compute the probability that the particle hits the top area dividing the value
200  of the EffectiveTopArea by the total effective area (EffTop+EffSide).
201 
202  Then we "decide" which area is hit by the particle just throwing random numbers and comparing
203  them with the probability defined above.
204 
205  If the particle hits the top area, we randomize its X,Y coordinates over a circle of radius sRadius
206  and fixing Z = sHeight.
207 
208  If the particle hits the side area, we randomize Z between 0 and sHeight the and phi
209  to give the position around the tank (with the radius fixed to sRadius)
210 
211  (These ideas were taken from CachedShowerRegenerator module).
212  */
213 
214  if (fVerticalMuonMode) {
215  // to inject vertical muons all over the scintillator
216  const double x = scinLength/2 * RandFlat::shoot(fRandomEngine, -1, 1);
217  const double y = scinWidth/2 * RandFlat::shoot(fRandomEngine, -1, 1);
218 
219  const Point position = Point(x, y, sHeight, stationCS);
220  const Vector momentum = Vector(0, 0, -1*GeV, stationCS, Vector::kCartesian);
221  const Particle particle =
222  Particle(13, utl::Particle::eBackground, position, momentum, 0, 1); // For this purpose particle's time is irrelevant
223 
224  station.AddParticle(particle);
225 
226  } // in case of VerticalMuonMode = ON
227 
228 
229  else {
230 
231  const double EffTopArea = kPi*Sqr(sRadius)*cos(pTheta); // pTheta is measured from the station reference plane
232  const double EffSideArea = 2*sRadius*sHeight*sin(pTheta);
233  const double ProbSeeTop = EffTopArea / (EffTopArea + EffSideArea);
234  const double rand1 = RandFlat::shoot(fRandomEngine, 0, 1);
235 
236 
237 
238  if (rand1 <= ProbSeeTop) { // Particle injected on the top
239 
240  const double rand2 = RandFlat::shoot(fRandomEngine, 0, 1);
241  const double r = sRadius*sqrt(rand2);
242  const double phi = RandFlat::shoot(fRandomEngine, 0, kTwoPi);
243 
244  const double x = r * cos(phi);
245  const double y = r * sin(phi);
246  const double z = sHeight;
247 
248  const Point position = Point(x, y, z, stationCS);
249  const Vector momentum = Vector(px, py, pz, stationCS, Vector::kCartesian);
250  const Particle particle =
251  Particle(particleId, utl::Particle::eBackground, position, momentum, 0, 1);
252 
253  station.AddParticle(particle);
254  }
255 
256  else { // Particle injected on the side
257 
258  // For the X and Y component we need to find the angle between
259  // the (tank) X-Y axis and the incoming particle direction. Then add
260  // an angle sampled from an arcsin distribution
261 
262 
263  const double rand2 = RandFlat::shoot(fRandomEngine, 0, 1);
264  const double rand3 = RandFlat::shoot(fRandomEngine, 0, 1);
265 
266  const double phi = pPhi + asin(1-2*rand2);
267 
268  const double z = sHeight*rand3;
269  const double x = sRadius * cos(phi);
270  const double y = sRadius * sin(phi);
271 
272  const Point position = Point(x, y, z, stationCS);
273  const Vector momentum = Vector(px, py, pz, stationCS, Vector::kCartesian);
274  const Particle particle =
275  Particle(particleId, utl::Particle::eBackground, position, momentum, 0, 1);
276 
277  station.AddParticle(particle);
278 
279  }
280  }
281 return eSuccess;
282 } // end LEInjector::Run()
283 
284 
285 
288 {
289  delete fInputStream;
290  return eSuccess;
291 }
292 
293 // Configure (x)emacs for this file ...
294 // Local Variables:
295 // mode: c++
296 // End:
Branch GetTopBranch() const
Definition: Branch.cc:63
constexpr double mm
Definition: AugerUnits.h:113
const double degree
constexpr T Sqr(const T &x)
Point object.
Definition: Point.h:32
bool HasStation(const int stationId) const
Check whether station exists.
Definition: SEvent.cc:81
Detector description interface for Station-related data.
Report success to RunController.
Definition: VModule.h:62
void MakeSimData()
Make station simulated data object.
Interface class to access to the SD part of an event.
Definition: SEvent.h:39
Describes a particle for Simulation.
Definition: Particle.h:26
void ClearParticleList()
Clear the station particle list.
#define INFO(message)
Macro for logging informational messages.
Definition: ErrorLogger.h:161
Base class for exceptions trying to access non-existing components.
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
Definition: Branch.cc:211
std::ifstream * fInputStream
Definition: LEInjector.h:70
Base class to report exceptions in IO.
boost::shared_ptr< const CoordinateTransformer > CoordinateSystemPtr
Shared pointer for coordinate systems.
Class representing a document branch.
Definition: Branch.h:107
Break current loop. It works for nested loops too!
Definition: VModule.h:66
class to hold data at Station level
bool HasSimData() const
Check whether station simulated data exists.
constexpr double kPi
Definition: MathConstants.h:24
const double second
Definition: GalacticUnits.h:32
constexpr double kTwoPi
Definition: MathConstants.h:27
utl::CoordinateSystemPtr GetLocalCoordinateSystem() const
Get the Auger reference system centered on the tank.
void MakeStation(const int stationId)
make a station with specifying Id, throw if invalid stationId
Definition: SEvent.cc:65
void AddParticle(const utl::Particle &particle)
void GetData(bool &b) const
Overloads of the GetData member template function.
Definition: Branch.cc:644
Station & GetStation(const int stationId)
retrieve station by id throw utl::NonExistentComponentException if n.a.
Definition: SEvent.h:116
constexpr double GeV
Definition: AugerUnits.h:187
ResultFlag
Flag returned by module methods to the RunController.
Definition: VModule.h:60
int CorsikaToPDG(const int corsikaCode)
converters from CORSIKA to PDG particle codes
fwk::VModule::ResultFlag Finish()
Finish: invoked at end of the run (NOT end of the event)
Definition: LEInjector.cc:287
constexpr double cm
Definition: AugerUnits.h:117
struct particle_info particle[80]
Vector object.
Definition: Vector.h:30
fwk::VModule::ResultFlag Run(evt::Event &event)
Run: invoked once per event.
Definition: LEInjector.cc:91
Report failure to RunController, causing RunController to terminate execution.
Definition: VModule.h:64
sevt::StationSimData & GetSimData()
Get simulated data at station level.
utl::CoordinateSystemPtr Get(const std::string &id)
Get a well-known Coordinate System.
#define ERROR(message)
Macro for logging error messages.
Definition: ErrorLogger.h:165
bool HasSEvent() const
fwk::VModule::ResultFlag Init()
Initialize: invoked at beginning of run (NOT beginning of event)
Definition: LEInjector.cc:61
utl::RandomEngine::RandomEngineType * fRandomEngine
Definition: LEInjector.h:73

, generated on Tue Sep 26 2023.