CMS 3D CMS Logo

CaloSD.cc
Go to the documentation of this file.
1 // File: CaloSD.cc
3 // Description: Sensitive Detector class for calorimeters
5 
11 
12 #include "G4EventManager.hh"
13 #include "G4SDManager.hh"
14 #include "G4Step.hh"
15 #include "G4Track.hh"
16 #include "G4VProcess.hh"
17 #include "G4GFlashSpot.hh"
18 #include "G4ParticleTable.hh"
19 
20 #include "G4SystemOfUnits.hh"
21 #include "G4PhysicalConstants.hh"
22 
23 #include <fstream>
24 
25 //#define EDM_ML_DEBUG
26 
28  const DDCompactView& cpv,
29  const SensitiveDetectorCatalog& clg,
30  edm::ParameterSet const& p,
31  const SimTrackManager* manager,
32  float timeSliceUnit,
33  bool ignoreTkID)
34  : SensitiveCaloDetector(name, cpv, clg, p),
35  G4VGFlashSensitiveDetector(),
36  eminHit(0.),
37  currentHit(nullptr),
38  m_trackManager(manager),
39  theHC(nullptr),
40  ignoreTrackID(ignoreTkID),
41  hcID(-1),
42  timeSlice(timeSliceUnit),
43  eminHitD(0.) {
44  //Parameters
45  edm::ParameterSet m_CaloSD = p.getParameter<edm::ParameterSet>("CaloSD");
46  energyCut = m_CaloSD.getParameter<double>("EminTrack") * GeV;
47  tmaxHit = m_CaloSD.getParameter<double>("TmaxHit") * ns;
48  std::vector<double> eminHits = m_CaloSD.getParameter<std::vector<double> >("EminHits");
49  std::vector<double> tmaxHits = m_CaloSD.getParameter<std::vector<double> >("TmaxHits");
50  std::vector<std::string> hcn = m_CaloSD.getParameter<std::vector<std::string> >("HCNames");
51  std::vector<int> useResMap = m_CaloSD.getParameter<std::vector<int> >("UseResponseTables");
52  std::vector<double> eminHitX = m_CaloSD.getParameter<std::vector<double> >("EminHitsDepth");
53  suppressHeavy = m_CaloSD.getParameter<bool>("SuppressHeavy");
54  kmaxIon = m_CaloSD.getParameter<double>("IonThreshold") * MeV;
55  kmaxProton = m_CaloSD.getParameter<double>("ProtonThreshold") * MeV;
56  kmaxNeutron = m_CaloSD.getParameter<double>("NeutronThreshold") * MeV;
57  nCheckedHits = m_CaloSD.getUntrackedParameter<int>("CheckHits", 25);
58  useMap = m_CaloSD.getUntrackedParameter<bool>("UseMap", true);
59  int verbn = m_CaloSD.getUntrackedParameter<int>("Verbosity", 0);
60  corrTOFBeam = m_CaloSD.getParameter<bool>("CorrectTOFBeam");
61  double beamZ = m_CaloSD.getParameter<double>("BeamPosition") * cm;
62  correctT = beamZ / c_light / nanosecond;
63 
64  SetVerboseLevel(verbn);
65  meanResponse.reset(nullptr);
66  for (unsigned int k = 0; k < hcn.size(); ++k) {
67  if (name == hcn[k]) {
68  if (k < eminHits.size())
69  eminHit = eminHits[k] * MeV;
70  if (k < eminHitX.size())
71  eminHitD = eminHitX[k] * MeV;
72  if (k < tmaxHits.size())
73  tmaxHit = tmaxHits[k] * ns;
74  if (k < useResMap.size() && useResMap[k] > 0) {
75  meanResponse.reset(new CaloMeanResponse(p));
76  break;
77  }
78  }
79  }
80  slave.reset(new CaloSlaveSD(name));
81 
84  isParameterized = false;
85 
86  entrancePoint.set(0., 0., 0.);
87  entranceLocal.set(0., 0., 0.);
88  posGlobal.set(0., 0., 0.);
90 
92  forceSave = false;
93 
94  edm::LogVerbatim("CaloSim") << "CaloSD: Minimum energy of track for saving it " << energyCut / GeV << " GeV"
95  << "\n"
96  << " Use of HitID Map " << useMap << "\n"
97  << " Check last " << nCheckedHits << " before saving the hit\n"
98  << " Correct TOF globally by " << correctT << " ns (Flag =" << corrTOFBeam << ")\n"
99  << " Save hits recorded before " << tmaxHit << " ns and if energy is above "
100  << eminHit / MeV << " MeV (for depth 0) or " << eminHitD / MeV
101  << " MeV (for nonzero depths);\n"
102  << " Time Slice Unit " << timeSlice << " Ignore TrackID Flag " << ignoreTrackID;
103 }
104 
106 
107 G4bool CaloSD::ProcessHits(G4Step* aStep, G4TouchableHistory*) {
108  NaNTrap(aStep);
109 
110 #ifdef EDM_ML_DEBUG
111  edm::LogVerbatim("CaloSim") << "CaloSD::" << GetName() << " ID= " << aStep->GetTrack()->GetTrackID()
112  << " prID= " << aStep->GetTrack()->GetParentID()
113  << " Eprestep= " << aStep->GetPreStepPoint()->GetKineticEnergy()
114  << " step= " << aStep->GetStepLength() << " Edep= " << aStep->GetTotalEnergyDeposit();
115 #endif
116  // apply shower library or parameterisation
117  if (isParameterized) {
118  if (getFromLibrary(aStep)) {
119  // for parameterized showers the primary track should be killed
120  aStep->GetTrack()->SetTrackStatus(fStopAndKill);
121  auto tv = aStep->GetSecondary();
122  auto vol = aStep->GetPreStepPoint()->GetPhysicalVolume();
123  for (auto& tk : *tv) {
124  if (tk->GetVolume() == vol) {
125  tk->SetTrackStatus(fStopAndKill);
126  }
127  }
128  return true;
129  }
130  }
131 
132  // ignore steps without energy deposit
133  edepositEM = edepositHAD = 0.f;
134  unsigned int unitID = setDetUnitId(aStep);
135  auto const theTrack = aStep->GetTrack();
136  uint16_t depth = getDepth(aStep);
137 
138  double time = theTrack->GetGlobalTime() / nanosecond;
139  int primaryID = getTrackID(theTrack);
140  if (unitID > 0) {
141  currentID.setID(unitID, time, primaryID, depth);
142  } else {
143  if (aStep->GetTotalEnergyDeposit() > 0.0) {
144  const G4TouchableHistory* touch = static_cast<const G4TouchableHistory*>(theTrack->GetTouchable());
145  edm::LogVerbatim("CaloSim") << "CaloSD::ProcessHits: unitID= " << unitID << " currUnit= " << currentID.unitID()
146  << " Detector: " << GetName() << " trackID= " << theTrack->GetTrackID() << " "
147  << theTrack->GetDefinition()->GetParticleName()
148  << "\n Edep= " << aStep->GetTotalEnergyDeposit()
149  << " PV: " << touch->GetVolume(0)->GetName()
150  << " PVid= " << touch->GetReplicaNumber(0) << " MVid= " << touch->GetReplicaNumber(1);
151  }
152  return false;
153  }
154 
155  if (aStep->GetTotalEnergyDeposit() == 0.0) {
156  //---VI: This line is for backward compatibility and should be removed
157  hitExists(aStep);
158  //---
159  return false;
160  }
161 
162  double energy = getEnergyDeposit(aStep);
163  if (energy > 0.0) {
165  edepositEM = energy;
166  } else {
168  }
169 #ifdef EDM_ML_DEBUG
170  G4TouchableHistory* touch = (G4TouchableHistory*)(theTrack->GetTouchable());
171  edm::LogVerbatim("CaloSim") << "CaloSD::" << GetName() << " PV:" << touch->GetVolume(0)->GetName()
172  << " PVid=" << touch->GetReplicaNumber(0) << " MVid=" << touch->GetReplicaNumber(1)
173  << " Unit:" << std::hex << unitID << std::dec << " Edep=" << edepositEM << " "
174  << edepositHAD << " ID=" << theTrack->GetTrackID() << " pID=" << theTrack->GetParentID()
175  << " E=" << theTrack->GetKineticEnergy() << " S=" << aStep->GetStepLength() << "\n "
176  << theTrack->GetDefinition()->GetParticleName() << " primaryID= " << primaryID
177  << " currentID= (" << currentID << ") previousID= (" << previousID << ")";
178 #endif
179  if (!hitExists(aStep)) {
180  currentHit = createNewHit(aStep);
181  }
182  return true;
183  }
184  return false;
185 }
186 
187 bool CaloSD::ProcessHits(G4GFlashSpot* aSpot, G4TouchableHistory*) {
188  edepositEM = edepositHAD = 0.f;
189  const G4Track* track = aSpot->GetOriginatorTrack()->GetPrimaryTrack();
191  return false;
192  }
193  double edep = aSpot->GetEnergySpot()->GetEnergy();
194  if (edep <= 0.0) {
195  return false;
196  }
197  edepositEM = edep;
198  G4Step fFakeStep;
199  G4StepPoint* fFakePreStepPoint = fFakeStep.GetPreStepPoint();
200  G4StepPoint* fFakePostStepPoint = fFakeStep.GetPostStepPoint();
201  fFakePreStepPoint->SetPosition(aSpot->GetPosition());
202  fFakePostStepPoint->SetPosition(aSpot->GetPosition());
203 
204  G4TouchableHandle fTouchableHandle = aSpot->GetTouchableHandle();
205  fFakePreStepPoint->SetTouchableHandle(fTouchableHandle);
206  fFakeStep.SetTotalEnergyDeposit(edep);
207 
208  unsigned int unitID = setDetUnitId(&fFakeStep);
209 
210  if (unitID > 0) {
211  double time = 0;
212  int primaryID = getTrackID(track);
213  uint16_t depth = getDepth(&fFakeStep);
214  currentID.setID(unitID, time, primaryID, depth);
215 #ifdef EDM_ML_DEBUG
216  edm::LogVerbatim("CaloSim") << "CaloSD:: GetSpotInfo for Unit 0x" << std::hex << currentID.unitID() << std::dec
217  << " Edeposit = " << edepositEM << " " << edepositHAD;
218 #endif
219  // Update if in the same detector, time-slice and for same track
220  if (currentID == previousID) {
222  } else {
223  posGlobal = aSpot->GetEnergySpot()->GetPosition();
224  // Reset entry point for new primary
225  if (currentID.trackID() != previousID.trackID()) {
226  entrancePoint = aSpot->GetPosition();
227  entranceLocal = aSpot->GetTouchableHandle()->GetHistory()->GetTopTransform().TransformPoint(entrancePoint);
228  incidentEnergy = track->GetKineticEnergy();
229 #ifdef EDM_ML_DEBUG
230  edm::LogVerbatim("CaloSim") << "CaloSD: Incident energy " << incidentEnergy / GeV << " GeV and"
231  << " entrance point " << entrancePoint << " (Global) " << entranceLocal
232  << " (Local)";
233 #endif
234  }
235  if (!checkHit()) {
236  currentHit = createNewHit(&fFakeStep);
237  }
238  }
239  return true;
240  }
241  return false;
242 }
243 
244 double CaloSD::getEnergyDeposit(const G4Step* aStep) { return aStep->GetTotalEnergyDeposit(); }
245 
246 bool CaloSD::getFromLibrary(const G4Step*) { return false; }
247 
248 void CaloSD::Initialize(G4HCofThisEvent* HCE) {
249  totalHits = 0;
250 
251 #ifdef EDM_ML_DEBUG
252  edm::LogVerbatim("CaloSim") << "CaloSD : Initialize called for " << GetName();
253 #endif
254 
255  //This initialization is performed at the beginning of an event
256  //------------------------------------------------------------
257  theHC = new CaloG4HitCollection(GetName(), collectionName[0]);
258 
259  if (hcID < 0) {
260  hcID = G4SDManager::GetSDMpointer()->GetCollectionID(collectionName[0]);
261  }
262  //theHC ownership is transfered here to HCE
263  HCE->AddHitsCollection(hcID, theHC);
264 }
265 
266 void CaloSD::EndOfEvent(G4HCofThisEvent*) {
267  // clean the hits for the last tracks
268 
270 
271 #ifdef EDM_ML_DEBUG
272  edm::LogVerbatim("CaloSim") << "CaloSD: EndofEvent entered with " << theHC->entries() << " entries";
273 #endif
274 }
275 
276 void CaloSD::clear() {}
277 
279 
281 #ifdef EDM_ML_DEBUG
282  edm::LogVerbatim("CaloSim") << "CaloSD: Collection " << theHC->GetName();
283 #endif
284  theHC->PrintAllHits();
285 }
286 
288  if (slave.get()->name() == hname) {
289  cc = slave.get()->hits();
290  }
291  slave.get()->Clean();
292 }
293 
294 G4ThreeVector CaloSD::setToLocal(const G4ThreeVector& global, const G4VTouchable* touch) const {
295  return touch->GetHistory()->GetTopTransform().TransformPoint(global);
296 }
297 
298 G4ThreeVector CaloSD::setToGlobal(const G4ThreeVector& local, const G4VTouchable* touch) const {
299  return touch->GetHistory()->GetTopTransform().Inverse().TransformPoint(local);
300 }
301 
302 bool CaloSD::hitExists(const G4Step* aStep) {
303  // Update if in the same detector, time-slice and for same track
304  if (currentID == previousID) {
306  return true;
307  }
308 
309  // Reset entry point for new primary
310  posGlobal = aStep->GetPreStepPoint()->GetPosition();
311  if (currentID.trackID() != previousID.trackID()) {
312  resetForNewPrimary(aStep);
313  }
314  return checkHit();
315 }
316 
318  //look in the HitContainer whether a hit with the same ID already exists:
319  bool found = false;
320  if (useMap) {
321  std::map<CaloHitID, CaloG4Hit*>::const_iterator it = hitMap.find(currentID);
322  if (it != hitMap.end()) {
323  currentHit = it->second;
324  found = true;
325  }
326  } else if (nCheckedHits > 0) {
327  int minhit = (theHC->entries() > nCheckedHits ? theHC->entries() - nCheckedHits : 0);
328  int maxhit = theHC->entries() - 1;
329 
330  for (int j = maxhit; j > minhit; --j) {
331  if ((*theHC)[j]->getID() == currentID) {
332  currentHit = (*theHC)[j];
333  found = true;
334  break;
335  }
336  }
337  }
338 
339  if (found) {
341  }
342  return found;
343 }
344 
345 int CaloSD::getNumberOfHits() { return theHC->entries(); }
346 
347 CaloG4Hit* CaloSD::createNewHit(const G4Step* aStep) {
348  auto const theTrack = aStep->GetTrack();
349 #ifdef EDM_ML_DEBUG
350  edm::LogVerbatim("CaloSim") << "CaloSD::CreateNewHit " << getNumberOfHits() << " for " << GetName()
351  << " Unit:" << currentID.unitID() << " " << currentID.depth() << " Edep= " << edepositEM
352  << " " << edepositHAD << " primaryID= " << currentID.trackID()
353  << " timeSlice= " << currentID.timeSliceID() << " ID= " << theTrack->GetTrackID() << " "
354  << theTrack->GetDefinition()->GetParticleName()
355  << " E(GeV)= " << theTrack->GetKineticEnergy() / GeV
356  << " parentID= " << theTrack->GetParentID() << "\n Ein= " << incidentEnergy
357  << " entranceGlobal: " << entrancePoint << " entranceLocal: " << entranceLocal
358  << " posGlobal: " << posGlobal;
359 #endif
360 
361  CaloG4Hit* aHit;
362  if (!reusehit.empty()) {
363  aHit = reusehit.back().release();
364  aHit->setEM(0.f);
365  aHit->setHadr(0.f);
366  reusehit.pop_back();
367  } else {
368  aHit = new CaloG4Hit;
369  }
370 
371  aHit->setID(currentID);
372  aHit->setEntry(entrancePoint.x(), entrancePoint.y(), entrancePoint.z());
374  aHit->setPosition(posGlobal.x(), posGlobal.y(), posGlobal.z());
376  updateHit(aHit);
377 
378  storeHit(aHit);
379  double etrack = 0;
380  if (currentID.trackID() == primIDSaved) { // The track is saved; nothing to be done
381  } else if (currentID.trackID() == theTrack->GetTrackID()) {
382  etrack = theTrack->GetKineticEnergy();
383 #ifdef EDM_ML_DEBUG
384  edm::LogVerbatim("CaloSim") << "CaloSD: set save the track " << currentID.trackID() << " etrack " << etrack
385  << " eCut " << energyCut << " force: " << forceSave
386  << " save: " << (etrack >= energyCut || forceSave);
387 #endif
388  if (etrack >= energyCut || forceSave) {
389  TrackInformation* trkInfo = cmsTrackInformation(theTrack);
390  trkInfo->storeTrack(true);
391  trkInfo->putInHistory();
392  }
393  } else {
395 #ifdef EDM_ML_DEBUG
396  edm::LogVerbatim("CaloSim") << "CaloSD : TrackwithHistory pointer for " << currentID.trackID() << " is " << trkh;
397 #endif
398  if (trkh != nullptr) {
399  etrack = sqrt(trkh->momentum().Mag2());
400  if (etrack >= energyCut) {
401  trkh->save();
402 #ifdef EDM_ML_DEBUG
403  edm::LogVerbatim("CaloSim") << "CaloSD: set save the track " << currentID.trackID() << " with Hit";
404 #endif
405  }
406  }
407  }
409  if (useMap)
410  ++totalHits;
411  return aHit;
412 }
413 
416 #ifdef EDM_ML_DEBUG
417  edm::LogVerbatim("CaloSim") << "CaloSD:" << GetName() << " Add energy deposit in " << currentID
418  << " Edep_em(MeV)= " << edepositEM << " Edep_had(MeV)= " << edepositHAD;
419 #endif
420 
421  // buffer for next steps:
423 }
424 
425 void CaloSD::resetForNewPrimary(const G4Step* aStep) {
426  auto const preStepPoint = aStep->GetPreStepPoint();
427  entrancePoint = preStepPoint->GetPosition();
428  entranceLocal = setToLocal(entrancePoint, preStepPoint->GetTouchable());
429  incidentEnergy = preStepPoint->GetKineticEnergy();
430 #ifdef EDM_ML_DEBUG
431  edm::LogVerbatim("CaloSim") << "CaloSD::resetForNewPrimary for " << GetName()
432  << " ID= " << aStep->GetTrack()->GetTrackID() << " Ein= " << incidentEnergy / GeV
433  << " GeV and"
434  << " entrance point global: " << entrancePoint << " local: " << entranceLocal;
435 #endif
436 }
437 
438 double CaloSD::getAttenuation(const G4Step* aStep, double birk1, double birk2, double birk3) const {
439  double weight = 1.;
440  double charge = aStep->GetPreStepPoint()->GetCharge();
441  double length = aStep->GetStepLength();
442 
443  if (charge != 0. && length > 0.) {
444  double density = aStep->GetPreStepPoint()->GetMaterial()->GetDensity();
445  double dedx = aStep->GetTotalEnergyDeposit() / length;
446  double rkb = birk1 / density;
447  double c = birk2 * rkb * rkb;
448  if (std::abs(charge) >= 2.)
449  rkb /= birk3; // based on alpha particle data
450  weight = 1. / (1. + rkb * dedx + c * dedx * dedx);
451 #ifdef EDM_ML_DEBUG
452  edm::LogVerbatim("CaloSim") << "CaloSD::getAttenuation in " << aStep->GetPreStepPoint()->GetMaterial()->GetName()
453  << " Charge " << charge << " dE/dx " << dedx << " Birk Const " << rkb << ", " << c
454  << " Weight = " << weight << " dE " << aStep->GetTotalEnergyDeposit();
455 #endif
456  }
457  return weight;
458 }
459 
460 void CaloSD::update(const BeginOfRun*) { initRun(); }
461 
462 void CaloSD::update(const BeginOfEvent* g4Event) {
463 #ifdef EDM_ML_DEBUG
464  edm::LogVerbatim("CaloSim") << "CaloSD: Dispatched BeginOfEvent for " << GetName() << " !";
465 #endif
466  clearHits();
467  initEvent(g4Event);
468 }
469 
470 void CaloSD::update(const EndOfTrack* trk) {
471  int id = (*trk)()->GetTrackID();
472  TrackInformation* trkI = cmsTrackInformation((*trk)());
473  int lastTrackID = -1;
474  if (trkI)
475  lastTrackID = trkI->getIDonCaloSurface();
476  if (id == lastTrackID) {
477  const TrackContainer* trksForThisEvent = m_trackManager->trackContainer();
478  if (trksForThisEvent != nullptr) {
479  int it = (int)(trksForThisEvent->size()) - 1;
480  if (it >= 0) {
481  TrackWithHistory* trkH = (*trksForThisEvent)[it];
482  if (trkH->trackID() == (unsigned int)(id))
483  tkMap[id] = trkH;
484 #ifdef EDM_ML_DEBUG
485  edm::LogVerbatim("CaloSim") << "CaloSD: get track " << it << " from Container of size "
486  << trksForThisEvent->size() << " with ID " << trkH->trackID();
487  } else {
488  edm::LogVerbatim("CaloSim") << "CaloSD: get track " << it << " from Container of size "
489  << trksForThisEvent->size() << " with no ID";
490 #endif
491  }
492  }
493  }
494 }
495 
496 void CaloSD::update(const ::EndOfEvent*) {
497  endEvent();
498  slave.get()->ReserveMemory(theHC->entries());
499 
500  int count(0);
501  int wrong(0);
502  double eEM(0.0);
503  double eHAD(0.0);
504  double eEM2(0.0);
505  double eHAD2(0.0);
506  double tt(0.0);
507  double zloc(0.0);
508  double zglob(0.0);
509  double ee(0.0);
510 
511  for (int i = 0; i < theHC->entries(); ++i) {
512  if (!saveHit((*theHC)[i])) {
513  ++wrong;
514  }
515  ++count;
516  double x = (*theHC)[i]->getEM();
517  eEM += x;
518  eEM2 += x * x;
519  x = (*theHC)[i]->getHadr();
520  eHAD += x;
521  eHAD2 += x * x;
522  tt += (*theHC)[i]->getTimeSlice();
523  ee += (*theHC)[i]->getIncidentEnergy();
524  zglob += std::abs((*theHC)[i]->getEntry().z());
525  zloc += std::abs((*theHC)[i]->getEntryLocal().z());
526  }
527 
528  double norm = (count > 0) ? 1.0 / count : 0.0;
529  eEM *= norm;
530  eEM2 *= norm;
531  eHAD *= norm;
532  eHAD2 *= norm;
533  eEM2 = std::sqrt(eEM2 - eEM * eEM);
534  eHAD2 = std::sqrt(eHAD2 - eHAD * eHAD);
535  tt *= norm;
536  ee *= norm;
537  zglob *= norm;
538  zloc *= norm;
539 
540  edm::LogVerbatim("CaloSim") << "CaloSD: " << GetName() << " store " << count << " hits; " << wrong
541  << " track IDs not given properly and " << totalHits - count
542  << " hits not passing cuts\n EmeanEM= " << eEM << " ErmsEM= " << eEM2
543  << "\n EmeanHAD= " << eHAD << " ErmsHAD= " << eHAD2 << " TimeMean= " << tt
544  << " E0mean= " << ee << " Zglob= " << zglob << " Zloc= " << zloc << " ";
545 
546  tkMap.erase(tkMap.begin(), tkMap.end());
547  std::vector<std::unique_ptr<CaloG4Hit>>().swap(reusehit);
548  if (useMap) hitMap.erase (hitMap.begin(), hitMap.end());
549 }
550 
552  cleanIndex = 0;
553  previousID.reset();
554  primIDSaved = -99;
555 #ifdef EDM_ML_DEBUG
556  edm::LogVerbatim("CaloSim") << "CaloSD: Clears hit vector for " << GetName()
557  << " and initialise slave: " << slave.get()->name();
558 #endif
559  slave.get()->Initialize();
560 }
561 
564  fpCaloG4HitAllocator->ResetStorage();
565  }
566 }
567 
569 
571 
573 
574 int CaloSD::getTrackID(const G4Track* aTrack) {
575  int primaryID = 0;
576  forceSave = false;
577  TrackInformation* trkInfo = cmsTrackInformation(aTrack);
578  if (trkInfo) {
579  primaryID = trkInfo->getIDonCaloSurface();
580 #ifdef EDM_ML_DEBUG
581  edm::LogVerbatim("CaloSim") << "CaloSD: hit update from track Id on Calo Surface " << trkInfo->getIDonCaloSurface();
582 #endif
583  } else {
584  primaryID = aTrack->GetTrackID();
585 #ifdef EDM_ML_DEBUG
586  edm::LogWarning("CaloSim") << "CaloSD: Problem with primaryID **** set by force to TkID **** " << primaryID;
587 #endif
588  }
589  return primaryID;
590 }
591 
592 int CaloSD::setTrackID(const G4Step* aStep) {
593  auto const theTrack = aStep->GetTrack();
594  TrackInformation* trkInfo = cmsTrackInformation(theTrack);
595  int primaryID = trkInfo->getIDonCaloSurface();
596  if (primaryID == 0) {
597  primaryID = theTrack->GetTrackID();
598  }
599 
600  if (primaryID != previousID.trackID()) {
601  resetForNewPrimary(aStep);
602  }
603 #ifdef EDM_ML_DEBUG
604  edm::LogVerbatim("CaloSim") << "CaloSD::setTrackID for " << GetName()
605  << " trackID= " << aStep->GetTrack()->GetTrackID() << " primaryID= " << primaryID;
606 #endif
607  return primaryID;
608 }
609 
610 uint16_t CaloSD::getDepth(const G4Step*) { return 0; }
611 
613  double emin(eminHit);
614  if (hit->getDepth() > 0)
615  emin = eminHitD;
616 #ifdef EDM_ML_DEBUG
617  edm::LogVerbatim("CaloSim") << "CaloSD::filterHit(..) Depth " << hit->getDepth() << " Emin = " << emin << " ("
618  << eminHit << ", " << eminHitD << ")";
619 #endif
620  return ((time <= tmaxHit) && (hit->getEnergyDeposit() > emin));
621 }
622 
623 double CaloSD::getResponseWt(const G4Track* aTrack) {
624  double wt = 1.0;
625  if (meanResponse.get()) {
626  TrackInformation* trkInfo = cmsTrackInformation(aTrack);
627  wt = meanResponse.get()->getWeight(trkInfo->genParticlePID(), trkInfo->genParticleP());
628  }
629  return wt;
630 }
631 
633  if (hit == nullptr || previousID.trackID() < 0) {
634  edm::LogWarning("CaloSim") << "CaloSD: hit to be stored is nullptr !!"
635  << " previousID.trackID()= " << previousID.trackID();
636  return;
637  }
638 
639  theHC->insert(hit);
640  if (useMap)
641  hitMap.insert(std::pair<CaloHitID, CaloG4Hit*>(previousID, hit));
642 }
643 
645  int tkID;
646  bool ok = true;
647  if (m_trackManager) {
648  tkID = m_trackManager->giveMotherNeeded(aHit->getTrackID());
649  if (tkID == 0) {
650  if (m_trackManager->trackExists(aHit->getTrackID()))
651  tkID = (aHit->getTrackID());
652  else {
653  ok = false;
654  }
655  }
656  } else {
657  tkID = aHit->getTrackID();
658  ok = false;
659  }
660 #ifdef EDM_ML_DEBUG
661  edm::LogVerbatim("CaloSim") << "CalosD: Track ID " << aHit->getTrackID() << " changed to " << tkID
662  << " by SimTrackManager Status " << ok;
663 #endif
664  double time = aHit->getTimeSlice();
665  if (corrTOFBeam)
666  time += correctT;
667  slave.get()->processHits(aHit->getUnitID(), aHit->getEM() / GeV, aHit->getHadr() / GeV, time, tkID, aHit->getDepth());
668 #ifdef EDM_ML_DEBUG
669  edm::LogVerbatim("CaloSim") << "CaloSD: Store Hit at " << std::hex << aHit->getUnitID() << std::dec << " "
670  << aHit->getDepth() << " due to " << tkID << " in time " << time << " of energy "
671  << aHit->getEM() / GeV << " GeV (EM) and " << aHit->getHadr() / GeV << " GeV (Hadr)";
672 #endif
673  return ok;
674 }
675 
676 void CaloSD::update(const BeginOfTrack* trk) {
677  int primary = -1;
678  TrackInformation* trkInfo = cmsTrackInformation((*trk)());
679  if (trkInfo->isPrimary())
680  primary = (*trk)()->GetTrackID();
681 
682 #ifdef EDM_ML_DEBUG
683  edm::LogVerbatim("CaloSim") << "New track: isPrimary " << trkInfo->isPrimary() << " primary ID = " << primary
684  << " primary ancestor ID " << primAncestor;
685 #endif
686 
687  // update the information if a different primary track ID
688 
689  if (primary > 0 && primary != primAncestor) {
690  primAncestor = primary;
691 
692  // clean the hits information
693 
694  if (theHC->entries() > 0)
696  }
697 }
698 
700  std::vector<CaloG4Hit*>* theCollection = theHC->GetVector();
701 
702 #ifdef EDM_ML_DEBUG
703  edm::LogVerbatim("CaloSim") << "CaloSD: collection before merging, size = " << theHC->entries();
704 #endif
705  if (reusehit.empty())
706  reusehit.reserve(theHC->entries() - cleanIndex);
707 
708  // if no map used, merge before hits to have the save situation as a map
709  if ( !useMap ) {
710  std::vector<CaloG4Hit*> hitvec;
711 
712  hitvec.swap(*theCollection);
713  sort((hitvec.begin() + cleanIndex), hitvec.end(), CaloG4HitLess());
714 #ifdef EDM_ML_DEBUG
715  edm::LogVerbatim("CaloSim") << "CaloSD::cleanHitCollection: sort hits in buffer starting from "
716  << "element = " << cleanIndex;
717  for (unsigned int i = 0; i < hitvec.size(); ++i)
718  edm::LogVerbatim("CaloSim") << i << " " << *hitvec[i];
719 #endif
721  for (unsigned int i= cleanIndex; i < hitvec.size(); ++i) {
722  int jump = 0;
723  for (unsigned int j = i + 1; j < hitvec.size() && equal(hitvec[i], hitvec[j]); ++j) {
724  ++jump;
725  // merge j to i
726  (*hitvec[i]).addEnergyDeposit(*hitvec[j]);
727  (*hitvec[j]).setEM(0.);
728  (*hitvec[j]).setHadr(0.);
729  reusehit.emplace_back(hitvec[j]);
730  hitvec[j] = nullptr;
731  }
732  i += jump;
733  }
734 #ifdef EDM_ML_DEBUG
735  edm::LogVerbatim("CaloSim") << "CaloSD: cleanHitCollection merge the hits in buffer ";
736  for (unsigned int i = 0; i < hitvec.size(); ++i)
737  edm::LogVerbatim("CaloSim") << i << " " << *hitvec[i];
738 #endif
739  //move all nullptr to end of list and then remove them
740  hitvec.erase(std::stable_partition(hitvec.begin()+cleanIndex,
741  hitvec.end(), [](CaloG4Hit* p) { return p!= nullptr;}),
742  hitvec.end());
743 #ifdef EDM_ML_DEBUG
744  edm::LogVerbatim("CaloSim") << "CaloSD::cleanHitCollection: remove the merged hits in buffer,"
745  << " new size = " << hitvec.size();
746  for (unsigned int i = 0; i < hitvec.size(); ++i)
747  edm::LogVerbatim("CaloSim") << i << " " << *hitvec[i];
748 #endif
749  hitvec.swap(*theCollection);
750  totalHits = theHC->entries();
751  }
752 
753 #ifdef EDM_ML_DEBUG
754  edm::LogVerbatim("CaloSim") << "CaloSD: collection after merging, size= " << theHC->entries()
755  << " Size of reusehit= " << reusehit.size()
756  << "\n starting hit selection from index = " << cleanIndex;
757 #endif
758 
759  int addhit = 0;
760  for (unsigned int i = cleanIndex; i < theCollection->size(); ++i) {
761  CaloG4Hit* aHit((*theCollection)[i]);
762 
763  // selection
764 
765  double time = aHit->getTimeSlice();
766  if (corrTOFBeam)
767  time += correctT;
768  if (!filterHit(aHit, time)) {
769 #ifdef EDM_ML_DEBUG
770  edm::LogVerbatim("CaloSim") << "CaloSD: dropped CaloG4Hit "
771  << " " << *aHit;
772 #endif
773 
774  // create the list of hits to be reused
775 
776  reusehit.emplace_back((*theCollection)[i]);
777  (*theCollection)[i] = nullptr;
778  ++addhit;
779  }
780  }
781 
782 #ifdef EDM_ML_DEBUG
783  edm::LogVerbatim("CaloSim") << "CaloSD: Size of reusehit after selection = " << reusehit.size()
784  << " Number of added hit = " << addhit;
785 #endif
786  if (useMap) {
787  if (addhit > 0) {
788  int offset = reusehit.size() - addhit;
789  for (int ii = addhit - 1; ii >= 0; --ii) {
790  CaloHitID theID = reusehit[offset + ii]->getID();
791  hitMap.erase(theID);
792  }
793  }
794  }
795 
796  //move all nullptr to end of list and then remove them
797  theCollection->erase(std::stable_partition(theCollection->begin()+cleanIndex,
798  theCollection->end(), [](CaloG4Hit* p) { return p!= nullptr;}),
799  theCollection->end());
800 #ifdef EDM_ML_DEBUG
801  edm::LogVerbatim("CaloSim") << "CaloSD: hit collection after selection, size = " << theHC->entries();
802  theHC->PrintAllHits();
803 #endif
804 
805  cleanIndex = theHC->entries();
806 }
float edepositEM
Definition: CaloSD.h:129
Int_t getEntry(TBranch *branch, EntryNumber entryNumber)
Definition: RootTree.cc:495
double energyCut
Definition: CaloSD.h:133
T getParameter(std::string const &) const
T getUntrackedParameter(std::string const &, T const &) const
virtual bool getFromLibrary(const G4Step *step)
Definition: CaloSD.cc:246
std::vector< PCaloHit > PCaloHitContainer
const double GeV
Definition: MathUtil.h:16
double kmaxNeutron
Definition: CaloSD.h:138
G4ThreadLocal G4Allocator< CaloG4Hit > * fpCaloG4HitAllocator
Definition: CaloG4Hit.cc:11
void updateHit(CaloG4Hit *)
Definition: CaloSD.cc:414
virtual uint16_t getDepth(const G4Step *)
Definition: CaloSD.cc:610
virtual double getEnergyDeposit(const G4Step *step)
Definition: CaloSD.cc:244
bool storeTrack() const
int getIDonCaloSurface() const
bool corrTOFBeam
Definition: CaloSD.h:153
int totalHits
Definition: CaloSD.h:158
void setIncidentEnergy(double e)
Definition: CaloG4Hit.h:62
void setEntryLocal(double x, double y, double z)
Definition: CaloG4Hit.h:50
void DrawAll() override
Definition: CaloSD.cc:278
void clear() override
Definition: CaloSD.cc:276
#define nullptr
uint32_t setDetUnitId(const G4Step *step) override=0
double genParticleP() const
bool useMap
Definition: CaloSD.h:152
uint16_t getDepth() const
Definition: CaloG4Hit.h:68
int hcID
Definition: CaloSD.h:155
double eminHitD
Definition: CaloSD.h:163
Definition: weight.py:1
G4ThreeVector posGlobal
Definition: CaloSD.h:127
virtual int getTrackID(const G4Track *)
Definition: CaloSD.cc:574
int primIDSaved
Definition: CaloSD.h:159
void Initialize(G4HCofThisEvent *HCE) override
Definition: CaloSD.cc:248
int primAncestor
Definition: CaloSD.h:156
uint16_t depth() const
Definition: CaloHitID.h:24
void reset() override
Definition: CaloSD.cc:562
Compact representation of the geometrical detector hierarchy.
Definition: DDCompactView.h:80
double kmaxProton
Definition: CaloSD.h:138
void fillHits(edm::PCaloHitContainer &, const std::string &) override
Definition: CaloSD.cc:287
double eminHit
Definition: CaloSD.h:133
void swap(Association< C > &lhs, Association< C > &rhs)
Definition: Association.h:116
bool equal(const T &first, const T &second)
Definition: Equal.h:34
virtual void initEvent(const BeginOfEvent *)
Definition: CaloSD.cc:570
void cleanHitCollection()
Definition: CaloSD.cc:699
void reset()
Definition: CaloHitID.cc:48
const double MeV
bool forceSave
Definition: CaloSD.h:140
void addEnergyDeposit(double em, double hd)
Definition: CaloG4Hit.cc:45
float timeSlice
Definition: CaloSD.h:162
const TrackContainer * trackContainer() const
int genParticlePID() const
bool checkHit()
Definition: CaloSD.cc:317
std::string const collectionName[nCollections]
Definition: Collections.h:47
double kmaxIon
Definition: CaloSD.h:138
bool suppressHeavy
Definition: CaloSD.h:137
std::unique_ptr< CaloSlaveSD > slave
Definition: CaloSD.h:145
int timeSliceID() const
Definition: CaloHitID.h:21
std::vector< TrackWithHistory * > TrackContainer
Definition: TrackContainer.h:8
float edepositHAD
Definition: CaloSD.h:129
T sqrt(T t)
Definition: SSEVec.h:18
unsigned int trackID() const
int trackID() const
Definition: CaloHitID.h:23
void resetForNewPrimary(const G4Step *)
Definition: CaloSD.cc:425
bool trackExists(unsigned int i) const
void setEM(double e)
Definition: CaloG4Hit.h:56
void setID(uint32_t i, double d, int j, uint16_t k=0)
Definition: CaloG4Hit.h:71
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
CaloG4Hit * createNewHit(const G4Step *)
Definition: CaloSD.cc:347
G4bool ProcessHits(G4Step *step, G4TouchableHistory *) override
Definition: CaloSD.cc:107
double f[11][100]
int getNumberOfHits()
Definition: CaloSD.cc:345
G4ThreeVector setToGlobal(const G4ThreeVector &, const G4VTouchable *) const
Definition: CaloSD.cc:298
CaloSD(const std::string &aSDname, const DDCompactView &cpv, const SensitiveDetectorCatalog &clg, edm::ParameterSet const &p, const SimTrackManager *, float timeSlice=1., bool ignoreTkID=false)
Definition: CaloSD.cc:27
CaloHitID previousID
Definition: CaloSD.h:131
~CaloSD() override
Definition: CaloSD.cc:105
CaloG4Hit * currentHit
Definition: CaloSD.h:135
int giveMotherNeeded(int i) const
void storeHit(CaloG4Hit *)
Definition: CaloSD.cc:632
TrackInformation * cmsTrackInformation(const G4Track *aTrack)
virtual bool filterHit(CaloG4Hit *, double)
Definition: CaloSD.cc:612
ii
Definition: cuy.py:590
double tmaxHit
Definition: CaloSD.h:133
int k[5][pyjets_maxn]
void setID(uint32_t unitID, double timeSlice, int trackID, uint16_t depth=0)
Definition: CaloHitID.cc:40
G4ThreeVector setToLocal(const G4ThreeVector &, const G4VTouchable *) const
Definition: CaloSD.cc:294
bool hitExists(const G4Step *)
Definition: CaloSD.cc:302
int getTrackID() const
Definition: CaloG4Hit.h:64
std::unique_ptr< CaloMeanResponse > meanResponse
Definition: CaloSD.h:146
CaloHitID currentID
Definition: CaloSD.h:131
virtual void initRun()
Definition: CaloSD.cc:568
double correctT
Definition: CaloSD.h:164
std::map< CaloHitID, CaloG4Hit * > hitMap
Definition: CaloSD.h:166
const math::XYZVectorD & momentum() const
bool isPrimary() const
void EndOfEvent(G4HCofThisEvent *eventHC) override
Definition: CaloSD.cc:266
CSCCFEBTimeSlice const *const timeSlice(T const &data, int nCFEB, int nSample)
double getAttenuation(const G4Step *aStep, double birk1, double birk2, double birk3) const
Definition: CaloSD.cc:438
double getEM() const
Definition: CaloG4Hit.h:55
int nCheckedHits
Definition: CaloSD.h:160
virtual void endEvent()
Definition: CaloSD.cc:572
CaloG4HitCollection * theHC
Definition: CaloSD.h:148
void setHadr(double e)
Definition: CaloG4Hit.h:59
float incidentEnergy
Definition: CaloSD.h:128
virtual int setTrackID(const G4Step *)
Definition: CaloSD.cc:592
void setPosition(double x, double y, double z)
Definition: CaloG4Hit.h:53
void setEntry(double x, double y, double z)
Definition: CaloG4Hit.h:47
G4THitsCollection< CaloG4Hit > CaloG4HitCollection
static bool isGammaElectronPositron(int pdgCode)
bool isParameterized
Definition: CaloSD.h:151
double getTimeSlice() const
Definition: CaloG4Hit.h:66
std::map< int, TrackWithHistory * > tkMap
Definition: CaloSD.h:167
std::vector< std::unique_ptr< CaloG4Hit > > reusehit
Definition: CaloSD.h:168
const SimTrackManager * m_trackManager
Definition: CaloSD.h:143
uint32_t getUnitID() const
Definition: CaloG4Hit.h:65
uint32_t unitID() const
Definition: CaloHitID.h:20
void clearHits() override
Definition: CaloSD.cc:551
double getResponseWt(const G4Track *)
Definition: CaloSD.cc:623
bool saveHit(CaloG4Hit *)
Definition: CaloSD.cc:644
void PrintAll() override
Definition: CaloSD.cc:280
G4ThreeVector entrancePoint
Definition: CaloSD.h:125
G4ThreeVector entranceLocal
Definition: CaloSD.h:126
double getHadr() const
Definition: CaloG4Hit.h:58
void update(const BeginOfRun *) override
This routine will be called when the appropriate signal arrives.
Definition: CaloSD.cc:460
double getEnergyDeposit() const
Definition: CaloG4Hit.h:77
int cleanIndex
Definition: CaloSD.h:157
void NaNTrap(const G4Step *step) const
bool ignoreTrackID
Definition: CaloSD.h:150