ATLAS Offline Software
Loading...
Searching...
No Matches
TrackCollHandle_TruthTracks.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
5
7// //
8// Implementation of class TrackCollHandle_TruthTracks //
9// //
10// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) //
11// Initial version: March 2008 //
12// //
14
23#include "VP1Base/IVP1System.h"
24#include "VP1Base/VP1Msg.h"
27
28#include "AtlasHepMC/GenEvent.h"
32
34
37
44#include "CLHEP/Units/PhysicalConstants.h"
45
46#include "CLHEP/Vector/LorentzVector.h"
47
48#include <QStringList>
49#include <QTime>
50#include <QElapsedTimer>
51
52
53//____________________________________________________________________
55public:
56 static double mag(const HepMC::FourVector& v) {
57 return std::sqrt( v.x()*v.x() + v.y()*v.y() + v.z()*v.z() );
58 }
59
61 bool loadHitLists(std::map<SimBarCode,SimHitList> & hitLists);
62 void loadGenParticles( std::map<SimBarCode,HepMC::ConstGenParticlePtr> & genParticles,
63 const HepMC::ConstGenVertexPtr& vtx );
64 bool loadGenParticles( std::map<SimBarCode,HepMC::ConstGenParticlePtr> & genParticles,
65 const QString& hepMcCollKey );
66
67 template <class collT>
68 void addHitCollections(std::map<SimBarCode,SimHitList> & hitLists);
69
70// static SimHitHandleBase * createHitHandle( const TrackRecord * h ) { return new SimHitHandle_TrackRecord(h); }
73 static SimHitHandleBase * createHitHandle( const SiHit& h ) { return new SimHitHandle_SiHit(&h); }
74
75 static QString nameHepMCAugmentedEnd;
76 static QString nameAugmentedOnly;
77
78 void createSecondaryHitLists(const SimBarCode& origSimBarCode,
79 const SimHitList& origHitList,
80 std::map<SimBarCode,SimHitList> & outlists,
81 int& newBarCode );
82 std::list<SimHitHandleBase*>::iterator closestCompatibleHandleItr(SimHitHandleBase* handle,
83 const std::list<SimHitHandleBase*>::iterator& itFirst,
84 std::list<SimHitHandleBase*>& handleList,
85 const double& massSquared) const;
86
87 std::map<SimBarCode::ExtBarCode,int> extBarCode2pdg;
88
91 if (!((updateGUICounter++)%750)) {
92 theclass->systemBase()->updateGUI();
93 }
94 }
95
96 bool cut_fromIROnly = false;
98 bool cut_excludeNeutrals = false;
99
100 bool displayAscObjs = false;
102
104
105 static const int maxPdgCode = 1000000000;
106
107};
108
110QString TrackCollHandle_TruthTracks::Imp::nameAugmentedOnly = "Sim hits/trk rec.";
111
112//____________________________________________________________________
114{
115 QStringList l;
116 VP1SGContentsHelper sgcont(sys);
117
118 QStringList mcevent_keys = sgcont.getKeys<McEventCollection>();
119 QStringList trackrecord_keys = sgcont.getKeys<TrackRecordCollection>();
120
121 QStringList keys_siliconhits, keys_trthits, keys_mdthits,
122 keys_rpchits, keys_tgchits, keys_cschits;
123
125 keys_siliconhits = sgcont.getKeys<SiHitCollection>();//"PixelHits" and "SCT_Hits"
127 keys_trthits = sgcont.getKeys<TRTUncompressedHitCollection>();//"TRTUncompressedHits"
128 if (false&&/*fixme!!*/VP1JobConfigInfo::hasMuonGeometry()) {
129 keys_mdthits = sgcont.getKeys<MDTSimHitCollection>();
130 keys_rpchits = sgcont.getKeys<RPCSimHitCollection>();
131 keys_tgchits = sgcont.getKeys<TGCSimHitCollection>();
132 keys_cschits = sgcont.getKeys<CSCSimHitCollection>();
133 }
134
135 bool extrainfo = ! ( keys_siliconhits.empty() && keys_trthits.empty()
136 && keys_mdthits.empty() && keys_rpchits.empty()
137 && keys_tgchits.empty() && keys_cschits.empty()
138 && trackrecord_keys.empty() );
139
140 if (extrainfo&&mcevent_keys.empty()) {
142 return l;
143 }
144
145 for (const QString& mcevent_key : mcevent_keys) {
146 l << mcevent_key;
147 if (extrainfo)
148 l << mcevent_key + Imp::nameHepMCAugmentedEnd;
149 }
150
151 //Fixme: REMOVE THIS (only for testing!!):
152 if (extrainfo)
154
155 return l;
156}
157
158//____________________________________________________________________
160 const QString& name)
161 : TrackCollHandleBase(cd,name,TrackType::TruthTrack), m_d(new Imp)
162{
163 setHelperClassName("TrackCollHandle_TruthTracks");
164 m_d->theclass = this;
165 m_d->updateGUICounter = 0;
166 m_d->cut_fromIROnly = true;
167 m_d->cut_excludeBarcodeZero = true;
168 m_d->cut_excludeNeutrals = true;
169 m_d->displayAscObjs = false;
170}
171
172//____________________________________________________________________
177
178//____________________________________________________________________
180{
181 connect(controller,SIGNAL(cutTruthFromIROnlyChanged(bool)),this,SLOT(setCutFromIROnly(bool)));
183
184 connect(controller,SIGNAL(cutExcludeBarcodeZeroChanged(bool)),this,SLOT(setCutExcludeBarcodeZero(bool)));
186
187 connect(controller,SIGNAL(cutTruthExcludeNeutralsChanged(bool)),this,SLOT(setCutExcludeNeutrals(bool)));
189
190 connect(controller,SIGNAL(showTruthAscObjsChanged(bool)),this,SLOT(setShowAscObjs(bool)));
191 setShowAscObjs(controller->showTruthAscObjs());
192}
193
194//____________________________________________________________________
196{
197 if (m_d->displayAscObjs==b)
198 return;
199 m_d->displayAscObjs=b;
200 messageVerbose("Associated objects shown flag changed to " + str(b));
201 m_d->updateVisibleAssociatedObjects();
202}
203
204//____________________________________________________________________
205template <class collT>
206void TrackCollHandle_TruthTracks::Imp::addHitCollections(std::map<SimBarCode,SimHitList> & hitLists)
207{
208 std::map<SimBarCode,SimHitList>::iterator itHitList;
209
210 VP1SGAccessHelper sgaccess(theclass->systemBase());
211
212 for (const QString& key : VP1SGContentsHelper(theclass->systemBase()).getKeys<collT>()) {
213 const collT * hitColl;
214 if (!sgaccess.retrieve(hitColl, key)) {
215 theclass->message("Error: Could not retrieve "+QString(typeid(collT).name())+" collection with key = "+key);
216 continue;
217 }
218 theclass->messageVerbose("Retrieved hit collection of type "+QString(typeid(collT).name())+" with key = "+key);
219 typename collT::const_iterator it, itE(hitColl->end());
220 int itot(0), iadded(0);
221 for (it=hitColl->begin();it!=itE;++it) {
222 ++itot;
224 SimHitHandleBase * handle = createHitHandle(*it);
225 handle->cacheMomentum();
226 theclass->fixPDGCode(handle);
227 SimBarCode trackID = handle->simBarCode();
228 if (trackID.pdgCode()>maxPdgCode) {
229 continue;
230 }
231 if (trackID.isNonUniqueSecondary()) {
232 double absmom = handle->momentum();
233 if (absmom>=0&&absmom<1.0*CLHEP::MeV) {//Fixme: Useful? Put it higher??
234 // if (VP1Msg::verbose())
235 // theclass->messageVerbose("Ignoring low momentum sim hit for non. unique secondary particle");
236 delete handle;
237 continue;
238 }
239 }
240 itHitList = hitLists.find(trackID);
241 if ( itHitList == hitLists.end() ) {
242 SimHitList l;
243 l.push_back(std::pair<double,SimHitHandleBase*>(handle->hitTime(),handle));
244 hitLists[trackID] = l;
245 } else {
246 itHitList->second.emplace_back(handle->hitTime(),handle);
247 }
248 ++iadded;
249 }
250 theclass->messageVerbose(" => used "+str(iadded)+" of "+str(itot)+" hits");
251 }
252
253}
254
255//____________________________________________________________________
256bool TrackCollHandle_TruthTracks::Imp::loadHitLists(std::map<SimBarCode,SimHitList> & hitLists)
257{
258 //Fixme: Return false if we do not find at least one collection
260
261 //Important that collections which inherently contains pdg codes (TRT) are loaded first!
264
267
268 if (VP1Msg::verbose())
269 theclass->messageVerbose( "Found " + str( hitLists.size() ) + " lists of sim. hits.");
270
271 //Time to assign all simhits with known pdg code a charge:
272 std::map<SimBarCode,SimHitList>::iterator it, itE(hitLists.end());
273 for (it = hitLists.begin(); it!=itE; ++it) {
274 if (it->first.unknownPdgCode())
275 continue;
276 bool ok;
277 double charge = VP1ParticleData::particleCharge(it->first.pdgCode(),ok);
278 if (!ok)
279 continue;
280 SimHitList::iterator itHit(it->second.begin()), itHitE(it->second.end());
281 for (;itHit!=itHitE;++itHit)
282 itHit->second->setCharge(charge);
284 }
285
286 //Fixme: Add hits from muon subsystems.
287
288 //Sort hitLists:
289 for (it = hitLists.begin(); it!=itE; ++it) {
290 sort(it->second.begin(),it->second.end());
292 }
293 return true;
294}
295
296
297//____________________________________________________________________
299{
300 int pdgfromsimhit =handle->actualPDGCodeFromSimHit();
301 bool isNonUniqueSecondary = handle->simBarCode().isNonUniqueSecondary();
302 SimBarCode::ExtBarCode extBarCode = handle->simBarCode().extBarCode();
303
304 if (pdgfromsimhit!=SimBarCode::unknownPDG) {
305 handle->setPDG(handle->actualPDGCodeFromSimHit());
306 std::map<SimBarCode::ExtBarCode,int>::const_iterator it = m_d->extBarCode2pdg.find(extBarCode);
307 if ( !isNonUniqueSecondary && it==m_d->extBarCode2pdg.end())
308 m_d->extBarCode2pdg[extBarCode] = pdgfromsimhit;
309 return;
310 }
311 if (isNonUniqueSecondary)
312 return;
313 std::map<SimBarCode::ExtBarCode,int>::const_iterator it = m_d->extBarCode2pdg.find(extBarCode);
314 if (it!=m_d->extBarCode2pdg.end()) {
315 handle->setPDG(it->second);
316 }
317}
318
319//____________________________________________________________________
320void TrackCollHandle_TruthTracks::Imp::loadGenParticles( std::map<SimBarCode,HepMC::ConstGenParticlePtr> & genParticles,
321 const HepMC::ConstGenVertexPtr& vtx )
322{
323 if (!vtx)
324 return;
325 for (const auto& p: *vtx){
326
327 if (!p)//fixme: message.
328 continue;
329 const HepMC::GenEvent* evt = p->parent_event();
330 if (!evt)
331 continue;//fixme: message.
332 //Fixme: If verbose: check barcode does not already exists!
333 SimBarCode simBarCode(HepMC::barcode(p),0/*evt->event_number()...fixme: correct??*/,p->pdg_id());
334 genParticles[simBarCode] = p;
335 if (!simBarCode.isNonUniqueSecondary())
336 extBarCode2pdg[simBarCode.extBarCode()] = p->pdg_id();
337
338 loadGenParticles(genParticles,p->end_vertex());
339 }
340}
341
342//____________________________________________________________________
343bool TrackCollHandle_TruthTracks::Imp::loadGenParticles( std::map<SimBarCode,HepMC::ConstGenParticlePtr> & genParticles,
344 const QString& hepMcCollKey )
345{
347 const McEventCollection* mcColl;
348 if (!VP1SGAccessHelper(theclass->systemBase()).retrieve(mcColl,hepMcCollKey)) {
349 theclass->message("Error: Could not retrieve "+QString(typeid(McEventCollection).name())+" collection with key = "+hepMcCollKey);
350 return false;//fixme message
351 }
352
353 McEventCollection::const_iterator itEvt(mcColl->begin()), itEvtEnd(mcColl->end());
354 if (itEvt==itEvtEnd)
355 return false;//fixme message
356
357 for (;itEvt!=itEvtEnd;++itEvt) {
358 //NB: Signal is always the first event in collection!
359 const HepMC::GenEvent * evt = *itEvt;
360 if (!evt)
361 continue;
362#ifdef HEPMC3
363 for(auto itVtx: evt->vertices()) loadGenParticles(genParticles,itVtx);
364#else
365 HepMC::GenEvent::vertex_const_iterator itVtx(evt->vertices_begin()), itVtxEnd(evt->vertices_end());
366 for(;itVtx!=itVtxEnd;++itVtx) {
367 loadGenParticles(genParticles,*itVtx);
368 }
369#endif
370 }
371
372 return true;
373}
374
375//____________________________________________________________________
377{
378 //Decode name to figure out if we need to load simhits/track records and which HepMC key to use.
379 bool augmentedonly = name()==Imp::nameAugmentedOnly;
380 bool augmented = augmentedonly || name().endsWith(Imp::nameHepMCAugmentedEnd);
381 QString hepmckey;
382 if (!augmentedonly) {
383 hepmckey = name();
384 if (augmented)
385 hepmckey.chop(Imp::nameHepMCAugmentedEnd.count());
386 }
387
388 //get genparticles (should be done BEFORE we load sim. hits., so the barCode2pdg map gets filled):
389 std::map<SimBarCode,HepMC::ConstGenParticlePtr> genParticles;
390 if (!hepmckey.isEmpty())
391 if (!m_d->loadGenParticles(genParticles,hepmckey))
392 return false;
393
394 //get sim hits and track records:
395 std::map<SimBarCode,SimHitList> hitLists;
396 if (augmented) {
397 if (!m_d->loadHitLists(hitLists))
398 return false;
399 messageVerbose("TrackCollHandle_TruthTracks "+name()
400 +": Found "+str(hitLists.size())+" truth particles from simhits");
401 }
402
403 //Finally we need to combine the info we thus found, and construct
404 //actual track handles:
405
406 //We do this by looping through the simhit list, and checking for
407 //genparticles with the same SimBarCode. Those gen particles we use
408 //in this way, we take out of the map (put to null), to indicate we
409 //already used them. In the final step we add genparticle-only
410 //handles for the remaining genparticle (unless they have production
411 //and decay vertices ultra-close to each other):
412
413 std::map<SimBarCode,HepMC::ConstGenParticlePtr>::iterator itGenPart, itGenPartEnd(genParticles.end());
414 std::map<SimBarCode,SimHitList>::iterator itHitList, itHitListEnd(hitLists.end()), itHitListTemp;
415
416 //First we attempt to sort secondaries with barcode=0 into new lists
417 //of hits that are likely to have come from the same particle.
418
419 int newBarCode(-1);
420 std::map<SimBarCode,SimHitList> secondaryHitLists;
421 messageVerbose("Sorting non-unique secondaries into lists of hits likely to originate from the same track.");
422 QElapsedTimer timer;timer.start();
423 for (itHitList = hitLists.begin();itHitList!=itHitListEnd;) {
424 if (itHitList->first.isNonUniqueSecondary()) {
425 m_d->createSecondaryHitLists(itHitList->first,itHitList->second,secondaryHitLists,newBarCode);
426 itHitListTemp = itHitList;
427 ++itHitList;
428 hitLists.erase(itHitListTemp);
429 } else {
430 ++itHitList;
431 }
432 }
433 messageVerbose("Finished sorting non-unique secondaries into lists. Time spent: "+str(timer.elapsed()*0.001)+" seconds");
434 std::map<SimBarCode,SimHitList>::iterator itSecondaryList,itSecondaryListEnd(secondaryHitLists.end());
435 for (itSecondaryList = secondaryHitLists.begin();itSecondaryList!=itSecondaryListEnd;++itSecondaryList)
436 hitLists[itSecondaryList->first] = itSecondaryList->second;//Fixme: Check that it does not already exist!
437
438 for (itHitList = hitLists.begin();itHitList!=itHitListEnd;++itHitList) {
439 if (itHitList->second.empty()) {
440 message("load WARNING: Ignoring empty hit list.");
441 continue;
442 }
443 itGenPart = genParticles.find(itHitList->first);
445 if (itGenPart!=itGenPartEnd) {
446 p = itGenPart->second;
447 itGenPart->second = 0;
448 }
449
450 m_d->possiblyUpdateGUI();
451
452 if (m_d->fixMomentumInfoInSimHits(p,itHitList->second))//Provide guesses for momentum in simhits that needs them (and deletes the rest).
453 addTrackHandle( new TrackHandle_TruthTrack( this, itHitList->first, itHitList->second, p ) );
454 }
455
456 const double minSpacialSeparation = 1.0e-3*CLHEP::mm;
457 const double minSepSq = minSpacialSeparation*minSpacialSeparation;
458 for (itGenPart=genParticles.begin();itGenPart!=itGenPartEnd;++itGenPart) {
459 HepMC::ConstGenParticlePtr p = itGenPart->second;
460 if (!p)
461 continue;
462 if (abs(p->pdg_id())>=Imp::maxPdgCode)//Internal particle... (fixme: find proper limit!!)
463 continue;
464 if (!p->production_vertex())
465 continue;
466 if (p->end_vertex()) {
467 double dx(p->end_vertex()->position().x()-p->production_vertex()->position().x());
468 double dy(p->end_vertex()->position().y()-p->production_vertex()->position().y());
469 double dz(p->end_vertex()->position().z()-p->production_vertex()->position().z());
470 if ( dx*dx+dy*dy+dz*dz < minSepSq )
471 continue;
472 }
473 m_d->possiblyUpdateGUI();
474 addTrackHandle( new TrackHandle_TruthTrack( this, itGenPart->first, SimHitList(), p ) );
475 }
476
477 //Maybe we need to show measurements, etc.:
478 m_d->updateVisibleAssociatedObjects();
479
480 return true;
481}
482
483//____________________________________________________________________
485{
486 if (!TrackCollHandleBase::cut(handle))
487 return false;
488
489 if (m_d->cut_excludeNeutrals && handle->hasCharge() && handle->charge()==0.0)
490 return false;
491
492 TrackHandle_TruthTrack * truthhandle = static_cast<TrackHandle_TruthTrack *>(handle);
493 if (m_d->cut_excludeBarcodeZero && truthhandle->hasBarCodeZero())
494 return false;
495
496 if (m_d->cut_fromIROnly && ! truthhandle->hasVertexAtIR(2.8*CLHEP::cm*2.8*CLHEP::cm,50*CLHEP::cm))
497 return false;
498
499 return true;
500}
501
502//____________________________________________________________________
504{
505 if (m_d->cut_fromIROnly == b)
506 return;
507 m_d->cut_fromIROnly = b;
508 if (b)
510 else
512}
513
514//____________________________________________________________________
516{
517 if (m_d->cut_excludeBarcodeZero==b)
518 return;
519 m_d->cut_excludeBarcodeZero=b;
520 if (b)
522 else
524}
525
526//____________________________________________________________________
528{
529 if (m_d->cut_excludeNeutrals==b)
530 return;
531 m_d->cut_excludeNeutrals=b;
532 if (b)
534 else
536}
537
538//____________________________________________________________________
540 const SimHitList& origHitList,
541 std::map<SimBarCode,SimHitList> & outlists,
542 int& newBarCode )
543{
544 if (!origSimBarCode.isNonUniqueSecondary()||newBarCode>=0) {
545 theclass->message("createSecondaryHitLists"
546 " ERROR: Unexpected input");
547 return;
548 }
549
550 unsigned ntothitinput = origHitList.size();
551 HepMcParticleLink::index_type evtIndex = origSimBarCode.evtIndex();
552 int pdgCode = origSimBarCode.pdgCode();
553
555 // Temporarily put the (time,handle) pairs from the vector into a list. //
557
558 SimHitList::const_iterator itOrig(origHitList.begin()),itOrigE(origHitList.end());
559 std::list<SimHitHandleBase*> handleList;
560 for(;itOrig!=itOrigE;++itOrig)
561 handleList.push_back(itOrig->second);
562
564 // Produce handle lists based on requirements of proximity, //
565 // decreasing momenta and causality. //
567 std::set<std::list<SimHitHandleBase*> > outHandleLists;
568
569 bool ok;
570 double mass = VP1ParticleData::particleMass(pdgCode,ok);
571 double massSquared( (ok&&mass>=0) ? mass*mass : -1);
572 while (!handleList.empty()) {
573 std::list<SimHitHandleBase*> list;
574 std::list<SimHitHandleBase*>::iterator it(handleList.begin()), itNext, itTemp;
575 //Take this handle from the list, and increment to next one:
576 SimHitHandleBase * handle = *it;
577 list.push_back(handle);
578 itTemp = it++;
579 handleList.erase(itTemp);
580 while ( true ) {
581 if (it==handleList.end())
582 break;//TEST
583 itNext = closestCompatibleHandleItr(handle,it,handleList,massSquared);
585 if (itNext == handleList.end())//Fixme: cache handleList.end()? Check erase invalidation!
586 break;
587 handle = *itNext;
588 list.push_back(handle);
589 it = itNext; ++it;
590 handleList.erase(itNext);
591 if (it == handleList.end())//Fixme: cache handleList.end()? Check erase invalidation!
592 break;
593 }
594 if (list.size()==1) {//5 is ok for trt, but probably not for silicon!
595 //We need at least two sim hits//FIXME: 5?
596 //Fixme: Make minimum number of hits depend on energy?
597// theclass->messageVerbose("Ignoring secondary with barCode 0, since it seems to be the only sim. hit. by this track.");//Fixme: We could do something with posStart/posEnd?//fixme: update text to reflect 5
598 //FIXME: use this!: delete *(list.begin());
599 } else {
600 outHandleLists.insert(list);
601 }
602 }
603
605 // Put handle lists in output handle lists, and assign unique new fake barcodes //
607
608 //We assign fake negative barcodes to
609 //secondaries, since negative barcodes are
610 //by convention reserved for vertices in
611 //the HepMC collection.
612
613 std::set<std::list<SimHitHandleBase*> >::iterator itOutList(outHandleLists.begin()), itOutListE(outHandleLists.end());
614 unsigned totused(0);
615 for (;itOutList!=itOutListE;++itOutList) {
616 const SimBarCode fakeBarCode(newBarCode--,evtIndex,pdgCode);
617 //Fixme: Update barcodes contained in simhithandles!!
618 const unsigned n = itOutList->size();
619 totused += n;
620 outlists[fakeBarCode] = SimHitList();
621 std::map<SimBarCode,SimHitList>::iterator itActualOutList = outlists.find(fakeBarCode);
622 itActualOutList->second.reserve(n);
623
624 std::list<SimHitHandleBase*>::const_iterator itHandle(itOutList->begin()),itHandleE(itOutList->end());
625 for (;itHandle!=itHandleE;++itHandle)
626 itActualOutList->second.emplace_back((*itHandle)->hitTime(),*itHandle);
627
628 //Should be ok already, but just to be safe: (fixme: don't do this?)
629 sort(itActualOutList->second.begin(),itActualOutList->second.end());
630 }
631
632 if (VP1Msg::verbose())
633 theclass->messageVerbose("Grouped "+str(ntothitinput)+" secondaries with pdgCode = "
634 +str(pdgCode)+" into "+str(outHandleLists.size())
635 +" tracks ("+str(ntothitinput-totused)+" went unused).");
636}
637
638
639//____________________________________________________________________
641 const std::list<SimHitHandleBase*>::iterator& itFirst,
642 std::list<SimHitHandleBase*>& handleList,
643 const double& massSquared) const {
644// if (itFirst==handleList.end())
645// return handleList.end();
646 const double mom = handle->momentum();
647 const double momSq = mom*mom;
648 const double betaSqMax = ( (mom < 0 || massSquared<=0 ? 1 : (momSq/(momSq+massSquared)) ));
649 const double speedSqMax = 4.0* CLHEP::c_squared * betaSqMax;//NB: The factor of 4 is a fudge factor, not really clear why needed!!! VP1 or GEANT4 bug!
650 // const double speedSqMax = 1.0001 * c_squared;/*fixme test*/
651// const double speedSqMax = 1.1*betaSqMax*300*300;/*fixme test*/
652// double testmsq=ParticleConstants::electronMassInMeV*MeV*ParticleConstants::electronMassInMeV;
653// const double speedSqMax = 1.0001 * c_squared * ( (mom < 0 || testmsq<=0 ? 1 : (momSq/(momSq+testmsq)) ));
654
655 unsigned ichecked(0);
656 unsigned maxchecked(50);
657
658 const double hitTime = handle->hitTime();
659 const Amg::Vector3D pos = handle->posStart();
660 double mom2, flightTime;
661 std::list<SimHitHandleBase*>::iterator it(itFirst), itE(handleList.end());
662 std::list<SimHitHandleBase*>::iterator itMinDist(itE);
663 double minDistSq(100*CLHEP::cm*100*CLHEP::cm);//Put to 1.0e99 for no hard limit.
664 if (mom>0)
665 if (mom<500*CLHEP::MeV) {
666 minDistSq = 20*CLHEP::cm*20*CLHEP::cm;
667 if (mom<100*CLHEP::MeV) {
668 minDistSq = 10*CLHEP::cm*10*CLHEP::cm;
669 if (mom<10*CLHEP::MeV)
670 minDistSq = 5*CLHEP::cm*5*CLHEP::cm;
671 }
672 }
673
674 for (;it!=itE;++it) {
675 ++ichecked;
676 mom2 = (*it)->momentum();
677 //Possible decreasing momentum requirement:
678 if (mom>=0&&mom2>=0) {
679 if (mom2>mom)
680 continue;
681 if (mom2<0.5*mom)//Guard against delta-rays-ish.
682 continue;
683 }
684
685 //Maximal separation requirement:
686 const double distSquared = ((*it)->posStart()-pos).mag2();
687
688 //Only investigate if it is the closest one:
689 if (distSquared>=minDistSq)
690 continue;
691
692 flightTime = (*it)->hitTime() - hitTime;
693 if (flightTime<=0||flightTime>100*CLHEP::ns) {
694 //Second hit comes before (shouldn't happen), or waaaay after the first hit.
695 if (flightTime<0)
696 theclass->message("closestCompatibleHandleItr WARNING: Should never happen. T1="+str(hitTime)+", T2="+str((*it)->hitTime()));
697 continue;
698 } else {
699 if (distSquared>flightTime*flightTime*speedSqMax)
700 continue;
701 }
702
703
704 //Check for coalignment of momenta:
705 double mindotproduct = -0.5;
706 if (mom>10.0*CLHEP::MeV) {
707 mindotproduct = -0.1;
708 if (mom>1000.0*CLHEP::MeV) {
709 mindotproduct = 0.5;
710 if (mom>10000.0*CLHEP::MeV) {
711 mindotproduct = 0.80;
712 }
713 }
714 }
715 if (mindotproduct>-1.0)
716 if (handle->momentumDirection().dot((*it)->momentumDirection())<mindotproduct)
717 continue;
718
719 // theclass->messageDebug("Test. Hit passed mom and causality.");
720
721 // //Possible minimal separation requirement: //FIXME: Turn this on if momentum is greater than...?
722 // if (mom2>=0&&massSquared>=0) {
723 // const double speedSqMin = 0.9999 * c_squared * momSq/(momSq+massSquared);
724 // const double minDistSquared = flightTimeSq*speedSqMin;
725 // if (distSquared<minDistSquared)
726 // continue;
727 // }
728 //Fixme: We might also make some requirement that distance should be less than e.g. 20cm??
729
730 //Hits are in principle compatible. Store it if it is also the closest:
731 // if (distSquared<minDistSq) {
732 minDistSq = distSquared;
733 itMinDist = it;
734
735 if (distSquared<15*15*CLHEP::cm*CLHEP::cm) {
736 //We already found a very good hit - should not look much further.
737 if (distSquared<5*5*CLHEP::cm*CLHEP::cm)
738 maxchecked = ichecked + 5;
739 else
740 maxchecked = ichecked + 15;
741 }
742
743 if (ichecked>maxchecked)//For performance reasons
744 break;
745 }
746 return itMinDist;
747}
748
749
750//____________________________________________________________________
752 //Returns false only if we prune down to zero information!
753
754 if (hitlist.empty())
755 return true;
756
757
758 static double unknown = -1.0e99;
759 double mom(unknown), time(unknown);
760 if (p) {
761 HepMC::ConstGenVertexPtr v = p->production_vertex();
762 if (v) {
763 mom = mag(p->momentum());
764 time = v->position().t()/CLHEP::c_light;
765 // theclass->messageDebug("fixMomentumInfoInSimHits genparticle "+str(mom/GeV)+" GeV, time = "+str(time/ns)+" ns");
766 }
767 }
768
769 //First thing we do is to quickly determine if we are in the special
770 //situation of all hits+genparticle missing momentum information, or
771 //all hits already including momentum information.
772
773 bool sawhitwithoutmominfo(false);
774 bool sawhitwithmominfo(mom!=unknown);
775 SimHitList::iterator it(hitlist.begin()), itE(hitlist.end());
776 for (;it!=itE;++it) {
777 const bool hasinfo = it->second->momentum()>=0.0;
778 if (hasinfo)
779 sawhitwithmominfo = true;
780 else
781 sawhitwithoutmominfo = true;
782 if (sawhitwithoutmominfo&&sawhitwithmominfo)
783 break;
784 }
785
786 if (!sawhitwithoutmominfo) {
787 //Already perfectly fine
788 return true;
789 }
790 if (!sawhitwithmominfo) {
791 //Worst case scenario. Discard all for now.
792 theclass->messageDebug("Discarding hitlist." );
793 SimHitList::iterator it(hitlist.begin()), itE(hitlist.end());
794 for (;it!=itE;++it)
795 delete it->second;
796 hitlist.clear();
797 return false;
798 }
799
800// {
801// if (time!=unknown)
802// theclass->messageDebug("BEFORE STARTS WITH GP time = "+str(time/ns)+" ns, mom = "+str(mom/GeV)+" GeV" );
803// SimHitList::iterator it(hitlist.begin()), itE(hitlist.end());
804// for (;it!=itE;++it) {
805// theclass->messageDebug("BEFORE time = "+str(it->second->hitTime()/ns)+" ns, mom = "+str(it->second->momentum()/GeV)+" GeV" );
806// }
807// }
808
809 //OK, we have some mom info, but not in all hits. Time to do some dirty work!
810
811 //First (if no genparticle), we check if the hitlist begins with
812 //hits without momentum information. If it does, we simply supply
813 //the first hit with an *extrapolated* guess!
814 if (mom==unknown) {
815 if (hitlist.at(0).second->momentum()<0.0) {
816 SimHitList::iterator it(hitlist.begin()), itE(hitlist.end());
817 for (;it!=itE;++it) {
818 if (it->second->momentum()>=0.0) {
819 hitlist.at(0).second->setFakeMomentum(it->second->momentum()*1.00001);//We make it slightly bigger. Just because.
820 break;
821 }
822 }
823 if (hitlist.at(0).second->momentum()<0.0) {
824 theclass->messageDebug("fixMomentumInfoInSimHits ERROR: Should not happen! (1)" );
825 //Fixme: clear hitlist.
826 return false;
827 }
828 }
829 mom = hitlist.at(0).second->momentum();
830 time = hitlist.at(0).second->hitTime();
831 }
832
833 //Then we check if the hitlist ends with hits without momentum
834 //information. If it does we simply supply the very last of the hits
835 //with an *extrapolated* guess! (FIXME: ASSUME 0.01% loss every CLHEP::ns or
836 //something else that is simple? Or even use the extrapolator to the
837 //last of those hits?)
838 unsigned ilast = hitlist.size()-1;
839 if (hitlist.at(ilast).second->momentum()<0.0) {
840 for (int iLastWithMom = ilast-1;iLastWithMom>=0;--iLastWithMom) {
841 if (hitlist.at(iLastWithMom).second->momentum()>0.0) {
842 hitlist.at(ilast).second->setFakeMomentum(hitlist.at(iLastWithMom).second->momentum()*0.99999);//Slight smaller. Just because.
843 break;
844 }
845 }
846 if (hitlist.at(ilast).second->momentum()<0.0) {
847 //Get it from the genparticle:
848 if (mom==unknown) {
849 theclass->messageDebug("fixMomentumInfoInSimHits ERROR: Should not happen! (2)" );
850 //Fixme: clear hitlist.
851 return false;
852 }
853 hitlist.at(ilast).second->setFakeMomentum(mom*0.99999);
854 }
855 }
856
857 //Every unknown momentum is now surrounded in time with momentum information. Time to interpolate!!
858 if (mom==unknown||time==unknown) {
859 //No genparticle. Initialise from first hit.
860 mom = hitlist.at(0).second->momentum();
861 time = hitlist.at(0).second->hitTime();
862 }
863
864 unsigned iNextWithMom(0);
865 for (unsigned i = 0; i < hitlist.size(); ++i) {
866 if (hitlist.at(i).second->momentum()>=0.0) {
867 mom = hitlist.at(i).second->momentum();
868 time = hitlist.at(i).second->hitTime();
869 continue;
870 }
871 if (iNextWithMom<=i) {
872 for (unsigned j = i+1;j<hitlist.size();++j) {
873 if (hitlist.at(j).second->momentum()>=0.0) {
874 iNextWithMom = j;
875 break;
876 }
877 }
878 if (iNextWithMom<=i) {
879 theclass->messageDebug("fixMomentumInfoInSimHits ERROR: Should not happen! (3)" );
880 //Fixme: clear hitlist.
881 return false;
882 }
883 }
884 //
885 double time2 = hitlist.at(iNextWithMom).second->hitTime();
886 double mom2 = hitlist.at(iNextWithMom).second->momentum();
887 double t = hitlist.at(i).second->hitTime();
888// theclass->message("ABOUT TO INTERPOLATE time="+str(time/ns)+", t="+str(t/ns)+", time2="+str(time2/ns)+", mom="+str(mom/GeV)+", mom2="+str(mom2/GeV));//fixme
889
890 if (t<=time||t>=time2||time2<=time)
891 theclass->message("SUSPICIOUS TIME");//fixme
892 if (mom2>=mom)
893 theclass->message("SUSPICIOUS MOM mom="+str(mom)+", mom2="+str(mom2));//fixme
894 mom += (mom2-mom)*(t-time)/(time2-time);
895 time = t;
896 hitlist.at(i).second->setFakeMomentum(mom);
897 }
898
899
900
901
902// //Now we loop through the list and see what we need to fix, if anything:
903
904// unsigned iNextWithMom(0);
905// for (unsigned i = 1/*already dealt with first*/; i < hitlist.size(); ++i) {
906// if (hitlist.at(i).second->momentum()>=0.0) {
907// mom = hitlist.at(i).second->momentum();
908// time = hitlist.at(i).second->hitTime();
909// } else {
910// if (iNextWithMom<=i) {
911// for (unsigned j = i+1;j<hitlist.size();++j) {
912// if (hitlist.at(j).second->momentum()>=0.0) {
913// iNextWithMom = j;
914// break;
915// }
916// }
917// if (iNextWithMom<=i) {
918// //Discard end of list!!
919// unsigned j = i;
920// for (;j<hitlist.size();++j) {
921// //TESTdelete hitlist.at(j).second;
922// }
923// hitlist.resize(j);
924// theclass->messageDebug("Discarded "+str(hitlist.size()-i)+" simhits due to missing momentum information at the start of the list");
925// return !hitlist.empty() || !p;
926// }
927// //Interpolate mom(time) values:
928// double time2 = hitlist.at(iNextWithMom).second->hitTime();
929// double mom2 = hitlist.at(iNextWithMom).second->momentum();
930// double t = hitlist.at(i).second->hitTime();
931// if (t<=time||t>=time2||time2<=time)
932// theclass->message("SUSPICIOUS TIME");//fixme
933// if (mom2>=mom)
934// theclass->message("SUSPICIOUS MOM");//fixme
935// mom = (t-time)/(time2-time)*(mom2-mom);
936// time = t;
937// hitlist.at(i).second->setFakeMomentum(mom);
938// }
939// }
940// }
941
942
943// // typedef std::vector<std::pair<double,SimHitHandleBase*> > SimHitList;//hitTime() to SimHitHandle's
944
945
946// {
947// SimHitList::iterator it(hitlist.begin()), itE(hitlist.end());
948// for (;it!=itE;++it) {
949// theclass->messageDebug("AFTER time = "+str(it->second->hitTime()/ns)+" ns, mom = "+str(it->second->momentum()/GeV)+" GeV" );
950// }
951// }
952
953 return true;
954
955}
956
957
958//If has momentum - Check light-speed consistency given positions and time.
959//mom should be decreasing
960
961//____________________________________________________________________
963{
964
965 theclass->message("updateVisibleAssociatedObjects");//fixme
966 theclass->largeChangesBegin();
967 theclass->trackHandleIterationBegin();
969 while ((handle=static_cast<TrackHandle_TruthTrack*>(theclass->getNextTrackHandle()))) {
971 }
972 theclass->largeChangesEnd();
973}
974
float hitTime(const AFP_SIDSimHit &hit)
Scalar mag() const
mag method
double charge(const T &p)
Definition AtlasPID.h:997
AtlasHitsVector< CSCSimHit > CSCSimHitCollection
AtlasHitsVector< MDTSimHit > MDTSimHitCollection
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
AtlasHitsVector< RPCSimHit > RPCSimHitCollection
AtlasHitsVector< SiHit > SiHitCollection
std::vector< std::pair< double, SimHitHandleBase * > > SimHitList
AtlasHitsVector< TGCSimHit > TGCSimHitCollection
AtlasHitsVector< TRTUncompressedHit > TRTUncompressedHitCollection
AtlasHitsVector< TrackRecord > TrackRecordCollection
Header file for AthHistogramAlgorithm.
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
This defines the McEventCollection, which is really just an ObjectVector of McEvent objectsFile: Gene...
Definition SiHit.h:19
std::pair< int, HepMcParticleLink::index_type > ExtBarCode
Definition SimBarCode.h:42
ExtBarCode extBarCode() const
Definition SimBarCode.h:43
static const int unknownPDG
Definition SimBarCode.h:25
bool isNonUniqueSecondary() const
HepMcParticleLink::index_type evtIndex() const
int pdgCode() const
virtual double hitTime() const =0
virtual Amg::Vector3D posStart() const =0
virtual Amg::Vector3D momentumDirection() const =0
virtual int actualPDGCodeFromSimHit() const
SimBarCode simBarCode() const
double momentum() const
const QString & name() const
virtual bool cut(TrackHandleBase *)
void addTrackHandle(TrackHandleBase *)
TrackCollHandleBase(TrackSysCommonData *, const QString &name, TrackType::Type)
static SimHitHandleBase * createHitHandle(const TRTUncompressedHit &h)
void addHitCollections(std::map< SimBarCode, SimHitList > &hitLists)
std::map< SimBarCode::ExtBarCode, int > extBarCode2pdg
bool fixMomentumInfoInSimHits(HepMC::ConstGenParticlePtr p, SimHitList &hitlist) const
bool loadHitLists(std::map< SimBarCode, SimHitList > &hitLists)
std::list< SimHitHandleBase * >::iterator closestCompatibleHandleItr(SimHitHandleBase *handle, const std::list< SimHitHandleBase * >::iterator &itFirst, std::list< SimHitHandleBase * > &handleList, const double &massSquared) const
static SimHitHandleBase * createHitHandle(const TrackRecord &h)
void createSecondaryHitLists(const SimBarCode &origSimBarCode, const SimHitList &origHitList, std::map< SimBarCode, SimHitList > &outlists, int &newBarCode)
static double mag(const HepMC::FourVector &v)
static SimHitHandleBase * createHitHandle(const SiHit &h)
void loadGenParticles(std::map< SimBarCode, HepMC::ConstGenParticlePtr > &genParticles, const HepMC::ConstGenVertexPtr &vtx)
static QStringList availableCollections(IVP1System *)
virtual bool cut(TrackHandleBase *)
TrackCollHandle_TruthTracks(TrackSysCommonData *, const QString &name)
virtual void setupSettingsFromControllerSpecific(TrackSystemController *)
void fixPDGCode(SimHitHandleBase *) const
double charge() const
bool hasCharge() const
bool hasVertexAtIR(const double &rmaxsq, const double &zmax) const
void messageVerbose(const QString &) const
void message(const QString &) const
void setHelperClassName(const QString &n)
static bool hasTRTGeometry()
static bool hasPixelGeometry()
static bool hasSCTGeometry()
static bool hasMuonGeometry()
static bool verbose()
Definition VP1Msg.h:31
static double particleMass(const int &pdgcode, bool &ok)
static double particleCharge(const int &pdgcode, bool &ok)
bool retrieve(const T *&, const QString &key) const
QStringList getKeys() const
int count(std::string s, const std::string &regx)
count how many occurances of a regx are in a string
Definition hcg.cxx:146
Eigen::Matrix< double, 3, 1 > Vector3D
int barcode(const T *p)
Definition Barcode.h:16
const GenParticle * ConstGenParticlePtr
Definition GenParticle.h:38
const HepMC::GenVertex * ConstGenVertexPtr
Definition GenVertex.h:60