ATLAS Offline Software
Loading...
Searching...
No Matches
VP1TrackSystem.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6// //
7// Implementation of class VP1TrackSystem //
8// //
9// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) //
10// Initial version: February 2008 //
11// //
13
23
33
39#include "VP1Base/VP1Msg.h"
40
41#include "VP1Utils/VP1DetInfo.h"
42
44
45#include <Inventor/nodes/SoSeparator.h>
46#include <Inventor/nodes/SoMaterial.h>
47#include <Inventor/nodes/SoSwitch.h>
48#include <Inventor/nodes/SoComplexity.h>
49#include <Inventor/nodes/SoLineSet.h>
50#include <Inventor/nodes/SoVertexProperty.h>
51#include "Inventor/nodes/SoDrawStyle.h"
52#include "Inventor/nodes/SoLightModel.h"
53#include <Inventor/nodes/SoCylinder.h>
54#include <Inventor/SoPath.h>
55#include <Inventor/nodes/SoFont.h>
56
58#include <sstream>
59
68
70//FIXME: ONLY HERE TEMPORARILY. WE NEED A HELPER CLASS!!
72#include "TrkTrack/Track.h"
81
82//____________________________________________________________________
84public:
90
91 InDetProjFlags::DetTypeFlags lastEmittedUsedIDProjections;
92 InDetProjFlags::DetTypeFlags currentUsedIDProjections() const;
93
94 SoSeparator * totmomsep = nullptr;
95 SoLineSet * totmomline = nullptr;
97 double totmass = 0.0;
98
99 QList<const Trk::PrepRawData*> selectedPRDs;
100
101 //Return value is number of track handles used for input (e.g. those without valid momentum info are ignored)
102 unsigned calcTotalMomentumOfSelectedHandles(Amg::Vector3D& totmom, Amg::Vector3D& totpos, double& mass) const;
103
104 template <class T>
105 QList<TrackCollHandleBase*> createSpecificCollections() {
106 QList<TrackCollHandleBase*> l;
107 for (const QString& name : T::availableCollections(theclass)) {
108 std::cout<<name.toStdString()<<std::endl;
109 T * col = new T(common,name);
110 col->init();
111 l << col;
112 }
113 return l;
114 }
115 QList<TrackCollHandleBase*> createCollections() {
116 QList<TrackCollHandleBase*> l;
117 l << createSpecificCollections<TrackCollHandle_TrkTrack>();
118 l << createSpecificCollections<TrackCollHandle_TrkSegment>();
119 // theclass->messageVerbose("Creating coll handle for TrackCollHandle_FatrasTruthTracks");
120 // l << createSpecificCollections<TrackCollHandle_FatrasTruthTracks>();
121 // theclass->messageVerbose("Creating coll handle for TrackCollHandle_TruthTracks");
122 l << createSpecificCollections<TrackCollHandle_TruthTracks>();
123 l << createSpecificCollections<TrackCollHandle_SimulationTracks>();
124 // theclass->messageVerbose("Creating coll handle for TrackCollHandle_TrackParticle");
125 l << createSpecificCollections<TrackCollHandle_TrackParticle>();
126 l << createSpecificCollections<TrackCollHandle_xAODTrackParticle>();
127 theclass->message("Creating coll handle for ACTS TrackContainers");
128 l << createSpecificCollections<TrackCollHandle_TrackContainer>();
129 return l;
130 }
131 std::vector<std::map<GeoPVConstLink, float> > chamberT0s;
132 std::map<const Trk::Track*, SoMaterial*> vertexMaterialForTrackBases;
133};
134
135//____________________________________________________________________
138 "System showing all track-like objects.",
139 "Edward.Moyse@cern.ch, Thomas.Kittelmann@cern.ch"), m_d(new Imp)
140{
141 m_d->theclass = this;
142 m_d->sel_tracks = nullptr;
143 m_d->common = nullptr;
144 m_d->totmomsep = nullptr;
145 m_d->totmomline = nullptr;
146 m_d->totmomgev = Amg::Vector3D(0,0,0);
147 m_d->ascObjSelManager = nullptr;
149 m_d->lastEmittedUsedIDProjections = InDetProjFlags::NoDet;
150 const unsigned n_chamber_t0_sources=2;
151 m_d->chamberT0s.resize(n_chamber_t0_sources);
152}
153
154//____________________________________________________________________
156{
157 delete m_d;
158}
159
160//____________________________________________________________________
162{
163 messageVerbose("systemcreate");
165 m_d->common->controller()->initTools();
166
167 connect(m_d->common->controller(),SIGNAL(shownTrackPartsChanged(TrackCommonFlags::TrackPartsFlags)),
169 connect(m_d->common->controller()->collWidget(),SIGNAL(visibleStdCollectionsChanged(const QList<VP1StdCollection*>&)),
172
173}
174
175//____________________________________________________________________
177{
178 messageVerbose("systemuncreate");
179 if (m_d->totmomsep) {
180 m_d->totmomsep->unref();
181 m_d->totmomsep=nullptr;
182 }
183 if (m_d->totmomline) {
184 m_d->totmomline->unref();
185 m_d->totmomline = nullptr;
186 }
187 delete m_d->common; m_d->common = nullptr;
188}
189
190//____________________________________________________________________
192{
193 messageVerbose("buildController start");
194 TrackSystemController * controller = new TrackSystemController(this);
195 m_d->common = new TrackSysCommonData(this,controller);//Fixme: Do this on-demand in buildeventscenegraph!!
196 controller->setCommonData(m_d->common);
197
198 connect(controller,SIGNAL(selectionModeChanged(TrackCommonFlags::SELECTIONMODE)),this,SLOT(updateSelectionMode()));
200 connect(controller,SIGNAL(showTotMomentumOnMultiTrackSelectionChanged(bool)),this,SLOT(updateShownTotMomentum()));
202
203 connect(controller,SIGNAL(refit()),this,SLOT(refit()));//temp.
204
205 controller->setNumberOfSelectedPRDsAndTracks(m_d->selectedPRDs.count(),0);
206
207 messageVerbose("buildController end");
208 return controller;
209}
210
211//____________________________________________________________________
213{
214 messageVerbose("buildEventSceneGraph start2");
215
216 // set complexity to a lower value, so that e.g. the straws are manageable
217 SoComplexity * complexity = new SoComplexity;
218 complexity->value.setValue(0.3f);//Fixme: Hardcoded here and elsewhere (fixme: Recheck all complexity values!)
219 root->addChild(complexity);
220 root->addChild(m_d->common->controller()->ascObjDrawStyle());
221 root->addChild(m_d->common->controller()->ascObjComplexity());//this will be inherited to the tracks
222 // (but giving no effect)
223
224 m_d->sel_tracks = new SoCooperativeSelection;
225 m_d->sel_tracks->activePolicy = SoCooperativeSelection::ACTIVE;
226 m_d->sel_tracks->ref();
227 registerSelectionNode(m_d->sel_tracks);
228 // m_d->sel_tracks->addChild(m_d->common->controller()->trackLightModel());
229 // m_d->sel_tracks->addChild(m_d->common->controller()->trackDrawStyle());
230
231 m_d->ascObjSelManager = new AscObjSelectionManager (root,this,m_d->common->controller());
232 m_d->common->setEventData(m_d->ascObjSelManager);//commondata assumes ownership of ascObjMgr.
233 m_d->common->trackLODManager()->setAttachNode(m_d->ascObjSelManager->getAscObjAttachSep());
234
235// reset last selected trk
236 m_d->common->setLastSelectedTrack(nullptr);
238
239 if (!m_d->common->m_textSep) {
240 // FIXME!
241 // std::cout<<"Making new Text sep"<<std::endl;
242 m_d->common->m_textSep = new SoSeparator;
243 m_d->common->m_textSep->setName("TextSep");
244 m_d->common->m_textSep->ref();
245 }
246 root->addChild(m_d->common->m_textSep);
247
248 // Fixme - what if font is missing?
249 SoFont *myFont = new SoFont;
250 myFont->name.setValue("Arial");
251 myFont->size.setValue(12.0);
252 m_d->common->m_textSep->addChild(myFont);
253
254 messageVerbose("createCollections start");
255
256 //Create collection list based on contents of event store, populate gui and apply states:
257 m_d->common->controller()->collWidget()->setCollections(m_d->createCollections());
258
259 //Add collections to event scenegraph:
260 for (VP1StdCollection* col : m_d->common->controller()->collWidget()->collections<VP1StdCollection>())
261 m_d->sel_tracks->addChild(col->collSwitch());
262
263 root->addChild(m_d->sel_tracks);
264 if (!m_d->totmomsep) {
265 m_d->totmomsep = new SoSeparator;
266 m_d->totmomsep->ref();
267 }
268 // m_d->totmomsep->addChild(m_d->common->controller()->trackDrawStyle());
269 root->addChild(m_d->totmomsep);
270
271 //
272 // Loading T0 measurements of muon chambers
273 //
274 // This will loop over all the T0 measurements found for muon chambers.
275 // And it will store them into the 'm_d->chamberT0s' vector.
276 // TODO! But do we still need it here?? Allow this to be configured?
277 //
278 std::vector<std::string> key;
279 key.emplace_back("MooreMuonChamberT0s");
280 key.emplace_back("MboyMuonChamberT0s");
281 assert(m_d->chamberT0s.size()==key.size());
282
283 for (unsigned int i=0; i<m_d->chamberT0s.size(); i++){
284 assert(i<key.size());
285 m_d->chamberT0s.at(i).clear();
286 const Muon::ChamberT0s* chamberT0s(nullptr);
287 const MuonGM::MuonDetectorManager * muonDetManager = VP1DetInfo::muonDetMgr();
288
289 bool isThere = sg->contains<Muon::ChamberT0s>(key[i]);
290 if (isThere && sg->retrieve(chamberT0s, key[i]).isFailure())
291 message("Problems loading ChamberT0s!");
292 else
293 if (!isThere) messageVerbose("No " +QString(key[i].c_str())+ " in event");
294
295 if (chamberT0s ){
296 messageVerbose("Found " +QString(key[i].c_str())+ " Chamber T0s");
297
298 std::vector< std::pair< Identifier, float > >::const_iterator it, itEnd=chamberT0s->getAllT0s().end();
299 for (it=chamberT0s->getAllT0s().begin(); it!=itEnd; ++it){
300
301 // chamber name
302 std::string stationName( muonDetManager->mdtIdHelper()->stationNameString (muonDetManager->mdtIdHelper()->stationName( it->first )) );
303 messageVerbose("station="+QString(stationName.c_str()));
304
305
306 if (muonDetManager->mdtIdHelper()->is_mdt(it->first)){
307 messageDebug("---> getting MDT T0s");
308
309 std::string techStr( muonDetManager->mdtIdHelper()->technologyString(muonDetManager->mdtIdHelper()->technology(it->first)) );
310 //int stName = muonDetManager->mdtIdHelper()->stationName(it->first);
311 float stEta = muonDetManager->mdtIdHelper()->stationEta(it->first);
312 float stPhi = muonDetManager->mdtIdHelper()->stationPhi(it->first);
313 int ml = muonDetManager->mdtIdHelper()->multilayer(it->first);
314 //std::cout << "MDT chamber Info - Identifier: " << it->first << " - technology: " <<techStr << " - stName: " << stName << " - stEta: " << stEta << " - stPhi: " << stPhi << " - ml: " << ml << std::endl;
315 messageDebug( "MDT chamber Info - technology: " + QString::fromStdString(techStr) + " - stName: " + QString::fromStdString(stationName) + " - stEta: " + QString::number(stEta) + " - stPhi: " + QString::number(stPhi) + " - ml: " + QString::number(ml) );
316
317 const MuonGM::MuonReadoutElement* muonDetEl = dynamic_cast<const MuonGM::MuonReadoutElement*>(muonDetManager->getMdtReadoutElement (it->first));
318 if (muonDetEl) m_d->chamberT0s[i][muonDetEl->getMaterialGeom()->getParent()]=it->second;
319 }
320 else if (muonDetManager->cscIdHelper()->is_csc(it->first)){
321 messageDebug("---> getting CSC T0s");
322
323 std::string techStr( muonDetManager->cscIdHelper()->technologyString(muonDetManager->cscIdHelper()->technology(it->first)) );
324 //int stName = muonDetManager->cscIdHelper()->stationName(it->first);
325 float stEta = muonDetManager->cscIdHelper()->stationEta(it->first);
326 float stPhi = muonDetManager->cscIdHelper()->stationPhi(it->first);
327 //std::cout << "CSC chamber Info - Identifier: " << it->first << " - technology: " <<techStr << " - stName: " << stationName << " - stEta: " << stEta << " - stPhi: " << stPhi << std::endl;
328 messageDebug( "MDT chamber Info - technology: " + QString::fromStdString(techStr) + " - stName: " + QString::fromStdString(stationName) + " - stEta: " + QString::number(stEta) + " - stPhi: " + QString::number(stPhi) );
329
330 const MuonGM::CscReadoutElement* muonDetEl = dynamic_cast<const MuonGM::CscReadoutElement*>(muonDetManager->getCscReadoutElement (it->first));
331 if (muonDetEl) m_d->chamberT0s[i][muonDetEl->getMaterialGeom()->getParent()]=it->second;
332 }
333 }
334 emit muonChamberT0sChanged(m_d->chamberT0s[i],i);
335 }
336 }
337
338 messageVerbose("buildEventSceneGraph end");
339}
340
341
342//____________________________________________________________________
344{
345 messageVerbose("systemErase begin");
346
347 m_d->common->controller()->collWidget()->clear();
348 messageVerbose("collWidget cleared");
349
350 if (m_d->common->controller()->trackObjBrowser()) m_d->common->controller()->trackObjBrowser()->clear();
351
352 m_d->common->clearEventData();
353 if (m_d->sel_tracks) {
354 unregisterSelectionNode(m_d->sel_tracks);
355 m_d->sel_tracks->unref();
356 m_d->sel_tracks=nullptr;
357 }
358
359 if (m_d->totmomsep)
360 m_d->totmomsep->removeAllChildren();
361
362 if (m_d->common->m_textSep) // FIXME!
363 m_d->common->m_textSep->removeAllChildren();
364
365 m_d->totmomgev = Amg::Vector3D(0,0,0);
366
367 if (VP1Msg::verbose()) {
370 +" instances of AssociatedObjectHandleBase alive at end of systemerase(). "
371 "(ignore this warning if there is more than one track system instance).");
374 +" instances of TrackHandleBase alive at end of systemerase(). "
375 "(ignore this warning if there is more than one track system instance).");
376 }
377
378 std::map<const Trk::Track*, SoMaterial*>::iterator itMat = m_d->vertexMaterialForTrackBases.begin();
379 std::map<const Trk::Track*, SoMaterial*>::iterator itMatEnd = m_d->vertexMaterialForTrackBases.end();
380 for(;itMat!=itMatEnd;++itMat) {
381 SoMaterial* curmat = itMat->second;
382 curmat->unref();
383 }
384 m_d->vertexMaterialForTrackBases.clear();
385 for (unsigned int i=0;i<m_d->chamberT0s.size();++i)
386 m_d->chamberT0s.at(i).clear();
387
388 messageVerbose("systemErase end");
389}
390
391//____________________________________________________________________
393{
394 //Version & base state:
395 VP1Serialise serialise(1/*version*/,this);
396 serialise.save(IVP13DSystemSimple::saveState());//Info from base class
397
398 // Actual state info:
400 serialise.save(m_d->common->controller()->saveSettings());
401 serialise.save(static_cast<VP1CollectionWidget*>(m_d->common->controller()->collWidget()));
402
403 serialise.disableUnsavedChecks();//We do the testing in the controller
404
405 return serialise.result();
406}
407
408//____________________________________________________________________
410{
411 //Version & base state:
412 VP1Deserialise state(ba,this);
413 if (state.version()==0) {
414 //We simply won't support .vp1 files from the old track system.
415 message("Warning: State data has obsolete format - ignoring!");
416 return;
417 }
418 if (state.version()!=1) {
419 message("Warning: State data has wrong format - ignoring!");
420 return;
421 }
422
424
426
427 m_d->common->controller()->restoreSettings(state.restoreByteArray());
428 state.restore(static_cast<VP1CollectionWidget*>(m_d->common->controller()->collWidget()));
429
430 state.disableUnrestoredChecks();//We do the testing in the controller
431}
432
433//____________________________________________________________________
434void VP1TrackSystem::emitTouchedMuonChambersChanged(const std::set<GeoPVConstLink>& s)
435{
436 messageVerbose("Emitting touchedMuonChambersChanged (with ntouchedchambers = "+QString::number(s.size())+")" );
438}
439
440//____________________________________________________________________
442{
444 if (trackhelper) {
445 //Fixme: For now we re-encode in a vector, to get old signal/slot signatures. We should change that!
446 // -> and remember not to put const in front of the so materials!!
447 std::vector< std::pair<const Trk::Track*, const SoMaterial*> > vistracks;
448 vistracks.reserve(trackhelper->visibleObjects().size());
449 std::map<const Trk::Track*,SoMaterial*>::const_iterator it, itE = trackhelper->visibleObjects().end();
450 for (it = trackhelper->visibleObjects().begin();it!=itE;++it)
451 vistracks.emplace_back(it->first,it->second);
452 messageVerbose("Emitting visibleTracksChanged (with nvistracks = "+QString::number(vistracks.size())+")" );
453 emit visibleTracksChanged(vistracks);
454 return;
455 }
457 if (segmenthelper) {
458 //Fixme: For now we re-encode in a vector, to get old signal/slot signatures. We should change that!
459 // -> and remember not to put const in front of the so materials!!
460 std::vector< std::pair<const Trk::Segment*, const SoMaterial*> > vissegments;
461 vissegments.reserve(segmenthelper->visibleObjects().size());
462 std::map<const Trk::Segment*,SoMaterial*>::const_iterator it, itE = segmenthelper->visibleObjects().end();
463 for (it = segmenthelper->visibleObjects().begin();it!=itE;++it)
464 vissegments.emplace_back(it->first,it->second);
465 messageVerbose("Emitting visibleSegmentsChanged (with nvissegments = "+QString::number(vissegments.size())+")" );
466 emit visibleSegmentsChanged(vissegments);
467 return;
468 }
469 message("unexpected signal received in visibleObjectsChanged slot");
470}
471
472//____________________________________________________________________
473void VP1TrackSystem::setApplicableIDProjections( InDetProjFlags::InDetProjPartsFlags pixel,
474 InDetProjFlags::InDetProjPartsFlags sct,
475 InDetProjFlags::InDetProjPartsFlags trt )
476{
477 messageVerbose("Signal received in setApplicableIDProjections slot");
479 if (!m_d->common)//After uncreate.
480 return;
481 bool changes(false);
482 if (m_d->common->indetProjHelper_Pixel()->parts() != pixel) {
483 m_d->common->indetProjHelper_Pixel()->setParts(pixel);
484 changes = true;
485 }
486 if (m_d->common->indetProjHelper_SCT()->parts() != sct) {
487 m_d->common->indetProjHelper_SCT()->setParts(sct);
488 changes = true;
489 }
490 if (m_d->common->indetProjHelper_TRT()->parts() != trt) {
491 m_d->common->indetProjHelper_TRT()->setParts(trt);
492 changes = true;
493 }
494
495 if (changes) {
496 messageVerbose(" => Flags changed.");
497 if (m_d->common->controller()) {
498 for( TrackCollHandleBase* collhandle : m_d->common->controller()->collWidget()->collections<TrackCollHandleBase>() )
499 collhandle->updateInDetProjectionsOfAllHandles();
500 }
501 } else {
502 messageVerbose(" => Flags unchanged.");
503 }
504}
505
506
507//____________________________________________________________________
509{
510 messageVerbose("updateSelectionMode start");
511 if (!m_d->sel_tracks||!m_d->ascObjSelManager) {
512 messageVerbose("updateSelectionMode Warning: Ignoring due to null pointers.");
513 return;
514 }
515 deselectAll();
516 m_d->ascObjSelManager->deselectAll();
517 m_d->selMode = m_d->common->controller()->selectionMode();//NB: Don't abort if unchanged (we call this method to init)
518 if (m_d->selMode==TrackCommonFlags::TRACKFIT) {
519 messageVerbose("updateSelectionMode => TRACKFIT");
520 m_d->sel_tracks->policy = SoCooperativeSelection::SINGLE;
521 m_d->ascObjSelManager->setMode(AscObjSelectionManager::SHIFT);
522 } else if (m_d->selMode==TrackCommonFlags::MULTITRACK) {
523 messageVerbose("updateSelectionMode => MULTITRACK");
524 m_d->sel_tracks->policy = SoCooperativeSelection::TOGGLE;
525 m_d->ascObjSelManager->setMode(AscObjSelectionManager::SINGLE);
526 } else {
528 message("updateSelectionMode ERROR: Unexpected selection mode flag");
529 messageVerbose("updateSelectionMode => SINGLEOBJECT");
530 m_d->sel_tracks->policy = SoCooperativeSelection::SINGLE;
531 m_d->ascObjSelManager->setMode(AscObjSelectionManager::SINGLE);
532 }
533 messageVerbose("updateSelectionMode end");
534}
535
536//____________________________________________________________________
537void VP1TrackSystem::userPickedNode(SoNode* pickedNode, SoPath* /*pickedPath*/)
538{
539 messageVerbose("userPickedNode");
540 if (pickedNode==m_d->totmomline) {
541 message("Total momentum of selected tracks [GeV]: p = "+str(m_d->totmomgev)+", m = "+str(m_d->totmass/CLHEP::GeV));
542 return;
543 }
544
545 message("Unknown object clicked");
546}
547
548//____________________________________________________________________
550{
551 messageVerbose("userSelectedSingleNode");
552 AssociatedObjectHandleBase* pickedHandle(nullptr);
553 if (!m_d->ascObjSelManager->handleUserSelectedSingleNode(sel,node,pickedPath,pickedHandle)) {
554 if (sel==m_d->sel_tracks) {
555 //Hack to get selections working when representing tracks with tubes:
556 if (node->getTypeId().isDerivedFrom(SoCylinder::getClassTypeId())) {
557 pickedPath->pop();
558 node=pickedPath->getTail();
559 }
560 TrackHandleBase * handle = m_d->common->trackHandle(node);
561 if (!handle) {
562 message("ERROR: Unknown track.");
563 return;
564 }
565 TrackHandle_TrkTrack * handle_trktrack = dynamic_cast<TrackHandle_TrkTrack *>(handle);
566 if (handle_trktrack&&m_d->selMode==TrackCommonFlags::TRACKFIT) {
567 messageVerbose("userSelectedSingleNode - find measurements for track fit");
568
569 QList<AssociatedObjectHandleBase*> trackmeas = handle_trktrack->getVisibleMeasurements();
570
571 if (trackmeas.empty()) message("In refit mode, but no visible measurements found so can't do anything. Perhaps they're not enabled in 'Details'?");
572 QList<AssociatedObjectHandleBase*> currentsel = m_d->ascObjSelManager->currentSelection();
573 //If at least one of the track measurements is unselected, we
574 //select them all. Otherwise we deselect them.
575 bool oneunselected(false);
576 for (AssociatedObjectHandleBase* meas : trackmeas) {
577 if (!currentsel.contains(meas)) {
578 oneunselected = true;
579 break;
580 }
581 }
582 QList<const Trk::PrepRawData*> prdSet;
583 if (oneunselected) {
584 messageVerbose("userSelectedSingleNode - selecting " +QString::number(trackmeas.size()) + " measurements.");
585 m_d->ascObjSelManager->ensureSelected(trackmeas);
586
587 // Add PRDs. Need to be careful as they might not exist.
588 for (AssociatedObjectHandleBase* meas : trackmeas) {
589 AscObj_TSOS* tsosAsc = dynamic_cast<AscObj_TSOS*>(meas);
590 if (tsosAsc && tsosAsc->rioOnTrack() && tsosAsc->rioOnTrack()->prepRawData()) prdSet.append(tsosAsc->rioOnTrack()->prepRawData());
591 }
592 } else {
593 messageVerbose("userSelectedSingleNode - deselecting " +QString::number(trackmeas.size()) + " measurements.");
594 m_d->ascObjSelManager->ensureDeselected(trackmeas);
595 }
596 setSelectedPRDs(prdSet); // FIXME - maybe I should append/remove from existing list?
597
598 m_d->sel_tracks->deselectAll();
599 } else {
600 if (m_d->common->controller()->printInfoOnSingleSelection()){
601 message(handle->clicked());
602 messageVerbose("Emitting newTrackSelected ");
603 m_d->common->setLastSelectedTrack(handle);
604 emit newTrackSelected(*handle);
605 m_d->common->controller()->setNumberOfSelectedPRDsAndTracks(m_d->selectedPRDs.count(),1); // FIXME - we can do this more cleanly?
606 }
607 }
608 } else {
609 message("ERROR: Unknown selection.");
610 return;
611 }
612 }
613 if (m_d->common->controller()->orientAndZoomOnSingleSelection()) {
614 if (!pickedHandle||!pickedHandle->initiatesOwnZooms()) {
615 std::set<SoCamera*> cameras = getCameraList();
616 std::set<SoCamera*>::iterator it,itE = cameras.end();
617 for (it=cameras.begin();it!=itE;++it)
618 VP1CameraHelper::animatedZoomToPath(*it,sel,pickedPath,2.0,1.0);
619 }
620 }
621}
622
623//____________________________________________________________________
625{
626 messageVerbose("userClickedOnBgd");
627 if (m_d->ascObjSelManager)
628 m_d->ascObjSelManager->userClickedOnBgd();
629 m_d->common->setLastSelectedTrack(nullptr);
630 QList<const Trk::PrepRawData*> prdSet;
631 setSelectedPRDs(prdSet ); // pass in empty collection. FIXME - this should depend on mode?
632}
633
634//____________________________________________________________________
636{
637 messageVerbose("userDeselectedSingleNode");
638}
639
640//____________________________________________________________________
642{
643 totmom = Amg::Vector3D(0,0,0);
644 totpos = Amg::Vector3D(0,0,0);
645 mass = 0;
646 if (!sel_tracks)
647 return 0;
648 unsigned nused(0);
649 double totenergy(0);
650 for (int i = 0; i < sel_tracks->getList()->getLength(); ++i) {
651 SoFullPath *fPath = static_cast<SoFullPath *>((*(sel_tracks->getList()))[i]);
652 TrackHandleBase * handle = common->trackHandle(fPath?fPath->getTail():nullptr);
653 if (!handle)
654 continue;
655 Amg::Vector3D mom = handle->momentum();
656 if (mom.mag2()==0.0)
657 continue;
658 //Fixme: Get actual position of perigee!!
659 std::optional<Amg::Vector3D> pos = handle->startPoint();
660 if (!pos)
661 continue;
662 ++nused;
663 totmom += mom;
664 totpos += *pos;
665 mass = handle->hasMass() ? handle->mass() : 0;
666 totenergy += sqrt(mom.mag2() + mass*mass);
667 }
668 if (nused>1) {
669 double msq = totenergy*totenergy - totmom.mag2();
670 mass = (msq<0?-1.0:1.0)*sqrt(fabs(msq));
671 totpos /= nused;
672 }
673 return nused;
674}
675
676
677//____________________________________________________________________
679{
680 messageVerbose("updateShownTotMomentum");
681 if (!m_d->common->controller()->showTotMomentumOnMultiTrackSelection()) {
682 //ensure detach:
683 messageVerbose(" => detach");
684 if (m_d->totmomsep&&m_d->totmomline&&m_d->totmomsep->findChild(m_d->totmomline)>-1)
685 m_d->totmomsep->removeChild(m_d->totmomline);
686 return;
687 }
688 Amg::Vector3D totmom;
689 Amg::Vector3D totpos;
690 double totmass;
691 unsigned nused = m_d->calcTotalMomentumOfSelectedHandles(totmom,totpos,totmass);
692 if (nused==0) {
693 //ensure detach:
694 messageVerbose(" => detach");
695 if (m_d->totmomsep&&m_d->totmomline&&m_d->totmomsep->findChild(m_d->totmomline)>-1)
696 m_d->totmomsep->removeChild(m_d->totmomline);
697 } else {
698 //ensure correct lineset:
699 Amg::Vector3D p2 = totpos+totmom.unit()*1*CLHEP::m;
700 if (!m_d->totmomline) {
701 m_d->totmomline = new SoLineSet;
702 m_d->totmomline->ref();
703 SoVertexProperty * vertices = new SoVertexProperty;
704 m_d->totmomline->vertexProperty = vertices;
705 m_d->totmomline->numVertices.set1Value(0,2);
706
707 }
708 SoVertexProperty * vertices = static_cast<SoVertexProperty*>(m_d->totmomline->vertexProperty.getValue());
709 vertices->vertex.set1Value(0,totpos.x(),totpos.y(),totpos.z());
710 vertices->vertex.set1Value(1,p2.x(),p2.y(),p2.z());
711 m_d->totmomgev = totmom / CLHEP::GeV;
712 m_d->totmass = totmass;
713 //ensure attach:
714 messageVerbose(" => attach");
715 if (m_d->totmomsep&&m_d->totmomline&&m_d->totmomsep->findChild(m_d->totmomline)<0)
716 m_d->totmomsep->addChild(m_d->totmomline);
717 return;
718 }
719
720}
721
722//____________________________________________________________________
723void VP1TrackSystem::userChangedSelection(SoCooperativeSelection* sel, const QSet<SoNode*>& /*nodes*/, QSet<SoPath*>/*paths*/)
724{
725 messageVerbose("userChangedSelection begin");
726 if (sel!=m_d->sel_tracks)
727 return;
728 messageVerbose("userChangedSelection => sel_tracks!!");
729
730
731 if (m_d->common->controller()->printTotMomentumOnMultiTrackSelection()) {
732 Amg::Vector3D totmom;
733 Amg::Vector3D totpos;
734 double totmass;
735 if (m_d->calcTotalMomentumOfSelectedHandles(totmom,totpos,totmass)>0) {
736 Amg::Vector3D totmomgev = totmom;
737 totmomgev /= CLHEP::GeV;
738 message("Total momentum [GeV] : "+str(totmomgev));//Fixme: Eta/phi/etc...
739 message("Total mass [GeV] : "+str(totmass/CLHEP::GeV));//Fixme: Eta/phi/etc...
740 }
741 }
742
744}
745
746
747
748
749//____________________________________________________________________
750InDetProjFlags::DetTypeFlags VP1TrackSystem::Imp::currentUsedIDProjections() const
751{
752 if (common->controller()->collWidget()->visibleStdCollections().isEmpty())
754 if (common->controller()->shownTrackParts() & TrackCommonFlags::InDetProjections)
757}
758
759//____________________________________________________________________
761{
762 InDetProjFlags::DetTypeFlags usedidprojs = m_d->currentUsedIDProjections();
763 if (m_d->lastEmittedUsedIDProjections == usedidprojs)
764 return;
765 m_d->lastEmittedUsedIDProjections = usedidprojs;
766 usedIDProjectionsChanged(usedidprojs);
767}
768
769//____________________________________________________________________
770void VP1TrackSystem::setSelectedPRDs(const QList<const Trk::PrepRawData*>& s)
771{
772 m_d->selectedPRDs = s;
773 if (m_d->common&&m_d->common->controller())
774 m_d->common->controller()->setNumberOfSelectedPRDsAndTracks(m_d->selectedPRDs.count(),0);
775}
776
777//____________________________________________________________________
779{
780 //FIXME: WE NEED A HELPER CLASS!!
781
782 if (!m_d->common||!m_d->common->controller()||!m_d->sel_tracks)//To check that we are actually refreshed
783 return;
784 messageVerbose("Refit requested with mode="+TrackCommonFlags::toString(m_d->common->controller()->fitterMode()));
785 const Trk::ITrackFitter* currentFitter = m_d->common->controller()->trackFitter();
786 if (!currentFitter) {
787 message("ERROR - Aborting refit as no fitter available.");
788 return;
789 }
790
791 QList<const Trk::Track*> fittedtracks;
792 switch (m_d->common->controller()->fitterMode()) {
793 case TrackCommonFlags::FROMPRDS: refitFromPRDs(currentFitter, fittedtracks);break;
794 case TrackCommonFlags::REFITSINGLETRACK: refitSingleTrack(currentFitter, fittedtracks);break;
795 case TrackCommonFlags::EXTENDTRACKWITHPRDS: message("Not yet implemented");break;
796 case TrackCommonFlags::COMBINETWOTRACKS: message("Not yet implemented");break;
797 }
798
799 if (fittedtracks.empty()) return;
800
801 TrackCollHandle_RefittedTracks * newtrackcoll =
803 m_d->common->controller()->nameOfNewlyFittedCollections(),
804 fittedtracks);
805 newtrackcoll->init();
806
807 QList<TrackCollHandleBase*> newcols;
808 newcols << newtrackcoll;
809
810 m_d->common->controller()->collWidget()->addCollections(newcols);
811
812 //Add new collections to event scenegraph and turn them on:
813 for (TrackCollHandleBase* col : newcols) {
814 m_d->sel_tracks->addChild(col->collSwitch());
815 col->setVisible(true);
816 }
817}
818
819void VP1TrackSystem::refitFromPRDs(const Trk::ITrackFitter* , QList<const Trk::Track*>& )
820{
821 // FIXME (or remove, since no one used this I think - EJWM)
822
823 // std::vector<const Trk::PrepRawData*> prdSet;
824 // prdSet.reserve(m_d->selectedPRDs.count());
825 // for (const Trk::PrepRawData* prd : m_d->selectedPRDs)
826 // prdSet.push_back(prd);
827 //
828 // if (prdSet.size()==0) {
829 // message("ERROR - Aborting refit as prdset is empty");
830 // return;
831 // }
832 //
833 // //Get direction from PRD locations
834 // unsigned i1(0),i2(prdSet.size()-1);
835 // const Amg::Vector3D* globPos0 = prdSet.at(i1)->detectorElement()->surface(prdSet.at(i1)->identify()).localToGlobal(prdSet.at(i1)->localPosition());
836 // const Amg::Vector3D* globPos1 = prdSet.at(i2)->detectorElement()->surface(prdSet.at(i2)->identify()).localToGlobal(prdSet.at(i2)->localPosition());
837 // Amg::Vector3D globMom = *globPos1 - *globPos0;
838 //
839 // // Loop and try several momenta
840 // double minMom = 3000.0;
841 // double maxMom = 23000.0;
842 // int numberIterations = 10;
843 // double stepSize = (maxMom-minMom)/static_cast<double>(numberIterations);
844 //
845 // const Trk::Track* bestTrack=0;
846 // bool outlier = m_d->common->controller()->fitterRemoveOutliers();
847 // Trk::ParticleHypothesis hypo = m_d->common->controller()->fitterParticleHypthesis();
848 // for ( double initialMom = minMom ; initialMom<=maxMom ; initialMom+=stepSize){
849 // globMom.setMag(initialMom);
850 // Trk::Perigee params(*globPos0, globMom, 1.0, Amg::Vector3D(0.0,0.0,0.0));
851 //
852 // const Trk::Track* fittedtrk = currentFitter->fit(prdSet, params, outlier,hypo );
853 //
854 // QString mom=QString::number(initialMom);
855 // if (!fittedtrk || !(fittedtrk->fitQuality() ) ) {
856 // message("Track fit failed for seed momentum: "+mom+", outlier="+QString::number(outlier));
857 // delete fittedtrk; //Discard tracks with no FQ (shouldn't ever happen, but need to test)
858 // } else {
859 // if (!bestTrack) {
860 // bestTrack=fittedtrk; // first valid track
861 // message("Track fit succeeded for seed momentum:"+mom+", outlier="+QString::number(outlier)+", and is new best track.");
862 // } else {
863 // // okay, have valid fit so now compare to previous track...
864 // const Trk::FitQuality* bestFQ = bestTrack->fitQuality();
865 // const Trk::FitQuality* fittedFQ = fittedtrk->fitQuality();
866 // if ( (fittedFQ->chiSquared()/fittedFQ->doubleNumberDoF())>(bestFQ->chiSquared()/bestFQ->doubleNumberDoF()) ){
867 // delete bestTrack; bestTrack=fittedtrk; // Replace old best track with this one
868 // message("Track fit succeeded for seed momentum:"+mom+", outlier="+QString::number(outlier)+", and is new best track.");
869 // } else {
870 // delete fittedtrk; // fit not as good as previous fit.
871 // message("Track fit succeeded for seed momentum:"+mom+", outlier="+QString::number(outlier)+", but is not best track.");
872 // }
873 // }
874 // }
875 //
876 // }
877 //
878 // if (!bestTrack) {
879 // message("All fits failed - no resulting track.");
880 // return;
881 // }
882 //
883 // delete globPos0; delete globPos1;
884 //
885 // fittedtracks << bestTrack;
886 //
887 // std::ostringstream s;
888 // s << *bestTrack;
889 // messageVerbose( QString(s.str().c_str()).split('\n'));
890}
891
892void VP1TrackSystem::refitSingleTrack(const Trk::ITrackFitter* currentFitter, QList<const Trk::Track*>& fittedtracks)
893{
894 const TrackHandleBase* handle = m_d->common->lastSelectedTrackHandle();
895 const TrackHandle_TrkTrack* trkhandle = dynamic_cast<const TrackHandle_TrkTrack*>(handle);
896 if (!trkhandle) return; // shouldn't ever happen
897 const Trk::Track* track =trkhandle->trkTrackPointer();
898 if (!track) return; // shouldn't ever happen
899
900 bool outlier = m_d->common->controller()->fitterRemoveOutliers();
901 Trk::ParticleHypothesis hypo = m_d->common->controller()->fitterParticleHypthesis();
902
903 const Trk::Track* fittedtrk =
904 currentFitter->fit(Gaudi::Hive::currentContext(), *track, outlier, hypo).release();
905
906 if (!fittedtrk) {
907 message("Fit failed - no resulting track.");
908 return;
909 }
910
911 fittedtracks << fittedtrk;
912
913 std::ostringstream s;
914 s << *fittedtrk;
915 messageVerbose( QString(s.str().c_str()).split('\n'));
916}
917
919{
920 return m_d->sel_tracks;
921}
922
924 messageVerbose("updateAlignment");
925
926 std::vector<double> values = m_d->common->controller()->alignmentShiftValue();
927 int level = m_d->common->controller()->alignmentShiftLevel();
928
929 messageVerbose("updateAlignment called with level="+QString::number(level));
930 assert (values.size()==6);
931 messageVerbose("0="+QString::number(values[0]));
932 messageVerbose("1="+QString::number(values[1]));
933 messageVerbose("2="+QString::number(values[2]));
934 messageVerbose("3="+QString::number(values[3]));
935 messageVerbose("4="+QString::number(values[4]));
936 messageVerbose("5="+QString::number(values[5]));
937
938 const Trk::TrkDetElementBase* detEl = nullptr;
939
940 // Try to find last selected TSOS
941 if (!m_d->ascObjSelManager) {
942 // this shouldn't happen!
943 message ("No selection manager - giving up.");
944 return;
945 }
946
947 QList<AssociatedObjectHandleBase*> currentsel = m_d->ascObjSelManager->currentSelection();
948 for (AssociatedObjectHandleBase* meas : currentsel) {
949 AscObj_TSOS* tsosAsc = dynamic_cast<AscObj_TSOS*>(meas);
950 if (tsosAsc){
951 if (tsosAsc->rioOnTrack() )
952 detEl= tsosAsc->rioOnTrack()->detectorElement ();
953 else if (tsosAsc->trackStateOnSurface()->trackParameters() )
955 }
956 if (detEl) break; // set, so can skip rest
957 }
958 if (!detEl){
959 messageVerbose("No det Element found");
960
961 return;// Abort!
962 } else {
963 const MdtIdHelper* mdtIdHelper = VP1DetInfo::mdtIDHelper();
964 std::string stationName(mdtIdHelper->stationNameString (mdtIdHelper->stationName(detEl->identify())));
965
966 messageVerbose("Found det Element from station="+QString(stationName.c_str()));
967 }
968
969 // redraw everything;
970 // FIXME
971}
972
973void VP1TrackSystem::tracksFromVertexChanged(QList< std::pair<const SoMaterial*, QList< const Trk::Track*> > >& vertexList){
974 messageVerbose("VP1TrackSystem::tracksFromVertexChanged. Got a list THIS big! "+QString::number(vertexList.size()));
975
976 // firstly, by default option to cut tracks by vertex is disabled, so enable:
977 m_d->common->controller()->vertexCutsAllowed(true);
978
979 // do something with vertexList!
980 for (const auto& it : vertexList){
981 SoMaterial* mat = const_cast<SoMaterial*>(it.first);
982 messageVerbose("Number of tracks associated with this vertex= "+QString::number(it.second.size()));
983
984
985 for (const Trk::Track* trk : it.second) {
986 m_d->vertexMaterialForTrackBases[trk]=mat;
987 mat->ref();
988// messageVerbose("Adding TrackHandleBase with pointer= "+QString::number((unsigned int)handle)+" for trk="+QString::number((unsigned int)trk));
989 }
990 }
991
992 // update track collections too.
993 for (TrackCollHandleBase* coll : m_d->common->controller()->collWidget()->collections<TrackCollHandleBase>())
994 if (coll->allowColourByVertex()) coll->updateMaterialOfAllHandles();
995}
996
998
999 const TrackHandle_TrkTrack* handle = dynamic_cast<const TrackHandle_TrkTrack*>(trk);
1000 if (handle) {
1001 std::map<const Trk::Track*, SoMaterial*>::const_iterator it = m_d->vertexMaterialForTrackBases.find(handle->trkTrackPointer());
1002
1003 if (it!=m_d->vertexMaterialForTrackBases.end()){
1004 return it->second;
1005 }
1006 }
1007 messageVerbose("VP1TrackSystem::materialFromVertex. No matching track handle for handle with pointer="+QString::number((uintptr_t)trk));
1008 return nullptr;
1009}
1010
1011
const Trk::RIO_OnTrack * rioOnTrack() const
const Trk::TrackStateOnSurface * trackStateOnSurface() const
Definition AscObj_TSOS.h:65
IVP13DSystemSimple(const QString &name, const QString &information, const QString &contact_info)
void unregisterSelectionNode(SoCooperativeSelection *)
virtual void deselectAll(SoCooperativeSelection *exception_sel=0)
void registerSelectionNode(SoCooperativeSelection *)
CamList getCameraList()
void messageVerbose(const QString &) const
virtual void restoreFromState(QByteArray)
void messageDebug(const QString &) const
const QString & name() const
State state() const
void message(const QString &) const
virtual QByteArray saveState()
int multilayer(const Identifier &id) const
Access to components of the ID.
The MuonDetectorManager stores the transient representation of the Muon Spectrometer geometry and pro...
const MdtReadoutElement * getMdtReadoutElement(const Identifier &id) const
access via extended identifier (requires unpacking)
const CscReadoutElement * getCscReadoutElement(const Identifier &id) const
access via extended identifier (requires unpacking)
Base class for the XxxReadoutElement, with Xxx = Mdt, Rpc, Tgc, Csc.
int stationEta(const Identifier &id) const
const std::string & technologyString(const int &index) const
bool is_csc(const Identifier &id) const
int stationPhi(const Identifier &id) const
int technology(const Identifier &id) const
int stationName(const Identifier &id) const
bool is_mdt(const Identifier &id) const
const std::string & stationNameString(const int &index) const
Stores links between chambers and the reconstructed T0.
Definition ChamberT0s.h:17
const std::vector< std::pair< Identifier, float > > & getAllT0s() const
Returns entire list of T0s.
Definition ChamberT0s.h:68
The Athena Transient Store API.
StatusCode retrieve(const T *&ptr) const
Retrieve the default object into a const T*.
bool contains(const TKEY &key) const
Look up a keyed object in TDS (compare also tryRetrieve) returns false if object not available in TDS...
virtual void init(VP1MaterialButtonBase *matBut=0)
static QString toString(const SELECTIONMODE &)
QList< AssociatedObjectHandleBase * > getVisibleMeasurements() const
bool hasMass() const
virtual std::optional< Amg::Vector3D > startPoint() const
returns 0 if can't find start point.
virtual double mass() const
virtual QStringList clicked() const =0
Called when user selects the node (stringlist is displayed in messagebox).
virtual Amg::Vector3D momentum() const
static int numberOfInstances()
const Trk::Track * trkTrackPointer() const
void setNumberOfSelectedPRDsAndTracks(unsigned prds, unsigned trks)
void setCommonData(TrackSysCommonData *)
set pointer to the common data
Provides the abstract interface for track fitting in the common ATLAS Tracking EDM.
virtual std::unique_ptr< Track > fit(const EventContext &ctx, const Track &track, const RunOutlierRemoval runOutlier=false, const ParticleHypothesis matEffects=Trk::nonInteracting) const =0
RE-FIT A TRACK.
virtual const Surface & associatedSurface() const override=0
Access to the Surface associated to the Parameters.
virtual const TrkDetElementBase * detectorElement() const =0
returns the detector element, assoicated with the PRD of this class
virtual const Trk::PrepRawData * prepRawData() const =0
returns the PrepRawData (also known as RIO) object to which this RIO_OnTrack is associated.
const TrkDetElementBase * associatedDetectorElement() const
return associated Detector Element
const TrackParameters * trackParameters() const
return ptr to trackparameters const overload
This is the base class for all tracking detector elements with read-out relevant information.
virtual Identifier identify() const =0
Identifier.
static VP1CameraHelper * animatedZoomToPath(SoCamera *camera, SoGroup *sceneroot, SoPath *path, double duration_in_secs=1.0, double clipVolPercent=100.0, double slack=1.0, const SbVec3f &lookat=SbVec3f(999, 999, 999), const SbVec3f &upvec=SbVec3f(999, 999, 999), bool varySpeed=true, bool forceCircular=false)
static const MdtIdHelper * mdtIDHelper()
static const MuonGM::MuonDetectorManager * muonDetMgr()
static bool verbose()
Definition VP1Msg.h:31
std::vector< std::map< GeoPVConstLink, float > > chamberT0s
std::map< const Trk::Track *, SoMaterial * > vertexMaterialForTrackBases
Amg::Vector3D totmomgev
InDetProjFlags::DetTypeFlags currentUsedIDProjections() const
unsigned calcTotalMomentumOfSelectedHandles(Amg::Vector3D &totmom, Amg::Vector3D &totpos, double &mass) const
QList< TrackCollHandleBase * > createCollections()
VP1TrackSystem * theclass
AscObjSelectionManager * ascObjSelManager
SoCooperativeSelection * sel_tracks
QList< TrackCollHandleBase * > createSpecificCollections()
QList< const Trk::PrepRawData * > selectedPRDs
SoSeparator * totmomsep
TrackCommonFlags::SELECTIONMODE selMode
InDetProjFlags::DetTypeFlags lastEmittedUsedIDProjections
void refitSingleTrack(const Trk::ITrackFitter *currentFitter, QList< const Trk::Track * > &fittedtracks)
void tracksFromVertexChanged(QList< std::pair< const SoMaterial *, QList< const Trk::Track * > > > &)
SoCooperativeSelection * selTracks()
Needed in TrackSystemController::objectBrowserClicked(QTreeWidgetItem * item, int)
void visibleTracksChanged(const std::vector< std::pair< const Trk::Track *, const SoMaterial * > > &)
void possiblyEmitUsedIDProjectionsChanged()
QWidget * buildController()
QByteArray saveState()
void touchedMuonChambersChanged(const std::set< GeoPVConstLink > &)
void updateAlignment()
Special mode to allow in VP1 alignment tests.
void visibleSegmentsChanged(const std::vector< std::pair< const Trk::Segment *, const SoMaterial * > > &)
void restoreFromState(QByteArray)
void setSelectedPRDs(const QList< const Trk::PrepRawData * > &)
virtual ~VP1TrackSystem()
void userDeselectedSingleNode(SoCooperativeSelection *, SoNode *, SoPath *)
void userPickedNode(SoNode *pickedNode, SoPath *pickedPath)
void systemcreate(StoreGateSvc *detstore)
void updateShownTotMomentum()
void setApplicableIDProjections(InDetProjFlags::InDetProjPartsFlags pixel, InDetProjFlags::InDetProjPartsFlags sct, InDetProjFlags::InDetProjPartsFlags trt)
void userSelectedSingleNode(SoCooperativeSelection *, SoNode *, SoPath *)
void muonChamberT0sChanged(const std::map< GeoPVConstLink, float > &, int)
The map is the dt0 per chamber, plus a label identifier, which by convention (!) is 0=Moore,...
void newTrackSelected(const TrackHandleBase &)
void emitTouchedMuonChambersChanged(const std::set< GeoPVConstLink > &)
void usedIDProjectionsChanged(InDetProjFlags::DetTypeFlags)
void userChangedSelection(SoCooperativeSelection *, const QSet< SoNode * > &, QSet< SoPath * >)
VP1TrackSystem(const QString &name="Tracks")
void buildEventSceneGraph(StoreGateSvc *sg, SoSeparator *root)
SoMaterial * materialFromVertex(const TrackHandleBase *trk) const
Returns the material for the vertex which knows this trackhandle (if known)
void refitFromPRDs(const Trk::ITrackFitter *currentFitter, QList< const Trk::Track * > &fittedtracks)
const std::map< const objectT *, SoMaterial * > & visibleObjects()
Definition node.h:24
Eigen::Matrix< double, 3, 1 > Vector3D
ParticleHypothesis
Enumeration for Particle hypothesis respecting the interaction with material.