CMS 3D CMS Logo

TrackerSimHitProducer.cc
Go to the documentation of this file.
1 #include <vector>
2 #include <memory>
3 
4 // framework
8 
9 // tracking
15 
16 // fastsim
23 
24 // data formats
32 
33 // other
37 
38 
40 // Author: L. Vanelderen, S. Kurz
41 // Date: 29 May 2017
43 
44 
45 typedef std::pair<const GeomDet*,TrajectoryStateOnSurface> DetWithState;
46 
47 namespace fastsim
48 {
50 
56  {
57  public:
60 
62  ~TrackerSimHitProducer() override{;}
63 
65 
71  void interact(Particle & particle,const SimplifiedGeometry & layer,std::vector<std::unique_ptr<Particle> > & secondaries,const RandomEngineAndDistribution & random) override;
72 
74  void registerProducts(edm::ProducerBase & producer) const override;
75 
77  void storeProducts(edm::Event & iEvent) override;
78 
80 
90  std::pair<double, PSimHit*> createHitOnDetector(const TrajectoryStateOnSurface & particle, int pdgId, double layerThickness, double eLoss, int simTrackId, const GeomDet & detector, GlobalPoint & refPos);
91 
92  private:
93  const double onSurfaceTolerance_;
94  std::unique_ptr<edm::PSimHitContainer> simHitContainer_;
95  double minMomentum_;
97  };
98 }
99 
100 
101 
103  : fastsim::InteractionModel(name)
104  , onSurfaceTolerance_(0.01)
106 {
107  // Set the minimal momentum
108  minMomentum_ = cfg.getParameter<double>("minMomentumCut");
109  // - if not set, particles from outside the beampipe with a negative speed in R direction are propagated but no SimHits
110  // - particle with positive (negative) z and negative (positive) speed in z direction: no SimHits
111  // -> this is not neccesary since a track reconstruction is not possible in this case anyways
112  doHitsFromInboundParticles_ = cfg.getParameter<bool>("doHitsFromInboundParticles");
113 }
114 
116 {
117  producer.produces<edm::PSimHitContainer>("TrackerHits");
118 }
119 
121 {
122  iEvent.put(std::move(simHitContainer_), "TrackerHits");
124 }
125 
126 void fastsim::TrackerSimHitProducer::interact(Particle & particle,const SimplifiedGeometry & layer,std::vector<std::unique_ptr<Particle> > & secondaries,const RandomEngineAndDistribution & random)
127 {
128  // the energy deposit in the layer
129  double energyDeposit = particle.getEnergyDeposit();
130  particle.setEnergyDeposit(0);
131 
132  //
133  // don't save hits from particle that did a loop or are inbound (coming from the outer part of the tracker, going towards the center)
134  //
136  if(particle.isLooper()){
137  return;
138  }
139  if(particle.momentum().X()*particle.position().X() + particle.momentum().Y()*particle.position().Y() < 0){
140  particle.setLooper();
141  return;
142  }
143  if(layer.isForward() && ((particle.position().Z() > 0 && particle.momentum().Z() < 0) || (particle.position().Z() < 0 && particle.momentum().Z() > 0))){
144  particle.setLooper();
145  return;
146  }
147  }
148 
149  //
150  // check that layer has tracker modules
151  //
152  if(!layer.getDetLayer())
153  {
154  return;
155  }
156 
157  //
158  // no material
159  //
160  if(layer.getThickness(particle.position(), particle.momentum()) < 1E-10)
161  {
162  return;
163  }
164 
165  //
166  // only charged particles
167  //
168  if(particle.charge()==0)
169  {
170  return;
171  }
172 
173  //
174  // save hit only if momentum higher than threshold
175  //
176  if(particle.momentum().Perp2() < minMomentum_*minMomentum_)
177  {
178  return;
179  }
180 
181  // create the trajectory of the particle
183  GlobalPoint position( particle.position().X(), particle.position().Y(), particle.position().Z());
184  GlobalVector momentum( particle.momentum().Px(), particle.momentum().Py(), particle.momentum().Pz());
185  auto plane = layer.getDetLayer()->surface().tangentPlane(position);
186  TrajectoryStateOnSurface trajectory(GlobalTrajectoryParameters( position, momentum, TrackCharge( particle.charge()), &magneticField), *plane);
187 
188  // find detectors compatible with the particle's trajectory
191  std::vector<DetWithState> compatibleDetectors = layer.getDetLayer()->compatibleDets(trajectory, propagator, est);
192 
194  // You have to sort the simHits in the order they occur!
196 
197  // The old algorithm (sorting by distance to IP) doesn't seem to make sense to me (what if particle moves inwards?)
198 
199  // Detector layers have to be sorted by proximity to particle.position
200  // Propagate particle backwards a bit to make sure it's outside any components
201  std::map<double, PSimHit*> distAndHits;
202  // Position relative to which the hits should be sorted
203  GlobalPoint positionOutside(particle.position().x()-particle.momentum().x()/particle.momentum().P()*10.,
204  particle.position().y()-particle.momentum().y()/particle.momentum().P()*10.,
205  particle.position().z()-particle.momentum().z()/particle.momentum().P()*10.);
206 
207  // FastSim: cheat tracking -> assign hits to closest charged daughter if particle decays
208  int pdgId = particle.getMotherDeltaR() == -1 ? particle.pdgId() : particle.getMotherPdgId();
209 
210  // loop over the compatible detectors
211  for (const auto & detectorWithState : compatibleDetectors)
212  {
213  const GeomDet & detector = *detectorWithState.first;
214  const TrajectoryStateOnSurface & particleState = detectorWithState.second;
215 
216  // if the detector has no components
217  if(detector.isLeaf())
218  {
219  std::pair<double, PSimHit*> hitPair = createHitOnDetector(particleState, pdgId, layer.getThickness(particle.position()), energyDeposit, particle.simTrackIndex(), detector, positionOutside);
220  if(hitPair.second){
221  distAndHits.insert(distAndHits.end(), hitPair);
222  }
223  }
224  else
225  {
226  // if the detector has components
227  for(const auto component : detector.components())
228  {
229  std::pair<double, PSimHit*> hitPair = createHitOnDetector(particleState, pdgId,layer.getThickness(particle.position()), energyDeposit, particle.simTrackIndex(), *component, positionOutside);
230  if(hitPair.second){
231  distAndHits.insert(distAndHits.end(), hitPair);
232  }
233  }
234  }
235  }
236 
237  // Fill simHitContainer
238  for(std::map<double, PSimHit*>::const_iterator it = distAndHits.begin(); it != distAndHits.end(); it++){
239  simHitContainer_->push_back(*(it->second));
240  }
241 
242 }
243 
244 // Also returns distance to simHit since hits have to be ordered (in time) afterwards. Necessary to do explicit copy of TrajectoryStateOnSurface particle (not call by reference)
245 std::pair<double, PSimHit*> fastsim::TrackerSimHitProducer::createHitOnDetector(const TrajectoryStateOnSurface & particle, int pdgId, double layerThickness, double eLoss, int simTrackId, const GeomDet & detector, GlobalPoint & refPos)
246 {
247  // determine position and momentum of particle in the coordinate system of the detector
248  LocalPoint localPosition;
249  LocalVector localMomentum;
250 
251  // if the particle is close enough, no further propagation is needed
252  if(fabs(detector.toLocal(particle.globalPosition()).z()) < onSurfaceTolerance_)
253  {
254  localPosition = particle.localPosition();
255  localMomentum = particle.localMomentum();
256  }
257  // else, propagate
258  else
259  {
260  // find crossing of particle with detector layer
262  particle.globalMomentum().basicVector(),
263  particle.transverseCurvature(),
264  anyDirection);
265  std::pair<bool,double> path = crossing.pathLength(detector.surface());
266  // case propagation succeeds
267  if (path.first)
268  {
269  localPosition = detector.toLocal( GlobalPoint( crossing.position(path.second)));
270  localMomentum = detector.toLocal( GlobalVector( crossing.direction(path.second)));
271  localMomentum = localMomentum.unit() * particle.localMomentum().mag();
272  }
273  // case propagation fails
274  else
275  {
276  return std::pair<double, PSimHit*>(0, nullptr);
277  }
278  }
279 
280  // find entry and exit point of particle in detector
281  const Plane& detectorPlane = detector.surface();
282  double halfThick = 0.5 * detectorPlane.bounds().thickness();
283  double pZ = localMomentum.z();
284  LocalPoint entry = localPosition + (-halfThick / pZ) * localMomentum;
285  LocalPoint exit = localPosition + (halfThick / pZ) * localMomentum;
286  double tof = particle.globalPosition().mag() / fastsim::Constants::speedOfLight ; // in nanoseconds
287 
288  // make sure the simhit is physically on the module
289  double boundX = detectorPlane.bounds().width() / 2.;
290  double boundY = detectorPlane.bounds().length() / 2.;
291  // Special treatment for TID and TEC trapeziodal modules
292  unsigned subdet = DetId(detector.geographicalId()).subdetId();
293  if (subdet == 4 || subdet == 6)
294  boundX *= 1. - localPosition.y() / detectorPlane.position().perp();
295  if(fabs(localPosition.x()) > boundX || fabs(localPosition.y()) > boundY )
296  {
297  return std::pair<double, PSimHit*>(0, nullptr);
298  }
299 
300  // Create the hit: the energy loss rescaled to the module thickness
301  // Total thickness is in radiation lengths, 1 radlen = 9.36 cm
302  // Sensitive module thickness is about 30 microns larger than
303  // the module thickness itself
304  eLoss *= (2. * halfThick - 0.003) / (9.36 * layerThickness);
305 
306  // Position of the hit in global coordinates
307  GlobalPoint hitPos(detector.surface().toGlobal(localPosition));
308 
309  return std::pair<double, PSimHit*>((hitPos-refPos).mag(),
310  new PSimHit(entry, exit, localMomentum.mag(), tof, eLoss, pdgId,
311  detector.geographicalId().rawId(), simTrackId,
312  localMomentum.theta(),
313  localMomentum.phi()));
314 }
315 
319  "fastsim::TrackerSimHitProducer"
320  );
BranchAliasSetterT< ProductType > produces()
declare what type of product will make and with which optional label
GlobalPoint toGlobal(const Point2DBase< Scalar, LocalTag > lp) const
Definition: Surface.h:106
T getParameter(std::string const &) const
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Event.h:136
TrackerSimHitProducer(const std::string &name, const edm::ParameterSet &cfg)
Constructor.
virtual ConstReferenceCountingPointer< TangentPlane > tangentPlane(const GlobalPoint &) const =0
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
T mag() const
The vector magnitude. Equivalent to sqrt(vec.mag2())
std::pair< const GeomDet *, TrajectoryStateOnSurface > DetWithState
int getMotherPdgId() const
Get pdgIdto mother particle (only makes sense if mother and daughter charged).
Definition: Particle.h:213
Geom::Phi< T > phi() const
Definition: PV3DBase.h:69
Global3DPoint GlobalPoint
Definition: GlobalPoint.h:10
T y() const
Definition: PV3DBase.h:63
GlobalPoint globalPosition() const
LocalPoint toLocal(const GlobalPoint &gp) const
Conversion to the R.F. of the GeomDet.
Definition: GeomDet.h:69
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.
const Bounds & bounds() const
Definition: Surface.h:120
int pdgId() const
Return pdgId of the particle.
Definition: Particle.h:136
TRandom random
Definition: MVATrainer.cc:138
std::unique_ptr< edm::PSimHitContainer > simHitContainer_
The SimHit.
void interact(Particle &particle, const SimplifiedGeometry &layer, std::vector< std::unique_ptr< Particle > > &secondaries, const RandomEngineAndDistribution &random) override
Perform the interaction.
double isLooper() const
Check if this particle is about to do a loop in the tracker or the direction of the momentum is going...
Definition: Particle.h:199
const Plane & surface() const
The nominal surface of the GeomDet.
Definition: GeomDet.h:42
Definition: Plane.h:17
virtual std::vector< DetWithState > compatibleDets(const TrajectoryStateOnSurface &startingState, const Propagator &prop, const MeasurementEstimator &est) const
Geom::Theta< T > theta() const
Definition: PV3DBase.h:75
uint32_t rawId() const
get the raw id
Definition: DetId.h:44
LocalVector localMomentum() const
~TrackerSimHitProducer() override
Default destructor.
Base class for any interaction model between a particle and a tracker layer.
int TrackCharge
Definition: TrackCharge.h:4
Produces SimHits in the tracker layers.
void setLooper()
This particle is about to do a loop in the tracker or the direction of the momentum is going inwards...
Definition: Particle.h:99
int iEvent
Definition: GenABIO.cc:230
bool doHitsFromInboundParticles_
If not set, incoming particles (negative speed relative to center of detector) don&#39;t create a SimHits...
T mag() const
Definition: PV3DBase.h:67
virtual const double getMagneticFieldZ(const math::XYZTLorentzVector &position) const =0
Return magnetic field (field only has Z component!) on the layer.
T z() const
Definition: PV3DBase.h:64
virtual const BoundSurface & surface() const =0
The surface of the GeometricSearchDet.
DetId geographicalId() const
The label of this GeomDet.
Definition: GeomDet.h:79
virtual bool isLeaf() const
is a Unit
Definition: GeomDet.h:85
int simTrackIndex() const
Return index of the SimTrack.
Definition: Particle.h:155
virtual std::vector< const GeomDet * > components() const
Returns direct components, if any.
Definition: GeomDet.h:88
Vector3DBase unit() const
Definition: Vector3DBase.h:57
Definition: DetId.h:18
void registerProducts(edm::ProducerBase &producer) const override
Register the SimHit collection.
virtual float thickness() const =0
double minMomentum_
Set the minimal momentum of incoming particle.
double getMotherDeltaR() const
Get delta R to mother particle (only makes sense if mother and daughter charged). ...
Definition: Particle.h:206
void storeProducts(edm::Event &iEvent) override
Store the SimHit collection.
double charge() const
Return charge of the particle.
Definition: Particle.h:139
virtual const double getThickness(const math::XYZTLorentzVector &position) const =0
Return thickness of the layer at a given position.
const DetLayer * getDetLayer() const
Return pointer to the assigned active layer (if any).
HLT enums.
GlobalVector globalMomentum() const
static int position[264][3]
Definition: ReadPGInfo.cc:509
double getEnergyDeposit() const
Return the energy the particle deposited in the tracker layer that was last hit (ionization).
Definition: Particle.h:192
const math::XYZTLorentzVector & momentum() const
Return momentum of the particle.
Definition: Particle.h:145
std::pair< double, PSimHit * > createHitOnDetector(const TrajectoryStateOnSurface &particle, int pdgId, double layerThickness, double eLoss, int simTrackId, const GeomDet &detector, GlobalPoint &refPos)
Helper funtion to create the actual SimHit on a detector (sub-) module.
#define DEFINE_EDM_PLUGIN(factory, type, name)
std::vector< PSimHit > PSimHitContainer
T x() const
Definition: PV3DBase.h:62
const BasicVectorType & basicVector() const
Definition: PV3DBase.h:56
void setEnergyDeposit(double energyDeposit)
Set the energy the particle deposited in the tracker layer that was last hit (ionization).
Definition: Particle.h:92
def move(src, dest)
Definition: eostools.py:510
Global3DVector GlobalVector
Definition: GlobalVector.h:10
const double onSurfaceTolerance_
Max distance between particle and active (sub-) module. Otherwise particle has to be propagated...