CMS 3D CMS Logo

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