CMS 3D CMS Logo

ParticleManager.cc
Go to the documentation of this file.
2 
3 #include "HepMC/GenEvent.h"
4 #include "HepMC/Units.h"
5 #include "HepPDT/ParticleDataTable.hh"
6 
11 
16 
18  const HepMC::GenEvent & genEvent,
19  const HepPDT::ParticleDataTable & particleDataTable,
20  double beamPipeRadius,
21  double deltaRchargedMother,
22  const fastsim::ParticleFilter & particleFilter,
23  std::vector<SimTrack> & simTracks,
24  std::vector<SimVertex> & simVertices)
25  : genEvent_(&genEvent)
26  , genParticleIterator_(genEvent_->particles_begin())
27  , genParticleEnd_(genEvent_->particles_end())
28  , genParticleIndex_(1)
29  , particleDataTable_(&particleDataTable)
30  , beamPipeRadius2_(beamPipeRadius*beamPipeRadius)
31  , deltaRchargedMother_(deltaRchargedMother)
32  , particleFilter_(&particleFilter)
33  , simTracks_(&simTracks)
34  , simVertices_(&simVertices)
35  // prepare unit convsersions
36  // --------------------------------------------
37  // | | hepmc | cms |
38  // --------------------------------------------
39  // | length | genEvent_->length_unit | cm |
40  // | momentum | genEvent_->momentum_unit | GeV |
41  // | time | length unit (t*c) | ns |
42  // --------------------------------------------
43  , momentumUnitConversionFactor_(conversion_factor( genEvent_->momentum_unit(), HepMC::Units::GEV ))
44  , lengthUnitConversionFactor_(conversion_factor(genEvent_->length_unit(),HepMC::Units::LengthUnit::CM))
45  , lengthUnitConversionFactor2_(lengthUnitConversionFactor_*lengthUnitConversionFactor_)
46  , timeUnitConversionFactor_(lengthUnitConversionFactor_/fastsim::Constants::speedOfLight)
47 
48 {
49 
50  // add the main vertex from the signal event to the simvertex collection
51  if(genEvent.vertices_begin() != genEvent_->vertices_end())
52  {
53  const HepMC::FourVector & position = (*genEvent.vertices_begin())->position();
55  position.y()*lengthUnitConversionFactor_,
56  position.z()*lengthUnitConversionFactor_,
57  position.t()*timeUnitConversionFactor_)
58  ,-1);
59  }
60 }
61 
63 
65 {
66  std::unique_ptr<fastsim::Particle> particle;
67 
68  // retrieve particle from buffer
69  if(!particleBuffer_.empty())
70  {
71  particle = std::move(particleBuffer_.back());
72  particleBuffer_.pop_back();
73  }
74  // or from genParticle list
75  else
76  {
77  particle = nextGenParticle();
78  if(!particle) return nullptr;
79  }
80 
81  // if filter does not accept, skip particle
82  if(!particleFilter_->accepts(*particle))
83  {
84  return nextParticle(random);
85  }
86 
87  // lifetime or charge of particle are not yet set
88  if(!particle->remainingProperLifeTimeIsSet() || !particle->chargeIsSet())
89  {
90  // retrieve the particle data
91  const HepPDT::ParticleData * particleData = particleDataTable_->particle(HepPDT::ParticleID(particle->pdgId()));
92  if(!particleData)
93  {
94  // in very few events the Decayer (pythia) produces high mass resonances that are for some reason not present in the table (even though they should technically be)
95  // they have short lifetimes, so decay them right away (charge and lifetime cannot be taken from table)
96  particle->setRemainingProperLifeTimeC(0.);
97  particle->setCharge(0.);
98  }
99 
100  // set lifetime
101  if(!particle->remainingProperLifeTimeIsSet())
102  {
103  // The lifetime is 0. in the Pythia Particle Data Table! Calculate from width instead (ct=hbar/width).
104  // ct=particleData->lifetime().value();
105  double width = particleData->totalWidth().value();
106  if(width > 1.0e-35)
107  {
108  particle->setRemainingProperLifeTimeC(-log(random.flatShoot())*6.582119e-25/width/10.); // ct in cm
109  }
110  else
111  {
112  particle->setStable();
113  }
114  }
115 
116  // set charge
117  if(!particle->chargeIsSet())
118  {
119  particle->setCharge(particleData->charge());
120  }
121  }
122 
123  // add corresponding simTrack to simTrack collection
124  unsigned simTrackIndex = addSimTrack(particle.get());
125  particle->setSimTrackIndex(simTrackIndex);
126 
127  // and return
128  return particle;
129 }
130 
131 
133  const math::XYZTLorentzVector & vertexPosition,
134  int parentSimTrackIndex,
135  std::vector<std::unique_ptr<Particle> > & secondaries,
136  const SimplifiedGeometry * layer)
137 {
138 
139  // vertex must be within the accepted volume
140  if(!particleFilter_->acceptsVtx(vertexPosition))
141  {
142  return;
143  }
144 
145  // no need to create vertex in case no particles are produced
146  if(secondaries.empty()){
147  return;
148  }
149 
150  // add simVertex
151  unsigned simVertexIndex = addSimVertex(vertexPosition,parentSimTrackIndex);
152 
153  // closest charged daughter continues the track of the mother particle
154  // simplified tracking algorithm for fastSim
155  double distMin = 99999.;
156  int idx = -1;
157  int idxMin = -1;
158  for(auto & secondary : secondaries)
159  {
160  idx++;
161  if(secondary->getMotherDeltaR() != -1){
162  if(secondary->getMotherDeltaR() > deltaRchargedMother_){
163  // larger than max requirement on deltaR
164  secondary->resetMother();
165  }else{
166  if(secondary->getMotherDeltaR() < distMin){
167  distMin = secondary->getMotherDeltaR();
168  idxMin = idx;
169  }
170  }
171  }
172  }
173 
174  // add secondaries to buffer
175  idx = -1;
176  for(auto & secondary : secondaries)
177  {
178  idx++;
179  if(idxMin != -1){
180  // reset all but the particle with the lowest deltaR (which is at idxMin)
181  if(secondary->getMotherDeltaR() != -1 && idx != idxMin){
182  secondary->resetMother();
183  }
184  }
185 
186  // set origin vertex
187  secondary->setSimVertexIndex(simVertexIndex);
188  //
189  if(layer)
190  {
191  secondary->setOnLayer(layer->isForward(), layer->index());
192  }
193  // ...and add particle to buffer
194  particleBuffer_.push_back(std::move(secondary));
195  }
196 
197 }
198 
200 {
201  return this->addSimVertex(particle->position(), particle->simTrackIndex());
202 }
203 
206  int parentSimTrackIndex)
207 {
208  int simVertexIndex = simVertices_->size();
209  simVertices_->emplace_back(position.Vect(),
210  position.T(),
211  parentSimTrackIndex,
212  simVertexIndex);
213  return simVertexIndex;
214 }
215 
217 {
218  int simTrackIndex = simTracks_->size();
219  simTracks_->emplace_back(particle->pdgId(),
220  particle->momentum(),
221  particle->simVertexIndex(),
222  particle->genParticleIndex());
223  simTracks_->back().setTrackId(simTrackIndex);
224  return simTrackIndex;
225 }
226 
227 std::unique_ptr<fastsim::Particle> fastsim::ParticleManager::nextGenParticle()
228 {
229  // only consider particles that start in the beam pipe and end outside the beam pipe
230  // try to get the decay time from pythia
231  // use hepmc units
232  // make the link simtrack to simvertex
233  // try not to change the simvertex structure
234 
235  // loop over gen particles
237  {
238  // some handy pointers and references
239  const HepMC::GenParticle & particle = **genParticleIterator_;
240  const HepMC::GenVertex * productionVertex = particle.production_vertex();
241  const HepMC::GenVertex * endVertex = particle.end_vertex();
242 
243  // skip incoming particles
244  if(!productionVertex){
245  continue;
246  }
247 
248  // particle must be produced within the beampipe
249  if(productionVertex->position().perp2()*lengthUnitConversionFactor2_ > beamPipeRadius2_)
250  {
251  continue;
252  }
253 
254  // particle must not decay before it reaches the beam pipe
255  if(endVertex && endVertex->position().perp2()*lengthUnitConversionFactor2_ < beamPipeRadius2_)
256  {
257  continue;
258  }
259 
260  // make the particle
261  std::unique_ptr<Particle> newParticle(
262  new Particle(particle.pdg_id(),
263  math::XYZTLorentzVector(productionVertex->position().x()*lengthUnitConversionFactor_,
264  productionVertex->position().y()*lengthUnitConversionFactor_,
265  productionVertex->position().z()*lengthUnitConversionFactor_,
266  productionVertex->position().t()*timeUnitConversionFactor_),
268  particle.momentum().y()*momentumUnitConversionFactor_,
269  particle.momentum().z()*momentumUnitConversionFactor_,
270  particle.momentum().e()*momentumUnitConversionFactor_)));
271  newParticle->setGenParticleIndex(genParticleIndex_);
272 
273  // try to get the life time of the particle from the genEvent
274  if(endVertex)
275  {
276  double labFrameLifeTime = (endVertex->position().t() - productionVertex->position().t())*timeUnitConversionFactor_;
277  newParticle->setRemainingProperLifeTimeC(labFrameLifeTime / newParticle->gamma() * fastsim::Constants::speedOfLight);
278  }
279 
280  // Find production vertex if it already exists. Otherwise create new vertex
281  // Possible to recreate the whole GenEvent using SimTracks/SimVertices (see FBaseSimEvent::fill(..))
282  bool foundVtx = false;
283  for(const auto& simVtx : *simVertices_){
284  if(std::abs(simVtx.position().x() - newParticle->position().x()) < 1E-3 && std::abs(simVtx.position().y() - newParticle->position().y()) < 1E-3 && std::abs(simVtx.position().z() - newParticle->position().z()) < 1E-3){
285  newParticle->setSimVertexIndex(simVtx.vertexId());
286  foundVtx = true;
287  break;
288  }
289  }
290  if(!foundVtx) newParticle->setSimVertexIndex(addSimVertex(newParticle->position(), -1));
291 
292  // iterator/index has to be increased in case of return (is not done by the loop then)
294  // and return
295  return newParticle;
296  }
297 
298  return std::unique_ptr<Particle>();
299 }
Implementation of a generic detector layer (base class for forward/barrel layers).
const math::XYZTLorentzVector & position() const
Return position of the particle.
Definition: Particle.h:142
double flatShoot(double xmin=0.0, double xmax=1.0) const
HepPDT::ParticleDataTable ParticleDataTable
const double deltaRchargedMother_
For FastSim (cheat) tracking: cut on the angle between a charged mother and charged daughter...
bool accepts(const Particle &particle) const
Check all if all criteria are fullfilled.
const ParticleFilter *const particleFilter_
(Kinematic) cuts on the particles that have to be propagated.
int genParticleIndex() const
Return index of the particle in the genParticle vector.
Definition: Particle.h:167
double momentumUnitConversionFactor_
Convert pythia units to GeV (FastSim standard)
std::vector< std::unique_ptr< Particle > > particleBuffer_
The vector of all secondaries that are not yet propagated in the event.
static double constexpr speedOfLight
Speed of light [cm / ns].
Definition: Constants.h:16
virtual bool isForward() const =0
Returns false/true depending if the object is a (non-abstract) barrel/forward layer.
HepMC::GenEvent::particle_const_iterator genParticleIterator_
Iterator to keep track on which GenParticles where already considered.
int pdgId() const
Return pdgId of the particle.
Definition: Particle.h:136
TRandom random
Definition: MVATrainer.cc:138
const HepMC::GenEvent *const genEvent_
The GenEvent.
const HepMC::GenEvent::particle_const_iterator genParticleEnd_
The last particle of the GenEvent.
double lengthUnitConversionFactor2_
Convert pythia unis to cm^2 (FastSim standard)
unsigned addSimTrack(const Particle *particle)
Add a simTrack (simTrack contains some basic info about the particle, e.g. pdgId).
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:29
int simVertexIndex() const
Return index of the origin vertex.
Definition: Particle.h:161
const double beamPipeRadius2_
(Radius of the beampipe)^2
ParticleManager(const HepMC::GenEvent &genEvent, const HepPDT::ParticleDataTable &particleDataTable, double beamPipeRadius, double deltaRchargedMother, const ParticleFilter &particleFilter, std::vector< SimTrack > &simTracks, std::vector< SimVertex > &simVertices)
Constructor.
~ParticleManager()
Default destructor.
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
void addSecondaries(const math::XYZTLorentzVector &vertexPosition, int motherSimTrackId, std::vector< std::unique_ptr< Particle > > &secondaries, const SimplifiedGeometry *layer=nullptr)
Adds secondaries that are produced by any of the interactions (or particle decay) to the buffer...
std::unique_ptr< Particle > nextParticle(const RandomEngineAndDistribution &random)
Returns the next particle that has to be propagated (secondary or genParticle).
HepPDT::ParticleData ParticleData
int simTrackIndex() const
Return index of the SimTrack.
Definition: Particle.h:155
std::vector< SimTrack > * simTracks_
The generated SimTrack of this event.
std::unique_ptr< Particle > nextGenParticle()
Returns next particle from the GenEvent that has to be propagated.
double lengthUnitConversionFactor_
Convert pythia unis to cm (FastSim standard)
const HepPDT::ParticleDataTable *const particleDataTable_
Necessary to get information like lifetime and charge of a particle if unknown.
double timeUnitConversionFactor_
Convert pythia unis to ns (FastSim standard)
int index() const
Return index of this layer (layers are numbered according to their position in the detector)...
static int position[264][3]
Definition: ReadPGInfo.cc:509
std::vector< SimVertex > * simVertices_
The generated SimVertices of this event.
const math::XYZTLorentzVector & momentum() const
Return momentum of the particle.
Definition: Particle.h:145
(Kinematic) cuts on the particles that are propagated.
Definition of a generic FastSim Particle which can be propagated through the detector (formerly Parti...
Definition: Particle.h:19
int genParticleIndex_
Index of particle in the GenEvent (if it is a GenParticle)
unsigned addSimVertex(const math::XYZTLorentzVector &position, int motherIndex)
Add a simVertex (simVertex contains information about the track it was produced). ...
unsigned addEndVertex(const Particle *particle)
Necessary to add an end vertex to a particle.
def move(src, dest)
Definition: eostools.py:511
bool acceptsVtx(const math::XYZTLorentzVector &originVertexPosition) const
Vertex within tracker volume.