ATLAS Offline Software
Loading...
Searching...
No Matches
VP1GeometrySystem.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6// //
7// Implementation of class VP1GeometrySystem //
8// //
9// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> //
10// //
11// Derived from V-atlas geometry system by Joe Boudreau. //
12// Origins of initial version dates back to ~1996, initial VP1 //
13// version by TK (May 2007) and almost entirely rewritten Oct 2007. //
14// Major refactoring october 2008. //
15// Updates: //
16// - Aug 2019, Riccardo.Maria.Bianchi@cern.ch //
17// //
19
22
31
33
38#include "VP1Base/VP1Msg.h"
39#include <Inventor/nodes/SoSeparator.h>
40#include <Inventor/nodes/SoSwitch.h>
41#include <Inventor/events/SoKeyboardEvent.h>
42#include <Inventor/nodes/SoPickStyle.h>
43#include <Inventor/nodes/SoEventCallback.h>
44#include <Inventor/nodes/SoCamera.h>
45#include <Inventor/nodes/SoCylinder.h>
46#include <Inventor/nodes/SoFont.h>
47
48#include "GeoModelKernel/GeoVolumeCursor.h"
49#include "GeoModelKernel/GeoPrintGraphAction.h"
51
52#ifndef BUILDVP1LIGHT
56#include "VP1Utils/VP1DetInfo.h"
64#endif
65
66#ifdef BUILDVP1LIGHT
67#include "GeoModelKernel/GeoBox.h"
68#include "GeoModelKernel/GeoCountVolAction.h"
69#include "GeoModelKernel/GeoAccessVolumeAction.h"
70#include "GeoModelDBManager/GMDBManager.h"
71#include "GeoRead/GReadIn.h"
72
73// #include "GeoModelExamples/ToyDetectorFactory.h"
74//#include "GeoModelExamples/SimplestToyDetectorFactory.h"
75
76#include <QStack>
77#include <QString>
78#include <QSettings>
79#endif // BUILDVP1LIGHT
80
81
82#include <QDebug>
83#include <QRegExp>
84#include <QByteArray>
85#include <QTimer>
86#include <QHeaderView>
87#include <QApplication>
88#include <QCheckBox>
89#include <QMessageBox>
90#include <QFileInfo>
91
92#include <map>
93#include <ranges>
94
96public:
97 Imp (VP1GeometrySystem*gs, const VP1GeoFlags::SubSystemFlags& ssf)
98 : theclass(gs), sceneroot(0),
103 #ifndef BUILDVP1LIGHT
104 ,pv2MuonStationInit(false)
105 #endif
106 {
107 const unsigned n_chamber_t0_sources=2;
108 for (unsigned i=0;i<n_chamber_t0_sources;++i)
109 chamberT0s.append(0);
110 }
111
113 SoSeparator * sceneroot;
114
115 std::map<SoSeparator*,VolumeHandle*> sonodesep2volhandle;
116 //Might be needed later: std::map<GeoPVConstLink,VolumeHandle*> pv2volhandle;
117
118 #ifdef BUILDVP1LIGHT
119 GeoModelExperiment* getGeometry();
120 GeoModelExperiment* createTheExperiment(GeoPhysVol* world = nullptr);
121 GeoModelExperiment* getGeometryFromLocalDB();
122 GeoModelExperiment* getDummyGeometry();
123 #endif
124
125
127 public:
128 // "geomodellocation" contains name of tree tops,
129 // or possible a bit more complex info in case of muons.
130 SubSystemInfo( QCheckBox* cb,const QRegExp& the_geomodeltreetopregexp, bool the_negatetreetopregexp,
131 const QRegExp& the_geomodelchildrenregexp, bool the_negatechildrenregexp, VP1GeoFlags::SubSystemFlag the_flag,
132 const std::string& the_matname,
133 const QRegExp& the_geomodelgrandchildrenregexp, bool the_negategrandchildrenregexp=false)
134 : isbuilt(false), checkbox(cb),
135 geomodeltreetopregexp(the_geomodeltreetopregexp),
136 geomodelchildrenregexp(the_geomodelchildrenregexp),
137 geomodelgrandchildrenregexp(the_geomodelgrandchildrenregexp),
138 negatetreetopregexp(the_negatetreetopregexp),
139 negatechildrenregexp(the_negatechildrenregexp),
140 negategrandchildrenregexp(the_negategrandchildrenregexp),
141 matname(the_matname), flag(the_flag), soswitch(0)
142 {
143
144 muonchambers=false;
145
146 // we set to True if the name contains any of the Muon flags here below
147 if (geomodeltreetopregexp.pattern()=="Muon") {
148 muonchambers = ( matname=="CSC"||matname=="TGC"||matname=="EndcapMdt"||matname=="MM"||matname=="sTGC"
149 ||matname=="BarrelInner"||matname=="BarrelMiddle"||matname=="BarrelOuter" );
150 }
151
152 }
153
154 //Info needed to define the system (along with the checkbox pointer in the map below):
157 QCheckBox* checkbox;
158
159 /* Regular Expressions for three levels of filtering: treetop, children, and grandchildren
160 *
161 * For example:
162 *
163 * - Muon --> treetop volume
164 * - ANON --> child volume
165 * - BAR_Toroid --> granchild volume
166 *
167 */
168 QRegExp geomodeltreetopregexp; //For picking the geomodel treetops
169 QRegExp geomodelchildrenregexp; //If instead of the treetops, this system consists of volumes below the treetop, this is non-empty.
170 QRegExp geomodelgrandchildrenregexp;//If instead of the treetops, this system consists of volumes below the child of a treetop, this is non-empty.
174
175
176 std::string matname; //if nonempty, use this from detvisattr instead of the top volname.
178
179
180 //Information needed to initialise the system:
181 class TreetopInfo { public:
183 PVConstLink pV;
184 HepGeom::Transform3D xf;// = av.getTransform();
185 std::string volname;
186 };
187 std::vector<TreetopInfo> treetopinfo;
188
189 //Switch associated with the system - it is initialised only if the system has info available:
190 SoSwitch * soswitch;
191
192 //For the use-case of automatically enabling/disabling specific muon chambers:
194 bool hasMuonChambers() const {
195 return muonchambers;
196 }
197
198 bool childrenRegExpNameCompatible(const std::string& volname) const {
199 return negatechildrenregexp!=geomodelchildrenregexp.exactMatch(volname.c_str());
200 }
201
202 bool grandchildrenRegExpNameCompatible(const std::string& volname) const {
203 if(VP1Msg::debug()){
204 std::cout << "volname: " << volname << " - regexpr: " << geomodelgrandchildrenregexp.pattern().toStdString() << std::endl;
205 std::cout << "negategrandchildrenregexp: " << negategrandchildrenregexp << std::endl;
206 }
207 return negategrandchildrenregexp!=geomodelgrandchildrenregexp.exactMatch(volname.c_str());
208 }
209
210 void dump() const {
211 std::cout<<" SubSystemInfo @ "<<this<<"\n"
212 <<(isbuilt?"Is built.\n":"Is not built.\n")
213 <<(muonchambers?"Has muon chambers.\n":"No muon chambers.\n");
214 std::cout<<"Contains following volhandles: [";
215 for (auto vol : vollist) std::cout<<&vol<<",";
216 std::cout<<"]"<<std::endl;
217 std::cout<<"Matname = "<<matname<<std::endl;
218 std::cout<<"Contains following TreetopInfo: [";
219 for (const auto& tt : treetopinfo) std::cout<<tt.volname<<",";
220 std::cout<<"]"<<std::endl;
221
222 }
223
224 };
225
226 QList<SubSystemInfo*> subsysInfoList;//We need to keep and ordered version also (since wildcards in regexp might match more than one subsystem info).
228 const QString& treetopregexp, const QString& childrenregexp="",
229 const std::string& matname="", bool negatetreetopregexp = false, bool negatechildrenregexp = false,
230 const QString& grandchildrenregexp="", bool negategrandchildrenregexp = false);
231
232 SubSystemInfo* chamberPVToMuonSubSystemInfo(const GeoPVConstLink& chamberPV);
233
242
243 VP1GeoFlags::SubSystemFlags initialSubSystemsTurnedOn;
248
249 //Helpers used for printouts://FIXME: To VolumeHandle!!
250 static double exclusiveMass(const PVConstLink& pv);
251 static double inclusiveMass(const PVConstLink& pv);
252 static double volume(const PVConstLink& pv);
253
254 //Basically for the zapping, and to ignore all clicks with ctrl/shift:
255 static void catchKbdState(void *userData, SoEventCallback *CB);
256 const SoKeyboardEvent *kbEvent;
257
258 //For automatic (de)iconisation of muon chambers:
259 std::map<PVConstLink,VolumeHandle*> muonchambers_pv2handles;
260 void updateTouchedMuonChamber(VolumeHandle * chamberhandle );
261 std::map<QObject*,std::set<GeoPVConstLink> > sender2ChamberList;
262
263 //Check all tubes in chamber and returns directions parallel with a tube which is closest to present camera direction (as well as the "up" directions of that tube):
264 std::pair<SbVec3f,SbVec3f> getClosestMuonDriftTubeDirections(const SbVec3f& cameraDirection, const SbVec3f& cameraUpDirection, VolumeHandle * chamberhandle );
265 std::pair<SbVec3f,SbVec3f> getClosestCSCOrTGCEdgeDirections(const SbVec3f& cameraDirection, VolumeHandle * chamberhandle );
267
268 //For letting other systems know what is the appropriate data projections:
270
272 void expandVisibleVolumesRecursively(VolumeHandle*,const QRegExp&,bool bymatname);
273 void iconifyVisibleVolumesRecursively(VolumeHandle*,const QRegExp&,bool bymatname);
274
275 SoSeparator* m_textSep;
276
277 #ifndef BUILDVP1LIGHT
278 std::map<GeoPVConstLink,const MuonGM::MuonStation*> pv2MuonStation;
282 QStringList stationInfo(const MuonGM::MuonStation*);
283 #endif
284
285 void expandAllChildren(VolumeHandle*, bool isPixel, bool brl, bool ecA, bool ecC);
287 void showITkPixelModules(VolumeHandle*, bool brl, bool ecA, bool ecC);
288 void showITkStripModules(VolumeHandle*, bool brl, bool ecA, bool ecC);
291
292 QMap<quint32,QByteArray> restoredTopvolstates;
293 void applyTopVolStates(const QMap<quint32,QByteArray>&, bool disablenotif = false);
294
295 // Helper function for emiting a signal to the PartSpect system
296 // This function creates path entry prefixes (=Detector Factory name in G4) and extra
297 // path entries (top level volumes, python envelopes) depending on the subsystem of the selected volume
298 void createPathExtras(const VolumeHandle*, QString&, QStack<QString>&);
299
300 QList<const std::map<GeoPVConstLink, float>*> chamberT0s;
301};
302
303//_____________________________________________________________________________________
304VP1GeometrySystem::VP1GeometrySystem( const VP1GeoFlags::SubSystemFlags& SubSystemsTurnedOn, const QString& name )
306 "This system displays the geometry as defined in the GeoModel tree.",
307 "Riccardo.Maria.Bianchi@cern.ch"),
308 m_d(new Imp(this,SubSystemsTurnedOn))
309{
310}
311
312
313//_____________________________________________________________________________________
315{
316
317 m_d->volumetreemodel->cleanup();
318 delete m_d->matVisAttributes; m_d->matVisAttributes = 0;
319 delete m_d->detVisAttributes; m_d->detVisAttributes = 0;
320 delete m_d->volVisAttributes; m_d->volVisAttributes = 0;
321
322 for (Imp::SubSystemInfo * subsys : m_d->subsysInfoList)
323 delete subsys;
324 m_d->subsysInfoList.clear();
325
326}
327
328//_____________________________________________________________________________________
330{
331 delete m_d;
332 m_d = 0;
333}
334
335//_____________________________________________________________________________________
338 m_d->controller->setGeometrySelectable(b);
339}
340
341//_____________________________________________________________________________________
344 m_d->controller->setZoomToVolumeOnClick(b);
345}
346
347//_____________________________________________________________________________________
349{
351 m_d->controller->setOrientViewToMuonChambersOnClick(b);
352}
353
354//_____________________________________________________________________________________
356{
358 if (m_d->controller->autoAdaptMuonChambersToEventData()!=b) {
359 m_d->controller->setAutoAdaptMuonChambersToEventData(b);
360 if (b)
362 }
363}
364
365//_____________________________________________________________________________________
367 const QString& treetopregexp, const QString& childrenregexp,
368 const std::string& matname, bool negatetreetopregexp, bool negatechildrenregexp,
369 const QString& grandchildrenregexp, bool negategrandchildrenregexp)
370{
371 theclass->messageDebug("VP1GeometrySystem::Imp::addSubSystem - flag: '" + QString(f) + "' - matName: '" + str(matname.c_str()) + "'." );
372
373 QCheckBox * cb = controller->subSystemCheckBox(f);
374 if (!cb) {
375 theclass->message("Error: Problems retrieving checkbox for subsystem "+str(f));
376 return;
377 }
378 subsysInfoList << new SubSystemInfo(cb,QRegExp(treetopregexp),negatetreetopregexp,
379 QRegExp(childrenregexp),negatechildrenregexp,f,matname,
380 QRegExp(grandchildrenregexp), negategrandchildrenregexp);
381 //FIXME: DELETE!!!
382}
383
384//_____________________________________________________________________________________
386{
387 message("VP1GeometrySystem::buildController");
388
389 m_d->controller = new GeoSysController(this);
390
391 m_d->phisectormanager = new PhiSectorManager(m_d->controller->phiSectionWidget(),this,this);
392
393
394 connect(m_d->controller,SIGNAL(showVolumeOutLinesChanged(bool)),this,SLOT(setShowVolumeOutLines(bool)));
395 setShowVolumeOutLines(m_d->controller->showVolumeOutLines());
396 connect(m_d->controller,SIGNAL(saveMaterialsToFile(QString,bool)),this,SLOT(saveMaterialsToFile(QString,bool)));
397 connect(m_d->controller,SIGNAL(loadMaterialsFromFile(QString)),this,SLOT(loadMaterialsFromFile(QString)));
398
399 connect(m_d->controller,SIGNAL(transparencyChanged(float)),this,SLOT(updateTransparency()));
402 connect (m_d->controller,SIGNAL(volumeResetRequested(VolumeHandle*)),
404 connect(m_d->controller,SIGNAL(adaptMuonChambersToEventData()),this,SLOT(adaptMuonChambersToEventData()));
405 connect(m_d->controller,SIGNAL(muonChamberAdaptionStyleChanged(VP1GeoFlags::MuonChamberAdaptionStyleFlags)),
406 this,SLOT(adaptMuonChambersStyleChanged()));
407 connect(m_d->controller,SIGNAL(autoExpandByVolumeOrMaterialName(bool,QString)),this,SLOT(autoExpandByVolumeOrMaterialName(bool,QString)));
408 connect(m_d->controller,SIGNAL(autoIconifyByVolumeOrMaterialName(bool,QString)),this,SLOT(autoIconifyByVolumeOrMaterialName(bool,QString)));
409 connect(m_d->controller,SIGNAL(actionOnAllNonStandardVolumes(bool)),this,SLOT(actionOnAllNonStandardVolumes(bool)));
410 connect(m_d->controller,SIGNAL(autoAdaptPixelsOrSCT(bool,bool,bool,bool,bool,bool)),this,SLOT(autoAdaptPixelsOrSCT(bool,bool,bool,bool,bool,bool)));
411 connect(m_d->controller,SIGNAL(autoAdaptMuonNSW(bool,bool,bool,bool,bool,bool)),this,SLOT(autoAdaptMuonNSW(bool, bool,bool,bool,bool,bool)));
412 connect(m_d->controller,SIGNAL(autoAdaptHGTD(bool,bool,bool,bool,bool,bool,bool,bool,bool,bool,bool,bool,bool,bool)),this,SLOT(autoAdaptHGTD(bool,bool,bool,bool,bool,bool,bool,bool,bool,bool,bool,bool,bool,bool)));
413 connect(m_d->controller,SIGNAL(resetSubSystems(VP1GeoFlags::SubSystemFlags)),this,SLOT(resetSubSystems(VP1GeoFlags::SubSystemFlags)));
414
415 connect(m_d->controller,SIGNAL(labelsChanged(int)),this,SLOT(setLabels(int)));
416 connect(m_d->controller,SIGNAL(labelPosOffsetChanged(QList<int>)),this,SLOT(setLabelPosOffsets(QList<int>)));
417 setLabels(m_d->controller->labels());
418
419
420 /* This is where we define the available different subsystems and their location in the geomodel tree.
421 *
422 * if the reg expr does not match any volume, the corresponding subsystem checkbox in the Geo GUI gets disabled.
423 *
424 * syntax: addSubSystem(VP1GeoFlags::SubSystemFlag&, // the associated system flag
425 QString& treetopregexp, // the regular expr for the top/root name of the main sub-detector system
426 QString& childrenregexp="", // the reg expr for the children of the main sub-detector
427 std::string& matname="", // a name we choose for displaying in VP1
428 bool negatetreetopregexp = false, // if we want to negate the top reg expr
429 bool negatechildrenregexp = false); // if we want to negate the children reg expr
430 const QString& grandchildrenregexp="", // the regex for granchildren of the main sub-detector
431 bool negategrandchildrenregexp = false // wheter we want to negate teh granchildren regex
432 */
433
435 m_d->addSubSystem( VP1GeoFlags::ITkPixel,"ITkPixel", "", "ITkPixel");
436 m_d->addSubSystem( VP1GeoFlags::ITkStrip,"ITkStrip", "", "ITkStrip");
437 } else {
438 m_d->addSubSystem( VP1GeoFlags::Pixel,"Pixel");
439 m_d->addSubSystem( VP1GeoFlags::SCT,"SCT");
440 m_d->addSubSystem( VP1GeoFlags::TRT,"TRT");
441 }
443 m_d->addSubSystem(VP1GeoFlags::HGTD, "HGTD", "", "HGTD");
444 }
445 m_d->addSubSystem( VP1GeoFlags::InDetServMat,"InDetServMat");
446 m_d->addSubSystem( VP1GeoFlags::LAr, ".*LAr.*");
447 m_d->addSubSystem( VP1GeoFlags::Tile,"Tile");
448 m_d->addSubSystem( VP1GeoFlags::CavernInfra,"CavernInfra");
449 m_d->addSubSystem( VP1GeoFlags::BeamPipe,"BeamPipe");
450 m_d->addSubSystem( VP1GeoFlags::LUCID,".*Lucid.*");
451 m_d->addSubSystem( VP1GeoFlags::ZDC,".*ZDC.*");
452 m_d->addSubSystem( VP1GeoFlags::ALFA,".*ALFA.*");
453 m_d->addSubSystem( VP1GeoFlags::AFP,".*AFP.*");
454 m_d->addSubSystem( VP1GeoFlags::ForwardRegion,".*ForwardRegion.*");
455
456 //The muon systems require special treatment, since we want to
457 //cherrypick below the treetop (this is the main reason for a lot
458 //of the ugly stuff in this class):
459 m_d->addSubSystem( VP1GeoFlags::MuonEndcapStationCSC,"Muon","CS.*","CSC");
460 m_d->addSubSystem( VP1GeoFlags::MuonEndcapStationTGC,"Muon","T(1|2|3|4).*","TGC");
461 m_d->addSubSystem( VP1GeoFlags::MuonEndcapStationMDT,"Muon","(EI|EM|EO|EE).*","EndcapMdt");
462 m_d->addSubSystem( VP1GeoFlags::MuonEndcapStationNSW,"Muon",".*ANON.*","MuonNSW",false, false, "NewSmallWheel.*");
463
464 m_d->addSubSystem( VP1GeoFlags::MuonBarrelStationInner,"Muon","(BI|BEE).*","BarrelInner");
465 m_d->addSubSystem( VP1GeoFlags::MuonBarrelStationMiddle,"Muon","BM.*","BarrelMiddle");
466 m_d->addSubSystem( VP1GeoFlags::MuonBarrelStationOuter,"Muon","BO.*","BarrelOuter");
467
468 //This last one is even more horrible. We want everything from the Muon treetop that is NOT included elsewhere:
469// m_d->addSubSystem( VP1GeoFlags::MuonToroidsEtc,"Muon","(CS|T1|T2|T3|T4|EI|EM|EO|EE|BI|BEE|BM|BO).*","Muon",false,true);
470
471 // Toroid
472 m_d->addSubSystem( VP1GeoFlags::BarrelToroid,"Muon",".*ANON.*","BarrelToroid", false, false, "BAR_Toroid.*");
473 m_d->addSubSystem( VP1GeoFlags::ToroidECA,"Muon",".*ANON.*","ToroidECA", false, false, "ECT_Toroids.*");
474// m_d->addSubSystem( VP1GeoFlags::ToroidECC,"Muon",".*ANON.*","ToroidECC", false, false, "ECT_Toroids");
475
476 // Muon Feet
477 m_d->addSubSystem( VP1GeoFlags::MuonFeet,"Muon",".*ANON.*","MuonFeet", false, false, "Feet.*");
478
479 // Muon shielding
480 m_d->addSubSystem( VP1GeoFlags::MuonShielding,"Muon",".*ANON.*","Shielding", false, false, "(JDSH|JTSH|JFSH).*");
481
482
483 // All muon stuff --> this will be linked to the "Services" checkbox in the GUI
484 // m_d->addSubSystem( VP1GeoFlags::MuonToroidsEtc,"Muon","(CS|T1|T2|T3|T4|EI|EM|EO|EE|BI|BEE|BM|BO).*","MuonEtc",false,true);
485 m_d->addSubSystem( VP1GeoFlags::MuonToroidsEtc,"Muon",".*(CS|T1|T2|T3|T4|EI|EM|EO|EE|BI|BEE|BM|BO).*","MuonEtc",false,true,"(ECT_Toroids|BAR_Toroid|Feet|NewSmallWheel|JDSH|JTSH|JFSH).*",true);
486
487 // m_d->addSubSystem( VP1GeoFlags::MuonToroidsEtc,"Muon","*.Feet.*","MuonEtc");
488
489 //This one MUST be added last. It will get slightly special treatment in various places!
490 m_d->addSubSystem( VP1GeoFlags::AllUnrecognisedVolumes,".*");
491
492
493 //Setup models/views for volume tree browser and zapped volumes list:
494 m_d->volumetreemodel = new VolumeTreeModel(m_d->controller->volumeTreeBrowser());
495 m_d->controller->volumeTreeBrowser()->header()->hide();
496 m_d->controller->volumeTreeBrowser()->uniformRowHeights();
497 m_d->controller->volumeTreeBrowser()->setModel(m_d->volumetreemodel);
498
499 return m_d->controller;
500}
501
502
503//_____________________________________________________________________________________
505{
506 m_d->ensureInitVisAttributes();
507}
508
509//_____________________________________________________________________________________
510void VP1GeometrySystem::Imp::catchKbdState(void *address, SoEventCallback *CB) {
511 VP1GeometrySystem::Imp *This=static_cast<VP1GeometrySystem::Imp*>(address);
512 if (This)
513 This->kbEvent = static_cast<const SoKeyboardEvent *>(CB->getEvent());
514}
515
516//_____________________________________________________________________________________
518{
519 m_d->sceneroot = root;
520
521 #ifndef BUILDVP1LIGHT
523 message("Error: GeoModel not configured properly in job.");
524 return;
525 }
526
527 //Get the world volume:
528 const GeoModelExperiment * theExpt;
529 if (!VP1SGAccessHelper(this,true).retrieve(theExpt,"ATLAS")) {
530 message("Error: Could not retrieve the ATLAS GeoModelExperiment from detector store");
531 return;
532 }
533 #endif
534
535 #ifdef BUILDVP1LIGHT
536 GeoModelExperiment* theExpt = m_d->getGeometry();
537 #endif
538 PVConstLink world(theExpt->getPhysVol());
539
540 if (!m_d->m_textSep) {
541 // FIXME!
542 // std::cout<<"Making new Text sep"<<std::endl;
543 m_d->m_textSep = new SoSeparator;
544 m_d->m_textSep->setName("TextSep");
545 m_d->m_textSep->ref();
546 }
547 m_d->sceneroot->addChild(m_d->m_textSep);
548
549 // FIXME - what if font is missing?
550 SoFont *myFont = new SoFont;
551 myFont->name.setValue("Arial");
552 myFont->size.setValue(12.0);
553 m_d->m_textSep->addChild(myFont);
554
555 bool save = root->enableNotify(false);
556
557 //Catch keyboard events:
558 SoEventCallback *catchEvents = new SoEventCallback();
559 catchEvents->addEventCallback(SoKeyboardEvent::getClassTypeId(),Imp::catchKbdState, m_d);
560 root->addChild(catchEvents);
561
562 root->addChild(m_d->controller->drawOptions());
563 root->addChild(m_d->controller->pickStyle());
564
565 if(VP1Msg::debug()){
566 qDebug() << "Configuring the default systems... - subsysInfoList len:" << (m_d->subsysInfoList).length();
567 }
568 // we switch on the systems flagged to be turned on at start
569 for (Imp::SubSystemInfo * subsys : m_d->subsysInfoList)
570 {
571 VP1Msg::messageDebug("Switching on this system: " + QString::fromStdString(subsys->matname) + " - " + subsys->flag);
572 bool on(m_d->initialSubSystemsTurnedOn & subsys->flag);
573 subsys->checkbox->setChecked( on );
574 subsys->checkbox->setEnabled(false);
575 subsys->checkbox->setToolTip("This sub-system is not available");
576 connect(subsys->checkbox,SIGNAL(toggled(bool)),this,SLOT(checkboxChanged()));
577 }
578
579 //Locate geometry info for the various subsystems, and add the info as appropriate:
580
581 QCheckBox * checkBoxOther = m_d->controller->subSystemCheckBox(VP1GeoFlags::AllUnrecognisedVolumes);
582
583 if(VP1Msg::debug()){
584 qDebug() << "Looping on volumes from the input GeoModel...";
585 }
586 GeoVolumeCursor av(world);
587 while (!av.atEnd()) {
588
589 std::string name = av.getName();
590 if(VP1Msg::debug()){
591 qDebug() << "volume name:" << QString::fromStdString(name);
592 }
593
594 // DEBUG
595 VP1Msg::messageDebug("DEBUG: Found GeoModel treetop: "+QString(name.c_str()));
596
597 //Let us see if we recognize this volume:
598 bool found = false;
599 for (Imp::SubSystemInfo * subsys : m_d->subsysInfoList) {
600 if (subsys->negatetreetopregexp!=subsys->geomodeltreetopregexp.exactMatch(name.c_str()))
601 {
602 if (subsys->checkbox==checkBoxOther&&found) {
603 continue;//The "other" subsystem has a wildcard which matches everything - but we only want stuff that is nowhere else.
604 }
605
606 if(VP1Msg::debug()){
607 qDebug() << (subsys->geomodeltreetopregexp).pattern() << subsys->geomodeltreetopregexp.exactMatch(name.c_str()) << subsys->negatetreetopregexp;
608 qDebug() << "setting 'found' to TRUE for pattern:" << (subsys->geomodeltreetopregexp).pattern();
609 }
610 found = true;
611 //We did... now, time to extract info:
612 subsys->treetopinfo.resize(subsys->treetopinfo.size()+1);
613 subsys->treetopinfo.back().pV = av.getVolume();
614 subsys->treetopinfo.back().xf = Amg::EigenTransformToCLHEP(av.getTransform());
615 subsys->treetopinfo.back().volname = av.getName();
616
617 //Add a switch for this system (turned off for now):
618 SoSwitch * sw = new SoSwitch();
619 //But add a separator on top of it (for caching):
620 subsys->soswitch = sw;
621 if (sw->whichChild.getValue() != SO_SWITCH_NONE)
622 sw->whichChild = SO_SWITCH_NONE;
623 SoSeparator * sep = new SoSeparator;
624 sep->addChild(sw);
625 root->addChild(sep);
626 //Enable the corresponding checkbox:
627 subsys->checkbox->setEnabled(true);
628 subsys->checkbox->setToolTip("Toggle the display of the "+subsys->checkbox->text()+" sub system");
629 //NB: Dont break here - several systems might share same treetop!
630 // break;
631 }
632 }
633 if (!found) {
634 message("Warning: Found unexpected GeoModel treetop: "+QString(name.c_str()));
635 }
636
637 av.next(); // increment volume cursor.
638 }
639
640 //Hide other cb if not needed:
641 if (!checkBoxOther->isEnabled())
642 checkBoxOther->setVisible(false);
643
644 //Build the geometry for those (available) subsystems that starts out being turned on:
645 for (Imp::SubSystemInfo * subsys : m_d->subsysInfoList) {
646 if (!subsys->soswitch||!subsys->checkbox->isChecked())
647 continue;
648 m_d->buildSystem(subsys);
649 //Enable in 3D view:
650 if (subsys->soswitch->whichChild.getValue() != SO_SWITCH_ALL)
651 subsys->soswitch->whichChild = SO_SWITCH_ALL;
652 //Enable in tree browser:
653 m_d->volumetreemodel->enableSubSystem(subsys->flag);
654 // new ModelTest(m_d->volumetreemodel, m_d->treeView_volumebrowser);
655 }
656 if (!m_d->restoredTopvolstates.isEmpty()) {
657 m_d->applyTopVolStates(m_d->restoredTopvolstates,false);
658 m_d->restoredTopvolstates.clear();
659 }
660 m_d->phisectormanager->updateRepresentationsOfVolsAroundZAxis();
661 root->enableNotify(save);
662 if (save)
663 root->touch();
664
665
666 if (m_d->controller->autoAdaptMuonChambersToEventData())
668
669 //To ensure we emit it once upon startup:
670 QTimer::singleShot(0, this, SLOT(emit_appropriateMDTProjectionsChanged()));
671}
672
673#ifdef BUILDVP1LIGHT
674//_____________________________________________________________________________________
675GeoModelExperiment* VP1GeometrySystem::Imp::getGeometry()
676{
677 // return getDummyGeometry(); // for test
678 return getGeometryFromLocalDB(); // for production
679}
680#endif
681
682#ifdef BUILDVP1LIGHT
683//_____________________________________________________________________________________
684GeoModelExperiment* VP1GeometrySystem::Imp::createTheExperiment(GeoPhysVol* world)
685{
686 if (world == nullptr)
687 {
688 // Setup the 'World' volume from which everything else will be suspended
689 double densityOfAir=0.1;
690 const GeoMaterial* worldMat = new GeoMaterial("std::Air", densityOfAir);
691 const GeoBox* worldBox = new GeoBox(1000*CLHEP::cm, 1000*CLHEP::cm, 1000*CLHEP::cm);
692 const GeoLogVol* worldLog = new GeoLogVol("WorldLog", worldBox, worldMat);
693 // GeoPhysVol* worldPhys = new GeoPhysVol(worldLog);
694 world = new GeoPhysVol(worldLog);
695 }
696 // Setup the 'Experiment' manager
697 GeoModelExperiment* theExperiment = new GeoModelExperiment(world);
698 return theExperiment;
699}
700
701
702//_____________________________________________________________________________________
703GeoModelExperiment* VP1GeometrySystem::Imp::getDummyGeometry()
704{
705 // create the world volume container and its manager
706 GeoModelExperiment* theExperiment = createTheExperiment();
707 //GeoPhysVol* world = theExperiment->getPhysVol();
708
709// // we create the 'detector' geometry and we add it to the world volume
710// ToyDetectorFactory factory(NULL); // more complex geometry example
711// // SimplestToyDetectorFactory factory(NULL); // more complex geometry example
712// factory.create(world);
713// std::cout << "treetop numbers: " << factory.getDetectorManager()->getNumTreeTops() << std::endl;
714 VP1Msg::messageDebug("Method VP1GeometrySystem::Imp::getDummyGeometry() has to be ported to the new standalone GeoModel.");
715
716 return theExperiment;
717}
718
719
720//_____________________________________________________________________________________
721GeoModelExperiment* VP1GeometrySystem::Imp::getGeometryFromLocalDB()
722{
723
724 // GET GEOMETRY FROM LOCAL DB
725 // Set valid db path before first run
726 // static const QString path = "../../local/data/geometry.db";
727 QSettings settings("ATLAS", "VP1Light");
728 QString path = settings.value("db/path").toString();
729 if(VP1Msg::debug()){
730 qDebug() << "Using this DB file:" << path;
731 }
732
733
734 // check if DB file exists. If not, return
735 if (! QFileInfo(path).exists() ) {
736 qWarning() << "ERROR!! DB '" << path << "' does not exist!!";
737 qWarning() << "Returning..." << "\n";
738 // return;
739 throw;
740 }
741 // open the DB
742 GMDBManager* db = new GMDBManager(path);
743 /* Open database */
744 if (db->isOpen()) {
745 if(VP1Msg::debug()){
746 qDebug() << "OK! Database is open!";
747 }
748 }
749 else {
750 if(VP1Msg::debug()){
751 qDebug() << "Database is not open!";
752 }
753 // return;
754 throw;
755 }
756
757 /* setup the GeoModel reader */
758 GeoModelPers::GReadIn readInGeo = GeoModelPers::GReadIn(db);
759 if(VP1Msg::debug()){
760 qDebug() << "GReadIn set.";
761 }
762
763 /* build the GeoModel geometry */
764 GeoPhysVol* dbPhys = readInGeo.buildGeoModel(); // builds the whole GeoModel tree in memory
765 // GeoPhysVol* worldPhys = readInGeo.getGeoModelHandle(); // get only the root volume and its first-level children
766 if(VP1Msg::debug()){
767 qDebug() << "GReadIn::buildGeoModel() done.";
768 }
769 // create the world volume container and its manager
770 GeoModelExperiment* theExperiment = createTheExperiment(dbPhys);
771 // GeoPhysVol* world = theExperiment->getPhysVol();
772
773 return theExperiment;
774
775}
776#endif
777
778//_____________________________________________________________________________________
780{
781 QCheckBox * cb = static_cast<QCheckBox*>(sender());
782 Imp::SubSystemInfo * subsys(0);
783 for (Imp::SubSystemInfo * ss : m_d->subsysInfoList) {
784 if (cb==ss->checkbox) {
785 subsys=ss;
786 break;
787 }
788 }
789 if (!subsys) {
790 message("ERROR: Unknown checkbox");
791 return;
792 }
793
794 SoSwitch * sw = subsys->soswitch;
795 assert(sw);
796 if (cb->isChecked()) {
797 SbBool save = sw->enableNotify(false);
798 if (sw->getNumChildren()==0) {
799 m_d->buildSystem(subsys);
800 m_d->phisectormanager->updateRepresentationsOfVolsAroundZAxis();//
801 }
802 if (sw->whichChild.getValue() != SO_SWITCH_ALL)
803 sw->whichChild = SO_SWITCH_ALL;
804 sw->enableNotify(save);
805 //Enable in tree browser:
806 m_d->volumetreemodel->enableSubSystem(subsys->flag);
807 // new ModelTest(m_d->volumetreemodel, m_d->treeView_volumebrowser);
808 if (save)
809 sw->touch();
810 } else {
811 if (sw->whichChild.getValue() != SO_SWITCH_NONE)
812 sw->whichChild = SO_SWITCH_NONE;
813 m_d->volumetreemodel->disableSubSystem(subsys->flag);
814 }
815}
816
817//_____________________________________________________________________________________
818void VP1GeometrySystem::userPickedNode(SoNode* , SoPath *pickedPath)
819{
820
822 // We want to find the volumehandle for the volume. To do so, we look //
823 // for the SoSeparator identifying the actual picked shape node, and //
824 // use it to look up the handle: //
826
827 //Looking for the identifying "nodesep", there are three scenarios
828 //for the type signatures of the final part of the path:
829 //
830 // 1) Most shapes:
831 // nodesep -> pickedNode (but we must pop to a group node in case of SoCylinders)
832 //
833 // 2) Volumes Around Z (all phi sectors enabled):
834 // nodesep -> switch -> pickedNode
835 //
836 // 3) Volumes Around Z (only some phi sectors enabled):
837 // nodesep -> switch -> sep -> pickedNode
838 //
839 // In the third scenario we also have to pop the path, in order for
840 // all phi-slices of the part gets highlighted (since more than one
841 // soshape node represents the volume).
842
843
844 VP1Msg::messageDebug("VP1GeometrySystem::userPickedNode()");
845
846 if (pickedPath->getNodeFromTail(0)->getTypeId()==SoCylinder::getClassTypeId())
847 pickedPath->pop();
848
849 if (pickedPath->getLength()<5) {
850 message("Path too short");
851 return;
852 }
853
854 SoSeparator * nodesep(0);
855
856 if (pickedPath->getNodeFromTail(1)->getTypeId()==SoSeparator::getClassTypeId()
857 && pickedPath->getNodeFromTail(2)->getTypeId()==SoSwitch::getClassTypeId()
858 && pickedPath->getNodeFromTail(3)->getTypeId()==SoSeparator::getClassTypeId())
859 {
860 //Scenario 3:
861 nodesep = static_cast<SoSeparator*>(pickedPath->getNodeFromTail(3));
862 pickedPath->pop();//To get highlighting of siblings also.
863 }
864 else if (pickedPath->getNodeFromTail(1)->getTypeId()==SoSwitch::getClassTypeId()
865 && pickedPath->getNodeFromTail(2)->getTypeId()==SoSeparator::getClassTypeId())
866 {
867 //Scenario 2:
868 nodesep = static_cast<SoSeparator*>(pickedPath->getNodeFromTail(2));
869 }
870 else if (pickedPath->getNodeFromTail(1)->getTypeId()==SoSeparator::getClassTypeId()) {
871 //Scenario 1 (normal):
872 nodesep = static_cast<SoSeparator*>(pickedPath->getNodeFromTail(1));
873 }
874 if (!nodesep) {
875 message("Unexpected picked path");
876 return;
877 }
878 if ( (!(nodesep)) || (m_d->sonodesep2volhandle.find(nodesep) == m_d->sonodesep2volhandle.end()) ) {
879 message("Problems finding volume handle");
880 return;
881 }
882 VolumeHandle * volhandle = m_d->sonodesep2volhandle[nodesep];
883 if (!volhandle) {
884 message("Found NULL volume handle");
885 return;
886 }
887
889 // Next thing to do is to check whether volume was clicked on with a //
890 // modifier of SHIFT/CTRL/Z. If so, we have to change the state on //
891 // the volume handle. Otherwise, we need to print some information: //
893
894 //For focus reason, and since Qt doesn't allow standard keys such as
895 //'z' as modifiers, we check for keypress states using a combination
896 //of the inventor and Qt way
897
898 bool shift_isdown = (Qt::ShiftModifier & QApplication::keyboardModifiers());
899// || ( m_d->kbEvent && (SO_KEY_PRESS_EVENT(m_d->kbEvent, SoKeyboardEvent::LEFT_SHIFT)||
900// SO_KEY_PRESS_EVENT(m_d->kbEvent, SoKeyboardEvent::RIGHT_SHIFT)) ) );
901
902 if (shift_isdown) {
903 //Parent of volume should be put in CONTRACTED state.
904 deselectAll();
905 if (volhandle->parent())
907 m_d->phisectormanager->updateRepresentationsOfVolsAroundZAxis();
908 return;
909 }
910
911 bool ctrl_isdown = (Qt::ControlModifier & QApplication::keyboardModifiers());
912// || ( m_d->kbEvent && (SO_KEY_PRESS_EVENT(m_d->kbEvent, SoKeyboardEvent::LEFT_CONTROL)||
913// SO_KEY_PRESS_EVENT(m_d->kbEvent, SoKeyboardEvent::RIGHT_CONTROL)) ) );
914
915 if (ctrl_isdown) {
916 //Volume should be put in EXPANDED state if it has children.
917 deselectAll();
918 if (volhandle->nChildren()>0) {
920 }
921 m_d->phisectormanager->updateRepresentationsOfVolsAroundZAxis();
922 return;
923 }
924
925 bool z_isdown = m_d->kbEvent && SO_KEY_PRESS_EVENT(m_d->kbEvent,SoKeyboardEvent::Z);
926 if (z_isdown) {
927 //Volume should be put in ZAPPED state.
928 deselectAll();
929 volhandle->setState(VP1GeoFlags::ZAPPED);
930 message("===> Zapping Node: "+volhandle->getName());
931 // std::cout<<"Zapped VH="<<volhandle<<std::endl;
932 return;
933 }
934
936 // Depending on settings, we are to realign the camera if the //
937 // clicked volume is (daughter of) a muon chamber //
939
940 bool orientedView(false);
941 if (m_d->controller->orientViewToMuonChambersOnClick() && volhandle->isInMuonChamber()) {
942 //Volume is an, or is daughter of an, MDT, CSC or TGC chamber
944 orientedView = true;
945 //Now we must fix the tail of the pickedPath to ensure we
946 //select the correct node corresponding to the clicked volume
947 //again (it might have become attached/detached by the call to
948 //orientViewToMuonChamber):
949 if (!VP1QtInventorUtils::changePathTail(pickedPath,m_d->sceneroot,volhandle->nodeSoSeparator())) {
950 message("Warning: Failed to relocate picked node.");
951 deselectAll();
952 }
953 }
954
956 // Zoom to volume //
958
959 //Nb: We don't do this if we already oriented to the muon chamber above.
960 if (!orientedView&&m_d->controller->zoomToVolumeOnClick()) {
961 if (m_d->sceneroot&&volhandle->nodeSoSeparator()) {
962 std::set<SoCamera*> cameras = getCameraList();
963 std::set<SoCamera*>::iterator it,itE = cameras.end();
964 for (it=cameras.begin();it!=itE;++it) {
965 VP1CameraHelper::animatedZoomToSubTree(*it,m_d->sceneroot,volhandle->nodeSoSeparator(),2.0,1.0);
966 }
967 }
968 }
969
970
972 // Update last-select controls //
974
975 m_d->controller->setLastSelectedVolume(volhandle);
976
978 // OK, time to print some information for the volume //
980
981 message("===> Selected Node: "+volhandle->getName());
982 // std::cout<<"VolHandle = "<<volhandle<<std::endl;
983 if (m_d->controller->printInfoOnClick_Shape()) {
984 for (const QString& str : DumpShape::shapeToStringList(volhandle->geoPVConstLink()->getLogVol()->getShape()))
985 message(str);
986 }
987
988 if (m_d->controller->printInfoOnClick_Material()) {
989 message("===> Material:");
990 for (const QString& line : VP1GeomUtils::geoMaterialToStringList(volhandle->geoMaterial()))
991 message(" "+line);
992 }
993
994 if ( m_d->controller->printInfoOnClick_CopyNumber() ) {
995 int cn = volhandle->copyNumber();
996 message("===> CopyNo : "+(cn>=0?QString::number(cn):QString(cn==-1?"Invalid":"Error reconstructing copynumber")));
997 }
998
999 if ( m_d->controller->printInfoOnClick_Transform() ) {
1000
1001 float translation_x, translation_y, translation_z, rotaxis_x, rotaxis_y, rotaxis_z, rotangle_radians;
1003 translation_x, translation_y, translation_z,
1004 rotaxis_x, rotaxis_y, rotaxis_z, rotangle_radians );
1005 message("===> Local Translation:");
1006 message(" x = "+QString::number(translation_x/CLHEP::mm)+" mm");
1007 message(" y = "+QString::number(translation_y/CLHEP::mm)+" mm");
1008 message(" z = "+QString::number(translation_z/CLHEP::mm)+" mm");
1009 message("===> Local Rotation:");
1010 message(" axis x = "+QString::number(rotaxis_x));
1011 message(" axis y = "+QString::number(rotaxis_y));
1012 message(" axis z = "+QString::number(rotaxis_z));
1013 message(" angle = "+QString::number(rotangle_radians*180.0/M_PI)+" deg");
1015 translation_x, translation_y, translation_z,
1016 rotaxis_x, rotaxis_y, rotaxis_z, rotangle_radians );
1017 message("===> Global Translation:");
1018 message(" x = "+QString::number(translation_x/CLHEP::mm)+" mm");
1019 message(" y = "+QString::number(translation_y/CLHEP::mm)+" mm");
1020 message(" z = "+QString::number(translation_z/CLHEP::mm)+" mm");
1021 message("===> Global Rotation:");
1022 message(" axis x = "+QString::number(rotaxis_x));
1023 message(" axis y = "+QString::number(rotaxis_y));
1024 message(" axis z = "+QString::number(rotaxis_z));
1025 message(" angle = "+QString::number(rotangle_radians*180.0/M_PI)+" deg");
1026 }
1027
1028 if (m_d->controller->printInfoOnClick_Tree()) {
1029 std::ostringstream str;
1030 GeoPrintGraphAction pg(str);
1031 volhandle->geoPVConstLink()->exec(&pg);
1032 message("===> Tree:");
1033 for (const QString& line : QString(str.str().c_str()).split("\n"))
1034 message(" "+line);
1035 }
1036
1037 if (m_d->controller->printInfoOnClick_Mass()) {
1038 //FIXME: Move the mass calculations to the volume handles, and let
1039 //the common data cache some of the volume information by
1040 //logVolume).
1041 message("===> Total Mass &lt;===");
1042 message("Inclusive "+QString::number(Imp::inclusiveMass(volhandle->geoPVConstLink())/CLHEP::kilogram)+" kg");
1043 message("Exclusive "+QString::number(Imp::exclusiveMass(volhandle->geoPVConstLink())/CLHEP::kilogram)+" kg");
1044 }
1045
1046 if (m_d->controller->printInfoOnClick_MuonStationInfo()&&volhandle->isInMuonChamber()) {
1047 PVConstLink pvlink = volhandle->topLevelParent()->geoPVConstLink();
1048 std::map<PVConstLink,VolumeHandle*>::const_iterator itChamber = m_d->muonchambers_pv2handles.find(pvlink);
1049 #ifndef BUILDVP1LIGHT
1050 if (itChamber!=m_d->muonchambers_pv2handles.end()) {
1051 m_d->ensureInitPV2MuonStationMap();
1052 std::map<GeoPVConstLink,const MuonGM::MuonStation*>::const_iterator itStation(m_d->pv2MuonStation.find(pvlink));
1053 if (itStation!=m_d->pv2MuonStation.end()) {
1054 message("===> Muon station &lt;===");
1055 message(" ",m_d->stationInfo(itStation->second));
1056 }
1057 }
1058 #endif
1059 }
1060
1062 // Emit a signal for the VP1UtilitySystems::PartSpect system //
1064 QStack<QString> partspectPath, extras;
1065 QString detFactoryName;
1066
1067 VolumeHandle *parentVH(volhandle), *childVH(volhandle);
1068 m_d->createPathExtras(volhandle,detFactoryName,extras);
1069
1070 do {
1071 parentVH = parentVH->parent();
1072 PVConstLink parentPVLink = parentVH ? parentVH->geoPVConstLink() : childVH->geoPVConstLink()->getParent();
1073 if (parentPVLink) {
1074 int indexOfChild = parentVH ? childVH->childNumber() : parentPVLink->indexOf(childVH->geoPVConstLink()).value();
1075
1076 std::string childPVName = parentPVLink->getNameOfChildVol(indexOfChild);
1077 QString pathEntry = childPVName=="ANON" ? detFactoryName+childVH->getName() : QString(childPVName.c_str());
1078
1079 std::optional<int> childCopyNo = parentPVLink->getIdOfChildVol(indexOfChild);
1080 if(childCopyNo) {
1081 QString strCopyNo;
1082 strCopyNo.setNum(*childCopyNo);
1083 pathEntry += ("::"+strCopyNo);
1084 }
1085 partspectPath.push(pathEntry);
1086 childVH = parentVH;
1087 }
1088 }while(parentVH);
1089
1090 while(!extras.isEmpty())
1091 partspectPath.push(extras.pop());
1092
1093 partspectPath.push("Atlas::Atlas");
1094
1095 // Emit the signal
1096 //volhandle cannot be NULL here (coverity 16287)
1097 //int cn=(!volhandle) ? -1 : volhandle->copyNumber();
1098 int cn=volhandle->copyNumber();
1099 plotSpectrum(partspectPath,cn);
1100}
1101
1102//_____________________________________________________________________________________
1104{
1105 VP1Msg::messageDebug("VP1GeometrySystem::Imp::buildSystem()" );
1106
1107 if (!si||si->isbuilt)
1108 return;
1109 si->isbuilt = true;
1110 int ichild(0);
1111
1113 #ifndef BUILDVP1LIGHT
1114 ensureInitPV2MuonStationMap(); // Needed for Muon Station names.
1115 #endif
1116
1117// // DEBUG
1118// for (Imp::SubSystemInfo*si : m_d->subsysInfoList) {
1119// VP1Msg::messageDebug("vol: " + QString((si->flag).str_c()) );
1120// }
1121
1122 assert(si->soswitch);
1123 SoSeparator * subsystemsep = new SoSeparator;
1124 phisectormanager->registerSubSystemSeparator(si->flag,subsystemsep);
1125 phisectormanager->largeChangesBegin();
1126
1127 SbBool save = si->soswitch->enableNotify(false);
1128
1129 if (si->geomodelchildrenregexp.isEmpty()) {
1130 //Loop over the treetop's that we previously selected:
1131 std::vector<SubSystemInfo::TreetopInfo>::const_iterator it, itE = si->treetopinfo.end();
1132 for (it=si->treetopinfo.begin();it!=itE;++it)
1133 {
1134 VP1Msg::messageDebug("toptree vol: " + QString(it->volname.c_str()) );
1135
1136 //Find material:
1137 SoMaterial*m = detVisAttributes->get(it->volname);
1138 if (!m) {
1139 theclass->message("Warning: Did not find a predefined material for volume: "+QString(it->volname.c_str()));
1140 }
1143 controller->zappedVolumeListModel(),controller->volumeTreeBrowser(), m_textSep);
1144 SbMatrix matr;
1146 VolumeHandle * vh = new VolumeHandle(volhandle_subsysdata,0,it->pV,ichild++,VolumeHandle::NONMUONCHAMBER,matr);
1147 si->vollist.push_back(vh);
1148 // std::cout<<"Non muon chamber VH="<<vh<<std::endl;
1149 }
1150 } else {
1151 //Loop over the children of the physical volumes of the treetops that we previously selected:
1152 std::vector<SubSystemInfo::TreetopInfo>::const_iterator it, itE = si->treetopinfo.end();
1153 for (it=si->treetopinfo.begin();it!=itE;++it) {
1154
1155 VP1Msg::messageDebug("group name: " + QString(si->matname.c_str()) );
1156
1157 //NB: Here we use the si->matname. Above we use the si->volname. Historical reasons!
1158
1159 //Find material for top-nodes:
1160 SoMaterial*mat_top(0);
1161 if (si->matname!="")
1162 mat_top = detVisAttributes->get(si->matname);
1163
1166 controller->zappedVolumeListModel(),controller->volumeTreeBrowser(),m_textSep);
1167 volhandle_subsysdata->ref();
1168
1169 const bool hasMuonChambers=si->hasMuonChambers();
1170
1171 GeoVolumeCursor av(it->pV);
1172 //unsigned int count=0;
1173 while (!av.atEnd()) {
1174
1175 // DEBUG
1176// VP1Msg::messageDebug("child vol: " + QString(av.getName().c_str()) );
1177
1178 //Use the childrenregexp to select the correct child volumes:
1179 if (si->childrenRegExpNameCompatible(av.getName().c_str())) {
1180 PVConstLink pVD = av.getVolume();
1181 SbMatrix matr;
1183 VolumeHandle * vh=0;
1184 // std::cout<<count++<<": dump SubSystemInfo\n"<<"---"<<std::endl;
1185 // si->dump();
1186 // std::cout<<"---"<<std::endl;
1187 if (hasMuonChambers){
1188 #ifndef BUILDVP1LIGHT
1189 vh = new MuonVolumeHandle(volhandle_subsysdata,0,pVD,ichild++,VolumeHandle::MUONCHAMBER_DIRTY,matr,pv2MuonStation[pVD],chamberT0s);
1190 #endif
1191 #ifdef BUILDVP1LIGHT
1192 vh = new VolumeHandle(volhandle_subsysdata,0,pVD,ichild++,VolumeHandle::MUONCHAMBER_DIRTY,matr);
1193 #endif
1194 muonchambers_pv2handles[pVD] = vh;
1195 if(VP1Msg::debug()){
1196 std::cout<<"Has muon chamber VH="<<vh<<std::endl;
1197 }
1198
1199 } else {
1200
1201 vh = new VolumeHandle(volhandle_subsysdata,0,pVD,ichild++,
1203 // std::cout<<"Does not have muon chamber (weird one) VH="<<vh<<std::endl;
1204 }
1205
1206 // DEBUG
1207// VP1Msg::messageDebug("granchild vol: " + vh->getName() + " - " + vh->getDescriptiveName() );
1208
1209 if (si->geomodelgrandchildrenregexp.isEmpty()) {
1210 // append the volume to the current list
1211 theclass->messageDebug("grandchild inserted : " + vh->getDescriptiveName() + " - " + vh->getName() );
1212 si->vollist.push_back(vh);
1213
1214 } else {
1215 VP1Msg::messageDebug("filtering at grandchild level...");
1216 if (si->grandchildrenRegExpNameCompatible(vh->getName().toStdString() ) ) {
1217 VP1Msg::messageDebug("filtered grandchild inserted : " + vh->getDescriptiveName() + " - " + vh->getName() );
1218 // append the volume to the current list
1219 si->vollist.push_back(vh);
1220 } else {
1221 theclass->message("Zapping this volumehandle because it's probably junk."+vh->getDescriptiveName() + " - " + vh->getName());
1222 vh->setState(VP1GeoFlags::ZAPPED); // FIXME - better solution for this? Maybe just don't create them?
1223
1224 // std::cout<<"Not adding "<<vh->getName().toStdString()<<"["<<vh<<"] to vollist"<<std::endl;
1225 }
1226 }
1227 }
1228 av.next(); // increment volume cursor.
1229 }
1230 volhandle_subsysdata->unref();//To ensure it is deleted if it was not used.
1231 }
1232 }
1233
1234 if (VP1Msg::debug()) si->dump();
1235
1236 VP1Msg::messageDebug("volumetreemodel->addSubSystem...");
1237 volumetreemodel->addSubSystem( si->flag, si->vollist );
1238
1239 //NB: We let the destructor of volumetreemodel take care of deleting
1240 //our (top) volume handles, since it has to keep a list of them
1241 //anyway.
1242
1243
1244 //Perform auto expansion of all ether volumes (needed for muon dead material):
1245 VP1Msg::messageDebug("Perform auto expansion of all ether volumes (needed for muon dead material)");
1246 VolumeHandle::VolumeHandleListItr it, itE(si->vollist.end());
1247 //int idx=0; // for debug
1248 for (it = si->vollist.begin(); it!=itE; ++it){
1249 //VP1Msg::messageDebug("\nexpanding idx: " + QString::number(++idx));
1250 (*it)->expandMothersRecursivelyToNonEther();
1251 //VP1Msg::messageDebug("expand DONE.");
1252 }
1253
1254
1255 VP1Msg::messageDebug("addChild...");
1256 phisectormanager->updateRepresentationsOfVolsAroundZAxis();
1257 phisectormanager->largeChangesEnd();
1258 si->soswitch->addChild(subsystemsep);
1259 si->soswitch->enableNotify(save);
1260 if (save)
1261 si->soswitch->touch();
1262 VP1Msg::messageDebug("END of VP1GeometrySystem::Imp::buildSystem() " );
1263}
1264
1265//_____________________________________________________________________________________
1266double VP1GeometrySystem::Imp::exclusiveMass(const PVConstLink& pv) {
1267 const GeoLogVol* lv = pv->getLogVol();
1268 const GeoMaterial *material = lv->getMaterial();
1269 double density = material->getDensity();
1270 return density*volume(pv);
1271}
1272
1273
1274//_____________________________________________________________________________________
1275double VP1GeometrySystem::Imp::volume(const PVConstLink& pv) {
1276 const GeoLogVol * lv = pv->getLogVol();
1277 const GeoShape *shape = lv->getShape();
1278 return shape->volume();
1279}
1280
1281
1282//_____________________________________________________________________________________
1283double VP1GeometrySystem::Imp::inclusiveMass(const PVConstLink& pv) {
1284
1285 const GeoLogVol* lv = pv->getLogVol();
1286 const GeoMaterial *material = lv->getMaterial();
1287 double density = material->getDensity();
1288
1289 double mass = exclusiveMass(pv);
1290
1291 GeoVolumeCursor av(pv);
1292 while (!av.atEnd()) {
1293 mass += inclusiveMass(av.getVolume());
1294 mass -= volume(av.getVolume())*density;
1295 av.next();
1296 }
1297
1298 return mass;
1299}
1300
1301//_____________________________________________________________________________________
1303
1305
1306 VP1Serialise serialise(7/*version*/,this);
1307 serialise.save(IVP13DSystemSimple::saveState());
1308
1309 //Controller:
1310 serialise.save(m_d->controller->saveSettings());
1311
1312 //Subsystem checkboxes:
1313 QMap<QString,bool> subsysstate;
1314 for (Imp::SubSystemInfo * subsys : m_d->subsysInfoList) {
1315 serialise.widgetHandled(subsys->checkbox);
1316 subsysstate.insert(subsys->checkbox->text(),subsys->checkbox->isChecked());
1317 }
1318 serialise.save(subsysstate);
1319
1320 //Volume states:
1321 QMap<quint32,QByteArray> topvolstates;
1322 for (Imp::SubSystemInfo * subsys : m_d->subsysInfoList) {
1323 if (m_d->controller->autoAdaptMuonChambersToEventData()&&subsys->hasMuonChambers())
1324 continue;//No need to store muon chamber data which will anyway be auto-adapted away.
1325 VolumeHandle::VolumeHandleListItr it(subsys->vollist.begin()),itE(subsys->vollist.end());
1326 for (;it!=itE;++it)
1327 topvolstates.insert((*it)->hashID(),(*it)->getPersistifiableState());
1328 }
1329 serialise.save(topvolstates);
1330
1331 m_d->ensureInitVisAttributes();
1332 serialise.save(m_d->detVisAttributes->getState());//version 7+
1333 serialise.save(m_d->matVisAttributes->getState());//version 7+
1334 serialise.save(m_d->volVisAttributes->getState());//version 7+
1335
1336 serialise.disableUnsavedChecks();//We do the testing in the controller
1337 return serialise.result();
1338}
1339
1340//_____________________________________________________________________________________
1342 VP1Deserialise state(ba,this);
1343 if (state.version()<0||state.version()>7) {
1344 message("Warning: State data in .vp1 file is in wrong format - ignoring!");
1345 return;
1346 }
1347 if (state.version()<=5) {
1348 message("Warning: State data in .vp1 file is in obsolete format - ignoring!");
1349 return;
1350 }
1351
1353 IVP13DSystemSimple::restoreFromState(state.restoreByteArray());
1354
1355 //Controller:
1356 m_d->controller->restoreSettings(state.restoreByteArray());
1357
1358 //Subsystem checkboxes:
1359 VP1GeoFlags::SubSystemFlags flags;
1360 QMap<QString,bool> subsysstate = state.restore<QMap<QString,bool> >();
1361 for (Imp::SubSystemInfo * subsys : m_d->subsysInfoList) {
1362 state.widgetHandled(subsys->checkbox);
1363 if (subsysstate.contains(subsys->checkbox->text())&&subsysstate[subsys->checkbox->text()])
1364 flags |= subsys->flag;
1365 }
1366 m_d->initialSubSystemsTurnedOn = flags;
1367
1368 //Volume states:
1369 QMap<quint32,QByteArray> topvolstates;
1370 topvolstates = state.restore<QMap<quint32,QByteArray> >();
1371 if (m_d->sceneroot)//(for some reason) we already have been in buildPermanentScenegraph
1372 m_d->applyTopVolStates(topvolstates,true);
1373 else
1374 m_d->restoredTopvolstates = topvolstates;//save until buildPermanentScenegraph
1375
1376 if (state.version()>=7) {
1377 m_d->ensureInitVisAttributes();
1378 m_d->detVisAttributes->applyState(state.restoreByteArray());
1379 m_d->matVisAttributes->applyState(state.restoreByteArray());
1380 m_d->volVisAttributes->applyState(state.restoreByteArray());
1381 }
1382
1383 state.disableUnrestoredChecks();//We do the testing in the controller
1384
1385 //Special:
1386 if (m_d->controller->autoAdaptMuonChambersToEventData())
1388}
1389
1390//_____________________________________________________________________________________
1391void VP1GeometrySystem::Imp::applyTopVolStates(const QMap<quint32,QByteArray>&topvolstates,bool disablenotif)
1392{
1393 if (disablenotif)
1394 phisectormanager->largeChangesBegin();
1395 QMap<quint32,QByteArray>::const_iterator topvolstatesItr;
1396 for (Imp::SubSystemInfo * subsys : subsysInfoList) {
1397 VolumeHandle::VolumeHandleListItr it(subsys->vollist.begin()),itE(subsys->vollist.end());
1398 for (;it!=itE;++it) {
1399 topvolstatesItr = topvolstates.find((*it)->hashID());
1400 if (topvolstatesItr!=topvolstates.end())
1401 (*it)->applyPersistifiableState(topvolstatesItr.value());
1402 }
1403 }
1404 if (disablenotif) {
1405 phisectormanager->updateRepresentationsOfVolsAroundZAxis();
1406 phisectormanager->largeChangesEnd();
1407 }
1408}
1409
1410//_____________________________________________________________________________________
1411void VP1GeometrySystem::Imp::createPathExtras(const VolumeHandle* volhandle, QString& prefix, QStack<QString>& entries)
1412{
1413 switch(volhandle->subsystem()){
1414 case VP1GeoFlags::Pixel: {
1415 prefix = QString("Pixel::");
1416 entries.push("IDET::IDET");
1418 entries.push("ITkPixel::ITkPixel");
1419 else
1420 entries.push("Pixel::Pixel");
1421 return;
1422 }
1423 case VP1GeoFlags::SCT:{
1424 prefix = QString("SCT::");
1425 entries.push("IDET::IDET");
1427 entries.push("ITkStrip::ITkStrip");
1428 else
1429 entries.push("SCT::SCT");
1430 return;
1431 }
1432 case VP1GeoFlags::HGTD: {
1433 prefix = QString("HGTD::");
1434 entries.push("IDET::IDET");
1435 entries.push("HGTD::HGTD");
1436 return;
1437 }
1438 case VP1GeoFlags::TRT:{
1439 prefix = QString("TRT::");
1440 entries.push("IDET::IDET");
1441 entries.push("TRT::TRT");
1442 return;
1443 }
1445 prefix = QString("InDetServMat::");
1446 entries.push("IDET::IDET");
1447 return;
1448 }
1449 case VP1GeoFlags::LAr:{
1450 prefix = QString("LArMgr::");
1451 entries.push("CALO::CALO");
1452 entries.push("LArMgr::LArMgr");
1453 return;
1454 }
1455 case VP1GeoFlags::Tile:{
1456 prefix = QString("Tile::");
1457 entries.push("CALO::CALO");
1458 entries.push("Tile::Tile");
1459 return;
1460 }
1474 prefix = QString("Muon::");
1475 entries.push("MUONQ02::MUONQ02");
1476 entries.push("Muon::MuonSys");
1477 return;
1478 }
1480 prefix = QString("BeamPipe::");
1481 entries.push("BeamPipe::BeamPipe");
1482 return;
1483 }
1484 case VP1GeoFlags::None:
1486 case VP1GeoFlags::LUCID:
1487 case VP1GeoFlags::ZDC:
1488 case VP1GeoFlags::ALFA:
1489 case VP1GeoFlags::AFP:
1492 default:{
1493 return;
1494 }
1495 }
1496}
1497
1498//_____________________________________________________________________________________
1500{
1502 if (val<0||val>100) {
1503 message("setCurvedSurfaceRealism Error: Value "+str(val)+"out of range!");
1504 return;
1505 }
1506 m_d->controller->setComplexity(val==100?1.0:(val==0?0.0:val/100.0));
1507}
1508
1509
1510
1511//_____________________________________________________________________________________
1513{
1515
1516 float transparency = m_d->controller->transparency();
1517
1518 VolumeHandle* lastSelVol = m_d->controller->lastSelectedVolume();
1519 m_d->controller->setLastSelectedVolume(0);
1520 m_d->ensureInitVisAttributes();
1521 m_d->detVisAttributes->overrideTransparencies(transparency);
1522 m_d->matVisAttributes->overrideTransparencies(transparency);
1523 m_d->volVisAttributes->overrideTransparencies(transparency);
1524 m_d->controller->setLastSelectedVolume(lastSelVol);
1525}
1526
1527//_____________________________________________________________________________________
1528void VP1GeometrySystem::resetSubSystems(VP1GeoFlags::SubSystemFlags f)
1529{
1530 if (!f) {
1531 return;
1532 }
1533
1534 deselectAll();
1535 for (Imp::SubSystemInfo*si : m_d->subsysInfoList) {
1536 if (si->flag & f) {
1537 if (!si->isbuilt) {
1538 continue;
1539 }
1540 VolumeHandle::VolumeHandleListItr it(si->vollist.begin()),itE(si->vollist.end());
1541 for (;it!=itE;++it) {
1542 messageDebug("resetting volume --> " + (*it)->getName() );
1543 (*it)->reset();
1544 }
1545 }
1546 }
1547}
1548
1549//_____________________________________________________________________________________
1551{
1552 if (m_d->muonchambers_pv2handles.empty())
1553 return;
1554
1555 std::set<GeoPVConstLink> allchambers;
1556 if (!m_d->sender2ChamberList.empty()) {
1557 allchambers = (m_d->sender2ChamberList.begin())->second;
1558 std::map<QObject*,std::set<GeoPVConstLink> >::iterator itLists,itListsE(m_d->sender2ChamberList.end());
1559 for (itLists = m_d->sender2ChamberList.begin(),++itLists;itLists != itListsE;++itLists) {
1560 allchambers.insert(itLists->second.begin(),itLists->second.end());
1561 }
1562 }
1563
1564 //Idea: Maybe just iconise them all and then selectively deiconise the few? Then we can avoid most searches!
1565 bool save = m_d->sceneroot->enableNotify(false);
1566 m_d->phisectormanager->largeChangesBegin();
1567
1568 deselectAll();
1569 std::map<PVConstLink,VolumeHandle*>::iterator it, itE=m_d->muonchambers_pv2handles.end();
1570 std::set<GeoPVConstLink>::iterator itchambersE = allchambers.end();
1571 for (it=m_d->muonchambers_pv2handles.begin();it!=itE;++it) {
1572 if (allchambers.find(it->first)==itchambersE)
1573 it->second->setState(VP1GeoFlags::ZAPPED);
1574 else {
1575 if (it->second->muonChamberDirty())
1576 m_d->updateTouchedMuonChamber(it->second);
1577 }
1578 }
1579 m_d->phisectormanager->updateRepresentationsOfVolsAroundZAxis();
1580 m_d->phisectormanager->largeChangesEnd();
1581 if (save) {
1582 m_d->sceneroot->enableNotify(true);
1583 m_d->sceneroot->touch();
1584 }
1585}
1586
1587//_____________________________________________________________________________________
1589{
1590 //Make all chamber representations dirty:
1591 std::map<PVConstLink,VolumeHandle*>::iterator it, itE=m_d->muonchambers_pv2handles.end();
1592 for (it=m_d->muonchambers_pv2handles.begin();it!=itE;++it)
1593 it->second->setMuonChamberDirty(true);
1594
1595 //Adapt immediately if necessary:
1596 if (m_d->controller->autoAdaptMuonChambersToEventData())
1599}
1600
1601//_____________________________________________________________________________________
1603{
1604 if (!m_d->controller) {
1605 message("emit_appropriateMDTProjectionsChanged called before controller built.");
1606 return;
1607 }
1608 VP1GeoFlags::MuonChamberAdaptionStyleFlags f(m_d->controller->muonChamberAdaptionStyle());
1609 bool option_openmdtchambers = f & VP1GeoFlags::OpenMDTChambers;
1610 bool option_hidetubes = f & VP1GeoFlags::HideMDTTubes;
1611 int i (option_openmdtchambers?(option_hidetubes?0:1):2);
1612 if ( m_d->last_appropriatemdtprojections != i ) {
1613 m_d->last_appropriatemdtprojections = i;
1615 }
1616}
1617
1618//_____________________________________________________________________________________
1619void VP1GeometrySystem::reiconizeToShowSpecificMuonChambers(const std::set<GeoPVConstLink>& chambers)
1620{
1621 //Update map of touched chamber lists:
1622 bool listChanged(m_d->sender2ChamberList.find(sender())!=m_d->sender2ChamberList.end()?
1623 (chambers != m_d->sender2ChamberList[sender()]):true);
1624 m_d->sender2ChamberList[sender()] = chambers;
1625
1626 //Trigger update if list changed and in auto mode:
1627 if ( listChanged && m_d->controller->autoAdaptMuonChambersToEventData() )
1629}
1630
1631//_____________________________________________________________________________________
1633{
1634 std::string stationname = chamberhandle->getNameStdString();
1635 if (stationname.empty()) {
1636 theclass->message("Warning: Asked to handle muon chamber (station) with empty name!");
1637 return;
1638 }
1639 //NB: For efficiency we make sure that mothers are ZAPPED while
1640 //changing state of their children.
1641
1642 //options:
1643
1644 VP1GeoFlags::MuonChamberAdaptionStyleFlags f(controller->muonChamberAdaptionStyle());
1645 bool option_openmdtchambers = f & VP1GeoFlags::OpenMDTChambers;
1646 bool option_hidetubes = f & VP1GeoFlags::HideMDTTubes;
1647 bool option_hiderpcvolumes = f & VP1GeoFlags::HideRPCVolumes;
1648 bool option_opencscchambers = f & VP1GeoFlags::OpenCSCChambers;
1649 bool option_opentgcchambers = f & VP1GeoFlags::OpenTGCChambers;
1650
1651 char firstletter = stationname[0];
1652 std::string name1,name2;
1653 if (firstletter=='E' || firstletter =='B') {
1654 //Barrel/Endcap MDT.
1655 // If we are to open it, we expand two levels.
1656 // -> and possibly zap the tubes/rpc volumes also according to options.
1657 if (option_openmdtchambers) {
1658 chamberhandle->setState(VP1GeoFlags::ZAPPED);
1659 chamberhandle->contractDaughtersRecursively();
1660 chamberhandle->initialiseChildren();
1661 VolumeHandle::VolumeHandleListItr itch(chamberhandle->childrenBegin()), itchE(chamberhandle->childrenEnd());
1662 for (;itch!=itchE;++itch) {
1663 //Any daughter with the name "Ded..." should be zapped,
1664 //otherwise we loop over the children to zap tubes/rpc vols.
1665 (*itch)->setState(VP1GeoFlags::ZAPPED);
1666 name1 = (*itch)->getNameStdString();
1667 if (name1.size()>2&&name1[0]=='D'&&name1[1]=='e'&&name1[2]=='d')
1668 continue;
1669
1670 (*itch)->initialiseChildren();
1671 VolumeHandle::VolumeHandleListItr itch2((*itch)->childrenBegin()), itch2E((*itch)->childrenEnd());
1672 for (;itch2!=itch2E;++itch2) {
1673 //Any of these daughters with the name
1674 //"MDTDriftWall"/"Rpc..."/"RPC..."/"Ded..." should be
1675 //zapped (according to options). Others should be contracted.
1676 name2 = (*itch2)->getNameStdString();
1677 bool zap = false;
1678 if (option_hidetubes&&name2=="MDTDriftWall") {
1679 zap = true;
1680 } else if (name2.size()>2&&name2[0]=='R'&&((name2[1]=='p'&&name2[2]=='c')||(name2[1]=='P'&&name2[2]=='C'))) {
1681 zap = (option_hiderpcvolumes||name2!="Rpclayer");
1682 } else if (name2.size()>2&&name2[0]=='D'&&name2[1]=='e'&&name2[2]=='d') {
1683 zap = true;
1684 }
1685 (*itch2)->setState(zap?VP1GeoFlags::ZAPPED:VP1GeoFlags::CONTRACTED);
1686 }
1687 (*itch)->setState(VP1GeoFlags::EXPANDED);
1688 }
1689 chamberhandle->setState(VP1GeoFlags::EXPANDED);
1690 } else {
1691 chamberhandle->reset();
1692 }
1693 } else {
1694 if (firstletter=='C') {
1695 //CSC: We either contract completely or expand once + zap "CscArCO2" + zap spacers
1696 chamberhandle->setState(VP1GeoFlags::ZAPPED);
1697 chamberhandle->contractDaughtersRecursively();//To put into default state
1698 if (option_opencscchambers) {
1699 //We must zap spacers, and otherwise expand down three levels and zap all "CscArCO2":
1700 chamberhandle->initialiseChildren();
1701 VolumeHandle::VolumeHandleListItr itch(chamberhandle->childrenBegin()), itchE(chamberhandle->childrenEnd());
1702 for (;itch!=itchE;++itch) {
1703 if ((*itch)->hasName("CSCspacer")) {
1704 (*itch)->setState(VP1GeoFlags::ZAPPED);
1705 continue;
1706 }
1707 if ((*itch)->nChildren()<1)
1708 continue;
1709 (*itch)->initialiseChildren();
1710 VolumeHandle::VolumeHandleListItr itch2((*itch)->childrenBegin()), itch2E((*itch)->childrenEnd());
1711 for (;itch2!=itch2E;++itch2) {
1712 if ((*itch2)->nChildren()<1)
1713 continue;
1714 (*itch2)->initialiseChildren();
1715 VolumeHandle::VolumeHandleListItr itch3((*itch2)->childrenBegin()), itch3E((*itch2)->childrenEnd());
1716 for (;itch3!=itch3E;++itch3) {
1717 if ((*itch3)->getNameStdString()=="CscArCO2")
1718 (*itch3)->setState(VP1GeoFlags::ZAPPED);
1719 }
1720 (*itch2)->setState(VP1GeoFlags::EXPANDED);
1721 }
1722 (*itch)->setState(VP1GeoFlags::EXPANDED);
1723 }
1724 chamberhandle->setState(VP1GeoFlags::EXPANDED);
1725 } else {
1726 chamberhandle->setState(VP1GeoFlags::CONTRACTED);
1727 }
1728 } else {
1729 //TGC: If 'open' we expand two levels and zap all gas volumes.
1730 chamberhandle->setState(VP1GeoFlags::ZAPPED);
1731 chamberhandle->contractDaughtersRecursively();//To put into default state
1732 if (option_opentgcchambers) {
1733 //Expand once more and then zap daughters called "muo::TGCGas"
1734 chamberhandle->initialiseChildren();
1735 VolumeHandle::VolumeHandleListItr itch(chamberhandle->childrenBegin()), itchE(chamberhandle->childrenEnd());
1736 for (;itch!=itchE;++itch) {
1737 if ((*itch)->nChildren()<1)
1738 continue;
1739 (*itch)->initialiseChildren();
1740 VolumeHandle::VolumeHandleListItr itch2((*itch)->childrenBegin()), itch2E((*itch)->childrenEnd());
1741 for (;itch2!=itch2E;++itch2) {
1742 if ((*itch2)->getNameStdString()=="muo::TGCGas")
1743 (*itch2)->setState(VP1GeoFlags::ZAPPED);
1744 }
1745 (*itch)->setState(VP1GeoFlags::EXPANDED);
1746 }
1747 chamberhandle->setState(VP1GeoFlags::EXPANDED);
1748 } else {
1749 chamberhandle->setState(VP1GeoFlags::CONTRACTED);
1750 }
1751 }
1752 }
1753 chamberhandle->setMuonChamberDirty(false);
1754}
1755
1756//_____________________________________________________________________________________
1758{
1759 VP1Msg::messageDebug("VP1GeometrySystem::Imp::chamberPVToMuonSubSystemInfo()");
1760
1761 std::string name = chamberPV->getLogVol()->getName();
1762
1763 VP1Msg::messageDebug("name: " + QString::fromStdString(name) );
1764
1765 for (SubSystemInfo * subsys : subsysInfoList) {
1766 if (!subsys->hasMuonChambers())
1767 continue;
1768 if (subsys->childrenRegExpNameCompatible(name)) {
1769 //NB: We assume once again that all muon chambers are to be
1770 //compared with childrenRegExp.
1771 return subsys;
1772 }
1773 }
1774 return 0;
1775}
1776
1777//_____________________________________________________________________________________
1778void VP1GeometrySystem::orientViewToMuonChamber(const GeoPVConstLink& chamberPV)
1779{
1780 if (!m_d->sceneroot)
1781 return;
1782
1783 //Find relevant muon subsystem info:
1784 Imp::SubSystemInfo * subsys = m_d->chamberPVToMuonSubSystemInfo(chamberPV);
1785 if (!subsys) {
1786 message("Error: Asked to orient view to chamber volume '"
1787 +QString(chamberPV->getLogVol()->getName().c_str())
1788 +"', which doesn't fit the known format of any chamber!");
1789 return;
1790 }
1791
1792 //Subsystem must be available:
1793 if (!subsys->soswitch) {//NB: Could as well look at checkbox enabled state instead of whether sw pointer is null.
1794 message("Warning: Asked to orient view to muon chamber volume which is not available. Perhaps muon geometry was not built?");
1795 return;
1796 }
1797
1798 //Find handle for the muon chamber (possibly ensure that relevant muon subsystem is build):
1799 std::map<PVConstLink,VolumeHandle*>::iterator itChamber = m_d->muonchambers_pv2handles.find(chamberPV);
1800 if (itChamber==m_d->muonchambers_pv2handles.end()) {
1801 //Probably the muon relevant muon system was not initialised. Build and try again:
1802 m_d->buildSystem(subsys);
1803 itChamber = m_d->muonchambers_pv2handles.find(chamberPV);
1804 if (itChamber==m_d->muonchambers_pv2handles.end()) {
1805 message("Error: Asked to orient view to chamber volume '"
1806 +QString(chamberPV->getLogVol()->getName().c_str())
1807 +"', but could not find chamber handle!");
1808 return;
1809 }
1810 }
1811 VolumeHandle * chamberHandle = itChamber->second;
1812
1813 //Figure out if we are MDT, CSC or TGC (if not we print warning and abort);
1814
1815 std::string name = chamberHandle->getNameStdString();
1816
1817 bool isCSCOrTGC = name.size()>=2 && ( (name[0]=='C' && name[1]=='S') || (name[0]=='T') );
1818 if (!isCSCOrTGC&&!(name.size()>=1&&(name[0]=='E'||name[0]=='B'))) {
1819 //Neither CSC, TGC or MDT:
1820 message("orientViewToMuonChamber Warning: Not CSC, TGC or MDT station!");
1821 return;
1822 }
1823
1824 bool save = subsys->soswitch->enableNotify(false);//Disable notifications to avoid chamber flickering in for a moment.
1825
1826 //If subsystem soswitch is turned off, we turn it on temporarily
1827 int32_t soswitch_val = subsys->soswitch->whichChild.getValue();
1828 if (soswitch_val!=SO_SWITCH_ALL)
1829 subsys->soswitch->whichChild = SO_SWITCH_ALL;
1830
1831 VP1GeoFlags::VOLSTATE oldChamberState = chamberHandle->state();
1832 chamberHandle->setState(VP1GeoFlags::CONTRACTED);
1833
1834 SoSeparator * chambersep = chamberHandle->nodeSoSeparator();
1835 if (chambersep) {
1836 std::set<SoCamera*> cameras = getCameraList();
1837 std::set<SoCamera*>::iterator it,itE = cameras.end();
1838 for (it=cameras.begin();it!=itE;++it) {
1839 //Find desired camera orientation (must be parallel to tubes - and
1840 //we choose the one of the possible orientations which is closest to
1841 //current camera orientation - i.e. loop over tubes and try both
1842 //positive and negative directions of each tube.
1843
1844 SbRotation camrot = (*it)->orientation.getValue();
1845 SbVec3f cameraDir(0, 0, -1); // init to default view direction vector
1846 camrot.multVec(cameraDir, cameraDir);
1847 SbVec3f cameraUpVec(0, 1, 0); // init to default up vector
1848 camrot.multVec(cameraUpVec, cameraUpVec);
1849
1850 std::pair<SbVec3f,SbVec3f> chamberdirections;
1851 if (isCSCOrTGC) {
1852 //CSC/TGC chamber - look at top TRD shape for directions
1853 chamberdirections = m_d->getClosestCSCOrTGCEdgeDirections(cameraDir,chamberHandle);
1854 } else {
1855 //MDT chamber - look at tubes for direction
1856 chamberdirections = m_d->getClosestMuonDriftTubeDirections(cameraDir,cameraUpVec,chamberHandle);
1857 }
1858 SbVec3f newdirection = - chamberdirections.first;
1859 SbVec3f newup(cameraUpVec);
1860 const float epsilon(0.00001f);
1861 if (m_d->previousAlignedChamberHandle==chamberHandle&&cameraDir.equals(newdirection,epsilon)) {
1862 //If we already zoomed in the direction of the chamber,
1863 //subsequent requests aligns the upvector along the other chamber
1864 //axes.
1865 SbRotation rot(cameraDir,0.5*M_PI);
1866 SbVec3f chambdir1 = chamberdirections.second;
1867 SbVec3f chambdir2,chambdir3,chambdir4;
1868 rot.multVec(chambdir1,chambdir2);
1869 rot.multVec(chambdir2,chambdir3);
1870 rot.multVec(chambdir3,chambdir4);
1871 if (cameraUpVec.equals(chambdir1,epsilon)) {
1872 newup = chambdir2;
1873 } else if (cameraUpVec.equals(chambdir2,epsilon)) {
1874 newup = chambdir3;
1875 } else if (cameraUpVec.equals(chambdir3,epsilon)) {
1876 newup = chambdir4;
1877 } else if (cameraUpVec.equals(chambdir4,epsilon)) {
1878 newup = chambdir1;
1879 } else {
1880 //Take the closest one...
1881 float cos1 = chambdir1.dot(cameraUpVec);
1882 float cos2 = chambdir2.dot(cameraUpVec);
1883 float cos3 = chambdir3.dot(cameraUpVec);
1884 float cos4 = chambdir4.dot(cameraUpVec);
1885 float maxcos = std::max(std::max(cos1,cos2),std::max(cos3,cos4));
1886 if (cos1==maxcos)
1887 newup = chambdir1;
1888 else if (cos2==maxcos)
1889 newup = chambdir2;
1890 else if (cos3==maxcos)
1891 newup = chambdir3;
1892 else
1893 newup = chambdir4;
1894 }
1895 }
1896
1897 //Zoom to chamber with given orientation - and we make sure the
1898 //chamber is attached while we initiate the zoom (so the camera
1899 //helper can use a boundaryboxaction to find the bounding box):
1900 VP1CameraHelper::animatedZoomToSubTree(*it,m_d->sceneroot,chambersep,1.0, 100.0, 100.0, 1.0,newdirection,newup);
1901 }
1902 }
1903
1904 chamberHandle->setState(oldChamberState);
1905 if (soswitch_val!=SO_SWITCH_ALL)
1906 subsys->soswitch->whichChild.setValue(soswitch_val);
1907 if (save) {
1908 subsys->soswitch->enableNotify(true);
1909 subsys->soswitch->touch();
1910 }
1911 m_d->previousAlignedChamberHandle=chamberHandle;
1912
1913}
1914
1915//Check all tubes in chamber and returns directions parallel with a tube which is closest to present camera direction:
1916//_____________________________________________________________________________________
1917std::pair<SbVec3f,SbVec3f> VP1GeometrySystem::Imp::getClosestMuonDriftTubeDirections( const SbVec3f& cameraDirection,
1918 const SbVec3f& cameraUpDirection,
1919 VolumeHandle * chamberhandle )
1920{
1921 //We assume chamberhandle is to an MDT station (barrel or endcap).
1922 SbVec3f closesttubedir(cameraDirection);
1923 SbVec3f closesttubeupvec(cameraUpDirection);
1924 float smallestcosangle(1.1);
1925
1926 //Barrel/Endcap MDT. Expand two levels and then check the individual tubes.
1927 chamberhandle->initialiseChildren();
1928 VolumeHandle::VolumeHandleListItr itch(chamberhandle->childrenBegin()), itchE(chamberhandle->childrenEnd());
1929 for (;itch!=itchE;++itch) {
1930 //Any daughter with the name "Ded..." should be ignored
1931 std::string name1 = (*itch)->getNameStdString();
1932 if (name1.size()>2&&name1[0]=='D'&&name1[1]=='e'&&name1[2]=='d')
1933 continue;
1934
1935 (*itch)->initialiseChildren();
1936 VolumeHandle::VolumeHandleListItr itch2((*itch)->childrenBegin()), itch2E((*itch)->childrenEnd());
1937 //Various variables needed to deal with each tube:
1938 const SbVec3f unitz(0.0f,0.0f,1.0f);
1939 const SbVec3f unity(0.0f,1.0f,0.0f);
1940 SbVec3f tubeglob;
1941 SbVec3f translation, scale;
1942 SbRotation rotation, scalerotation;
1943
1944 for (;itch2!=itch2E;++itch2) {
1945 if ((*itch2)->getNameStdString()=="MDTDriftWall") {
1946 //OK, we got the handle of a tube (wall). Lets find its direction!
1947 //->We assume that the tube, in its local coordinate system, is aligned with the z axis.
1948 //Get global rotation of tube:
1949 (*itch2)->getGlobalTransformToVolume().getTransform(translation,rotation,scale,scalerotation);
1950 rotation.multVec (unitz, tubeglob);
1951 if (tubeglob.dot(cameraDirection)<smallestcosangle) {
1952 smallestcosangle = tubeglob.dot(cameraDirection);
1953 closesttubedir = tubeglob;
1954 rotation.multVec(unity, closesttubeupvec);
1955 }
1956 if (tubeglob.dot(-cameraDirection)<smallestcosangle) {
1957 smallestcosangle = tubeglob.dot(-cameraDirection);
1958 closesttubedir = -tubeglob;
1959 rotation.multVec(unity, closesttubeupvec);
1960 }
1961 }
1962 }
1963 }
1964 return std::pair<SbVec3f,SbVec3f>(closesttubedir,closesttubeupvec);
1965}
1966
1967//_____________________________________________________________________________________
1968std::pair<SbVec3f,SbVec3f> VP1GeometrySystem::Imp::getClosestCSCOrTGCEdgeDirections( const SbVec3f& cameraDirection,
1969 VolumeHandle * chamberhandle )
1970{
1971 // It turns out that the correct chamber directions for CSC/TGC chambers is the y and z axes.
1972 std::vector<SbVec3f> directions;
1973 directions.push_back(SbVec3f(0.0f,1.0f,0.0f));
1974 directions.push_back(SbVec3f(0.0f,-1.0f,0.0f));
1975 directions.push_back(SbVec3f(0.0f,0.0f,1.0f));
1976 directions.push_back(SbVec3f(0.0f,0.0f,-1.0f));
1977
1978 directions.push_back(SbVec3f(1.0f,0.0f,0.0f));
1979 directions.push_back(SbVec3f(-1.0f,0.0f,0.0f));
1980
1981 //Get local->global transformation for chamber:
1982 SbVec3f translation, scale;
1983 SbRotation rotation, scalerotation;
1984 chamberhandle->getGlobalTransformToVolume().getTransform(translation,rotation,scale,scalerotation);
1985
1986 //Put directions into global coordinates:
1987 for (unsigned i = 0; i<directions.size();++i)
1988 rotation.multVec(directions[i],directions[i]);
1989
1990 //Find the one closest to the camera:
1991 SbVec3f chamberDir(-cameraDirection);
1992 float smallestcosangle(1.1);
1993 for (unsigned i = 0; i<directions.size();++i) {
1994 if (directions.at(i).dot(cameraDirection)<smallestcosangle) {
1995 smallestcosangle = directions.at(i).dot(cameraDirection);
1996 chamberDir = directions.at(i);
1997 }
1998 }
1999
2000 //cameraUpDirection should always (0,1,0) transformed to global
2001 //coordinates:
2002 SbVec3f chamberUp;
2003 float x,y,z;
2004 chamberDir.getValue(x,y,z);
2005 if (x!=0.0f) {
2006 rotation.multVec(SbVec3f(0.0f,1.0f,0.0f),chamberUp);
2007 } else {
2008 rotation.multVec(SbVec3f(1.0f,0.0f,0.0f),chamberUp);
2009 }
2010
2011 //Done:
2012 return std::pair<SbVec3f,SbVec3f>(chamberDir,chamberUp);
2013}
2014
2015//_____________________________________________________________________________________
2017{
2018 assert(target!=VP1GeoFlags::CONTRACTED);
2019 if (handle->isAttached()) {
2020 //The volume is visible, so ignore daughters
2021 if (handle->isInitialisedAndHasNonStandardShape()) {
2022 if (target!=VP1GeoFlags::EXPANDED||handle->nChildren()>0)
2023 handle->setState(target);
2024 }
2025 return;
2026 } else if (handle->state()==VP1GeoFlags::ZAPPED)
2027 return;
2028 //Must be expanded: Let us call on any (initialised) children instead.
2029 if (handle->nChildren()==0||!handle->childrenAreInitialised())
2030 return;
2031 VolumeHandle::VolumeHandleListItr it(handle->childrenBegin()), itE(handle->childrenEnd());
2032 for(;it!=itE;++it)
2034
2035}
2036
2037//_____________________________________________________________________________________
2039{
2041 messageVerbose("Action on volumes with non-standard VRML representations. Target state is "+VP1GeoFlags::toString(target));
2042
2043 std::vector<std::pair<VolumeHandle::VolumeHandleListItr,VolumeHandle::VolumeHandleListItr> > roothandles;
2044 m_d->volumetreemodel->getRootHandles(roothandles);
2046
2047 bool save = m_d->sceneroot->enableNotify(false);
2048 m_d->phisectormanager->largeChangesBegin();
2049
2050 deselectAll();
2051
2052 for (unsigned i = 0; i<roothandles.size();++i) {
2053 it = roothandles.at(i).first;
2054 itE = roothandles.at(i).second;
2055 for(;it!=itE;++it) {
2056 m_d->changeStateOfVisibleNonStandardVolumesRecursively(*it,target);
2057 }
2058 }
2059
2060 m_d->phisectormanager->updateRepresentationsOfVolsAroundZAxis();
2061 m_d->phisectormanager->largeChangesEnd();
2062 if (save) {
2063 m_d->sceneroot->enableNotify(true);
2064 m_d->sceneroot->touch();
2065 }
2066}
2067
2068//_____________________________________________________________________________________
2069void VP1GeometrySystem::autoExpandByVolumeOrMaterialName(bool bymatname,const QString& targetname)
2070{
2071 if (targetname.isEmpty()) {
2072 VP1Msg::messageDebug("targetname is empty.");
2073 return;
2074 }
2075
2076 messageVerbose("Auto expansions of visible volumes requested. Target all volumes with "
2077 +str(bymatname?"material name":"name")+" matching "+targetname);
2078
2079 QRegExp selregexp(targetname,Qt::CaseSensitive,QRegExp::Wildcard);
2080
2081 std::vector<std::pair<VolumeHandle::VolumeHandleListItr,VolumeHandle::VolumeHandleListItr> > roothandles;
2082 m_d->volumetreemodel->getRootHandles(roothandles);
2084
2085 bool save = m_d->sceneroot->enableNotify(false);
2086 m_d->phisectormanager->largeChangesBegin();
2087
2088 deselectAll();
2089
2090 for (unsigned i = 0; i<roothandles.size();++i) {
2091 it = roothandles.at(i).first;
2092 itE = roothandles.at(i).second;
2093 for(;it!=itE;++it)
2094 m_d->expandVisibleVolumesRecursively(*it,selregexp,bymatname);
2095 }
2096
2097 m_d->phisectormanager->updateRepresentationsOfVolsAroundZAxis();
2098 m_d->phisectormanager->largeChangesEnd();
2099 if (save) {
2100 m_d->sceneroot->enableNotify(true);
2101 m_d->sceneroot->touch();
2102 }
2103}
2104
2105//_____________________________________________________________________________________
2106void VP1GeometrySystem::Imp::expandVisibleVolumesRecursively(VolumeHandle* handle,const QRegExp& selregexp,bool bymatname)
2107{
2108 if (handle->state()==VP1GeoFlags::ZAPPED)
2109 return;
2110 if (handle->state()==VP1GeoFlags::CONTRACTED) {
2111 //See if we match (and have children) - if so, update state.
2112 if (handle->nChildren()>0
2113 && selregexp.exactMatch(bymatname?QString(handle->geoMaterial()->getName().c_str()):handle->getName())) {
2114 handle->setState(VP1GeoFlags::EXPANDED);
2115 }
2116 return;
2117 }
2118 //Must be expanded: Let us call on any (initialised) children instead.
2119 if (handle->nChildren()==0||!handle->childrenAreInitialised())
2120 return;
2121 VolumeHandle::VolumeHandleListItr it(handle->childrenBegin()), itE(handle->childrenEnd());
2122 for(;it!=itE;++it)
2123 expandVisibleVolumesRecursively(*it,selregexp,bymatname);
2124}
2125
2126//_____________________________________________________________________________________
2127void VP1GeometrySystem::Imp::iconifyVisibleVolumesRecursively(VolumeHandle* handle,const QRegExp& selregexp,bool bymatname)
2128{
2129 if (handle->state()==VP1GeoFlags::ZAPPED)
2130 return;
2131
2132 if (handle->state()==VP1GeoFlags::CONTRACTED) {
2133 //See if we match -- if so, update state.
2134 if( selregexp.exactMatch(bymatname?QString(handle->geoMaterial()->getName().c_str()):handle->getName())) {
2135 handle->setState(VP1GeoFlags::ZAPPED);
2136 }
2137 return;
2138 }
2139 //Must be expanded: Let us call on any (initialised) children instead.
2140 if (handle->nChildren()==0||!handle->childrenAreInitialised())
2141 return;
2142 VolumeHandle::VolumeHandleListItr it(handle->childrenBegin()), itE(handle->childrenEnd());
2143 for(;it!=itE;++it)
2144 iconifyVisibleVolumesRecursively(*it,selregexp,bymatname);
2145}
2146
2147
2148//_____________________________________________________________________________________
2149void VP1GeometrySystem::autoIconifyByVolumeOrMaterialName(bool bymatname,const QString& targetname)
2150{
2151 if (targetname.isEmpty()) {
2152 VP1Msg::messageDebug("targetname is empty.");
2153 return;
2154 }
2155
2156 messageVerbose("Auto iconification/zapping of visible volumes requested. Target all volumes with "
2157 +str(bymatname?"material name":"name")+" matching "+targetname);
2158
2159 QRegExp selregexp(targetname,Qt::CaseSensitive,QRegExp::Wildcard);
2160
2161 std::vector<std::pair<VolumeHandle::VolumeHandleListItr,VolumeHandle::VolumeHandleListItr> > roothandles;
2162 m_d->volumetreemodel->getRootHandles(roothandles);
2164
2165 bool save = m_d->sceneroot->enableNotify(false);
2166 m_d->phisectormanager->largeChangesBegin();
2167
2168 deselectAll();
2169
2170 for (unsigned i = 0; i<roothandles.size();++i) {
2171 it = roothandles.at(i).first;
2172 itE = roothandles.at(i).second;
2173 for(;it!=itE;++it)
2174 m_d->iconifyVisibleVolumesRecursively(*it,selregexp,bymatname);
2175 }
2176
2177 m_d->phisectormanager->updateRepresentationsOfVolsAroundZAxis();
2178 m_d->phisectormanager->largeChangesEnd();
2179 if (save) {
2180 m_d->sceneroot->enableNotify(true);
2181 m_d->sceneroot->touch();
2182 }
2183}
2184#ifndef BUILDVP1LIGHT
2185//_____________________________________________________________________________________
2187{
2188 if (!elem)
2189 return;
2190 GeoPVConstLink pvlink = elem->getMaterialGeom()->getParent();
2191 const MuonGM::MuonStation * station = elem->parentMuonStation();
2192 if (!station) {
2193 theclass->message("WARNING: Ignored null station pointer");
2194 return;
2195 }
2196 pv2MuonStation[pvlink] = station;
2197}
2198
2199//_____________________________________________________________________________________
2201{
2202 if (pv2MuonStationInit) {
2203 VP1Msg::messageDebug("MuonStation map already initialized.");
2204 return;
2205 }
2206 pv2MuonStationInit = true;
2207 theclass->messageVerbose("Initializing physical volume link -> MuonStation map.");
2208
2210 if (!mgr) {
2211 VP1Msg::message("WARNING: Could not get muon detector manager to construct volume -> muon station map!");
2212 return;
2213 }
2214 if (mgr->nMdtRE()) {
2215 for (auto det_el = mgr->mdtIdHelper()->detectorElement_begin();
2216 det_el != mgr->mdtIdHelper()->detectorElement_end(); ++det_el) {
2217 updatePV2MuonStationMap(mgr->getMdtReadoutElement(*det_el));
2218 }
2219 }
2220 if (mgr->nRpcRE()) {
2221 for (auto det_el = mgr->rpcIdHelper()->detectorElement_begin();
2222 det_el != mgr->rpcIdHelper()->detectorElement_end(); ++det_el) {
2223 updatePV2MuonStationMap(mgr->getRpcReadoutElement(*det_el));
2224 }
2225 }
2226 if (mgr->nCscRE()) {
2227 for (auto det_el = mgr->cscIdHelper()->detectorElement_begin();
2228 det_el != mgr->cscIdHelper()->detectorElement_end(); ++det_el) {
2229 updatePV2MuonStationMap(mgr->getCscReadoutElement(*det_el));
2230 }
2231 }
2232 if (mgr->nTgcRE()) {
2233 for (auto det_el = mgr->tgcIdHelper()->detectorElement_begin();
2234 det_el != mgr->tgcIdHelper()->detectorElement_end(); ++det_el) {
2235 updatePV2MuonStationMap(mgr->getTgcReadoutElement(*det_el));
2236 }
2237 }
2238
2239 VP1Msg::messageDebug("Initialised physical volume link -> MuonStation map. Found "+str(pv2MuonStation.size())+" stations.");
2240
2241}
2242
2243//_____________________________________________________________________________________
2245{
2246 QStringList l;
2247 if (!station) {
2248 l <<"Null ptr!";
2249 return l;
2250 }
2251 l << "Name: "+str(station->getStationName().c_str());
2252 l << "(Eta,Phi) index: ("+str(station->getEtaIndex())+", "+str(station->getPhiIndex())+")";
2253 return l;
2254}
2255#endif
2256
2257//_____________________________________________________________________________________
2258void VP1GeometrySystem::autoAdaptPixelsOrSCT(bool pixel,bool brl, bool ecA, bool ecC, bool bcmA, bool bcmC)
2259{
2260 #ifndef BUILDVP1LIGHT
2262 return;
2263 #endif
2264 //VP1GeoFlags::SubSystemFlag subSysFlag( pixel ? VP1GeoFlags::Pixel : VP1GeoFlags::SCT );
2266
2267 bool bcm(bcmA||bcmC);
2268 bool ec(ecA||ecC);
2269
2271 //Find subsystem:
2272 Imp::SubSystemInfo* subsys(0);
2273 for (Imp::SubSystemInfo*si : m_d->subsysInfoList) {
2274 if (si->flag == subSysFlag) {
2275 subsys = si;
2276 break;
2277 }
2278 }
2279 if (!subsys) {
2280 message("AutoAdaptPixelsOrSCT Error: Could not find subsystem");
2281 return;
2282 }
2283
2284
2286 //Abort if corresponding subsystem is not built:
2287 if (!subsys->isbuilt) {
2288 VP1Msg::messageDebug("AutoAdaptPixelsOrSCT: Aborting since subsystem geometry not built yet");
2289 return;//Disabling now due to phi-sector problems if "click some phi sectors"->"adapt pixel"->"turn on pixel"
2290 }
2291 bool save = m_d->sceneroot->enableNotify(false);
2292 m_d->phisectormanager->largeChangesBegin();
2293 VolumeHandle::VolumeHandleListItr it(subsys->vollist.begin()),itE(subsys->vollist.end());
2294
2295 if (pixel) {
2296 // --> Pixel
2297 for (;it!=itE;++it) {
2298 (*it)->initialiseChildren();
2299 (*it)->setState(VP1GeoFlags::CONTRACTED);
2300 VolumeHandle::VolumeHandleListItr itChl((*it)->childrenBegin()),itChlE((*it)->childrenEnd());
2301 for (;itChl!=itChlE;++itChl) {
2302 bool unzap(false);
2303 (*itChl)->setState(VP1GeoFlags::ZAPPED);
2305 if (brl&&(*itChl)->hasName("barrelLog")) {
2306 unzap = true;
2307 m_d->showPixelModules(*itChl);
2308 } else if ((ec)&&(*itChl)->hasName("EndCapLog")) {
2309 if (((*itChl)->isPositiveZ()?ecA:ecC)) {
2310 m_d->showPixelModules(*itChl);
2311 unzap = true;
2312 }
2313 } else if (bcm&&(*itChl)->hasName("bcmModLog")) {
2314 if (((*itChl)->isPositiveZ()?bcmA:bcmC)) {
2315 (*itChl)->reset();
2316 (*itChl)->setState(VP1GeoFlags::EXPANDED);
2317 }
2318 }
2319 } else {
2320 if ((*itChl)->hasName("ITkPixelDetector")) {
2321 m_d->showITkPixelModules(*itChl, brl, ecA, ecC);
2322 unzap = true;
2323 }
2324 }
2325 if (unzap)
2326 (*itChl)->setState(VP1GeoFlags::EXPANDED);
2327 }
2328 (*it)->setState(VP1GeoFlags::EXPANDED);
2329 }
2330 } else {
2331 // --> SCT
2332 for (;it!=itE;++it) {
2333 (*it)->initialiseChildren();
2334 (*it)->setState(VP1GeoFlags::CONTRACTED);
2335 bool unzap(false);
2336 (*it)->setState(VP1GeoFlags::ZAPPED);
2338 if (brl&&(*it)->hasName("SCT_Barrel")) {
2339 unzap = true;
2340 m_d->showSCTBarrelModules(*it);
2341 } else if (ecA&&(*it)->hasName("SCT_ForwardA")) {
2342 unzap = true;
2343 m_d->showSCTEndcapModules(*it);
2344 } else if (ecC&&(*it)->hasName("SCT_ForwardC")) {
2345 unzap = true;
2346 m_d->showSCTEndcapModules(*it);
2347 }
2348 } else {
2349 m_d->showITkStripModules(*it, brl, ecA, ecC);
2350 unzap=true;
2351 }
2352 if (unzap)
2353 (*it)->setState(VP1GeoFlags::EXPANDED);
2354 }
2355 }
2356 m_d->phisectormanager->updateRepresentationsOfVolsAroundZAxis();
2357 m_d->phisectormanager->largeChangesEnd();
2358 if (save) {
2359 m_d->sceneroot->enableNotify(true);
2360 m_d->sceneroot->touch();
2361 }
2362}
2363
2364
2365//_____________________________________________________________________________________
2366void VP1GeometrySystem::autoAdaptMuonNSW(bool reset, bool stgc, bool mm, bool passiveSpacer, bool passiveStructure,bool passiveAPlate)
2367{
2368 VP1Msg::messageDebug("VP1GeometrySystem::autoAdaptMuonNSW()");
2369
2370 #ifndef BUILDVP1LIGHT
2371 // return if Muon and MuonNSW are not configured/present/ON
2373 return;
2374 #endif
2375
2376 if( reset )
2377 VP1Msg::messageDebug("resetting to full NSW...");
2378
2380
2382 //Find subsystem:
2383 Imp::SubSystemInfo* subsys(0);
2384 for (Imp::SubSystemInfo*si : m_d->subsysInfoList) {
2385 if (si->flag == subSysFlag) {
2386 subsys = si;
2387 break;
2388 }
2389 }
2390 if (!subsys) {
2391 message("autoAdaptMuonNSW Error: Could not find subsystem");
2392 return;
2393 }
2394
2395
2397 //Abort if corresponding subsystem is not built:
2398 if (!subsys->isbuilt) {
2399 VP1Msg::messageDebug("autoAdaptMuonNSW: Aborting since subsystem geometry not built yet");
2400 return;//Disabling now due to phi-sector problems if "click some phi sectors"->"adapt pixel"->"turn on pixel"
2401 }
2402 bool save = m_d->sceneroot->enableNotify(false);
2403 m_d->phisectormanager->largeChangesBegin();
2404
2405 VolumeHandle::VolumeHandleListItr it(subsys->vollist.begin()),itE(subsys->vollist.end());
2406
2407 // loop over first level children (i.e., 'NewSmallWheel')
2408 for (;it!=itE;++it) {
2409
2410 (*it)->initialiseChildren();
2411 (*it)->setState(VP1GeoFlags::CONTRACTED);
2412 VolumeHandle::VolumeHandleListItr itChl((*it)->childrenBegin()),itChlE((*it)->childrenEnd());
2413
2414 // loop over second level children (i.e., 'NSW_sTGC', 'NSW_MM')
2415 for (;itChl!=itChlE;++itChl) {
2416
2417 bool unzap( reset? true : false );
2418
2419 if ( !reset ) {
2420 (*itChl)->setState(VP1GeoFlags::ZAPPED);
2421 if ( (stgc) && (*itChl)->hasName("NSW_sTGC") ) {
2422 unzap = true;
2423 //m_d->showPixelModules(*itChl);
2424 } else if ( (mm) && (*itChl)->hasName("NSW_MM") ) {
2425 unzap = true;
2426 //m_d->showPixelModules(*itChl);
2427 } else if ( (passiveSpacer) && (*itChl)->hasName("NSW_Spacer") ) {
2428 unzap = true;
2429 } else if ( (passiveStructure) && (*itChl)->hasName("NSW_Aluminum_Structure_and_HUB") ) {
2430 unzap = true;
2431 } else if ( (passiveAPlate) && (*itChl)->hasName("A_Plate") ) {
2432 unzap = true;
2433 }
2434 }
2435 if (unzap) {
2436 (*itChl)->setState(VP1GeoFlags::EXPANDED);
2437 }
2438 }
2439 (*it)->setState(VP1GeoFlags::EXPANDED);
2440 }
2441
2442 m_d->phisectormanager->updateRepresentationsOfVolsAroundZAxis();
2443 m_d->phisectormanager->largeChangesEnd();
2444
2445 if (save) {
2446 m_d->sceneroot->enableNotify(true);
2447 m_d->sceneroot->touch();
2448 }
2449}
2450
2451
2452//_____________________________________________________________________________________
2453void VP1GeometrySystem::autoAdaptHGTD(bool reset, bool flex, bool hybrid, bool glue, bool sensors, bool inactive, bool asic, bool supportPlate, bool frontCover, bool backCover, bool moderatorIn, bool moderatorOut, bool outerRCover, bool coolingLines)
2454{
2455 VP1Msg::messageDebug("VP1GeometrySystem::autoAdaptHGTD()");
2456
2457 #ifndef BUILDVP1LIGHT
2459 return;
2460 #endif
2461
2462 if( reset )
2463 VP1Msg::messageDebug("resetting to full HGTD...");
2464
2466
2468 //Find subsystem:
2469 Imp::SubSystemInfo* subsys(0);
2470 for (Imp::SubSystemInfo*si : m_d->subsysInfoList) {
2471 if (si->flag == subSysFlag) {
2472 subsys = si;
2473 break;
2474 }
2475 }
2476 if (!subsys) {
2477 message("autoAdaptHGTD Error: Could not find subsystem");
2478 return;
2479 }
2480
2482 //Abort if corresponding subsystem is not built:
2483 if (!subsys->isbuilt) {
2484 VP1Msg::messageDebug("autoAdaptHGTD: Aborting since subsystem geometry not built yet");
2485 return;
2486 }
2487
2488 bool save = m_d->sceneroot->enableNotify(false);
2489 m_d->phisectormanager->largeChangesBegin();
2490
2491 for (VolumeHandle* volume : subsys->vollist) {
2492 if (reset) {
2493 volume->reset();
2495 } else {
2497 handles.push_back(volume);
2498
2499 for (unsigned i = 0; i < handles.size(); ++i) {
2500 handles.at(i)->initialiseChildren();
2501 for (VolumeHandle* child : std::ranges::subrange(
2502 handles.at(i)->childrenBegin(), handles.at(i)->childrenEnd()))
2503 handles.push_back(child);
2504 }
2505
2506 for (VolumeHandle* handle : handles)
2507 handle->setState(VP1GeoFlags::ZAPPED);
2508
2509 bool unzap(false);
2510 for (VolumeHandle* handle : handles) {
2511 const QString name = handle->getName();
2512 bool selected(false);
2513 if (flex && (name=="HGTDFlexPackage" || name.startsWith("HGTDFlexTube"))) {
2514 selected = true;
2515 } else if (hybrid && name=="HGTDHybrid") {
2516 selected = true;
2517 } else if (glue && (name=="HGTDGlueSensor" || name=="HGTDGlueAsic")) {
2518 selected = true;
2519 } else if (sensors && name.startsWith("HGTDSiSensor")) {
2520 selected = true;
2521 } else if (inactive && name=="HGTDLGADInactive") {
2522 selected = true;
2523 } else if (asic && name=="HGTDASIC") {
2524 selected = true;
2525 } else if (supportPlate && name=="HGTDSupportPlate") {
2526 selected = true;
2527 } else if (frontCover && name=="HGTDFrontCover") {
2528 selected = true;
2529 } else if (backCover && name=="HGTDBackCover") {
2530 selected = true;
2531 } else if (moderatorIn && name=="HGTDModeratorIn") {
2532 selected = true;
2533 } else if (moderatorOut && name=="HGTDModeratorOut") {
2534 selected = true;
2535 } else if (outerRCover && name=="HGTDOuterRCover") {
2536 selected = true;
2537 } else if (coolingLines && name=="HGTDPeripheralCoolingLines") {
2538 selected = true;
2539 }
2540
2541 if (selected) {
2542 unzap = true;
2543 handle->setState(VP1GeoFlags::CONTRACTED);
2544 VolumeHandle* parent = handle->parent();
2545 while (parent) {
2546 parent->setState(VP1GeoFlags::EXPANDED);
2547 parent = parent->parent();
2548 }
2549 }
2550 }
2551 if (!unzap)
2553 }
2554 }
2555
2556 m_d->phisectormanager->updateRepresentationsOfVolsAroundZAxis();
2557 m_d->phisectormanager->largeChangesEnd();
2558
2559 if (save) {
2560 m_d->sceneroot->enableNotify(true);
2561 m_d->sceneroot->touch();
2562 }
2563}
2564
2565
2566
2567
2568//_____________________________________________________________________________________
2570{
2571 VP1Msg::messageDebug("VP1GeometrySystem::Imp::showPixelModules()");
2572 h->initialiseChildren();
2573 VolumeHandle::VolumeHandleListItr it(h->childrenBegin()),itE(h->childrenEnd());
2574 for (;it!=itE;++it) {
2575 if ((*it)->hasName("moduleLog")) {
2576 (*it)->setState(VP1GeoFlags::ZAPPED);
2577 (*it)->contractDaughtersRecursively();
2578 (*it)->initialiseChildren();
2579 VolumeHandle::VolumeHandleListItr itMod((*it)->childrenBegin()),itModE((*it)->childrenEnd());
2580 for (;itMod!=itModE;++itMod) {
2581 if ((*itMod)->getName().startsWith("si"))
2582 (*itMod)->setState(VP1GeoFlags::CONTRACTED);
2583 else
2584 (*itMod)->setState(VP1GeoFlags::ZAPPED);
2585 }
2586 (*it)->setState(VP1GeoFlags::EXPANDED);
2587 continue;
2588 }
2589 if ((*it)->hasName("pigtailLog")||(*it)->hasName("omegaLog")) {
2590 (*it)->setState(VP1GeoFlags::ZAPPED);
2591 (*it)->contractDaughtersRecursively();
2592 continue;
2593 }
2594 if ((*it)->nChildren()<1) {
2595 (*it)->setState(VP1GeoFlags::ZAPPED);
2596 continue;
2597 }
2598 (*it)->setState(VP1GeoFlags::ZAPPED);
2599 showPixelModules(*it);
2600 (*it)->setState(VP1GeoFlags::EXPANDED);
2601 }
2602}
2603
2604void VP1GeometrySystem::Imp::expandAllChildren(VolumeHandle* h, bool isPixel, bool brl, bool ecA, bool ecC) {
2605
2606 if (h->nChildren()==0) {
2607 if (isPixel and (ecA or ecC)) {
2608 float translation_x, translation_y, translation_z, rotaxis_x, rotaxis_y, rotaxis_z, rotangle_radians;
2609 VP1LinAlgUtils::decodeTransformation( h->getGlobalTransformToVolume(),
2610 translation_x, translation_y, translation_z,
2611 rotaxis_x, rotaxis_y, rotaxis_z, rotangle_radians );
2612 if ((!ecA || !ecC) && ((ecA and (translation_z<0.)) or (ecC and (translation_z>0.) ))) {
2613 h->setState(VP1GeoFlags::ZAPPED);
2614 return;
2615 }
2616 }
2617
2618 // check if you have to select it
2619 std::vector< std::string > selected_volumes = {};
2620 if (brl) {
2621 if (isPixel) {
2622 selected_volumes.push_back("InnerBarrelSingleMod_Sensor");
2623 selected_volumes.push_back("InnerBarrelQuadMod_Sensor");
2624 selected_volumes.push_back("OuterBarrelQuadMod_Sensor");
2625 selected_volumes.push_back("LongeronCoolingTube");
2626 selected_volumes.push_back("InnerPixBarrelSupport_Stave");
2627 selected_volumes.push_back("InnerPixBarrelSupport_Stave1");
2628 selected_volumes.push_back("LongeronCornerBase");
2629 selected_volumes.push_back("LongeronCornerEnd");
2630 selected_volumes.push_back("LongeronTrussWall");
2631 selected_volumes.push_back("LongeronCapBase");
2632 selected_volumes.push_back("LongeronTopCap");
2633
2634 } else {
2635 selected_volumes.push_back("BRLSensorSS");
2636 selected_volumes.push_back("BRLSensorMS");
2637 selected_volumes.push_back("B_HybridPCB");
2638 selected_volumes.push_back("DCDC_PCB");
2639 selected_volumes.push_back("DCDC_Box");
2640 selected_volumes.push_back("Bex_HybridPCB_near");
2641 selected_volumes.push_back("Bex_HybridPCB_far");
2642 }
2643 }
2644 if (ecA or ecC) {
2645 if (isPixel) {
2646 selected_volumes.push_back("InclinedQuadMod_Sensor");
2647 selected_volumes.push_back("InnerRingSingleMod_Sensor");
2648 selected_volumes.push_back("InnerEndcapQuadMod_Sensor");
2649 selected_volumes.push_back("OuterEndcapQuadMod_Sensor");
2650 selected_volumes.push_back("L2HalfRingCoolingPipe");
2651 selected_volumes.push_back("L3HalfRingCoolingPipe");
2652 selected_volumes.push_back("L4endcapcoolingpipe");
2653 selected_volumes.push_back("InclL2HalfShell");
2654 selected_volumes.push_back("InclL2Support");
2655 selected_volumes.push_back("InclL3HalfShell");
2656 selected_volumes.push_back("InclL3Support");
2657 selected_volumes.push_back("InclL4HalfShell");
2658 selected_volumes.push_back("InclL4Support");
2659 selected_volumes.push_back("InnerPixEndcap_CoupledRingSupport");
2660 selected_volumes.push_back("InnerPixEndcap_IntermediateRingSupport");
2661 selected_volumes.push_back("InnerPixEndcap_L1RingSupport");
2662 selected_volumes.push_back("L2HalfRingCarbonFoamInner");
2663 selected_volumes.push_back("L2HalfRingCarbonFoamOuter");
2664 selected_volumes.push_back("L2HalfRingFaceSheet");
2665 selected_volumes.push_back("L3HalfRingCarbonFoamInner");
2666 selected_volumes.push_back("L3HalfRingCarbonFoamOuter");
2667 selected_volumes.push_back("L3HalfRingFaceSheet");
2668 selected_volumes.push_back("L4endcapinnerCarbonFoam");
2669 selected_volumes.push_back("L4endcapouterCarbonFoam");
2670 selected_volumes.push_back("L4endcapFaceSheet");
2671 selected_volumes.push_back("L2HalfShell");
2672 selected_volumes.push_back("L3HalfShell");
2673 selected_volumes.push_back("L4HalfShell");
2674 } else {
2675 selected_volumes.push_back("ECSensor0");
2676 selected_volumes.push_back("ECSensor1");
2677 selected_volumes.push_back("ECSensor2");
2678 selected_volumes.push_back("ECSensor3");
2679 selected_volumes.push_back("ECSensor4");
2680 selected_volumes.push_back("ECSensor5");
2681 selected_volumes.push_back("ECSensorBack0");
2682 selected_volumes.push_back("ECSensorBack1");
2683 selected_volumes.push_back("ECSensorBack2");
2684 selected_volumes.push_back("ECSensorBack3");
2685 selected_volumes.push_back("ECSensorBack4");
2686 selected_volumes.push_back("ECSensorBack5");
2687 }
2688 }
2689
2690 std::string name = h->getName().toStdString();
2691
2692 if (not isPixel and (ecA or ecC)) {
2693 // check servises in the endcap
2694 if (name.starts_with("ECHybrid") or name.starts_with("DCDC_EC"))
2695 return;
2696 }
2697
2698 if (std::find(selected_volumes.begin(), selected_volumes.end(), name) == selected_volumes.end()) {
2699 h->setState(VP1GeoFlags::ZAPPED);
2700 return;
2701 }
2702 return;
2703 } else if (not isPixel and (h->getName().toStdString()=="PetalCore" or
2704 h->getName().toStdString()=="StaveCoreSS" or
2705 h->getName().toStdString() =="StaveCoreMS")) {
2706 return;
2707 }
2708 h->initialiseChildren();
2709
2710 h->setState(VP1GeoFlags::EXPANDED);
2711 VolumeHandle::VolumeHandleListItr it(h->childrenBegin()),itE(h->childrenEnd());
2712 for (;it!=itE;++it) {
2713 expandAllChildren(*it, isPixel, brl, ecA, ecC);
2714 }
2715}
2716
2718{
2719 VP1Msg::messageDebug("VP1GeometrySystem::Imp::showITkPixelModules()");
2720 h->initialiseChildren();
2721 VolumeHandle::VolumeHandleListItr it(h->childrenBegin()),itE(h->childrenEnd());
2722 // std::cout << "Processing volume with name = " << h->getName().toStdString() << " and " << h->nChildren() << " children..." << std::endl;
2723 for (;it!=itE;++it) {
2724 expandAllChildren(*it, true, brl, ecA, ecC);
2725 }
2726}
2727
2728
2730{
2731 VP1Msg::messageDebug("VP1GeometrySystem::Imp::showITkStripModules()");
2732 h->initialiseChildren();
2733 VolumeHandle::VolumeHandleListItr it(h->childrenBegin()),itE(h->childrenEnd());
2734 // std::cout << "Processing volume with name = " << h->getName().toStdString() << " and " << h->nChildren() << " children..." << std::endl;
2735 for (;it!=itE;++it) {
2736 if (brl and (*it)->hasName("ITkStrip_Barrel")) {
2737 expandAllChildren(*it, false, brl, ecA, ecC);
2738 }
2739 else if (ecA and (*it)->hasName("ITkStrip_ForwardPlus")) {
2740 expandAllChildren(*it, false, brl, ecA, ecC);
2741 }
2742 else if (ecC and (*it)->hasName("ITkStrip_ForwardMinus")) {
2743 expandAllChildren(*it, false, brl, ecA, ecC);
2744 } else
2745 (*it)->setState(VP1GeoFlags::ZAPPED);
2746 }
2747}
2748
2749//_____________________________________________________________________________________
2751{
2752 VP1Msg::messageDebug("VP1GeometrySystem::Imp::showSCTBarrelModules()");
2753 h->initialiseChildren();
2754 VolumeHandle::VolumeHandleListItr it(h->childrenBegin()),itE(h->childrenEnd());
2755 for (;it!=itE;++it) {
2756 if ((*it)->getName().startsWith("Layer")) {
2757 (*it)->setState(VP1GeoFlags::ZAPPED);
2758 (*it)->initialiseChildren();
2759 VolumeHandle::VolumeHandleListItr itLay((*it)->childrenBegin()),itLayE((*it)->childrenEnd());
2760 for (;itLay!=itLayE;++itLay) {
2761 if ((*itLay)->getName().endsWith("Active")&&(*itLay)->getName().startsWith("Layer")) {
2762 (*itLay)->setState(VP1GeoFlags::ZAPPED);
2763 (*itLay)->initialiseChildren();
2764 VolumeHandle::VolumeHandleListItr itActLay((*itLay)->childrenBegin()),itActLayE((*itLay)->childrenEnd());
2765 for (;itActLay!=itActLayE;++itActLay) {
2766 if ((*itActLay)->getName().startsWith("Ski")) {
2767 (*itActLay)->setState(VP1GeoFlags::ZAPPED);
2768 (*itActLay)->initialiseChildren();
2769 VolumeHandle::VolumeHandleListItr itSki((*itActLay)->childrenBegin()),itSkiE((*itActLay)->childrenEnd());
2770 for (;itSki!=itSkiE;++itSki) {
2771 //Ends with "Envelope": open, otherwise zap. Of those, zap all without "Sensor" in the name.
2772 if ((*itSki)->hasName("Module")) {
2773 //Open and zap those without "Sensor" in the name:
2774 (*itSki)->setState(VP1GeoFlags::ZAPPED);
2775 (*itSki)->initialiseChildren();
2776 VolumeHandle::VolumeHandleListItr itMod((*itSki)->childrenBegin()),itModE((*itSki)->childrenEnd());
2777 for (;itMod!=itModE;++itMod) {
2778 if ((*itMod)->getName().contains("Envelope")) {
2779 (*itMod)->setState(VP1GeoFlags::ZAPPED);
2780 (*itMod)->initialiseChildren();
2781 VolumeHandle::VolumeHandleListItr itEnv((*itMod)->childrenBegin()),itEnvE((*itMod)->childrenEnd());
2782 for(;itEnv!=itEnvE;++itEnv) {
2783 if ((*itEnv)->getName().contains("Sensor"))
2784 (*itEnv)->reset();
2785 else
2786 (*itEnv)->setState(VP1GeoFlags::ZAPPED);
2787 }
2788 (*itMod)->setState(VP1GeoFlags::EXPANDED);
2789 } else {
2790 (*itMod)->setState(VP1GeoFlags::ZAPPED);
2791 }
2792 }
2793 (*itSki)->setState(VP1GeoFlags::EXPANDED);
2794 } else {
2795 (*itSki)->setState(VP1GeoFlags::ZAPPED);
2796 }//end if-elsi "Envelope"
2797 }//endfor itSki
2798 (*itActLay)->setState(VP1GeoFlags::EXPANDED);
2799 } else {
2800 (*itActLay)->setState(VP1GeoFlags::ZAPPED);
2801 }//end if-else "Ski"
2802 }
2803 (*itLay)->setState(VP1GeoFlags::EXPANDED);
2804 } else {
2805 (*itLay)->setState(VP1GeoFlags::ZAPPED);
2806 (*itLay)->contractDaughtersRecursively();
2807 }
2808 }
2809 (*it)->setState(VP1GeoFlags::EXPANDED);
2810 } else {
2811 (*it)->setState(VP1GeoFlags::ZAPPED);
2812 (*it)->contractDaughtersRecursively();
2813 }
2814 }
2815}
2816
2817//_____________________________________________________________________________________
2819{
2820 VP1Msg::messageDebug("VP1GeometrySystem::Imp::showSCTEndcapModules()");
2821 h->initialiseChildren();
2822 VolumeHandle::VolumeHandleListItr it(h->childrenBegin()),itE(h->childrenEnd());
2823 for (;it!=itE;++it) {
2824 if ((*it)->getName().startsWith("Wheel")) {
2825 (*it)->setState(VP1GeoFlags::ZAPPED);
2826 (*it)->initialiseChildren();
2827 VolumeHandle::VolumeHandleListItr itWhl((*it)->childrenBegin()),itWhlE((*it)->childrenEnd());
2828 for (;itWhl!=itWhlE;++itWhl) {
2829 if ((*itWhl)->getName().startsWith("Ring")) {
2830 (*itWhl)->setState(VP1GeoFlags::ZAPPED);
2831 (*itWhl)->initialiseChildren();
2832 VolumeHandle::VolumeHandleListItr itRng((*itWhl)->childrenBegin()),itRngE((*itWhl)->childrenEnd());
2833 for (;itRng!=itRngE;++itRng) {
2834 if ((*itRng)->getName().startsWith("FwdModule")) {
2835 (*itRng)->setState(VP1GeoFlags::ZAPPED);
2836 (*itRng)->initialiseChildren();
2837 VolumeHandle::VolumeHandleListItr itMod((*itRng)->childrenBegin()),itModE((*itRng)->childrenEnd());
2838 for(;itMod!=itModE;++itMod) {
2839 if ((*itMod)->getName().startsWith("ECSensor")) {
2840 (*itMod)->reset();
2841 } else {
2842 (*itMod)->setState(VP1GeoFlags::ZAPPED);
2843 }
2844 }
2845 (*itRng)->setState(VP1GeoFlags::EXPANDED);
2846 } else {
2847 (*itRng)->setState(VP1GeoFlags::ZAPPED);
2848 }
2849 }
2850 (*itWhl)->setState(VP1GeoFlags::EXPANDED);
2851 } else {
2852 (*itWhl)->setState(VP1GeoFlags::ZAPPED);
2853 (*itWhl)->contractDaughtersRecursively();
2854 }
2855 }
2856 (*it)->setState(VP1GeoFlags::EXPANDED);
2857 } else {
2858 (*it)->setState(VP1GeoFlags::ZAPPED);
2859 (*it)->contractDaughtersRecursively();
2860 }
2861 }
2862}
2863
2864//_____________________________________________________________________________________
2866{
2867 //might not use this slot presently...
2868 if (!vh)
2869 return;
2870 deselectAll();
2871 vh->setState(state);
2872 m_d->phisectormanager->updateRepresentationsOfVolsAroundZAxis();
2873}
2874
2875//_____________________________________________________________________________________
2877{
2878 if (!vh)
2879 return;
2880 deselectAll();
2881 vh->reset();
2882 m_d->phisectormanager->updateRepresentationsOfVolsAroundZAxis();
2883}
2884
2885//_____________________________________________________________________________________
2887{
2888 std::map<SoSeparator*,VolumeHandle*>::iterator it,itE(m_d->sonodesep2volhandle.end());
2889 for (it =m_d->sonodesep2volhandle.begin();it!=itE;++it)
2891}
2892
2893
2894//_____________________________________________________________________________________
2895void VP1GeometrySystem::saveMaterialsToFile(const QString& filename,bool onlyChangedMaterials)
2896{
2897 if (filename.isEmpty())
2898 return;
2899
2900 //If file exists, ask to overwrite.
2901 QFileInfo fi(filename);
2902 if (fi.exists()) {
2903 if (!fi.isWritable()) {
2904 QMessageBox::critical(0, "Error - could not save to file "+filename,
2905 "Could not save to file: <i>"+filename+"</i>"
2906 +"<br/><br/>Reason: File exists already and is write protected",QMessageBox::Ok,QMessageBox::Ok);
2907 return;
2908 }
2909 }
2910
2911 QFile file(filename);
2912 if (!file.open(QIODevice::WriteOnly)) {
2913 QMessageBox::critical(0, "Error - problems writing to file "+filename,
2914 "Problems writing to file: <i>"+filename+"</i>",QMessageBox::Ok,QMessageBox::Ok);
2915 return;
2916 }
2917
2918 m_d->ensureInitVisAttributes();
2919 VP1Serialise s(0/*version*/,this);
2920 //Save some file ID info!!
2921 s.save(QString("VP1GeoMaterialsBegin"));
2922 s.save(m_d->detVisAttributes->getState(onlyChangedMaterials));
2923 s.save(m_d->matVisAttributes->getState(onlyChangedMaterials));
2924 s.save(m_d->volVisAttributes->getState(onlyChangedMaterials));
2925 s.save(QString("VP1GeoMaterialsEnd"));
2926 s.disableUnsavedChecks();
2927
2928 QDataStream outfile(&file);
2929 outfile<<qCompress(s.result()).toBase64();
2930
2931}
2932
2933//_____________________________________________________________________________________
2934void VP1GeometrySystem::loadMaterialsFromFile(const QString& filename)
2935{
2936 if (filename.isEmpty())
2937 return;
2938 QFileInfo fi(filename);
2939 if (!fi.exists()) {
2940 QMessageBox::critical(0, "Error - file does not exists: "+filename,
2941 "File does not exists: <i>"+filename+"</i>",QMessageBox::Ok,QMessageBox::Ok);
2942 return;
2943 }
2944 if (!fi.isReadable()) {
2945 QMessageBox::critical(0, "Error - file is not readable: "+filename,
2946 "File is not readable: <i>"+filename+"</i>",QMessageBox::Ok,QMessageBox::Ok);
2947 return;
2948 }
2949 //open file
2950 QFile file(filename);
2951 if (!file.open(QIODevice::ReadOnly)) {
2952 QMessageBox::critical(0, "Error - problems opening file "+filename,
2953 "Problems opening file: <i>"+filename+"</i>",QMessageBox::Ok,QMessageBox::Ok);
2954 return;
2955 }
2956 QByteArray byteArray64;
2957 QDataStream infile(&file);
2958 infile >> byteArray64;
2959 QByteArray byteArray = qUncompress(QByteArray::fromBase64(byteArray64));
2960
2961 VP1Deserialise s(byteArray,this);
2962 if (s.version()!=0) {
2963 QMessageBox::critical(0, "Error - File in wrong format "+filename,
2964 "File in wrong format: <i>"+filename+"</i>",QMessageBox::Ok,QMessageBox::Ok);
2965 return;
2966 }
2967 QString txtbegin, txtend;
2968 QByteArray baDet, baMat, baVol;
2969 txtbegin = s.restoreString();
2970 baDet = s.restoreByteArray();
2971 baMat = s.restoreByteArray();
2972 baVol = s.restoreByteArray();
2973 txtend = s.restoreString();
2974 s.disableUnrestoredChecks();
2975 if (txtbegin!="VP1GeoMaterialsBegin"||txtend!="VP1GeoMaterialsEnd") {
2976 QMessageBox::critical(0, "Error - File in wrong format "+filename,
2977 "File in wrong format: <i>"+filename+"</i>",QMessageBox::Ok,QMessageBox::Ok);
2978 return;
2979 }
2980
2981 m_d->ensureInitVisAttributes();
2982 m_d->detVisAttributes->applyState(baDet);
2983 m_d->matVisAttributes->applyState(baMat);
2984 m_d->volVisAttributes->applyState(baVol);
2985
2986 VolumeHandle* lastsel = m_d->controller->lastSelectedVolume();
2987 m_d->controller->setLastSelectedVolume(0);
2988 m_d->controller->setLastSelectedVolume(lastsel);
2989}
2990
2991//____________________________________________________________________
2993{
2994 messageVerbose("setLabelPosOffsets called");
2995 setLabels(m_d->controller->labels());
2996}
2997
2999 messageVerbose("setLabels "+str(i)+" for this many chambers:"+str(m_d->muonchambers_pv2handles.size()));
3000 // loop over all contained volumes (all visible volumes?) and update labels.
3001 // Just muons to start with
3002 std::map<PVConstLink,VolumeHandle*>::const_iterator it = m_d->muonchambers_pv2handles.begin(), itEnd = m_d->muonchambers_pv2handles.end();
3003 for (; it!=itEnd ; ++it){
3004 if (it->second->isInMuonChamber()) it->second->updateLabels(); // currently only do labels for Muon volumes
3005 }
3006}
3007
3009 m_d->controller->setLabelsEnabled(t0s,hits);
3010}
3011
3012void VP1GeometrySystem::muonChamberT0sChanged(const std::map<GeoPVConstLink, float>& t0s, int index){
3013 messageVerbose("muonChamberT0sChanged for this many chambers:"+str(t0s.size()));
3014 if (index>=m_d->chamberT0s.size())
3015 message("ERROR: chamber t0 index out of bounds!");
3016 else
3017 m_d->chamberT0s[index]=&t0s;
3018}
#define M_PI
double length(const pvec &v)
static Double_t ss
#define y
#define x
#define z
Header file for AthHistogramAlgorithm.
static QStringList shapeToStringList(const GeoShape *shape)
Definition DumpShape.cxx:34
GeoPhysVol * getPhysVol()
Destructor.
IVP13DSystemSimple(const QString &name, const QString &information, const QString &contact_info)
virtual void deselectAll(SoCooperativeSelection *exception_sel=0)
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()
The MuonDetectorManager stores the transient representation of the Muon Spectrometer geometry and pro...
Base class for the XxxReadoutElement, with Xxx = Mdt, Rpc, Tgc, Csc.
int getEtaIndex() const
a la AMDB
int getPhiIndex() const
a la AMDB
const std::string & getStationName() const
like BMS5, T1F1, CSL1
The Athena Transient Store API.
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)
static const MuonGM::MuonDetectorManager * muonDetMgr()
@ MuonEndcapStationTGC
Definition VP1GeoFlags.h:47
@ AllUnrecognisedVolumes
Definition VP1GeoFlags.h:73
@ MuonEndcapStationNSW
Definition VP1GeoFlags.h:65
@ MuonBarrelStationInner
Definition VP1GeoFlags.h:42
@ MuonBarrelStationMiddle
Definition VP1GeoFlags.h:44
@ MuonBarrelStationOuter
Definition VP1GeoFlags.h:45
@ MuonEndcapStationCSC
Definition VP1GeoFlags.h:46
@ MuonEndcapStationMDT
Definition VP1GeoFlags.h:49
static QString toString(const VOLSTATE &)
static QStringList geoMaterialToStringList(const GeoMaterial *)
SubSystemInfo(QCheckBox *cb, const QRegExp &the_geomodeltreetopregexp, bool the_negatetreetopregexp, const QRegExp &the_geomodelchildrenregexp, bool the_negatechildrenregexp, VP1GeoFlags::SubSystemFlag the_flag, const std::string &the_matname, const QRegExp &the_geomodelgrandchildrenregexp, bool the_negategrandchildrenregexp=false)
bool grandchildrenRegExpNameCompatible(const std::string &volname) const
bool childrenRegExpNameCompatible(const std::string &volname) const
VolumeHandle::VolumeHandleList vollist
void createPathExtras(const VolumeHandle *, QString &, QStack< QString > &)
void expandAllChildren(VolumeHandle *, bool isPixel, bool brl, bool ecA, bool ecC)
VP1GeometrySystem * theclass
void showSCTEndcapModules(VolumeHandle *)
void expandVisibleVolumesRecursively(VolumeHandle *, const QRegExp &, bool bymatname)
void showITkStripModules(VolumeHandle *, bool brl, bool ecA, bool ecC)
QStringList stationInfo(const MuonGM::MuonStation *)
SubSystemInfo * chamberPVToMuonSubSystemInfo(const GeoPVConstLink &chamberPV)
void addSubSystem(const VP1GeoFlags::SubSystemFlag &, const QString &treetopregexp, const QString &childrenregexp="", const std::string &matname="", bool negatetreetopregexp=false, bool negatechildrenregexp=false, const QString &grandchildrenregexp="", bool negategrandchildrenregexp=false)
QList< SubSystemInfo * > subsysInfoList
VP1GeoFlags::SubSystemFlags initialSubSystemsTurnedOn
void showSCTBarrelModules(VolumeHandle *)
void showPixelModules(VolumeHandle *)
static void catchKbdState(void *userData, SoEventCallback *CB)
void showITkPixelModules(VolumeHandle *, bool brl, bool ecA, bool ecC)
void updateTouchedMuonChamber(VolumeHandle *chamberhandle)
std::map< PVConstLink, VolumeHandle * > muonchambers_pv2handles
SoSeparator * m_textSep
Separator used to hold all visible labels.
PhiSectorManager * phisectormanager
std::pair< SbVec3f, SbVec3f > getClosestMuonDriftTubeDirections(const SbVec3f &cameraDirection, const SbVec3f &cameraUpDirection, VolumeHandle *chamberhandle)
VolumeHandle * previousAlignedChamberHandle
static double volume(const PVConstLink &pv)
void changeStateOfVisibleNonStandardVolumesRecursively(VolumeHandle *, VP1GeoFlags::VOLSTATE)
void buildSystem(SubSystemInfo *)
DetVisAttributes * detVisAttributes
std::map< GeoPVConstLink, const MuonGM::MuonStation * > pv2MuonStation
void updatePV2MuonStationMap(const MuonGM::MuonReadoutElement *elem)
std::map< SoSeparator *, VolumeHandle * > sonodesep2volhandle
static double inclusiveMass(const PVConstLink &pv)
VolVisAttributes * volVisAttributes
void iconifyVisibleVolumesRecursively(VolumeHandle *, const QRegExp &, bool bymatname)
GeoSysController * controller
void applyTopVolStates(const QMap< quint32, QByteArray > &, bool disablenotif=false)
Imp(VP1GeometrySystem *gs, const VP1GeoFlags::SubSystemFlags &ssf)
std::map< QObject *, std::set< GeoPVConstLink > > sender2ChamberList
const SoKeyboardEvent * kbEvent
QList< const std::map< GeoPVConstLink, float > * > chamberT0s
std::pair< SbVec3f, SbVec3f > getClosestCSCOrTGCEdgeDirections(const SbVec3f &cameraDirection, VolumeHandle *chamberhandle)
MatVisAttributes * matVisAttributes
VolumeTreeModel * volumetreemodel
static double exclusiveMass(const PVConstLink &pv)
QMap< quint32, QByteArray > restoredTopvolstates
void buildPermanentSceneGraph(StoreGateSvc *detstore, SoSeparator *root)
void loadMaterialsFromFile(const QString &)
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 userPickedNode(SoNode *pickedNode, SoPath *pickedPath)
void setOrientViewToMuonChambersOnClick(bool)
void autoAdaptMuonNSW(bool reset, bool stgc, bool mm, bool passiveSpacer, bool passiveStructure, bool passiveAPlate)
void setZoomToVolumeOnClick(bool)
void emit_appropriateMDTProjectionsChanged()
void enableMuonChamberLabels(bool, bool)
first is t0s, 2nd is hits
VP1GeometrySystem(const VP1GeoFlags::SubSystemFlags &SubSystemsTurnedOn=VP1GeoFlags::None, const QString &name="Geo")
void orientViewToMuonChamber(const GeoPVConstLink &chamberPV)
void resetSubSystems(VP1GeoFlags::SubSystemFlags)
void autoIconifyByVolumeOrMaterialName(bool, const QString &)
void volumeResetRequested(VolumeHandle *)
void plotSpectrum(QStack< QString > &, int copyNumber=-1)
void autoAdaptPixelsOrSCT(bool, bool, bool, bool, bool, bool)
void autoAdaptHGTD(bool reset, bool flex, bool hybrid, bool glue, bool sensors, bool inactive, bool asic, bool supportPlate, bool frontCover, bool backCover, bool moderatorIn, bool moderatorOut, bool outerRCover, bool coolingLines)
void volumeStateChangeRequested(VolumeHandle *, VP1GeoFlags::VOLSTATE)
void setLabelPosOffsets(const QList< int > &)
void systemcreate(StoreGateSvc *detstore)
void autoExpandByVolumeOrMaterialName(bool, const QString &)
void appropriateMDTProjectionsChanged(int)
void actionOnAllNonStandardVolumes(bool)
void setAutoAdaptMuonChambersToEventData(bool)
void reiconizeToShowSpecificMuonChambers(const std::set< GeoPVConstLink > &)
void saveMaterialsToFile(const QString &, bool)
void restoreFromState(QByteArray)
static bool hasMuonNSWGeometry()
static bool hasGeoModelExperiment()
static bool hasPixelGeometry()
static bool hasSCTGeometry()
static bool hasHGTDGeometry()
static bool hasITkGeometry()
static bool hasMuonGeometry()
static void decodeTransformation(const SbMatrix &, float &translation_x, float &translation_y, float &translation_z, float &rotaxis_x, float &rotaxis_y, float &rotaxis_z, float &rotangle_radians)
static void transformToMatrix(SoTransform *xf, SbMatrix &result)
static bool debug()
Definition VP1Msg.h:32
static void messageDebug(const QString &)
Definition VP1Msg.cxx:39
static void message(const QString &, IVP1System *sys=0)
Definition VP1Msg.cxx:30
static bool changePathTail(SoPath *path, SoNode *commonBranchPoint, SoNode *newtail)
static void setShowVolumeOutlines(SoGroup *nodesep, bool showvol)
void setState(const VP1GeoFlags::VOLSTATE &state)
const SbMatrix & getGlobalTransformToVolume() const
std::string getNameStdString() const
VP1GeoFlags::VOLSTATE state() const
const GeoMaterial * geoMaterial() const
void initialiseChildren()
QString getName() const
VolumeHandleListItr childrenBegin()
SbMatrix getLocalTransformToVolume() const
VolumeHandleListItr childrenEnd()
VolumeHandle * topLevelParent()
void contractDaughtersRecursively()
SoSeparator * nodeSoSeparator() const
std::vector< VolumeHandle * > VolumeHandleList
GeoPVConstLink geoPVConstLink() const
int copyNumber() const
bool isInMuonChamber() const
void setMuonChamberDirty(bool)
virtual QString getDescriptiveName() const
VolumeHandleList::iterator VolumeHandleListItr
VP1GeoFlags::SubSystemFlag subsystem() const
VolumeHandle * parent()
int childNumber() const
unsigned nChildren() const
bool exists(const std::string &filename)
does a file exist
double entries
Definition listroot.cxx:49
HepGeom::Transform3D EigenTransformToCLHEP(const Amg::Transform3D &eigenTransf)
Converts an Eigen-based Amg::Transform3D into a CLHEP-based HepGeom::Transform3D.
path
python interpreter configuration --------------------------------------—
Definition athena.py:130
Definition index.py:1
TFile * file