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