ATLAS Offline Software
Loading...
Searching...
No Matches
Example3DSystem5.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 Example3DSystem5 //
8// //
9// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> //
10// //
11// Initial version: June 2007 //
12// //
14
16#include "ui_example5controllerform.h"
17
19#include "TrkTrack/Track.h"
23//#include "CLHEP/Units/SystemOfUnits.h"
24#include "GaudiKernel/SystemOfUnits.h"
25
26
27#include <Inventor/nodes/SoSeparator.h>
28#include <Inventor/nodes/SoLineSet.h>
29#include <Inventor/nodes/SoVertexProperty.h>
30#include <Inventor/nodes/SoSwitch.h>
31
34
35//_____________________________________________________________________________________
37 : IVP13DSystemSimple("Ex3DSys5",
38 "This is an illustration of a very basic 3D system.\n"
39 "It transforms track information found in storegate"
40 " into 3D objects, displays track information and zooms to them upon selection, "
41 "and has a controller which allows the user to set a pt cut on tracks."
42 " It also has a multiple selection mode which can be used to display the combined invariant mass of tracks",
43 "Thomas.Kittelmann@cern.ch"), m_ptcut(0*Gaudi::Units::GeV), m_multiselection(0)
44{
45}
46
47//_____________________________________________________________________________________
49{
50 //Clear maps:
51 m_nodeToTrack.clear();
52 m_switchToPt.clear();
53
54 //1) Try to get the collection of (InDet) tracks from storegate:
55
56 //Sanity check:
57 if (!sg) {
58 message("Error: Got null storegate pointer");
59 return;
60 }
61
62 const TrackCollection *trackColl;
63 std::string trackname="Tracks";
64 StatusCode status = sg->retrieve(trackColl, trackname);
65 if (status != StatusCode::SUCCESS || !trackColl) {
66 message("Error: Could not retrieve track collection (used key="+QString(trackname.c_str())+")");
67 return;
68 }
69
70 //2) Add SoCooperativeSelection node under which we will put all the
71 //tracks. Register it and put its policy to TOGGLE (i.e. clicking
72 //adds or removes tracks from selection). In updateSelectionMode we
73 //will update its ACTIVE/INERT status depending on whether multiple
74 //selections are enabled: If ACTIVE, we get lists of selected nodes
75 //in the userChangedSelection(...) method, otherwise we get single
76 //nodes in the userPickedNode(...) method as always. We could also
77 //simply have changed its policy and gotten information about the
78 //clicks in a userSelectedSingleNode(...) method instead (the
79 //reason for the two available ways of doing this is that you might
80 //want to have several different selection nodes in your graph in
81 //the case where you have different types of physics objects
82 //displayed from the same system):
84 m_multiselection->policy = SoCooperativeSelection::TOGGLE;
85 registerSelectionNode(m_multiselection);//Always do this for SoCooperativeSelection nodes in your graph.
86 updateSelectionMode( true );//Since our controller starts with the single mode selected, we init like that also.
87
88 //2) Loop over the tracks and construct a relevant 3D object for each of them (a SoLineSet):
89
90 TrackCollection::const_iterator trackItr, trackItrEnd = trackColl->end();
91
92 for ( trackItr = trackColl->begin() ; trackItr != trackItrEnd; ++trackItr) {
93 const Trk::Track *track = (*trackItr);
94 const DataVector<const Trk::TrackParameters> *params = track->trackParameters();
95
96 //Just a sanity check (we need at least two points on the track):
97 if ( !params || params->size()<2 )
98 continue;
99
100 //The list of points on this track should be set in a so-called
101 //SoVertexProperty (which one realises by reading the
102 //documentation for SoLineSet at http://doc.coin3d.org/Coin/):
103
104 SoVertexProperty *vertices = new SoVertexProperty();
105
106 int iver(0);
108 for (it = params->begin();it!=itE;++it) {
109 vertices->vertex.set1Value(iver++,(*it)->position().x(),(*it)->position().y(),(*it)->position().z());
110 }
111
112 //Create a set of lines from these vertices:
113 SoLineSet * line = new SoLineSet();
114 line->numVertices = iver;
115 line->vertexProperty = vertices;
116
117 //We add the line to the tree below an SoSwitch. The latter is needed to turn the track on/off:
118 SoSwitch * sw = new SoSwitch();
119
120 // initial value of switch is based on current pt cut:
121 double pt = params->front()->pT();
122 sw->whichChild = pt > m_ptcut ? SO_SWITCH_ALL : SO_SWITCH_NONE;
123
124 // the user might change the pt cut later, so we need a list of the switches and the pT of their corresponding tracks:
125 m_switchToPt[sw] = pt;
126
127 sw->addChild(line);
128 m_multiselection->addChild(sw);
129
130 //Bookkeep which track this 3D object corresponds to (we will need this to display track info when the user clicks):
131 m_nodeToTrack[line] = track;
132
133 //To avoid GUI freeze-ups:
134 updateGUI();
135 }
136
137 //Add the selection node under the root:
138 root->addChild(m_multiselection);
139
140}
141
142//_____________________________________________________________________________________
143void Example3DSystem5::userPickedNode(SoNode* pickedNode, SoPath * /*pickedPath*/) {
144
145 //User clicked on "pickedNode". We should know which track this belongs to:
146 if (m_nodeToTrack.find(pickedNode)==m_nodeToTrack.end()) {
147 message("Error: Does not have track information for picked node");
148 return;
149 }
150
151 //Get parameters:
152 const DataVector<const Trk::TrackParameters> *params = m_nodeToTrack[pickedNode]->trackParameters();
153 if ( !params || params->empty() ) {
154 message("Error: Track has no trackparameters");
155 return;
156 }
157
158 //Show some interesting information (from the first trackparameter):
159 message("===> Track info:");
160 message(" |p| = "+QString::number(params->front()->momentum().mag()/Gaudi::Units::GeV)+" GeV");
161 message(" pT = "+QString::number(params->front()->pT()/Gaudi::Units::GeV)+" GeV");
162 message(" Q = "+QString::number(params->front()->charge()));
163 message(" eta = "+QString::number(params->front()->eta()));
164
165 //Zoom to track:
166 CamList cameras = getCameraList();
167 for (CamListItr itCam = cameras.begin(); itCam!=cameras.end(); ++itCam) {
169 }
170}
171
172//_____________________________________________________________________________________
173void Example3DSystem5::userChangedSelection(SoCooperativeSelection*, const QSet<SoNode*> & nodes, QSet<SoPath*>)
174{
175 //Calculate and print invariant mass.
176 if (nodes.count()<2)
177 return;
178
179 //Loop over the nodes, find their track pointers and add up their four-momentum (assuming massless particles):
180 Amg::Vector3D total3mom(0.0, 0.0, 0.0); //This is just a three vector
181 double totalenergy(0);//for the energy part of the lorentz vector
182
183 for (SoNode * node : nodes) {
184 //Track pointer:
185 if (m_nodeToTrack.find(node)==m_nodeToTrack.end()) {
186 message("Error: Does not have track information for all nodes");
187 return;
188 }
189 //Parameters:
190 const DataVector<const Trk::TrackParameters> *params = m_nodeToTrack[node]->trackParameters();
191 if ( !params || params->empty() ) {
192 message("Error: Track has no trackparameters");
193 return;
194 }
195 total3mom += params->front()->momentum();
196 totalenergy += params->front()->momentum().mag();
197 }
198 //Display result:
199 double invmasssq = totalenergy*totalenergy - total3mom.mag2();
200 QString invmass_str = invmasssq>=0.0 ? QString::number(sqrt(invmasssq)/Gaudi::Units::GeV) : "sqrt(-1)*"+QString::number(sqrt(-invmasssq)/Gaudi::Units::GeV);
201 message("Invariant mass of "+QString::number(nodes.count())+" selected tracks (massless particles): "+invmass_str+" GeV");
202}
203
204//_____________________________________________________________________________________
206{
207 QWidget * controller = new QWidget(0);
208 Ui::Example5ControllerForm ui;
209 ui.setupUi(controller);
210
211 m_ptcut = ui.doubleSpinBox_ptcut->value()*Gaudi::Units::GeV;
212 connect(ui.doubleSpinBox_ptcut,SIGNAL(valueChanged(double)),this,SLOT(ptCutChanged(double)));
213 connect(ui.radioButton_select_single,SIGNAL(toggled(bool)),this,SLOT(updateSelectionMode(bool)));
214
215 return controller;
216}
217
218//_____________________________________________________________________________________
220{
221 //Save this value since we need it when building next event:
222 m_ptcut = ptcut*Gaudi::Units::GeV;
223
224 //Update switches to display relevant tracks:
225 std::map<SoSwitch*,double>::iterator it, itE = m_switchToPt.end();
226 for ( it = m_switchToPt.begin(); it!=itE; ++it) {
227 it->first->whichChild = ( it->second>m_ptcut ? SO_SWITCH_ALL : SO_SWITCH_NONE );
228 }
229}
230
231//_____________________________________________________________________________________
233{
234 //If multiselection not created or if we dont need to change anything - abort:
235 if ( !m_multiselection || single == (m_multiselection->activePolicy.getValue()==SoCooperativeSelection::INERT) )
236 return;
237
238 //When we change selection mode we deselect everything - always a good idea to avoid hard to debug problems later:
239 deselectAll();
240
241 if (single)
243 else
245
246}
DataVector< Trk::Track > TrackCollection
This typedef represents a collection of Trk::Track objects.
Derived DataVector<T>.
Definition DataVector.h:795
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.
SoCooperativeSelection * m_multiselection
void ptCutChanged(double)
std::map< SoNode *, const Trk::Track * > m_nodeToTrack
void userChangedSelection(SoCooperativeSelection *, const QSet< SoNode * > &, QSet< SoPath * >)
std::map< SoSwitch *, double > m_switchToPt
void updateSelectionMode(bool single)
void buildEventSceneGraph(StoreGateSvc *sg, SoSeparator *root)
void userPickedNode(SoNode *pickedNode, SoPath *pickedPath)
QWidget * buildController()
IVP13DSystemSimple(const QString &name, const QString &information, const QString &contact_info)
std::set< SoCamera * > CamList
virtual void deselectAll(SoCooperativeSelection *exception_sel=0)
void registerSelectionNode(SoCooperativeSelection *)
CamList getCameraList()
CamList::iterator CamListItr
void message(const QString &) const
The Athena Transient Store API.
StatusCode retrieve(const T *&ptr) const
Retrieve the default object into a const T*.
static VP1CameraHelper * animatedZoomToSubTree(SoCamera *camera, SoGroup *sceneroot, SoNode *subtreeroot, double duration_in_secs=1.0, double clipVolPercent=100.0, double lastClipVolPercent=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)
Definition node.h:24
Eigen::Matrix< double, 3, 1 > Vector3D
=============================================================================