CMS 3D CMS Logo

CaloTrkProcessing.cc
Go to the documentation of this file.
4 
6 
8 
9 #include "G4EventManager.hh"
10 #include "G4LogicalVolumeStore.hh"
11 #include "G4LogicalVolume.hh"
12 #include "G4Step.hh"
13 #include "G4Track.hh"
14 #include "G4SystemOfUnits.hh"
15 #include "DD4hep/Filter.h"
16 
17 #include <sstream>
18 //#define EDM_ML_DEBUG
19 
21  const CaloSimulationParameters& csps,
22  const SensitiveDetectorCatalog& clg,
23  bool testBeam,
24  double eMin,
25  bool putHistory,
26  bool doFineCalo,
27  double eMinFine,
28  int addlevel,
29  const std::vector<std::string>& fineNames,
30  const std::vector<int>& fineLevels,
31  const std::vector<int>& useFines,
32  const SimTrackManager*)
34  testBeam_(testBeam),
35  eMin_(eMin),
36  putHistory_(putHistory),
37  doFineCalo_(doFineCalo),
38  eMinFine_(eMinFine),
39  addlevel_(addlevel),
40  lastTrackID_(-1) {
41  //Initialise the parameter set
42 
43  edm::LogVerbatim("CaloSim") << "CaloTrkProcessing: Initialised with TestBeam = " << testBeam_ << " Emin = " << eMin_
44  << " Flags " << putHistory_ << " (History), " << doFineCalo_ << " (Special Calorimeter)";
45  edm::LogVerbatim("CaloSim") << "CaloTrkProcessing: Have a possibility of " << fineNames.size()
46  << " fine calorimeters of which " << useFines.size() << " are selected";
47  for (unsigned int k = 0; k < fineNames.size(); ++k)
48  edm::LogVerbatim("CaloSim") << "[" << k << "] " << fineNames[k] << " at " << fineLevels[k];
49  std::ostringstream st1;
50  for (unsigned int k = 0; k < useFines.size(); ++k)
51  st1 << " [" << k << "] " << useFines[k] << ":" << fineNames[useFines[k]];
52  edm::LogVerbatim("CaloSim") << "CaloTrkProcessing used calorimeters" << st1.str();
53 
54  // Debug prints
55  edm::LogVerbatim("CaloSim") << "CaloTrkProcessing: " << csps.caloNames_.size() << " entries for caloNames:";
56  for (unsigned int i = 0; i < csps.caloNames_.size(); i++)
57  edm::LogVerbatim("CaloSim") << " (" << i << ") " << csps.caloNames_[i];
58  edm::LogVerbatim("CaloSim") << "CaloTrkProcessing: " << csps.levels_.size() << " entries for levels:";
59  for (unsigned int i = 0; i < csps.levels_.size(); i++)
60  edm::LogVerbatim("CaloSim") << " (" << i << ") " << (csps.levels_[i] + addlevel_);
61  edm::LogVerbatim("CaloSim") << "CaloTrkProcessing: " << csps.neighbours_.size() << " entries for neighbours:";
62  for (unsigned int i = 0; i < csps.neighbours_.size(); i++)
63  edm::LogVerbatim("CaloSim") << " (" << i << ") " << csps.neighbours_[i];
64  edm::LogVerbatim("CaloSim") << "CaloTrkProcessing: " << csps.insideNames_.size() << " entries for insideNames:";
65  for (unsigned int i = 0; i < csps.insideNames_.size(); i++)
66  edm::LogVerbatim("CaloSim") << " (" << i << ") " << csps.insideNames_[i];
67  edm::LogVerbatim("CaloSim") << "CaloTrkProcessing: " << csps.insideLevel_.size() << " entries for insideLevel:";
68  for (unsigned int i = 0; i < csps.insideLevel_.size(); i++)
69  edm::LogVerbatim("CaloSim") << " (" << i << ") " << (csps.insideLevel_[i] + addlevel_);
70 
71  if (csps.caloNames_.size() < csps.neighbours_.size()) {
72  edm::LogError("CaloSim") << "CaloTrkProcessing: # of Calorimeter bins " << csps.caloNames_.size()
73  << " does not match with " << csps.neighbours_.size() << " ==> illegal ";
74  throw cms::Exception("Unknown", "CaloTrkProcessing")
75  << "Calorimeter array size does not match with size of neighbours\n";
76  }
77 
78  const G4LogicalVolumeStore* lvs = G4LogicalVolumeStore::GetInstance();
79  std::vector<G4LogicalVolume*>::const_iterator lvcite;
80  int istart = 0;
81  for (unsigned int i = 0; i < csps.caloNames_.size(); i++) {
82  G4LogicalVolume* lv = nullptr;
83  G4String name(csps.caloNames_[i]);
84  for (lvcite = lvs->begin(); lvcite != lvs->end(); lvcite++) {
85  G4String namx(static_cast<std::string>(dd4hep::dd::noNamespace((*lvcite)->GetName())));
86  if (namx == name) {
87  lv = (*lvcite);
88  break;
89  }
90  }
91  if (lv != nullptr) {
93  detector.name = name;
94  detector.lv = lv;
95  detector.level = (csps.levels_[i] + addlevel_);
96  if (istart + csps.neighbours_[i] > static_cast<int>(csps.insideNames_.size())) {
97  edm::LogError("CaloSim") << "CaloTrkProcessing: # of InsideNames bins " << csps.insideNames_.size()
98  << " too few compaerd to " << istart + csps.neighbours_[i]
99  << " requested ==> illegal ";
100  throw cms::Exception("Unknown", "CaloTrkProcessing")
101  << "InsideNames array size does not match with list of neighbours\n";
102  }
103  std::vector<std::string> inside;
104  std::vector<G4LogicalVolume*> insideLV;
105  std::vector<int> insideLevels;
106  for (int k = 0; k < csps.neighbours_[i]; k++) {
107  lv = nullptr;
108  name = static_cast<G4String>(csps.insideNames_[istart + k]);
109  for (lvcite = lvs->begin(); lvcite != lvs->end(); lvcite++) {
110  G4String namx(static_cast<std::string>(dd4hep::dd::noNamespace((*lvcite)->GetName())));
111  if (namx == name) {
112  lv = (*lvcite);
113  break;
114  }
115  }
116  inside.push_back(name);
117  insideLV.push_back(lv);
118  insideLevels.push_back(csps.insideLevel_[istart + k] + addlevel_);
119  }
120  detector.fromDets = inside;
121  detector.fromDetL = insideLV;
122  detector.fromLevels = insideLevels;
123  detectors_.emplace_back(detector);
124  }
125  istart += csps.neighbours_[i];
126  }
127 
128  for (unsigned int i = 0; i < useFines.size(); i++) {
129  G4LogicalVolume* lv = nullptr;
130  G4String name = static_cast<G4String>(fineNames[useFines[i]]);
131  for (lvcite = lvs->begin(); lvcite != lvs->end(); lvcite++) {
132  G4String namx(static_cast<std::string>(dd4hep::dd::noNamespace((*lvcite)->GetName())));
133  if (namx == name) {
134  lv = (*lvcite);
135  break;
136  }
137  }
138  if (lv != nullptr) {
140  detector.name = name;
141  detector.lv = lv;
142  detector.level = fineLevels[useFines[i]];
143  detector.fromDets.clear();
144  detector.fromDetL.clear();
145  detector.fromLevels.clear();
146  fineDetectors_.emplace_back(detector);
147  }
148  }
149 
150  edm::LogVerbatim("CaloSim") << "CaloTrkProcessing: with " << detectors_.size() << " calorimetric volumes";
151  for (unsigned int i = 0; i < detectors_.size(); i++) {
152  edm::LogVerbatim("CaloSim") << "CaloTrkProcessing: Calorimeter volume " << i << " " << detectors_[i].name << " LV "
153  << detectors_[i].lv << " at level " << detectors_[i].level << " with "
154  << detectors_[i].fromDets.size() << " neighbours";
155  for (unsigned int k = 0; k < detectors_[i].fromDets.size(); k++)
156  edm::LogVerbatim("CaloSim") << " Element " << k << " " << detectors_[i].fromDets[k] << " LV "
157  << detectors_[i].fromDetL[k] << " at level " << detectors_[i].fromLevels[k];
158  }
159 
160  doFineCalo_ = doFineCalo_ && !(fineDetectors_.empty());
161  edm::LogVerbatim("CaloSim") << "CaloTrkProcessing: with " << fineDetectors_.size() << " special calorimetric volumes";
162  for (unsigned int i = 0; i < detectors_.size(); i++)
163  edm::LogVerbatim("CaloSim") << "CaloTrkProcessing: Calorimeter volume " << i << " " << detectors_[i].name << " LV "
164  << detectors_[i].lv << " at level " << detectors_[i].level;
165 }
166 
168 
170 
171 void CaloTrkProcessing::update(const G4Step* aStep) {
172  // define if you are at the surface of CALO
173 
174  G4Track* theTrack = aStep->GetTrack();
175  int id = theTrack->GetTrackID();
176 
177  TrackInformation* trkInfo = dynamic_cast<TrackInformation*>(theTrack->GetUserInformation());
178 
179  if (trkInfo == nullptr) {
180  edm::LogError("CaloSim") << "CaloTrkProcessing: No trk info !!!! abort ";
181  throw cms::Exception("Unknown", "CaloTrkProcessing") << "cannot get trkInfo for Track " << id << "\n";
182  }
183 
184  if (doFineCalo_) {
185  int prestepLV = isItCalo(aStep->GetPreStepPoint()->GetTouchable(), fineDetectors_);
186  int poststepLV = isItCalo(aStep->GetPostStepPoint()->GetTouchable(), fineDetectors_);
187 
188  // Once per track, determine whether track started in fine volume
189  if (!trkInfo->startedInFineVolumeIsSet())
190  trkInfo->setStartedInFineVolume(prestepLV >= 0);
191 
192  // Boundary-crossing logic
193  if (prestepLV < 0 && poststepLV >= 0) {
194 #ifdef EDM_ML_DEBUG
195  edm::LogVerbatim("DoFineCalo") << "Track " << id << " entered a fine volume:"
196  << " pdgid=" << theTrack->GetDefinition()->GetPDGEncoding()
197  << " theTrack->GetCurrentStepNumber()=" << theTrack->GetCurrentStepNumber()
198  << " prestepLV=" << prestepLV << " poststepLV=" << poststepLV
199  << " GetKineticEnergy[GeV]=" << theTrack->GetKineticEnergy() / CLHEP::GeV
200  << " prestepPosition[cm]=("
201  << theTrack->GetStep()->GetPreStepPoint()->GetPosition().x() / CLHEP::cm << ","
202  << theTrack->GetStep()->GetPreStepPoint()->GetPosition().y() / CLHEP::cm << ","
203  << theTrack->GetStep()->GetPreStepPoint()->GetPosition().z() / CLHEP::cm << ")"
204  << " poststepPosition[cm]=("
205  << theTrack->GetStep()->GetPostStepPoint()->GetPosition().x() / CLHEP::cm << ","
206  << theTrack->GetStep()->GetPostStepPoint()->GetPosition().y() / CLHEP::cm << ","
207  << theTrack->GetStep()->GetPostStepPoint()->GetPosition().z() / CLHEP::cm << ")"
208  << " position[cm]=(" << theTrack->GetPosition().x() / CLHEP::cm << ","
209  << theTrack->GetPosition().y() / CLHEP::cm << ","
210  << theTrack->GetPosition().z() / CLHEP::cm << ")"
211  << " vertex_position[cm]=(" << theTrack->GetVertexPosition().x() / CLHEP::cm << ","
212  << theTrack->GetVertexPosition().y() / CLHEP::cm << ","
213  << theTrack->GetVertexPosition().z() / CLHEP::cm << ")"
214  << " GetVertexKineticEnergy[GeV]="
215  << theTrack->GetVertexKineticEnergy() / CLHEP::GeV;
216 #endif
217  if (!trkInfo->startedInFineVolume() && !trkInfo->crossedBoundary()) {
218  trkInfo->setCrossedBoundary(theTrack);
219 #ifdef EDM_ML_DEBUG
220  edm::LogVerbatim("DoFineCalo") << "Track " << id << " marked as boundary-crossing; sanity check:"
221  << " theTrack->GetTrackID()=" << theTrack->GetTrackID()
222  << " trkInfo->crossedBoundary()=" << trkInfo->crossedBoundary();
223 #endif
224  }
225 #ifdef EDM_ML_DEBUG
226  else {
227  edm::LogVerbatim("DoFineCalo") << "Track " << id << " REENTERED a fine volume;"
228  << " not counting this boundary crossing!";
229  }
230 #endif
231 
232  }
233 #ifdef EDM_ML_DEBUG
234  else if (prestepLV >= 0 && poststepLV < 0) {
235  edm::LogVerbatim("DoFineCalo") << "Track " << id << " exited a fine volume:"
236  << " theTrack->GetCurrentStepNumber()=" << theTrack->GetCurrentStepNumber()
237  << " prestepLV=" << prestepLV << " poststepLV=" << poststepLV
238  << " GetKineticEnergy[GeV]=" << theTrack->GetKineticEnergy() / CLHEP::GeV
239  << " prestepPosition[cm]=("
240  << theTrack->GetStep()->GetPreStepPoint()->GetPosition().x() / CLHEP::cm << ","
241  << theTrack->GetStep()->GetPreStepPoint()->GetPosition().y() / CLHEP::cm << ","
242  << theTrack->GetStep()->GetPreStepPoint()->GetPosition().z() / CLHEP::cm << ")"
243  << " poststepPosition[cm]=("
244  << theTrack->GetStep()->GetPostStepPoint()->GetPosition().x() / CLHEP::cm << ","
245  << theTrack->GetStep()->GetPostStepPoint()->GetPosition().y() / CLHEP::cm << ","
246  << theTrack->GetStep()->GetPostStepPoint()->GetPosition().z() / CLHEP::cm << ")";
247  }
248 #endif
249  }
250 
251  if (testBeam_) {
252  if (trkInfo->getIDonCaloSurface() == 0) {
253 #ifdef EDM_ML_DEBUG
254  edm::LogVerbatim("CaloSim") << "CaloTrkProcessing set IDonCaloSurface to " << id << " at step Number "
255  << theTrack->GetCurrentStepNumber();
256 #endif
257  trkInfo->setIDonCaloSurface(id, 0, 0, theTrack->GetDefinition()->GetPDGEncoding(), theTrack->GetMomentum().mag());
258  lastTrackID_ = id;
259  if (theTrack->GetKineticEnergy() / CLHEP::MeV > eMin_)
260  trkInfo->putInHistory();
261  }
262  } else {
263  if (putHistory_) {
264  trkInfo->putInHistory();
265  // trkInfo->setAncestor();
266  }
267 #ifdef EDM_ML_DEBUG
268  edm::LogVerbatim("CaloSim") << "CaloTrkProcessing Entered for " << id << " at stepNumber "
269  << theTrack->GetCurrentStepNumber() << " IDonCaloSur.. "
270  << trkInfo->getIDonCaloSurface() << " CaloCheck " << trkInfo->caloIDChecked();
271 #endif
272  if (trkInfo->getIDonCaloSurface() != 0) {
273  if (trkInfo->caloIDChecked() == false) {
274  G4StepPoint* postStepPoint = aStep->GetPostStepPoint();
275  const G4VTouchable* post_touch = postStepPoint->GetTouchable();
276 
277  if (isItInside(post_touch, trkInfo->getIDCaloVolume(), trkInfo->getIDLastVolume()) > 0) {
278  trkInfo->setIDonCaloSurface(0, -1, -1, 0, 0);
279  } else {
280  trkInfo->setCaloIDChecked(true);
281  }
282  }
283  } else {
284  G4StepPoint* postStepPoint = aStep->GetPostStepPoint();
285  const G4VTouchable* post_touch = postStepPoint->GetTouchable();
286  int ical = isItCalo(post_touch, detectors_);
287  if (ical >= 0) {
288  G4StepPoint* preStepPoint = aStep->GetPreStepPoint();
289  const G4VTouchable* pre_touch = preStepPoint->GetTouchable();
290  int inside = isItInside(pre_touch, ical, -1);
291  if (inside >= 0 || (theTrack->GetCurrentStepNumber() == 1)) {
292  trkInfo->setIDonCaloSurface(
293  id, ical, inside, theTrack->GetDefinition()->GetPDGEncoding(), theTrack->GetMomentum().mag());
294  trkInfo->setCaloIDChecked(true);
295  if (!doFineCalo_)
296  trkInfo->setCrossedBoundary(theTrack);
297  lastTrackID_ = id;
298  if (theTrack->GetKineticEnergy() / CLHEP::MeV > eMin_)
299  trkInfo->putInHistory();
300 #ifdef EDM_ML_DEBUG
301  edm::LogVerbatim("CaloSim") << "CaloTrkProcessing: set ID on Calo " << ical << " surface (Inside " << inside
302  << ") to " << id << " of a Track with Kinetic Energy "
303  << theTrack->GetKineticEnergy() / CLHEP::MeV << " MeV";
304 #endif
305  }
306  }
307  }
308  }
309 }
310 
311 int CaloTrkProcessing::isItCalo(const G4VTouchable* touch, const std::vector<Detector>& detectors) {
312  int lastLevel = -1;
313  G4LogicalVolume* lv = nullptr;
314  for (unsigned int it = 0; it < detectors.size(); it++) {
315  if (lastLevel != detectors[it].level) {
316  lastLevel = detectors[it].level;
317  lv = detLV(touch, lastLevel);
318 #ifdef EDM_ML_DEBUG
319  std::string name1 = "Unknown";
320  if (lv != 0)
321  name1 = lv->GetName();
322  edm::LogVerbatim("CaloSim") << "CaloTrkProcessing: volume " << name1 << " at Level " << lastLevel;
323  int levels = detLevels(touch);
324  if (levels > 0) {
325  G4String name2[20];
326  int copyno2[20];
327  detectorLevel(touch, levels, copyno2, name2);
328  for (int i2 = 0; i2 < levels; i2++)
329  edm::LogVerbatim("CaloSim") << " " << i2 << " " << name2[i2] << " " << copyno2[i2];
330  }
331 #endif
332  }
333  bool ok = (lv == detectors[it].lv);
334  if (ok)
335  return it;
336  }
337  return -1;
338 }
339 
340 int CaloTrkProcessing::isItInside(const G4VTouchable* touch, int idcal, int idin) {
341  int lastLevel = -1;
342  G4LogicalVolume* lv = nullptr;
343  int id1, id2;
344  if (idcal < 0) {
345  id1 = 0;
346  id2 = static_cast<int>(detectors_.size());
347  } else {
348  id1 = idcal;
349  id2 = id1 + 1;
350  }
351  for (int it1 = id1; it1 < id2; it1++) {
352  if (idin < 0) {
353  for (unsigned int it2 = 0; it2 < detectors_[it1].fromDets.size(); it2++) {
354  if (lastLevel != detectors_[it1].fromLevels[it2]) {
355  lastLevel = detectors_[it1].fromLevels[it2];
356  lv = detLV(touch, lastLevel);
357 #ifdef EDM_ML_DEBUG
358  std::string name1 = "Unknown";
359  if (lv != 0)
360  name1 = lv->GetName();
361  edm::LogVerbatim("CaloSim") << "CaloTrkProcessing: volume " << name1 << " at Level " << lastLevel;
362  int levels = detLevels(touch);
363  if (levels > 0) {
364  G4String name2[20];
365  int copyno2[20];
366  detectorLevel(touch, levels, copyno2, name2);
367  for (int i2 = 0; i2 < levels; i2++)
368  edm::LogVerbatim("CaloSim") << " " << i2 << " " << name2[i2] << " " << copyno2[i2];
369  }
370 #endif
371  }
372  bool ok = (lv == detectors_[it1].fromDetL[it2]);
373  if (ok)
374  return it2;
375  }
376  } else {
377  lastLevel = detectors_[it1].fromLevels[idin];
378  lv = detLV(touch, lastLevel);
379 #ifdef EDM_ML_DEBUG
380  std::string name1 = "Unknown";
381  if (lv != 0)
382  name1 = lv->GetName();
383  edm::LogVerbatim("CaloSim") << "CaloTrkProcessing: volume " << name1 << " at Level " << lastLevel;
384  int levels = detLevels(touch);
385  if (levels > 0) {
386  G4String name2[20];
387  int copyno2[20];
388  detectorLevel(touch, levels, copyno2, name2);
389  for (int i2 = 0; i2 < levels; i2++)
390  edm::LogVerbatim("CaloSim") << " " << i2 << " " << name2[i2] << " " << copyno2[i2];
391  }
392 #endif
393  bool ok = (lv == detectors_[it1].fromDetL[idin]);
394  if (ok)
395  return idin;
396  }
397  }
398  return -1;
399 }
400 
401 int CaloTrkProcessing::detLevels(const G4VTouchable* touch) const {
402  //Return number of levels
403  if (touch)
404  return ((touch->GetHistoryDepth()) + 1);
405  else
406  return 0;
407 }
408 
409 G4LogicalVolume* CaloTrkProcessing::detLV(const G4VTouchable* touch, int currentlevel) const {
410  G4LogicalVolume* lv = nullptr;
411  if (touch) {
412  int level = ((touch->GetHistoryDepth()) + 1);
413  if (level > 0 && level >= currentlevel) {
414  int ii = level - currentlevel;
415  lv = touch->GetVolume(ii)->GetLogicalVolume();
416  return lv;
417  }
418  }
419  return lv;
420 }
421 
422 void CaloTrkProcessing::detectorLevel(const G4VTouchable* touch, int& level, int* copyno, G4String* name) const {
423  static const std::string unknown("Unknown");
424  //Get name and copy numbers
425  if (level > 0) {
426  for (int ii = 0; ii < level; ii++) {
427  int i = level - ii - 1;
428  G4VPhysicalVolume* pv = touch->GetVolume(i);
429  if (pv != nullptr)
430  name[ii] = pv->GetName();
431  else
432  name[ii] = unknown;
433  copyno[ii] = touch->GetReplicaNumber(i);
434  }
435  }
436 #ifdef EDM_ML_DEBUG
437  edm::LogVerbatim("CaloSimX") << "CaloTrkProcessing::detectorLevel "
438  << " with " << level << ":" << detLevels(touch) << " levels";
439  for (int ii = 0; ii < level; ii++)
440  edm::LogVerbatim("CaloSimX") << "[" << ii << "] " << name[ii] << ":" << copyno[ii];
441 #endif
442 }
void update(const BeginOfEvent *evt) override
This routine will be called when the appropriate signal arrives.
Log< level::Info, true > LogVerbatim
int getIDCaloVolume() const
bool crossedBoundary() const
std::vector< std::string > insideNames_
G4LogicalVolume * detLV(const G4VTouchable *, int) const
Log< level::Error, false > LogError
void setStartedInFineVolume(bool flag=true)
bool caloIDChecked() const
void detectorLevel(const G4VTouchable *, int &, int *, G4String *) const
int isItInside(const G4VTouchable *, int, int)
def detectors(dt=True, csc=True, me42=False, chambers=True, superlayers=False, layers=False)
std::vector< Detector > fineDetectors_
int detLevels(const G4VTouchable *) const
int getIDonCaloSurface() const
ii
Definition: cuy.py:589
CaloTrkProcessing(const std::string &aSDname, const CaloSimulationParameters &csps, const SensitiveDetectorCatalog &clg, bool testBeam, double eMin, bool putHistory, bool doFineCalo, double eMinFine, int addlevel, const std::vector< std::string > &fineNames, const std::vector< int > &fineLevels, const std::vector< int > &useFines, const SimTrackManager *)
int getIDLastVolume() const
int isItCalo(const G4VTouchable *, const std::vector< Detector > &)
~CaloTrkProcessing() override
bool startedInFineVolumeIsSet()
bool startedInFineVolume() const
void setCaloIDChecked(bool f)
void setIDonCaloSurface(int id, int ical, int last, int pdgID, double p)
void setCrossedBoundary(const G4Track *track)
std::vector< std::string > caloNames_
std::vector< Detector > detectors_