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