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