SLIC  6.1.1
Simulation for the Linear Collider (SLIC) - Geant4 simulation application
LcioHitsCollectionBuilder.cc
Go to the documentation of this file.
2 
3 // SLIC
4 #include "HitsCollectionUtil.hh"
5 #include "MCParticleManager.hh"
6 #include "SlicApplication.hh"
7 
8 // LCDD
9 #include "lcdd/util/StringUtil.hh"
10 
11 // Geant4
12 #include "G4SDManager.hh"
13 #include "G4SystemOfUnits.hh"
14 
15 // LCIO
16 #include "EVENT/MCParticle.h"
17 #include "IMPL/LCCollectionVec.h"
18 #include "IMPL/LCFlagImpl.h"
19 
20 // LCIO
21 using IMPL::SimCalorimeterHitImpl;
22 using IMPL::SimTrackerHitImpl;
23 using IMPL::LCEventImpl;
24 using IMPL::LCFlagImpl;
25 using IMPL::LCCollectionVec;
26 using EVENT::LCIO;
27 using EVENT::MCParticle;
28 
29 // STL
30 #include <iostream>
31 
32 using std::string;
33 
34 namespace slic {
35 
37  Module("LcioHitsCollectionBuilder"), m_storeMomentum(0) {
38 
39  // setup default coll flag for cal hits
41 
42  // Set store momentum bit for TrackerHits
43  m_trkCollFlag.setBit(LCIO::THBIT_MOMENTUM);
44 }
45 
47 }
48 
49 // create the hit collections
51 
52  // fetch HCIDs
53  std::vector<int> hcids = HitsCollectionUtil::getHCIDs();
54 
55  // fetch hit collection of event
56  G4HCofThisEvent* HCE = m_currentG4Event->GetHCofThisEvent();
57 
58  // HC table
59  G4HCtable* HCtbl = G4SDManager::GetSDMpointer()->GetHCtable();
60 
61  // HCID
62  G4int hcid;
63 
64  LCCollectionVec* collVec = 0;
65 
66  // Loop over HC IDs.
67  for (std::vector<int>::const_iterator iter = hcids.begin(); iter != hcids.end(); iter++) {
68 
69  hcid = *iter;
70 
71  // retrieve Sensitive Detector ptr
72  SensitiveDetector *SD = static_cast<SensitiveDetector*>(G4SDManager::GetSDMpointer()->FindSensitiveDetector(HCtbl->GetSDname(hcid)));
73 
74  // Get hits collections from SD.
75  for (int i = 0; i < SD->getNumberOfHitsCollections(); i++) {
76  if (SD->getHCID(i) == hcid) {
77  G4VHitsCollection* HC = HCE->GetHC(hcid);
78 
79  // add a LCCollectionVec if got a HC
80  if (HC) {
81  // set LCIO endcap bit in the flag (i.e. CHBIT_BARREL ) according to SDs setting
82  setEndcapFlag(SD);
83 
84  // create collection vector based on type of SD
85  collVec = createCollectionVec(HC, SD->getType());
86 
87  // Store the cellID description into the LCIO::cellIDEncoding parameter in the collection.
88  if (SD->getIdSpec()) {
89  std::string id = SD->getIdSpec()->getFieldDescription();
90  collVec->parameters().setValue(LCIO::CellIDEncoding, id);
91  }
92 
93  // Check for existing collection.
94  if (containsCollection(m_currentLCEvent, HC->GetName())) {
95  // Update existing collection.
96  // TODO: Check for matching id scheme and flags!
97  LCCollectionVec * collection = (LCCollectionVec*) m_currentLCEvent->getCollection(HC->GetName());
98  collection->insert(collection->begin(), collVec->begin(), collVec->end());
99  }
100  // No collection found.
101  else {
102  // Add new collection vector to LCEvent.
103  m_currentLCEvent->addCollection(collVec, HC->GetName());
104 
105 #ifdef SLIC_LOG
106  //log() << LOG::always << HC->GetName() << " has " << collVec->size() << " hits" << LOG::done;
107 #endif
108  }
109  }
110 
111  else {
112  G4Exception("LcioHitsCollectionBuilder::createHitCollections()", "", FatalException, "No collection found for Hits Collection ID");
113  }
114  }
115  }
116  }
117 }
118 
119 // create the CollectionVec (decides which overloaded subfunction to call)
120 IMPL::LCCollectionVec* LcioHitsCollectionBuilder::createCollectionVec(G4VHitsCollection* g4HC, SensitiveDetector::EType SDtype) {
121 
122  // vec to create
123  LCCollectionVec* collVec = 0;
124 
125  // cal hits
126  if (SDtype == SensitiveDetector::eCalorimeter) {
127  collVec = createCalorimeterCollectionVec(g4HC);
128  }
129  // tracker hits
130  else if (SDtype == SensitiveDetector::eTracker) {
131  collVec = createTrackerCollectionVec(g4HC);
132  }
133  // unknown type of hit
134  else {
135  G4Exception("", "", FatalException, "Unknown HC type.");
136  }
137 
138  return collVec;
139 }
140 
141 LCCollectionVec* LcioHitsCollectionBuilder::createTrackerCollectionVec(G4VHitsCollection* g4HC) {
142  // create Lcio tracker coll
143  LCCollectionVec* collVec = new LCCollectionVec(LCIO::SIMTRACKERHIT);
144 
145  // cast to G4 trk HC
146  TrackerHitsCollection* trkHits = dynamic_cast<TrackerHitsCollection*>(g4HC);
147 
148  // call overloaded save function for trk hits
149  saveHits(trkHits, collVec);
150 
151  // set trk flags
152  collVec->setFlag(m_trkCollFlag.getFlag());
153 
154  return collVec;
155 }
156 
157 LCCollectionVec* LcioHitsCollectionBuilder::createCalorimeterCollectionVec(G4VHitsCollection* g4HC) {
158  // create Lcio cal coll
159  LCCollectionVec* collVec = new LCCollectionVec(LCIO::SIMCALORIMETERHIT);
160 
161  // cast to G4 cal HC
162  CalorimeterHitsCollection* calHits = dynamic_cast<CalorimeterHitsCollection*>(g4HC);
163 
164  // call overloaded save function for cal hits
165  saveHits(calHits, collVec);
166 
167  // set cal flags
168  collVec->setFlag(m_calCollFlag.getFlag());
169 
170  return collVec;
171 }
172 
174  m_calCollFlag.setBit(LCIO::CHBIT_LONG);
175  m_calCollFlag.setBit(LCIO::CHBIT_ID1);
176 }
177 
178 void LcioHitsCollectionBuilder::setEndcapFlag(SensitiveDetector* g4sd) {
179  bool ec_flag = g4sd->getEndcapFlag();
180 
181  // set for cal
182  if (g4sd->getType() == SensitiveDetector::eCalorimeter) {
183  if (ec_flag) {
184  m_calCollFlag.unsetBit(LCIO::CHBIT_BARREL);
185  } else {
186  m_calCollFlag.setBit(LCIO::CHBIT_BARREL);
187  }
188  }
189  // set for trk
190  else if (g4sd->getType() == SensitiveDetector::eTracker) {
191  if (ec_flag) {
192  m_trkCollFlag.unsetBit(LCIO::THBIT_BARREL);
193  } else {
194  m_trkCollFlag.setBit(LCIO::THBIT_BARREL);
195  }
196  }
197 }
198 
199 // save cal hits
200 void LcioHitsCollectionBuilder::saveHits(CalorimeterHitsCollection* calHits, IMPL::LCCollectionVec* lcioColl) {
201  size_t s = calHits->GetSize();
202  for (size_t i = 0; i < s; i++) {
203  CalorimeterHit* calHit = static_cast<CalorimeterHit*>(calHits->GetHit(i));
204  lcioColl->push_back(createHit(calHit));
205  }
206 }
207 
208 // save trk hits
209 void LcioHitsCollectionBuilder::saveHits(TrackerHitsCollection* trkHits, IMPL::LCCollectionVec* lcioColl) {
210  size_t s = trkHits->GetSize();
211  for (size_t i = 0; i < s; i++) {
212  TrackerHit* trkHit = static_cast<TrackerHit*>(trkHits->GetHit(i));
213  lcioColl->push_back(createHit(trkHit));
214  }
215 }
216 
217 // create cal hit from G4
218 IMPL::SimCalorimeterHitImpl* LcioHitsCollectionBuilder::createHit(CalorimeterHit* calHit) {
219  SimCalorimeterHitImpl* simCalHit = new SimCalorimeterHitImpl();
220 
221  // set cellid from cal hit's id64
222  const Id64bit& id64 = calHit->getId64bit();
223  simCalHit->setCellID0(id64.getId0());
224  simCalHit->setCellID1(id64.getId1());
225 
226  // position
227  const G4ThreeVector hitPos = calHit->getPosition();
228  float pos[3] = { (float)hitPos.x(), (float)hitPos.y(), (float)hitPos.z() };
229  simCalHit->setPosition(pos);
230 
231  // copy Mcp contrib info; energy is also incremented by contrib addition
232  addParticleContributions(calHit, simCalHit);
233 
234  // compare edep of calHit with simHit when debugging
235 //#ifdef SLIC_DEBUG
236  const HitContributionList& contribs = calHit->getHitContributions();
237  double totE = 0;
238  for (HitContributionList::const_iterator iter = contribs.begin(); iter != contribs.end(); iter++) {
239  totE += (*iter).getEdep();
240  }
241 
242  // Set energy from total of individual contributions.
243  //simCalHit->setEnergy(totE/GeV);
244 
245  //std::cout << "set totE = " << totE/GeV << std::endl;
246  // sanity check so that new and old edeps must match
247  //if (abs( totE/GeV - simCalHit->getEnergy() ) > ( 0.001 * totE ) )
248  //{
249  // log() << LOG::debug << "g4 hit E: " << totE << LOG::done;
250  // log() << LOG::debug << "sim hit E: " << simCalHit->getEnergy() << LOG::done;
251  // G4Exception("", "", JustWarning, "LCIO simCalHit E != G4 CalHit E, within tolerance");
252  //}
253 //#endif
254 
255  return simCalHit;
256 }
257 
258 // create trk hit from G4
259 IMPL::SimTrackerHitImpl* LcioHitsCollectionBuilder::createHit(TrackerHit* trackerHit) {
260 
261  SimTrackerHitImpl* simTrackerHit = new SimTrackerHitImpl();
262 
263  // position in mm
264  const G4ThreeVector hitPos = trackerHit->getPosition();
265  double pos[3] = { hitPos.x(), hitPos.y(), hitPos.z() };
266  simTrackerHit->setPosition(pos);
267 
268  // momentum in GeV
269  const G4ThreeVector& momentum = trackerHit->getMomentum();
270  simTrackerHit->setMomentum(momentum.x() / GeV, momentum.y() / GeV, momentum.z() / GeV);
271 
272  // pathLength = distance between exit and entry points in mm
273  simTrackerHit->setPathLength(trackerHit->getLength());
274 
275  // dEdx in GeV (LCIO units)
276  float edep = trackerHit->getEdep();
277  simTrackerHit->setEDep(edep / GeV);
278 
279  // time in NS
280  float tEdep = trackerHit->getTdep();
281  simTrackerHit->setTime(tEdep);
282 
283  // Cell ID.
284  simTrackerHit->setCellID0(trackerHit->getId());
285 
286  // MCP using McpManager
287  MCParticle* mcp = MCParticleManager::instance()->findMCParticle(trackerHit->getTrackID());
288 
289  if (!mcp) {
290  log().error("No MCParticle found for trackID <" + StringUtil::toString(trackerHit->getTrackID()) + "> when processing SimTrackerHit");
291  } else {
292  simTrackerHit->setMCParticle(mcp);
293  }
294 
295  return simTrackerHit;
296 }
297 
298 // add an MCParticle hit contribution from G4 to LCIO
299 void LcioHitsCollectionBuilder::addParticleContributions(CalorimeterHit* g4CalHit, IMPL::SimCalorimeterHitImpl* simCalHit) {
300  // Create empty hit contrib list.
301  HitContributionList contribs;
302 
303  // Use aggregation of contribs by track ID if CHBIT_PDG is not set.
304  if (!m_calCollFlag.bitSet(LCIO::CHBIT_PDG)) {
305  // Pass a ref to contrib list, which will get filled.
306  combineMcpHitContribs(g4CalHit->getHitContributions(), contribs);
307  }
308  // Otherwise, use the complete list from the CalHit.
309  else {
310  contribs = g4CalHit->getHitContributions();
311  }
312 
313  // Add contribs to the LCIO MCParticle.
314  size_t ncontrib = 0;
315  for (HitContributionList::const_iterator iter = contribs.begin(); iter != contribs.end(); iter++) {
316  // This contrib.
317  const HitContribution& contrib = (*iter);
318 
319  // Get the MCParticle pointer from the track ID.
320  MCParticle* contribMcp = MCParticleManager::instance()->findMCParticle(contrib.getTrackID());
321 
322  if (contribMcp != 0) {
323  // Add the MCParticle contribution to the hit.
324  simCalHit->addMCParticleContribution(contribMcp, (float) (contrib.getEdep() / GeV), (float) (contrib.getGlobalTime()), contrib.getPDGID(), const_cast<float*>(contrib.getPosition()));
325  ++ncontrib;
326  }
327  // Problem! Contributing particle is missing from MCParticle list.
328 #ifdef SLIC_LOG
329  else
330  {
331  log() << LOG::error << "No MCParticle from track ID <" << contrib.getTrackID() << "> when processing SimCalorimeterHit" << LOG::endl;
332  }
333 #endif
334  }
335 
336 #ifdef SLIC_LOG
337  if ( ncontrib == 0 ) {
338  log().error("No hit contributions for CalorimeterHit.");
339  }
340 #endif
341 }
342 
343 void LcioHitsCollectionBuilder::combineMcpHitContribs(const HitContributionList& longContrib, HitContributionList& combinedContrib) {
344  combinedContrib.clear();
345 
346  // iterate over long list (one entry for every hit)
347  for (HitContributionList::const_iterator iter = longContrib.begin(); iter != longContrib.end(); iter++) {
348  int trkId = (*iter).getTrackID();
349 
350  //log().debug("Combining hits on trk_id: " + StringUtil::toString( trk_id ) );
351 
352  // old track id in new combined list?
353  HitContribution* trk_contrib = 0;
354  if ((trk_contrib = findHitContribution((*iter).getTrackID(), combinedContrib))) {
355  // Add to the energy deposition.
356  trk_contrib->incrEdep((*iter).getEdep());
357 
358  // Set the minimum time.
359  trk_contrib->setMinTime((*iter).getGlobalTime());
360  }
361  // no existing contrib
362  else {
363  // Create a new contribution.
364  combinedContrib.push_back(HitContribution(trkId, (*iter).getEdep(), (*iter).getPDGID(), (*iter).getGlobalTime()));
365  }
366  }
367 }
368 
369 HitContribution* LcioHitsCollectionBuilder::findHitContribution(int trk_id, HitContributionList& contribs) {
370  HitContribution* c = 0;
371  for (HitContributionList::iterator iter = contribs.begin(); iter != contribs.end(); iter++) {
372  if ((*iter).getTrackID() == trk_id) {
373  c = &(*iter);
374  break;
375  }
376  }
377 
378  return c;
379 }
380 
381 EVENT::LCEvent* LcioHitsCollectionBuilder::createHitCollectionsFromEvent(const G4Event* g4evt, EVENT::LCEvent* lcevt) {
382  // set instance vars
383  m_currentG4Event = g4evt;
384  m_currentLCEvent = lcevt;
385 
386  // call real HC creation function
388 
389  // return evt pntr, which is same as input
390  return m_currentLCEvent;
391 }
392 
394  if (setting) {
395  m_calCollFlag.setBit(LCIO::CHBIT_LONG);
396  } else {
397  m_calCollFlag.unsetBit(LCIO::CHBIT_LONG);
398  }
399 
400 #ifdef SLIC_LOG
401  log().verbose("Set CHBIT_LONG: " + StringUtil::toString( setting ) );
402 #endif
403 }
404 
406  if (setting) {
407  m_calCollFlag.setBit(LCIO::CHBIT_PDG);
408  } else {
409  m_calCollFlag.setBit(LCIO::CHBIT_PDG);
410  }
411 
412 #ifdef SLIC_LOG
413  log().verbose("Set CHBIT_PDG: " + StringUtil::toString( setting ) );
414 #endif
415 }
416 
417 bool LcioHitsCollectionBuilder::containsCollection(EVENT::LCEvent* event, const string& collectionName) {
418  for (std::vector<string>::const_iterator iter = event->getCollectionNames()->begin(); iter != event->getCollectionNames()->end(); iter++) {
419  const string thisName = *iter;
420  if (thisName.compare(collectionName) == 0) {
421  return true;
422  }
423  }
424  return false;
425 }
426 } // namespace
static MCParticleManager * instance()
static std::vector< int > getHCIDs()
void combineMcpHitContribs(const HitContributionList &allContributions, HitContributionList &combinedContributions)
IMPL::LCCollectionVec * createCollectionVec(G4VHitsCollection *hitCollection, SensitiveDetector::EType sensitiveDetectorType)
HitContribution * findHitContribution(int trackID, HitContributionList &contributions)
void setEndcapFlag(SensitiveDetector *sensitiveDetector)
static bool containsCollection(EVENT::LCEvent *event, const std::string &name)
IMPL::LCCollectionVec * createTrackerCollectionVec(G4VHitsCollection *hitCollection)
EVENT::LCEvent * createHitCollectionsFromEvent(const G4Event *event, EVENT::LCEvent *lcioEvent)
void addParticleContributions(CalorimeterHit *calorimeterHit, IMPL::SimCalorimeterHitImpl *simCalorimeterHit)
IMPL::LCCollectionVec * createCalorimeterCollectionVec(G4VHitsCollection *hitCollection)
void saveHits(CalorimeterHitsCollection *calorimeterHits, IMPL::LCCollectionVec *collection)
IMPL::SimCalorimeterHitImpl * createHit(CalorimeterHit *calorimeterHit)
LogStream & verbose()
Definition: LogStream.hh:238
LogStream & error()
Definition: LogStream.hh:262
Base class for slic code modules that provides common functionality, such as logging to an output str...
Definition: Module.hh:25
LogStream & log()
Definition: Module.hh:99
@ error
Definition: LogStream.hh:33
@ endl
Definition: LogStream.hh:26