CMS 3D CMS Logo

TkAccumulatingSensitiveDetector.cc
Go to the documentation of this file.
2 
5 
8 
14 
18 
22 
26 
27 #include "G4Track.hh"
28 #include "G4StepPoint.hh"
29 #include "G4VProcess.hh"
30 
31 #include "G4SystemOfUnits.hh"
32 
33 #include <vector>
34 #include <iostream>
35 
37 
38 //#define FAKEFRAMEROTATION
39 
40 static
43 {
44  static thread_local TrackerG4SimHitNumberingScheme s_scheme(cpv, det);
45  return s_scheme;
46 }
47 
49  const DDCompactView & cpv,
50  const SensitiveDetectorCatalog & clg,
51  edm::ParameterSet const & p,
52  const SimTrackManager* manager) :
53  SensitiveTkDetector(name, cpv, clg, p),theManager(manager),
54  rTracker(1200.*CLHEP::mm),zTracker(3000.*CLHEP::mm),mySimHit(nullptr),
55  lastId(0),lastTrack(0),oldVolume(nullptr),px(0.0f),py(0.0f),pz(0.0f),eventno(0),pname("")
56 {
57  edm::ParameterSet m_TrackerSD = p.getParameter<edm::ParameterSet>("TrackerSD");
58  allowZeroEnergyLoss = m_TrackerSD.getParameter<bool>("ZeroEnergyLoss");
59  neverAccumulate = m_TrackerSD.getParameter<bool>("NeverAccumulate");
60  printHits = m_TrackerSD.getParameter<bool>("PrintHits");
61  theTofLimit = m_TrackerSD.getParameter<double>("ElectronicSigmaInNanoSeconds")*3*CLHEP::ns; // 3 sigma
62  energyCut = m_TrackerSD.getParameter<double>("EnergyThresholdForPersistencyInGeV")*CLHEP::GeV; //default must be 0.5
63  energyHistoryCut = m_TrackerSD.getParameter<double>("EnergyThresholdForHistoryInGeV")*CLHEP::GeV;//default must be 0.05
65 
66  // No Rotation given in input, automagically choose one based upon the name
67  std::string rotType;
68  theRotation.reset(new TrackerFrameRotation());
69  rotType = "TrackerFrameRotation";
70 
71 #ifdef FAKEFRAMEROTATION
72  theRotation.reset(new FakeFrameRotation());
73  rotType = "FakeFrameRotation";
74 #endif
75 
76  edm::LogInfo("TrackerSimInfo")<<" TkAccumulatingSensitiveDetector: "
77  <<" Criteria for Saving Tracker SimTracks: \n"
78  <<" History: "<<energyHistoryCut<< " MeV; Persistency: "
79  << energyCut<<" MeV; TofLimit: " << theTofLimit << " ns"
80  <<"\n FrameRotation type " << rotType
81  <<" rTracker(cm)= " << rTracker/CLHEP::cm
82  <<" zTracker(cm)= " << zTracker/CLHEP::cm
83  <<" allowZeroEnergyLoss: " << allowZeroEnergyLoss
84  <<" neverAccumulate: " << neverAccumulate
85  <<" printHits: " << printHits;
86 
87  slaveLowTof.reset(new TrackingSlaveSD(name+"LowTof"));
88  slaveHighTof.reset(new TrackingSlaveSD(name+"HighTof"));
89 
90  std::vector<std::string> temp;
91  temp.push_back(slaveLowTof.get()->name());
92  temp.push_back(slaveHighTof.get()->name());
93  setNames(temp);
94 
97  theNumberingScheme.reset(nullptr);
98 }
99 
101 {}
102 
103 bool TkAccumulatingSensitiveDetector::ProcessHits(G4Step * aStep, G4TouchableHistory *)
104 {
105  LogDebug("TrackerSimDebug")<< " Entering a new Step " << aStep->GetTotalEnergyDeposit() << " "
106  << aStep->GetPreStepPoint()->GetPhysicalVolume()->GetLogicalVolume()->GetName();
107 
108  if (aStep->GetTotalEnergyDeposit()>0. || allowZeroEnergyLoss)
109  {
110  if (!mySimHit)
111  {
112  createHit(aStep);
113  }
114  else if(neverAccumulate || newHit(aStep))
115  {
116  sendHit();
117  createHit(aStep);
118  }
119  else
120  {
121  updateHit(aStep);
122  }
123  return true;
124  }
125  return false;
126 }
127 
129 {
130  return theNumberingScheme.get()->g4ToNumberingScheme(step->GetPreStepPoint()->GetTouchable());
131 }
132 
134  const G4Track* gTrack = (*bot)();
135 
136 #ifdef DUMPPROCESSES
137  if (gTrack->GetCreatorProcess()) {
138  edm::LogInfo("TrackerSimInfo")<<" -> PROCESS CREATOR : "
139  <<gTrack->GetCreatorProcess()->GetProcessName();
140  } else {
141  edm::LogInfo("TrackerSimInfo") <<" -> No Creator process";
142  }
143 #endif
144 
145  //
146  //Position
147  //
148  const G4ThreeVector& pos = gTrack->GetPosition();
149  LogDebug("TrackerSimDebug")
150  << " update(..) of " << gTrack->GetDefinition()->GetParticleName()
151  << " trackID= " << gTrack->GetTrackID()
152  <<" E(MeV)= "<<gTrack->GetKineticEnergy() <<" Ecut= " << energyCut
153  << " R(mm)= " << pos.perp() << " Z(mm)= " << pos.z();
154 
155  //
156  // Check if in Tracker Volume
157  //
158  if (pos.x()*pos.x() + pos.y()*pos.y() < rTracker2 && std::abs(pos.z()) < zTracker){
159  //
160  // inside the Tracker
161  //
162  if (gTrack->GetKineticEnergy() > energyCut){
164  info->storeTrack(true);
165  }
166  //
167  // Save History?
168  //
169  if (gTrack->GetKineticEnergy() > energyHistoryCut){
171  info->putInHistory();
172  //LogDebug("TrackerSimDebug")<<" POINTER "<<info;
173  // <<" track inside the tracker selected for HISTORY";
174  // <<"Track ID (history track)= "<<gTrack->GetTrackID();
175  }
176  }
177 }
178 
180 {
181  if (mySimHit == nullptr) return;
182  if (printHits)
183  {
184  TkSimHitPrinter thePrinter("TkHitPositionOSCAR.dat");
185  thePrinter.startNewSimHit(GetName(),oldVolume->GetLogicalVolume()->GetName(),
187  thePrinter.printLocal(mySimHit->entryPoint(),mySimHit->exitPoint());
190  thePrinter.printGlobalMomentum(px,py,pz);
191  LogDebug("TrackerSimDebug")<< " Storing PSimHit: " << mySimHit->detUnitId()
192  << " " << mySimHit->trackId() << " " << mySimHit->energyLoss()
193  << " " << mySimHit->entryPoint() << " " << mySimHit->exitPoint();
194  }
195 
196  if (mySimHit->timeOfFlight() < theTofLimit) {
197  slaveLowTof.get()->processHits(*mySimHit); // implicit conversion (slicing) to PSimHit!!!
198  } else {
199  slaveHighTof.get()->processHits(*mySimHit); // implicit conversion (slicing) to PSimHit!!!
200  }
201  //
202  // clean up
203  delete mySimHit;
204  mySimHit = nullptr;
205  lastTrack = 0;
206  lastId = 0;
207 }
208 
210 {
211  // VI: previous hit should be already deleted
212  // in past here was a check if a hit is inside a sensitive detector,
213  // this is not needed, because call to senstive detector happens
214  // only inside the volume
215  const G4Track * theTrack = aStep->GetTrack();
216  Local3DPoint theExitPoint = theRotation.get()->transformPoint(LocalPostStepPosition(aStep));
217  Local3DPoint theEntryPoint;
218  //
219  // Check particle type - for gamma and neutral hadrons energy deposition
220  // should be local (VI)
221  //
222  if(0.0 == theTrack->GetDefinition()->GetPDGCharge()) {
223  theEntryPoint = theExitPoint;
224  } else {
225  theEntryPoint = theRotation.get()->transformPoint(LocalPreStepPosition(aStep));
226  }
227 
228  //
229  // This allows to send he skipEvent if it is outside!
230  //
231  const G4StepPoint* preStepPoint = aStep->GetPreStepPoint();
232  float thePabs = preStepPoint->GetMomentum().mag()/GeV;
233  float theTof = preStepPoint->GetGlobalTime()/nanosecond;
234  float theEnergyLoss = aStep->GetTotalEnergyDeposit()/GeV;
235  int theParticleType = theG4TrackToParticleID.get()->particleID(theTrack);
236  uint32_t theDetUnitId = setDetUnitId(aStep);
237  int theTrackID = theTrack->GetTrackID();
238  if (theDetUnitId == 0)
239  {
240  edm::LogWarning("TkAccumulatingSensitiveDetector::createHit")
241  << " theDetUnitId is not valid for " << GetName();
242  throw cms::Exception("TkAccumulatingSensitiveDetector::createHit")
243  << "cannot get theDetUnitId for G4Track " << theTrackID;
244  }
245 
246  // To whom assign the Hit?
247  // First iteration: if the track is to be stored, use the current number;
248  // otherwise, get to the mother
249  unsigned int theTrackIDInsideTheSimHit=theTrackID;
250 
251  G4VUserTrackInformation * info = theTrack->GetUserInformation();
252  if (info == nullptr) {
253  edm::LogWarning("TkAccumulatingSensitiveDetector::createHit")
254  << " no UserTrackInformation available for trackID= " << theTrackID;
255  throw cms::Exception("TkAccumulatingSensitiveDetector::createHit")
256  << " cannot handle hits for tracking in " << GetName();
257  } else {
258  TrackInformation * temp = dynamic_cast<TrackInformation* >(info);
259  if (temp ==nullptr) {
260  edm::LogWarning("TkAccumulatingSensitiveDetector::createHit")
261  << " G4VUserTrackInformation is not a TrackInformation for trackID= "
262  << theTrackID;
263  throw cms::Exception("TkAccumulatingSensitiveDetector::createHit")
264  << " cannot handle hits for tracking in " << GetName();
265  } else {
266  if (temp->storeTrack() == false) {
267  // Go to the mother!
268  theTrackIDInsideTheSimHit = theTrack->GetParentID();
269  LogDebug("TrackerSimDebug")
270  << " TkAccumulatingSensitiveDetector::createHit(): setting the TrackID from "
271  << theTrackIDInsideTheSimHit
272  << " to the mother one " << theTrackIDInsideTheSimHit << " " << theEnergyLoss;
273  } else {
274  LogDebug("TrackerSimDebug")
275  << " TkAccumulatingSensitiveDetector:createHit(): leaving the current TrackID "
276  << theTrackIDInsideTheSimHit;
277  }
278  }
279  }
280 
281  const G4ThreeVector& gmd = preStepPoint->GetMomentumDirection();
282  // convert it to local frame
283  G4ThreeVector lmd = ((G4TouchableHistory *)(preStepPoint->GetTouchable()))->GetHistory()
284  ->GetTopTransform().TransformAxis(gmd);
285  Local3DPoint lnmd = theRotation.get()->transformPoint(ConvertToLocal3DPoint(lmd));
286  float theThetaAtEntry = lnmd.theta();
287  float thePhiAtEntry = lnmd.phi();
288 
289  mySimHit = new UpdatablePSimHit(theEntryPoint,theExitPoint,thePabs,theTof,
290  theEnergyLoss,theParticleType,theDetUnitId,
291  theTrackIDInsideTheSimHit,theThetaAtEntry,thePhiAtEntry,
292  theG4ProcTypeEnumerator.get()->processId(theTrack->GetCreatorProcess()));
293  lastId = theDetUnitId;
294  lastTrack = theTrackID;
295 
296  // only for debugging
297  if (printHits) {
298  // point on Geant4 unit (mm)
299  globalEntryPoint = ConvertToLocal3DPoint(preStepPoint->GetPosition());
300  globalExitPoint = ConvertToLocal3DPoint(aStep->GetPostStepPoint()->GetPosition());
301  // in CMS unit (GeV)
302  px = preStepPoint->GetMomentum().x()/GeV;
303  py = preStepPoint->GetMomentum().y()/GeV;
304  pz = preStepPoint->GetMomentum().z()/GeV;
305  oldVolume = preStepPoint->GetPhysicalVolume();
306  pname = theTrack->GetDefinition()->GetParticleName();
307  LogDebug("TrackerSimDebug")<< " Created PSimHit: " << pname
308  << " " << mySimHit->detUnitId() << " " << mySimHit->trackId()
309  << " " << theTrackID
310  << " p= " << aStep->GetPreStepPoint()->GetMomentum().mag()
311  << " " << mySimHit->energyLoss() << " " << mySimHit->entryPoint()
312  << " " << mySimHit->exitPoint();
313  }
314 }
315 
317 {
318  // VI: in past here was a check if a hit is inside a sensitive detector,
319  // this is not needed, because call to senstive detector happens
320  // only inside the volume
321  Local3DPoint theExitPoint = theRotation.get()->transformPoint(LocalPostStepPosition(aStep));
322  float theEnergyLoss = aStep->GetTotalEnergyDeposit()/GeV;
323  mySimHit->setExitPoint(theExitPoint);
324  mySimHit->addEnergyLoss(theEnergyLoss);
325  if (printHits) {
326  globalExitPoint = ConvertToLocal3DPoint(aStep->GetPostStepPoint()->GetPosition());
327  }
328  LogDebug("TrackerSimDebug")
329  << " updateHit: for " << aStep->GetTrack()->GetDefinition()->GetParticleName()
330  << " trackID= " << aStep->GetTrack()->GetTrackID() << " deltaEloss= " << theEnergyLoss
331  << "\n Updated PSimHit: " << mySimHit->detUnitId() << " " << mySimHit->trackId()
332  << " " << mySimHit->energyLoss() << " " << mySimHit->entryPoint()
333  << " " << mySimHit->exitPoint();
334 }
335 
336 bool TkAccumulatingSensitiveDetector::newHit(const G4Step * aStep)
337 {
338  const G4Track * theTrack = aStep->GetTrack();
339 
340  // for neutral particles do not merge hits (V.I.)
341  if(0.0 == theTrack->GetDefinition()->GetPDGCharge()) return true;
342 
343  uint32_t theDetUnitId = setDetUnitId(aStep);
344  int theTrackID = theTrack->GetTrackID();
345 
346  LogDebug("TrackerSimDebug")<< "newHit: OLD(detID,trID) = (" << lastId << "," << lastTrack
347  << "), NEW = (" << theDetUnitId << "," << theTrackID
348  << ") Step length(mm)= " << aStep->GetStepLength()
349  << " Edep= " << aStep->GetTotalEnergyDeposit()
350  << " p= " << aStep->GetPreStepPoint()->GetMomentum().mag();
351  return ((theTrackID == lastTrack) && (lastId == theDetUnitId) && closeHit(aStep))
352  ? false : true;
353 }
354 
356 {
357  const float tolerance2 = 0.0025f; // (0.5 mm)^2 are allowed between entry and exit
358  Local3DPoint theEntryPoint = theRotation.get()->transformPoint(LocalPreStepPosition(aStep));
359  LogDebug("TrackerSimDebug")<< " closeHit: distance = "
360  << (mySimHit->exitPoint()-theEntryPoint).mag();
361 
362  return ((mySimHit->exitPoint()-theEntryPoint).mag2() < tolerance2) ? true : false;
363 }
364 
366 {
367  LogDebug("TrackerSimDebug")<< " Saving the last hit in a ROU " << GetName();
368  if (mySimHit != nullptr) sendHit();
369 }
370 
372 {
373  clearHits();
374  eventno = (*i)()->GetEventID();
375  delete mySimHit;
376  mySimHit = nullptr;
377 }
378 
380 {
382  const edm::EventSetup* es = (*i)();
383  es->get<IdealGeometryRecord>().get( pDD );
384 
386  es->get<IdealGeometryRecord>().get(pView);
387 
388  theNumberingScheme.reset(&(numberingScheme(*pView,*pDD)));
389 }
390 
392 {
393  slaveLowTof.get()->Initialize();
394  slaveHighTof.get()->Initialize();
395 }
396 
398  TrackInformation* info = nullptr;
399  G4VUserTrackInformation* temp = gTrack->GetUserInformation();
400  if (temp == nullptr){
401  edm::LogWarning("TkAccumulatingSensitiveDetector::getTrackInformation")
402  <<" ERROR: no G4VUserTrackInformation available for track "
403  << gTrack->GetTrackID() << " Ekin(MeV)= " << gTrack->GetKineticEnergy()
404  << " " << gTrack->GetDefinition()->GetParticleName();
405  throw cms::Exception("TkAccumulatingSensitiveDetector::getTrackInformation")
406  << " cannot handle hits for tracking in " << GetName();
407  }else{
408  info = dynamic_cast<TrackInformation*>(temp);
409  if (info == nullptr){
410  edm::LogWarning("TkAccumulatingSensitiveDetector::getTrackInformation")
411  << " G4VUserTrackInformation is not a TrackInformation for "
412  <<"TrackID= " << gTrack->GetTrackID() << " Ekin(MeV)= " << gTrack->GetKineticEnergy()
413  << " " << gTrack->GetDefinition()->GetParticleName();
414  throw cms::Exception("TkAccumulatingSensitiveDetector::getTrackInformation")
415  << " cannot handle hits for tracking in " << GetName();
416  }
417  }
418  return info;
419 }
420 
422 
423  if (slaveLowTof.get()->name() == hname) { cc=slaveLowTof.get()->hits(); }
424  else if (slaveHighTof.get()->name() == hname) { cc=slaveHighTof.get()->hits();}
425 }
#define LogDebug(id)
T getParameter(std::string const &) const
static const TGPicture * info(bool iBackgroundIsBlack)
const double GeV
Definition: MathUtil.h:16
void update(const BeginOfEvent *) override
This routine will be called when the appropriate signal arrives.
std::unique_ptr< TrackingSlaveSD > slaveHighTof
TrackInformation * getTrackInformation(const G4Track *)
bool storeTrack() const
std::unique_ptr< FrameRotation > theRotation
Local3DPoint ConvertToLocal3DPoint(const G4ThreeVector &point) const
T mag() const
The vector magnitude. Equivalent to sqrt(vec.mag2())
std::unique_ptr< const G4ProcessTypeEnumerator > theG4ProcTypeEnumerator
void printHitData(const std::string &, float, float, float) const
Geom::Phi< T > phi() const
Definition: PV3DBase.h:69
TkAccumulatingSensitiveDetector(const std::string &, const DDCompactView &, const SensitiveDetectorCatalog &, edm::ParameterSet const &, const SimTrackManager *)
std::unique_ptr< const G4TrackToParticleID > theG4TrackToParticleID
void setExitPoint(const Local3DPoint &exit)
bool ProcessHits(G4Step *, G4TouchableHistory *) override
uint32_t setDetUnitId(const G4Step *) override
#define nullptr
type of data representation of DDCompactView
Definition: DDCompactView.h:90
void printGlobalMomentum(float, float, float) const
std::unique_ptr< TrackingSlaveSD > slaveLowTof
static TrackerG4SimHitNumberingScheme & numberingScheme(const DDCompactView &cpv, const GeometricDet &det)
Geom::Theta< T > theta() const
Definition: PV3DBase.h:75
void fillHits(edm::PSimHitContainer &, const std::string &) override
Local3DPoint exitPoint() const
Exit point in the local Det frame.
Definition: PSimHit.h:38
float timeOfFlight() const
Definition: PSimHit.h:69
T mag2() const
The vector magnitude squared. Equivalent to vec.dot(vec)
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double f[11][100]
float pabs() const
fast and more accurate access to momentumAtEntry().mag()
Definition: PSimHit.h:63
std::unique_ptr< TrackerG4SimHitNumberingScheme > theNumberingScheme
void addEnergyLoss(float eloss)
Local3DPoint LocalPostStepPosition(const G4Step *step) const
const T & get() const
Definition: EventSetup.h:58
void printGlobal(const Local3DPoint &, const Local3DPoint &) const
void setNames(const std::vector< std::string > &)
float energyLoss() const
The energy deposit in the PSimHit, in ???.
Definition: PSimHit.h:75
Local3DPoint LocalPreStepPosition(const G4Step *step) const
unsigned int trackId() const
Definition: PSimHit.h:102
std::vector< PSimHit > PSimHitContainer
step
void EndOfEvent(G4HCofThisEvent *) override
void printLocal(const Local3DPoint &, const Local3DPoint &) const
Local3DPoint entryPoint() const
Entry point in the local Det frame.
Definition: PSimHit.h:35
unsigned int detUnitId() const
Definition: PSimHit.h:93
void startNewSimHit(const std::string &, const std::string &, int, int, int, int)