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)),this,SLOT(autoAdaptHGTD(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 modules, bool supportStructure, bool coolingLines, bool covers, bool moderator, bool servicesElectronics)
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 (modules && (name=="HGTDFlexPackage" ||
2514 name.startsWith("HGTDFlexTube") ||
2515 name=="HGTDHybrid" ||
2516 name=="HGTDGlueSensor" ||
2517 name=="HGTDGlueAsic" ||
2518 name.startsWith("HGTDSiSensor") ||
2519 name=="HGTDLGADInactive" ||
2520 name=="HGTDASIC")) {
2521 selected = true;
2522 } else if (supportStructure && (name=="HGTDSupportPlate" || name=="HGTDCoolingPlate")) {
2523 selected = true;
2524 } else if (coolingLines && name=="HGTDPeripheralCoolingLines") {
2525 selected = true;
2526 } else if (covers && (name=="HGTDFrontCover" ||
2527 name=="HGTDBackCover" ||
2528 name=="HGTDOuterRCover" ||
2529 name=="HGTDInnerRCover1" ||
2530 name=="HGTDInnerRCover2" ||
2531 name=="HGTDInnerRCover3")) {
2532 selected = true;
2533 } else if (moderator && (name=="HGTDModeratorIn" || name=="HGTDModeratorOut")) {
2534 selected = true;
2535 } else if (servicesElectronics && (name=="support_F_vol" ||
2536 name=="support_B_vol" ||
2537 name.startsWith("PowerBlock_") ||
2538 name.startsWith("VTRx_"))) {
2539 selected = true;
2540 }
2541
2542 if (selected) {
2543 unzap = true;
2544 handle->setState(VP1GeoFlags::CONTRACTED);
2545 VolumeHandle* parent = handle->parent();
2546 while (parent) {
2547 parent->setState(VP1GeoFlags::EXPANDED);
2548 parent = parent->parent();
2549 }
2550 }
2551 }
2552 if (!unzap)
2554 }
2555 }
2556
2557 m_d->phisectormanager->updateRepresentationsOfVolsAroundZAxis();
2558 m_d->phisectormanager->largeChangesEnd();
2559
2560 if (save) {
2561 m_d->sceneroot->enableNotify(true);
2562 m_d->sceneroot->touch();
2563 }
2564}
2565
2566
2567
2568
2569//_____________________________________________________________________________________
2571{
2572 VP1Msg::messageDebug("VP1GeometrySystem::Imp::showPixelModules()");
2573 h->initialiseChildren();
2574 VolumeHandle::VolumeHandleListItr it(h->childrenBegin()),itE(h->childrenEnd());
2575 for (;it!=itE;++it) {
2576 if ((*it)->hasName("moduleLog")) {
2577 (*it)->setState(VP1GeoFlags::ZAPPED);
2578 (*it)->contractDaughtersRecursively();
2579 (*it)->initialiseChildren();
2580 VolumeHandle::VolumeHandleListItr itMod((*it)->childrenBegin()),itModE((*it)->childrenEnd());
2581 for (;itMod!=itModE;++itMod) {
2582 if ((*itMod)->getName().startsWith("si"))
2583 (*itMod)->setState(VP1GeoFlags::CONTRACTED);
2584 else
2585 (*itMod)->setState(VP1GeoFlags::ZAPPED);
2586 }
2587 (*it)->setState(VP1GeoFlags::EXPANDED);
2588 continue;
2589 }
2590 if ((*it)->hasName("pigtailLog")||(*it)->hasName("omegaLog")) {
2591 (*it)->setState(VP1GeoFlags::ZAPPED);
2592 (*it)->contractDaughtersRecursively();
2593 continue;
2594 }
2595 if ((*it)->nChildren()<1) {
2596 (*it)->setState(VP1GeoFlags::ZAPPED);
2597 continue;
2598 }
2599 (*it)->setState(VP1GeoFlags::ZAPPED);
2600 showPixelModules(*it);
2601 (*it)->setState(VP1GeoFlags::EXPANDED);
2602 }
2603}
2604
2605void VP1GeometrySystem::Imp::expandAllChildren(VolumeHandle* h, bool isPixel, bool brl, bool ecA, bool ecC) {
2606
2607 if (h->nChildren()==0) {
2608 if (isPixel and (ecA or ecC)) {
2609 float translation_x, translation_y, translation_z, rotaxis_x, rotaxis_y, rotaxis_z, rotangle_radians;
2610 VP1LinAlgUtils::decodeTransformation( h->getGlobalTransformToVolume(),
2611 translation_x, translation_y, translation_z,
2612 rotaxis_x, rotaxis_y, rotaxis_z, rotangle_radians );
2613 if ((!ecA || !ecC) && ((ecA and (translation_z<0.)) or (ecC and (translation_z>0.) ))) {
2614 h->setState(VP1GeoFlags::ZAPPED);
2615 return;
2616 }
2617 }
2618
2619 // check if you have to select it
2620 std::vector< std::string > selected_volumes = {};
2621 if (brl) {
2622 if (isPixel) {
2623 selected_volumes.push_back("InnerBarrelSingleMod_Sensor");
2624 selected_volumes.push_back("InnerBarrelQuadMod_Sensor");
2625 selected_volumes.push_back("OuterBarrelQuadMod_Sensor");
2626 selected_volumes.push_back("LongeronCoolingTube");
2627 selected_volumes.push_back("InnerPixBarrelSupport_Stave");
2628 selected_volumes.push_back("InnerPixBarrelSupport_Stave1");
2629 selected_volumes.push_back("LongeronCornerBase");
2630 selected_volumes.push_back("LongeronCornerEnd");
2631 selected_volumes.push_back("LongeronTrussWall");
2632 selected_volumes.push_back("LongeronCapBase");
2633 selected_volumes.push_back("LongeronTopCap");
2634
2635 } else {
2636 selected_volumes.push_back("BRLSensorSS");
2637 selected_volumes.push_back("BRLSensorMS");
2638 selected_volumes.push_back("B_HybridPCB");
2639 selected_volumes.push_back("DCDC_PCB");
2640 selected_volumes.push_back("DCDC_Box");
2641 selected_volumes.push_back("Bex_HybridPCB_near");
2642 selected_volumes.push_back("Bex_HybridPCB_far");
2643 }
2644 }
2645 if (ecA or ecC) {
2646 if (isPixel) {
2647 selected_volumes.push_back("InclinedQuadMod_Sensor");
2648 selected_volumes.push_back("InnerRingSingleMod_Sensor");
2649 selected_volumes.push_back("InnerEndcapQuadMod_Sensor");
2650 selected_volumes.push_back("OuterEndcapQuadMod_Sensor");
2651 selected_volumes.push_back("L2HalfRingCoolingPipe");
2652 selected_volumes.push_back("L3HalfRingCoolingPipe");
2653 selected_volumes.push_back("L4endcapcoolingpipe");
2654 selected_volumes.push_back("InclL2HalfShell");
2655 selected_volumes.push_back("InclL2Support");
2656 selected_volumes.push_back("InclL3HalfShell");
2657 selected_volumes.push_back("InclL3Support");
2658 selected_volumes.push_back("InclL4HalfShell");
2659 selected_volumes.push_back("InclL4Support");
2660 selected_volumes.push_back("InnerPixEndcap_CoupledRingSupport");
2661 selected_volumes.push_back("InnerPixEndcap_IntermediateRingSupport");
2662 selected_volumes.push_back("InnerPixEndcap_L1RingSupport");
2663 selected_volumes.push_back("L2HalfRingCarbonFoamInner");
2664 selected_volumes.push_back("L2HalfRingCarbonFoamOuter");
2665 selected_volumes.push_back("L2HalfRingFaceSheet");
2666 selected_volumes.push_back("L3HalfRingCarbonFoamInner");
2667 selected_volumes.push_back("L3HalfRingCarbonFoamOuter");
2668 selected_volumes.push_back("L3HalfRingFaceSheet");
2669 selected_volumes.push_back("L4endcapinnerCarbonFoam");
2670 selected_volumes.push_back("L4endcapouterCarbonFoam");
2671 selected_volumes.push_back("L4endcapFaceSheet");
2672 selected_volumes.push_back("L2HalfShell");
2673 selected_volumes.push_back("L3HalfShell");
2674 selected_volumes.push_back("L4HalfShell");
2675 } else {
2676 selected_volumes.push_back("ECSensor0");
2677 selected_volumes.push_back("ECSensor1");
2678 selected_volumes.push_back("ECSensor2");
2679 selected_volumes.push_back("ECSensor3");
2680 selected_volumes.push_back("ECSensor4");
2681 selected_volumes.push_back("ECSensor5");
2682 selected_volumes.push_back("ECSensorBack0");
2683 selected_volumes.push_back("ECSensorBack1");
2684 selected_volumes.push_back("ECSensorBack2");
2685 selected_volumes.push_back("ECSensorBack3");
2686 selected_volumes.push_back("ECSensorBack4");
2687 selected_volumes.push_back("ECSensorBack5");
2688 }
2689 }
2690
2691 std::string name = h->getName().toStdString();
2692
2693 if (not isPixel and (ecA or ecC)) {
2694 // check servises in the endcap
2695 if (name.starts_with("ECHybrid") or name.starts_with("DCDC_EC"))
2696 return;
2697 }
2698
2699 if (std::find(selected_volumes.begin(), selected_volumes.end(), name) == selected_volumes.end()) {
2700 h->setState(VP1GeoFlags::ZAPPED);
2701 return;
2702 }
2703 return;
2704 } else if (not isPixel and (h->getName().toStdString()=="PetalCore" or
2705 h->getName().toStdString()=="StaveCoreSS" or
2706 h->getName().toStdString() =="StaveCoreMS")) {
2707 return;
2708 }
2709 h->initialiseChildren();
2710
2711 h->setState(VP1GeoFlags::EXPANDED);
2712 VolumeHandle::VolumeHandleListItr it(h->childrenBegin()),itE(h->childrenEnd());
2713 for (;it!=itE;++it) {
2714 expandAllChildren(*it, isPixel, brl, ecA, ecC);
2715 }
2716}
2717
2719{
2720 VP1Msg::messageDebug("VP1GeometrySystem::Imp::showITkPixelModules()");
2721 h->initialiseChildren();
2722 VolumeHandle::VolumeHandleListItr it(h->childrenBegin()),itE(h->childrenEnd());
2723 // std::cout << "Processing volume with name = " << h->getName().toStdString() << " and " << h->nChildren() << " children..." << std::endl;
2724 for (;it!=itE;++it) {
2725 expandAllChildren(*it, true, brl, ecA, ecC);
2726 }
2727}
2728
2729
2731{
2732 VP1Msg::messageDebug("VP1GeometrySystem::Imp::showITkStripModules()");
2733 h->initialiseChildren();
2734 VolumeHandle::VolumeHandleListItr it(h->childrenBegin()),itE(h->childrenEnd());
2735 // std::cout << "Processing volume with name = " << h->getName().toStdString() << " and " << h->nChildren() << " children..." << std::endl;
2736 for (;it!=itE;++it) {
2737 if (brl and (*it)->hasName("ITkStrip_Barrel")) {
2738 expandAllChildren(*it, false, brl, ecA, ecC);
2739 }
2740 else if (ecA and (*it)->hasName("ITkStrip_ForwardPlus")) {
2741 expandAllChildren(*it, false, brl, ecA, ecC);
2742 }
2743 else if (ecC and (*it)->hasName("ITkStrip_ForwardMinus")) {
2744 expandAllChildren(*it, false, brl, ecA, ecC);
2745 } else
2746 (*it)->setState(VP1GeoFlags::ZAPPED);
2747 }
2748}
2749
2750//_____________________________________________________________________________________
2752{
2753 VP1Msg::messageDebug("VP1GeometrySystem::Imp::showSCTBarrelModules()");
2754 h->initialiseChildren();
2755 VolumeHandle::VolumeHandleListItr it(h->childrenBegin()),itE(h->childrenEnd());
2756 for (;it!=itE;++it) {
2757 if ((*it)->getName().startsWith("Layer")) {
2758 (*it)->setState(VP1GeoFlags::ZAPPED);
2759 (*it)->initialiseChildren();
2760 VolumeHandle::VolumeHandleListItr itLay((*it)->childrenBegin()),itLayE((*it)->childrenEnd());
2761 for (;itLay!=itLayE;++itLay) {
2762 if ((*itLay)->getName().endsWith("Active")&&(*itLay)->getName().startsWith("Layer")) {
2763 (*itLay)->setState(VP1GeoFlags::ZAPPED);
2764 (*itLay)->initialiseChildren();
2765 VolumeHandle::VolumeHandleListItr itActLay((*itLay)->childrenBegin()),itActLayE((*itLay)->childrenEnd());
2766 for (;itActLay!=itActLayE;++itActLay) {
2767 if ((*itActLay)->getName().startsWith("Ski")) {
2768 (*itActLay)->setState(VP1GeoFlags::ZAPPED);
2769 (*itActLay)->initialiseChildren();
2770 VolumeHandle::VolumeHandleListItr itSki((*itActLay)->childrenBegin()),itSkiE((*itActLay)->childrenEnd());
2771 for (;itSki!=itSkiE;++itSki) {
2772 //Ends with "Envelope": open, otherwise zap. Of those, zap all without "Sensor" in the name.
2773 if ((*itSki)->hasName("Module")) {
2774 //Open and zap those without "Sensor" in the name:
2775 (*itSki)->setState(VP1GeoFlags::ZAPPED);
2776 (*itSki)->initialiseChildren();
2777 VolumeHandle::VolumeHandleListItr itMod((*itSki)->childrenBegin()),itModE((*itSki)->childrenEnd());
2778 for (;itMod!=itModE;++itMod) {
2779 if ((*itMod)->getName().contains("Envelope")) {
2780 (*itMod)->setState(VP1GeoFlags::ZAPPED);
2781 (*itMod)->initialiseChildren();
2782 VolumeHandle::VolumeHandleListItr itEnv((*itMod)->childrenBegin()),itEnvE((*itMod)->childrenEnd());
2783 for(;itEnv!=itEnvE;++itEnv) {
2784 if ((*itEnv)->getName().contains("Sensor"))
2785 (*itEnv)->reset();
2786 else
2787 (*itEnv)->setState(VP1GeoFlags::ZAPPED);
2788 }
2789 (*itMod)->setState(VP1GeoFlags::EXPANDED);
2790 } else {
2791 (*itMod)->setState(VP1GeoFlags::ZAPPED);
2792 }
2793 }
2794 (*itSki)->setState(VP1GeoFlags::EXPANDED);
2795 } else {
2796 (*itSki)->setState(VP1GeoFlags::ZAPPED);
2797 }//end if-elsi "Envelope"
2798 }//endfor itSki
2799 (*itActLay)->setState(VP1GeoFlags::EXPANDED);
2800 } else {
2801 (*itActLay)->setState(VP1GeoFlags::ZAPPED);
2802 }//end if-else "Ski"
2803 }
2804 (*itLay)->setState(VP1GeoFlags::EXPANDED);
2805 } else {
2806 (*itLay)->setState(VP1GeoFlags::ZAPPED);
2807 (*itLay)->contractDaughtersRecursively();
2808 }
2809 }
2810 (*it)->setState(VP1GeoFlags::EXPANDED);
2811 } else {
2812 (*it)->setState(VP1GeoFlags::ZAPPED);
2813 (*it)->contractDaughtersRecursively();
2814 }
2815 }
2816}
2817
2818//_____________________________________________________________________________________
2820{
2821 VP1Msg::messageDebug("VP1GeometrySystem::Imp::showSCTEndcapModules()");
2822 h->initialiseChildren();
2823 VolumeHandle::VolumeHandleListItr it(h->childrenBegin()),itE(h->childrenEnd());
2824 for (;it!=itE;++it) {
2825 if ((*it)->getName().startsWith("Wheel")) {
2826 (*it)->setState(VP1GeoFlags::ZAPPED);
2827 (*it)->initialiseChildren();
2828 VolumeHandle::VolumeHandleListItr itWhl((*it)->childrenBegin()),itWhlE((*it)->childrenEnd());
2829 for (;itWhl!=itWhlE;++itWhl) {
2830 if ((*itWhl)->getName().startsWith("Ring")) {
2831 (*itWhl)->setState(VP1GeoFlags::ZAPPED);
2832 (*itWhl)->initialiseChildren();
2833 VolumeHandle::VolumeHandleListItr itRng((*itWhl)->childrenBegin()),itRngE((*itWhl)->childrenEnd());
2834 for (;itRng!=itRngE;++itRng) {
2835 if ((*itRng)->getName().startsWith("FwdModule")) {
2836 (*itRng)->setState(VP1GeoFlags::ZAPPED);
2837 (*itRng)->initialiseChildren();
2838 VolumeHandle::VolumeHandleListItr itMod((*itRng)->childrenBegin()),itModE((*itRng)->childrenEnd());
2839 for(;itMod!=itModE;++itMod) {
2840 if ((*itMod)->getName().startsWith("ECSensor")) {
2841 (*itMod)->reset();
2842 } else {
2843 (*itMod)->setState(VP1GeoFlags::ZAPPED);
2844 }
2845 }
2846 (*itRng)->setState(VP1GeoFlags::EXPANDED);
2847 } else {
2848 (*itRng)->setState(VP1GeoFlags::ZAPPED);
2849 }
2850 }
2851 (*itWhl)->setState(VP1GeoFlags::EXPANDED);
2852 } else {
2853 (*itWhl)->setState(VP1GeoFlags::ZAPPED);
2854 (*itWhl)->contractDaughtersRecursively();
2855 }
2856 }
2857 (*it)->setState(VP1GeoFlags::EXPANDED);
2858 } else {
2859 (*it)->setState(VP1GeoFlags::ZAPPED);
2860 (*it)->contractDaughtersRecursively();
2861 }
2862 }
2863}
2864
2865//_____________________________________________________________________________________
2867{
2868 //might not use this slot presently...
2869 if (!vh)
2870 return;
2871 deselectAll();
2872 vh->setState(state);
2873 m_d->phisectormanager->updateRepresentationsOfVolsAroundZAxis();
2874}
2875
2876//_____________________________________________________________________________________
2878{
2879 if (!vh)
2880 return;
2881 deselectAll();
2882 vh->reset();
2883 m_d->phisectormanager->updateRepresentationsOfVolsAroundZAxis();
2884}
2885
2886//_____________________________________________________________________________________
2888{
2889 std::map<SoSeparator*,VolumeHandle*>::iterator it,itE(m_d->sonodesep2volhandle.end());
2890 for (it =m_d->sonodesep2volhandle.begin();it!=itE;++it)
2892}
2893
2894
2895//_____________________________________________________________________________________
2896void VP1GeometrySystem::saveMaterialsToFile(const QString& filename,bool onlyChangedMaterials)
2897{
2898 if (filename.isEmpty())
2899 return;
2900
2901 //If file exists, ask to overwrite.
2902 QFileInfo fi(filename);
2903 if (fi.exists()) {
2904 if (!fi.isWritable()) {
2905 QMessageBox::critical(0, "Error - could not save to file "+filename,
2906 "Could not save to file: <i>"+filename+"</i>"
2907 +"<br/><br/>Reason: File exists already and is write protected",QMessageBox::Ok,QMessageBox::Ok);
2908 return;
2909 }
2910 }
2911
2912 QFile file(filename);
2913 if (!file.open(QIODevice::WriteOnly)) {
2914 QMessageBox::critical(0, "Error - problems writing to file "+filename,
2915 "Problems writing to file: <i>"+filename+"</i>",QMessageBox::Ok,QMessageBox::Ok);
2916 return;
2917 }
2918
2919 m_d->ensureInitVisAttributes();
2920 VP1Serialise s(0/*version*/,this);
2921 //Save some file ID info!!
2922 s.save(QString("VP1GeoMaterialsBegin"));
2923 s.save(m_d->detVisAttributes->getState(onlyChangedMaterials));
2924 s.save(m_d->matVisAttributes->getState(onlyChangedMaterials));
2925 s.save(m_d->volVisAttributes->getState(onlyChangedMaterials));
2926 s.save(QString("VP1GeoMaterialsEnd"));
2927 s.disableUnsavedChecks();
2928
2929 QDataStream outfile(&file);
2930 outfile<<qCompress(s.result()).toBase64();
2931
2932}
2933
2934//_____________________________________________________________________________________
2935void VP1GeometrySystem::loadMaterialsFromFile(const QString& filename)
2936{
2937 if (filename.isEmpty())
2938 return;
2939 QFileInfo fi(filename);
2940 if (!fi.exists()) {
2941 QMessageBox::critical(0, "Error - file does not exists: "+filename,
2942 "File does not exists: <i>"+filename+"</i>",QMessageBox::Ok,QMessageBox::Ok);
2943 return;
2944 }
2945 if (!fi.isReadable()) {
2946 QMessageBox::critical(0, "Error - file is not readable: "+filename,
2947 "File is not readable: <i>"+filename+"</i>",QMessageBox::Ok,QMessageBox::Ok);
2948 return;
2949 }
2950 //open file
2951 QFile file(filename);
2952 if (!file.open(QIODevice::ReadOnly)) {
2953 QMessageBox::critical(0, "Error - problems opening file "+filename,
2954 "Problems opening file: <i>"+filename+"</i>",QMessageBox::Ok,QMessageBox::Ok);
2955 return;
2956 }
2957 QByteArray byteArray64;
2958 QDataStream infile(&file);
2959 infile >> byteArray64;
2960 QByteArray byteArray = qUncompress(QByteArray::fromBase64(byteArray64));
2961
2962 VP1Deserialise s(byteArray,this);
2963 if (s.version()!=0) {
2964 QMessageBox::critical(0, "Error - File in wrong format "+filename,
2965 "File in wrong format: <i>"+filename+"</i>",QMessageBox::Ok,QMessageBox::Ok);
2966 return;
2967 }
2968 QString txtbegin, txtend;
2969 QByteArray baDet, baMat, baVol;
2970 txtbegin = s.restoreString();
2971 baDet = s.restoreByteArray();
2972 baMat = s.restoreByteArray();
2973 baVol = s.restoreByteArray();
2974 txtend = s.restoreString();
2975 s.disableUnrestoredChecks();
2976 if (txtbegin!="VP1GeoMaterialsBegin"||txtend!="VP1GeoMaterialsEnd") {
2977 QMessageBox::critical(0, "Error - File in wrong format "+filename,
2978 "File in wrong format: <i>"+filename+"</i>",QMessageBox::Ok,QMessageBox::Ok);
2979 return;
2980 }
2981
2982 m_d->ensureInitVisAttributes();
2983 m_d->detVisAttributes->applyState(baDet);
2984 m_d->matVisAttributes->applyState(baMat);
2985 m_d->volVisAttributes->applyState(baVol);
2986
2987 VolumeHandle* lastsel = m_d->controller->lastSelectedVolume();
2988 m_d->controller->setLastSelectedVolume(0);
2989 m_d->controller->setLastSelectedVolume(lastsel);
2990}
2991
2992//____________________________________________________________________
2994{
2995 messageVerbose("setLabelPosOffsets called");
2996 setLabels(m_d->controller->labels());
2997}
2998
3000 messageVerbose("setLabels "+str(i)+" for this many chambers:"+str(m_d->muonchambers_pv2handles.size()));
3001 // loop over all contained volumes (all visible volumes?) and update labels.
3002 // Just muons to start with
3003 std::map<PVConstLink,VolumeHandle*>::const_iterator it = m_d->muonchambers_pv2handles.begin(), itEnd = m_d->muonchambers_pv2handles.end();
3004 for (; it!=itEnd ; ++it){
3005 if (it->second->isInMuonChamber()) it->second->updateLabels(); // currently only do labels for Muon volumes
3006 }
3007}
3008
3010 m_d->controller->setLabelsEnabled(t0s,hits);
3011}
3012
3013void VP1GeometrySystem::muonChamberT0sChanged(const std::map<GeoPVConstLink, float>& t0s, int index){
3014 messageVerbose("muonChamberT0sChanged for this many chambers:"+str(t0s.size()));
3015 if (index>=m_d->chamberT0s.size())
3016 message("ERROR: chamber t0 index out of bounds!");
3017 else
3018 m_d->chamberT0s[index]=&t0s;
3019}
#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 autoAdaptHGTD(bool reset, bool modules, bool supportStructure, bool coolingLines, bool covers, bool moderator, bool servicesElectronics)
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 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