From ceec66cd6e82aa8c6a977d9173a1ab6c55fb25e0 Mon Sep 17 00:00:00 2001 From: Dave Casper <dcasper@uci.edu> Date: Sun, 8 Sep 2019 03:23:50 +0000 Subject: [PATCH] Detector description, simulation and display for veto detector --- Control/CalypsoCommon/CMakeLists.txt | 25 + Control/CalypsoCommon/python/GlobalFlags.py | 295 +++ Control/CalypsoCommon/python/__init__.py | 1 + Control/CalypsoConfiguration/CMakeLists.txt | 15 + .../python/AllConfigFlags.py | 206 ++ .../python/DetectorConfigFlags.py | 73 + .../CalypsoConfiguration/python/__init__.py | 1 + .../python/DetDescrCnvSvcConfig.py | 11 + .../DetDescrCnvSvc/src/DetDescrConverter.cxx | 3 +- .../GeoModel/FaserGeoModel/CMakeLists.txt | 5 + .../GeoModel/FaserGeoModel/data/geomDB.sql | 4 +- .../python/FaserGeoModelConfig.py | 5 +- .../FaserGeoModel/python/GeoModelConfig.py | 55 + .../FaserGeoModel/python/ScintGMConfig.py | 23 +- .../test/FaserGeometryConfig_EVNT_test.py | 53 + .../GeoModel/GeoAdaptors/CMakeLists.txt | 31 + .../GeoAdaptors/GeoAdaptors/GeoScintHit.h | 61 + .../GeoAdaptors/GeoAdaptors/GeoScintHit.icc | 71 + .../GeoModel/GeoAdaptors/src/statics.cxx | 13 + .../GeoModel/GeoModelSvc/src/GeoModelSvc.cxx | 8 + .../GeoModel/GeoModelTest/CMakeLists.txt | 1 + .../GeoModelTest/python/GeoModelTestConfig.py | 47 + .../GeoModel/GeoModelTest/python/__init__.py | 1 + .../GeoModelTest/src/GeoModelTestAlg.cxx | 3 +- .../VetoGeoModel/python/VetoGeoModelConfig.py | 36 +- .../VetoGeoModel/src/VetoStation.cxx | 4 +- .../VetoGeoModel/test/VetoGMConfig_test.py | 25 + .../ScintSimAthenaPool/CMakeLists.txt | 37 + .../ScintSimDataCollection_p1.h | 4 + .../ScintSimEventAthenaPool/ScintSimData_p1.h | 4 + .../ScintSimEventAthenaPoolCnvDict.h | 9 + .../ScintSimEventAthenaPool/selection.xml | 2 + .../src/ScintHitCollectionCnv.cxx | 32 + .../src/ScintHitCollectionCnv.h | 29 + .../ScintSimEventTPCnv/CMakeLists.txt | 37 + .../ScintHits/ScintHitCnv_p1.h | 34 + .../ScintHits/ScintHitCollectionCnv_p1.h | 41 + .../ScintHits/ScintHitCollection_p1.h | 57 + .../ScintHits/ScintHit_p1.h | 19 + .../ScintSimEventTPCnvDict.h | 20 + .../ScintSimEventTPCnv/selection.xml | 7 + .../src/ScintHits/ScintHitCnv_p1.cxx | 54 + .../ScintHits/ScintHitCollectionCnv_p1.cxx | 312 +++ Scintillator/ScintG4/VetoG4_SD/CMakeLists.txt | 36 + .../VetoG4_SD/python/VetoG4_SDConfig.py | 19 + .../VetoG4_SD/python/VetoG4_SDConfigDb.py | 5 + .../VetoG4_SD/python/VetoG4_SDToolConfig.py | 21 + .../ScintG4/VetoG4_SD/src/VetoSensorSD.cxx | 116 + .../ScintG4/VetoG4_SD/src/VetoSensorSD.h | 50 + .../VetoG4_SD/src/VetoSensorSDTool.cxx | 32 + .../ScintG4/VetoG4_SD/src/VetoSensorSDTool.h | 36 + .../src/components/VetoG4_SD_entries.cxx | 3 + .../test/VetoG4_SDToolConfig_test.py | 54 + Scintillator/ScintSimEvent/CMakeLists.txt | 40 + .../ScintSimEvent/ScintSimEvent/ScintHit.h | 185 ++ .../ScintSimEvent/ScintHitCollection.h | 20 + .../ScintSimEvent/ScintHitIdHelper.h | 59 + .../ScintSimEvent/ScintSimEventDict.h | 10 + .../ScintSimEvent/ScintSimEvent/selection.xml | 5 + Scintillator/ScintSimEvent/src/ScintHit.cxx | 176 ++ .../ScintSimEvent/src/ScintHitIdHelper.cxx | 104 + Simulation/G4Faser/G4FaserAlg/CMakeLists.txt | 53 + .../G4FaserAlg/python/G4FaserAlgConfigNew.py | 171 ++ .../G4Faser/G4FaserAlg/python/__init__.py | 0 Simulation/G4Faser/G4FaserApp/CMakeLists.txt | 54 + Simulation/G4Faser/G4FaserApp/test/runG4.py | 135 + .../G4Faser/G4FaserInterfaces/CMakeLists.txt | 23 + .../G4Faser/G4FaserServices/CMakeLists.txt | 43 + .../python/G4FaserFieldServices.py | 204 ++ .../python/G4FaserServicesConfigNew.py | 140 + .../G4FaserServices/python/__init__.py | 0 .../G4FaserServices/src/FaserGeoIDSvc.cxx | 71 + .../G4FaserServices/src/FaserGeoIDSvc.h | 66 + .../components/G4FaserServices_entries.cxx | 3 + .../G4Faser/G4FaserTools/CMakeLists.txt | 44 + .../G4FaserTools/python/G4FaserToolsConfig.py | 141 + .../G4FaserTools/python/G4FieldConfigNew.py | 331 +++ .../python/G4GeometryToolConfig.py | 64 + .../python/G4PhysicsRegionConfigNew.py | 302 +++ .../G4Faser/G4FaserTools/python/__init__.py | 0 Simulation/G4Utilities/Geo2G4/CMakeLists.txt | 52 + .../src/ExtParameterisedVolumeBuilder.cxx | 279 ++ .../src/ExtParameterisedVolumeBuilder.h | 44 + .../G4Utilities/Geo2G4/src/G4ShiftedCone.cxx | 2267 +++++++++++++++++ .../G4Utilities/Geo2G4/src/G4ShiftedCone.h | 247 ++ .../G4Utilities/Geo2G4/src/G4ShiftedCone.icc | 337 +++ .../Geo2G4/src/GDMLDetectorTool.cxx | 86 + .../G4Utilities/Geo2G4/src/GDMLDetectorTool.h | 53 + .../Geo2G4/src/Geo2G4AssemblyFactory.cxx | 41 + .../Geo2G4/src/Geo2G4AssemblyFactory.h | 27 + .../Geo2G4/src/Geo2G4AssemblyTriplet.h | 218 ++ .../Geo2G4/src/Geo2G4AssemblyVolume.cxx | 350 +++ .../Geo2G4/src/Geo2G4AssemblyVolume.h | 235 ++ .../G4Utilities/Geo2G4/src/Geo2G4Builder.cxx | 221 ++ .../G4Utilities/Geo2G4/src/Geo2G4Builder.h | 71 + .../Geo2G4/src/Geo2G4LVFactory.cxx | 99 + .../G4Utilities/Geo2G4/src/Geo2G4LVFactory.h | 21 + .../Geo2G4/src/Geo2G4LogicalVolumeFactory.cxx | 39 + .../Geo2G4/src/Geo2G4LogicalVolumeFactory.h | 17 + .../src/Geo2G4OpticalSurfaceFactory.cxx | 127 + .../Geo2G4/src/Geo2G4OpticalSurfaceFactory.h | 25 + .../Geo2G4/src/Geo2G4STParameterisation.cxx | 32 + .../Geo2G4/src/Geo2G4STParameterisation.h | 71 + .../Geo2G4/src/Geo2G4SolidFactory.cxx | 588 +++++ .../Geo2G4/src/Geo2G4SolidFactory.h | 56 + .../G4Utilities/Geo2G4/src/Geo2G4Svc.cxx | 121 + Simulation/G4Utilities/Geo2G4/src/Geo2G4Svc.h | 50 + .../Geo2G4/src/Geo2G4SvcAccessor.h | 34 + .../Geo2G4/src/GeoDetectorTool.cxx | 117 + .../G4Utilities/Geo2G4/src/GeoDetectorTool.h | 61 + .../Geo2G4/src/InitializeBuilders.cxx | 12 + .../Geo2G4/src/SingleLogicalVolumeFactory.cxx | 44 + .../Geo2G4/src/SingleLogicalVolumeFactory.h | 29 + .../G4Utilities/Geo2G4/src/VolumeBuilder.h | 52 + .../Geo2G4/src/components/Geo2G4_entries.cxx | 7 + .../Geo2G4/src/lcg_dict/selection.xml | 3 + Simulation/README.md | 10 + graphics/VTI12/README.md | 9 + graphics/VTI12/VTI12Algs/CMakeLists.txt | 62 + .../VTI12AlgsEnvironmentConfig.cmake.in | 13 + graphics/VTI12/VTI12Algs/share/vti12 | 1216 +++++++++ graphics/VTI12/VTI12Algs/share/vti12.py | 455 ++++ graphics/VTI12/VTI12Algs/src/VTI12Alg.cxx | 268 ++ graphics/VTI12/VTI12Algs/src/VTI12Alg.h | 59 + .../src/components/VTI12Algs_entries.cxx | 4 + graphics/VTI12/VTI12Gui/CMakeLists.txt | 43 + .../VTI12/VTI12Gui/VTI12Gui/VP1AODSelection.h | 54 + .../VTI12Gui/VTI12Gui/VP1Authenticator.h | 59 + .../VTI12/VTI12Gui/VTI12Gui/VP1AvailEvents.h | 83 + .../VTI12Gui/VTI12Gui/VP1AvailEvtsHttp.h | 55 + .../VTI12Gui/VTI12Gui/VP1AvailEvtsHttps.h | 66 + .../VTI12Gui/VTI12Gui/VP1AvailEvtsLocalDir.h | 53 + .../VTI12Gui/VTI12Gui/VP1ChannelManager.h | 86 + .../VTI12/VTI12Gui/VTI12Gui/VP1DockWidget.h | 58 + .../VTI12Gui/VTI12Gui/VP1EventDisplayEditor.h | 93 + .../VTI12Gui/VP1EventDisplaySceneView.h | 116 + .../VTI12/VTI12Gui/VTI12Gui/VP1EventFile.h | 56 + .../VTI12Gui/VTI12Gui/VP1EvtsOnServerInfo.h | 58 + .../VTI12Gui/VTI12Gui/VP1ExecutionScheduler.h | 149 ++ .../VTI12Gui/VTI12Gui/VP1ExpertSettings.h | 131 + .../VTI12Gui/VTI12Gui/VP1GeoDBSelection.h | 54 + graphics/VTI12/VTI12Gui/VTI12Gui/VP1Gui.h | 76 + .../VTI12/VTI12Gui/VTI12Gui/VP1HttpGetFile.h | 70 + .../VTI12Gui/VP1IncomingMessageDialog.h | 58 + graphics/VTI12/VTI12Gui/VTI12Gui/VP1MD5Sum.h | 47 + .../VTI12/VTI12Gui/VTI12Gui/VP1MainWindow.h | 270 ++ .../VTI12/VTI12Gui/VTI12Gui/VP1PluginDialog.h | 44 + .../VTI12/VTI12Gui/VTI12Gui/VP1Prioritiser.h | 50 + .../VTI12Gui/VTI12Gui/VP1QtApplication.h | 53 + .../VTI12/VTI12Gui/VTI12Gui/VP1SelectEvent.h | 42 + .../VTI12/VTI12Gui/VTI12Gui/VP1TabManager.h | 112 + .../VTI12/VTI12Gui/VTI12Gui/VP1TcpServer.h | 60 + .../VTI12/VTI12Gui/VTI12Gui/VP1TextBrowser.h | 21 + .../VTI12/VTI12Gui/VTI12Gui/VP1WebWatcher.h | 72 + .../VTI12/VTI12Gui/src/VP1AODSelection.cxx | 129 + .../VTI12/VTI12Gui/src/VP1Authenticator.cxx | 590 +++++ .../VTI12/VTI12Gui/src/VP1AvailEvents.cxx | 362 +++ .../VTI12/VTI12Gui/src/VP1AvailEvtsHttp.cxx | 250 ++ .../VTI12/VTI12Gui/src/VP1AvailEvtsHttps.cxx | 397 +++ .../VTI12Gui/src/VP1AvailEvtsLocalDir.cxx | 81 + .../VTI12/VTI12Gui/src/VP1ChannelManager.cxx | 615 +++++ graphics/VTI12/VTI12Gui/src/VP1DockWidget.cxx | 319 +++ .../VTI12Gui/src/VP1EventDisplayEditor.cxx | 730 ++++++ .../VTI12Gui/src/VP1EventDisplaySceneView.cxx | 373 +++ graphics/VTI12/VTI12Gui/src/VP1EventFile.cxx | 200 ++ .../VTI12Gui/src/VP1EvtsOnServerInfo.cxx | 262 ++ .../VTI12Gui/src/VP1ExecutionScheduler.cxx | 1501 +++++++++++ .../VTI12/VTI12Gui/src/VP1ExpertSettings.cxx | 551 ++++ .../VTI12/VTI12Gui/src/VP1GeoDBSelection.cxx | 129 + graphics/VTI12/VTI12Gui/src/VP1Gui.cxx | 242 ++ .../VTI12/VTI12Gui/src/VP1HttpGetFile.cxx | 156 ++ .../VTI12Gui/src/VP1HttpGetFile_Private.h | 275 ++ .../VTI12Gui/src/VP1IncomingMessageDialog.cxx | 213 ++ .../VTI12Gui/src/VP1LocalEvtRetriever.cxx | 135 + .../VTI12/VTI12Gui/src/VP1LocalEvtRetriever.h | 43 + graphics/VTI12/VTI12Gui/src/VP1MD5Sum.cxx | 99 + graphics/VTI12/VTI12Gui/src/VP1MainWindow.cxx | 1943 ++++++++++++++ .../VTI12/VTI12Gui/src/VP1PluginDialog.cxx | 164 ++ .../VTI12/VTI12Gui/src/VP1Prioritiser.cxx | 329 +++ .../VTI12/VTI12Gui/src/VP1QtApplication.cxx | 69 + .../VTI12/VTI12Gui/src/VP1SelectEvent.cxx | 68 + .../VTI12Gui/src/VP1StreamMenuUpdater.cxx | 78 + .../VTI12/VTI12Gui/src/VP1StreamMenuUpdater.h | 37 + graphics/VTI12/VTI12Gui/src/VP1TabManager.cxx | 1580 ++++++++++++ graphics/VTI12/VTI12Gui/src/VP1TcpServer.cxx | 214 ++ .../VTI12/VTI12Gui/src/VP1TextBrowser.cxx | 39 + graphics/VTI12/VTI12Gui/src/VP1WebWatcher.cxx | 339 +++ .../VTI12Gui/src/icons/3D_mode_24x24.png | Bin 0 -> 2832 bytes .../VTI12/VTI12Gui/src/icons/3d_32x32.png | Bin 0 -> 1894 bytes .../VTI12Gui/src/icons/3d_glasses_24x24.png | Bin 0 -> 957 bytes .../VTI12/VTI12Gui/src/icons/back_32x32.png | Bin 0 -> 2230 bytes .../src/icons/button_cancel_32x32.png | Bin 0 -> 1468 bytes .../VTI12Gui/src/icons/button_ok_32x32.png | Bin 0 -> 1393 bytes graphics/VTI12/VTI12Gui/src/icons/camera.png | Bin 0 -> 1514 bytes .../VTI12/VTI12Gui/src/icons/down_32x32.png | Bin 0 -> 2248 bytes .../VTI12/VTI12Gui/src/icons/edit_32x32.png | Bin 0 -> 1627 bytes .../VTI12Gui/src/icons/editcopy_32x32.png | Bin 0 -> 3781 bytes .../src/icons/event_display_32x32.png | Bin 0 -> 9319 bytes .../VTI12Gui/src/icons/fileclose_32x32.png | Bin 0 -> 1594 bytes .../VTI12Gui/src/icons/filefind_32x32.png | Bin 0 -> 2161 bytes .../VTI12Gui/src/icons/filenew_32x32.png | Bin 0 -> 1177 bytes .../VTI12Gui/src/icons/fileopen_32x32.png | Bin 0 -> 2232 bytes .../VTI12/VTI12Gui/src/icons/fileprint.png | Bin 0 -> 1456 bytes .../VTI12Gui/src/icons/fileprint_32x32.png | Bin 0 -> 1463 bytes .../src/icons/filequickprint_32x32.png | Bin 0 -> 2088 bytes .../VTI12Gui/src/icons/filesave_32x32.png | Bin 0 -> 1348 bytes .../VTI12Gui/src/icons/filesaveas_32x32.png | Bin 0 -> 2069 bytes .../VTI12Gui/src/icons/forward_32x32.png | Bin 0 -> 2257 bytes .../VTI12/VTI12Gui/src/icons/help_32x32.png | Bin 0 -> 1683 bytes .../VTI12/VTI12Gui/src/icons/info_32x32.png | Bin 0 -> 1706 bytes .../VTI12/VTI12Gui/src/icons/kcalc_32x32.png | Bin 0 -> 2701 bytes .../VTI12/VTI12Gui/src/icons/kchart_32x32.png | Bin 0 -> 2872 bytes .../VTI12/VTI12Gui/src/icons/kivio_32x32.png | Bin 0 -> 7700 bytes .../VTI12/VTI12Gui/src/icons/launch_32x32.png | Bin 0 -> 2288 bytes .../VTI12Gui/src/icons/list_add_font.png | Bin 0 -> 1433 bytes .../VTI12Gui/src/icons/list_add_font_001.png | Bin 0 -> 1023 bytes .../VTI12/VTI12Gui/src/icons/log_32x32.png | Bin 0 -> 1910 bytes .../VTI12Gui/src/icons/network_64x64.png | Bin 0 -> 6272 bytes .../src/icons/network_disconnect_64x64.png | Bin 0 -> 7354 bytes .../VTI12/VTI12Gui/src/icons/no3D_32x32.png | Bin 0 -> 1530 bytes .../src/icons/package_settings_32x32.png | Bin 0 -> 1789 bytes .../VTI12/VTI12Gui/src/icons/redo_32x32.png | Bin 0 -> 1236 bytes .../VTI12/VTI12Gui/src/icons/rotateleft.png | Bin 0 -> 1754 bytes .../VTI12/VTI12Gui/src/icons/rotateright.png | Bin 0 -> 1732 bytes .../VTI12/VTI12Gui/src/icons/undo_32x32.png | Bin 0 -> 1178 bytes .../src/icons/window_fullscreen_32x32.png | Bin 0 -> 1198 bytes .../VTI12Gui/src/icons/window_list_32x32.png | Bin 0 -> 2105 bytes .../src/icons/window_nofullscreen_32x32.png | Bin 0 -> 1202 bytes .../VTI12Gui/src/icons/yast_route_32x32.png | Bin 0 -> 1744 bytes graphics/VTI12/VTI12Gui/src/icons/zoomin.png | Bin 0 -> 1622 bytes graphics/VTI12/VTI12Gui/src/icons/zoomout.png | Bin 0 -> 1601 bytes .../src/images/ATLAS-Logo-New_1000pixels.png | Bin 0 -> 25753 bytes .../src/images/ATLAS-Logo-New_1200pixels.png | Bin 0 -> 32861 bytes .../src/images/ATLAS-Logo-New_300pixels.png | Bin 0 -> 11082 bytes .../src/images/ATLAS-Logo-New_450pixels.png | Bin 0 -> 17097 bytes .../src/images/ATLAS-Logo-New_600pixels.png | Bin 0 -> 23520 bytes .../src/images/ATLAS-Logo-New_800pixels.png | Bin 0 -> 20081 bytes .../ATLAS-chrome-logo-URL-blue_300px.png | Bin 0 -> 138388 bytes .../ATLAS-chrome-logo-URL-blue_450px.png | Bin 0 -> 239723 bytes .../ATLAS-chrome-logo-URL-blue_600px.png | Bin 0 -> 360352 bytes .../images/ATLAS-chrome-logo-URL_300px.png | Bin 0 -> 134817 bytes .../images/ATLAS-chrome-logo-URL_450px.png | Bin 0 -> 234389 bytes .../images/ATLAS-chrome-logo-URL_600px.png | Bin 0 -> 355598 bytes graphics/VTI12/VTI12Gui/src/vp1.qrc | 61 + .../VTI12/VTI12Gui/src/vp1authenticator.ui | 209 ++ .../VTI12Gui/src/vp1eventdisplayeditor.ui | 594 +++++ .../VTI12Gui/src/vp1incomingmessagedialog.ui | 541 ++++ graphics/VTI12/VTI12Gui/src/vp1mainwindow.ui | 915 +++++++ .../VTI12/VTI12Gui/src/vp1plugindialog.ui | 265 ++ .../VTI12FaserPlugin/CMakeLists.txt | 29 + .../VTI12FaserPlugin/VP1FaserChannel.h | 32 + .../VP1FaserPlugin_VP1AutoFactory.h | 25 + .../VTI12FaserPlugin/src/VP1FaserChannel.cxx | 37 + .../src/VP1FaserPlugin_VP1AutoFactory.cxx | 24 + .../VTI12GeometryPlugin/CMakeLists.txt | 27 + .../VTI12GeometryPlugin/VP1GeometryChannel.h | 32 + .../VP1GeometryPlugin_VP1AutoFactory.h | 25 + .../src/VP1GeometryChannel.cxx | 33 + .../src/VP1GeometryPlugin_VP1AutoFactory.cxx | 24 + .../VTI12GeometrySystems/CMakeLists.txt | 57 + .../VTI12GeometrySystems/DumpShape.h | 33 + .../VTI12GeometrySystems/GeoSysController.h | 123 + .../VTI12GeometrySystems/PhiSectorManager.h | 78 + .../VTI12GeometrySystems/VP1GeoFlags.h | 93 + .../VTI12GeometrySystems/VP1GeoTreeView.h | 48 + .../VTI12GeometrySystems/VP1GeomUtils.h | 23 + .../VTI12GeometrySystems/VP1GeometrySystem.h | 94 + .../VTI12GeometrySystems/VisAttributes.h | 71 + .../VTI12GeometrySystems/VolumeHandle.h | 174 ++ .../VolumeHandleSharedData.h | 72 + .../VTI12GeometrySystems/VolumeTreeModel.h | 51 + .../ZappedVolumeListModel.h | 75 + .../VTI12GeometrySystems/src/DumpShape.cxx | 240 ++ .../src/GeoSysController.cxx | 610 +++++ .../src/PhiSectorManager.cxx | 529 ++++ .../VTI12GeometrySystems/src/VP1GeoFlags.cxx | 27 + .../src/VP1GeoTreeView.cxx | 70 + .../VTI12GeometrySystems/src/VP1GeomUtils.cxx | 26 + .../src/VP1GeometrySystem.cxx | 1434 +++++++++++ .../src/VisAttributes.cxx | 1108 ++++++++ .../VTI12GeometrySystems/src/VolumeHandle.cxx | 730 ++++++ .../src/VolumeHandleSharedData.cxx | 228 ++ .../src/VolumeTreeModel.cxx | 536 ++++ .../src/ZappedVolumeListModel.cxx | 22 + .../src/geometrysystemcontroller.ui | 488 ++++ .../src/settings_display_form.ui | 460 ++++ .../src/settings_iconisedvols_form.ui | 54 + .../src/settings_interactions_form.ui | 147 ++ .../src/settings_misc_form.ui | 245 ++ .../src/settings_treebrowser_form.ui | 61 + .../VTI12GuideLineSystems/CMakeLists.txt | 35 + .../GuideSysController.h | 208 ++ .../VTI12GuideLineSystems/InDetProjHelper.h | 103 + .../VTI12GuideLineSystems/InDetProjParams.h | 89 + .../ProjectionSurfacesHelper.h | 73 + .../VTI12GuideLineSystems/VP1CartesianGrid.h | 49 + .../VTI12GuideLineSystems/VP1CoordinateAxes.h | 49 + .../VP1CylindricalGrid.h | 49 + .../VTI12GuideLineSystems/VP1EtaCone.h | 53 + .../VTI12GuideLineSystems/VP1Floor.h | 55 + .../VP1GuideLineSystem.h | 78 + .../VTI12GuideLineSystems/VP1Letters.h | 48 + .../VTI12GuideLineSystems/VP1Lines.h | 35 + .../VP1TrackingVolumes.h | 51 + .../src/GuideSysController.cxx | 1072 ++++++++ .../src/InDetProjHelper.cxx | 964 +++++++ .../src/ProjectionSurfacesHelper.cxx | 481 ++++ .../src/VP1CartesianGrid.cxx | 213 ++ .../src/VP1CoordinateAxes.cxx | 228 ++ .../src/VP1CylindricalGrid.cxx | 241 ++ .../VTI12GuideLineSystems/src/VP1EtaCone.cxx | 217 ++ .../VTI12GuideLineSystems/src/VP1Floor.cxx | 223 ++ .../src/VP1GuideLineSystem.cxx | 345 +++ .../VTI12GuideLineSystems/src/VP1Letters.cxx | 293 +++ .../VTI12GuideLineSystems/src/VP1Lines.cxx | 148 ++ .../src/VP1TrackingVolumes.cxx | 219 ++ .../src/guidelinescontrollerform.ui | 176 ++ .../guides_settings_coordinateaxes_form.ui | 347 +++ .../src/guides_settings_etacones_form.ui | 308 +++ .../guides_settings_floorandletters_form.ui | 294 +++ .../src/guides_settings_grid_form.ui | 246 ++ .../src/guides_settings_idprojsurfs_form.ui | 683 +++++ .../src/guides_settings_lines_form.ui | 192 ++ .../src/guides_settings_trkvolumes_form.ui | 139 + .../VTI12SimHitSystems/CMakeLists.txt | 38 + .../VTI12SimHitSystems/VP1SimHitSystem.h | 34 + .../src/VP1SimHitSystem.cxx | 251 ++ .../src/simhitcontrollerform.ui | 208 ++ .../VTI12TrackSystems/CMakeLists.txt | 92 + .../AscObjSelectionManager.h | 98 + .../VTI12TrackSystems/AscObj_TSOS.h | 118 + .../VTI12TrackSystems/AscObj_TruthPoint.h | 47 + .../AssociatedObjectHandleBase.h | 97 + .../VTI12TrackSystems/MeasurementToSoNode.h | 137 + .../VTI12TrackSystems/SimBarCode.h | 58 + .../VTI12TrackSystems/SimBarCode.icc | 82 + .../VTI12TrackSystems/SimHitHandleBase.h | 95 + .../VTI12TrackSystems/SimHitHandle_ScintHit.h | 50 + .../SimHitHandle_TrackRecord.h | 92 + .../VTI12TrackSystems/TrackCollHandleBase.h | 264 ++ ...ckCollHandle_FatrasTruthTracks.h_toBeFixed | 39 + .../TrackCollHandle_RefittedTracks.h | 46 + .../TrackCollHandle_TrackParticle.hSave | 47 + .../TrackCollHandle_TrkSegment.hSave | 56 + .../TrackCollHandle_TrkTrack.h | 60 + .../TrackCollHandle_TruthTracks.h | 59 + .../TrackCollHandle_xAODTrackParticle.hSave | 45 + .../VTI12TrackSystems/TrackCollWidget.h | 42 + .../TrackCollectionSettingsButton.h | 108 + .../VTI12TrackSystems/TrackCommonFlags.h | 79 + .../VTI12TrackSystems/TrackHandleBase.h | 208 ++ .../TrackHandle_FatrasTruthTrack.hSave | 49 + .../VTI12TrackSystems/TrackHandle_TrkTrack.h | 67 + .../TrackHandle_TruthTrack.h | 64 + .../VTI12TrackSystems/TrackLODManager.h | 73 + .../TrackPropagationHelper.h | 62 + .../VTI12TrackSystems/TrackSysCommonData.h | 126 + .../VTI12TrackSystems/TrackSystemController.h | 275 ++ .../VTI12TrackSystems/TrackTypes.h | 33 + .../VTI12TrackSystems/TrkObjToString.h | 107 + .../VTI12TrackSystems/VP1TrackSanity.h | 56 + .../VTI12TrackSystems/VP1TrackSummary.h | 47 + .../VTI12TrackSystems/VP1TrackSystem.h | 99 + .../src/AscObjSelectionManager.cxx | 414 +++ .../VTI12TrackSystems/src/AscObj_TSOS.cxx | 1107 ++++++++ .../src/AscObj_TruthPoint.cxx | 160 ++ .../src/AssociatedObjectHandleBase.cxx | 208 ++ .../src/MeasurementToSoNode.cxx | 288 +++ .../src/SimHitHandle_ScintHit.cxx | 172 ++ .../src/SimHitHandle_TrackRecord.cxx | 63 + .../src/TrackCollHandleBase.cxx | 1256 +++++++++ .../src/TrackCollHandle_RefittedTracks.cxx | 62 + .../src/TrackCollHandle_TrkTrack.cxx | 159 ++ .../src/TrackCollHandle_TruthTracks.cxx | 968 +++++++ .../VTI12TrackSystems/src/TrackCollWidget.cxx | 44 + .../src/TrackCollectionSettingsButton.cxx | 642 +++++ .../src/TrackCommonFlags.cxx | 49 + .../VTI12TrackSystems/src/TrackHandleBase.cxx | 1819 +++++++++++++ .../src/TrackHandle_TrkTrack.cxx | 342 +++ .../src/TrackHandle_TruthTrack.cxx | 340 +++ .../VTI12TrackSystems/src/TrackLODManager.cxx | 364 +++ .../src/TrackPropagationHelper.cxx | 544 ++++ .../src/TrackSysCommonData.cxx | 192 ++ .../src/TrackSystemController.cxx | 2206 ++++++++++++++++ .../VTI12TrackSystems/src/TrackTypes.cxx | 124 + .../VTI12TrackSystems/src/TrkObjToString.cxx | 424 +++ .../VTI12TrackSystems/src/VP1TrackSanity.cxx | 109 + .../VTI12TrackSystems/src/VP1TrackSummary.cxx | 101 + .../VTI12TrackSystems/src/VP1TrackSystem.cxx | 940 +++++++ .../VTI12TrackSystems/src/objectbrowser.ui | 94 + .../src/pertrackcollectionsettings_form.ui | 540 ++++ .../src/settings_ascobjs_form.ui | 940 +++++++ .../src/settings_colouring_form.ui | 703 +++++ .../src/settings_cuts_form.ui | 359 +++ .../src/settings_extrapolation_form.ui | 252 ++ .../src/settings_interactions_form.ui | 318 +++ .../src/settings_projections_form.ui | 157 ++ .../src/shift_muon_chamber_form.ui | 269 ++ .../src/vp1trackcontrollerform.ui | 161 ++ graphics/VTI12/VTI12Utils/CMakeLists.txt | 62 + .../VTI12/VTI12Utils/VTI12Utils/HitToSoNode.h | 64 + .../VTI12Utils/VTI12Utils/HitsSoNodeManager.h | 45 + .../VTI12Utils/VTI12Utils/InDetProjFlags.h | 85 + .../VTI12Utils/SbPolyhedrizeAction.h | 77 + .../VTI12/VTI12Utils/VTI12Utils/SoTools.h | 30 + .../VTI12Utils/VTI12Utils/SoVisualizeAction.h | 71 + .../VTI12Utils/VTI12Utils/SurfaceToSoNode.h | 60 + .../VTI12Utils/VP1AvailableToolsHelper.h | 81 + .../VTI12/VTI12Utils/VTI12Utils/VP1DetInfo.h | 84 + .../VTI12Utils/VTI12Utils/VP1ErrorUtils.h | 83 + .../VTI12Utils/VTI12Utils/VP1JobConfigInfo.h | 52 + .../VTI12Utils/VTI12Utils/VP1LinAlgUtils.h | 97 + .../VTI12Utils/VTI12Utils/VP1ParticleData.h | 42 + .../VTI12Utils/VTI12Utils/VP1SGAccessHelper.h | 66 + .../VTI12Utils/VP1SGAccessHelper.icc | 98 + .../VTI12Utils/VP1SGContentsHelper.h | 67 + .../VTI12Utils/VP1ToolAccessHelper.h | 52 + .../VTI12Utils/VP1ToolAccessHelper.icc | 103 + .../VTI12/VTI12Utils/src/HitToSodeNode.cxx | 218 ++ .../VTI12Utils/src/HitsSoNodeManager.cxx | 463 ++++ .../VTI12/VTI12Utils/src/InDetProjFlags.cxx | 86 + .../VTI12Utils/src/SbPolyhedrizeAction.cxx | 289 +++ graphics/VTI12/VTI12Utils/src/SoTools.cpp | 37 + .../VTI12Utils/src/SoVisualizeAction.cxx | 338 +++ .../VTI12/VTI12Utils/src/SurfaceToSoNode.cxx | 252 ++ .../src/VP1AvailableToolsHelper.cxx | 319 +++ graphics/VTI12/VTI12Utils/src/VP1DetInfo.cxx | 174 ++ .../VTI12/VTI12Utils/src/VP1ErrorUtils.cxx | 402 +++ .../VTI12/VTI12Utils/src/VP1JobConfigInfo.cxx | 172 ++ .../VTI12/VTI12Utils/src/VP1LinAlgUtils.cxx | 455 ++++ .../VTI12/VTI12Utils/src/VP1ParticleData.cxx | 176 ++ .../VTI12Utils/src/VP1SGAccessHelper.cxx | 67 + .../VTI12Utils/src/VP1SGContentsHelper.cxx | 125 + .../VTI12Utils/src/VP1ToolAccessHelper.cxx | 34 + 434 files changed, 71787 insertions(+), 41 deletions(-) create mode 100644 Control/CalypsoCommon/CMakeLists.txt create mode 100644 Control/CalypsoCommon/python/GlobalFlags.py create mode 100644 Control/CalypsoCommon/python/__init__.py create mode 100644 Control/CalypsoConfiguration/CMakeLists.txt create mode 100644 Control/CalypsoConfiguration/python/AllConfigFlags.py create mode 100644 Control/CalypsoConfiguration/python/DetectorConfigFlags.py create mode 100644 Control/CalypsoConfiguration/python/__init__.py create mode 100644 DetectorDescription/DetDescrCnvSvc/python/DetDescrCnvSvcConfig.py create mode 100644 DetectorDescription/GeoModel/FaserGeoModel/python/GeoModelConfig.py create mode 100644 DetectorDescription/GeoModel/FaserGeoModel/test/FaserGeometryConfig_EVNT_test.py create mode 100644 DetectorDescription/GeoModel/GeoAdaptors/CMakeLists.txt create mode 100644 DetectorDescription/GeoModel/GeoAdaptors/GeoAdaptors/GeoScintHit.h create mode 100644 DetectorDescription/GeoModel/GeoAdaptors/GeoAdaptors/GeoScintHit.icc create mode 100644 DetectorDescription/GeoModel/GeoAdaptors/src/statics.cxx create mode 100644 DetectorDescription/GeoModel/GeoModelTest/python/GeoModelTestConfig.py create mode 100644 DetectorDescription/GeoModel/GeoModelTest/python/__init__.py create mode 100644 Scintillator/ScintDetDescr/VetoGeoModel/test/VetoGMConfig_test.py create mode 100644 Scintillator/ScintEventCnv/ScintSimAthenaPool/CMakeLists.txt create mode 100644 Scintillator/ScintEventCnv/ScintSimAthenaPool/ScintSimEventAthenaPool/ScintSimDataCollection_p1.h create mode 100644 Scintillator/ScintEventCnv/ScintSimAthenaPool/ScintSimEventAthenaPool/ScintSimData_p1.h create mode 100644 Scintillator/ScintEventCnv/ScintSimAthenaPool/ScintSimEventAthenaPool/ScintSimEventAthenaPoolCnvDict.h create mode 100644 Scintillator/ScintEventCnv/ScintSimAthenaPool/ScintSimEventAthenaPool/selection.xml create mode 100644 Scintillator/ScintEventCnv/ScintSimAthenaPool/src/ScintHitCollectionCnv.cxx create mode 100644 Scintillator/ScintEventCnv/ScintSimAthenaPool/src/ScintHitCollectionCnv.h create mode 100644 Scintillator/ScintEventCnv/ScintSimEventTPCnv/CMakeLists.txt create mode 100644 Scintillator/ScintEventCnv/ScintSimEventTPCnv/ScintSimEventTPCnv/ScintHits/ScintHitCnv_p1.h create mode 100644 Scintillator/ScintEventCnv/ScintSimEventTPCnv/ScintSimEventTPCnv/ScintHits/ScintHitCollectionCnv_p1.h create mode 100644 Scintillator/ScintEventCnv/ScintSimEventTPCnv/ScintSimEventTPCnv/ScintHits/ScintHitCollection_p1.h create mode 100644 Scintillator/ScintEventCnv/ScintSimEventTPCnv/ScintSimEventTPCnv/ScintHits/ScintHit_p1.h create mode 100644 Scintillator/ScintEventCnv/ScintSimEventTPCnv/ScintSimEventTPCnv/ScintSimEventTPCnvDict.h create mode 100644 Scintillator/ScintEventCnv/ScintSimEventTPCnv/ScintSimEventTPCnv/selection.xml create mode 100644 Scintillator/ScintEventCnv/ScintSimEventTPCnv/src/ScintHits/ScintHitCnv_p1.cxx create mode 100644 Scintillator/ScintEventCnv/ScintSimEventTPCnv/src/ScintHits/ScintHitCollectionCnv_p1.cxx create mode 100644 Scintillator/ScintG4/VetoG4_SD/CMakeLists.txt create mode 100644 Scintillator/ScintG4/VetoG4_SD/python/VetoG4_SDConfig.py create mode 100644 Scintillator/ScintG4/VetoG4_SD/python/VetoG4_SDConfigDb.py create mode 100644 Scintillator/ScintG4/VetoG4_SD/python/VetoG4_SDToolConfig.py create mode 100644 Scintillator/ScintG4/VetoG4_SD/src/VetoSensorSD.cxx create mode 100644 Scintillator/ScintG4/VetoG4_SD/src/VetoSensorSD.h create mode 100644 Scintillator/ScintG4/VetoG4_SD/src/VetoSensorSDTool.cxx create mode 100644 Scintillator/ScintG4/VetoG4_SD/src/VetoSensorSDTool.h create mode 100644 Scintillator/ScintG4/VetoG4_SD/src/components/VetoG4_SD_entries.cxx create mode 100644 Scintillator/ScintG4/VetoG4_SD/test/VetoG4_SDToolConfig_test.py create mode 100644 Scintillator/ScintSimEvent/CMakeLists.txt create mode 100644 Scintillator/ScintSimEvent/ScintSimEvent/ScintHit.h create mode 100644 Scintillator/ScintSimEvent/ScintSimEvent/ScintHitCollection.h create mode 100644 Scintillator/ScintSimEvent/ScintSimEvent/ScintHitIdHelper.h create mode 100644 Scintillator/ScintSimEvent/ScintSimEvent/ScintSimEventDict.h create mode 100644 Scintillator/ScintSimEvent/ScintSimEvent/selection.xml create mode 100644 Scintillator/ScintSimEvent/src/ScintHit.cxx create mode 100644 Scintillator/ScintSimEvent/src/ScintHitIdHelper.cxx create mode 100644 Simulation/G4Faser/G4FaserAlg/CMakeLists.txt create mode 100644 Simulation/G4Faser/G4FaserAlg/python/G4FaserAlgConfigNew.py create mode 100644 Simulation/G4Faser/G4FaserAlg/python/__init__.py create mode 100644 Simulation/G4Faser/G4FaserApp/CMakeLists.txt create mode 100644 Simulation/G4Faser/G4FaserApp/test/runG4.py create mode 100644 Simulation/G4Faser/G4FaserInterfaces/CMakeLists.txt create mode 100644 Simulation/G4Faser/G4FaserServices/CMakeLists.txt create mode 100644 Simulation/G4Faser/G4FaserServices/python/G4FaserFieldServices.py create mode 100644 Simulation/G4Faser/G4FaserServices/python/G4FaserServicesConfigNew.py create mode 100644 Simulation/G4Faser/G4FaserServices/python/__init__.py create mode 100644 Simulation/G4Faser/G4FaserServices/src/FaserGeoIDSvc.cxx create mode 100644 Simulation/G4Faser/G4FaserServices/src/FaserGeoIDSvc.h create mode 100644 Simulation/G4Faser/G4FaserServices/src/components/G4FaserServices_entries.cxx create mode 100644 Simulation/G4Faser/G4FaserTools/CMakeLists.txt create mode 100644 Simulation/G4Faser/G4FaserTools/python/G4FaserToolsConfig.py create mode 100644 Simulation/G4Faser/G4FaserTools/python/G4FieldConfigNew.py create mode 100644 Simulation/G4Faser/G4FaserTools/python/G4GeometryToolConfig.py create mode 100644 Simulation/G4Faser/G4FaserTools/python/G4PhysicsRegionConfigNew.py create mode 100644 Simulation/G4Faser/G4FaserTools/python/__init__.py create mode 100644 Simulation/G4Utilities/Geo2G4/CMakeLists.txt create mode 100644 Simulation/G4Utilities/Geo2G4/src/ExtParameterisedVolumeBuilder.cxx create mode 100644 Simulation/G4Utilities/Geo2G4/src/ExtParameterisedVolumeBuilder.h create mode 100644 Simulation/G4Utilities/Geo2G4/src/G4ShiftedCone.cxx create mode 100644 Simulation/G4Utilities/Geo2G4/src/G4ShiftedCone.h create mode 100644 Simulation/G4Utilities/Geo2G4/src/G4ShiftedCone.icc create mode 100644 Simulation/G4Utilities/Geo2G4/src/GDMLDetectorTool.cxx create mode 100644 Simulation/G4Utilities/Geo2G4/src/GDMLDetectorTool.h create mode 100644 Simulation/G4Utilities/Geo2G4/src/Geo2G4AssemblyFactory.cxx create mode 100644 Simulation/G4Utilities/Geo2G4/src/Geo2G4AssemblyFactory.h create mode 100644 Simulation/G4Utilities/Geo2G4/src/Geo2G4AssemblyTriplet.h create mode 100644 Simulation/G4Utilities/Geo2G4/src/Geo2G4AssemblyVolume.cxx create mode 100644 Simulation/G4Utilities/Geo2G4/src/Geo2G4AssemblyVolume.h create mode 100644 Simulation/G4Utilities/Geo2G4/src/Geo2G4Builder.cxx create mode 100644 Simulation/G4Utilities/Geo2G4/src/Geo2G4Builder.h create mode 100644 Simulation/G4Utilities/Geo2G4/src/Geo2G4LVFactory.cxx create mode 100644 Simulation/G4Utilities/Geo2G4/src/Geo2G4LVFactory.h create mode 100644 Simulation/G4Utilities/Geo2G4/src/Geo2G4LogicalVolumeFactory.cxx create mode 100644 Simulation/G4Utilities/Geo2G4/src/Geo2G4LogicalVolumeFactory.h create mode 100644 Simulation/G4Utilities/Geo2G4/src/Geo2G4OpticalSurfaceFactory.cxx create mode 100644 Simulation/G4Utilities/Geo2G4/src/Geo2G4OpticalSurfaceFactory.h create mode 100644 Simulation/G4Utilities/Geo2G4/src/Geo2G4STParameterisation.cxx create mode 100644 Simulation/G4Utilities/Geo2G4/src/Geo2G4STParameterisation.h create mode 100644 Simulation/G4Utilities/Geo2G4/src/Geo2G4SolidFactory.cxx create mode 100644 Simulation/G4Utilities/Geo2G4/src/Geo2G4SolidFactory.h create mode 100644 Simulation/G4Utilities/Geo2G4/src/Geo2G4Svc.cxx create mode 100644 Simulation/G4Utilities/Geo2G4/src/Geo2G4Svc.h create mode 100644 Simulation/G4Utilities/Geo2G4/src/Geo2G4SvcAccessor.h create mode 100644 Simulation/G4Utilities/Geo2G4/src/GeoDetectorTool.cxx create mode 100644 Simulation/G4Utilities/Geo2G4/src/GeoDetectorTool.h create mode 100644 Simulation/G4Utilities/Geo2G4/src/InitializeBuilders.cxx create mode 100644 Simulation/G4Utilities/Geo2G4/src/SingleLogicalVolumeFactory.cxx create mode 100644 Simulation/G4Utilities/Geo2G4/src/SingleLogicalVolumeFactory.h create mode 100644 Simulation/G4Utilities/Geo2G4/src/VolumeBuilder.h create mode 100644 Simulation/G4Utilities/Geo2G4/src/components/Geo2G4_entries.cxx create mode 100644 Simulation/G4Utilities/Geo2G4/src/lcg_dict/selection.xml create mode 100644 Simulation/README.md create mode 100644 graphics/VTI12/README.md create mode 100644 graphics/VTI12/VTI12Algs/CMakeLists.txt create mode 100644 graphics/VTI12/VTI12Algs/VTI12AlgsEnvironmentConfig.cmake.in create mode 100644 graphics/VTI12/VTI12Algs/share/vti12 create mode 100644 graphics/VTI12/VTI12Algs/share/vti12.py create mode 100644 graphics/VTI12/VTI12Algs/src/VTI12Alg.cxx create mode 100644 graphics/VTI12/VTI12Algs/src/VTI12Alg.h create mode 100644 graphics/VTI12/VTI12Algs/src/components/VTI12Algs_entries.cxx create mode 100644 graphics/VTI12/VTI12Gui/CMakeLists.txt create mode 100644 graphics/VTI12/VTI12Gui/VTI12Gui/VP1AODSelection.h create mode 100644 graphics/VTI12/VTI12Gui/VTI12Gui/VP1Authenticator.h create mode 100644 graphics/VTI12/VTI12Gui/VTI12Gui/VP1AvailEvents.h create mode 100644 graphics/VTI12/VTI12Gui/VTI12Gui/VP1AvailEvtsHttp.h create mode 100644 graphics/VTI12/VTI12Gui/VTI12Gui/VP1AvailEvtsHttps.h create mode 100644 graphics/VTI12/VTI12Gui/VTI12Gui/VP1AvailEvtsLocalDir.h create mode 100644 graphics/VTI12/VTI12Gui/VTI12Gui/VP1ChannelManager.h create mode 100644 graphics/VTI12/VTI12Gui/VTI12Gui/VP1DockWidget.h create mode 100644 graphics/VTI12/VTI12Gui/VTI12Gui/VP1EventDisplayEditor.h create mode 100644 graphics/VTI12/VTI12Gui/VTI12Gui/VP1EventDisplaySceneView.h create mode 100644 graphics/VTI12/VTI12Gui/VTI12Gui/VP1EventFile.h create mode 100644 graphics/VTI12/VTI12Gui/VTI12Gui/VP1EvtsOnServerInfo.h create mode 100644 graphics/VTI12/VTI12Gui/VTI12Gui/VP1ExecutionScheduler.h create mode 100644 graphics/VTI12/VTI12Gui/VTI12Gui/VP1ExpertSettings.h create mode 100644 graphics/VTI12/VTI12Gui/VTI12Gui/VP1GeoDBSelection.h create mode 100644 graphics/VTI12/VTI12Gui/VTI12Gui/VP1Gui.h create mode 100644 graphics/VTI12/VTI12Gui/VTI12Gui/VP1HttpGetFile.h create mode 100644 graphics/VTI12/VTI12Gui/VTI12Gui/VP1IncomingMessageDialog.h create mode 100644 graphics/VTI12/VTI12Gui/VTI12Gui/VP1MD5Sum.h create mode 100644 graphics/VTI12/VTI12Gui/VTI12Gui/VP1MainWindow.h create mode 100644 graphics/VTI12/VTI12Gui/VTI12Gui/VP1PluginDialog.h create mode 100644 graphics/VTI12/VTI12Gui/VTI12Gui/VP1Prioritiser.h create mode 100644 graphics/VTI12/VTI12Gui/VTI12Gui/VP1QtApplication.h create mode 100644 graphics/VTI12/VTI12Gui/VTI12Gui/VP1SelectEvent.h create mode 100644 graphics/VTI12/VTI12Gui/VTI12Gui/VP1TabManager.h create mode 100644 graphics/VTI12/VTI12Gui/VTI12Gui/VP1TcpServer.h create mode 100644 graphics/VTI12/VTI12Gui/VTI12Gui/VP1TextBrowser.h create mode 100644 graphics/VTI12/VTI12Gui/VTI12Gui/VP1WebWatcher.h create mode 100644 graphics/VTI12/VTI12Gui/src/VP1AODSelection.cxx create mode 100644 graphics/VTI12/VTI12Gui/src/VP1Authenticator.cxx create mode 100644 graphics/VTI12/VTI12Gui/src/VP1AvailEvents.cxx create mode 100644 graphics/VTI12/VTI12Gui/src/VP1AvailEvtsHttp.cxx create mode 100644 graphics/VTI12/VTI12Gui/src/VP1AvailEvtsHttps.cxx create mode 100644 graphics/VTI12/VTI12Gui/src/VP1AvailEvtsLocalDir.cxx create mode 100644 graphics/VTI12/VTI12Gui/src/VP1ChannelManager.cxx create mode 100644 graphics/VTI12/VTI12Gui/src/VP1DockWidget.cxx create mode 100644 graphics/VTI12/VTI12Gui/src/VP1EventDisplayEditor.cxx create mode 100644 graphics/VTI12/VTI12Gui/src/VP1EventDisplaySceneView.cxx create mode 100644 graphics/VTI12/VTI12Gui/src/VP1EventFile.cxx create mode 100644 graphics/VTI12/VTI12Gui/src/VP1EvtsOnServerInfo.cxx create mode 100644 graphics/VTI12/VTI12Gui/src/VP1ExecutionScheduler.cxx create mode 100644 graphics/VTI12/VTI12Gui/src/VP1ExpertSettings.cxx create mode 100644 graphics/VTI12/VTI12Gui/src/VP1GeoDBSelection.cxx create mode 100644 graphics/VTI12/VTI12Gui/src/VP1Gui.cxx create mode 100644 graphics/VTI12/VTI12Gui/src/VP1HttpGetFile.cxx create mode 100644 graphics/VTI12/VTI12Gui/src/VP1HttpGetFile_Private.h create mode 100644 graphics/VTI12/VTI12Gui/src/VP1IncomingMessageDialog.cxx create mode 100644 graphics/VTI12/VTI12Gui/src/VP1LocalEvtRetriever.cxx create mode 100644 graphics/VTI12/VTI12Gui/src/VP1LocalEvtRetriever.h create mode 100644 graphics/VTI12/VTI12Gui/src/VP1MD5Sum.cxx create mode 100644 graphics/VTI12/VTI12Gui/src/VP1MainWindow.cxx create mode 100644 graphics/VTI12/VTI12Gui/src/VP1PluginDialog.cxx create mode 100644 graphics/VTI12/VTI12Gui/src/VP1Prioritiser.cxx create mode 100644 graphics/VTI12/VTI12Gui/src/VP1QtApplication.cxx create mode 100644 graphics/VTI12/VTI12Gui/src/VP1SelectEvent.cxx create mode 100644 graphics/VTI12/VTI12Gui/src/VP1StreamMenuUpdater.cxx create mode 100644 graphics/VTI12/VTI12Gui/src/VP1StreamMenuUpdater.h create mode 100644 graphics/VTI12/VTI12Gui/src/VP1TabManager.cxx create mode 100644 graphics/VTI12/VTI12Gui/src/VP1TcpServer.cxx create mode 100644 graphics/VTI12/VTI12Gui/src/VP1TextBrowser.cxx create mode 100644 graphics/VTI12/VTI12Gui/src/VP1WebWatcher.cxx create mode 100644 graphics/VTI12/VTI12Gui/src/icons/3D_mode_24x24.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/3d_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/3d_glasses_24x24.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/back_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/button_cancel_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/button_ok_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/camera.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/down_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/edit_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/editcopy_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/event_display_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/fileclose_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/filefind_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/filenew_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/fileopen_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/fileprint.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/fileprint_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/filequickprint_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/filesave_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/filesaveas_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/forward_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/help_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/info_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/kcalc_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/kchart_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/kivio_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/launch_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/list_add_font.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/list_add_font_001.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/log_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/network_64x64.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/network_disconnect_64x64.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/no3D_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/package_settings_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/redo_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/rotateleft.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/rotateright.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/undo_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/window_fullscreen_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/window_list_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/window_nofullscreen_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/yast_route_32x32.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/zoomin.png create mode 100644 graphics/VTI12/VTI12Gui/src/icons/zoomout.png create mode 100644 graphics/VTI12/VTI12Gui/src/images/ATLAS-Logo-New_1000pixels.png create mode 100644 graphics/VTI12/VTI12Gui/src/images/ATLAS-Logo-New_1200pixels.png create mode 100644 graphics/VTI12/VTI12Gui/src/images/ATLAS-Logo-New_300pixels.png create mode 100644 graphics/VTI12/VTI12Gui/src/images/ATLAS-Logo-New_450pixels.png create mode 100644 graphics/VTI12/VTI12Gui/src/images/ATLAS-Logo-New_600pixels.png create mode 100644 graphics/VTI12/VTI12Gui/src/images/ATLAS-Logo-New_800pixels.png create mode 100644 graphics/VTI12/VTI12Gui/src/images/ATLAS-chrome-logo-URL-blue_300px.png create mode 100644 graphics/VTI12/VTI12Gui/src/images/ATLAS-chrome-logo-URL-blue_450px.png create mode 100644 graphics/VTI12/VTI12Gui/src/images/ATLAS-chrome-logo-URL-blue_600px.png create mode 100644 graphics/VTI12/VTI12Gui/src/images/ATLAS-chrome-logo-URL_300px.png create mode 100644 graphics/VTI12/VTI12Gui/src/images/ATLAS-chrome-logo-URL_450px.png create mode 100644 graphics/VTI12/VTI12Gui/src/images/ATLAS-chrome-logo-URL_600px.png create mode 100644 graphics/VTI12/VTI12Gui/src/vp1.qrc create mode 100644 graphics/VTI12/VTI12Gui/src/vp1authenticator.ui create mode 100644 graphics/VTI12/VTI12Gui/src/vp1eventdisplayeditor.ui create mode 100644 graphics/VTI12/VTI12Gui/src/vp1incomingmessagedialog.ui create mode 100644 graphics/VTI12/VTI12Gui/src/vp1mainwindow.ui create mode 100644 graphics/VTI12/VTI12Gui/src/vp1plugindialog.ui create mode 100644 graphics/VTI12/VTI12Plugins/VTI12FaserPlugin/CMakeLists.txt create mode 100755 graphics/VTI12/VTI12Plugins/VTI12FaserPlugin/VTI12FaserPlugin/VP1FaserChannel.h create mode 100644 graphics/VTI12/VTI12Plugins/VTI12FaserPlugin/VTI12FaserPlugin/VP1FaserPlugin_VP1AutoFactory.h create mode 100755 graphics/VTI12/VTI12Plugins/VTI12FaserPlugin/src/VP1FaserChannel.cxx create mode 100644 graphics/VTI12/VTI12Plugins/VTI12FaserPlugin/src/VP1FaserPlugin_VP1AutoFactory.cxx create mode 100644 graphics/VTI12/VTI12Plugins/VTI12GeometryPlugin/CMakeLists.txt create mode 100755 graphics/VTI12/VTI12Plugins/VTI12GeometryPlugin/VTI12GeometryPlugin/VP1GeometryChannel.h create mode 100644 graphics/VTI12/VTI12Plugins/VTI12GeometryPlugin/VTI12GeometryPlugin/VP1GeometryPlugin_VP1AutoFactory.h create mode 100755 graphics/VTI12/VTI12Plugins/VTI12GeometryPlugin/src/VP1GeometryChannel.cxx create mode 100644 graphics/VTI12/VTI12Plugins/VTI12GeometryPlugin/src/VP1GeometryPlugin_VP1AutoFactory.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/CMakeLists.txt create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/DumpShape.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/GeoSysController.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/PhiSectorManager.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VP1GeoFlags.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VP1GeoTreeView.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VP1GeomUtils.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VP1GeometrySystem.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VisAttributes.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VolumeHandle.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VolumeHandleSharedData.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VolumeTreeModel.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/ZappedVolumeListModel.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/DumpShape.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/GeoSysController.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/PhiSectorManager.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VP1GeoFlags.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VP1GeoTreeView.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VP1GeomUtils.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VP1GeometrySystem.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VisAttributes.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VolumeHandle.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VolumeHandleSharedData.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VolumeTreeModel.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/ZappedVolumeListModel.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/geometrysystemcontroller.ui create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/settings_display_form.ui create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/settings_iconisedvols_form.ui create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/settings_interactions_form.ui create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/settings_misc_form.ui create mode 100644 graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/settings_treebrowser_form.ui create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/CMakeLists.txt create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/GuideSysController.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/InDetProjHelper.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/InDetProjParams.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/ProjectionSurfacesHelper.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1CartesianGrid.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1CoordinateAxes.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1CylindricalGrid.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1EtaCone.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1Floor.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1GuideLineSystem.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1Letters.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1Lines.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1TrackingVolumes.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/GuideSysController.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/InDetProjHelper.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/ProjectionSurfacesHelper.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1CartesianGrid.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1CoordinateAxes.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1CylindricalGrid.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1EtaCone.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1Floor.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1GuideLineSystem.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1Letters.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1Lines.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1TrackingVolumes.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guidelinescontrollerform.ui create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guides_settings_coordinateaxes_form.ui create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guides_settings_etacones_form.ui create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guides_settings_floorandletters_form.ui create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guides_settings_grid_form.ui create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guides_settings_idprojsurfs_form.ui create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guides_settings_lines_form.ui create mode 100644 graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guides_settings_trkvolumes_form.ui create mode 100644 graphics/VTI12/VTI12Systems/VTI12SimHitSystems/CMakeLists.txt create mode 100755 graphics/VTI12/VTI12Systems/VTI12SimHitSystems/VTI12SimHitSystems/VP1SimHitSystem.h create mode 100755 graphics/VTI12/VTI12Systems/VTI12SimHitSystems/src/VP1SimHitSystem.cxx create mode 100755 graphics/VTI12/VTI12Systems/VTI12SimHitSystems/src/simhitcontrollerform.ui create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/CMakeLists.txt create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/AscObjSelectionManager.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/AscObj_TSOS.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/AscObj_TruthPoint.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/AssociatedObjectHandleBase.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/MeasurementToSoNode.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/SimBarCode.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/SimBarCode.icc create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/SimHitHandleBase.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/SimHitHandle_ScintHit.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/SimHitHandle_TrackRecord.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandleBase.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandle_FatrasTruthTracks.h_toBeFixed create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandle_RefittedTracks.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandle_TrackParticle.hSave create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandle_TrkSegment.hSave create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandle_TrkTrack.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandle_TruthTracks.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandle_xAODTrackParticle.hSave create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollWidget.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollectionSettingsButton.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCommonFlags.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackHandleBase.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackHandle_FatrasTruthTrack.hSave create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackHandle_TrkTrack.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackHandle_TruthTrack.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackLODManager.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackPropagationHelper.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackSysCommonData.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackSystemController.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackTypes.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrkObjToString.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/VP1TrackSanity.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/VP1TrackSummary.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/VP1TrackSystem.h create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/AscObjSelectionManager.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/AscObj_TSOS.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/AscObj_TruthPoint.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/AssociatedObjectHandleBase.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/MeasurementToSoNode.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/SimHitHandle_ScintHit.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/SimHitHandle_TrackRecord.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCollHandleBase.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCollHandle_RefittedTracks.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCollHandle_TrkTrack.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCollHandle_TruthTracks.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCollWidget.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCollectionSettingsButton.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCommonFlags.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackHandleBase.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackHandle_TrkTrack.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackHandle_TruthTrack.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackLODManager.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackPropagationHelper.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackSysCommonData.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackSystemController.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackTypes.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrkObjToString.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/VP1TrackSanity.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/VP1TrackSummary.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/VP1TrackSystem.cxx create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/objectbrowser.ui create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/pertrackcollectionsettings_form.ui create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/settings_ascobjs_form.ui create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/settings_colouring_form.ui create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/settings_cuts_form.ui create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/settings_extrapolation_form.ui create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/settings_interactions_form.ui create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/settings_projections_form.ui create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/shift_muon_chamber_form.ui create mode 100644 graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/vp1trackcontrollerform.ui create mode 100644 graphics/VTI12/VTI12Utils/CMakeLists.txt create mode 100644 graphics/VTI12/VTI12Utils/VTI12Utils/HitToSoNode.h create mode 100644 graphics/VTI12/VTI12Utils/VTI12Utils/HitsSoNodeManager.h create mode 100644 graphics/VTI12/VTI12Utils/VTI12Utils/InDetProjFlags.h create mode 100644 graphics/VTI12/VTI12Utils/VTI12Utils/SbPolyhedrizeAction.h create mode 100644 graphics/VTI12/VTI12Utils/VTI12Utils/SoTools.h create mode 100644 graphics/VTI12/VTI12Utils/VTI12Utils/SoVisualizeAction.h create mode 100644 graphics/VTI12/VTI12Utils/VTI12Utils/SurfaceToSoNode.h create mode 100644 graphics/VTI12/VTI12Utils/VTI12Utils/VP1AvailableToolsHelper.h create mode 100644 graphics/VTI12/VTI12Utils/VTI12Utils/VP1DetInfo.h create mode 100644 graphics/VTI12/VTI12Utils/VTI12Utils/VP1ErrorUtils.h create mode 100644 graphics/VTI12/VTI12Utils/VTI12Utils/VP1JobConfigInfo.h create mode 100644 graphics/VTI12/VTI12Utils/VTI12Utils/VP1LinAlgUtils.h create mode 100644 graphics/VTI12/VTI12Utils/VTI12Utils/VP1ParticleData.h create mode 100644 graphics/VTI12/VTI12Utils/VTI12Utils/VP1SGAccessHelper.h create mode 100644 graphics/VTI12/VTI12Utils/VTI12Utils/VP1SGAccessHelper.icc create mode 100644 graphics/VTI12/VTI12Utils/VTI12Utils/VP1SGContentsHelper.h create mode 100644 graphics/VTI12/VTI12Utils/VTI12Utils/VP1ToolAccessHelper.h create mode 100644 graphics/VTI12/VTI12Utils/VTI12Utils/VP1ToolAccessHelper.icc create mode 100644 graphics/VTI12/VTI12Utils/src/HitToSodeNode.cxx create mode 100644 graphics/VTI12/VTI12Utils/src/HitsSoNodeManager.cxx create mode 100644 graphics/VTI12/VTI12Utils/src/InDetProjFlags.cxx create mode 100644 graphics/VTI12/VTI12Utils/src/SbPolyhedrizeAction.cxx create mode 100644 graphics/VTI12/VTI12Utils/src/SoTools.cpp create mode 100644 graphics/VTI12/VTI12Utils/src/SoVisualizeAction.cxx create mode 100644 graphics/VTI12/VTI12Utils/src/SurfaceToSoNode.cxx create mode 100644 graphics/VTI12/VTI12Utils/src/VP1AvailableToolsHelper.cxx create mode 100644 graphics/VTI12/VTI12Utils/src/VP1DetInfo.cxx create mode 100644 graphics/VTI12/VTI12Utils/src/VP1ErrorUtils.cxx create mode 100644 graphics/VTI12/VTI12Utils/src/VP1JobConfigInfo.cxx create mode 100644 graphics/VTI12/VTI12Utils/src/VP1LinAlgUtils.cxx create mode 100644 graphics/VTI12/VTI12Utils/src/VP1ParticleData.cxx create mode 100644 graphics/VTI12/VTI12Utils/src/VP1SGAccessHelper.cxx create mode 100644 graphics/VTI12/VTI12Utils/src/VP1SGContentsHelper.cxx create mode 100644 graphics/VTI12/VTI12Utils/src/VP1ToolAccessHelper.cxx diff --git a/Control/CalypsoCommon/CMakeLists.txt b/Control/CalypsoCommon/CMakeLists.txt new file mode 100644 index 000000000..3b99b49df --- /dev/null +++ b/Control/CalypsoCommon/CMakeLists.txt @@ -0,0 +1,25 @@ +################################################################################ +# Package: CalypsoCommon +################################################################################ + +# Declare the package name: +atlas_subdir( CalypsoCommon ) + +# Declare the package's dependencies: +atlas_depends_on_subdirs( PRIVATE + TestPolicy ) + +# External dependencies: +find_package( six ) + +# Install files from the package: +atlas_install_headers( CalypsoCommon ) +atlas_install_python_modules( python/*.py python/Utils ) +#atlas_install_joboptions( share/Preparation.py share/Execution.py share/Atlas.UnixStandardJob.py test/*.py +# share/zeroJO.py share/Atlas_Gen.UnixStandardJob.py share/MemTraceInclude.py share/runbatch.py) +#atlas_install_scripts( share/athena.py share/athena3.py share/athena_preload.sh share/chappy.py share/find_cfg_dups.py share/test_cfg_pickling.py ) +#atlas_install_runtime(share/*.pkl) + +# Aliases: +atlas_add_alias( calypso "athena.py" ) + diff --git a/Control/CalypsoCommon/python/GlobalFlags.py b/Control/CalypsoCommon/python/GlobalFlags.py new file mode 100644 index 000000000..b5905af74 --- /dev/null +++ b/Control/CalypsoCommon/python/GlobalFlags.py @@ -0,0 +1,295 @@ +# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + +############################################################################### +## +## @file AthenaCommon/python/GlobalFlags.py +## @brief Python module to hold common flags to configure JobOptions +## + +""" GlobalFlags + Python module to hold common global flags + + + + The module has been re-written in terms of the new JobProperties and the + original class implementation was modified to allow a smooth transition. + For example: + GlobalFlags.DetGeo.set_atlas() + will internally do: + jobproperties.Global.DetGeo='atlas' + At some point "GlobalFlags.DetGeo.set_atlas()" we will add a warning + message and later on we declare them obsolete + + +""" + +from __future__ import print_function + +__author__ = "S.Binet, M.Gallas, David Rousseau" +__version__= "$Revision: 1.14 $" +__doc__ = "Global job properties" + +__all__ = [ "GlobalFlags", "globalflags" ] + +##----------------------------------------------------------------------------- +# imports +from AthenaCommon.JobProperties import JobProperty, JobPropertyContainer +from AthenaCommon.JobProperties import jobproperties + + +# +class DetGeo(JobProperty): + """ Which detector configuration : atlas, combined test beam or commisisoning + """ + statusOn=True + allowedTypes=['str'] + allowedValues=['atlas','ctbh8','ctbh6','commis','faser'] + StoredValue='faser' + + # automatically generate is_xyz() helpers + for v in allowedValues: + exec( "def is_%s(self): return self() == '%s'" % (v,v) ) + +# +class DetDescrVersion(JobProperty): + """ Detector geometry DB tag + see https://twiki.cern.ch/twiki/bin/view/Atlas/DetDescrVersion. + """ + statusOn=True + allowedTypes=['str'] +# allowedValues=['DC1','DC2','DC2-Final','DC2-Initial','Rome-Initial',\ +# 'Rome-Initial-v00','Rome-Final','DC1-Initial',\ +# 'DC1-Final','CTB','Commissioning-Calo','Commissioning-Muon'\ +# 'ATLAS-DC3-01','ATLAS-DC3-02','Default'] + StoredValue='FASER-00' + +class ConditionsTag(JobProperty): + """ See https://twiki.cern.ch/twiki/bin/view/Atlas/CoolProdTags + """ + statusOn=True + allowedTypes=['str'] + StoredValue='OFLCOND-RUN12-SDR-31' + +# +class DatabaseInstance(JobProperty): + """Switch between run1/run2 database instance""" + statusOn=True + allowedTypes=['str'] + allowedValues=['auto','COMP200','CONDBR2'] + StoredValue='auto' +# +class DataSource(JobProperty): + """ Where does the data comes from : real data, geant3 or geant4 + """ + statusOn=True + allowedTypes=['str'] + allowedValues=['data','geant3','geant4'] + StoredValue='geant4' + + # automatically generate is_xyz() helpers + for v in allowedValues: + exec( "def is_%s(self): return self() == '%s'" % (v,v) ) + +# +class InputFormat(JobProperty): + """ Input format of the data + """ + statusOn=True + allowedTypes=['str'] + allowedValues=['zebra','pool','bytestream'] + StoredValue='pool' + + # automatically generate is_xyz() helpers + for v in allowedValues: + exec( "def is_%s(self): return self() == '%s'" % (v,v) ) + +# +class Luminosity(JobProperty): + """ Luminosity + + zero -> no pile up at all + verylow -> 10^33 + low -> 2 10^33 + high -> 10^34 + + """ + statusOn=False + allowedTypes=['str'] + allowedValues=['zero','verylow','low','high'] + StoredValue='low' + + # automatically generate is_xyz() helpers + for v in allowedValues: + exec( "def is_%s(self): return self() == '%s'" % (v,v) ) + + # prepare removal for Luminosity + #def _undo_action(self): + # print ("WARNING GlobalFlags.Luminosity is OBSOLETE. Please use beamFlags instead.") + + #def _do_action(self): + # print ("WARNING GlobalFlags.Luminosity is OBSOLETE. Please use beamFlags instead.") + + #def get_Value(self): + # print ("WARNING GlobalFlags.Luminosity is OBSOLETE. Please use beamFlags instead.") + # return self.statusOn + +# +class isOverlay(JobProperty): + """ if data is overlayed + """ + statusOn=True + allowedTypes=['bool'] + StoredValue=False + + +# Defines the container for the reconstruction flags +class Global(JobPropertyContainer): + """ The global flag/job property container. + """ + +# add the reconstruction flags container to the top container +jobproperties.add_Container(Global) + + +# I want always the following flags in the Global container +list_jobproperties=[DetGeo,DataSource,InputFormat,Luminosity,DetDescrVersion,ConditionsTag,DatabaseInstance,isOverlay] +for i in list_jobproperties: + jobproperties.Global.add_JobProperty(i) + +# The short name (carefull do not select same name as shot name as well. +# otherwise problems with pickle) +globalflags=jobproperties.Global + + +############################################################################### +## OLD code that will be completely replaced by globalflags based on JobProperties +############################################################################### +# GlobalFlags : Author Tadashi Maeno, David Rousseau +# This is class for main jobs configuration flags +# +# Category : DetGeo has states : atlas ctbh6 ctbh8 (ctbh6 and ctbh8 grouped in ctb) +# Category : DataSource has states : data geant3 geant4 +# Category : InputFormat has states : zebra pool bytestream +# +#Each category can be set once and only once by the main topOptions. +# states are mutually exclusive +# +# from RecExCommon.GlobalFlags import GlobalFlags +# GlobalFlags.DetGeo.set_atlas() # set DetGeo to be atlas +# (trying to set again the same category will throw an error) +# +# state can be interrogated as follows (by construction, one category +# is only in one state. Testing a category that has not been set +# throws an error): +# if GlobalFlags.DetGeo.is_atlas(): +# +#Groupings canbe used to interrogate (no set methods available): +# if GlobalFlags.DetGeo.is_ctb(): (or of is_ctbh6() and is_ctbh8()) + +class GlobalFlags: + + # prefix of flag member + _flagPrefix = '_flag_' + + # Detector geometry + class DetGeo: + _name ='DetGeo' + _beenSet = False + + _flag_atlas = False + _flag_ctbh6 = False + _flag_ctbh8 = False + _flag_commis = False + _flag_faser = False + + # special is-method + def is_ctb (cls): + # stop if any flags have not been set yet + if not cls._beenSet: + raise RuntimeError('ERROR : GlobalFlags.%s has not been set!' % cls.__name__) + return cls._flag_ctbh6 | cls._flag_ctbh8 + is_ctb = classmethod(is_ctb) + + # Data source + class DataSource: + _name ='DataSource' + _beenSet = False + + _flag_data = False + _flag_geant3 = False + _flag_geant4 = False + + # Data input format + class InputFormat: + _name ='InputFormat' + _beenSet = False + + _flag_zebra = False + _flag_pool = False + _flag_bytestream = False + + # Data luminosity + class Luminosity: + _name ='Luminosity' + _beenSet = False + # no pile up at all + _flag_zero = False + # 10^33 + _flag_verylow = False + # 2 10^33 + _flag_low = False + # 1 10^34 + _flag_high = False + + # class list + _classObjList = [DetGeo,DataSource,InputFormat,Luminosity] + + # append set- and is-method + for _classObj in _classObjList: + for _attr in dir(_classObj)[:]: + # look for flag member + if 0 == _attr.find(_flagPrefix): + # temporary class for function object + class _TmpC: + def __init__ (self,clsObj,flagName): + self._clsObj = clsObj + self._flagName = flagName + def set (self): + # stop if already set + if self._clsObj._beenSet: + raise RuntimeError('ERROR : GlobalFlags.%s has been already set!' % self._clsObj.__name__) + # set flags true + setattr(self._clsObj, self._flagName, True) + self._clsObj._beenSet = True + raise RuntimeError("ERROR GlobalFlags.set_%s() deprecated ! Use globalflags.%s.set_Value_and_Lock(blah) instead !" % (self._clsObj.__name__+"."+self._flagName[6:],self._clsObj.__name__)) + # setting at the same time jobproperties value + data={'JobProperties.Global':{self._clsObj._name:self._flagName.replace('_flag_','')}} + jobproperties.set_JobProperties(data) + def is_xyz (self): + raise RuntimeError("ERROR GlobalFlags.is_%s() deprecated ! Use if globalflags.%s == blah instead !" % (self._flagName[6:],self._clsObj.__name__)) + # stop if any flags have not been set yet + if not self._clsObj._beenSet: + raise RuntimeError('ERROR : GlobalFlags.%s has not been set!' % self._clsObj.__name__) + return getattr(self._clsObj, self._flagName) + + _tmpC = _TmpC(_classObj,_attr) + # register methods + _setMethod = _attr.replace(_flagPrefix,'set_') + setattr(_classObj,_setMethod, _tmpC.set) + _isMethod = _attr.replace(_flagPrefix,'is_') + setattr(_classObj,_isMethod, _tmpC.is_xyz) + + # dump Setting + def Print (cls): + format = "%12s : %s" + for classObj in cls._classObjList: + flagName = '----' + for attr in dir(classObj): + # look for flag member + if 0 == attr.find(cls._flagPrefix): + # test if this flag on + if classObj.__dict__[attr]: + flagName = attr.replace(cls._flagPrefix,'') + print (format % (classObj.__name__, flagName)) + + # class method + Print = classmethod(Print) diff --git a/Control/CalypsoCommon/python/__init__.py b/Control/CalypsoCommon/python/__init__.py new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/Control/CalypsoCommon/python/__init__.py @@ -0,0 +1 @@ + diff --git a/Control/CalypsoConfiguration/CMakeLists.txt b/Control/CalypsoConfiguration/CMakeLists.txt new file mode 100644 index 000000000..717b71d09 --- /dev/null +++ b/Control/CalypsoConfiguration/CMakeLists.txt @@ -0,0 +1,15 @@ +################################################################################ +# Package: CalypsoConfiguration +################################################################################ + +# Declare the package name: +atlas_subdir( CalypsoConfiguration ) + +atlas_depends_on_subdirs( Control/AthenaConfiguration ) + +# External dependencies: +find_package( six ) + +# Install files from the package: +atlas_install_python_modules( python/*.py ) + diff --git a/Control/CalypsoConfiguration/python/AllConfigFlags.py b/Control/CalypsoConfiguration/python/AllConfigFlags.py new file mode 100644 index 000000000..263f093b1 --- /dev/null +++ b/Control/CalypsoConfiguration/python/AllConfigFlags.py @@ -0,0 +1,206 @@ +# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + +from __future__ import print_function + +from AthenaConfiguration.AllConfigFlags import ConfigFlags as athenaConfigFlags +from AthenaConfiguration.AllConfigFlags import GetFileMD +# from AthenaConfiguration.AthConfigFlags import AthConfigFlags +# from AthenaCommon.SystemOfUnits import TeV +# from AthenaConfiguration.AutoConfigFlags import GetFileMD, GetDetDescrInfo +import six + + +def _moduleExists (modName): + if six.PY34: + import importlib + return importlib.util.find_spec (modName) is not None + else: + import imp + try: + imp.find_module (modName) + except ImportError: + return False + return True + + +def _addFlagsCategory (acf, name, generator, modName = None): + if _moduleExists (modName): + return acf.addFlagsCategory (name, generator) + return None + + +def _createCfgFlags(): + + # acf=AthConfigFlags() + fcf = athenaConfigFlags + + # acf.addFlag('Input.Files', ["_ATHENA_GENERIC_INPUTFILE_NAME_",] ) # former global.InputFiles + # acf.addFlag('Input.SecondaryFiles', []) # secondary input files for DoubleEventSelector + # acf.addFlag('Input.isMC', lambda prevFlags : "IS_SIMULATION" in GetFileMD(prevFlags.Input.Files).get("eventTypes",[]) ) # former global.isMC + # acf.addFlag('Input.RunNumber', lambda prevFlags : list(GetFileMD(prevFlags.Input.Files).get("runNumbers",[]))) # former global.RunNumber + # acf.addFlag('Input.ProjectName', lambda prevFlags : GetFileMD(prevFlags.Input.Files).get("project_name","data17_13TeV") ) # former global.ProjectName + + # def _inputCollections(inputFile): + # rawCollections = [type_key[1] for type_key in GetFileMD(inputFile).get("itemList",[])] + # collections = filter(lambda col: not col.endswith('Aux.'), rawCollections) + # return collections + + # acf.addFlag('Input.Collections', lambda prevFlags : _inputCollections(prevFlags.Input.Files) ) + + # acf.addFlag('Concurrency.NumProcs', 0) + # acf.addFlag('Concurrency.NumThreads', 0) + # acf.addFlag('Concurrency.NumConcurrentEvents', 0) + + # acf.addFlag('Scheduler.CheckDependencies', True) + # acf.addFlag('Scheduler.ShowDataDeps', True) + # acf.addFlag('Scheduler.ShowDataFlow', True) + # acf.addFlag('Scheduler.ShowControlFlow', True) + + # acf.addFlag('Common.isOnline', False ) # Job runs in an online environment (access only to resources available at P1) # former global.isOnline + # acf.addFlag('Common.useOnlineLumi', lambda prevFlags : prevFlags.Common.isOnline ) # Use online version of luminosity. ??? Should just use isOnline? + # acf.addFlag('Common.doExpressProcessing', False) + + # def _checkProject(): + # import os + # if "AthSimulation_DIR" in os.environ: + # return "AthSimulation" + # #TODO expand this method. + # return "Athena" + # acf.addFlag('Common.Project', _checkProject()) + + # replace global.Beam* + # acf.addFlag('Beam.BunchSpacing', 25) # former global.BunchSpacing + # acf.addFlag('Beam.Type', lambda prevFlags : GetFileMD(prevFlags.Input.Files).get('beam_type','collisions') )# former global.BeamType + # acf.addFlag("Beam.NumberOfCollisions", lambda prevFlags : 2. if prevFlags.Beam.Type=='collisions' else 0.) # former global.NumberOfCollisions + # acf.addFlag('Beam.Energy', lambda prevFlags : GetFileMD(prevFlags.Input.Files).get('beam_energy',7*TeV)) # former global.BeamEnergy + # acf.addFlag('Beam.estimatedLuminosity', lambda prevFlags : ( 1E33*(prevFlags.Beam.NumberOfCollisions)/2.3 ) *\ + # (25./prevFlags.Beam.BunchSpacing)) # former flobal.estimatedLuminosity + + + # acf.addFlag('Output.doESD', False) # produce ESD containers + + # acf.addFlag('Output.EVNTFileName','myEVNT.pool.root') + # acf.addFlag('Output.HITSFileName','myHITS.pool.root') + # acf.addFlag('Output.RDOFileName','myRDO.pool.root') + # acf.addFlag('Output.ESDFileName','myESD.pool.root') + # acf.addFlag('Output.AODFileName','myAOD.pool.root') + # acf.addFlag('Output.HISTFileName','myHIST.root') + + # Might move this elsewhere in the future. + # Some flags from https://gitlab.cern.ch/atlas/athena/blob/master/Tracking/TrkDetDescr/TrkDetDescrSvc/python/TrkDetDescrJobProperties.py + # (many, e.g. those that set properties of one tool are not needed) + # acf.addFlag('TrackingGeometry.MagneticFileMode', 6) + # acf.addFlag('TrackingGeometry.MaterialSource', 'COOL') # Can be COOL, Input or None + +#Detector Flags: + def __detector(): + from CalypsoConfiguration.DetectorConfigFlags import createDetectorConfigFlags + return createDetectorConfigFlags() + # acf.addFlagsCategory( "Detector", __detector ) + fcf.join( __detector() ) + +#Simulation Flags: + def __simulation(): + from G4AtlasApps.SimConfigFlags import createSimConfigFlags + return createSimConfigFlags() + _addFlagsCategory (fcf, "Sim", __simulation, 'G4AtlasApps' ) + +#Digitization Flags: + # def __digitization(): + # from Digitization.DigitizationConfigFlags import createDigitizationCfgFlags + # return createDigitizationCfgFlags() + # _addFlagsCategory(acf, "Digitization", __digitization, 'Digitization' ) + +#Overlay Flags: + # def __overlay(): + # from OverlayConfiguration.OverlayConfigFlags import createOverlayConfigFlags + # return createOverlayConfigFlags() + # _addFlagsCategory(acf, "Overlay", __overlay, 'OverlayConfiguration' ) + +#Geo Model Flags: + # acf.addFlag('GeoModel.Layout', 'atlas') # replaces global.GeoLayout + # acf.addFlag("GeoModel.AtlasVersion", lambda prevFlags : GetFileMD(prevFlags.Input.Files).get("GeoAtlas",None) or "ATLAS-R2-2016-01-00-01") # + # acf.addFlag("GeoModel.Align.Dynamic", lambda prevFlags : (not prevFlags.Detector.Simulate)) + # acf.addFlag("GeoModel.StripGeoType", lambda prevFlags : GetDetDescrInfo(prevFlags.GeoModel.AtlasVersion).get('StripGeoType',"GMX")) # Based on CommonGeometryFlags.StripGeoType + # acf.addFlag("GeoModel.Run", lambda prevFlags : GetDetDescrInfo(prevFlags.GeoModel.AtlasVersion).get('Run',"RUN2")) # Based on CommonGeometryFlags.Run (InDetGeometryFlags.isSLHC replaced by GeoModel.Run=="RUN4") + # acf.addFlag("GeoModel.Type", lambda prevFlags : GetDetDescrInfo(prevFlags.GeoModel.AtlasVersion).get('GeoType',"UNDEFINED")) # Geometry type in {ITKLoI, ITkLoI-VF, etc...} + # acf.addFlag("GeoModel.IBLLayout", lambda prevFlags : GetDetDescrInfo(prevFlags.GeoModel.AtlasVersion).get('IBLlayout',"UNDEFINED")) # IBL layer layout in {"planar", "3D", "noIBL", "UNDEFINED"} + fcf.addFlag("GeoModel.FaserVersion", lambda prevFlags : GetFileMD(prevFlags.Input.Files).get("GeoFaser",None) or "FASER-00") + fcf.addFlag("GeoModel.GeoExportFile","") + +#IOVDbSvc Flags: + # acf.addFlag("IOVDb.GlobalTag",lambda prevFlags : GetFileMD(prevFlags.Input.Files).get("IOVDbGlobalTag",None) or "CONDBR2-BLKPA-2017-05") + # from IOVDbSvc.IOVDbAutoCfgFlags import getDatabaseInstanceDefault + # acf.addFlag("IOVDb.DatabaseInstance",getDatabaseInstanceDefault) + + + # def __lar(): + # from LArConfiguration.LArConfigFlags import createLArConfigFlags + # return createLArConfigFlags() + # _addFlagsCategory(acf, "LAr", __lar, 'LArConfiguration' ) + + # def __tile(): + # from TileConfiguration.TileConfigFlags import createTileConfigFlags + # return createTileConfigFlags() + # _addFlagsCategory(acf, 'Tile', __tile, 'TileConfiguration' ) + +#CaloNoise Flags + # acf.addFlag("Calo.Noise.fixedLumiForNoise",-1) + # acf.addFlag("Calo.Noise.useCaloNoiseLumi",True) + +#CaloCell flags + # acf.addFlag("Calo.Cell.doLArHVCorr",False) # Disable for now as it is broken... + # acf.addFlag("Calo.Cell.doPileupOffsetBCIDCorr", True) +#TopoCluster Flags: + # acf.addFlag("Calo.TopoCluster.doTwoGaussianNoise",True) + # acf.addFlag("Calo.TopoCluster.doTreatEnergyCutAsAbsolute",False) + # acf.addFlag("Calo.TopoCluster.doTopoClusterLocalCalib",True) + +#Random engine Flags: + # acf.addFlag("Random.Engine", "dSFMT") # Random service used in {"dSFMT", "Ranlux64", "Ranecu"} + + # def __trigger(): + # from TriggerJobOpts.TriggerConfigFlags import createTriggerFlags + # return createTriggerFlags() + # _addFlagsCategory(acf, "Trigger", __trigger, 'TriggerJobOpts' ) + + # def __muon(): + # from MuonConfig.MuonConfigFlags import createMuonConfigFlags + # return createMuonConfigFlags() + # _addFlagsCategory(acf, "Muon", __muon, 'MuonConfig' ) + + # def __egamma(): + # from egammaConfig.egammaConfigFlags import createEgammaConfigFlags + # return createEgammaConfigFlags() + # _addFlagsCategory(acf, "Egamma", __egamma, 'egammaConfig' ) + + # def __pflow(): + # from eflowRec.PFConfigFlags import createPFConfigFlags + # return createPFConfigFlags() + # _addFlagsCategory(acf,"PF",__pflow, 'eflowRec') + + # def __dq(): + # from AthenaMonitoring.DQConfigFlags import createDQConfigFlags, createComplexDQConfigFlags + # dqf = createDQConfigFlags() + # dqf.join( createComplexDQConfigFlags() ) + # return dqf + # _addFlagsCategory(acf, "DQ", __dq, 'AthenaMonitoring' ) + + return fcf + + +ConfigFlags=_createCfgFlags() + +del _createCfgFlags + +if __name__=="__main__": + import sys + if len(sys.argv)>1: + ConfigFlags.Input.Files = sys.argv[1:] + else: + ConfigFlags.Input.Files = [ "/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/CommonInputs/data16_13TeV.00311321.physics_Main.recon.AOD.r9264/AOD.11038520._000001.pool.root.1",] + + ConfigFlags.loadAllDynamicFlags() + ConfigFlags.initAll() + ConfigFlags.dump() + diff --git a/Control/CalypsoConfiguration/python/DetectorConfigFlags.py b/Control/CalypsoConfiguration/python/DetectorConfigFlags.py new file mode 100644 index 000000000..3ee03697e --- /dev/null +++ b/Control/CalypsoConfiguration/python/DetectorConfigFlags.py @@ -0,0 +1,73 @@ +# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + +from __future__ import print_function + +from AthenaConfiguration.AthConfigFlags import AthConfigFlags + +# This module is based upon Control/AthenaCommon/python/DetFlags.py +# Only some flags have been migrated. + +def createDetectorConfigFlags(): + dcf=AthConfigFlags() + + #Detector.Geometry - merger of the old geometry and detdescr tasks + dcf.addFlag('Detector.GeometryUpstreamDipole', False) + dcf.addFlag('Detector.GeometryCentralDipole', False) + dcf.addFlag('Detector.GeometryDownstreamDipole',False) + dcf.addFlag('Detector.GeometryDipole', lambda prevFlags : (prevFlags.Detector.GeometryUpstreamDipole or + prevFlags.Detector.GeometryCentralDipole or + prevFlags.Detector.GeometryDownstreamDipole)) + dcf.addFlag('Detector.GeometryVeto', False) + dcf.addFlag('Detector.GeometryTrigger', False) + dcf.addFlag('Detector.GeometryPreshower', False) + dcf.addFlag('Detector.GeometryScintillator', lambda prevFlags : (prevFlags.Detector.GeometryVeto or + prevFlags.Detector.GeometryTrigger or + prevFlags.Detector.GeometryPreshower)) + dcf.addFlag('Detector.GeometryFaserSCT', False) + dcf.addFlag('Detector.GeometryTracker', lambda prevFlags : prevFlags.Detector.GeometryFaserSCT ) + dcf.addFlag('Detector.GeometryEcal', False) + dcf.addFlag('Detector.GeometryFaserCalo', lambda prevFlags : prevFlags.DetectorGeometry.Ecal) + dcf.addFlag('Detector.GeometryFaser', lambda prevFlags : (prevFlags.Detector.GeometryDecayVolume or + prevFlags.Detector.GeometryScintillator or + prevFlags.Detector.GeometryTracker or + prevFlags.Detector.GeometryFaserCalo)) + + #Detector.Simulate + dcf.addFlag('Detector.SimulateUpstreamDipole', False) + dcf.addFlag('Detector.SimulateCentralDipole', False) + dcf.addFlag('Detector.SimulateDownstreamDipole',False) + dcf.addFlag('Detector.SimulateDipole', lambda prevFlags : (prevFlags.Detector.SimulateUpstreamDipole or + prevFlags.Detector.SimulateCentralDipole or + prevFlags.Detector.SimulateDownstreamDipole)) + dcf.addFlag('Detector.SimulateDecayVolume', False) + dcf.addFlag('Detector.SimulateVeto', False) + dcf.addFlag('Detector.SimulateTrigger', False) + dcf.addFlag('Detector.SimulatePreshower', False) + dcf.addFlag('Detector.SimulateScintillator',lambda prevFlags : (prevFlags.Detector.SimulateVeto or + prevFlags.Detector.SimulateTrigger or + prevFlags.Detector.SimulatePreshower)) + dcf.addFlag('Detector.SimulateFaserSCT', False) + dcf.addFlag('Detector.SimulateTracker', lambda prevFlags : prevFlags.Detector.SimulateFaserSCT ) + dcf.addFlag('Detector.SimulateEcal', False) + dcf.addFlag('Detector.SimulateFaserCalo', lambda prevFlags : prevFlags.Detector.SimulateEcal) + dcf.addFlag('Detector.SimulateFaser', lambda prevFlags : (prevFlags.Detector.SimulateDecayVolume or + prevFlags.Detector.SimulateScintillator or + prevFlags.Detector.SimulateTracker or + prevFlags.Detector.SimulateFaserCalo)) + + #Detector.Overlay + dcf.addFlag('Detector.OverlayVeto', False) + dcf.addFlag('Detector.OverlayTrigger', False) + dcf.addFlag('Detector.OverlayPreshower', False) + dcf.addFlag('Detector.OverlayScintillator', lambda prevFlags : (prevFlags.Detector.OverlayVeto or + prevFlags.Detector.OverlayTrigger or + prevFlags.Detector.OverlayPreshower)) + dcf.addFlag('Detector.OverlayFaserSCT', False) + dcf.addFlag('Detector.OverlayTracker', lambda prevFlags : prevFlags.Detector.OverlayFaserSCT ) + dcf.addFlag('Detector.OverlayEcal', False) + dcf.addFlag('Detector.OverlayFaserCalo', lambda prevFlags : prevFlags.Detector.OverlayEcal) + dcf.addFlag('Detector.OverlayFaser', lambda prevFlags : (prevFlags.Detector.OverlayScintillator or + prevFlags.Detector.OverlayTracker or + prevFlags.Detector.OverlayFaserCalo)) + + return dcf diff --git a/Control/CalypsoConfiguration/python/__init__.py b/Control/CalypsoConfiguration/python/__init__.py new file mode 100644 index 000000000..bd7ae5cfe --- /dev/null +++ b/Control/CalypsoConfiguration/python/__init__.py @@ -0,0 +1 @@ +__all__=[ 'ConfigFlags' ] \ No newline at end of file diff --git a/DetectorDescription/DetDescrCnvSvc/python/DetDescrCnvSvcConfig.py b/DetectorDescription/DetDescrCnvSvc/python/DetDescrCnvSvcConfig.py new file mode 100644 index 000000000..5a5c2fbea --- /dev/null +++ b/DetectorDescription/DetDescrCnvSvc/python/DetDescrCnvSvcConfig.py @@ -0,0 +1,11 @@ +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator + +def DetDescrCnvSvcCfg(configFlags=None): + from DetDescrCnvSvc.DetDescrCnvSvcConf import DetDescrCnvSvc + from GaudiSvc.GaudiSvcConf import EvtPersistencySvc + acc=ComponentAccumulator() + # Specify primary Identifier dictionary to be use + detDescrCnvSvc=DetDescrCnvSvc(IdDictName = "FaserGeoModel/FASER_IDS.xml",IdDictFromRDB = True) + acc.addService(detDescrCnvSvc) + acc.addService(EvtPersistencySvc("EventPersistencySvc",CnvServices=[detDescrCnvSvc.getName(),])) #No service handle yet??? + return acc diff --git a/DetectorDescription/DetDescrCnvSvc/src/DetDescrConverter.cxx b/DetectorDescription/DetDescrCnvSvc/src/DetDescrConverter.cxx index f4427802a..606a9f168 100644 --- a/DetectorDescription/DetDescrCnvSvc/src/DetDescrConverter.cxx +++ b/DetectorDescription/DetDescrCnvSvc/src/DetDescrConverter.cxx @@ -114,8 +114,7 @@ DetDescrConverter::storageType() DetDescrConverter::DetDescrConverter(const CLID& myCLID, ISvcLocator* svcloc) : Converter(DetDescr_StorageType, myCLID, svcloc) //m_CLID(myCLID) -{ - +{ IInterface* toCnvSvc = 0; m_cnvSvc = 0; StatusCode status = serviceLocator() diff --git a/DetectorDescription/GeoModel/FaserGeoModel/CMakeLists.txt b/DetectorDescription/GeoModel/FaserGeoModel/CMakeLists.txt index 99774a67e..c3facd1d2 100644 --- a/DetectorDescription/GeoModel/FaserGeoModel/CMakeLists.txt +++ b/DetectorDescription/GeoModel/FaserGeoModel/CMakeLists.txt @@ -23,3 +23,8 @@ atlas_install_python_modules( python/*.py ) # Install xml files from the package: atlas_install_xmls( data/*.xml data/*.dtd ) +atlas_install_scripts( test/*.py ) + +atlas_add_test( EVNT_InputGeo_test + SCRIPT test/FaserGeometryConfig_EVNT_test.py + PROPERTIES TIMEOUT 300 ) diff --git a/DetectorDescription/GeoModel/FaserGeoModel/data/geomDB.sql b/DetectorDescription/GeoModel/FaserGeoModel/data/geomDB.sql index 1a6007a90..163b05690 100644 --- a/DetectorDescription/GeoModel/FaserGeoModel/data/geomDB.sql +++ b/DetectorDescription/GeoModel/FaserGeoModel/data/geomDB.sql @@ -947,8 +947,8 @@ INSERT INTO "ELEMENTS_DATA2TAG" VALUES (100008, 91); -- -- INSERT INTO "VETOTOPLEVEL_DATA" VALUES (0, 0.0, 0.0, -1650.0, 0.0, 0.0, 0.0, 321, "Veto"); -INSERT INTO "VETOTOPLEVEL_DATA" VALUES (1, 0.0, 0.0, -100.0, 0.0, 0.0, 0.0, 321, "StationA"); -INSERT INTO "VETOTOPLEVEL_DATA" VALUES (2, 0.0, 0.0, 100.0, 0.0, 0.0, 0.0, 321, "StationB"); +INSERT INTO "VETOTOPLEVEL_DATA" VALUES (1, 0.0, 0.0, -300.0, 0.0, 0.0, 0.0, 321, "StationA"); +INSERT INTO "VETOTOPLEVEL_DATA" VALUES (2, 0.0, 0.0, 300.0, 0.0, 0.0, 0.0, 321, "StationB"); INSERT INTO "VETOTOPLEVEL_DATA2TAG" VALUES (100009, 0); INSERT INTO "VETOTOPLEVEL_DATA2TAG" VALUES (100009, 1); INSERT INTO "VETOTOPLEVEL_DATA2TAG" VALUES (100009, 2); diff --git a/DetectorDescription/GeoModel/FaserGeoModel/python/FaserGeoModelConfig.py b/DetectorDescription/GeoModel/FaserGeoModel/python/FaserGeoModelConfig.py index ce5e989cb..ff9539259 100644 --- a/DetectorDescription/GeoModel/FaserGeoModel/python/FaserGeoModelConfig.py +++ b/DetectorDescription/GeoModel/FaserGeoModel/python/FaserGeoModelConfig.py @@ -3,14 +3,11 @@ # from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator -from AthenaConfiguration.AthConfigFlags import AthConfigFlags def FaserGeometryCfg (flags): acc = ComponentAccumulator() from FaserGeoModel.ScintGMConfig import ScintGeometryCfg acc.merge(ScintGeometryCfg(flags)) - # if (flags.Detector.Simulate and flags.Beam.Type == "cosmics") or flags.Detector.SimulateCavern: - # from CavernInfraGeoModel.CavernInfraGeoModelConf import CavernInfraDetectorTool - # gms.DetectorTools += [ CavernInfraDetectorTool() ] + return acc diff --git a/DetectorDescription/GeoModel/FaserGeoModel/python/GeoModelConfig.py b/DetectorDescription/GeoModel/FaserGeoModel/python/GeoModelConfig.py new file mode 100644 index 000000000..40675be17 --- /dev/null +++ b/DetectorDescription/GeoModel/FaserGeoModel/python/GeoModelConfig.py @@ -0,0 +1,55 @@ +from __future__ import print_function +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator +from AthenaCommon.Configurable import Configurable +from AthenaCommon.Constants import VERBOSE + +def GeoModelCfg(configFlags): + version = configFlags.GeoModel.FaserVersion + geoExportFile = configFlags.GeoModel.GeoExportFile + + from AthenaCommon.AppMgr import release_metadata + rel_metadata = release_metadata() + relversion = rel_metadata['release'].split('.') + if len(relversion) < 3: + relversion = rel_metadata['base release'].split('.') + + + result=ComponentAccumulator() + from GeoModelSvc.GeoModelSvcConf import GeoModelSvc + gms=GeoModelSvc(FaserVersion=version, + GeoExportFile = geoExportFile, + SupportedGeometry = int(relversion[0]) + ) + if configFlags.Detector.Simulate: + ## Protects GeoModelSvc in the simulation from the AlignCallbacks + gms.AlignCallbacks = False + result.addService(gms,primary=True) + + + #Get DetDescrCnvSvc (for identifier dictionaries (identifier helpers) + from DetDescrCnvSvc.DetDescrCnvSvcConfig import DetDescrCnvSvcCfg + result.merge(DetDescrCnvSvcCfg(configFlags)) + + from EventInfoMgt.TagInfoMgrConfig import TagInfoMgrCfg + tim_ca,tagInfoMgr = TagInfoMgrCfg(configFlags) + # result.addService(tagInfoMgr) + result.merge(tim_ca) + #TagInfoMgr used by GeoModelSvc but no ServiceHandle. Relies on string-name + + return result + + + +if __name__ == "__main__": + from AthenaConfiguration.AllConfigFlags import ConfigFlags + # from AthenaConfiguration.TestDefaults import defaultTestFiles + # ConfigFlags.Input.Files = defaultTestFiles.RAW + Configurable.configurableRun3Behavior=1 + ConfigFlags.addFlag("GeoModel.FaserVersion", "Faser-00") + ConfigFlags.GeoModel.FaserVersion = "Faser-00" + ConfigFlags.lock() + + acc = GeoModelCfg( ConfigFlags ) + acc.store( file( "test.pkl", "w" ), useBootStrapFile = False ) + + print("All OK") diff --git a/DetectorDescription/GeoModel/FaserGeoModel/python/ScintGMConfig.py b/DetectorDescription/GeoModel/FaserGeoModel/python/ScintGMConfig.py index 3e2bbfe0b..afcf0ed65 100644 --- a/DetectorDescription/GeoModel/FaserGeoModel/python/ScintGMConfig.py +++ b/DetectorDescription/GeoModel/FaserGeoModel/python/ScintGMConfig.py @@ -3,8 +3,6 @@ # from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator -from AthenaConfiguration.AthConfigFlags import AthConfigFlags -from IOVDbSvc.IOVDbSvcConfig import addFoldersSplitOnline # def InDetServiceMaterialCfg (flags): # from AtlasGeoModel.GeoModelConfig import GeoModelCfg @@ -25,8 +23,8 @@ from IOVDbSvc.IOVDbSvcConfig import addFoldersSplitOnline def ScintGeometryCfg (flags): acc = ComponentAccumulator() - from ScintGeoModel.ScintGeoModelConfig import ScintGeometryCfg - acc.merge(ScintGeometryCfg( flags )) + from VetoGeoModel.VetoGeoModelConfig import VetoGeometryCfg + acc.merge(VetoGeometryCfg( flags )) return acc @@ -41,13 +39,16 @@ if __name__ == "__main__": # Set up logging and new style config log.setLevel(DEBUG) Configurable.configurableRun3Behavior = True - from AthenaConfiguration.TestDefaults import defaultTestFiles + ConfigFlags.addFlag("GeoModel.FaserVersion", "Faser-00") + ConfigFlags.addFlag("Detector.SimulateVeto", True) + + # from AthenaConfiguration.TestDefaults import defaultTestFiles # Provide MC input - ConfigFlags.Input.Files = defaultTestFiles.HITS + # ConfigFlags.Input.Files = defaultTestFiles.HITS ConfigFlags.IOVDb.GlobalTag = "OFLCOND-MC16-SDR-16" - ConfigFlags.Detector.SimulatePixel = True - ConfigFlags.Detector.SimulateSCT = True - ConfigFlags.Detector.SimulateTRT = True + # ConfigFlags.Detector.SimulatePixel = True + ConfigFlags.Detector.SimulateVeto = True + # ConfigFlags.Detector.SimulateTRT = True ConfigFlags.GeoModel.Align.Dynamic = False # Provide data input ##from AthenaConfiguration.TestDefaults import defaultTestFiles @@ -58,11 +59,11 @@ if __name__ == "__main__": # Construct ComponentAccumulator acc = MainServicesSerialCfg() acc.merge(PoolReadCfg(ConfigFlags)) - acc.merge(InDetGeometryCfg(ConfigFlags)) # FIXME This sets up the whole ID geometry would be nicer just to set up min required + acc.merge(ScintGeometryCfg(ConfigFlags)) # FIXME This sets up the whole Scint geometry would be nicer just to set up min required #acc.getService("StoreGateSvc").Dump=True acc.getService("ConditionStore").Dump=True acc.printConfig(withDetails=True) - f=open('InDetGMCfg2.pkl','w') + f=open('ScintGMCfg2.pkl','w') acc.store(f) f.close() ConfigFlags.dump() diff --git a/DetectorDescription/GeoModel/FaserGeoModel/test/FaserGeometryConfig_EVNT_test.py b/DetectorDescription/GeoModel/FaserGeoModel/test/FaserGeometryConfig_EVNT_test.py new file mode 100644 index 000000000..15e91a51f --- /dev/null +++ b/DetectorDescription/GeoModel/FaserGeoModel/test/FaserGeometryConfig_EVNT_test.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python +"""Run a test on Atlas Geometry configuration using a EVNT file as input + +Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +""" +if __name__ == "__main__": + import os + from AthenaCommon.Logging import log + from AthenaCommon.Constants import VERBOSE, INFO + from AthenaCommon.Configurable import Configurable + from CalypsoConfiguration.AllConfigFlags import ConfigFlags + from AthenaConfiguration.MainServicesConfig import MainServicesSerialCfg + from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg + # from AtlasGeoModel.AtlasGeoModelConfig import AtlasGeometryCfg + # Set up logging and new style config + from FaserGeoModel.FaserGeoModelConfig import FaserGeometryCfg + log.setLevel(VERBOSE) + Configurable.configurableRun3Behavior = True + + from AthenaConfiguration.TestDefaults import defaultTestFiles + # Provide MC input + ConfigFlags.Input.Files = defaultTestFiles.EVNT + # ConfigFlags.GeoModel.AtlasVersion = "ATLAS-R2-2016-01-00-01" + ConfigFlags.GeoModel.FaserVersion = "FASER-00" + ConfigFlags.Detector.SimulateVeto = True + ConfigFlags.IOVDb.GlobalTag = "OFLCOND-MC16-SDR-16" + ConfigFlags.GeoModel.Align.Dynamic = False + ConfigFlags.lock() + + # Construct ComponentAccumulator + acc = MainServicesSerialCfg() + acc.merge(PoolReadCfg(ConfigFlags)) + acc.merge(FaserGeometryCfg(ConfigFlags)) + #acc.getService("StoreGateSvc").Dump=True + acc.getService("ConditionStore").Dump=True + + # from GaudiCoreSvc.GaudiCoreSvcConf import MessageSvc + # msgSvc = MessageSvc() + # acc.addService(msgSvc) + + from AthenaCommon.Logging import logging + logging.getLogger('forcomps').setLevel(VERBOSE) + acc.foreach_component("*").OutputLevel = VERBOSE + + acc.foreach_component("*ClassID*").OutputLevel = INFO + + acc.printConfig(withDetails=True) + f=open('FaserGeoModelCfg_EVNT.pkl','w') + acc.store(f, useBootStrapFile = False) + f.close() + ConfigFlags.dump() + # Execute and finish + acc.run(maxEvents=3) diff --git a/DetectorDescription/GeoModel/GeoAdaptors/CMakeLists.txt b/DetectorDescription/GeoModel/GeoAdaptors/CMakeLists.txt new file mode 100644 index 000000000..4b05ff389 --- /dev/null +++ b/DetectorDescription/GeoModel/GeoAdaptors/CMakeLists.txt @@ -0,0 +1,31 @@ +################################################################################ +# Package: GeoAdaptors +################################################################################ + +# Declare the package name: +atlas_subdir( GeoAdaptors ) + +# Declare the package's dependencies: +atlas_depends_on_subdirs( PUBLIC + Control/StoreGate + DetectorDescription/Identifier + DetectorDescription/GeoPrimitives + Scintillator/ScintDetDescr/ScintIdentifier + Scintillator/ScintDetDescr/ScintReadoutGeometry + Scintillator/ScintSimEvent +# InnerDetector/InDetDetDescr/InDetIdentifier +# InnerDetector/InDetDetDescr/InDetReadoutGeometry +# InnerDetector/InDetSimEvent + ) + +# External dependencies: +find_package( CLHEP ) + +# Component(s) in the package: +atlas_add_library( GeoAdaptors + src/*.cxx + PUBLIC_HEADERS GeoAdaptors + INCLUDE_DIRS ${CLHEP_INCLUDE_DIRS} + DEFINITIONS ${CLHEP_DEFINITIONS} + LINK_LIBRARIES ${CLHEP_LIBRARIES} Identifier ScintIdentifier ScintReadoutGeometry ScintSimEvent StoreGateLib SGtests ) + diff --git a/DetectorDescription/GeoModel/GeoAdaptors/GeoAdaptors/GeoScintHit.h b/DetectorDescription/GeoModel/GeoAdaptors/GeoAdaptors/GeoScintHit.h new file mode 100644 index 000000000..f9d6068e3 --- /dev/null +++ b/DetectorDescription/GeoModel/GeoAdaptors/GeoAdaptors/GeoScintHit.h @@ -0,0 +1,61 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef GEOADAPTORS_GEOSCINTHIT_h +#define GEOADAPTORS_GEOSCINTHIT_h +//----------------------------------------------------------// +// // +// An adaptor for ScintHits. // +// // +// Joe Boudreau Feb 04. // +// // +// This adaptor class allows ScintHits to behave // +// as if they knew which detector they were in. // +// // +// // +//----------------------------------------------------------// +#include "CLHEP/Geometry/Point3D.h" +class ScintHit; +class VetoID; +class TriggerID; +class PreshowerID; +namespace ScintDD { + class VetoDetectorManager; + class TriggerDetectorManager; + class PreshowerDetectorManager; +} + +class GeoScintHit { + + public: + + // Constructor: + GeoScintHit(const ScintHit & h); + + // Get the absolute global position: + HepGeom::Point3D<double> getGlobalPosition() const; + + // Underlying hit. + const ScintHit &data() const { return *m_hit;} + + // Is this hit ok? + + operator bool () const { return s_veto || s_trigger || s_preshower; } + + private: + + static void init(); + + const ScintHit *m_hit; + static const ScintDD::VetoDetectorManager *s_veto; + static const ScintDD::TriggerDetectorManager *s_trigger; + static const ScintDD::PreshowerDetectorManager *s_preshower; + static const VetoID *s_vID; + static const TriggerID *s_tID; + static const PreshowerID *s_pID; +}; + +#include "GeoAdaptors/GeoScintHit.icc" + +#endif diff --git a/DetectorDescription/GeoModel/GeoAdaptors/GeoAdaptors/GeoScintHit.icc b/DetectorDescription/GeoModel/GeoAdaptors/GeoAdaptors/GeoScintHit.icc new file mode 100644 index 000000000..b1cdaef10 --- /dev/null +++ b/DetectorDescription/GeoModel/GeoAdaptors/GeoAdaptors/GeoScintHit.icc @@ -0,0 +1,71 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "ScintSimEvent/ScintHit.h" +#include "ScintReadoutGeometry/ScintDetectorElement.h" +#include "ScintReadoutGeometry/VetoDetectorManager.h" +// #include "ScintReadoutGeometry/TriggerDetectorManager.h" +// #include "ScintReadoutGeometry/PreshowerDetectorManager.h" +#include "StoreGate/StoreGateSvc.h" +#include "StoreGate/StoreGate.h" +#include "ScintIdentifier/VetoID.h" +// #include "ScintIdentifier/TriggerID.h" +// #include "ScintIdentifier/PreshowerID.h" +#include "GeoPrimitives/CLHEPtoEigenConverter.h" + +inline void GeoScintHit::init() { + + StoreGateSvc *detStore = StoreGate::pointer("DetectorStore"); + if(detStore->retrieve(s_veto,"Veto").isFailure()) + s_veto = 0; +// if(detStore->retrieve(s_trigger,"Trigger").isFailure()) + s_trigger = 0; +// if(detStore->retrieve(s_trigger,"Preshower").isFailure()) + s_preshower = 0; + if(detStore->retrieve(s_vID,"VetoID").isFailure()) + s_vID = 0; +// if(detStore->retrieve(s_tID,"TriggerID").isFailure()) + s_tID = 0; +// if(detStore->retrieve(s_pID,"PreshowerID").isFailure()) + s_pID = 0; +} + +inline GeoScintHit::GeoScintHit (const ScintHit & h) { + m_hit = &h; + if (!s_veto /*|| ! s_trigger || ! s_preshower */) init(); +} + +inline HepGeom::Point3D<double> GeoScintHit::getGlobalPosition() const { + + int Station = m_hit->getStation(); + Identifier id; + const ScintDD::ScintDetectorElement *geoelement=NULL; + if (m_hit->isVeto()) { + id = s_vID->plate_id(Station, + m_hit->getPlate()); + geoelement = s_veto->getDetectorElement(id); + } +// else if (m_hit->isTrigger()) { +// id = s_tID->wafer_id(Barrel, +// m_hit->getPlate()); +// geoelement = s_trigger->getDetectorElement(id); +// } else { +// id = s_pID->wafer_id(Barrel, +// m_hit->getPlate()); +// geoelement = s_preshower->getDetectorElement(id); +// } + + + if (geoelement) { + + const HepGeom::Point3D<double> globalStartPos = Amg::EigenTransformToCLHEP(geoelement->transformHit()) * HepGeom::Point3D<double>(m_hit->localStartPosition()); + + double x=globalStartPos.x(); + double y=globalStartPos.y(); + double z=globalStartPos.z(); + return HepGeom::Point3D<double>(x,y,z); + } + + return HepGeom::Point3D<double>(0.0,0.0,0.0); +} diff --git a/DetectorDescription/GeoModel/GeoAdaptors/src/statics.cxx b/DetectorDescription/GeoModel/GeoAdaptors/src/statics.cxx new file mode 100644 index 000000000..7f0b684ff --- /dev/null +++ b/DetectorDescription/GeoModel/GeoAdaptors/src/statics.cxx @@ -0,0 +1,13 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "GeoAdaptors/GeoScintHit.h" + +const ScintDD::VetoDetectorManager *GeoScintHit::s_veto = 0; +const ScintDD::TriggerDetectorManager *GeoScintHit::s_trigger = 0; +const ScintDD::PreshowerDetectorManager *GeoScintHit::s_preshower = 0; +const VetoID *GeoScintHit::s_vID = 0; +const TriggerID *GeoScintHit::s_tID = 0; +const PreshowerID *GeoScintHit::s_pID = 0; + diff --git a/DetectorDescription/GeoModel/GeoModelSvc/src/GeoModelSvc.cxx b/DetectorDescription/GeoModel/GeoModelSvc/src/GeoModelSvc.cxx index b25d954a9..bd0427a1f 100644 --- a/DetectorDescription/GeoModel/GeoModelSvc/src/GeoModelSvc.cxx +++ b/DetectorDescription/GeoModel/GeoModelSvc/src/GeoModelSvc.cxx @@ -91,10 +91,18 @@ StatusCode GeoModelSvc::initialize() // correctly initialized. // We ensure this is indeed correct by manually initialize it so there is // no more service-ordering problem triggered by jobO mix-up + ATH_MSG_VERBOSE("Initializing DetDescrCnvSvc"); ServiceHandle<IConversionSvc> conversionSvc("DetDescrCnvSvc", this->name()); ATH_CHECK( conversionSvc.retrieve() ); // --- Sebastien + // Working around Gaudi Issue https://gitlab.cern.ch/gaudi/Gaudi/issues/82 + Service* convSvc=dynamic_cast<Service*>(conversionSvc.get()); + if (convSvc->FSMState() < Gaudi::StateMachine::INITIALIZED) { + ATH_MSG_INFO("Explicitly initializing DetDescrCnvSvc"); + convSvc->sysInitialize(); + } + ATH_CHECK( m_detectorTools.retrieve() ); ToolHandleArray< IGeoModelTool >::iterator itPriv = m_detectorTools.begin(), diff --git a/DetectorDescription/GeoModel/GeoModelTest/CMakeLists.txt b/DetectorDescription/GeoModel/GeoModelTest/CMakeLists.txt index 6a60e8242..6072a5a2f 100644 --- a/DetectorDescription/GeoModel/GeoModelTest/CMakeLists.txt +++ b/DetectorDescription/GeoModel/GeoModelTest/CMakeLists.txt @@ -26,4 +26,5 @@ atlas_add_component( GeoModelTest # Install files from the package: #atlas_install_headers( GeoModelTest ) atlas_install_joboptions( share/*.py ) +atlas_install_python_modules( python/*.py ) diff --git a/DetectorDescription/GeoModel/GeoModelTest/python/GeoModelTestConfig.py b/DetectorDescription/GeoModel/GeoModelTest/python/GeoModelTestConfig.py new file mode 100644 index 000000000..0e516aafe --- /dev/null +++ b/DetectorDescription/GeoModel/GeoModelTest/python/GeoModelTestConfig.py @@ -0,0 +1,47 @@ +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator + +def GeoModelTestCfg(flags): + + from FaserGeoModel.FaserGeoModelConfig import FaserGeometryCfg + a = FaserGeometryCfg(flags) + + from GeoModelTest.GeoModelTestConf import GeoModelTestAlg + a.addEventAlgo(GeoModelTestAlg()) + + return a + + +if __name__ == "__main__": + from AthenaCommon.Logging import log, logging + from AthenaCommon.Constants import VERBOSE, INFO + log.setLevel(VERBOSE) + + from AthenaCommon.Configurable import Configurable + Configurable.configurableRun3Behavior = True +# Flag definition + from AthenaConfiguration.AllConfigFlags import ConfigFlags + ConfigFlags.addFlag("GeoModel.FaserVersion", "Faser-00") + ConfigFlags.addFlag("GeoModel.GeoExportFile", "") + ConfigFlags.addFlag("Detector.SimulateVeto", True) +# Flag specification + ConfigFlags.GeoModel.FaserVersion = "FASER-00" + ConfigFlags.GeoModel.GeoExportFile = "faserGeo.db" + ConfigFlags.GeoModel.Align.Dynamic = False + ConfigFlags.lock() + ConfigFlags.dump() + +# Configuration + from AthenaConfiguration.MainServicesConfig import MainServicesSerialCfg + # from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg + + acc = MainServicesSerialCfg() + # acc.merge(PoolReadCfg(ConfigFlags)) + acc.merge(GeoModelTestCfg(ConfigFlags)) + + logging.getLogger('forcomps').setLevel(VERBOSE) + acc.foreach_component("*").OutputLevel = VERBOSE + acc.foreach_component("*ClassID*").OutputLevel = INFO + + acc.printConfig(withDetails=True) + # Execute and finish + acc.run(maxEvents=1) diff --git a/DetectorDescription/GeoModel/GeoModelTest/python/__init__.py b/DetectorDescription/GeoModel/GeoModelTest/python/__init__.py new file mode 100644 index 000000000..c3ff304a0 --- /dev/null +++ b/DetectorDescription/GeoModel/GeoModelTest/python/__init__.py @@ -0,0 +1 @@ +# __author__ = 'Dave Casper' diff --git a/DetectorDescription/GeoModel/GeoModelTest/src/GeoModelTestAlg.cxx b/DetectorDescription/GeoModel/GeoModelTest/src/GeoModelTestAlg.cxx index ddc2adb21..1c2beaf68 100644 --- a/DetectorDescription/GeoModel/GeoModelTest/src/GeoModelTestAlg.cxx +++ b/DetectorDescription/GeoModel/GeoModelTest/src/GeoModelTestAlg.cxx @@ -14,12 +14,11 @@ GeoModelTestAlg::~GeoModelTestAlg() { } StatusCode GeoModelTestAlg::initialize() { - return StatusCode::SUCCESS; } StatusCode GeoModelTestAlg::execute() -{ +{ GeoModelExperiment* theExpt = nullptr; std::vector<std::string> listOfManagers; ATH_CHECK(detStore()->retrieve(theExpt, "FASER")); diff --git a/Scintillator/ScintDetDescr/VetoGeoModel/python/VetoGeoModelConfig.py b/Scintillator/ScintDetDescr/VetoGeoModel/python/VetoGeoModelConfig.py index b69bc0683..6e942ae35 100644 --- a/Scintillator/ScintDetDescr/VetoGeoModel/python/VetoGeoModelConfig.py +++ b/Scintillator/ScintDetDescr/VetoGeoModel/python/VetoGeoModelConfig.py @@ -8,42 +8,42 @@ def getVetoDetectorTool(name="VetoDetectorTool", **kwargs): kwargs.setdefault("RDBAccessSvc", "RDBAccessSvc"); kwargs.setdefault("GeometryDBSvc", "ScintGeometryDBSvc"); kwargs.setdefault("GeoDbTagSvc", "GeoDbTagSvc"); -# from AthenaCommon.DetFlags import DetFlags return CfgMgr.VetoDetectorTool(name, **kwargs) - -###### ComponentAccumulator - -from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator -from AthenaConfiguration.AthConfigFlags import AthConfigFlags from IOVDbSvc.IOVDbSvcConfig import addFoldersSplitOnline def VetoGeometryCfg( flags ): from FaserGeoModel.GeoModelConfig import GeoModelCfg - acc,geoModelSvc = GeoModelCfg( flags ) + acc = GeoModelCfg( flags ) + geoModelSvc = acc.getPrimary() + from GeometryDBSvc.GeometryDBSvcConf import GeometryDBSvc acc.addService(GeometryDBSvc("ScintGeometryDBSvc")) + from VetoGeoModel.VetoGeoModelConf import VetoDetectorTool vetoDetectorTool = VetoDetectorTool() -# vetoDetectorTool.useDynamicAlignFolders = flags.GeoModel.Align.Dynamic + + vetoDetectorTool.useDynamicAlignFolders = flags.GeoModel.Align.Dynamic geoModelSvc.DetectorTools += [ vetoDetectorTool ] - acc.addService(geoModelSvc) + # if flags.GeoModel.Align.Dynamic: # acc.merge(addFoldersSplitOnline(flags,"INDET","/Indet/Onl/AlignL1/ID","/Indet/AlignL1/ID",className="CondAttrListCollection")) # acc.merge(addFoldersSplitOnline(flags,"INDET","/Indet/Onl/AlignL2/SCT","/Indet/AlignL2/SCT",className="CondAttrListCollection")) # acc.merge(addFoldersSplitOnline(flags,"INDET","/Indet/Onl/AlignL3","/Indet/AlignL3",className="AlignableTransformContainer")) # else: - # if (not flags.Detector.SimulateSCT) or flags.Detector.OverlaySCT: + # if (not flags.Detector.SimulateVeto) or flags.Detector.OverlayVeto: # acc.merge(addFoldersSplitOnline(flags,"INDET","/Indet/Onl/Align","/Indet/Align",className="AlignableTransformContainer")) # else: # acc.merge(addFoldersSplitOnline(flags,"INDET","/Indet/Onl/Align","/Indet/Align")) + # if flags.Common.Project is not "AthSimulation": # Protection for AthSimulation builds - # if (not flags.Detector.SimulateSCT) or flags.Detector.OverlaySCT: - # from SCT_ConditionsAlgorithms.SCT_ConditionsAlgorithmsConf import SCT_AlignCondAlg - # sctAlignCondAlg = SCT_AlignCondAlg(name = "SCT_AlignCondAlg", - # UseDynamicAlignFolders = flags.GeoModel.Align.Dynamic) - # acc.addCondAlgo(sctAlignCondAlg) - # from SCT_ConditionsAlgorithms.SCT_ConditionsAlgorithmsConf import SCT_DetectorElementCondAlg - # sctDetectorElementCondAlg = SCT_DetectorElementCondAlg(name = "SCT_DetectorElementCondAlg") - # acc.addCondAlgo(sctDetectorElementCondAlg) + # if (not flags.Detector.SimulateVeto) or flags.Detector.OverlayVeto: + # from VetoConditionsAlgorithms.VetoConditionsAlgorithmsConf import VetoAlignCondAlg + # vetoAlignCondAlg = VetoAlignCondAlg(name = "VetoAlignCondAlg", + # UseDynamicAlignFolders = flags.GeoModel.Align.Dynamic) + # acc.addCondAlgo(vetoAlignCondAlg) + # from VetoConditionsAlgorithms.VetoConditionsAlgorithmsConf import VetoDetectorElementCondAlg + # vetoDetectorElementCondAlg = VetoDetectorElementCondAlg(name = "VetoDetectorElementCondAlg") + # acc.addCondAlgo(vetoDetectorElementCondAlg) + return acc diff --git a/Scintillator/ScintDetDescr/VetoGeoModel/src/VetoStation.cxx b/Scintillator/ScintDetDescr/VetoGeoModel/src/VetoStation.cxx index 9b3c274cc..2e99328b6 100644 --- a/Scintillator/ScintDetDescr/VetoGeoModel/src/VetoStation.cxx +++ b/Scintillator/ScintDetDescr/VetoGeoModel/src/VetoStation.cxx @@ -102,7 +102,7 @@ VetoStation::build(VetoIdentifier id) // // We reduce to allow some alignment clearance // layerLength -= 2*m_zClearance; - double activeLength = m_length - m_safety/2; + double activeDepth = m_thickness - m_safety/2; double plateThickness = m_plate->thickness(); for (int iPlate = 0; iPlate < m_numPlates; iPlate++) { @@ -111,7 +111,7 @@ VetoStation::build(VetoIdentifier id) id.setPlate(iPlate); GeoAlignableTransform* transform = new GeoAlignableTransform(GeoTrf::Translate3D(0.0, 0.0, - (plateThickness - activeLength)/2 + iPlate * m_platePitch)); + (plateThickness - activeDepth)/2 + iPlate * m_platePitch)); station->add(transform); GeoVPhysVol* platePV = m_plate->build(id); station->add(platePV); diff --git a/Scintillator/ScintDetDescr/VetoGeoModel/test/VetoGMConfig_test.py b/Scintillator/ScintDetDescr/VetoGeoModel/test/VetoGMConfig_test.py new file mode 100644 index 000000000..1f75ad6d5 --- /dev/null +++ b/Scintillator/ScintDetDescr/VetoGeoModel/test/VetoGMConfig_test.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python +"""Run tests on VetoGeoModel configuration + +Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +""" +if __name__ == "__main__": + from AthenaCommon.Configurable import Configurable + Configurable.configurableRun3Behavior=1 + from CalypsoConfiguration.AllConfigFlags import ConfigFlags + from AthenaConfiguration.TestDefaults import defaultTestFiles + + ConfigFlags.Input.Files = defaultTestFiles.HITS + ConfigFlags.IOVDb.GlobalTag = "OFLCOND-MC16-SDR-16" + # ConfigFlags.Detector.SimulatePixel = False + ConfigFlags.Detector.SimulateVeto = False + # ConfigFlags.Detector.SimulateTRT = False + ConfigFlags.GeoModel.Align.Dynamic = False + ConfigFlags.lock() + + from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator + from VetoGeoModel.VetoGeoModelConfig import VetoGeometryCfg + acc = VetoGeometryCfg(ConfigFlags) + f=open('VetoGeometryCfg.pkl','w') + acc.store(f) + f.close() diff --git a/Scintillator/ScintEventCnv/ScintSimAthenaPool/CMakeLists.txt b/Scintillator/ScintEventCnv/ScintSimAthenaPool/CMakeLists.txt new file mode 100644 index 000000000..484823435 --- /dev/null +++ b/Scintillator/ScintEventCnv/ScintSimAthenaPool/CMakeLists.txt @@ -0,0 +1,37 @@ +################################################################################ +# Package: ScintSimEventAthenaPool +################################################################################ + +# Declare the package name: +atlas_subdir( ScintSimEventAthenaPool ) + +# Declare the package's dependencies: +atlas_depends_on_subdirs( PRIVATE + AtlasTest/TestTools + Database/AthenaPOOL/AthenaPoolCnvSvc + Database/AthenaPOOL/AthenaPoolUtilities + Database/AtlasSealCLHEP + GaudiKernel + Scintillator/ScintEventCnv/ScintSimEventTPCnv + Scintillator/ScintSimEvent ) + +# External dependencies: +find_package( ROOT COMPONENTS Core Tree MathCore Hist RIO pthread ) + +# Component(s) in the package: +atlas_add_poolcnv_library( ScintSimEventAthenaPoolPoolCnv + src/*.cxx + FILES ScintSimEvent/ScintHitCollection.h + INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} + LINK_LIBRARIES ${ROOT_LIBRARIES} AthenaPoolCnvSvcLib AthenaPoolUtilities AtlasSealCLHEP GaudiKernel ScintSimEventTPCnv ScintSimEvent ) + +atlas_add_dictionary( ScintSimEventAthenaPoolCnvDict + ScintSimEventAthenaPool/ScintSimEventAthenaPoolCnvDict.h + ScintSimEventAthenaPool/selection.xml + INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} + LINK_LIBRARIES ${ROOT_LIBRARIES} AthenaPoolCnvSvcLib AthenaPoolUtilities AtlasSealCLHEP GaudiKernel ScintSimEventTPCnv ScintSimEvent ) + +# Install files from the package: +atlas_install_headers( ScintSimEventAthenaPool ) +atlas_install_joboptions( share/*.py ) + diff --git a/Scintillator/ScintEventCnv/ScintSimAthenaPool/ScintSimEventAthenaPool/ScintSimDataCollection_p1.h b/Scintillator/ScintEventCnv/ScintSimAthenaPool/ScintSimEventAthenaPool/ScintSimDataCollection_p1.h new file mode 100644 index 000000000..2298acdeb --- /dev/null +++ b/Scintillator/ScintEventCnv/ScintSimAthenaPool/ScintSimEventAthenaPool/ScintSimDataCollection_p1.h @@ -0,0 +1,4 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + diff --git a/Scintillator/ScintEventCnv/ScintSimAthenaPool/ScintSimEventAthenaPool/ScintSimData_p1.h b/Scintillator/ScintEventCnv/ScintSimAthenaPool/ScintSimEventAthenaPool/ScintSimData_p1.h new file mode 100644 index 000000000..2298acdeb --- /dev/null +++ b/Scintillator/ScintEventCnv/ScintSimAthenaPool/ScintSimEventAthenaPool/ScintSimData_p1.h @@ -0,0 +1,4 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + diff --git a/Scintillator/ScintEventCnv/ScintSimAthenaPool/ScintSimEventAthenaPool/ScintSimEventAthenaPoolCnvDict.h b/Scintillator/ScintEventCnv/ScintSimAthenaPool/ScintSimEventAthenaPool/ScintSimEventAthenaPoolCnvDict.h new file mode 100644 index 000000000..e17d593c9 --- /dev/null +++ b/Scintillator/ScintEventCnv/ScintSimAthenaPool/ScintSimEventAthenaPool/ScintSimEventAthenaPoolCnvDict.h @@ -0,0 +1,9 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef SCINTSIMEVENTATHENAPOOLDICT_H +#define SCINTSIMEVENTATHENAPOOLDICT_H + + +#endif diff --git a/Scintillator/ScintEventCnv/ScintSimAthenaPool/ScintSimEventAthenaPool/selection.xml b/Scintillator/ScintEventCnv/ScintSimAthenaPool/ScintSimEventAthenaPool/selection.xml new file mode 100644 index 000000000..2eff49dff --- /dev/null +++ b/Scintillator/ScintEventCnv/ScintSimAthenaPool/ScintSimEventAthenaPool/selection.xml @@ -0,0 +1,2 @@ +<lcgdict> +</lcgdict> diff --git a/Scintillator/ScintEventCnv/ScintSimAthenaPool/src/ScintHitCollectionCnv.cxx b/Scintillator/ScintEventCnv/ScintSimAthenaPool/src/ScintHitCollectionCnv.cxx new file mode 100644 index 000000000..88592d298 --- /dev/null +++ b/Scintillator/ScintEventCnv/ScintSimAthenaPool/src/ScintHitCollectionCnv.cxx @@ -0,0 +1,32 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#include "ScintSimEventTPCnv/ScintHits/ScintHitCollectionCnv_p1.h" +#include "ScintSimEventTPCnv/ScintHits/ScintHit_p1.h" +#include "ScintHitCollectionCnv.h" + + +ScintHitCollection_PERS* ScintHitCollectionCnv::createPersistent(ScintHitCollection* transCont) { + MsgStream mlog(msgSvc(), "ScintHitCollectionConverter" ); + ScintHitCollectionCnv_PERS converter; + ScintHitCollection_PERS *persObj = converter.createPersistent( transCont, mlog ); + return persObj; +} + + +ScintHitCollection* ScintHitCollectionCnv::createTransient() { + MsgStream mlog(msgSvc(), "ScintHitCollectionConverter" ); + ScintHitCollectionCnv_p1 converter_p1; + + static const pool::Guid p1_guid("B2573A16-4B46-4E1E-98E3-F93421680779"); + + ScintHitCollection *trans_cont(0); + if( this->compareClassGuid(p1_guid)) { + std::unique_ptr< ScintHitCollection_p1 > col_vect( this->poolReadObject< ScintHitCollection_p1 >() ); + trans_cont = converter_p1.createTransient( col_vect.get(), mlog ); + } else { + throw std::runtime_error("Unsupported persistent version of Data container"); + } + return trans_cont; +} diff --git a/Scintillator/ScintEventCnv/ScintSimAthenaPool/src/ScintHitCollectionCnv.h b/Scintillator/ScintEventCnv/ScintSimAthenaPool/src/ScintHitCollectionCnv.h new file mode 100644 index 000000000..ca9c329dd --- /dev/null +++ b/Scintillator/ScintEventCnv/ScintSimAthenaPool/src/ScintHitCollectionCnv.h @@ -0,0 +1,29 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef SCINTHITCOLLECTIONCNV +#define SCINTHITCOLLECTIONCNV + +#include "ScintSimEvent/ScintHitCollection.h" +#include "ScintSimEventTPCnv/ScintHits/ScintHitCollection_p1.h" +#include "ScintSimEventTPCnv/ScintHits/ScintHitCollectionCnv_p1.h" +#include "AthenaPoolCnvSvc/T_AthenaPoolCustomCnv.h" +// Gaudi +#include "GaudiKernel/MsgStream.h" +// typedef to the latest persistent version +typedef ScintHitCollection_p1 ScintHitCollection_PERS; +typedef ScintHitCollectionCnv_p1 ScintHitCollectionCnv_PERS; + +class ScintHitCollectionCnv : public T_AthenaPoolCustomCnv<ScintHitCollection, ScintHitCollection_PERS > { + friend class CnvFactory<ScintHitCollectionCnv>; +public: + ScintHitCollectionCnv(ISvcLocator* svcloc) : + T_AthenaPoolCustomCnv<ScintHitCollection, ScintHitCollection_PERS >( svcloc) {} +protected: + ScintHitCollection_PERS* createPersistent(ScintHitCollection* transCont); + ScintHitCollection* createTransient (); +}; + + +#endif diff --git a/Scintillator/ScintEventCnv/ScintSimEventTPCnv/CMakeLists.txt b/Scintillator/ScintEventCnv/ScintSimEventTPCnv/CMakeLists.txt new file mode 100644 index 000000000..ff9e4ed64 --- /dev/null +++ b/Scintillator/ScintEventCnv/ScintSimEventTPCnv/CMakeLists.txt @@ -0,0 +1,37 @@ +############################################################################### +# Package: ScintSimEventTPCnv +################################################################################ + +# Declare the package name: +atlas_subdir( ScintSimEventTPCnv ) + +# Declare the package's dependencies: +atlas_depends_on_subdirs( PUBLIC + Database/AthenaPOOL/AthenaPoolCnvSvc + GaudiKernel + Generators/GeneratorObjectsTPCnv + Scintillator/ScintSimEvent + PRIVATE + AtlasTest/TestTools + Control/StoreGate + DetectorDescription/Identifier ) + +# External dependencies: +find_package( CLHEP ) +find_package( ROOT COMPONENTS Core Tree MathCore Hist RIO pthread ) + +# Component(s) in the package: +atlas_add_library( ScintSimEventTPCnv + src/ScintHits/*.cxx + PUBLIC_HEADERS ScintSimEventTPCnv + PRIVATE_INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} + PRIVATE_DEFINITIONS ${CLHEP_DEFINITIONS} + LINK_LIBRARIES GaudiKernel GeneratorObjectsTPCnv ScintSimEvent AthenaPoolCnvSvcLib StoreGateLib SGtests + PRIVATE_LINK_LIBRARIES ${ROOT_LIBRARIES} ${CLHEP_LIBRARIES} TestTools Identifier ) + +atlas_add_dictionary( ScintSimEventTPCnvDict + ScintSimEventTPCnv/ScintSimEventTPCnvDict.h + ScintSimEventTPCnv/selection.xml + INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} + LINK_LIBRARIES ${ROOT_LIBRARIES} ${CLHEP_LIBRARIES} AthenaPoolCnvSvcLib GaudiKernel GeneratorObjectsTPCnv ScintSimEvent TestTools StoreGateLib SGtests Identifier ScintSimEventTPCnv ) + diff --git a/Scintillator/ScintEventCnv/ScintSimEventTPCnv/ScintSimEventTPCnv/ScintHits/ScintHitCnv_p1.h b/Scintillator/ScintEventCnv/ScintSimEventTPCnv/ScintSimEventTPCnv/ScintHits/ScintHitCnv_p1.h new file mode 100644 index 000000000..0edaf0168 --- /dev/null +++ b/Scintillator/ScintEventCnv/ScintSimEventTPCnv/ScintSimEventTPCnv/ScintHits/ScintHitCnv_p1.h @@ -0,0 +1,34 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef SCINTHITCNV_P1_H +#define SCINTHITCNV_P1_H + +/* +Transient/Persistent converter for ScintHit class +Author: Davide Costanzo +*/ + +#include "ScintSimEvent/ScintHit.h" +#include "ScintHit_p1.h" + +#include "AthenaPoolCnvSvc/T_AthenaPoolTPConverter.h" + +class MsgStream; + + +class ScintHitCnv_p1 : public T_AthenaPoolTPCnvBase<ScintHit, ScintHit_p1> +{ +public: + + ScintHitCnv_p1() {} + + virtual void persToTrans(const ScintHit_p1* persObj, ScintHit* +transObj, MsgStream &log); + virtual void transToPers(const ScintHit* transObj, ScintHit_p1* +persObj, MsgStream &log); +}; + + +#endif diff --git a/Scintillator/ScintEventCnv/ScintSimEventTPCnv/ScintSimEventTPCnv/ScintHits/ScintHitCollectionCnv_p1.h b/Scintillator/ScintEventCnv/ScintSimEventTPCnv/ScintSimEventTPCnv/ScintHits/ScintHitCollectionCnv_p1.h new file mode 100644 index 000000000..8353e92b8 --- /dev/null +++ b/Scintillator/ScintEventCnv/ScintSimEventTPCnv/ScintSimEventTPCnv/ScintHits/ScintHitCollectionCnv_p1.h @@ -0,0 +1,41 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef SCINTHITCOLLECTIONCNV_P1_H +#define SCINTHITCOLLECTIONCNV_P1_H + +// SiHitCollectionCnv_p1, T/P separation of Scint Hits +// author D.Costanzo <davide.costanzo@cern.ch> +// author O.Arnaez <olivier.arnaez@cern.ch> + +#include "AthenaPoolCnvSvc/T_AthenaPoolTPConverter.h" +#include "ScintSimEvent/ScintHitCollection.h" +#include "ScintHitCollection_p1.h" + + +class ScintHitCollectionCnv_p1 : public T_AthenaPoolTPCnvBase<ScintHitCollection, ScintHitCollection_p1> +{ + public: + + ScintHitCollectionCnv_p1() {}; + + virtual ScintHitCollection* createTransient(const ScintHitCollection_p1* persObj, MsgStream &log); + + virtual void persToTrans(const ScintHitCollection_p1* persCont, + ScintHitCollection* transCont, + MsgStream &log) ; + virtual void transToPers(const ScintHitCollection* transCont, + ScintHitCollection_p1* persCont, + MsgStream &log) ; + + private: + + static const double m_persEneUnit; + static const double m_persLenUnit; + static const double m_persAngUnit; + static const double m_2bHalfMaximum; + static const int m_2bMaximum; +}; + +#endif diff --git a/Scintillator/ScintEventCnv/ScintSimEventTPCnv/ScintSimEventTPCnv/ScintHits/ScintHitCollection_p1.h b/Scintillator/ScintEventCnv/ScintSimEventTPCnv/ScintSimEventTPCnv/ScintHits/ScintHitCollection_p1.h new file mode 100644 index 000000000..d9c10916a --- /dev/null +++ b/Scintillator/ScintEventCnv/ScintSimEventTPCnv/ScintSimEventTPCnv/ScintHits/ScintHitCollection_p1.h @@ -0,0 +1,57 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef SCINTHITCOLLECTION_P1_H +#define SCINTHITCOLLECTION_P1_H + +/* + +Authors: Davide Costanzo Rob Duxfield + +*/ + +#include <vector> +#include <string> + +class ScintHitCollection_p1 +{ + public: +/// Default constructor + ScintHitCollection_p1 (); + //private: + + std::vector<float> m_hit1_meanTime; // 1 element per string + std::vector<float> m_hit1_x0; // + std::vector<float> m_hit1_y0; // + std::vector<float> m_hit1_z0; // + std::vector<float> m_hit1_theta; // + std::vector<float> m_hit1_phi; // + std::vector<unsigned short> m_nHits; // + + std::vector<unsigned short> m_hitEne_2b; // 1 element per hit + std::vector<unsigned short> m_hitLength_2b; // + + std::vector<unsigned short> m_dTheta; // 1 element per hit except for first hit in string + std::vector<unsigned short> m_dPhi; // + + std::vector<float> m_hitEne_4b; // 1 element per hit with m_hitEne_2b[i] == 2**16 + + std::vector<float> m_hitLength_4b; // 1 element per hit with m_hitLength_2b[i] == 2**16 + + std::vector<unsigned long> m_barcode; + std::vector<unsigned short> m_mcEvtIndex; + std::vector<char> m_evtColl; + std::vector<unsigned short> m_nBC; + + std::vector<unsigned long> m_id; + std::vector<unsigned short> m_nId; +}; + + +// inlines + +inline +ScintHitCollection_p1::ScintHitCollection_p1 () {} + +#endif diff --git a/Scintillator/ScintEventCnv/ScintSimEventTPCnv/ScintSimEventTPCnv/ScintHits/ScintHit_p1.h b/Scintillator/ScintEventCnv/ScintSimEventTPCnv/ScintSimEventTPCnv/ScintHits/ScintHit_p1.h new file mode 100644 index 000000000..a4f31c5bf --- /dev/null +++ b/Scintillator/ScintEventCnv/ScintSimEventTPCnv/ScintSimEventTPCnv/ScintHits/ScintHit_p1.h @@ -0,0 +1,19 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef SCINTHIT_P1_H +#define SCINTHIT_P1_H + +#include "GeneratorObjectsTPCnv/HepMcParticleLink_p2.h" + +class ScintHit_p1 { + public: + float m_stX, m_stY, m_stZ; + float m_enX, m_enY, m_enZ; + float m_energyLoss; // deposited energy + float m_meanTime; // time of energy deposition + HepMcParticleLink_p2 m_partLink; + unsigned int m_ID; +}; +#endif diff --git a/Scintillator/ScintEventCnv/ScintSimEventTPCnv/ScintSimEventTPCnv/ScintSimEventTPCnvDict.h b/Scintillator/ScintEventCnv/ScintSimEventTPCnv/ScintSimEventTPCnv/ScintSimEventTPCnvDict.h new file mode 100644 index 000000000..b18bdb772 --- /dev/null +++ b/Scintillator/ScintEventCnv/ScintSimEventTPCnv/ScintSimEventTPCnv/ScintSimEventTPCnvDict.h @@ -0,0 +1,20 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef SCINTEVENTTPCNV_SCINTSIMEVENTTPCNVDICT_H +#define SCINTEVENTTPCNV_SCINTSIMEVENTTPCNVDICT_H + +//----------------------------------------------------------------------------- +// +// file: ScintSimEventTPCnvDict_p1.h +// +//----------------------------------------------------------------------------- + + +#include "ScintSimEventTPCnv/ScintHits/ScintHitCnv_p1.h" +#include "ScintSimEventTPCnv/ScintHits/ScintHitCollectionCnv_p1.h" +#include "ScintSimEventTPCnv/ScintHits/ScintHitCollection_p1.h" +#include "ScintSimEventTPCnv/ScintHits/ScintHit_p1.h" + +#endif // SCINTEVENTTPCNV_INDETSIMEVENTTPCNVDICT_H diff --git a/Scintillator/ScintEventCnv/ScintSimEventTPCnv/ScintSimEventTPCnv/selection.xml b/Scintillator/ScintEventCnv/ScintSimEventTPCnv/ScintSimEventTPCnv/selection.xml new file mode 100644 index 000000000..6b0d915ea --- /dev/null +++ b/Scintillator/ScintEventCnv/ScintSimEventTPCnv/ScintSimEventTPCnv/selection.xml @@ -0,0 +1,7 @@ +<lcgdict> + + <!-- ScintHits --> + <class name="ScintHit_p1" /> + <class name="std::vector<ScintHit_p1>" /> + <class name="ScintHitCollection_p1" id="B2573A16-4B46-4E1E-98E3-F93421680779" /> +</lcgdict> diff --git a/Scintillator/ScintEventCnv/ScintSimEventTPCnv/src/ScintHits/ScintHitCnv_p1.cxx b/Scintillator/ScintEventCnv/ScintSimEventTPCnv/src/ScintHits/ScintHitCnv_p1.cxx new file mode 100644 index 000000000..870821f8f --- /dev/null +++ b/Scintillator/ScintEventCnv/ScintSimEventTPCnv/src/ScintHits/ScintHitCnv_p1.cxx @@ -0,0 +1,54 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "ScintSimEvent/ScintHit.h" +#include "Identifier/Identifier.h" +#include "GeneratorObjectsTPCnv/HepMcParticleLinkCnv_p2.h" + +#include "ScintSimEventTPCnv/ScintHits/ScintHit_p1.h" +#include "ScintSimEventTPCnv/ScintHits/ScintHitCnv_p1.h" + + +void +ScintHitCnv_p1::persToTrans(const ScintHit_p1* persObj, ScintHit* transObj, MsgStream &log) +{ + HepMcParticleLinkCnv_p2 HepMcPLCnv; + HepMcParticleLink link; + HepMcPLCnv.persToTrans(&(persObj->m_partLink),&link, log); + + *transObj = ScintHit (HepGeom::Point3D<double> (persObj->m_stX, + persObj->m_stY, + persObj->m_stZ), + HepGeom::Point3D<double> (persObj->m_enX, + persObj->m_enY, + persObj->m_enZ), + persObj->m_energyLoss, + persObj->m_meanTime, + link, + persObj->m_ID + ); +} + + +void +ScintHitCnv_p1::transToPers(const ScintHit* transObj, ScintHit_p1* persObj, MsgStream &log) +{ +// if (log.level() <= MSG::DEBUG) log << MSG::DEBUG << "ScintHitCnv_p1::transToPers called " << endmsg; + HepMcParticleLinkCnv_p2 HepMcPLCnv; + + HepGeom::Point3D<double> st = transObj->localStartPosition(); + persObj->m_stX = st.x(); + persObj->m_stY = st.y(); + persObj->m_stZ = st.z(); + + HepGeom::Point3D<double> en = transObj->localEndPosition(); + persObj->m_enX = en.x(); + persObj->m_enY = en.y(); + persObj->m_enZ = en.z(); + + persObj->m_energyLoss = transObj->energyLoss(); + persObj->m_meanTime = transObj->meanTime(); + persObj->m_ID = transObj->identify(); + HepMcPLCnv.transToPers(&(transObj->particleLink()),&(persObj->m_partLink), log); +} diff --git a/Scintillator/ScintEventCnv/ScintSimEventTPCnv/src/ScintHits/ScintHitCollectionCnv_p1.cxx b/Scintillator/ScintEventCnv/ScintSimEventTPCnv/src/ScintHits/ScintHitCollectionCnv_p1.cxx new file mode 100644 index 000000000..08e4c55e9 --- /dev/null +++ b/Scintillator/ScintEventCnv/ScintSimEventTPCnv/src/ScintHits/ScintHitCollectionCnv_p1.cxx @@ -0,0 +1,312 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#include "ScintSimEvent/ScintHit.h" +#include "ScintSimEvent/ScintHitCollection.h" +#include "ScintSimEventTPCnv/ScintHits/ScintHitCollection_p1.h" +#include "ScintSimEventTPCnv/ScintHits/ScintHitCollectionCnv_p1.h" +#include "GeneratorObjects/HepMcParticleLink.h" + +#include <cmath> + +//CLHEP +#include "CLHEP/Geometry/Point3D.h" +// Gaudi +#include "GaudiKernel/MsgStream.h" +// Athena +#include "StoreGate/StoreGateSvc.h" + +// * * * stolen from eflowRec * * * // +inline double phicorr(double a) +{ + if (a <= -M_PI) + { + return a+(2*M_PI*floor(-(a-M_PI)/(2*M_PI))); + } + else if (a > M_PI) + { + return a-(2*M_PI*floor((a+M_PI)/(2*M_PI))); + } + else + { + return a; + } +} + +// * * * stolen from eflowRec * * * // +inline double cycle(double a, double b) +{ + double del = b-a; + if (del > M_PI) + { + return a+2.0*M_PI; + } + else if (del < -M_PI) + { + return a-2.0*M_PI; + } + else + { + return a; + } +} + + +const double ScintHitCollectionCnv_p1::m_persEneUnit = 1.0e-5; +const double ScintHitCollectionCnv_p1::m_persLenUnit = 1.0e-5; +const double ScintHitCollectionCnv_p1::m_persAngUnit = 1.0e-5; +const double ScintHitCollectionCnv_p1::m_2bHalfMaximum = pow(2.0, 15.0); +const int ScintHitCollectionCnv_p1::m_2bMaximum = (unsigned short)(-1); + + +void ScintHitCollectionCnv_p1::transToPers(const ScintHitCollection* transCont, ScintHitCollection_p1* persCont, MsgStream &/*log*/) +{ + // Finds hits belonging to a "string" (in which the end point of one hit is the same as the start point of the next) and + // persistifies the end point of each hit plus the start point of the first hit in each string. + // + // Further compression is achieved by optimising the storage of the position vectors:- start (x,y,z) and (theta,phi) of + // first hit are stored as floats, (delta_theta,delta_phi) relative to the fisrst hit are stored as 2 byte numbers and + // used to specify the hit direction. All hit lengths are stored as 2 byte numbers. + // + // Additional savings are achieved by storing the energy loss for each hit as a 2 byte number and only storing the mean + // time of the first hit per string. + // + // See http://indico.cern.ch/getFile.py/access?contribId=11&resId=2&materialId=slides&confId=30893 for more info. + + static const double dRcut = 1.0e-7; + static const double dTcut = 1.0; + + const HepMcParticleLink * lastLink=nullptr; + int lastId = -1; + double stringFirstTheta = 0.0; + double stringFirstPhi = 0.0; + double lastT = 0.0; + double persSumE = 0.0; + double transSumE = 0.0; + unsigned int idx = 0; + unsigned int endBC = 0; + unsigned int endId = 0; + unsigned int endHit = 0; + HepGeom::Point3D<double> lastTransEnd(0.0, 0.0, 0.0); + HepGeom::Point3D<double> lastPersEnd(0.0, 0.0, 0.0); + + for (ScintHitCollection::const_iterator it = transCont->begin(); it != transCont->end(); ++it) { + + ScintHitCollection::const_iterator siHit = it; + + + if ( !lastLink || (siHit->particleLink() != *lastLink) ) { + + // store barcode once for set of consecutive hits with same barcode + + lastLink = &(siHit->particleLink()); + persCont->m_barcode.push_back(lastLink->barcode()); + persCont->m_mcEvtIndex.push_back(lastLink->eventIndex()); + persCont->m_evtColl.push_back(lastLink->getEventCollectionAsChar()); + + if (idx > 0) { + persCont->m_nBC.push_back(idx - endBC); + endBC = idx; + } + } + + if ( (int)siHit->identify() != lastId ) { + + // store id once for set of consecutive hits with same barcode + + lastId = siHit->identify(); + persCont->m_id.push_back(lastId); + + if (idx > 0) { + persCont->m_nId.push_back(idx - endId); + endId = idx; + } + } + + HepGeom::Point3D<double> st = siHit->localStartPosition(); + HepGeom::Point3D<double> en = siHit->localEndPosition(); + + const double dx = st.x() - lastTransEnd.x(); + const double dy = st.y() - lastTransEnd.y(); + const double dz = st.z() - lastTransEnd.z(); + const double t = siHit->meanTime(); + + const double dRLast = sqrt(dx * dx + dy * dy + dz * dz); // dR between end of previous hit and start of current one + const double dTLast = fabs(t - lastT); + + CLHEP::Hep3Vector direction(0.0, 0.0, 0.0); + double theta = 0.0; + double phi = 0.0; + bool startNewString = false; + + if (dRLast < dRcut && dTLast < dTcut) { + + // hit is part of existing string + + direction = CLHEP::Hep3Vector( en.x() - lastPersEnd.x(), en.y() - lastPersEnd.y(), en.z() - lastPersEnd.z() ); + + theta = direction.theta(); + phi = phicorr( direction.phi() ); + + const int dTheta_2b = (int)( (theta - stringFirstTheta) / m_persAngUnit + m_2bHalfMaximum + 0.5 ); + const int dPhi_2b = (int)( (cycle(phi, stringFirstPhi) - stringFirstPhi) / m_persAngUnit + m_2bHalfMaximum + 0.5 ); + + if ( dTheta_2b < m_2bMaximum && dTheta_2b >= 0 && dPhi_2b < m_2bMaximum && dPhi_2b >= 0) { + persCont->m_dTheta.push_back(dTheta_2b); + persCont->m_dPhi.push_back(dPhi_2b); + theta = stringFirstTheta + ( (double)dTheta_2b - m_2bHalfMaximum ) * m_persAngUnit; + phi = stringFirstPhi + ( (double)dPhi_2b - m_2bHalfMaximum ) * m_persAngUnit; + phi = phicorr(phi); + } + else { + startNewString = true; + } + } + + if (startNewString || dRLast >= dRcut || dTLast >= dTcut) { + + // begin new hit string + + direction = CLHEP::Hep3Vector( en.x() - st.x(), en.y() - st.y(), en.z() - st.z() ); + + theta = direction.theta(); + phi = phicorr( direction.phi() ); + + persCont->m_hit1_meanTime.push_back(t); + persCont->m_hit1_x0.push_back(st.x()); + persCont->m_hit1_y0.push_back(st.y()); + persCont->m_hit1_z0.push_back(st.z()); + persCont->m_hit1_theta.push_back(theta); + persCont->m_hit1_phi.push_back(phi); + + lastPersEnd = HepGeom::Point3D<double>(st.x(), st.y(), st.z()); + + stringFirstTheta = theta; + stringFirstPhi = phi; + + if (idx > 0) { + persCont->m_nHits.push_back(idx - endHit); + endHit = idx; + } + } + + lastTransEnd = HepGeom::Point3D<double>(en.x(), en.y(), en.z()); + transSumE += siHit->energyLoss(); + + const int eneLoss_2b = (int)((transSumE - persSumE) / m_persEneUnit + 0.5); // calculated to allow recovery sum over + // whole hit string to chosen precision + + const int hitLength_2b = (int)(direction.mag() / m_persLenUnit + 0.5); // calculated to give the correct position to + // the chosen precision, NOT the length of the + // hit (small difference in practice). + double eneLoss = 0.0; + + if (eneLoss_2b >= m_2bMaximum) { + eneLoss = siHit->energyLoss(); + persCont->m_hitEne_2b.push_back(m_2bMaximum); + persCont->m_hitEne_4b.push_back(eneLoss); + } + else { + eneLoss = eneLoss_2b * m_persEneUnit; + persCont->m_hitEne_2b.push_back(eneLoss_2b); + } + + double length = 0.0; + + if (hitLength_2b >= m_2bMaximum) { + length = direction.mag(); + persCont->m_hitLength_2b.push_back(m_2bMaximum); + persCont->m_hitLength_4b.push_back(direction.mag()); + } + else { + length = hitLength_2b * m_persLenUnit; + persCont->m_hitLength_2b.push_back(hitLength_2b); + } + + CLHEP::Hep3Vector persDir(length, 0.0, 0.0); + persDir.setTheta(theta); + persDir.setPhi(phi); + + lastPersEnd = (CLHEP::Hep3Vector)lastPersEnd + persDir; + persSumE += eneLoss; + lastT = t; + + ++idx; + } + + persCont->m_nBC.push_back(idx - endBC); + persCont->m_nId.push_back(idx - endId); + persCont->m_nHits.push_back(idx - endHit); +} + + +ScintHitCollection* ScintHitCollectionCnv_p1::createTransient(const ScintHitCollection_p1* persObj, MsgStream &log) { + std::unique_ptr<ScintHitCollection> trans(std::make_unique<ScintHitCollection>("DefaultCollectionName",persObj->m_nHits.size())); + persToTrans(persObj, trans.get(), log); + return(trans.release()); +} + + +void ScintHitCollectionCnv_p1::persToTrans(const ScintHitCollection_p1* persCont, ScintHitCollection* transCont, MsgStream &/*log*/) +{ + unsigned int hitCount = 0; + unsigned int angleCount = 0; + unsigned int idxBC = 0; + unsigned int idxId = 0; + unsigned int idxEne4b = 0; + unsigned int idxLen4b = 0; + unsigned int endHit = 0; + unsigned int endBC = 0; + unsigned int endId = 0; + + for (unsigned int i = 0; i < persCont->m_nHits.size(); i++) { + + if (persCont->m_nHits[i]) { + + const unsigned int start = endHit; + endHit += persCont->m_nHits[i]; + + const double t0 = persCont->m_hit1_meanTime[i]; + const double theta0 = persCont->m_hit1_theta[i]; + const double phi0 = persCont->m_hit1_phi[i]; + HepGeom::Point3D<double> endLast(persCont->m_hit1_x0[i], persCont->m_hit1_y0[i], persCont->m_hit1_z0[i]); + + for (unsigned int j = start; j < endHit; j++) { + + if (j >= endBC + persCont->m_nBC[idxBC]) + endBC += persCont->m_nBC[idxBC++]; + + if (j >= endId + persCont->m_nId[idxId]) + endId += persCont->m_nId[idxId++]; + + const double eneLoss_2b = persCont->m_hitEne_2b[hitCount]; + const double hitLength_2b = persCont->m_hitLength_2b[hitCount]; + + const double eneLoss = (eneLoss_2b < m_2bMaximum) ? eneLoss_2b * m_persEneUnit : persCont->m_hitEne_4b[idxEne4b++]; + const double length = (hitLength_2b < m_2bMaximum) ? hitLength_2b * m_persLenUnit : persCont->m_hitLength_4b[idxLen4b++]; + + const double dTheta = (j > start) ? ((double)persCont->m_dTheta[angleCount] - m_2bHalfMaximum) * m_persAngUnit : 0.0; + const double dPhi = (j > start) ? ((double)persCont->m_dPhi[angleCount] - m_2bHalfMaximum) * m_persAngUnit : 0.0; + + const double meanTime = t0; + const double theta = theta0 + dTheta; + const double phi = phicorr(phi0 + dPhi); + + CLHEP::Hep3Vector r(length, 0.0, 0.0); + r.setTheta(theta); + r.setPhi(phi); + + HepGeom::Point3D<double> endThis( endLast + r ); + + HepMcParticleLink partLink( persCont->m_barcode[idxBC], persCont->m_mcEvtIndex[idxBC], HepMcParticleLink::ExtendedBarCode::eventCollectionFromChar(persCont->m_evtColl[idxBC]), HepMcParticleLink::IS_INDEX ); + transCont->Emplace( endLast, endThis, eneLoss, meanTime, partLink, persCont->m_id[idxId]); + + endLast = endThis; + + ++hitCount; + if (j > start) ++angleCount; + } + } + } +} diff --git a/Scintillator/ScintG4/VetoG4_SD/CMakeLists.txt b/Scintillator/ScintG4/VetoG4_SD/CMakeLists.txt new file mode 100644 index 000000000..5598c4ea9 --- /dev/null +++ b/Scintillator/ScintG4/VetoG4_SD/CMakeLists.txt @@ -0,0 +1,36 @@ +################################################################################ +# Package: VetoG4_SD +################################################################################ + +# Declare the package name: +atlas_subdir( VetoG4_SD ) + +# Declare the package's dependencies: +atlas_depends_on_subdirs( PRIVATE + Control/StoreGate + GaudiKernel + Scintillator/ScintSimEvent + Simulation/G4Atlas/G4AtlasTools + Simulation/G4Sim/MCTruth + ) + +# External dependencies: +find_package( CLHEP ) +find_package( Geant4 ) +find_package( XercesC ) + +# Component(s) in the package: +atlas_add_component( VetoG4_SD + src/*.cxx + src/components/*.cxx + INCLUDE_DIRS ${GEANT4_INCLUDE_DIRS} ${XERCESC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} + LINK_LIBRARIES ${GEANT4_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} StoreGateLib SGtests GaudiKernel ScintSimEvent G4AtlasToolsLib MCTruth ) + +atlas_add_test( VetoG4_SDToolConfig_test + SCRIPT test/VetoG4_SDToolConfig_test.py + PROPERTIES TIMEOUT 300 ) + +# Install files from the package: +atlas_install_python_modules( python/*.py ) +atlas_install_scripts( test/*.py ) + diff --git a/Scintillator/ScintG4/VetoG4_SD/python/VetoG4_SDConfig.py b/Scintillator/ScintG4/VetoG4_SD/python/VetoG4_SDConfig.py new file mode 100644 index 000000000..de3fe9618 --- /dev/null +++ b/Scintillator/ScintG4/VetoG4_SD/python/VetoG4_SDConfig.py @@ -0,0 +1,19 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + +from AthenaCommon import CfgMgr +from G4AtlasApps.SimFlags import simFlags + +from ISF_Algorithms.collection_merger_helpers import generate_mergeable_collection_name + + +def getVetoSensorSD(name="VetoSensorSD", **kwargs): + bare_collection_name = "VetoHits" + mergeable_collection_suffix = "_G4" + merger_input_property = "VetoHits" + hits_collection_name = generate_mergeable_collection_name(bare_collection_name, + mergeable_collection_suffix, + merger_input_property) + kwargs.setdefault("LogicalVolumeNames", ["Veto::Plate"]) + kwargs.setdefault("OutputCollectionNames", [hits_collection_name]) + return CfgMgr.VetoSensorSDTool(name, **kwargs) + diff --git a/Scintillator/ScintG4/VetoG4_SD/python/VetoG4_SDConfigDb.py b/Scintillator/ScintG4/VetoG4_SD/python/VetoG4_SDConfigDb.py new file mode 100644 index 000000000..e1e81d469 --- /dev/null +++ b/Scintillator/ScintG4/VetoG4_SD/python/VetoG4_SDConfigDb.py @@ -0,0 +1,5 @@ +# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + +from AthenaCommon.CfgGetter import addTool + +addTool("VetoG4_SD.VetoG4_SDConfig.getVetoSensorSD" , "VetoSensorSD" ) diff --git a/Scintillator/ScintG4/VetoG4_SD/python/VetoG4_SDToolConfig.py b/Scintillator/ScintG4/VetoG4_SD/python/VetoG4_SDToolConfig.py new file mode 100644 index 000000000..5503826fc --- /dev/null +++ b/Scintillator/ScintG4/VetoG4_SD/python/VetoG4_SDToolConfig.py @@ -0,0 +1,21 @@ +# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator +from ISF_Algorithms.collection_merger_helpersNew import CollectionMergerCfg + +# from VetoG4_SD.VetoG4_SDConf import VetoSensorSDTool +from VetoG4_SD.VetoG4_SDConfig import getVetoSensorSD + +def VetoSensorSDCfg(ConfigFlags, name="VetoSensorSD", **kwargs): + + result = ComponentAccumulator() + bare_collection_name = "VetoHits" + mergeable_collection_suffix = "_G4" + merger_input_property = "VetoHits" + + acc, hits_collection_name = CollectionMergerCfg(ConfigFlags, bare_collection_name, mergeable_collection_suffix, merger_input_property) + kwargs.setdefault("LogicalVolumeNames", ["Veto::Plate"]) + kwargs.setdefault("OutputCollectionNames", [hits_collection_name]) + + result.merge(acc) + return result, getVetoSensorSD(name, **kwargs) diff --git a/Scintillator/ScintG4/VetoG4_SD/src/VetoSensorSD.cxx b/Scintillator/ScintG4/VetoG4_SD/src/VetoSensorSD.cxx new file mode 100644 index 000000000..af5d52876 --- /dev/null +++ b/Scintillator/ScintG4/VetoG4_SD/src/VetoSensorSD.cxx @@ -0,0 +1,116 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +// +// Veto Sensitive Detector. +// The Hits are processed here. For every hit I get the position and +// an information on the sensor in which the interaction happened +// + +// class headers +#include "VetoSensorSD.h" + +// athena includes +#include "MCTruth/TrackHelper.h" + +// Geant4 includes +#include "G4Step.hh" +#include "G4ThreeVector.hh" +#include "G4SDManager.hh" +#include "G4Geantino.hh" +#include "G4ChargedGeantino.hh" + +// CLHEP transform +#include "CLHEP/Geometry/Transform3D.h" + +#include <memory> // For make unique + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... + +VetoSensorSD::VetoSensorSD( const std::string& name, const std::string& hitCollectionName ) + : G4VSensitiveDetector( name ) + , m_HitColl( hitCollectionName ) +{ +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... + +void VetoSensorSD::Initialize(G4HCofThisEvent *) +{ + if (!m_HitColl.isValid()) m_HitColl = std::make_unique<ScintHitCollection>(); +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... + +G4bool VetoSensorSD::ProcessHits(G4Step* aStep, G4TouchableHistory* /*ROhist*/) +{ + double edep = aStep->GetTotalEnergyDeposit(); + if(edep==0.) { + if(aStep->GetTrack()->GetDefinition()!=G4Geantino::GeantinoDefinition() && + aStep->GetTrack()->GetDefinition()!=G4ChargedGeantino::ChargedGeantinoDefinition()) + return false; + } + edep *= CLHEP::MeV; + // + // Get the Touchable History: + // + const G4TouchableHistory *myTouch = dynamic_cast<const G4TouchableHistory*>(aStep->GetPreStepPoint()->GetTouchable()); + // + // Get the hit coordinates. Start and End Point + // + G4ThreeVector coord1 = aStep->GetPreStepPoint()->GetPosition(); + G4ThreeVector coord2 = aStep->GetPostStepPoint()->GetPosition(); + // + // Calculate the local step begin and end position. + // From a G4 FAQ: + // http://geant4-hn.slac.stanford.edu:5090/HyperNews/public/get/geometry/17/1.html + // + const G4AffineTransform transformation = myTouch->GetHistory()->GetTopTransform(); + G4ThreeVector localPosition1 = transformation.TransformPoint(coord1); + G4ThreeVector localPosition2 = transformation.TransformPoint(coord2); + // + // Get it into a vector in local coords and with the right units: + // + HepGeom::Point3D<double> lP1,lP2; + + // No funny business with coordinates like ATLAS... + lP1[2] = localPosition1[2]*CLHEP::mm; + lP1[1] = localPosition1[1]*CLHEP::mm; + lP1[0] = localPosition1[0]*CLHEP::mm; + + lP2[2] = localPosition2[2]*CLHEP::mm; + lP2[1] = localPosition2[1]*CLHEP::mm; + lP2[0] = localPosition2[0]*CLHEP::mm; + + // Now Navigate the history to know in what detector the step is: + // and finally set the ID of det element in which the hit is. + // + //G4int History; + // + // Get station and plate + // + int station = 0; + int plate = 0; + this->indexMethod(myTouch, station, plate); + // get the HepMcParticleLink from the TrackHelper + TrackHelper trHelp(aStep->GetTrack()); + m_HitColl->Emplace(lP1, + lP2, + edep, + aStep->GetPreStepPoint()->GetGlobalTime(),//use the global time. i.e. the time from the beginning of the event + trHelp.GetParticleLink(), + 0,station,plate); + return true; +} + +void VetoSensorSD::indexMethod(const G4TouchableHistory *myTouch, + int &station, int &plate) { + + + plate = myTouch->GetVolume()->GetCopyNo(); + const std::string stationName = myTouch->GetVolume(1)->GetLogicalVolume()->GetName(); + station = (stationName == "Veto::VetoStationA" ? 0 : 1 ); + + return; +} diff --git a/Scintillator/ScintG4/VetoG4_SD/src/VetoSensorSD.h b/Scintillator/ScintG4/VetoG4_SD/src/VetoSensorSD.h new file mode 100644 index 000000000..52e6a2bc5 --- /dev/null +++ b/Scintillator/ScintG4/VetoG4_SD/src/VetoSensorSD.h @@ -0,0 +1,50 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +/**************************************************************** + Veto Sensitive Detector class +****************************************************************/ + +#ifndef VETOG4_SD_VETOSENSORSD_H +#define VETOG4_SD_VETOSENSORSD_H + +// Base class +#include "G4VSensitiveDetector.hh" + +// For the hits +#include "ScintSimEvent/ScintHitCollection.h" +#include "StoreGate/WriteHandle.h" + +// G4 needed classes +class G4Step; +class G4TouchableHistory; + +class VetoSensorSD : public G4VSensitiveDetector +{ +public: + // Constructor + VetoSensorSD(const std::string& name, const std::string& hitCollectionName); + + // Destructor + ~VetoSensorSD() { /* If all goes well we do not own myHitColl here */ } + + // Deal with each G4 hit + G4bool ProcessHits(G4Step*, G4TouchableHistory*) override; + + // For setting up the hit collection + void Initialize(G4HCofThisEvent*) override final; + + /** Templated method to stuff a single hit into the sensitive detector class. This + could get rather tricky, but the idea is to allow fast simulations to use the very + same SD classes as the standard simulation. */ + template <class... Args> void AddHit(Args&&... args){ m_HitColl->Emplace( args... ); } + +private: + void indexMethod(const G4TouchableHistory *myTouch, int &station, int &plate); +protected: + // The hits collection + SG::WriteHandle<ScintHitCollection> m_HitColl; +}; + +#endif //VETOG4_SD_VETOSENSORSD_H diff --git a/Scintillator/ScintG4/VetoG4_SD/src/VetoSensorSDTool.cxx b/Scintillator/ScintG4/VetoG4_SD/src/VetoSensorSDTool.cxx new file mode 100644 index 000000000..bd19e9516 --- /dev/null +++ b/Scintillator/ScintG4/VetoG4_SD/src/VetoSensorSDTool.cxx @@ -0,0 +1,32 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// Veto Sensitive Detector Tool. +// + +// class header +#include "VetoSensorSDTool.h" + +// package includes +#include "VetoSensorSD.h" + +// STL includes +#include <exception> + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... + +VetoSensorSDTool::VetoSensorSDTool(const std::string& type, const std::string& name, const IInterface* parent) + : SensitiveDetectorBase( type , name , parent ) +{ + +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... + +G4VSensitiveDetector* VetoSensorSDTool::makeSD() +{ + ATH_MSG_DEBUG( "Creating Veto SD: " << name() ); + return new VetoSensorSD(name(), m_outputCollectionNames[0]); +} + diff --git a/Scintillator/ScintG4/VetoG4_SD/src/VetoSensorSDTool.h b/Scintillator/ScintG4/VetoG4_SD/src/VetoSensorSDTool.h new file mode 100644 index 000000000..33751c0bb --- /dev/null +++ b/Scintillator/ScintG4/VetoG4_SD/src/VetoSensorSDTool.h @@ -0,0 +1,36 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/**************************************************************** + Veto Sensitive Detector Tool + ****************************************************************/ + +#ifndef VETOG4_SD_VETOSENSORSDTOOL_H +#define VETOG4_SD_VETOSENSORSDTOOL_H + +// Base class +#include "G4AtlasTools/SensitiveDetectorBase.h" + +// STL headers +#include <string> + +class G4VSensitiveDetector; + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..... + +class VetoSensorSDTool : public SensitiveDetectorBase +{ + public: + // Constructor + VetoSensorSDTool(const std::string& type, const std::string& name, const IInterface *parent); + + // Destructor + ~VetoSensorSDTool() { /* If all goes well we do not own myHitColl here */ } + +protected: + // Make me an SD! + G4VSensitiveDetector* makeSD() override final; +}; + +#endif //VETOG4_SD_VETOSENSORSDTOOL_H diff --git a/Scintillator/ScintG4/VetoG4_SD/src/components/VetoG4_SD_entries.cxx b/Scintillator/ScintG4/VetoG4_SD/src/components/VetoG4_SD_entries.cxx new file mode 100644 index 000000000..db34c8ee1 --- /dev/null +++ b/Scintillator/ScintG4/VetoG4_SD/src/components/VetoG4_SD_entries.cxx @@ -0,0 +1,3 @@ +#include "../VetoSensorSDTool.h" + +DECLARE_COMPONENT( VetoSensorSDTool ) diff --git a/Scintillator/ScintG4/VetoG4_SD/test/VetoG4_SDToolConfig_test.py b/Scintillator/ScintG4/VetoG4_SD/test/VetoG4_SDToolConfig_test.py new file mode 100644 index 000000000..2eb4d3cb4 --- /dev/null +++ b/Scintillator/ScintG4/VetoG4_SD/test/VetoG4_SDToolConfig_test.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python +"""Run tests on VetoG4_SD configuration + +Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +""" +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator + + +if __name__ == '__main__': + + + #import config flags + from CalypsoConfiguration.AllConfigFlags import ConfigFlags + # Set up logging and config behaviour + from AthenaCommon.Logging import log + from AthenaCommon.Constants import DEBUG + from AthenaCommon.Configurable import Configurable + log.setLevel(DEBUG) + Configurable.configurableRun3Behavior = 1 + + + # ConfigFlags.Sim.ISF.Run = True + ConfigFlags.Detector.SimulateVeto = True + + #Provide input + from AthenaConfiguration.TestDefaults import defaultTestFiles + inputDir = defaultTestFiles.d + ConfigFlags.Input.Files = defaultTestFiles.EVNT + + # Finalize + ConfigFlags.lock() + + + ## Initialize a new component accumulator + cfg = ComponentAccumulator() + + from VetoG4_SD.VetoG4_SDToolConfig import VetoSensorSDCfg + + acc, tool = VetoSensorSDCfg(ConfigFlags) + acc.addPublicTool(tool) + cfg.merge(acc) + + + cfg.printConfig(withDetails=True, summariseProps = True) + ConfigFlags.dump() + + f=open("test.pkl","w") + cfg.store(f) + f.close() + + + + print cfg._publicTools + print "-----------------finished----------------------" diff --git a/Scintillator/ScintSimEvent/CMakeLists.txt b/Scintillator/ScintSimEvent/CMakeLists.txt new file mode 100644 index 000000000..b0f889d01 --- /dev/null +++ b/Scintillator/ScintSimEvent/CMakeLists.txt @@ -0,0 +1,40 @@ +################################################################################ +# Package: ScintSimEvent +################################################################################ + +# Declare the package name: +atlas_subdir( ScintSimEvent ) + +# Declare the package's dependencies: +atlas_depends_on_subdirs( PUBLIC + Control/AthenaKernel + Control/AthAllocators + Control/CxxUtils + Generators/GeneratorObjects + Simulation/HitManagement + + PRIVATE + Control/StoreGate + Scintillator/ScintDetDescr/ScintIdentifier ) + +# External dependencies: +find_package( CLHEP ) +find_package( Geant4 ) +find_package( ROOT COMPONENTS Core Tree MathCore Hist RIO pthread ) + +# Component(s) in the package: +atlas_add_library( ScintSimEvent + src/*.cxx + PUBLIC_HEADERS ScintSimEvent + INCLUDE_DIRS ${CLHEP_INCLUDE_DIRS} + PRIVATE_INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${GEANT4_INCLUDE_DIRS} + DEFINITIONS ${CLHEP_DEFINITIONS} + LINK_LIBRARIES ${CLHEP_LIBRARIES} AthAllocators AthenaKernel CxxUtils GeneratorObjects HitManagement StoreGateLib SGtests + PRIVATE_LINK_LIBRARIES ${ROOT_LIBRARIES} ScintIdentifier ) + +atlas_add_dictionary( ScintSimEventDict + ScintSimEvent/ScintSimEventDict.h + ScintSimEvent/selection.xml + INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${GEANT4_INCLUDE_DIRS} + LINK_LIBRARIES ${ROOT_LIBRARIES} ${CLHEP_LIBRARIES} AthAllocators CxxUtils GeneratorObjects HitManagement StoreGateLib SGtests ScintIdentifier ScintSimEvent ) + diff --git a/Scintillator/ScintSimEvent/ScintSimEvent/ScintHit.h b/Scintillator/ScintSimEvent/ScintSimEvent/ScintHit.h new file mode 100644 index 000000000..5a0a4d172 --- /dev/null +++ b/Scintillator/ScintSimEvent/ScintSimEvent/ScintHit.h @@ -0,0 +1,185 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/////////////////////////////////////////////////////////////////// +// ScintHit.h +// Header file for class ScintHit +/////////////////////////////////////////////////////////////////// +// Class for the Veto, Trigger and Preshower hits +/////////////////////////////////////////////////////////////////// + +#ifndef SCINTSIMEVENT_SCINTHIT_H +#define SCINTSIMEVENT_SCINTHIT_H + +// Data members classes +#include "CLHEP/Geometry/Point3D.h" +#include "GeneratorObjects/HepMcParticleLink.h" + +class ScintHit { + + /////////////////////////////////////////////////////////////////// + // Public methods: + /////////////////////////////////////////////////////////////////// +public: + + // Constructor with parameters: + // local start position of the energy deposit + // local end position of the energy deposit + // deposited energy + // time of energy deposition + // number of track which released this energy + // + ScintHit(const HepGeom::Point3D<double> &localStartPosition, + const HepGeom::Point3D<double> &localEndPosition, + const double energyLoss, + const double meanTime, + const int trackNumber, + const unsigned int id); + + ScintHit(const HepGeom::Point3D<double> &localStartPosition, + const HepGeom::Point3D<double> &localEndPosition, + const double energyLoss, + const double meanTime, + const int trackNumber, + const int, const int, const int); + // Constructor with parameters: + // local start position of the energy deposit + // local end position of the energy deposit + // deposited energy + // time of energy deposition + // link to particle which released this energy + // + ScintHit(const HepGeom::Point3D<double> &localStartPosition, + const HepGeom::Point3D<double> &localEndPosition, + const double energyLoss, + const double meanTime, + const HepMcParticleLink &track, + const unsigned int id); + + ScintHit(const HepGeom::Point3D<double> &localStartPosition, + const HepGeom::Point3D<double> &localEndPosition, + const double energyLoss, + const double meanTime, + const HepMcParticleLink &track, + const int, const int, const int); + // needed by athenaRoot + ScintHit(); + + // Destructor: + virtual ~ScintHit(); + + //move assignment defaulted + ScintHit & operator = (ScintHit &&) = default; + //assignment defaulted + ScintHit & operator = (const ScintHit &) = default; + //copy c'tor defaulted + ScintHit(const ScintHit &) = default; + + /////////////////////////////////////////////////////////////////// + // Const methods: + /////////////////////////////////////////////////////////////////// + + unsigned int identify() const; + + // local start position of the energy deposit: + HepGeom::Point3D<double> localStartPosition() const; + + HepGeom::Point3D<double> localEndPosition() const; + + // deposited energy: + double energyLoss() const; + + // time of energy deposition: FIXME name! + double meanTime() const; + + // Set the time of energy deposition: FIXME name! + void setMeanTime(float meanTime); + + // number of track which released this energy: + int trackNumber() const; + + // link to the particle generating the hit + const HepMcParticleLink& particleLink() const; + + // Veto, trigger or preshower? + bool isVeto() const; + bool isTrigger() const; + bool isPreshower() const; + + // Station + int getStation() const; + + // Plate + int getPlate() const; + + // some print-out: + void print() const; + + bool operator < (const ScintHit& rhs) const + {return m_ID < rhs.m_ID;} + + /////////////////////////////////////////////////////////////////// + // Non-const methods: + /////////////////////////////////////////////////////////////////// + // Scale the length, used to go from cm to mm, of whatever we like. + void ScaleLength(double); + + /////////////////////////////////////////////////////////////////// + // Private data: + /////////////////////////////////////////////////////////////////// +private: + + float m_stX, m_stY, m_stZ; + float m_enX, m_enY, m_enZ; + float m_energyLoss; // deposited energy + float m_meanTime; // time of energy deposition + HepMcParticleLink m_partLink; + unsigned int m_ID; +public: + // enum + // { xDep = 2, xPhi = 0, xEta = 1}; +}; + + +/////////////////////////////////////////////////////////////////// +// Inline methods: +/////////////////////////////////////////////////////////////////// + +inline unsigned int ScintHit::identify() const +{ + return m_ID; +} + +inline double ScintHit::energyLoss() const +{ + return (double) m_energyLoss; +} + +inline double ScintHit::meanTime() const +{ + return (double) m_meanTime; +} + +inline void ScintHit::setMeanTime(float meanTime) +{ + m_meanTime=meanTime; +} + +inline const HepMcParticleLink& ScintHit::particleLink() const +{ + return m_partLink; +} + + + +/////////////////////////////////////////////////////////////////// +// open functions: +/////////////////////////////////////////////////////////////////// + +inline float hitTime(const ScintHit& hit) +{ + return (float) hit.meanTime(); +} + +#endif // SCINTSIMEVENT_SCINTHIT_H diff --git a/Scintillator/ScintSimEvent/ScintSimEvent/ScintHitCollection.h b/Scintillator/ScintSimEvent/ScintSimEvent/ScintHitCollection.h new file mode 100644 index 000000000..9eabf2a43 --- /dev/null +++ b/Scintillator/ScintSimEvent/ScintSimEvent/ScintHitCollection.h @@ -0,0 +1,20 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef SCINTSIMEVENT_SCINTHITCOLLECTION_H +#define SCINTSIMEVENT_SCINTHITCOLLECTION_H + +#include "ScintSimEvent/ScintHit.h" +#include "HitManagement/AtlasHitsVector.h" +#include "AthenaKernel/CLASS_DEF.h" + +typedef AtlasHitsVector<ScintHit> ScintHitCollection; +typedef AtlasHitsVector<ScintHit>::iterator ScintHitIterator; +typedef AtlasHitsVector<ScintHit>::const_iterator ScintHitConstIterator; + +#ifndef __CINT__ + CLASS_DEF(ScintHitCollection, 1209245270, 1 ) +#endif + +#endif // SCINTSIMEVENT_SCINTHITCOLLECTION_H diff --git a/Scintillator/ScintSimEvent/ScintSimEvent/ScintHitIdHelper.h b/Scintillator/ScintSimEvent/ScintSimEvent/ScintHitIdHelper.h new file mode 100644 index 000000000..2874bac89 --- /dev/null +++ b/Scintillator/ScintSimEvent/ScintSimEvent/ScintHitIdHelper.h @@ -0,0 +1,59 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef SCINTSIMEVENT_SCINTHITIDHELPER +#define SCINTSIMEVENT_SCINTHITIDHELPER + +// +// This is a helper class to build an identifing integer used by +// the simulation. It inherits from HitIdHelper, in order to get +// all the packing and shifting for free. +// The class is a singleton and a static GetHelper() is provided +// the constructor calls the Initialize() method which sets all the +// field dimensions +// Methods are provided to get access to the ScintTracker Geometry +// description +// + + +// +// Base Class +#include "HitManagement/HitIdHelper.h" + +// This class is singleton and static method and variable are used. +#include "CxxUtils/checker_macros.h" +ATLAS_NO_CHECK_FILE_THREAD_SAFETY; + +class ScintHitIdHelper : HitIdHelper { + public: + // + // Access to the helper + static ScintHitIdHelper* GetHelper(); + // + // Info retrieval: + // Veto or Trigger or Preshower + bool isVeto(const int& hid) const; + bool isTrigger(const int& hid) const; + bool isPreshower(const int& hid) const; + + // Barrel or Endcap + int getStation(const int& hid) const; + + // Layer/Disk + int getPlate(const int& hid) const; + + // + // Info packing: + int buildHitId(const int, const int, const int) const; + + private: + // + // private constructor to have a singleton + ScintHitIdHelper(); + // + // Initialize the helper, only called by the constructor + void Initialize(); +}; + +#endif // SCINTSIMEVENT_SCINTHITIDHELPER diff --git a/Scintillator/ScintSimEvent/ScintSimEvent/ScintSimEventDict.h b/Scintillator/ScintSimEvent/ScintSimEvent/ScintSimEventDict.h new file mode 100644 index 000000000..946cd3e13 --- /dev/null +++ b/Scintillator/ScintSimEvent/ScintSimEvent/ScintSimEventDict.h @@ -0,0 +1,10 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef SCINTSIMEVENT_SCINTSIMEVENTDICT_H +#define SCINTSIMEVENT_SCINTSIMEVENTDICT_H + +#include "ScintSimEvent/ScintHitCollection.h" + +#endif \ No newline at end of file diff --git a/Scintillator/ScintSimEvent/ScintSimEvent/selection.xml b/Scintillator/ScintSimEvent/ScintSimEvent/selection.xml new file mode 100644 index 000000000..a1874958a --- /dev/null +++ b/Scintillator/ScintSimEvent/ScintSimEvent/selection.xml @@ -0,0 +1,5 @@ +<lcgdict> + <class name="AtlasHitsVector<ScintHit>" /> + <class name="std::vector<ScintHit>" /> + <class name="ScintHit" /> +</lcgdict> diff --git a/Scintillator/ScintSimEvent/src/ScintHit.cxx b/Scintillator/ScintSimEvent/src/ScintHit.cxx new file mode 100644 index 000000000..2ef1cfd9b --- /dev/null +++ b/Scintillator/ScintSimEvent/src/ScintHit.cxx @@ -0,0 +1,176 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "ScintSimEvent/ScintHit.h" +#include "ScintSimEvent/ScintHitIdHelper.h" + +// Default consdtructor needed by athenaroot +// +ScintHit::ScintHit( ) : + m_stX(0.), + m_stY(0.), + m_stZ(0.), + m_enX(0.), + m_enY(0.), + m_enZ(0.), + m_energyLoss(0.), + m_meanTime(0.), + m_partLink(), + m_ID(0xffff) +{ + +} + +ScintHit::~ScintHit() {} + + +// Constructor +ScintHit::ScintHit(const HepGeom::Point3D<double> &localStartPosition, + const HepGeom::Point3D<double> &localEndPosition, + const double energyLoss, + const double meanTime, + const int trackNumber, + const unsigned int id) : + m_stX( (float) localStartPosition.x() ), + m_stY( (float) localStartPosition.y() ), + m_stZ( (float) localStartPosition.z() ), + m_enX( (float) localEndPosition.x() ), + m_enY( (float) localEndPosition.y() ), + m_enZ( (float) localEndPosition.z() ), + m_energyLoss(energyLoss), + m_meanTime(meanTime), + m_partLink(trackNumber), + m_ID(id) +{ +} + +// Constructor +ScintHit::ScintHit(const HepGeom::Point3D<double> &localStartPosition, + const HepGeom::Point3D<double> &localEndPosition, + const double energyLoss, + const double meanTime, + const int trackNumber, + const int veto_trigger_preshower, + const int station, + const int plate) : + m_stX( (float) localStartPosition.x() ), + m_stY( (float) localStartPosition.y() ), + m_stZ( (float) localStartPosition.z() ), + m_enX( (float) localEndPosition.x() ), + m_enY( (float) localEndPosition.y() ), + m_enZ( (float) localEndPosition.z() ), + m_energyLoss(energyLoss), + m_meanTime(meanTime), + m_partLink(trackNumber), + m_ID(0) +{ + // Compress the location info into the integer: + m_ID = ScintHitIdHelper::GetHelper()->buildHitId(veto_trigger_preshower, + station, + plate); +} + +// Constructor +ScintHit::ScintHit(const HepGeom::Point3D<double> &localStartPosition, + const HepGeom::Point3D<double> &localEndPosition, + const double energyLoss, + const double meanTime, + const HepMcParticleLink &track, + const unsigned int id) : + m_stX( (float) localStartPosition.x() ), + m_stY( (float) localStartPosition.y() ), + m_stZ( (float) localStartPosition.z() ), + m_enX( (float) localEndPosition.x() ), + m_enY( (float) localEndPosition.y() ), + m_enZ( (float) localEndPosition.z() ), + m_energyLoss(energyLoss), + m_meanTime(meanTime), + m_partLink(track), + m_ID(id) +{ +} + +// Constructor +ScintHit::ScintHit(const HepGeom::Point3D<double> &localStartPosition, + const HepGeom::Point3D<double> &localEndPosition, + const double energyLoss, + const double meanTime, + const HepMcParticleLink &track, + const int veto_trigger_preshower, + const int station, + const int plate) : + m_stX( (float) localStartPosition.x() ), + m_stY( (float) localStartPosition.y() ), + m_stZ( (float) localStartPosition.z() ), + m_enX( (float) localEndPosition.x() ), + m_enY( (float) localEndPosition.y() ), + m_enZ( (float) localEndPosition.z() ), + m_energyLoss(energyLoss), + m_meanTime(meanTime), + m_partLink(track), + m_ID(0) +{ + // Compress the location info into the integer: + m_ID = ScintHitIdHelper::GetHelper()->buildHitId(veto_trigger_preshower, + station, + plate); +} + +void ScintHit::ScaleLength(double sfactor) { + m_stX *= (float) sfactor; + m_stY *= (float) sfactor; + m_stZ *= (float) sfactor; + m_enX *= (float) sfactor; + m_enY *= (float) sfactor; + m_enZ *= (float) sfactor; +} + +bool ScintHit::isVeto() const { + return ScintHitIdHelper::GetHelper()->isVeto(m_ID); +} + +bool ScintHit::isTrigger() const { + return ScintHitIdHelper::GetHelper()->isTrigger(m_ID); +} + +bool ScintHit::isPreshower() const { + return ScintHitIdHelper::GetHelper()->isPreshower(m_ID); +} + +HepGeom::Point3D<double> ScintHit::localStartPosition() const +{ + return HepGeom::Point3D<double>((double) m_stX, (double) m_stY, (double) m_stZ); +} + +HepGeom::Point3D<double> ScintHit::localEndPosition() const +{ + return HepGeom::Point3D<double>((double) m_enX, (double) m_enY, (double) m_enZ); +} + +int ScintHit::getStation() const { + return ScintHitIdHelper::GetHelper()->getStation(m_ID); +} + +int ScintHit::getPlate() const { + return ScintHitIdHelper::GetHelper()->getPlate(m_ID); +} + +void ScintHit::print() const { + if (isVeto()) { + std::cout << "*** Veto Hit " << std::endl; + } else if (isTrigger()) { + std::cout << "*** Trigger Hit " << std::endl; + } else if (isPreshower()) { + std::cout << "*** Preshower Hit " << std::endl; + } else { + std::cout << "*** Unrecognized Scintillator Hit " << std::endl; + } + std::cout << " Station Number " << getStation() << std::endl; + std::cout << " Plate Number " << getPlate() << std::endl; +} + +int ScintHit::trackNumber() const +{ + return m_partLink.barcode(); +} diff --git a/Scintillator/ScintSimEvent/src/ScintHitIdHelper.cxx b/Scintillator/ScintSimEvent/src/ScintHitIdHelper.cxx new file mode 100644 index 000000000..ad7abd151 --- /dev/null +++ b/Scintillator/ScintSimEvent/src/ScintHitIdHelper.cxx @@ -0,0 +1,104 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#include <mutex> + +#include "ScintSimEvent/ScintHitIdHelper.h" +#include "StoreGate/StoreGateSvc.h" +#include "StoreGate/StoreGate.h" +#include "ScintIdentifier/VetoID.h" + +#include "G4Types.hh" +#ifdef G4MULTITHREADED +# include "GaudiKernel/ContextSpecificPtr.h" +#endif + +static std::mutex sgMutex; + +// This class is singleton and static method and variable are used. +ATLAS_NO_CHECK_FILE_THREAD_SAFETY; + +// +// private constructor +ScintHitIdHelper::ScintHitIdHelper() :HitIdHelper() { + Initialize(); +} + +ScintHitIdHelper* ScintHitIdHelper::GetHelper() { +#ifdef G4MULTITHREADED + // Context-specific singleton + static Gaudi::Hive::ContextSpecificPtr<ScintHitIdHelper> helperPtr; + if(!helperPtr) helperPtr = new ScintHitIdHelper(); + return helperPtr.get(); +#else + static ScintHitIdHelper helper; + return &helper; +#endif +} + +void ScintHitIdHelper::Initialize() { + + // determine whether hits were created with an SLHC dictionary + // in which case eta module field is expanded. + // Need to lock this thread-unsafe retrieval + const VetoID* pix; + StoreGateSvc* detStore(nullptr); + { + std::lock_guard<std::mutex> lock(sgMutex); + detStore = StoreGate::pointer("DetectorStore"); + if (detStore->retrieve(pix, "VetoID").isFailure()) { pix = 0; } + } + + InitializeField("VetoTriggerPreshower", 0, 2); + InitializeField("Station", -2, 2); + InitializeField("Plate", 0, 4); +} + +// Info retrieval: +// Veto or Trigger or Preshower +bool ScintHitIdHelper::isVeto(const int& hid) const +{ + int ps = this->GetFieldValue("VetoTriggerPreshower", hid); + if ( ps == 0 ) return true; + else return false; +} + +bool ScintHitIdHelper::isTrigger(const int& hid) const +{ + int ps = this->GetFieldValue("VetoTriggerPreshower", hid); + if ( ps == 1 ) return true; + else return false; +} + +bool ScintHitIdHelper::isPreshower(const int& hid) const +{ + int ps = this->GetFieldValue("VetoTriggerPreshower", hid); + if ( ps == 2 ) return true; + else return false; +} + +// Station +int ScintHitIdHelper::getStation(const int& hid) const +{ + return this->GetFieldValue("Station", hid); +} + +// Plate +int ScintHitIdHelper::getPlate(const int& hid) const +{ + return this->GetFieldValue("Plate", hid); +} + +// +// Info packing: +int ScintHitIdHelper::buildHitId(const int veto_trigger_preshower, + const int station, + const int plate) const +{ + int theID(0); + this->SetFieldValue("VetoTriggerPreshower", veto_trigger_preshower, theID); + this->SetFieldValue("Station", station, theID); + this->SetFieldValue("Plate", plate, theID); + return theID; +} diff --git a/Simulation/G4Faser/G4FaserAlg/CMakeLists.txt b/Simulation/G4Faser/G4FaserAlg/CMakeLists.txt new file mode 100644 index 000000000..66f8d8f35 --- /dev/null +++ b/Simulation/G4Faser/G4FaserAlg/CMakeLists.txt @@ -0,0 +1,53 @@ +################################################################################ +# Package: G4FaserAlg +################################################################################ + +# Declare the package name: +atlas_subdir( G4FaserAlg ) + +# Declare the package's dependencies: +atlas_depends_on_subdirs( PUBLIC + GaudiKernel + PRIVATE + Control/AthenaBaseComps + Control/AthenaKernel + Control/SGTools + Control/StoreGate + DetectorDescription/GeoModel/GeoModelInterfaces + Event/EventInfo + Generators/GeneratorObjects + Simulation/G4Atlas/G4AtlasInterfaces + Simulation/G4Sim/MCTruthBase + Simulation/ISF/ISF_Core/ISF_Interfaces + Simulation/Barcode/BarcodeInterfaces) + +# External dependencies: +find_package( CLHEP ) +find_package( Geant4 ) +find_package( HepMC ) +find_package( XercesC ) +find_package( Eigen ) + +# G4AtlasAlgLib library + +#atlas_add_library( G4FaserAlgLib +# src/*.cxx +# PUBLIC_HEADERS G4AtlasAlg +# INCLUDE_DIRS ${GEANT4_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS} ${XERCESC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} +# ${HEPMC_INCLUDE_DIRS} +# LINK_LIBRARIES ${GEANT4_LIBRARIES} ${EIGEN_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} ${HEPMC_LIBRARIES} AthenaBaseComps AthenaKernel GaudiKernel G4AtlasInterfaces SGTools StoreGateLib SGtests EventInfo GeneratorObjects MCTruthBaseLib ) +# +# Component(s) in the package: +#atlas_add_component( G4FaserAlg +# src/components/*.cxx +# PUBLIC_HEADERS G4FaserAlg +# INCLUDE_DIRS ${GEANT4_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS} ${XERCESC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${HEPMC_INCLUDE_DIRS} +# LINK_LIBRARIES ${GEANT4_LIBRARIES} ${EIGEN_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} ${HEPMC_LIBRARIES} AthenaBaseComps AthenaKernel GaudiKernel G4AtlasInterfaces G4FaserAlgLib SGTools StoreGateLib SGtests EventInfo GeneratorObjects MCTruthBaseLib ) + +#atlas_add_test( G4FaserAlgConfig_Test +# SCRIPT test/runG4.py +# PROPERTIES TIMEOUT 300 ) + +# Install files from the package: +atlas_install_python_modules( python/*.py ) +atlas_install_scripts( test/*.py ) diff --git a/Simulation/G4Faser/G4FaserAlg/python/G4FaserAlgConfigNew.py b/Simulation/G4Faser/G4FaserAlg/python/G4FaserAlgConfigNew.py new file mode 100644 index 000000000..f69c2a836 --- /dev/null +++ b/Simulation/G4Faser/G4FaserAlg/python/G4FaserAlgConfigNew.py @@ -0,0 +1,171 @@ +# +# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +# +from AthenaCommon.AppMgr import * + +# +# Manager classes for detector geometry and sensitive detectors +# +from G4FaserServices.G4FaserServicesConfigNew import DetectorGeometrySvcCfg, FaserGeoIDSvcCfg +from G4FaserTools.G4FaserToolsConfig import getSensitiveDetectorMasterTool +# +# Framework utilities +# +from ISF_Services.ISF_ServicesConfigNew import MC15aPlusTruthServiceCfg, InputConverterCfg +# +# The GeoIDSvcCfg call is a disaster, bringing in tons of ATLAS-specific +# stuff that would have to be rewritten; instead, we define FASER as being +# unconditionally in the "undefined" ATLAS region; this may eventually limit +# the granularity of truth strategies we can use +# +#from ISF_Services.ISF_ServicesConfigNew import GeoIDSvcCfg +# +from G4AtlasAlg.G4AtlasAlgConf import G4AtlasAlg + +#to still migrate: getAthenaStackingActionTool, getAthenaTrackingActionTool + +def G4FaserAlgCfg(ConfigFlags, name='G4FaserAlg', **kwargs): + # + # add Services to G4AtlasAlg + # + result = DetectorGeometrySvcCfg(ConfigFlags) + kwargs.setdefault('DetGeoSvc', result.getService("DetectorGeometrySvc")) + # + # MC particle container names + # + kwargs.setdefault("InputTruthCollection", "GEN_EVENT") + kwargs.setdefault("OutputTruthCollection", "TruthEvent") + # + # Option to free memory by dropping GeoModel after construction + # + # if ConfigFlags.Sim.ReleaseGeoModel: + kwargs.setdefault('ReleaseGeoModel', ConfigFlags.Sim.ReleaseGeoModel) + # + # Record the particle flux during the simulation + # + # if ConfigFlags.Sim.RecordFlux: + kwargs.setdefault('RecordFlux' , ConfigFlags.Sim.RecordFlux) + # + # Treatment of bad events + # + # if ConfigFlags.Sim.FlagAbortedEvents: + ## default false + kwargs.setdefault('FlagAbortedEvents' ,ConfigFlags.Sim.FlagAbortedEvents) + if ConfigFlags.Sim.FlagAbortedEvents and ConfigFlags.Sim.KillAbortedEvents: + print('WARNING When G4AtlasAlg.FlagAbortedEvents is True G4AtlasAlg.KillAbortedEvents should be False!!! Setting G4AtlasAlg.KillAbortedEvents = False now!') + kwargs.setdefault('KillAbortedEvents' ,False) + # if ConfigFlags.Sim.KillAbortedEvents: + ## default true + kwargs.setdefault('KillAbortedEvents' ,ConfigFlags.Sim.KillAbortedEvents) + # + # Random numbers + # + from RngComps.RandomServices import AthEngines, RNG + if ConfigFlags.Random.Engine in AthEngines.keys(): + result.merge(RNG(ConfigFlags.Random.Engine, name="AthRNGSvc")) + kwargs.setdefault("AtRndmGenSvc",result.getService("AthRNGSvc")) + + kwargs.setdefault("RandomGenerator", "athena") + # + # Multi-threading settinggs + # + is_hive = ConfigFlags.Concurrency.NumThreads > 1 + kwargs.setdefault('MultiThreading', is_hive) + # + # What truth information to save? + # + accMCTruth = MC15aPlusTruthServiceCfg(ConfigFlags) + result.merge(accMCTruth) + kwargs.setdefault('TruthRecordService', result.getService("ISF_MC15aPlusTruthService")) + #kwargs.setdefault('TruthRecordService', ConfigFlags.Sim.TruthStrategy) # TODO need to have manual override (simFlags.TruthStrategy.TruthServiceName()) + # + # Run-time geometry navigation for truth filtering - the ISF service is incompatible with FASER + # + # accGeoID = GeoIDSvcCfg(ConfigFlags) + # result.merge(accGeoID) + # kwargs.setdefault('GeoIDSvc', result.getService('ISF_GeoIDSvc')) + accGeoID = FaserGeoIDSvcCfg(ConfigFlags) + result.merge(accGeoID) + kwargs.setdefault('GeoIDSvc', result.getService('ISF_FaserGeoIDSvc')) + # + # Converts generator particles to a proprietary type managed by ISF + # + accInputConverter = InputConverterCfg(ConfigFlags) + result.merge(accInputConverter) + kwargs.setdefault('InputConverter', result.getService("ISF_InputConverter")) + # + # Output level + # + ## G4AtlasAlg verbosities (available domains = Navigator, Propagator, Tracking, Stepping, Stacking, Event) + ## Set stepper verbose = 1 if the Athena logging level is <= DEBUG + # TODO: Why does it complain that G4AtlasAlgConf.G4AtlasAlg has no "Verbosities" object? Fix. + verbosities=dict() + #from AthenaCommon.AppMgr import ServiceMgr + #if ServiceMgr.MessageSvc.OutputLevel <= 2: + # verbosities["Tracking"]='1' + # print verbosities + kwargs.setdefault('Verbosities', verbosities) + # + # Set commands for the G4AtlasAlg + # + kwargs.setdefault("G4Commands", ConfigFlags.Sim.G4Commands) + # + # Default to using all known sensitive detectors + # + # result.addPublicTool(getSensitiveDetectorMasterTool()) + # kwargs.setdefault("SenDetMasterTool", result.getPublicTool("SensitiveDetectorMasterTool")) + + result.addEventAlgo(G4AtlasAlg(name, **kwargs)) + return result + +if __name__ == '__main__': + from AthenaConfiguration.MainServicesConfig import MainServicesSerialCfg + import os + + # Set up logging and config behaviour + from AthenaCommon.Logging import log + from AthenaCommon.Constants import DEBUG + from AthenaCommon.Configurable import Configurable + log.setLevel(DEBUG) + Configurable.configurableRun3Behavior = 1 + + + #import config flags + from AthenaConfiguration.AllConfigFlags import ConfigFlags + + from AthenaConfiguration.TestDefaults import defaultTestFiles + inputDir = defaultTestFiles.d + ConfigFlags.Input.Files = defaultTestFiles.EVNT + + ConfigFlags.Sim.WorldRRange = 15000 + ConfigFlags.Sim.WorldZRange = 27000 #change defaults? + ConfigFlags.Detector.SimulateForward = False + # Finalize + ConfigFlags.lock() + + ## Initialize a new component accumulator + cfg = MainServicesSerialCfg() + + #add the algorithm + cfg.merge(G4FaserAlgCfg(ConfigFlags)) + + # Dump config + cfg.getService("StoreGateSvc").Dump = True + cfg.getService("ConditionStore").Dump = True + cfg.printConfig(withDetails=True, summariseProps = True) + ConfigFlags.dump() + + + # Execute and finish + sc = cfg.run(maxEvents=3) + # Success should be 0 + os.sys.exit(not sc.isSuccess()) + + #f=open("test.pkl","w") + #cfg.store(f) + #f.close() + + + + print(cfg._publicTools) + print("-----------------finished----------------------") diff --git a/Simulation/G4Faser/G4FaserAlg/python/__init__.py b/Simulation/G4Faser/G4FaserAlg/python/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/Simulation/G4Faser/G4FaserApp/CMakeLists.txt b/Simulation/G4Faser/G4FaserApp/CMakeLists.txt new file mode 100644 index 000000000..02b9a8f55 --- /dev/null +++ b/Simulation/G4Faser/G4FaserApp/CMakeLists.txt @@ -0,0 +1,54 @@ +################################################################################ +# Package: G4FaserApp +################################################################################ + +# Declare the package name: +atlas_subdir( G4FaserApp ) + +# Declare the package's dependencies: +atlas_depends_on_subdirs( PUBLIC + GaudiKernel + PRIVATE + Control/AthenaBaseComps + Control/AthenaKernel + Control/SGTools + Control/StoreGate + DetectorDescription/GeoModel/GeoModelInterfaces + Event/EventInfo + Generators/GeneratorObjects + Simulation/G4Atlas/G4AtlasInterfaces + Simulation/G4Atlas/G4AtlasAlgs + Simulation/G4Sim/MCTruthBase + Simulation/ISF/ISF_Core/ISF_Interfaces + Simulation/Barcode/BarcodeInterfaces) + +# External dependencies: +find_package( CLHEP ) +find_package( Geant4 ) +find_package( HepMC ) +find_package( XercesC ) +find_package( Eigen ) + +# G4AtlasAlgLib library + +#atlas_add_library( G4AtlasAlgLib +# src/*.cxx +# PUBLIC_HEADERS G4AtlasAlg +# INCLUDE_DIRS ${GEANT4_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS} ${XERCESC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} +# ${HEPMC_INCLUDE_DIRS} +# LINK_LIBRARIES ${GEANT4_LIBRARIES} ${EIGEN_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} ${HEPMC_LIBRARIES} AthenaBaseComps AthenaKernel GaudiKernel G4AtlasInterfaces SGTools StoreGateLib SGtests EventInfo GeneratorObjects MCTruthBaseLib ) +# +# Component(s) in the package: +#atlas_add_component( G4AtlasAlg +# src/components/*.cxx +# PUBLIC_HEADERS G4AtlasAlg +# INCLUDE_DIRS ${GEANT4_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS} ${XERCESC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${HEPMC_INCLUDE_DIRS} +# LINK_LIBRARIES ${GEANT4_LIBRARIES} ${EIGEN_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} ${HEPMC_LIBRARIES} AthenaBaseComps AthenaKernel GaudiKernel G4AtlasInterfaces G4AtlasAlgLib SGTools StoreGateLib SGtests EventInfo GeneratorObjects MCTruthBaseLib ) + +atlas_add_test( G4FaserAlgConfig_Test + SCRIPT test/runG4.py + PROPERTIES TIMEOUT 300 ) + +# Install files from the package: +atlas_install_python_modules( python/*.py ) +atlas_install_scripts( test/*.py ) diff --git a/Simulation/G4Faser/G4FaserApp/test/runG4.py b/Simulation/G4Faser/G4FaserApp/test/runG4.py new file mode 100644 index 000000000..998084c53 --- /dev/null +++ b/Simulation/G4Faser/G4FaserApp/test/runG4.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python +if __name__ == "__main__": + import os + import GaudiPython + import ParticleGun as PG + from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator + from AthenaCommon.AppMgr import * + from AthenaCommon.Logging import log, logging + from AthenaCommon.SystemOfUnits import TeV + from AthenaCommon.PhysicalConstants import pi + from AthenaCommon.Constants import VERBOSE, INFO + from AthenaCommon.Configurable import Configurable + from CalypsoConfiguration.AllConfigFlags import ConfigFlags + from AthenaConfiguration.MainServicesConfig import MainServicesSerialCfg + from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg + from McEventSelector.McEventSelectorConfig import McEventSelectorCfg + from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg + from FaserGeoModel.FaserGeoModelConfig import FaserGeometryCfg + from G4FaserAlg.G4FaserAlgConfigNew import G4FaserAlgCfg + from G4FaserServices.G4FaserServicesConfigNew import G4GeometryNotifierSvcCfg + from G4AtlasTools.G4AtlasToolsConf import SensitiveDetectorMasterTool + from G4FaserTools.G4FaserToolsConfig import generateSensitiveDetectorList + from VetoG4_SD.VetoG4_SDToolConfig import VetoSensorSDCfg +# +# Set up logging and new style config +# + log.setLevel(VERBOSE) + Configurable.configurableRun3Behavior = True +# +# Input settings (Generator file) +# +# from AthenaConfiguration.TestDefaults import defaultTestFiles +# ConfigFlags.Input.Files = defaultTestFiles.EVNT +# +# Alternatively, these must ALL be explicitly set to run without an input file +# (if missing, it will try to read metadata from a non-existent file and crash) +# + ConfigFlags.Input.Files = [""] + ConfigFlags.Input.isMC = True + ConfigFlags.Input.RunNumber = 12345 + ConfigFlags.Input.Collections = [""] + ConfigFlags.ProjectName = "mc19" + ConfigFlags.Common.isOnline = False + ConfigFlags.Beam.Type = "collisions" + ConfigFlags.Beam.Energy = 7*TeV + ConfigFlags.GeoModel.FaserVersion = "FASER-00" # Always needed + ConfigFlags.IOVDb.GlobalTag = "OFLCOND-MC16-SDR-14" # Always needed +# Workaround for bug/missing flag; unimportant otherwise + ConfigFlags.addFlag("Input.InitialTimeStamp", 0) +# Workaround to avoid failing metadata peek + ConfigFlags.GeoModel.AtlasVersion = "ATLAS-R2-2016-01-00-01" # Always needed to fool autoconfig +# Workaround to avoid problematic ISF code + ConfigFlags.GeoModel.Layout = "Development" +# To be sure... + ConfigFlags.Concurrency.NumThreads = 1 +# +# Output settings +# + ConfigFlags.Output.HITSFileName = "g4.HITS.root" + ConfigFlags.GeoModel.GeoExportFile = "faserGeo.db" # Optional dump of geometry for browsing in vp1light +# +# Geometry-related settings +# Do not change! +# + ConfigFlags.Detector.SimulateVeto = True + ConfigFlags.Detector.GeometryVeto = True + ConfigFlags.GeoModel.Align.Dynamic = False + ConfigFlags.Sim.ReleaseGeoModel = False +# +# All flags should be set before calling lock +# + ConfigFlags.lock() +# +# Construct ComponentAccumulator +# + acc = MainServicesSerialCfg() +# +# Particle Gun generator (comment out to read generator file) +# Raw energies (without units given) are interpreted as MeV +# + pg = PG.ParticleGun() + pg.McEventKey = "GEN_EVENT" + pg.randomSeed = 123456 + pg.sampler.pid = -13 + pg.sampler.mom = PG.EThetaMPhiSampler(energy=1*TeV, theta=[0, pi/10], phi=[0, 2*pi], mass=105.71) + pg.sampler.pos = PG.PosSampler(x=[-10, 10], y=[-10, 10], z=-2100.0, t=0.0) + acc.addEventAlgo(pg, "AthBeginSeq") # to run *before* G4 +# +# Only one of these two should be used in a given job +# (MCEventSelectorCfg for generating events with no input file, +# PoolReadCfg when reading generator data from an input file) +# + acc.merge(McEventSelectorCfg(ConfigFlags)) + # acc.merge(PoolReadCfg(ConfigFlags)) +# +# Output stream configuration +# + acc.merge(OutputStreamCfg(ConfigFlags, + "HITS", + ["EventInfo#*", + "McEventCollection#TruthEvent", + "McEventCollection#GEN_EVENT", + "ScintHitCollection#*" + ])) + acc.getEventAlgo("OutputStreamHITS").AcceptAlgs = ["G4FaserAlg"] # optional + acc.getEventAlgo("OutputStreamHITS").WritingTool.ProcessingTag = "StreamHITS" # required +# +# Here is the "manual" configuration of the Geant4 pieces +# + acc.merge(FaserGeometryCfg(ConfigFlags)) + acc.merge(G4FaserAlgCfg(ConfigFlags)) + algo = acc.getEventAlgo("G4FaserAlg") + veto, vetosd = VetoSensorSDCfg(ConfigFlags) + sendet = SensitiveDetectorMasterTool(SensitiveDetectors = [vetosd]) + acc.addPublicTool(sendet) + algo.SenDetMasterTool = sendet + acc.merge(veto) + acc.addService(G4GeometryNotifierSvcCfg(ConfigFlags, ActivateLVNotifier=True)) +# +# Verbosity +# +# ConfigFlags.dump() +# logging.getLogger('forcomps').setLevel(VERBOSE) +# acc.foreach_component("*").OutputLevel = VERBOSE +# acc.foreach_component("*ClassID*").OutputLevel = INFO +# acc.getService("StoreGateSvc").Dump=True +# acc.getService("ConditionStore").Dump=True +# acc.printConfig(withDetails=True) + f=open('FaserG4AppCfg_EVNT.pkl','w') + acc.store(f) + f.close() +# +# Execute and finish +# + acc.run(maxEvents=1000) diff --git a/Simulation/G4Faser/G4FaserInterfaces/CMakeLists.txt b/Simulation/G4Faser/G4FaserInterfaces/CMakeLists.txt new file mode 100644 index 000000000..b2c9cfb4b --- /dev/null +++ b/Simulation/G4Faser/G4FaserInterfaces/CMakeLists.txt @@ -0,0 +1,23 @@ +################################################################################ +# Package: G4FaserInterfaces +################################################################################ + +# Declare the package name: +atlas_subdir( G4FaserInterfaces ) + +# Declare the package's dependencies: +atlas_depends_on_subdirs( PUBLIC + GaudiKernel ) + +# External dependencies: +find_package( CLHEP ) +find_package( Geant4 ) +find_package( XercesC ) + +# Component(s) in the package: +atlas_add_library( G4FaserInterfaces + PUBLIC_HEADERS G4FaserInterfaces + INCLUDE_DIRS ${GEANT4_INCLUDE_DIRS} ${XERCESC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} + DEFINITIONS ${CLHEP_DEFINITIONS} + LINK_LIBRARIES ${GEANT4_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} GaudiKernel ) + diff --git a/Simulation/G4Faser/G4FaserServices/CMakeLists.txt b/Simulation/G4Faser/G4FaserServices/CMakeLists.txt new file mode 100644 index 000000000..36c0adb75 --- /dev/null +++ b/Simulation/G4Faser/G4FaserServices/CMakeLists.txt @@ -0,0 +1,43 @@ +################################################################################ +# Package: G4FaserServices +################################################################################ + +# Declare the package name: +atlas_subdir( G4FaserServices ) + +# Declare the package's dependencies: +atlas_depends_on_subdirs( PUBLIC + GaudiKernel + PRIVATE + Control/AthenaBaseComps + Control/StoreGate + DetectorDescription/AtlasDetDescr + Generators/GeneratorObjects + Generators/TruthUtils + Simulation/G4Sim/MCTruth + Simulation/G4Sim/SimHelpers + Simulation/G4Sim/TrackRecord + Simulation/ISF/ISF_Core/ISF_Event + Simulation/ISF/ISF_Core/ISF_Interfaces + Simulation/ISF/ISF_HepMC/ISF_HepMC_Interfaces + Tools/PmbCxxUtils ) + +# External dependencies: +find_package( CLHEP ) +find_package( Eigen ) +find_package( Geant4 ) +find_package( HepMC ) +find_package( HepPDT ) +find_package( ROOT COMPONENTS Core Tree MathCore Hist RIO pthread ) + +# Component(s) in the package: +atlas_add_component( G4FaserServices + src/*.cxx + src/components/*.cxx + INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${GEANT4_INCLUDE_DIRS} ${HEPMC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${HEPPDT_INCLUDE_DIRS} + LINK_LIBRARIES ${ROOT_LIBRARIES} ${GEANT4_LIBRARIES} ${HEPMC_LIBRARIES} ${CLHEP_LIBRARIES} ${HEPPDT_LIBRARIES} GaudiKernel AthenaBaseComps StoreGateLib SGtests GeneratorObjects MCTruth SimHelpers ISF_Event ISF_Interfaces PmbCxxUtils TruthUtils ) + + +# Install files from the package: +atlas_install_python_modules( python/*.py ) +atlas_install_scripts( test/*.py ) diff --git a/Simulation/G4Faser/G4FaserServices/python/G4FaserFieldServices.py b/Simulation/G4Faser/G4FaserServices/python/G4FaserFieldServices.py new file mode 100644 index 000000000..909073669 --- /dev/null +++ b/Simulation/G4Faser/G4FaserServices/python/G4FaserFieldServices.py @@ -0,0 +1,204 @@ +# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +# +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator +from G4AtlasServices.G4AtlasServicesConf import StandardFieldSvc, ConstantFieldSvc +from AthenaCommon.SystemOfUnits import tesla +from MagFieldServices.MagFieldServicesConfig import MagneticFieldSvcCfg +#to prevent unit tests failing when just running over simulation +# import os +# if "AthSimulation_DIR" not in os.environ: +# from ForwardRegionMgField.ForwardRegionMgFieldConf import MagField__ForwardRegionFieldSvc + +def StandardFieldSvcCfg(ConfigFlags,name="StandardField", **kwargs): + result = ComponentAccumulator() + + #setup the field and add the magneticfield service + acc = MagneticFieldSvcCfg(ConfigFlags) + result.merge(acc) + + kwargs.setdefault("MagneticFieldSvc", result.getService("AtlasFieldSvc")) # TODO This should probably be based on simFlags.MagneticField? + #kwargs.setdefault("FieldOn", True) + + result.addService(StandardFieldSvc(name, **kwargs)) + return result + +def ConstantFieldSvcCfg(ConfigFlags,name="ConstantField", **kwargs): + result = ComponentAccumulator() + + #setup the field and add the magneticfield service + # acc = MagneticFieldSvcCfg(ConfigFlags) + # result.merge(acc) + + # kwargs.setdefault("MagneticFieldSvc", result.getService("AtlasFieldSvc")) # TODO This should probably be based on simFlags.MagneticField? + #kwargs.setdefault("FieldOn", True) + + kwargs.setdefault("FieldX", 0.55 * tesla) + kwargs.setdefault("FieldY", 0.00 * tesla ) + kwargs.setdefault("FieldZ", 0.00 * tesla ) + result.addService(ConstantFieldSvc(name, **kwargs)) + return result + + +# def ForwardFieldSvcCfg(ConfigFlags, name="ForwardField", **kwargs): +# result = ComponentAccumulator() + +# #setup the field and add the magneticfield service +# acc = MagneticFieldSvcCfg(ConfigFlags) +# result.merge(acc) + +# #FIXME Once it exists this version should use the new MagField Service defined in ForwardRegionMgField +# kwargs.setdefault("MagneticFieldSvc", result.getService("AtlasFieldSvc")) +# #kwargs.setdefault("FieldOn", True) + +# result.addService(StandardFieldSvc(name, **kwargs)) +# return result + +# def Q1FwdG4FieldSvcCfg(ConfigFlags, name='Q1FwdG4FieldSvc', **kwargs): +# result = ComponentAccumulator() + +# result.addService( MagField__ForwardRegionFieldSvc("Q1", +# Magnet = 0, # FIXME find a better way to do this. +# MQXA_DataFile = "MQXA_NOMINAL.dat")) + +# kwargs.setdefault("MagneticFieldSvc", result.getService("Q1")) +# result.addService(StandardFieldSvc(name, **kwargs)) +# return result +# def Q2FwdG4FieldSvcCfg(ConfigFlags, name='Q2FwdG4FieldSvc', **kwargs): +# result = ComponentAccumulator() + +# result.addService( MagField__ForwardRegionFieldSvc("Q2", +# Magnet = 1, # FIXME find a better way to do this. +# MQXA_DataFile = "MQXA_NOMINAL.dat")) +# kwargs.setdefault("MagneticFieldSvc", result.getService("Q2")) +# result.addService(StandardFieldSvc(name, **kwargs)) +# return result +# def Q3FwdG4FieldSvcCfg(ConfigFlags, name='Q3FwdG4FieldSvc', **kwargs): +# result = ComponentAccumulator() + +# result.addService( MagField__ForwardRegionFieldSvc("Q3", +# Magnet = 2, # FIXME find a better way to do this. +# MQXA_DataFile = "MQXA_NOMINAL.dat")) +# kwargs.setdefault("MagneticFieldSvc", result.getService("Q3")) +# result.addService(StandardFieldSvc(name, **kwargs)) +# return result +# def D1FwdG4FieldSvcCfg(ConfigFlags, name='D1FwdG4FieldSvc', **kwargs): +# result = ComponentAccumulator() +# result.addService( MagField__ForwardRegionFieldSvc("D1", +# Magnet = 3))# FIXME find a better way to do this. + +# kwargs.setdefault("MagneticFieldSvc", result.getService("D1")) +# result.addService(StandardFieldSvc(name, **kwargs)) +# return result +# def D2FwdG4FieldSvcCfg(ConfigFlags, name='D2FwdG4FieldSvc', **kwargs): +# result = ComponentAccumulator() + +# result.addService( MagField__ForwardRegionFieldSvc("D2", +# Magnet = 4))# FIXME find a better way to do this. +# kwargs.setdefault("MagneticFieldSvc", result.getService("D2")) +# result.addService(StandardFieldSvc(name, **kwargs)) +# return result +# def Q4FwdG4FieldSvcCfg(ConfigFlags, name='Q4FwdG4FieldSvc', **kwargs): +# result = ComponentAccumulator() +# result.addService( MagField__ForwardRegionFieldSvc("Q4", +# Magnet = 5))# FIXME find a better way to do this. +# kwargs.setdefault("MagneticFieldSvc", result.getService("Q4")) +# result.addService(StandardFieldSvc(name, **kwargs)) +# return result +# def Q5FwdG4FieldSvcCfg(ConfigFlags, name='Q5FwdG4FieldSvc', **kwargs): +# result = ComponentAccumulator() +# result.addService( MagField__ForwardRegionFieldSvc("Q5", +# Magnet = 6))# FIXME find a better way to do this. +# kwargs.setdefault("MagneticFieldSvc", result.getService("Q5")) +# result.addService(StandardFieldSvc(name, **kwargs)) +# return result +# def Q6FwdG4FieldSvcCfg(ConfigFlags, name='Q6FwdG4FieldSvc', **kwargs): +# result = ComponentAccumulator() +# result.addService( MagField__ForwardRegionFieldSvc("Q6", +# Magnet = 7))# FIXME find a better way to do this. +# kwargs.setdefault("MagneticFieldSvc", result.getService("Q6")) +# result.addService(StandardFieldSvc(name, **kwargs)) +# return result +# def Q7FwdG4FieldSvcCfg(ConfigFlags, name='Q7FwdG4FieldSvc', **kwargs): +# result = ComponentAccumulator() +# result.addService( MagField__ForwardRegionFieldSvc("Q7", +# Magnet = 8))# FIXME find a better way to do this. +# kwargs.setdefault("MagneticFieldSvc", result.getService("Q7")) +# result.addService(StandardFieldSvc(name, **kwargs)) +# return result +# def Q1HKickFwdG4FieldSvcCfg(ConfigFlags, name='Q1HKickFwdG4FieldSvc', **kwargs): +# result = ComponentAccumulator() +# result.addService( MagField__ForwardRegionFieldSvc("Q1HKick", +# Magnet = 9))# FIXME find a better way to do this. +# kwargs.setdefault("MagneticFieldSvc", result.getService("Q1HKick")) +# result.addService(StandardFieldSvc(name, **kwargs)) +# return result +# def Q1VKickFwdG4FieldSvcCfg(ConfigFlags, name='Q1VKickFwdG4FieldSvc', **kwargs): #note is lower case "v" in ForwardRegionMgFieldConfig.py +# result = ComponentAccumulator() +# result.addService( MagField__ForwardRegionFieldSvc("Q1VKick", +# Magnet = 10))# FIXME find a better way to do this. +# kwargs.setdefault("MagneticFieldSvc", result.getService("Q1VKick")) +# result.addService(StandardFieldSvc(name, **kwargs)) +# return result +# def Q2HKickFwdG4FieldSvcCfg(ConfigFlags, name='Q2HKickFwdG4FieldSvc', **kwargs): +# result = ComponentAccumulator() +# result.addService( MagField__ForwardRegionFieldSvc("Q2HKick", +# Magnet = 11))# FIXME find a better way to do this. +# kwargs.setdefault("MagneticFieldSvc", result.getService("Q2HKick")) +# result.addService(StandardFieldSvc(name, **kwargs)) +# return result +# def Q2VKickFwdG4FieldSvcCfg(ConfigFlags, name='Q2VKickFwdG4FieldSvc', **kwargs): +# result = ComponentAccumulator() +# result.addService( MagField__ForwardRegionFieldSvc("Q2VKick", +# Magnet = 12))# FIXME find a better way to do this. +# kwargs.setdefault("MagneticFieldSvc", result.getService("Q2VKick")) +# result.addService(StandardFieldSvc(name, **kwargs)) +# return result +# def Q3HKickFwdG4FieldSvcCfg(ConfigFlags, name='Q3HKickFwdG4FieldSvc', **kwargs): +# result = ComponentAccumulator() +# result.addService( MagField__ForwardRegionFieldSvc("Q3HKick", +# Magnet = 13))# FIXME find a better way to do this. +# kwargs.setdefault("MagneticFieldSvc", result.getService("Q3HKick")) +# result.addService(StandardFieldSvc(name, **kwargs)) +# return result +# def Q3VKickFwdG4FieldSvcCfg(ConfigFlags, name='Q3VKickFwdG4FieldSvc', **kwargs): +# result = ComponentAccumulator() +# result.addService( MagField__ForwardRegionFieldSvc("Q3VKick", +# Magnet = 14))# FIXME find a better way to do this. +# kwargs.setdefault("MagneticFieldSvc", result.getService("Q3VKick")) +# result.addService(StandardFieldSvc(name, **kwargs)) +# return result +# def Q4VKickAFwdG4FieldSvcCfg(ConfigFlags, name='Q4VKickAFwdG4FieldSvc', **kwargs): +# result = ComponentAccumulator() +# result.addService( MagField__ForwardRegionFieldSvc("Q4VKickA", +# Magnet = 15))# FIXME find a better way to do this. +# kwargs.setdefault("MagneticFieldSvc", result.getService("Q4VKickA")) +# result.addService(StandardFieldSvc(name, **kwargs)) +# return result +# def Q4HKickFwdG4FieldSvcCfg(ConfigFlags, name='Q4HKickFwdG4FieldSvc', **kwargs): +# result = ComponentAccumulator() +# result.addService( MagField__ForwardRegionFieldSvc("Q4HKick", +# Magnet = 16))# FIXME find a better way to do this. +# kwargs.setdefault("MagneticFieldSvc", result.getService("Q4HKick")) +# result.addService(StandardFieldSvc(name, **kwargs)) +# return result +# def Q4VKickBFwdG4FieldSvcCfg(ConfigFlags, name='Q4VKickBFwdG4FieldSvc', **kwargs): +# result = ComponentAccumulator() +# result.addService( MagField__ForwardRegionFieldSvc("Q4VKickB", +# Magnet = 17))# FIXME find a better way to do this. +# kwargs.setdefault("MagneticFieldSvc", result.getService("Q4VKickB")) +# result.addService(StandardFieldSvc(name, **kwargs)) +# return result +# def Q5HKickFwdG4FieldSvcCfg(ConfigFlags, name='Q5HKickFwdG4FieldSvc', **kwargs): +# result = ComponentAccumulator() +# result.addService( MagField__ForwardRegionFieldSvc("Q5HKick", +# Magnet = 18))# FIXME find a better way to do this. +# kwargs.setdefault("MagneticFieldSvc", result.getService("Q5HKick")) +# result.addService(StandardFieldSvc(name, **kwargs)) +# return result +# def Q6VKickFwdG4FieldSvcCfg(ConfigFlags, name='Q6VKickFwdG4FieldSvc', **kwargs): +# result = ComponentAccumulator() +# result.addService( MagField__ForwardRegionFieldSvc("Q6VKick", +# Magnet = 19))# FIXME find a better way to do this. +# kwargs.setdefault("MagneticFieldSvc", result.getService("Q6VKick")) +# result.addService(StandardFieldSvc(name, **kwargs)) +# return result diff --git a/Simulation/G4Faser/G4FaserServices/python/G4FaserServicesConfigNew.py b/Simulation/G4Faser/G4FaserServices/python/G4FaserServicesConfigNew.py new file mode 100644 index 000000000..96c702359 --- /dev/null +++ b/Simulation/G4Faser/G4FaserServices/python/G4FaserServicesConfigNew.py @@ -0,0 +1,140 @@ +# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +# +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator +# +# The code of these services is experiment-agnostic, so we just have to configure them here for FASER instead of ATLAS +# +from G4AtlasServices.G4AtlasServicesConf import DetectorGeometrySvc, G4AtlasSvc, G4GeometryNotifierSvc +# +# Physics region tools +# +from G4FaserTools.G4PhysicsRegionConfigNew import ScintillatorPhysicsRegionToolCfg #, TrackerPhysicsRegionToolCfg, FaserCaloPhysicsRegionToolCfg +from G4FaserServices.G4FaserServicesConf import ISF__FaserGeoIDSvc +# +# Geometry tools +# +from G4FaserTools.G4GeometryToolConfig import MaterialDescriptionToolCfg, G4AtlasDetectorConstructionToolCfg, FASEREnvelopeCfg +# +# Magnetic field tools - start simple +# +from G4FaserTools.G4FieldConfigNew import FASERFieldManagerToolCfg, VetoFieldManagerToolCfg +# +# Future field managers (?) +# +# from G4FaserTools.G4FieldConfigNew import TriggerFieldManagerToolCfg, PreshowerFieldManagerToolCfg, UpstreamTrackerFieldManagerToolCfg, CentralTrackerFieldManagerToolCfg, DownstreamTrackerFieldManagerToolCfg, UpstreamDipoleFieldManagerToolCfg, CentralDipoleFieldManagerToolCfg, DownstreamDipleFieldManagerToolCfg, FaserCaloFieldManagerToolCfg +# +# +def FaserGeoIDSvcCfg(ConfigFlags, name="ISF_FaserGeoIDSvc", **kwargs): + result = ComponentAccumulator() + # with ISF volume definitions + result.addService(ISF__FaserGeoIDSvc(name, **kwargs)) + return result +# +def getFASER_RegionCreatorList(ConfigFlags): + regionCreatorList = [] + + from G4AtlasApps.SimFlags import simFlags + # Settings to widen the region of study - not yet supported by FASER + # if ConfigFlags.Beam.Type == 'cosmics' or ConfigFlags.Sim.CavernBG != 'Signal': + # regionCreatorList += [SX1PhysicsRegionToolCfg(ConfigFlags), BedrockPhysicsRegionToolCfg(ConfigFlags), CavernShaftsConcretePhysicsRegionToolCfg(ConfigFlags)] + + if ConfigFlags.Detector.SimulateScintillator: + regionCreatorList += [ScintillatorPhysicsRegionToolCfg(ConfigFlags)] + + # if ConfigFlags.Detector.SimulateTracker: + # regionCreatorList += [TrackerPhysicsRegionToolCfg(ConfigFlags)] + + # if ConfigFlags.Detector.SimulateFaserCalo: + # regionCreatorList += [FaserCaloPhysicsRegionToolCfg(ConfigFlags)] + + return regionCreatorList + +######################################################################### +def FASER_FieldMgrListCfg(ConfigFlags): + result = ComponentAccumulator() + fieldMgrList = [] + + acc = FASERFieldManagerToolCfg(ConfigFlags) + tool = result.popToolsAndMerge(acc) + fieldMgrList += [tool] + + # if ConfigFlags.Detector.SimulateUpstreamDipole: + # acc = UpstreamDipoleFieldManagerToolCfg(ConfigFlags) + # tool = result.popToolsAndMerge(acc) + # fieldMgrList += [tool] + # if ConfigFlags.Detector.SimulateCentralDipole: + # acc = CentralDipoleFieldManagerToolCfg(ConfigFlags) + # tool = result.popToolsAndMerge(acc) + # fieldMgrList += [tool] + # if ConfigFlags.Detector.SimulateDownstreamDipole: + # acc = DownstreamDipoleFieldManagerToolCfg(ConfigFlags) + # tool = result.popToolsAndMerge(acc) + # fieldMgrList += [tool] + if ConfigFlags.Detector.SimulateVeto: + acc = VetoFieldManagerToolCfg(ConfigFlags) + tool = result.popToolsAndMerge(acc) + fieldMgrList += [tool] + # if ConfigFlags.Detector.SimulateTrigger: + # acc = TriggerFieldManagerToolCfg(ConfigFlags) + # tool = result.popToolsAndMerge(acc) + # fieldMgrList += [tool] + # if ConfigFlags.Detector.SimulatePreshower: + # acc = PreshowerFieldManagerToolCfg(ConfigFlags) + # tool = result.popToolsAndMerge(acc) + # fieldMgrList += [tool] + # if ConfigFlags.Detector.SimulateTracker: + # acc = UpstreamTrackerFieldManagerToolCfg(ConfigFlags) + # tool = result.popToolsAndMerge(acc) + # fieldMgrList += [tool] + # acc = CentralTrackerFieldManagerToolCfg(ConfigFlags) + # tool = result.popToolsAndMerge(acc) + # fieldMgrList += [tool] + # acc = DownstreamTrackerFieldManagerToolCfg(ConfigFlags) + # tool = result.popToolsAndMerge(acc) + # fieldMgrList += [tool] + # if ConfigFlags.Detector.SimulateFaserCalo: + # acc = FaserCaloFieldManagerToolCfg(ConfigFlags) + # tool = result.popToolsAndMerge(acc) + # fieldMgrList += [tool] + + result.setPrivateTools(fieldMgrList) + return result + +def getGeometryConfigurationTools(ConfigFlags): + geoConfigToolList = [] + # The methods for these tools should be defined in the + # package containing each tool, so G4FaserTools in this case + geoConfigToolList += [MaterialDescriptionToolCfg(ConfigFlags)] + return geoConfigToolList + + +def DetectorGeometrySvcCfg(ConfigFlags, name="DetectorGeometrySvc", **kwargs): + result = ComponentAccumulator() + kwargs.setdefault("DetectorConstruction", G4AtlasDetectorConstructionToolCfg(ConfigFlags)) + kwargs.setdefault("GeometryConfigurationTools", getGeometryConfigurationTools(ConfigFlags)) + + accGeo, toolGeo = FASEREnvelopeCfg(ConfigFlags) + kwargs.setdefault("World", toolGeo) + result.merge(accGeo) + kwargs.setdefault("RegionCreators", getFASER_RegionCreatorList(ConfigFlags)) + acc = FASER_FieldMgrListCfg(ConfigFlags) + fieldMgrList = result.popToolsAndMerge(acc) + kwargs.setdefault("FieldManagers", fieldMgrList) + + result.addService(DetectorGeometrySvc(name, **kwargs)) + return result + +def G4AtlasSvcCfg(ConfigFlags, name="G4AtlasSvc", **kwargs): + if ConfigFlags.Concurrency.NumThreads > 0: + is_hive = True + else: + is_hive = False + kwargs.setdefault("isMT", is_hive) + kwargs.setdefault("DetectorGeometrySvc", 'DetectorGeometrySvc') + return G4AtlasSvc(name, **kwargs) + + +def G4GeometryNotifierSvcCfg(ConfigFlags, name="G4GeometryNotifierSvc", **kwargs): + kwargs.setdefault("ActivateLVNotifier", True) + kwargs.setdefault("ActivatePVNotifier", False) + return G4GeometryNotifierSvc(name, **kwargs) diff --git a/Simulation/G4Faser/G4FaserServices/python/__init__.py b/Simulation/G4Faser/G4FaserServices/python/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/Simulation/G4Faser/G4FaserServices/src/FaserGeoIDSvc.cxx b/Simulation/G4Faser/G4FaserServices/src/FaserGeoIDSvc.cxx new file mode 100644 index 000000000..7958b3acb --- /dev/null +++ b/Simulation/G4Faser/G4FaserServices/src/FaserGeoIDSvc.cxx @@ -0,0 +1,71 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/////////////////////////////////////////////////////////////////// +// GeoIDSvc.cxx, (c) ATLAS Detector software +/////////////////////////////////////////////////////////////////// + +// class header include +#include "FaserGeoIDSvc.h" + +// framework includes +#include "GaudiKernel/Bootstrap.h" +#include "GaudiKernel/ISvcLocator.h" + +// DetectorDescription +#include "AtlasDetDescr/AtlasRegionHelper.h" + +// STL includes +#include <algorithm> + +/** Constructor **/ +ISF::FaserGeoIDSvc::FaserGeoIDSvc(const std::string& name,ISvcLocator* svc) : + base_class(name,svc) +{ } + + +/** Destructor **/ +ISF::FaserGeoIDSvc::~FaserGeoIDSvc() +{ } + + +// Athena algtool's Hooks +StatusCode ISF::FaserGeoIDSvc::initialize() +{ + ATH_MSG_INFO("initialize() ..."); + + ATH_MSG_INFO("initialize() successful"); + return StatusCode::SUCCESS; +} + + +StatusCode ISF::FaserGeoIDSvc::finalize() { + ATH_MSG_INFO("finalize() ..."); + + ATH_MSG_INFO("finalize() successful"); + return StatusCode::SUCCESS; +} + + +ISF::InsideType ISF::FaserGeoIDSvc::inside(const Amg::Vector3D& , AtlasDetDescr::AtlasRegion geoID) const { + +// Only one answer... + return (geoID == AtlasDetDescr::fUndefinedAtlasRegion ? ISF::fInside : ISF::fOutside); +} + + +AtlasDetDescr::AtlasRegion ISF::FaserGeoIDSvc::identifyGeoID(const Amg::Vector3D& ) const { + +// Only one answer... + return AtlasDetDescr::fUndefinedAtlasRegion; +} + + +AtlasDetDescr::AtlasRegion ISF::FaserGeoIDSvc::identifyNextGeoID(const Amg::Vector3D& , + const Amg::Vector3D& ) const { + +// Only one answer... + return AtlasDetDescr::fUndefinedAtlasRegion; +} + diff --git a/Simulation/G4Faser/G4FaserServices/src/FaserGeoIDSvc.h b/Simulation/G4Faser/G4FaserServices/src/FaserGeoIDSvc.h new file mode 100644 index 000000000..5faf5ff6a --- /dev/null +++ b/Simulation/G4Faser/G4FaserServices/src/FaserGeoIDSvc.h @@ -0,0 +1,66 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +////////////////////////////////////////////////////////////////// +// FaserGeoIDSvc.h, (c) ATLAS Detector software +/////////////////////////////////////////////////////////////////// + +#ifndef G4FASERSERVICES_FASERGEOIDSVC_H +#define G4FASERSERVICES_FASERGEOIDSVC_H 1 + +// framework includes +#include "GaudiKernel/ServiceHandle.h" +#include "AthenaBaseComps/AthService.h" + +// STL includes +#include <vector> +#include <list> +#include <set> + +// DetectorDescription +#include "AtlasDetDescr/AtlasRegion.h" + +// ISF includes +#include "ISF_Interfaces/IGeoIDSvc.h" + +namespace ISF { + + /** @class GeoIDSvc + + A fast Athena service identifying the AtlasRegion a given position/particle is in. + + @author Elmar.Ritsch -at- cern.ch + + This dummy version for FASER says that everything is in the "undefined" ATLAS region + + */ + class FaserGeoIDSvc : public extends<AthService, ISF::IGeoIDSvc> { + public: + /** Constructor with parameters */ + FaserGeoIDSvc(const std::string& name,ISvcLocator* svc); + + /** Destructor */ + ~FaserGeoIDSvc(); + + // Athena algtool's Hooks + StatusCode initialize(); + StatusCode finalize(); + + /** A static filter that returns the SimGeoID of the given position */ + AtlasDetDescr::AtlasRegion identifyGeoID(const Amg::Vector3D &pos) const; + + /** Checks if the given position (or ISFParticle) is inside a given SimGeoID */ + ISF::InsideType inside(const Amg::Vector3D &pos, AtlasDetDescr::AtlasRegion geoID) const; + + /** Find the SimGeoID that the particle will enter with its next infinitesimal step + along the given direction */ + AtlasDetDescr::AtlasRegion identifyNextGeoID(const Amg::Vector3D &pos, const Amg::Vector3D &dir) const; + + private: + + }; + +} // ISF namespace + +#endif //> !FASERSERVICES_FASERGEOIDSVC_H diff --git a/Simulation/G4Faser/G4FaserServices/src/components/G4FaserServices_entries.cxx b/Simulation/G4Faser/G4FaserServices/src/components/G4FaserServices_entries.cxx new file mode 100644 index 000000000..0b310990b --- /dev/null +++ b/Simulation/G4Faser/G4FaserServices/src/components/G4FaserServices_entries.cxx @@ -0,0 +1,3 @@ +#include "../FaserGeoIDSvc.h" + +DECLARE_COMPONENT( ISF::FaserGeoIDSvc ) diff --git a/Simulation/G4Faser/G4FaserTools/CMakeLists.txt b/Simulation/G4Faser/G4FaserTools/CMakeLists.txt new file mode 100644 index 000000000..e6729ddd9 --- /dev/null +++ b/Simulation/G4Faser/G4FaserTools/CMakeLists.txt @@ -0,0 +1,44 @@ +################################################################################ +# Package: G4FaserTools +################################################################################ + +# Declare the package name: +atlas_subdir( G4FaserTools ) + +# Declare the package's dependencies: +atlas_depends_on_subdirs( PUBLIC + AtlasGeometryCommon/SubDetectorEnvelopes + Control/AthenaBaseComps + Simulation/G4Atlas/G4AtlasInterfaces + PRIVATE + GaudiKernel + Simulation/G4Utilities/G4PhysicsLists ) + +# External dependencies: +find_package( Boost COMPONENTS filesystem thread system ) +find_package( CLHEP ) +find_package( Geant4 ) +find_package( TBB ) +find_package( XercesC ) + +# Component(s) in the package: +#atlas_add_library( G4FaserToolsLib +# src/*.cxx +# src/*.cc +# PUBLIC_HEADERS G4FaserTools +# INCLUDE_DIRS ${XERCESC_INCLUDE_DIRS} ${GEANT4_INCLUDE_DIRS} ${TBB_INCLUDE_DIRS} +# PRIVATE_INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} +# PRIVATE_DEFINITIONS ${CLHEP_DEFINITIONS} +# LINK_LIBRARIES ${XERCESC_LIBRARIES} ${GEANT4_LIBRARIES} ${TBB_LIBRARIES} AthenaBaseComps G4AtlasInterfaces +# PRIVATE_LINK_LIBRARIES ${Boost_LIBRARIES} ${CLHEP_LIBRARIES} GaudiKernel G4PhysicsLists ) + +#atlas_add_component( G4FaserTools +# src/components/*.cxx +# INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${XERCESC_INCLUDE_DIRS} ${GEANT4_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${TBB_INCLUDE_DIRS} +# LINK_LIBRARIES ${Boost_LIBRARIES} ${XERCESC_LIBRARIES} ${GEANT4_LIBRARIES} ${CLHEP_LIBRARIES} ${TBB_LIBRARIES} AthenaBaseComps G4AtlasInterfaces GaudiKernel G4PhysicsLists G4FaserToolsLib ) + + +# Install files from the package: +atlas_install_python_modules( python/*.py ) +atlas_install_scripts( test/*.py ) + diff --git a/Simulation/G4Faser/G4FaserTools/python/G4FaserToolsConfig.py b/Simulation/G4Faser/G4FaserTools/python/G4FaserToolsConfig.py new file mode 100644 index 000000000..f81b5f675 --- /dev/null +++ b/Simulation/G4Faser/G4FaserTools/python/G4FaserToolsConfig.py @@ -0,0 +1,141 @@ +# Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration + +from AthenaCommon import CfgMgr + +def generateFastSimulationList(): + FastSimulationList=[] + # + # Not yet supported in FASER + # + # from G4AtlasApps.SimFlags import simFlags + # from CalypsoCommon.DetFlags import DetFlags + # if DetFlags.bpipe_on(): + # if hasattr(simFlags, 'ForwardDetectors') and simFlags.ForwardDetectors.statusOn and simFlags.ForwardDetectors() == 2: + # FastSimulationList += ['ForwardTransportModel'] + # if hasattr(simFlags, 'BeamPipeSimMode') and simFlags.BeamPipeSimMode.statusOn and simFlags.BeamPipeSimMode() != "Normal": + # FastSimulationList += [ 'SimpleFastKiller' ] + # if DetFlags.geometry.LAr_on(): + # ## Shower parameterization overrides the calibration hit flag + # if simFlags.LArParameterization.statusOn and simFlags.LArParameterization() > 0 \ + # and simFlags.CalibrationRun.statusOn and simFlags.CalibrationRun.get_Value() in ['LAr','LAr+Tile','DeadLAr']: + # print 'getFastSimulationMasterTool FATAL :: You requested both calibration hits and frozen showers / parameterization in the LAr.' + # print ' Such a configuration is not allowed, and would give junk calibration hits where the showers are modified.' + # print ' Please try again with a different value of simFlags.LArParameterization or simFlags.CalibrationRun ' + # raise RuntimeError('Configuration not allowed') + # if simFlags.LArParameterization() > 0: + # #FIXME If we're only using Frozen Showers in the FCAL do we really need to set up the EMB and EMEC as well? + # FastSimulationList += ['EMBFastShower', 'EMECFastShower', 'FCALFastShower', 'FCAL2FastShower'] + # if simFlags.LArParameterization.get_Value() > 1: + # FastSimulationList += ['DeadMaterialShower'] + # elif simFlags.LArParameterization() is None or simFlags.LArParameterization() == 0: + # print "getFastSimulationMasterTool INFO No Frozen Showers" + # if DetFlags.Muon_on(): + # if hasattr(simFlags, 'CavernBG') and simFlags.CavernBG.statusOn and simFlags.CavernBG.get_Value() != 'Read' and\ + # not (hasattr(simFlags, 'RecordFlux') and simFlags.RecordFlux.statusOn and simFlags.RecordFlux()): + # FastSimulationList += ['NeutronFastSim'] + return FastSimulationList + +# def getFastSimulationMasterTool(name="FastSimulationMasterTool", **kwargs): +# kwargs.setdefault("FastSimulations", generateFastSimulationList()) +# return CfgMgr.FastSimulationMasterTool(name, **kwargs) + +# def getEmptyFastSimulationMasterTool(name="EmptyFastSimulationMasterTool", **kwargs): +# return CfgMgr.FastSimulationMasterTool(name, **kwargs) + +# def generateFwdSensitiveDetectorList(): +# SensitiveDetectorList=[] +# from G4AtlasApps.SimFlags import simFlags +# from AthenaCommon.DetFlags import DetFlags +# if DetFlags.simulate.Lucid_on(): +# SensitiveDetectorList += [ 'LUCID_SensitiveDetector' ] +# if hasattr(simFlags, 'ForwardDetectors') and simFlags.ForwardDetectors.statusOn: +# if DetFlags.simulate.ZDC_on(): +# SensitiveDetectorList += [ 'ZDC_PixelSD', 'ZDC_StripSD' ] +# if DetFlags.simulate.ALFA_on(): +# SensitiveDetectorList += [ 'ALFA_SensitiveDetector' ] +# if DetFlags.simulate.AFP_on(): +# SensitiveDetectorList += [ 'AFP_SensitiveDetector' ] +# #SensitiveDetectorList += [ 'AFP_SiDSensitiveDetector', 'AFP_TDSensitiveDetector' ] + +# return SensitiveDetectorList + +# def generateTrackFastSimSensitiveDetectorList(): +# SensitiveDetectorList=[] +# from AthenaCommon.DetFlags import DetFlags +# from G4AtlasApps.SimFlags import simFlags +# if (DetFlags.Muon_on() and simFlags.CavernBG.statusOn and simFlags.CavernBG.get_Value() != 'Read' and 'Write' in simFlags.CavernBG.get_Value()) or (hasattr(simFlags, 'StoppedParticleFile') and simFlags.StoppedParticleFile.statusOn): +# SensitiveDetectorList += [ 'TrackFastSimSD' ] +# return SensitiveDetectorList + +def generateScintillatorSensitiveDetectorList(): + SensitiveDetectorList=[] + from CalypsoConfiguration.AllConfigFlags import ConfigFlags + if (ConfigFlags.Detector.SimulateScintillator): + if (ConfigFlags.Detector.SimulateVeto): + SensitiveDetectorList += [ 'VetoSensorSD' ] + # if (ConfigFlags.Detector.SimulateTrigger): + # SensitiveDetectorList += [ 'TriggerSensorSD'] + # if (ConfigFlags.Detector.SimulatePreshowe): + # SensitiveDetectorList += [ 'PreshowerSD'] + return SensitiveDetectorList + +def generateTrackerSensitiveDetectorList(): + SensitiveDetectorList=[] + # from CalypsoConfiguration.AllFlags import ConfigFlags + # if (ConfigFlags.Detector.SimulateTracker): + # SensitiveDetectorList += [ 'SctSensorSD' ] + return SensitiveDetectorList + +def generateFaserCaloSensitiveDetectorList(): + SensitiveDetectorList=[] + # from CalypsoConfiguration.AllFlags import ConfigFlags + # if (ConfigFlags.Detector.SimulateFaserCalo): + # SensitiveDetectorList += [ 'FaserCaloSensorSD' ] + return SensitiveDetectorList + +def generateSensitiveDetectorList(): + SensitiveDetectorList=[] + SensitiveDetectorList += generateScintillatorSensitiveDetectorList() + SensitiveDetectorList += generateTrackerSensitiveDetectorList() + SensitiveDetectorList += generateFaserCaloSensitiveDetectorList() + return SensitiveDetectorList + +def getSensitiveDetectorMasterTool(name="SensitiveDetectorMasterTool", **kwargs): + kwargs.setdefault("SensitiveDetectors", generateSensitiveDetectorList()) + return CfgMgr.SensitiveDetectorMasterTool(name, **kwargs) + +def getEmptySensitiveDetectorMasterTool(name="EmptySensitiveDetectorMasterTool", **kwargs): + return CfgMgr.SensitiveDetectorMasterTool(name, **kwargs) + +def getPhysicsListToolBase(name="PhysicsListToolBase", **kwargs): + PhysOptionList = ["G4StepLimitationTool"] + from CalypsoConfiguration.AllFlags import ConfigFlags + PhysOptionList += ConfigFlags.Sim.PhysicsOptions + PhysDecaysList = [] + + kwargs.setdefault("PhysOption", PhysOptionList) + kwargs.setdefault("PhysicsDecay", PhysDecaysList) + kwargs.setdefault("PhysicsList", ConfigFlags.Sim.PhysicsList) + + if 'PhysicsList' in kwargs: + if kwargs['PhysicsList'].endswith('_EMV') or kwargs['PhysicsList'].endswith('_EMX'): + raise RuntimeError( 'PhysicsList not allowed: '+kwargs['PhysicsList'] ) + kwargs.setdefault("GeneralCut", 1.) + if (ConfigFlags.Sim.NeutronTimeCut.statusOn): + kwargs.setdefault("NeutronTimeCut", ConfigFlags.Sim.NeutronTimeCut) + if (ConfigFlags.Sim.NeutronEnergyCut.statusOn): + kwargs.setdefault("NeutronEnergyCut", ConfigFlags.Sim.NeutronEnergyCut) + if (ConfigFlags.Sim.ApplyEMCuts.statusOn): + kwargs.setdefault("ApplyEMCuts", ConfigFlags.Sim.ApplyEMCuts) + return CfgMgr.PhysicsListToolBase(name, **kwargs) + +def getReducedStepSizeUserLimitsTool(name="ReducedStepSizeUserLimitsTool", **kwargs): + from AthenaCommon.SystemOfUnits import millimeter + kwargs.setdefault("OutputLevel", 1) + kwargs.setdefault("VolumeList", [ + "Faser::Faser", + ]) + kwargs.setdefault("MaxStep", 10.*millimeter) + kwargs.setdefault("MatchType", "contains") + return CfgMgr.UserLimitsTool(name, **kwargs) + diff --git a/Simulation/G4Faser/G4FaserTools/python/G4FieldConfigNew.py b/Simulation/G4Faser/G4FaserTools/python/G4FieldConfigNew.py new file mode 100644 index 000000000..2b2ede247 --- /dev/null +++ b/Simulation/G4Faser/G4FaserTools/python/G4FieldConfigNew.py @@ -0,0 +1,331 @@ +# +# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +# +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator +from CalypsoConfiguration.AllConfigFlags import ConfigFlags +from G4AtlasApps.SimFlags import simFlags +# +# These field tools and services are generic and can be reused by reconfiguring them +# +from G4AtlasTools.G4AtlasToolsConf import GlobalFieldManagerTool, DetectorFieldManagerTool +# +from G4FaserServices.G4FaserFieldServices import StandardFieldSvcCfg, ConstantFieldSvcCfg +# +# Field Managers +# +def FASERFieldManagerToolCfg(ConfigFlags, name='FaserFieldManager', **kwargs): + result = ComponentAccumulator() + kwargs.setdefault("IntegratorStepper", simFlags.G4Stepper.get_Value()) + + # acc = StandardFieldSvcCfg(ConfigFlags) + # kwargs.setdefault("FieldSvc", acc.getService("StandardField")) + acc = ConstantFieldSvcCfg(ConfigFlags) + kwargs.setdefault("FieldSvc", acc.getService("ConstantField")) + result.merge(acc) + + kwargs.setdefault("UseTightMuonStepping", False) + if simFlags.EquationOfMotion.statusOn: + kwargs.setdefault("EquationOfMotion", simFlags.EquationOfMotion.get_Value()) + result.setPrivateTools(GlobalFieldManagerTool(name, **kwargs)) + return result + +def TightMuonsFASERFieldManagerToolCfg(ConfigFlags, name='TightMuonsFASERFieldManager', **kwargs): + result = ComponentAccumulator() + kwargs.setdefault("IntegratorStepper", simFlags.G4Stepper.get_Value()) + + # acc = StandardFieldSvcCfg(ConfigFlags) + # kwargs.setdefault("FieldSvc", acc.getService("StandardField")) + acc = ConstantFieldSvcCfg(ConfigFlags) + kwargs.setdefault("FieldSvc", acc.getService("ConstantField")) + result.merge(acc) + + kwargs.setdefault("UseTightMuonStepping",True) + if simFlags.EquationOfMotion.statusOn: + kwargs.setdefault("EquationOfMotion", simFlags.EquationOfMotion.get_Value() ) + + result.setPrivateTools(GlobalFieldManagerTool(name, **kwargs)) + return result + +# #not used in G4AtlasServicesConfigNew? +# def ClassicFieldManagerToolCfg(ConfigFlags, name='ClassicFieldManager', **kwargs): +# kwargs.setdefault("IntegratorStepper", "ClassicalRK4") +# return ATLASFieldManagerToolCfg(ConfigFlags, name, **kwargs) +# +def BasicDetectorFieldManagerToolCfg(ConfigFlags, name='BasicDetectorFieldManager', **kwargs): + result = ComponentAccumulator() + kwargs.setdefault("IntegratorStepper", simFlags.G4Stepper.get_Value()) + + acc = StandardFieldSvcCfg(ConfigFlags) + kwargs.setdefault("FieldSvc", acc.getService("StandardField")) + result.merge(acc) + + kwargs.setdefault('MuonOnlyField', False) + if sim.EquationOfMotion.statusOn: + kwargs.setdefault("EquationOfMotion", simFlags.EquationOfMotion.get_Value() ) + + result.setPrivateTools(DetectorFieldManagerTool(name, **kwargs)) + return result +# +# Simple constant field everywhere +# +def BasicDetectorConstantFieldManagerToolCfg(ConfigFlags, name='BasicDetectorConstantFieldManager', **kwargs): + result = ComponentAccumulator() + kwargs.setdefault("IntegratorStepper", simFlags.G4Stepper.get_Value()) + + # acc = StandardFieldSvcCfg(ConfigFlags) + # kwargs.setdefault("FieldSvc", acc.getService("StandardField")) + acc = ConstantFieldSvcCfg(ConfigFlags) + kwargs.setdefault("FieldSvc", acc.getService("ConstantField")) + result.merge(acc) + + kwargs.setdefault('MuonOnlyField', False) + if simFlags.EquationOfMotion.statusOn: + kwargs.setdefault("EquationOfMotion", simFlags.EquationOfMotion.get_Value() ) + + result.setPrivateTools(DetectorFieldManagerTool(name, **kwargs)) + return result +# +# Same numerical values as ATLAS Inner Detector +# +def VetoFieldManagerToolCfg(ConfigFlags, name='VetoFieldManager', **kwargs): + kwargs.setdefault("LogicalVolumes", ['Veto::Veto']) + #kwargs.setdefault('DeltaChord', 0.00001) + kwargs.setdefault('DeltaIntersection', 0.00001) + kwargs.setdefault('DeltaOneStep', 0.0001) + kwargs.setdefault('MaximumEpsilonStep', 0.001) + kwargs.setdefault('MinimumEpsilonStep', 0.00001) + return BasicDetectorConstantFieldManagerToolCfg(ConfigFlags, name, **kwargs) + +# def BeamPipeFieldManagerToolCfg(ConfigFlags, name='BeamPipeFieldManager', **kwargs): +# kwargs.setdefault("LogicalVolumes", ['BeamPipe::BeamPipe']) +# #kwargs.setdefault('DeltaChord', 0.00001) +# kwargs.setdefault('DeltaIntersection', 0.00001) +# kwargs.setdefault('DeltaOneStep', 0.0001) +# kwargs.setdefault('MaximumEpsilonStep', 0.001) +# kwargs.setdefault('MinimumEpsilonStep', 0.00001) +# return BasicDetectorFieldManagerToolCfg(ConfigFlags, name, **kwargs) + +# def InDetFieldManagerToolCfg(ConfigFlags, name='InDetFieldManager', **kwargs): +# kwargs.setdefault("LogicalVolumes", ['IDET::IDET']) +# #kwargs.setdefault('DeltaChord', 0.00001) +# kwargs.setdefault('DeltaIntersection', 0.00001) +# kwargs.setdefault('DeltaOneStep', 0.0001) +# kwargs.setdefault('MaximumEpsilonStep', 0.001) +# kwargs.setdefault('MinimumEpsilonStep', 0.00001) +# return BasicDetectorFieldManagerToolCfg(ConfigFlags, name, **kwargs) + +# def MuonsOnlyInCaloFieldManagerToolCfg(ConfigFlags, name='MuonsOnlyInCaloFieldManager', **kwargs): +# kwargs.setdefault("LogicalVolumes", ['CALO::CALO']) +# #kwargs.setdefault('DeltaChord', 0.00000002) +# kwargs.setdefault('DeltaIntersection', 0.00000002) +# kwargs.setdefault('DeltaOneStep', 0.000001) +# kwargs.setdefault('MaximumEpsilonStep', 0.0000009) +# kwargs.setdefault('MinimumEpsilonStep', 0.000001) +# kwargs.setdefault('MuonOnlyField', True) +# return BasicDetectorFieldManagerToolCfg(ConfigFlags, name, **kwargs) + +# def MuonFieldManagerToolCfg(ConfigFlags, name='MuonFieldManager', **kwargs): +# kwargs.setdefault("LogicalVolumes", ['MUONQ02::MUONQ02']) +# #kwargs.setdefault('DeltaChord', 0.00000002) +# kwargs.setdefault('DeltaIntersection', 0.00000002) +# kwargs.setdefault('DeltaOneStep', 0.000001) +# kwargs.setdefault('MaximumEpsilonStep', 0.0000009) +# kwargs.setdefault('MinimumEpsilonStep', 0.000001) +# return BasicDetectorFieldManagerToolCfg(ConfigFlags, name, **kwargs) + +#not used in G4AtlasServicesConfigNew? +# def BasicFwdFieldManagerToolCfg(ConfigFlags, name='FwdFieldManagerTool', **kwargs): +# result=ComponentAccumulator() + +# #kwargs.setdefault('DeltaChord', 0.00000002) +# kwargs.setdefault('DeltaIntersection', 1e-9) +# kwargs.setdefault('DeltaOneStep', 1e-8) +# kwargs.setdefault('MaximumEpsilonStep', 1e-8) +# kwargs.setdefault('MinimumEpsilonStep', 1e-9) + +# accForwardField = ForwardFieldSvcCfg(ConfigFlags) +# #kwargs.setdefault("FieldSvc", ForwardFieldSvcCfg(ConfigFlags)) +# kwargs.setdefault("FieldSvc", accForwardField.getService("ForwardField")) #accessing the right service? +# result.merge(accForwardField) + +# #from G4AtlasApps.SimFlags import simFlags +# #if simFlags.FwdStepLimitation.statusOn: +# # kwargs.setdefault("MaximumStep", simFlags.FwdStepLimitation()) +# if False: +# kwargs.setdefault("MaximumStep", 1000.) +# acc = BasicDetectorFieldManagerToolCfg(ConfigFlags, name, **kwargs) +# tool = result.popToolsAndMerge(acc) +# result.setPrivateTools(tool) +# return result + +# def Q1FwdFieldManagerToolCfg(ConfigFlags, name='Q1FwdFieldManager', **kwargs): +# result = Q1FwdG4FieldSvcCfg(ConfigFlags) +# kwargs.setdefault("FieldSvc", result.getService('Q1FwdG4FieldSvc')) +# kwargs.setdefault("LogicalVolumes", ['FwdRegion::LQXAA.1R1MagQ1']) +# acc=BasicFwdFieldManagerToolCfg(ConfigFlags, name, **kwargs) +# tool = result.popToolsAndMerge(acc) +# result.setPrivateTools(tool) +# return result +# def Q2FwdFieldManagerToolCfg(ConfigFlags, name='Q2FwdFieldManager', **kwargs): +# result=Q2FwdG4FieldSvcCfg(ConfigFlags) +# kwargs.setdefault("FieldSvc", result.getService('Q2FwdG4FieldSvc')) +# kwargs.setdefault("LogicalVolumes", ['FwdRegion::LQXBA.2R1MagQ2a', 'FwdRegion::LQXBA.2R1MagQ2b']) +# acc=BasicFwdFieldManagerToolCfg(ConfigFlags, name, **kwargs) +# tool = result.popToolsAndMerge(acc) +# result.setPrivateTools(tool) +# return result +# def Q3FwdFieldManagerToolCfg(ConfigFlags, name='Q3FwdFieldManager', **kwargs): +# result=Q3FwdG4FieldSvcCfg(ConfigFlags) +# kwargs.setdefault("FieldSvc", result.getService('Q3FwdG4FieldSvc')) +# kwargs.setdefault("LogicalVolumes", ['FwdRegion::LQXAG.3R1MagQ3']) +# acc=BasicFwdFieldManagerToolCfg(ConfigFlags, name, **kwargs) +# tool = result.popToolsAndMerge(acc) +# result.setPrivateTools(tool) +# return result +# def D1FwdFieldManagerToolCfg(ConfigFlags, name='D1FwdFieldManager', **kwargs): +# result=D1FwdG4FieldSvcCfg(ConfigFlags) +# kwargs.setdefault("FieldSvc", result.getService('D1FwdG4FieldSvc')) +# kwargs.setdefault("LogicalVolumes", ['FwdRegion::MBXW.A4R1MagD1a', 'FwdRegion::MBXW.B4R1MagD1b', +# 'FwdRegion::MBXW.C4R1MagD1c', 'FwdRegion::MBXW.D4R1MagD1d', +# 'FwdRegion::MBXW.E4R1MagD1e', 'FwdRegion::MBXW.F4R1MagD1f']) +# acc=BasicFwdFieldManagerToolCfg(ConfigFlags, name, **kwargs) +# tool = result.popToolsAndMerge(acc) +# result.setPrivateTools(tool) +# return result +# def D2FwdFieldManagerToolCfg(ConfigFlags, name='D2FwdFieldManager', **kwargs): +# result=D2FwdG4FieldSvcCfg(ConfigFlags) +# kwargs.setdefault("FieldSvc", result.getService('D2FwdG4FieldSvc')) +# kwargs.setdefault("LogicalVolumes", ['FwdRegion::LBRCD.4R1MagD2']) +# acc=BasicFwdFieldManagerToolCfg(ConfigFlags, name, **kwargs) +# tool = result.popToolsAndMerge(acc) +# result.setPrivateTools(tool) +# return result +# def Q4FwdFieldManagerToolCfg(ConfigFlags, name='Q4FwdFieldManager', **kwargs): +# result=Q4FwdG4FieldSvcCfg(ConfigFlags) +# kwargs.setdefault("FieldSvc", result.getService('Q4FwdG4FieldSvc')) +# kwargs.setdefault("LogicalVolumes", ['FwdRegion::LQYCH.4R1MagQ4']) +# acc=BasicFwdFieldManagerToolCfg(ConfigFlags, name, **kwargs) +# tool = result.popToolsAndMerge(acc) +# result.setPrivateTools(tool) +# return result +# def Q5FwdFieldManagerToolCfg(ConfigFlags, name='Q5FwdFieldManager', **kwargs): +# result=Q5FwdG4FieldSvcCfg(ConfigFlags) +# kwargs.setdefault("FieldSvc", result.getService('Q5FwdG4FieldSvc')) +# kwargs.setdefault("LogicalVolumes", ['FwdRegion::LQNDC.5R1MagQ5']) +# acc=BasicFwdFieldManagerToolCfg(ConfigFlags, name, **kwargs) +# tool = result.popToolsAndMerge(acc) +# result.setPrivateTools(tool) +# return result +# def Q6FwdFieldManagerToolCfg(ConfigFlags, name='Q6FwdFieldManager', **kwargs): +# result=Q6FwdG4FieldSvcCfg(ConfigFlags) +# kwargs.setdefault("FieldSvc", result.getService('Q6FwdG4FieldSvc')) +# kwargs.setdefault("LogicalVolumes", ['FwdRegion::LQNDD.6R1MagQ6']) +# acc=BasicFwdFieldManagerToolCfg(ConfigFlags, name, **kwargs) +# tool = result.popToolsAndMerge(acc) +# result.setPrivateTools(tool) +# return result +# def Q7FwdFieldManagerToolCfg(ConfigFlags, name='Q7FwdFieldManager', **kwargs): +# result=Q7FwdG4FieldSvcCfg(ConfigFlags) +# kwargs.setdefault("FieldSvc", result.getService('Q7FwdG4FieldSvc')) +# kwargs.setdefault("LogicalVolumes", ['FwdRegion::LQNFD.7R1MagQ7a', 'FwdRegion::LQNFD.7R1MagQ7b']) +# acc=BasicFwdFieldManagerToolCfg(ConfigFlags, name, **kwargs) +# tool = result.popToolsAndMerge(acc) +# result.setPrivateTools(tool) +# return result +# def Q1HKickFwdFieldManagerToolCfg(ConfigFlags, name='Q1HKickFwdFieldManager', **kwargs): +# result=Q1HKickFwdG4FieldSvcCfg(ConfigFlags) +# kwargs.setdefault("FieldSvc", result.getService('Q1HKickFwdG4FieldSvc')) +# kwargs.setdefault("LogicalVolumes", ['FwdRegion::LQXAA.1R1MagQ1HKick']) +# acc=BasicFwdFieldManagerToolCfg(ConfigFlags, name, **kwargs) +# tool = result.popToolsAndMerge(acc) +# result.setPrivateTools(tool) +# return result +# def Q1VKickFwdFieldManagerToolCfg(ConfigFlags, name='Q1VKickFwdFieldManager', **kwargs): +# result=Q1VKickFwdG4FieldSvcCfg(ConfigFlags) +# kwargs.setdefault("FieldSvc", result.getService('Q1VKickFwdG4FieldSvc')) +# kwargs.setdefault("LogicalVolumes", ['FwdRegion::LQXAA.1R1MagQ1VKick']) +# acc=BasicFwdFieldManagerToolCfg(ConfigFlags, name, **kwargs) +# tool = result.popToolsAndMerge(acc) +# result.setPrivateTools(tool) +# return result +# def Q2HKickFwdFieldManagerToolCfg(ConfigFlags, name='Q2HKickFwdFieldManager', **kwargs): +# result=Q2HKickFwdG4FieldSvcCfg(ConfigFlags) +# kwargs.setdefault("FieldSvc", result.getService('Q2HKickFwdG4FieldSvc')) +# kwargs.setdefault("LogicalVolumes", ['FwdRegion::LQXBA.2R1MagQ2HKick']) +# acc=BasicFwdFieldManagerToolCfg(ConfigFlags, name, **kwargs) +# tool = result.popToolsAndMerge(acc) +# result.setPrivateTools(tool) +# return result +# def Q2VKickFwdFieldManagerToolCfg(ConfigFlags, name='Q2VKickFwdFieldManager', **kwargs): +# result=Q2VKickFwdG4FieldSvcCfg(ConfigFlags) +# kwargs.setdefault("FieldSvc", result.getService('Q2VKickFwdG4FieldSvc')) +# kwargs.setdefault("LogicalVolumes", ['FwdRegion::LQXBA.2R1MagQ2VKick']) +# acc=BasicFwdFieldManagerToolCfg(ConfigFlags, name, **kwargs) +# tool = result.popToolsAndMerge(acc) +# result.setPrivateTools(tool) +# return result +# def Q3HKickFwdFieldManagerToolCfg(ConfigFlags, name='Q3HKickFwdFieldManager', **kwargs): +# result=Q3HKickFwdG4FieldSvcCfg(ConfigFlags) +# kwargs.setdefault("FieldSvc", result.getService('Q3HKickFwdG4FieldSvc')) +# kwargs.setdefault("LogicalVolumes", ['FwdRegion::LQXAG.3R1MagQ3HKick']) +# acc=BasicFwdFieldManagerToolCfg(ConfigFlags, name, **kwargs) +# tool = result.popToolsAndMerge(acc) +# result.setPrivateTools(tool) +# return result +# def Q3VKickFwdFieldManagerToolCfg(ConfigFlags, name='Q3VKickFwdFieldManager', **kwargs): +# result=Q3VKickFwdG4FieldSvcCfg(ConfigFlags) +# kwargs.setdefault("FieldSvc", result.getService('Q3VKickFwdG4FieldSvc')) +# kwargs.setdefault("LogicalVolumes", ['FwdRegion::LQXAG.3R1MagQ3VKick']) +# acc=BasicFwdFieldManagerToolCfg(ConfigFlags, name, **kwargs) +# tool = result.popToolsAndMerge(acc) +# result.setPrivateTools(tool) +# return result +# def Q4VKickAFwdFieldManagerToolCfg(ConfigFlags, name='Q4VKickAFwdFieldManager', **kwargs): +# result=Q4VKickAFwdG4FieldSvcCfg(ConfigFlags) +# kwargs.setdefault("FieldSvc", result.getService('Q4VKickAFwdG4FieldSvc')) +# kwargs.setdefault("LogicalVolumes", ['FwdRegion::LQYCH.4R1MagQ4VKickA']) +# acc=BasicFwdFieldManagerToolCfg(ConfigFlags, name, **kwargs) +# tool = result.popToolsAndMerge(acc) +# result.setPrivateTools(tool) +# return result +# def Q4HKickFwdFieldManagerToolCfg(ConfigFlags, name='Q4HKickFwdFieldManager', **kwargs): +# result=Q4HKickFwdG4FieldSvcCfg(ConfigFlags) +# kwargs.setdefault("FieldSvc", result.getService('Q4HKickFwdG4FieldSvc')) +# kwargs.setdefault("LogicalVolumes", ['FwdRegion::LQYCH.4R1MagQ4HKick']) +# acc=BasicFwdFieldManagerToolCfg(ConfigFlags, name, **kwargs) +# tool = result.popToolsAndMerge(acc) +# result.setPrivateTools(tool) +# return result +# def Q4VKickBFwdFieldManagerToolCfg(ConfigFlags, name='Q4VKickBFwdFieldManager', **kwargs): +# result=Q4VKickBFwdG4FieldSvcCfg(ConfigFlags) +# kwargs.setdefault("FieldSvc", result.getService('Q4VKickBFwdG4FieldSvc')) +# kwargs.setdefault("LogicalVolumes", ['FwdRegion::LQYCH.4R1MagQ4VKickB']) +# acc=BasicFwdFieldManagerToolCfg(ConfigFlags, name, **kwargs) +# tool = result.popToolsAndMerge(acc) +# result.setPrivateTools(tool) +# return result +# def Q5HKickFwdFieldManagerToolCfg(ConfigFlags, name='Q5HKickFwdFieldManager', **kwargs): +# result=Q5HKickFwdG4FieldSvcCfg(ConfigFlags) +# kwargs.setdefault("FieldSvc", result.getService('Q5HKickFwdG4FieldSvc')) +# kwargs.setdefault("LogicalVolumes", ['FwdRegion::LQNDC.5R1MagQ5HKick']) +# acc=BasicFwdFieldManagerToolCfg(ConfigFlags, name, **kwargs) +# tool = result.popToolsAndMerge(acc) +# result.setPrivateTools(tool) +# return result +# def Q6VKickFwdFieldManagerToolCfg(ConfigFlags, name='Q6VKickFwdFieldManager', **kwargs): +# result=Q6VKickFwdG4FieldSvcCfg(ConfigFlags) +# kwargs.setdefault("FieldSvc", result.getService('Q6VKickFwdG4FieldSvc')) +# kwargs.setdefault("LogicalVolumes", ['FwdRegion::LQNDD.6R1MagQ6VKick']) +# acc=BasicFwdFieldManagerToolCfg(ConfigFlags, name, **kwargs) +# tool = result.popToolsAndMerge(acc) +# result.setPrivateTools(tool) +# return result + +# def FwdRegionFieldManagerToolCfg(ConfigFlags, name='FwdRegionFieldManager', **kwargs): +# kwargs.setdefault("LogicalVolumes", ['FwdRegion::ForwardRegionGeoModel']) +# #from G4AtlasApps.SimFlags import simFlags +# #if simFlags.FwdStepLimitation.statusOn: +# # kwargs.setdefault("MaximumStep", simFlags.FwdStepLimitation()) +# if False: +# kwargs.setdefault("MaximumStep", 1000.) +# return BasicDetectorFieldManagerToolCfg(ConfigFlags, name, **kwargs) diff --git a/Simulation/G4Faser/G4FaserTools/python/G4GeometryToolConfig.py b/Simulation/G4Faser/G4FaserTools/python/G4GeometryToolConfig.py new file mode 100644 index 000000000..b48c9ebe7 --- /dev/null +++ b/Simulation/G4Faser/G4FaserTools/python/G4GeometryToolConfig.py @@ -0,0 +1,64 @@ +# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator + +from Geo2G4.Geo2G4Conf import GeoDetectorTool + +from G4AtlasTools.G4AtlasToolsConf import CylindricalEnvelope, PolyconicalEnvelope, MaterialDescriptionTool,G4AtlasDetectorConstructionTool, BoxEnvelope #(check) + +from AthenaCommon.SystemOfUnits import mm, cm, m +from VetoGeoModel.VetoGeoModelConfig import VetoGeometryCfg + +#ToDo - finish migrating this (dnoel) +#Todo - just return component accumulator +#to still migrate: getCavernWorld, getCavernInfraGeoDetectorTool +#from ForwardRegionProperties.ForwardRegionPropertiesToolConfig import ForwardRegionPropertiesCfg + +def VetoGeoDetectorToolCfg(ConfigFlags, name='Veto', **kwargs): + #set up geometry + result=VetoGeometryCfg(ConfigFlags) + kwargs.setdefault("DetectorName", "Veto") + return result, GeoDetectorTool(name, **kwargs) + +def generateSubDetectorList(ConfigFlags): + result = ComponentAccumulator() + SubDetectorList=[] + + if ConfigFlags.Detector.SimulateVeto: + accVeto, toolVeto = VetoGeoDetectorToolCfg(ConfigFlags) + SubDetectorList += [ toolVeto ] + result.merge(accVeto) + + return result, SubDetectorList + +def FASEREnvelopeCfg(ConfigFlags, name="Faser", **kwargs): + result = ComponentAccumulator() + + kwargs.setdefault("DetectorName", "Faser") + accSubDetectors, SubDetectorList = generateSubDetectorList(ConfigFlags) + result.merge(accSubDetectors) + + kwargs.setdefault("OffsetX", 0.0 * mm) + kwargs.setdefault("OffsetY", 0.0 * mm) + kwargs.setdefault("OffsetZ", 0.0 * mm) + # kwargs.setdefault("OffsetX", 0.0 * mm) + # kwargs.setdefault("OffsetY", 0.0 * mm) + # kwargs.setdefault("OffsetZ", -1650.0 * mm) + + # kwargs.setdefault("dX", 16.0 * mm) + # kwargs.setdefault("dY", 16.0 * mm) + # kwargs.setdefault("dZ", 33.0 * mm) + kwargs.setdefault("dX", 600.0 * mm) + kwargs.setdefault("dY", 600.0 * mm) + kwargs.setdefault("dZ", 2500.0 * mm) + + kwargs.setdefault("SubDetectors", SubDetectorList) + + return result, BoxEnvelope(name, **kwargs) + +def G4AtlasDetectorConstructionToolCfg(ConfigFlags, name="G4FaserDetectorConstructionTool", **kwargs): + return G4AtlasDetectorConstructionTool(name, **kwargs) + +def MaterialDescriptionToolCfg(ConfigFlags, name="MaterialDescriptionTool", **kwargs): + ## kwargs.setdefault("SomeProperty", aValue) + return MaterialDescriptionTool(name, **kwargs) + diff --git a/Simulation/G4Faser/G4FaserTools/python/G4PhysicsRegionConfigNew.py b/Simulation/G4Faser/G4FaserTools/python/G4PhysicsRegionConfigNew.py new file mode 100644 index 000000000..3dab4476d --- /dev/null +++ b/Simulation/G4Faser/G4FaserTools/python/G4PhysicsRegionConfigNew.py @@ -0,0 +1,302 @@ +# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +from G4AtlasTools.G4AtlasToolsConf import RegionCreator + +# Beampipe Regions +# def BeampipeFwdCutPhysicsRegionToolCfg(ConfigFlags, name='BeampipeFwdCutPhysicsRegionTool', **kwargs): +# kwargs.setdefault("RegionName", 'BeampipeFwdCut') +# volumeList = ['BeamPipe::SectionF47', 'BeamPipe::SectionF48', 'BeamPipe::SectionF61'] +# kwargs.setdefault("VolumeList", volumeList) +# from G4AtlasApps.SimFlags import simFlags + +# #if simFlags.BeamPipeSimMode() == "FastSim": +# if True: +# kwargs.setdefault("ElectronCut", 10.) +# kwargs.setdefault("PositronCut", 10.) +# kwargs.setdefault("GammaCut", 10.) +# print('Adding fast sim model to the beampipe!') +# else: +# assert simFlags.BeamPipeCut.statusOn +# if simFlags.BeamPipeCut() < 1: +# msg = "Setting the forward beam pipe range cuts to %e mm " % simFlags.BeamPipeCut() +# msg += "-- cut is < 1 mm, I hope you know what you're doing!" +# print(msg) +# if simFlags.BeamPipeSimMode() == "EGammaRangeCuts": +# kwargs.setdefault("ElectronCut", simFlags.BeamPipeCut()) +# kwargs.setdefault("PositronCut", simFlags.BeamPipeCut()) +# kwargs.setdefault("GammaCut", simFlags.BeamPipeCut()) +# elif simFlags.BeamPipeSimMode() == "EGammaPRangeCuts": +# kwargs.setdefault("ElectronCut", simFlags.BeamPipeCut()) +# kwargs.setdefault("PositronCut", simFlags.BeamPipeCut()) +# kwargs.setdefault("GammaCut", simFlags.BeamPipeCut()) +# kwargs.setdefault("ProtonCut", simFlags.BeamPipeCut()) +# return RegionCreator(name, **kwargs) + +# def FWDBeamLinePhysicsRegionToolCfg(ConfigFlags, name='FWDBeamLinePhysicsRegionTool', **kwargs): +# kwargs.setdefault("RegionName", 'FWDBeamLine') +# volumeList = ['BeamPipe::SectionF46'] +# kwargs.setdefault("VolumeList", volumeList) +# return RegionCreator(name, **kwargs) + +# # Forward Regions +# def FwdRegionPhysicsRegionToolCfg(ConfigFlags, name='FwdRegionPhysicsRegionTool', **kwargs): +# kwargs.setdefault("RegionName", 'FwdRegion') +# volumeList = ['FwdRegion::ForwardRegionGeoModel'] +# kwargs.setdefault("VolumeList", volumeList) +# kwargs.setdefault("ElectronCut", 200.) +# kwargs.setdefault("PositronCut", 200.) +# kwargs.setdefault("GammaCut", 200.) +# return RegionCreator(name, **kwargs) + +# # Inner Detector Regions +# def PixelPhysicsRegionToolCfg(ConfigFlags, name='PixelPhysicsRegionTool', **kwargs): +# kwargs.setdefault("RegionName", 'Pixel') +# volumeList = ['Pixel::siLog', 'Pixel::siBLayLog'] +# from AtlasGeoModel.CommonGMJobProperties import CommonGeometryFlags as commonGeoFlags +# from AtlasGeoModel.InDetGMJobProperties import InDetGeometryFlags as geoFlags +# if (ConfigFlags.GeoModel.Run in ["RUN2", "RUN3"]) or (commonGeoFlags.Run()=="UNDEFINED" and geoFlags.isIBL()): +# volumeList += ['Pixel::dbmDiamondLog'] +# kwargs.setdefault("VolumeList", volumeList) +# kwargs.setdefault("ElectronCut", 0.05) +# kwargs.setdefault("PositronCut", 0.05) +# kwargs.setdefault("GammaCut", 0.05) +# return RegionCreator(name, **kwargs) + +# Values identical to ATLAS SCT +def ScintillatorPhysicsRegionToolCfg(ConfigFlags, name='ScintillatorPhysicsRegionTool', **kwargs): + kwargs.setdefault("RegionName", 'Scintillator') + volumeList = ['Veto::Plate' , 'Trigger::Plate', 'Preshower::Plate'] + kwargs.setdefault("VolumeList", volumeList) + kwargs.setdefault("ElectronCut", 0.05) + kwargs.setdefault("PositronCut", 0.05) + kwargs.setdefault("GammaCut", 0.05) + return RegionCreator(name, **kwargs) + + +# def SCTPhysicsRegionToolCfg(ConfigFlags, name='SCTPhysicsRegionTool', **kwargs): +# kwargs.setdefault("RegionName", 'SCT') +# volumeList = ['SCT::BRLSensor', 'SCT::BRLSensorSS', 'SCT::BRLSensorMS', +# 'SCT::ECSensor0', 'SCT::ECSensor1', 'SCT::ECSensor2', +# 'SCT::ECSensor3', 'SCT::ECSensor4', 'SCT::ECSensor5'] +# kwargs.setdefault("VolumeList", volumeList) +# kwargs.setdefault("ElectronCut", 0.05) +# kwargs.setdefault("PositronCut", 0.05) +# kwargs.setdefault("GammaCut", 0.05) +# return RegionCreator(name, **kwargs) + +# def TRTPhysicsRegionToolCfg(ConfigFlags, name='TRTPhysicsRegionTool', **kwargs): +# #rangeCut = simFlags.TRTRangeCut._Value() +# rangeCut = 30.0 +# kwargs.setdefault("RegionName", 'TRT') +# volumeList = ['TRT::Gas', 'TRT::GasMA'] +# kwargs.setdefault("VolumeList", volumeList) +# kwargs.setdefault("ElectronCut", rangeCut) +# kwargs.setdefault("PositronCut", rangeCut) +# # The photon range cut is meant to stay small +# kwargs.setdefault("GammaCut", 0.05) +# return RegionCreator(name, **kwargs) + +# def TRT_ArPhysicsRegionToolCfg(ConfigFlags, name='TRT_ArPhysicsRegionTool', **kwargs): +# kwargs.setdefault("RegionName", 'TRT_Ar') +# volumeList = ['TRT::Gas_Ar', 'TRT::GasMA_Ar'] +# kwargs.setdefault("VolumeList", volumeList) +# kwargs.setdefault("ElectronCut", 30.0) +# kwargs.setdefault("PositronCut", 30.0) +# kwargs.setdefault("GammaCut", 0.05) +# return RegionCreator(name, **kwargs) + +# def TRT_KrPhysicsRegionToolCfg(ConfigFlags, name='TRT_KrPhysicsRegionTool', **kwargs): +# kwargs.setdefault("RegionName", 'TRT_Kr') +# volumeList = ['TRT::Gas_Kr', 'TRT::GasMA_Kr'] +# kwargs.setdefault("VolumeList", volumeList) +# kwargs.setdefault("ElectronCut", 15.0) +# kwargs.setdefault("PositronCut", 15.0) +# kwargs.setdefault("GammaCut", 0.05) +# return RegionCreator(name, **kwargs) + +# # Calo Regions +# def EMBPhysicsRegionToolCfg(ConfigFlags, name='EMBPhysicsRegionTool', **kwargs): +# kwargs.setdefault("RegionName", 'EMB') +# volumeList = ['LArMgr::LAr::EMB::STAC'] +# kwargs.setdefault("VolumeList", volumeList) +# rangeEMB = 0.03 +# from G4AtlasApps.SimFlags import simFlags +# if '_EMV' not in simFlags.PhysicsList() and '_EMX' not in simFlags.PhysicsList(): +# rangeEMB = 0.1 +# kwargs.setdefault("ElectronCut", rangeEMB) +# kwargs.setdefault("PositronCut", rangeEMB) +# kwargs.setdefault("GammaCut", rangeEMB) +# return RegionCreator(name, **kwargs) + +# def EMECPhysicsRegionToolCfg(ConfigFlags, name='EMECPhysicsRegionTool', **kwargs): +# kwargs.setdefault("RegionName", 'EMEC') +# volumeList = ['LArMgr::LAr::EMEC::Mother'] +# kwargs.setdefault("VolumeList", volumeList) +# rangeEMEC = 0.03 +# from G4AtlasApps.SimFlags import simFlags +# if '_EMV' not in simFlags.PhysicsList() and '_EMX' not in simFlags.PhysicsList(): +# rangeEMEC = 0.1 +# kwargs.setdefault("ElectronCut", rangeEMEC) +# kwargs.setdefault("PositronCut", rangeEMEC) +# kwargs.setdefault("GammaCut", rangeEMEC) +# return RegionCreator(name, **kwargs) + +# def HECPhysicsRegionToolCfg(ConfigFlags, name='HECPhysicsRegionTool', **kwargs): +# kwargs.setdefault("RegionName", 'HEC') +# volumeList = ['LArMgr::LAr::HEC::LiquidArgon'] +# kwargs.setdefault("VolumeList", volumeList) +# rangeHEC = 0.03 +# from G4AtlasApps.SimFlags import simFlags +# if '_EMV' not in simFlags.PhysicsList() and '_EMX' not in simFlags.PhysicsList(): +# rangeHEC = 1.0 +# kwargs.setdefault("ElectronCut", rangeHEC) +# kwargs.setdefault("PositronCut", rangeHEC) +# kwargs.setdefault("GammaCut", rangeHEC) +# return RegionCreator(name, **kwargs) + +# def FCALPhysicsRegionToolCfg(ConfigFlags, name='FCALPhysicsRegionTool', **kwargs): +# kwargs.setdefault("RegionName", 'FCAL') +# volumeList = ['LArMgr::LAr::FCAL::LiquidArgonC'] +# kwargs.setdefault("VolumeList", volumeList) +# kwargs.setdefault("ElectronCut", 0.03) +# kwargs.setdefault("PositronCut", 0.03) +# kwargs.setdefault("GammaCut", 0.03) +# return RegionCreator(name, **kwargs) + +# def EMECParaPhysicsRegionToolCfg(ConfigFlags, name='EMECParaPhysicsRegionTool', **kwargs): +# kwargs.setdefault("RegionName", 'EMECPara') +# volumeList = ['LArMgr::LAr::EMEC::Pos::InnerWheel', 'LArMgr::LAr::EMEC::Pos::OuterWheel', +# 'LArMgr::LAr::EMEC::Neg::InnerWheel', 'LArMgr::LAr::EMEC::Neg::OuterWheel'] +# kwargs.setdefault("VolumeList", volumeList) +# rangeEMEC = 0.03 +# from G4AtlasApps.SimFlags import simFlags +# if '_EMV' not in simFlags.PhysicsList() and '_EMX' not in simFlags.PhysicsList(): +# rangeEMEC = 0.1 +# kwargs.setdefault("ElectronCut", rangeEMEC) +# kwargs.setdefault("PositronCut", rangeEMEC) +# kwargs.setdefault("GammaCut", rangeEMEC) +# return RegionCreator(name, **kwargs) + +# def FCALParaPhysicsRegionToolCfg(ConfigFlags, name='FCALParaPhysicsRegionTool', **kwargs): +# kwargs.setdefault("RegionName", 'FCALPara') +# volumeList = ['LArMgr::LAr::FCAL::Module1::Absorber'] +# kwargs.setdefault("VolumeList", volumeList) +# kwargs.setdefault("ElectronCut", 0.03) +# kwargs.setdefault("PositronCut", 0.03) +# kwargs.setdefault("GammaCut", 0.03) +# return RegionCreator(name, **kwargs) + +# def FCAL2ParaPhysicsRegionToolCfg(ConfigFlags, name='FCAL2ParaPhysicsRegionTool', **kwargs): +# kwargs.setdefault("RegionName", 'FCAL2Para') +# volumeList = ['LArMgr::LAr::FCAL::Module2::Absorber', 'LArMgr::LAr::FCAL::Module3::Absorber'] +# kwargs.setdefault("VolumeList", volumeList) +# kwargs.setdefault("ElectronCut", 0.03) +# kwargs.setdefault("PositronCut", 0.03) +# kwargs.setdefault("GammaCut", 0.03) +# return RegionCreator(name, **kwargs) + +# def PreSampLArPhysicsRegionToolCfg(ConfigFlags, name='PreSampLArPhysicsRegionTool', **kwargs): +# kwargs.setdefault("RegionName", 'PreSampLAr') +# volumeList = ['LArMgr::LAr::Endcap::Presampler::LiquidArgon'] +# kwargs.setdefault("VolumeList", volumeList) +# return RegionCreator(name, **kwargs) + +# def DeadMaterialPhysicsRegionToolCfg(ConfigFlags, name='DeadMaterialPhysicsRegionTool', **kwargs): +# kwargs.setdefault("RegionName", 'DeadMaterial') +# volumeList = [] +# sectionList = range(16,49) # does not include 49 +# sectionList += [ 51, 52, 53, 54 ] +# for section in sectionList: +# volumeList += ['BeamPipe::SectionF'+str(section)] +# volumeList += ['LArMgr::LAr::Endcap::Cryostat::Cylinder', +# 'LArMgr::LAr::Endcap::Cryostat::Cylinder::Mixed', +# 'LArMgr::LAr::Endcap::Cryostat::Cone::Mixed', +# 'LArMgr::LAr::Endcap::Cryostat::Cone', +# 'DiskShieldingPlugs', 'ToroidShieldingInnerPlugs', +# 'ForwardShieldingMainCylinder'] +# kwargs.setdefault("VolumeList", volumeList) +# kwargs.setdefault("ElectronCut", 1.0) +# kwargs.setdefault("PositronCut", 1.0) +# kwargs.setdefault("GammaCut", 1.0) +# return RegionCreator(name, **kwargs) + +# #Muon Regions +# def DriftWallPhysicsRegionToolCfg(ConfigFlags, name='DriftWallPhysicsRegionTool', **kwargs): +# kwargs.setdefault("RegionName", 'DriftWall') +# volumeList = ['Muon::MDTDriftWall'] +# kwargs.setdefault("VolumeList", volumeList) +# kwargs.setdefault("ElectronCut", 0.05) +# kwargs.setdefault("PositronCut", 0.05) +# return RegionCreator(name, **kwargs) + +# def DriftWall1PhysicsRegionToolCfg(ConfigFlags, name='DriftWall1PhysicsRegionTool', **kwargs): +# kwargs.setdefault("RegionName", 'DriftWall1') +# volumeList = ['Muon::Endplug'] +# kwargs.setdefault("VolumeList", volumeList) +# kwargs.setdefault("ElectronCut", 1.0) +# kwargs.setdefault("PositronCut", 1.0) +# return RegionCreator(name, **kwargs) + +# def DriftWall2PhysicsRegionToolCfg(ConfigFlags, name='DriftWall2PhysicsRegionTool', **kwargs): +# kwargs.setdefault("RegionName", 'DriftWall2') +# volumeList = ['Muon::SensitiveGas'] +# kwargs.setdefault("VolumeList", volumeList) +# kwargs.setdefault("ElectronCut", 1.0) +# kwargs.setdefault("PositronCut", 1.0) +# return RegionCreator(name, **kwargs) + +# def MuonSystemFastPhysicsRegionToolCfg(ConfigFlags, name='MuonSystemFastPhysicsRegionTool', **kwargs): +# kwargs.setdefault("RegionName", 'MuonSystemFastRegion') +# volumeList = [] +# if ConfigFlags.Sim.CavernBG == 'World': +# volumeList += ['BeamPipe::BeamPipe', 'IDET::IDET'] +# volumeList = ['Muon::MuonSys'] +# kwargs.setdefault("VolumeList", volumeList) +# kwargs.setdefault("ElectronCut", 1.0) +# kwargs.setdefault("PositronCut", 1.0) +# return RegionCreator(name, **kwargs) + +# def MuonPhysicsRegionToolCfg(ConfigFlags, name="MuonPhysicsRegionTool", **kwargs): +# kwargs.setdefault("RegionName", 'MuonSys') +# volumeList = ['Muon::MuonSys'] +# kwargs.setdefault("VolumeList", volumeList) +# kwargs.setdefault("ElectronCut", 0.1) +# kwargs.setdefault("PositronCut", 0.1) +# kwargs.setdefault("GammaCut", 0.1) +# return RegionCreator(name, **kwargs) + +# # Cavern Regions +# def SX1PhysicsRegionToolCfg(ConfigFlags, name='SX1PhysicsRegionTool', **kwargs): +# kwargs.setdefault("RegionName", 'SX1') +# volumeList = ['CavernInfra::SX1Air'] +# kwargs.setdefault("VolumeList", volumeList) +# kwargs.setdefault("ElectronCut", 2000.) +# kwargs.setdefault("PositronCut", 2000.) +# kwargs.setdefault("GammaCut", 2000.) +# return RegionCreator(name, **kwargs) + +# def BedrockPhysicsRegionToolCfg(ConfigFlags, name='BedrockPhysicsRegionTool', **kwargs): +# kwargs.setdefault("RegionName", 'BEDROCK') +# volumeList = ['CavernInfra::BEDROCK'] +# kwargs.setdefault("VolumeList", volumeList) +# kwargs.setdefault("ElectronCut", 1000000.) +# kwargs.setdefault("PositronCut", 1000000.) +# kwargs.setdefault("GammaCut", 1000000.) +# return RegionCreator(name, **kwargs) + +# def CavernShaftsConcretePhysicsRegionToolCfg(ConfigFlags, name='CavernShaftsConcretePhysicsRegionTool', **kwargs): +# kwargs.setdefault("RegionName", 'CAV_SHAFTS_CONC') +# volumeList = ['CavernInfra::CAV_SHAFTS_CONC'] +# kwargs.setdefault("VolumeList", volumeList) +# kwargs.setdefault("ElectronCut", 150.) +# kwargs.setdefault("PositronCut", 150.) +# kwargs.setdefault("GammaCut", 150.) +# return RegionCreator(name, **kwargs) + +##def getCavernShaftsAirPhysicsRegionTool(name='CavernShaftsAirPhysicsRegionTool', **kwargs): +## kwargs.setdefault("RegionName", 'CAV_SHAFTS_AIR') +## volumeList = ['CavernInfra::CAV_SHAFTS_AIR'] +## kwargs.setdefault("VolumeList", volumeList) +## kwargs.setdefault("ElectronCut", 2000.) +## kwargs.setdefault("PositronCut", 2000.) +## kwargs.setdefault("GammaCut", 2000.) +## return CfgMgr.RegionCreator(name, **kwargs) diff --git a/Simulation/G4Faser/G4FaserTools/python/__init__.py b/Simulation/G4Faser/G4FaserTools/python/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/Simulation/G4Utilities/Geo2G4/CMakeLists.txt b/Simulation/G4Utilities/Geo2G4/CMakeLists.txt new file mode 100644 index 000000000..f30e1839c --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/CMakeLists.txt @@ -0,0 +1,52 @@ +################################################################################ +# Package: Geo2G4 +################################################################################ + +# Declare the package name: +atlas_subdir( Geo2G4 ) + +# Declare the package's dependencies: +atlas_depends_on_subdirs( PUBLIC + GaudiKernel + PRIVATE + Control/AthenaBaseComps + Control/AthenaKernel + Control/StoreGate + DetectorDescription/GeoModel/GeoModelInterfaces + DetectorDescription/GeoModel/GeoSpecialShapes + DetectorDescription/GeoModel/GeoModelUtilities + DetectorDescription/GeoPrimitives + Simulation/G4Atlas/G4AtlasInterfaces + Simulation/G4Atlas/G4AtlasTools + Simulation/G4Sim/SimHelpers + Simulation/G4Utilities/GeoMaterial2G4 ) + +# External dependencies: +find_package( Boost COMPONENTS filesystem thread system ) +find_package( CLHEP ) +find_package( Geant4 ) +find_package( ROOT COMPONENTS MathCore RIO Core Tree Hist pthread ) +find_package( XercesC ) +find_package( GeoModel ) + +# Component(s) in the package: +atlas_add_library( Geo2G4Lib + src/*.cxx + PUBLIC_HEADERS Geo2G4 + INCLUDE_DIRS ${XERCESC_INCLUDE_DIRS} ${GEANT4_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} + PRIVATE_INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${GEOMODEL_INCLUDE_DIRS} + PRIVATE_DEFINITIONS ${CLHEP_DEFINITIONS} + LINK_LIBRARIES ${XERCESC_LIBRARIES} ${GEANT4_LIBRARIES} ${ROOT_LIBRARIES} GaudiKernel + PRIVATE_LINK_LIBRARIES ${Boost_LIBRARIES} ${CLHEP_LIBRARIES} ${GEOMODEL_LIBRARIES} AthenaBaseComps GeoSpecialShapes G4AtlasToolsLib SimHelpers GeoMaterial2G4 AthenaKernel GeoModelUtilities StoreGateLib SGtests ) + +atlas_add_component( Geo2G4 + src/components/*.cxx + INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${XERCESC_INCLUDE_DIRS} ${GEANT4_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${GEOMODEL_INCLUDE_DIRS} + LINK_LIBRARIES ${Boost_LIBRARIES} ${XERCESC_LIBRARIES} ${GEANT4_LIBRARIES} ${ROOT_LIBRARIES} ${CLHEP_LIBRARIES} ${GEOMODEL_LIBRARIES} AthenaKernel GeoModelUtilities GaudiKernel AthenaBaseComps StoreGateLib SGtests GeoSpecialShapes G4AtlasToolsLib SimHelpers GeoMaterial2G4 Geo2G4Lib ) + +#atlas_add_dictionary( LArWheelSolidCheckerDict +# src/LArWheelSolidDDProxy.h +# src/lcg_dict/selection.xml +# INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${XERCESC_INCLUDE_DIRS} ${GEANT4_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${GEOMODEL_INCLUDE_DIRS} +# LINK_LIBRARIES ${Boost_LIBRARIES} ${XERCESC_LIBRARIES} ${GEANT4_LIBRARIES} ${ROOT_LIBRARIES} ${CLHEP_LIBRARIES} ${GEOMODEL_LIBRARIES} AthenaKernel GeoModelUtilities GaudiKernel AthenaBaseComps StoreGateLib SGtests GeoSpecialShapes SimHelpers GeoMaterial2G4 Geo2G4Lib ) + diff --git a/Simulation/G4Utilities/Geo2G4/src/ExtParameterisedVolumeBuilder.cxx b/Simulation/G4Utilities/Geo2G4/src/ExtParameterisedVolumeBuilder.cxx new file mode 100644 index 000000000..286030c43 --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/ExtParameterisedVolumeBuilder.cxx @@ -0,0 +1,279 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ + +#include "ExtParameterisedVolumeBuilder.h" +#include "Geo2G4AssemblyVolume.h" +#include "Geo2G4LVFactory.h" +#include "Geo2G4STParameterisation.h" +#include "G4LogicalVolume.hh" + +#include "G4PVPlacement.hh" +#include "G4ReflectionFactory.hh" +#include "G4VPVParameterisation.hh" +#include "G4PVParameterised.hh" +#include "globals.hh" + +#include "SimHelpers/ServiceAccessor.h" + +#include "GeoModelKernel/GeoAccessVolAndSTAction.h" +#include "GeoModelKernel/GeoVolumeCursor.h" +#include "GeoModelKernel/GeoMaterial.h" +#include "GeoModelKernel/GeoLogVol.h" +#include "GeoModelKernel/GeoSerialTransformer.h" +#include "GeoModelInterfaces/StoredMaterialManager.h" +#include "AthenaBaseComps/AthMsgStreamMacros.h" + +#include "StoreGate/StoreGateSvc.h" +#include <iostream> + +#include "GeoPrimitives/CLHEPtoEigenConverter.h" + +ExtParameterisedVolumeBuilder::ExtParameterisedVolumeBuilder(std::string n, Geo2G4AssemblyFactory* G4AssemblyFactory): + VolumeBuilder(n), + m_getMatEther(true), + m_matEther(0), + m_matHypUr(0), + m_msg(n), + m_G4AssemblyFactory(G4AssemblyFactory) +{ +} + +G4LogicalVolume* ExtParameterisedVolumeBuilder::Build(const PVConstLink theGeoPhysVolume, OpticalVolumesMap* optical_volumes) +{ + PVConstLink theGeoPhysChild; + const GeoSerialTransformer* serialTransformerChild=0; + G4LogicalVolume* theG4LogChild; + unsigned int numChildNodes; // number of child nodes (PV and ST) + bool descend; // flag to continue geo tree navigation + bool serialExists = false; // flag for existence of ST among childs + std::string nameChild; + + if(m_getMatEther) getMatEther(); + + static Geo2G4LVFactory LVFactory; + + G4LogicalVolume* theG4LogVolume = LVFactory.Build(theGeoPhysVolume,descend); + + if(!descend) return theG4LogVolume; + + numChildNodes = theGeoPhysVolume->getNChildVolAndST(); + + // ***************************************************************** + // ** + // ** If m_ST2Param flag is set: + // ** Check if there's any serial transformer among child volumes + // ** + // ***************************************************************** + + if(m_paramOn) + for(size_t counter1=0; counter1<numChildNodes; counter1++) + { + GeoAccessVolAndSTAction actionVolAndST(counter1); + theGeoPhysVolume->exec(&actionVolAndST); + + if((serialTransformerChild=actionVolAndST.getSerialTransformer())) + { + nameChild = actionVolAndST.getName(); + serialExists = true; + break; + } + } + // *************************************************************************** + // ** Next steps: + // ** + // ** 1. If ST exists and numChildNodes==1, translate ST to G4 ST + // ** + // ** 2. If ST exists and numChildNodes !=1, print information message and + // ** translate ST to single placements as well as all other child volumes + // ** + // ** 3. There's no ST - ok, nothing special ... + // ** + // *************************************************************************** + + if(serialExists && (numChildNodes==1)) + { + theGeoPhysChild = serialTransformerChild->getVolume(); + + // Build the child + if(!(theG4LogChild = Build(theGeoPhysChild,optical_volumes))) return 0; + + if (nameChild == "ANON") nameChild=theG4LogChild->GetName(); + nameChild += "_Param"; + + Geo2G4STParameterisation* stParameterisation = new Geo2G4STParameterisation(serialTransformerChild->getFunction(), + serialTransformerChild->getNCopies()); + + G4VPhysicalVolume* pvParametrised __attribute__ ((unused)) = new G4PVParameterised(nameChild, + theG4LogChild, + theG4LogVolume, + kUndefined, + serialTransformerChild->getNCopies(), + stParameterisation); + } + else + { + if(serialExists) + { + std::string volName = theGeoPhysVolume->getLogVol()->getName(); + PrintSTInfo(volName); + } + + GeoVolumeCursor av(theGeoPhysVolume); + while (!av.atEnd()) + { + int id = 16969; + + // Get child phys volume + theGeoPhysChild = av.getVolume(); + // Get its transform + G4Transform3D theG4Position(Amg::EigenTransformToCLHEP(av.getTransform())); + + Query<int> Qint = av.getId(); + if(Qint.isValid()) id = Qint; + + if(m_matEther == theGeoPhysChild->getLogVol()->getMaterial()) + { + Geo2G4AssemblyVolume* assembly = BuildAssembly(theGeoPhysChild); + + if(Qint.isValid()) + assembly->MakeImprint(theG4LogVolume,theG4Position,id); + else + assembly->MakeImprint(theG4LogVolume,theG4Position); + } + else if(m_matHypUr == theGeoPhysChild->getLogVol()->getMaterial()) + { + Geo2G4AssemblyVolume* assembly = BuildAssembly(theGeoPhysChild); + + if(Qint.isValid()) + assembly->MakeImprint(theG4LogVolume,theG4Position,id,true); + else + assembly->MakeImprint(theG4LogVolume,theG4Position,0,true); + } + else + { + nameChild = av.getName(); + + // Build the child + if(!(theG4LogChild = Build(theGeoPhysChild,optical_volumes))) return 0; + + if (nameChild == "ANON") nameChild=theG4LogChild->GetName(); + + G4PhysicalVolumesPair pvPair = G4ReflectionFactory::Instance()->Place(theG4Position, + nameChild, + theG4LogChild, + theG4LogVolume, + false, + id); + + // if GeoModel volume is optical store it in the map + if(optical_volumes!=0) + { + const GeoOpticalPhysVol* opticalGeoPhysChild = + dynamic_cast < const GeoOpticalPhysVol* >(theGeoPhysChild.operator->()); + if(opticalGeoPhysChild) + (*optical_volumes)[opticalGeoPhysChild] = pvPair.first; + } + } + + av.next(); + } + } + + return theG4LogVolume; +} + +Geo2G4AssemblyVolume* ExtParameterisedVolumeBuilder::BuildAssembly(PVConstLink pv) +{ + PVConstLink theGeoPhysChild; + G4LogicalVolume* theG4LogChild = 0; + Geo2G4AssemblyVolume* theG4AssemblyChild = 0; + bool descend; // flag to continue geo tree navigation + + if(m_getMatEther) getMatEther(); + + Geo2G4AssemblyVolume* assemblyVolume = m_G4AssemblyFactory->Build(pv,descend); + + if(!descend) return assemblyVolume; + + // Loop over child volumes and add them to the Geo2G4AssemblyVolume + GeoVolumeCursor av(pv); + while (!av.atEnd()) + { + theGeoPhysChild = av.getVolume(); + std::string nameChild = av.getName(); + + std::string strVolume = std::string("Volume ") + nameChild + " (" + + theGeoPhysChild->getLogVol()->getName() + ")"; + + // Check if it is an assembly + if(m_matEther == theGeoPhysChild->getLogVol()->getMaterial() || + m_matHypUr == theGeoPhysChild->getLogVol()->getMaterial() ) + { + // Build the child assembly + if(!(theG4AssemblyChild = BuildAssembly(theGeoPhysChild))) return 0; + + // Get its transform + G4Transform3D theG4Position(Amg::EigenTransformToCLHEP(av.getTransform())); + + assemblyVolume->AddPlacedAssembly(theG4AssemblyChild,theG4Position); + } + else + { + Query<int> Qint = av.getId(); + + // Build the child + if(!(theG4LogChild = Build(theGeoPhysChild))) return 0; + + // Get its transform + G4Transform3D theG4Position(Amg::EigenTransformToCLHEP(av.getTransform())); + + int placedID = 0; + if(Qint.isValid()) placedID = Qint; + + std::string placedName = nameChild=="ANON" ? "" : nameChild; + + + assemblyVolume->AddPlacedVolume(theG4LogChild,theG4Position,placedID,placedName); + } + + av.next(); + } + + return assemblyVolume; +} + +void ExtParameterisedVolumeBuilder::PrintSTInfo(std::string volume) const +{ + ATH_MSG_INFO ( "**********************************************" ); + ATH_MSG_INFO ( "** " ); + ATH_MSG_INFO ( "** The Volume " << volume ); + ATH_MSG_INFO ( "** Has children of two different types" ); + ATH_MSG_INFO ( "** PeoPhysVolume and GeoSerialTransformer" ); + ATH_MSG_INFO ( "** In this case GeoSerialTransformer will be " ); + ATH_MSG_INFO ( "** translated into G4 placement but not in " ); + ATH_MSG_INFO ( "** G4Parameterisation" ); + ATH_MSG_INFO ( "** " ); + ATH_MSG_INFO ( "********************************************** " ); +} + +void ExtParameterisedVolumeBuilder::getMatEther() const +{ + StoreGateSvc* pDetStore=0; + ISvcLocator* svcLocator = Gaudi::svcLocator(); + if(svcLocator->service("DetectorStore",pDetStore).isFailure()) { + ATH_MSG_ERROR ( "ExtParameterisedVolumeBuilder: Unable to access Detector Store" ); + } + else + { + const StoredMaterialManager* theMaterialManager = nullptr; + if(pDetStore->retrieve(theMaterialManager, "MATERIALS").isFailure()) { + ATH_MSG_ERROR ( "ExtParameterisedVolumeBuilder: Unable to access Material Manager" ); + } + else { + m_matEther = theMaterialManager->getMaterial("special::Ether"); + m_matHypUr = theMaterialManager->getMaterial("special::HyperUranium"); + } + } + m_getMatEther = false; +} diff --git a/Simulation/G4Utilities/Geo2G4/src/ExtParameterisedVolumeBuilder.h b/Simulation/G4Utilities/Geo2G4/src/ExtParameterisedVolumeBuilder.h new file mode 100644 index 000000000..807fb3962 --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/ExtParameterisedVolumeBuilder.h @@ -0,0 +1,44 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef GEO2G4_ExtParameterisedVolumeBuilder_H +#define GEO2G4_ExtParameterisedVolumeBuilder_H + +#include "VolumeBuilder.h" +#include "Geo2G4AssemblyFactory.h" + +#include "AthenaKernel/MsgStreamMember.h" +#include <string> + +class Geo2G4AssemblyVolume; +class GeoMaterial; + +class ExtParameterisedVolumeBuilder: public VolumeBuilder +{ +public: + ExtParameterisedVolumeBuilder(std::string n, Geo2G4AssemblyFactory* G4AssemblyFactory); + /// + G4LogicalVolume* Build(PVConstLink pv, OpticalVolumesMap* optical_volumes = 0); + /// + Geo2G4AssemblyVolume* BuildAssembly(PVConstLink pv); + /// Log a message using the Athena controlled logging system + MsgStream& msg( MSG::Level lvl ) const { return m_msg << lvl; } + /// Check whether the logging system is active at the provided verbosity level + bool msgLvl( MSG::Level lvl ) const { return m_msg.get().level() <= lvl; } + private: + /// Prints info when some PhysVol contains both types (PV and ST) of daughters + void PrintSTInfo(std::string volume) const; + /// + void getMatEther() const; + + mutable bool m_getMatEther; + mutable const GeoMaterial* m_matEther; + mutable const GeoMaterial* m_matHypUr; + /// Private message stream member + mutable Athena::MsgStreamMember m_msg; + + Geo2G4AssemblyFactory* m_G4AssemblyFactory; +}; + +#endif diff --git a/Simulation/G4Utilities/Geo2G4/src/G4ShiftedCone.cxx b/Simulation/G4Utilities/Geo2G4/src/G4ShiftedCone.cxx new file mode 100644 index 000000000..0ade1417a --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/G4ShiftedCone.cxx @@ -0,0 +1,2267 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +// +// The G4ShiftedCone class copied from standard G4Cons and modified to: +// 1) have an arbitrary position along Z axis, +// 2) represent a twopi-cone. Sectors are not supported but the +// corresponding code kept and just commented out. +// + +// +// ******************************************************************** +// * License and Disclaimer * +// * * +// * The Geant4 software is copyright of the Copyright Holders of * +// * the Geant4 Collaboration. It is provided under the terms and * +// * conditions of the Geant4 Software License, included in the file * +// * LICENSE and available at http://cern.ch/geant4/license . These * +// * include a list of copyright holders. * +// * * +// * Neither the authors of this software system, nor their employing * +// * institutes,nor the agencies providing financial support for this * +// * work make any representation or warranty, express or implied, * +// * regarding this software system or assume any liability for its * +// * use. Please see the license in the file LICENSE and URL above * +// * for the full disclaimer and the limitation of liability. * +// * * +// * This code implementation is the result of the scientific and * +// * technical work of the GEANT4 collaboration. * +// * By using, copying, modifying or distributing the software (or * +// * any work based on the software) you agree to acknowledge its * +// * use in resulting scientific publications, and indicate your * +// * acceptance of all terms of the Geant4 Software license. * +// ******************************************************************** +// +// +// +// +// class G4ShiftedCone +// +// Implementation for G4ShiftedCone class +// +// History: +// 03.07.2019 A. Sukharev: copied from G4Cons +// -------------------------------------------------------------------- + +#include "G4ShiftedCone.h" + +#include "G4GeomTools.hh" +#include "G4VoxelLimits.hh" +#include "G4AffineTransform.hh" +#include "G4BoundingEnvelope.hh" +#include "G4GeometryTolerance.hh" + +#include "G4VPVParameterisation.hh" + +#include "meshdefs.hh" + +#include "Randomize.hh" + +#include "G4VGraphicsScene.hh" + +using namespace CLHEP; + +//////////////////////////////////////////////////////////////////////// +// +// Private enum: Not for external use - used by distanceToOut + +enum ESide {kNull,kRMin,kRMax,kSPhi,kEPhi,kPZ,kMZ}; + +// used by normal + +enum ENorm {kNRMin,kNRMax,kNSPhi,kNEPhi,kNZ}; + +////////////////////////////////////////////////////////////////////////// +// +// constructor - check parameters, convert angles so 0<sphi+dpshi<=2_PI +// - note if pDPhi>2PI then reset to 2PI + +G4ShiftedCone::G4ShiftedCone( const G4String& pName, + G4double pZ1, G4double pZ2, + G4double pRmin1, G4double pRmax1, + G4double pRmin2, G4double pRmax2) +// G4double pDz, +// G4double pSPhi, G4double pDPhi) + : G4CSGSolid(pName), fRmin1(pRmin1), fRmin2(pRmin2), + fRmax1(pRmax1), fRmax2(pRmax2), + fDz((pZ2 - pZ1) * 0.5), fZshift(pZ1 + fDz) + // fSPhi(0.), fDPhi(0.) +{ + kRadTolerance = G4GeometryTolerance::GetInstance()->GetRadialTolerance(); + kAngTolerance = G4GeometryTolerance::GetInstance()->GetAngularTolerance(); + + halfCarTolerance=kCarTolerance*0.5; + halfRadTolerance=kRadTolerance*0.5; + halfAngTolerance=kAngTolerance*0.5; + + // Check z-len + // + if ( fDz < 0 ) + { + std::ostringstream message; + message << "Invalid Z half-length for Solid: " << GetName() << G4endl + << " hZ = " << fDz; + G4Exception("G4ShiftedCone::G4ShiftedCone()", "GeomSolids0002", + FatalException, message); + } + + // Check radii + // + if (((pRmin1>=pRmax1) || (pRmin2>=pRmax2) || (pRmin1<0)) && (pRmin2<0)) + { + std::ostringstream message; + message << "Invalid values of radii for Solid: " << GetName() << G4endl + << " pRmin1 = " << pRmin1 << ", pRmin2 = " << pRmin2 + << ", pRmax1 = " << pRmax1 << ", pRmax2 = " << pRmax2; + G4Exception("G4ShiftedCone::G4ShiftedCone()", "GeomSolids0002", + FatalException, message) ; + } + if( (pRmin1 == 0.0) && (pRmin2 > 0.0) ) { fRmin1 = 1e3*kRadTolerance ; } + if( (pRmin2 == 0.0) && (pRmin1 > 0.0) ) { fRmin2 = 1e3*kRadTolerance ; } + + // Check angles + // +// CheckPhiAngles(pSPhi, pDPhi); +} + +/////////////////////////////////////////////////////////////////////// +// +// Fake default constructor - sets only member data and allocates memory +// for usage restricted to object persistency. +// +G4ShiftedCone::G4ShiftedCone( __void__& a ) + : G4CSGSolid(a), kRadTolerance(0.), kAngTolerance(0.), + fRmin1(0.), fRmin2(0.), fRmax1(0.), fRmax2(0.), + fDz(0.), fZshift(0.), +// fSPhi(0.), fDPhi(0.), sinCPhi(0.), cosCPhi(0.), cosHDPhiOT(0.), +// cosHDPhiIT(0.), sinSPhi(0.), cosSPhi(0.), sinEPhi(0.), cosEPhi(0.), +// fPhiFullCone(false), + halfCarTolerance(0.), halfRadTolerance(0.), halfAngTolerance(0.) +{ +} + +/////////////////////////////////////////////////////////////////////// +// +// Destructor + +G4ShiftedCone::~G4ShiftedCone() +{ +} + +////////////////////////////////////////////////////////////////////////// +// +// Copy constructor + +G4ShiftedCone::G4ShiftedCone(const G4ShiftedCone& rhs) + : G4CSGSolid(rhs), kRadTolerance(rhs.kRadTolerance), + kAngTolerance(rhs.kAngTolerance), fRmin1(rhs.fRmin1), fRmin2(rhs.fRmin2), + fRmax1(rhs.fRmax1), fRmax2(rhs.fRmax2), fDz(rhs.fDz), fZshift(rhs.fZshift), +// fSPhi(rhs.fSPhi), +// fDPhi(rhs.fDPhi), sinCPhi(rhs.sinCPhi), cosCPhi(rhs.cosCPhi), +// cosHDPhiOT(rhs.cosHDPhiOT), cosHDPhiIT(rhs.cosHDPhiIT), +// sinSPhi(rhs.sinSPhi), cosSPhi(rhs.cosSPhi), sinEPhi(rhs.sinEPhi), +// cosEPhi(rhs.cosEPhi), fPhiFullCone(rhs.fPhiFullCone), + halfCarTolerance(rhs.halfCarTolerance), + halfRadTolerance(rhs.halfRadTolerance), + halfAngTolerance(rhs.halfAngTolerance) +{ +} + +////////////////////////////////////////////////////////////////////////// +// +// Assignment operator + +G4ShiftedCone& G4ShiftedCone::operator = (const G4ShiftedCone& rhs) +{ + // Check assignment to self + // + if (this == &rhs) { return *this; } + + // Copy base class data + // + G4CSGSolid::operator=(rhs); + + // Copy data + // + kRadTolerance = rhs.kRadTolerance; + kAngTolerance = rhs.kAngTolerance; + fRmin1 = rhs.fRmin1; fRmin2 = rhs.fRmin2; + fRmax1 = rhs.fRmax1; fRmax2 = rhs.fRmax2; + fDz = rhs.fDz; fZshift = rhs.fZshift; +// fSPhi = rhs.fSPhi; fDPhi = rhs.fDPhi; +// sinCPhi = rhs.sinCPhi; cosCPhi = rhs.cosCPhi; +// cosHDPhiOT = rhs.cosHDPhiOT; cosHDPhiIT = rhs.cosHDPhiIT; +// sinSPhi = rhs.sinSPhi; cosSPhi = rhs.cosSPhi; +// sinEPhi = rhs.sinEPhi; cosEPhi = rhs.cosEPhi; +// fPhiFullCone = rhs.fPhiFullCone; + halfCarTolerance = rhs.halfCarTolerance; + halfRadTolerance = rhs.halfRadTolerance; + halfAngTolerance = rhs.halfAngTolerance; + + return *this; +} + +///////////////////////////////////////////////////////////////////// +// +// Return whether point inside/outside/on surface + +EInside G4ShiftedCone::Inside(const G4ThreeVector& p) const +{ + G4double r2, rl, rh, /*pPhi,*/ tolRMin, tolRMax; // rh2, rl2 ; + EInside in; + + G4double z = p.z() - fZshift; + + if (std::fabs(z) > fDz + halfCarTolerance ) { return in = kOutside; } + else if(std::fabs(z) >= fDz - halfCarTolerance ) { in = kSurface; } + else { in = kInside; } + + r2 = p.x()*p.x() + p.y()*p.y() ; + rl = 0.5*(fRmin2*(z + fDz) + fRmin1*(fDz - z))/fDz ; + rh = 0.5*(fRmax2*(z+fDz)+fRmax1*(fDz-z))/fDz; + + // rh2 = rh*rh; + + tolRMin = rl - halfRadTolerance; + if ( tolRMin < 0 ) { tolRMin = 0; } + tolRMax = rh + halfRadTolerance; + + if ( (r2<tolRMin*tolRMin) || (r2>tolRMax*tolRMax) ) { return in = kOutside; } + + if (rl) { tolRMin = rl + halfRadTolerance; } + else { tolRMin = 0.0; } + tolRMax = rh - halfRadTolerance; + + if (in == kInside) // else it's kSurface already + { + if ( (r2 < tolRMin*tolRMin) || (r2 >= tolRMax*tolRMax) ) { in = kSurface; } + } +/* + if ( !fPhiFullCone && ((p.x() != 0.0) || (p.y() != 0.0)) ) + { + pPhi = std::atan2(p.y(),p.x()) ; + + if ( pPhi < fSPhi - halfAngTolerance ) { pPhi += twopi; } + else if ( pPhi > fSPhi + fDPhi + halfAngTolerance ) { pPhi -= twopi; } + + if ( (pPhi < fSPhi - halfAngTolerance) || + (pPhi > fSPhi + fDPhi + halfAngTolerance) ) { return in = kOutside; } + + else if (in == kInside) // else it's kSurface anyway already + { + if ( (pPhi < fSPhi + halfAngTolerance) || + (pPhi > fSPhi + fDPhi - halfAngTolerance) ) { in = kSurface; } + } + } + else if ( !fPhiFullCone ) { in = kSurface; } +*/ + return in ; +} + +///////////////////////////////////////////////////////////////////////// +// +// Dispatch to parameterisation for replication mechanism dimension +// computation & modification. + +void G4ShiftedCone::ComputeDimensions( G4VPVParameterisation*,// p, + const G4int ,//n, + const G4VPhysicalVolume* )//pRep ) +{ + std::ostringstream message; + message << "ComputeDimensions is not implemented for Solid: " << GetName(); + G4Exception("G4ShiftedCone::ComputeDimensions()", "GeomSolids0002", + FatalException, message) ; +// p->ComputeDimensions(*this,n,pRep) ; +} + +/////////////////////////////////////////////////////////////////////// +// +// Get bounding box + +void G4ShiftedCone::BoundingLimits(G4ThreeVector& pMin, G4ThreeVector& pMax) const +{ +// G4double rmin = std::min(GetInnerRadiusMinusZ(),GetInnerRadiusPlusZ()); + G4double rmax = std::max(GetOuterRadiusMinusZ(),GetOuterRadiusPlusZ()); + + // Find bounding box + // +/* if (GetDeltaPhiAngle() < twopi) + { + G4double dz = GetZHalfLength(); + G4TwoVector vmin,vmax; + G4GeomTools::DiskExtent(rmin,rmax, + GetSinStartPhi(),GetCosStartPhi(), + GetSinEndPhi(),GetCosEndPhi(), + vmin,vmax); + pMin.set(vmin.x(),vmin.y(),-dz); + pMax.set(vmax.x(),vmax.y(), dz); + } + else*/ + { + pMin.set(-rmax,-rmax, fZshift - fDz); + pMax.set( rmax, rmax, fZshift + fDz); + } + + // Check correctness of the bounding box + // + if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z()) + { + std::ostringstream message; + message << "Bad bounding box (min >= max) for solid: " + << GetName() << " !" + << "\npMin = " << pMin + << "\npMax = " << pMax; + G4Exception("G4ShiftedCone::BoundingLimits()", "GeomMgt0001", + JustWarning, message); + DumpInfo(); + } +} + +/////////////////////////////////////////////////////////////////////// +// +// Calculate extent under transform and specified limit + +G4bool G4ShiftedCone::CalculateExtent( const EAxis pAxis, + const G4VoxelLimits& pVoxelLimit, + const G4AffineTransform& pTransform, + G4double& pMin, + G4double& pMax ) const +{ + G4ThreeVector bmin, bmax; + G4bool exist; + + // Get bounding box + BoundingLimits(bmin,bmax); + + // Check bounding box + G4BoundingEnvelope bbox(bmin,bmax); +#ifdef G4BBOX_EXTENT + if (true) return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax); +#endif + if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax)) + { + return exist = (pMin < pMax) ? true : false; + } + + // Get parameters of the solid + G4double rmin1 = GetInnerRadiusMinusZ(); + G4double rmax1 = GetOuterRadiusMinusZ(); + G4double rmin2 = GetInnerRadiusPlusZ(); + G4double rmax2 = GetOuterRadiusPlusZ(); + G4double z1 = GetZ1(); + G4double z2 = GetZ2(); + G4double dphi = GetDeltaPhiAngle(); + + // Find bounding envelope and calculate extent + // + const G4int NSTEPS = 24; // number of steps for whole circle + G4double astep = twopi/NSTEPS; // max angle for one step + G4int ksteps = (dphi <= astep) ? 1 : (G4int)((dphi-deg)/astep) + 1; + G4double ang = dphi/ksteps; + + G4double sinHalf = std::sin(0.5*ang); + G4double cosHalf = std::cos(0.5*ang); + G4double sinStep = 2.*sinHalf*cosHalf; + G4double cosStep = 1. - 2.*sinHalf*sinHalf; + G4double rext1 = rmax1/cosHalf; + G4double rext2 = rmax2/cosHalf; + + // bounding envelope for full cone without hole consists of two polygons, + // in other cases it is a sequence of quadrilaterals + if (rmin1 == 0 && rmin2 == 0 && dphi == twopi) + { + G4double sinCur = sinHalf; + G4double cosCur = cosHalf; + + G4ThreeVectorList baseA(NSTEPS),baseB(NSTEPS); + for (G4int k=0; k<NSTEPS; ++k) + { + baseA[k].set(rext1*cosCur,rext1*sinCur, z1); + baseB[k].set(rext2*cosCur,rext2*sinCur, z2); + + G4double sinTmp = sinCur; + sinCur = sinCur*cosStep + cosCur*sinStep; + cosCur = cosCur*cosStep - sinTmp*sinStep; + } + std::vector<const G4ThreeVectorList *> polygons(2); + polygons[0] = &baseA; + polygons[1] = &baseB; + G4BoundingEnvelope benv(bmin,bmax,polygons); + exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax); + } + else + { + + G4double sinStart = GetSinStartPhi(); + G4double cosStart = GetCosStartPhi(); + G4double sinEnd = GetSinEndPhi(); + G4double cosEnd = GetCosEndPhi(); + G4double sinCur = sinStart*cosHalf + cosStart*sinHalf; + G4double cosCur = cosStart*cosHalf - sinStart*sinHalf; + + // set quadrilaterals + G4ThreeVectorList pols[NSTEPS+2]; + for (G4int k=0; k<ksteps+2; ++k) pols[k].resize(4); + pols[0][0].set(rmin2*cosStart,rmin2*sinStart, z2); + pols[0][1].set(rmin1*cosStart,rmin1*sinStart, z1); + pols[0][2].set(rmax1*cosStart,rmax1*sinStart, z1); + pols[0][3].set(rmax2*cosStart,rmax2*sinStart, z2); + for (G4int k=1; k<ksteps+1; ++k) + { + pols[k][0].set(rmin2*cosCur,rmin2*sinCur, z2); + pols[k][1].set(rmin1*cosCur,rmin1*sinCur, z1); + pols[k][2].set(rext1*cosCur,rext1*sinCur, z1); + pols[k][3].set(rext2*cosCur,rext2*sinCur, z2); + + G4double sinTmp = sinCur; + sinCur = sinCur*cosStep + cosCur*sinStep; + cosCur = cosCur*cosStep - sinTmp*sinStep; + } + pols[ksteps+1][0].set(rmin2*cosEnd,rmin2*sinEnd, z2); + pols[ksteps+1][1].set(rmin1*cosEnd,rmin1*sinEnd, z1); + pols[ksteps+1][2].set(rmax1*cosEnd,rmax1*sinEnd, z1); + pols[ksteps+1][3].set(rmax2*cosEnd,rmax2*sinEnd, z2); + + // set envelope and calculate extent + std::vector<const G4ThreeVectorList *> polygons; + polygons.resize(ksteps+2); + for (G4int k=0; k<ksteps+2; ++k) polygons[k] = &pols[k]; + G4BoundingEnvelope benv(bmin,bmax,polygons); + exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax); + } + return exist; +} + +//////////////////////////////////////////////////////////////////////// +// +// Return unit normal of surface closest to p +// - note if point on z axis, ignore phi divided sides +// - unsafe if point close to z axis a rmin=0 - no explicit checks + +G4ThreeVector G4ShiftedCone::SurfaceNormal( const G4ThreeVector& p) const +{ + G4int noSurfaces = 0; + G4double rho;//, pPhi; + G4double distZ, distRMin, distRMax; +// G4double distSPhi = kInfinity, distEPhi = kInfinity; + G4double tanRMin, secRMin, pRMin, widRMin; + G4double tanRMax, secRMax, pRMax, widRMax; + + G4ThreeVector norm, sumnorm(0.,0.,0.), nZ = G4ThreeVector(0.,0.,1.); + G4ThreeVector nR, nr(0.,0.,0.), nPs, nPe; + + G4double z = p.z() - fZshift; + + distZ = std::fabs(std::fabs(z) - fDz); + rho = std::sqrt(p.x()*p.x() + p.y()*p.y()); + + tanRMin = (fRmin2 - fRmin1)*0.5/fDz; + secRMin = std::sqrt(1 + tanRMin*tanRMin); + pRMin = rho - z*tanRMin; + widRMin = fRmin2 - fDz*tanRMin; + distRMin = std::fabs(pRMin - widRMin)/secRMin; + + tanRMax = (fRmax2 - fRmax1)*0.5/fDz; + secRMax = std::sqrt(1+tanRMax*tanRMax); + pRMax = rho - z*tanRMax; + widRMax = fRmax2 - fDz*tanRMax; + distRMax = std::fabs(pRMax - widRMax)/secRMax; +/* + if (!fPhiFullCone) // Protected against (0,0,z) + { + if ( rho ) + { + pPhi = std::atan2(p.y(),p.x()); + + if (pPhi < fSPhi-halfCarTolerance) { pPhi += twopi; } + else if (pPhi > fSPhi+fDPhi+halfCarTolerance) { pPhi -= twopi; } + + distSPhi = std::fabs( pPhi - fSPhi ); + distEPhi = std::fabs( pPhi - fSPhi - fDPhi ); + } + else if( !(fRmin1) || !(fRmin2) ) + { + distSPhi = 0.; + distEPhi = 0.; + } + nPs = G4ThreeVector(std::sin(fSPhi), -std::cos(fSPhi), 0); + nPe = G4ThreeVector(-std::sin(fSPhi+fDPhi), std::cos(fSPhi+fDPhi), 0); + }*/ + if ( rho > halfCarTolerance ) + { + nR = G4ThreeVector(p.x()/rho/secRMax, p.y()/rho/secRMax, -tanRMax/secRMax); + if (fRmin1 || fRmin2) + { + nr = G4ThreeVector(-p.x()/rho/secRMin,-p.y()/rho/secRMin,tanRMin/secRMin); + } + } + + if( distRMax <= halfCarTolerance ) + { + noSurfaces ++; + sumnorm += nR; + } + if( (fRmin1 || fRmin2) && (distRMin <= halfCarTolerance) ) + { + noSurfaces ++; + sumnorm += nr; + } +/* if( !fPhiFullCone ) + { + if (distSPhi <= halfAngTolerance) + { + noSurfaces ++; + sumnorm += nPs; + } + if (distEPhi <= halfAngTolerance) + { + noSurfaces ++; + sumnorm += nPe; + } + }*/ + if (distZ <= halfCarTolerance) + { + noSurfaces ++; + if ( z >= 0.) { sumnorm += nZ; } + else { sumnorm -= nZ; } + } + if ( noSurfaces == 0 ) + { +#ifdef G4CSGDEBUG + G4Exception("G4ShiftedCone::SurfaceNormal(p)", "GeomSolids1002", + JustWarning, "Point p is not on surface !?" ); +#endif + norm = ApproxSurfaceNormal(p); + } + else if ( noSurfaces == 1 ) { norm = sumnorm; } + else { norm = sumnorm.unit(); } + + return norm ; +} + +//////////////////////////////////////////////////////////////////////////// +// +// Algorithm for SurfaceNormal() following the original specification +// for points not on the surface + +G4ThreeVector G4ShiftedCone::ApproxSurfaceNormal( const G4ThreeVector& p ) const +{ + ENorm side ; + G4ThreeVector norm ; + G4double rho;//, phi ; + G4double distZ, distRMin, distRMax;//, distSPhi, distEPhi, distMin ; + G4double tanRMin, secRMin, pRMin, widRMin ; + G4double tanRMax, secRMax, pRMax, widRMax ; + + G4double z = p.z() - fZshift; + + distZ = std::fabs(std::fabs(z) - fDz) ; + rho = std::sqrt(p.x()*p.x() + p.y()*p.y()) ; + + tanRMin = (fRmin2 - fRmin1)*0.5/fDz ; + secRMin = std::sqrt(1 + tanRMin*tanRMin) ; + pRMin = rho - z*tanRMin ; + widRMin = fRmin2 - fDz*tanRMin ; + distRMin = std::fabs(pRMin - widRMin)/secRMin ; + + tanRMax = (fRmax2 - fRmax1)*0.5/fDz ; + secRMax = std::sqrt(1+tanRMax*tanRMax) ; + pRMax = rho - z*tanRMax ; + widRMax = fRmax2 - fDz*tanRMax ; + distRMax = std::fabs(pRMax - widRMax)/secRMax ; + + if (distRMin < distRMax) // First minimum + { + if (distZ < distRMin) + { +// distMin = distZ ; + side = kNZ ; + } + else + { +// distMin = distRMin ; + side = kNRMin ; + } + } + else + { + if (distZ < distRMax) + { +// distMin = distZ ; + side = kNZ ; + } + else + { +// distMin = distRMax ; + side = kNRMax ; + } + } +/* + if ( !fPhiFullCone && rho ) // Protected against (0,0,z) + { + phi = std::atan2(p.y(),p.x()) ; + + if (phi < 0) { phi += twopi; } + + if (fSPhi < 0) { distSPhi = std::fabs(phi - (fSPhi + twopi))*rho; } + else { distSPhi = std::fabs(phi - fSPhi)*rho; } + + distEPhi = std::fabs(phi - fSPhi - fDPhi)*rho ; + + // Find new minimum + + if (distSPhi < distEPhi) + { + if (distSPhi < distMin) { side = kNSPhi; } + } + else + { + if (distEPhi < distMin) { side = kNEPhi; } + } + }*/ + switch (side) + { + case kNRMin: // Inner radius + rho *= secRMin ; + norm = G4ThreeVector(-p.x()/rho, -p.y()/rho, tanRMin/secRMin) ; + break ; + case kNRMax: // Outer radius + rho *= secRMax ; + norm = G4ThreeVector(p.x()/rho, p.y()/rho, -tanRMax/secRMax) ; + break ; + case kNZ: // +/- dz + if (z > 0) { norm = G4ThreeVector(0,0,1); } + else { norm = G4ThreeVector(0,0,-1); } + break ; +// case kNSPhi: +// norm = G4ThreeVector(std::sin(fSPhi), -std::cos(fSPhi), 0) ; +// break ; +// case kNEPhi: +// norm=G4ThreeVector(-std::sin(fSPhi+fDPhi), std::cos(fSPhi+fDPhi), 0) ; +// break ; + default: // Should never reach this case... + DumpInfo(); + G4Exception("G4ShiftedCone::ApproxSurfaceNormal()", + "GeomSolids1002", JustWarning, + "Undefined side for valid surface normal to solid."); + break ; + } + return norm ; +} + +//////////////////////////////////////////////////////////////////////// +// +// Calculate distance to shape from outside, along normalised vector +// - return kInfinity if no intersection, or intersection distance <= tolerance +// +// - Compute the intersection with the z planes +// - if at valid r, phi, return +// +// -> If point is outside cone, compute intersection with rmax1*0.5 +// - if at valid phi,z return +// - if inside outer cone, handle case when on tolerant outer cone +// boundary and heading inwards(->0 to in) +// +// -> Compute intersection with inner cone, taking largest +ve root +// - if valid (in z,phi), save intersction +// +// -> If phi segmented, compute intersections with phi half planes +// - return smallest of valid phi intersections and +// inner radius intersection +// +// NOTE: +// - `if valid' implies tolerant checking of intersection points +// - z, phi intersection from Tubs + +G4double G4ShiftedCone::DistanceToIn( const G4ThreeVector& p, + const G4ThreeVector& v ) const +{ + G4double snxt = kInfinity ; // snxt = default return value + const G4double dRmax = 50*(fRmax1+fRmax2);// 100*(Rmax1+Rmax2)/2. + + G4double tanRMax,secRMax,rMaxAv;//,rMaxOAv ; // Data for cones + G4double tanRMin,secRMin,rMinAv;//,rMinOAv ; + G4double rout,rin ; + + G4double tolORMin,/*tolORMin2,*/tolIRMin,tolIRMin2 ; // `generous' radii squared + G4double /*tolORMax2,*/tolIRMax,tolIRMax2 ; + G4double tolODz,tolIDz ; + + G4double /*Dist,*/ sd,xi,yi,zi,ri=0.,risec,rhoi2;//,cosPsi ; // Intersection point vars + + G4double t1,t2,t3,b,c,d ; // Quadratic solver variables + G4double nt1,nt2,nt3 ; +// G4double Comp ; + + G4ThreeVector Normal; + + G4double z = p.z() - fZshift; + + // Cone Precalcs + + tanRMin = (fRmin2 - fRmin1)*0.5/fDz ; + secRMin = std::sqrt(1.0 + tanRMin*tanRMin) ; + rMinAv = (fRmin1 + fRmin2)*0.5 ; +/* + if (rMinAv > halfRadTolerance) + { + rMinOAv = rMinAv - halfRadTolerance ; + } + else + { + rMinOAv = 0.0 ; + }*/ + tanRMax = (fRmax2 - fRmax1)*0.5/fDz ; + secRMax = std::sqrt(1.0 + tanRMax*tanRMax) ; + rMaxAv = (fRmax1 + fRmax2)*0.5 ; +// rMaxOAv = rMaxAv + halfRadTolerance ; + + // Intersection with z-surfaces + + tolIDz = fDz - halfCarTolerance ; + tolODz = fDz + halfCarTolerance ; + + if (std::fabs(z) >= tolIDz) + { + if ( z*v.z() < 0 ) // at +Z going in -Z or visa versa + { + sd = (std::fabs(z) - fDz)/std::fabs(v.z()) ; // Z intersect distance + + if( sd < 0.0 ) { sd = 0.0; } // negative dist -> zero + + xi = p.x() + sd*v.x() ; // Intersection coords + yi = p.y() + sd*v.y() ; + rhoi2 = xi*xi + yi*yi ; + + // Check validity of intersection + // Calculate (outer) tolerant radi^2 at intersecion + + if (v.z() > 0) + { + tolORMin = fRmin1 - halfRadTolerance*secRMin ; + tolIRMin = fRmin1 + halfRadTolerance*secRMin ; + tolIRMax = fRmax1 - halfRadTolerance*secRMin ; + // tolORMax2 = (fRmax1 + halfRadTolerance*secRMax)* + // (fRmax1 + halfRadTolerance*secRMax) ; + } + else + { + tolORMin = fRmin2 - halfRadTolerance*secRMin ; + tolIRMin = fRmin2 + halfRadTolerance*secRMin ; + tolIRMax = fRmax2 - halfRadTolerance*secRMin ; + // tolORMax2 = (fRmax2 + halfRadTolerance*secRMax)* + // (fRmax2 + halfRadTolerance*secRMax) ; + } + if ( tolORMin > 0 ) + { + // tolORMin2 = tolORMin*tolORMin ; + tolIRMin2 = tolIRMin*tolIRMin ; + } + else + { + // tolORMin2 = 0.0 ; + tolIRMin2 = 0.0 ; + } + if ( tolIRMax > 0 ) { tolIRMax2 = tolIRMax*tolIRMax; } + else { tolIRMax2 = 0.0; } + + if ( (tolIRMin2 <= rhoi2) && (rhoi2 <= tolIRMax2) ) + { +/* if ( !fPhiFullCone && rhoi2 ) + { + // Psi = angle made with central (average) phi of shape + + cosPsi = (xi*cosCPhi + yi*sinCPhi)/std::sqrt(rhoi2) ; + + if (cosPsi >= cosHDPhiIT) { return sd; } + } + else */ + { + return sd; + } + } + } + else // On/outside extent, and heading away -> cannot intersect + { + return snxt ; + } + } + +// ----> Can not intersect z surfaces + + +// Intersection with outer cone (possible return) and +// inner cone (must also check phi) +// +// Intersection point (xi,yi,zi) on line x=p.x+t*v.x etc. +// +// Intersects with x^2+y^2=(a*z+b)^2 +// +// where a=tanRMax or tanRMin +// b=rMaxAv or rMinAv +// +// (vx^2+vy^2-(a*vz)^2)t^2+2t(pxvx+pyvy-a*vz(a*pz+b))+px^2+py^2-(a*pz+b)^2=0 ; +// t1 t2 t3 +// +// \--------u-------/ \-----------v----------/ \---------w--------/ +// + + t1 = 1.0 - v.z()*v.z() ; + t2 = p.x()*v.x() + p.y()*v.y() ; + t3 = p.x()*p.x() + p.y()*p.y() ; + rin = tanRMin*z + rMinAv ; + rout = tanRMax*z + rMaxAv ; + + // Outer Cone Intersection + // Must be outside/on outer cone for valid intersection + + nt1 = t1 - (tanRMax*v.z())*(tanRMax*v.z()) ; + nt2 = t2 - tanRMax*v.z()*rout ; + nt3 = t3 - rout*rout ; + + if (std::fabs(nt1) > kRadTolerance) // Equation quadratic => 2 roots + { + b = nt2/nt1; + c = nt3/nt1; + d = b*b-c ; + if ( (nt3 > rout*rout*kRadTolerance*kRadTolerance*secRMax*secRMax) + || (rout < 0) ) + { + // If outside real cone (should be rho-rout>kRadTolerance*0.5 + // NOT rho^2 etc) saves a std::sqrt() at expense of accuracy + + if (d >= 0) + { + + if ((rout < 0) && (nt3 <= 0)) + { + // Inside `shadow cone' with -ve radius + // -> 2nd root could be on real cone + + if (b>0) { sd = c/(-b-std::sqrt(d)); } + else { sd = -b + std::sqrt(d); } + } + else + { + if ((b <= 0) && (c >= 0)) // both >=0, try smaller root + { + sd=c/(-b+std::sqrt(d)); + } + else + { + if ( c <= 0 ) // second >=0 + { + sd = -b + std::sqrt(d) ; + if((sd<0) & (sd>-halfRadTolerance)) sd=0; + } + else // both negative, travel away + { + return kInfinity ; + } + } + } + if ( sd >= 0 ) // If 'forwards'. Check z intersection + { + if ( sd>dRmax ) // Avoid rounding errors due to precision issues on + { // 64 bits systems. Split long distances and recompute + G4double fTerm = sd-std::fmod(sd,dRmax); + sd = fTerm + DistanceToIn(p+fTerm*v,v); + } + zi = z + sd*v.z() ; + + if (std::fabs(zi) <= tolODz) + { + // Z ok. Check phi intersection if reqd + + return sd; +/* if ( fPhiFullCone ) { return sd; } + else + { + xi = p.x() + sd*v.x() ; + yi = p.y() + sd*v.y() ; + ri = rMaxAv + zi*tanRMax ; + cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ; + + if ( cosPsi >= cosHDPhiIT ) { return sd; } + }*/ + } + } // end if (sd>0) + } + } + else + { + // Inside outer cone + // check not inside, and heading through G4ShiftedCone (-> 0 to in) + + if ( ( t3 > (rin + halfRadTolerance*secRMin)* + (rin + halfRadTolerance*secRMin) ) + && (nt2 < 0) && (d >= 0) && (std::fabs(z) <= tolIDz) ) + { + // Inside cones, delta r -ve, inside z extent + // Point is on the Surface => check Direction using Normal.dot(v) + + xi = p.x() ; + yi = p.y() ; + risec = std::sqrt(xi*xi + yi*yi)*secRMax ; + Normal = G4ThreeVector(xi/risec,yi/risec,-tanRMax/secRMax) ; +/* if ( !fPhiFullCone ) + { + cosPsi = (p.x()*cosCPhi + p.y()*sinCPhi)/std::sqrt(t3) ; + if ( cosPsi >= cosHDPhiIT ) + { + if ( Normal.dot(v) <= 0 ) { return 0.0; } + } + } + else*/ + { + if ( Normal.dot(v) <= 0 ) { return 0.0; } + } + } + } + } + else // Single root case + { + if ( std::fabs(nt2) > kRadTolerance ) + { + sd = -0.5*nt3/nt2 ; + + if ( sd < 0 ) { return kInfinity; } // travel away + else // sd >= 0, If 'forwards'. Check z intersection + { + zi = z + sd*v.z() ; + + if ((std::fabs(zi) <= tolODz) && (nt2 < 0)) + { + // Z ok. Check phi intersection if reqd + return sd; +/* if ( fPhiFullCone ) { return sd; } + else + { + xi = p.x() + sd*v.x() ; + yi = p.y() + sd*v.y() ; + ri = rMaxAv + zi*tanRMax ; + cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ; + + if (cosPsi >= cosHDPhiIT) { return sd; } + }*/ + } + } + } + else // travel || cone surface from its origin + { + sd = kInfinity ; + } + } + + // Inner Cone Intersection + // o Space is divided into 3 areas: + // 1) Radius greater than real inner cone & imaginary cone & outside + // tolerance + // 2) Radius less than inner or imaginary cone & outside tolarance + // 3) Within tolerance of real or imaginary cones + // - Extra checks needed for 3's intersections + // => lots of duplicated code + + if (rMinAv) + { + nt1 = t1 - (tanRMin*v.z())*(tanRMin*v.z()) ; + nt2 = t2 - tanRMin*v.z()*rin ; + nt3 = t3 - rin*rin ; + + if ( nt1 ) + { + if ( nt3 > rin*kRadTolerance*secRMin ) + { + // At radius greater than real & imaginary cones + // -> 2nd root, with zi check + + b = nt2/nt1 ; + c = nt3/nt1 ; + d = b*b-c ; + if (d >= 0) // > 0 + { + if(b>0){sd = c/( -b-std::sqrt(d));} + else {sd = -b + std::sqrt(d) ;} + + if ( sd >= 0 ) // > 0 + { + if ( sd>dRmax ) // Avoid rounding errors due to precision issues on + { // 64 bits systems. Split long distance and recompute + G4double fTerm = sd-std::fmod(sd,dRmax); + sd = fTerm + DistanceToIn(p+fTerm*v,v); + } + zi = z + sd*v.z() ; + + if ( std::fabs(zi) <= tolODz ) + { +/* if ( !fPhiFullCone ) + { + xi = p.x() + sd*v.x() ; + yi = p.y() + sd*v.y() ; + ri = rMinAv + zi*tanRMin ; + cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ; + + if (cosPsi >= cosHDPhiIT) + { + if ( sd > halfRadTolerance ) { snxt=sd; } + else + { + // Calculate a normal vector in order to check Direction + + risec = std::sqrt(xi*xi + yi*yi)*secRMin ; + Normal = G4ThreeVector(-xi/risec,-yi/risec,tanRMin/secRMin); + if ( Normal.dot(v) <= 0 ) { snxt = sd; } + } + } + } + else */ + { + if ( sd > halfRadTolerance ) { return sd; } + else + { + // Calculate a normal vector in order to check Direction + + xi = p.x() + sd*v.x() ; + yi = p.y() + sd*v.y() ; + risec = std::sqrt(xi*xi + yi*yi)*secRMin ; + Normal = G4ThreeVector(-xi/risec,-yi/risec,tanRMin/secRMin) ; + if ( Normal.dot(v) <= 0 ) { return sd; } + } + } + } + } + } + } + else if ( nt3 < -rin*kRadTolerance*secRMin ) + { + // Within radius of inner cone (real or imaginary) + // -> Try 2nd root, with checking intersection is with real cone + // -> If check fails, try 1st root, also checking intersection is + // on real cone + + b = nt2/nt1 ; + c = nt3/nt1 ; + d = b*b - c ; + + if ( d >= 0 ) // > 0 + { + if (b>0) { sd = c/(-b-std::sqrt(d)); } + else { sd = -b + std::sqrt(d); } + zi = z + sd*v.z() ; + ri = rMinAv + zi*tanRMin ; + + if ( ri > 0 ) + { + if ( (sd >= 0) && (std::fabs(zi) <= tolODz) ) // sd > 0 + { + if ( sd>dRmax ) // Avoid rounding errors due to precision issues + { // seen on 64 bits systems. Split and recompute + G4double fTerm = sd-std::fmod(sd,dRmax); + sd = fTerm + DistanceToIn(p+fTerm*v,v); + } +/* if ( !fPhiFullCone ) + { + xi = p.x() + sd*v.x() ; + yi = p.y() + sd*v.y() ; + cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ; + + if (cosPsi >= cosHDPhiOT) + { + if ( sd > halfRadTolerance ) { snxt=sd; } + else + { + // Calculate a normal vector in order to check Direction + + risec = std::sqrt(xi*xi + yi*yi)*secRMin ; + Normal = G4ThreeVector(-xi/risec,-yi/risec,tanRMin/secRMin); + if ( Normal.dot(v) <= 0 ) { snxt = sd; } + } + } + } + else */ + { + if( sd > halfRadTolerance ) { return sd; } + else + { + // Calculate a normal vector in order to check Direction + + xi = p.x() + sd*v.x() ; + yi = p.y() + sd*v.y() ; + risec = std::sqrt(xi*xi + yi*yi)*secRMin ; + Normal = G4ThreeVector(-xi/risec,-yi/risec,tanRMin/secRMin) ; + if ( Normal.dot(v) <= 0 ) { return sd; } + } + } + } + } + else + { + if (b>0) { sd = -b - std::sqrt(d); } + else { sd = c/(-b+std::sqrt(d)); } + zi = z + sd*v.z() ; + ri = rMinAv + zi*tanRMin ; + + if ( (sd >= 0) && (ri > 0) && (std::fabs(zi) <= tolODz) ) // sd>0 + { + if ( sd>dRmax ) // Avoid rounding errors due to precision issues + { // seen on 64 bits systems. Split and recompute + G4double fTerm = sd-std::fmod(sd,dRmax); + sd = fTerm + DistanceToIn(p+fTerm*v,v); + } +/* if ( !fPhiFullCone ) + { + xi = p.x() + sd*v.x() ; + yi = p.y() + sd*v.y() ; + cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ; + + if (cosPsi >= cosHDPhiIT) + { + if ( sd > halfRadTolerance ) { snxt=sd; } + else + { + // Calculate a normal vector in order to check Direction + + risec = std::sqrt(xi*xi + yi*yi)*secRMin ; + Normal = G4ThreeVector(-xi/risec,-yi/risec,tanRMin/secRMin); + if ( Normal.dot(v) <= 0 ) { snxt = sd; } + } + } + } + else */ + { + if ( sd > halfRadTolerance ) { return sd; } + else + { + // Calculate a normal vector in order to check Direction + + xi = p.x() + sd*v.x() ; + yi = p.y() + sd*v.y() ; + risec = std::sqrt(xi*xi + yi*yi)*secRMin ; + Normal = G4ThreeVector(-xi/risec,-yi/risec,tanRMin/secRMin) ; + if ( Normal.dot(v) <= 0 ) { return sd; } + } + } + } + } + } + } + else + { + // Within kRadTol*0.5 of inner cone (real OR imaginary) + // ----> Check not travelling through (=>0 to in) + // ----> if not: + // -2nd root with validity check + + if ( std::fabs(z) <= tolODz ) + { + if ( nt2 > 0 ) + { + // Inside inner real cone, heading outwards, inside z range + +/* if ( !fPhiFullCone ) + { + cosPsi = (p.x()*cosCPhi + p.y()*sinCPhi)/std::sqrt(t3) ; + + if (cosPsi >= cosHDPhiIT) { return 0.0; } + } + else */ { return 0.0; } + } + else + { + // Within z extent, but not travelling through + // -> 2nd root or kInfinity if 1st root on imaginary cone + + b = nt2/nt1 ; + c = nt3/nt1 ; + d = b*b - c ; + + if ( d >= 0 ) // > 0 + { + if (b>0) { sd = -b - std::sqrt(d); } + else { sd = c/(-b+std::sqrt(d)); } + zi = z + sd*v.z() ; + ri = rMinAv + zi*tanRMin ; + + if ( ri > 0 ) // 2nd root + { + if (b>0) { sd = c/(-b-std::sqrt(d)); } + else { sd = -b + std::sqrt(d); } + + zi = z + sd*v.z() ; + + if ( (sd >= 0) && (std::fabs(zi) <= tolODz) ) // sd>0 + { + if ( sd>dRmax ) // Avoid rounding errors due to precision issue + { // seen on 64 bits systems. Split and recompute + G4double fTerm = sd-std::fmod(sd,dRmax); + sd = fTerm + DistanceToIn(p+fTerm*v,v); + } +/* if ( !fPhiFullCone ) + { + xi = p.x() + sd*v.x() ; + yi = p.y() + sd*v.y() ; + ri = rMinAv + zi*tanRMin ; + cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ; + + if ( cosPsi >= cosHDPhiIT ) { snxt = sd; } + } + else */ { return sd; } + } + } + else { return kInfinity; } + } + } + } + else // 2nd root + { + b = nt2/nt1 ; + c = nt3/nt1 ; + d = b*b - c ; + + if ( d > 0 ) + { + if (b>0) { sd = c/(-b-std::sqrt(d)); } + else { sd = -b + std::sqrt(d) ; } + zi = z + sd*v.z() ; + + if ( (sd >= 0) && (std::fabs(zi) <= tolODz) ) // sd>0 + { + if ( sd>dRmax ) // Avoid rounding errors due to precision issues + { // seen on 64 bits systems. Split and recompute + G4double fTerm = sd-std::fmod(sd,dRmax); + sd = fTerm + DistanceToIn(p+fTerm*v,v); + } +/* if ( !fPhiFullCone ) + { + xi = p.x() + sd*v.x(); + yi = p.y() + sd*v.y(); + ri = rMinAv + zi*tanRMin ; + cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri; + + if (cosPsi >= cosHDPhiIT) { snxt = sd; } + } + else */ { return sd; } + } + } + } + } + } + } + + // Phi segment intersection + // + // o Tolerant of points inside phi planes by up to kCarTolerance*0.5 + // + // o NOTE: Large duplication of code between sphi & ephi checks + // -> only diffs: sphi -> ephi, Comp -> -Comp and half-plane + // intersection check <=0 -> >=0 + // -> Should use some form of loop Construct +/* + if ( !fPhiFullCone ) + { + // First phi surface (starting phi) + + Comp = v.x()*sinSPhi - v.y()*cosSPhi ; + + if ( Comp < 0 ) // Component in outwards normal dirn + { + Dist = (p.y()*cosSPhi - p.x()*sinSPhi) ; + + if (Dist < halfCarTolerance) + { + sd = Dist/Comp ; + + if ( sd < snxt ) + { + if ( sd < 0 ) { sd = 0.0; } + + zi = z + sd*v.z() ; + + if ( std::fabs(zi) <= tolODz ) + { + xi = p.x() + sd*v.x() ; + yi = p.y() + sd*v.y() ; + rhoi2 = xi*xi + yi*yi ; + tolORMin2 = (rMinOAv + zi*tanRMin)*(rMinOAv + zi*tanRMin) ; + tolORMax2 = (rMaxOAv + zi*tanRMax)*(rMaxOAv + zi*tanRMax) ; + + if ( (rhoi2 >= tolORMin2) && (rhoi2 <= tolORMax2) ) + { + // z and r intersections good - check intersecting with + // correct half-plane + + if ((yi*cosCPhi - xi*sinCPhi) <= 0 ) { snxt = sd; } + } + } + } + } + } + + // Second phi surface (Ending phi) + + Comp = -(v.x()*sinEPhi - v.y()*cosEPhi) ; + + if ( Comp < 0 ) // Component in outwards normal dirn + { + Dist = -(p.y()*cosEPhi - p.x()*sinEPhi) ; + if (Dist < halfCarTolerance) + { + sd = Dist/Comp ; + + if ( sd < snxt ) + { + if ( sd < 0 ) { sd = 0.0; } + + zi = z + sd*v.z() ; + + if (std::fabs(zi) <= tolODz) + { + xi = p.x() + sd*v.x() ; + yi = p.y() + sd*v.y() ; + rhoi2 = xi*xi + yi*yi ; + tolORMin2 = (rMinOAv + zi*tanRMin)*(rMinOAv + zi*tanRMin) ; + tolORMax2 = (rMaxOAv + zi*tanRMax)*(rMaxOAv + zi*tanRMax) ; + + if ( (rhoi2 >= tolORMin2) && (rhoi2 <= tolORMax2) ) + { + // z and r intersections good - check intersecting with + // correct half-plane + + if ( (yi*cosCPhi - xi*sinCPhi) >= 0.0 ) { snxt = sd; } + } + } + } + } + } + }*/ + if (snxt < halfCarTolerance) { snxt = 0.; } + + return snxt ; +} + +////////////////////////////////////////////////////////////////////////////// +// +// Calculate distance (<= actual) to closest surface of shape from outside +// - Calculate distance to z, radial planes +// - Only to phi planes if outside phi extent +// - Return 0 if point inside + +G4double G4ShiftedCone::DistanceToIn(const G4ThreeVector& p) const +{ + G4double safe=0.0, rho, safeR1, safeR2, safeZ;//, safePhi, cosPsi ; + G4double tanRMin, secRMin, pRMin ; + G4double tanRMax, secRMax, pRMax ; + + G4double z = p.z() - fZshift; + + rho = std::sqrt(p.x()*p.x() + p.y()*p.y()) ; + safeZ = std::fabs(z) - fDz ; + + if ( fRmin1 || fRmin2 ) + { + tanRMin = (fRmin2 - fRmin1)*0.5/fDz ; + secRMin = std::sqrt(1.0 + tanRMin*tanRMin) ; + pRMin = tanRMin*z + (fRmin1 + fRmin2)*0.5 ; + safeR1 = (pRMin - rho)/secRMin ; + + tanRMax = (fRmax2 - fRmax1)*0.5/fDz ; + secRMax = std::sqrt(1.0 + tanRMax*tanRMax) ; + pRMax = tanRMax*z + (fRmax1 + fRmax2)*0.5 ; + safeR2 = (rho - pRMax)/secRMax ; + + if ( safeR1 > safeR2) { safe = safeR1; } + else { safe = safeR2; } + } + else + { + tanRMax = (fRmax2 - fRmax1)*0.5/fDz ; + secRMax = std::sqrt(1.0 + tanRMax*tanRMax) ; + pRMax = tanRMax*z + (fRmax1 + fRmax2)*0.5 ; + safe = (rho - pRMax)/secRMax ; + } + if ( safeZ > safe ) { safe = safeZ; } + +/* if ( !fPhiFullCone && rho ) + { + // Psi=angle from central phi to point + + cosPsi = (p.x()*cosCPhi + p.y()*sinCPhi)/rho ; + + if ( cosPsi < std::cos(fDPhi*0.5) ) // Point lies outside phi range + { + if ( (p.y()*cosCPhi - p.x()*sinCPhi) <= 0.0 ) + { + safePhi = std::fabs(p.x()*std::sin(fSPhi)-p.y()*std::cos(fSPhi)); + } + else + { + safePhi = std::fabs(p.x()*sinEPhi-p.y()*cosEPhi); + } + if ( safePhi > safe ) { safe = safePhi; } + } + }*/ + if ( safe < 0.0 ) { safe = 0.0; } + + return safe ; +} + +/////////////////////////////////////////////////////////////// +// +// Calculate distance to surface of shape from 'inside', allowing for tolerance +// - Only Calc rmax intersection if no valid rmin intersection + +G4double G4ShiftedCone::DistanceToOut( const G4ThreeVector& p, + const G4ThreeVector& v, + const G4bool calcNorm, + G4bool *validNorm, + G4ThreeVector *n) const +{ + ESide side = kNull, sider = kNull;//, sidephi = kNull; + + G4double snxt,srd,/*sphi,*/pdist ; + + G4double tanRMax, secRMax, rMaxAv ; // Data for outer cone + G4double tanRMin, secRMin, rMinAv ; // Data for inner cone + + G4double t1, t2, t3, rout, rin, nt1, nt2, nt3 ; + G4double b, c, d, sr2, sr3 ; + + // Vars for intersection within tolerance + + ESide sidetol = kNull ; + G4double slentol = kInfinity ; + + // Vars for phi intersection: + +// G4double pDistS, compS, pDistE, compE, sphi2, vphi ; + G4double zi, ri, deltaRoi2, xi, yi, risec ; + + // Z plane intersection + + G4double z = p.z() - fZshift; + + if ( v.z() > 0.0 ) + { + pdist = fDz - z ; + + if (pdist > halfCarTolerance) + { + snxt = pdist/v.z() ; + side = kPZ ; + } + else + { + if (calcNorm) + { + *n = G4ThreeVector(0,0,1) ; + *validNorm = true ; + } + return snxt = 0.0; + } + } + else if ( v.z() < 0.0 ) + { + pdist = fDz + z ; + + if ( pdist > halfCarTolerance) + { + snxt = -pdist/v.z() ; + side = kMZ ; + } + else + { + if ( calcNorm ) + { + *n = G4ThreeVector(0,0,-1) ; + *validNorm = true ; + } + return snxt = 0.0 ; + } + } + else // Travel perpendicular to z axis + { + snxt = kInfinity ; + side = kNull ; + } + + // Radial Intersections + // + // Intersection with outer cone (possible return) and + // inner cone (must also check phi) + // + // Intersection point (xi,yi,zi) on line x=p.x+t*v.x etc. + // + // Intersects with x^2+y^2=(a*z+b)^2 + // + // where a=tanRMax or tanRMin + // b=rMaxAv or rMinAv + // + // (vx^2+vy^2-(a*vz)^2)t^2+2t(pxvx+pyvy-a*vz(a*pz+b))+px^2+py^2-(a*pz+b)^2=0 ; + // t1 t2 t3 + // + // \--------u-------/ \-----------v----------/ \---------w--------/ + + tanRMax = (fRmax2 - fRmax1)*0.5/fDz ; + secRMax = std::sqrt(1.0 + tanRMax*tanRMax) ; + rMaxAv = (fRmax1 + fRmax2)*0.5 ; + + + t1 = 1.0 - v.z()*v.z() ; // since v normalised + t2 = p.x()*v.x() + p.y()*v.y() ; + t3 = p.x()*p.x() + p.y()*p.y() ; + rout = tanRMax*z + rMaxAv ; + + nt1 = t1 - (tanRMax*v.z())*(tanRMax*v.z()) ; + nt2 = t2 - tanRMax*v.z()*rout ; + nt3 = t3 - rout*rout ; + + if (v.z() > 0.0) + { + deltaRoi2 = snxt*snxt*t1 + 2*snxt*t2 + t3 + - fRmax2*(fRmax2 + kRadTolerance*secRMax); + } + else if ( v.z() < 0.0 ) + { + deltaRoi2 = snxt*snxt*t1 + 2*snxt*t2 + t3 + - fRmax1*(fRmax1 + kRadTolerance*secRMax); + } + else + { + deltaRoi2 = 1.0; + } + + if ( nt1 && (deltaRoi2 > 0.0) ) + { + // Equation quadratic => 2 roots : second root must be leaving + + b = nt2/nt1 ; + c = nt3/nt1 ; + d = b*b - c ; + + if ( d >= 0 ) + { + // Check if on outer cone & heading outwards + // NOTE: Should use rho-rout>-kRadTolerance*0.5 + + if (nt3 > -halfRadTolerance && nt2 >= 0 ) + { + if (calcNorm) + { + risec = std::sqrt(t3)*secRMax ; + *validNorm = true ; + *n = G4ThreeVector(p.x()/risec,p.y()/risec,-tanRMax/secRMax); + } + return snxt=0 ; + } + else + { + sider = kRMax ; + if (b>0) { srd = -b - std::sqrt(d); } + else { srd = c/(-b+std::sqrt(d)) ; } + + zi = z + srd*v.z() ; + ri = tanRMax*zi + rMaxAv ; + + if ((ri >= 0) && (-halfRadTolerance <= srd) && (srd <= halfRadTolerance)) + { + // An intersection within the tolerance + // we will Store it in case it is good - + // + slentol = srd ; + sidetol = kRMax ; + } + if ( (ri < 0) || (srd < halfRadTolerance) ) + { + // Safety: if both roots -ve ensure that srd cannot `win' + // distance to out + + if (b>0) { sr2 = c/(-b-std::sqrt(d)); } + else { sr2 = -b + std::sqrt(d); } + zi = z + sr2*v.z() ; + ri = tanRMax*zi + rMaxAv ; + + if ((ri >= 0) && (sr2 > halfRadTolerance)) + { + srd = sr2; + } + else + { + srd = kInfinity ; + + if( (-halfRadTolerance <= sr2) && ( sr2 <= halfRadTolerance) ) + { + // An intersection within the tolerance. + // Storing it in case it is good. + + slentol = sr2 ; + sidetol = kRMax ; + } + } + } + } + } + else + { + // No intersection with outer cone & not parallel + // -> already outside, no intersection + + if ( calcNorm ) + { + risec = std::sqrt(t3)*secRMax; + *validNorm = true; + *n = G4ThreeVector(p.x()/risec,p.y()/risec,-tanRMax/secRMax); + } + return snxt = 0.0 ; + } + } + else if ( nt2 && (deltaRoi2 > 0.0) ) + { + // Linear case (only one intersection) => point outside outer cone + + if ( calcNorm ) + { + risec = std::sqrt(t3)*secRMax; + *validNorm = true; + *n = G4ThreeVector(p.x()/risec,p.y()/risec,-tanRMax/secRMax); + } + return snxt = 0.0 ; + } + else + { + // No intersection -> parallel to outer cone + // => Z or inner cone intersection + + srd = kInfinity ; + } + + // Check possible intersection within tolerance + + if ( slentol <= halfCarTolerance ) + { + // An intersection within the tolerance was found. + // We must accept it only if the momentum points outwards. + // + // G4ThreeVector ptTol ; // The point of the intersection + // ptTol= p + slentol*v ; + // ri=tanRMax*zi+rMaxAv ; + // + // Calculate a normal vector, as below + + xi = p.x() + slentol*v.x(); + yi = p.y() + slentol*v.y(); + risec = std::sqrt(xi*xi + yi*yi)*secRMax; + G4ThreeVector Normal = G4ThreeVector(xi/risec,yi/risec,-tanRMax/secRMax); + + if ( Normal.dot(v) > 0 ) // We will leave the Cone immediatelly + { + if ( calcNorm ) + { + *n = Normal.unit() ; + *validNorm = true ; + } + return snxt = 0.0 ; + } + else // On the surface, but not heading out so we ignore this intersection + { // (as it is within tolerance). + slentol = kInfinity ; + } + } + + // Inner Cone intersection + + if ( fRmin1 || fRmin2 ) + { + tanRMin = (fRmin2 - fRmin1)*0.5/fDz ; + nt1 = t1 - (tanRMin*v.z())*(tanRMin*v.z()) ; + + if ( nt1 ) + { + secRMin = std::sqrt(1.0 + tanRMin*tanRMin) ; + rMinAv = (fRmin1 + fRmin2)*0.5 ; + rin = tanRMin*z + rMinAv ; + nt2 = t2 - tanRMin*v.z()*rin ; + nt3 = t3 - rin*rin ; + + // Equation quadratic => 2 roots : first root must be leaving + + b = nt2/nt1 ; + c = nt3/nt1 ; + d = b*b - c ; + + if ( d >= 0.0 ) + { + // NOTE: should be rho-rin<kRadTolerance*0.5, + // but using squared versions for efficiency + + if (nt3 < kRadTolerance*(rin + kRadTolerance*0.25)) + { + if ( nt2 < 0.0 ) + { + if (calcNorm) { *validNorm = false; } + return snxt = 0.0; + } + } + else + { + if (b>0) { sr2 = -b - std::sqrt(d); } + else { sr2 = c/(-b+std::sqrt(d)); } + zi = z + sr2*v.z() ; + ri = tanRMin*zi + rMinAv ; + + if( (ri>=0.0)&&(-halfRadTolerance<=sr2)&&(sr2<=halfRadTolerance) ) + { + // An intersection within the tolerance + // storing it in case it is good. + + slentol = sr2 ; + sidetol = kRMax ; + } + if( (ri<0) || (sr2 < halfRadTolerance) ) + { + if (b>0) { sr3 = c/(-b-std::sqrt(d)); } + else { sr3 = -b + std::sqrt(d) ; } + + // Safety: if both roots -ve ensure that srd cannot `win' + // distancetoout + + if ( sr3 > halfRadTolerance ) + { + if( sr3 < srd ) + { + zi = z + sr3*v.z() ; + ri = tanRMin*zi + rMinAv ; + + if ( ri >= 0.0 ) + { + srd=sr3 ; + sider=kRMin ; + } + } + } + else if ( sr3 > -halfRadTolerance ) + { + // Intersection in tolerance. Store to check if it's good + + slentol = sr3 ; + sidetol = kRMin ; + } + } + else if ( (sr2 < srd) && (sr2 > halfCarTolerance) ) + { + srd = sr2 ; + sider = kRMin ; + } + else if (sr2 > -halfCarTolerance) + { + // Intersection in tolerance. Store to check if it's good + + slentol = sr2 ; + sidetol = kRMin ; + } + if( slentol <= halfCarTolerance ) + { + // An intersection within the tolerance was found. + // We must accept it only if the momentum points outwards. + + G4ThreeVector Normal ; + + // Calculate a normal vector, as below + + xi = p.x() + slentol*v.x() ; + yi = p.y() + slentol*v.y() ; + if( sidetol==kRMax ) + { + risec = std::sqrt(xi*xi + yi*yi)*secRMax ; + Normal = G4ThreeVector(xi/risec,yi/risec,-tanRMax/secRMax) ; + } + else + { + risec = std::sqrt(xi*xi + yi*yi)*secRMin ; + Normal = G4ThreeVector(-xi/risec,-yi/risec,tanRMin/secRMin) ; + } + if( Normal.dot(v) > 0 ) + { + // We will leave the cone immediately + + if( calcNorm ) + { + *n = Normal.unit() ; + *validNorm = true ; + } + return snxt = 0.0 ; + } + else + { + // On the surface, but not heading out so we ignore this + // intersection (as it is within tolerance). + + slentol = kInfinity ; + } + } + } + } + } + } + + // Linear case => point outside inner cone ---> outer cone intersect + // + // Phi Intersection +/* + if ( !fPhiFullCone ) + { + // add angle calculation with correction + // of the difference in domain of atan2 and Sphi + + vphi = std::atan2(v.y(),v.x()) ; + + if ( vphi < fSPhi - halfAngTolerance ) { vphi += twopi; } + else if ( vphi > fSPhi + fDPhi + halfAngTolerance ) { vphi -= twopi; } + + if ( p.x() || p.y() ) // Check if on z axis (rho not needed later) + { + // pDist -ve when inside + + pDistS = p.x()*sinSPhi - p.y()*cosSPhi ; + pDistE = -p.x()*sinEPhi + p.y()*cosEPhi ; + + // Comp -ve when in direction of outwards normal + + compS = -sinSPhi*v.x() + cosSPhi*v.y() ; + compE = sinEPhi*v.x() - cosEPhi*v.y() ; + + sidephi = kNull ; + + if( ( (fDPhi <= pi) && ( (pDistS <= halfCarTolerance) + && (pDistE <= halfCarTolerance) ) ) + || ( (fDPhi > pi) && !((pDistS > halfCarTolerance) + && (pDistE > halfCarTolerance) ) ) ) + { + // Inside both phi *full* planes + if ( compS < 0 ) + { + sphi = pDistS/compS ; + if (sphi >= -halfCarTolerance) + { + xi = p.x() + sphi*v.x() ; + yi = p.y() + sphi*v.y() ; + + // Check intersecting with correct half-plane + // (if not -> no intersect) + // + if ( (std::fabs(xi)<=kCarTolerance) + && (std::fabs(yi)<=kCarTolerance) ) + { + sidephi= kSPhi; + if ( ( fSPhi-halfAngTolerance <= vphi ) + && ( fSPhi+fDPhi+halfAngTolerance >=vphi ) ) + { + sphi = kInfinity; + } + } + else + if ( (yi*cosCPhi-xi*sinCPhi)>=0 ) + { + sphi = kInfinity ; + } + else + { + sidephi = kSPhi ; + if ( pDistS > -halfCarTolerance ) + { + sphi = 0.0 ; // Leave by sphi immediately + } + } + } + else + { + sphi = kInfinity ; + } + } + else + { + sphi = kInfinity ; + } + + if ( compE < 0 ) + { + sphi2 = pDistE/compE ; + + // Only check further if < starting phi intersection + // + if ( (sphi2 > -halfCarTolerance) && (sphi2 < sphi) ) + { + xi = p.x() + sphi2*v.x() ; + yi = p.y() + sphi2*v.y() ; + + // Check intersecting with correct half-plane + + if ( (std::fabs(xi)<=kCarTolerance) + && (std::fabs(yi)<=kCarTolerance) ) + { + // Leaving via ending phi + + if(!( (fSPhi-halfAngTolerance <= vphi) + && (fSPhi+fDPhi+halfAngTolerance >= vphi) ) ) + { + sidephi = kEPhi ; + if ( pDistE <= -halfCarTolerance ) { sphi = sphi2; } + else { sphi = 0.0; } + } + } + else // Check intersecting with correct half-plane + if ( yi*cosCPhi-xi*sinCPhi >= 0 ) + { + // Leaving via ending phi + + sidephi = kEPhi ; + if ( pDistE <= -halfCarTolerance ) { sphi = sphi2; } + else { sphi = 0.0; } + } + } + } + } + else + { + sphi = kInfinity ; + } + } + else + { + // On z axis + travel not || to z axis -> if phi of vector direction + // within phi of shape, Step limited by rmax, else Step =0 + + if ( (fSPhi-halfAngTolerance <= vphi) + && (vphi <= fSPhi+fDPhi+halfAngTolerance) ) + { + sphi = kInfinity ; + } + else + { + sidephi = kSPhi ; // arbitrary + sphi = 0.0 ; + } + } + if ( sphi < snxt ) // Order intersecttions + { + snxt=sphi ; + side=sidephi ; + } + } +*/ + if ( srd < snxt ) // Order intersections + { + snxt = srd ; + side = sider ; + } + if (calcNorm) + { + switch(side) + { // Note: returned vector not normalised + case kRMax: // (divide by frmax for unit vector) + xi = p.x() + snxt*v.x() ; + yi = p.y() + snxt*v.y() ; + risec = std::sqrt(xi*xi + yi*yi)*secRMax ; + *n = G4ThreeVector(xi/risec,yi/risec,-tanRMax/secRMax) ; + *validNorm = true ; + break ; + case kRMin: + *validNorm = false ; // Rmin is inconvex + break ; +/* case kSPhi: + if ( fDPhi <= pi ) + { + *n = G4ThreeVector(sinSPhi, -cosSPhi, 0); + *validNorm = true ; + } + else + { + *validNorm = false ; + } + break ; + case kEPhi: + if ( fDPhi <= pi ) + { + *n = G4ThreeVector(-sinEPhi, cosEPhi, 0); + *validNorm = true ; + } + else + { + *validNorm = false ; + } + break ;*/ + case kPZ: + *n = G4ThreeVector(0,0,1) ; + *validNorm = true ; + break ; + case kMZ: + *n = G4ThreeVector(0,0,-1) ; + *validNorm = true ; + break ; + default: + G4cout << G4endl ; + DumpInfo(); + std::ostringstream message; + G4int oldprc = message.precision(16) ; + message << "Undefined side for valid surface normal to solid." + << G4endl + << "Position:" << G4endl << G4endl + << "p.x() = " << p.x()/mm << " mm" << G4endl + << "p.y() = " << p.y()/mm << " mm" << G4endl + << "p.z() = " << p.z()/mm << " mm" << G4endl << G4endl + << "pho at z = " << std::sqrt( p.x()*p.x()+p.y()*p.y() )/mm + << " mm" << G4endl << G4endl ; + if( p.x() != 0. || p.y() != 0.) + { + message << "point phi = " << std::atan2(p.y(),p.x())/degree + << " degree" << G4endl << G4endl ; + } + message << "Direction:" << G4endl << G4endl + << "v.x() = " << v.x() << G4endl + << "v.y() = " << v.y() << G4endl + << "v.z() = " << v.z() << G4endl<< G4endl + << "Proposed distance :" << G4endl<< G4endl + << "snxt = " << snxt/mm << " mm" << G4endl ; + message.precision(oldprc) ; + G4Exception("G4ShiftedCone::DistanceToOut(p,v,..)","GeomSolids1002", + JustWarning, message) ; + break ; + } + } + if (snxt < halfCarTolerance) { snxt = 0.; } + + return snxt ; +} + +////////////////////////////////////////////////////////////////// +// +// Calculate distance (<=actual) to closest surface of shape from inside + +G4double G4ShiftedCone::DistanceToOut(const G4ThreeVector& p) const +{ + G4double safe=0.0, rho, safeR1, safeR2, safeZ;//, safePhi; + G4double tanRMin, secRMin, pRMin; + G4double tanRMax, secRMax, pRMax; + +#ifdef G4CSGDEBUG + if( Inside(p) == kOutside ) + { + G4int oldprc=G4cout.precision(16) ; + G4cout << G4endl ; + DumpInfo(); + G4cout << "Position:" << G4endl << G4endl ; + G4cout << "p.x() = " << p.x()/mm << " mm" << G4endl ; + G4cout << "p.y() = " << p.y()/mm << " mm" << G4endl ; + G4cout << "p.z() = " << p.z()/mm << " mm" << G4endl << G4endl ; + G4cout << "pho at z = " << std::sqrt( p.x()*p.x()+p.y()*p.y() )/mm + << " mm" << G4endl << G4endl ; + if( (p.x() != 0.) || (p.x() != 0.) ) + { + G4cout << "point phi = " << std::atan2(p.y(),p.x())/degree + << " degree" << G4endl << G4endl ; + } + G4cout.precision(oldprc) ; + G4Exception("G4ShiftedCone::DistanceToOut(p)", "GeomSolids1002", + JustWarning, "Point p is outside !?" ); + } +#endif + + G4double z = p.z() - fZshift; + + rho = std::sqrt(p.x()*p.x() + p.y()*p.y()) ; + safeZ = fDz - std::fabs(z) ; + + if (fRmin1 || fRmin2) + { + tanRMin = (fRmin2 - fRmin1)*0.5/fDz ; + secRMin = std::sqrt(1.0 + tanRMin*tanRMin) ; + pRMin = tanRMin*z + (fRmin1 + fRmin2)*0.5 ; + safeR1 = (rho - pRMin)/secRMin ; + } + else + { + safeR1 = kInfinity ; + } + + tanRMax = (fRmax2 - fRmax1)*0.5/fDz ; + secRMax = std::sqrt(1.0 + tanRMax*tanRMax) ; + pRMax = tanRMax*z + (fRmax1+fRmax2)*0.5 ; + safeR2 = (pRMax - rho)/secRMax ; + + if (safeR1 < safeR2) { safe = safeR1; } + else { safe = safeR2; } + if (safeZ < safe) { safe = safeZ ; } + + // Check if phi divided, Calc distances closest phi plane +/* + if (!fPhiFullCone) + { + // Above/below central phi of G4ShiftedCone? + + if ( (p.y()*cosCPhi - p.x()*sinCPhi) <= 0 ) + { + safePhi = -(p.x()*sinSPhi - p.y()*cosSPhi) ; + } + else + { + safePhi = (p.x()*sinEPhi - p.y()*cosEPhi) ; + } + if (safePhi < safe) { safe = safePhi; } + }*/ + if ( safe < 0 ) { safe = 0; } + + return safe ; +} + +////////////////////////////////////////////////////////////////////////// +// +// GetEntityType + +G4GeometryType G4ShiftedCone::GetEntityType() const +{ + return G4String("G4ShiftedCone"); +} + +////////////////////////////////////////////////////////////////////////// +// +// Make a clone of the object +// +G4VSolid* G4ShiftedCone::Clone() const +{ + return new G4ShiftedCone(*this); +} + +////////////////////////////////////////////////////////////////////////// +// +// Stream object contents to an output stream + +std::ostream& G4ShiftedCone::StreamInfo(std::ostream& os) const +{ + G4int oldprc = os.precision(16); + os << "-----------------------------------------------------------\n" + << " *** Dump for solid - " << GetName() << " ***\n" + << " ===================================================\n" + << " Solid type: G4ShiftedCone\n" + << " Parameters: \n" + << " inside -fDz radius: " << fRmin1/mm << " mm \n" + << " outside -fDz radius: " << fRmax1/mm << " mm \n" + << " inside +fDz radius: " << fRmin2/mm << " mm \n" + << " outside +fDz radius: " << fRmax2/mm << " mm \n" + << " Z1 : " << GetZ1()/mm << " mm \n" + << " Z2 : " << GetZ2()/mm << " mm \n" +// << " starting angle of segment: " << fSPhi/degree << " degrees \n" +// << " delta angle of segment : " << fDPhi/degree << " degrees \n" + << "-----------------------------------------------------------\n"; + os.precision(oldprc); + + return os; +} + + + +///////////////////////////////////////////////////////////////////////// +// +// GetPointOnSurface + +G4ThreeVector G4ShiftedCone::GetPointOnSurface() const +{ + // declare working variables + // + G4double rone = (fRmax1-fRmax2)/(2.*fDz); + G4double rtwo = (fRmin1-fRmin2)/(2.*fDz); + G4double qone = (fRmax1 == fRmax2) ? 0. : fDz*(fRmax1+fRmax2)/(fRmax1-fRmax2); + G4double qtwo = (fRmin1 == fRmin2) ? 0. : fDz*(fRmin1+fRmin2)/(fRmin1-fRmin2); + + G4double slin = std::hypot(fRmin1-fRmin2, 2.*fDz); + G4double slout = std::hypot(fRmax1-fRmax2, 2.*fDz); + G4double Aone = 0.5*GetDeltaPhiAngle()*(fRmax2 + fRmax1)*slout; // outer surface + G4double Atwo = 0.5*GetDeltaPhiAngle()*(fRmin2 + fRmin1)*slin; // inner surface + G4double Athree = 0.5*GetDeltaPhiAngle()*(fRmax1*fRmax1-fRmin1*fRmin1); // base at -Dz + G4double Afour = 0.5*GetDeltaPhiAngle()*(fRmax2*fRmax2-fRmin2*fRmin2); // base at +Dz + G4double Afive = fDz*(fRmax1-fRmin1+fRmax2-fRmin2); // phi section + + G4double phi = G4RandFlat::shoot(GetStartPhiAngle(),GetStartPhiAngle() + GetDeltaPhiAngle()); + G4double cosu = std::cos(phi); + G4double sinu = std::sin(phi); + G4double rRand1 = GetRadiusInRing(fRmin1, fRmax1); + G4double rRand2 = GetRadiusInRing(fRmin2, fRmax2); + + G4bool fPhiFullCone = true; + if ( (GetStartPhiAngle() == 0.) && fPhiFullCone ) { Afive = 0.; } + G4double chose = G4RandFlat::shoot(0.,Aone+Atwo+Athree+Afour+2.*Afive); + + if( (chose >= 0.) && (chose < Aone) ) // outer surface + { + if(fRmax1 != fRmax2) + { + G4double zRand = G4RandFlat::shoot(-1.*fDz,fDz); + return G4ThreeVector (rone*cosu*(qone-zRand), + rone*sinu*(qone-zRand), zRand + fZshift); + } + else + { + return G4ThreeVector(fRmax1*cosu, fRmax2*sinu, + G4RandFlat::shoot(-1.*fDz,fDz) + fZshift); + } + } + else if( (chose >= Aone) && (chose < Aone + Atwo) ) // inner surface + { + if(fRmin1 != fRmin2) + { + G4double zRand = G4RandFlat::shoot(-1.*fDz,fDz); + return G4ThreeVector (rtwo*cosu*(qtwo-zRand), + rtwo*sinu*(qtwo-zRand), zRand + fZshift); + } + else + { + return G4ThreeVector(fRmin1*cosu, fRmin2*sinu, + G4RandFlat::shoot(-1.*fDz,fDz) + fZshift); + } + } + else if( (chose >= Aone + Atwo) && (chose < Aone + Atwo + Athree) ) // base at -Dz + { + return G4ThreeVector (rRand1*cosu, rRand1*sinu, -1*fDz + fZshift); + } + else if( (chose >= Aone + Atwo + Athree) + && (chose < Aone + Atwo + Athree + Afour) ) // base at +Dz + { + return G4ThreeVector (rRand2*cosu,rRand2*sinu,fDz + fZshift); + } + else if( (chose >= Aone + Atwo + Athree + Afour) // SPhi section + && (chose < Aone + Atwo + Athree + Afour + Afive) ) + { + G4double zRand = G4RandFlat::shoot(-1.*fDz,fDz); + rRand1 = G4RandFlat::shoot(fRmin2-((zRand-fDz)/(2.*fDz))*(fRmin1-fRmin2), + fRmax2-((zRand-fDz)/(2.*fDz))*(fRmax1-fRmax2)); + return G4ThreeVector (rRand1*GetCosStartPhi(), + rRand1*GetSinStartPhi(), zRand + fZshift); + } + else // SPhi+DPhi section + { + G4double zRand = G4RandFlat::shoot(-1.*fDz,fDz); + rRand1 = G4RandFlat::shoot(fRmin2-((zRand-fDz)/(2.*fDz))*(fRmin1-fRmin2), + fRmax2-((zRand-fDz)/(2.*fDz))*(fRmax1-fRmax2)); + return G4ThreeVector (rRand1*GetCosEndPhi(), + rRand1*GetSinEndPhi(), zRand + fZshift); + } +} + +////////////////////////////////////////////////////////////////////////// +// +// Methods for visualisation + +void G4ShiftedCone::DescribeYourselfTo (G4VGraphicsScene& scene) const +{ + scene.AddSolid (*this); +} + +G4Polyhedron* G4ShiftedCone::CreatePolyhedron () const +{ + G4double rmin[2] = { GetRmin1(), GetRmin2() }; + G4double rmax[2] = { GetRmax1(), GetRmax2() }; + G4double z[2] = { GetZ1(), GetZ2() }; + return new G4PolyhedronPcon( + GetStartPhiAngle(), GetDeltaPhiAngle(), 2, z, rmin, rmax + ); +} diff --git a/Simulation/G4Utilities/Geo2G4/src/G4ShiftedCone.h b/Simulation/G4Utilities/Geo2G4/src/G4ShiftedCone.h new file mode 100644 index 000000000..8107ba934 --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/G4ShiftedCone.h @@ -0,0 +1,247 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +// +// The G4ShiftedCone class copied from standard G4Cons and modified to: +// 1) have an arbitrary position along Z axis, +// 2) represent a twopi-cone. Sectors are not supported but the +// corresponding code kept and just commented out. +// + +// +// ******************************************************************** +// * License and Disclaimer * +// * * +// * The Geant4 software is copyright of the Copyright Holders of * +// * the Geant4 Collaboration. It is provided under the terms and * +// * conditions of the Geant4 Software License, included in the file * +// * LICENSE and available at http://cern.ch/geant4/license . These * +// * include a list of copyright holders. * +// * * +// * Neither the authors of this software system, nor their employing * +// * institutes,nor the agencies providing financial support for this * +// * work make any representation or warranty, express or implied, * +// * regarding this software system or assume any liability for its * +// * use. Please see the license in the file LICENSE and URL above * +// * for the full disclaimer and the limitation of liability. * +// * * +// * This code implementation is the result of the scientific and * +// * technical work of the GEANT4 collaboration. * +// * By using, copying, modifying or distributing the software (or * +// * any work based on the software) you agree to acknowledge its * +// * use in resulting scientific publications, and indicate your * +// * acceptance of all terms of the Geant4 Software license. * +// ******************************************************************** +// +// +// +// +// -------------------------------------------------------------------- +// GEANT 4 class header file +// +// G4ShiftedCone +// +// Class description: +// +// A G4ShiftedCone is, in the general case, a Phi segment of a cone, +// inner and outer radii specified at z1 and z2. +// This version does not support phi segmetation, but the code is kept +// in case it would be necessary later. +// The Phi segment is described by a starting fSPhi angle, and the +// +fDPhi delta angle for the shape. +// If the delta angle is >=2*pi, the shape is treated as continuous +// in Phi +// +// Member Data: +// +// fRmin1 inside radius at z1 +// fRmin2 inside radius at z2 +// fRmax1 outside radius at z1 +// fRmax2 outside radius at z2 +// fDz half length in z +// +// fSPhi starting angle of the segment in radians +// fDPhi delta angle of the segment in radians +// +// fPhiFullCone Boolean variable used for indicate the Phi Section +// always true in the current version, hope compiler optimize +// +// Note: +// Internally fSPhi & fDPhi are adjusted so that fDPhi<=2PI, +// and fDPhi+fSPhi<=2PI. This enables simpler comparisons to be +// made with (say) Phi of a point. + +// History: +// 03.07.2019 A. Sukharev copied from G4Cons for ATLAS EMEC needs +// -------------------------------------------------------------------- +#ifndef G4ShiftedCone_HH +#define G4ShiftedCone_HH + +#include <CLHEP/Units/PhysicalConstants.h> + +#include "G4CSGSolid.hh" +#include "G4Polyhedron.hh" + +class G4ShiftedCone : public G4CSGSolid +{ + public: // with description + + G4ShiftedCone(const G4String& pName, + G4double pZ1, G4double pZ2, + G4double pRmin1, G4double pRmax1, + G4double pRmin2, G4double pRmax2); + // G4double pSPhi, G4double pDPhi); + // + // Constructs a cone with the given name and dimensions + + ~G4ShiftedCone() ; + // + // Destructor + + // Accessors + + inline G4double GetInnerRadiusMinusZ() const; + inline G4double GetOuterRadiusMinusZ() const; + inline G4double GetInnerRadiusPlusZ() const; + inline G4double GetOuterRadiusPlusZ() const; + inline G4double GetZHalfLength() const; + inline G4double GetZ1() const; + inline G4double GetZ2() const; + inline G4double GetStartPhiAngle() const; + inline G4double GetDeltaPhiAngle() const; + inline G4double GetSinStartPhi() const; + inline G4double GetCosStartPhi() const; + inline G4double GetSinEndPhi() const; + inline G4double GetCosEndPhi() const; + + // Modifiers + + inline void SetInnerRadiusMinusZ (G4double Rmin1 ); + inline void SetOuterRadiusMinusZ (G4double Rmax1 ); + inline void SetInnerRadiusPlusZ (G4double Rmin2 ); + inline void SetOuterRadiusPlusZ (G4double Rmax2 ); +// inline void SetStartPhiAngle (G4double newSPhi, G4bool trig=true); +// inline void SetDeltaPhiAngle (G4double newDPhi); + + // Other methods for solid + + inline G4double GetCubicVolume(); + inline G4double GetSurfaceArea(); + + void ComputeDimensions( G4VPVParameterisation* p, + const G4int n, + const G4VPhysicalVolume* pRep ); + + void BoundingLimits(G4ThreeVector& pMin, G4ThreeVector& pMax) const; + + G4bool CalculateExtent( const EAxis pAxis, + const G4VoxelLimits& pVoxelLimit, + const G4AffineTransform& pTransform, + G4double& pMin, G4double& pMax ) const; + + EInside Inside( const G4ThreeVector& p ) const; + + G4ThreeVector SurfaceNormal( const G4ThreeVector& p ) const; + + G4double DistanceToIn (const G4ThreeVector& p, + const G4ThreeVector& v) const; + G4double DistanceToIn (const G4ThreeVector& p) const; + G4double DistanceToOut(const G4ThreeVector& p, + const G4ThreeVector& v, + const G4bool calcNorm=G4bool(false), + G4bool *validNorm=0, + G4ThreeVector *n=0) const; + G4double DistanceToOut(const G4ThreeVector& p) const; + + G4GeometryType GetEntityType() const; + + G4ThreeVector GetPointOnSurface() const; + + G4VSolid* Clone() const; + + std::ostream& StreamInfo(std::ostream& os) const; + + // Visualisation functions + + void DescribeYourselfTo( G4VGraphicsScene& scene ) const; + G4Polyhedron* CreatePolyhedron() const; + + public: // without description + + G4ShiftedCone(__void__&); + // + // Fake default constructor for usage restricted to direct object + // persistency for clients requiring preallocation of memory for + // persistifiable objects. + + G4ShiftedCone(const G4ShiftedCone& rhs); + G4ShiftedCone& operator=(const G4ShiftedCone& rhs); + // Copy constructor and assignment operator. + + // Old access functions + + inline G4double GetRmin1() const; + inline G4double GetRmax1() const; + inline G4double GetRmin2() const; + inline G4double GetRmax2() const; +// inline G4double GetSPhi() const; +// inline G4double GetDPhi() const; + + private: + + inline void Initialize(); + // + // Reset relevant values to zero + +// inline void CheckSPhiAngle(G4double sPhi); +// inline void CheckDPhiAngle(G4double dPhi); +// inline void CheckPhiAngles(G4double sPhi, G4double dPhi); + // + // Reset relevant flags and angle values + + inline void InitializeTrigonometry(); + // + // Recompute relevant trigonometric values and cache them + + G4ThreeVector ApproxSurfaceNormal(const G4ThreeVector& p) const; + // + // Algorithm for SurfaceNormal() following the original + // specification for points not on the surface + + private: + + // Used by distanceToOut + // + enum ESide {kNull,kRMin,kRMax,kSPhi,kEPhi,kPZ,kMZ}; + + // used by normal + // + enum ENorm {kNRMin,kNRMax,kNSPhi,kNEPhi,kNZ}; + + G4double kRadTolerance, kAngTolerance; + // + // Radial and angular tolerances + + G4double fRmin1, fRmin2, fRmax1, fRmax2; + G4double fDz, fZshift;//, fSPhi, fDPhi; + // + // Radial and angular dimensions + +// G4double sinCPhi, cosCPhi, cosHDPhiOT, cosHDPhiIT, +// sinSPhi, cosSPhi, sinEPhi, cosEPhi; + // + // Cached trigonometric values + +// const G4bool fPhiFullCone; + // + // Flag for identification of section or full cone + + G4double halfCarTolerance, halfRadTolerance, halfAngTolerance; + // + // Cached half tolerance values +}; + +#include "G4ShiftedCone.icc" + +#endif diff --git a/Simulation/G4Utilities/Geo2G4/src/G4ShiftedCone.icc b/Simulation/G4Utilities/Geo2G4/src/G4ShiftedCone.icc new file mode 100644 index 000000000..1d78d1118 --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/G4ShiftedCone.icc @@ -0,0 +1,337 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +// +// ******************************************************************** +// * License and Disclaimer * +// * * +// * The Geant4 software is copyright of the Copyright Holders of * +// * the Geant4 Collaboration. It is provided under the terms and * +// * conditions of the Geant4 Software License, included in the file * +// * LICENSE and available at http://cern.ch/geant4/license . These * +// * include a list of copyright holders. * +// * * +// * Neither the authors of this software system, nor their employing * +// * institutes,nor the agencies providing financial support for this * +// * work make any representation or warranty, express or implied, * +// * regarding this software system or assume any liability for its * +// * use. Please see the license in the file LICENSE and URL above * +// * for the full disclaimer and the limitation of liability. * +// * * +// * This code implementation is the result of the scientific and * +// * technical work of the GEANT4 collaboration. * +// * By using, copying, modifying or distributing the software (or * +// * any work based on the software) you agree to acknowledge its * +// * use in resulting scientific publications, and indicate your * +// * acceptance of all terms of the Geant4 Software license. * +// ******************************************************************** +// +// +// +// -------------------------------------------------------------------- +// GEANT 4 inline definitions file +// +// G4ShiftedCone.icc +// +// Implementation of inline methods of G4ShiftedCone +// -------------------------------------------------------------------- + +inline +G4double G4ShiftedCone::GetInnerRadiusMinusZ() const +{ + return fRmin1 ; +} + +inline +G4double G4ShiftedCone::GetOuterRadiusMinusZ() const +{ + return fRmax1 ; +} + +inline +G4double G4ShiftedCone::GetInnerRadiusPlusZ() const +{ + return fRmin2 ; +} + +inline +G4double G4ShiftedCone::GetOuterRadiusPlusZ() const +{ + return fRmax2 ; +} + +inline +G4double G4ShiftedCone::GetZHalfLength() const +{ + return fDz ; +} + +inline +G4double G4ShiftedCone::GetZ1() const +{ + return fZshift - fDz ; +} + +inline +G4double G4ShiftedCone::GetZ2() const +{ + return fZshift + fDz ; +} + +inline +G4double G4ShiftedCone::GetStartPhiAngle() const +{ + return 0.; // fSPhi ; +} + +inline +G4double G4ShiftedCone::GetDeltaPhiAngle() const +{ + return CLHEP::twopi; //fDPhi; +} + +inline +G4double G4ShiftedCone::GetSinStartPhi() const +{ + return 0.; //sinSPhi; +} + +inline +G4double G4ShiftedCone::GetCosStartPhi() const +{ + return 1.;// cosSPhi; +} + +inline +G4double G4ShiftedCone::GetSinEndPhi() const +{ + return 0.;// sinEPhi; +} + +inline +G4double G4ShiftedCone::GetCosEndPhi() const +{ + return 1.;//cosEPhi; +} + +inline +void G4ShiftedCone::Initialize() +{ + fCubicVolume = 0.; + fSurfaceArea = 0.; + fRebuildPolyhedron = true; +} + +/* +inline +void G4ShiftedCone::InitializeTrigonometry() +{ + G4double hDPhi = 0.5*fDPhi; // half delta phi + G4double cPhi = fSPhi + hDPhi; + G4double ePhi = fSPhi + fDPhi; + + sinCPhi = std::sin(cPhi); + cosCPhi = std::cos(cPhi); + cosHDPhiIT = std::cos(hDPhi - 0.5*kAngTolerance); // inner/outer tol half dphi + cosHDPhiOT = std::cos(hDPhi + 0.5*kAngTolerance); + sinSPhi = std::sin(fSPhi); + cosSPhi = std::cos(fSPhi); + sinEPhi = std::sin(ePhi); + cosEPhi = std::cos(ePhi); +} + +inline void G4ShiftedCone::CheckSPhiAngle(G4double sPhi) +{ + // Ensure fSphi in 0-2PI or -2PI-0 range if shape crosses 0 + + if ( sPhi < 0 ) + { + fSPhi = CLHEP::twopi - std::fmod(std::fabs(sPhi),CLHEP::twopi); + } + else + { + fSPhi = std::fmod(sPhi,CLHEP::twopi) ; + } + if ( fSPhi+fDPhi > CLHEP::twopi ) + { + fSPhi -= CLHEP::twopi ; + } +} + +inline void G4ShiftedCone::CheckDPhiAngle(G4double dPhi) +{ + fPhiFullCone = true; + if ( dPhi >= CLHEP::twopi-kAngTolerance*0.5 ) + { + fDPhi=CLHEP::twopi; + fSPhi=0; + } + else + { + fPhiFullCone = false; + if ( dPhi > 0 ) + { + fDPhi = dPhi; + } + else + { + std::ostringstream message; + message << "Invalid dphi." << G4endl + << "Negative or zero delta-Phi (" << dPhi << ") in solid: " + << GetName(); + G4Exception("G4ShiftedCone::CheckDPhiAngle()", "GeomSolids0002", + FatalException, message); + } + } +} + +inline void G4ShiftedCone::CheckPhiAngles(G4double sPhi, G4double dPhi) +{ + CheckDPhiAngle(dPhi); + if ( (fDPhi<CLHEP::twopi) && (sPhi) ) { CheckSPhiAngle(sPhi); } + InitializeTrigonometry(); +} +*/ + +inline +void G4ShiftedCone::SetInnerRadiusMinusZ( G4double Rmin1 ) +{ + fRmin1= Rmin1 ; + Initialize(); +} + +inline +void G4ShiftedCone::SetOuterRadiusMinusZ( G4double Rmax1 ) +{ + fRmax1= Rmax1 ; + Initialize(); +} + +inline +void G4ShiftedCone::SetInnerRadiusPlusZ ( G4double Rmin2 ) +{ + fRmin2= Rmin2 ; + Initialize(); +} + +inline +void G4ShiftedCone::SetOuterRadiusPlusZ ( G4double Rmax2 ) +{ + fRmax2= Rmax2 ; + Initialize(); +} + +/*inline +void G4ShiftedCone::SetZHalfLength ( G4double newDz ) +{ + fDz= newDz ; + Initialize(); +}*/ + +/* +inline +void G4ShiftedCone::SetStartPhiAngle ( G4double newSPhi, G4bool compute ) +{ + // Flag 'compute' can be used to explicitely avoid recomputation of + // trigonometry in case SetDeltaPhiAngle() is invoked afterwards + + CheckSPhiAngle(newSPhi); + fPhiFullCone = false; + if (compute) { InitializeTrigonometry(); } + Initialize(); +} + +void G4ShiftedCone::SetDeltaPhiAngle ( G4double newDPhi ) +{ + CheckPhiAngles(fSPhi, newDPhi); + Initialize(); +} +*/ +// Old access methods ... + +inline +G4double G4ShiftedCone::GetRmin1() const +{ + return GetInnerRadiusMinusZ(); +} + +inline +G4double G4ShiftedCone::GetRmax1() const +{ + return GetOuterRadiusMinusZ(); +} + +inline +G4double G4ShiftedCone::GetRmin2() const +{ + return GetInnerRadiusPlusZ(); +} + +inline +G4double G4ShiftedCone::GetRmax2() const +{ + return GetOuterRadiusPlusZ(); +} +/* +inline +G4double G4ShiftedCone::GetDz() const +{ + return GetZHalfLength(); +} + +inline +G4double G4ShiftedCone::GetSPhi() const +{ + return GetStartPhiAngle(); +} + +inline +G4double G4ShiftedCone::GetDPhi() const +{ + return GetDeltaPhiAngle(); +} +*/ +inline +G4double G4ShiftedCone::GetCubicVolume() +{ + if(fCubicVolume != 0.) {;} + else + { + G4double Rmean, rMean, deltaR, deltar; + + Rmean = 0.5*(fRmax1+fRmax2); + deltaR = fRmax1-fRmax2; + + rMean = 0.5*(fRmin1+fRmin2); + deltar = fRmin1-fRmin2; + fCubicVolume = GetDeltaPhiAngle()*fDz*(Rmean*Rmean-rMean*rMean + +(deltaR*deltaR-deltar*deltar)/12); + } + return fCubicVolume; +} + +inline +G4double G4ShiftedCone::GetSurfaceArea() +{ + if(fSurfaceArea != 0.) {;} + else + { + G4double mmin, mmax, dmin, dmax; + + mmin= (fRmin1+fRmin2)*0.5; + mmax= (fRmax1+fRmax2)*0.5; + dmin= (fRmin2-fRmin1); + dmax= (fRmax2-fRmax1); + + fSurfaceArea = GetDeltaPhiAngle()*( mmin * std::sqrt(dmin*dmin+4*fDz*fDz) + + mmax * std::sqrt(dmax*dmax+4*fDz*fDz) + + 0.5*(fRmax1*fRmax1-fRmin1*fRmin1 + +fRmax2*fRmax2-fRmin2*fRmin2 )); +/* if(!fPhiFullCone) + { + fSurfaceArea = fSurfaceArea+4*fDz*(mmax-mmin); + }*/ + } + return fSurfaceArea; +} diff --git a/Simulation/G4Utilities/Geo2G4/src/GDMLDetectorTool.cxx b/Simulation/G4Utilities/Geo2G4/src/GDMLDetectorTool.cxx new file mode 100644 index 000000000..f484943eb --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/GDMLDetectorTool.cxx @@ -0,0 +1,86 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// Base class +#include "G4AtlasTools/DetectorGeometryBase.h" +#include "GDMLDetectorTool.h" + +#include "G4GDMLParser.hh" +#include "G4NistManager.hh" +#include "G4LogicalVolume.hh" +#include "G4PVPlacement.hh" + +// Geant4 includes used in functions + +GDMLDetectorTool::GDMLDetectorTool(const std::string& type, const std::string& name, const IInterface* parent) + : DetectorGeometryBase(type,name,parent),m_GDMLFileName(""),m_blGetTopTransform(true),m_geoDetectorName("") +{ + m_topTransform.setIdentity(); + ATH_MSG_DEBUG( "GDMLDetectorTool constructor for " << name ); + declareProperty("GeoDetectorName",m_geoDetectorName, "Name of the detector in GeoModel, if different from G4."); + declareProperty("GDMLFileName",m_GDMLFileName,"Name of the GDML file to be used as input."); + +} + +StatusCode GDMLDetectorTool::initialize() +{ + ATH_MSG_DEBUG( name() << " GDMLDetectorTool::initialize(): Starting" ); + + if(m_detectorName.empty()) + { + m_detectorName = this->name(); + // re-initialize m_detectorName in order to take the real detector name rather than the path to it + size_t ipos=m_detectorName.find_last_of("."); + size_t length=m_detectorName.size(); + if (ipos<length) + { + ATH_MSG_DEBUG( "m_detectorName: " << m_detectorName << " needs to be reset."); + m_detectorName=m_detectorName.substr(ipos+1,length-ipos-1); + ATH_MSG_DEBUG( "m_detectorName default value reset to " << m_detectorName); + } + } + ATH_MSG_DEBUG( name() << "GDMLDetectorTool::initialize() : Detector name = " << m_detectorName<<" File name: "<<m_GDMLFileName ); + if(m_geoDetectorName.empty()) + { + m_geoDetectorName = m_detectorName; + } + if(m_GDMLFileName.empty()) + { + m_GDMLFileName = m_detectorName+".gdml"; + } + ATH_MSG_DEBUG( name() << "GDMLDetectorTool::initialize() : Geo Detector name = " << m_geoDetectorName<<" File name: "<<m_GDMLFileName ); + + ATH_MSG_DEBUG( name() << " GDMLDetectorTool::initialize(): Finished" ); + return StatusCode::SUCCESS; +} + + +void GDMLDetectorTool::BuildGeometry() +{ + ATH_MSG_VERBOSE( name() << " GDMLDetectorTool::BuildGeometry(): Starting" ); + + G4GDMLParser parser; + parser.Read(m_GDMLFileName.c_str(),false); + m_envelope.theEnvelope=parser.GetWorldVolume()->GetLogicalVolume(); + + ATH_MSG_VERBOSE( name() << " GDMLDetectorTool::BuildGeometry(): Finished" ); +} + +bool GDMLDetectorTool::IsTopTransform() +{ + return m_blGetTopTransform; +} + +void GDMLDetectorTool::SetInitialTransformation() +{ + ATH_MSG_VERBOSE( name() << " GDMLDetectorTool::SetInitialTransformation(): Starting" ); + if (!m_envelope.theRotation) + { + ATH_MSG_VERBOSE( name() << " GDMLDetectorTool::SetInitialTransformation(): Creating new G4RotationMatrix" ); + m_envelope.theRotation=new G4RotationMatrix; + } + *(m_envelope.theRotation)=m_topTransform.getRotation().inverse(); + m_envelope.thePosition=m_topTransform.getTranslation(); + ATH_MSG_VERBOSE( name() << " GDMLDetectorTool::SetInitialTransformation(): Finished" ); +} diff --git a/Simulation/G4Utilities/Geo2G4/src/GDMLDetectorTool.h b/Simulation/G4Utilities/Geo2G4/src/GDMLDetectorTool.h new file mode 100644 index 000000000..36e719de6 --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/GDMLDetectorTool.h @@ -0,0 +1,53 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef GEO2G4_GDMLDetectorTool_H +#define GEO2G4_GDMLDetectorTool_H + +// Base classes +#include "G4AtlasTools/DetectorGeometryBase.h" +#include "G4AtlasInterfaces/IDetectorGeometrySvc.h" + +#include "G4Transform3D.hh" + +// Members + +// STL library +#include <string> +#include <vector> + +/** @class GDMLDetectorTool + * + * Tool for building detectors out of a GDML description. + * + * @author Andrea Dell'Acqua + * @date 2017-02-21 + */ + +class GDMLDetectorTool final : public DetectorGeometryBase +{ + public: + // Basic constructor and destructor + GDMLDetectorTool(const std::string& type, const std::string& name, const IInterface *parent); + ~GDMLDetectorTool() {} + + /** Athena method. called at initialization time, being customized here */ + virtual StatusCode initialize() override final; + + /** virtual methods being implemented here */ + + virtual void BuildGeometry() override final; + + private: + + std::string m_GDMLFileName; + std::string m_builderName; + bool m_blGetTopTransform; + G4Transform3D m_topTransform; + std::string m_geoDetectorName; + bool IsTopTransform(); + void SetInitialTransformation(); +}; + +#endif // GEO2G4_GDMLDetectorTool_H diff --git a/Simulation/G4Utilities/Geo2G4/src/Geo2G4AssemblyFactory.cxx b/Simulation/G4Utilities/Geo2G4/src/Geo2G4AssemblyFactory.cxx new file mode 100644 index 000000000..631bbf145 --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/Geo2G4AssemblyFactory.cxx @@ -0,0 +1,41 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "Geo2G4AssemblyFactory.h" +#include "Geo2G4AssemblyVolume.h" + +#include "GeoModelKernel/GeoLogVol.h" +#include "GeoModelKernel/GeoVPhysVol.h" + +#include <iostream> + +Geo2G4AssemblyFactory::Geo2G4AssemblyFactory() +{ +} + +Geo2G4AssemblyVolume* Geo2G4AssemblyFactory::Build(const PVConstLink thePhys, + bool& descend) +{ + const GeoLogVol* theLog = thePhys->getLogVol(); + + // Check if the assembly was used in GeoModel as a leaf node + if(thePhys->getNChildVols() == 0) + throw std::runtime_error(std::string("In GeoModel description the assembly ") + theLog->getName() + + std::string(" has no children!")); + + descend = true; + + // Search for the assembly in the map + auto it = m_assemblyMap.find(&(*thePhys)); + if(it == m_assemblyMap.end()) + { + auto pair = m_assemblyMap.emplace(&(*thePhys), std::make_unique<Geo2G4AssemblyVolume> ()); + return pair.first->second.get(); + } + else + { + descend = false; + return it->second.get(); + } +} diff --git a/Simulation/G4Utilities/Geo2G4/src/Geo2G4AssemblyFactory.h b/Simulation/G4Utilities/Geo2G4/src/Geo2G4AssemblyFactory.h new file mode 100644 index 000000000..16c935612 --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/Geo2G4AssemblyFactory.h @@ -0,0 +1,27 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef GEO2G4_Geo2G4AssemblyFactory_h +#define GEO2G4_Geo2G4AssemblyFactory_h + +#include "GeoModelKernel/GeoVPhysVol.h" +#include "Geo2G4AssemblyFactory.h" + +#include <map> +#include <memory> + +class Geo2G4AssemblyVolume; + +class Geo2G4AssemblyFactory +{ + public: + Geo2G4AssemblyFactory(); + Geo2G4AssemblyVolume* Build(const PVConstLink thePhys, + bool& descend); + + private: + std::map<const GeoVPhysVol*, std::unique_ptr<Geo2G4AssemblyVolume>, std::less<const GeoVPhysVol*> > m_assemblyMap; +}; + +#endif diff --git a/Simulation/G4Utilities/Geo2G4/src/Geo2G4AssemblyTriplet.h b/Simulation/G4Utilities/Geo2G4/src/Geo2G4AssemblyTriplet.h new file mode 100644 index 000000000..a7ba9be6c --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/Geo2G4AssemblyTriplet.h @@ -0,0 +1,218 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef GEO2G4_ASSEMBLYTRIPLET_H +#define GEO2G4_ASSEMBLYTRIPLET_H + +#include "G4ThreeVector.hh" +#include "G4RotationMatrix.hh" + +class G4LogicalVolume; +class Geo2G4AssemblyVolume; + +class Geo2G4AssemblyTriplet +{ + public: // with description + + Geo2G4AssemblyTriplet(); + // Default constructor + + Geo2G4AssemblyTriplet( G4LogicalVolume* pVolume, + G4ThreeVector& translation, + G4RotationMatrix* pRotation, + G4bool isReflection = false); + // An explicit constructor for a logical volume + + Geo2G4AssemblyTriplet( Geo2G4AssemblyVolume* pAssembly, + G4ThreeVector& translation, + G4RotationMatrix* pRotation, + G4bool isReflection = false); + // An explicit constructor for an assembly volume + + Geo2G4AssemblyTriplet( const Geo2G4AssemblyTriplet& second ); + // Copy constructor + + ~Geo2G4AssemblyTriplet(); + // Destructor + + Geo2G4AssemblyTriplet& operator=( const Geo2G4AssemblyTriplet& second ); + // Assignment operator + + G4LogicalVolume* GetVolume() const; + // Retrieve the logical volume reference + + void SetVolume( G4LogicalVolume* pVolume ); + // Update the logical volume reference + + Geo2G4AssemblyVolume* GetAssembly() const; + // Retrieve the assembly volume reference + + void SetAssembly( Geo2G4AssemblyVolume* pAssembly ); + // Update the assembly volume reference + + G4ThreeVector GetTranslation() const; + // Retrieve the logical volume translation + + void SetTranslation( G4ThreeVector& pVolume ); + // Update the logical volume translation + + G4RotationMatrix* GetRotation() const; + // Retrieve the logical volume rotation + + void SetRotation( G4RotationMatrix* pVolume ); + // Update the logical volume rotation + + G4bool IsReflection() const; + // Return true if the logical or assembly volume has reflection + + private: + + G4LogicalVolume* m_volume; + // A logical volume + + G4ThreeVector m_translation; + // A logical volume translation + + G4RotationMatrix* m_rotation; + // A logical volume rotation + + private: + + // Member data for handling assemblies of assemblies and reflections + + Geo2G4AssemblyVolume* m_assembly; + // An assembly volume + + G4bool m_isReflection; + // True if the logical or assembly volume has reflection +}; + +inline +Geo2G4AssemblyTriplet::Geo2G4AssemblyTriplet() + : m_volume( 0 ), m_rotation( 0 ), m_assembly(0), m_isReflection(false) +{ + G4ThreeVector v(0.,0.,0.); + m_translation = v; +} + +inline +Geo2G4AssemblyTriplet::Geo2G4AssemblyTriplet( G4LogicalVolume* pVolume, + G4ThreeVector& translation, + G4RotationMatrix* pRotation, + G4bool isReflection ) + : m_volume( pVolume ), m_translation( translation ), m_rotation( pRotation ), + m_assembly( 0 ), m_isReflection(isReflection) +{ +} + +inline +Geo2G4AssemblyTriplet::Geo2G4AssemblyTriplet( Geo2G4AssemblyVolume* pAssembly, + G4ThreeVector& translation, + G4RotationMatrix* pRotation, + G4bool isReflection ) + : m_volume( 0 ), m_translation( translation ), m_rotation( pRotation ), + m_assembly( pAssembly ), m_isReflection(isReflection) +{ +} + +inline +Geo2G4AssemblyTriplet::Geo2G4AssemblyTriplet( const Geo2G4AssemblyTriplet& second ) +{ + m_volume = second.GetVolume(); + m_rotation = second.GetRotation(); + m_translation = second.GetTranslation(); + m_assembly = second.GetAssembly(); + m_isReflection = second.IsReflection(); +} + +inline +Geo2G4AssemblyTriplet::~Geo2G4AssemblyTriplet() +{ +} + +inline +G4LogicalVolume* Geo2G4AssemblyTriplet::GetVolume() const +{ + return m_volume; +} + +inline +void Geo2G4AssemblyTriplet::SetVolume( G4LogicalVolume* pVolume ) +{ + if ( m_assembly ) + { + G4Exception("Geo2G4AssemblyTriplet::SetVolume()", + "IllegalCall", JustWarning, + "There is an assembly already set, it will be ignored."); + } + m_volume = pVolume; + m_assembly = 0; +} + +inline +Geo2G4AssemblyVolume* Geo2G4AssemblyTriplet::GetAssembly() const +{ + return m_assembly; +} + +inline +void Geo2G4AssemblyTriplet::SetAssembly( Geo2G4AssemblyVolume* pAssembly ) +{ + if ( m_volume ) + { + G4Exception("Geo2G4AssemblyTriplet::SetAssembly()", + "IllegalCall", JustWarning, + "There is a volume already set, it will be ignored."); + } + m_assembly = pAssembly; + m_volume = 0; +} + +inline +G4ThreeVector Geo2G4AssemblyTriplet::GetTranslation() const +{ + return m_translation; +} + +inline +void Geo2G4AssemblyTriplet::SetTranslation( G4ThreeVector& translation ) +{ + m_translation = translation; +} + +inline +G4RotationMatrix* Geo2G4AssemblyTriplet::GetRotation() const +{ + return m_rotation; +} + +inline +void Geo2G4AssemblyTriplet::SetRotation( G4RotationMatrix* pRotation ) +{ + m_rotation = pRotation; +} + +inline +G4bool Geo2G4AssemblyTriplet::IsReflection() const +{ + return m_isReflection; +} + +inline +Geo2G4AssemblyTriplet& +Geo2G4AssemblyTriplet::operator=( const Geo2G4AssemblyTriplet& second ) +{ + if( this != &second ) + { + m_volume = second.GetVolume(); + m_rotation = second.GetRotation(); + m_translation = second.GetTranslation(); + m_assembly = second.GetAssembly(); + m_isReflection = second.IsReflection(); + } + + return *this; +} + +#endif diff --git a/Simulation/G4Utilities/Geo2G4/src/Geo2G4AssemblyVolume.cxx b/Simulation/G4Utilities/Geo2G4/src/Geo2G4AssemblyVolume.cxx new file mode 100644 index 000000000..86de232db --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/Geo2G4AssemblyVolume.cxx @@ -0,0 +1,350 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "Geo2G4AssemblyVolume.h" +#include "G4PVPlacement.hh" +#include "G4RotationMatrix.hh" +#include "G4AffineTransform.hh" +#include "G4LogicalVolume.hh" +#include "G4VPhysicalVolume.hh" +#include "G4ReflectionFactory.hh" + +#include <sstream> + +unsigned int Geo2G4AssemblyVolume::s_instanceCounter = 0; + +// Default constructor +// +Geo2G4AssemblyVolume::Geo2G4AssemblyVolume() +: m_assemblyID( 0 ) +{ + InstanceCountPlus(); + SetAssemblyID( GetInstanceCount() ); + SetImprintsCount( 0 ); +} + +// Destructor +// +Geo2G4AssemblyVolume::~Geo2G4AssemblyVolume() +{ + unsigned int howmany = m_triplets.size(); + if( howmany != 0 ) + { + for( unsigned int i = 0; i < howmany; i++ ) + { + G4RotationMatrix* pRotToClean = m_triplets[i].GetRotation(); + if( pRotToClean != 0 ) + { + delete pRotToClean; + } + } + } + m_triplets.clear(); + + howmany = m_PVStore.size(); + if( howmany != 0 ) + { + for( unsigned int j = 0; j < howmany; j++ ) + { + G4RotationMatrix* pRotToClean = m_PVStore[j]->GetRotation(); + if( pRotToClean != 0 ) + { + delete pRotToClean; + } + delete m_PVStore[j]; + } + } + m_PVStore.clear(); + InstanceCountMinus(); +} + +// Add and place the given volume according to the specified +// translation and rotation. +// +// The rotation matrix passed in can be 0 = identity or an address even of an +// object on the upper stack frame. During assembly imprint, it creates anyway +// a new matrix and keeps track of it so it can delete it later at destruction +// time. +// This policy has been adopted since user has no control on the way the +// rotations are combined. +// +void Geo2G4AssemblyVolume::AddPlacedVolume( G4LogicalVolume* pVolume, + G4ThreeVector& translation, + G4RotationMatrix* pRotation, + int copyNo, G4String userC) +{ + G4RotationMatrix* toStore = new G4RotationMatrix; + + if( pRotation != 0 ) { *toStore = *pRotation; } + + Geo2G4AssemblyTriplet toAdd( pVolume, translation, toStore ); + m_triplets.push_back( toAdd ); + + m_copyNumbers.push_back( copyNo ); + m_userComments.push_back( userC ); +} + +// Add and place the given volume according to the specified transformation +// +void Geo2G4AssemblyVolume::AddPlacedVolume( G4LogicalVolume* pVolume, + G4Transform3D& transformation, + int copyNo, G4String userC) +{ + // Decompose transformation + G4Scale3D scale; + G4Rotate3D rotation; + G4Translate3D translation; + transformation.getDecomposition(scale, rotation, translation); + + G4ThreeVector v = translation.getTranslation(); + G4RotationMatrix* r = new G4RotationMatrix; + *r = rotation.getRotation(); + + G4bool isReflection = false; + if (scale(0,0)*scale(1,1)*scale(2,2) < 0.) { isReflection = true; } + + Geo2G4AssemblyTriplet toAdd( pVolume, v, r, isReflection ); + m_triplets.push_back( toAdd ); + + m_copyNumbers.push_back( copyNo ); + m_userComments.push_back( userC ); +} + +// Add and place the given assembly volume according to the specified +// translation and rotation. +// +void Geo2G4AssemblyVolume::AddPlacedAssembly( Geo2G4AssemblyVolume* pAssembly, + G4ThreeVector& translation, + G4RotationMatrix* pRotation ) +{ + G4RotationMatrix* toStore = new G4RotationMatrix; + + if( pRotation != 0 ) { *toStore = *pRotation; } + + Geo2G4AssemblyTriplet toAdd( pAssembly, translation, toStore ); + m_triplets.push_back( toAdd ); +} + +// Add and place the given assembly volume according to the specified +// transformation +// +void Geo2G4AssemblyVolume::AddPlacedAssembly( Geo2G4AssemblyVolume* pAssembly, + G4Transform3D& transformation ) +{ + // Decompose transformation + // + G4Scale3D scale; + G4Rotate3D rotation; + G4Translate3D translation; + transformation.getDecomposition(scale, rotation, translation); + + G4ThreeVector v = translation.getTranslation(); + G4RotationMatrix* r = new G4RotationMatrix; + *r = rotation.getRotation(); + + G4bool isReflection = false; + if (scale(0,0)*scale(1,1)*scale(2,2) < 0.) { isReflection = true; } + + Geo2G4AssemblyTriplet toAdd( pAssembly, v, r, isReflection ); + m_triplets.push_back( toAdd ); +} + +// Create an instance of an assembly volume inside of the specified +// mother volume. This works analogically to making stamp imprints. +// This method makes use of the Geant4 affine transformation class. +// The algorithm is defined as follows: +// +// Having rotation matrix Rm and translation vector Tm to be applied +// inside the mother and rotation matrix Ra and translation vector Ta +// to be applied inside the assembly itself for each of the participating +// volumes the resulting transformation is +// +// Tfinal = Ta * Tm +// +// where Ta and Tm are constructed as +// +// -1 -1 +// Ta = Ra * Ta and Tm = Rm * Tm +// +// which in words means that we create first the affine transformations +// by inverse rotation matrices and translations for mother and assembly. +// The resulting final transformation to be applied to each of the +// participating volumes is their product. +// +// IMPORTANT NOTE! +// The order of multiplication is reversed when comparing to CLHEP 3D +// transformation matrix(G4Transform3D class). +// +// The rotation matrix passed in can be 0 = identity or an address even of an +// object on the upper stack frame. During assembly imprint, it creates anyway +// a new matrix and keeps track of it so it can delete it later at destruction +// time. +// This policy has been adopted since user has no control on the way the +// rotations are combined. +// +// If the assembly volume contains assembly (a'), the function is called +// recursively with composed transformation: +// +// Tanew = Ta * Ta' +// +void Geo2G4AssemblyVolume::MakeImprint( Geo2G4AssemblyVolume* pAssembly, + G4LogicalVolume* pMotherLV, + G4Transform3D& transformation, + G4int copyNumBase, + G4bool ITkScheme, + G4bool surfCheck ) +{ + unsigned int numberOfDaughters; + + if( copyNumBase == 0 ) + { + numberOfDaughters = pMotherLV->GetNoDaughters(); + } + else + { + numberOfDaughters = copyNumBase; + } + // We start from the first available index + // + numberOfDaughters++; + + ImprintsCountPlus(); + std::vector<Geo2G4AssemblyTriplet> triplets = pAssembly->m_triplets; + for( unsigned int i = 0; i < triplets.size(); i++ ) + { + G4Transform3D Ta( *(triplets[i].GetRotation()), + triplets[i].GetTranslation() ); + if ( triplets[i].IsReflection() ) { Ta = Ta * G4ReflectZ3D(); } + + G4Transform3D Tfinal = transformation * Ta; + if ( triplets[i].GetVolume() ) + { + // Generate the unique name for the next PV instance + // The name has format: + // + // av_WWW_impr_XXX_YYY_ZZZ + // where the fields mean: + // WWW - assembly volume instance number + // XXX - assembly volume imprint number + // YYY - the name of a log. volume we want to make a placement of + // ZZZ - the log. volume index inside the assembly volume + // + + + std::stringstream pvName; + pvName << "av_" + << GetAssemblyID() + << "_impr_" + << GetImprintsCount() + << "_" + << triplets[i].GetVolume()->GetName().c_str() + << "_pv_" + << i; + if (i<m_userComments.size() && !(m_userComments[i].empty())) pvName<<"_"<<m_userComments[i]; + pvName<<std::ends; + // Generate a new physical volume instance inside a mother + // (as we allow 3D transformation use G4ReflectionFactory to + // take into account eventual reflection) + // + int ccn=numberOfDaughters + i; + if (i<m_copyNumbers.size() && m_copyNumbers[i]) { + if(ITkScheme) ccn=m_copyNumbers[i]; + else ccn=m_copyNumbers[i]+copyNumBase; + } + + G4PhysicalVolumesPair pvPlaced + = G4ReflectionFactory::Instance()->Place( Tfinal, + pvName.str().c_str(), + triplets[i].GetVolume(), + pMotherLV, + false, + ccn, + surfCheck ); + + + // Register the physical volume created by us so we can delete it later + // + m_PVStore.push_back( pvPlaced.first ); + if ( pvPlaced.second ) { m_PVStore.push_back( pvPlaced.second ); } + } + else if ( triplets[i].GetAssembly() ) + { + // Place volumes in this assembly with composed transformation + // + if(ITkScheme) triplets[i].GetAssembly()->MakeImprint( triplets[i].GetAssembly(), pMotherLV, + Tfinal, i*100+copyNumBase, ITkScheme, surfCheck ); + else MakeImprint( triplets[i].GetAssembly(), pMotherLV, + Tfinal, i*100+copyNumBase, ITkScheme, surfCheck ); + } + else + { + G4Exception("Geo2G4AssemblyVolume::MakeImprint(..)", + "NotApplicable", FatalException, + "Triplet has no volume and no assembly"); + } + } +} + +void Geo2G4AssemblyVolume::MakeImprint( G4LogicalVolume* pMotherLV, + G4ThreeVector& translationInMother, + G4RotationMatrix* pRotationInMother, + G4int copyNumBase, + G4bool ITkScheme, + G4bool surfCheck ) +{ + // If needed user can specify explicitely the base count from which to start + // off for the generation of phys. vol. copy numbers. + // The old behaviour is preserved when copyNumBase == 0, e.g. the generated + // copy numbers start from the count equal to current number of daughter + // volumes before an imprint is made + + // Compose transformation + // + if( pRotationInMother == 0 ) + { + // Make it by default an indentity matrix + // + pRotationInMother = + const_cast<G4RotationMatrix*>( &G4RotationMatrix::IDENTITY ); + } + + G4Transform3D transform( *pRotationInMother, + translationInMother ); + MakeImprint(this, pMotherLV, transform, copyNumBase, ITkScheme, surfCheck); +} + +void Geo2G4AssemblyVolume::MakeImprint( G4LogicalVolume* pMotherLV, + G4Transform3D& transformation, + G4int copyNumBase, + G4bool ITkScheme, + G4bool surfCheck ) +{ + // If needed user can specify explicitely the base count from which to start + // off for the generation of phys. vol. copy numbers. + // The old behaviour is preserved when copyNumBase == 0, e.g. the generated + // copy numbers start from the count equal to current number of daughter + // volumes before a imprint is made + + MakeImprint(this, pMotherLV, transformation, copyNumBase, ITkScheme, surfCheck); +} + +unsigned int Geo2G4AssemblyVolume::GetInstanceCount() const +{ + return Geo2G4AssemblyVolume::s_instanceCounter; +} + +void Geo2G4AssemblyVolume::SetInstanceCount( unsigned int value ) +{ + Geo2G4AssemblyVolume::s_instanceCounter = value; +} + +void Geo2G4AssemblyVolume::InstanceCountPlus() +{ + Geo2G4AssemblyVolume::s_instanceCounter++; +} + +void Geo2G4AssemblyVolume::InstanceCountMinus() +{ + Geo2G4AssemblyVolume::s_instanceCounter--; +} diff --git a/Simulation/G4Utilities/Geo2G4/src/Geo2G4AssemblyVolume.h b/Simulation/G4Utilities/Geo2G4/src/Geo2G4AssemblyVolume.h new file mode 100644 index 000000000..7efa3d105 --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/Geo2G4AssemblyVolume.h @@ -0,0 +1,235 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef GEO2G4_ASSEMBLYVOLUME_H +#define GEO2G4_ASSEMBLYVOLUME_H + +#include "Geo2G4AssemblyTriplet.h" +#include "G4Transform3D.hh" +#include <vector> + +class G4VPhysicalVolume; + +class Geo2G4AssemblyVolume +{ +public: // with description + + Geo2G4AssemblyVolume(); + Geo2G4AssemblyVolume( G4LogicalVolume* volume, + G4ThreeVector& translation, + G4RotationMatrix* rotation); + ~Geo2G4AssemblyVolume(); + // + // Constructors & destructor. + // At destruction all the generated physical volumes and associated + // rotation matrices of the imprints will be destroyed. + // + // The rotation matrix passed as argument can be 0 (identity) or an address + // even of an object on the upper stack frame. During assembly imprint, a + // new matrix is created anyway and it is kept track of it so it can be + // automatically deleted later at the end of the application. + // This policy is adopted since user has no control on the way the + // rotations are combined. + + void AddPlacedVolume( G4LogicalVolume* pPlacedVolume, + G4ThreeVector& translation, + G4RotationMatrix* rotation, + int copyNo=0,G4String userComment=""); + // + // Place the given volume 'pPlacedVolume' inside the assembly. + // + // The adopted approach: + // + // - Place it w.r.t. the assembly coordinate system. + // This step is applied to each of the participating volumes. + // + // The other possible approaches: + // + // - Place w.r.t. the firstly added volume. + // When placed the first, the virtual coordinate system becomes + // the coordinate system of the first one. + // Every next volume being added into the assembly will be placed + // w.r.t to the first one. + // + // - Place w.r.t the last placed volume. + // When placed the first, the virtual coordinate system becomes + // the coordinate system of the first one. + // Every next volume being added into the assembly will be placed + // w.r.t to the previous one. + // + // The rotation matrix passed as argument can be 0 (identity) or an address + // even of an object on the upper stack frame. During assembly imprint, a + // new matrix is created anyway and it is kept track of it so it can be + // automatically deleted later at the end of the application. + // This policy is adopted since user has no control on the way the + // rotations are combined. + + void AddPlacedVolume( G4LogicalVolume* pPlacedVolume, + G4Transform3D& transformation, + int copyNo=0,G4String userComment=""); + // + // The same as previous, but takes complete 3D transformation in space + // as its argument. + + void AddPlacedAssembly( Geo2G4AssemblyVolume* pAssembly, + G4Transform3D& transformation); + // + // The same as previous AddPlacedVolume(), but takes an assembly volume + // as its argument. + + void AddPlacedAssembly( Geo2G4AssemblyVolume* pAssembly, + G4ThreeVector& translation, + G4RotationMatrix* rotation); + // + // The same as above AddPlacedVolume(), but takes an assembly volume + // as its argument with translation and rotation. + + void MakeImprint( G4LogicalVolume* pMotherLV, + G4ThreeVector& translationInMother, + G4RotationMatrix* pRotationInMother, + G4int copyNumBase = 0, + G4bool ITkScheme = false, + G4bool surfCheck = false ); + // + // Creates instance of an assembly volume inside the given mother volume. + + void MakeImprint( G4LogicalVolume* pMotherLV, + G4Transform3D& transformation, + G4int copyNumBase = 0, + G4bool ITkScheme = false, + G4bool surfCheck = false ); + // + // The same as previous Imprint() method, but takes complete 3D + // transformation in space as its argument. + + inline std::vector<G4VPhysicalVolume*>::iterator GetVolumesIterator(); + inline unsigned int TotalImprintedVolumes() const; + // + // Methods to access the physical volumes imprinted with the assembly. + + unsigned int GetImprintsCount() const; + // + // Return the number of made imprints. + + unsigned int GetInstanceCount() const; + // + // Return the number of existing instance of Geo2G4AssemblyVolume class. + + unsigned int GetAssemblyID() const; + // + // Return instance number of this concrete object. + +protected: + + void SetInstanceCount( unsigned int value ); + void SetAssemblyID( unsigned int value ); + + void InstanceCountPlus(); + void InstanceCountMinus(); + + void SetImprintsCount( unsigned int value ); + void ImprintsCountPlus(); + void ImprintsCountMinus(); + // + // Internal counting mechanism, used to compute unique the names of + // physical volumes created by MakeImprint() methods. + +private: + + void MakeImprint( Geo2G4AssemblyVolume* pAssembly, + G4LogicalVolume* pMotherLV, + G4Transform3D& transformation, + G4int copyNumBase = 0, + G4bool ITkScheme = false, + G4bool surfCheck = false ); + // + // Function for placement of the given assembly in the given mother + // (called recursively if the assembly contains an assembly). + +private: + + std::vector<Geo2G4AssemblyTriplet> m_triplets; + std::vector<int> m_copyNumbers; + std::vector<G4String> m_userComments; + // + // Participating volumes represented as a vector of + // <logical volume, translation, rotation>. + + std::vector<G4VPhysicalVolume*> m_PVStore; + // + // We need to keep list of physical volumes created by MakeImprint() method + // in order to be able to cleanup the objects when not needed anymore. + // This requires the user to keep assembly objects in memory during the + // whole job or during the life-time of G4Navigator, logical volume store + // and physical volume store keep pointers to physical volumes generated by + // the assembly volume. + // When an assembly object is about to die it will destroy all its + // generated physical volumes and rotation matrices as well ! + + unsigned int m_imprintsCounter; + // + // Number of imprints of the given assembly volume. + + static unsigned int s_instanceCounter; + // + // Class instance counter. + + unsigned int m_assemblyID; + // + // Assembly object ID derived from instance counter at construction time. + +}; + +inline +unsigned int Geo2G4AssemblyVolume::GetImprintsCount() const +{ + return m_imprintsCounter; +} + +inline +void Geo2G4AssemblyVolume::SetImprintsCount( unsigned int value ) +{ + m_imprintsCounter = value; +} + + +inline +void Geo2G4AssemblyVolume::ImprintsCountPlus() +{ + m_imprintsCounter++; +} + +inline +void Geo2G4AssemblyVolume::ImprintsCountMinus() +{ + m_imprintsCounter--; +} + +inline +unsigned int Geo2G4AssemblyVolume::GetAssemblyID() const +{ + return m_assemblyID; +} + +inline +void Geo2G4AssemblyVolume::SetAssemblyID( unsigned int value ) +{ + m_assemblyID = value; +} + +inline +std::vector<G4VPhysicalVolume*>::iterator +Geo2G4AssemblyVolume::GetVolumesIterator() +{ + std::vector<G4VPhysicalVolume*>::iterator iterator = m_PVStore.begin(); + return iterator; +} + +inline +unsigned int Geo2G4AssemblyVolume::TotalImprintedVolumes() const +{ + return m_PVStore.size(); +} + +#endif diff --git a/Simulation/G4Utilities/Geo2G4/src/Geo2G4Builder.cxx b/Simulation/G4Utilities/Geo2G4/src/Geo2G4Builder.cxx new file mode 100644 index 000000000..c0bafadb0 --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/Geo2G4Builder.cxx @@ -0,0 +1,221 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ + +#include "Geo2G4Builder.h" +#include "Geo2G4SvcAccessor.h" +#include "G4AtlasInterfaces/Geo2G4SvcBase.h" +#include "Geo2G4OpticalSurfaceFactory.h" + +#include "GeoModelKernel/GeoVDetectorManager.h" +#include "GeoModelKernel/GeoShapeUnion.h" +#include "GeoModelKernel/GeoShapeShift.h" +#include "GeoModelKernel/GeoMaterial.h" +#include "GeoModelKernel/GeoLogVol.h" +#include "GeoModelKernel/GeoPhysVol.h" +#include "GeoModelKernel/GeoTransform.h" + +#include "GeoModelUtilities/GeoModelExperiment.h" +#include "GeoModelInterfaces/StoredMaterialManager.h" + +#include "AthenaBaseComps/AthMsgStreamMacros.h" + +#include "GaudiKernel/ISvcLocator.h" +#include "GaudiKernel/Bootstrap.h" +#include "StoreGate/StoreGateSvc.h" +#include "StoreGate/StoreGate.h" + +#include "G4ReflectionFactory.hh" +#include "G4LogicalBorderSurface.hh" +#include "G4OpticalSurface.hh" + +#include <map> +#include <iostream> + +Geo2G4Builder::Geo2G4Builder(std::string detectorName) + : m_detectorName(detectorName) + , m_motherTransform(GeoTrf::Transform3D::Identity()) + , m_matAir(nullptr) + , m_pDetStore(nullptr) + , m_msg("Geo2G4Builder") +{ + ISvcLocator* svcLocator = Gaudi::svcLocator(); // from Bootstrap + StatusCode sc=svcLocator->service("DetectorStore",m_pDetStore); + if (sc.isFailure()) { + ATH_MSG_FATAL("Geo2G4Builder for detector "<<detectorName<<"could not access the detector store - PANIC!!!!"); + abort(); + } + + const GeoModelExperiment* theExpt = nullptr; + sc = m_pDetStore->retrieve( theExpt ); + if(sc.isFailure()){ + ATH_MSG_ERROR("Detector "<< detectorName << "could not get GeoModelExperiment!"); + } else { + const GeoVDetectorManager *theManager = theExpt->getManager(detectorName); + + for(unsigned int i=0; i<theManager->getNumTreeTops(); i++) + m_treeTops.push_back(theManager->getTreeTop(i)); + + ATH_MSG_INFO("Found detector: top volume(s)"); + for(unsigned int i=0; i<m_treeTops.size();i++) + ATH_MSG_INFO( " Tree Top " << i << " " << m_treeTops[i]->getLogVol()->getName() ); + + if(m_treeTops.size()>1) + { + // -------- -------- MATERIAL MANAGER -------- ---------- + const StoredMaterialManager* theMaterialManager = nullptr; + sc = m_pDetStore->retrieve(theMaterialManager, "MATERIALS"); + if(sc.isFailure()) + ATH_MSG_ERROR("Detector "<< detectorName << "could not retrieve Material Manager when number of tree tops > 1"); + else + m_matAir = theMaterialManager->getMaterial("std::Air"); + } + + Geo2G4SvcAccessor accessor; + Geo2G4SvcBase *g=accessor.GetGeo2G4Svc(); + m_theBuilder=g->GetDefaultBuilder(); + if(m_theBuilder) + ATH_MSG_INFO("Set volume builder ---> "<< m_theBuilder->GetKey()); + else + ATH_MSG_WARNING("0 pointer to volume builder." + <<"\n Use 'DefaultBuilder' property of Geo2G4Svc or" + <<"\n 'GetVolumeBuilder' method of Geo2G4Builder"); + } +} + +G4LogicalVolume* Geo2G4Builder::BuildTree() +{ + G4LogicalVolume* result = 0; + OpticalVolumesMap* optical_volumes = 0; + const GeoBorderSurfaceContainer* surface_container = 0; + + // Check whether we have to deal with optical surfaces + if(m_pDetStore->contains<GeoBorderSurfaceContainer>(m_detectorName)) + { + StatusCode sc = m_pDetStore->retrieve(surface_container,m_detectorName); + if(sc.isSuccess() && surface_container!=0 && surface_container->size()>0) + optical_volumes = new OpticalVolumesMap(); + } + + if(m_theBuilder) { + if(m_treeTops.size()==1) { + m_motherTransform = m_treeTops[0]->getX(); + result = m_theBuilder->Build(m_treeTops[0],optical_volumes); + } else { + // Create temporary GeoModel physical volume + // The shape is composed by TreeTop shapes + their transforms + const GeoShape& shFirst = (*(m_treeTops[0]->getLogVol()->getShape()))<<(m_treeTops[0]->getX()); + const GeoShape* shResult = &shFirst; + + for(unsigned int i=1; i<m_treeTops.size(); i++){ + const GeoShape& shNext = (*shResult).add((*(m_treeTops[i]->getLogVol()->getShape()))<<(m_treeTops[i]->getX())); + shResult = &shNext; + } + + GeoLogVol* lvEnvelope = new GeoLogVol(m_detectorName,shResult,m_matAir); + GeoPhysVol* pvEnvelope = new GeoPhysVol(lvEnvelope); + + result = m_theBuilder->Build(pvEnvelope); + + // Get pointer to the World + PVConstLink world = m_treeTops[0]->getParent(); + + // Add all tree tops to the result + for(unsigned int i=0; i<m_treeTops.size(); i++) { + // Current Tree Top and its index + PVConstLink pv = m_treeTops[i]; + Query<unsigned int> childIndx = world->indexOf(pv); + + // Tree Top transformation + G4Transform3D theG4Position(Amg::EigenTransformToCLHEP(world->getXToChildVol(childIndx))); + + // Copy number + int id = 16969; + Query<int> Qint = world->getIdOfChildVol(childIndx); + if(Qint.isValid()) id = Qint; + + // PV Tree Top name + std::string nameTT = world->getNameOfChildVol(childIndx); + if (nameTT == "ANON") nameTT = pv->getLogVol()->getName(); + + + G4LogicalVolume* g4LV = m_theBuilder->Build(pv,optical_volumes); + G4ReflectionFactory::Instance()->Place(theG4Position, + nameTT, + g4LV, + result, + false, + id); + } + + // Add the temporary physical volume to the GeoModelExperiment + GeoModelExperiment * theExpt; + StatusCode sc = m_pDetStore->retrieve(theExpt); + if(sc.isFailure()) + ATH_MSG_WARNING("Unable to retrieve GeoModelExperiment. Temporary volume cannot be released"); + else + theExpt->addTmpVolume(pvEnvelope); + } + } + + // build optical surfaces if necessary + if(optical_volumes!=0 && optical_volumes->size()>0){ + BuildOpticalSurfaces(surface_container,optical_volumes); + } else if (optical_volumes!=0){ + ATH_MSG_WARNING("Optical volumes apparently requested, but none found! Deleting temps"); + } + if (optical_volumes!=0) delete optical_volumes; + return result; +} + + +VolumeBuilder* Geo2G4Builder::GetVolumeBuilder(std::string bname) +{ + Geo2G4SvcAccessor accessor; + Geo2G4SvcBase *g=accessor.GetGeo2G4Svc(); + + m_theBuilder=g->GetVolumeBuilder(bname); + return m_theBuilder; +} + +void Geo2G4Builder::BuildOpticalSurfaces(const GeoBorderSurfaceContainer* surface_container, + const OpticalVolumesMap* optical_volumes) +{ + Geo2G4OpticalSurfaceFactory surfaceFactory; + + // Iterate over all Border Surfaces in the container + GeoBorderSurfaceContainer::const_iterator first = surface_container->begin(); + GeoBorderSurfaceContainer::const_iterator last = surface_container->end(); + + for(;first!=last;first++) + { + // Build Optical Surface + const GeoBorderSurface& border_surface = *first; + G4OpticalSurface* g4OptSurface = surfaceFactory.Build(border_surface.getOptSurface()); + + G4VPhysicalVolume* g4PV1 = 0; + G4VPhysicalVolume* g4PV2 = 0; + OpticalVolumesMap::const_iterator volIt; + + // First physical volume + volIt = optical_volumes->find(border_surface.getPV1()); + if(volIt == optical_volumes->end()) + { + ATH_MSG_WARNING("Unable to find " << border_surface.getPV1()->getLogVol()->getName() << " in Optical Volumes map"); + continue; + } + g4PV1 = volIt.operator->()->second; + + // Second physical volume + volIt = optical_volumes->find(border_surface.getPV2()); + if(volIt == optical_volumes->end()) + { + ATH_MSG_WARNING("Unable to find " << border_surface.getPV1()->getLogVol()->getName() << " in Optical Volumes map"); + continue; + } + g4PV2 = volIt.operator->()->second; + + // G4LogicalBorderSurface + G4LogicalBorderSurface* g4BorderSurface __attribute__((unused)) = new G4LogicalBorderSurface(border_surface.getName(),g4PV1,g4PV2,g4OptSurface); + } +} diff --git a/Simulation/G4Utilities/Geo2G4/src/Geo2G4Builder.h b/Simulation/G4Utilities/Geo2G4/src/Geo2G4Builder.h new file mode 100644 index 000000000..3aa785ebb --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/Geo2G4Builder.h @@ -0,0 +1,71 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef GEO2G4_Geo2G4Builder_H +#define GEO2G4_Geo2G4Builder_H + +// main builder to create/position all volumes described in a GeoModel Tree + +// GeoVPhysVol +#include "VolumeBuilder.h" +#include "GeoModelKernel/GeoVPhysVol.h" +#include "GeoModelKernel/GeoDefinitions.h" +#include "G4LogicalVolume.hh" +//#include "Geo2G4/GenericVolumeBuilder.h" + +// Typedef +#include "GeoModelUtilities/GeoBorderSurfaceContainer.h" + +#include "AthenaKernel/MsgStreamMember.h" + +#include "GeoPrimitives/CLHEPtoEigenConverter.h" + +// STL includes +#include <string> +#include <vector> + +class GeoMaterial; +class StoreGateSvc; + +class Geo2G4Builder { + +public: + // Constructor: + Geo2G4Builder(std::string detectorName); + // Destructor: + ~Geo2G4Builder() {;} + + // Build method - geometry + G4LogicalVolume* BuildTree(); + + // Build method - optical surfaces + void BuildOpticalSurfaces(const GeoBorderSurfaceContainer* surface_container, + const OpticalVolumesMap* optical_volumes); + + // Access volume builder: + VolumeBuilder* GetVolumeBuilder(std::string); + + HepGeom::Transform3D GetDetectorTransform() {return Amg::EigenTransformToCLHEP(m_motherTransform);} + /// Log a message using the Athena controlled logging system + MsgStream& msg( MSG::Level lvl ) const { return m_msg << lvl; } + /// Check whether the logging system is active at the provided verbosity level + bool msgLvl( MSG::Level lvl ) const { return m_msg.get().level() <= lvl; } + +private: + + // GeoVDetectorManager* theDetectorElement; + std::string m_detectorName; + GeoTrf::Transform3D m_motherTransform; + std::vector<PVConstLink> m_treeTops; + VolumeBuilder *m_theBuilder; + + // std::Air in the case when top boolean envelope has to be built + const GeoMaterial* m_matAir; + StoreGateSvc* m_pDetStore; + + /// Private message stream member + mutable Athena::MsgStreamMember m_msg; +}; + +#endif diff --git a/Simulation/G4Utilities/Geo2G4/src/Geo2G4LVFactory.cxx b/Simulation/G4Utilities/Geo2G4/src/Geo2G4LVFactory.cxx new file mode 100644 index 000000000..f20c86fa8 --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/Geo2G4LVFactory.cxx @@ -0,0 +1,99 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "Geo2G4LVFactory.h" +#include "Geo2G4SolidFactory.h" +#include "GeoMaterial2G4/Geo2G4MaterialFactory.h" + +#include "GeoModelKernel/GeoLogVol.h" +#include "GeoModelKernel/GeoFullPhysVol.h" + +#include "G4LogicalVolume.hh" +#include "G4Material.hh" + +#include <iostream> +#include <map> + +typedef std::map<const GeoLogVol*, G4LogicalVolume*, std::less<const GeoLogVol*> > leafVMap; +typedef std::map<const GeoVPhysVol*, G4LogicalVolume*, std::less<const GeoVPhysVol*> > branchVMap; + +typedef std::map<const GeoFullPhysVol*, G4LogicalVolume*, std::less<const GeoFullPhysVol*> > fullPVMap; + +Geo2G4LVFactory::Geo2G4LVFactory() +{ +} + +G4LogicalVolume* Geo2G4LVFactory::Build(const PVConstLink thePhys, + bool& descend) const +{ + static Geo2G4SolidFactory theSolidFactory; + static Geo2G4MaterialFactory theMaterialFactory; + + static leafVMap sharedLeafLV; + static branchVMap sharedBranchLV; + static fullPVMap clonedLV; + + const GeoFullPhysVol* fullPV = dynamic_cast<const GeoFullPhysVol*>(&(*thePhys)); + const GeoFullPhysVol* clonePV=0; + + const GeoLogVol* theLog = thePhys->getLogVol(); + G4LogicalVolume *theG4Log=0; + G4Material* theG4Mat=0; + G4VSolid* theG4Solid=0; + + descend = true; + bool putLeaf = false; + bool putBranch = false; + bool putFullPV = false; + + // Check if it is a leaf node of Geo tree + if(thePhys->getNChildVols() == 0) + { + descend=false; + + if(sharedLeafLV.find(theLog) != sharedLeafLV.end()) + return sharedLeafLV[theLog]; + else // here supposed to be ---> else if(theLog->refCount() > 1) + putLeaf = true; + } + // Work with the Full Physical Volumes + else if(fullPV) + { + clonePV = fullPV->cloneOrigin(); + if (clonedLV.find(clonePV)==clonedLV.end()) + { + if(clonePV) putFullPV = true; + } + else + { + descend = false; + return clonedLV[clonePV]; + } + } + else + { + if(sharedBranchLV.find(&(*thePhys)) == sharedBranchLV.end()) + putBranch = true; + else + { + descend = false; + return sharedBranchLV[&(*thePhys)]; + } + } + // Actually build the G4Log + + theG4Mat=theMaterialFactory.Build(theLog->getMaterial()); + theG4Solid = theSolidFactory.Build(theLog->getShape(),theLog->getName()); + + theG4Log = new G4LogicalVolume(theG4Solid, + theG4Mat, + theLog->getName(), + 0,0,0); + + if(putLeaf) sharedLeafLV[theLog] = theG4Log; + if(putBranch) sharedBranchLV[&(*thePhys)] = theG4Log; + if(putFullPV) clonedLV[clonePV] = theG4Log; + + return theG4Log; +} diff --git a/Simulation/G4Utilities/Geo2G4/src/Geo2G4LVFactory.h b/Simulation/G4Utilities/Geo2G4/src/Geo2G4LVFactory.h new file mode 100644 index 000000000..3b75b06b8 --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/Geo2G4LVFactory.h @@ -0,0 +1,21 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef GEO2G4_Geo2G4LVFactory_h +#define GEO2G4_Geo2G4LVFactory_h + +#include "GeoModelKernel/GeoVPhysVol.h" + +class G4LogicalVolume; +class GeoLogVol; + +class Geo2G4LVFactory +{ + public: + Geo2G4LVFactory(); + G4LogicalVolume* Build(const PVConstLink, + bool&) const; +}; + +#endif diff --git a/Simulation/G4Utilities/Geo2G4/src/Geo2G4LogicalVolumeFactory.cxx b/Simulation/G4Utilities/Geo2G4/src/Geo2G4LogicalVolumeFactory.cxx new file mode 100644 index 000000000..f37928cf0 --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/Geo2G4LogicalVolumeFactory.cxx @@ -0,0 +1,39 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "Geo2G4LogicalVolumeFactory.h" +#include "Geo2G4SolidFactory.h" +#include "GeoMaterial2G4/Geo2G4MaterialFactory.h" + +#include "GeoModelKernel/GeoLogVol.h" + +#include "G4LogicalVolume.hh" +#include "G4Material.hh" + +#include "SimHelpers/ServiceAccessor.h" + +Geo2G4LogicalVolumeFactory::Geo2G4LogicalVolumeFactory() +{ +} + +G4LogicalVolume *Geo2G4LogicalVolumeFactory::Build(const GeoLogVol* theLog) const +{ + static Geo2G4SolidFactory theSolidFactory; + static Geo2G4MaterialFactory theMaterialFactory; + // + // Get Material from GeoModel + // + std::string n= theLog->getName(); + G4LogicalVolume *theG4Log=0; + G4Material* theG4Mat=theMaterialFactory.Build(theLog->getMaterial()); + + G4VSolid * theG4Solid = theSolidFactory.Build(theLog->getShape(),theLog->getName()); + + theG4Log = new G4LogicalVolume(theG4Solid, + theG4Mat, + theLog->getName(), + 0,0,0); ; + + return theG4Log; +} diff --git a/Simulation/G4Utilities/Geo2G4/src/Geo2G4LogicalVolumeFactory.h b/Simulation/G4Utilities/Geo2G4/src/Geo2G4LogicalVolumeFactory.h new file mode 100644 index 000000000..fec639690 --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/Geo2G4LogicalVolumeFactory.h @@ -0,0 +1,17 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef GEO2G4_Geo2G4LogicalVolumeFactory_h +#define GEO2G4_Geo2G4LogicalVolumeFactory_h + +class G4LogicalVolume; +class GeoLogVol; + +class Geo2G4LogicalVolumeFactory { +public: + Geo2G4LogicalVolumeFactory(); + G4LogicalVolume* Build(const GeoLogVol*) const; +}; + +#endif diff --git a/Simulation/G4Utilities/Geo2G4/src/Geo2G4OpticalSurfaceFactory.cxx b/Simulation/G4Utilities/Geo2G4/src/Geo2G4OpticalSurfaceFactory.cxx new file mode 100644 index 000000000..3af74f855 --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/Geo2G4OpticalSurfaceFactory.cxx @@ -0,0 +1,127 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "Geo2G4OpticalSurfaceFactory.h" +#include "GeoMaterial2G4/Geo2G4MatPropTableFactory.h" + +#include "GeoModelUtilities/GeoOpticalSurface.h" + +#include "G4OpticalSurface.hh" + +Geo2G4OpticalSurfaceFactory::Geo2G4OpticalSurfaceFactory() +{ +} + +G4OpticalSurface* Geo2G4OpticalSurfaceFactory::Build(const GeoOpticalSurface* geoOpticalSurface) +{ + // + // Check if this surface has already been defined. + // + if(m_definedOptSurfaces.find(geoOpticalSurface) != m_definedOptSurfaces.end()) { + return m_definedOptSurfaces[geoOpticalSurface]; + } + + // map enums + G4OpticalSurfaceModel g4Model; + G4OpticalSurfaceFinish g4Finish; + G4SurfaceType g4Type; + + switch(geoOpticalSurface->GetModel()) + { + case GeoOpticalSurface::glisur: + { + g4Model = glisur; + break; + } + case GeoOpticalSurface::unified: + { + g4Model = unified; + break; + } + default: + g4Model = glisur; + } + + switch(geoOpticalSurface->GetFinish()) + { + case GeoOpticalSurface::polished: + { + g4Finish = polished; + break; + } + case GeoOpticalSurface::polishedfrontpainted: + { + g4Finish = polishedfrontpainted; + break; + } + case GeoOpticalSurface::polishedbackpainted: + { + g4Finish = polishedbackpainted; + break; + } + case GeoOpticalSurface::ground: + { + g4Finish = ground; + break; + } + case GeoOpticalSurface::groundfrontpainted: + { + g4Finish = groundfrontpainted; + break; + } + case GeoOpticalSurface::groundbackpainted: + { + g4Finish = groundbackpainted; + break; + } + default: + g4Finish = polished; + } + + switch(geoOpticalSurface->GetType()) + { + case GeoOpticalSurface::dielectric_metal: + { + g4Type = dielectric_metal; + break; + } + case GeoOpticalSurface::dielectric_dielectric: + { + g4Type = dielectric_dielectric; + break; + } + case GeoOpticalSurface::firsov: + { + g4Type = firsov; + break; + } + case GeoOpticalSurface::x_ray: + { + g4Type = x_ray; + break; + } + default: + g4Type = dielectric_dielectric; + } + + + + G4OpticalSurface* newG4Surface = new G4OpticalSurface(geoOpticalSurface->GetName(), + g4Model, + g4Finish, + g4Type, + geoOpticalSurface->GetParameter()); + + // Create material properties table + Geo2G4MatPropTableFactory* tFactory = Geo2G4MatPropTableFactory::instance(); + GeoMaterialPropertiesTable* geoPropTable = geoOpticalSurface->GetMaterialPropertiesTable(); + + if(geoPropTable){ + G4MaterialPropertiesTable* g4PropTable = tFactory->Build(geoPropTable); + if(g4PropTable) + newG4Surface->SetMaterialPropertiesTable(g4PropTable); + } + + return newG4Surface; +} diff --git a/Simulation/G4Utilities/Geo2G4/src/Geo2G4OpticalSurfaceFactory.h b/Simulation/G4Utilities/Geo2G4/src/Geo2G4OpticalSurfaceFactory.h new file mode 100644 index 000000000..035f1988e --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/Geo2G4OpticalSurfaceFactory.h @@ -0,0 +1,25 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef GEO2G4_Geo2G4OpticalSurfaceFactory_h +#define GEO2G4_Geo2G4OpticalSurfaceFactory_h + +#include <map> + +class GeoOpticalSurface; +class G4OpticalSurface; + +typedef std::map<const GeoOpticalSurface* , G4OpticalSurface*, std::less<const GeoOpticalSurface*> > Geo2G4OptSurfaceMap; + +class Geo2G4OpticalSurfaceFactory +{ + public: + Geo2G4OpticalSurfaceFactory(); + + G4OpticalSurface* Build(const GeoOpticalSurface*); + private: + Geo2G4OptSurfaceMap m_definedOptSurfaces; +}; + +#endif diff --git a/Simulation/G4Utilities/Geo2G4/src/Geo2G4STParameterisation.cxx b/Simulation/G4Utilities/Geo2G4/src/Geo2G4STParameterisation.cxx new file mode 100644 index 000000000..65ab76da7 --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/Geo2G4STParameterisation.cxx @@ -0,0 +1,32 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "Geo2G4STParameterisation.h" +#include "G4VPhysicalVolume.hh" +#include "GeoPrimitives/CLHEPtoEigenConverter.h" +#include "CLHEP/Geometry/Transform3D.h" + +Geo2G4STParameterisation::Geo2G4STParameterisation(const GeoXF::Function* func, + unsigned int copies): + m_function(func->clone()), + m_nCopies(copies) +{ + m_rotation = new G4RotationMatrix(); +} + +Geo2G4STParameterisation::~Geo2G4STParameterisation() +{ + delete m_rotation; +} + +void Geo2G4STParameterisation::ComputeTransformation(const G4int copyNo, + G4VPhysicalVolume* physVol) const +{ + HepGeom::Transform3D transform = Amg::EigenTransformToCLHEP((*m_function)(copyNo)); + G4ThreeVector translation = transform.getTranslation(); + *m_rotation = transform.getRotation().inverse(); + + physVol->SetTranslation(translation); + physVol->SetRotation(m_rotation); +} diff --git a/Simulation/G4Utilities/Geo2G4/src/Geo2G4STParameterisation.h b/Simulation/G4Utilities/Geo2G4/src/Geo2G4STParameterisation.h new file mode 100644 index 000000000..4e501cedb --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/Geo2G4STParameterisation.h @@ -0,0 +1,71 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef GEO2G4_Geo2G4STParameterisation_H +#define GEO2G4_Geo2G4STParameterisation_H + +#include "globals.hh" +#include "G4VPVParameterisation.hh" +#include "G4RotationMatrix.hh" + +#include "GeoModelKernel/GeoXF.h" + +class G4VPhysicalVolume; + +// Dummy declarations. To avoid warnings +class G4Box; +class G4Trd; +class G4Trap; +class G4Cons; +class G4Sphere; +class G4Torus; +class G4Para; +class G4Hype; +class G4Tubs; +class G4Orb; +class G4Polyhedra; +class G4Polycone; +class G4Ellipsoid; + +class Geo2G4STParameterisation : public G4VPVParameterisation +{ +public: + + Geo2G4STParameterisation(const GeoXF::Function* func, + unsigned int copies); + + virtual ~Geo2G4STParameterisation(); + + void ComputeTransformation (const G4int copyNo, + G4VPhysicalVolume* physVol) const; + +private: + // Declaring, but not defining private copy-constructor and + // assignment operator, as an object of this class should never be + // copied. + Geo2G4STParameterisation(const Geo2G4STParameterisation&); + Geo2G4STParameterisation& operator= (const Geo2G4STParameterisation&); + + // Dummy declarations. To avoid warnings + + void ComputeDimensions (G4Box&,const G4int,const G4VPhysicalVolume*) const {} + void ComputeDimensions (G4Trd&,const G4int,const G4VPhysicalVolume*) const {} + void ComputeDimensions (G4Trap&,const G4int,const G4VPhysicalVolume*) const {} + void ComputeDimensions (G4Cons&,const G4int,const G4VPhysicalVolume*) const {} + void ComputeDimensions (G4Sphere&,const G4int,const G4VPhysicalVolume*) const {} + void ComputeDimensions (G4Torus&,const G4int,const G4VPhysicalVolume*) const {} + void ComputeDimensions (G4Para&,const G4int,const G4VPhysicalVolume*) const {} + void ComputeDimensions (G4Hype&,const G4int,const G4VPhysicalVolume*) const {} + void ComputeDimensions (G4Tubs&,const G4int,const G4VPhysicalVolume*) const {} + void ComputeDimensions (G4Orb&,const G4int,const G4VPhysicalVolume*) const {} + void ComputeDimensions (G4Polyhedra&,const G4int,const G4VPhysicalVolume*) const {} + void ComputeDimensions (G4Polycone&,const G4int,const G4VPhysicalVolume*) const {} + void ComputeDimensions (G4Ellipsoid&,const G4int,const G4VPhysicalVolume*) const {} + + const GeoXF::Function *m_function; + G4RotationMatrix* m_rotation; + unsigned int m_nCopies; +}; + +#endif diff --git a/Simulation/G4Utilities/Geo2G4/src/Geo2G4SolidFactory.cxx b/Simulation/G4Utilities/Geo2G4/src/Geo2G4SolidFactory.cxx new file mode 100644 index 000000000..1fefc0820 --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/Geo2G4SolidFactory.cxx @@ -0,0 +1,588 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "Geo2G4SolidFactory.h" +// #include "LArWheelSolid.h" +// #include "LArWheelSliceSolid.h" +// #include "LArWheelSolidDDProxy.h" + +// #include "GeoSpecialShapes/LArCustomShape.h" + +#include "GeoModelKernel/GeoShape.h" +#include "GeoModelKernel/GeoBox.h" +#include "GeoModelKernel/GeoTube.h" +#include "GeoModelKernel/GeoTubs.h" +#include "GeoModelKernel/GeoTrd.h" +#include "GeoModelKernel/GeoPcon.h" +#include "GeoModelKernel/GeoPgon.h" +#include "GeoModelKernel/GeoPara.h" +#include "GeoModelKernel/GeoTrap.h" +#include "GeoModelKernel/GeoCons.h" +#include "GeoModelKernel/GeoSimplePolygonBrep.h" +#include "GeoModelKernel/GeoTessellatedSolid.h" +#include "GeoModelKernel/GeoEllipticalTube.h" +#include "GeoModelKernel/GeoTorus.h" +#include "GeoModelKernel/GeoGenericTrap.h" +#include "GeoModelKernel/GeoShapeShift.h" +#include "GeoModelKernel/GeoShapeUnion.h" +#include "GeoModelKernel/GeoShapeIntersection.h" +#include "GeoModelKernel/GeoShapeSubtraction.h" +#include "AthenaBaseComps/AthMsgStreamMacros.h" + +#include "G4VSolid.hh" +#include "G4Box.hh" +#include "G4Tubs.hh" +#include "G4Trd.hh" +#include "G4Polycone.hh" +#include "G4Cons.hh" +#include "G4Polyhedra.hh" +#include "G4Trap.hh" +#include "G4Para.hh" +#include "G4UnionSolid.hh" +#include "G4DisplacedSolid.hh" +#include "G4IntersectionSolid.hh" +#include "G4SubtractionSolid.hh" +#include "G4ExtrudedSolid.hh" +#include "G4TessellatedSolid.hh" +#include "G4EllipticalTube.hh" +#include "G4Torus.hh" +#include "G4TriangularFacet.hh" +#include "G4QuadrangularFacet.hh" +#include "G4GenericTrap.hh" + +#include <iostream> +#include <map> +#include <cmath> + +#include "GeoPrimitives/CLHEPtoEigenConverter.h" + +typedef std::map<const GeoShape*, G4VSolid*, std::less<const GeoShape*> > shapesMap; +typedef std::map<std::string, G4VSolid*,std::less<std::string> > customSolidMap; + +// const Geo2G4SolidFactory::LArWheelSolid_typemap Geo2G4SolidFactory::s_lwsTypes = { +// /* entries w/o explicit Pos/Neg kept for backward compatibility */ +// { "LAr::EMEC::InnerWheel::Absorber", {InnerAbsorberWheel, 1} }, +// { "LAr::EMEC::InnerWheel::Electrode", {InnerElectrodWheel, 1} }, +// { "LAr::EMEC::InnerWheel::Glue", {InnerGlueWheel, 1} }, +// { "LAr::EMEC::InnerWheel::Lead", {InnerLeadWheel, 1} }, + +// { "LAr::EMEC::OuterWheel::Absorber", {OuterAbsorberWheel, 1} }, +// { "LAr::EMEC::OuterWheel::Electrode", {OuterElectrodWheel, 1} }, +// { "LAr::EMEC::OuterWheel::Glue", {OuterGlueWheel, 1} }, +// { "LAr::EMEC::OuterWheel::Lead", {OuterLeadWheel, 1} }, + +// { "LAr::EMEC::Pos::InnerWheel::Absorber", {InnerAbsorberWheel, 1} }, +// { "LAr::EMEC::Pos::InnerWheel::Electrode", {InnerElectrodWheel, 1} }, +// { "LAr::EMEC::Pos::InnerWheel::Glue", {InnerGlueWheel, 1} }, +// { "LAr::EMEC::Pos::InnerWheel::Lead", {InnerLeadWheel, 1} }, + +// { "LAr::EMEC::Pos::OuterWheel::Absorber", {OuterAbsorberWheel, 1} }, +// { "LAr::EMEC::Pos::OuterWheel::Electrode", {OuterElectrodWheel, 1} }, +// { "LAr::EMEC::Pos::OuterWheel::Glue", {OuterGlueWheel, 1} }, +// { "LAr::EMEC::Pos::OuterWheel::Lead", {OuterLeadWheel, 1} }, + +// { "LAr::EMEC::Neg::InnerWheel::Absorber", {InnerAbsorberWheel, -1} }, +// { "LAr::EMEC::Neg::InnerWheel::Electrode", {InnerElectrodWheel, -1} }, +// { "LAr::EMEC::Neg::InnerWheel::Glue", {InnerGlueWheel, -1} }, +// { "LAr::EMEC::Neg::InnerWheel::Lead", {InnerLeadWheel, -1} }, + +// { "LAr::EMEC::Neg::OuterWheel::Absorber", {OuterAbsorberWheel, -1} }, +// { "LAr::EMEC::Neg::OuterWheel::Electrode", {OuterElectrodWheel, -1} }, +// { "LAr::EMEC::Neg::OuterWheel::Glue", {OuterGlueWheel, -1} }, +// { "LAr::EMEC::Neg::OuterWheel::Lead", {OuterLeadWheel, -1} }, + +// { "LAr::EMEC::InnerModule::Absorber", {InnerAbsorberModule, 1} }, +// { "LAr::EMEC::InnerModule::Electrode", {InnerElectrodModule, 1} }, +// { "LAr::EMEC::OuterModule::Absorber", {OuterAbsorberModule, 1} }, +// { "LAr::EMEC::OuterModule::Electrode", {OuterElectrodModule, 1} }, + +// { "LAr::EMEC::Pos::InnerCone::Absorber", {InnerAbsorberCone, 1} }, +// { "LAr::EMEC::Pos::InnerCone::Electrode", {InnerElectrodCone, 1} }, +// { "LAr::EMEC::Pos::InnerCone::Glue", {InnerGlueCone, 1} }, +// { "LAr::EMEC::Pos::InnerCone::Lead", {InnerLeadCone, 1} }, + +// { "LAr::EMEC::Neg::InnerCone::Absorber", {InnerAbsorberCone, -1} }, +// { "LAr::EMEC::Neg::InnerCone::Electrode", {InnerElectrodCone, -1} }, +// { "LAr::EMEC::Neg::InnerCone::Glue", {InnerGlueCone, -1} }, +// { "LAr::EMEC::Neg::InnerCone::Lead", {InnerLeadCone, -1} }, + +// { "LAr::EMEC::Pos::OuterFrontCone::Absorber", {OuterAbsorberFrontCone, 1} }, +// { "LAr::EMEC::Pos::OuterFrontCone::Electrode", {OuterElectrodFrontCone, 1} }, +// { "LAr::EMEC::Pos::OuterFrontCone::Glue", {OuterGlueFrontCone, 1} }, +// { "LAr::EMEC::Pos::OuterFrontCone::Lead", {OuterLeadFrontCone, 1} }, + +// { "LAr::EMEC::Neg::OuterFrontCone::Absorber", {OuterAbsorberFrontCone, -1} }, +// { "LAr::EMEC::Neg::OuterFrontCone::Electrode", {OuterElectrodFrontCone, -1} }, +// { "LAr::EMEC::Neg::OuterFrontCone::Glue", {OuterGlueFrontCone, -1} }, +// { "LAr::EMEC::Neg::OuterFrontCone::Lead", {OuterLeadFrontCone, -1} }, + +// { "LAr::EMEC::Pos::OuterBackCone::Absorber", {OuterAbsorberBackCone, 1} }, +// { "LAr::EMEC::Pos::OuterBackCone::Electrode", {OuterElectrodBackCone, 1} }, +// { "LAr::EMEC::Pos::OuterBackCone::Glue", {OuterGlueBackCone, 1} }, +// { "LAr::EMEC::Pos::OuterBackCone::Lead", {OuterLeadBackCone, 1} }, + +// { "LAr::EMEC::Neg::OuterBackCone::Absorber", {OuterAbsorberBackCone, -1} }, +// { "LAr::EMEC::Neg::OuterBackCone::Electrode", {OuterElectrodBackCone, -1} }, +// { "LAr::EMEC::Neg::OuterBackCone::Glue", {OuterGlueBackCone, -1} }, +// { "LAr::EMEC::Neg::OuterBackCone::Lead", {OuterLeadBackCone, -1} }, +// }; + +Geo2G4SolidFactory::Geo2G4SolidFactory() : + m_msg("Geo2G4SolidFactory"), + m_detStore( "StoreGateSvc/DetectorStore", "Geo2G4SolidFactory" ) +{ +} + +G4VSolid *Geo2G4SolidFactory::Build(const GeoShape* geoShape, std::string name) const +{ + G4VSolid* theSolid(nullptr); + + static customSolidMap customSolids; + static shapesMap sharedShapes; + if(sharedShapes.find(geoShape)!=sharedShapes.end()) + return sharedShapes[geoShape]; + + // ------- Variables for boolean operations + G4VSolid* solidA(nullptr); + G4VSolid* solidB(nullptr); + // ------- Variables for Pcon and Pgon + int nPlanes; + double* zPlane(nullptr); + double* rInner(nullptr); + double* rOuter(nullptr); + + std::string n = name; + + // + // The Box + // + if(geoShape->typeID() == GeoBox::getClassTypeID() ) + { + const GeoBox* theBox = dynamic_cast<const GeoBox*> (geoShape); + if (nullptr==theBox) throw std::runtime_error("TypeID did not match cast for box"); + if (n.empty()) n="G4Box"; + if (theBox->getXHalfLength()<=0.){ ATH_MSG_WARNING("Box " << n << " has an x side of " << theBox->getXHalfLength() <<" - using std::abs.");} + if (theBox->getYHalfLength()<=0.){ ATH_MSG_WARNING("Box " << n << " has an y side of " << theBox->getYHalfLength() <<" - using std::abs.");} + if (theBox->getZHalfLength()<=0.){ ATH_MSG_WARNING("Box " << n << " has an z side of " << theBox->getZHalfLength() <<" - using std::abs.");} + theSolid = new G4Box(n, + std::abs(theBox->getXHalfLength()), + std::abs(theBox->getYHalfLength()), + std::abs(theBox->getZHalfLength())); + } + // + // The Tube + // + else if(geoShape->typeID() == GeoTube::getClassTypeID() ) + { + const GeoTube* theTube = dynamic_cast<const GeoTube*> (geoShape); + if (nullptr==theTube) throw std::runtime_error("TypeID did not match cast for tube"); + if (n.empty()) n="G4Tube"; + if (theTube->getRMax()<=0.){ ATH_MSG_WARNING("Tube " << n << " has a max radius of " << theTube->getRMax() <<" - using std::abs.");} + if (theTube->getZHalfLength()<=0.){ ATH_MSG_WARNING("Tube " << n << " has a z half length of " << theTube->getZHalfLength() << " - using std::abs.");} + if (theTube->getRMax()<theTube->getRMin()){ ATH_MSG_WARNING("Tube " << n << " has a max radius of " << theTube->getRMax() << " and a min radius of " << theTube->getRMin());} + theSolid = new G4Tubs(n, + theTube->getRMin(), + std::abs(theTube->getRMax()), + std::abs(theTube->getZHalfLength()), + 0.,360*CLHEP::deg); + } + // + // The Tubs + // + else if(geoShape->typeID() == GeoTubs::getClassTypeID() ) + { + const GeoTubs* theTubs = dynamic_cast<const GeoTubs*> (geoShape); + if (nullptr==theTubs) throw std::runtime_error("TypeID did not match cast for tubs"); + if (n.empty()) n="G4Tubs"; + if (theTubs->getRMin()<0.){ ATH_MSG_WARNING("Tubs " << n << " has a min radius of " << theTubs->getRMax());} + if (theTubs->getRMax()<=0.){ ATH_MSG_WARNING("Tubs " << n << " has a max radius of " << theTubs->getRMax() <<" - using std::abs.");} + if (theTubs->getZHalfLength()<=0.){ ATH_MSG_WARNING("Tubs " << n << " has a half length of " << theTubs->getZHalfLength() <<" - using std::abs.");} + if (theTubs->getRMax()<theTubs->getRMin()){ ATH_MSG_WARNING("Tubs " << n << " has a max radius of " << theTubs->getRMax() << " and a min radius of " << theTubs->getRMin());} + if (theTubs->getDPhi()<=0.){ ATH_MSG_WARNING("Tubs " << n << " has a dPhi of " << theTubs->getDPhi());} + theSolid = new G4Tubs(n, + theTubs->getRMin(), + std::abs(theTubs->getRMax()), + std::abs(theTubs->getZHalfLength()), + theTubs->getSPhi(), + theTubs->getDPhi()); + } + // + // The Trd + // + else if(geoShape->typeID() == GeoTrd::getClassTypeID() ) + { + const GeoTrd* theTrd = dynamic_cast<const GeoTrd*> (geoShape); + if (nullptr==theTrd) throw std::runtime_error("TypeID did not match cast for trd"); + if (n.empty()) n="G4Trd"; + if (theTrd->getXHalfLength1()<0.){ ATH_MSG_WARNING("Trd " << n << " has a x half length 1 of " << theTrd->getXHalfLength1() << " - using std::abs.");} + if (theTrd->getXHalfLength2()<0.){ ATH_MSG_WARNING("Trd " << n << " has a x half length 2 of " << theTrd->getXHalfLength2() << " - using std::abs.");} + if (theTrd->getYHalfLength1()<0.){ ATH_MSG_WARNING("Trd " << n << " has a y half length 1 of " << theTrd->getYHalfLength1() << " - using std::abs.");} + if (theTrd->getYHalfLength2()<0.){ ATH_MSG_WARNING("Trd " << n << " has a y half length 2 of " << theTrd->getYHalfLength2() << " - using std::abs.");} + if (theTrd->getZHalfLength()<=0.){ ATH_MSG_WARNING("Trd " << n << " has a z half length of " << theTrd->getZHalfLength() << " - using std::abs.");} + if (theTrd->getXHalfLength1()<=0. && theTrd->getXHalfLength2()<=0.){ ATH_MSG_WARNING("Trd " << n << " has an x half length 1 of " << theTrd->getXHalfLength1() + << " and an x half length 2 of " << theTrd->getXHalfLength2() << " - using std::abs.");} + if (theTrd->getYHalfLength1()<=0. && theTrd->getYHalfLength2()<=0.){ ATH_MSG_WARNING("Trd " << n << " has a y half length 1 of " << theTrd->getYHalfLength1() + << " and a y half length 2 of " << theTrd->getYHalfLength2() << " - using std::abs.");} + theSolid = new G4Trd(n, + std::abs(theTrd->getXHalfLength1()), + std::abs(theTrd->getXHalfLength2()), + std::abs(theTrd->getYHalfLength1()), + std::abs(theTrd->getYHalfLength2()), + std::abs(theTrd->getZHalfLength())); + } + // + // GeoPcon + // + else if(geoShape->typeID() == GeoPcon::getClassTypeID()) + { + const GeoPcon* thePcon = dynamic_cast<const GeoPcon*>(geoShape); + if (nullptr==thePcon) throw std::runtime_error("TypeID did not match cast for pcon"); + if (n.empty()) n="G4Polycone"; + nPlanes = static_cast<int>(thePcon->getNPlanes()); + zPlane = new double[nPlanes]; + rInner = new double[nPlanes]; + rOuter = new double[nPlanes]; + for (unsigned int index=0; index<static_cast<unsigned int>(nPlanes); index++) + { + zPlane[index] = thePcon->getZPlane(index); + rInner[index] = thePcon->getRMinPlane(index); + rOuter[index] = thePcon->getRMaxPlane(index); + if (rInner[index]<0.){ ATH_MSG_WARNING("PCon " << n << " has an inner radius of " << rInner[index] << " for slice " << index << " of " << nPlanes);} + if (rOuter[index]<=0.){ + ATH_MSG_WARNING("PCon " << n << " has an outer radius of " << rOuter[index] << " for slice " << index << " of " << nPlanes << " - using std::abs."); + rOuter[index] = std::abs(rOuter[index]); + } + } + + theSolid = new G4Polycone(n, + thePcon->getSPhi(), + thePcon->getDPhi(), + nPlanes, + zPlane, + rInner, + rOuter); + } + // + // GeoCons + // + else if(geoShape->typeID() == GeoCons::getClassTypeID()) + { + const GeoCons* theCons = dynamic_cast<const GeoCons*>(geoShape); + if (nullptr==theCons) throw std::runtime_error("TypeID did not match cast for cons"); + if (n.empty()) n="G4Cons"; + if (theCons->getRMax1()<0.){ ATH_MSG_WARNING("Cons " << n << " has a max radius 1 of " << theCons->getRMax1() << " - will use std::abs.");} + if (theCons->getRMax2()<0.){ ATH_MSG_WARNING("Cons " << n << " has a max radius 2 of " << theCons->getRMax2() << " - will use std::abs.");} + if (theCons->getRMin1()<0.){ ATH_MSG_WARNING("Cons " << n << " has a min radius 1 of " << theCons->getRMin1());} + if (theCons->getRMin2()<0.){ ATH_MSG_WARNING("Cons " << n << " has a min radius 2 of " << theCons->getRMin2());} + if (theCons->getDZ()<=0){ ATH_MSG_WARNING("Cons " << n << " has a DZ of " << theCons->getDZ() << " - will use std::abs.");} + if (theCons->getRMax1()<=0. && theCons->getRMax2()<=0.){ ATH_MSG_WARNING("Cons " << n << " has a max radius 1 of " << theCons->getRMax1() + << " and a max radius 2 of " << theCons->getRMax2() << " - will use std::abs.");} + theSolid = new G4Cons(n, + theCons->getRMin1(), + std::abs(theCons->getRMax1()), + theCons->getRMin2(), + std::abs(theCons->getRMax2()), + std::abs(theCons->getDZ()), + theCons->getSPhi(), + theCons->getDPhi()); + } + // + // GeoPara + // + else if(geoShape->typeID() == GeoPara::getClassTypeID()) + { + const GeoPara* thePara = dynamic_cast<const GeoPara*>(geoShape); + if (nullptr==thePara) throw std::runtime_error("TypeID did not match cast for para"); + if (n.empty()) n="G4Para"; + if (thePara->getXHalfLength()<=0.){ ATH_MSG_WARNING("Para " << n << " has an x side of " << thePara->getXHalfLength() <<" - using std::abs.");} + if (thePara->getYHalfLength()<=0.){ ATH_MSG_WARNING("Para " << n << " has an y side of " << thePara->getYHalfLength() <<" - using std::abs.");} + if (thePara->getZHalfLength()<=0.){ ATH_MSG_WARNING("Para " << n << " has an z side of " << thePara->getZHalfLength() <<" - using std::abs.");} + theSolid = new G4Para(n, + std::abs(thePara->getXHalfLength()), + std::abs(thePara->getYHalfLength()), + std::abs(thePara->getZHalfLength()), + thePara->getAlpha(), + thePara->getTheta(), + thePara->getPhi()); + } + // + // GeoPgon + // + else if(geoShape->typeID() == GeoPgon::getClassTypeID()) + { + const GeoPgon* thePgon = dynamic_cast<const GeoPgon*>(geoShape); + if (nullptr==thePgon) throw std::runtime_error("TypeID did not match cast for pgon"); + if (n.empty()) n="G4Polyhedra"; + nPlanes = static_cast<int>(thePgon->getNPlanes()); + zPlane = new double[nPlanes]; + rInner = new double[nPlanes]; + rOuter = new double[nPlanes]; + double alpha = thePgon->getDPhi()/(2*thePgon->getNSides()); // 1/2 openning angle + for (unsigned int index=0; index<static_cast<unsigned int>(nPlanes); index++) + { + zPlane[index] = thePgon->getZPlane(index); + rInner[index] = thePgon->getRMinPlane(index)*cos(alpha); + rOuter[index] = thePgon->getRMaxPlane(index)*cos(alpha); + if (rInner[index]<0.){ ATH_MSG_WARNING("Pgon " << n << " has an inner radius of " << rInner[index] << " for slice " << index << " of " << nPlanes);} + if (rOuter[index]<=0.){ + ATH_MSG_WARNING("Pgon " << n << " has an outer radius of " << rOuter[index] << " for slice " << index << " of " << nPlanes << " - using std::abs."); + rOuter[index] = std::abs(rOuter[index]); + } + } + + theSolid = new G4Polyhedra(n, + thePgon->getSPhi(), + thePgon->getDPhi(), + thePgon->getNSides(), + nPlanes, + zPlane, + rInner, + rOuter); + } + // + // GeoTrap + // + else if(geoShape->typeID() == GeoTrap::getClassTypeID()) + { + const GeoTrap* theTrap = dynamic_cast<const GeoTrap*>(geoShape); + if (nullptr==theTrap) throw std::runtime_error("TypeID did not match cast for trap"); + if (n.empty()) n="G4Trap"; + if (theTrap->getZHalfLength()<=0.){ ATH_MSG_WARNING("Trap " << n << " has an z side of " << theTrap->getZHalfLength() <<" - using std::abs.");} + theSolid = new G4Trap(n, + std::abs(theTrap->getZHalfLength()), + theTrap->getTheta(), + theTrap->getPhi(), + theTrap->getDydzn(), + theTrap->getDxdyndzn(), + theTrap->getDxdypdzn(), + theTrap->getAngleydzn(), + theTrap->getDydzp(), + theTrap->getDxdyndzp(), + theTrap->getDxdypdzp(), + theTrap->getAngleydzp()); + } + // + // Simple Polygon Brep + // + else if(geoShape->typeID() == GeoSimplePolygonBrep::getClassTypeID()) + { + const GeoSimplePolygonBrep* theBrep = dynamic_cast<const GeoSimplePolygonBrep*>(geoShape); + if (nullptr==theBrep) throw std::runtime_error("TypeID did not match cast for brep"); + if (n.empty()) n="G4ExtrudedSolid"; + double dz = theBrep->getDZ(); + int nVertices = theBrep->getNVertices(); + + G4TwoVector off(0,0); + std::vector<G4TwoVector> polygon; + + for(int i=0; i<nVertices; i++) + polygon.push_back(G4TwoVector(theBrep->getXVertex(nVertices-1-i),theBrep->getYVertex(nVertices-1-i))); + + theSolid = new G4ExtrudedSolid(n,polygon,dz,off,1,off,1); + } + // + // Tessellated Solid + // + else if(geoShape->typeID() == GeoTessellatedSolid::getClassTypeID()) + { + const GeoTessellatedSolid* theTessellated = dynamic_cast<const GeoTessellatedSolid*>(geoShape); + if (nullptr==theTessellated) throw std::runtime_error("TypeID did not match cast for tessellated solid"); + if(n.empty()) n="G4TessellatedSolid"; + + G4TessellatedSolid* g4Tessellated = new G4TessellatedSolid(n); + for(size_t i=0; i<theTessellated->getNumberOfFacets(); ++i) { + GeoFacet* geoFacet = theTessellated->getFacet(i); + G4FacetVertexType vertexType = (geoFacet->getVertexType()==GeoFacet::ABSOLUTE? ABSOLUTE : RELATIVE); + G4VFacet* g4Facet(nullptr); + if(geoFacet->getNumberOfVertices()==3) + g4Facet = new G4TriangularFacet(Amg::EigenToHep3Vector(geoFacet->getVertex(0)), + Amg::EigenToHep3Vector(geoFacet->getVertex(1)), + Amg::EigenToHep3Vector(geoFacet->getVertex(2)), + vertexType); + else + g4Facet = new G4QuadrangularFacet(Amg::EigenToHep3Vector(geoFacet->getVertex(0)), + Amg::EigenToHep3Vector(geoFacet->getVertex(1)), + Amg::EigenToHep3Vector(geoFacet->getVertex(2)), + Amg::EigenToHep3Vector(geoFacet->getVertex(3)), + vertexType); + + g4Tessellated->AddFacet(g4Facet); + } + g4Tessellated->SetSolidClosed(true); + theSolid = g4Tessellated; + } + // + // Elliptical Tube + // + else if(geoShape->typeID() == GeoEllipticalTube::getClassTypeID()) + { + const GeoEllipticalTube* theEltube = dynamic_cast<const GeoEllipticalTube*>(geoShape); + if (nullptr==theEltube) throw std::runtime_error("TypeID did not match cast for elliptical tube"); + if (n.empty()) n="G4EllipticalTube"; + + if (theEltube->getXHalfLength()<=0.){ ATH_MSG_WARNING("Eltube " << n << " has an x side of " << theEltube->getXHalfLength() <<" - using std::abs.");} + if (theEltube->getYHalfLength()<=0.){ ATH_MSG_WARNING("Eltube " << n << " has an y side of " << theEltube->getYHalfLength() <<" - using std::abs.");} + if (theEltube->getZHalfLength()<=0.){ ATH_MSG_WARNING("Eltube " << n << " has an z side of " << theEltube->getZHalfLength() <<" - using std::abs.");} + G4EllipticalTube* g4Eltube = new G4EllipticalTube(n + ,std::abs(theEltube->getXHalfLength()) + ,std::abs(theEltube->getYHalfLength()) + ,std::abs(theEltube->getZHalfLength())); + theSolid = g4Eltube; + } + // + // Torus + // + else if(geoShape->typeID() == GeoTorus::getClassTypeID() ) { + const GeoTorus* theTorus = dynamic_cast<const GeoTorus*> (geoShape); + if (nullptr==theTorus) throw std::runtime_error("TypeID did not match cast for torus"); + if (n.empty()) n="G4Torus"; + + theSolid = new G4Torus(n, + theTorus->getRMin(), + theTorus->getRMax(), + theTorus->getRTor(), + theTorus->getSPhi(), + theTorus->getDPhi()); + } + // + // Generic Trap + // + else if(geoShape->typeID() == GeoGenericTrap::getClassTypeID()) { + const GeoGenericTrap* theGenTrap = dynamic_cast<const GeoGenericTrap*>(geoShape); + if (nullptr==theGenTrap) throw std::runtime_error("TypeID did not match cast for generic trap"); + if (n.empty()) n="G4GenericTrap"; + if (theGenTrap->getZHalfLength()<=0.){ ATH_MSG_WARNING("GenTrap " << n << " has an z side of " << theGenTrap->getZHalfLength() <<" - using std::abs.");} + + // Translate vector of vertices from Eigen to CLHEP + std::vector<CLHEP::Hep2Vector> clhepVertices; + clhepVertices.reserve(theGenTrap->getVertices().size()); + for(const GeoTrf::Vector2D& geoVertex : theGenTrap->getVertices()) { + clhepVertices.push_back(CLHEP::Hep2Vector(geoVertex.x(),geoVertex.y())); + } + + G4GenericTrap* g4GenTrap = new G4GenericTrap(n + ,std::abs(theGenTrap->getZHalfLength()) + ,clhepVertices); + theSolid = g4GenTrap; + } + // + // Boolean volumes + // We make use of G4DisplacedSolid which is not documented in the manual but makes the implementation + // a lot simpler. + // + // GeoShapeShift + // + else if (geoShape->typeID() == GeoShapeShift::getClassTypeID() ) + { + const GeoShapeShift* theShapeShift = dynamic_cast<const GeoShapeShift*> (geoShape); + if (nullptr==theShapeShift) throw std::runtime_error("TypeID did not match cast for shape shift"); + if (n.empty()) n="DisplacedSolid"; + G4VSolid * undisplacedSolid = Build(theShapeShift->getOp()); + theSolid = new G4DisplacedSolid(n, undisplacedSolid, Amg::EigenTransformToCLHEP(theShapeShift->getX())); + } + // + // GeoShapeUnion + // + else if (geoShape->typeID() == GeoShapeUnion::getClassTypeID() ) + { + const GeoShapeUnion* theUnion = dynamic_cast<const GeoShapeUnion*> (geoShape); + if (nullptr==theUnion) throw std::runtime_error("TypeID did not match cast for union"); + if (n.empty()) n="Union"; + solidA = Build(theUnion->getOpA()); + solidB = Build(theUnion->getOpB()); + theSolid = new G4UnionSolid(n, solidA, solidB); + } + // + // GeoShapeIntersection + // + else if (geoShape->typeID() == GeoShapeIntersection::getClassTypeID() ) + { + const GeoShapeIntersection* theIntersection = dynamic_cast<const GeoShapeIntersection*>(geoShape); + if (nullptr==theIntersection) throw std::runtime_error("TypeID did not match cast for intersection"); + if (n.empty()) n="Intersection"; + solidA = Build(theIntersection->getOpA()); + solidB = Build(theIntersection->getOpB()); + theSolid = new G4IntersectionSolid(n, solidA, solidB); + } + // + // GeoShapeSubtraction + // + else if (geoShape->typeID() == GeoShapeSubtraction::getClassTypeID() ) + { + const GeoShapeSubtraction* theSubtraction = dynamic_cast<const GeoShapeSubtraction*>(geoShape); + if (nullptr==theSubtraction) throw std::runtime_error("TypeID did not match cast for subtraction"); + if (n.empty()) n="Subtraction"; + solidA = Build(theSubtraction->getOpA()); + solidB = Build(theSubtraction->getOpB()); + theSolid = new G4SubtractionSolid(n, solidA, solidB); + } + // + // Custom Shapes (presently LAr shapes only) + // + // else if(geoShape->typeID() == LArCustomShape::getClassTypeID()) + // { + // const LArCustomShape* customShape = dynamic_cast<const LArCustomShape*> (geoShape); + // if (nullptr==customShape) throw std::runtime_error("TypeID did not match cast for custom shape"); + // std::string customName = customShape->name(); + // customSolidMap::const_iterator it = customSolids.find(customName); + // if(it!=customSolids.end()) + // theSolid = it->second; + // else + // { + // theSolid = nullptr; + // // if(customName.find("Slice") != std::string::npos){ + // // theSolid = createLArWheelSliceSolid(customShape); + // // } else { + // // theSolid = createLArWheelSolid(customName, s_lwsTypes.at(customName) ); // map.at throws std::out_of_range exception on unknown shape name + // // } + // if ( nullptr == theSolid ) { + // std::string error = std::string("Can't create LArWheelSolid for name ") + customName + " in Geo2G4SolidFactory::Build"; + // throw std::runtime_error(error); + // } + + // if(theSolid != nullptr) customSolids[customName] = theSolid; + // } + // } + // + // Catch All + // + else + { + ATH_MSG_FATAL("Sorry this solid is not yet implemented... "); + ATH_MSG_FATAL(geoShape->type()); + ATH_MSG_FATAL("You will have a core dump..."); + return nullptr; + } + + sharedShapes[geoShape] = theSolid; + return theSolid; +} + +// G4VSolid* Geo2G4SolidFactory::createLArWheelSolid(const std::string& name, const LArWheelSolidDef_t & lwsdef) const { // LArWheelSolid_t wheelType, int zside +// LArWheelSolid_t wheelType = lwsdef.first; +// int zside = lwsdef.second; + +// LArWheelSolid * theLWS = new LArWheelSolid(name, wheelType, zside); + +// LArWheelSolidDDProxy * theLWS_p = new LArWheelSolidDDProxy(theLWS); +// // ownership is passed to detStore +// if ( detStore()->record(theLWS_p, name).isFailure() ) { +// ATH_MSG_WARNING("Can't store proxy for LArWheelSolid to the DetectorStore"); +// delete theLWS_p; +// } +// return theLWS; +// } + +// G4VSolid* Geo2G4SolidFactory::createLArWheelSliceSolid(const LArCustomShape* customShape) const +// { +// LArWheelSliceSolid *theLWS = new LArWheelSliceSolid(customShape->name(), customShape->calculator()); + +// LArWheelSolidDDProxy *theLWS_p = new LArWheelSolidDDProxy(theLWS); +// // ownership is passed to detStore +// if(detStore()->record(theLWS_p, theLWS->GetName()).isFailure()){ +// ATH_MSG_WARNING("Can't store proxy for LArWheelSolid to the DetectorStore"); +// delete theLWS_p; +// } +// return theLWS; +// } diff --git a/Simulation/G4Utilities/Geo2G4/src/Geo2G4SolidFactory.h b/Simulation/G4Utilities/Geo2G4/src/Geo2G4SolidFactory.h new file mode 100644 index 000000000..97c5d1301 --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/Geo2G4SolidFactory.h @@ -0,0 +1,56 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef GEO2G4_Geo2G4SolidFactory_h +#define GEO2G4_Geo2G4SolidFactory_h + +#include <map> +#include <string> + +#include "GaudiKernel/ServiceHandle.h" +//#include "GaudiKernel/StatusCode.h" + +#include "AthenaKernel/MsgStreamMember.h" +#include "StoreGate/StoreGateSvc.h" +// #include "LArWheelSolid_type.h" + +class G4VSolid; +class GeoShape; +// class LArCustomShape; + +class Geo2G4SolidFactory +{ +public: + typedef ServiceHandle<StoreGateSvc> StoreGateSvc_t; + // typedef std::pair<LArWheelSolid_t, int> LArWheelSolidDef_t; + // typedef std::map<std::string, LArWheelSolidDef_t> LArWheelSolid_typemap; + + Geo2G4SolidFactory(); + G4VSolid* Build(const GeoShape*, std::string name=std::string("")) const; + /// Log a message using the Athena controlled logging system + MsgStream& msg( MSG::Level lvl ) const { return m_msg << lvl; } + /// Check whether the logging system is active at the provided verbosity level + bool msgLvl( MSG::Level lvl ) const { return m_msg.get().level() <= lvl; } + + /** @brief The standard @c StoreGateSvc/DetectorStore + * Returns (kind of) a pointer to the @c StoreGateSvc + */ + StoreGateSvc_t& detStore() const; +private: + // G4VSolid* createLArWheelSolid(const std::string& name, const LArWheelSolidDef_t & lwsdef) const; + // G4VSolid* createLArWheelSliceSolid(const LArCustomShape* ) const; + + // static const LArWheelSolid_typemap s_lwsTypes; + + /// Private message stream member + mutable Athena::MsgStreamMember m_msg; + /// Pointer to StoreGate (detector store by default) + mutable StoreGateSvc_t m_detStore; +}; + +inline ServiceHandle<StoreGateSvc>& Geo2G4SolidFactory::detStore() const { + return m_detStore; +} + +#endif diff --git a/Simulation/G4Utilities/Geo2G4/src/Geo2G4Svc.cxx b/Simulation/G4Utilities/Geo2G4/src/Geo2G4Svc.cxx new file mode 100644 index 000000000..39435689a --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/Geo2G4Svc.cxx @@ -0,0 +1,121 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "Geo2G4Svc.h" +#include "VolumeBuilder.h" +#include "ExtParameterisedVolumeBuilder.h" + +void InitializeBuilders(Geo2G4AssemblyFactory*); + +Geo2G4Svc::Geo2G4Svc(const std::string& name, ISvcLocator* svcLocator) + : base_class(name,svcLocator) + , m_defaultBuilder(nullptr) + , m_getTopTransform(true) + , m_G4AssemblyFactory(nullptr) +{ + ATH_MSG_VERBOSE ("Creating the Geo2G4Svc."); + declareProperty("GetTopTransform", m_getTopTransform); +} +Geo2G4Svc::~Geo2G4Svc() +{;} + +StatusCode Geo2G4Svc::initialize() +{ + static int initialized=0; + if (initialized) + { + ATH_MSG_VERBOSE (" Geo2G4Svc already initialized."); + return StatusCode::SUCCESS; + } + ATH_MSG_VERBOSE ("Initializing the Geo2G4Svc."); + ATH_MSG_VERBOSE ("Creating all builders available."); + m_G4AssemblyFactory = std::make_unique<Geo2G4AssemblyFactory>(); + InitializeBuilders(m_G4AssemblyFactory.get()); // separate function not part of this class + + const std::string nameBuilder = "Extended_Parameterised_Volume_Builder"; //TODO Configurable property?? + this->SetDefaultBuilder(nameBuilder); + ATH_MSG_VERBOSE (nameBuilder << " --> set as default builder" ); + ATH_MSG_VERBOSE (nameBuilder << " --> ParamOn flag = " << m_defaultBuilder->GetParam()); + initialized=1; + if(msgLvl(MSG::VERBOSE)) + { + this->ListVolumeBuilders(); + } + return StatusCode::SUCCESS; +} + +StatusCode Geo2G4Svc::finalize() +{ + ATH_MSG_VERBOSE ("Finalizing the Geo2G4Svc."); + + // clear builders... + // TODO: replace with std::unique_ptr + for (auto &x : m_builders) { + if (x.second) + delete x.second; + } + + return StatusCode::SUCCESS; +} + +void Geo2G4Svc::handle(const Incident& ) +{ +} + +void Geo2G4Svc::RegisterVolumeBuilder(VolumeBuilder* vb) +{ + std::string key(vb->GetKey()); + if (m_builders.find(key)!=m_builders.end()) + { + ATH_MSG_DEBUG ("Trying to set an already existing builder "<<key); + ATH_MSG_DEBUG ("\t request ignored, nothing done "); + } + else + { + m_builders[key]=vb; + ATH_MSG_DEBUG ("Volume builder registered "<<key); + } +} + +void Geo2G4Svc::ListVolumeBuilders() const +{ + ATH_MSG_INFO("---- List of all Volume Builders registered with Geo2G4Svc ----"); + ATH_MSG_INFO("---------------------------------------------------------------"); + for (const auto& builder : m_builders) + { + ATH_MSG_INFO(" Volume Builder: "<<builder.second->GetKey()); + } + ATH_MSG_INFO("---------------------------------------------------------------"); + ATH_MSG_INFO(" default builder is "<<m_defaultBuilder->GetKey()); +} + +void Geo2G4Svc::UnregisterVolumeBuilder(VolumeBuilder* vb) +{ + const std::string key(vb->GetKey()); + if (m_builders.find(key)!=m_builders.end()) + { + ATH_MSG_DEBUG ("Removing builder "<<key<<" from the list"); + m_builders.erase(key); + } + else + { + ATH_MSG_ERROR ("Trying to remove a not-existing builder "<<key); + ATH_MSG_ERROR ("\t request ignored, nothing done "); + } +} + +VolumeBuilder* Geo2G4Svc::GetVolumeBuilder(std::string s) const +{ + const auto builderItr(m_builders.find(s)); + if (builderItr!=m_builders.end()) + { + return builderItr->second; + } + else + { + ATH_MSG_ERROR ("Trying to retrieve a not existing builder "<<s); + ATH_MSG_ERROR ("\treturning Default Builder"); + } + return m_defaultBuilder; +} diff --git a/Simulation/G4Utilities/Geo2G4/src/Geo2G4Svc.h b/Simulation/G4Utilities/Geo2G4/src/Geo2G4Svc.h new file mode 100644 index 000000000..f32f0fdd0 --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/Geo2G4Svc.h @@ -0,0 +1,50 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef GEO2G4_Geo2G4Svc_H +#define GEO2G4_Geo2G4Svc_H + +#include "G4AtlasInterfaces/IGeo2G4Svc.h" + +#include "AthenaBaseComps/AthService.h" +#include "GaudiKernel/IIncidentListener.h" + +#include "Geo2G4AssemblyFactory.h" +#include "Geo2G4AssemblyVolume.h" + +#include <string> +#include <map> +#include <memory> + +class VolumeBuilder; +typedef std::map< std::string, VolumeBuilder*,std::less<std::string> > BuilderMap; + +/// @todo NEEDS DOCUMENTATION +class Geo2G4Svc: public extends<AthService, IGeo2G4Svc, IIncidentListener> +{ +public: + Geo2G4Svc(const std::string& , ISvcLocator *); + virtual ~Geo2G4Svc(); + /// AthService methods + virtual StatusCode initialize() override final; + virtual StatusCode finalize() override final; + /// IIncidentListener methods - FIXME does this service actually need to listen for Incidents? + virtual void handle(const Incident&) override final; + /// Geo2G4SvcBase methods + virtual void RegisterVolumeBuilder(VolumeBuilder* vb) override final; + virtual void UnregisterVolumeBuilder(VolumeBuilder* vb) override final; + virtual void SetDefaultBuilder(VolumeBuilder *vb) override final {m_defaultBuilder=vb;} + virtual void SetDefaultBuilder(std::string n) override final {this->SetDefaultBuilder(this->GetVolumeBuilder(n));} + virtual VolumeBuilder* GetVolumeBuilder(std::string s) const override final; + virtual VolumeBuilder* GetDefaultBuilder() const override final {return m_defaultBuilder;} + virtual bool UseTopTransforms() const override final {return m_getTopTransform;} + virtual void ListVolumeBuilders() const override final; +private: + VolumeBuilder *m_defaultBuilder; + BuilderMap m_builders ; + bool m_getTopTransform; + std::unique_ptr<Geo2G4AssemblyFactory> m_G4AssemblyFactory; +}; + +#endif diff --git a/Simulation/G4Utilities/Geo2G4/src/Geo2G4SvcAccessor.h b/Simulation/G4Utilities/Geo2G4/src/Geo2G4SvcAccessor.h new file mode 100644 index 000000000..70a5956a6 --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/Geo2G4SvcAccessor.h @@ -0,0 +1,34 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef GEO2G4_Geo2G4SvcAccessor_H +#define GEO2G4_Geo2G4SvcAccessor_H + +#include "G4AtlasInterfaces/Geo2G4SvcBase.h" +#include "G4AtlasInterfaces/IGeo2G4Svc.h" + +#include "GaudiKernel/ISvcLocator.h" +#include "GaudiKernel/Bootstrap.h" + +class Geo2G4SvcAccessor { +public: + Geo2G4SvcBase* GetGeo2G4Svc() const; +}; + +inline Geo2G4SvcBase* Geo2G4SvcAccessor::GetGeo2G4Svc() const +{ + IService* g2gSvc; + ISvcLocator* svcLocator = Gaudi::svcLocator(); // from Bootstrap + StatusCode result = svcLocator->service("Geo2G4Svc",g2gSvc); + + if(result.isSuccess()) + { + Geo2G4SvcBase* temp=dynamic_cast<Geo2G4SvcBase*>(g2gSvc); + return temp; + } + else + return 0; +} + +#endif diff --git a/Simulation/G4Utilities/Geo2G4/src/GeoDetectorTool.cxx b/Simulation/G4Utilities/Geo2G4/src/GeoDetectorTool.cxx new file mode 100644 index 000000000..53ea20418 --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/GeoDetectorTool.cxx @@ -0,0 +1,117 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +// Base class +#include "G4AtlasTools/DetectorGeometryBase.h" +#include "GeoDetectorTool.h" +#include "Geo2G4Builder.h" +#include "VolumeBuilder.h" + +#include "G4NistManager.hh" +#include "G4LogicalVolume.hh" +#include "G4PVPlacement.hh" +#include "G4GDMLParser.hh" + +// Geant4 includes used in functions + +GeoDetectorTool::GeoDetectorTool(const std::string& type, const std::string& name, const IInterface* parent) + : DetectorGeometryBase(type,name,parent),m_blParamOn(false),m_blGetTopTransform(true),m_geoDetectorName("") +{ + m_topTransform.setIdentity(); + ATH_MSG_DEBUG( "GeoDetectorTool constructor for " << name ); + declareProperty("GeoDetectorName",m_geoDetectorName, "Name of the detector in GeoModel, if different from G4."); + declareProperty("GDMLFileOut",m_dumpGDMLFile,"File name where the GDML description for the detector will be dumped."); + +} + +StatusCode GeoDetectorTool::initialize() +{ + ATH_MSG_VERBOSE( name() << " GeoDetectorTool::initialize(): Starting" ); + if(m_detectorName.empty()) + { + m_detectorName = this->name(); + // re-initialize m_detectorName in order to take the real detector name rather than the path to it + size_t ipos=m_detectorName.find_last_of("."); + size_t length=m_detectorName.size(); + if (ipos<length) + { + ATH_MSG_VERBOSE( "m_detectorName: " << m_detectorName << " needs to be reset."); + m_detectorName=m_detectorName.substr(ipos+1,length-ipos-1); + ATH_MSG_VERBOSE( "m_detectorName default value reset to " << m_detectorName); + } + } + ATH_MSG_DEBUG( name() << "GeoDetectorTool::initialize() : Detector name = " << m_detectorName ); + if(m_geoDetectorName.empty()) + { + m_geoDetectorName = m_detectorName; + } + ATH_MSG_DEBUG( name() << "GeoDetectorTool::initialize() : Geo Detector name = " << m_geoDetectorName ); + + ATH_CHECK(m_geo2G4Svc.retrieve()); + m_builderName = m_geo2G4Svc->GetDefaultBuilder()->GetKey(); + m_blGetTopTransform = m_geo2G4Svc->UseTopTransforms(); + ATH_MSG_VERBOSE( name() << " GeoDetectorTool::initialize(): UseTopTransforms = " << m_blGetTopTransform ); + ATH_MSG_VERBOSE( name() << " GeoDetectorTool::initialize(): Finished" ); + return StatusCode::SUCCESS; +} + + +void GeoDetectorTool::BuildGeometry() +{ + ATH_MSG_VERBOSE( name() << " GeoDetectorTool::BuildGeometry(): Starting" ); + G4LogicalVolume* temp = this->Convert(); + m_envelope.theEnvelope=temp; + + if (this->IsTopTransform()) + { + this->SetInitialTransformation(); + } + ATH_MSG_VERBOSE( name() << " GeoDetectorTool::BuildGeometry(): Finished" ); +} + +void GeoDetectorTool::PositionInParent() +{ + ATH_MSG_DEBUG( name() << " GeoDetectorTool::PositionInParent(): Starting" ); + + DetectorGeometryBase::PositionInParent(); + if (!m_dumpGDMLFile.empty()) { + G4GDMLParser parser; + parser.Write(m_dumpGDMLFile,m_envelope.thePositionedVolume); + } +} + +G4LogicalVolume* GeoDetectorTool::Convert() +{ + ATH_MSG_VERBOSE( name() << " GeoDetectorTool::Convert(): Starting" ); + ATH_MSG_DEBUG( name() << " GeoDetectorTool::Convert(): GeoDetectorName:builderName = "<<m_geoDetectorName<<":"<<m_builderName); + Geo2G4Builder Builder(m_geoDetectorName); + VolumeBuilder *b=Builder.GetVolumeBuilder(m_builderName); + b->SetParam(m_blParamOn); + G4LogicalVolume *temp=Builder.BuildTree(); + if(this->IsTopTransform()) + { + m_topTransform = Builder.GetDetectorTransform(); + } + + ATH_MSG_VERBOSE( name() << " GeoDetectorTool::Convert(): Finished" ); + return temp; +} + +bool GeoDetectorTool::IsTopTransform() +{ + return m_blGetTopTransform; +} + +void GeoDetectorTool::SetInitialTransformation() +{ + ATH_MSG_VERBOSE( name() << " GeoDetectorTool::SetInitialTransformation(): Starting" ); + if (!m_envelope.theRotation) + { + ATH_MSG_VERBOSE( name() << " GeoDetectorTool::SetInitialTransformation(): Creating new G4RotationMatrix" ); + m_envelope.theRotation=new G4RotationMatrix; + } + *(m_envelope.theRotation)=m_topTransform.getRotation().inverse(); + m_envelope.thePosition=m_topTransform.getTranslation(); + ATH_MSG_VERBOSE( name() << " GeoDetectorTool::SetInitialTransformation(): Finished" ); +} diff --git a/Simulation/G4Utilities/Geo2G4/src/GeoDetectorTool.h b/Simulation/G4Utilities/Geo2G4/src/GeoDetectorTool.h new file mode 100644 index 000000000..b4eb6489f --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/GeoDetectorTool.h @@ -0,0 +1,61 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef GEO2G4_GeoDetectorTool_H +#define GEO2G4_GeoDetectorTool_H + +// Base classes +#include "G4AtlasTools/DetectorGeometryBase.h" +//#include "G4AtlasInterfaces/IDetectorGeometrySvc.h" +#include "G4AtlasInterfaces/IGeo2G4Svc.h" + +#include "G4Transform3D.hh" + +// Members + +// STL library +#include <string> +#include <vector> + +/** @class GeoDetectorTool GeoDetectorTool.h "G4AtlasTools/GeoDetectorTool.h" +* +* Tool for building detectors out of a GeoModel description. Basically a +* carbon copy of GeoDetectorFacility in GeoDetectorPlugins which is supposed +* to replace. +* +* @author Andrea Dell'Acqua +* @date 2015-03-10 +*/ + +class GeoDetectorTool final : public DetectorGeometryBase +{ +public: + // Basic constructor and destructor + GeoDetectorTool(const std::string& type, const std::string& name, const IInterface *parent); + ~GeoDetectorTool() {} + + /** Athena method. called at initialization time, being customized here */ + virtual StatusCode initialize() override final; + + /** virtual methods being implemented here */ + + virtual void BuildGeometry() override final; + + virtual void PositionInParent() override final; + +private: + + std::string m_builderName; + std::string m_dumpGDMLFile=""; + bool m_blParamOn; + bool m_blGetTopTransform; + G4Transform3D m_topTransform; + std::string m_geoDetectorName; + G4LogicalVolume* Convert(); + bool IsTopTransform(); + void SetInitialTransformation(); + ServiceHandle<IGeo2G4Svc> m_geo2G4Svc{this, "Geo2G4Svc", "Geo2G4Svc", ""}; +}; + +#endif diff --git a/Simulation/G4Utilities/Geo2G4/src/InitializeBuilders.cxx b/Simulation/G4Utilities/Geo2G4/src/InitializeBuilders.cxx new file mode 100644 index 000000000..7a002c344 --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/InitializeBuilders.cxx @@ -0,0 +1,12 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "ExtParameterisedVolumeBuilder.h" +#include "Geo2G4AssemblyFactory.h" + +void InitializeBuilders(Geo2G4AssemblyFactory* assemblyFactory) +{ + ExtParameterisedVolumeBuilder *epb __attribute__ ((unused)) = + new ExtParameterisedVolumeBuilder("Extended_Parameterised_Volume_Builder", assemblyFactory); +} diff --git a/Simulation/G4Utilities/Geo2G4/src/SingleLogicalVolumeFactory.cxx b/Simulation/G4Utilities/Geo2G4/src/SingleLogicalVolumeFactory.cxx new file mode 100644 index 000000000..24ae0c0d6 --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/SingleLogicalVolumeFactory.cxx @@ -0,0 +1,44 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "SingleLogicalVolumeFactory.h" +#include "Geo2G4SolidFactory.h" +#include "GeoMaterial2G4/Geo2G4MaterialFactory.h" +#include "GeoModelKernel/GeoLogVol.h" +#include "SimHelpers/ServiceAccessor.h" +#include "AthenaBaseComps/AthMsgStreamMacros.h" +#include "G4LogicalVolume.hh" +#include "G4Material.hh" + +SingleLogicalVolumeFactory::SingleLogicalVolumeFactory(): m_msg("SingleLogicalVolumeFactory") +{ +} + +typedef std::map<std::string, G4LogicalVolume*, std::less<std::string> > vMap; + +G4LogicalVolume *SingleLogicalVolumeFactory::Build(const GeoLogVol* theLog) const +{ + static Geo2G4SolidFactory theSolidFactory; + static Geo2G4MaterialFactory theMaterialFactory; + static vMap volumeList; + // + // Get Material from GeoModel + // + std::string n= theLog->getName(); + if (volumeList.find(n) == volumeList.end()) { + G4LogicalVolume *theG4Log=0; + G4Material* theG4Mat=theMaterialFactory.Build(theLog->getMaterial()); + + G4VSolid * theG4Solid = theSolidFactory.Build(theLog->getShape()); + + ATH_MSG_DEBUG("Building logical volume (single) "<<theLog->getName()<< " " << theG4Mat); + theG4Log = new G4LogicalVolume(theG4Solid, + theG4Mat, + theLog->getName(), + 0,0,0); + volumeList[n] = theG4Log; + return theG4Log; + } + return volumeList[n]; +} diff --git a/Simulation/G4Utilities/Geo2G4/src/SingleLogicalVolumeFactory.h b/Simulation/G4Utilities/Geo2G4/src/SingleLogicalVolumeFactory.h new file mode 100644 index 000000000..7a089ee90 --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/SingleLogicalVolumeFactory.h @@ -0,0 +1,29 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef GEO2G4_SingleLogicalVolumeFactory_h +#define GEO2G4_SingleLogicalVolumeFactory_h + +#include "AthenaKernel/MsgStreamMember.h" + +class G4LogicalVolume; +class GeoLogVol; + +#include <string> +#include <map> + +class SingleLogicalVolumeFactory { +public: + SingleLogicalVolumeFactory(); + G4LogicalVolume* Build(const GeoLogVol*) const; + /// Log a message using the Athena controlled logging system + MsgStream& msg( MSG::Level lvl ) const { return m_msg << lvl; } + /// Check whether the logging system is active at the provided verbosity level + bool msgLvl( MSG::Level lvl ) const { return m_msg.get().level() <= lvl; } + private: + /// Private message stream member + mutable Athena::MsgStreamMember m_msg; +}; + +#endif diff --git a/Simulation/G4Utilities/Geo2G4/src/VolumeBuilder.h b/Simulation/G4Utilities/Geo2G4/src/VolumeBuilder.h new file mode 100644 index 000000000..afc5195d0 --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/VolumeBuilder.h @@ -0,0 +1,52 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef GEO2G4_VolumeBuilder_H +#define GEO2G4_VolumeBuilder_H + +#include "G4LogicalVolume.hh" +#include "Geo2G4SvcAccessor.h" + +#include "GeoModelUtilities/GeoOpticalPhysVol.h" + +#include "G4VPhysicalVolume.hh" + +#include <string> +#include <iostream> +#include <map> + +typedef std::map< const GeoOpticalPhysVol*, G4VPhysicalVolume*,std::less< const GeoOpticalPhysVol*> > OpticalVolumesMap; + +class VolumeBuilder +{ + public: + VolumeBuilder(std::string k): m_paramOn(false), m_key(k) + { + Geo2G4SvcAccessor accessor; + Geo2G4SvcBase *g=accessor.GetGeo2G4Svc(); + g->RegisterVolumeBuilder(this); + } + + virtual ~VolumeBuilder() + { + Geo2G4SvcAccessor accessor; + Geo2G4SvcBase *g=accessor.GetGeo2G4Svc(); + g->UnregisterVolumeBuilder(this); + } + + std::string GetKey() const {return m_key;} + + // flag controlling Parameterization to Parameterization translation + void SetParam(bool flag){m_paramOn = flag;} + bool GetParam(){return m_paramOn;} + + virtual G4LogicalVolume* Build(PVConstLink pv, OpticalVolumesMap* optical_volumes = 0) = 0; + + protected: + bool m_paramOn; + + private: + std::string m_key; +}; +#endif diff --git a/Simulation/G4Utilities/Geo2G4/src/components/Geo2G4_entries.cxx b/Simulation/G4Utilities/Geo2G4/src/components/Geo2G4_entries.cxx new file mode 100644 index 000000000..103fd8729 --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/components/Geo2G4_entries.cxx @@ -0,0 +1,7 @@ +#include "../Geo2G4Svc.h" +#include "../GeoDetectorTool.h" +#include "../GDMLDetectorTool.h" + +DECLARE_COMPONENT( Geo2G4Svc ) +DECLARE_COMPONENT( GeoDetectorTool ) +DECLARE_COMPONENT( GDMLDetectorTool ) diff --git a/Simulation/G4Utilities/Geo2G4/src/lcg_dict/selection.xml b/Simulation/G4Utilities/Geo2G4/src/lcg_dict/selection.xml new file mode 100644 index 000000000..98e02df07 --- /dev/null +++ b/Simulation/G4Utilities/Geo2G4/src/lcg_dict/selection.xml @@ -0,0 +1,3 @@ +<lcgdict> + <class name="LArWheelSolidDDProxy" /> +</lcgdict> diff --git a/Simulation/README.md b/Simulation/README.md new file mode 100644 index 000000000..14718f6d7 --- /dev/null +++ b/Simulation/README.md @@ -0,0 +1,10 @@ +To generate Calypso MC data from an installation (run) directory: + +1) edit the G4FaserApp/test/runG4.py file to setup the job +....the default generator is particle-gun; it can also read EVNT files but note that the Veto is far away from (0,0,0) where most ATLAS generators put things by default +....read the comments carefully as a few other things have to be changed in the job options to switch between internal generator and generator data-file + +2) source ./setup.sh +3) runG4.py + +(setup.sh will put the script in your path) diff --git a/graphics/VTI12/README.md b/graphics/VTI12/README.md new file mode 100644 index 000000000..48657faa6 --- /dev/null +++ b/graphics/VTI12/README.md @@ -0,0 +1,9 @@ +To run on Calypso MC data (from an installation (run) directory): + +% source ./setup.sh + +% export VP1PLUGINPATH=./lib + +% vti12 -mc -noautoconf <input HITS or EVNT file> + +Note that VP1PLUGINPATH can be ninja-changed by asetup, and if it does not include the installation library folder, nothing will work \ No newline at end of file diff --git a/graphics/VTI12/VTI12Algs/CMakeLists.txt b/graphics/VTI12/VTI12Algs/CMakeLists.txt new file mode 100644 index 000000000..6c233e645 --- /dev/null +++ b/graphics/VTI12/VTI12Algs/CMakeLists.txt @@ -0,0 +1,62 @@ +################################################################################ +# Package: VTI12Algs +################################################################################ + +# Declare the package name: +atlas_subdir( VTI12Algs ) + +# Declare the package's dependencies: +atlas_depends_on_subdirs( PUBLIC + Control/AthenaBaseComps + GaudiKernel + PRIVATE + Event/EventInfo + Tools/PathResolver + graphics/VTI12/VTI12Gui + graphics/VTI12/VP1UtilsBase ) + +# "Externals" dependencies - They are needed at runtime, only +find_package( libxkbcommon ) +find_package( glib ) +find_package( libffi ) + +# Component(s) in the package: +atlas_add_component( VTI12Algs + src/*.cxx + src/components/*.cxx + LINK_LIBRARIES AthenaBaseComps GaudiKernel EventInfo PathResolver + PRIVATE_LINK_LIBRARIES VTI12Gui VP1UtilsBase ) + +# Install files from the package: +atlas_install_headers( VTI12Algs ) +atlas_install_python_modules( python/*.py ) +atlas_install_joboptions( share/*.py ) +atlas_install_scripts( share/vti12 ) +atlas_install_scripts( share/clear-bash-hash-table-vp1 ) + +#---------------------------------------------------------- +# CONFIGURING THE ENVIRONMENT VARIABLES FOR THE PACKAGE # +# +#message( "CMAKE_BINARY_DIR path:" ${CMAKE_BINARY_DIR} ) +#message( "ATLAS_PLATFORM path:" ${ATLAS_PLATFORM} ) +# set a variable to be used in the 'Config' script. +# The variable will be substituted with the path when file is 'configured' +# and copied from 'source' to 'binary' +set( BUILD_DIR ${CMAKE_BINARY_DIR}/${ATLAS_PLATFORM} ) +# Configure the environment setup module. +# The 'configure_file' command here below copies the input file in the 'source' dir +# to the output file in 'binary' dir, e.g. in ../build/graphics/VP1/VP1Algs/ +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/VTI12AlgsEnvironmentConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/VTI12AlgsEnvironmentConfig.cmake + @ONLY ) +# Set the folder where CMake can find the 'Config' file for the dummy package +set( VTI12AlgsEnvironment_DIR ${CMAKE_CURRENT_BINARY_DIR} + CACHE PATH "Location of VTI12AlgsEnvironmentConfig.cmake" + FORCE + ) +# And now "find" it! It will set the env vars defined in the package's 'Config' file. +find_package( VTI12AlgsEnvironment ) +# message( "VP1PLUGINPATH has been set to: " $ENV{VP1PLUGINPATH} ) + + diff --git a/graphics/VTI12/VTI12Algs/VTI12AlgsEnvironmentConfig.cmake.in b/graphics/VTI12/VTI12Algs/VTI12AlgsEnvironmentConfig.cmake.in new file mode 100644 index 000000000..f91e98774 --- /dev/null +++ b/graphics/VTI12/VTI12Algs/VTI12AlgsEnvironmentConfig.cmake.in @@ -0,0 +1,13 @@ +# --- Set the environment variables need by the package VP1Algs --- +# rbianchi@cern.ch - Nov 2016, Feb 2018 + +# Set the environment variables + + +set( VP1ALGSENVIRONMENT_ENVIRONMENT + FORCESET VP1PLUGINPATH \${@CMAKE_PROJECT_NAME@_DIR}/lib + ) + +# Silently declare the module found +set( VP1ALGSENVIRONMENT_FOUND TRUE ) + diff --git a/graphics/VTI12/VTI12Algs/share/vti12 b/graphics/VTI12/VTI12Algs/share/vti12 new file mode 100644 index 000000000..803466b4e --- /dev/null +++ b/graphics/VTI12/VTI12Algs/share/vti12 @@ -0,0 +1,1216 @@ +#!/bin/bash + +# Script for constructing command which launches athena on vp1.py, with appropriate options (in the -c flag). +# +# Author: Thomas.Kittelmann@cern.ch +# First useful version: July 2007 +# +# Modified: Manuel.Proissl@cern.ch, March 2012 +# Riccardo.Maria.Bianchi@cern.ch, multiple times +# Edward.Moyse@cern.ch, multiple times +# +# Current Maintainers: +# - Riccardo.Maria.Bianchi@cern.ch +# - Edward.Moyse@cern.ch +# +# Questions: Riccardo.Maria.Bianchi@cern.ch +# +# + + +#fixme/todo: option to start cruise mode (event/second) +#fixme/todo: MULTINP_CPY should not be allowed to exist beforehand! + + +### TERMINAL COLORS ### +GREEN='\033[1;32m' +YELLOW='\033[1;33m' +LIGHTBLUE='\033[1;34m' +RED='\033[0;31m' +WHITE='\033[0;97m' +UNDERLINED='\033[4m' +BOLD='\033[1m' +NC='\033[0m' # No Color +# then use: +# - printf "I ${RED}love${NC} Stack Overflow\n" +# - echo -e "I ${RED}love${NC} Stack Overflow" + + + +echo +echo "******************************************" +echo +echo "Launching VTI12 - the FASER 3D event display" +echo +echo "******************************************" +echo +echo + +################################################## +# Workaraound for LD_PRELOAD # +# # +# Details: # +# https://its.cern.ch/jira/browse/ATLASVPONE-228 # +# # +################################################## +echo -e "${LIGHTBLUE}*** VP1 NOTE ***${NC} setting LD_PRELOAD=/usr/lib64/libGL.so.1 env var, to correctly load OpenGL before all other TLS libs. That is caused by a bug in Red Hat 6. For details, see: https://its.cern.ch/jira/browse/ATLASVPONE-228" +export LD_PRELOAD=/usr/lib64/libGL.so.1 +################################################## + +################################################## +# Workaraound for keyboard input issue on LXPLUS # +# # +# Details: # +# https://its.cern.ch/jira/browse/ATLASVPONE-380 # +# # +################################################## +if [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then + # We are on a GNU/Linux platform machine + if [[ $(hostname) == lxplus* ]]; then + # We are on a LXPLUS machine + echo "uname: " "$(expr substr $(uname -s) 1 5)" + echo "hostname: " "$(hostname)" + echo -e "${LIGHTBLUE}*** VP1 NOTE ***${NC} you are running VP1 remotely on a LXPLUS machine. Hence, we set the 'QT_XKB_CONFIG_ROOT environment variable to fix the problem LXPLUS machine have with the new Qt5 framework, which prevent a proper detection of keyboard events. For details, see: https://its.cern.ch/jira/browse/ATLASVPONE-380." + export QT_XKB_CONFIG_ROOT=/usr/share/X11/xkb + fi # closes "lxplus" +fi # closes "Linux" +################################################## + + + +APP=`basename $0` + +which athena.py > /dev/null 2>&1 +if [ $? != 0 ]; then + echo "Error: athena.py not found in path. Please setup atlas release before running" + exit 1 +fi + + +####################################### +## Warning Messages ## +####################################### +MUSTQUIT=0 +if [ -z ${Athena_VERSION+x} ]; then + echo "ERROR! The variable 'Athena_VERSION' is unset! Apparently Athena is not properly set. Quitting..." + MUSTQUIT=1 +else + if [[ ${Athena_VERSION} =~ ^21\. ]]; then + echo; echo -e " ${RED}${BOLD} *** WARNING! Release 21 detected! *** ${NC}"; echo + echo -e " Apparently, you are using the Release 21 of the Athena environment. Unfortunately, VP1 does not work in rel. 21. ${UNDERLINED}Please use a release >= 22, or the 'master' release${NC}. By using them, you can still access and visualize data produced with rel. 21, if you need that." + echo; echo -e " ${RED}${BOLD}--->${NC} Please refer to the instructions published at: ${NC}${BOLD}${UNDERLINED} http://atlas-vp1.web.cern.ch/atlas-vp1/home/documentation/running-the-latest-vp1-version/${NC} ${RED}${BOLD}<---${NC}"; echo; echo + MUSTQUIT=1 + fi +fi + +if [ $MUSTQUIT -eq 1 ]; then + exit 1; +fi + + + + +####################################### +## Init config variables ## +####################################### + +LIVEDEFAULTDETDESCR="ATLAS-GEO-10-00-00" +LIVEDEFAULTGLOBCOND="COMCOND-BLKPST-004-01" +LIVEDEFAULTEVENTSRC="https://atlas-live.cern.ch/event_files/L1MinBias/vp1fileinfo.txt" +LIVELOCALDEFAULTEVENTSRC="/VP1_events/" +LIVEBOOTSTRAPSRC="http://atlas-vp1.web.cern.ch/atlas-vp1/live-bootstrap/vp1fileinfo.txt" + +declare -a FILES_POOLROOT +declare -a FILES_VP1CFG +declare -a FILES_EXTRAJOBOPT +declare -a LOCALEVENTSRC_AVAILDIRS +FLAG_HELP=0 +FLAG_DATA=0 +FLAG_TEST=0 +ERRORS="" +DETDESCRTAG="" +GLOBCONDTAG="" +SKIPEVENTS="" +CRUISEWITHTIME="" +LOGFILE="" +FILTEREVENTS="" +FLAG_BATCH=0 +FLAG_BATCH_RANDOM_CONFIG=0 +FLAG_BATCH_ALL_EVENTS=0 +FLAG_BATCH_N_EVENTS=0 +FLAG_BATCH_OUT_FOLDER="" +FLAG_LARHV=0 +# FLAG_FULLTOROIDS=0 +FLAG_DONTCLEANUPEVTCPY=0 +FLAG_LIVE=0 +FLAG_LIVELOCAL=0 +FLAG_NOAUTOCONF=0 +FLAG_TRIG=0 +FLAG_NOCALO=0 +FLAG_NOID=0 +FLAG_NOSORTDBREPLICAS=0 +FLAG_NOMUON=0 +FLAG_LUCID=0 +FLAG_ONLINE=0 +FLAG_ALFA=0 +FLAG_FORWARD_REGION=0 +FLAG_ZDC=0 +FLAG_CAVERN=0 +FLAG_TOYDETECTOR=0 +FLAG_GEOMODELSTATS=0 +FLAG_EXTRAPOLATOR=0 +FLAG_NOEXTRAPOLATOR=0 +FLAG_FITTER=0 +FLAG_MC=0 +FLAG_FATRAS=0 +FLAG_NOGUI=0 +FLAG_CGAL=0 +FLAG_NSW=0 +FLAG_SLHC=0 +#FLAG_CUSTOMGEOMETRY=0 # currently not used +FLAG_ADVANCED_ANTIALIASING=0 +MULTINP_SRC="" +MULTINP_CPY="" +TRIGDEC="" +FATRAS_TRUTHKEY="" +ATHENAOPTS="" + +####################################### +## Decode command line options ## +####################################### + +#echo -e "\nnumber of positional parameters (args): " $# # for DEBUG only + +# index init +i=1 + +# start looping over the number of positional parameters ($#) +while [ $i -le $# ]; do + + # get the i-positional parameter + arg=${!i} + + #echo -e "\nevaluating arg: " $arg # for DEBUG only + + ################ + # HELP / USAGE # + ################ + if [ "x${arg}" == "x-h" -o "x${arg}" == "x-help" -o "x${arg}" == "x--help" ]; then + FLAG_HELP=1 + + + ######################## + # COMMAND-LINE OPTIONS # + ######################## + + elif [ "x${arg}" == "x-larhv" ]; then + FLAG_LARHV=1 + # elif [ "x${arg}" == "x-fulltoroids" ]; then + # FLAG_FULLTOROIDS=1 + elif [ "x${arg}" == "x-live" ]; then + FLAG_LIVE=1 + elif [ "x${arg}" == "x-livelocal" ]; then + FLAG_LIVELOCAL=1 + # + # + # + #----------- + # BATCH MODE + #----------- + # check if the user provided config files with -batch/-b options + elif [ "x${arg}" == "x-batch" -o "x${arg}" == "x-b" ]; then + if [[ "$*" == *.vp1* ]] + then + FLAG_BATCH=1 + # text in bold, note in bold and red. at the end we reset the text style + echo "" + echo -e "\e[1m\e[31m\e[4mNote!\e[24m You chose to run VP1 in 'batch-mode' ('${arg}').\e[39m" + echo -e "Thus, the main VP1 window will be not shown, but in the end you will get a PNG file with the rendered image of the 3D window, based on the configuration file you provided.\e[0m" + echo "" + else + ERRORS="$ERRORS\nBatch mode needs at least one configuration file ('.vp1')" + fi + elif [ "x${arg}" == "x-batch-all-events" ]; then + FLAG_BATCH_ALL_EVENTS=1 + elif [ "x${arg}" == "x-batch-random-config" ]; then + FLAG_BATCH_RANDOM_CONFIG=1 + elif [ "x${arg:0:21}" == "x-batch-output-folder=" ]; then + FLAG_BATCH_OUT_FOLDER=${arg:21:$((${#arg}-21))} + if [ "x$FLAG_BATCH_OUT_FOLDER" == "x" ]; then + ERRORS="$ERRORS\nNeed argument to -batch-output-folder. Ex: -batch-output-folder=myFolder" + fi + elif [ "x${arg:0:21}" == "x-batch-output-folder" ]; then # catch arg without '=' character + FLAG_BATCH_OUT_FOLDER_2=${arg:20:$((${#arg}-20))} + if [ "x$FLAG_BATCH_OUT_FOLDER_2" == "x" ]; then + ERRORS="$ERRORS\nNeed argument to -batch-output-folder. Ex: -batch-output-folder=path/to/myFolder" + fi + elif [ "x${arg:0:16}" == "x-batch-n-events=" ]; then + FLAG_BATCH_N_EVENTS=${arg:16:$((${#arg}-16))} + echo -e "\e[1m\e[31m\e[4mNote!\e[24m You chose to run VP1 in 'batch-mode' over ${FLAG_BATCH_N_EVENTS} events ('${arg}'). VP1 will exit after having processed the given number of events.\e[39m" + if [ "x$FLAG_BATCH_N_EVENTS" == "x" ]; then + ERRORS="$ERRORS\nNeed a numeric argument to -batch-n-events" + else + #check it is integer: + echo "$FLAG_BATCH_N_EVENTS" | grep '^[0-9][0-9]*$' > /dev/null 2>&1 || \ + ERRORS="$ERRORS\nArgument to -batch-n-events must be an integer!" + fi + #echo "(sleeping for 2 secs...)" + echo "" + sleep 2s # to let the user read the warning messages about the batch mode + ### end of batch mode settings + # + # + elif [ "x${arg}" == "x-noautoconf" ]; then + FLAG_NOAUTOCONF=1 + elif [ "x${arg}" == "x-nocleanupeventcpy" ]; then + FLAG_DONTCLEANUPEVTCPY=1 + elif [ "x${arg}" == "x-data" ]; then + FLAG_DATA=1 + elif [ "x${arg}" == "x-test" ]; then + FLAG_TEST=1 + elif [ "x${arg}" == "x-trig" ]; then + FLAG_TRIG=1 + elif [ "x${arg}" == "x-nocalo" ]; then + FLAG_NOCALO=1 + elif [ "x${arg}" == "x-noid" ]; then + FLAG_NOID=1 + elif [ "x${arg}" == "x-nomuon" ]; then + FLAG_NOMUON=1 + elif [ "x${arg}" == "x-nosortdbreplicas" ]; then + FLAG_NOSORTDBREPLICAS=1 + elif [ "x${arg}" == "x-lucid" ]; then + FLAG_LUCID=1 + elif [ "x${arg}" == "x-online" ]; then + FLAG_ONLINE=1 + elif [ "x${arg}" == "x-alfa" ]; then + FLAG_ALFA=1 + elif [ "x${arg}" == "x-forwardregion" ]; then + FLAG_FORWARD_REGION=1 + elif [ "x${arg}" == "x-zdc" ]; then + FLAG_ZDC=1 + elif [ "x${arg}" == "x-cavern" ]; then + FLAG_CAVERN=1 + elif [ "x${arg}" == "x-toy-detector" ]; then + FLAG_TOYDETECTOR=1 + elif [ "x${arg}" == "x-geomodel-stats" ]; then + FLAG_GEOMODELSTATS=1 + elif [ "x${arg}" == "x-extrapolator" ]; then + FLAG_EXTRAPOLATOR=1 + elif [ "x${arg}" == "x-noextrapolator" ]; then + FLAG_NOEXTRAPOLATOR=1 + elif [ "x${arg}" == "x-refit" ]; then + FLAG_FITTER=1 + elif [ "x${arg}" == "x-fatras" ]; then + FLAG_FATRAS=1 + elif [ "x${arg}" == "x-nogui" ]; then + FLAG_NOGUI=1 + elif [ "x${arg}" == "x-cgal" ]; then + FLAG_CGAL=1 + elif [ "x${arg}" == "x-nsw" ]; then + FLAG_NSW=1 + elif [ "x${arg}" == "x-slhc" ]; then + echo "SLHC" + FLAG_SLHC=1 + #elif [ "x${arg}" == "x-customgeom" ]; then + # FLAG_CUSTOMGEOMETRY=1 + elif [ "x${arg}" == "x-advanced-aa" ]; then + FLAG_ADVANCED_ANTIALIASING=1 + export VP1_ADVANCED_ANTIALIASING=1 + elif [ "x${arg}" == "x-mc" ]; then + FLAG_MC=1 + elif [ "x${arg}" == "x-multinp" ]; then + echo "IGNORING OBSOlETE FLAG -multinp" + elif [ "x${arg:0:10}" == "x-detdescr=" ]; then + DETDESCRTAG=${arg:10:$((${#arg}-10))} + if [ "x$DETDESCRTAG" == "x" ]; then + ERRORS="$ERRORS\nNeed argument to -detdescr" + fi + elif [ "x${arg:0:10}" == "x-detdescr" ]; then + DETDESCRTAG_2=${arg:9:$((${#arg}-9))} + if [ "x$DETDESCRTAG_2" == "x" ]; then + ERRORS="$ERRORS\nNeed argument to -detdescr. Example: -detdescr=ATLAS-GEO-20-00-01" + fi + elif [ "x${arg:0:10}" == "x-globcond=" ]; then + GLOBCONDTAG=${arg:10:$((${#arg}-10))} + if [ "x$GLOBCONDTAG" == "x" ]; then + ERRORS="$ERRORS\nNeed argument to -globcond" + fi + elif [ "x${arg:0:10}" == "x-eventsrc=" ]; then + MULTINP_SRC=${arg:10:$((${#arg}-10))} + if [ "x$MULTINP_SRC" == "x" ]; then + ERRORS="$ERRORS\nNeed argument to -eventsrc" + fi + elif [ "x${arg:0:10}" == "x-eventcpy=" ]; then + MULTINP_CPY=${arg:10:$((${#arg}-10))} + if [ "x$MULTINP_CPY" == "x" ]; then + ERRORS="$ERRORS\nNeed argument to -eventcpy" + fi + elif [ "x${arg:0:9}" == "x-logfile=" ]; then + LOGFILE=${arg:9:$((${#arg}-9))} + if [ "x$LOGFILE" == "x" ]; then + ERRORS="$ERRORS\nNeed argument to -logfile" + fi + elif [ "x${arg:0:9}" == "x-trigdec=" ]; then + TRIGDEC=${arg:9:$((${#arg}-9))} + if [ "x$TRIGDEC" == "x" ]; then + ERRORS="$ERRORS\nNeed argument to -trigdec" + fi + elif [ "x${arg:0:11}" == "x-fatraskey=" ]; then + FATRAS_TRUTHKEY=${arg:11:$((${#arg}-11))} + if [ "x$FATRAS_TRUTHKEY" == "x" ]; then + ERRORS="$ERRORS\nNeed argument to -fatraskey" + fi + elif [ "x${arg:0:12}" == "x-skipevents=" ]; then + SKIPEVENTS=${arg:12:$((${#arg}-12))} + if [ "x$SKIPEVENTS" == "x" ]; then + ERRORS="$ERRORS\nNeed argument to -skipevents" + else + #check it is integer: + echo "$SKIPEVENTS" | grep '^[0-9][0-9]*$' > /dev/null 2>&1 || \ + ERRORS="$ERRORS\nArgument to -skipevents must be an integer!" + fi + elif [ "x${arg:0:11}" == "x-evtfilter=" ]; then + FILTEREVENTS=${arg:11:$((${#arg}-11))} + if [ "x$FILTEREVENTS" == "x" ]; then + ERRORS="$ERRORS\nNeed argument to -evtfilter" + fi + elif [ "x${arg:0:8}" == "x-cruise=" ]; then + CRUISEWITHTIME=${arg:8:$((${#arg}-8))} + if [ "x$CRUISEWITHTIME" == "x" ]; then + ERRORS="$ERRORS\nNeed argument to -cruise" + else + #check it is integer: + echo "$CRUISEWITHTIME" | grep '^[0-9][0-9]*$' > /dev/null 2>&1 || \ + ERRORS="$ERRORS\nArgument to -cruise must be an integer!" + if [ "x$CRUISEWITHTIME" == "x0" ]; then + ERRORS="$ERRORS\nArgument to -cruise must be positive!" + fi + fi + elif [ "x${arg:0:12}" == "x-athenaopts=" ]; then + ATHENAOPTS=${arg:12:$((${#arg}-12))} + if [ "x$ATHENAOPTS" == "x" ]; then + ERRORS="$ERRORS\nNeed argument to -athenaopts" + fi + elif [ "x${arg:0:16}" == "x-extraevtsrcdir=" ]; then + EXTRADIR=${arg:16:$((${#arg}-16))} + if [ "x$EXTRADIR" == "x" ]; then + ERRORS="$ERRORS\nNeed argument to -extraevtsrcdir" + else + if [ ! -d $EXTRADIR ]; then + ERRORS="$ERRORS\nExtra event source directory $EXTRADIR does not exist" + else + LOCALEVENTSRC_AVAILDIRS[${#LOCALEVENTSRC_AVAILDIRS[@]}]="$EXTRADIR" + fi + fi + + + ################### + # VP1 CONFIG FILE # + ################### + elif [ ${#arg} -gt 4 -a ${arg:$((${#arg}-4)):4} == ".vp1" ]; then + FILES_VP1CFG[${#FILES_VP1CFG[@]}]="${arg}" + + + ##################### + # EXTRA JOB OPTIONS # + ##################### + elif [ ${#arg} -gt 3 -a ${arg:$((${#arg}-3)):3} == ".py" ]; then + FILES_EXTRAJOBOPT[${#FILES_EXTRAJOBOPT[@]}]="${arg}" + + + ######################## + # EOS / LFN INPUT DATA # + ######################## + + # NOTES: + # - about reg-exp matching: https://its.cern.ch/jira/browse/ATLASVPONE-314 + # - 'elif' first checks if argument length is > 3 and if not begins with "-", + # then it checks the match with the reg-exp + + elif [[ ${#arg} -gt 3 && ${arg:0:1} != "-" && ( "${arg}" =~ ^LFN: ) ]]; then + echo -e "\n\e[1;94mOpening a file through the \e[4m'LFN:'\e[24m protocol...\e[0m" + FILES_POOLROOT[${#FILES_POOLROOT[@]}]="${arg}" + echo -e "\e[94mOpening the file: " $FILES_POOLROOT "\e[0m\n" + + elif [[ ${#arg} -gt 3 && ${arg:0:1} != "-" && ( "${arg}" =~ ^root: ) ]]; then + echo -e "\n\e[1;94mOpening a file through the \e[4m'root:'\e[24m protocol...\e[0m" + FILES_POOLROOT[${#FILES_POOLROOT[@]}]="${arg}" + echo -e "\e[94mOpening the file: " $FILES_POOLROOT "\e[0m\n" + + #################### + # LOCAL INPUT DATA # + #################### + + # NOTES: + # - 'elif' first checks if argument length is > 3 and if not begins with "-", + # then it checks if the file exists + + elif [[ ${#arg} -gt 3 && ${arg:0:1} != "-" && ( -f "${arg}" ) ]]; then + FILES_POOLROOT[${#FILES_POOLROOT[@]}]="${arg}" + echo -e "\n\e[94mOpening the local file: " $FILES_POOLROOT "\e[0m\n" + + + ################### + # DEFAULT (ERROR) # + ################### + else + ERRORS="$ERRORS\nUnknown argument: ${arg}" + fi + + # INCREMENT THE INDEX + i=$((i+1)) +done + + + + + +######################## +### SETTINGS ### +######################## + + +# batch mode +if [ "x$FLAG_BATCH_N_EVENTS" != "x0" -a "x$FLAG_BATCH" == "x0" ]; then + ERRORS="$ERRORS\nOption '-batch-n-events' can't be used without '-batch'..." +fi +if [ "x$FLAG_BATCH_N_EVENTS" != "x0" -a "x$FLAG_BATCH_ALL_EVENTS" == "x1" ]; then + ERRORS="$ERRORS\nOption '-batch-n-events' can't be used together with '-batch-all-events'... Please choose one or the other." +fi +if [ "x$FLAG_BATCH_ALL_EVENTS" == "x1" -a "x$FLAG_BATCH" == "x0" ]; then + ERRORS="$ERRORS\nOption '-batch-all-events' can't be used without '-batch'..." +fi +if [ "x$FLAG_BATCH_RANDOM_CONFIG" == "x1" -a "x$FLAG_BATCH" == "x0" ]; then + ERRORS="$ERRORS\nOption '-batch-random-config' can't be used without '-batch'..." +fi +if [ "x$FLAG_BATCH_RANDOM_CONFIG" == "x1" ]; then + echo -e "\e[1m\e[31m\e[4mNote!\e[24m You chose the option '-batch-random-config'.\e[39m" + echo -e "Thus, for each event a different configuration file will be used, randomly picked from the configuration files (.vp1) you provided:\e[0m" + printf "["; printf '"%s", ' "${FILES_VP1CFG[@]}"; printf "]\n"; echo +fi +if [ "x$FLAG_BATCH_OUT_FOLDER" != "x" -a "x$FLAG_BATCH" == "x0" ]; then + ERRORS="$ERRORS\nOption '-batch-output-folder' can't be used without '-batch'..." +fi + + +#live & noautoconf flags (AutoConfiguration is disabled in live and livelocal modes) + +if [ "x$FLAG_LIVE" == "x1" ]; then + if [ "x$FLAG_MC" == "x1" ]; then + echo "Notice: -mc flag is ignored when -live is present" + fi + FLAG_MC=0 + if [ "x$FLAG_NOAUTOCONF" == "x1" ]; then + echo "Notice: -noautoconf flag is redundant when -live is present" + fi + FLAG_NOAUTOCONF=1 + if [ "x$MULTINP_SRC" == "x" ]; then + MULTINP_SRC="$LIVEDEFAULTEVENTSRC" + fi + if [ "x$DETDESCRTAG" == "x" ]; then + DETDESCRTAG="$LIVEDEFAULTDETDESCR" + fi + if [ "x$GLOBCONDTAG" == "x" ]; then + GLOBCONDTAG="$LIVEDEFAULTGLOBCOND" + fi +elif [ "x$FLAG_LIVELOCAL" == "x1" ]; then + if [ "x$FLAG_MC" == "x1" ]; then + echo "Notice: -mc flag is ignored when -livelocal is present" + fi + FLAG_MC=0 + if [ "x$FLAG_NOAUTOCONF" == "x1" ]; then + echo "Notice: -noautoconf flag is redundant when -livelocal is present" + fi + FLAG_NOAUTOCONF=1 + if [ "x$MULTINP_SRC" == "x" ]; then + MULTINP_SRC="$LIVELOCALDEFAULTEVENTSRC" + fi + if [ "x$DETDESCRTAG" == "x" ]; then + DETDESCRTAG="$LIVEDEFAULTDETDESCR" + fi + if [ "x$GLOBCONDTAG" == "x" ]; then + GLOBCONDTAG="$LIVEDEFAULTGLOBCOND" + fi +elif [ "x$FLAG_NOAUTOCONF" == "x0" -a ${#FILES_POOLROOT[@]} != 0 ]; then + if [ "x$FLAG_MC" == "x1" ]; then + echo "Notice: -mc flag is ignored when autoconfiguration is ON" + fi + FLAG_MC=0 +fi + +if [ "x$FLAG_LIVE" == "x1" -a "x$FLAG_LIVELOCAL" == "x1" ]; then + ERRORS="$ERRORS\nDon't specify both -live and -livelocal" +fi + +#default: +if [ "x$MULTINP_SRC" != "x" -a "x$MULTINP_CPY" == "x" ]; then + MULTINP_CPY="/tmp/$USER/vp1events/$RANDOM" +fi + +# Sanity checks: +if [ "x$MULTINP_SRC" == "x" -a "x$FLAG_DONTCLEANUPEVTCPY" == "x1" ]; then + ERRORS="$ERRORS\nOption -nocleanupeventcpy can't be set without -eventsrc=..." +fi +if [ "x$MULTINP_CPY" != "x" -a "x$MULTINP_SRC" == "x" ]; then + ERRORS="$ERRORS\nOption -eventcpy=... can't be set without -eventsrc=..." +fi + +if [ "x$FLAG_NOID" == "x1" -a "x$FLAG_FATRAS" == "x1" ]; then + ERRORS="$ERRORS\nOptions -fatras and -noid can not be applied simultaneously" +fi + +if [ "x$FLAG_LIVE" == "x1" -a "x$FLAG_FATRAS" == "x1" ]; then + ERRORS="$ERRORS\nOptions -fatras and -live can not be applied simultaneously" +fi + +if [ "x$FLAG_LIVELOCAL" == "x1" -a "x$FLAG_FATRAS" == "x1" ]; then + ERRORS="$ERRORS\nOptions -fatras and -livelocal can not be applied simultaneously" +fi + +if [ "x$FLAG_NOID" == "x1" -a "x$FLAG_NOMUON" == "x1" -a "x$FLAG_EXTRAPOLATOR" == "x1" ]; then + ERRORS="$ERRORS\nOptions -extrapolator can not be used when both -noid and -nomuon are specified" +fi + +if [ "x$FLAG_EXTRAPOLATOR" == "x1" -a "x$FLAG_NOEXTRAPOLATOR" == "x1" ]; then + ERRORS="$ERRORS\nOptions -extrapolator and -noextrapolator are incompatible" +fi + +if [ "x$FLAG_NOID" == "x1" -a "x$FLAG_NOMUON" == "x1" -a "x$FLAG_FITTER" == "x1" ]; then + ERRORS="$ERRORS\nOptions -refit can not be used when both -noid and -nomuon are specified" +fi + +if [ "x$MULTINP_CPY" != "x" -a -f "$MULTINP_CPY" ]; then + ERRORS="$ERRORS\n-eventcpy directory set to point to a file" +fi + +# TODO: Check this "bootstrap": what is it? Is it still needed? +BOOTSTRAPNAME="bootstrapevent.pool.root" +BOOTSTRAPFILE="${MULTINP_CPY}/${BOOTSTRAPNAME}" +BOOTSTRAP_HTTPFILEINFO="${MULTINP_CPY}/bootstrap_fileinfo.txt" +HTTPMODE=0 +if [ "x$MULTINP_SRC" != "x" ]; then + if [ ${#FILES_POOLROOT[@]} != 0 ]; then + #cant have input files. + ERRORS="$ERRORS\nPlease don't specify input files when running with -live, -livelocal or -eventsrc=..." + else + FILES_POOLROOT[${#FILES_POOLROOT[@]}]="${BOOTSTRAPFILE}" + fi + HTTPMODE=1 + echo $MULTINP_SRC|grep '^https://..*/..*' > /dev/null || HTTPMODE=0 + echo $MULTINP_SRC|grep '/$' > /dev/null && HTTPMODE=0 + if [ "x$HTTPMODE" == "x0" ]; then + if [ "x$MULTINP_SRC" != "x" -a ! -d "$MULTINP_SRC" ]; then + ERRORS="$ERRORS\n-eventsrc directory does not exists" + fi + elif [ "x$MULTINP_CPY" == "x$MULTINP_SRC" ]; then + #Fixme: Could probably cheat this check by presense of trailing '/', symlinks, etc. + ERRORS="$ERRORS\n-eventsrc and -eventcpy directories must be different" + fi +fi + +if [ ${#LOCALEVENTSRC_AVAILDIRS[@]} != 0 ]; then + if [ "x$MULTINP_SRC" == "x" ]; then + ERRORS="$ERRORS\n-extraevtsrcdir can not be specified without the -eventsrc flag" + fi + if [ "x$HTTPMODE" != "x0" ]; then + ERRORS="$ERRORS\n-extraevtsrcdir can not be used when -eventsrc is not a local directory" + fi +fi + +if [ "x$FLAG_EXTRAPOLATOR" == "x0" -a "x$FLAG_EXTRAPOLATOR" == "x0" ]; then + if [ "x$FLAG_NOID" == "x1" -a "x$FLAG_NOMUON" == "x1" ]; then + FLAG_NOEXTRAPOLATOR=1 + else + FLAG_EXTRAPOLATOR=1 + fi +fi + + +####################################### +## Possibly print out errors/usage ## +####################################### + +if [ "x$ERRORS" != "x" ]; then + echo "=================================================================" + echo "Errors found in commandline options!!!:" + echo -e "$ERRORS" + echo + echo "Run 'vp1 -h' for more information" + echo "=================================================================" + echo + exit 1 +fi + +if [ "x$FLAG_HELP" != "x0" ]; then + echo "The $APP script serves as a frontend which runs athena with vp1.py and appropriate options." + echo + echo "Usage: " + echo + echo "$APP [inputfiles] [configfiles] [jobopt fragments] [options]" + echo + echo "Config files must have the .vp1 extension, joboption fragments the .py extension," + echo "and any other argument which doesn't start with '-' is assumed to be an input file if such a file exists." + echo + echo " -h, -help, --help : Display this help (with examples) and exit." + echo + echo " -batch : Run VP1 in 'batch' mode with a given configuration file." + echo + echo " -batch-all-events : Process all events in the input data file in '-batch' mode. Use this together with '-batch'." + echo + echo " -batch-n-events=N : Process 'N' events in the input data file in '-batch' mode. Use this together with '-batch'." + echo + echo " -batch-output-folder : Specify an output folder to store the event displays produced with the '-batch' option." + echo + echo " -batch-random-config : Run VP1 in 'batch' mode; for each single event a configuration file will be randomly picked out of the configuration files provided by the user. Use this together with '-batch'." + echo + echo " -larhv : Access current LAr HV data in the DCS_OFL database via VP1 CaloReadout system." + echo + echo " -data : Input files are data [default assumption is simulation]. " + echo + echo " -detdescr=TAG : Set global geometry tag. Overrides autoconfiguration" + echo + echo " -globcond=TAG : Set global conditions tag. Overrides autoconfiguration" + echo + echo " -skipevents=N : Skip the first N events" + echo + echo " -evtfilter=FILTER : Only process the events in the FILTER list." + echo " Format is a comma separated list of event numbers, where each event number" + echo " can optionally be preceeded by a run number and a semicolon." + echo " Prepend the list with an \"%\" to instead exclude the events." + echo " For instance select a few nice events like: -evtfilter=7,13,5300:26,54" + echo " Or exclude a few bad events like: -evtfilter=%7,13,5300:26,54" + echo + echo " It is also possible to specify one or more files with run/evt numbers" + echo " specified on each line: -evtfilter=%7,13,5300:26,54,myevents1.txt" + echo + echo " -cruise=N : Start in cruise mode, changing events after N seconds" + echo + echo " -logfile=mylogfile.txt : Leave a copy of the output in mylogfile.txt (both stdout and stderr)" + echo + echo " -trig : Init trigger information to be displayed with the Trigger Plugin" + echo + echo " -nocalo : Don't init geometry and converters for calorimeter systems." + echo " -noid : Don't init geometry and converters for the inner detector." + echo " -nomuon : Don't init geometry and converters for muon systems." + # echo " -fulltoroids : Build complete and rather heavyweight description of muon dead materials." + # echo " A lightweight version is built by default" + echo " -lucid : Init geometry and converters for the LUCID forward detector." + echo " -alfa : Init geometry and converters for the ALFA forward detector." + echo " -forwardregion : Init geometry and converters for the FrwardRegion." + echo " -zdc : Init geometry and converters for the ZDC forward detector." + echo " -cavern : Init geometry for the cavern infrastructure." + echo + echo " -toy-detector : Let VP1 visualize the "ToyDetector" volumes of GeoModelExamples (as 'Other unrecognized volumes.' in the Geo system)" + echo + echo " -geomodel-stats : Write GeoModel stats to a file." + echo + echo " -extrapolator : Whether to configure an extrapolator for more precise track representation." + echo " -noextrapolator Default is -extrapolator unless both -nomuon and -noid are specified." + echo + echo " -refit : Allows VP1-controlled refit from PrepRawData." + echo + echo " -online : Use this flag for running VP1 at P1." + echo + echo " -mc : Tell VP1 that it is running over MC data. The flag is ignored when autoconfiguration is ON" + echo " (default mode when running over data files)" + echo + echo " -fatras : Use Fatras (in single-track-simulation mode if no input file with generated event)" + echo " -fatraskey=KEY : Optionally override truth key used by Fatras (typical values are GEN_EVENT or TruthEvent)" + echo + echo " -eventsrc=DIR : Directory to take single event files from (do not specify input files in this case)." + echo " To get files from a web server (i.e. live events), put instead the url to the file" + echo " residing in the same directory (most users should just use the -live option instead)." + echo + echo " -extraevtsrcdir=DIR : Directory to add to the menu to allow user to change eventsrc on the fly." + echo " This argument can appear several times and should only be used when eventsrc is" + echo " a local directory" + echo + echo " -eventcpy=DIR : Directory to keep local copies of processed event files." + echo " If -eventsrc is set, then -eventcpy will default to /tmp/$USER/vp1events/$RANDOM " + echo " -nocleanupeventcpy : Prevent removal of eventcpy directory after athena process finishes." + echo + echo " -live : Run on live events from point 1. This is a convenience option which implies" + echo " other options [unless explicitly set]:" + echo " -noautoconf" + echo " -eventsrc=$LIVEDEFAULTEVENTSRC" + echo " -detdescr=$LIVEDEFAULTDETDESCR" + echo " -globcond=$LIVEDEFAULTGLOBCOND" + echo + echo " -livelocal : Run on live events from point 1 in local directory. This is a convenience option" + echo " which implies other options [unless explicitly set]:" + echo " -noautoconf" + echo " -eventsrc=$LIVELOCALDEFAULTEVENTSRC" + echo " -detdescr=$LIVEDEFAULTDETDESCR" + echo " -globcond=$LIVEDEFAULTGLOBCOND" + echo + echo " -noautoconf : Disable AutoConfiguration. VP1 runs in the 'data' mode by default" + echo " use '-mc' flag for switching to the MC mode" + echo + echo " -nosortdbreplicas : Do not attempt to sort DB replicas according to geographical proximity." + echo + echo " -trigdec=file.xml : Use file.xml as source of trigger decision category data." + echo " -trigdec=embedded : Trigger decision category data is embedded in the input file(s)." + echo " -trigdec=someserver.cern.ch : Trigger decision category data is available from the server someserver.cern.ch." + echo + echo " -athenaopts=<options> : Pass <options> onto athena invocation (type 'athena.py -h' to see available options)." + echo " NB: You can not use the -c option." + echo + echo " -cgal : Use CGAL boolean instead of vp1 boolean." + echo + echo " -nsw : Enable the Muon New Small Wheel geometry (and disable the existing small wheel)." + echo + echo " -slhc : Enable special configurations for SLHC studies." + echo + echo " -customgeom : Enable a custom geometry." + echo + echo " -advanced-aa : Enable advanced anti-aliasing for crisper, higher-quality images. DOES NOT WORK ON LXPLUS MACHINES!!!" + echo + echo " -test : Show the athena command instead of executing it." + echo + echo "Note that the order of specified files/options is not important, and that they can in general be mixed quite" + echo "liberally (when it makes sense - of course dont put e.g. both -trigdec=file.xml and -trigdec=embedded)" + echo + echo + echo "*********" + echo "Examples:" + echo + echo " * Simply run on the input files myevents1.pool.root and myevents2.pool.root" + echo + echo " \$>$APP myevents1.pool.root myevents2.pool.root" + echo + echo " * Simply run on the input file myevents.pool.root and have the joboption fragments myopts1.py and myopts2.py" + echo " included after the standard vp1 setup" + echo + echo " \$>$APP myevents.pool.root myopts1.py myopts2.py" + echo + echo " * Run on myevents1.pool.root, and use a file, mytrigger.xml, as source of trigger decision data:" + echo + echo " \$>$APP myevents1.pool.root -trigdec=mytrigger.xml" + echo + echo " * Run on myevents1.pool.root, don't init geometry and converters for the calorimeter systems:" + echo + echo " \$>$APP myevents1.pool.root -nocalo" + echo + echo " * Run on myevents1.pool.root, and use detector description tag \"ATLAS-GEO-10-00-00\":" + echo + echo " \$>$APP myevents1.pool.root -detdescr=ATLAS-GEO-10-00-00" + echo + echo " * Run on myevents1.pool.root, and pass on a couple of options to the athena invocation (in this case" + echo " we want to run with a debugger and also set the loglevel to WARNING):" + echo + echo " \$>$APP myevents1.pool.root -athenaopts='-d -l WARNING'" + echo + echo " * Run on myevents1.pool.root, and preload the tab/channel configuration files myconfig1.vp1 and myconfig2.vp1:" + echo + echo " \$>$APP myevents1.pool.root myconfig1.vp1 myconfig2.vp1" + echo + echo " * Run on myevents1.pool.root, and preload two tab/channel configuration files: myconfig1.vp1 and myconfig2.vp1; at start, VP1 will create multiple tabs, from the pieces of configuration information contained in both files:" + echo + echo " \$>$APP myevents1.pool.root myconfig1.vp1 myconfig2.vp1" + echo + echo " * Run in 'batch mode' on 'myevents1.pool.root' with the configuration file 'myconfig1.vp1'." + echo " No graphical window will appear, but in the end you will get the PNG file containing the render of the 3D window." + echo + echo " \$>$APP -batch myevents.pool.root myconfig1.vp1" + echo + echo " * Some more advanced examples, using several options at once:" + echo + echo " \$>$APP -detdescr=ATLAS-GEO-10-00-00 myevents1.pool.root myevents2.pool.root myconfig1.vp1 -athenaopts='-d'" + echo " \$>$APP -detdescr=ATLAS-GEO-10-00-00 myevents1.pool.root myconfig1.vp1 -nocalo -nomuon -trigdec=embedded" + echo + exit 0 +fi + +######################################## +## Setup & run according to options ## +######################################## + +if [ "x$FLAG_DONTCLEANUPEVTCPY" != "x1" -a "x$MULTINP_CPY" != "x" ]; then + if [ ${#MULTINP_CPY} -lt 8 -o "x$MULTINP_CPY" == "$HOME" -o "x$MULTINP_CPY" == "$HOME/" ]; then + echo "NOTICE: Turning off removal of ${MULTINP_CPY} since it seems to be too short or pointing at $HOME." + FLAG_DONTCLEANUPEVTCPY=1 + fi +fi + +if [ "x$FLAG_DATA" != "x0" ]; then + echo "Error: Support for the -data flag is actually not implemented yet!" + exit 1 +fi + +PYTHONFILES="" +i=0 +while [ $i -le $((${#FILES_VP1CFG[@]}-1)) ]; do + if [ "x$PYTHONFILES" == "x" ]; then + PYTHONFILES='vp1CfgFiles=["'"${FILES_VP1CFG[$i]}"'"' + else + PYTHONFILES="${PYTHONFILES}"',"'"${FILES_VP1CFG[$i]}"'"' + fi + i=$((i+1)) +done +if [ "x$PYTHONFILES" != "x" ]; then + PYTHONFILES="${PYTHONFILES}"']' +fi + + +POOLROOTFILES="" +i=0 +while [ $i -le $((${#FILES_POOLROOT[@]}-1)) ]; do + if [ "x$POOLROOTFILES" == "x" ]; then + POOLROOTFILES='vp1InputFiles=["'"${FILES_POOLROOT[$i]}"'"' + else + POOLROOTFILES="${POOLROOTFILES}"',"'"${FILES_POOLROOT[$i]}"'"' + fi + i=$((i+1)) +done +if [ "x$POOLROOTFILES" != "x" ]; then + POOLROOTFILES="${POOLROOTFILES}"']' +fi + +EXTRAINPUTDIRS="" +i=0 +while [ $i -le $((${#LOCALEVENTSRC_AVAILDIRS[@]}-1)) ]; do + if [ "x$EXTRAINPUTDIRS" == "x" ]; then + EXTRAINPUTDIRS='vp1MultiAvailableSrcDirs=["'"${LOCALEVENTSRC_AVAILDIRS[$i]}"'"' + else + EXTRAINPUTDIRS="${EXTRAINPUTDIRS}"',"'"${LOCALEVENTSRC_AVAILDIRS[$i]}"'"' + fi + i=$((i+1)) +done +if [ "x$EXTRAINPUTDIRS" != "x" ]; then + EXTRAINPUTDIRS="${EXTRAINPUTDIRS}"']' +fi + +EXTRAJOBOPT="" +i=0 +while [ $i -le $((${#FILES_EXTRAJOBOPT[@]}-1)) ]; do + if [ "x$EXTRAJOBOPT" == "x" ]; then + EXTRAJOBOPT="${FILES_EXTRAJOBOPT[$i]}" + else + EXTRAJOBOPT="${EXTRAJOBOPT} ${FILES_EXTRAJOBOPT[$i]}" + fi + i=$((i+1)) +done + +JOBOPT="VTI12Algs/vti12.py" +if [ -f vti12.py ]; then + JOBOPT=vti12.py +fi + +OPTS="$PYTHONFILES" +if [ "x$POOLROOTFILES" != "x" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}$POOLROOTFILES" +fi +if [ "x$EXTRAINPUTDIRS" != "x" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}$EXTRAINPUTDIRS" +fi +if [ "x$DETDESCRTAG" != "x" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}DetDescrVersion=\"$DETDESCRTAG\"" +fi +if [ "x$GLOBCONDTAG" != "x" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1GlobCond=\"$GLOBCONDTAG\"" +fi +if [ "x$SKIPEVENTS" != "x" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}skipEvents=$SKIPEVENTS" +fi +if [ "x$FILTEREVENTS" != "x" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1FilterEvents=\"$FILTEREVENTS\"" +fi +if [ "x$CRUISEWITHTIME" != "x" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1CruiseTime=$CRUISEWITHTIME" +fi +if [ "x$FLAG_TRIG" != "x0" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1Trig=True" +fi +if [ "x$FLAG_NOCALO" != "x0" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1Calo=False" +fi +if [ "x$FLAG_NOID" != "x0" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1ID=False" +fi +if [ "x$FLAG_NOMUON" != "x0" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1Muon=False" +fi +if [ "x$FLAG_NOSORTDBREPLICAS" != "x0" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1NoSortDBReplicas=True" +fi +if [ "x$FLAG_BATCH" != "x0" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1Batch=True" +fi +if [ "x$FLAG_BATCH_ALL_EVENTS" != "x0" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1BatchAllEvents=True" +fi +if [ "x$FLAG_BATCH_N_EVENTS" != "x0" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1BatchNEvents=$FLAG_BATCH_N_EVENTS" +fi +if [ "x$FLAG_BATCH_OUT_FOLDER" != "x" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1BatchOutFolder=\"$FLAG_BATCH_OUT_FOLDER\"" +fi +if [ "x$FLAG_BATCH_RANDOM_CONFIG" != "x0" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1BatchRandomConfiguration=True" +fi +if [ "x$FLAG_LARHV" != "x0" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1LarHvData=True" +fi +# if [ "x$FLAG_FULLTOROIDS" != "x0" ]; then +# if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi +# OPTS="${OPTS}vp1FullToroids=True" +# fi +if [ "x$FLAG_ONLINE" != "x0" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1Online=True" +fi +if [ "x$FLAG_LUCID" != "x0" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1LUCID=True" +fi +if [ "x$FLAG_ALFA" != "x0" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1ALFA=True" +fi +if [ "x$FLAG_FORWARD_REGION" != "x0" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1ForwardRegion=True" +fi +if [ "x$FLAG_ZDC" != "x0" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1ZDC=True" +fi +if [ "x$FLAG_CAVERN" != "x0" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1Cavern=True" +fi +if [ "x$FLAG_TOYDETECTOR" != "x0" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1ToyDetector=True" +fi +if [ "x$FLAG_GEOMODELSTATS" != "x0" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1GeoModelStats=True" +fi +if [ "x$FLAG_EXTRAPOLATOR" != "x0" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1Extrapolator=True" +fi +if [ "x$FLAG_NOEXTRAPOLATOR" != "x0" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1Extrapolator=False" +fi +if [ "x$FLAG_NOAUTOCONF" != "x0" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1NoAutoConf=True" +fi +if [ "x$FLAG_FITTER" != "x0" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + ERRORS="$ERRORS\nOption -refit is not currently supported." +fi +if [ "x$FLAG_FATRAS" != "x0" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1Fatras=True" +fi +if [ "x$FLAG_NSW" != "x0" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1NSW=True" +fi +if [ "x$FLAG_SLHC" != "x0" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1SLHC=True" +fi +#if [ "x$FLAG_CUSTOMGEOMETRY" != "x0" ]; then +# if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi +# OPTS="${OPTS}vp1CustomGeometry=True" +#fi +#if [ "x$FLAG_ADVANCED_ANTIALIASING" != "x0" ]; then +# if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi +# OPTS="${OPTS}vp1AdvancedAntialiasing=True" +#fi +if [ "x$FLAG_NOGUI" != "x0" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1NoGui=True" +fi +if [ "x$FLAG_MC" != "x0" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1Mc=True" +fi +if [ "x$MULTINP_SRC" != "x" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1Multinp=True" +fi +if [ "x$MULTINP_SRC" != "x" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1Multinpsrc=\"$MULTINP_SRC\"" +fi +if [ "x$MULTINP_CPY" != "x" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1Multinpcpy=\"$MULTINP_CPY\"" +fi +if [ "x$TRIGDEC" != "x" ]; then + if [ ${#TRIGDEC} -gt 5 -a ${TRIGDEC:$((${#TRIGDEC}-4)):4} == ".xml" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1TrigDecXML=\"$TRIGDEC\"" + else + echo "Error: Support for the -trigdec flag for embedded or server is actually not implemented in this script yet! So far only .xml sources work" + exit 1 + fi +fi +if [ "x$FATRAS_TRUTHKEY" != "x" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1FatrasTruthKey=\"$FATRAS_TRUTHKEY\"" +fi + +if [ "x$LOGFILE" != "x" ]; then + #Fixme: Check that this actually redirects stderr correctly!! + CMD="$CMD 2>&1|tee $LOGFILE" +fi +#Test mode: +if [ "x$FLAG_TEST" != "x0" ]; then + if [ "x$HTTPMODE" == "x1" ]; then + echo "--> Start by downloading a fresh file from $MULTINP_SRC to $BOOTSTRAPFILE" + fi + if [ "x$MULTINP_CPY" != "x" -a ! -d "$MULTINP_CPY" ]; then + echo mkdir -p $MULTINP_CPY + fi + if [ "x$LOGFILE" != "x" ]; then + echo athena.py $ATHENAOPTS -c "'$OPTS'" $JOBOPT $EXTRAJOBOPT "2>&1|tee $LOGFILE" + else + echo athena.py $ATHENAOPTS -c "'$OPTS'" $JOBOPT $EXTRAJOBOPT + fi + exit 0 +fi + +################################################## +## Possibly get boot-strap file for http mode ## +################################################## + +if [ "x$MULTINP_CPY" != "x" -a ! -d "$MULTINP_CPY" ]; then + mkdir -p $MULTINP_CPY + if [ $? != 0 ]; then + echo + echo "Failed to create $MULTINP_CPY" + echo + exit 1 + fi +fi + + +if [ "x$HTTPMODE" == "x1" ]; then + if [ -f $BOOTSTRAPFILE ]; then + echo + echo + echo "Using existing $BOOTSTRAPFILE as first event." + echo + echo "In case of problems, try first to remove this file and then restart" + echo + echo + else + echo "Need to acquire $BOOTSTRAPFILE" + while [ 1 ]; do + rm -f $BOOTSTRAP_HTTPFILEINFO + echo + echo "Executing wget $LIVEBOOTSTRAPSRC --output-document=$BOOTSTRAP_HTTPFILEINFO" + wget $LIVEBOOTSTRAPSRC --output-document=$BOOTSTRAP_HTTPFILEINFO + if [ $? != 0 ]; then + echo + echo "Download failed!" + echo + rm -f $BOOTSTRAP_HTTPFILEINFO + exit 1 + fi + echo "Download succesful" + #Check integrity of downloaded file: + OK=1 + grep '^vp1_.*_.*_.*.pool.root' $BOOTSTRAP_HTTPFILEINFO |grep -v "copy " > /dev/null || OK=0 + grep 'begin_checksums' $BOOTSTRAP_HTTPFILEINFO > /dev/null || OK=0 + grep 'end_checksums' $BOOTSTRAP_HTTPFILEINFO > /dev/null || OK=0 + if [ "x$OK" == "x1" ]; then + echo "Downloaded info file content seems sane." + break + else + echo "Problems with content of downloaded info file. Will retry in 5 seconds." + sleep 5 + fi + done + #Decode to find recent file: + FILELINE=`grep '^vp1_.*_.*_.*.pool.root' $BOOTSTRAP_HTTPFILEINFO |grep -v "copy "|head -1|tr '\t' ' '` + FILE=`echo $FILELINE|awk '{print $1}'` + SUM=`echo $FILELINE|awk '{print $2}'` + FILEURL=`echo $LIVEBOOTSTRAPSRC|sed 's#http://\(.*\)/.*$#http://\1/#'`$FILE + echo FILE=$FILE + echo FILEURL=$FILEURL + echo SUM=$SUM + OK=1 + BOOTSTRAPFILE_SUMFILE=$BOOTSTRAPFILE.md5sum + rm -f $BOOTSTRAPFILE $BOOTSTRAPFILE_SUMFILE + echo "Executing wget ${FILEURL} --output-document=$BOOTSTRAP_HTTPFILEINFO" + wget ${FILEURL} --output-document=$BOOTSTRAPFILE || OK=0 + if [ $? != 0 ]; then + echo + echo "Download failed!" + echo + rm -f $BOOTSTRAPFILE $BOOTSTRAPFILE_SUMFILE + exit 1 + fi + echo "$SUM $BOOTSTRAPFILE" > $BOOTSTRAPFILE_SUMFILE + if [ $? != 0 ]; then + echo + echo "Could not create md5sum check file" + echo + rm -f $BOOTSTRAPFILE $BOOTSTRAPFILE_SUMFILE + exit 1 + fi + md5sum --status --check $BOOTSTRAPFILE_SUMFILE + if [ $? != 0 ]; then + echo + echo "md5sum check of downloaded bootstrap event file failed!" + echo + rm -f $BOOTSTRAPFILE $BOOTSTRAPFILE_SUMFILE + exit 1 + fi + echo "Checksum of downloaded Bootstrap event file is OK. Proceeding to launch athena." + fi +elif [ "x$MULTINP_SRC" != "x" ]; then + NEWEST=`ls -1rt $MULTINP_SRC/*_*_*.pool.root |tail -1` + if [ ! -f $NEWEST ]; then + echo + echo "Could not find event file in $MULTINP_SRC to use to bootstrap athena. " + echo + exit 1 + fi + cp $NEWEST -f $BOOTSTRAPFILE + if [ $? != 0 -o ! -f $BOOTSTRAPFILE ]; then + echo + echo "Could not copy newest event file $BOOTSTRAPFILE!" + echo + rm -f $BOOTSTRAPFILE + exit 1 + fi +fi + +if [ "x$LOGFILE" != "x" ]; then + athena.py $ATHENAOPTS -c "$OPTS" $JOBOPT $EXTRAJOBOPT 2>&1|tee $LOGFILE +else + athena.py $ATHENAOPTS -c "$OPTS" $JOBOPT $EXTRAJOBOPT +fi + +if [ "x$FLAG_DONTCLEANUPEVTCPY" != "x1" -a "x$MULTINP_CPY" != "x" ]; then + if [ -d "${MULTINP_CPY}" -a -f "${MULTINP_CPY}/${BOOTSTRAPNAME}" ]; then + rm -rf "${MULTINP_CPY}" + fi +fi diff --git a/graphics/VTI12/VTI12Algs/share/vti12.py b/graphics/VTI12/VTI12Algs/share/vti12.py new file mode 100644 index 000000000..6acbbac58 --- /dev/null +++ b/graphics/VTI12/VTI12Algs/share/vti12.py @@ -0,0 +1,455 @@ +if not 'vp1InputFiles' in dir(): vp1InputFiles = [] +if not 'vp1CfgFiles' in dir(): vp1CfgFiles = [] +if not 'vp1ID' in dir(): vp1ID=False +if not 'vp1Calo' in dir(): vp1Calo=False +if not 'vp1Muon' in dir(): vp1Muon=False +if not 'vp1LUCID' in dir(): vp1LUCID=False +if not 'vp1ALFA' in dir(): vp1ALFA=False +if not 'vp1ForwardRegion' in dir(): vp1ForwardRegion=False +if not 'vp1ZDC' in dir(): vp1ZDC=False +if not 'vp1Extrapolator' in dir(): vp1Extrapolator=True +# if not 'vp1Fitter' in dir(): vp1Fitter=False +if not 'vp1Fatras' in dir(): vp1Fatras=False +if not 'vp1FatrasMuon' in dir(): vp1FatrasMuon=(vp1Fatras and vp1Muon) +if not 'vp1FatrasCalo' in dir(): vp1FatrasCalo=(vp1Fatras and vp1Calo) +if not 'vp1FatrasTruthKey' in dir(): vp1FatrasTruthKey="" +if not 'vp1Online' in dir(): vp1Online=False +if not 'vp1Mc' in dir(): vp1Mc=False +if not 'vp1Multinp' in dir(): vp1Multinp=False +if not 'vp1Multinpsrc' in dir(): vp1Multinpsrc="" +if not 'vp1Multinpcpy' in dir(): vp1Multinpcpy="" +if not 'vp1MultiAvailableSrcDirs' in dir(): vp1MultiAvailableSrcDirs = [] +if not 'vp1TrigDecXML' in dir(): vp1TrigDecXML="" +if not 'vp1Batch' in dir(): vp1Batch=False +if not 'vp1BatchAllEvents' in dir(): vp1BatchAllEvents=False +if not 'vp1BatchNEvents' in dir(): vp1BatchNEvents=0 +if not 'vp1BatchOutFolder' in dir(): vp1BatchOutFolder="" +if not 'vp1BatchRandomConfiguration' in dir(): vp1BatchRandomConfiguration=False +if not 'vp1LarHvData' in dir(): vp1LarHvData=False +# if not 'vp1FullToroids' in dir(): vp1FullToroids=False +if not 'vp1CruiseTime' in dir(): vp1CruiseTime=0 +if not 'vp1NoSortDBReplicas' in dir(): vp1NoSortDBReplicas=False +if not 'vp1FilterEvents' in dir(): vp1FilterEvents="" +if not 'vp1NoGui' in dir(): vp1NoGui=False +if not 'vp1SpacePoints' in dir(): vp1SpacePoints=False +if not 'vp1Cavern' in dir(): vp1Cavern=False +if not 'vp1NoAutoConf' in dir(): vp1NoAutoConf=False +if not 'vp1Trig' in dir(): vp1Trig=False +if not 'vp1NSW' in dir(): vp1NSW=False + +def vp1CfgErr(s): print "VP1 CONFIGURATION ERROR: %s" % s + +if (vp1Fatras and not vp1ID): + vp1CfgErr("Fatras can not be enabled without inner detector. Turning off Fatras.") + vp1Fatras=False +if (vp1FatrasMuon and not vp1Fatras): + vp1CfgErr("FatrasMuon can not be enabled without Fatras enabled. Turning off FatrasMuon.") + vp1FatrasMuon=False +if (vp1FatrasMuon and not vp1Muon): + vp1CfgErr("FatrasMuon can not be enabled without muon systems. Turning off FatrasMuon.") + vp1FatrasMuon=False +if (vp1FatrasCalo and not vp1Fatras): + vp1CfgErr("FatrasCalo can not be enabled without Fatras enabled. Turning off FatrasCalo.") + vp1FatrasCalo=False +if (vp1FatrasCalo and not vp1Calo): + vp1CfgErr("FatrasCalo can not be enabled without calo systems. Turning off FatrasCalo.") + vp1FatrasCalo=False +if ( vp1FatrasTruthKey != "" and not vp1Fatras ): + vp1CfgErr("FatrasTruthKey set but Fatras not enabled. Unsetting FatrasTruthKey.") + vp1FatrasTruthKey="" + +if (vp1NSW and not vp1Muon): + vp1CfgErr("Muon New Small Wheel (NSW) turned on, but no Muon geometry. Disabling NSW.") + vp1NSW=False + + + + +print "*** VP1 NOTE *** setting COIN_GLXGLUE env vars to make screenshots working remotely..." +print "*** VP1 NOTE *** COIN_GLXGLUE_NO_GLX13_PBUFFERS=1 - " + "COIN_GLXGLUE_NO_PBUFFERS=1" +os.putenv("COIN_GLXGLUE_NO_GLX13_PBUFFERS","1") +os.putenv("COIN_GLXGLUE_NO_PBUFFERS","1") + + + +#Set VP1ATLREL integer so we can do e.g. "if VP1ATLREL>=160002:" +include('VP1Algs/vp1FragmentConstructVP1ATLREL.py') + +#Disable FPE checks :-( +from RecExConfig.RecFlags import rec +rec.doFloatingPointException.set_Value_and_Lock(False) + +if (vp1InputFiles == []): + # Create an event selector: + import AthenaCommon.AtlasUnixGeneratorJob + # Configure GlobalFlags + from AthenaCommon.GlobalFlags import globalflags +# from CalypsoCommon.GlobalFlags import globalflags + globalflags.DetGeo.set_Value_and_Lock('atlas') + globalflags.DataSource.set_Value_and_Lock('geant4') + + # Set geometry version + if (not "DetDescrVersion" in dir()): + DetDescrVersion = "FASER-00" + globalflags.DetDescrVersion = DetDescrVersion + + # Set conditions tag + if not 'vp1GlobCond' in dir(): + vp1GlobCond="OFLCOND-SDR-BS7T-05-14" + from IOVDbSvc.CondDB import conddb + conddb.setGlobalTag(vp1GlobCond) + + + ### NEW FOR REL. >= 22 + + # Conditions Service for reading conditions data in serial and MT Athena + from IOVSvc.IOVSvcConf import CondSvc + svcMgr += CondSvc() + + from AthenaCommon.AlgSequence import AthSequencer + condSeq = AthSequencer("AthCondSeq") + + # Conditions data access infrastructure for serial and MT Athena + from IOVSvc.IOVSvcConf import CondInputLoader + condSeq += CondInputLoader( "CondInputLoader") + + import StoreGate.StoreGateConf as StoreGateConf + svcMgr += StoreGateConf.StoreGateSvc("ConditionStore") + +else: + if(vp1NoAutoConf): + # AutoConfiguration disabled + import AthenaCommon.AtlasUnixStandardJob + + if(vp1Online): + from AthenaCommon.AthenaCommonFlags import athenaCommonFlags + athenaCommonFlags.isOnline = True + + from AthenaCommon.GlobalFlags import globalflags +# from CalypsoCommon.GlobalFlags import globalflags + globalflags.DetGeo.set_Value_and_Lock('atlas') + if(vp1Mc): + globalflags.DataSource.set_Value_and_Lock('geant4') + else: + globalflags.DataSource.set_Value_and_Lock('data') + globalflags.InputFormat.set_Value_and_Lock('pool') + globalflags.Luminosity.set_Value_and_Lock('zero') + from AthenaCommon.BeamFlags import jobproperties + jobproperties.Beam.beamType="collisions" + + # Set geometry version + if (not "DetDescrVersion" in dir()): + DetDescrVersion = "FASER-00" + globalflags.DetDescrVersion = DetDescrVersion + + # Set conditions tag + if not 'vp1GlobCond' in dir(): + if (vp1Mc): + vp1GlobCond="OFLCOND-SIM-BS7T-02" + else: + vp1GlobCond="COMCOND-BLKPST-004-01" + + from IOVDbSvc.CondDB import conddb + conddb.setGlobalTag(vp1GlobCond) + + import AthenaPoolCnvSvc.ReadAthenaPool #sets up reading of any POOL files (but POOL is slow) + svcMgr.EventSelector.InputCollections = vp1InputFiles + + ### NEW FOR REL. >= 22 + + # Conditions Service for reading conditions data in serial and MT Athena + from IOVSvc.IOVSvcConf import CondSvc + svcMgr += CondSvc() + + from AthenaCommon.AlgSequence import AthSequencer + condSeq = AthSequencer("AthCondSeq") + + # Conditions data access infrastructure for serial and MT Athena + from IOVSvc.IOVSvcConf import CondInputLoader + condSeq += CondInputLoader( "CondInputLoader") + + import StoreGate.StoreGateConf as StoreGateConf + svcMgr += StoreGateConf.StoreGateSvc("ConditionStore") + + else: + # AutoConfiguration enabled + from AthenaCommon.AthenaCommonFlags import athenaCommonFlags + athenaCommonFlags.FilesInput=vp1InputFiles + + from RecExConfig.RecFlags import rec + rec.AutoConfiguration=['everything'] + rec.doAOD.set_Value_and_Lock(False) + rec.doESD.set_Value_and_Lock(False) + + # Override geometry tag from command line + if("DetDescrVersion" in dir()): + from AthenaCommon.GlobalFlags import globalflags +# from CalypsoCommon.GlobalFlags import globalflags + globalflags.DetDescrVersion = DetDescrVersion + #globalflags.DetDescrVersion.set_Value_and_Lock(DetDescrVersion) + + athenaCommonFlags.EvtMax=-1 + include('RecExCond/RecExCommon_flags.py') + + # Override global conditions tag from command line + if('vp1GlobCond' in dir()): + from IOVDbSvc.CondDB import conddb + conddb.setGlobalTag(vp1GlobCond) + + + ### NEW FOR REL. >= 22 + + # Conditions Service for reading conditions data in serial and MT Athena + from IOVSvc.IOVSvcConf import CondSvc + svcMgr += CondSvc() + + from AthenaCommon.AlgSequence import AthSequencer + condSeq = AthSequencer("AthCondSeq") + + # Conditions data access infrastructure for serial and MT Athena + from IOVSvc.IOVSvcConf import CondInputLoader + condSeq += CondInputLoader( "CondInputLoader") + + import StoreGate.StoreGateConf as StoreGateConf + svcMgr += StoreGateConf.StoreGateSvc("ConditionStore") + +if vp1FilterEvents: + import VP1Algs.VP1EvtFilter + vp1FilterEvents = VP1Algs.VP1EvtFilter.parseFilterString(vp1FilterEvents) + VP1Algs.VP1EvtFilter.installEventFilter(vp1FilterEvents) + +from AthenaCommon.AlgSequence import AlgSequence +topSequence = AlgSequence() + + +#BATCH-MODE +# If "vp1Batch" is TRUE, then set the corresponding env var. +# The GUI of VP1 will not be shown, but the config file will be taken +# and in the end a render of the 3D window will be saved as PNG file. +# +# Moreover, if "vp1BatchAllEvents" is TRUE, then all the events +# in the provided data file will be processed with the same configuration +# file provided by the user. +# +if vp1Batch: + os.putenv("VP1_BATCHMODE","1") +if vp1BatchAllEvents: + os.putenv("VP1_BATCHMODE_ALLEVENTS","1") +if vp1BatchNEvents > 0: + os.putenv("VP1_BATCHMODE_NEVENTS", str(vp1BatchNEvents) ) +if (vp1BatchOutFolder != ""): + os.putenv("VP1_BATCHMODE_OUT_FOLDER", vp1BatchOutFolder) +if vp1BatchRandomConfiguration: + os.putenv("VP1_BATCHMODE_RANDOMCONFIG","1") + + + +#Detector setup: +from AthenaCommon.DetFlags import DetFlags +#from CalypsoCommon.DetFlags import DetFlags +if (vp1ID): DetFlags.ID_setOn() +else: vp1Extrapolator = False + +#watch LAr HV: +if ( vp1LarHvData ): + from time import time + svcMgr.AthenaSealSvc.CheckDictionary = TRUE + svcMgr.EventSelector.InitialTimeStamp = int (time()) + svcMgr.EventSelector.TimeStampInterval = 1 + from IOVDbSvc.CondDB import conddb + conddb.addFolder("DCS_OFL","/LAR/DCS/HV/BARREl/I16") + conddb.addFolder("DCS_OFL","/LAR/DCS/HV/BARREL/I8") +#------------ + +if (vp1Fatras): + include( "FatrasExample/Fatras_jobOptions.py" ) + +if (vp1TrigDecXML!=""): + include( "TrigConfigSvc/jobOptions_commonSetup.py" ) + include( "TrigConfigSvc/jobOptions_setupLVL1Svc.py" ) + include( "TrigConfigSvc/jobOptions_setupHLTSvc.py" ) + HLTConfigSvc.XMLMenuFile = vp1TrigDecXML + from TrigDecisionTool.TrigDecisionToolConf import Trig__TrigDecisionTool + ToolSvc += Trig__TrigDecisionTool("TrigDecisionTool") + +if (vp1Calo): + from AthenaCommon.GlobalFlags import globalflags +# from CalypsoCommon.GlobalFlags import globalflags + if globalflags.DataSource() == 'data' : + include ("LArConditionsCommon/LArIdMap_comm_jobOptions.py") + else: + include ("LArConditionsCommon/LArConditionsCommon_MC_jobOptions.py") + include ("LArConditionsCommon/LArIdMap_MC_jobOptions.py") + +#Extrapolator: +if vp1Extrapolator and (vp1ID or vp1Muon): + # Force tool initializations needed by the extrapolator + from VP1TrkAuxAlgs.VP1TrkAuxAlgsConf import VP1TrkInitializer + VP1TrkInitializer = VP1TrkInitializer() + VP1TrkInitializer.ForceExtrapolatorTools = True + topSequence += VP1TrkInitializer + + if not vp1Fatras and vp1Mc: + include ('TrkDetDescrSvc/AtlasTrackingGeometrySvc.py') + + from TrkExTools.AtlasExtrapolator import AtlasExtrapolator + VP1ExtraPolatorName='VP1Extrapolator'; + VP1Extrapolator = AtlasExtrapolator(name=VP1ExtraPolatorName) + + from TrkExEngine.AtlasExtrapolationEngine import AtlasExtrapolationEngine + ExtrapolationEngine = AtlasExtrapolationEngine(name='Extrapolation', nameprefix='Atlas', ToolOutputLevel=INFO) + ToolSvc += ExtrapolationEngine + + # Previous config from SetupFitters.py + # from TrkExTools.TrkExToolsConf import Trk__Extrapolator as Extrapolator + # VP1Extrapolator = Extrapolator(name='VP1Extrapolator', + # Navigator = VP1Navigator, + # MaterialEffectsUpdators = [ VP1MaterialUpdator ], + # Propagators = [ VP1Propagator ] ) + + ToolSvc += VP1Extrapolator + #We should append to variable instead: + os.putenv("VP1_JOBCFG_EXTRA_VP1_EXTRAPOLATORS","Trk::Extrapolator/"+VP1ExtraPolatorName) + +#Fitter: +# if vp1Fitter and vp1Extrapolator and (vp1ID or vp1Muon): +# VP1TrkInitializer.ForceFitterTools = True +# os.putenv("VP1_DEVEL_ENABLEREFIT","1") +# ########################################################## +# # The Extrapolator +# include('TrkDetDescrSvc/AtlasTrackingGeometrySvc.py') +# +# from TrkExRungeKuttaPropagator.TrkExRungeKuttaPropagatorConf import Trk__RungeKuttaPropagator as Propagator +# VP1Propagator = Propagator(name = 'VP1Propagator') +# ToolSvc += VP1Propagator +# +# # the Navigator has to get this one +# from TrkExTools.TrkExToolsConf import Trk__Navigator +# VP1Navigator = Trk__Navigator(name = 'VP1Navigator') +# VP1Navigator.TrackingGeometrySvc = svcMgr.AtlasTrackingGeometrySvc +# ToolSvc += VP1Navigator +# +# from TrkExTools.TrkExToolsConf import Trk__MaterialEffectsUpdator as MatUpdator +# VP1MaterialUpdator = MatUpdator(name='VP1MaterialEffectsUpdator') +# ToolSvc += VP1MaterialUpdator +# +# from TrkMeasurementUpdator_xk.TrkMeasurementUpdator_xkConf import Trk__KalmanUpdator_xk +# VP1Updator = Trk__KalmanUpdator_xk(name = 'VP1Updator') +# ToolSvc += VP1Updator +# +# from TrkDynamicNoiseAdjustor.TrkDynamicNoiseAdjustorConf import Trk__InDetDynamicNoiseAdjustment +# VP1DNAdjustor = Trk__InDetDynamicNoiseAdjustment(name = 'VP1DNAdjustor') +# #yminmax = 100.0) +# ToolSvc += VP1DNAdjustor +# from TrkKalmanFitter.TrkKalmanFitterConf import Trk__ForwardKalmanFitter as PublicFKF +# VP1FKF = PublicFKF(name = 'VP1FKF', +# StateChi2PerNDFPreCut = 25.0) +# ToolSvc += VP1FKF +# +# from TrkKalmanFitter.TrkKalmanFitterConf import Trk__KalmanSmoother as PublicBKS +# VP1BKS = PublicBKS(name = 'VP1BKS', +# InitialCovarianceSeedFactor = 200.) +# ToolSvc += VP1BKS +# +# from TrkKalmanFitter.TrkKalmanFitterConf import Trk__KalmanOutlierLogic as PublicKOL +# VP1KOL = PublicKOL(name = 'VP1KOL', +# StateChi2PerNDFCut = 12.5) +# ToolSvc += VP1KOL +# +# #FIXME! Only do this for Muons? +# from MuonRecExample import MuonRecTools +# MdtTubeHitOnTrackCreator = MuonRecTools.getPublicTool("MdtTubeHitOnTrackCreator") +# +# from TrkRIO_OnTrackCreator.TrkRIO_OnTrackCreatorConf import Trk__RIO_OnTrackCreator +# VP1RotCreator = Trk__RIO_OnTrackCreator(name = 'VP1RotCreator', +# ToolMuonDriftCircle = MdtTubeHitOnTrackCreator , +# Mode = 'all') +# ToolSvc += VP1RotCreator +# print VP1RotCreator +# print MdtTubeHitOnTrackCreator +# +# from TrkKalmanFitter.TrkKalmanFitterConf import Trk__KalmanFitter as ConfiguredKalmanFitter +# VP1KalmanFitter = ConfiguredKalmanFitter(name = 'VP1KalmanFitter', +# ExtrapolatorHandle = VP1Extrapolator, +# RIO_OnTrackCreatorHandle = VP1RotCreator, +# MeasurementUpdatorHandle = VP1Updator, +# ForwardKalmanFitterHandle = VP1FKF, +# KalmanSmootherHandle = VP1BKS, +# KalmanOutlierLogicHandle = VP1KOL, +# DynamicNoiseAdjustorHandle = None, +# AlignableSurfaceProviderHandle = None) +# +# ToolSvc += VP1KalmanFitter +# +# print VP1KalmanFitter +# os.putenv("VP1_JOBCFG_EXTRA_VP1_FITTERS",VP1KalmanFitter.name()) +# +# +# VP1KalmanFitterDNA = ConfiguredKalmanFitter(name = 'VP1KalmanFitterDNA', +# ExtrapolatorHandle = VP1Extrapolator, +# RIO_OnTrackCreatorHandle = VP1RotCreator, +# MeasurementUpdatorHandle = VP1Updator, +# ForwardKalmanFitterHandle = VP1FKF, +# KalmanSmootherHandle = VP1BKS, +# KalmanOutlierLogicHandle = VP1KOL, +# DynamicNoiseAdjustorHandle = VP1DNAdjustor, +# AlignableSurfaceProviderHandle = None) +# +# ToolSvc += VP1KalmanFitterDNA +# os.putenv("VP1_JOBCFG_EXTRA_VP1_FITTERS",VP1KalmanFitterDNA.name()) +# +# +# from TrkGlobalChi2Fitter.TrkGlobalChi2FitterConf import Trk__GlobalChi2Fitter +# VP1GlobalChi2Fitter = Trk__GlobalChi2Fitter(name = 'VP1GlobalChi2Fitter', +# ExtrapolationTool = VP1Extrapolator, +# NavigatorTool = VP1Navigator, +# PropagatorTool = VP1Propagator, +# RotCreatorTool = VP1RotCreator, +# MeasurementUpdateTool = VP1Updator, +# StraightLine = False, +# OutlierCut = 3.0, +# SignedDriftRadius = True, +# RecalculateDerivatives= True +# ) +# print VP1GlobalChi2Fitter +# ToolSvc += VP1GlobalChi2Fitter +# +# VP1GlobalChi2Fitter.OutputLevel=DEBUG +# +# os.putenv("VP1_JOBCFG_EXTRA_VP1_FITTERS","Trk::KalmanFitter/"+VP1KalmanFitter.name()+";"+"Trk::KalmanFitter/"+VP1KalmanFitterDNA.name()+";"+"Trk::GlobalChi2Fitter/"+VP1GlobalChi2Fitter.name()) + +#On a machine where the hostname does not indicate domain, pool will +#fail if trying to find nearest replica. In any case, dblookup.xml +#needs to be patched when running on real data: +include('VP1Algs/vp1FragmentFixDBReplica.py') + +if vp1NoSortDBReplicas: + PoolSvc = Service( "PoolSvc" ) + PoolSvc.SortReplicas = False + +from FaserGeoModel import SetGeometryVersion +from FaserGeoModel import GeoModelInit + +from GeoModelSvc.GeoModelSvcConf import GeoModelSvc +GeoModelSvc = GeoModelSvc() +GeoModelSvc.PrintMaterials = True +GeoModelSvc.GeoExportFile = "faserGeo.db" + +#Finally, the VP1 algorithm itself: +from VTI12Algs.VTI12AlgsConf import VTI12Alg +topSequence += VTI12Alg("VTI12Alg") + +VTI12Alg.NoGui=vp1NoGui + +if vp1CruiseTime > 0: + VTI12Alg.InitialCruiseMode = "EVENT" + VTI12Alg.InitialCruiseModePeriod = vp1CruiseTime + +VTI12Alg.InitiallyLoadedVP1Files = vp1CfgFiles +if (vp1Multinp): + VTI12Alg.MultipleFilesON = True + VTI12Alg.MFSourceDir = vp1Multinpsrc + VTI12Alg.MFLocalCopyDir = vp1Multinpcpy + VTI12Alg.MFAvailableLocalInputDirectories = vp1MultiAvailableSrcDirs + +topSequence.TimeOut=0 diff --git a/graphics/VTI12/VTI12Algs/src/VTI12Alg.cxx b/graphics/VTI12/VTI12Algs/src/VTI12Alg.cxx new file mode 100644 index 000000000..09a6e312e --- /dev/null +++ b/graphics/VTI12/VTI12Algs/src/VTI12Alg.cxx @@ -0,0 +1,268 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#include "VTI12Alg.h" + +#include "VTI12Gui/VP1Gui.h" +#include "VP1UtilsBase/VP1FileUtilities.h" + +#include "EventInfo/EventInfo.h" +#include "EventInfo/TriggerInfo.h" +#include "EventInfo/EventID.h" +#include "PathResolver/PathResolver.h" + +#include "GaudiKernel/IToolSvc.h" +#include "GaudiKernel/FileIncident.h" +#include "GaudiKernel/ServiceHandle.h" +#include "GaudiKernel/IEvtSelector.h" +#include "GaudiKernel/IIncidentSvc.h" + +#include <vector> +#include <stdexcept> +#include <iostream> +#include <iomanip> +#include <cstdint> // for uint64_t (unsigned long long) +#include <cstdlib> //For setenv + + +//____________________________________________________________________ +VTI12Alg::VTI12Alg(const std::string& name, ISvcLocator* svcLocator): + AthAlgorithm(name, svcLocator), + m_toolSvc(0),m_vp1gui(0) +{ + declareProperty("InitiallyLoadedVP1Files",m_initialvp1files); + declareProperty("InitialCruiseMode",m_initialCruiseMode="NONE"); + declareProperty("InitialCruiseModePeriod",m_initialCruiseSeconds=10); + + declareProperty("NoGui",m_noGui=false); + + // **** MF **** + declareProperty("MultipleFilesON",m_mfOn=false); + declareProperty("MFNumFileLimit",m_mfLimit=10); + declareProperty("MFSourceDir",m_mfSourceDir=""); + declareProperty("MFLocalCopyDir",m_mfLocalCopyDir=""); + declareProperty("MFAvailableLocalInputDirectories",m_mfAvailableLocalInputDirectories); + + + // Two ways of running in multiple files mode: + // + // 1) Source is directory on filesystem (e.g. for use in the control room). + // * MFSourceDir indicates the directory where files can be found. + // * MFLocalCopyDir indicates the temporary directory where + // files are copied before we tell pool to get them there. + // 2) Source is web directory + // * MFSourceDir indicates http url to small text file (to be + // parsed by VP1Gui/VP1EvtsOnServerInfo), with a list of + // available files (assumed to be in the same dir). + // Example value: "http://pcatdwww.cern.ch/atlas-point1/vp1events/fileinfo.txt" + // * MFLocalCopyDir has same meaning as before, but this time a + // subdirectory of it, "active_downloads", will be used to + // download files before they are subsequently moved to + // MFLocalCopyDir itself. + + // **** MF **** + + // Pick up patched Coin + ::setenv("LCGPATCH_COINMULTISELECT","1",1); +} + +//____________________________________________________________________ +VTI12Alg::~VTI12Alg() +{ +} + +//____________________________________________________________________ +StatusCode VTI12Alg::initialize() +{ + msg(MSG::INFO) << " in initialize() " << endmsg; + + //ToolSvc + StatusCode status = service("ToolSvc",m_toolSvc); + if (status.isFailure()||!m_toolSvc) { + msg(MSG::ERROR) << " Unable to get ToolSvc!" << endmsg; + return status; + } + + std::vector<std::string>::iterator it, itE = m_initialvp1files.end(); + for (it = m_initialvp1files.begin();it!=itE;++it) { + std::string file = PathResolver::find_file (*it, "DATAPATH"); + if (file=="") + file = PathResolver::find_file (*it+".vp1", "DATAPATH"); + if (file!="") + *it = file; + } + + // use the incident service to register a handler + IIncidentSvc* incsvc = 0; + status = service("IncidentSvc", incsvc, true); + + if(status.isFailure() || incsvc==0) { + msg(MSG::WARNING) << "Unable to get IncidentSvc! MF mechanism is disabled" << endmsg; + return StatusCode::SUCCESS; + } + + std::string endfilekey("EndTagFile"); + incsvc->addListener(this, endfilekey, 0); + msg(MSG::DEBUG) << "Added listener on "<<endfilekey << endmsg; + + //Create VP1 gui object and see if it considers settings to be valid. + m_vp1gui = new VP1Gui(&(*evtStore()),&(*detStore()),serviceLocator(),m_toolSvc, + m_initialvp1files, + m_initialCruiseMode,m_initialCruiseSeconds, + (m_mfOn ? m_mfSourceDir : ""), + (m_mfOn ? m_mfLocalCopyDir : ""), + m_mfLimit, + ( m_mfOn ? m_mfAvailableLocalInputDirectories : std::vector<std::string>() ) ); + if (!m_vp1gui->argumentsAreValid()) { + delete m_vp1gui; + m_vp1gui = 0; + exit(1);//Should we do this? It is kind of nice to not have to dig through the logfile to find the failure. + return StatusCode::FAILURE; + } + return StatusCode::SUCCESS; +} + +//____________________________________________________________________ +StatusCode VTI12Alg::execute() +{ + msg(MSG::DEBUG) <<" in execute() " << endmsg; + + if (!m_vp1gui) + return StatusCode::FAILURE; + + if (!m_noGui&&!m_vp1gui->hasBeenInitialised()) { + m_vp1gui->init();//Launch! + } + + const EventInfo* evt; + StatusCode status = evtStore()->retrieve(evt); + if(status.isSuccess()) { + // Get run/event number: + const uint64_t eventNumber = evt->event_ID()->event_number(); + int runNumber = evt->event_ID()->run_number(); + msg(MSG::DEBUG) << " Got run number = " << runNumber + << ", event number = " << eventNumber << endmsg; + // Get time stamp: + unsigned time = evt->event_ID()->time_stamp();//0 means no info. + + // Get L1 trigger type + const TriggerInfo* trig = evt->trigger_info(); + unsigned int trigType = trig ? trig->level1TriggerType() : 0; + + if (m_noGui||m_vp1gui->executeNewEvent(runNumber,eventNumber,trigType,time)) { + return StatusCode::SUCCESS; + } else { + msg(MSG::INFO) << " Ending application gracefully." << endmsg; + return StatusCode::FAILURE; + } + }; + + msg(MSG::WARNING) << " Unable to retrieve EventInfo from StoreGate. Skipping" << endmsg; + return StatusCode::SUCCESS; + +} + +//____________________________________________________________________ +StatusCode VTI12Alg::finalize() +{ + msg(MSG::INFO) <<" in finalize() " << endmsg; + + if (!m_vp1gui) + return StatusCode::FAILURE; + + if (!m_noGui) + m_vp1gui->cleanup(); + delete m_vp1gui; + + return StatusCode::SUCCESS; +} + +//____________________________________________________________________ +void VTI12Alg::handle(const Incident& inc) +{ + msg(MSG::INFO) << "Handling incident '" << inc.type() << "'" << endmsg; + + if (!m_vp1gui) { + msg(MSG::INFO) << "Aborting due to null VP1Gui pointer." << endmsg; + return; + } + + const FileIncident* fileInc = dynamic_cast<const FileIncident*>(&inc); + if(fileInc == 0) { + msg(MSG::WARNING) << " Unable to cast to file incident" << endmsg; + return; + } + else + msg(MSG::DEBUG) << " Casting to file incident successful" << endmsg; + + // Locate the EventSelector + ServiceHandle<IEvtSelector> pEvtSelector("EventSelector", this->name()); + StatusCode sc = pEvtSelector.retrieve(); + + if(!sc.isSuccess() || 0 == pEvtSelector) { + msg(MSG::WARNING) << "Could not find EventSelector" << endmsg; + return; + } + else + msg(MSG::DEBUG) << " Got EventSelector" << endmsg; + + IProperty* propertyServer = dynamic_cast<IProperty*>(pEvtSelector.operator->()); + if (!propertyServer) { + msg(MSG::WARNING) << "Could not get propertyServer" << endmsg; + return; + } + + std::vector<std::string> vect; + StringArrayProperty inputCollections("InputCollections", vect); + + sc = propertyServer->getProperty(&inputCollections); + if(!sc.isSuccess()) { + msg(MSG::INFO) << "Could not get InputCollections property" << endmsg; + return; + } + else + msg(MSG::DEBUG) << " Got InputCollections property" << endmsg; + + std::vector<std::string>::const_iterator iter = inputCollections.value().begin(); + std::vector<std::string>::const_iterator last = inputCollections.value().end(); + for(; iter != last; iter++) { + if(*iter != fileInc->fileName()) + vect.push_back(*iter); + } + + if(m_mfOn) { + std::string strNewFileName = m_vp1gui->nextRequestedEventFile(); + + if (strNewFileName.empty()) + return; + if (!VP1FileUtilities::fileExistsAndReadable(strNewFileName)) { + msg(MSG::WARNING) << " File requested by VP1 does not exists or is not readable: "<<strNewFileName<<". Ending." << endmsg; + return; + } + + vect.push_back(strNewFileName); + msg(MSG::INFO) << " Setting next event file: " << strNewFileName<< endmsg; + } + else { + std::vector<std::string> strNewFileNames = m_vp1gui->userRequestedFiles(); + for(unsigned i=0; i<strNewFileNames.size(); ++i) { + const std::string& strNewFileName = strNewFileNames[i]; + if (strNewFileName.empty()) + continue; + if (!VP1FileUtilities::fileExistsAndReadable(strNewFileName)) { + msg(MSG::WARNING) << " File requested by VP1 does not exists or is not readable: " << strNewFileName << endmsg; + continue; + } + vect.push_back(strNewFileName); + msg(MSG::INFO) << " Setting next event file: " << strNewFileName<< endmsg; + } + } + + StringArrayProperty newInputCollections("InputCollections", vect); + + if(propertyServer->setProperty(newInputCollections)!=StatusCode::SUCCESS) + msg(MSG::WARNING) << "Could not set new InputCollections property" << endmsg; + else + msg(MSG::DEBUG) << " InputCollections property set" << endmsg; +} diff --git a/graphics/VTI12/VTI12Algs/src/VTI12Alg.h b/graphics/VTI12/VTI12Algs/src/VTI12Alg.h new file mode 100644 index 000000000..9de2bbe4a --- /dev/null +++ b/graphics/VTI12/VTI12Algs/src/VTI12Alg.h @@ -0,0 +1,59 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////// +// // +// Header file for class VP1Alg // +// // +// update: Riccardo-Maria BIANCHI <rbianchi@cern.ch> // +// 23 May 2014 // +// // +// This is the Athena algorithm starting a VP1 GUI // +// // +///////////////////////////////////////////////////////////// + + +#ifndef VP1ALGS_VP1ALG +#define VP1ALGS_VP1ALG + +#include "AthenaBaseComps/AthAlgorithm.h" +#include "GaudiKernel/IIncidentListener.h" + +#include <string> +#include <vector> + +class VP1Gui; + +class VTI12Alg: public AthAlgorithm, + public IIncidentListener +{ + public: + VTI12Alg(const std::string& name, ISvcLocator* pSvcLocator); + ~VTI12Alg(); + + StatusCode initialize(); + StatusCode execute(); + StatusCode finalize(); + + void handle(const Incident& inc); + + private: + IToolSvc* m_toolSvc; + VP1Gui * m_vp1gui; + + std::vector<std::string> m_initialvp1files; + std::string m_initialCruiseMode;//"NONE", "EVENT", "TAB", "BOTH". + unsigned m_initialCruiseSeconds; + + bool m_noGui;//For testing job-options in RTT + + // Properties for multiple input files (mf) + bool m_mfOn; // Flag to turn multiple files ON/OFF. Default OFF + std::string m_mfSourceDir; // Directory to take event files from + std::string m_mfLocalCopyDir; // Directory to keep local copies of processed events. Default "." + int m_mfLimit; // Maximum number of local copies to keep + std::vector<std::string> m_mfAvailableLocalInputDirectories;//Will only be used if sourcedir is set and local +}; + +#endif diff --git a/graphics/VTI12/VTI12Algs/src/components/VTI12Algs_entries.cxx b/graphics/VTI12/VTI12Algs/src/components/VTI12Algs_entries.cxx new file mode 100644 index 000000000..1b2319b4e --- /dev/null +++ b/graphics/VTI12/VTI12Algs/src/components/VTI12Algs_entries.cxx @@ -0,0 +1,4 @@ +#include "../VTI12Alg.h" + +DECLARE_COMPONENT( VTI12Alg ) + diff --git a/graphics/VTI12/VTI12Gui/CMakeLists.txt b/graphics/VTI12/VTI12Gui/CMakeLists.txt new file mode 100644 index 000000000..08a7234d7 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/CMakeLists.txt @@ -0,0 +1,43 @@ +################################################################################ +# Package: VTI12Gui +################################################################################ +# Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> +# Author: Riccardo Maria BIANCHI <rbianchi@cern.ch> +################################################################################ + +# Declare the package name: +atlas_subdir( VTI12Gui ) + +# Declare the package's dependencies: +atlas_depends_on_subdirs( + PUBLIC Event/xAOD/xAODBase + PUBLIC graphics/VP1/VP1Base + PUBLIC graphics/VP1/VP1UtilsBase + ) + +# External dependencies: +find_package( Qt5 COMPONENTS Core OpenGL Gui Network PrintSupport Widgets ) +find_package( Coin3D ) +find_package( SoQt ) + +# Generate UI files automatically: +set( CMAKE_AUTOUIC TRUE ) +# Generate MOC files automatically: +set( CMAKE_AUTOMOC TRUE ) +# Generate resource files automatically: +set( CMAKE_AUTORCC TRUE ) + +# Component(s) in the package: +atlas_add_library( VTI12Gui VTI12Gui/*.h src/*.h src/*.cxx src/*.qrc + PUBLIC_HEADERS VTI12Gui + PRIVATE_INCLUDE_DIRS ${COIN3D_INCLUDE_DIRS} ${SOQT_INCLUDE_DIRS} + ${CMAKE_CURRENT_BINARY_DIR} + LINK_LIBRARIES VP1Base Qt5::Core Qt5::OpenGL Qt5::Gui VP1UtilsBase + Qt5::PrintSupport + PRIVATE_LINK_LIBRARIES ${COIN3D_LIBRARIES} ${SOQT_LIBRARIES} PathResolver xAODBase + xAODRootAccess xAODEventInfo xAODRootAccessInterfaces Qt5::Network ) + +# Install files from the package: +##atlas_install_scripts( share/* ) # installs into bin/ +atlas_install_runtime( share/* ) # install into share/ //TODO: check if we still need this! + diff --git a/graphics/VTI12/VTI12Gui/VTI12Gui/VP1AODSelection.h b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1AODSelection.h new file mode 100644 index 000000000..4c8bc0fae --- /dev/null +++ b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1AODSelection.h @@ -0,0 +1,54 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +////////////////////////////////////////////////////////////////////////// +// // +// Header file for class VP1AODSelection // +// // +// Description: Dialog for the selection of a xAOD file // +// // +// Author: Sebastian Andreas Merkt (sebastian.andreas.merkt@cern.ch) // +// Initial version: November 2017 // +// // +////////////////////////////////////////////////////////////////////////// + +#ifndef VP1AODSELECTION_H +#define VP1AODSELECTION_H + +#include <QDialog> +#include <QComboBox> +#include <QPushButton> +#include <QDialogButtonBox> + +class VP1AODSelection : public QDialog +{ + Q_OBJECT +public: + explicit VP1AODSelection(QWidget *parent = 0); + +private slots: + //Open the file selection dialog + void on_browseButton_clicked(); + + //Check and Save the settings + void loadDatabase(); + +public slots: + +private: + QString m_fileName; + QComboBox *m_directoryComboBox; + QPushButton *m_browseButton; + QPushButton *m_openButton; + QPushButton *m_cancelButton; + QDialogButtonBox *m_buttonBox; + + //Animate the click + void animateFindClick(); + + //Method to create the drop down combobox + QComboBox *createComboBox(const QString &text = QString()); +}; + +#endif // VP1AODSELECTION_H diff --git a/graphics/VTI12/VTI12Gui/VTI12Gui/VP1Authenticator.h b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1Authenticator.h new file mode 100644 index 000000000..6d5b59529 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1Authenticator.h @@ -0,0 +1,59 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1Authenticator // +// // +// Description: ... // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VP1AUTHENTICATOR_H +#define VP1AUTHENTICATOR_H + +#include "../src/ui_vp1authenticator.h" + +#include <QObject> +#include <QDialog> +#include <QNetworkReply> + + + +class QNetworkAccessManager; +class QSslError; + +class VP1Authenticator : public QDialog, public Ui::dlgAuthentication +{ + Q_OBJECT + +public: + + VP1Authenticator(QWidget*,QString); + virtual ~VP1Authenticator(); + + bool connectToServer(); + QNetworkAccessManager* networkAccessManager(); + +signals: + void authenticationSuccessful(QNetworkAccessManager*); + +private slots: + // ---- Https/SSL slots ---- + // Slots of the QNetworkReply + void finished(); + void error(QNetworkReply::NetworkError); + void sslErrors(const QList<QSslError>&); + + // GUI slots + void loginClicked(); + +private: + class Imp; + Imp* m_d; +}; + +#endif + diff --git a/graphics/VTI12/VTI12Gui/VTI12Gui/VP1AvailEvents.h b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1AvailEvents.h new file mode 100644 index 000000000..73fd54582 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1AvailEvents.h @@ -0,0 +1,83 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1AvailEvents // +// // +// Description: Class for keeping track of available events // +// when running VP1 in single-file-per-event // +// mode. // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: May 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef IVP1AVAILEVENTS_H +#define IVP1AVAILEVENTS_H +#include <QObject> +#include <QList> +#include "VTI12Gui/VP1EventFile.h" + +class VP1AvailEvents : public QObject { + + Q_OBJECT + +public: + + VP1AvailEvents(int timeCutForNew, QString tmpdir, int maxLocalFilesToKeep = -1, QObject * parent = 0);//maxLocalFilesToKeep<=2 means keep all. + //timeCutForNew: <0 : no time Cut; + // 0 : only newest is fresh + // >0 : time cut in seconds. + virtual void init() = 0;//Forbidden to do any real work before init is called (in particular emit signals!). + + virtual ~VP1AvailEvents(); + + //Next two returns ordered lists such that first means newer. + QList<VP1EventFile> allLocalEvents() const;//All events copied to tmp directory + QList<VP1EventFile> freshEvents() const;//Events that are considered "new", and which have not been investigated yet. + VP1EventFile newestEvent() const;//The newest event. Might have been investigated. + + void setCurrentEvent(int run,int event);//Call on every new event to update the history. + int maxLocalFilesToKeep() const; + +protected: + void cleanupAndCheckForEventListChanges();//Call from derived classes to ensure proper emission of XXXEventsChanged() signals. + void invalidateDirCache(const QString& dir);//Call from derived classes after making changes to files in directory. + bool inHistory(int run, int event) const; + QList<VP1EventFile> allEventFilesInDir(const QString& dir) const; + QList<VP1EventFile> freshEvents(VP1EventFile newestEvt, const QList<VP1EventFile>&) const;//Given timecut and newestEvt, trim down + //list so we only get the "fresh events" left. + QString tmpDir() const; + QString tmpLocalFileDir() const; + QString tmpActiveRetrievalDir();//attempts to create temporary subdirectory in tmpCopyDir which + //can be used for temporary files while downloading/copying, etc. + //returns an empty string in case of problems. + + //Definition of fresh events: + int timeCutForNew() const; + bool requireNewestRunNumber() const { return false; /*fixme*/ } + //Convenience: + bool isConsideredFresh ( const VP1EventFile& evt, const VP1EventFile& newestEvt ) const; + + void messageDebug(const QString&) const;//Messages to appear on output. +signals: + void allLocalEventsChanged(); + void freshEventsChanged(); + void message(const QString&) const;//Messages to appear in GUI. + +private slots: + void actualCleanup(); + void actualCheckForEventListChanges(); + +private: + + class Imp; + Imp * m_d; + +}; + +#endif diff --git a/graphics/VTI12/VTI12Gui/VTI12Gui/VP1AvailEvtsHttp.h b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1AvailEvtsHttp.h new file mode 100644 index 000000000..6c1e79b30 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1AvailEvtsHttp.h @@ -0,0 +1,55 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1AvailEvtsHttp // +// // +// Description: Implementation of VP1AvailEvents which // +// monitors and retrieves events from a web // +// directory (mainly from point1) // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: May 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VP1AVAILEVTSHTTP_H +#define VP1AVAILEVTSHTTP_H + +#include "VTI12Gui/VP1AvailEvents.h" + +class VP1AvailEvtsHttp : public VP1AvailEvents { + + Q_OBJECT + +public: + + VP1AvailEvtsHttp( QString fileinfoUrl, + int updateInterval, + int timeCutForNew, + QString tmpcopydir, + int maxLocalFilesToKeep = -1, + QObject * parent = 0 ); + virtual ~VP1AvailEvtsHttp(); + + virtual void init(); + +private slots: + void fileInfoChanged(); + void fileInfoDownloadSuccessful( const QString& urltofile, const QString& localtargetfile ); + void fileInfoDownloadFailed( const QString& error, const QString& urltofile,const QString& localtargetfile ); + void eventFileDownloadSuccessful( const QString& urltofile, const QString& localtargetfile, const QString& data ); + void eventFileDownloadFailed( const QString& error, const QString& urltofile,const QString& localtargetfile ); + void examineEvtsOnServer(); + +private: + + class Imp; + Imp * m_d; + +}; + +#endif diff --git a/graphics/VTI12/VTI12Gui/VTI12Gui/VP1AvailEvtsHttps.h b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1AvailEvtsHttps.h new file mode 100644 index 000000000..b7ae66c55 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1AvailEvtsHttps.h @@ -0,0 +1,66 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1AvailEvtsHttps // +// // +// Description: ... // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VP1AVAILEVTSHTTPS_H +#define VP1AVAILEVTSHTTPS_H + +// include C++ +//#include <stddef.h> // this to fix the 'ptrdiff_t' does not name a type error with Qt (http://qt-project.org/forums/viewthread/16992) + +#include <QObject> +#include <QNetworkReply> + +#include "VTI12Gui/VP1AvailEvents.h" + +class QNetworkAccessManager; + +class VP1AvailEvtsHttps : public VP1AvailEvents +{ + Q_OBJECT + +public: + + VP1AvailEvtsHttps(QString fileinfoUrl, + int updateInterval, + int timeCutForNew, + QString tmpcopydir, + int maxLocalFilesToKeep = -1, + QObject * parent = 0); + virtual ~VP1AvailEvtsHttps(); + + virtual void init(); + + QString fileinfoLocation(); + +public slots: + void start(QNetworkAccessManager* netmanager); + +private slots: + // ---- Https/SSL slots ---- + // Slots of the QNetworkReply + void finished(); + void error(QNetworkReply::NetworkError); + void sslErrors(const QList<QSslError>&); + void dataReadProgress(qint64,qint64); + void checkForStall(); + + // Timer slot + void generateHttpsRequest(); + +private: + class Imp; + Imp* m_d; +}; + +#endif + diff --git a/graphics/VTI12/VTI12Gui/VTI12Gui/VP1AvailEvtsLocalDir.h b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1AvailEvtsLocalDir.h new file mode 100644 index 000000000..6bd8e69f2 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1AvailEvtsLocalDir.h @@ -0,0 +1,53 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1AvailEvtsLocalDir // +// // +// Description: Implementation of VP1AvailEvents which // +// monitors events as they appear in a local // +// directory. // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: May 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VP1AVAILEVTSLOCALDIR_H +#define VP1AVAILEVTSLOCALDIR_H + +#include "VTI12Gui/VP1AvailEvents.h" + +class VP1AvailEvtsLocalDir : public VP1AvailEvents { + + Q_OBJECT + +public: + + friend class VP1LocalEvtRetriever; + + VP1AvailEvtsLocalDir( int timeCutForNew, + QString sourcedir, + QString tmpcopydir, + int maxLocalFilesToKeep = -1, + QObject * parent = 0 ); + void setSourceDir(QString); + QString currentSourceDir() const; + + //Just to let this class transport the info around: + void setAvailableSourceDirectories(QStringList); + QStringList availableSourceDirectories() const; + + virtual ~VP1AvailEvtsLocalDir(); + + virtual void init(); + +private: + class Imp; + Imp * m_d; +}; + +#endif diff --git a/graphics/VTI12/VTI12Gui/VTI12Gui/VP1ChannelManager.h b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1ChannelManager.h new file mode 100644 index 000000000..cd0bcfd35 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1ChannelManager.h @@ -0,0 +1,86 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////// +// // +// Header file for class VP1ChannelManager // +// // +// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Initial version: April 2007 // +// // +///////////////////////////////////////////////////////////// + +#ifndef VP1CHANNELMANAGER_H +#define VP1CHANNELMANAGER_H + +// channel manager - manages channel plugins, and knows which are +// available. (also creates/deletes/clones channels, + manages channels ids.) + +class IVP1ChannelWidget; +class VP1ExecutionScheduler; +class VP1MainWindow; +#include <QObject> +#include <QStringList> + +class VP1ChannelManager : public QObject { + + Q_OBJECT + +public: + VP1ChannelManager(VP1ExecutionScheduler*,VP1MainWindow*); + ~VP1ChannelManager(); + + QString loadPluginFile(QString filename); + //This does not actually instantiate any channel widgets - it merely + //instantiates the widget factory from the plugin file (if possible, + //otherwise it returns an error messages), and notices which + //channels are provided by this factor (if 0 channels are provided, + //it also returns an error message). If an empty string was + //returned, there were no errors. + bool unloadPluginFile(QString filename); + + QStringList currentPluginFiles() const; + + QStringList channelsInPluginFile(QString filename) const;//An empty returned stringlist is probably because 'filename' never was loaded succesfully. + + QStringList basename2UniqueNames(QString basename) const; + + bool deleteChannel(QString channeluniquename); + + IVP1ChannelWidget * getChannel( QString channelbasename, QString& err );//returns 0 if unsuccesful. Otherwise, 'err' contains an error message. + unsigned nActive( QString channelbasename ) const; + + IVP1ChannelWidget* uniqueName2Channel(QString uniquename) const; + + bool hasRefreshingSystem(const QString& uniquename) const; + + QStringList uniquenames() const; + + bool uniqueNameExists(QString) const; + bool baseNameExists(QString) const; + bool channelWithBasenameIsLoaded(QString basename) const; + + QStringList serializePluginInfo() const; + + QWidget* getController(IVP1ChannelWidget*); + + QString getIconLocation(const QString& channelname, const bool& isbasename=true);//Returns empty string if channelname is not recognised. + + QStringList availableChannelList(); + +signals: + void uniquename_channelListChanged(QStringList);//gives a list of channel unique_name's. + void availableChannelListChanged(QStringList);//gives a list of channel base_name's. + void availableUnusedChannelListChanged(QStringList);//gives a list of channel base_name's (only the one's that dont appear anywhere). + void newChannelCreated(IVP1ChannelWidget*); + void channelUncreated(IVP1ChannelWidget*); + +private: + class Imp; + Imp * m_d; +}; + +#endif + diff --git a/graphics/VTI12/VTI12Gui/VTI12Gui/VP1DockWidget.h b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1DockWidget.h new file mode 100644 index 000000000..cbd07e529 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1DockWidget.h @@ -0,0 +1,58 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////// +// // +// Header file for class VP1DockWidget // +// // +// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Initial version: April 2007 // +// // +///////////////////////////////////////////////////////////// + +#ifndef VP1DOCKWIDGET_H +#define VP1DOCKWIDGET_H + +#include <QDockWidget> + +class IVP1ChannelWidget; +class VP1TabManager; +class QResizeEvent; + +class VP1DockWidget : public QDockWidget { + + Q_OBJECT + +public: + + VP1DockWidget ( IVP1ChannelWidget * cw, VP1TabManager* tm ); + virtual ~VP1DockWidget(); + + void setSelected(); + void setUnselected(); + bool isSelected() const; + + IVP1ChannelWidget * channelWidget() const; + + //For dropping in and out of fullscreen: + void ensureCWHasNoParent(); + void ensureCWHasParent(); + + static QString highlightStyle();//Here so that other parts of the gui can use the same style for highlighting. + +signals: + void wasSelected(VP1DockWidget*); +private slots: + void systemRefreshInfoChanged(QString sysrefreshing, int nsysOn, int nsysOnRefreshed); + void updateTitle(); +protected: + void contextMenuEvent ( QContextMenuEvent * event ); + void resizeEvent ( QResizeEvent * event ); +protected: + class Imp; + Imp * m_d; +}; + +#endif diff --git a/graphics/VTI12/VTI12Gui/VTI12Gui/VP1EventDisplayEditor.h b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1EventDisplayEditor.h new file mode 100644 index 000000000..368e6138f --- /dev/null +++ b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1EventDisplayEditor.h @@ -0,0 +1,93 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1EventDisplayEditor // +// // +// Description: Event display editor. // +// // +// Author: Riccardo-Maria BIANCHI (rbianchi@cern.ch) // +// Initial version: September 2013 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VP1CUSTOMTOUREDITOR_H +#define VP1CUSTOMTOUREDITOR_H + +#include "VTI12Gui/VP1EventDisplaySceneView.h" + +#include "VP1Base/IVP1ChannelWidget.h" +#include "VP1Base/VP1Msg.h" + +#include <QWidget> +#include <QGraphicsView> +#include <QGraphicsScene> +#include <QGraphicsPixmapItem> +#include <QSplitter> + +class VP1MainWindow; + + +class VP1EventDisplayEditor : public QWidget { + + Q_OBJECT + +public: + + VP1EventDisplayEditor(VP1MainWindow* mainWindow, QList<unsigned long long> listRunEventNumberTimestamp); + virtual ~VP1EventDisplayEditor(); + +// QGraphicsView* getView(); + + void addPixmapList(QList<QPixmap>& list, QStringList& listNames); + void setTabsList(QStringList listNames); + + // void setState(QByteArray); + // QByteArray state() const; + + +protected: + void closeEvent(QCloseEvent*); + +private slots: + // void buttonClicked(); + void setTextLabel(); + void removeObject(); + void addLogo(); + void setBackgroundColor(); + void savePicture(); + void printPicture(); + void getTabSnapshot(); + void enableCustomTextField(bool checked); + +private: + + QString getEventDetailsLabel(); + void addTextLabel(QString text, QFont font); + + class Imp; + Imp * m_d; + QGraphicsScene* m_scene; +// QGraphicsScene* scene_preview; + QList< QGraphicsItem* > m_sceneItems; +// QGraphicsItem *itemPreview; + + VP1EventDisplaySceneView* m_preview; + + QStringList m_listTabNames; + QList<IVP1ChannelWidget*> m_allTabs; + + VP1MainWindow* m_mainWindow; + + int m_runNumber; + unsigned long long m_eventNumber; + unsigned m_eventTimestamp; + +// QSplitter *h1Splitter; +// QSplitter *h2Splitter; +}; + +#endif diff --git a/graphics/VTI12/VTI12Gui/VTI12Gui/VP1EventDisplaySceneView.h b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1EventDisplaySceneView.h new file mode 100644 index 000000000..37825e4a9 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1EventDisplaySceneView.h @@ -0,0 +1,116 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/* + * jira_1 + * VP1EventDisplaySceneView.h + * + * Created on: Sep 26, 2013 + * Author: rbianchi <Riccardo.Maria.Bianchi@cern.ch> + * + */ + +#ifndef VP1EVENTDISPLAYSCENEVIEW_H_ +#define VP1EVENTDISPLAYSCENEVIEW_H_ + + +#include <QtGui> +#include <QFrame> +#include <QHBoxLayout> +#include <QVBoxLayout> +#include <QGraphicsView> + +QT_FORWARD_DECLARE_CLASS(QLabel) +QT_FORWARD_DECLARE_CLASS(QSlider) +QT_FORWARD_DECLARE_CLASS(QToolButton) + +class VP1EventDisplaySceneView; + + +/* + * we create a new class inheriting from QGraphicsView, + * to reimplement the wheel event in order to use the wheel + * to zoom the image, when used over the zoom sliders + */ +class GraphicsView : public QGraphicsView +{ + Q_OBJECT +public: + GraphicsView(VP1EventDisplaySceneView *v) : QGraphicsView(), m_view(v) { } + +protected: + void wheelEvent(QWheelEvent *); + +private: + VP1EventDisplaySceneView *m_view; +}; + + + +/* + * The QFrame which contains the graphicsView and all other widgets. + * + * If the 'preview' argument is set to true, then a 'preview' view is built + * without rotation sliders and the zoom set to see the whole scene. + */ +class VP1EventDisplaySceneView : public QFrame +{ + Q_OBJECT +public: + VP1EventDisplaySceneView(const QString &name, bool preview = false, QWidget *parent = 0); + ~VP1EventDisplaySceneView(); + + QGraphicsView *view() const; + void setPreviewZoom(qreal xx); + void addRenderingFrame(); + void showRenderingFrame(); + void hideRenderingFrame(); + + public slots: + void zoomIn(int level = 1); + void zoomOut(int level = 1); + void print(); + + private slots: + void resetView(); + void setResetButtonEnabled(); + void setupMatrix(); + void togglePointerMode(); + void toggleOpenGL(); + void toggleAntialiasing(); + void rotateLeft(); + void rotateRight(); + + private: + GraphicsView *m_graphicsView; + + bool m_preview; + + QGraphicsRectItem* m_frame; + QGraphicsLineItem * m_line; + + QLabel *m_label; + QLabel *m_label2; + + QToolButton *m_selectModeButton; + QToolButton *m_dragModeButton; + QToolButton *m_openGlButton; + QToolButton *m_antialiasButton; + QToolButton *m_printButton; + QToolButton *m_resetButton; + + QVBoxLayout *m_zoomSliderLayout; + QSlider *m_zoomSlider; + QToolButton *m_zoomInIcon; + QToolButton *m_zoomOutIcon; + + QHBoxLayout *m_rotateSliderLayout; + QSlider *m_rotateSlider; + QToolButton *m_rotateLeftIcon; + QToolButton *m_rotateRightIcon; + +}; + + +#endif /* VP1EVENTDISPLAYSCENEVIEW_H_ */ diff --git a/graphics/VTI12/VTI12Gui/VTI12Gui/VP1EventFile.h b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1EventFile.h new file mode 100644 index 000000000..a9c99dde2 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1EventFile.h @@ -0,0 +1,56 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1EventFile // +// // +// Description: Class describing single-event files // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: May 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VP1EVENTFILE_H +#define VP1EVENTFILE_H + +#include <QString> +#include <QDateTime> + +class VP1EventFile { +public: + //The interesting bits: + //Event identity: + int runNumber() const; + unsigned long long eventNumber() const; + unsigned rawTime() const; + QDateTime time() const; + + //Where it is: + QString fileName() const;//base file name only. No '/' allowed! + QString md5Sum() const; + + bool isValid() const;//Internally, invalid instances are those with rawTime()==0. + QString print() const; + + //The boring bits: + VP1EventFile();//constructs invalid instance. + ~VP1EventFile(); + bool operator<(const VP1EventFile &) const;//Newer means "smaller". + bool operator==(const VP1EventFile &) const; + bool operator!=(const VP1EventFile &) const; + VP1EventFile(const VP1EventFile & ); + VP1EventFile & operator= (const VP1EventFile & ); + VP1EventFile(const QString& filename,const QString& md5sum, + int runnumber, unsigned long long eventnumber,unsigned time, bool isvalid = true ); + VP1EventFile(const QString&, const QString& md5sum = 0);//will attempt to decode from file name (e.g. vp1_234_123_1321334.pool.root). Instance becomes invalid if not succesful. +private: + class Imp; + Imp * m_d; + +}; + +#endif diff --git a/graphics/VTI12/VTI12Gui/VTI12Gui/VP1EvtsOnServerInfo.h b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1EvtsOnServerInfo.h new file mode 100644 index 000000000..8f278e8e7 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1EvtsOnServerInfo.h @@ -0,0 +1,58 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1EvtsOnServerInfo // +// // +// Description: Class for parsing the fileinfo.txt file // +// from the http directory where event files // +// from point 1 are available // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: May 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VP1EVTSONSERVERINFO_H +#define VP1EVTSONSERVERINFO_H + +#include <QString> +#include <QStringList> +#include "VTI12Gui/VP1EventFile.h" + +class VP1EvtsOnServerInfo { +public: + + VP1EvtsOnServerInfo(const QString& infofile);//the fileinfo.txt file from the server + ~VP1EvtsOnServerInfo(); + + bool isValid() const;//Check if infofile parsed succesfully. + QString error() const;//When !isValid, this gives an explanation. + + QStringList print() const; + + //Access the results: + unsigned long long numberOfEvents() const; + VP1EventFile newestEvent() const; + QList<VP1EventFile> events(int timecut = -1, bool requireNewestRunNumber = false ) const; + //Returns events in order of increasing time. + // + // * If timecut>0, only events within timecut seconds of newest + // event will be in list. + // * If requireNewestRunNumber is set, only events with same run + // number as the newest event will be in the list. + +private: + + VP1EvtsOnServerInfo( const VP1EvtsOnServerInfo & ); + VP1EvtsOnServerInfo & operator= ( const VP1EvtsOnServerInfo & ); + + class Imp; + Imp * m_d; + +}; + +#endif diff --git a/graphics/VTI12/VTI12Gui/VTI12Gui/VP1ExecutionScheduler.h b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1ExecutionScheduler.h new file mode 100644 index 000000000..a959ee95d --- /dev/null +++ b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1ExecutionScheduler.h @@ -0,0 +1,149 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////// +// // +// Header file for class VP1ExecutionScheduler // +// // +// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Initial version: April 2007 // +// // +///////////////////////////////////////////////////////////// + +#ifndef VP1EXECUTIONSCHEDULER_H +#define VP1EXECUTIONSCHEDULER_H + +// include C++ +//#include <stddef.h> // this to fix the 'ptrdiff_t' does not name a type error with Qt (http://qt-project.org/forums/viewthread/16992) + +// include VP1 +#include "VTI12Gui/VP1QtApplication.h" + +// include Qt +#include <QObject> +#include <QStringList> + +#ifdef BUILDVP1LIGHT + #include <TTree.h> + #include "xAODBase/IParticle.h" +#endif // BUILDVP1LIGHT + + +class IVP1System; +class IVP1ChannelWidget; + +class StoreGateSvc; +class IToolSvc; +class ISvcLocator; +class VP1AvailEvents; + +class VP1ExecutionScheduler : public QObject { + + Q_OBJECT + +public: + + //Cruise mode: + enum CruiseMode { NONE, + TAB, //Cycles to a new tab at a fixed interval (when it is loaded - gives soonvisible bonus) + EVENT,//Proceeds to a new event at a fixed interval (counting from when all visible channels are refreshed) + BOTH };//Cycles through all tabs and loads next event when they have all been shown. + + + void setCruiseMode(const CruiseMode&); + + //Fixme: Need shortcut keys for the cruise modes as well as next/prev. tab (for full screen). + + + //init/cleanup: + static VP1ExecutionScheduler* init(StoreGateSvc* eventStore, + StoreGateSvc* detStore, + ISvcLocator* svcLocator, + IToolSvc*toolSvc, + QStringList joboptions, + QString initialCruiseMode = "NONE", + unsigned initialCruiseSeconds = 10, + QString singleEventSource = "", + QString singleEventLocalTmpDir = "", + unsigned localFileCacheLimit = 10, + QStringList availableLocalInputDirectories = QStringList() ); + static void cleanup(VP1ExecutionScheduler*); + + //Call when new event data are available (returns false when the user closes the program) + bool executeNewEvent(const int& runnumber, const unsigned long long& eventnumber, const unsigned& triggerType = 0, const unsigned& time = 0);// + + VP1ExecutionScheduler(QObject * parent, + StoreGateSvc*eventStore,StoreGateSvc*detStore, + ISvcLocator* svcLocator,IToolSvc*toolSvc, + VP1AvailEvents * availEvents); + virtual ~VP1ExecutionScheduler(); + + void bringFromConstructedToReady(IVP1ChannelWidget*); + void uncreateAndDelete(IVP1ChannelWidget*); + + bool isRefreshing() const; + + bool hasAllActiveSystemsRefreshed(IVP1ChannelWidget*) const; + + //For VP1Gui: + QString nextRequestedEventFile() const; + + //For use by whatever logic wants to determine the next event file + //(probably VP1MainWindow): + void setNextRequestedEventFile(const QString&); + + QStringList userRequestedFiles(); + + QString saveSnaphsotToFile(IVP1System* s, bool batch = false); + + + #if defined BUILDVP1LIGHT + void loadEvent(); + QString split(const std::string& input, const std::string& regex); + int getEvtNr(){ return m_evtNr; }; + void setEvtNr(int evtNr){ m_evtNr = evtNr; }; + int getTotEvtNr(){ return m_totEvtNr; }; + #endif // BUILDVP1LIGHT + +signals: + void refreshingStatusChanged(bool); + + + +private: + class Imp; + Imp * m_d; + void refreshSystem(IVP1System*); + void eraseSystem(IVP1System*); + void actualUncreateAndDelete(IVP1ChannelWidget*); + + #if defined BUILDVP1LIGHT + xAOD::TEvent* m_event; + ::TFile* m_ifile; + QList<QStringList> m_list; + int m_evtNr = 0; + int m_totEvtNr = -1; + bool m_goBackFlag = false; + bool firstlaunch = true; + #endif // BUILDVP1LIGHT + +private slots: + void processSystemForRefresh(); + void updateProgressBarDuringRefresh(); + void channelCreated(IVP1ChannelWidget*); + void channelUncreated(IVP1ChannelWidget*); + void startRefreshQueueIfAppropriate(); + void systemNeedErase(); + + void performCruise(); + //OPVASK: void abortCruise(); + //Start + + #if defined BUILDVP1LIGHT + void passEvent(IVP1System*); + #endif // BUILDVP1LIGHT +}; + +#endif diff --git a/graphics/VTI12/VTI12Gui/VTI12Gui/VP1ExpertSettings.h b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1ExpertSettings.h new file mode 100644 index 000000000..af550ca00 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1ExpertSettings.h @@ -0,0 +1,131 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +////////////////////////////////////////////////////////////////////////// +// // +// Header file for class VP1ExpertSettings // +// // +// Description: Additional VP1 settings // +// // +// Author: Sebastian Andreas Merkt (sebastian.andreas.merkt@cern.ch) // +// Initial version: August 2017 // +// // +////////////////////////////////////////////////////////////////////////// + +#ifndef VP1EXPERTSETTINGS_H +#define VP1EXPERTSETTINGS_H + +#include <QDialog> +#include <QComboBox> +#include <QPushButton> +#include <QDialogButtonBox> +#include <QCheckBox> + +class VP1ExpertSettings : public QDialog +{ + Q_OBJECT +public: + explicit VP1ExpertSettings(QWidget *parent = 0); + +public slots: + void setPluginPath(const QString &path); + void setFileSelectDir(const QString &path); + void setScreenshotDir(const QString &path); + void setAuthLog(const QString &path); + +private: + QString m_pluginPath; + QString m_fileSelectDir; + QString m_screenshotDir; + QString m_authLog; + QDialogButtonBox* m_buttonBox; + QTabWidget* m_tabWidget; + QPushButton* m_okButton; + + bool checkBoxState(); + void closeEvent(QCloseEvent *event); + void keyPressEvent(QKeyEvent *event); + void setExpertSetting(const QString &type, const QString &name); +}; + + + + + + +class GeneralTab : public QWidget +{ + Q_OBJECT + +public: + explicit GeneralTab(QWidget *parent = 0); + +private slots: + #if defined BUILDVP1LIGHT + void setExpertSetting(const QString &type, const QString &name); + #else + void setExpertSetting(const QString &name); + #endif + void on_browseButton1_clicked(); + void slotScreenshotDirChanged(const QString &path); + +signals: + void signalScreenshotDirChanged(const QString &path); + +private: + QCheckBox* m_checkboxVerbose; + QCheckBox* m_checkboxDebug; + QCheckBox* m_checkboxDisallowMultipleChannels; + QCheckBox* m_checkboxDisplayMouseClicks; + QCheckBox* m_checkboxEnableAskOnClose; + QCheckBox* m_checkboxGuidesSphereInsteadOfCoordaxes; + QCheckBox* m_checkboxAntiAliasing; + QPushButton* m_browseButton1; + QLineEdit* m_lineEdit1; +}; + + + + + + +class AdvancedTab : public QWidget +{ + Q_OBJECT + +public: + explicit AdvancedTab(QWidget *parent = 0); + +private slots: + void on_browseButton1_clicked(); + void on_browseButton2_clicked(); + void on_browseButton3_clicked(); + void slotPluginPathChanged(const QString &path); + void slotFileSelectDirChanged(const QString &path); + void slotAuthLogChanged(const QString &path); + #if defined BUILDVP1LIGHT + void setExpertSetting(const QString &type, const QString &name); + #else + void setExpertSetting(const QString &name); + #endif + +signals: + void signalPluginPathChanged(const QString &path); + void signalFileSelectDirChanged(const QString &path); + void signalAuthLogChanged(const QString &path); + +private: + QPushButton* m_browseButton1; + QPushButton* m_browseButton2; + QPushButton* m_browseButton3; + QCheckBox* m_checkboxEnableInformOnEndOfJob; + QCheckBox* m_checkboxHardExitAtEnd; + QCheckBox* m_checkboxDevelShowAllCruiseAndEventControls; + QLineEdit* m_lineEdit1; + QLineEdit* m_lineEdit2; + QLineEdit* m_lineEdit3; +}; + + +#endif // VP1EXPERTSETTINGS_H diff --git a/graphics/VTI12/VTI12Gui/VTI12Gui/VP1GeoDBSelection.h b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1GeoDBSelection.h new file mode 100644 index 000000000..f07ef556d --- /dev/null +++ b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1GeoDBSelection.h @@ -0,0 +1,54 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +////////////////////////////////////////////////////////////////////////// +// // +// Header file for class VP1GeoDBSelection // +// // +// Description: Dialog for the selection of a geometry database // +// // +// Author: Sebastian Andreas Merkt (sebastian.andreas.merkt@cern.ch) // +// Initial version: August 2017 // +// // +////////////////////////////////////////////////////////////////////////// + +#ifndef VP1GEODBSELECTION_H +#define VP1GEODBSELECTION_H + +#include <QDialog> +#include <QComboBox> +#include <QPushButton> +#include <QDialogButtonBox> + +class VP1GeoDBSelection : public QDialog +{ + Q_OBJECT +public: + explicit VP1GeoDBSelection(QWidget *parent = 0); + +private slots: + //Open the file selection dialog + void on_browseButton_clicked(); + + //Check and Save the settings + void loadDatabase(); + +public slots: + +private: + QString m_fileName; + QComboBox *m_directoryComboBox; + QPushButton *m_browseButton; + QPushButton *m_openButton; + QPushButton *m_cancelButton; + QDialogButtonBox *m_buttonBox; + + //Animate the click + void animateFindClick(); + + //Method to create the drop down combobox + QComboBox *createComboBox(const QString &text = QString()); +}; + +#endif // VP1GEODBSELECTION_H diff --git a/graphics/VTI12/VTI12Gui/VTI12Gui/VP1Gui.h b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1Gui.h new file mode 100644 index 000000000..f67d9e6dd --- /dev/null +++ b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1Gui.h @@ -0,0 +1,76 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////// +// // +// Header file for class VP1Gui // +// // +// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Initial version: April 2007 // +// // +///////////////////////////////////////////////////////////// + +#ifndef VP1GUI_H +#define VP1GUI_H + +//NB: There should never be any Qt (or Athena of course) includes in this file!!! + +#include <string> +#include <vector> +#include <cstdint> // for uint64_t (unsigned long long) + +class StoreGateSvc; +class IToolSvc; +class ISvcLocator; + +class VP1Gui { +public: + + VP1Gui(StoreGateSvc* sg, StoreGateSvc* detstore, + ISvcLocator* svclocator,IToolSvc*toolSvc, + const std::vector<std::string>& initialvp1files=std::vector<std::string>(), + const std::string& initialCruiseMode = "NONE", unsigned initialCruiseSeconds = 10, + const std::string& singleEventSource = "", const std::string& singleEventLocalTmpDir = "", + unsigned localFileCacheLimit = 10, + const std::vector<std::string>& availableLocalInputDirectories = std::vector<std::string>() ); + ~VP1Gui(); + + //We can check the validity of the argument already during algorithm initialise: + bool argumentsAreValid() const; + + //Called in the first algorithm refresh to launch the gui: + void init(); + bool hasBeenInitialised(); + + //Called every algorithm refresh: + bool executeNewEvent( const int& run, + const uint64_t & event, + const unsigned& triggerType = 0,//When available + const unsigned& time = 0 //When available (seconds since 1970) + ); + //Called in algorithm finalise: + void cleanup(); + + std::vector<std::string> userRequestedFiles(); + + //Called when handling end-of-file incident (in multi-file mode) + std::string nextRequestedEventFile() const;//When mode where next input + //file is chosen dynamically, + //the choice is reported + //here. If empty is returned, + //the algorithm is expected to + //just take the latest file + //from the directory. +private: + + VP1Gui(const VP1Gui & ); + VP1Gui & operator= (const VP1Gui & ); + + class Imp; + Imp * m_d; + +}; + +#endif diff --git a/graphics/VTI12/VTI12Gui/VTI12Gui/VP1HttpGetFile.h b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1HttpGetFile.h new file mode 100644 index 000000000..d51604154 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1HttpGetFile.h @@ -0,0 +1,70 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1HttpGetFile // +// // +// Description: Download files in the background and get // +// notified upon completion. Optionally // +// require correct md5sum. // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: May 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VP1HTTPGETFILE_H +#define VP1HTTPGETFILE_H + +#include <QObject> +#include <QByteArray> + +class VP1HttpGetFile : public QObject { + + Q_OBJECT + +public: + + VP1HttpGetFile(QObject * parent = 0); + virtual ~VP1HttpGetFile(); + + void setMaxNumberOfPendingDownloads(unsigned); + unsigned maxNumberOfPendingDownloads() const;//Default is 8. A value of 0 disables limit. + unsigned numberOfPendingDownloads() const; + + bool isDownloading(const QString& urltofile) const; + bool isDownloadingTo(const QString& localtargetfile) const; + + QString startDownload( const QString& urltofile, + const QString& localtargetfile, + const QString& md5sum = "",//md5sum in hex format (like linux md5sum program outputs) + const QString& data = "" ); + + //Returns non-empty string in case download could not be started + //(too many pending downloads or already downloading to that target). + +signals: + //If download was started succesfully, it will always end with one + //of the following signals being emitted at a later time: + void downloadSuccessful( const QString& urltofile, + const QString& localtargetfile, + const QString& data ); + void downloadFailed( const QString& error, + const QString& urltofile, + const QString& localtargetfile, + const QString& data ); +private: + class Imp; + Imp * m_d; +private slots: + void downloadThreadFinished(); + void downloadThreadTerminated(); +}; + +//Todo: Set accepts-gzip header? + + +#endif diff --git a/graphics/VTI12/VTI12Gui/VTI12Gui/VP1IncomingMessageDialog.h b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1IncomingMessageDialog.h new file mode 100644 index 000000000..2a12658cb --- /dev/null +++ b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1IncomingMessageDialog.h @@ -0,0 +1,58 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////// +// // +// Header file for class VP1IncomingMessageDialog // +// // +// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Initial version: April 2007 // +// // +///////////////////////////////////////////////////////////// + +#ifndef VP1INCOMINGMESSAGEDIALOG_H +#define VP1INCOMINGMESSAGEDIALOG_H + +#include "VP1Base/VP1ExternalRequest.h" + +#include <QDialog> +#include <QQueue> +#include <QList> + +class VP1TabManager; +class VP1ChannelManager; + +class VP1IncomingMessageDialog : public QDialog { + + Q_OBJECT + +public: + + VP1IncomingMessageDialog( const VP1ExternalRequest&, + QQueue<VP1ExternalRequest>*, + bool *blockallmessages, + QList<QString>* messages_blockedsenders, + QList<VP1ExternalRequest>* _messages_blockedexactmessages, + VP1TabManager*, + VP1ChannelManager* , + QWidget *parent = 0 ); + virtual ~VP1IncomingMessageDialog(); + + void updatependinginfo(); +protected slots: + void request_gothere(); + void request_allclear(); + void request_allblock(); + void request_senderclear(); + void request_senderblock(); + void request_messageblock(); + void request_messageclear(); + +private: + class Imp; + Imp * m_d; +}; + +#endif diff --git a/graphics/VTI12/VTI12Gui/VTI12Gui/VP1MD5Sum.h b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1MD5Sum.h new file mode 100644 index 000000000..c79c0ab64 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1MD5Sum.h @@ -0,0 +1,47 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1MD5Sum // +// // +// Description: Calculates md5sum of file without reading // +// entire file into memory at once. // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: May 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VP1MD5SUM_H +#define VP1MD5SUM_H + +#include <QString> +#include <QByteArray> + +class VP1MD5Sum { +public: + + static QByteArray sum( const QString& filename ); + //Returns empty array in case of errors + + static bool sumMatches( const QString& filename, const QByteArray& md5sum ); + static bool sumMatches( const QString& filename, const QString& md5sum ); + //Returns false in case of errors (missing or unreadable file/empty md5sum) or mismatch. + + //We always assume sums in byte arrays to be raw bits, and sums in + //strings to be in hex format. Here are methods for + //conversion/sanity checking: + static QString sumToString(const QByteArray& ); + static QByteArray sumToByteArray(const QString& ); + static bool validMD5Sum(const QString&);//Does string have correct length and contain no invalid characters? + static QString sumToStandardFormat(const QString&);//Removes spaces converts to lower case. +private: + class Imp; + VP1MD5Sum(); + ~VP1MD5Sum(); +}; + +#endif diff --git a/graphics/VTI12/VTI12Gui/VTI12Gui/VP1MainWindow.h b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1MainWindow.h new file mode 100644 index 000000000..ca1bbdc5d --- /dev/null +++ b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1MainWindow.h @@ -0,0 +1,270 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////// +// // +// Header file for class VP1MainWindow // +// // +// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Initial version: April 2007 // +// // +///////////////////////////////////////////////////////////// + +#ifndef VP1MainWindow_H +#define VP1MainWindow_H + +// include the related GUI +#include "../src/ui_vp1mainwindow.h" + +// include VP1 +#include "VTI12Gui/VP1TcpServer.h" +#include "VTI12Gui/VP1EventDisplayEditor.h" + +// include Qt +#include <QQueue> +#include <QStringList> +#include <QMap> + +class VP1ChannelManager; +class VP1TabManager; +class QStringList; +class IVP1ChannelWidget; +//class VP1ConfigForm; +class VP1ExecutionScheduler; +class VP1AvailEvents; +class VP1IncomingMessageDialog; +class VP1PluginDialog; +class QProgressBar; +class QLabel; +class QComboBox; +class VP1StreamMenuUpdater; +class QMutex; + +//#include <QtGlobal> +//#if QT_VERSION > QT_VERSION_CHECK(5, 5, 0) +// class QWebEngineView; // Qt 5.6 +//#else +// class QWebView; +//#endif + + +struct VP1DirStatusData +{ + VP1DirStatusData() + : inputDir() + , dirStatus() + , enabled(true) + , bold(false) + {}; + + VP1DirStatusData(QString the_inputDir + , QString the_dirStatus + , bool the_enabled + , bool the_bold) + : inputDir(the_inputDir) + , dirStatus(the_dirStatus) + , enabled(the_enabled) + , bold(the_bold) + {}; + + QString inputDir; + QString dirStatus; + bool enabled; + bool bold; +}; + +typedef QMap<QAction*,VP1DirStatusData> VP1DirStatuses; + + +class VP1MainWindow : public QMainWindow, public Ui::VP1MainWindow +{ + Q_OBJECT + +public: + VP1MainWindow(VP1ExecutionScheduler*,VP1AvailEvents * availEvents,QWidget *parent = 0); + ~VP1MainWindow(); + + bool okToProceedToNextEvent() const; + + // Set next event to the execution scheduler and updates event controls + // We needed to separate this method from goToNextEvent() in order to be able + // to skip the bootstrap event in the https mode + void nextEvent(); + + QStringList userRequestedFiles(); + +public slots: + void loadPluginFile(QString filename); + + #ifdef BUILDVP1LIGHT + void request_expertSettings(); + #endif + void request_addEmptyTab(); + void request_channelInformation(); + void request_printChannel(); + QString request_saveChannelSnapshot(QString xLabel=""); + void request_cruisemodechange(); + void request_saveasConfig(); + void request_saveConfig(); + void request_loadConfig(); + void request_loadPlugin(); + void unloadPlugin_continue(); + void pluginDialogClosed(); + void saveAllCurrentChannels(); + void makeAllChannelsEventDisplay(); + void getAllChannelsIntoSnapshots(QList<QPixmap>& list, QStringList& listNames); + QPixmap getSingleChannelCustomSnapshot(IVP1ChannelWidget* tab, int width = 0); + QPixmap getSingleChannelCustomSnapshot(QString tabName, int width = 0); + + void tabListChanged(QStringList); + + void selectedChannelChanged(IVP1ChannelWidget*); + + void loadConfigurationFromFile(QString file); + void replaceConfigurationFile(QString file); + + void addToMessageBox( const QString&, const QString& extrastyleopts = "", + const QString& title = "", const QString& titleextrastyleopts = "" ); + void systemAddToMessageBox( const QString& ); + void channelAddToMessageBox( const QString& ); + void helperAddToMessageBox( const QString& ); + void changeFontSize(int); + + //For use when going to a new event (this updates system lists and quit()'s the app): + void goToNextEvent(); + #if defined BUILDVP1LIGHT + void goToPreviousEvent(); + void chooseEvent(); + #endif +public: + void setRunEvtNumber(const int& runnumber, const unsigned long long& eventnumber, const unsigned& triggerType = 0, const unsigned& time = 0, const bool& printmessage = true ); + bool mustQuit() const; + + VP1ChannelManager * channelManager() const { return m_channelmanager; } + VP1TabManager * tabManager() const { return m_tabmanager; } + + bool userRequestedExit() { return m_userRequestedExit; } + + int getRunNumber() { return m_runnumber; } + unsigned long long getEventNumber() { return m_eventnumber; } + int getEventTimestamp() { return m_timestamp; } + +protected: + VP1ChannelManager * m_channelmanager; + VP1TabManager * m_tabmanager; + QString m_currentconfigfile; + int m_runnumber; + unsigned long long m_eventnumber; + unsigned m_timestamp; + bool m_betweenevents; + + void closeEvent(QCloseEvent *event); + bool m_mustquit; + + QWidget* m_dummyemptycontroller; + VP1ExecutionScheduler*m_scheduler; + VP1AvailEvents * m_availEvents; + + VP1TcpServer m_tcpserver; + void listenOnTcp(); + + VP1IncomingMessageDialog* m_currentincomingdialog; + QQueue<VP1ExternalRequest> m_requestqueue; + bool m_blockallmessages; + QList<QString> m_messages_blockedsenders; + QList<VP1ExternalRequest> m_messages_blockedexactmessages; + + void addChannelIconsToComboBox(QComboBox* cb, const bool& isbasenames); + + QStringList m_currentunloadpluginfiles; + VP1PluginDialog*m_plugindialog; + + void setupStatusBar(); + QLabel*m_statusbarlabel; + + QMap<QString,QString> availablePluginFiles() const; + QMap<QString,QString> availableFiles(const QString& extension, + const QString& pathvar, + const QString& instareasubdir, + const QString& extradirenvvar, + bool currentdir = false) const; + +public: + QProgressBar*progressbar; +protected slots: + void receivedExternalRequest(VP1ExternalRequest); + void processEnqueuedRequests(); + void finishedIncomingDialog(); + void updateTcpIcon(); + void postInitUpdates(); + void showMenu_loadPlugin(); + void showMenu_loadPluginItemSelected(); + void showMenu_loadConfFile(); + void showMenu_loadConfFileItemSelected(); + void changeStyleActionTriggered(); + void changeFontSizeActionTriggered(); + void updateCentralStackWidget(); + void quickSetupTriggered(); + void updateEventControls(); + void addEventFile(); + void help_openUserGuide(); + void help_openUserSupport(); + void help_openVP1WebSite(); + void help_openAbout(); + + void updateInputDirectoriesStatus(); + void inputDirectoryActionTriggered(); + + void launch3DstereoEditor(); + + +protected: + QAction * m_action_infoAboutLoadedPlugins; + QMenu * m_menu_loadPlugin; + QMenu * m_menu_loadConfFile; + QMenu * m_menu_changeStyle; + QMenu * m_menu_changeFontSize; + QAction * m_actionAdd_empty_tab; + QAction * m_actionEnableExpertSettings; + QAction * m_actionSave_current_tabs; + QAction* m_action_addEventFile; + QAction* m_action_openUsersGuide; + QAction* m_action_openUsersSupport; + QAction* m_action_openVP1Site; + QAction* m_action_openAbout; + + QList<QAction*> m_inputdiractions; + VP1DirStatuses m_inputdirstatuses; + QString m_currentsaveimagepath; + QString m_currentloadpluginpath; + QString m_currentStream; + + //Fontsize: + QFont m_defaultfont; + double m_defaultfont_pointsize; + int m_defaultfont_pixelsize; + const QString m_settingsfile; + + bool m_userRequestedExit; + + QStringList m_userRequestedFiles; + + VP1StreamMenuUpdater* m_streamMenuUpdater; + QMutex* m_mutex; + +// // Web broser instance to show VP1 documentation +// #if QT_VERSION > QT_VERSION_CHECK(5, 5, 0) +// QWebEngineView *m_view; // Qt 5 +// #else +// QWebView *m_view; +// #endif + + // Event display editor + VP1EventDisplayEditor* m_edEditor; +}; + + +#endif + diff --git a/graphics/VTI12/VTI12Gui/VTI12Gui/VP1PluginDialog.h b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1PluginDialog.h new file mode 100644 index 000000000..ce06a1c26 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1PluginDialog.h @@ -0,0 +1,44 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////// +// // +// Header file for class VP1PluginDialog // +// // +// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Initial version: April 2007 // +// // +///////////////////////////////////////////////////////////// + +#ifndef VP1PLUGINDIALOG_H +#define VP1PLUGINDIALOG_H + +#include <QDialog> + +class VP1ChannelManager; +class VP1ExecutionScheduler; + +class VP1PluginDialog : public QDialog { + + Q_OBJECT + +public: + + VP1PluginDialog( QWidget*parent, VP1ChannelManager*,VP1ExecutionScheduler*); + virtual ~VP1PluginDialog(); + + QString unloadfile(); +private: + + class Imp; + Imp * m_d; + +private slots: + void pluginSelected(int i); + void unloadclicked(); + void updateRefreshInfo(); +}; + +#endif diff --git a/graphics/VTI12/VTI12Gui/VTI12Gui/VP1Prioritiser.h b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1Prioritiser.h new file mode 100644 index 000000000..316470139 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1Prioritiser.h @@ -0,0 +1,50 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////// +// // +// Header file for class VP1Prioritiser // +// // +// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Initial version: April 2007 // +// // +///////////////////////////////////////////////////////////// + +#ifndef VP1PRIORITISER_H +#define VP1PRIORITISER_H + +#include <QObject> +class IVP1System; +class IVP1ChannelWidget; + +class VP1Prioritiser : public QObject { + + Q_OBJECT + +public: + + VP1Prioritiser(QObject*parent); + virtual ~VP1Prioritiser(); + + double beginTiming_Refresh(IVP1System*);//Returns an estimate based on earlier measurements + double elapsedTiming_Refresh(); + double endTiming_Refresh();//Returns timing + + IVP1System* nextErasedActiveSystemByPriority();//Returns 0 if there are no systems with (ActiveState,State)==(ON,ERASED) + QList<IVP1System*> getSystemsToEraseByPriority();//Returns all systems in REFRESHED state - in prioritised order. + + double estimateRemainingCalcTime() const; + +public slots: + void visibleChannelsChanged(const QSet<IVP1ChannelWidget*>&vis,const QSet<IVP1ChannelWidget*>&soonvis,const double& soonvisbonus); + void channelCreated(IVP1ChannelWidget*); + void channelUncreated(IVP1ChannelWidget*); +private: + class Imp; + Imp * m_d; + void setupSysItr(IVP1ChannelWidget*cw); +}; + +#endif diff --git a/graphics/VTI12/VTI12Gui/VTI12Gui/VP1QtApplication.h b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1QtApplication.h new file mode 100644 index 000000000..35be98bc7 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1QtApplication.h @@ -0,0 +1,53 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////// +// // +// Header file for class VP1QtApplication // +// // +// Author: Riccardo Maria BIANCHI <rbianchi@cern.ch> // +// // +// This class reimplements the basic notify() method // +// of the QApplication class, in order to catch // +// exceptions from C++, and to avoid fatal errors // +// like: // +// "Qt has caught an exception thrown from an event // +// handler. Throwing exceptions from an event handler // +// is not supported in Qt. You must reimplement // +// QApplication::notify() and catch all exceptions // +// there. // +// // +// // +// Initial version: 19 November 2012 // +// // +///////////////////////////////////////////////////////// + +#ifndef VP1QTAPPLICATION_H +#define VP1QTAPPLICATION_H + +// include C++ +//#include <stddef.h> // this to fix the 'ptrdiff_t' does not name a type error with Qt (http://qt-project.org/forums/viewthread/16992) + +// include Qt +#include <QApplication> +#include <QMessageBox> + + + + +/* reimplementaion of the main QApplication class, + * to reimplement the notify() function, + * in order to catch C++ exceptions + */ +class VP1QtApplication: public QApplication { + Q_OBJECT +public: + VP1QtApplication(int &argc, char **argv): QApplication(argc, argv) {}; + virtual ~VP1QtApplication() {}; + virtual bool notify(QObject *rec, QEvent *ev); +}; + +#endif + + diff --git a/graphics/VTI12/VTI12Gui/VTI12Gui/VP1SelectEvent.h b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1SelectEvent.h new file mode 100644 index 000000000..e62b0b551 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1SelectEvent.h @@ -0,0 +1,42 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +////////////////////////////////////////////////////////////////////////// +// // +// Header file for class VP1SelectEvent // +// // +// Description: Dialog for the selection of a specific event in a file // +// // +// Author: Sebastian Andreas Merkt (sebastian.andreas.merkt@cern.ch) // +// Initial version: August 2018 // +// // +////////////////////////////////////////////////////////////////////////// + +#ifndef VP1SELECTEVENT_H +#define VP1SELECTEVENT_H + +#include <QDialog> +#include <QPushButton> +#include <QDialogButtonBox> +#include <QSpinBox> + +class VP1SelectEvent : public QDialog +{ + Q_OBJECT +public: + explicit VP1SelectEvent(int totEvtNr, int evtNr, QWidget *parent = 0); + +public slots: + +private: + void passEvtNr(); + void reject(); + + QPushButton* m_cancelButton; + QPushButton* m_openButton; + QDialogButtonBox* m_buttonBox; + QSpinBox* m_spinBox; +}; + +#endif // VP1SELECTEVENT_H diff --git a/graphics/VTI12/VTI12Gui/VTI12Gui/VP1TabManager.h b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1TabManager.h new file mode 100644 index 000000000..8f21ea431 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1TabManager.h @@ -0,0 +1,112 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////// +// // +// Header file for class VP1TabManager // +// // +// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Initial version: April 2007 // +// // +///////////////////////////////////////////////////////////// + +#ifndef VP1TABMANAGER_H +#define VP1TABMANAGER_H + +#include <QObject> +#include <QStringList> +#include <QMultiMap> +#include <QPair> +class VP1TabWidget; +class VP1ChannelManager; +class VP1DockWidget; +class IVP1ChannelWidget; +class QPoint; + +//NB: The tab manager is allowed to pop up boxes with warnings, information, etc. + +class VP1TabManager : public QObject { + + Q_OBJECT + +public: + + VP1TabManager(QObject*parent, VP1TabWidget *,VP1ChannelManager*); + ~VP1TabManager(); + + bool hasTab(QString) const; + bool showTab(QString); + bool showFirstChannelWithGivenBasename(QString basename); + QString suggestNewTabName(QString oldtabname) const; + QString currentTab() const; + QString currentChannelUniqueName() const; + IVP1ChannelWidget* selectedChannelWidget() const; + int nTabs() const; + void dropOutOfFullScreen();//Does nothing if not in FS mode. + + QList<IVP1ChannelWidget*> allChannels() const;//No particular order. + const QSet<IVP1ChannelWidget*>& visibleChannels() const; + const QSet<IVP1ChannelWidget*>& soonVisibleChannels() const; + bool isVisible(IVP1ChannelWidget*) const; + //bool isInNextTab(); + + void setTabCruiseMode(const bool&); + + QStringList tabList(); + QString channelToTab(IVP1ChannelWidget*); + + void launchStereoEditorCurrentTab(); +// void setAntiAliasingCurrentTab(bool); + + IVP1ChannelWidget * addChannelToTab( QString channelbasename, QString tabname ); +public slots: + void addNewTab( QString, const int& index = -1 ); + void renameTab( QString tabname, QString newtabname ); + void removeTab( QString tabname );// -> Also removes channels obviously. + void removeChannel(QString channeluniquename); + void moveChannelToTab(QString channeluniquename,QString tabname); + void cloneChannelToTab(QString channeluniquename,QString tabname); + void cloneTab(QString oldtabname,QString newtabname); + void removeAllTabs(); + + + void saveConfigurationToFile(QString filename,const bool& askonoverride=true); + void loadConfigurationFromFile(QString filename,const QMap<QString,QString>& availableplugins); + + void showChannelFullScreen(IVP1ChannelWidget*); + void showCurrentChannelFullScreen(); + void showTabFullScreen(QString tabname); + void showCurrentTabFullScreen(); + + void showNextTab(); + void showPreviousTab(); + + void raiseTabBarContextMenu(int,const QPoint &); + void setSelectedDockWidget(VP1DockWidget*dw=0); + void setSelectedChannelWidget(IVP1ChannelWidget*cw=0);//selects the associated dock widget + + //The next two methods/slots are needed to allow channels to remove themselves: +public: + void removeChannelAfterQueueEmpties(const QString&); +signals: + void tabListChanged(QStringList); + void selectedChannelChanged(IVP1ChannelWidget*);//0 if all were unselected + void visibleChannelsChanged(const QSet<IVP1ChannelWidget*>&vis,const QSet<IVP1ChannelWidget*>&soonvis,const double& soonvisbonus); + +protected: + class Imp; + Imp * m_d; + + bool eventFilter ( QObject *, QEvent * ); + typedef QPair<QByteArray,QMultiMap<QString,QByteArray> > ChanState; + void serializeChannelState(IVP1ChannelWidget*,ChanState&state); + void unserializeChannelState(IVP1ChannelWidget*cw,ChanState tate); + +protected slots: + void currentVisibleChanged(); + void executePendingChannelRemoval(); +}; + +#endif diff --git a/graphics/VTI12/VTI12Gui/VTI12Gui/VP1TcpServer.h b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1TcpServer.h new file mode 100644 index 000000000..eba055351 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1TcpServer.h @@ -0,0 +1,60 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////// +// // +// Header file for class VP1TcpServer // +// // +// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Initial version: April 2007 // +// // +///////////////////////////////////////////////////////////// + +#ifndef VP1TCPSERVER_H +#define VP1TCPSERVER_H + +#include <QObject> +#include <QAbstractSocket> +#include "VP1Base/VP1ExternalRequest.h" + +class VP1TcpServer : public QObject { + + Q_OBJECT + +public: + + ///////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////// + + VP1TcpServer(); + virtual ~VP1TcpServer(); + + bool listen(QString& err, const quint16& port = 4747);//Returns false (and fills the err string) if not successful. + quint16 port() const; + bool isListening(); +public slots: + void close(); + +signals: + void receivedExternalRequest(VP1ExternalRequest); + void listenStateChanged(bool);//Might be emitted up to 2 seconds after the state really changed + + ///////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////// + +private: + class Imp; + Imp * m_d; +private slots: + void acceptConnection(); + void readData(); + void handleError(QAbstractSocket::SocketError); + void socketDestroyed(QObject*); + void listenStateMightHaveChanged(); +}; + +#endif diff --git a/graphics/VTI12/VTI12Gui/VTI12Gui/VP1TextBrowser.h b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1TextBrowser.h new file mode 100644 index 000000000..4ee31a50d --- /dev/null +++ b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1TextBrowser.h @@ -0,0 +1,21 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef VP1TEXTBROWSER_H +#define VP1TEXTBROWSER_H + +#include <QTextBrowser> + +class VP1TextBrowser : public QTextBrowser { +public: + + VP1TextBrowser(QWidget * parent = 0); + virtual ~VP1TextBrowser(); + +protected: + void contextMenuEvent(QContextMenuEvent *); + +}; + +#endif diff --git a/graphics/VTI12/VTI12Gui/VTI12Gui/VP1WebWatcher.h b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1WebWatcher.h new file mode 100644 index 000000000..85cfd7421 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/VTI12Gui/VP1WebWatcher.h @@ -0,0 +1,72 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1WebWatcher // +// // +// Description: Http analogy of QFileSystemWatcher, which // +// uses http HEAD requests (in a subthread) at // +// regular intervals to monitor for changes // +// in files located on a webserver. // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: June 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VP1WEBWATCHER_H +#define VP1WEBWATCHER_H + +#include <QObject> +#include <QStringList> + + +class QDateTime; + +class VP1WebWatcher : public QObject { + + Q_OBJECT + +public: + + VP1WebWatcher( int recheckInterval_ms = 30000, QObject * parent = 0 ); + VP1WebWatcher( const QStringList& urls, int recheckInterval_ms = 30000, QObject * parent = 0 ); + virtual ~VP1WebWatcher(); + + void addUrl(const QString&); + void addUrls(const QStringList&); + + QStringList urls() const; + bool isWatchingUrl(const QString&) const; + + void removeUrl(const QString&); + void removeUrls(const QStringList&); + + //Get more information: + enum RESULT { UNKNOWN,//Might be because no http request was yet done. + INVALID_URL, + CONNECTION_PROBLEMS,//Various problems (server not found, no net connection, etc.) + NOT_ON_SERVER,//Request returned 404 (file not found on server) + EXISTS };//File was found on server + RESULT lastResult(const QString& url); + QString lastResultToString(const QString& url); + + QDateTime lastModTime(const QString& url);//Always invalid if lastResult(url)!=EXISTS (might be invalid for EXISTS as well). + +signals: + void urlChanged(const QString& url ); + +private slots: + void httpRequestDone(bool); +protected: + void timerEvent(QTimerEvent*); +private: + class Imp; + Imp * m_d; + +}; + +#endif diff --git a/graphics/VTI12/VTI12Gui/src/VP1AODSelection.cxx b/graphics/VTI12/VTI12Gui/src/VP1AODSelection.cxx new file mode 100644 index 000000000..6fd07a9e9 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1AODSelection.cxx @@ -0,0 +1,129 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +////////////////////////////////////////////////////////////////////////// +// // +// Header file for class VP1AODSelection // +// // +// Description: Dialog for the selection of a xAOD file // +// // +// Author: Sebastian Andreas Merkt (sebastian.andreas.merkt@cern.ch) // +// Initial version: November 2017 // +// // +////////////////////////////////////////////////////////////////////////// + +#include "VTI12Gui/VP1AODSelection.h" + +#include <QPushButton> +#include <QGridLayout> +#include <QLabel> +#include <QComboBox> +#include <QFileInfo> + +#include <QtWidgets> + +VP1AODSelection::VP1AODSelection(QWidget *parent) : QDialog(parent) +{ + //Set default dialog size + int nWidth = 800; + int nHeight = 220; + if (parent != NULL) + setGeometry(parent->x() + parent->width()/2 - nWidth/2, + parent->y() + parent->height()/2 - nHeight/2, + nWidth, nHeight); + else + resize(nWidth, nHeight); + + //Browse button to select database + m_browseButton = new QPushButton(tr("&Browse..."), this); + connect(m_browseButton, &QAbstractButton::clicked, this, &VP1AODSelection::on_browseButton_clicked); + + //Buttonbox to set Open, Cancel buttons + m_buttonBox = new QDialogButtonBox(this); + m_openButton = m_buttonBox->addButton(tr("&Open"), QDialogButtonBox::AcceptRole); + m_cancelButton = m_buttonBox->addButton(tr("&Cancel"),QDialogButtonBox::RejectRole); + connect(m_openButton, &QPushButton::clicked, this, &VP1AODSelection::loadDatabase); + connect(m_cancelButton, &QPushButton::clicked, this, &VP1AODSelection::reject); + + //Open QSettings to store path do database + QSettings settings("ATLAS", "VP1Light"); + QString text; + + //If no xAOD file has been provided via command line argument, the "xaod/path" value is "" + if(settings.value("aod/path").toString()==""){ + m_openButton->setEnabled(false); + text = "(*)"; + } else { //If a xAOD file has been provided show it in the combobox + text = settings.value("aod/path").toString(); + } + //Create the combobox + m_directoryComboBox = createComboBox(text); + + //Create the main layout + QGridLayout *mainLayout = new QGridLayout(this); + mainLayout->addWidget(new QLabel(tr("Select AOD file:")), 0, 0); + mainLayout->addWidget(m_directoryComboBox, 1, 0, 1, 2); + mainLayout->addWidget(m_browseButton, 1, 4); + mainLayout->addWidget(m_buttonBox, 3, 4); + + m_browseButton->setMinimumWidth(200); + m_buttonBox->setMinimumWidth(200); + m_browseButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + m_buttonBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); +} + +//Method to create the drop down combobox +QComboBox *VP1AODSelection::createComboBox(const QString &text) +{ + QComboBox *comboBox = new QComboBox; + comboBox->setMinimumWidth(600); + comboBox->setEditable(false); + comboBox->addItem(text); + comboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + return comboBox; +} + +//Animate the click +void VP1AODSelection::animateFindClick() +{ + m_openButton->animateClick(); +} + +//Open the file selection dialog +void VP1AODSelection::on_browseButton_clicked() +{ + m_fileName = QFileDialog::getOpenFileName(this, + tr("Select AOD file"), QDir::currentPath(), + tr("AOD Files (*)")); + + // Add the selected file to the combobox + if (!m_fileName.isEmpty()) { + if (m_directoryComboBox->findText(m_fileName) == -1) + m_directoryComboBox->addItem(m_fileName); + m_directoryComboBox->setCurrentIndex(m_directoryComboBox->findText(m_fileName)); + + //When valid a database is selected, enable the Open button to confirm + m_openButton->setEnabled(true); + } + +} + +//Check and Save the settings +void VP1AODSelection::loadDatabase(){ + + //Save xAOD path to settings + QSettings settings("ATLAS", "VP1Light"); + settings.setValue("aod/path", m_directoryComboBox->itemText(m_directoryComboBox->currentIndex())); + + //If the selected xAOD does not exists, go back + if (!QFileInfo::exists(m_directoryComboBox->itemText(m_directoryComboBox->currentIndex()))){ + QMessageBox msgBox; + msgBox.setWindowTitle("Virtual TI 12"); + msgBox.setText("AOD file does not exist. Please choose another file."); + msgBox.exec(); + return; + } + VP1AODSelection::setResult(1); + VP1AODSelection::accept(); +} diff --git a/graphics/VTI12/VTI12Gui/src/VP1Authenticator.cxx b/graphics/VTI12/VTI12Gui/src/VP1Authenticator.cxx new file mode 100644 index 000000000..16bf6bb96 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1Authenticator.cxx @@ -0,0 +1,590 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "VTI12Gui/VP1Authenticator.h" + +#include "VP1Base/VP1QtUtils.h" + +#include <QNetworkAccessManager> +#include <QSslError> +#include <QNetworkCookie> +#include <QFile> +#include <QFileInfo> +#include <QUrl> +#include <QBuffer> +#include <QStringMatcher> + +#include <iostream> +#include <QMetaType> + +//______________________ Imp ______________________________ +class VP1Authenticator::Imp { + +public: + Imp(VP1Authenticator*,QString); + ~Imp(); + + // Gets value of the HTML tag attribute. Returns an empty string if attribute not found + QString getTagAttributeVal(const QString& tag, const QString& attribute); + + // Connect signals of the QNetworkReply to slots of the VP1Authenticator + void connectToAuthenticator(VP1Authenticator* authenticator); + + // Display error message in the TextEdit box + void displayError(QString); + + VP1Authenticator* m_theClass; + QNetworkAccessManager* m_netmanager; + QNetworkReply* m_netreply; + QFile* m_log; + + int stage; + QString m_fileInfoUrl; + QString m_loginServer; +}; + +VP1Authenticator::Imp::Imp(VP1Authenticator* theClass + ,QString fileInfoUrl) + : m_theClass(theClass) + , m_netmanager(new QNetworkAccessManager()) + , m_netreply(0) + , m_log(0) + , stage(1) + , m_fileInfoUrl(fileInfoUrl) + , m_loginServer("login.cern.ch") +{ + #if defined BUILDVP1LIGHT + bool checkAuthEnabled = VP1QtUtils::expertSettingIsOn("expert","ExpertSettings/VP1_AUTH_ENABLELOG"); + #else + bool checkAuthEnabled = VP1QtUtils::environmentVariableIsOn("VP1_AUTH_ENABLELOG"); + #endif + + if(checkAuthEnabled) { + QString logname("vp1live-auth.log"); + if(QFileInfo(logname).exists() && !QFile(logname).remove()) + std::cerr << "VP1Authenticator ERROR: Unable to remove old logfile" << std::endl; + else { + m_log = new QFile(logname); + if(!m_log->open(QIODevice::WriteOnly)) { + std::cerr << "VP1Authenticator ERROR: Unable to open new logfile for writing" << std::endl; + delete m_log; + m_log = 0; + } + } + } +} + +VP1Authenticator::Imp::~Imp() +{ + // deleting m_netmanager is not my responsibility :) + delete m_netreply; + + if(m_log) { + m_log->close(); + delete m_log; + } +} + +QString VP1Authenticator::Imp::getTagAttributeVal(const QString& tag, const QString& attribute) +{ + QStringMatcher startMatcher(attribute + "=\"",Qt::CaseInsensitive); + QStringMatcher endMatcher("\""); + + int startPos = startMatcher.indexIn(tag); + if(startPos==-1) + return QString(""); + else { + int endPos = endMatcher.indexIn(tag,startPos+startMatcher.pattern().size()); + if(endPos==-1) // something is wrong with this tag + return QString(""); + else + return tag.mid(startPos+startMatcher.pattern().size(),endPos-startPos-startMatcher.pattern().size()); + } +} + +void VP1Authenticator::Imp::connectToAuthenticator(VP1Authenticator* authenticator) +{ + connect(m_netreply, SIGNAL(finished()), + authenticator, SLOT(finished())); + connect(m_netreply, SIGNAL(error(QNetworkReply::NetworkError)), + authenticator, SLOT(error(QNetworkReply::NetworkError))); + connect(m_netreply, SIGNAL(sslErrors(const QList<QSslError>&)), + authenticator, SLOT(sslErrors(const QList<QSslError>&))); +} + +void VP1Authenticator::Imp::displayError(QString message) +{ + m_theClass->teditError->setVisible(true); + m_theClass->setFixedSize(400,350); + m_theClass->teditError->append(message); + m_theClass->inpPhr->clear(); + m_theClass->inpPers->setEnabled(true); + m_theClass->inpPhr->setEnabled(true); + m_theClass->inpPhr->setFocus(); + if(m_log) { + QByteArray logBa(QString(message+"\n").toStdString().c_str()); + m_log->write(logBa); + } +} + +//__________________________ Main Class __________________________________ +VP1Authenticator::VP1Authenticator(QWidget* parent, QString fileInfoUrl) + : QDialog(parent) + , m_d(new Imp(this,fileInfoUrl)) +{ + setupUi(this); + setFixedSize(400,200); + + // Configure GUI properties + teditError->setVisible(false); + teditError->setLineWrapMode(QTextEdit::NoWrap); + pbtnLogin->setDefault(true); + + // Connect GUI signals to slots + connect(pbtnLogin,SIGNAL(clicked()),this,SLOT(loginClicked())); + connect(pbtnCancel,SIGNAL(clicked()),this,SLOT(reject())); + + qRegisterMetaType<QList<QSslError> >("QList<QSslError>"); +} + +VP1Authenticator::~VP1Authenticator() +{ + delete m_d; +} + +//____________ Https/SSL slots________________ + +bool VP1Authenticator::connectToServer() +{ + QUrl fileinfoUrl(m_d->m_fileInfoUrl); + QNetworkRequest netrequest(fileinfoUrl); + m_d->m_netreply = m_d->m_netmanager->get(netrequest); + m_d->connectToAuthenticator(this); + + return true; +} + +void VP1Authenticator::finished() +{ + QString message("\n\nVP1Authenticator done. STAGE " + QString::number(m_d->stage) + "\n"); + + QUrl redirectionUrl; + QList<QNetworkCookie> cookielist; + + // ******** Collect some information for the log ******** + + // ** Headers + QVariant val = m_d->m_netreply->header(QNetworkRequest::SetCookieHeader); + if(val.type()==QVariant::Invalid) { + message += QString(" No set cookies\n"); + } else if (!val.canConvert<QList<QNetworkCookie> >()){ + message += QString(" Cannot convert to the list of cookies\n"); + } else { + cookielist = val.value<QList<QNetworkCookie> >(); + for(int ii=0; ii<cookielist.size(); ++ii) { + const QNetworkCookie& cookie = cookielist.at(ii); + message += (" Received cookie #" + QString::number(ii) + "\n"); + message += (" *** Path: " + cookie.path() + "\n"); + message += (" *** Domain: " + cookie.domain() + "\n"); + message += (QString(" *** Secure: ") + (cookie.isSecure() ? "YES" : "NO") + "\n"); + message += (QString(" *** Session: ") + (cookie.isSessionCookie() ? "YES" : "NO") + "\n"); + message += (" *** Name: " + QString(cookie.name().constData()) + "\n"); + message += (" *** Value: " + QString(cookie.value().constData()) + "\n"); + } + } + + val = m_d->m_netreply->header(QNetworkRequest::ContentTypeHeader); + if(val.type()==QVariant::Invalid) { + message += QString(" No ContentType\n"); + } else if (!val.canConvert<QString>()) { + message += QString(" Cannot convert Content Type to String\n"); + } else { + QString conttype = val.value<QString>(); + message += QString(" Content type: " + conttype + "\n"); + } + + val = m_d->m_netreply->header(QNetworkRequest::ContentLengthHeader); + if(val.type()==QVariant::Invalid) { + message += QString(" No ContentLength\n"); + } else if (!val.canConvert<int>()) { + message += QString(" Cannot convert Content Length to int\n"); + } else { + int contlength = val.value<int>(); + message += QString(" Content Length: " + QString::number(contlength) + "\n"); + } + + val = m_d->m_netreply->header(QNetworkRequest::LocationHeader); + if(val.type()==QVariant::Invalid) { + message += QString(" No Location\n"); + } else if (!val.canConvert<QUrl>()) { + message += QString(" Cannot convert Content Length to QUrl\n"); + } else { + QUrl url = val.value<QUrl>(); + message += QString(" Location URL " + url.toString() + "\n"); + } + + // ** Attributes + val = m_d->m_netreply->attribute(QNetworkRequest::HttpStatusCodeAttribute); + if(val.type()==QVariant::Invalid) { + message += QString(" No StatusCode Attribute\n"); + } else if (!val.canConvert<int>()) { + message += QString(" Cannot convert StatusCode to int\n"); + } else { + int sc = val.value<int>(); + message += QString(" StatusCode : " +QString::number(sc) + "\n"); + } + + val = m_d->m_netreply->attribute(QNetworkRequest::RedirectionTargetAttribute); + if(val.type()==QVariant::Invalid) { + message += QString(" No Redirection Attribute\n"); + } else if (!val.canConvert<QUrl>()) { + message += QString(" Cannot convert Redirection to QUrl\n"); + } else { + redirectionUrl = val.value<QUrl>(); + message += QString(" Redirection : " + redirectionUrl.toString() + "\n"); + } + + message += QString("\n HTML response >>>>>\n"); + + QByteArray logMessage(message.toStdString().c_str()); + + // ** Write reply to log ** + QByteArray ba = m_d->m_netreply->readAll(); + logMessage = logMessage.append(ba); + logMessage = logMessage.append("\n<<<<< HTML response\n\n\n"); + if(m_d->m_log) + m_d->m_log->write(logMessage); + + + // *** Stage 5: + // Final response from the server. It may happen that the + // authentication was successfull, however the user is not + // authorized to access the requested resource + // + // Check that... + if(m_d->stage==5) { + QString replyBody(ba.data()); + if(replyBody.contains("authorization failed", Qt::CaseInsensitive)) { + QString errMessage("Authorization Failed"); + m_d->displayError(errMessage); + m_d->m_netmanager->deleteLater(); + m_d->m_netmanager = new QNetworkAccessManager(); + m_d->stage=1; + m_d->m_netreply=0; + return; + } + + if(m_d->m_netreply->error()==QNetworkReply::NoError) + authenticationSuccessful(m_d->m_netmanager); + } + + // ** Check for errors ** + if(m_d->m_netreply->error()!=QNetworkReply::NoError) { + QString errMessage("Network error occured during authentication phase\n"); + errMessage += QString("Error code " + QString::number((int)m_d->m_netreply->error()) + "\nExplanation on http://doc.trolltech.com/4.4/qnetworkreply.html#NetworkError-enum"); + m_d->displayError(errMessage); + m_d->stage=1; + return; + } + + // *** Stage 1: + // Received a reply redirecting us to login.cern.ch + // Take the redirection URL and issue GET request for it + if(m_d->stage==1) { + if(redirectionUrl.isEmpty() || redirectionUrl.host() != m_d->m_loginServer) { + QString errMessage("Wrong URL: " + m_d->m_fileInfoUrl + "\nPlease fix the URL and restart the job"); + m_d->displayError(errMessage); + m_d->stage=1; + return; + } else { + QNetworkRequest netrequest(redirectionUrl); + m_d->m_netreply = m_d->m_netmanager->get(netrequest); + if(m_d->m_log) { + QByteArray baLog("Get request sent\n_______________________________________________________\n\n"); + m_d->m_log->write(baLog); + } + m_d->connectToAuthenticator(this); + m_d->stage++; + return; + } + } + + // *** Stage 2: + // Received authentication form + // Parse contents of the authentication form + // look for input tags and collect their attributes + if(m_d->stage==2) { + QString replyBody(ba.data()); + + QString newRequestBody("__EVENTTARGET=&__EVENTARGUMENT=&__LASTFOCUS="); + + QStringMatcher inputStartMatcher("<input ",Qt::CaseInsensitive); + QStringMatcher inputEndMatcher("/>"); + + int inputStart = inputStartMatcher.indexIn(replyBody,0); + + while(inputStart!=-1) { + int inputEnd = inputEndMatcher.indexIn(replyBody,inputStart+inputStartMatcher.pattern().size()); + if(inputEnd==-1) // something is wrong with this tag + break; + else { + // Let's parse it + QString tag = replyBody.mid(inputStart,inputEnd-inputStart); + QString typeVal = m_d->getTagAttributeVal(tag,"type"); + QString nameVal = m_d->getTagAttributeVal(tag,"name"); + QString valueVal = m_d->getTagAttributeVal(tag,"value").replace(" ","+"); + + if(QString::compare(typeVal,"text",Qt::CaseInsensitive)==0) + valueVal = inpPers->text(); + else if(QString::compare(typeVal,"password",Qt::CaseInsensitive)==0) + valueVal = inpPhr->text(); + + if(QString::compare(typeVal,"checkbox",Qt::CaseInsensitive)!=0) { + QByteArray encodedNameVal = QUrl::toPercentEncoding(nameVal); + if(QString::compare(typeVal,"submit",Qt::CaseInsensitive)==0 + || QString::compare(typeVal,"text",Qt::CaseInsensitive)==0 + || QString::compare(typeVal,"password",Qt::CaseInsensitive)==0 ) { + newRequestBody+=("&"+QString(encodedNameVal)+"="+valueVal); + } else { + QByteArray encodedValueVal = QUrl::toPercentEncoding(valueVal); + if(newRequestBody.size()!=0) + newRequestBody+="&"; + newRequestBody+=(QString(encodedNameVal)+"="+QString(encodedValueVal)); + } + } + + // move to the next input + inputStart = inputStartMatcher.indexIn(replyBody,inputEnd+inputEndMatcher.pattern().size()); + } + } + + QByteArray newBody; + newBody=newBody.insert(0,newRequestBody); + + QString logMessage = "New Request Length: " + QString::number(newBody.size()) + "\n"; + logMessage += ("New Request Body:\n" + newRequestBody.replace(inpPhr->text(),"xxx") + "\n"); + + // Get form action + // !!! Hardwire this for now: + QString actionUrlString("https://"+m_d->m_loginServer); + + QStringMatcher actionStartMatcher("action=\"",Qt::CaseInsensitive); + QStringMatcher actionEndMatcher("\""); + int actionStart = actionStartMatcher.indexIn(replyBody,0); + if(actionStart!=-1) { + int actionEnd = actionEndMatcher.indexIn(replyBody,actionStart+actionStartMatcher.pattern().size()); + if(actionEnd!=-1) + actionUrlString += replyBody.mid(actionStart+actionStartMatcher.pattern().size(),actionEnd-actionStart-actionStartMatcher.pattern().size()); + } + + logMessage += ("New URL: " + actionUrlString + "\n"); + QByteArray actionUrlBa(actionUrlString.toStdString().c_str()); + QString actionUrlStringDecoded = QUrl::fromPercentEncoding(actionUrlBa); + logMessage += ("Decoded URL: " + actionUrlStringDecoded.replace("&","&") + + "\n\nPost request sent\n_______________________________________________________\n\n"); + + // Send Post request: + QNetworkRequest netrequest(QUrl(actionUrlStringDecoded.replace("&","&"))); + netrequest.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded"); + netrequest.setHeader(QNetworkRequest::ContentLengthHeader,newBody.size()); + m_d->m_netreply = m_d->m_netmanager->post(netrequest,newBody); + if(m_d->m_log) { + QByteArray baLog(logMessage.toStdString().c_str()); + m_d->m_log->write(baLog); + } + m_d->connectToAuthenticator(this); + m_d->stage++; + return; + } + + // *** Stage 3: + // Received response from the autentication attempt + // + // Check if the authentication was successful. This can be done + // either of these two ways: + // 1. Check number of set cookies, if it = 0 then authentication failed + // 2. Look for 'Logon failure' string in the response body + // We implement the option #1 + // + // If the authentication considered successfull then parse contents of the + // response, look for input tags and collect their attributes + // and compose a new POST request + if(m_d->stage==3) { + + if(cookielist.size()==0) { + // Authentication failed + QString errMessage("Authentication failed, please try again\n"); + m_d->displayError(errMessage); + m_d->stage=1; + return; + } + + QString replyBody(ba.data()); + QByteArray excludeFromEncoding(" "); + QString newRequestBody(""); + + QStringMatcher inputStartMatcher("<input ",Qt::CaseInsensitive); + QStringMatcher inputEndMatcher("/>"); + + int inputStart = inputStartMatcher.indexIn(replyBody,0); + + while(inputStart!=-1) { + + // It can happen that /> is in the middle of some string, for example it can + // be part of value="...". We need to take this into account as well + int inputEnd = inputStart; + int quoteCount = 1; // just to be able to enter the next loop + int quotePos = inputStart; + QStringMatcher quoteMatcher("\""); + + while(quoteCount%2!=0) { + inputEnd = inputEndMatcher.indexIn(replyBody,quotePos); + if(inputEnd==-1) + break; + quoteCount = 0; + quotePos = inputStart; + + while(true) { + quotePos = quoteMatcher.indexIn(replyBody,quotePos); + if(quotePos==-1||quotePos>inputEnd) + break; + quoteCount++; + quotePos++; + } + } + + if(inputEnd==-1) // something is wrong with this tag + break; + else { + // Let's parse it + QString tag = replyBody.mid(inputStart,inputEnd-inputStart); + QString typeVal = m_d->getTagAttributeVal(tag,"type"); + QString nameVal = m_d->getTagAttributeVal(tag,"name"); + QString valueVal = m_d->getTagAttributeVal(tag,"value"); + + if(QString::compare(typeVal,"text",Qt::CaseInsensitive)==0) + valueVal = inpPers->text(); + else if(QString::compare(typeVal,"password",Qt::CaseInsensitive)==0) + valueVal = inpPhr->text(); + + if(QString::compare(typeVal,"checkbox",Qt::CaseInsensitive)!=0 && + QString::compare(typeVal,"submit",Qt::CaseInsensitive)!=0) { + QByteArray encodedNameVal = QUrl::toPercentEncoding(nameVal); + QString valueVal1 = valueVal.replace("<","<"); + QString valueVal2 = valueVal.replace(""","\""); + QByteArray encodedValueVal = QUrl::toPercentEncoding(valueVal2,excludeFromEncoding); + if(newRequestBody.size()!=0) + newRequestBody+="&"; + newRequestBody+=(QString(encodedNameVal)+"="+QString(encodedValueVal).replace(" ","+")); + } + + // move to the next input + inputStart = inputStartMatcher.indexIn(replyBody,inputEnd+inputEndMatcher.pattern().size()); + } + } + + QByteArray newBody; + newBody=newBody.insert(0,newRequestBody); + + QString logMessage = "New Request Length: " + QString::number(newBody.size()) + "\n"; + logMessage += ("New Request Body:\n" + newRequestBody + "\n"); + + // Get form action + QString actionUrlString(""); + + QStringMatcher actionStartMatcher("action=\"",Qt::CaseInsensitive); + QStringMatcher actionEndMatcher("\""); + int actionStart = actionStartMatcher.indexIn(replyBody,0); + if(actionStart!=-1) { + int actionEnd = actionEndMatcher.indexIn(replyBody,actionStart+actionStartMatcher.pattern().size()); + if(actionEnd!=-1) + actionUrlString = replyBody.mid(actionStart+actionStartMatcher.pattern().size(),actionEnd-actionStart-actionStartMatcher.pattern().size()); + } + + logMessage += ("New URL: " + actionUrlString + "\n"); + + // Send Post request: + QNetworkRequest netrequest; + netrequest.setUrl(actionUrlString); + netrequest.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded"); + netrequest.setHeader(QNetworkRequest::ContentLengthHeader,newBody.size()); + m_d->m_netreply = m_d->m_netmanager->post(netrequest,newBody); + logMessage += ("\n\nPost request sent\n_______________________________________________________\n\n"); + if(m_d->m_log) { + QByteArray baLog(logMessage.toStdString().c_str()); + m_d->m_log->write(baLog); + } + m_d->connectToAuthenticator(this); + m_d->stage++; + return; + } + + // *** Stage 4: + // Recieved a final redirection to the requested resource + // Just try to get it + if(m_d->stage==4) { + QNetworkRequest netrequest(redirectionUrl); + m_d->m_netreply = m_d->m_netmanager->get(netrequest); + if(m_d->m_log) { + QByteArray baLog("Get request sent\n_______________________________________________________\n\n"); + m_d->m_log->write(baLog); + } + m_d->connectToAuthenticator(this); + m_d->stage++; + return; + } +} + +void VP1Authenticator::error(QNetworkReply::NetworkError err) +{ + if(m_d->m_log) { + QString message("VP1Authenticator error. STAGE " + QString::number(m_d->stage) + ", error code: " + QString::number((int)err) + "\n"); + QByteArray ba(message.toStdString().c_str()); + m_d->m_log->write(ba); + } +} + +void VP1Authenticator::sslErrors(const QList<QSslError>& errlist) +{ + if(m_d->m_log) { + QString message("VP1Authenticator SSL errors. STAGE " + QString::number(m_d->stage) + "\n"); + for(int ii=0; ii<errlist.size(); ++ii) + message += (" " + QString::number((int)errlist.at(ii).error()) + ", " + errlist.at(ii).errorString() + "\n"); + QByteArray ba(message.toStdString().c_str()); + m_d->m_log->write(ba); + } + m_d->m_netreply->ignoreSslErrors(); +} + +//____________ GUI slots________________ +void VP1Authenticator::loginClicked() +{ + // Hide error box, if visible + if(teditError->isVisible()) { + teditError->setVisible(false); + setFixedSize(400,200); + teditError->clear(); + } + + // Set focus on the login box, if empty + if(inpPers->text().isEmpty()) { + inpPers->setFocus(); + return; + } + + // Set focus on the pass box, if empty + if(inpPhr->text().isEmpty()) { + inpPhr->setFocus(); + return; + } + + inpPers->setEnabled(false); + inpPhr->setEnabled(false); + connectToServer(); +} + +QNetworkAccessManager* VP1Authenticator::networkAccessManager() +{ + return m_d->m_netmanager; +} diff --git a/graphics/VTI12/VTI12Gui/src/VP1AvailEvents.cxx b/graphics/VTI12/VTI12Gui/src/VP1AvailEvents.cxx new file mode 100644 index 000000000..eac6e48f2 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1AvailEvents.cxx @@ -0,0 +1,362 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class VP1AvailEvents // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: May 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12Gui/VP1AvailEvents.h" +#include "VP1Base/VP1Msg.h" +#include <QFileInfo> +#include <QDirIterator> +#include <QTimer> + +#include <algorithm> +#include <set> +#include <map> +#include <iostream> + +//____________________________________________________________________ +class VP1AvailEvents::Imp { +public: + VP1AvailEvents*theclass; + int timeCutForNew; + QString tmpDir; + int maxLocalFilesToKeep; + //subdirs in tmpDir, generated on the fly: + QString tmpLocalFileDir; + QString tmpActiveRetrievalDir; + + //Returns empty in case of problems: + QString attemptGenerationOfTmpSubdir(const QString& preferredname, QString& cachevar); + + class EventID { + public: + EventID(int r, unsigned long long e) : eventNumber(e), runNumber(r) {} + unsigned long long eventNumber; + int runNumber; + bool operator==(const EventID & o) const{ + return eventNumber==o.eventNumber && runNumber==o.runNumber; + } + bool operator<(const EventID & o) const + { + //This ordering is not "newer". It is solely to be able to use in a set. + return runNumber==o.runNumber ? eventNumber < o.eventNumber : runNumber < o.runNumber; + } + + EventID & operator= (const EventID & o ) + { + if (&o == this) return *this; + eventNumber = o.eventNumber; + runNumber = o.runNumber; + return *this; + } + }; + + static EventID evtToID(const VP1EventFile& evt) { + return EventID(evt.runNumber(),evt.eventNumber()); + } + + QList<EventID> historyOrdered; + std::set<EventID> historySorted; + QList<VP1EventFile> lastAllLocal; + QList<VP1EventFile> lastFresh; + + std::map<QString,std::pair<QDateTime,QList<VP1EventFile> > > dircache;//dirname -> (modtime,result) + + void cleanupTmpLocalFiles(); +}; + + +//____________________________________________________________________ +VP1AvailEvents::VP1AvailEvents(int timeCutForNew, QString td, int maxLocalFilesToKeep, QObject * parent) + : QObject(parent), m_d(new Imp) +{ + m_d->theclass = this; + m_d->timeCutForNew = timeCutForNew; + m_d->tmpDir = QString(td + (td.endsWith("/")?"":"/")).replace("//","/"); + m_d->maxLocalFilesToKeep = maxLocalFilesToKeep; +} + +//____________________________________________________________________ +VP1AvailEvents::~VP1AvailEvents() +{ + //Fixme: These two remove commands only has an effect when dir is empty!! + if (!m_d->tmpActiveRetrievalDir.isEmpty()&&m_d->tmpActiveRetrievalDir!="bad") + QFile::remove(m_d->tmpActiveRetrievalDir); + if (!m_d->tmpLocalFileDir.isEmpty()&&m_d->tmpLocalFileDir!="bad") + QFile::remove(m_d->tmpLocalFileDir); + delete m_d; +} + +//____________________________________________________________________ +int VP1AvailEvents::timeCutForNew() const +{ + return m_d->timeCutForNew; +} + +//____________________________________________________________________ +int VP1AvailEvents::maxLocalFilesToKeep() const +{ + return m_d->maxLocalFilesToKeep; +} + +//____________________________________________________________________ +QString VP1AvailEvents::tmpDir() const +{ + return m_d->tmpDir; +} + +//____________________________________________________________________ +QList<VP1EventFile> VP1AvailEvents::freshEvents(VP1EventFile newestEvt, const QList<VP1EventFile>& inputEventList) const +{ + QList<VP1EventFile> l; + if (!newestEvt.isValid()) + return l; + std::set<Imp::EventID>::const_iterator histIt, histItE(m_d->historySorted.end()); + if (m_d->timeCutForNew==0) { + if (m_d->historySorted.find(Imp::evtToID(newestEvt))==histItE) + l << newestEvt; + return l; + } + foreach(VP1EventFile evt, inputEventList) + if (m_d->historySorted.find(Imp::evtToID(evt))==histItE && isConsideredFresh(evt,newestEvt)) + l << evt; + return l; +} + + +//____________________________________________________________________ +QList<VP1EventFile> VP1AvailEvents::freshEvents() const +{ + return freshEvents(newestEvent(),allLocalEvents()); +} + +//____________________________________________________________________ +VP1EventFile VP1AvailEvents::newestEvent() const +{ + QList<VP1EventFile> evts(allLocalEvents()); + if (evts.isEmpty()) + return VP1EventFile();//invalid + return evts.front(); +} + +//____________________________________________________________________ +void VP1AvailEvents::setCurrentEvent(int run,int event) +{ + m_d->historyOrdered << Imp::EventID(run,event); + m_d->historySorted.insert(Imp::EventID(run,event)); +} + +//____________________________________________________________________ +void VP1AvailEvents::actualCleanup() +{ + //First we cleanup: + m_d->cleanupTmpLocalFiles(); + + //Then we schedule a check for event list changes: + QTimer::singleShot(10, this, SLOT(actualCheckForEventListChanges())); +} + +//____________________________________________________________________ +void VP1AvailEvents::actualCheckForEventListChanges() +{ + QList<VP1EventFile> allLocal = allLocalEvents(); + QList<VP1EventFile> fresh = freshEvents(); + if (m_d->lastAllLocal != allLocal) { + m_d->lastAllLocal = allLocal; + allLocalEventsChanged(); + } + if (m_d->lastFresh != fresh) { + m_d->lastFresh = fresh; + freshEventsChanged(); + } +} + +//____________________________________________________________________ +void VP1AvailEvents::cleanupAndCheckForEventListChanges() +{ + //We schedule the cleanup to take place shortly. The check for event + //list changes will be scheduled after the cleanup: + + //Then we schedule a check for event list changes: + QTimer::singleShot(10, this, SLOT(actualCleanup())); + +} + +//____________________________________________________________________ +bool VP1AvailEvents::inHistory(int run, int event) const +{ + return m_d->historySorted.find(Imp::EventID(run,event))!=m_d->historySorted.end(); +} + + +//____________________________________________________________________ +void VP1AvailEvents::invalidateDirCache(const QString& dir) +{ + std::map<QString,std::pair<QDateTime,QList<VP1EventFile> > >::iterator it = m_d->dircache.find(dir); + if (it!=m_d->dircache.end()) + m_d->dircache.erase(it); +} + +//____________________________________________________________________ +QList<VP1EventFile> VP1AvailEvents::allEventFilesInDir(const QString& dir) const +{ + if (dir.isEmpty()) + return QList<VP1EventFile>(); + + QFileInfo fi_dir(dir); + if (!fi_dir.exists()||!fi_dir.isDir()) + return QList<VP1EventFile>(); + + QDateTime modtime = fi_dir.lastModified(); + if (abs(modtime.time().msecsTo(QTime::currentTime()))>50) { + std::map<QString,std::pair<QDateTime,QList<VP1EventFile> > >::iterator it = m_d->dircache.find(dir); + if (it!=m_d->dircache.end()&&it->second.first==modtime) + return it->second.second; + } + + QStringList filters; + filters << "*_*.pool.root"; + //fixme + QDirIterator itDir(dir,filters,QDir::Files | QDir::NoDotAndDotDot | QDir::Readable | QDir::CaseSensitive); + + QList<VP1EventFile> l; + while (itDir.hasNext()) { + QString fn = itDir.next(); + fn.replace("//","/"); + VP1EventFile evt(fn); + if (evt.isValid()) + l << evt; + else + message("Could not decode event file name: "+fn); + } + + qSort(l); + + m_d->dircache[dir]=std::make_pair(modtime,l); + return l; +} + +//____________________________________________________________________ +QList<VP1EventFile> VP1AvailEvents::allLocalEvents() const +{ + return allEventFilesInDir(tmpLocalFileDir()); +} + + +//____________________________________________________________________ +QString VP1AvailEvents::Imp::attemptGenerationOfTmpSubdir(const QString& preferredname, QString& cachevar) +{ + if (!cachevar.isEmpty()) + return cachevar=="bad"?"":cachevar; + + QFileInfo fi(tmpDir); + if (!( fi.exists()&&fi.isDir())) { + theclass->message("Could not create subdir in "+tmpDir+", since it does not exists or is not a directory" ); + cachevar="bad"; + return ""; + } + int i(0); + while (true) { + ++i; + QString dir = tmpDir+(tmpDir.endsWith("/")?"":"/")+preferredname+(i==1?QString(""):QString::number(i))+"/"; + if (!QFile::exists(dir)) { + bool ok = QDir().mkdir(dir); + if (!ok) { + theclass->message("Could not create directory:: "+dir ); + cachevar="bad"; + return ""; + } + cachevar = dir; + return dir; + } + } +} + +//____________________________________________________________________ +QString VP1AvailEvents::tmpActiveRetrievalDir() +{ + return m_d->attemptGenerationOfTmpSubdir("activeretrievals",m_d->tmpActiveRetrievalDir); +} + +//____________________________________________________________________ +QString VP1AvailEvents::tmpLocalFileDir() const +{ + return m_d->attemptGenerationOfTmpSubdir("eventfiles",m_d->tmpLocalFileDir); +} + +//____________________________________________________________________ +void VP1AvailEvents::Imp::cleanupTmpLocalFiles() +{ + if (maxLocalFilesToKeep<=2) + return; + if (tmpLocalFileDir.isEmpty()) + return; + QString dir = theclass->tmpLocalFileDir(); + if (dir.isEmpty()) + return; + + QList<VP1EventFile> events = theclass->allLocalEvents(); + int ntoremove = events.count()-maxLocalFilesToKeep; + if (ntoremove<=3)//3 instead of 0 to keep down the times we call the machinery below. + return; + + //Rules of engagement: + //We never delete the current event. We never delete the previous + //event. We never delete the maxLocalFilesToKeep newest of the fresh + //events. + + QList<Imp::EventID> protectedEvents; + if (!historyOrdered.isEmpty()) { + protectedEvents << historyOrdered.back(); + if (historyOrdered.count()>1) + protectedEvents << historyOrdered.at(historyOrdered.count()-2); + } + QList<VP1EventFile> freshEvts = theclass->freshEvents(); + int ifreshkept(0); + foreach (VP1EventFile evt,theclass->freshEvents()) { + protectedEvents << Imp::evtToID(evt); + if (++ifreshkept==maxLocalFilesToKeep) + break; + } + + //Remove: + for (int i = events.count()-1; i>=0; --i ) { + if (protectedEvents.contains(Imp::evtToID(events.at(i)))) { + continue; + } + QFile::remove(events.at(i).fileName()); + if (--ntoremove<=0) + break; + } + theclass->invalidateDirCache(theclass->tmpLocalFileDir()); +} + +//____________________________________________________________________ +bool VP1AvailEvents::isConsideredFresh ( const VP1EventFile& evt, const VP1EventFile& newestEvt ) const +{ + //Notice: Logic here must be similar to logic in VP1EvtsOnServerInfo::events + + if (m_d->timeCutForNew==0) { + //Special case where only the newest event is fresh + return evt.rawTime()==newestEvt.rawTime() && evt.runNumber()==newestEvt.runNumber(); + } + if (requireNewestRunNumber()&&evt.runNumber()!=newestEvt.runNumber()) + return false; + const unsigned oldest_time = (m_d->timeCutForNew<0||unsigned(m_d->timeCutForNew)>newestEvt.rawTime()) ? 0 : newestEvt.rawTime() - m_d->timeCutForNew; + return evt.rawTime() >= oldest_time; +} + +//____________________________________________________________________ +void VP1AvailEvents::messageDebug(const QString& s) const +{ + std::cout<<VP1Msg::prefix_verbose()<<": "<<s.toStdString()<<std::endl; +} diff --git a/graphics/VTI12/VTI12Gui/src/VP1AvailEvtsHttp.cxx b/graphics/VTI12/VTI12Gui/src/VP1AvailEvtsHttp.cxx new file mode 100644 index 000000000..312bd0fc9 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1AvailEvtsHttp.cxx @@ -0,0 +1,250 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class VP1AvailEvtsHttp // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: May 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12Gui/VP1AvailEvtsHttp.h" +#include "VTI12Gui/VP1HttpGetFile.h" +#include "VTI12Gui/VP1EvtsOnServerInfo.h" +#include "VTI12Gui/VP1WebWatcher.h" +#include <QTimer> +#include <QFileInfo> +#include <QDir> +#include <QFile> +#include <QUrl> + +//____________________________________________________________________ +class VP1AvailEvtsHttp::Imp { +public: + VP1AvailEvtsHttp * theclass; + QString fileinfoUrl; + QString baseUrl; + VP1HttpGetFile httpgetfile_events; + VP1HttpGetFile httpgetfile_fileinfo; + VP1WebWatcher * webwatcher_fileinfo; + VP1EvtsOnServerInfo * evtsOnServer; + QTimer * examineEvtsOnServerTimer; + void restartExamineEvtsOnServerTimer() { + if (!examineEvtsOnServerTimer) { + examineEvtsOnServerTimer = new QTimer(theclass); + connect( examineEvtsOnServerTimer, SIGNAL(timeout()), theclass, SLOT(examineEvtsOnServer())); + } + examineEvtsOnServerTimer->start(3000); + } + void getFileInfoLater() { + QTimer::singleShot(10000, theclass, SLOT(fileInfoChanged())); + } + static unsigned ntmpdlcount; +}; + +unsigned VP1AvailEvtsHttp::Imp::ntmpdlcount = 0; + +//____________________________________________________________________ +VP1AvailEvtsHttp::VP1AvailEvtsHttp( QString fileinfoUrl, + int updateInterval, + int timeCutForNew, + QString tmpcopydir, + int maxLocalFilesToKeep, + QObject * parent ) + : VP1AvailEvents(timeCutForNew,tmpcopydir,maxLocalFilesToKeep,parent), m_d(new Imp) +{ + m_d->theclass = this; + m_d->examineEvtsOnServerTimer = 0; + m_d->fileinfoUrl = fileinfoUrl; + QUrl url(fileinfoUrl); + if (url.isValid()) { + QString path = url.path(); + QString infofilebasename = QFileInfo(path).fileName(); + if (!infofilebasename.isEmpty()&&path.endsWith(infofilebasename)) { + m_d->baseUrl=fileinfoUrl; + m_d->baseUrl.chop(infofilebasename.count()); + if (!QUrl(m_d->baseUrl).isValid()) + m_d->baseUrl=""; + else if (!m_d->baseUrl.endsWith("/")) + m_d->baseUrl += "/"; + } + } + + m_d->evtsOnServer = 0; + connect(&(m_d->httpgetfile_fileinfo),SIGNAL(downloadSuccessful(const QString&,const QString&,const QString&)), + this,SLOT(fileInfoDownloadSuccessful(const QString&,const QString&))); + connect(&(m_d->httpgetfile_fileinfo),SIGNAL(downloadFailed(const QString&,const QString&,const QString&,const QString&)), + this,SLOT(fileInfoDownloadFailed(const QString&,const QString&,const QString&))); + connect(&(m_d->httpgetfile_events),SIGNAL(downloadSuccessful(const QString&,const QString&,const QString&)), + this,SLOT(eventFileDownloadSuccessful(const QString&,const QString&,const QString&))); + connect(&(m_d->httpgetfile_events),SIGNAL(downloadFailed(const QString&,const QString&,const QString&,const QString&)), + this,SLOT(eventFileDownloadFailed(const QString&,const QString&,const QString&))); + + m_d->webwatcher_fileinfo = new VP1WebWatcher(updateInterval*1000,this); + connect(m_d->webwatcher_fileinfo,SIGNAL(urlChanged(const QString&)),this,SLOT(fileInfoChanged())); +} + +//____________________________________________________________________ +void VP1AvailEvtsHttp::init() +{ + m_d->webwatcher_fileinfo->addUrl(m_d->fileinfoUrl);//A signal will be triggered the first time the webwatcher knows anything about the url. + m_d->restartExamineEvtsOnServerTimer(); +} + +//____________________________________________________________________ +VP1AvailEvtsHttp::~VP1AvailEvtsHttp() +{ + delete m_d->evtsOnServer; + delete m_d; +} + +//____________________________________________________________________ +void VP1AvailEvtsHttp::fileInfoChanged() +{ + if (m_d->webwatcher_fileinfo->lastResult(m_d->fileinfoUrl)!=VP1WebWatcher::EXISTS) { + message("Problems investigating "+m_d->fileinfoUrl); + message(" ===> "+m_d->webwatcher_fileinfo->lastResultToString(m_d->fileinfoUrl)); + return; + } + QString ad = tmpActiveRetrievalDir(); + if (ad.isEmpty()) { + message("Error: No temporary retrieval directory set!"); + m_d->getFileInfoLater();//Avoid stalling forever (however this is an unlikely error). + return; + } + QString target = ad+"downloadedfileinfo.txt"; + if ( QFileInfo(target).exists() && !QFile(target).remove() ) { + message("ERROR: Could not remove old "+target); + m_d->getFileInfoLater();//Avoid stalling forever in case user fixes error (i.e. fixes permissions). + return; + } + QString err = m_d->httpgetfile_fileinfo.startDownload( m_d->fileinfoUrl,target); + if (!err.isEmpty()) { + message("Problems starting download to get file-info file: "+err); + m_d->getFileInfoLater();//Avoid stalling forever in case user fixes error (i.e. fixes net connection). + } +} + +//____________________________________________________________________ +void VP1AvailEvtsHttp::fileInfoDownloadSuccessful( const QString& urltofile, const QString& localtargetfile ) +{ + VP1EvtsOnServerInfo * newEvtsOnServerInfo = new VP1EvtsOnServerInfo(localtargetfile); + if (!newEvtsOnServerInfo->isValid()) { + message("Problems decoding info in file downloaded from "+urltofile); + message("Error: "+newEvtsOnServerInfo->error()); + delete newEvtsOnServerInfo; + QFile::remove(localtargetfile); + m_d->getFileInfoLater();//Avoid stalling forever in case this is temporary. + invalidateDirCache(tmpActiveRetrievalDir()); + return; + } + delete m_d->evtsOnServer; + m_d->evtsOnServer = newEvtsOnServerInfo; + + examineEvtsOnServer(); +} + +//____________________________________________________________________ +void VP1AvailEvtsHttp::examineEvtsOnServer() +{ + m_d->restartExamineEvtsOnServerTimer();//To ensure we don't get events too closely spaced here. + if (m_d->httpgetfile_events.numberOfPendingDownloads()>3) + return; + if (!m_d->evtsOnServer) + return; + + //Start download of one of the files from the server? + VP1EventFile evtToGet; + QString localfiledir = tmpLocalFileDir(); + if (localfiledir.isEmpty()) { + message("Problems with temporary local event file directory."); + return; + } + + foreach (VP1EventFile evt, m_d->evtsOnServer->events(timeCutForNew(), requireNewestRunNumber() )) { + //We are looking for an event which was never seen before and not available locally: + if (!evt.isValid()||inHistory(evt.runNumber(),evt.eventNumber())) + continue; + if ( !QFile::exists ( localfiledir+evt.fileName() ) ) { + evtToGet=evt; + break; + } + } + + if (!evtToGet.isValid()&&m_d->examineEvtsOnServerTimer) + m_d->examineEvtsOnServerTimer->stop();//No need to check back regularly until we get new information. + + if (evtToGet.isValid()) { + //Before we get it, let us check that we don't already have 3 + //fresh events locally which are newer than the one we are trying + //to download: + QList<VP1EventFile> freshLocalEvents = freshEvents(); + unsigned nNewer(0); + foreach(VP1EventFile evt,freshLocalEvents) { + if (evt < evtToGet) { + ++nNewer; + if (nNewer>=3) { + return; + } + } + } + QString ad = tmpActiveRetrievalDir(); + if (!ad.isEmpty()) { + QString url = m_d->baseUrl+evtToGet.fileName(); + QString target = ad+evtToGet.fileName()+"_"+QString::number(Imp::ntmpdlcount++); + //A quick check that we are not already downloading that file currently: + if (!m_d->httpgetfile_events.isDownloading(url)&&!m_d->httpgetfile_events.isDownloadingTo(target)) { + QString err = m_d->httpgetfile_events.startDownload( url,target,evtToGet.md5Sum(),localfiledir+evtToGet.fileName()); + if (!err.isEmpty()) { + message("Problems starting download of :" +url); + message(" => "+err); + } + } else { + //We are already downloading url - abort silently. + return; + } + } else { + message("Problems with temporary local download directory."); + } + } + invalidateDirCache(tmpActiveRetrievalDir());//Fixme: remove from here??? +} + + +//____________________________________________________________________ +void VP1AvailEvtsHttp::fileInfoDownloadFailed( const QString& error, const QString& urltofile,const QString& localtargetfile ) +{ + message("Problems downloading "+urltofile+": "+error); + QFile::remove(localtargetfile); + invalidateDirCache(tmpActiveRetrievalDir()); + m_d->getFileInfoLater();//Avoid stalling forever in case this is temporary. +} + +//____________________________________________________________________ +void VP1AvailEvtsHttp::eventFileDownloadSuccessful( const QString&, const QString& localtargetfile, const QString& data ) +{ + invalidateDirCache(tmpLocalFileDir()); + invalidateDirCache(tmpActiveRetrievalDir()); + + if (!QFile::rename(localtargetfile,data)) { + message("Error: Could not move "+localtargetfile+" to "+data); + QFile::remove(localtargetfile); + QFile::remove(data); + m_d->getFileInfoLater();//Avoid stalling forever in case this is temporary. + return; + } + cleanupAndCheckForEventListChanges(); +} + +//____________________________________________________________________ +void VP1AvailEvtsHttp::eventFileDownloadFailed( const QString& error, const QString& urltofile,const QString& localtargetfile ) +{ + message("Problems downloading "+urltofile+": "+error); + QFile::remove(localtargetfile); + m_d->getFileInfoLater();//Avoid stalling forever in case this is temporary. + invalidateDirCache(tmpActiveRetrievalDir()); +} diff --git a/graphics/VTI12/VTI12Gui/src/VP1AvailEvtsHttps.cxx b/graphics/VTI12/VTI12Gui/src/VP1AvailEvtsHttps.cxx new file mode 100644 index 000000000..530e33794 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1AvailEvtsHttps.cxx @@ -0,0 +1,397 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "VTI12Gui/VP1AvailEvtsHttps.h" +#include "VTI12Gui/VP1EvtsOnServerInfo.h" +#include "VTI12Gui/VP1EventFile.h" +#include "VTI12Gui/VP1MD5Sum.h" +#include "VP1Base/VP1Msg.h" + +#include <QNetworkAccessManager> +#include <QSslError> +#include <QNetworkCookie> +#include <QFile> +#include <QFileInfo> +#include <QUrl> +#include <QTimer> +#include <QBuffer> +#include <QStringMatcher> +#include <QDateTime> + +#include <iostream> +#include <QMetaType> + +/* + Stage values: + 0 - get head and check its last_modified header + 1 - get file info + 2 - get event file(s) + */ + +class VP1AvailEvtsHttps::Imp { + public: + Imp(VP1AvailEvtsHttps* + ,QString + ,int); + ~Imp(); + + void startTimer(int interval=0); + + // Connect signals of the QNetworkReply to slots of the VP1AvailEvtsHttps + void connectNetworkSignalsToSlots(); + + VP1AvailEvtsHttps* m_theclass; + QString m_fileInfoUrl; + QString m_baseUrl; + int m_updateInterval; + + QNetworkAccessManager* m_netmanager; + QNetworkReply* m_netreply; + QString m_evtToGet; + int m_stage; + QString m_urlLastMod; + QString m_expectedMD5Sum; + qint64 m_bytesReceived; + unsigned m_lastChangeTime; + + QTimer m_stallTimer; +}; + +VP1AvailEvtsHttps::Imp::Imp(VP1AvailEvtsHttps* theclass + ,QString fileInfoUrl + ,int updateInterval) + : m_theclass(theclass) + , m_fileInfoUrl(fileInfoUrl) + , m_baseUrl("") + , m_updateInterval(updateInterval) + , m_netmanager(0) + , m_netreply(0) + , m_evtToGet("") + , m_stage(0) + , m_urlLastMod("UNKNOWN") + , m_expectedMD5Sum("") + , m_bytesReceived(0) + , m_lastChangeTime(0) + , m_stallTimer(0) +{ + QUrl url(m_fileInfoUrl); + if (url.isValid()) { + QString path = url.path(); + QString infofilebasename = QFileInfo(path).fileName(); + if (!infofilebasename.isEmpty()&&path.endsWith(infofilebasename)) { + m_baseUrl=m_fileInfoUrl; + m_baseUrl.chop(infofilebasename.count()); + if (!QUrl(m_baseUrl).isValid()) + m_baseUrl=""; + else if (!m_baseUrl.endsWith("/")) + m_baseUrl += "/"; + } + } + + connect(&m_stallTimer,SIGNAL(timeout()), m_theclass, SLOT(checkForStall())); + m_stallTimer.start(10000); +} + +VP1AvailEvtsHttps::Imp::~Imp() +{ +} + +void VP1AvailEvtsHttps::Imp::startTimer(int interval) +{ + QTimer::singleShot((interval>0 ? m_updateInterval : 60) ,m_theclass,SLOT(generateHttpsRequest())); +} + +void VP1AvailEvtsHttps::Imp::connectNetworkSignalsToSlots() +{ + connect(m_netreply, SIGNAL(finished()), + m_theclass, SLOT(finished())); + connect(m_netreply, SIGNAL(error(QNetworkReply::NetworkError)), + m_theclass, SLOT(error(QNetworkReply::NetworkError))); + connect(m_netreply, SIGNAL(sslErrors(const QList<QSslError>&)), + m_theclass, SLOT(sslErrors(const QList<QSslError>&))); + connect(m_netreply, SIGNAL(downloadProgress(qint64,qint64)), + m_theclass, SLOT(dataReadProgress(qint64,qint64))); + m_bytesReceived = 0; +} + +VP1AvailEvtsHttps::VP1AvailEvtsHttps(QString fileinfoUrl, + int updateInterval, + int timeCutForNew, + QString tmpcopydir, + int maxLocalFilesToKeep, + QObject * parent) + : VP1AvailEvents(timeCutForNew,tmpcopydir,maxLocalFilesToKeep,parent) + , m_d(new Imp(this,fileinfoUrl,updateInterval)) +{ +} + +VP1AvailEvtsHttps::~VP1AvailEvtsHttps() +{ + delete m_d; +} + +void VP1AvailEvtsHttps::init() +{ + // Dummy for now +} + +void VP1AvailEvtsHttps::start(QNetworkAccessManager* netmanager) +{ + m_d->m_netmanager = netmanager; + m_d->startTimer(); +} + +QString VP1AvailEvtsHttps::fileinfoLocation() +{ + return m_d->m_fileInfoUrl; +} + +void VP1AvailEvtsHttps::generateHttpsRequest() +{ + QUrl fileInfoUrl(m_d->m_fileInfoUrl); + QNetworkRequest netrequest(fileInfoUrl); + if(m_d->m_stage==0) { + /** ---- For logging + std::cout << "VP1AvailEvtsHttps getHead stage -- " << m_d->m_stage << " --" << std::endl; + **/ + m_d->m_netreply = m_d->m_netmanager->head(netrequest); + } else if(m_d->m_stage==1) { + /** ---- For logging + std::cout << "VP1AvailEvtsHttps get stage -- " << m_d->m_stage << " --" << std::endl; + **/ + m_d->m_netreply = m_d->m_netmanager->get(netrequest); + } else { + // stage 2 + /** ---- For logging + std::cout << "VP1AvailEvtsHttps get stage -- " << m_d->m_stage << " --" << std::endl; + **/ + + QString activeRetrievalDir = tmpActiveRetrievalDir(); + QString target = activeRetrievalDir +"downloadedfileinfo.txt"; + VP1EvtsOnServerInfo newEvtsOnServerInfo(target); + + if (!newEvtsOnServerInfo.isValid()) { + message("Problems decoding info in file downloaded from " + m_d->m_fileInfoUrl); + QFile::remove(target); + invalidateDirCache(tmpActiveRetrievalDir()); + m_d->m_stage = 0; + m_d->startTimer(m_d->m_updateInterval); + return; + } + + VP1EventFile evtToGet; + QString localfiledir = tmpLocalFileDir(); + + foreach (VP1EventFile evt, newEvtsOnServerInfo.events(timeCutForNew(),requireNewestRunNumber())) { + //We are looking for an event which was never seen before and not available locally: + if (!evt.isValid()||inHistory(evt.runNumber(),evt.eventNumber())) + continue; + if (!QFile::exists(localfiledir+evt.fileName())){ + evtToGet=evt; + break; + } + } + + if(evtToGet.isValid()) { + //Before we get it, let us check that we don't already have 3 + //fresh events locally which are newer than the one we are trying + //to download: + QList<VP1EventFile> freshLocalEvents = freshEvents(); + unsigned nNewer(0); + foreach(VP1EventFile evt,freshLocalEvents) { + if (evt < evtToGet) { + ++nNewer; + if (nNewer>=3) { + m_d->m_stage = 0; + m_d->startTimer(m_d->m_updateInterval); + return; + } + } + } + + QUrl url(m_d->m_baseUrl + evtToGet.fileName()); + m_d->m_expectedMD5Sum = evtToGet.md5Sum(); + /** ---- For logging + std::cout << " Event : " << url.toString().toStdString() << std::endl; + **/ + QNetworkRequest netrequestEvt(url); + m_d->m_evtToGet = evtToGet.fileName(); + m_d->m_netreply = m_d->m_netmanager->get(netrequestEvt); + } else { + m_d->m_stage = 0; + m_d->startTimer(m_d->m_updateInterval); + return; + } + } + m_d->connectNetworkSignalsToSlots(); +} + +void VP1AvailEvtsHttps::finished() +{ + VP1Msg::messageDebug("VP1AvailEvtsHttps::finished()"); + int sc=-9999; + QVariant val = m_d->m_netreply->attribute(QNetworkRequest::HttpStatusCodeAttribute); + if(val.type()==QVariant::Int) + sc = val.value<int>(); + else if(val.type()==QVariant::Invalid) + message("No status code obtained while processing " + m_d->m_netreply->url().toString()); + else if(!val.canConvert<int>()) + message("Cannot convert status code to int while processing " + m_d->m_netreply->url().toString()); + else + sc = val.value<int>(); + + VP1Msg::messageDebug("sc: " + QString::number(sc)); + + QString lastModified; + QVariant lastModHeader = m_d->m_netreply->header(QNetworkRequest::LastModifiedHeader); + if(lastModHeader.type()!=QVariant::Invalid && + lastModHeader.canConvert<QDateTime>()) { + QDateTime lastModTime = lastModHeader.value<QDateTime>(); + lastModified = lastModTime.toString(); + } + + /** ---- For logging + std::cout << "VP1AvailEvtsHttps stage -- " << m_d->m_stage + << " -- finished with error=" << (int)m_d->m_netreply->error() + << ", sc=" << sc + << ", LM=" << lastModified.toStdString() << std::endl; + **/ + + if(m_d->m_netreply->error()==QNetworkReply::NoError) { + if(m_d->m_stage==0) { + if(!lastModified.isEmpty() && lastModified!=m_d->m_urlLastMod) { + // The file info has been modified, go to the stage 1 + m_d->m_urlLastMod = lastModified; + m_d->m_stage = 1; + } else { + // Reuse the already downloaded file info + m_d->m_stage = 2; + } + }else if(m_d->m_stage==1) { + // Write out fileinfo to local file for parsing + QString activeRetrievalDir = tmpActiveRetrievalDir(); + QString target = activeRetrievalDir +"downloadedfileinfo.txt"; + /** ---- For logging + std::cout << " Active Ret Dir: " << activeRetrievalDir.toStdString() << std::endl; + std::cout << " Target : " << target.toStdString() << std::endl; + **/ + + // Delete already existing fileinfo + if(QFileInfo(target).exists() && !QFile(target).remove()) { + message("ERROR: Could not remove the old fileinfo " + target); + m_d->m_stage = 0; + m_d->startTimer(m_d->m_updateInterval); + return; + } + + // Create new fileinfo + QFile localfileinfo(target); + if(!localfileinfo.open(QIODevice::WriteOnly)) { + message("ERROR: Unable to open " + target + " for writing"); + m_d->m_stage = 0; + m_d->startTimer(m_d->m_updateInterval); + return; + } + + // Wrute received fileinfo to local file + QByteArray ba = m_d->m_netreply->readAll(); + localfileinfo.write(ba); + localfileinfo.close(); + m_d->m_stage = 2; + }else if(m_d->m_stage==2) { + // Open target file for writing + QString target = tmpActiveRetrievalDir() + m_d->m_evtToGet; + QFile targetFile(target); + if(!targetFile.open(QIODevice::WriteOnly)) { + message("ERROR: Unable to open " + target + " for writing"); + m_d->m_stage = 0; + m_d->startTimer(m_d->m_updateInterval); + return; + } + + // Write to file + QByteArray ba = m_d->m_netreply->readAll(); + targetFile.write(ba); + targetFile.close(); + /** ---- For logging + std::cout << "\t\t" << target.toStdString() << " written and closed" << std::endl; + **/ + + // Checksum test + bool match = VP1MD5Sum::sumMatches(target,m_d->m_expectedMD5Sum); + if(!match) { + message("Checksum did not match"); + QFile::remove(target); + m_d->m_stage = 0; + m_d->startTimer(m_d->m_updateInterval); + return; + } + + QString finalTarget = tmpLocalFileDir()+m_d->m_evtToGet; + if(!QFile::rename(target,finalTarget)) { + message("ERROR: Could not move " + target + " to " + finalTarget); + QFile::remove(target); + QFile::remove(finalTarget); + } else { + cleanupAndCheckForEventListChanges(); + } + + m_d->m_stage = 0; + } + } + else + m_d->m_stage = 0; + + m_d->m_netreply->blockSignals(true); + m_d->m_netreply->deleteLater(); + m_d->m_netreply = 0; + + int interval = m_d->m_stage>0 ? 0 : m_d->m_updateInterval; + m_d->startTimer(interval); +} + +void VP1AvailEvtsHttps::error(QNetworkReply::NetworkError err) +{ + message("Error processing " + m_d->m_netreply->url().toString() + + "\n ===> Error code: " + QString::number((int)err) + + "\n Error decoding here: http://doc.trolltech.com/4.4/qnetworkreply.html#NetworkError-enum"); +} + +void VP1AvailEvtsHttps::sslErrors(const QList<QSslError>&) +{ + /** ---- For logging + std::cout << "VP1AvailEvtsHttps SSL errors" << std::endl; + for(int ii=0; ii<errlist.size(); ++ii) + std::cout << " SSL * " << (int)errlist.at(ii).error() + << ", " << errlist.at(ii).errorString().toStdString() << std::endl; + **/ + m_d->m_netreply->ignoreSslErrors(); +} + +void VP1AvailEvtsHttps::dataReadProgress(qint64 received, qint64) +{ + if(m_d->m_stage>0) { + if(received>m_d->m_bytesReceived) { + m_d->m_lastChangeTime = QDateTime::currentDateTime().toTime_t(); + m_d->m_bytesReceived = received; + } + } else { + m_d->m_lastChangeTime = QDateTime::currentDateTime().toTime_t(); + } +} + +void VP1AvailEvtsHttps::checkForStall() +{ + unsigned currentTime = QDateTime::currentDateTime().toTime_t(); + if (currentTime>m_d->m_lastChangeTime+10) { + // Abort current download and go to stage 0 + if(m_d->m_netreply) { + m_d->m_netreply->blockSignals(true); + delete m_d->m_netreply; + m_d->m_netreply=0; + m_d->m_stage = 0; + m_d->startTimer(m_d->m_updateInterval); + } + } +} diff --git a/graphics/VTI12/VTI12Gui/src/VP1AvailEvtsLocalDir.cxx b/graphics/VTI12/VTI12Gui/src/VP1AvailEvtsLocalDir.cxx new file mode 100644 index 000000000..f2233b707 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1AvailEvtsLocalDir.cxx @@ -0,0 +1,81 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class VP1AvailEvtsLocalDir // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: May 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12Gui/VP1AvailEvtsLocalDir.h" +#include "VP1LocalEvtRetriever.h" + +#include <QStringList> + +//____________________________________________________________________ +class VP1AvailEvtsLocalDir::Imp { +public: + Imp(const QString& sd) : sourcedir(sd), retriever(0) {} + QString sourcedir; + static unsigned ntmpdlcount; + QStringList availablesourcedirs; + VP1LocalEvtRetriever* retriever; +}; + +unsigned VP1AvailEvtsLocalDir::Imp::ntmpdlcount = 0; + +//____________________________________________________________________ +VP1AvailEvtsLocalDir::VP1AvailEvtsLocalDir(int timeCutForNew, + QString sourcedir, + QString tmpcopydir, + int maxLocalFilesToKeep, + QObject * parent ) + : VP1AvailEvents(timeCutForNew,tmpcopydir,maxLocalFilesToKeep,parent), + m_d(new Imp(sourcedir+(sourcedir.endsWith("/")?"":"/"))) +{ +} + + +//____________________________________________________________________ +void VP1AvailEvtsLocalDir::init() +{ + m_d->retriever = new VP1LocalEvtRetriever(this,m_d->sourcedir); // Memleak + m_d->retriever->start(); +} + +//____________________________________________________________________ +VP1AvailEvtsLocalDir::~VP1AvailEvtsLocalDir() +{ + delete m_d; +} + +//____________________________________________________________________ +QString VP1AvailEvtsLocalDir::currentSourceDir() const +{ + return m_d->sourcedir; +} + +//____________________________________________________________________ +void VP1AvailEvtsLocalDir::setSourceDir(QString dir) +{ + m_d->retriever->setSourceDir(dir); + m_d->sourcedir = dir; +} + +//____________________________________________________________________ +void VP1AvailEvtsLocalDir::setAvailableSourceDirectories(QStringList l) +{ + m_d->availablesourcedirs = l; +} + + +//____________________________________________________________________ +QStringList VP1AvailEvtsLocalDir::availableSourceDirectories() const +{ + return m_d->availablesourcedirs; +} diff --git a/graphics/VTI12/VTI12Gui/src/VP1ChannelManager.cxx b/graphics/VTI12/VTI12Gui/src/VP1ChannelManager.cxx new file mode 100644 index 000000000..d32212b72 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1ChannelManager.cxx @@ -0,0 +1,615 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////// +// // +// Implementation of class VP1ChannelManager // +// // +// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Initial version: April 2007 // +// // +///////////////////////////////////////////////////////////// + +/////////////////////////////////////// CHANNELS /////////////////////////////////////////////////////// +// +// NB: It is assumed that all channel methods are very fast to execute. Real work belongs in systems!! +// +// Constructor: Allocate systems, and call registerSystem on +// them. After the constructor the name(), information() and type() +// methods should work (and their returned values should not change +// throughout the channel lifetime. You may never delete a system yourself. +// +// Create: You can assume that all systems have had their create() +// method already called. Here you can perform any initialisation you +// need to, including allocating a controller if you need to and +// registering it with registerController. You may never delete a controller yourself. +// +// The next two methods, refresh and erase, will be called an +// undetermined amount of times by the framework (including zero), and +// always in the cycle: refresh-erase-refresh-erase-refresh-erase-...-refresh-erase +// +// Refresh: You can assume that all systems have just had their refresh +// methods called, and thus have just processed data from a new event. Any gui +// updates you need to perform (e.g. changing the zoom level of a viewer to +// encompass all the items put into it by the systems) you can do here. +// +// Erase: You can assume that all systems have just had their erase methods called. +// The goal here is to stop the channel from displaying any +// event data, since we are preparing to leave an event and load +// a new one. If we did not blank out the presented data here, +// we might end up in a situation where different channels +// displays data from different events at the same time! (For +// accumulators this is of course a little different). +// +// Uncreate: You can assume that all systems have had their uncreate() +// method already called. Here you can perform any release of resources you +// need to (remember to no delete systems or the controller!). +// Dont emit any signals during this method (or during the destructor). +// +// Destructor: There really should not be anything left to do here... +// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include "VTI12Gui/VP1ChannelManager.h" +#include "VTI12Gui/VP1ExecutionScheduler.h" +#include "VTI12Gui/VP1MainWindow.h" + +#include "VP1Base/IVP1ChannelWidgetFactory.h" +#include "VP1Base/IVP1ChannelWidget.h" + +#include <QPluginLoader> +#include <QFileInfo> +#include <QMap> +#include <QScrollArea> + +#include <map> +#include <set> +#include <cassert> + +//QT_NO_PLUGIN_CHECK + +class VP1ChannelManager::Imp { + +public: + + VP1ChannelManager*channelmanager; + VP1ExecutionScheduler*scheduler; + VP1MainWindow*mainwindow; + + //Actual created channels: + std::map<QString,std::set<IVP1ChannelWidget*> > basename_2_channels; + std::map<QString,IVP1ChannelWidget*> uniquename_2_channel; + + //plugin info: + std::map<QString,std::pair<QStringList,IVP1ChannelWidgetFactory *> > pluginfile_2_basenamesAndFactory; + std::map<QString,QString> basename_2_pluginfile; + std::map<QString,QPluginLoader*> pluginfile_2_pluginloader; + + QList<QObject*> additionalOwnedObjects;//For deletion in destructor + void emit_basename_availableChannelListChanged(); + void emit_basename_availableUnusedChannelListChanged(); + + std::map<IVP1ChannelWidget*,QWidget*> channel_2_controller; + QMap<QString,QString> basename2iconlocation; + + //These next four should always be used to properly new, create, + //uncreate and delete channels and their systems. The channel is + //responsible for new'ing systems in its constructor, but + //create/uncreate/delete of systems are handled by the + //channelmanager. Controllers are also deleted by the channelmanager. + IVP1ChannelWidget * constructChannel( QString channelbasename, QString& err, bool init = true ); + + QString channelTypeToIconLocation(const IVP1ChannelWidget::Type& type) const; +}; + +//___________________________________________________________________________________ +VP1ChannelManager::VP1ChannelManager(VP1ExecutionScheduler*sched,VP1MainWindow*mw) : m_d(new Imp) +{ + m_d->channelmanager=this; + m_d->scheduler=sched; + m_d->mainwindow=mw; +} + +//___________________________________________________________________________________ +VP1ChannelManager::~VP1ChannelManager() +{ + while(!m_d->uniquename_2_channel.empty()) + deleteChannel(m_d->uniquename_2_channel.begin()->first); + + std::map<QString,QPluginLoader*>::const_iterator it, itE = m_d->pluginfile_2_pluginloader.end(); + for(it=m_d->pluginfile_2_pluginloader.begin();it!=itE;++it) + delete it->second; + + foreach (QObject* o,m_d->additionalOwnedObjects) + delete o; + delete m_d; +} + +//___________________________________________________________________________________ +//Fixme: Return error string in case of problems. +bool VP1ChannelManager::deleteChannel(QString channeluniquename) { + + //Find info: + assert(m_d->uniquename_2_channel.find(channeluniquename)!=m_d->uniquename_2_channel.end()); + IVP1ChannelWidget * cw = m_d->uniquename_2_channel[channeluniquename]; + QString bn = cw->name(); + assert(m_d->basename_2_channels.find(bn)!=m_d->basename_2_channels.end()); + + //Remove channelwidget from maps, and delete it. + assert(m_d->basename_2_channels[bn].find(cw)!=m_d->basename_2_channels[bn].end()); + m_d->basename_2_channels[bn].erase(m_d->basename_2_channels[bn].find(cw)); + m_d->uniquename_2_channel.erase(m_d->uniquename_2_channel.find(channeluniquename)); + + m_d->scheduler->uncreateAndDelete(cw);//The actual uncreate()+delete might be postponed if a system is + //presently refreshing. But for all bookkeeping purposes it already + //happened! + + channelUncreated(cw); + + //Remove controller from maps - and ensure the widget gets deleted + //in any case (it is a scrollarea, not the controller known by the + //actual channelwidget): + assert(m_d->channel_2_controller.find(cw)!=m_d->channel_2_controller.end()); + m_d->channel_2_controller[cw]->deleteLater(); + m_d->channel_2_controller.erase(m_d->channel_2_controller.find(cw)); + assert(m_d->channel_2_controller.find(cw)==m_d->channel_2_controller.end()); + + //Finally, assign new cloneids to any remaining channels of the same basename: + //First wipe old info in uniquename_2_channel. + std::set<IVP1ChannelWidget*>::iterator it = m_d->basename_2_channels[bn].begin(); + std::set<IVP1ChannelWidget*>::iterator itE = m_d->basename_2_channels[bn].end(); + for (;it!=itE;++it) { + assert(m_d->uniquename_2_channel.find((*it)->unique_name())!=m_d->uniquename_2_channel.end()); + m_d->uniquename_2_channel.erase(m_d->uniquename_2_channel.find((*it)->unique_name())); + } + + it = m_d->basename_2_channels[bn].begin(); + unsigned id(0); + for (;it!=itE;++it) { + (*it)->setCloneID(id++); + (*it)->unique_name(); + assert(m_d->uniquename_2_channel.find((*it)->unique_name())==m_d->uniquename_2_channel.end()); + m_d->uniquename_2_channel[(*it)->unique_name()]=(*it); + } + + uniquename_channelListChanged(uniquenames()); + m_d->emit_basename_availableUnusedChannelListChanged(); + return true; +} + + +//___________________________________________________________________________________ +bool VP1ChannelManager::unloadPluginFile(QString filename) { + + VP1Msg::messageVerbose("VP1ChannelManager::unloadPluginFile()"); + + if (m_d->pluginfile_2_pluginloader.find(filename)==m_d->pluginfile_2_pluginloader.end()) + return false; + + assert(m_d->pluginfile_2_basenamesAndFactory.find(filename)!=m_d->pluginfile_2_basenamesAndFactory.end()); + assert(m_d->pluginfile_2_pluginloader.find(filename)!=m_d->pluginfile_2_pluginloader.end()); + + //Find basenames provided by this plugin, as well as factory and pluginloader: + QStringList bns = channelsInPluginFile(filename); + IVP1ChannelWidgetFactory * fact = m_d->pluginfile_2_basenamesAndFactory.find(filename)->second.second; + QPluginLoader* loader = m_d->pluginfile_2_pluginloader[filename]; + + //Abort if any active channels are affected by this plugin: + foreach (QString bn, bns) + if (nActive(bn)>0) + return false; + + //Delete factory: + delete fact; + + //Unload: + bool success = loader->unload(); + delete loader; + + //Update maps: + m_d->pluginfile_2_basenamesAndFactory.erase(m_d->pluginfile_2_basenamesAndFactory.find(filename)); + m_d->pluginfile_2_pluginloader.erase(m_d->pluginfile_2_pluginloader.find(filename)); + foreach (QString bn, bns) { + m_d->basename_2_channels.erase(m_d->basename_2_channels.find(bn)); + m_d->basename_2_pluginfile.erase(m_d->basename_2_pluginfile.find(bn)); + } + + //Emit signals regarding changes: + uniquename_channelListChanged(uniquenames()); + m_d->emit_basename_availableChannelListChanged(); + m_d->emit_basename_availableUnusedChannelListChanged(); + + //Return: + return success; +} + +//___________________________________________________________________________________ +QString VP1ChannelManager::loadPluginFile(QString filename) +{ + + VP1Msg::messageVerbose("VP1ChannelManager::loadPluginFile() - filename: " + filename); + + QString bn = QFileInfo(filename).fileName(); + + if (m_d->pluginfile_2_basenamesAndFactory.find(filename)!=m_d->pluginfile_2_basenamesAndFactory.end()) { + return "Error: Plugin already loaded."; + } else { + + + QFileInfo fi(filename); + if (!fi.exists()) + return "File does not exist"; + if (!fi.isReadable()) + return "File is not readable"; + + VP1Msg::messageVerbose("plugin path: " + fi.absoluteFilePath()); + VP1Msg::messageVerbose("app path: " + QCoreApplication::applicationDirPath()); + VP1Msg::messageVerbose("library path: " + QLibraryInfo::location(QLibraryInfo::PluginsPath)); + + QString pluginAbsPath = fi.absoluteFilePath(); + + QPluginLoader * loader = new QPluginLoader(pluginAbsPath);//Fixme: Ensure all loaders gets unloaded on shutdown (and thus deleted) + m_d->pluginfile_2_pluginloader[filename]=loader; + + bool loadOk = loader->load(); + + if (!loadOk) { + VP1Msg::message("ERROR! Failed to load plugin. Error message: "+loader->errorString()); + + VP1Msg::message("Trying to load the 'dbg' build..."); + + /* + * when running VP1 sometimes (especially from the devval release) the + * load of the plugin fails silently... + * After a long investigation, I found that the problem is in the mismatch + * between the compilation flag of the main Qt application + * and the flag of the plugin modules. + * For example the main application is compiled in 'dbg', while the plugins + * are compiled in 'opt' mode... + * We still understand why... + * In the meantime I implemented a workaround: the 'opt' flag is replaced + * by the 'dbg' flag when the plugin fails to load. + * + */ + // QString build = "x86_64-slc6-gcc47-opt"; + //QString buildB = "x86_64-slc6-gcc47-dbg"; + //pluginAbsPath.replace(build, buildB); + + pluginAbsPath.replace("opt", "dbg"); + + loader = new QPluginLoader(pluginAbsPath); + loadOk = loader->load(); + + if (loadOk) VP1Msg::message("Ok! 'dbg' build of the plugin successfully loaded!"); + else VP1Msg::message("ERROR!! Also the 'dbg' build failed to load!!"); + + } + + + QObject *plugin = loader->instance(); + + + if (!plugin) { + + bool error = loader->errorString().isNull(); + + + QString errStr = "ERROR!!"; + if (error) + errStr = QString("Did not find any compatible plugins in file"); + else + errStr = loader->errorString(); + + + return errStr; + } + + + IVP1ChannelWidgetFactory * fact = qobject_cast<IVP1ChannelWidgetFactory *>(plugin); + m_d->additionalOwnedObjects << plugin; + + + if (!fact) + return "Did not find any channel factory in plugin file"; + + + QStringList providedbasenames = fact->channelWidgetsProvided(); + + + if (providedbasenames.count()==0) + return "Found channel factory in plugin file, but no advertised channels!"; + + + m_d->pluginfile_2_basenamesAndFactory[filename] = std::pair<QStringList,IVP1ChannelWidgetFactory *>(providedbasenames,fact); + + + foreach (QString bn,providedbasenames) { + if (m_d->basename_2_pluginfile.find(bn)!=m_d->basename_2_pluginfile.end()) + return "Channels navp1 '"+bn+"' are already provided by plugin file " + +m_d->basename_2_pluginfile[bn]+" (ignoring other plugins in file '"+filename+"')"; + } + + + foreach (QString bn,providedbasenames) { + m_d->basename_2_pluginfile[bn] = filename; + m_d->basename_2_channels[bn] = std::set<IVP1ChannelWidget*>(); + } + + + m_d->emit_basename_availableChannelListChanged(); + m_d->emit_basename_availableUnusedChannelListChanged(); + + + //Fixme: check 20 chars. + } + + + m_d->mainwindow->addToMessageBox( "Successfully loaded "+bn, "color:#008b00" ); + QString out = "providing channels: "+channelsInPluginFile(filename).join(", "); + m_d->mainwindow->addToMessageBox( out, "color:#008b00" ); + + + return ""; +} + +//___________________________________________________________________________________ +QStringList VP1ChannelManager::channelsInPluginFile(QString filename) const { + if (m_d->pluginfile_2_basenamesAndFactory.find(filename)==m_d->pluginfile_2_basenamesAndFactory.end()) + return QStringList(); + return m_d->pluginfile_2_basenamesAndFactory[filename].first; +} + +//___________________________________________________________________________________ +IVP1ChannelWidget * VP1ChannelManager::Imp::constructChannel( QString channelbasename, QString& err, bool init ) { + if (basename_2_pluginfile.find(channelbasename)==basename_2_pluginfile.end()) { + err = "Did not find plugin providing channel named '"+channelbasename+"'"; + return 0; + } + QString plf = basename_2_pluginfile[channelbasename]; + //sanity: + assert(pluginfile_2_basenamesAndFactory.find(plf)!=pluginfile_2_basenamesAndFactory.end()&&"This should never happen!"); + assert(pluginfile_2_basenamesAndFactory[plf].first.contains(channelbasename)&&"This should never happen!"); + IVP1ChannelWidget * cw = pluginfile_2_basenamesAndFactory[plf].second->getChannelWidget(channelbasename); + if (!cw) { + err = "Plugin file '"+plf+"' did not provide channel navp1 '"+channelbasename+"' despite advertising this capability!"; + return 0; + } else { + err=""; + } + + if (channelbasename!=cw->name()) { + err = "Actual basename of channel widget constructed by factory is not the one requested: '"+cw->name() + +"' vs. '"+channelbasename+"'. This is most likely due to a mistake in the plugin!!"; + delete cw; + return 0; + } + + //Cache the icon associated with this channel for future use (and override if there is already a cache): + QString icontext = channelTypeToIconLocation(cw->type()); + basename2iconlocation[cw->name()]=icontext; + + if (init) + cw->init(); + + //Sanity: should not have controller registered: + assert(channel_2_controller.find(cw)==channel_2_controller.end()); + + return cw; +} + +//___________________________________________________________________________________ +IVP1ChannelWidget * VP1ChannelManager::getChannel( QString channelbasename, QString& err ) { + IVP1ChannelWidget * cw = m_d->constructChannel( channelbasename, err ); + if (!cw) + return 0; + cw->setUpdatesEnabled(false); + cw->setCloneID(nActive(channelbasename)); + assert(m_d->uniquename_2_channel.find(cw->unique_name())==m_d->uniquename_2_channel.end()); + m_d->uniquename_2_channel[cw->unique_name()]=cw; + m_d->basename_2_channels[channelbasename].insert(cw); + + assert(cw->state()==IVP1ChannelWidget::CONSTRUCTED); + m_d->scheduler->bringFromConstructedToReady(cw);//Fixme: should return bool + assert(cw->state()==IVP1ChannelWidget::READY); + + assert(m_d->channel_2_controller.find(cw)==m_d->channel_2_controller.end()); + QWidget * controller = cw->controllerWidget(); + QScrollArea * scrollarea = new QScrollArea; + // controller->setParent(scrollarea); + scrollarea->setObjectName("VP1ControllerScrollArea"); + scrollarea->setWidgetResizable(true); + scrollarea->setFrameShape(QFrame::NoFrame); + scrollarea->setFrameShadow(QFrame::Plain); + + + //scrollArea->setBackgroundRole(QPalette::Dark); + scrollarea->setWidget(controller); + m_d->channel_2_controller[cw] = scrollarea; + + uniquename_channelListChanged(uniquenames()); + m_d->emit_basename_availableUnusedChannelListChanged(); + newChannelCreated(cw); + cw->setUpdatesEnabled(true); + + return cw; +} + +//___________________________________________________________________________________ +QWidget* VP1ChannelManager::getController(IVP1ChannelWidget*cw) { + assert(m_d->channel_2_controller.find(cw)!=m_d->channel_2_controller.end()); + return m_d->channel_2_controller[cw]; +} + +//___________________________________________________________________________________ +unsigned VP1ChannelManager::nActive( QString channelbasename ) const { + if (m_d->basename_2_channels.find(channelbasename)==m_d->basename_2_channels.end()) + return 0; + return m_d->basename_2_channels[channelbasename].size(); +} + +//fixme: Always check uniqueness (and <20chars) of basenames! + +//___________________________________________________________________________________ +IVP1ChannelWidget* VP1ChannelManager::uniqueName2Channel(QString uniquename) const { + if (m_d->uniquename_2_channel.find(uniquename)==m_d->uniquename_2_channel.end()) + return 0; + return m_d->uniquename_2_channel[uniquename]; +} + +//___________________________________________________________________________________ +bool VP1ChannelManager::uniqueNameExists(QString uniquename) const { + return (m_d->uniquename_2_channel.find(uniquename)!=m_d->uniquename_2_channel.end()); +} + +//___________________________________________________________________________________ +bool VP1ChannelManager::baseNameExists(QString basename) const { + return (m_d->basename_2_pluginfile.find(basename)!=m_d->basename_2_pluginfile.end()); +} + +//___________________________________________________________________________________ +QStringList VP1ChannelManager::uniquenames() const { + QStringList l; + std::map<QString,IVP1ChannelWidget*>::iterator it = m_d->uniquename_2_channel.begin(); + std::map<QString,IVP1ChannelWidget*>::iterator itE = m_d->uniquename_2_channel.end(); + + for (;it!=itE;++it) + l << it->first; + + return l; +} + + +//___________________________________________________________________________________ +void VP1ChannelManager::Imp::emit_basename_availableChannelListChanged() { + QStringList l; + + std::map<QString,QString>::const_iterator it = basename_2_pluginfile.begin(); + std::map<QString,QString>::const_iterator itE = basename_2_pluginfile.end(); + for (;it!=itE;++it) { + l << it->first; + } + channelmanager->availableChannelListChanged(l); + +} + +//___________________________________________________________________________________ +QStringList VP1ChannelManager::availableChannelList() { + QStringList l; + std::map<QString,QString>::const_iterator it = m_d->basename_2_pluginfile.begin(); + std::map<QString,QString>::const_iterator itE = m_d->basename_2_pluginfile.end(); + for (;it!=itE;++it) { + l << it->first; + } + return l; +} + +//___________________________________________________________________________________ +void VP1ChannelManager::Imp::emit_basename_availableUnusedChannelListChanged() { + QStringList l; + + std::map<QString,QString>::const_iterator it = basename_2_pluginfile.begin(); + std::map<QString,QString>::const_iterator itE = basename_2_pluginfile.end(); + for (;it!=itE;++it) { + if (channelmanager->nActive(it->first)==0) + l << it->first; + } + + channelmanager->availableUnusedChannelListChanged(l); +} + +//___________________________________________________________________________________ +QStringList VP1ChannelManager::serializePluginInfo() const { + std::map<QString,std::pair<QStringList,IVP1ChannelWidgetFactory *> >::const_iterator + it, itE = m_d->pluginfile_2_basenamesAndFactory.end(); + + QStringList l; + for( it = m_d->pluginfile_2_basenamesAndFactory.begin(); it!=itE; ++it ) { + l<<QFileInfo(it->first).fileName(); + } + return l; +} + +//___________________________________________________________________________________ +QStringList VP1ChannelManager::currentPluginFiles() const { + std::map<QString,QPluginLoader*>::const_iterator it = m_d->pluginfile_2_pluginloader.begin(); + std::map<QString,QPluginLoader*>::const_iterator itE = m_d->pluginfile_2_pluginloader.end(); + QStringList l; + for(;it!=itE;++it) { + l<<it->first; + } + return l; +} + +//___________________________________________________________________________________ +QStringList VP1ChannelManager::basename2UniqueNames(QString basename) const { + + if (m_d->basename_2_channels.find(basename)==m_d->basename_2_channels.end()) + return QStringList(); + + std::set<IVP1ChannelWidget*>::const_iterator it = m_d->basename_2_channels[basename].begin(); + std::set<IVP1ChannelWidget*>::const_iterator itE = m_d->basename_2_channels[basename].end(); + + QStringList l; + for (;it!=itE;++it) { + l << (*it)->unique_name(); + } + return l; +} + +//___________________________________________________________________________________ +bool VP1ChannelManager::channelWithBasenameIsLoaded(QString basename) const { + if (m_d->basename_2_channels.find(basename)==m_d->basename_2_channels.end()) + return false; + return !m_d->basename_2_channels[basename].empty(); +} + + +//___________________________________________________________________________________ +QString VP1ChannelManager::Imp::channelTypeToIconLocation(const IVP1ChannelWidget::Type& type) const +{ + if (type==IVP1ChannelWidget::THREEDIMENSIONAL) return ":/vp1/icons/icons/3d_32x32.png"; + if (type==IVP1ChannelWidget::TWODIMENSIONAL) return ":/vp1/icons/icons/kivio_32x32.png";//Fixme: Better icon. + if (type==IVP1ChannelWidget::NUMBERS) return ":/vp1/icons/icons/kcalc_32x32.png"; + if (type==IVP1ChannelWidget::HISTOGRAM) return ":/vp1/icons/icons/kchart_32x32.png"; + if (type==IVP1ChannelWidget::UNKNOWN) return ":/vp1/icons/icons/help_32x32.png"; + return ""; +} + +//___________________________________________________________________________________ +bool VP1ChannelManager::hasRefreshingSystem(const QString& uniquename) const +{ + IVP1ChannelWidget*cw = uniqueName2Channel(uniquename); + return cw ? cw->hasRefreshingSystem() : false; +} + +//___________________________________________________________________________________ +QString VP1ChannelManager::getIconLocation(const QString& channelname, const bool& isbasename) +{ + if (!isbasename) { + IVP1ChannelWidget* cw = uniqueName2Channel(channelname); + if (!cw) + return ""; + return m_d->channelTypeToIconLocation(cw->type()); + } + + if (m_d->basename2iconlocation.contains(channelname)) + return m_d->basename2iconlocation[channelname]; + + //We have to briefly construct a channel in order to get its type. + //The following create and destruct maneouver is to get a proper + //cache of the icontext associated with the channel: + QString err; + IVP1ChannelWidget * cw = m_d->constructChannel( channelname, err, false /*don't init()*/ ); + if (!cw) + return ""; + cw->deleteControllers(); + delete cw; + assert(m_d->channel_2_controller.find(cw)==m_d->channel_2_controller.end()); + + //Try again; + if (m_d->basename2iconlocation.contains(channelname)) + return m_d->basename2iconlocation[channelname]; + return ""; +} diff --git a/graphics/VTI12/VTI12Gui/src/VP1DockWidget.cxx b/graphics/VTI12/VTI12Gui/src/VP1DockWidget.cxx new file mode 100644 index 000000000..3905767ac --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1DockWidget.cxx @@ -0,0 +1,319 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////// +// // +// Implementation of class VP1DockWidget // +// // +// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Initial version: April 2007 // +// // +///////////////////////////////////////////////////////////// + +#include "VTI12Gui/VP1DockWidget.h" +#include "VTI12Gui/VP1TabManager.h" +#include "VP1Base/IVP1ChannelWidget.h" + +#include <QFrame> +#include <QEvent> +#include <QSet> +#include <QVBoxLayout> +#include <QContextMenuEvent> +#include <QMenu> + +#include <cassert> +#include <iostream> + +//____________________________________________________________________ +class VP1DockWidget::Imp { +public: + class FilterItem; + Imp(VP1DockWidget*_dw,IVP1ChannelWidget * cw,VP1TabManager * tabmanager); + FilterItem* filteritem; + VP1DockWidget * dw; + QFrame * frame; + QVBoxLayout * vboxLayout; + IVP1ChannelWidget * channelwidget; + int unselectedmargin; + QString selectedstylesheet; + bool selected; + QString title_refreshpart; + VP1TabManager* tabmanager; +}; + +//____________________________________________________________________ +class VP1DockWidget::Imp::FilterItem : public QObject { +public: + FilterItem(VP1DockWidget* dw) : QObject(dw),m_dw(dw) {} + VP1DockWidget* m_dw; + + void init() { + installEventFilterRecursively(m_dw); + m_activationevents.insert(QEvent::ContextMenu); + //m_activationevents.insert(QEvent::EnterEditFocus); --> Does not compile. + m_activationevents.insert(QEvent::FocusIn); + m_activationevents.insert(QEvent::KeyPress); + m_activationevents.insert(QEvent::MouseButtonDblClick); + m_activationevents.insert(QEvent::MouseButtonPress); + m_activationevents.insert(QEvent::TabletPress); + m_activationevents.insert(QEvent::Wheel); + } + +protected: + QSet<QEvent::Type> m_activationevents; + + bool eventFilter ( QObject * watched, QEvent * event ) { + + if (event->type()==QEvent::ChildAdded) { + //Maybe the user added a widget, so update the event filters (todo: test that it works): + foreach(QObject* c, watched->children()) { + installEventFilterRecursively(c,true); + installEventFilterRecursively(c); + } + return false; + } + + if ( !m_dw->m_d->selected && m_activationevents.contains(event->type()) ) { + m_dw->setSelected(); + m_dw->wasSelected(m_dw); + } + // if ( watched==m_dw && event->type() == QEvent::Enter ) + // m_dw->channelWidget()->setFocus(Qt::OtherFocusReason); + + return false; + } + + void installEventFilterRecursively(QObject * child, const bool& remove=false ) { + //NB: we install it on all QObjects in the tree rather than just + //the QWidgets, since we need to watch for ChildAdded events. + if (child==this) + return; + if (!child){ + std::cerr<<"installEventFilterRecursively: Child is NULL. Aborting."<<std::endl; + return; + } + if (remove) + child->removeEventFilter(this); + else + child->installEventFilter(this); + foreach(QObject* c, child->children()) + installEventFilterRecursively(c,remove); + } +}; + +//____________________________________________________________________ +VP1DockWidget::Imp::Imp(VP1DockWidget* the_dw,IVP1ChannelWidget * cw,VP1TabManager * the_tabmanager) + : filteritem(new FilterItem(the_dw)), dw(the_dw), frame(0), vboxLayout(0),channelwidget(cw), + unselectedmargin(0),selected(false),tabmanager(the_tabmanager) {} + +//____________________________________________________________________ +VP1DockWidget::~VP1DockWidget() +{ + delete m_d->filteritem; + delete m_d; m_d=0; +} + +//______________________________________________________________________ +QString VP1DockWidget::highlightStyle() +{ + return "background-color: rgba(0, 0, 255, 12%)"; +} + +//______________________________________________________________________ +VP1DockWidget::VP1DockWidget ( IVP1ChannelWidget * cw, VP1TabManager* tm ) + : QDockWidget ( cw->unique_name(), 0 ), m_d(new Imp(this,cw,tm)) +{ + + setObjectName("VP1DockWidget:"+cw->name());//For storing/saving the layout of the dock widgets within the dock area. + + setFocusProxy(cw); + + setAllowedAreas(Qt::TopDockWidgetArea); + setFeatures(VP1DockWidget::DockWidgetMovable | VP1DockWidget::DockWidgetFloatable); + + m_d->selectedstylesheet="QFrame#VP1DockWidgetFrame { "+highlightStyle()+" } "; + + //Add frame, which will light up on selection: + m_d->frame = new QFrame(this); + m_d->frame->setObjectName("VP1DockWidgetFrame"); + cw->setObjectName("IVP1ChannelWidget:"+cw->name()); + ensureCWHasParent();//setup the cw in the frame + + //Figure out what margin our drawn frame imposes: + setSelected(); + int marg_left, marg_top, marg_right, marg_bottom; + m_d->frame->getContentsMargins ( &marg_left, &marg_top, &marg_right, &marg_bottom ); + Q_ASSERT(marg_left==marg_top&&marg_left==marg_right&&marg_left==marg_bottom&&"Qt changed its margin behaviour for QFrame!!"); + m_d->unselectedmargin=marg_left; + + //Channel starts unselected: + setUnselected(); + + connect(cw,SIGNAL(uniqueNameChanged(QString)),this,SLOT(updateTitle())); + connect(cw,SIGNAL(systemRefreshInfoChanged(QString,int,int)),this,SLOT(systemRefreshInfoChanged(QString,int,int))); + + //Setup a watch for selections: + m_d->filteritem->init(); + +} + +//______________________________________________________________________ +void VP1DockWidget::ensureCWHasNoParent() +{ + if (!channelWidget()||!channelWidget()->parent()) + return; + channelWidget()->setParent(0); + setWidget(0); + if (m_d->frame->layout()&&m_d->frame->layout()->indexOf(m_d->channelwidget)>=0) { + assert(m_d->vboxLayout); + m_d->vboxLayout->removeWidget(m_d->channelwidget); + } +} + +//______________________________________________________________________ +void VP1DockWidget::ensureCWHasParent() +{ + if (!channelWidget()||channelWidget()->parent()) + return; + if (!m_d->frame->layout()) { + assert(!m_d->vboxLayout); + m_d->vboxLayout = new QVBoxLayout(0); + m_d->frame->setLayout(m_d->vboxLayout); + m_d->vboxLayout->setObjectName("vp1dock-frame-layout"); + m_d->vboxLayout->setSpacing(0); + } + if (m_d->frame->layout()->indexOf(m_d->channelwidget)<0) + m_d->frame->layout()->addWidget(m_d->channelwidget); + channelWidget()->setParent(m_d->frame); + setWidget(m_d->frame); +} + +//______________________________________________________________________ +void VP1DockWidget::systemRefreshInfoChanged(QString sysrefreshing, int nsysOn, int nsysOnRefreshed) +{ + assert(nsysOnRefreshed<=nsysOn); + if (nsysOn==nsysOnRefreshed) { + // assert(sysrefreshing.isEmpty()); + m_d->title_refreshpart.clear(); + updateTitle(); + return; + } + assert(nsysOnRefreshed<nsysOn); + if (sysrefreshing.isEmpty()) { + m_d->title_refreshpart = " [Refreshed "+QString::number(nsysOnRefreshed)+"/"+QString::number(nsysOn)+"]"; + } else { + m_d->title_refreshpart = " [Refreshing "+QString::number(nsysOnRefreshed+1)+"/"+QString::number(nsysOn)+": "+sysrefreshing+" ]"; + } + updateTitle(); +} + +//______________________________________________________________________ +void VP1DockWidget::updateTitle() +{ + if (m_d->selected) + setWindowTitle(">>> "+m_d->channelwidget->unique_name()+m_d->title_refreshpart+" <<<"); + else + setWindowTitle(m_d->channelwidget->unique_name()+m_d->title_refreshpart); +} + +//______________________________________________________________________ +void VP1DockWidget::setSelected() +{ + if (m_d->selected) + return; + m_d->selected=true; + m_d->frame->setStyleSheet(m_d->selectedstylesheet); + assert(m_d->vboxLayout); + m_d->vboxLayout->setMargin(0); + m_d->frame->setFrameShape(QFrame::StyledPanel); + updateTitle(); +} + +//______________________________________________________________________ +void VP1DockWidget::setUnselected() +{ + if (!m_d->selected) + return; + m_d->selected=false; + m_d->frame->setStyleSheet(""); + assert(m_d->vboxLayout); + m_d->vboxLayout->setMargin(m_d->unselectedmargin); + m_d->frame->setFrameShape(QFrame::NoFrame); + updateTitle(); +} + +//______________________________________________________________________ +IVP1ChannelWidget * VP1DockWidget::channelWidget() const +{ + return m_d->channelwidget; +} + +//______________________________________________________________________ +bool VP1DockWidget::isSelected() const +{ + return m_d->selected; +} + +//______________________________________________________________________ +void VP1DockWidget::contextMenuEvent ( QContextMenuEvent * event ) +{ + //Inside the frame, we use the normal behaviour: + if (m_d->frame->geometry().contains(event->pos())) { + QDockWidget::contextMenuEvent ( event ); + return; + } + //Outside we show our contextmenu: + + //Construct menu: + QMenu menu(this); +// menu.addAction("Channel: "+m_d->channelwidget->unique_name())->setEnabled(false); +// menu.addSeparator(); + + QAction* pFullScreenAction = menu.addAction("Show &full Screen"); + menu.addSeparator(); + QAction* pRemoveAction = menu.addAction("&Remove channel"); + menu.addSeparator (); + QAction* pMoveChannelAction = menu.addAction("&Move to tab"); + + QStringList tablist = m_d->tabmanager->tabList(); + QMenu menu_movechan(this); + if (tablist.count()==1) { + menu_movechan.addAction("No other tabs available")->setEnabled(false); + } else { + QString thistab = m_d->tabmanager->channelToTab(m_d->channelwidget); + foreach (QString tab, tablist) { + if (tab!=thistab) + menu_movechan.addAction(tab)->setData("MOVECHAN"); + } + } + pMoveChannelAction->setMenu(&menu_movechan); + + //Execute + QAction * selAct = menu.exec(event->globalPos()); + //Act on selection: + if (!selAct) + return; + if (selAct==pFullScreenAction) { + m_d->tabmanager->showChannelFullScreen(m_d->channelwidget); + return; + } + if (selAct==pRemoveAction) { + m_d->tabmanager->removeChannelAfterQueueEmpties(m_d->channelwidget->unique_name()); + return; + } + if (selAct->data()=="MOVECHAN") { + m_d->tabmanager->moveChannelToTab(m_d->channelwidget->unique_name(),selAct->text()); + return; + } + std::cout<<"ERROR in VP1DockWidget::contextMenuEvent!!!!!"<<std::endl; + +} + +//______________________________________________________________________ +void VP1DockWidget::resizeEvent ( QResizeEvent * event ) +{ + m_d->channelwidget->dockResized(); + QDockWidget::resizeEvent(event); +} diff --git a/graphics/VTI12/VTI12Gui/src/VP1EventDisplayEditor.cxx b/graphics/VTI12/VTI12Gui/src/VP1EventDisplayEditor.cxx new file mode 100644 index 000000000..388d087b9 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1EventDisplayEditor.cxx @@ -0,0 +1,730 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1EventDisplayEditor // +// // +// Description: Event display editor. // +// // +// Author: Riccardo-Maria BIANCHI (rbianchi@cern.ch) // +// Initial version: September 2013 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12Gui/VP1EventDisplayEditor.h" +#include "ui_vp1eventdisplayeditor.h" + +#include "VP1Base/VP1ExaminerViewer.h" +#include "VP1Base/VP1QtInventorUtils.h" +#include "VP1Base/VP1Serialise.h" +#include "VP1Base/VP1Deserialise.h" +#include "VTI12Gui/VP1MainWindow.h" + +#include <QRectF> +#include <QShortcut> +#include <QCloseEvent> +#include <QFileDialog> + +#include <iostream> + + +//____________________________________________________________________ +class VP1EventDisplayEditor::Imp { + +public: + + VP1EventDisplayEditor * theclass; + Ui::VP1EventDisplayEditorForm ui; + + // VP1ExaminerViewer* viewer; + + // QGraphicsScene* scene; + + // QWidget * frameHolderWidget; + +}; + + +////____________________________________________________________________ +//QByteArray VP1EventDisplayEditor::state() const +//{ +// VP1Serialise s(0/*version*/); +// QList<QByteArray> frameStates; +// foreach(VP1CustomTourFrameWidget*frame,d->frames) { +// frameStates << frame->serialise(); +// s.ignoreWidget(frame); +// } +// s.save(frameStates); +// s.save(d->ui.doubleSpinBox_theta); +// s.save(d->ui.doubleSpinBox_radius); +// s.save(d->ui.groupBox_utilityZoom); +// s.warnUnsaved(this); +// return s.result(); +//} + +////____________________________________________________________________ +//void VP1EventDisplayEditor::setState(QByteArray ba) +//{ +// foreach(VP1CustomTourFrameWidget*frame,d->frames) +// frame->deleteLater(); +// d->frames.clear(); +// +// VP1Deserialise s(ba); +// if (s.version()!=0) +// return; +// QList<QByteArray> frameStates = s.restore<QList<QByteArray> >(); +// s.restore(d->ui.doubleSpinBox_theta); +// s.restore(d->ui.doubleSpinBox_radius); +// s.restore(d->ui.groupBox_utilityZoom); +// s.warnUnrestored(this); +// +// d->ui.widget_utilityZoomContents->setVisible(d->ui.groupBox_utilityZoom->isChecked()); +// +// foreach(QByteArray ba2, frameStates) +// d->addFrame(new VP1CustomTourFrameWidget(ba2)); +// d->updateFrameListVisuals(); +// enabledFrameListChanged(); +//} + + +/* + * My first, old version + */ +////____________________________________________________________________ +////VP1EventDisplayEditor::VP1EventDisplayEditor(VP1ExaminerViewer* viewer) +//VP1EventDisplayEditor::VP1EventDisplayEditor() +//: QWidget(0,Qt::WindowStaysOnTopHint), d(new Imp) +//{ +// d->theclass = this; +// d->ui.setupUi(this); +// +// scene = new QGraphicsScene(); // the size of the scene is by default infinite. But we will limit the view, here below +// scene->setSceneRect(QRectF(0.0, 0.0, 4000., 2641.)); +// +// scene_preview = new QGraphicsScene(); +// +// +// d->ui.graphicsView->setScene(scene); +// d->ui.graphicsView->setSceneRect(0, 0, 4000, 2641); // the size of a final ATLAS event display +// d->ui.graphicsView->setMaximumSize(1000, 660); // the size of the view window on the screen +// +// d->ui.graphicsView_preview->setScene(scene_preview); +// d->ui.graphicsView_preview->setSceneRect(0, 0, 333, 220); // the size of the preview scene +// d->ui.graphicsView_preview->setMaximumSize(333, 220); // the size of the preview window +// +// // set the default bkg color: black +// setBackgroundColor(); +// +// setWindowIcon(QIcon(QString(":/vp1/icons/icons/3d_32x32.png"))); +// +// connect(d->ui.pushButton_addText,SIGNAL(clicked()), this,SLOT(addTextLabel())); +// connect(d->ui.pushButton_removeObj,SIGNAL(clicked()), this,SLOT(removeObject())); +// connect(d->ui.pushButton_addLogo,SIGNAL(clicked()), this,SLOT(addLogo())); +// +// connect(d->ui.radioButton_black,SIGNAL(clicked()), this,SLOT(setBackgroundColor())); +// connect(d->ui.radioButton_white,SIGNAL(clicked()), this,SLOT(setBackgroundColor())); +// connect(d->ui.radioButton_transparent,SIGNAL(clicked()), this,SLOT(setBackgroundColor())); +// +// connect(scene,SIGNAL(changed(const QList<QRectF>&)), this,SLOT(updatePreview(const QList<QRectF>&))); +// +//} + + +/* + * new version + */ +//____________________________________________________________________ +VP1EventDisplayEditor::VP1EventDisplayEditor(VP1MainWindow* mainWindow, QList<unsigned long long> listRunEventNumberTimestamp) +//: QWidget(0,Qt::WindowStaysOnTopHint), d(new Imp) +: QWidget(0), m_d(new Imp) +{ + m_mainWindow = mainWindow; + + m_runNumber = listRunEventNumberTimestamp[0]; + m_eventNumber = listRunEventNumberTimestamp[1]; + m_eventTimestamp = listRunEventNumberTimestamp[2]; + + + m_d->theclass = this; + m_d->ui.setupUi(this); + + /* initialize the scene + * + * this is the scene that will be rendered and saved to the file. + * By default the scene dimension is 4000x2641 pixels. + * + */ + m_scene = new QGraphicsScene(); + m_scene->setSceneRect(QRectF(0.0, 0.0, 4000., 2641.)); + + + VP1EventDisplaySceneView *view = new VP1EventDisplaySceneView("Full-size view"); + view->view()->setScene(m_scene); + + m_preview = new VP1EventDisplaySceneView("Preview", true); + m_preview->view()->setScene(m_scene); + + // the right splitter, containing the list of objects in the scene and the preview + QSplitter *previewSplitter = new QSplitter; + previewSplitter->setOrientation(Qt::Vertical); + + // the center splitter, containing the main view and the preview splitter + QSplitter *viewSplitter = new QSplitter; + viewSplitter->setOrientation(Qt::Horizontal); + + // the center splitter, containing the main view and the preview splitter + QSplitter *toolsSplitter = new QSplitter; + toolsSplitter->setOrientation(Qt::Vertical); + + // the main splitter, containing all views + QSplitter *mainSplitter = new QSplitter; + mainSplitter->setOrientation(Qt::Horizontal); + + + previewSplitter->addWidget(m_d->ui.groupBox_objectList); + previewSplitter->addWidget(m_preview); + previewSplitter->addWidget(m_d->ui.groupBox_actions); + + + QWidget *containerPreview = new QWidget; + QVBoxLayout *containerPreview_layout = new QVBoxLayout; + + containerPreview_layout->addWidget(previewSplitter); + containerPreview->setLayout(containerPreview_layout); + + viewSplitter->addWidget(view); + viewSplitter->addWidget(containerPreview); + + QWidget *containerAllViews = new QWidget; + QHBoxLayout *containerAllViews_layout = new QHBoxLayout; + containerAllViews_layout->addWidget(viewSplitter); + containerAllViews->setLayout(containerAllViews_layout); + + + toolsSplitter->addWidget(m_d->ui.groupBox_getTab); + toolsSplitter->addWidget(m_d->ui.groupBox_bkg); + toolsSplitter->addWidget(m_d->ui.groupBox_logo); + toolsSplitter->addWidget(m_d->ui.groupBox_labels); + + QWidget *containerTools = new QWidget; + QVBoxLayout *containerTools_layout = new QVBoxLayout; + containerTools_layout->addWidget(toolsSplitter); + containerTools_layout->addStretch(1); + containerTools->setLayout(containerTools_layout); + + + // mainSplitter->addWidget(containerTools); + mainSplitter->addWidget(containerAllViews); + + QGridLayout* grid = static_cast<QGridLayout*>(this->layout()); + grid->addWidget(containerTools); + grid->addWidget(mainSplitter); + + + + /* + * setting the size of the preview window + */ + //m_preview->view()->setFixedSize(450,302); + /* + * this triggers a better fitInView() but not enough for our purpose. + * See: http://stackoverflow.com/a/17085612 + */ + //m_preview->show(); + + /* + * setting the size of the viewport + * + * Details: + * The QGraphicsView is not the widget that actually contains the scene, + * because the QGraphicsView also manages the scrollbars. + * The scene is drawn in the viewport widget, + * which is a little smaller than the QGraphicsView. + * (http://qt-project.org/forums/viewthread/17504) + * + * Update: useful, but it's useless here, because we want to use fitInView() + * from the view, and that does not match with the viewport size. + */ + // m_preview->view()->viewport()->setFixedSize(400,265); + + + QSize size = m_preview->view()->maximumViewportSize(); + VP1Msg::message("scene rect: " + QString::number(m_scene->sceneRect().width()) + " - " + QString::number(m_scene->sceneRect().height()) ); + VP1Msg::message("max preview size: " + QString::number(size.width()) + " - " + QString::number(size.height()) ); + + m_preview->view()->ensureVisible ( m_scene->sceneRect(), 0, 0 ); + m_preview->view()->fitInView( m_scene->sceneRect(), Qt::KeepAspectRatio); + + // add a frame to preview to define the the rendering area + m_preview->addRenderingFrame(); + + // set the default m_scene bkg color: black + this->setBackgroundColor(); // the "black" checkbox is checked by default in the GUI + + setWindowIcon(QIcon(QString(":/vp1/icons/icons/3d_32x32.png"))); + + connect(m_d->ui.pushButton_get,SIGNAL(clicked()), this,SLOT(getTabSnapshot())); + +// connect(m_d->ui.pushButton_eventDetailsLabel,SIGNAL(clicked()), this,SLOT(getEventDetailsLabel())); + + + connect(m_d->ui.radioButton_eventDetails,SIGNAL(toggled(bool)), this,SLOT(enableCustomTextField(bool))); + // connect(m_d->ui.radioButton_customText,SIGNAL(toggled()), this,SLOT(showCustomTextField())); + + connect(m_d->ui.pushButton_addText,SIGNAL(clicked()), this,SLOT(setTextLabel())); + connect(m_d->ui.pushButton_removeObj,SIGNAL(clicked()), this,SLOT(removeObject())); + connect(m_d->ui.pushButton_addLogo,SIGNAL(clicked()), this,SLOT(addLogo())); + + connect(m_d->ui.pushButton_save,SIGNAL(clicked()), this,SLOT(savePicture())); + connect(m_d->ui.pushButton_print,SIGNAL(clicked()), this,SLOT(printPicture())); + + + connect(m_d->ui.radioButton_black,SIGNAL(clicked()), this,SLOT(setBackgroundColor())); + connect(m_d->ui.radioButton_white,SIGNAL(clicked()), this,SLOT(setBackgroundColor())); + connect(m_d->ui.radioButton_transparent,SIGNAL(clicked()), this,SLOT(setBackgroundColor())); + + this->setWindowTitle(tr("ATLAS VP1 Event Display Editor")); + + this->getEventDetailsLabel(); + + +} + +/* + * Qt example + */ +//VP1EventDisplayEditor::VP1EventDisplayEditor() +////: QWidget(0,Qt::WindowStaysOnTopHint), m_d(new Imp) +//: QWidget(0), m_d(new Imp) +//{ +// m_d->theclass = this; +// m_d->ui.setupUi(this); +// +// m_scene = new QGraphicsScene(); +// +// h1Splitter = new QSplitter; +// h2Splitter = new QSplitter; +// +// QSplitter *vSplitter = new QSplitter; +// vSplitter->setOrientation(Qt::Vertical); +// vSplitter->addWidget(h1Splitter); +// vSplitter->addWidget(h2Splitter); +// +// VP1EventDisplaySceneView *view = new VP1EventDisplaySceneView("Top left view"); +// view->view()->setScene(m_scene); +// h1Splitter->addWidget(view); +// +// view = new VP1EventDisplaySceneView("Top right view"); +// view->view()->setScene(m_scene); +// h1Splitter->addWidget(view); +// +// view = new VP1EventDisplaySceneView("Bottom left view"); +// view->view()->setScene(m_scene); +// h2Splitter->addWidget(view); +// +// view = new VP1EventDisplaySceneView("Bottom right view"); +// view->view()->setScene(m_scene); +// h2Splitter->addWidget(view); +// +// QLayout *layout = this->layout(); +// layout->addWidget(vSplitter); +//// setLayout(layout); +// +// setWindowTitle(tr("Chip Demo")); +// +// +//} + + + +//____________________________________________________________________ +VP1EventDisplayEditor::~VP1EventDisplayEditor() +{ + // m_d->frameHolderWidget->deleteLater(); + // foreach(VP1CustomTourFrameWidget*frame,m_d->frames) + // frame->deleteLater(); + delete m_d; + delete m_scene; + // delete scene_preview; +} + + +//____________________________________________________________________ +void VP1EventDisplayEditor::enableCustomTextField(bool checked) +{ +// if (m_d->ui.radioButton_eventDetails->isChecked()) + if (checked) + m_d->ui.lineEdit_customLabelText->setEnabled(false); + else + m_d->ui.lineEdit_customLabelText->setEnabled(true); +} + + +//____________________________________________________________________ +QString VP1EventDisplayEditor::getEventDetailsLabel() +{ + + QString evtstr = "Run: "+QString::number(m_runNumber)+"\n" + + "Event: "+QString::number(m_eventNumber)+"\n" + + QString(m_eventTimestamp>0 ? QDateTime::fromTime_t(m_eventTimestamp).toString(Qt::ISODate).replace('T',' ')+ " CEST" : ""); + + //VP1Msg::messageVerbose(evtstr); + + return evtstr; +} + + +//____________________________________________________________________ +void VP1EventDisplayEditor::printPicture() +{ + m_preview->print(); +} + + +//____________________________________________________________________ +void VP1EventDisplayEditor::savePicture() +{ + VP1Msg::messageVerbose("VP1EventDisplayEditor::savePicture()"); + + // hide the rendering frame, cause we do not want it in the final picture + m_preview->hideRenderingFrame(); + + QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), + "event_display.png", + tr("Images (*.png *.jpg)")); + + QImage image(m_scene->sceneRect().size().toSize(), QImage::Format_ARGB32); + image.fill(Qt::transparent); + + QPainter painter(&image); + painter.setRenderHint(QPainter::Antialiasing); + + m_scene->render(&painter); + + image.save(fileName); + + // show the rendering frame again + m_preview->showRenderingFrame(); + +} + + + + + + +//____________________________________________________________________ +void VP1EventDisplayEditor::addPixmapList(QList<QPixmap>& list, QStringList& listNames) +{ + VP1Msg::messageVerbose("VP1EventDisplayEditor::addPixmapList()"); + + if (!list.isEmpty()) { + foreach (QPixmap img, list) { + // add and set it movableimage to the scene + QGraphicsPixmapItem* item = m_scene->addPixmap(img); + item->setFlags(QGraphicsItem::ItemIsMovable); + m_sceneItems << item; + } + } + + if (!listNames.isEmpty()) { + foreach (QString name, listNames) { + // add image name to the list + new QListWidgetItem(name, m_d->ui.listWidget); + } + } +} + + +//____________________________________________________________________ +void VP1EventDisplayEditor::removeObject() +{ + QListWidgetItem * currentItem = m_d->ui.listWidget->currentItem(); + QString text = currentItem->text(); + int currentPos = m_d->ui.listWidget->row( currentItem ); + + // remove the object from the scene + m_scene->removeItem( m_sceneItems[currentPos] ); + // remove its associated pointer in our list + m_sceneItems.removeAt( currentPos ); + // remove its associated label + QListWidgetItem * item = m_d->ui.listWidget->takeItem(currentPos); + delete item; + + VP1Msg::message("Successfully removed the object: " + text); +} + +//// SLOT +////____________________________________________________________________ +//void VP1EventDisplayEditor::addTextLabelSlot() +//{ +// this->addTextLabel(); +//} + + +//____________________________________________________________________ +void VP1EventDisplayEditor::setTextLabel() +{ + QString text; + QFont font; + +// /* if we use this function programmatically, +// * passing text directly +// */ +// if (!textString.isEmpty()) { +// +// text = textString; +// +// // default settings +// int size = 32; +// int weight = QFont::Normal; +// bool italics = false; +// QString typeface = "Courier"; +// +// // default font +// font = QFont(typeface, size, weight, italics); +// +// // default font family, if Courier is not available +// font.setStyleHint(QFont::TypeWriter); +// +// } + +// /* if we use this function from the GUI, +// * then we get all user's settings from the GUI itself +// */ +// else { + + if (m_d->ui.radioButton_eventDetails->isChecked()) { + // get the event details + text = this->getEventDetailsLabel(); + } + else { + // get the user's text + text = m_d->ui.lineEdit_customLabelText->text(); + } + + + // get users' settings + int size = 0; + if (m_d->ui.radioButton_size12->isChecked()) size = 12; + else if (m_d->ui.radioButton_size24->isChecked()) size = 24; + else if (m_d->ui.radioButton_size32->isChecked()) size = 32; + else if (m_d->ui.radioButton_size44->isChecked()) size = 44; + else if (m_d->ui.radioButton_sizeCustom->isChecked()) { + size = m_d->ui.spinBox_size->value(); + } + + QString typeface = "Courier"; // default typeface + + int weight = QFont::Normal; + if (m_d->ui.radioButton_light->isChecked()) weight = QFont::Light; + else if (m_d->ui.radioButton_normal->isChecked()) weight = QFont::Normal; + else if (m_d->ui.radioButton_bold->isChecked()) weight = QFont::Bold; + else if (m_d->ui.radioButton_black_2->isChecked()) weight = QFont::Black; + + bool italics = false; + if (m_d->ui.radioButton_italics->isChecked()) italics = true; + + font = QFont(typeface, size, weight, italics); + + if (m_d->ui.radioButton_monaco->isChecked()) { + // typeface = "Monaco"; + typeface = "Courier"; + font.setStyleHint(QFont::TypeWriter); // this defines the family to choose from, if the preferred typeface is not available on the host system + } + else if (m_d->ui.radioButton_helvetica->isChecked()) { + typeface = "Helvetica"; + font.setStyleHint(QFont::SansSerif); + } + else if (m_d->ui.radioButton_times->isChecked()) { + typeface = "Times"; + font.setStyleHint(QFont::Serif); + } + font.setFamily(typeface); + +// } + + this->addTextLabel(text, font); +} + + +//____________________________________________________________________ +void VP1EventDisplayEditor::addTextLabel(QString text, QFont font) +{ +// adding the label to the m_scene +QGraphicsTextItem* item = m_scene->addText(text, font); +item->setFlags(QGraphicsItem::ItemIsMovable); + +// set the user's preferred color +if (m_d->ui.radioButton_whiteText->isChecked()) { + item->setDefaultTextColor(Qt::white); +} else if (m_d->ui.radioButton_blackText->isChecked()) { + item->setDefaultTextColor(Qt::black); +} + +// adding the label to the list of objects +QString strippedText = text.replace('\n',' ').replace('\t', ' ').simplified(); +new QListWidgetItem(strippedText, m_d->ui.listWidget); + +// adding the label to list of object pointers +m_sceneItems << item; +} + + +//____________________________________________________________________ +void VP1EventDisplayEditor::getTabSnapshot() +{ + int tabN = m_d->ui.comboBox_tabNumber->currentIndex(); + QString tabName = m_d->ui.comboBox_tabNumber->currentText(); + VP1Msg::messageVerbose("Got tab: " + tabName + " at idx: " + QString::number(tabN) ); + + int imageWidth = m_d->ui.spinBox_imageWidth->value(); + VP1Msg::messageVerbose("width: " + QString::number(imageWidth) ); + + QPixmap snap = m_mainWindow->getSingleChannelCustomSnapshot( tabName, imageWidth ); + + tabName = tabName + "_" + QString::number(imageWidth); + + + QList<QPixmap> listPixmap; + QStringList listNamesPixmap; + + listPixmap << snap; + listNamesPixmap << tabName; + + this->addPixmapList(listPixmap, listNamesPixmap); + +} + +//____________________________________________________________________ +void VP1EventDisplayEditor::setTabsList( QStringList listNames ) +{ + VP1Msg::messageVerbose("VP1EventDisplayEditor::setTabsList()"); + + m_d->ui.comboBox_tabNumber->addItems(listNames); + +} + + +//____________________________________________________________________ +void VP1EventDisplayEditor::addLogo() +{ + QPixmap pix; + QString name; + + // load the right version of the ATLAS logo + if ( m_d->ui.radioButton_300px->isChecked() ) { + if ( m_d->ui.radioButton_gray->isChecked() ) + pix.load(":/vp1/images/images/ATLAS-Logo-New_300pixels.png"); + if (m_d->ui.radioButton_blue->isChecked() ) + pix.load(":/vp1/images/images/ATLAS-chrome-logo-URL-blue_300px.png"); + name = "logo_300px"; + } + else if ( m_d->ui.radioButton_450px->isChecked() ) { + if ( m_d->ui.radioButton_gray->isChecked() ) + pix.load(":/vp1/images/images/ATLAS-Logo-New_450pixels.png"); + if (m_d->ui.radioButton_blue->isChecked() ) + pix.load(":/vp1/images/images/ATLAS-chrome-logo-URL-blue_450px.png"); + name = "logo_450px"; + } + else if ( m_d->ui.radioButton_600px->isChecked() ) { + if ( m_d->ui.radioButton_gray->isChecked() ) + pix.load(":/vp1/images/images/ATLAS-Logo-New_600pixels.png"); + if (m_d->ui.radioButton_blue->isChecked() ) + pix.load(":/vp1/images/images/ATLAS-chrome-logo-URL-blue_600px.png"); + name = "logo_600px"; + } + else if ( m_d->ui.radioButton_800px->isChecked() ) { + if ( m_d->ui.radioButton_gray->isChecked() ) + pix.load(":/vp1/images/images/ATLAS-Logo-New_800pixels.png"); +// if (m_d->ui.radioButton_blue->isChecked() ) +// pix.load(":/vp1/images/images/ATLAS-chrome-logo-URL-blue_600px.png"); + name = "logo_800px"; + } + else if ( m_d->ui.radioButton_1000px->isChecked() ) { + if ( m_d->ui.radioButton_gray->isChecked() ) + pix.load(":/vp1/images/images/ATLAS-Logo-New_1000pixels.png"); +// if (m_d->ui.radioButton_blue->isChecked() ) +// pix.load(":/vp1/images/images/ATLAS-chrome-logo-URL-blue_600px.png"); + name = "logo_1000px"; + } + else if ( m_d->ui.radioButton_1200px->isChecked() ) { + if ( m_d->ui.radioButton_gray->isChecked() ) + pix.load(":/vp1/images/images/ATLAS-Logo-New_1200pixels.png"); +// if (m_d->ui.radioButton_blue->isChecked() ) +// pix.load(":/vp1/images/images/ATLAS-chrome-logo-URL-blue_600px.png"); + name = "logo_1200px"; + } + + // add the logo to the m_scene + QGraphicsPixmapItem* item = m_scene->addPixmap(pix); + item->setFlags(QGraphicsItem::ItemIsMovable); + // add to the list of pointers + m_sceneItems << item; + // add to the list of object labels + new QListWidgetItem(name, m_d->ui.listWidget); +} + + +//____________________________________________________________________ +void VP1EventDisplayEditor::setBackgroundColor() +{ + + // a white background + if ( m_d->ui.radioButton_white->isChecked() ) + m_scene->setBackgroundBrush(Qt::white); + // a black background + else if ( m_d->ui.radioButton_black->isChecked() ) + m_scene->setBackgroundBrush(Qt::black); + // a transparent background + else if ( m_d->ui.radioButton_transparent->isChecked() ) { + m_scene->setBackgroundBrush(Qt::NoBrush); + // // a gradient background + // QRadialGradient gradient(0, 0, 10); + // gradient.setSpread(QGradient::RepeatSpread); + // m_scene->setBackgroundBrush(gradient); + } +} + + + +//____________________________________________________________________ +void VP1EventDisplayEditor::closeEvent(QCloseEvent*ev) +{ + // if you want to just hide the window when closed, uncomment the lines below + ev->ignore(); + hide(); + + // this, instead, will close the window + // ev->accept(); +} + +//QGraphicsView* VP1EventDisplayEditor::getView() +//{ +// return m_d->ui.graphicsView; +//} + + + + +////____________________________________________________________________ +//void VP1EventDisplayEditor::buttonClicked() +//{ +// if (m_d->ui.pushButton_addCurrentView==sender()) { +// VP1CustomTourFrameWidget * frame = new VP1CustomTourFrameWidget(m_d->viewer->currentCamIsPerspective(), +// m_d->viewer->currentCameraState()); +// m_d->addFrame(frame); +// m_d->updateFrameSnapshot(frame); +// m_d->updateFrameListVisuals(); +// } else if (m_d->ui.pushButton_refreshPreviews==sender()) { +// foreach(VP1CustomTourFrameWidget*frame,m_d->frames) +// m_d->updateFrameSnapshot(frame); +// } else if (m_d->ui.pushButton_execute==sender()) { +// m_d->viewer->startCustomTour(); +// } else if (m_d->ui.pushButton_utilityZoomShow==sender()) { +// } +//} + diff --git a/graphics/VTI12/VTI12Gui/src/VP1EventDisplaySceneView.cxx b/graphics/VTI12/VTI12Gui/src/VP1EventDisplaySceneView.cxx new file mode 100644 index 000000000..aca3fdc77 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1EventDisplaySceneView.cxx @@ -0,0 +1,373 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/* + * jira_1 + * VP1EventDisplaySceneView.cxx + * + * Created on: Sep 26, 2013 + * Author: rbianchi <Riccardo.Maria.Bianchi@cern.ch> + * + */ + +#include "VTI12Gui/VP1EventDisplaySceneView.h" +#include "VP1Base/VP1Msg.h" + +#include <QtGui> +#include <QPrinter> +#include <QPrintDialog> + +#ifndef QT_NO_OPENGL + #include <QtOpenGL> +#endif + +#include <qmath.h> + +// with this we can use the mouse central wheel on the zoom sliders +void GraphicsView::wheelEvent(QWheelEvent *e) +{ + if (e->modifiers() & Qt::ControlModifier) { + if (e->delta() > 0) + m_view->zoomIn(6); + else + m_view->zoomOut(6); + e->accept(); + } else { + QGraphicsView::wheelEvent(e); + } +} + +VP1EventDisplaySceneView::VP1EventDisplaySceneView(const QString &name, bool preview, QWidget *parent) +: QFrame(parent),m_frame(nullptr),m_line(nullptr) +{ + m_preview = preview; + + + setFrameStyle(Sunken | StyledPanel); + + m_graphicsView = new GraphicsView(this); + m_graphicsView->setRenderHint(QPainter::Antialiasing, false); + m_graphicsView->setDragMode(QGraphicsView::RubberBandDrag); + m_graphicsView->setOptimizationFlags(QGraphicsView::DontSavePainterState); + m_graphicsView->setViewportUpdateMode(QGraphicsView::SmartViewportUpdate); + m_graphicsView->setTransformationAnchor(QGraphicsView::AnchorUnderMouse); + + int size = style()->pixelMetric(QStyle::PM_ToolBarIconSize); + QSize iconSize(size, size); + + + // ZOOM BUTTONS + + m_zoomInIcon = new QToolButton; + m_zoomInIcon->setAutoRepeat(true); + m_zoomInIcon->setAutoRepeatInterval(33); + m_zoomInIcon->setAutoRepeatDelay(0); + m_zoomInIcon->setIcon(QPixmap(":/vp1/icons/icons/zoomin.png")); + m_zoomInIcon->setIconSize(iconSize); + + m_zoomOutIcon = new QToolButton; + m_zoomOutIcon->setAutoRepeat(true); + m_zoomOutIcon->setAutoRepeatInterval(33); + m_zoomOutIcon->setAutoRepeatDelay(0); + m_zoomOutIcon->setIcon(QPixmap(":/vp1/icons/icons/zoomout.png")); + m_zoomOutIcon->setIconSize(iconSize); + + m_zoomSlider = new QSlider(); + m_zoomSlider->setMinimum(0); + m_zoomSlider->setMaximum(500); + m_zoomSlider->setValue(250); + m_zoomSlider->setTickPosition(QSlider::TicksRight); + + // Zoom slider layout + m_zoomSliderLayout = new QVBoxLayout; + m_zoomSliderLayout->addWidget(m_zoomInIcon); + m_zoomSliderLayout->addWidget(m_zoomSlider); + m_zoomSliderLayout->addWidget(m_zoomOutIcon); + + + // ROTATION BUTTONS + m_rotateLeftIcon = new QToolButton(); + m_rotateLeftIcon->setIcon(QPixmap(":/vp1/icons/icons/rotateleft.png")); + m_rotateLeftIcon->setIconSize(iconSize); + + m_rotateRightIcon = new QToolButton(); + m_rotateRightIcon->setIcon(QPixmap(":/vp1/icons/icons/rotateright.png")); + m_rotateRightIcon->setIconSize(iconSize); + + m_rotateSlider = new QSlider(); + m_rotateSlider->setOrientation(Qt::Horizontal); + m_rotateSlider->setMinimum(-360); + m_rotateSlider->setMaximum(360); + m_rotateSlider->setValue(0); + m_rotateSlider->setTickPosition(QSlider::TicksBelow); + + // Rotate slider layout + m_rotateSliderLayout = new QHBoxLayout; + m_rotateSliderLayout->addWidget(m_rotateLeftIcon); + m_rotateSliderLayout->addWidget(m_rotateSlider); + m_rotateSliderLayout->addWidget(m_rotateRightIcon); + + m_resetButton = new QToolButton; + m_resetButton->setText(tr("Reset")); + m_resetButton->setEnabled(false); + + // Label layout + QHBoxLayout *labelLayout = new QHBoxLayout; + m_label = new QLabel(name); + m_label2 = new QLabel(tr("Pointer Mode")); + + m_selectModeButton = new QToolButton; + m_selectModeButton->setText(tr("Select & Move items")); + m_selectModeButton->setCheckable(true); + m_selectModeButton->setChecked(true); + + m_dragModeButton = new QToolButton; + m_dragModeButton->setText(tr("Drag View")); + m_dragModeButton->setCheckable(true); + m_dragModeButton->setChecked(false); + + m_antialiasButton = new QToolButton; + m_antialiasButton->setText(tr("Antialiasing")); + m_antialiasButton->setCheckable(true); + m_antialiasButton->setChecked(false); + + m_openGlButton = new QToolButton; + m_openGlButton->setText(tr("OpenGL")); + m_openGlButton->setCheckable(true); +#ifndef QT_NO_OPENGL + m_openGlButton->setEnabled(QGLFormat::hasOpenGL()); +#else + m_openGlButton->setEnabled(false); +#endif + m_printButton = new QToolButton; + m_printButton->setIcon(QIcon(QPixmap(":/vp1/icons/icons/fileprint.png"))); + + QButtonGroup *pointerModeGroup = new QButtonGroup; + pointerModeGroup->setExclusive(true); + pointerModeGroup->addButton(m_selectModeButton); + pointerModeGroup->addButton(m_dragModeButton); + + labelLayout->addWidget(m_label); + labelLayout->addStretch(); + + if (!preview) { + labelLayout->addWidget(m_label2); + labelLayout->addWidget(m_selectModeButton); + labelLayout->addWidget(m_dragModeButton); + labelLayout->addStretch(); +// labelLayout->addWidget(m_antialiasButton); // we don't use these buttons +// labelLayout->addWidget(m_openGlButton); +// labelLayout->addWidget(m_printButton); + } + + QGridLayout *topLayout = new QGridLayout; + topLayout->addLayout(labelLayout, 0, 0); + topLayout->addWidget(m_graphicsView, 1, 0); + /* + * PREVIEW WINDOW + * we don't need the rotation or zoom buttons for the "preview" view + * and we put the reset button just below the zoom buttons + */ + if (preview) { + // m_zoomSliderLayout->addWidget(m_resetButton); + } + /* + * FULL SIZE WINDOW + */ + else { + topLayout->addLayout(m_zoomSliderLayout, 1, 1); + topLayout->addLayout(m_rotateSliderLayout, 2, 0); + topLayout->addWidget(m_resetButton, 2, 1); + } + + setLayout(topLayout); + + + + + connect(m_resetButton, SIGNAL(clicked()), this, SLOT(resetView())); + + connect(m_graphicsView->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(setResetButtonEnabled())); + connect(m_graphicsView->horizontalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(setResetButtonEnabled())); + + connect(m_selectModeButton, SIGNAL(toggled(bool)), this, SLOT(togglePointerMode())); + connect(m_dragModeButton, SIGNAL(toggled(bool)), this, SLOT(togglePointerMode())); + + connect(m_zoomSlider, SIGNAL(valueChanged(int)), this, SLOT(setupMatrix())); + connect(m_zoomInIcon, SIGNAL(clicked()), this, SLOT(zoomIn())); + connect(m_zoomOutIcon, SIGNAL(clicked()), this, SLOT(zoomOut())); + + connect(m_rotateSlider, SIGNAL(valueChanged(int)), this, SLOT(setupMatrix())); + connect(m_rotateLeftIcon, SIGNAL(clicked()), this, SLOT(rotateLeft())); + connect(m_rotateRightIcon, SIGNAL(clicked()), this, SLOT(rotateRight())); + + + // we do not use these three buttons now... +// connect(m_printButton, SIGNAL(clicked()), this, SLOT(print())); +// connect(m_antialiasButton, SIGNAL(toggled(bool)), this, SLOT(toggleAntialiasing())); +// connect(m_openGlButton, SIGNAL(toggled(bool)), this, SLOT(toggleOpenGL())); + + setupMatrix(); // only useful for the full-view window +} + +VP1EventDisplaySceneView::~VP1EventDisplaySceneView() +{ + /* if preview, many buttons are not added to any widget or layout, + * so we have to destroy them by hand + */ + if (m_preview) { + delete m_rotateSlider; + delete m_rotateLeftIcon; + delete m_rotateRightIcon; + delete m_rotateSliderLayout; + delete m_zoomSlider; + delete m_zoomInIcon; + delete m_zoomOutIcon; + delete m_zoomSliderLayout; + delete m_resetButton; + delete m_label2; + delete m_selectModeButton; + delete m_dragModeButton; + } + /* + * we have to destroy them by hand, because we do not use them in this version of the GUI + */ + delete m_antialiasButton; + delete m_openGlButton; + delete m_printButton; +} + +QGraphicsView *VP1EventDisplaySceneView::view() const +{ + return static_cast<QGraphicsView *>(m_graphicsView); +} + +void VP1EventDisplaySceneView::addRenderingFrame() +{ +// adding a rect to the preview to define the rendering area +// QPen pen2(Qt::green, 5, Qt::DashDotLine, Qt::RoundCap, Qt::RoundJoin); + QPen pen(Qt::red, 5, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin); + QRectF sceneRect = m_graphicsView->scene()->sceneRect(); + m_frame = m_graphicsView->scene()->addRect( sceneRect, pen ); + + /* we also have to add a line on the bottom of the scene, + * since the bottom side of the frame will go out of the view, + * due to the thickness of the frame lines. + */ + qreal x1 = sceneRect.left(); + qreal y1 = sceneRect.bottom(); + qreal y2 = y1; + qreal x2 = sceneRect.right(); + + m_line = m_graphicsView->scene()->addLine( x1, y1, x2, y2, pen); +} + +void VP1EventDisplaySceneView::showRenderingFrame() +{ + m_frame->show(); + m_line->show(); +} + +void VP1EventDisplaySceneView::hideRenderingFrame() +{ + m_frame->hide(); + m_line->hide(); +} + + + +void VP1EventDisplaySceneView::resetView() +{ + m_zoomSlider->setValue(250); + m_rotateSlider->setValue(0); + setupMatrix(); + m_graphicsView->ensureVisible(QRectF(0, 0, 0, 0)); + + m_resetButton->setEnabled(false); +} + +void VP1EventDisplaySceneView::setResetButtonEnabled() +{ + m_resetButton->setEnabled(true); +} + +void VP1EventDisplaySceneView::setPreviewZoom(qreal xx) +{ + if (m_preview) { + QMatrix matrix; + matrix.scale(xx, xx); + m_graphicsView->setMatrix(matrix); + } else { + VP1Msg::message("Warning!! using setPreviewZoom() on a full-size view has no effect."); + } + +} + +void VP1EventDisplaySceneView::setupMatrix() +{ + if (!m_preview) { + QMatrix matrix; + qreal scale = qPow(qreal(2), (m_zoomSlider->value() - 250) / qreal(50)); + matrix.scale(scale, scale); + matrix.rotate(m_rotateSlider->value()); + + m_graphicsView->setMatrix(matrix); + setResetButtonEnabled(); + } + +} + +void VP1EventDisplaySceneView::togglePointerMode() +{ + m_graphicsView->setDragMode(m_selectModeButton->isChecked() + ? QGraphicsView::RubberBandDrag + : QGraphicsView::ScrollHandDrag); + m_graphicsView->setInteractive(m_selectModeButton->isChecked()); +} + +void VP1EventDisplaySceneView::toggleOpenGL() +{ +#ifndef QT_NO_OPENGL + m_graphicsView->setViewport(m_openGlButton->isChecked() ? new QGLWidget(QGLFormat(QGL::SampleBuffers)) : new QWidget); +#endif +} + +void VP1EventDisplaySceneView::toggleAntialiasing() +{ + m_graphicsView->setRenderHint(QPainter::Antialiasing, m_antialiasButton->isChecked()); +} + +void VP1EventDisplaySceneView::print() +{ +#ifndef QT_NO_PRINTER + QPrinter printer; + QPrintDialog dialog(&printer, this); + if (dialog.exec() == QDialog::Accepted) { + QPainter painter(&printer); + m_graphicsView->render(&painter); + } +#endif +} + +void VP1EventDisplaySceneView::zoomIn(int level) +{ + m_zoomSlider->setValue(m_zoomSlider->value() + level); +} + +void VP1EventDisplaySceneView::zoomOut(int level) +{ + m_zoomSlider->setValue(m_zoomSlider->value() - level); +} + +void VP1EventDisplaySceneView::rotateLeft() +{ + m_rotateSlider->setValue(m_rotateSlider->value() - 10); +} + +void VP1EventDisplaySceneView::rotateRight() +{ + m_rotateSlider->setValue(m_rotateSlider->value() + 10); +} + + diff --git a/graphics/VTI12/VTI12Gui/src/VP1EventFile.cxx b/graphics/VTI12/VTI12Gui/src/VP1EventFile.cxx new file mode 100644 index 000000000..dbf7acc97 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1EventFile.cxx @@ -0,0 +1,200 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class VP1EventFile // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: May 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12Gui/VP1EventFile.h" +#include <QStringList> + +//____________________________________________________________________ +class VP1EventFile::Imp { +public: + Imp() : runNumber(0), eventNumber(0), rawTime(0), valid(false) {} + Imp(const QString& fn,const QString& sum, + int r,int e,unsigned t,bool isvalid) + : fileName(fn), md5Sum(sum), + runNumber(r), eventNumber(e), rawTime(t), valid(isvalid) + {} + QString fileName; + QString md5Sum; + int runNumber; + unsigned long long eventNumber; + unsigned rawTime; + bool valid; + + static Imp * initFromFilename(const QString& filename, const QString& md5sum); +}; + +//____________________________________________________________________ +VP1EventFile::VP1EventFile() + : m_d(new Imp) +{ +} + +//____________________________________________________________________ +VP1EventFile::Imp * VP1EventFile::Imp::initFromFilename(const QString& filename, const QString& md5sum) +{ + QStringList filenameparts = filename.split('.', QString::SkipEmptyParts ); + if (filenameparts.isEmpty()) + return new Imp; + + //We find the relevant part of the filename the following way: + //Starting from the back, we find the first part which contains at + //least two underscores) + int ieventinfo=-1; + for (int i=filenameparts.count()-1;i>=0;--i) { + if (filenameparts.at(i).count('_')>=2) { + ieventinfo = i; + break; + } + } + if (ieventinfo==-1) + return new Imp; + + QStringList eventinfoparts = filenameparts.at(ieventinfo).split('_', QString::SkipEmptyParts ); + if (eventinfoparts.count()<3) + return new Imp; + bool ok; + int time = eventinfoparts.at(eventinfoparts.count()-1).toInt(&ok); + // if (!ok||time<1175378400/*april 1. 2007*/||time>2058991200/*april 1 2035*/) + if (!ok||time>2058991200/*april 1 2035*/)//No lower bound sanity check, since the events sometimes have faulty ~1970 timestamps! + return new Imp; + + unsigned long long eventnumber = eventinfoparts.at(eventinfoparts.count()-2).toInt(&ok); + if (!ok) + return new Imp; + int runnumber = eventinfoparts.at(eventinfoparts.count()-3).toInt(&ok); + if (!ok) + return new Imp; + return new Imp(filename,md5sum,runnumber,eventnumber,time,true); +} + +//____________________________________________________________________ +VP1EventFile::VP1EventFile(const QString& filename, const QString& md5sum) + : m_d(Imp::initFromFilename(filename,md5sum)) +{ +} + +//____________________________________________________________________ +VP1EventFile::VP1EventFile(const QString& filename,const QString& md5sum, + int runnumber, unsigned long long eventnumber,unsigned time,bool isvalid) + : m_d(new Imp(filename,md5sum,runnumber,eventnumber,time,isvalid)) +{ +} + +//____________________________________________________________________ +VP1EventFile::~VP1EventFile() +{ + delete m_d; +} + +//____________________________________________________________________ +bool VP1EventFile::operator<( const VP1EventFile & other ) const +{ + //newer (larger time, run and evt numbers) means "smaller". + if (m_d->rawTime!=other.m_d->rawTime) return m_d->rawTime>other.m_d->rawTime; + if (m_d->runNumber!=other.m_d->runNumber) return m_d->runNumber>other.m_d->runNumber; + if (m_d->eventNumber!=other.m_d->eventNumber) return m_d->eventNumber>other.m_d->eventNumber; + if (m_d->fileName!=other.m_d->fileName) return m_d->fileName<other.m_d->fileName; + if (m_d->valid!=other.m_d->valid) return m_d->valid; + return m_d->md5Sum<other.m_d->md5Sum; +} + +//____________________________________________________________________ +bool VP1EventFile::operator==(const VP1EventFile & other ) const +{ + return m_d->rawTime==other.m_d->rawTime + && m_d->eventNumber==other.m_d->eventNumber + && m_d->md5Sum==other.m_d->md5Sum + && m_d->fileName==other.m_d->fileName + && m_d->runNumber==other.m_d->runNumber + && m_d->valid==other.m_d->valid; +} + +//____________________________________________________________________ +bool VP1EventFile::operator!=(const VP1EventFile & other ) const +{ + return !(*this==other); +} + +//____________________________________________________________________ +VP1EventFile::VP1EventFile( const VP1EventFile & other ) + : m_d(new Imp) +{ + *this = other; +} + +//____________________________________________________________________ +VP1EventFile & VP1EventFile::operator= ( const VP1EventFile & other ) +{ + m_d->fileName = other.m_d->fileName; + m_d->md5Sum = other.m_d->md5Sum; + m_d->runNumber = other.m_d->runNumber; + m_d->eventNumber = other.m_d->eventNumber; + m_d->rawTime = other.m_d->rawTime; + m_d->valid = other.m_d->valid; + return *this; +} + +//____________________________________________________________________ +bool VP1EventFile::isValid() const +{ + return m_d->valid; +} + +//____________________________________________________________________ +QString VP1EventFile::fileName() const +{ + return m_d->fileName; +} + +//____________________________________________________________________ +QString VP1EventFile::md5Sum() const +{ + return m_d->md5Sum; +} + +//____________________________________________________________________ +int VP1EventFile::runNumber() const +{ + return m_d->runNumber; +} + +//____________________________________________________________________ +unsigned long long VP1EventFile::eventNumber() const +{ + return m_d->eventNumber; +} + +//____________________________________________________________________ +unsigned VP1EventFile::rawTime() const +{ + return m_d->rawTime; +} + +//____________________________________________________________________ +QDateTime VP1EventFile::time() const +{ + return QDateTime::fromTime_t(m_d->rawTime); +} + +//____________________________________________________________________ +QString VP1EventFile::print() const +{ + if (!isValid()) + return "[invalid]"; + return fileName() + +", run="+QString::number(runNumber()) + +", evt="+QString::number(eventNumber()) + +", time="+time().toString() + +", md5="+md5Sum(); +} diff --git a/graphics/VTI12/VTI12Gui/src/VP1EvtsOnServerInfo.cxx b/graphics/VTI12/VTI12Gui/src/VP1EvtsOnServerInfo.cxx new file mode 100644 index 000000000..b6e02cd07 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1EvtsOnServerInfo.cxx @@ -0,0 +1,262 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class VP1EvtsOnServerInfo // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: May 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12Gui/VP1EvtsOnServerInfo.h" +#include "VTI12Gui/VP1MD5Sum.h" +#include <QFileInfo> +#include <QTextStream> +#include <map> + + +//____________________________________________________________________ +class VP1EvtsOnServerInfo::Imp { +public: + Imp(const QString& infofile) + { + error = init(infofile); + } + + QString error; + QString init(const QString& infofile); + + QList<VP1EventFile> events;//if invalid, we make a list with one dummy + //event (to avoid crashes if user forget to + //check isValid()) +}; + + +//____________________________________________________________________ +VP1EvtsOnServerInfo::VP1EvtsOnServerInfo(const QString& infofile) + : m_d(new Imp(infofile)) +{ +} + +//____________________________________________________________________ +VP1EvtsOnServerInfo::~VP1EvtsOnServerInfo() +{ + delete m_d; +} + +//____________________________________________________________________ +bool VP1EvtsOnServerInfo::isValid() const +{ + return m_d->error.isEmpty(); +} + +//____________________________________________________________________ +QString VP1EvtsOnServerInfo::error() const +{ + return m_d->error; +} + +//____________________________________________________________________ +QStringList VP1EvtsOnServerInfo::print() const +{ + QStringList l; + if (!isValid()) { + l << "Invalid. Reason: " + error(); + return l; + } + l << "Valid with "+QString::number(numberOfEvents())+" files:"; + foreach(VP1EventFile evt, events()) + l << " "+evt.print(); + l << "Events within 10 minutes of latest:"; + foreach(VP1EventFile evt, events(10*60)) + l << " "+evt.print(); + l << "Events with same run number as latest:"; + foreach(VP1EventFile evt, events(-1,true)) + l << " "+evt.print(); + l << "Events with same run number as latest and within 1 minute:"; + foreach(VP1EventFile evt, events(1*60,true)) + l << " "+evt.print(); + + return l; +} + +//____________________________________________________________________ +QString VP1EvtsOnServerInfo::Imp::init(const QString& infofile) +{ + //Example of file we are trying to parse: + // + //begin_copyresult + //source dir /client/VP1_events + //dest dir /www/web_files/html/vp1events + //vp1_69629_5487_1211316972.pool.root copy success + //end_copyresult + //begin_checksums + //vp1_69629_5487_1211316972.pool.root 30fa3c9a05251a4d741fce52c304a341 + //vp1_69629_5270_1211316960.pool.root 7a38564cdd2f2951e76ec37c565dbbf9 + //vp1_69629_3968_1211316900.pool.root 6c716952a7fdb0371b1541a45d0029f8 + //end_checksums + // + //The format of the event file names are: vp1_[run#]_[evt#]_[unixtime].pool.root + // + //In principle we are only interested in the checksums section, but + //it might be a good sanity check to see that the last copied file + //(from copyresult) is also the one with the highest time. + + /////////////////////////////////////////////////////// + // Basic check that file exists, is readable, etc. // + /////////////////////////////////////////////////////// + + if (infofile.isEmpty()) + return "Given empty path to info file"; + QFileInfo fi(infofile); + if (!fi.exists()) + return "infofile "+infofile+" does not exist"; + if (!fi.isReadable()) + return "infofile "+infofile+" is not readable"; + if (fi.size()==0) + return "infofile "+infofile+" is not empty"; + + ///////////////////////////////////////////////////////////////////////////// + // Read file into stringlist, ignoring empty lines and excess whitespace // + ///////////////////////////////////////////////////////////////////////////// + + int i_begin_copyresult(-1), i_end_copyresult(-1); + int i_begin_checksums(-1), i_end_checksums(-1); + + + QStringList lines; + QFile file(infofile); + if (!file.open(QFile::ReadOnly)) + return "Could not open file in readonly mode"; + + //Just to avoid any potential performance problems if pointed to a + //wrong input file: + const qint64 max_linelength(1000); + const qint64 max_numberoflines(2000); + qint64 ilines(0); + + QTextStream stream(&file); + while (!stream.atEnd()) { + + if (ilines++>max_numberoflines) + return "Too many lines in file"; + + //Read and prune next line: + QString rawline = stream.readLine(max_linelength).simplified(); + if (rawline.isEmpty()) + continue; + + //Get section boundaries: + if (rawline=="begin_copyresult") { + if (i_begin_copyresult!=-1) + return "Saw two lines with begin_copyresult"; + i_begin_copyresult = lines.count(); + } else if (rawline=="end_copyresult") { + if (i_end_copyresult!=-1) + return "Saw two lines with end_copyresult"; + i_end_copyresult = lines.count(); + } else if (rawline=="begin_checksums") { + if (i_begin_checksums!=-1) + return "Saw two lines with begin_checksums"; + i_begin_checksums = lines.count(); + } else if (rawline=="end_checksums") { + if (i_end_checksums!=-1) + return "Saw two lines with end_checksums"; + i_end_checksums = lines.count(); + } + + //Store line: + lines << rawline; + } + if (lines.isEmpty()) + return "Did not read any lines from file"; + + //copy result is only used for a sanity check, so we keep it optional + const bool hascopyresult(i_begin_copyresult!=-1||i_end_copyresult!=-1); + + if (i_begin_checksums==-1) return "File did not have begin_checksums line"; + if (i_end_checksums==-1) return "File did not have end_checksums line"; + if (i_end_checksums<=i_begin_checksums) return "checksum section delimiters out of order"; + + if (hascopyresult) { + if (i_begin_copyresult==-1) return "File had end_copyresult but no begin_copyresult line"; + if (i_end_copyresult==-1) return "File had begin_copyresult but no end_copyresult line"; + if (i_end_copyresult<=i_begin_copyresult) return "copyresult section delimiters out of order"; + if (i_begin_copyresult>i_begin_checksums&&i_begin_copyresult<i_end_checksums) + return "copyresult and checksum sections mixed"; + if (i_end_copyresult>i_begin_checksums&&i_end_copyresult<i_end_checksums) + return "copyresult and checksum sections mixed"; + } + + /////////////////////////////// + // Let the parsing begin!! // + /////////////////////////////// + + for (int i = i_begin_checksums+1;i < i_end_checksums; ++i) { + QStringList parts = lines.at(i).split ( ' ', QString::SkipEmptyParts ); + if (parts.count()!=2) + return "Invalid line in checksums section"; + QString filename(parts.at(0)); + QString md5sum(VP1MD5Sum::sumToStandardFormat(parts.at(1))); + if (!VP1MD5Sum::validMD5Sum(md5sum)) + return "Invalid md5sum in checksums section: "+md5sum; + VP1EventFile evt(filename,md5sum); + if (!evt.isValid()) + return "Failed to decode event file information from filename: "+filename; + events << evt; + } + + qSort(events); + + if (hascopyresult) { + //Todo: Use the copy result lines for a sanity check of that the + //newest file is also the one copied last (if copy succesful). + } + + return ""; +} + +//____________________________________________________________________ +unsigned long long VP1EvtsOnServerInfo::numberOfEvents() const +{ + return m_d->events.count(); +} + +//____________________________________________________________________ +VP1EventFile VP1EvtsOnServerInfo::newestEvent() const +{ + return m_d->events.isEmpty() ? VP1EventFile() : m_d->events.at(0); +} + +//____________________________________________________________________ +QList<VP1EventFile> VP1EvtsOnServerInfo::events(int timecut, bool requireNewestRunNumber ) const +{ + //Notice: Logic here must be similar to logic in VP1AvailEvents::isConsideredFresh + + if ( m_d->events.isEmpty() ) + return m_d->events; + + if (timecut==0) { + QList<VP1EventFile> l; + l << m_d->events.at(0); + return l; + } + const unsigned newestRawTime = m_d->events.at(0).rawTime(); + const int newestRunNumber = m_d->events.at(0).runNumber(); + + const unsigned minTime = (timecut<0&&unsigned(timecut)>newestRawTime) ? 0 : newestRawTime-timecut; + + QList<VP1EventFile> out; + foreach (VP1EventFile evt, m_d->events) { + if (minTime>0&&evt.rawTime()<minTime) + continue; + if (requireNewestRunNumber&&evt.runNumber()!=newestRunNumber) + continue; + out << evt; + } + return out; +} diff --git a/graphics/VTI12/VTI12Gui/src/VP1ExecutionScheduler.cxx b/graphics/VTI12/VTI12Gui/src/VP1ExecutionScheduler.cxx new file mode 100644 index 000000000..3a300d1d1 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1ExecutionScheduler.cxx @@ -0,0 +1,1501 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////// +// // +// Implementation of class VP1ExecutionScheduler // +// // +// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Initial version: April 2007 // +// // +// History: // +// R.M.Bianchi <rbianchi@cern.ch> - Feb 2013 // +// // +///////////////////////////////////////////////////////////// + +//TODO: +// +// * Save sys2time data in .vp1 file +// * Disable custom controllers between events! +// * Integrate with cruise modes (tab and event) +// * In tab cruise mode, dont go to next tab until it is ready. Thus, +// we need to be able to ask the scheduler if a given tab is ready. +// * "Soon to be visible" priority +// * General performance optimisation (inline internal methods + +// cache iterators). +// * Take care of accumulators. +// * Accumulate cruise mode (with ETA if it is a given number of events). + +/* this to fix the 'ptrdiff_t' does not name a type error with Qt: + * refs: + * - http://qt-project.org/forums/viewthread/16992 + * - http://stackoverflow.com/questions/6727193/g-4-6-complains-about-iterator-difference-type-g-4-4-and-visual-studio-don + */ +// #include <stddef.h> + + +#include "VTI12Gui/VP1ExecutionScheduler.h" +#include "VTI12Gui/VP1AvailEvents.h" +#include "VTI12Gui/VP1AvailEvtsHttp.h" +#include "VTI12Gui/VP1AvailEvtsHttps.h" +#include "VTI12Gui/VP1AvailEvtsLocalDir.h" +#include "VTI12Gui/VP1Authenticator.h" +#include "VTI12Gui/VP1Prioritiser.h" +#include "VTI12Gui/VP1MainWindow.h" +#include "VTI12Gui/VP1ChannelManager.h" +#include "VTI12Gui/VP1TabManager.h" + +#include "VP1Base/VP1QtUtils.h" +#include "VP1Base/IVP1System.h" +#include "VP1Base/VP1QtUtils.h" +#include "VP1Base/IVP1ChannelWidget.h" +#include "VP1Base/VP1Msg.h" +#include "VP1Base/VP1HelperClassBase.h" +#include "VP1Base/VP1AthenaPtrs.h" +#include "VP1Base/VP1Settings.h" + +#include "VP1UtilsBase/VP1BatchUtilities.h" + +#include <QApplication> +#include <QProgressBar> +#include <QDesktopWidget> +#include <QMouseEvent> +#include <QWheelEvent> +#include <QCursor> +#include <QTimer> +#include <QSet> +#include <QStringList> +#include <QMessageBox> +#include <QCommandLineParser> + +#include <Inventor/C/errors/debugerror.h> +#include <Inventor/Qt/SoQt.h> + +#include <set> +#include <cassert> +#include <iostream> //For "widgetcount" output +#include <sstream> // std::ostringstream +#include <ctime> +#include <stdexcept> +#include <string> +#include <vector> + + + +std::vector<std::string> qstringlistToVecString(QStringList list) +{ + std::vector<std::string> vec; + foreach(QString str, list) { + vec.push_back(str.toStdString()); + } + return vec; +} + + +#ifdef BUILDVP1LIGHT + //Qt + #include <QSettings> + + // XAOD + #include "xAODRootAccess/Init.h" + #include "xAODRootAccess/TEvent.h" + #include "xAODRootAccess/TStore.h" + #include "xAODRootAccess/tools/Message.h" + #include "xAODRootAccess/TAuxStore.h" + #include "xAODCore/AuxContainerBase.h" + #include "xAODCore/tools/ReadStats.h" + #include "xAODCore/tools/IOStats.h" + + // // For testing + #include "xAODEventInfo/EventInfo.h" + #include <QDebug> + #include "xAODRootAccessInterfaces/TActiveEvent.h" + #include "xAODRootAccessInterfaces/TVirtualEvent.h" + #include <TTree.h> + #include <regex> + #include <QString> + + // ROOT include(s): + #include <TTree.h> + #include <TFile.h> + #include <TError.h> + + template <typename... Args> inline void unused(Args&&...) {} // to declare unused variables (see executeNewEvent() ). +#endif // BUILDVP1LIGHT + + + +//___________________________________________________________________ +class VP1ExecutionScheduler::Imp { +public: + class GlobalEventFilter;//Used to animate mouse clicks (for screencasts); + GlobalEventFilter * globalEventFilter; + + VP1ExecutionScheduler * scheduler; + VP1Prioritiser * prioritiser; + VP1MainWindow* mainwindow; + + long int eventsProcessed; + + bool batchMode; + bool batchModeAllEvents; + int batchModeNEvents; + bool batchModeRandomConfig; + VP1BatchUtilities* batchUtilities; + + VP1AvailEvents * availEvents; + + QTimer * refreshtimer; + IVP1System* currentsystemrefreshing; + bool allSystemsRefreshed; + bool goingtonextevent; + + //Statusbar: + QProgressBar * pb; + double calctimethisevent; + double currentrefreshsystemestimate; + void updateProgressBar(); + QTimer * pbtimer; + + //When receiving erase requests for a system that is currently refreshing, we use this: + bool eraseJustAfterRefresh; + IVP1ChannelWidget* postponedUncreateAndDeleteCW; + + CruiseMode cruisemode; + QTimer * cruisetimer; + bool allVisibleRefreshed() const; + bool allSoonVisibleRefreshed() const; + void initCruise(); + void performPostRefreshCruiseActions(IVP1ChannelWidget*cw); + bool cruisetab_waitingtoproceed; + + static void warnIfWidgetsAlive(); + + QString nextRequestedEvent; + + bool skipEvent; +}; + +//___________________________________________________________________ +class VP1ExecutionScheduler::Imp::GlobalEventFilter : public QObject { +public: + GlobalEventFilter():m_lastPopup(QTime::currentTime()), + m_lastPopupWasQMenu(false){} + bool eventFilter ( QObject * watched, QEvent * event ) { + if (event->type()==QEvent::MouseButtonPress + ||event->type()==QEvent::MouseButtonDblClick + ||event->type()==QEvent::Wheel) { + QTime t = QTime::currentTime(); + int timediff(abs(t.msecsTo(m_lastPopup))); + int timecut(m_lastPopupWasQMenu?300:100); + if (timediff>timecut) { + m_lastPopup = t; + QString txt; + QMouseEvent*mouseEvent = dynamic_cast<QMouseEvent*>(event); + if (mouseEvent) { + txt = event->type()==QEvent::MouseButtonDblClick?"Dbl-click" + :(mouseEvent->button()&Qt::LeftButton?"Left-click" + :(mouseEvent->button()&Qt::RightButton?"Right-click":"Middle-click")); + } else { + QWheelEvent * wheelEvent = dynamic_cast<QWheelEvent*>(event); + if (wheelEvent) + txt = "wheel"; + else + txt = "Unknown event"; + } + // std::cout<<"Popup (dt="<<timediff<<") "<<txt.toStdString()<<". watched = "<<watched + // <<" (on="<<watched->objectName().toStdString()<<")" + // <<" (cn="<<watched->metaObject()->className()<<")" + // <<std::endl; + QLabel * label = new QLabel(txt,0,Qt::Tool|Qt::FramelessWindowHint + |Qt::X11BypassWindowManagerHint|Qt::WindowStaysOnTopHint); + label->setStyleSheet("background-color: yellow;color: black;" + "font: bold 140%;border: 2px solid black"); + //"border-radius: 3px;" + label->setFrameStyle(QFrame::StyledPanel); + label->setAttribute(Qt::WA_ShowWithoutActivating); + label->setFocusPolicy(Qt::NoFocus); + QPoint p(QCursor::pos().x()-label->sizeHint().width()/2,QCursor::pos().y()-label->sizeHint().height()); + label->move(p); + QTimer::singleShot(0,label,SLOT(show())); + QTimer::singleShot(500, label, SLOT(deleteLater())); + m_lastPopupWasQMenu = (dynamic_cast<QMenu*>(watched)!=0); + } + } + return false; + } +private: + QTime m_lastPopup; + bool m_lastPopupWasQMenu; +}; + +//___________________________________________________________________ +VP1ExecutionScheduler::VP1ExecutionScheduler( QObject * parent, + StoreGateSvc* eventStore, + StoreGateSvc* detStore, + ISvcLocator* svcLocator, + IToolSvc*toolSvc, + VP1AvailEvents * availEvents) +: QObject(parent), m_d(new Imp) +{ + m_d->availEvents = availEvents; + VP1AthenaPtrs::setPointers(eventStore,detStore,svcLocator,toolSvc); + m_d->eventsProcessed = 0; + + m_d->scheduler = this; + m_d->prioritiser = new VP1Prioritiser(this); + m_d->mainwindow = new VP1MainWindow(this,availEvents);//mainwindow takes ownership of available events + + m_d->batchMode = false; + m_d->batchUtilities = nullptr; + m_d->batchModeAllEvents = false; + m_d->batchModeNEvents = 0; + m_d->batchModeRandomConfig = false; + + m_d->allSystemsRefreshed = false; + m_d->goingtonextevent=true; + m_d->currentsystemrefreshing=0; + m_d->eraseJustAfterRefresh=false; + m_d->postponedUncreateAndDeleteCW=0; + m_d->refreshtimer = new QTimer(this); + connect(m_d->refreshtimer, SIGNAL(timeout()), this, SLOT(processSystemForRefresh())); + + //Connect signals to ensure that prioritiser knows about present channels and their visibility: + connect(m_d->mainwindow->channelManager(),SIGNAL(newChannelCreated(IVP1ChannelWidget*)),m_d->prioritiser, SLOT(channelCreated(IVP1ChannelWidget*))); + connect(m_d->mainwindow->channelManager(),SIGNAL(channelUncreated(IVP1ChannelWidget*)),m_d->prioritiser, SLOT(channelUncreated(IVP1ChannelWidget*))); + connect(m_d->mainwindow->channelManager(),SIGNAL(newChannelCreated(IVP1ChannelWidget*)),this, SLOT(channelCreated(IVP1ChannelWidget*))); + connect(m_d->mainwindow->channelManager(),SIGNAL(channelUncreated(IVP1ChannelWidget*)),this, SLOT(channelUncreated(IVP1ChannelWidget*))); + + connect(m_d->mainwindow->tabManager(),SIGNAL(visibleChannelsChanged(const QSet<IVP1ChannelWidget*>&,const QSet<IVP1ChannelWidget*>&,const double&)), + m_d->prioritiser,SLOT(visibleChannelsChanged(const QSet<IVP1ChannelWidget*>&,const QSet<IVP1ChannelWidget*>&,const double&))); + + + // Init and show the main window of VP1 + SoQt::init( m_d->mainwindow );// SoQt::init( "VP1" ); + + // check if 'batch mode' + bool batchMode = VP1QtUtils::environmentVariableIsSet("VP1_BATCHMODE"); // ::getenv("VP1_BATCHMODE"); + if(VP1Msg::debug()){ + qDebug() << "VP1ExecutionScheduler:: Do we run in 'batch' mode?" << batchMode; + } + if (batchMode) { + VP1Msg::messageWarningAllRed("User has run VP1 in 'batch-mode', so the main window of the program will not be shown."); + m_d->batchMode = true; + + // check if the user set the "all events" option as well + m_d->batchModeAllEvents = VP1QtUtils::environmentVariableIsSet("VP1_BATCHMODE_ALLEVENTS"); + + // check if the user set the "random configuration file" option as well + m_d->batchModeRandomConfig = VP1QtUtils::environmentVariableIsSet("VP1_BATCHMODE_RANDOMCONFIG"); + } + else { + m_d->mainwindow->show(); + } + + + m_d->pb = m_d->mainwindow->progressbar; + m_d->pbtimer = new QTimer(this); + connect(m_d->pbtimer, SIGNAL(timeout()), this, SLOT(updateProgressBarDuringRefresh())); + m_d->calctimethisevent=0; + m_d->currentrefreshsystemestimate=0; + + m_d->cruisemode = NONE; + m_d->cruisetimer = new QTimer(this); + connect(m_d->cruisetimer, SIGNAL(timeout()), this, SLOT(performCruise())); + m_d->cruisetab_waitingtoproceed=false; + + #if defined BUILDVP1LIGHT + bool checkDisplayMouseClicks = VP1QtUtils::expertSettingIsOn("general","ExpertSettings/VP1_DISPLAY_MOUSE_CLICKS"); + #else + bool checkDisplayMouseClicks = VP1QtUtils::environmentVariableIsOn("VP1_DISPLAY_MOUSE_CLICKS"); + #endif + + if (checkDisplayMouseClicks) { + m_d->globalEventFilter = new Imp::GlobalEventFilter; + qApp->installEventFilter(m_d->globalEventFilter); + } else { + m_d->globalEventFilter = 0; + } + + VP1AvailEvtsHttps* availEvtsHttps = dynamic_cast<VP1AvailEvtsHttps*>(availEvents); + if(availEvtsHttps) { + m_d->skipEvent = true; + VP1Authenticator* auth = new VP1Authenticator(m_d->mainwindow,availEvtsHttps->fileinfoLocation()); + + connect(auth,SIGNAL(authenticationSuccessful(QNetworkAccessManager*)), + availEvtsHttps,SLOT(start(QNetworkAccessManager*))); + connect(availEvtsHttps,SIGNAL(freshEventsChanged()), + auth,SLOT(accept())); + + SoQt::init(auth); + auth->exec(); + delete auth; + } + else + m_d->skipEvent = false; +} + +//___________________________________________________________________ +VP1ExecutionScheduler::~VP1ExecutionScheduler() +{ + m_d->refreshtimer->stop(); + delete m_d->batchUtilities; + delete m_d->mainwindow; + delete m_d->prioritiser; + delete m_d->globalEventFilter; + delete m_d; +} + +//___________________________________________________________________ +VP1ExecutionScheduler* VP1ExecutionScheduler::init( StoreGateSvc* eventStore, + StoreGateSvc* detStore, + ISvcLocator* svcLocator, + IToolSvc*toolSvc, + QStringList joboptions, + QString initialCruiseMode, + unsigned initialCruiseSeconds, + QString singleEventSource, + QString singleEventLocalTmpDir, + unsigned localFileCacheLimit, + QStringList availableLocalInputDirectories ) +{ + //First we make sure the DISPLAY variable is set (importing ROOT in + //athena.py might cause it to be unset!). + // + //NB: The following might only be relevant in X11 build: + if (VP1QtUtils::environmentVariableValue("DISPLAY").isEmpty()) { + const bool unset(!VP1QtUtils::environmentVariableIsSet("DISPLAY")); + QString alternative = VP1QtUtils::environmentVariableValue("DISPLAY_ORIG"); + if (alternative.isEmpty()) { + VP1Msg::message("ERROR: The DISPLAY environment variable is "+QString(unset?"not set":"empty")+"."); + VP1Msg::message("This is likely due to perfmon being turned on (cf. https://savannah.cern.ch/bugs/?35461 )."); + VP1Msg::message("You can work around this problem by either disabling perfmon, or by setting " + "the DISPLAY_ORIG environment variable to the contents of DISPLAY before launching your job."); + VP1Msg::message("E.g., in bash do:"); + VP1Msg::message(" export DISPLAY_ORIG=$DISPLAY"); + VP1Msg::message(""); + VP1Msg::message("For the current job, I will try with DISPLAY=\":0.0\", which is the correct value when running locally."); + alternative=":0.0"; + } else { + VP1Msg::message("WARNING: The DISPLAY environment variable is "+QString(unset?"not set":"empty")+". Setting to value found in DISPLAY_ORIG"); + } + VP1Msg::message("WARNING: Setting DISPLAY variable to '"+alternative+"'"); + VP1QtUtils::setEnvironmentVariable("DISPLAY",alternative); + } + + + + QCoreApplication::setOrganizationName("FASER"); + #if defined BUILDVP1LIGHT + QCoreApplication::setApplicationName("VP1Light"); + #else + QCoreApplication::setApplicationName("VTI12"); + #endif + QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL); + + + + // here we check if the main (and unique!) Qt application has been initialized already. If not we initialize it. + if (qApp) { + VP1Msg::message("VP1ExecutionScheduler::init ERROR: QApplication already initialized. Expect problems!!!"); + } else { + //NB: Static to avoid scope-problems: + static int argc=1; + static char execpath[] = "/some/fake/executable/vp1"; + static char *argv[2]; + // VP1Msg::messageDebug("setting argv[0]..."); + argv[0] = execpath; + // VP1Msg::messageDebug("setting argv[1]..."); + argv[1] = NULL; + // instead of using the default Qt QApplication class, + // we now use our custom inherited class where we + // reimplemented the notify() method, in order to catch + // C++ exceptions, especially while running it inside Athena. + //new QApplication(argc, argv); + new VP1QtApplication(argc, argv); + } + + VP1AvailEvents * availEvents(0); + if (!singleEventSource.isEmpty()&&!singleEventLocalTmpDir.isEmpty()) { + const bool httpmode = singleEventSource.startsWith("http://"); + const bool httpsmode = singleEventSource.startsWith("https://"); + //Create appropriate instance: + if (httpmode) { + availEvents = new VP1AvailEvtsHttp(singleEventSource, 60/*update interval*/, 30*60/*time cut for new*/, singleEventLocalTmpDir,localFileCacheLimit); + } else if(httpsmode) { + availEvents = new VP1AvailEvtsHttps(singleEventSource, 1000/*update interval*/, 30*60/*time cut for new*/, singleEventLocalTmpDir,localFileCacheLimit); + } else { + availEvents = new VP1AvailEvtsLocalDir(5*60/*time cut for new*/, singleEventSource, + singleEventLocalTmpDir,localFileCacheLimit); + static_cast<VP1AvailEvtsLocalDir*>(availEvents)->setAvailableSourceDirectories(availableLocalInputDirectories); + + } + + } + + VP1ExecutionScheduler*scheduler = new VP1ExecutionScheduler(0,eventStore,detStore,svcLocator,toolSvc,availEvents); + + //Pass on "joboptions" + if (joboptions.empty()) { + //scheduler->m_d->mainwindow->tabManager()->addNewTab("My Tab"); + } else { + qDebug() << "config files: " << joboptions; // DEBUG + foreach(QString opt,joboptions) + scheduler->m_d->mainwindow->loadConfigurationFromFile(opt); + + if ( scheduler->m_d->batchMode ) { + if (scheduler->m_d->batchModeRandomConfig ) { + if (joboptions.size() != 0 ) { + scheduler->m_d->batchUtilities = new VP1BatchUtilities( qstringlistToVecString(joboptions) ); + } + } + QString batchNevents = VP1QtUtils::environmentVariableValue("VP1_BATCHMODE_NEVENTS"); + if (batchNevents > 0 ) { + scheduler->m_d->batchModeNEvents = batchNevents.toInt(); + } + } + } + + + if (scheduler->m_d->mainwindow->tabWidget_central->count()<=1) { + if (initialCruiseMode=="TAB") { + VP1Msg::message("ERROR: Can not start in cruisemode TAB unless there are at least 2 tabs loaded from initial .vp1 files. Reverting to cruise mode NONE."); + initialCruiseMode="NONE"; + } else if (initialCruiseMode=="BOTH") { + VP1Msg::message("ERROR: Can not start in cruisemode BOTH unless there are at least 2 tabs loaded from initial .vp1 files. Reverting to cruise mode EVENT."); + initialCruiseMode="EVENT"; + } + } + + //Set default value of cruisemode (dont use setCruiseMode() since it starts timers): + if (initialCruiseMode=="EVENT") { + scheduler->m_d->cruisemode=EVENT; + scheduler->m_d->mainwindow->radioButton_cruise_event->setChecked(true); + scheduler->m_d->mainwindow->pushButton_cruise->setChecked(true); + + } else if (initialCruiseMode=="TAB") { + scheduler->m_d->cruisemode=TAB; + scheduler->m_d->mainwindow->radioButton_cruise_tab->setChecked(true); + scheduler->m_d->mainwindow->pushButton_cruise->setChecked(true); + } else if (initialCruiseMode=="BOTH") { + scheduler->m_d->cruisemode=BOTH; + scheduler->m_d->mainwindow->radioButton_cruise_both->setChecked(true); + scheduler->m_d->mainwindow->pushButton_cruise->setChecked(true); + } else { + if (initialCruiseMode!="NONE") + VP1Msg::message("ERROR: unknown initial cruise mode "+initialCruiseMode+" (valid are NONE/EVENT/TAB/BOTH). Assuming NONE."); + scheduler->m_d->cruisemode=NONE; + scheduler->m_d->mainwindow->radioButton_cruise_event->setChecked(true); + scheduler->m_d->mainwindow->pushButton_cruise->setChecked(false); + } + + scheduler->m_d->mainwindow->request_cruisemodechange(); + + int cruisesecs = ( initialCruiseSeconds == 0 ? 0 : + std::max(scheduler->m_d->mainwindow->spinBox_cruise->minimum(), + std::min(scheduler->m_d->mainwindow->spinBox_cruise->maximum(), + static_cast<int>(initialCruiseSeconds)))); + if ( cruisesecs>0 ) + scheduler->m_d->mainwindow->spinBox_cruise->setValue(cruisesecs); + + + return scheduler; +} + +//___________________________________________________________________ +void VP1ExecutionScheduler::cleanup(VP1ExecutionScheduler*scheduler) +{ + #if defined BUILDVP1LIGHT + bool checkEnableInformOnEndOfJob = VP1QtUtils::expertSettingIsOn("expert","ExpertSettings/VP1_ENABLE_INFORM_ON_END_OF_JOB"); + #else + bool checkEnableInformOnEndOfJob = VP1QtUtils::environmentVariableIsOn("VP1_ENABLE_INFORM_ON_END_OF_JOB"); + #endif + + if (checkEnableInformOnEndOfJob && ( !scheduler||!(scheduler->m_d->mainwindow->userRequestedExit()) ) ) + QMessageBox::information(0, "End of job reached",Qt::convertFromPlainText("Job about to end.\n\nThis is most" + " likely since there are no more available events to process."),QMessageBox::Ok,QMessageBox::Ok); + + if (scheduler) { + delete scheduler; +// qApp->processEvents(QEventLoop::DeferredDeletion); // Qt 4 + qApp->processEvents(); // Qt 5 + qApp->deleteLater(); // Qt 5 + + Imp::warnIfWidgetsAlive(); + VP1HelperClassBase::warnUndeletedInstances(); + + delete qApp; + SoQt::done(); + } + + + + const QString quickExitEnv("VP1_HARD_EXIT_AT_END"); + + #if defined BUILDVP1LIGHT + bool checkHardExitAtEnd = VP1QtUtils::expertSettingIsOn("expert","ExpertSettings/"+quickExitEnv); + #else + bool checkHardExitAtEnd = VP1QtUtils::environmentVariableIsOn(quickExitEnv); + #endif + + if (checkHardExitAtEnd) { + VP1Msg::message("Hard job exit (unset "+quickExitEnv+" to disable this behaviour)."); + exit(0); + } + +} + +//___________________________________________________________________ +void VP1ExecutionScheduler::Imp::updateProgressBar() +{ + double remaining = prioritiser->estimateRemainingCalcTime(); + if (remaining>0.0) { + pb->setMaximum(static_cast<int>((calctimethisevent+remaining)*10.0)); + pb->setValue(static_cast<int>((calctimethisevent)*10.0)); + pb->show(); + if (!pbtimer->isActive()) + pbtimer->start(40);//25 "frames"/second. If it is good enough for TV, it is good enough for us. + } else { + calctimethisevent=0.0; + pb->hide(); + pb->reset(); + pbtimer->stop(); + } +} +//___________________________________________________________________ +void VP1ExecutionScheduler::updateProgressBarDuringRefresh() +{ + if (m_d->currentrefreshsystemestimate<1.0) + return; + double timing=(m_d->prioritiser->elapsedTiming_Refresh())*0.95;//The *0.95 is to give a smoother overall impression. + if (timing>m_d->currentrefreshsystemestimate) + return; + m_d->pb->setValue(static_cast<int>((m_d->calctimethisevent+timing)*10.0)); +} + + +//___________________________________________________________________ +QString VP1ExecutionScheduler::nextRequestedEventFile() const +{ + return m_d->nextRequestedEvent; +} + +//___________________________________________________________________ +void VP1ExecutionScheduler::setNextRequestedEventFile(const QString& f) +{ + m_d->nextRequestedEvent = f; +} + +//___________________________________________________________________ +bool VP1ExecutionScheduler::executeNewEvent(const int& runnumber, const unsigned long long& eventnumber, const unsigned& triggerType, const unsigned& time) +{ + VP1Msg::messageDebug("VP1ExecutionScheduler::executeNewEvent()"); + + m_d->nextRequestedEvent=""; + +#if defined BUILDVP1LIGHT + unused(runnumber,eventnumber,triggerType,time); // silences the "unused parameter" warnings when building VP1Light. In this case, in fact, those variables will be used later in loadEvent(). + if ( !firstlaunch ) { + if ( (getEvtNr() >= 0) && (getEvtNr() < m_totEvtNr) ) { // If selected event number is available in file + loadEvent(); + //Pass the event to the AOD System + std::set<IVP1System *>::iterator itsys, itsysE = m_d->mainwindow->tabManager()->selectedChannelWidget()->systems().end(); + for (itsys = m_d->mainwindow->tabManager()->selectedChannelWidget()->systems().begin();itsys!=itsysE;++itsys) { + if((*itsys)->name()=="Analysis"){ + passEvent(*itsys); + } + } + } + else if ( (getEvtNr() < 0) && (getEvtNr() >= m_totEvtNr) ) { + QMessageBox msgBox; + msgBox.setWindowTitle("No more events"); + msgBox.setText("There are no more events in this file. Returning to previous event."); + msgBox.setIcon(QMessageBox::Icon::Information); + msgBox.exec(); + } + } + else{ + firstlaunch = false; + } +#else + m_d->mainwindow->setRunEvtNumber(runnumber, eventnumber, triggerType, time, !m_d->skipEvent); +#endif + + m_d->goingtonextevent = false; + m_d->calctimethisevent=0; + m_d->currentrefreshsystemestimate=0; + m_d->updateProgressBar(); + + assert(!m_d->refreshtimer->isActive());//fixme: -> if. + + + VP1Msg::messageDebug("calling refreshtimer->start()..."); + m_d->refreshtimer->start(); + + VP1Msg::messageDebug("calling initCruise..."); + m_d->initCruise(); + VP1Msg::messageDebug("initCruise called."); + + //Flush event queue before reenabling controllers, etc.: + qApp->processEvents(); + VP1Msg::messageDebug("qApp->processEvents() called."); + + //Enable various user input: + m_d->mainwindow->groupBox_channelcontrols->setEnabled(true); + m_d->mainwindow->groupBox_cruise->setEnabled(true); + m_d->mainwindow->groupBox_event->setEnabled(true); + + + VP1Msg::messageDebug("batch mode: " + QString::number(m_d->batchMode)); + + if (m_d->batchModeRandomConfig) { + VP1Msg::messageDebug("User chose 'batch' and 'batch-random-config'. So we now replace the configuration with a random one from the input set..."); + QString randomConfigFile = QString::fromStdString( m_d->batchUtilities->getRandomConfigFile() ); + m_d->mainwindow->replaceConfigurationFile(randomConfigFile); + } + + if ( m_d->batchMode && m_d->allVisibleRefreshed() ) { // or m_d->allSystemsRefreshed ??? + VP1Msg::messageDebug("We're in batch mode, skipping the execution of the GUI..."); + } else { + VP1Msg::messageDebug("skipEvent: " + QString::number(m_d->skipEvent)); + if(m_d->skipEvent) { + VP1Msg::messageDebug("skipEvent"); + m_d->skipEvent=false; + m_d->mainwindow->nextEvent(); + } + else { + VP1Msg::messageDebug("calling qApp->exec()..."); + qApp->exec();//NOTE!!! We then exit the exec() when someone pushes the "next event" button. + } + } + + VP1Msg::messageDebug("Disabling user inputs..."); + //Disable various user input: + m_d->mainwindow->groupBox_channelcontrols->setEnabled(false); + m_d->mainwindow->groupBox_cruise->setEnabled(false); + m_d->mainwindow->groupBox_event->setEnabled(false); + + m_d->goingtonextevent = true; + + if (m_d->refreshtimer->isActive()) { + m_d->refreshtimer->stop(); + } + m_d->pb->hide(); + m_d->pb->reset(); + m_d->pbtimer->stop(); + //Fixme: Refresh all accumulators that still needs refresh (or just have the button disabled until now) + + //Fixme: wait here until end of any active refreshing... + + VP1Msg::messageDebug("Erasing systems..."); + assert(!m_d->currentsystemrefreshing); + foreach(IVP1System*s,m_d->prioritiser->getSystemsToEraseByPriority()) { + qApp->processEvents(QEventLoop::ExcludeUserInputEvents|QEventLoop::ExcludeSocketNotifiers); + eraseSystem(s); + } + + ++m_d->eventsProcessed; // we don't use Athena's tools for this, so we can use this in VP1Light as well. + VP1Msg::messageDebug("event processed. " + QString::number(m_d->eventsProcessed) + " events processed so far."); + + //Let channels know we are going to the next event now: + foreach(IVP1ChannelWidget*cw, m_d->mainwindow->tabManager()->allChannels()) { + cw->goingToNextEvent(); + } + + qApp->processEvents(QEventLoop::ExcludeUserInputEvents|QEventLoop::ExcludeSocketNotifiers); + + + VP1Msg::messageDebug("mainwindow->mustQuit ? " + QString::number(m_d->mainwindow->mustQuit()) ); + return !m_d->mainwindow->mustQuit(); +} + +//___________________________________________________________________ +void VP1ExecutionScheduler::eraseSystem(IVP1System*s) { + + VP1Msg::messageDebug("VP1ExecutionScheduler::eraseSystem()"); + + assert(s->state()==IVP1System::REFRESHED); + assert(!s->isRefreshing()); + + QString base = QString(s->name())+" from channel "+s->channel()->unique_name(); + m_d->mainwindow->statusBar()->showMessage( "Erasing system ["+base+"]" ); + VP1Msg::messageDebug("ERASING - " + base); + + s->disallowUpdateGUI(); + s->erase();//fixme: time? + s->setState(IVP1System::ERASED); + m_d->mainwindow->statusBar()->showMessage( "Post-erase update to channel ["+base+"]" ); + s->channel()->systemErased(s);//fixme: time? + m_d->mainwindow->statusBar()->clearMessage(); +} + +//___________________________________________________________________ +void VP1ExecutionScheduler::systemNeedErase() { + IVP1System*s = static_cast<IVP1System*>(sender()); + assert(s); + if (m_d->currentsystemrefreshing!=s) { + eraseSystem(s); + } else { + assert(s->isRefreshing()); + m_d->eraseJustAfterRefresh=true; + } +} + +//___________________________________________________________________ +void VP1ExecutionScheduler::processSystemForRefresh() +{ + assert(!m_d->goingtonextevent); + if (m_d->currentsystemrefreshing) + return; + + IVP1System * s = m_d->prioritiser->nextErasedActiveSystemByPriority(); + if (s) { + refreshSystem(s); + } else { + assert(m_d->refreshtimer->isActive());//fixme: -> if. ??? + //if (refreshtimer->isActive()) + m_d->refreshtimer->stop(); + m_d->pb->hide(); + m_d->pb->reset(); + m_d->pbtimer->stop(); + } +} + +//___________________________________________________________________ +void VP1ExecutionScheduler::channelCreated(IVP1ChannelWidget* cw) +{ + std::set<IVP1System*>::const_iterator it, itE = cw->systems().end(); + for (it=cw->systems().begin();it!=itE;++it) { + qInfo() << "System name:" << (*it)->name(); + connect(*it,SIGNAL(inactiveSystemTurnedActive()),this,SLOT(startRefreshQueueIfAppropriate())); + connect(*it,SIGNAL(needErase()),this,SLOT(systemNeedErase())); + #ifdef BUILDVP1LIGHT + connect(*it,SIGNAL(signalLoadEvent(IVP1System*)),this,SLOT(passEvent(IVP1System*))); + #endif // BUILDVP1LIGHT + } + startRefreshQueueIfAppropriate(); + +} + +//___________________________________________________________________ +void VP1ExecutionScheduler::channelUncreated(IVP1ChannelWidget* cw) +{ + std::set<IVP1System*>::const_iterator it, itE = cw->systems().end(); + for (it=cw->systems().begin();it!=itE;++it) + disconnect(*it,SIGNAL(inactiveSystemTurnedActive()),this,SLOT(startRefreshQueueIfAppropriate())); +} + +//___________________________________________________________________ +void VP1ExecutionScheduler::startRefreshQueueIfAppropriate() +{ + if (!m_d->goingtonextevent&&!m_d->refreshtimer->isActive()) + m_d->refreshtimer->start(); +} + +//___________________________________________________________________ +bool VP1ExecutionScheduler::isRefreshing() const +{ + return m_d->currentsystemrefreshing; +} + +//___________________________________________________________________ +void VP1ExecutionScheduler::refreshSystem(IVP1System*s) +{ + QString sysname = s->name(); + VP1Msg::messageDebug("VP1ExecutionScheduler::refreshSystem() - system: " + sysname); + + m_d->updateProgressBar(); + + assert(s->state()==IVP1System::ERASED); + assert(s->activeState()==IVP1System::ON); + assert(!m_d->currentsystemrefreshing); + + m_d->currentrefreshsystemestimate = m_d->prioritiser->beginTiming_Refresh(s); + m_d->currentsystemrefreshing = s; + + QString base = QString(s->name())+" from channel "+s->channel()->unique_name(); + m_d->mainwindow->statusBar()->showMessage( "Refreshing system ["+base+"]" ); + + s->allowUpdateGUI(); + s->setRefreshing(true); + refreshingStatusChanged(true); + s->channel()->emitRefreshInfoChanged(); + s->refresh(VP1AthenaPtrs::eventStore()); + s->setState(IVP1System::REFRESHED); + s->setRefreshing(false); + s->disallowUpdateGUI(); + + m_d->mainwindow->statusBar()->showMessage( "Post-refresh update to channel ["+base+"]" ); + s->channel()->systemRefreshed(s);//fixme: time independently? + + m_d->mainwindow->statusBar()->clearMessage(); + m_d->currentsystemrefreshing = 0; + m_d->calctimethisevent += m_d->prioritiser->endTiming_Refresh(); + m_d->currentrefreshsystemestimate=0; + m_d->updateProgressBar(); + + refreshingStatusChanged(false); + s->channel()->emitRefreshInfoChanged(); + + VP1Msg::messageDebug("checking if all systems have refreshed..."); + if (hasAllActiveSystemsRefreshed(s->channel())) { + + VP1Msg::messageDebug("All systems refreshed! - last system refreshed! - system: " + sysname); + s->channel()->lastOfActiveSystemsRefreshed(); + + m_d->allSystemsRefreshed = true; // check if that is fine for multiple channels window: i.e. VP1 instances with a couple of 3DCkocktail windows, for example. + + } // end of hasAllActiveSystemsRefreshed() + + m_d->performPostRefreshCruiseActions(s->channel()); + + if (m_d->eraseJustAfterRefresh) { + //Someone asked to erase the system while it was refreshing! + m_d->eraseJustAfterRefresh=false; + //Check that it still needs to (maybe it was flicked back to ON by the impatient user) + if (s->activeState()==IVP1System::OFF) + eraseSystem(s); + } + if (m_d->postponedUncreateAndDeleteCW) { + actualUncreateAndDelete(m_d->postponedUncreateAndDeleteCW); + m_d->postponedUncreateAndDeleteCW=0; + } + + VP1Msg::messageDebug("end of refreshing the system: " + sysname); + +// // if in "batch mode", now exit from VP1 +// if (m_d->batchMode) { +// +//// if (hasAllActiveSystemsRefreshed(s->channel())) { +//// VP1Msg::messageWarningRed("All systems refreshed!"); +// +// VP1Msg::messageWarningRed("'batch mode'. Now exiting VP1"); +// +// // N.B. calling QApplication::quit() here it makes move to the next event; +// // NOTE!!!! It can be useful for a batch mode on all events of one single file!! +// // TODO: An additional switch to the command line batch option should be implemented +// //QApplication::quit(); +// +// //for the moment, we only quit VP1. +// //To quit the application completely, we have to call "MainWindow::close()" +// m_d->mainwindow->close(); +//// } +// +// } + + // *************************** + // we now run all the things + // that need to be done + // after all tabs are drawn... + // *************************** + if ( hasAllActiveSystemsRefreshed(s->channel()) ) { + + + if (m_d->batchMode) { + + VP1Msg::messageDebug("we are in 'batch-mode'..."); + VP1Msg::messageDebug("batchModeNEvents: " + QString::number(m_d->batchModeNEvents) + " - m_d->eventsProcessed: " + QString::number(m_d->eventsProcessed) ); + + // saving the snapshot of the 3D window to a file + QString save_ok = saveSnaphsotToFile(s, true); + if (save_ok == "") { + VP1Msg::messageWarningAllRed("FAILED! The snapshot for the channel '" + s->channel()->name() + "' has not been saved!"); + } else { + VP1Msg::message("OK! Snapshot saved to file: " + save_ok); + } + + + if (m_d->batchModeAllEvents) { + VP1Msg::messageWarningAllRed("******************************************************************"); + VP1Msg::messageWarningAllRed("'batch mode' with 'all events' option. Moving to the next event..."); + VP1Msg::messageWarningAllRed("******************************************************************"); + // N.B. calling QApplication::quit() here it makes VP1 move to the next event; + QApplication::quit(); + // Now, VP1ExecutionScheduler::executeNewEvent() will end, then VP1Gui::executeNewEvent() will end, then they will start again: first VP1Gui then VP1ExecutionScheduler. + } else if ( m_d->batchModeNEvents > 0 ) { + if ( m_d->batchModeNEvents == m_d->eventsProcessed+1) { // here we use +1 because this is performed after the creation of the event snapshot. //TODO: maybe we can move this to a more natural place, at the beginning or at the end of an event + VP1Msg::messageWarningAllRed("******************************************************************"); + VP1Msg::messageWarningAllRed("'batch mode' with 'batch-n-events' option. Processed the " + QString::number(m_d->eventsProcessed+1) + " events set by the user. Now exiting VP1"); + VP1Msg::messageWarningAllRed("******************************************************************"); + m_d->mainwindow->close(); + } else { + VP1Msg::messageWarningAllRed("'batch mode' with 'batch-n-events' option. Moving to the next event..."); + // N.B. calling QApplication::quit() here it makes VP1 move to the next event; + QApplication::quit(); + // Now, VP1ExecutionScheduler::executeNewEvent() will end, then VP1Gui::executeNewEvent() will end, then they will start again: first VP1Gui then VP1ExecutionScheduler. + } + } + else { + // We come here if the user did not choose to run batch mode on all events. + // Thus, we want to close VP1 completely. + // So, in order to do that, we have to call "MainWindow::close()" + VP1Msg::messageWarningRed("'batch mode'. Done. Now exiting VP1"); + m_d->mainwindow->close(); + } + + + } + } +} + +//___________________________________________________________________ +QString VP1ExecutionScheduler::saveSnaphsotToFile(IVP1System* s, bool batch) +{ + QString chnlname = s->name().toLower(); + VP1Msg::messageDebug("VP1ExecutionScheduler::saveSnaphsotToFile() - taking the snapshot of the channel " + chnlname ); + + QString currentsaveimagepath = VP1Settings::defaultFileSelectDirectory() + QDir::separator(); + + + if (batch) { + + VP1Msg::messageDebug("Note: 'batch-mode'"); + + + // A FOLDER CONTAINER + QString folderName = ""; + + // check if use specified an output folder for the batch job + QString batchOutFolder = VP1QtUtils::environmentVariableValue("VP1_BATCHMODE_OUT_FOLDER"); // ::getenv("VP1_BATCHMODE"); + if ( ! (batchOutFolder == "") ) { + VP1Msg::messageDebug("Setting 'batch' output folder from user's settings"); + folderName = batchOutFolder; + } + else + folderName = "atlas_vp1_batch_images"; + + // check if the folder already exists, if not make a new folder + QDir dir(folderName); + if (!dir.exists()) { + dir.mkpath("."); + } + + QString folder; + if (folderName.startsWith("/")) + folder = folderName + QDir::separator(); + else + folder = currentsaveimagepath + folderName + QDir::separator(); + + VP1Msg::messageDebug("folder set: " + folder); + + + // EVENT INFO AND TIMESTAMP + + QString runnumb = QString::number(m_d->mainwindow->getRunNumber()); + QString evnumb = QString::number(m_d->mainwindow->getEventNumber()); + QString evtimestamp = QString::number(m_d->mainwindow->getEventTimestamp()); + + time_t t_evttimestamp = m_d->mainwindow->getEventTimestamp(); + tm * human_evtimestamp = localtime(&t_evttimestamp); + + std::ostringstream h_evtimestamp_ostri; + h_evtimestamp_ostri << 1900 + human_evtimestamp->tm_year + << "-" << 1 + human_evtimestamp->tm_mon // tm_mon is in the range [0, 11], so 1 must be added to get real months + << "-" << human_evtimestamp->tm_mday + << "T" << human_evtimestamp->tm_hour << "-" << human_evtimestamp->tm_min << "-" << human_evtimestamp->tm_sec << "CEST"; + + std::string h_evtimestamp_str = h_evtimestamp_ostri.str(); + QString h_evtimestamp = QString::fromStdString(h_evtimestamp_str); + + // IMAGE TIMESTAMP + + time_t t_timestamp = time(0); // get time now; + tm *ltm = localtime(&t_timestamp); + + // print various components of tm structure. + VP1Msg::messageDebug( "Year: "+ QString::number(1900 + ltm->tm_year) + + " - " + "Month: " + QString::number(1 + ltm->tm_mon) + " - " // tm_mon is in the range [0, 11], so 1 must be added to get real months + + "Day: " + QString::number(ltm->tm_mday) + + " - " "Time: " + QString::number(ltm->tm_hour) + ":" + QString::number(ltm->tm_min) + ":" + QString::number(ltm->tm_sec) + "CEST"); + + std::ostringstream ostri_unix; + ostri_unix << t_timestamp; + + std::ostringstream ostri; + ostri << 1900 + ltm->tm_year + << "-" << 1 + ltm->tm_mon // tm_mon is in the range [0, 11], so 1 must be added to get real months + << "-" << ltm->tm_mday + << "T" << ltm->tm_hour << "-" << ltm->tm_min << "-" << ltm->tm_sec << "CEST"; + + std::string unixTimestamp = ostri_unix.str(); + std::string humanTimestamp = ostri.str(); + QString q_unixTimestamp = QString::fromStdString(unixTimestamp); + QString q_humanTimestamp = QString::fromStdString(humanTimestamp); + VP1Msg::messageDebug("Unix timestamp: " + q_unixTimestamp ); + VP1Msg::messageDebug("'human readable' timestamp: " + q_humanTimestamp ); + + /* channel's name is the name of the last channel updated by the executer, + * i.e. the name changes according to the order the channels are refreshed. + * Thus, we don't use the channel's name in the filename, + * because it could be misleading. + */ + //QString filename = currentsaveimagepath + "vp1_" + chnlname + "_snapshot_" + q_humanTimestamp + ".png"; + QString filename = folder + "vp1_batch_snapshot_r" + runnumb + "_ev" + evnumb + "_evtime_H" + h_evtimestamp + "_U" + evtimestamp + "___imgtime_H" + q_humanTimestamp + "_U" + q_unixTimestamp + ".png"; + + // taking the actual snapshot + QPixmap pm = s->channel()->getSnapshot(); + if (pm.isNull()) { + VP1Msg::messageDebug("QPixmap is null! returning..."); + return QString(); + } + + // saving to file + pm.save(filename); + + // save last-saved image filename to working dir + QString latestImageFileName = currentsaveimagepath + QString("latest_vp1image"); + QFile latestImage(latestImageFileName); + if(latestImage.exists() && !latestImage.remove()) + throw std::runtime_error("Unable to overwrite the existing latest image file"); + if(!latestImage.open(QIODevice::WriteOnly | QIODevice::Text)) + throw std::runtime_error("Unable to create new latest image file"); + latestImage.write(filename.toStdString().c_str()); + latestImage.close(); + + + return filename; + } + + // default exit + return QString();//filename; + +} + + + +//___________________________________________________________________ +void VP1ExecutionScheduler::bringFromConstructedToReady(IVP1ChannelWidget*cw) +{ + assert(cw->state()==IVP1ChannelWidget::CONSTRUCTED); + + connect(cw,SIGNAL(message(const QString&)),m_d->mainwindow,SLOT(channelAddToMessageBox(const QString&))); + + std::set<IVP1System *>::iterator itsys, itsysE = cw->systems().end(); + for (itsys = cw->systems().begin();itsys!=itsysE;++itsys) { + assert((*itsys)->state()==IVP1System::CONSTRUCTED); + connect((*itsys),SIGNAL(sysmessage(const QString&)),m_d->mainwindow,SLOT(systemAddToMessageBox(const QString&))); + } + itsysE = cw->systems().end(); + for (itsys = cw->systems().begin();itsys!=itsysE;++itsys) { + (*itsys)->setCanRegisterController(true); + (*itsys)->create(VP1AthenaPtrs::detectorStore()); + (*itsys)->setCanRegisterController(false); + (*itsys)->setState(IVP1System::ERASED); + } + assert(cw->state()==IVP1ChannelWidget::CONSTRUCTED); + cw->setCanRegister(true,false);//Ok to register controllers during create. + cw->create(); + cw->setCanRegister(false,false); + cw->setState(IVP1ChannelWidget::READY); + + assert(cw->state()==IVP1ChannelWidget::READY); + //Fixme: statusbar!!!!! +} + +//___________________________________________________________________ +void VP1ExecutionScheduler::uncreateAndDelete(IVP1ChannelWidget*cw) +{ + assert(cw->state()==IVP1ChannelWidget::READY); + if (m_d->currentsystemrefreshing&&cw->systems().find(m_d->currentsystemrefreshing)!=cw->systems().end()) { + assert(!m_d->postponedUncreateAndDeleteCW); + m_d->postponedUncreateAndDeleteCW=cw; + } else { + actualUncreateAndDelete(cw); + } +} + +//___________________________________________________________________ +void VP1ExecutionScheduler::actualUncreateAndDelete(IVP1ChannelWidget*cw) +{ + assert(cw->state()==IVP1ChannelWidget::READY); + cw->setUpdatesEnabled(false);//Just because... + + //From this point on, we are not interested in signals from the channel (and its systems) that could disturb us: + std::set<IVP1System *>::iterator itsys, itsysE = cw->systems().end(); + for (itsys = cw->systems().begin();itsys!=itsysE;++itsys) { + (*itsys)->blockSignals(true); + disconnect(*itsys,0,0,0); + } + cw->blockSignals(true); + disconnect(cw,0,0,0); + + //Make sure that all systems gets in the ERASED state. Throw assert if any is presently refreshing (BAD PROGRAMMER!!) + for (itsys = cw->systems().begin();itsys!=itsysE;++itsys) { + assert(m_d->currentsystemrefreshing!=(*itsys)); + if ((*itsys)->state()==IVP1System::REFRESHED) + eraseSystem(*itsys); + } + + //Uncreate systems: + for (itsys = cw->systems().begin();itsys!=itsysE;++itsys) { + assert((*itsys)->state()==IVP1System::ERASED); + (*itsys)->uncreate(); + (*itsys)->setState(IVP1System::UNCREATED); + } + + //Uncreate channel: + assert(cw->state()==IVP1ChannelWidget::READY); + cw->uncreate();//Fixme: Return codes!! + cw->setState(IVP1ChannelWidget::UNCREATED); + + assert(cw->state()==IVP1ChannelWidget::UNCREATED); + + cw->deleteControllers();//Also deletes system controllers. + + //Delete: + cw->deleteLater(); + +} + +//___________________________________________________________________ +void VP1ExecutionScheduler::Imp::warnIfWidgetsAlive() +{ + QSet<QWidget*> w_ignore, wl = QApplication::allWidgets().toSet(); + w_ignore<<qApp->desktop(); + foreach (QObject*o,qApp->children()) { + if (o->isWidgetType()) + w_ignore << static_cast<QWidget*>(o); + } + foreach (QWidget * w, wl) { + if (w->objectName().startsWith("internal clipboard")) + w_ignore << w; + if (w->objectName()=="empty_widget") + w_ignore << w; + } + wl.subtract(w_ignore); + if (!wl.empty()) { + std::cout<<std::endl; + std::cout<<"VP1 WARNING: "<<wl.count()<< " widget"<<(wl.count()>1?"s":"")<<" left at end of job:"<<std::endl; + int i(0); + foreach(QWidget*w,wl) { + std::cout<<++i<<") Address="<<w<<", ObjectName="<<w->objectName().toStdString()<<", ClassName="<<w->metaObject()->className()<<std::endl; + } + std::cout<<std::endl; + } +} + +//___________________________________________________________________ +bool VP1ExecutionScheduler::hasAllActiveSystemsRefreshed( IVP1ChannelWidget* cw ) const +{ + VP1Msg::messageDebug("VP1ExecutionScheduler::hasAllActiveSystemsRefreshed() - channelWidget: " + cw->name()); + + std::set<IVP1System*>::const_iterator it, itE = cw->systems().end(); + int i=0; + for (it=cw->systems().begin();it!=itE;++it) { + + /* + * enum State { CONSTRUCTED=0, REFRESHED, ERASED, UNCREATED }; + * enum ActiveState { ON=0, OFF };//Whether it is part of the erase/refresh cycle. + */ + if (VP1Msg::verbose()) { + QString name = QString((*it)->name()); + QString active = QString::number((*it)->activeState()); + QString state = QString::number((*it)->state()); + std::cout << i << " - name: " << name.toStdString() << " - active: " << active.toStdString() << " - refreshed: " << state.toStdString() << std::endl; + } + if ((*it)->activeState()==IVP1System::ON&&(*it)->state()!=IVP1System::REFRESHED) + return false; + + i++; + } + + return true; +} + +//___________________________________________________________________ +bool VP1ExecutionScheduler::Imp::allVisibleRefreshed() const +{ + foreach(IVP1ChannelWidget*cw,mainwindow->tabManager()->visibleChannels()) + if (!scheduler->hasAllActiveSystemsRefreshed(cw)) + return false; + return true; +} + +//___________________________________________________________________ +bool VP1ExecutionScheduler::Imp::allSoonVisibleRefreshed() const +{ + foreach(IVP1ChannelWidget*cw,mainwindow->tabManager()->soonVisibleChannels()) + if (!scheduler->hasAllActiveSystemsRefreshed(cw)) + return false; + return true; +} + +//___________________________________________________________________ +void VP1ExecutionScheduler::Imp::performPostRefreshCruiseActions(IVP1ChannelWidget*cw) { + + //Abort if not in cruise mode, or if the system just refreshed did + //not make cw fully refreshed: + if (cruisemode==NONE||!scheduler->hasAllActiveSystemsRefreshed(cw)) + return; + + if (cruisemode==EVENT) { + //Abort if this refresh did not make all visible channels refreshed: + if (!mainwindow->tabManager()->isVisible(cw)||!allVisibleRefreshed()) + return; + //Start the countdown for the next event: + assert(!cruisetimer->isActive()); + cruisetimer->start(mainwindow->spinBox_cruise->value()*1000); + return; + } else if (cruisemode==TAB) { + if (cruisetab_waitingtoproceed) { + //We are waiting for channels in the next tab to refresh before + //we can move on, so we should check if this channel refresh + //made all soonvisible channels refreshed. If so: move on. + if (allSoonVisibleRefreshed()) { + mainwindow->tabManager()->showNextTab(); + cruisetab_waitingtoproceed=false; + //If now all visible are refreshed, we start the timer again. + if (allVisibleRefreshed()) + cruisetimer->start(mainwindow->spinBox_cruise->value()*1000); + } + } else { + //Same as in the EVENT case: Check if it is time to start the countdown: + //Abort if this refresh did not make all visible channels refreshed: + if (!mainwindow->tabManager()->isVisible(cw)||!allVisibleRefreshed()) + return; + //Start the countdown for the next event: + assert(!cruisetimer->isActive()); + cruisetimer->start(mainwindow->spinBox_cruise->value()*1000); + return; + } + + return; + } else { + assert(cruisemode==BOTH); + assert(0&&"not implemented"); + } +} + +//___________________________________________________________________ +void VP1ExecutionScheduler::Imp::initCruise() +{ + //No matter what we stop the timer when changing mode or starting a new event. + if (cruisetimer->isActive()) + cruisetimer->stop(); + cruisetab_waitingtoproceed=false; + + //FIXME: DO STUFF HERE + + switch (cruisemode) { + case NONE: + VP1Msg::messageVerbose("initCruise NONE"); + break; + case TAB: + if (allVisibleRefreshed()) + cruisetimer->start(mainwindow->spinBox_cruise->value()*1000); + VP1Msg::messageVerbose("initCruise TAB"); + break; + case EVENT: + //Start cruise countdown if all visible refreshed: + if (allVisibleRefreshed()) + cruisetimer->start(mainwindow->spinBox_cruise->value()*1000); + VP1Msg::messageVerbose("initCruise EVENT"); + break; + case BOTH: + VP1Msg::messageVerbose("initCruise BOTH"); + break; + default: + assert(0&&"UNKNOWN CRUISE MODE"); + break; + } +} + +//___________________________________________________________________ +void VP1ExecutionScheduler::setCruiseMode(const CruiseMode& m) +{ + if (m_d->cruisemode == m) + return; + m_d->cruisemode = m; + + m_d->mainwindow->tabManager()->setTabCruiseMode(m==TAB||m==BOTH); + + m_d->initCruise(); + +} + +//Fixme: abort cruise when this and that... (or, sometimes just reset timer). + +//___________________________________________________________________ +void VP1ExecutionScheduler::performCruise() +{ + //In any case, we should stop the timer (fixme: What if there are 0 visible channels - when will the timer get started again?): + m_d->cruisetimer->stop(); + + if (!m_d->mainwindow->okToProceedToNextEvent()) { + //Hmm. Would like to cruise, but that is not ok. Check back in a few seconds. + m_d->cruisetimer->start( (m_d->mainwindow->spinBox_cruise->value() > 5 ? 3000 : 1000) ); + return; + } + + assert(!m_d->goingtonextevent);//Otherwise it is a bit silly? + + switch (m_d->cruisemode) { + case NONE: + assert(0&&"should never happen"); + break; + case TAB: + assert(m_d->cruisetab_waitingtoproceed==false); + if (m_d->allSoonVisibleRefreshed()) { + m_d->mainwindow->tabManager()->showNextTab(); + //If now all visible are refreshed, we start the timer again. + if (m_d->allVisibleRefreshed()) + m_d->cruisetimer->start(m_d->mainwindow->spinBox_cruise->value()*1000); + } else { + m_d->cruisetab_waitingtoproceed=true; + } + break; + case EVENT: + m_d->mainwindow->goToNextEvent(); + VP1Msg::messageDebug("Crusing to next event"); + break; + case BOTH: + assert(0&&"Not implemented"); + VP1Msg::messageDebug("ERROR: BOTH cruise mode not implemented"); + break; + default: + assert(0&&"UNKNOWN CRUISE MODE"); + VP1Msg::messageDebug("ERROR: Unknown cruise mode"); + break; + } +} + +//___________________________________________________________________ +QStringList VP1ExecutionScheduler::userRequestedFiles() +{ + return m_d->mainwindow->userRequestedFiles(); +} + + +//When in tabcruise mode: +// 1) We know that we are not in single-channel FS mode. +// 2) Soonvisible next + +//FS tab mode: What about floating dock widgets? Rather high priority, but those in next tab should get next... + +//Actually: Floating widgets from other tabs should get docked anyway when going FS-tab when in cruise-TAB mode... + + +//___________________________________________________________________ +#ifdef BUILDVP1LIGHT +void VP1ExecutionScheduler::loadEvent(){ + // Get the name of the application: + const char* appName = "VP1Light"; + + // Initialize the environment: + if( !xAOD::Init( appName ).isSuccess() ) { + ::Error( appName, XAOD_MESSAGE( "Failed to execute xAOD::Init" ) ); + return; + } + + m_event = new xAOD::TEvent( xAOD::TEvent::kAthenaAccess ); + + // Get local xAOD and set valid xAOD path + QSettings settings("ATLAS", "VP1Light"); + std::string path = settings.value("aod/path").toString().toStdString(); + + // Open xAOD file and read it in + m_ifile = ::TFile::Open( path.c_str(), "READ" ); + if( ! m_ifile ) { + ::Error( appName, XAOD_MESSAGE( "File %s couldn't be opened..." ), + path.c_str() ); + return; + } + if( !m_event->readFrom( m_ifile ).isSuccess() ) { + ::Error( appName, XAOD_MESSAGE( "Failed to read from xAOD file %s" ), + path.c_str() ); + return; + } + + // Check if file is empty: + if( m_event->getEntry( 0 ) < 0 ) { + ::Error( appName, XAOD_MESSAGE( "Couldn't load entry 0 from file %s" ), + path.c_str() ); + return; + } + + //Load the current event + m_event->getEntry( m_evtNr ); + + // List for available collections + QStringList jetList; + QStringList vertexList; + QStringList otherList; + QStringList caloClusterList; + QStringList trackParticleList; + QStringList muonList; + QStringList electronList; + + + // // Loop over all entries in the CollectionTree + TTree* ct = (TTree*)m_ifile->Get("CollectionTree"); + m_totEvtNr = ct->GetEntriesFast(); + for (int i = 0; i<ct->GetListOfBranches()->GetEntries();i++){ + std::string className = ct->GetBranch(ct->GetListOfBranches()->At(i)->GetName())->GetClassName(); + + // Store collections in their respective QStringList + if(split(className,"_v[1-9]")=="DataVector<xAOD::Vertex>"){ + vertexList << ct->GetListOfBranches()->At(i)->GetName(); + } + if(split(className,"_v[1-9]")=="xAOD::MissingETContainer"){ + otherList << ct->GetListOfBranches()->At(i)->GetName(); + } + if(split(className,"_v[1-9]")=="DataVector<xAOD::Jet>"){ + jetList << ct->GetListOfBranches()->At(i)->GetName(); + } + if(split(className,"_v[1-9]")=="DataVector<xAOD::CaloCluster>"){ + caloClusterList << ct->GetListOfBranches()->At(i)->GetName(); + } + if(split(className,"_v[1-9]")=="DataVector<xAOD::TrackParticle>"){ + trackParticleList << ct->GetListOfBranches()->At(i)->GetName(); + } + if(split(className,"_v[1-9]")=="DataVector<xAOD::Muon>"){ + muonList << ct->GetListOfBranches()->At(i)->GetName(); + } + if(split(className,"_v[1-9]")=="DataVector<xAOD::Electron>"){ + electronList << ct->GetListOfBranches()->At(i)->GetName(); + } + } + + //Fill the collection lists + m_list.append(vertexList); + m_list.append(otherList); + m_list.append(jetList); + m_list.append(caloClusterList); + m_list.append(trackParticleList); + m_list.append(muonList); + m_list.append(electronList); + + // Get the event info: + const xAOD::EventInfo *eventInfo = nullptr; + if( !m_event->retrieve (eventInfo, "EventInfo").isSuccess() ) { + VP1Msg::messageWarningRed("Failed to retrieve EventInfo"); + return; + } + // Save Event info + m_d->mainwindow->setRunEvtNumber(eventInfo->runNumber(),eventInfo->eventNumber(),eventInfo->level1TriggerType(),eventInfo->timeStamp()); + + // Update the GUI event counter + QString currentEvt = "Event: " + QString::number(getEvtNr()+1) + "/" + QString::number(getTotEvtNr()); + m_d->mainwindow->pushButton_eventselect->setText(currentEvt); +} + +//____________________________________________________________________ +void VP1ExecutionScheduler::passEvent(IVP1System* sys){ + sys->setEvent(m_event); + sys->setObjectList(m_list); +} + +//____________________________________________________________________ +QString VP1ExecutionScheduler::split(const std::string& input, const std::string& regex) { + std::regex re(regex); + std::sregex_token_iterator first{input.begin(), input.end(), re, -1}, last; + std::vector<std::string> vec = {first, last}; + QStringList list; + for (unsigned int i=0;i<vec.size();i++){ + list << QString::fromStdString(vec[i]); + } + return list.join(""); +} +#endif // BUILDVP1LIGHT diff --git a/graphics/VTI12/VTI12Gui/src/VP1ExpertSettings.cxx b/graphics/VTI12/VTI12Gui/src/VP1ExpertSettings.cxx new file mode 100644 index 000000000..e6e1c60ec --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1ExpertSettings.cxx @@ -0,0 +1,551 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +////////////////////////////////////////////////////////////////////////// +// // +// Source file for class VP1ExpertSettings // +// // +// Description: Additional VP1 settings // +// // +// Author: Sebastian Andreas Merkt (sebastian.andreas.merkt@cern.ch) // +// Initial version: August 2017 // +// // +////////////////////////////////////////////////////////////////////////// + +#include "VTI12Gui/VP1ExpertSettings.h" +#include "VP1Base/VP1QtUtils.h" +#include "VP1Base/VP1Msg.h" + +#include <QPushButton> +#include <QGridLayout> +#include <QLabel> +#include <QComboBox> +#include <QCheckBox> +#include <QDir> +#include <QKeyEvent> + +#include <QtWidgets> + + +template <typename... Args> inline void unused(Args&&...) {} // to declare variables as 'unused' + + + +VP1ExpertSettings::VP1ExpertSettings(QWidget *parent) : QDialog(parent) +{ + + m_tabWidget = new QTabWidget; + GeneralTab *generalTab = new GeneralTab(); + AdvancedTab *advancedTab = new AdvancedTab(); + m_tabWidget->addTab(generalTab, tr("Settings")); + connect(generalTab, &GeneralTab::signalScreenshotDirChanged, this, &VP1ExpertSettings::setScreenshotDir); + + #if defined BUILDVP1LIGHT + QString pluginPath=VP1QtUtils::expertSettingValue("expert","ExpertSettings/VP1PLUGINPATH"); + QString fileSelectDir=VP1QtUtils::expertSettingValue("expert","ExpertSettings/VP1_FILESELECTDIR"); + QString screenshotDir=VP1QtUtils::expertSettingValue("general","ExpertSettings/VP1_SCREENSHOTS_DIR"); + QString authLog=VP1QtUtils::expertSettingValue("expert","ExpertSettings/VP1_AUTH_ENABLELOG"); + + if(VP1QtUtils::expertSettingIsOn("general", "ExpertSettings/enableExpertSettings")){ + m_tabWidget->addTab(advancedTab, tr("Advanced")); + connect(advancedTab, &AdvancedTab::signalPluginPathChanged, this, &VP1ExpertSettings::setPluginPath); + connect(advancedTab, &AdvancedTab::signalFileSelectDirChanged, this, &VP1ExpertSettings::setFileSelectDir); + connect(advancedTab, &AdvancedTab::signalAuthLogChanged, this, &VP1ExpertSettings::setAuthLog); + } + #else + QString pluginPath=VP1QtUtils::environmentVariableValue("VP1PLUGINPATH"); + QString fileSelectDir=VP1QtUtils::environmentVariableValue("VP1_FILESELECTDIR"); + QString screenshotDir=VP1QtUtils::environmentVariableValue("VP1_SCREENSHOTS_DIR"); + QString authLog=VP1QtUtils::environmentVariableValue("VP1_AUTH_ENABLELOG"); + + // Always enable Advanced settings for VP1 + m_tabWidget->addTab(advancedTab, tr("Advanced")); + connect(advancedTab, &AdvancedTab::signalPluginPathChanged, this, &VP1ExpertSettings::setPluginPath); + connect(advancedTab, &AdvancedTab::signalFileSelectDirChanged, this, &VP1ExpertSettings::setFileSelectDir); + connect(advancedTab, &AdvancedTab::signalAuthLogChanged, this, &VP1ExpertSettings::setAuthLog); + #endif + + m_buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok); + + connect(m_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::close); + // connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); + + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addWidget(m_tabWidget); + mainLayout->addWidget(m_buttonBox); + setLayout(mainLayout); + + this->setWindowTitle(tr("VP1 Settings")); + + +} + +void VP1ExpertSettings::closeEvent(QCloseEvent *event) +{ + //Update settings + #if defined BUILDVP1LIGHT + VP1Msg::enableMsg("general", "ExpertSettings/VP1_VERBOSE_OUTPUT"); + VP1Msg::enableMsg("general", "ExpertSettings/VP1_DEBUG_OUTPUT"); + #else + VP1Msg::enableMsg("VP1_VERBOSE_OUTPUT"); + VP1Msg::enableMsg("VP1_DEBUG_OUTPUT"); + #endif + + // if(QDir(pluginPath).exists()||pluginPath==""){ + #if defined BUILDVP1LIGHT + VP1QtUtils::setExpertSetting("expert","ExpertSettings/VP1PLUGINPATH", m_pluginPath); + VP1QtUtils::setExpertSetting("expert","ExpertSettings/VP1_FILESELECTDIR", m_fileSelectDir); + VP1QtUtils::setExpertSetting("expert","ExpertSettings/VP1_AUTH_ENABLELOG", m_authLog); + VP1QtUtils::setExpertSetting("general","ExpertSettings/VP1_SCREENSHOTS_DIR", m_screenshotDir); + #else + VP1QtUtils::setEnvironmentVariable("VP1PLUGINPATH", m_pluginPath); + VP1QtUtils::setEnvironmentVariable("VP1_FILESELECTDIR", m_fileSelectDir); + VP1QtUtils::setEnvironmentVariable("VP1_AUTH_ENABLELOG", m_authLog); + VP1QtUtils::setEnvironmentVariable("VP1_SCREENSHOTS_DIR", m_screenshotDir); + #endif + + #if defined BUILDVP1LIGHT + QMessageBox msgBox; + QCheckBox *cb = new QCheckBox("Don't ask again."); + msgBox.setWindowTitle("Settings"); + msgBox.setText("Some settings may require a restart of VP1."); + msgBox.setIcon(QMessageBox::Icon::Information); + msgBox.setCheckBox(cb); + + if(VP1QtUtils::expertSettingIsOn("general","Configuration/enableCloseSettingsReminder")){ + cb->setChecked(true); + } + connect(cb, &QCheckBox::toggled, [this](){VP1ExpertSettings::setExpertSetting("general","Configuration/enableCloseSettingsReminder");}); + + if(cb->checkState()==Qt::Unchecked){ + msgBox.exec(); + } + + event->accept(); + #else + unused(event); + #endif + + +} + +void VP1ExpertSettings::keyPressEvent(QKeyEvent *event){ + if(event->key() == Qt::Key_Escape) + VP1ExpertSettings::close(); +} + +void VP1ExpertSettings::setPluginPath(const QString &path){ + m_pluginPath = path; +} + +void VP1ExpertSettings::setFileSelectDir(const QString &path){ + m_fileSelectDir = path; +} + +void VP1ExpertSettings::setScreenshotDir(const QString &path){ + m_screenshotDir = path; +} + +void VP1ExpertSettings::setAuthLog(const QString &path){ + m_authLog = path; +} + +void VP1ExpertSettings::setExpertSetting(const QString &type, const QString &name){ + if(!VP1QtUtils::expertSettingIsOn(type, name)){ + VP1QtUtils::setExpertSetting(type, name, "1"); + } else { + VP1QtUtils::setExpertSetting(type, name, ""); + } +} + +GeneralTab::GeneralTab(QWidget *parent) + : QWidget(parent) +{ + + QGroupBox *generalGroup = new QGroupBox(tr("General settings")); + + m_checkboxVerbose = new QCheckBox("&Verbose output", this); + m_checkboxVerbose->setToolTip( QApplication::translate(__FUNCTION__, " <html>\n" + " <div style=\"width: 300px;\">Enable A LOT more verbose output to stdout from VP1. It is very useful if you run with this before sending us logfiles for bug reports.</div>" + " </html>", 0 + )); + #if defined BUILDVP1LIGHT + if(VP1QtUtils::expertSettingIsOn("general","ExpertSettings/VP1_VERBOSE_OUTPUT")){ + m_checkboxVerbose->setChecked(true); + } + connect(m_checkboxVerbose, &QCheckBox::toggled, [this](){GeneralTab::setExpertSetting("general","ExpertSettings/VP1_VERBOSE_OUTPUT");}); + #else + if(VP1QtUtils::environmentVariableIsOn("VP1_VERBOSE_OUTPUT")){ + m_checkboxVerbose->setChecked(true); + } + connect(m_checkboxVerbose, &QCheckBox::toggled, [this](){GeneralTab::setExpertSetting("VP1_VERBOSE_OUTPUT");}); + #endif + + m_checkboxDebug = new QCheckBox("&Debug output", this); + m_checkboxDebug->setToolTip( QApplication::translate(__FUNCTION__, " <html>\n" + " <div style=\"width: 300px;\">Enable A LOT more debug output to stdout from VP1. It is very useful if you run with this before sending us logfiles for bug reports.</div>" + " </html>", 0 + )); + #if defined BUILDVP1LIGHT + if(VP1QtUtils::expertSettingIsOn("general","ExpertSettings/VP1_DEBUG_OUTPUT")){ + m_checkboxDebug->setChecked(true); + } + connect(m_checkboxDebug, &QCheckBox::toggled, [this](){GeneralTab::setExpertSetting("general","ExpertSettings/VP1_DEBUG_OUTPUT");}); + #else + if(VP1QtUtils::environmentVariableIsOn("VP1_DEBUG_OUTPUT")){ + m_checkboxDebug->setChecked(true); + } + connect(m_checkboxDebug, &QCheckBox::toggled, [this](){GeneralTab::setExpertSetting("VP1_DEBUG_OUTPUT");}); + #endif + + m_checkboxDisallowMultipleChannels = new QCheckBox("D&isallow multiple channels", this); + m_checkboxDisallowMultipleChannels->setToolTip( QApplication::translate(__FUNCTION__, " <html>\n" + " <div style=\"width: 300px;\">This variable exists to help users whose graphics drivers are broken in such a way as to make VP1 crash when showing multiple 3D widgets. Setting this variable will thus ensure that the user can only ever open one channel, and it will remove the little 3D preview window normally shown when editing a material.</div>" + " </html>", 0 + )); + #if defined BUILDVP1LIGHT + if(VP1QtUtils::expertSettingIsOn("general","ExpertSettings/VP1_DISALLOW_MULTIPLE_CHANNELS")){ + m_checkboxDisallowMultipleChannels->setChecked(true); + } + connect(m_checkboxDisallowMultipleChannels, &QCheckBox::toggled, [this](){GeneralTab::setExpertSetting("general","ExpertSettings/VP1_DISALLOW_MULTIPLE_CHANNELS");}); + #else + if(VP1QtUtils::environmentVariableIsOn("VP1_DISALLOW_MULTIPLE_CHANNELS")){ + m_checkboxDisallowMultipleChannels->setChecked(true); + } + connect(m_checkboxDisallowMultipleChannels, &QCheckBox::toggled, [this](){GeneralTab::setExpertSetting("VP1_DISALLOW_MULTIPLE_CHANNELS");}); + #endif + + m_checkboxDisplayMouseClicks = new QCheckBox("Dis&play mouse clicks", this); + m_checkboxDisplayMouseClicks->setToolTip( QApplication::translate(__FUNCTION__, " <html>\n" + " <div style=\"width: 300px;\">Makes a small popup window appear whenever the user clicks a mouse-button in VP1. Basically this feature exists since it is used when producing the movies (screencasts) on this webpage.</div>" + " </html>", 0 + )); + #if defined BUILDVP1LIGHT + if(VP1QtUtils::expertSettingIsOn("general","ExpertSettings/VP1_DISPLAY_MOUSE_CLICKS")){ + m_checkboxDisplayMouseClicks->setChecked(true); + } + connect(m_checkboxDisplayMouseClicks, &QCheckBox::toggled, [this](){GeneralTab::setExpertSetting("general","ExpertSettings/VP1_DISPLAY_MOUSE_CLICKS");}); + #else + if(VP1QtUtils::environmentVariableIsOn("VP1_DISPLAY_MOUSE_CLICKS")){ + m_checkboxDisplayMouseClicks->setChecked(true); + } + connect(m_checkboxDisplayMouseClicks, &QCheckBox::toggled, [this](){GeneralTab::setExpertSetting("VP1_DISPLAY_MOUSE_CLICKS");}); + #endif + + m_checkboxEnableAskOnClose = new QCheckBox("&Ask on close", this); + m_checkboxEnableAskOnClose->setToolTip( QApplication::translate(__FUNCTION__, " <html>\n" + " <div style=\"width: 300px;\">By default, closing the VP1 window immediately results in the job being finished. Setting this variable will instead make VP1 ask the user if it should really close.</div>" + " </html>", 0 + )); + #if defined BUILDVP1LIGHT + if(VP1QtUtils::expertSettingIsOn("general","ExpertSettings/VP1_ENABLE_ASK_ON_CLOSE")){ + m_checkboxEnableAskOnClose->setChecked(true); + } + connect(m_checkboxEnableAskOnClose, &QCheckBox::toggled, [this](){GeneralTab::setExpertSetting("general","ExpertSettings/VP1_ENABLE_ASK_ON_CLOSE");}); + #else + if(VP1QtUtils::environmentVariableIsOn("VP1_ENABLE_ASK_ON_CLOSE")){ + m_checkboxEnableAskOnClose->setChecked(true); + } + connect(m_checkboxEnableAskOnClose, &QCheckBox::toggled, [this](){GeneralTab::setExpertSetting("VP1_ENABLE_ASK_ON_CLOSE");}); + #endif + + + m_checkboxGuidesSphereInsteadOfCoordaxes = new QCheckBox("G&uides sphere instead of coordinate axes", this); + m_checkboxGuidesSphereInsteadOfCoordaxes->setToolTip( QApplication::translate(__FUNCTION__, " <html>\n" + " <div style=\"width: 300px;\">Replaces the coordinate axes with a red sphere.</div>" + " </html>", 0 + )); + #if defined BUILDVP1LIGHT + if(VP1QtUtils::expertSettingIsOn("general","ExpertSettings/VP1_GUIDES_SPHERE_INSTEAD_OF_COORDAXES")){ + m_checkboxGuidesSphereInsteadOfCoordaxes->setChecked(true); + } + connect(m_checkboxGuidesSphereInsteadOfCoordaxes, &QCheckBox::toggled, [this](){GeneralTab::setExpertSetting("general","ExpertSettings/VP1_GUIDES_SPHERE_INSTEAD_OF_COORDAXES");}); + #else + if(VP1QtUtils::environmentVariableIsOn("VP1_GUIDES_SPHERE_INSTEAD_OF_COORDAXES")){ + m_checkboxGuidesSphereInsteadOfCoordaxes->setChecked(true); + } + connect(m_checkboxGuidesSphereInsteadOfCoordaxes, &QCheckBox::toggled, [this](){GeneralTab::setExpertSetting("VP1_GUIDES_SPHERE_INSTEAD_OF_COORDAXES");}); + #endif + + + m_checkboxAntiAliasing = new QCheckBox("Advanced Anti-Aliasing", this); + m_checkboxAntiAliasing->setToolTip( QApplication::translate(__FUNCTION__, " <html>\n" + " <div style=\"width: 300px;\">Switches on advanced Anti-Aliasing. WARNING: May cause issues with certain graphics drivers.</div>" + " </html>", 0 + )); + #if defined BUILDVP1LIGHT + if(VP1QtUtils::expertSettingIsOn("general","ExpertSettings/VP1_ADVANCED_ANTIALIASING")){ + m_checkboxAntiAliasing->setChecked(true); + } + connect(m_checkboxAntiAliasing, &QCheckBox::toggled, [this](){GeneralTab::setExpertSetting("general","ExpertSettings/VP1_ADVANCED_ANTIALIASING");}); + #else + if(VP1QtUtils::environmentVariableIsOn("VP1_ADVANCED_ANTIALIASING")){ + m_checkboxAntiAliasing->setChecked(true); + } + connect(m_checkboxAntiAliasing, &QCheckBox::toggled, [this](){GeneralTab::setExpertSetting("VP1_ADVANCED_ANTIALIASING");}); + #endif + + + + QGroupBox *directoryGroup = new QGroupBox(tr("Directory settings")); + + m_browseButton1 = new QPushButton(tr("&Browse..."), this); + connect(m_browseButton1, &QAbstractButton::clicked, this, &GeneralTab::on_browseButton1_clicked); + #if defined BUILDVP1LIGHT + m_lineEdit1 = new QLineEdit(VP1QtUtils::expertSettingValue("general","ExpertSettings/VP1_SCREENSHOTS_DIR"), this); + #else + m_lineEdit1 = new QLineEdit(VP1QtUtils::environmentVariableValue("VP1_SCREENSHOTS_DIR"), this); + #endif + m_lineEdit1->setToolTip( QApplication::translate(__FUNCTION__, " <html>\n" + " <div style=\"width: 300px;\">Turns on the automatic generation of screen-shots for all channels at every event. The value must be a valid writable directory, where all generated screenshot files will be stored.</div>" + " </html>", 0 + )); + connect(m_lineEdit1, &QLineEdit::textChanged, this, &GeneralTab::slotScreenshotDirChanged); + + + QVBoxLayout *generalLayout = new QVBoxLayout; + generalLayout->addWidget(m_checkboxVerbose); + generalLayout->addWidget(m_checkboxDebug); + generalLayout->addWidget(m_checkboxDisallowMultipleChannels); + generalLayout->addWidget(m_checkboxDisplayMouseClicks); + generalLayout->addWidget(m_checkboxEnableAskOnClose); + generalLayout->addWidget(m_checkboxGuidesSphereInsteadOfCoordaxes); + generalLayout->addWidget(m_checkboxAntiAliasing); + generalGroup->setLayout(generalLayout); + + QGridLayout *gridLayout = new QGridLayout(this); + gridLayout->addWidget(new QLabel(tr("Screenshots directory:")), 0, 0); + gridLayout->addWidget(m_lineEdit1,1,0); + gridLayout->addWidget(m_browseButton1,1,1); + directoryGroup->setLayout(gridLayout); + + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addWidget(generalGroup); + mainLayout->addWidget(directoryGroup); + mainLayout->addStretch(1); + setLayout(mainLayout); + +} + +#if defined BUILDVP1LIGHT +void GeneralTab::setExpertSetting(const QString &type, const QString &name){ + if(!VP1QtUtils::expertSettingIsOn(type, name)){ + VP1QtUtils::setExpertSetting(type, name, "1"); + } else { + VP1QtUtils::setExpertSetting(type, name, ""); + } +} +#else +void GeneralTab::setExpertSetting(const QString &name){ + if(!VP1QtUtils::environmentVariableIsOn(name)){ + VP1QtUtils::setEnvironmentVariable(name, "1"); + } else { + VP1QtUtils::unsetEnvironmentVariable(name); + } +} +#endif + +void GeneralTab::on_browseButton1_clicked(){ + QString fileName = QFileDialog::getExistingDirectory(this, + tr("Select screenshot directory"), QDir::currentPath(), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + + m_lineEdit1->setText(fileName); +} + +void GeneralTab::slotScreenshotDirChanged(const QString &path){ + emit signalScreenshotDirChanged(path); +} + + +AdvancedTab::AdvancedTab(QWidget *parent) + : QWidget(parent) +{ + QGroupBox *checkBoxGroup = new QGroupBox(tr("Advanced settings")); + + m_checkboxEnableInformOnEndOfJob = new QCheckBox("&Enable inform on end of job", this); + m_checkboxEnableInformOnEndOfJob->setToolTip( QApplication::translate(__FUNCTION__, " <html>\n" + " <div style=\"width: 300px;\">By default, VP1 simply exits at the end of the ATHENA job, which might be confusing to some. When this variable is set, VP1 will show an dialog, letting the user know that the end of the job has been reached.</div>" + " </html>", 0 + )); + #if defined BUILDVP1LIGHT + if(VP1QtUtils::expertSettingIsOn("expert","ExpertSettings/VP1_ENABLE_INFORM_ON_END_OF_JOB")){ + m_checkboxEnableInformOnEndOfJob->setChecked(true); + } + connect(m_checkboxEnableInformOnEndOfJob, &QCheckBox::toggled, [this](){AdvancedTab::setExpertSetting("expert","ExpertSettings/VP1_ENABLE_INFORM_ON_END_OF_JOB");}); + #else + if(VP1QtUtils::environmentVariableIsOn("VP1_ENABLE_INFORM_ON_END_OF_JOB")){ + m_checkboxEnableInformOnEndOfJob->setChecked(true); + } + connect(m_checkboxEnableInformOnEndOfJob, &QCheckBox::toggled, [this](){AdvancedTab::setExpertSetting("VP1_ENABLE_INFORM_ON_END_OF_JOB");}); + #endif + + m_checkboxHardExitAtEnd = new QCheckBox("&Hard exit at end", this); + m_checkboxHardExitAtEnd->setToolTip( QApplication::translate(__FUNCTION__, " <html>\n" + " <div style=\"width: 300px;\">By default, the VP1 algorithm simply tells ATHENA to end the job when VP1 is being closed. This means that ATHENA will shut down with its usual procedure, calling finalise on algorithms, generating summaries, etc. If this variable is set, then VP1 will make the process end immediately and abrubtly instead - saving the user some time.</div>" + " </html>", 0 + )); + #if defined BUILDVP1LIGHT + if(VP1QtUtils::expertSettingIsOn("expert","ExpertSettings/VP1_HARD_EXIT_AT_END")){ + m_checkboxHardExitAtEnd->setChecked(true); + } + connect(m_checkboxHardExitAtEnd, &QCheckBox::toggled, [this](){AdvancedTab::setExpertSetting("expert","ExpertSettings/VP1_HARD_EXIT_AT_END");}); + #else + if(VP1QtUtils::environmentVariableIsOn("VP1_HARD_EXIT_AT_END")){ + m_checkboxHardExitAtEnd->setChecked(true); + } + connect(m_checkboxHardExitAtEnd, &QCheckBox::toggled, [this](){AdvancedTab::setExpertSetting("VP1_HARD_EXIT_AT_END");}); + #endif + + m_checkboxDevelShowAllCruiseAndEventControls = new QCheckBox("&Show all cruise and event controls", this); + m_checkboxDevelShowAllCruiseAndEventControls->setToolTip( QApplication::translate(__FUNCTION__, " <html>\n" + " <div style=\"width: 300px;\">Use to enable a few controls related to VP1 cruise-mode, which have presently been disabled.</div>" + " </html>", 0 + )); + #if defined BUILDVP1LIGHT + if(VP1QtUtils::expertSettingIsOn("expert","ExpertSettings/VP1_DEVEL_SHOW_ALL_CRUISE_AND_EVENT_CONTROLS")){ + m_checkboxDevelShowAllCruiseAndEventControls->setChecked(true); + } + connect(m_checkboxDevelShowAllCruiseAndEventControls, &QCheckBox::toggled, [this](){AdvancedTab::setExpertSetting("expert","ExpertSettings/VP1_DEVEL_SHOW_ALL_CRUISE_AND_EVENT_CONTROLS");}); + #else + if(VP1QtUtils::environmentVariableIsOn("VP1_DEVEL_SHOW_ALL_CRUISE_AND_EVENT_CONTROLS")){ + m_checkboxDevelShowAllCruiseAndEventControls->setChecked(true); + } + connect(m_checkboxDevelShowAllCruiseAndEventControls, &QCheckBox::toggled, [this](){AdvancedTab::setExpertSetting("VP1_DEVEL_SHOW_ALL_CRUISE_AND_EVENT_CONTROLS");}); + #endif + + + QGroupBox *directoryGroup = new QGroupBox(tr("Directory settings")); + + m_browseButton1 = new QPushButton(tr("&Browse..."), this); + connect(m_browseButton1, &QAbstractButton::clicked, this, &AdvancedTab::on_browseButton1_clicked); + m_lineEdit1 = new QLineEdit("", this); + + #if defined BUILDVP1LIGHT + if(VP1QtUtils::expertSettingValue("expert","ExpertSettings/VP1PLUGINPATH")==""){ + #ifdef MACBUNDLE + m_lineEdit1->setText(QCoreApplication::applicationDirPath()+"/../Frameworks"); + #else + m_lineEdit1->setText(QCoreApplication::applicationDirPath()+"/../lib"); + #endif + } else { + m_lineEdit1->setText(VP1QtUtils::expertSettingValue("expert","ExpertSettings/VP1PLUGINPATH")); + } + #else + if(VP1QtUtils::environmentVariableValue("VP1PLUGINPATH")==""){ + m_lineEdit1->setText(QCoreApplication::applicationDirPath()+"/../lib"); + } else { + m_lineEdit1->setText(VP1QtUtils::environmentVariableValue("VP1PLUGINPATH")); + } + #endif + m_lineEdit1->setToolTip( QApplication::translate(__FUNCTION__, " <html>\n" + " <div style=\"width: 300px;\">Select the directory that contains the plugin libraries.</div>" + " </html>", 0 + )); + connect(m_lineEdit1, &QLineEdit::textChanged, this, &AdvancedTab::slotPluginPathChanged); + + m_browseButton2 = new QPushButton(tr("B&rowse..."), this); + connect(m_browseButton2, &QAbstractButton::clicked, this, &AdvancedTab::on_browseButton2_clicked); + #if defined BUILDVP1LIGHT + m_lineEdit2 = new QLineEdit(VP1QtUtils::expertSettingValue("expert","ExpertSettings/VP1_FILESELECTDIR"), this); + #else + m_lineEdit2 = new QLineEdit(VP1QtUtils::environmentVariableValue("VP1_FILESELECTDIR"), this); + #endif + m_lineEdit2->setToolTip( QApplication::translate(__FUNCTION__, " <html>\n" + " <div style=\"width: 300px;\">By default, the various VP1 file selectors starts in the job run-directory. Setting this variable to a directory ensures that that directory is used by default instead.</div>" + " </html>", 0 + )); + connect(m_lineEdit2, &QLineEdit::textChanged, this, &AdvancedTab::slotFileSelectDirChanged); + + m_browseButton3 = new QPushButton(tr("Br&owse..."), this); + connect(m_browseButton3, &QAbstractButton::clicked, this, &AdvancedTab::on_browseButton3_clicked); + #if defined BUILDVP1LIGHT + m_lineEdit3 = new QLineEdit(VP1QtUtils::expertSettingValue("expert","ExpertSettings/VP1_AUTH_ENABLELOG"), this); + #else + m_lineEdit3 = new QLineEdit(VP1QtUtils::environmentVariableValue("VP1_AUTH_ENABLELOG"), this); + #endif + m_lineEdit3->setToolTip( QApplication::translate(__FUNCTION__, " <html>\n" + " <div style=\"width: 300px;\">Enables creation of an authentication log file for VP1 live.</div>" + " </html>", 0 + )); + connect(m_lineEdit3, &QLineEdit::textChanged, this, &AdvancedTab::slotAuthLogChanged); + + + QVBoxLayout *checkBoxLayout = new QVBoxLayout; + checkBoxLayout->addWidget(m_checkboxEnableInformOnEndOfJob); + checkBoxLayout->addWidget(m_checkboxHardExitAtEnd); + checkBoxLayout->addWidget(m_checkboxDevelShowAllCruiseAndEventControls); + checkBoxGroup->setLayout(checkBoxLayout); + + QGridLayout *gridLayout = new QGridLayout(this); + gridLayout->addWidget(new QLabel(tr("Plugin path:")), 0, 0); + gridLayout->addWidget(m_lineEdit1,1,0); + gridLayout->addWidget(m_browseButton1,1,1); + gridLayout->addWidget(new QLabel(tr("File selection directory:")), 2, 0); + gridLayout->addWidget(m_lineEdit2,3,0); + gridLayout->addWidget(m_browseButton2,3,1); + gridLayout->addWidget(new QLabel(tr("Authentication log directory:")), 4, 0); + gridLayout->addWidget(m_lineEdit3,5,0); + gridLayout->addWidget(m_browseButton3,5,1); + directoryGroup->setLayout(gridLayout); + + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addWidget(checkBoxGroup); + mainLayout->addWidget(directoryGroup); + mainLayout->addStretch(1); + setLayout(mainLayout); +} + +void AdvancedTab::on_browseButton1_clicked() +{ + QString fileName = QFileDialog::getExistingDirectory(this, + tr("Select Plugin Path"), QDir::currentPath(), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + + m_lineEdit1->setText(fileName); +} + +void AdvancedTab::on_browseButton2_clicked() +{ + QString fileName = QFileDialog::getExistingDirectory(this, + tr("Select file directory"), QDir::currentPath(), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + + m_lineEdit2->setText(fileName); +} + +void AdvancedTab::on_browseButton3_clicked() +{ + QString fileName = QFileDialog::getExistingDirectory(this, + tr("Select authentication directory"), QDir::currentPath(), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + + m_lineEdit3->setText(fileName); +} + +void AdvancedTab::slotPluginPathChanged(const QString &path){ + emit signalPluginPathChanged(path); +} + +void AdvancedTab::slotFileSelectDirChanged(const QString &path){ + emit signalFileSelectDirChanged(path); +} + +void AdvancedTab::slotAuthLogChanged(const QString &path){ + emit signalAuthLogChanged(path); +} + +#if defined BUILDVP1LIGHT +void AdvancedTab::setExpertSetting(const QString &type, const QString &name){ + if(!VP1QtUtils::expertSettingIsOn(type, name)) { + VP1QtUtils::setExpertSetting(type, name, "1"); + } else { + VP1QtUtils::setExpertSetting(type, name, ""); + } +} +#else +void AdvancedTab::setExpertSetting(const QString &name){ + if(!VP1QtUtils::environmentVariableIsOn(name)) { + VP1QtUtils::setEnvironmentVariable(name, "1"); + } else { + VP1QtUtils::unsetEnvironmentVariable(name); + } +} +#endif diff --git a/graphics/VTI12/VTI12Gui/src/VP1GeoDBSelection.cxx b/graphics/VTI12/VTI12Gui/src/VP1GeoDBSelection.cxx new file mode 100644 index 000000000..08356a298 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1GeoDBSelection.cxx @@ -0,0 +1,129 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +////////////////////////////////////////////////////////////////////////// +// // +// Source file for class VP1GeoDBSelection // +// // +// Description: Dialog for the selection of a geometry database // +// // +// Author: Sebastian Andreas Merkt (sebastian.andreas.merkt@cern.ch) // +// Initial version: August 2017 // +// // +////////////////////////////////////////////////////////////////////////// + +#include "VTI12Gui/VP1GeoDBSelection.h" + +#include <QPushButton> +#include <QGridLayout> +#include <QLabel> +#include <QComboBox> +#include <QFileInfo> + +#include <QtWidgets> + +VP1GeoDBSelection::VP1GeoDBSelection(QWidget *parent) : QDialog(parent) +{ + //Set default dialog size + int nWidth = 800; + int nHeight = 220; + if (parent != NULL) + setGeometry(parent->x() + parent->width()/2 - nWidth/2, + parent->y() + parent->height()/2 - nHeight/2, + nWidth, nHeight); + else + resize(nWidth, nHeight); + + //Browse button to select database + m_browseButton = new QPushButton(tr("&Browse..."), this); + connect(m_browseButton, &QAbstractButton::clicked, this, &VP1GeoDBSelection::on_browseButton_clicked); + + //Buttonbox to set Open, Cancel buttons + m_buttonBox = new QDialogButtonBox(this); + m_openButton = m_buttonBox->addButton(tr("&Open"), QDialogButtonBox::AcceptRole); + m_cancelButton = m_buttonBox->addButton(tr("&Cancel"),QDialogButtonBox::RejectRole); + connect(m_openButton, &QPushButton::clicked, this, &VP1GeoDBSelection::loadDatabase); + connect(m_cancelButton, &QPushButton::clicked, this, &VP1GeoDBSelection::reject); + + //Open QSettings to store path do database + QSettings settings("ATLAS", "VP1Light"); + QString text; + + //If no db file has been provided via command line argument, the "db/path" value is "" + if(settings.value("db/path").toString()==""){ + m_openButton->setEnabled(false); + text = "(*.db)"; + } else { //If a db file has been provided show it in the combobox + text = settings.value("db/path").toString(); + } + //Create the combobox + m_directoryComboBox = createComboBox(text); + + //Create the main layout + QGridLayout *mainLayout = new QGridLayout(this); + mainLayout->addWidget(new QLabel(tr("Select Geometry Database:")), 0, 0); + mainLayout->addWidget(m_directoryComboBox, 1, 0, 1, 2); + mainLayout->addWidget(m_browseButton, 1, 4); + mainLayout->addWidget(m_buttonBox, 3, 4); + + m_browseButton->setMinimumWidth(200); + m_buttonBox->setMinimumWidth(200); + m_browseButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + m_buttonBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); +} + +//Method to create the drop down combobox +QComboBox *VP1GeoDBSelection::createComboBox(const QString &text) +{ + QComboBox *comboBox = new QComboBox; + comboBox->setMinimumWidth(600); + comboBox->setEditable(false); + comboBox->addItem(text); + comboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + return comboBox; +} + +//Animate the click +void VP1GeoDBSelection::animateFindClick() +{ + m_openButton->animateClick(); +} + +//Open the file selection dialog +void VP1GeoDBSelection::on_browseButton_clicked() +{ + m_fileName = QFileDialog::getOpenFileName(this, + tr("Select Database"), QDir::currentPath(), + tr("DB Files (*.db)")); + + // Add the selected file to the combobox + if (!m_fileName.isEmpty()) { + if (m_directoryComboBox->findText(m_fileName) == -1) + m_directoryComboBox->addItem(m_fileName); + m_directoryComboBox->setCurrentIndex(m_directoryComboBox->findText(m_fileName)); + + //When valid a database is selected, enable the Open button to confirm + m_openButton->setEnabled(true); + } + +} + +//Check and Save the settings +void VP1GeoDBSelection::loadDatabase(){ + + //Save DB path to settings + QSettings settings("ATLAS", "VP1Light"); + settings.setValue("db/path", m_directoryComboBox->itemText(m_directoryComboBox->currentIndex())); + + //If the selected DB does not exists, go back + if (!QFileInfo::exists(m_directoryComboBox->itemText(m_directoryComboBox->currentIndex()))){ + QMessageBox msgBox; + msgBox.setWindowTitle("Virtual TI 12"); + msgBox.setText("Database does not exist. Please choose another database file."); + msgBox.exec(); + return; + } + VP1GeoDBSelection::setResult(1); + VP1GeoDBSelection::accept(); +} diff --git a/graphics/VTI12/VTI12Gui/src/VP1Gui.cxx b/graphics/VTI12/VTI12Gui/src/VP1Gui.cxx new file mode 100644 index 000000000..6b06cb35e --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1Gui.cxx @@ -0,0 +1,242 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////// +// // +// Implementation of class VP1Gui // +// // +// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Initial version: April 2007 // +// // +///////////////////////////////////////////////////////////// + +#include "VTI12Gui/VP1Gui.h" +#include "VTI12Gui/VP1ExecutionScheduler.h" +#include "VP1Base/VP1Msg.h" + +#include <QStringList> +#include <QFile> +#include <QFileInfo> +#include <QUrl> +#include <QSslSocket> + +#include <cassert> +#include <iostream> + +//____________________________________________________________________ +class VP1Gui::Imp { +public: + Imp() : the_scheduler(nullptr), sg(nullptr), detstore(nullptr), + svclocator(nullptr), toolSvc(nullptr), + initialvp1files{}, + initialCruiseSeconds{}, + localFileCacheLimit{}{ + //nop + } + VP1ExecutionScheduler * the_scheduler; + + //We hold the arguments here until init is called: + StoreGateSvc * sg; + StoreGateSvc * detstore; + ISvcLocator * svclocator; + IToolSvc * toolSvc; + QStringList initialvp1files; + QString initialCruiseMode; + unsigned initialCruiseSeconds; + QString singleEventSource; + QString singleEventLocalTmpDir; + unsigned localFileCacheLimit; + QStringList availableLocalInputDirectories; +}; + + +//____________________________________________________________________ +VP1Gui::VP1Gui(StoreGateSvc* sg,StoreGateSvc* detstore, + ISvcLocator* svclocator,IToolSvc*toolSvc, + const std::vector<std::string>& initialvp1files, + const std::string& initialCruiseMode, unsigned initialCruiseSeconds, + const std::string& singleEventSource, const std::string& singleEventLocalTmpDir, + unsigned localFileCacheLimit, + const std::vector<std::string>& availableLocalInputDirectories ) + : m_d(new Imp) +{ + m_d->sg = sg; + m_d->detstore = detstore; + m_d->svclocator = svclocator; + m_d->toolSvc = toolSvc; + m_d->initialCruiseMode = QString(initialCruiseMode.c_str()).simplified(); + m_d->initialCruiseSeconds = initialCruiseSeconds; + m_d->singleEventSource = singleEventSource.c_str(); + m_d->singleEventLocalTmpDir = singleEventLocalTmpDir.c_str(); + m_d->localFileCacheLimit = localFileCacheLimit; + + std::vector<std::string>::const_iterator it, itE = initialvp1files.end(); + for (it = initialvp1files.begin();it!=itE;++it) + m_d->initialvp1files << it->c_str(); + + itE = availableLocalInputDirectories.end(); + for (it = availableLocalInputDirectories.begin();it!=itE;++it) + m_d->availableLocalInputDirectories << it->c_str(); + +} + +//____________________________________________________________________ +VP1Gui::~VP1Gui() +{ + delete m_d; m_d=0; +} + +//____________________________________________________________________ +bool VP1Gui::argumentsAreValid() const +{ + //Athena pointers: + + if (!m_d->sg) { + VP1Msg::message("ERROR: Null pointer to event store."); + return false; + } + if (!m_d->detstore) { + VP1Msg::message("ERROR: Null pointer to detector store."); + return false; + } + if (!m_d->svclocator) { + VP1Msg::message("ERROR: Null pointer to service locator."); + return false; + } + if (!m_d->toolSvc) { + VP1Msg::message("ERROR: Null pointer to tool service."); + return false; + } + + //Initial files: + + // ...no checks... + + //Cruise mode: + if (m_d->initialCruiseMode!="NONE"&&m_d->initialCruiseMode!="EVENT"&&m_d->initialCruiseMode!="TAB"&&m_d->initialCruiseMode!="BOTH") { + VP1Msg::message("WARNING: unknown initial cruise mode "+m_d->initialCruiseMode+" (valid are NONE/EVENT/TAB/BOTH). Assuming NONE."); + m_d->initialCruiseMode = "NONE"; + } + + //Single-Event-Per-File modes: + if (!m_d->singleEventSource.isEmpty()&&!m_d->singleEventLocalTmpDir.isEmpty()) { + const bool httpmode = m_d->singleEventSource.startsWith("http://") || m_d->singleEventSource.startsWith("https://") ; + if (httpmode) { + QUrl url(m_d->singleEventSource); + if (!url.isValid()||url.path().isEmpty()) { + //Fixme: check that path ends with a filename! + VP1Msg::message("VP1ExecutionScheduler::init ERROR: Source URL ("+m_d->singleEventSource+") incorrect format!"); + return false; + } + + // For the https mode check if the platform supports SSL + if(m_d->singleEventSource.startsWith("https://") + && ! (QSslSocket::supportsSsl()) ) { + VP1Msg::message("VP1ExecutionScheduler::init ERROR: Unable to retrieve events over Https. The platform does not support SSL"); + return false; + } + } else { + QFileInfo fi_s(m_d->singleEventSource), fi_l(m_d->singleEventLocalTmpDir); + if (!fi_s.exists()||!fi_s.isDir()||!fi_s.isReadable()) { + VP1Msg::message("ERROR: Source directory ("+m_d->singleEventSource+") does not exist, is not readable, or is not a directory!"); + return false; + } + if (!fi_l.exists()||!fi_l.isDir()||!fi_l.isReadable()||!fi_l.isWritable()) { + VP1Msg::message("ERROR: Local tmp directory ("+m_d->singleEventLocalTmpDir+") does not exist, had incorrect permissions, or is not a directory!"); + return false; + } + if (fi_l.canonicalFilePath()==fi_s.canonicalFilePath()) { + VP1Msg::message("ERROR: Local tmp directory ("+m_d->singleEventLocalTmpDir+") is the same the source directory ("+m_d->singleEventSource+")"); + return false; + } + } + } else { + if (!m_d->singleEventSource.isEmpty()||!m_d->singleEventLocalTmpDir.isEmpty()) { + VP1Msg::message("ERROR: Only one of SourceDir and LocalCopyDir set. Set either both or none."); + return false; + } + } + + if (m_d->localFileCacheLimit==1||m_d->localFileCacheLimit==2) { + VP1Msg::message("WARNING: Too low value of localFileCacheLimit. Setting to 3. (Set to 0 to disable removal of locally cached files."); + m_d->localFileCacheLimit=3; + } + + return true; +} + +//____________________________________________________________________ +bool VP1Gui::hasBeenInitialised() +{ + return m_d->the_scheduler != 0; +} + +//____________________________________________________________________ +void VP1Gui::init() +{ + VP1Msg::messageDebug("Start of VP1Gui::init()..."); + + assert(!m_d->the_scheduler&&"Dont init twice!!"); + VP1Msg::message(""); + VP1Msg::message("==================================================="); + VP1Msg::message(" Launching the VP1 GUI"); + VP1Msg::message("==================================================="); + VP1Msg::message(""); + m_d->the_scheduler = VP1ExecutionScheduler::init(m_d->sg, + m_d->detstore, + m_d->svclocator, + m_d->toolSvc, + m_d->initialvp1files, + m_d->initialCruiseMode,m_d->initialCruiseSeconds, + m_d->singleEventSource,m_d->singleEventLocalTmpDir, + m_d->localFileCacheLimit, + m_d->availableLocalInputDirectories); + + VP1Msg::messageDebug("end of VP1Gui::init()."); +} + +//____________________________________________________________________ +void VP1Gui::cleanup() +{ + assert(m_d->the_scheduler&&"Cant cleanup before init"); + VP1ExecutionScheduler::cleanup(m_d->the_scheduler); +} + +//____________________________________________________________________ +bool VP1Gui::executeNewEvent( const int& run, const uint64_t& event, const unsigned& triggerType, const unsigned& time ) +{ + VP1Msg::messageDebug("Examining new event ( run# "+QString::number(run)+", event# "+QString::number(event)+" )"); + + bool b = m_d->the_scheduler->executeNewEvent(run,event,triggerType,time); + + // NOTE: + // we will go on to the lines here below + // only when the user clicks on the "Next event" button. + + VP1Msg::messageDebug("Leaving event ( run# "+QString::number(run)+", event# "+QString::number(event)+" )" + +(nextRequestedEventFile().empty()?QString(""):". Next requested event file: "+QString(nextRequestedEventFile().c_str()))); + + VP1Msg::messageDebug("end of VP1Gui::executeNewEvent()."); + + return b; +} + +//____________________________________________________________________ +std::string VP1Gui::nextRequestedEventFile() const +{ + return m_d->the_scheduler->nextRequestedEventFile().toStdString(); +} + +//____________________________________________________________________ +std::vector<std::string> VP1Gui::userRequestedFiles() +{ + std::vector<std::string> retvector; + if(m_d->the_scheduler) { + const QStringList& inplist = m_d->the_scheduler->userRequestedFiles(); + for(int i=0; i<inplist.size(); ++i) + retvector.push_back(inplist.at(i).toStdString()); + } + return retvector; +} diff --git a/graphics/VTI12/VTI12Gui/src/VP1HttpGetFile.cxx b/graphics/VTI12/VTI12Gui/src/VP1HttpGetFile.cxx new file mode 100644 index 000000000..499f244f3 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1HttpGetFile.cxx @@ -0,0 +1,156 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class VP1HttpGetFile // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: May 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12Gui/VP1HttpGetFile.h" +#include <QTimer> + +#define VP1HttpGetFile_cxx +#include "VP1HttpGetFile_Private.h" +#undef VP1HttpGetFile_cxx + +//____________________________________________________________________ +class VP1HttpGetFile::Imp { +public: + Imp() : maxDownloads(8), dead(false) {} + unsigned maxDownloads; + bool dead; + QList<VP1HttpGetFile_DownloadThread *> activeDownloadThreads; +}; + +//____________________________________________________________________ +VP1HttpGetFile::VP1HttpGetFile(QObject * parent) + : QObject(parent), m_d(new Imp) +{ +} + +//____________________________________________________________________ +VP1HttpGetFile::~VP1HttpGetFile() +{ + m_d->dead = true; + foreach( VP1HttpGetFile_DownloadThread * thread, m_d->activeDownloadThreads) { + thread->blockSignals(true); + QString urltofile = thread->urltofile(); + QString localtargetfile = thread->localtargetfile(); + QString data = thread->data(); + emit downloadFailed( "VP1HttpGetFile object deleted before download finished", urltofile, localtargetfile, data ); + thread->terminate(); + thread->wait(); + thread->deleteLater(); + } + delete m_d; +} + +//____________________________________________________________________ +void VP1HttpGetFile::setMaxNumberOfPendingDownloads(unsigned n) +{ + m_d->maxDownloads = n; +} + +//____________________________________________________________________ +unsigned VP1HttpGetFile::maxNumberOfPendingDownloads() const +{ + return m_d->maxDownloads; +} + +//____________________________________________________________________ +unsigned VP1HttpGetFile::numberOfPendingDownloads() const +{ + return m_d->activeDownloadThreads.size(); +} + +//____________________________________________________________________ +QString VP1HttpGetFile::startDownload( const QString& urltofile, + const QString& localtargetfile, + const QString& md5sum, + const QString& data ) +{ + if (m_d->maxDownloads>0 && unsigned(m_d->activeDownloadThreads.count()) >= m_d->maxDownloads) + return "Too many simultaneous downloads requested"; + + if (isDownloadingTo(localtargetfile)) + return "Already downloading file to location: "+localtargetfile; + + VP1HttpGetFile_DownloadThread * thread = new VP1HttpGetFile_DownloadThread( urltofile, localtargetfile, md5sum, data); + connect(thread,SIGNAL(finished()),this,SLOT(downloadThreadFinished())); + connect(thread,SIGNAL(terminated()),this,SLOT(downloadThreadTerminated())); + m_d->activeDownloadThreads << thread; + thread->start(); + + return "";//Download started succesfully. +} + +//____________________________________________________________________ +void VP1HttpGetFile::downloadThreadFinished() +{ + if (m_d->dead) + return; + VP1HttpGetFile_DownloadThread * thread = dynamic_cast<VP1HttpGetFile_DownloadThread *>(sender()); + if (!thread) + return; + m_d->activeDownloadThreads.removeAll(thread); + const QString urltofile = thread->urltofile(); + const QString localtargetfile = thread->localtargetfile(); + const QString data = thread->data(); + const bool errors = thread->errors(); + const QString errorString = thread->errorString(); + thread->wait(); + thread->deleteLater(); + if (errors) + emit downloadFailed( errorString, urltofile, localtargetfile, data ); + else + emit downloadSuccessful( urltofile, localtargetfile, data ); +} + +//____________________________________________________________________ +void VP1HttpGetFile::downloadThreadTerminated() +{ + if (m_d->dead) + return; + VP1HttpGetFile_DownloadThread * thread = dynamic_cast<VP1HttpGetFile_DownloadThread *>(sender()); + if (!thread) + return; + m_d->activeDownloadThreads.removeAll(thread); + const QString urltofile = thread->urltofile(); + const QString localtargetfile = thread->localtargetfile(); + const QString data = thread->data(); + thread->wait(); + thread->deleteLater(); + emit downloadFailed( "Download thread terminated", urltofile, localtargetfile, data ); + + //NB: As always when threads are terminated, we might get memory + //leaks, but it usually only happens if the VP1HttpGetFile instance + //is deleted prematurely (e.g. at program shutdown). +} + +//____________________________________________________________________ +bool VP1HttpGetFile::isDownloading(const QString& urltofile) const +{ + foreach( VP1HttpGetFile_DownloadThread * thread, m_d->activeDownloadThreads) + if (urltofile==thread->urltofile()) { + QTimer::singleShot(0, thread, SLOT(checkForStall())); + return true; + } + return false; +} + +//____________________________________________________________________ +bool VP1HttpGetFile::isDownloadingTo(const QString& localtargetfile) const +{ + foreach( VP1HttpGetFile_DownloadThread * thread, m_d->activeDownloadThreads) + if (localtargetfile==thread->localtargetfile()) { + QTimer::singleShot(0, thread, SLOT(checkForStall())); + return true; + } + return false; +} diff --git a/graphics/VTI12/VTI12Gui/src/VP1HttpGetFile_Private.h b/graphics/VTI12/VTI12Gui/src/VP1HttpGetFile_Private.h new file mode 100644 index 000000000..0e05ecc83 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1HttpGetFile_Private.h @@ -0,0 +1,275 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Internal classes for VP1HttpGetFile // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: June 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include <QThread> +#include <QMutex> +#include <QTimer> +#include <QDateTime> +#include <QFileInfo> +#include <QFile> +#include <QDir> +#include <QUrl> + +//#include <QHttp> // Qt 4 +//#include <QNetworkAccessManager> // TODO: use this to port to Qt5 + +#include "VTI12Gui/VP1MD5Sum.h" + +class VP1HttpGetFile_DownloadThread : public QThread { + + Q_OBJECT + +public: + + VP1HttpGetFile_DownloadThread( const QString& urltofile, + const QString& localtargetfile, + const QString& expectedMD5Sum, + const QString& data, + QObject * parent = 0); + virtual ~VP1HttpGetFile_DownloadThread(){} + + //For accessing the results: + bool errors() const { m_mutex.lock(); bool err=!m_errorString.isEmpty(); m_mutex.unlock(); return err; } + QString errorString() const { m_mutex.lock(); QString err = m_errorString; m_mutex.unlock(); return err; } + + QString urltofile() const { return m_urltofile; } + QString localtargetfile() const { return m_localtargetfile; } + QString expectedMD5Sum() const { return m_expectedMD5Sum; } + QString data() const { return m_data; } + +protected: + void run(); +public slots: + void checkForStall(); +private slots: + void done(bool); + void dataReadProgress(); +private: + const QString m_urltofile; + const QString m_localtargetfile; + const QString m_expectedMD5Sum; + const QString m_data; + QString m_errorString; + mutable QMutex m_mutex;//Protects m_errors; +// QHttp * m_http; // Old Qt4 code --> TODO: need to be ported to Qt5!! + enum DOWNLOADFINISHSTATUS { NOTFINISHED, NOERRORS, HTTPERROR, STALLEDERROR, SIZEDECREASEDERROR }; + DOWNLOADFINISHSTATUS m_downloadFinishedStatus;//-1: not finished, 0: error, 1: no-error + unsigned m_lastChangeTime; + qint64 m_lastcheckedsize;//-2 never checked, -1 does not exists. + enum CLEANUPOPT { CLEANUPLOCALFILE, DONTTOUCHLOCALFILE}; + void endInFailure(const QString&, CLEANUPOPT ); +}; + +//Remember that we are also included from the qt moc file: +#ifdef VP1HttpGetFile_cxx + +//____________________________________________________________________ +VP1HttpGetFile_DownloadThread::VP1HttpGetFile_DownloadThread( const QString& urltofile, + const QString& localtargetfile, + const QString& expectedMD5Sum, + const QString& data, + QObject * parent ) + : QThread(parent), + m_urltofile(urltofile), + m_localtargetfile(localtargetfile), + m_expectedMD5Sum(expectedMD5Sum), + m_data(data), + m_errorString("Download not finished"), +// m_http(0), + m_downloadFinishedStatus(NOTFINISHED), + m_lastChangeTime(0), + m_lastcheckedsize(-2) +{ +} + +//____________________________________________________________________ +void VP1HttpGetFile_DownloadThread::endInFailure(const QString& err, CLEANUPOPT opt) +{ + m_mutex.lock(); + + if (opt==CLEANUPLOCALFILE&&QFile::exists(m_localtargetfile)) + QFile::remove(m_localtargetfile); + + m_errorString = err.isEmpty() ? "Unspecified error" : err; + m_mutex.unlock(); +} + +//____________________________________________________________________ +void VP1HttpGetFile_DownloadThread::checkForStall() +{ + // TODO: to be ported to Qt5!! +// if (!m_http) +// return; +// unsigned currentTime = QDateTime::currentDateTime().toTime_t(); +// if (currentTime>m_lastChangeTime+10) {//10s +// m_downloadFinishedStatus = STALLEDERROR; +// quit(); +// } +} + +//____________________________________________________________________ +void VP1HttpGetFile_DownloadThread::done(bool error) +{ + m_downloadFinishedStatus = error ? HTTPERROR : NOERRORS; + quit(); +} + +//____________________________________________________________________ +void VP1HttpGetFile_DownloadThread::dataReadProgress() +{ + //We monitor that filesize of files downloaded is strictly + //increasing (and that a created file does not disappear): + QFileInfo fi(m_localtargetfile); + qint64 currentsize = fi.exists() ? fi.size() : -1; + if (currentsize < m_lastcheckedsize) { + m_downloadFinishedStatus = SIZEDECREASEDERROR; + quit(); + } + + //For stall-detection: + if (currentsize > m_lastcheckedsize) + m_lastChangeTime = QDateTime::currentDateTime().toTime_t(); + + m_lastcheckedsize = currentsize; +} + +//____________________________________________________________________ +void VP1HttpGetFile_DownloadThread::run() { + + // NOTE!! TODO: This has to be ported to Qt 5!!! + /* + //////////////////////// + // Input validation // + //////////////////////// + + //Input validation ==> MD5 sum + + if ( !m_expectedMD5Sum.isEmpty() && !VP1MD5Sum::validMD5Sum(m_expectedMD5Sum) ) { + endInFailure("Invalid target md5sum: "+m_expectedMD5Sum,CLEANUPLOCALFILE); + return; + } + + //Input validation ==> URL + + if (m_urltofile.isEmpty()) { + endInFailure("Empty URL",DONTTOUCHLOCALFILE); + return; + } + + QUrl url(m_urltofile.contains("://") ? m_urltofile : "http://" + m_urltofile); + if (!url.isValid()||url.host().isEmpty()) { + endInFailure("Invalid URL: "+m_urltofile,DONTTOUCHLOCALFILE); + return; + } + //Input validation ==> Target file + + //File can not exist already and we abort if we are already + //downloading a file to that location: + QFileInfo fi(m_localtargetfile); + if (fi.exists()) { + //In one case we might still end well: if we know the target + //checksum and if the file has it (this also does away with + //several problems of "simultaneous downloads started": + if (!m_expectedMD5Sum.isEmpty()&&VP1MD5Sum::sumMatches(m_localtargetfile,m_expectedMD5Sum)) + return; + endInFailure ("Download target already exists: "+m_localtargetfile,DONTTOUCHLOCALFILE); + return; + } + if (!fi.dir().exists()) { + endInFailure("Directory ("+fi.dir().absolutePath()+") for download target does not exist: "+m_localtargetfile,DONTTOUCHLOCALFILE); + return; + } + + //Open target file: + QFile file(m_localtargetfile); + if (!file.open(QIODevice::WriteOnly)) { + endInFailure("Could not open file for write access: "+m_localtargetfile,DONTTOUCHLOCALFILE); + return; + } + + /////////////////////////////////// + // HTTP request and event loop // + /////////////////////////////////// + + m_http = new QHttp(0); + + connect(m_http,SIGNAL(done(bool)),this,SLOT(done(bool))); + connect(m_http,SIGNAL(dataReadProgress(int,int)),this,SLOT(dataReadProgress())); + + QHttpRequestHeader header("GET", url.path()+(url.hasQuery()?"?"+url.encodedQuery():QString(""))); + // ^^^ Todo: We could support username/passwd part of url also. + header.setValue("Host", url.host()); + header.setValue("User-Agent", "ATLASVP1"); + m_http->setHost(url.host()); + m_lastChangeTime = QDateTime::currentDateTime().toTime_t(); + + //Go: + m_http->request(header,0,&file); + QTimer timer(0); + connect(&timer, SIGNAL(timeout()), this, SLOT(checkForStall())); + timer.start(1000);//1s + exec(); + timer.stop(); + + //Cleanup http: + m_http->blockSignals(true); + if (m_http->hasPendingRequests()) + m_http->clearPendingRequests(); + if (m_http->currentId()!=0) + m_http->abort(); + delete m_http; + m_http = 0; + + file.close(); + + //Errors? + if (m_downloadFinishedStatus!=NOERRORS) { + switch(m_downloadFinishedStatus) { + case HTTPERROR: + endInFailure("Download finished with error "+m_http->errorString(),CLEANUPLOCALFILE); + return; + case STALLEDERROR: + endInFailure("Download stalled",CLEANUPLOCALFILE); + return; + case SIZEDECREASEDERROR: + endInFailure("Aborted since file was either removed or decreased in size.",CLEANUPLOCALFILE); + return; + default: + endInFailure("Unexpected download status (SHOULD NEVER HAPPEN)",CLEANUPLOCALFILE); + return; + } + } + + ///////////////////// + // Checksum test // + ///////////////////// + + if (!m_expectedMD5Sum.isEmpty()) { + bool match = VP1MD5Sum::sumMatches(m_localtargetfile,m_expectedMD5Sum); + if (!match) { + endInFailure("Checksum did not match",CLEANUPLOCALFILE); + return; + } + } + + //All ok: + + m_mutex.lock(); + m_errorString = ""; + m_mutex.unlock(); + */ + +} + +#endif diff --git a/graphics/VTI12/VTI12Gui/src/VP1IncomingMessageDialog.cxx b/graphics/VTI12/VTI12Gui/src/VP1IncomingMessageDialog.cxx new file mode 100644 index 000000000..84b6d2d28 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1IncomingMessageDialog.cxx @@ -0,0 +1,213 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////// +// // +// Implementation of class VP1IncomingMessageDialog // +// // +// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Initial version: April 2007 // +// // +///////////////////////////////////////////////////////////// + +#include "ui_vp1incomingmessagedialog.h" +#include "VTI12Gui/VP1IncomingMessageDialog.h" +#include "VTI12Gui/VP1TabManager.h" +#include "VTI12Gui/VP1ChannelManager.h" + +#include <QList> +#include <QMessageBox> + +#include <cassert> + +//____________________________________________________________________ +class VP1IncomingMessageDialog::Imp { +public: + Imp(const VP1ExternalRequest& r) : tabmanager{}, channelmanager{}, requestqueue{},request(r), + lcdNumber_pending{}, lcdNumber_pendingsender{}, lcdNumber_pendingexactsame{}, + blockallmessages{}, pushButton_allclear{}, pushButton_senderclear{}, + pushButton_messageclear{}, messages_blockedsenders{}, messages_blockedexactmessages{} + { + //nop + } + VP1TabManager* tabmanager; + VP1ChannelManager* channelmanager; + QQueue<VP1ExternalRequest>* requestqueue; + VP1ExternalRequest request; + QLCDNumber *lcdNumber_pending; + QLCDNumber *lcdNumber_pendingsender; + QLCDNumber *lcdNumber_pendingexactsame; + bool *blockallmessages; + QPushButton * pushButton_allclear; + QPushButton * pushButton_senderclear; + QPushButton * pushButton_messageclear; + QList<QString>* messages_blockedsenders; + QList<VP1ExternalRequest>* messages_blockedexactmessages; +}; + +//____________________________________________________________________ +VP1IncomingMessageDialog::VP1IncomingMessageDialog(const VP1ExternalRequest& r, + QQueue<VP1ExternalRequest>* rq, + bool *blockallmessages, + QList<QString>* messages_blockedsenders, + QList<VP1ExternalRequest>* messages_blockedexactmessages, + VP1TabManager* tm, + VP1ChannelManager* cm, + QWidget *parent) + : QDialog(parent), m_d(new Imp(r)) +{ + m_d->tabmanager= tm; + m_d->channelmanager= cm; + m_d->requestqueue = rq; + m_d->blockallmessages=blockallmessages; + m_d->messages_blockedsenders=messages_blockedsenders; + m_d->messages_blockedexactmessages=messages_blockedexactmessages; + Ui::VP1IncomingMessageForm ui; + ui.setupUi(this); + + m_d->pushButton_allclear = ui.pushButton_allclear; + m_d->pushButton_senderclear = ui.pushButton_senderclear; + m_d->pushButton_messageclear = ui.pushButton_messageclear; + + m_d->lcdNumber_pending = ui.lcdNumber_pending; + m_d->lcdNumber_pendingsender = ui.lcdNumber_pendingsender; + m_d->lcdNumber_pendingexactsame = ui.lcdNumber_pendingexactsame; + updatependinginfo(); + + connect(ui.pushButton_allclear,SIGNAL(clicked()),this,SLOT(request_allclear())); + connect(ui.pushButton_allblock,SIGNAL(clicked()),this,SLOT(request_allblock())); + connect(ui.pushButton_senderclear,SIGNAL(clicked()),this,SLOT(request_senderclear())); + connect(ui.pushButton_senderblock,SIGNAL(clicked()),this,SLOT(request_senderblock())); + connect(ui.pushButton_messageblock,SIGNAL(clicked()),this,SLOT(request_messageblock())); + connect(ui.pushButton_messageclear,SIGNAL(clicked()),this,SLOT(request_messageclear())); + + connect(ui.pushButton_showtab_gothere,SIGNAL(clicked()),this,SLOT(request_gothere())); + + ui.textBrowser_message->setText(m_d->request.message()); + ui.label_header->setText(ui.label_header->text().replace("SENDERPLACEHOLDER",m_d->request.sender())); + if (m_d->request.action()==VP1ExternalRequest::SHOWMESSAGE) { + ui.widget_showtab->hide(); + } else if (m_d->request.action()==VP1ExternalRequest::SHOWTAB) { + ui.label_showtab->setText(ui.label_showtab->text().replace("DUMMYTABNAME",m_d->request.actioninfo())); + if (m_d->tabmanager->hasTab(m_d->request.actioninfo())) { + ui.label_showtaberror->hide(); + } else { + ui.pushButton_showtab_gothere->hide(); + } + } else if (m_d->request.action()==VP1ExternalRequest::SHOWCHANNEL) { + ui.label_showtab->setText(ui.label_showtab->text().replace("tab","channel")); + ui.label_showtab->setText(ui.label_showtab->text().replace("DUMMYTABNAME",m_d->request.actioninfo())); + + if (m_d->channelmanager->channelWithBasenameIsLoaded(m_d->request.actioninfo())) { + ui.label_showtaberror->hide(); + } else { + ui.label_showtaberror->setText(ui.label_showtaberror->text().replace("tab","channel")); + ui.pushButton_showtab_gothere->hide(); + } + + } else { + assert(0&&"This should never happen unless you did not hardcode all action types!"); + } +} + +//____________________________________________________________________ +VP1IncomingMessageDialog::~VP1IncomingMessageDialog() +{ + delete m_d; m_d=0; +} + +//____________________________________________________________________ +void VP1IncomingMessageDialog::request_gothere() +{ + if (m_d->request.action()==VP1ExternalRequest::SHOWTAB) { + m_d->tabmanager->showTab(m_d->request.actioninfo()); + } else if (m_d->request.action()==VP1ExternalRequest::SHOWCHANNEL) { + m_d->tabmanager->showFirstChannelWithGivenBasename(m_d->request.actioninfo()); + } +} + +//____________________________________________________________________ +void VP1IncomingMessageDialog::updatependinginfo() +{ + m_d->lcdNumber_pending->display(m_d->requestqueue->count()); + int nsender(0); + foreach (VP1ExternalRequest er, *(m_d->requestqueue)) { + if (er.sender()==m_d->request.sender()) + ++nsender; + } + m_d->lcdNumber_pendingsender->display(nsender); + int nequal(0); + foreach (VP1ExternalRequest er, *(m_d->requestqueue)) { + if (m_d->request==er) + ++nequal; + } + m_d->lcdNumber_pendingexactsame->display(nequal); + + + m_d->pushButton_allclear->setEnabled(m_d->requestqueue->count()>0); + m_d->pushButton_senderclear->setEnabled(nsender>0); + m_d->pushButton_messageclear->setEnabled(nequal>0); +} + +//____________________________________________________________________ +void VP1IncomingMessageDialog::request_allclear() +{ + m_d->requestqueue->clear(); + updatependinginfo(); +} + +//____________________________________________________________________ +void VP1IncomingMessageDialog::request_allblock() +{ + int ret = QMessageBox::question(this, "VP1 - Block all incoming messages?", + "This will block all incoming messages to the application.\nProceed?", + QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Cancel ); + if (ret!=QMessageBox::Ok) + return; + *(m_d->blockallmessages)=true; + request_allclear(); +} + +//____________________________________________________________________ +void VP1IncomingMessageDialog::request_senderclear() +{ + QList<VP1ExternalRequest> tmp; + foreach (VP1ExternalRequest er, *(m_d->requestqueue)) { + if (!tmp.contains(er)&&er.sender()==m_d->request.sender()) + tmp<<er; + } + foreach (VP1ExternalRequest er, tmp) { + m_d->requestqueue->removeAll (er); + } + updatependinginfo(); +} + +//____________________________________________________________________ +void VP1IncomingMessageDialog::request_senderblock() +{ + *(m_d->messages_blockedsenders)<<m_d->request.sender(); + request_senderclear(); +} + +//____________________________________________________________________ +void VP1IncomingMessageDialog::request_messageclear() +{ + QList<VP1ExternalRequest> tmp; + foreach (VP1ExternalRequest er, *(m_d->requestqueue)) { + if (!tmp.contains(er)&&er==m_d->request) + tmp<<er; + } + foreach (VP1ExternalRequest er, tmp) { + m_d->requestqueue->removeAll(er); + } + updatependinginfo(); +} + +//____________________________________________________________________ +void VP1IncomingMessageDialog::request_messageblock() +{ + *(m_d->messages_blockedexactmessages)<<m_d->request; + request_messageclear(); +} diff --git a/graphics/VTI12/VTI12Gui/src/VP1LocalEvtRetriever.cxx b/graphics/VTI12/VTI12Gui/src/VP1LocalEvtRetriever.cxx new file mode 100644 index 000000000..1b6778281 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1LocalEvtRetriever.cxx @@ -0,0 +1,135 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "VP1LocalEvtRetriever.h" +#include "VTI12Gui/VP1AvailEvtsLocalDir.h" + +#include <QFile> +#include <QFileInfo> +#include <QTimer> +#include <QMutexLocker> + +VP1LocalEvtRetriever::VP1LocalEvtRetriever(VP1AvailEvtsLocalDir* availEvts + , QString sourcedir + , QObject* parent) + : QThread(parent) + , m_availEvts(availEvts) + , m_sourcedir(sourcedir) + , m_timer(0) +{ +} + +VP1LocalEvtRetriever::~VP1LocalEvtRetriever() +{ + delete m_timer; +} + +void VP1LocalEvtRetriever::run() +{ + m_timer = new QTimer(0); + connect(m_timer, SIGNAL(timeout()), this, SLOT(updateLocalDirFromSource()),Qt::DirectConnection); + m_timer->start(3000); + updateLocalDirFromSource(); + exec(); +} + +void VP1LocalEvtRetriever::updateLocalDirFromSource() +{ + QMutexLocker locker(&m_mutex); + updateLocalDir(); +} + +void VP1LocalEvtRetriever::updateLocalDir() +{ + QList<VP1EventFile> evts = m_availEvts->allEventFilesInDir(m_sourcedir); + if (evts.isEmpty()) { + m_availEvts->cleanupAndCheckForEventListChanges();//In case we e.g. changed to an empty input directory + return; + } + //We don't copy more than enough to give us 3 fresh files. But if + //there are more available, we will check back in 3 seconds. + + const int nfreshneeded = 3 - m_availEvts->freshEvents().count(); + if (evts.count()>m_availEvts->maxLocalFilesToKeep()+3&&nfreshneeded<=0) { + //Don't copy anything, but schedule cleanup and check back in 3 seconds: + m_availEvts->cleanupAndCheckForEventListChanges(); +// --- todo? QTimer::singleShot(3000, this, SLOT(updateLocalDirFromSource())); + return; + } + + static unsigned ntmpdlcount = 0; + + QList<VP1EventFile> freshEvtsInSource = m_availEvts->freshEvents(evts.front(), evts); + + QString ad = m_availEvts->tmpActiveRetrievalDir(); + QString tmplocal = m_availEvts->tmpLocalFileDir(); + bool changestmplocal(false), changesad(false); + if (!ad.isEmpty()&&!tmplocal.isEmpty()) { + int ncopied(0); + foreach (VP1EventFile evt, freshEvtsInSource) { + QString fn = evt.fileName(); + QString basefn = QFileInfo(fn).fileName(); + QString target = tmplocal + basefn; + if (!QFile::exists(target)) { + QString tmptarget = ad+basefn+"_"+QString::number(ntmpdlcount++); + if (!QFile::copy(fn,tmptarget)) { + m_availEvts->message("Problems copying "+fn+" to "+tmptarget); + changesad = true; + } else { + if (!QFile::rename(tmptarget,target)) { + m_availEvts->message("Problems moving "+tmptarget+" to "+target+" directory"); + changesad = true; + } else { + if (!QFile::exists(target)) { + m_availEvts->message("Inconsistent copy of "+basefn+" to local tmp directory"); + } else { + ++ncopied; + m_availEvts->messageDebug("Copied "+basefn+" to local tmp directory");//Fixme: verbose! + changestmplocal = true; + } + } + } + } + if (ncopied>=nfreshneeded) { +// -- todo? QTimer::singleShot(3000, this, SLOT(updateLocalDirFromSource())); + break; + } + } + } else { + m_availEvts->message("Problems with temporary local directories."); + } + if (changestmplocal) + m_availEvts->invalidateDirCache(tmplocal); + if (changesad) + m_availEvts->invalidateDirCache(ad); + m_availEvts->cleanupAndCheckForEventListChanges(); +} + +void VP1LocalEvtRetriever::setSourceDir(QString dir) +{ + QMutexLocker locker(&m_mutex); + + if (!dir.endsWith("/")) + dir += "/"; + if (m_sourcedir==dir) + return; + + //Ensure that the next event is from the new directory by removing + //all cached fresh events: + + while (true) { + QList<VP1EventFile> freshevts = m_availEvts->freshEvents(); + if (freshevts.isEmpty()) + break; + foreach(VP1EventFile evt, freshevts) { + QString fn = evt.fileName(); + if (!QFile::remove(fn)) + m_availEvts->message("ERROR: Could not remove "+fn); + } + } + + //Now change directory + m_sourcedir = dir; + updateLocalDir(); +} diff --git a/graphics/VTI12/VTI12Gui/src/VP1LocalEvtRetriever.h b/graphics/VTI12/VTI12Gui/src/VP1LocalEvtRetriever.h new file mode 100644 index 000000000..4b436b5c7 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1LocalEvtRetriever.h @@ -0,0 +1,43 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef VP1LocalEvtRetriever_h +#define VP1LocalEvtRetriever_h + +#include <QThread> +#include <QString> +#include <QMutex> + +class VP1AvailEvtsLocalDir; +class QTimer; + +class VP1LocalEvtRetriever : public QThread +{ + Q_OBJECT + + public: + VP1LocalEvtRetriever(VP1AvailEvtsLocalDir* + ,QString + ,QObject* parent = 0); + ~VP1LocalEvtRetriever(); + + void setSourceDir(QString); + + public slots: + void updateLocalDirFromSource(); + + protected: + void run(); + + private: + void updateLocalDir(); // Called by updateLocalDirFromSource() and by setSourceDir(QString) + // Does the actual work. Has been introduced in order to avoid mutex deadlocks + + VP1AvailEvtsLocalDir* m_availEvts; + QString m_sourcedir; + QTimer* m_timer; + QMutex m_mutex; +}; + +#endif diff --git a/graphics/VTI12/VTI12Gui/src/VP1MD5Sum.cxx b/graphics/VTI12/VTI12Gui/src/VP1MD5Sum.cxx new file mode 100644 index 000000000..952516c54 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1MD5Sum.cxx @@ -0,0 +1,99 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class VP1MD5Sum // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: May 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12Gui/VP1MD5Sum.h" +#include <QFileInfo> +#include <QCryptographicHash> +#include <QRegExp> + +//____________________________________________________________________ +class VP1MD5Sum::Imp { +public: + static bool fileok(const QString& filename); + static QByteArray actualMd5Sum( const QString& filename, bool&ok ); +}; + +//____________________________________________________________________ +QByteArray VP1MD5Sum::sum(const QString& filename) +{ + if (!Imp::fileok(filename)) + return QByteArray(); + bool ok; + QByteArray arr = Imp::actualMd5Sum(filename,ok); + return ok ? arr : QByteArray(); +} + +//____________________________________________________________________ +bool VP1MD5Sum::sumMatches( const QString& filename, const QByteArray& targetmd5sum ) +{ + if (targetmd5sum.isEmpty()||!Imp::fileok(filename)) + return false; + bool ok; + return targetmd5sum==Imp::actualMd5Sum(filename,ok) && ok; +} + +//____________________________________________________________________ +bool VP1MD5Sum::sumMatches( const QString& filename, const QString& md5sum ) +{ + return sumMatches( filename, sumToByteArray(md5sum) ); +} + +//____________________________________________________________________ +bool VP1MD5Sum::Imp::fileok(const QString& filename) +{ + QFileInfo fi(filename); + return fi.exists() && fi.isReadable(); +} + +//____________________________________________________________________ +QByteArray VP1MD5Sum::Imp::actualMd5Sum( const QString& filename, bool&ok ) +{ + ok = false; + QFile file(filename); + QCryptographicHash md5Hash(QCryptographicHash::Md5); + + if (file.open(QIODevice::ReadOnly | QIODevice::Unbuffered)) { + ok = true; + while (!file.atEnd()) + md5Hash.addData(file.read(10485760)); + } + file.close(); + return md5Hash.result(); +} + +//____________________________________________________________________ +QString VP1MD5Sum::sumToString(const QByteArray& ba ) +{ + return ba.toHex(); +} + +//____________________________________________________________________ +QByteArray VP1MD5Sum::sumToByteArray(const QString& str ) +{ + return QByteArray::fromHex(QByteArray().append(str)); +} + +//____________________________________________________________________ +bool VP1MD5Sum::validMD5Sum(const QString& sum) +{ + if (sum.count()!=32) + return false; + return QRegExp("[0-9a-z]*").exactMatch(sum.toLower()); +} + +//____________________________________________________________________ +QString VP1MD5Sum::sumToStandardFormat(const QString& sum) +{ + return sum.simplified().toLower(); +} diff --git a/graphics/VTI12/VTI12Gui/src/VP1MainWindow.cxx b/graphics/VTI12/VTI12Gui/src/VP1MainWindow.cxx new file mode 100644 index 000000000..f86ddf08f --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1MainWindow.cxx @@ -0,0 +1,1943 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////// +// // +// Implementation of class VP1MainWindow // +// // +// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Initial version: April 2007 // +// +// Updates: +// - Riccardo.Maria.Bianchi@cern.ch +// // +///////////////////////////////////////////////////////////// + +#include "VTI12Gui/VP1MainWindow.h" + +#include "VTI12Gui/VP1ChannelManager.h" +#include "VTI12Gui/VP1TabManager.h" +#include "VTI12Gui/VP1ExecutionScheduler.h" +#include "VTI12Gui/VP1IncomingMessageDialog.h" +#include "VTI12Gui/VP1PluginDialog.h" +#include "VTI12Gui/VP1DockWidget.h" +#include "VTI12Gui/VP1AvailEvents.h" +#include "VTI12Gui/VP1AvailEvtsLocalDir.h" +#include "VP1StreamMenuUpdater.h" + +#ifdef BUILDVP1LIGHT + #include "VP1Gui/VP1ExpertSettings.h" + #include "VP1Gui/VP1GeoDBSelection.h" + #include "VP1Gui/VP1AODSelection.h" + #include "VP1Gui/VP1SelectEvent.h" +#endif + +#include "VP1UtilsBase/VP1FileUtilities.h" + +#include "VP1Base/IVP1ChannelWidget.h" +#include "VP1Base/IVP1System.h" +#include "VP1Base/VP1Msg.h" +#include "VP1Base/VP1Settings.h" +#include "VP1Base/VP1QtUtils.h" + + +#include <QMessageBox> +#include <QInputDialog> +#include <QLabel> +#include <QCloseEvent> +#include <QFileDialog> +#include <QDir> +#include <QTimer> +#include <QSettings> +#include <QComboBox> +#include <QPainter> +#include <QPrinter> +#include <QPrintDialog> +#include <QProgressBar> +#include <QStyleFactory> +#include <QDateTime> +#include <QMutex> +#include <QDesktopServices> +#include <QUrl> +#include <QProcess> +#include <QGraphicsView> +#include <QGraphicsScene> +#include <QtGui> +#include <QSettings> +#include <QScrollBar> + + + +/* FIXME: LCG does not ship QWebEngine with Qt5 at the moment, + * but later you want to put it back again! + */ +/* +#include <QtGlobal> +#if QT_VERSION > QT_VERSION_CHECK(5, 5, 0) + #include <QWebEngineView> // Qt 5.6 +#else + #include <QtWebKit> +#endif +*/ + +#include <cassert> +#include <iostream> + + +//_________________________________________________________________________________ +VP1MainWindow::VP1MainWindow(VP1ExecutionScheduler*sched,VP1AvailEvents * ae,QWidget * parent) +: QMainWindow(parent), + m_runnumber(-1), + m_eventnumber(-1), + m_betweenevents(true), + m_mustquit(false), + m_dummyemptycontroller(new QWidget(0)), + m_scheduler(sched), + m_availEvents(ae), + m_settingsfile(QDir::homePath()+QDir::separator()+".atlasvp1"), + m_userRequestedExit(false), + m_streamMenuUpdater(0), + m_mutex(new QMutex()), +// #if QT_VERSION > QT_VERSION_CHECK(5, 5, 0) +// m_view(new QWebEngineView(0)), +// #else +// m_view(new QWebView(0)), +// #endif + m_edEditor(0) +{ + setupUi(this); // this sets up the GUI + + setupStatusBar(); + // + #if defined BUILDVP1LIGHT + bool checkShowAllCruiseAndEventControls = VP1QtUtils::expertSettingIsSet("expert","ExpertSettings/VP1_DEVEL_SHOW_ALL_CRUISE_AND_EVENT_CONTROLS"); + #else + bool checkShowAllCruiseAndEventControls = VP1QtUtils::environmentVariableIsOn("VP1_DEVEL_SHOW_ALL_CRUISE_AND_EVENT_CONTROLS"); + #endif + + if (!checkShowAllCruiseAndEventControls) { + pushButton_eventseek->setVisible(false); + groupBox_cruise->setVisible(false); + } + + if (m_availEvents) { + connect(m_availEvents,SIGNAL(message(const QString&)),this,SLOT(helperAddToMessageBox(const QString&))); + connect(m_availEvents,SIGNAL(freshEventsChanged()),this,SLOT(updateEventControls())); + } + + // File menu + if(!m_availEvents) { + QMenu* menu_file = new QMenu(menubar); + menu_file->setObjectName("menu_file"); + menu_file->setTitle("&File"); + menubar->addAction(menu_file->menuAction()); + m_action_addEventFile = menu_file->addAction("&Add event file ..."); + + connect(m_action_addEventFile,SIGNAL(triggered(bool)),this,SLOT(addEventFile())); + } + + #ifndef BUILDVP1LIGHT + pushButton_previousevent->setVisible(false); + pushButton_eventselect->setVisible(false); + #else + pushButton_eventselect->setVisible(true); + pushButton_eventselect->setText("Event: 0/0"); + pushButton_eventselect->setEnabled(false); + pushButton_previousevent->setEnabled(false); + //Disable all controls that are not available in VP1Light + // pushButton_quicksetup_3dcocktail->setEnabled(false); + // pushButton_quicksetup_3dcocktail->setToolTip("Not available in VP1Light"); + pushButton_quicksetup_trackingstudies->setEnabled(false); + pushButton_quicksetup_trackingstudies->setToolTip("Not available in VP1Light"); + pushButton_quicksetup_calostudies->setEnabled(false); + pushButton_quicksetup_calostudies->setToolTip("Not available in VP1Light"); + action_quicklaunch_Tracking_studies->setEnabled(false); + action_quicklaunch_Tracking_studies->setToolTip("Not available in VP1Light"); + action_quicklaunch_Calo_studies->setEnabled(false); + action_quicklaunch_Calo_studies->setToolTip("Not available in VP1Light"); + action_quicklaunch_Storegate_browser->setEnabled(false); + action_quicklaunch_Storegate_browser->setToolTip("Not available in VP1Light"); + action_quicklaunch_trackcalo_commis->setEnabled(false); + action_quicklaunch_trackcalo_commis->setToolTip("Not available in VP1Light"); + m_action_addEventFile->setEnabled(false); + #endif + + //////////////////////////////////////////////////// + //Do we need a menu for multiple input directories? + + VP1AvailEvtsLocalDir* availLocal = dynamic_cast<VP1AvailEvtsLocalDir*>(m_availEvents); + + QStringList inputdirs; + if (availLocal) + inputdirs = availLocal->availableSourceDirectories(); + + if (availLocal&&!inputdirs.isEmpty()) { + + QString currentdir = availLocal->currentSourceDir(); + if (currentdir.endsWith("/")) + currentdir.chop(1); + m_currentStream = QDir(currentdir).dirName(); + QMenu * menu_inputdir = new QMenu(menubar); + menu_inputdir->setObjectName("menu_inputdir"); + menu_inputdir->setTitle("&Stream"); + + menubar->addAction(menu_inputdir->menuAction()); + + QActionGroup * inputdir_actiongroup = new QActionGroup(menu_inputdir); + QAction*action_inputdir_current(0); + foreach (QString inputdir, inputdirs) { + if (inputdir.endsWith("/")) + inputdir.chop(1); + QString dirname = QDir(inputdir).dirName(); + QAction * action_inputdir = new QAction(this); + action_inputdir->setObjectName("action_inputdir_"+dirname); + action_inputdir->setData(inputdir); + action_inputdir->setStatusTip("Get input files from: "+inputdir); + action_inputdir->setCheckable(true); + + if (currentdir==inputdir) + action_inputdir_current = action_inputdir; + menu_inputdir->addAction(action_inputdir); + inputdir_actiongroup->addAction(action_inputdir); + m_inputdiractions << action_inputdir; + connect(action_inputdir,SIGNAL(triggered(bool)),this,SLOT(inputDirectoryActionTriggered())); + } + if (action_inputdir_current) { + action_inputdir_current->blockSignals(true); + action_inputdir_current->setChecked(true); + action_inputdir_current->blockSignals(false); + } + + // Populate inputdirstatuses + foreach(QAction* action, m_inputdiractions) + m_inputdirstatuses[action] = VP1DirStatusData(action->data().toString(), + QString(), + true, + false); + + m_streamMenuUpdater = new VP1StreamMenuUpdater(m_inputdirstatuses,m_mutex); + m_streamMenuUpdater->start(); + + //Fixme: start timer which every minute checks the status of these directories + QTimer *timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), this, SLOT(updateInputDirectoriesStatus())); + timer->start(5000);//update this menu rather often (this is only for P1 anyway) + } + + //....... + + m_channelmanager = new VP1ChannelManager(m_scheduler,this); + m_tabmanager = new VP1TabManager(this,tabWidget_central,m_channelmanager); + stackedWidget_customcontrols->addWidget(m_dummyemptycontroller); + + //Final touches to instructions page: + + // Remove any margins added by the layouts in the stacked + // widget. This really ought to be the default for stacked widgets! + for (int i=0;i<stackedWidget_central->count();++i) + stackedWidget_central->widget(i)->layout()->setContentsMargins(0,0,0,0); + + frame_instructions->setStyleSheet("QFrame#frame_instructions { "+VP1DockWidget::highlightStyle()+" } "); + frame_instructions->setFrameShape(QFrame::StyledPanel); + // textBrowser_intro1->setStyleSheet("QTextBrowser#textBrowser_intro1 { background-color: rgba(0, 0, 0, 0%) } "); + // textBrowser_intro2->setStyleSheet("QTextBrowser#textBrowser_intro2 { background-color: rgba(0, 0, 0, 0%) } "); + #ifndef BUILDVP1LIGHT + connect(pushButton_quicksetup_faser,SIGNAL(clicked()),this,SLOT(quickSetupTriggered())); + #else + connect(pushButton_quicksetup_faser,SIGNAL(clicked()),this,SLOT(quickSetupTriggered())); + #endif + // connect(pushButton_quicksetup_trackingstudies,SIGNAL(clicked()),this,SLOT(quickSetupTriggered())); + // connect(pushButton_quicksetup_calostudies,SIGNAL(clicked()),this,SLOT(quickSetupTriggered())); + connect(pushButton_quicksetup_geometrystudies,SIGNAL(clicked()),this,SLOT(quickSetupTriggered())); + connect(pushButton_quicksetup_analysisstudies,SIGNAL(clicked()),this,SLOT(quickSetupTriggered())); + + //Default application font: + m_defaultfont = QApplication::font(); + m_defaultfont_pointsize = m_defaultfont.pointSizeF(); + if (m_defaultfont_pointsize<0.0) + m_defaultfont_pixelsize = m_defaultfont.pixelSize(); + else + m_defaultfont_pixelsize = -1; + + //Tabs: + connect(m_tabmanager,SIGNAL(tabListChanged(QStringList)),this,SLOT(tabListChanged(QStringList))); + connect(tabWidget_central,SIGNAL(currentChanged(int)),this,SLOT(updateCentralStackWidget())); + updateCentralStackWidget(); + + //Channels: + + connect(pushButton_saveAllChannels,SIGNAL(clicked()),this,SLOT(saveAllCurrentChannels())); + connect(pushButton_makeEventDisplay,SIGNAL(clicked()),this,SLOT(makeAllChannelsEventDisplay())); + + connect(pushButton_3D,SIGNAL(clicked()),this,SLOT(launch3DstereoEditor())); + + connect(pushButton_channelfullscreen,SIGNAL(clicked()),m_tabmanager,SLOT(showCurrentChannelFullScreen())); + connect(pushButton_channelinformation,SIGNAL(clicked()),this,SLOT(request_channelInformation())); + connect(pushButton_printchannel,SIGNAL(clicked()),this,SLOT(request_printChannel())); + connect(pushButton_savesnapshotchannel,SIGNAL(clicked()),this,SLOT(request_saveChannelSnapshot())); + connect(m_tabmanager,SIGNAL(selectedChannelChanged(IVP1ChannelWidget*)),this,SLOT(selectedChannelChanged(IVP1ChannelWidget*))); + + //Menu: + //Quick start: + // connect(action_quicklaunch_Tracking_studies,SIGNAL(triggered(bool)),this,SLOT(quickSetupTriggered())); + // connect(action_quicklaunch_Calo_studies,SIGNAL(triggered(bool)),this,SLOT(quickSetupTriggered())); + connect(action_quicklaunch_Geometry_studies,SIGNAL(triggered(bool)),this,SLOT(quickSetupTriggered())); + connect(action_quicklaunch_analysisstudies,SIGNAL(triggered(bool)),this,SLOT(quickSetupTriggered())); + connect(action_quicklaunch_Storegate_browser,SIGNAL(triggered(bool)),this,SLOT(quickSetupTriggered())); + connect(action_quicklaunch_faser,SIGNAL(triggered(bool)),this,SLOT(quickSetupTriggered())); + // connect(action_quicklaunch_trackcalo_commis,SIGNAL(triggered(bool)),this,SLOT(quickSetupTriggered())); + connect(action_exit_VP1,SIGNAL(triggered(bool)),this,SLOT(close())); + + //Configuration + m_menu_loadConfFile = menuConfiguration->addMenu ( "&Load tab configuration from file" ); + m_menu_loadConfFile->setStatusTip("Select .vp1 config file to load"); + connect(m_menu_loadConfFile,SIGNAL(aboutToShow()),this,SLOT(showMenu_loadConfFile())); + menuConfiguration->addSeparator(); + //plugins: + m_menu_loadPlugin = menuConfiguration->addMenu ( "&Load plugin" ); + m_menu_loadPlugin->setStatusTip("Select plugin to load"); + // m_action_infoAboutLoadedPlugins = menuPlugins->addAction ( "&Info about loaded plugins" ); + // m_action_infoAboutLoadedPlugins->setStatusTip("Get information about the presently loaded plugins"); + // m_action_infoAboutLoadedPlugins->setEnabled(false); + connect(m_menu_loadPlugin,SIGNAL(aboutToShow()),this,SLOT(showMenu_loadPlugin())); + //Style + m_menu_changeStyle = menu_Style->addMenu ( "&Style" ); + QActionGroup * styleGroup = new QActionGroup(this); + QAction * laststyleact(0); + bool foundplastique=false; + QSettings s(m_settingsfile,QSettings::IniFormat); + QString defaultstyle=s.value("style/defaultstyle", "Fusion").toString(); + foreach (QString style, QStyleFactory::keys() ) { + QAction * act = m_menu_changeStyle->addAction(style); + act->setStatusTip("Change application style to "+style); + connect(act,SIGNAL(triggered(bool)),this,SLOT(changeStyleActionTriggered())); + act->setCheckable(true); + styleGroup->addAction(act); + laststyleact=act; + if (act->text()==defaultstyle) { + act->setChecked(true); + QApplication::setStyle(QStyleFactory::create(act->text())); + foundplastique=true; + } + } + if (!foundplastique) { + laststyleact->setChecked(true); + QApplication::setStyle(QStyleFactory::create(laststyleact->text())); + } + //Fonts: + int savedgoal = 0; + if (m_defaultfont_pointsize<0.0) + savedgoal = s.value("font/pixelsize_diff", 0).toInt(); + else + savedgoal = s.value("font/pointsize_relativepercent", 0).toInt(); + + m_menu_changeFontSize = menu_Style->addMenu ( "&Font size" ); + QList<int> fontoptions; + if (m_defaultfont_pointsize<0.0) + fontoptions <<15<<10<<+5<<+3<<+2<<+1<<0<<-1<<-2<<-3<<-5<<-10<<-20<<-30; + else + fontoptions <<150<<100<<50<<30<<20<<10<<5<<0<<-5<<-10<<-20<<-30<<-50; + + QActionGroup * fontGroup = new QActionGroup(this); + bool foundsavedgoal(false); + QAction * normalfontact(0); + foreach (int fontopt,fontoptions) { + if (m_defaultfont_pixelsize>0&&m_defaultfont_pixelsize+fontopt<=0) + continue; + QString text = (fontopt==0?"normal": (fontopt>0?"+":"")+QString::number(fontopt)+(m_defaultfont_pointsize < 0.0? " pixels" : "%")); + QAction * act = m_menu_changeFontSize->addAction(text); + act->setStatusTip("Change overall font size of application to "+text); + act->setData(fontopt); + act->setCheckable(true); + fontGroup->addAction(act); + connect(act,SIGNAL(triggered(bool)),this,SLOT(changeFontSizeActionTriggered())); + if (fontopt==0) + normalfontact=act; + if (savedgoal==fontopt) { + act->setChecked(true); + changeFontSize(fontopt); + foundsavedgoal=true; + } + } + if (!foundsavedgoal) { + normalfontact->setChecked(true); + } + + // + m_actionSave_current_tabs = menuConfiguration->addAction ( "&Save current tab configuration to file" ); + m_actionSave_current_tabs->setStatusTip("Save current tab/channel layout to .vp1 config file"); + menuConfiguration->addSeparator(); + m_actionAdd_empty_tab = menuConfiguration->addAction ( "&Add empty tab" ); + m_actionAdd_empty_tab->setStatusTip("Add empty tab to the current tab list"); + connect(m_actionAdd_empty_tab,SIGNAL(triggered(bool)),this,SLOT(request_addEmptyTab())); + connect(m_actionSave_current_tabs,SIGNAL(triggered(bool)),this,SLOT(request_saveasConfig())); + + //ExpertSettings + #ifdef BUILDVP1LIGHT + menuConfiguration->addSeparator(); + m_actionEnableExpertSettings = menuConfiguration->addAction ( "&Settings" ); + m_actionEnableExpertSettings->setStatusTip("Open additional settings"); + connect(m_actionEnableExpertSettings, &QAction::triggered, this, &VP1MainWindow::request_expertSettings); + #endif + + //Event navigation: + connect(pushButton_nextevent,SIGNAL(clicked()),this,SLOT(goToNextEvent())); + #ifdef BUILDVP1LIGHT + connect(pushButton_previousevent,SIGNAL(clicked()),this,SLOT(goToPreviousEvent())); + connect(pushButton_eventselect,SIGNAL(clicked()),this,SLOT(chooseEvent())); + #endif + + //Listen for external requests: + connect(&m_tcpserver,SIGNAL(receivedExternalRequest(VP1ExternalRequest)),this,SLOT(receivedExternalRequest(VP1ExternalRequest))); + listenOnTcp(); + // updateTcpIcon(); + connect(&m_tcpserver,SIGNAL(listenStateChanged(bool)),this,SLOT(updateTcpIcon())); + updateTcpIcon(); + m_currentincomingdialog=0; + m_blockallmessages=false; + m_plugindialog=0; + + //Cruise: + connect(pushButton_cruise,SIGNAL(clicked()),this,SLOT(request_cruisemodechange())); + connect(radioButton_cruise_event,SIGNAL(clicked()),this,SLOT(request_cruisemodechange())); + connect(radioButton_cruise_tab,SIGNAL(clicked()),this,SLOT(request_cruisemodechange())); + connect(radioButton_cruise_both,SIGNAL(clicked()),this,SLOT(request_cruisemodechange())); + + // Help menu + QMenu* menu_help = new QMenu(menubar); + menu_help->setObjectName("menu_help"); + menu_help->setTitle("&Help"); + menubar->addAction(menu_help->menuAction()); + m_action_openVP1Site = menu_help->addAction("VP1 &Web Site"); + m_action_openUsersGuide = menu_help->addAction("VP1 &User's Guide"); + m_action_openUsersSupport = menu_help->addAction("VP1 User's &Support (in the system browser)"); + menu_help->addSeparator(); + m_action_openAbout = menu_help->addAction("&About VP1"); + + QTimer::singleShot(0, this, SLOT(postInitUpdates())); + m_currentsaveimagepath = VP1Settings::defaultFileSelectDirectory(); + m_currentloadpluginpath = VP1Settings::defaultFileSelectDirectory(); + + connect(m_action_openUsersGuide,SIGNAL(triggered(bool)),this,SLOT(help_openUserGuide())); + connect(m_action_openVP1Site,SIGNAL(triggered(bool)),this,SLOT(help_openVP1WebSite())); + connect(m_action_openUsersSupport,SIGNAL(triggered(bool)),this,SLOT(help_openUserSupport())); + connect(m_action_openAbout,SIGNAL(triggered(bool)),this,SLOT(help_openAbout())); + + // FIXME: enabling menubar again. It's part of a quickfix, described here: https://its.cern.ch/jira/browse/ATLASVPONE-120 + #ifndef BUILDVP1LIGHT + menubar->setEnabled(false); + #endif +} + +//_________________________________________________________________________________ +void VP1MainWindow::launch3DstereoEditor() +{ + VP1Msg::messageDebug("VP1MainWindow::launch3DstereoEditor()"); + m_tabmanager->launchStereoEditorCurrentTab(); + +} + +//_________________________________________________________________________________ +void VP1MainWindow::help_openUserGuide() { + /* + * Open the online help from a web url location + * with the default system web browser + */ + VP1Msg::messageDebug("VP1MainWindow::help_openUserGuide()"); +// +// // we use the Qt Web Browser to show the VP1 documentation +// #if QT_VERSION > QT_VERSION_CHECK(5, 5, 0) +// QWebEngineView *old = m_view; +// m_view = new QWebEngineView(0); +// #else +// QWebView *old = m_view; +// m_view = new QWebView(0); +// #endif +// +// m_view->load(QUrl("http://atlas-vp1.web.cern.ch/atlas-vp1/doc/")); +// m_view->show(); +// delete old; old = 0; + + return; +} + +//_________________________________________________________________________________ +void VP1MainWindow::help_openUserSupport() { + /* + * Open the online page with links to the JIRA issue collectors + * with the default system web browser + */ + VP1Msg::messageDebug("VP1MainWindow::help_openUserSupport()"); + + // fixme: apparently javascript does not work in the embedded browser, so I use the default system one + + // we use here the default system browser + QDesktopServices::openUrl(QUrl("http://atlas-vp1.web.cern.ch/atlas-vp1/vp1_users_support/")); + +// // we use the Qt Web Browser to show the VP1 user's support page +// QWebEngineView *old = m_view; +// m_view = new QWebEngineView(0); +// m_view->load(QUrl("http://atlas-vp1.web.cern.ch/atlas-vp1/vp1_users_support_em/")); +// m_view->show(); +// delete old; old = 0; + + return; +} + +//_________________________________________________________________________________ +void VP1MainWindow::help_openVP1WebSite() { + /* + * Open the online help from a web url location + * with the default system web browser + */ + VP1Msg::messageDebug("VP1MainWindow::help_openVP1WebSite()"); +// +// // we use the Qt Web Browser to show the VP1 web site +// #if QT_VERSION > QT_VERSION_CHECK(5, 5, 0) +// QWebEngineView *old = m_view; +// m_view = new QWebEngineView(0); +// #else +// QWebView *old = m_view; +// m_view = new QWebView(0); +// #endif +// +// m_view->resize(1000, 800); +// m_view->load(QUrl("http://atlas-vp1.web.cern.ch/atlas-vp1/")); +// m_view->show(); +// delete old; old = 0; + return; +} + + +//_________________________________________________________________________________ +void VP1MainWindow::help_openAbout() { + /* + * open the online help with the internal web browser + */ + VP1Msg::messageDebug("VP1MainWindow::help_openAbout()"); +// +// // we use the Qt Web Browser to show the VP1 "About" page +// #if QT_VERSION > QT_VERSION_CHECK(5, 5, 0) +// QWebEngineView *old = m_view; +// m_view = new QWebEngineView(0); +// #else +// QWebView *old = m_view; +// m_view = new QWebView(0); +// #endif +// +// m_view->load(QUrl("https://atlas-vp1.web.cern.ch/atlas-vp1/doc_new/about_vp1/CREDITS.html")); +// m_view->show(); +// delete old; old = 0; + + return; +} + + +//_________________________________________________________________________________ +void VP1MainWindow::postInitUpdates(){ + + //Make sure that the splitters give maximum space for the tab area. + + int sum1 = splitter_tabwidget_messagebox->sizes().at(0) + splitter_tabwidget_messagebox->sizes().at(1); + QList<int> sizes1; sizes1 << sum1 << 0; + splitter_tabwidget_messagebox->setSizes ( sizes1 ); + int bottom = 1; + while (splitter_tabwidget_messagebox->sizes().at(1)==0&&bottom<50000) { + QList<int> sizes2; sizes2 << sum1-bottom << bottom; + splitter_tabwidget_messagebox->setSizes ( sizes2 ); + ++bottom; + } + + int sum2 = splitter_leftright->sizes().at(0) + splitter_leftright->sizes().at(1); + int left = 300; + QList<int> sizes3; sizes3 << left << sum2-left; + splitter_leftright->setSizes ( sizes3 ); + while (splitter_leftright->sizes().at(0)==0&&left<50000) { + QList<int> sizes4; sizes4 << left << sum2-left; + splitter_leftright->setSizes ( sizes4 ); + ++left; + } + + int prefwidths = std::max<int>(left,widget_controlsContainer->sizeHint().width()); + prefwidths = std::max<int>(prefwidths,groupBox_channelcontrols->sizeHint().width()); + prefwidths = std::max<int>(prefwidths,groupBox_cruise->sizeHint().width()); + prefwidths = std::max<int>(prefwidths,groupBox_event->sizeHint().width()); + prefwidths = std::max<int>(prefwidths,stackedWidget_customcontrols->sizeHint().width()); + widget_controlsContainer->setMaximumWidth(50+prefwidths); + // int h1(textBrowser_intro1->viewport()->sizeHint().height()); + // textBrowser_intro1->setMaximumHeight(h1+2); + if (m_availEvents) + m_availEvents->init(); + updateEventControls(); +} + +//_________________________________________________________________________________ +void VP1MainWindow::setupStatusBar() { + progressbar = new QProgressBar(); + progressbar->setMinimum(0); + progressbar->reset(); + progressbar->setOrientation(Qt::Horizontal); + statusBar()->addPermanentWidget(progressbar); + m_statusbarlabel = new QLabel(); + //Turn off ugly box around items in statusbar: + statusBar()->setStyleSheet("QStatusBar::item { border-width: 0 }"); + statusBar()->addPermanentWidget(m_statusbarlabel); + progressbar->hide(); +} + +//_________________________________________________________________________________ +VP1MainWindow::~VP1MainWindow() +{ + if (m_edEditor) { + VP1Msg::messageDebug("deleting the editor"); + delete m_edEditor; + } + VP1Msg::messageDebug("deleting the tab manager"); + delete m_tabmanager; + VP1Msg::messageDebug("deleting the channel manager"); + delete m_channelmanager; + VP1Msg::messageDebug("deleting the events"); + delete m_availEvents; + + if(m_streamMenuUpdater) { + VP1Msg::messageDebug("deleting the streamupdater"); + m_streamMenuUpdater->quit(); + m_streamMenuUpdater->deleteLater(); + } + + VP1Msg::messageDebug("deleting the mutex"); + delete m_mutex; + + VP1Msg::messageDebug("deleting the view"); +// delete m_view; // TODO: Qt5 +// m_view = 0;// TODO: Qt5 +} + +//_________________________________________________________________________________ +bool VP1MainWindow::mustQuit() const { + return m_mustquit; +} + + +//_________________________________________________________________________________ +void VP1MainWindow::updateTcpIcon() +{ + bool l = m_tcpserver.isListening(); + m_statusbarlabel->setPixmap(QIcon(l?":/vp1/icons/icons/network_64x64.png":":/vp1/icons/icons/network_disconnect_64x64.png") + .pixmap(progressbar->height(),progressbar->height(),QIcon::Normal,QIcon::On)); + m_statusbarlabel->setToolTip(l?"Listening on port "+QString::number(m_tcpserver.port())+" for incoming messsages" + :"VP1 is presently NOT listening for incoming messages"); + +} + +//_________________________________________________________________________________ +void VP1MainWindow::loadPluginFile(QString filename) +{ + VP1Msg::messageDebug("loadPluginFile()"); + + QString err = m_channelmanager->loadPluginFile(filename); + if (!err.isEmpty()) { + QMessageBox::critical(0, "Error - could not load plugin file: "+filename, + "Could not load plugin file: " + +filename+"\n\nReason: "+err,QMessageBox::Ok,QMessageBox::Ok); + VP1Msg::message("Could not load plugin file: "+filename+"\n\nReason: "+err); + } + //Fixme: Error message here is hardcoded to be the same as in loadPluginFile method!! +} + +//_________________________________________________________________________________ +void VP1MainWindow::request_addEmptyTab() { + bool ok; + QString newtabname = QInputDialog::getText( 0, "New Tab Name","New tab name:", + QLineEdit::Normal, m_tabmanager->suggestNewTabName("My Tab"), &ok ); + if (!ok||newtabname.isEmpty()) + return; + m_tabmanager->addNewTab(newtabname); +} + +//_________________________________________________________________________________ +void VP1MainWindow::tabListChanged(QStringList l) { + updateCentralStackWidget(); + if (l.count()) { + m_actionSave_current_tabs->setEnabled(true); + groupBox_cruise->setEnabled(true); + } else { + m_actionSave_current_tabs->setEnabled(false); + groupBox_cruise->setEnabled(false); + } + if (l.count()>1) { + radioButton_cruise_tab->setEnabled(true); + radioButton_cruise_both->setEnabled(true); + } else { + if (radioButton_cruise_tab->isChecked()||radioButton_cruise_both->isChecked()) + radioButton_cruise_event->setChecked(true); + radioButton_cruise_tab->setEnabled(false); + radioButton_cruise_both->setEnabled(false); + } +} + +//_________________________________________________________________________________ +void VP1MainWindow::addChannelIconsToComboBox(QComboBox* cb, const bool& isbasenames) { + int n= cb->count(); + for (int i = 0; i<n; ++i) { + QString icontext = m_channelmanager->getIconLocation(cb->itemText(i), isbasenames); + if (!icontext.isEmpty()) + cb->setItemIcon ( i, QIcon(icontext) ); + } +} + +//_________________________________________________________________________________ +void VP1MainWindow::selectedChannelChanged(IVP1ChannelWidget* cw) +{ + VP1Msg::messageDebug("VP1MainWindow::selectedChannelChanged()"); + + //Controls box: + if (cw) { + groupBox_channelcontrols->setTitle("Controls: "+cw->unique_name()); + groupBox_channelcontrols->setEnabled(true); + QWidget* controller = m_channelmanager->getController(cw); + if (!controller) { + stackedWidget_customcontrols->setCurrentWidget(m_dummyemptycontroller); + } else { + if (stackedWidget_customcontrols->indexOf(controller)==-1) + stackedWidget_customcontrols->addWidget(controller); + stackedWidget_customcontrols->setCurrentWidget(controller); + } + } else { + groupBox_channelcontrols->setTitle("Controls: no channel selected"); + groupBox_channelcontrols->setEnabled(false); + stackedWidget_customcontrols->setCurrentWidget(m_dummyemptycontroller); + } + + // FIXME: enabling menubar again. It's part of a quickfix, described here: https://its.cern.ch/jira/browse/ATLASVPONE-120 + menubar->setEnabled(true); + + // FIXME: enabling menubar again. It's part of a quickfix, described here: https://its.cern.ch/jira/browse/ATLASVPONE-120 + menubar->setEnabled(true); +} + +//_________________________________________________________________________________ +void VP1MainWindow::request_saveasConfig() { + + QString filename = QFileDialog::getSaveFileName(this, "Select configuration file to save", + (m_currentconfigfile.isEmpty()?VP1Settings::defaultFileSelectDirectory():m_currentconfigfile), + "VP1 Configuration files (*.vp1)",0,QFileDialog::DontResolveSymlinks); + if(filename.isEmpty()) + return; + + if (!filename.endsWith(".vp1")) + filename += ".vp1"; + + m_tabmanager->saveConfigurationToFile(filename,false/*Since the filedialog already asks*/); + m_currentconfigfile=filename; +} + +//_________________________________________________________________________________ +void VP1MainWindow::request_saveConfig() +{ + if (m_currentconfigfile.isEmpty()) { + request_saveasConfig(); + return; + } + m_tabmanager->saveConfigurationToFile(m_currentconfigfile,false); +} + +//_________________________________________________________________________________ +void VP1MainWindow::request_loadConfig() +{ + QString filename = QFileDialog::getOpenFileName(this, "Select configuration file to load", + (m_currentconfigfile.isEmpty()?VP1Settings::defaultFileSelectDirectory():m_currentconfigfile), + "VP1 configuration files (*.vp1)",0,QFileDialog::DontResolveSymlinks); + if(filename.isEmpty()) + return; + m_tabmanager->loadConfigurationFromFile(filename,availablePluginFiles()); + m_currentconfigfile=filename; +} + +//_________________________________________________________________________________ +void VP1MainWindow::request_loadPlugin() +{ +#ifdef __APPLE__ + QString sharedlibsuffix = "dylib"; +#else + QString sharedlibsuffix = "so"; +#endif + qDebug() << "VP1MainWindow::request_loadPlugin()"<<m_currentloadpluginpath; + + QString filename = QFileDialog::getOpenFileName(this, "Select plugin file to load", + m_currentloadpluginpath, + "VP1 plugin files (*VP1*."+sharedlibsuffix+")",0,QFileDialog::DontResolveSymlinks); + if(filename.isEmpty()) + return; + m_currentloadpluginpath = QFileInfo(filename).dir().absolutePath(); + loadPluginFile(filename); +} + +//_________________________________________________________________________________ +QMap<QString,QString> VP1MainWindow::availableFiles(const QString& extension, + const QString& pathvar,//LD_LIBRARY_PATH or DATAPATH + const QString& instareasubdir, + const QString& extradirenvvar, + bool currentdir ) const +{ + + qDebug() << "VP1MainWindow::availableFiles()"; + qDebug() << "extension:" << extension << "pathvar:" << pathvar << "instareasubdir:" << instareasubdir << "extradirenvvar:" << extradirenvvar << "currentdir:" << currentdir; + + + //Add directories from extradirenvvar (e.g. $VP1PLUGINPATH) + QStringList vp1pluginpath = extradirenvvar.isEmpty() ? QStringList() : QString(::getenv(extradirenvvar.toStdString().c_str())).split(":",QString::SkipEmptyParts); + if(VP1Msg::debug()){ + qDebug() << "extradirenvvar:" << extradirenvvar; + qDebug() << "vp1pluginpath:" << vp1pluginpath; + } + + #ifdef BUILDVP1LIGHT + //Add dir from Expert Settings + if(VP1QtUtils::expertSettingValue("expert","ExpertSettings/VP1PLUGINPATH")==""){ + vp1pluginpath<<QCoreApplication::applicationDirPath()+"/../lib"; + } else{ + vp1pluginpath<<VP1QtUtils::expertSettingValue("expert","ExpertSettings/VP1PLUGINPATH"); + } + #endif + + //Currentdir: + if (currentdir) { + vp1pluginpath<<QDir::currentPath(); + if (QDir::currentPath()!=VP1Settings::defaultFileSelectDirectory()) + vp1pluginpath<<VP1Settings::defaultFileSelectDirectory(); + } + + //Add directories from pathvar (looking in subdir instareasubdir): + QString varStr = QString(::getenv(pathvar.toStdString().c_str())); + //VP1Msg::messageDebug("Add directories from pathvar... " + pathvar + " - " + varStr); + QString path = QString(::getenv(pathvar.toStdString().c_str())); + if (!path.isEmpty()) { + //!instareasubdir.isEmpty()&& + QStringList tmp = path.split(":",QString::SkipEmptyParts);//This 'tmp' is for SLC3 compilation. + foreach (QString dir,tmp) { + vp1pluginpath << ( instareasubdir.isEmpty() ? dir : dir+QDir::separator()+QDir::separator()+instareasubdir ); + } + } + + //Remove all nonexisting directories: + foreach (QString plugindir, vp1pluginpath) { + QFileInfo fi(plugindir); + if (!fi.exists()||!fi.isDir()) { + vp1pluginpath.removeAll(plugindir); + } + } + + //Find all files with required extension in the directories (in case of duplicates - the ones appearing first are used): + QMap<QString,QString> plugins2fullpath; + foreach (QString plugindir, vp1pluginpath) { + QStringList plugins = QDir(plugindir).entryList((QStringList()<<("*"+extension)),QDir::CaseSensitive | QDir::Files | QDir::Readable,QDir::Name); + foreach (QString plugin, plugins) { + plugin = QFileInfo(plugin).fileName(); + if (!plugins2fullpath.contains(plugin)) { + QString fullpath = plugindir+QDir::separator()+plugin; + plugins2fullpath[plugin]=fullpath; + } + } + } + return plugins2fullpath; +} + +//_________________________________________________________________________________ +QMap<QString,QString> VP1MainWindow::availablePluginFiles() const +{ +VP1Msg::messageDebug("VP1MainWindow::availablePluginFiles()"); + +#ifdef __APPLE__ + QString sharedlibsuffix = "dylib"; +#else + QString sharedlibsuffix = "so"; +#endif + + return availableFiles( "."+sharedlibsuffix, "LD_LIBRARY_PATH", "vp1plugins", "VP1PLUGINPATH" ); + +} + +//_________________________________________________________________________________ +void VP1MainWindow::pluginDialogClosed() { + if (!m_plugindialog) + return; + + int res = m_plugindialog->result(); + QString filename = m_plugindialog->unloadfile(); + disconnect(m_plugindialog,SIGNAL(finished(int)),this,SLOT(pluginDialogClosed())); + m_plugindialog->deleteLater(); + m_plugindialog = 0; + + if (res!=QDialog::Accepted||filename.isEmpty()) + return; + + //How many channels would be affected by such unloading? + QStringList bns = m_channelmanager->channelsInPluginFile(filename); + int naffected(0); + foreach (QString bn, bns) + naffected += m_channelmanager->nActive(bn); + + foreach (QString bn, bns) { + while(m_channelmanager->basename2UniqueNames(bn).count()>0) + m_tabmanager->removeChannel(m_channelmanager->basename2UniqueNames(bn).value(0)); + } + + m_currentunloadpluginfiles << filename; + QTimer::singleShot(0, this, SLOT(unloadPlugin_continue())); + +} + +//_________________________________________________________________________________ +void VP1MainWindow::unloadPlugin_continue() +{ + foreach (QString filename, m_currentunloadpluginfiles) { + bool success = m_channelmanager->unloadPluginFile(filename); + if (!success) + QMessageBox::critical(0, "Error - problems unloading plugin file: "+filename, + "Problems encountered while attempting to unload plugin file: "+filename,QMessageBox::Ok,QMessageBox::Ok); + } + m_currentunloadpluginfiles.clear(); +} + +//_________________________________________________________________________________ +bool VP1MainWindow::okToProceedToNextEvent() const +{ + return ! (m_betweenevents || (m_availEvents&&m_availEvents->freshEvents().isEmpty())); +} + + +//_________________________________________________________________________________ +void VP1MainWindow::nextEvent() { + m_betweenevents=true; + if (m_availEvents) { + QList<VP1EventFile> evts = m_availEvents->freshEvents(); + if (evts.empty()) { + addToMessageBox("ERROR: Going to next event, but one is not available!"); + m_scheduler->setNextRequestedEventFile(""); + } else { + m_scheduler->setNextRequestedEventFile(evts.front().fileName()); + } + } + updateEventControls(); +} + +//_________________________________________________________________________________ +void VP1MainWindow::goToNextEvent() { + #if defined BUILDVP1LIGHT + std::cout << "goToNextEvent: \n" + << "m_scheduler->getEvtNr()+2: " << m_scheduler->getEvtNr()+2 + << "\nm_scheduler->getTotEvtNr(): " << m_scheduler->getTotEvtNr() << std::endl; + if ( m_scheduler->getEvtNr()+2 < m_scheduler->getTotEvtNr() ) { + std::cout << "First case" << std::endl; + m_scheduler->setEvtNr(m_scheduler->getEvtNr()+1); + nextEvent(); + qApp->quit(); + } + else if( m_scheduler->getEvtNr()+2 == m_scheduler->getTotEvtNr() ) { + std::cout << "Second case" << std::endl; + m_scheduler->setEvtNr(m_scheduler->getEvtNr()+1); + nextEvent(); + qApp->quit(); + } + #else + nextEvent(); + qApp->quit(); + #endif +} + +#if defined BUILDVP1LIGHT +//_________________________________________________________________________________ +void VP1MainWindow::goToPreviousEvent() { + if ( m_scheduler->getEvtNr()-1 > 0 ) { + m_scheduler->setEvtNr(m_scheduler->getEvtNr()-1); + nextEvent(); + qApp->quit(); + } + else if( m_scheduler->getEvtNr()-1 == 0 ) { + m_scheduler->setEvtNr(m_scheduler->getEvtNr()-1); + nextEvent(); + qApp->quit(); + } +} +#endif + +//_________________________________________________________________________________ +void VP1MainWindow::closeEvent(QCloseEvent * event) +{ + VP1Msg::messageDebug("VP1MainWindow::closeEvent()"); + + bool checkEnableAskOnClose; + #if defined BUILDVP1LIGHT + checkEnableAskOnClose = VP1QtUtils::expertSettingIsSet("general","ExpertSettings/VP1_ENABLE_ASK_ON_CLOSE"); + #else + checkEnableAskOnClose = VP1QtUtils::environmentVariableIsOn("VP1_ENABLE_ASK_ON_CLOSE"); + #endif + + if (checkEnableAskOnClose) { + int ret = QMessageBox::warning(this, + "Close VP1?", + "You are about to close VP1 and end the job.\nProceed?", + QMessageBox::Ok| QMessageBox::Cancel, + QMessageBox::Cancel ); + if (ret!=QMessageBox::Ok) { + event->ignore(); + return; + } + m_userRequestedExit = true; + } + + hide(); + + VP1Msg::messageDebug("calling tabmanager->setSelectedDockWidget(0)..."); + m_tabmanager->setSelectedDockWidget(0); + VP1Msg::messageDebug("tabmanager->setSelectedDockWidget(0) called."); + + m_mustquit=true; // this will inform VP1Alg that we want to quit VP1 (then we'll quit the Athena algorithm) + VP1Msg::messageDebug("calling qApp->quit()..."); + qApp->quit(); +} + +//_________________________________________________________________________________ +void VP1MainWindow::setRunEvtNumber(const int& r, const unsigned long long& e, const unsigned& triggerType, const unsigned& time, const bool& printmessage ) { + + m_scheduler->setNextRequestedEventFile(""); + const bool sameasold(m_runnumber==r&&m_eventnumber==e); + + m_runnumber=r; + m_eventnumber=e; + m_timestamp=time; + + m_betweenevents = false; + if (m_availEvents) + m_availEvents->setCurrentEvent(r,e); + + foreach(IVP1ChannelWidget* channel,m_tabmanager->allChannels()) { + channel->setRunEvtNumber(r,e); + channel->setEvtTimestamp(time); + } + + if(printmessage) { + qulonglong evNumber = m_eventnumber; + QString evtstr = "run# "+QString::number(m_runnumber)+", event# "+QString::number(evNumber)+(sameasold?" (reused)":""); + QString trighex = triggerType > 0 ? "0x"+QString::number(triggerType, 16).toUpper().rightJustified(sizeof(triggerType),'0') : ""; + QString expandedevtstr = evtstr + + QString(trighex.isEmpty()?QString(""):", triggerType: "+trighex) + + QString(time>0 ? ", time: "+QDateTime::fromTime_t(time).toString(Qt::ISODate).replace('T',' ') : "") + + QString(m_currentStream.isEmpty()?"":", "+m_currentStream); + + #ifdef BUILDVP1LIGHT + setWindowTitle("VP1Light ["+expandedevtstr+"]"); + #else + setWindowTitle("VTI 12 (Virtual TI 12) ["+expandedevtstr+"]"); + #endif // BUILDVP1LIGHT + + groupBox_event->setTitle("Event [loaded]"); + label_run_event->setText("["+evtstr+"]"); + + addToMessageBox("New event: "+expandedevtstr,"color:#ff0000"); + + } + updateEventControls(); +} + +//_________________________________________________________________________________ +void VP1MainWindow::addToMessageBox( const QString& m, const QString& extrastyleopts, + const QString& title, const QString& titleextrastyleopts ) +{ + + if (title.isEmpty()) + std::cout<<VP1Msg::prefix_msg()<<": "<<m.toStdString()<<std::endl; + else + std::cout<<VP1Msg::prefix_msg()<<": "<<title.toStdString() << ": " <<m.toStdString()<<std::endl; + + + QString titlepart = ( title.isEmpty() ? "" : ( titleextrastyleopts.isEmpty() ? title + : "<span style=\"font-style:italic;"+titleextrastyleopts+";\">["+title+"]</span> ")); + + textBrowser_channelmessages->append(titlepart + + ( extrastyleopts.isEmpty() ? m + : "<span style=\"font-style:italic;"+extrastyleopts+";\">"+m+"</span>")); + textBrowser_channelmessages->verticalScrollBar()->setSliderPosition(textBrowser_channelmessages->verticalScrollBar()->maximum()); +} + +//_________________________________________________________________________________ +void VP1MainWindow::systemAddToMessageBox( const QString& m ) +{ + IVP1System*sys = static_cast<IVP1System*>(sender()); + if (!sys) { + addToMessageBox("VP1MainWindow::systemAddToMessageBox Error: Only prints system messages!"); + return; + } + if (!sys->channel()) { + addToMessageBox("VP1MainWindow::systemAddToMessageBox Error: System does not know its channel!"); + return; + } + addToMessageBox( m, "color:#000000",sys->channel()->unique_name()+"/"+sys->name(),"color:#0000ff" ); +} + +//_________________________________________________________________________________ +void VP1MainWindow::channelAddToMessageBox( const QString& m ) +{ + IVP1ChannelWidget*cw = static_cast<IVP1ChannelWidget*>(sender()); + if (!cw) { + addToMessageBox("VP1MainWindow::channelAddToMessageBox Error: Only prints channelwidget messages!"); + return; + } + addToMessageBox(m,"color:#000000", cw->unique_name(),"color:#0000ff"); +} + +//_________________________________________________________________________________ +void VP1MainWindow::helperAddToMessageBox( const QString& m ) +{ + addToMessageBox(m); +} + +//_________________________________________________________________________________ +void VP1MainWindow::request_channelInformation() { + if(!m_tabmanager->selectedChannelWidget()) + return; + + QString out = "Information about channel: "+m_tabmanager->selectedChannelWidget()->name() + "\n\n"; + out += "Contact: "+m_tabmanager->selectedChannelWidget()->contact_info()+"\n"; + out += "Information: "+m_tabmanager->selectedChannelWidget()->information()+"\n"; + out += "Systems:\n\n"; + std::set<IVP1System *>::iterator itsys, itsysE = m_tabmanager->selectedChannelWidget()->systems().end(); + for (itsys = m_tabmanager->selectedChannelWidget()->systems().begin();itsys!=itsysE;++itsys) { + out += " ==> System "+(*itsys)->name()+"\n"; + out += " Contact: "+(*itsys)->contact_info()+"\n"; + out += " Information: "+(*itsys)->information()+"\n"; + out += "\n"; + } + + QMessageBox::information(0, "Information about channel: "+m_tabmanager->selectedChannelWidget()->name(),Qt::convertFromPlainText(out),QMessageBox::Ok,QMessageBox::Ok); +} + +//_________________________________________________________________________________ +void VP1MainWindow::makeAllChannelsEventDisplay() +{ + VP1Msg::messageVerbose("VP1MainWindow::makeAllChannelsEventDisplay()"); + + QList<QPixmap> list; + QStringList listNames; + QList<unsigned long long> listRunEventNumberTimestamp; + + getAllChannelsIntoSnapshots(list, listNames); + + listRunEventNumberTimestamp << m_runnumber; + listRunEventNumberTimestamp << m_eventnumber; + listRunEventNumberTimestamp << m_timestamp; + + // create a new editor window + m_edEditor = new VP1EventDisplayEditor(this, listRunEventNumberTimestamp); + + m_edEditor->addPixmapList(list, listNames); + + // pass the lists of all tabs and their names to the editor + m_edEditor->setTabsList( listNames); + + m_edEditor->show(); + +} + + + + +//_________________________________________________________________________________ +void VP1MainWindow::getAllChannelsIntoSnapshots(QList<QPixmap>& list, QStringList& listNames) +{ + VP1Msg::messageDebug("VP1MainWindow::getAllChannelsIntoSnapshots()"); + +// int nTabs = m_tabmanager->nTabs(); + QList<IVP1ChannelWidget*> allTabs = m_tabmanager->allChannels(); + + if (allTabs.isEmpty()) { + VP1Msg::message("WARNING - No tabs to save."); + return; + } + + int nT = 0; + + // loop over all tabs/channels + foreach(IVP1ChannelWidget* widg, allTabs) { + + // increase tab number + ++nT; + + // get channel name (e.g. Geometry, 3DCocktail) +// QString channelname = widg->unique_name().toLower(); + QString channelname = m_tabmanager->channelToTab(widg); + channelname.replace(' ','_'); + VP1Msg::messageDebug("tab: " + channelname); + +// // get channel info, only for debug +// QString info = widg->information(); +// VP1Msg::messageDebug("channel info: " + info); + + + QPixmap snap = getSingleChannelCustomSnapshot(widg); + + list << snap; + listNames << channelname; + + } + + VP1Msg::messageVerbose(QString::number(nT)+" tabs/channels saved in the QList."); + +} + +//_________________________________________________________________________________ +QPixmap VP1MainWindow::getSingleChannelCustomSnapshot(IVP1ChannelWidget* tab, int width) +{ + VP1Msg::messageDebug("VP1MainWindow::getSingleChannelCustomSnapshot()"); + + // std::cout << "tab: " << tab << std::endl; + + // save the anti-aliasing status, set by the user + bool antialias_original = tab->isAntiAliasing(); + + // for the final event display images we want the anti-aliasing turned ON, + tab->setAntiAliasing(true); + + // get the snapshot + QPixmap snap; + if (width) + snap = tab->getSnapshot(true, width); // 'true' means 'transparent background' + else + snap = tab->getSnapshot(true); // 'true' means 'transparent background' + + if (snap.isNull()) { + VP1Msg::message("ERROR! - No snapshot produced!"); + return QPixmap(); + } + + // go back to the original anti-aliasing status, set by the user for the tab + tab->setAntiAliasing(antialias_original); + + return snap; +} +//_________________________________________________________________________________ +QPixmap VP1MainWindow::getSingleChannelCustomSnapshot(QString tabName, int width) +{ + QList<IVP1ChannelWidget*> allTabs = m_tabmanager->allChannels(); + + if (allTabs.isEmpty()) { + VP1Msg::message("WARNING - No tabs to get snapshots from."); + } + + // loop over all tabs/channels + foreach(IVP1ChannelWidget* widg, allTabs) { + + // get channel name (e.g. Geometry, 3DCocktail) + QString channelname = m_tabmanager->channelToTab(widg); + channelname.replace(' ','_'); + + if (channelname == tabName) { + VP1Msg::messageDebug("found tab: " + channelname); + + if (width) + return getSingleChannelCustomSnapshot(widg, width); + else + return getSingleChannelCustomSnapshot(widg); + + } + } + return QPixmap(); +} + +//_________________________________________________________________________________ +void VP1MainWindow::saveAllCurrentChannels() +{ + VP1Msg::messageDebug("VP1MainWindow::saveAllCurrentChannels()"); + + int nTabs = m_tabmanager->nTabs(); + + VP1Msg::messageDebug("# of tabs: " + QString::number(nTabs)); + + QList<IVP1ChannelWidget*> allTabs = m_tabmanager->allChannels(); + + if (allTabs.isEmpty()) { + VP1Msg::message("WARNING - No tabs to save."); + return; + } + + +// QString guess; +// QString chnlname = m_tabmanager->selectedChannelWidget()->name().toLower(); +// chnlname.replace(' ','_'); + + QString base=m_currentsaveimagepath+QDir::separator()+"vp1" + + "_run"+QString::number(m_runnumber)+"_evt"+QString::number(m_eventnumber) + + QString(m_timestamp>0 ? "_"+QDateTime::fromTime_t(m_timestamp).toString(Qt::ISODate).replace(':','-') : ""); + + + // check for existing files + int i(2); + while (QFile::exists(base+".png")) { + base = base+"_"+QString::number(i++); + } + + // let the user choose the base filename + QString filename = QFileDialog::getSaveFileName(0, "Select target image file", base, + "Image (*.png *.bmp)", + 0,QFileDialog::DontResolveSymlinks); + if(filename.isEmpty()) { + VP1Msg::message("WARNING - No filename selected."); + return; + } + + m_currentsaveimagepath = QFileInfo(filename).dir().absolutePath (); + + + QStringList tab_save_files; + + int nT = 0; + foreach(IVP1ChannelWidget* widg, allTabs) { + + // increase tab number + ++nT; + + // get channel name (e.g. Geometry, 3DCocktail) + QString channelname = widg->name().toLower(); + channelname.replace(' ','_'); + VP1Msg::messageDebug("tab: " + channelname); + +// // get channel info, only for debug +// QString info = widg->information(); +// VP1Msg::messageDebug("channel info: " + info); + + QPixmap snap = widg->getSnapshot(); + if (snap.isNull()) { + VP1Msg::message("ERROR! - No snapshot produced!"); + return; + } + + QString tabfilename = filename + "_" + QString::number(nT) + "_" + channelname + ".png"; + + if (!(tabfilename.endsWith(".png",Qt::CaseInsensitive)||tabfilename.endsWith(".bmp",Qt::CaseInsensitive))) + tabfilename += ".png"; + + + snap.save(tabfilename); + + tab_save_files << tabfilename; + } + + VP1Msg::message("Tabs saved as: " + tab_save_files.join(" - ")); + + + QMessageBox::information(this, tr("Snapshots saved."), + "All tabs have been saved as snapshots in the following files:\n\n"+tab_save_files.join("\n"), + QMessageBox::Ok, + QMessageBox::Ok); + + +// // TODO: test to create a multilayered PSD or TIFF file +// // but doesn't work with the ImageMagick version shipped with SLC5... +// // So I give it up now... +// QProcess *proc = new QProcess(); +// QString program = "convert"; +// QStringList arguments; +// arguments = tab_save_files; +// arguments << " " + m_currentsaveimagepath + QDir::separator() + "out.psd"; +// VP1Msg::messageDebug("running: " + program + " " + arguments.join(" ")); +// +// // start the process +// proc->start(program, arguments ); +// +// if (!proc->waitForStarted()) +// return; +// +// if (!proc->waitForFinished()) +// return; + +} + +//_________________________________________________________________________________ +/* + * save a snaphot of the currently selected tab. + * + * nsnap is an optional parameter: it's an extra label being added + * to the output filename. + */ +QString VP1MainWindow::request_saveChannelSnapshot(QString xLabel) +{ + + VP1Msg::messageDebug("VP1MainWindow::request_saveChannelSnapshot()"); + + if(!m_tabmanager->selectedChannelWidget()) { + return QString(); + } + + QString guess; + QString chnlname = m_tabmanager->selectedChannelWidget()->name().toLower(); + chnlname.replace(' ','_'); + + QString base=m_currentsaveimagepath+QDir::separator()+"vp1_"+chnlname + +"_run"+QString::number(m_runnumber)+"_evt"+QString::number(m_eventnumber) + + QString(m_timestamp>0 ? "_"+QDateTime::fromTime_t(m_timestamp).toString(Qt::ISODate).replace(':','-') : ""); + + + // check for existing files + guess=base; + int i(2); + while (QFile::exists(guess+".png")) { + guess=base+"_"+QString::number(i++); + } + guess+=".png"; + + + // adding the extra label xLabel, if provided + if (!xLabel.isEmpty()) { + guess += "_" + xLabel; + } + + + QString filename = QFileDialog::getSaveFileName(0, "Select target image file", guess, + "Image (*.png *.bmp)", + 0,QFileDialog::DontResolveSymlinks); + if(filename.isEmpty()) + return QString(); + + m_currentsaveimagepath = QFileInfo(filename).dir().absolutePath (); + + if (!(filename.endsWith(".png",Qt::CaseInsensitive)||filename.endsWith(".bmp",Qt::CaseInsensitive))) + filename += ".png"; + + VP1Msg::messageVerbose("calling snapshot"); + QPixmap pm = m_tabmanager->selectedChannelWidget()->getSnapshot(); + + if (pm.isNull()) + return QString(); + + pm.save(filename); + return filename; +} + +//_________________________________________________________________________________ +void VP1MainWindow::request_printChannel() { + if(!m_tabmanager->selectedChannelWidget()) + return; + + //The following will paint the widget onto a paper and bring up the print dialog: + QPrinter printer; + QPrintDialog dialog(&printer, this); + if (dialog.exec() == QDialog::Accepted) { + QPixmap pm = m_tabmanager->selectedChannelWidget()->getSnapshot(); + if (pm.isNull()) + return; + QPainter painter; + painter.begin(&printer); + painter.drawPixmap(0,0,pm); + painter.end(); + } +} + + +//_________________________________________________________________________________ +void VP1MainWindow::loadConfigurationFromFile(QString file) { + m_tabmanager->loadConfigurationFromFile(file,availablePluginFiles()); +} + +//_________________________________________________________________________________ +void VP1MainWindow::replaceConfigurationFile(QString file) +{ + VP1Msg::messageDebug("VP1MainWindow::replaceConfigurationFile() : " + file); + m_tabmanager->removeAllTabs(); + m_tabmanager->loadConfigurationFromFile(file,availablePluginFiles()); +} + +//_________________________________________________________________________________ +void VP1MainWindow::listenOnTcp() +{ + QString err; + if (!m_tcpserver.listen(err)) { + qDebug("%s", err.toStdString().c_str()); + } +} + + +//_________________________________________________________________________________ +void VP1MainWindow::finishedIncomingDialog() +{ + m_currentincomingdialog=0; + if (!m_requestqueue.empty()) + QTimer::singleShot(0, this, SLOT(processEnqueuedRequests())); +} + + +//_________________________________________________________________________________ +void VP1MainWindow::processEnqueuedRequests() +{ + if (!m_requestqueue.empty()) + receivedExternalRequest(m_requestqueue.dequeue()); +} + +//_________________________________________________________________________________ +void VP1MainWindow::receivedExternalRequest(VP1ExternalRequest request) +{ + if (m_blockallmessages) + return; + if (m_messages_blockedsenders.contains(request.sender())) + return; + if (m_messages_blockedexactmessages.contains(request)) + return; + if (m_currentincomingdialog) { + //Fixme: store TIME of incoming request (to show the user). + if (m_requestqueue.count()<999) { + m_requestqueue.enqueue(request); + m_currentincomingdialog->updatependinginfo(); + } + return; + } + VP1IncomingMessageDialog * md = new VP1IncomingMessageDialog(request,&m_requestqueue,&m_blockallmessages, + &m_messages_blockedsenders,&m_messages_blockedexactmessages, + m_tabmanager,m_channelmanager,this); + m_currentincomingdialog=md; + connect(md,SIGNAL(finished(int)),this,SLOT(finishedIncomingDialog())); + m_tabmanager->dropOutOfFullScreen(); + md->show(); +} + +//_________________________________________________________________________________ +void VP1MainWindow::request_cruisemodechange() +{ + if (pushButton_cruise->isChecked()) { + if (radioButton_cruise_event->isChecked()) { + m_scheduler->setCruiseMode(VP1ExecutionScheduler::EVENT); + groupBox_cruise->setTitle("Cruise Mode [event]"); + } else if (radioButton_cruise_tab->isChecked()) { + m_scheduler->setCruiseMode(VP1ExecutionScheduler::TAB); + groupBox_cruise->setTitle("Cruise Mode [tab]"); + } else if (radioButton_cruise_both->isChecked()) { + m_scheduler->setCruiseMode(VP1ExecutionScheduler::BOTH); + groupBox_cruise->setTitle("Cruise Mode [event && tab]"); + } else { assert(0); } + } else { + m_scheduler->setCruiseMode(VP1ExecutionScheduler::NONE); + groupBox_cruise->setTitle("Cruise Mode [off]"); + } +} + +//_________________________________________________________________________________ +void VP1MainWindow::showMenu_loadPlugin() +{ + m_menu_loadPlugin->clear(); + + QMap<QString,QString> plugins2fullpath = availablePluginFiles(); + + if (plugins2fullpath.empty()) { + m_menu_loadPlugin->addAction("No plugins found")->setEnabled(false); + return; + } + + QStringList pluglist(plugins2fullpath.keys()); + pluglist.sort(); + + QStringList currentpluginfiles = m_channelmanager->currentPluginFiles(); + foreach(QString plug,pluglist) { + QAction * act = m_menu_loadPlugin->addAction(plug); + assert(plugins2fullpath.contains(plug)); + QString fullpath = plugins2fullpath[plug]; + if (currentpluginfiles.contains(fullpath)) { + act->setEnabled(false); + } else { + act->setData(fullpath); + act->setStatusTip(fullpath); + connect(act,SIGNAL(triggered(bool)),this,SLOT(showMenu_loadPluginItemSelected())); + } + } + + m_menu_loadPlugin->addSeparator(); + QAction * act_browse = m_menu_loadPlugin->addAction("&Browse..."); + act_browse->setStatusTip("Browse filesystem for VP1 plugin files"); + connect(act_browse,SIGNAL(triggered(bool)),this,SLOT(request_loadPlugin())); + +} + +//_________________________________________________________________________________ +void VP1MainWindow::showMenu_loadPluginItemSelected() +{ + QAction * act = static_cast<QAction*>(sender()); + assert(act); + if (!act) + return; + loadPluginFile(act->data().toString()); +} + + +//_________________________________________________________________________________ +void VP1MainWindow::showMenu_loadConfFile() +{ + m_menu_loadConfFile->clear(); + + QMap<QString,QString> conffile2fullpath = availableFiles( ".vp1", "DATAPATH", "", "VP1CONFIGFILEPATH", true ); + + #ifndef BUILDVP1LIGHT + if (conffile2fullpath.empty()) { + m_menu_loadConfFile->addAction("No .vp1 config files found")->setEnabled(false); + return; + } + + QStringList filelist(conffile2fullpath.keys()); + filelist.sort(); + + foreach(QString file,filelist) { + QAction * act = m_menu_loadConfFile->addAction(file); + assert(conffile2fullpath.contains(file)); + QString fullpath = conffile2fullpath[file]; + act->setData(fullpath); + act->setStatusTip(fullpath); + connect(act,SIGNAL(triggered(bool)),this,SLOT(showMenu_loadConfFileItemSelected())); + } + #endif + + m_menu_loadConfFile->addSeparator(); + QAction * act_browse = m_menu_loadConfFile->addAction("&Browse..."); + act_browse->setStatusTip("Browse filesystem for .vp1 config file"); + connect(act_browse,SIGNAL(triggered(bool)),this,SLOT(request_loadConfig())); + +} + + +//_________________________________________________________________________________ +void VP1MainWindow::showMenu_loadConfFileItemSelected() +{ + QAction * act = static_cast<QAction*>(sender()); + assert(act); + if (!act) + return; + loadConfigurationFromFile(act->data().toString()); +} + +//_________________________________________________________________________________ +void VP1MainWindow::changeStyleActionTriggered() +{ + QAction * act = static_cast<QAction*>(sender()); + assert(act); + if (!act) + return; + assert(QStyleFactory::keys().contains(act->text())); + if (!QStyleFactory::keys().contains(act->text())) + return; + QApplication::setStyle(QStyleFactory::create(act->text())); + QSettings s(m_settingsfile,QSettings::IniFormat); + s.setValue("style/defaultstyle",act->text()); + +} + +//_________________________________________________________________________________ +void VP1MainWindow::changeFontSizeActionTriggered() +{ + QAction * act = static_cast<QAction*>(sender()); + assert(act); + if (!act) + return; + bool ok; + int goal = act->data().toInt(&ok); + assert(ok); + if (!ok) + return; + changeFontSize(goal); +} + +//_________________________________________________________________________________ +void VP1MainWindow::changeFontSize(int goal) +{ + QFont newfont = m_defaultfont; + QSettings s(m_settingsfile,QSettings::IniFormat); + if (m_defaultfont_pointsize<0.0) { + //pixels + assert(m_defaultfont_pixelsize+goal>0); + if (m_defaultfont_pixelsize+goal<=0) + return; + if (m_defaultfont_pixelsize+goal>200) + return; + newfont.setPixelSize(m_defaultfont_pixelsize+goal); + s.setValue("font/pixelsize_diff",goal); + } else { + //pointsize + double fact = (goal+100.0)/100.0; + if (fact<0.01||fact>50) + return; + double newpointsize=m_defaultfont_pointsize*fact; + if (newpointsize<0) + return; + newfont.setPointSizeF(newpointsize); + s.setValue("font/pointsize_relativepercent",goal); + } + QApplication::setFont(newfont); +} + + +//_________________________________________________________________________________ +void VP1MainWindow::updateCentralStackWidget() +{ + QWidget * targetpage = tabWidget_central->count() ? page_tabwidget : page_instructions; + if (stackedWidget_central->currentWidget() != targetpage) + stackedWidget_central->setCurrentWidget(targetpage); +} + +//_________________________________________________________________________________ +void VP1MainWindow::quickSetupTriggered() +{ + VP1Msg::messageVerbose("VP1MainWindow::quickSetupTriggered()"); + + QSettings settings("FASER", "VP1Light"); + + QString plugfile, channelname, tabname; + + if (sender()==pushButton_quicksetup_geometrystudies||sender()==action_quicklaunch_Geometry_studies) { + + //Open geometry database selection dialog for VP1Light +#ifdef BUILDVP1LIGHT + if(settings.value("db/dbByEnv").toString().isEmpty()){ + VP1GeoDBSelection dbSelection; + dbSelection.exec(); + if(!dbSelection.result()) + return; + } +#endif // BUILDVP1LIGHT + + plugfile="libVTI12GeometryPlugin.so"; + channelname="Geometry"; + tabname = "Geometry"; + } /*else if (sender()==pushButton_quicksetup_trackingstudies||sender()==action_quicklaunch_Tracking_studies) { + plugfile="libVP1TrackPlugin.so"; + channelname="Tracking"; + tabname = "Tracking"; + } else if (sender()==pushButton_quicksetup_calostudies||sender()==action_quicklaunch_Calo_studies) { + plugfile="libVP1CaloPlugin.so"; + channelname="Calo Cells"; + tabname = "Calorimeter"; + } else if (sender()==action_quicklaunch_Storegate_browser) { + plugfile="libVP1BanksPlugin.so"; + channelname="Banks"; + tabname = "StoreGate"; + }*/ + else if (sender()==pushButton_quicksetup_faser||sender()==action_quicklaunch_faser) { +#ifndef BUILDVP1LIGHT + plugfile="libVTI12FaserPlugin.so"; + channelname="Faser"; + tabname = "Faser"; +#else + //Open Geometry DB and AOD file selection dialog for VP1Light + if(settings.value("aod/aodByEnv").toString().isEmpty()){ + VP1AODSelection aodSelection; + aodSelection.exec(); + if(!aodSelection.result()) + return; + } + if(settings.value("db/dbByEnv").toString().isEmpty()){ + VP1GeoDBSelection dbSelection; + dbSelection.exec(); + if(!dbSelection.result()) + return; + } + m_scheduler->loadEvent(); + + pushButton_eventselect->setEnabled(true); + plugfile="libVP1LightPlugin.so"; + channelname="VP1Light"; + tabname = "Geometry/AOD"; +#endif // BUILDVP1LIGHT + } /*else if (sender()==action_quicklaunch_trackcalo_commis) { + plugfile="libVP13DCocktailPlugin.so"; + channelname="TrackCalo"; + tabname = "Track/Calo"; + } */else if (sender()==pushButton_quicksetup_analysisstudies||sender()==action_quicklaunch_analysisstudies) { + + //Open AOD file selection dialog for VP1Light +#ifdef BUILDVP1LIGHT + if(settings.value("aod/aodByEnv").toString().isEmpty()){ + VP1AODSelection aodSelection; + aodSelection.exec(); + if(!aodSelection.result()) + return; + } + m_scheduler->loadEvent(); + pushButton_eventselect->setEnabled(true); +#endif // BUILDVP1LIGHT + + plugfile="libVP1AODPlugin.so"; + channelname="AOD"; + tabname = "Analysis"; + } else { + addToMessageBox("quickSetupTriggered() Error: Unknown sender"); + return; + } + +#ifdef __APPLE__ + if (plugfile.endsWith(".so")) + plugfile = plugfile.left(plugfile.count()-3)+".dylib"; +#endif + + + //Check that the plugin is available: + QMap<QString,QString> plugins2fullpath = availablePluginFiles(); + if(VP1Msg::debug()){ + qDebug() << "plugins2fullpath: " << plugins2fullpath; + } + + if (!plugins2fullpath.contains(plugfile)) { + QMessageBox::critical(0, "Error - could not locate plugin file: "+plugfile, + "could not locate plugin file: " + +plugfile,QMessageBox::Ok,QMessageBox::Ok); + return; + } + QString plugfile_fullpath = plugins2fullpath[plugfile]; + + + //Load plugin + if (!m_channelmanager->currentPluginFiles().contains(plugfile_fullpath)) { + QString err = m_channelmanager->loadPluginFile(plugfile_fullpath); + if (!err.isEmpty()||!m_channelmanager->currentPluginFiles().contains(plugfile_fullpath)) { + QMessageBox::critical(0, "Error - could not load plugin file: "+plugfile_fullpath,//Fixme: Error message here is hardcoded to be the same as in loadPluginFile method!! + "Could not load plugin file: " + +plugfile_fullpath+"\n\nReason: "+err,QMessageBox::Ok,QMessageBox::Ok); + return; + } + } + + + //Check that plugin contains necessary channel: + if (!m_channelmanager->channelsInPluginFile(plugfile_fullpath).contains(channelname)) { + QMessageBox::critical(0, "Error - did not find necessary channel: "+channelname, + "Could not find channel: "+channelname+" in loaded plugin "+plugfile_fullpath, + QMessageBox::Ok,QMessageBox::Ok); + return; + } + + bool save = updatesEnabled(); + setUpdatesEnabled(false); + + + //Add tab: + QString newtabname = m_tabmanager->suggestNewTabName(tabname); + m_tabmanager->addNewTab(newtabname); + if (!m_tabmanager->hasTab(newtabname)) { + QMessageBox::critical(0, "Error - could not create tab: "+newtabname, + "Could not create tab: "+newtabname, + QMessageBox::Ok,QMessageBox::Ok); + setUpdatesEnabled(save); + return; + } + + + //Finally, add channel: + + if (!m_tabmanager->addChannelToTab( channelname, newtabname )) { + QMessageBox::critical(0, "Error - problems launching channel: "+channelname, + "Problems launching channel: "+channelname, + QMessageBox::Ok,QMessageBox::Ok); + setUpdatesEnabled(save); + return; + } + + + m_tabmanager->showTab(newtabname); + + + setUpdatesEnabled(save); +} + +//_________________________________________________________________________________ +void VP1MainWindow::updateEventControls() +{ + pushButton_nextevent->setEnabled(okToProceedToNextEvent()); + #if defined BUILDVP1LIGHT + pushButton_previousevent->setEnabled(okToProceedToNextEvent()); + #endif +} + +//_________________________________________________________________________________ +void VP1MainWindow::updateInputDirectoriesStatus() +{ + if(!m_mutex->tryLock()) return; + + QFont f; + QFont fb; + fb.setBold(true); + + foreach (QAction * act,m_inputdiractions) { + VP1DirStatusData& dirstatus = m_inputdirstatuses[act]; + QString inputdir(act->data().toString()); + QString dirname = QDir(inputdir).dirName(); + act->setEnabled(dirstatus.enabled); + act->setFont(dirstatus.bold?fb:f); + act->setText(dirname+" ["+dirstatus.dirStatus+"]"); + } + + m_mutex->unlock(); +} + +//_________________________________________________________________________________ +void VP1MainWindow::inputDirectoryActionTriggered() +{ + QAction * act = dynamic_cast<QAction*>(sender()); + if (!act) + return; + VP1AvailEvtsLocalDir* availLocal = dynamic_cast<VP1AvailEvtsLocalDir*>(m_availEvents); + if (!availLocal) + return; + QString inputdir(act->data().toString()); + QFileInfo fi(inputdir); + if (fi.exists()&&fi.isDir()) { + availLocal->setSourceDir(inputdir); + // std::cout<<VP1Msg::prefix_msg()<<": " + // <<"VP1Message: inputdirectory changed to " + // <<availLocal->currentSourceDir().toStdString()<<std::endl; + m_currentStream = QDir(availLocal->currentSourceDir()).dirName(); + } + + +} + +//________________________________________________________________________________ +QStringList VP1MainWindow::userRequestedFiles() +{ + QStringList returnval(m_userRequestedFiles); + m_userRequestedFiles.clear(); + return returnval; +} + +//_________________________________________________________________________________ +void VP1MainWindow::addEventFile() +{ + QString newEventFile = QFileDialog::getOpenFileName(NULL + ,tr("Open Event File") + ,VP1Settings::defaultFileSelectDirectory() + ,tr("All files (*.*)")); + if(newEventFile.isEmpty()) return; + if(VP1FileUtilities::fileExistsAndReadable(newEventFile.toStdString())) { + m_userRequestedFiles.append(newEventFile); + addToMessageBox(newEventFile + " will be appended to the list of input files"); + } + else + QMessageBox::critical(0, newEventFile + " either does not exist or is not readable", + newEventFile + " either does not exist or is not readable", + QMessageBox::Ok,QMessageBox::Ok); +} + +//_________________________________________________________________________________ +#ifdef BUILDVP1LIGHT +void VP1MainWindow::request_expertSettings(){ + VP1ExpertSettings es; + es.exec(); +} + +void VP1MainWindow::chooseEvent(){ + //Open event selection dialog for VP1Light + VP1SelectEvent selectEvent(m_scheduler->getTotEvtNr(), m_scheduler->getEvtNr()); + selectEvent.exec(); + int newEvtNr = selectEvent.result()-1; + + if( (newEvtNr >= 0) && (newEvtNr <= m_scheduler->getTotEvtNr()-1) ){ + m_scheduler->setEvtNr(newEvtNr); + nextEvent(); + qApp->quit(); + } +} +#endif // BUILDVP1LIGHT diff --git a/graphics/VTI12/VTI12Gui/src/VP1PluginDialog.cxx b/graphics/VTI12/VTI12Gui/src/VP1PluginDialog.cxx new file mode 100644 index 000000000..e5078e6d3 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1PluginDialog.cxx @@ -0,0 +1,164 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////// +// // +// Implementation of class VP1PluginDialog // +// // +// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Initial version: April 2007 // +// // +///////////////////////////////////////////////////////////// + +#include "VTI12Gui/VP1PluginDialog.h" +#include "ui_vp1plugindialog.h" +#include "VTI12Gui/VP1ChannelManager.h" +#include "VTI12Gui/VP1ExecutionScheduler.h" +#include "VP1Base/IVP1ChannelWidget.h" +#include <QFileInfo> +#include <cassert> + +//____________________________________________________________________ +class VP1PluginDialog::Imp { +public: + VP1PluginDialog*pd; + VP1ChannelManager* channelmanager; + VP1ExecutionScheduler* scheduler; + void setInfo(); + QLabel * label_selectplugin; + QComboBox * comboBox_plugins; + QLabel * label_fullpathtitle; + QLabel * label_fullpath; + QLabel * label_channels; + QPushButton * pushButton_unload; + QTextBrowser * textBrowser_channels; + QMap<int,QString> index_2_fullpath; + QString unloadfile; +}; + +//____________________________________________________________________ +VP1PluginDialog::VP1PluginDialog(QWidget*parent, VP1ChannelManager*cm,VP1ExecutionScheduler*scheduler) + : QDialog(parent), m_d(new Imp) +{ + m_d->pd = this; + m_d->channelmanager=cm; + m_d->scheduler=scheduler; + Ui::VP1PluginDialog ui; + ui.setupUi(this); + ui.textBrowser_channels->viewport()->setBackgroundRole(QPalette::NoRole); + m_d->label_selectplugin = ui.label_selectplugin; + m_d->comboBox_plugins = ui.comboBox_plugins; + m_d->label_fullpathtitle = ui.label_fullpathtitle; + m_d->label_fullpath = ui.label_fullpath; + m_d->label_channels = ui.label_channels; + m_d->pushButton_unload = ui.pushButton_unload; + m_d->textBrowser_channels = ui.textBrowser_channels; + m_d->setInfo(); + setModal(true); + connect(m_d->comboBox_plugins,SIGNAL(currentIndexChanged(int)),this,SLOT(pluginSelected(int))); + connect(m_d->pushButton_unload,SIGNAL(clicked()),this,SLOT(unloadclicked())); + connect(scheduler,SIGNAL(refreshingStatusChanged(bool)),this,SLOT(updateRefreshInfo())); + +} + +//____________________________________________________________________ +void VP1PluginDialog::unloadclicked() +{ + int i = m_d->comboBox_plugins->currentIndex(); + if (i<0) + return; + assert(m_d->index_2_fullpath.contains(i)); + m_d->unloadfile=m_d->index_2_fullpath.value(i); + accept(); +} + +//____________________________________________________________________ +QString VP1PluginDialog::unloadfile() +{ + return m_d->unloadfile; +} + +//____________________________________________________________________ +VP1PluginDialog::~VP1PluginDialog() +{ + delete m_d; m_d=0; +} + +//____________________________________________________________________ +void VP1PluginDialog::Imp::setInfo() +{ + QStringList files = channelmanager->currentPluginFiles(); + comboBox_plugins->clear(); + index_2_fullpath.clear(); + if (files.empty()) { + label_selectplugin->setEnabled(false); + comboBox_plugins->setEnabled(false); + label_fullpathtitle->setEnabled(false); + label_fullpath->setEnabled(false); + label_channels->setEnabled(false); + pushButton_unload->setEnabled(false); + label_fullpath->setText("n/a"); + comboBox_plugins->addItem("No plugins loaded"); + textBrowser_channels->setHtml(""); + textBrowser_channels->setEnabled(false); + } else { + label_selectplugin->setEnabled(true); + comboBox_plugins->setEnabled(true); + label_fullpathtitle->setEnabled(true); + label_fullpath->setEnabled(true); + label_channels->setEnabled(true); + pushButton_unload->setEnabled(true); + textBrowser_channels->setEnabled(true); + + int i(0); + foreach(QString file,files) { + QFileInfo fi(file); + comboBox_plugins->addItem(fi.fileName()); + index_2_fullpath.insert(i++,file); + } + comboBox_plugins->setCurrentIndex(0); + pd->pluginSelected(0); + } +} + +//____________________________________________________________________ +void VP1PluginDialog::pluginSelected(int i) +{ + assert(i<m_d->comboBox_plugins->count()); + assert(m_d->index_2_fullpath.contains(i)); + m_d->label_fullpath->setText(m_d->index_2_fullpath.value(i)); + QStringList availablechannels = m_d->channelmanager->channelsInPluginFile(m_d->index_2_fullpath.value(i)); + if (availablechannels.empty()) { + m_d->textBrowser_channels->setHtml("none"); + m_d->textBrowser_channels->setEnabled(false); + } else { + QString text; + foreach(QString bn,availablechannels) { + QStringList uns = m_d->channelmanager->basename2UniqueNames(bn); + bool refreshing=false; + foreach(QString un,uns) { + if (m_d->channelmanager->hasRefreshingSystem(un)) + refreshing=true; + IVP1ChannelWidget* cw = m_d->channelmanager->uniqueName2Channel(un); + assert(cw); + connect(cw,SIGNAL(systemRefreshInfoChanged(QString,int,int)),this,SLOT(updateRefreshInfo())); + } + m_d->pushButton_unload->setEnabled(!m_d->scheduler->isRefreshing()); + QString icontext = m_d->channelmanager->getIconLocation(bn); + text += (icontext.isEmpty()?"":"<img src=\""+icontext+"\">")+"<i>" + +bn+(uns.empty()?"":" ["+QString::number(uns.count()) + +" active"+(refreshing?" (refreshing)":"")+"]")+"</i><br/>"; + } + m_d->textBrowser_channels->setHtml(text); + m_d->textBrowser_channels->setEnabled(true); + } +} + +//____________________________________________________________________ +void VP1PluginDialog::updateRefreshInfo() { + int i = m_d->comboBox_plugins->currentIndex(); + if (i!=-1) + pluginSelected(i); +} diff --git a/graphics/VTI12/VTI12Gui/src/VP1Prioritiser.cxx b/graphics/VTI12/VTI12Gui/src/VP1Prioritiser.cxx new file mode 100644 index 000000000..1fa524816 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1Prioritiser.cxx @@ -0,0 +1,329 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////// +// // +// Implementation of class VP1Prioritiser // +// // +// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Initial version: April 2007 // +// // +///////////////////////////////////////////////////////////// + +#include "VTI12Gui/VP1Prioritiser.h" +#include "VP1Base/IVP1ChannelWidget.h" +#include "VP1Base/IVP1System.h" +#include <QTime> +#include <QQueue> +#include <QSet> +#include <map> +#include <cassert> + +///////////////////////////////////////////////////////////////////// +//////////////////// Class VP1Prioritiser::Imp //////////////////// +///////////////////////////////////////////////////////////////////// + +//____________________________________________________________________ +class VP1Prioritiser::Imp { +public: + + class SystemInfo{ + public: + enum VisibilityState { NOTVISIBLE, VISIBLE, SOONVISIBLE }; + SystemInfo(IVP1System*,Imp *, IVP1ChannelWidget *, const VisibilityState& ); + ~SystemInfo(); + IVP1System * system; + void setVisibilityState(const VisibilityState&); + void addTimeMeasurement(const double&); + double refreshtime() const { return m_timing; } + private: + double m_timing; + double m_priority; + const bool m_accumulator; + VisibilityState m_vs; + void calcPriority(); + Imp *m_d; + void removeFromPriMap(); + QQueue<double> m_timemeasurements; + }; + + VP1Prioritiser * prioritiser; + //The following map is for prioritising the order of system refreshes: + typedef std::multimap<double,IVP1System*> Pri2SysMap; + Pri2SysMap priority2sys;//This map is kept updated automatically by the SystemInfo objects. + + QSet<IVP1ChannelWidget*> visiblechannels, soonvisiblechannels; + double soonvisbonus; + + QHash<IVP1System*,SystemInfo*> sys2info; + + QTime * stopwatch; + IVP1System* currenttimedsystem; + + void updateSysinfoWithVisibilityState(const QSet<IVP1ChannelWidget*>& channels, + const SystemInfo::VisibilityState&vs); + + + std::set<IVP1System *>::const_iterator itsys, itsysE; +}; + +///////////////////////////////////////////////////////////////////// +////////////// Class VP1Prioritiser::Imp::SystemInfo ////////////// +///////////////////////////////////////////////////////////////////// + +//____________________________________________________________________ +inline VP1Prioritiser::Imp::SystemInfo::SystemInfo(IVP1System*s,Imp *d,IVP1ChannelWidget * cw, const VisibilityState& vs ) + : system(s), m_priority(117117.117), + m_accumulator(cw->isAccumulator()),m_vs(vs),m_d(d) +{ + //If another system with the same name exists already, we use that + //timing as a reasonable guess. Otherwise we use the average of the + //other channels. Failing that we use a default of 500ms.: + double tmp(0); + bool found(false); + QHash<IVP1System*,Imp::SystemInfo*>::iterator itE = m_d->sys2info.end(); + for (QHash<IVP1System*,Imp::SystemInfo*>::iterator it=m_d->sys2info.begin();it!=itE;++it) { + if ( it.key()->name() == s->name() ) { + m_timing=it.value()->refreshtime(); + found=true; + break; + } + tmp += m_timing=it.value()->refreshtime(); + } + if (!found&&!m_d->sys2info.empty()) + m_timing = tmp/m_d->sys2info.count(); + else + m_timing=500; + + calcPriority(); +} + +//____________________________________________________________________ +inline VP1Prioritiser::Imp::SystemInfo::~SystemInfo() +{ + removeFromPriMap(); +} + +//____________________________________________________________________ +inline void VP1Prioritiser::Imp::SystemInfo::setVisibilityState(const VisibilityState& vs ) +{ + //Fixme: When do we get tabmanager setVisible signals? At startup? When channels are added? + //Fixme: Do not emit these during file loading!! + if (m_vs==vs) + return; + m_vs = vs; + calcPriority(); +} + +//____________________________________________________________________ +inline void VP1Prioritiser::Imp::SystemInfo::addTimeMeasurement(const double&t) +{ + //Keep the seven latest measurements, and use a truncated mean as + //final estimate. + + m_timemeasurements.enqueue(t); + if (m_timemeasurements.count()==8) + m_timemeasurements.dequeue(); + + QList<double> tmplist = m_timemeasurements; + qSort(tmplist.begin(), tmplist.end()); + + switch(tmplist.count()) { + case 1: m_timing = tmplist.at(0); break; + case 2: m_timing = 0.5*(tmplist.at(0)+tmplist.at(1)); break; + case 3: m_timing = tmplist.at(1); break; + case 4: m_timing = 0.5*(tmplist.at(1)+tmplist.at(2)); break; + case 5: m_timing = (tmplist.at(1)+tmplist.at(2)+tmplist.at(3))/3.0; break; + case 6: m_timing = 0.5*(tmplist.at(2)+tmplist.at(3)); break; + case 7: m_timing = (tmplist.at(2)+tmplist.at(3)+tmplist.at(4))/3.0; break; + default: assert(0&&"Should never happen"); break; + } + + calcPriority(); +} + +//____________________________________________________________________ +inline void VP1Prioritiser::Imp::SystemInfo::calcPriority() +{ + //1) Remove from m_d->priority2sys map + + if (m_priority!=117117.117) + removeFromPriMap(); + + //2) Calculate new priority + + //Priority is based on how long the systems take to refresh (the + //fastest gets refreshed first). In order to ensure that visible, + //soonvisible, and accumulators gets priority they get a bonus of + //30s, XXXms, and 100ms respectively (where XXX depends on the scenario): + + m_priority = m_timing + (m_vs==VISIBLE?-30000.0:(m_vs==SOONVISIBLE?-m_d->soonvisbonus:0.0)) + (m_accumulator?-100.0:0.0); + + //3) Add to m_d->priority2sys map + + std::pair<double,IVP1System*> a(m_priority,system); + m_d->priority2sys.insert(a); +} + +//____________________________________________________________________ +inline void VP1Prioritiser::Imp::SystemInfo::removeFromPriMap() +{ + //Fixme: Cache itp and it (in class Imp even?)! + std::pair<Pri2SysMap::iterator, Pri2SysMap::iterator> itp(m_d->priority2sys.equal_range(m_priority)); + Pri2SysMap::iterator it = itp.first; + for (;it!=itp.second;++it) { + if (it->second==system) { + m_d->priority2sys.erase(it); + break; + } + } + assert(it != itp.second); +} + +///////////////////////////////////////////////////////////////////// +////////////////////// Class VP1Prioritiser /////////////////////// +///////////////////////////////////////////////////////////////////// + +//____________________________________________________________________ +VP1Prioritiser::VP1Prioritiser(QObject*parent) + : QObject(parent), m_d(new Imp) +{ + m_d->prioritiser=this; + m_d->stopwatch = new QTime(); + m_d->currenttimedsystem=0; + m_d->soonvisbonus=0; +} + +//____________________________________________________________________ +VP1Prioritiser::~VP1Prioritiser() +{ + delete m_d->stopwatch; + delete m_d; m_d=0; +} + +//___________________________________________________________________ +IVP1System* VP1Prioritiser::nextErasedActiveSystemByPriority() { + Imp::Pri2SysMap::iterator itE = m_d->priority2sys.end(); + for (Imp::Pri2SysMap::iterator it=m_d->priority2sys.begin();it!=itE;++it) { + if ( it->second->state()==IVP1System::ERASED &&it->second->activeState()==IVP1System::ON ) + return it->second; + } + return 0; +} + +//___________________________________________________________________ +QList<IVP1System*> VP1Prioritiser::getSystemsToEraseByPriority() { + QList<IVP1System*> tmp; + Imp::Pri2SysMap::iterator itE = m_d->priority2sys.end(); + for (Imp::Pri2SysMap::iterator it=m_d->priority2sys.begin();it!=itE;++it) { + if ( it->second->state()==IVP1System::REFRESHED ) + tmp << it->second; + } + return tmp; +} + + +//___________________________________________________________________ +double VP1Prioritiser::estimateRemainingCalcTime() const +{ + double tmp(0); + QHash<IVP1System*,Imp::SystemInfo*>::iterator itE = m_d->sys2info.end(); + for (QHash<IVP1System*,Imp::SystemInfo*>::iterator it=m_d->sys2info.begin();it!=itE;++it) { + if ( it.key()->state()==IVP1System::ERASED &&it.key()->activeState()==IVP1System::ON ) + tmp += it.value()->refreshtime(); + } + return tmp; +} + +//___________________________________________________________________ +double VP1Prioritiser::beginTiming_Refresh(IVP1System*s) +{ + assert(!m_d->currenttimedsystem); + m_d->stopwatch->start(); + m_d->currenttimedsystem=s; + assert(m_d->sys2info.contains(s)); + return m_d->sys2info[s]->refreshtime(); +} + + +//___________________________________________________________________ +double VP1Prioritiser::elapsedTiming_Refresh() +{ + return static_cast<double>(m_d->stopwatch->elapsed()); +} + +//___________________________________________________________________ +double VP1Prioritiser::endTiming_Refresh() +{ + assert(m_d->currenttimedsystem); + double timing = static_cast<double>(m_d->stopwatch->elapsed()); + if (m_d->sys2info.contains(m_d->currenttimedsystem)) {//This check, since the corresponding channel might have become uncreated in the meantime. + m_d->sys2info[m_d->currenttimedsystem]->addTimeMeasurement(timing); + } + m_d->currenttimedsystem=0; + return timing; +} + +//____________________________________________________________________ +void VP1Prioritiser::setupSysItr(IVP1ChannelWidget*cw) { + m_d->itsys = cw->systems().begin(); + m_d->itsysE = cw->systems().end(); +} + +//___________________________________________________________________ +void VP1Prioritiser::Imp::updateSysinfoWithVisibilityState(const QSet<IVP1ChannelWidget*>& channels, + const SystemInfo::VisibilityState&vs) { + foreach(IVP1ChannelWidget*cw,channels) { + for (prioritiser->setupSysItr(cw);itsys!=itsysE;++itsys) { + assert(sys2info.contains(*itsys)); + //if (sys2info.contains(*itsys))//This check since channel deletion might have triggered this update. + sys2info[*itsys]->setVisibilityState(vs); + } + } +} + +//___________________________________________________________________ +void VP1Prioritiser::visibleChannelsChanged(const QSet<IVP1ChannelWidget*>&newvis, + const QSet<IVP1ChannelWidget*>&newsoonvis, + const double& soonvisbonus) +{ + if (m_d->visiblechannels==newvis&&m_d->soonvisiblechannels==newsoonvis&&m_d->soonvisbonus==soonvisbonus) + return; + m_d->updateSysinfoWithVisibilityState(m_d->visiblechannels,Imp::SystemInfo::NOTVISIBLE); + m_d->updateSysinfoWithVisibilityState(m_d->soonvisiblechannels,Imp::SystemInfo::NOTVISIBLE); + m_d->updateSysinfoWithVisibilityState(newvis,Imp::SystemInfo::VISIBLE); + m_d->updateSysinfoWithVisibilityState(newsoonvis,Imp::SystemInfo::SOONVISIBLE); + m_d->visiblechannels = newvis; + m_d->soonvisiblechannels = newsoonvis; + m_d->soonvisbonus = soonvisbonus; +} + +//___________________________________________________________________ +void VP1Prioritiser::channelCreated(IVP1ChannelWidget* cw) +{ + bool visible = m_d->visiblechannels.contains(cw); + bool soonvisible = m_d->soonvisiblechannels.contains(cw); + assert(!(visible&&soonvisible)); + for (setupSysItr(cw);m_d->itsys!=m_d->itsysE;++m_d->itsys) { + assert(!m_d->sys2info.contains(*(m_d->itsys))); + Imp::SystemInfo* info = new Imp::SystemInfo(*(m_d->itsys),m_d,cw, + (visible?Imp::SystemInfo::VISIBLE:(soonvisible?Imp::SystemInfo::SOONVISIBLE:Imp::SystemInfo::NOTVISIBLE))); + m_d->sys2info.insert(*(m_d->itsys),info); + } +} + +//___________________________________________________________________ +void VP1Prioritiser::channelUncreated(IVP1ChannelWidget* cw) +{ + for (setupSysItr(cw);m_d->itsys!=m_d->itsysE;++m_d->itsys) { + assert(m_d->sys2info.contains(*(m_d->itsys))); + delete m_d->sys2info[*(m_d->itsys)]; + m_d->sys2info.remove(*(m_d->itsys)); + } + if (m_d->visiblechannels.contains(cw)) + m_d->visiblechannels.remove(cw); + if (m_d->soonvisiblechannels.contains(cw)) + m_d->soonvisiblechannels.remove(cw); +} diff --git a/graphics/VTI12/VTI12Gui/src/VP1QtApplication.cxx b/graphics/VTI12/VTI12Gui/src/VP1QtApplication.cxx new file mode 100644 index 000000000..dee159985 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1QtApplication.cxx @@ -0,0 +1,69 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////// +// // +// Implementation file for class VP1QtApplication // +// // +// Author: Riccardo Maria BIANCHI <rbianchi@cern.ch> // +// // +// This class reimplements the basic notify() method // +// of the QApplication class, in order to catch // +// exceptions from C++, and to avoid fatal errors // +// like: // +// "Qt has caught an exception thrown from an event // +// handler. Throwing exceptions from an event handler // +// is not supported in Qt. You must reimplement // +// QApplication::notify() and catch all exceptions // +// there. // +// // +// // +// Initial version: 19 November 2012 // +// // +///////////////////////////////////////////////////////// + + +// include VP1 +#include "VTI12Gui/VP1QtApplication.h" +#include "VP1Base/VP1Msg.h" + +// include Qt +#include <QEvent> + +// include C++ +#include <typeinfo> +//#include <stddef.h> // this to fix the 'ptrdiff_t' does not name a type error with Qt (http://qt-project.org/forums/viewthread/16992) + + +bool VP1QtApplication::notify(QObject *rec, QEvent *ev) +{ + //std::cout << (3, "Called VP1QtApplication::notify()") << std::endl; + + // only for debug + //VP1Msg::message("VP1QtApplication:notify()"); + + // for normal events we pass to QApplication:notify()... + try { + return QApplication::notify(rec, ev); + } + catch (std::exception &e) { + VP1Msg::message("VP1QtApplication: std::exception: "); + qWarning("VP1QtApplication: Error '%s' sending event '%s' to object '%s' ('%s')", + e.what(), typeid(*ev).name(), qPrintable(rec->objectName()), + typeid(*rec).name()); + qWarning("throwing the exception again..."); + throw e; + return false; + } + catch (char const *str) { + VP1Msg::message("VP1QtApplication: EXCEPTION: " + QString(str) ); + return false; + } + catch (...) { + VP1Msg::message("VP1QtApplication: Unknown exception!"); + return false; + } + //VP1Msg::message("VP1QtApplication: outside catch..."); // only for DEBUG + return false; +} diff --git a/graphics/VTI12/VTI12Gui/src/VP1SelectEvent.cxx b/graphics/VTI12/VTI12Gui/src/VP1SelectEvent.cxx new file mode 100644 index 000000000..41a4ac70b --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1SelectEvent.cxx @@ -0,0 +1,68 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +////////////////////////////////////////////////////////////////////////// +// // +// Source file for class VP1SelectEvent // +// // +// Description: Dialog for the selection of a specific event in a file // +// // +// Author: Sebastian Andreas Merkt (sebastian.andreas.merkt@cern.ch) // +// Initial version: August 2018 // +// // +////////////////////////////////////////////////////////////////////////// + +#include "VTI12Gui/VP1SelectEvent.h" + +#include <QPushButton> +#include <QGridLayout> + +#include <QtWidgets> +#include <QString> + +VP1SelectEvent::VP1SelectEvent(int totEvtNr, int evtNr, QWidget *parent) : QDialog(parent) +{ + //Set default dialog size + int nWidth = 400; + int nHeight = 200; + if (parent != NULL) + setGeometry(parent->x() + parent->width()/2 - nWidth/2, + parent->y() + parent->height()/2 - nHeight/2, + nWidth, nHeight); + else + resize(nWidth, nHeight); + + //Buttonbox to set Open, Cancel buttons + m_buttonBox = new QDialogButtonBox(this); + m_openButton = m_buttonBox->addButton(tr("&Select"), QDialogButtonBox::AcceptRole); + m_cancelButton = m_buttonBox->addButton(tr("&Cancel"),QDialogButtonBox::RejectRole); + connect(m_openButton, &QPushButton::clicked, this, &VP1SelectEvent::passEvtNr); + connect(m_cancelButton, &QPushButton::clicked, this, &VP1SelectEvent::reject); + + + m_spinBox = new QSpinBox(); + m_spinBox->setRange(1, totEvtNr); + m_spinBox->setSingleStep(1); + m_spinBox->setValue(evtNr+1); + + const QString line2 = QString::number(totEvtNr) + " events in file."; + + //Create the main layout + QGridLayout *mainLayout = new QGridLayout(this); + mainLayout->addWidget(new QLabel(tr("Select event:")), 0, 0); + mainLayout->addWidget(m_spinBox, 0, 1); + mainLayout->addWidget(new QLabel(line2), 1, 0); + mainLayout->addWidget(m_buttonBox, 2, 1); + +} + +void VP1SelectEvent::passEvtNr(){ + if( m_spinBox->value() != 0 ) { + VP1SelectEvent::done(m_spinBox->value()); + } +} + +void VP1SelectEvent::reject(){ + VP1SelectEvent::done(-1); +} diff --git a/graphics/VTI12/VTI12Gui/src/VP1StreamMenuUpdater.cxx b/graphics/VTI12/VTI12Gui/src/VP1StreamMenuUpdater.cxx new file mode 100644 index 000000000..a3a3925c3 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1StreamMenuUpdater.cxx @@ -0,0 +1,78 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "VP1StreamMenuUpdater.h" + +#include <QDir> +#include <QFile> +#include <QFileInfo> +#include <QTextStream> +#include <QTimer> +#include <QDateTime> +#include <QMutexLocker> + +VP1StreamMenuUpdater::VP1StreamMenuUpdater(VP1DirStatuses& diractions + ,QMutex* mutex + ,QObject* parent) + : QThread(parent) + , m_inputdiractions(diractions) + , m_mutex(mutex) + , m_timer(0) +{ +} + +VP1StreamMenuUpdater::~VP1StreamMenuUpdater() +{ + delete m_timer; +} + +void VP1StreamMenuUpdater::run() +{ + updateInputDirectoriesStatus(); + m_timer = new QTimer(0); + connect(m_timer, SIGNAL(timeout()), this, SLOT(updateInputDirectoriesStatus()),Qt::DirectConnection); + m_timer->start(5000); + exec(); +} + +void VP1StreamMenuUpdater::updateInputDirectoriesStatus() +{ + QMutexLocker locker(m_mutex); + + foreach (QAction* act,m_inputdiractions.keys()) { + VP1DirStatusData& dirstatus = m_inputdiractions[act]; + dirstatus.enabled = true; + dirstatus.bold = false; + dirstatus.dirStatus = "unknown"; + + // Check whether it exists and is really a directory + QFileInfo fi(dirstatus.inputDir); + if (!fi.exists()||!fi.isDir()) { + dirstatus.enabled = false; + dirstatus.dirStatus = "not found"; + } else { + // Access the latest_vp1event file in order to get the name of the latest vp1 event file + // in the directory + QFile latestFileRef(dirstatus.inputDir + "/latest_vp1event"); + if(latestFileRef.exists() + && latestFileRef.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream textStream(&latestFileRef); + QString latestFileName = textStream.readLine(); + latestFileRef.close(); + + QFileInfo latestFile(latestFileName); + if(latestFile.exists()) { + int secondswithoutupdate = latestFile.lastModified().secsTo(QDateTime::currentDateTime()); + dirstatus.bold = (secondswithoutupdate<60); + if (secondswithoutupdate<120) + dirstatus.dirStatus = QString::number(secondswithoutupdate)+" seconds since update"; + else if (secondswithoutupdate<7200) + dirstatus.dirStatus = QString::number(static_cast<int>(secondswithoutupdate/60.0+0.5))+" minutes since update"; + else + dirstatus.dirStatus = QString::number(static_cast<int>(secondswithoutupdate/3600.0+0.5))+" hours since update"; + } + } + } + } +} diff --git a/graphics/VTI12/VTI12Gui/src/VP1StreamMenuUpdater.h b/graphics/VTI12/VTI12Gui/src/VP1StreamMenuUpdater.h new file mode 100644 index 000000000..2ded5f6ba --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1StreamMenuUpdater.h @@ -0,0 +1,37 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef VP1StreamMenuUpdater_h +#define VP1StreamMenuUpdater_h + +#include "VTI12Gui/VP1MainWindow.h" +#include <QThread> + +class QMutex; +class QTimer; + +class VP1StreamMenuUpdater : public QThread +{ + Q_OBJECT + + public: + VP1StreamMenuUpdater(VP1DirStatuses& + ,QMutex* + ,QObject* parent = 0); + + ~VP1StreamMenuUpdater(); + + public slots: + void updateInputDirectoriesStatus(); + + protected: + void run(); + + private: + VP1DirStatuses& m_inputdiractions; + QMutex* m_mutex; + QTimer* m_timer; +}; + +#endif diff --git a/graphics/VTI12/VTI12Gui/src/VP1TabManager.cxx b/graphics/VTI12/VTI12Gui/src/VP1TabManager.cxx new file mode 100644 index 000000000..58a127a99 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1TabManager.cxx @@ -0,0 +1,1580 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////// +// // +// Implementation of class VP1TabManager // +// // +// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Initial version: April 2007 // +// // +///////////////////////////////////////////////////////////// + +#include "VTI12Gui/VP1TabManager.h" +#include "VTI12Gui/VP1ChannelManager.h" +#include "VTI12Gui/VP1DockWidget.h" + +#include "VP1Base/VP1TabWidget.h" +#include "VP1Base/VP1TabBar.h" +#include "VP1Base/IVP1System.h" +#include "VP1Base/IVP1ChannelWidget.h" +#include "VP1Base/IVP13DStandardChannelWidget.h" +#include "VP1Base/VP1QtUtils.h" +#include "VP1Base/VP1Serialise.h" +#include "VP1Base/VP1Deserialise.h" +#include "VP1Base/VP1Msg.h" + +#include <QEvent> +#include <QPoint> +#include <QSet> +#include <QFileInfo> +#include <QMap> +#include <QTimer> +#include <QBuffer> +#include <QByteArray> +#include <QMessageBox> +#include <QMenu> +#include <QKeyEvent> +#include <QMainWindow> +#include <QApplication> +#include <QInputDialog> + +#include <map> +#include <set> +#include <cassert> +#include <iostream>//fixme + + + +//_______________________________________________________________________ +class VP1TabManager::Imp { +public: + //Constructor, tabwidget & channel manager: + Imp(VP1TabManager*tm,VP1TabWidget* tw, VP1ChannelManager* cm) + : tabmanager(tm), tabwidget(tw),channelmanager(cm), + dontEmitVisibilityChanges{}, + selecteddockwidget(0), + fullscreen_dockwidget(0),fullscreen_channelwidget(0), + fullscreen_tabindex(-1),fullscreen_tab(0),tabcruisemode(false) {} + + VP1TabManager* tabmanager; + VP1TabWidget * tabwidget; + VP1ChannelManager* channelmanager; + + //Convenience: + QMainWindow * channel2tab(IVP1ChannelWidget*cw); + QMainWindow * name2tab(QString tabname);//Returns 0 if not found + + //The actual bookkeeping maps: + std::map<QString,QMainWindow *> name_2_tab; + std::map<IVP1ChannelWidget*,VP1DockWidget*> channelwidget_2_dockwidget; + std::map<QMainWindow*,std::set<IVP1ChannelWidget*> > tab_2_channelwidgets; + + //For sanity checking input, and providing appropriate warnings. + //Fixme: Check also max number of chars. + bool checkTabnameNotEmpty(QString tabname) const; + bool checkTabnameExists(QString tabname) const; + bool checkTabnameNotExists(QString tabname) const; + + bool checkChannelNameExists(QString channelbasename, const bool& isuniquename, const bool& checkfornonexistance = false) const; + + bool dontEmitVisibilityChanges; + QSet<IVP1ChannelWidget*> lastvisible; + QSet<IVP1ChannelWidget*> lastsoonvisible; + + VP1DockWidget* selecteddockwidget; + //Fullscreen of individual channels: + VP1DockWidget* fullscreen_dockwidget; + IVP1ChannelWidget* fullscreen_channelwidget; + //Fullscreen of tabs: + QString fullscreen_tabname; + int fullscreen_tabindex; + QMainWindow* fullscreen_tab; + std::set<VP1DockWidget*> fullscreen_floatingdocks; + + QMap<QString,QStringList> serializeTabAndChannelConfigInfo() const; + void serializeTabAndChannelConfigInfo(QMap<QString,QMultiMap<QString,ChanState> >& tab2channels, + QMap<QString,QByteArray>&tab2arrangements) const; + + QMainWindow* previousTab(); + QMainWindow* nextTab(); + bool tabcruisemode; + + QStringList channelsInTab(QMainWindow* tab); + QStringList channelsInTab(const QString&); + + QString channelWithPendingRemoval; +}; + +//_______________________________________________________________________ +VP1TabManager::VP1TabManager( QObject* parent, VP1TabWidget * tw, VP1ChannelManager* cm ) + : QObject(parent), m_d(new Imp(this,tw,cm)) { + + m_d->dontEmitVisibilityChanges=false; + tw->setTabReorderingEnabled(true); + connect(tw->getVP1TabBar(),SIGNAL(contextMenu( int, const QPoint& )), + this,SLOT(raiseTabBarContextMenu(int,const QPoint &))); + + connect(tw,SIGNAL(currentChanged(int)),this,SLOT(currentVisibleChanged())); +} + + + +//_______________________________________________________________________ +VP1TabManager::~VP1TabManager(){ + while (m_d->tabwidget->count()>0) { + removeTab( m_d->tabwidget->tabText(0) ); + } + delete m_d; +} + + +//___________________________________________________________________________________ +void VP1TabManager::launchStereoEditorCurrentTab(){ + VP1Msg::messageVerbose("VP1TabManager::launchStereoEditorCurrentTab()"); + IVP13DStandardChannelWidget* channel = dynamic_cast<IVP13DStandardChannelWidget*>(selectedChannelWidget()); + if (channel ) { + channel->launchStereoEditor(); + } +} + + + +////___________________________________________________________________________________ +//void VP1TabManager::setAntiAliasingCurrentTab(bool aa) +//{ +// VP1Msg::messageVerbose("VP1TabManager::setAntiAliasingCurrentTab()"); +// +// if (dynamic_cast<IVP13DStandardChannelWidget*>(selectedChannelWidget()) ) { +// IVP13DStandardChannelWidget* channel = dynamic_cast<IVP13DStandardChannelWidget*>(selectedChannelWidget()); +// channel->setAntiAliasing(aa); +// } +//} + + +//___________________________________________________________________________________ +bool VP1TabManager::Imp::checkTabnameExists(QString tabname) const { + if (!checkTabnameNotEmpty(tabname)) + return false; + if (name_2_tab.find(tabname)==name_2_tab.end()) { + QMessageBox::critical(0, "Error - Tab "+tabname+" does not exists", + "Tab <i>"+tabname+"</i> does not exists.",QMessageBox::Ok,QMessageBox::Ok); + return false; + } + return true; +} + +//___________________________________________________________________________________ +bool VP1TabManager::Imp::checkTabnameNotExists(QString tabname) const { + if (!checkTabnameNotEmpty(tabname)) + return false; + if (name_2_tab.find(tabname)!=name_2_tab.end()) { + QMessageBox::critical(0, "Error - Tab "+tabname+" already exists", + "Tab <i>"+tabname+"</i> already exists.",QMessageBox::Ok,QMessageBox::Ok); + return false; + } + return true; +} + +//___________________________________________________________________________________ +bool VP1TabManager::Imp::checkTabnameNotEmpty(QString tabname) const { + if (tabname.isEmpty()) { + QMessageBox::critical(0, "Error - Empty tab name provided", + "Empty tab name provided.",QMessageBox::Ok,QMessageBox::Ok); + return false; + } + return true; +} + +//___________________________________________________________________________________ +bool VP1TabManager::Imp::checkChannelNameExists(QString channelname, const bool& isuniquename, const bool& checkfornonexistance) const { + if (channelname.isEmpty()) { + QMessageBox::critical(0, "Error - Empty channel name provided", + "Empty channel name provided.",QMessageBox::Ok,QMessageBox::Ok); + return false; + } + if ( checkfornonexistance == ( isuniquename ? channelmanager->uniqueNameExists(channelname) + : channelmanager->baseNameExists(channelname) ) ) { + QString tmp = ( checkfornonexistance ? "already":"does not" ); + QMessageBox::critical(0, "Error - Channel "+channelname+" "+tmp+" exists", + "Channel <i>"+channelname+"</i> "+tmp+" exists.",QMessageBox::Ok,QMessageBox::Ok); + return false; + } + return true; +} + +//_______________________________________________________________________ +QStringList VP1TabManager::Imp::channelsInTab(QMainWindow* tab) +{ + assert(tab_2_channelwidgets.find(tab)!=tab_2_channelwidgets.end()); + if (tab_2_channelwidgets.find(tab)==tab_2_channelwidgets.end()) + return QStringList(); + std::set<IVP1ChannelWidget*>::const_iterator it, itE = tab_2_channelwidgets[tab].end(); + + QStringList l; + for (it = tab_2_channelwidgets[tab].begin();it!=itE;++it) { + l << (*it)->unique_name(); + } + + return l; +} + +//_______________________________________________________________________ +QStringList VP1TabManager::Imp::channelsInTab(const QString& tabname) +{ + //Get list of (unique) names of channels in this tab: + assert(name_2_tab.find(tabname)!=name_2_tab.end()); + if (name_2_tab.find(tabname)==name_2_tab.end()) + return QStringList(); + return channelsInTab(name_2_tab[tabname]); +} + + +//_______________________________________________________________________ +void VP1TabManager::addNewTab(QString tabname,const int& index) +{ + if (!m_d->checkTabnameNotExists(tabname)) return; + bool save = m_d->dontEmitVisibilityChanges; + m_d->dontEmitVisibilityChanges=true; + + QMainWindow * t = new QMainWindow(); + t->setDockNestingEnabled(true); + if (index==-1) + m_d->tabwidget->addTab(t,tabname); + else + m_d->tabwidget->insertTab(index,t,tabname); + //NB: Do not call: t->setParent(m_d->tabwidget); + m_d->name_2_tab[tabname]=t; + m_d->tab_2_channelwidgets[t] = std::set<IVP1ChannelWidget*>(); + tabListChanged(tabList()); + m_d->dontEmitVisibilityChanges=save; + currentVisibleChanged(); +} + +//___________________________________________________________________________________ +void VP1TabManager::dropOutOfFullScreen() +{ + if (!(m_d->fullscreen_dockwidget||m_d->fullscreen_tab)) + return; + + bool save = m_d->dontEmitVisibilityChanges; + m_d->dontEmitVisibilityChanges=true; + qApp->removeEventFilter(this); + QWidget * focuswidget = qApp->focusWidget(); + + if (m_d->fullscreen_dockwidget) { + assert(m_d->fullscreen_dockwidget&&m_d->fullscreen_channelwidget); + m_d->fullscreen_dockwidget->ensureCWHasParent(); + m_d->fullscreen_channelwidget->showNormal();//fixme? Do inside dockwidget? + m_d->fullscreen_dockwidget=0; + m_d->fullscreen_channelwidget=0; + } else { + assert(m_d->fullscreen_tab); + QWidget * dummywidget=m_d->tabwidget->widget(m_d->fullscreen_tabindex); + m_d->tabwidget->removeTab(m_d->fullscreen_tabindex); + m_d->tabwidget->insertTab(m_d->fullscreen_tabindex, m_d->fullscreen_tab, m_d->fullscreen_tabname ); + delete dummywidget; + m_d->tabwidget->setCurrentIndex(m_d->fullscreen_tabindex); + //Make dockwidgets in the tab floatable again + assert(m_d->tab_2_channelwidgets.find(m_d->fullscreen_tab)!=m_d->tab_2_channelwidgets.end()); + std::set<IVP1ChannelWidget*>::const_iterator it = m_d->tab_2_channelwidgets[m_d->fullscreen_tab].begin(); + std::set<IVP1ChannelWidget*>::const_iterator itE = m_d->tab_2_channelwidgets[m_d->fullscreen_tab].end(); + for (;it!=itE;++it) { + assert(m_d->channelwidget_2_dockwidget.find(*it)!=m_d->channelwidget_2_dockwidget.end()); + VP1DockWidget * dock = m_d->channelwidget_2_dockwidget[*it]; + dock->setFeatures(VP1DockWidget::DockWidgetMovable|VP1DockWidget::DockWidgetFloatable); + if (m_d->fullscreen_floatingdocks.find(dock)!=m_d->fullscreen_floatingdocks.end()) + dock->setFloating(true); + } + m_d->fullscreen_tabname = ""; + m_d->fullscreen_tabindex = -1; + m_d->fullscreen_tab = 0; + m_d->fullscreen_floatingdocks.clear(); + } + if (focuswidget&&!focuswidget->hasFocus()) + focuswidget->setFocus(Qt::OtherFocusReason); + m_d->dontEmitVisibilityChanges=save; + currentVisibleChanged(); +} + +//___________________________________________________________________________________ +bool VP1TabManager::eventFilter ( QObject *, QEvent * event ) { + + //When in fullscreen mode we monitor all events in the application + //to look for ESC (leave fullscreen) and to prevent any toplevel + //widgets from getting closed by e.g. the user pressing ALT+F4. + + if (event->type()==QEvent::Close) { + event->ignore(); + return true; + } + + if (event->type()!=QEvent::KeyPress) + return false; + + QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event); + assert(keyEvent); + if (keyEvent->key()!=Qt::Key_Escape) + return false; + + dropOutOfFullScreen(); + + //Eat the event: + return true; +} + +//___________________________________________________________________________________ +void VP1TabManager::setSelectedDockWidget(VP1DockWidget*dw) { + + VP1Msg::messageDebug("VP1TabManager::setSelectedDockWidget()"); + + if ( m_d->selecteddockwidget == dw ) + return; + + if (m_d->selecteddockwidget) + m_d->selecteddockwidget->setUnselected(); + + m_d->selecteddockwidget=dw; + if (dw) + dw->setSelected(); + + selectedChannelChanged( dw ? dw->channelWidget() : 0 ); +} + +//___________________________________________________________________________________ +void VP1TabManager::setSelectedChannelWidget(IVP1ChannelWidget*cw) +{ + if (!cw) { + setSelectedDockWidget(0); + return; + } + assert(m_d->channelwidget_2_dockwidget.find(cw)!=m_d->channelwidget_2_dockwidget.end()); + setSelectedDockWidget(m_d->channelwidget_2_dockwidget[cw]); +} + +//___________________________________________________________________________________ +void VP1TabManager::showChannelFullScreen(IVP1ChannelWidget*cw) { + dropOutOfFullScreen(); + + assert(m_d->channelwidget_2_dockwidget.find(cw)!=m_d->channelwidget_2_dockwidget.end()); + VP1DockWidget* dock = m_d->channelwidget_2_dockwidget[cw]; + bool save = m_d->dontEmitVisibilityChanges; + m_d->dontEmitVisibilityChanges=true; + m_d->fullscreen_dockwidget=dock; + m_d->fullscreen_channelwidget=cw; + cw->hide(); + dock->ensureCWHasNoParent(); + cw->showFullScreen(); + qApp->installEventFilter(this); + m_d->dontEmitVisibilityChanges=save; + currentVisibleChanged(); + + +} + +//___________________________________________________________________________________ +void VP1TabManager::showCurrentChannelFullScreen() +{ + if(!m_d->selecteddockwidget) + return; + showChannelFullScreen(m_d->selecteddockwidget->channelWidget()); +} + +//___________________________________________________________________________________ +QString VP1TabManager::currentChannelUniqueName() const +{ + if(!m_d->selecteddockwidget) + return ""; + else + return m_d->selecteddockwidget->channelWidget()->unique_name(); +} + +//___________________________________________________________________________________ +void VP1TabManager::showTabFullScreen(QString tabname) +{ + int index = 0; + for (; index < m_d->tabwidget->count(); ++index) { + if (m_d->tabwidget->tabText(index)==tabname) + break; + } + if (index >= m_d->tabwidget->count()) + return; + dropOutOfFullScreen(); + //Test that we are not already fs: + assert(m_d->fullscreen_tabname.isEmpty()); + assert(m_d->fullscreen_tabindex==-1); + assert(!m_d->fullscreen_tab); + assert(m_d->fullscreen_floatingdocks.empty()); + + bool save = m_d->dontEmitVisibilityChanges; + m_d->dontEmitVisibilityChanges=true; + + //Set tab info: + m_d->fullscreen_tabindex = index; + m_d->fullscreen_tabname = m_d->tabwidget->tabText(m_d->fullscreen_tabindex); + assert(m_d->name_2_tab.find(m_d->fullscreen_tabname)!=m_d->name_2_tab.end()); + m_d->fullscreen_tab = m_d->name_2_tab[m_d->fullscreen_tabname]; + //Dock all dockwidgets in the tab that are currently floating, and make them unfloatable: + assert(m_d->tab_2_channelwidgets.find(m_d->fullscreen_tab)!=m_d->tab_2_channelwidgets.end()); + std::set<IVP1ChannelWidget*>::const_iterator it = m_d->tab_2_channelwidgets[m_d->fullscreen_tab].begin(); + std::set<IVP1ChannelWidget*>::const_iterator itE = m_d->tab_2_channelwidgets[m_d->fullscreen_tab].end(); + for (;it!=itE;++it) { + assert(m_d->channelwidget_2_dockwidget.find(*it)!=m_d->channelwidget_2_dockwidget.end()); + VP1DockWidget * dock = m_d->channelwidget_2_dockwidget[*it]; + if (dock->isFloating()) { + m_d->fullscreen_floatingdocks.insert(dock); + dock->setFloating(false); + } + dock->setFeatures(VP1DockWidget::DockWidgetMovable); + } + + //Remove tab, put a dummy in its place, and go fullscreen: + m_d->tabwidget->removeTab(m_d->fullscreen_tabindex); + m_d->fullscreen_tab->hide(); + m_d->fullscreen_tab->setParent(0); + m_d->tabwidget->insertTab ( m_d->fullscreen_tabindex, new QWidget(), m_d->fullscreen_tabname ); + m_d->fullscreen_tab->showFullScreen(); + //Needs an extra update apparently, to get selection frame properly enlarged + it = m_d->tab_2_channelwidgets[m_d->fullscreen_tab].begin(); + itE = m_d->tab_2_channelwidgets[m_d->fullscreen_tab].end(); + for (;it!=itE;++it) { + assert(m_d->channelwidget_2_dockwidget.find(*it)!=m_d->channelwidget_2_dockwidget.end()); + VP1DockWidget * dock = m_d->channelwidget_2_dockwidget[*it]; + dock->update(); + } + + qApp->installEventFilter(this); + m_d->dontEmitVisibilityChanges=save; + currentVisibleChanged(); + +} + +//___________________________________________________________________________________ +void VP1TabManager::showCurrentTabFullScreen() +{ + if (m_d->tabwidget->count()==0) + return; + showTabFullScreen(m_d->tabwidget->tabText(m_d->tabwidget->currentIndex())); +} + + + +//___________________________________________________________________________________ +IVP1ChannelWidget* VP1TabManager::selectedChannelWidget() const { + return m_d->selecteddockwidget ? m_d->selecteddockwidget->channelWidget() : 0; +} + +//_______________________________________________________________________ +IVP1ChannelWidget * VP1TabManager::addChannelToTab(QString channelbasename,QString tabname) { + + #if defined BUILDVP1LIGHT + bool checkDisallowMultipleChannels = VP1QtUtils::expertSettingIsOn("general","ExpertSettings/VP1_DISALLOW_MULTIPLE_CHANNELS"); + #else + bool checkDisallowMultipleChannels = VP1QtUtils::environmentVariableIsOn("VP1_DISALLOW_MULTIPLE_CHANNELS"); + #endif + + if (m_d->channelwidget_2_dockwidget.size()&&checkDisallowMultipleChannels) { + QMessageBox::critical(0, "Error - Not allowed to open channel", + "The possibility to launch multiple channels has been disabled by the environment variable VP1_DISALLOW_MULTIPLE_CHANNELS." + " This was likely set since some badly written 3D drivers have been known to cause crashes when showing multiple 3D views." + "\n In order to launch a new channel you must thus first remove the already active channel." + "\n To disable this behaviour don't set VP1_DISALLOW_MULTIPLE_CHANNELS, or set it to \"0'.",QMessageBox::Ok,QMessageBox::Ok); + return 0; + } + + if (!m_d->checkTabnameExists(tabname)) return 0; + if (!m_d->checkChannelNameExists(channelbasename, false)) return 0; + + //Then we get the channel: + QString err; + IVP1ChannelWidget * cw = m_d->channelmanager->getChannel( channelbasename,err ); + if (!err.isEmpty()) { + QMessageBox::critical(0, "Error - could not get channel: "+channelbasename, + "Could not get channel: "+channelbasename + +"\n\nReason: "+err,QMessageBox::Ok,QMessageBox::Ok); + + return 0; + } + assert(cw); + bool save = m_d->dontEmitVisibilityChanges; + m_d->dontEmitVisibilityChanges=true; + cw->setUpdatesEnabled(false); + + //Everything went well - go ahead and add the channel to the tab. + VP1DockWidget *dock = new VP1DockWidget(cw,this); + connect(dock,SIGNAL(topLevelChanged(bool)),this,SLOT(currentVisibleChanged())); + connect(dock,SIGNAL(wasSelected(VP1DockWidget*)),this,SLOT(setSelectedDockWidget(VP1DockWidget*))); + + QMainWindow * tab = m_d->name_2_tab[tabname]; + tab->addDockWidget(Qt::TopDockWidgetArea, dock); + + assert(m_d->channelwidget_2_dockwidget.find(cw)==m_d->channelwidget_2_dockwidget.end()); + m_d->channelwidget_2_dockwidget[cw]=dock; + assert(m_d->tab_2_channelwidgets.find(tab)!=m_d->tab_2_channelwidgets.end()); + m_d->tab_2_channelwidgets[tab].insert(cw); + cw->setUpdatesEnabled(true); + m_d->dontEmitVisibilityChanges=save; + currentVisibleChanged(); + return cw; +} + +//_______________________________________________________________________ +void VP1TabManager::renameTab( QString tabname, QString newtabname ) { + if (!m_d->checkTabnameExists(tabname)) return; + if (!m_d->checkTabnameNotExists(newtabname)) return; + + QMainWindow * tab = m_d->name_2_tab[tabname]; + + m_d->name_2_tab.erase(m_d->name_2_tab.find(tabname)); + m_d->name_2_tab[newtabname]=tab; + int tabindex = m_d->tabwidget->indexOf(tab); + assert(tabindex!=-1); + m_d->tabwidget->setTabText ( tabindex, newtabname ); + tabListChanged(tabList()); +} + +//_______________________________________________________________________ +QStringList VP1TabManager::tabList() { + QStringList l; + for (int i = 0; i < m_d->tabwidget->count(); ++i) { + l<<m_d->tabwidget->tabText(i); + } + return l; +} + + +//_______________________________________________________________________ +void VP1TabManager::removeTab( QString tabname ) { + + if (!m_d->checkTabnameExists(tabname)) return; + + bool save = m_d->dontEmitVisibilityChanges; + m_d->dontEmitVisibilityChanges=true; + + assert(m_d->name_2_tab.find(tabname)!=m_d->name_2_tab.end()); + QMainWindow * tab = m_d->name_2_tab[tabname]; + assert(tab); + assert(m_d->tab_2_channelwidgets.find(tab)!=m_d->tab_2_channelwidgets.end()); + + //First, we turn off updates on all channel widgets in the tab (this + //prevents some crashes due to poorly written channels): + std::set<IVP1ChannelWidget*>::const_iterator it = m_d->tab_2_channelwidgets[tab].begin(); + std::set<IVP1ChannelWidget*>::const_iterator itE = m_d->tab_2_channelwidgets[tab].end(); + for (;it!=itE;++it) { + (*it)->setUpdatesEnabled(false);//Fixme: do this on detach/reattach also? + (*it)->hide(); + } + + while(m_d->tab_2_channelwidgets[tab].size()>0) { + IVP1ChannelWidget * channelwidget = *(m_d->tab_2_channelwidgets[tab].begin()); + removeChannel(channelwidget->unique_name()); + } + + //Remove the tab from the tabwidget (this does not actually delete the tab) + m_d->name_2_tab.erase(m_d->name_2_tab.find(tabname)); + int i = m_d->tabwidget->indexOf(tab); + assert(i!=-1); + m_d->tabwidget->removeTab(i); + + delete tab; + + tabListChanged(tabList()); + m_d->dontEmitVisibilityChanges=save; + currentVisibleChanged(); +} + + +//_______________________________________________________________________ +void VP1TabManager::removeAllTabs() +{ + VP1Msg::messageDebug("VP1TabManager::removeAllTabs()"); + foreach(QString tab, tabList() ) { + removeTab(tab); + } +} + + +//___________________________________________________________________________________ +void VP1TabManager::removeChannel(QString channeluniquename) { + + VP1Msg::messageDebug("VP1TabManager::removeChannel()"); + + if (!m_d->checkChannelNameExists(channeluniquename, true)) return; + + IVP1ChannelWidget* cw = m_d->channelmanager->uniqueName2Channel(channeluniquename); + assert(cw); + + //Unselect if selected: + if (m_d->selecteddockwidget&&cw==m_d->selecteddockwidget->channelWidget()) + setSelectedDockWidget(0); + + QString bn = cw->name(); + cw->setUpdatesEnabled(false); + + assert(m_d->channelwidget_2_dockwidget.find(cw)!=m_d->channelwidget_2_dockwidget.end()); + VP1DockWidget * dw = m_d->channelwidget_2_dockwidget[cw]; + + //Update maps: + assert(m_d->channelwidget_2_dockwidget.find(cw)!=m_d->channelwidget_2_dockwidget.end()); + m_d->channelwidget_2_dockwidget.erase(m_d->channelwidget_2_dockwidget.find(cw)); + + //And remove dock from tab. + QMainWindow * tab = m_d->channel2tab(cw); + assert(tab); + +// int itab = m_d->tabwidget->indexOf(tab); +// assert(itab!=-1); +// QString tabname = m_d->tabwidget->tabText(itab); + // m_d->tabwidget->removeTab(itab); + tab->setUpdatesEnabled(false); + tab->removeDockWidget(dw); + + + //Update map: + assert(m_d->tab_2_channelwidgets[tab].find(cw)!=m_d->tab_2_channelwidgets[tab].end()); + m_d->tab_2_channelwidgets[tab].erase(m_d->tab_2_channelwidgets[tab].find(cw)); + + //delete channel + cw->hide(); + dw->ensureCWHasNoParent(); + [[maybe_unused]] //To avoid compile warning in opt mode. + bool ok=m_d->channelmanager->deleteChannel(cw->unique_name()); + assert(ok); + + //delete dock widget + delete dw; + + tab->setUpdatesEnabled(true); + // m_d->tabwidget->insertTab(itab,tab,tabname); + + if (m_d->selecteddockwidget==dw) { + m_d->selecteddockwidget=0; + selectedChannelChanged(0); + } + + currentVisibleChanged(); +} + +//___________________________________________________________________________________ +QMainWindow * VP1TabManager::Imp::channel2tab(IVP1ChannelWidget*cw) { + std::map<QMainWindow*,std::set<IVP1ChannelWidget*> >::iterator it = tab_2_channelwidgets.begin(); + std::map<QMainWindow*,std::set<IVP1ChannelWidget*> >::iterator itE = tab_2_channelwidgets.end(); + for (;it!=itE;++it) { + if (it->second.find(cw)!=it->second.end()) + return it->first; + } + return 0; +} + + +//___________________________________________________________________________________ +QMainWindow * VP1TabManager::Imp::name2tab(QString tabname) +{ + if (name_2_tab.find(tabname)==name_2_tab.end()) + return 0; + return name_2_tab[tabname]; +} + +//Fixme: check for empty input strings in all methods where applicable! + +//___________________________________________________________________________________ +void VP1TabManager::moveChannelToTab(QString channeluniquename,QString tabname) { + + if (!m_d->checkTabnameExists(tabname)) return; + if (!m_d->checkChannelNameExists(channeluniquename, true)) return; + + QMainWindow * tab_new = m_d->name_2_tab[tabname]; + assert(tab_new); + IVP1ChannelWidget* cw = m_d->channelmanager->uniqueName2Channel(channeluniquename); + assert(cw); + + assert(m_d->channelwidget_2_dockwidget.find(cw)!=m_d->channelwidget_2_dockwidget.end()); + + VP1DockWidget* dw = m_d->channelwidget_2_dockwidget[cw]; + assert(dw); + QMainWindow * tab_old = m_d->channel2tab(cw); + assert(tab_old); + + if (tab_old==tab_new)//Fixme: Make warning here instead, and ensure that the interface does not allow this. + return; + + tab_old->removeDockWidget(dw); + dw->setParent(tab_new); + tab_new->addDockWidget(Qt::TopDockWidgetArea, dw); + dw->show(); + + //Update tab_2_channelwidgets: + assert(m_d->tab_2_channelwidgets.find(tab_old)!=m_d->tab_2_channelwidgets.end()); + assert(m_d->tab_2_channelwidgets.find(tab_new)!=m_d->tab_2_channelwidgets.end()); + assert(m_d->tab_2_channelwidgets[tab_old].find(cw)!=m_d->tab_2_channelwidgets[tab_old].end()); + assert(m_d->tab_2_channelwidgets[tab_new].find(cw)==m_d->tab_2_channelwidgets[tab_new].end());//dies! + m_d->tab_2_channelwidgets[tab_old].erase(m_d->tab_2_channelwidgets[tab_old].find(cw)); + m_d->tab_2_channelwidgets[tab_new].insert(cw); + +} + +//___________________________________________________________________________________ +void VP1TabManager::cloneChannelToTab(QString channeluniquename,QString tabname) { + if (!m_d->checkTabnameExists(tabname)) return; + if (!m_d->checkChannelNameExists(channeluniquename, true)) return; + IVP1ChannelWidget* cw = m_d->channelmanager->uniqueName2Channel(channeluniquename); + assert(cw); + IVP1ChannelWidget * newcw = addChannelToTab(cw->name(),tabname); + if (newcw) { + ChanState state; + serializeChannelState(cw,state); + unserializeChannelState(newcw,state); + } +} + +//___________________________________________________________________________________ +void VP1TabManager::cloneTab(QString oldtabname,QString newtabname) +{ + if (!m_d->checkTabnameExists(oldtabname)) return; + if (!m_d->checkTabnameNotExists(newtabname)) return; + + addNewTab(newtabname); + + assert(m_d->name_2_tab.find(newtabname)!=m_d->name_2_tab.end()); + + QMainWindow * oldtab = m_d->name_2_tab[oldtabname]; + + assert(m_d->tab_2_channelwidgets.find(oldtab)!=m_d->tab_2_channelwidgets.end()); + std::set<IVP1ChannelWidget*>::const_iterator it = m_d->tab_2_channelwidgets[oldtab].begin(); + std::set<IVP1ChannelWidget*>::const_iterator itE = m_d->tab_2_channelwidgets[oldtab].end(); + + for (;it!=itE;++it) { + IVP1ChannelWidget * newcw = addChannelToTab((*it)->name(),newtabname); + if (newcw) { + ChanState state; + serializeChannelState(*it,state); + unserializeChannelState(newcw,state); + } + } + + QMainWindow * newtab = m_d->name_2_tab[newtabname]; + QByteArray state = oldtab->saveState(); + if (!newtab->restoreState(state)) + QMessageBox::warning(0, "Warning - Problems cloning channel arrangement", + "Problems cloning channel arrangement.",QMessageBox::Ok,QMessageBox::Ok); +} + + + +//___________________________________________________________________________________ +void VP1TabManager::saveConfigurationToFile(QString filename,const bool& askonoverride) { + if (filename.isEmpty()) { + QMessageBox::critical(0, "Error - Empty file name provided", + "Empty file name provided.",QMessageBox::Ok,QMessageBox::Ok); + return; + } + //If file exists, ask to overwrite. + QFileInfo fi(filename); + if (fi.exists()) { + if (!fi.isWritable()) { + QMessageBox::critical(0, "Error - could not save to file "+filename, + "Could not save to file: <i>"+filename+"</i>" + +"<br/><br/>Reason: File exists already and is write protected",QMessageBox::Ok,QMessageBox::Ok); + return; + } + if (askonoverride) { + int ret = QMessageBox::question(0, "File already exists: "+filename, + "The file <i>"+filename+"</i> already exists.\n" + "Override this file?", + QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Cancel); + if (ret==QMessageBox::Cancel) + return; + } + } + + QFile file(filename); + if (!file.open(QIODevice::WriteOnly)) { + QMessageBox::critical(0, "Error - problems writing to file "+filename, + "Problems writing to file: <i>"+filename+"</i>",QMessageBox::Ok,QMessageBox::Ok); + return; + } + + //Serialise : + QMap<QString,QMultiMap<QString,ChanState> > tab2channels; + QMap<QString,QByteArray> tab2arrangements; + m_d->serializeTabAndChannelConfigInfo(tab2channels, tab2arrangements); + + //Put into bytearray: + QByteArray byteArray; + QBuffer buffer(&byteArray); + buffer.open(QIODevice::WriteOnly); + QDataStream out(&buffer); + out<<QString("This is an automatically generated config file for VP1. [cfg version 003]" ); + out<<m_d->channelmanager->serializePluginInfo(); + out<<tab2channels; + out<<tab2arrangements; + out<<tabList();//For tab *order* + out<<QString("This is the end of the automatically generated config file for VP1." ); + buffer.close(); + + QDataStream outfile(&file); + outfile<<qCompress(byteArray).toBase64(); + + +} + +//___________________________________________________________________________________ +void VP1TabManager::loadConfigurationFromFile(QString filename,const QMap<QString,QString>& availableplugins) { + if (filename.isEmpty()) { + QMessageBox::critical(0, "Error - Empty file name provided", + "Empty file name provided.",QMessageBox::Ok,QMessageBox::Ok); + return; + } + QFileInfo fi(filename); + if (!fi.exists()) { + QMessageBox::critical(0, "Error - file does not exists: "+filename, + "File does not exists: <i>"+filename+"</i>",QMessageBox::Ok,QMessageBox::Ok); + return; + } + if (!fi.isReadable()) { + QMessageBox::critical(0, "Error - file is not readable: "+filename, + "File is not readable: <i>"+filename+"</i>",QMessageBox::Ok,QMessageBox::Ok); + return; + } + //open file + QFile file(filename); + if (!file.open(QIODevice::ReadOnly)) { + QMessageBox::critical(0, "Error - problems opening file "+filename, + "Problems opening file: <i>"+filename+"</i>",QMessageBox::Ok,QMessageBox::Ok); + return; + } + + //Read: + QString head,foot; + QStringList pluginfiles; + QMap<QString,QMultiMap<QString,ChanState> > tab2channels; + QMap<QString,QByteArray> tab2arrangements; + QStringList tabs_orded; + + QByteArray byteArray64; + QDataStream infile(&file); + infile >> byteArray64; + + QByteArray byteArray = qUncompress(QByteArray::fromBase64(byteArray64)); + + QBuffer buffer(&byteArray); + buffer.open(QIODevice::ReadOnly); + QDataStream in(&buffer); + in >> head; + in >> pluginfiles; + in >> tab2channels; + in >> tab2arrangements; + in >> tabs_orded; + in >> foot; + buffer.close(); + + if (head!="This is an automatically generated config file for VP1. [cfg version 003]" + ||foot!="This is the end of the automatically generated config file for VP1." + ||tab2channels.count()!=tab2arrangements.count()) { + QMessageBox::critical(0, "Error - file not in correct format: "+filename, + "File not in correct format: <i>"+filename+"</i>",QMessageBox::Ok,QMessageBox::Ok); + return; + } + + QStringList pf_withproblem; + QStringList errormessage; + +#ifdef __APPLE__ + QString sharedlibsuffix_correct = ".dylib"; + QString sharedlibsuffix_wrong = ".so"; +#else + QString sharedlibsuffix_correct = ".so"; + QString sharedlibsuffix_wrong = ".dylib"; +#endif + + foreach(QString pf,pluginfiles) { + if (pf.endsWith(sharedlibsuffix_wrong)) { + pf.replace(sharedlibsuffix_wrong, sharedlibsuffix_correct); + } + + if (!availableplugins.contains(pf)) { + pf_withproblem<<pf; + errormessage<<"Could not locate " + pf; + continue; + } + QString pfabsolute = availableplugins[pf]; + QString err; + if (m_d->channelmanager->channelsInPluginFile(pfabsolute).empty()) + err = m_d->channelmanager->loadPluginFile(pfabsolute); + if (!err.isEmpty()) { + pf_withproblem<<pfabsolute; + errormessage<<err; + } + } + + if (!pf_withproblem.empty()) { + assert(pf_withproblem.count()==errormessage.count()); + QString tmp; + for (int i = 0; i<pf_withproblem.count();++i) { + tmp += pf_withproblem.value(i)+": "+errormessage.value(i)+"\n"; + } + QMessageBox::warning(0, "Warning - could not load all plugins", + "Some or more plugins did not load properly:\n\n"+tmp,QMessageBox::Ok,QMessageBox::Ok); + } + + QString channelsFailureMsg; + QString tabArrangementFailureMsg; + + QString lastaddedtab; + + foreach (QString newtabname_infile, tabs_orded) { + //Check format: + if (!tab2channels.contains(newtabname_infile)||!tab2arrangements.contains(newtabname_infile)) { + QMessageBox::critical(0, "Error - file not in correct format: "+filename, + "File not in correct format: <i>"+filename+"</i>",QMessageBox::Ok,QMessageBox::Ok); + return; + } + + //We are about to add a new tab. If there is already one with + //that name we remove it if it is empty: + QMainWindow * existingtab = m_d->name2tab(newtabname_infile); + if (existingtab) { + if (m_d->tab_2_channelwidgets.find(existingtab)==m_d->tab_2_channelwidgets.end() + ||m_d->tab_2_channelwidgets[existingtab].empty()) + removeTab(newtabname_infile); + } + + //Special case: If there are presently no loaded channels, and + //only one existing tab named 'My Tab', then we remove that one + if (m_d->channelwidget_2_dockwidget.empty() + &&m_d->name_2_tab.size()==1 + &&m_d->name_2_tab.begin()->first=="My Tab") + removeTab("My Tab"); + + QString newtabname = suggestNewTabName(newtabname_infile); + addNewTab(newtabname); + if (!m_d->checkTabnameExists(newtabname)) + return; + lastaddedtab=newtabname; + + QMapIterator<QString,ChanState> it( tab2channels.value(newtabname_infile) ); + + while (it.hasNext()) { + it.next(); + //it.key(): Channel base name. + //it.value(): Channel state info. + if (!m_d->channelmanager->baseNameExists(it.key())) { + channelsFailureMsg += it.key()+" (tab "+newtabname+")"+"\n"; + } else { + IVP1ChannelWidget * cw = addChannelToTab( it.key(), newtabname ); + if (cw) + unserializeChannelState(cw,it.value()); + else + channelsFailureMsg += it.key()+" (tab "+newtabname+")"+"\n"; + } + } + + //Setup layout state: + assert(m_d->name_2_tab.find(newtabname)!=m_d->name_2_tab.end()); + QMainWindow * tab = m_d->name_2_tab.find(newtabname)->second; + QByteArray state = tab2arrangements.value(newtabname_infile); + + if (!state.isEmpty()) { + if (!tab->restoreState(state,0/*version*/)) { + tabArrangementFailureMsg += newtabname+"\n"; + } + } + } + if (!channelsFailureMsg.isEmpty()) { + QMessageBox::warning(0, "Warning - could not start all channels", + "Some or more channels were not available to start:\n\n" + +channelsFailureMsg,QMessageBox::Ok,QMessageBox::Ok); + } + if (!tabArrangementFailureMsg.isEmpty()) { + QMessageBox::warning(0, "Warning - could not arrange channels in all tabs", + "The arrangement of channels could not be properly determined withing the following tabs:\n\n" + +tabArrangementFailureMsg,QMessageBox::Ok,QMessageBox::Ok); + } + if (!lastaddedtab.isEmpty()) + showTab(lastaddedtab); +} + +//___________________________________________________________________________________ +void VP1TabManager::Imp::serializeTabAndChannelConfigInfo(QMap<QString,QMultiMap<QString,ChanState> >& tab2channels, + QMap<QString,QByteArray>& tab2arrangements) const { + + tab2channels.clear(); + tab2arrangements.clear(); + for (int i = 0; i< tabwidget->count();++i) { + QString tabname = tabwidget->tabText(i); + assert(name_2_tab.find(tabname)!=name_2_tab.end()); + QMainWindow * tab = name_2_tab.find(tabname)->second; + QMultiMap<QString,ChanState> channelsinfo; + std::map<QMainWindow*,std::set<IVP1ChannelWidget*> >::const_iterator itcws=tab_2_channelwidgets.find(tab); + assert(itcws!=tab_2_channelwidgets.end()); + std::set<IVP1ChannelWidget*>::const_iterator it = itcws->second.begin(); + std::set<IVP1ChannelWidget*>::const_iterator itE = itcws->second.end(); + for (;it!=itE;++it) { + ChanState chanstate; + tabmanager->serializeChannelState(*it,chanstate); + channelsinfo.insert((*it)->name(),chanstate); + } + tab2channels.insert(tabname,channelsinfo); + + + tab2arrangements.insert(tabname,tab->saveState(0/*version*/)); + } +} + +//___________________________________________________________________________________ +QString VP1TabManager::suggestNewTabName(QString oldtabname) const { + QString newtabname=oldtabname; + int i = 1; + while (m_d->name_2_tab.find(newtabname)!=m_d->name_2_tab.end()) + newtabname=oldtabname+" "+QString::number(++i); + return newtabname; +} + +//___________________________________________________________________________________ +QString VP1TabManager::currentTab() const { + if (m_d->tabwidget->count()==0) + return ""; + return m_d->tabwidget->tabText(m_d->tabwidget->currentIndex()); +} + +//___________________________________________________________________________________ +int VP1TabManager::nTabs() const { + return m_d->tabwidget->count(); +} + +//___________________________________________________________________________________ +QMainWindow* VP1TabManager::Imp::nextTab(){ + if (tabwidget->count()<=1) + return 0; + std::cout<<"currentindex:"<<tabwidget->currentIndex()<<std::endl; + std::cout<<"nextindex:"<<(tabwidget->currentIndex() + 1) % tabwidget->count()<<std::endl; + std::cout<<"ntabs:"<<tab_2_channelwidgets.size()<<std::endl; + QMainWindow*nexttab=static_cast<QMainWindow*>(tabwidget->widget((tabwidget->currentIndex() + 1) % tabwidget->count())); + assert(nexttab); + assert(tab_2_channelwidgets.find(nexttab)!=tab_2_channelwidgets.end()); +// if (tab_2_channelwidgets.find(nexttab)==tab_2_channelwidgets.end()) +// return fullscreen_tab; +// else + return nexttab; +} + +//___________________________________________________________________________________ +QMainWindow* VP1TabManager::Imp::previousTab(){ + if (tabwidget->count()<=1) + return 0; + int newindex = tabwidget->currentIndex() - 1; + if (newindex<0) + newindex += tabwidget->count(); + QMainWindow*prevtab = static_cast<QMainWindow*>(tabwidget->widget(newindex % tabwidget->count())); + if (tab_2_channelwidgets.find(prevtab)==tab_2_channelwidgets.end()) + return fullscreen_tab; + else + return prevtab; +} + +//___________________________________________________________________________________ +bool VP1TabManager::showTab(QString tabname){ + int itarget(-1); + for (int i = 0; i < m_d->tabwidget->count(); ++i) { + if (m_d->tabwidget->tabText(i)==tabname) { + itarget = i; + break; + } + } + if (itarget<0) + return false; + if (itarget==m_d->tabwidget->currentIndex()) + return true; + + bool save = m_d->dontEmitVisibilityChanges; + m_d->dontEmitVisibilityChanges=true; + + bool fullscreentab = (m_d->fullscreen_tab!=0); + if (m_d->fullscreen_channelwidget||m_d->fullscreen_tab) + dropOutOfFullScreen(); + + m_d->tabwidget->setCurrentIndex(itarget); + if (fullscreentab) + showCurrentTabFullScreen(); + m_d->dontEmitVisibilityChanges=save; + currentVisibleChanged(); + return true; +} + + +//___________________________________________________________________________________ +void VP1TabManager::showNextTab(){ + if (m_d->tabwidget->count()<=1) + return; + assert(!m_d->fullscreen_channelwidget); + if (m_d->fullscreen_tab) { + bool save = m_d->dontEmitVisibilityChanges; + m_d->dontEmitVisibilityChanges=true; + dropOutOfFullScreen(); + showNextTab(); + showCurrentTabFullScreen(); + m_d->dontEmitVisibilityChanges=save; + } + m_d->tabwidget->setCurrentIndex((m_d->tabwidget->currentIndex() + 1) % m_d->tabwidget->count()); +} + +//___________________________________________________________________________________ +void VP1TabManager::showPreviousTab() { + assert(!m_d->fullscreen_channelwidget); + assert(!m_d->fullscreen_tab);//Fixme: as above. + if (m_d->tabwidget->count()<=1) + return; + int newindex = m_d->tabwidget->currentIndex() - 1; + if (newindex<0) + newindex += m_d->tabwidget->count(); + m_d->tabwidget->setCurrentIndex( newindex % m_d->tabwidget->count()); +} + +//___________________________________________________________________________________ +void VP1TabManager::raiseTabBarContextMenu(int i,const QPoint & p) { + + QString tabname = m_d->tabwidget->tabText(i); + + QMenu menu(m_d->tabwidget); + + //Construct menu: + // menu.addAction("Tab: "+tabname)->setEnabled(false); + // menu.addSeparator (); + QAction* pFullScreenAction = menu.addAction("Show &full Screen"); + menu.addSeparator(); + QAction* pRenameAction = menu.addAction("Re&name tab"); + QAction* pDeleteAction = menu.addAction("&Remove tab"); + menu.addSeparator (); + QAction* pInsertNewAction = menu.addAction("&Insert new tab"); + QAction* pCloneAction = menu.addAction("&Clone tab"); + menu.addSeparator (); + QAction* pAddChannelAction = menu.addAction("&Add channel"); + QAction* pRemoveChannelAction = menu.addAction("R&emove channel"); + + QMenu menu_addchan(m_d->tabwidget); + QStringList chnls = m_d->channelmanager->availableChannelList(); + if (chnls.empty()) { + menu_addchan.addAction("No channels available")->setEnabled(false); + } else { + foreach (QString chnl, chnls) { + QString iconloc = m_d->channelmanager->getIconLocation(chnl, true); + QAction* pChnlAct; + if (iconloc.isEmpty()) + pChnlAct = menu_addchan.addAction(chnl); + else + pChnlAct = menu_addchan.addAction(QIcon(iconloc),chnl); + pChnlAct->setData("ADDCHAN"); + } + } + pAddChannelAction->setMenu(&menu_addchan); + QStringList chnls_rem = m_d->channelsInTab(tabname); + if (chnls_rem.empty()) + pFullScreenAction->setEnabled(false); + QMenu menu_remchan(m_d->tabwidget); + if (chnls_rem.empty()) { + menu_remchan.addAction("No channels in tab")->setEnabled(false); + } else { + foreach (QString chnl, chnls_rem) { + QString iconloc = m_d->channelmanager->getIconLocation(chnl, false); + QAction* pChnlAct; + if (iconloc.isEmpty()) + pChnlAct = menu_remchan.addAction(chnl); + else + pChnlAct = menu_remchan.addAction(QIcon(iconloc),chnl); + pChnlAct->setData("REMCHAN"); + } + } + pRemoveChannelAction->setMenu(&menu_remchan); + + + //Execute + QAction * selAct = menu.exec(p); + // + if (!selAct) + return; + if (selAct==pFullScreenAction) { + showTabFullScreen(tabname); + return; + } + if (selAct==pRenameAction) { + bool ok; + QString text = QInputDialog::getText( 0, "Rename tab '"+tabname+"'","Rename tab '"+tabname+"' to:", + QLineEdit::Normal, tabname, &ok ); + if (!ok||text==tabname) + return; + renameTab(tabname,text); + return; + } + if (selAct==pDeleteAction) { + removeTab( tabname ); + return; + } + if (selAct==pInsertNewAction) { + bool ok; + QString newtabname = QInputDialog::getText( 0, "New Tab Name","New tab name:", + QLineEdit::Normal, suggestNewTabName("My Tab"), &ok ); + if (!ok||newtabname.isEmpty()) + return; + addNewTab(newtabname,i+1); + return; + } + if (selAct==pCloneAction) { + bool ok; + QString newtabname = QInputDialog::getText( 0, "Cloning '"+tabname+"'.","Cloning '"+tabname+"'. Name of new tab:", + QLineEdit::Normal, suggestNewTabName(tabname), &ok ); + if (!ok||newtabname.isEmpty()) + return; + cloneTab(tabname,newtabname); + return; + } + if (selAct==pAddChannelAction) { + return; + } + //Only option left is channels... + if (selAct->data()=="ADDCHAN") { + addChannelToTab( selAct->text(), tabname ); + return; + } + if (selAct->data()=="REMCHAN") { + removeChannel( selAct->text() ); + return; + } + std::cout<<"ERROR in VP1TabManager::raiseTabBarContextMenu!!!!!"<<std::endl; +} + +//___________________________________________________________________________________ +void VP1TabManager::currentVisibleChanged() { + if (m_d->dontEmitVisibilityChanges) + return; + + QSet<IVP1ChannelWidget*> visible; + QSet<IVP1ChannelWidget*> soonvisible; + double soonbonus(0.0); + + ///////////////////////////////////////////////////////////////////// + //////////////////////////// VISIBLE //////////////////////////// + ///////////////////////////////////////////////////////////////////// + + if (m_d->fullscreen_dockwidget) { + //Thats an easy one: + visible << m_d->fullscreen_dockwidget->channelWidget(); + } else if (m_d->fullscreen_tab) { + //Add all channel widgets from this tab: + assert(m_d->tab_2_channelwidgets.find(m_d->fullscreen_tab)!=m_d->tab_2_channelwidgets.end()); + std::set<IVP1ChannelWidget*>::iterator it,itE; + itE = m_d->tab_2_channelwidgets[m_d->fullscreen_tab].end(); + for (it = m_d->tab_2_channelwidgets[m_d->fullscreen_tab].begin();it!=itE;++it) { + visible << *it; + } + std::cout<<"fullscreen tab:"<<m_d->fullscreen_tab<<std::endl; + } else { + //Go through the tabs, if it is the current tab we add all dock + //widgets, otherwise we add those that are floating: + QWidget * currentTab = m_d->tabwidget->currentWidget(); + std::map<QMainWindow*,std::set<IVP1ChannelWidget*> >::iterator tabIt,tabItE = m_d->tab_2_channelwidgets.end(); + std::set<IVP1ChannelWidget*>::iterator it,itE; + for (tabIt=m_d->tab_2_channelwidgets.begin();tabIt!=tabItE;++tabIt) { + //Loop over channels; + it = tabIt->second.begin(); + itE = tabIt->second.end(); + for (;it!=itE;++it) { + if (currentTab==tabIt->first) { + //Add all: + visible << *it; + } else { + if (!m_d->fullscreen_tab) { + //Add only if floating and not a fullscreen tab: + assert(m_d->channelwidget_2_dockwidget.find(*it)!=m_d->channelwidget_2_dockwidget.end()); + if (m_d->channelwidget_2_dockwidget[*it]->isFloating()) + visible << *it; + } + } + } + } + } + + ///////////////////////////////////////////////////////////////////// + ///////////////////////// SOON VISIBLE ////////////////////////// + ///////////////////////////////////////////////////////////////////// + + if (m_d->fullscreen_dockwidget) { + assert(!m_d->tabcruisemode); + //Soon visible: All floating channels (not this one) and all channels in the present tab. + soonbonus = 2000;//We are afterall quite sure here what will soon be visible. + QWidget * currentTab = m_d->tabwidget->currentWidget(); + std::map<QMainWindow*,std::set<IVP1ChannelWidget*> >::iterator tabIt, tabItE = m_d->tab_2_channelwidgets.end(); + std::set<IVP1ChannelWidget*>::iterator it,itE; + for (tabIt=m_d->tab_2_channelwidgets.begin();tabIt!=tabItE;++tabIt) { + //Loop over channels; + itE = tabIt->second.end(); + for (it=tabIt->second.begin();it!=itE;++it) { + if (currentTab==tabIt->first) { + //Add all except the fullscreen'ed one: + if (*it!=m_d->fullscreen_dockwidget->channelWidget()) + soonvisible << *it; + } else { + //Add only if floating: + assert(m_d->channelwidget_2_dockwidget.find(*it)!=m_d->channelwidget_2_dockwidget.end()); + if (m_d->channelwidget_2_dockwidget[*it]->isFloating()) + soonvisible << *it; + } + } + } + } else if (m_d->fullscreen_tab) { + if (m_d->tabcruisemode&&m_d->tab_2_channelwidgets.size()>1) { + //Everything in the next tab. + soonbonus = 10000;//Very important that the stuff in the next tab gets a high priority! + QMainWindow * nexttab = m_d->nextTab(); + assert(nexttab); + std::cout<<"fullscreen tab:"<<m_d->fullscreen_tab<<std::endl; + std::cout<<"nexttab:"<<nexttab<<std::endl; + assert(m_d->tab_2_channelwidgets.find(nexttab)!=m_d->tab_2_channelwidgets.end()); + std::set<IVP1ChannelWidget*>::iterator it,itE=m_d->tab_2_channelwidgets[nexttab].end(); + for(it=m_d->tab_2_channelwidgets[nexttab].begin();it!=itE;++it){ + soonvisible << *it; + } + } else { + //All floating channels not in the present tab + soonbonus = 1000;//We are rather sure here what will soon be visible. + QWidget * currentTab = m_d->tabwidget->currentWidget(); + std::map<QMainWindow*,std::set<IVP1ChannelWidget*> >::iterator tabIt, tabItE = m_d->tab_2_channelwidgets.end(); + std::set<IVP1ChannelWidget*>::iterator it,itE; + for (tabIt=m_d->tab_2_channelwidgets.begin();tabIt!=tabItE;++tabIt) { + //Loop over channels; + itE = tabIt->second.end(); + for (it=tabIt->second.begin();it!=itE;++it) { + if (m_d->fullscreen_tab!=tabIt->first&¤tTab!=tabIt->first) { + //Add only if floating: + assert(m_d->channelwidget_2_dockwidget.find(*it)!=m_d->channelwidget_2_dockwidget.end()); + if (m_d->channelwidget_2_dockwidget[*it]->isFloating()) + soonvisible << *it; + } + } + } + } + } else { + //Add everything non-floating from the next tab. + soonbonus = 200;//A weak guess (fixme: Stronger if tab cruise mode). + if (m_d->tabwidget->count()>=2) { + int nexttabindex = (m_d->tabwidget->currentIndex() + 1) % m_d->tabwidget->count(); + QMainWindow* tab = static_cast<QMainWindow*>(m_d->tabwidget->widget(nexttabindex)); + assert(tab); + assert(m_d->tab_2_channelwidgets.find(tab)!=m_d->tab_2_channelwidgets.end()); + std::set<IVP1ChannelWidget*>::iterator it,itE=m_d->tab_2_channelwidgets[tab].end(); + for (it=m_d->tab_2_channelwidgets[tab].begin();it!=itE;++it) { + assert(m_d->channelwidget_2_dockwidget.find(*it)!=m_d->channelwidget_2_dockwidget.end()); + if (!m_d->channelwidget_2_dockwidget[*it]->isFloating()) + soonvisible << *it; + } + } + } + + + assert(soonbonus>0.0); + +#ifndef NDEBUG + //There should be no intersection between visible and soon visible! + QSet<IVP1ChannelWidget*> tmp = visible; + tmp.intersect(soonvisible); + assert(tmp.empty()); +#endif + + if (visible!=m_d->lastvisible||soonvisible!=m_d->lastsoonvisible) { + m_d->lastvisible=visible; + m_d->lastsoonvisible=soonvisible; + visibleChannelsChanged(visible,soonvisible,soonbonus); + + //To ensure that we dont show controllers for channels that are + //not visible: + if (m_d->selecteddockwidget) { + if (!visible.contains(m_d->selecteddockwidget->channelWidget())) + setSelectedDockWidget(0); + } + + //To make sure we automatically select a channel if it is the only + //one visible: + if (visible.count()==1&&(!m_d->selecteddockwidget||*(visible.begin())!=m_d->selecteddockwidget->channelWidget())) { + assert(m_d->channelwidget_2_dockwidget.find(*(visible.begin()))!=m_d->channelwidget_2_dockwidget.end()); + setSelectedDockWidget(m_d->channelwidget_2_dockwidget[*(visible.begin())]); + } + } +} + +//___________________________________________________________________________________ +QString VP1TabManager::channelToTab(IVP1ChannelWidget*cw) +{ + QMainWindow * tab = m_d->channel2tab(cw); + if (!tab) + return "VP1TabManager::channelToTab ERROR: Unknown CW"; + + std::map<QString,QMainWindow *>::const_iterator it, itE = m_d->name_2_tab.end(); + for ( it = m_d->name_2_tab.begin(); it!=itE; ++it ) { + if (it->second == tab) + return it->first; + } + return ""; +} + +//___________________________________________________________________________________ +bool VP1TabManager::hasTab(QString tabname) const +{ + return m_d->name_2_tab.find(tabname)!=m_d->name_2_tab.end(); +} + +//___________________________________________________________________________________ +bool VP1TabManager::showFirstChannelWithGivenBasename(QString basename) { + + std::set<IVP1ChannelWidget*>::const_iterator it2,it2E; + + std::map<QMainWindow*,std::set<IVP1ChannelWidget*> >::const_iterator + it = m_d->tab_2_channelwidgets.begin(), itE=m_d->tab_2_channelwidgets.end(); + for (;it!=itE;++it) { + it2=it->second.begin(); + it2E=it->second.end(); + for (;it2!=it2E;++it2) { + if ((*it2)->name()==basename) { + //Figure out the tabname: + std::map<QString,QMainWindow *>::const_iterator it3,it3E; + it3=m_d->name_2_tab.begin();it3E=m_d->name_2_tab.end(); + for (;it3!=it3E;++it3) { + if (it3->second==it->first) + return showTab(it3->first); + } + //Something is wrong. + return false; + } + } + } + return false; +} + + +//___________________________________________________________________________________ +QList<IVP1ChannelWidget*> VP1TabManager::allChannels() const +{ + QList<IVP1ChannelWidget*> l; + std::map<IVP1ChannelWidget*,VP1DockWidget*>::iterator it, itE(m_d->channelwidget_2_dockwidget.end()); + for(it=m_d->channelwidget_2_dockwidget.begin();it!=itE;++it) { + l <<it->first; + } + return l; +} + + +//___________________________________________________________________________________ +const QSet<IVP1ChannelWidget*>& VP1TabManager::visibleChannels() const +{ + return m_d->lastvisible; +} +//___________________________________________________________________________________ +const QSet<IVP1ChannelWidget*>& VP1TabManager::soonVisibleChannels() const +{ + return m_d->lastsoonvisible; +} + + +//___________________________________________________________________________________ +bool VP1TabManager::isVisible(IVP1ChannelWidget*cw) const +{ + return m_d->lastvisible.contains(cw); +} + +//___________________________________________________________________________________ +void VP1TabManager::setTabCruiseMode(const bool& b) { + if (m_d->tabcruisemode==b) + return; + bool save = m_d->dontEmitVisibilityChanges; + m_d->dontEmitVisibilityChanges = true; + m_d->tabcruisemode = b; +// if (m_d->tabcruisemode) { +// assert(!fullscreen_dockwidget);//We cant be in FS single-channel mode. +// if (fullscreen_tab) { +// //Dock all floating (in other tabs) immediately (fixme: only when they need to be shown!. +// } else { +// //normal mode +// } +// } else { +// } + //Soonvisible might have changed - so emit changes: + m_d->dontEmitVisibilityChanges=save; + currentVisibleChanged(); +} + + + + +//___________________________________________________________________________________ +void VP1TabManager::removeChannelAfterQueueEmpties(const QString& chnlun) +{ + m_d->channelWithPendingRemoval = chnlun; + QTimer::singleShot(0, this, SLOT(executePendingChannelRemoval())); +} + +//___________________________________________________________________________________ +void VP1TabManager::executePendingChannelRemoval() +{ + if (m_d->channelWithPendingRemoval.isEmpty()) + return; + removeChannel(m_d->channelWithPendingRemoval); + m_d->channelWithPendingRemoval=""; +} + +//___________________________________________________________________________________ +void VP1TabManager::serializeChannelState(IVP1ChannelWidget*cw,ChanState&state) +{ + QMap<QString,QByteArray> sysstate; + std::set<IVP1System*>::const_iterator it, itE = cw->systems().end(); + for (it=cw->systems().begin();it!=itE;++it) { + unsigned nVP1Serialise = VP1Serialise::numberOfInstantiations(); + sysstate.insertMulti((*it)->name(),(*it)->saveState()); + if (nVP1Serialise==VP1Serialise::numberOfInstantiations()) + VP1Msg::messageDebug("VP1TabManager WARNING: System "+(*it)->name() + +" did not use VP1Serialise in implementation of saveState()"); + } + + state.first = cw->saveState(); + state.second = sysstate; +} + +//___________________________________________________________________________________ +void VP1TabManager::unserializeChannelState(IVP1ChannelWidget*cw,ChanState state) +{ + if(!state.first.isEmpty()) + cw->restoreFromState(state.first); + + QList<QString> storedSystems = state.second.keys(); + + std::set<IVP1System*>::const_iterator itsys, itsysE = cw->systems().end(); + for (itsys=cw->systems().begin();itsys!=itsysE;++itsys) { + QString name = (*itsys)->name(); + //Look for the first entry with this system name in the list. If it is there - use it and remove it: + QMultiMap<QString,QByteArray>::iterator it_state = state.second.find(name); + if (it_state != state.second.end()) { + storedSystems.removeAll(name); +// //Lets make sure that we advance it_state to the LAST of the elements with the same key: +// QMultiMap<QString,QByteArray>::iterator it_state_tmp = it_state; +// while ( it_state_tmp != state.second.end() && it_state_tmp.key() == (*itsys)->name() ) { +// it_state=it_state_tmp; +// ++it_state_tmp; +// } + //Fixme ^^^: The above has not been tested on any channel which + //actually has multiple similar systems. So might be buggy. + + //Use it and remove it from array: + if (!it_state.value().isEmpty()) { + unsigned nVP1Deserialise = VP1Deserialise::numberOfInstantiations(); + (*itsys)->restoreFromState(it_state.value()); + if (nVP1Deserialise==VP1Deserialise::numberOfInstantiations()) + VP1Msg::messageDebug("VP1TabManager WARNING: System "+(*itsys)->name() + +" did not use VP1Deserialise in implementation of restoreFromState()"); + } + //state.second.erase(it_state); + } else { + std::cout<<"VP1TabManager::unserializeChannelState Warning: Did not find state data for system "<<name.toStdString()<<std::endl; + } + } + foreach (QString name,storedSystems) + std::cout<<"VP1TabManager::unserializeChannelState Warning: Did not use stored configuration for system "<<name.toStdString()<<std::endl; +} diff --git a/graphics/VTI12/VTI12Gui/src/VP1TcpServer.cxx b/graphics/VTI12/VTI12Gui/src/VP1TcpServer.cxx new file mode 100644 index 000000000..d59cce42a --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1TcpServer.cxx @@ -0,0 +1,214 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////// +// // +// Implementation of class VP1TcpServer // +// // +// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Initial version: April 2007 // +// // +///////////////////////////////////////////////////////////// + +#include "VTI12Gui/VP1TcpServer.h" +#include <QTcpServer> +#include <QTcpSocket> +#include <QDataStream> +#include <QTimer> +#include <QMap> +#include <cassert> + +//____________________________________________________________________ +class VP1TcpServer::Imp { +public: + VP1TcpServer * tcpserv; + quint16 port; + QTcpServer tcpserver; + QMap<QTcpSocket *,quint16> sockets2blocksize; + QTcpSocket * recognisedSocket(QObject*) const; + int lastemit_listen; +}; + +//____________________________________________________________________ +VP1TcpServer::VP1TcpServer() + : QObject(), m_d(new Imp) +{ + m_d->lastemit_listen=-1; + m_d->tcpserv=this; + m_d->port=0; + connect(&m_d->tcpserver, SIGNAL(newConnection()),this, SLOT(acceptConnection())); + + // + QTimer * timer = new QTimer(this); + timer->start(2000); + connect(timer, SIGNAL(timeout()),this, SLOT(listenStateMightHaveChanged())); +} + +//____________________________________________________________________ +VP1TcpServer::~VP1TcpServer() +{ + close(); + delete m_d; m_d=0; +} + +//____________________________________________________________________ +bool VP1TcpServer::listen(QString& err, const quint16& port) { + if (isListening()) + close(); + bool success = m_d->tcpserver.listen(QHostAddress::LocalHost,port); + if (!success) { + err = m_d->tcpserver.errorString(); + m_d->port=0; + listenStateMightHaveChanged(); + return false; + } + m_d->port=port; + err.clear(); + + listenStateMightHaveChanged(); + return true; +} + +//____________________________________________________________________ +quint16 VP1TcpServer::port() const +{ + return m_d->port; +} + +//____________________________________________________________________ +bool VP1TcpServer::isListening() +{ + return m_d->tcpserver.isListening(); +} + +//____________________________________________________________________ +void VP1TcpServer::close() +{ + if (!isListening()) + return; + disconnect(&m_d->tcpserver, SIGNAL(newConnection()),this, SLOT(acceptConnection())); + + QMapIterator<QTcpSocket *,quint16> it(m_d->sockets2blocksize); + while (it.hasNext()) { + it.next(); + QTcpSocket * socket = it.key(); + delete socket; + } + m_d->sockets2blocksize.clear(); + + m_d->tcpserver.close(); + m_d->port=0; + listenStateMightHaveChanged(); +} + +//____________________________________________________________________ +void VP1TcpServer::acceptConnection() +{ + if (!m_d->tcpserver.hasPendingConnections()) + return; + QTcpSocket * socket = m_d->tcpserver.nextPendingConnection(); + if (m_d->sockets2blocksize.contains(socket)) { + //we are already dealing with this one, but look back here in a + //short while to se if anything else is queued. + QTimer::singleShot(100, this, SLOT(acceptConnection())); + return; + } + assert(!m_d->sockets2blocksize.contains(socket)); + m_d->sockets2blocksize.insert(socket,0); + connect(socket, SIGNAL(readyRead()),this, SLOT(readData())); + connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(handleError(QAbstractSocket::SocketError))); + connect(socket, SIGNAL(disconnected()),socket, SLOT(deleteLater())); + connect(socket, SIGNAL(destroyed(QObject*)),this,SLOT(socketDestroyed (QObject*))); + listenStateMightHaveChanged(); +} + +//____________________________________________________________________ +void VP1TcpServer::handleError(QAbstractSocket::SocketError se) +{ + if (se == QTcpSocket::RemoteHostClosedError) + return; + QTcpSocket * socket = m_d->recognisedSocket(sender()); + if (!socket) + return; + if (socket->state()!=QAbstractSocket::UnconnectedState) { + socket->disconnectFromHost(); + } + // std::cout << "VP1TcpServer::Error during connection:"<<m_d->tcpserver.errorString().toStdString()<<std::endl; + listenStateMightHaveChanged(); +} + +//____________________________________________________________________ +void VP1TcpServer::readData() +{ + QTcpSocket * socket = m_d->recognisedSocket(sender()); + if (!socket) + return; + if (socket->state()!=QAbstractSocket::ConnectedState) { + // assert(0&&"This should never happen..."); + return; + } + + QDataStream in(socket); + in.setVersion(QDataStream::Qt_4_2); + + //Make sure that we can read enough to determine the data length: + if (m_d->sockets2blocksize[socket] == 0) { + if (socket->bytesAvailable() < (int)sizeof(quint16)) + return; + in >> m_d->sockets2blocksize[socket]; + } + + //Make sure that we can read all of the data: + if (socket->bytesAvailable() < m_d->sockets2blocksize[socket]) + return; + + QString data; + in >> data; + // qDebug(QString("Got: "+data).toStdString().c_str()); + + if (m_d->sockets2blocksize.contains(socket)) { + socket->disconnectFromHost(); + } + + //Notice that we dont fire any signals unless we positively see something that we know how to handle! + if (data.startsWith("VP1ExternalRequest")) { + VP1ExternalRequest request(data); + if (request.isValid()) { + //qDebug("Got valid VP1ExternalRequest!"); + receivedExternalRequest(request); + } + } + listenStateMightHaveChanged(); +} + +//____________________________________________________________________ +QTcpSocket * VP1TcpServer::Imp::recognisedSocket(QObject*o) const +{ + QTcpSocket * socket = static_cast<QTcpSocket *>(o); + if (!socket) + return 0; + return sockets2blocksize.contains(socket) ? socket : 0; +} + +//____________________________________________________________________ +void VP1TcpServer::socketDestroyed ( QObject * obj ) +{ + QTcpSocket * socket = static_cast<QTcpSocket *>(obj); + if (!socket) + return; + if (m_d->sockets2blocksize.contains(socket)) + m_d->sockets2blocksize.remove(socket); + listenStateMightHaveChanged(); +} +//____________________________________________________________________ +void VP1TcpServer::listenStateMightHaveChanged() +{ + bool l = isListening(); + bool last = m_d->lastemit_listen == 1 ? true : false; + if (m_d->lastemit_listen==-1||(l!=last)) { + listenStateChanged(l); + } + m_d->lastemit_listen = l ? 1 : 0; +} diff --git a/graphics/VTI12/VTI12Gui/src/VP1TextBrowser.cxx b/graphics/VTI12/VTI12Gui/src/VP1TextBrowser.cxx new file mode 100644 index 000000000..d1fa3c70f --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1TextBrowser.cxx @@ -0,0 +1,39 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +#include "VTI12Gui/VP1TextBrowser.h" + +#include <QMenu> +#include <QContextMenuEvent> + +//____________________________________________________________________ +VP1TextBrowser::VP1TextBrowser(QWidget * parent) + : QTextBrowser(parent) +{ +} + +//____________________________________________________________________ +VP1TextBrowser::~VP1TextBrowser() +{ +} + +//____________________________________________________________________ +void VP1TextBrowser::contextMenuEvent(QContextMenuEvent * e) { + QMenu *menu = createStandardContextMenu(); + menu->addSeparator(); + QAction * clearAct = menu->addAction("C&lear all"); + QAction * zoominAct = menu->addAction("Zoom &in"); + QAction * zoomoutAct = menu->addAction("Zoom &out"); + + QAction * selAct = menu->exec(e->globalPos()); + delete menu; + if (selAct==clearAct) + clear(); + else if (selAct==zoominAct) + zoomIn(); + else if (selAct==zoomoutAct) + zoomOut(); + +} diff --git a/graphics/VTI12/VTI12Gui/src/VP1WebWatcher.cxx b/graphics/VTI12/VTI12Gui/src/VP1WebWatcher.cxx new file mode 100644 index 000000000..b9132b8a8 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/VP1WebWatcher.cxx @@ -0,0 +1,339 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class VP1WebWatcher // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: June 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12Gui/VP1WebWatcher.h" + +#include <QUrl> +#include <QThread> +#include <QDateTime> + +#include <iostream> + + +// TODO: replace QHttp with QNetworkManager!! See: http://stackoverflow.com/a/26182590 +// #include <QHttp> +// #include <QHttpRequestHeader> +// #include <QHttpResponseHeader> + +//Special values for result strings: +static const QString VP1WebWatcher_PREFIX = "vp1webwatcher_"; +static const QString VP1WebWatcher_Unknown = VP1WebWatcher_PREFIX+"unknown"; +static const QString VP1WebWatcher_ResultNotReady = VP1WebWatcher_PREFIX+"result_not_ready"; +static const QString VP1WebWatcher_UrlInvalid = VP1WebWatcher_PREFIX+"url_invalid"; +static const QString VP1WebWatcher_httpProblems = VP1WebWatcher_PREFIX+"http_problems"; +static const QString VP1WebWatcher_FileNotExist = VP1WebWatcher_PREFIX+"file_not_existant"; + +//____________________________________________________________________ +class VP1WebWatcher::Imp { +public: + class HttpThread : public QThread { + public: + //________________________________________ + HttpThread(const QString& url, VP1WebWatcher*ww ) + : QThread(), + m_url(url), + m_result(VP1WebWatcher_ResultNotReady), + m_httpStartTime(0), + // m_http(0), + m_watcher(ww) {} + + //________________________________________ + ~HttpThread() { /*delete m_http;*/ } + + //________________________________________ + QString result() const { return m_result; } + //For special values, see static variables. All other values will + //be the value of the "last-modified" value of the http response + //header. + + //________________________________________ + QString url() const { return m_url; } + + //________________________________________ + int httpStartTime() const { return m_httpStartTime; } + + //________________________________________ + void run() + { + // TODO: replace with QNetworkManager!! + + std::cout << "WARNING!! - VP1WebWatcher::run() needs to be ported to QNetworkManager. Returning..." << std::endl; + + // QUrl qurl(m_url); + // if (!qurl.isValid()) { + // m_result = VP1WebWatcher_UrlInvalid; + // return; + // } + // m_http = new QHttp; + // QHttpRequestHeader header("HEAD", m_url); + // header.setValue("Host", qurl.host()); + // header.setValue("User-Agent", "ATLASVP1"); + // m_http->setHost(qurl.host()); + // m_httpStartTime = QDateTime::currentDateTime().toTime_t(); + // m_http->request(header); + // connect(m_http,SIGNAL(done(bool)),m_watcher,SLOT(httpRequestDone(bool)),Qt::QueuedConnection); + // exec(); + // m_http->deleteLater(); + // m_http = 0; + } + + //________________________________________ + bool handleDone(bool /*error*/, QObject * /*sender*/) { + + // TODO: replace with QNetworkManager!! + std::cout << "WARNING!! - VP1WebWatcher::handleDone() needs to be ported to QNetworkManager. Returning..." << std::endl; + + // if (sender!=m_http) + // return false; + // if (!m_http) { + // quit(); + // return false; + // } + // if (error) { + // m_result = VP1WebWatcher_httpProblems; + // quit(); + // return true; + // } + // QHttpResponseHeader response = m_http->lastResponse(); + // if (!response.isValid()||!response.hasKey("last-modified")) { + // int sc = response.statusCode(); + // m_result = (sc==404||sc==410)? VP1WebWatcher_FileNotExist : VP1WebWatcher_httpProblems; + // quit(); + // return true; + // } + // m_result = response.value("last-modified"); + // quit(); + // return true; + return true; + + } + + // TODO: replace with QNetworkManager!! + // QHttp * http() const { + // return m_http; + // } + + private: + const QString m_url; + QString m_result; + unsigned m_httpStartTime; + // QHttp * m_http; + VP1WebWatcher* m_watcher; + }; + + //___________________________________________________________________ + Imp(VP1WebWatcher *tc,int ri) : theclass(tc), recheckInterval_ms(ri) {} + VP1WebWatcher * theclass; + const int recheckInterval_ms; + + class WatchedUrl { + public: + WatchedUrl(const QString& u) : url(u), thread(0), lastResult(VP1WebWatcher_Unknown) {} + ~WatchedUrl() { ensureEndThread(thread); } + QString url; + HttpThread* thread; + QString lastResult; + }; + QList<WatchedUrl*> watchedUrls; + + + static void ensureEndThread(HttpThread*& /*thread*/) { + + // if (!thread) + // return; + // thread->blockSignals(true); + // if (thread->http()) + // thread->http()->blockSignals(true); + // thread->quit(); + // if (!thread->wait(50)) {//Put 50 -> 0 to test the terminate fallback. + // thread->terminate(); + // thread->wait();//Ensure synchronisation (so we can safely delete) + // } + // thread->deleteLater(); + // thread=0; + } + + void startDownload(WatchedUrl* /*wu*/) { + + // ensureEndThread(wu->thread); + // wu->thread = new Imp::HttpThread(wu->url,theclass); + // wu->thread->start(); + } + +}; + + +//____________________________________________________________________ +VP1WebWatcher::VP1WebWatcher(int recheckInterval_ms, QObject * parent) + : QObject(parent), m_d(new Imp(this,recheckInterval_ms)) +{ + startTimer(recheckInterval_ms); +} + +//____________________________________________________________________ +VP1WebWatcher::VP1WebWatcher(const QStringList& urls, int recheckInterval_ms, QObject * parent) + : QObject(parent), m_d(new Imp(this,recheckInterval_ms)) +{ + addUrls(urls); + startTimer(recheckInterval_ms); +} + +//____________________________________________________________________ +VP1WebWatcher::~VP1WebWatcher() +{ + while(!m_d->watchedUrls.isEmpty()) + removeUrl(m_d->watchedUrls.front()->url); + delete m_d; +} + +//____________________________________________________________________ +void VP1WebWatcher::httpRequestDone(bool error) +{ + foreach(Imp::WatchedUrl*wu, m_d->watchedUrls) + if (wu->thread && wu->thread->handleDone(error, sender())) { + bool changed = wu->lastResult != wu->thread->result(); + wu->lastResult = wu->thread->result(); + m_d->ensureEndThread(wu->thread); + if (changed) + emit urlChanged(wu->url); + return; + } + //We could not find the thread with that http instance. We must + //assume it was terminated. +} + +//____________________________________________________________________ +bool VP1WebWatcher::isWatchingUrl(const QString&u) const +{ + foreach (Imp::WatchedUrl*wu, m_d->watchedUrls) { + if (wu->url == u) + return true; + } + return false; +} + +//____________________________________________________________________ +void VP1WebWatcher::addUrl(const QString&/*u*/) +{ + // if (isWatchingUrl(u)) + // return; + // Imp::WatchedUrl * wu = new Imp::WatchedUrl(u); + // m_d->watchedUrls << wu; + // m_d->startDownload(wu); +} + +//____________________________________________________________________ +void VP1WebWatcher::addUrls(const QStringList&/*l*/) +{ + // foreach (QString u, l) + // addUrl(u); +} + +//____________________________________________________________________ +QStringList VP1WebWatcher::urls() const +{ + QStringList l; + // foreach(Imp::WatchedUrl*wu,m_d->watchedUrls) + // l << wu->url; + return l; +} + +//____________________________________________________________________ +void VP1WebWatcher::removeUrl(const QString&/*u*/) +{ + // foreach(Imp::WatchedUrl*wu,m_d->watchedUrls) + // if (wu->url == u) { + // m_d->watchedUrls.removeAll(wu); + // delete wu; + // return; + // } +} + +//____________________________________________________________________ +void VP1WebWatcher::removeUrls(const QStringList&/*l*/) +{ + // foreach (QString u, l) + // removeUrl(u); +} + +//____________________________________________________________________ +void VP1WebWatcher::timerEvent(QTimerEvent*) +{ + // const unsigned currentTime = QDateTime::currentDateTime().toTime_t(); + // foreach(Imp::WatchedUrl*wu,m_d->watchedUrls) { + // if (!wu->thread) { + // m_d->startDownload(wu); + // } else { + // //Thread is running. Check that it didn't run for too long. + // // + // //(No matter what, we never restart running thread that have been + // //running for less than a second, or no less than twice the + // //recheckInterval!) + // if (wu->thread->httpStartTime()>0 && currentTime - wu->thread->httpStartTime() > (unsigned(m_d->recheckInterval_ms) * 1000 * 2 + 1000)) { + // m_d->ensureEndThread(wu->thread); + // m_d->startDownload(wu); + // } + // } + // } +} + +//____________________________________________________________________ +VP1WebWatcher::RESULT VP1WebWatcher::lastResult(const QString& url) +{ + foreach(Imp::WatchedUrl*wu, m_d->watchedUrls) + if (wu->url==url) { + if (wu->lastResult==VP1WebWatcher_UrlInvalid) + return INVALID_URL; + if (wu->lastResult==VP1WebWatcher_httpProblems) + return CONNECTION_PROBLEMS; + if (wu->lastResult==VP1WebWatcher_FileNotExist) + return NOT_ON_SERVER; + if (wu->lastResult==VP1WebWatcher_Unknown) + return UNKNOWN; + if (wu->lastResult==VP1WebWatcher_ResultNotReady) + return UNKNOWN; + return EXISTS; + } + return UNKNOWN; +} + +//____________________________________________________________________ +QString VP1WebWatcher::lastResultToString(const QString& url) +{ + switch (lastResult(url)) { + case UNKNOWN: return "UNKNOWN"; + case INVALID_URL: return "INVALID_URL"; + case CONNECTION_PROBLEMS: return "CONNECTION_PROBLEMS"; + case NOT_ON_SERVER: return "NOT_ON_SERVER"; + case EXISTS: return "EXISTS"; + default: + return "UNKNOWN"; + } +} + +//____________________________________________________________________ +QDateTime VP1WebWatcher::lastModTime(const QString& url) +{ + foreach(Imp::WatchedUrl*wu, m_d->watchedUrls) + if (wu->url==url) { + if (wu->lastResult.startsWith(VP1WebWatcher_PREFIX)) + return QDateTime();//invalid + QString lastmod = wu->lastResult; + lastmod = lastmod.simplified(); + lastmod.chop(4); + QDateTime dt(QDateTime::fromString(lastmod,"ddd, dd MMM yyyy hh:mm:ss")); + dt.setTimeSpec(Qt::UTC); + return dt; + } + return QDateTime();//invalid +} diff --git a/graphics/VTI12/VTI12Gui/src/icons/3D_mode_24x24.png b/graphics/VTI12/VTI12Gui/src/icons/3D_mode_24x24.png new file mode 100644 index 0000000000000000000000000000000000000000..eafdbb8687fbde43317132aa39b2fb2f39042498 GIT binary patch literal 2832 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 QmmmqaXzOf4KJRz;zY)HC<p2Nx literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/3d_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/3d_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..226d45a27a91ee805fff76041eb14d1dfc9aca59 GIT binary patch literal 1894 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 literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/3d_glasses_24x24.png b/graphics/VTI12/VTI12Gui/src/icons/3d_glasses_24x24.png new file mode 100644 index 0000000000000000000000000000000000000000..b20f95c2755f1a9c40b468d36e9b886fbe393e55 GIT binary patch literal 957 zcmV;u148_XP)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv00006VoOIv00000 z008+zyMF)x010qNS#tmY07w7;07w8v$!k6U000Sga6xAP000;O000;Ocub|H0009B zNkl<ZNXNC)Pe>F|90%~hKd5b4CTwbTD9lg`1P>lsP|!9!bnq}F5hfKuC7rfo=^>Et z(nX7e#E=f5RMgf%%!6o<&>?VB2nuVrb#?yio1K}RH@^4n;0z4Qu7864-R3Z#_kQ2^ z`w7AxDi{p<LZOgf*Y#=uC42dIuXtH!XJ<(u5U3a!7%0dK-qqFRk3=HX0DSqx4~U{z z*wWHc{$HK!25)a~uMCI7RRGF&4FlL0kH;@blJt^u{ue;nFpNjr;D-f45E>gB_X~nh zkPEE@a23F7(=>HW)4(|g08mPks;bghELNWj@95|_I669d#QpZdod5y=?gDs72pN@S z`3>iM4#2B;Jl--fG0|Y#whrLh4!9pcQ8*l~vTgf5fK~y3jjdWsrBc(0MB*`H>?VLS zy}iAqo>+!AH#eW{gvVmBE<#AmF+T_Z3;-7uMR_30@;lD?ZzmQgib5!*p8<?eN^h^M ztn|#z&K}EwR}w;Ac%ogfEGr@aAeqy$yu5ruRn@d@Z#BmlLo%5}I-Lf9G=MLXB#o`F zuipc30YJ537=JwY*wE0BPnPAMf@zw`Y@=w~cG8P)Y;0Ts&<&tpRn?EWuCF;UAdyI1 z_u#{Bw3O0mfe@nVx?YoI&Ix1etD-2soSQdgiKX5&O{}i2-g5Av45M1$oXY?zGM9)k zmReX?XpKgr=bekzWIpKN;9!NOX<&@q0nndmxMLczEbCh|8XZohQau2Ui=tSls_NRz z%*;^-v!<q|PI~cRFzB0{oIK^+ye=#59B@dM<!;NeoWjBP54^20EUPwuo3LcY(< z&DDAFP$=Z5lr{mt{QSH>E1t1%#iA${j*pMmNs@E}K%1L6A>=K9_W*hp7Z*=^hN6K| zioU+Snr(5nYHMptaxBp~03*7tM>I|2oby!x6Q*fCQB~F274GSzB-@6%u~?RM7QkiG zG@nY6v_dIe+BNQ0b8~ZXHr$D&H0Oivr2v%X4R@=pt*t0;xTlk{yy2cI_+R`VN+Zn` z7I(dj0000qdQ@0+LvL_-a%pF1bN~Q&+H=k?s4U7%&nQt?sbFMaV4-VdU}&V^>F4Yp f6s+K$o8$oivbYJ$6&hcb00000NkvXXu0mjf(|4&1 literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/back_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/back_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..895755ea218c530c2dc317c870b155b128c33bbe GIT binary patch literal 2230 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 Ef^j`Ag8%>k literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/button_cancel_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/button_cancel_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..c6464d90a6f2c00e81f1d237c7f35ab9a5a4af8c GIT binary patch literal 1468 zcmV;t1w;CYP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004XF*Lt006JZ zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU%PDw;TRCwBA z{Qv(y!$1On0Aj%AfXC(xiBHTKKJ3?Jump11fS8e7^G}L17@ihqIIv%oAq~i72Vy2< zd4K?7!e%*8a2}hg0>3;f!_HYs3=U9@jO17jG;2Svlz=@C1H;Uf{0uojVJ>8Q0Rjjm z1VENQHD~z$bxPX*f5*4}f0JeM|BfERr)hEw?m%e{QXB#G`G@<qQvd&zNB(~up!ffz zAjAJfybNVPX&#s(00M{!-RA<aX$+jk{tOI%|1b!JRWR_G8}d5yFsz;;!(dNrNWgq9 zq9(;JZw1u$>lcHti~@s_xdwwOBSYsxZiXyaNB{&76E4dc{`>~hA|XW#{AT*RPC!RY zk|OK~Y?d?p{ta=2q%?!Fp%Q~C6GP_$E{G!l0toB?plSWAstOpEgXuqi7{mgz83c`W zc%8TzR!@+??Ff99!)OsPF$O*%P6kCrhFYK&5r6;!JK**=2G1|o9(;bcxE{lD7+>5! zl|j%@gV%|ZVRfGvrXz^4oZ;7RhC7$9GrW28{p+ls45gqD00<zk0~{|ioZa(*A>_l6 zGoRlqZN;!0Oal#(^p0l`G*IJp;$T?aD}rzYDV9Hb{PF9IpA2P7|1g{f>iq~1K#ZVV zzz75&!+@#X9+cofaSjT0WXmCrg5W2cmomJ$aPRZJuMDB;%nTnSm>G7GV)=?c3}=D% zJq6-7009JZ05mBuu!B-ND8Yf^92D&6mV@~~{CLM&hF2FKd<JU&FRCWRM~>w{{1YI6 zkR1Sb1SqwG5*#SbLBWo0Im7Q?kdQdI3m8iO8Dxwt$g&)W{{sXNx&z>j0Ht<Nf&<05 zv`09G<p}<7vMmQ$1`t5l8~}F&D7AwUoRFRpuZ(jb)h!1BfB?ef0JtMSsofFi2w`mn zURiq&s#*>L00D&00dPn32r}5)voov~)s*Fxvv#DK<sbkMKum;cYmi1zRs*H>|9}4C zwHy*M{}}%N0~Zh=3tt2ATU?fd06+i{3IU=^I0zfUzkTZw!?Rc4zU=<P5ZU&JVK2~_ zAGjO<5I{_%)@p<-XZZP>K~+MSL6V=H$CZg;SrZF`9li<-Ab^;tZ8^hF5dDWiO^BC4 zlADFshJj&qBQx#_3?P7*D6t%r;O<<$g<(0^K|g*osByA0NU}159nrvq-4Or*gpmeF ztyn+_PD+%E8x-uwmV?<K`uiV-o4@`sJpIS;`3M6;Xv2SogUE>zAb?ODKu)a&O6>_O z3==?c4hnX3%Nc-{GXOKsO-68j{Cwm;&=Cv>M*sv6+yUfR4$bGUt5_JcKnV^M=b&Im zw;Tp;GC&={fN%sr0D&EFN`jGG%b!B?IRhxQgW?(#=jxznMzb83BLD&j?0~ZpjPH4* z1O(LFJjpHLK!6>T+Ch$xVqoA^|BE|&UjX8FKu5SRFlYh<5I7fn{Kru7`N;={w>Phn zTfBlx%=*6!2M+_|7?j{{;wal*0PzPPJ`U_B04aWe00KL}`8C7BJHHr8?;X6v@b=Cv za?5tGBO3lO90Ua~D41_zvHS)Q9|AUlfi2RFK;}1q0D^T)Kn~#nbsCQIG5mjJuk`<4 zsKx(V8vOqca5H>~U;#Iw&4E~khz<%!jsqCK?t2&*K3!)3R}KH40r5T{28#Cq<$*E9 zpbWATAb^m2Mqoz(I}K&Wcp3g*k>@1Ga;%Oxhs$!Hod5xZ-Z=$30@!INJIKxOIhutb zgAB{DI-;3@p&P?;AOHv;Y_%a1wA&;Cr9Tp?QVBQ$RQw8q5*#?rA?XK1{{txi2rvKz WgC|A8ZBFw50000<MNUMnLSTZPf@psL literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/button_ok_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/button_ok_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..230de530290111e50a10d55d40dd404be3d4d5b7 GIT binary patch literal 1393 zcmV-%1&;cOP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004XF*Lt006JZ zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU%14%?dRCwBA z{Qv(y!$1On0AgYoU;q$61MUET02*)y00a;VBO@c-EfrnO;K<Cx(7?pZU<VLDOe_l- z9HAjWbC<9#VsPYG!f^2GABKIOelgg6ddM&hAb=Pd7Bc*2_{p%0A&nsesOB3G|E0Rk zbAg^@WN2Uj`WP;Dg`t(9n_)9R05LKAVt54fe-uL>&?yWId_c@hHH)V*C^F0hdvPB( z3%4D^Z=e_mp8;Ck&9EKFdIJzZOh7+xW%vVRaxnxlbTZ7NiX$chEuIRrn3>_85RXt? zm{}Nu2&V`G(6e6{4l^_{OlH^!RP`K)UjhUW$N`5y4zM!>h7LDF07DxEj_3tiJP~3s zKM#MLkG&5=T5uY}k*h}-9zJ{cm0>MIIZzhl^QR!oK~WA6K%j)j%Fxg7%ht`7;V<J~ zhGRRAF)(~)*uYT7kOY+bL{ysS1X|1tj^j91c2))rBMk;)b7O`NuRk#C+q{qA)B8_f zf#F=nu%F>9Q1vrV&;#*LApQpsKoDQrGnjp6`mQQvE5*RZ%f|5b!CMUmO9pj@gA6;M zvGyN_#R3ej3?0BUw49lpSzpFfhC$m~n}JuJm*M%V=M0Bd9%A_Z`ujbGl?<f}Cm1fF zSq?T6Ab^;`3>yZSpWlDF04-(sC-#qliI<7t`~B}44CX*b9LC~^R-nbs43!N37*;T{ zGurc+^D&6~i8HV$vM_vR`ONU<<r{{Z%Wg9KdH?4g!)%5UhTA|0vHUFqC?z171rR`x zyq^QKNSxsYODqcmqdY|D@5R3i|2F@FL`N4iIvN>xfpj4d=QD6J@B<ylz+wi}!+}(U zTm-syGtj+1816C52U`A&;Q=(x-vjX<^w0zdAec^OhFXUEKm%nN+!#;{W7rJDUx1Ea zX1K+`!H^Ej&-@IwKrx`@Kt3vfsej9`hhaU#6rkk~p+0{P4Mhw95I~5OZpNSrbe}1M zJ~Y{ZuqY6N{Ctl=1Ly#21|6W4K|sDL)aieb@OdEK1dic74AX&m=`+J)Xjc1x%W@C^ z2p|?H{h#4GFgreD$Ygj8<nbe^&;VjVAZ7<*0jSt7G*h+$@ns->2ef<+&~iu?drnL) z0tg`F@}CtLyT2H`fGk}S^8QwEvC6=32bh^RgA15fK>UK(EDR7psD+IoFe3f~16UO; zc(Gwnt+5^I^V>knw=%4Q`uYVp)eu>y00a;V68j&}{|A9d(Gw$x(E%tIuL9!N;PlbY zuoG_iOQ_TS5gUL20fZU?%D^PV1k9Ae&~$*y=PSV0ePuWajI?76`=FM;BGqyb00<z| z7SS4DO#TL@-h0r5hK@mH*m7{L{>pF)ShQXO7p+gA!A`Q}AOH|R=uNVJz~J2i%<-6( zgL3mCAbt$==^3EqSAZm>fC2gZJ2{qv06+ktJK#Ss1P(ELL@G3YK?8U#I9=ak*ad93 zTm$+aVmV5=P7VMFAZ*PrR)%PxwV;wt8;BnP@gZ=!zQ?c^ShT(a7p=&p8$}%pfB?c? z=W7A8BMUGyf{Z^1#9x7#Z6C1m!L*!W01!afn&tn1emV#)NRNSoeGf4B3xJm2L#kA$ zVmSx^1Q7Oq!B=4A!vGHU9l+8JR<u5$w&frI5I~H0qDBaa#h_K_E23LRBm#f{V#FiP z3ax@b+3N>Qn(IIS5I~Fr-8%*dpaJh20t6TUk9(C7r4lQ!00000NkvXXu0mjfCrwI~ literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/camera.png b/graphics/VTI12/VTI12Gui/src/icons/camera.png new file mode 100644 index 0000000000000000000000000000000000000000..97bb20ac9810bd16f9ad9c6ca501e77d15c561ee GIT binary patch literal 1514 zcmV<G1r_><P)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004XF*Lt006JZ zHwB96000G{Nkl<Zc%1E)-)o#%8OJ~8J!gKrnIw}YaVE(oUE0F58)GT8)r!!FYjrQA zpmz(ql!9RKMth-NXhlK9#qFXf?5=pdto;j=3dX%smvPxHEon+knBruTnQ3MwlXvF* zb&eO=^D+~YOZBD?Je>DEhxa_s`99z8b6$96&+PwfV&GX`y?XU)qobo=2WCCb+bEaI z?>u?(<nB=)FE1~@bnV);-;9oqPRDUPv}TM!2!T=x07vZ40XR~cci;W}FYnyB^HWhO zl}_BaapOlLBO@nV*IkxUVvIpbNe~2Ky<UHBa&j_q90#p+5+I5q&YnH{*-Mu$P58b~ z6h#<gFvgI{WDr6SMG<ivV+`~HO*WIl5rQa=d2i)Uyz<JcpHtVbUw`xF&6{7b8*8nJ z<M`tbP0ASaVh{vqt&=saHDMUiZnr6y%j9x7ve_&`2*NO=*XtprB$LU|@Aoh$*6L}- z$H)2e2iq(?2a_p>OeXWZnwgm?S;&GQAdX|AC>ruG43l}SHJwg}e!tK0<HwnqnIW6a z4#D5;cG=$Erdq8snj0ZEHp0q-4x4_!{YNcMPLFd;#Q;VbW5R?GLLBNAekmoM=V6TD z;>C-&u1g%pJbn6<PNzc<1V|~Fn3$kgERxIRSYQ7qsdSHPm&b?^$S=>3OBwEe6ak=w z5Ex?;*pG6pHNNlD@Ao->{ygb)np&;K=H@1iMk7H>YmHKh+1Xj<=jWN5dye(>b>?P^ zIF5tS8jT>1_xYrZF|4kxvbD8^F=mJZaU3J1q}S^a$1y<=aOKLCB>2Y02D`hvOifKu ztJUasyG%_@vA4I!>gsAzrhGon)^>wJp+FSrL?uZA-ENn5yPY6mlQ71hlwxmh58wAG z7K;=L1%e=;)oKB-w6w%;-+qhRw|~KIx5pQjKhL+n^IeouRI63S$H#G9msYDq5CjMz zk_4obICf&N-u8LWwAL&vECA4Mx6xWNKR?eKw_oSSKlvHwE??*6Z~mOWf4IpHfAD=P zV;YS{vR4oUiBuB=faJ8c1P9$BF*!MzY?RC8c<|r>uit)y*$dy}ORv7h<T&i4FY||A zf06S0f8)YuF5!6|y<QKc6mcA*ltOErB&CE9LxJo#$OrpDDwRqQ85tR2YpVvp*!+1u z{Fg_n+9%4Ng6teyTboHRd-AolHIz~qW2jUr!w4J<Y)6}56h-Xq?G3G;Ir9Q1o}VYP z`xj0e|0)v`c|KVABZYjQ(=RL~NEu`BJda0@9uY-RQbqvhU<n4@A_EYHA=}&A*q$E* z0i{xjx8D98OP^@6``6cKz5gbu^>_Hzjc;)J^ckWkB9%&Ej7b8f(`izvRB}fsOR&RE zAICAaPdJXl#>NJVi;HBlS$1}I5JK?j3m2GQSYU1SKD}O#7tg&+ChJnK*BKidBb`p; z`#$x0eF#yjg8wMNARnyTL>i3-j~_p#R4O5*Ow{1IE}#6=IXus!-EPzEcFE`Sq|<2} z$Dz?^&}=sM8_~z?x26W0!a?{4<zm<G-Mh#1^fa#P;`=_WRtv{*h~t<r3=@J{<@ml& zrBWe^A{@uzpd}nQOnL|Bgb*~FO;%P`Xf~U;u8UHNFbwg1pCAZOO6^0d6rSht@ZrOx z7aYbdWeF9A;ZP^E%(n?z7eY|2R=IokE~Qe5LZN_^GTG4Ho;y1`R4NtP?KV=%p$;g7 zKuWovz{JFaT3lSD*Xtd6`lEPZ6FxW!A;@Gh96NT5d_F%E*slA&&-(g0Qc9sZozC{D zQ>RYae}O>+4tpOQ?H`Zra8}M*YqHtw&@F2Z5JeH5=h@PQ>ej7Ww`#T8uZqQDAq+!v zP>P2kaFkL8C4H2%?OeHB{zt7=`^ernCxJO&SR?;ks{l{_hw+}-GdtY=4c=S3PFs8E QhyVZp07*qoM6N<$f_dfLWdHyG literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/down_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/down_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..adb188bc10a9e8ed563d75ae55f9cdfcbea4931e GIT binary patch literal 2248 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 W*1l}3yZ3Vd0000<MNUMnLSTYb2`H%m literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/edit_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/edit_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..1d691451514079074d6c1a4b057d8c1406e5621d GIT binary patch literal 1627 zcmW+%dr(tn7XNZ@$OA4UJT&n|l2T1t=n}w+f@>}{izxDtIu&heQXak^5m-S%a+4?z z&GJyodneR!)v>J&)6P__ySX8t7(u9Y#-g?4(x6bbHGm+H<bE6Wk8^%!&dizfnDaZQ zIx~G!p#M^T06^g86lInV#S6k=`E=pQldpZi)uik!1Rx-EK^UN=P3Utn_a>z!0nkxX z=H7N;AtE;=D-D2?D*+%30L(!jjsfs@IRL+_0Z3>9KydWDsyi6~zaKX%leU*U%~@YS zjcHl2*1nI6|CCk^M#f|UfK)M@#1P~fw76&b34})#&<&l_{V+bfd|o@+`2aqMUvUDj z_5wy1^DSX@=Ipo#wGCNt&npEVqPh1I*I~bQvYn={56)?eKcYSFvoQb52|!Gc5?5sv ze>N~c7Y%7ese2s$ac~E%eQtBXq0k>7+`XKJulh#dtD3*imir&BJ`?6<AXU}bXL`lh z_P)+u&gEv|O;P$@$795QLt+=HdDy6<l2;hOGd8PSQiHW$lXtv8nEZea|D+$8-wE_u zZJvYr6sa#kyA%q!{FA5sE_WZdqImembqqU)2bH86Z~3}VW@#9oG9HmdheOcH$D7(m zaGeVG2&xp5@;fE>>|)VSXZ+D=tF5br%g49AeRWrRP|)2om~lD&Fm;XkjyYCd=J0#) zPxlx1G{4`?RqOMETRSFY+Xk13iIf5$TS|YjlO!eZqK=9jm{j1spi49>41ezKBwy^b ziz8M(6t8;suIojh?1<3FZT97ex_l-3O5@j<@jU)Yk!#?Tp%oxB(N?&>l(mL?qC%^M zaq`%hki)BRQ12uZwLx<8m*6*ADnM<#_U<TBPZ@x1e1}R{E@Z`;zwJP#Mzj?QSXB)E zA7H8dLHP4y-GmowS*k!*SbO?hr?=JUQlB+YBC}?`-(%8^i6&wK__#9BF*F{48Slgs zR<e(DE!oGI5~*dbm@+tXfvQZ$P-$e`0K<s2U)*#S^{vi6wx>L{QJ1z`ucO{KZ{5Qf zKH5f#sr;L#pwvKEqRmZozl*o@O)qS&KJKd~c!YqaaJig*istoz_vpaaZ^{4Ex?(-_ zR4sM&vjkKc7bh=8#yOcMT%u8a@&^(zuRtO<htnuWtPh%HZy7EANUk|J3POL$xYnvW z30-l&SdO<Qt&U#2Pde}jwjZ)H8{BSDE9y+r{}=CNSfTEi3@#QEt^`MP&t!&3xHdZo zNfWROa4Mk4v*Sp`5P5y#oRMdc)j>fI>&%9Th=>6Rd5BXCWHRU4;0FD_nPG0;b}z3< z4<}G2e>dBM+^(OqhOqYRUsp8(b?G_GVFiLki=OZ0Pdq?&WEzdVj@1BTi(7S+yH<rM z{-b3daD*TsNJ_&czrY9q4yYpX8(5dqNIg5kN<N<HvaoNnMypk1X5Me=67R;Eq_Zkc z+cde-X)=+^Ck)ifeib>uSoKt8`Rsn<qKrX1#>a1N1iQ||Q#@>PXg%f-tC5yzlZhJa zK8IbRPhr|}xMy~LI??vVq!7}`VecE!rTXgX*<n91k*(?eYtP4Glh<Rnl5<Z`q2US9 z)`)4F>6rEKOFL=nyytRz*_r_EMb45W>$D)7&)C>fe=P@unY5OL8C*sB@@Khcw<Nds zuY0|uJO<{k?Z{bdAc`3SH!O8{-szi*e?GvRZwvnFrD%65^b$?;jId46$8W!kQNx&9 zr4$llCd%#p9%En4$f-*k%~OxOK&1(F{+V`mC6KX+M`+z1Pwh~ajCE^DfrAe9w;rff zPM6NimsXsMi;s~ZtsCsOezF!oC~2D$U7v*t=NdE=ja(-C!|UlHU7kg^|J5_YVDhbx zC&#A*tYg1QG5h|&0VRt&1F^a?Ug3K(t{E+4C$baKfMrsYEtR?9oL^ej+T4X9nLjTx z&%&vf(T4iwMTP?0-&Sj~1RtO!W&Pam>i)4}-#d|!Zx_)9JDPkbImZt$PE&*>h0%pY zjcmP;D!Jm>OY8!@pOaB<LbJETps5ngC3I1@*)hjEygr2MV~=x<B&ueRIM&;xY&aeU z__#W>+><Mm`z(j7NuK)?vCel!)%E#XHzqzDzQE*&le0I3%K%>u1fC+={KZUx?-78_ Me@j>1_&}}yALD7)0RR91 literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/editcopy_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/editcopy_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..cfa9cb4317e27d2ee0f8a5116cfea21e3f151a43 GIT binary patch literal 3781 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 literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/event_display_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/event_display_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..b883d6946658a4d506ebe8e0696840aee5887570 GIT binary patch literal 9319 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 LsIE{cZx;MN8a2YE literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/fileclose_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/fileclose_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..8acc84d11a0411695db414ff2bc3d6dee4f2b442 GIT binary patch literal 1594 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 literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/filefind_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/filefind_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..418a8ad2c3118e92ce23c00e3a7af5d98ffc4817 GIT binary patch literal 2161 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 literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/filenew_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/filenew_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..8a303b7db293befc3120b9ebd48be3217fa9077c GIT binary patch literal 1177 zcmW+$e@s(%5dS`2d2MOCw&I{=K#NSrq(Tuka4=h-bRZRLHHHxvXh%!4ABY775!=^- zq+r93$h0m@Pz*umgu&*R(*dEHibX-@4-5_pOeTrL2uOkUy*>Ej?sCcJ?sK_(?yBS& zpD}y_d;kE9v{Z?Li2OC9AcQY0EnOf2DKBw%A^`37SnukWM9wWr$t>D;NK;g-)Tu#Y z?je<$pZ2XXPpwcZbB`Uqt4<(l!qX&)`%9jw+&C_R>4CRg^u7@G*v%s|dPUn08!oQ^ zFEjf&^kPLp7m#9%MP>M4@9U`<L*<-EA6>Tm_O$cS>KuI!@424i{Q4(xHB8{C{V5Xd z%3`h2IhW1HmUw17@pV%+JtE`rn^RACrP6g!RpW#PnN?{Jr4%{fr$PLhLA0+g94;Rl zc$lOcz7bkm^%0Ga+6%#7Y=M}J3N(n$YUOZUJGh*Zr{_3V1&-V^`EhSeoGyY=Kt?Z8 zwUHZ>1N&^0wDgN60o`;{KtFImGnpP6yqU8BKsHJK74oxty*6+d(1Zbc_X;et7&w0$ zFmG974@d8D4K%m3ghv|&FPwEbAPV1dFb8sYJ0x+yig5L~GRH-|&oFR<6HW{kIA=d? zoE_=E+R=Il1*(u(lDIW$dy-bZ(Z0(kI<?wIShk9taz6Uw0X^IJ`8;o^ut$&QbszNv z$hWmb4Rz%W4-y2OLA|6S-oC<a4xVJgpsvmK$sPk1)zP^<+P%8kWUQwe?jY+hu-jbs z&0UJj*FqoHyK`NhB_13fPwTe0m^K6EECyn*cN%E4D)-`QWdBU$I597>(s+`ZnQ9DN zsCA0w4M?lOHL^nt>R*8zr5y-P8WXWv=lqi<aT7-Nm(eYb-nwO`<sE53{cbx1Ajuh6 zychF)01Nv(Y8T?r;W!STt*m<kWhTH=7%%3(bNJMQed|EI+bav3iWL5do2JftXGY-g zW3t5}69>GYG{flc6TDE21t@$!MY(6b7%4bdUd^og$I_ehZ=}#^^m$*%5U`CuLv+TL zf?LZ=B0U+9ShNrOuvg@m#d6boxolrJt{aE9k(V3Kai^_46BSg)(u5AJN7vM*C4=;= zg6ps}_7cl$)N7YkHl%<A&@XlM+{v&?!-Q#e+~6K%@lms`w;h+?!;?FM!f<05{mo`G zvlHGQY8rvyOINTZ{{|YL!z1RL+#0Gq0!5T^>#LP4LQf1GQm~0MoO9OnkevEGwddV6 zG0DcF#oNT!DEvzJ1noM-+;`v9-N63pC5~I#RyqI*Hr@C{dL<?#1o-1jf0RVAg)|@R zvq`#*WR_SasoZImGQAP)ag;rvtax!uZbk!<st9)t!M`QxOn+I;#$Uriye{C$qd0#- zG<naD=y*A0ftTJ6O*iB6?9lk2JNN^%=SPTWSFvlS^|pPd^eCl`0rt?e!*C7awHL6& zB|)#3L~!-0^Qch8<gyrBJ=l~i&I*Xb%5PB6h(%YzdUs1Zu}Dfw*m>cXzF!0pWnqIl pZScpf->IKw-3CyF6O_UzfI+<K_;11%Q77?RKw3(M<XTdW>3{KY=uiLv literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/fileopen_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/fileopen_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..503a0045911aea0af4dfa1562ca1216941935702 GIT binary patch literal 2232 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 literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/fileprint.png b/graphics/VTI12/VTI12Gui/src/icons/fileprint.png new file mode 100644 index 0000000000000000000000000000000000000000..ba7c02dc18d3145ffc2565afd7761cf8d3bbea99 GIT binary patch literal 1456 zcmV;h1yA~kP)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv000GdNkl<ZNXL~` zdrVVz6#fb=eefKVXL+p_VIT}48SydPCV}B3PQ)!4i_sWIGMAVwX3iLwk!aZV$Nq6l zx42{z9hqciS&Yd9j069WfeK6z_rNLR{iw9Gy=`xMcg_zAI(2g=J^9^xd++z1^PTT^ zuS!uAl$Py<U-oITa|%9=dO{tMpPPJF^7xBn*(Y1fi3YFiTcHWj>b-8&)Yht(3npj! zhVZz-1RFN&M_Jjs*iyCsr1Br})rl5`9!vdS1b~`S#iy$JW0wVxgL2xnlvejVftS)` zTKUc6;s?zyOrQ~b4PSpzcWVZ4(}_)5%DYZrOq#!QQ`PI0w4^^aL2|-VFePLo-nasN z*IK{-{nt6Te1OXfI6O;fodf8H!d2_Ev=sjnEGa1o(b3Tl5_n}VWUm)KAEByLKX<fW zw$9O^gVb|)mvW9sCj3BFK_NY*eNL~7fnFbr%F0R{K71ImEH6mD6x=bMS-VmE;U@x_ z$ePc7+p+Pjk{4YvAo~L2VQxB~1th9JJp9RmF#R~v%o*@faSZPF`yU_>9faxzp;q-{ z>lTYhucS2H_>FX@YA5Z$@Dy-s3>f$m7#f)`>;2jfo|YtOx5wjoB=}+neBJL?ffbTv zfBCMO^<Sz+C0K`bh%f-=M8H5*>w=tAkqc_N@rAcvg)IH?>4}DuF+}ni$veda50xlz zt)=B6k$96%pJo?^z%^$>&$TW{BVO2LH-dO3l7yfjEpFY8fW?x5<HwKJPESwQwzak0 zB%;;y;LJk^6do`Y<~xv(kW|^+{1YO>LqQUtv$GSD+YMuEJR-uvpwVhzFlgX$`>|^E zYT=ym@o{8iWMoD}L`)w#bf|zJuiZyLz(v{F*<bD2^+uM<<%GlGfaLL_yZ1UQnOP_# z*Ral^p`nP0iJ=bWw~x(c2USnQS7Bsi1lzW4W3tZr`uey)CxXCWFnm~DU7eMYVZre5 zFf<wsbUGb!a&pk$-;enCcyWzma&i(@t5tM2J39-f(@BmBhuLgKT3Q;)%gckCnwmbJ zn3&kQNI(uS1OT`iK4uW!7nzxvXl-qU(P$KQRIAm(F;o=GB95I-7bK?}*L$wx&h0z= zd_F-LxeGxsHa4cvus~fPH8mAcQBep92@&n<^?DQ*7Lpt`K}<S>tvNb6ir(H{*zI;Y z9>eg^5T>j%h>M9sFx0ezpyPT40fGFLmzP(>a-2DHMgV4IWg#UcMF21vcf&dl5fBrz zG=bHeW<l=CTwIJi279*;KDQ8qx2RtbxZUm>$;rtmDJc;eGYPwgH7zbKMpsuC1_lPi z@L49UR*NulRBmoAmM>q9=*Va|Jr1axufdtDLX&dtewzjd2S>6L9I>&nsHv&J;NT#- zySvfQ&>$+0i;EL!GMT`|Fahh&UG(()f>RBr@KQ+y;*yQ9OE&*P2Z|sd879u3KaVwQ z)+{oor>6@bzSi8_LNaL(85t?&Fg-nqt5>fIx!k-*$N*KZR3b4kQMhl}GK-Ps6CzB* zn~Z%;>pIfBv97Kzk%t}FfNaML7cK~Cbh;26Ir0e&+$Dycl9Gyqghb@$=cA&cf|Y<@ z@gpxc&)(P9_dG$|6d*jrdnBtZDk@T1T3QxAlQa*dz5Sxn)^<hNv*(DibLVbl-@d)d zxpQY1@40m8l2Te)%H!>#{D?mf0*?u}E%yICkwE#w=FOWGvZK<`(V-kXctBaZ_E}}e zj#}mD(JPA0HV@p`*r<>h=zE7BDc_+q-}kl)5Cpb=AlNAs>*>{SgEkw#4y}~mQNCv~ zrMGY2{-#1Zm|q8tl+_CrKNyc9V3*tzn<z`L@ZnyFvW3**U*d0oCjN)8IX;m90000< KMNUMnLSTaDs<syZ literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/fileprint_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/fileprint_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..4325b61869b5b505ef01cb3b2b3a434ec2c1c83b GIT binary patch literal 1463 zcmV;o1xWgdP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004XF*Lt006JZ zHwB96000GUNkl<Zc$~FY-%A`<6#nkqySsN+XZ(fQgzVa&i4P&7U}_o~LQq5~*g_Dx zBpOMee?cClW&<J5C8d20n&ia?+olAI5P}aSkxGPap_E8S@}MTDJMOx(GduU*KBO}p zb$5+Pdf;&H&b@QK@0>gLoU;U#MH?L*{f<)FO9*i)Z6t(1DFpyfN)aig5<+}4F)=Y+ z={;6yabRE|#5wQ3a^*@Z=e+Dbr4)n^5JJFpT~JCfKR=KA_wRQDcy|H-KnN)$5($Jt zp^E!l*Y%ZBikg}lD5Z*f+24}@r4+8~mLwphgzLJ#=RpEOh`mg|9RWf}$>$z;DFWWN z@IeS@nzoBXC2-euA*J-+{on+G;N=JeZ^U~Os03b)0PyB!yiEiu?wFaGu?Zo<Be4^x zlopFcp9Fxy`w-C1pFf|}b^RkRq?J@k2`QzY6DXyK#bUi9BO}Q(XU>$3blHXB;o+}( zdV21xuCC(c%a>q``Q8P?U+xH&mzQzq(4oEq2M+W-eE6^yzz_Q(P*YQLvA@3`w{G3S z^z<||P21(Q5W@G|Bjf$fX0wRL<LKz<z~bWK#eESN8X9Ud4CB+bwl-Y9e!V0?DJ2}o z*>?7h<Dgh9`YMEgWm({ycMS~<bxuu9EtVxPI5?<t&Ohgze^Fmw-`m~Yt(Qwep7%;A z5JI478Yra*g+l(EF$N(7!r?GZoH!AdQa%_N8F^sa_D_`3U+&($y8!?M04`j(aF}!c z<H??r9jAIup}oBwT6pg(v>&l;8&97;#r*s{9zTBk_tw_dx!bpIrvU)TWb)g4Ki^Z9 zwA7=ON9xJy6D5RD|Ch|p&Z=ZGIROB4czC#>uCDI;%fpwe(`Fi@OQTp^Tg18Mb6}J~ zD!Jzs+>a7M(9qC;g@uK~EiEl~m=NN#qeqW6M~x^tWCw0+-9Vx`@#fmOdsfqZi<A<E zVc^)YW5&wLN*|+?o^5Gqfsg{4((q-=mk?6GcI*!h4*Zwe6Nv;Ok;o^ks;a85wzd|T zOa@9RFvdVBEn9})RlIEJ^$CVyAQp?YvPdKnXN<wJEEJ1H5JEr*0i_h0ruo&-yKXx@ z2?Fc{3yxlrQc8hR3Q8%W(P%xRloBBXY}?+}#drpTKpq*7h_~kL4FU$A?X=@nRYFLF zX_{8BZCejkvEUJS%>{tBZnJ_CwBx-`DTQs@AcSl(rPM+;n;odDtMdt1mQ^wu?+OmQ ziC!!g0{}3_kj-WRV3{eUW=+!^ux;B9-_@&Ev9PcJ0DgYo&qwL)C4?XniGUD-cs!1q zH*bP-4j}|g(}a{V%`{DWu)e-7^7%aV>i)*Y26DL^0HCX@3!R;vaGZ+&OSYZ8mvBte z#LUbL0O0lO*Vx+Hf~IMZQetgw4UDll_Wb$tKdP&%f6rtxJ%(XG2!VqK4`O|N9fS~! zjg6tVw-=UWl?5)<s(Fr>rim9XUZAnD5&3)`u~-b7o0~9A^RJbamEQ;ejE|2G>bgGJ z*w|?3x(;2}!5G8F#s>QP`%zU@RTkW9NP^9ZH!l{8NT<`#bsa(oWHK2zj)PaPUgb^G z{QBCpYj^yE9UB{K4~0TQob!QbG}=KajU7LJoSr^?x+J(#s$?%1oGYd9?AbFcEiFkQ zgq6?d(}hCeS0ThyDwRqD|CZyRjE|3N06ylN&s@56=}1#kQ%M3l+p|(6gb>K(a+sT& z%j9yovjEbmRLTw7*;VvYsgw+bLQSo$tw-wX>vw@Tj)QzY56iOru}~=Zqo=lQqfjV- z5Q66B=335qd?z?irX>r9!?kN`Yky8oPL|98!Au8iPgdS~a1=r)##p2j);~59o)z~? RX4n7#002ovPDHLkV1ht9vIPJD literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/filequickprint_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/filequickprint_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..9763b92b56877213b850318d11f9854f6f139991 GIT binary patch literal 2088 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 SE=tP)0000<MNUMnLSTY>cMVej literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/filesave_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/filesave_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..dd00abd1663bb5e8be36eb3c3542da8294c5c31d GIT binary patch literal 1348 zcmWlZYfw{17>4&GA&C$;K~VyP5-tK&CI+kn8I_!HiGZUMkSetb0R+cuVx$5JB;gWJ zP=i%Os}gW(nUN`Aal8z}2}DbfGN`DvmKMTQD9SAn0?9c&{Mhf?@5k=E`_8lPdGYQY zj`r^M0076>n5YDzb5<6eO4QS5&zguvIV{{I1fbCnYIk9RnBB6Xld|?mGqbW&<rzSD zNSc<xi9L~eI3pn=^-%7qu8eKOnRl^K!o-{pX;vH;=n;|<q@}SWfQgVl17a_9O?reG z@BtL(Suyi<Rb{2h*js}lj1gS)vVKY+*+O^!mhnts9`n^NXV<uKZ`E{_o%BLLZJ5Ni zbQeGI$*j7G2U~3mmxZDTW>A4;Y>msVr;{Om7Wr~}H$zci%aqBv7E~&QFZcoy{W*lH z+LmVLL-l`31#Xx%I!yNltrR9CDpf^A*HlHfuNkdXqAP6KxN)NzRp23EPj2#J;?$S| z%iGfL44~pkAd%VZ_FI?XVl{M<dxq-knM)OhbE!}P_sXyZe$$$Q76dmnY5ljZJa8X< zj?W_h#nb)%qJ#6bzm5asz$@1Y+^`t+0cr(~)fylQb3fe*b#4#y)40Ty&5=EI@DCug z%L$Zx{N-|uTbp7T$^u89keLX}du9O+q=@fwUiMTAQ}$d^(O7G@^|Sr9f{}S?4H{yl z_(z!vVUCiw+S?#c(zGK7?|6Ne%XaB+OwN}q&P_PHpBg}D+8q$#p&EoaW3&wz%}Mn) zoLpEm<@NF{Ui*y!XaYDxxGsE&c6}Kh$1&Sa#-9IRMhc1n|2Dy(eAu;$3Fw?Z4$Qz; zfY4;#+8e*9s9oi9L*3-<M0=&pGFkfesT)(;eC&B*6-BO_9$*~-gr>WIZB-acoVn## z9iQTYrl5K0i(kwhEq=vU?=d&mS_i7V2{x+Z!3(>=z{T>noeB+metvutkNWfH8Xbvo zGPn%8*u)-d9?;bz*#H5}+QY6%Zs0*wl7_|}SKzkNK2*8Rwg|PDmSO5%(O&AAOc9m4 zH?wR#iu=5E5bso(iUJySuVx%}(gB5;$p>c7K>Gs?4+rI(S*gy)eIz}`&MuyOYAVIA z8D-6F|Lt9*r}~BiAeGsDUwJ;6sVZFX;8j;TmKX^<BFbmbq|wS_apFL2DIq6yq)-qu z%Sd2!iO^>Eib-bwoP=gAiE?;KCg3~gf@~?U%-uGcCOS3j*@aEpQtMvRyPLbZx*edt zcBy2QLoEE!iLkaJihkb_h4QiCPAQeoFKEfZO4p6!yw~7CfP_D^>C%e-EyovWY%B41 z4lRDM(USC~@PH<-?5H<4yuz`gwRH-?q&eO8|3Cz^&Lpj5X>Qb`m2Wocv#&~`osN#w z3)k*w;)hk&J`6fTBdielP+T|Y)a1bTNXFxaAg^}~C3n`y*2l$kVEP$&L>#mtERkj< ztql>VN_xC<QsuKlr<?3>%$xQ}&>|KVQy%LgR{vNvMhig1?jV&)O<cM60vQ>#NSk^U zksFwts;aT)hG9dvXt&JJemT$=Q}%%dWh4wKL5D#-=(Fb5wD%F^#fz&97<{}=&+}z& z7Uq+j(<Ks0x`th0!v&PcI=~81NaA%BLqvo`oYFN;qpY^p{N9-f%SKsR>$wFd(O3BV zxL4J)FYvKkP_AxlOjh1E3Iqz0r}D!+3Y{Y|ae{d<Hhgy2RYr1Q4i<*?Ad{SG=&OqQ zJc`G`snPCGu~|EWfjE@FmPLDd+MY<Pe?uvBEksbKgn&{u&3HsAUdc%i8@)T~*9b}B E|KUhYx&QzG literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/filesaveas_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/filesaveas_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..61a080ecd0b0b51138042585fdcfb87899bf24ba GIT binary patch literal 2069 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 bQW!e)oA><zAEMsA*P)ozv8x&)1oHm@>c6@5 literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/forward_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/forward_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..6e8a04bf98f126982c54d0f859c34a5e61c80266 GIT binary patch literal 2257 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 literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/help_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/help_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..5858f03f7e766cf8bf9c8333ad75a8adf08f7750 GIT binary patch literal 1683 zcmV;E25k9>P)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004XF*Lt006JZ zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU&B}qg<RCwBA z{Qv(y!$1On0Ac|VjEsy#YdFThpa7&4{xL8(05Jo|`TrpJ0FeE_1&E0?3*>o#0Ad6a z1RQXRfk6OhcmmLpcpz;6wGeJO8hrtX7XsM}ycifh5OM%O01<Qm(DDYLVfjEq1wg^Y z2gF=J%%QK(z{SrGR`U&n4;^Co2&CTv@pp(rJ^=AVKcIem4gd%soDMh*@%4U?k3klT zf^b9x1B<se1B<UORs;WCy2S8j%NB;m%a=3UfBYEiFi?m9&2S9D5*i@80RjlC1Avwr zKrI�rDkXT^ZQx>lv72Wx?`)KYe2Oc=9B}pKsq7*cB8Q{{Q*Iz{1JNz@w!FH{(}d zAH&W0^BL{{)j~tVF%0M!bO!(g5QYPwKEDsLT#A>MLA<1dfi)liV(7DH44-b^WMGz; zXAp#nA%l0jcQbIZvomlC2tY#Q#tnwMwY3ZvZruW<50E1iBauP^WH&$nVK@L7=jTDe zE(v5y&z{Y|q^b&u=eu_qKEHp@AYNQdIC%ptWO)7@V#(*v47Upk7|sFpgQ6pvfx!^j z0RRESgeAclfP!5jCx?Ma1jqtf`uE8bhR^Tb5ob9FsHrh90HXw?mk}5}Dp^?!s@&Y5 zP%v1GmM8%N2p$3_fk6)B-)9EWS_TFToOyY0MQ<)%WDuD!0n?YKfKLAXn}GpnID@k@ z1B0+ILjKDa28PwE;oRRxjxcPRH;(}*`T^(=#Y7Mdv>PCR;2{9b=K^9tHoF%v2LpW! z!^|owsFr^OX1L9p85mx^gs1_f_-WG^et$qp=sY~Yc>4x7gB6%SH3bDh_JGS2m@<F> zLUuqrIJ@cTF))GB1Tgqum>J|lWUyxsiaZ#<dd2YJ!Ua@y92{V|KfsXsxn>Q6JkZCS zkgORGQvwh`EU@AgC}_Y75|EODxEcv?iHagPAYUB=>iGU0Ma_L+XlOe)poskdhRUC- zR~i2Q{0SEWCGML*yJkX)^alU|!~*rb0;m`T`IDK83*sZ>3gg5HNL<UwF)$oH3``Vn zP~>m_`o$m(%x=iw?|}mhzt5e+NS`3D+<@8%asWU8fgJ#<SU?V7XJKJr1SKA90GP+I zf!nOC3<^t@Ft9@NKG;LRwD2P_5vzJ`MCAnvt^)u81PcMMAU7!MpanlZZ~+)v+ACLL zSpLn?k>TG1?3JP*QpE)V009IG0f+!7n2B@%FcUIp149L?<>-kKy$*od2?78CgyMj& zz{JA!_AOEMI0LXyLa`j^;~#;6z+kz+z=TKdTeJ`W2q0J#8~_T|{{k5dEIRR7{0C$J zkQT7BLy`Lpw44!WIWqyre?vIn0EiC|K(G*a0CEwiK9~6S54Cm#TJ|5w#UL4GBtBRP z$kzmX4g=2-!4FO(009Kn;|k<}DvDQ70Y*qI1;J1;W;D$D@FAi+-?$M&9v8j`ar}iM zr~?23hy~u505+q5!DH|gn5|@(nF;ztsG@>_;o3D|i4H7&7cF971eJOOz_q`B89o9N zI?w?NVPXIQ#DbJE7l6{ijlX{dWS~tgeBd$=3j^B=|AAOUU7dmb=~KcDT3`<Q2Wby1 zfQbPF5K4Ps6R@fTIYJ%i01ZJw+$kAUv~JtRAPlTE!2sCmVX(2mn}Cl4OV^{oN(|`H z#xiJ?46+*_fG`>)>!1x1V_=;ikHZnqzJ6tpx_=*45LEJ=K8;oVRiNeDfvqV}+?Sy> zNB{ze1xq2}2n>b$C!akN_y=rWDT;|<7|07uC*b-XROP||C@moKVU`1HNvP$Zc7P+g zJU{?pZIrHrHcCP5107(aQ&(9T(_5f6LR=ig(zR<D7>*vr40d2M>?p8+f>~aUrBMnH zKscM_%Yc^ugEq^#fOUi(Frle{YC|HxwMUN_jsY95AAnW%e`vG397nSpAb<#VOcp^B zCb(n54Q!amNlP<G0HcK$=yPEqAxM)An7Tg!qvSC#xbFaS!$)8m`3Ld!#4-XM6Mz6B zs%th6scZHR5<LuP{X*pK8N6#&Mnu;PAb^N+05X^XX}rKYr!dR^Lp!HMBz8^#0*G;- dyXOD_1^^bFwd$2fhRpx~002ovPDHLkV1o6(s~-RW literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/info_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/info_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..4405fae307ae946a9321c99ef9e03a6db03e92ca GIT binary patch literal 1706 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 AumAu6 literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/kcalc_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/kcalc_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..34063167c6a89693cf2365735725739c878bbe6a GIT binary patch literal 2701 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 Hu0mjfIFSoB literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/kchart_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/kchart_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..943b8bd106bf656c833d69e45dec456f7470ff0c GIT binary patch literal 2872 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 GN&f@*jC^bW literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/kivio_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/kivio_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..9872c4ab5aa59e07a843501f9b8cb2f7031ce452 GIT binary patch literal 7700 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 Tq3_Gvx`4;7{X1W6C#U@n&7xz| literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/launch_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/launch_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..5f61bea7173e81fefb6d71d7df5c0b89ffce24b1 GIT binary patch literal 2288 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 Ang9R* literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/list_add_font.png b/graphics/VTI12/VTI12Gui/src/icons/list_add_font.png new file mode 100644 index 0000000000000000000000000000000000000000..3bc461bc35561f6107495d66f4a17f10be0c6e91 GIT binary patch literal 1433 zcmV;K1!nq*P)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004b3#c}2nYxW zd<bNS00009a7bBm000Aa000Aa0e#hi%m4rY8FWQhbW?9;ba!ELWdL_~cP?peYja~^ zaAhuUa%Y?FJQ@H11r|v}K~z|Uy;o~!n^hQo&iO7$nygLN%<fh?%5>GW)w)({7c_L@ z*s#hrHgppa#LX%AL&rdL{;4n~gTY`33gQJ3abrUfiYvMf9ISKcR&2EG+R<Io*)?n0 zT$=AYH-ETvO={bubUyI?_}=rL_j$haKIbKYQVL2b1iOM2-QC?<`h6juvuA&KaIPGR zG&l-|hldFk5JD*TTsijyKrAFT06^wYb5g*3>HU8H@|`<(em{eP+yy|)Pr`~7D~@@+ z-fdM?Ri5lMkwZ;7XT~h>`~Cjn;^G&2dU{AC5_x1kHKw#6zY`#YkflqPelj#PL@r*u zh-frgm7OER+&!4mg1q?A)YSBbrfF5@&!2~7S<p1CIy)yX6Xt`;%F0C^kEbOV4E9Y- zOu#fv)YR0}O-szjgt-_djq>vHgST$oibbQ*ccqkAwQ3byF4vmuy!&Fp`uh4cl+xYd zaCo1TvJ(JGOH1K!IF{7b)_U`;m-if4ym;}kNF)-xe*OB1NF;K@<MG4*z~OM9sHiBz zh<TcDZV7(BzZpQ&$jHds=~zigNv~200O0fa9?#sdfGw!2t1}7;3Xa5LvEu^+10CtO zuIoKg{`;j4ha=+zWDX|ObJbc{Son^Va%D6c-7q!IIq#k#CSw@oGFx(L!TR;<AE1=J zpGYK*hC-piscV*Hbt$Dl2!UZ3nKvOX56lA7G(TpHrA9|bTe8=Z$z)f$1-h>Lwr<^8 zGRdDqZGEnUKp;?02ziBb9?>-IbVWr47-LA2`g}f}5CTdmbX^C48UVinfXu<zQ#>G` zLCaVqgpfcWaFj9DYuomx>MkgyNIPFjsR<!`gphJdDWsH>0&<yz_f9|nS^NkD0=qcp z4YqA>x^Uq_>r6!&8yjma%PO}l3-NfoG9ABC7J7Ye`-?A!ll|tK)%$<jxN`e5*?VX7 zz~;@H3zbrbgb=MA9UU{01AvtB4<Q6%u^5uc<m62_G4RdvyUN}w{OGaIou@+I1vdS- zrf3!cndc>hI0&GWbG~mjasV(4quVr1Fvh?bTbqtY$KnM{aagbrjmNZ9ickBE_@AS= zxw-jCrPN*kUw3qLbZ2kMhSTZnHVgx{ZG$mZ;&!{20f3zpWR%^(?bK~dq%2q|K5g%` zTd-rt4pS-hnNo@X_-Zb405A;WrfHh6SKF|fEEL3@;bkpLU=k<B?J-y+1uzZNHg7)r zZ56y8cWUG6=2Ndd{J~2ZCJbH<8jP_+N~yI<DM%^*&QZWdLI}<nXK-NM0k|A4NL_*w zAcZ(=mO%5mZ6HcV|7brt!<U`yS5I$mzjJcWq=3##mn$xHUOEBbq4X6agnZf1(C`DL z^zgZJ=O(g=8yg$9xLmGHUaz;AF$UYR(G~83ZP-}kal@npOiO?(3sh13ITFH9EP`ZG z;tA(+<>E?_wzjs_k}%Ks*m!kcZ-0{6w%~$;aSlj;3y%7_x@($2rH}#;fPe%95DJA# zEz5E_T}}wjaa^8!>RRI3Zj+mCq5z#zJo<Dwq-z|!uMner1WvaB(~SvNAwAr-<;sU7 z{k5$>|5W8P-G2oFf$2_}C(Kv%@uuf$7P*Qo4F1j$k;7$!?~UG=nse_O<}kJLh2RQF z&cUUGgaRkiNhSqQYFuq^Z(rE|XGF#0V*-OW7?KGlI2Ez!DR*0NKd|9Q*@4>$v443< nwb>u;{i3hs>Yo2qKrZ+P2d1<Z%3rN|00000NkvXXu0mjfa9y2Z literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/list_add_font_001.png b/graphics/VTI12/VTI12Gui/src/icons/list_add_font_001.png new file mode 100644 index 0000000000000000000000000000000000000000..64fb6c78947047c689926ade713e478721f2a8f7 GIT binary patch literal 1023 zcmV<b0|5MqP)<h;3K|Lk000e1NJLTq000&M000&U1^@s6#I$TX00004b3#c}2nYxW zd<bNS00009a7bBm0007E0007E0l_d;`Tzg`8FWQhbW?9;ba!ELWdL_~cP?peYja~^ zaAhuUa%Y?FJQ@H11AIwDK~y-6os>^Z99100zwgb=&TJXjB~UbOO_Z={6aQ50#h4-? z%|-%BYPN<IJrGO}nxI~cP1*}J{yETt_RwhKQ9`2!wL~uv6H~Ghg+q}=+7fgHqzmlu zXNNcc-g_Ph<xh7h?Jt>3GT-<8{QkT*4^m2`QmJR9lz5OQnS8aVmjXapnW5qVBNQs` zr2xSB{ve&5oo}_bx1ZS0TDtKP_gt7rBqF-5_sq`D9^a`H_p1BD0##L27skiOqobpv zwL7q)c)J_(DIsn~OH0d>ob%Vm#>QY6#?kFsDJR`Wu@FLB%w#g>f*?R$UEL8v$d->6 z@AsaY*VNQ>s!%96ilSUHO;bdpQN6ytzV1%ay(=y*H#axy06v|Yn|p71dfKU}smTIB zb#?V~TkY%tE|ryYeugnNFf}!G0{~Q2y$Jw@VLV;Jva8}E<i^IvLqdqtj^mu${3fN$ zNGYLd+7oAgd-wg0!Ix+3jvGJqXM3;g_LuzQLZML4>gwwExm@mGEEYQm0F{-M79j+h zrXBhD*44uop8q;#=mvUkesS{4$&bvdiHX9V;6x&E-1q$k&+~p)6y-BTQNTHes;W^! z2oy!BU0k*-LMe3Bz|yi6V#F^8up7KJi|+1j>ihoZjIpkfk&*AVCydAA6|U>9_`a`t z1)*AQ9xipkJQvIl$eyD}r_=8UA=Zb7hj&0zKcu=?7yBT+a7~QLVM>{duK3GvDFa(~ z;ROC<!#A~}Iuc>c@l!wU04I~lLsH65IOi|zPS`)$|MvM8&OaK~!{C%dAs`NH_&!7O z*qb0yF|#ZGVtoG3ifjM;(sAdmAcT<C*49f>N_S{zD7_nOyS9G)zw2;R2j!-TkP1lR zfy0H%9Zcji_}iL?=TOv#Y8BGf*7gVpUL+tN+P3`+V+^kAUJi%DUqvF3`AzWPLxX3b z<FrXl1yVv)C>}c&g)r8jXCKCLU_mnol&}o63h(m9D5P8?l)hq`1`N{xg1b-3iQ5ey z-wrMH<Ym4L0GZG-zs6}*g>k?@wy=OjKX>#14b7Nkn)}DeSzGPv>zhlZUW@hiUYWTY zS31ZWL^?qLT}ns*T$A~~x^nqVT?K%}MJsbZ&<!%!f@MdR93P%T1=q#;c9{aez`%fg t-{2@NmRsC=eElgQ0{QLynYH|O`G2Qzz3Y`R;?n>C002ovPDHLkV1nUa=QscW literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/log_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/log_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..c491c08d541a49154364908d93242ea322642e9e GIT binary patch literal 1910 zcmWkveNdA57XH1wfFv)1eF>TZno1KEM%OGIfizRI;&!`bjnxYpeQdW{wQhbSAc<L2 z<d%|I($<u-b$97wx2@et2um<hTX##VO)WHQox;==5#RUXALl$XXXZI`&NFkKQz>1u zlI9=m4*;O0r=_g(A!jNmWM9rNDjM;@wEbzD@&TaEm<kBg)-ioW;tt7b2>>@wmQ4Kf zn<++4+Pc*M6h#7{(f}}y`|tw*2Lu3oL;+Z403c{z)wV~e0FVdMQzYvTy_9=#T$Ef| zijfLQEB>fgV&3h5kV>Yw=~0*vCE=I8WRb9l(+JO>rS8ESMR>ia_+VknnR(9v)I^w` zD@Rd!YfMkk<axE^;t6%{(}iShwAeAiwu6E=Zc^<d!2)XgqAd@$AwNbIW^-ayK(0=o zoNP9mdPCvln?%_9cnN}>y{mqR8{G?MULMB3wO_hEQNh|>H;5qg@W2Hyg)=+%#TLx} zjyDFjo<5~VWs0V^^Z7|R;*(35=L1(G&NyR|Lb3j96(A%4r<8@Z2W1fYRL3&5vzWV` z`~6~hf2sso5qfNlKG#hT_q&2gx;Wm?xY7_MIDg{oS@rooQQ|I$$e{8sK*?H*x<*ZL zu>*g?@yqg~C(vNzQgvAqdQu_xG`lKJ&-%pnEg|DTVg!1oW30k*?)Qq?Zz)~+<@s#E zAdY#gX1m>g$qbIlVA?b?`qxHn^xBI(2&5m))Mbim0}bmrj3#mdW9{?FG5WxSNGWXs z1j=>z&4a^F_G8|{*IX!*SFbEpxV?V~t=G2IGm|in%{Baat?9C{Ff_s`2DwX*p5W6N z;;hTy3UF?grg6$JQI_t)xeL9{j&G3p-~XVhAn=|I-5wU^hU9AcaBPBl_e^DFrCOtb zZ;Xw7?ne0hh7ANFqjfQOZfhmqAy!r4Fb%NmEe|a&?0vCz){+f`+um)a2+TY2)W~hH z=)bCcVz#tEPF&)g$usvCGXRD2YXFKWw!8lhsWx2-090XYiF-8c^b2))+gM{aE50+H znWgU14K0jFY?T0Kz8*HH%Ry)MT)+^=hnfQ%*XOVC$~uc@WEI_<tf;BJMc9L6{MN`a zoa5}G<-TT{5-_3HJ9=E*$EI5Aaiyiov=f#Y9u07(8vF)qJxU~qJt@yRq*JR;g-$=y zsOk@XVp??NC?-S86@^hdr!^A`LenmmpQR17clWe=CdTML>))dCl=N*jz)@wH-v8Gq z;X4rBjci1Go0%lAhF7V3qotytC4O*7^zV>3$!5J#QiqhV_X#Pl?>}{ge0<fYEERf5 zQ7xZ$e-f8FP|dSY-#DGgp!$IL5AOU3!B#HU6~ePP2<fB7BEq^b5K5JUclASWV#$xK zLS|>@&zvgrYgf%mU2nyALVX)~4SyiOr{>@;&_Fq}6C(^S6?6y%xTZfxTI;bsat*(t zll!~%MX(bnq%`-i$a;;=W_E@pqHe2}5=*Y^Ms%5cMmf%mo#PvYZ!0J9y7Rw=G@%1| z3dL;l!8Kv1KT!)7(?EWZVBj1x{$3YLbyG8)v?p7KWDoL@Y-5A0;@?VfoF8nBPTl!X z-c$g@;L;Jm`=w<3OL_0ByPwgO0s)qT%5ot2(W{L{zKxJR_l6@a0Bm22)(POt$Dx7Z zs0~;0s!6pj{T$UG#dju>wh5GEY@eVVE88cYtV0|)cbru>8^0y=dd6YHNA9cu8^now zSC5;sU8kV+M6WDm?p0i82oRG2bfgzZWfscnN1S7%tT2@z-k-_knu&{#kTwSh7A;?1 z#@fuA+@VF|L54t`J?*<_1C}#0#b-=q*_$|i^ae*i`d*Iq6IVcsGbCL!X7ikE^Yl}2 z3=MRUgQA5nH9BqKVyLXeADzUhD-XkjDe3}>RjIbvZ6n9knsJe-Y@FV9@rH4bcqYd$ zwN+_inieU%B)-AGDoyUN-{}rCH$@|R`@Fcl#kKFv@<R#8%!eW+Ml1~8!xMv>X#T8* zMCFJ#M#HcMYs0yz<g7dD0uw~lytvjVOu_$?x|<7T^vw^@#$*m6cw`9c&99h6zj14` z8RnbJ_V+L7re)Iqxjmy_X+0iKjc`XRQX88?hQ&a31(M#22@ikR6T|?H_sT%pzno-N z``t{PgGoCpGJaw69_02WlB-1`mH{`FQK?aJai%V|s5E!yo;@W?4|@s{j9Nd=7N5}n z@D~rYH9vVG4geqgB9}?4vGEyi^QB#1KK+@XefjcbO~=*M@TOAg)i93Av<xhjRl(vS zN#s0Rpb=FLy(J~DT1B<xg&0RdbAR-;>wugD1J-Ef!~TD7{9$Ws!NG$Mz~;Tj_b#OX zpUuK2054clJvKUOdFu^`J1`~tV4n2jwdy`&e0^f!B3qumZQr|fREAh*bhp^;_r7gt zXrMVD<-E#b!^%>x+v4_)4{wy#cR#M#00>6|UrJ|^W;5=a59K_5HXJbxJe3n`Nf{sL e(;_#h01Tkthi>;Yc=CKd5~QzKlk)v?wCw*IPdnBC literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/network_64x64.png b/graphics/VTI12/VTI12Gui/src/icons/network_64x64.png new file mode 100644 index 0000000000000000000000000000000000000000..c17168af0409627d8439c03f9401fdac025231ca GIT binary patch literal 6272 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 literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/network_disconnect_64x64.png b/graphics/VTI12/VTI12Gui/src/icons/network_disconnect_64x64.png new file mode 100644 index 0000000000000000000000000000000000000000..a7dabdb90b0984d3e07226910285e4753a5d031c GIT binary patch literal 7354 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 literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/no3D_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/no3D_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..62beec408a1fed0b1746ec0034b41e8dc31f5e45 GIT binary patch literal 1530 zcmV<W1qJ$vP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004XF*Lt006JZ zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU%j7da6RCwBA z{Qv(y!$1On0AgYoU;q$6EYvW>ON}vJU5r8X&tFVAHdc@=oD2-i>_7%2v>6#08UFnI z#<1r6uT=m6L=^|5m@{MqIWkx<{J<jl4~QL_85nd@7#MzkfrznkFfi=MWjLL%{1HF^ zQN;n@|1f-J_zh(I!6FF~|H}p>c!7=qh5#cdAUGL*{b6PJ^N-;-Kmf5&Ei(VZLl_hM z1qRKpPe8|fW&pe3|8Iu>e}93c00M}G=BW(i<G;XQ`27tSLf@fDADCGFLlO)?0I|>| zss95y;Li^T20P$C!~sCZ0R#~J8~}<25C+)_N-O^$Apj6SB$We<l9o=4+~UgQg#a`P z!1yaL1RyCEAb^N=03(}#q((r~LQb8CT9O?AN^o$?p$>tD06+i{<p5y8!6fBYJ=5I9 zRpzHwZa5>4lr?D~0Cd3buc)B_4FP}vA}$0Z90OA_vVGZr(f3b4g@eH$w;t#yHsV77 zEeb%6`TGZ)8~_4{i5TDWm?aciX>l>!egPHKigjV&Q?MZ^8-f$zPefvbW<!7gA{+t| zF2S}Q!PeZ&3=Fs4K*fY)7#R$*DuIq;C9aVAjg$tyL$V{(0RRDn*8z+y9DGcc#Z6vD z+zb~UGcdgP2=x)DeAi8NVGuJ8BRUa+3nC!?4UGb58UP3&{2`zmnWts#uA#`!z_9N& zBrSm*0Mg4Nz`$TySq%&XVW5M46HbIs%i*~Ik_G?*2&V%WxuujD%t{JvRT&vR0@dFG z`JN40cCtXreRV%g1_j?-hQADd31`D^ko^A#8WR5?Apj6SxI;iAwpdhCTS!TWf#DfY z-*b@fxqz4xib2&oFE9xhBxN&ja;q}@CngvCK$Hd0Gyo7lSc_stURf1}&|Q%l(m*ya z@x2172L%AwVkV@T50n-p)I=Cq6+{^RUL}wSfjQvcPpC##ctHdZK-lX7gS2`!bxi?v zQJ}>@bq_(cDH}8j7?BzpAj}06WaeeS9|FH1!4C=vki!4J;AsFLfG`}uC~oM$5Wg!@ zUIZA*Kp%eqI^Zc#-+xe$Go!V1K$sn9;NSna%K)$qAPc`jECn@!|1-nW06+ktIDnCf zm6aiAK`W!QD6_mE(D%@weg(3K1FD)4Dfs_E)4~rlOPL^{40bSx&jt*7=5LVZ(SN7{ zCP)+j1Q2QnD0{>*7>8I10TUYs(D(2ELhO16(!-4w0)L?x<N#RIGD9tfVVHy2e?c6; z^as)`11V&KL;*km!5zTJ%*MtLvp$c3mz_Zv=zwpG2s^$qLk(v}YJR~a+0cB=f#v{^ zILI<qVCw%1YJ~iU2(m#MBme<~2muw31O{zqeO90)96&=p{DW8s3f-S<P=lC}qTmk{ z!-AR}>KGUea{yTGH^c$Vf1wRmpdsv#5C8}uumc#``9v9#c2qNPaWL=z4fqbK_5MNZ z0yU)nAsYw_f!|OJ^DWGB4k#OjK@MO8MghxLh@l{l`~#ZI0dW9806~m2POV^2vyuac z4p8L%KS*L_gatn<)Nojk{)HrLNU$?AFtIZt3MURMA;Ag^M<!;71Ac?zmXU#(^AAXf z5g>qA7zI^~7~<FGfU*h5{ttf`f%OC^h(HB3BLf#JBZD-M&Bq2}1I+}A{RTSV3$S7N z0qB6Y>^~TOG5%xt17!aNI*^eQf|)?2COZo-ZGn14+z{6Q>xBQHs`$@uhF{-)1FL!l zMt}ffWZ)FlV&Idu0NVPWfdyy^Gti~X2%4FRiGdY}S%4NZ19dO~!v&lKfI;;8|38Lb zKfW`l{=CT`%=`r$vdln7GO<8B%)|_`ff-SH0rmU?7Qz34IRR8AU46)K3?P6Q2fB9* g5I_UoI|c|a024XZOLd8vIRF3v07*qoM6N<$f`Lq6SO5S3 literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/package_settings_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/package_settings_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..9c2e38401ddc2f77f6d9e355de362b206107391b GIT binary patch literal 1789 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 literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/redo_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/redo_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..8a065ddae632b026c5d6c8876e0bc34a7eaf2c5c GIT binary patch literal 1236 zcmV;_1S|WAP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004XF*Lt006JZ zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU$W=TXrRCwBA z{Qv(y!$1On0AgYoU;q$61MUET02*)y00hv0I{+Yn2HXJv0mMj1fzTQT0jB>9fy|5y z0ZdE`_KZvn{OD@_{b9KL=O@FFUk@23f2v}*4HWtd#6)E;fB?enfQ3Md85s&$m>BXI z7#aAzWW5-41$7y0#T`(TJ^b>3;mE5)4BH-WWBB;%Bg5aX3@iU0Whe&fe*tv}UH}k4 z*c~vNA&`NIVLlH#4}YX~BtxJ|AcG8#3_;&4xVC^{*7;csU%q{L%5aMzmZ68?C{Xw} zzR&;&AWR2LXIKEVJl;sbh#}7*kAa7chom@t`Q;@;=gv-sN3S1!X1K@@!Z3s35K#Ch zE=K?a5W)eI7zBVpeE^8{1DyjI)TGoHZr;Di@Z;wXhPzMif|UsJ2{H)r3Na{1D=^4O z%i(my_n+SxW^I_o@bdY~=M1YDoEeTYfDHJBO)WqGAso=luz{76)n8ppo#Ex<mkh7p zyoQK>X1L7ohv5s*4=)&a7?c^<7{o!CkB^VR*xZ;wL0bW<BR+ll#IR}UCWhZne=lQb zWhej&y~CC!00Ic&fDVQU44}jY18*4iFgygt-%4PJK!WclQd}}KcrxfR7&1fw!_1Rc zl$Sv}Qk#L9of*Rs4~{)xczX0H1H*g<GluI7*MLG_(bWJ15F<k)gCo$$eUPwYxWKRl z7#0^9?gM!r!Tx7p_y!HWe^3X2$_^GF=3?+=FlR7jSimO9#={rG$H2&enxy{z_{;FF z7wGXPKo8DfXa@?tMGpml0Ac|e+YdJS6~kO$0$dDaeE^36FchIa{{yugJ>)(!Y-ZTS zz`+pq>(8&1Zx+1aWk^L+#R|kq;J`NplDtqeQ5*meKrBGN2{Jrqr~#(^Jy6SE0r3~8 z#n`h?8G{4R7$%^z7=fY2$nc(F9#C~Y!zrMg9-3M~AZBCGXYd2+5d)gd3)BHG!5BUO z1Q5t4pnN6@_2oNgJpIF&#EXGZ#srNrbf5~v!DwQSfOr}1Yzq)TjL`UGgIf9vujR1% zBb#9fFnA*wyns9%GAe*=Kzs%4xHf<QVuo7y8*h-KgVVsc*J98B=59>}Zcv2*)lCfE z0>qbq_zp1bZD!aE5J1diR$_k{&NJ);IzgS`9*~4N;x7RV^7&;Tz6-Q`C&M}*>p4IG zk?Vl};8457umc$H#5rO+)be{k%lASo2bJ6a0mMu}RSt2)6`&(jfR4BibOaYrL;y>$ z?*!tjpppq_`9Xx`pfUy^fGBYQ!V%Y?A@K;w5ip;F^2-fyg6n5EjA}V3{Q(3Jr4B$i z;yTa~YCuOk0Xl*cD8dKCpnC8&Zp%TM0Ro5`4#0H8GoT|tRz1dVIS2p*5Va9Axa<pN zSkDj*bd(*iUSVLc0b*rnfrrrs1qdKU8aV<K0b)SR39Zy#<MKH`05Q@qBsie-FMK5| yKmaigbl(slfCju@01!X}?f`%Q8gK^y1Q-Bp!C>YW?&hTc0000<MNUMnLSTYiX8tAs literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/rotateleft.png b/graphics/VTI12/VTI12Gui/src/icons/rotateleft.png new file mode 100644 index 0000000000000000000000000000000000000000..8cfa931986b270eee022af8f2855226638008a35 GIT binary patch literal 1754 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 literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/rotateright.png b/graphics/VTI12/VTI12Gui/src/icons/rotateright.png new file mode 100644 index 0000000000000000000000000000000000000000..ec5e8664a13d6681b51f9e58dfbd876b3633d5de GIT binary patch literal 1732 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 a8UFw|)e>7p%to*P0000<MNUMnLSTYzqd2Vq literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/undo_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/undo_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..0cbd408ba50b973c21e370a0475f74dd4a206623 GIT binary patch literal 1178 zcmV;L1ZDe)P)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004XF*Lt006JZ zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU$EJ;K`RCwBA z{Qv(y!$1On0AgYoU;q$61MUET02*)y00hv0I{+Yn2HXJv0Yngqu3<=&+Q9H%Y$d}I zAeS46nW<?$Kmg$l0j7lvi64J5%v0yFX87=jA(~|x!(yN?A2l5T5J0%mY=%UJc?|!3 z4*UGS1cVK@8~%g%3=<gE17!uN<p_WP!fwbkpyiAV^XydZ7}D+18Qub+n2;EQFt;$n znWtwo80;9-8Fn-50IK{A#1xfe00D&QfQb;x4b%-7{2l$lmct;wFh2tyHy^`|CpR=0 zY=Dl~OSvNe0tnRsJrK(kH53^vT`U>iVSyYX91L7MTnvvNJ=S2b0y^RVWsU#{AVxT= z9cVc-!#rUfVFnFP4T2h<UwO`OZ~Hw4hR+Ne7@8T9fI^>u_%Epr00<z60~#Tgv+A=l z2>1vPt@-PvuMFQde`8?y0(3+Nd5!=GAV!8-pyf=!^sNu%`H>NZ7lC*a$TdJm^pNfd zfB<4-sKOI>F+ePbCbkBMZ{bjXlOdjAEjXKgAvR3_1P}|u3kGY3_Y5jPAMgRSAQGh> zLkq)g1|9}+G#v^+d=-=k7?v?SV>k~Cy+6Q&`yXuKZiWj$niU$g_#IFT4*7b300Jpw zgO+X_D2Xx)=vQq9GloDcnil}^3!sxvGh{LxXE*`m{e)Wh3mOGK@H!w5nCh4q>VOe- z4IqF(KK=(a;2SjPAXt|{nBfD1GdOL4z#k;63dHw-4(DZXW#DJn&u||Y_zVmmp=RLD zl4%Tz4CcVJ@*fygAX~37)B^+%EXe;u9fH7Oz?kM`C;`h#LX*{Bq~ry1#C@P6*cqaL zA*ITo#PFEm1~5_}`cXkLFdU5;DnVroP*wq~;w><Qw=%2;2p~qhg;X@KQ04);I~p2E z*uXU)J^>B*e+*B6UU>+lF9LOgk}p3nsBIzDDiF&+)xT#r#;}T^8kCX%0*DcBLa}6! z0tVVCU}#7)1VK{^F7OnJK@Ry06_bYQQHILx0jH9Cz#_aD7y@@dq5uKJNU*4O239@d z3>$$y;AL<FitvzFPJoi-L2z_|9JhyIGqA{FV0Z&{(g%P5VkE){HlPz6fMKzKffJY- z41gk<MCbw~<-5=z{{hS~_Zj+tQ3VQv*FgLVnrQz31P~*U#Wg#yq)-Irj7|nF248Tn z%0T0l8%_0Va2zuLQv)bXd<E8D8yU_3WBe^RfxZDJKTx>|P0j!T#7IJ&!3s`P+Q5t{ z&kzZW3VWc4GKNZ!rQaDY11&xZEU*p$tpoY?1Jqfcp^*a5DF6Y)NMekFvMnbxCGbK0 z&yLo#`wuNGejt@AU!i3UMjZhVK#XKmKa5a^utL)~GZu6HK^^f6S}^^?Wf(vJF%ER! s5FmgCyk7tiKm+aofB+hB2LJ>Z0O33%qw0R97ytkO07*qoM6N<$f-3UAfB*mh literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/window_fullscreen_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/window_fullscreen_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..5c9864f587752da1b3dc7b2724858eed82f302ac GIT binary patch literal 1198 zcmV;f1X25mP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004XF*Lt006JZ zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU$KuJVFRCwBA z{Qv(y!$1On0Ad6Y7Ly(t{{Qz^@bAwbO#lA=W%&2^AH%;tAPi+A^Fj1K2>ll<|DWMM zNbK)l6g_{z{QqEausmGN?+^dZr=JH}`wxi!0|XGG#pFkcj7-e)METi(1_Cwy{tuy{ z_|I<`8z>HB{{gFkih=q6;cOK3Ky&`UE&j*w{~wV4{fFV-&sPlpf4<6RxKcO==zt#p z0mK5b+*D0~K}ML1;rDL_F#h!m75_wL|3srf;y)pLI2%a+28J!r4GjN4Vay5*Z=fR> zzn@_E&-Q;JkhcklUjPIU6G$9x`5%Y_{s3uUNW$@7Bn&iz0q7wx4aQKhfB#YG{~(N> zyqK6682^jFcpwG`Kmf6TSRkK(ECo3Lng06+)pEEa{z4pq;-J5n4kD1g*?^cCAb`LQ zu$Dyf0nE_92!sFP!RR6M2j+NS;so(wxeP-6XZZPsi=k^7!W94k!~zs!aFC;3wgOrB zAMBa`Q1*W)8zT4VBPWUj00M{wxg7YS%*nvO#lpbI$Hu@Y$jQL9<q1WW|Bh5;`2Xe$ z!~YLI7#KePW?;PZ0W60M00M{!r6A&E1zOC(z$nB`vE?Alyz~~(JT9Pz*ufrygvLJ< zeE<Q(^dHGZi~>N*g}E6RMEMzhl-g2cIXKAcT^JYyc^Me_Il-X{$vLPF00<x^<fO_d z!o$F|{s9A%m@osQm>9#a`B`LJ&bYD==ow)KCSd`Ff6H%yqZF1NkO4pdp+o`KntNcH zqvHSrqqr0UTjDhGd=4c3g!BSEB+l@semB_Xzn9*|8U+9Wgc1cPnKW)PQI;btM(|+{ z`W4!bp$3#akpVyeF_BXn{{PQ_VHsgQEVNKV03d*Hh5&xc|C4Ar13aqG9RLtOB!vKG zkpCw+B+wHfKmai@5E%mKmLr#Lq=W=|2mk~SQ6YfOa*{*hFRB9o0*LAVKT<8nmJUdB z3^D)+Ae<opDul3GPP}9IwpC&}2F)IT077xVHy;@=4JwBJzj?{<dvPuS%W+2w@1`<_ z|1Y00@b&qE<@j?Av9=EY0th7={(t|S;hV1<!@sv582-O~%fK8x5o>`%Oh|n2?qvA? z>J`JkS8o~kv-BagB3Kcs0{{XDr7rmY=@-NQkKY*>-hXCbZQX~XZYMq@J``_ZV0irz z=$WtJDj8c800a<fLG<kp&=Eg@A@PmjXSfQ^a-P^|;7ieF`2P-Q`Fluv;2)MO4-h~o z4HB-~-_VN9|9JU?vgZ4lS1{z!69Pa0v4BG0^XG5i0s>Z4{)f^K{(lrXtZM!vi9;=c zTZ0_!pjHy7!H5I^0tg%eCQY~C9SBg*<}Z3r2f4?C++#wMLoZ~A0RRC6>NfBJu`Cet z)45yt5r`iH1Q4v>!im&>p%(ylff&961Q6pu_l^Mqh>2l<0YHEO0Ln<K&d%<>fB*mh M07*qoM6N<$f@`P}3;+NC literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/window_list_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/window_list_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..f8d64d1dfdf542f311a5c6a278cff4e82ddabc91 GIT binary patch literal 2105 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 Z0BM60e`H%%hkne1AphNd*SGP+{{cB>lHLFS literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/window_nofullscreen_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/window_nofullscreen_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..bff406c34922b896fb0086da884225e6eef9ccd3 GIT binary patch literal 1202 zcmV;j1Wo&iP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800004XF*Lt006JZ zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU$L`g(JRCwBA z{Qv(y!$1On0Ad6Y7Ly(t{{Qz^@bAwbO#lA=W%&2^AH%;tAPi+A^Fj1K2>ll<|DWMM zNbK)l6g_{z{QqEausmGN?+^dZr=JH}`wxi!0|XGG#pFkcj7-e)METi(1_Cwy{tuy{ z_|I<`8z>HB{{gFkih=q6;cOK3Ky&`UE&j*w{~wV4{fFV-&sPlpf4<6RxKcO==zt#p z0mK5b+*D0~K}ML1;rDL_F#h!m75_wL|3srf;y)pLI2%a+28J!r4GjN4Vay5*Z=fR> zzn@_E&-Q;JkhcklUjPIU6G$9x`5%Y_{s3uUNW$@7Bn&iz0q7wx4aQKhfB#YG{~(N> zyqK6682^jFcpwG`Kmf6TSRkK(ECo3Lng06+)pEEa{z4pq;-J5n4kD1g*?^cCAb`LQ zu$Dyf0nE_92!sFP!RR6M2j+NS;so(wxeP-6XZZPsi=k^7!W94k!~zs!aFC;3wgOrB zAMBa`Q1*W)8zT4VBPWUj00M{!y&U+pD3_|1gZNC#^HCgw3;+TM#R0$OXEFSL`HbO5 zg#(!XEkucI%YO&TLwsH1$ngKoO9qxT#ZU+QL(vBiKurIUT*Q_*jp6^RR}BANy=C|o zr~uUXg?yjC|IY9i=z)K4KQR1%`<CHXP&YK^pgI5`fLPFzDo6KWhHt)d4F5lVXZZi= zC)vUN{}V84F$1$53lqbiNv9!M6H62T1Q13V_~s+S@c-Rcpbvg9Fns<^p5-9o+aIt8 z{=fgmz?7hclm<{k03d)^{-e2wYs(Xof*oNof)8>K<E0M}$H8*}1cS0CG5`o5CUR=S z|Nj|KEJL>(J0BKWs38ClKuqW%K%C|ONwk~+9#!ZL00<zGLI5+!|C1aN=!p;@fS4GF z3;}e@kxMsHLIOPm00M}p5Wr_S$szF<)d2tj#Pt6ksg`3)2c$U$82|(j3r0BrEWJP_ z;QtSha)9ghH#EzMa}1j)u)61BVPNEAV_+2IWcWDyDnuQc2LS>IBMP|I+yiRh0%~Lj z8-U+(+|k0o%L+7ygMm?q8(}$?*aiq7jBE(5hy-~V82LHDuE$p35EBxN0zk`!xfvKl z`56TJd=Mohnj-)LhzZ$QpsJWrSeSuHSb%|j!vk>8Vb<-$g#@Dr55uSF7a5qugc%sc z#27?(Rbh<+fB-_R4dW&QHHtH^b{qsNW?lafYdKF$G<=$J9?XB6yMcjGT#DhPOAAIB z00IC3gpvk83Yg=j;H+fuI|g@dc<I;(mq$+s009K9j6Q$<1}-3AMdg1e4dMSsk;AIy zKax1q61X+U(GF^;fEtWQ03d+C+0dlv7Q6!i>e>87@97}-c#wNcXmaR<3^4#8fI!^_ zJ|LC_VtzVz3qJz!V}JmH^;<ZR`Y-eXpw`ZJfB<3~=-x3v05LHPFaQWJ0MgZ-sB1SB QX8-^I07*qoM6N<$g8m>1y8r+H literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/yast_route_32x32.png b/graphics/VTI12/VTI12Gui/src/icons/yast_route_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..e0f8730639d8481713a747ce21012455ef1dc1d6 GIT binary patch literal 1744 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 literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/zoomin.png b/graphics/VTI12/VTI12Gui/src/icons/zoomin.png new file mode 100644 index 0000000000000000000000000000000000000000..8b0daeea4801323d5ca253f7ee4d9215e60903ce GIT binary patch literal 1622 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 U)bUA|oB#j-07*qoM6N<$f<#*pbpQYW literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/icons/zoomout.png b/graphics/VTI12/VTI12Gui/src/icons/zoomout.png new file mode 100644 index 0000000000000000000000000000000000000000..1575dd24f6da8f5db31756a07b3baf6a8329001d GIT binary patch literal 1601 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 literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/images/ATLAS-Logo-New_1000pixels.png b/graphics/VTI12/VTI12Gui/src/images/ATLAS-Logo-New_1000pixels.png new file mode 100644 index 0000000000000000000000000000000000000000..1aceea38cd0387d38bed094000970b615671b282 GIT binary patch literal 25753 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 literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/images/ATLAS-Logo-New_1200pixels.png b/graphics/VTI12/VTI12Gui/src/images/ATLAS-Logo-New_1200pixels.png new file mode 100644 index 0000000000000000000000000000000000000000..a77a726961e0bb439f9a21c5536fef3114dffb80 GIT binary patch literal 32861 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 B^Y8!w literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/images/ATLAS-Logo-New_300pixels.png b/graphics/VTI12/VTI12Gui/src/images/ATLAS-Logo-New_300pixels.png new file mode 100644 index 0000000000000000000000000000000000000000..04f5d2fe22cd907316457b671645c22a133f1537 GIT binary patch literal 11082 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 QI{*Lx07*qoM6N<$f>ZQBIRF3v literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/images/ATLAS-Logo-New_450pixels.png b/graphics/VTI12/VTI12Gui/src/images/ATLAS-Logo-New_450pixels.png new file mode 100644 index 0000000000000000000000000000000000000000..cfc0d720097fd1f98eaa06386ffff086794082cb GIT binary patch literal 17097 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 V-g0up*k}L%002ovPDHLkV1mBaSO)+A literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/images/ATLAS-Logo-New_600pixels.png b/graphics/VTI12/VTI12Gui/src/images/ATLAS-Logo-New_600pixels.png new file mode 100644 index 0000000000000000000000000000000000000000..7fe94ad5277d9ef52545f8820c62d4e03b726100 GIT binary patch literal 23520 zcmYIv1yCDYuyvt0#odd$yB9C+?jE4H7BB8@#a)9t6n75}!KJvn^XT{9{QpcQ$t07# zdw0*--Mf1euB0G^gn*Cm>C-19>F?qypFTlqeY}5!gZX%VZk6r)c)@d#&~j0=w{USc zb~67YVrFk*{#Dx6*wS3Z+}P}=<A}Myr%$>8(&8d&9^jKK=oZ5HW&bV$2}mevfCG)r zD!fANrV{WQtwaPSjd0a~{t6ki4DH!j5B$eNA%K!1E-q-*Z#}zy!s0A*d3l+)p1pnJ zSzurKEGCDSeLq8ypO2rv2<ecxfj59l5rho~4iL%U2ROsnrsPhbHgt*{pDy`|gCt>2 zk8_a_!6hQkG=TGEzfiC%ri3!4gq0W{_*=JVS~@)-651B;nHf@DnEw0i<b{^Y9*W2_ z7k~uT_B+S`9$X>fr5Vih?<dL-72{u(D)Ad2M0A%C)Ks}Hy$^P)D|2tPK*Wvj@5-UM z`7{yvrT*$m$8g|$krf&M0j%v~uDt$*^BV;q7V4CX-lfb<_MarRZaSz3Ia{m-+rTDK zkY~~j-^ETFH(*i6_}G#tJ>s7nNR8}G)kY1_-4}3(NJjC%*$BVLvpc8?duOQV<7=7- z1g-T0jE2*|CVNl{(=e}mL!~J9N}Z7l$PNh%E#hSmTK>Q4BvXn%o!UWHyz!EF$$>iI zz@cokuf6*w`A|~Yq+zZX5C!Cpg*k!%L|EIhTt?Eto=!AB7AT(a&=ROqTB5rDQ-=I& z(u)uvG-5<somp5L0`Qc3E7vmNF5<-tP>h(y?=Xi3HV7%N0lR~18a+V^U%&|>8FT}k zEz0*$r~SD|3wag)l%_M9cU3USTtK7120E{VYp{rZ61nF57Deuz3Az#ionaJEnzY*s z8gBeC@gC-C++S>-JoSSIyNd8jMp?-Jvm7Q?jfplFz*48DfEdK4kJZpVK!GlC-S`J< zLGL(`c<U)wkf6a)zHNQEzc6J<IVz;Wl4vES$wy+=Tj&3_g5zK$%m;vlsnqPX<#Ckz zxetBn#%hJH&=??t324rS0~d+3tI7@Dl3iBhp5ixT^_%@xL|EQNfddEfWn%q90yGf8 z2KLm1HD*g1*AlwCzCY~-1erxn)eCBTV-(@n9NlUUnp(0CY%&C4mx(R?p#X%2Q!%K2 zsGrn?T~iDPh8N-gE@xMvV+7N#7d42mK|byW_!E<Qpr^Gnu$#yy7L`)+L(UkwvMX#v zB?l@(K9S@{9J1|yxFudochTcukJaAF^Xj#g)PaE9Ab$Z8qkxx@w-AtUgtXdI)mj2- zMcT;#T}`61)bLHDG@n$rSY2-_{^5ZJZ}tlkHd?@Y+*83m-B+V6MNZp(HUye?L(rLh zj~Ayt2pJiiGw=YM4;UU^3%E;0cK&Z!eF((Fb!id))xORyc(9`h;nGm!gP`vBsHtU1 z_ytPn0b~&`h0wNtOEhHr2jihQFKWOqbkGA9!yFB$G5Gen|5B{)-WI2+!B#g-cdTg3 zMTBTu149STQB0gHY5%!qh758+Po$j`Ku?JZ6&BD=bHmSD85URZmpNqlVl<Zst-;vV z>HR>LjD=geh6(R-3Pf7{Z%1#Jr@IPvC7~E_n#|C)$#D+B(wEgD?F`!jm-P4qj*L8w zU1VoTNR@*nCTzVs8R`|8Q-^d$|CW?_gl0H8-}+%tu{t3<KmqI1am1Yvo$&j0IP6xs z!=Gg4$pk$#q^H57(w4n(#D^k1!P`X42IwA!E8K`o^z={ZZ4^T)(FWyaYE*}dF|gnb z!St^O#8;{te$EFL(rj&?H<Jc+YS>D@{x{*eXOcOp`^4TEZfM)T_{VuzFM-H@|BOo; z>)+UbJE6|Ff9yVxhTK*CWGhLZR*A2ZTF1rXy0Nu{vpglu(^l;=KN|0l#3oSEI3ifY zd=_=kM?)I<qLcN6`_BwAO=h-adgBUb^%Pq74RBjWF>pPbJGqqv<a*(2Q*R==igIi- z)-<_t(V__aiYqYpNu5igQOr7oUQnlyK2ZO-Md?*HXM{F==TA|Q6AB6{wh{l{qC?q0 ze2Bw^0)BSQlrp5}Il-(wF=q`|*su@uiacK-7s;p}^n^kutc(r#=X^6M4SWU;G4AhI z+x_>N@R~oobb}mjO+Z|7q+e<c$HTp#ZRG%X=9V<I^_~Q)x*R{-zb^vDSfs*PE9w5( zQ{^iJqLeckgl4&EM(9bGI3oIKvku^KR%GQXAcxbzAZbTiHmbmj^EJTD9@JzN`21X& z<{8__qnYq`M&-XfP(wssaqG_43O%ONy@?clflKx7i3-)eSotz(TZ22XRFJn(g1wX2 z=uWV@gE&yw6jl(L7B)F>6R-4-pL>W}bFCH4O`D4*-Ze2;roH7bITaHpeA*%^Dk?%R z>^J=B+;zF{h6JmY2;yCurbH^%FS1~A)NlWS69T;vBa<Y*3bR=MZWSNX4Zrrtbdb;9 z7T<KbveSNln7KG^_UiWiZ<D3xun|h^AvO_yLlVUQ_!ZTl9Hc7k4WGFs@~k4q<sOb& z_z@?@)w|;N5ppUlom=*NDpAp}nWPCEwWQC<?*qTwQQ&6{z42G1Won75tI%Y48y$nY zY(#v4vbUH2ZN(d!!5U12UZ05xPY+|;1@*iQ<-pU$J9JDn8YiC7A=*_i!S`qL{tHAn z<`-FA2<)!1H;wLevI0}oaOuLo1W#fAq3ZSKdo5CWaiB?xA$o%i#ZNUb8ZV-zLnChG zvMXsG6p}_Lrfj0b%!2s<g^>h6zxQpgKHG>g75A2S=-BihB4}=vt6>mf0plK#d@1!& zb8x1W7j^p4ucTq8bN$EEI+r?!<&Sy8F7+>U#h3-Zb)@7VES=otHwvA3)uNhI{tNoC zkl4W~C~gb{cnzF^cjd1cVGUWPcfpTVNWcH+DZ~dcG`Q^Vx*$Ik7$>YOA(UQYn|bH{ z)m5KUEB&W{t8#2OYUtgoX$pw}rC!fLnyVkWD&qMw<PC)Ot{(xZSr$>ld4OAT$<B6I z47{Bxy_&pX_vNp_1Ody>x61!1APk93Ri7PW?hbuwpSK}7aDs@jx(RvvSri-0HJ-j! z;X9ObqU+_O&60>!UK$$qXrCTcT`-Ffyo>fc_!en#3EM7r!dmv);!h#VAY)K>YP<1I zv4{l!LMqXqSU=vByx`tPzRckSbjA`X;CodXTnj7oN$gsoji?IQ(Ra0Uu3#u3_0IuK z1!>?2b_<s(;fS)?2Mv$`Mxx<KUoKMpz5vrNhgUU_#&-uGsawbN)9`=ZvrPchfIJA% z>R-geC(+MjaKTbD63lxLe@$5Cv(#@1&|I4%rUg0-hB{L)O+6`~2VU?p3DP-6;RH<y z_C>2|4OPzU1JXRBrJ)!C@M*GriiOzz(>vN<0_H}7a4Z`UED>YQ&hIPbPdd?E8gMtV ze7D+HhL0`%)rd4|tGb~g4RRqGE&=dxVO0>b-KWv=#I$2Gz#%h|---d0Z6&hC_brNz z{)dx()iLp~uQw*3Jr@S4ifg0(b2BtQQj7M+A{&Uke8(c(Q)Ik#d(54*b4XjPJqhn* z3!BZf2RT9FhIZTcFB4mQJ7i*gxs?KvBn1B$6<(4OV!nt=dMFv{03AB`1J*e;*ZvNB z2UlpJHk09kVEJ|-<px~N{6l!1xIrYr&x~?9v9R!aLQ4`lpI`Gn@IUh*Kp;9Vk`Rpz zpZTPlE+=RlgqfD1-$akWlT;Eby!*j{dui|GgEo9j*p`IJs79-`bMwSkTD<4&;gXfj z-9d6~5f=3S+3Q<(?<!}G>9V?;NzC?pzxd=pEdc%*frNpuBOE4^wy2wn2Jl|nJI@W> z)|4Rzsj=F!q%Vh;h4%FDpB@}cBn(tqS89wHwNV#-);kjB_f&YadGBl1g!hTLuQGDw zzw+yyK**?xmmTgAryH26=m(yxR+tgPDjG&-*$zH(!Kp_(1^;ACw?O3~5%yxOQk>1u z!iL`QDpOIm04<P5s9b+d`R1VzH$d*Vxgux^Yvq-z$X+BtB5Gcw+e-K3b%~LX{4;Es zVmFx6A|sNh3&XM5{D2z)TB->9n`)g4#B-qBtuEB5G^@oQ*JDhI@54XCa4~2kfZ<St zh5?TLs4q%H#|87cs{boTn#t%EC()M_;fhu8uhv}&=*<9Kb!ak~+iL!USX9alYH1So zwUFW}sJUlos;a1Y@f1boQFUHlB_AS8EPcHH1^WR;tss#=_Da)Ndcv-qPo1s@+`W&| zR5EqrrRnZTi-%#qyRSb*W9c;a75YZwr}GjnjD);NB1Q$53K;TqCAzpqhnXj#<eyA6 zKjHo>2u63st!kRwfU<`f?L=c?3>7hih3lJ~ckhaPO{4=okn(MIa!HtaR2Z+WA0{Hv z{`H0W^;Ji_MKo7vk<>_kd#O05g){4)$3N<KEI536zJ(&7j2b|Q7SRpv)vZ--CQONf zS4LJMyJ$Y$VIu8{#o55H#3-05hEPd1Yy^S}7(58kJAZ}N#cY4xULiiE@dWo@p<)Yx zSRYHT_6{?2o)I370Q4U@I4bYjKn6d@*e*_7>Nt)L9=^ojlCnjV45Xo<alO$_mr;V& zxB6~tlBOP?9axorDKl7B-}j^mWvP>p|K~?WBMA|vlAaiIV@t~!9&hbiZg?*Jm`gxS z@vV2XS;~;3j}i!Gu9gUIVX=ANqoSn%;=cAZuq?je%Ra1aTf(Xz8IfX)wnD!4%dVXp zLymNML9p7t6gmT^bsfQfkEQIiL*`4p1z3W3GDJIWC7UaiZpkmP5v#c4X7$z3ouk#t z)7F)W+AB`M@U>rYpNCu<p=`N_o82<Y6CT~A44~2LPy(IdxbHn8-LU?b+nfCxWkAJl zz<npX4XTD%%l@>vUIDa*_!yrbnU|dM7!Bn86qBp63Dj_v*g)c{9gqF6a4H~7<w7^) z#(iTy=1=5Bf>lj9{a%E%%8T#Yb3BY@%sxr~fJCX&t<zUKSz_X(6MRTSDz3M`1dA3n z#hX%@It>*~izr;0I<UKuPP*k52vkz9Hd03#kq8a(<=2&q2qZ($OcUs{7%%9bOM4Nx zc^19fcqV)%$9G}<U)e<!{=vm2ltX+E2GJ1@S+_W4PXyO9`m94vjO1%Q2uKD)bs9XP z-Lg6X`#)LHg5fk`IXt|*Cy^0eL*7-U<$~cfn<d~h_qFmG$dokMQ(tiycRhx1b(Bdc z|GDv_l)Xg(2gJC-@cM2r+;CGBws?9y7{8uqHT@jDmJ)OMg*&^e1K&(q9^ZgYubXFY zBIy&ZaqyAF?f{$MItxL1z2HEEH#Br)VR*)zj`EFl#}hBC|F3zt<!IPn9uFxAlmrOD zOtY&dsDS7(xt4I3Ti9~f^+N1!!Ut+Ep~hVAi8qr7<{iJA$j~<dI#D=M%Y_^H&MAu6 z4sy{JvXwW3ybU45*N;L})~{o8>0M>J%BJjJJhG)XYR!igt`AU7qcnHwB1ni3ire&P z=JOqjwTuqhmvd4=z(`EAj)6LkMF!K}Wlp<A-!A1)><Uoa5D3W)aa|IVf72%+?IzPZ zC93u1(WwEaP9&EXbjh(%{#Q^UXx(jmB&v-jNEzHKL07fcR}+xXcZWaircjxuHa}LR zq7*THZzZOEW_`^o6E&4kGdAG7X5lx$enMi@Wk-+8rWyQ!x4@LOk6QJ~uig4|eNMf1 z*(Syo6vdbuoA{6Ea_BV<4u-?EFX}_*Hlc66G+URY$`383c*y&&gde5tc9O!vC506Z zj4tUH!;1S1P_-1y=}vjq;m#~&mkUgq*NBvxT7TV6pqtTn6BNDL^QgSJ?%%goDD`NH z{|H3~VWZ%f${#+XwW)|%wRI058geOe`bz)M9cHThBTYOtl46N_+S@B)Wa7pH<Jq+Z ztFD|>#p#_eMzG|x+9AZJL1nj<uWIm4I2Z~@%vR=&z9*Ji>?Goo`49T$3I6jN2;9oz z63{9q9!=$4;e1|=F{UO|FQc_ThRWX){gYmF{l3>s!JEh#^XM8{zuR#wLY>}$>;ap5 z*B;~Q1LDqA#7{)^Br#_=)JsDizgNY>?#lT-nUtEgKi)e2V{Vc(BsPX=(jkKC^blHC zHQ`gn_fC={p1ljWo&w0$#xR<GsRJhZm-zrpBmi(Y`^~lI>Hb1#W0S=<pu{w<wNH)T z{lNW<w6)Vtwk0Pfj8)~d@2|`}i(-G%zgRod1i8=~V-818PUdSUbaP)%8}m#ube>i~ z!;smZbms%Q!@%(2X~})%rvO+6`HIQjXMBnM6#{=s^a$*Y55TfrxJEh=){DHv81kHz zy`EM6hf5h_C?GG<7|TvDIoz}hBihqxFy@et$|`Sd0#5*W5E_w39%dgQF0A&9A<C<y zi{bf~yJ!c2?`?Z^kTY6wdN;E$vD2i9HpN2jK<+FAt$%u|=ypd$U}w-b2tj9VC^+h= z(CEdR@KfE}4m@D^=p_gZ&Uv~VaLYWOEN}Ww2N@G1*<cQZPk(w70+_0ta06@8QPE98 zd7Cn1+EO<ERi#NySTz=o3<SiNE0AooW+W^)J}FmAX4vmlF}Ky21&wXBL9bC$+DouU zN{&+YgRIfG&YN9D6@y{VzZQ-HU?#C9bX+aGgBp%j%{O#OnGojxI}}G?)#xQ|-=lTC z(%sz0B@JaMN7>JOfnONtmk<<|+40uj?i3QDD9wczD4p~{h4NpZlX;eKp^``?kXIDx zH){NieLDXT*L_=Hy3+ad{lAkvT8*CQWNFw&Z)?m<8Z4{TmUo9(fNOQ_@y0r&&uawk zges@F5L3F5Zsz-l<a?Tn{6Y99@kvJXM&IO~p9!p8U~OXKqmnp(PH^q1+W(X3xj<?Z z?99`lxqo@rAllmtzu2X-DkN+k^yADhB<Oda^^d@Xi>=%&3jNQYhE+qP<IqL3@IJaU z!!dFG>bB_pev|4nUOGO7|42||6WwO*i~KrK$nV|{l>_zS$%J0e^SdtQn!je?={Yht z3-1ZZ@-~_9K7<1^4XOaaIPoap<RXwwXy~_?UuYl^YSZ9R!G8soo#$LFQ*pnwAETUv zw0C}(fH+2S@zQ08NrIWss;G}b@z1(hO__J4kdUCldGi2}&Q@usTmKyt%x1f5a>;cD z`HlP136GHIgT_A>Tlky9+Mq7rtm^hw(Gj^#_Rd2`j?+|79NhSr+`?(WY0euzP>{YB z4{`x4s#2@ct7-CnO@^~+5`#=2vAJ<z-^VI^R~P`F`vC=EOafE@RjD7(-#~XMyXk!# zL9=e&XslZ8hwPOfh~I@useUtg>9#@~F60|!AEDUTGMJf9F7Bg)p<77J0iFc3BbVi@ z<LoF-c8Qrg<(S$-YP6h48~$GXBL$xp&$^OWeS}bU`rzG+g>M%JP{refr{}!Wf#&d} zfUTS~c1`c7{Y<tnRQ6Juo0StdC#ZOEu1E&snG<A6rAQ+Z)Z{FuFw}P<&wAq{ND_(z z{|gC2eB>xA^!z}Vwpj`zwtA~SYO117;Ztm6`sVdE18e-^&s%QDPsxhN(^b{*2sl>~ zD&av_-cW(Y`iH-r`~+>q97V7{GuU(?SF*3uVXk8)!et?_CPB)b!V*&(1t&^Q;yyjE zq@|Acm^5%SQt7d!Cw6`+IqZsD!GV{$kk<uVIFLJfR8Jl@2AHl%olv~FDePl2fnSXK z#W&lkP1EOc>UDm(?q$Y~3AUI18sURqS=kpKK`y5!Omfm)SB>=GtB%)5d(*RzcL#;M z^eF89tZPV{u^>5MJm~#$NB&cm)pw|V-}@z7qvzYo@EcdJ?{{I+!Gyc~Ic2Zb4Dm$* zAb@Tgs_NXN6JZias^>Uv+n?4;hi0`HA#IKd4V}AaSKH&F86Eyxz^u?wi(6_7f${GT zbw6kO-Xb^9YD+^xLB?Dv0f$Hnq}p`GPa(+?n$ww*EYB`y(?lvbO%qNU0;_vP7@dCE zQvvtD*V4?6uloy&2wqY;=CJ!=E3@bQ`p}ka5H@B}9C$)XoCRc58T1(5c*wQX-l_-p zj(1}-1BN<)Z;VXE+1u5GWA;d3wmVtsDIBKH#fI}6edL|RB}styno`zyoE45s1G}no zDG6F4UGB>zUBLajCWIL3N`VR4-+RD}lv4+bu$_%LQBdV`e_>Ag7^M-C`w3tV4q~*Z z@>|6v3H|(lqdiC?v1%ZeUXR+25u3Z<#6lDjnk7q!<QnTb)8`?SYwHC&d4y=G>>hXW zfJ8xDXQEl2$I_`D39v0V5NoIHV@M}cCgh-LwS9R>YXFRXCV?LNN{{j-Ztv-g3o-%* zNL`qNZxUQt*$26R6BBKT@Jhsms4jZz_)s{xuED9WXTn+rw|#_?KfuRt@o20v3CHEV zM$;L^cprxgQN(6kJy&?GM|b0%1fK{_UL*G%%3S(_v@p2s);1Mr2S3=EPcs04q%uWC z+?6Vqol>ITt$Bw)uU9#3vZ#U9#D%1YoHGQcHLp`aOHQTMJ=bU)9jLkoEp>VcuYf7P zR3BsR?RuhD7c=A@1vflK0k(L~m8+T-OW&xL-p60)|ASc@GsYED_EQ{V@@EF*s;NOr zhwHjZQg2_TCRF`fN({=phPg9;&I#S$c`eE<!>yjZ(XycWYZp!mE+^hff_h{~tn>`k zBOVc`=2>ev8*`eG0Q@Ix)_7QDw1C~s?z2C>{kK=ajb@YkV;u$zzx+8vO}*s8e`dh( zZeSrgR9_b9%I`Bt&<Z>>y|sPX?-@F|vIT9x#fy(`&<!~1-9twt4D~@`^BU(9mN{DI za9UXM>srl0<Eb_yf`wHxX{d%m3CFMzz&Qx3BY-lN(9W;ZlTm3RQ}vK)l*=?a-K6Rt zBb-OE$$j~QpN$2?t-|Z!T2ty$3Afji7cqQInj&ZI>F`)Z4;Ptkm<M_~zdJQ*o@6tk z7|Fg4g+enB{+8mSnEIH1An*GgFxvT*PHVKZH2z8yq_tSi3FNZx;Y$@Trq-f$vk&LO zTO*gukcb{QVtAlvd)5W45%r_}-VCpq-LF7DW#;ZOef}ul_I0rj-Y^<iqCYaang_ML zM(%Y_qtPh#>9O{Sce7PSRAmm(pVAoOnA|b-k9O(N`wj*%ASrpA<i|x2Z209+1mt^7 z0m4je8a+yF!2I+KXO@J77U}uu;N82jL*+aKY~jcf?a(nU>eKT`nCnwNT+>hLNqU_d z;*rAzYzgHE1d{kJI?!Wow^k$c^Y6z;1y;PJ6=)~34gyM}yx;goOQn3}4ASV*LG-<t zB*O=V?{sIw4Qqw1@o*2hr>4+UD$F;LTKnv*c!SeAYx<^s56t>RPqwL<oemapRd1hS zrGTOD$zw5Zl9R7pMVQR_E*~SSqS7Dw-OkpH?l8+RcIfWr2^xRfN=fK3lIRO~V!+8x ze2p(QEY7wWc@EGIl==r+Aw)#%ChPIIK0qUhQRvaan^-N_&~wwkrl2%JydCs20>4I* zinl>#Iuxwq2vUgnlT&6X;LxIB(iFxo_@C);%C|VI<G=lbe}AOFd=b<sDrf;_J;Y+$ zJYS1W-TH|^?BBR&(HJ!bZa;Xs<Rb7_*!MooQLO6A<yQhpnHQ9X*vOjiM$0fRt4Zhk zD>Q1-nN5gJYW8({5d46iv)H*NUu@cZQ~Me}8ui>(l=(-Dtyj)yXphD*pYa=?@}a#! z7WJYjADlI*%$?BhzP6@Zg!GPdx9+QTZRff2(tu(}{R!(zqHM~Oj1tECN$C5cC*RMP zzBl~(7u+cn<mJWifNx{&d15u9?e1k*z&D0yESnC2n|se0P6$AXQNWjd*7l*=DtaKU ztwFXcTr<-}UsL6zd4vj2#LMJTG4zvr8UD2k{mvEEdyaqbUVrlRtI~>IT*4;d6psJl ziSkgLw!qpF@2M{uP$BhzA`ebOGkl~nAcPr_5qZ*S{;_13=TG2J=KxwQpU#b!7qYQM zB-)L^up>)>0<%-CT4&P!#~3RD(pfy7bL@EK-sX4D42LU04CCm!pt@{#FX3)EM2o`s z1PMiBB)=uZ&$dzv!JgX8Og-&KI!24&LGBY)%L-DhQ#w16CJu+_MRD(~2Rc}c$@ySs zuOyflo2;JN*b-+#(C7Zr`ACG~-Dp<@)ui5UY$s&TlIX7Y8R+-S*Y@p_N*lP%HGBxi zwV3?EidV8s(gUZFCMgBx=}dn++m|6k15{t8@7zuh*_ZxiLseLR7tqPd_+g;<8TZ<f zhk2Zl)lgg6o7|2>h$M;hNHQ^oPR4Pm4QgLYgPl~Tf*kCk7v1FC$PHl=lgSL1xF!{2 zF1|{ny8p()9e?%<9GcWX%Enj@N7Fm`Xd-9k<$(#Li+kZDWVz5q8Oq}^Z+r(Yq7#*Z z1SPx0TJW=XQrAQ9&M{zLHQClJr>{<FWZK!9Lt|C*fre8aITf<J`iM=n&i3razQor1 z=Bw%~D}t6A$7<w{axV{XiL9gxjHOcZ?}m-k^$tX^!|kSBwKH{NdD%2D=$S||4(sg^ z%C>{^QoYPb`?s?Frv-b6<3TIxuN|FO0O6?%+^yc_d)^>QbWbKU_Tj4lp)}4NA2K~t zF+;vSpM+79*(j(>H#)csoV5l-FwFSvtoa|sz0`Y?^>C|hXsC^uNSTE$FOIFWn^*F? zj@RPX?}HQJYRX+|l~Q!nm{d?sTWzcbSS>iHi2(@iUlYm{H@XQKrJ;efcZJ7jHQ4r| z`w1XKjPZpS9BM0cjmS8ypTi4vpG^eAtBvndhz`VIqX0AAe+~ZF!+st&BI%Z82MgcZ zWr6J9-GIk*%p#sKp-v|lB;{{Il;E;1WfpUjrn4Uo!chay1BIVPA{CzPjJzM5^oT5j zuN@QYZClFv_2osZ1ijOaNg7APFa-W=j8YiI%ef>I#=7TZZJ;?Mwoti(?-7w07cKKF zbM7a{-IyqrZ2bG5@injWe3*x3rk8n_pGl<Jy^dNo6)Q1?+4c!!eXDvj$fCF94t0zY z)X**aPp)yEH{&9<45YIO=cvUkURsar?Eo57b@gUfpMq0QKVu+Md@Z9^j#j2(ZqlAa z(CO@{&2mAV_4JT-@FDr$G<hwcMd9GnS%`sgPsBbPkbU=F`RakIT<1&rSj#-|3iqu3 z8cd^IQ|cpiJL!-!j?og~{X^Kley)^#--ywpfa2B58uZ2-x?|Kx3j6nzm(YgldEFv= zpdqT4b~M7l4qz8U0i^R2U6mFrNUM<POQ4nuacqP`!QL@cLmEgjboevJREu%yc}EpP zKl}+9g$DhHg>i|L^#<$B$~-zzQEN!cYq;H%bW1?AAe^Rm@E<F~^eMAH=g73p^<Lb{ zs_80rTvJ*tkQ}4-k+pFGsh6Ez%g#)Q$A2BZJbC=h45IHw3OCz$))v7xj>PW^tk{zh z%C44uLaz)FaW+Kip?Z<%)JwEG+Zc$?URSW&*R^VZqy*e0NEi1lRzi(xPLh~kt*T1= z%6L+k-|!)W8sd0iy7|i~VA0*ecFneAH&)B+4M*>-q$X#7@3kZ>f}wgKP(mYb%#QL* zNRjyBO?*@H&M0$bT%Y@Zviq}dy-zX2C3@VEIRd^)Y`9Mmr~bk`f#u$GF8WVi$c?Y& zLGyfuN8+@a&$(8}HTZYl#sM(vR9*}#GX1;)5@ov<P1LO5wgGjf*F4r?;hD`upAeEe z8cpHq%6!Y<speL*>nlm>$!jJHWo7wwX8ta6VqR=O-~9O(vZ*1<KYrf+8gwG>OvjHq z@$Q%Bfn30^i;)WmHbb>;Z!eUU{saAoGkdwG@Fmi@-lIwKZGab2<XG*PVvFXF4vGHR z&4tm!b_{4kZYjEOXi0+Vz5<VYP#hoHLR>RwfRp#G$AXyHg5&o*o`*1|Fy0|2bxQv3 zR7yez72NgoW?b(Ur{cbWOUmVk8hJVN&tIeP{YwY*rp+F78S&8Tu<N=W^Fy&t9Gu9( z$NnIva`z4NdO;oFfUI|HHsY<jp>*{GsoHHf$bK>Mk```u$X7(1l|l64dIX#JF8ul! z1hN-WQFyo@QpFrV%6t4Qc!G1E=73K?V$myK_)rBM>AA{%CXm|H`^`oAVKG9NQ>xs* zM%y;)%M^U94`C~9x>s!$oMAmWqZPJ7QWfXrMUj)lI;vB6m&SR*IysDP3$iJ=O{aZq z7fdgzKjjLPHJN?<=&6wVW$mQSL=fLSf9u`Ahh{(ily!|s$*pmBGwo;i@k#J-V}3jK z_^IQD7WTTmIYi_Mu<C^y0PGEpB`7PHTU5vg$i5kOp(}OdYv-9EflH3O^=GwyS(TS> z2*p3dNy8jlQFbb#i0dg%@!gB`%sQ-nCtN9bDMgih-(5mMOG*9fajF}ZW0s-ZT8+B5 zapM5A6<1FBa}m#sl9M5V*0rN?p)6fRN<U1?+cESiyhiuAHgw0GYDtK7B?y|~rA7%4 zIb16zOlU5PeMvfd4jG_~UAr=F?^iu!&>4rtRz6=3Q2$O_Q*BBh7s=CVsNehC?@vIR z$cBC$d`(|AHS)3v(u7TC)ikIfGU@!piqx4h>w1qayw`J2(dN4i#b1m)_TZ8H<)%+u z88e5){*k8XEo5h>!o+yEZG1vf<B=sl*GC|F=(TJ12of9mOKdb+9UmDK+m+gv#?NOs z^j~i35|}=l>#WR}*;1v)G$4rE=1z!=VX5mLu&|=xj`7_&|5}@(r)*cu(a9@DuU(!% zNc#x*lw?p-vV_cEh%?1Z?_7Oj7CRDPjipXf4{(Rr&`*ieE-xSazjh3ExxA@jRs-=G z9tBSB(Hx~>;<>HvqhdA7@;qcAo?Dt9Zqc4==b;(YvP*?v=W45=DcgZl4=`x+w+&fe za%%V0=*uWY7fDWWB$9%nLGDFFEgQ)v27;7{CH>#J+jzE`b}vi09=FBZQ%v=tY9&kz zC=_=+COXM3wqK}Vbbq;3Ma8y8e>Bv#i42PyTLgY8MqEl~@$Q(~=_*0kAWT7OOljan zIa;*hIP<|?$$n|Z;0B{*R-`sWxBU|5@clZ%9^$+n+Rrc~@|J+UUO_G9S5S1EY}9^Q zWYa5Xy(@tgU92`P!urfdK6EVcb+y0Gw=3C$;2lM!UCRUiLF>0Bro<(*9SwoU(zzwu zPtOpRKJxV`?Qg|5%PSW`lVCa=bZVob+CaC6_Lfr`*2x3Fpxqbnh)G@0PFJuZ+MDWw z^p?kKm3XSHGy>$@U)Hhds7$RouiNyj7y5DfMw@+BB}Mqxke~BKk9<^n^if`SS}}{V zJ$5AJz72Ve31jQ0TP>a5Vwe)FM!ygCjk~l^tRF=mJuJVn*lBh95;OZ=e}8LJhcSyy zGbbrtBH^-r(WD7lUO|xFSP4nwvS^*=)hAF6meqk^iYNf0KAtD6(s$-NOjbRl=5^?d zzU^%n=H8;fcT-qImy1uP=8VM}MPY?q_iOI1b-*u>R`91+;js&G1-u6Hq0mL(G}&(R ze<oq{4lSO1SfU_$wd{HN{rI^HU|1~haxjd3p}GufmI-4MHb>Iq-yK5E|JTJKscTI^ zgD1r=p}+weFz$wx=(9LLd1sLV5mexCv!1{SmE@4GgkT^{Sj%*Oa+Bs0k4-++{i$=+ zcjs{6;(Nd?4Z%%R=uTpe<;P&2(kASO;o_`7g1B>RY)$O=j!lSALS(mMb}&gD)Q@R| zKsJSLGROUT+Pl`+tgn%u9vj}i+SOB1`qDhsIY^&rE-~BD4ta{_24RHdAM!2KzSXk! z;)91(ojMf^l7zfbP|-IOTB=Zzg>}|`eRPBua(~^&XTYbX<iRiA#=BrH2FN2WENT^a zm&EcY)HQ#_l<5xOP*!yQAQg?0*F|aC-?`hqE<h9dYITi+KZ!<cn3tzxkiRG~kj9qy zQ3JW071TBP$mjDL_Pp9upF`hNF!QrTFY?E}WW9gG9;2myC;gbFIMe9ND8E#D@81+K zY!oH<2#$!tYXyZBOVj=Q)&rH2Xag6y8{Q@wVfY??1u@Sn3R0WE)PXf-JCTd#I-U%B zonX2wBVO7Y&8(hIE$_O5lpAf|E_t|i+Ag_?&2OMjOIo<7F(g|&F5`Sie~|7yskl*0 zA$b<+mJ18ED%ZfO@lA1=oOms?QQor<Th2OC0_TbFOGP~;0}lWmZ8$H!dD7)fTzr*s z#GGP$Av>Zgn>Y@IJL@~Te<Q^EN1mDGTO_@!pFEeCsb)M?V^?<$@tfy(m6h50G#z)j zk1*3vhtKXEh<Ot24Qhn^1WR_}EDlKN#hWwzq359fun%-fYiU!28f0F%)k4DdV&e6( zMsLN%iV45zNKAbl<Mh_K<t{Fkc_awxmo;~~#&Ek5mT3^%zC^cQk)pAY9Dy|K9r{|f zu^T#AG27SrgKA(gg-%BMg3_C%cG2dleQ~z+p?oAgW#3s~VbpDX-B2bah@;HsTB&TK zEL!f!k8$Z1{ZNGKroQM8Y3>%G0uSVN=q(8=rFOYUBrevg6x(8fHQf9=ptn&u)d@-Q zS>bxyYhX4NUj(b-=uasPQhiXCzfatt6;aQQ56XUB1Lj!cCeo$qE*M%}YqCCI;TvtZ zy~a#p|GKBQjBUR?qT9qy`I{n{f(qWIUodZ2!1Nru9<clVWDK;y^Vy^XSqd|ocG}kx zE-iKNBqz1+mwX!+hqchjX_`ikOf8XNHHt^uLgmMiS#nu#`<k~HTDE5sb0wbr0xfn? z2eanxi*>If8V9@{c^|}H-+JX&qn_XdCfhzM6SCU~7%I64B10-FL+nmr@#^>lf3i_c z8O>-VG+g2*ulKMK{QCVZv=tLc3e~qc)?R9~Ttm)7u=ih~pM3cn3EQ%Nr#vz=_N64G z<=tb?zg%&@#W}6C3udWK>mk}%Z`VqH^{vFE@AFm3oKq@;W~i$xVSQBQxQ`0Zzn9Q3 z%4FT^dCf|Laz?~FS?!Z3FF{@#(yZ*}A>9^2#llZDJc^_8N&bZ2qAqaSjz$_@twmDq z5P-O_z^kIH5;!uhshundsh53q6CYvIa|C_l=RId&f5po{Rvf}AG)FPUl*I1c;U-6M z&96cT%f8hK-D>eNa#yyqw?;Q0<8kLa&Nc@IY;_{NDjWs!QwrtLX|FQ_wp|}pZn?|r zq_EyfOKjF9F(stOG_vnx$tH#fma^~9F(}*jIE*e^fM53m+NTVG0T2?sp4odC)sWbP zmeiG=B9V<wiPbpNN90GV7LL;Uekt5@Uj1sgRq{NcSW&4F%h*VY?6cN4sD5wI%(C7c zgA}WO4_6mbohVw=lk$I67gvATZ|U{c0J+12=RIQ|2<avFJafvj<e6{{x~DV<w17A! z=BcCo2ZCIEBTi{#or@mI+_Etv@Dx)`+Sdws{<>&HJRliDG>~rTXcanqn<q*wj1g%` ze5i~uh{WpWVSf4=`G;dyk>G4=^*efd-ehuw3U>vxt%&0DWd82NSLyRUEZ8dIW6T4g z+*AItT+^VRvBP3BEXwY<iB47O95W$&+i-6d5vMh=Zz~A86JJlw1{Y^6<cS&9PQNaH z+>@i~BPz5(+aEZwckG?_(qMV68d=<9zqG)HTv%lLnE+-`X3xu?i>;>7^VTF8HxkbI z-bT|;@k6)9%Q5*ub~F>3ryJwXZ4~b8IdX!k+d~5+whDdTi`5a+){^X#|DOU<hqLVF zU#At<?8Y<c>_g7fB}>uh`aAJ+=v$@95GF4%+k`j5I0Z7Vr6Ykkjy2&WKG%P*oFt#G zimnU`dK}AWPGP2-2|U2u%2xK~4a|n3utoh(SSQ(pYW^s<I=LO9*U~!VS01l9E{vR- za1e-LUwMjtRipeU{8?<DCW4O`nIm|UEJm??#+!LBa2IJEi7Qf;u0QagHn5!4RU<l) z0gZb@v3g_fYaSId1~3c^-~#vY-o;lnl4D6Y28REzQ+$@(`M84xv&TbHg)?q`jB}Fx z$21sN*DZBgc1QkVW(a9hu&flDctd&-lp$nJIVx~K6}@cO9{Lp7#oWw2qzNAg(G<JQ z_VCe<l7WlUYtWdsUfB4a&;Ez|a}HG<gR@rNq1WW>Pi$JY@5&J|Q|^)}jZo7;9VdqZ zk!hv4s#}kg1hRmdVZ3lj#9-xO5vh-=Dh+NVD7&fdPC#SKA@0FlsBfz#UMKK@PagQ> z<@wCa4O=qY$|kh&dfI0oJI39QjNX}oTvdDKb$5I|AMoX@Q)B5GLZ{7=eZ8a_DnNV@ zyVcV_9}}7b>DUu|53AxQ@*p65)l0G=;lgNy+*S~@gHZWZUC*HYT|pHJ0+D8|E(=#` zlOyivje-8q)U9tSjG=PYeD#<3FQ1L>yYpZ>$=gkXMQiRlka(PPq>jJ1@C^c^7)yCo z9*>M%eh1F!XPlwPJAn;aP_DsBppnkjCCs@yCR{CsKqmcE_ufYeXT0c0U!LtGNjb5Z zTi-v_b7Wj<@V^heCs)`Fl;P{d)dkcUjG72dl^bo_+?h#o)Sz5(#DBU$rw8U@^-0H_ zY>&z8s5kf}403SKkI<#2R&nX7MJ6G)sLb$B8f%tl0o0P<C_@$EMhZxZ>jLvqgnQRM zuDlf*1uk21M4{MXSeqFZ&odTLK+9njg+FkhJUPf%<`ZupdPnL^-AK`+2&ip4Hu+~w zohQJQx0*eQQahh^e`$n)W0<qy??cd&`@vJhnZQh2>6117XTE%$XWvccBsY4cGv?Kl zj(>xg9C$}rMqh@fq#HuCcKKSKTzMx@L4>DV0}<ulmR;gwitM{O+v(#I&qRLN=@v0_ zHjdN4DR}CYR!9$Lh#2sL_{L?j1)D(|<aL{sRc%N6m`45y{#dbGhC|zrmAwot>&|@e z`L6)2nw-{OM3cGLG|J=3LZ6(%>%O+aqjV7Ve8lG0;J(JY9v!A%djZv%uViPi3JF1% zhICYA27<xz^Z|H>98{PNn=_%E2rk=Re`R&utA~V?E!{sT(X}_1{V_wojV|$dmRSUe zy<oLZLgrUZ^JE)bIZE9@SmSIk6;mkALNR#gMA=7IV}4pY)f{)#s9RM|kh+Xce(JN> z_=1E=b>>5%JsInIYNqHkPboU~kn!ZtE!$8}Cb}l0k=vj5*1%`L^q^g74qczWt(ta0 z3)MmK_OkS#lP-!W;ph|f)N7e9x96|;VHW30oPlg;j7k$I5gU(@A(D~7ocIH4x>k6t zi>9p2^E>aJNbRk^R`mWSj8wY(cstMHz}P@DLDx*we7E?jJ<bNzG-qO28q_mDaF6bZ zJfCLNGCN(*p41)w8=#p|=CYEnQ>_ZSfR9*j^B36An*VPJGz7Th)DJlHs;cL$o+X7< zgs8=$aoJ#>1HEQ!*4s*k)H2SX8Soq`jL|vPoa{}Q|AiEnEdISlu|y{y;d11uLN0r~ z8+NXap96rSdkQ@{Y!8n4b|Km*xAgbpQeXJ7cC-ZMdE~Sbkrnlt&P{_Ty7k~^G7c;_ z7#uJxjO(qjMh)4NM#3uLL-?r~bniK$(0A^Xs9qy-kAZc+oQD_in$E|~${FIDy9Rs6 zNTD0=H+RofcWpgHp<3t71-B2{LZ#-JEw}%M#Ezpr2GE!8YC94b!x)w|R&EAUMH5ng zM*k5BbI8ML-JNO;<nKZFCf%s*xS1A>K^^m;=0wd`lYLS*H`-oI@p*0^ajTPXk|g?Y zKl^TC=$qlk5CW1HeaxB|_zg9!T7?ZRM>XZZcN<&GlN89lk>nyr#-9gTZu||Y0j)xq zJ18#3UMo!`>Kkdmxgb&_Lg4lXx6w}JyXr6Lq~V?h(pGlx2v!f1JaWyxEE@~!@e@bj zT23El6sjNH`)KG#wGXpCGUlZQDG=AkiAr&sRN|v*{o^)aO_gv{vGKYGPvsBIec_9k zN&eRLcza-og|HW!J!V7wnbo&^Ne?g0D_W62-r6<;Y;e+;4BJ;&DpZ%*fa}LdUi~3` z;`@$&qobaZyNK1W>U|d?A)kb?BOU*p=R6INXziu?$Yf4yRKm||4&CnZi?CNR5ka0h zqpaX`S7qrl5^;zFMj&Qn7bexfhNsYwqegc*6JyZqOAY#$LAz|jl!w*mi9;RY`-l0) zY&ioxJ!LS~OBL63i(iB0Pi=J%;ph)E0ZC?4AB0rFCp@e@Uy{NJRPvp3#wL4$QEU2< z+2#TZ=^omLL^PTCBd4pjHe;Akw0Ciu#)c;q*uJBOC;YkAZYPfawVRR7EEV3$m+_pT z(M|t3Ej*R+5XS_!A*567EiIB8)T*xhM!?$=HuSoYvD3J@bUK!7ihP;c!m9`eYWpTv zgHz;xRwomjFV+^NA4z7U{*`-pUBjWL|5g=(uRLR(n5D;<z;^_J6;R3|tZzm6gK(wf z(wixZGo@gJjLcC@nwU68`Z6TK@n$M9L*PvJqyHaa7=53S;3MMUV`<jML$60_7GL>h zc9|;6Ko572As4wcy}Yblh>>Y1S8J()bdz{jG~0yydleJcf|)k<t~?b>1Lv9sm}pug zrLZUlMSIBZ{U{sV#GDeF?$X7Q+GUp`O%kUOgl}l>Y&YPtC0oGOD@0;gs&{Mn;6ET` zZJ_u}T}N2yK9yM&in850U})@~T{ckU?JFl;hS@S`5~S*fh5_7ua<Nwa`1_Ffw6S~1 z-bOjE&?oaxeh`F*u~=O(3)<}8UZ}2ZB;XKQm7p20YQUK2tQ%!(N;vH>r{!ENlYfB$ z#x~M8uIGqBZYoMIi{*2bxmlst{CFeMKK_g;2at2ES+*~mo7c|yxFp3`GE{oMBnRhX zsfg6Uzik^48>R@AMD0*m6)vU19MNbYuVvMPQ|u@YzI*4yAc9p)5J>#yLQp0?-#x{m z6?8lmne8jqjz{0DX>#*CFy*b~Hjvhb(ZW^F!8-3k+PZWAyrf5?tz5WAsO41{-RKhi z)gkgAsrN`JiQufnewBHJ-tDiT3qyVGpCeH_Do`<yRt6)HZClLSl@h!paar{p7iaG# zo5+O%-V6cTtw1U&SFtiEAcCnZ-=~?I+h`L)GC!KfO-*$_&zASKMuH?Ru?@UKE6YVl zOxC3BJTipF&<(3zUZYy=Rv_d;7#AMRgRZST<uzMD`P*Q(u@m$uOi}dL89RSBF>6$& z6uWDoZ=g1jsHrRI1V5%q&QUreB%8}$A`^6?%9qXQOOT88F=>2pGM;mCr41MaT8#b) z$Q<jR8wuVJ5h4l#nyPk>;ksP3p@E9J9xO)a{UP3(i28|=y`0F9?)D!`$%Ddn2A6?_ z*X_*NsEJpHhnX=_=Baq29-oD5dNSU#aT%d~VJnk9!%B5E-Y(nWUNKb`f0z^k@mOmL zs=NSLy2gSxUJ3O{Ai1xWrjpxBn^OxzcQ?eDagM)#YOe{K5L9S!P%+i$J5Mho3R+Mo zTZ@C&v8$k;<69MZ$v_PMlv5N1i4D&^c5<N5A;FgZZXkCSQ(yQJbHX$yP}*CbU#bKm z<We@~Oi&DP10WCmZj^%O-{)sd&%sM~IAJyU(JJS%3n1Me#x!{`&3|&rUkf4BIEOhE zVjU0?whI&iT2%h%S(WMTo&aOXL<YQ<Nse2<?rG#NpDk7$K)y{*g~^v}h98d67@_$- z=B17A{k)Eur+6_5ri+MIuz_a$IGC8f2a{Af1UK2Hz54O9f)H|K+<sI*rp#=ge{mh3 zOtDq#c5+Izgs>?mraZ-^19FqQydwQpE8eqQ>6~`N4==_ZCKio;4wwF$M^h=TI6Vg` z^bn0}GvyA(()Sp=e&Zi|YP|4FjCl@=84*YAsr%z5ws(=g`mJ5WN+ir<wk>0s-3zoZ zV;2UcS)fdOzoD!F5$PF(;Ur`+@GespUH<f%r_e1!pO0_v2dGizfYTKAT77S+QwZP* zN11p`!;JMd95R#l3@d-~sj~p>&D$yIz<FzO&)QwU1lL>6+8y*Jp%Z1MU~QzTcazPF ztXuT9y9!VR@M+0faeD-IN60r2Bw;@Tw7#|X5U|78ik*fqDfL#y4!!#6Td+^g@)Fzp zLC^|Uc5S$;&7TXTnw}T3gFy@zM$)hZh1}9O?(ZI=+-9c1iBb}G!f;K9)O0FDWI#e@ z2t9hc-FZZ*2Q-<13}#77k}?Gv=qcPfB_c9hoPU5c?irwvPzxy4xKpJc7<MGxeld?S z7#WjMkSuuf5*{-VMTTpUhdy66=f1XYzII3cu!&`M$zEYp>sHb6mpMYq$;4>jM_fmV zg|;2bb-izRkH}eB#ydeA(^R}X{(43*9+=^^D$JP}n!GF?MzRpeOBnh`^Zw9_1+8-) zB)o*9JpEHRw6?VsP*|LQ9;Fkv`*?_c^BEyfQ;>wb0&bTU*zK8}#@A-<jdDs(6&%cL zkb><YvVRFZCH@%E32T!e6;o_Eu**dIxik2xNMbC4<}b{|{HLiQ4;8txy8OVY$-wN` zo@bMhFLz=Qg+BwDy3!6j*T+JkY<m)-_+?s%Qu<oxJN!A>LQPj`WzZMU-^<^;Wadav zb{(P^U6*JnVKyr8ZnNT7q_j0?T?WHxp*7=4ztj1I;0l{3IG*bo86!em3vVxm;^efI z=!kTW_E{+(^H7@VPCf5e9B!fC!s<+M3zC?!(^l<N<<Ipt|3oD<QVM_CdCc|MeZ<xE z$h`MjMma?sNE3h;=NABsMO-dhbLoP4&6uW!L@Ms>=;5?{1kZC6RHU}SMq>s;*Q^F9 zP7+QrQzBpWw4&N{t&mtS<bNdEWEslsX4?Py+lPKDO$<pYq)KmIljF#la^G}boEXTp zG+6*egZ9F1Ir%#3bp_5{BW(EX#Iuf+{C-38D0ZZaG!pbyPt%y2TWYWV{+aS5)ob8^ z_F(~1pj51e@*BZV2ase~7l4gK2T>+fUv=ND(D`uZadi|oQ@nFvO@QRH<-H`)yI-lP z{@@i^(<xTNv`ND=T=$gLmQCraAbl}TVz=8+t}Vl()l;ahNYxD_w!(acr_dlkIYHs7 zlXhneeSc~ykSlb^^oN-t)y6RkgWy9jp-S&{r*N?UUw-W~aoQ3u*vaW#rK>Wlp2kf8 zYy5+iRsU14QAfV5A38?ayE<qc5zKGGAeGejEGmadbIsx_zf*xpOxV?Is|sto@X@vg zo49q2$qIqXSr(VBnL7L>$fPzD=82vrtKoITH_Cm9|KP|jaRbP{)7J(LnST8fFMA+K z6d@z6HL4IG^i%(exg-S|4wL8mGjLxfTd0Bmo~tId7B5@T{h7D`364>$6yH1;m{X~= zWYsKEL)NwEqVmO1ZT%j{oHCdTgJL$&nP-yYi3vDT>=yS7WmwEgd72}TpVr_Kqe2C< zci|Yj{DR|S$zwHl#6nln+5N%y`PDm9;;l?fPT4SNYrzamY7p$!QJ@BD%^m7{{3np^ zMlk0x*#~fSx8Hv1y_8^(cIW0GOB6x5EV@g|6HjafI{C0xL0e5z3?*K>fhK<hD~P7A z@t2s&SMN|^camvbc}LZmnYf9V%vlPO1bzxca^az)^ykZx^%5FXVnv=a|J(6VVLR)Q zH$M2z<q6;=ZzjzkYVGQ#f5=d-{@$o%ccpZznJF|TM{GE2O{F&ajd;WnR@#?}!EhIi zb1m%m1vSy=`woX=n(Ig0KTX)FwZMEogdIgNwY(;badt<%nHMw3<n#%cJ$m6|NQPt& zesEo{a!^FPQ74AP?qRh$zAOuOn9<@dSLcI=Z5BALjvr1Ew^BXiIf7LFHueucw3<{F zIJ@4L`cny@eR)?cI%o?dR%sF+(X}3Go!sj0z!QE1^uIkJw9Q0CeUDx7r)KPFAi9r4 z*mtGSeb3K7!VKK8Vrv@R!u^>PGaM=4bXEFW$?E>2sYc&r{i}1df<p_8Zh4yR|IEm` zcXqz5L6_m*=$jZLJ5yKU3i(VDG_aS)*jf_&#DD@3=^t3+;z0)uWz#MBG)c4Cn5(Y$ zJ=9V^SHIA6gt}3KA<<vrHNPms!#f{Gde0-F^p!U@G(m10rBNv-Pr-NUniX`0{PA~R z;^VM)d>2#QldQ|kG@4y9Uxs&3@eb}r%WWc@ra4B<16xkjr+r6p&{^Ew{{&YWsO5Hk z&qLLZ|3NDi+9t0}9xDIM^#edDAbCU&zLdj9OrDTGZ%_`$Nt2gsd>fA8^MbaC)DhKQ zrWf(@1v(de!EmHpybT8#LT(;8m-tec*kXN`N4kbzOTK|1ic$;G-K?9#aqeruzRTmC zLBP@yI!v8>Eyh>vz<LGCG6`5q7VLZ$wO<$Qmf&%K<dcW26<?Or7|X)}SA7MQB0;3u zEIECYwHnki9pU*H<T9*Ri`6d0<*yeLEuX5^Ygq&=iY_l$!1KaPh`DgrHhNiZo5L}N zO1U#JyT~hqJdgU2ic%zje~1|8<5uGfF_DqJ*+S||8a=Va$1LV%9ND**2K?a4B4Eub z#jUm0D`-~)?ayuSqNK3qdO3ZywQ8P~JXHP!Agr$Qx>5l82W_n!j)Q;WxEAfhJhb@) zkgZt9`kgJ>*KdeP&9qV${azLU3mbmXoyyM++VL&^vRvQZ3*X$`!hJ{~*U>o~XB$zJ z=7Ur4G&vmSo)+%IhjJ1g>j_@s9et#jBFANioMR7)(c&!=w0}uPPW)vNux2mGc^=c^ zLe_RU9D~GdPquI$4h`B1IUHvr(K1g;^U1?Jh#BqK7VblmTE3dYaW)Iu)Ct$cFN`WD zME6rP`eOTTD+_4gsIYN@80{U(gWDwI=*S)=>5P6Qx^W0uXeiETv4?yCF%Is&!QbG^ z7N2zP$)PWKW{BLnUgvnFNf2edY7WQ2ud&sgu1QqvJCdGSrfW)l+CVgGkJ^UcClSo+ zS)pr*Is~>nKq#bS8QQ7`?EfeDJYYv>XDLjnhl;6KT_%1Xw12kH13r@&^{LMRiNODU z&^~POmnE7d(kb|K6zwUd%+R|jw@16ZqJ2STeV!fm#r%x#7n}$1&FCYo@8p{llG}bQ z(X}>bvl@=^p5Gbo1nuJ%@8?-;U;g6xo$;<@Q=W`xd`^4LE7`e&a&uUtrpTeceiV}o zl;8&()=Aom7I1i;H?1rJ7OKd@OZGsJRd^#S*(-{oC`vm+)_64Q{ew1d(B`v3*sS)W zb2|I+(px6g9G=1oYs{yewowO>#LZ-rM=M2iHtBCZwZh>iR^T2kO-_hf78BtN8SZPS z7?tvR_6y4w3=Ev*R+WTl^%X@?6s1K$DEd&MEffe*J#Fh_|3#RZ#x5IW|3-5>+6qpz zUy6LeWf8El%ISk|&pP%7&k?lC#c!fer1J~KI1eg{q9}^e6@;g8w*A;D7gd%h!mMf# zo?9h7e=a73_)O2|PSVG{^!ZT~MNyRYp)3Mc7LH=562nOzaj^Z1m{4M$&TmJFUvs3Q zD2k#eDqz)37N*Q0wncGs(3TUE2g3)LBlpqarYMS{C@NqTi7ZTnk4t<=I1vbBa@|Qx z;<~KaMe@mLtSE}2D2fVLiRj2+A4$_CTq7p4>)#~X96j?$K8ZRNMNt$*Q2{FvKQ*}h zNU5)s0*Ui5>8&P4^OY5A>5x+tMNt$Lu!=&XVVh(b{w&3IgRM|Rb?q#2S&i2rrznb| zC@NsJ%6UH4z_uhdBVi~h|EVuHwt;=!sY6at6h%=~z$yxjrfGOAgL5DyKQ$34e={b< z_Rk0HX&rKkq9}@@0#;EN(ZIIUD0(HsbHSG@jk)nk(E_oGq9}@@0#<=&B$|&Z+TUe( zE~Ii;u+D8r`*58OH$_ntMNt8(NQ`V?+d&zg$5uhRD#dnJXDs9?ilQirq5@XK{G4(- ze7CYnv#^R4uIkMyPv!5+bf_tcq9{uH(4!>hnO1}Ke$d{?;P^8J?TVmHonqS??Rk_P zve3^b{`|<^lg1)6p=Zz*v*#ENjOZ>VzuD&*o$qY6{Sxuf!tvkCsIM4v3)H!<4lCG` z-ei<Co=2_`W)f2>D(i8>HIBFAW`c)vo-^X!#=-UdV8`$e4SW=43D3hqcI<bC#wh3b zk;h~A7gK>_V$A&;YwurYlh5IOkMFfvgVwLkv6OWD|7`m&>vMO#+bUz{$BgH+X@fRz z=sLK*arXKe>AP<B8R+G4oRwa{8k2InXES=yonUWLz3}3{xJ86<lCIw4;bHD(`)S#r zz1HBqm~bhqy;a0{avW+=t}Kn2oW(w@w+3w`$8pXJ+JPDM4>d9e*_T5-FNk04bMuWD zA3*x{2{941U*<S&b`09Np2p3vpe=5%F-s_Gbyl6{+-b)#g6+3r0%2Yi6FK~ZJ=eVH zXOBN^=vwHzhk~}A$75e4CgOTx%>840E^j|ZvW9DZBx2$YpTj#r`*j0zOfB{f+OeL- z{|92y2mP4wzV{2-5sq{2W<T0ix8pkt)(P4zp?4g|p?uvE4Zg4Y1nq&K%_U6;GHdlj zqk}Ry_KHE<Gv&5-1?`0v5wJR{#!Qy2vd@l;&XX6zcaGyM8nnYRIL1C!xQglzUV4A^ z(C-~}_G?c&$;@YkW6t^7puH`o9Mm!`GH!};&S;5xi_v!TF}8Nl{wzj=O`l(Fh2>_w z<MZmfxZ{S;ValLw=IQwBSm8>VG=}mR{~Z~=H<R8wz?yN2=XYFI_ogGkSoGFfIf`(c zWRrIaO+;Ev-vy%N&AaxC(ZvDwi#09tS}mE2Lp^9zvi`E)K}=q@bL}Lj_@%FyBJ$7L zcfwTKCI4e{PeQ`B3D@f^dH;1bX`jClQ{kix{nNC2TowT<jd|`ZG4|U=K;tnm<+cxt zQBf=Tb8$@HPZ6|J8`$^pR!b2DT8djr(nsB_uz8mi02KeA<@!_5?hV=u+8zG|6XCKM z?{oH`t*>3{9o~hrYB!Wiz{05)^Tlt)sMs-Q9Fk%`PfFvCg<CZ6g@2I_ue!!zmSb_E z9WyTH?)6iCec@BGvtt>4PDhro@7K1^Soad1yDt-oZ`KIfzok4ru)go%78&nz!!{9M zvwm;Z%RE6lTHg_Fit>O@WhcFD#5m8*nL(!v%HX^<PPrZCmpj_%C5g6>gswePz9bNY zzs>lZUJlynK|9W|{5Y#g7+%L1jq|O-Z1`!;{f;^G>4<*k*_lO*|JB?Hp7V{YKzdrv z=a0$k?UdsNf$)22Jo2<&o)P01T{-7Y`w=#c?Q`B;GbPv$CYF801Vpqun}{*%XB7>) zbxE$96ha@S9RF-XMD(~OU&CHOyFs!`hm<u0K4H!1XaAq%<9vmn%^b0edFm-KPX37m z+hz+`(+BO3LHmQ946<Uh6>=JZiD}7{+g>EuhvgO-idY|3!1F?2*i@oT5dFnC#3zmR zW4&L;T>lkKxW4;?wtviWq8%5pA1-^<nE25aljrTL9MAvnk}h#?GvS>76|;Os``*}I zOax_IYL^4-^^a(i_rydy$@LEXzNDShvhbNDrOBERzmK)YEt1CboS@xS@_WjM&MCIf zClv7fuwv{|=Qj7)51=q)B>275k)ono6K@KUd9T@<GhfF0XTP5`xDUd=`=r?JZ7b2Y z6Gb)C@KQZk+~K)I)~%9YKMM!#FOFqsQU0%>{XWh<3#jq&b$KynU3@9FYQlS<)y6uS z*hlS$BPl`RQV<X@u|XTXCy4HSz_BbVGa*j%;UEIEjQ17rqqkd&+*jVA`|5mFj2pbT zeF6PLj5^&1Ph_x<U!~lR>l!0UQ6TTrg^p#Y*-uLF9AFxBIf9=kCcjqE8EPl7xI*O{ z>2S%E*R9YR7gf4W8}$boRm}2HrW!QOSwyr(eI$G=MmwfHZ|V6-;`0>Ze>$IbQ*#9@ zv{v|Cte(T9+9>m;*an;U)jF&S$8qA0C><ciL>>1<ymibtD^n^Ce8kR;Sx!>FX>_<` z3jSJ`#w=f|jrszMz*|=E41<<<l?L~ZmUhL6-yakcgrYPi9G`AK)S|#==>+Yj<_K8W zzVTf^yEC=tW8pOTR0jJ=6NQ2w&bK<O3P&w7-Z5gzxr9O3ILWaMT1p(lCzPx&NXy`= zZZMN1bI?}m<Nlas^mn`D#bUm}Ki1`U)Tnbh+N&t@&h<IWJFO1dzb|VDQTQBgs$G?@ zfYsMNP=Cx(Tk%5%`>FSV98u#-RcS7iwsC0}$(s`uZj1osG8La8<;>ELxx`hEaY_}i zyf8FIsGUmME7>c7O}9Ii;aEIv10V5GS>f@;eOLvoOqk6o5uS`$hY!*|+Ew`oSVYv| zk-uRM*TR?4?<G4EUA;97uam|d>lMEoA?`YSn6C#^{Y_-k!H#uF0dZPM`(SL1v8{e8 z+0&_A@ITNB<I59eCM2)Y+9~%-K*6FBzu#s5)encpsaSO=H|7c$z|G(<+ExAqEWT9k zv;*HKIFORLd+DJ4Gh=}*DVT}=p~I>0;Na~lbJJnJzPeX^iB0X8EO~+aRN`m8BSsJy zufrsB`osvX<kb1Gjrw9b`>!icVA^OxS81FZtDbKqn|t@9opW6rEa_7mseqLL9OAC= zC|vOsPS`E^Ey(jji0B7R>_-I2S9Ca)f`3+h)rP^zb~iDmhD{vn5Rv$BiLakzm@~&b zS6}N8$(*Icos!~n$v;_YGpPtVnCzp{r)&^2K3(935|tGC4Vh%l(wdu%Q~kk7^z_h} z^-k9A@+V;ZO`;QZH40g`Pq)%B`^Owu1gG-9xA{0Kn+b%1%&z2)CyG0*0}1AiEBU>m z43(>v;;@{br*<)&#T6cYO4^G`x)XA;Mfot2k8MDm`y|!H+!4Ry`#T{*IMDZIWA{$% zhuASO>mu;(-0lLF4}S|LsNFN%AGTgnJK$VLA>HqD>YJqH3kHh`18!${@bGa+6XMTH zh7jsJOFoddiriLbMl74HhG6zx$?w%3G0X6c8J**~RJ3XJI>mO_i4&9W#1aTsn>&_G zl=5ftZsfhnwXYDd4wVOPtYe?sIr{e2(BDO4Hv0@ronrj+zWh9AAuViXMZxh~aVt}h z1@4#R<;YaPssT>KM`g6HFYQA{DT$YxAno@}xZb6rPOJnM>?HO3Ibb%yJc4QNt(?!9 z8gQ5b*GRbjze6wVGD5kWI3JgLb3UIFYJ3I9P13v{aH##E!2P|0#A~<lLwcdj-WApF zN}>s=K^QKbvz8S;l9X*Cy~?@~zw=T4Qq|u@%$k0V<0G#YQ;4Y$u!7`kUY<VUx5Mo_ zG)hRU6ocMR1+2#CW(Ufj8{7|H8BbfGg@<os6Z<Af9xS2;ZxW?P17oRK72(l<;H>_b zePPA%mHl`qE7RB)VO%b-VUoW#rI&4Kn6iM+04W!!PC>HE-$`^$yb2>y3YV<}A60`R zK62286M24Rf_-e{nE1o*<>?A|{k<F5wi)9;>OK9c6%<{HmA%E3j(egV2Y40&7CD42 zk!UBwq!3ASv;Eq8PMWU~;-x=Jg7vOxvJj{=#&h<=pqADZ)8MBCJpXPH&v7>^FfvII z07BS1W~#Yr?CV0wx6pH0VXR<g?H)0K^HGL>TP^nj-fz^we7z0(uWy7P6s1MpDxrWC zRT_t=%sUbY2TC@O6A;b#ViC)#i$VX=ZXMI3!EK4+!<VIB%6;H_bD3>Ln!u(_@Wn%z zzLv!)KS?5%ikht*-;-6VCXY@#xleCf(l6wvC7r3F9a+G(v@rRTbM4wT?Z2?_Ni;ZB z5yBdo0b**~eHgQ^1s%fKAZcz?dAsq0{qS(PQ1FiWlNh&*wxV9C9v>U*s-#6A3gq&X z!WD!604wnxTR`o=>=LbZu7;}cL-g5dm=0-Pjv7)iB&jff@G(aL`wndhDFBwRjp$mE zEzVYla7C>={O88%Q1lMwFzT@Wr;Ym{Y@MJ+Xq5Sgz=v9q=mRC%RCawEy*rBn?giJy zEI&%xuo!e$gN5)!;aftvF_WQT8fBLuaA0zvC}-N*S-i|ow>P55i5d|ayVqDpwO5mP z(@q{e>)Z|jpTw5mH{qP8wPP`<z>S)FmlnHk&xmov9@@m?4@og@cs55!d6J@%BkuzH z&d@}z(UbG~5x-NL@S+&uBC2*F=>zUB$#p+wl@0Zdf7U00wrHC5qwRf+@?XYffvCbA z+f~4t$KLRHJRIi}JDHK>aZCyNW#Jmj-z(8WoChTCJgj8r%oo+7b*xWLms_R$k%VFe z+Ox&@PW;@&^T2oW$~JgDaHF_cUlUF!r}l$%twXqqeMX}!1<OlxiU(5WlqD^|xzbu` zI>-}9f>D>d0UvW{7w?D=mRpi;p|6Fkg{w-W%#!v?WK2o=rPjntKCX5uZ&8b~Js`Ze z{~Yr%;L@(1A<3dkiwF_AZ`kK?aXab%+~jjAqvP>#`+@aAsC^`EC*I>FU5>bRfdb@@ zNBoWz#Z^&ZOUHZXhLX;|tpb|b!7<Abz`}X&T6Qk2zQH{+-uJ)6_=lhtEL)`A;x#6! z8$~HAJ*}V=72q+>zPMdJGV@!(q$rHGlhdbF?K3;!<0FZdm6~DrnJp{E^w0D7g${$% zp!r-#Ci%TBVc!=E#7yq^njWED7mF+1&A^D?dOLnc$bCe+vZ;)-W4$xxSvWNGTg&=? zRts2JCA=dWG^GoEXSD%kV|qK0x_C(@Phh8%3xX?FaV)#o3MPDIxk|>6*Jb^JTnouh z``Zb>(ul13l^7EWxr7Kv!4!udkox~*Gl9UEsy5bscoDGUD#3J6&{op!bHc~KHxa+n zXW_!ZJim)XtV>PUQQDPF=MnqPaX~TYr9w)JmKU(-l)(+Yc*xAWV#&WEn55z&BkvN; z++J1|5qHijzJ5=t`hQ%pQhW@GVDgzz^#xen#_1Ss3YZR0b1cK$h32%oc2gu@Ipz)e zD_niRRohW53&jDm_~(vg1j(IJ_4g00`o8KGk|HlmxgQedtzp05%C7EPzQ*$V^w}vb z1X{TAn;jkcf{ybgSi-KaC}GI;^NM5HYC+pyyU2;l#5%BQt|C!sR8ng)ia(=WSQx&v z@_-9caQx2xf4sD)7Ax#zhj!+(I`=^?tW~5j?N^Z)5VMRZiP!YmDJ4A2n>v;;?ym{` z#zTL2%$L=HVsaWON;Q}a<4WKlm@lZ^6v?A@Vh;0bF_saa?qF0^0-}3=(Jm|$$OaF^ zEI+{t%->0IlR0N9VBtUTV#00FRN*{J*@)3C(jWL=#ra9RD&>iUR3<?ltCJkdh+sJ? z=7oQ$V_C&nehTegB?P`eH^sbTPSY-mgo)Ob{$_LgZ<Kiu!RmJHzCuF%Q&+U|+%n1P z^>Zs;d{mg|ums!jm9c@uJF=A#Qu@bb?0#9Fmr`<4%zZu63eIs~S+1zN6(zoaveLew zsd7b6<5RSQc2Oj*yik~w(EP0xv5ZnruV~j55(2``jaj~z7^~5D?IK{+%FTfQMikZK zE!ZEwt+9M*eO^ijd31JlEF&+}Sv9uDQS-!@<%AqBtKF=Gcw0;|R~H0P%%a`Y1+>Od z(dVSWAVtbd5zB7UZYwl6w7=t6h6MnJ_#Ulz;ZefW>@~JI&rVFO2FXPS)>voj8k4P3 zEXWLfYRvK@C0STEX2QoD%ZP|U3#QRwN|<xRU9WT=eV0T+L|K%XkeY+rI@Z5KyRFcm z$&JecN6^rm?I2+Bcbtg~2l&fcbP)VLXj3Ox?<m^`ee}8cA4QD-L4aD!vFzG9Ud;G- z;PCFsBQ-#b)4Nh1t?rbJ@E#X!x@XYV(_zqsdNfjKyoTy~v+&#^ZK!DstL0{_Az%>| z@O2CJ1DcMl>J-L^Aj3iLX3+$WWU?j$dYU5O9ri^-J+dr|KCc`j^n5Gzr&%Bb{BPn8 zvp?Ei!w{Vx6GPg9(N;T==Hrl(MmUrg*+KSZJGpG>SWch>zMoopYZ6b2$tjj3+Vc7m zU*}qO4o(v&gT@@q5E0O2iNNE7mnhJ_?J8i+D(+fqya29g(S9KJRsTA-At5PR5ORQ_ z(ISfF<2HREZX)iQVM$pgLjkK2;n&Nt9H;jWQtX%QFe69R?3~UXa}!aLvWIPHA#d4Z zCHUw=_(oF|m7JE0)`yAaRjUTU`EIGL6~-U<!4hBR{?b@pw4p(JSjv;V{#`M?ho`s8 zKn|M-=M}e;`_uNTq7_-7fo-uL<Cpf97<Dx!#5LMUO3#3alC8S@0IL;<f_!ah6Y5gv zH!gV|2@v<x+nF1kQjQGJyc^;osVE(yffAFG#GK?RucPnH;&Oh_o^MwHE6&98LJRjp z7Mc_KZh#oaRlce}voB61UkFw>GG;<XThNF}_bPGc>JfYY`|E8`LJ$b?wqx0p_N%^| zcGLfOPK<RR4lRvSJ}~DW-mU^xTo(7SE!+>}ULjKKM?3kBvqBdt%@^&%PMGP)I`)af z{BV7qa)%_2F74qzf;K3FV;mmyJP>++s@?`A1krABX27+@6y{b8yock0P%!a7s@+sd z9u{{3=av?*o)vdJr&i7Zg+PUAXMQmzKia}#{3BKnlii*F<9CIV-q{lG!-FptPV-mm zvy^xoX7Tm@Cvlg<;p5@BjLw&Yv**Pu-%j!|74|5}z4b+hZF$m2Iu6WUcf~9x&(q== z_fIqKOWgkJIqsb?%kGf+0t4dCr^E9YE&6-28Sj<21kTNTzT@s$N4@<W?nuI>aV&g5 zx)#NyRKadRyP}0B`eEYEWRGfdxRt(X_*xOEM$%PM0ifomB0T1!+wB)?D?uH`)2%R? z^<c)2;LD8m7j=%k#W=$b%kaE8&QEsV6C;k7RbDKF_0y!QS(9UwA=xh<Y-dRJk$&Cn zGv*`ujt@-|(1y!m^^(S`Igpr^Jc3b?UueB&m+bNkj<n-+iqIJ4I^Ont-wB9%CG;#Z zW*@3!A7lZ?&0^+IfAvf;58Y@#ihmBxf5SYy)2bO{=Z35;K%D#6;wOUkLHk}F8@hKd zW_S!fc!|be+i?v%-``7fENA}_Q{7`+NSNh3>+<>Q=<JO25naxHO_7SA+AoWj{5GO> kpA<z=6h%>-{J#JL076jWO&I9tCjbBd07*qoM6N<$f-lAt2mk;8 literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/images/ATLAS-Logo-New_800pixels.png b/graphics/VTI12/VTI12Gui/src/images/ATLAS-Logo-New_800pixels.png new file mode 100644 index 0000000000000000000000000000000000000000..0ae136472c95180723bc7cf222217e41d6f13b0e GIT binary patch literal 20081 zcmX6EV|ZOn^9F5f+i2{hvC+7(ZTrS~W7}++G`4Nqw$t#&&X@H2b)IJjXJ&SGc4v1c zOhHZp0Tve)001CJNs9gi03e6~05Cb|uOA~mDDGAt9~@^fb!R0zQ)f2=M-zaMv7Mm_ zv6PL0naNKR17mlGVG~{eKn_hxR7e@Pa+>w(GCQ&mB8K_i*@1zt*v*Wwr7TzkC<Kp( z-BFHJ_)qo=Glr-#vXYP&ZK&NB_xc1Irhyvq8OiHgUaLn(2CiscR@}4A(@IX9n~Cdd zC*8NWi<kNQ?iehd_jaG_gYk5fFCQZLDY*9{tE1tdVc=XnHF`yjEULes29z^BDt2(} zTTxX0{AHbr@PP*q^y?#IYv?ijEo_wedc1Bwt{V9=B>*Q1^9dvt>_NpR<={Wc*#&eC z{LtG(A^#lq1Aye6t@-eYYE2(;NnlV>$VPugmZds;!UX-APzZ8H7c~ylBvm%c#6lA* z?Ltxh54oY`cErHfLq#JP>>Fyls{gfu`3WEvJcU6*A<(je!Y>%oZ6}2b2LBvJCLR|H zAy1HJZ6lD43%sq|KS|zm`2-01&B4WJi-m;7peSvGi9NPZ^1}U}AS7ro2^MK{`R*LK z_pS5kaA8PbMcck`^obm=f)Pd-^8Z->K_j7{i9J3Q`)Xe3cFeYl_6-e|b#72V{}WRZ zjk#rX@pPGAe*dI;cXBhS5)MP6V&I_6Yn;a?h30_9<C6;@9+?Qs@@Q2!@&@m9?HN(P z_uv>9b^Am}4_A*<`j3$zCSk(Wt^TxM_KDd6ec)ha4w5zepvSsAX8&s7{6G6L!^Fg8 zZ><VKjwuT`<qrT$b7J(h3+egzLz>9w{^?|hOk|cUck+IzYW_B))SE*j!9Cy(N20oq z(V{>9X(qu?age0^yiK6SK2HvhMJyaBKRbmtmpMlR+3OxC@+m4Yxd?D(8rtWlh)127 z_T=iDm;a8PsR81I`uHb!s};mki*C!l@i<0lpq-dnPb-Qo{|UHUSgKdqwrmuh)d?W~ zo0-PN#i`>YN@zHq1NH&+V?tOPu3hgSOpH6T%RYx0{*=ZqHfrU#mdA8Vu=M-M40Jp* z)F≥L|pdq(6AC*Kt2&<qj&OlUO{0KLK4^11H|2OxY0-IVp|S$`5^EUWd)rtA+bu zDF0kQBrFChBWw&a9fLm>YDZLoKRy%jlg=BrWH*^aiBp1q))a9Vq3|l};Qsd?EZF~3 zwTH$~Wh5oQJ4$BH@yz5$(iL9W9;E$W6yK<y5JDiep=8)N&l2`q{!JU<8f21Bo?9|r zyhOwIOw6`1sv18lhscs@JaV4Dlm2rWVPv9OvYkAJ|GaI1He|gc8rc1z$e&c9>R!AA zSKQd)F%}Ugnb;m81!I;c^@3dg9Q(%7KHA!K<Xqb8)VpI?>NRuOhOYzZ|Ad$QOKTK% z5AF-_D!o3WY*To0iTun9pDY#3%s1SSiIAZ9FARp19Lp1L^@)YKvh4U9jJOLRJ`nt5 zA)MaUqBH^~Pv}JlnaCrMb6t&A3mo<c$o`r8Ie5R{$&Iq2U!wQoM%3|1U-&jS?jK>f z(0BKS-l48bqPgo|n`gz9kPo7Z(yP2A12~_5HoBrP+ZpzM0M1NiJYnADH^U)e4=xPW z$%dKsY<wc1a*`9#xeJ^lc!bCh_)MaZ_C2LeXqF{N#Ls-X#0)#JUG^DhtMp+Bjl}H+ z)`H!&Ik@($Gh6b<Kf%xfYNR$K7XPYqW_#a%C(Zw<Kc<|z;YK$s!w>z*{)L4jgDuH( z>b}wB{1}^@R#@3u#w~DQ_WF|djI;c6BK&{|Q>_K!h9OmDaf7=GRKlilWA_WS4u_J~ z$_EGzoS$CP$H+gSd3PIn6}bAVdV{U&JE7ILy=SxcGzYbRU|Rn4K;7{>p9U8tVbLMt zYi^a8iCHIg<nYh9iChg}Mrilox~x^qu?(RUc5TB)n%owl{+v(2z#XHReNpZ&Ml*te zneN2gwsk4u)-uh~pStg$5*LV{i1kkj;Do0rZtb$&7bm#w{U$4^|Fk?ZnVlAHb?sHm z+E#gg2B)1Z?VF8C2PM0JukPCm<sKMA<$D`G<KyJ<f4-Oy8mO)Eqxa<==mgDgZ<E2- z3s^yKk0S5dC#B)l(bHJ3wJ=w2rB^P)HlJ$&nF#@PGKLZYPg%Jo#(M2QBpGYL-7#s_ zp>p$HSmaimpmVgYw|;M}{sR{P!kwwlRpZG~%IG58URuAU7p|kbTK6;Dbx^au;c~SR z88~mU`qZX}{nvGaN+qJ#0-X>TO9@DF%{etC_lmp0--tWkt=qW0Pod|Z%e=9HA9BEV zd^ONcfF8Vzg?9f57RUKgb}Tp!b}`q>?8;^9o)XJ+uKU5$?-Jfj3Bum?QiC%%#|0Cl z&R@)Fut0wE!`F4eDWI!7Wp}LBp|uz8bCP1C0nE2Pd&z+^u?Wx^&|$$BIX9WBprRi8 zQ&4Kw_Lol?B}KgU8X!e_V{_eicKK(RN(Yt22LEGr@A=08xs$|t=e5Y@W#N}+ivx>i zpZ`TcAyaALl<45b(%RNP4xyXauG_DnHK@t|31-~yon0~%=Ivug@kEPE=zMODTaDeE zPJ6GCl-A;d1u>SYNVq-h;nr;}f%)UjrJo|aaNK2Uy9>zR;(q0C@ZNK)qdCS~YI3<n zjcTg>2WOAv!E=^qBa$!9Qom1CX8^ZLA8O$};Zns~TmPU3_~3fnb3pdQO)?*wfw1E) ztJXWoJnRPJK&Q&D5v_P17+nGojE!+~TDz~<IN_O!UAs#mm!T|;c~A~AQva;#2hW?} zSa|<6$H|w@u8(Q>m97hPA_5#^&h(ACC>vlEW#Rr{BdGs1TPnJz?tt~Gr9>lmzS<TQ zlW;g#V?Gkp8+Q<n*6TolL-6@KG>FOk#h!%j!!g+s(|+XI&45c}ktcAn=INHF{iIrw zU!Qt)Awf(I(dK?_R@?|R;PpKR0hcieu?Oaj_}EbfXg2;f8HxT=pXo|QE@qHD$H4&C z(=HW?<<>saI(fF;E`GCGX~HdYs)g;$Kbw>Kw_nKTc1R2$yO`c`B9sk^Fc^Ewk}z^U zPyp_wqg~Z0p;#q$wT$5b(<q-<-2x3hnLpSar73r|6g@`L2!ZVP%(7b!GU1sx(BSs< z+-NoT5q#fyZ^&PhcYWxNU(|!x6U5V%dp}*v-ujeJ9lA4}lh1~Ox18UJjk0<B_Lh_v zzJD7M1S)JSqeL3UGx*$mV{0CUT7&h9r|;+LPK&oKZpXWJnOSb2Z)tepqd<e$BGs0> za!44v4t5XM;{LcF6o4nzJMIWSvK;0MtrvB|2sr7aa&EYo_7mK~pYz29xT^`UH38Yh z?e1)_%b&6UI^p^A6mrONe;5U9zHdF%X<qYMlc#Rps&F?IST1RRTY)TE5u+pfhXku$ z_nAM{_A`j;(ClqJIF!)g#R@K*=j8LgU;F9ro>!tuP;pPPfVf$(BeKa;jy9sR$o~0@ z8#6yQ?r;2t@Eh2=y}%=;vMj^{A?TR)M~`rN^wBOjw}$(-u>SzZr^}y#3h*4fsj;a3 z$guqpCO}-u*vWr<2q(Bx7J-oy;99<v^A!aMq9<d5*mx<)pC@3z^VcoeMI}Q#Lb%?O zRJWH3j-K*tFLOh;Jx@p_jMDOlA`Q3N_D95mX^IbIK^pMA4(ZGn6r>T^-V-L6UJuJh z0-HcBzGJgU-n2%eTy;*cveveU2QE@U+q;cxHe++5&!5cU`MdDWy}YccHYFOcm(>R6 zSmd=N&BwQ39@=6W+6IJ=7c%UK2pm>3=nYrJ?S*E266s@$Op%NJsdyjE6O-=`DvwPw zYA5xQWwQHjiewX**L%WOib5n`uv6dT>9#4D9~b%=PMNBhxsK!WJw?05v~=Zdso}-h zb6C%oWTrIy-6NRsLT1b-iNC!ZH*0Kzqk%atm_+^CR|({9Cd0Zt)g<1^{~r3*H5YN( zZIq1)zy>tR#Xw^-3yJ~i5lWjG^e#rNGy<98_FXD&(vd*@DO1cCe+C1K$6kwlh%!>W zHUzBy9Sb3Ff(X#2N`3e*>}4tcC=nsOtcgif4z|a*69yY`aK|4yUUb*b@89v(4fhsZ z`r&KhIg5U7u$O)I<)wbN%GcL14W+Qf-A~52jdr<p=SJr3tTY2QJ6d+g2uP*00Q*G_ zm^RA|tuiN?e@hA8n3%tT52qpPz50HclA!DmvyE^galW1{$F1Y$EAv?I@yeo!DYf8v z3-IaFvR&D6OD&+yxV??ypc7nyd+DleRrX!iGR`6Et`jDdSdN9TVgPe-pxC#65sL6T zGh5S}=iVm2@{9NM?G77?`+V>HMq=gl)wMkPHXqFmk9YaQ;Rf1F<M@}_a8fWHCno3k z_kk@wqlSOEj89a51qJZJ=Jvhl;icH5a!`k+a7{w^<lN&W%j_$O8WM+?LI8ejn1$TG zgZE8u*!FX@JIMgT=4PUasjH*TV2hWx$Mr!}8%NmKg?s;I&aHvDRqYQH&OyixQcwEY z*7L{K#w;UV;!o}P;9}bXy3^FKGX$)4euW2_48}B%>-Kslf0MO+^o}4iax+l`MzZgf zRK(>3wr3%c1Jp1`>ku6UKZ$vfiB-NDZFD_YS*=BLhmtdM?bp4skW>!xr(pOBR3`!$ za!6EW2H3B++KP=LANfCNNMMoCddq(($V6jja`c6Gy&0J<6np2CFXl<Q`_CU${EhXQ zH?S2?m;SkE<5PTHwd4A4rRL4#OZd2Ms4;%&jW34Epd6S|n7YD`u}<EfH$E?9=!c{8 z?Sz`$V0RYz^bKe&zqR{0u-6Kaq|)!T9`@RW5|FD!-D_*uu1Q2l59^VO|NUn#?Dr|p z&5+b!&Lq;ydP@MwH}O((RyUBojFC0N62^EZ7aJ!jKLh-M>2D{cd)-Gq{y=S&+X@nN z_zyZ_7O<I-u2m`11`@&!rh2Gino&;`ij@Xkq=4o)@^^U%)#eplB15!KRN{?0{fF1e zezUOutXTB~+lUuo)H*)wwU@H{(>NsIsq*eixCh_C*WU{K*K3MN#U)m~v!CH_diqz& z>cAqYpdHVPwOOyc6H;GSeHL2>0&RM=%==D@u%ETqs^;PThywbLuwAW?%|aUAFQCs= zMFJC{eRfj4!ukF;$9;iC*qkw`b*Xy(z3_cAOwxU|*UT0d{z_+|?fT}2-fa54_cz}` zdfiw7MaH2T;TtLHh5M^XynrAEC;RjNYAQ4ZPC_}06b~E*@8+cSAOvd$cKdcmwG5El zzj08~uncIlCZoxwoxZx)ll_FP&+<9)IG*qDwAz+t!z50(_Q_$t;HLNA`AJnS=ePBx z_@GAEPX=K?1zA3fara3+2t}Jh@Cy3Cu7q@YQC7wAzvSr3|13>WPL&!6{nCvdmbcv= z4_Z)YZ#oW#SZ^n;58von_no66=kA_<an#w}4H*v(#GYVy`uy?Fukvm(Ux)a4-!%o* zEh_>d39#>Aw`7wskK6uY!6Q+y+Ze;B8^bMBZTs*x^>F%l>piB6r|?u2C)^ZC=c9TK zlzq|X&O0;$Od>#r@=Sx6YjbRw`UrWa7n3}sl6m~|6X<~~m!hHFT8rPGW2ZemwnT4N z>@OLbz92fT-@NYQKP*jqttt4WmT~5A*79C+z5K{Up$6m!Up#LBhu*ZIV-8u5E!5r) zl@{bHYDZld<N~429y#n*U!MEyiLW7iUwsj%cEzc3VWcsLd~t$s4QrVmA{i4c`HF^Q zr7^JfPqHLP)SfqYV^hx@R~`f=3+-^bQ1R;5V*vnRHV)QS!q$$5G3#5a1oK%liy`ln zeqZdAQd!4B+3bs(XS{VdQbCU3&OJtU@2!gkj0Do2ykaV0;X?lTK>0Kep^7GUpYfov z-n?$Fp(bhgyW+g77RtyNZO<fqn5;={DuADw7yKUgckI9Nz_Gao77HC@vQ-7v$G6Tt z$t*xMj$=&)GSO^s4w?Jc6c;<otuIm?JT1zH)Os_+Yi#eP$4zavSYS1l4{r(w_V`l+ zu9#t45CASqFH-|xK~N?W-O06p%C<vN(DoO+pQjV^tSkb?0T~B=d-PNV#SgIwC-(@Y zL8%8U+7up6d)!F(2nd(RqN|-4J#|NyX+eXVoNSfgg*Jd#|6B}Iy;K(3hIw@)my84U z!U5G^c8D;sE=1t@K@aN159WJu7Dr#w$eo?6b^MVuo@a43#a5dP2{bTfc#kx%nIQn7 z8B=%P5rbP+)wEV&?c#ApMUK&_f<dpcXcMcUF$~RLQ_?gTMpZ~T2bJv*(NgqDjP&Xi zA92N<@^SRkz-mA@&vM}C3TEhj0Kd?j`aA%FM|fae&V_b6;T{I(?rLr)FEd-q00L!E z@q>ENgSpMa@uUws@PyoyaY!yZL<%)Av|T>kn1OUpVe@OwD7M=8?j)JObxgPBRXx02 zk<>cx5r9~=;6Gi?jpKv6B;L_W4>mKU`BWgS;NQrKwM#77^zfLgo(Xz(*tYR8xynP7 z4eVxDACBScSmyY)w0qBp-#@w@aTzsl`63WcmJWlHa&fOdj*EWkFn9W)q$E++bl*dh zYFZ*SoG?}1_5XqmKQ~dM5H;|Z{f9-q*pD7@i7a%Rn&$GTQ*xPl7Quh(kI%9p;qqq= zACzlIP^KB0Jf;xZntrHYIYxx<)Kdi@7S3av?BPQ|Vs;*z=Z%PR>6NTI(8>ZlS}?(I z*s+!F7!5vTnwU!6s*#kwx2Mli?&xP2T^CbM7X0YadAxh2g;Z0#W_5AuxN{y6aZ8bB z1^6{VulrHKkIHymzF1EFUCO<bg6JJh1{{ldog&*f_3&*QIKHw}qVC*n<g=9r8xv^4 zHJdfFsw`gR?LNI$#yAmnf0e|>1oVj??OVh23VYp*PZyET;>Ti<IbXathNWC+c^R*W z<TC+J#HbP65usyRWQ{l{jSQr^9_yBUiXNU#B*1<Gxn7x@hAn))0GM$KN!Wv;ULXA* zE>ld(0nBADwRShJ)<BZ>2qXwHj~u*7JO6^7U6ahw#a0n_LIljQ+??y;{J*)fPD-`W z@9Yn2^&z9gn4I5rkpZDWlU_0A{e$QrgCMaigqBs9cDX<qO>Ad|zCn&$4};5vuo##H zf}p|Xp!fk5qx=4V>SAtp8r+Ia5pdJ9Rqmmk@3}kq2mnKp<X3CqxY*9qi0@<uK^HD| z=A?o?6u+%h2xsx^6+qPiKp`1;5T4!+u@)>6bDO*haEawt>CT-OvQ<JsgwA23ZNhCe z_ySu*NaleW068oUH(`3B<7HK@$&9?Ls^agfB88xga0w;1Q~|7FWQ#P`rf!r&LQUHQ z+6)hDj8X#RHKvhU6>}~WVIEBis3ypKc|RnC)4}@Op`-#Jc;pp!`ivZWJHnec8A6{- zX~(_HYJT!Cr60ebF^G7G34g3%in(|}PNMS+1d{RIJshl>y5ygGDArE!V~3mALAMQf zVPw{U0iIL!$Tv%i4V01Qj2s`{wfxM%?XuKUvE|~uCa6+&jG&Z|#=N@vJ5~j!l!2kK z+(d#v>qQY2Dcuz2JQb^p*6tQ|6j$E8Clk>RkASo-8UX%yquBnQ^q4>Wiw}0z*)Jhj zJoPxr%|czH)NL-7!vQL49&h?k7;E>Hfz^(<iI#Vxp1OE7$u8SQHLADL*{S%<?>tPM z<FO()pp^(9OtHW;lZX_|P}Ah-p?y7m6ZH(<CyxIz@?WktZ754^;0>d9=DGBS=%dGw zE?TCHoij>64n9l_J)9l~EkYcgT3MsZU{w93MK$4Lg(B~f`G>#dqG+h}c*md4=Q}+G z&D$VU*QONM+5QECi4TT3cG7~=;-%R?Q52ZHIY|D#bO5B|!)`R`H)X#O*LHE#<*cNn zQthDlHF!=z3=anoUTZYu=arh~@s5iF+9sGJn8!DIemyK<qvIr?>XXKxhdJJNdp5WC zMx}I7?09eZbBSI0JDcN05ruG3WY3LlPb;YVp*n1)UT_|`pwruDf2zbWW#>Xh2&=&Z zcV`KJ4$bYY#9XfWv$XG~Q^1l2<{{9>v01<|l=EH++!R>8h^^tp<7hk8O5p4)XF4h% zpmIHxMjRq^bV{3Z@1W`It&!40pqGDMp4wX9G_LTr@^2(tOUC%EENsCLGL$t{%|{*{ z<GR8ogRT9P_`Y2<@N(M)F1jFhev%Fa;L<Nc^kyO-Sc~0mViXhBme7TN#2<ON^9e<u z|Kb{60X3Vh8GEAn)L7_JZ|jjo1@(5`8U#1&oheIzk2V>sNS&-&8!sL#|Ky_ts-8Xp znl=BYuSZ8aU|xjKJi@Nss44>AiTfmKn&GDh|KbVr5kzAnRj}?xrk)*tw5NOB_=M5} z%Nw>m!`7-%FvvIxyrM<#ipIa?ycWC^D!qD-j?u}t$T7L8Jx#8sJ$l8H_;+7=YU4jf zK4b1)QRm=jqE=*%sCnhIg88`VvL}BPuwt2PHZyv?;icnz@-%~Z-v~)8$AQ{ypXA%+ zqppP)))lyis7&E`ZU2N7iXO1~-bEDBc+UP;&S}-Wfw%gT3M%nu9^D-*|3k~=&2tuB z$LrszUw_Tm6eE7?H~w+9<D+}j<TNckwU>`2p~2OuS6r3oX>iqe-1Bx+Hu5<U!(BPc z_PVA8K=-PTr-!Jz?T7GthHRurJe@`o<nUe^>b2WtxLL0*C{;!P#ozK8u6nvQ=vS70 zQn8CmS?%^X1+3I@4pl3ZU6*x?J_%zj6o>o?%c#MB5?6Ils>fMaFQcs3v&)VGO`Tti zFSJ`Nh0bw&``GUQM)jlD4WTdJ6MJeKX2j?0i|Xwl$f5QP8!d;DL*ta{TNfIvixbEq zHs`Q4REo?ut$yU-`3w$|EH0tQhs#8hx4uhI*<uVMJdbxrc{%JA@Fja?<MFe3NjKm< z38`@rBBi5(`(41d%a`B7&s;#fzoC1u%krWS9p=KP9>hv+=eq5`dv}tFbJ!p)$(JO` zLm2I445E1{ubUiv<nbYpN!f&Y7ua@%xxpGZk&C|!)Y&Pn{(AVz$VS>t_Eher>jdf9 z;Bb=&41Y$_uO6xFH-z<NkM9AYv7v`^P^-$P#ro2ORz(XH*cSa#a0YQW8~8-v*nK7e z8J<2vQ^~;Q(|W^hDkM+fO*`}5H;z(VNQ|$#6bXMZi$nC<BmY1lakmizwrCk>C|;Lp znHMy?n>e3qzVk!JUaKP(x8m<*<3CRI*iXyX_8O=s2o6lLp-amNRanal>cgW3tL(lu zRXi?Rs9s1_DVlfR-4i_Z9alnnts{pZ;^gBq0v^I6u3AH~Wkm!kDN(Rs9v49uozc{6 zooH0_2ov6awDBK28LtHE%9etXF)|36mNNnkb<F?#CjX8ZZ1Sk4;x3^2RhKdWt@Mvs zArixa^7M9gqg3`4-xq+-PSH2(q$&I9N}2`l<@zd3d$%;0SgqdSF>j5ol{}Fv)PogT z;U@&i$^fZ5O;tB-haLSE>VvQpq%#$3*WuTxCAox?raNmHou<}KPA|aS@E|<E&-?M$ zlmebfLf1VJcnZ|+XdtO+3k)(Jg|2hz)CNKXLAOKR_;`L?G#e;Q6*{k^rX?QPxQ0pm z>9P2#-K<(;|5Y7NS+j`+MIoCa=WzLQJ3NC%K0XilnKEzTRg7M6JT~gW-!36)@fDrl zX047W_?dG~6n7u)iO}nR-(QF=DGxEC<zj$OI(v|$UMT#^c_14OcOYq$ACt@x($GwV zCL;1yY9{h`Rb-++!1i<70U8%&oAieKEwe%#)DAT84zsq@Df|-qY(OJONB>ZpjMt^! zKOoaT5OCwc_<qdqiBO#Gx<p(eT&<es4wM^tBo+&zKJjQFzSdNEv{d9Q4907-YZqv9 zxW2fgk8=P3xB?@p6gClqHCOHIvEwJ-_iV;H8Rw`^^MB1V>6rNjyY6{{@944fUlYm` z8ejE)X(-c#{;As7ru&VAm-&GgMZ6T!=&3_3ax(vnve@5V6ExY-Mx?v%!&Snp_e`AN znb+1J%VDh-pW?$(eLD%}N9<q#^sQV@;oK)|#(!AR^<X#P>fHht#qx@CiBQBMI~ke2 zUrp9}jbktMB3G#<gom$6@rrefltW|93=i*okF6K@Q;gaYB(zV97T0FGT3#zrfar5L zVqeZcpuMRf9)t|A4;ANt&!VkjJ|(;B{f`Uv!kG@-xDWO|1TEk`Fp;em13zBjt)ngX zovi%4|I(Tic`naDGu<uI<sS7*P<Ajr?xd=)il>`QbZB==4np<SysHrr?(8KE);-_+ z$C<U?yP3%=CxWTWLez=J)IEek&`Y)B1j1j0JATvE1;?_YtNa*&CJYo-p4BrjUcT+F z0)Bp{4$OEfvp65@DeQJqHrjX)I;2)RpaY>U0=8WBT&K}hnYb^f54Wc{aKwa9D;SwD zh=XmrN&15`jiu{pQ1C9SVWPt?e3rLNJEye+l^--50@w)xO8Ty4RWItBnAmneJ};Pt zvgc^=gkZ!J+Ghf?cbaXpXAT53F;E3z036^<9~WwO?Gg%ZydKC@!g_4a*|jS(LLQ;x zJqu}l6YBSmR9rY@4BFXn-ws}mLGB454*`7sqjW;bCg7AJ0vtelyJt$5z0Qma`>&}{ zi*XPAT}C4U<@i9C6z{voJtOZ`6~3r;_Md86(!GtXGsk!Vd6I8B2WRy(S9&j2)cm>w zB_j$P$OxPW3z=#kuCXbuKo>KnsMmIb_*;t(0N=*g3fpO^e5YNCUIFD3EQ!4^H{075 z8w=5Z(|Z|S4Aqxx`9d6ga!!kG#KVfT8<+5?%>Ad5rlS)^O@d=;G##oxD3|!oCCb~m zE;<EavvYVY6I*sU9gH~6yKtO!BnT^zlw^Gv4Q{@XRM6UGD>FFVm?l>b!Pdj#7ni*L zYZ;Agm12}%tWrTq{_Ba6J8X-O%qVw`C$}xXt3aiHK_DO&oMdl*xnUTWuaQ*p_Z<n# zey~>ge}L%(B`q{Jj7wma*#TA0H|2pR4bc5A8TgL+(fp5~4dy*FS&nWkqFx~Wd@9z; zfm0Kg#VFdyA8^3^vtzdV61ppKMp+y*jC(epMG>{Z0P8uo6H@5q{LBUXGF*)!ilN8u zrg=`dx&}K2@v;?g<tVg^=Pouj!`0AUhm^O1kAPLJ@L6n>y>sI3s)3Y<3LuH37VLs0 z9~{w}i+yK8)JCipw;H_gWvJ(13##H*M&R8TS@dHmDsdhr_-}?A%QgLV?I(4}E`#{p zl044P5?TN<tDZJ?55Y5iGjwmd=v3)&%7*LpoLFczKoMeKq4<hzPpm9sz+`+i{M7CH zHg&Jm+>n6rkuR6NR}KLRa)0#{E&G}*+H*>D`q87cvKxKj2`LhJ;Ufm%Ch9`gAcpS* z)ib)EQm}#4I2gdZ%TasS0n3ddkxpdl>ltJ$@|f=}osWLed`I6L1w<fdNt1x$cqnN@ z(vZ*jYx}bos*gi-LQPu*MZ@*u6>uzSHT^^4Db9+XaBc$lV=!U^_3_8!<y%Rv1#igg zKR#bV86KpiJD=%prpQsSX}I@XN`4!qE#YbsJ+y+NAC@Sy)DFDo*zgl)!Di7?ob;Y6 zx!^lBwSKgbeH?xb$pg<1RhpoCaiMJKun2V%mU@t2&>1Wl1?P@*)ib-cq~}YHxDfsn zN+G>0>PMFfPgTUgG^AIRd)xA1`Of+gIr>Lb9Fct_xxX0kgZ0Yk2$GvU4!mJpCI~Q9 zi@i5YDuW^jm4*?%TRb|+(g+cd#e9F0<>mFPR1DN}QmU`EVoaogsA0G;S`+*=0`p#f zxVtxEW3wMPX0R+#VgM#+9bA{x#?4-!v&R<b!?bs8@CSOw9aeZRzxQ{e$)!%e^0i*j zfX<@_!~4bS#);HBeSy;Yd|Xuf--Ec@>*FEpXy-N=$W`f$kjh-OCvRgBhw1^&<aXhp z2q>NW9s<DH?q3aSCq@?)a&qI=GYP;Vc001g3D`2FK_$J8#AU9!A$eGnLhoalX>Y4E z@v*swD3ezSDm+4ei2bpYQ|=OxW6yox01|+--#}@pe&0-W+Z;OJR_>&GjXQR99fPzs z6>(3F`>m}!Ttvt%c#Szd1N%q9Df=;Xee~p^O2)+mS9<iYuv5I(U{c0rgTDQKLjmqb zR$f!7zAka={<kMJ`z!zZCU~nZ3TZqVt*|j+FW8;bV33}=@+L`$Av<%rn>%w81Qv;` zoa2O*u>U!3<nE8s*hdCA9g6RFpkJ%T=RH;ao7P}m8Q#k(D#E!jmqb`0BDq*F8jv3A zWEj3NxKe1R_?hYtk<t;1PFU%lQhc1d(GkZC%8i-<YZ0qP8?dtKIoLi6EnZn)Swt(= z=1Q}#452@c`BM%UKJ~}Nnt7$(-_<Yb4p<n$^#;-EiNqqc15G8e)l>VD`lZHd{jP*= zl<!7n?xUOEY6E}hEQH1sAAijz7$yPT2p#%&tc_OmR22n(WOR5F?WZ}oQ9C<n*iYS4 zF61W~){++Iuld^=LZb7T>Q9-{5fSfnzr2t$s$cblZ~U?8Zp2iI5-HC&&BhI-1ir*N zckpny8zZ&292A`HrZUk1s;U?VF@5Gwvh{kY_h4m{X<MHB$3ph7My>wV>bM(PpxU@f zVpV`^%yDosr(_teM!lHi61ht|$aoo7HnS#t?Y!cx3XZ9WpImIIz6+vt^Q}VS283QU zpCw2V!<Q0peDLdQNJ$SgTYmuhnT<jiwu-cD)#FJ~vC7|ytAZTpwB_W61?EFzD6c&U zCHrZK2%Sf}1Ug|qZ-nN&^N(1an+n%Z^A5F#{up?23Em^5Wkj61%{-BFgVnI3vbH*e z@~egZ6_J%g#6H<@7h@BxU{E`}nldfDeq2)US_`J+$6rXr^5BDUQom!Cud-$bEUl(o zm!&Q8rFv^PPznp{V$p11!mNR#)t9!L+X4;UQ5VzNH;A?N?~pxtp4u;3C)HI-v8dqF znSAE2%uEt2XN(oN(!0)?E7~+N{_B~$^alu<_u=}m=MROs=wb30Wes@~3$MASxU3S! zb|mJ*&&l>=9FRM$)hVD2P;45lTpgM%Tjj(Q?CgF#Ryk(waV0W6Y#%)<Mq>elSrgUx z4)+n--``F00(Hqn$vDWZy%MHgx0FLOZ`k4t*;XnNowgIGx~7Gj-Kr&50%dLFw^f=# zFU|k5HzO!|onj9w2J4*>ur)0eU3X>Zf%!qq3A(z3s==F!ww9pcymXXp_ou*Y5XuD( zNyX%NuLS(ZGOUYcK?y@2>FfIDnIB=ypNO1rz_D!gr<AhOu9i%jP}5rG@V{Uk8wU-U zU)Yy!^l12c0O$lpMBn>HN#8{V#lS(!j$@PG_d^xP$2tnxH(X&E*`h<zUnp*a$Lb~= z&h>vkalP_6J31WoiKAOql4$T`M`U0cRjr^f$R1MmS*rO)Y8^1WSZ;ldau$Q~Q?ReM zD}y@M+5f9govtgp?<HliA=YyrKDL{+vfRF$M#U$;^FvIMNTz17D%&Q@=osK$_}iGb z3tZ=xSXk9_z&cx{HPQ)#q?R!9NJ{mhnM<|BR+~(_g#SWmXr~uq7icb|!1a{<FB*5V zj+-bg3EfMDj2i|qR+r%*fa#I@oXE^gv>lWEJuvo@O2jh=Rew7hzD`11QjNV?hMBn= zxM~k#_WVP@$P>YE>k(?-RJmMcBKJ`g=NmI7rUY{MTNT|btKE_t;xjee_IX}fN*T{N zndXDTU7-t&y=+ow^*~JoOiO9QlM5rlpn_swP{|1G=rSO_HXU2^G?o5X2YG1EwW-AS zZkB>9jB4FcSRq=AJi8sD9&<~|9xm;@-KQwDW5EIG%q};coY9C2+WY^BE|yA(4N){s zRSHWkw2@Fj$o&qD<#!ZLr@n6X5I0RW#IUiY)4Pvcwpds*X*+YZXj|sE^spAmXW-G^ z<c}a=MuYhFk$iqbC9nfP0|sRcvQA?VGx}kt-3!^N`dstQ6qY?ixZ%bV{-dh4rxRvb z53QI}$Z<m<wd7iD8m5r4X}EVQEz`k2Z1|~K-YO&3XQX;@8+!umbc=VI2l3=UX`3z% zMlDKFC+-4`KK3lX$>%<|kj_^78_z;!hTmBtH|&jbmH2ydPTo8EsEuLA{DEsSDxr0b z-;O8uFe`Rv;~X^WUSt#tS1k?9JQw+<3;eIk-i(hl+tE+5a@sF0+ZSm}F`3t+qOHa% z2|}ux9q)7cf4Y1DJgrjUzuBg^M^*I6*NF+=e1GOAV>BL>)(X{!9Ljb$lb)#t0<!1S zJ6FG5@Zbm@=cwVt>=-CA3Slkgc!ltkpLpf&Y;Sa_Z+P&TdiLz{Tjd;9O-*Wx0m)j* z-nO6k9Uq@RFLVN$5IY@lbWf`^%8<+5JO&vO0(RNmG&pQl$zS?F<Rg%}o@}uRr*0JV ziY_cgla_6ELBkcGb&5UH1f09Jsr%5s4BRgryq@$?R-}Xtx-m%<+tuSl-(#pZd#OYo zLUs|{vrz2d0dH}dx24|N1c+k3O!?sQr!`u(wOFfF)zIHT`lx1U?+z}H(M-*o$q(Zz zA#0(rTsEk|<l?%I@eVDgkIK9I>1=doxp|jMsM2BU0bCW#ogicD&zoufvr&eOo|ZK< zHwPCk_P@D*i(*KP^Mc%42$2W7nu<TT8>2?hl{K|A;H?Trfo2;FBsHV9y<;*~m4g<< z4j2ka*y5%61-dvxIz2~FA^rHY!;#cXroBD*$(6`OPrvgK-%)ff7emAR@H?d*w$av! zG~lL15Tc=roY(AK6fPQ45KX_{9t}7Tp}M~q+4h$HNOm8L0a*O-e!HgC!?%{G&vHGB zwTo@*F2C>Bm)MwJ`+8v#GsIe~2Qk$a2S0S&tUvTW<38Y#O~7{wN!d~|&nUGDtN1u; zI<KUd$h*2T-HhjL+q+998OI^RR5I#aD2L`Bp~UswwA>-S!NitZE;hBKu4$-pkT0v( z3#aV;;x#e-<D3=7fJaC)>EJ%na6?zTX);6car1uJeW~MlaO?KL?53kkc&~k>M$Ay} zz2IE`vhR9$wWan+u8q*&)5Z&Eps?YlX5Th9w;=`Vt2~X;Gu-0>&Z%+rQAl!MI$9Hx zxcdb_1g}>KFFQDHNQDmbXfhfOjZ!&8np??_r0RDnvr#UWd9f`%h|Ji}=1CvaN`K*5 zxDh!Wy_8xcnO3@m%oqaX5tfG48#sTp*EV`HiR8n_RCCH6TzP>7;GT^(@0#tqA%*mt zNMb)<MPtutAHEw`LY<rpbzVKFQ!hvfqBTy(w==us@+t*Udy8i)Td$Q$rkQT5=6W1E z#CQ4ZTqTaD(9rVpc_kFLfCF@K+wkP2C$Pf!sk|G^?AYZ+VPWaX-dfaD`k^<1i-`N1 z=sRPJBotL={^P#+0avXO{($b#+l|Fr#N26#I>K4?;A{cRC-wsSmHxSVtjv15w{o^t zv47<K?jHIF0kX6^M#b5!#jp*$zbm<ZYI$R}0hU!_uYyLTTE~4jVa7BjCceuPgLp^R zT9XQKUK!t3j>zF@4+>HM3Q@ZSRg43!3%`(r4S!$88*o|9R?JK0SfELukS3@f=vm*s z1{^0qQ`*!jUCG3IVQOT0i+V|j4n9+^uS0~`6A5&$BXzwZ`3Mn8vbMVBN}W{a<6E~A zYbb*o+s(krUM?@_F{qEUlP0n6Devl}oS)}z3q`qeUHy_S|8O$>BM-#(^p)kh(yV-! zZ#{L<$M##~Gg7Ok)I)BT<dy0ZszD*p(f8?+^>U}r*Re)EfG#q&dr~v<9%jMZI9VRJ zw&rcUBpP|t)TVme;hhm0^^t`>i4mh=@xPpbgJ4yR0eUhx;ItezL*obnloW!$ut0Iv z(NR$B2f5j->3U%KZkw!-x~#v|5>!ZPY;3XPk)=i<z!#{0ViED~rBVSdk&x1R{BeMV zvzVlL>)OPS(5Y2Z<W40K&E?EU2guQ2eg<$p-Q5cB!lI6%93*A`%|Q;Oo2;ZdmG{K* z63(SUISqVNn2}dAw%WqN9Yod*ez~C%#ay-mQRqDzyk?XD9vMexv4`&^iz`E5GD||f zAaVOWki5{)U8>$P3g=rc6pqQ;4UwyWftyOYJsLlGuz5{^`J(`s%yajh5_M$*VB*B? z((!f@pmA&t1=zuUR*}clsBSw*bqwYx81YMfyk;QZcgQ@b{2~n`!IlYZ6RkD&xkbb& zq!wf<DIMI`OkX44*xbd=EMT<*_>sV!j^>8Nx*Vu+sb*&aNb--WE~)iMc}?LzE<g_u z0O0;5fd(wOlA&nN_vm0d$?Vb~6L=pOq@MC<k*LRCpKo=@`yF)R@FdCGJsqdwf!fcG ze9*DZ$Z;gY`xoqUu-gWRQqf~X0R1k1KImS@UYi4c^pk*>$yG=wJ@l=<Yb$NzPU)}j z39oWK$x6Tkw45j(`NwOsN1CBCb113kX>6LC8n7<EFTTLz`TR#1CS=D;?daB}RIG|h z3NbKLVa8aZo6XA+AjJ!fb^ht5hPymH4y@nhhe2`4Lk{B&uruvG?rhOTs#LYf*!(WD zxVGxhi5Yq^dP0uCq0AXVuaRF8AfY-gUr;%fPp%+(DtA1lrawYLFGiccuI#zJtywnH z<%UoyG}3o{ey}ZoWz|8XDBD(+96DsE?~A^M2ZZfg6Y)n~c>u<X;RrIZ;Ln}H!Np*x zJ_t$2$oNl()35SZi#(c7#Lr0l5?V<ZOVR%Qg;^B``~U;+@?SyKw7(lSy$>a=Ag`S0 z`$Wsl*R_{1T7Z6$@Vh+|8}9@euN*3&7m*nBwi=<}gUVV4gMm5#yJQOkHJIH5`)j>} zwg;--@7N7WUa0s}KG2beYM`Eb0MhWG?%eVDuF&p(O$kuzktT@9iPL)`5A&LO%sVTD zs22<VN!fkcc0aL*cWj!jjyyUX<beT5h1P}4us_fGL3<A@{A7Xv|K5<x;ZaAuXqKP3 zYZ*kWjr&o09_$Xtc<=3XvH_ADkfSMbv7Y|WYj!>SbEz>4cm<oK_Fgz_o#4<`dUv_s zPAOGE+i?hv99^2+(l5H{#<qOKo#BFiG9j)81%dkZ74Bp9EWi5B5uPV_A^hZnEr`E* zoIYP6i+w%+LH1JYwNCDVyw80F1@`-4<|gKn);HC|9zkr+D6>xr4*+SB8f?gT;~(7L zbk~M7Un<3G`BBgzBs@8?C<favwdZMiel6fbEXXvpb&)X}K`w!S6!|FBII-qQ<n%Eu zkkyQbIE1l@9lKLb^d~0;USY`Yp(>H)N!55r41Wau9w4^W-nM$bY0((g>34v2i3Hqi z`6Nj?I{)3S-u<ZG507cKyJG<F;|tUS{klE_iydhhgaF?X;NP?QQ^SZws2#xAo_^Oa zY5$$<XPZ#PDjEp1=tKn8gMgIAxviFA<KD6a%7<MK{m3gT@ArAH^S)W5W?S4|JzVM( zW+OzEb=ypYl2=Xkm;Rbx_G)*dbZqxn@2C>>dpXcUf}c?N%73}sn86B`JjMgS?+$_R zpX<r@mTb6p*CQ+zM6K+Zjdt4`gPM$jB|{;+PkT-VZ$*E;R~(6gZY)_i9vHapk4OL~ zvK)J^0U-_FkG)D^jaTYJSB$v0CM~(~*KbX~?gVTnF0~DJ$DSDPr|8Q5hd&ivyGe*z zO|@XT`Z`xXYo*6nuSdCTC6|X3hp*zb{vKicCA6jR3cf2x+b^G&cxJA&4aqz0{YxX5 zpW383QF;%o)V{^YH<#~srDLyPXNP4uA}g|!;vN-@?iJd{nj1%MC=OS8uTJH=I@lXX zWLXJkIq#>TM4K8!mOE)RP<u2G!2XE8YGK(ujC{y`L@307jcpNZxe|k!O+F^;{bu{+ z-op_uxvy^wc_o|2!z9|9+C)#I<W7RT=3+>1WkI}TFC(`B6YOT+*mA+4;XQowU)zu8 z(V<ZN8wCAc2Cyy$L+gh{7(h@u-P`~_9bVYDx9pvV(nYhg?mttd-@Itr)rVn_C)<dO z77Coa?60X-BWDsSjylR90GCHTyy%VD$U#txUEK;xbTRu)`A1+R_Ye(+Z1<v&m|^lk zNK)BGA9;G)f0wlP4_mLfYD!I#awm_~oa7XObtMCRwN|9?qXbIu_Kei(NPu6HqIy5V zeB|8;=bm>(4A9$V4IFjV)T!8!hOm$-!<fqII2&C4j#Kl6a~=pmZ4v72yulUp#4ynz zS_bSckb5!XfbA&OHhVW!ua!aRS&m)DdiJN3(BeY_n!M%Y`I-`qudnVd`{6{fRRw?7 zx4A`*P!;Zhf$Bx}FvMffyuP2kO(?fr2DpI5@^)aSZ>EN0c?}0tA7iXCmA}H=U)>Jh zjDLec)*EdOd-!+-9!jjwSPQUC0462r0nzQoJ{ITXv41geIi-=HE$d<wGa~TC*whn^ zs8AM{rtkm^gaH~G8^t>fW?vH^oKHO@xu^OF8Io>#cN8+*k8N#yUZAhlj1uJh@hHS# zIOtgW_52Emb#Bm|S7>@YRUaE%Y{h?JYAcf<VqOkXP+TP7+avN+{SV27fb1CvByK|I z;|e6d#LGWF_K^y9IMX9L@47j5>^TTQaq$2c`e7~Y>3A&1?x%(b3HAdu8@rWIB4-xD zAf$VukI))$KH5w*X>oOhxI3CElLl+2o_Ig<%-||R18$6Z<g%HFcb$p5qza;F3#OqB zd7R(|lSFKrIUS`$4&H}K`E$v2@kBBW7Yi+%CJNdl6D}+J@@f8G*S^{XYfgY+oa8_~ zf?sSL5o0klK{u9;5rNuai@OU0A%C{Oa3rn>2%ACNyQAM$(<#-GK5w2RmL+l)-~{WA zoW@hk@SsHAVi0tZIkl~ZlIjngV8QotBs&H<7>#?pr*QRpEP+D=h5GFP@&LxKCPKO! zibvtu=hy0igJXA4yI?R%filfh>D!7??l~NedZ2=H-Vc3;u@g^6Z-a}FoX_T!nUciI zMi&cz0yFRCv8cX)#Y;S79fZc}6FK5V6$ZgN*Iw_F$3MgWqGEd)Nik!~KHh!48pvbr z;aRV|<YGL0*4f0^MkWr8RlfW)z>CyeH4p|g@_V?b#Bg^Pe~8cD+!s_tY{E<v2+{6P zIE9YsNA6^@1dA7(;UMj^CJ2STHKE@+K(fmGnBgg+4&F}Kf*xqSk0-W!OH}#j<XCU2 zuWma|or=tNx+3M6B5zkqe8k`S?8t=wg1%WqL1itA7!E&yg<{2ggqj-@merKSGyxS@ z0k;<hQqlahjpFb)>6ngH<liD!Ja1%%WtI3ykdnB>!X9fybT#=SKWaf&d)ysN7=Q&3 zMYQkk2mlV<uEb!O29>nuhliGA+Va)=8<pp6BwY=#r_R`W^E?dkaB{IRZj<`k?Km<@ zJi?hUoO$n!!7N>BxVRU+o&edaZN*{_cXfSV`{5>Tf|vjMSNp6>D*k0`vQ<(cBp9qG z?#*MRYoT}e?g~0(=OMlW8=u*X)Qfn>?XeMo3e*+sy@BuhY@g+~zpz#ve+%ysy|PZO zq4Uzroj(@~dtk)B-Y5S-$5`bjxq!a?EN`ufNS<LtgifelF~~b@EZlpqxzj~ML3^Kl z*FB+)_><^+N*LQ}oeDW4j5RQqP^oKfi19)7QHK~CxRE7Iuh&3-auD!r^?Tdwa~Qyc z{s)C&ThjZ(Sv(IXeV9!Dk1e0c1ewL9&ZFH<l0vAxiJ<ha#|=6bNL}(KWcee-S5np@ zg+v4GDc~O$aB@UTD_X1XY*Jr4U4U6?GXJ=I^oABPxhEv{((9$rh%O*junzufya7PR zUOrCmjcYb)2-j2)XrD+F{Oe@&BEI7%{`tppX0$8Gxv8S<#b{%(UgeS~9qqFd!q4i` zuP*P1T6bZE`cjEQTOE_a{nH=-FjVSI8!yRk!pY0_1{%=FpJRf4kUtDg0@$RyliOVt z_3nV<(gpvTS&@mitEaD8RHv)xV21zZX{y=`>wgjeAVYJ|y?vULM``qS5H!?Zmh5Cc zn`=HBT=$*@I}c}O4z1}T{&h3~Acy?WAzriBW)A7Tb^a3_I@X}d23Q#~^atqULugXz zEo^N+&hj~}AIMBEbuaGyf;%F()GO2(TCraLIuxN}?QuxocNuCIYauTFVG;|17aU#p z=H%qqjR;UC^UM9Xz?Av-$A><x;9qe<n_4Vx-}om+1Q_Ui_S6ba7nkHnbve<9Dnu&9 zc-`{4D*8jG`n<-h-n!h9+zGW_hFpenOM{&{9aS>(_uGeW)Aj7KmuU@W6Lp{RHC{Rb zbaJ}Amsa_Wo*x$%HN(~~Gx=6`3nrn=A3bV-<uOCi0t1T_3E7>i?I*Xb-q6^(g9*5i zX;iy2=#Ojek1bPBL{>gq?7l}ro3r=8na7TAdP+Hmt^I5A__~|z@{^m{+2ag@ZU>he zo%b)#h*vMnZAfNd{O@HINlPMC)+M9-*B^?Ms<aUu>#r~#{5}l%Z86_)-8CvaiY+&q zf-M?DdUp%PW%x~eQ1b9uc(HNpHXt13z*Bt!|4sLRyTbD+*x(WZGL*zSNdKsKC8<9q zAEYl_#Iszt)Fmr#^+3lusuQ2hHab+G@A*zDI-}o4CT<EpXn&s;oCH5E5zNnB5G|ri zf&yk3@q2Lc&G7NMV+P3d9fgGzeboqtpoWfL#&cmPoi_%ED^4Ry2yCM09`!1fFdnmq z?@1x?O*^+SgZE4v!vTks++1RT^toy3mZkT}$98X|J0WLgKd+?Anb9*bC4pTGgWhfP zl6pByq)3A_%CZxce21t1+7v>zQ3%o}74#578#KPIaxt7yTM9jUn4#E+VVg!4LIYXQ ze^rfQK#K`y>yweio<t!TW)cpBXPv-3|Bjx6b5-<+`ojPQGPKjs=y&zveLC`!_S>z} z-Cx66gSC5&hH+P~Z&6UQ;s?Gqm;74HRRzKaywi_O+h8e)(9L8}MQ&e*ho_z~g>c^a zq^Xld{7)f%4<uyD!7JweJ_6O+WFOE8SLj@Tk+M8r5+WSLp<bxD+exaF@dPxE4m?-% z@^Oui3FBAt>83c^5y4fyP<@nFtaPmKZ^>y~Z;ZJS*c^I1*P_M)(}Z#+$4C&_3gTjR z#V_9Z?-D<ru1{;BBl4WHpc42=Ps+4%3#%5wlLfr6n^Zw!@|*pxXHUEVCDnH=ww_3v z_Y;>qlbSvq7B(+XAx8Fg*Uxsn+*%82IaLRquNC5+77>$e%O3M0D-mR85H+LAfW?O; z5Ux)2#n_+^L3HQEbccmEkU{4T40QIW(Jw^|cPf){GG4pA{##5w$I2;y=F+DN@i1-q zoAWBR`fT5|xo~A)t8z!*DD_6<Y%rC8o_c)uc;jht%D!}4V2TE7C1O%Siz4Sj`+=!B zgZ#$!6EWS@m@O@2sF0ueN886=Hx185Al3rkfv;E9gT|gu7tuh?cDi|HYz37krEd2s z;RV6rfW_nB^VnLDm$<Fq)U|i%@7cLaa`$FD>B0Ni!{|k*Z3iI~7|5ZDTvpn5<jTRm zZ4-1ppN4XTx}#DlQb;?tw6ciW;B9b9e-naMYSp;=;{Oy!ih)bl?K6)Y29aB*eQp8I zC6mt<miFGrhy_q$&XV#ve&%KMKt3<~u-DJoEk3KHGb-w0L$|U8+Ua6ftX`v!2w5%V z9lxg3;s@khkg^IS?y%MK)ws>M<9HMY|9PYs?Av7_gQR8az@1pmuguhg7W6BE8>?S5 zO6j?N)RItd2MgwmwaQ>Q4yzc>?ILB4S?js<CQ^@6yhP|;<}rl&VDtpr`($qM)=kFq zja7iUrN=Yv7ht+38%g8c#3c$Lq64*+p26Nx;FnxrXcd!#kls9b{wDTXhU18H+R{Ts zt?eIZ5;~dQ@5sbwILF;9AN68S+WdEEc<l@a9BsF3tZRkk?0<s<Awyf*y)2=P()(61 z@y;JpN_goEn7Zn4=i7GPGL21LKnc+8+<wCW2zeBU-OYyRU-Kqf?Rb_q$zQ@fzw-_t z<OIy7j$DxmMn}Xnn}sVyhRtS=uB-q<<DS7}BPr2@_==0F?Hqj>&=8?S{Qyga4DeQl z&4)j99xx`?s&WFvObJ<}LvEJ7e58-X61yZx0UP(;BPQF4z`RA+DPx-q>=DjZ6905O z77q0oXWt4UGHCpr{{<}!((}UyH5dmA!!iiJTI2nS0@I#8xzCLP5g^@f_?ai-LyR&x z9e$^cr$R6kmWhVCKsV8A;)2dI?en3hizZF<t`l#BnH#(Z<0TGE!)KXqOV7HRf43Ee zHSKsE5YBVZG`#+cWe*$pAV4(X++~?vS%i!1HPlLk$1E@disW->v-uX8nG1TGkZzKA zUTDvel;I(T0NH2FP_^cto&T;2dm39Z66=Hv;aB1E@7{CJv`3aa`v}E~Nq}f_kE=<Q zhk~2}i|9BHv|Q*i@zZALhN%l$dhwWqH=L(Dm}>l(7(kqe$AO7Qa6`C`9YL?-Sogd; zvv3a|6P7EUxj{3kcn+FSl@|%22@vh`ap%HlFJGV3+p!2de2J47XidXVtU9iFFdK)F z{$%w9FE%d>?+e0p>_5M|io!1UFugzGdk%`QHTB%zko(mSZwD41_t|iLKGwQ%EPOMP zI=GBii8Xl}lFznF?`iFEA2;7+`Ca9q-sNOx<?Htw_&zo@ehSun&~q)%FVnDL3|70y zcpmFeEeXTp4qm6a@T(XFWgkh_MPT;HwLSyu?6F+$eG09FC_n}l9}C&AJiigz3J|;> z{W0y~GkrG3WHX&~xF=H&y^?XeGaNr(LpV}f^KIw)LJbg;xh^;)vWp0dat_ut&rJ~# zs}^%RuKC<UA<zF8g8<3;$-^xIT34HL{x37LsGN)Pz269}v`g<HSObZVwHj3a2{^Z- z4jK=F&COTtnYP6YZd2Zf)obvOnI|N3A|Box%L%bGBzw%viZSd8d$3QP7ox2<x6b=< zs29nY>4@ezxNIPr=#XxiUOgaM?W)P<-9~MH4X^=P-r{HQet_-G_qM!8rTNyRq1aEd z3Y#V)%6Lti92{ik&99)}`J2_e<saRf^Ok$`IVYsO(N`E&-MvgcPyC2C|Iy%ml8}Bu z)kn_-h=wQ3GfPc^4m{9hQwTW$w#~y0BL@25x}gBMjHn0AKQ%cJa?&Y#*@vC~ZptM+ zd%U5~((emA)cv7hSgY)~_n}c3mL4dKYUY%CH~zJ?F4w}f;r<{c>RA`Q3XmSX9wIj6 z6y!F7$!{7%O6gtj#VGrn#d9h+&H8PIy2L0=f=f<C2jN?d01-jaBn0kb&A)$V$deHv zv(k2zXIozL){)w`=Zso+tmJ@*$3t9G8ZSGyEI!2WKHq5=7=!X`8beA9Iao&z3nmSJ z?2NkTMyz;9MUOn2P7xo2QFri>o9;~-rE%=Nn*c+*p&O?A_0)Ftz*KpA<OUt9p`7bR zyFQ=<<=;QFFk(zM_v=Vc5Ss|JH5(!HAU?JyIc=DiKVRU6J}N#=8K0<;kd0gBcsMjv zrY;QYV`k=|tqZ^6nVa7FDjJlhmxK0qjGAQuvePUucXUlL3y&>LJRo>KhT$?xt6Oy! zPvthp>l4f7FT^OlWX;Drzu9ZylQl!(1d}i<lauVa@T=I1zN|9)729ICCuHqR44#cI zeN<BKg=JNM=&9(C%>q*s9$SIegaylVm<>6V`u*xY?ixn*5{iX)?vMQ|v=ZPnHf_#N z#D`O4zd7c)9o6ki2H{uh1ge>BxcC1?dxKnOX3+s(G$Eb+pd}{<P7j6_AL7Ek)Eti# zjP1P1X3OFR%i?3}y|BTJeqPEH+3y@R9_aDIns;j;%JZ;J9MpL?rUoJh(p_V>nVDzU z=Cc$5k_{hrB@_KFu_V4G9uTT<fNib}?sGX5FbS{9vwlmP`p8B_$EEIFr&PKMhSQpt z$(rwyI|X*A3y(Uh5s9BWem=yHX?WU%qAcy%&jDEv^n2w2exB&*{=W?j9Zq7v8XEq0 zVY2y32!mllo>ag49_Z=+`pBLqCt&~ExfkXCuklERi^&=-*Yd5wJt9?bzTxq5hU`o8 z8j&db*5bhY=GpN>z!mp6XhOQlULf31l*Nt!sk^bevQgoYvSDrN0a>!3!7?WIcCmA! zFQ-70tUfGLs$#tlaJ_ybi4gXX`0r`NYd!|!aAR;d@-aJ{KRK=26BuD=xEJIqRQ8`G zbrsu^=VbrJ&iYGwmd|~cviQ)`m)!8}gkOQpwKp@|3@>-~gLP&Wj<DT;0fIMfGqdmu z*1TKlo{v>wSaso7L>)lWy+F7+P+*9|i6#PMNA=m{C7!&T%yUkQ8mZxe<p~yr?-zr& zUhh|bQ4fJhLf%!23U2^D8XgP7{g*ZG4%1#AyZhj_uUX}15`G0O_X2_3u&x3`Z@|Lh zCh?9^oxk{CI&O$Hu!u>|54rEFia}g9_&oqIz?%2lFf_@L+^>dJ=lvk+01jc=Azc#E zrwmsI0ixK5gOo(pPZ-jFU|KEV2SWum&<$~7c)xBc9`;3M7MeNMP%nVc4cyfcLB7A{ z3B__l(=e=K#vw&tplUBzXXcSXl<Br0K)T$BGFk5vE3Io{2<Dl2{s-NO!N!_1Eg4!E zcquP4vzS)GQXm$t8?5=9;Tqg9To}yHRQJNV9%n=yz%gz!vnsKa>Fz2(I^2jW6(1PT ze`8!Ln(~fd36s#Pm&$YoYjTq{I0a(pAp!%}Gzpc4WbUXtIN63>)ioz1{0i#!0@F|| zDbqd4I7n_MKw2U#=_yNCzY*54W~iVmx&fMq-mj*Kmkm0^P6$hZNDPlfgEdb>vf-%{ z4rBGm9-EsDd8%Nr7ZjO!bdVgv{f|)_Mu3R>@|@wUGzMh@G!0A1No0bK>&^5;cHN>6 zMw7CHIkN!~V4RRn{P*BSp%{d9hn{tw-~}TI4fX<)Lw2$EzA#+F2#`yL@+eIg;tg^1 z(1EMWEZ?Z{p@E(PndEm7mIARDxrL#TI?{U&hNbRQy6#y@^Fc7(3)Y!gZ>%h<4}V60 z9QsQQ-!NrC?d)pw6nNV3$7JE&;|YNl>rEcE7l!w3(el@rCg)O?5Msgf<nyB8^Aoz$ zC4Xa0&MGt%A+wD9j{XElL*;hOFdn6?8}8)<xqO&W)(x6q;&o`!;q}l4+~nt3zYv4b z(WD3ip1)z|#v}}@3cMfC2BLl}@V4UbO~Zfie$>-7F;PylrK-ZECPYF%eD3Mwa<F?u zdvKWCyVqTdMaWt#f1eaqs2j6wDAp&I7;8RoL-$tKeBC`Jd3>`L`Bl(i&1Ghu-$Or_ zB6&|eo7O4VDH1(Uj-PzbDYu?|0rHRG&wphIj~ayXpvo<L)Ycm!@x|W|e!bAwMp9%0 zR5sI4KND};%3_ZmIR$z!5#drHh)Of8`3R6Te{b+UDZ;QMyk{`JwGbeygrB4GytwM= z-cLo;$zD*`Uj~kFa%6FuC|x$!<Je9l-)<U@<-_ekN}ZCd4vI<755Zcsx(3~%vy2Ks z5CIJm(gphA3^y;U7NVE%E9kQ3I)ySrwE!_OYB|j`6AXQd8+pKq5P2$JcPdD7hCMB` z|G>oHt+zcK8eC^|h=sH;O-QF7&agDKNfrzlbQB@7h6+Z)t^hINC&O3EP#z*N?#|S} zdt}&?5+A1JZkr_0HrarioB~a$5Cjnz9Zl{f`r!;m6OYD{rpaIlydahZh>796X839! zRB|FSw5N!$xU{&*3`4K_df@6hFAU#KC>F%9x8EA>wRrx9o0BGCSl<~ju(<B12HS$S zM{dqZ&CgCUTu&y8^ONRjoE;Ewhc?T+eEqBA+cdvJZiG`tJq^^GFg18<F+c*i<d&Ft z-(-DD9uucV5IUv_=@elY4jJRRu(wS{2szkA4kSKj{f6BqBS02vBpf@bloF1&xG{|t za%0bgy6#1|e5qO3G6!EN`<RsYXwqr?e1J8+F0bi2Gpnp3xk}$VG(rUMVPBV0oXgCt z)VlP;DR^G?&Q}8gLiiQf-U~L;Dxv((J4U0yxE(QYCRzRIjtG@YZstJ@PVt7wocy~Z zMnu&7WJ9eTyNSbJzv^RdRDhUx$TmY&t7~vg!n)5An0mjATwVifeo!%9yYBiBybag< zAmd^<_bXS=41;^K)1GDU{X5<FhI@<4@y#=LC-Ix1tD_ox-yxrYP4-=HpFdtaKjk9I zmy~=x21(BV00000V8k0kAtEkjQA8j1Ret#*lmY+%00000000000Q}<r1sDK83n_zS SpPrcj0000<MNUMnLSTYb_iCg7 literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/images/ATLAS-chrome-logo-URL-blue_300px.png b/graphics/VTI12/VTI12Gui/src/images/ATLAS-chrome-logo-URL-blue_300px.png new file mode 100644 index 0000000000000000000000000000000000000000..c4077a1d0d6c9543e6990e3a4605f0488c936dc4 GIT binary patch literal 138388 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 F{{Z)F3YY)@ literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/images/ATLAS-chrome-logo-URL-blue_450px.png b/graphics/VTI12/VTI12Gui/src/images/ATLAS-chrome-logo-URL-blue_450px.png new file mode 100644 index 0000000000000000000000000000000000000000..ff530faae81eaa6b08e9681479c6455e065d7013 GIT binary patch literal 239723 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�{L?ID)SO-Qe6t;zSG?o*o?W&!iG>5gt7 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¥_8$7}Df|b?;cH zNG!pV`cUHC5#l^UJELtLM&1<x(o5*eL?^5ZTL?ObXX0rTaOC5K_6X(7bwhqsN$CX; zpcidIIvlz)pNA{bq>S-hK|B^|{`Zd6b<Oqg9(5>avuK};*?}*9Zyi-418Sc&!S)~p z9yZ2J-xAy8h~)aA=hQ13Ic}IKDp4#rgVtP2b{0T^>)m1zv!&XFKQyQn_c~~R1OH!i z^tc4J&}Pgy&hq1Mjk@S$v9j!hEUJ__2|K_Sqr#zB&*G`2IBnN`fz2Yff%4Wpt2;@J zfFu?qg~rxE&VDHRqP%D6=5*(3;0zWT>|{E*#8)#rI6DqzozLd&W_wf*{vVDjU%;hp zdZIEOynUq;1n`MhrJT-U%hP<qjc*ozMI<g-CpuDkjyl(W(4yabX)Ps`{f)fs?i%6U zvl--?3v(k}M!RaWgI=Z-EsUnU`a-LI!=MXB5xt{Oa>Trd<CgQqip&mdHX&X)-U+Hy z7n%nK3uo$W{(7tYeM|`$&V2k;{##uq99*D!Ja)`zgxhw%q6zwOQ7EeXC(VW!@b|wZ z!u`Ir4My@<+BjM^fR0&F@qzmovrz}YKrp#NCmzX1JWH-H<+Tt>f}DtYM)@B_vOo2o znA0*-;+VJ2uuiq^4L1dB<3@{H9zN?{*g0TQ54`wvfXlup@m15xv&|6qp}+B~GtZ=( zH%V8qs-MRAhWaeo@FOGm40gCQxz{7D`}3-N){=H6?{@IfT!sEO!-K>Q)>YSqRuIhZ zx^Mf*$~b6;4BC3V|HAC*;gf1{8uiK{Y1so7P?5GF@Sk~-KK83txaOh%WN&jTc}pgz zsG}ttM4P)c`Jz}DdK;=7{eUvL==)#Dqd}kk10=5}!{pzV_(gE;)@Bu#V<hX|%2;NO zyuFrgpH0X<7ByQKP0$Imq3~d4p=09c4k@UYk}a7*Dh)7Ne&MhckUhZhTWgWMd3y7p z`Y{7h1UGyOwD}+~e>UJtW1^ROeo_Boru!gDOFcl$+;<^2L4@Q)?ly4Z4BW*wc%Z}! zq;qGvKR<o`W7Q_o*}|z-9U3zyYS{%pRGS(F6oG61vaN_K!rylE{pB+An?~;3i;cP7 zc;*2@jpgNs!w@NB&zM}gLFyTV)9Xi9^0$O+-6oE1_B&CVNwGfS#wJ%|Bb{j{SL@H3 z_Lly)3Ao=Y?W;>YHo2f>R@~_3Bs^srB!Q)O_un46oEGn;y{*+&6XB!8ij(vZ?pyiy zlT^6xFhpN;brBMV(~wQGN@SzsgF&>JFk;91(#tBfeuZ>wao=e_Z)k53srL3~pbc)H z@Jp}}36hMDiGAZMoT2&XRM4!2;|sp>8USAT9g~R|+R6Pp;Kc*i`nKPC$2MCd!|>i3 zjeD|gnrHm{VFfc$^WM@Ix^Q~Uc!p@){Ae!4=dTKJ-d`EFUoft1F<z_<CG|iDe2sfP z7W|c>C4p*)R;aAa=Bey%-#lT^^%7kv#Ed#i^`AV8@shvJ?_4&g2tt~8^#0$YM>8(f zVEm`zq4{M``giW8u{$CKOwbyULd9g}zV!(08aPX2C~Bu6UxlE>o_$%&9308n5sf)n zGyYscBPzJq%Ut3O=EqX<ntB#uXrsXLgNcgmf4b}cbb$X~55o_LTZzSt8RUKE0Vc-d NQj$}bg-L%3`hOz?S-k)N literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/images/ATLAS-chrome-logo-URL-blue_600px.png b/graphics/VTI12/VTI12Gui/src/images/ATLAS-chrome-logo-URL-blue_600px.png new file mode 100644 index 0000000000000000000000000000000000000000..70004ee0931a8200a17e8f66493a57afefe3c9c4 GIT binary patch literal 360352 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	>6Nz=Kr>KY>!K>{~aVX5fO0Nvn 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%0D|lgnrdwyWAGvVtQ~yDaSBxTP(k8Q4Z?dnpfM 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	<Mze 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 bynCVWCWa7yl_pMyd;8?1m8I$>jYI!GAFw*Q literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/images/ATLAS-chrome-logo-URL_300px.png b/graphics/VTI12/VTI12Gui/src/images/ATLAS-chrome-logo-URL_300px.png new file mode 100644 index 0000000000000000000000000000000000000000..717c1c6ca15e44398a52b5ae1ddac2d6bf665c13 GIT binary patch literal 134817 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∨p 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 A0ssI2 literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/images/ATLAS-chrome-logo-URL_450px.png b/graphics/VTI12/VTI12Gui/src/images/ATLAS-chrome-logo-URL_450px.png new file mode 100644 index 0000000000000000000000000000000000000000..81b8ac75abbd09073501dc48a7515b977a9620b3 GIT binary patch literal 234389 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%0DGiHh~e0KY3vja*3QKm#S_&C{N0t zsts@&Qf;YL5E6<A3BSVqMA=P~5p<vpAtsTQq&c``B<gFR?*4T-{iu3WeSkBKnn%q8 zpKPXfQ#-+jVOg-auL@gsK*@nWsSSVdQ5{}YxqiDHaW`?x2i~lTYZLd2YSjt9<2#Qh ztnC_kBI0sH>Yd5bR#Ic>Us&hzF6Rx*n+62(FAci%G~!@r?NFDHLCYu0-^gFfqNNL& zz03|~R|RkI$%GEJu!oR&%Ov2frmbs^R!6M}t!%)0nRNr}6(}^=YVgb;6)%v3kI4A@ z@1GZ&H!tsZ;PSr9Byen2+mpwSJviQK=8Q8Qr{|u|+IO?zpnA3Hw+3!JytDT9@87Rq zRxK=FSlt6mY)rSBEPs6+p(KPvJol%^(}QRY4np2cia!(|k3O-3Vg|>axbr3|;@P}s zX$m2;fF4TE`u?9oIkSJ89XZ<^@apNc$aBrR!{_;De>oRD*6xY;@rNhA;nKqV!ZU>$ zSV~of;<jS5`~XloN7=P>D4^;^`_nD|{`*o5sD@NifI2~)qRxRseWXfAAw=k*jyn1^ z%3Z>o;YgezgdB3nHE6E}$Di^CsG-zYY7B%_H`0&v(Lg2Cg&11kqcuEH4SY0H2e14= z{B$Ox%rT}fb^?Yfqw9w07+)$ZO;F@2N@5m8&y2P&y-f9{no;Xi7APtUmrK@>t<+}X zko-FNUeZ9id(P6F!8txE&!R1beuaZ@0sye%>+Km%H&|r24&ZkXOy`eRwaXZt9*~|d zyCCf^^_14(xS&1SFm0LGavNo)6Vr+5$XOYe|2pxtrMw<*I&TZFHKPw79K$MHuBven zE5!z43gC9&t>jK&t{24?1{Y0}$3?e^@{XFXcnBjH!<hb*nTjkVtElDV;memVlAb@4 z^)IH2Rur9J>QHf1JXL0DcnSUfvN)BZb5HxDP7FXFW;WCNnJ)R`^5l7wWRs#BMQw<B zB}l+Y9LEX9s{98^42dN%qdLAk|KjQksl0`JiTtg+19OzOgg1*<W^=s}RS_n-Jny9= z=3_g6ZCHu>sN6YOzbs)hPr$S1sY)j-m^e3b-li2VM~)wTXSAE3j?c&%r+to%>S$$Z zecpPt?nUtjv4vOy5C`H;oB>6#B1RDpWIg@Z`{Q(+i55rMMr}xcaIg2>Mt7Av<PQt( zD;|*b?hZE`^BuEf`d77YKDhB66{|n8*nMH~qFkW5W%ZTSbBh8#Mt?N=n6O}Pb-vG) z>Z431xV(04<vONDmd*;D2%Xz_Robf5v(y)OmyzI;Fi2&5J>cq~YhhOuVF97pp;I^R z?Xs++cc&QiKPS0pe?bGMbxkQfqwG~W6)2%(FJ;M&aZUz~XPgf7eq|YDMXdhI$zxpd zYu&h(rL801MVyUjyw|O7VE?H8ItA^*{K8*_m8S<;Sasw2qhR!yYs^bP)l2nKxzenq zWtQbQ%bo-0*}bzpWBZr{{PFw!&idWRciWlG5kX;x!|NPaK6mhf-{!k!=xyS;Ua zx=<BvQ2s5<mn^KkARd^sWBjoRuS<A)r|#Lf*JP%3()pz7NjZ5+pW!v^YK$1#$GVPn zw9N^_>RO{EN42&CR5bOLiUSlL3V}ig$n?*+nUR3ak9R&A{Mg`4*PEp`I^MW8d%}q~ zXM9cv-ckh)xH$acp}O)!?RS2OwUvW1-erVmrYUz}JjO6%0klCov<2j6<iE+|dDcm{ z6HOD3mD&LS0+|GKz;JYc0Q+$kyZ%;}|0{+c4LuF@0pWVl1<_#@Qv0RWPMaZ97E?v} z#np*E(-tk6R!jzr%Yw4e3c8Rk<l4SD9~T^-Cr^=#lekHiF~Oiw3!W9FRR4R3&x%%w zZvb2=Cx*L|i6|aiSX9(Pb|X4A$}Vc1VioLQ2U~h_d3myiY^HuEmtGEkG2;0LS&!mL z#cxXdX?rS$x<FO28wCJNtuwXJw4T6v&-I1tliy!Hy7I8j5!Vs5lhP8qBwk(G)N{Sp zX|MMkmYMH2w>PK6{=ze&x1wl()InX;2BeQ<+hm7;_otJ!l55hl?@qhZ<nEm(!*92~ zRd6eGQnSO$kB>WU@%r!`>8*pe+A2rA3VreVrMb$HyO=kD8&vudA$W=qfXIl7D1n>@ z*+a6Ya{Hy%N<WddUHR+N;g8QhUauB*?)U3=^z!KI(JFvf$dmC7%lAKP7diIXse>Og z`)4-K%-3GxQ0$oLc)MC>ljA1VCX~oa+)zACJR0CQb82yF0F0Oh4M28IzFhu0kkc~f zeU1_f6B6ILyzQR1J#un*_lSpgs)tPvvj{!$TlA@dv-QrBd!`=eTz0qy(<AN+ACG)A z^>26MPb`15?8>rHKnJZ3lJ?C%x<-wRdKkr>d#w7I>YIIj+qBOq+WDGOyz5x4QIf-w zt?*EckT;UI0pgP4^y6A6BCZ(+*S&iBq<@5VxHx?9ZtwW`xIS^o2)gtz$ni?Ms{0-$ z4Ss*~y&=$kZ2P44;lR1N=Z>AL8TxYnzJ15`nf5y8Z{y$I|HjlS)mnK~^E}_R*s7-0 zW9yS9sXCFmmO3Il<vH>i@#+FN%p7431M+8zvx*=f??P_RyfMf~ic9iJ>{;CTq4$IL z59&Q#l9!gdFYjDVu}~naB`k|#>juxiF2D4Oteb2jV6xGqr^#RhD+Vhv6jDX!7gwK$ zJclxn^O*C3b3oY=iAY2uKpK)3q#3vw3o@2xT%z(n?#^72Sw}gWKBn5Ciolx6+SBW& z*F$d#KwYBFQlWHiwn=tm_FZ{E^qZ(=(Osx6n1l(;L}unEU+eR@LM~CqUiN+Q>&qzl z6QzmLP`Q_};x6H><^2NSY}I|X74g$4gx7+Coq`VooIH*-C#-O6rf+87%<1D!6}Ko3 zEr#|2v}3L^*BJj#1Fu7xl9N~_za!frbHzH@PT5M?jpsVdW#$nB0F5hd@A2J-H6CsQ zI7M6&Zl4F%dDrt6<Y~1ZRXRd3MKOukp&#y`8TLYpXh92L_{;-_Lmm`2E!Ha0ExM{_ zr_a$V%nN5y(3g<{xL-Bna^Lsft$SJkxkbj2iz%<NjkC?Nw)XRqI+Wa&zTnS*J3Qcl z-JeeU-hzX%s3mog#!7dquFIq3Yviw9^(Wm)SJDj;xLdWK<HJc0$b*gm)t<_w{Nv{3 z(AlBcOM9qfJXxA7iYrAw+`(w<{d8h;5BG2vCrgHxbS%j%^<btk1DU?bDkWE`qm)#k zpgeVOf$|^&<vtaaQJ$zd4@JmEe0NEYAw8UAl9in0FPG1oce&A<#(Nq$2Nv4o*aX|w zYU!+VNvBjN!|58aA+E$oaHeo#p?zWfe228fY5UUxWBlJPd-Lqgm762(kG<dJzUy-x zV=d#g#u8PX5belm5hFB^=Wnv6&bpOrrvO^(MGj&UplEW*#^Q{pLwnWgZrY=5=R+>P zx%jwPchuFLp|@H0Q8j02;}X8qv@|~PaiTC$6~cSD>cuZF@-MG9p-fy&NN)dgl8ez7 z-hV&&4*qt)`M`OgM89ZT@k~H`OI%0Xyf<+i>cn$=>C}Pm#1G(qVW=ZtBOfXs3xxIw z=@Zi6>GH?-9^HPVbH&&0vAw|F4!>RI1<^qZtA1SnY4%Upo4Ri=Ak8TGAl(QEt_k}I z2X;E+(9-dO!xEp?q6G0~vEAo@_o~(^KUG~Ita@nO&@<21g{=#_9rp3;!bDEe&ZJ`C zvPtlZ;P2}F`E#&w<fcBq9|3B%s(#dGb<X<-!yYVopga3e^R~^0HE(vhp&ifO*Y0+U zIeOi6kLqo6e?_(D{6_T`^(gFJSf{9Ifn#dj4=+>RMuo+Z*Y<I(FOR%xb#v5>4)Igz zMXDgx5sWwbV610+{Fr0GnSAH`>ra1G?N>#qUNU>p4|m`Wz?HZWH-Pq1xvAX9?qcua zQ^k6jtviqG;M&ojHf8EEiA=f0Ocf}Ek6u3<{3r<Eui|_0uiuQ%>yc}od%Rt7>B!PY zr82BTL)<|l?1cd_fC0d)r`Is6NY7#vPcM!vsBZJvW{J(z;wMZmG)H{^r>f?2x|@4v z#GSVQF(wwo^uy*HPIklWSp&LDdr5Cd^95ODX{Z?8PwV1K2r&shQXgrN^p5I*JVxGG ze&}Ua;zAsWJpe$WQ8etoNKxyOn#E6nUoZ+I0d%_2Zg=}FZ$h3Pe4_hg;n2%|l3LGe zeF!*a)y68oszZ|x5|#FC?QQmE%w6U+Q^GaNUz%4vuTIvUWTWI?lSVx0@{0fR^{acq zwHkMByr*%k^qf;AC&r%`0ck{dm{wTpC5eT{3tfvw?%2e<qQmK}%wF_^E@}d3L0XZP zK<QycZACNUQBtR*Ly1$u^my;Mhw<J3zVn*fwRg9yZmR*R7AYdD8GU*L)10}t-=%(? zI<x9JUEJpN+G~(k-<n4(+FL%iyj^FH4$<A9<Kr})XT;OvkJZj8U0ym*F<*715QXuD zO+Th*KFZjddG2Lu^5~?fqzz9^V*AIQiPeuCYu?f<*Q}1TyxILPgmEKZS7Cab)!eo1 z*8B?WpR(`rz865|`s`I%d#<nOm)84UpROHz9C=Rr9eEx1>(tU7qVvSLpzw5I+d^+y zY+{pl5$|?Bh>4Ae)ry^YRbRh`o`s%cVbZ18Adf5mVA`g<Ed_51Y64BRG($50UR?Kj z?on_1UH*8vUZCyxTTT2MuWzz>+Z?+o_A>kR0ZR<(8#XX#=DAH+UpQVg%J?aBmd>ST zlfi}BMGuQM<#qdLk!hGY@>R(DUC9%YMNjX(iH)D|W_pyDhty+`d;fyCcLs^wlScn- zv2mGPnjDx5h-^eDq6v!h_pOsAB`utlSL9w4Qe<FI!1ywana0ds)K|M!wI*#zTM)%v zd5ZivSth+DJtDpM`dzXt=}uC-`b~4c-rl3T4{AR=0#GNYLh5?-<h)0@gLB(=StW-& zUH&^&AN_C#EwL9ol$qK$#3q!IDaBVy4wWRzPIHvpV6IQv8oHNiq^j)Z_ztST^@oLp z<!=z)GVF2KW8l!JgUt^Pl-LCC3mO-6_t8d$K%OBlWWGx3)zsRl-56%UfVr3F^%+sL zx#n-_zkl6ORK3L@>Zyk+R{vcE7LC}KzSn2(8DMkl?^&BB+4^066}T)g=EZy2O4%>6 z34i{4Vi(4&j|o*ejp;VhXk_ZpkL&zauUg{+bg*ud+xEfV7Uy5ffhYS-_iqL^`~2Sg z_ei7p=bg?5os&FqEb3KcU*!Ggae8~;P4Zg<Cgj&^lg>{5b^7`ABWYLD(t-9JTF15d z&H*<5cOmMKSCl%gBeDI_60!VGpmy${?A6cm443<Vv|#@XMD6rLsg3%mp6dVjktxwx zfT3j%N^Oz$>2CeXj~0xjVt%?CLKc>P6nD789e{mVo|!MgmRAk|paterKFF`5j%UWG zz16-$-JJJ78+sqbW5m|feh}f>T1Ab}8nNBhyj9~;w6!1Cs-WanQp6~=FD;c&k5P(f zYgKC2h)v9>k=s%;LZuojm$vtxc;0`(`JVIoo}WIi<1@uj*hDr2FU7bTt~k6Z@&ZY% zOLOse)1Iu(5dAZWp8G?wqRh=poQ}D9s^O}W7qkGKvc=G1-7b%WH~0HNqLFK>iJx-* z2U=(^-8VXLs#I4cf$m0rt669XU>YaO)mkb8PA;5;c659d*b2VFO0t-M6J1{XRYXJA z%Ic#}&=B5uZQcTrsUuo*ABMao1I550VbQX_6MsliZ>T9$P|_)rBg`6KVOVA5MPU8o zZiVtyF_=pcQdr*N_z3A&Lap@)p8cpRd(Vq*L0^mQ$Kj4jD(qIC8A7?nqW}O7r)#E0 zH><Gu-jYXF-sGX*Pav8U4I*IK$D#63L&nny_4z>c2ZqUkA_c4kRal{pd;D38SMgg` ziD)dZtH{Y_`{SJt$q<2DB-pfk)OrnrG(%xoPLvkF7=xlg`$stm2Vc!)QiH^{!0TSM zA43N37&MMZ4zyv94A$QXax98K^*4LQu4;#E?@$y45-&iNf|M`}Ax`HXoK)kq<CT?_ zVG=FG2rUv#SE@x?LPnR3gEt;(TpLuD#tpWX;Kt+8KxxZN6$9XTC(Ml?2MTkiF!~&) zu28kag2se~=Eqxmhq(lnY!FM{c<fsbQF;l2c1(Apxppm10mi4swd7=&T16Mps=@F2 zg0K(75qVc_NHrw=`t%1XBg#H2>R%rAS(6>fT>>j+HEGlo>Xn|2&^k-=X&ou5aY#y0 z0_?5RsmL=H1->R^oc_7;IPE98j~m78Aa)747>!A-7|-$18F<D_1irAJBG<g%yPMp- z?ILRvYtdx?#NQcfGUpgjjd)!XK~nR6`KobO^4Hh9C8LNkg|R9oMV~x~vRhe6K)d#8 zurtChFi|8eTY^Mo2vT9;+w6rPEtJ}Zosn~k0KUp3=p@?n#u2l>#4PjgLMy*{-}w$b z^rw-$>?DeKBbGhKN_9tRhlw?(=xK<5Z@{@;upT(!K(X7k+vL5+CvN-Fin}*!QPc`t zN-<DX*xZiX*fm$^UeKg*`Dk84YV@*>YSR9hjkER-rjy*zD7fFXP{KvjB0BOBvWD*8 zlKwSiD;lUbwe=j~6e)TO=CF#UtTLI(Ta5Cx;U)P+!F5-pkNODi!7aM`8GyXP*hN+$ z2JgdvbFcp?7vzTH`3NX&$g0{?2M55rX4;c9yk5++B4!jq){pDH9Yzq!vq~OPNp~X1 zC25;&uPGgm4?76Or51vq>x_r^yD+W=`xrhLlbw#D)%Ab?Eh3|6yLwyg4{X<svr(N8 z>glMCNV&D;98bI!PdJZwq)SxyasINy=g&{&v{Hs1F|g>$+dnL1upvzPIy-l3eS`NP zRr>QNe%%))$$U~es!bQ0h{FR5<0trIw2OjlP*yJg*ymliN}+K%Gr7965^bC6WTuk* zM6wuhWW4`j_{2@R1N2OCQ}ojh4{I9hPo~JIz1sxYwGh-aDz7&z_|HiwDd=e+qbHmu zK`UQ9Jy2PAU6rXI11m$D%UeLwt#oIqMs^_0`W`0t{^(aa&aPQhVdwtNzzEAvrHL)s zVHpKnipj6+2-9DnIb!wDJ+Ze_t+jETzoZ`Sq%XrZZTVuTY@OJ|!gJY>?U3W{t?5R0 zIqEX!?tMB<a=xI_B;fg!W3r%~;01TZo1IS4lQe}jnnVL(tbeVTC?BebC$nsiEW;WI zsr`dMV@s1RlS{+4c)!pqS~#_XXmZc#^wk3-Jow*WIi1lN=u+v}P@of_r!ds#8IzS~ zO!v*3nCqP!=4#A#ycjC$XpW`@QF8t%HhprTs;qjK`IG0e%`OB0iyQg)#WlP^yAHO2 zo5hyPjQQ6Rm%^gtlcT!uKxr2X)_B!lQ<K4bJC^S=Wt^hjx63B0&vV=o`Eb>*=d>vI zeG`uNOo&4OI*_h6E05Y3tnQ`x<A$N6h@`;7l^b241R4)xz}h2+tU;`RNY)yZ$Xpr8 z-`t*t)!6p7POdGoWXIXEp&6_0b-3>w3E;SX;kE=)dA~*f>C`?mc|U_tixb8O&hxpO z72tQG*ytET%IdA48kvka<<Eg>{Cz2e0!$-kpUpsiZoQ}?`L7R3Q8xK2js3QRzF+ua zG;%F3ft(xIbheufp4~5e!B)K|vIY|8^FAMZ`)*MeGSfF3A)|e+Pdu}CAPnG+ZXLY8 z%oE>aFoYygCvuilv|ZeT8E*^TxLp%ji$9C6WMwY@H?3_ZyaC?+s5Q1Q+UDQ^ZT)eE z_@p|<Th9pLh|!CTTyT&Yf$sYR>1DJd=JvMWO9Y%kS~`+<6P_DJo}#ZN`A4ZVqni&- zZ=inEoH9f9CFtzo@fhwxVHXZN3&N$!w!6_QYdpuPgkE1g#kbnzR!0u@Ykp~7F3jiT zJ2?#5RF=T3KvnKsLAW{NQx8EQ%k#NzsiJ*F&M^ml?3g~=H-4a_u))<nb6F*|ic$uj zo4~)hV~c1Vj-mZc!~G}L>Sdg^21iU%w>%GFjL?h~C~Z0nGU`l=7eN@e1g?9{(1mwL zQrpgloFKm?KxMAJv+lWt^6&WI`=-AB(G%&y&Y%&(+|sut?PSTGB``@QN2$XIY{rA% z9r{xKd1EweVOdu5I#pk@Zl6R6)yF70iI@tfU$kNgVQnvzoWCgiom?dIZVB+L5$Iyp z&&3KfF>Fb>Tu7l|W5ZD5-<Rd$GEEWc2Jmov+u~Bk9J^)An;aO%G0;`{znRP-{xzvp zD39cq?<?P*2R0e0WJ|rDUs-6rSH7Q~n}z;=VVR-9VAqB`=PALc?*mS`W@ckrV|+XI E9|&a!YybcN literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/images/ATLAS-chrome-logo-URL_600px.png b/graphics/VTI12/VTI12Gui/src/images/ATLAS-chrome-logo-URL_600px.png new file mode 100644 index 0000000000000000000000000000000000000000..362f722a5f95b86c64fc1590a4449c532c1b0d47 GIT binary patch literal 355598 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�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%0DRYI%Hi=R_^n>Dl_LkZT+<C^KnCz6<!AslykgX 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≫1UOeCA`Y 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%0AMF1K8^ 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�_{&DiY}NQ|cPw#1GOQL^~m+1;iWiM!W!7RAd(U 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 literal 0 HcmV?d00001 diff --git a/graphics/VTI12/VTI12Gui/src/vp1.qrc b/graphics/VTI12/VTI12Gui/src/vp1.qrc new file mode 100644 index 000000000..8ef40a3b2 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/vp1.qrc @@ -0,0 +1,61 @@ +<RCC> + <qresource prefix="/vp1/icons"> + <file>icons/list_add_font_001.png</file> + <file>icons/list_add_font.png</file> + <file>icons/rotateleft.png</file> + <file>icons/rotateright.png</file> + <file>icons/zoomin.png</file> + <file>icons/zoomout.png</file> + <file>icons/fileprint.png</file> + <file>icons/3d_glasses_24x24.png</file> + <file>icons/3D_mode_24x24.png</file> + <file>icons/3d_32x32.png</file> + <file>icons/event_display_32x32.png</file> + <file>icons/back_32x32.png</file> + <file>icons/button_cancel_32x32.png</file> + <file>icons/button_ok_32x32.png</file> + <file>icons/down_32x32.png</file> + <file>icons/edit_32x32.png</file> + <file>icons/editcopy_32x32.png</file> + <file>icons/fileclose_32x32.png</file> + <file>icons/filefind_32x32.png</file> + <file>icons/filenew_32x32.png</file> + <file>icons/fileopen_32x32.png</file> + <file>icons/fileprint_32x32.png</file> + <file>icons/filequickprint_32x32.png</file> + <file>icons/filesave_32x32.png</file> + <file>icons/filesaveas_32x32.png</file> + <file>icons/forward_32x32.png</file> + <file>icons/help_32x32.png</file> + <file>icons/info_32x32.png</file> + <file>icons/kcalc_32x32.png</file> + <file>icons/kchart_32x32.png</file> + <file>icons/kivio_32x32.png</file> + <file>icons/launch_32x32.png</file> + <file>icons/network_64x64.png</file> + <file>icons/network_disconnect_64x64.png</file> + <file>icons/no3D_32x32.png</file> + <file>icons/package_settings_32x32.png</file> + <file>icons/redo_32x32.png</file> + <file>icons/undo_32x32.png</file> + <file>icons/window_fullscreen_32x32.png</file> + <file>icons/window_list_32x32.png</file> + <file>icons/window_nofullscreen_32x32.png</file> + <file>icons/yast_route_32x32.png</file> + <file>icons/camera.png</file> + </qresource> + <qresource prefix="/vp1/images"> + <file>images/ATLAS-chrome-logo-URL-blue_600px.png</file> + <file>images/ATLAS-chrome-logo-URL-blue_450px.png</file> + <file>images/ATLAS-chrome-logo-URL-blue_300px.png</file> + <file>images/ATLAS-chrome-logo-URL_600px.png</file> + <file>images/ATLAS-chrome-logo-URL_450px.png</file> + <file>images/ATLAS-chrome-logo-URL_300px.png</file> + <file>images/ATLAS-Logo-New_1200pixels.png</file> + <file>images/ATLAS-Logo-New_1000pixels.png</file> + <file>images/ATLAS-Logo-New_800pixels.png</file> + <file>images/ATLAS-Logo-New_600pixels.png</file> + <file>images/ATLAS-Logo-New_450pixels.png</file> + <file>images/ATLAS-Logo-New_300pixels.png</file> + </qresource> +</RCC> diff --git a/graphics/VTI12/VTI12Gui/src/vp1authenticator.ui b/graphics/VTI12/VTI12Gui/src/vp1authenticator.ui new file mode 100644 index 000000000..21c8e3920 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/vp1authenticator.ui @@ -0,0 +1,209 @@ +<ui version="4.0" > + <class>dlgAuthentication</class> + <widget class="QDialog" name="dlgAuthentication" > + <property name="windowModality" > + <enum>Qt::ApplicationModal</enum> + </property> + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>380</width> + <height>447</height> + </rect> + </property> + <property name="windowTitle" > + <string>Login</string> + </property> + <property name="sizeGripEnabled" > + <bool>false</bool> + </property> + <property name="modal" > + <bool>false</bool> + </property> + <layout class="QGridLayout" name="gridLayout_3" > + <item row="0" column="0" colspan="3" > + <widget class="QLabel" name="lblTitle" > + <property name="font" > + <font> + <pointsize>12</pointsize> + </font> + </property> + <property name="text" > + <string>Please enter your NICE login and password</string> + </property> + <property name="alignment" > + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item row="1" column="0" > + <spacer name="horizontalSpacer_5" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>32</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="1" > + <widget class="QWidget" native="1" name="wdgBackground" > + <layout class="QGridLayout" name="gridLayout_2" > + <item row="0" column="0" > + <spacer name="horizontalSpacer" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>18</width> + <height>52</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="1" colspan="2" > + <layout class="QGridLayout" name="gridLayout" > + <item row="0" column="0" > + <widget class="QLabel" name="lblPers" > + <property name="text" > + <string>Login</string> + </property> + </widget> + </item> + <item row="0" column="1" > + <widget class="QLineEdit" name="inpPers" /> + </item> + <item row="1" column="0" > + <widget class="QLabel" name="lblPhr" > + <property name="text" > + <string>Password</string> + </property> + </widget> + </item> + <item row="1" column="1" > + <widget class="QLineEdit" name="inpPhr" > + <property name="echoMode" > + <enum>QLineEdit::Password</enum> + </property> + </widget> + </item> + </layout> + </item> + <item row="0" column="3" > + <spacer name="horizontalSpacer_2" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>28</width> + <height>52</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="0" > + <spacer name="horizontalSpacer_3" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>18</width> + <height>24</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="1" > + <widget class="QPushButton" name="pbtnLogin" > + <property name="text" > + <string>Login</string> + </property> + </widget> + </item> + <item row="1" column="2" > + <widget class="QPushButton" name="pbtnCancel" > + <property name="text" > + <string>Cancel</string> + </property> + </widget> + </item> + <item row="1" column="3" > + <spacer name="horizontalSpacer_4" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>28</width> + <height>24</height> + </size> + </property> + </spacer> + </item> + <item row="2" column="0" colspan="4" > + <widget class="QTextEdit" name="teditError" > + <property name="enabled" > + <bool>true</bool> + </property> + <property name="autoFillBackground" > + <bool>false</bool> + </property> + <property name="readOnly" > + <bool>true</bool> + </property> + </widget> + </item> + <item row="3" column="2" > + <spacer name="verticalSpacer_2" > + <property name="orientation" > + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item row="1" column="2" > + <spacer name="horizontalSpacer_6" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>31</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="2" column="1" > + <spacer name="verticalSpacer" > + <property name="orientation" > + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>20</width> + <height>35</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/graphics/VTI12/VTI12Gui/src/vp1eventdisplayeditor.ui b/graphics/VTI12/VTI12Gui/src/vp1eventdisplayeditor.ui new file mode 100644 index 000000000..1829e697a --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/vp1eventdisplayeditor.ui @@ -0,0 +1,594 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>VP1EventDisplayEditorForm</class> + <widget class="QWidget" name="VP1EventDisplayEditorForm"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>1038</width> + <height>923</height> + </rect> + </property> + <property name="windowTitle"> + <string>Event Display Editor</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <layout class="QVBoxLayout" name="verticalLayout_left"> + <item> + <widget class="QGroupBox" name="groupBox_getTab"> + <property name="title"> + <string>Get image from Tab</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_6"> + <item> + <widget class="QComboBox" name="comboBox_tabNumber"/> + </item> + <item> + <widget class="QSpinBox" name="spinBox_imageWidth"> + <property name="toolTip"> + <string>Specify the width of the image generated from the selected tab</string> + </property> + <property name="suffix"> + <string> px</string> + </property> + <property name="maximum"> + <number>4000</number> + </property> + <property name="singleStep"> + <number>100</number> + </property> + <property name="value"> + <number>1000</number> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pushButton_get"> + <property name="text"> + <string>Get!</string> + </property> + <property name="icon"> + <iconset resource="vp1.qrc"> + <normaloff>:/vp1/icons/icons/redo_32x32.png</normaloff>:/vp1/icons/icons/redo_32x32.png</iconset> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_bkg"> + <property name="title"> + <string>Background Color</string> + </property> + <property name="flat"> + <bool>false</bool> + </property> + <property name="checkable"> + <bool>false</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QRadioButton" name="radioButton_black"> + <property name="text"> + <string>Black</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_white"> + <property name="text"> + <string>White</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_transparent"> + <property name="text"> + <string>Transparent</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_logo"> + <property name="title"> + <string>ATLAS Logo</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_6"> + <item> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <layout class="QVBoxLayout" name="verticalLayout_5"> + <item> + <widget class="QGroupBox" name="groupBox_3"> + <property name="title"> + <string>style</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_8"> + <item> + <widget class="QRadioButton" name="radioButton_gray"> + <property name="text"> + <string>Gray</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_blue"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Blue</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <widget class="QGroupBox" name="groupBox_4"> + <property name="title"> + <string>width</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_7"> + <item> + <widget class="QRadioButton" name="radioButton_300px"> + <property name="text"> + <string>300 px</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_450px"> + <property name="text"> + <string>450 px</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_600px"> + <property name="text"> + <string>600 px</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_800px"> + <property name="text"> + <string>800 px</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_1000px"> + <property name="text"> + <string>1000 px</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_1200px"> + <property name="text"> + <string>1200 px</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item> + <widget class="QPushButton" name="pushButton_addLogo"> + <property name="maximumSize"> + <size> + <width>150</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string>Add ATLAS logo</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_labels"> + <property name="title"> + <string>Labels</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_12"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QGroupBox" name="groupBox_6"> + <property name="title"> + <string>Add a text label</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_13"> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>GroupBox</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_17"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_7"> + <item> + <widget class="QRadioButton" name="radioButton_customText"> + <property name="text"> + <string>custom text</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_eventDetails"> + <property name="toolTip"> + <string>Add a label to the picture, with run number, event number and event timestamp</string> + </property> + <property name="text"> + <string>event details</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Add label</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="lineEdit_customLabelText"/> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_4"> + <item> + <widget class="QRadioButton" name="radioButton_blackText"> + <property name="text"> + <string>Black</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_whiteText"> + <property name="text"> + <string>White</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pushButton_addText"> + <property name="text"> + <string>Add label</string> + </property> + <property name="icon"> + <iconset resource="vp1.qrc"> + <normaloff>:/vp1/icons/icons/list_add_font.png</normaloff>:/vp1/icons/icons/list_add_font.png</iconset> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_5"> + <item> + <widget class="QGroupBox" name="groupBox_font"> + <property name="title"> + <string>font</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QRadioButton" name="radioButton_monaco"> + <property name="text"> + <string>Courier</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_helvetica"> + <property name="text"> + <string>Helvetica</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_times"> + <property name="text"> + <string>Times</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_size"> + <property name="title"> + <string>size</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_10"> + <item> + <widget class="QRadioButton" name="radioButton_size12"> + <property name="text"> + <string>12</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_size24"> + <property name="text"> + <string>24</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_size32"> + <property name="text"> + <string>32</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_size44"> + <property name="text"> + <string>44</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_sizeCustom"> + <property name="text"> + <string>custom</string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="spinBox_size"/> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_style"> + <property name="title"> + <string>style</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_14"> + <item> + <widget class="QRadioButton" name="radioButton_light"> + <property name="text"> + <string>Light</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_normal"> + <property name="text"> + <string>Normal</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_bold"> + <property name="text"> + <string>Bold</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_italics"> + <property name="text"> + <string>Italic</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_black_2"> + <property name="text"> + <string>Black</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item row="0" column="2"> + <layout class="QVBoxLayout" name="verticalLayout_9"> + <item> + <widget class="QGroupBox" name="groupBox_objectList"> + <property name="title"> + <string>Graphics object lists</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_11"> + <item> + <widget class="QListWidget" name="listWidget"/> + </item> + <item> + <widget class="QPushButton" name="pushButton_removeObj"> + <property name="maximumSize"> + <size> + <width>150</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string>Remove object</string> + </property> + <property name="icon"> + <iconset resource="vp1.qrc"> + <normaloff>:/vp1/icons/icons/button_cancel_32x32.png</normaloff>:/vp1/icons/icons/button_cancel_32x32.png</iconset> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QFrame" name="framePreview"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_actions"> + <property name="title"> + <string>Actions</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_8"> + <item> + <widget class="QPushButton" name="pushButton_print"> + <property name="maximumSize"> + <size> + <width>150</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string>Print Picture</string> + </property> + <property name="icon"> + <iconset resource="vp1.qrc"> + <normaloff>:/vp1/icons/icons/fileprint_32x32.png</normaloff>:/vp1/icons/icons/fileprint_32x32.png</iconset> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pushButton_save"> + <property name="maximumSize"> + <size> + <width>150</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string>Save Picture</string> + </property> + <property name="icon"> + <iconset resource="vp1.qrc"> + <normaloff>:/vp1/icons/icons/filesave_32x32.png</normaloff>:/vp1/icons/icons/filesave_32x32.png</iconset> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </item> + <item row="0" column="1"> + <widget class="QWidget" name="widgetView" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Ignored"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>300</width> + <height>0</height> + </size> + </property> + </widget> + </item> + </layout> + </widget> + <resources> + <include location="vp1.qrc"/> + </resources> + <connections/> +</ui> diff --git a/graphics/VTI12/VTI12Gui/src/vp1incomingmessagedialog.ui b/graphics/VTI12/VTI12Gui/src/vp1incomingmessagedialog.ui new file mode 100644 index 000000000..48db96e41 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/vp1incomingmessagedialog.ui @@ -0,0 +1,541 @@ +<ui version="4.0" > + <class>VP1IncomingMessageForm</class> + <widget class="QWidget" name="VP1IncomingMessageForm" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>473</width> + <height>231</height> + </rect> + </property> + <property name="windowTitle" > + <string>Form</string> + </property> + <layout class="QVBoxLayout" > + <property name="margin" > + <number>9</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <widget class="QFrame" name="frame" > + <property name="frameShape" > + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow" > + <enum>QFrame::Raised</enum> + </property> + <layout class="QHBoxLayout" > + <property name="margin" > + <number>6</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <layout class="QHBoxLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <layout class="QHBoxLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>22</number> + </property> + <item> + <layout class="QGridLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item row="1" column="0" > + <widget class="QPushButton" name="pushButton_allclear" > + <property name="sizePolicy" > + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize" > + <size> + <width>16777215</width> + <height>18</height> + </size> + </property> + <property name="text" > + <string>Clear</string> + </property> + </widget> + </item> + <item row="1" column="1" colspan="2" > + <widget class="QPushButton" name="pushButton_allblock" > + <property name="sizePolicy" > + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize" > + <size> + <width>16777215</width> + <height>18</height> + </size> + </property> + <property name="text" > + <string>Block</string> + </property> + </widget> + </item> + <item row="0" column="2" > + <widget class="QLCDNumber" name="lcdNumber_pending" > + <property name="sizePolicy" > + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape" > + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow" > + <enum>QFrame::Raised</enum> + </property> + <property name="smallDecimalPoint" > + <bool>true</bool> + </property> + <property name="numDigits" > + <number>3</number> + </property> + </widget> + </item> + <item row="0" column="0" colspan="2" > + <widget class="QLabel" name="label_2" > + <property name="text" > + <string>Pending messages:</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QGridLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item row="1" column="1" colspan="2" > + <widget class="QPushButton" name="pushButton_senderblock" > + <property name="sizePolicy" > + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize" > + <size> + <width>16777215</width> + <height>18</height> + </size> + </property> + <property name="text" > + <string>Block</string> + </property> + </widget> + </item> + <item row="1" column="0" > + <widget class="QPushButton" name="pushButton_senderclear" > + <property name="sizePolicy" > + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize" > + <size> + <width>16777215</width> + <height>18</height> + </size> + </property> + <property name="text" > + <string>Clear</string> + </property> + </widget> + </item> + <item row="0" column="2" > + <widget class="QLCDNumber" name="lcdNumber_pendingsender" > + <property name="sizePolicy" > + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape" > + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow" > + <enum>QFrame::Raised</enum> + </property> + <property name="smallDecimalPoint" > + <bool>true</bool> + </property> + <property name="numDigits" > + <number>3</number> + </property> + </widget> + </item> + <item row="0" column="0" colspan="2" > + <widget class="QLabel" name="label_3" > + <property name="text" > + <string>From this sender:</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QGridLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item row="0" column="2" > + <widget class="QLCDNumber" name="lcdNumber_pendingexactsame" > + <property name="sizePolicy" > + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape" > + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow" > + <enum>QFrame::Raised</enum> + </property> + <property name="smallDecimalPoint" > + <bool>true</bool> + </property> + <property name="numDigits" > + <number>3</number> + </property> + </widget> + </item> + <item row="1" column="1" colspan="2" > + <widget class="QPushButton" name="pushButton_messageblock" > + <property name="sizePolicy" > + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize" > + <size> + <width>16777215</width> + <height>18</height> + </size> + </property> + <property name="text" > + <string>Block</string> + </property> + </widget> + </item> + <item row="0" column="0" colspan="2" > + <widget class="QLabel" name="label_4" > + <property name="text" > + <string>Same exact message:</string> + </property> + </widget> + </item> + <item row="1" column="0" > + <widget class="QPushButton" name="pushButton_messageclear" > + <property name="sizePolicy" > + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize" > + <size> + <width>16777215</width> + <height>18</height> + </size> + </property> + <property name="text" > + <string>Clear</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QHBoxLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <widget class="QLabel" name="label_header" > + <property name="text" > + <string><html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Incoming message from <span style=" font-weight:600;">SENDERPLACEHOLDER</span>:</p></body></html></string> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QTextBrowser" name="textBrowser_message" > + <property name="minimumSize" > + <size> + <width>50</width> + <height>50</height> + </size> + </property> + <property name="textInteractionFlags" > + <enum>Qt::TextSelectableByMouse</enum> + </property> + </widget> + </item> + <item> + <widget class="QWidget" native="1" name="widget_showtab" > + <layout class="QVBoxLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <layout class="QHBoxLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" > + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label_showtab" > + <property name="text" > + <string><html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">It is requested that you look at the tab named <span style=" font-weight:600;">DUMMYTABNAME</span></p></body></html></string> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" > + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_showtab_gothere" > + <property name="text" > + <string>&Go there now</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label_showtaberror" > + <property name="text" > + <string><html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; color:#ff0000;">Unfortunately such a tab was not found!</span></p></body></html></string> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QHBoxLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_dismiss" > + <property name="text" > + <string>&Dismiss</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <tabstops> + <tabstop>pushButton_showtab_gothere</tabstop> + <tabstop>pushButton_dismiss</tabstop> + <tabstop>pushButton_allclear</tabstop> + <tabstop>pushButton_allblock</tabstop> + <tabstop>pushButton_senderclear</tabstop> + <tabstop>pushButton_senderblock</tabstop> + <tabstop>pushButton_messageclear</tabstop> + <tabstop>pushButton_messageblock</tabstop> + <tabstop>textBrowser_message</tabstop> + </tabstops> + <resources/> + <connections> + <connection> + <sender>pushButton_dismiss</sender> + <signal>clicked()</signal> + <receiver>VP1IncomingMessageForm</receiver> + <slot>close()</slot> + <hints> + <hint type="sourcelabel" > + <x>571</x> + <y>624</y> + </hint> + <hint type="destinationlabel" > + <x>444</x> + <y>630</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/graphics/VTI12/VTI12Gui/src/vp1mainwindow.ui b/graphics/VTI12/VTI12Gui/src/vp1mainwindow.ui new file mode 100644 index 000000000..1aa101925 --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/vp1mainwindow.ui @@ -0,0 +1,915 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>VP1MainWindow</class> + <widget class="QMainWindow" name="VP1MainWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>1281</width> + <height>913</height> + </rect> + </property> + <property name="windowTitle"> + <string>Virtual TI 12</string> + </property> + <property name="windowIcon"> + <iconset resource="vp1.qrc"> + <normaloff>:/vp1/icons/icons/3d_32x32.png</normaloff>:/vp1/icons/icons/3d_32x32.png</iconset> + </property> + <widget class="QWidget" name="centralwidget"> + <layout class="QVBoxLayout"> + <property name="leftMargin"> + <number>6</number> + </property> + <property name="topMargin"> + <number>5</number> + </property> + <property name="rightMargin"> + <number>7</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QSplitter" name="splitter_leftright"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <widget class="QWidget" name="widget_controlsContainer" native="true"> + <layout class="QVBoxLayout"> + <property name="spacing"> + <number>4</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>3</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QGroupBox" name="groupBox_channelcontrols"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Controls - No channel selected</string> + </property> + <layout class="QVBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="leftMargin"> + <number>4</number> + </property> + <property name="topMargin"> + <number>4</number> + </property> + <property name="rightMargin"> + <number>4</number> + </property> + <property name="bottomMargin"> + <number>4</number> + </property> + <item> + <layout class="QHBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QPushButton" name="pushButton_channelfullscreen"> + <property name="toolTip"> + <string>Show current channel fullscreen</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="vp1.qrc"> + <normaloff>:/vp1/icons/icons/window_fullscreen_32x32.png</normaloff>:/vp1/icons/icons/window_fullscreen_32x32.png</iconset> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pushButton_channelinformation"> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="vp1.qrc"> + <normaloff>:/vp1/icons/icons/info_32x32.png</normaloff>:/vp1/icons/icons/info_32x32.png</iconset> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_printchannel"> + <property name="toolTip"> + <string>Print channel snapshot</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="vp1.qrc"> + <normaloff>:/vp1/icons/icons/fileprint_32x32.png</normaloff>:/vp1/icons/icons/fileprint_32x32.png</iconset> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pushButton_savesnapshotchannel"> + <property name="toolTip"> + <string>Save channel snapshot to image file</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="vp1.qrc"> + <normaloff>:/vp1/icons/icons/camera.png</normaloff>:/vp1/icons/icons/camera.png</iconset> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pushButton_saveAllChannels"> + <property name="toolTip"> + <string>Save all tabs/channels as images in different files</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="vp1.qrc"> + <normaloff>:/vp1/icons/icons/window_list_32x32.png</normaloff>:/vp1/icons/icons/window_list_32x32.png</iconset> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_makeEventDisplay"> + <property name="toolTip"> + <string>Event Display Editor: Combine current tabs/channels into a single event display, with logo and event details, ready for publication.</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="vp1.qrc"> + <normaloff>:/vp1/icons/icons/event_display_32x32.png</normaloff>:/vp1/icons/icons/event_display_32x32.png</iconset> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pushButton_3D"> + <property name="toolTip"> + <string>Open the 3D Stereo tools</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="vp1.qrc"> + <normaloff>:/vp1/icons/icons/3D_mode_24x24.png</normaloff>:/vp1/icons/icons/3D_mode_24x24.png</iconset> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="Line" name="line"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QStackedWidget" name="stackedWidget_customcontrols"> + <widget class="QWidget" name="page"/> + <widget class="QWidget" name="page_2"/> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_cruise"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="title"> + <string>Cruise Mode [off]</string> + </property> + <layout class="QHBoxLayout"> + <item> + <layout class="QHBoxLayout"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <widget class="QRadioButton" name="radioButton_cruise_event"> + <property name="text"> + <string>Evt</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_cruise_tab"> + <property name="text"> + <string>Tab</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_cruise_both"> + <property name="text"> + <string>Both</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>10</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_event"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Event [No event loaded]</string> + </property> + <layout class="QHBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="leftMargin"> + <number>4</number> + </property> + <property name="topMargin"> + <number>4</number> + </property> + <property name="rightMargin"> + <number>4</number> + </property> + <property name="bottomMargin"> + <number>4</number> + </property> + <item> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <widget class="QLabel" name="label_run_event"> + <property name="text"> + <string>TextLabel</string> + </property> + <property name="textInteractionFlags"> + <set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QPushButton" name="pushButton_previousevent"> + <property name="toolTip"> + <string>Go back to previous event [Ctrl-P]</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="../src/vp1.qrc"> + <normaloff>:/vp1/icons/icons/back_32x32.png</normaloff>:/vp1/icons/icons/back_32x32.png</iconset> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pushButton_eventselect"> + <property name="toolTip"> + <string>Select an event in the current AOD file.</string> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pushButton_nextevent"> + <property name="toolTip"> + <string>Proceed to next event [Ctrl-N]</string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="vp1.qrc"> + <normaloff>:/vp1/icons/icons/forward_32x32.png</normaloff>:/vp1/icons/icons/forward_32x32.png</iconset> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pushButton_eventseek"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Seek</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pushButton_cruise"> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="vp1.qrc"> + <normaloff>:/vp1/icons/icons/redo_32x32.png</normaloff>:/vp1/icons/icons/redo_32x32.png</iconset> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="spinBox_cruise"> + <property name="alignment"> + <set>Qt::AlignRight</set> + </property> + <property name="suffix"> + <string> s</string> + </property> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>999</number> + </property> + <property name="value"> + <number>10</number> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <widget class="QSplitter" name="splitter_tabwidget_messagebox"> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="lineWidth"> + <number>0</number> + </property> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <widget class="QStackedWidget" name="stackedWidget_central"> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="lineWidth"> + <number>0</number> + </property> + <property name="currentIndex"> + <number>1</number> + </property> + <widget class="QWidget" name="page_tabwidget"> + <layout class="QVBoxLayout"> + <item> + <widget class="VP1TabWidget" name="tabWidget_central"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Ignored" vsizetype="Ignored"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>200</width> + <height>200</height> + </size> + </property> + <property name="currentIndex"> + <number>-1</number> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="page_instructions"> + <layout class="QVBoxLayout"> + <item> + <widget class="QFrame" name="frame_instructions"> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <spacer name="verticalSpacer_2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>1</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout"> + <property name="spacing"> + <number>13</number> + </property> + <item> + <widget class="QLabel" name="label"> + <property name="maximumSize"> + <size> + <width>500</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600; font-style:italic;">Welcome to Virtual TI 12</span></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; font-style:italic;"> </span><a href="[http://cern.ch/atlas-vp1]"><span style=" text-decoration: underline; color:#0000ff;">[http://cern.ch/atlas-vp1]</span></a></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">VP1 is now uses plugins to process and present the data and</p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">detector information which is available in the ATHENA process it runs on top of.</p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Most users should proceed by selecting one of these modes:</p></body></html></string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QGridLayout" name="gridLayout"> + <property name="spacing"> + <number>2</number> + </property> + <item row="0" column="0" colspan="3"> + <widget class="QPushButton" name="pushButton_quicksetup_faser"> + <property name="toolTip"> + <string>Launch the VP1FaserPlugin within a new tab</string> + </property> + <property name="text"> + <string>All studies</string> + </property> + </widget> + </item> + <item row="1" column="0" colspan="3"> + <widget class="QPushButton" name="pushButton_quicksetup_geometrystudies"> + <property name="toolTip"> + <string>Launch the VP1GeometryPlugin within a new tab</string> + </property> + <property name="text"> + <string>Geometry studies</string> + </property> + </widget> + </item> + <item row="2" column="0" colspan="3"> + <widget class="QPushButton" name="pushButton_quicksetup_analysisstudies"> + <property name="toolTip"> + <string><html><head/><body><p>Launch the Analysis Object (AOD) plugin within a new tab.</p></body></html></string> + </property> + <property name="text"> + <string>This space for rent</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QLabel" name="label_2"> + <property name="maximumSize"> + <size> + <width>500</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<table border="0" style="-qt-table-type: root; margin-top:4px; margin-bottom:4px; margin-left:4px; margin-right:4px;"> +<tr> +<td style="border: none;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Advanced users might wish to take full advantage of the flexible configuration</span></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">capabilities of VP1 by loading and configuring plugins via the &quot;Quick Launch&quot;</span></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">and &quot;Configuration&quot; menus, and by right-clicking tabs.</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Note that it is possible </span></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">to save and load configurations </span></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">from the &quot;Configuration&quot; menu.</span></p></td></tr></table></body></html></string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>1</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </widget> + <widget class="VP1TextBrowser" name="textBrowser_channelmessages"> + <property name="toolTip"> + <string>Message box. Displays messages from channels and systems.</string> + </property> + <property name="html"> + <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Cantarell'; font-size:11pt; font-weight:400; font-style:normal;"> +<table border="0" style="-qt-table-type: root; margin-top:4px; margin-bottom:4px; margin-left:4px; margin-right:4px;"> +<tr> +<td style="border: none;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:10pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:10pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:10pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:10pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:10pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:10pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:10pt;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p></td></tr></table></body></html></string> + </property> + <property name="textInteractionFlags"> + <set>Qt::TextSelectableByMouse</set> + </property> + </widget> + </widget> + </widget> + </item> + </layout> + </widget> + <widget class="QMenuBar" name="menubar"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>1281</width> + <height>42</height> + </rect> + </property> + <widget class="QMenu" name="menuConfiguration"> + <property name="title"> + <string>&Configuration</string> + </property> + <addaction name="separator"/> + </widget> + <widget class="QMenu" name="menu_Style"> + <property name="title"> + <string>&Style</string> + </property> + </widget> + <widget class="QMenu" name="menuQuick_Launch"> + <property name="title"> + <string>&Quick Launch</string> + </property> + <addaction name="action_quicklaunch_faser"/> + <!-- <addaction name="action_quicklaunch_Tracking_studies"/> + <addaction name="action_quicklaunch_Calo_studies"/> --> + <addaction name="action_quicklaunch_Geometry_studies"/> + <!-- <addaction name="action_quicklaunch_trackcalo_commis"/> --> + <addaction name="action_quicklaunch_analysisstudies"/> + <addaction name="action_quicklaunch_Storegate_browser"/> + <addaction name="separator"/> + <addaction name="action_exit_VP1"/> + </widget> + <addaction name="menuQuick_Launch"/> + <addaction name="menuConfiguration"/> + <addaction name="menu_Style"/> + </widget> + <widget class="QStatusBar" name="statusbar"/> + <action name="actionLoad_plugin"> + <property name="text"> + <string>Load plugin</string> + </property> + </action> + <action name="actionAdd_empty_tab2"> + <property name="text"> + <string>&Add empty tab</string> + </property> + </action> + <action name="actionInfo_about_loaded_plugins"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>&Info about loaded plugins</string> + </property> + </action> + <action name="actionLaunch_config_dialog"> + <property name="text"> + <string>Launch &config dialog</string> + </property> + </action> + <action name="actionLoad_tab_configuration_from_file"> + <property name="text"> + <string>&Load tab configuration from file</string> + </property> + </action> + <action name="actionSave_current_tabs2"> + <property name="text"> + <string>&Save current tab configuration to file</string> + </property> + </action> + <action name="actionDummyLoadPlugSubMenu"> + <property name="text"> + <string>DummyLoadPlugSubMenu</string> + </property> + </action> + <action name="actionLoad_Plugin"> + <property name="text"> + <string>Load Plugin</string> + </property> + </action> + <!-- <action name="action_quicklaunch_Tracking_studies"> + <property name="text"> + <string>&Tracking only studies</string> + </property> + <property name="statusTip"> + <string>Launch a tab with a track channel</string> + </property> + </action> + <action name="action_quicklaunch_Calo_studies"> + <property name="text"> + <string>&Calo only studies</string> + </property> + <property name="statusTip"> + <string>Launch a tab with a calo cells channel</string> + </property> + </action> --> + <action name="action_quicklaunch_Geometry_studies"> + <property name="text"> + <string>&Geometry studies</string> + </property> + <property name="statusTip"> + <string>Launch a tab with a geometry channel</string> + </property> + </action> + <action name="action_exit_VP1"> + <property name="text"> + <string>E&xit VP1</string> + </property> + <property name="statusTip"> + <string>Close down VP1</string> + </property> + </action> + <action name="action_quicklaunch_Storegate_browser"> + <property name="text"> + <string>&Storegate browser</string> + </property> + <property name="statusTip"> + <string>Launch a tab with a banks channel</string> + </property> + </action> + <action name="action_quicklaunch_faser"> + <property name="text"> + <string>All &Faser studies</string> + </property> + </action> + <action name="action_quicklaunch_trackcalo_commis"> + <property name="text"> + <string>T&rack/Calo commis. studies</string> + </property> + </action> + <action name="action_file_Add_event_file"> + <property name="text"> + <string>&Add event file ...</string> + </property> + </action> + <action name="actionEnableExpertSettings"> + <property name="text"> + <string>&EnableExpertSettings</string> + </property> + <property name="toolTip"> + <string>Open additional settings</string> + </property> + </action> + <action name="action_quicklaunch_analysisstudies"> + <property name="text"> + <string>A&nalysis Studies</string> + </property> + </action> + </widget> + <customwidgets> + <customwidget> + <class>VP1TabWidget</class> + <extends>QTabWidget</extends> + <header>VP1Base/VP1TabWidget.h</header> + <container>1</container> + </customwidget> + <customwidget> + <class>VP1TextBrowser</class> + <extends>QTextBrowser</extends> + <header>VTI12Gui/VP1TextBrowser.h</header> + </customwidget> + </customwidgets> + <tabstops> + <tabstop>pushButton_channelfullscreen</tabstop> + <tabstop>pushButton_channelinformation</tabstop> + <tabstop>radioButton_cruise_event</tabstop> + <tabstop>radioButton_cruise_tab</tabstop> + <tabstop>radioButton_cruise_both</tabstop> + <tabstop>tabWidget_central</tabstop> + <tabstop>textBrowser_channelmessages</tabstop> + </tabstops> + <resources> + <include location="vp1.qrc"/> + </resources> + <connections/> +</ui> diff --git a/graphics/VTI12/VTI12Gui/src/vp1plugindialog.ui b/graphics/VTI12/VTI12Gui/src/vp1plugindialog.ui new file mode 100644 index 000000000..ebd38dcba --- /dev/null +++ b/graphics/VTI12/VTI12Gui/src/vp1plugindialog.ui @@ -0,0 +1,265 @@ +<ui version="4.0" > + <class>VP1PluginDialog</class> + <widget class="QDialog" name="VP1PluginDialog" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>441</width> + <height>211</height> + </rect> + </property> + <property name="windowTitle" > + <string>Dialog</string> + </property> + <layout class="QVBoxLayout" > + <property name="margin" > + <number>9</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <layout class="QHBoxLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <layout class="QHBoxLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <widget class="QLabel" name="label_selectplugin" > + <property name="enabled" > + <bool>false</bool> + </property> + <property name="text" > + <string>Select plugin:</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="comboBox_plugins" > + <property name="enabled" > + <bool>false</bool> + </property> + <property name="minimumSize" > + <size> + <width>150</width> + <height>0</height> + </size> + </property> + <property name="minimumContentsLength" > + <number>50</number> + </property> + <item> + <property name="text" > + <string>No plugins loaded</string> + </property> + </item> + </widget> + </item> + </layout> + </item> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <layout class="QHBoxLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <widget class="QLabel" name="label_fullpathtitle" > + <property name="enabled" > + <bool>false</bool> + </property> + <property name="text" > + <string>Full path:</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_fullpath" > + <property name="enabled" > + <bool>false</bool> + </property> + <property name="text" > + <string>n/a</string> + </property> + <property name="textInteractionFlags" > + <enum>Qt::TextSelectableByMouse</enum> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <layout class="QGridLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item row="0" column="1" > + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="0" > + <widget class="QLabel" name="label_channels" > + <property name="enabled" > + <bool>false</bool> + </property> + <property name="text" > + <string>Channels available in this plugin:</string> + </property> + </widget> + </item> + <item row="1" column="0" colspan="2" > + <widget class="QTextBrowser" name="textBrowser_channels" > + <property name="minimumSize" > + <size> + <width>0</width> + <height>100</height> + </size> + </property> + <property name="frameShape" > + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow" > + <enum>QFrame::Plain</enum> + </property> + <property name="textInteractionFlags" > + <enum>Qt::TextSelectableByMouse</enum> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QVBoxLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" > + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_unload" > + <property name="enabled" > + <bool>false</bool> + </property> + <property name="text" > + <string>Unload</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pushButton_cancel" > + <property name="text" > + <string>Cancel</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>pushButton_cancel</sender> + <signal>clicked()</signal> + <receiver>VP1PluginDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel" > + <x>355</x> + <y>142</y> + </hint> + <hint type="destinationlabel" > + <x>291</x> + <y>132</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/graphics/VTI12/VTI12Plugins/VTI12FaserPlugin/CMakeLists.txt b/graphics/VTI12/VTI12Plugins/VTI12FaserPlugin/CMakeLists.txt new file mode 100644 index 000000000..8f864c585 --- /dev/null +++ b/graphics/VTI12/VTI12Plugins/VTI12FaserPlugin/CMakeLists.txt @@ -0,0 +1,29 @@ +################################################################################ +# Package: VTI12FaserPlugin +################################################################################ + +# Declare the package name: +atlas_subdir( VTI12FaserPlugin ) + +# Declare the package's dependencies: +atlas_depends_on_subdirs( + PUBLIC + graphics/VP1/VP1Base + PRIVATE + graphics/VTI12/VTI12Systems/VTI12TrackSystems + graphics/VTI12/VTI12Systems/VTI12SimHitSystems + graphics/VTI12/VTI12Systems/VTI12GeometrySystems + graphics/VTI12/VTI12Systems/VTI12GuideLineSystems ) + +# External dependencies: +find_package( Qt5 COMPONENTS Core Gui Widgets ) + +# Generate MOC files automatically: +set( CMAKE_AUTOMOC TRUE ) + +# Build the library. +atlas_add_library( VTI12FaserPlugin + VTI12FaserPlugin/*.h src/*.cxx src/*.qrc + PUBLIC_HEADERS VTI12FaserPlugin + LINK_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets + PRIVATE_LINK_LIBRARIES VP1Base VTI12GuideLineSystems VTI12GeometrySystems VTI12SimHitSystems VTI12TrackSystems) diff --git a/graphics/VTI12/VTI12Plugins/VTI12FaserPlugin/VTI12FaserPlugin/VP1FaserChannel.h b/graphics/VTI12/VTI12Plugins/VTI12FaserPlugin/VTI12FaserPlugin/VP1FaserChannel.h new file mode 100755 index 000000000..ffec5e6aa --- /dev/null +++ b/graphics/VTI12/VTI12Plugins/VTI12FaserPlugin/VTI12FaserPlugin/VP1FaserChannel.h @@ -0,0 +1,32 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////// +// // +// Header file for class VP1FaserChannel // +// // +// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Initial version: May 2007 // +// // +///////////////////////////////////////////////////////////// + +#ifndef VP1FASERCHANNEL_H +#define VP1FASERCHANNEL_H + +#include "VP1Base/IVP13DStandardChannelWidget.h" + +class VP1FaserChannel : public IVP13DStandardChannelWidget { + + Q_OBJECT + +public: + + VP1FaserChannel(); + void init(); + virtual ~VP1FaserChannel(){} + +}; + +#endif diff --git a/graphics/VTI12/VTI12Plugins/VTI12FaserPlugin/VTI12FaserPlugin/VP1FaserPlugin_VP1AutoFactory.h b/graphics/VTI12/VTI12Plugins/VTI12FaserPlugin/VTI12FaserPlugin/VP1FaserPlugin_VP1AutoFactory.h new file mode 100644 index 000000000..68b88ed29 --- /dev/null +++ b/graphics/VTI12/VTI12Plugins/VTI12FaserPlugin/VTI12FaserPlugin/VP1FaserPlugin_VP1AutoFactory.h @@ -0,0 +1,25 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ +//Autogenerated VP1 Factory Code Header File (Fri Aug 19 13:36:52 CEST 2016) + +#ifndef VTI12FaserPlugin_VP1AutoFactory_H +#define VTI12FaserPlugin_VP1AutoFactory_H + +#include <QObject> +#include <QStringList> + +#include "VP1Base/IVP1ChannelWidgetFactory.h" + +class VP1FaserPlugin_VP1AutoFactory : public QObject, public IVP1ChannelWidgetFactory +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "VP1FaserPlugin" ) + Q_INTERFACES(IVP1ChannelWidgetFactory) + +public: + virtual QStringList channelWidgetsProvided() const; + virtual IVP1ChannelWidget * getChannelWidget(const QString & channelwidget); +}; + +#endif diff --git a/graphics/VTI12/VTI12Plugins/VTI12FaserPlugin/src/VP1FaserChannel.cxx b/graphics/VTI12/VTI12Plugins/VTI12FaserPlugin/src/VP1FaserChannel.cxx new file mode 100755 index 000000000..79b2a54c2 --- /dev/null +++ b/graphics/VTI12/VTI12Plugins/VTI12FaserPlugin/src/VP1FaserChannel.cxx @@ -0,0 +1,37 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////// +// // +// Implementation of class VP1FaserChannel // +// // +// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Initial version: May 2007 // +// // +///////////////////////////////////////////////////////////// + +#include "VTI12FaserPlugin/VP1FaserChannel.h" +#include "VTI12TrackSystems/VP1TrackSystem.h" +#include "VTI12GeometrySystems/VP1GeometrySystem.h" +#include "VTI12GuideLineSystems/VP1GuideLineSystem.h" +#include "VTI12SimHitSystems/VP1SimHitSystem.h" +#include "VP1Base/VP1QtUtils.h" + +VP1FaserChannel::VP1FaserChannel() + : IVP13DStandardChannelWidget(VP1CHANNELNAMEINPLUGIN(VP1FaserChannel,"Faser"), + "This channel shows geometry, hits and tracks.", + "Dave Casper dcasper@uci.edu") +{ +} + +void VP1FaserChannel::init() +{ + addSystem(new VP1TrackSystem); + addSystem(new VP1SimHitSystem); + addSystem(new VP1GeometrySystem); + addSystem(new VP1GuideLineSystem); + // if (VP1QtUtils::environmentVariableIsOn("VP1_SECOND_GEOMSYS")) + // addSystem(new VP1GeometrySystem(VP1GeoFlags::None,"AltGeo"),IVP13DStandardChannelWidget::StartDisabled); +} diff --git a/graphics/VTI12/VTI12Plugins/VTI12FaserPlugin/src/VP1FaserPlugin_VP1AutoFactory.cxx b/graphics/VTI12/VTI12Plugins/VTI12FaserPlugin/src/VP1FaserPlugin_VP1AutoFactory.cxx new file mode 100644 index 000000000..7515ec877 --- /dev/null +++ b/graphics/VTI12/VTI12Plugins/VTI12FaserPlugin/src/VP1FaserPlugin_VP1AutoFactory.cxx @@ -0,0 +1,24 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ +//Autogenerated VP1 Factory Code Implementation File (Fri Aug 19 13:36:52 CEST 2016) + +#include <QtPlugin> +#include "VTI12FaserPlugin/VP1FaserPlugin_VP1AutoFactory.h" +#include "VTI12FaserPlugin/VP1FaserChannel.h" + +QStringList VP1FaserPlugin_VP1AutoFactory::channelWidgetsProvided() const +{ + return QStringList() + << "Faser" + ; +} + +IVP1ChannelWidget * VP1FaserPlugin_VP1AutoFactory::getChannelWidget(const QString & channelwidget) +{ + if (channelwidget == "Faser") + return new VP1FaserChannel(); + + return 0; +} + diff --git a/graphics/VTI12/VTI12Plugins/VTI12GeometryPlugin/CMakeLists.txt b/graphics/VTI12/VTI12Plugins/VTI12GeometryPlugin/CMakeLists.txt new file mode 100644 index 000000000..b6ed459a0 --- /dev/null +++ b/graphics/VTI12/VTI12Plugins/VTI12GeometryPlugin/CMakeLists.txt @@ -0,0 +1,27 @@ +################################################################################ +# Package: VTI12GeometryPlugin +################################################################################ + +# Declare the package name: +atlas_subdir( VTI12GeometryPlugin ) + +# Declare the package's dependencies: +atlas_depends_on_subdirs( + PUBLIC + graphics/VP1/VP1Base + PRIVATE + graphics/VTI12/VTI12Systems/VTI12GeometrySystems + graphics/VTI12/VTI12Systems/VTI12GuideLineSystems ) + +# External dependencies: +find_package( Qt5 COMPONENTS Core Gui Widgets ) + +# Generate MOC files automatically: +set( CMAKE_AUTOMOC TRUE ) + +# Build the library. +atlas_add_library( VTI12GeometryPlugin + VTI12GeometryPlugin/*.h src/*.cxx src/*.qrc + PUBLIC_HEADERS VTI12GeometryPlugin + LINK_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets + PRIVATE_LINK_LIBRARIES VP1Base VTI12GuideLineSystems VTI12GeometrySystems ) diff --git a/graphics/VTI12/VTI12Plugins/VTI12GeometryPlugin/VTI12GeometryPlugin/VP1GeometryChannel.h b/graphics/VTI12/VTI12Plugins/VTI12GeometryPlugin/VTI12GeometryPlugin/VP1GeometryChannel.h new file mode 100755 index 000000000..c1d67a30a --- /dev/null +++ b/graphics/VTI12/VTI12Plugins/VTI12GeometryPlugin/VTI12GeometryPlugin/VP1GeometryChannel.h @@ -0,0 +1,32 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////// +// // +// Header file for class VP1GeometryChannel // +// // +// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Initial version: May 2007 // +// // +///////////////////////////////////////////////////////////// + +#ifndef VP1GEOMETRYCHANNEL_H +#define VP1GEOMETRYCHANNEL_H + +#include "VP1Base/IVP13DStandardChannelWidget.h" + +class VP1GeometryChannel : public IVP13DStandardChannelWidget { + + Q_OBJECT + +public: + + VP1GeometryChannel(); + void init(); + virtual ~VP1GeometryChannel(){} + +}; + +#endif diff --git a/graphics/VTI12/VTI12Plugins/VTI12GeometryPlugin/VTI12GeometryPlugin/VP1GeometryPlugin_VP1AutoFactory.h b/graphics/VTI12/VTI12Plugins/VTI12GeometryPlugin/VTI12GeometryPlugin/VP1GeometryPlugin_VP1AutoFactory.h new file mode 100644 index 000000000..de6b6ef99 --- /dev/null +++ b/graphics/VTI12/VTI12Plugins/VTI12GeometryPlugin/VTI12GeometryPlugin/VP1GeometryPlugin_VP1AutoFactory.h @@ -0,0 +1,25 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ +//Autogenerated VP1 Factory Code Header File (Fri Aug 19 13:36:52 CEST 2016) + +#ifndef VP1GeometryPlugin_VP1AutoFactory_H +#define VP1GeometryPlugin_VP1AutoFactory_H + +#include <QObject> +#include <QStringList> + +#include "VP1Base/IVP1ChannelWidgetFactory.h" + +class VP1GeometryPlugin_VP1AutoFactory : public QObject, public IVP1ChannelWidgetFactory +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "VP1GeometryPlugin" ) + Q_INTERFACES(IVP1ChannelWidgetFactory) + +public: + virtual QStringList channelWidgetsProvided() const; + virtual IVP1ChannelWidget * getChannelWidget(const QString & channelwidget); +}; + +#endif diff --git a/graphics/VTI12/VTI12Plugins/VTI12GeometryPlugin/src/VP1GeometryChannel.cxx b/graphics/VTI12/VTI12Plugins/VTI12GeometryPlugin/src/VP1GeometryChannel.cxx new file mode 100755 index 000000000..4e9c373ff --- /dev/null +++ b/graphics/VTI12/VTI12Plugins/VTI12GeometryPlugin/src/VP1GeometryChannel.cxx @@ -0,0 +1,33 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////// +// // +// Implementation of class VP1GeometryChannel // +// // +// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Initial version: May 2007 // +// // +///////////////////////////////////////////////////////////// + +#include "VTI12GeometryPlugin/VP1GeometryChannel.h" +#include "VTI12GeometrySystems/VP1GeometrySystem.h" +#include "VTI12GuideLineSystems/VP1GuideLineSystem.h" +#include "VP1Base/VP1QtUtils.h" + +VP1GeometryChannel::VP1GeometryChannel() + : IVP13DStandardChannelWidget(VP1CHANNELNAMEINPLUGIN(VP1GeometryChannel,"Geometry"), + "This channel shows the geometry as defined in GeoModel.", + "Thomas.Kittelmann@cern.ch;Riccardo.Maria.Bianchi@cern.ch") +{ +} + +void VP1GeometryChannel::init() +{ + addSystem(new VP1GuideLineSystem); + addSystem(new VP1GeometrySystem); + // if (VP1QtUtils::environmentVariableIsOn("VP1_SECOND_GEOMSYS")) + // addSystem(new VP1GeometrySystem(VP1GeoFlags::None,"AltGeo"),IVP13DStandardChannelWidget::StartDisabled); +} diff --git a/graphics/VTI12/VTI12Plugins/VTI12GeometryPlugin/src/VP1GeometryPlugin_VP1AutoFactory.cxx b/graphics/VTI12/VTI12Plugins/VTI12GeometryPlugin/src/VP1GeometryPlugin_VP1AutoFactory.cxx new file mode 100644 index 000000000..23c979494 --- /dev/null +++ b/graphics/VTI12/VTI12Plugins/VTI12GeometryPlugin/src/VP1GeometryPlugin_VP1AutoFactory.cxx @@ -0,0 +1,24 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ +//Autogenerated VP1 Factory Code Implementation File (Fri Aug 19 13:36:52 CEST 2016) + +#include <QtPlugin> +#include "VTI12GeometryPlugin/VP1GeometryPlugin_VP1AutoFactory.h" +#include "VTI12GeometryPlugin/VP1GeometryChannel.h" + +QStringList VP1GeometryPlugin_VP1AutoFactory::channelWidgetsProvided() const +{ + return QStringList() + << "Geometry" + ; +} + +IVP1ChannelWidget * VP1GeometryPlugin_VP1AutoFactory::getChannelWidget(const QString & channelwidget) +{ + if (channelwidget == "Geometry") + return new VP1GeometryChannel(); + + return 0; +} + diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/CMakeLists.txt b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/CMakeLists.txt new file mode 100644 index 000000000..8224c45f6 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/CMakeLists.txt @@ -0,0 +1,57 @@ +# $Id: CMakeLists.txt 732131 2016-03-24 11:03:29Z krasznaa $ +################################################################################ +# Package: VTI12GeometrySystems +################################################################################ + +# Declare the package name: +atlas_subdir( VTI12GeometrySystems ) + +# Declare the package's dependencies: +atlas_depends_on_subdirs( + PUBLIC + DetectorDescription/GeoPrimitives + Generators/TruthUtils + Event/xAOD/xAODTruth + graphics/VP1/VP1Base + PRIVATE + DetectorDescription/GeoModel/GeoModelUtilities + DetectorDescription/GeoModel/GeoModelFaserUtilities + DetectorDescription/GeoModel/GeoModelExamples + DetectorDescription/GeoModel/GeoModelStandalone/GeoModelDBManager + DetectorDescription/GeoModel/GeoModelStandalone/GeoRead + graphics/VP1/VP1HEPVis + graphics/VTI12/VTI12Utils ) + +# External dependencies: +find_package( CLHEP ) +find_package( Coin3D ) +find_package( Qt5 COMPONENTS Core Gui Widgets Sql ) +find_package( GeoModel ) +if( APPLE ) + find_package(OpenGL REQUIRED) +endif() + +# Find includes in corresponding build directories +set(CMAKE_INCLUDE_CURRENT_DIR ON) +# Generate UI files automatically: +# Note: add the "Widgets" component to "find_package( Qt5 ...)" if you have UI files, otherwise UIC, even if CMAKE_AUTOUIC is set to ON, is not run +set( CMAKE_AUTOUIC ON ) +# Generate MOC files automatically: +set( CMAKE_AUTOMOC ON ) +# Generate resource files automatically: +set( CMAKE_AUTORCC ON ) + +### Build the library. +# Remember: the auto-generated UI files are put under +# CMAKE_CURRENT_BINARY_DIR, so it needs to be added explicitly to the +# declaration of PRIVATE_INCLUDE_DIRS. + +atlas_add_library( VTI12GeometrySystems + VTI12GeometrySystems/*.h src/*.cxx + PUBLIC_HEADERS VTI12GeometrySystems + INCLUDE_DIRS ${COIN3D_INCLUDE_DIRS} + PRIVATE_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR} + PRIVATE_DEFINITIONS ${CLHEP_DEFINITIONS} + LINK_LIBRARIES ${COIN3D_LIBRARIES} ${GEOMODEL_LIBRARIES} TruthUtils xAODTruth VP1Base GL Qt5::Core Qt5::Widgets + PRIVATE_LINK_LIBRARIES ${CLHEP_LIBRARIES} GeoModelUtilities GeoModelFaserUtilities VP1HEPVis VTI12Utils Qt5::Gui ) + diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/DumpShape.h b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/DumpShape.h new file mode 100644 index 000000000..0e6c30ccc --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/DumpShape.h @@ -0,0 +1,33 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef DUMPSHAPE_H +#define DUMPSHAPE_H + +/////////////////////////////////////////////////////////////////////// +// // +// Convenience class used to dump the parameters of a GeoShape to a // +// printable form (represented by a QStringList) // +// // +// Original code by Joe Boudreau, adapted // +// in the present form by T. Kittelmann // +// // +/////////////////////////////////////////////////////////////////////// + +#include <QStringList> + +class GeoShape; + +class DumpShape { +public: + + static QStringList shapeToStringList(const GeoShape* shape); +private: + + DumpShape(){}; + ~DumpShape(){}; + +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/GeoSysController.h b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/GeoSysController.h new file mode 100644 index 000000000..415a978f3 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/GeoSysController.h @@ -0,0 +1,123 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class GeoSysController // +// // +// Description: Controller for the geometry system. // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: October 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef GEOSYSCONTROLLER_H +#define GEOSYSCONTROLLER_H + +#include "VP1Base/VP1Controller.h" +#include "VTI12GeometrySystems/VP1GeoFlags.h" +class VolumeHandle; +class SoGroup; +class SoPickStyle; +class VP1GeoTreeView; +class PhiSectionWidget; +class ZappedVolumeListModel; + +class GeoSysController : public VP1Controller { + + Q_OBJECT + +public: + + GeoSysController(IVP1System * sys); + virtual ~GeoSysController(); + + //Change defaults (call right after constructor): + void setGeometrySelectable(bool); + void setZoomToVolumeOnClick(bool); + void setComplexity(double); + + // Labels +// void setAvailableLabels(IVP1System* sys, QStringList providedLabels); + void setLabelsEnabled(bool t0s, bool hits); //!< controls whether the checkboxes are enabled or not. Set in e.g. VP1SysConf.cxx, via VP1GeometrySystem + + void actualRestoreSettings(VP1Deserialise&); + int currentSettingsVersion() const; + void actualSaveSettings(VP1Serialise&) const; + + void setLastSelectedVolume(VolumeHandle*); + VolumeHandle* lastSelectedVolume() const; + + QCheckBox * subSystemCheckBox(VP1GeoFlags::SubSystemFlag) const;//Checkbox will be disabled + //if corresponding geometry + //is not present in job. + + SoGroup * drawOptions() const; + SoPickStyle * pickStyle() const; + VP1GeoTreeView * volumeTreeBrowser() const; + PhiSectionWidget * phiSectionWidget() const; + ZappedVolumeListModel * zappedVolumeListModel() const; + + /////////////////////////////////// + // Access Methods for settings // + /////////////////////////////////// + + //Those only queried on-demand: + bool printInfoOnClick_Shape() const; + bool printInfoOnClick_Material() const; + bool printInfoOnClick_CopyNumber() const; + bool printInfoOnClick_Transform() const; + bool printInfoOnClick_Tree() const; + bool printInfoOnClick_Mass() const; + bool zoomToVolumeOnClick() const; + + //Settings with change signals: + + float transparency() const; + bool showVolumeOutLines() const; + int labels() const; + QList<int> labelPosOffset() ; //!< Offset in x,y,z + + /////////////////////////////////////// + // Signals for changes in settings // + /////////////////////////////////////// +signals: + + //Change signals: + void transparencyChanged(float); + void showVolumeOutLinesChanged(bool); + void labelsChanged(int); + void labelPosOffsetChanged(QList<int>); + + //Signals without state: + void resetSubSystems(VP1GeoFlags::SubSystemFlags); + void autoExpandByVolumeOrMaterialName(bool,QString);//volname: (false,namestr), matname: (true,namestr) + void actionOnAllNonStandardVolumes(bool);//true: zap, false: expand. + void volumeStateChangeRequested(VolumeHandle*,VP1GeoFlags::VOLSTATE);//Might not be used atm. + void volumeResetRequested(VolumeHandle*); + + void saveMaterialsToFile(QString,bool);//(filename,onlyChangedMaterials) + void loadMaterialsFromFile(QString);//filename + +private: + + class Imp; + Imp * m_d; + +private slots: + void possibleChange_transparency(); + void possibleChange_showVolumeOutLines(); + void updatePickStyle(); + void saveMaterialsRequested(); + void loadMaterialsRequested(); + void emit_autoExpandByVolumeOrMaterialName(); + void emit_actionOnAllNonStandardVolumes(); + void emit_resetSubSystems(); + void possibleChange_labels(); + void possibleChange_labelPosOffset(); +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/PhiSectorManager.h b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/PhiSectorManager.h new file mode 100644 index 000000000..974a47f39 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/PhiSectorManager.h @@ -0,0 +1,78 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef PHISECTORMANAGER_H +#define PHISECTORMANAGER_H + +///////////////////////////////////////////////////////////////////////// +// // +// Header file for class PhiSectorManager // +// // +// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Initial VP1 version: September 2007 // +// // +///////////////////////////////////////////////////////////////////////// + +#include <QObject> +#include "VTI12GeometrySystems/VP1GeoFlags.h" + +class PhiSectionWidget; + +class SoSwitch; +class SoSeparator; +class SoNode; +class SbMatrix; +class VP1ExtraSepLayerHelper; +class IVP1System; + +class PhiSectorManager : public QObject { + + Q_OBJECT + +public: + + PhiSectorManager(PhiSectionWidget *, IVP1System *, QObject*parent=0); + virtual ~PhiSectorManager(); + + //Used by the geometry system to let the manager know under separator stuff for a given subsystem goes: + void registerSubSystemSeparator(VP1GeoFlags::SubSystemFlag flag,SoSeparator * subsystemsep); + + //Volume handles first call this method to figure out what kind of volume they are: + int getVolumeType(const SbMatrix& transform, SoNode * shape) const; + //The return value, iphi, indicates the type: + // 0...(nphi-1): Volume with a bounding box not around the Z axis. + // -1: Volume has bounding box around Z-axis, but can not be dynamically altered (probably boolean) + // -2: Volume is around Z-axis AND can be dynamically subdivided (SoTubs, SoCons, SoPcons, SoLAr). + //if return value was >=-1, attach it via (iphi is the return value from getVolumeType): + VP1ExtraSepLayerHelper * getSepHelperForNode(VP1GeoFlags::SubSystemFlag flag, int iphi); + + /** Addition to handle label separators, in exactly the same way as getSepHelperForNode(...)*/ + VP1ExtraSepLayerHelper * getLabelSepHelperForNode(VP1GeoFlags::SubSystemFlag flag, int iphi); + //if return value was -2, a call to the following is required + //instead (again the returned helper is to be used to attach/detach + //the nodesep to the scenegraph: + VP1ExtraSepLayerHelper * registerVolumeAroundZAxis( VP1GeoFlags::SubSystemFlag flag, SoSwitch* sw, const SbMatrix& tranformation ); + //NB: The switch should have your regular shape as its only child (other stuff for the dynamical volumes will be added dynamically): + //NB: "tranformation" must be the complete transformation up to the shape. + + //For updating the phi-slicings: + void updateRepresentationsOfVolsAroundZAxis(); + + //If changing the states of a lot of volume handles, call these before and after. + void largeChangesBegin(); + void largeChangesEnd(); + +protected slots: + void enabledPhiSectorsChanged(); + void updateEnabledPhiSections(int); + +private: + + class Imp; + Imp * m_d; + +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VP1GeoFlags.h b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VP1GeoFlags.h new file mode 100644 index 000000000..6fdd33808 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VP1GeoFlags.h @@ -0,0 +1,93 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1GeoFlags // +// // +// Description: Flags for geometry system. // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: October 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VP1GEOFLAGS_H +#define VP1GEOFLAGS_H + +#include <QFlags> +#include <QString> + +class VP1GeoFlags { +public: + + enum SubSystemFlag { // 32-bits hexadecimal bitmask + + None = 0x00000000, + Veto = 0x00000001, + Trigger = 0x00000002, + Preshower = 0x00000004, + + SCT = 0x00000008, + + Ecal = 0x00000010, + // Pixel = 0x00000001, // bit 0 + // SCT = 0x00000002, // 1 + // TRT = 0x00000004, // 2 + // InDetServMat = 0x00000008, // 3 + + // LAr = 0x00000010, // 4 + // Tile = 0x00000020, // 5 + // BarrelToroid = 0x00000040, // 6 - FIXME - make barrel + // MuonBarrelStationInner = 0x00000080, // 7 + + // MuonBarrelStationMiddle = 0x00000100, // 8 + // MuonBarrelStationOuter = 0x00000200, // 9 + // MuonEndcapStationCSC = 0x00000400, // 10 + // MuonEndcapStationTGC = 0x00000800, // 11 + + // MuonEndcapStationMDT = 0x00001000, // 12 + // AllMuonChambers = 0x00001F80, // == all bits occupied by the Muon chambers (80+100+200+400+800+1000) + // CavernInfra = 0x00002000, // 13 + // BeamPipe = 0x00004000, // 14 + // // free = 0x00008000, // 15 + + // LUCID = 0x00010000, // 16 + // ZDC = 0x00020000, // 17 + // ALFA = 0x00040000, // 18 + // ToroidECA = 0x00080000, // 19 + + // ToroidECC = 0x00100000, // 20 FIXME! Remove and cleanup nomenclature + // MuonFeet = 0x00200000, // 21 + // MuonShielding = 0x00400000, // 22 + // MuonToroidsEtc = 0x00800000, // 23 + + // MuonEndcapStationNSW = 0x01000000, // 24 + // ForwardRegion = 0x02000000, // 25 + // free = 0x04000000, // 26 + // free = 0x08000000, // 27 + + // free = 0x10000000, // 28 + // free = 0x20000000, // 29 + // free = 0x40000000, // 30 + AllUnrecognisedVolumes = 0x80000000 // bit 31 + }; + Q_DECLARE_FLAGS(SubSystemFlags, SubSystemFlag) + + //VolumeState: + enum VOLSTATE { CONTRACTED,//Show volume if parent is EXPANDED, never show children. + EXPANDED,//Dont show volume ( => show all un-zapped children or their children as appropriate). + ZAPPED//Dont show volume ( => show no children). + }; + static QString toString(const VOLSTATE&); + +private: + VP1GeoFlags(); + ~VP1GeoFlags(); +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(VP1GeoFlags::SubSystemFlags) + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VP1GeoTreeView.h b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VP1GeoTreeView.h new file mode 100644 index 000000000..dffa89424 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VP1GeoTreeView.h @@ -0,0 +1,48 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1GeoTreeView // +// // +// Description: ... // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: January 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VP1GEOTREEVIEW_H +#define VP1GEOTREEVIEW_H + +#include <QTreeView> + +class VP1GeoTreeView : public QTreeView { + + Q_OBJECT + +public: + + VP1GeoTreeView(QWidget * parent = 0); + virtual ~VP1GeoTreeView(); + +public slots: + void updateAllNonHiddenIndices();//Useful, but not particularly inexpensive to call. + void scheduleUpdateOfAllNonHiddenIndices();//Will call the previous + //method after event + //queue is empty. Even if + //this method is called + //multiple times before + //that happens, only one + //update will be + //triggered. +private: + + class Imp; + Imp * m_d; + +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VP1GeomUtils.h b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VP1GeomUtils.h new file mode 100644 index 000000000..29f343da4 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VP1GeomUtils.h @@ -0,0 +1,23 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef VP1GEOMUTILS_H +#define VP1GEOMUTILS_H + +class GeoMaterial; +class GeoElement; +#include <QStringList> + +class VP1GeomUtils { +public: + + static QStringList geoMaterialToStringList(const GeoMaterial*); + static QStringList geoElementToStringList(const GeoElement*); + +private: + VP1GeomUtils() {} + ~VP1GeomUtils() {} +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VP1GeometrySystem.h b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VP1GeometrySystem.h new file mode 100644 index 000000000..15017454c --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VP1GeometrySystem.h @@ -0,0 +1,94 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef VP1GEOMETRYSYSTEM_H +#define VP1GEOMETRYSYSTEM_H + +///////////////////////////////////////////////////////////////////////// +// // +// Header file for class VP1GeometrySystem // +// // +// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Derived from V-atlas geometry system by Joe Boudreau. // +// Origins of initial version dates back to ~1996, initial VP1 // +// version by TK (May 2007) and almost entirely rewritten Oct 2007 // +// // +///////////////////////////////////////////////////////////////////////// + +#include "VP1Base/IVP13DSystemSimple.h" +#include "GeoModelKernel/GeoPVConstLink.h"//It would be good to get rid of this. +#include "VTI12GeometrySystems/VP1GeoFlags.h" +#include "VTI12GeometrySystems/VolumeHandle.h"//fixme +#include <set> +#include <map> +#include <QStack> +#include <QString> + +class VP1GeometrySystem : public IVP13DSystemSimple { + + Q_OBJECT + +public: + + + VP1GeometrySystem( const VP1GeoFlags::SubSystemFlags& SubSystemsTurnedOn = VP1GeoFlags::None, + QString name = "Geo" ); + virtual ~VP1GeometrySystem(); + + //Method that channel can use to override defaults: + void setGeometrySelectable(bool); + void setZoomToVolumeOnClick(bool); + void setOrientViewToMuonChambersOnClick(bool); + + + QWidget * buildController(); + + void systemcreate(StoreGateSvc*detstore); + void buildPermanentSceneGraph(StoreGateSvc* detstore, SoSeparator *root); + void buildEventSceneGraph(StoreGateSvc*, SoSeparator *) {} + void userPickedNode(SoNode* pickedNode, SoPath *pickedPath); + void systemuncreate(); + + QByteArray saveState(); + void restoreFromState(QByteArray); + void enableMuonChamberLabels(bool, bool);//!< first is t0s, 2nd is hits + +signals: + void appropriateMDTProjectionsChanged(int);//To give hints to prd/track/segment systems about + //0: No projections, 1: Project to end of tubes, 2: Project to end of chamber volume. + void plotSpectrum(QStack<QString>&, int copyNumber=-1); // Send information about selected volume to the VP1UtilitySystems::PartSpectSystem + //The stack represents the path to the selected volume. The entries of this patch have form Volname::CopyNo + //The Volname is either physical volume name, or, in case the former is absent, the logical volume name + //The ::CopyNo suffix is added only when CopyNo is applicable + +public slots: + + void setCurvedSurfaceRealism(int);//Accepts values in the range 0..100. +protected slots: + void checkboxChanged(); + void updateTransparency(); + + // void autoAdaptPixelsOrSCT(bool,bool,bool,bool,bool,bool);//pixel,brl,ecA,ecC,bcmA,bcmC + void resetSubSystems(VP1GeoFlags::SubSystemFlags); + void autoExpandByVolumeOrMaterialName(bool,QString);//volname: (false,namestr), matname: (true,namestr) + void actionOnAllNonStandardVolumes(bool);//true: zap, false: expand. + + void volumeStateChangeRequested(VolumeHandle*,VP1GeoFlags::VOLSTATE); + void volumeResetRequested(VolumeHandle*); + + void setShowVolumeOutLines(bool); + + void saveMaterialsToFile(QString,bool);//(filename,onlyChangedMaterials) + void loadMaterialsFromFile(QString);//filename + + void setLabels(int); + void setLabelPosOffsets(QList<int>); + +protected: + class Imp; + Imp * m_d; +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VisAttributes.h b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VisAttributes.h new file mode 100644 index 000000000..b2b9ac460 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VisAttributes.h @@ -0,0 +1,71 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef VP1GEOMETRYSYSTEMS_GEOVISATTRIBUTES_H +#define VP1GEOMETRYSYSTEMS_GEOVISATTRIBUTES_H + +#include <string> +#include <QByteArray> +#include <QMap> +#include <QString> +class SoMaterial; + +class VisAttributes { + + public: + + // Constructor: + VisAttributes(); + //delete copy + VisAttributes(const VisAttributes &) = delete; + //delete assignment + VisAttributes & operator=(const VisAttributes &)=delete; + void init();//Call at end of constructor in derived classes. + // Destructor: + virtual ~VisAttributes(); + + // Fetch a material + SoMaterial *get(const std::string & name) const; + + //Override transparencies of materials (will multiply current transparencies): + void overrideTransparencies(float transpfact); + + QByteArray getState(bool onlyChangedMaterials=true); + void applyState(QByteArray); + + protected: + + // Add a material + void add(const std::string & name, SoMaterial *); + + private: + + class Imp; + Imp * m_d; + + +}; + + +// A list of Vis attributes for Detectors: +class DetVisAttributes : public VisAttributes { + public: + DetVisAttributes(); +}; + + +// A list of Vis attributes for Materials: +class MatVisAttributes : public VisAttributes { + public: + MatVisAttributes(); +}; + + +// A list of Vis attributes for Volumes: +class VolVisAttributes : public VisAttributes { + public: + VolVisAttributes(); +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VolumeHandle.h b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VolumeHandle.h new file mode 100644 index 000000000..8ea699358 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VolumeHandle.h @@ -0,0 +1,174 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef VOLUMEHANDLE_H +#define VOLUMEHANDLE_H + +#include <vector> + +#include "VTI12GeometrySystems/VP1GeoFlags.h" +#include "GeoModelKernel/GeoPVConstLink.h" +#include <QString> + +//Only initialises child classes on demand. And even then their SoNodes are not initialised until they must be shown. +class VolumeHandleSharedData; +class SoMaterial; +class SoSeparator; +class GeoMaterial; +#include <Inventor/C/errors/debugerror.h> +#include <Inventor/SbMatrix.h> + +class VolumeHandle { +public: + + enum MuonChamberState { NONMUONCHAMBER,//Default + MUONCHAMBERCHILD,//Top-level parent is muon chamber + MUONCHAMBER,//Muon chamber, adjusted to event data + MUONCHAMBER_DIRTY };//Muon chamber, not adjusted to event data + inline bool isInMuonChamber() const;//Muon chamber volume or muon chamber offspring + inline bool isMuonChamber() const;//Muon chamber volume (top-level volume) + inline void setMuonChamberDirty(bool);//Don't call unless isMuonChamber() + inline bool muonChamberDirty() const;//if is a muon chamber volume which is dirty + inline MuonChamberState muonChamberState() const; + + VolumeHandle(VolumeHandleSharedData * ,VolumeHandle * parent, const GeoPVConstLink&,int childNumber, + const MuonChamberState& mcs = NONMUONCHAMBER, const SbMatrix& accumTrans = SbMatrix() ); + + virtual ~VolumeHandle();//lots of stuff to do here! + //Used (recursively) upon deletion (never delete before children are deleted). + void initialiseChildren(); + inline bool childrenAreInitialised() const; //Always check this before getting the child list iterators + unsigned nChildren() const;//Works even before children are initialised + + SoMaterial * material(); + + //Information for printout: + QString getName() const; + int copyNumber() const;//Returns -1 if doesnt have a valid copy number (because volume is not replicated), -2 in case of error. + quint32 hashID() const;//For vp1 persistification + + GeoPVConstLink geoPVConstLink() const; + const GeoMaterial * geoMaterial() const; + std::string getNameStdString() const; + + bool hasName(const std::string&) const; + + const SbMatrix& getGlobalTransformToVolume() const;//Transform from world to this volume. + SbMatrix getLocalTransformToVolume() const;//Transform from mother (=world for treetops) to this volume. + + bool isPositiveZ() const;//Uses getGlobalTransformToVolume to figure out whether Z of the transformation. + + ///////////////////// + // Navigation: // + ///////////////////// + typedef std::vector<VolumeHandle *> VolumeHandleList; + typedef VolumeHandleList::iterator VolumeHandleListItr; + typedef VolumeHandleList::const_iterator VolumeHandleListConstItr; + + inline VolumeHandle * parent();//returns 0 if toplevel. + inline VolumeHandle * topLevelParent();//goes up through parents and returns the toplevel one (returns itself if toplevel). + inline VolumeHandleListItr childrenBegin();//Dont use if not childrenAreInitialised(). + inline VolumeHandleListItr childrenEnd();//Dont use if not childrenAreInitialised() + inline VolumeHandle * child(int index) const;//Will crash if out of range! + inline int childNumber() const; + + // void zoomToVolume(SoCamera*, SoSeparator * root); + // void ensureVisibleInTreeWidget(); + + inline VP1GeoFlags::VOLSTATE state() const; + void setState( const VP1GeoFlags::VOLSTATE& state ); + void reset();//Set state of volume and all daughters to contracted + bool isAttached() const; + void contractDaughtersRecursively(); + + bool isEther() const; + void expandMothersRecursivelyToNonEther();//expands the tree down to volumes that are either not ether or without children + + bool isInitialisedAndHasNonStandardShape() const;//True if the 3D shape of this volume can not be represented by standard VRML nodes. + + SoSeparator * nodeSoSeparator() const;//Returns pointer to 3D representation of volume (null if not built yet). + void ensureBuildNodeSep(); + + //Convenience: + // void zap(); + // void ensureVisible(); + // void expandAllChildren(unsigned limit = 50); + + // void ensureVisibleInTreeWidget(); + // double mass() const; + // int copyNumber() const; + // ... + // Get SoNodes, pvconstlink, ... + + void updateLabels(); + + QByteArray getPersistifiableState() const; + void applyPersistifiableState(QByteArray); + + // Which subsystem I'm in? + VP1GeoFlags::SubSystemFlag subsystem() const; + + // For labels + virtual QString getDescriptiveName() const; + virtual QString muonChamberT0(unsigned int=0) const; + +public: + class Imp;//For once this is declared public. This is to avoid + //problems with datastream operators. +private: + + // Illegal to copy/assign a VolumeHandle: + VolumeHandle(const VolumeHandle & ); + VolumeHandle & operator= (const VolumeHandle & ); + + Imp * m_d; + + //Here for inline methods: + const int m_childNumber;//0 if the first child of parent, 1 if the second, etc. + const unsigned m_nchildren;//cached for efficiency. + MuonChamberState m_muonChamberState; + + VolumeHandle * m_parent; + VolumeHandleList m_children; + VP1GeoFlags::VOLSTATE m_state; + //Some of these could be moved to private implementation with some care: + bool haveParentsNotExpanded() const; + void attachAllContractedChildren();//also checks children of expanded children (recursively). + void detachAllContractedChildren();//also checks children of expanded children (recursively). +}; + +///////////////// +// INLINES // +///////////////// + +inline VolumeHandle * VolumeHandle::parent() { return m_parent; } +inline VolumeHandle * VolumeHandle::topLevelParent() { return m_parent ? m_parent->topLevelParent() : this; } +inline bool VolumeHandle::childrenAreInitialised() const { return m_children.size()==m_nchildren; } +inline VolumeHandle::VolumeHandleListItr VolumeHandle::childrenBegin() { return m_children.begin(); } +inline VolumeHandle::VolumeHandleListItr VolumeHandle::childrenEnd() { return m_children.end(); } +inline unsigned VolumeHandle::nChildren() const { return m_nchildren; } +inline VolumeHandle * VolumeHandle::child(int index) const { return m_children.at(index); } +inline int VolumeHandle::childNumber() const { return m_childNumber; } +inline VP1GeoFlags::VOLSTATE VolumeHandle::state() const { return m_state; } +inline bool VolumeHandle::isInMuonChamber() const { return m_muonChamberState!=NONMUONCHAMBER; } +inline bool VolumeHandle::isMuonChamber() const { return m_muonChamberState==MUONCHAMBER || m_muonChamberState==MUONCHAMBER_DIRTY; } +inline VolumeHandle::MuonChamberState VolumeHandle::muonChamberState() const { return m_muonChamberState; } +inline void VolumeHandle::setMuonChamberDirty(bool b) { if (isMuonChamber()) m_muonChamberState = b?MUONCHAMBER_DIRTY:MUONCHAMBER; } +inline bool VolumeHandle::muonChamberDirty() const { return m_muonChamberState==MUONCHAMBER_DIRTY; } +inline void VolumeHandle::reset() { + setState( VP1GeoFlags::CONTRACTED ); + contractDaughtersRecursively(); +} +inline QString VolumeHandle::getDescriptiveName() const { + QString name = getName(); + name.remove("_Station"); + return name; +} + +inline QString VolumeHandle::muonChamberT0(unsigned int /**i*/) const { + return QString(); +} + + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VolumeHandleSharedData.h b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VolumeHandleSharedData.h new file mode 100644 index 000000000..dbc9b1d35 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VolumeHandleSharedData.h @@ -0,0 +1,72 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef VOLUMEHANDLESHAREDDATA_H +#define VOLUMEHANDLESHAREDDATA_H + +//This reference counted class keeps data (and related methods) which are common +//for all volume handle nodes under a given top-level handle. + +#include "GeoModelKernel/GeoPVConstLink.h" +#include "VTI12GeometrySystems/VP1GeoFlags.h" +#include <map> +class SoNode; +class SoGroup; +class SoSeparator; +class VolumeHandle; +class SoMaterial; +class PhiSectorManager; +class ZappedVolumeListModel; +class MatVisAttributes; +class VolVisAttributes; +class VP1GeoTreeView; +class GeoSysController; + +class VolumeHandleSharedData { +public: + VolumeHandleSharedData(GeoSysController * controller,VP1GeoFlags::SubSystemFlag,std::map<SoSeparator*,VolumeHandle*>* sonodesep2volhandle, + const GeoPVConstLink& motherpV,PhiSectorManager*, + SoMaterial * topMaterial,MatVisAttributes *,VolVisAttributes *, + ZappedVolumeListModel *, VP1GeoTreeView *, SoSeparator*); + ~VolumeHandleSharedData(); + void ref(); + void unref(); + + //Fixme: Inline? + GeoPVConstLink geoPVConstLinkOfTreeTopsMother() const; + PhiSectorManager* phiSectorManager() const; + VP1GeoFlags::SubSystemFlag subSystemFlag() const; + SoMaterial * fallBackTopLevelMaterial() const; + VP1GeoTreeView * volumeBrowser() const { return m_volumebrowser; } + MatVisAttributes * matVisAttributes() const; + VolVisAttributes * volVisAttributes() const; + inline SoSeparator* textSep() const {return m_textSep;} + GeoSysController* controller() const; + void addZappedVolumeToGui(VolumeHandle*); + void removeZappedVolumesFromGui(VolumeHandle*); + + SoNode * toShapeNode(const GeoPVConstLink& pV);//Returns shape of pV->getLogVol() (uses shared instancing as appropriate) + SoNode * getSoCylinderOrientedLikeGeoTube(const double& radius, const double& halfLength);//(uses shared instancing as appropriate) + + void registerNodeSepForVolumeHandle(SoSeparator*,VolumeHandle*); + + static void setShowVolumeOutlines(SoGroup*nodesep,bool showvol); + + +private: + + // It is illegal to copy/assign a VolumeHandleSharedData: + VolumeHandleSharedData(const VolumeHandleSharedData & ); + VolumeHandleSharedData & operator= (const VolumeHandleSharedData & ); + + class Imp; + Imp * m_d; + + //For inlines: + VP1GeoTreeView * m_volumebrowser; + SoSeparator* m_textSep; //!< base text sep + +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VolumeTreeModel.h b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VolumeTreeModel.h new file mode 100644 index 000000000..964787fe2 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/VolumeTreeModel.h @@ -0,0 +1,51 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef VOLUMETREEMODEL_H +#define VOLUMETREEMODEL_H + +#include <QAbstractItemModel> + +#include "VTI12GeometrySystems/VolumeHandle.h" +#include "VTI12GeometrySystems/VP1GeoFlags.h" +#include "VP1Base/VP1Msg.h" + +class VolumeTreeModel : public QAbstractItemModel { + + Q_OBJECT + +public: + + VolumeTreeModel( QObject * parent = 0 ); + virtual ~VolumeTreeModel(); + + //These are the methods used by the geometry system: + void addSubSystem( VP1GeoFlags::SubSystemFlag flag, + const VolumeHandle::VolumeHandleList& roothandles ); + void enableSubSystem(VP1GeoFlags::SubSystemFlag flag); + void disableSubSystem(VP1GeoFlags::SubSystemFlag flag); + + void getRootHandles(std::vector<std::pair<VolumeHandle::VolumeHandleListItr,VolumeHandle::VolumeHandleListItr> >&) const; + + //The following are for use by the view: + QModelIndex index(int, int, const QModelIndex&) const; + QModelIndex parent(const QModelIndex&) const; + int rowCount(const QModelIndex&) const; + int columnCount(const QModelIndex& idx) const { return rowCount(idx) > 0 ? 1 : 0; } + QVariant data(const QModelIndex&, int) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + QVariant headerData(int section, Qt::Orientation orientation,int role) const; + bool hasChildren ( const QModelIndex & parent = QModelIndex() ) const; + bool canFetchMore ( const QModelIndex & parent ) const; + void fetchMore ( const QModelIndex & parent ); + + //To be called from system uncreate: + void cleanup(); +private: + class Imp; + Imp * m_d; + +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/ZappedVolumeListModel.h b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/ZappedVolumeListModel.h new file mode 100644 index 000000000..30478bdca --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/VTI12GeometrySystems/ZappedVolumeListModel.h @@ -0,0 +1,75 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef ZAPPEDVOLUMELISTMODEL_H +#define ZAPPEDVOLUMELISTMODEL_H + +#include <QAbstractListModel> +#include <QList> +#include "VTI12GeometrySystems/VolumeHandle.h" + +class QWidget; +class QToolBox; + +class ZappedVolumeListModel : public QAbstractListModel { + + Q_OBJECT + +public: + + ZappedVolumeListModel(QObject * parent = 0); + + virtual ~ZappedVolumeListModel(); + + inline int rowCount ( const QModelIndex & parent = QModelIndex() ) const; + inline Qt::ItemFlags flags ( const QModelIndex & index ) const; + inline QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const; + + //For use by VolumeHandleSharedData's: + inline void addToZappedVolumes( VolumeHandle * );//Assumes that the handle is known not to be zapped before. + inline void removeFromZappedVolumes( VolumeHandle * );//Assumes that the handle is known to be zapped before. + +public slots: + void activated(const QModelIndex&); + +private: + + QList<VolumeHandle*> m_zappedhandles; +}; + +///////////////// +// INLINES // +///////////////// + +inline int ZappedVolumeListModel::rowCount ( const QModelIndex & parent ) const +{ + return parent.isValid() ? 0 : m_zappedhandles.count(); +} + +inline Qt::ItemFlags ZappedVolumeListModel::flags ( const QModelIndex & index ) const +{ + return index.isValid() ? (Qt::ItemIsEnabled|Qt::ItemIsSelectable) : static_cast<Qt::ItemFlags>(0); +} + + +inline QVariant ZappedVolumeListModel::data ( const QModelIndex & index, int role ) const +{ + return (role!=Qt::DisplayRole||!index.isValid()) ? QVariant() : m_zappedhandles.at(index.row())->getName(); +} + +inline void ZappedVolumeListModel::addToZappedVolumes( VolumeHandle * handle ) +{ + beginResetModel(); // see: http://doc.qt.io/qt-5/qabstractitemmodel-obsolete.html + m_zappedhandles << handle; + endResetModel(); +} + +inline void ZappedVolumeListModel::removeFromZappedVolumes( VolumeHandle * handle ) +{ + beginResetModel(); + m_zappedhandles.removeAll(handle); + endResetModel(); +} + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/DumpShape.cxx b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/DumpShape.cxx new file mode 100644 index 000000000..a40832eff --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/DumpShape.cxx @@ -0,0 +1,240 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "VTI12GeometrySystems/DumpShape.h" + +#include "GeoPrimitives/GeoPrimitives.h" +#include "GeoModelKernel/GeoShape.h" +#include "GeoModelKernel/GeoBox.h" +#include "GeoModelKernel/GeoTubs.h" +#include "GeoModelKernel/GeoTube.h" +#include "GeoModelKernel/GeoCons.h" +#include "GeoModelKernel/GeoTrap.h" +#include "GeoModelKernel/GeoTrd.h" +#include "GeoModelKernel/GeoPcon.h" +#include "GeoModelKernel/GeoPgon.h" +#include "GeoModelKernel/GeoPara.h" +#include "GeoModelKernel/GeoShapeShift.h" +#include "GeoModelKernel/GeoShapeUnion.h" +#include "GeoModelKernel/GeoShapeIntersection.h" +#include "GeoModelKernel/GeoShapeSubtraction.h" +#include "GeoModelKernel/GeoGenericTrap.h" + +#include "CLHEP/Units/SystemOfUnits.h" +#include "CLHEP/Vector/TwoVector.h" + +#include "VTI12Utils/VP1LinAlgUtils.h" +#include "Inventor/SbMatrix.h" +#include <cassert> + +//Fixme: Add support for the SimpleBREP GeoShape. + +//____________________________________________________________________ +QStringList DumpShape::shapeToStringList(const GeoShape* shape) +{ + QStringList out; + + if(shape->typeID() == GeoBox::getClassTypeID() ) { + const GeoBox* theBox = dynamic_cast<const GeoBox*> (shape); + assert(theBox); + if (theBox){ + out << " =========> Box:"; + out << " X = "+QString::number(theBox->getXHalfLength()/CLHEP::mm)+" mm"; + out << " Y = "+QString::number(theBox->getYHalfLength()/CLHEP::mm)+" mm"; + out << " Z = "+QString::number(theBox->getZHalfLength()/CLHEP::mm)+" mm"; + } + } else if(shape->typeID() == GeoTube::getClassTypeID() ) { + const GeoTube* theTube = dynamic_cast<const GeoTube*> (shape); + assert(theTube); + if (theTube){ + out << " =========> Tube:"; + out << " RMin = "+QString::number(theTube->getRMin()/CLHEP::mm)+" mm"; + out << " RMax = "+QString::number(theTube->getRMax()/CLHEP::mm)+" mm"; + out << " DZ = "+QString::number(theTube->getZHalfLength()/CLHEP::mm)+" mm"; + } + } else if(shape->typeID() == GeoTubs::getClassTypeID() ) { + const GeoTubs* theTubs = dynamic_cast<const GeoTubs*> (shape); + assert(theTubs); + if (theTubs){ + out << " =========> Tubs:"; + out << " RMin = "+QString::number(theTubs->getRMin()/CLHEP::mm)+" mm"; + out << " RMax = "+QString::number(theTubs->getRMax()/CLHEP::mm)+" mm"; + out << " DZ = "+QString::number(theTubs->getZHalfLength()/CLHEP::mm)+" mm"; + out << " SPhi = "+QString::number(theTubs->getSPhi()); + out << " DPhi = "+QString::number(theTubs->getDPhi()); + } + } else if(shape->typeID() == GeoTrd::getClassTypeID() ) { + const GeoTrd* theTrd = dynamic_cast<const GeoTrd*> (shape); + assert(theTrd); + if (theTrd){ + out << " =========> Trd:"; + out << " X1 = "+QString::number(theTrd->getXHalfLength1()/CLHEP::mm)+" mm"; + out << " X2 = "+QString::number(theTrd->getXHalfLength2()/CLHEP::mm)+" mm"; + out << " Y1 = "+QString::number(theTrd->getYHalfLength1()/CLHEP::mm)+" mm"; + out << " Y2 = "+QString::number(theTrd->getYHalfLength2()/CLHEP::mm)+" mm"; + out << " Z = "+QString::number(theTrd->getZHalfLength()/CLHEP::mm)+" mm"; + } + } else if(shape->typeID() == GeoPcon::getClassTypeID()) { + const GeoPcon* thePcon = dynamic_cast<const GeoPcon*>(shape); + assert(thePcon);//only in dbg builds + if (thePcon){ + out << " =========> Pcon:"; + out<<" Start phi = "+QString::number(thePcon->getSPhi())+", Delta phi = "+QString::number(thePcon->getDPhi()); + for (unsigned index=0; index < thePcon->getNPlanes(); ++index) { + out << " Plane "+QString::number(index); + out << " -> RMin = "+QString::number(thePcon->getRMinPlane(index)/CLHEP::mm)+" mm"; + out << " -> RMax = "+QString::number(thePcon->getRMaxPlane(index)/CLHEP::mm)+" mm"; + out << " -> Z = "+QString::number(thePcon->getZPlane(index)/CLHEP::mm)+" mm"; + } + } + } else if(shape->typeID() == GeoCons::getClassTypeID()) { + const GeoCons* theCons = dynamic_cast<const GeoCons*>(shape); + assert(theCons); + if (theCons){ + out << " =========> Cons:"; + out << " RMin1 = "<<QString::number(theCons->getRMin1()/CLHEP::mm)+" mm"; + out << " RMin2 = "<<QString::number(theCons->getRMin2()/CLHEP::mm)+" mm"; + out << " RMax1 = "<<QString::number(theCons->getRMax1()/CLHEP::mm)+" mm"; + out << " RMax2 = "<<QString::number(theCons->getRMax2()/CLHEP::mm)+" mm"; + out << " DZ = "<<QString::number(theCons->getDZ()/CLHEP::mm)+" mm"; + out << " SPhi = "+QString::number(theCons->getSPhi()); + out << " DPhi = "+QString::number(theCons->getDPhi()); + } + } else if(shape->typeID() == GeoPara::getClassTypeID()) { + const GeoPara* thePara = dynamic_cast<const GeoPara*>(shape); + assert(thePara); + if (thePara){ + out << " =========> Para:"; + out << " X = "+QString::number(thePara->getXHalfLength()/CLHEP::mm)+" mm"; + out << " Y = "+QString::number(thePara->getYHalfLength()/CLHEP::mm)+" mm"; + out << " Z = "+QString::number(thePara->getZHalfLength()/CLHEP::mm)+" mm"; + out << " Alpha = "+QString::number(thePara->getAlpha()); + out << " Theta = "+QString::number(thePara->getTheta()); + out << " Phi = "+QString::number(thePara->getPhi()); + } + } else if(shape->typeID() == GeoPgon::getClassTypeID()) { + const GeoPgon* thePgon = dynamic_cast<const GeoPgon*>(shape); + assert(thePgon); + if (thePgon){ + out << " =========> Pgon:"; + for (unsigned int index=0; index<thePgon->getNPlanes(); index++) + { + out << " Plane "+QString::number(index); + out << ": -> RMin = "+QString::number(thePgon->getRMinPlane(index)/CLHEP::mm)+" mm"; + out << ": -> RMax = "+QString::number(thePgon->getRMaxPlane(index)/CLHEP::mm)+" mm"; + out << " -> Z = "+QString::number(thePgon->getZPlane(index)/CLHEP::mm)+" mm"; + } + } + } else if(shape->typeID() == GeoTrap::getClassTypeID()) { + const GeoTrap* theTrap = dynamic_cast<const GeoTrap*>(shape); + assert(theTrap); + if (theTrap){ + out << " =========> Trap:"; + out << " DZ = "+QString::number(theTrap->getZHalfLength()/CLHEP::mm)+" mm"; + out << " Theta = "+QString::number(theTrap->getTheta()); + out << " Phi = "+QString::number(theTrap->getPhi()); + out << " Dydzn = "+QString::number(theTrap->getDydzn()/CLHEP::mm)+" mm"; + out << " Dxdyndzn = "+QString::number(theTrap->getDxdyndzn()/CLHEP::mm)+" mm"; + out << " Dxdypdzn = "+QString::number(theTrap->getDxdypdzn()/CLHEP::mm)+" mm"; + out << " Angleydzn = "+QString::number(theTrap->getAngleydzn()); + out << " Dydzp = "+QString::number(theTrap->getDydzp()/CLHEP::mm)+" mm"; + out << " Dxdyndzp = "+QString::number(theTrap->getDxdyndzp()/CLHEP::mm)+" mm"; + out << " Dxdypdzp = "+QString::number(theTrap->getDxdypdzp()/CLHEP::mm)+" mm"; + out << " Angleydzp = "+QString::number(theTrap->getAngleydzp()); + } + } + // Boolean volumes: + else if (shape->typeID() == GeoShapeShift::getClassTypeID() ) { + const GeoShapeShift* theShift = dynamic_cast<const GeoShapeShift*>(shape); + assert(theShift); + if (theShift){ + out << " =========> GeoShapeShift:"; + SbMatrix t; + VP1LinAlgUtils::transformToMatrix(Amg::EigenTransformToCLHEP(theShift->getX()), t); + float translation_x, translation_y, translation_z, rotaxis_x, rotaxis_y, rotaxis_z, rotangle_radians; + VP1LinAlgUtils::decodeTransformation( t, + translation_x, translation_y, translation_z, + rotaxis_x, rotaxis_y, rotaxis_z, rotangle_radians ); + out << " Information about contained transformation:"; + out << "===> Translation:"; + out << " x = "+QString::number(translation_x/CLHEP::mm)+" mm"; + out << " y = "+QString::number(translation_y/CLHEP::mm)+" mm"; + out << " z = "+QString::number(translation_z/CLHEP::mm)+" mm"; + out << "===> Rotation:"; + out << " axis x = "+QString::number(rotaxis_x); + out << " axis y = "+QString::number(rotaxis_y); + out << " axis z = "+QString::number(rotaxis_z); + out << " angle = "+QString::number(rotangle_radians*180.0/M_PI)+" deg"; + + out << " Information about contained GeoShape:"; + foreach(QString str,shapeToStringList(theShift->getOp())){ + out <<" ==> "+str; + } + } + } else if (shape->typeID() == GeoShapeUnion::getClassTypeID() ) { + const GeoShapeUnion* theUnion = dynamic_cast<const GeoShapeUnion*>(shape); + assert(theUnion); + if (theUnion){ + out << " =========> GeoShapeUnion:"; + out << " First operand:"; + foreach (QString s,shapeToStringList(theUnion->getOpA())) + out << " ==> "+s; + out << " Second operand:"; + foreach (QString s,shapeToStringList(theUnion->getOpB())) + out << " ==> "+s; + } + } else if (shape->typeID() == GeoShapeIntersection::getClassTypeID() ) { + const GeoShapeIntersection* theIntersection = dynamic_cast<const GeoShapeIntersection*>(shape); + assert(theIntersection); + if (theIntersection){ + out << " =========> GeoShapeIntersection:"; + out << " First operand:"; + foreach (QString s,shapeToStringList(theIntersection->getOpA())) + out << " ==> "+s; + out << " Second operand:"; + foreach (QString s,shapeToStringList(theIntersection->getOpB())) + out << " ==> "+s; + } + } else if (shape->typeID() == GeoShapeSubtraction::getClassTypeID() ) { + const GeoShapeSubtraction* theSubtraction = dynamic_cast<const GeoShapeSubtraction*>(shape); + assert(theSubtraction); + if (theSubtraction){ + out << " =========> GeoShapeSubtraction:"; + out << " First operand:"; + foreach (QString s,shapeToStringList(theSubtraction->getOpA())) + out << " ==> "+s; + out << " Second operand:"; + foreach (QString s,shapeToStringList(theSubtraction->getOpB())) + out << " ==> "+s; + } + } else if (shape->typeID() == GeoGenericTrap::getClassTypeID() ) { + const GeoGenericTrap* theGenericTrap = dynamic_cast<const GeoGenericTrap*>(shape); + assert(theGenericTrap); + if (theGenericTrap){ + out << " =========> GenericTrap:"; + out << " halfZlength = "+QString::number(theGenericTrap->getZHalfLength()/CLHEP::mm)+" mm"; + std::vector<CLHEP::Hep2Vector> vertices; + vertices.reserve(theGenericTrap->getVertices().size()); + for(const auto& geoVertex : theGenericTrap->getVertices()) { + vertices.push_back(CLHEP::Hep2Vector(geoVertex.x(),geoVertex.y())); + } + //in total 8 vertices by definition! + out << "==> First 4 vertices at - hz/2"; + out << "(Ax,Ay) = ( "+QString::number(vertices[0].x()/CLHEP::mm)+" , "+QString::number(vertices[0].y()/CLHEP::mm)+" ) mm"; + out << "(Bx,By) = ( "+QString::number(vertices[1].x()/CLHEP::mm)+" , "+QString::number(vertices[1].y()/CLHEP::mm)+" ) mm"; + out << "(Cx,Cy) = ( "+QString::number(vertices[2].x()/CLHEP::mm)+" , "+QString::number(vertices[2].y()/CLHEP::mm)+" ) mm"; + out << "(Dx,Dy) = ( "+QString::number(vertices[3].x()/CLHEP::mm)+" , "+QString::number(vertices[3].y()/CLHEP::mm)+" ) mm"; + out <<"==> Second 4 vertices at +hz/2"; + out << "(Ax,Ay) = ( "+QString::number(vertices[4].x()/CLHEP::mm)+" , "+QString::number(vertices[4].y()/CLHEP::mm)+" ) mm"; + out << "(Bx,By) = ( "+QString::number(vertices[5].x()/CLHEP::mm)+" , "+QString::number(vertices[5].y()/CLHEP::mm)+" ) mm"; + out << "(Cx,Cy) = ( "+QString::number(vertices[6].x()/CLHEP::mm)+" , "+QString::number(vertices[6].y()/CLHEP::mm)+" ) mm"; + out << "(Dx,Dy) = ( "+QString::number(vertices[7].x()/CLHEP::mm)+" , "+QString::number(vertices[7].y()/CLHEP::mm)+" ) mm"; + } + } else { + out << " =========> Unknown shape..."; + } + + return out; + +} diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/GeoSysController.cxx b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/GeoSysController.cxx new file mode 100644 index 000000000..1353fedde --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/GeoSysController.cxx @@ -0,0 +1,610 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class GeoSysController // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: October 2008 // +// // +//////////////////////////////////////////////////////////////// + +#define VP1IMPVARNAME m_d + +#include "VTI12GeometrySystems/GeoSysController.h" +#include "VTI12GeometrySystems/ZappedVolumeListModel.h" +#include "VP1Base/VP1Serialise.h" +#include "VP1Base/VP1Deserialise.h" +#include "VP1Base/VP1Settings.h" +#include "VP1Base/IVP1System.h" +#ifndef BUILDVP1LIGHT + #include "VTI12Utils/VP1JobConfigInfo.h" +#endif + +#include "ui_geometrysystemcontroller.h" +#include "ui_settings_display_form.h" +#include "ui_settings_iconisedvols_form.h" +#include "ui_settings_interactions_form.h" +#include "ui_settings_misc_form.h" +#include "ui_settings_treebrowser_form.h" + +#include <Inventor/nodes/SoPickStyle.h> + +#include <QFileDialog> + +#include <map> + + +//____________________________________________________________________ +class GeoSysController::Imp { +public: + GeoSysController * theclass; + Ui::GeometrySystemControllerForm ui; + Ui::GeoSysSettingsDisplayForm ui_disp; + Ui::GeoSysSettingsIconisedVolumesForm ui_iconisedvols; + Ui::GeoSysSettingsInteractionsForm ui_int; + Ui::GeoSysSettingsMiscForm ui_misc; + Ui::GeoSysSettingsTreeBrowserForm ui_treebrowser; + std::map<VP1GeoFlags::SubSystemFlag,QCheckBox*> subSysCheckBoxMap; + float last_transparency; + bool last_showVolumeOutLines; + int last_labels; //!< needed for POSSIBLECHANGE_IMP macro. + QList<int> last_labelPosOffset; //!< needed for POSSIBLECHANGE_IMP macro. + SoPickStyle * pickStyle; + VolumeHandle * lastSelectedVolHandle; + ZappedVolumeListModel * zappedVolumeListModel; + + QString lastSaveMaterialsFile; + QString lastLoadMaterialsFile; + +// std::map<QString, QList<QCheckBox*> > labelProvidingSystems; //!< First is name of system, second is list of types of information provided (system stores actual information) +}; + + +//____________________________________________________________________ +GeoSysController::GeoSysController(IVP1System * sys) + : VP1Controller(sys,"GeoSysController"), m_d(new Imp) +{ + m_d->theclass = this; + m_d->ui.setupUi(this); + + initDialog(m_d->ui_disp, m_d->ui.pushButton_settings_display); + initDialog(m_d->ui_iconisedvols, m_d->ui.pushButton_settings_iconisedvols); + initDialog(m_d->ui_int, m_d->ui.pushButton_settings_interactions); + initDialog(m_d->ui_misc, m_d->ui.pushButton_settings_misc); + initDialog(m_d->ui_treebrowser, m_d->ui.pushButton_settings_treebrowser); + + // m_d->ui_disp.widget_drawOptions->setLineWidthsDisabled(); + m_d->ui_disp.widget_drawOptions->setPointSizesDisabled(); +// m_d->ui_disp.widget_drawOptions->setBaseLightingDisabled(); + m_d->ui_disp.widget_drawOptions->setComplexity(0.6); + + m_d->pickStyle = new SoPickStyle; + m_d->pickStyle->ref(); + + #ifndef BUILDVP1LIGHT + //Possibly hide parts of gui, depending on job configuration: + if (!VP1JobConfigInfo::hasGeoModelExperiment()) { + m_d->ui.groupBox_scintillator->setVisible(false); + m_d->ui.groupBox_tracker->setVisible(false); + m_d->ui.groupBox_calorimeter->setVisible(false); + m_d->ui.groupBox_misc->setVisible(false); + message("GeoModel not properly initialised."); + } else { + // m_d->ui.groupBox_innerdetector->setVisible(VP1JobConfigInfo::hasPixelGeometry() + // || VP1JobConfigInfo::hasSCTGeometry() + // || VP1JobConfigInfo::hasTRTGeometry() + // || VP1JobConfigInfo::hasInDetServiceMaterialGeometry()); + // m_d->ui_misc.groupBox_pixelactivemodules->setVisible(VP1JobConfigInfo::hasPixelGeometry()); + // m_d->ui_misc.groupBox_sctactivemodules->setVisible(VP1JobConfigInfo::hasSCTGeometry()); + } + #endif + + + m_d->zappedVolumeListModel = new ZappedVolumeListModel(m_d->ui_iconisedvols.listView_iconisedvolumes); + m_d->ui_iconisedvols.listView_iconisedvolumes->setUniformItemSizes(true); + m_d->ui_iconisedvols.listView_iconisedvolumes->setSelectionMode(QAbstractItemView::ExtendedSelection); + m_d->ui_iconisedvols.listView_iconisedvolumes->setModel(m_d->zappedVolumeListModel); + + connect(m_d->ui_iconisedvols.listView_iconisedvolumes,SIGNAL(activated(const QModelIndex&)), + m_d->zappedVolumeListModel,SLOT(activated(const QModelIndex&))); + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Setup connections which monitor changes in the controller so that we may emit signals as appropriate: // + ///////////////////////////////////////////////////////////////////////////////////////////////////////////// + + addUpdateSlot(SLOT(updatePickStyle())); + connectToLastUpdateSlot(m_d->ui_int.checkBox_geomselectable); + + addUpdateSlot(SLOT(possibleChange_showVolumeOutLines())); + connectToLastUpdateSlot(m_d->ui_disp.checkBox_showVolumeOutLines); + + addUpdateSlot(SLOT(possibleChange_transparency())); + connectToLastUpdateSlot(m_d->ui_disp.spinBox_transp); + + initLastVars(); + + //Connections for state-less signals: + + connect(m_d->ui_disp.pushButton_saveChangedMaterials,SIGNAL(clicked()),this,SLOT(saveMaterialsRequested())); + connect(m_d->ui_disp.pushButton_loadMaterials,SIGNAL(clicked()),this,SLOT(loadMaterialsRequested())); + + connect(m_d->ui_misc.pushButton_nonStandardShapes_Iconify,SIGNAL(clicked()), + this,SLOT(emit_actionOnAllNonStandardVolumes())); + connect(m_d->ui_misc.pushButton_nonStandardShapes_Expand,SIGNAL(clicked()), + this,SLOT(emit_actionOnAllNonStandardVolumes())); + + connect(m_d->ui_misc.lineEdit_expand_vols_matname,SIGNAL(returnPressed()),this,SLOT(emit_autoExpandByVolumeOrMaterialName())); + connect(m_d->ui_misc.pushButton_expand_vols_matname,SIGNAL(clicked()),this,SLOT(emit_autoExpandByVolumeOrMaterialName())); + connect(m_d->ui_misc.lineEdit_expand_vols_volname,SIGNAL(returnPressed()),this,SLOT(emit_autoExpandByVolumeOrMaterialName())); + connect(m_d->ui_misc.pushButton_expand_vols_volname,SIGNAL(clicked()),this,SLOT(emit_autoExpandByVolumeOrMaterialName())); + + connect(m_d->ui_misc.toolButton_sctmod_reset,SIGNAL(clicked(bool)),this,SLOT(emit_resetSubSystems())); + + setLastSelectedVolume(0); + + // SCINTILLATOR + m_d->subSysCheckBoxMap[VP1GeoFlags::Veto] = m_d->ui.checkBox_Veto; + m_d->subSysCheckBoxMap[VP1GeoFlags::Trigger] = m_d->ui.checkBox_Trigger; + m_d->subSysCheckBoxMap[VP1GeoFlags::Preshower] = m_d->ui.checkBox_Preshower; + + // Tracker + m_d->subSysCheckBoxMap[VP1GeoFlags::SCT] = m_d->ui.checkBox_SCT; + + // Calorimeter + m_d->subSysCheckBoxMap[VP1GeoFlags::Ecal] = m_d->ui.checkBox_Ecal; + + // MISCELLANEOUS + // OTHER + m_d->subSysCheckBoxMap[VP1GeoFlags::AllUnrecognisedVolumes] = m_d->ui.checkBox_other; + + // -> labels + addUpdateSlot(SLOT(possibleChange_labels())); + connectToLastUpdateSlot(m_d->ui_disp.groupBox_labels); + connectToLastUpdateSlot(m_d->ui_disp.checkBox_labels_names); + connectToLastUpdateSlot(m_d->ui_disp.checkBox_labels_mooret0s); + connectToLastUpdateSlot(m_d->ui_disp.checkBox_labels_mboyt0s); + connectToLastUpdateSlot(m_d->ui_disp.checkBox_labels_hits); + + addUpdateSlot(SLOT(possibleChange_labelPosOffset())); + connectToLastUpdateSlot(m_d->ui_disp.horizontalSlider_labels_xOffset); + connectToLastUpdateSlot(m_d->ui_disp.horizontalSlider_labels_yOffset); + connectToLastUpdateSlot(m_d->ui_disp.horizontalSlider_labels_zOffset); + + m_d->last_labels=0; +} + +//____________________________________________________________________ +GeoSysController::~GeoSysController() +{ + m_d->pickStyle->unref(); + delete m_d; +} + +//____________________________________________________________________ +void GeoSysController::setGeometrySelectable(bool b) +{ + m_d->ui_int.checkBox_geomselectable->setChecked(b); + updatePickStyle(); +} + +//____________________________________________________________________ +void GeoSysController::setComplexity(double c) +{ + m_d->ui_disp.widget_drawOptions->setComplexity(c); +} + +//____________________________________________________________________ +void GeoSysController::setZoomToVolumeOnClick(bool b) +{ + m_d->ui_int.checkBox_zoomToVolumes->setChecked(b); +} + +//____________________________________________________________________ +void GeoSysController::setLastSelectedVolume(VolumeHandle*vh) +{ + m_d->lastSelectedVolHandle = vh; + m_d->ui_disp.matButton_lastSel->setEnabled(vh!=0); + if (vh) { + QList<SoMaterial*> mats = m_d->ui_disp.matButton_lastSel->handledMaterials(); + if (mats.isEmpty()||mats.at(0)!=vh->material()) { + m_d->ui_disp.matButton_lastSel->clearHandledMaterials(); + m_d->ui_disp.matButton_lastSel->setMaterial(vh->material()); + } + } else { + m_d->ui_disp.matButton_lastSel->clearHandledMaterials(); + } +} + +//____________________________________________________________________ +VolumeHandle* GeoSysController::lastSelectedVolume() const +{ + return m_d->lastSelectedVolHandle; +} + +//____________________________________________________________________ +void GeoSysController::saveMaterialsRequested() +{ + const bool ctrl_isdown = (Qt::ControlModifier & QApplication::keyboardModifiers()); + const bool onlyChangedMaterials = !ctrl_isdown; + + QString filename + = QFileDialog::getSaveFileName(this, "Select geometry material file to save", + (m_d->lastSaveMaterialsFile.isEmpty()? + VP1Settings::defaultFileSelectDirectory() + :m_d->lastSaveMaterialsFile), + "VP1 geometry material files (*.vp1geomat)", + 0,QFileDialog::DontResolveSymlinks); + + if(filename.isEmpty()) + return; + + if (!filename.endsWith(".vp1geomat")) + filename += ".vp1geomat"; + + m_d->lastSaveMaterialsFile = filename; + + messageVerbose("Emitting saveMaterialsToFile(\""+filename+"\","+str(onlyChangedMaterials)+")"); + emit saveMaterialsToFile(filename,onlyChangedMaterials); + +} + +//____________________________________________________________________ +void GeoSysController::loadMaterialsRequested() +{ + QString filename = QFileDialog::getOpenFileName(this, "Select geometry material file to load", + (m_d->lastLoadMaterialsFile.isEmpty()? + VP1Settings::defaultFileSelectDirectory() + :m_d->lastLoadMaterialsFile), + "VP1 geometry material files (*.vp1geomat)", + 0,QFileDialog::DontResolveSymlinks); + if(filename.isEmpty()) + return; + + m_d->lastLoadMaterialsFile = filename; + + messageVerbose("Emitting loadMaterialsFromFile(\""+filename+"\")"); + emit loadMaterialsFromFile(filename); +} + +//____________________________________________________________________ +QCheckBox * GeoSysController::subSystemCheckBox(VP1GeoFlags::SubSystemFlag f) const +{ + std::map<VP1GeoFlags::SubSystemFlag,QCheckBox*>::const_iterator it = m_d->subSysCheckBoxMap.find(f); + return it==m_d->subSysCheckBoxMap.end() ? 0 : it->second; +} + +//____________________________________________________________________ +SoGroup * GeoSysController::drawOptions() const +{ + return m_d->ui_disp.widget_drawOptions->drawOptionsGroup(); +} + +//____________________________________________________________________ +SoPickStyle * GeoSysController::pickStyle() const +{ + return m_d->pickStyle; +} + +//____________________________________________________________________ +VP1GeoTreeView * GeoSysController::volumeTreeBrowser() const +{ + return m_d->ui_treebrowser.treeView_volumebrowser; +} + +//____________________________________________________________________ +PhiSectionWidget * GeoSysController::phiSectionWidget() const +{ + return m_d->ui_disp.phisectionwidget; +} + +//____________________________________________________________________ +ZappedVolumeListModel * GeoSysController::zappedVolumeListModel() const +{ + return m_d->zappedVolumeListModel; +} + +//____________________________________________________________________ +bool GeoSysController::zoomToVolumeOnClick() const +{ + return m_d->ui_int.checkBox_zoomToVolumes->isChecked(); +} + +//____________________________________________________________________ +bool GeoSysController::printInfoOnClick_Shape() const +{ + return m_d->ui_int.checkBox_print_shape->isChecked(); +} + +//____________________________________________________________________ +bool GeoSysController::printInfoOnClick_Material() const +{ + return m_d->ui_int.checkBox_print_material->isChecked(); +} + +//____________________________________________________________________ +bool GeoSysController::printInfoOnClick_CopyNumber() const +{ + return m_d->ui_int.checkBox_print_copyno->isChecked(); +} + +//____________________________________________________________________ +bool GeoSysController::printInfoOnClick_Transform() const +{ + return m_d->ui_int.checkBox_print_transform->isChecked(); +} + +//____________________________________________________________________ +bool GeoSysController::printInfoOnClick_Tree() const +{ + return m_d->ui_int.checkBox_print_tree->isChecked(); +} + +//____________________________________________________________________ +bool GeoSysController::printInfoOnClick_Mass() const +{ + return m_d->ui_int.checkBox_print_mass->isChecked(); +} + +//_____________________________________________________________________________________ +void GeoSysController::updatePickStyle() +{ + m_d->pickStyle->style = m_d->ui_int.checkBox_geomselectable->isChecked() + ? SoPickStyle::SHAPE : SoPickStyle::UNPICKABLE; +} + +//____________________________________________________________________ +float GeoSysController::transparency() const +{ + int v(m_d->ui_disp.spinBox_transp->value()); + return (v>=100?1.0:(v<=0?0.0:v/100.0)); +} + +//____________________________________________________________________ +bool GeoSysController::showVolumeOutLines() const +{ + return m_d->ui_disp.checkBox_showVolumeOutLines->isChecked(); +} + +//void GeoSysController::setAvailableLabels(IVP1System* sys, QStringList providedLabels){ +// messageVerbose("setAvailableLabels for "+sys->name() ); +// if (m_d->labelProvidingSystems.find(sys->name())!=m_d->labelProvidingSystems.end()) +// return; +// QList<QCheckBox*> checkboxes; +// foreach(QString label, providedLabels) { +// QCheckBox *checkbox = new QCheckBox(label, this); +// checkboxes.append(checkbox); +// } +// m_d->labelProvidingSystems[sys->name()]= checkboxes; +//// std::map<QString, QList<QCheckBox*> > labelProvidingSystems; //!< First is name of system, second is list of types of information provided (system stores actual information) +// +//} + +void GeoSysController::setLabelsEnabled(bool t0s, bool hits){ + // make sure that when labels are enabled, only the systems which we have are enabled too + if (t0s) { + connect(m_d->ui_disp.groupBox_labels,SIGNAL(toggled(bool)), + m_d->ui_disp.checkBox_labels_mooret0s,SLOT(setEnabled(bool))); + connect(m_d->ui_disp.groupBox_labels,SIGNAL(toggled(bool)), + m_d->ui_disp.checkBox_labels_mboyt0s,SLOT(setEnabled(bool))); + } else { + m_d->ui_disp.checkBox_labels_mooret0s->setEnabled(false); + m_d->ui_disp.checkBox_labels_mboyt0s->setEnabled(false); + } + if (hits) { + connect(m_d->ui_disp.groupBox_labels,SIGNAL(toggled(bool)), + m_d->ui_disp.checkBox_labels_hits,SLOT(setEnabled(bool))); + } else { + m_d->ui_disp.checkBox_labels_hits->setEnabled(false); + } + + messageVerbose("setLabelsEnabled() t0s="+str(t0s)+", hits="+str(hits)); +} + + +int GeoSysController::labels() const { + if (!m_d->ui_disp.groupBox_labels->isChecked()) return 0; + int labels=0; + if (m_d->ui_disp.checkBox_labels_names->isChecked()) labels|=0x1; + if (m_d->ui_disp.checkBox_labels_mooret0s->isChecked()) labels|=0x2; + if (m_d->ui_disp.checkBox_labels_mboyt0s->isChecked()) labels|=0x4; + // leaving space for another t0 type, if necessary + if (m_d->ui_disp.checkBox_labels_hits->isChecked()) labels|=0x10; + return labels; +} + +QList<int> GeoSysController::labelPosOffset() +{ + QList<int> values; + values << m_d->ui_disp.horizontalSlider_labels_xOffset->value(); + values << m_d->ui_disp.horizontalSlider_labels_yOffset->value(); + values << m_d->ui_disp.horizontalSlider_labels_zOffset->value(); + return values; +} + +// //____________________________________________________________________ +// void GeoSysController::emit_autoAdaptPixelsOrSCT() +// { +// bool pixel(sender()==m_d->ui_misc.toolButton_pixelmod_adapt); +// bool brl = pixel ? m_d->ui_misc.checkBox_pixelmod_barrel->isChecked() +// : m_d->ui_misc.checkBox_sctmod_barrel->isChecked(); +// bool ecA = pixel ? m_d->ui_misc.checkBox_pixelmod_endcapA->isChecked() +// : m_d->ui_misc.checkBox_sctmod_endcapA->isChecked(); +// bool ecC = pixel ? m_d->ui_misc.checkBox_pixelmod_endcapC->isChecked() +// : m_d->ui_misc.checkBox_sctmod_endcapC->isChecked(); +// bool bcmA = pixel ? m_d->ui_misc.checkBox_bcmMod_Aside->isChecked() : false; +// bool bcmC = pixel ? m_d->ui_misc.checkBox_bcmMod_Cside->isChecked() : false; + +// messageVerbose ("Emitting autoAdaptPixelsOrSCT("+str(pixel)+", "+str(brl)+","+str(ecA)+","+str(ecC)+","+str(bcmA)+","+str(bcmC)+")"); +// emit autoAdaptPixelsOrSCT(pixel,brl,ecA,ecC,bcmA,bcmC); +// } + +//____________________________________________________________________ +void GeoSysController::emit_autoExpandByVolumeOrMaterialName() +{ + bool volname(sender()==m_d->ui_misc.pushButton_expand_vols_volname + ||sender()==m_d->ui_misc.lineEdit_expand_vols_volname); + QString name(volname?m_d->ui_misc.lineEdit_expand_vols_volname->text() + :m_d->ui_misc.lineEdit_expand_vols_matname->text()); + if (name.isEmpty()) + return; + messageVerbose("emitting autoExpandByVolumeOrMaterialName("+str(!volname)+", "+name+")"); + emit autoExpandByVolumeOrMaterialName(!volname,name); +} + +//____________________________________________________________________ +void GeoSysController::emit_actionOnAllNonStandardVolumes() { + bool zap(sender()==m_d->ui_misc.pushButton_nonStandardShapes_Iconify); + messageVerbose("emitting actionOnAllNonStandardVolumes("+str(zap)+")"); + emit actionOnAllNonStandardVolumes(zap); +} + +//____________________________________________________________________ +//! Reset to the sub-system top volume. +/*! + The method reset the view to the whole sub-system + by contracting all children to the mother volume. + It does work properly only if the top sub-system + volume has a concrete shape. If, instead, it is a + mere container, then this method does not work + because it will hide the children of the top + container volume. In that case, you should implement + a custom method. + + Note: for an example of a custom solution, + please refer to the 'VP1GeometrySystem::autoAdaptMuonNSW()' + method, triggered by the emission of the 'autoAdaptMuonNSW()' + signal in the 'emit_autoAdaptMuonNSW()' of this class. +*/ +void GeoSysController::emit_resetSubSystems() +{ + VP1GeoFlags::SubSystemFlags f(0); + // if (sender()==m_d->ui_misc.toolButton_pixelmod_reset) + // f = VP1GeoFlags::Pixel; + // else + if (sender()==m_d->ui_misc.toolButton_sctmod_reset) + f = VP1GeoFlags::SCT; + messageVerbose(" Emitting resetSubSystems("+str(f)+")"); + emit resetSubSystems(f); +} + +//____________________________________________________________________ +int GeoSysController::currentSettingsVersion() const +{ + return 6; +} + +//____________________________________________________________________ +void GeoSysController::actualSaveSettings(VP1Serialise&s) const +{ + s.save(m_d->ui_disp.phisectionwidget);//version <=1 saved in old format + s.save(m_d->ui_disp.spinBox_transp); + // s.save(m_d->ui_misc.checkBox_pixelmod_barrel); + // s.save(m_d->ui_misc.checkBox_pixelmod_endcapA); + // s.save(m_d->ui_misc.checkBox_pixelmod_endcapC); + s.save(m_d->ui_misc.checkBox_sctmod_upstream); + s.save(m_d->ui_misc.checkBox_sctmod_central); + s.save(m_d->ui_misc.checkBox_sctmod_downstream); + s.save(m_d->ui_disp.widget_drawOptions); + s.save(m_d->ui_misc.lineEdit_expand_vols_matname); + s.save(m_d->ui_misc.lineEdit_expand_vols_volname); + s.save(m_d->ui_int.checkBox_geomselectable); + s.save(m_d->ui_int.checkBox_print_shape); + s.save(m_d->ui_int.checkBox_print_material); + s.save(m_d->ui_int.checkBox_print_transform); + s.save(m_d->ui_int.checkBox_print_mass); + s.save(m_d->ui_int.checkBox_print_copyno); + s.save(m_d->ui_int.checkBox_print_tree); + s.save(m_d->ui_int.checkBox_zoomToVolumes); + s.save(m_d->ui_disp.checkBox_showVolumeOutLines);//version 1+ + + // labels - version 4+ + s.save(m_d->ui_disp.groupBox_labels); + s.save(m_d->ui_disp.horizontalSlider_labels_xOffset); + s.save(m_d->ui_disp.horizontalSlider_labels_yOffset); + s.save(m_d->ui_disp.horizontalSlider_labels_zOffset); + s.save(m_d->ui_disp.checkBox_labels_names); + //version 5+ + s.save(m_d->ui_disp.checkBox_labels_mboyt0s); + s.save(m_d->ui_disp.checkBox_labels_mooret0s); + s.save(m_d->ui_disp.checkBox_labels_hits); + + s.ignoreWidget(m_d->ui_disp.matButton_lastSel); + std::map<VP1GeoFlags::SubSystemFlag,QCheckBox*>::const_iterator it,itE(m_d->subSysCheckBoxMap.end()); + for (it=m_d->subSysCheckBoxMap.begin();it!=itE;++it) + s.ignoreWidget(it->second); +} + +//____________________________________________________________________ +void GeoSysController::actualRestoreSettings(VP1Deserialise& s) +{ + if (s.version()<0||s.version()>currentSettingsVersion()) { + message("Warning: State data in .vp1 file has unsupported version ("+str(s.version())+")"); + return; + } + + if (s.version()<=1) { + s.ignoreObsoletePhiSectionWidgetState(); + s.ignoreWidget(m_d->ui_disp.phisectionwidget); + } else { + s.restore(m_d->ui_disp.phisectionwidget); + } + s.restore(m_d->ui_disp.spinBox_transp); + // s.restore(m_d->ui_misc.checkBox_pixelmod_barrel); + // s.restore(m_d->ui_misc.checkBox_pixelmod_endcapA); + // s.restore(m_d->ui_misc.checkBox_pixelmod_endcapC); + s.restore(m_d->ui_misc.checkBox_sctmod_upstream); + s.restore(m_d->ui_misc.checkBox_sctmod_central); + s.restore(m_d->ui_misc.checkBox_sctmod_downstream); + s.restore(m_d->ui_disp.widget_drawOptions); + s.restore(m_d->ui_misc.lineEdit_expand_vols_matname); + s.restore(m_d->ui_misc.lineEdit_expand_vols_volname); + s.restore(m_d->ui_int.checkBox_geomselectable); + s.restore(m_d->ui_int.checkBox_print_shape); + s.restore(m_d->ui_int.checkBox_print_material); + s.restore(m_d->ui_int.checkBox_print_transform); + s.restore(m_d->ui_int.checkBox_print_mass); + s.restore(m_d->ui_int.checkBox_print_copyno); + s.restore(m_d->ui_int.checkBox_print_tree); + s.restore(m_d->ui_int.checkBox_zoomToVolumes); + if (s.version()>=1) + s.restore(m_d->ui_disp.checkBox_showVolumeOutLines); + // labels + if (s.version()>=4){ + s.restore(m_d->ui_disp.groupBox_labels); + s.restore(m_d->ui_disp.horizontalSlider_labels_xOffset); + s.restore(m_d->ui_disp.horizontalSlider_labels_yOffset); + s.restore(m_d->ui_disp.horizontalSlider_labels_zOffset); + s.restore(m_d->ui_disp.checkBox_labels_names); + } + if (s.version()>=5){ + s.restore(m_d->ui_disp.checkBox_labels_mboyt0s); + s.restore(m_d->ui_disp.checkBox_labels_mooret0s); + s.restore(m_d->ui_disp.checkBox_labels_hits); + } + + s.ignoreWidget(m_d->ui_disp.matButton_lastSel); + std::map<VP1GeoFlags::SubSystemFlag,QCheckBox*>::const_iterator it,itE(m_d->subSysCheckBoxMap.end()); + for (it=m_d->subSysCheckBoxMap.begin();it!=itE;++it) + s.ignoreWidget(it->second); + + m_d->ui_int.groupBox_printOnSelection->setEnabled(m_d->ui_int.checkBox_geomselectable->isChecked()); + m_d->ui_int.groupBox_automaticViewReorientations->setEnabled(m_d->ui_int.checkBox_geomselectable->isChecked()); + +} + +/////////////////////////////////////////////////////////////////////////// +// Test for possible changes in values and emit signals as appropriate: +// (possibleChange_XXX() slots code provided by macros) +#define VP1CONTROLLERCLASSNAME GeoSysController +#include "VP1Base/VP1ControllerMacros.h" +POSSIBLECHANGE_IMP(transparency) +POSSIBLECHANGE_IMP(showVolumeOutLines) +POSSIBLECHANGE_IMP(labels) +POSSIBLECHANGE_IMP(labelPosOffset) + + + diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/PhiSectorManager.cxx b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/PhiSectorManager.cxx new file mode 100644 index 000000000..e7d9e839d --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/PhiSectorManager.cxx @@ -0,0 +1,529 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////////////////// +// // +// Implementation of class PhiSectorManager // +// // +// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Initial VP1 version: September 2007 // +// // +///////////////////////////////////////////////////////////////////////// + +#include "VTI12GeometrySystems/PhiSectorManager.h" +#include "VP1Base/PhiSectionWidget.h" +#include "VP1Base/VP1ExtraSepLayerHelper.h" +#include "VP1Base/VP1Msg.h" +#include "VP1Base/IVP1System.h" +#include "VTI12Utils/VP1LinAlgUtils.h" + +#include <VP1HEPVis/nodes/SoTubs.h> +#include "VP1HEPVis/nodes/SoPcons.h" +#include "VP1HEPVis/nodes/SoCons.h" +#include "VP1HEPVis/nodes/SoLAr.h" + +#include <Inventor/nodes/SoSwitch.h> +#include <Inventor/nodes/SoSeparator.h> +#include <Inventor/actions/SoGetBoundingBoxAction.h> + +#include <Inventor/SbLinear.h> +#include <Inventor/SbViewportRegion.h> + +#include <map> +#include <set> +#include <cmath> + +#define NPHISECTORS 36 + +//____________________________________________________________________ +class PhiSectorManager::Imp { +public: + PhiSectionWidget * phisectionwidget; + IVP1System * system; + + std::map<VP1GeoFlags::SubSystemFlag,SoSeparator *> subsysflag2sep; + std::map<VP1GeoFlags::SubSystemFlag,SoSeparator *> subsysflag2labelsep; + std::map<VP1GeoFlags::SubSystemFlag,std::map<int,VP1ExtraSepLayerHelper*> > subsysflag_2_iphi2sephelper; + std::map<VP1GeoFlags::SubSystemFlag,std::map<int,VP1ExtraSepLayerHelper*> > subsysflag_2_iphi2labelsephelper; + std::map<VP1GeoFlags::SubSystemFlag,VP1ExtraSepLayerHelper*> subsysflag_2_volAroundZSepHelper; + + //NB: If in the future we implement the phi-sector switching on a per-subsystem basis, just keep track of which switches are from which subsystems: + std::map<int,std::set<SoSwitch*> > iphi2switches; + std::map<int,std::set<SoSwitch*> > iphi2Labelswitches; + + //The rest of the stuff is for the dynamical "slicing" of volumes around the Z-axis: + std::map<SoSwitch*,std::pair<SoTubs*,SoSeparator*> > volaroundZ_tubs; + std::map<SoSwitch*,std::pair<SoPcons*,SoSeparator*> > volaroundZ_pcons; + std::map<SoSwitch*,std::pair<SoCons*,SoSeparator*> > volaroundZ_cons; + std::map<SoSwitch*,std::pair<SoLAr*,SoSeparator*> > volaroundZ_lar; + std::map<SoSwitch*,std::pair<double,bool> > volaroundZ_switch2transfinfo;//switch -> phi rotation around z and rotated around y flag. + template <class T> + void updateRepresentationsOfVolsAroundZAxis_Specific(std::map<SoSwitch*,std::pair<T*,SoSeparator*> >& volaroundZ); + void getPhiExtentOfShape( const SoTubs* tubs, double& phistart, double& phispan); + void getPhiExtentOfShape( const SoPcons* pcons, double& phistart, double& phispan); + void getPhiExtentOfShape( const SoCons* cons, double& phistart, double& phispan); + void getPhiExtentOfShape( const SoLAr* lar, double& phistart, double& phispan); + void copyShapeFieldsAndOverridePhiRange( const SoTubs* source, SoTubs* dest, double phistart, double phispan); + void copyShapeFieldsAndOverridePhiRange( const SoPcons* source, SoPcons* dest, double phistart, double phispan); + void copyShapeFieldsAndOverridePhiRange( const SoCons* source, SoCons* dest, double phistart, double phispan); + void copyShapeFieldsAndOverridePhiRange( const SoLAr* source, SoLAr* dest, double phistart, double phispan); + int nactivelargechanges; + + QVector<bool> currentlyEnabledPhiSectors; +}; + +//____________________________________________________________________ +void PhiSectorManager::registerSubSystemSeparator(VP1GeoFlags::SubSystemFlag flag,SoSeparator * subsystemsep) +{ + assert(m_d->subsysflag2sep.find(flag)==m_d->subsysflag2sep.end()); + assert(m_d->subsysflag_2_iphi2sephelper.find(flag)==m_d->subsysflag_2_iphi2sephelper.end()); + m_d->subsysflag_2_iphi2sephelper[flag] = std::map<int,VP1ExtraSepLayerHelper*>(); + m_d->subsysflag2sep[flag] = subsystemsep; + + assert(m_d->subsysflag2labelsep.find(flag)==m_d->subsysflag2labelsep.end()); + assert(m_d->subsysflag_2_iphi2labelsephelper.find(flag)==m_d->subsysflag_2_iphi2labelsephelper.end()); + m_d->subsysflag_2_iphi2labelsephelper[flag] = std::map<int,VP1ExtraSepLayerHelper*>(); + m_d->subsysflag2labelsep[flag] = subsystemsep; +} + +//____________________________________________________________________ +VP1ExtraSepLayerHelper * PhiSectorManager::getSepHelperForNode(VP1GeoFlags::SubSystemFlag flag, int iphi) +{ + assert(iphi>=-1); + assert(m_d->subsysflag2sep.find(flag)!=m_d->subsysflag2sep.end()); + assert(m_d->subsysflag_2_iphi2sephelper.find(flag)!=m_d->subsysflag_2_iphi2sephelper.end()); + + if (m_d->subsysflag_2_iphi2sephelper[flag].find(iphi)!=m_d->subsysflag_2_iphi2sephelper[flag].end()) { + return m_d->subsysflag_2_iphi2sephelper[flag][iphi]; + } + + SoSwitch * sw = new SoSwitch; + sw->whichChild = (iphi>=0 ? m_d->phisectionwidget->virtualSectorEnabled(iphi,NPHISECTORS):!m_d->phisectionwidget->allSectorsOff()) ? SO_SWITCH_ALL : SO_SWITCH_NONE; + + if (m_d->iphi2switches.find(iphi)==m_d->iphi2switches.end()) + m_d->iphi2switches[iphi] = std::set<SoSwitch*>(); + m_d->iphi2switches[iphi].insert(sw); + + SoSeparator * sep = new SoSeparator; + sep->ref(); + VP1ExtraSepLayerHelper * sephelper = new VP1ExtraSepLayerHelper(sep); + m_d->subsysflag_2_iphi2sephelper[flag][iphi] = sephelper; + + sw->addChild(sep); + m_d->subsysflag2sep[flag]->addChild(sw); + return sephelper; +} + +//____________________________________________________________________ +VP1ExtraSepLayerHelper * PhiSectorManager::getLabelSepHelperForNode(VP1GeoFlags::SubSystemFlag flag, int iphi) +{ + assert(iphi>=-1); + assert(m_d->subsysflag2labelsep.find(flag)!=m_d->subsysflag2labelsep.end()); + assert(m_d->subsysflag_2_iphi2labelsephelper.find(flag)!=m_d->subsysflag_2_iphi2labelsephelper.end()); + + if (m_d->subsysflag_2_iphi2labelsephelper[flag].find(iphi)!=m_d->subsysflag_2_iphi2labelsephelper[flag].end()) { + return m_d->subsysflag_2_iphi2labelsephelper[flag][iphi]; + } + + SoSwitch * sw = new SoSwitch; + sw->whichChild = (iphi>=0 ? m_d->phisectionwidget->virtualSectorEnabled(iphi,NPHISECTORS):!m_d->phisectionwidget->allSectorsOff()) ? SO_SWITCH_ALL : SO_SWITCH_NONE; + + if (m_d->iphi2Labelswitches.find(iphi)==m_d->iphi2Labelswitches.end()) + m_d->iphi2Labelswitches[iphi] = std::set<SoSwitch*>(); + m_d->iphi2Labelswitches[iphi].insert(sw); + + SoSeparator * sep = new SoSeparator; + sep->ref(); + VP1ExtraSepLayerHelper * sephelper = new VP1ExtraSepLayerHelper(sep); + m_d->subsysflag_2_iphi2labelsephelper[flag][iphi] = sephelper; + + sw->addChild(sep); + m_d->subsysflag2labelsep[flag]->addChild(sw); + return sephelper; +} + +//____________________________________________________________________ +VP1ExtraSepLayerHelper * PhiSectorManager::registerVolumeAroundZAxis( VP1GeoFlags::SubSystemFlag flag, SoSwitch* sw, const SbMatrix& transf ) +{ + //Assumes that the switch, sw, has the unsliced shape node as the + //first child (0) and a separator as the second child (1), under + //which shapes representing the phi-sliced shape will be placed. + + //If not all phi sectors are visible, the sep node will be + //populated with children representing the shape cut up + //appropriately, and the switch will show the sep rather than the + //shapeWithAllPhiSectors. + + assert(sw->getNumChildren()==2); +// assert(sw->getChild(0)->getTypeId().isDerivedFrom(SoShape::getClassTypeId())); + assert(sw->getChild(1)->getTypeId()==SoSeparator::getClassTypeId()); + + SoNode* shape = static_cast<SoShape*>(sw->getChild(0)); + SoSeparator* sep = static_cast<SoSeparator*>(sw->getChild(1)); + + //Start unsliced: + if (sw->whichChild.getValue() != 0) + sw->whichChild = 0; + + // Register the shape according to type: + if (shape->getTypeId()==SoTubs::getClassTypeId()) { + m_d->volaroundZ_tubs[sw] = std::pair<SoTubs*,SoSeparator*>(static_cast<SoTubs*>(shape),sep); + } else if (shape->getTypeId()==SoPcons::getClassTypeId()) { + m_d->volaroundZ_pcons[sw] = std::pair<SoPcons*,SoSeparator*>(static_cast<SoPcons*>(shape),sep); + } else if (shape->getTypeId()==SoCons::getClassTypeId()) { + m_d->volaroundZ_cons[sw] = std::pair<SoCons*,SoSeparator*>(static_cast<SoCons*>(shape),sep); + } else { + assert(shape->getTypeId()==SoLAr::getClassTypeId()); + m_d->volaroundZ_lar[sw] = std::pair<SoLAr*,SoSeparator*>(static_cast<SoLAr*>(shape),sep); + } + + //Test: Are we roughly given by a rotation around the y-axis? + SbVec3f unitz (0.0f, 0.0f, 1.0f); + SbVec3f transfunitz; + + SbVec3f translation; SbRotation rotation; SbVec3f scaleFactor; SbRotation scaleOrientation; + transf.getTransform (translation, rotation, scaleFactor, scaleOrientation); + + rotation.multVec(unitz,transfunitz); + + float x,y,z; + transfunitz.getValue(x,y,z); + //Look at direction in x-z plane - is it consistent with z<0 and |x|<<|z|? Then we have rotated around y: + bool rotaroundy = (z<0&&std::fabs(x)*10<std::fabs(z)); + + //Test: Whats the rough value we are rotated around z? + SbVec3f unitx (1.0f, 0.0f, 0.0f); + SbVec3f transfunitx; + rotation.multVec(unitx,transfunitx); + transfunitx.getValue(x,y,z); + double phirot = VP1LinAlgUtils::phiFromXY(x, y ); + m_d->volaroundZ_switch2transfinfo[sw] = std::pair<double,bool>(phirot,rotaroundy); + + //Return the sephelper for this subsystems volumes around Z: + if (m_d->subsysflag_2_volAroundZSepHelper.find(flag)!=m_d->subsysflag_2_volAroundZSepHelper.end()) + return m_d->subsysflag_2_volAroundZSepHelper[flag]; + + SoSeparator * subsyssep_volaroundZ = new SoSeparator; + assert(m_d->subsysflag2sep.find(flag)!=m_d->subsysflag2sep.end()); + m_d->subsysflag2sep[flag]->addChild(subsyssep_volaroundZ); + + subsyssep_volaroundZ->ref(); + VP1ExtraSepLayerHelper * sephelper = new VP1ExtraSepLayerHelper(subsyssep_volaroundZ); + m_d->subsysflag_2_volAroundZSepHelper[flag] = sephelper; + return sephelper; +} + +//____________________________________________________________________ +int PhiSectorManager::getVolumeType(const SbMatrix& transform, SoNode * shape) const { + if (!shape) { + VP1Msg::message("ERROR: getVolumeType got a NULL shape pointer"); + return 0; + } + + //Step 1) Find the (projected) bounding box. + shape->ref(); + SbViewportRegion dummyvp; + SoGetBoundingBoxAction a(dummyvp);//Fixme: Cache this guy? + a.apply(shape); + SbXfBox3f xfbox = a.getXfBoundingBox(); + xfbox.transform(transform); + SbBox3f box = xfbox.project(); + shape->unrefNoDelete(); + + //Step 2) Does it enclose the Z-axis? + float minx, miny, minz, maxx, maxy, maxz; + box.getBounds(minx, miny, minz, maxx, maxy, maxz); + float x,y,z; + box.getCenter().getValue(x,y,z); + if (std::abs(x*20.0)<std::abs(std::min(minx,maxx))&&std::abs(y*20.0)<std::abs(std::min(miny,maxy))) { + // -> Yes: It is one of the volumes we can handle dynamically? + if (shape->getTypeId()==SoTubs::getClassTypeId() + ||shape->getTypeId()==SoPcons::getClassTypeId() + ||shape->getTypeId()==SoCons::getClassTypeId() + ||shape->getTypeId()==SoLAr::getClassTypeId()) { + // -> Yes: + return -2; + } else { + // -> No: + //Fixme: Move this message somewhere appropriate??? + //shape cannot be NULL here, so 'false' case is redundant (coverity 16272) + //std::string Typenametest = shape ? shape->getTypeId().getName().getString() : "NULL"; + std::string Typenametest = shape->getTypeId().getName().getString(); + m_d->system->message("WARNING: Unknown volume type (boolean?) for volume around Z-axis (type " + +QString(Typenametest.c_str())+"). Phi-sector cuts won't work for this!"); + return -1; + } + } + + //Step 3: Find phi of center and return appropriate iphi: + return PhiSectionWidget::phiToVirtualSectorIndex(VP1LinAlgUtils::phiFromXY(x,y),NPHISECTORS); + +} + +//____________________________________________________________________ +PhiSectorManager::PhiSectorManager(PhiSectionWidget * psw, IVP1System * sys, QObject*parent) + : QObject(parent), m_d(new Imp) +{ + m_d->phisectionwidget = psw; + m_d->system=sys; + m_d->nactivelargechanges = 0; + m_d->currentlyEnabledPhiSectors = QVector<bool>(NPHISECTORS,false); + QList<int> l; l << 4 << 6 << 9 << 12 << 18 << NPHISECTORS;//NB: All must be divisors in NPHISECTORS + psw->setNumberOfSectors(12); + psw->setAllowedNumberOfSectors(l); + + connect(psw,SIGNAL(enabledPhiRangesChanged(const QList<VP1Interval>&)),this,SLOT(enabledPhiSectorsChanged())); + enabledPhiSectorsChanged(); +} + +//____________________________________________________________________ +PhiSectorManager::~PhiSectorManager() +{ + + std::map<VP1GeoFlags::SubSystemFlag,std::map<int,VP1ExtraSepLayerHelper*> >::iterator it, itE = m_d->subsysflag_2_iphi2sephelper.end(); + for (it = m_d->subsysflag_2_iphi2sephelper.begin();it!=itE;++it) { + std::map<int,VP1ExtraSepLayerHelper*>::iterator it2(it->second.begin()),it2E(it->second.end()); + for (;it2!=it2E;++it2) { + SoSeparator * sep = it2->second->topSeparator(); + delete (it2->second); + sep->unref(); + } + } + + std::map<VP1GeoFlags::SubSystemFlag,std::map<int,VP1ExtraSepLayerHelper*> >::iterator it4, itE4 = m_d->subsysflag_2_iphi2labelsephelper.end(); + for (it4 = m_d->subsysflag_2_iphi2labelsephelper.begin();it4!=itE4;++it4) { + std::map<int,VP1ExtraSepLayerHelper*>::iterator it5(it4->second.begin()),it5E(it4->second.end()); + for (;it5!=it5E;++it5) { + SoSeparator * sep = it5->second->topSeparator(); + delete (it5->second); + sep->unref(); + } + } + std::map<VP1GeoFlags::SubSystemFlag,VP1ExtraSepLayerHelper*>::iterator it3,it3E = m_d->subsysflag_2_volAroundZSepHelper.end(); + for (it3 = m_d->subsysflag_2_volAroundZSepHelper.begin();it3!=it3E;++it3) { + SoSeparator * sep = it3->second->topSeparator(); + delete (it3->second); + sep->unref(); + } + delete m_d; m_d=0; +} + +//_____________________________________________________________________________________ +void PhiSectorManager::enabledPhiSectorsChanged() +{ + QVector<bool> v = m_d->phisectionwidget->virtualSectorsEnabled(NPHISECTORS); + if (m_d->currentlyEnabledPhiSectors == v) + return; + QList<int> changedPhiSectors; + for (int iphi = 0; iphi < NPHISECTORS; ++iphi) + if (m_d->currentlyEnabledPhiSectors[iphi]!=v[iphi]) + changedPhiSectors << iphi; + m_d->currentlyEnabledPhiSectors = v; + foreach (int iphi,changedPhiSectors) + updateEnabledPhiSections(iphi); +} + +//_____________________________________________________________________________________ +void PhiSectorManager::updateEnabledPhiSections(int iphi) { + bool turnedon = m_d->currentlyEnabledPhiSectors.at(iphi); + if (m_d->iphi2switches.find(iphi)!=m_d->iphi2switches.end()) { + std::set<SoSwitch*>::iterator it, itE = m_d->iphi2switches[iphi].end(); + for (it = m_d->iphi2switches[iphi].begin();it!=itE;++it) { + if ((*it)->whichChild.getValue() != (turnedon?SO_SWITCH_ALL:SO_SWITCH_NONE)) + (*it)->whichChild = (turnedon?SO_SWITCH_ALL:SO_SWITCH_NONE); + } + } + + if (m_d->iphi2Labelswitches.find(iphi)!=m_d->iphi2Labelswitches.end()) { + std::set<SoSwitch*>::iterator it, itE = m_d->iphi2Labelswitches[iphi].end(); + for (it = m_d->iphi2Labelswitches[iphi].begin();it!=itE;++it) { + if ((*it)->whichChild.getValue() != (turnedon?SO_SWITCH_ALL:SO_SWITCH_NONE)) + (*it)->whichChild = (turnedon?SO_SWITCH_ALL:SO_SWITCH_NONE); + } + } + // FIXME - need to find a way to turn on labels for recently made visible phi sections, OR build them all by default. + + //Update the switches for boolean, etc., volumes around the Z axis. + bool alloff = m_d->phisectionwidget->allSectorsOff(); + std::map<int,std::set<SoSwitch*> >::iterator it_zax_switches = m_d->iphi2switches.find(-1); + if (it_zax_switches!=m_d->iphi2switches.end()) { + std::set<SoSwitch*>::iterator it, itE = it_zax_switches->second.end(); + for (it = it_zax_switches->second.begin();it!=itE;++it) { + if ((*it)->whichChild.getValue() != (alloff?SO_SWITCH_NONE:SO_SWITCH_ALL)) + (*it)->whichChild = (alloff?SO_SWITCH_NONE:SO_SWITCH_ALL); + } + } + updateRepresentationsOfVolsAroundZAxis(); +} + +//_____________________________________________________________________________________ +void PhiSectorManager::Imp::getPhiExtentOfShape( const SoTubs* tubs, double& phistart, double& phispan) +{ + phistart = tubs->pSPhi.getValue(); + phispan = tubs->pDPhi.getValue(); +} + +//_____________________________________________________________________________________ +void PhiSectorManager::Imp::copyShapeFieldsAndOverridePhiRange( const SoTubs* source, SoTubs* dest, double phistart, double phispan) +{ + dest->pRMin.setValue(source->pRMin.getValue()); + dest->pRMax.setValue(source->pRMax.getValue()); + dest->pDz.setValue(source->pDz.getValue()); + dest->pSPhi.setValue(phistart); + dest->pDPhi.setValue(phispan); + dest->drawEdgeLines.setValue(source->drawEdgeLines.getValue()); +} + +//_____________________________________________________________________________________ +void PhiSectorManager::Imp::getPhiExtentOfShape( const SoPcons* pcons, double& phistart, double& phispan) +{ + phistart = pcons->fSPhi.getValue(); + phispan = pcons->fDPhi.getValue(); +} + +//_____________________________________________________________________________________ +void PhiSectorManager::Imp::copyShapeFieldsAndOverridePhiRange( const SoPcons* source, SoPcons* dest, double phistart, double phispan) +{ + dest->fRmin = source->fRmin; + dest->fRmax = source->fRmax; + dest->fDz = source->fDz; + dest->fSPhi.setValue(phistart); + dest->fDPhi.setValue(phispan); + dest->drawEdgeLines.setValue(source->drawEdgeLines.getValue()); +} + +//_____________________________________________________________________________________ +void PhiSectorManager::Imp::getPhiExtentOfShape( const SoCons* cons, double& phistart, double& phispan) +{ + phistart = cons->fSPhi.getValue(); + phispan = cons->fDPhi.getValue(); +} + +//_____________________________________________________________________________________ +void PhiSectorManager::Imp::copyShapeFieldsAndOverridePhiRange( const SoCons* source, SoCons* dest, double phistart, double phispan) +{ + dest->fRmin1.setValue(source->fRmin1.getValue()); + dest->fRmin2.setValue(source->fRmin2.getValue()); + dest->fRmax1.setValue(source->fRmax1.getValue()); + dest->fRmax2.setValue(source->fRmax2.getValue()); + dest->fDz.setValue(source->fDz.getValue()); + dest->fSPhi.setValue(phistart); + dest->fDPhi.setValue(phispan); +} + +//_____________________________________________________________________________________ +void PhiSectorManager::Imp::getPhiExtentOfShape( const SoLAr* lar, double& phistart, double& phispan) +{ + phistart = lar->fSPhi.getValue(); + phispan = lar->fDPhi.getValue(); +} + +//_____________________________________________________________________________________ +void PhiSectorManager::Imp::copyShapeFieldsAndOverridePhiRange( const SoLAr* source, SoLAr* dest, double phistart, double phispan) +{ + dest->fRmin = source->fRmin; + dest->fRmax = source->fRmax; + dest->fDz = source->fDz; + dest->fSPhi.setValue(phistart); + dest->fDPhi.setValue(phispan); +} + +//_____________________________________________________________________________________ +template <class T> +void PhiSectorManager::Imp::updateRepresentationsOfVolsAroundZAxis_Specific(std::map<SoSwitch*,std::pair<T*,SoSeparator*> >& volaroundZ) +{ + + typename std::map<SoSwitch*,std::pair<T*,SoSeparator*> >::iterator it, itE = volaroundZ.end(); + for (it = volaroundZ.begin();it!=itE;++it) { + if (phisectionwidget->allSectorsOff()) { + if (it->first->whichChild.getValue() != SO_SWITCH_NONE) + it->first->whichChild = SO_SWITCH_NONE; + } else if (phisectionwidget->allSectorsOn()) { + if (it->first->whichChild.getValue() != 0) + it->first->whichChild = 0; + } else { + //Update and use sep node: + SbBool save = it->first->enableNotify(false); + SoSeparator * sep = it->second.second; + sep->removeAllChildren(); + //Figure out phirot/yrot info: + std::map<SoSwitch*,std::pair<double,bool> >::iterator it_transfinfo = volaroundZ_switch2transfinfo.find(it->first); + if (it_transfinfo==volaroundZ_switch2transfinfo.end()) { + system->message("updateRepresentationsOfVolsAroundZAxis_Specific ERROR: Inconsistent maps"); + continue; + } + double phirot = it_transfinfo->second.first; + bool rotaroundy = it_transfinfo->second.second; + + double sphi, dphi; + getPhiExtentOfShape(it->second.first,sphi,dphi); + + QList<VP1Interval> ranges = phisectionwidget->enabledPhiRanges( sphi, sphi+dphi ); + + int n = ranges.count(); + for (int i = 0; i< n; ++i) { + T * shape = new T; + double deltaphi = ranges.at(i).length(); + double startphi = rotaroundy ? - ranges.at(i).upper() - 2*M_PI + phirot : ranges.at(i).lower()-phirot; + while (startphi<0) startphi += 2*M_PI; + while (startphi+deltaphi>2*M_PI) startphi -= 2*M_PI; + copyShapeFieldsAndOverridePhiRange( it->second.first, shape, startphi, deltaphi ); + sep->addChild(shape); + } + + it->first->whichChild = 1; + it->first->enableNotify(save); + if (save) + it->first->touch(); + + } + } + +} + +//_____________________________________________________________________________________ +void PhiSectorManager::updateRepresentationsOfVolsAroundZAxis() +{ + m_d->updateRepresentationsOfVolsAroundZAxis_Specific<SoTubs>(m_d->volaroundZ_tubs); + m_d->updateRepresentationsOfVolsAroundZAxis_Specific<SoPcons>(m_d->volaroundZ_pcons); + m_d->updateRepresentationsOfVolsAroundZAxis_Specific<SoCons>(m_d->volaroundZ_cons); + m_d->updateRepresentationsOfVolsAroundZAxis_Specific<SoLAr>(m_d->volaroundZ_lar); +} + +//_____________________________________________________________________________________ +void PhiSectorManager::largeChangesBegin() +{ + if (++(m_d->nactivelargechanges)==1) { + VP1Msg::messageVerbose("PhiSectorManager disabling notifications begin"); + std::map<VP1GeoFlags::SubSystemFlag,std::map<int,VP1ExtraSepLayerHelper*> >::iterator it, itE = m_d->subsysflag_2_iphi2sephelper.end(); + for (it = m_d->subsysflag_2_iphi2sephelper.begin();it!=itE;++it) { + std::map<int,VP1ExtraSepLayerHelper*>::iterator it2(it->second.begin()),it2E(it->second.end()); + for (;it2!=it2E;++it2) + it2->second->largeChangesBegin(); + } + std::map<VP1GeoFlags::SubSystemFlag,VP1ExtraSepLayerHelper*>::iterator it3,it3E = m_d->subsysflag_2_volAroundZSepHelper.end(); + for (it3 = m_d->subsysflag_2_volAroundZSepHelper.begin();it3!=it3E;++it3) + it3->second->largeChangesBegin(); + VP1Msg::messageVerbose("PhiSectorManager disabling notifications end"); + } +} + +//_____________________________________________________________________________________ +void PhiSectorManager::largeChangesEnd() +{ + if (--(m_d->nactivelargechanges)==0) { + VP1Msg::messageVerbose("PhiSectorManager enabling notifications begin"); + std::map<VP1GeoFlags::SubSystemFlag,std::map<int,VP1ExtraSepLayerHelper*> >::iterator it, itE = m_d->subsysflag_2_iphi2sephelper.end(); + for (it = m_d->subsysflag_2_iphi2sephelper.begin();it!=itE;++it) { + std::map<int,VP1ExtraSepLayerHelper*>::iterator it2(it->second.begin()),it2E(it->second.end()); + for (;it2!=it2E;++it2) + it2->second->largeChangesEnd(); + } + std::map<VP1GeoFlags::SubSystemFlag,VP1ExtraSepLayerHelper*>::iterator it3,it3E = m_d->subsysflag_2_volAroundZSepHelper.end(); + for (it3 = m_d->subsysflag_2_volAroundZSepHelper.begin();it3!=it3E;++it3) + it3->second->largeChangesEnd(); + VP1Msg::messageVerbose("PhiSectorManager enabling notifications end"); + } +} diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VP1GeoFlags.cxx b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VP1GeoFlags.cxx new file mode 100644 index 000000000..b1b4f324c --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VP1GeoFlags.cxx @@ -0,0 +1,27 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class VP1GeoFlags // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: October 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12GeometrySystems/VP1GeoFlags.h" + +//____________________________________________________________________ +QString VP1GeoFlags::toString(const VOLSTATE& s) +{ + switch (s) { + case CONTRACTED: return "CONTRACTED"; + case EXPANDED: return "EXPANDED"; + case ZAPPED: return "ZAPPED"; + default: + return "<UNKNOWN>"; + } +} diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VP1GeoTreeView.cxx b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VP1GeoTreeView.cxx new file mode 100644 index 000000000..84d1bc4be --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VP1GeoTreeView.cxx @@ -0,0 +1,70 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class VP1GeoTreeView // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: January 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12GeometrySystems/VP1GeoTreeView.h" +#include <QTimer> + +//____________________________________________________________________ +class VP1GeoTreeView::Imp { +public: + bool updatescheduled; +}; + + +//____________________________________________________________________ +VP1GeoTreeView::VP1GeoTreeView(QWidget * parent) + : QTreeView(parent), m_d(new Imp) +{ + m_d->updatescheduled = false; +} + +//____________________________________________________________________ +VP1GeoTreeView::~VP1GeoTreeView() +{ + delete m_d; +} + +//____________________________________________________________________ +void VP1GeoTreeView::updateAllNonHiddenIndices() +{ + if (m_d->updatescheduled) + m_d->updatescheduled = false; + bool save = updatesEnabled(); + setUpdatesEnabled(false); + + //The following is a bit of a hack. Could probably be done better? + QModelIndexList oldselection = selectionModel()->selectedIndexes(); + selectAll(); + QModelIndexList allindexes = selectionModel()->selectedIndexes(); + foreach ( QModelIndex idx, allindexes) { + update(idx); + } + selectionModel()->clearSelection(); + foreach ( QModelIndex idx, oldselection ) + selectionModel()->select(idx,QItemSelectionModel::Select); + + + if (save) { + setUpdatesEnabled(true); + update(); + } +} + +//____________________________________________________________________ +void VP1GeoTreeView::scheduleUpdateOfAllNonHiddenIndices() +{ + if (m_d->updatescheduled) + return; + QTimer::singleShot(0, this, SLOT(updateAllNonHiddenIndices())); +} diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VP1GeomUtils.cxx b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VP1GeomUtils.cxx new file mode 100644 index 000000000..0568b083a --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VP1GeomUtils.cxx @@ -0,0 +1,26 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "VTI12GeometrySystems/VP1GeomUtils.h" +#include "GeoModelKernel/GeoMaterial.h" +#include "GeoModelKernel/GeoElement.h" + +//______________________________________________________________________________________ +QStringList VP1GeomUtils::geoMaterialToStringList( const GeoMaterial* mat ) +{ + //Fixme: Show all info. + QStringList l; + l << mat->getName().c_str(); + return l; +} + + +//______________________________________________________________________________________ +QStringList VP1GeomUtils::geoElementToStringList( const GeoElement* elem ) +{ + //Fixme: Show all info. + QStringList l; + l << elem->getName().c_str(); + return l; +} diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VP1GeometrySystem.cxx b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VP1GeometrySystem.cxx new file mode 100644 index 000000000..787f6d923 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VP1GeometrySystem.cxx @@ -0,0 +1,1434 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////////////////// +// // +// Implementation of class VP1GeometrySystem // +// // +// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Derived from V-atlas geometry system by Joe Boudreau. // +// Origins of initial version dates back to ~1996, initial VP1 // +// version by TK (May 2007) and almost entirely rewritten Oct 2007. // +// Major refactoring october 2008. // +// Updates: // +// - Aug 2019, Riccardo.Maria.Bianchi@cern.ch // +// // +///////////////////////////////////////////////////////////////////////// + +#include "VTI12GeometrySystems/VP1GeometrySystem.h" +#include "VTI12GeometrySystems/GeoSysController.h" + +#include "VTI12GeometrySystems/VP1GeoTreeView.h" +#include "VTI12GeometrySystems/VolumeHandle.h" +#include "VTI12GeometrySystems/VolumeHandleSharedData.h" +#include "VTI12GeometrySystems/VolumeTreeModel.h" +#include "VTI12GeometrySystems/VP1GeomUtils.h" +#include "VTI12GeometrySystems/VisAttributes.h" +#include "VTI12GeometrySystems/DumpShape.h" +#include "VTI12GeometrySystems/PhiSectorManager.h" + +#include "VTI12Utils/VP1LinAlgUtils.h" + +#include "VP1Base/VP1CameraHelper.h" +#include "VP1Base/VP1QtInventorUtils.h" +#include "VP1Base/VP1Serialise.h" +#include "VP1Base/VP1Deserialise.h" +#include "VP1Base/VP1Msg.h" +#include <Inventor/nodes/SoSeparator.h> +#include <Inventor/nodes/SoSwitch.h> +#include <Inventor/events/SoKeyboardEvent.h> +#include <Inventor/nodes/SoPickStyle.h> +#include <Inventor/nodes/SoEventCallback.h> +#include <Inventor/nodes/SoCamera.h> +#include <Inventor/nodes/SoCylinder.h> +#include <Inventor/nodes/SoFont.h> + +#include "GeoModelKernel/GeoVolumeCursor.h" +#include "GeoModelKernel/GeoPrintGraphAction.h" +#include "GeoModelUtilities/GeoModelExperiment.h" + +#ifndef BUILDVP1LIGHT +#include "VTI12Utils/VP1JobConfigInfo.h" +#include "VTI12Utils/VP1SGAccessHelper.h" +#include "VTI12Utils/VP1DetInfo.h" +#endif + +#include <QDebug> +#include <QRegExp> +#include <QByteArray> +#include <QTimer> +#include <QHeaderView> +#include <QApplication> +#include <QCheckBox> +#include <QMessageBox> +#include <QFileInfo> + +#include <map> + +class VP1GeometrySystem::Imp { +public: + Imp (VP1GeometrySystem*gs, const VP1GeoFlags::SubSystemFlags& ssf) + : theclass(gs), sceneroot(0), + detVisAttributes(0), matVisAttributes(0), volVisAttributes(0), + initialSubSystemsTurnedOn(ssf),controller(0),phisectormanager(0), + volumetreemodel(0),kbEvent(0), m_textSep(0) + { + const unsigned n_chamber_t0_sources=2; + for (unsigned i=0;i<n_chamber_t0_sources;++i) + chamberT0s.append(0); + } + + VP1GeometrySystem * theclass; + SoSeparator * sceneroot; + + std::map<SoSeparator*,VolumeHandle*> sonodesep2volhandle; + + class SubSystemInfo { + public: + // "geomodellocation" contains name of tree tops, + // or possible a bit more complex info in case of muons. + 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) + : isbuilt(false), checkbox(cb), + geomodeltreetopregexp(the_geomodeltreetopregexp), + geomodelchildrenregexp(the_geomodelchildrenregexp), + geomodelgrandchildrenregexp(the_geomodelgrandchildrenregexp), + negatetreetopregexp(the_negatetreetopregexp), + negatechildrenregexp(the_negatechildrenregexp), + negategrandchildrenregexp(the_negategrandchildrenregexp), + matname(the_matname), flag(the_flag), soswitch(0) + { + + } + + //Info needed to define the system (along with the checkbox pointer in the map below): + bool isbuilt; + VolumeHandle::VolumeHandleList vollist; + QCheckBox* checkbox; + + /* Regular Expressions for three levels of filtering: treetop, children, and grandchildren + * + * For example: + * + * - Muon --> treetop volume + * - ANON --> child volume + * - BAR_Toroid --> granchild volume + * + */ + QRegExp geomodeltreetopregexp; //For picking the geomodel treetops + QRegExp geomodelchildrenregexp; //If instead of the treetops, this system consists of volumes below the treetop, this is non-empty. + QRegExp geomodelgrandchildrenregexp;//If instead of the treetops, this system consists of volumes below the child of a treetop, this is non-empty. + bool negatetreetopregexp; + bool negatechildrenregexp; + bool negategrandchildrenregexp; + + + std::string matname; //if nonempty, use this from detvisattr instead of the top volname. + VP1GeoFlags::SubSystemFlag flag; + + + //Information needed to initialise the system: + class TreetopInfo { public: + TreetopInfo() {} + PVConstLink pV; + HepGeom::Transform3D xf;// = av.getTransform(); + std::string volname; + }; + std::vector<TreetopInfo> treetopinfo; + + //Switch associated with the system - it is initialised only if the system has info available: + SoSwitch * soswitch; + + bool childrenRegExpNameCompatible(const std::string& volname) const { + return negatechildrenregexp!=geomodelchildrenregexp.exactMatch(volname.c_str()); + } + + bool grandchildrenRegExpNameCompatible(const std::string& volname) const { + if(VP1Msg::debug()){ + std::cout << "volname: " << volname << " - regexpr: " << geomodelgrandchildrenregexp.pattern().toStdString() << std::endl; + std::cout << "negategrandchildrenregexp: " << negategrandchildrenregexp << std::endl; + } + return negategrandchildrenregexp!=geomodelgrandchildrenregexp.exactMatch(volname.c_str()); + } + + void dump() const { + std::cout<<" SubSystemInfo @ "<<this<<"\n" + <<(isbuilt?"Is built.\n":"Is not built.\n"); + std::cout<<"Contains following volhandles: ["; + for (auto vol : vollist) std::cout<<&vol<<","; + std::cout<<"]"<<std::endl; + std::cout<<"Matname = "<<matname<<std::endl; + std::cout<<"Contains following TreetopInfo: ["; + for (auto tt : treetopinfo) std::cout<<tt.volname<<","; + std::cout<<"]"<<std::endl; + + } + + }; + + QList<SubSystemInfo*> subsysInfoList;//We need to keep and ordered version also (since wildcards in regexp might match more than one subsystem info). + 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); + + DetVisAttributes *detVisAttributes; + MatVisAttributes *matVisAttributes; + VolVisAttributes *volVisAttributes; + void ensureInitVisAttributes() { + if (!detVisAttributes) detVisAttributes = new DetVisAttributes(); + if (!matVisAttributes) matVisAttributes = new MatVisAttributes(); + if (!volVisAttributes) volVisAttributes = new VolVisAttributes(); + } + + VP1GeoFlags::SubSystemFlags initialSubSystemsTurnedOn; + void buildSystem(SubSystemInfo*); + GeoSysController * controller; + PhiSectorManager * phisectormanager; + VolumeTreeModel * volumetreemodel; + + //Helpers used for printouts://FIXME: To VolumeHandle!! + static double exclusiveMass(const PVConstLink& pv); + static double inclusiveMass(const PVConstLink& pv); + static double volume(const PVConstLink& pv); + + //Basically for the zapping, and to ignore all clicks with ctrl/shift: + static void catchKbdState(void *userData, SoEventCallback *CB); + const SoKeyboardEvent *kbEvent; + + void changeStateOfVisibleNonStandardVolumesRecursively(VolumeHandle*,VP1GeoFlags::VOLSTATE); + void expandVisibleVolumesRecursively(VolumeHandle*,const QRegExp&,bool bymatname); + + SoSeparator* m_textSep;//!< Separator used to hold all visible labels. + + // void showPixelModules(VolumeHandle*); + // void showSCTBarrelModules(VolumeHandle*); + // void showSCTEndcapModules(VolumeHandle*); + + QMap<quint32,QByteArray> restoredTopvolstates; + void applyTopVolStates(const QMap<quint32,QByteArray>&, bool disablenotif = false); + + // Helper function for emiting a signal to the PartSpect system + // This function creates path entry prefixes (=Detector Factory name in G4) and extra + // path entries (top level volumes, python envelopes) depending on the subsystem of the selected volume + void createPathExtras(const VolumeHandle*, QString&, QStack<QString>&); + + QList<const std::map<GeoPVConstLink, float>*> chamberT0s; +}; + +//_____________________________________________________________________________________ +VP1GeometrySystem::VP1GeometrySystem( const VP1GeoFlags::SubSystemFlags& SubSystemsTurnedOn, QString name ) + : IVP13DSystemSimple(name, + "This system displays the geometry as defined in the GeoModel tree.", + "Riccardo.Maria.Bianchi@cern.ch"), + m_d(new Imp(this,SubSystemsTurnedOn)) +{ +} + + +//_____________________________________________________________________________________ +void VP1GeometrySystem::systemuncreate() +{ + + m_d->volumetreemodel->cleanup(); + delete m_d->matVisAttributes; m_d->matVisAttributes = 0; + delete m_d->detVisAttributes; m_d->detVisAttributes = 0; + delete m_d->volVisAttributes; m_d->volVisAttributes = 0; + + foreach (Imp::SubSystemInfo * subsys, m_d->subsysInfoList) + delete subsys; + m_d->subsysInfoList.clear(); + +} + +//_____________________________________________________________________________________ +VP1GeometrySystem::~VP1GeometrySystem() +{ + delete m_d; + m_d = 0; +} + +//_____________________________________________________________________________________ +void VP1GeometrySystem::setGeometrySelectable(bool b) { + ensureBuildController(); + m_d->controller->setGeometrySelectable(b); +} + +//_____________________________________________________________________________________ +void VP1GeometrySystem::setZoomToVolumeOnClick(bool b) { + ensureBuildController(); + m_d->controller->setZoomToVolumeOnClick(b); +} + +//_____________________________________________________________________________________ +void VP1GeometrySystem::Imp::addSubSystem(const VP1GeoFlags::SubSystemFlag& f, + const QString& treetopregexp, const QString& childrenregexp, + const std::string& matname, bool negatetreetopregexp, bool negatechildrenregexp, + const QString& grandchildrenregexp, bool negategrandchildrenregexp) +{ + theclass->message("VP1GeometrySystem::Imp::addSubSystem - flag: '" + QString(f) + "' - matName: '" + str(matname.c_str()) + "'." ); + + QCheckBox * cb = controller->subSystemCheckBox(f); + if (!cb) { + theclass->message("Error: Problems retrieving checkbox for subsystem "+str(f)); + return; + } + subsysInfoList << new SubSystemInfo(cb,QRegExp(treetopregexp),negatetreetopregexp, + QRegExp(childrenregexp),negatechildrenregexp,f,matname, + QRegExp(grandchildrenregexp), negategrandchildrenregexp); + //FIXME: DELETE!!! +} + +//_____________________________________________________________________________________ +QWidget * VP1GeometrySystem::buildController() +{ + message("VP1GeometrySystem::buildController"); + + m_d->controller = new GeoSysController(this); + + m_d->phisectormanager = new PhiSectorManager(m_d->controller->phiSectionWidget(),this,this); + + + connect(m_d->controller,SIGNAL(showVolumeOutLinesChanged(bool)),this,SLOT(setShowVolumeOutLines(bool))); + setShowVolumeOutLines(m_d->controller->showVolumeOutLines()); + connect(m_d->controller,SIGNAL(saveMaterialsToFile(QString,bool)),this,SLOT(saveMaterialsToFile(QString,bool))); + connect(m_d->controller,SIGNAL(loadMaterialsFromFile(QString)),this,SLOT(loadMaterialsFromFile(QString))); + + connect(m_d->controller,SIGNAL(transparencyChanged(float)),this,SLOT(updateTransparency())); + connect (m_d->controller,SIGNAL(volumeStateChangeRequested(VolumeHandle*,VP1GeoFlags::VOLSTATE)), + this,SLOT(volumeStateChangeRequested(VolumeHandle*,VP1GeoFlags::VOLSTATE))); + connect (m_d->controller,SIGNAL(volumeResetRequested(VolumeHandle*)), + this,SLOT(volumeResetRequested(VolumeHandle*))); + connect(m_d->controller,SIGNAL(autoExpandByVolumeOrMaterialName(bool,QString)),this,SLOT(autoExpandByVolumeOrMaterialName(bool,QString))); + connect(m_d->controller,SIGNAL(actionOnAllNonStandardVolumes(bool)),this,SLOT(actionOnAllNonStandardVolumes(bool))); + // connect(m_d->controller,SIGNAL(autoAdaptPixelsOrSCT(bool,bool,bool,bool,bool,bool)),this,SLOT(autoAdaptPixelsOrSCT(bool,bool,bool,bool,bool,bool))); + connect(m_d->controller,SIGNAL(resetSubSystems(VP1GeoFlags::SubSystemFlags)),this,SLOT(resetSubSystems(VP1GeoFlags::SubSystemFlags))); + + connect(m_d->controller,SIGNAL(labelsChanged(int)),this,SLOT(setLabels(int))); + connect(m_d->controller,SIGNAL(labelPosOffsetChanged(QList<int>)),this,SLOT(setLabelPosOffsets(QList<int>))); + setLabels(m_d->controller->labels()); + + + /* This is where we define the available different subsystems and their location in the geomodel tree. + * + * if the reg expr does not match any volume, the corresponding subsystem checkbox in the Geo GUI gets disabled. + * + * syntax: addSubSystem(VP1GeoFlags::SubSystemFlag&, // the associated system flag + QString& treetopregexp, // the regular expr for the top/root name of the main sub-detector system + QString& childrenregexp="", // the reg expr for the children of the main sub-detector + std::string& matname="", // a name we choose for displaying in VP1 + bool negatetreetopregexp = false, // if we want to negate the top reg expr + bool negatechildrenregexp = false); // if we want to negate the children reg expr + const QString& grandchildrenregexp="", // the regex for granchildren of the main sub-detector + bool negategrandchildrenregexp = false // wheter we want to negate teh granchildren regex + */ + m_d->addSubSystem( VP1GeoFlags::Veto, "Veto"); + m_d->addSubSystem( VP1GeoFlags::Trigger, "Trigger"); + m_d->addSubSystem( VP1GeoFlags::Preshower,"Preshower"); + m_d->addSubSystem( VP1GeoFlags::SCT, "SCT"); + m_d->addSubSystem( VP1GeoFlags::Ecal, "Ecal"); + + + + //This one MUST be added last. It will get slightly special treatment in various places! + m_d->addSubSystem( VP1GeoFlags::AllUnrecognisedVolumes,".*"); + + + //Setup models/views for volume tree browser and zapped volumes list: + m_d->volumetreemodel = new VolumeTreeModel(m_d->controller->volumeTreeBrowser()); + m_d->controller->volumeTreeBrowser()->header()->hide(); + m_d->controller->volumeTreeBrowser()->uniformRowHeights(); + m_d->controller->volumeTreeBrowser()->setModel(m_d->volumetreemodel); + + return m_d->controller; +} + + +//_____________________________________________________________________________________ +void VP1GeometrySystem::systemcreate(StoreGateSvc*) +{ + m_d->ensureInitVisAttributes(); +} + +//_____________________________________________________________________________________ +void VP1GeometrySystem::Imp::catchKbdState(void *address, SoEventCallback *CB) { + VP1GeometrySystem::Imp *This=static_cast<VP1GeometrySystem::Imp*>(address); + if (This) + This->kbEvent = static_cast<const SoKeyboardEvent *>(CB->getEvent()); +} + +//_____________________________________________________________________________________ +void VP1GeometrySystem::buildPermanentSceneGraph(StoreGateSvc*/*detstore*/, SoSeparator *root) +{ + m_d->sceneroot = root; + + #ifndef BUILDVP1LIGHT + if (!VP1JobConfigInfo::hasGeoModelExperiment()) { + message("Error: GeoModel not configured properly in job."); + return; + } + + //Get the world volume: + const GeoModelExperiment * theExpt; + if (!VP1SGAccessHelper(this,true).retrieve(theExpt,"FASER")) { + message("Error: Could not retrieve the FASER GeoModelExperiment from detector store"); + return; + } + #endif + + PVConstLink world(theExpt->getPhysVol()); + + if (!m_d->m_textSep) { + // FIXME! + // std::cout<<"Making new Text sep"<<std::endl; + m_d->m_textSep = new SoSeparator; + m_d->m_textSep->setName("TextSep"); + m_d->m_textSep->ref(); + } + m_d->sceneroot->addChild(m_d->m_textSep); + + // FIXME - what if font is missing? + SoFont *myFont = new SoFont; + myFont->name.setValue("Arial"); + myFont->size.setValue(12.0); + m_d->m_textSep->addChild(myFont); + + bool save = root->enableNotify(false); + + //Catch keyboard events: + SoEventCallback *catchEvents = new SoEventCallback(); + catchEvents->addEventCallback(SoKeyboardEvent::getClassTypeId(),Imp::catchKbdState, m_d); + root->addChild(catchEvents); + + root->addChild(m_d->controller->drawOptions()); + root->addChild(m_d->controller->pickStyle()); + + if(VP1Msg::debug()){ + qDebug() << "Configuring the default systems... - subsysInfoList len:" << (m_d->subsysInfoList).length(); + } + // we switch on the systems flagged to be turned on at start + foreach (Imp::SubSystemInfo * subsys, m_d->subsysInfoList) + { + VP1Msg::messageDebug("Switching on this system: " + QString::fromStdString(subsys->matname) + " - " + subsys->flag); + bool on(m_d->initialSubSystemsTurnedOn & subsys->flag); + subsys->checkbox->setChecked( on ); + subsys->checkbox->setEnabled(false); + subsys->checkbox->setToolTip("This sub-system is not available"); + connect(subsys->checkbox,SIGNAL(toggled(bool)),this,SLOT(checkboxChanged())); + } + + //Locate geometry info for the various subsystems, and add the info as appropriate: + + QCheckBox * checkBoxOther = m_d->controller->subSystemCheckBox(VP1GeoFlags::AllUnrecognisedVolumes); + + if(VP1Msg::debug()){ + qDebug() << "Looping on volumes from the input GeoModel..."; + } + GeoVolumeCursor av(world); + while (!av.atEnd()) { + + std::string name = av.getName(); + if(VP1Msg::debug()){ + qDebug() << "volume name:" << QString::fromStdString(name); + } + + // DEBUG + VP1Msg::messageDebug("DEBUG: Found GeoModel treetop: "+QString(name.c_str())); + + //Let us see if we recognize this volume: + bool found = false; + foreach (Imp::SubSystemInfo * subsys, m_d->subsysInfoList) { + if (subsys->negatetreetopregexp!=subsys->geomodeltreetopregexp.exactMatch(name.c_str())) + { + if (subsys->checkbox==checkBoxOther&&found) { + continue;//The "other" subsystem has a wildcard which matches everything - but we only want stuff that is nowhere else. + } + + if(VP1Msg::debug()){ + qDebug() << (subsys->geomodeltreetopregexp).pattern() << subsys->geomodeltreetopregexp.exactMatch(name.c_str()) << subsys->negatetreetopregexp; + qDebug() << "setting 'found' to TRUE for pattern:" << (subsys->geomodeltreetopregexp).pattern(); + } + found = true; + //We did... now, time to extract info: + subsys->treetopinfo.resize(subsys->treetopinfo.size()+1); + subsys->treetopinfo.back().pV = av.getVolume(); + subsys->treetopinfo.back().xf = Amg::EigenTransformToCLHEP(av.getTransform()); + subsys->treetopinfo.back().volname = av.getName(); + + //Add a switch for this system (turned off for now): + SoSwitch * sw = new SoSwitch(); + //But add a separator on top of it (for caching): + subsys->soswitch = sw; + if (sw->whichChild.getValue() != SO_SWITCH_NONE) + sw->whichChild = SO_SWITCH_NONE; + SoSeparator * sep = new SoSeparator; + sep->addChild(sw); + root->addChild(sep); + //Enable the corresponding checkbox: + subsys->checkbox->setEnabled(true); + subsys->checkbox->setToolTip("Toggle the display of the "+subsys->checkbox->text()+" sub system"); + //NB: Dont break here - several systems might share same treetop! + // break; + } + } + if (!found) { + message("Warning: Found unexpected GeoModel treetop: "+QString(name.c_str())); + } + + av.next(); // increment volume cursor. + } + + //Hide other cb if not needed: + if (!checkBoxOther->isEnabled()) + checkBoxOther->setVisible(false); + + //Build the geometry for those (available) subsystems that starts out being turned on: + foreach (Imp::SubSystemInfo * subsys, m_d->subsysInfoList) { + if (!subsys->soswitch||!subsys->checkbox->isChecked()) + continue; + m_d->buildSystem(subsys); + //Enable in 3D view: + if (subsys->soswitch->whichChild.getValue() != SO_SWITCH_ALL) + subsys->soswitch->whichChild = SO_SWITCH_ALL; + //Enable in tree browser: + m_d->volumetreemodel->enableSubSystem(subsys->flag); + // new ModelTest(m_d->volumetreemodel, m_d->treeView_volumebrowser); + } + if (!m_d->restoredTopvolstates.isEmpty()) { + m_d->applyTopVolStates(m_d->restoredTopvolstates,false); + m_d->restoredTopvolstates.clear(); + } + m_d->phisectormanager->updateRepresentationsOfVolsAroundZAxis(); + root->enableNotify(save); + if (save) + root->touch(); + +} + +//_____________________________________________________________________________________ +void VP1GeometrySystem::checkboxChanged() +{ + QCheckBox * cb = static_cast<QCheckBox*>(sender()); + Imp::SubSystemInfo * subsys(0); + foreach (Imp::SubSystemInfo * ss, m_d->subsysInfoList) { + if (cb==ss->checkbox) { + subsys=ss; + break; + } + } + if (!subsys) { + message("ERROR: Unknown checkbox"); + return; + } + SoSwitch * sw = subsys->soswitch; + assert(sw); + if (cb->isChecked()) { + SbBool save = sw->enableNotify(false); + if (sw->getNumChildren()==0) { + m_d->buildSystem(subsys); + m_d->phisectormanager->updateRepresentationsOfVolsAroundZAxis();// + } + if (sw->whichChild.getValue() != SO_SWITCH_ALL) + sw->whichChild = SO_SWITCH_ALL; + sw->enableNotify(save); + //Enable in tree browser: + m_d->volumetreemodel->enableSubSystem(subsys->flag); + // new ModelTest(m_d->volumetreemodel, m_d->treeView_volumebrowser); + if (save) + sw->touch(); + } else { + if (sw->whichChild.getValue() != SO_SWITCH_NONE) + sw->whichChild = SO_SWITCH_NONE; + m_d->volumetreemodel->disableSubSystem(subsys->flag); + } +} + +//_____________________________________________________________________________________ +void VP1GeometrySystem::userPickedNode(SoNode* , SoPath *pickedPath) +{ + + ////////////////////////////////////////////////////////////////////////// + // We want to find the volumehandle for the volume. To do so, we look // + // for the SoSeparator identifying the actual picked shape node, and // + // use it to look up the handle: // + ////////////////////////////////////////////////////////////////////////// + + //Looking for the identifying "nodesep", there are three scenarios + //for the type signatures of the final part of the path: + // + // 1) Most shapes: + // nodesep -> pickedNode (but we must pop to a group node in case of SoCylinders) + // + // 2) Volumes Around Z (all phi sectors enabled): + // nodesep -> switch -> pickedNode + // + // 3) Volumes Around Z (only some phi sectors enabled): + // nodesep -> switch -> sep -> pickedNode + // + // In the third scenario we also have to pop the path, in order for + // all phi-slices of the part gets highlighted (since more than one + // soshape node represents the volume). + + // std::cout << "Entering userPickedNode" << std::endl; + VP1Msg::messageDebug("VP1GeometrySystem::userPickedNode()"); + + if (pickedPath->getNodeFromTail(0)->getTypeId()==SoCylinder::getClassTypeId()) + pickedPath->pop(); + + if (pickedPath->getLength()<5) { + message("Path too short"); + return; + } + + SoSeparator * nodesep(0); + + if (pickedPath->getNodeFromTail(1)->getTypeId()==SoSeparator::getClassTypeId() + && pickedPath->getNodeFromTail(2)->getTypeId()==SoSwitch::getClassTypeId() + && pickedPath->getNodeFromTail(3)->getTypeId()==SoSeparator::getClassTypeId()) + { + //Scenario 3: + nodesep = static_cast<SoSeparator*>(pickedPath->getNodeFromTail(3)); + pickedPath->pop();//To get highlighting of siblings also. + } + else if (pickedPath->getNodeFromTail(1)->getTypeId()==SoSwitch::getClassTypeId() + && pickedPath->getNodeFromTail(2)->getTypeId()==SoSeparator::getClassTypeId()) + { + //Scenario 2: + nodesep = static_cast<SoSeparator*>(pickedPath->getNodeFromTail(2)); + } + else if (pickedPath->getNodeFromTail(1)->getTypeId()==SoSeparator::getClassTypeId()) { + //Scenario 1 (normal): + nodesep = static_cast<SoSeparator*>(pickedPath->getNodeFromTail(1)); + } + if (!nodesep) { + message("Unexpected picked path"); + return; + } + if ( (!(nodesep)) || (m_d->sonodesep2volhandle.find(nodesep) == m_d->sonodesep2volhandle.end()) ) { + message("Problems finding volume handle"); + return; + } + VolumeHandle * volhandle = m_d->sonodesep2volhandle[nodesep]; + if (!volhandle) { + message("Found NULL volume handle"); + return; + } + + ///////////////////////////////////////////////////////////////////////// + // Next thing to do is to check whether volume was clicked on with a // + // modifier of SHIFT/CTRL/Z. If so, we have to change the state on // + // the volume handle. Otherwise, we need to print some information: // + ///////////////////////////////////////////////////////////////////////// + + //For focus reason, and since Qt doesn't allow standard keys such as + //'z' as modifiers, we check for keypress states using a combination + //of the inventor and Qt way + + bool shift_isdown = (Qt::ShiftModifier & QApplication::keyboardModifiers()); +// || ( m_d->kbEvent && (SO_KEY_PRESS_EVENT(m_d->kbEvent, SoKeyboardEvent::LEFT_SHIFT)|| +// SO_KEY_PRESS_EVENT(m_d->kbEvent, SoKeyboardEvent::RIGHT_SHIFT)) ) ); + + if (shift_isdown) { + //Parent of volume should be put in CONTRACTED state. + deselectAll(); + if (volhandle->parent()) + volhandle->parent()->setState(VP1GeoFlags::CONTRACTED); + m_d->phisectormanager->updateRepresentationsOfVolsAroundZAxis(); + return; + } + + bool ctrl_isdown = (Qt::ControlModifier & QApplication::keyboardModifiers()); +// || ( m_d->kbEvent && (SO_KEY_PRESS_EVENT(m_d->kbEvent, SoKeyboardEvent::LEFT_CONTROL)|| +// SO_KEY_PRESS_EVENT(m_d->kbEvent, SoKeyboardEvent::RIGHT_CONTROL)) ) ); + + if (ctrl_isdown) { + //Volume should be put in EXPANDED state if it has children. + message("Calling deselectAll"); + deselectAll(); + message("Back from deselectAll"); + if (volhandle->nChildren()>0) { + message("Calling volhandle->setState"); + volhandle->setState(VP1GeoFlags::EXPANDED); + } + message("calling phisectormanager"); + m_d->phisectormanager->updateRepresentationsOfVolsAroundZAxis(); + message("leaving ctrl_isdown"); + return; + } + + bool z_isdown = m_d->kbEvent && SO_KEY_PRESS_EVENT(m_d->kbEvent,SoKeyboardEvent::Z); + if (z_isdown) { + //Volume should be put in ZAPPED state. + deselectAll(); + volhandle->setState(VP1GeoFlags::ZAPPED); + message("===> Zapping Node: "+volhandle->getName()); + // std::cout<<"Zapped VH="<<volhandle<<std::endl; + return; + } + + + bool orientedView(false); + + ////////////////////// + // Zoom to volume // + ////////////////////// + + //Nb: We don't do this if we already oriented to the muon chamber above. + if (!orientedView&&m_d->controller->zoomToVolumeOnClick()) { + if (m_d->sceneroot&&volhandle->nodeSoSeparator()) { + std::set<SoCamera*> cameras = getCameraList(); + std::set<SoCamera*>::iterator it,itE = cameras.end(); + for (it=cameras.begin();it!=itE;++it) { + VP1CameraHelper::animatedZoomToSubTree(*it,m_d->sceneroot,volhandle->nodeSoSeparator(),2.0,1.0); + } + } + } + + + /////////////////////////////////// + // Update last-select controls // + /////////////////////////////////// + + m_d->controller->setLastSelectedVolume(volhandle); + + ///////////////////////////////////////////////////////// + // OK, time to print some information for the volume // + ///////////////////////////////////////////////////////// + + message("===> Selected Node: "+volhandle->getName()); + // std::cout<<"VolHandle = "<<volhandle<<std::endl; + if (m_d->controller->printInfoOnClick_Shape()) { + foreach (QString str, DumpShape::shapeToStringList(volhandle->geoPVConstLink()->getLogVol()->getShape())) + message(str); + } + + if (m_d->controller->printInfoOnClick_Material()) { + message("===> Material:"); + foreach (QString line, VP1GeomUtils::geoMaterialToStringList(volhandle->geoMaterial())) + message(" "+line); + } + + if ( m_d->controller->printInfoOnClick_CopyNumber() ) { + int cn = volhandle->copyNumber(); + message("===> CopyNo : "+(cn>=0?QString::number(cn):QString(cn==-1?"Invalid":"Error reconstructing copynumber"))); + } + + if ( m_d->controller->printInfoOnClick_Transform() ) { + + float translation_x, translation_y, translation_z, rotaxis_x, rotaxis_y, rotaxis_z, rotangle_radians; + VP1LinAlgUtils::decodeTransformation( volhandle->getLocalTransformToVolume(), + translation_x, translation_y, translation_z, + rotaxis_x, rotaxis_y, rotaxis_z, rotangle_radians ); + message("===> Local Translation:"); + message(" x = "+QString::number(translation_x/CLHEP::mm)+" mm"); + message(" y = "+QString::number(translation_y/CLHEP::mm)+" mm"); + message(" z = "+QString::number(translation_z/CLHEP::mm)+" mm"); + message("===> Local Rotation:"); + message(" axis x = "+QString::number(rotaxis_x)); + message(" axis y = "+QString::number(rotaxis_y)); + message(" axis z = "+QString::number(rotaxis_z)); + message(" angle = "+QString::number(rotangle_radians*180.0/M_PI)+" deg"); + VP1LinAlgUtils::decodeTransformation( volhandle->getGlobalTransformToVolume(), + translation_x, translation_y, translation_z, + rotaxis_x, rotaxis_y, rotaxis_z, rotangle_radians ); + message("===> Global Translation:"); + message(" x = "+QString::number(translation_x/CLHEP::mm)+" mm"); + message(" y = "+QString::number(translation_y/CLHEP::mm)+" mm"); + message(" z = "+QString::number(translation_z/CLHEP::mm)+" mm"); + message("===> Global Rotation:"); + message(" axis x = "+QString::number(rotaxis_x)); + message(" axis y = "+QString::number(rotaxis_y)); + message(" axis z = "+QString::number(rotaxis_z)); + message(" angle = "+QString::number(rotangle_radians*180.0/M_PI)+" deg"); + } + + if (m_d->controller->printInfoOnClick_Tree()) { + std::ostringstream str; + GeoPrintGraphAction pg(str); + volhandle->geoPVConstLink()->exec(&pg); + message("===> Tree:"); + foreach (QString line, QString(str.str().c_str()).split("\n")) + message(" "+line); + } + + if (m_d->controller->printInfoOnClick_Mass()) { + //FIXME: Move the mass calculations to the volume handles, and let + //the common data cache some of the volume information by + //logVolume). + message("===> Total Mass <==="); + message("Inclusive "+QString::number(Imp::inclusiveMass(volhandle->geoPVConstLink())/CLHEP::kilogram)+" kg"); + message("Exclusive "+QString::number(Imp::exclusiveMass(volhandle->geoPVConstLink())/CLHEP::kilogram)+" kg"); + } + + + ///////////////////////////////////////////////////////////////// + // Emit a signal for the VP1UtilitySystems::PartSpect system // + ///////////////////////////////////////////////////////////////// + QStack<QString> partspectPath, extras; + QString detFactoryName; + + VolumeHandle *parentVH(volhandle), *childVH(volhandle); + m_d->createPathExtras(volhandle,detFactoryName,extras); + + do { + parentVH = parentVH->parent(); + PVConstLink parentPVLink = parentVH ? parentVH->geoPVConstLink() : childVH->geoPVConstLink()->getParent(); + if (parentPVLink) { + int indexOfChild = parentVH ? childVH->childNumber() : (int)parentPVLink->indexOf(childVH->geoPVConstLink()); + + std::string childPVName = parentPVLink->getNameOfChildVol(indexOfChild); + QString pathEntry = childPVName=="ANON" ? detFactoryName+childVH->getName() : QString(childPVName.c_str()); + + Query<int> childCopyNo = parentPVLink->getIdOfChildVol(indexOfChild); + if(childCopyNo.isValid()) { + QString strCopyNo; + strCopyNo.setNum(childCopyNo); + pathEntry += ("::"+strCopyNo); + } + partspectPath.push(pathEntry); + childVH = parentVH; + } + }while(parentVH); + + while(!extras.isEmpty()) + partspectPath.push(extras.pop()); + + partspectPath.push("Atlas::Atlas"); + + // Emit the signal + //volhandle cannot be NULL here (coverity 16287) + //int cn=(!volhandle) ? -1 : volhandle->copyNumber(); + int cn=volhandle->copyNumber(); + plotSpectrum(partspectPath,cn); +} + +//_____________________________________________________________________________________ +void VP1GeometrySystem::Imp::buildSystem(SubSystemInfo* si) +{ + VP1Msg::messageDebug("VP1GeometrySystem::Imp::buildSystem()" ); + + if (!si||si->isbuilt) + return; + si->isbuilt = true; + int ichild(0); + + ensureInitVisAttributes(); + +// // DEBUG +// foreach(Imp::SubSystemInfo*si,m_d->subsysInfoList) { +// VP1Msg::messageDebug("vol: " + QString((si->flag).str_c()) ); +// } + + assert(si->soswitch); + SoSeparator * subsystemsep = new SoSeparator; + phisectormanager->registerSubSystemSeparator(si->flag,subsystemsep); + phisectormanager->largeChangesBegin(); + + SbBool save = si->soswitch->enableNotify(false); + + if (si->geomodelchildrenregexp.isEmpty()) { + //Loop over the treetop's that we previously selected: + + std::vector<SubSystemInfo::TreetopInfo>::const_iterator it, itE = si->treetopinfo.end(); + for (it=si->treetopinfo.begin();it!=itE;++it) + { + VP1Msg::messageDebug("toptree vol: " + QString(it->volname.c_str()) ); + + //Find material: + SoMaterial*m = detVisAttributes->get(it->volname); + if (!m) { + theclass->message("Warning: Did not find a predefined material for volume: "+QString(it->volname.c_str())); + } + VolumeHandleSharedData* volhandle_subsysdata = new VolumeHandleSharedData(controller,si->flag,&sonodesep2volhandle,it->pV,phisectormanager, + m,matVisAttributes,volVisAttributes, + controller->zappedVolumeListModel(),controller->volumeTreeBrowser(), m_textSep); + SbMatrix matr; + VP1LinAlgUtils::transformToMatrix(it->xf,matr); + VolumeHandle * vh = new VolumeHandle(volhandle_subsysdata,0,it->pV,ichild++,VolumeHandle::NONMUONCHAMBER,matr); + si->vollist.push_back(vh); + // std::cout<<"Non muon chamber VH="<<vh<<std::endl; + } + } else { + //Loop over the children of the physical volumes of the treetops that we previously selected: + std::vector<SubSystemInfo::TreetopInfo>::const_iterator it, itE = si->treetopinfo.end(); + for (it=si->treetopinfo.begin();it!=itE;++it) { + + VP1Msg::messageDebug("group name: " + QString(si->matname.c_str()) ); + + //NB: Here we use the si->matname. Above we use the si->volname. Historical reasons! + + //Find material for top-nodes: + SoMaterial*mat_top(0); + if (si->matname!="") + mat_top = detVisAttributes->get(si->matname); + + VolumeHandleSharedData* volhandle_subsysdata = new VolumeHandleSharedData(controller,si->flag,&sonodesep2volhandle,it->pV,phisectormanager, + mat_top,matVisAttributes,volVisAttributes, + controller->zappedVolumeListModel(),controller->volumeTreeBrowser(),m_textSep); + volhandle_subsysdata->ref(); + + GeoVolumeCursor av(it->pV); + //unsigned int count=0; + while (!av.atEnd()) { + + // DEBUG +// VP1Msg::messageDebug("child vol: " + QString(av.getName().c_str()) ); + + //Use the childrenregexp to select the correct child volumes: + if (si->childrenRegExpNameCompatible(av.getName().c_str())) { + PVConstLink pVD = av.getVolume(); + SbMatrix matr; + VP1LinAlgUtils::transformToMatrix(Amg::EigenTransformToCLHEP(av.getTransform()),matr); + VolumeHandle * vh=0; + // std::cout<<count++<<": dump SubSystemInfo\n"<<"---"<<std::endl; + // si->dump(); + // std::cout<<"---"<<std::endl; + + vh = new VolumeHandle(volhandle_subsysdata,0,pVD,ichild++, + VolumeHandle::NONMUONCHAMBER,matr); + // std::cout<<"Does not have muon chamber (weird one) VH="<<vh<<std::endl; + + // DEBUG +// VP1Msg::messageDebug("granchild vol: " + vh->getName() + " - " + vh->getDescriptiveName() ); + + if (si->geomodelgrandchildrenregexp.isEmpty()) { + // append the volume to the current list + theclass->messageDebug("grandchild inserted : " + vh->getDescriptiveName() + " - " + vh->getName() ); + si->vollist.push_back(vh); + + } else { + VP1Msg::messageDebug("filtering at grandchild level..."); + if (si->grandchildrenRegExpNameCompatible(vh->getName().toStdString() ) ) { + VP1Msg::messageDebug("filtered grandchild inserted : " + vh->getDescriptiveName() + " - " + vh->getName() ); + // append the volume to the current list + si->vollist.push_back(vh); + } else { + theclass->message("Zapping this volumehandle because it's probably junk."+vh->getDescriptiveName() + " - " + vh->getName()); + vh->setState(VP1GeoFlags::ZAPPED); // FIXME - better solution for this? Maybe just don't create them? + + // std::cout<<"Not adding "<<vh->getName().toStdString()<<"["<<vh<<"] to vollist"<<std::endl; + } + } + } + av.next(); // increment volume cursor. + } + volhandle_subsysdata->unref();//To ensure it is deleted if it was not used. + } + } + + + si->dump(); + + VP1Msg::messageDebug("volumetreemodel->addSubSystem..."); + volumetreemodel->addSubSystem( si->flag, si->vollist ); + + //NB: We let the destructor of volumetreemodel take care of deleting + //our (top) volume handles, since it has to keep a list of them + //anyway. + + + //Perform auto expansion of all ether volumes (needed for muon dead material): + VP1Msg::messageDebug("Perform auto expansion of all ether volumes"); + VolumeHandle::VolumeHandleListItr it, itE(si->vollist.end()); + //int idx=0; // for debug + for (it = si->vollist.begin(); it!=itE; ++it){ + //VP1Msg::messageDebug("\nexpanding idx: " + QString::number(++idx)); + (*it)->expandMothersRecursivelyToNonEther(); + //VP1Msg::messageDebug("expand DONE."); + } + + + VP1Msg::messageDebug("addChild..."); + phisectormanager->updateRepresentationsOfVolsAroundZAxis(); + phisectormanager->largeChangesEnd(); + si->soswitch->addChild(subsystemsep); + si->soswitch->enableNotify(save); + if (save) + si->soswitch->touch(); + VP1Msg::messageDebug("END of VP1GeometrySystem::Imp::buildSystem() " ); +} + +//_____________________________________________________________________________________ +double VP1GeometrySystem::Imp::exclusiveMass(const PVConstLink& pv) { + const GeoLogVol* lv = pv->getLogVol(); + const GeoMaterial *material = lv->getMaterial(); + double density = material->getDensity(); + return density*volume(pv); +} + + +//_____________________________________________________________________________________ +double VP1GeometrySystem::Imp::volume(const PVConstLink& pv) { + const GeoLogVol * lv = pv->getLogVol(); + const GeoShape *shape = lv->getShape(); + return shape->volume(); +} + + +//_____________________________________________________________________________________ +double VP1GeometrySystem::Imp::inclusiveMass(const PVConstLink& pv) { + + const GeoLogVol* lv = pv->getLogVol(); + const GeoMaterial *material = lv->getMaterial(); + double density = material->getDensity(); + + double mass = exclusiveMass(pv); + + GeoVolumeCursor av(pv); + while (!av.atEnd()) { + mass += inclusiveMass(av.getVolume()); + mass -= volume(av.getVolume())*density; + av.next(); + } + + return mass; +} + +//_____________________________________________________________________________________ +QByteArray VP1GeometrySystem::saveState() { + + ensureBuildController(); + + VP1Serialise serialise(7/*version*/,this); + serialise.save(IVP13DSystemSimple::saveState()); + + //Controller: + serialise.save(m_d->controller->saveSettings()); + + //Subsystem checkboxes: + QMap<QString,bool> subsysstate; + foreach (Imp::SubSystemInfo * subsys, m_d->subsysInfoList) { + serialise.widgetHandled(subsys->checkbox); + subsysstate.insert(subsys->checkbox->text(),subsys->checkbox->isChecked()); + } + serialise.save(subsysstate); + + //Volume states: + QMap<quint32,QByteArray> topvolstates; + foreach (Imp::SubSystemInfo * subsys, m_d->subsysInfoList) { + VolumeHandle::VolumeHandleListItr it(subsys->vollist.begin()),itE(subsys->vollist.end()); + for (;it!=itE;++it) + topvolstates.insert((*it)->hashID(),(*it)->getPersistifiableState()); + } + serialise.save(topvolstates); + + m_d->ensureInitVisAttributes(); + serialise.save(m_d->detVisAttributes->getState());//version 7+ + serialise.save(m_d->matVisAttributes->getState());//version 7+ + serialise.save(m_d->volVisAttributes->getState());//version 7+ + + serialise.disableUnsavedChecks();//We do the testing in the controller + return serialise.result(); +} + +//_____________________________________________________________________________________ +void VP1GeometrySystem::restoreFromState(QByteArray ba) { + VP1Deserialise state(ba,this); + if (state.version()<0||state.version()>7) { + message("Warning: State data in .vp1 file is in wrong format - ignoring!"); + return; + } + if (state.version()<=5) { + message("Warning: State data in .vp1 file is in obsolete format - ignoring!"); + return; + } + + ensureBuildController(); + IVP13DSystemSimple::restoreFromState(state.restoreByteArray()); + + //Controller: + m_d->controller->restoreSettings(state.restoreByteArray()); + + //Subsystem checkboxes: + VP1GeoFlags::SubSystemFlags flags(0); + QMap<QString,bool> subsysstate = state.restore<QMap<QString,bool> >(); + foreach (Imp::SubSystemInfo * subsys, m_d->subsysInfoList) { + state.widgetHandled(subsys->checkbox); + if (subsysstate.contains(subsys->checkbox->text())&&subsysstate[subsys->checkbox->text()]) + flags |= subsys->flag; + } + m_d->initialSubSystemsTurnedOn = flags; + + //Volume states: + QMap<quint32,QByteArray> topvolstates; + topvolstates = state.restore<QMap<quint32,QByteArray> >(); + if (m_d->sceneroot)//(for some reason) we already have been in buildPermanentScenegraph + m_d->applyTopVolStates(topvolstates,true); + else + m_d->restoredTopvolstates = topvolstates;//save until buildPermanentScenegraph + + if (state.version()>=7) { + m_d->ensureInitVisAttributes(); + m_d->detVisAttributes->applyState(state.restoreByteArray()); + m_d->matVisAttributes->applyState(state.restoreByteArray()); + m_d->volVisAttributes->applyState(state.restoreByteArray()); + } + + state.disableUnrestoredChecks();//We do the testing in the controller +} + +//_____________________________________________________________________________________ +void VP1GeometrySystem::Imp::applyTopVolStates(const QMap<quint32,QByteArray>&topvolstates,bool disablenotif) +{ + if (disablenotif) + phisectormanager->largeChangesBegin(); + QMap<quint32,QByteArray>::const_iterator topvolstatesItr; + foreach (Imp::SubSystemInfo * subsys, subsysInfoList) { + VolumeHandle::VolumeHandleListItr it(subsys->vollist.begin()),itE(subsys->vollist.end()); + for (;it!=itE;++it) { + topvolstatesItr = topvolstates.find((*it)->hashID()); + if (topvolstatesItr!=topvolstates.end()) + (*it)->applyPersistifiableState(topvolstatesItr.value()); + } + } + if (disablenotif) { + phisectormanager->updateRepresentationsOfVolsAroundZAxis(); + phisectormanager->largeChangesEnd(); + } +} + +//_____________________________________________________________________________________ +void VP1GeometrySystem::Imp::createPathExtras(const VolumeHandle* volhandle, QString& prefix, QStack<QString>& entries) +{ + switch(volhandle->subsystem()){ + case VP1GeoFlags::Veto:{ + prefix = QString("Veto::"); + entries.push("SCINT::SCINT"); + entries.push("Veto::Veto"); + return; + } + case VP1GeoFlags::Trigger:{ + prefix = QString("Trigger::"); + entries.push("SCINT::SCINT"); + entries.push("Trigger::Trigger"); + return; + } + case VP1GeoFlags::Preshower:{ + prefix = QString("Preshower::"); + entries.push("SCINT::SCINT"); + entries.push("Preshower::Preshower"); + return; + } + case VP1GeoFlags::SCT:{ + prefix = QString("SCT::"); + entries.push("TRACKER::TRACKER"); + entries.push("SCT::SCT"); + return; + } + case VP1GeoFlags::Ecal:{ + prefix = QString("Ecal::"); + entries.push("CALO::CALO"); + entries.push("Ecal::Ecal"); + return; + } + case VP1GeoFlags::None: + case VP1GeoFlags::AllUnrecognisedVolumes: + default:{ + return; + } + } +} + +//_____________________________________________________________________________________ +void VP1GeometrySystem::setCurvedSurfaceRealism(int val) +{ + ensureBuildController(); + if (val<0||val>100) { + message("setCurvedSurfaceRealism Error: Value "+str(val)+"out of range!"); + return; + } + m_d->controller->setComplexity(val==100?1.0:(val==0?0.0:val/100.0)); +} + + + +//_____________________________________________________________________________________ +void VP1GeometrySystem::updateTransparency() +{ + ensureBuildController(); + + float transparency = m_d->controller->transparency(); + + VolumeHandle* lastSelVol = m_d->controller->lastSelectedVolume(); + m_d->controller->setLastSelectedVolume(0); + m_d->ensureInitVisAttributes(); + m_d->detVisAttributes->overrideTransparencies(transparency); + m_d->matVisAttributes->overrideTransparencies(transparency); + m_d->volVisAttributes->overrideTransparencies(transparency); + m_d->controller->setLastSelectedVolume(lastSelVol); +} + +//_____________________________________________________________________________________ +void VP1GeometrySystem::resetSubSystems(VP1GeoFlags::SubSystemFlags f) +{ + if (!f) { + return; + } + + deselectAll(); + foreach(Imp::SubSystemInfo*si,m_d->subsysInfoList) { + if (si->flag & f) { + if (!si->isbuilt) { + continue; + } + VolumeHandle::VolumeHandleListItr it(si->vollist.begin()),itE(si->vollist.end()); + for (;it!=itE;++it) { + messageDebug("resetting volume --> " + (*it)->getName() ); + (*it)->reset(); + } + } + } +} + +//_____________________________________________________________________________________ +void VP1GeometrySystem::Imp::changeStateOfVisibleNonStandardVolumesRecursively(VolumeHandle*handle,VP1GeoFlags::VOLSTATE target) +{ + assert(target!=VP1GeoFlags::CONTRACTED); + if (handle->isAttached()) { + //The volume is visible, so ignore daughters + if (handle->isInitialisedAndHasNonStandardShape()) { + if (target!=VP1GeoFlags::EXPANDED||handle->nChildren()>0) + handle->setState(target); + } + return; + } else if (handle->state()==VP1GeoFlags::ZAPPED) + return; + //Must be expanded: Let us call on any (initialised) children instead. + if (handle->nChildren()==0||!handle->childrenAreInitialised()) + return; + VolumeHandle::VolumeHandleListItr it(handle->childrenBegin()), itE(handle->childrenEnd()); + for(;it!=itE;++it) + changeStateOfVisibleNonStandardVolumesRecursively(*it,target); + +} + +//_____________________________________________________________________________________ +void VP1GeometrySystem::actionOnAllNonStandardVolumes(bool zap) +{ + VP1GeoFlags::VOLSTATE target = zap ? VP1GeoFlags::ZAPPED : VP1GeoFlags::EXPANDED; + messageVerbose("Action on volumes with non-standard VRML representations. Target state is "+VP1GeoFlags::toString(target)); + + std::vector<std::pair<VolumeHandle::VolumeHandleListItr,VolumeHandle::VolumeHandleListItr> > roothandles; + m_d->volumetreemodel->getRootHandles(roothandles); + VolumeHandle::VolumeHandleListItr it, itE; + + bool save = m_d->sceneroot->enableNotify(false); + m_d->phisectormanager->largeChangesBegin(); + + deselectAll(); + + for (unsigned i = 0; i<roothandles.size();++i) { + it = roothandles.at(i).first; + itE = roothandles.at(i).second; + for(;it!=itE;++it) { + m_d->changeStateOfVisibleNonStandardVolumesRecursively(*it,target); + } + } + + m_d->phisectormanager->updateRepresentationsOfVolsAroundZAxis(); + m_d->phisectormanager->largeChangesEnd(); + if (save) { + m_d->sceneroot->enableNotify(true); + m_d->sceneroot->touch(); + } +} + +//_____________________________________________________________________________________ +void VP1GeometrySystem::autoExpandByVolumeOrMaterialName(bool bymatname,QString targetname) +{ + if (targetname.isEmpty()) { + VP1Msg::messageDebug("targetname is empty."); + return; + } + + messageVerbose("Auto expansions of visible volumes requested. Target all volumes with " + +str(bymatname?"material name":"name")+" matching "+targetname); + + QRegExp selregexp(targetname,Qt::CaseSensitive,QRegExp::Wildcard); + + std::vector<std::pair<VolumeHandle::VolumeHandleListItr,VolumeHandle::VolumeHandleListItr> > roothandles; + m_d->volumetreemodel->getRootHandles(roothandles); + VolumeHandle::VolumeHandleListItr it, itE; + + bool save = m_d->sceneroot->enableNotify(false); + m_d->phisectormanager->largeChangesBegin(); + + deselectAll(); + + for (unsigned i = 0; i<roothandles.size();++i) { + it = roothandles.at(i).first; + itE = roothandles.at(i).second; + for(;it!=itE;++it) + m_d->expandVisibleVolumesRecursively(*it,selregexp,bymatname); + } + + m_d->phisectormanager->updateRepresentationsOfVolsAroundZAxis(); + m_d->phisectormanager->largeChangesEnd(); + if (save) { + m_d->sceneroot->enableNotify(true); + m_d->sceneroot->touch(); + } +} + +//_____________________________________________________________________________________ +void VP1GeometrySystem::Imp::expandVisibleVolumesRecursively(VolumeHandle* handle,const QRegExp& selregexp,bool bymatname) +{ + if (handle->state()==VP1GeoFlags::ZAPPED) + return; + if (handle->state()==VP1GeoFlags::CONTRACTED) { + //See if we match (and have children) - if so, update state. + if (handle->nChildren()>0 + && selregexp.exactMatch(bymatname?QString(handle->geoMaterial()->getName().c_str()):handle->getName())) { + handle->setState(VP1GeoFlags::EXPANDED); + } + return; + } + //Must be expanded: Let us call on any (initialised) children instead. + if (handle->nChildren()==0||!handle->childrenAreInitialised()) + return; + VolumeHandle::VolumeHandleListItr it(handle->childrenBegin()), itE(handle->childrenEnd()); + for(;it!=itE;++it) + expandVisibleVolumesRecursively(*it,selregexp,bymatname); +} + +//_____________________________________________________________________________________ +void VP1GeometrySystem::volumeStateChangeRequested(VolumeHandle*vh,VP1GeoFlags::VOLSTATE state) +{ + //might not use this slot presently... + if (!vh) + return; + deselectAll(); + vh->setState(state); + m_d->phisectormanager->updateRepresentationsOfVolsAroundZAxis(); +} + +//_____________________________________________________________________________________ +void VP1GeometrySystem::volumeResetRequested(VolumeHandle*vh) +{ + if (!vh) + return; + deselectAll(); + vh->reset(); + m_d->phisectormanager->updateRepresentationsOfVolsAroundZAxis(); +} + +//_____________________________________________________________________________________ +void VP1GeometrySystem::setShowVolumeOutLines(bool b) +{ + std::map<SoSeparator*,VolumeHandle*>::iterator it,itE(m_d->sonodesep2volhandle.end()); + for (it =m_d->sonodesep2volhandle.begin();it!=itE;++it) + VolumeHandleSharedData::setShowVolumeOutlines(it->first,b); +} + + +//_____________________________________________________________________________________ +void VP1GeometrySystem::saveMaterialsToFile(QString filename,bool onlyChangedMaterials) +{ + if (filename.isEmpty()) + return; + + //If file exists, ask to overwrite. + QFileInfo fi(filename); + if (fi.exists()) { + if (!fi.isWritable()) { + QMessageBox::critical(0, "Error - could not save to file "+filename, + "Could not save to file: <i>"+filename+"</i>" + +"<br/><br/>Reason: File exists already and is write protected",QMessageBox::Ok,QMessageBox::Ok); + return; + } + } + + QFile file(filename); + if (!file.open(QIODevice::WriteOnly)) { + QMessageBox::critical(0, "Error - problems writing to file "+filename, + "Problems writing to file: <i>"+filename+"</i>",QMessageBox::Ok,QMessageBox::Ok); + return; + } + + m_d->ensureInitVisAttributes(); + VP1Serialise s(0/*version*/,this); + //Save some file ID info!! + s.save(QString("VP1GeoMaterialsBegin")); + s.save(m_d->detVisAttributes->getState(onlyChangedMaterials)); + s.save(m_d->matVisAttributes->getState(onlyChangedMaterials)); + s.save(m_d->volVisAttributes->getState(onlyChangedMaterials)); + s.save(QString("VP1GeoMaterialsEnd")); + s.disableUnsavedChecks(); + + QDataStream outfile(&file); + outfile<<qCompress(s.result()).toBase64(); + +} + +//_____________________________________________________________________________________ +void VP1GeometrySystem::loadMaterialsFromFile(QString filename) +{ + if (filename.isEmpty()) + return; + QFileInfo fi(filename); + if (!fi.exists()) { + QMessageBox::critical(0, "Error - file does not exists: "+filename, + "File does not exists: <i>"+filename+"</i>",QMessageBox::Ok,QMessageBox::Ok); + return; + } + if (!fi.isReadable()) { + QMessageBox::critical(0, "Error - file is not readable: "+filename, + "File is not readable: <i>"+filename+"</i>",QMessageBox::Ok,QMessageBox::Ok); + return; + } + //open file + QFile file(filename); + if (!file.open(QIODevice::ReadOnly)) { + QMessageBox::critical(0, "Error - problems opening file "+filename, + "Problems opening file: <i>"+filename+"</i>",QMessageBox::Ok,QMessageBox::Ok); + return; + } + QByteArray byteArray64; + QDataStream infile(&file); + infile >> byteArray64; + QByteArray byteArray = qUncompress(QByteArray::fromBase64(byteArray64)); + + VP1Deserialise s(byteArray,this); + if (s.version()!=0) { + QMessageBox::critical(0, "Error - File in wrong format "+filename, + "File in wrong format: <i>"+filename+"</i>",QMessageBox::Ok,QMessageBox::Ok); + return; + } + QString txtbegin, txtend; + QByteArray baDet, baMat, baVol; + txtbegin = s.restoreString(); + baDet = s.restoreByteArray(); + baMat = s.restoreByteArray(); + baVol = s.restoreByteArray(); + txtend = s.restoreString(); + s.disableUnrestoredChecks(); + if (txtbegin!="VP1GeoMaterialsBegin"||txtend!="VP1GeoMaterialsEnd") { + QMessageBox::critical(0, "Error - File in wrong format "+filename, + "File in wrong format: <i>"+filename+"</i>",QMessageBox::Ok,QMessageBox::Ok); + return; + } + + m_d->ensureInitVisAttributes(); + m_d->detVisAttributes->applyState(baDet); + m_d->matVisAttributes->applyState(baMat); + m_d->volVisAttributes->applyState(baVol); + + VolumeHandle* lastsel = m_d->controller->lastSelectedVolume(); + m_d->controller->setLastSelectedVolume(0); + m_d->controller->setLastSelectedVolume(lastsel); +} + +//____________________________________________________________________ +void VP1GeometrySystem::setLabelPosOffsets( QList<int> /**offsets*/) +{ + messageVerbose("setLabelPosOffsets called"); + setLabels(m_d->controller->labels()); +} + +void VP1GeometrySystem::setLabels(int /*i*/){ + +} diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VisAttributes.cxx b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VisAttributes.cxx new file mode 100644 index 000000000..33daeb5ea --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VisAttributes.cxx @@ -0,0 +1,1108 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#include "VTI12GeometrySystems/VisAttributes.h" + +#include "VP1Base/VP1QtInventorUtils.h" +#include <Inventor/nodes/SoMaterial.h> +#include <iostream> +#include <QBuffer> + +/////////////////////////////////////// Base class /////////////////////////////////////// + +#include <map> +#include <iostream> + +class VisAttributes::Imp { +public: + // The material map is here: + std::map< std::string, SoMaterial *> _map; + + QMap<QString,QByteArray> currentState() const; + QMap<QString,QByteArray> initialState; +}; + +//____________________________________________________________________ +void VisAttributes::init() +{ + m_d->initialState = m_d->currentState(); +} + +//____________________________________________________________________ +QByteArray VisAttributes::getState(bool onlyChangedMaterials) +{ + //Figure out states to store + QMap<QString,QByteArray> storedstates, statesnow = m_d->currentState(); + if (onlyChangedMaterials) { + QMap<QString,QByteArray>::const_iterator it, itE(statesnow.constEnd()); + QMap<QString,QByteArray>::const_iterator itOrig, itOrigE(m_d->initialState.constEnd()); + for (it = statesnow.constBegin(); it!=itE; ++it) { + itOrig = m_d->initialState.constFind(it.key()); + if (itOrig==itOrigE||it.value()!=itOrig.value()) + storedstates.insert(it.key(),it.value()); + } + } else { + storedstates = statesnow; + } + + //Put map in bytearray and return: + QByteArray byteArray; + QBuffer buffer(&byteArray); + buffer.open(QIODevice::WriteOnly); + QDataStream out(&buffer); + out << qint32(0);//version + out << storedstates; + buffer.close(); + return byteArray; + +} + +//____________________________________________________________________ +void VisAttributes::applyState(QByteArray ba) +{ + //Get map out: + QMap<QString,QByteArray> storedstates; + QBuffer buffer(&ba); + buffer.open(QIODevice::ReadOnly); + QDataStream state(&buffer); + qint32 version; + state >> version; + if (version!=0) + return;//ignore silently + state >> storedstates; + buffer.close(); + + std::map< std::string, SoMaterial *>::iterator itMat,itMatE(m_d->_map.end()); + + //Apply states from map: + QMap<QString,QByteArray>::const_iterator it, itE(storedstates.constEnd()); + for (it = storedstates.constBegin(); it!=itE; ++it) { + itMat = m_d->_map.find(it.key().toStdString()); + if (itMat!=itMatE) { + QByteArray b(it.value()); + VP1QtInventorUtils::deserialiseSoMaterial(b,itMat->second); + } + } + +} + +//____________________________________________________________________ +QMap<QString,QByteArray> VisAttributes::Imp::currentState() const +{ + QMap<QString,QByteArray> outmap; + std::map< std::string, SoMaterial *>::const_iterator it(_map.begin()), itE(_map.end()); + for (;it!=itE;++it) + outmap.insert(QString(it->first.c_str()),VP1QtInventorUtils::serialiseSoMaterial(it->second)); + return outmap; +} + +//____________________________________________________________________ +VisAttributes::VisAttributes() : m_d(new Imp) { +} + +//____________________________________________________________________ +VisAttributes::~VisAttributes() { + + std::map<std::string, SoMaterial *>::iterator m,e=m_d->_map.end(); + for (m=m_d->_map.begin();m!=e;m++) + (*m).second->unref(); + + delete m_d; +} + +SoMaterial *VisAttributes::get (const std::string & name) const { + std::map <std::string, SoMaterial *>::const_iterator m = m_d->_map.find(name); + if (m!=m_d->_map.end()) { + return (*m).second; + } else { + return NULL; + } +} + +void VisAttributes::add(const std::string & name, SoMaterial *material) { + if (m_d->_map.find(name)!=m_d->_map.end()) { + std::cout<<"VisAttributes::add ERROR: Material " <<name<<" already added!"<<std::endl; + return; + } + material->ref(); + m_d->_map[name]=material; + if (material->transparency.getNum()!=1) + std::cout<<"VisAttributes::add Warning: Found #transparency values different from 1 in material "<<name<<std::endl; + if (material->transparency[0]!=0.0) + std::cout<<"VisAttributes::add Warning: Found transparency value different from 0 in material "<<name<<std::endl; +} + +void VisAttributes::overrideTransparencies(float transpfact) +{ + std::map< std::string, SoMaterial *>::iterator it, itE = m_d->_map.end(); + for (it=m_d->_map.begin();it!=itE;++it) + it->second->transparency.set1Value( 0, transpfact ); +} + +//////////////////////////////// Attributes for detectors //////////////////////////////// + +DetVisAttributes::DetVisAttributes() { + + { + SoMaterial *material = new SoMaterial; + material->ambientColor.setValue(0, .157811, .187004); + material->diffuseColor.setValue(0, .631244, .748016); + material->specularColor.setValue(.915152, .915152, .915152); + material->shininess.setValue(0.642424); + add("Veto",material); + } + + { + SoMaterial *material = new SoMaterial; + material->ambientColor.setValue(0, .157811, .187004); + material->diffuseColor.setValue(.40, .631244, .748016); + material->specularColor.setValue(.915152, .915152, .915152); + material->shininess.setValue(0.642424); + add("Trigger",material); + } + + { + SoMaterial *material = new SoMaterial; + material->ambientColor.setValue(0, .157811, .187004); + material->diffuseColor.setValue(1, .8, .7); + material->specularColor.setValue(.915152, .915152, .915152); + material->shininess.setValue(0.642424); + add("Preshower",material); + } + + { + SoMaterial *material = new SoMaterial; + material->ambientColor.setValue(0, .6, .6); + material->diffuseColor.setValue(1, .8, .7); + material->specularColor.setValue(.91515, .915152, .915152); + material->shininess.setValue(0.642424); + add("CavernInfra",material); + } + + { + SoMaterial *material = new SoMaterial; + material->ambientColor.setValue(0, .157811, .187004); + material->diffuseColor.setValue(1, 0, 0); + material->specularColor.setValue(.915152, .915152, .915152); + material->shininess.setValue(0.642424); + + add("Ecal",material); + } + // { + // SoMaterial *material = new SoMaterial; + // material->ambientColor.setValue(0.2, 0.2, 0.2); + // material->diffuseColor.setValue(0, 0.6667, 1.0); + // material->specularColor.setValue(0,0,0); + // material->shininess.setValue(0.642424); +// material->ambientColor.setValue(0, .157811, .187004); +// material->diffuseColor.setValue(1, 0, 0); +// material->specularColor.setValue(.915152, .915152, .915152); +// material->shininess.setValue(0.642424); + +// add("Muon",material); + +// { +// SoMaterial *material = new SoMaterial; +// material->ambientColor.setValue(0, .157811, .187004); +// material->diffuseColor.setValue(.98, .8, .21); +// material->specularColor.setValue(.915152, .915152, .915152); +// material->shininess.setValue(0.2); +// add("CSC",material); +// } + +// { +// SoMaterial *material = new SoMaterial; +// material->ambientColor.setValue(0, .157811, .187004); +// material->diffuseColor.setValue(0, .9, .5); +// material->specularColor.setValue(.915152, .915152, .915152); +// material->shininess.setValue(0.2); +// add("EndcapMdt",material); +// } + +// { +// SoMaterial *material = new SoMaterial; +// material->ambientColor.setValue(0,0,0); +// material->diffuseColor.setValue(0.41,0,0.26); +// material->specularColor.setValue(0,0,0); +// material->shininess.setValue(0.2); +// add("TGC",material); +// } + +// { +// SoMaterial *material = new SoMaterial; + +// material->ambientColor.setValue(0.2, 0.2, 0.2); +// material->diffuseColor.setValue(0, 0.6667, 1.0); +// material->specularColor.setValue(0,0,0); +// // material->ambientColor.setValue(0, .157811, .187004); +// // material->diffuseColor.setValue(1, .2, .7); +// // material->specularColor.setValue(.915152, .915152, .915152); +// material->shininess.setValue(0.2); + + +// add("BarrelInner",material); +// add("BarrelMiddle",material); +// add("BarrelOuter",material); +// } + +// { +// SoMaterial *material = new SoMaterial; +// material->ambientColor.setValue(0, .157811, .187004); +// material->diffuseColor.setValue(1, .5, .5); +// material->specularColor.setValue(.915152, .915152, .915152); +// material->shininess.setValue(0.2); +// add("BarrelToroid",material); +// add("EndcapToroid",material); +// } + +// { +// SoMaterial *material = new SoMaterial; +// material->ambientColor.setValue(0, .157811, .187004); +// material->diffuseColor.setValue(.5, .5, 1.0); +// material->specularColor.setValue(.915152, .915152, .915152); +// material->shininess.setValue(0.2); +// add("Feet",material); +// } +// } + + { + SoMaterial *material = new SoMaterial; + material->ambientColor.setValue(.37, .69, 1.00); + material->diffuseColor.setValue(.21, .64, 1.00); + material->specularColor.setValue(1, 1, 1); + material->shininess.setValue(1.0); + add("SCT",material); + } + + // { + // SoMaterial *material = new SoMaterial; + // add("LAr",material); + // add("LArBarrel",material); + // add("LArEndcapPos",material); + // add("LArEndcapNeg",material); + // } + + // { + // SoMaterial *material = new SoMaterial; + // add("TRT",material); + // } + + // { + // SoMaterial *material = new SoMaterial; + // add("InDetServMat",material); + // material->diffuseColor.setValue(0.4,0.31,0); + // material->shininess.setValue(1.0); + // } + + // { + // SoMaterial *material = new SoMaterial(); + // add("LucidSideA",material); + // add("LucidSideC",material); + // material->diffuseColor.setValue(0.6,0.11,0.3); + // material->shininess.setValue(1.0); + // } + + // { + // SoMaterial *material = new SoMaterial; + // material->ambientColor.setValue(0, .157811, .187004); + // material->diffuseColor.setValue(0., 0., 0.56862745); + // material->specularColor.setValue(.915152, .915152, .915152); + // material->shininess.setValue(0.2); + // add("Zdc",material); + // } + + + // { + // SoMaterial *material = new SoMaterial(); + // add("LcdXXX",material); + // add("LcdYYY",material); + // material->diffuseColor.setValue(0.6,0.11,0.3); + // material->shininess.setValue(1.0); + // } + + init(); +} + +//////////////////////////////// Attributes for materials //////////////////////////////// + +MatVisAttributes::MatVisAttributes() { + { + //NB: Must be here!! + SoMaterial *m = new SoMaterial; + add("DEFAULT",m); + } + + + + /* + * ETHER MATERIAL + * This transparent material was used to hide the "fakeVolume" added by AGDD, + * but there are other "standard" volumes, which use "Ether" material, for example in CSC chambers. + * So we do not use this workaround anymore... + { + // + // Ether: ---> it's a special "totally transparent" material, made to hide the "fakeVol" volume used in GeoModel to cope with the G4GeoAssembly objects in G4 + // more details: + // - https://its.cern.ch/jira/browse/ATLASVPONE-166 + // - https://svnweb.cern.ch/trac/atlasoff/browser/DetectorDescription/AGDD/AGDDControl/trunk/src/AGDD2GeoModelBuilder.cxx?rev=648789#L502 + // + SoMaterial *m = new SoMaterial; + m->ambientColor.setValue(0.2, 0.2, 0.2); + m->diffuseColor.setValue(0.58, 0.47, 0.81); + m->specularColor.setValue(0.56, 0.55, 0.56); + m->transparency.setValue(1.0); // --> TOTALLY TRANSPARENT!!! (set it to < 1.0 (e.g. 0.5) if you want to see the "fakeVol" cylinder in GeoModel) + add("Ether",m); + } + */ + + + { + // C02: + SoMaterial *m = new SoMaterial; + m->ambientColor.setValue(0.2, 0.2, 0.2); + m->diffuseColor.setValue(0.58, 0.47, 0.81); + m->specularColor.setValue(0.56, 0.55, 0.56); + add("CO2",m); + add("ArCO2",m); + } + + { + // Silicon + SoMaterial *m = new SoMaterial; + m->ambientColor.setValue(0.98, 0.82, 0.02); + m->diffuseColor.setValue(0.16, 0.26, 0.36); + m->specularColor.setValue(0.56, 0.55, 0.56); + m->shininess.setValue(0.13); + add("Silicon",m); + } + + { + // Kapton + SoMaterial *m = new SoMaterial; + m->ambientColor.setValue(0.2, 0.127931, 0.177402); + m->diffuseColor.setValue( 0.57665, 0.155139, 0.180815); + m->specularColor.setValue(0.441667, 0.441667, 0.441667); + m->shininess.setValue(0.67); + add("Kapton",m); + add("KaptonC",m); //used by LAr. + add("FCalCableHarness",m); //used by LAr. + } + + { + // Aluminium + SoMaterial *m = new SoMaterial; + m->ambientColor.setValue (0.70, 0.72, 0.72); + m->diffuseColor.setValue (0.56, 0.57, 0.57); + m->specularColor.setValue(0.71, 0.48, 0.46); + m->shininess.setValue(0.23); + add("Aluminium",m); + } + + { + // Iron + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.1, 0.1, 0.1); + m->specularColor.setValue(0.92, 0.92, 0.89); + m->shininess.setValue(0.60); + add("Iron",m); + } + + { + // Tungsten + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.14, 0.14, 0.14); + m->specularColor.setValue(0.84, 0.94, 1.00); + m->shininess.setValue(0.20); + add("Tungsten",m); + add("Wolfram",m); + add("FCal23Absorber",m); + } + { + // Lead + SoMaterial *m = new SoMaterial; + m->ambientColor.setValue (0.05, .05, 0.7); + m->diffuseColor.setValue (0.39, 0.36, 0.47); + m->specularColor.setValue(0.33, 0.33, 0.35); + m->shininess.setValue(0.30); + add("Lead",m); + add("Thinabs",m); + add("Thickabs",m); + } + + { + // G10 + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.308764, 0.314286, 0.142384); + m->specularColor.setValue(0.268276, 0.315312, 0.308455); + m->shininess.setValue(0.617021); + add("G10",m); + + } + + { + // Muon Scintillator + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.381944, 0.748016, 0); + m->specularColor.setValue(0.963636, 0.963636, 0.963636); + m->shininess.setValue(0.981818); + add("Scintillator",m); + } + + { + // Epoxy + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0, 0.748016, 0.176015); + m->specularColor.setValue(0.981818, 0.981818, 0.981818); + m->shininess.setValue(0.721212); + add("Epoxy",m); + } + + { + // Stainless steel + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.424238, 0.424238, 0.424238); + m->specularColor.setValue(0.168, 0.168, 0.168); + m->shininess.setValue(0.153696); + add("Stainless",m); + } + { + // Liquid Argon + SoMaterial *m = new SoMaterial; + m->ambientColor.setValue (0.05, .05, .06); + m->diffuseColor.setValue (0.39, .36, .48); + m->specularColor.setValue(0.33, .33, .35); + m->emissiveColor.setValue(0.45, .60, .60); + m->shininess.setValue(0.3); + add("LiquidArgon",m); + } + { + // Copper + SoMaterial *m = new SoMaterial; + m->ambientColor.setValue (0.0, 0.0, 0.0); + m->diffuseColor.setValue (1.0, .43, .36); + m->specularColor.setValue(1.0, 1.0, 1.0); + m->shininess.setValue(0.4); + add("Copper",m); + add("FCal1Absorber",m); + } + + { + // Cables + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (1.0, 0, 0); + add("Cables",m); + } + + { + // MBoards + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0, 1, 0); + add("MBoards",m); + } + + { + // Carbon + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.2, 0.2, 0.2); + m->ambientColor.setValue (0.07, 0.07, 0.07); + m->specularColor.setValue (0.8, 0.8, 0.8); + m->emissiveColor.setValue (0.028, 0.028, 0.028); + add("Carbon",m); + } + + { + //Titanium + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.62, 0.62, 0.62); + m->specularColor.setValue (0.294, 0.294, 0.294); + m->shininess.setValue(.20); + add("Titanium",m); + } + + { + //ECServices + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.7, 0.7, 0.7); + m->specularColor.setValue (0.5, 0.5, 0.5); + add("ECServices",m); + } + + { + //ECCables + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.1, 0.1, 0.1); + add("ECCables",m); + } + + { + //Services + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.765, 0.718, 0.541); + m->specularColor.setValue (0.5, 0.5, 0.5); + add("Services",m); + } + + { + //MatOmega + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.22, 0.22, 0.22); + add("MatOmega",m); + add("pix::Omega_BL",m); + add("pix::Omega_L1",m); + add("pix::Omega_L2",m); + } + + { + //MatConn + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0, 0, 0); + m->specularColor.setValue (0.8, 0.8, 0.8); + add("MatConn",m); + add("pix::Connector_BL",m); + add("pix::Connector_L1",m); + add("pix::Connector_L2",m); + } + + { + //MatPigtail + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.95, 0.58, 0.13); + m->specularColor.setValue (0.8, 0.75, 0.7); + m->shininess.setValue(.30); + add("MatPigtail",m); + } + + { + // MatAlTube + SoMaterial *m = new SoMaterial; + m->ambientColor.setValue (0.70, 0.72, 0.72); + m->diffuseColor.setValue (0.56, 0.57, 0.57); + m->specularColor.setValue(0.71, 0.48, 0.46); + m->shininess.setValue(0.23); + add("MatAlTube",m); + add("pix::AlTube_BL",m); + add("pix::AlTube_L1",m); + add("pix::AlTube_L2",m); + add("MatAlTubeFix",m); + } + + { + //MatT0 (Cable) + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.06, 0.06, 0.06); + m->specularColor.setValue (0.8, 0.8, 0.8); + add("MatT0",m); + add("Cable",m); + } + + { + //MatCap1 + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0, 0, 0.2); + add("MatCap1",m); + } + + { + //MatCap2 + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0, 0, 0.27); + add("MatCap2",m); + } + + { + //MatTMT + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.42, 0.42, 0.42); + add("MatTMT",m); + add("pix::AsTMT_BL",m); + add("pix::AsTMT_L1",m); + add("pix::AsTMT_L2",m); + } + + { + //MatGlue + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (1, 1, 0.78); + add("MatGlue",m); + add("pix::GlueOmegaStave_BL0",m); + add("pix::GlueOmegaStave_L10",m); + add("pix::GlueOmegaStave_L20",m); + } + + { + //Glue + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (1, 1, 0.75); + add("pix::GlueOmegaStave_BL1",m); + add("pix::GlueOmegaStave_L11",m); + add("pix::GlueOmegaStave_L21",m); + } + + { + //MatPP11 + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.08, 0.03, 0.03); + add("MatPP11",m); + } + + { + //MatPP12 + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.325, 0.292, 0.257); + add("MatPP12",m); + } + + { + //MatPP13 + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.42, 0.38, 0.30); + m->emissiveColor.setValue (0.028, 0.028, 0.028); + add("MatPP13",m); + } + + { + //MatPP14 + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.3, 0.3, 0.3); + m->emissiveColor.setValue (0.028, 0.028, 0.028); + add("MatPP14",m); + } + + { + //MatPP15 + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.2, 0.2, 0.23); + m->emissiveColor.setValue (0.028, 0.028, 0.028); + add("MatPP15",m); + } + + { + //MatPP16 + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.4, 0.4, 0.4); + m->emissiveColor.setValue (0.028, 0.028, 0.028); + add("MatPP16",m); + } + + { + //MatPP17 + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.17, 0.19, 0.16); + m->emissiveColor.setValue (0.028, 0.028, 0.028); + add("MatPP17",m); + } + + { + //Disk + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.5, 0.5, 0.5); + m->specularColor.setValue (0.5, 0.5, 0.5); + m->emissiveColor.setValue (0.028, 0.028, 0.028); + add("Disk",m); + } + + { + //Hybrid + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.15, 0.33, 0); + m->specularColor.setValue (0.39, 0.39, 0.39); + m->emissiveColor.setValue (0.028, 0.028, 0.028); + m->shininess.setValue(.60); + add("Hybrid",m); + } + + { + //Chip + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.8, 0.51, 0.105); + m->specularColor.setValue (0.39, 0.39, 0.39); + m->emissiveColor.setValue (0.028, 0.028, 0.028); + m->shininess.setValue(.60); + add("Chip",m); + } + + { + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.8, 0.51, 0.105); + m->specularColor.setValue (0.39, 0.39, 0.39); + m->emissiveColor.setValue (0.028, 0.028, 0.028); + m->shininess.setValue(.60); + add("pix::Chip",m); + } + + { + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.15, 0.33, 0); + m->specularColor.setValue (0.39, 0.39, 0.39); + m->emissiveColor.setValue (0.028, 0.028, 0.028); + m->shininess.setValue(.60); + add("pix::Hybrid",m); + } + + { + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.42, 0.42, 0.42); + add("pix:AsTMT_BL",m); + } + + { + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.95, 0.52, 0.12); + m->specularColor.setValue (0.8, 0.75, 0.7); + m->shininess.setValue(.30); + add("pix::PigtailCyl",m); + add("pix::PigtailFlat",m); + } + + { + // Rings and Service Support + SoMaterial *m = new SoMaterial; + m->ambientColor.setValue (0.50, 0.49, 0.12); + m->diffuseColor.setValue (0.665, 0.618, 0.441); + m->specularColor.setValue(0.51, 0.48, 0.16); + m->shininess.setValue(0.37); + //Rings + add("pix::AsRingCen_BL",m); + add("pix::AsRingInt_BL",m); + add("pix::AsRingOut_BL",m); + add("pix::AsRing_L1",m); + add("pix::AsRingOut_L1",m); + add("pix::AsRing_L2",m); + add("pix::AsRingOut_L2",m); + //ServiceSupport + add("pix::ServiceSupport_BL",m); + add("pix::ServiceSupport_L1",m); + add("pix::ServiceSupport_L2",m); + } + { + // Halfshell + SoMaterial *m = new SoMaterial; + m->ambientColor.setValue (0.21, 0.23, 0.23); + m->diffuseColor.setValue (0.1, 0.11, 0.11); + m->specularColor.setValue(0.31, 0.28, 0.06); + m->shininess.setValue(0.43); + add("pix::Halfshell_BL",m); + add("pix::Halfshell_L1",m); + add("pix::Halfshell_L2",m); + } + + { + SoMaterial *m = new SoMaterial; + m->ambientColor.setValue (0.40, 0.42, 0.42); + m->diffuseColor.setValue (0.36, 0.37, 0.37); + m->specularColor.setValue(0.51, 0.28, 0.26); + m->shininess.setValue(0.38); + add("Prepreg",m); + } + + { + SoMaterial *m = new SoMaterial; + m->ambientColor.setValue (0.10, 0.12, 0.12); + m->diffuseColor.setValue (0.09, 0.10, 0.17); + add("pix::CablesAxial_BL",m); + add("pix::CoolingAxial_BL",m); + add("pix::CabCoolAxial_L1",m); + add("pix::CabCoolAxial_L2",m); + add("pix::CabCoolRadial_L1",m); + add("pix::OuterCable_BL",m); + add("pix::OuterCabCool_L1",m); + add("pix::OuterCabCool_L2",m); + } + { + SoMaterial *m = new SoMaterial; + m->ambientColor.setValue (0.12, 0.14, 0.14); + m->diffuseColor.setValue (0.10, 0.11, 0.19); + add("pix::CablesRadial_BL",m); + add("pix::CoolingRadial_BL",m); + add("pix::CabCoolRadial_L2",m); + add("pix::OuterCooling_BL",m); + } + + { + SoMaterial *m = new SoMaterial; + m->ambientColor.setValue (0.20, 0.25, 0.25); + m->diffuseColor.setValue (0.22, 0.22, 0.22); + add("pix::Ulink_BL_A",m); + add("pix::AsUlink_BL_C",m); + add("pix::AsUlink_L1",m); + add("pix::AsUlink_L2",m); + } + + { + SoMaterial *m = new SoMaterial; + m->ambientColor.setValue (0.40, 0.42, 0.42); + m->diffuseColor.setValue (0.36, 0.37, 0.37); + m->specularColor.setValue(0.51, 0.28, 0.26); + m->shininess.setValue(0.38); + add("pix::SSR_BL_A",m); + add("pix::SSR_BL_C",m); + add("pix::SSR_L1_A",m); + add("pix::SSR_L1_C",m); + add("pix::SSR_L2",m); + } + + { + SoMaterial *m = new SoMaterial; + m->ambientColor.setValue (0.35, 0.37, 0.37); + m->diffuseColor.setValue (0.31, 0.32, 0.32); + m->specularColor.setValue(0.51, 0.28, 0.26); + m->shininess.setValue(0.38); + add("pix::InnerSkin_BL",m); + add("pix::InnerSkin_L1",m); + add("pix::InnerSkin_L2",m); + } + + { + SoMaterial *m = new SoMaterial; + m->ambientColor.setValue (0.55, 0.57, 0.57); + m->diffuseColor.setValue (0.51, 0.52, 0.52); + m->specularColor.setValue(0.51, 0.28, 0.26); + m->shininess.setValue(0.33); + add("pix::Fingers1",m); + add("pix::Fingers2",m); + add("pix::Fingers3",m); + add("pix::Fingers4",m); + } + + { + SoMaterial *m = new SoMaterial; + m->ambientColor.setValue (0.60, 0.62, 0.62); + m->diffuseColor.setValue (0.51, 0.52, 0.52); + m->specularColor.setValue(0.61, 0.38, 0.36); + m->shininess.setValue(0.28); + add("Peek",m); + } + + { + //Glass + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.8, 0.9, 1.0); + m->specularColor.setValue (0.39, 0.39, 0.39); + m->emissiveColor.setValue (0.028, 0.028, 0.028); + m->shininess.setValue(.60); + add("Glass",m); + } + + { + SoMaterial *material = new SoMaterial; + material->diffuseColor.setValue(0.9,0.7,0.5); + material->ambientColor.setValue(0.57,0.57,0.57); + material->specularColor.setValue(0.27,0.27,0.27); + material->shininess.setValue(.80); + add("AlNitride",material); + add("Dogleg",material); + add("BrlBaseBoard",material); + add("BrlHybrid",material); + add("BrlBracket",material); + add("PigTail",material); + } + + { + SoMaterial *material = new SoMaterial; + material->diffuseColor.setValue(0.40,0.60,0.40); + material->ambientColor.setValue(0.57,0.57,0.57); + material->specularColor.setValue(0.27,0.27,0.27); + material->shininess.setValue(.80); + add("PowerTape",material); + } + + { + SoMaterial *material = new SoMaterial; + material->diffuseColor.setValue(0.57,0.82,0.9); + material->ambientColor.setValue(0.57,0.57,0.57); + material->specularColor.setValue(0.27,0.27,0.27); + material->shininess.setValue(.80); + add("CoolingBlock",material); + add("sct::CoolBlockSecHi",material); + add("sct::CoolBlockSecLo",material); + add("sct::DiscCoolingInn",material); + add("sct::DiscCoolingOut",material); + } + + { /* Large structures in sct */ + SoMaterial *material = new SoMaterial; + //material->diffuseColor.setValue(0.7,0.6,0.5); + material->diffuseColor.setValue(0.8,0.7,0.6); + material->ambientColor.setValue(0.57,0.57,0.57); + material->specularColor.setValue(0.27,0.27,0.27); + material->shininess.setValue(.80); + add("sct::DiscCoolingMid",material); + add("sct::DiscPowerTapeMid",material); + add("sct::DiscPowerTapeInn",material); + add("sct::DiscPowerTapeOut",material); + add("sct::EMI",material); + add("sct::EMIJoint",material); + add("sct::Flange0",material); + add("sct::Flange1",material); + add("sct::Flange2",material); + add("sct::Flange3",material); + add("sct::FwdFrontSupport",material); + add("sct::FwdITE",material); + add("sct::FwdLMT",material); + add("sct::FwdLMTCooling",material); + add("sct::FwdOTE",material); + add("sct::FwdRearSupport",material); + add("sct::FwdRail",material); + add("sct::FwdSupport",material); + add("sct::FwdSpineMid",material); + add("sct::FwdSpineOut",material); + add("sct::FwdSpineInn",material); + add("sct::Harness",material); + add("sct::OptoHarnessO",material); + add("sct::OptoHarnessOM",material); + add("sct::OptoHarnessOMI",material); + add("sct::Spider",material); + add("sct::SupportCyl0",material); + add("sct::SupportCyl1",material); + add("sct::SupportCyl2",material); + add("sct::SupportCyl3",material); + add("sct::TSCylinder",material); + } + + { /* Details in sct (A) */ + SoMaterial *material = new SoMaterial; + material->diffuseColor.setValue(0.6,0.525,0.45); + material->ambientColor.setValue(0.57,0.57,0.57); + material->specularColor.setValue(0.27,0.27,0.27); + material->shininess.setValue(.80); + add("sct::FwdHybrid",material); + add("sct::CoolBlockMainHi",material); + add("sct::CoolBlockMainLo",material); + } + + { /* Details in sct (B) */ + SoMaterial *material = new SoMaterial; + material->diffuseColor.setValue(0.4,0.35,0.30); + material->ambientColor.setValue(0.57,0.57,0.57); + material->specularColor.setValue(0.27,0.27,0.27); + material->shininess.setValue(.80); + add("sct::CFiberInterLink",material); + add("sct::Clamp0",material); + add("sct::Clamp1",material); + add("sct::Clamp2",material); + add("sct::Clamp3",material); + add("sct::CoolingEnd0",material); + add("sct::CoolingEnd1",material); + add("sct::CoolingEnd2",material); + add("sct::CoolingEnd3",material); + add("sct::CoolingPipe",material); + add("sct::DiscFixation",material); + add("sct::DiscSupport0",material); + add("sct::DiscSupport1",material); + add("sct::ModuleConnector",material); + add("sct::DiscSupport2",material); + add("sct::DiscSupport3",material); + add("sct::DiscSupport4",material); + add("sct::DiscSupport5",material); + add("sct::DiscSupport6",material); + add("sct::DiscSupport7",material); + add("sct::DiscSupport8",material); + add("sct::FSIBL",material); + add("sct::FSIBH",material); + add("sct::FSIFL",material); + add("sct::FSIFH",material); + add("sct::FwdCoolingPipe",material); + add("sct::FwdFlangeFrontInn",material); + add("sct::FwdFlangeFrontOut",material); + add("sct::FwdFlangeRearInn",material); + add("sct::FwdFlangeRearOut",material); + add("sct::FwdNPipe",material); + add("sct::FwdShuntShield",material); + add("sct::PPConnector",material); + add("sct::PPCooling",material); + add("sct::PPF0c",material); + add("sct::PPF0e",material); + add("sct::PPF0o",material); + add("sct::TSBulkhead",material); + add("sct::TSEndPanel",material); + } + { + SoMaterial * m = new SoMaterial; + m->diffuseColor.setValue(SbColor(0.33333,0.33333,0.49804)); + m->shininess.setValue(0); + add("sct::FwdFibres",m); + } + + { + // NSW - sTGC + SoMaterial * m = new SoMaterial; + m->ambientColor.setValue(0.2, 0.2, 0.2); + m->diffuseColor.setValue(0, 0.6667, 1.0); + m->specularColor.setValue(0,0,0); + m->shininess.setValue(0.2); + add("Honeycomb",m); + } + { + // NSW - MicroMegas (MM) + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.765, 0.718, 0.541); + m->specularColor.setValue (0.5, 0.5, 0.5); + //m->ambientColor.setValue(0, .157811, .187004); + //m->diffuseColor.setValue(.98, .8, .21); + //m->specularColor.setValue(.915152, .915152, .915152); + m->shininess.setValue(0.2); + add("PCB",m); + } + { + // NSW - Shield Steel + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (0.424238, 0.424238, 0.424238); + m->specularColor.setValue(0.168, 0.168, 0.168); + m->shininess.setValue(0.153696); + add("ShieldSteel",m); + } + + + +////////////// + init(); +} + +//////////////////////////////// Attributes for volumes //////////////////////////////// + +VolVisAttributes::VolVisAttributes() { + + // WARM CYLINDER + { + SoMaterial *m = new SoMaterial; + m->ambientColor.setValue(1, .4, .4); + m->diffuseColor.setValue(1, .4, .4); + m->specularColor.setValue(0.441667, 0.441667, 0.441667); + m->shininess.setValue(0.67); + add( "LAr::Barrel::Cryostat::Cylinder::#4",m); + add( "LAr::Barrel::Cryostat::Cylinder::#5",m); + add( "LAr::Barrel::Cryostat::Cylinder::#6",m); + add( "LAr::Barrel::Cryostat::Cylinder::#7",m); + add( "LAr::Barrel::Cryostat::Cylinder::#8",m); + add( "LAr::Barrel::Cryostat::Cylinder::#9",m); + add( "LAr::Barrel::Cryostat::InnerWall",m); + add( "LAr::Barrel::Cryostat::InnerEndWall",m); + add( "LAr::Barrel::Cryostat::Leg",m); + } + + { + // WARM CYLINDER + SoMaterial *m = new SoMaterial; + m->ambientColor.setValue(.4, .4, 1); + m->diffuseColor.setValue(.4, .4, 1); + m->specularColor.setValue(0.441667, 0.441667, 0.441667); + m->shininess.setValue(0.67); + add( "LAr::Barrel::Cryostat::Cylinder::#0",m); + add( "LAr::Barrel::Cryostat::Cylinder::#1",m); + add( "LAr::Barrel::Cryostat::Cylinder::#2",m); + add( "LAr::Barrel::Cryostat::Cylinder::#3",m); + add( "LAr::Barrel::Cryostat::Ear",m); + add( "LAr::Barrel::Cryostat::OuterWall",m); + } + + { + SoMaterial *m = new SoMaterial; + m->diffuseColor.setValue (1, 1, 0.5); + m->ambientColor.setValue (0.54, 0.54, 0.27); + m->emissiveColor.setValue (0.133, 0.133, 0.067); + add("bcmModLog",m); + add("bcmWallLog",m); + } + init(); +} diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VolumeHandle.cxx b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VolumeHandle.cxx new file mode 100644 index 000000000..69b3d59b6 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VolumeHandle.cxx @@ -0,0 +1,730 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ + +#include "VTI12GeometrySystems/VolumeHandle.h" +#include "VTI12GeometrySystems/VolumeHandleSharedData.h" +#include "VTI12GeometrySystems/PhiSectorManager.h" +#include "VTI12GeometrySystems/VisAttributes.h" +#include "VTI12GeometrySystems/VP1GeoTreeView.h" +#include "VTI12GeometrySystems/GeoSysController.h" + +#include "VP1Base/VP1ExtraSepLayerHelper.h" +#include "VP1Base/VP1Msg.h" +// #include "VP1Base/VP1QtInventorUtils.h" +#include "VTI12Utils/VP1LinAlgUtils.h" +#include "VP1HEPVis/nodes/SoTransparency.h" +#include "VP1HEPVis/nodes/SoPolyhedron.h" +#include "VP1HEPVis/nodes/SoPcons.h" +#include "VP1HEPVis/VP1HEPVisUtils.h" + +#include "GeoModelKernel/GeoVolumeCursor.h" +#include "GeoModelKernel/GeoShapeShift.h" +#include "GeoModelKernel/GeoTube.h" +#include "GeoModelKernel/GeoTubs.h" + +#include <Inventor/nodes/SoSeparator.h> +#include <Inventor/nodes/SoTransform.h> +#include <Inventor/nodes/SoSwitch.h> +#include <Inventor/nodes/SoShape.h> +#include <Inventor/nodes/SoMaterial.h> +#include <Inventor/nodes/SoText2.h> +#include <Inventor/nodes/SoTranslation.h> + +#include <QHash> +#include <QBuffer> +#include <QByteArray> +#include <QPair> +#include <QSet> +#include <QMap> +#include <QDataStream> + +//____________________________________________________________________ +class VolumeHandle::Imp { +public: + Imp(VolumeHandleSharedData * the_cd, const GeoPVConstLink& the_pV, const SbMatrix& the_ac) + : commondata(the_cd), pV(the_pV),accumTrans(the_ac),attachsepHelper(0),attachlabelSepHelper(0),nodesep(0), material(0), label_sep(0), labels(0), isattached(false) {} + + VolumeHandleSharedData * commondata; + GeoPVConstLink pV; + const SbMatrix accumTrans;//FIXME: Use pointer - and free once children are created AND nodesep has been build. Or just construct on the fly! + + VP1ExtraSepLayerHelper * attachsepHelper; + VP1ExtraSepLayerHelper * attachlabelSepHelper; + + SoSeparator * nodesep; + SoMaterial * material; + SoSeparator* label_sep; + int labels; + QList<int> labelsPosOffsets; + + bool isattached; + void attach(VolumeHandle*vh); + void detach(); + + class VolState { + public: + int nZappedChildren() const { return m_zappedChildren.count(); } + int nExpandedChildren() const { return m_expandedChildren.count(); } + QMap<quint32,VolState> m_expandedChildren; + QSet<quint32> m_zappedChildren; + }; + + static VolState getChildStates(const VolumeHandle*theclass ); + static void applyChildStates(const VolState&,VolumeHandle*theclass); + static bool hasNonStandardShapeChildren(const SoGroup*g); + +}; + + +QDataStream & operator<< ( QDataStream & out, const VolumeHandle::Imp::VolState & vs ) { + out << vs.m_expandedChildren; + out << vs.m_zappedChildren; + return out; +} +QDataStream & operator>> ( QDataStream & in, VolumeHandle::Imp::VolState & vs ) { + in >> vs.m_expandedChildren; + in >> vs.m_zappedChildren; + return in; +} + +//____________________________________________________________________ +VolumeHandle::VolumeHandle(VolumeHandleSharedData * cd,VolumeHandle * parent, const GeoPVConstLink& pV, int childNumber, const MuonChamberState& mcs, const SbMatrix& accumTrans) + : m_d(new Imp(cd,pV,accumTrans)), m_childNumber(childNumber), m_nchildren(childNumber>=0?pV->getNChildVols():0), m_muonChamberState(mcs), m_parent(parent), + m_state(VP1GeoFlags::CONTRACTED) +{ + // std::cout<<"VolumeHandle ctor for "<<this<<" with parent="<<parent<<" and GeoPVConstLink @"<<&pV<<std::endl; + //commondata might be 0 in the special case where VolumeHandle is + //used as a base class for other reasons inside + //VolumeTreeModel. Just make sure we dont crash in that case. + if (cd) { + cd->ref(); + if (!haveParentsNotExpanded()) + m_d->attach(this); + } +} + +//____________________________________________________________________ +VolumeHandle::~VolumeHandle() +{ + if (m_d->commondata) { + setState(VP1GeoFlags::ZAPPED); + m_d->commondata->removeZappedVolumesFromGui(this); + if (childrenAreInitialised()) { + VolumeHandleListItr it, itE = m_children.end(); + for (it = m_children.begin(); it!=itE; ++it) + delete *it; + m_children.clear(); + } + if (m_d->material) + m_d->material->unref(); + if (m_d->nodesep) + m_d->nodesep->unref(); + if (m_d->label_sep) + m_d->label_sep->unref(); + m_d->commondata->unref(); + } + delete m_d; +} + +//____________________________________________________________________ +void VolumeHandle::initialiseChildren() +{ + if (childrenAreInitialised()) + return; + + assert(m_nchildren); + + //Loop over children: + m_children.reserve(m_nchildren); + unsigned ichild(0); + GeoVolumeCursor av(m_d->pV); + while (!av.atEnd()) { + + //Add transformation between parent and child to find the complete transformation of the child: + SbMatrix matr; + VP1LinAlgUtils::transformToMatrix(Amg::EigenTransformToCLHEP(av.getTransform()), matr); + matr.multRight(m_d->accumTrans); + m_children.push_back(new VolumeHandle(m_d->commondata,this,av.getVolume(),ichild++,(isInMuonChamber()?MUONCHAMBERCHILD:NONMUONCHAMBER),matr)); + //std::cout << "initialised: " << av.getName() << " - " << m_children.back()->getName().toStdString() << " - " << m_children.back() << std::endl; + av.next(); + } + + assert(ichild==m_nchildren&&m_children.size()==m_nchildren); + +} + +//____________________________________________________________________ +GeoPVConstLink VolumeHandle::geoPVConstLink() const +{ + return m_d->pV; +} + +//____________________________________________________________________ +QString VolumeHandle::getName() const +{ + return m_d->pV->getLogVol()->getName().c_str(); +} + +//____________________________________________________________________ +std::string VolumeHandle::getNameStdString() const +{ + return m_d->pV->getLogVol()->getName(); +} + +//____________________________________________________________________ +bool VolumeHandle::hasName(const std::string& n) const +{ + return m_d->pV->getLogVol()->getName() == n; +} + +//____________________________________________________________________ +SoMaterial * VolumeHandle::material() +{ + if (m_d->material) + return m_d->material; + + //First see if the "databases" of volumes/material know about this volume: + + SoMaterial * mat = m_d->commondata->volVisAttributes()->get(m_d->pV->getLogVol()->getName()); + if (mat) { + m_d->material = mat; + m_d->material->ref(); + return m_d->material; + } + mat = m_d->commondata->matVisAttributes()->get(m_d->pV->getLogVol()->getMaterial()->getName()); + if (mat) { + m_d->material = mat; + m_d->material->ref(); + return m_d->material; + } + + //Apparently not. We now have two ways of finding a material: We can + //take a system dependent fallback material, or we can take the + //material of the parent. + + mat = m_d->commondata->fallBackTopLevelMaterial(); + if (mat) { + m_d->material = mat; + m_d->material->ref(); + return m_d->material; + } + + if (m_parent) { + m_d->material = m_parent->material(); + assert(m_d->material); + m_d->material->ref(); + return m_d->material; + } + + m_d->material = m_d->commondata->matVisAttributes()->get("DEFAULT"); + assert(m_d->material); + m_d->material->ref(); + return m_d->material; +} + +//____________________________________________________________________ +SoSeparator * VolumeHandle::nodeSoSeparator() const +{ + return m_d->nodesep; +} + +//____________________________________________________________________ +void VolumeHandle::ensureBuildNodeSep() +{ + VP1Msg::messageDebug("VolumeHandle::ensureBuildNodeSep()"); + if (m_d->nodesep && m_d->label_sep) + return; + + m_d->label_sep = new SoSeparator; + m_d->label_sep->ref(); + + m_d->nodesep = new SoSeparator;//FIXME: rendercaching?? + // m_d->nodesep->renderCaching.setValue(SoSeparator::ON); + // m_d->nodesep->boundingBoxCaching.setValue(SoSeparator::ON); + m_d->nodesep->ref();//Since we are keeping it around irrespective of whether it is attached or not. + + //Transform: + m_d->nodesep->addChild(VP1LinAlgUtils::toSoTransform(m_d->accumTrans)); + + //VP1Msg::messageDebug("calling toShapeNode()..."); + SoNode * shape = m_d->commondata->toShapeNode(m_d->pV);//NB: Ignore contained transformation of GeoShapeShifts. + if (!shape) { + m_d->nodesep->removeAllChildren(); + std::cout << "Geomsys/VolumeHandle Error: Null shape!!!"<<std::endl; + return; + } + + //What phi sector do we belong in? + int iphi = m_d->commondata->phiSectorManager()->getVolumeType(m_d->accumTrans, shape); + + if (iphi >= -1 ) { + //VP1Msg::messageDebug("Cylinders [iphi >= -1]..."); + //Substitute shapes that are essentially cylinders with such. This + //can be done safely since this tube won't need + //phi-slicing and is done to gain render performance. + if ( m_d->pV->getLogVol()->getShape()->typeID()==GeoTube::getClassTypeID() ) + { + //VP1Msg::messageDebug("GeoTube..."); + const GeoTube * geotube = static_cast<const GeoTube*>(m_d->pV->getLogVol()->getShape()); + if (geotube->getRMin()==0.0) + shape = m_d->commondata->getSoCylinderOrientedLikeGeoTube(geotube->getRMax(),geotube->getZHalfLength()); + } + else if ( m_d->pV->getLogVol()->getShape()->typeID()==GeoTubs::getClassTypeID() ) + { + //VP1Msg::messageDebug("GeoTubs..."); + const GeoTubs * geotubs = static_cast<const GeoTubs*>(m_d->pV->getLogVol()->getShape()); + if (geotubs->getRMin()==0.0 && geotubs->getDPhi() >= 2*M_PI-1.0e-6) + shape = m_d->commondata->getSoCylinderOrientedLikeGeoTube(geotubs->getRMax(),geotubs->getZHalfLength()); + } + } + + //In the case of a GeoShapeShift we add its contained transformation here: + //Fixme: Remember to use this extra transformation for phisector cuts also! + if (m_d->pV->getLogVol()->getShape()->typeID()==GeoShapeShift::getClassTypeID()) + m_d->nodesep->addChild(VP1LinAlgUtils::toSoTransform(Amg::EigenTransformToCLHEP(dynamic_cast<const GeoShapeShift*>(m_d->pV->getLogVol()->getShape())->getX()))); + + //Add shape child(ren) and get the separator (helper) where we attach the nodesep when volume is visible: + if (iphi >= -1) { + m_d->nodesep->addChild(shape); + m_d->attachsepHelper = m_d->commondata->phiSectorManager()->getSepHelperForNode(m_d->commondata->subSystemFlag(), iphi); + m_d->attachlabelSepHelper = m_d->commondata->phiSectorManager()->getLabelSepHelperForNode(m_d->commondata->subSystemFlag(), iphi); + } else { + SoSwitch * sw = new SoSwitch; + sw->addChild(shape); + SoSeparator * sep_slicedvols = new SoSeparator; + sw->addChild(sep_slicedvols); + sw->whichChild = 0; + m_d->nodesep->addChild(sw); + m_d->attachsepHelper = m_d->commondata->phiSectorManager()->registerVolumeAroundZAxis( m_d->commondata->subSystemFlag(), sw, m_d->accumTrans ); + //FIXME - what about labels? + } + + //Register shape to volume handle connection (for user interactions): + //NB: "shape" might be shared between several volumes, so we use the separator above for the actual link! + //(this must be done last as it also sets outline defaults) + m_d->commondata->registerNodeSepForVolumeHandle(m_d->nodesep,this); + + //VP1Msg::messageDebug("VolumeHandle::ensureBuildNodeSep() - DONE."); +} + +//____________________________________________________________________ +void VolumeHandle::Imp::attach(VolumeHandle*vh) +{ + VP1Msg::messageDebug("VolumeHandle::Imp::attach() - name: " + vh->getName()); + if (!isattached) { + vh->ensureBuildNodeSep(); + if (attachsepHelper) { + VP1Msg::messageDebug("adding node..."); + attachsepHelper->addNodeUnderMaterial(nodesep,vh->material()); + } + if (attachlabelSepHelper) { + VP1Msg::messageDebug("adding label..."); + attachlabelSepHelper->addNode(label_sep); + } + isattached=true; + commondata->volumeBrowser()->scheduleUpdateOfAllNonHiddenIndices();//Browser need to change e.g. colour for this volume + } + //VP1Msg::messageDebug("attach: DONE."); +} + +//____________________________________________________________________ +void VolumeHandle::Imp::detach() +{ + if (isattached) { + if (attachsepHelper) + attachsepHelper->removeNodeUnderMaterial(nodesep,material); + if (attachlabelSepHelper) + attachlabelSepHelper->removeNode(label_sep); + isattached=false; + commondata->volumeBrowser()->scheduleUpdateOfAllNonHiddenIndices();//Browser need to change e.g. colour for this volume + } +} + +//____________________________________________________________________ +void VolumeHandle::setState( const VP1GeoFlags::VOLSTATE& state ) +{ + if (m_state==state) + return; + + //Mark muon chamber as dirty. + if (isInMuonChamber()) { + VolumeHandle *tp = topLevelParent(); + if (tp->m_muonChamberState == MUONCHAMBER) + tp->m_muonChamberState = MUONCHAMBER_DIRTY; + } + + //Update state flag and presence in GUI lists: + VP1GeoFlags::VOLSTATE oldstate = m_state; + m_state = state; + if (oldstate==VP1GeoFlags::ZAPPED) + m_d->commondata->removeZappedVolumesFromGui(this); + else if (state==VP1GeoFlags::ZAPPED) + m_d->commondata->addZappedVolumeToGui(this); + + //Only thing left is visibility updates (i.e. attachment to 3D scenegraph). + + if (haveParentsNotExpanded()) { + //No visibility updates necessary + assert(!m_d->isattached); + return; + } + + //We might need visibility updates. Which ones depend on the + //particular change of state: + + if (state==VP1GeoFlags::CONTRACTED) { + // VP1GeoFlags::EXPANDED/VP1GeoFlags::ZAPPED -> VP1GeoFlags::CONTRACTED: Show this and hide all children. + m_d->attach(this); + detachAllContractedChildren(); + } else if (state==VP1GeoFlags::EXPANDED) { + // VP1GeoFlags::CONTRACTED -> VP1GeoFlags::EXPANDED: Hide this. Allow children to be shown. + // VP1GeoFlags::ZAPPED -> VP1GeoFlags::EXPANDED: Allow children to be shown. + if (oldstate==VP1GeoFlags::CONTRACTED) + m_d->detach(); + attachAllContractedChildren(); + } else { + assert(state==VP1GeoFlags::ZAPPED); + // VP1GeoFlags::CONTRACTED -> VP1GeoFlags::ZAPPED: Hide this. + // VP1GeoFlags::EXPANDED -> VP1GeoFlags::ZAPPED: Hide all children. + if (oldstate==VP1GeoFlags::CONTRACTED) + m_d->detach(); + else + detachAllContractedChildren(); + } +} + +//____________________________________________________________________ +void VolumeHandle::contractDaughtersRecursively() +{ + if (!childrenAreInitialised()) + return;//Fine to abort since children starts in contracted state + //if initialised at a later time. + VolumeHandleListItr childItrE = m_children.end(); + for (VolumeHandleListItr childItr = m_children.begin(); childItr!=childItrE; ++childItr) { + (*childItr)->setState(VP1GeoFlags::CONTRACTED); + (*childItr)->contractDaughtersRecursively(); + } +} + +//____________________________________________________________________ +bool VolumeHandle::haveParentsNotExpanded() const +{ + return m_parent ? ( m_parent->state()==VP1GeoFlags::EXPANDED ? m_parent->haveParentsNotExpanded() : true ) : false; +} + +//____________________________________________________________________ +void VolumeHandle::attachAllContractedChildren() { + + if (!m_nchildren) + return; + if (!childrenAreInitialised()) + initialiseChildren(); + + VolumeHandleListItr childItrE = m_children.end(); + for (VolumeHandleListItr childItr = m_children.begin(); childItr!=childItrE; ++childItr) { + if ((*childItr)->state()==VP1GeoFlags::CONTRACTED) + (*childItr)->m_d->attach(*childItr); + else if ((*childItr)->state()==VP1GeoFlags::EXPANDED) + (*childItr)->attachAllContractedChildren(); + } +} + +//____________________________________________________________________ +void VolumeHandle::detachAllContractedChildren() { + if (!m_nchildren) + return; + if (!childrenAreInitialised()) + return;//Since children not initialised won't have been attached! + + VolumeHandleListItr childItrE = m_children.end(); + for (VolumeHandleListItr childItr = m_children.begin(); childItr!=childItrE; ++childItr) { + if ((*childItr)->state()==VP1GeoFlags::CONTRACTED) + (*childItr)->m_d->detach(); + else if ((*childItr)->state()==VP1GeoFlags::EXPANDED) + (*childItr)->detachAllContractedChildren(); + } +} + +//____________________________________________________________________ +int VolumeHandle::copyNumber() const +{ + GeoPVConstLink parent_pV; + if (m_parent) { + parent_pV = m_parent->geoPVConstLink(); + } else { + parent_pV = m_d->commondata->geoPVConstLinkOfTreeTopsMother(); + if (parent_pV==m_d->pV) { + //To follow historical behaviour, we always assume that + //tree-tops (in the GeoModel sense) have a copy number of 0. + return 0; + } + } + GeoVolumeCursor av(parent_pV); + int i(0);//We need to check the childNumber since volumes in a replica have same volume link + while (!av.atEnd()) { + if (m_childNumber==i&&m_d->pV==av.getVolume()) { + Query<int> Qint = av.getId(); + return Qint.isValid() ? int(Qint) : -1;//-1 for "Invalid" + } + av.next(); + ++i; + } + return -2;//error +} + +//____________________________________________________________________ +quint32 VolumeHandle::hashID() const +{ + // return qHash( QPair<QString,quint32>(getName(),copyNumber()));//NOT UNIQUE!! + return qHash( QPair<QString,quint32>(getName(),childNumber())); +} + +//____________________________________________________________________ +const SbMatrix& VolumeHandle::getGlobalTransformToVolume() const { + return m_d->accumTrans; +} + +//____________________________________________________________________ +SbMatrix VolumeHandle::getLocalTransformToVolume() const { + if (!m_parent) + return m_d->accumTrans; + return m_parent->getGlobalTransformToVolume().inverse().multRight(m_d->accumTrans); +} + +//____________________________________________________________________ +bool VolumeHandle::isAttached() const +{ + return m_d->isattached; +} + +//____________________________________________________________________ +const GeoMaterial * VolumeHandle::geoMaterial() const { + return geoPVConstLink()->getLogVol()->getMaterial(); +} + +//____________________________________________________________________ +bool VolumeHandle::isEther() const +{ + return !isMuonChamber() && QString(geoMaterial()->getName().c_str()).endsWith("Ether"); +} + +//____________________________________________________________________ +void VolumeHandle::expandMothersRecursivelyToNonEther() { + //std::cout<<"VolumeHandle::expandMothersRecursivelyToNonEther() for "<<this->getNameStdString() << " [" <<this<< "]" << " - n. children: " << nChildren() << std::endl; + + if (!nChildren()||!isEther()) { + //VP1Msg::messageDebug("====> no children or not 'Ether' material. Skipping & returning."); + return; + } + + setState(VP1GeoFlags::ZAPPED); + initialiseChildren(); + VolumeHandleListItr childItrE = m_children.end(); + for (VolumeHandleListItr childItr = m_children.begin(); childItr!=childItrE; ++childItr) { + //std::cout << "\t-->expanding child " << (*childItr)->getNameStdString() << " - " << (*childItr) << std::endl ; + (*childItr)->expandMothersRecursivelyToNonEther(); + } + setState(VP1GeoFlags::EXPANDED); + //std::cout<<"VolumeHandle::expandMothersRecursivelyToNonEther() for "<<this->getNameStdString() << " [" <<this<< "]" <<" DONE.\n\n"<<std::endl; + +} + +//____________________________________________________________________ +QByteArray VolumeHandle::getPersistifiableState() const +{ + QByteArray ba; + QBuffer buffer(&ba); + buffer.open(QIODevice::WriteOnly); + + QDataStream out(&buffer); + out << (qint32)0;//version + out << qint32(m_state==VP1GeoFlags::CONTRACTED? 0 : (m_state==VP1GeoFlags::EXPANDED?1:2)); + out << Imp::getChildStates(this); + + buffer.close(); + return ba; + +} + +//____________________________________________________________________ +void VolumeHandle::applyPersistifiableState( QByteArray ba ) +{ + QBuffer buffer(&ba); + buffer.open(QIODevice::ReadOnly); + QDataStream state(&buffer); + qint32 version; + state >> version; + if (version!=0) + return;//We ignore wrong versions silently here. + qint32 st; + state >> st; + VP1GeoFlags::VOLSTATE newstate(VP1GeoFlags::CONTRACTED); + if (st == 2) + newstate = VP1GeoFlags::ZAPPED; + else if (st == 1) + newstate = VP1GeoFlags::EXPANDED; + + Imp::VolState vs; + state >> vs; + buffer.close(); + + if (newstate==VP1GeoFlags::EXPANDED) { + setState(VP1GeoFlags::ZAPPED); + m_d->applyChildStates(vs,this); + } + setState(newstate); +} + +//____________________________________________________________________ +VP1GeoFlags::SubSystemFlag VolumeHandle::subsystem() const +{ + return m_d->commondata->subSystemFlag(); +} + +//____________________________________________________________________ +VolumeHandle::Imp::VolState VolumeHandle::Imp::getChildStates(const VolumeHandle* theclass) +{ + VolState vs; + if (theclass->m_state!=VP1GeoFlags::EXPANDED||theclass->m_nchildren==0||!theclass->childrenAreInitialised()) + return vs; + + VolumeHandleListConstItr it, itE = theclass->m_children.end(); + for (it = theclass->m_children.begin(); it!=itE; ++it) { + if ((*it)->state()==VP1GeoFlags::ZAPPED) + vs.m_zappedChildren.insert((*it)->hashID()); + else if ((*it)->state()==VP1GeoFlags::EXPANDED) + vs.m_expandedChildren.insert((*it)->hashID(),(*it)->m_d->getChildStates(*it)); + } + return vs; +} + +//____________________________________________________________________ +void VolumeHandle::Imp::applyChildStates(const VolState& vs,VolumeHandle*theclass) +{ + bool hasExpandedChildren = !vs.m_expandedChildren.isEmpty(); + bool hasZappedChildren = !vs.m_zappedChildren.isEmpty(); + if (!hasExpandedChildren&&!hasZappedChildren) + return; + + QMap<quint32,VolState>::const_iterator expItr, expItrEnd = vs.m_expandedChildren.end(); + QSet<quint32>::const_iterator zapItr, zapItrEnd = vs.m_zappedChildren.end(); + + theclass->initialiseChildren(); + VolumeHandleListConstItr it, itE = theclass->m_children.end(); + for (it = theclass->m_children.begin(); it!=itE; ++it) { + quint32 id = (*it)->hashID(); + zapItr = vs.m_zappedChildren.find(id); + if (zapItr!=zapItrEnd) { + (*it)->setState(VP1GeoFlags::ZAPPED); + continue; + } + expItr = vs.m_expandedChildren.find(id); + if (expItr!=expItrEnd) { + (*it)->setState(VP1GeoFlags::ZAPPED); + applyChildStates(expItr.value(),*it); + (*it)->setState(VP1GeoFlags::EXPANDED); + } + } +} + +//____________________________________________________________________ +bool VolumeHandle::Imp::hasNonStandardShapeChildren(const SoGroup*g) +{ + const int n(g->getNumChildren()); + for (int i=0; i < n; ++i) { + const SoNode*c = g->getChild(i); + if (c->getTypeId().isDerivedFrom(SoShape::getClassTypeId())) { + if (c->getTypeId().isDerivedFrom(SoPcons::getClassTypeId()) + ||c->getTypeId().isDerivedFrom(SoPolyhedron::getClassTypeId()) + ||c->getTypeId().isDerivedFrom(SoTransparency::getClassTypeId())) + return true; + } else if (c->getTypeId().isDerivedFrom(SoGroup::getClassTypeId())) { + if (hasNonStandardShapeChildren(static_cast<const SoGroup*>(c))) + return true; + } + } + return false; +} + +//____________________________________________________________________ +bool VolumeHandle::isInitialisedAndHasNonStandardShape() const +{ + VP1HEPVisUtils::initAllCustomClasses(); + return m_d->nodesep ? Imp::hasNonStandardShapeChildren(m_d->nodesep) : false; +} + +//____________________________________________________________________ +bool VolumeHandle::isPositiveZ() const +{ + SbVec3f dir; + m_d->accumTrans.multDirMatrix(SbVec3f(0,0,1),dir); + float x,y,z; + dir.getValue(x,y,z); + return z>0; +} + +void VolumeHandle::updateLabels() { + int labels = m_d->commondata->controller()->labels(); + QList<int> offsets = m_d->commondata->controller()->labelPosOffset(); + + m_d->attachlabelSepHelper->largeChangesBegin(); + + if ( m_d->labels != labels || m_d->labelsPosOffsets != offsets){ + m_d->labels = labels; + m_d->labelsPosOffsets = offsets; + m_d->label_sep->removeAllChildren (); + + SoText2 *labelText = new SoText2; + labelText->ref(); + QStringList text; + if (labels&0x1){ + QString name = getDescriptiveName(); + text << name; + } + + // only one label selected - must be better way to do this! + bool singleLabel = (labels&0x2 && !(labels&0x4) && !(labels&0x8)) + || (labels&0x4 && !(labels&0x2) && !(labels&0x8)) + || (labels&0x8 && !(labels&0x2) && !(labels&0x4)); + if (isInMuonChamber() && labels&0xE){ + for (unsigned int i=0; i<3 ;++i){ + // Check to see which label we use. + unsigned int mask=1<<(i+1); + if (!(labels&mask)) continue; // bits 1,2,3 are used for labels + + QString output; + if ( singleLabel ) { + output+="t0="; + } else { + if (i==0) output+="Moore t0="; + if (i==1) output+="Mboy t0="; + if (i==2) output+="<unknown>="; + } + output += muonChamberT0(i); + text << output; + } + } + + unsigned int row=0; + foreach(QString str, text){ + QByteArray array = str.toLatin1(); + labelText->string.set1Value(row++,array.data()); + } + + SoTransform *labelTranslate = VP1LinAlgUtils::toSoTransform(m_d->accumTrans); + assert(labelTranslate!=0); + float offScale=10.0; + float labx,laby,labz; + labelTranslate->translation.getValue().getValue(labx,laby,labz); +// std::cout <<getNameStdString()<<" offsets (x,y,z)=("<<offsets[0]<<","<<offsets[1]<<","<<offsets[2]<<")"<<std::endl; + + labelTranslate->translation.setValue(labx+(offsets[0]*offScale),laby+(offsets[1]*offScale),labz+(offsets[2]*offScale)); + + m_d->label_sep->addChild(labelTranslate); + m_d->label_sep->addChild(labelText); + } + + m_d->attachlabelSepHelper->largeChangesEnd(); +} + diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VolumeHandleSharedData.cxx b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VolumeHandleSharedData.cxx new file mode 100644 index 000000000..ec1b98fe2 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VolumeHandleSharedData.cxx @@ -0,0 +1,228 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "VTI12GeometrySystems/VolumeHandleSharedData.h" +#include "VTI12GeometrySystems/ZappedVolumeListModel.h" +#include "VTI12GeometrySystems/GeoSysController.h" +#include "VTI12Utils/SoVisualizeAction.h" + +#include "GeoModelKernel/GeoVPhysVol.h" +#include "GeoModelKernel/GeoShapeShift.h" + +#include "VP1HEPVis/nodes/SoGenericBox.h" +#include "VP1HEPVis/nodes/SoTubs.h" +#include "VP1HEPVis/nodes/SoPcons.h" +#include "VP1HEPVis/nodes/SoTessellated.h" + +#include <Inventor/nodes/SoCylinder.h> +#include <Inventor/nodes/SoRotationXYZ.h> +#include <Inventor/nodes/SoSeparator.h> + +#include <map> + +//____________________________________________________________________ +class VolumeHandleSharedData::Imp { +public: + GeoSysController * controller; + std::map<const GeoLogVol *, SoShape *> logvol2shape; + std::map<double, SoNode *> id2shape; + SoVisualizeAction visaction; + std::map<SoSeparator*,VolumeHandle*>* sonodesep2volhandle; + GeoPVConstLink motherpV; + PhiSectorManager* phisectormanager; + VP1GeoFlags::SubSystemFlag subsysflag; + SoMaterial * topMaterial; + MatVisAttributes *matVisAttributes; + VolVisAttributes *volVisAttributes; + ZappedVolumeListModel * zappedvolumelistmodel; + int ref; +}; + +//____________________________________________________________________ +VolumeHandleSharedData::VolumeHandleSharedData(GeoSysController * controller, + VP1GeoFlags::SubSystemFlag flag,std::map<SoSeparator*,VolumeHandle*>* sonodesep2volhandle, + const GeoPVConstLink& motherpV,PhiSectorManager*psm, SoMaterial * topMaterial, + MatVisAttributes *matVisAttributes,VolVisAttributes *volVisAttributes, + ZappedVolumeListModel * zappedvolumelistmodel, VP1GeoTreeView * volbrowser, SoSeparator* textSep ) + : m_d(new Imp), m_volumebrowser(volbrowser), m_textSep(textSep) +{ + m_d->ref = 0; + m_d->controller=controller; + m_d->sonodesep2volhandle = sonodesep2volhandle; + m_d->motherpV = motherpV; + m_d->phisectormanager = psm; + m_d->subsysflag = flag; + m_d->topMaterial = topMaterial; + m_d->matVisAttributes = matVisAttributes; + m_d->volVisAttributes = volVisAttributes; + m_d->zappedvolumelistmodel = zappedvolumelistmodel; +} + +//____________________________________________________________________ +VolumeHandleSharedData::~VolumeHandleSharedData() +{ + std::map<const GeoLogVol *, SoShape *>::iterator it, itE = m_d->logvol2shape.end(); + for (it=m_d->logvol2shape.begin();it!=itE;++it) { + if (it->second) + it->second->unref(); + } + std::map<double, SoNode *>::iterator it2, it2E = m_d->id2shape.end(); + for (it2=m_d->id2shape.begin();it2!=it2E;++it2) { + if (it2->second) + it2->second->unref(); + } + delete m_d; m_d=0; +} + +//____________________________________________________________________ +void VolumeHandleSharedData::ref() +{ + ++(m_d->ref); +} + +//____________________________________________________________________ +void VolumeHandleSharedData::unref() +{ + --(m_d->ref); + if (!m_d->ref) + delete this; +} + +//____________________________________________________________________ +MatVisAttributes * VolumeHandleSharedData::matVisAttributes() const +{ + return m_d->matVisAttributes; +} + +//____________________________________________________________________ +VolVisAttributes * VolumeHandleSharedData::volVisAttributes() const +{ + return m_d->volVisAttributes; +} + +//____________________________________________________________________ +SoMaterial * VolumeHandleSharedData::fallBackTopLevelMaterial() const +{ + return m_d->topMaterial; +} + +//____________________________________________________________________ +VP1GeoFlags::SubSystemFlag VolumeHandleSharedData::subSystemFlag() const +{ + return m_d->subsysflag; +} + +//____________________________________________________________________ +PhiSectorManager* VolumeHandleSharedData::phiSectorManager() const +{ + return m_d->phisectormanager; +} + +//____________________________________________________________________ +GeoSysController* VolumeHandleSharedData::controller() const +{ + return m_d->controller; +} + +//_____________________________________________________________________________________ +void VolumeHandleSharedData::registerNodeSepForVolumeHandle(SoSeparator*n,VolumeHandle*vh) +{ + assert(m_d->sonodesep2volhandle->find(n)==m_d->sonodesep2volhandle->end()); + (*(m_d->sonodesep2volhandle))[n]=vh; + setShowVolumeOutlines(n,m_d->controller->showVolumeOutLines()); +} + +//_____________________________________________________________________________________ +void VolumeHandleSharedData::setShowVolumeOutlines(SoGroup*nodegroup,bool showvol) +{ + for (int i = 0; i<nodegroup->getNumChildren();++i) { + SoNode * n = nodegroup->getChild(i); + if (n->getTypeId().isDerivedFrom(SoGenericBox::getClassTypeId())) { + if (static_cast<SoGenericBox*>(n)->drawEdgeLines.getValue()!=showvol) + static_cast<SoGenericBox*>(n)->drawEdgeLines.setValue(showvol); + } else if (n->getTypeId().isDerivedFrom(SoTubs::getClassTypeId())) { + if (static_cast<SoTubs*>(n)->drawEdgeLines.getValue()!=showvol){ + static_cast<SoTubs*>(n)->drawEdgeLines.setValue(showvol); + } + } else if (n->getTypeId().isDerivedFrom(SoPcons::getClassTypeId())) { + if (static_cast<SoPcons*>(n)->drawEdgeLines.getValue()!=showvol){ + static_cast<SoPcons*>(n)->drawEdgeLines.setValue(showvol); + } + } else if (n->getTypeId().isDerivedFrom(SoTessellated::getClassTypeId())) { + if (static_cast<SoTessellated*>(n)->drawEdgeLines.getValue()!=showvol){ + static_cast<SoTessellated*>(n)->drawEdgeLines.setValue(showvol); + } + } else if (n->getTypeId().isDerivedFrom(SoGroup::getClassTypeId())) { + setShowVolumeOutlines(static_cast<SoGroup*>(n),showvol); + } + } +} + +//_____________________________________________________________________________________ +SoNode * VolumeHandleSharedData::toShapeNode(const GeoPVConstLink& pV) +{ + const GeoLogVol * logVolume = pV->getLogVol(); + + // if shape already stored for this volume, return that + SoShape * shape (0); + std::map<const GeoLogVol *, SoShape *>::iterator itShape = m_d->logvol2shape.find(logVolume); + if (itShape!=m_d->logvol2shape.end()) { + return itShape->second; + } + + const GeoShape * geoshape = logVolume->getShape(); + + m_d->visaction.reset(); + if (geoshape->typeID()==GeoShapeShift::getClassTypeID()) { + dynamic_cast<const GeoShapeShift*>(geoshape)->getOp()->exec(&(m_d->visaction)); + //NB: the transformation part of the GeoShapeShift will be applied elsewhere + } else { + geoshape->exec(&(m_d->visaction)); + } + shape = m_d->visaction.getShape(); + if (shape) + shape->ref(); + m_d->logvol2shape[logVolume] = shape; + return shape; +} + +//____________________________________________________________________ +SoNode * VolumeHandleSharedData::getSoCylinderOrientedLikeGeoTube(const double& radius, const double& halfLength) +{ + double id = radius - 9999.0*halfLength; + std::map<double, SoNode *>::iterator it = m_d->id2shape.find(id); + if (it!=m_d->id2shape.end()) + return it->second; + + SoGroup * group = new SoGroup; + SoRotationXYZ * rot = new SoRotationXYZ; + rot->axis.setValue(SoRotationXYZ::X); + rot->angle.setValue(M_PI*0.5f); + group->addChild(rot); + SoCylinder * cyl = new SoCylinder; + cyl->radius.setValue(radius); + cyl->height.setValue(2.0*halfLength); + group->addChild(cyl); + group->ref(); + m_d->id2shape[id]=group; + return group; +} + +//____________________________________________________________________ +GeoPVConstLink VolumeHandleSharedData::geoPVConstLinkOfTreeTopsMother() const +{ + return m_d->motherpV; +} + +//____________________________________________________________________ +void VolumeHandleSharedData::addZappedVolumeToGui( VolumeHandle * handle ) +{ + m_d->zappedvolumelistmodel->addToZappedVolumes(handle); +} + +//____________________________________________________________________ +void VolumeHandleSharedData::removeZappedVolumesFromGui( VolumeHandle * handle ) +{ + m_d->zappedvolumelistmodel->removeFromZappedVolumes(handle); +} diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VolumeTreeModel.cxx b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VolumeTreeModel.cxx new file mode 100644 index 000000000..c4613e0b4 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/VolumeTreeModel.cxx @@ -0,0 +1,536 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#include "VTI12GeometrySystems/VolumeTreeModel.h" +#include <cassert> +#include <iostream> +#include <QColor> + +////////////////////////////////////////////////////////////////////// +//NB: Since the QModelIndices uses void pointers, the VolumeHandle, +//SectionInfo and SubSystem classes must derive from the same +//base class before we know which class we can cast to. +// +//In order to not add any unnecessary overhead to VolumeHandle (which +//has a copy of the entire GeoModel tree), we let SectionInfo and +//SubSystem both inherit from VolumeHandle, and we use the +//m_childNumber field (which is always non-negative for actual +//VolumeHandles) of VolumeHandle to indicate the type: +// +// -2: SectionInfo +// -1: SubSystem +// 0+: Regular VolumeHandle +// +// This is taken care of by the constructors of the two derived +// classes, and four helper methods below makes the conversions a +// breeze (even though its a bit hackish behind the scenes) +////////////////////////////////////////////////////////////////////////////// + +//____________________________________________________________________ +class VolumeTreeModel::Imp { +public: + //Static definitions of sections and which subsystems goes in which sections: + enum SECTION { UNKNOWN, SCINT, TRACKER, CALO, MISC }; + static std::map<SECTION,QString> section2string; + static std::map<VP1GeoFlags::SubSystemFlag,SECTION> subsysflag2section; + static std::map<VP1GeoFlags::SubSystemFlag,QString> subsysflag2string; + static void defineSubSystem(VP1GeoFlags::SubSystemFlag,QString,SECTION); + + //Class for the dynamic information of a given subsystem: + class SectionInfo; + class SubSystem: public VolumeHandle { + public: + SubSystem(SectionInfo *si,VP1GeoFlags::SubSystemFlag sf) + : VolumeHandle(0,0, GeoPVConstLink(), -1), + section(si), subsysflag(sf) {} + ~SubSystem() { + VolumeHandle::VolumeHandleListItr volItr, volItrE(volhandlelist.end()); + for (volItr = volhandlelist.begin();volItr!=volItrE;++volItr) + delete (*volItr);//This is where volume handles are deleted + } + // + SectionInfo * section; + VP1GeoFlags::SubSystemFlag subsysflag; + VolumeHandle::VolumeHandleList volhandlelist; + QString name; + }; + //lists/maps for the added subsystems: + std::map<VP1GeoFlags::SubSystemFlag,SubSystem*> flag2subsystems; + //Map to quickly find subsystem from volumehandle. Only contains volumehandles from enabled subsystems: + std::map<VolumeHandle*,SubSystem*> volhandle2subsystem; + + //Class for the dynamic information about sections and their daughter subsystems: + class SectionInfo: public VolumeHandle { + public: + SectionInfo(SECTION sf): VolumeHandle(0,0, GeoPVConstLink(), -2),sectionflag(sf) {} + // + SECTION sectionflag; + QList<SubSystem*> enabledSubSystems; + QList<SubSystem*> disabledSubSystems; + QString name; + }; + //Lists of these sections: + QList<SectionInfo*> allSections; + QList<SectionInfo*> activeSections; + + //Convenience methods for dealing with the void pointers from the QModelIndices: + static VolumeHandle* handlePointer(const QModelIndex& idx) { return static_cast<VolumeHandle*>(idx.internalPointer()); } + static bool isSectionInfoPointer(VolumeHandle* handle) { return handle->childNumber()==-2; } + static bool isSubSystemPointer(VolumeHandle* handle) { return handle->childNumber()==-1; } + static bool isRegularVolumeHandle(VolumeHandle* handle) { return handle->childNumber()>=0; } + static SectionInfo * sectionInfoPointer (VolumeHandle* handle) { return handle->childNumber()==-2 ? static_cast<SectionInfo*>(handle) : 0; } + static SubSystem * subSystemPointer (VolumeHandle* handle) { return handle->childNumber()==-1 ? static_cast<SubSystem*>(handle) : 0; } + /////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + +}; + +//Static variables: +std::map<VolumeTreeModel::Imp::SECTION,QString> VolumeTreeModel::Imp::section2string; +std::map<VP1GeoFlags::SubSystemFlag,VolumeTreeModel::Imp::SECTION> VolumeTreeModel::Imp::subsysflag2section; +std::map<VP1GeoFlags::SubSystemFlag,QString> VolumeTreeModel::Imp::subsysflag2string; + +//____________________________________________________________________ +void VolumeTreeModel::Imp::defineSubSystem(VP1GeoFlags::SubSystemFlag subsysflag, QString subsysname, SECTION section) +{ + Imp::subsysflag2section[subsysflag] = section; + Imp::subsysflag2string[subsysflag] = subsysname; +} + +//____________________________________________________________________ +VolumeTreeModel::VolumeTreeModel( QObject * parent ) + : QAbstractItemModel(parent), m_d(new Imp()) +{ + if (Imp::section2string.empty()) { + Imp::section2string[Imp::UNKNOWN] = "Unknown"; + Imp::section2string[Imp::SCINT] = "Scintillators"; + Imp::section2string[Imp::TRACKER] = "Muon Spectrometer"; + Imp::section2string[Imp::CALO] = "Calorimeter"; + Imp::section2string[Imp::MISC] = "Miscellaneous"; + } + if (Imp::subsysflag2section.empty()) { + Imp::defineSubSystem(VP1GeoFlags::None,"None",Imp::UNKNOWN); + // Scintillator + Imp::defineSubSystem(VP1GeoFlags::Veto, "Veto", Imp::SCINT); + Imp::defineSubSystem(VP1GeoFlags::Trigger, "Trigger", Imp::SCINT); + Imp::defineSubSystem(VP1GeoFlags::Preshower, "Preshower", Imp::SCINT); + // Tracker + Imp::defineSubSystem(VP1GeoFlags::SCT, "Tracker", Imp::TRACKER); + // Calorimeter + Imp::defineSubSystem(VP1GeoFlags::Ecal, "Ecal", Imp::CALO); + + // // Inner Detector + // Imp::defineSubSystem(VP1GeoFlags::Pixel,"Pixel",Imp::INDET); + // Imp::defineSubSystem(VP1GeoFlags::SCT,"SCT",Imp::INDET); + // Imp::defineSubSystem(VP1GeoFlags::TRT,"TRT",Imp::INDET); + // Imp::defineSubSystem(VP1GeoFlags::InDetServMat,"Services",Imp::INDET); + // // Calorimeters + // Imp::defineSubSystem(VP1GeoFlags::LAr,"LAr",Imp::CALO); + // Imp::defineSubSystem(VP1GeoFlags::Tile,"Tile",Imp::CALO); + // //Toroids + // Imp::defineSubSystem(VP1GeoFlags::BarrelToroid,"Toroid Barrel",Imp::MUON); + // Imp::defineSubSystem(VP1GeoFlags::ToroidECA,"Toroid EndCap side A",Imp::MUON); + // Imp::defineSubSystem(VP1GeoFlags::ToroidECC,"Toroid EndCap side C",Imp::MUON); + // // Structure + // Imp::defineSubSystem(VP1GeoFlags::MuonFeet,"Feets",Imp::MUON); + // Imp::defineSubSystem(VP1GeoFlags::MuonShielding,"Shields, etc.",Imp::MUON); + // Imp::defineSubSystem(VP1GeoFlags::MuonToroidsEtc,"Muon etc.",Imp::MUON); + // // Muon chambers + // Imp::defineSubSystem(VP1GeoFlags::MuonBarrelStationInner,"Inner Barrel Stations",Imp::MUON); + // Imp::defineSubSystem(VP1GeoFlags::MuonBarrelStationMiddle,"Middle Barrel Stations",Imp::MUON); + // Imp::defineSubSystem(VP1GeoFlags::MuonBarrelStationOuter,"Outer Barrel Stations",Imp::MUON); + // Imp::defineSubSystem(VP1GeoFlags::MuonEndcapStationCSC,"Endcap CSC",Imp::MUON); + // Imp::defineSubSystem(VP1GeoFlags::MuonEndcapStationTGC,"Endcap TGC",Imp::MUON); + // Imp::defineSubSystem(VP1GeoFlags::MuonEndcapStationMDT,"Endcap MDT",Imp::MUON); + // Imp::defineSubSystem(VP1GeoFlags::MuonEndcapStationNSW,"Endcap NSW",Imp::MUON); + // // Beam Pipe + // Imp::defineSubSystem(VP1GeoFlags::BeamPipe,"Beam Pipe",Imp::MISC); + // // FWD detectors + // Imp::defineSubSystem(VP1GeoFlags::LUCID,"LUCID",Imp::MISC); + // Imp::defineSubSystem(VP1GeoFlags::ZDC,"ZDC",Imp::MISC); + // Imp::defineSubSystem(VP1GeoFlags::ForwardRegion,"ForwardRegion",Imp::MISC); + // // Cavern + // Imp::defineSubSystem(VP1GeoFlags::CavernInfra,"Cavern Infrastructure",Imp::MISC); + } +} + +//____________________________________________________________________ +void VolumeTreeModel::cleanup() +{ + //This is where we delete all SectionInfo/SubSystem pointers (and thus also all VolumeHandles): + std::map<VP1GeoFlags::SubSystemFlag,Imp::SubSystem*>::iterator it, itE = m_d->flag2subsystems.end(); + for (it = m_d->flag2subsystems.begin();it!=itE;++it) + disableSubSystem(it->first); + for (it = m_d->flag2subsystems.begin();it!=itE;++it) + delete it->second; + foreach (Imp::SectionInfo* section, m_d->allSections) + delete section; +} + +//____________________________________________________________________ +VolumeTreeModel::~VolumeTreeModel() +{ + delete m_d; +} + +//____________________________________________________________________ +void VolumeTreeModel::addSubSystem( VP1GeoFlags::SubSystemFlag flag, + const VolumeHandle::VolumeHandleList& roothandles ) +{ + //NB: This method does not need to be super-fast, thus we do a lot + //of not-so-fast iterations over maps/lists rather than keep extra + //maps/lists around. + + //Check whether we added this subsystem already: + bool found(false); + foreach(Imp::SectionInfo* section, m_d->allSections) { + foreach(Imp::SubSystem* subsys,(section->enabledSubSystems+section->disabledSubSystems)) { + if (subsys->subsysflag==flag) { + found=true; + break; + } + } + } + + if (found) { + // std::cout<<"VolumeTreeModel::addSubSystem Error: System has already been added!"<<std::endl; + return; + } + + //Determine section flag: + Imp::SECTION sectionflag; + if (Imp::subsysflag2section.find(flag)==Imp::subsysflag2section.end()) { + std::cout<<"VolumeTreeModel::addSubSystem Error: Unknown system flag! Please update the code!"<<std::endl; + sectionflag=Imp::UNKNOWN; + } else { + sectionflag=Imp::subsysflag2section[flag]; + } + + //Find the section belonging to the system (create a new one if + //needed - i.e. if this is the first subsystem in a given section): + Imp::SectionInfo* section(0); + found = false; + foreach(Imp::SectionInfo* sec, m_d->allSections) { + if (sec->sectionflag==sectionflag) { + //std::cout << "added section: " << sec->sectionflag << std::endl; + section = sec; + break; + } + } + + if (!section) { + section = new Imp::SectionInfo(sectionflag); + //section->sectionflag = sectionflag; + if (Imp::section2string.find(sectionflag)==Imp::section2string.end()) + section->name = "Unknown Section Flag"; + else + section->name = Imp::section2string[sectionflag]; + m_d->allSections<<section; + //We dont add it to m_d->activeSections since the subsystem (and + //thus the section since it has no other subsystems) is considered + //disabled until enabled by a call to enableSubSystem(). + } + + //Create SubSystem instance for this subsystem and give it the roothandles: + Imp::SubSystem * subsys = new Imp::SubSystem(section,flag); + //subsys->section = section; + //subsys->subsysflag = flag; + if (Imp::subsysflag2string.find(flag)==Imp::subsysflag2string.end()) + subsys->name = "Unknown subsystem flag"; + else + subsys->name = Imp::subsysflag2string[flag]; + subsys->volhandlelist = roothandles; + + //Add the subsystem pointer to the relevant maps: + section->disabledSubSystems << subsys; + m_d->flag2subsystems[flag]=subsys; +} + +//____________________________________________________________________ +void VolumeTreeModel::enableSubSystem(VP1GeoFlags::SubSystemFlag flag) +{ + beginResetModel(); // see: http://doc.qt.io/qt-5/qabstractitemmodel-obsolete.html + + //Check the subsystem was added previously: + if (m_d->flag2subsystems.find(flag)==m_d->flag2subsystems.end()) { + std::cout<<"VolumeTreeModel::enableSubSystem Error: System never added!"<<std::endl; + return; + } + Imp::SubSystem * subsys = m_d->flag2subsystems[flag]; + //Find the appropriate section: + Imp::SectionInfo* section(0); + foreach(Imp::SectionInfo* sec, m_d->allSections) { + if (sec->enabledSubSystems.contains(subsys)) { + //It is already enabled + assert(!sec->disabledSubSystems.contains(subsys)); + return; + } + if (sec->disabledSubSystems.contains(subsys)) { + assert(!sec->enabledSubSystems.contains(subsys)); + section=sec; + break; + } + } + assert(section); + if (!section) { + std::cout<<"VolumeTreeModel::enableSubSystem Error: Did not find section of subsystem!."<<std::endl; + return; + } + //Move the subsystem from the disabled to the enabled list: + section->enabledSubSystems << subsys;//Fixme: Ordering. + section->disabledSubSystems.removeAll(subsys); + //If the newly added subsystem is the only enabled subsystem, the section needs to be enabled as well: + if (section->enabledSubSystems.count()==1) { + assert(!m_d->activeSections.contains(section)); + m_d->activeSections << section;//Fixme: Ordering. + } + //Put volume handle pointers into quick subsystem access map: + foreach (VolumeHandle* volhandle, subsys->volhandlelist ) { + m_d->volhandle2subsystem[volhandle] = subsys; + } + + endResetModel(); + +} + +//____________________________________________________________________ +void VolumeTreeModel::disableSubSystem(VP1GeoFlags::SubSystemFlag flag) +{ + beginResetModel(); // see: http://doc.qt.io/qt-5/qabstractitemmodel-obsolete.html + + //If it was not even added previously we can just return: + if (m_d->flag2subsystems.find(flag)==m_d->flag2subsystems.end()) + return; + + Imp::SubSystem * subsys = m_d->flag2subsystems[flag]; + //Find the appropriate section: + Imp::SectionInfo* section(0); + foreach(Imp::SectionInfo* sec, m_d->allSections) { + if (sec->disabledSubSystems.contains(subsys)) { + //It is already disabled + assert(!sec->enabledSubSystems.contains(subsys)); + return; + } + if (sec->enabledSubSystems.contains(subsys)) { + assert(!sec->disabledSubSystems.contains(subsys)); + section=sec; + break; + } + } + assert(section); + if (!section) { + std::cout<<"VolumeTreeModel::disableSubSystem Error: Did not find section of subsystem!."<<std::endl; + return; + } + + //Move the subsystem from the enabled to the disabled list: + section->disabledSubSystems << subsys; + section->enabledSubSystems.removeAll(subsys); + //If the newly disabled subsystem was the only enabled subsystem, the section needs to be disabled as well: + if (section->enabledSubSystems.count()==0) { + assert(m_d->activeSections.contains(section)); + m_d->activeSections.removeAll(section); + } + + //Remove volume handle pointers from quick subsystem access map: + foreach (VolumeHandle* volhandle, subsys->volhandlelist ) { + Q_ASSERT(m_d->volhandle2subsystem.find(volhandle)!=m_d->volhandle2subsystem.end()); + m_d->volhandle2subsystem.erase(m_d->volhandle2subsystem.find(volhandle)); + } + + endResetModel(); +// reset();//Fixme: use proper insert rows/colums/etc. instead! +} + +//____________________________________________________________________ +void VolumeTreeModel::getRootHandles(std::vector<std::pair<VolumeHandle::VolumeHandleListItr,VolumeHandle::VolumeHandleListItr> >& out) const +{ + out.clear(); + out.reserve(m_d->flag2subsystems.size()); + std::map<VP1GeoFlags::SubSystemFlag,Imp::SubSystem*>::iterator it, itE = m_d->flag2subsystems.end(); + for (it = m_d->flag2subsystems.begin();it!=itE;++it) + out.push_back(std::pair<VolumeHandle::VolumeHandleListItr,VolumeHandle::VolumeHandleListItr> + (it->second->volhandlelist.begin(),it->second->volhandlelist.end())); + +} + +//____________________________________________________________________ +QModelIndex VolumeTreeModel::index(int row, int column, const QModelIndex &parent) const +{ + //Check that row and column are in allowed ranges (positive and within row/column count of parent): + if (!hasIndex(row, column, parent)) + return QModelIndex(); + + if (!parent.isValid()) { + //We must return the index of a section label: + Q_ASSERT(row<m_d->activeSections.count()); + return createIndex(row, column, m_d->activeSections.at(row)); + } + + VolumeHandle * parentHandle = Imp::handlePointer(parent); + + if (Imp::isRegularVolumeHandle(parentHandle)) { + if (!parentHandle->childrenAreInitialised()) + parentHandle->initialiseChildren();//Fixme: It seems that it is occasionally necessary to do this. Why?? Why not fetchMore?? + VolumeHandle * childHandle = parentHandle->child(row); + Q_ASSERT(childHandle); + return createIndex(row, column, childHandle); + } + + if (Imp::isSubSystemPointer(parentHandle)) { + //Return index of top-level volume: + Q_ASSERT(unsigned(row)<Imp::subSystemPointer(parentHandle)->volhandlelist.size()); + return createIndex(row, column, Imp::subSystemPointer(parentHandle)->volhandlelist.at(row)); + } + + //Must be SectionInfo: + Q_ASSERT(Imp::isSectionInfoPointer(parentHandle)); + Q_ASSERT(row<Imp::sectionInfoPointer(parentHandle)->enabledSubSystems.count()); + return createIndex(row, column, Imp::sectionInfoPointer(parentHandle)->enabledSubSystems.at(row)); +} + +//____________________________________________________________________ +QModelIndex VolumeTreeModel::parent(const QModelIndex& index) const +{ + if (!index.isValid()) + return QModelIndex(); + + //See if we have a volumeHandle as index: + VolumeHandle *childHandle = Imp::handlePointer(index); + + if (Imp::isRegularVolumeHandle(childHandle)) { + VolumeHandle *parentHandle = childHandle->parent(); + if (parentHandle) + return createIndex(parentHandle->childNumber(), 0, parentHandle); + + //childHandle has 0 parent pointer => parent must be a subsystem label: + Q_ASSERT(m_d->volhandle2subsystem.find(childHandle)!=m_d->volhandle2subsystem.end()); + Imp::SubSystem * subsys = m_d->volhandle2subsystem[childHandle]; + Q_ASSERT(subsys); + Q_ASSERT(subsys->section->enabledSubSystems.contains(subsys)); + return createIndex(subsys->section->enabledSubSystems.indexOf(subsys), 0, subsys); + } + + + if (Imp::isSubSystemPointer(childHandle)) { + //Index is a SubSystem => parent must be a section label: + Q_ASSERT(m_d->activeSections.contains(Imp::subSystemPointer(childHandle)->section)); + return createIndex(m_d->activeSections.indexOf(Imp::subSystemPointer(childHandle)->section), 0, Imp::subSystemPointer(childHandle)->section); + } + + //Must be SectionInfo => parent is root (i.e. invalid): + Q_ASSERT(Imp::isSectionInfoPointer(childHandle)); + return QModelIndex(); +} + +//____________________________________________________________________ +int VolumeTreeModel::rowCount(const QModelIndex& parent) const +{ + if (parent.column() > 0) + return 0; + + if (!parent.isValid()) + return m_d->activeSections.size();//Number of active sections + + VolumeHandle * parentHandle = Imp::handlePointer(parent); + + if (Imp::isRegularVolumeHandle(parentHandle)) { + return parentHandle->nChildren(); + } + + if (Imp::isSubSystemPointer(parentHandle)) { + return Imp::subSystemPointer(parentHandle)->volhandlelist.size(); + } + + //Must be SectionInfo pointer: + Q_ASSERT(Imp::isSectionInfoPointer(parentHandle)); + return Imp::sectionInfoPointer(parentHandle)->enabledSubSystems.count(); +} + +//____________________________________________________________________ +QVariant VolumeTreeModel::data(const QModelIndex& index, int role) const +{ + if ((role!=Qt::DisplayRole&&role!=Qt::TextColorRole)||!index.isValid()) + return QVariant(); + + VolumeHandle *volumeHandle = Imp::handlePointer(index); + if (Imp::isRegularVolumeHandle(volumeHandle)) { + if (role==Qt::TextColorRole) { + if (volumeHandle->isAttached()) + return QVariant(); + else + return QColor::fromRgbF( 0.5, 0.5, 0.5 ); + } + //DisplayRole: + if (volumeHandle->nChildren()>1) + return volumeHandle->getName()+" ["+QString::number(volumeHandle->nChildren())+"]"; + else + return volumeHandle->getName(); + } + + if (role==Qt::TextColorRole) + return QVariant(); + + if (Imp::isSubSystemPointer(volumeHandle)) + return Imp::subSystemPointer(volumeHandle)->name; + + Q_ASSERT(Imp::isSectionInfoPointer(volumeHandle)); + return Imp::sectionInfoPointer(volumeHandle)->name; +} + + +//____________________________________________________________________ +Qt::ItemFlags VolumeTreeModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return 0; + + if (Imp::isRegularVolumeHandle(Imp::handlePointer(index))) + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; + else + return Qt::ItemIsEnabled; +} + +//____________________________________________________________________ +QVariant VolumeTreeModel::headerData(int /*section*/, Qt::Orientation /*orientation*/,int /*role*/) const +{ + return QVariant(); +} + +//____________________________________________________________________ +bool VolumeTreeModel::canFetchMore( const QModelIndex & parent ) const +{ + if (!parent.isValid()) + return false; + + VolumeHandle * parentHandle = Imp::handlePointer(parent); + + if (Imp::isRegularVolumeHandle(parentHandle)&&!parentHandle->childrenAreInitialised()) + return true; + + return false; +} + +//____________________________________________________________________ +void VolumeTreeModel::fetchMore( const QModelIndex & parent ) +{ + if (!parent.isValid()) + return;//should probably never happen + + VolumeHandle* parentHandle = Imp::handlePointer(parent); + + if (Imp::isRegularVolumeHandle(parentHandle)&&!parentHandle->childrenAreInitialised()) { + // beginInsertRows(parent,0,int(parentHandle->nChildren())-1); + parentHandle->initialiseChildren(); + layoutChanged();//fixme?? + // endInsertRows(); + return; + } +} + +//____________________________________________________________________ +bool VolumeTreeModel::hasChildren ( const QModelIndex & parent ) const +{ + return rowCount(parent)>0;//Our rowCount is relatively fast (no looping to count). +} diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/ZappedVolumeListModel.cxx b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/ZappedVolumeListModel.cxx new file mode 100644 index 000000000..da2dc1dde --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/ZappedVolumeListModel.cxx @@ -0,0 +1,22 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "VTI12GeometrySystems/ZappedVolumeListModel.h" + +//____________________________________________________________________ +ZappedVolumeListModel::ZappedVolumeListModel(QObject * parent) + : QAbstractListModel(parent) +{ +} + +//____________________________________________________________________ +ZappedVolumeListModel::~ZappedVolumeListModel() +{ +} + +//____________________________________________________________________ +void ZappedVolumeListModel::activated(const QModelIndex& index) +{ + m_zappedhandles.at(index.row())->setState(VP1GeoFlags::CONTRACTED); +} diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/geometrysystemcontroller.ui b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/geometrysystemcontroller.ui new file mode 100644 index 000000000..d9bbb2b36 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/geometrysystemcontroller.ui @@ -0,0 +1,488 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>GeometrySystemControllerForm</class> + <widget class="QWidget" name="GeometrySystemControllerForm"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>338</width> + <height>822</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <property name="leftMargin"> + <number>6</number> + </property> + <property name="topMargin"> + <number>6</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>4</number> + </property> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <widget class="QWidget" name="widget_settingsButtonsPlaceholder" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <layout class="QGridLayout" name="_19"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <item row="0" column="0"> + <widget class="QPushButton" name="pushButton_settings_display"> + <property name="toolTip"> + <string>Configure overall display options such as phi-sector cutaways and transparency</string> + </property> + <property name="text"> + <string>Display</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QPushButton" name="pushButton_settings_interactions"> + <property name="toolTip"> + <string>Configure what happens when a geometry volume is clicked</string> + </property> + <property name="text"> + <string>Interactions</string> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QPushButton" name="pushButton_settings_iconisedvols"> + <property name="toolTip"> + <string>Show a list of iconised/zapped volumes and possible restore them.</string> + </property> + <property name="text"> + <string>Icon Box</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QPushButton" name="pushButton_settings_misc"> + <property name="toolTip"> + <string>Miscellaneous controls such as automatic actions on multiple volumes, or editing the colour of the last volume clicked.</string> + </property> + <property name="text"> + <string>Misc.</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QPushButton" name="pushButton_settings_treebrowser"> + <property name="toolTip"> + <string>Browse the detector volume in a tree-view.</string> + </property> + <property name="text"> + <string>Browser</string> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QPushButton" name="pushButton_settings_unused"> + <property name="toolTip"> + <string>Currently unused</string> + </property> + <property name="text"> + <string>Unused</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>8</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <layout class="QVBoxLayout" name="_2"> + <property name="spacing"> + <number>4</number> + </property> + <item> + <widget class="QGroupBox" name="groupBox_scintillator"> + <property name="title"> + <string>Scintillator</string> + </property> + <layout class="QHBoxLayout" name="_3"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>4</number> + </property> + <property name="topMargin"> + <number>4</number> + </property> + <property name="rightMargin"> + <number>4</number> + </property> + <property name="bottomMargin"> + <number>4</number> + </property> + <item> + <layout class="QGridLayout" name="_4"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <property name="horizontalSpacing"> + <number>6</number> + </property> + <property name="verticalSpacing"> + <number>0</number> + </property> + <item row="0" column="0"> + <widget class="QCheckBox" name="checkBox_Veto"> + <property name="text"> + <string>Veto</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QCheckBox" name="checkBox_Trigger"> + <property name="text"> + <string>Trigger</string> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QCheckBox" name="checkBox_Preshower"> + <property name="text"> + <string>Preshower</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_tracker"> + <property name="title"> + <string>Tracker</string> + </property> + <layout class="QHBoxLayout" name="_5"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>4</number> + </property> + <property name="topMargin"> + <number>4</number> + </property> + <property name="rightMargin"> + <number>4</number> + </property> + <property name="bottomMargin"> + <number>4</number> + </property> + <item> + <widget class="QCheckBox" name="checkBox_SCT"> + <property name="text"> + <string>SCT</string> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_calorimeter"> + <property name="title"> + <string>Calorimeter</string> + </property> + <layout class="QVBoxLayout" name="_12"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>4</number> + </property> + <property name="topMargin"> + <number>4</number> + </property> + <property name="rightMargin"> + <number>4</number> + </property> + <property name="bottomMargin"> + <number>4</number> + </property> + <item> + <layout class="QHBoxLayout" name="_14"> + <item> + <widget class="QCheckBox" name="checkBox_Ecal"> + <property name="text"> + <string>Ecal</string> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_misc"> + <property name="title"> + <string>Miscellaneous</string> + </property> + <layout class="QVBoxLayout" name="_12_2"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>4</number> + </property> + <property name="topMargin"> + <number>4</number> + </property> + <property name="rightMargin"> + <number>4</number> + </property> + <property name="bottomMargin"> + <number>4</number> + </property> + <item> + <layout class="QHBoxLayout" name="_13"> + <item> + <widget class="QCheckBox" name="checkBox_CavernInfra"> + <property name="text"> + <string>Cavern Infrastructure</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QCheckBox" name="checkBox_other"> + <property name="text"> + <string>Other unrecognised volumes.</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="_15"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <layout class="QVBoxLayout" name="_16"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="label_12"> + <property name="text"> + <string>Instructions:</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="_17"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QVBoxLayout" name="_18"> + <property name="spacing"> + <number>1</number> + </property> + <item> + <widget class="QLabel" name="label_9"> + <property name="text"> + <string>Crtl+click: Expand to child volumes</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_10"> + <property name="text"> + <string>Shift+click: Contract to mother volume</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_11"> + <property name="text"> + <string>Z+click: Iconify (remove) volume</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>1</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/settings_display_form.ui b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/settings_display_form.ui new file mode 100644 index 000000000..292aef8be --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/settings_display_form.ui @@ -0,0 +1,460 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>GeoSysSettingsDisplayForm</class> + <widget class="QWidget" name="GeoSysSettingsDisplayForm"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>397</width> + <height>562</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Phi Sector Cutaways</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="PhiSectionWidget" name="phisectionwidget"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>60</width> + <height>60</height> + </size> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>70</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_5"> + <property name="title"> + <string>Draw options</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Transparency:</string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="spinBox_transp"> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="suffix"> + <string> %</string> + </property> + <property name="maximum"> + <number>100</number> + </property> + <property name="singleStep"> + <number>5</number> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QCheckBox" name="checkBox_showVolumeOutLines"> + <property name="toolTip"> + <string>Decorate shapes with lines at the edges (current only certain shapes such as muon chambers are supported)</string> + </property> + <property name="text"> + <string>Show outlines</string> + </property> + </widget> + </item> + <item> + <widget class="VP1DrawOptionsWidget" name="widget_drawOptions" native="true"/> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_colouring"> + <property name="title"> + <string>Custom Colouring</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0" colspan="2"> + <layout class="QHBoxLayout" name="_8"> + <item> + <widget class="QLabel" name="label_13"> + <property name="text"> + <string>Edit material of last selected volume:</string> + </property> + </widget> + </item> + <item> + <widget class="VP1MaterialButton" name="matButton_lastSel"> + <property name="toolTip"> + <string>Edit the material of the last picked volume</string> + </property> + <property name="text"> + <string/> + </property> + </widget> + </item> + </layout> + </item> + <item row="1" column="0"> + <widget class="QPushButton" name="pushButton_saveChangedMaterials"> + <property name="toolTip"> + <string>Store changed materials into a .vp1geomat file which can be loaded later (hold down CTRL while clicking to store ALL materials, rather than just the ones that do not have default values)</string> + </property> + <property name="text"> + <string>Save changed materials</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QPushButton" name="pushButton_loadMaterials"> + <property name="toolTip"> + <string>Load materials from a .vp1geomat file</string> + </property> + <property name="text"> + <string>Load materials</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_labels"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="title"> + <string>Labels</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>false</bool> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <widget class="QCheckBox" name="checkBox_labels_names"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="toolTip"> + <string>Enables the drawing of track labels</string> + </property> + <property name="text"> + <string>Chamber name</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_labels_mooret0s"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Chamber t0s (Moore)</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_labels_mboyt0s"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Chamber t0s (Mboy)</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_labels_hits"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Hit counts</string> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>17</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QGroupBox" name="groupBox_2"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>150</width> + <height>0</height> + </size> + </property> + <property name="title"> + <string>Offset</string> + </property> + <property name="flat"> + <bool>false</bool> + </property> + <layout class="QGridLayout" name="gridLayout_3"> + <property name="bottomMargin"> + <number>7</number> + </property> + <property name="horizontalSpacing"> + <number>-1</number> + </property> + <property name="verticalSpacing"> + <number>0</number> + </property> + <item row="0" column="0"> + <widget class="QLabel" name="label_11"> + <property name="text"> + <string>x</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QSlider" name="horizontalSlider_labels_yOffset"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>32</height> + </size> + </property> + <property name="minimum"> + <number>-100</number> + </property> + <property name="maximum"> + <number>100</number> + </property> + <property name="tracking"> + <bool>true</bool> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="invertedAppearance"> + <bool>false</bool> + </property> + <property name="tickPosition"> + <enum>QSlider::TicksAbove</enum> + </property> + <property name="tickInterval"> + <number>25</number> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QSlider" name="horizontalSlider_labels_zOffset"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>32</height> + </size> + </property> + <property name="minimum"> + <number>-100</number> + </property> + <property name="maximum"> + <number>100</number> + </property> + <property name="tracking"> + <bool>true</bool> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="invertedAppearance"> + <bool>false</bool> + </property> + <property name="tickPosition"> + <enum>QSlider::TicksAbove</enum> + </property> + <property name="tickInterval"> + <number>25</number> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_9"> + <property name="text"> + <string>z</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QSlider" name="horizontalSlider_labels_xOffset"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>32</height> + </size> + </property> + <property name="minimum"> + <number>-100</number> + </property> + <property name="maximum"> + <number>100</number> + </property> + <property name="tracking"> + <bool>true</bool> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="invertedAppearance"> + <bool>false</bool> + </property> + <property name="tickPosition"> + <enum>QSlider::TicksAbove</enum> + </property> + <property name="tickInterval"> + <number>25</number> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>y</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="_4"> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_close"> + <property name="text"> + <string>&Close</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>VP1MaterialButton</class> + <extends>QPushButton</extends> + <header>VP1Base/VP1MaterialButton.h</header> + </customwidget> + <customwidget> + <class>VP1DrawOptionsWidget</class> + <extends>QWidget</extends> + <header>VP1Base/VP1DrawOptionsWidget.h</header> + <container>1</container> + </customwidget> + <customwidget> + <class>PhiSectionWidget</class> + <extends>QGraphicsView</extends> + <header>VP1Base/PhiSectionWidget.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections> + <connection> + <sender>groupBox_labels</sender> + <signal>toggled(bool)</signal> + <receiver>checkBox_labels_names</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>198</x> + <y>426</y> + </hint> + <hint type="destinationlabel"> + <x>118</x> + <y>396</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/settings_iconisedvols_form.ui b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/settings_iconisedvols_form.ui new file mode 100644 index 000000000..5b6a9b817 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/settings_iconisedvols_form.ui @@ -0,0 +1,54 @@ +<ui version="4.0" > + <class>GeoSysSettingsIconisedVolumesForm</class> + <widget class="QWidget" name="GeoSysSettingsIconisedVolumesForm" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>196</width> + <height>165</height> + </rect> + </property> + <property name="windowTitle" > + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout" > + <item> + <widget class="QLabel" name="label" > + <property name="text" > + <string>Iconised volumes (click to restore):</string> + </property> + </widget> + </item> + <item> + <widget class="QListView" name="listView_iconisedvolumes" /> + </item> + <item> + <layout class="QHBoxLayout" name="_4" > + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_close" > + <property name="text" > + <string>&Close</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/settings_interactions_form.ui b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/settings_interactions_form.ui new file mode 100644 index 000000000..2e2f567c3 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/settings_interactions_form.ui @@ -0,0 +1,147 @@ +<ui version="4.0" > + <class>GeoSysSettingsInteractionsForm</class> + <widget class="QWidget" name="GeoSysSettingsInteractionsForm" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>240</width> + <height>298</height> + </rect> + </property> + <property name="windowTitle" > + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout" > + <item> + <layout class="QHBoxLayout" name="_3" > + <item> + <widget class="QCheckBox" name="checkBox_geomselectable" > + <property name="text" > + <string>Geometry is selectable</string> + </property> + <property name="checked" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>16</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QGroupBox" name="groupBox_printOnSelection" > + <property name="title" > + <string>Print on Selection</string> + </property> + <layout class="QGridLayout" name="blabla_2" > + <item row="0" column="0" > + <widget class="QCheckBox" name="checkBox_print_shape" > + <property name="text" > + <string>Shape</string> + </property> + </widget> + </item> + <item row="0" column="1" > + <widget class="QCheckBox" name="checkBox_print_material" > + <property name="text" > + <string>Material</string> + </property> + <property name="checked" > + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="0" > + <widget class="QCheckBox" name="checkBox_print_transform" > + <property name="text" > + <string>Transform</string> + </property> + </widget> + </item> + <item row="1" column="1" > + <widget class="QCheckBox" name="checkBox_print_mass" > + <property name="toolTip" > + <string><html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">In the case where either the selected volume or one its daugthers (or daughters daughters, etc.), is defined as a boolean volume, this might not give an entirely accurate result.</p></body></html></string> + </property> + <property name="text" > + <string>Mass (unreliable)</string> + </property> + </widget> + </item> + <item row="2" column="0" > + <widget class="QCheckBox" name="checkBox_print_copyno" > + <property name="text" > + <string>Copy No</string> + </property> + </widget> + </item> + <item row="2" column="1" > + <widget class="QCheckBox" name="checkBox_print_tree" > + <property name="text" > + <string>Tree</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_automaticViewReorientations" > + <property name="title" > + <string>Automatic view reorientations</string> + </property> + <layout class="QVBoxLayout" > + <item> + <widget class="QCheckBox" name="checkBox_zoomToVolumes" > + <property name="text" > + <string>Zoom to volumes</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="_4" > + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_close" > + <property name="text" > + <string>&Close</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/settings_misc_form.ui b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/settings_misc_form.ui new file mode 100644 index 000000000..cde208ed6 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/settings_misc_form.ui @@ -0,0 +1,245 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>GeoSysSettingsMiscForm</class> + <widget class="QWidget" name="GeoSysSettingsMiscForm"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>370</width> + <height>360</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QGroupBox" name="groupBox_trackeractivemodules"> + <property name="title"> + <string>Tracker active stations (not implemented)</string> + </property> + <layout class="QHBoxLayout" name="_3"> + <property name="leftMargin"> + <number>4</number> + </property> + <property name="topMargin"> + <number>4</number> + </property> + <property name="rightMargin"> + <number>4</number> + </property> + <property name="bottomMargin"> + <number>4</number> + </property> + <item> + <layout class="QVBoxLayout" name="_4"> + <item> + <widget class="QCheckBox" name="checkBox_sctmod_upstream"> + <property name="text"> + <string>Upstream</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_sctmod_central"> + <property name="text"> + <string>Central</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_sctmod_downstream"> + <property name="text"> + <string>Downstream</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="toolButton_sctmod_adapt"> + <property name="text"> + <string>Adapt</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="toolButton_sctmod_reset"> + <property name="text"> + <string>Reset</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Actions on visible volumes</string> + </property> + <layout class="QGridLayout" name="_5"> + <property name="leftMargin"> + <number>4</number> + </property> + <property name="topMargin"> + <number>4</number> + </property> + <property name="rightMargin"> + <number>4</number> + </property> + <property name="bottomMargin"> + <number>4</number> + </property> + <property name="horizontalSpacing"> + <number>2</number> + </property> + <item row="0" column="0" colspan="2"> + <widget class="QLabel" name="label_7"> + <property name="text"> + <string>Vols. with mat:</string> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QLineEdit" name="lineEdit_expand_vols_matname"> + <property name="minimumSize"> + <size> + <width>50</width> + <height>0</height> + </size> + </property> + <property name="toolTip"> + <string><html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Matching is case-sensitive and wildcards are allowed.</p></body></html></string> + </property> + <property name="text"> + <string>Air</string> + </property> + </widget> + </item> + <item row="0" column="3"> + <widget class="QPushButton" name="pushButton_expand_vols_matname"> + <property name="text"> + <string>Expand</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_8"> + <property name="text"> + <string>Vols. named:</string> + </property> + </widget> + </item> + <item row="1" column="1" colspan="2"> + <widget class="QLineEdit" name="lineEdit_expand_vols_volname"> + <property name="toolTip"> + <string><html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Matching is case-insensitive and wildcards are allowed.</p></body></html></string> + </property> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="1" column="3"> + <widget class="QPushButton" name="pushButton_expand_vols_volname"> + <property name="text"> + <string>Expand</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label"> + <property name="toolTip"> + <string>Actions on all shapes with 3D representations that are not standard VRML. Useful if you intend to dump the scene to a portable file.</string> + </property> + <property name="text"> + <string>Non-standard shapes:</string> + </property> + </widget> + </item> + <item row="2" column="2" colspan="2"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QPushButton" name="pushButton_nonStandardShapes_Iconify"> + <property name="toolTip"> + <string>Actions on all shapes with 3D representations that are not standard VRML. Useful if you intend to dump the scene to a portable file.</string> + </property> + <property name="text"> + <string>Iconify</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pushButton_nonStandardShapes_Expand"> + <property name="toolTip"> + <string>Actions on all shapes with 3D representations that are not standard VRML. Useful if you intend to dump the scene to a portable file.</string> + </property> + <property name="text"> + <string>Expand</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="_10"> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_close"> + <property name="text"> + <string>&Close</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/settings_treebrowser_form.ui b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/settings_treebrowser_form.ui new file mode 100644 index 000000000..10a405c1d --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GeometrySystems/src/settings_treebrowser_form.ui @@ -0,0 +1,61 @@ +<ui version="4.0" > + <class>GeoSysSettingsTreeBrowserForm</class> + <widget class="QWidget" name="GeoSysSettingsTreeBrowserForm" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>214</width> + <height>165</height> + </rect> + </property> + <property name="windowTitle" > + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout" > + <item> + <widget class="QLabel" name="label" > + <property name="text" > + <string>GeoModel volume hierachy:</string> + </property> + </widget> + </item> + <item> + <widget class="VP1GeoTreeView" name="treeView_volumebrowser" /> + </item> + <item> + <layout class="QHBoxLayout" name="_4" > + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_close" > + <property name="text" > + <string>&Close</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>VP1GeoTreeView</class> + <extends>QTreeView</extends> + <header>VTI12GeometrySystems/VP1GeoTreeView.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/CMakeLists.txt b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/CMakeLists.txt new file mode 100644 index 000000000..09c90e47a --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/CMakeLists.txt @@ -0,0 +1,35 @@ +# $Id: CMakeLists.txt 728676 2016-03-09 15:11:49Z krasznaa $ +################################################################################ +# Package: VTI12GuideLineSystems +################################################################################ + +# Declare the package name: +atlas_subdir( VTI12GuideLineSystems ) + +# Declare the package's dependencies: +atlas_depends_on_subdirs( + PUBLIC + DetectorDescription/GeoPrimitives + graphics/VP1/VP1Base + graphics/VTI12/VTI12Utils + PRIVATE + GaudiKernel + graphics/VP1/VP1HEPVis ) + +# External dependencies: +find_package( Coin3D ) +find_package( Qt5 COMPONENTS Core Gui Widgets ) + +# Generate UI files automatically: +set( CMAKE_AUTOUIC TRUE ) +# Generate MOC files automatically: +set( CMAKE_AUTOMOC TRUE ) + +# Component(s) in the package: +atlas_add_library( VTI12GuideLineSystems VTI12GuideLineSystems/*.h src/*.cxx + PUBLIC_HEADERS VP1GuideLineSystems + INCLUDE_DIRS ${COIN3D_INCLUDE_DIRS} + LINK_LIBRARIES ${COIN3D_LIBRARIES} GeoPrimitives VP1Base VTI12Utils + Qt5::Core Qt5::Gui + PRIVATE_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR} + PRIVATE_LINK_LIBRARIES GaudiKernel VP1HEPVis ) diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/GuideSysController.h b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/GuideSysController.h new file mode 100644 index 000000000..ddef1cb10 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/GuideSysController.h @@ -0,0 +1,208 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class GuideSysController // +// // +// Description: Guide system controller. // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: July 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef GUIDESYSCONTROLLER_H +#define GUIDESYSCONTROLLER_H + +#include "VP1Base/VP1Controller.h" +#include "VTI12Utils/InDetProjFlags.h" +#include <Inventor/C/errors/debugerror.h> +#include <Inventor/SbColor4f.h> +class SoMaterial; + +class GuideSysController : public VP1Controller { + + Q_OBJECT + +public: + + GuideSysController(IVP1System * sys); + virtual ~GuideSysController(); + + void actualRestoreSettings(VP1Deserialise&); + int currentSettingsVersion() const; + void actualSaveSettings(VP1Serialise&) const; + + /////////////////////////////////// + // Access Methods for settings // + /////////////////////////////////// + + //Fixme: SoGroup * drawOptions() const; + + //Various materials: + SoMaterial * lettersMaterial() const; + SoMaterial * xAxisMaterial() const; + SoMaterial * yAxisMaterial() const; + SoMaterial * zAxisMaterial() const; + SoMaterial * etaCone1Material() const; + SoMaterial * etaCone2Material() const; + SoMaterial * etaCone3Material() const; + SoMaterial * pixelProjSurfMaterial() const; + SoMaterial * sctProjSurfMaterial() const; + SoMaterial * trtProjSurfMaterial() const; + SoMaterial * idTrkVolumesMaterial() const; + SoMaterial * caloTrkVolumesMaterial() const; + SoMaterial * msTrkVolumesMaterial() const; + + //Floor: + bool showFloor() const; + SbColor4f floorColourAndTransp() const; + double floorExtent() const; + double floorSpacing() const; + double floorHeight() const; + + //Letters: + bool showLetters() const; + double lettersZPos() const; + double lettersVerticalPos() const; + + //Coordinate axis + bool showAxes() const; + double axesLength() const;//A negative value means that negative parts will be shown as well + SbVec3f axesPosition() const; + double relAxesThickness() const; + + //Grid: + bool showCartesianGrid() const; + bool showCylindricalGrid() const; + SbColor4f gridColourAndTransp() const; + double gridSpacing() const; + double gridExtent() const; + + //Eta cones: + bool showEtaCone1() const; + bool showEtaCone2() const; + bool showEtaCone3() const; + double etaConeValue1() const; + double etaConeValue2() const; + double etaConeValue3() const; + double etaExtent() const;//>0: extent means to a given radius, <0: extent means to a given z. + + //TrackingVolumes + bool showTrackingVolumes() const; + bool showInnerDetector() const; + bool showCalorimeters() const; + bool showMuonSpectrometer() const; + + // Lines + bool showLines() const; + double lineLength() const; + SbVec3f lineDirection() const; + + //ID Proj surfs: + + //This is the surfaces the data systems should project their data to: + InDetProjFlags::InDetProjPartsFlags applicablePixelProjParts() const; + InDetProjFlags::InDetProjPartsFlags applicableSCTProjParts() const; + InDetProjFlags::InDetProjPartsFlags applicableTRTProjParts() const; + //This is the surfaces the guideline system should draw surfaces: + InDetProjFlags::InDetProjPartsFlags shownPixelProjSurfaces() const; + InDetProjFlags::InDetProjPartsFlags shownSCTProjSurfaces() const; + InDetProjFlags::InDetProjPartsFlags shownTRTProjSurfaces() const; + + //Info arriving from other systems: + void setInDetDetTypesUsingProjections(InDetProjFlags::DetTypeFlags); + + /////////////////////////////////////// + // Signals for changes in settings // + /////////////////////////////////////// +signals: + void showFloorChanged(bool); + void floorColourAndTranspChanged( const SbColor4f& ); + void floorExtentChanged(const double&); + void floorSpacingChanged(const double&); + void floorHeightChanged(const double&); + void showLettersChanged(bool); + void lettersZPosChanged(const double&); + void lettersVerticalPosChanged(const double&); + void showAxesChanged(bool); + void axesLengthChanged(const double&); + void axesPositionChanged(const SbVec3f&); + void relAxesThicknessChanged(const double&); + void showCartesianGridChanged(bool); + void showCylindricalGridChanged(bool); + void gridColourAndTranspChanged( const SbColor4f& ); + void gridSpacingChanged(const double&); + void gridExtentChanged(const double&); + void showEtaCone1Changed(bool); + void showEtaCone2Changed(bool); + void showEtaCone3Changed(bool); + void etaConeValue1Changed(const double&); + void etaConeValue2Changed(const double&); + void etaConeValue3Changed(const double&); + void etaExtentChanged(const double&); + void applicablePixelProjPartsChanged(InDetProjFlags::InDetProjPartsFlags); + void applicableSCTProjPartsChanged(InDetProjFlags::InDetProjPartsFlags); + void applicableTRTProjPartsChanged(InDetProjFlags::InDetProjPartsFlags); + void shownPixelProjSurfacesChanged(InDetProjFlags::InDetProjPartsFlags); + void shownSCTProjSurfacesChanged(InDetProjFlags::InDetProjPartsFlags); + void shownTRTProjSurfacesChanged(InDetProjFlags::InDetProjPartsFlags); + void showTrackingVolumesChanged(bool); + void showInnerDetectorChanged(bool); + void showCalorimetersChanged(bool); + void showMuonSpectrometerChanged(bool); + void showLinesChanged(bool); + void lineDirectionChanged(const SbVec3f&); + +private: + + class Imp; + Imp * m_d; + +private slots: + void updateProjPartsCheckboxStates_Pixel(); + void updateProjPartsCheckboxStates_SCT(); + void updateProjPartsCheckboxStates_TRT(); + void possibleChange_showFloor(); + void possibleChange_floorColourAndTransp(); + void possibleChange_floorExtent(); + void possibleChange_floorSpacing(); + void possibleChange_floorHeight(); + void possibleChange_showLetters(); + void possibleChange_lettersZPos(); + void possibleChange_lettersVerticalPos(); + void possibleChange_showAxes(); + void possibleChange_axesLength(); + void possibleChange_axesPosition(); + void possibleChange_relAxesThickness(); + void possibleChange_showCartesianGrid(); + void possibleChange_showCylindricalGrid(); + void possibleChange_gridColourAndTransp(); + void possibleChange_gridSpacing(); + void possibleChange_gridExtent(); + void possibleChange_showEtaCone1(); + void possibleChange_showEtaCone2(); + void possibleChange_showEtaCone3(); + void possibleChange_etaConeValue1(); + void possibleChange_etaConeValue2(); + void possibleChange_etaConeValue3(); + void possibleChange_etaExtent(); + void possibleChange_applicablePixelProjParts(); + void possibleChange_applicableSCTProjParts(); + void possibleChange_applicableTRTProjParts(); + void possibleChange_shownPixelProjSurfaces(); + void possibleChange_shownSCTProjSurfaces(); + void possibleChange_shownTRTProjSurfaces(); + void possibleChange_showTrackingVolumes(); + void possibleChange_showInnerDetector(); + void possibleChange_showCalorimeters(); + void possibleChange_showMuonSpectrometer(); + void possibleChange_showLines(); + void possibleChange_lineDirection(); +}; + + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/InDetProjHelper.h b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/InDetProjHelper.h new file mode 100644 index 000000000..5450d0ace --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/InDetProjHelper.h @@ -0,0 +1,103 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class InDetProjHelper // +// // +// Description: Helper class for calculating projections // +// of data to inner detector surfaces. // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: February 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef INDETPROJHELPER_H +#define INDETPROJHELPER_H + +#include "VP1Base/VP1HelperClassBase.h" +#include "VTI12Utils/InDetProjFlags.h" + +#include "GeoPrimitives/GeoPrimitives.h" +#include "GeoPrimitives/GeoPrimitivesHelpers.h" + + +#include <vector> +#include <set> + + + + +class InDetProjHelper : public VP1HelperClassBase { +public: + + //Use one of the following to create an appropriate helper: + static InDetProjHelper * createPixelHelper(IVP1System* sys = 0); + static InDetProjHelper * createSCTHelper(IVP1System* sys = 0); + static InDetProjHelper * createTRTHelper(IVP1System* sys = 0); + //(non-zero system pointers to let error messages appear in gui) + + virtual ~InDetProjHelper(); + + InDetProjFlags::InDetProjPartsFlags setParts(InDetProjFlags::InDetProjPartsFlags);//returns old value + InDetProjFlags::InDetProjPartsFlags parts() const; + + //Clip path to volumes of the enabled detector parts, as given by the parts flag. + void clipPath( const std::vector<Amg::Vector3D >& path, Amg::SetVectorVector3D& resulting_subpaths ) const; + + void clipPath( const std::vector<Amg::Vector3D >& path, + Amg::SetVectorVector3D& resulting_subpaths_barrelA, + Amg::SetVectorVector3D& resulting_subpaths_barrelC, + Amg::SetVectorVector3D& resulting_subpaths_endcapA, + Amg::SetVectorVector3D& resulting_subpaths_endcapC ) const; + + //Clip path as above, and then project the resulting subpaths to surfaces as given by the current parts flag. + void projectPath( const std::vector<Amg::Vector3D >& path, Amg::SetVectorVector3D& resulting_projections ) const; + void projectPath( const std::vector<Amg::Vector3D >& path, + Amg::SetVectorVector3D& resulting_projections_barrelA, + Amg::SetVectorVector3D& resulting_projections_barrelC, + Amg::SetVectorVector3D& resulting_projections_endcapA, + Amg::SetVectorVector3D& resulting_projections_endcapC ) const; + + //To figure out which parts a given track crosses (this does NOT depend on the current InDetProjPartsFlags setting). + enum PartsFlag { NoParts = 0x00, BarrelA = 0x01, BarrelC = 0x02, EndCapA = 0x04, EndCapC = 0x08 }; + Q_DECLARE_FLAGS(PartsFlags, PartsFlag) + PartsFlags touchedParts( const std::vector<Amg::Vector3D >& path ) const; + + //Fixme: Projection of points? Projection of driftcircle (get normal and point? Or just get transform?) + + static void transformECPointToZPlane_specialZtoR(Amg::Vector3D& p, + const double& planeZ, + const double& planeRBegin, + const double& endcapZBegin, + const double& squeezeFactor ); + +private: + + InDetProjHelper( double surfacethickness, + double data_disttosurface_epsilon, + double barrel_inner_radius, + double barrel_outer_radius, + double barrel_posneg_z, + double endcap_surface_z, + double endcap_surface_length, + double endcap_inner_radius, + double endcap_outer_radius, + double endcap_zasr_innerradius, + double endcap_zasr_endcapz_begin, + double endcap_zasr_squeezefact, + IVP1System* sys ); + + + + class Imp; + Imp * m_d; + +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(InDetProjHelper::PartsFlags) + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/InDetProjParams.h b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/InDetProjParams.h new file mode 100644 index 000000000..fa33c3eda --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/InDetProjParams.h @@ -0,0 +1,89 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +//////////////////////////////////////////////////////////////// +// // +// Header file for class InDetProjParams // +// // +// Description: This is our "database" of parameters for the // +// inner detector surfaces". In the future we // +// might wish to get this information from // +// geomodel instead. // +// // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: February 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef INDETPROJPARAMS_H +#define INDETPROJPARAMS_H + +class InDetProjParams { +public: + + static double surfacethickness() { return 0.3; } + + //Fixme: The pixel/sct parameters are not used at the moment, and + // are simply set to some silly values! + + static double pixel_barrel_inner_radius() { return 10; } + static double pixel_barrel_outer_radius() { return 20; } + static double pixel_barrel_posneg_z() { return 10; } + static double pixel_endcap_surface_z() { return 100; } + static double pixel_endcap_surface_length() { return 50; } + static double pixel_endcap_inner_radius() { return 20; } + static double pixel_endcap_outer_radius() { return 40; } + static double pixel_endcap_zasr_disttobarrelcyl() { return 10; }//Not used + static double pixel_endcap_zasr_squeezefact() { return 2.5; }//Not used + static double pixel_data_disttosurface_epsilon() { return 0.5; } + + static double sct_barrel_inner_radius() { return 20; } + static double sct_barrel_outer_radius() { return 40; } + static double sct_barrel_posneg_z() { return 20; } + static double sct_endcap_surface_z() { return 200; } + static double sct_endcap_surface_length() { return 100; } + static double sct_endcap_inner_radius() { return 40; } + static double sct_endcap_outer_radius() { return 80; } + static double sct_endcap_zasr_disttobarrelcyl() { return 20; }//Not used + static double sct_endcap_zasr_squeezefact() { return 2.5; }//Not used + static double sct_data_disttosurface_epsilon() { return 0.5; } + + static double trt_barrel_inner_radius() { return 540; } + static double trt_barrel_outer_radius() { return 1100; } + static double trt_barrel_posneg_z() { return 712.5+6; } + static double trt_endcap_surface_z() { return 1778.5; } + static double trt_endcap_surface_length() { return 2.0*(936.25+10); } + static double trt_endcap_inner_radius() { return 643.7-4; } + static double trt_endcap_outer_radius() { return 1004-9; } + static double trt_endcap_zasr_disttobarrelcyl() { return 20.0; } + static double trt_endcap_zasr_squeezefact() { return 2.5; } + static double trt_data_disttosurface_epsilon() { return 11.0; } + + + //Convenience: + static double pixel_endcap_zasr_innerradius() + { + return pixel_barrel_outer_radius()+pixel_endcap_zasr_disttobarrelcyl(); + } + static double sct_endcap_zasr_innerradius() + { + return sct_barrel_outer_radius()+sct_endcap_zasr_disttobarrelcyl(); + } + static double trt_endcap_zasr_innerradius() + { + return trt_barrel_outer_radius()+trt_endcap_zasr_disttobarrelcyl(); + } + + static double pixel_endcap_zasr_endcapz_begin() { return pixel_endcap_surface_z()-0.5*pixel_endcap_surface_length(); } + static double sct_endcap_zasr_endcapz_begin() { return sct_endcap_surface_z()-0.5*sct_endcap_surface_length(); } + static double trt_endcap_zasr_endcapz_begin() { return trt_endcap_surface_z()-0.5*trt_endcap_surface_length(); } + +private: + InDetProjParams(); + ~InDetProjParams(); +}; + +#endif + diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/ProjectionSurfacesHelper.h b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/ProjectionSurfacesHelper.h new file mode 100644 index 000000000..b0fe3c760 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/ProjectionSurfacesHelper.h @@ -0,0 +1,73 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class ProjectionSurfacesHelper // +// // +// Description: Helper class used to display surfaces for // +// either pixel, sct or trt. // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: February 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef PROJECTIONSURFACESHELPER_H +#define PROJECTIONSURFACESHELPER_H + +class SoSeparator; +class SoMaterial; + +#include <QObject> +#include "VP1Base/VP1HelperClassBase.h" +#include "VTI12Utils/InDetProjFlags.h" + +class ProjectionSurfacesHelper : public QObject, public VP1HelperClassBase { + + Q_OBJECT + +public: + + + //Use one of the following to create an appropriate helper + //(projection surfaces will be put under a second internal separator + //under attachsep): + static ProjectionSurfacesHelper * createPixelHelper(SoMaterial*,SoSeparator * attachsep,QObject*parent=0,IVP1System* sys = 0); + static ProjectionSurfacesHelper * createSCTHelper(SoMaterial*,SoSeparator * attachsep,QObject*parent=0,IVP1System* sys = 0); + static ProjectionSurfacesHelper * createTRTHelper(SoMaterial*,SoSeparator * attachsep,QObject*parent=0,IVP1System* sys = 0); + //(non-zero system pointers to let error messages appear in gui) + + virtual ~ProjectionSurfacesHelper(); + + //To see what parts are shown or to access (e.g. to edit) the + //material of the projection surfaces, use these two methods: + InDetProjFlags::InDetProjPartsFlags shownParts() const; + SoMaterial * material(); + +public slots: + //Use this slot to control what parts are shown (default is none): + void setSurfaces(InDetProjFlags::InDetProjPartsFlags); + +private: + + ProjectionSurfacesHelper( double surfacethickness, + double barrel_inner_radius, + double barrel_outer_radius, + double barrel_posneg_z, + double endcap_surface_z, + double endcap_surface_length, + double endcap_inner_radius, + double endcap_outer_radius, + double endcap_zasr_disttobarrelcyl, + double endcap_zasr_squeezefact, + SoMaterial*, SoSeparator * attachsep, QObject * parent, IVP1System*sys ); + + class Imp; + Imp * m_d; + +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1CartesianGrid.h b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1CartesianGrid.h new file mode 100644 index 000000000..3dbeb5bce --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1CartesianGrid.h @@ -0,0 +1,49 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1CartesianGrid // +// // +// Description: Helper class providing a cartesian grid. // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: July 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VP1CARTESIANGRID_H +#define VP1CARTESIANGRID_H + +#include "VP1Base/VP1HelperClassBase.h" +#include <QObject> +#include <Inventor/C/errors/debugerror.h> +#include <Inventor/SbColor4f.h> +class SoSeparator; + +class VP1CartesianGrid : public QObject, public VP1HelperClassBase { + + Q_OBJECT + +public: + + VP1CartesianGrid( SoSeparator * attachsep,//where the grid separator will attach itself when visible + IVP1System * sys,QObject * parent = 0); + virtual ~VP1CartesianGrid(); + +public slots: + + void setShown(bool);//will attach/detach itself from attachsep depending on this + void setColourAndTransp(const SbColor4f&); + void setExtent(const double&);//A negative value means that negative parts will be shown as well + void setSpacing(const double&); + +private: + class Imp; + Imp * m_d; + +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1CoordinateAxes.h b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1CoordinateAxes.h new file mode 100644 index 000000000..3a4cbe19d --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1CoordinateAxes.h @@ -0,0 +1,49 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1CoordinateAxes // +// // +// Description: Helper class providing coordinate axes // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: April 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VP1COORDINATEAXES_H +#define VP1COORDINATEAXES_H + +#include "VP1Base/VP1HelperClassBase.h" +#include <QObject> + +class SoMaterial; +class SoSeparator; + +class VP1CoordinateAxes : public QObject, public VP1HelperClassBase { + + Q_OBJECT + +public: + + VP1CoordinateAxes( SoMaterial * xmat,SoMaterial * ymat,SoMaterial * zmat, + SoSeparator * attachsep,//where the axis + //separator will attach + //itself when visible + IVP1System * sys,QObject * parent = 0); + virtual ~VP1CoordinateAxes(); + +public slots: + void setShown(bool);//will attach/detach itself from attachsep depending on this + void setLength(const double&);//A negative value means that negative parts will be shown as well + void setPosition(const SbVec3f&); + void setRelativeAxisThickness(const double&); +private: + class Imp; + Imp * m_d; +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1CylindricalGrid.h b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1CylindricalGrid.h new file mode 100644 index 000000000..b4b0410fe --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1CylindricalGrid.h @@ -0,0 +1,49 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1CylindricalGrid // +// // +// Description: Helper class providing a cylindrical grid. // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: July 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VP1CYLINDRICALGRID_H +#define VP1CYLINDRICALGRID_H + +#include "VP1Base/VP1HelperClassBase.h" +#include <QObject> +#include <Inventor/C/errors/debugerror.h> +#include <Inventor/SbColor4f.h> +class SoSeparator; + +class VP1CylindricalGrid : public QObject, public VP1HelperClassBase { + + Q_OBJECT + +public: + + VP1CylindricalGrid( SoSeparator * attachsep,//where the grid separator will attach itself when visible + IVP1System * sys,QObject * parent = 0); + virtual ~VP1CylindricalGrid(); + +public slots: + + void setShown(bool);//will attach/detach itself from attachsep depending on this + void setColourAndTransp(const SbColor4f&); + void setExtent(const double&);//A negative value means that negative parts will be shown as well + void setSpacing(const double&); + +private: + class Imp; + Imp * m_d; + +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1EtaCone.h b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1EtaCone.h new file mode 100644 index 000000000..446dfb101 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1EtaCone.h @@ -0,0 +1,53 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1EtaCone // +// // +// Description: Helper class providing an eta cone. // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: July 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VP1ETACONE_H +#define VP1ETACONE_H + +#include "VP1Base/VP1HelperClassBase.h" +#include <QObject> + +class SoMaterial; +class SoSeparator; + +class VP1EtaCone : public QObject, public VP1HelperClassBase { + + Q_OBJECT + +public: + + //Used in various places. Put it here to avoid copying code: + static bool calcParsFromExtentAndSpacing( VP1HelperClassBase*,const double& extent, const double& spacing, + const int& nmaxlimit, int& nmax, double& distmax ); + + VP1EtaCone( SoMaterial * mat, + SoSeparator * attachsep,//where the cone separator will attach itself when visible + IVP1System * sys,QObject * parent = 0); + virtual ~VP1EtaCone(); + +public slots: + + void setShown(bool);//will attach/detach itself from attachsep depending on this + void setExtent(const double&);//>0: extent means to a given radius, <0: extent means to a given z. + void setEtaValue(const double&); + +private: + class Imp; + Imp * m_d; + +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1Floor.h b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1Floor.h new file mode 100644 index 000000000..1921d6f8e --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1Floor.h @@ -0,0 +1,55 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1Floor // +// // +// Description: Helper class providing a floor. // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: July 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VP1FLOOR_H +#define VP1FLOOR_H + +#include "VP1Base/VP1HelperClassBase.h" +#include <QObject> +#include <Inventor/C/errors/debugerror.h> +#include <Inventor/SbColor4f.h> +class SoSeparator; + +class VP1Floor : public QObject, public VP1HelperClassBase { + + Q_OBJECT + +public: + + //Static methods used in various places. Put it here to avoid copying code: + static int nMax() { return 400; } + static bool calcParsFromExtentAndSpacing( VP1HelperClassBase*,const double& extent, const double& spacing, + const int& nmaxlimit, int& nmax, double& distmax ); + + VP1Floor( SoSeparator * attachsep,//where the floor separator will attach itself when visible + IVP1System * sys,QObject * parent = 0); + virtual ~VP1Floor(); + +public slots: + + void setShown(bool);//will attach/detach itself from attachsep depending on this + void setColourAndTransp(const SbColor4f&); + void setExtent(const double&);//A negative value means that negative parts will be shown as well + void setSpacing(const double&); + void setVerticalPosition(const double&); + +private: + class Imp; + Imp * m_d; + +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1GuideLineSystem.h b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1GuideLineSystem.h new file mode 100644 index 000000000..15e99042d --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1GuideLineSystem.h @@ -0,0 +1,78 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef VP1GUIDELINESYSTEM_H +#define VP1GUIDELINESYSTEM_H + +///////////////////////////////////////////////////////////////////////// +// // +// Header file for class VP1GuideLineSystem // +// // +// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Initial version: July 2007 // +// // +///////////////////////////////////////////////////////////////////////// + +#include "VP1Base/IVP13DSystemSimple.h" +#include "VTI12Utils/InDetProjFlags.h" +#include <QColor>//Fixme obsolete + +class VP1GuideLineSystem : public IVP13DSystemSimple { + + Q_OBJECT + +public: + + /////////////////// + // Constructor // + /////////////////// + + VP1GuideLineSystem(); + + ////////////////////////////////////////// + // Reimplementations from base class: // + ////////////////////////////////////////// + + virtual ~VP1GuideLineSystem(); + void buildPermanentSceneGraph(StoreGateSvc* detstore, SoSeparator *root); + void buildEventSceneGraph(StoreGateSvc*, SoSeparator *); + void systemuncreate(); + QWidget * buildController(); + QByteArray saveState(); + void restoreFromState(QByteArray ba); + + //////////////////////////////////////////// + // Signals/slots for InDet Projections: // + //////////////////////////////////////////// + +public slots: + + //To automatically show projection surfaces depending on data + //projected to those (NB: Several senders can connect to this slot, + //and the final result will be a union of the requested parts): + // + //As elsewhere, it is important that senders emit signals with + //InDetProjFlags::NoDet in their systemerase(). + void setIDDetTypesUsingProjections( InDetProjFlags::DetTypeFlags ); + + //Channel should explicitly call this after making all connections to other systems. + void possiblyEmit_ApplicableProjectionsChanged(); + +signals: + + //So data systems can automatically project to the correct surfaces + //(of course, when the surfaces are "off" in the guide line system, + //they will not be rendered, but they will still be the ones used + //for projections: + void applicableProjectionsChanged( InDetProjFlags::InDetProjPartsFlags pixel, + InDetProjFlags::InDetProjPartsFlags sct, + InDetProjFlags::InDetProjPartsFlags trt ); + +private: + class Imp; + Imp * m_d; +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1Letters.h b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1Letters.h new file mode 100644 index 000000000..20171a8a3 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1Letters.h @@ -0,0 +1,48 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1Letters // +// // +// Description: Helper class providing a letters. // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: July 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VP1LETTERS_H +#define VP1LETTERS_H + +#include "VP1Base/VP1HelperClassBase.h" +#include <QObject> + +class SoMaterial; +class SoSeparator; + +class VP1Letters : public QObject, public VP1HelperClassBase { + + Q_OBJECT + +public: + + VP1Letters( SoMaterial * mat, + SoSeparator * attachsep,//where the letters separator will attach itself when visible + IVP1System * sys,QObject * parent = 0); + virtual ~VP1Letters(); + +public slots: + void setShown(bool);//will attach/detach itself from attachsep depending on this + void setZPos(const double&); + void setVerticalPosition(const double&); + +private: + class Imp; + Imp * m_d; + +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1Lines.h b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1Lines.h new file mode 100644 index 000000000..d35194613 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1Lines.h @@ -0,0 +1,35 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef VP1LINES_H +#define VP1LINES_H + +#include "VP1Base/VP1HelperClassBase.h" +#include <QObject> +#include <Inventor/C/errors/debugerror.h> +#include <Inventor/SbColor4f.h> +class SoSeparator; + +class VP1Lines : public QObject, public VP1HelperClassBase { + + Q_OBJECT + +public: + + VP1Lines( SoSeparator * attachsep,//where the grid separator will attach itself when visible + IVP1System * sys,QObject * parent = 0); + virtual ~VP1Lines(); + +public slots: + + void setShown(bool);//will attach/detach itself from attachsep depending on this + void setColourAndTransp(const SbColor4f&); + void setDirection(const SbVec3f&); + +private: + class Imp; + Imp * m_d; +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1TrackingVolumes.h b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1TrackingVolumes.h new file mode 100644 index 000000000..bcbbc96dd --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/VTI12GuideLineSystems/VP1TrackingVolumes.h @@ -0,0 +1,51 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1TrackingVolumes // +// // +// Description: Helper class providing coordinate axes // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: April 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VP1TRACKINGVOLUMES_H +#define VP1TRACKINGVOLUMES_H + +#include "VP1Base/VP1HelperClassBase.h" +#include <QObject> + +class SoMaterial; +class SoSeparator; + +class VP1TrackingVolumes : public QObject, public VP1HelperClassBase { + + Q_OBJECT + +public: + + VP1TrackingVolumes( SoMaterial * materialID,SoMaterial * materialCalo,SoMaterial * materialMS, + bool showID, bool showCalo, bool showMS, + SoSeparator * attachsep,//where the vol + //separator will attach + //itself when visible + IVP1System * sys,QObject * parent = 0); + virtual ~VP1TrackingVolumes(); + +public slots: + void setShown(bool);//!< will attach/detach itself from attachsep depending on this + void setShownID(bool);//!< will attach/detach ID from sep depending on this + void setShownCalo(bool);//!< will attach/detach Calo from sep depending on this + void setShownMS(bool);//!< will attach/detach MS from sep depending on this + +private: + class Imp; + Imp * m_d; +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/GuideSysController.cxx b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/GuideSysController.cxx new file mode 100644 index 000000000..641b5b598 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/GuideSysController.cxx @@ -0,0 +1,1072 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class GuideSysController // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: July 2008 // +// // +//////////////////////////////////////////////////////////////// + +#define VP1IMPVARNAME m_d + +#include "VTI12GuideLineSystems/GuideSysController.h" +#include "VTI12GuideLineSystems/VP1Floor.h" +#include "ui_guidelinescontrollerform.h" +#include "ui_guides_settings_coordinateaxes_form.h" +#include "ui_guides_settings_etacones_form.h" +#include "ui_guides_settings_floorandletters_form.h" +#include "ui_guides_settings_grid_form.h" +#include "ui_guides_settings_idprojsurfs_form.h" +#include "ui_guides_settings_trkvolumes_form.h" +#include "ui_guides_settings_lines_form.h" +#include "VP1Base/VP1Serialise.h" +#include "VP1Base/VP1Deserialise.h" + +// System of units +#ifdef BUILDVP1LIGHT + #include "GeoModelKernel/Units.h" + #define SYSTEM_OF_UNITS GeoModelKernelUnits // --> 'GeoModelKernelUnits::cm' +#else + #include "GaudiKernel/SystemOfUnits.h" + #define SYSTEM_OF_UNITS Gaudi::Units // --> 'Gaudi::Units::cm' +#endif + +#include <cmath> + +//____________________________________________________________________ +class GuideSysController::Imp { +public: + GuideSysController * theclass; + Ui::VP1GuidesControllerForm ui; + Ui::VP1GuidesSysSettingsCoordinateAxesForm ui_axes; + Ui::VP1GuidesSysSettingsEtaConeForm ui_etacones; + Ui::VP1GuidesSysSettingsFloorAndLettersForm ui_floorandletters; + Ui::VP1GuidesSysSettingsGridForm ui_grid; + Ui::VP1GuidesSysSettingsIDProjSurfsForm ui_idprojsurfs; + Ui::VP1TrackingVolumesForm ui_trkvolumes; + Ui::VP1LinesForm ui_lines; + + static SbColor4f color4f(const QColor& col, int transp_int) { + return SbColor4f(std::max<float>(0.0f,std::min<float>(1.0f,col.redF())), + std::max<float>(0.0f,std::min<float>(1.0f,col.greenF())), + std::max<float>(0.0f,std::min<float>(1.0f,col.blueF())), + std::max<float>(0.0f,std::min<float>(1.0f,1.0-transp_int/100.0))); + } + + InDetProjFlags::DetTypeFlags inDetDetTypesUsingProjections; + + bool last_showFloor; + SbColor4f last_floorColourAndTransp; + double last_floorExtent; + double last_floorSpacing; + double last_floorHeight; + bool last_showLetters; + double last_lettersZPos; + double last_lettersVerticalPos; + bool last_showAxes; + double last_axesLength; + SbVec3f last_axesPosition; + double last_relAxesThickness; + bool last_showCartesianGrid; + bool last_showCylindricalGrid; + SbColor4f last_gridColourAndTransp; + double last_gridSpacing; + double last_gridExtent; + bool last_showEtaCone1; + bool last_showEtaCone2; + bool last_showEtaCone3; + double last_etaConeValue1; + double last_etaConeValue2; + double last_etaConeValue3; + double last_etaExtent; + bool last_showTrackingVolumes; + bool last_showInnerDetector; + bool last_showCalorimeters; + bool last_showMuonSpectrometer; + bool last_showLines; + SbVec3f last_lineDirection; + double last_line_eta; // This is needed to update the display in possibleChange_lineDirection + + InDetProjFlags::InDetProjPartsFlags last_applicablePixelProjParts; + InDetProjFlags::InDetProjPartsFlags last_applicableSCTProjParts; + InDetProjFlags::InDetProjPartsFlags last_applicableTRTProjParts; + InDetProjFlags::InDetProjPartsFlags last_shownPixelProjSurfaces; + InDetProjFlags::InDetProjPartsFlags last_shownSCTProjSurfaces; + InDetProjFlags::InDetProjPartsFlags last_shownTRTProjSurfaces; + + static InDetProjFlags::InDetProjPartsFlags projPartsFlag( bool barrelinner, bool barrelouter, + bool endcapinner, bool endcapouter, + bool endcap_hidenormalcyls_when_zasr = false, + bool endcap_zasr = false ); + InDetProjFlags::DetTypeFlags pixelPartsEnabledByGUIOrDataUsage() const; + InDetProjFlags::DetTypeFlags sctPartsEnabledByGUIOrDataUsage() const; + InDetProjFlags::DetTypeFlags trtPartsEnabledByGUIOrDataUsage() const; +}; + +//____________________________________________________________________ +GuideSysController::GuideSysController(IVP1System * sys) + : VP1Controller(sys,"GuideSysController"), m_d(new Imp) +{ + m_d->theclass = this; + m_d->ui.setupUi(this); + + initDialog(m_d->ui_axes, m_d->ui.pushButton_settings_coordinateAxes,m_d->ui.checkBox_coordinateAxes); + initDialog(m_d->ui_etacones, m_d->ui.pushButton_settings_etaCones,m_d->ui.checkBox_etaCones); + initDialog(m_d->ui_floorandletters, m_d->ui.pushButton_settings_floorAndLetters,m_d->ui.checkBox_floorAndLetters); + initDialog(m_d->ui_grid, m_d->ui.pushButton_settings_grid,m_d->ui.checkBox_grid); + initDialog(m_d->ui_idprojsurfs, m_d->ui.pushButton_settings_inDetProjSurfs,m_d->ui.checkBox_inDetProjSurfs); + initDialog(m_d->ui_trkvolumes, m_d->ui.pushButton_settings_trkVolumes,m_d->ui.checkBox_trkVolumes); + initDialog(m_d->ui_lines, m_d->ui.pushButton_settings_lines,m_d->ui.checkBox_lines); + + //Hide SCT/Pixel projection surface controls for now: + m_d->ui_idprojsurfs.groupBox_pixelproj->setVisible(false); + m_d->ui_idprojsurfs.groupBox_sctproj->setVisible(false); + + //Since we have different logical groups of radio buttons inside + //same groupboxes, we make sure they are coordinated correctly: + + QButtonGroup * pixelproj_barrel_radiogroup = defineRadioButtonGroup(m_d->ui_idprojsurfs.radioButton_pixelprojsurf_barrel_inner, + m_d->ui_idprojsurfs.radioButton_pixelprojsurf_barrel_outer, + m_d->ui_idprojsurfs.radioButton_pixelprojsurf_barrel_both); + m_d->ui_idprojsurfs.radioButton_pixelprojsurf_barrel_inner->setChecked(true); + QButtonGroup * pixelproj_endcap_radiogroup = defineRadioButtonGroup(m_d->ui_idprojsurfs.radioButton_pixelprojsurf_endcap_inner, + m_d->ui_idprojsurfs.radioButton_pixelprojsurf_endcap_outer, + m_d->ui_idprojsurfs.radioButton_pixelprojsurf_endcap_both); + m_d->ui_idprojsurfs.radioButton_pixelprojsurf_endcap_inner->setChecked(true); + + + QButtonGroup * sctproj_barrel_radiogroup = defineRadioButtonGroup(m_d->ui_idprojsurfs.radioButton_sctprojsurf_barrel_inner, + m_d->ui_idprojsurfs.radioButton_sctprojsurf_barrel_outer, + m_d->ui_idprojsurfs.radioButton_sctprojsurf_barrel_both); + m_d->ui_idprojsurfs.radioButton_sctprojsurf_barrel_inner->setChecked(true); + QButtonGroup * sctproj_endcap_radiogroup = defineRadioButtonGroup(m_d->ui_idprojsurfs.radioButton_sctprojsurf_endcap_inner, + m_d->ui_idprojsurfs.radioButton_sctprojsurf_endcap_outer, + m_d->ui_idprojsurfs.radioButton_sctprojsurf_endcap_both); + m_d->ui_idprojsurfs.radioButton_sctprojsurf_endcap_inner->setChecked(true); + + + QButtonGroup * trtproj_barrel_radiogroup = defineRadioButtonGroup(m_d->ui_idprojsurfs.radioButton_trtprojsurf_barrel_inner, + m_d->ui_idprojsurfs.radioButton_trtprojsurf_barrel_outer, + m_d->ui_idprojsurfs.radioButton_trtprojsurf_barrel_both); + m_d->ui_idprojsurfs.radioButton_trtprojsurf_barrel_inner->setChecked(true); + QButtonGroup * trtproj_endcap_radiogroup = defineRadioButtonGroup(m_d->ui_idprojsurfs.radioButton_trtprojsurf_endcap_inner, + m_d->ui_idprojsurfs.radioButton_trtprojsurf_endcap_outer, + m_d->ui_idprojsurfs.radioButton_trtprojsurf_endcap_both); + m_d->ui_idprojsurfs.radioButton_trtprojsurf_endcap_inner->setChecked(true); + + //Setup material buttons: + m_d->ui_floorandletters.colorButton_floor->setColor(QColor::fromRgbF(0.5,0.5,0.5)); + m_d->ui_grid.colorButton_grid->setColor(QColor::fromRgbF(1.0,1.0,1.0)); + m_d->ui_floorandletters.matButton_letters->setMaterial(VP1MaterialButton::createMaterial(0.5,0.5,0.5,0.1)); + m_d->ui_axes.matButton_axes_x->setMaterial(VP1MaterialButton::createMaterial(1,0,0,0.15)); + m_d->ui_axes.matButton_axes_y->setMaterial(VP1MaterialButton::createMaterial(0,1,0,0.15)); + m_d->ui_axes.matButton_axes_z->setMaterial(VP1MaterialButton::createMaterial(0,0,2,0.15)); + m_d->ui_etacones.matButton_etaCone1->setMaterial(VP1MaterialButton::createMaterial(1,1,0,0.2,0.5)); + m_d->ui_etacones.matButton_etaCone2->setMaterial(VP1MaterialButton::createMaterial(1,0.56471,0.20784,0.2,0.5)); + m_d->ui_etacones.matButton_etaCone3->setMaterial(VP1MaterialButton::createMaterial(1,0.15686,0.08235,0.2,0.5)); + m_d->ui_idprojsurfs.pushButton_projsurfmaterial_pixel->setMaterial(VP1MaterialButton::createMaterial(126/255.0, 194/255.0, 204/255.0,0.05,0.35)); + m_d->ui_idprojsurfs.pushButton_projsurfmaterial_sct->setMaterial(VP1MaterialButton::createMaterial(126/255.0, 194/255.0, 204/255.0,0.05,0.35)); + m_d->ui_idprojsurfs.pushButton_projsurfmaterial_trt->setMaterial(VP1MaterialButton::createMaterial(126/255.0, 194/255.0, 204/255.0,0.05,0.35)); + m_d->ui_trkvolumes.matButton_ID->setMaterial(VP1MaterialButton::createMaterial(1,0,0,0.15)); + m_d->ui_trkvolumes.matButton_Calo->setMaterial(VP1MaterialButton::createMaterial(0,1,0,0.15)); + m_d->ui_trkvolumes.matButton_MS->setMaterial(VP1MaterialButton::createMaterial(0,0,2,0.15)); + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Setup connections which monitor changes in the controller so that we may emit signals as appropriate: // + ///////////////////////////////////////////////////////////////////////////////////////////////////////////// + + addUpdateSlot(SLOT(possibleChange_showFloor())); + connectToLastUpdateSlot(m_d->ui.checkBox_floorAndLetters); + connectToLastUpdateSlot(m_d->ui_floorandletters.checkBox_floorenabled); + + addUpdateSlot(SLOT(possibleChange_floorColourAndTransp())); + connectToLastUpdateSlot(m_d->ui_floorandletters.colorButton_floor); + connectToLastUpdateSlot(m_d->ui_floorandletters.spinBox_floortransp); + + addUpdateSlot(SLOT(possibleChange_floorExtent())); + connectToLastUpdateSlot(m_d->ui_floorandletters.doubleSpinBox_floorextent); + + addUpdateSlot(SLOT(possibleChange_floorSpacing())); + connectToLastUpdateSlot(m_d->ui_floorandletters.doubleSpinBox_floorspacing); + + addUpdateSlot(SLOT(possibleChange_floorHeight())); + connectToLastUpdateSlot(m_d->ui_floorandletters.doubleSpinBox_floorheight); + + addUpdateSlot(SLOT(possibleChange_showLetters())); + connectToLastUpdateSlot(m_d->ui.checkBox_floorAndLetters); + connectToLastUpdateSlot(m_d->ui_floorandletters.checkBox_acdesignations); + + addUpdateSlot(SLOT(possibleChange_lettersZPos())); + connectToLastUpdateSlot(this,SIGNAL(floorExtentChanged(const double&))); + connectToLastUpdateSlot(this,SIGNAL(floorSpacingChanged(const double&))); + + addUpdateSlot(SLOT(possibleChange_lettersVerticalPos())); + connectToLastUpdateSlot(this,SIGNAL(floorHeightChanged(const double&))); + + addUpdateSlot(SLOT(possibleChange_showAxes())); + connectToLastUpdateSlot(m_d->ui.checkBox_coordinateAxes); + + addUpdateSlot(SLOT(possibleChange_axesLength())); + connectToLastUpdateSlot(m_d->ui_axes.checkBox_axes_shownegativeparts); + connectToLastUpdateSlot(m_d->ui_axes.doubleSpinBox_axes_lengths_m); + + addUpdateSlot(SLOT(possibleChange_axesPosition())); + connectToLastUpdateSlot(m_d->ui_axes.doubleSpinBox_axes_xpos_m); + connectToLastUpdateSlot(m_d->ui_axes.doubleSpinBox_axes_ypos_m); + connectToLastUpdateSlot(m_d->ui_axes.doubleSpinBox_axes_zpos_m); + + addUpdateSlot(SLOT(possibleChange_relAxesThickness())); + connectToLastUpdateSlot(m_d->ui_axes.doubleSpinBox_axes_relthickness); + + addUpdateSlot(SLOT(possibleChange_showCartesianGrid())); + connectToLastUpdateSlot(m_d->ui.checkBox_grid); + connectToLastUpdateSlot(m_d->ui_grid.radioButton_grid_cartesian); + + addUpdateSlot(SLOT(possibleChange_showCylindricalGrid())); + connectToLastUpdateSlot(m_d->ui.checkBox_grid); + connectToLastUpdateSlot(m_d->ui_grid.radioButton_grid_cylindrical); + + addUpdateSlot(SLOT(possibleChange_gridColourAndTransp())); + connectToLastUpdateSlot(m_d->ui_grid.colorButton_grid); + connectToLastUpdateSlot(m_d->ui_grid.spinBox_gridtransp); + + addUpdateSlot(SLOT(possibleChange_gridSpacing())); + connectToLastUpdateSlot(m_d->ui_grid.doubleSpinBox_gridspacing); + + addUpdateSlot(SLOT(possibleChange_gridExtent())); + connectToLastUpdateSlot(m_d->ui_grid.doubleSpinBox_gridextent); + + addUpdateSlot(SLOT(possibleChange_showEtaCone1())); + connectToLastUpdateSlot(m_d->ui.checkBox_etaCones); + connectToLastUpdateSlot(m_d->ui_etacones.checkBox_etacone1); + + addUpdateSlot(SLOT(possibleChange_showEtaCone2())); + connectToLastUpdateSlot(m_d->ui.checkBox_etaCones); + connectToLastUpdateSlot(m_d->ui_etacones.checkBox_etacone2); + + addUpdateSlot(SLOT(possibleChange_showEtaCone3())); + connectToLastUpdateSlot(m_d->ui.checkBox_etaCones); + connectToLastUpdateSlot(m_d->ui_etacones.checkBox_etacone3); + + addUpdateSlot(SLOT(possibleChange_etaConeValue1())); + connectToLastUpdateSlot(m_d->ui_etacones.doubleSpinBox_etaval1); + + addUpdateSlot(SLOT(possibleChange_etaConeValue2())); + connectToLastUpdateSlot(m_d->ui_etacones.doubleSpinBox_etaval2); + + addUpdateSlot(SLOT(possibleChange_etaConeValue3())); + connectToLastUpdateSlot(m_d->ui_etacones.doubleSpinBox_etaval3); + + addUpdateSlot(SLOT(possibleChange_etaExtent())); + connectToLastUpdateSlot(m_d->ui_etacones.doubleSpinBox_etaconeextent); + connectToLastUpdateSlot(m_d->ui_etacones.radioButton_etaconeextentisr); + + addUpdateSlot(SLOT(possibleChange_applicablePixelProjParts())); + connectToLastUpdateSlot(pixelproj_barrel_radiogroup); + connectToLastUpdateSlot(pixelproj_endcap_radiogroup); + + addUpdateSlot(SLOT(possibleChange_applicableSCTProjParts())); + connectToLastUpdateSlot(sctproj_barrel_radiogroup); + connectToLastUpdateSlot(sctproj_endcap_radiogroup); + + addUpdateSlot(SLOT(possibleChange_applicableTRTProjParts())); + connectToLastUpdateSlot(trtproj_barrel_radiogroup); + connectToLastUpdateSlot(trtproj_endcap_radiogroup); + connectToLastUpdateSlot(m_d->ui_idprojsurfs.checkBox_trtprojsurf_z2r); + + addUpdateSlot(SLOT(possibleChange_shownPixelProjSurfaces())); + connectToLastUpdateSlot(m_d->ui.checkBox_inDetProjSurfs); + connectToLastUpdateSlot(this,SIGNAL(applicablePixelProjPartsChanged(InDetProjFlags::InDetProjPartsFlags))); + connectToLastUpdateSlot(m_d->ui_idprojsurfs.groupBox_pixelproj); + connectToLastUpdateSlot(m_d->ui_idprojsurfs.checkBox_pixelprojsurf_parts_asneeded); + connectToLastUpdateSlot(m_d->ui_idprojsurfs.checkBox_pixelprojsurf_parts_barrelA); + connectToLastUpdateSlot(m_d->ui_idprojsurfs.checkBox_pixelprojsurf_parts_barrelC); + connectToLastUpdateSlot(m_d->ui_idprojsurfs.checkBox_pixelprojsurf_parts_endcapA); + connectToLastUpdateSlot(m_d->ui_idprojsurfs.checkBox_pixelprojsurf_parts_endcapC); + + addUpdateSlot(SLOT(possibleChange_shownSCTProjSurfaces())); + connectToLastUpdateSlot(m_d->ui.checkBox_inDetProjSurfs); + connectToLastUpdateSlot(this,SIGNAL(applicableSCTProjPartsChanged(InDetProjFlags::InDetProjPartsFlags))); + connectToLastUpdateSlot(m_d->ui_idprojsurfs.groupBox_sctproj); + connectToLastUpdateSlot(m_d->ui_idprojsurfs.checkBox_sctprojsurf_parts_asneeded); + connectToLastUpdateSlot(m_d->ui_idprojsurfs.checkBox_sctprojsurf_parts_barrelA); + connectToLastUpdateSlot(m_d->ui_idprojsurfs.checkBox_sctprojsurf_parts_barrelC); + connectToLastUpdateSlot(m_d->ui_idprojsurfs.checkBox_sctprojsurf_parts_endcapA); + connectToLastUpdateSlot(m_d->ui_idprojsurfs.checkBox_sctprojsurf_parts_endcapC); + + addUpdateSlot(SLOT(possibleChange_shownTRTProjSurfaces())); + connectToLastUpdateSlot(m_d->ui.checkBox_inDetProjSurfs); + connectToLastUpdateSlot(this,SIGNAL(applicableTRTProjPartsChanged(InDetProjFlags::InDetProjPartsFlags))); + connectToLastUpdateSlot(m_d->ui_idprojsurfs.groupBox_trtproj); + connectToLastUpdateSlot(m_d->ui_idprojsurfs.checkBox_trtprojsurf_parts_asneeded); + connectToLastUpdateSlot(m_d->ui_idprojsurfs.checkBox_trtprojsurf_parts_barrelA); + connectToLastUpdateSlot(m_d->ui_idprojsurfs.checkBox_trtprojsurf_parts_barrelC); + connectToLastUpdateSlot(m_d->ui_idprojsurfs.checkBox_trtprojsurf_parts_endcapA); + connectToLastUpdateSlot(m_d->ui_idprojsurfs.checkBox_trtprojsurf_parts_endcapC); + + addUpdateSlot(SLOT(updateProjPartsCheckboxStates_Pixel())); + connectToLastUpdateSlot(m_d->ui_idprojsurfs.checkBox_pixelprojsurf_parts_asneeded); + + addUpdateSlot(SLOT(updateProjPartsCheckboxStates_SCT())); + connectToLastUpdateSlot(m_d->ui_idprojsurfs.checkBox_sctprojsurf_parts_asneeded); + + addUpdateSlot(SLOT(updateProjPartsCheckboxStates_TRT())); + connectToLastUpdateSlot(m_d->ui_idprojsurfs.checkBox_trtprojsurf_parts_asneeded); + + addUpdateSlot(SLOT(possibleChange_showTrackingVolumes())); + connectToLastUpdateSlot(m_d->ui.checkBox_trkVolumes); + + addUpdateSlot(SLOT(possibleChange_showInnerDetector())); + connectToLastUpdateSlot(m_d->ui_trkvolumes.checkBox_ID); + addUpdateSlot(SLOT(possibleChange_showCalorimeters())); + connectToLastUpdateSlot(m_d->ui_trkvolumes.checkBox_Calo); + addUpdateSlot(SLOT(possibleChange_showMuonSpectrometer())); + connectToLastUpdateSlot(m_d->ui_trkvolumes.checkBox_MS); + + addUpdateSlot(SLOT(possibleChange_showLines())); + connectToLastUpdateSlot(m_d->ui.checkBox_lines); + + addUpdateSlot(SLOT(possibleChange_lineDirection())); + connectToLastUpdateSlot(m_d->ui_lines.doubleSpinBox_phi); + connectToLastUpdateSlot(m_d->ui_lines.doubleSpinBox_theta); + connectToLastUpdateSlot(m_d->ui_lines.doubleSpinBox_eta); + connectToLastUpdateSlot(m_d->ui_lines.doubleSpinBox_length); + + + initLastVars(); +} + +//____________________________________________________________________ +GuideSysController::~GuideSysController() +{ + delete m_d; +} + +//____________________________________________________________________ +//Material access methods: +SoMaterial * GuideSysController::lettersMaterial() const { return m_d->ui_floorandletters.matButton_letters->handledMaterials().at(0); } +SoMaterial * GuideSysController::xAxisMaterial() const { return m_d->ui_axes.matButton_axes_x->handledMaterials().at(0); } +SoMaterial * GuideSysController::yAxisMaterial() const { return m_d->ui_axes.matButton_axes_y->handledMaterials().at(0); } +SoMaterial * GuideSysController::zAxisMaterial() const { return m_d->ui_axes.matButton_axes_z->handledMaterials().at(0); } +SoMaterial * GuideSysController::etaCone1Material() const { return m_d->ui_etacones.matButton_etaCone1->handledMaterials().at(0); } +SoMaterial * GuideSysController::etaCone2Material() const { return m_d->ui_etacones.matButton_etaCone2->handledMaterials().at(0); } +SoMaterial * GuideSysController::etaCone3Material() const { return m_d->ui_etacones.matButton_etaCone3->handledMaterials().at(0); } +SoMaterial * GuideSysController::pixelProjSurfMaterial() const { return m_d->ui_idprojsurfs.pushButton_projsurfmaterial_pixel->handledMaterials().at(0); } +SoMaterial * GuideSysController::sctProjSurfMaterial() const { return m_d->ui_idprojsurfs.pushButton_projsurfmaterial_sct->handledMaterials().at(0); } +SoMaterial * GuideSysController::trtProjSurfMaterial() const { return m_d->ui_idprojsurfs.pushButton_projsurfmaterial_trt->handledMaterials().at(0); } +SoMaterial * GuideSysController::idTrkVolumesMaterial() const { return m_d->ui_trkvolumes.matButton_ID->handledMaterials().at(0); } +SoMaterial * GuideSysController::caloTrkVolumesMaterial() const { return m_d->ui_trkvolumes.matButton_Calo->handledMaterials().at(0); } +SoMaterial * GuideSysController::msTrkVolumesMaterial() const { return m_d->ui_trkvolumes.matButton_MS->handledMaterials().at(0); } + +//____________________________________________________________________ +bool GuideSysController::showFloor() const +{ + return m_d->ui.checkBox_floorAndLetters->isChecked() && + m_d->ui_floorandletters.checkBox_floorenabled->isChecked(); +} + +//____________________________________________________________________ +SbColor4f GuideSysController::floorColourAndTransp() const +{ + return Imp::color4f(m_d->ui_floorandletters.colorButton_floor->color(),m_d->ui_floorandletters.spinBox_floortransp->value()); +} + +//____________________________________________________________________ +double GuideSysController::floorExtent() const +{ + return m_d->ui_floorandletters.doubleSpinBox_floorextent->value()*SYSTEM_OF_UNITS::m; +} + +//____________________________________________________________________ +double GuideSysController::floorSpacing() const +{ + return m_d->ui_floorandletters.doubleSpinBox_floorspacing->value()*SYSTEM_OF_UNITS::m; +} + +//____________________________________________________________________ +double GuideSysController::floorHeight() const +{ + return m_d->ui_floorandletters.doubleSpinBox_floorheight->value()*SYSTEM_OF_UNITS::m; +} + +//____________________________________________________________________ +bool GuideSysController::showLetters() const +{ + return m_d->ui.checkBox_floorAndLetters->isChecked() && + m_d->ui_floorandletters.checkBox_acdesignations->isChecked(); +} + +//____________________________________________________________________ +double GuideSysController::lettersZPos() const +{ + + int nmax; double distmax; + if (!VP1Floor::calcParsFromExtentAndSpacing( (VP1HelperClassBase*)this, floorExtent(), floorSpacing(), VP1Floor::nMax(), nmax, distmax )) { + nmax = 10; + distmax = 10*SYSTEM_OF_UNITS::m; + message("lettersZPos ERROR: Problems calculating floor nmax/distmax."); + } + return distmax*1.1; +} + +//____________________________________________________________________ +double GuideSysController::lettersVerticalPos() const +{ + return floorHeight()+1.5*SYSTEM_OF_UNITS::m; +} + +//____________________________________________________________________ +bool GuideSysController::showAxes() const +{ + return m_d->ui.checkBox_coordinateAxes->isChecked(); +} + +//____________________________________________________________________ +double GuideSysController::axesLength() const +{ + return m_d->ui_axes.doubleSpinBox_axes_lengths_m->value()*SYSTEM_OF_UNITS::m * + (m_d->ui_axes.checkBox_axes_shownegativeparts->isChecked()?-1.0:1.0); +} + +//____________________________________________________________________ +SbVec3f GuideSysController::axesPosition() const +{ + return SbVec3f(m_d->ui_axes.doubleSpinBox_axes_xpos_m->value()*SYSTEM_OF_UNITS::m, + m_d->ui_axes.doubleSpinBox_axes_ypos_m->value()*SYSTEM_OF_UNITS::m, + m_d->ui_axes.doubleSpinBox_axes_zpos_m->value()*SYSTEM_OF_UNITS::m); +} + +//____________________________________________________________________ +double GuideSysController::relAxesThickness() const +{ + return m_d->ui_axes.doubleSpinBox_axes_relthickness->value(); +} + +//____________________________________________________________________ +bool GuideSysController::showCartesianGrid() const +{ + return m_d->ui.checkBox_grid->isChecked() && + m_d->ui_grid.radioButton_grid_cartesian->isChecked(); +} + +//____________________________________________________________________ +bool GuideSysController::showCylindricalGrid() const +{ + return m_d->ui.checkBox_grid->isChecked() && + m_d->ui_grid.radioButton_grid_cylindrical->isChecked(); +} + +//____________________________________________________________________ +SbColor4f GuideSysController::gridColourAndTransp() const +{ + return Imp::color4f(m_d->ui_grid.colorButton_grid->color(),m_d->ui_grid.spinBox_gridtransp->value()); +} + +//____________________________________________________________________ +double GuideSysController::gridSpacing() const +{ + return m_d->ui_grid.doubleSpinBox_gridspacing->value()*SYSTEM_OF_UNITS::m; +} + +//____________________________________________________________________ +double GuideSysController::gridExtent() const +{ + return m_d->ui_grid.doubleSpinBox_gridextent->value()*SYSTEM_OF_UNITS::m; +} + +//____________________________________________________________________ +bool GuideSysController::showEtaCone1() const +{ + return m_d->ui.checkBox_etaCones->isChecked() && + m_d->ui_etacones.checkBox_etacone1->isChecked(); +} + +//____________________________________________________________________ +bool GuideSysController::showEtaCone2() const +{ + return m_d->ui.checkBox_etaCones->isChecked() && + m_d->ui_etacones.checkBox_etacone2->isChecked(); +} + +//____________________________________________________________________ +bool GuideSysController::showEtaCone3() const +{ + return m_d->ui.checkBox_etaCones->isChecked() && + m_d->ui_etacones.checkBox_etacone3->isChecked(); +} + +//____________________________________________________________________ +double GuideSysController::etaConeValue1() const +{ + return std::max(1.0e-5,m_d->ui_etacones.doubleSpinBox_etaval1->value()); +} + +//____________________________________________________________________ +double GuideSysController::etaConeValue2() const +{ + return std::max(1.0e-5,m_d->ui_etacones.doubleSpinBox_etaval2->value()); +} + +//____________________________________________________________________ +double GuideSysController::etaConeValue3() const +{ + return std::max(1.0e-5,m_d->ui_etacones.doubleSpinBox_etaval3->value()); +} + +//____________________________________________________________________ +double GuideSysController::etaExtent() const +{ + return m_d->ui_etacones.doubleSpinBox_etaconeextent->value() * SYSTEM_OF_UNITS::m + * (m_d->ui_etacones.radioButton_etaconeextentisr->isChecked() ? 1.0 : -1.0); +} + +//____________________________________________________________________ +bool GuideSysController::showLines() const +{ + return m_d->ui.checkBox_lines->isChecked(); +} + + +//____________________________________________________________________ +SbVec3f GuideSysController::lineDirection() const +{ + double r = lineLength(); + double phi = m_d->ui_lines.doubleSpinBox_phi->value(); + double theta = m_d->ui_lines.doubleSpinBox_theta->value(); + SbVec3f direction(r*sin(theta)*cos(phi),r*sin(theta)*sin(phi), r*cos(theta)); + return direction; +} + +//____________________________________________________________________ +double GuideSysController::lineLength() const +{ + return m_d->ui_lines.doubleSpinBox_length->value() * SYSTEM_OF_UNITS::m; +} + +//_____________________________________________________________________________________ +InDetProjFlags::InDetProjPartsFlags GuideSysController::Imp::projPartsFlag( bool barrelinner, bool barrelouter, + bool endcapinner, bool endcapouter, + bool endcap_hidenormalcyls_when_zasr, + bool endcap_zasr ) +{ + InDetProjFlags::InDetProjPartsFlags parts(InDetProjFlags::NoProjections); + //Given the general parts needed, what specific surfaces do we need: + if ( barrelinner ) + parts |= InDetProjFlags::BarrelCentral; + if ( barrelouter ) { + parts |= InDetProjFlags::BarrelPositive; + parts |= InDetProjFlags::BarrelNegative; + } + + if ( !( endcap_zasr && endcap_hidenormalcyls_when_zasr ) ) { + if ( endcapinner ) { + //Inner: + parts |= InDetProjFlags::EndCapInnerPositive; + parts |= InDetProjFlags::EndCapInnerNegative; + } + if ( endcapouter ) { + //Outer: + parts |= InDetProjFlags::EndCapOuterPositive; + parts |= InDetProjFlags::EndCapOuterNegative; + } + } + //Special ZasR surfaces for the endcaps, placed in the barrel positions: + if (endcap_zasr) { + if ( barrelinner ) + parts |= InDetProjFlags::TRT_EndCapZToRCentral; + if ( barrelouter ) { + parts |= InDetProjFlags::TRT_EndCapZToRPositive; + parts |= InDetProjFlags::TRT_EndCapZToRNegative; + } + } + return parts; +} + +//____________________________________________________________________ +InDetProjFlags::InDetProjPartsFlags GuideSysController::applicablePixelProjParts() const +{ + return Imp::projPartsFlag( m_d->ui_idprojsurfs.radioButton_pixelprojsurf_barrel_inner->isChecked() || m_d->ui_idprojsurfs.radioButton_pixelprojsurf_barrel_both->isChecked(), + m_d->ui_idprojsurfs.radioButton_pixelprojsurf_barrel_outer->isChecked() || m_d->ui_idprojsurfs.radioButton_pixelprojsurf_barrel_both->isChecked(), + m_d->ui_idprojsurfs.radioButton_pixelprojsurf_endcap_inner->isChecked() || m_d->ui_idprojsurfs.radioButton_pixelprojsurf_endcap_both->isChecked(), + m_d->ui_idprojsurfs.radioButton_pixelprojsurf_endcap_outer->isChecked() || m_d->ui_idprojsurfs.radioButton_pixelprojsurf_endcap_both->isChecked() ); +} + +//____________________________________________________________________ +InDetProjFlags::InDetProjPartsFlags GuideSysController::applicableSCTProjParts() const +{ + return Imp::projPartsFlag( m_d->ui_idprojsurfs.radioButton_sctprojsurf_barrel_inner->isChecked() || m_d->ui_idprojsurfs.radioButton_sctprojsurf_barrel_both->isChecked(), + m_d->ui_idprojsurfs.radioButton_sctprojsurf_barrel_outer->isChecked() || m_d->ui_idprojsurfs.radioButton_sctprojsurf_barrel_both->isChecked(), + m_d->ui_idprojsurfs.radioButton_sctprojsurf_endcap_inner->isChecked() || m_d->ui_idprojsurfs.radioButton_sctprojsurf_endcap_both->isChecked(), + m_d->ui_idprojsurfs.radioButton_sctprojsurf_endcap_outer->isChecked() || m_d->ui_idprojsurfs.radioButton_sctprojsurf_endcap_both->isChecked() ); +} + +//____________________________________________________________________ +InDetProjFlags::InDetProjPartsFlags GuideSysController::applicableTRTProjParts() const +{ + return Imp::projPartsFlag( m_d->ui_idprojsurfs.radioButton_trtprojsurf_barrel_inner->isChecked() || m_d->ui_idprojsurfs.radioButton_trtprojsurf_barrel_both->isChecked(), + m_d->ui_idprojsurfs.radioButton_trtprojsurf_barrel_outer->isChecked() || m_d->ui_idprojsurfs.radioButton_trtprojsurf_barrel_both->isChecked(), + m_d->ui_idprojsurfs.radioButton_trtprojsurf_endcap_inner->isChecked() || m_d->ui_idprojsurfs.radioButton_trtprojsurf_endcap_both->isChecked(), + m_d->ui_idprojsurfs.radioButton_trtprojsurf_endcap_outer->isChecked() || m_d->ui_idprojsurfs.radioButton_trtprojsurf_endcap_both->isChecked(), + true, m_d->ui_idprojsurfs.checkBox_trtprojsurf_z2r->isChecked() ); +} + +//_____________________________________________________________________________________ +InDetProjFlags::DetTypeFlags GuideSysController::Imp::trtPartsEnabledByGUIOrDataUsage() const +{ + InDetProjFlags::DetTypeFlags f(InDetProjFlags::NoDet); + if (ui_idprojsurfs.groupBox_trtproj->isChecked()) { + if (ui_idprojsurfs.checkBox_trtprojsurf_parts_asneeded->isChecked()) { + f |= (inDetDetTypesUsingProjections&InDetProjFlags::TRT_all); + } else { + if (ui_idprojsurfs.checkBox_trtprojsurf_parts_barrelA->isChecked()) f |= InDetProjFlags::TRT_brlpos; + if (ui_idprojsurfs.checkBox_trtprojsurf_parts_barrelC->isChecked()) f |= InDetProjFlags::TRT_brlneg; + if (ui_idprojsurfs.checkBox_trtprojsurf_parts_endcapA->isChecked()) f |= InDetProjFlags::TRT_ecpos; + if (ui_idprojsurfs.checkBox_trtprojsurf_parts_endcapC->isChecked()) f |= InDetProjFlags::TRT_ecneg; + } + } + return f; +} + +//_____________________________________________________________________________________ +InDetProjFlags::DetTypeFlags GuideSysController::Imp::sctPartsEnabledByGUIOrDataUsage() const +{ + InDetProjFlags::DetTypeFlags f(InDetProjFlags::NoDet); + if (ui_idprojsurfs.groupBox_sctproj->isChecked()) { + if (ui_idprojsurfs.checkBox_sctprojsurf_parts_asneeded->isChecked()) { + f |= (inDetDetTypesUsingProjections&InDetProjFlags::SCT_all); + } else { + if (ui_idprojsurfs.checkBox_sctprojsurf_parts_barrelA->isChecked()) f |= InDetProjFlags::SCT_brlpos; + if (ui_idprojsurfs.checkBox_sctprojsurf_parts_barrelC->isChecked()) f |= InDetProjFlags::SCT_brlneg; + if (ui_idprojsurfs.checkBox_sctprojsurf_parts_endcapA->isChecked()) f |= InDetProjFlags::SCT_ecpos; + if (ui_idprojsurfs.checkBox_sctprojsurf_parts_endcapC->isChecked()) f |= InDetProjFlags::SCT_ecneg; + } + } + return f; +} + +//_____________________________________________________________________________________ +InDetProjFlags::DetTypeFlags GuideSysController::Imp::pixelPartsEnabledByGUIOrDataUsage() const +{ + InDetProjFlags::DetTypeFlags f(InDetProjFlags::NoDet); + if (ui_idprojsurfs.groupBox_pixelproj->isChecked()) { + if (ui_idprojsurfs.checkBox_pixelprojsurf_parts_asneeded->isChecked()) { + f |= (inDetDetTypesUsingProjections&InDetProjFlags::Pixel_all); + } else { + if (ui_idprojsurfs.checkBox_pixelprojsurf_parts_barrelA->isChecked()) f |= InDetProjFlags::Pixel_brlpos; + if (ui_idprojsurfs.checkBox_pixelprojsurf_parts_barrelC->isChecked()) f |= InDetProjFlags::Pixel_brlneg; + if (ui_idprojsurfs.checkBox_pixelprojsurf_parts_endcapA->isChecked()) f |= InDetProjFlags::Pixel_ecpos; + if (ui_idprojsurfs.checkBox_pixelprojsurf_parts_endcapC->isChecked()) f |= InDetProjFlags::Pixel_ecneg; + } + } + return f; +} + +//____________________________________________________________________ +InDetProjFlags::InDetProjPartsFlags GuideSysController::shownPixelProjSurfaces() const +{ + InDetProjFlags::DetTypeFlags enabledDetRegions = m_d->pixelPartsEnabledByGUIOrDataUsage(); + if (!(InDetProjFlags::Pixel_all&enabledDetRegions)||!m_d->ui.checkBox_inDetProjSurfs->isChecked()) + return InDetProjFlags::NoProjections; + InDetProjFlags::InDetProjPartsFlags pixelProjParts(applicablePixelProjParts()); + if (pixelProjParts==InDetProjFlags::NoProjections) + return InDetProjFlags::NoProjections; + InDetProjFlags::InDetProjPartsFlags dummy_sct(InDetProjFlags::NoProjections), dummy_trt(InDetProjFlags::NoProjections); + InDetProjFlags::projectionPartsGivenUsedDetectors( pixelProjParts, dummy_sct, dummy_trt, enabledDetRegions ); + return pixelProjParts; +} + +//____________________________________________________________________ +InDetProjFlags::InDetProjPartsFlags GuideSysController::shownSCTProjSurfaces() const +{ + InDetProjFlags::DetTypeFlags enabledDetRegions = m_d->sctPartsEnabledByGUIOrDataUsage(); + if (!(InDetProjFlags::SCT_all&enabledDetRegions)||!m_d->ui.checkBox_inDetProjSurfs->isChecked()) + return InDetProjFlags::NoProjections; + InDetProjFlags::InDetProjPartsFlags sctProjParts(applicableSCTProjParts()); + if (sctProjParts==InDetProjFlags::NoProjections) + return InDetProjFlags::NoProjections; + InDetProjFlags::InDetProjPartsFlags dummy_pixel(InDetProjFlags::NoProjections), dummy_trt(InDetProjFlags::NoProjections); + InDetProjFlags::projectionPartsGivenUsedDetectors( dummy_pixel, sctProjParts, dummy_trt, enabledDetRegions ); + return sctProjParts; +} + +//____________________________________________________________________ +InDetProjFlags::InDetProjPartsFlags GuideSysController::shownTRTProjSurfaces() const +{ + InDetProjFlags::DetTypeFlags enabledDetRegions = m_d->trtPartsEnabledByGUIOrDataUsage(); + if (!(InDetProjFlags::TRT_all&enabledDetRegions)||!m_d->ui.checkBox_inDetProjSurfs->isChecked()) + return InDetProjFlags::NoProjections; + InDetProjFlags::InDetProjPartsFlags trtProjParts(applicableTRTProjParts()); + if (trtProjParts==InDetProjFlags::NoProjections) + return InDetProjFlags::NoProjections; + InDetProjFlags::InDetProjPartsFlags dummy_pixel(InDetProjFlags::NoProjections), dummy_sct(InDetProjFlags::NoProjections); + InDetProjFlags::projectionPartsGivenUsedDetectors( dummy_pixel, dummy_sct, trtProjParts,enabledDetRegions ); + return trtProjParts; +} + +//____________________________________________________________________ +void GuideSysController::setInDetDetTypesUsingProjections(InDetProjFlags::DetTypeFlags f) +{ + if (m_d->inDetDetTypesUsingProjections==f) + return; + m_d->inDetDetTypesUsingProjections=f; + possibleChange_shownPixelProjSurfaces(); + possibleChange_shownSCTProjSurfaces(); + possibleChange_shownTRTProjSurfaces(); +} + +//____________________________________________________________________ +void GuideSysController::updateProjPartsCheckboxStates_Pixel() +{ + const bool e(!m_d->ui_idprojsurfs.checkBox_pixelprojsurf_parts_asneeded->isChecked()); + m_d->ui_idprojsurfs.checkBox_pixelprojsurf_parts_barrelA->setEnabled(e); + m_d->ui_idprojsurfs.checkBox_pixelprojsurf_parts_barrelC->setEnabled(e); + m_d->ui_idprojsurfs.checkBox_pixelprojsurf_parts_endcapA->setEnabled(e); + m_d->ui_idprojsurfs.checkBox_pixelprojsurf_parts_endcapC->setEnabled(e); +} + +//____________________________________________________________________ +void GuideSysController::updateProjPartsCheckboxStates_SCT() +{ + const bool e(!m_d->ui_idprojsurfs.checkBox_sctprojsurf_parts_asneeded->isChecked()); + m_d->ui_idprojsurfs.checkBox_sctprojsurf_parts_barrelA->setEnabled(e); + m_d->ui_idprojsurfs.checkBox_sctprojsurf_parts_barrelC->setEnabled(e); + m_d->ui_idprojsurfs.checkBox_sctprojsurf_parts_endcapA->setEnabled(e); + m_d->ui_idprojsurfs.checkBox_sctprojsurf_parts_endcapC->setEnabled(e); +} + +//____________________________________________________________________ +void GuideSysController::updateProjPartsCheckboxStates_TRT() +{ + const bool e(!m_d->ui_idprojsurfs.checkBox_trtprojsurf_parts_asneeded->isChecked()); + m_d->ui_idprojsurfs.checkBox_trtprojsurf_parts_barrelA->setEnabled(e); + m_d->ui_idprojsurfs.checkBox_trtprojsurf_parts_barrelC->setEnabled(e); + m_d->ui_idprojsurfs.checkBox_trtprojsurf_parts_endcapA->setEnabled(e); + m_d->ui_idprojsurfs.checkBox_trtprojsurf_parts_endcapC->setEnabled(e); +} + +bool GuideSysController::showTrackingVolumes() const +{ + return m_d->ui.checkBox_trkVolumes->isChecked(); +} + +bool GuideSysController::showInnerDetector() const +{ + return m_d->ui_trkvolumes.checkBox_ID->isChecked(); +} + +bool GuideSysController::showCalorimeters() const +{ + return m_d->ui_trkvolumes.checkBox_Calo->isChecked(); +} + +bool GuideSysController::showMuonSpectrometer() const +{ + return m_d->ui_trkvolumes.checkBox_MS->isChecked(); +} + +//____________________________________________________________________ +int GuideSysController::currentSettingsVersion() const +{ + return 3; +} + +//____________________________________________________________________ +void GuideSysController::actualSaveSettings(VP1Serialise&s) const +{ + + //version 0 output an integer here. + + //Materials + s.save(m_d->ui_floorandletters.matButton_letters); + s.save(m_d->ui_axes.matButton_axes_x); + s.save(m_d->ui_axes.matButton_axes_y); + s.save(m_d->ui_axes.matButton_axes_z); + s.save(m_d->ui_etacones.matButton_etaCone1); + s.save(m_d->ui_etacones.matButton_etaCone2); + s.save(m_d->ui_etacones.matButton_etaCone3); + s.save(m_d->ui_idprojsurfs.pushButton_projsurfmaterial_pixel); + s.save(m_d->ui_idprojsurfs.pushButton_projsurfmaterial_sct); + s.save(m_d->ui_idprojsurfs.pushButton_projsurfmaterial_trt); + + //Everything apart from projection surfaces: + s.save(m_d->ui_grid.colorButton_grid); + s.save(m_d->ui_grid.spinBox_gridtransp); + s.save(m_d->ui_floorandletters.colorButton_floor); + s.save(m_d->ui_floorandletters.spinBox_floortransp); + s.save(m_d->ui_floorandletters.doubleSpinBox_floorheight); + s.save(m_d->ui_floorandletters.checkBox_floorenabled); + s.save(m_d->ui_floorandletters.doubleSpinBox_floorspacing); + s.save(m_d->ui_floorandletters.doubleSpinBox_floorextent); + s.save(m_d->ui_floorandletters.checkBox_acdesignations); + //Version 0 output bool here + s.save(m_d->ui_axes.checkBox_axes_shownegativeparts); + s.save(m_d->ui_axes.doubleSpinBox_axes_lengths_m); + s.save(m_d->ui_axes.doubleSpinBox_axes_relthickness); + s.save(m_d->ui_axes.doubleSpinBox_axes_xpos_m); + s.save(m_d->ui_axes.doubleSpinBox_axes_ypos_m); + s.save(m_d->ui_axes.doubleSpinBox_axes_zpos_m); + s.save(0/*backwards compat*/,m_d->ui_grid.radioButton_grid_cartesian,m_d->ui_grid.radioButton_grid_cylindrical); + s.save(m_d->ui_grid.doubleSpinBox_gridspacing); + s.save(m_d->ui_grid.doubleSpinBox_gridextent); + s.save(m_d->ui_etacones.checkBox_etacone1); + s.save(m_d->ui_etacones.doubleSpinBox_etaval1); + s.save(m_d->ui_etacones.checkBox_etacone2); + s.save(m_d->ui_etacones.doubleSpinBox_etaval2); + s.save(m_d->ui_etacones.checkBox_etacone3); + s.save(m_d->ui_etacones.doubleSpinBox_etaval3); + s.save(m_d->ui_etacones.doubleSpinBox_etaconeextent); + s.save(m_d->ui_etacones.radioButton_etaconeextentisr,m_d->ui_etacones.radioButton_etaconeextentisz); + + //Projection surfaces: + + s.save(m_d->ui_idprojsurfs.groupBox_pixelproj); + s.save(m_d->ui_idprojsurfs.checkBox_pixelprojsurf_parts_asneeded); + s.save(m_d->ui_idprojsurfs.checkBox_pixelprojsurf_parts_barrelA); + s.save(m_d->ui_idprojsurfs.checkBox_pixelprojsurf_parts_barrelC); + s.save(m_d->ui_idprojsurfs.checkBox_pixelprojsurf_parts_endcapA); + s.save(m_d->ui_idprojsurfs.checkBox_pixelprojsurf_parts_endcapC); + s.save(m_d->ui_idprojsurfs.radioButton_pixelprojsurf_barrel_inner, + m_d->ui_idprojsurfs.radioButton_pixelprojsurf_barrel_outer, + m_d->ui_idprojsurfs.radioButton_pixelprojsurf_barrel_both); + s.save(m_d->ui_idprojsurfs.radioButton_pixelprojsurf_endcap_inner, + m_d->ui_idprojsurfs.radioButton_pixelprojsurf_endcap_outer, + m_d->ui_idprojsurfs.radioButton_pixelprojsurf_endcap_both); + s.save(m_d->ui_idprojsurfs.groupBox_sctproj); + s.save(m_d->ui_idprojsurfs.checkBox_sctprojsurf_parts_asneeded); + s.save(m_d->ui_idprojsurfs.checkBox_sctprojsurf_parts_barrelA); + s.save(m_d->ui_idprojsurfs.checkBox_sctprojsurf_parts_barrelC); + s.save(m_d->ui_idprojsurfs.checkBox_sctprojsurf_parts_endcapA); + s.save(m_d->ui_idprojsurfs.checkBox_sctprojsurf_parts_endcapC); + s.save(m_d->ui_idprojsurfs.radioButton_sctprojsurf_barrel_inner, + m_d->ui_idprojsurfs.radioButton_sctprojsurf_barrel_outer, + m_d->ui_idprojsurfs.radioButton_sctprojsurf_barrel_both); + s.save(m_d->ui_idprojsurfs.radioButton_sctprojsurf_endcap_inner, + m_d->ui_idprojsurfs.radioButton_sctprojsurf_endcap_outer, + m_d->ui_idprojsurfs.radioButton_sctprojsurf_endcap_both); + s.save(m_d->ui_idprojsurfs.groupBox_trtproj); + s.save(m_d->ui_idprojsurfs.checkBox_trtprojsurf_parts_asneeded); + s.save(m_d->ui_idprojsurfs.checkBox_trtprojsurf_parts_barrelA); + s.save(m_d->ui_idprojsurfs.checkBox_trtprojsurf_parts_barrelC); + s.save(m_d->ui_idprojsurfs.checkBox_trtprojsurf_parts_endcapA); + s.save(m_d->ui_idprojsurfs.checkBox_trtprojsurf_parts_endcapC); + s.save(m_d->ui_idprojsurfs.radioButton_trtprojsurf_barrel_inner, + m_d->ui_idprojsurfs.radioButton_trtprojsurf_barrel_outer, + m_d->ui_idprojsurfs.radioButton_trtprojsurf_barrel_both); + s.save(m_d->ui_idprojsurfs.radioButton_trtprojsurf_endcap_inner, + m_d->ui_idprojsurfs.radioButton_trtprojsurf_endcap_outer, + m_d->ui_idprojsurfs.radioButton_trtprojsurf_endcap_both); + s.save(m_d->ui_idprojsurfs.checkBox_trtprojsurf_z2r); + + s.save(m_d->ui.checkBox_coordinateAxes);//version 1+ + s.save(m_d->ui.checkBox_etaCones); + s.save(m_d->ui.checkBox_floorAndLetters);//version 1+ + s.save(m_d->ui.checkBox_grid);//version 1+ + s.save(m_d->ui.checkBox_inDetProjSurfs);//version 1+ + + //Tracking volumes: + // All version 2+ + s.save(m_d->ui.checkBox_trkVolumes); + + //material + s.save(m_d->ui_trkvolumes.matButton_ID); + s.save(m_d->ui_trkvolumes.matButton_Calo); + s.save(m_d->ui_trkvolumes.matButton_MS); + s.save(m_d->ui_trkvolumes.checkBox_ID); + s.save(m_d->ui_trkvolumes.checkBox_Calo); + s.save(m_d->ui_trkvolumes.checkBox_MS); + + // Line from origin + s.save(m_d->ui.checkBox_lines); + s.save(m_d->ui_lines.doubleSpinBox_phi); + s.save(m_d->ui_lines.doubleSpinBox_phi); + s.save(m_d->ui_lines.doubleSpinBox_eta); + s.save(m_d->ui_lines.doubleSpinBox_length); +} + +//____________________________________________________________________ +void GuideSysController::actualRestoreSettings(VP1Deserialise& s) +{ + if (s.version()<0||s.version()>2) { + message("Warning: State data in .vp1 file has unsupported version ("+str(s.version())+")"); + return; + } + + if (s.version()==0) + s.ignoreInt(); + + //Materials + s.restore(m_d->ui_floorandletters.matButton_letters); + s.restore(m_d->ui_axes.matButton_axes_x); + s.restore(m_d->ui_axes.matButton_axes_y); + s.restore(m_d->ui_axes.matButton_axes_z); + s.restore(m_d->ui_etacones.matButton_etaCone1); + s.restore(m_d->ui_etacones.matButton_etaCone2); + s.restore(m_d->ui_etacones.matButton_etaCone3); + s.restore(m_d->ui_idprojsurfs.pushButton_projsurfmaterial_pixel); + s.restore(m_d->ui_idprojsurfs.pushButton_projsurfmaterial_sct); + s.restore(m_d->ui_idprojsurfs.pushButton_projsurfmaterial_trt); + + + //Everything apart from projection surfaces: + s.restore(m_d->ui_grid.colorButton_grid); + s.restore(m_d->ui_grid.spinBox_gridtransp); + s.restore(m_d->ui_floorandletters.colorButton_floor); + s.restore(m_d->ui_floorandletters.spinBox_floortransp); + s.restore(m_d->ui_floorandletters.doubleSpinBox_floorheight); + s.restore(m_d->ui_floorandletters.checkBox_floorenabled); + s.restore(m_d->ui_floorandletters.doubleSpinBox_floorspacing); + s.restore(m_d->ui_floorandletters.doubleSpinBox_floorextent); + s.restore(m_d->ui_floorandletters.checkBox_acdesignations); + if (s.version()==0) + s.ignoreBool(); + s.restore(m_d->ui_axes.checkBox_axes_shownegativeparts); + s.restore(m_d->ui_axes.doubleSpinBox_axes_lengths_m); + s.restore(m_d->ui_axes.doubleSpinBox_axes_relthickness); + s.restore(m_d->ui_axes.doubleSpinBox_axes_xpos_m); + s.restore(m_d->ui_axes.doubleSpinBox_axes_ypos_m); + s.restore(m_d->ui_axes.doubleSpinBox_axes_zpos_m); + s.restore(0/*backwards compat*/,m_d->ui_grid.radioButton_grid_cartesian,m_d->ui_grid.radioButton_grid_cylindrical); + s.restore(m_d->ui_grid.doubleSpinBox_gridspacing); + s.restore(m_d->ui_grid.doubleSpinBox_gridextent); + s.restore(m_d->ui_etacones.checkBox_etacone1); + s.restore(m_d->ui_etacones.doubleSpinBox_etaval1); + s.restore(m_d->ui_etacones.checkBox_etacone2); + s.restore(m_d->ui_etacones.doubleSpinBox_etaval2); + s.restore(m_d->ui_etacones.checkBox_etacone3); + s.restore(m_d->ui_etacones.doubleSpinBox_etaval3); + s.restore(m_d->ui_etacones.doubleSpinBox_etaconeextent); + s.restore(m_d->ui_etacones.radioButton_etaconeextentisr,m_d->ui_etacones.radioButton_etaconeextentisz); + + //Projection surfaces: + + s.restore(m_d->ui_idprojsurfs.groupBox_pixelproj); + s.restore(m_d->ui_idprojsurfs.checkBox_pixelprojsurf_parts_asneeded); + s.restore(m_d->ui_idprojsurfs.checkBox_pixelprojsurf_parts_barrelA); + s.restore(m_d->ui_idprojsurfs.checkBox_pixelprojsurf_parts_barrelC); + s.restore(m_d->ui_idprojsurfs.checkBox_pixelprojsurf_parts_endcapA); + s.restore(m_d->ui_idprojsurfs.checkBox_pixelprojsurf_parts_endcapC); + s.restore(m_d->ui_idprojsurfs.radioButton_pixelprojsurf_barrel_inner, + m_d->ui_idprojsurfs.radioButton_pixelprojsurf_barrel_outer, + m_d->ui_idprojsurfs.radioButton_pixelprojsurf_barrel_both); + s.restore(m_d->ui_idprojsurfs.radioButton_pixelprojsurf_endcap_inner, + m_d->ui_idprojsurfs.radioButton_pixelprojsurf_endcap_outer, + m_d->ui_idprojsurfs.radioButton_pixelprojsurf_endcap_both); + s.restore(m_d->ui_idprojsurfs.groupBox_sctproj); + s.restore(m_d->ui_idprojsurfs.checkBox_sctprojsurf_parts_asneeded); + s.restore(m_d->ui_idprojsurfs.checkBox_sctprojsurf_parts_barrelA); + s.restore(m_d->ui_idprojsurfs.checkBox_sctprojsurf_parts_barrelC); + s.restore(m_d->ui_idprojsurfs.checkBox_sctprojsurf_parts_endcapA); + s.restore(m_d->ui_idprojsurfs.checkBox_sctprojsurf_parts_endcapC); + s.restore(m_d->ui_idprojsurfs.radioButton_sctprojsurf_barrel_inner, + m_d->ui_idprojsurfs.radioButton_sctprojsurf_barrel_outer, + m_d->ui_idprojsurfs.radioButton_sctprojsurf_barrel_both); + s.restore(m_d->ui_idprojsurfs.radioButton_sctprojsurf_endcap_inner, + m_d->ui_idprojsurfs.radioButton_sctprojsurf_endcap_outer, + m_d->ui_idprojsurfs.radioButton_sctprojsurf_endcap_both); + s.restore(m_d->ui_idprojsurfs.groupBox_trtproj); + s.restore(m_d->ui_idprojsurfs.checkBox_trtprojsurf_parts_asneeded); + s.restore(m_d->ui_idprojsurfs.checkBox_trtprojsurf_parts_barrelA); + s.restore(m_d->ui_idprojsurfs.checkBox_trtprojsurf_parts_barrelC); + s.restore(m_d->ui_idprojsurfs.checkBox_trtprojsurf_parts_endcapA); + s.restore(m_d->ui_idprojsurfs.checkBox_trtprojsurf_parts_endcapC); + s.restore(m_d->ui_idprojsurfs.radioButton_trtprojsurf_barrel_inner, + m_d->ui_idprojsurfs.radioButton_trtprojsurf_barrel_outer, + m_d->ui_idprojsurfs.radioButton_trtprojsurf_barrel_both); + s.restore(m_d->ui_idprojsurfs.radioButton_trtprojsurf_endcap_inner, + m_d->ui_idprojsurfs.radioButton_trtprojsurf_endcap_outer, + m_d->ui_idprojsurfs.radioButton_trtprojsurf_endcap_both); + s.restore(m_d->ui_idprojsurfs.checkBox_trtprojsurf_z2r); + + if (s.version()>=1) { + s.restore(m_d->ui.checkBox_coordinateAxes); + s.restore(m_d->ui.checkBox_etaCones); + s.restore(m_d->ui.checkBox_floorAndLetters); + s.restore(m_d->ui.checkBox_grid); + s.restore(m_d->ui.checkBox_inDetProjSurfs); + } + + if (s.version()>=2) { + s.restore(m_d->ui.checkBox_trkVolumes); + s.restore(m_d->ui_trkvolumes.matButton_ID); + s.restore(m_d->ui_trkvolumes.matButton_Calo); + s.restore(m_d->ui_trkvolumes.matButton_MS); + s.restore(m_d->ui_trkvolumes.checkBox_ID); + s.restore(m_d->ui_trkvolumes.checkBox_Calo); + s.restore(m_d->ui_trkvolumes.checkBox_MS); + } + if (s.version()>=3) { + s.restore(m_d->ui.checkBox_lines); + s.restore(m_d->ui_lines.doubleSpinBox_phi); + s.restore(m_d->ui_lines.doubleSpinBox_phi); + s.restore(m_d->ui_lines.doubleSpinBox_eta); + s.restore(m_d->ui_lines.doubleSpinBox_length); + } +} + +void GuideSysController::possibleChange_lineDirection() { + // Bit of a hack possibly to do this here, but I want to be able to update the direction by changing either theta or eta + double eta = m_d->ui_lines.doubleSpinBox_eta->value(); + double theta = m_d->ui_lines.doubleSpinBox_theta->value(); + + if (m_d->last_line_eta != eta){ + // eta has changed, so update theta in the UI + theta = 2*std::atan(std::exp(-1.0 * eta)); + m_d->ui_lines.doubleSpinBox_theta->setValue(theta); + } else if ( theta!= std::acos(m_d->last_lineDirection[2] / lineLength() ) ){ + eta = -1.0 * std::log(std::tan(theta/2.0)); + m_d->ui_lines.doubleSpinBox_eta->setValue(eta); + } + m_d->last_line_eta = m_d->ui_lines.doubleSpinBox_eta->value(); + if (changed( m_d->last_lineDirection , lineDirection() ) ) { + if (verbose()&&!initVarsMode()) messageVerbose("Emitting "+QString()+"( lineDirectionChanged"+toString(m_d->last_lineDirection)+" )"); + emit lineDirectionChanged(m_d->last_lineDirection); + } +} + + +/////////////////////////////////////////////////////////////////////////// +// Test for possible changes in values and emit signals as appropriate: +// (possibleChange_XXX() slots code provided by macros) +#define VP1CONTROLLERCLASSNAME GuideSysController +#include "VP1Base/VP1ControllerMacros.h" +POSSIBLECHANGE_IMP(showFloor) +POSSIBLECHANGE_IMP(floorColourAndTransp) +POSSIBLECHANGE_IMP(floorExtent) +POSSIBLECHANGE_IMP(floorSpacing) +POSSIBLECHANGE_IMP(floorHeight) +POSSIBLECHANGE_IMP(showLetters) +POSSIBLECHANGE_IMP(lettersZPos) +POSSIBLECHANGE_IMP(lettersVerticalPos) +POSSIBLECHANGE_IMP(showAxes) +POSSIBLECHANGE_IMP(axesLength) +POSSIBLECHANGE_IMP(axesPosition) +POSSIBLECHANGE_IMP(relAxesThickness) +POSSIBLECHANGE_IMP(showCartesianGrid) +POSSIBLECHANGE_IMP(showCylindricalGrid) +POSSIBLECHANGE_IMP(gridColourAndTransp) +POSSIBLECHANGE_IMP(gridSpacing) +POSSIBLECHANGE_IMP(gridExtent) +POSSIBLECHANGE_IMP(showEtaCone1) +POSSIBLECHANGE_IMP(showEtaCone2) +POSSIBLECHANGE_IMP(showEtaCone3) +POSSIBLECHANGE_IMP(etaConeValue1) +POSSIBLECHANGE_IMP(etaConeValue2) +POSSIBLECHANGE_IMP(etaConeValue3) +POSSIBLECHANGE_IMP(etaExtent) +POSSIBLECHANGE_IMP(applicablePixelProjParts) +POSSIBLECHANGE_IMP(applicableSCTProjParts) +POSSIBLECHANGE_IMP(applicableTRTProjParts) +POSSIBLECHANGE_IMP(shownPixelProjSurfaces) +POSSIBLECHANGE_IMP(shownSCTProjSurfaces) +POSSIBLECHANGE_IMP(shownTRTProjSurfaces) +POSSIBLECHANGE_IMP(showTrackingVolumes) +POSSIBLECHANGE_IMP(showInnerDetector) +POSSIBLECHANGE_IMP(showCalorimeters) +POSSIBLECHANGE_IMP(showMuonSpectrometer) +POSSIBLECHANGE_IMP(showLines) +//POSSIBLECHANGE_IMP(lineDirection) Implemented this manually so we can update eta/theta diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/InDetProjHelper.cxx b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/InDetProjHelper.cxx new file mode 100644 index 000000000..1a01f22c2 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/InDetProjHelper.cxx @@ -0,0 +1,964 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class InDetProjHelper // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: February 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12GuideLineSystems/InDetProjHelper.h" +#include "VTI12GuideLineSystems/InDetProjParams.h" +#include "VP1Base/VP1Msg.h" + +#include "GeoPrimitives/GeoPrimitives.h" + +#ifdef BUILDVP1LIGHT + #include "CLHEP/Units/SystemOfUnits.h" + #define SYSTEM_OF_UNITS CLHEP +#else + #include "GaudiKernel/SystemOfUnits.h" + #define SYSTEM_OF_UNITS Gaudi::Units +#endif + +//Fixme: Epsilon in projections! (at least take surface thickness into account!) + +//____________________________________________________________________ +InDetProjHelper * InDetProjHelper::createPixelHelper( IVP1System* system ) +{ + return new InDetProjHelper( InDetProjParams::surfacethickness(), + InDetProjParams::pixel_data_disttosurface_epsilon(), + InDetProjParams::pixel_barrel_inner_radius(), + InDetProjParams::pixel_barrel_outer_radius(), + InDetProjParams::pixel_barrel_posneg_z(), + InDetProjParams::pixel_endcap_surface_z(), + InDetProjParams::pixel_endcap_surface_length(), + InDetProjParams::pixel_endcap_inner_radius(), + InDetProjParams::pixel_endcap_outer_radius(), + InDetProjParams::pixel_endcap_zasr_innerradius(), + InDetProjParams::pixel_endcap_zasr_endcapz_begin(), + InDetProjParams::pixel_endcap_zasr_squeezefact(), + system ); +} + +//____________________________________________________________________ +InDetProjHelper * InDetProjHelper::createSCTHelper(IVP1System* system ) +{ + return new InDetProjHelper( InDetProjParams::surfacethickness(), + InDetProjParams::sct_data_disttosurface_epsilon(), + InDetProjParams::sct_barrel_inner_radius(), + InDetProjParams::sct_barrel_outer_radius(), + InDetProjParams::sct_barrel_posneg_z(), + InDetProjParams::sct_endcap_surface_z(), + InDetProjParams::sct_endcap_surface_length(), + InDetProjParams::sct_endcap_inner_radius(), + InDetProjParams::sct_endcap_outer_radius(), + InDetProjParams::sct_endcap_zasr_innerradius(), + InDetProjParams::sct_endcap_zasr_endcapz_begin(), + InDetProjParams::sct_endcap_zasr_squeezefact(), + system ); +} + +//____________________________________________________________________ +InDetProjHelper * InDetProjHelper::createTRTHelper(IVP1System* system ) +{ + return new InDetProjHelper( InDetProjParams::surfacethickness(), + InDetProjParams::trt_data_disttosurface_epsilon(), + InDetProjParams::trt_barrel_inner_radius(), + InDetProjParams::trt_barrel_outer_radius(), + InDetProjParams::trt_barrel_posneg_z(), + InDetProjParams::trt_endcap_surface_z(), + InDetProjParams::trt_endcap_surface_length(), + InDetProjParams::trt_endcap_inner_radius(), + InDetProjParams::trt_endcap_outer_radius(), + InDetProjParams::trt_endcap_zasr_innerradius(), + InDetProjParams::trt_endcap_zasr_endcapz_begin(), + InDetProjParams::trt_endcap_zasr_squeezefact(), + system ); +} + +//____________________________________________________________________ +class InDetProjHelper::Imp { +public: + InDetProjHelper * theclass; + + //Applicable projections: + InDetProjFlags::InDetProjPartsFlags parts; + + //The parameters: + double surfacethickness; + double data_disttosurface_epsilon; + double barrel_inner_radius; + double barrel_outer_radius; + double barrel_posneg_z; + double endcap_surface_z; + double endcap_surface_length; + double endcap_inner_radius; + double endcap_outer_radius; + double endcap_zasr_innerradius; + double endcap_zasr_endcapz_begin; + double endcap_zasr_squeezefact; + + //Parameters of maximal cylinder covering all enabled parts of + //detector: + double covercyl_zmin; + double covercyl_zmax; + double covercyl_rmin; + double covercyl_rmax; + +// //Helper methods: + void lineCircleIntersection( const Amg::Vector3D&a, const Amg::Vector3D&b,const double& r, + double & u1, double& u2 ) const; + + //Clip segments to cylinders and planes: + void movePoint1ToZPlaneAndPoint2( Amg::Vector3D& p1, const Amg::Vector3D& p2, const double& z ) const; + bool clipSegmentToZInterval( Amg::Vector3D&a, Amg::Vector3D&b, const double& zmin, const double& zmax ) const; + void movePoint1ToInfiniteCylinderAndPoint2( Amg::Vector3D&p1, const Amg::Vector3D&p2, const double& r ) const; + bool clipSegmentToInfiniteHollowCylinder( Amg::Vector3D&a, Amg::Vector3D&b, + const double& rmin, const double& rmax, + Amg::Vector3D&seg2_a, Amg::Vector3D&seg2_b ) const; + + bool clipSegmentToHollowCylinder( Amg::Vector3D&a, Amg::Vector3D&b, + const double& rmin, const double& rmax, + const double& zmin, const double& zmax, + Amg::Vector3D&seg2_a, Amg::Vector3D&seg2_b ) const; + + void clipPathToHollowCylinder( const std::vector<Amg::Vector3D >& in, +// Amg::SetVectorVector3D& out,//<- where clipped pieces of the paths will be appended. + Amg::SetVectorVector3D& out,//<- where clipped pieces of the paths will be appended. + const double& rmin, const double& rmax, + const double& zmin, const double& zmax ) const; + + bool touchesHollowCylinder( const std::vector<Amg::Vector3D >& path, + const double& rmin, const double& rmax, + const double& zmin, const double& zmax ) const; + //Project points to cylinders and planes: + void projectPathToInfiniteCylinder( const std::vector<Amg::Vector3D >& in, + Amg::SetVectorVector3D& outset, const double& r ) const; + void projectPathToZPlane( const std::vector<Amg::Vector3D >& in, + Amg::SetVectorVector3D& outset, const double& z ) const; + void projectPathToZPlane_specialZtoR( const std::vector<Amg::Vector3D >& in, + Amg::SetVectorVector3D& outset, const double& z ) const; + +}; + +//____________________________________________________________________ +InDetProjHelper::InDetProjHelper( double surfacethickness, + double data_disttosurface_epsilon, + double barrel_inner_radius, + double barrel_outer_radius, + double barrel_posneg_z, + double endcap_surface_z, + double endcap_surface_length, + double endcap_inner_radius, + double endcap_outer_radius, + double endcap_zasr_innerradius, + double endcap_zasr_endcapz_begin, + double endcap_zasr_squeezefact, + IVP1System* sys ) + : VP1HelperClassBase(sys,"InDetProjHelper"), m_d(new Imp) +{ + m_d->theclass = this; + + m_d->surfacethickness = surfacethickness; + m_d->data_disttosurface_epsilon = data_disttosurface_epsilon; + m_d->barrel_inner_radius = barrel_inner_radius; + m_d->barrel_outer_radius = barrel_outer_radius; + m_d->barrel_posneg_z = barrel_posneg_z; + m_d->endcap_surface_z = endcap_surface_z; + m_d->endcap_surface_length = endcap_surface_length; + m_d->endcap_inner_radius = endcap_inner_radius; + m_d->endcap_outer_radius = endcap_outer_radius; + m_d->endcap_zasr_innerradius = endcap_zasr_innerradius; + m_d->endcap_zasr_endcapz_begin = endcap_zasr_endcapz_begin; + m_d->endcap_zasr_squeezefact = endcap_zasr_squeezefact; + + m_d->parts = InDetProjFlags::NoProjections; + m_d->covercyl_zmin = 0.0; + m_d->covercyl_zmax = 0.0; + m_d->covercyl_rmin = 0.0; + m_d->covercyl_rmax = 0.0; + +} + +//____________________________________________________________________ +InDetProjHelper::~InDetProjHelper() +{ + delete m_d; +} + +//____________________________________________________________________ +InDetProjFlags::InDetProjPartsFlags InDetProjHelper::setParts( InDetProjFlags::InDetProjPartsFlags newparts ) +{ + if ( m_d->parts==newparts ) + return m_d->parts; + InDetProjFlags::InDetProjPartsFlags oldparts = m_d->parts; + m_d->parts = newparts; + + //Update parameters of smallest cylinder covering all enabled clip volumes. + if (m_d->parts == InDetProjFlags::NoProjections) { + m_d->covercyl_zmin = 0.0; + m_d->covercyl_zmax = 0.0; + m_d->covercyl_rmin = 0.0; + m_d->covercyl_rmax = 0.0; + return oldparts; + } + + bool no_ec_neg = !( m_d->parts & InDetProjFlags::EndCap_AllNeg ); + bool no_ec_pos = !( m_d->parts & InDetProjFlags::EndCap_AllPos ); + bool no_brl_neg = !( m_d->parts & InDetProjFlags::Barrel_AllNeg ); + bool no_brl_pos = !( m_d->parts & InDetProjFlags::Barrel_AllPos ); + bool barrel = m_d->parts & InDetProjFlags::Barrel_All; + bool endcap = m_d->parts & InDetProjFlags::EndCap_All; + + m_d->covercyl_zmin = - m_d->endcap_surface_z - 0.5*m_d->endcap_surface_length; + if ( no_ec_neg ) { + m_d->covercyl_zmin = - m_d->barrel_posneg_z; + if ( no_brl_neg ) { + m_d->covercyl_zmin = 0.0; + if ( no_brl_pos ) { + m_d->covercyl_zmin = m_d->barrel_posneg_z; + if ( no_ec_pos ) + m_d->covercyl_zmin = m_d->endcap_surface_z + 0.5*m_d->endcap_surface_length + 1.0e99; + } + } + } + m_d->covercyl_zmax = m_d->endcap_surface_z + 0.5*m_d->endcap_surface_length; + if ( no_ec_pos ) { + m_d->covercyl_zmax = m_d->barrel_posneg_z; + if ( no_brl_pos ) { + m_d->covercyl_zmax = 0.0; + if ( no_brl_neg ) { + m_d->covercyl_zmax = - m_d->barrel_posneg_z; + if ( no_ec_neg ) + m_d->covercyl_zmax = - m_d->endcap_surface_z - 0.5*m_d->endcap_surface_length - 1.0e99; + } + } + } + if ( m_d->covercyl_zmin >= m_d->covercyl_zmax ) + m_d->covercyl_zmin = m_d->covercyl_zmax = 0; + + if ( barrel && endcap ) { + m_d->covercyl_rmin = std::min(m_d->barrel_inner_radius,m_d->endcap_inner_radius); + m_d->covercyl_rmax = std::max(m_d->barrel_outer_radius,m_d->endcap_outer_radius); + } else { + if (barrel) { + m_d->covercyl_rmin = m_d->barrel_inner_radius; + m_d->covercyl_rmax = m_d->barrel_outer_radius; + } else if (endcap) { + m_d->covercyl_rmin = m_d->endcap_inner_radius; + m_d->covercyl_rmax = m_d->endcap_outer_radius; + } else { + message("Unforeseen execution path encountered."); + m_d->covercyl_rmin = 0; + m_d->covercyl_rmax = 0; + } + } + if ( m_d->covercyl_rmin >= m_d->covercyl_rmax ) + m_d->covercyl_rmin = m_d->covercyl_rmax = 0; + return oldparts; +} + +//____________________________________________________________________ +InDetProjFlags::InDetProjPartsFlags InDetProjHelper::parts() const +{ + return m_d->parts; +} + +//____________________________________________________________________ +void InDetProjHelper::clipPath( const std::vector<Amg::Vector3D >& path, + Amg::SetVectorVector3D& resulting_subpaths ) const +{ + clipPath(path,resulting_subpaths,resulting_subpaths,resulting_subpaths,resulting_subpaths); +} + +//____________________________________________________________________ +void InDetProjHelper::clipPath( const std::vector<Amg::Vector3D >& path, + Amg::SetVectorVector3D& resulting_subpaths_barrelA, + Amg::SetVectorVector3D& resulting_subpaths_barrelC, + Amg::SetVectorVector3D& resulting_subpaths_endcapA, + Amg::SetVectorVector3D& resulting_subpaths_endcapC ) const +{ + if (VP1Msg::verbose()) + messageVerbose("clipPath(..) called. Input path has "+QString::number(path.size())+" points."); + + resulting_subpaths_barrelA.clear(); + resulting_subpaths_barrelC.clear(); + resulting_subpaths_endcapA.clear(); + resulting_subpaths_endcapC.clear(); + + //Fixme: If verbose - perform sanity check of input data (check for NAN's). + if (m_d->parts == InDetProjFlags::NoProjections ) { + if (VP1Msg::verbose()) + messageVerbose("All projections currently off."); + return; + } + if ( path.size()<2 ) { + if (VP1Msg::verbose()) + messageVerbose("Input path too short."); + return; + } + + // Find the clipped path's in all of the enabled detector parts. + + //For efficiency, we first clip the path to the smallest + //axis-aligned cylinder containing all of the projective volumes + Amg::SetVectorVector3D paths_clipped; + m_d->clipPathToHollowCylinder( path, paths_clipped, + m_d->covercyl_rmin, m_d->covercyl_rmax, + m_d->covercyl_zmin, m_d->covercyl_zmax ); + + if (paths_clipped.empty()) { + if (VP1Msg::verbose()) + messageVerbose("Path entirely outside clip volumes."); + return; + } + + const bool enabled_brlA = m_d->parts & InDetProjFlags::Barrel_AllPos; + const bool enabled_brlC = m_d->parts & InDetProjFlags::Barrel_AllNeg; + const bool enabled_ecA = m_d->parts & InDetProjFlags::EndCap_AllPos; + const bool enabled_ecC = m_d->parts & InDetProjFlags::EndCap_AllNeg; + + //Special case: If exactly one of the four parts is enabled, we already have our result: + if ( ( (enabled_brlA?1:0) + (enabled_brlC?1:0) + (enabled_ecA?1:0) + (enabled_ecC?1:0) ) == 1 ) { + if (enabled_brlA) { + resulting_subpaths_barrelA = paths_clipped; + if (VP1Msg::verbose()) + messageVerbose("clipPath(..) only brlA enabled. Returning."); + return; + } + if (enabled_brlC) { + resulting_subpaths_barrelC = paths_clipped; + if (VP1Msg::verbose()) + messageVerbose("clipPath(..) only brlC enabled. Returning."); + return; + } + if (enabled_ecA) { + resulting_subpaths_endcapA = paths_clipped; + if (VP1Msg::verbose()) + messageVerbose("clipPath(..) only ecA enabled. Returning."); + return; + } + if (enabled_ecC) { + resulting_subpaths_endcapC = paths_clipped; + if (VP1Msg::verbose()) + messageVerbose("clipPath(..) only ecC enabled. Returning."); + return; + } + } + + + //For each of the segments, we then find its clipped parts inside + //the four detector volumes: BarrelA, BarrelC, EndCapA, EndCapC. + // Amg::SetVectorVector3D paths_brlA, paths_brlC, paths_ecA,paths_ecC; + Amg::SetVectorVector3D::const_iterator it, itE(paths_clipped.end()); + for (it = paths_clipped.begin();it!=itE;++it) { + if ( enabled_brlA ) + m_d->clipPathToHollowCylinder( *it, resulting_subpaths_barrelA, m_d->barrel_inner_radius, m_d->barrel_outer_radius, 0, m_d->barrel_posneg_z ); + if ( enabled_brlC ) + m_d->clipPathToHollowCylinder( *it, resulting_subpaths_barrelC, m_d->barrel_inner_radius, m_d->barrel_outer_radius, - m_d->barrel_posneg_z, 0 ); + if ( enabled_ecA ) + m_d->clipPathToHollowCylinder( *it, resulting_subpaths_endcapA, m_d->endcap_inner_radius, m_d->endcap_outer_radius, + m_d->endcap_surface_z - m_d->endcap_surface_length * 0.5, m_d->endcap_surface_z + m_d->endcap_surface_length * 0.5 ); + if ( enabled_ecC ) + m_d->clipPathToHollowCylinder( *it, resulting_subpaths_endcapC, m_d->endcap_inner_radius, m_d->endcap_outer_radius, + - m_d->endcap_surface_z - m_d->endcap_surface_length * 0.5, - m_d->endcap_surface_z + m_d->endcap_surface_length * 0.5 ); + } + + messageVerbose("clipPath(..) end."); + //Fixme: If verbose: sanity check on output! +} + +//____________________________________________________________________ +void InDetProjHelper::Imp::movePoint1ToZPlaneAndPoint2( Amg::Vector3D& p1, const Amg::Vector3D& p2, const double& z ) const +{ + double dx(p2.x()-p1.x()), dy(p2.y()-p1.y()), dz(p2.z()-p1.z()); + if (dz==0.0) { + theclass->message("movePoint1ToZPlaneAndPoint2 Error: Points have same z!!"); + return; + } + double s( (z-p1.z())/dz ); +// p1.set( p1.x()+dx*s, p1.y()+dy*s, z ); + Amg::setVector3DCartesian( p1, p1.x()+dx*s, p1.y()+dy*s, z ); +} + +//____________________________________________________________________ +bool InDetProjHelper::Imp::clipSegmentToZInterval( Amg::Vector3D&a, Amg::Vector3D&b, + const double& zmin, const double& zmax ) const +{ + if (a.z()<zmin) { + if (b.z()<zmin)//both <zmin + return false; + //a<zmin, b>=zmin: + movePoint1ToZPlaneAndPoint2(a,b,zmin); + if (b.z()>zmax) + movePoint1ToZPlaneAndPoint2(b,a,zmax); + return true; + } else { + if (b.z()<zmin) { + //a>=zmin, b<zmin + movePoint1ToZPlaneAndPoint2(b,a,zmin); + if (a.z()>zmax) + movePoint1ToZPlaneAndPoint2(a,b,zmax); + return true; + } else { + //Both are > zmin + if (a.z()>zmax) { + if (b.z()>zmax) + return false; + movePoint1ToZPlaneAndPoint2(a,b,zmax); + return true; + } else { + //zmin<=a<=zmax, b>=zmin + if (b.z()>zmax) + movePoint1ToZPlaneAndPoint2(b,a,zmax); + return true; + } + } + } +} + +//____________________________________________________________________ +void InDetProjHelper::Imp::movePoint1ToInfiniteCylinderAndPoint2( Amg::Vector3D&p1, const Amg::Vector3D&p2,const double& r ) const +{ + //Fixme: what happens here if we don't cross? And how can we be sure + //that we don't move FURTHER than the other point? (i.e. if the + //infinite line with p1 and p2 crosses, but the segment p1p2 does + //not!? + +// double p1r(p1.r()); +// double dr(p2.r()-p1r); + double p1r( Amg::rVector3D(p1) ); + double dr( Amg::rVector3D(p2)-p1r ); + + if (dr==0.0) { + theclass->message("movePoint1ToInfiniteCylinderAndPoint2 Error: Points have same r!!"); + return; + } + double s((r-p1r)/dr); + double t(1.0-s); + Amg::setVector3DCartesian( p1, p1.x()*t + p2.x()*s, p1.y()*t + p2.y()*s, p1.z()*t + p2.z()*s ); + +} + +//____________________________________________________________________ +void InDetProjHelper::Imp::lineCircleIntersection( const Amg::Vector3D&a, const Amg::Vector3D&b,const double& r, + double & u1, double& u2 ) const +{ + const double dx = b.x()-a.x(); + const double dy = b.y()-a.y(); + double A = dx*dx+dy*dy; + if (A==0.0) { + //That's not a line => no intersections unless points are exactly on circumference! + u1 = u2 = ( a.x()*a.x()+a.y()*a.y() == r*r ? 0.0 : 1.0e99 ); + return; + } + double B = 2.0*( a.x()*dx + a.y()*dy ); + double C = a.x()*a.x()+a.y()*a.y() - r*r; + double D = B*B-4*A*C; + + if (D>0.0) { + //Intersections + double sqrtD = sqrt(D); + u1 = 0.5 * ( -B - sqrtD) / A; + u2 = 0.5 * ( -B + sqrtD) / A; + } else if (D<0.0) { + //No intersections: + u1 = u2 = -1.0e99; + } else { + //intersection in one point + u1 = u2 = -0.5*B/A; + } + +} + +//____________________________________________________________________ +bool InDetProjHelper::Imp::clipSegmentToInfiniteHollowCylinder( Amg::Vector3D&a, Amg::Vector3D&b, + const double& rmin, const double& rmax, + Amg::Vector3D&seg2_a, Amg::Vector3D&seg2_b ) const +{ + //* if returns false: segment does not intersect hollow cylinder - do + // NOT use returned points for anything. + //* if returns true and seg2_a==seg2_b: Use "a" and "b" for the clipped segment. + //* if returns true and seg2_a!=seg2_b: The clip resulting in TWO new segments + // (it was cut in two by the inner wall). + + //Fixme: Stuff like the following!: + // if (VP1SanityCheck::enabled()) { + // VP1SanityCheck::beginGroup("InDetProjHelper::Imp::clipSegmentToInfiniteHollowCylinder"); + // VP1SanityCheck::positiveParameter("rmin",rmin); + // VP1SanityCheck::positiveParameter("rmax",rmax); + // VP1SanityCheck::parameter("point a",a); + // VP1SanityCheck::parameter("point b",b); + // VP1SanityCheck::endGroup(); + // } + const double ar2 = a.x()*a.x()+a.y()*a.y(); + const double br2 = b.x()*b.x()+b.y()*b.y(); + const double rmin2 = rmin*rmin; + //We might be inside inner wall: + if (ar2 <= rmin2 && br2 <= rmin2 ) { + // seg2_a=seg2_b; +// if (VP1Msg::verbose()) +// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder Segment entirely inside rmin."); + return false; + } + //Some fast checks for being outside: + if ( (a.x()<=-rmax&&b.x()<=-rmax) || (a.x()>=rmax&&b.x()>=rmax) || (a.y()<=-rmax&&b.y()<=-rmax)|| (a.y()>=rmax&&b.y()>=rmax) ) { +// if (VP1Msg::verbose()) +// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder Segment clearly entirely outside outside rmax."); +// seg2_a=seg2_b; + return false; + } + + //If a==b (apart from perhaps z coord), the check is simple: + const double dx = b.x()-a.x(); + const double dy = b.y()-a.y(); + const double rmax2 = rmax*rmax; + if (dx==0.0&&dy==0.0) { + //Apparently a==b (apart from perhaps z coord). +// if (VP1Msg::verbose()) +// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder a==b."); + return ar2<=rmax2; + } + //Find point which is closest to the z-axis and on the segment: + const double u = - (a.y()*dy+a.x()*dx)/(dx*dx+dy*dy); + const double px = ( u <= 0 ? a.x() : ( u >= 1 ? b.x() : a.x()+u*dx ) ); + const double py = ( u <= 0 ? a.y() : ( u >= 1 ? b.y() : a.y()+u*dy ) ); + const double pr2 = px*px+py*py; + if (pr2>=rmax2) { +// if (VP1Msg::verbose()) +// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder segment entirely outside rmax."); +// seg2_a=seg2_b; + return false; + + + } + //We now know that the segment does indeed intersect the clip volume. + seg2_a=seg2_b;//signature of just one segment: + + if (pr2>=rmin2&&ar2<=rmax2&&br2<=rmax2) { + //We are actually already entirely inside the clip volume. +// if (VP1Msg::verbose()) +// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder segment entirely inside clip volume." +// " (pr="+QString::number(sqrt(pr2))+", ar="+QString::number(sqrt(ar2)) +// +", br="+QString::number(sqrt(br2))+")"); + return true; + } + + //First we simply clip to the outer cylinder: + if (ar2>rmax2||br2>rmax2) { + //We need to clip a-b to be inside the outer cylinder. + //Find intersections: + double u1, u2; + lineCircleIntersection(a,b,rmax,u1,u2);//u1<=u2 ! + if (u1==u2) { + //We are just touching - but we already tested against this! + theclass->message("This should never happen(1)."); + // seg2_a=seg2_b; + return false; + } + Amg::Vector3D asave(a); + if (u1>0&&u1<1) { + //move a to a+u1*(b-a) + a = a+u1*(b-a); +// if (VP1Msg::verbose()) +// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder sliding a towards b, at the rmax circle."); + } + if (u2>0&&u2<1) { + //move b to a+u2*(b-a) + b = asave+u2*(b-asave); +// if (VP1Msg::verbose()) +// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder sliding b towards a, at the rmax circle."); + } + } + + if (pr2>=rmin2) { +// if (VP1Msg::verbose()) +// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder remaining segment is now entirely inside."); + return true; + } + //Ok, we know that we intersect the inner cylinder + double u1, u2; + lineCircleIntersection(a,b,rmin,u1,u2);//u1<=u2 ! + + if (u1>0&&u1<1) { + if (u2>0&&u2<1) { + //We intersect twice. Thus, two line segments: + //a to "a+u1*(b-a)" and "a+u2*(b-a)" to b + //a=a; + seg2_b = b; + b = a+u1*(seg2_b-a); + seg2_a=a+u2*(seg2_b-a); +// if (VP1Msg::verbose()) +// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder Two resulting segments!."); + return true; + } + b = a+u1*(b-a); +// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder One resulting segment (b->a)!."); + return true; + } + if (u2>0&&u2<1) + a = a+u2*(b-a); +// theclass->messageVerbose("clipSegmentToInfiniteHollowCylinder One resulting segment (a->b)!."); + return true; +} + + + +//____________________________________________________________________ +bool InDetProjHelper::Imp::clipSegmentToHollowCylinder( Amg::Vector3D&a, Amg::Vector3D&b, + const double& rmin, const double& rmax, + const double& zmin, const double& zmax, + Amg::Vector3D&seg2_a, Amg::Vector3D&seg2_b ) const +{ + // seg2_a = seg2_b;//test +// if (VP1Msg::verbose()) { +// theclass->messageVerbose("clipSegmentToHollowCylinder called with:"); +// theclass->messageVerbose(" rmin = "+QString::number(rmin)); +// theclass->messageVerbose(" rmax = "+QString::number(rmax)); +// theclass->messageVerbose(" zmin = "+QString::number(zmin)); +// theclass->messageVerbose(" zmax = "+QString::number(zmax)); +// theclass->messageVerbose(" a = ("+QString::number(a.x())+", "+QString::number(a.y())+", "+QString::number(a.z())+")"); +// theclass->messageVerbose(" b = ("+QString::number(b.x())+", "+QString::number(b.y())+", "+QString::number(b.z())+")"); +// } + if (!clipSegmentToZInterval(a,b,zmin,zmax)) { + // seg2_a = seg2_b; +// if (VP1Msg::verbose()) +// theclass->messageVerbose("clipSegmentToHollowCylinder segment outside z-interval."); + return false; + } +// if (VP1Msg::verbose()) { +// theclass->messageVerbose("clipSegmentToHollowCylinder parameters after clipSegmentToZInterval:"); +// if (a.z()<zmin||a.z()>zmax) +// theclass->messageVerbose("clipSegmentToHollowCylinder ERROR in clipSegmentToZInterval call (a_z wrong)."); +// if (b.z()<zmin||b.z()>zmax) +// theclass->messageVerbose("clipSegmentToHollowCylinder ERROR in clipSegmentToZInterval call (b_z wrong)."); +// theclass->messageVerbose(" a = ("+QString::number(a.x())+", "+QString::number(a.y())+", "+QString::number(a.z())+")"); +// theclass->messageVerbose(" b = ("+QString::number(b.x())+", "+QString::number(b.y())+", "+QString::number(b.z())+")"); +// } + if (!clipSegmentToInfiniteHollowCylinder(a,b,rmin,rmax,seg2_a,seg2_b)) { + // seg2_a = seg2_b; +// if (VP1Msg::verbose()) +// theclass->messageVerbose("clipSegmentToHollowCylinder segment outside infinite hollow cylinder."); + return false; + } +// if (VP1Msg::verbose()) { +// theclass->messageVerbose("clipSegmentToHollowCylinder parameters after clipSegmentToInfiniteHollowCylinder:"); +// theclass->messageVerbose(" a = ("+QString::number(a.x())+", "+QString::number(a.y())+", "+QString::number(a.z())+")"); +// theclass->messageVerbose(" b = ("+QString::number(b.x())+", "+QString::number(b.y())+", "+QString::number(b.z())+")"); +// const double ar2 = a.x()*a.x()+a.y()*a.y(); +// const double br2 = b.x()*b.x()+b.y()*b.y(); +// if (ar2<rmin*rmin||ar2>rmax*rmax) +// theclass->messageVerbose("clipSegmentToHollowCylinder ERROR in clipSegmentToInfiniteHollowCylinder call (a wrong)."); +// if (br2<rmin*rmin||br2>rmax*rmax) +// theclass->messageVerbose("clipSegmentToHollowCylinder ERROR in clipSegmentToInfiniteHollowCylinder call (b wrong)."); +// theclass->messageVerbose("clipSegmentToHollowCylinder returning."); +// } + + return true; +} + +//____________________________________________________________________ +void InDetProjHelper::Imp::clipPathToHollowCylinder( const std::vector<Amg::Vector3D >& in, +// Amg::SetVectorVector3D& out, + Amg::SetVectorVector3D& out, + const double& rmin, const double& rmax, + const double& zmin, const double& zmax ) const +{ +// if (VP1Msg::verbose()) { +// theclass->messageVerbose("clipPathToHollowCylinder called"); +// theclass->messageVerbose(" ===> rmin = "+QString::number(rmin)); +// theclass->messageVerbose(" ===> rmax = "+QString::number(rmax)); +// theclass->messageVerbose(" ===> zmin = "+QString::number(zmin)); +// theclass->messageVerbose(" ===> zmax = "+QString::number(zmax)); +// } + + out.clear(); + if (rmin>=rmax||rmin<0||zmin>=zmax) { + theclass->message("clipPathToHollowCylinder Error: Non-sensical cylinder parameters!"); + return; + } + const unsigned n=in.size(); + if (n<2) + return; + + Amg::Vector3D a,b; + Amg::Vector3D seg2_a,seg2_b; + std::vector<Amg::Vector3D > v; + for (unsigned i = 1; i<n; ++i) { + // theclass->messageVerbose("clipPathToHollowCylinder -> dealing with segment "+QString::number(i-1)+"->"+QString::number(i)); + + a = in.at(i-1);//fixme: .at()->[] + b = in.at(i); + if ( clipSegmentToHollowCylinder( a,b,rmin,rmax,zmin,zmax,seg2_a,seg2_b ) ) { + if (v.empty()) { + v.push_back(a); + v.push_back(b); + if (seg2_a!=seg2_b) { + out.insert(v); + v.clear(); + v.push_back(seg2_a); + v.push_back(seg2_b); + } + } else { + //We know that previous segment was also touching. Therefore + //it must necessarily be true that v.back()==a. + if ( v.back() != a ) { + theclass->messageDebug("ERROR: Inconsistency found while building clip part");//Fixme: downgrade to messageDebug for now, but need to understand this! + out.insert(v); + v.clear(); + v.push_back(a); + } + v.push_back(b); + if (seg2_a!=seg2_b) { + out.insert(v); + v.clear(); + v.push_back(seg2_a); + v.push_back(seg2_b); + } + } + } else { +// theclass->messageVerbose("Segment does not touch"); + //Segment doesn't touch cylinder volume - flush part currently building if any. + if (!v.empty()) { + out.insert(v); + v.clear(); + } + } + } + if (!v.empty()) { +// theclass->messageDebug("v not empty"); + out.insert(v); + } +} + +//____________________________________________________________________ +void InDetProjHelper::Imp::projectPathToInfiniteCylinder( const std::vector<Amg::Vector3D >& in, + Amg::SetVectorVector3D& outset, const double& r ) const +{ + std::vector<Amg::Vector3D > out(in); + std::vector<Amg::Vector3D >::iterator it(out.begin()), itE(out.end()); + double s; + for (;it!=itE;++it) { + if ( it->x()==0.0 && it->y()==0.0 ) { + theclass->message("ERROR: Point has x==0 and y==0. Ambiguous projection of point."); + +// it->setX(1.0); + it->x() = 1.0; + } + s = r / sqrt( it->x()*it->x()+it->y()*it->y() ); + +// it->setX(it->x()*s); +// it->setY(it->y()*s); + it->x() = it->x()*s; + it->y() = it->y()*s; + + } + outset.insert(out); +} + +//____________________________________________________________________ +void InDetProjHelper::Imp::projectPathToZPlane( const std::vector<Amg::Vector3D >& in, + Amg::SetVectorVector3D& outset, const double& z ) const +{ + std::vector<Amg::Vector3D > out(in); + std::vector<Amg::Vector3D >::iterator it(out.begin()), itE(out.end()); + for (;it!=itE;++it) { +// it->setZ(z); + it->z() = z; + } + outset.insert(out); +} + + +//____________________________________________________________________ +void InDetProjHelper::transformECPointToZPlane_specialZtoR( Amg::Vector3D& p, + const double& planeZ, + const double& planeRBegin, + const double& endcapZBegin, + const double& squeezeFactor ) +{ + if ( p.x()==0.0 && p.y()==0.0 ) { + VP1Msg::message("InDetProjHelper::transformECPointToZPlane_specialZtoR ERROR: " + "Point has x==0 and y==0. Ambiguous projection of point."); +// p.setX(1.0); + p.x() = 1.0; + } + const double r = planeRBegin + (fabs(p.z())-endcapZBegin)/squeezeFactor; + const double s = r / sqrt( p.x()*p.x()+p.y()*p.y() ); +// p.setX(p.x()*s); +// p.setY(p.y()*s); +// p.setZ(planeZ); + p.x() = p.x()*s; + p.y() = p.y()*s; + p.z() = planeZ; +} + +//____________________________________________________________________ +void InDetProjHelper::Imp::projectPathToZPlane_specialZtoR( const std::vector<Amg::Vector3D >& in, + Amg::SetVectorVector3D& outset, + const double& z ) const +{ + std::vector<Amg::Vector3D > out(in); + std::vector<Amg::Vector3D >::iterator it(out.begin()), itE(out.end()); + for (;it!=itE;++it) + InDetProjHelper::transformECPointToZPlane_specialZtoR(*it, + z, + endcap_zasr_innerradius, + endcap_zasr_endcapz_begin, + endcap_zasr_squeezefact); + outset.insert(out); +} + +//____________________________________________________________________ +void InDetProjHelper::projectPath( const std::vector<Amg::Vector3D >& path, + Amg::SetVectorVector3D& resulting_projs ) const +{ + projectPath(path,resulting_projs,resulting_projs,resulting_projs,resulting_projs); +} + +//____________________________________________________________________ +void InDetProjHelper::projectPath( const std::vector<Amg::Vector3D >& path, + Amg::SetVectorVector3D& resulting_projections_barrelA, + Amg::SetVectorVector3D& resulting_projections_barrelC, + Amg::SetVectorVector3D& resulting_projections_endcapA, + Amg::SetVectorVector3D& resulting_projections_endcapC ) const +{ + if (VP1Msg::verbose()) + messageVerbose("projectPath(..) called. Input path has "+QString::number(path.size())+" points."); + + resulting_projections_barrelA.clear(); + resulting_projections_barrelC.clear(); + resulting_projections_endcapA.clear(); + resulting_projections_endcapC.clear(); + + //Fixme: If verbose - perform sanity check of input data (check for NAN's). + if (m_d->parts == InDetProjFlags::NoProjections ) { + if (VP1Msg::verbose()) + messageVerbose("All projections currently off."); + return; + } + if ( path.size()<2 ) { + if (VP1Msg::verbose()) + messageVerbose("Input path too short."); + return; + } + + // ===> First we must find the clipped path's in all of the enabled detector parts. + + Amg::SetVectorVector3D paths_brlA, paths_brlC, paths_ecA,paths_ecC; + clipPath( path,paths_brlA, paths_brlC, paths_ecA,paths_ecC); + + // ===> Then we project those. + + //Fixme: The dependence on surface thickness and epsilon below is very preliminary. + + const double eps = m_d->data_disttosurface_epsilon; + const double endcapeps(-5*SYSTEM_OF_UNITS::mm);//fixme hardcoding.. + + Amg::SetVectorVector3D::const_iterator it,itE; + + if (m_d->parts & InDetProjFlags::Barrel_AllPos) { + itE = paths_brlA.end(); + if ( m_d->parts & InDetProjFlags::BarrelCentral ) + for ( it = paths_brlA.begin(); it!=itE; ++it ) + m_d->projectPathToZPlane( *it, resulting_projections_barrelA, 0.5*m_d->surfacethickness+eps ); + if ( m_d->parts & InDetProjFlags::BarrelPositive ) + for ( it = paths_brlA.begin(); it!=itE; ++it ) + m_d->projectPathToZPlane( *it, resulting_projections_barrelA, m_d->barrel_posneg_z - eps ); + } + if ( m_d->parts & InDetProjFlags::Barrel_AllNeg ) { + itE = paths_brlC.end(); + if ( m_d->parts & InDetProjFlags::BarrelCentral ) + for ( it = paths_brlC.begin(); it!=itE; ++it ) + m_d->projectPathToZPlane( *it, resulting_projections_barrelC, - 0.5*m_d->surfacethickness - eps); + if ( m_d->parts & InDetProjFlags::BarrelNegative ) + for ( it = paths_brlC.begin(); it!=itE; ++it ) + m_d->projectPathToZPlane( *it, resulting_projections_barrelC, - m_d->barrel_posneg_z ); + } + if ( m_d->parts & InDetProjFlags::EndCap_AllPos ) { + itE = paths_ecA.end(); + if ( m_d->parts & InDetProjFlags::EndCapInnerPositive ) + for ( it = paths_ecA.begin(); it!=itE; ++it ) + m_d->projectPathToInfiniteCylinder( *it, resulting_projections_endcapA, m_d->endcap_inner_radius + eps+endcapeps ); + if ( m_d->parts & InDetProjFlags::EndCapOuterPositive ) + for ( it = paths_ecA.begin(); it!=itE; ++it ) + m_d->projectPathToInfiniteCylinder( *it, resulting_projections_endcapA, m_d->endcap_outer_radius + eps+endcapeps ); + //Fixme: Make sure to use the same parameters here as in PRDHandle_TRT.cxx: + if ( m_d->parts & InDetProjFlags::TRT_EndCapZToRCentral ) + for ( it = paths_ecA.begin(); it!=itE; ++it ) + m_d->projectPathToZPlane_specialZtoR( *it, resulting_projections_endcapA, + 0.5*m_d->surfacethickness + eps ); + //Fixme: Make sure to use the same parameters here as in PRDHandle_TRT.cxx: + if ( m_d->parts & InDetProjFlags::TRT_EndCapZToRPositive ) + for ( it = paths_ecA.begin(); it!=itE; ++it ) + m_d->projectPathToZPlane_specialZtoR( *it, resulting_projections_endcapA, + m_d->barrel_posneg_z - 0.5*m_d->surfacethickness - eps /*fixme: +- epsilon??*/ ); + } + if ( m_d->parts & InDetProjFlags::EndCap_AllNeg ) { + itE = paths_ecC.end(); + if ( m_d->parts & InDetProjFlags::EndCapInnerNegative ) + for ( it = paths_ecC.begin(); it!=itE; ++it ) + m_d->projectPathToInfiniteCylinder( *it, resulting_projections_endcapC, m_d->endcap_inner_radius + eps+endcapeps ); + if ( m_d->parts & InDetProjFlags::EndCapOuterNegative ) + for ( it = paths_ecC.begin(); it!=itE; ++it ) + m_d->projectPathToInfiniteCylinder( *it, resulting_projections_endcapC, m_d->endcap_outer_radius + eps+endcapeps ); + //Fixme: Make sure to use the same parameters here as in PRDHandle_TRT.cxx: + if ( m_d->parts & InDetProjFlags::TRT_EndCapZToRCentral ) + for ( it = paths_ecC.begin(); it!=itE; ++it ) + m_d->projectPathToZPlane_specialZtoR( *it, resulting_projections_endcapC, + - 0.5*m_d->surfacethickness - eps ); + //Fixme: Make sure to use the same parameters here as in PRDHandle_TRT.cxx: + if ( m_d->parts & InDetProjFlags::TRT_EndCapZToRNegative ) + for ( it = paths_ecC.begin(); it!=itE; ++it ) + m_d->projectPathToZPlane_specialZtoR( *it, resulting_projections_endcapC, + - m_d->barrel_posneg_z + 0.5*m_d->surfacethickness + eps/*fixme: +- epsilon??*/ ); + } + +} + +//____________________________________________________________________ +InDetProjHelper::PartsFlags InDetProjHelper::touchedParts( const std::vector<Amg::Vector3D >& path ) const +{ + if (VP1Msg::verbose()) + messageVerbose("touchedParts(..) called. Input path has "+QString::number(path.size())+" points."); + PartsFlags touchedparts = NoParts; + if ( m_d->touchesHollowCylinder(path,m_d->barrel_inner_radius, m_d->barrel_outer_radius, 0, m_d->barrel_posneg_z) ) + touchedparts |= BarrelA; + if ( m_d->touchesHollowCylinder(path,m_d->barrel_inner_radius, m_d->barrel_outer_radius, - m_d->barrel_posneg_z, 0) ) + touchedparts |= BarrelC; + if ( m_d->touchesHollowCylinder(path,m_d->endcap_inner_radius, m_d->endcap_outer_radius, + m_d->endcap_surface_z - m_d->endcap_surface_length * 0.5, m_d->endcap_surface_z + m_d->endcap_surface_length * 0.5 ) ) + touchedparts |= EndCapA; + if ( m_d->touchesHollowCylinder(path, m_d->endcap_inner_radius, m_d->endcap_outer_radius, + - m_d->endcap_surface_z - m_d->endcap_surface_length * 0.5, - m_d->endcap_surface_z + m_d->endcap_surface_length * 0.5) ) + touchedparts |= EndCapC; + return touchedparts; +} + +//____________________________________________________________________ +bool InDetProjHelper::Imp::touchesHollowCylinder( const std::vector<Amg::Vector3D >& path, + const double& rmin, const double& rmax, + const double& zmin, const double& zmax ) const +{ + const double rmin2(rmin*rmin), rmax2(rmax*rmax); + double r2; + std::vector<Amg::Vector3D >::const_iterator it(path.begin()), itE(path.end()); + for (;it!=itE;++it) { + if (it->z()<zmin) + continue; + if (it->z()>zmax) + continue; + r2 = it->x()*it->x()+it->y()*it->y(); + if (r2<rmin2) + continue; + if (r2<=rmax2) + return true; + } + return false; +} diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/ProjectionSurfacesHelper.cxx b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/ProjectionSurfacesHelper.cxx new file mode 100644 index 000000000..e468cabf1 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/ProjectionSurfacesHelper.cxx @@ -0,0 +1,481 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "VTI12GuideLineSystems/ProjectionSurfacesHelper.h" +#include "VTI12GuideLineSystems/InDetProjParams.h" +#include "VP1HEPVis/nodes/SoTubs.h" +#include "VP1Base/VP1Msg.h" + +#include <Inventor/nodes/SoMaterial.h> +#include <Inventor/nodes/SoSeparator.h> +#include <Inventor/nodes/SoTranslation.h> +#include <Inventor/nodes/SoPickStyle.h> + +//____________________________________________________________________ +ProjectionSurfacesHelper * ProjectionSurfacesHelper::createPixelHelper( SoMaterial* mat, + SoSeparator * attachsep, + QObject*parent, + IVP1System* sys ) +{ + return new ProjectionSurfacesHelper( InDetProjParams::surfacethickness(), + InDetProjParams::pixel_barrel_inner_radius(), + InDetProjParams::pixel_barrel_outer_radius(), + InDetProjParams::pixel_barrel_posneg_z(), + InDetProjParams::pixel_endcap_surface_z(), + InDetProjParams::pixel_endcap_surface_length(), + InDetProjParams::pixel_endcap_inner_radius(), + InDetProjParams::pixel_endcap_outer_radius(), + InDetProjParams::pixel_endcap_zasr_disttobarrelcyl(), + InDetProjParams::pixel_endcap_zasr_squeezefact(), + mat, attachsep, parent,sys ); +} + +//____________________________________________________________________ +ProjectionSurfacesHelper * ProjectionSurfacesHelper::createSCTHelper( SoMaterial* mat, + SoSeparator * attachsep, + QObject*parent, + IVP1System* sys ) +{ + return new ProjectionSurfacesHelper( InDetProjParams::surfacethickness(), + InDetProjParams::sct_barrel_inner_radius(), + InDetProjParams::sct_barrel_outer_radius(), + InDetProjParams::sct_barrel_posneg_z(), + InDetProjParams::sct_endcap_surface_z(), + InDetProjParams::sct_endcap_surface_length(), + InDetProjParams::sct_endcap_inner_radius(), + InDetProjParams::sct_endcap_outer_radius(), + InDetProjParams::sct_endcap_zasr_disttobarrelcyl(), + InDetProjParams::sct_endcap_zasr_squeezefact(), + mat, attachsep, parent,sys ); +} + +//____________________________________________________________________ +ProjectionSurfacesHelper * ProjectionSurfacesHelper::createTRTHelper( SoMaterial* mat, + SoSeparator * attachsep, + QObject*parent, + IVP1System* sys ) +{ + return new ProjectionSurfacesHelper( InDetProjParams::surfacethickness(), + InDetProjParams::trt_barrel_inner_radius(), + InDetProjParams::trt_barrel_outer_radius(), + InDetProjParams::trt_barrel_posneg_z(), + InDetProjParams::trt_endcap_surface_z(), + InDetProjParams::trt_endcap_surface_length(), + InDetProjParams::trt_endcap_inner_radius(), + InDetProjParams::trt_endcap_outer_radius(), + InDetProjParams::trt_endcap_zasr_disttobarrelcyl(), + InDetProjParams::trt_endcap_zasr_squeezefact(), + mat, attachsep, parent,sys ); +} + +//____________________________________________________________________ +class ProjectionSurfacesHelper::Imp { +public: + Imp(ProjectionSurfacesHelper*tc,SoSeparator * as) : theclass(tc), + attachsep(as), + parts(InDetProjFlags::NoProjections), + material(0), + sep(0), + barrelcylshape(0), + endcapinnershape(0), + endcapoutershape(0), + endcapzasrcylshape(0), + sep_barrel_central(0), + sep_barrel_pos(0), + sep_barrel_neg(0), + sep_endcap_inner_pos(0), + sep_endcap_outer_pos(0), + sep_endcap_inner_neg(0), + sep_endcap_outer_neg(0), + sep_endcap_zasr_central(0), + sep_endcap_zasr_pos(0), + sep_endcap_zasr_neg(0), + surfacethickness(0), + barrel_inner_radius(0), + barrel_outer_radius(0), + barrel_posneg_z(0), + endcap_surface_z(0), + endcap_surface_length(0), + endcap_inner_radius(0), + endcap_outer_radius(0), + endcap_zasr_disttobarrelcyl(0), + endcap_zasr_squeezefact(0) + { + if (as) + as->ref(); + } + + ProjectionSurfacesHelper * theclass; + SoSeparator * attachsep; + InDetProjFlags::InDetProjPartsFlags parts; + + SoMaterial * material; + SoSeparator * sep; + SoShape * barrelcylshape; + SoShape * endcapinnershape; + SoShape * endcapoutershape; + SoShape * endcapzasrcylshape; + SoShape * barrelCylShape(); + SoShape * endcapInnerShape(); + SoShape * endcapOuterShape(); + SoShape * endcapZAsRCylShape(); + + SoSeparator * sep_barrel_central; + SoSeparator * sep_barrel_pos; + SoSeparator * sep_barrel_neg; + SoSeparator * sep_endcap_inner_pos; + SoSeparator * sep_endcap_outer_pos; + SoSeparator * sep_endcap_inner_neg; + SoSeparator * sep_endcap_outer_neg; + SoSeparator * sep_endcap_zasr_central; + SoSeparator * sep_endcap_zasr_pos; + SoSeparator * sep_endcap_zasr_neg; + + void initPartsSep(float zpos, SoSeparator*&sep, SoShape*); + + void ensureDetached(SoSeparator*); + void ensureAttached(SoSeparator*); + + //The parameters: + double surfacethickness; + double barrel_inner_radius; + double barrel_outer_radius; + double barrel_posneg_z; + double endcap_surface_z; + double endcap_surface_length; + double endcap_inner_radius; + double endcap_outer_radius; + double endcap_zasr_disttobarrelcyl; + double endcap_zasr_squeezefact; + static const int nphi = 64; +}; + +//____________________________________________________________________ +ProjectionSurfacesHelper::ProjectionSurfacesHelper( double surfacethickness, + double barrel_inner_radius, + double barrel_outer_radius, + double barrel_posneg_z, + double endcap_surface_z, + double endcap_surface_length, + double endcap_inner_radius, + double endcap_outer_radius, + double endcap_zasr_disttobarrelcyl, + double endcap_zasr_squeezefact, + SoMaterial* mat, SoSeparator * attachsep, QObject * parent,IVP1System*sys) + : QObject(parent), VP1HelperClassBase(sys,"ProjectionSurfacesHelper"), m_d(new Imp(this,attachsep)) +{ + m_d->material = mat; + if (m_d->material) + m_d->material->ref(); + m_d->sep = 0; + m_d->barrelcylshape = 0; + m_d->endcapinnershape = 0; + m_d->endcapoutershape = 0; + m_d->endcapzasrcylshape = 0; + m_d->sep_barrel_central = 0; + m_d->sep_barrel_pos = 0; + m_d->sep_barrel_neg = 0; + m_d->sep_endcap_inner_pos = 0; + m_d->sep_endcap_outer_pos = 0; + m_d->sep_endcap_inner_neg = 0; + m_d->sep_endcap_outer_neg = 0; + m_d->sep_endcap_zasr_central = 0; + m_d->sep_endcap_zasr_pos = 0; + m_d->sep_endcap_zasr_neg = 0; + + m_d->surfacethickness = surfacethickness; + m_d->barrel_inner_radius = barrel_inner_radius; + m_d->barrel_outer_radius = barrel_outer_radius; + m_d->barrel_posneg_z = barrel_posneg_z; + m_d->endcap_surface_z = endcap_surface_z; + m_d->endcap_surface_length = endcap_surface_length; + m_d->endcap_inner_radius = endcap_inner_radius; + m_d->endcap_outer_radius = endcap_outer_radius; + m_d->endcap_zasr_disttobarrelcyl = endcap_zasr_disttobarrelcyl; + m_d->endcap_zasr_squeezefact = endcap_zasr_squeezefact; +} + +//____________________________________________________________________ +ProjectionSurfacesHelper::~ProjectionSurfacesHelper() +{ + messageVerbose("destructor begin"); + QList<SoNode*> l; + + l << m_d->attachsep + << m_d->material + << m_d->sep + << m_d->barrelcylshape + << m_d->endcapinnershape + << m_d->endcapoutershape + << m_d->endcapzasrcylshape + << m_d->sep_barrel_central + << m_d->sep_barrel_pos + << m_d->sep_barrel_neg + << m_d->sep_endcap_inner_pos + << m_d->sep_endcap_outer_pos + << m_d->sep_endcap_inner_neg + << m_d->sep_endcap_outer_neg + << m_d->sep_endcap_zasr_central + << m_d->sep_endcap_zasr_pos + << m_d->sep_endcap_zasr_neg; + + foreach(SoNode* n, l) + if (n) + n->unref(); + + delete m_d; + messageVerbose("destructor end"); +} + +//____________________________________________________________________ +InDetProjFlags::InDetProjPartsFlags ProjectionSurfacesHelper::shownParts() const +{ + if (VP1Msg::verbose()) + messageVerbose("shownParts"); + return m_d->parts; +} + +//____________________________________________________________________ +void ProjectionSurfacesHelper::setSurfaces( InDetProjFlags::InDetProjPartsFlags newparts ) +{ + messageVerbose("setSurfaces"); + if (m_d->parts==newparts) + return; + messageVerbose("setSurfaces - changed"); + InDetProjFlags::InDetProjPartsFlags changedparts(m_d->parts ^ newparts); + m_d->parts = newparts; + bool save = m_d->attachsep->enableNotify(false); + + ////////////////////////////////////////////// + + if (changedparts&InDetProjFlags::BarrelPositive) { + if (newparts&InDetProjFlags::BarrelPositive) { + if (!m_d->sep_barrel_pos) + m_d->initPartsSep(m_d->barrel_posneg_z,m_d->sep_barrel_pos,m_d->barrelCylShape()); + m_d->ensureAttached(m_d->sep_barrel_pos); + } else { + m_d->ensureDetached(m_d->sep_barrel_pos); + } + } + if (changedparts&InDetProjFlags::BarrelNegative) { + if (newparts&InDetProjFlags::BarrelNegative) { + if (!m_d->sep_barrel_neg) + m_d->initPartsSep(-m_d->barrel_posneg_z,m_d->sep_barrel_neg,m_d->barrelCylShape()); + m_d->ensureAttached(m_d->sep_barrel_neg); + } else { + m_d->ensureDetached(m_d->sep_barrel_neg); + } + } + if (changedparts&InDetProjFlags::BarrelCentral) { + if (newparts&InDetProjFlags::BarrelCentral) { + if (!m_d->sep_barrel_central) + m_d->initPartsSep(0.0,m_d->sep_barrel_central,m_d->barrelCylShape()); + m_d->ensureAttached(m_d->sep_barrel_central); + } else { + m_d->ensureDetached(m_d->sep_barrel_central); + } + } + if (changedparts&InDetProjFlags::EndCapInnerPositive) { + if (newparts&InDetProjFlags::EndCapInnerPositive) { + if (!m_d->sep_endcap_inner_pos) + m_d->initPartsSep(m_d->endcap_surface_z,m_d->sep_endcap_inner_pos,m_d->endcapInnerShape()); + m_d->ensureAttached(m_d->sep_endcap_inner_pos); + } else { + m_d->ensureDetached(m_d->sep_endcap_inner_pos); + } + } + if (changedparts&InDetProjFlags::EndCapOuterPositive) { + if (newparts&InDetProjFlags::EndCapOuterPositive) { + if (!m_d->sep_endcap_outer_pos) + m_d->initPartsSep(m_d->endcap_surface_z,m_d->sep_endcap_outer_pos,m_d->endcapOuterShape()); + m_d->ensureAttached(m_d->sep_endcap_outer_pos); + } else { + m_d->ensureDetached(m_d->sep_endcap_outer_pos); + } + } + if (changedparts&InDetProjFlags::EndCapInnerNegative) { + if (newparts&InDetProjFlags::EndCapInnerNegative) { + if (!m_d->sep_endcap_inner_neg) + m_d->initPartsSep(-m_d->endcap_surface_z,m_d->sep_endcap_inner_neg,m_d->endcapInnerShape()); + m_d->ensureAttached(m_d->sep_endcap_inner_neg); + } else { + m_d->ensureDetached(m_d->sep_endcap_inner_neg); + } + } + if (changedparts&InDetProjFlags::EndCapOuterNegative) { + if (newparts&InDetProjFlags::EndCapOuterNegative) { + if (!m_d->sep_endcap_outer_neg) + m_d->initPartsSep(-m_d->endcap_surface_z,m_d->sep_endcap_outer_neg,m_d->endcapOuterShape()); + m_d->ensureAttached(m_d->sep_endcap_outer_neg); + } else { + m_d->ensureDetached(m_d->sep_endcap_outer_neg); + } + } + if (changedparts&InDetProjFlags::TRT_EndCapZToRCentral) { + if (newparts&InDetProjFlags::TRT_EndCapZToRCentral) { + if (!m_d->sep_endcap_zasr_central) + m_d->initPartsSep(0.0,m_d->sep_endcap_zasr_central,m_d->endcapZAsRCylShape()); + m_d->ensureAttached(m_d->sep_endcap_zasr_central); + } else { + m_d->ensureDetached(m_d->sep_endcap_zasr_central); + } + } + if (changedparts&InDetProjFlags::TRT_EndCapZToRPositive) { + if (newparts&InDetProjFlags::TRT_EndCapZToRPositive) { + if (!m_d->sep_endcap_zasr_pos) + m_d->initPartsSep(m_d->barrel_posneg_z,m_d->sep_endcap_zasr_pos,m_d->endcapZAsRCylShape()); + m_d->ensureAttached(m_d->sep_endcap_zasr_pos); + } else { + m_d->ensureDetached(m_d->sep_endcap_zasr_pos); + } + } + if (changedparts&InDetProjFlags::TRT_EndCapZToRNegative) { + if (newparts&InDetProjFlags::TRT_EndCapZToRNegative) { + if (!m_d->sep_endcap_zasr_neg) + m_d->initPartsSep(-m_d->barrel_posneg_z,m_d->sep_endcap_zasr_neg,m_d->endcapZAsRCylShape()); + m_d->ensureAttached(m_d->sep_endcap_zasr_neg); + } else { + m_d->ensureDetached(m_d->sep_endcap_zasr_neg); + } + } + + ////////////////////////////////////////////// + m_d->attachsep->enableNotify(save); + if (save) + m_d->attachsep->touch(); + messageVerbose("setSurfaces - changed end"); +} + +//____________________________________________________________________ +void ProjectionSurfacesHelper::Imp::initPartsSep(float zpos, SoSeparator*&sep, SoShape*shape) +{ + theclass->messageVerbose("initPartsSep begin"); + sep = new SoSeparator(); + sep->ref(); + if (zpos!=0.0f) { + SoTranslation * t = new SoTranslation; + t->translation.setValue(0.0f,0.0f,zpos); + sep->addChild(t); + } + sep->addChild(shape); + theclass->messageVerbose("initPartsSep end"); +} + +//____________________________________________________________________ +SoMaterial * ProjectionSurfacesHelper::material() +{ + if (VP1Msg::verbose()) + messageVerbose("material"); + return m_d->material; +} + +//____________________________________________________________________ +SoShape * ProjectionSurfacesHelper::Imp::barrelCylShape() +{ + theclass->messageVerbose("barrelCylShape"); + if (!barrelcylshape) { + SoTubs::initClass(); + SoTubs * disc = new SoTubs; + disc->pRMin = barrel_inner_radius; + disc->pRMax = barrel_outer_radius; + disc->pDz = 0.5*surfacethickness; + disc->pSPhi = 0.0; + disc->pDPhi = 2*M_PI; + disc->pOverrideNPhi = nphi;//Ignore complexity and just use a good amount of subdivisions =n*32 (its just a single surface anyway) + barrelcylshape = disc; + barrelcylshape->ref(); + } + return barrelcylshape; +} + +//____________________________________________________________________ +SoShape * ProjectionSurfacesHelper::Imp::endcapInnerShape() +{ + theclass->messageVerbose("endcapInnerShape"); + if (!endcapinnershape) { + SoTubs::initClass(); + SoTubs * cyl = new SoTubs; + cyl->pRMax = endcap_inner_radius; + cyl->pRMin = endcap_inner_radius-surfacethickness; + cyl->pDz = 0.5*endcap_surface_length; + cyl->pSPhi = 0.0; + cyl->pDPhi = 2*M_PI; + cyl->pOverrideNPhi = nphi;//Ignore complexity and just use a good amount of subdivisions =n*32 (its just a single surface anyway) + endcapinnershape = cyl; + endcapinnershape->ref(); + } + return endcapinnershape; +} + +//____________________________________________________________________ +SoShape * ProjectionSurfacesHelper::Imp::endcapOuterShape() +{ + theclass->messageVerbose("endcapOuterShape"); + if (!endcapoutershape) { + SoTubs::initClass(); + SoTubs * cyl = new SoTubs; + cyl->pRMax = endcap_outer_radius; + cyl->pRMin = endcap_outer_radius-surfacethickness; + cyl->pDz = 0.5*endcap_surface_length; + cyl->pSPhi = 0.0; + cyl->pDPhi = 2*M_PI; + cyl->pOverrideNPhi = nphi;//Ignore complexity and just use a good amount of subdivisions =n*32 (its just a single surface anyway) + endcapoutershape = cyl; + endcapoutershape->ref(); + } + return endcapoutershape; +} + +//____________________________________________________________________ +SoShape * ProjectionSurfacesHelper::Imp::endcapZAsRCylShape() +{ + theclass->messageVerbose("endcapZAsRCylShape"); + if (!endcapzasrcylshape) { + SoTubs::initClass(); + SoTubs * disc = new SoTubs; + double rmin = barrel_outer_radius+endcap_zasr_disttobarrelcyl; + disc->pRMin = rmin; + disc->pRMax = rmin + endcap_surface_length/endcap_zasr_squeezefact; + disc->pDz = 0.5*surfacethickness; + disc->pSPhi = 0.0; + disc->pDPhi = 2*M_PI; + disc->pOverrideNPhi = nphi;//Ignore complexity and just use a good amount of subdivisions =n*32 (its just a single surface anyway) + endcapzasrcylshape = disc; + endcapzasrcylshape->ref(); + } + return endcapzasrcylshape; +} + +//____________________________________________________________________ +void ProjectionSurfacesHelper::Imp::ensureDetached(SoSeparator*s) +{ + if (VP1Msg::verbose()) + theclass->messageVerbose("ensureDetached"); + if (!sep||!s) + return; + if (sep->findChild(s)>-1) + sep->removeChild(s); +} + +//____________________________________________________________________ +void ProjectionSurfacesHelper::Imp::ensureAttached(SoSeparator*s) +{ + if (VP1Msg::verbose()) + theclass->messageVerbose("ensureAttached"); + if (!s) + return; + if (!sep) { + sep = new SoSeparator; + sep->ref(); + SoPickStyle *pickStyle = new SoPickStyle; + pickStyle->style=SoPickStyle::UNPICKABLE; + sep->addChild(pickStyle); + if (material) + sep->addChild(material); + attachsep->addChild(sep); + } + sep->addChild(s); + if (VP1Msg::verbose()) + theclass->messageVerbose("ensureAttached done"); +} diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1CartesianGrid.cxx b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1CartesianGrid.cxx new file mode 100644 index 000000000..29ecb6c74 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1CartesianGrid.cxx @@ -0,0 +1,213 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class VP1CartesianGrid // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: July 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12GuideLineSystems/VP1CartesianGrid.h" +#include "VTI12GuideLineSystems/VP1Floor.h"//for calcPars... static method + +#include <Inventor/nodes/SoSeparator.h> +#include <Inventor/nodes/SoVertexProperty.h> +#include <Inventor/nodes/SoLineSet.h> +#include <Inventor/SbColor4f.h> + +#ifdef BUILDVP1LIGHT + #include "CLHEP/Units/SystemOfUnits.h" + #define SYSTEM_OF_UNITS CLHEP +#else + #include "GaudiKernel/SystemOfUnits.h" + #define SYSTEM_OF_UNITS Gaudi::Units +#endif + +//____________________________________________________________________ +class VP1CartesianGrid::Imp { +public: + Imp(VP1CartesianGrid *, + SoSeparator * attachsep); + VP1CartesianGrid * theclass; + SoSeparator * attachSep; + + bool shown; + SbColor4f colourAndTransp; + double extent; + double spacing; + + SoSeparator * sep; + + void rebuild3DObjects(); + void updateColour(); +}; + +//____________________________________________________________________ +VP1CartesianGrid::VP1CartesianGrid(SoSeparator * attachsep, + IVP1System * sys,QObject * parent) + : QObject(parent), VP1HelperClassBase(sys,"VP1CartesianGrid"), m_d(new Imp(this,attachsep)) +{ +} + +//____________________________________________________________________ +VP1CartesianGrid::~VP1CartesianGrid() +{ + setShown(false); + if (m_d->sep) + m_d->sep->unref(); + m_d->attachSep->unref(); + delete m_d; +} + +//____________________________________________________________________ +VP1CartesianGrid::Imp::Imp(VP1CartesianGrid *tc,SoSeparator * as) + : theclass(tc), attachSep(as), shown(false), + colourAndTransp(SbColor4f(1,1,1,1)),extent(10), spacing(1), sep(0) +{ + attachSep->ref(); +} + +//____________________________________________________________________ +void VP1CartesianGrid::Imp::rebuild3DObjects() +{ + theclass->messageVerbose("(Re)building 3D objects"); + + if (sep) { + sep->removeAllChildren(); + } else { + sep = new SoSeparator; + sep->ref(); + } + + const bool save = sep->enableNotify(false); + + int nmax; double distmax; + if (!VP1Floor::calcParsFromExtentAndSpacing( theclass, extent, spacing, 40/*max lines*/, nmax, distmax )) { + nmax = 10; + distmax = 10*SYSTEM_OF_UNITS::m; + theclass->message("ERROR: Problems calculating nmax/distmax."); + } + + SoVertexProperty * grid_cartesian_vertices = new SoVertexProperty(); + + int ivert(0); + int nsublines(0); + + //First, loop over (x,z) values and add one line parallel with the y-axis through each. + for (int ix = -nmax; ix<=nmax; ++ix) + for (int iz = -nmax; iz<=nmax; ++iz) { + double x = ix*spacing; + double z = iz*spacing; + grid_cartesian_vertices->vertex.set1Value(ivert++,x,-distmax,z); + grid_cartesian_vertices->vertex.set1Value(ivert++,x,+distmax,z); + ++nsublines; + } + + //Next, loop over y values and add a plane of lines parallel to the x-z plane. + for (int iy = -nmax; iy<=nmax; ++iy) { + double y = iy*spacing; + for (int ix = -nmax; ix<=nmax; ++ix) { + double x = ix*spacing; + grid_cartesian_vertices->vertex.set1Value(ivert++,x,y,-distmax); + grid_cartesian_vertices->vertex.set1Value(ivert++,x,y,+distmax); + ++nsublines; + } + for (int iz = -nmax; iz<=nmax; ++iz) { + double z = iz*spacing; + grid_cartesian_vertices->vertex.set1Value(ivert++,-distmax,y,z); + grid_cartesian_vertices->vertex.set1Value(ivert++,+distmax,y,z); + ++nsublines; + } + } + + grid_cartesian_vertices->materialBinding=SoMaterialBinding::OVERALL; + grid_cartesian_vertices->normalBinding=SoNormalBinding::OVERALL; + SoLineSet * line = new SoLineSet(); + line->numVertices.enableNotify(FALSE); + line->numVertices.setNum(nsublines); + for (int i=0;i<nsublines;++i) + line->numVertices.set1Value(i,2); + line->vertexProperty = grid_cartesian_vertices; + line->numVertices.enableNotify(TRUE); + line->numVertices.touch(); + + sep->addChild(line); + updateColour(); + + if (save) { + sep->enableNotify(true); + sep->touch(); + } + +} + +//____________________________________________________________________ +void VP1CartesianGrid::Imp::updateColour() +{ + theclass->messageVerbose("Updating packed colour"); + if (!sep||sep->getNumChildren()<1) + return; + SoNode * n = sep->getChild(0); + if (!n||n->getTypeId()!=SoLineSet::getClassTypeId()) + return; + SoLineSet * line = static_cast<SoLineSet*>(n); + SoVertexProperty * vertices = static_cast<SoVertexProperty *>(line->vertexProperty.getValue()); + if (!vertices) + return; + vertices->orderedRGBA = colourAndTransp.getPackedValue(); +} + +//____________________________________________________________________ +void VP1CartesianGrid::setShown(bool b) +{ + messageVerbose("Signal received: setShown("+str(b)+")"); + if (m_d->shown==b) + return; + m_d->shown=b; + if (m_d->shown) { + m_d->rebuild3DObjects(); + if (m_d->attachSep->findChild(m_d->sep)<0) + m_d->attachSep->addChild(m_d->sep); + } else { + if (m_d->sep&&m_d->attachSep->findChild(m_d->sep)>=0) + m_d->attachSep->removeChild(m_d->sep); + } +} + +//____________________________________________________________________ +void VP1CartesianGrid::setColourAndTransp(const SbColor4f&ct) +{ + messageVerbose("Signal received in setColourAndTransp slot."); + if (m_d->colourAndTransp==ct) + return; + m_d->colourAndTransp=ct; + if (m_d->shown) + m_d->updateColour(); +} + +//____________________________________________________________________ +void VP1CartesianGrid::setExtent(const double& e) +{ + messageVerbose("Signal received: setExtent("+str(e)+")"); + if (m_d->extent==e) + return; + m_d->extent=e; + if (m_d->shown) + m_d->rebuild3DObjects(); +} + +//____________________________________________________________________ +void VP1CartesianGrid::setSpacing(const double&s) +{ + messageVerbose("Signal received: setSpacing("+str(s)+")"); + if (m_d->spacing==s) + return; + m_d->spacing=s; + if (m_d->shown) + m_d->rebuild3DObjects(); +} diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1CoordinateAxes.cxx b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1CoordinateAxes.cxx new file mode 100644 index 000000000..74ec06e97 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1CoordinateAxes.cxx @@ -0,0 +1,228 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class VP1CoordinateAxes // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: April 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12GuideLineSystems/VP1CoordinateAxes.h" +#include "VP1Base/VP1QtUtils.h" +#include <Inventor/C/errors/debugerror.h> +#include <Inventor/nodes/SoMaterial.h> +#include <Inventor/nodes/SoSeparator.h> +#include <Inventor/nodes/SoCylinder.h> +#include <Inventor/nodes/SoCone.h> +#include <Inventor/nodes/SoTranslation.h> +#include <Inventor/nodes/SoRotationXYZ.h> +#include <Inventor/nodes/SoSphere.h> + +//____________________________________________________________________ +class VP1CoordinateAxes::Imp { +public: + Imp(VP1CoordinateAxes *, + SoMaterial * xmat, + SoMaterial * ymat, + SoMaterial * zmat, + SoSeparator * attachsep); + VP1CoordinateAxes * theclass; + SoMaterial * materialXAxis; + SoMaterial * materialYAxis; + SoMaterial * materialZAxis; + SoSeparator * attachSep; + + bool shown; + SbVec3f origo; + double axislength;//negative means show negative parts + double relaxisthick; + + SoSeparator * sep; + SoTranslation * overall_translation; + SoSphere * alternative_Sphere; + SoSeparator * singleaxis_sep; + SoCylinder * singleaxis_cyl; + SoCone * singleaxis_cone; + SoTranslation * singleaxis_cyltranslation; + SoTranslation * singleaxis_conetranslation; + + void updateFields(); + void ensureInit3DObjects(); +}; + +//____________________________________________________________________ +VP1CoordinateAxes::VP1CoordinateAxes(SoMaterial * xmat,SoMaterial * ymat,SoMaterial * zmat, + SoSeparator * attachsep, + IVP1System * sys,QObject * parent) + : QObject(parent), VP1HelperClassBase(sys,"VP1CoordinateAxes"), m_d(new Imp(this,xmat,ymat,zmat,attachsep)) +{ +} + +//____________________________________________________________________ +VP1CoordinateAxes::~VP1CoordinateAxes() +{ + setShown(false); + if (m_d->sep) + m_d->sep->unref(); + if (m_d->singleaxis_sep) + m_d->singleaxis_sep->unref(); + m_d->materialXAxis->unref(); + m_d->materialYAxis->unref(); + m_d->materialZAxis->unref(); + m_d->attachSep->unref(); + delete m_d; +} + +//____________________________________________________________________ +VP1CoordinateAxes::Imp::Imp(VP1CoordinateAxes *tc,SoMaterial * xmat,SoMaterial * ymat,SoMaterial * zmat,SoSeparator * as) + : theclass(tc), materialXAxis(xmat), materialYAxis(ymat), materialZAxis(zmat), attachSep(as), shown(false), + origo(SbVec3f(0,0,0)), axislength(1), relaxisthick(0.1), + sep(0), overall_translation(0), alternative_Sphere(0), singleaxis_sep(0), singleaxis_cyl(0), + singleaxis_cone(0), singleaxis_cyltranslation(0), singleaxis_conetranslation(0) +{ + materialXAxis->ref(); + materialYAxis->ref(); + materialZAxis->ref(); + attachSep->ref(); +} + +//____________________________________________________________________ +void VP1CoordinateAxes::Imp::ensureInit3DObjects() +{ + if (sep) + return; + theclass->messageVerbose("Building 3D objects"); + sep = new SoSeparator; sep->ref(); + + singleaxis_sep = new SoSeparator; singleaxis_sep->ref(); + singleaxis_cyltranslation = new SoTranslation; singleaxis_sep->addChild(singleaxis_cyltranslation); + singleaxis_cyl = new SoCylinder; singleaxis_sep->addChild(singleaxis_cyl); + singleaxis_conetranslation = new SoTranslation; singleaxis_sep->addChild(singleaxis_conetranslation); + singleaxis_cone = new SoCone; singleaxis_sep->addChild(singleaxis_cone); + + overall_translation = new SoTranslation; + + sep->addChild(overall_translation); + + #if defined BUILDVP1LIGHT + const bool alternativeRep = VP1QtUtils::expertSettingIsOn("general","ExpertSettings/VP1_GUIDES_SPHERE_INSTEAD_OF_COORDAXES"); + #else + const bool alternativeRep = VP1QtUtils::environmentVariableIsOn("VP1_GUIDES_SPHERE_INSTEAD_OF_COORDAXES"); + #endif + + if (alternativeRep) { + sep->addChild(materialXAxis); + alternative_Sphere = new SoSphere; + sep->addChild(alternative_Sphere); + return; + } + + + sep->addChild(materialYAxis); + sep->addChild(singleaxis_sep);//Single-axis points towards y by default. + + SoRotationXYZ * rotx = new SoRotationXYZ; + rotx->axis.setValue(SoRotationXYZ::Z); + rotx->angle.setValue(-0.5*M_PI); + sep->addChild(rotx); + + sep->addChild(materialXAxis); + sep->addChild(singleaxis_sep);//Single-axis points towards y by default. + + + SoRotationXYZ * rotz = new SoRotationXYZ; + rotz->axis.setValue(SoRotationXYZ::X); + rotz->angle.setValue(0.5*M_PI); + sep->addChild(rotz); + + sep->addChild(materialZAxis); + sep->addChild(singleaxis_sep);//Single-axis points towards y by default. + + singleaxis_cyl->parts.setValue(SoCylinder::SIDES|SoCylinder::BOTTOM); +} + +//____________________________________________________________________ +void VP1CoordinateAxes::Imp::updateFields() +{ + ensureInit3DObjects(); + theclass->messageVerbose("Updating fields"); + + const bool save = sep->enableNotify(false); + + const double cylradius = relaxisthick*fabs(axislength); + const double coneradius = 1.5*cylradius; + const double coneheight = 2.0*coneradius; + overall_translation->translation.setValue(origo); + + if (alternative_Sphere) { + alternative_Sphere->radius.setValue(fabs(axislength)); + } else { + singleaxis_cyltranslation->translation.setValue(0.0,(axislength<0?0.0:0.5*fabs(axislength))-0.5*coneheight,0.0); + singleaxis_cyl->radius.setValue(cylradius); + singleaxis_cyl->height.setValue( (axislength<0 ? 2.0 : 1.0) * fabs(axislength) - coneheight ); + singleaxis_conetranslation->translation.setValue(0.0,(axislength<0?1.0:0.5)*fabs(axislength),0.0); + singleaxis_cone->bottomRadius.setValue(coneradius); + singleaxis_cone->height.setValue(coneheight); + } + + if (save) { + sep->enableNotify(true); + sep->touch(); + } +} + +//____________________________________________________________________ +void VP1CoordinateAxes::setShown(bool b) +{ + messageVerbose("Signal received: setShown("+str(b)+")"); + if (m_d->shown==b) + return; + m_d->shown=b; + if (m_d->shown) { + m_d->updateFields(); + if (m_d->attachSep->findChild(m_d->sep)<0) + m_d->attachSep->addChild(m_d->sep); + } else { + if (m_d->sep&&m_d->attachSep->findChild(m_d->sep)>=0) + m_d->attachSep->removeChild(m_d->sep); + } +} + +//____________________________________________________________________ +void VP1CoordinateAxes::setPosition(const SbVec3f& o) +{ + messageVerbose("Signal received: setPosition("+str(o)+")"); + if (m_d->origo==o) + return; + m_d->origo=o; + if (m_d->shown) + m_d->updateFields(); +} + + +//____________________________________________________________________ +void VP1CoordinateAxes::setLength(const double&l) +{ + messageVerbose("Signal received: setLength("+str(l)+")"); + if (m_d->axislength==l) + return; + m_d->axislength=l; + if (m_d->shown) + m_d->updateFields(); +} + +//____________________________________________________________________ +void VP1CoordinateAxes::setRelativeAxisThickness(const double& t) +{ + messageVerbose("Signal received: setRelativeAxisThickness("+str(t)+")"); + if (m_d->relaxisthick==t) + return; + m_d->relaxisthick=t; + if (m_d->shown) + m_d->updateFields(); +} diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1CylindricalGrid.cxx b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1CylindricalGrid.cxx new file mode 100644 index 000000000..6b05136ca --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1CylindricalGrid.cxx @@ -0,0 +1,241 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class VP1CylindricalGrid // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: July 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12GuideLineSystems/VP1CylindricalGrid.h" +#include "VTI12GuideLineSystems/VP1Floor.h"//for calcPars... static method +#include "VP1Base/VP1QtInventorUtils.h" + +#include <Inventor/nodes/SoSeparator.h> +#include <Inventor/nodes/SoVertexProperty.h> +#include <Inventor/nodes/SoLineSet.h> +#include <Inventor/nodes/SoTranslation.h> +#include <Inventor/nodes/SoPackedColor.h> +#include <Inventor/SbColor4f.h> + +#ifdef BUILDVP1LIGHT + #include "CLHEP/Units/SystemOfUnits.h" + #define SYSTEM_OF_UNITS CLHEP +#else + #include "GaudiKernel/SystemOfUnits.h" + #define SYSTEM_OF_UNITS Gaudi::Units +#endif + +//____________________________________________________________________ +class VP1CylindricalGrid::Imp { +public: + Imp(VP1CylindricalGrid *, + SoSeparator * attachsep); + VP1CylindricalGrid * theclass; + SoSeparator * attachSep; + + bool shown; + SbColor4f colourAndTransp; + double extent; + double spacing; + + SoSeparator * sep; + SoPackedColor * circlecol; + + void rebuild3DObjects(); + void updateColour(); +}; + +//____________________________________________________________________ +VP1CylindricalGrid::VP1CylindricalGrid(SoSeparator * attachsep, + IVP1System * sys,QObject * parent) + : QObject(parent), VP1HelperClassBase(sys,"VP1CylindricalGrid"), m_d(new Imp(this,attachsep)) +{ +} + +//____________________________________________________________________ +VP1CylindricalGrid::~VP1CylindricalGrid() +{ + setShown(false); + if (m_d->sep) + m_d->sep->unref(); + if (m_d->circlecol) + m_d->circlecol->unref(); + m_d->attachSep->unref(); + delete m_d; +} + +//____________________________________________________________________ +VP1CylindricalGrid::Imp::Imp(VP1CylindricalGrid *tc,SoSeparator * as) + : theclass(tc), attachSep(as), shown(false), + colourAndTransp(SbColor4f(1,1,1,1)),extent(10), spacing(1), + sep(0), circlecol(0) +{ + attachSep->ref(); +} + +//____________________________________________________________________ +void VP1CylindricalGrid::Imp::rebuild3DObjects() +{ + theclass->messageVerbose("(Re)building 3D objects"); + + if (sep) { + sep->removeAllChildren(); + } else { + sep = new SoSeparator; + sep->ref(); + } + + const bool save = sep->enableNotify(false); + + int nmax; double distmax; + if (!VP1Floor::calcParsFromExtentAndSpacing( theclass, extent, spacing, 20/*max lines*/, nmax, distmax )) { + nmax = 10; + distmax = 10*SYSTEM_OF_UNITS::m; + theclass->message("ERROR: Problems calculating nmax/distmax."); + } + + if (!circlecol) { + circlecol = new SoPackedColor(); + circlecol->ref(); + } + + //Add circles: + sep->addChild(circlecol); + + for (int ir=1;ir<=nmax;++ir) { + SoNode * circle = VP1QtInventorUtils::createCircle(ir*spacing); + SoSeparator * s = new SoSeparator; + SoTranslation *t1= new SoTranslation(); + t1->translation.setValue(0.0,0.0,-distmax-spacing); + s->addChild(t1); + for (int iz = -nmax; iz<=nmax; ++iz) { + SoTranslation *t2= new SoTranslation(); + t2->translation.setValue(0.0,0.0,spacing); + s->addChild(t2); + s->addChild(circle); + } + sep->addChild(s); + } + + //Add lines: + + SoVertexProperty * grid_cylindrical_vertices = new SoVertexProperty(); + + int ivert(0); + int nsublines(0); + static const double invsqrttwo = 1.0/sqrt(2.0); + for (int ir=1;ir<=nmax;++ir) { + double r = ir*spacing; + double r2 = r*invsqrttwo; + grid_cylindrical_vertices->vertex.set1Value(ivert++,r,0,-distmax); + grid_cylindrical_vertices->vertex.set1Value(ivert++,r,0,+distmax); + grid_cylindrical_vertices->vertex.set1Value(ivert++,0,r,-distmax); + grid_cylindrical_vertices->vertex.set1Value(ivert++,0,r,+distmax); + grid_cylindrical_vertices->vertex.set1Value(ivert++,-r,0,-distmax); + grid_cylindrical_vertices->vertex.set1Value(ivert++,-r,0,+distmax); + grid_cylindrical_vertices->vertex.set1Value(ivert++,0,-r,-distmax); + grid_cylindrical_vertices->vertex.set1Value(ivert++,0,-r,+distmax); + grid_cylindrical_vertices->vertex.set1Value(ivert++,r2,r2,-distmax); + grid_cylindrical_vertices->vertex.set1Value(ivert++,r2,r2,+distmax); + grid_cylindrical_vertices->vertex.set1Value(ivert++,r2,-r2,-distmax); + grid_cylindrical_vertices->vertex.set1Value(ivert++,r2,-r2,+distmax); + grid_cylindrical_vertices->vertex.set1Value(ivert++,-r2,r2,-distmax); + grid_cylindrical_vertices->vertex.set1Value(ivert++,-r2,r2,+distmax); + grid_cylindrical_vertices->vertex.set1Value(ivert++,-r2,-r2,-distmax); + grid_cylindrical_vertices->vertex.set1Value(ivert++,-r2,-r2,+distmax); + nsublines+=8; + } + + grid_cylindrical_vertices->materialBinding=SoMaterialBinding::OVERALL; + grid_cylindrical_vertices->normalBinding=SoNormalBinding::OVERALL; + SoLineSet * line = new SoLineSet(); + line->numVertices.enableNotify(FALSE); + line->numVertices.setNum(nsublines); + for (int i=0;i<nsublines;++i) + line->numVertices.set1Value(i,2); + line->vertexProperty = grid_cylindrical_vertices; + line->numVertices.enableNotify(TRUE); + line->numVertices.touch(); + + sep->addChild(line); + updateColour(); + + if (save) { + sep->enableNotify(true); + sep->touch(); + } + +} + +//____________________________________________________________________ +void VP1CylindricalGrid::Imp::updateColour() +{ + theclass->messageVerbose("Updating packed colour"); + if (circlecol) + circlecol->orderedRGBA = colourAndTransp.getPackedValue(); + if (!sep||sep->getNumChildren()<1) + return; + SoNode * n = sep->getChild(0); + if (!n||n->getTypeId()!=SoLineSet::getClassTypeId()) + return; + SoLineSet * line = static_cast<SoLineSet*>(n); + SoVertexProperty * vertices = static_cast<SoVertexProperty *>(line->vertexProperty.getValue()); + if (vertices) + vertices->orderedRGBA = colourAndTransp.getPackedValue(); +} + +//____________________________________________________________________ +void VP1CylindricalGrid::setShown(bool b) +{ + messageVerbose("Signal received: setShown("+str(b)+")"); + if (m_d->shown==b) + return; + m_d->shown=b; + if (m_d->shown) { + m_d->rebuild3DObjects(); + if (m_d->attachSep->findChild(m_d->sep)<0) + m_d->attachSep->addChild(m_d->sep); + } else { + if (m_d->sep&&m_d->attachSep->findChild(m_d->sep)>=0) + m_d->attachSep->removeChild(m_d->sep); + } +} + +//____________________________________________________________________ +void VP1CylindricalGrid::setColourAndTransp(const SbColor4f&ct) +{ + messageVerbose("Signal received in setColourAndTransp slot."); + if (m_d->colourAndTransp==ct) + return; + m_d->colourAndTransp=ct; + if (m_d->shown) + m_d->updateColour(); +} + +//____________________________________________________________________ +void VP1CylindricalGrid::setExtent(const double& e) +{ + messageVerbose("Signal received: setExtent("+str(e)+")"); + if (m_d->extent==e) + return; + m_d->extent=e; + if (m_d->shown) + m_d->rebuild3DObjects(); +} + +//____________________________________________________________________ +void VP1CylindricalGrid::setSpacing(const double&s) +{ + messageVerbose("Signal received: setSpacing("+str(s)+")"); + if (m_d->spacing==s) + return; + m_d->spacing=s; + if (m_d->shown) + m_d->rebuild3DObjects(); +} diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1EtaCone.cxx b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1EtaCone.cxx new file mode 100644 index 000000000..e5866ce14 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1EtaCone.cxx @@ -0,0 +1,217 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class VP1EtaCone // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: April 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12GuideLineSystems/VP1EtaCone.h" + +#include <Inventor/C/errors/debugerror.h> +#include <Inventor/nodes/SoMaterial.h> +#include <Inventor/nodes/SoCone.h> +#include <Inventor/nodes/SoSeparator.h> +#include <Inventor/nodes/SoTranslation.h> +#include <Inventor/nodes/SoRotationXYZ.h> + +#ifdef BUILDVP1LIGHT + #include "CLHEP/Units/SystemOfUnits.h" + #define SYSTEM_OF_UNITS CLHEP +#else + #include "GaudiKernel/SystemOfUnits.h" + #define SYSTEM_OF_UNITS Gaudi::Units +#endif + +//____________________________________________________________________ +class VP1EtaCone::Imp { +public: + Imp(VP1EtaCone *, + SoMaterial * mat, + SoSeparator * attachsep); + VP1EtaCone * theclass; + SoMaterial * material; + SoSeparator * attachSep; + + bool shown; + double etaval; + double extent; + + SoSeparator * sep; + SoCone * cone1; + SoTranslation * trans1; + SoCone * innercone1; + SoTranslation * innertrans1; + SoCone * cone2; + SoTranslation * trans2; + SoCone * innercone2; + SoTranslation * innertrans2; + + void updateFields(); + void ensureInit3DObjects(); +}; + +//____________________________________________________________________ +VP1EtaCone::VP1EtaCone(SoMaterial * mat,SoSeparator * attachsep, + IVP1System * sys,QObject * parent) + : QObject(parent), VP1HelperClassBase(sys,"VP1EtaCone"), m_d(new Imp(this,mat,attachsep)) +{ +} + +//____________________________________________________________________ +VP1EtaCone::~VP1EtaCone() +{ + setShown(false); + if (m_d->sep) + m_d->sep->unref(); + m_d->material->unref(); + m_d->attachSep->unref(); + delete m_d; +} + +//____________________________________________________________________ +VP1EtaCone::Imp::Imp(VP1EtaCone *tc,SoMaterial * mat,SoSeparator * as) + : theclass(tc), material(mat), attachSep(as), shown(false), + etaval(1), extent(1), sep(0), + cone1(0), trans1(0), innercone1(0), innertrans1(0), + cone2(0), trans2(0), innercone2(0), innertrans2(0) +{ + material->ref(); + attachSep->ref(); +} + +//____________________________________________________________________ +void VP1EtaCone::Imp::ensureInit3DObjects() +{ + if (sep) + return; + theclass->messageVerbose("Building 3D objects"); + sep = new SoSeparator; + sep->ref(); + sep->addChild(material); + + SoSeparator * sepfirst = new SoSeparator; + SoSeparator * sepsecond = new SoSeparator; + + for ( int i = 0;i<2;++i){ + SoRotationXYZ * xf = new SoRotationXYZ(); + xf->axis=SoRotationXYZ::X; + xf->angle = i==0 ? 90.0*SYSTEM_OF_UNITS::deg : -90*SYSTEM_OF_UNITS::deg; + SoTranslation * xl = new SoTranslation(); + SoCone * cone = new SoCone(); + SoTranslation * innerxl = new SoTranslation(); + SoCone * innercone = new SoCone(); + + if (i==0) { + cone1 = cone; + trans1 = xl; + innercone1 = innercone; + innertrans1 = innerxl; + } else { + cone2 = cone; + trans2 = xl; + innercone2 = innercone; + innertrans2 = innerxl; + } + + cone->removePart(SoCone::BOTTOM); + innercone->removePart(SoCone::BOTTOM); + + SoSeparator * s(i==0?sepfirst:sepsecond); + s->addChild(xf); + s->addChild(xl); + s->addChild(cone); + s->addChild(innerxl); + s->addChild(innercone); + sep->addChild(s); + } +} + +//____________________________________________________________________ +void VP1EtaCone::Imp::updateFields() +{ + ensureInit3DObjects(); + theclass->messageVerbose("Updating fields"); + + double theta = 2*atan(exp(-fabs(etaval))); + double tanfact = tan(theta); + bool etaconeextentisz = (extent<0); + double absextent = fabs(extent); + double coneHeight,bottomRadius; + if (etaconeextentisz) { + coneHeight = absextent; + bottomRadius = coneHeight*tanfact; + } else { + bottomRadius = absextent; + coneHeight=bottomRadius/tanfact; + } + + theclass->messageVerbose("etaval = "+str(etaval)); + theclass->messageVerbose("extent = "+str(extent)); + theclass->messageVerbose("absextent = "+str(absextent)); + theclass->messageVerbose("tanfact = "+str(tanfact)); + theclass->messageVerbose("bottomRadius = "+str(bottomRadius)); + theclass->messageVerbose("coneHeight = "+str(coneHeight)); + + cone1->bottomRadius = bottomRadius; + cone1->height = coneHeight; + cone2->bottomRadius = bottomRadius; + cone2->height = coneHeight; + trans1->translation.setValue(0, -coneHeight/2, 0); + trans2->translation.setValue(0, -coneHeight/2, 0); + + innercone1->bottomRadius = bottomRadius; + innercone1->height = -coneHeight; + innercone2->bottomRadius = bottomRadius; + innercone2->height = -coneHeight; + //To avoid render flicker from the overlapping cones, we move the inner cone slightly away from origo: + const double epsilon = 0.50*SYSTEM_OF_UNITS::mm; + innertrans1->translation.setValue(0, coneHeight/2+1.001*coneHeight/2+epsilon, 0); + innertrans2->translation.setValue(0, coneHeight/2+1.001*coneHeight/2+epsilon, 0); + +} + +//____________________________________________________________________ +void VP1EtaCone::setShown(bool b) +{ + messageVerbose("Signal received: setShown("+str(b)+")"); + if (m_d->shown==b) + return; + m_d->shown=b; + if (m_d->shown) { + m_d->updateFields(); + if (m_d->attachSep->findChild(m_d->sep)<0) + m_d->attachSep->addChild(m_d->sep); + } else { + if (m_d->sep&&m_d->attachSep->findChild(m_d->sep)>=0) + m_d->attachSep->removeChild(m_d->sep); + } +} + +//____________________________________________________________________ +void VP1EtaCone::setExtent(const double&p) +{ + messageVerbose("Signal received: setExtent("+str(p)+")"); + if (m_d->extent==p) + return; + m_d->extent=p; + if (m_d->shown) + m_d->updateFields(); +} + +//____________________________________________________________________ +void VP1EtaCone::setEtaValue(const double&p) +{ + messageVerbose("Signal received: setEtaValue("+str(p)+")"); + if (m_d->etaval==p) + return; + m_d->etaval=p; + if (m_d->shown) + m_d->updateFields(); +} diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1Floor.cxx b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1Floor.cxx new file mode 100644 index 000000000..ee38adf4c --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1Floor.cxx @@ -0,0 +1,223 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class VP1Floor // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: July 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12GuideLineSystems/VP1Floor.h" +#include <Inventor/nodes/SoSeparator.h> +#include <Inventor/nodes/SoVertexProperty.h> +#include <Inventor/nodes/SoLineSet.h> +#include <Inventor/SbColor4f.h> + +#ifdef BUILDVP1LIGHT + #include "CLHEP/Units/SystemOfUnits.h" + #define SYSTEM_OF_UNITS CLHEP +#else + #include "GaudiKernel/SystemOfUnits.h" + #define SYSTEM_OF_UNITS Gaudi::Units +#endif + +//____________________________________________________________________ +bool VP1Floor::calcParsFromExtentAndSpacing( VP1HelperClassBase*helper,const double& extent, const double& spacing, const int& nmaxlimit, int& nmax, double& distmax ) +{ + if (extent<0.0||spacing<=0.0) + return false; + nmax=static_cast<int>(extent/spacing+0.5); + if (nmax<1) + nmax =1; + if (nmax>nmaxlimit) { + helper->message("Too many lines requested. All will not be shown."); + nmax=nmaxlimit; + } + distmax = nmax*spacing; + return true; +} + +//____________________________________________________________________ +class VP1Floor::Imp { +public: + Imp(VP1Floor *, + SoSeparator * attachsep); + VP1Floor * theclass; + SoSeparator * attachSep; + + bool shown; + SbColor4f colourAndTransp; + double extent; + double spacing; + double vertpos; + + SoSeparator * sep; + + void rebuild3DObjects(); + void updateColour(); +}; + +//____________________________________________________________________ +VP1Floor::VP1Floor(SoSeparator * attachsep, + IVP1System * sys,QObject * parent) + : QObject(parent), VP1HelperClassBase(sys,"VP1Floor"), m_d(new Imp(this,attachsep)) +{ +} + +//____________________________________________________________________ +VP1Floor::~VP1Floor() +{ + setShown(false); + if (m_d->sep) + m_d->sep->unref(); + m_d->attachSep->unref(); + delete m_d; +} + +//____________________________________________________________________ +VP1Floor::Imp::Imp(VP1Floor *tc,SoSeparator * as) + : theclass(tc), attachSep(as), shown(false), + colourAndTransp(SbColor4f(1,1,1,1)),extent(10), spacing(1), vertpos(0), sep(0) +{ + attachSep->ref(); +} + +//____________________________________________________________________ +void VP1Floor::Imp::rebuild3DObjects() +{ + theclass->messageVerbose("(Re)building 3D objects"); + + if (sep) { + sep->removeAllChildren(); + } else { + sep = new SoSeparator; + sep->ref(); + } + + const bool save = sep->enableNotify(false); + + int nmax; double distmax; + if (!calcParsFromExtentAndSpacing( theclass, extent, spacing, VP1Floor::nMax(), nmax, distmax )) { + nmax = 10; + distmax = 10*SYSTEM_OF_UNITS::m; + theclass->message("ERROR: Problems calculating nmax/distmax."); + } + + SoVertexProperty * floor_vertices = new SoVertexProperty(); + int ivert(0); + int nsublines(0); + for (int ix = -nmax; ix<=nmax; ++ix) { + double x = ix*spacing; + floor_vertices->vertex.set1Value(ivert++,x,vertpos,-distmax); + floor_vertices->vertex.set1Value(ivert++,x,vertpos,+distmax); + ++nsublines; + } + for (int iz = -nmax; iz<=nmax; ++iz) { + double z = iz*spacing; + floor_vertices->vertex.set1Value(ivert++,-distmax,vertpos,z); + floor_vertices->vertex.set1Value(ivert++,+distmax,vertpos,z); + ++nsublines; + } + + floor_vertices->materialBinding=SoMaterialBinding::OVERALL; + floor_vertices->normalBinding=SoNormalBinding::OVERALL; + SoLineSet * line = new SoLineSet(); + line->numVertices.enableNotify(FALSE); + line->numVertices.setNum(nsublines); + for (int i=0;i<nsublines;++i) + line->numVertices.set1Value(i,2); + line->vertexProperty = floor_vertices; + line->numVertices.enableNotify(TRUE); + line->numVertices.touch(); + + sep->addChild(line); + updateColour(); + + if (save) { + sep->enableNotify(true); + sep->touch(); + } + +} + +//____________________________________________________________________ +void VP1Floor::Imp::updateColour() +{ + theclass->messageVerbose("Updating packed colour"); + if (!sep||sep->getNumChildren()<1) + return; + SoNode * n = sep->getChild(0); + if (!n||n->getTypeId()!=SoLineSet::getClassTypeId()) + return; + SoLineSet * line = static_cast<SoLineSet*>(n); + SoVertexProperty * vertices = static_cast<SoVertexProperty *>(line->vertexProperty.getValue()); + if (!vertices) + return; + vertices->orderedRGBA = colourAndTransp.getPackedValue(); +} + +//____________________________________________________________________ +void VP1Floor::setShown(bool b) +{ + messageVerbose("Signal received: setShown("+str(b)+")"); + if (m_d->shown==b) + return; + m_d->shown=b; + if (m_d->shown) { + m_d->rebuild3DObjects(); + if (m_d->attachSep->findChild(m_d->sep)<0) + m_d->attachSep->addChild(m_d->sep); + } else { + if (m_d->sep&&m_d->attachSep->findChild(m_d->sep)>=0) + m_d->attachSep->removeChild(m_d->sep); + } +} + +//____________________________________________________________________ +void VP1Floor::setColourAndTransp(const SbColor4f&ct) +{ + messageVerbose("Signal received in setColourAndTransp slot."); + if (m_d->colourAndTransp==ct) + return; + m_d->colourAndTransp=ct; + if (m_d->shown) + m_d->updateColour(); +} + +//____________________________________________________________________ +void VP1Floor::setExtent(const double& e) +{ + messageVerbose("Signal received: setExtent("+str(e)+")"); + if (m_d->extent==e) + return; + m_d->extent=e; + if (m_d->shown) + m_d->rebuild3DObjects(); +} + +//____________________________________________________________________ +void VP1Floor::setSpacing(const double&s) +{ + messageVerbose("Signal received: setSpacing("+str(s)+")"); + if (m_d->spacing==s) + return; + m_d->spacing=s; + if (m_d->shown) + m_d->rebuild3DObjects(); +} + +//____________________________________________________________________ +void VP1Floor::setVerticalPosition(const double&p) +{ + messageVerbose("Signal received: setVerticalPosition("+str(p)+")"); + if (m_d->vertpos==p) + return; + m_d->vertpos=p; + if (m_d->shown) + m_d->rebuild3DObjects(); +} diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1GuideLineSystem.cxx b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1GuideLineSystem.cxx new file mode 100644 index 000000000..e1d281a77 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1GuideLineSystem.cxx @@ -0,0 +1,345 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +///////////////////////////////////////////////////////////////////////// +// // +// Implementation of class VP1GuideLineSystem // +// // +// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Initial version: July 2007 // +// // +///////////////////////////////////////////////////////////////////////// + +#include "VTI12GuideLineSystems/VP1GuideLineSystem.h" +#include "VTI12GuideLineSystems/GuideSysController.h" +#include "VTI12GuideLineSystems/ProjectionSurfacesHelper.h" +#include "VTI12GuideLineSystems/VP1CoordinateAxes.h" +#include "VTI12GuideLineSystems/VP1Floor.h" +#include "VTI12GuideLineSystems/VP1Letters.h" +#include "VTI12GuideLineSystems/VP1EtaCone.h" +#include "VTI12GuideLineSystems/VP1CartesianGrid.h" +#include "VTI12GuideLineSystems/VP1CylindricalGrid.h" +#include "VTI12GuideLineSystems/VP1TrackingVolumes.h" +#include "VTI12GuideLineSystems/VP1Lines.h" + +#include "VP1Base/VP1Serialise.h" +#include "VP1Base/VP1Deserialise.h" +#include "VP1Base/VP1Msg.h" + +#include <Inventor/nodes/SoSeparator.h> +#include <Inventor/nodes/SoPickStyle.h> +#include <Inventor/nodes/SoComplexity.h> +#include <Inventor/SbVec3f.h> + +#include <map> + +class VP1GuideLineSystem::Imp { +public: + Imp(VP1GuideLineSystem*tc) : theclass(tc), + controller(0), + coordinateaxes(0), + floor(0), + cartesiangrid(0), + cylindricalgrid(0), + letters(0), + etacone1(0), + etacone2(0), + etacone3(0), + trackingVolumes(0), + projsurfhelper_pixel(0), + projsurfhelper_sct(0), + projsurfhelper_trt(0), + lastemit_pixel(InDetProjFlags::NoProjections), + lastemit_sct(InDetProjFlags::NoProjections), + lastemit_trt(InDetProjFlags::NoProjections) {} + VP1GuideLineSystem *theclass; + GuideSysController * controller; + VP1CoordinateAxes * coordinateaxes; + VP1Floor * floor; + VP1CartesianGrid * cartesiangrid; + VP1CylindricalGrid * cylindricalgrid; + VP1Letters * letters; + VP1EtaCone * etacone1; + VP1EtaCone * etacone2; + VP1EtaCone * etacone3; + VP1TrackingVolumes * trackingVolumes; + VP1Lines * lines; + + ProjectionSurfacesHelper * projsurfhelper_pixel; + ProjectionSurfacesHelper * projsurfhelper_sct; + ProjectionSurfacesHelper * projsurfhelper_trt; + InDetProjFlags::InDetProjPartsFlags lastemit_pixel; + InDetProjFlags::InDetProjPartsFlags lastemit_sct; + InDetProjFlags::InDetProjPartsFlags lastemit_trt; + + //For knowing which ID parts are used by data systems: + std::map<QObject*,InDetProjFlags::DetTypeFlags> sender2iddettypeswithprojs; +}; + +//_____________________________________________________________________________________ +VP1GuideLineSystem::VP1GuideLineSystem() + : IVP13DSystemSimple("Guides", + "System providing visual guides", + "Thomas.Kittelmann@cern.ch"), m_d(new Imp(this)) +{ +} + + +//_____________________________________________________________________________________ +VP1GuideLineSystem::~VP1GuideLineSystem() +{ + delete m_d; +} + +//_____________________________________________________________________________________ +QWidget * VP1GuideLineSystem::buildController() +{ + m_d->controller = new GuideSysController(this); + return m_d->controller; +} + +//_____________________________________________________________________________________ +void VP1GuideLineSystem::buildEventSceneGraph(StoreGateSvc*, SoSeparator *) +{ +} + +//_____________________________________________________________________________________ +void VP1GuideLineSystem::buildPermanentSceneGraph(StoreGateSvc* /*detstore*/, SoSeparator *root) +{ + if(VP1Msg::verbose()){ + messageVerbose("buildPermanentSceneGraph"); + } + //No guidelines are pickable: + SoPickStyle *pickStyle = new SoPickStyle; + pickStyle->style=SoPickStyle::UNPICKABLE; + root->addChild(pickStyle); + + //High complexity val for eta cones: + SoComplexity * complexity = new SoComplexity; + complexity->value.setValue(2.0f); + root->addChild(complexity); + + //Floor: + m_d->floor = new VP1Floor(root,this); + connect(m_d->controller,SIGNAL(floorExtentChanged(const double&)),m_d->floor,SLOT(setExtent(const double&))); + m_d->floor->setExtent(m_d->controller->floorExtent()); + connect(m_d->controller,SIGNAL(floorSpacingChanged(const double&)),m_d->floor,SLOT(setSpacing(const double&))); + m_d->floor->setSpacing(m_d->controller->floorSpacing()); + connect(m_d->controller,SIGNAL(floorHeightChanged(const double&)),m_d->floor,SLOT(setVerticalPosition(const double&))); + m_d->floor->setVerticalPosition(m_d->controller->floorHeight()); + connect(m_d->controller,SIGNAL(floorColourAndTranspChanged( const SbColor4f&)),m_d->floor,SLOT(setColourAndTransp(const SbColor4f&))); + m_d->floor->setColourAndTransp(m_d->controller->floorColourAndTransp()); + connect(m_d->controller,SIGNAL(showFloorChanged(bool)),m_d->floor,SLOT(setShown(bool))); + m_d->floor->setShown(m_d->controller->showFloor()); + + //CartesianGrid: + m_d->cartesiangrid = new VP1CartesianGrid(root,this); + connect(m_d->controller,SIGNAL(gridExtentChanged(const double&)),m_d->cartesiangrid,SLOT(setExtent(const double&))); + m_d->cartesiangrid->setExtent(m_d->controller->gridExtent()); + connect(m_d->controller,SIGNAL(gridSpacingChanged(const double&)),m_d->cartesiangrid,SLOT(setSpacing(const double&))); + m_d->cartesiangrid->setSpacing(m_d->controller->gridSpacing()); + connect(m_d->controller,SIGNAL(gridColourAndTranspChanged( const SbColor4f&)),m_d->cartesiangrid,SLOT(setColourAndTransp(const SbColor4f&))); + m_d->cartesiangrid->setColourAndTransp(m_d->controller->gridColourAndTransp()); + connect(m_d->controller,SIGNAL(showCartesianGridChanged(bool)),m_d->cartesiangrid,SLOT(setShown(bool))); + m_d->cartesiangrid->setShown(m_d->controller->showCartesianGrid()); + + //CylindricalGrid: + m_d->cylindricalgrid = new VP1CylindricalGrid(root,this); + connect(m_d->controller,SIGNAL(gridExtentChanged(const double&)),m_d->cylindricalgrid,SLOT(setExtent(const double&))); + m_d->cylindricalgrid->setExtent(m_d->controller->gridExtent()); + connect(m_d->controller,SIGNAL(gridSpacingChanged(const double&)),m_d->cylindricalgrid,SLOT(setSpacing(const double&))); + m_d->cylindricalgrid->setSpacing(m_d->controller->gridSpacing()); + connect(m_d->controller,SIGNAL(gridColourAndTranspChanged( const SbColor4f&)),m_d->cylindricalgrid,SLOT(setColourAndTransp(const SbColor4f&))); + m_d->cylindricalgrid->setColourAndTransp(m_d->controller->gridColourAndTransp()); + connect(m_d->controller,SIGNAL(showCylindricalGridChanged(bool)),m_d->cylindricalgrid,SLOT(setShown(bool))); + m_d->cylindricalgrid->setShown(m_d->controller->showCylindricalGrid()); + + //Letters: + m_d->letters = new VP1Letters(m_d->controller->lettersMaterial(),root,this); + connect(m_d->controller,SIGNAL(lettersZPosChanged(const double&)),m_d->letters,SLOT(setZPos(const double&))); + m_d->letters->setZPos(m_d->controller->lettersZPos()); + connect(m_d->controller,SIGNAL(lettersVerticalPosChanged(const double&)),m_d->letters,SLOT(setVerticalPosition(const double&))); + m_d->letters->setVerticalPosition(m_d->controller->lettersVerticalPos()); + connect(m_d->controller,SIGNAL(showLettersChanged(bool)),m_d->letters,SLOT(setShown(bool))); + m_d->letters->setShown(m_d->controller->showLetters()); + + //Coordinate axes: + m_d->coordinateaxes = new VP1CoordinateAxes(m_d->controller->xAxisMaterial(), + m_d->controller->yAxisMaterial(), + m_d->controller->zAxisMaterial(), + root,this); + connect(m_d->controller,SIGNAL(axesLengthChanged(const double&)),m_d->coordinateaxes,SLOT(setLength(const double&))); + m_d->coordinateaxes->setLength(m_d->controller->axesLength()); + connect(m_d->controller,SIGNAL(axesPositionChanged(const SbVec3f&)),m_d->coordinateaxes,SLOT(setPosition(const SbVec3f&))); + m_d->coordinateaxes->setPosition(m_d->controller->axesPosition()); + connect(m_d->controller,SIGNAL(relAxesThicknessChanged(const double&)),m_d->coordinateaxes,SLOT(setRelativeAxisThickness(const double&))); + m_d->coordinateaxes->setRelativeAxisThickness(m_d->controller->relAxesThickness()); + connect(m_d->controller,SIGNAL(showAxesChanged(bool)),m_d->coordinateaxes,SLOT(setShown(bool))); + m_d->coordinateaxes->setShown(m_d->controller->showAxes()); + + //Eta cones: + m_d->etacone1 = new VP1EtaCone(m_d->controller->etaCone1Material(),root,this); + connect(m_d->controller,SIGNAL(etaExtentChanged(const double&)),m_d->etacone1,SLOT(setExtent(const double&))); + m_d->etacone1->setExtent(m_d->controller->etaExtent()); + connect(m_d->controller,SIGNAL(etaConeValue1Changed(const double&)),m_d->etacone1,SLOT(setEtaValue(const double&))); + m_d->etacone1->setEtaValue(m_d->controller->etaConeValue1()); + connect(m_d->controller,SIGNAL(showEtaCone1Changed(bool)),m_d->etacone1,SLOT(setShown(bool))); + m_d->etacone1->setShown(m_d->controller->showEtaCone1()); + + m_d->etacone2 = new VP1EtaCone(m_d->controller->etaCone2Material(),root,this); + connect(m_d->controller,SIGNAL(etaExtentChanged(const double&)),m_d->etacone2,SLOT(setExtent(const double&))); + m_d->etacone2->setExtent(m_d->controller->etaExtent()); + connect(m_d->controller,SIGNAL(etaConeValue2Changed(const double&)),m_d->etacone2,SLOT(setEtaValue(const double&))); + m_d->etacone2->setEtaValue(m_d->controller->etaConeValue2()); + connect(m_d->controller,SIGNAL(showEtaCone2Changed(bool)),m_d->etacone2,SLOT(setShown(bool))); + m_d->etacone2->setShown(m_d->controller->showEtaCone2()); + + m_d->etacone3 = new VP1EtaCone(m_d->controller->etaCone3Material(),root,this); + connect(m_d->controller,SIGNAL(etaExtentChanged(const double&)),m_d->etacone3,SLOT(setExtent(const double&))); + m_d->etacone3->setExtent(m_d->controller->etaExtent()); + connect(m_d->controller,SIGNAL(etaConeValue3Changed(const double&)),m_d->etacone3,SLOT(setEtaValue(const double&))); + m_d->etacone3->setEtaValue(m_d->controller->etaConeValue3()); + connect(m_d->controller,SIGNAL(showEtaCone3Changed(bool)),m_d->etacone3,SLOT(setShown(bool))); + m_d->etacone3->setShown(m_d->controller->showEtaCone3()); + + //Tracking Volumes: + m_d->trackingVolumes = new VP1TrackingVolumes(m_d->controller->idTrkVolumesMaterial(), + m_d->controller->caloTrkVolumesMaterial(), + m_d->controller->msTrkVolumesMaterial(), + m_d->controller->showInnerDetector(), + m_d->controller->showCalorimeters(), + m_d->controller->showMuonSpectrometer(), + root,this); + connect(m_d->controller,SIGNAL(showTrackingVolumesChanged(bool)),m_d->trackingVolumes,SLOT(setShown(bool))); + connect(m_d->controller,SIGNAL(showInnerDetectorChanged(bool)),m_d->trackingVolumes,SLOT(setShownID(bool))); + connect(m_d->controller,SIGNAL(showCalorimetersChanged(bool)),m_d->trackingVolumes,SLOT(setShownCalo(bool))); + connect(m_d->controller,SIGNAL(showMuonSpectrometerChanged(bool)),m_d->trackingVolumes,SLOT(setShownMS(bool))); + m_d->trackingVolumes->setShown(m_d->controller->showTrackingVolumes()); + + //Lines + m_d->lines = new VP1Lines(root, this); + connect(m_d->controller,SIGNAL(showLinesChanged(bool)),m_d->lines,SLOT(setShown(bool))); + m_d->lines->setShown(m_d->controller->showLines()); + connect(m_d->controller,SIGNAL(lineDirectionChanged(const SbVec3f&)),m_d->lines,SLOT(setDirection(const SbVec3f&))); + m_d->lines->setDirection(m_d->controller->lineDirection()); + + SoSeparator * projsep = new SoSeparator; + root->addChild(projsep); + + m_d->projsurfhelper_pixel = ProjectionSurfacesHelper::createPixelHelper(m_d->controller->pixelProjSurfMaterial(),projsep,this,this); + m_d->projsurfhelper_sct = ProjectionSurfacesHelper::createSCTHelper(m_d->controller->sctProjSurfMaterial(),projsep,this,this); + m_d->projsurfhelper_trt = ProjectionSurfacesHelper::createTRTHelper(m_d->controller->trtProjSurfMaterial(),projsep,this,this); + + connect(m_d->controller,SIGNAL(shownPixelProjSurfacesChanged(InDetProjFlags::InDetProjPartsFlags)), + m_d->projsurfhelper_pixel,SLOT(setSurfaces(InDetProjFlags::InDetProjPartsFlags))); + m_d->projsurfhelper_pixel->setSurfaces(m_d->controller->shownPixelProjSurfaces()); + + connect(m_d->controller,SIGNAL(shownSCTProjSurfacesChanged(InDetProjFlags::InDetProjPartsFlags)), + m_d->projsurfhelper_sct,SLOT(setSurfaces(InDetProjFlags::InDetProjPartsFlags))); + m_d->projsurfhelper_sct->setSurfaces(m_d->controller->shownSCTProjSurfaces()); + + connect(m_d->controller,SIGNAL(shownTRTProjSurfacesChanged(InDetProjFlags::InDetProjPartsFlags)), + m_d->projsurfhelper_trt,SLOT(setSurfaces(InDetProjFlags::InDetProjPartsFlags))); + m_d->projsurfhelper_trt->setSurfaces(m_d->controller->shownTRTProjSurfaces()); + + connect(m_d->controller,SIGNAL(applicablePixelProjPartsChanged(InDetProjFlags::InDetProjPartsFlags)),this,SLOT(possiblyEmit_ApplicableProjectionsChanged())); + connect(m_d->controller,SIGNAL(applicableSCTProjPartsChanged(InDetProjFlags::InDetProjPartsFlags)),this,SLOT(possiblyEmit_ApplicableProjectionsChanged())); + connect(m_d->controller,SIGNAL(applicableTRTProjPartsChanged(InDetProjFlags::InDetProjPartsFlags)),this,SLOT(possiblyEmit_ApplicableProjectionsChanged())); + + possiblyEmit_ApplicableProjectionsChanged();//fixme; late enough??? Problem with new delayed init: until guides are enabled, proper projections won't be known!! + //Thus, the channel should call this slot explicitly after making all connections!!! +} + +//_____________________________________________________________________________________ +void VP1GuideLineSystem::systemuncreate() +{ + delete m_d->coordinateaxes; m_d->coordinateaxes = 0; + delete m_d->floor; m_d->floor = 0; + delete m_d->cartesiangrid; m_d->cartesiangrid = 0; + delete m_d->cylindricalgrid; m_d->cylindricalgrid = 0; + delete m_d->letters; m_d->letters = 0; + delete m_d->etacone1; m_d->etacone1 = 0; + delete m_d->etacone2; m_d->etacone2 = 0; + delete m_d->etacone3; m_d->etacone3 = 0; + delete m_d->projsurfhelper_pixel; m_d->projsurfhelper_pixel = 0; + delete m_d->projsurfhelper_sct; m_d->projsurfhelper_sct = 0; + delete m_d->projsurfhelper_trt; m_d->projsurfhelper_trt = 0; + delete m_d->trackingVolumes; m_d->trackingVolumes = 0; + + m_d->controller=0; +} + + +//_____________________________________________________________________________________ +QByteArray VP1GuideLineSystem::saveState() { + + ensureBuildController(); + + VP1Serialise serialise(4/*version*/,this); + serialise.save(IVP13DSystemSimple::saveState()); + serialise.save(m_d->controller->saveSettings()); + serialise.disableUnsavedChecks();//We do the testing in the controller + return serialise.result(); +} + +//_____________________________________________________________________________________ +void VP1GuideLineSystem::restoreFromState(QByteArray ba) { + + VP1Deserialise state(ba,this); + if (state.version()<0||state.version()>4) { + message("Warning: State data in .vp1 file is in wrong format - ignoring!"); + state.disableUnrestoredChecks();//We do the testing in the controller + return; + } + if (state.version()>=0&&state.version()<=3) { + message("Warning: State data in .vp1 file is in obsolete format - ignoring!"); + state.disableUnrestoredChecks();//We do the testing in the controller + return; + } + ensureBuildController(); + + IVP13DSystemSimple::restoreFromState(state.restoreByteArray()); + m_d->controller->restoreSettings(state.restoreByteArray()); + state.disableUnrestoredChecks();//We do the testing in the controller +} + +//_____________________________________________________________________________________ +void VP1GuideLineSystem::setIDDetTypesUsingProjections( InDetProjFlags::DetTypeFlags f ) +{ + ensureBuildController(); + if (!m_d->controller) + return;//if receiving signals after uncreate + if(VP1Msg::verbose()){ + messageVerbose("Signal received in setIDDetTypesUsingProjections("+str(f)+") slot (from " + +QString(sender()?sender()->objectName():"NULL sender")+")"); + } + m_d->sender2iddettypeswithprojs[sender()] = f; + InDetProjFlags::DetTypeFlags used(InDetProjFlags::NoDet); + std::map<QObject*,InDetProjFlags::DetTypeFlags>::iterator it, itE = m_d->sender2iddettypeswithprojs.end(); + for (it=m_d->sender2iddettypeswithprojs.begin();it!=itE;++it) + used |= it->second; + m_d->controller->setInDetDetTypesUsingProjections(used); +} + +//_____________________________________________________________________________________ +void VP1GuideLineSystem::possiblyEmit_ApplicableProjectionsChanged() +{ + ensureBuildController(); + if (!m_d->controller) + return;//if receiving signals after uncreate + InDetProjFlags::InDetProjPartsFlags new_pixel = m_d->controller->applicablePixelProjParts(); + InDetProjFlags::InDetProjPartsFlags new_sct = m_d->controller->applicableSCTProjParts(); + InDetProjFlags::InDetProjPartsFlags new_trt = m_d->controller->applicableTRTProjParts(); + if (m_d->lastemit_pixel==new_pixel&&m_d->lastemit_sct==new_sct&&m_d->lastemit_trt==new_trt) + return; + m_d->lastemit_pixel=new_pixel; + m_d->lastemit_sct=new_sct; + m_d->lastemit_trt=new_trt; + if(VP1Msg::verbose()){ + messageVerbose("Emitting applicableProjectionsChanged("+str(m_d->lastemit_pixel)+", "+str(m_d->lastemit_sct)+", "+str(m_d->lastemit_trt)+")"); + } + emit applicableProjectionsChanged( m_d->lastemit_pixel,m_d->lastemit_sct,m_d->lastemit_trt ); +} diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1Letters.cxx b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1Letters.cxx new file mode 100644 index 000000000..d0cc39733 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1Letters.cxx @@ -0,0 +1,293 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class VP1Letters // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: April 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12GuideLineSystems/VP1Letters.h" +#include "VP1HEPVis/SbPolyhedron.h" +#include "VP1HEPVis/nodes/SoPolyhedron.h" +#include <Inventor/nodes/SoMaterial.h> +#include <Inventor/nodes/SoCube.h> +#include <Inventor/nodes/SoSeparator.h> +#include <Inventor/nodes/SoTranslation.h> +#include <Inventor/nodes/SoRotationXYZ.h> +#include <algorithm> +#include <vector> + +#ifdef BUILDVP1LIGHT + #include "CLHEP/Units/SystemOfUnits.h" + #define SYSTEM_OF_UNITS CLHEP +#else + #include "GaudiKernel/SystemOfUnits.h" + #define SYSTEM_OF_UNITS Gaudi::Units +#endif + +//____________________________________________________________________ +class VP1Letters::Imp { +public: + Imp(VP1Letters *, + SoMaterial * mat, + SoSeparator * attachsep); + VP1Letters * theclass; + SoMaterial * material; + SoSeparator * attachSep; + + void createLetterAData(std::vector<double>& x, std::vector<double>&y); + void createLetterCData(std::vector<double>& x, std::vector<double>&y); + void normalizeLetterData(std::vector<double>& x, std::vector<double>&y,double yheight); + SoNode * createLetter(const std::vector<double>& x, const std::vector<double>y); + + bool shown; + double zpos; + double vertpos; + + SoSeparator * sep; + SoTranslation * transA; + SoTranslation * transC; + + void updateFields(); + void ensureInit3DObjects(); +}; + +//____________________________________________________________________ +VP1Letters::VP1Letters(SoMaterial * mat,SoSeparator * attachsep, + IVP1System * sys,QObject * parent) + : QObject(parent), VP1HelperClassBase(sys,"VP1Letters"), m_d(new Imp(this,mat,attachsep)) +{ +} + +//____________________________________________________________________ +VP1Letters::~VP1Letters() +{ + setShown(false); + if (m_d->sep) + m_d->sep->unref(); + if (m_d->transA) + m_d->transA->unref(); + if (m_d->transC) + m_d->transC->unref(); + m_d->material->unref(); + m_d->attachSep->unref(); + delete m_d; +} + +//____________________________________________________________________ +VP1Letters::Imp::Imp(VP1Letters *tc,SoMaterial * mat,SoSeparator * as) + : theclass(tc), material(mat), attachSep(as), shown(false), + zpos(0),vertpos(0), sep(0), transA(0), transC(0) +{ + material->ref(); + attachSep->ref(); +} + + +//_____________________________________________________________________________________ +void VP1Letters::Imp::createLetterAData(std::vector<double>& x, std::vector<double>&y) { + + x.clear(); + y.clear(); + x.push_back(294.15418); y.push_back(175.81259); + x.push_back(230.15085); y.push_back(349.36906); + x.push_back(358.39109); y.push_back(349.36906); + x.push_back(294.15418); y.push_back(175.81259); + x.push_back(267.52506); y.push_back(129.32842); + x.push_back(321.01689); y.push_back(129.32842); + x.push_back(453.92891); y.push_back(478.07648); + x.push_back(404.87526); y.push_back(478.07648); + x.push_back(373.10719); y.push_back(388.61197); + x.push_back(215.90194); y.push_back(388.61197); + x.push_back(184.13386); y.push_back(478.07648); + x.push_back(134.37945); y.push_back(478.07648); + x.push_back(267.52506); y.push_back(129.32842); +} + +//_____________________________________________________________________________________ +void VP1Letters::Imp::createLetterCData(std::vector<double>& x, std::vector<double>&y) { + + x.clear(); + y.clear(); + x.push_back(666.70068); y.push_back(278.58533); + x.push_back(668.72098); y.push_back(165.44825); + x.push_back(591.94939); y.push_back(127.06245); + x.push_back(496.99505); y.push_back(98.77818); + x.push_back(400.02041); y.push_back(94.73757); + x.push_back(299.00515); y.push_back(108.87971); + x.push_back(224.25386); y.push_back(145.2452); + x.push_back(149.50258); y.push_back(201.81374); + x.push_back(92.934034); y.push_back(280.60564); + x.push_back(56.568543); y.push_back(379.60059); + x.push_back(46.467017); y.push_back(486.67676); + x.push_back(52.527932); y.push_back(591.73262); + x.push_back(76.771593); y.push_back(682.64635); + x.push_back(109.09647); y.push_back(741.2352); + x.push_back(145.46197); y.push_back(783.66161); + x.push_back(189.90868); y.push_back(830.12862); + x.push_back(248.49753); y.push_back(864.47381); + x.push_back(327.28942); y.push_back(886.69717); + x.push_back(406.08132); y.push_back(898.819); + x.push_back(454.56865); y.push_back(898.819); + x.push_back(523.25902); y.push_back(886.69717); + x.push_back(600.03061); y.push_back(858.41289); + x.push_back(646.49763); y.push_back(838.20984); + x.push_back(668.72098); y.push_back(818.00679); + x.push_back(666.70068); y.push_back(710.93062); + x.push_back(616.19305); y.push_back(751.33672); + x.push_back(555.5839); y.push_back(785.68191); + x.push_back(484.87322); y.push_back(807.90527); + x.push_back(430.32498); y.push_back(809.92557); + x.push_back(379.81736); y.push_back(807.90527); + x.push_back(317.1879); y.push_back(791.74283); + x.push_back(280.82241); y.push_back(775.58039); + x.push_back(248.49753); y.push_back(749.31642); + x.push_back(214.15234); y.push_back(710.93062); + x.push_back(175.76654); y.push_back(652.34177); + x.push_back(159.6041); y.push_back(565.46866); + x.push_back(155.56349); y.push_back(480.61584); + x.push_back(161.62441); y.push_back(401.82394); + x.push_back(189.90868); y.push_back(314.95082); + x.push_back(242.43661); y.push_back(242.21984); + x.push_back(301.02546); y.push_back(203.83404); + x.push_back(361.63461); y.push_back(181.61069); + x.push_back(426.28437); y.push_back(177.57008); + x.push_back(511.13719); y.push_back(187.6716); + x.push_back(587.90878); y.push_back(217.97618); + x.push_back(644.47732); y.push_back(258.38228); + //Correct orientation for SbPolyhedronPolygonXSect: + std::reverse(x.begin(), x.end()); + std::reverse(y.begin(), y.end()); +} + +//_____________________________________________________________________________________ +void VP1Letters::Imp::normalizeLetterData(std::vector<double>& x, std::vector<double>&y,double yheight) +{ + //Translates and rescales so letter goes from -0.5*yheight to +0.5*yheight in y, and is centered around 0 in x. + if (x.size()!=y.size()) { + theclass->message("normalizeLetterData Error: Input vectors have different length!"); + return; + } + + unsigned n = x.size(); + + double xmin(1e20),xmax(-1e20),ymin(1e20),ymax(-1e20); + for (unsigned i = 0; i<n;++i) { + if (x.at(i)<xmin) xmin = x.at(i); + if (x.at(i)>xmax) xmax = x.at(i); + if (y.at(i)<ymin) ymin = y.at(i); + if (y.at(i)>ymax) ymax = y.at(i); + } + + assert(ymax>ymin&&xmax>xmin); + + double scale=yheight/(ymax-ymin); + double xoffset=-xmin-0.5*(xmax-xmin); + for (unsigned i = 0; i<n;++i) { + x.at(i) = (x.at(i)+xoffset)*scale; + y.at(i) = (y.at(i)-ymin)*scale-0.5*yheight; + } + +} + +//_____________________________________________________________________________________ +SoNode * VP1Letters::Imp::createLetter(const std::vector<double>& x, const std::vector<double>y) { + if (x.size()!=y.size()) { + theclass->message("createLetter Error: Input vectors have different length!"); + return new SoCube; + } + + SoPolyhedron::initClass(); + // SbPolyhedron * sbpoly = static_cast<SbPolyhedron*>(new SbPolyhedronPolygonXSect(x,y,0.3*m)); + // SoPolyhedron * poly = new SoPolyhedron(sbpoly); + SoPolyhedron * poly = new SoPolyhedron(SbPolyhedronPolygonXSect(x,y,0.3*SYSTEM_OF_UNITS::m)); + return poly; +} + +//____________________________________________________________________ +void VP1Letters::Imp::ensureInit3DObjects() +{ + if (sep) + return; + theclass->messageVerbose("Building 3D objects"); + sep = new SoSeparator; sep->ref(); + sep->addChild(material); + + //Create letters: + std::vector<double> x,y; + createLetterAData(x,y); + normalizeLetterData(x,y,2*SYSTEM_OF_UNITS::m); + SoNode * letterA = createLetter(x,y); + createLetterCData(x,y); + normalizeLetterData(x,y,2*SYSTEM_OF_UNITS::m); + SoNode * letterC = createLetter(x,y); + + transA = new SoTranslation; + transA->ref(); + transC = new SoTranslation; + transC->ref(); + + SoRotationXYZ * xf = new SoRotationXYZ(); + xf->axis=SoRotationXYZ::Z; + xf->angle = 180*SYSTEM_OF_UNITS::deg; + + sep->addChild(transC); + sep->addChild(letterC); + sep->addChild(transA); + sep->addChild(xf); + sep->addChild(letterA); +} + +//____________________________________________________________________ +void VP1Letters::Imp::updateFields() +{ + ensureInit3DObjects(); + theclass->messageVerbose("Updating fields"); + transA->translation.setValue(0, 0, 2*zpos); + transC->translation.setValue(0, vertpos, -zpos); +} + +//____________________________________________________________________ +void VP1Letters::setShown(bool b) +{ + messageVerbose("Signal received: setShown("+str(b)+")"); + if (m_d->shown==b) + return; + m_d->shown=b; + if (m_d->shown) { + m_d->updateFields(); + if (m_d->attachSep->findChild(m_d->sep)<0) + m_d->attachSep->addChild(m_d->sep); + } else { + if (m_d->sep&&m_d->attachSep->findChild(m_d->sep)>=0) + m_d->attachSep->removeChild(m_d->sep); + } +} + +//____________________________________________________________________ +void VP1Letters::setZPos(const double&p) +{ + messageVerbose("Signal received: setZPos("+str(p)+")"); + if (m_d->zpos==p) + return; + m_d->zpos=p; + if (m_d->shown) + m_d->updateFields(); +} + +//____________________________________________________________________ +void VP1Letters::setVerticalPosition(const double&p) +{ + messageVerbose("Signal received: setVerticalPosition("+str(p)+")"); + if (m_d->vertpos==p) + return; + m_d->vertpos=p; + if (m_d->shown) + m_d->updateFields(); +} diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1Lines.cxx b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1Lines.cxx new file mode 100644 index 000000000..8ec1dda7a --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1Lines.cxx @@ -0,0 +1,148 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#include "VTI12GuideLineSystems/VP1Lines.h" + +#include <Inventor/nodes/SoSeparator.h> +#include <Inventor/nodes/SoVertexProperty.h> +#include <Inventor/nodes/SoLineSet.h> +#include <Inventor/SbColor4f.h> + + +//____________________________________________________________________ +class VP1Lines::Imp { +public: + Imp(VP1Lines *, + SoSeparator * attachsep); + VP1Lines * theclass; + SoSeparator * attachSep; + + bool shown; + SbColor4f colourAndTransp; + SbVec3f direction; + + SoSeparator * sep; + + void rebuild3DObjects(); + void updateColour(); +}; + +//____________________________________________________________________ +VP1Lines::VP1Lines(SoSeparator * attachsep, + IVP1System * sys,QObject * parent) + : QObject(parent), VP1HelperClassBase(sys,"VP1Lines"), m_d(new Imp(this,attachsep)) +{ +} + +//____________________________________________________________________ +VP1Lines::~VP1Lines() +{ + setShown(false); + if (m_d->sep) + m_d->sep->unref(); + m_d->attachSep->unref(); + delete m_d; +} + +//____________________________________________________________________ +VP1Lines::Imp::Imp(VP1Lines *tc,SoSeparator * as) + : theclass(tc), attachSep(as), shown(false), + colourAndTransp(SbColor4f(1,1,1,1)), direction(SbVec3f(0,0,0)), sep(0) +{ + attachSep->ref(); +} + +//____________________________________________________________________ +void VP1Lines::Imp::rebuild3DObjects() +{ + theclass->messageVerbose("(Re)building 3D objects"); + + if (sep) { + sep->removeAllChildren(); + } else { + sep = new SoSeparator; + sep->ref(); + } + + const bool save = sep->enableNotify(false); + + SoVertexProperty * line_vertices = new SoVertexProperty(); + + line_vertices->vertex.set1Value(0,0.0,0.0,0.0); + line_vertices->vertex.set1Value(1,direction[0],direction[1],direction[2]); + + line_vertices->materialBinding=SoMaterialBinding::OVERALL; + line_vertices->normalBinding=SoNormalBinding::OVERALL; + SoLineSet * line = new SoLineSet(); + line->numVertices.enableNotify(FALSE); + // line->numVertices.setNum(1); + // line->numVertices.set1Value(0,2); + line->vertexProperty = line_vertices; + line->numVertices.enableNotify(TRUE); + line->numVertices.touch(); + + sep->addChild(line); + updateColour(); + + if (save) { + sep->enableNotify(true); + sep->touch(); + } + +} + +//____________________________________________________________________ +void VP1Lines::Imp::updateColour() +{ + theclass->messageVerbose("Updating packed colour"); + if (!sep||sep->getNumChildren()<1) + return; + SoNode * n = sep->getChild(0); + if (!n||n->getTypeId()!=SoLineSet::getClassTypeId()) + return; + SoLineSet * line = static_cast<SoLineSet*>(n); + SoVertexProperty * vertices = static_cast<SoVertexProperty *>(line->vertexProperty.getValue()); + if (!vertices) + return; + vertices->orderedRGBA = colourAndTransp.getPackedValue(); +} + +//____________________________________________________________________ +void VP1Lines::setShown(bool b) +{ + messageVerbose("Signal received: setShown("+str(b)+")"); + if (m_d->shown==b) + return; + m_d->shown=b; + if (m_d->shown) { + m_d->rebuild3DObjects(); + if (m_d->attachSep->findChild(m_d->sep)<0) + m_d->attachSep->addChild(m_d->sep); + } else { + if (m_d->sep&&m_d->attachSep->findChild(m_d->sep)>=0) + m_d->attachSep->removeChild(m_d->sep); + } +} + +//____________________________________________________________________ +void VP1Lines::setColourAndTransp(const SbColor4f&ct) +{ + messageVerbose("Signal received in setColourAndTransp slot."); + if (m_d->colourAndTransp==ct) + return; + m_d->colourAndTransp=ct; + if (m_d->shown) + m_d->updateColour(); +} + +//____________________________________________________________________ +void VP1Lines::setDirection(const SbVec3f& o) +{ + messageVerbose("Signal received: setDirection("+str(o)+")"); + if (m_d->direction==o) + return; + m_d->direction=o; + if (m_d->shown) + m_d->rebuild3DObjects(); +} diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1TrackingVolumes.cxx b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1TrackingVolumes.cxx new file mode 100644 index 000000000..97fe38f20 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/VP1TrackingVolumes.cxx @@ -0,0 +1,219 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class VP1TrackingVolumes // +// // +// Author: Edward.Moyse@cern.ch // +// Initial version: March 2009 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12GuideLineSystems/VP1TrackingVolumes.h" +#include <Inventor/C/errors/debugerror.h> +#include <Inventor/nodes/SoMaterial.h> +#include <Inventor/nodes/SoSeparator.h> +#include <Inventor/nodes/SoCylinder.h> +#include <Inventor/nodes/SoCone.h> +#include <Inventor/nodes/SoTranslation.h> +#include <Inventor/nodes/SoRotationXYZ.h> +#include <iostream> +//____________________________________________________________________ +class VP1TrackingVolumes::Imp { +public: + Imp(VP1TrackingVolumes * tc, + SoMaterial * materialID, + SoMaterial * materialCalo, + SoMaterial * materialMS, + SoSeparator * attachsep, + bool showID, bool showCalo, bool showMS); + VP1TrackingVolumes * theclass; + SoSeparator * attachSep; + SoMaterial * materialID; + SoMaterial * materialCalo; + SoMaterial * materialMS; + + bool shown; + bool shownID; + bool shownCalo; + bool shownMS; + + SoSeparator * sep; + SoSeparator * sepID; + SoSeparator * sepCalo; + SoSeparator * sepMS; + SoCylinder* innerDetector; + SoCylinder* calos; + SoCylinder* muonSpectrometer; + + void updateFields(); + void ensureInit3DObjects(); +}; + +//____________________________________________________________________ +VP1TrackingVolumes::VP1TrackingVolumes( SoMaterial * materialID,SoMaterial * materialCalo,SoMaterial * materialMS, + bool showID, bool showCalo, bool showMS, + SoSeparator * attachsep, + IVP1System * sys,QObject * parent) + : QObject(parent), VP1HelperClassBase(sys,"VP1TrackingVolumes"), m_d(new Imp(this,materialID, materialCalo, materialMS, attachsep, showID, showCalo, showMS)) +{ +} + +//____________________________________________________________________ +VP1TrackingVolumes::~VP1TrackingVolumes() +{ + + setShown(false); + if (m_d->sepID) + m_d->sepID->unref(); + if (m_d->sepCalo) + m_d->sepCalo->unref(); + if (m_d->sepMS) + m_d->sepMS->unref(); + + if (m_d->sep) + m_d->sep->unref(); + std::cout<<"m_d->attachSep"<<std::endl; + + m_d->attachSep->unref(); + delete m_d; +} + +//____________________________________________________________________ +VP1TrackingVolumes::Imp::Imp(VP1TrackingVolumes *tc, SoMaterial * materialID,SoMaterial * materialCalo,SoMaterial * materialMS, SoSeparator * as, bool showID, bool showCalo, bool showMS) + : theclass(tc), attachSep(as), + materialID(materialID), materialCalo(materialCalo), materialMS(materialMS), + shown(false), shownID(showID), shownCalo(showCalo), shownMS(showMS), + sep(0),sepID(0),sepCalo(0),sepMS(0),innerDetector(0),calos(0),muonSpectrometer(0) +{ + attachSep->ref(); +} + +//____________________________________________________________________ +void VP1TrackingVolumes::Imp::ensureInit3DObjects() +{ + if (sep && sepID && sepCalo && sepMS) + return; + theclass->messageVerbose("Building 3D objects"); + + sep = new SoSeparator; + sep->ref(); + SoRotationXYZ * rotz = new SoRotationXYZ; + rotz->axis.setValue(SoRotationXYZ::X); + rotz->angle.setValue(0.5*M_PI); + sep->addChild(rotz); + + sepID = new SoSeparator; + sepID->ref(); + sepID->addChild(materialID); + innerDetector = new SoCylinder; + innerDetector->radius.setValue(1100.0); + innerDetector->height.setValue( 6400.0 ); + sepID->addChild(innerDetector); + + sepCalo = new SoSeparator; + sepCalo->ref(); + sepCalo->addChild(materialCalo); + calos = new SoCylinder; + calos->radius.setValue(4250.0); + calos->height.setValue( 6779.0*2.0 ); + sepCalo->addChild(calos); + + sepMS = new SoSeparator; + sepMS->ref(); + sepMS->addChild(materialMS); + muonSpectrometer = new SoCylinder; + muonSpectrometer->radius.setValue(15000.0); + muonSpectrometer->height.setValue( 21000.0*2.0 ); + sepMS->addChild(muonSpectrometer); + + +// innerDetector->parts.setValue(SoCylinder::SIDES|SoCylinder::BOTTOM); +} + +//____________________________________________________________________ +void VP1TrackingVolumes::Imp::updateFields() +{ + ensureInit3DObjects(); + theclass->messageVerbose("Updating fields"); + + const bool save = sep->enableNotify(false); + + if (shownID ){ + if (sep->findChild(sepID)<0) + sep->addChild(sepID); + } else { + sep->removeChild(sepID); + } + + if (shownCalo ){ + if (sep->findChild(sepCalo)<0) + sep->addChild(sepCalo); + } else { + sep->removeChild(sepCalo); + } + + if (shownMS ){ + if (sep->findChild(sepMS)<0) + sep->addChild(sepMS); + } else { + sep->removeChild(sepMS); + } + + if (save) { + sep->enableNotify(true); + sep->touch(); + } +} + +//____________________________________________________________________ +void VP1TrackingVolumes::setShown(bool b) +{ + messageVerbose("Signal received: setShown("+str(b)+")"); + if (m_d->shown==b) + return; + m_d->shown=b; + if (m_d->shown) { + m_d->updateFields(); + if (m_d->attachSep->findChild(m_d->sep)<0) + m_d->attachSep->addChild(m_d->sep); + } else { + m_d->attachSep->removeChild(m_d->sep); + } +} + +//____________________________________________________________________ +void VP1TrackingVolumes::setShownID(bool b) +{ + messageVerbose("Signal received: setShownID("+str(b)+")"); + if (m_d->shownID==b) + return; + m_d->shownID=b; + if (m_d->shown) + m_d->updateFields(); +} + +//____________________________________________________________________ +void VP1TrackingVolumes::setShownCalo(bool b) +{ + messageVerbose("Signal received: setShownCalo("+str(b)+")"); + if (m_d->shownCalo==b) + return; + m_d->shownCalo=b; + if (m_d->shown) + m_d->updateFields(); +} + +//____________________________________________________________________ +void VP1TrackingVolumes::setShownMS(bool b) +{ + messageVerbose("Signal received: setShownMS("+str(b)+")"); + if (m_d->shownMS==b) + return; + m_d->shownMS=b; + if (m_d->shown) + m_d->updateFields(); +} diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guidelinescontrollerform.ui b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guidelinescontrollerform.ui new file mode 100644 index 000000000..f0d1f101b --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guidelinescontrollerform.ui @@ -0,0 +1,176 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>VP1GuidesControllerForm</class> + <widget class="QWidget" name="VP1GuidesControllerForm"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>267</width> + <height>182</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QGridLayout"> + <property name="rightMargin"> + <number>1</number> + </property> + <property name="bottomMargin"> + <number>1</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <item row="0" column="0"> + <layout class="QGridLayout"> + <property name="horizontalSpacing"> + <number>2</number> + </property> + <property name="verticalSpacing"> + <number>0</number> + </property> + <item row="0" column="0"> + <widget class="QCheckBox" name="checkBox_floorAndLetters"> + <property name="text"> + <string>Floor && Letters</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QPushButton" name="pushButton_settings_floorAndLetters"> + <property name="text"> + <string>Configure</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QCheckBox" name="checkBox_coordinateAxes"> + <property name="text"> + <string>Coordinate axes</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QPushButton" name="pushButton_settings_coordinateAxes"> + <property name="text"> + <string>Configure</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QCheckBox" name="checkBox_grid"> + <property name="text"> + <string>Grid</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QPushButton" name="pushButton_settings_grid"> + <property name="text"> + <string>Configure</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QCheckBox" name="checkBox_etaCones"> + <property name="text"> + <string>Eta Cones</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QPushButton" name="pushButton_settings_etaCones"> + <property name="text"> + <string>Configure</string> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QCheckBox" name="checkBox_inDetProjSurfs"> + <property name="text"> + <string>ID projection surfaces</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QPushButton" name="pushButton_settings_inDetProjSurfs"> + <property name="text"> + <string>Configure</string> + </property> + </widget> + </item> + <item row="5" column="1"> + <widget class="QPushButton" name="pushButton_settings_trkVolumes"> + <property name="text"> + <string>Configure</string> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QCheckBox" name="checkBox_trkVolumes"> + <property name="text"> + <string>Tracking Volumes</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="7" column="0"> + <widget class="QCheckBox" name="checkBox_lines"> + <property name="text"> + <string>Line from origin</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="7" column="1"> + <widget class="QPushButton" name="pushButton_settings_lines"> + <property name="text"> + <string>Configure</string> + </property> + </widget> + </item> + </layout> + </item> + <item row="0" column="1"> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="0"> + <spacer> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>1</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guides_settings_coordinateaxes_form.ui b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guides_settings_coordinateaxes_form.ui new file mode 100644 index 000000000..02f1c6ee5 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guides_settings_coordinateaxes_form.ui @@ -0,0 +1,347 @@ +<ui version="4.0" > + <class>VP1GuidesSysSettingsCoordinateAxesForm</class> + <widget class="QWidget" name="VP1GuidesSysSettingsCoordinateAxesForm" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>296</width> + <height>248</height> + </rect> + </property> + <property name="windowTitle" > + <string>Form</string> + </property> + <layout class="QVBoxLayout" > + <item> + <widget class="QGroupBox" name="groupBox_4" > + <property name="title" > + <string>Coordinate Axes</string> + </property> + <layout class="QVBoxLayout" > + <item> + <layout class="QHBoxLayout" > + <item> + <widget class="QLabel" name="label_22" > + <property name="text" > + <string>Position (x,y,z):</string> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType" > + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" > + <size> + <width>1</width> + <height>5</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" > + <item> + <widget class="QDoubleSpinBox" name="doubleSpinBox_axes_xpos_m" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Preferred" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="alignment" > + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="suffix" > + <string> m</string> + </property> + <property name="decimals" > + <number>3</number> + </property> + <property name="minimum" > + <double>-99.989999999999995</double> + </property> + <property name="singleStep" > + <double>0.010000000000000</double> + </property> + <property name="value" > + <double>0.000000000000000</double> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="doubleSpinBox_axes_ypos_m" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Preferred" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="alignment" > + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="suffix" > + <string> m</string> + </property> + <property name="decimals" > + <number>3</number> + </property> + <property name="minimum" > + <double>-99.989999999999995</double> + </property> + <property name="singleStep" > + <double>0.010000000000000</double> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="doubleSpinBox_axes_zpos_m" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Preferred" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="alignment" > + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="suffix" > + <string> m</string> + </property> + <property name="decimals" > + <number>3</number> + </property> + <property name="minimum" > + <double>-99.989999999999995</double> + </property> + <property name="singleStep" > + <double>0.010000000000000</double> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" > + <size> + <width>1</width> + <height>5</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" > + <item> + <widget class="QLabel" name="label_24" > + <property name="text" > + <string>Colours (x,y,z):</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>2</number> + </property> + <item> + <widget class="VP1MaterialButton" name="matButton_axes_x" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Fixed" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string/> + </property> + </widget> + </item> + <item> + <widget class="VP1MaterialButton" name="matButton_axes_y" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Fixed" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string/> + </property> + </widget> + </item> + <item> + <widget class="VP1MaterialButton" name="matButton_axes_z" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Fixed" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string/> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType" > + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" > + <size> + <width>1</width> + <height>5</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>9</number> + </property> + <item> + <widget class="QLabel" name="label_23" > + <property name="text" > + <string>Lengths:</string> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="doubleSpinBox_axes_lengths_m" > + <property name="alignment" > + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="suffix" > + <string> m</string> + </property> + <property name="decimals" > + <number>3</number> + </property> + <property name="minimum" > + <double>0.001000000000000</double> + </property> + <property name="singleStep" > + <double>0.100000000000000</double> + </property> + <property name="value" > + <double>1.000000000000000</double> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_25" > + <property name="text" > + <string>Rel. thick.:</string> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="doubleSpinBox_axes_relthickness" > + <property name="decimals" > + <number>3</number> + </property> + <property name="minimum" > + <double>0.001000000000000</double> + </property> + <property name="maximum" > + <double>0.150000000000000</double> + </property> + <property name="singleStep" > + <double>0.010000000000000</double> + </property> + <property name="value" > + <double>0.030000000000000</double> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" > + <item> + <widget class="QCheckBox" name="checkBox_axes_shownegativeparts" > + <property name="text" > + <string>Show negative parts</string> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType" > + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" > + <size> + <width>1</width> + <height>5</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>0</number> + </property> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" > + <size> + <width>1</width> + <height>5</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_close" > + <property name="text" > + <string>&Close</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>VP1MaterialButton</class> + <extends>QPushButton</extends> + <header>VP1Base/VP1MaterialButton.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guides_settings_etacones_form.ui b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guides_settings_etacones_form.ui new file mode 100644 index 000000000..4a3fe1c81 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guides_settings_etacones_form.ui @@ -0,0 +1,308 @@ +<ui version="4.0" > + <class>VP1GuidesSysSettingsEtaConeForm</class> + <widget class="QWidget" name="VP1GuidesSysSettingsEtaConeForm" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>220</width> + <height>211</height> + </rect> + </property> + <property name="windowTitle" > + <string>Form</string> + </property> + <layout class="QVBoxLayout" > + <item> + <widget class="QGroupBox" name="groupBox_2" > + <property name="title" > + <string>Cones of constant eta</string> + </property> + <layout class="QGridLayout" > + <property name="leftMargin" > + <number>4</number> + </property> + <property name="topMargin" > + <number>4</number> + </property> + <property name="rightMargin" > + <number>4</number> + </property> + <property name="bottomMargin" > + <number>4</number> + </property> + <property name="horizontalSpacing" > + <number>4</number> + </property> + <item row="0" column="0" > + <layout class="QVBoxLayout" > + <property name="spacing" > + <number>2</number> + </property> + <item> + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>3</number> + </property> + <item> + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>0</number> + </property> + <item> + <widget class="QCheckBox" name="checkBox_etacone1" > + <property name="text" > + <string>eta =</string> + </property> + <property name="checked" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="doubleSpinBox_etaval1" > + <property name="alignment" > + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="minimum" > + <double>0.010000000000000</double> + </property> + <property name="maximum" > + <double>10.000000000000000</double> + </property> + <property name="singleStep" > + <double>0.250000000000000</double> + </property> + <property name="value" > + <double>1.000000000000000</double> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="VP1MaterialButton" name="matButton_etaCone1" > + <property name="text" > + <string/> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>3</number> + </property> + <item> + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>0</number> + </property> + <item> + <widget class="QCheckBox" name="checkBox_etacone2" > + <property name="text" > + <string>eta =</string> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="doubleSpinBox_etaval2" > + <property name="alignment" > + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="minimum" > + <double>0.010000000000000</double> + </property> + <property name="maximum" > + <double>10.000000000000000</double> + </property> + <property name="singleStep" > + <double>0.250000000000000</double> + </property> + <property name="value" > + <double>2.000000000000000</double> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="VP1MaterialButton" name="matButton_etaCone2" > + <property name="text" > + <string/> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>3</number> + </property> + <item> + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>0</number> + </property> + <item> + <widget class="QCheckBox" name="checkBox_etacone3" > + <property name="text" > + <string>eta =</string> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="doubleSpinBox_etaval3" > + <property name="alignment" > + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="minimum" > + <double>0.010000000000000</double> + </property> + <property name="maximum" > + <double>10.000000000000000</double> + </property> + <property name="singleStep" > + <double>0.250000000000000</double> + </property> + <property name="value" > + <double>3.000000000000000</double> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="VP1MaterialButton" name="matButton_etaCone3" > + <property name="text" > + <string/> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item row="0" column="1" > + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType" > + <enum>QSizePolicy::Preferred</enum> + </property> + <property name="sizeHint" > + <size> + <width>16</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="0" colspan="2" > + <layout class="QHBoxLayout" > + <item> + <widget class="QLabel" name="label_6" > + <property name="text" > + <string>Extent:</string> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="doubleSpinBox_etaconeextent" > + <property name="alignment" > + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="suffix" > + <string> m</string> + </property> + <property name="minimum" > + <double>0.010000000000000</double> + </property> + <property name="singleStep" > + <double>0.250000000000000</double> + </property> + <property name="value" > + <double>4.000000000000000</double> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_etaconeextentisr" > + <property name="text" > + <string>r</string> + </property> + <property name="checked" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_etaconeextentisz" > + <property name="text" > + <string>Z</string> + </property> + <property name="checked" > + <bool>false</bool> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>0</number> + </property> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" > + <size> + <width>1</width> + <height>5</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_close" > + <property name="text" > + <string>&Close</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>VP1MaterialButton</class> + <extends>QPushButton</extends> + <header>VP1Base/VP1MaterialButton.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guides_settings_floorandletters_form.ui b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guides_settings_floorandletters_form.ui new file mode 100644 index 000000000..39b686fa9 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guides_settings_floorandletters_form.ui @@ -0,0 +1,294 @@ +<ui version="4.0" > + <class>VP1GuidesSysSettingsFloorAndLettersForm</class> + <widget class="QWidget" name="VP1GuidesSysSettingsFloorAndLettersForm" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>283</width> + <height>188</height> + </rect> + </property> + <property name="windowTitle" > + <string>Form</string> + </property> + <layout class="QVBoxLayout" > + <item> + <widget class="QGroupBox" name="groupBox_3" > + <property name="title" > + <string>Floor/Letters</string> + </property> + <layout class="QGridLayout" > + <property name="leftMargin" > + <number>4</number> + </property> + <property name="topMargin" > + <number>4</number> + </property> + <property name="rightMargin" > + <number>4</number> + </property> + <property name="bottomMargin" > + <number>4</number> + </property> + <item row="0" column="0" > + <layout class="QHBoxLayout" > + <item> + <widget class="QCheckBox" name="checkBox_floorenabled" > + <property name="text" > + <string>Floor</string> + </property> + <property name="checked" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>2</number> + </property> + <item> + <widget class="VP1ColorSelectButton" name="colorButton_floor" > + <property name="text" > + <string/> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_12" > + <property name="text" > + <string>Transp.:</string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="spinBox_floortransp" > + <property name="alignment" > + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="suffix" > + <string> %</string> + </property> + <property name="maximum" > + <number>100</number> + </property> + <property name="singleStep" > + <number>5</number> + </property> + <property name="value" > + <number>0</number> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item row="0" column="1" colspan="2" > + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType" > + <enum>QSizePolicy::Preferred</enum> + </property> + <property name="sizeHint" > + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="0" colspan="2" > + <layout class="QHBoxLayout" > + <item> + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>0</number> + </property> + <item> + <widget class="QCheckBox" name="checkBox_acdesignations" > + <property name="text" > + <string>A+C letters</string> + </property> + <property name="checked" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="VP1MaterialButton" name="matButton_letters" > + <property name="text" > + <string/> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>2</number> + </property> + <item> + <widget class="QLabel" name="label_9" > + <property name="text" > + <string>Height:</string> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="doubleSpinBox_floorheight" > + <property name="alignment" > + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="suffix" > + <string> m</string> + </property> + <property name="minimum" > + <double>-99.989999999999995</double> + </property> + <property name="value" > + <double>-11.000000000000000</double> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item row="1" column="2" > + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType" > + <enum>QSizePolicy::Preferred</enum> + </property> + <property name="sizeHint" > + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="2" column="0" colspan="3" > + <layout class="QHBoxLayout" > + <item> + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>2</number> + </property> + <item> + <widget class="QLabel" name="label_8" > + <property name="text" > + <string>Spacing:</string> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="doubleSpinBox_floorspacing" > + <property name="alignment" > + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="suffix" > + <string> m</string> + </property> + <property name="minimum" > + <double>0.010000000000000</double> + </property> + <property name="maximum" > + <double>40.000000000000000</double> + </property> + <property name="singleStep" > + <double>0.250000000000000</double> + </property> + <property name="value" > + <double>2.000000000000000</double> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>2</number> + </property> + <item> + <widget class="QLabel" name="label_7" > + <property name="text" > + <string>Extent:</string> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="doubleSpinBox_floorextent" > + <property name="alignment" > + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="suffix" > + <string> m</string> + </property> + <property name="minimum" > + <double>1.000000000000000</double> + </property> + <property name="value" > + <double>16.000000000000000</double> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>0</number> + </property> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" > + <size> + <width>1</width> + <height>5</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_close" > + <property name="text" > + <string>&Close</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>VP1MaterialButton</class> + <extends>QPushButton</extends> + <header>VP1Base/VP1MaterialButton.h</header> + </customwidget> + <customwidget> + <class>VP1ColorSelectButton</class> + <extends>QPushButton</extends> + <header>VP1Base/VP1ColorSelectButton.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guides_settings_grid_form.ui b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guides_settings_grid_form.ui new file mode 100644 index 000000000..562c08e39 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guides_settings_grid_form.ui @@ -0,0 +1,246 @@ +<ui version="4.0" > + <class>VP1GuidesSysSettingsGridForm</class> + <widget class="QWidget" name="VP1GuidesSysSettingsGridForm" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>275</width> + <height>178</height> + </rect> + </property> + <property name="windowTitle" > + <string>Form</string> + </property> + <layout class="QVBoxLayout" > + <item> + <widget class="QGroupBox" name="groupBox" > + <property name="title" > + <string>Grid</string> + </property> + <layout class="QGridLayout" > + <property name="leftMargin" > + <number>4</number> + </property> + <property name="topMargin" > + <number>4</number> + </property> + <property name="rightMargin" > + <number>4</number> + </property> + <property name="bottomMargin" > + <number>4</number> + </property> + <item row="0" column="0" colspan="2" > + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>2</number> + </property> + <item> + <widget class="QRadioButton" name="radioButton_grid_cartesian" > + <property name="text" > + <string>Cartesian</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_grid_cylindrical" > + <property name="text" > + <string>Cylindrical</string> + </property> + <property name="checked" > + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </item> + <item row="0" column="2" > + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType" > + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" > + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="0" > + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>2</number> + </property> + <item> + <widget class="VP1ColorSelectButton" name="colorButton_grid" > + <property name="text" > + <string/> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_26" > + <property name="text" > + <string>Transp.:</string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="spinBox_gridtransp" > + <property name="alignment" > + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="suffix" > + <string> %</string> + </property> + <property name="maximum" > + <number>100</number> + </property> + <property name="singleStep" > + <number>5</number> + </property> + <property name="value" > + <number>0</number> + </property> + </widget> + </item> + </layout> + </item> + <item row="1" column="1" colspan="2" > + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType" > + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" > + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="2" column="0" colspan="3" > + <layout class="QHBoxLayout" > + <item> + <widget class="QLabel" name="label_3" > + <property name="text" > + <string>Spacing:</string> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="doubleSpinBox_gridspacing" > + <property name="alignment" > + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="suffix" > + <string> m</string> + </property> + <property name="decimals" > + <number>2</number> + </property> + <property name="minimum" > + <double>0.010000000000000</double> + </property> + <property name="maximum" > + <double>99.989999999999995</double> + </property> + <property name="singleStep" > + <double>0.250000000000000</double> + </property> + <property name="value" > + <double>2.000000000000000</double> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType" > + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" > + <size> + <width>5</width> + <height>5</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label_4" > + <property name="text" > + <string>Extent:</string> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="doubleSpinBox_gridextent" > + <property name="alignment" > + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="suffix" > + <string> m</string> + </property> + <property name="decimals" > + <number>2</number> + </property> + <property name="value" > + <double>4.000000000000000</double> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>0</number> + </property> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" > + <size> + <width>1</width> + <height>5</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_close" > + <property name="text" > + <string>&Close</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>VP1ColorSelectButton</class> + <extends>QPushButton</extends> + <header>VP1Base/VP1ColorSelectButton.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guides_settings_idprojsurfs_form.ui b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guides_settings_idprojsurfs_form.ui new file mode 100644 index 000000000..37397fb73 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guides_settings_idprojsurfs_form.ui @@ -0,0 +1,683 @@ +<ui version="4.0" > + <class>VP1GuidesSysSettingsIDProjSurfsForm</class> + <widget class="QWidget" name="VP1GuidesSysSettingsIDProjSurfsForm" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>266</width> + <height>552</height> + </rect> + </property> + <property name="windowTitle" > + <string>Form</string> + </property> + <layout class="QVBoxLayout" > + <item> + <widget class="QGroupBox" name="groupBox_pixelproj" > + <property name="title" > + <string>Pixel Projections</string> + </property> + <property name="checkable" > + <bool>true</bool> + </property> + <property name="checked" > + <bool>false</bool> + </property> + <layout class="QGridLayout" > + <property name="leftMargin" > + <number>4</number> + </property> + <property name="topMargin" > + <number>4</number> + </property> + <property name="rightMargin" > + <number>4</number> + </property> + <property name="bottomMargin" > + <number>4</number> + </property> + <item row="0" column="0" > + <layout class="QHBoxLayout" > + <item> + <widget class="QLabel" name="label_19" > + <property name="text" > + <string>Show surfaces: </string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_pixelprojsurf_parts_asneeded" > + <property name="text" > + <string>As needed</string> + </property> + <property name="checked" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="VP1MaterialButton" name="pushButton_projsurfmaterial_pixel" > + <property name="text" > + <string/> + </property> + </widget> + </item> + </layout> + </item> + <item row="0" column="1" > + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType" > + <enum>QSizePolicy::Preferred</enum> + </property> + <property name="sizeHint" > + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="0" colspan="2" > + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>0</number> + </property> + <property name="leftMargin" > + <number>20</number> + </property> + <item> + <widget class="QCheckBox" name="checkBox_pixelprojsurf_parts_barrelA" > + <property name="enabled" > + <bool>false</bool> + </property> + <property name="text" > + <string>brl A</string> + </property> + <property name="checked" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_pixelprojsurf_parts_barrelC" > + <property name="enabled" > + <bool>false</bool> + </property> + <property name="text" > + <string>brl C</string> + </property> + <property name="checked" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_pixelprojsurf_parts_endcapA" > + <property name="enabled" > + <bool>false</bool> + </property> + <property name="text" > + <string>ec A</string> + </property> + <property name="checked" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_pixelprojsurf_parts_endcapC" > + <property name="enabled" > + <bool>false</bool> + </property> + <property name="text" > + <string>ec C</string> + </property> + <property name="checked" > + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </item> + <item row="2" column="0" colspan="2" > + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>0</number> + </property> + <item> + <widget class="QLabel" name="label_20" > + <property name="text" > + <string>brl pos: </string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_pixelprojsurf_barrel_inner" > + <property name="text" > + <string>Inner</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_pixelprojsurf_barrel_outer" > + <property name="text" > + <string>Outer</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_pixelprojsurf_barrel_both" > + <property name="text" > + <string>Both</string> + </property> + </widget> + </item> + </layout> + </item> + <item row="3" column="0" colspan="2" > + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>0</number> + </property> + <item> + <widget class="QLabel" name="label_21" > + <property name="text" > + <string>ec pos: </string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_pixelprojsurf_endcap_inner" > + <property name="text" > + <string>Inner</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_pixelprojsurf_endcap_outer" > + <property name="text" > + <string>Outer</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_pixelprojsurf_endcap_both" > + <property name="text" > + <string>Both</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_sctproj" > + <property name="title" > + <string>SCT Projections</string> + </property> + <property name="checkable" > + <bool>true</bool> + </property> + <property name="checked" > + <bool>false</bool> + </property> + <layout class="QGridLayout" > + <property name="leftMargin" > + <number>4</number> + </property> + <property name="topMargin" > + <number>4</number> + </property> + <property name="rightMargin" > + <number>4</number> + </property> + <property name="bottomMargin" > + <number>4</number> + </property> + <item row="0" column="0" > + <layout class="QHBoxLayout" > + <item> + <widget class="QLabel" name="label_15" > + <property name="text" > + <string>Show surfaces: </string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_sctprojsurf_parts_asneeded" > + <property name="text" > + <string>As needed</string> + </property> + <property name="checked" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="VP1MaterialButton" name="pushButton_projsurfmaterial_sct" > + <property name="text" > + <string/> + </property> + </widget> + </item> + </layout> + </item> + <item row="0" column="1" > + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType" > + <enum>QSizePolicy::Preferred</enum> + </property> + <property name="sizeHint" > + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="0" colspan="2" > + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>0</number> + </property> + <property name="leftMargin" > + <number>20</number> + </property> + <item> + <widget class="QCheckBox" name="checkBox_sctprojsurf_parts_barrelA" > + <property name="enabled" > + <bool>false</bool> + </property> + <property name="text" > + <string>brl A</string> + </property> + <property name="checked" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_sctprojsurf_parts_barrelC" > + <property name="enabled" > + <bool>false</bool> + </property> + <property name="text" > + <string>brl C</string> + </property> + <property name="checked" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_sctprojsurf_parts_endcapA" > + <property name="enabled" > + <bool>false</bool> + </property> + <property name="text" > + <string>ec A</string> + </property> + <property name="checked" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_sctprojsurf_parts_endcapC" > + <property name="enabled" > + <bool>false</bool> + </property> + <property name="text" > + <string>ec C</string> + </property> + <property name="checked" > + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </item> + <item row="2" column="0" colspan="2" > + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>0</number> + </property> + <item> + <widget class="QLabel" name="label_17" > + <property name="text" > + <string>brl pos: </string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_sctprojsurf_barrel_inner" > + <property name="text" > + <string>Inner</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_sctprojsurf_barrel_outer" > + <property name="text" > + <string>Outer</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_sctprojsurf_barrel_both" > + <property name="text" > + <string>Both</string> + </property> + </widget> + </item> + </layout> + </item> + <item row="3" column="0" colspan="2" > + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>0</number> + </property> + <item> + <widget class="QLabel" name="label_18" > + <property name="text" > + <string>ec pos: </string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_sctprojsurf_endcap_inner" > + <property name="text" > + <string>Inner</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_sctprojsurf_endcap_outer" > + <property name="text" > + <string>Outer</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_sctprojsurf_endcap_both" > + <property name="text" > + <string>Both</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_trtproj" > + <property name="title" > + <string>TRT Projections</string> + </property> + <property name="checkable" > + <bool>true</bool> + </property> + <layout class="QGridLayout" > + <property name="leftMargin" > + <number>4</number> + </property> + <property name="topMargin" > + <number>4</number> + </property> + <property name="rightMargin" > + <number>4</number> + </property> + <property name="bottomMargin" > + <number>4</number> + </property> + <item row="0" column="0" colspan="2" > + <layout class="QHBoxLayout" > + <item> + <widget class="QLabel" name="label_14" > + <property name="text" > + <string>Show surfaces: </string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_trtprojsurf_parts_asneeded" > + <property name="text" > + <string>As needed</string> + </property> + <property name="checked" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="VP1MaterialButton" name="pushButton_projsurfmaterial_trt" > + <property name="text" > + <string/> + </property> + </widget> + </item> + </layout> + </item> + <item row="0" column="2" > + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType" > + <enum>QSizePolicy::Preferred</enum> + </property> + <property name="sizeHint" > + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="0" colspan="3" > + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>0</number> + </property> + <property name="leftMargin" > + <number>20</number> + </property> + <item> + <widget class="QCheckBox" name="checkBox_trtprojsurf_parts_barrelA" > + <property name="enabled" > + <bool>false</bool> + </property> + <property name="text" > + <string>brl A</string> + </property> + <property name="checked" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_trtprojsurf_parts_barrelC" > + <property name="enabled" > + <bool>false</bool> + </property> + <property name="text" > + <string>brl C</string> + </property> + <property name="checked" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_trtprojsurf_parts_endcapA" > + <property name="enabled" > + <bool>false</bool> + </property> + <property name="text" > + <string>ec A</string> + </property> + <property name="checked" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_trtprojsurf_parts_endcapC" > + <property name="enabled" > + <bool>false</bool> + </property> + <property name="text" > + <string>ec C</string> + </property> + <property name="checked" > + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </item> + <item row="2" column="0" colspan="3" > + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>0</number> + </property> + <item> + <widget class="QLabel" name="label_13" > + <property name="text" > + <string>brl pos: </string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_trtprojsurf_barrel_inner" > + <property name="text" > + <string>Inner</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_trtprojsurf_barrel_outer" > + <property name="text" > + <string>Outer</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_trtprojsurf_barrel_both" > + <property name="text" > + <string>Both</string> + </property> + </widget> + </item> + </layout> + </item> + <item row="3" column="0" colspan="3" > + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>0</number> + </property> + <item> + <widget class="QLabel" name="label_16" > + <property name="text" > + <string>ec pos: </string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_trtprojsurf_endcap_inner" > + <property name="text" > + <string>Inner</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_trtprojsurf_endcap_outer" > + <property name="text" > + <string>Outer</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_trtprojsurf_endcap_both" > + <property name="text" > + <string>Both</string> + </property> + </widget> + </item> + </layout> + </item> + <item row="4" column="0" > + <widget class="QCheckBox" name="checkBox_trtprojsurf_z2r" > + <property name="text" > + <string>Project ec to brl planes (Z to R)</string> + </property> + </widget> + </item> + <item row="4" column="1" colspan="2" > + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType" > + <enum>QSizePolicy::Preferred</enum> + </property> + <property name="sizeHint" > + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QHBoxLayout" > + <property name="spacing" > + <number>0</number> + </property> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" > + <size> + <width>1</width> + <height>5</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_close" > + <property name="text" > + <string>&Close</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>VP1MaterialButton</class> + <extends>QPushButton</extends> + <header>VP1Base/VP1MaterialButton.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guides_settings_lines_form.ui b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guides_settings_lines_form.ui new file mode 100644 index 000000000..aa6ab3689 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guides_settings_lines_form.ui @@ -0,0 +1,192 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>VP1LinesForm</class> + <widget class="QWidget" name="VP1LinesForm"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>333</width> + <height>166</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QGridLayout" name="gridLayout"> + <item row="6" column="0"> + <widget class="QLabel" name="label_26"> + <property name="text"> + <string>Length</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QDoubleSpinBox" name="doubleSpinBox_phi"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="suffix"> + <string/> + </property> + <property name="decimals"> + <number>3</number> + </property> + <property name="minimum"> + <double>-6.280000000000000</double> + </property> + <property name="maximum"> + <double>6.280000000000000</double> + </property> + <property name="singleStep"> + <double>0.010000000000000</double> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QDoubleSpinBox" name="doubleSpinBox_theta"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="suffix"> + <string/> + </property> + <property name="decimals"> + <number>3</number> + </property> + <property name="minimum"> + <double>-6.280000000000000</double> + </property> + <property name="maximum"> + <double>6.280000000000000</double> + </property> + <property name="singleStep"> + <double>0.010000000000000</double> + </property> + </widget> + </item> + <item row="6" column="1"> + <widget class="QDoubleSpinBox" name="doubleSpinBox_length"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="suffix"> + <string> m</string> + </property> + <property name="decimals"> + <number>3</number> + </property> + <property name="minimum"> + <double>-99.989999999999995</double> + </property> + <property name="singleStep"> + <double>0.010000000000000</double> + </property> + <property name="value"> + <double>5.000000000000000</double> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="label_27"> + <property name="text"> + <string>Theta</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QDoubleSpinBox" name="doubleSpinBox_eta"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="suffix"> + <string/> + </property> + <property name="decimals"> + <number>3</number> + </property> + <property name="minimum"> + <double>-5.000000000000000</double> + </property> + <property name="maximum"> + <double>5.000000000000000</double> + </property> + <property name="singleStep"> + <double>0.010000000000000</double> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_24"> + <property name="text"> + <string>Eta</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_25"> + <property name="text"> + <string>Phi</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="_2"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>5</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_close"> + <property name="text"> + <string>&Close</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guides_settings_trkvolumes_form.ui b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guides_settings_trkvolumes_form.ui new file mode 100644 index 000000000..973ad5d78 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12GuideLineSystems/src/guides_settings_trkvolumes_form.ui @@ -0,0 +1,139 @@ +<ui version="4.0" > + <class>VP1TrackingVolumesForm</class> + <widget class="QWidget" name="VP1TrackingVolumesForm" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>236</width> + <height>158</height> + </rect> + </property> + <property name="windowTitle" > + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout" > + <item> + <layout class="QGridLayout" name="gridLayout" > + <item row="0" column="0" > + <widget class="QCheckBox" name="checkBox_ID" > + <property name="enabled" > + <bool>true</bool> + </property> + <property name="toolTip" > + <string>More formally, in the TrackingVolumes service, this is known as the CalorimeterEntryLayer</string> + </property> + <property name="text" > + <string>Inner Detector</string> + </property> + <property name="checked" > + <bool>true</bool> + </property> + </widget> + </item> + <item row="0" column="1" > + <widget class="VP1MaterialButton" name="matButton_ID" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Fixed" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string/> + </property> + </widget> + </item> + <item row="1" column="0" > + <widget class="QCheckBox" name="checkBox_Calo" > + <property name="enabled" > + <bool>true</bool> + </property> + <property name="text" > + <string>Calorimeters</string> + </property> + </widget> + </item> + <item row="1" column="1" > + <widget class="VP1MaterialButton" name="matButton_Calo" > + <property name="enabled" > + <bool>true</bool> + </property> + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Fixed" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string/> + </property> + </widget> + </item> + <item row="2" column="0" > + <widget class="QCheckBox" name="checkBox_MS" > + <property name="enabled" > + <bool>true</bool> + </property> + <property name="text" > + <string>MuonSpectrometer</string> + </property> + </widget> + </item> + <item row="2" column="1" > + <widget class="VP1MaterialButton" name="matButton_MS" > + <property name="enabled" > + <bool>true</bool> + </property> + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Fixed" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string/> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="_2" > + <property name="spacing" > + <number>0</number> + </property> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>1</width> + <height>5</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_close" > + <property name="text" > + <string>&Close</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>VP1MaterialButton</class> + <extends>QPushButton</extends> + <header>VP1Base/VP1MaterialButton.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/graphics/VTI12/VTI12Systems/VTI12SimHitSystems/CMakeLists.txt b/graphics/VTI12/VTI12Systems/VTI12SimHitSystems/CMakeLists.txt new file mode 100644 index 000000000..e70a808b9 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12SimHitSystems/CMakeLists.txt @@ -0,0 +1,38 @@ +################################################################################ +# Package: VTI12SimHitSystems +################################################################################ + +# Declare the package name: +atlas_subdir( VTI12SimHitSystems ) + +# Declare the package's dependencies: +atlas_depends_on_subdirs( PUBLIC + graphics/VP1/VP1Base + PRIVATE + Control/StoreGate + DetectorDescription/GeoModel/GeoAdaptors + DetectorDescription/GeoPrimitives + Scintillator/ScintSimEvent + graphics/VTI12/VTI12Utils ) + +# External dependencies: +find_package( Coin3D ) +find_package( Eigen ) +find_package( Qt5 COMPONENTS Core Widgets ) + +# Generate UI files automatically: +set( CMAKE_AUTOUIC TRUE ) +# Generate MOC files automatically: +set( CMAKE_AUTOMOC TRUE ) +# Generate resource files automatically: +set( CMAKE_AUTORCC TRUE ) +# to let CMake find .h files automatically-generated from .ui files +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +# Component(s) in the package: +atlas_add_library( VTI12SimHitSystems VTI12SimHitSystems/*.h src/*.h src/*.cxx src/*.qrc + PUBLIC_HEADERS VTI12SimHitSystems + PRIVATE_INCLUDE_DIRS ${COIN3D_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS} + LINK_LIBRARIES VP1Base Qt5::Core Qt5::Widgets GL StoreGateLib SGtests + PRIVATE_LINK_LIBRARIES ${COIN3D_LIBRARIES} ${EIGEN_LIBRARIES} GeoAdaptors GeoPrimitives ScintSimEvent VTI12Utils ) + diff --git a/graphics/VTI12/VTI12Systems/VTI12SimHitSystems/VTI12SimHitSystems/VP1SimHitSystem.h b/graphics/VTI12/VTI12Systems/VTI12SimHitSystems/VTI12SimHitSystems/VP1SimHitSystem.h new file mode 100755 index 000000000..6ee0a3ca5 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12SimHitSystems/VTI12SimHitSystems/VP1SimHitSystem.h @@ -0,0 +1,34 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef VP1SIMHITSYSTEM_H +#define VP1SIMHITSYSTEM_H + +#include "VP1Base/IVP13DSystemSimple.h" + +class VP1SimHitSystem: public IVP13DSystemSimple +{ + Q_OBJECT + + public: + VP1SimHitSystem(); + ~VP1SimHitSystem(); + + QWidget* buildController(); + + void systemcreate(StoreGateSvc* detstore); + void buildEventSceneGraph(StoreGateSvc* sg, SoSeparator *root); + + protected slots: + void checkboxChanged(); + + private: + class Clockwork; + Clockwork* m_clockwork; + + void buildHitTree(const QString& detector); + +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12SimHitSystems/src/VP1SimHitSystem.cxx b/graphics/VTI12/VTI12Systems/VTI12SimHitSystems/src/VP1SimHitSystem.cxx new file mode 100755 index 000000000..2d5b5be43 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12SimHitSystems/src/VP1SimHitSystem.cxx @@ -0,0 +1,251 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "VTI12SimHitSystems/VP1SimHitSystem.h" +#include "ui_simhitcontrollerform.h" + +#include "StoreGate/StoreGateSvc.h" + +#include <QMap> +#include <QSet> + +#include <Inventor/C/errors/debugerror.h> +#include <Inventor/nodes/SoDrawStyle.h> +#include <Inventor/nodes/SoMaterial.h> +#include <Inventor/nodes/SoSeparator.h> +#include <Inventor/nodes/SoSwitch.h> +#include <Inventor/nodes/SoVertexProperty.h> +#include <Inventor/nodes/SoPointSet.h> +#include <Inventor/SbColor.h> + +#include "ScintSimEvent/ScintHitCollection.h" +#include "GeoAdaptors/GeoScintHit.h" +// #include "InDetSimEvent/SiHitCollection.h" +// #include "InDetSimEvent/TRTUncompressedHitCollection.h" +// #include "GeoAdaptors/GeoTRTUncompressedHit.h" +// #include "GeoAdaptors/GeoSiHit.h" + +#include "VTI12Utils/VP1SGContentsHelper.h" + +#include "GeoPrimitives/GeoPrimitives.h" + +class VP1SimHitSystem::Clockwork +{ +public: + QMap<QString,SoSwitch*> switchMap; + QMap<QString,SbColor> colorMap; + QMap<QCheckBox*,QString> checkBoxNamesMap; + QMap<QString,QCheckBox*> checkBoxMap; + QSet<QString> hitsThisEvent; + StoreGateSvc * sg; +}; + +VP1SimHitSystem::VP1SimHitSystem() + :IVP13DSystemSimple("Sim Hits","Display simulation hits","Vakho Tsulaia <Vakhtang.Tsulaia@cern.ch>"), + m_clockwork(new Clockwork()) +{ +} + +VP1SimHitSystem::~VP1SimHitSystem() +{ + delete m_clockwork; + m_clockwork = 0; +} + +QWidget* VP1SimHitSystem::buildController() +{ + QWidget* controller = new QWidget(0); + Ui::SimHitControllerForm ui; + ui.setupUi(controller); + + // Populate Check Box Names Map + m_clockwork->checkBoxNamesMap.insert(ui.chbxVetoHits,"Veto"); + m_clockwork->checkBoxNamesMap.insert(ui.chbxTriggerHits,"Trigger"); + m_clockwork->checkBoxNamesMap.insert(ui.chbxPreshowerHits,"Preshower"); + m_clockwork->checkBoxNamesMap.insert(ui.chbxTrackerHits,"Tracker"); + m_clockwork->checkBoxNamesMap.insert(ui.chbxCaloHits,"Calorimeter"); + + // Populate Check Box Map and connect slots + foreach(QCheckBox* cb,m_clockwork->checkBoxNamesMap.keys()) + { + connect(cb,SIGNAL(toggled(bool)),this,SLOT(checkboxChanged())); + m_clockwork->checkBoxMap.insert(m_clockwork->checkBoxNamesMap[cb],cb); + } + + return controller; +} + +void VP1SimHitSystem::systemcreate(StoreGateSvc* /*detstore*/) +{ + // Populate Color Map + m_clockwork->colorMap.insert("Veto",SbColor(0,0,1)); + m_clockwork->colorMap.insert("Trigger",SbColor(1,1,1)); + m_clockwork->colorMap.insert("Preshower",SbColor(1,0,0)); + m_clockwork->colorMap.insert("Tracker",SbColor(.98,.8,.21)); + m_clockwork->colorMap.insert("Calorimeter",SbColor(0,.44,.28)); +} + +void VP1SimHitSystem::buildEventSceneGraph(StoreGateSvc* sg, SoSeparator *root) +{ + // --- Draw style: POINTS + SoDrawStyle* ds = new SoDrawStyle(); + ds->style.setValue(SoDrawStyle::POINTS); + ds->pointSize=4; + root->addChild(ds); + + // Keep SG pointer + m_clockwork->sg = sg; + + // clean up + m_clockwork->switchMap.clear(); + m_clockwork->hitsThisEvent.clear(); + + if(!sg) + { + message("0 pointer to the Store Gate!"); + return; + } + + foreach(QString detector,m_clockwork->checkBoxMap.keys()) + { + // Add switch, off by default + SoSwitch* sw = new SoSwitch(); + sw->whichChild = SO_SWITCH_NONE; + root->addChild(sw); + m_clockwork->switchMap.insert(detector,sw); + + // Build subtree if the check box is ON + if(m_clockwork->checkBoxMap.contains(detector) && + m_clockwork->checkBoxMap[detector]->isChecked()) + { + buildHitTree(detector); + sw->whichChild = SO_SWITCH_ALL; + } + updateGUI(); + } +} + +void VP1SimHitSystem::checkboxChanged() +{ + // Get ChB pointer + QCheckBox* cb = dynamic_cast<QCheckBox*>(sender()); + if(cb && m_clockwork->checkBoxNamesMap.contains(cb)) + { + // Get detector name + QString detector = m_clockwork->checkBoxNamesMap[cb]; + if(m_clockwork->switchMap.contains(detector)) + { + // Get swtich + SoSwitch* sw = m_clockwork->switchMap[detector]; + if(cb->isChecked()){ + // Build subtree if necessary + if(!m_clockwork->hitsThisEvent.contains(detector)) + buildHitTree(detector); + sw->whichChild = SO_SWITCH_ALL; + } + else + sw->whichChild = SO_SWITCH_NONE; + } else { + message("WARNING: Unknown detector:"+detector); + } + } +} + + +void VP1SimHitSystem::buildHitTree(const QString& detector) +{ + messageVerbose("buildHitTree for "+detector); + if(m_clockwork->hitsThisEvent.contains(detector)) { + messageVerbose(" in hitsThisEvent"); return; + } + if(!m_clockwork->colorMap.contains(detector)) { + messageVerbose("not in colorMap"); return; + } + if(!m_clockwork->switchMap.contains(detector)) { + messageVerbose("not in switchMap"); return; + } + + // -- Initializations + StoreGateSvc* sg = m_clockwork->sg; + SoSwitch* sw = m_clockwork->switchMap[detector]; + unsigned int hitCount = 0; + + SoVertexProperty* hitVtxProperty = new SoVertexProperty(); + SoPointSet* hitPointSet = new SoPointSet(); + + hitVtxProperty->enableNotify(FALSE); + hitPointSet->enableNotify(FALSE); + + // -- COLOR + SoMaterial* material = new SoMaterial(); + material->diffuseColor.setValue(m_clockwork->colorMap[detector]); + + sw->addChild(material); + + // Take hits from SG + if(detector=="Veto") + { + // + // Veto: + // + const ScintHitCollection* p_collection = nullptr; + if(sg->retrieve(p_collection, "VetoHits")==StatusCode::SUCCESS) + { + for(ScintHitConstIterator i_hit=p_collection->begin(); i_hit!=p_collection->end(); ++i_hit) + { + GeoScintHit ghit(*i_hit); + if(!ghit) continue; + HepGeom::Point3D<double> u = ghit.getGlobalPosition(); + hitVtxProperty->vertex.set1Value(hitCount++,u.x(),u.y(),u.z()); + } + } + else + message("Unable to retrieve Veto Hits"); + } + else if(detector=="Trigger") + { + // + // Trigger: + // + const DataHandle<ScintHitCollection> s_collection; + if(sg->retrieve(s_collection,"TriggerHits")==StatusCode::SUCCESS) + { + for(ScintHitConstIterator i_hit=s_collection->begin();i_hit!=s_collection->end();++i_hit) + { + GeoScintHit ghit(*i_hit); + if (!ghit) continue; + HepGeom::Point3D<double> u = ghit.getGlobalPosition(); + hitVtxProperty->vertex.set1Value(hitCount++,u.x(),u.y(),u.z()); + } + } + else + message("Unable to retrieve Trigger Hits"); + } + else if(detector=="Preshower") + { + // + // Preshower: + // + const DataHandle<ScintHitCollection> t_collection; + if(sg->retrieve(t_collection,"PreshowerHits")==StatusCode::SUCCESS) + { + for(ScintHitConstIterator i_hit=t_collection->begin();i_hit!=t_collection->end();++i_hit) + { + GeoScintHit ghit(*i_hit); + if(!ghit) continue; + Amg::Vector3D u = Amg::Hep3VectorToEigen(ghit.getGlobalPosition()); + hitVtxProperty->vertex.set1Value(hitCount++,u.x(),u.y(), u.z() ); + } + } + else + message("Unable to retrieve Preshower Hits"); + } + // Add to the switch + hitPointSet->numPoints=hitCount; + hitPointSet->vertexProperty.setValue(hitVtxProperty); + sw->addChild(hitPointSet); + hitPointSet->enableNotify(TRUE); + hitVtxProperty->enableNotify(TRUE); +} + diff --git a/graphics/VTI12/VTI12Systems/VTI12SimHitSystems/src/simhitcontrollerform.ui b/graphics/VTI12/VTI12Systems/VTI12SimHitSystems/src/simhitcontrollerform.ui new file mode 100755 index 000000000..b12880a81 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12SimHitSystems/src/simhitcontrollerform.ui @@ -0,0 +1,208 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>SimHitControllerForm</class> + <widget class="QWidget" name="SimHitControllerForm"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>454</width> + <height>310</height> + </rect> + </property> + <property name="windowTitle"> + <string>Sim Hits</string> + </property> + <layout class="QHBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>9</number> + </property> + <item> + <layout class="QVBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>0</number> + </property> + <item> + <layout class="QVBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>0</number> + </property> + <item> + <layout class="QHBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="lblGeneral"> + <property name="text"> + <string>Select hits to show</string> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>71</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>0</number> + </property> + <item> + <layout class="QVBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>0</number> + </property> + </layout> + </item> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Scintillator</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QCheckBox" name="chbxVetoHits"> + <property name="text"> + <string>Veto Hits</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="chbxTriggerHits"> + <property name="text"> + <string>Trigger Hits</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="chbxPreshowerHits"> + <property name="text"> + <string>Preshower Hits</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QGroupBox" name="groupBox_2"> + <property name="title"> + <string>Tracker</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QCheckBox" name="chbxTrackerHits"> + <property name="text"> + <string>Tracker Hits</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QVBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>0</number> + </property> + </layout> + </item> + </layout> + </item> + </layout> + </item> + <item> + <widget class="QGroupBox" name="groupBox_3"> + <property name="title"> + <string>Calorimeter</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <widget class="QCheckBox" name="chbxCaloHits"> + <property name="text"> + <string>Calorimeter Hits</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>111</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>111</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/CMakeLists.txt b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/CMakeLists.txt new file mode 100644 index 000000000..7ac5f9320 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/CMakeLists.txt @@ -0,0 +1,92 @@ +# $Id: CMakeLists.txt 728682 2016-03-09 15:17:26Z krasznaa $ +################################################################################ +# Package: VTI12TrackSystems +################################################################################ + +# Declare the package name: +atlas_subdir( VTI12TrackSystems ) + +# Declare the package's dependencies: +atlas_depends_on_subdirs( + PUBLIC + DetectorDescription/GeoPrimitives + DetectorDescription/Identifier +# Event/xAOD/xAODTracking + GaudiKernel + Generators/GeneratorObjects + Simulation/G4Sim/TrackRecord + Tracking/TrkDetDescr/TrkDetDescrInterfaces + Tracking/TrkDetDescr/TrkSurfaces + Tracking/TrkEvent/TrkEventPrimitives + Tracking/TrkEvent/TrkParameters + graphics/VP1/VP1Base + graphics/VTI12/VTI12Utils + PRIVATE + Control/AthContainers + Control/StoreGate + DetectorDescription/FaserDetDescr + Event/EventPrimitives +# ForwardDetectors/ForwardSimulation/ForwardRegion_SimEv +# InnerDetector/InDetDetDescr/InDetIdentifier +# InnerDetector/InDetDetDescr/InDetReadoutGeometry +# InnerDetector/InDetRecEvent/InDetPrepRawData +# InnerDetector/InDetRecEvent/InDetRIO_OnTrack +# InnerDetector/InDetSimEvent + Scintillator/ScintDetDescr/ScintIdentifier + Scintillator/ScintDetDescr/ScintReadoutGeometry + Scintillator/ScintSimEvent + Reconstruction/Particle + Tracking/TrkDetDescr/TrkDetDescrUtils + Tracking/TrkDetDescr/TrkDetElementBase + Tracking/TrkDetDescr/TrkVolumes + Tracking/TrkEvent/TrkCompetingRIOsOnTrack + Tracking/TrkEvent/TrkMaterialOnTrack + Tracking/TrkEvent/TrkMeasurementBase + Tracking/TrkEvent/TrkPrepRawData + Tracking/TrkEvent/TrkPseudoMeasurementOnTrack + Tracking/TrkEvent/TrkRIO_OnTrack + Tracking/TrkEvent/TrkSegment + Tracking/TrkEvent/TrkTrack + Tracking/TrkEvent/TrkTrackSummary + Tracking/TrkExtrapolation/TrkExInterfaces + Tracking/TrkFitter/TrkFitterInterfaces + graphics/VP1/VP1HEPVis + graphics/VTI12/VTI12Systems/VTI12GuideLineSystems +# graphics/VP1/VP1Systems/VP1PRDSystems + ) + +# External dependencies: +find_package( CLHEP ) +find_package( Coin3D ) +find_package( HepMC ) +find_package( Qt5 COMPONENTS Core Gui Widgets ) +find_package( GeoModel ) + +# Generate UI files automatically: +# Note: add the "Widgets" component to "find_package( Qt5 ...)" if you have UI files, otherwise UIC, even if CMAKE_AUTOUIC is set to ON, is not run +set( CMAKE_AUTOUIC TRUE ) +# Generate MOC files automatically: +set( CMAKE_AUTOMOC TRUE ) + +# Component(s) in the package: +atlas_add_library( VTI12TrackSystems VTI12TrackSystems/*.h src/*.cxx + PUBLIC_HEADERS VTI12TrackSystems + PRIVATE_INCLUDE_DIRS ${COIN3D_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} + ${HEPMC_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR} + LINK_LIBRARIES ${GEOMODEL_LIBRARIES} GeoPrimitives Identifier + #xAODTracking + GaudiKernel GeneratorObjects TrkDetDescrInterfaces TrkSurfaces + TrkEventPrimitives TrkParameters VP1Base VTI12Utils StoreGateLib SGtests + Qt5::Core Qt5::Gui + PRIVATE_LINK_LIBRARIES ${COIN3D_LIBRARIES} ${CLHEP_LIBRARIES} + ${HEPMC_LIBRARIES} AthContainers FaserDetDescr EventPrimitives + ScintIdentifier ScintSimEvent ScintReadoutGeometry + #InDetIdentifier InDetReadoutGeometry InDetPrepRawData InDetRIO_OnTrack InDetSimEvent + Particle + TrkDetDescrUtils TrkDetElementBase TrkVolumes TrkCompetingRIOsOnTrack + TrkMaterialOnTrack TrkMeasurementBase TrkPrepRawData + TrkPseudoMeasurementOnTrack TrkRIO_OnTrack TrkSegment TrkTrack + TrkTrackSummary TrkExInterfaces TrkFitterInterfaces VP1HEPVis + VP1GuideLineSystems + #VP1PRDSystems + ) diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/AscObjSelectionManager.h b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/AscObjSelectionManager.h new file mode 100644 index 000000000..721eedf9e --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/AscObjSelectionManager.h @@ -0,0 +1,98 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class AscObjSelectionManager // +// // +// Description: Manages selection of associated objects // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: April 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef ASCOBJSELECTIONMANAGER_H +#define ASCOBJSELECTIONMANAGER_H + +//Fixme: Make this class usable by prd system also. Maybe make common +//handle base class which tells simple/detailed nodes? + +#include "VP1Base/VP1HelperClassBase.h" +#include <QObject> +#include <QList> + +class AssociatedObjectHandleBase; +class IVP13DSystem; +class TrackSystemController; +class SoCooperativeSelection; +class SoSeparator; +class SoNode; +class SoPath; + +//Lifetime of this object should be from system refresh to system erase. + +class AscObjSelectionManager : public QObject, public VP1HelperClassBase { + + Q_OBJECT + +public: + //Will create selection nodes as appropriate under the event root. + AscObjSelectionManager(SoSeparator* eventRoot,IVP13DSystem *, TrackSystemController*); + void aboutTodelete();//Call this just before deletion (needed since signals should not be emitted from destructors). + virtual ~AscObjSelectionManager(); + //Associated objects must all be attached under this separator: + SoSeparator * getAscObjAttachSep() const; + + /////////////////////////////////////////// + //Fixme: add method for changing mode of operation (single, toggle, shift+click) + + enum MODE { SINGLE, TOGGLE, SHIFT }; + QString toString(MODE) const; + MODE mode() const; + void setMode(MODE); + + void pretendUserClicked(AssociatedObjectHandleBase*); + + void ensureDeselected(const QList<AssociatedObjectHandleBase*>&); + void ensureSelected(const QList<AssociatedObjectHandleBase*>&);//Call with length==1 if in single mode. + void deselectAll(); + + QList<AssociatedObjectHandleBase*> currentSelection() const; + + SoSeparator* eventRoot(); + +signals: + void currentSelectionChanged(const QList<AssociatedObjectHandleBase*>&); + +private: + //For system: + friend class VP1TrackSystem; +// void setEventData( SoCooperativeSelection * sel_click, SoCooperativeSelection * sel_highlight ); +// void eraseEventData(); + //The following returns true if the passed selection node belongs to + //this manager (if not, the system must handle the selection in + //another way). + bool handleUserSelectedSingleNode(SoCooperativeSelection*, SoNode* , SoPath*, AssociatedObjectHandleBase*&);//SINGLE + void userClickedOnBgd(); + +// bool handleUserDeselectedSingleNode(SoCooperativeSelection*, SoNode* , SoPath*);//SINGLE +// bool handleUserChangedSelection(SoCooperativeSelection*, QSet<SoNode*>, QSet<SoPath*>);//TOGGLE/SHIFT +private: + //For associated objects: + friend class AssociatedObjectHandleBase; + void registerAscObj(SoSeparator*simple,SoSeparator *detailed,AssociatedObjectHandleBase*); + void unregisterAscObj(SoSeparator*simple,SoSeparator *detailed); + //Fixme: When a handle changes pickable state to unpickable it + //must be removed from selection list if selected! +private slots: +// void ascObjDetailLevelAboutToChange(); + void ascObjDetailLevelChanged(); +private: + class Imp; + Imp * m_d; +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/AscObj_TSOS.h b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/AscObj_TSOS.h new file mode 100644 index 000000000..394bebc8b --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/AscObj_TSOS.h @@ -0,0 +1,118 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class AscObj_TSOS // +// // +// Description: Handle for TSOS's // +// // +// Author: Troels Kofoed Jacobsen // +// Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: June 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef ASCOBJ_TSOS_H +#define ASCOBJ_TSOS_H + +#include "VTI12TrackSystems/AssociatedObjectHandleBase.h" +#include "VTI12TrackSystems/TrackCommonFlags.h" +#include "VTI12TrackSystems/MeasurementToSoNode.h" +#include "VTI12TrackSystems/TrkObjToString.h" +#include "TrkParameters/TrackParameters.h" + +// Eigen migration +//#include "TrkEventPrimitives/GlobalPosition.h" +#include "GeoPrimitives/GeoPrimitives.h" + +#include <QTreeWidgetItem> +#include "VTI12Utils/HitToSoNode.h" + + +typedef AmgSymMatrix(2) AmgCovMatrix; // new Eigen-based CovarianceMatrix + + + +class SoTranslation; +namespace Trk { + class RIO_OnTrack; + class CompetingRIOsOnTrack; + class Surface; + class TrackStateOnSurface; + class MeasurementBase; +} + +class AscObj_TSOS : public AssociatedObjectHandleBase { +public: + + AscObj_TSOS(TrackHandleBase *, const Trk::TrackStateOnSurface *, + unsigned indexOfPointOnTrack); + void setDistToNextPar(const double&); + + void buildShapes(SoSeparator*&shape_simple, SoSeparator*&shape_detailed); + QStringList clicked(); + void zoomView(); //!< Depending on the controller settings, will attempt to zoom the view to this TSOS, for example in click() + bool isShortMeasurement(); //!< Return true if TRT/MDT & shortened mode is on, false otherwise + + virtual void setVisible(bool); + + TrackCommonFlags::TSOSPartsFlags parts() const { return m_parts; } + bool hasParameters() const { return m_parts & TrackCommonFlags::TSOS_TrackPars; } + bool hasParError() const { return m_parts & TrackCommonFlags::TSOS_AnyParsErrors; } + bool hasError() const { return m_parts & TrackCommonFlags::TSOS_AnyErrors; } + bool hasMaterialEffect() const { return m_parts & TrackCommonFlags::TSOS_AnyMaterialEffects; } + bool hasSurface() const { return m_parts & TrackCommonFlags::TSOS_AnySurface; } + bool hasMeasurement() const { return m_parts & TrackCommonFlags::TSOS_AnyMeasurement; } + + const Trk::MeasurementBase * measurement() const; + const Trk::Surface * surface() const; + const Trk::RIO_OnTrack * rioOnTrack() const; + const Trk::CompetingRIOsOnTrack * competingRIOsOnTrack() const; + const Trk::TrackStateOnSurface * trackStateOnSurface() const {return m_tsos;} + + //Add identify() method??? + + Amg::Vector3D approxCenter() const; + + virtual bool initiatesOwnZooms() const { return true; } + + virtual QTreeWidgetItem* browserTreeItem() const {return m_objBrowseTree;} + virtual void setBrowserTreeItem(QTreeWidgetItem* obt) {m_objBrowseTree=obt;} + +protected: + int regionIndex() const; + double lodCrossOverValue() const {return 1000; } + +private: + virtual ~AscObj_TSOS() {}//Private so it can only be deleted by TrackHandleBase + const Trk::TrackStateOnSurface * m_tsos; + TrackCommonFlags::TSOSPartsFlags m_parts; + unsigned m_indexOfPointOnTrack; + double m_distToNextPar; + QTreeWidgetItem* m_objBrowseTree; + + double deviationFromMeasurement(const bool& absolute = false); + void addDeviationFromMeasurementInfoToShapes( SoSeparator*&shape_simple, SoSeparator*&shape_detailed); + void addTransformToSurface( SoSeparator*&shape_simple, SoSeparator*&shape_detailed); + void addTrackParamInfoToShapes( SoSeparator*&shape_simple, SoSeparator*&shape_detailed, + bool showPars, bool showParsErrors, bool showSurfaces ); + void addErrors(const Trk::Surface& theSurface, const AmgSymMatrix(5)& tmpCovMat, + const Amg::Vector2D& localPos, const Amg::Vector3D& p1, bool showSurfaces, + SoSeparator* shape_simple, SoSeparator* shape_detailed, bool force1D, bool applyLocalTrans ); + void addRIO_OnTrackInfoToShapes( SoSeparator*&shape_simple, SoSeparator*&shape_detailed, const Trk::RIO_OnTrack* rio, bool blockDrawingOfGP=false); + void addCompetingRIO_OnTrackInfoToShapes( SoSeparator*&shape_simple, SoSeparator*&shape_detailed); + void addSurfaceToShapes( SoSeparator*&shape_simple, SoSeparator*&shape_detailed); + void addMaterialEffectsToShapes( SoSeparator*&shape_simple, SoSeparator*&shape_detailed); + + void ensureInitSeps( SoSeparator*&shape_simple, SoSeparator*&shape_detailed); + SoTranslation* getZTranslationTube( const Trk::Surface *, const double& maxTrans ) const; + + Trk::MeasurementToSoNode m_measCnv; + TrkObjToString m_objToType; + HitToSoNode m_hitToSoNode; +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/AscObj_TruthPoint.h b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/AscObj_TruthPoint.h new file mode 100644 index 000000000..c487e2e60 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/AscObj_TruthPoint.h @@ -0,0 +1,47 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class AscObj_TruthPoint // +// // +// Description: Asc. Obj. handle for each truth point on a // +// truth track. // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: May 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef ASCOBJ_TRUTHPOINT_H +#define ASCOBJ_TRUTHPOINT_H + +#include "VTI12TrackSystems/AssociatedObjectHandleBase.h" + +namespace HepMC { class GenVertex; class GenParticle; } +class SimHitHandleBase; + +class AscObj_TruthPoint : public AssociatedObjectHandleBase { +public: + + AscObj_TruthPoint( TrackHandleBase*, const HepMC::GenVertex * v, const HepMC::GenParticle * p ); + AscObj_TruthPoint( TrackHandleBase*, SimHitHandleBase* ); + virtual ~AscObj_TruthPoint(); + + void buildShapes(SoSeparator*&shape_simple, SoSeparator*&shape_detailed); + QStringList clicked(); + +protected: + int regionIndex() const; + double lodCrossOverValue() const; + +private: + + class Imp; + Imp * m_d; + +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/AssociatedObjectHandleBase.h b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/AssociatedObjectHandleBase.h new file mode 100644 index 000000000..b645b1923 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/AssociatedObjectHandleBase.h @@ -0,0 +1,97 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class AssociatedObjectHandleBase // +// // +// Description: Handle for objects associated with tracks, // +// such as measurements, surfaces, etc. // +// It might provide just one object, or it // +// might alternatively be split into multiple // +// components (parts) // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: March 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef ASSOCIATEDOBJECTHANDLEBASE_H +#define ASSOCIATEDOBJECTHANDLEBASE_H + + +class TrackHandleBase; +class SoTransform; +class SoNode; +class SoSeparator; +class TrackSysCommonData; +class AssocObjAttachmentHandle; +#include <QStringList> + +class AssociatedObjectHandleBase { +public: + + static int numberOfInstances(); + + AssociatedObjectHandleBase(TrackHandleBase*);//The handle will register itself + //with the trackhandle, which will + //also take care of deleting it + //before moving to next event. + virtual QStringList clicked() = 0; + // virtual SoNode * getNodeForPart( int part ) const = 0; + virtual unsigned nParts() const { return 1; } + + TrackSysCommonData * common() const; + + enum PICKSTYLE { UNPICKABLE, ALL, COMPONENTS }; + void setPickable(PICKSTYLE); + PICKSTYLE pickStyle() const { return m_pickStyle; } + virtual void setVisible(bool); + bool visible() const { return m_visible; } + void toggleVisible() { setVisible(!m_visible); } + + TrackHandleBase* trackHandle() const { return m_trackHandle; } + void update3DObjects();//Call when settings changed affecting the shapes. + + //Return current shapes (0 if not built at the moment): + SoSeparator* shapeSimple() const; + SoSeparator* shapeDetailed() const; + + virtual bool initiatesOwnZooms() const { return false; } + +protected: + + virtual void buildShapes(SoSeparator*&shape_simple, SoSeparator*&shape_detailed) = 0; + //The returned SoSeparators should return all necessary transforms, + //and must optionally also include any necessary SoMaterial nodes + //(otherwise everything will get the track colour). + + //The next two are for LevelOfDetail. Probably return per detector type/station id? + virtual int regionIndex() const { return 0; }; + virtual double lodCrossOverValue() const { return 50*50; }; + +private: + + // It is illegal to copy/assign an AssociatedObjectHandleBase: + AssociatedObjectHandleBase( const AssociatedObjectHandleBase & ); + AssociatedObjectHandleBase & operator= ( const AssociatedObjectHandleBase & ); + + class Imp; + Imp * m_d; + + TrackHandleBase* m_trackHandle; + bool m_visible; + PICKSTYLE m_pickStyle; + void registerShapes(SoSeparator*simple,SoSeparator*detailed); + void unregisterShapes(SoSeparator*simple,SoSeparator*detailed); + AssocObjAttachmentHandle * getAttachmentHandle(); + +protected: + friend class TrackHandleBase; + virtual ~AssociatedObjectHandleBase();//The TrackHandleBase will delete it. + +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/MeasurementToSoNode.h b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/MeasurementToSoNode.h new file mode 100644 index 000000000..5ef77cd01 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/MeasurementToSoNode.h @@ -0,0 +1,137 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TRK_VP1TRACKSYSTEMS_MEASUREMENTTOSONODE_H +#define TRK_VP1TRACKSYSTEMS_MEASUREMENTTOSONODE_H +#include <vector> +#include <map> +#include <string> +#include "Identifier/Identifier.h" +#include "VTI12Utils/HitsSoNodeManager.h" +#include "VTI12TrackSystems/TrkObjToString.h" + +class SoNode; +class SoCube; +class SoTubs; +class SoSeparator; +class SoTransform; +class SoMaterial; + +// namespace InDet { +// class PixelCluster; +// class SCT_Cluster; +// class TRT_DriftCircle; +// } + +// namespace InDetDD { +// class SiDetectorElement; +// } +namespace ScintDD { + class ScintDetectorElement; +} + +namespace Trk { +// class LocalPosition; + class TrkDetElementBase; + class PrepRawData; + class RIO_OnTrack; + class CompetingRIOsOnTrack; + class PseudoMeasurementOnTrack; + class MeasurementBase; + + class MeasurementToSoNode { + public: + + enum ClusterDrawMode { SingleStrip=0, MultipleStrips=1, Errors=2 }; + + MeasurementToSoNode(); + + void initialize( ); + + /** This is the most general and most complete method - it returns a separator with nodes and transform. The material is not + added here as it should be at the top of the tree (in general) */ + std::pair<SoSeparator*, std::vector<SoNode*> > \ + createMeasSep( const Trk::MeasurementBase& meas); + + /** Returns a vector of SoNodes to represent the RIO_OnTrack. The cluster mode determines how the clusters are drawn - + i.e. as single central strip or the strips contributing to the cluster*/ + std::vector<SoNode*> toSoNodes( const Trk::RIO_OnTrack& prd); + + std::vector<SoNode*> toSoNodes( const Trk::CompetingRIOsOnTrack& crot); + + std::vector<SoNode*> toSoNodes( const Trk::PseudoMeasurementOnTrack& crot); + + // create basic shapes + + // SoNode* createPointMarker(); + SoNode* createLineMarker(double halfLength, bool isTube=false ); + + /** Generic routine which creates SoNode from passed detector element, plus measurement type*/ + SoNode* toSoNode(const Trk::TrkDetElementBase* baseDetEl, Identifier id, TrkObjToString::MeasurementType prdType, Amg::Vector2D locPos); + + //specific types + // SoNode* toSoNode(const InDetDD::SiDetectorElement* detElement, Identifier id, TrkObjToString::MeasurementType detType, Amg::Vector2D& locPos); + + void setClusterDrawMode (ClusterDrawMode mode); + ClusterDrawMode clusterDrawMode (); + + void setSimpleView( TrkObjToString::MeasurementType type, bool value ); + void setSimpleViewAll( bool value ); + bool isSimpleView( TrkObjToString::MeasurementType type ); + + /** Uses the local coords & the surface of the passed PRD to create a transform for the strip*/ + // SoTransform* createTransform( const Trk::PrepRawData& prd, + // MeasurementType detType); + + /** Uses the local coords & the surface of the passed Trk::MeasurementBase to create a transform for the strip*/ + SoTransform* createTransform( const Trk::MeasurementBase& rot, + TrkObjToString::MeasurementType detType); + + private: + std::vector<bool> m_simpleView; + double m_stripThickness; //!< Depth/Thickness of strips in z (local coords) + std::vector< SoMaterial* > m_materials; + + ClusterDrawMode m_clusDrawMode; + float m_dtLength; //!< Only used when in ShortMode + + HitsSoNodeManager m_nodeManager; + TrkObjToString m_objToType; + }; +} + +inline void +Trk::MeasurementToSoNode::setClusterDrawMode(Trk::MeasurementToSoNode::ClusterDrawMode mode) +{ + m_clusDrawMode=mode; +} + +inline Trk::MeasurementToSoNode::ClusterDrawMode +Trk::MeasurementToSoNode::clusterDrawMode() +{ + return m_clusDrawMode; +} + +inline void +Trk::MeasurementToSoNode::setSimpleView(TrkObjToString::MeasurementType type, bool value) +{ + m_simpleView[type]=value; +} + +inline void +Trk::MeasurementToSoNode::setSimpleViewAll( bool value) +{ + unsigned int end = static_cast<TrkObjToString::MeasurementType>(TrkObjToString::Unknown); + for (unsigned int i=0; i<end; ++i) m_simpleView[i]=value; +} + +inline bool +Trk::MeasurementToSoNode::isSimpleView(TrkObjToString::MeasurementType type) +{ + return m_simpleView[type]; +} + + +#endif + diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/SimBarCode.h b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/SimBarCode.h new file mode 100644 index 000000000..4435d2c5d --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/SimBarCode.h @@ -0,0 +1,58 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class SimBarCode // +// // +// Description: Identifier for truth particle // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: April 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef SIMBARCODE_H +#define SIMBARCODE_H + +#include "GeneratorObjects/HepMcParticleLink.h" + +class SimBarCode { +public: + + static const int unknownPDG = -999;//Fixme: Better choice? 0? + + SimBarCode(int barCode, HepMcParticleLink::index_type evtIndex, int pdgCode); + SimBarCode(const HepMcParticleLink&, int pdgCode); + ~SimBarCode(){} + + inline int barCode() const;//For non-unique secondaries, this will return a negative number, which should not be presented to the user. + inline int actualBarCode() const;//The original present in the simhit + inline HepMcParticleLink::index_type evtIndex() const; + inline int pdgCode() const; + inline bool unknownPdgCode() const { return m_pdgCode==unknownPDG; } + + inline bool isNonUniqueSecondary() const; + + //For sorting (Does consider pdgCodes, even when one is unknown): + inline bool operator<(const SimBarCode&) const; + + typedef std::pair<int,HepMcParticleLink::index_type> ExtBarCode; + ExtBarCode extBarCode() const { return ExtBarCode(barCode(),evtIndex()); } +// //Comparison operators do not consider pdgCodes if one of them is unknown! +// inline bool operator==(const SimBarCode&) const; +// inline bool operator!=(const SimBarCode&) const; + +private: + int m_barCode; + HepMcParticleLink::index_type m_evtIndex; + int m_pdgCode; +// inline bool pdgCodesCompatible(const SimBarCode&) const; +}; + + +#include "VTI12TrackSystems/SimBarCode.icc" + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/SimBarCode.icc b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/SimBarCode.icc new file mode 100644 index 000000000..82ccf4333 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/SimBarCode.icc @@ -0,0 +1,82 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Inline file for class SimBarCode // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: April 2008 // +// // +//////////////////////////////////////////////////////////////// + +//____________________________________________________________________ +inline SimBarCode::SimBarCode(int barCode, HepMcParticleLink::index_type evtIndex, int pdgCode) + : m_barCode(barCode), m_evtIndex(evtIndex), m_pdgCode(pdgCode) +{ +} + +//____________________________________________________________________ +inline SimBarCode::SimBarCode(const HepMcParticleLink& l, int pdgCode) + : m_barCode(l.barcode()), m_evtIndex(l.eventIndex()), m_pdgCode(pdgCode) +{ +} + +//____________________________________________________________________ +inline int SimBarCode::barCode() const +{ + return m_barCode; +} + +//____________________________________________________________________ +inline int SimBarCode::actualBarCode() const { + return m_barCode < 0 ? 0 : m_barCode; +} + +//____________________________________________________________________ +inline HepMcParticleLink::index_type SimBarCode::evtIndex() const +{ + return m_evtIndex; +} + +//____________________________________________________________________ +inline int SimBarCode::pdgCode() const +{ + return m_pdgCode; +} + +//____________________________________________________________________ +inline bool SimBarCode::isNonUniqueSecondary() const { + return m_barCode<=0; +} + +// //____________________________________________________________________ +// inline bool SimBarCode::pdgCodesCompatible(const SimBarCode& o) const +// { +// return m_pdgCode == o.m_pdgCode;//fixme +// // return m_pdgCode == o.m_pdgCode || m_pdgCode == unknownPDG || o.m_pdgCode == unknownPDG; +// } + +// //____________________________________________________________________ +// inline bool SimBarCode::operator==(const SimBarCode& o) const +// { +// if (m_barCode != o.m_barCode || m_evtIndex != o.m_evtIndex) +// return false; +// return pdgCodesCompatible(o); +// } + +// //____________________________________________________________________ +// inline bool SimBarCode::operator!=(const SimBarCode& o) const +// { +// return !(*this==o); +// } + +//____________________________________________________________________ +inline bool SimBarCode::operator<(const SimBarCode& o) const +{ + if (m_evtIndex == o.m_evtIndex) + return m_barCode == o.m_barCode ? m_pdgCode < o.m_pdgCode : m_barCode < o.m_barCode; + return m_evtIndex < o.m_evtIndex; +} diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/SimHitHandleBase.h b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/SimHitHandleBase.h new file mode 100644 index 000000000..9331c97fe --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/SimHitHandleBase.h @@ -0,0 +1,95 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for sim. hit. handle classes // +// // +// Description: Wrapper for simhits and track records // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: March 2008 // +// update: Feb 2014 - Ric Bianchi (rbianchi@cern.ch)// +// // +//////////////////////////////////////////////////////////////// + +#ifndef SIMHITHANDLEBASE_H +#define SIMHITHANDLEBASE_H + +#include "VTI12TrackSystems/SimBarCode.h" + +// Eigen migration +//#include "TrkEventPrimitives/GlobalMomentum.h" +//#include "TrkEventPrimitives/GlobalPosition.h" +#include "GeoPrimitives/GeoPrimitives.h" + +#include "GeneratorObjects/HepMcParticleLink.h" +#include "TrkParameters/TrackParameters.h" +#include <QString> +// typedef std::pair<int,HepMcParticleLink::index_type> ExtBarCode; + +class SimHitHandleBase { +public: + SimHitHandleBase() : m_trackPars(nullptr),m_pdgId(SimBarCode::unknownPDG), m_fakemom(-2), m_charge(-99999.0) {} + virtual ~SimHitHandleBase(){} + virtual QString type() const = 0; + + //Fixme: Evaluate which of the following we really need: + virtual Amg::Vector3D momentumDirection() const = 0; + virtual double actualMomentum() const { return -1; } + double momentum() const { return m_fakemom == -2 ? actualMomentum() : m_fakemom; } + virtual Amg::Vector3D posStart() const = 0; + virtual Amg::Vector3D posEnd() const = 0; + virtual double hitTime() const = 0; + + virtual const HepMcParticleLink& particleLink() const = 0; + int pdg() const; + SimBarCode simBarCode() const { return SimBarCode(particleLink(),pdg()); } + + bool hasCharge() const { return m_charge!=-99999.0; } + double charge() const { return m_charge; } +// static ExtBarCode extBarCode(const HepMcParticleLink& l) { return ExtBarCode( l.barcode(),l.eventIndex()); } +// inline ExtBarCode extBarCode() const { return extBarCode( particleLink() ); } + + virtual Trk::TrackParameters * createTrackParameters() const = 0; + + //FIXME: for TrackCollHandle_TruthTracks + void setFakeMomentum(const double& m ) { m_fakemom = m; } + void setCharge(const double& c ) { m_charge = c; } + void cacheMomentum() { if (m_fakemom==-2) m_fakemom = actualMomentum(); } + +protected: + virtual int actualPDGCodeFromSimHit() const { return SimBarCode::unknownPDG; }; + +private: + // It is illegal to copy/assign a SimHitHandleBase: + SimHitHandleBase( const SimHitHandleBase & ); + SimHitHandleBase & operator= ( const SimHitHandleBase & ); + mutable Trk::TrackParameters * m_trackPars; + int m_pdgId; + void setPDG(int);//For TrackCollHandle_TruthTracks in case actualPDGCodeFromSimHit() returns SimBarCode::unknownPDG; + double m_fakemom; + double m_charge; + friend class TrackCollHandle_TruthTracks; + friend class TrackCollHandle_SimulationTracks; +}; + +typedef std::vector<std::pair<double,SimHitHandleBase*> > SimHitList;//hitTime() to SimHitHandle's + +/////////////// +// Inlines // +/////////////// + +inline int SimHitHandleBase::pdg() const +{ + return m_pdgId; +} + +inline void SimHitHandleBase::setPDG(int pdg) +{ + m_pdgId = pdg; +} + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/SimHitHandle_ScintHit.h b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/SimHitHandle_ScintHit.h new file mode 100644 index 000000000..36b75c49c --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/SimHitHandle_ScintHit.h @@ -0,0 +1,50 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class SimHitHandle_SiHit // +// // +// Description: Handle for SiHit's // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: March 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef SIMHITHANDLE_SIHIT_H +#define SIMHITHANDLE_SIHIT_H + +#include "VTI12TrackSystems/SimHitHandleBase.h" + +#include "GeoPrimitives/GeoPrimitives.h" +#include "TrkParameters/TrackParameters.h" + +class ScintHit; +class SimHitHandle_ScintHit : public SimHitHandleBase { +public: + + SimHitHandle_ScintHit( const ScintHit * ); + virtual ~SimHitHandle_ScintHit(); + + QString type() const { return "ScintHit"; }; + + Amg::Vector3D momentumDirection() const; + Amg::Vector3D posStart() const; + Amg::Vector3D posEnd() const; + double hitTime() const; + + const HepMcParticleLink& particleLink() const; + + Trk::TrackParameters * createTrackParameters() const; + +private: + + class Imp; + Imp * m_d; + +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/SimHitHandle_TrackRecord.h b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/SimHitHandle_TrackRecord.h new file mode 100644 index 000000000..34f2247fc --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/SimHitHandle_TrackRecord.h @@ -0,0 +1,92 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class SimHitHandle_TrackRecord // +// // +// Description: Handle for Track Records // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: May 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef SIMHITHANDLE_TRACKRECORD_H +#define SIMHITHANDLE_TRACKRECORD_H + +#include "VTI12TrackSystems/SimHitHandleBase.h" +#include "TrackRecord/TrackRecord.h" +#include "GeoPrimitives/CLHEPtoEigenConverter.h" + + +class TrackRecord; +class HepMcParticleLink; + +class SimHitHandle_TrackRecord : public SimHitHandleBase { +public: + + SimHitHandle_TrackRecord(const TrackRecord*); + virtual ~SimHitHandle_TrackRecord(); + + QString type() const { return "TrackRecord"; }; + + Amg::Vector3D momentumDirection() const; + double actualMomentum() const; + Amg::Vector3D posStart() const; + Amg::Vector3D posEnd() const;//We fake this one as a point 0.1mm away from posStart, in the momentumDirection. + double hitTime() const; + int actualPDGCodeFromSimHit() const; + const HepMcParticleLink& particleLink() const; + Trk::TrackParameters * createTrackParameters() const; + +private: + + TrackRecord* m_trkrecord;//We keep this as non-const pointers due to wrong constness in TrackRecord methods!! + double m_mom; + Amg::Vector3D m_momdir; + const HepMcParticleLink* m_link; +}; + +/////////////// +// Inlines // +/////////////// + +inline Amg::Vector3D SimHitHandle_TrackRecord::momentumDirection() const +{ + return m_momdir; +} + +inline double SimHitHandle_TrackRecord::actualMomentum() const +{ + return m_mom; +} + +inline Amg::Vector3D SimHitHandle_TrackRecord::posStart() const +{ + return Amg::Hep3VectorToEigen(m_trkrecord->GetPosition()); +} + +inline Amg::Vector3D SimHitHandle_TrackRecord::posEnd() const +{ + return posStart() + 0.1*CLHEP::mm*(momentumDirection());//faking it... but shouldn't matter. +} + +inline double SimHitHandle_TrackRecord::hitTime() const +{ + return m_trkrecord->GetTime(); +} + +inline int SimHitHandle_TrackRecord::actualPDGCodeFromSimHit() const +{ + return m_trkrecord->GetPDGCode(); +} + +inline const HepMcParticleLink& SimHitHandle_TrackRecord::particleLink() const +{ + return *m_link; +} + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandleBase.h b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandleBase.h new file mode 100644 index 000000000..24bd5b39a --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandleBase.h @@ -0,0 +1,264 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class TrackCollHandleBase // +// // +// Description: Base class for collection handles // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: February 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef TRACKCOLLHANDLEBASE_H +#define TRACKCOLLHANDLEBASE_H + +#include "VTI12TrackSystems/TrackTypes.h" +#include "VTI12TrackSystems/TrackCommonFlags.h" +#include "VTI12TrackSystems/TrackSysCommonData.h"//Not strictly needed + //here, but since all + //derived classes will + //need it we put it + //here. +#include "VP1Base/VP1Interval.h" +#include "VP1Base/VP1QtUtils.h" +#include "VTI12TrackSystems/TrackSystemController.h" +#include <QColor> +#include <iostream> + + +class TrackSystemController; +class TrackHandleBase; +class SoSeparator; +class SoMaterial; +class VP1ExtraSepLayerHelper; +class TrackSysCommonData; +namespace Trk { + class Track; + class Segment; + class IExtrapolator; +} + +#include "VP1Base/VP1StdCollection.h" + +class TrackCollHandleBase : public VP1StdCollection +{ + + Q_OBJECT + +public: + + //Each derived class should implement a "static QStringList + //availableCollections();" method, which the collection widget will + //use to determine the available collections. + + TrackCollHandleBase(TrackSysCommonData *, + const QString& name, + TrackType::Type); + virtual void init(VP1MaterialButtonBase* matBut=0);//reimplementations must start with a call to this. + virtual ~TrackCollHandleBase(); + + //Called just after creation. Should set current cut values and + //connections with controller to monitor future changes. Reimplement + //the ..Specific method to setup subsystem specific settings. + void setupSettingsFromController(TrackSystemController*); +protected: + virtual void setupSettingsFromControllerSpecific(TrackSystemController*) {}; +public: + + /////////////////////////////////////////////////////////// + // For loading the data and resetting after each event: // + /////////////////////////////////////////////////////////// + + //For use by the handles: + QString name() const; + TrackSysCommonData * common() const { return m_commonData; } + // + VP1ExtraSepLayerHelper * sephelper() const { return m_sephelper; }//For attaching/detaching. FIXME: TO BASE!! + + virtual bool canUsePropagator() { return true; } + + double trackTubeRadius() const { return m_trackTubeRadius; } + + virtual bool mightHaveSubSystemHitInfo() const { return false; } + + virtual QByteArray persistifiableState() const;//!<Provide specific implementation + virtual void setState(const QByteArray&);//!<Provide specific implementation + +protected: + + //Must be called from derived classes when filling in new track handles. + void hintNumberOfTracksInEvent(unsigned); + void addTrackHandle(TrackHandleBase*); + + //For iterating over track handles: + void trackHandleIterationBegin(); + TrackHandleBase* getNextTrackHandle(); //Returns 0 when done. + + //Override if special cuts. Remember to call base class implementation also for common cuts. + virtual bool cut(TrackHandleBase*);//Return true if should be shown (based on various cuts), false otherwise. + + //Utility (fixme: put in utility class elsewhere). + template <class T> void cleanupPtrContainer(T&) const;//Delete pointers and calls .clear() + // template <class T> void cleanupNodeContainer(T&) const;//unref's pointers and calls .clear() + + void recheckCutStatus(TrackHandleBase*);//Call in derived classes for handles that might be effected by a change in cuts. + + //Convenience methods which can be called from derived classes or + //the trackcollwidget (but specialised procedures might be more + //optimal) +public: + void recheckCutStatusOfAllVisibleHandles(); + void recheckCutStatusOfAllNotVisibleHandles(); + void recheckCutStatusOfAllHandles(); + void update3DObjectsOfAllHandles(bool invalidatePropagatedPoints = false, float maxR = 0.0 ); // maxR being set will override the prop max value from the controller, e.g. for animations + void updateMaterialOfAllHandles(); + void updateInDetProjectionsOfAllHandles(); + void updateMuonProjectionsOfAllHandles(); + + int nShownHandles() { return m_nshownhandles; } + //For use only by TrackHandleBase::setVisible(..): + void incrementNShownHandles() { ++m_nshownhandles; } + void decrementNShownHandles() { --m_nshownhandles; } + + virtual bool mayHaveAssociatedObjects() const { return false; } + + // FIXME - really not sure any of the prop stuff belongs here. Property of commondata/controller, not coll handle. EJWM + Trk::IExtrapolator * propagator() const { return m_propagator; } + TrackSystemController::PropagationOptionFlags propagationOptions() { return m_propagationOptions; } + + bool ignoreMEOTinProp() const { return m_propagationOptions.testFlag(TrackSystemController::IgnoreMEOT); } + bool extendTracks() const { return m_propagationOptions.testFlag(TrackSystemController::ExtendTrack); } + TrackCommonFlags::TrackPartsFlags parts() const { return m_parts; } + + enum COLOURBY { COLOUR_PERCOLLECTION, COLOUR_RANDOM, COLOUR_BYPID, COLOUR_MOMENTUM, COLOUR_CHARGE, COLOUR_DISTANCE, COLOUR_VERTEX }; + static QString toString(const COLOURBY&); + + COLOURBY colourBy() const { return m_colourby; } + + virtual COLOURBY defaultColourBy () const { return COLOUR_PERCOLLECTION; } + virtual bool allowColourByPID() const { return false; } + virtual bool allowColourByMomentum() const { return true; } + virtual bool allowColourByCharge() const { return true; } + virtual bool allowColourByDistanceFromSelectedTrack() const {return VP1QtUtils::environmentVariableIsOn("VP1_TRKSYS_COLOURBYDIST"); } + virtual bool allowColourByVertex() const { return false; } + virtual void collMaterialTransparencyAndBrightnessChanged(); + + // Cuts + bool useDefaultCuts() const; //!< Return true if this collection uses the default (i.e. controller) cuts + bool cutOnlyVertexAssocTracks() const; //!< Return true if this collection should only should tracks associated to a vertex + //General cuts: + VP1Interval cutAllowedPt() const; + VP1Interval cutAllowedEta() const; + QList<VP1Interval> cutAllowedPhi() const;//All off: empty list. All on: list with one entry: ]-inf,inf[ + //Cuts for number of hits per subsystem: + QList<unsigned> cutRequiredNHits() const;//Empty list: no requirements. Otherwise a list + // with a length of four (pixel,sct,trt,muon) + + void vertexCutsAllowed(bool); // called if vertex system is available. + //Truth cuts: + bool cutTruthFromIROnly() const; + bool cutExcludeBarcodeZero() const; + bool cutTruthExcludeNeutrals() const; + +protected: + + qint32 provideCollTypeID() const; + virtual QString provideSection() const { return TrackType::typeToSectionHeader(m_type); };//FIXME + virtual QString provideSectionToolTip() const { return TrackType::typeToSectionHeaderToolTip(m_type); };//FIXME + virtual QString provideText() const { return name(); };//FIXME + virtual void assignDefaultMaterial(SoMaterial*) const; + virtual QColor defaultColor() const = 0;//Will be used in assignDefaultMaterial + QList<QWidget*> provideExtraWidgetsForGuiRow() const; + QByteArray extraWidgetsState() const; + void setExtraWidgetsState(const QByteArray&); +private slots: + void colourByComboBoxItemChanged(); +public slots: + void rerandomiseRandomTrackColours(); + void trackSelectionChanged(); + void setShownTSOSParts(TrackCommonFlags::TSOSPartsFlags); + void setLabels(TrackSystemController::TrackLabelModes); + void setLabelTrkOffset(float); + void setLabelPosOffsets(QList<int>); + void setCustomColouredTSOSParts(TrackCommonFlags::TSOSPartsFlags); + void setUseShortTRTMeasurements(bool); + void setUseShortMDTMeasurements(bool); + void setDrawMeasGlobalPositions(bool); + void setMeasurementsShorttubesScale(double); + void setNStdDevForParamErrors(const double&); + void setNumberOfPointsOnCircles(int); + void setMaterialEffectsOnTrackScale(double); + void setParTubeErrorsDrawCylinders(bool); + void setRequiredNHits(const QList<unsigned>&); + void setOnlyVertexAssocTracks(bool); + void extrapolateToThisVolumeChanged(void); + void clipVolumeChanged(double); +private: + + class Imp; + Imp * m_d; + + int m_nshownhandles; + TrackType::Type m_type; + TrackSysCommonData * m_commonData; + + VP1ExtraSepLayerHelper * m_sephelper; + Trk::IExtrapolator * m_propagator; + TrackSystemController::PropagationOptionFlags m_propagationOptions; + float m_propMaxRadius; + TrackCommonFlags::TrackPartsFlags m_parts; + TrackSystemController::TrackLabelModes m_labels; + float m_labelsTrkOffset; + QList<int> m_labelsPosOffsets; + double m_trackTubeRadius; + COLOURBY m_colourby; + + VP1Interval m_cut_allowedPtSq;//We store the allowed interval for pt squared - to avoid sqrt's. + VP1Interval m_cut_allowedEta; + QList<VP1Interval> m_cut_allowedPhi; + QList<unsigned> m_cut_requiredNHits; + bool m_cut_pt_allowall; + bool m_cut_eta_allowall; + bool m_cut_phi_allowall; + bool m_cut_etaptphi_allwillfail; + void actualSetShownTSOSPartsOnHandles(); + void actualSetCustomColouredTSOSPartsOnHandles(); + void fillObjectBrowser(); + void updateObjectBrowserVisibilityCounts(); + +private slots: + void collVisibilityChanged(bool); + void setPropagator(Trk::IExtrapolator *); + void setPropagationOptions(TrackSystemController::PropagationOptionFlags); + void setPropMaxRadius(float); + void setParts(TrackCommonFlags::TrackPartsFlags); + void setParts(int); + void setTrackTubeRadius(const double&); + void setColourBy(COLOURBY); + void setUseDefaultCuts(bool); + void setCutAllowedPt(const VP1Interval&); + void setCutAllowedEta(const VP1Interval&); + void setCutAllowedPhi(const QList<VP1Interval>&); + void setActualPathShown(bool); + +}; + +//Fixme: Move elsewhere: +template <class T> void TrackCollHandleBase::cleanupPtrContainer(T&t) const +{ + typename T::iterator it(t.begin()), itE(t.end()); + for (;it!=itE;++it) + delete *it; + t.clear(); +} + +#endif + + + + diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandle_FatrasTruthTracks.h_toBeFixed b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandle_FatrasTruthTracks.h_toBeFixed new file mode 100644 index 000000000..5c4a75ffa --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandle_FatrasTruthTracks.h_toBeFixed @@ -0,0 +1,39 @@ + +//////////////////////////////////////////////////////////////// +// // +// Header file for class TrackCollHandle_FatrasTruthTracks // +// // +// Description: Specialisation of TrkTracks which contains // +// Fatras truth information // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: March 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef TRACKCOLLHANDLE_FATRASTRUTHTRACKS_H +#define TRACKCOLLHANDLE_FATRASTRUTHTRACKS_H + +#include "VP1TrackSystems/TrackCollHandle_TrkTrack.h" + +class TrackCollHandle_FatrasTruthTracks : public TrackCollHandle_TrkTrack { + + Q_OBJECT + +public: + + static QStringList availableCollections(IVP1System*);//For the collection widget. + + TrackCollHandle_FatrasTruthTracks(TrackSysCommonData *, + const QString& name); + virtual ~TrackCollHandle_FatrasTruthTracks() {} + +protected: + virtual bool allowColourByPID() const { return true; } + virtual COLOURBY defaultColourBy () const { return COLOUR_BYPID; } + virtual bool load(); + virtual QColor defaultColor() const { return QColor::fromRgbF(1.0f, 1.0f, 0.0f); } + +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandle_RefittedTracks.h b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandle_RefittedTracks.h new file mode 100644 index 000000000..be03ccbdb --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandle_RefittedTracks.h @@ -0,0 +1,46 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class TrackCollHandle_RefittedTracks // +// // +// Description: Specialisation of TrkTracks which contains // +// Fatras truth information // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: September 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef TRACKCOLLHANDLE_REFITTEDTRACKS_H +#define TRACKCOLLHANDLE_REFITTEDTRACKS_H + +#include "VTI12TrackSystems/TrackCollHandle_TrkTrack.h" +#include <QList> + +class TrackCollHandle_RefittedTracks : public TrackCollHandle_TrkTrack { + + Q_OBJECT + +public: + + TrackCollHandle_RefittedTracks( TrackSysCommonData *, + const QString& name, + QList<const Trk::Track*> fittedtracks ); + virtual ~TrackCollHandle_RefittedTracks(); + +protected: + virtual bool load(); + virtual QColor defaultColor() const { return QColor::fromRgbF(0.0f, 1.0f, 1.0f); } + +private: + + class Imp; + Imp * m_d; + +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandle_TrackParticle.hSave b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandle_TrackParticle.hSave new file mode 100644 index 000000000..ed6269601 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandle_TrackParticle.hSave @@ -0,0 +1,47 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class TrackCollHandle_TrackParticle // +// // +// Description: Collection handle for track particles // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: May 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef TRACKCOLLHANDLE_TRACKPARTICLE_H +#define TRACKCOLLHANDLE_TRACKPARTICLE_H + +#include "VTI12TrackSystems/TrackCollHandleBase.h" + +class TrackCollHandle_TrackParticle : public TrackCollHandleBase { + + Q_OBJECT + +public: + + static QStringList availableCollections(IVP1System*);//For the collection widget. + + TrackCollHandle_TrackParticle( TrackSysCommonData *, + const QString& name ); + virtual ~TrackCollHandle_TrackParticle(); + +protected: + virtual bool load(); + virtual bool cut(TrackHandleBase*); + virtual QColor defaultColor() const { return QColor::fromRgbF(1.0f, 1.0f, 0.5f); } + bool mightHaveSubSystemHitInfo() const { return true; } + +private: + + class Imp; + Imp * m_d; + +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandle_TrkSegment.hSave b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandle_TrkSegment.hSave new file mode 100644 index 000000000..26ede8280 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandle_TrkSegment.hSave @@ -0,0 +1,56 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class TrackCollHandle_TrkSegment // +// // +// Description: fixme // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: February 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef TRACKCOLLHANDLE_TRKSEGMENT_H +#define TRACKCOLLHANDLE_TRKSEGMENT_H + +#include "VTI12TrackSystems/TrackCollHandleBase.h" +#include <QStringList> + +class TrackHandle_TrkSegment; + +class TrackCollHandle_TrkSegment : public TrackCollHandleBase { + + Q_OBJECT + +public: + + static QStringList availableCollections(IVP1System*);//For the collection widget. + + TrackCollHandle_TrkSegment(TrackSysCommonData *, + const QString& name); + virtual ~TrackCollHandle_TrkSegment(); + + void setupSettingsFromControllerSpecific(TrackSystemController*); + + void visibleStateUpdated(TrackHandle_TrkSegment*);//Must be called whenever visibility/material of handle changes. + bool mightHaveSubSystemHitInfo() const { return true; } + +protected: + bool load(); + bool cut(TrackHandleBase*); + virtual QColor defaultColor() const { return QColor::fromRgbF(0.75f, 0.39f, 1.0f ); } + virtual bool allowColourByMomentum() const { return false; } + virtual bool allowColourByCharge() const { return false; } + +private: + + class Imp; + Imp * m_d; + +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandle_TrkTrack.h b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandle_TrkTrack.h new file mode 100644 index 000000000..f35919db1 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandle_TrkTrack.h @@ -0,0 +1,60 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class TrackCollHandle_TrkTrack // +// // +// Description: Collection handle for Trk::Tracks. // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: February 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef TRACKCOLLHANDLE_TRKTRACK_H +#define TRACKCOLLHANDLE_TRKTRACK_H + +#include "VTI12TrackSystems/TrackCollHandleBase.h" +#include "VTI12TrackSystems/TrackCommonFlags.h" +#include <QStringList> +#include <iostream> + +class TrackHandle_TrkTrack; +namespace Trk { class Track; } +class TrackCollHandle_TrkTrack : public TrackCollHandleBase { + + Q_OBJECT + +public: + + static QStringList availableCollections(IVP1System*);//For the collection widget. + + TrackCollHandle_TrkTrack(TrackSysCommonData *, + const QString& name, + TrackType::Type type = TrackType::TrkTrack); + virtual ~TrackCollHandle_TrkTrack(); + + //NB: All overridden methods should be virtual since + //TrackCollHandle_FatrasTruthTracks inherits from this. + virtual void setupSettingsFromControllerSpecific(TrackSystemController*); + virtual bool allowColourByVertex() const { return true;} + + void visibleStateUpdated(TrackHandle_TrkTrack*);//Must be called whenever visibility/material of handle changes. + bool mightHaveSubSystemHitInfo() const { return true; } + +protected: + virtual bool load(); + virtual bool cut(TrackHandleBase*); + virtual QColor defaultColor() const { return QColor::fromRgbF(1.0f, 0.666667f, 0.0f); } + +private: + + class Imp; + Imp * m_d; + +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandle_TruthTracks.h b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandle_TruthTracks.h new file mode 100644 index 000000000..60c9d0d51 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandle_TruthTracks.h @@ -0,0 +1,59 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class TrackCollHandle_TruthTracks // +// // +// Description: Collection handle for HepMC/simhit based // +// truth tracks // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: March 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef TRACKCOLLHANDLE_TRUTHTRACKS_H +#define TRACKCOLLHANDLE_TRUTHTRACKS_H + +#include "VTI12TrackSystems/TrackCollHandleBase.h" + +class SimHitHandleBase; + +class TrackCollHandle_TruthTracks : public TrackCollHandleBase { + + Q_OBJECT + +public: + + static QStringList availableCollections(IVP1System*);//For the collection widget. + + TrackCollHandle_TruthTracks(TrackSysCommonData *, + const QString& name); + virtual ~TrackCollHandle_TruthTracks(); + + virtual void setupSettingsFromControllerSpecific(TrackSystemController*); + +protected: + virtual COLOURBY defaultColourBy () const { return COLOUR_BYPID; } + virtual bool allowColourByPID() const { return true; } + virtual bool load(); + virtual bool cut(TrackHandleBase*); + virtual QColor defaultColor() const { return QColor::fromRgbF(0.42f, 0.96f, 0.16f); } + +private slots: + void setCutFromIROnly(bool); + void setCutExcludeBarcodeZero(bool); + void setCutExcludeNeutrals(bool); + void setShowAscObjs(bool); + +private: + + class Imp; + Imp * m_d; + void fixPDGCode(SimHitHandleBase*) const; +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandle_xAODTrackParticle.hSave b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandle_xAODTrackParticle.hSave new file mode 100644 index 000000000..677fcba3e --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollHandle_xAODTrackParticle.hSave @@ -0,0 +1,45 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +//////////////////////////////////////////////////////////////// + +// // +// Header file for class TrackCollHandle_TrackParticle // +// // +// Description: Collection handle for track particles // +// // +// // +//////////////////////////////////////////////////////////////// + +#ifndef TRACKCOLLHANDLE_XAODTRACKPARTICLE_H +#define TRACKCOLLHANDLE_XAODTRACKPARTICLE_H + +#include "VTI12TrackSystems/TrackCollHandleBase.h" + +class TrackCollHandle_xAODTrackParticle : public TrackCollHandleBase { + + Q_OBJECT + +public: + + static QStringList availableCollections(IVP1System*);//For the collection widget. + + TrackCollHandle_xAODTrackParticle( TrackSysCommonData *, + const QString& name ); + virtual ~TrackCollHandle_xAODTrackParticle(); + +protected: + virtual bool load(); + virtual bool cut(TrackHandleBase*); + virtual QColor defaultColor() const { return QColor::fromRgbF(1.0f, 1.0f, 0.5f); } + bool mightHaveSubSystemHitInfo() const { return true; } + +private: + + class Imp; + Imp * m_d; + +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollWidget.h b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollWidget.h new file mode 100644 index 000000000..e8b2b14e6 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollWidget.h @@ -0,0 +1,42 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class TrackCollWidget // +// // +// Description: Collection widget. Specialisation which // +// imposes desired section ordering. // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: February 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef TRACKCOLLWIDGET_H +#define TRACKCOLLWIDGET_H + +#include "VP1Base/VP1CollectionWidget.h" + +class TrackCollWidget : public VP1CollectionWidget { + + Q_OBJECT + +public: + + TrackCollWidget(QWidget * parent = 0) : VP1CollectionWidget(parent) {} + virtual ~TrackCollWidget(){} + +protected: + + void sortSections(QList<QString>&); + +private: + class Imp; + +}; + + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollectionSettingsButton.h b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollectionSettingsButton.h new file mode 100644 index 000000000..79f8ad3e3 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCollectionSettingsButton.h @@ -0,0 +1,108 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TRACKCOLLSETTINGSBUTTON_H +#define TRACKCOLLSETTINGSBUTTON_H + +#include "VP1Base/VP1MaterialButton.h" + +class SoDrawStyle; +class SoLightModel; + +class TrackCollectionSettingsButton : public VP1MaterialButtonBase { + + Q_OBJECT + +public: + + TrackCollectionSettingsButton(QWidget * parent = 0, int dim = 25);//dim<=0 => Won't change sizepolicy + virtual ~TrackCollectionSettingsButton(); + + void setDimension(int dim); + + // The below are necessary to fulfill the interface, but will just be passed onto the VP1MaterialButton owned by the TrackCollectionSettingsButton form + virtual bool setMaterial(SoMaterial*); + virtual void copyValuesFromMaterial(SoMaterial*); + virtual double lastAppliedTransparency() const ; + virtual double lastAppliedShininess() const ; + virtual double lastAppliedBrightness() const; + + // GUI for track lines... + double trackTubeRadius() const;//0 => don't show tubes for tracks + bool hideActualTrackPath() const; + + // GUI for cuts + bool useDefaultCuts() const; + bool cutOnlyVertexAssocTracks() const; //!< Return true if this collection should only should tracks associated to a vertex + VP1Interval cutAllowedPt() const; + VP1Interval cutAllowedEta() const; + QList<VP1Interval> cutAllowedPhi() const;//All off: empty list. All on: list with one entry: ]-inf,inf[ + //Cuts for number of hits per subsystem: + QList<unsigned> cutRequiredNHits() const;//Empty list: no requirements. Otherwise a list + // with a length of four (pixel,sct,trt,muon) + //Truth cuts: + bool cutTruthFromIROnly() const; + bool cutExcludeBarcodeZero() const; + bool cutTruthExcludeNeutrals() const; + + //Overall drawstyles, complexities and light models: + SoDrawStyle * trackDrawStyle() const; + SoLightModel * trackLightModel() const; + + QByteArray saveState() const; //!< fill out with the state of the object (used for drag and drop etc) + void restoreFromState( const QByteArray& ); + + signals: + void trackTubeRadiusChanged(const double&); + void lastAppliedChanged(); // emitted when something related to material changes + void hideActualTrackPathChanged(bool); + + void useDefaultCutsChanged(bool); + void cutAllowedPtChanged(const VP1Interval&); + void cutAllowedEtaChanged(const VP1Interval&); + void cutAllowedPhiChanged(const QList<VP1Interval>&); + void cutRequiredNHitsChanged(const QList<unsigned>&); + void cutTruthFromIROnlyChanged(bool); + void cutExcludeBarcodeZeroChanged(bool); + void cutTruthExcludeNeutralsChanged(bool); + void cutOnlyVertexAssocTracksChanged(bool); + + public slots: + void showEditMaterialDialog(); + void setText(const QString&); + + protected slots: + void updateButton(); + + protected: + // void initEditWindow();//!< Make sure that edit window is constructed + void mousePressEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void dropEvent(QDropEvent *event); + void dragEnterEvent(QDragEnterEvent *event); + private: + + class Imp; + Imp * m_d; + + private slots: + void updateTrackDrawStyle(); + void updateTrackLightModel(bool); + void updateTrackTubeRadius(); + void updateHideActualTrackPath(bool); + void possibleChange_useDefaultCuts(); + void possibleChange_cutAllowedPt(); + void possibleChange_cutAllowedEta(); + void possibleChange_cutAllowedPhi(); + void possibleChange_cutRequiredNHits(); + void possibleChange_cutTruthFromIROnly(); + void possibleChange_cutExcludeBarcodeZero(); + void possibleChange_cutTruthExcludeNeutrals(); + void possibleChange_cutOnlyVertexAssocTracks(); + +}; + +#endif + + diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCommonFlags.h b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCommonFlags.h new file mode 100644 index 000000000..a5e7a0ee9 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackCommonFlags.h @@ -0,0 +1,79 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +//////////////////////////////////////////////////////////////// +// // +// Various flags - put here to avoid the need to include // +// other header files just for the flags // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: March 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef TRACKCOMMONFLAGS_H +#define TRACKCOMMONFLAGS_H + +#include <QFlags> +#include <QString> + +class TrackCommonFlags { +public: + + enum TrackPartsFlag { + NoParts = 0x0000, + ActualPath = 0x0001, + InDetProjections = 0x0002, + MuonProjections = 0x0004, + VertexProjections = 0x0008 + }; + Q_DECLARE_FLAGS(TrackPartsFlags, TrackPartsFlag) + + enum SELECTIONMODE { SINGLEOBJECT, MULTITRACK, TRACKFIT }; + static QString toString(const SELECTIONMODE&); + + enum FITTERMODE { FROMPRDS, REFITSINGLETRACK, EXTENDTRACKWITHPRDS,COMBINETWOTRACKS }; + static QString toString(const FITTERMODE&); + + enum DETAILLEVEL { SIMPLE, DETAILED, AUTO }; + static QString toString(const DETAILLEVEL& ); + + enum TSOSPartsFlag { + TSOS_NoObjects = 0x0000, + TSOS_TrackPars = 0x0001, //!< bit 0 + TSOS_TrackParsErrorsNotPerigee = 0x0002, //!< bit 1 + TSOS_TrackParsErrorsPerigee = 0x0004, //!< bit 2 + TSOS_MeasError = 0x008, //!< bit 3 + TSOS_MeasRioOnTrackNotOutlier = 0x0010, //!< bit 4 + TSOS_MeasCompetingRioOnTrackNotOutlier = 0x0020, //!< bit 5 + TSOS_MeasRioOnTrackOutlier = 0x0040,//!< bit 6 + TSOS_MeasCompetingRioOnTrackOutlier = 0x0080,//!< bit 7 + TSOS_SurfacesDetElem = 0x0100, //!< bit 9 + TSOS_SurfacesCustom = 0x0200, //!< bit 10 + TSOS_TubeSurfaces = 0x0400, //!< bit 11 + TSOS_MaterialEffectsWithNoDeltaE = 0x1000, //!< bit 12 + TSOS_MaterialEffects = 0x2000,//!< bit 13 + TSOS_Hole = 0x4000,//!< bit 14 + //Convenience + TSOS_AnyMaterialEffects = 0x3000, + TSOS_AnySurface = 0x0700, + TSOS_AnyMeasurement = 0x00F0, + TSOS_AnyMeasurementNotOutlier = 0x0030, + TSOS_AnyMeasurementOutlier = 0x00C0, + TSOS_AnyMeasRioOnTrack = 0x0050, + TSOS_AnyMeasCompetingRioOnTrack = 0x00A0, + TSOS_AnyParsErrors = 0x0006, + TSOS_AnyErrors = 0x10FE + }; + Q_DECLARE_FLAGS(TSOSPartsFlags, TSOSPartsFlag) + +private: + TrackCommonFlags(); + ~TrackCommonFlags(); +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(TrackCommonFlags::TrackPartsFlags) +Q_DECLARE_OPERATORS_FOR_FLAGS(TrackCommonFlags::TSOSPartsFlags) + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackHandleBase.h b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackHandleBase.h new file mode 100644 index 000000000..bd8e9905e --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackHandleBase.h @@ -0,0 +1,208 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class TrackHandleBase // +// // +// Description: Base class for track handles. // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: February 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef TRACKHANDLEBASE_H +#define TRACKHANDLEBASE_H + +#include "VTI12TrackSystems/TrackCommonFlags.h" + +#include "TrkEventPrimitives/ParticleHypothesis.h" +#include "GeoModelKernel/GeoPVConstLink.h" + +//#include "CLHEP/Geometry/Point3D.h" +#include "GeoPrimitives/GeoPrimitives.h" + +#include <QStringList> +#include <QTreeWidgetItem> +#include <vector> +#include <set> +#include <QList> +#include <QFlags> + + +class AssocObjAttachmentHandle; +class AssociatedObjectHandleBase; +class TrackCollHandleBase; +class TrackSysCommonData; +class SoMaterial; +class SoNode; +class TrackLODHandle; + +namespace Trk { + class Track; + class FitQuality; +} + +class TrackHandleBase { +public: + + static int numberOfInstances(); + + TrackHandleBase(TrackCollHandleBase*); + virtual ~TrackHandleBase(); + + TrackSysCommonData * common() const; + + void setVisible(bool);//!< use by the collection handle. + bool visible() const { return m_visible; } + TrackCollHandleBase * collHandle() const { return m_collhandle; } + const std::set<GeoPVConstLink>& touchedMuonChambers() const; + void update3DObjects(bool invalidatePropagatedPoints = false, float maxR=0.0); + // void updateInDetProjections(); + // void updateMuonProjections(); + void updateMaterial(); + void rerandomiseRandomMaterial(); + void updateRandomColourTransparencyAndBrightness(); + SoMaterial * currentMaterial() const { return m_currentmaterial; } + + QStringList baseInfo() const; + /** Called when user selects the node (stringlist is displayed in messagebox). + Reimplementations should add info momInfo() to get momentum, eta, phi, pid,charge, mass printed.*/ + virtual QStringList clicked() const = 0; + + virtual Amg::Vector3D momentum() const { return Amg::Vector3D(0,0,0); } + virtual const Amg::Vector3D * startPoint() const;//!< returns 0 if can't find start point. + virtual const Amg::Vector3D * endPoint() const;//!< returns 0 if can't find start point. + virtual int pdgCode() const { return 0; }//!< 0 means unknown + + //Default implementation of the following two methods will based on + //pdgCode(). In the case of charge(), if it can't be determined + //based on pdgCode(), and attempt will be made by looking at the + //first track parameters charge (if a Trk::Track is + //provided). Override in case the charge/mass can be determined, but + //the pdg code not. (or if there is a faster way to get the charge than by constructing the Trk::Track first). + // + //NB: update: it is the calculateCharge() method which must be reimplemented for the charge! + double charge() const;//Returns unknown() in case of trouble. + virtual double mass() const;//Returns unknown() in case of trouble. + + bool hasCharge() const { return charge()!=unknown(); } + bool hasMass() const { return mass()!=unknown(); } + + static double unknown() { return -999.0; } + + virtual bool hasSubSystemHitInfo() const { return false; } + // virtual unsigned getNVetoHits() const { return 0; } + // virtual unsigned getNTriggerHits() const { return 0; } + // virtual unsigned getNPreshowerHits() const { return 0; } + virtual unsigned getNSCTHits() const { return 0; } + // virtual unsigned getNEcalHits() const { return 0; } + // virtual unsigned getNScintHits() const { return (getNVetoHits() + getNTriggerHits() + getNPreshowerHits()); } + // virtual bool isIDTrack() const ; + // virtual unsigned getNPixelHits() const { return 0; } + // virtual unsigned getNSCTHits() const { return 0; } + // virtual unsigned getNTRTHits() const { return 0; } + // virtual unsigned getNMuonHits() const { return (getNMDTHits()+getNRPCHits()+getNTGCHits()+getNCSCHits()); } + // virtual unsigned getNMuonPhiHits() const { return 0; } //!< The number of phi hits is part of hit counts below (i.e. RPC hits include phi hits), but reported separately due to importance. + // virtual unsigned getNMDTHits() const { return 0; } + // virtual unsigned getNRPCHits() const { return 0; } + // virtual unsigned getNTGCHits() const { return 0; } + // virtual unsigned getNCSCHits() const { return 0; } + // virtual unsigned getNMuonPrecisionHits() const { return getNMDTHits() + getNCSCHits(); } // This should really only count eta csc hits. + virtual const Trk::FitQuality* getFitQuality() const {return 0;} + + QList<AssociatedObjectHandleBase*> getVisibleMeasurements() const; + TrackCommonFlags::TSOSPartsFlags shownTSOSParts() const; + TrackCommonFlags::TSOSPartsFlags customColouredTSOSParts() const; + + std::vector< Amg::Vector3D > * hackGetPointsPropagated();//!< FIXME. Used to get position of track for use in short tubes etc. + + virtual QString shortInfo() const { return QString("Not yet implemented"); } //!< returns mom and hit information about track + virtual QString type() const { return QString("Not yet implemented"); } //!< return very short word with type (maybe link with collection type?) + + // Object browser code + // @TODO revisit this once plan for more general approach is completed. + virtual void fillObjectBrowser(QList<QTreeWidgetItem *>& list); //!< Overload in child classes + void updateObjectBrowser(){}; + QTreeWidgetItem* browserTreeItem() const ; + +protected: + + virtual double calculateCharge() const; + + //Ways of providing path information: + // * Provide a Trk::Track + // * Provide a vector of Amg::Vector3D (this precludes extrapolation) // BEFORE EIGEN MIGRATION WAS: HepGeom::Point3D<double>'s + // + //Override exactly one of the two following methods, in order to + //provide path information. It will be called exactly once and the + //derived class destructor will be responsible of any necessary + //memory cleanup of the returned objects: + virtual const Trk::Track * provide_pathInfoTrkTrack() const { return 0; }; + // virtual const std::vector< HepGeom::Point3D<double> > * provide_pathInfoPoints() const { return 0; } + virtual const std::vector< Amg::Vector3D > * provide_pathInfoPoints() const { return 0; } + + /** Default implementation of this next method bases hypothesis on pdgCode() and charge():*/ + virtual Trk::ParticleHypothesis extrapolationParticleHypothesis() const; + + virtual void visibleStateChanged();//!< override if need to take action in this case. + virtual void currentMaterialChanged() {};//!< override if need to take action in this case. + + QList<AssociatedObjectHandleBase*> getAllAscObjHandles() const; //!< Return list of all AscObj handles. Not guaranteed to be filled unless tsoses are visible. + +private: + + // It is illegal to copy/assign a TrackHandleBase: + TrackHandleBase(const TrackHandleBase & ); + TrackHandleBase & operator= (const TrackHandleBase & ); + + friend class AssocObjAttachmentHandle; + class Imp; + Imp * m_d; + + + //Here for inlining: + bool m_visible; + TrackCollHandleBase * m_collhandle; + SoMaterial * m_currentmaterial; + void clearLine(); + void registerTrack(); + + void updateShapes_TSOSWithMeasurements(); + void updateShapes_TSOSWithErrors(); + void updateShapes_TSOSWithMaterialEffects(); + void setShownTSOSParts(TrackCommonFlags::TSOSPartsFlags f); + void setCustomColouredTSOSParts(TrackCommonFlags::TSOSPartsFlags f); + + //For associated objects: + friend class AssociatedObjectHandleBase; + friend class TrackCollHandleBase; // Troels: maybe not needed... + AssocObjAttachmentHandle * getAttachmentHandle(int regionIndex, const double& crossoverval); +protected: + void registerAssocObject(AssociatedObjectHandleBase*);//!<Trackhandle assumes ownership + +}; + +class AssocObjAttachmentHandle { +public: + void attachNodes( SoNode*simple, SoNode*detailed, bool unpickable ); + void setPickableStateOfNodes( SoNode*simple, SoNode*detailed, bool unpickable );//!<Will attach if not currently attached. + void detachNodes( SoNode*simple, SoNode*detailed ); +private: + friend class TrackHandleBase;//The life of these classes are entirely owned by TrackHandleBase. + friend class TrackHandleBase::Imp;//The life of these classes are entirely owned by TrackHandleBase. + AssocObjAttachmentHandle(TrackLODHandle *,TrackHandleBase* ); + ~AssocObjAttachmentHandle(); + AssocObjAttachmentHandle(const AssocObjAttachmentHandle & ); + AssocObjAttachmentHandle & operator= (const AssocObjAttachmentHandle & ); + void trackMaterialChanged(); + void trackVisibilityChanged(); + class Imp; + Imp * m_d; +}; + + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackHandle_FatrasTruthTrack.hSave b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackHandle_FatrasTruthTrack.hSave new file mode 100644 index 000000000..a7b21a998 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackHandle_FatrasTruthTrack.hSave @@ -0,0 +1,49 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// +// //////////////////////////////////////////////////////////////// +// // // +// // Header file for class TrackHandle_FatrasTruthTrack // +// // // +// // Description: Specialisation of Trk::Track handles used // +// // for FatRas tracks. // +// // // +// // Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// // Initial version: March 2008 // +// // // +// //////////////////////////////////////////////////////////////// +// +// #ifndef TRACKHANDLE_FATRASTRUTHTRACK_H +// #define TRACKHANDLE_FATRASTRUTHTRACK_H +// +// #include "VP1TrackSystems/TrackHandle_TrkTrack.h" +// namespace Fatras{ class TrackParticleState; } +// +// class TrackHandle_FatrasTruthTrack : public TrackHandle_TrkTrack { +// public: +// +// TrackHandle_FatrasTruthTrack(TrackCollHandleBase*,const Fatras::TrackParticleState*); +// virtual ~TrackHandle_FatrasTruthTrack() {}; +// +// virtual QStringList clicked() const; +// +// virtual Amg::Vector3D momentum() const; +// virtual const Amg::Vector3D * startPoint() const; +// virtual int pdgCode() const; +// virtual QString type() const { return QString("Fatras"); } //!< return very short word with type (maybe link with collection type?) +// +// protected: +// virtual double calculateCharge() const; +// virtual Trk::ParticleHypothesis extrapolationParticleHypothesis() const; +// +// private: +// +// class Imp; +// Imp * d; +// +// +// }; +// +// #endif diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackHandle_TrkTrack.h b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackHandle_TrkTrack.h new file mode 100644 index 000000000..a2df693d7 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackHandle_TrkTrack.h @@ -0,0 +1,67 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class TrackHandle_TrkTrack // +// // +// Description: TrackHandle for Trk::Track's // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: February 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef TRACKHANDLE_TRKTRACK_H +#define TRACKHANDLE_TRKTRACK_H + +#include "VTI12TrackSystems/TrackHandleBase.h" +#include "VTI12TrackSystems/MeasurementToSoNode.h" + +#include "GeoPrimitives/GeoPrimitives.h" + +namespace Trk { + class Track; + class MeasurementBase; +} + +class TrackHandle_TrkTrack : public TrackHandleBase { +public: + + TrackHandle_TrkTrack(TrackCollHandleBase*,const Trk::Track*); + virtual ~TrackHandle_TrkTrack(); + + virtual QStringList clicked() const; + + virtual Amg::Vector3D momentum() const; + const Trk::Track * provide_pathInfoTrkTrack() const { return m_trk; }; + + const Trk::Track* trkTrackPointer() const { return m_trk; } + + virtual bool hasSubSystemHitInfo() const { ensureInitSubSysHitInfo(); return m_hitInfoStatus; } + virtual unsigned getNSCTHits() const { return m_nhits_sct; } + virtual const Trk::FitQuality* getFitQuality() const ; + + virtual void fillObjectBrowser(QList<QTreeWidgetItem *>& list); + void updateObjectBrowser(); + + SoNode* zoomToTSOS(unsigned int index); //!< Depending on controller configuration attempt to zoom to the corresponding TSOS & returned detailed node matching it + + virtual QString shortInfo() const; //!< returns mom and hit information about track + virtual QString type() const { return QString("Track"); } //!< return very short word with type (maybe link with collection type?) + +private: + void visibleStateChanged(); + void currentMaterialChanged(); + mutable unsigned m_nhits_sct; + mutable int m_hitInfoStatus;//!< -1: uninitialized, 0: not present, 1: present. + void ensureInitSubSysHitInfo() const; + +protected: + const Trk::Track* m_trk; + Trk::MeasurementToSoNode m_measToSoNode; //!< Just used to get types, so probably better to hive that functionality off. @FIXME +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackHandle_TruthTrack.h b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackHandle_TruthTrack.h new file mode 100644 index 000000000..7c35a0b46 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackHandle_TruthTrack.h @@ -0,0 +1,64 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class TrackHandle_TruthTrack // +// // +// Description: Handle for truth tracks based on HepMC // +// records and sim. hits. // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: March 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef TRACKHANDLE_TRUTHTRACK_H +#define TRACKHANDLE_TRUTHTRACK_H + +#include "VTI12TrackSystems/TrackHandleBase.h" +#include "VTI12TrackSystems/SimHitHandleBase.h" + +#include "GeoPrimitives/GeoPrimitives.h" + +namespace HepMC { class GenParticle; } + +class TrackHandle_TruthTrack : public TrackHandleBase { +public: + + TrackHandle_TruthTrack( TrackCollHandleBase*, + const SimBarCode&, + const SimHitList&, + const HepMC::GenParticle* genPart = 0 ); + + virtual ~TrackHandle_TruthTrack(); + + virtual QStringList clicked() const; + + virtual Amg::Vector3D momentum() const; + virtual int pdgCode() const; + bool hasBarCodeZero() const; + + + bool hasVertexAtIR(const double& rmaxsq, const double& zmax) const; + //Fixme: Something like this?: bool isPrimaryTrack() const; + void setAscObjsVisible(bool); + + virtual QString type() const { return QString("Truth"); } //!< return very short word with type (maybe link with collection type?) + + +protected: + virtual double calculateCharge() const; + const Trk::Track * provide_pathInfoTrkTrack() const; + void visibleStateChanged(); + +private: + + class Imp; + Imp * m_d; + +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackLODManager.h b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackLODManager.h new file mode 100644 index 000000000..5679101a8 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackLODManager.h @@ -0,0 +1,73 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class TrackLODManager // +// // +// Description: Manager class for taking care of the LOD // +// nodes needed for associated track objects. // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: March 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef TRACKLODMANAGER_H +#define TRACKLODMANAGER_H + +#include "VP1Base/VP1HelperClassBase.h" +#include "VTI12TrackSystems/TrackCommonFlags.h" +#include <QObject> + +//Fixme: Should this be a general utility class, to be used in the prd +// system as well? + +class TrackLODHandle; +class SoGroup; +class VP1ExtraSepLayerHelper; + +class TrackLODManager : public QObject, public VP1HelperClassBase { + + Q_OBJECT + +public: + TrackLODManager( QObject * parent = 0, IVP1System * sys = 0);// sys != for messages in gui. + virtual ~TrackLODManager(); + + void setAttachNode(SoGroup* attachnode); + void eraseEventData(); + + TrackLODHandle * getLODHandle(int regionindex, const double& crossover_value); + +public slots: + void setDetailLevel(TrackCommonFlags::DETAILLEVEL); + +private: + + class Imp; + Imp * m_d; + friend class TrackLODHandle; +}; + +//Handle class declaration: +class TrackLODHandle { +public: + void addNodes(SoGroup* simple,SoGroup*detailed ); + void removeNodes(SoGroup* simple,SoGroup*detailed ); +private: + TrackLODHandle(SoGroup*,VP1ExtraSepLayerHelper*,VP1ExtraSepLayerHelper*,int, const double& ); + ~TrackLODHandle(); + TrackLODHandle(const TrackLODHandle & ); + TrackLODHandle & operator= (const TrackLODHandle & ); + friend class TrackLODManager; + friend class TrackLODManager::Imp; + class Imp; + Imp * m_d; +}; + + + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackPropagationHelper.h b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackPropagationHelper.h new file mode 100644 index 000000000..1b042eb0c --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackPropagationHelper.h @@ -0,0 +1,62 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class TrackPropagationHelper // +// // +// Description: Helper class for using extrapolators to // +// extend raw track data // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Actual extrapolation code by Thijs Cornelissen // +// Initial version: February 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef TRACKPROPAGATIONHELPER_H +#define TRACKPROPAGATIONHELPER_H + +#include "VP1Base/VP1HelperClassBase.h" + +#include "TrkSurfaces/PlaneSurface.h" +#include "TrkEventPrimitives/ParticleHypothesis.h" + +//#include "CLHEP/Geometry/Point3D.h" +#include "GeoPrimitives/GeoPrimitives.h" + +#include <vector> + + + +namespace Trk { + class Track; + class IExtrapolator; + class Volume; +} + +class TrackPropagationHelper : public VP1HelperClassBase { +public: + + TrackPropagationHelper( IVP1System* sys ); + ~TrackPropagationHelper(); + + bool makePointsNeutral( std::vector<Amg::Vector3D >& points, const Trk::Track* ); + bool makePointsCharged( std::vector<Amg::Vector3D >& points, const Trk::Track*, + Trk::IExtrapolator * extrapolator, Trk::ParticleHypothesis hypo = Trk::nonInteracting, bool useMEOT=false, const Trk::Volume* volume=0 ); + + std::vector<Trk::PlaneSurface>& getExtrapolationSurfaces() const; + bool showExtrapolationSurfaces() const; + + // double maxR2ForTracks() const; //!< Returns the maximum r^2 to draw track curves up to. Set by + +private: + + class Imp; + Imp * m_d; + +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackSysCommonData.h b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackSysCommonData.h new file mode 100644 index 000000000..426e9c1b9 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackSysCommonData.h @@ -0,0 +1,126 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class TrackSysCommonData // +// // +// Description: Common pointers, data, node-to-object maps // +// etc. for the track system // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: April 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef TRACKSYSCOMMONDATA_H +#define TRACKSYSCOMMONDATA_H + +#include "VP1Base/VP1HelperClassBase.h" +#include "VP1Base/VisibleObjectToMaterialHelper.h" +#include "VTI12Utils/HitsSoNodeManager.h" + +class VP1TrackSystem; +class IVP13DSystem; +class AscObjSelectionManager; +class TrackSystemController; +// class InDetProjHelper; +class TrackPropagationHelper; +class TrackLODManager; +class VP1TrackSanity; +class SoNode; +class TrackHandleBase; +class SoPointSet; +class QTreeWidgetItem; +class SoSeparator;//Fixme! + +namespace Trk { + class Track; + class Segment; +} +class VP1TrackSystem; + +class TrackSysCommonData : public VP1HelperClassBase { +public: + + TrackSysCommonData(VP1TrackSystem * sys,TrackSystemController *); + virtual ~TrackSysCommonData(); + + VP1TrackSystem * system() const; + AscObjSelectionManager* ascObjSelectionManager() const;//returns null if not in refreshed state + TrackSystemController * controller() const; + // InDetProjHelper * indetProjHelper_Pixel() const; + // InDetProjHelper * indetProjHelper_SCT() const; + // InDetProjHelper * indetProjHelper_TRT() const; + TrackPropagationHelper * trackPropagationHelper() const; + TrackLODManager* trackLODManager() const; + VisibleObjectToMaterialHelper<Trk::Track> * visTrkTracksToMaterialHelper() const; + VisibleObjectToMaterialHelper<Trk::Segment> * visTrkSegmentsToMaterialHelper() const; + VP1TrackSanity * trackSanityHelper() const; + SoPointSet * singlePoint() const;//A single point at (0,0,0) + HitsSoNodeManager& nodeManager(); + + void setEventData(AscObjSelectionManager*); + void clearEventData(); //Deletes AscObjSelectionManager + + //register node->track connection (erased at next clearEventData) + void registerTrack(SoNode*,TrackHandleBase*); + void unregisterTrack(SoNode*); + + // void registerBrowserItem(QTreeWidgetItem* item, SoNode* node); + // void unregisterBrowserItem(QTreeWidgetItem* item); + + //get the connection: + TrackHandleBase* trackHandle(SoNode*n); + SoNode* node(TrackHandleBase* h); //!< Returns the node associated with this handle. Returns zero if no match found. + SoNode* node(QTreeWidgetItem* item); //!< Returns the node associated with this item. Returns zero if no match found. + + void setLastSelectedTrack(TrackHandleBase* sel); + TrackHandleBase* lastSelectedTrackHandle();//!< pointer to base of last selected track (zero if nothing selected) + SoSeparator* textSep(); // FIXME! FIXME! + + SoSeparator* m_textSep; // FIXME! FIXME! Make private, but then need set method for VP1TrackSystem.cxx:247 + + const TrackHandleBase* getHandle(const Trk::Track* trk); + +private: + class Imp; + Imp * m_d; + + VP1TrackSystem * m_3dsystem; + AscObjSelectionManager* m_ascObjSelectionManager; + TrackSystemController * m_controller; + // InDetProjHelper * m_indetProjHelper_Pixel; + // InDetProjHelper * m_indetProjHelper_SCT; + // InDetProjHelper * m_indetProjHelper_TRT; + TrackPropagationHelper * m_trackPropagationHelper; + TrackLODManager* m_trackLODManager; + VisibleObjectToMaterialHelper<Trk::Track> * m_visTrkTracksToMaterialHelper; + VisibleObjectToMaterialHelper<Trk::Segment> * m_visTrkSegmentsToMaterialHelper; + VP1TrackSanity * m_trackSanity; + SoPointSet * m_singlePoint; + TrackHandleBase* m_lastSelectedTrack; + HitsSoNodeManager m_nodeManager; +}; + +inline VP1TrackSystem* TrackSysCommonData::system() const { return m_3dsystem; } +inline AscObjSelectionManager* TrackSysCommonData::ascObjSelectionManager() const { return m_ascObjSelectionManager; } +inline TrackSystemController * TrackSysCommonData::controller() const { return m_controller; } +// inline InDetProjHelper * TrackSysCommonData::indetProjHelper_Pixel() const { return m_indetProjHelper_Pixel; } +// inline InDetProjHelper * TrackSysCommonData::indetProjHelper_SCT() const { return m_indetProjHelper_SCT; } +// inline InDetProjHelper * TrackSysCommonData::indetProjHelper_TRT() const { return m_indetProjHelper_TRT; } +inline TrackPropagationHelper * TrackSysCommonData::trackPropagationHelper() const { return m_trackPropagationHelper; } +inline TrackLODManager* TrackSysCommonData::trackLODManager() const { return m_trackLODManager; } +inline VisibleObjectToMaterialHelper<Trk::Track> * TrackSysCommonData::visTrkTracksToMaterialHelper() const { return m_visTrkTracksToMaterialHelper; } +inline VisibleObjectToMaterialHelper<Trk::Segment> * TrackSysCommonData::visTrkSegmentsToMaterialHelper() const { return m_visTrkSegmentsToMaterialHelper; } +inline VP1TrackSanity * TrackSysCommonData::trackSanityHelper() const { return m_trackSanity; } +inline SoPointSet * TrackSysCommonData::singlePoint() const { return m_singlePoint; } +inline void TrackSysCommonData::setLastSelectedTrack( TrackHandleBase* sel) {m_lastSelectedTrack=sel;} +inline TrackHandleBase* TrackSysCommonData::lastSelectedTrackHandle() {return m_lastSelectedTrack;} +inline SoSeparator* TrackSysCommonData::textSep() {return m_textSep;} // FIXME! FIXME! +inline HitsSoNodeManager& TrackSysCommonData::nodeManager() {return m_nodeManager;} + +#endif + diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackSystemController.h b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackSystemController.h new file mode 100644 index 000000000..b95ba96f0 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackSystemController.h @@ -0,0 +1,275 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class TrackSystemController // +// // +// Description: Controller widget for the track system // +// Keeps all nasty gui stuff internally, and // +// only presents the actual interesting data // +// with specialised access methods and signals. // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: February 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef TRACKSYSTEMCONTROLLER_H +#define TRACKSYSTEMCONTROLLER_H + +#include "VP1Base/VP1Controller.h" +#include "VTI12TrackSystems/TrackCommonFlags.h" +#include "TrkEventPrimitives/ParticleHypothesis.h" +#include <QFlags> +#include "GaudiKernel/ServiceHandle.h" +#include "TrkDetDescrInterfaces/ITrackingVolumesSvc.h" + +class TrackCollWidget; +class SoMaterial; +class SoDrawStyle; +// class SoLightModel; +class SoComplexity; +class TrackSysCommonData; + +// class TrackObjectBrowserController; + +class QTreeWidget; +class QTreeWidgetItem; + +namespace Trk { + class IExtrapolator; + class ITrackFitter; + class Track; + class Volume; +} + +class TrackSystemController : public VP1Controller { + + Q_OBJECT + +public: + + TrackSystemController(IVP1System * sys); + virtual ~TrackSystemController(); + + void initTools();//comboboxes for selecting tools + tool creation is + //postponed until this call (so it can wait until + //systemcreate()) + + void actualRestoreSettings(VP1Deserialise&); + int currentSettingsVersion() const; + void actualSaveSettings(VP1Serialise&) const; + + /*So we can enable/disable parts based on whether prd's & Tracks are selected:*/ + void setNumberOfSelectedPRDsAndTracks(unsigned prds, unsigned trks); + + TrackCollWidget * collWidget() const; + + /////////////////////////////////// + // Access Methods for settings // + /////////////////////////////////// + TrackCommonFlags::TrackPartsFlags shownTrackParts() const; + int vertexProjectionAngle() const; //Ranges from 0-179 i.e. is in degrees. Might be disabled, in which case will be -ve. + + // double trackTubeRadius() const;//0 => don't show tubes for tracks + enum PropagationOptionFlag {NoPropOptions=0x0000, IgnoreMEOT=0x0001, ExtendTrack=0x0002}; + Q_DECLARE_FLAGS(PropagationOptionFlags, PropagationOptionFlag) + Trk::IExtrapolator * propagator() const;//Null for no propagator - i.e. show raw data. + PropagationOptionFlags propagationOptions() const; + float propMaxRadius() const; + + bool ignoreMeasurementEffectsOnTrackInProp() ; //!< If true (default) don't use TSOS with MEOT to draw track points + // ITrackingVolumesSvc * trackingVolumeSvc() const; + const Trk::Volume * extrapolateToThisVolume() const ; //!< Returns the volume to which we extrapolate ID tracks, or zero if no VolumesSvc found. + Trk::ITrackFitter * trackFitter() const; + + QString nameOfNewlyFittedCollections() const;//queried on-demand, no signal. + TrackCommonFlags::SELECTIONMODE selectionMode() const; + TrackCommonFlags::FITTERMODE fitterMode() const; + bool fitterRemoveOutliers() const; + Trk::ParticleHypothesis fitterParticleHypthesis() const; + TrackCommonFlags::DETAILLEVEL assocObjDetailLevel() const; + + //Associated objects (base): + TrackCommonFlags::TSOSPartsFlags shownTSOSParts() const; + TrackCommonFlags::TSOSPartsFlags customColouredTSOSParts() const; + bool drawMeasGlobalPositions() const; + + bool hideCustomSurfaces() const; + bool hideTubeSurfaces() const; + double measurementsShorttubesScale() const; + double nStdDevForParamErrors() const; + bool parTubeErrorsDrawCylinders() const; + int numberOfPointsOnCircles() const;//will return numbers in {4,8,12,16,...} + double materialEffectsOnTrackScale() const; + + + bool showTruthAscObjs() const;//Fixme: obsolete + //General cuts: + VP1Interval cutAllowedPt() const; + VP1Interval cutAllowedEta() const; + QList<VP1Interval> cutAllowedPhi() const;//All off: empty list. All on: list with one entry: ]-inf,inf[ + //Cuts for number of hits per subsystem: + QList<unsigned> cutRequiredNHits() const;//Empty list: no requirements. Otherwise a list + // with a length of four (pixel,sct,trt,muon) + + void vertexCutsAllowed(bool); // called if vertex system is available. + bool cutOnlyVertexAssocTracks() const; + //Truth cuts: + bool cutTruthFromIROnly() const; + bool cutExcludeBarcodeZero() const; + bool cutTruthExcludeNeutrals() const; + //Interactions: + bool showTotMomentumOnMultiTrackSelection() const; + //No associated signals for the next four (only queried on-click): + bool orientAndZoomOnSingleSelection() const; + bool printInfoOnSingleSelection() const; + bool printVerboseInfoOnSingleSelection() const; + bool printTotMomentumOnMultiTrackSelection() const; + + //Material pointers returned by the next methods won't change during + //the lifetime of the system (but their fields may get updated by + //the controller): + SoMaterial * getMaterialForPDGCode(const int& pdgcode) const; + SoMaterial * getMaterialForCharge(const double& charge) const; + SoMaterial * getMaterialForMomentum(const double& absmom) const; + SoMaterial * customMatMeasurements() const; + SoMaterial * customMatMeasurementsOutliers() const; + SoMaterial * customMatParameters() const; + SoMaterial * customMatHoleParameters() const; + SoMaterial * customMatParameterErrors() const; + SoMaterial * customMatMaterialEffects() const; + SoMaterial * customMatSurfaces() const; + + //Overall drawstyles, complexities and light models: + // SoDrawStyle * trackDrawStyle() const; + // SoLightModel * trackLightModel() const; + SoDrawStyle * ascObjDrawStyle() const; + SoComplexity * ascObjComplexity() const; + + QTreeWidget* trackObjBrowser() const; //!< Returns a pointer to the Track Object Browser (if it exists) + TrackSysCommonData * common() const; //!< Returns a pointer to the common data (if it exists) + void setCommonData(TrackSysCommonData *) ; //!< set pointer to the common data + + // Return special information for VP1_TRKSYS_SHIFTCHAMBERS mode + std::vector<double> alignmentShiftValue(); + int alignmentShiftLevel(); + + // Labels + bool doTrackLabels(); + enum TrackLabelMode {NoLabels=0x0000, P=0x0001, Pt=0x0002, Pid=0x0004, Hits=0x0008, + FitQuality=0x0010, Direction=0x0020}; + Q_DECLARE_FLAGS(TrackLabelModes, TrackLabelMode) + + TrackLabelModes trackLabels(); + + float trackLabelTrkOffset() ; //!< Percentage of postion along track + QList<int> trackLabelPosOffset() ; //!< Offset in x,y,z + + int labelXOffset() ; //!< Absolute x offset + int labelYOffset() ; //!< Absolute y offset + int labelZOffset() ; //!< Absolute z offset + + /////////////////////////////////////// + // Signals for changes in settings // + /////////////////////////////////////// +signals: + void rerandomise();//This one doesn't have an access method, but is just emitted when needed. + void refit();//[TEMPORARY] This one doesn't have an access method, but is just emitted when needed. + void shownTrackPartsChanged(TrackCommonFlags::TrackPartsFlags); + void vertexProjectionAngleChanged(int); + void trackLabelsChanged(TrackSystemController::TrackLabelModes); + void trackLabelTrkOffsetChanged(float); + void trackLabelPosOffsetChanged(QList<int>); + // void trackTubeRadiusChanged(const double&); + void shownTSOSPartsChanged(TrackCommonFlags::TSOSPartsFlags); + void customColouredTSOSPartsChanged(TrackCommonFlags::TSOSPartsFlags); + void drawMeasGlobalPositionsChanged(bool); + void measurementsShorttubesScaleChanged(double); + void nStdDevForParamErrorsChanged(const double&); + void parTubeErrorsDrawCylindersChanged(bool); + void numberOfPointsOnCirclesChanged(int); + void materialEffectsOnTrackScaleChanged(double); + void propagatorChanged(Trk::IExtrapolator *); + void propagationOptionsChanged(TrackSystemController::PropagationOptionFlags); + void propMaxRadiusChanged(float); + void extrapolateToThisVolumeChanged(void); + // void ignoreMeasurementEffectsOnTrackInPropChanged(bool); + void trackFitterChanged(Trk::ITrackFitter *); + void selectionModeChanged(TrackCommonFlags::SELECTIONMODE); + void showTruthAscObjsChanged(bool); + void assocObjDetailLevelChanged( TrackCommonFlags::DETAILLEVEL ); + void cutAllowedPtChanged(const VP1Interval&); + void cutAllowedEtaChanged(const VP1Interval&); + void cutAllowedPhiChanged(const QList<VP1Interval>&); + void cutRequiredNHitsChanged(const QList<unsigned>&); + void cutTruthFromIROnlyChanged(bool); + void cutExcludeBarcodeZeroChanged(bool); + void cutTruthExcludeNeutralsChanged(bool); + void cutOnlyVertexAssocTracksChanged(bool); + void showTotMomentumOnMultiTrackSelectionChanged(bool); + +private: + + class Imp; + Imp * m_d; + + //For verbose output: + template <class T> static QString toString( const T& t ) { return VP1Controller::toString(t); }//unhide base methods + static QString toString( const TrackCommonFlags::SELECTIONMODE& par ) { return TrackCommonFlags::toString(par); } + static QString toString( const TrackCommonFlags::DETAILLEVEL& par ) { return TrackCommonFlags::toString(par); } + static QString toString( const QList<unsigned>& par ); + static QString toString( const QList<int>& par ); + +private slots: + void emitRerandomise(); + void emitRefit(); + // void updateTrackDrawStyle(); + // void updateTrackLightModel(); + void updateAscObjDrawStyle(); + void updateAscObjComplexity(); + void availableExtrapolatorsChanged(const QStringList&); + void availableFittersChanged(const QStringList&); + void emitExtrapolateToHereChanged(int); + void possibleChange_shownTrackParts(); + void possibleChange_vertexProjectionAngle(); + // void possibleChange_trackTubeRadius(); + void possibleChange_trackLabels(); + void possibleChange_trackLabelTrkOffset(); + void possibleChange_trackLabelPosOffset(); + void possibleChange_shownTSOSParts(); + void possibleChange_customColouredTSOSParts(); + void possibleChange_drawMeasGlobalPositions(); + void possibleChange_measurementsShorttubesScale(); + void possibleChange_nStdDevForParamErrors(); + void possibleChange_parTubeErrorsDrawCylinders(); + void possibleChange_numberOfPointsOnCircles(); + void possibleChange_materialEffectsOnTrackScale(); + void possibleChange_propagator(); + void possibleChange_propagationOptions(); + void possibleChange_propMaxRadius(); + // void possibleChange_ignoreMeasurementEffectsOnTrackInProp(); + void possibleChange_trackFitter(); + void possibleChange_selectionMode(); + void possibleChange_assocObjDetailLevel(); + void possibleChange_showTruthAscObjs(); + void possibleChange_cutAllowedPt(); + void possibleChange_cutAllowedEta(); + void possibleChange_cutAllowedPhi(); + void possibleChange_cutRequiredNHits(); + void possibleChange_cutTruthFromIROnly(); + void possibleChange_cutExcludeBarcodeZero(); + void possibleChange_cutTruthExcludeNeutrals(); + void possibleChange_cutOnlyVertexAssocTracks(); + void possibleChange_showTotMomentumOnMultiTrackSelection(); + void objectBrowserClicked(QTreeWidgetItem * item, int); + void updateFitPRDButtonState(); +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(TrackSystemController::TrackLabelModes) +Q_DECLARE_OPERATORS_FOR_FLAGS(TrackSystemController::PropagationOptionFlags) + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackTypes.h b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackTypes.h new file mode 100644 index 000000000..1f257378e --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrackTypes.h @@ -0,0 +1,33 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TRACKTYPES_H +#define TRACKTYPES_H + +#include <QString> + +class TrackType { +public: + //NB: The order listed here is the order presented in the GUI (see TrackCollWidget::sortSections(..)) + enum Type { + Unknown, TrkTrack, TrackParticle, FatrasTruthTrack, RefittedTrack, TrkSegment, TruthTrack, SimulationTrack, AnalysisObject, xAOD + }; + + static qint32 typeToInt(const Type&); + static Type intToType(const qint32&); + + static QString typeToString(const Type&); + static Type stringToType(const QString&str, bool & status); + + //For getting a pretty more human-readable string for the section headers: + static QString typeToSectionHeader(const Type&); + static Type sectionHeaderToType(const QString&, bool & status); + static QString typeToSectionHeaderToolTip(const Type&); + +private: + TrackType(); +}; + + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrkObjToString.h b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrkObjToString.h new file mode 100644 index 000000000..88ba6b5d0 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/TrkObjToString.h @@ -0,0 +1,107 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TRK_VP1TRACKSYSTEMS_TRKOBJTOSTRING_H +#define TRK_VP1TRACKSYSTEMS_TRKOBJTOSTRING_H +#include <string> +#include <QString> +#include <QStringList> +#include "TrkParameters/TrackParameters.h" +// #include "Identifier/Identifier.h" +#include "TrkEventPrimitives/FitQualityOnSurface.h" //typedef + +// class CscIdHelper; +// class RpcIdHelper; +// class TgcIdHelper; +// class MdtIdHelper; + +// namespace InDet { +// class PixelCluster; +// class SCT_Cluster; +// class TRT_DriftCircle; +// } + + +namespace Trk { + class PrepRawData; + class RIO_OnTrack; + class CompetingRIOsOnTrack; + class PseudoMeasurementOnTrack; + class MeasurementBase; + class MaterialEffectsBase; + class Segment; + class DetElementBase; +} + +class TrkObjToString { +public: + enum MeasurementType { + // Veto, + // Trigger, + // Preshower, + SCT, + // Ecal, + Hole, + CompetingROT, + PseudoMeasurement, + Segment, + Unknown + }; + + static MeasurementType type(const Trk::PrepRawData* prd); + static MeasurementType type(const Trk::MeasurementBase* meas); + static MeasurementType type(const Trk::TrkDetElementBase* detEl); + + static std::string typeName(MeasurementType type); //!< Returns a very short summary of the object type + static std::string typeName(const Trk::MeasurementBase& mb); //!< Returns a very short summary of mb + + static QString name(const Trk::MeasurementBase& mb); + static QString name(const Trk::TrackParameters& mb); + static QString name(const Trk::MaterialEffectsBase& mb); + static QString name(const Trk::FitQuality& mb); + + static QString shortInfo(const Trk::MeasurementBase& mb); + static QString shortInfo(const Trk::TrackParameters& tp); + static QString shortInfo(const Trk::MaterialEffectsBase& me); + static QString shortInfo(const Trk::FitQuality& fqos); + + static QStringList fullInfo(const Trk::MeasurementBase& tp); //!< Returns list of key, value, key, value etc + static QStringList fullInfo(const Trk::TrackParameters& tp); //!< Returns list of key, value, key, value etc + static QStringList fullInfo(const Trk::MaterialEffectsBase& tp); //!< Returns list of key, value, key, value etc + static QStringList fullInfo(const Trk::FitQuality& tp); //!< Returns list of key, value, key, value etc + + static void addBaseROTInfo(QString& info, const Trk::MeasurementBase& mb); + static void addFullInfo(QStringList& info, const Trk::RIO_OnTrack*); + static void addFullInfo(QStringList& info, const Trk::CompetingRIOsOnTrack*); + static void addFullInfo(QStringList& info, const Trk::PseudoMeasurementOnTrack*); + static void addFullInfo(QStringList& info, const Trk::Segment*); +}; + +inline +std::string +TrkObjToString::typeName(TrkObjToString::MeasurementType type) +{ + switch (type){ + // case Veto: return std::string("Veto RIO_OnTrack"); + // case Trigger: return std::string("Trigger RIO_OnTrack"); + // case Preshower: return std::string("Preshower RIO_OnTrack"); + case SCT: return std::string("SCT RIO_OnTrack"); + // case Ecal: return std::string("Ecal RIO_OnTrack"); + case Hole: return std::string("Hole"); + case CompetingROT: return std::string("CompetingROT"); + case PseudoMeasurement: return std::string("Pseudo"); + case Segment: return std::string("Segment"); + case Unknown: return std::string("Unknown"); + } + return std::string("Error!"); +} + +inline +std::string +TrkObjToString::typeName(const Trk::MeasurementBase& mb) +{ + return typeName(type(&mb)); +} + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/VP1TrackSanity.h b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/VP1TrackSanity.h new file mode 100644 index 000000000..38865da5e --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/VP1TrackSanity.h @@ -0,0 +1,56 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1TrackSanity // +// // +// Description: Helper class for ensuring track parameters, // +// measurements, etc. are constructed properly // +// before we start to ask them about their // +// global positions, etc. // +// // +// Authors: Edward Moyse (Edward.Moyse@cern.ch) // +// Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: March 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VP1TRACKSANITY_H +#define VP1TRACKSANITY_H + +#include "VP1Base/VP1HelperClassBase.h" +#include "TrkParameters/TrackParameters.h" + +namespace Trk { + class TrackStateOnSurface; + class MeasurementBase; + class RIO_OnTrack; + class PrepRawData; +} + +class VP1TrackSanity : public VP1HelperClassBase { +public: + + VP1TrackSanity(IVP1System * sys=0);//sys!=0 for messages in gui. + virtual ~VP1TrackSanity(); + + bool isSafe(const Trk::TrackStateOnSurface* ) const; + bool isSafe(const Trk::TrackParameters* ) const; + bool isSafe(const Trk::MeasurementBase* ) const; + bool isSafe(const Trk::RIO_OnTrack* ) const; + bool isSafe(const Trk::PrepRawData* ) const; + + //TK: OK, maybe we can't call all of these "isSafe", if more than + //one of the arguments inherit from the same baseclass (not sure if + //they do apart from measurementbase/rioontrack). +private: + + class Imp; + Imp * m_d; + +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/VP1TrackSummary.h b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/VP1TrackSummary.h new file mode 100644 index 000000000..e4e70fba8 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/VP1TrackSummary.h @@ -0,0 +1,47 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1TrackSummary // +// // +// Description: A few basic helpers providing track summary // +// information. // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: November 2009 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VP1TRACKSUMMARY_H +#define VP1TRACKSUMMARY_H +#include <set> + +namespace Trk { class Track; class Segment; class MeasurementBase; class TrkDetElementBase;} +class FaserDetectorID; + +class VP1TrackSummary { +public: + + static bool countHits( const Trk::Track*, + unsigned& nSCThits + ); + + static bool countHits( const Trk::Segment*, + unsigned& nSCThits + ); + + static void addCounts( std::set<const Trk::TrkDetElementBase*>& detelems, const Trk::MeasurementBase* meas, + const FaserDetectorID * idhelper, + unsigned& nSCThits + ); + +private: + VP1TrackSummary(); + ~VP1TrackSummary(); + +}; + +#endif diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/VP1TrackSystem.h b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/VP1TrackSystem.h new file mode 100644 index 000000000..d34a0e902 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/VTI12TrackSystems/VP1TrackSystem.h @@ -0,0 +1,99 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1TrackSystem // +// // +// Description: System displaying all track-like objects // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: February 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VP1TRACKSYSTEM_H +#define VP1TRACKSYSTEM_H + +#include "VP1Base/IVP13DSystemSimple.h" +// #include "VTI12Utils/InDetProjFlags.h" +#include "GeoModelKernel/GeoPVConstLink.h" +#include <QList> +#include <vector> +#include <map> +class SoMaterial; +class SoCooperativeSelection; +class TrackHandleBase; + +namespace Trk { + class Track; + class Segment; + class PrepRawData; + class ITrackFitter; +} + +class VP1TrackSystem : public IVP13DSystemSimple { + + Q_OBJECT + +public: + + VP1TrackSystem(QString name="Tracks"); + virtual ~VP1TrackSystem(); + + void systemcreate(StoreGateSvc* detstore); + void systemuncreate(); + QWidget * buildController(); + void buildEventSceneGraph(StoreGateSvc* sg, SoSeparator *root); + void systemerase(); + QByteArray saveState(); + void restoreFromState(QByteArray); + + void userPickedNode(SoNode* pickedNode, SoPath *pickedPath); + void userSelectedSingleNode(SoCooperativeSelection*, SoNode* , SoPath*);//SINGLE + void userDeselectedSingleNode(SoCooperativeSelection*, SoNode* , SoPath*);//SINGLE + void userChangedSelection(SoCooperativeSelection*, QSet<SoNode*>, QSet<SoPath*>);//TOGGLE/SHIFT + void userClickedOnBgd(); + SoCooperativeSelection * selTracks(); //!< Needed in TrackSystemController::objectBrowserClicked(QTreeWidgetItem * item, int) + SoCooperativeSelection * selAscs(); //!< Needed in TrackSystemController::objectBrowserClicked(QTreeWidgetItem * item, int) + SoMaterial* materialFromVertex(const TrackHandleBase* trk) const; //!< Returns the material for the vertex which knows this trackhandle (if known) + + public slots: + + //Fixme: It would be better (and more like the tracksys/segmentsys->prd sys interaction) just to receive a list of visible vertices/jets and their colours!! + // void highlightTracks( const std::vector<std::pair<SoMaterial*,std::set<const Trk::Track*> > >&);//Orders remembered on a per-sender basis, so a given sender + //(JetSystem/VertexSystem/...) can override its own orders again. + // void setApplicableIDProjections( InDetProjFlags::InDetProjPartsFlags pixel, + // InDetProjFlags::InDetProjPartsFlags sct, + // InDetProjFlags::InDetProjPartsFlags trt ); + + void setSelectedPRDs(const QList<const Trk::PrepRawData*>&); + void updateAlignment(); //!< Special mode to allow in VP1 alignment tests + void tracksFromVertexChanged(QList< std::pair<const SoMaterial*, QList< const Trk::Track*> > >& ); + +signals: + void visibleTracksChanged(const std::vector< std::pair<const Trk::Track*, const SoMaterial*> >&); + void visibleSegmentsChanged(const std::vector< std::pair<const Trk::Segment*, const SoMaterial*> >&); + // void usedIDProjectionsChanged( InDetProjFlags::DetTypeFlags ); + void newTrackSelected( const TrackHandleBase&); + +private slots: + void visibleObjectsChanged(); + void updateSelectionMode(); + void updateShownTotMomentum(); + // void possiblyEmitUsedIDProjectionsChanged(); + void refit();//Temporary +private: + + void refitFromPRDs(const Trk::ITrackFitter* currentFitter, QList<const Trk::Track*>& fittedtracks); + void refitSingleTrack(const Trk::ITrackFitter* currentFitter, QList<const Trk::Track*>& fittedtracks); + + class Imp; + Imp * m_d; + +}; + +#endif +// diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/AscObjSelectionManager.cxx b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/AscObjSelectionManager.cxx new file mode 100644 index 000000000..ee188215c --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/AscObjSelectionManager.cxx @@ -0,0 +1,414 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class AscObjSelectionManager // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: April 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12TrackSystems/AscObjSelectionManager.h" +#include "VTI12TrackSystems/TrackSystemController.h" +#include "VTI12TrackSystems/AssociatedObjectHandleBase.h" +#include "VP1Base/IVP13DSystem.h" +#include "VP1Base/SoCooperativeSelection.h" +#include "VP1Base/VP1QtInventorUtils.h" +#include "VP1Base/VP1Msg.h" +#include <Inventor/nodes/SoSeparator.h> +#include <Inventor/SoPath.h> +#include <QApplication> +#include<map> + +//____________________________________________________________________ +class AscObjSelectionManager::Imp { +public: + Imp(AscObjSelectionManager * tc,SoSeparator* root,IVP13DSystem * sys,TrackSystemController*c) + : theclass(tc), + eventRoot(root), + system(sys), + controller(c), + mode(SINGLE) + { + eventRoot->ref(); + sel_assocobjs_click = new SoCooperativeSelection; + sel_assocobjs_click->setName("sel_assocobjs_click"); + sel_assocobjs_click->ref(); + sel_assocobjs_click->activePolicy = SoCooperativeSelection::ACTIVE; + sel_assocobjs_click->policy = SoCooperativeSelection::SINGLE; + sys->registerSelectionNode(sel_assocobjs_click); + + sel_assocobjs = new SoCooperativeSelection; + sel_assocobjs->setName("sel_assocobjs"); + sel_assocobjs->ref(); + sel_assocobjs->activePolicy = SoCooperativeSelection::INERT; + sel_assocobjs_click->policy = SoCooperativeSelection::SINGLE; + sys->registerSelectionNode(sel_assocobjs); + + sel_assocobjs->addChild(sel_assocobjs_click); + root->addChild(sel_assocobjs); + } + ~Imp() + { + system->unregisterSelectionNode(sel_assocobjs_click); + sel_assocobjs_click->unref(); + sel_assocobjs->unref(); + eventRoot->unref(); + } + + AscObjSelectionManager * theclass; + SoSeparator* eventRoot; + IVP13DSystem * system; + TrackSystemController*controller; + MODE mode; + SoCooperativeSelection * sel_assocobjs_click; + SoCooperativeSelection * sel_assocobjs; + + std::map<SoSeparator*,AssociatedObjectHandleBase*> ascobjs_simpleToHandle; + std::map<SoSeparator*,AssociatedObjectHandleBase*> ascobjs_detailedToHandle; + +// bool ascObjHandleFixSelectionPath(AssociatedObjectHandleBase*,SoPath*); + AssociatedObjectHandleBase* ascObjHandle(const SoPath*); + AssociatedObjectHandleBase* ascObjHandle(const SoSeparator*); + QList<AssociatedObjectHandleBase*> selAscObjHandles; + + void updateSelectionVisuals(); + static bool shiftIsDown() { return Qt::ShiftModifier & QApplication::keyboardModifiers(); } + +}; + + + +//____________________________________________________________________ +AscObjSelectionManager::AscObjSelectionManager(SoSeparator* event_root,IVP13DSystem * sys,TrackSystemController*controller) + : QObject(sys), VP1HelperClassBase(sys,"AscObjSelectionManager"), m_d(new Imp(this,event_root,sys,controller)) +{ + connect(controller,SIGNAL(assocObjDetailLevelChanged(TrackCommonFlags::DETAILLEVEL)),this,SLOT(ascObjDetailLevelChanged())); + ascObjDetailLevelChanged(); +} + +//____________________________________________________________________ +void AscObjSelectionManager::aboutTodelete() +{ + //fixme: clear maps and emit signals! +} + +//____________________________________________________________________ +AscObjSelectionManager::~AscObjSelectionManager() +{ + //Fixme: sanity check that maps are cleared. + delete m_d; +} + +//____________________________________________________________________ +QString AscObjSelectionManager::toString(MODE m) const +{ + if (m==SINGLE) return "SINGLE"; + else if (m==TOGGLE) return "TOGGLE"; + else if (m==SHIFT) return "SHIFT"; + else return "UNKNOWN(ERROR)"; +} + +//____________________________________________________________________ +AscObjSelectionManager::MODE AscObjSelectionManager::mode() const +{ + return m_d->mode; +} + +//____________________________________________________________________ +void AscObjSelectionManager::setMode(MODE m) +{ + if (m_d->mode==m) + return; + message("Mode changed to "+toString(m)); + m_d->mode=m; +} + + +//____________________________________________________________________ +SoSeparator * AscObjSelectionManager::getAscObjAttachSep() const +{ + return m_d->sel_assocobjs_click; +} +//____________________________________________________________________ +void AscObjSelectionManager::registerAscObj(SoSeparator*simple,SoSeparator *detailed,AssociatedObjectHandleBase*handle) +{ + if (VP1Msg::verbose()) { + if (!simple||!detailed||!handle) { + message("registerAscObj ERROR: Received null pointer!"); + return; + } + std::map<SoSeparator*,AssociatedObjectHandleBase*>::iterator it, itE; + itE = m_d->ascobjs_simpleToHandle.end(); + for (it=m_d->ascobjs_simpleToHandle.begin();it!=itE;++it) { + if (it->first==simple||it->second==handle) + message("registerAscObj ERROR: Simple separator/handle already registered!"); + } + itE = m_d->ascobjs_detailedToHandle.end(); + for (it=m_d->ascobjs_detailedToHandle.begin();it!=itE;++it) { + if (it->first==detailed||it->second==handle) + message("registerAscObj ERROR: Detailed separator/handle already registered!"); + } + } + m_d->ascobjs_simpleToHandle[simple]=handle; + m_d->ascobjs_detailedToHandle[detailed]=handle; +} + +//____________________________________________________________________ +void AscObjSelectionManager::unregisterAscObj(SoSeparator*simple,SoSeparator *detailed) +{ + if (VP1Msg::verbose()) { + if (!simple||!detailed) { + message("unregisterAscObj ERROR: Received null pointer!"); + return; + } + } + std::map<SoSeparator*,AssociatedObjectHandleBase*>::iterator itSimple = m_d->ascobjs_simpleToHandle.find(simple); + if (itSimple==m_d->ascobjs_simpleToHandle.end()) { + message("unregisterAscObj ERROR: Not previously registered simple sep!"); + } else { + m_d->ascobjs_simpleToHandle.erase(itSimple); + } + std::map<SoSeparator*,AssociatedObjectHandleBase*>::iterator itDetailed = m_d->ascobjs_detailedToHandle.find(detailed); + if (itDetailed==m_d->ascobjs_detailedToHandle.end()) { + message("unregisterAscObj ERROR: Not previously registered detailed sep!"); + } else { + m_d->ascobjs_detailedToHandle.erase(itDetailed); + } +} + +//____________________________________________________________________ +AssociatedObjectHandleBase* AscObjSelectionManager::Imp::ascObjHandle(const SoPath*path) +{ + const int n(path?path->getLength():0); + AssociatedObjectHandleBase * handle(0); + for (int i = 0; i < n; ++i) { + if (path->getNodeFromTail(i)->getTypeId()==SoSeparator::getClassTypeId()) { + handle = ascObjHandle(static_cast<SoSeparator*>(path->getNodeFromTail(i))); + if (handle) + return handle; + } + } + return 0; +} + +//____________________________________________________________________ +AssociatedObjectHandleBase* AscObjSelectionManager::Imp::ascObjHandle(const SoSeparator*s) +{ + std::map<SoSeparator*,AssociatedObjectHandleBase*>::const_iterator + it(ascobjs_simpleToHandle.find(const_cast<SoSeparator*>(s))); + if (it!=ascobjs_simpleToHandle.end()) + return it->second; + it = ascobjs_detailedToHandle.find(const_cast<SoSeparator*>(s)); + return it==ascobjs_detailedToHandle.end() ? 0 : it->second; +} + +//____________________________________________________________________ +void AscObjSelectionManager::Imp::updateSelectionVisuals() +{ + const bool isSimpleMode = controller->assocObjDetailLevel()==TrackCommonFlags::SIMPLE; + sel_assocobjs->deselectAll(); + foreach (AssociatedObjectHandleBase* handle,selAscObjHandles) { + SoPath * path = new SoPath(sel_assocobjs); + path->ref(); + if (!VP1QtInventorUtils::changePathTail(path,sel_assocobjs, + (isSimpleMode?handle->shapeSimple():handle->shapeDetailed()))) { + theclass->message("updateSelectionVisuals ERROR: Failed to relocate picked node."); + path->unref(); + continue; + } + sel_assocobjs->select(path); + path->unref(); + } +} + + +//____________________________________________________________________ +bool AscObjSelectionManager::handleUserSelectedSingleNode( SoCooperativeSelection* sel, SoNode*, SoPath* pickedPath, AssociatedObjectHandleBase*& pickedHandle ) +{ + messageVerbose("handleUserSelectedSingleNode"); + pickedHandle = 0; + if (sel==m_d->sel_assocobjs) { + messageVerbose(" => ignore selections for m_d->sel_assocobjs"); + return true;//We simply ignore those + } + if (sel!=m_d->sel_assocobjs_click) { + messageVerbose(" => We don't handle this selection."); + return false; + } + + AssociatedObjectHandleBase* handle = m_d->ascObjHandle(pickedPath); + m_d->sel_assocobjs_click->deselectAll(); + if (!handle) { + message("ERROR: Unknown associated object."); + return true; + } + messageVerbose(" => Found handle. Mode is "+toString(m_d->mode)+", and number of previously selected handles is "+str(m_d->selAscObjHandles.count())); + pickedHandle = handle; + pretendUserClicked(handle);//we are not really pretending in this case of course... + return true; +} + +//____________________________________________________________________ +void AscObjSelectionManager::pretendUserClicked(AssociatedObjectHandleBase*handle) +{ + assert(handle); + if (!handle) + return; + const bool alreadyselected = m_d->selAscObjHandles.contains(handle); + qSort(m_d->selAscObjHandles); + QList<AssociatedObjectHandleBase*> selHandlesBefore = m_d->selAscObjHandles; + + if (m_d->mode==SINGLE) { + if (m_d->selAscObjHandles.isEmpty()) { + //Add handle to selection. + m_d->selAscObjHandles << handle; + if (m_d->controller->printInfoOnSingleSelection()) + m_d->system->message(handle->clicked()); + } else { + //Clear selection. + m_d->selAscObjHandles.clear(); + //Add if not already selected: + if (!alreadyselected) { + m_d->selAscObjHandles << handle; + if (m_d->controller->printInfoOnSingleSelection()) + m_d->system->message(handle->clicked()); + } + } + } else if (m_d->mode==SHIFT) { + if (Imp::shiftIsDown()) { + if (alreadyselected) + m_d->selAscObjHandles.removeAll(handle); + else + m_d->selAscObjHandles << handle; + } else { + m_d->selAscObjHandles.clear(); + if (!alreadyselected) + m_d->selAscObjHandles << handle; + } + } else if (m_d->mode==TOGGLE) { + if (alreadyselected) { + m_d->selAscObjHandles.removeAll(handle); + } else { + m_d->selAscObjHandles << handle; + } + } else { + message("ERROR: Should not happen!"); + deselectAll(); + return; + } + qSort(m_d->selAscObjHandles); + + if (selHandlesBefore!=m_d->selAscObjHandles) { + m_d->updateSelectionVisuals(); + currentSelectionChanged(m_d->selAscObjHandles); + } +} + + +//____________________________________________________________________ +void AscObjSelectionManager::userClickedOnBgd() +{ + if (m_d->mode==TOGGLE) + return; + if (m_d->mode==SHIFT&&Imp::shiftIsDown()) + return; + deselectAll(); +} + +//____________________________________________________________________ +void AscObjSelectionManager::deselectAll() +{ + if (m_d->selAscObjHandles.isEmpty()) + return; + m_d->selAscObjHandles.clear(); + currentSelectionChanged(m_d->selAscObjHandles); + m_d->updateSelectionVisuals(); +} + +//____________________________________________________________________ +void AscObjSelectionManager::ensureDeselected(const QList<AssociatedObjectHandleBase*>& handles) +{ + if (handles.isEmpty()) + return; + QList<AssociatedObjectHandleBase*> selHandlesBefore = m_d->selAscObjHandles; + foreach (AssociatedObjectHandleBase*handle,handles) + m_d->selAscObjHandles.removeAll(handle); + if (selHandlesBefore!=m_d->selAscObjHandles) { + m_d->updateSelectionVisuals(); + currentSelectionChanged(m_d->selAscObjHandles); + } +} + +//____________________________________________________________________ +void AscObjSelectionManager::ensureSelected(const QList<AssociatedObjectHandleBase*>& handles) +{ + if (handles.isEmpty()) + return; + if (m_d->mode==SINGLE) { + //Single selections + if (handles.count()>1) + message("WARNING: ensureSelected called with more than one handle in SINGLE mode. Ignoring all but the first."); + if (m_d->selAscObjHandles.contains(handles.at(0))) + return; + m_d->selAscObjHandles.clear(); + m_d->selAscObjHandles << handles.at(0); + currentSelectionChanged(m_d->selAscObjHandles); + m_d->updateSelectionVisuals(); + } else { + //Multi selections allowed + QList<AssociatedObjectHandleBase*> selHandlesBefore = m_d->selAscObjHandles; + foreach (AssociatedObjectHandleBase*handle,handles) { + if (!m_d->selAscObjHandles.contains(handle)) + m_d->selAscObjHandles << handle; + } + qSort(m_d->selAscObjHandles); + if (selHandlesBefore!=m_d->selAscObjHandles) { + m_d->updateSelectionVisuals(); + currentSelectionChanged(m_d->selAscObjHandles); + } + } + +} + +//____________________________________________________________________ +void AscObjSelectionManager::ascObjDetailLevelChanged() +{ + messageVerbose("Signal received in ascObjDetailLevelChanged slot"); + if (m_d->selAscObjHandles.isEmpty()) { + m_d->sel_assocobjs->deselectAll(); + return; + } + const SoPathList * pathlist = m_d->sel_assocobjs->getList(); + if (!pathlist||pathlist->getLength()!=m_d->selAscObjHandles.count()) + return; + + const bool isSimpleMode = (m_d->controller->assocObjDetailLevel()==TrackCommonFlags::SIMPLE); + int i(0); + foreach (AssociatedObjectHandleBase* handle,m_d->selAscObjHandles) { + SoPath * path = (*pathlist)[i++]; + if (!path) + continue; + if (!VP1QtInventorUtils::changePathTail(path,m_d->sel_assocobjs, + (isSimpleMode?handle->shapeSimple():handle->shapeDetailed()))) { + message("Warning: Failed to relocate picked node."); + deselectAll(); + return; + } + } +} + +//____________________________________________________________________ +QList<AssociatedObjectHandleBase*> AscObjSelectionManager::currentSelection() const +{ + return m_d->selAscObjHandles; +} + +SoSeparator* AscObjSelectionManager::eventRoot() +{ + return m_d->eventRoot; +} diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/AscObj_TSOS.cxx b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/AscObj_TSOS.cxx new file mode 100644 index 000000000..7e96708b1 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/AscObj_TSOS.cxx @@ -0,0 +1,1107 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class AscObj_TSOS // +// // +// Author: Troels Kofoed Jacobsen // +// Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: June 2008 // +// // +//////////////////////////////////////////////////////////////// + +//Surface from materialeffects. + +//Troels todo: +// projections (not right away) + +//Thomas todo: +// print truth info (get rid of truth points) +// Notify when path changes. +// +// Fixme: shared objects? Or cache scene parts for faster updating?? + +#include "VTI12TrackSystems/AscObj_TSOS.h" +#include "VTI12TrackSystems/VP1TrackSystem.h" +#include "VTI12TrackSystems/TrackSysCommonData.h" +#include "VTI12TrackSystems/TrackHandleBase.h" +#include "VTI12TrackSystems/TrackSystemController.h" +#include "VTI12TrackSystems/AscObjSelectionManager.h" +#include "VTI12TrackSystems/TrkObjToString.h" + +#include "VP1Base/VP1Msg.h" +#include "VP1Base/VP1CameraHelper.h" +#include "VP1Base/IVP13DSystem.h" +#include "VP1Base/VP1QtInventorUtils.h" +#include "VP1Base/VP1QtUtils.h" +#include "VTI12Utils/SurfaceToSoNode.h" +#include "VTI12Utils/VP1LinAlgUtils.h" +#include "VTI12Utils/VP1ErrorUtils.h" +#include "VTI12Utils/VP1DetInfo.h" +#include "VP1HEPVis/nodes/SoTransparency.h" + +#include "FaserDetDescr/FaserDetectorID.h" + +// #include "TrkEventPrimitives/DriftCircleSide.h" +// #include "TrkEventPrimitives/DriftCircleStatus.h" + + +#include "TrkSurfaces/CylinderSurface.h" +#include "TrkSurfaces/DiscSurface.h" +#include "TrkSurfaces/PerigeeSurface.h" +#include "TrkSurfaces/PlaneSurface.h" +#include "TrkSurfaces/StraightLineSurface.h" +#include "TrkMaterialOnTrack/MaterialEffectsBase.h" +#include "TrkMaterialOnTrack/EstimatedBremOnTrack.h" +#include "TrkMaterialOnTrack/MaterialEffectsOnTrack.h" +#include "TrkMaterialOnTrack/EnergyLoss.h" +#include "TrkMaterialOnTrack/ScatteringAngles.h" +#include "TrkTrack/TrackStateOnSurface.h" + +#include "TrkParameters/TrackParameters.h" + +#include "TrkMeasurementBase/MeasurementBase.h" +#include "TrkRIO_OnTrack/RIO_OnTrack.h" +// #include "InDetRIO_OnTrack/TRT_DriftCircleOnTrack.h" +#include "TrkCompetingRIOsOnTrack/CompetingRIOsOnTrack.h" + +#include <Inventor/nodes/SoLineSet.h> +#include <Inventor/nodes/SoSeparator.h> +#include <Inventor/nodes/SoVertexProperty.h> +#include <Inventor/nodes/SoPointSet.h> +#include <Inventor/nodes/SoCamera.h> +#include <Inventor/nodes/SoCylinder.h> +#include <Inventor/nodes/SoMaterial.h> +#include <Inventor/nodes/SoRotationXYZ.h> +#include <Inventor/nodes/SoTransform.h> +#include <Inventor/nodes/SoTranslation.h> +#include <Inventor/nodes/SoSphere.h> + +#include <set> + +#include "EventPrimitives/EventPrimitivesToStringConverter.h" +#include "GeoPrimitives/GeoPrimitivesToStringConverter.h" + +//____________________________________________________________________ +AscObj_TSOS::AscObj_TSOS( TrackHandleBase *track, + const Trk::TrackStateOnSurface * tsos, + unsigned indexOfPointOnTrack ) + : AssociatedObjectHandleBase(track), m_tsos(tsos), + m_parts(TrackCommonFlags::TSOS_NoObjects), + m_indexOfPointOnTrack(indexOfPointOnTrack), + m_distToNextPar(-1), + m_objBrowseTree(0) +{ + SoTransparency::initClass(); + + const Trk::Surface * surf(0); + + if (m_tsos->type(Trk::TrackStateOnSurface::Hole)) m_parts |= TrackCommonFlags::TSOS_Hole; + + if (m_tsos->trackParameters()) { + m_parts |= TrackCommonFlags::TSOS_TrackPars; + if (dynamic_cast<const Trk::TrackParameters *>(m_tsos->trackParameters())) { + if (m_tsos->type(Trk::TrackStateOnSurface::Perigee)) { + m_parts |= TrackCommonFlags::TSOS_TrackParsErrorsPerigee; + } + else { + m_parts |= TrackCommonFlags::TSOS_TrackParsErrorsNotPerigee; + } + } + surf = &(m_tsos->trackParameters()->associatedSurface()); + } + + if (measurement()) { + m_parts |= TrackCommonFlags::TSOS_MeasError; + if (rioOnTrack()) { + if (m_tsos->type(Trk::TrackStateOnSurface::Outlier)) + m_parts |= TrackCommonFlags::TSOS_MeasRioOnTrackOutlier; + else + m_parts |= TrackCommonFlags::TSOS_MeasRioOnTrackNotOutlier; + } else if (competingRIOsOnTrack()) { + if (m_tsos->type(Trk::TrackStateOnSurface::Outlier)) + m_parts |= TrackCommonFlags::TSOS_MeasCompetingRioOnTrackOutlier; + else + m_parts |= TrackCommonFlags::TSOS_MeasCompetingRioOnTrackNotOutlier; + } else + VP1Msg::messageDebug("Warning: Ignoring measurement which is not a (competing) rio on track."); + if (!surf) surf = &(measurement()->associatedSurface()); + } + const Trk::MaterialEffectsBase* matEff = m_tsos->materialEffectsOnTrack(); + if (matEff) { + const Trk::MaterialEffectsOnTrack * meot = dynamic_cast<const Trk::MaterialEffectsOnTrack * >(matEff); + if (meot) { + if (meot->energyLoss()&&meot->energyLoss()->deltaE()!=0) + m_parts |= TrackCommonFlags::TSOS_MaterialEffects; + else + m_parts |= TrackCommonFlags::TSOS_MaterialEffectsWithNoDeltaE; + } else { + if (dynamic_cast<const Trk::EstimatedBremOnTrack * >(matEff)) + VP1Msg::messageDebug("Warning: Ignoring EstimatedBremOnTrack."); + else + VP1Msg::messageDebug("Warning: Ignoring material effect which is not MaterialEffectsOnTrack."); + } + if (!surf) + surf = &(matEff->associatedSurface()); + } + if (surf) { + if (surf->associatedDetectorElement()) + m_parts |= TrackCommonFlags::TSOS_SurfacesDetElem; + else + m_parts |= TrackCommonFlags::TSOS_SurfacesCustom; + + } +} + +//____________________________________________________________________ +void AscObj_TSOS::setDistToNextPar(const double& d) +{ + //We assume this is called right after the constructor - so no need + //to update 3D objects. + m_distToNextPar = d; +} + +//____________________________________________________________________ +Amg::Vector3D AscObj_TSOS::approxCenter() const +{ + if (hasParameters()) + return m_tsos->trackParameters()->position(); + if (hasSurface()) + return surface()->center(); + VP1Msg::message("AscObj_TSOS::approxCenter() WARNING: Failed to determine" + " position from either params or surface"); + return Amg::Vector3D(0,0,0); +} + +//____________________________________________________________________ +int AscObj_TSOS::regionIndex() const +{ + Amg::Vector3D c = approxCenter(); + static const double l=30.0*CLHEP::cm; + return static_cast<int>(c.z()/l) + +1000*static_cast<int>(c.y()/l) + +1000000*static_cast<int>(c.x()/l); +} + +//____________________________________________________________________ +const Trk::MeasurementBase * AscObj_TSOS::measurement() const +{ + return m_tsos->measurementOnTrack(); +} + +//____________________________________________________________________ +SoTranslation* AscObj_TSOS::getZTranslationTube( const Trk::Surface * theSurface, + const double& maxTrans ) const +{ + const Amg::Vector3D* origo = theSurface->localToGlobal(Amg::Vector2D(0,0)); + const Amg::Vector3D* unitz = theSurface->localToGlobal(Amg::Vector2D(0,1)); + + std::vector< Amg::Vector3D > * points = trackHandle()->hackGetPointsPropagated();//FIXME + + double min = std::numeric_limits<double>::max(); + double smin=0; + size_t imin=0; + //First we find the point in PointsPropageted closest to the line. + for ( size_t i = 0; i<points->size(); i++) + { + double s; + double dist = VP1LinAlgUtils::distPointLine2( (*points)[i], *origo, *unitz, s ); + if (dist < min) + { + min = dist; + imin = i; + } + } + + if (points->size()>1 ){ + // FIXME - don't think we should ever really need this test. EJWM. + + //Then we get the parameters on the forward and backward lines giving the points with + //the shortest distances. + //We then use the line which has the parameter closest to 0.5 which means that it + //is inside the part of the line between this point and the next/previous + double sp,tp,sm,tm; + if (imin+1 < points->size() && imin >= 1) + { + VP1LinAlgUtils::distLineLineParam((*points).at(imin),(*points).at(imin+1),*origo,*unitz,tp,sp); + VP1LinAlgUtils::distLineLineParam((*points).at(imin-1),(*points).at(imin),*origo,*unitz,tm,sm); + smin = fabs(tm - 0.5) < fabs(tp - 0.5) ? sm : sp; + } else if (imin+1 >= points->size() && imin >= 1 ) + { + VP1LinAlgUtils::distLineLineParam((*points).at(imin-1),(*points).at(imin),*origo,*unitz,tm,sm); + smin = sm; + } else + { + VP1LinAlgUtils::distLineLineParam((*points).at(imin),(*points).at(imin+1),*origo,*unitz,tp,sp); + smin = sp; + } + } else { + // probably something is wrong! + VP1Msg::message("AscObj_TSOS::getZTranslationTube: <2 points returned by trackHandle!"); + } + + //Ensure that we do not get out of bounds, preserve sign of translation. + if (fabs(smin) > maxTrans) + { + double sign = smin > 0 ? 1.0 : -1.0; + smin = sign*maxTrans; + } + + SoTranslation * trans = new SoTranslation; + trans->translation.setValue(0,0,smin); + + return trans; +} + +double AscObj_TSOS::deviationFromMeasurement(const bool& absolute) +{ + double rioValue = 0; + double paramValue = 0; + double sigma = 1; + + const Trk::RIO_OnTrack* rio = rioOnTrack(); + if (!rio && competingRIOsOnTrack()!=0 ) { + // must be crot + rio = &(competingRIOsOnTrack()->rioOnTrack(competingRIOsOnTrack()->indexOfMaxAssignProb () )); + } else { + VP1Msg::message(" No ROT or cROT in AscObj_TSOS::deviationFromMeasurement(const bool& absolute)!"); + return 0.0; + } + return absolute ? fabs( rioValue - paramValue ) : fabs( rioValue - paramValue )/sigma; +} + +//____________________________________________________________________ +void AscObj_TSOS::addTrackParamInfoToShapes( SoSeparator*&shape_simple, + SoSeparator*&shape_detailed, + bool showPars, bool showParsErrors, bool showSurfaces) +{ + const Trk::TrackParameters* trackParams = m_tsos->trackParameters(); + Q_ASSERT(trackParams); + ensureInitSeps(shape_simple,shape_detailed); + + Amg::Vector3D p1(trackParams->position());//point + + if (showPars) { + +// Trk::GlobalMomentum u(trackParams->momentum().unit());//mom direction + Amg::Vector3D u(trackParams->momentum().unit());//mom direction + + double length = 5*CLHEP::cm; + if (m_distToNextPar>0) + length = std::min(m_distToNextPar*0.75,length); + Amg::Vector3D p2 = p1+length*u; + + //Line: + SoLineSet * line = new SoLineSet(); + SoVertexProperty * vertices = new SoVertexProperty(); + vertices->vertex.set1Value(0,p1.x(),p1.y(),p1.z()); + vertices->vertex.set1Value(1,p2.x(),p2.y(),p2.z()); + line->numVertices.set1Value(0,2); + + //Point: + SoPointSet * points = new SoPointSet; + SoVertexProperty * vertices2 = new SoVertexProperty; + vertices2->vertex.set1Value(0,p1.x(),p1.y(),p1.z()); + points->numPoints=1; + line->vertexProperty = vertices; + points->vertexProperty = vertices2; + + bool isHole= m_parts & TrackCommonFlags::TSOS_Hole; + if (trackHandle()->customColouredTSOSParts()&TrackCommonFlags::TSOS_TrackPars + || (isHole&&(trackHandle()->customColouredTSOSParts() & TrackCommonFlags::TSOS_Hole) ) ) { + SoMaterial * mat = isHole?common()->controller()->customMatHoleParameters():common()->controller()->customMatParameters(); + SoSeparator * sep = new SoSeparator; + sep->addChild(mat); + sep->addChild(line); + sep->addChild(points); + shape_simple->addChild(sep); + shape_detailed->addChild(sep); + } else { + shape_simple->addChild(line); + shape_simple->addChild(points); + shape_detailed->addChild(line); + shape_detailed->addChild(points); + } + } + + if ( showParsErrors ){ + SoTransform* theHitTransform = VP1LinAlgUtils::toSoTransform(surface()->transform()); // FIXME - remove if working in local coords + shape_detailed->addChild(theHitTransform); + // Need to cast in order to get error Matrix + if (trackParams->covariance()) // Only draw error if point is a measurement + { + // fixme! This is really ugly - can't be cast to a base class? MeasuredTrackParameters doesn't know LP. + const Trk::AtaStraightLine * atas = dynamic_cast<const Trk::AtaStraightLine *>(trackParams); + const Trk::Perigee * per = dynamic_cast<const Trk::Perigee *>(trackParams); + const Trk::AtaPlane * aap = dynamic_cast<const Trk::AtaPlane *>(trackParams); + const Trk::AtaDisc * aad = dynamic_cast<const Trk::AtaDisc *>(trackParams); + if (per||atas||aap||aad){ + const Amg::Vector2D& localPos = atas ? atas->localPosition() : (per ? per->localPosition() : (aap ? aap->localPosition() : aad->localPosition())); +// addErrors(*(trackParams->associatedSurface()), meas->localErrorMatrix().covariance(), localPos, p1, showSurfaces, shape_simple, shape_detailed, false, false); //FIXME - last parameter false when working in correct local coords + addErrors(trackParams->associatedSurface(), *trackParams->covariance(), localPos, p1, showSurfaces, shape_simple, shape_detailed, false, false); //FIXME - last parameter false when working in correct local coords + } else { + VP1Msg::messageVerbose("Not a supported parameter for errors: "); + // std::cout<<(*trackParams)<<std::endl; + } + } + } +} + +void AscObj_TSOS::addErrors(const Trk::Surface& theSurface, const AmgSymMatrix(5)& tmpCovMat, + const Amg::Vector2D& localPos, const Amg::Vector3D& p1, bool showSurfaces, SoSeparator* shape_simple, SoSeparator* shape_detailed, bool force1D, bool applyLocalTrans ) +{ + VP1Msg::messageVerbose("addErrors"); + if (applyLocalTrans) VP1Msg::messageVerbose("applyLocalTrans"); + + //Fixme: get from collhandle:!! + const bool settingsDRAWCYLINDER = common()->controller()->parTubeErrorsDrawCylinders(); + const bool settingsDRAWZERRCIRCLES = settingsDRAWCYLINDER; + const double settingsSIGMASCALE = common()->controller()->nStdDevForParamErrors(); + + SoSeparator * errSimple = new SoSeparator; + SoSeparator * errDetailed = new SoSeparator; + + //Possibly a custom colour + if (trackHandle()->customColouredTSOSParts()&TrackCommonFlags::TSOS_AnyParsErrors) { + // FIXME - what about meas errors? + SoMaterial * mat = common()->controller()->customMatParameterErrors(); + errSimple->addChild( mat ); + errDetailed->addChild( mat ); + } + // SoTransparency * transparent = new SoTransparency; + // transparent->transparency.setValue(0.5); + // errSimple->addChild( transparent ); + // errDetailed->addChild( transparent ); + + const int npoints = common()->controller()->numberOfPointsOnCircles(); + // Check for type of associated surface + // const Trk::Surface * theSurface = trackParams->associatedSurface(); + const Trk::CylinderSurface * cylSurf = dynamic_cast<const Trk::CylinderSurface *>(&theSurface); + const Trk::DiscSurface * disSurf = dynamic_cast<const Trk::DiscSurface *>(&theSurface); + const Trk::PerigeeSurface * perSurf = dynamic_cast<const Trk::PerigeeSurface *>(&theSurface); + const Trk::PlaneSurface * plaSurf = dynamic_cast<const Trk::PlaneSurface *>(&theSurface); + const Trk::StraightLineSurface * strSurf = dynamic_cast<const Trk::StraightLineSurface *>(&theSurface); + if ( plaSurf ) /* Plane Surface */ + { + // Shift from Surface centre to correct position + if (applyLocalTrans) { + SoTranslation * theTransform = new SoTranslation; + const Amg::Vector2D* locPosTmp = surface()->globalToLocal(p1); + if (locPosTmp) { + theTransform->translation.setValue(locPosTmp->x(),locPosTmp->y(),0.0); + // std::cout<<"applyLocalTrans & Offset=("<<locPosTmp->x()<<","<<locPosTmp->y()<<std::endl; + errSimple->addChild(theTransform); + errDetailed->addChild(theTransform); + delete locPosTmp; + } else { + VP1Msg::message("AscObj_TSOS::addErrors - failed to get tmp position"); + } + } + + VP1Msg::messageVerbose("Plane surf error of size:"+QString::number(tmpCovMat.rows())); + if (force1D) VP1Msg::messageVerbose("Forcing 1D"); + VP1ErrorUtils::errorAtPlaneSurface(errSimple, errDetailed, tmpCovMat, &theSurface, p1, settingsSIGMASCALE, npoints, showSurfaces, force1D, false ); + ensureInitSeps(shape_simple,shape_detailed); + shape_simple->addChild( errSimple ); + shape_detailed->addChild( errDetailed ); + } else if ( strSurf || perSurf) { + /* Straight Line Surface or perigee surface*/ + // Shift from Surface centre to correct position + if (applyLocalTrans){ + SoTranslation * theTransform = getZTranslationTube(&theSurface,10000.0); + errSimple->addChild(theTransform); + errDetailed->addChild(theTransform); + } + VP1ErrorUtils::errorAtStraightLineSurface(errSimple, errDetailed, tmpCovMat, localPos, &theSurface, settingsSIGMASCALE, settingsDRAWZERRCIRCLES, settingsDRAWCYLINDER, npoints, force1D, false); + ensureInitSeps(shape_simple,shape_detailed); + shape_simple->addChild( errSimple ); + shape_detailed->addChild( errDetailed ); + } else if ( cylSurf ) { + VP1Msg::message("WARNING: Visualisation of errors on Cylinder Surface not implemented"); + } else if ( disSurf ) { + VP1Msg::message("WARNING: Visualisation of errors on Disc Surface not implemented"); + } + VP1Msg::messageVerbose("leaving addErrors"); + + return; +} + +//____________________________________________________________________ +void AscObj_TSOS::addSurfaceToShapes( SoSeparator*&shape_simple, SoSeparator*&shape_detailed) +{ + // static int ignoreTubes=-1; + // if (ignoreTubes==-1) + // ignoreTubes = VP1QtUtils::environmentVariableIsOn("VP1_TRKSYS_NEVERSHOWTUBESURFACES") ? 1 : 0; + + if (common()->controller()->hideTubeSurfaces() &&dynamic_cast<const Trk::StraightLineSurface*>(surface())) + return; + + SurfaceToSoNode surfCnv;//fixme: check if need in common() + SoNode* theSurfSepSimple = surfCnv.translateSurface(*(surface()),true); + SoNode* theSurfSep = surfCnv.translateSurface(*(surface())); + if (theSurfSep) { + SoNode * nodeToAddSimple = theSurfSepSimple; + SoNode * nodeToAdd = theSurfSep; + ensureInitSeps(shape_simple,shape_detailed); + if (trackHandle()->customColouredTSOSParts()&TrackCommonFlags::TSOS_AnySurface) { + SoMaterial * mat = common()->controller()->customMatSurfaces(); + if (theSurfSep->getTypeId().isDerivedFrom(SoSeparator::getClassTypeId())) { + static_cast<SoSeparator*>(theSurfSepSimple)->insertChild(mat,0); + static_cast<SoSeparator*>(theSurfSep)->insertChild(mat,0); + } else { + SoSeparator * sepSimple = new SoSeparator; + sepSimple->addChild(mat); + sepSimple->addChild(theSurfSepSimple); + nodeToAddSimple = sepSimple; + SoSeparator * sep = new SoSeparator; + sep->addChild(mat); + sep->addChild(theSurfSep); + nodeToAdd = sep; + } + } +// shape_simple->addChild(nodeToAdd); //todo: check this. I changed nodeToAdd to nodeToAddSimple + shape_simple->addChild(nodeToAddSimple); + shape_detailed->addChild(nodeToAdd); + } else { + VP1Msg::message("AscObj_TSOS::addSurfaceToShapes WARNING: Got null shape."); + } +} + +//____________________________________________________________________ +void AscObj_TSOS::addMaterialEffectsToShapes( SoSeparator*&shape_simple, SoSeparator*&shape_detailed) +{ + const double settingsForceOnTrack = false; + + ensureInitSeps(shape_simple,shape_detailed); + SoSeparator * matSepSimple = new SoSeparator; + SoSeparator * matSepDetailed = new SoSeparator; + + //1) Transformation. + + if (m_tsos->trackParameters()) { + //Put on position of track parameter + Amg::Vector3D p1(m_tsos->trackParameters()->position());//point + SoTranslation * theTransform = new SoTranslation; + theTransform->translation.setValue(p1.x(),p1.y(),p1.z()); + matSepSimple->addChild(theTransform); + matSepDetailed->addChild(theTransform); + } else { + const Trk::Surface * surf = surface(); + if (!surf) { + VP1Msg::message("AscObj_TSOS::addMaterialEffectsToShapes WARNING: Has neither surface or parameter to get position!"); + } else { + if (settingsForceOnTrack) { + VP1Msg::message("AscObj_TSOS::addMaterialEffectsToShapes WARNING: settingsForceOnTrack not implemented"); + + //Take position from surface and somehow constrain it onto the line. + //(Fixme... same kind of treatment as in the "short tubes"... how?). + } else { + //Take center of surface if present. + SoTransform * theTransform = VP1LinAlgUtils::toSoTransform(surf->transform()); + matSepSimple->addChild(theTransform); + matSepDetailed->addChild(theTransform); + } + } + } + //2) Possibly a custom colour + + if (trackHandle()->customColouredTSOSParts()&TrackCommonFlags::TSOS_AnyMaterialEffects) { + SoMaterial * mat = common()->controller()->customMatMaterialEffects(); + matSepSimple->addChild(mat); + matSepDetailed->addChild(mat); + } + + //3) The shape + + SoPointSet * point = common()->singlePoint(); + matSepSimple->addChild(point); + + if (m_parts & TrackCommonFlags::TSOS_MaterialEffectsWithNoDeltaE) { + matSepDetailed->addChild(point); + } else { + const Trk::MaterialEffectsBase* matEff = m_tsos->materialEffectsOnTrack(); + const Trk::MaterialEffectsOnTrack* matEffOnTrk = dynamic_cast<const Trk::MaterialEffectsOnTrack*>(matEff); + if (matEffOnTrk){ + const double absDeltaE = fabs(matEffOnTrk->energyLoss()->deltaE()); + const double radius(absDeltaE > 1*CLHEP::eV ? 5.0*exp(log(absDeltaE/CLHEP::MeV)/3.0) : 0);//\propto cube root + //TK: radius used to be: 5.0*sqrt(absDE), but we want sphere volume \propto deltaE + const double scale = common()->controller()->materialEffectsOnTrackScale(); + if (scale * radius > 0.1) { + SoSphere * meotSphere = new SoSphere; + meotSphere->radius.setValue( scale * radius ); + matSepDetailed->addChild(meotSphere); + } else { + matSepDetailed->addChild(point); + } + } + } + + //Attach: + shape_simple->addChild(matSepSimple); + shape_detailed->addChild(matSepDetailed); +} + +//____________________________________________________________________ +void AscObj_TSOS::addRIO_OnTrackInfoToShapes( SoSeparator*&shape_simple, + SoSeparator*&shape_detailed, + const Trk::RIO_OnTrack* rio, bool blockDrawingOfGP) +{ + // VP1Msg::messageVerbose("AscObj_TSOS::addRIO_OnTrackInfoToShapes() start"); + + if (!rio) { return;} +// Identifier id = rio->identify(); + + ensureInitSeps(shape_simple,shape_detailed); + + TrackCommonFlags::TSOSPartsFlags f(trackHandle()->shownTSOSParts()&m_parts); + const bool showMeas(f & TrackCommonFlags::TSOS_AnyMeasurement); + const bool showMeasErrors(f & TrackCommonFlags::TSOS_MeasError); + + // TrkObjToString::MeasurementType type = m_objToType.type(rio); + // std::cout<<">>>>>>>>>>> addRIO_OnTrackInfoToShapes: Have measurement of type: "<<static_cast<unsigned int>(type)<<" & showRioOnTrack="<<showMeas<<std::endl; + if (showMeas){ + // std::pair<SoSeparator*, std::vector<SoNode*> > detailed_nodes, simple_nodes; + // handle colouring + // VP1Msg::message(m_objToType.name(*rio)); + + if (m_parts & trackHandle()->customColouredTSOSParts()&TrackCommonFlags::TSOS_AnyMeasRioOnTrack) { + SoMaterial * mat; + if (m_parts & trackHandle()->customColouredTSOSParts()&TrackCommonFlags::TSOS_MeasRioOnTrackNotOutlier) + mat = common()->controller()->customMatMeasurements(); + else + mat = common()->controller()->customMatMeasurementsOutliers(); + shape_simple->addChild(mat); + shape_detailed->addChild(mat); + } + + m_hitToSoNode.buildStripShapes(*rio,shape_simple,shape_detailed,blockDrawingOfGP); // transforms to localPos (i.e. assumes in surface frame) + } + +//Errors + if (showMeasErrors){ + const Trk::LocalParameters & locParams = rio->localParameters () ; +// VP1Msg::message( "Trying to draw measurement errors for ROT with id="+QString::number(rio->identify().get_compact())+" locparams have dim="+QString::number(locParams.dimension())+", locellmat="+QString::number(rio->localErrorMatrix().covariance().num_row())); + VP1Msg::message( "Trying to draw measurement errors for ROT with id="+QString::number(rio->identify().get_compact())+" locparams have dim="+QString::number(locParams.dimension())+", locellmat="+QString::number(rio->localCovariance().rows())); + + Amg::Vector2D localPos; + /* + * see: + * https://svnweb.cern.ch/trac/atlasoff/browser/Tracking/TrkEvent/TrkEventPrimitives/trunk/TrkEventPrimitives/LocalParameters.h + * https://svnweb.cern.ch/trac/atlasoff/browser/Tracking/TrkEvent/TrkEventPrimitives/trunk/src/LocalParameters.cxx + */ + if (locParams.contains(Trk::loc1)) { + localPos( locParams.get(Trk::loc1), locParams.contains(Trk::loc2) ? locParams.get(Trk::loc2) : 0 ); + } else{ + VP1Msg::message( "WARNING: locParams.contains(Trk::loc1) is FALSE!!"); + } + + bool force1D=false; + if (locParams.dimension ()!=rio->localCovariance().rows()){ + VP1Msg::message( "WARNING: ROT has inconsistent dimensions between cov matrix and local parameters. Forcing to 1D."); + force1D=true; + } + force1D=true; //FIXME! + + // last parameter sets whether we do a local shift. + addErrors(rio->associatedSurface(), rio->localCovariance(), localPos, rio->globalPosition(), false, + shape_simple, shape_detailed, force1D, true); + VP1Msg::message( "Done with measurement errors"); + } +} + +//____________________________________________________________________ +void AscObj_TSOS::addCompetingRIO_OnTrackInfoToShapes( SoSeparator*&shape_simple, + SoSeparator*&shape_detailed) +{ + // std::cout<<"addCompetingRIO_OnTrackInfoToShapes"<<std::endl; + const Trk::CompetingRIOsOnTrack * crio = competingRIOsOnTrack(); + + ensureInitSeps(shape_simple,shape_detailed); + + //Possibly a custom colour + if (m_parts & trackHandle()->customColouredTSOSParts()&TrackCommonFlags::TSOS_MeasCompetingRioOnTrackNotOutlier) { + SoMaterial * mat = common()->controller()->customMatMeasurements(); + shape_simple->addChild(mat); + shape_detailed->addChild(mat); + } else if (m_parts & trackHandle()->customColouredTSOSParts()&TrackCommonFlags::TSOS_MeasCompetingRioOnTrackOutlier) { + SoMaterial * mat = common()->controller()->customMatMeasurementsOutliers(); + shape_simple->addChild(mat); + shape_detailed->addChild(mat); + } + + if (common()->controller()->drawMeasGlobalPositions()){ + // std::cout<<"cROT - showing globalpositions."<<std::endl; + + // if (surface()!=crio->rioOnTrack(crio->indexOfMaxAssignProb ())->associatedSurface()) + // VP1Msg::message("AscObj_TSOS::addCompetingRIO_OnTrackInfoToShapes WARNING: cROT surface doesn't match one from surface()") ; +//Draw cross marking global position of the rio on track + SoTranslation * theTransform = new SoTranslation; + Amg::Vector3D offset = crio->globalPosition() - crio->associatedSurface().center(); + // std::cout<<"globalPOS=("<<crio->globalPosition().x()<<","<<crio->globalPosition().y()<<","<<crio->globalPosition().z()<<")"<<std::endl; + // std::cout<<"associatedSurf centre =("<<crio->associatedSurface().center().x()<<","<<crio->associatedSurface().center().y()<<","<<crio->associatedSurface().center().z()<<")"<<std::endl; + // std::cout<<"offset=("<<offset.x()<<","<<offset.y()<<","<<offset.z()<<")"<<std::endl; + // theTransform->translation.setValue( offset.x(), offset.y(), offset.z()); + + + Amg::Vector3D locPos = (crio->associatedSurface().transform().rotation().inverse())*(offset); + theTransform->translation.setValue( locPos.x(), locPos.y(), locPos.z()); + // std::cout<<"the GP Transform=("<<locPos.x()<<","<<locPos.y()<<","<<locPos.z()<<")"<<std::endl; + + // double xoff= crio->localParameters().get(Trk::loc1); + // double yoff= crio->localParameters().get(Trk::loc2); + // double zoff= globalpos.z()-surface().center().z(); + // theTransform->translation.setValue(xoff,yoff,0.0); + // SoTranslation * theTransformBack = new SoTranslation; + // theTransformBack->translation.setValue(-locPos.x(), -locPos.y(), -locPos.z()); + // std::cout<<"theTransformBack="<<Amg::toString(*theTransformBack)<<std::endl; + + SoSeparator * gpSep = new SoSeparator; + + gpSep->addChild(theTransform); + gpSep->addChild(common()->nodeManager().getShapeNode_Cross(50)); + shape_detailed->addChild(gpSep); + } + + //Draw all contained rio on tracks + TrackCommonFlags::TSOSPartsFlags f(trackHandle()->shownTSOSParts()&m_parts); + const bool showcRioOnTrack(f & TrackCommonFlags::TSOS_AnyMeasurement); + + if (showcRioOnTrack){ + + // FIXME - shouldn't need to use so many seps, but having problems with transformations. + SoSeparator * rotSepSimple = new SoSeparator; + SoSeparator * rotSepDetailed = new SoSeparator; + + // std::cout<<"addCompetingRIO_OnTrackInfoToShapes: About to draw most probable ROT"<<std::endl; + unsigned int maxProb = crio->indexOfMaxAssignProb (); + // std::cout<<"Drawing maxProb ["<<maxProb<<"] strip "<<std::endl; + addRIO_OnTrackInfoToShapes(rotSepSimple,rotSepDetailed, &(crio->rioOnTrack(maxProb)), true); + shape_detailed->addChild(rotSepDetailed); + shape_simple->addChild(rotSepSimple); + + // std::cout<<"addCompetingRIO_OnTrackInfoToShapes: Done drawing most probable"<<std::endl; + + SoTransparency * transparent = new SoTransparency; + transparent->transparency.setValue(0.5); + shape_detailed->addChild( transparent ); + + const Trk::RIO_OnTrack* rot = &(crio->rioOnTrack(maxProb)); + //if (rot==0 || rot == NULL) { VP1Msg::message("WARNING: cROT max prob ROT is NULL. Aborting."); return;} + if (!rot) { VP1Msg::message("WARNING: cROT has empty max prob ROT. Aborting."); return;} + // Now, last position drawn was that of strip pos for most probable ROT. So take this as basis. + if (!rot->detectorElement()) { VP1Msg::message("WARNING: most prob ROT from cROT has empty DE. Aborting."); return;} + + const Trk::Surface* lastSurf=&(crio->rioOnTrack(maxProb).associatedSurface()); + + // std::cout<<"lastSurf = ("<<*lastSurf<<") for most prob="<<rot->identify().get_compact()<<std::endl; + unsigned int nrio = crio->numberOfContainedROTs(); + for (unsigned int n = 0; n < nrio; n++) + { + if (n==maxProb) continue; // already drawn. + // std::cout<<"Strip #"<<n<<std::endl; + const Trk::RIO_OnTrack* rot = &(crio->rioOnTrack(n)); + + // SoTranslation * theTransform = new SoTranslation; + if (!rot) { VP1Msg::message("WARNING: cROT has empty ROT. Skipping."); continue;} + + // Now do offset from last strip pos, to new one (for strips on different layers, this will include a zoffset) + // const MuonGM::TgcReadoutElement* tgcDetEl = + // dynamic_cast<const MuonGM::TgcReadoutElement*>(rot->detectorElement()); + // const MuonGM::RpcReadoutElement* rpcDetEl = + // dynamic_cast<const MuonGM::RpcReadoutElement*>(rot->detectorElement()); + // + // // FIXME - could do all this a bit more elegantly with templates + // + // if ( (!tgcDetEl) && (!rpcDetEl)) { VP1Msg::message("WARNING: ROT from cROT has Unknown DE type. Skipping."); std::cout<<*rot<<std::endl; continue;} + // + // if (tgcDetEl){ + // currPos = tgcDetEl->stripPos(rot->identify()); + // } else { + // currPos = rpcDetEl->stripPos(rot->identify()); + // } + // Amg::Vector3D offset = currPos - lastPos; + // Amg::Vector3D<double> locPos = (rot->associatedSurface().transform().inverse())*(offset); + // theTransform->translation.setValue( locPos.x(), locPos.y(), locPos.z()); + // lastPos=currPos; + SoSeparator * rotSepSimple = new SoSeparator; + SoSeparator * rotSepDetailed = new SoSeparator; + + if ( &(rot->associatedSurface ())!=lastSurf) { + // std::cout<<"New surface!"<<std::endl; + // Do transformation to centre of new surface, especially important if there is a zoffset. + // NB we're assuming that the surfaces are aligned! Might not be entirely safe, but really should be! + // (I hate cROTs) + Amg::Vector3D offset = rot->associatedSurface().center() - lastSurf->center(); + // std::cout<<"new surf offset = "<<Amg::toString(offset)<<std::endl; + + // lastSurf = &(rot->associatedSurface()); + Amg::Vector3D locPos = (rot->associatedSurface().transform().rotation().inverse())*(offset); + // std::cout<<"new surf locPos = "<<Amg::toString(locPos)<<std::endl; + + SoTranslation * theTransform = new SoTranslation; + theTransform->translation.setValue( locPos.x(), locPos.y(), locPos.z()); + rotSepDetailed->addChild(theTransform); + rotSepSimple->addChild(theTransform); + } + // lastSurf = &(rot->associatedSurface()); + + // rotSepDetailed->addChild(theTransform); + // rotSepSimple->addChild(theTransform); + + + m_hitToSoNode.buildStripShapes(crio->rioOnTrack(n),rotSepSimple,rotSepDetailed,true); + shape_simple->addChild(rotSepSimple); + shape_detailed->addChild(rotSepDetailed); + // back to centre + + // std::cout<<"Rot "<<n<<" Done"<<std::endl; + + } + } +} + +//____________________________________________________________________ +void AscObj_TSOS::ensureInitSeps( SoSeparator*&shape_simple, + SoSeparator*&shape_detailed) +{ + if (!shape_simple) + shape_simple = new SoSeparator; + if (!shape_detailed) + shape_detailed = new SoSeparator; +} + +//____________________________________________________________________ +const Trk::RIO_OnTrack * AscObj_TSOS::rioOnTrack() const +{ + return dynamic_cast<const Trk::RIO_OnTrack *>(m_tsos->measurementOnTrack()); +} + +//____________________________________________________________________ +const Trk::CompetingRIOsOnTrack * AscObj_TSOS::competingRIOsOnTrack() const +{ + return dynamic_cast<const Trk::CompetingRIOsOnTrack *>(m_tsos->measurementOnTrack()); +} + +//____________________________________________________________________ +const Trk::Surface * AscObj_TSOS::surface() const +{ + const Trk::Surface * surf(0); + if (m_tsos->trackParameters()) + surf = &(m_tsos->trackParameters()->associatedSurface()); + if (!surf&&m_tsos->measurementOnTrack()) + surf = &(m_tsos->measurementOnTrack()->associatedSurface()); + if (!surf&&m_tsos->materialEffectsOnTrack()) + surf = &(m_tsos->materialEffectsOnTrack()->associatedSurface()); + return surf; +} + +void AscObj_TSOS::addTransformToSurface(SoSeparator*& shape_simple,SoSeparator*& shape_detailed){ + // SurfaceToSoNode surfCnv;//fixme: check if need in common() + // SoNode* theSurfSepSimple = surfCnv.translateSurface(*(surface()),true); + // SoNode* theSurfSep = surfCnv.translateSurface(*(surface())); + if (!surface()) {VP1Msg::message( "AscObj_TSOS::addTransformToSurface: WARNING: TSOS without Surface! Unable to get transform!");return;} + + // This is all a bit complicated, and can probably be cleaned up. The point is that TGCs need to be handled specially, or we could just use + // surface(), I think. + + TrkObjToString::MeasurementType type=TrkObjToString::Unknown; + if (surface()->associatedDetectorElement()) type= m_objToType.type(surface()->associatedDetectorElement()); + +// const Trk::RIO_OnTrack* rio = rioOnTrack() ? rioOnTrack() : competingRIOsOnTrack() ? competingRIOsOnTrack()->rioOnTrack(competingRIOsOnTrack()->indexOfMaxAssignProb()) : 0; + const Trk::RIO_OnTrack* rio = rioOnTrack() ? rioOnTrack() : competingRIOsOnTrack() ? &(competingRIOsOnTrack()->rioOnTrack(competingRIOsOnTrack()->indexOfMaxAssignProb())) : 0; + if (type==TrkObjToString::Unknown && rio) type=m_objToType.type(rio); + + SoTransform* theHitTransform=0; + if (rio) { + // TrkObjToString::MeasurementType type=m_objToType.type(rio); + // std::cout<<"Got ROT of type"<<static_cast<unsigned int>(type)<<std::endl; + theHitTransform=m_hitToSoNode.createTransform(*rio, true); + } else { + if (hasSurface() ) theHitTransform = VP1LinAlgUtils::toSoTransform(surface()->transform()); + } + + if (!theHitTransform) { + VP1Msg::message( "AscObj_TSOS::addTransformToSurface: WARNING: Unable to build transform"); + return; + } + shape_simple->addChild(theHitTransform); + shape_detailed->addChild(theHitTransform); +} + +//____________________________________________________________________ +void AscObj_TSOS::buildShapes(SoSeparator*&shape_simple, + SoSeparator*&shape_detailed) +{ + VP1Msg::messageVerbose("AscObj_TSOS::buildShapes() start"); + + TrackCommonFlags::TSOSPartsFlags f(trackHandle()->shownTSOSParts()&m_parts); + if (f==TrackCommonFlags::TSOS_NoObjects) + return; + const bool showPars(f & TrackCommonFlags::TSOS_TrackPars); + const bool showParsErrors(f & TrackCommonFlags::TSOS_AnyParsErrors); + const bool showRioOnTrack(f & TrackCommonFlags::TSOS_AnyMeasRioOnTrack); + const bool showCompetingRioOnTrack(f & TrackCommonFlags::TSOS_AnyMeasCompetingRioOnTrack); + const bool showSurfaces(f & TrackCommonFlags::TSOS_AnySurface); + const bool showMaterialEffects(f & TrackCommonFlags::TSOS_AnyMaterialEffects); + const bool showMeasErrors(f & TrackCommonFlags::TSOS_MeasError); + + ensureInitSeps(shape_simple,shape_detailed); + + // FIXME - would like to simplify this and use transform returned from surface, but means internal changes below + SoSeparator* param_simple= new SoSeparator; + SoSeparator* param_detailed= new SoSeparator; + if (showPars||showParsErrors) + addTrackParamInfoToShapes(param_simple,param_detailed,showPars,showParsErrors,showSurfaces); + shape_simple->addChild(param_simple); + shape_detailed->addChild(param_detailed); + + if (showMaterialEffects) + addMaterialEffectsToShapes( shape_simple, shape_detailed); + + if (showSurfaces) + addSurfaceToShapes( shape_simple, shape_detailed); + + // Transform to centre of surface. All other seps will (eventually) hang from this. + // TGCs are special, in that the position returned is that of the strip, due to rotation + addTransformToSurface(shape_simple,shape_detailed); + + // Measurements are a bit different and create a sep outside addRIO_OnTrackInfoToShapes, because addRIO_OnTrackInfoToShapes is used + // by addCompetingRIO_OnTrackInfoToShapes too + SoSeparator* meas_simple= new SoSeparator; + SoSeparator* meas_detailed= new SoSeparator; + if (rioOnTrack() && (showRioOnTrack||showMeasErrors)) + addRIO_OnTrackInfoToShapes(meas_simple,meas_detailed,rioOnTrack(), !(common()->controller()->drawMeasGlobalPositions())); + if (showCompetingRioOnTrack) + addCompetingRIO_OnTrackInfoToShapes(meas_simple,meas_detailed); // FIXME - handle cROT errors too. + shape_simple->addChild(meas_simple); + shape_detailed->addChild(meas_detailed); + + //Currently this doesn't do much as rio->globalPosition() returns a position + //along the axis! + /**bool showDeviationsFromMeasurements = false;//Fixme (and see below) + if ( showDeviationsFromMeasurements + && hasParameters() + && rioOnTrack() + && dynamic_cast<const Trk::TrackParameters *>(m_tsos->trackParameters()) ) + addDeviationFromMeasurementInfoToShapes(shape_simple,shape_detailed); + **/ + VP1Msg::messageVerbose("AscObj_TSOS::buildShapes() end"); + +} + +//____________________________________________________________________ +QStringList AscObj_TSOS::clicked() +{ + QStringList l; + if (!m_tsos) { + l << "ERROR: This associated object handle has a NULL TSOS pointer!!"; + return l; + } + + + l << "---"<<"Track State On Surface #"+VP1Msg::str(m_indexOfPointOnTrack)+":"; + + if (hasParameters()) + { + l << "----> "+TrkObjToString::name(*(m_tsos->trackParameters())); + QStringList list = TrkObjToString::fullInfo( *(m_tsos->trackParameters()) ); + for (int i = 0; i < (list.size()-1); ){ + l<< (list.at(i)+QString(" = ")+list.at(i+1) ); + i+=2; + } + // l << " -> Position (x,y,z) [CLHEP::mm]: "+VP1Msg::str(m_tsos->trackParameters()->position()/CLHEP::mm); + // l << " -> Momentum (Px,Py,Pz) [MeV]: "+VP1Msg::str(m_tsos->trackParameters()->momentum()/MeV) + ", |P| [GeV]: "+VP1Msg::str(m_tsos->trackParameters()->momentum().mag()/GeV); + // l << " -> Momentum (Pt) [GeV]: "+VP1Msg::str(m_tsos->trackParameters()->momentum().perp()/GeV); + //FIXME: parameter errors + } + + bool showDeviationsFromMeasurements = true;//Fixme (and see above) + if ( showDeviationsFromMeasurements + && hasParameters() + && (rioOnTrack() || competingRIOsOnTrack() ) + && dynamic_cast<const Trk::TrackParameters *>(m_tsos->trackParameters()) ) + { + if ( m_tsos->type(Trk::TrackStateOnSurface::Outlier)) + l << " -> Std deviations from measurement: " + VP1Msg::str(deviationFromMeasurement()) + " (Outlier)"; + else + l << " -> Std deviations from measurement: " + VP1Msg::str(deviationFromMeasurement()); + } + + if (m_tsos->measurementOnTrack()){ + l << "----> "+TrkObjToString::name(*(m_tsos->measurementOnTrack())); + QStringList list = TrkObjToString::fullInfo( *(m_tsos->measurementOnTrack()) ); + for (int i = 0; i < (list.size()-1); ){ + l<< (list.at(i)+QString(" = ")+list.at(i+1) ); + i+=2; + } + } + + + if (m_tsos->fitQualityOnSurface()) + { + l << "----> "+TrkObjToString::name(*(m_tsos->fitQualityOnSurface())); + QStringList list = TrkObjToString::fullInfo( *(m_tsos->fitQualityOnSurface()) ); + for (int i = 0; i < (list.size()-1); ){ + l<< (list.at(i)+QString(" = ")+list.at(i+1) ); + i+=2; + } + } + + if (m_tsos->materialEffectsOnTrack()) + { + l << "----> "+TrkObjToString::name(*(m_tsos->materialEffectsOnTrack())) ; + QStringList list = TrkObjToString::fullInfo( *(m_tsos->materialEffectsOnTrack()) ); + for (int i = 0; i < (list.size()-1); ){ + l<< (list.at(i)+QString(" = ")+list.at(i+1) ); + i+=2; + } + } + + if (common()->controller()->printVerboseInfoOnSingleSelection()) { + l << " ===== TrackStateOnSurface ====="; + std::ostringstream s2; + s2 << *m_tsos; + l << QString(s2.str().c_str()).split('\n'); + + if (surface()) { + l << " ===== Surface ====="; + std::ostringstream s; + s << *(surface()); + l << QString(s.str().c_str()).split('\n'); + } + } + + // Object browser stuff m_indexOfPointOnTrack + QTreeWidgetItem* trkObjBrowseritem = trackHandle()->browserTreeItem(); + if (trkObjBrowseritem){ + QTreeWidgetItem* me = trkObjBrowseritem->child(m_indexOfPointOnTrack); // I hope! + if (!me) { + VP1Msg::messageVerbose("ERROR! Can't find AscObj_TSOS item in track obj browser."); + } else { + QTreeWidget* trkObjBrowser = trkObjBrowseritem->treeWidget(); + trkObjBrowser->setCurrentItem(me); + trkObjBrowser->scrollToItem(me); + } + } + + zoomView(); // depending on controller settings, zoom view + + return l; +} + +void AscObj_TSOS::setVisible(bool vis) { + AssociatedObjectHandleBase::setVisible(vis); + + QTreeWidgetItem* trkObjBrowseritem = trackHandle()->browserTreeItem(); + if (trkObjBrowseritem){ + QTreeWidgetItem* me = trkObjBrowseritem->child(m_indexOfPointOnTrack); // I hope! + if (!me) { + VP1Msg::messageVerbose("ERROR! Can't find AscObj_TSOS item in track obj browser."); + } else { + QFont itemFont = me->font(1); + + if (!visible()) { + // std::cout<<"Hidden"<<std::endl; + me->setFlags(0); // not selectable, not enabled + itemFont.setStrikeOut(true); + + } else { + // std::cout<<"Vis"<<std::endl; + me->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); // selectable, enabled + itemFont.setStrikeOut(false); + + } + } + } +} + + +bool AscObj_TSOS::isShortMeasurement(){ + bool isShortMeasurement; + + isShortMeasurement = false; + + return isShortMeasurement; +} + +void AscObj_TSOS::zoomView() { + VP1Msg::messageVerbose("AscObj_TSOS::zoomView()"); + + if ( common()->controller()->orientAndZoomOnSingleSelection() ) + { + const bool showParsErrors( trackHandle()->shownTSOSParts()&m_parts & TrackCommonFlags::TSOS_AnyParsErrors); + + + if (!showParsErrors && !isShortMeasurement()) + { // Zoom without orientation + VP1Msg::messageVerbose("AscObj_TSOS::zoomView() Zoom without orientation"); + std::set<SoCamera*> cameras = common()->system()->getCameraList(); + std::set<SoCamera*>::iterator it,itE = cameras.end(); + for (it=cameras.begin();it!=itE;++it) { + if (common()->controller()->assocObjDetailLevel()==TrackCommonFlags::SIMPLE) + { + VP1CameraHelper::animatedZoomToSubTree(*it,common()->ascObjSelectionManager()->getAscObjAttachSep(),shapeSimple(),2.0,1.0); + } else + { + VP1CameraHelper::animatedZoomToSubTree(*it,common()->ascObjSelectionManager()->getAscObjAttachSep(),shapeDetailed(),2.0,1.0); + } + } + } else + { // Zoom and orient (this is dependant of surface type) + VP1Msg::messageVerbose("AscObj_TSOS::zoomView() Zoom and orient"); + + const Trk::Surface * theSurface = surface(); + const Trk::PerigeeSurface * perSurf = dynamic_cast<const Trk::PerigeeSurface *>(theSurface); + const Trk::PlaneSurface * plaSurf = dynamic_cast<const Trk::PlaneSurface *>(theSurface); + const Trk::StraightLineSurface * strSurf = dynamic_cast<const Trk::StraightLineSurface *>(theSurface); + if ( plaSurf || perSurf ) + { +// Trk::GlobalMomentum u(m_tsos->trackParameters()->momentum().unit()); + Amg::Vector3D u(m_tsos->trackParameters()->momentum().unit()); + + SbVec3f lookat0 = SbVec3f(-u[0],-u[1],-u[2]); + + std::set<SoCamera*> cameras = common()->system()->getCameraList(); + std::set<SoCamera*>::iterator it,itE = cameras.end(); + for (it=cameras.begin();it!=itE;++it) { + if (common()->controller()->assocObjDetailLevel()==TrackCommonFlags::SIMPLE) + { + VP1CameraHelper::animatedZoomToSubTree(*it,common()->ascObjSelectionManager()->getAscObjAttachSep(),shapeSimple(),2.0,100.0,100.0,1.0,lookat0); + } else + { + VP1CameraHelper::animatedZoomToSubTree(*it,common()->ascObjSelectionManager()->getAscObjAttachSep(),shapeDetailed(),2.0,100.0,100.0,1.0,lookat0); + } + } + } else if ( strSurf ) + { + SbVec3f lookat0 = SbVec3f(0,0,1); + SbVec3f lookat1; + + SbRotation rot = VP1LinAlgUtils::toSoTransform(theSurface->transform())->rotation.getValue(); + rot.multVec(lookat0,lookat0); + + std::set<SoCamera*> cameras = common()->system()->getCameraList(); + std::set<SoCamera*>::iterator it,itE = cameras.end(); + for (it=cameras.begin();it!=itE;++it) { + SbRotation camrot = (*it)->orientation.getValue(); + SbVec3f cameraDir = SbVec3f(0,0,-1); + camrot.multVec(cameraDir,cameraDir); + + lookat1 = cameraDir.dot(lookat0) > 0 ? lookat0 : -lookat0; + if (common()->controller()->assocObjDetailLevel()==TrackCommonFlags::SIMPLE) + { + VP1CameraHelper::animatedZoomToSubTree(*it,common()->ascObjSelectionManager()->getAscObjAttachSep(),shapeSimple(),2.0,100.0,100.0,1.0,lookat1); + } else + { + VP1CameraHelper::animatedZoomToSubTree(*it,common()->ascObjSelectionManager()->getAscObjAttachSep(),shapeDetailed(),2.0,100.0,100.0,1.0,lookat1); + } + } + } + } + } else { + VP1Msg::messageVerbose("AscObj_TSOS::zoomView() - zooming on selection not turned on."); + } +} diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/AscObj_TruthPoint.cxx b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/AscObj_TruthPoint.cxx new file mode 100644 index 000000000..29b651441 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/AscObj_TruthPoint.cxx @@ -0,0 +1,160 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class AscObj_TruthPoint // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: May 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12TrackSystems/AscObj_TruthPoint.h" +#include "VTI12TrackSystems/SimHitHandleBase.h" +#include "VP1Base/VP1Msg.h" +#include "HepMC/GenParticle.h" +#include "HepMC/GenVertex.h" + +// Eigen migration +//#include "TrkEventPrimitives/GlobalPosition.h" +//#include "TrkEventPrimitives/GlobalMomentum.h" +#include "GeoPrimitives/GeoPrimitives.h" +#include "GeoPrimitives/AmgStringHelpers.h" + +#include <Inventor/C/errors/debugerror.h> +#include <Inventor/nodes/SoLineSet.h> +#include <Inventor/nodes/SoSeparator.h> +#include <Inventor/nodes/SoVertexProperty.h> +#include "CLHEP/Units/SystemOfUnits.h" + +#include <string> // for C++11 to_string features + + +//____________________________________________________________________ +class AscObj_TruthPoint::Imp { +public: + Imp(const HepMC::GenVertex * v, const HepMC::GenParticle * p) + : genVertex(v), genParticle(p), simhit(0) {} + Imp(SimHitHandleBase*s) + : genVertex(0), genParticle(0), simhit(s) {} + const HepMC::GenVertex * genVertex; + const HepMC::GenParticle * genParticle; + SimHitHandleBase * simhit; +}; + + +//____________________________________________________________________ +AscObj_TruthPoint::AscObj_TruthPoint(TrackHandleBase*th, const HepMC::GenVertex * v, const HepMC::GenParticle * p) + : AssociatedObjectHandleBase(th), m_d(new Imp(v,p)) +{ +} + +//____________________________________________________________________ +AscObj_TruthPoint::AscObj_TruthPoint(TrackHandleBase*th, SimHitHandleBase*s) + : AssociatedObjectHandleBase(th), m_d(new Imp(s)) +{ +} + +//____________________________________________________________________ +AscObj_TruthPoint::~AscObj_TruthPoint() +{ + delete m_d; +} + +//____________________________________________________________________ +void AscObj_TruthPoint::buildShapes(SoSeparator*&shape_simple, SoSeparator*&shape_detailed) +{ + VP1Msg::message("AscObj_TruthPoint::buildShapes."); + + // Eigen migration +// Trk::GlobalPosition p1;//point +// Trk::GlobalMomentum u;//mom direction + Amg::Vector3D p1;//point + Amg::Vector3D u;//mom direction + + + if (m_d->simhit) { + p1 = m_d->simhit->posStart(); + u = m_d->simhit->momentumDirection(); + } + else + { + // Eigen migration +// p1 = Trk::GlobalPosition(m_d->genVertex->point3d().x(),m_d->genVertex->point3d().y(),m_d->genVertex->point3d().z()); +// u = Trk::GlobalMomentum(m_d->genParticle->momentum().px(),m_d->genParticle->momentum().py(),m_d->genParticle->momentum().pz()).unit(); + p1 = Amg::Vector3D(m_d->genVertex->point3d().x(),m_d->genVertex->point3d().y(),m_d->genVertex->point3d().z()); + u = Amg::Vector3D(m_d->genParticle->momentum().px(),m_d->genParticle->momentum().py(),m_d->genParticle->momentum().pz()).unit(); + } + + // Eigen migration +// Trk::GlobalPosition p2 = p1+5*CLHEP::cm*u; + Amg::Vector3D p2 = p1+5*CLHEP::cm*u; + + SoLineSet * line = new SoLineSet(); + SoVertexProperty * vertices = new SoVertexProperty(); + vertices->vertex.set1Value(0,p1.x(),p1.y(),p1.z()); + vertices->vertex.set1Value(1,p2.x(),p2.y(),p2.z()); + line->numVertices.set1Value(0,2); + line->vertexProperty = vertices; + + shape_simple = new SoSeparator; + shape_simple->addChild(line); + shape_detailed = shape_simple; + +// //Fixme: Uncomment these two lines: +// shape_detailed = new SoSeparator; +// shape_detailed->addChild(line); +} + +//____________________________________________________________________ +QStringList AscObj_TruthPoint::clicked() +{ + VP1Msg::messageVerbose("AscObj_TruthPoint::clicked()"); + + QStringList l; + + l << " ==> Truth point"; + if (m_d->simhit) { + l << "Sim Hit ("+m_d->simhit->type()+")"; +//// l << " Position: "+VP1Msg::str( m_d->simhit->posStart() ) ; +// l << " Direction: "+VP1Msg::str( m_d->simhit->momentumDirection() ); +// l << " Momentum: "+VP1Msg::str(m_d->simhit->momentum()/CLHEP::GeV)+" GeV"+(m_d->simhit->actualMomentum()==m_d->simhit->momentum()?"":" (fudged)"); + l << " Position: " + QString::fromStdString(Amg::AsString(m_d->simhit->posStart())); + l << " Direction: " + QString::fromStdString(Amg::AsString(m_d->simhit->momentumDirection())); + l << " Momentum: " + VP1Msg::str(m_d->simhit->momentum()/CLHEP::GeV)+" GeV"+(m_d->simhit->actualMomentum()==m_d->simhit->momentum()?"":" (fudged)"); + } else { + if (!m_d->genVertex||!m_d->genParticle) { + l << "ERROR"; + return l; + } + +// Trk::GlobalPosition p(m_d->genVertex->point3d().x(),m_d->genVertex->point3d().y(),m_d->genVertex->point3d().z()); +// Trk::GlobalMomentum mom(m_d->genParticle->momentum().px(),m_d->genParticle->momentum().py(),m_d->genParticle->momentum().pz()); + Amg::Vector3D p(m_d->genVertex->point3d().x(),m_d->genVertex->point3d().y(),m_d->genVertex->point3d().z()); + Amg::Vector3D mom(m_d->genParticle->momentum().px(),m_d->genParticle->momentum().py(),m_d->genParticle->momentum().pz()); + + l << "Gen Particle vertex"; +// l << " Position: "+VP1Msg::str(p); +// l << " Direction: "+ VP1Msg::str(mom.unit()); + l << " Position: "+ QString::fromStdString(Amg::AsString(p)); + l << " Direction: "+ QString::fromStdString( Amg::AsString(mom.unit()) ); + l << " Momentum: "+ VP1Msg::str(mom.mag()/CLHEP::GeV)+" GeV"; + } + + return l; +} + +//____________________________________________________________________ +int AscObj_TruthPoint::regionIndex() const +{ + return 0; +} + +//____________________________________________________________________ +double AscObj_TruthPoint::lodCrossOverValue() const +{ + return 100; +} diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/AssociatedObjectHandleBase.cxx b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/AssociatedObjectHandleBase.cxx new file mode 100644 index 000000000..73c6f5fa0 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/AssociatedObjectHandleBase.cxx @@ -0,0 +1,208 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class AssociatedObjectHandleBase // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: March 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12TrackSystems/AssociatedObjectHandleBase.h" +#include "VTI12TrackSystems/TrackHandleBase.h" +#include "VTI12TrackSystems/TrackCollHandleBase.h" +#include "VTI12TrackSystems/TrackSysCommonData.h" +#include "VTI12TrackSystems/AscObjSelectionManager.h" +#include "VTI12TrackSystems/VP1TrackSystem.h" +#include "VP1Base/VP1Msg.h" + +#include <Inventor/nodes/SoSeparator.h> + +//____________________________________________________________________ +class AssociatedObjectHandleBase::Imp { +public: + static int nascobjs; + Imp() : sep_simple(0), + sep_detailed(0), + attachhandle(0) + //,transform(0) + {} + SoSeparator * sep_simple; + SoSeparator * sep_detailed; + AssocObjAttachmentHandle * attachhandle; + + //SoTransform * transform; + void detach(); + void attach(AssociatedObjectHandleBase * theclass ); + void ensureShapesBuild(AssociatedObjectHandleBase * theclass ); + void ensureShapesErased(AssociatedObjectHandleBase * theclass ); +}; + +int AssociatedObjectHandleBase::Imp::nascobjs = 0; + +//____________________________________________________________________ +void AssociatedObjectHandleBase::Imp::ensureShapesBuild( AssociatedObjectHandleBase * theclass ) +{ + if (sep_simple&&sep_detailed) + return; + if (!sep_simple&&!sep_detailed) { + theclass->buildShapes(sep_simple, sep_detailed); + if (!sep_simple&&!sep_detailed) { + VP1Msg::messageDebug("AssociatedObjectHandleBase WARNING: Got null shapes! Replacing with simple points."); + sep_simple = new SoSeparator;//Fixme: Shared point!!! + } + if (sep_simple) + sep_simple->ref(); + if (sep_detailed) + sep_detailed->ref(); + } + if (!sep_detailed) { + sep_detailed = sep_simple; + sep_detailed->ref(); + } + if (!sep_simple) { + sep_simple = sep_detailed; + sep_simple->ref(); + } + + theclass->registerShapes(sep_simple,sep_detailed); +} + +//____________________________________________________________________ +void AssociatedObjectHandleBase::Imp::ensureShapesErased(AssociatedObjectHandleBase * theclass ) +{ + if (sep_simple||sep_detailed) { + theclass->unregisterShapes(sep_simple,sep_detailed); + if (sep_simple) { + sep_simple->unref(); + sep_simple = 0; + } + if (sep_detailed) { + sep_detailed->unref(); + sep_detailed = 0; + } + } +} + +//____________________________________________________________________ +void AssociatedObjectHandleBase::registerShapes(SoSeparator*simple,SoSeparator*detailed) +{ + m_trackHandle->collHandle()->common()->ascObjSelectionManager()->registerAscObj(simple,detailed,this); +} + +//____________________________________________________________________ +void AssociatedObjectHandleBase::unregisterShapes(SoSeparator*simple,SoSeparator*detailed) +{ + m_trackHandle->collHandle()->common()->ascObjSelectionManager()->unregisterAscObj(simple,detailed); +} + +//____________________________________________________________________ +TrackSysCommonData * AssociatedObjectHandleBase::common() const +{ + return m_trackHandle->common(); +} + +//____________________________________________________________________ +AssociatedObjectHandleBase::AssociatedObjectHandleBase(TrackHandleBase*th) + : m_d(new Imp),m_trackHandle(th), m_visible(false), m_pickStyle(UNPICKABLE/*better default?*/) +{ + ++Imp::nascobjs; +} + +//____________________________________________________________________ +AssociatedObjectHandleBase::~AssociatedObjectHandleBase() +{ + if (m_d->attachhandle&&m_visible&&m_d->sep_simple&&m_d->sep_detailed) { + m_d->attachhandle->detachNodes(m_d->sep_simple,m_d->sep_detailed); + } + m_d->ensureShapesErased(this ); + delete m_d; + --Imp::nascobjs; + +} + +//____________________________________________________________________ +int AssociatedObjectHandleBase::numberOfInstances() +{ + return Imp::nascobjs; +} + +//____________________________________________________________________ +void AssociatedObjectHandleBase::setPickable( PICKSTYLE ps ) +{ + if (m_pickStyle==ps) + return; + m_pickStyle=ps; + + //Fixme... + +} + +//____________________________________________________________________ +void AssociatedObjectHandleBase::Imp::detach() +{ + if (!attachhandle) + return;//Can't have been attached. + attachhandle->detachNodes(sep_simple,sep_detailed); +} + +//____________________________________________________________________ +AssocObjAttachmentHandle * AssociatedObjectHandleBase::getAttachmentHandle() +{ + return m_trackHandle->getAttachmentHandle(regionIndex(), lodCrossOverValue()); +} + + +//____________________________________________________________________ +void AssociatedObjectHandleBase::Imp::attach(AssociatedObjectHandleBase * theclass ) +{ + if (!attachhandle) + attachhandle = theclass->getAttachmentHandle(); + attachhandle->attachNodes(sep_simple,sep_detailed,(theclass->pickStyle()!=UNPICKABLE)); +} + + +//____________________________________________________________________ +void AssociatedObjectHandleBase::setVisible( bool b ) +{ + if (m_visible==b) + return; + m_visible=b; + if (b) { + m_d->ensureShapesBuild(this); + m_d->attach(this); + } else { + m_d->detach(); + } +} + +//____________________________________________________________________ +void AssociatedObjectHandleBase::update3DObjects() +{ + VP1Msg::messageVerbose("AssociatedObjectHandleBase update3DObjects."); + + if (m_visible) { + m_d->detach(); + m_d->ensureShapesErased(this); + m_d->ensureShapesBuild(this); + m_d->attach(this); + } else { + m_d->ensureShapesErased(this); + } +} + +//____________________________________________________________________ +SoSeparator* AssociatedObjectHandleBase::shapeSimple() const +{ + return m_d->sep_simple; +} + +//____________________________________________________________________ +SoSeparator* AssociatedObjectHandleBase::shapeDetailed() const +{ + return m_d->sep_detailed; +} diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/MeasurementToSoNode.cxx b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/MeasurementToSoNode.cxx new file mode 100644 index 000000000..634f9a072 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/MeasurementToSoNode.cxx @@ -0,0 +1,288 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "VTI12TrackSystems/MeasurementToSoNode.h" + +#include <Inventor/C/errors/debugerror.h> +#include <Inventor/nodes/SoSeparator.h> +#include <Inventor/nodes/SoTransform.h> +#include <Inventor/nodes/SoSphere.h> +#include "VP1HEPVis/nodes/SoTubs.h" +#include "VP1HEPVis/nodes/SoGenericBox.h" +#include <Inventor/nodes/SoPointSet.h> +#include <Inventor/nodes/SoLineSet.h> +#include <Inventor/nodes/SoCylinder.h> +#include <Inventor/nodes/SoRotationXYZ.h> + +#include "VTI12Utils/VP1LinAlgUtils.h" +#include "VTI12Utils/HitsSoNodeManager.h" +#include "VP1Base/VP1Msg.h" + + + +// Amg Eigen objects +#include "GeoPrimitives/GeoPrimitives.h" + +//MeasurementBase +#include "TrkMeasurementBase/MeasurementBase.h" + +//ROTs +#include "TrkRIO_OnTrack/RIO_OnTrack.h" +// #include "InDetRIO_OnTrack/PixelClusterOnTrack.h" +// #include "InDetRIO_OnTrack/SCT_ClusterOnTrack.h" +// #include "InDetRIO_OnTrack/TRT_DriftCircleOnTrack.h" +// #include "InDetRIO_OnTrack/SiClusterOnTrack.h" + +//CompetingROTs +#include "TrkCompetingRIOsOnTrack/CompetingRIOsOnTrack.h" + +//Pseudo Measurements +#include "TrkPseudoMeasurementOnTrack/PseudoMeasurementOnTrack.h" + +//Segments +#include "TrkSegment/Segment.h" + +// PRDs +// #include "InDetPrepRawData/PixelCluster.h" +// #include "InDetPrepRawData/SCT_Cluster.h" +// #include "InDetPrepRawData/TRT_DriftCircle.h" + +//IdHelpers +Trk::MeasurementToSoNode::MeasurementToSoNode() + : + m_stripThickness(0.8), + m_clusDrawMode(Trk::MeasurementToSoNode::SingleStrip), + m_dtLength(10.0) +{ + SoTubs::initClass(); + SoGenericBox::initClass(); + // Have simple view on by default + for (int i=0; i<TrkObjToString::Unknown ; i++) m_simpleView.push_back(true); +} + +std::pair<SoSeparator*, std::vector<SoNode*> > +Trk::MeasurementToSoNode::createMeasSep( const Trk::MeasurementBase& meas) +{ + + VP1Msg::messageVerbose("Trk::MeasurementToSoNode::createMeasSep()"); + + // Vector to hold all the nodes associated with this measurement + std::vector<SoNode*> measurements; + SoTransform* theHitTransform=0; + TrkObjToString::MeasurementType detType = m_objToType.type(&meas); + // Find the correct type and call that method. + + switch (detType) + { + case TrkObjToString::SCT: + { + const Trk::RIO_OnTrack* rot = dynamic_cast<const Trk::RIO_OnTrack*>(&meas); + if (rot){ + measurements = toSoNodes( *rot ); + theHitTransform=createTransform(*rot, detType); + } + break; + } + case TrkObjToString::CompetingROT: + { + const Trk::CompetingRIOsOnTrack* crot = dynamic_cast<const Trk::CompetingRIOsOnTrack*>(&meas); + if (crot){ + measurements = toSoNodes(*crot); + const Trk::RIO_OnTrack* mostProbROT = &(crot->rioOnTrack( crot->indexOfMaxAssignProb ())); + theHitTransform=createTransform( static_cast<const Trk::MeasurementBase&>(*mostProbROT), TrkObjToString::type( mostProbROT )); + } + break; + } + case TrkObjToString::PseudoMeasurement: + { + const Trk::PseudoMeasurementOnTrack* pseudo = dynamic_cast<const Trk::PseudoMeasurementOnTrack*>(&meas) ; + if (pseudo){ + measurements = toSoNodes(*pseudo); + theHitTransform=createTransform( *pseudo, detType); + } + break; + } + case TrkObjToString::Segment: + case TrkObjToString::Hole: + case TrkObjToString::Unknown: + { + std::cerr<< "MeasurementToSoNode::createMeasSep: WARNING - Unknown detector type!"<<std::endl; + std::cerr<<" Dumping MeasurementBase: "<<meas<<std::endl; + } + + } + // Add all the above to the separator + SoSeparator *theHitMarkerSep = new SoSeparator; + theHitMarkerSep->addChild(theHitTransform); + + std::vector<SoNode*>::const_iterator it, itEnd=measurements.end(); + for ( it = measurements.begin(); it!=itEnd; it++) + { + theHitMarkerSep->addChild(*it); + } + //std::cout<<"MeasurementToSoNode::createMeasSep - done"<<std::endl; + + return std::make_pair(theHitMarkerSep, measurements); +} + +std::vector<SoNode*> +Trk::MeasurementToSoNode::toSoNodes(const Trk::RIO_OnTrack& rot) +{ + //std::cout<<"toSoNodes"<<std::endl; + + //TODO Implement modes properly + std::vector<SoNode*> nodes ; + switch (m_clusDrawMode) + { + case SingleStrip: + case MultipleStrips: + case Errors: + { + double coord1 = rot.localParameters().get(Trk::loc1); + double coord2 = 0.0; + if (rot.localParameters().dimension()>1) coord2 = rot.localParameters().get(Trk::loc2); +// nodes.push_back( toSoNode(rot.detectorElement(), rot.identify(), m_objToType.type(&rot), Trk::LocalPosition(coord1,coord2) ) ); + nodes.push_back( toSoNode(rot.detectorElement(), rot.identify(), m_objToType.type(&rot), Amg::Vector2D(coord1,coord2) ) ); + break; + } + default: + break; + } + return nodes; +} + +std::vector<SoNode*> +Trk::MeasurementToSoNode::toSoNodes(const Trk::CompetingRIOsOnTrack& crot) +{ + VP1Msg::messageVerbose("Trk::MeasurementToSoNode::CompetingRIOsOnTrack()"); + + // + // ++++++++++++++++++++++ TO DO! +++++++++++++++++++++++++ + // + const Trk::RIO_OnTrack* mostProbROT = &(crot.rioOnTrack( crot.indexOfMaxAssignProb ())); + std::vector<SoNode*> nodes = toSoNodes( *mostProbROT ); // Temporary hack - should draw all competing ROTs and show them linked somehow. + return nodes; +} + +std::vector<SoNode*> +Trk::MeasurementToSoNode::toSoNodes(const Trk::PseudoMeasurementOnTrack& /*rot*/) +{ + // + // ++++++++++++++++++++++ TO DO! +++++++++++++++++++++++++ + // + VP1Msg::messageVerbose("Trk::MeasurementToSoNode::PseudoMeasurementOnTrack()"); + + std::vector<SoNode*> nodes ; + nodes.push_back( m_nodeManager.getShapeNode_Strip(10.0, 10.0, 10.0) ); + return nodes; +} + +SoNode* +Trk::MeasurementToSoNode::toSoNode(const Trk::TrkDetElementBase* /*baseDetEl*/, Identifier /*id*/, TrkObjToString::MeasurementType prdType, Amg::Vector2D /*locPos*/) +{ + VP1Msg::messageVerbose("Trk::MeasurementToSoNode::toSoNode(Trk)"); + + SoNode *theHitMarker = 0; + switch (prdType) + { + // case TrkObjToString::SCT: + // { + // const InDetDD::SiDetectorElement* detEl = dynamic_cast<const InDetDD::SiDetectorElement*>(baseDetEl); + // if(detEl){ // by definition this should never fail + // theHitMarker = toSoNode(detEl, id, prdType, locPos); + // } + // break; + // } + default: + //message( "Specific Hit type could not be identified."); + theHitMarker = m_nodeManager.getShapeNode_Strip(10.0, 10.0, 10.0); + break; + } + return theHitMarker; +} + + +// SoNode* +// Trk::MeasurementToSoNode::toSoNode( const InDetDD::SiDetectorElement* detEl, Identifier /*id*/, TrkObjToString::MeasurementType detType, Amg::Vector2D& locPos) +// { +// VP1Msg::messageVerbose("Trk::MeasurementToSoNode::toSoNode(InDetDD)"); + +// SoNode *theHitMarker = 0; +// if ( isSimpleView(TrkObjToString::Pixel) && detType==TrkObjToString::Pixel) +// { +// // theHitMarker = createPointMarker(); // Simple Pixel +// theHitMarker = m_nodeManager.getShapeNode_Point(); // Simple Pixel +// } +// else +// { + +// double stripLength=detEl->etaPitch() ; +// if (isSimpleView(TrkObjToString::SCT) && detType==TrkObjToString::SCT) +// { +// theHitMarker = createLineMarker(stripLength/2.0); // Simple SCT +// } +// else +// { +// double stripWidth=detEl->phiPitch( locPos ); +// theHitMarker = m_nodeManager.getShapeNode_Strip(stripLength, stripWidth, m_stripThickness); // Detailed SCT/Pixel +// } +// } +// return theHitMarker; +// } + +SoNode* +Trk::MeasurementToSoNode::createLineMarker( double halfLength, bool isTube ) +{ + //////std::cout<<"createLineMarker. halfLength="<<halfLength<<std::endl; + SoVertexProperty * scatVtxProperty = new SoVertexProperty(); + if (isTube) + { + scatVtxProperty->vertex.set1Value(0, 0.0,0.0,-halfLength); + scatVtxProperty->vertex.set1Value(1, 0.0,0.0, halfLength); + } + else + { + scatVtxProperty->vertex.set1Value(0, 0.0,-halfLength,0.0); + scatVtxProperty->vertex.set1Value(1, 0.0,halfLength,0.0); + } + SoLineSet * line = new SoLineSet(); + line->numVertices = 2; + line->vertexProperty = scatVtxProperty; + return line; +} + +SoTransform* +Trk::MeasurementToSoNode::createTransform( const Trk::MeasurementBase& mb, TrkObjToString::MeasurementType detType) +{ + const Trk::Surface& theSurface = mb.associatedSurface(); + + // We need to handle various cases: + // -> full tubes - use the surface position (or equivalent, global position of straw) + // -> short tubes/strips - use the global position of the ROT (but this is now done inside AscoObj_TSOS) + // -> long strips - use the global position of centre of strip. + + SoTransform* theHitTransform = VP1LinAlgUtils::toSoTransform(theSurface.transform()); + + Amg::Vector3D theHitGPos={-999.0,-999.0,-999.0} ; + // so, strips + switch (detType) { + // case TrkObjToString::SCT: + // { // For strips we should use the centre of the strip - this is a bit of a hack - should use detector elements (add above) + // const Amg::Vector3D* tempHitGPos = theSurface.localToGlobal( mb.localParameters() ); + // theHitGPos=*tempHitGPos; + // delete tempHitGPos; + // break; + // } + default: + // shouldn't ever get in here! + // initializations to avoid warnings + theHitGPos[0]=-999.; + theHitGPos[1]=-999.; + theHitGPos[2]=-999.; + break; + } + + theHitTransform->translation.setValue(theHitGPos[0], theHitGPos[1], theHitGPos[2]); + return theHitTransform; +} diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/SimHitHandle_ScintHit.cxx b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/SimHitHandle_ScintHit.cxx new file mode 100644 index 000000000..bde3998c6 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/SimHitHandle_ScintHit.cxx @@ -0,0 +1,172 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class SimHitHandle_ScintHit // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: March 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12TrackSystems/SimHitHandle_ScintHit.h" +#include "VP1Base/VP1Msg.h" +#include "VTI12Utils/VP1DetInfo.h" +#include "VTI12Utils/VP1ParticleData.h" + +#include "ScintSimEvent/ScintHit.h" +#include "ScintReadoutGeometry/ScintDetectorElement.h" +#include "ScintReadoutGeometry/VetoDetectorManager.h" +// #include "ScintReadoutGeometry/TriggerDetectorManager.h" +// #include "ScintReadoutGeometry/PreshowerDetectorManager.h" +#include "ScintIdentifier/VetoID.h" +// #include "ScintIdentifier/TriggerID.h" +// #include "ScintIdentifier/PreshowerID.h" +#include "VTI12TrackSystems/VP1TrackSanity.h" + +//____________________________________________________________________ +class SimHitHandle_ScintHit::Imp { +public: + Imp( const ScintHit * h ) : thehit(h),detelem(0) {} + const ScintHit * thehit; + mutable const ScintDD::ScintDetectorElement * detelem; + bool ensureDetElemInit() const; + Amg::Vector3D localToGlobal(const HepGeom::Point3D<double>&) const; +}; + + +//____________________________________________________________________ +SimHitHandle_ScintHit::SimHitHandle_ScintHit(const ScintHit * h) + : SimHitHandleBase(), m_d(new Imp(h)) +{ + if (!h) + VP1Msg::message("SimHitHandle_ScintHit constructor ERROR: Received null hit pointer"); +} + +//____________________________________________________________________ +SimHitHandle_ScintHit::~SimHitHandle_ScintHit() +{ + delete m_d; +} + +//____________________________________________________________________ +bool SimHitHandle_ScintHit::Imp::ensureDetElemInit() const +{ + if (detelem) + return true; + int Station = thehit->getStation(); + //Not needed anymore and spoils stuff for slhc studies: if (Barrel== 1) Barrel = -2;//Found this hack in GeoSiHit. + + if (thehit->isVeto()) { + Identifier id = VP1DetInfo::vetoIDHelper()->plate_id( Station, + thehit->getPlate() ); + //fixme: id is_valid ? + detelem = VP1DetInfo::vetoDetMgr()->getDetectorElement(id); + // } else if (theHit->isTrigger()) { + // Identifier id = VP1DetInfo::triggerIDHelper()->plate_id( Station, + // thehit->getPlate() ); + // //fixme: id is_valid ? + // detelem = VP1DetInfo::triggerDetMgr()->getDetectorElement(id); + // } else if (theHit->isPreshower()) { + // Identifier id = VP1DetInfo::preshowerIDHelper()->plate_id( Station, + // thehit->getPlate() ); + } + //Fixme : Handle case where detelem can not be found gracefully. And check pointers from VP1DetInfo!! + if (!detelem) + VP1Msg::messageDebug("SimHitHandle_ScintHit ERROR: Could not get detector element for hit!"); + return detelem!=0; +} + +//____________________________________________________________________ +//Trk::GlobalMomentum SimHitHandle_SiHit::momentumDirection() const +Amg::Vector3D SimHitHandle_ScintHit::momentumDirection() const +{ + if (VP1Msg::verbose()&&m_d->thehit->localEndPosition()==m_d->thehit->localStartPosition()) + VP1Msg::messageVerbose("SimHitHandle_ScintHit::momentumDirection() ERROR: posStart()==posEnd()"); + return (posEnd()-posStart()).unit(); +} + +//____________________________________________________________________ +Amg::Vector3D SimHitHandle_ScintHit::Imp::localToGlobal( const HepGeom::Point3D<double>& local ) const +{ + if (!ensureDetElemInit()) + return Amg::Vector3D(0,0,0); + return Amg::Vector3D(Amg::EigenTransformToCLHEP(detelem->transformHit()) * local); +} + +//____________________________________________________________________ +Amg::Vector3D SimHitHandle_ScintHit::posStart() const +{ + return m_d->localToGlobal(m_d->thehit->localStartPosition()); +} + +//____________________________________________________________________ +Amg::Vector3D SimHitHandle_ScintHit::posEnd() const +{ + return m_d->localToGlobal(m_d->thehit->localEndPosition()); +} + +//____________________________________________________________________ +double SimHitHandle_ScintHit::hitTime() const +{ + return m_d->thehit->meanTime(); +} + +//____________________________________________________________________ +const HepMcParticleLink& SimHitHandle_ScintHit::particleLink() const +{ + return m_d->thehit->particleLink(); +} + +//____________________________________________________________________ +Trk::TrackParameters * SimHitHandle_ScintHit::createTrackParameters() const +{ + //Find charge and magnitude of momentum: + double c; + if ( !hasCharge() ) { + bool ok; + c = VP1ParticleData::particleCharge(pdg(),ok); + if (!ok) { + VP1Msg::message("SimHitHandle_ScintHit::createTrackParameters ERROR: Could not find particle charge (pdg=" + +QString::number(pdg())+"). Assuming charge=+1."); + c = +1.0; + } else { + if (VP1Msg::verbose()) + VP1Msg::messageVerbose("Looked up particle charge for scintillator simhit with pdg code "+VP1Msg::str(pdg())+": "+VP1Msg::str(c)); + } + const_cast<SimHitHandle_ScintHit*>(this)->setCharge(c); + } else { + c = charge(); + } + + double mom = momentum(); + if (mom<=0) { + VP1Msg::message("SimHitHandle_ScintHit::createTrackParameters ERROR: Unknown momentum. Using 1 GeV"); + mom = 1*CLHEP::GeV; + } + + ////We could in principle get a surface like this: + // if (!m_d->ensureDetElemInit()) { + // VP1Msg::messageDebug("SimHitHandle_SiHit WARNING: Could not get detector element!"); + // return 0; + // } + // const Trk::PlaneSurface * surf + // = dynamic_cast<const Trk::PlaneSurface *>( &(m_d->detelem->surface())); + // if (!surf) { + // VP1Msg::message("SimHitHandle_SiHit::createTrackParameters ERROR: could not get Trk::PlaneSurface"); + // return 0; + // } + ////And then proceed to construct a new AtaPlane parameter with that + ////surface. However, that gives some problems, so instead we simply + ////create a perigee: + + const Amg::Vector3D globpos = posStart(); + +// const Trk::GlobalMomentum u(momentumDirection()); + const Amg::Vector3D u(momentumDirection()); + + return new Trk::Perigee(0, 0, u.phi(), u.theta(), c/mom, globpos); +} diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/SimHitHandle_TrackRecord.cxx b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/SimHitHandle_TrackRecord.cxx new file mode 100644 index 000000000..816c08f3e --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/SimHitHandle_TrackRecord.cxx @@ -0,0 +1,63 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class SimHitHandle_TrackRecord // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: May 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12TrackSystems/SimHitHandle_TrackRecord.h" +#include "VTI12Utils/VP1ParticleData.h" +#include "VP1Base/VP1Msg.h" + +#include "GeneratorObjects/HepMcParticleLink.h" +#include "TrkSurfaces/PlaneSurface.h" + +#include "TrkParameters/TrackParameters.h" + +//____________________________________________________________________ +SimHitHandle_TrackRecord::SimHitHandle_TrackRecord(const TrackRecord* tr) + : SimHitHandleBase(), + m_trkrecord(const_cast<TrackRecord*>(tr)), + m_mom(m_trkrecord->GetMomentum().mag()), + m_momdir( Amg::Hep3VectorToEigen( m_trkrecord->GetMomentum().unit() ) ), + m_link( new HepMcParticleLink(m_trkrecord->GetBarCode()))//NB: We assume an event index of 0 here!!! +{ +} + +//____________________________________________________________________ +SimHitHandle_TrackRecord::~SimHitHandle_TrackRecord() +{ + delete m_link; +} + +//____________________________________________________________________ +Trk::TrackParameters * SimHitHandle_TrackRecord::createTrackParameters() const +{ + Amg::Transform3D transf = Amg::CLHEPTranslate3DToEigen(HepGeom::Translate3D(m_trkrecord->GetPosition().x(),m_trkrecord->GetPosition().y(),m_trkrecord->GetPosition().z())); + //Surface: + const Trk::PlaneSurface * surf + = new Trk::PlaneSurface( &transf ); + //Fixme: surface and transform ever DELETED?? + + //Fixme: Don't do this in every simhit!!: + bool hasCharge; + double charge; + charge = VP1ParticleData::particleCharge(pdg(),hasCharge); + if (!hasCharge) { + VP1Msg::message("SimHitHandle_TrackRecord::createTrackParameters ERROR: Could not find particle charge (pdg=" + +QString::number(pdg())+"). Assuming charge=+1."); + charge = +1.0; + } else { + if (VP1Msg::verbose()) + VP1Msg::messageVerbose("Looked up particle charge for track record with pdg code "+VP1Msg::str(pdg())+": "+VP1Msg::str(charge)); + } + return new Trk::AtaPlane(posStart(), Amg::Hep3VectorToEigen(m_trkrecord->GetMomentum()),charge,*surf); +} + diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCollHandleBase.cxx b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCollHandleBase.cxx new file mode 100644 index 000000000..a37d36c15 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCollHandleBase.cxx @@ -0,0 +1,1256 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class TrackCollHandleBase // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: February 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12TrackSystems/TrackCollHandleBase.h" +#include "VTI12TrackSystems/VP1TrackSystem.h" +#include "VTI12TrackSystems/TrackHandleBase.h" +#include "VTI12TrackSystems/TrackSystemController.h" +#include "VTI12TrackSystems/AscObjSelectionManager.h" +#include "VTI12TrackSystems/AscObj_TSOS.h" +#include "VTI12TrackSystems/TrackCollectionSettingsButton.h" + +#include "VP1Base/VP1ExtraSepLayerHelper.h" +#include "VP1Utils/VP1LinAlgUtils.h" +#include "VP1Base/IVP13DSystem.h" +#include "VP1Base/VP1QtInventorUtils.h" +#include "VP1Base/VP1Serialise.h" +#include "VP1Base/VP1Deserialise.h" +#include "VP1Base/VP1CustomTourEditor.h" +#include "VP1Base/VP1Msg.h" + + +#include <Inventor/nodes/SoSeparator.h> +#include <Inventor/nodes/SoMaterial.h> +#include <Inventor/nodes/SoSwitch.h> +#include "Inventor/nodes/SoDrawStyle.h" +#include "Inventor/nodes/SoLightModel.h" + +#include "EventPrimitives/EventPrimitives.h" +#include "GeoPrimitives/GeoPrimitives.h" + +#include <QComboBox> +#include <QTreeWidgetItem> + +#include <qdatetime.h> +#include <vector> + +// #include "VP1TrackSystems/TrackObjectBrowserController.h" + + +//____________________________________________________________________ +class TrackCollHandleBase::Imp { +public: + TrackCollHandleBase * theclass; + QString name; + + //Vector of track handles: + std::vector<TrackHandleBase*> trackhandles; + //For iteration: + std::vector<TrackHandleBase*>::iterator itTrackHandles; + std::vector<TrackHandleBase*>::iterator itTrackHandlesEnd; + + Trk::IExtrapolator * lastUsedPropagator; + bool notifystatesave; + + TrackCommonFlags::TSOSPartsFlags shownTSOSParts; + TrackCommonFlags::TSOSPartsFlags customColouredTSOSParts; + bool tsos_useShortTRTMeasurements; + bool tsos_useShortMDTMeasurements; + bool tsos_drawMeasGlobalPositions; + double tsos_measurementsShorttubesScale; + double tsos_nStdDevForParamErrors; + int tsos_numberOfPointsOnCircles; + double tsos_materialEffectsOnTrackScale; + bool tsos_parTubeErrorsDrawCylinders; + + //Extra widgets: + QComboBox * comboBox_colourby; + + static QString comboBoxEntry_ColourByCollection() { return "Uniform"; } + static QString comboBoxEntry_ColourByRandom() { return "Random"; } + static QString comboBoxEntry_ColourByMomentum() { return "Mom."; } + static QString comboBoxEntry_ColourByCharge() { return "Charge"; } + static QString comboBoxEntry_ColourByPID() { return "PID"; } + static QString comboBoxEntry_ColourByDistanceFromSelectedTrack() { return "Dist. Sel."; } + static QString comboBoxEntry_ColourByVertex() { return "Vertex"; } + + QTreeWidgetItem* objBrowseTree; + TrackCollectionSettingsButton * matButton; + bool last_useDefaultCuts; +}; + + + +//____________________________________________________________________ +TrackCollHandleBase::TrackCollHandleBase( TrackSysCommonData * cd, + const QString& name, + TrackType::Type type) + : VP1StdCollection(cd->system(),"TrackCollHandle_"+TrackType::typeToString(type)+"_"+name), m_d(new Imp), + m_nshownhandles(0), m_type(type), + m_commonData(cd), + m_sephelper(0), + m_propagator(0), + m_propagationOptions(TrackSystemController::NoPropOptions), + m_propMaxRadius(0.0), + m_parts(TrackCommonFlags::NoParts), + m_labels(TrackSystemController::NoLabels), m_labelsTrkOffset(0.0), + m_trackTubeRadius(0.0), + m_colourby(COLOUR_PERCOLLECTION), + m_cut_allowedPtSq(VP1Interval()), + m_cut_allowedEta(VP1Interval()), + m_cut_allowedPhi(QList<VP1Interval>()), + m_cut_requiredNHits(QList<unsigned>()), + m_cut_pt_allowall(false), + m_cut_eta_allowall(false), + m_cut_phi_allowall(false), + m_cut_etaptphi_allwillfail(true) +{ + m_d->theclass = this; + m_d->name = name; + m_d->lastUsedPropagator = 0; + m_d->notifystatesave = false; + m_d->shownTSOSParts = TrackCommonFlags::TSOS_NoObjects; + m_d->customColouredTSOSParts = TrackCommonFlags::TSOS_NoObjects; + //Fixme: to avoid double work on startup, these should have the same + //values here as the controller defaults: + m_d->tsos_useShortTRTMeasurements = true; + m_d->tsos_useShortMDTMeasurements = true; + m_d->tsos_drawMeasGlobalPositions = false; + m_d->tsos_measurementsShorttubesScale = 2.0; + m_d->tsos_nStdDevForParamErrors = false; + m_d->tsos_numberOfPointsOnCircles = 12; + m_d->tsos_materialEffectsOnTrackScale = 2.0; + m_d->tsos_parTubeErrorsDrawCylinders = false; + + m_d->comboBox_colourby = new QComboBox; + m_d->objBrowseTree = 0; + m_d->matButton=0; +} + +//____________________________________________________________________ +void TrackCollHandleBase::init(VP1MaterialButtonBase*) +{ + m_d->matButton = new TrackCollectionSettingsButton; + m_d->matButton->setText(text()); + VP1StdCollection::init(m_d->matButton);//this call is required. Passing in TrackCollectionSettingsButton means we have the more complex button. + + setupSettingsFromController(common()->controller()); + + //Setup colour by: + m_d->comboBox_colourby->setToolTip("Determine how tracks from this collection are coloured.\n The 'Dist. Sel.' option means the tracks will be coloured by distance from the last selected track. "); + QStringList l; + l << Imp::comboBoxEntry_ColourByCollection(); + l << Imp::comboBoxEntry_ColourByRandom(); + if (allowColourByPID()) + l << Imp::comboBoxEntry_ColourByPID(); + if (allowColourByMomentum()) + l << Imp::comboBoxEntry_ColourByMomentum(); + if (allowColourByCharge()) + l << Imp::comboBoxEntry_ColourByCharge(); + if (allowColourByDistanceFromSelectedTrack()) + l << Imp::comboBoxEntry_ColourByDistanceFromSelectedTrack(); + if (allowColourByVertex()) { + // messageVerbose("Allow colour by vertex!"); + l << Imp::comboBoxEntry_ColourByVertex(); + } + m_d->comboBox_colourby->addItems(l); + m_d->comboBox_colourby->setCurrentIndex(0);//corresponds to per collection. + connect(m_d->comboBox_colourby,SIGNAL(currentIndexChanged(int)), + this,SLOT(colourByComboBoxItemChanged())); + + connect(this,SIGNAL(visibilityChanged(bool)),this,SLOT(collVisibilityChanged(bool))); + setColourBy(defaultColourBy()); + + // add stuff to control per collection settings. + collSwitch()->addChild(m_d->matButton->trackLightModel()); + collSwitch()->addChild(m_d->matButton->trackDrawStyle()); +} + +//____________________________________________________________________ +TrackCollHandleBase::~TrackCollHandleBase() +{ + messageVerbose("destructor start"); + cleanupPtrContainer(m_d->trackhandles); + if (m_sephelper) { + SoSeparator * sep = m_sephelper->topSeparator(); + sep->ref(); + delete m_sephelper; + sep->unref(); + } + delete m_d; + messageVerbose("destructor end"); +} + +//____________________________________________________________________ +void TrackCollHandleBase::setupSettingsFromController(TrackSystemController* controller) +{ + messageVerbose("setupSettingsFromController start"); + + assert(controller); + largeChangesBegin(); + + connect(controller->customTourEditor(),SIGNAL(clipVolumeRadiusChanged(double)),this,SLOT(clipVolumeChanged(double))); + + connect(controller,SIGNAL(propagatorChanged(Trk::IExtrapolator *)),this,SLOT(setPropagator(Trk::IExtrapolator *))); + setPropagator(controller->propagator()); + + connect(controller,SIGNAL(propagationOptionsChanged(TrackSystemController::PropagationOptionFlags)),this,SLOT(setPropagationOptions(TrackSystemController::PropagationOptionFlags))); + setPropagationOptions(controller->propagationOptions()); + + connect(controller,SIGNAL(propMaxRadiusChanged(float)),this,SLOT(setPropMaxRadius(float))); + setPropMaxRadius(controller->propMaxRadius()); + + // Doing this in a slightly different way to avoid making lots of new stuff in controller. + connect(controller,SIGNAL(extrapolateToThisVolumeChanged(void)),this,SLOT(extrapolateToThisVolumeChanged(void))); + + connect(controller,SIGNAL(shownTrackPartsChanged(TrackCommonFlags::TrackPartsFlags)),this,SLOT(setParts(TrackCommonFlags::TrackPartsFlags))); + connect(m_d->matButton,SIGNAL(hideActualTrackPathChanged(bool)),this,SLOT(setActualPathShown(bool))); + setParts(controller->shownTrackParts()); + + connect(controller,SIGNAL(vertexProjectionAngleChanged(int)),this,SLOT(setParts(int))); + setParts(controller->vertexProjectionAngle()); + + // connect(controller,SIGNAL(trackTubeRadiusChanged(const double&)),this,SLOT(setTrackTubeRadius(const double&))); + connect(m_d->matButton,SIGNAL(trackTubeRadiusChanged(const double&)),this,SLOT(setTrackTubeRadius(const double&))); + setTrackTubeRadius(m_d->matButton->trackTubeRadius()); + + connect(controller,SIGNAL(rerandomise()),this,SLOT(rerandomiseRandomTrackColours())); + + connect(common()->system(),SIGNAL(newTrackSelected( const TrackHandleBase&)),this,SLOT(trackSelectionChanged())); + + //cuts + connect(m_d->matButton,SIGNAL(useDefaultCutsChanged(bool)),this,SLOT(setUseDefaultCuts(bool))); + setUseDefaultCuts(m_d->matButton->useDefaultCuts()); + + connect(controller,SIGNAL(cutAllowedPtChanged(const VP1Interval&)),this,SLOT(setCutAllowedPt(const VP1Interval&))); + connect(m_d->matButton,SIGNAL(cutAllowedPtChanged(const VP1Interval&)),this,SLOT(setCutAllowedPt(const VP1Interval&))); + setCutAllowedPt(useDefaultCuts()?controller->cutAllowedPt():m_d->matButton->cutAllowedPt()); + + connect(controller,SIGNAL(cutAllowedEtaChanged(const VP1Interval&)),this,SLOT(setCutAllowedEta(const VP1Interval&))); + connect(m_d->matButton,SIGNAL(cutAllowedEtaChanged(const VP1Interval&)),this,SLOT(setCutAllowedEta(const VP1Interval&))); + setCutAllowedEta(useDefaultCuts()?controller->cutAllowedEta():m_d->matButton->cutAllowedEta()); + + connect(controller,SIGNAL(cutAllowedPhiChanged(const QList<VP1Interval>&)),this,SLOT(setCutAllowedPhi(const QList<VP1Interval>&))); + connect(m_d->matButton,SIGNAL(cutAllowedPhiChanged(const QList<VP1Interval>&)),this,SLOT(setCutAllowedPhi(const QList<VP1Interval>&))); + setCutAllowedPhi(useDefaultCuts()?controller->cutAllowedPhi():m_d->matButton->cutAllowedPhi()); + + connect(controller,SIGNAL(cutRequiredNHitsChanged(const QList<unsigned>&)),this,SLOT(setRequiredNHits(const QList<unsigned>&))); + connect(m_d->matButton,SIGNAL(cutRequiredNHitsChanged(const QList<unsigned>&)),this,SLOT(setRequiredNHits(const QList<unsigned>&))); + setRequiredNHits(useDefaultCuts()?controller->cutRequiredNHits():m_d->matButton->cutRequiredNHits()); + + connect(controller,SIGNAL(cutOnlyVertexAssocTracksChanged(bool)),this,SLOT(setOnlyVertexAssocTracks(bool))); + connect(m_d->matButton,SIGNAL(cutOnlyVertexAssocTracksChanged(bool)),this,SLOT(setOnlyVertexAssocTracks(bool))); + setOnlyVertexAssocTracks(useDefaultCuts()?controller->cutOnlyVertexAssocTracks():m_d->matButton->cutOnlyVertexAssocTracks()); + + connect(controller,SIGNAL(customColouredTSOSPartsChanged(TrackCommonFlags::TSOSPartsFlags)), + this,SLOT(setCustomColouredTSOSParts(TrackCommonFlags::TSOSPartsFlags))); + setCustomColouredTSOSParts(controller->customColouredTSOSParts()); + + connect(controller,SIGNAL(drawMeasGlobalPositionsChanged(bool)),this,SLOT(setDrawMeasGlobalPositions(bool))); + setDrawMeasGlobalPositions(controller->drawMeasGlobalPositions()); + + connect(controller,SIGNAL(measurementsShorttubesScaleChanged(double)),this,SLOT(setMeasurementsShorttubesScale(double))); + setMeasurementsShorttubesScale(controller->measurementsShorttubesScale()); + + connect(controller,SIGNAL(nStdDevForParamErrorsChanged(const double&)),this,SLOT(setNStdDevForParamErrors(const double&))); + setNStdDevForParamErrors(controller->nStdDevForParamErrors()); + + connect(controller,SIGNAL(numberOfPointsOnCirclesChanged(int)),this,SLOT(setNumberOfPointsOnCircles(int))); + setNumberOfPointsOnCircles(controller->numberOfPointsOnCircles()); + + connect(controller,SIGNAL(materialEffectsOnTrackScaleChanged(double)),this,SLOT(setMaterialEffectsOnTrackScale(double))); + setMaterialEffectsOnTrackScale(controller->materialEffectsOnTrackScale()); + + connect(controller,SIGNAL(parTubeErrorsDrawCylindersChanged(bool)),this,SLOT(setParTubeErrorsDrawCylinders(bool))); + setParTubeErrorsDrawCylinders(controller->parTubeErrorsDrawCylinders()); + + connect(controller,SIGNAL(shownTSOSPartsChanged(TrackCommonFlags::TSOSPartsFlags)), + this,SLOT(setShownTSOSParts(TrackCommonFlags::TSOSPartsFlags))); + setShownTSOSParts(controller->shownTSOSParts()); + + connect(controller,SIGNAL(customColouredTSOSPartsChanged(TrackCommonFlags::TSOSPartsFlags)), + this,SLOT(setCustomColouredTSOSParts(TrackCommonFlags::TSOSPartsFlags))); + setCustomColouredTSOSParts(controller->customColouredTSOSParts()); + + connect(controller,SIGNAL(trackLabelsChanged(TrackSystemController::TrackLabelModes)),this,SLOT(setLabels(TrackSystemController::TrackLabelModes))); + connect(controller,SIGNAL(trackLabelTrkOffsetChanged(float)),this,SLOT(setLabelTrkOffset(float))); + connect(controller,SIGNAL(trackLabelPosOffsetChanged(QList<int>)),this,SLOT(setLabelPosOffsets(QList<int>))); + setLabels(controller->trackLabels()); + + setupSettingsFromControllerSpecific(controller); + + largeChangesEnd(); + messageVerbose("setupSettingsFromController end"); + +} + +//____________________________________________________________________ +QString TrackCollHandleBase::name() const +{ + return m_d->name; +} + +//____________________________________________________________________ +bool TrackCollHandleBase::cut(TrackHandleBase* handle) +{ + // if (m_cut_etaptphi_allwillfail) + // return false; + + // messageVerbose("TrackCollHandleBase::cut - checking hit cuts."); + // if (mightHaveSubSystemHitInfo()&&!m_cut_requiredNHits.isEmpty()&&handle->hasSubSystemHitInfo()) { + // assert(m_cut_requiredNHits.count()==4); + // // Only apply ID cuts to tracks which have ID hits (so ID only and combined muons) + // if (handle->isIDTrack()){ + // if (handle->getNPixelHits()<m_cut_requiredNHits[0]) return false; + // if (handle->getNSCTHits()<m_cut_requiredNHits[1]) return false; + // if (handle->getNTRTHits()<m_cut_requiredNHits[2]) return false; + // } + // } + + if (!m_cut_pt_allowall||!m_cut_eta_allowall||!m_cut_phi_allowall) + { +// Trk::GlobalMomentum mom(handle->momentum()); + Amg::Vector3D mom(handle->momentum()); + + // convention is that if interval is real and negative, then P cut rather than pT + bool isPCut = (!m_cut_allowedPtSq.noLowerBound() && m_cut_allowedPtSq.lower()<=0) + || (!m_cut_allowedPtSq.noUpperBound() && m_cut_allowedPtSq.upper()<=0); + + if (mom.mag2()!=0.0) { + if (!m_cut_pt_allowall&&!isPCut && !m_cut_allowedPtSq.contains(mom.perp2())) + return false; + if (!m_cut_pt_allowall&& isPCut && !m_cut_allowedPtSq.contains(-mom.mag2())) + return false; + +// if (!m_cut_eta_allowall&&!m_cut_allowedEta.contains(mom.pseudoRapidity())){ + if (!m_cut_eta_allowall&&!m_cut_allowedEta.contains(mom.eta())){ // migration to Amg (Eigen) + return false; + } + if (!m_cut_phi_allowall) { + double phi = VP1LinAlgUtils::phiFromXY(mom.x(), mom.y() ); + bool ok(false); + foreach (VP1Interval phirange, m_cut_allowedPhi) { + if (phirange.contains(phi)||phirange.contains(phi+2*M_PI)||phirange.contains(phi-2*M_PI)) { + ok = true; + break; + } + } + if (!ok) + return false; + } + } + } + + if (cutOnlyVertexAssocTracks()){ + // std::cout<<"cutOnlyVertexAssocTracks: "<<handle<<",\t: "<<common()->system()->materialFromVertex(handle)<<std::endl; + return common()->system()->materialFromVertex(handle)!=0; // return false if no vertex material associated to this track + } + + return true; +} + +//____________________________________________________________________ +void TrackCollHandleBase::recheckCutStatus(TrackHandleBase* handle) +{ + handle->setVisible( visible() && cut(handle)); +} + +//____________________________________________________________________ +void TrackCollHandleBase::recheckCutStatusOfAllVisibleHandles() +{ + if (!isLoaded()) + return; + + //This method is called when a cut is tightened - thus we better start by deselectAll to avoid weird highlighting issues. + common()->system()->deselectAll(); + + largeChangesBegin(); + std::vector<TrackHandleBase*>::iterator it(m_d->trackhandles.begin()),itE(m_d->trackhandles.end()); + for (;it!=itE;++it) { + if ((*it)->visible()) + recheckCutStatus(*it); + } + updateObjectBrowserVisibilityCounts(); + largeChangesEnd(); + + message("recheckCutStatusOfAllVisibleHandles: "+str(nShownHandles())+"/"+str(m_d->trackhandles.size())+" pass cuts"); +} + +//____________________________________________________________________ +void TrackCollHandleBase::recheckCutStatusOfAllNotVisibleHandles() +{ + if (!isLoaded()) + return; + + largeChangesBegin(); + std::vector<TrackHandleBase*>::iterator it(m_d->trackhandles.begin()),itE(m_d->trackhandles.end()); + for (;it!=itE;++it) { + if (!(*it)->visible()) + recheckCutStatus(*it); + } + updateObjectBrowserVisibilityCounts(); + largeChangesEnd(); + + message("recheckCutStatusOfAllNotVisibleHandles: "+str(nShownHandles())+"/"+str(m_d->trackhandles.size())+" pass cuts"); +} + +//____________________________________________________________________ +void TrackCollHandleBase::recheckCutStatusOfAllHandles() +{ + if (!isLoaded()) + return; + largeChangesBegin(); + std::vector<TrackHandleBase*>::iterator it(m_d->trackhandles.begin()),itE(m_d->trackhandles.end()); + for (;it!=itE;++it) + recheckCutStatus(*it); + updateObjectBrowserVisibilityCounts(); + largeChangesEnd(); + + message("recheckCutStatusOfAllHandles: "+str(nShownHandles())+"/"+str(m_d->trackhandles.size())+" pass cuts"); +} + +//____________________________________________________________________ +void TrackCollHandleBase::update3DObjectsOfAllHandles(bool invalidatePropagatedPoints, float maxR ) +{ + if (!isLoaded()) + return; + if (VP1Msg::verbose()) + messageVerbose("update3DObjectsOfAllHandles start (" + "invalidatePropagatedPoints = " + +str(invalidatePropagatedPoints)+")"); + largeChangesBegin(); + std::vector<TrackHandleBase*>::iterator it(m_d->trackhandles.begin()),itE(m_d->trackhandles.end()); + for (;it!=itE;++it) + (*it)->update3DObjects(invalidatePropagatedPoints, maxR); + largeChangesEnd(); + messageVerbose("update3DObjectsOfAllHandles end"); +} + + + +// //____________________________________________________________________ +// void TrackCollHandleBase::updateInDetProjectionsOfAllHandles() +// { +// if (!isLoaded()) +// return; +// messageVerbose("updateInDetProjectionsOfAllHandles start"); +// largeChangesBegin(); +// std::vector<TrackHandleBase*>::iterator it(m_d->trackhandles.begin()),itE(m_d->trackhandles.end()); +// for (;it!=itE;++it) +// (*it)->updateInDetProjections(); +// largeChangesEnd(); +// messageVerbose("updateInDetProjectionsOfAllHandles end"); + +// } + +//____________________________________________________________________ +void TrackCollHandleBase::updateMaterialOfAllHandles() +{ + if (!isLoaded()) + return; + messageVerbose("updateMaterialOfAllHandles start"); + largeChangesBegin(); + std::vector<TrackHandleBase*>::iterator it(m_d->trackhandles.begin()),itE(m_d->trackhandles.end()); + for (;it!=itE;++it) + (*it)->updateMaterial(); + largeChangesEnd(); + messageVerbose("updateMaterialOfAllHandles end"); +} + +//____________________________________________________________________ +void TrackCollHandleBase::hintNumberOfTracksInEvent(unsigned n) +{ + m_d->trackhandles.reserve(n); +} + +//____________________________________________________________________ +void TrackCollHandleBase::addTrackHandle(TrackHandleBase* handle) +{ + m_d->trackhandles.push_back(handle); +} + +//____________________________________________________________________ +void TrackCollHandleBase::setPropagator( Trk::IExtrapolator * p) +{ + bool ignoreMEOT = common()->controller()->ignoreMeasurementEffectsOnTrackInProp(); + messageVerbose("setPropagator ("+str(p)+") "+ (ignoreMEOT?str("ignoring MEOT"):str("using MEOT")) ); + if (m_propagator==p) + return; + messageVerbose("setPropagator ==> Changed"); + m_propagator=p; + bool mustUpdatePropagatedPoints = (p && m_d->lastUsedPropagator!=p); + update3DObjectsOfAllHandles(mustUpdatePropagatedPoints); + if (p) + m_d->lastUsedPropagator = p; +} + +void TrackCollHandleBase::setPropagationOptions( TrackSystemController::PropagationOptionFlags options){ + messageVerbose("setPropagationOptions ==> Changed"); + m_propagationOptions=options; + update3DObjectsOfAllHandles(true); +} + +void TrackCollHandleBase::setPropMaxRadius( float radius){ + messageVerbose("setPropMaxRadius ==> Changed to "+str(radius)); + m_propMaxRadius=radius; + update3DObjectsOfAllHandles(true, radius); +} + +void TrackCollHandleBase::extrapolateToThisVolumeChanged(void){ + messageVerbose("extrapolateToThisVolume ==> Changed"); + update3DObjectsOfAllHandles(true); +} + +void TrackCollHandleBase::clipVolumeChanged(double radius){ + messageVerbose("clipVolumeChanged ==> Changed"); + update3DObjectsOfAllHandles(false, radius); +} + +//____________________________________________________________________ +void TrackCollHandleBase::setParts( TrackCommonFlags::TrackPartsFlags parts ) +{ + messageVerbose("setParts called"); + if (m_parts==parts) + return; + messageVerbose("setParts ==> Changed"); + m_parts = parts; + update3DObjectsOfAllHandles(); +} + +//____________________________________________________________________ +void TrackCollHandleBase::setParts( int angle) +{ + messageVerbose("setParts(int) called with angle="+str(angle)); + //bit of a hack this- didn't want to make entire new machinery just to track angle. + // FIXME + update3DObjectsOfAllHandles(true); +} + +//____________________________________________________________________ +void TrackCollHandleBase::setActualPathShown( bool hide) +{ + messageVerbose("setActualPathShown(bool) called with hide="+str(hide)); + + TrackCommonFlags::TrackPartsFlags parts = m_parts; + if (hide) parts &= ~TrackCommonFlags::ActualPath; + else parts |= TrackCommonFlags::ActualPath; + setParts(parts); +} + +//____________________________________________________________________ +void TrackCollHandleBase::setLabels( TrackSystemController::TrackLabelModes labels ) +{ + messageVerbose("setLabels called"); + if (m_labels==labels) + return; + messageVerbose("setLabels ==> Changed"); + m_labels = labels; + update3DObjectsOfAllHandles(); +} + +//____________________________________________________________________ +void TrackCollHandleBase::setLabelTrkOffset( float offset) +{ + messageVerbose("setLabelTrkOffset called"); + if (m_labelsTrkOffset==offset) + return; + messageVerbose("setLabelTrkOffset ==> Changed to "+QString::number(offset)); + m_labelsTrkOffset = offset; + update3DObjectsOfAllHandles(); +} + +//____________________________________________________________________ +void TrackCollHandleBase::setLabelPosOffsets( QList<int> offsets) +{ + messageVerbose("setLabelPosOffsets called"); + if (m_labelsPosOffsets==offsets) + return; + messageVerbose("setLabelPosOffsets ==> Changed"); + m_labelsPosOffsets = offsets; + update3DObjectsOfAllHandles(); +} + +//____________________________________________________________________ +void TrackCollHandleBase::setTrackTubeRadius(const double& r) +{ + messageVerbose("setTrackTubeRadius called"); + if (m_trackTubeRadius==r) + return; + m_trackTubeRadius=r; + messageVerbose("setTrackTubeRadius ==> Changed"); + update3DObjectsOfAllHandles(); +} + +//____________________________________________________________________ +void TrackCollHandleBase::setColourBy( TrackCollHandleBase::COLOURBY cb ) +{ + messageVerbose("setColourBy called"); + if (m_colourby==cb) + return; + messageVerbose("setColourBy ==> Changed"); + m_colourby=cb; + + //Update gui combobox: + QString targetText; + switch(cb) { + case COLOUR_BYPID: + targetText = Imp::comboBoxEntry_ColourByPID(); + break; + case COLOUR_RANDOM: + targetText = Imp::comboBoxEntry_ColourByRandom(); + break; + case COLOUR_MOMENTUM: + targetText = Imp::comboBoxEntry_ColourByMomentum(); + break; + case COLOUR_CHARGE: + targetText = Imp::comboBoxEntry_ColourByCharge(); + break; + case COLOUR_DISTANCE: + targetText = Imp::comboBoxEntry_ColourByDistanceFromSelectedTrack(); + break; + case COLOUR_VERTEX: + targetText = Imp::comboBoxEntry_ColourByVertex(); + break; + default: + case COLOUR_PERCOLLECTION: + targetText = Imp::comboBoxEntry_ColourByCollection(); + break; + } + if (targetText!=m_d->comboBox_colourby->currentText()) { + int i = m_d->comboBox_colourby->findText(targetText); + if (i>=0&&i<m_d->comboBox_colourby->count()) { + bool save = m_d->comboBox_colourby->blockSignals(true); + m_d->comboBox_colourby->setCurrentIndex(i); + m_d->comboBox_colourby->blockSignals(save); + } else { + message("ERROR: Problems finding correct text in combo box"); + } + } + + //Actual material updates: + largeChangesBegin(); + m_commonData->system()->deselectAll();//Todo: Reselect the selected track handles + //afterwards (collhandles should know selected handles) + updateMaterialOfAllHandles(); + largeChangesEnd(); + +} + +//____________________________________________________________________ +void TrackCollHandleBase::rerandomiseRandomTrackColours() +{ + if (!isLoaded()) + return; + messageVerbose("rerandomiseRandomTrackColours start"); + largeChangesBegin(); + std::vector<TrackHandleBase*>::iterator it(m_d->trackhandles.begin()),itE(m_d->trackhandles.end()); + for (;it!=itE;++it) + (*it)->rerandomiseRandomMaterial(); + largeChangesEnd(); + messageVerbose("rerandomiseRandomTrackColours end"); +} + +//____________________________________________________________________ +void TrackCollHandleBase::trackSelectionChanged() +{ + if (!isLoaded() || colourBy()!= COLOUR_DISTANCE) + return; + messageVerbose("trackSelectionChanged start"); + largeChangesBegin(); + std::vector<TrackHandleBase*>::iterator it(m_d->trackhandles.begin()),itE(m_d->trackhandles.end()); + for (;it!=itE;++it) + (*it)->updateMaterial(); + largeChangesEnd(); + messageVerbose("trackSelectionChanged end"); +} + +//____________________________________________________________________ +void TrackCollHandleBase::trackHandleIterationBegin() +{ + m_d->itTrackHandles = m_d->trackhandles.begin(); + m_d->itTrackHandlesEnd = m_d->trackhandles.end(); +} + +//____________________________________________________________________ +TrackHandleBase* TrackCollHandleBase::getNextTrackHandle() { + if (m_d->itTrackHandles==m_d->itTrackHandlesEnd) + return 0; + else + return *(m_d->itTrackHandles++); +} + + +void TrackCollHandleBase::setUseDefaultCuts(bool useDefaults){ + if (m_d->last_useDefaultCuts==useDefaults) return; + messageVerbose("setUseDefaultCuts changed to "+str(useDefaults)+"- rechecking all handles"); + // recheckCutStatusOfAllHandles(); + + setCutAllowedPt(useDefaultCuts()? common()->controller()->cutAllowedPt():m_d->matButton->cutAllowedPt()); + setCutAllowedEta(useDefaultCuts()?common()->controller()->cutAllowedEta():m_d->matButton->cutAllowedEta()); + setCutAllowedPhi(useDefaultCuts()?common()->controller()->cutAllowedPhi():m_d->matButton->cutAllowedPhi()); + setRequiredNHits(useDefaultCuts()?common()->controller()->cutRequiredNHits():m_d->matButton->cutRequiredNHits()); + setOnlyVertexAssocTracks(useDefaultCuts()?common()->controller()->cutOnlyVertexAssocTracks():m_d->matButton->cutOnlyVertexAssocTracks()); +} + +//____________________________________________________________________ +void TrackCollHandleBase::setCutAllowedPt(const VP1Interval& allowedpt) +{ + if (!allowedpt.isSane()) + return; + + //why do we need to do this? Why does it matter if it's negative? + //double minptsq = allowedpt.lower() <= 0.0 ? -std::numeric_limits<double>::infinity() : allowedpt.lower()*allowedpt.lower(); + //VP1Interval allowedptsq(minptsq,allowedpt.upper()*allowedpt.upper()); + + //Modified code from EJWM + double signMin = allowedpt.lower()<0.0 ? -1.0 : 1.0; + double signMax = allowedpt.upper()<0.0 ? -1.0 : 1.0; + double minptsq = allowedpt.lower() == -std::numeric_limits<double>::infinity() ? -std::numeric_limits<double>::infinity() : signMin*(allowedpt.lower()*allowedpt.lower()); + double maxptsq = allowedpt.upper() == std::numeric_limits<double>::infinity() ? std::numeric_limits<double>::infinity() : signMax*(allowedpt.upper()*allowedpt.upper()); + + VP1Interval allowedptsq(minptsq,maxptsq); + // std::cout<<"allowedptsq:isAllR"<<allowedptsq.isAllR()<<std::endl; + // std::cout<<"allowedptsq.isEmpty()"<<allowedptsq.isEmpty()<<std::endl; + + + if (m_cut_allowedPtSq==allowedptsq) + return; + m_cut_pt_allowall = allowedptsq.isAllR(); + m_cut_etaptphi_allwillfail = allowedptsq.isEmpty() || m_cut_allowedEta.isEmpty() || m_cut_allowedPhi.isEmpty(); + + if (!m_cut_allowedPtSq.contains(allowedptsq)&&!allowedptsq.contains(m_cut_allowedPtSq)) { + m_cut_allowedPtSq = allowedptsq; + recheckCutStatusOfAllHandles(); + return; + } + bool relaxcut = allowedptsq.contains(m_cut_allowedPtSq); + m_cut_allowedPtSq = allowedptsq; + if (relaxcut) + recheckCutStatusOfAllNotVisibleHandles(); + else + recheckCutStatusOfAllVisibleHandles(); +} + +//____________________________________________________________________ +void TrackCollHandleBase::setCutAllowedEta(const VP1Interval& allowedEta) +{ + messageVerbose("signal received in setCutAllowedEta ("+allowedEta.toString()+")"); + if (!allowedEta.isSane()) + return; + + if (m_cut_allowedEta==allowedEta) + return; + m_cut_eta_allowall = allowedEta.isAllR(); + m_cut_etaptphi_allwillfail = allowedEta.isEmpty() || m_cut_allowedPtSq.isEmpty() || m_cut_allowedPhi.isEmpty(); + + if (!m_cut_allowedEta.contains(allowedEta)&&!allowedEta.contains(m_cut_allowedEta)) { + m_cut_allowedEta = allowedEta; + recheckCutStatusOfAllHandles(); + return; + } + bool relaxcut = allowedEta.contains(m_cut_allowedEta); + m_cut_allowedEta = allowedEta; + if (relaxcut) + recheckCutStatusOfAllNotVisibleHandles(); + else + recheckCutStatusOfAllVisibleHandles(); +} + +//____________________________________________________________________ +void TrackCollHandleBase::setCutAllowedPhi(const QList<VP1Interval>& allowedPhi) +{ + messageVerbose("signal received in setCutAllowedPhi."); + + if (m_cut_allowedPhi==allowedPhi) + return; + m_cut_allowedPhi = allowedPhi; + + m_cut_phi_allowall = m_cut_allowedPhi.count()==1 && m_cut_allowedPhi.at(0).isAllR(); + m_cut_etaptphi_allwillfail = m_cut_allowedPhi.isEmpty() || m_cut_allowedPtSq.isEmpty() || m_cut_allowedEta.isEmpty(); + + if (m_cut_phi_allowall) { + recheckCutStatusOfAllNotVisibleHandles(); + return; + } + if (m_cut_etaptphi_allwillfail) { + recheckCutStatusOfAllVisibleHandles(); + return; + } + recheckCutStatusOfAllHandles(); + return; +} + +//____________________________________________________________________ +void TrackCollHandleBase::setRequiredNHits(const QList<unsigned>& l) +{ + if (!mightHaveSubSystemHitInfo()) + return;//never deal with this... + if (m_cut_requiredNHits==l) + return; + + //A bit complex to figure out if the cut change is pure relaxation or tightening: + bool relaxed(false),tightened(false); + if (m_cut_requiredNHits.isEmpty()) { + relaxed = false; + tightened = true; + } else { + if (l.isEmpty()) { + relaxed = true; + tightened = false; + } else { + assert(l.count()==m_cut_requiredNHits.count()); + relaxed = false; + tightened = false; + for (int i=0;i<l.count();++i) { + if (m_cut_requiredNHits[i]>l[i]) + relaxed=true; + else if (m_cut_requiredNHits[i]<l[i]) + tightened = true; + } + } + } + assert(relaxed||tightened); + m_cut_requiredNHits=l; + if (relaxed&&tightened) { + recheckCutStatusOfAllHandles(); + } else { + if (relaxed) + recheckCutStatusOfAllNotVisibleHandles(); + else + recheckCutStatusOfAllVisibleHandles(); + } +} + +//____________________________________________________________________ +void TrackCollHandleBase::setOnlyVertexAssocTracks(bool b){ + messageVerbose("setOnlyVertexAssocTracks changed to "+str(b)); + + if (b) + recheckCutStatusOfAllVisibleHandles(); + else + recheckCutStatusOfAllNotVisibleHandles(); +} + +//____________________________________________________________________ +void TrackCollHandleBase::actualSetCustomColouredTSOSPartsOnHandles() +{ + largeChangesBegin(); + trackHandleIterationBegin(); + TrackHandleBase* handle; + while ((handle=getNextTrackHandle())) + handle->setCustomColouredTSOSParts(m_d->customColouredTSOSParts); + largeChangesEnd(); +} + +//____________________________________________________________________ +void TrackCollHandleBase::actualSetShownTSOSPartsOnHandles() +{ + largeChangesBegin(); + trackHandleIterationBegin(); + TrackHandleBase* handle; + while ((handle=getNextTrackHandle())) + handle->setShownTSOSParts(m_d->shownTSOSParts); + largeChangesEnd(); + + fillObjectBrowser(); // FIXME! Probably not the right place to call this +} + +//____________________________________________________________________ +void TrackCollHandleBase::setShownTSOSParts(TrackCommonFlags::TSOSPartsFlags f) +{ + if (m_d->shownTSOSParts==f) + return; + m_d->shownTSOSParts=f; + if (visible()) messageVerbose("shown TSOS parts changed to "+str(f)); + actualSetShownTSOSPartsOnHandles(); +} + + +//____________________________________________________________________ +void TrackCollHandleBase::setCustomColouredTSOSParts(TrackCommonFlags::TSOSPartsFlags f) +{ + if (m_d->customColouredTSOSParts==f) + return; + m_d->customColouredTSOSParts=f; + if (visible()) messageVerbose("custom coloured TSOS parts changed to "+str(f)); + actualSetCustomColouredTSOSPartsOnHandles(); +} + +//____________________________________________________________________ +void TrackCollHandleBase::setUseShortTRTMeasurements(bool b) +{ + if (m_d->tsos_useShortTRTMeasurements==b) + return; + m_d->tsos_useShortTRTMeasurements=b; + largeChangesBegin(); + trackHandleIterationBegin(); + TrackHandleBase* handle; + while ((handle=getNextTrackHandle())) + handle->updateShapes_TSOSWithMeasurements(); + largeChangesEnd(); +} + + +//____________________________________________________________________ +void TrackCollHandleBase::setUseShortMDTMeasurements(bool b) +{ + if (m_d->tsos_useShortMDTMeasurements==b) + return; + m_d->tsos_useShortMDTMeasurements=b; + largeChangesBegin(); + trackHandleIterationBegin(); + TrackHandleBase* handle; + while ((handle=getNextTrackHandle())) + handle->updateShapes_TSOSWithMeasurements(); + largeChangesEnd(); +} + +//____________________________________________________________________ +void TrackCollHandleBase::setDrawMeasGlobalPositions(bool b) +{ + // if (visible()) messageVerbose("TrackCollHandleBase::setDrawMeasGlobalPositions => "+str(b)); + + if (m_d->tsos_drawMeasGlobalPositions==b) + return; + m_d->tsos_drawMeasGlobalPositions=b; + + largeChangesBegin(); + trackHandleIterationBegin(); + TrackHandleBase* handle; + while ((handle=getNextTrackHandle())) + handle->updateShapes_TSOSWithMeasurements(); + largeChangesEnd(); +} + +//____________________________________________________________________ +void TrackCollHandleBase::setMeasurementsShorttubesScale(double n) +{ + if (m_d->tsos_measurementsShorttubesScale==n) + return; + m_d->tsos_useShortMDTMeasurements=n; + largeChangesBegin(); + trackHandleIterationBegin(); + TrackHandleBase* handle; + while ((handle=getNextTrackHandle())) + handle->updateShapes_TSOSWithMeasurements(); + largeChangesEnd(); +} + +//____________________________________________________________________ +void TrackCollHandleBase::setNStdDevForParamErrors(const double& nstddev) +{ + if (m_d->tsos_nStdDevForParamErrors==nstddev) + return; + m_d->tsos_nStdDevForParamErrors=nstddev; + largeChangesBegin(); + trackHandleIterationBegin(); + TrackHandleBase* handle; + while ((handle=getNextTrackHandle())) + handle->updateShapes_TSOSWithErrors(); + largeChangesEnd(); +} + +//____________________________________________________________________ +void TrackCollHandleBase::setNumberOfPointsOnCircles(int n) +{ + if (m_d->tsos_numberOfPointsOnCircles==n) + return; + m_d->tsos_numberOfPointsOnCircles=n; + largeChangesBegin(); + trackHandleIterationBegin(); + TrackHandleBase* handle; + while ((handle=getNextTrackHandle())) + handle->updateShapes_TSOSWithErrors(); + largeChangesEnd(); +} + +//____________________________________________________________________ +void TrackCollHandleBase::setMaterialEffectsOnTrackScale(double n) +{ + if (m_d->tsos_materialEffectsOnTrackScale==n) + return; + m_d->tsos_materialEffectsOnTrackScale=n; + largeChangesBegin(); + trackHandleIterationBegin(); + TrackHandleBase* handle; + while ((handle=getNextTrackHandle())) + handle->updateShapes_TSOSWithMaterialEffects(); + largeChangesEnd(); +} + +//____________________________________________________________________ +void TrackCollHandleBase::setParTubeErrorsDrawCylinders(bool b) +{ + if (m_d->tsos_parTubeErrorsDrawCylinders==b) + return; + m_d->tsos_parTubeErrorsDrawCylinders=b; + largeChangesBegin(); + trackHandleIterationBegin(); + TrackHandleBase* handle; + while ((handle=getNextTrackHandle())) + handle->updateShapes_TSOSWithErrors(); + largeChangesEnd(); +} + +//____________________________________________________________________ +qint32 TrackCollHandleBase::provideCollTypeID() const +{ + return TrackType::typeToInt(m_type); +} + +//____________________________________________________________________ +void TrackCollHandleBase::collVisibilityChanged(bool vis) +{ + if (!m_sephelper) + m_sephelper = new VP1ExtraSepLayerHelper(collSep()); + + if (VP1Msg::verbose()) + messageVerbose("TrackCollHandleBase::collVisibilityChanged => "+str(vis)); + if (vis){ + recheckCutStatusOfAllNotVisibleHandles();//Fixme -> ofallhandles? All must be not visible anyway... + fillObjectBrowser(); + if (m_d->objBrowseTree) m_d->objBrowseTree->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); // selectable, enabled + }else{ + recheckCutStatusOfAllVisibleHandles(); +// QTreeWidget* trkObjBrowser = common()->controller()->trackObjBrowser(); +// if (m_d->objBrowseTree && trkObjBrowser) { +// trkObjBrowser->takeTopLevelItem(trkObjBrowser->indexOfTopLevelItem(m_d->objBrowseTree)); +// delete m_d->objBrowseTree; m_d->objBrowseTree=0; +// } + // FIXME - need to loop through handles setting pointers to deleted QTreeWidgetItems + if (m_d->objBrowseTree) m_d->objBrowseTree->setFlags(0); // not selectable, not enabled + } + actualSetShownTSOSPartsOnHandles(); + actualSetCustomColouredTSOSPartsOnHandles(); +} + +void TrackCollHandleBase::updateObjectBrowserVisibilityCounts() { + messageVerbose("TrackCollHandleBase::updateObjectBrowserVisibilityCounts called for "+name()); + QTreeWidget* trkObjBrowser = common()->controller()->trackObjBrowser(); + if (!trkObjBrowser || !m_d->objBrowseTree) { + messageVerbose("TrackCollHandleBase::updateObjectBrowserVisibilityCounts: no common()->controller()->trackObjBrowser() and/or m_d->objBrowseTree. Aborting"); + messageVerbose("trkObjBrowser: "+str(trkObjBrowser)+"\t m_d->objBrowseTree: "+str(m_d->objBrowseTree)); + return; + } + QString text(QString(": (")+QString::number(nShownHandles())+QString("/")+QString::number(m_d->trackhandles.size())+QString(") visible")); + m_d->objBrowseTree->setText(1, text); +} + +void TrackCollHandleBase::fillObjectBrowser() +{ + QTime t; + t.start(); + + QTreeWidget* trkObjBrowser = common()->controller()->trackObjBrowser(); + if (!trkObjBrowser) { + messageVerbose("TrackCollHandleBase::fillObjectBrowser: no common()->controller()->trackObjBrowser(). Aborting"); + return; + } + if (!nShownHandles()) { + //messageVerbose("TrackCollHandleBase::fillObjectBrowser: no shown handles, so leaving."); + return; // don't bother with hidden collection + } + messageVerbose("TrackCollHandleBase::fillObjectBrowser called for "+name()); + + trkObjBrowser->setUpdatesEnabled(false); + + bool firstTime=false; + if (!m_d->objBrowseTree) { + m_d->objBrowseTree = new QTreeWidgetItem(0); + firstTime=true; + messageVerbose("TrackCollHandleBase::fillObjectBrowser: First time so creating QTreeWidgetItem."); + } else { + int index = trkObjBrowser->indexOfTopLevelItem(m_d->objBrowseTree); + if (index==-1 ) { + messageVerbose("Missing from WidgetTree! Will continue but something must be wrong"); + } + } + + messageVerbose("TrackCollHandleBase::fillObjectBrowser about to start looping over tracks at "+QString::number(t.elapsed())+" ms"); + + QList<QTreeWidgetItem *> list; + trackHandleIterationBegin(); + TrackHandleBase* trkHandle=0; + unsigned int i=0; + unsigned int numVisible=0; + while ((trkHandle=getNextTrackHandle())) + { + if (firstTime){ + trkHandle->fillObjectBrowser(list); + } else { + trkHandle->updateObjectBrowser(); + } + + // messageVerbose("TrackCollHandleBase::fillObjectBrowser for track completed in "+QString::number(t.elapsed())); + + if (trkHandle->visible() ) numVisible++; + i++; + } + + QString text(QString(": (")+QString::number(numVisible)+QString("/")+QString::number(i)+QString(") visible")); + + m_d->objBrowseTree->setText(0, name()); + m_d->objBrowseTree->setText(1, text); + m_d->objBrowseTree->addChildren(list); + trkObjBrowser->addTopLevelItem(m_d->objBrowseTree); + trkObjBrowser->setUpdatesEnabled(true); + + messageVerbose("TrackCollHandleBase::fillObjectBrowser completed in "+QString::number(t.elapsed())+" ms"); + +} + +//____________________________________________________________________ +void TrackCollHandleBase::assignDefaultMaterial(SoMaterial * m) const +{ + VP1QtInventorUtils::setMatColor( m, defaultColor(), 0.18/*brightness*/ ); +} + +//____________________________________________________________________ +QString TrackCollHandleBase::toString(const COLOURBY&cb) +{ + switch (cb) { + case COLOUR_PERCOLLECTION: return "COLOUR_PERCOLLECTION"; + case COLOUR_RANDOM: return "COLOUR_RANDOM"; + case COLOUR_MOMENTUM: return "COLOUR_MOMENTUM"; + case COLOUR_CHARGE: return "COLOUR_CHARGE"; + case COLOUR_BYPID: return "COLOUR_BYPID"; + case COLOUR_DISTANCE: return "COLOUR_DISTANCE"; + default: return "Unknown (ERROR)"; + } +} +//____________________________________________________________________ +QList<QWidget*> TrackCollHandleBase::provideExtraWidgetsForGuiRow() const +{ + return QList<QWidget*>() << m_d->comboBox_colourby; + +} + +//____________________________________________________________________ +QByteArray TrackCollHandleBase::extraWidgetsState() const +{ + VP1Serialise serialise(0/*version*/,systemBase()); + serialise.save(m_d->comboBox_colourby); + serialise.disableUnsavedChecks(); + return serialise.result(); +} + +//____________________________________________________________________ +void TrackCollHandleBase::setExtraWidgetsState(const QByteArray& ba) +{ + VP1Deserialise state(ba, systemBase()); + if (state.version()!=0) + return;//just ignore silently... i guess we ought to warn? + state.restore(m_d->comboBox_colourby); + state.disableUnrestoredChecks(); + colourByComboBoxItemChanged(); +} + +//____________________________________________________________________ +void TrackCollHandleBase::colourByComboBoxItemChanged() +{ + messageVerbose("Collection detail level combo box changed index"); + if (m_d->comboBox_colourby->currentText()==Imp::comboBoxEntry_ColourByPID()) + setColourBy(COLOUR_BYPID); + else if (m_d->comboBox_colourby->currentText()==Imp::comboBoxEntry_ColourByRandom()) + setColourBy(COLOUR_RANDOM); + else if (m_d->comboBox_colourby->currentText()==Imp::comboBoxEntry_ColourByMomentum()) + setColourBy(COLOUR_MOMENTUM); + else if (m_d->comboBox_colourby->currentText()==Imp::comboBoxEntry_ColourByCharge()) + setColourBy(COLOUR_CHARGE); + else if (m_d->comboBox_colourby->currentText()==Imp::comboBoxEntry_ColourByDistanceFromSelectedTrack()) + setColourBy(COLOUR_DISTANCE); + else if (m_d->comboBox_colourby->currentText()==Imp::comboBoxEntry_ColourByVertex()) + setColourBy(COLOUR_VERTEX); + else + setColourBy(COLOUR_PERCOLLECTION); +} + +//____________________________________________________________________ +void TrackCollHandleBase::collMaterialTransparencyAndBrightnessChanged() +{ + messageVerbose("Collection colour changed"); + + if (m_d->comboBox_colourby->currentText()==Imp::comboBoxEntry_ColourByRandom()) { + largeChangesBegin(); + trackHandleIterationBegin(); + TrackHandleBase* handle; + while ((handle=getNextTrackHandle())) + handle->updateRandomColourTransparencyAndBrightness(); + largeChangesEnd(); + } else { + updateMaterialOfAllHandles(); + } +} + +bool TrackCollHandleBase::useDefaultCuts() const +{ + if (!m_d->matButton) { + message("ERROR: useDefaultCuts(..) called before init()"); + return true; + } + return m_d->matButton->useDefaultCuts(); +} + +bool TrackCollHandleBase::cutOnlyVertexAssocTracks() const +{ + if (!m_d->matButton) { + message("ERROR: cutOnlyVertexAssocTracks(..) called before init()"); + return false; + } + if (m_d->matButton->useDefaultCuts()) return common()->controller()->cutOnlyVertexAssocTracks(); + return m_d->matButton->cutOnlyVertexAssocTracks(); +} + + + + +//____________________________________________________________________ +void TrackCollHandleBase::setState(const QByteArray&state) +{ + if (!m_d->matButton) { + message("ERROR: setState(..) called before init()"); + return; + } + VP1Deserialise des(state); + des.disableUnrestoredChecks(); + if (des.version()!=0&&des.version()!=1) { + messageDebug("Warning: Ignoring state with wrong version"); + return; + } + bool vis = des.restoreBool(); + + QByteArray matState = des.restoreByteArray(); + m_d->matButton->restoreFromState(matState); + QByteArray extraWidgetState = des.version()>=1 ? des.restoreByteArray() : QByteArray(); + setVisible(vis); + + if (extraWidgetState!=QByteArray()) + setExtraWidgetsState(extraWidgetState); +} + +//____________________________________________________________________ +QByteArray TrackCollHandleBase::persistifiableState() const +{ + if (!m_d->matButton) { + message("ERROR: persistifiableState() called before init()"); + return QByteArray(); + } + VP1Serialise serialise(1/*version*/); + serialise.disableUnsavedChecks(); + serialise.save(visible()); + Q_ASSERT(m_d->matButton&&"Did you forget to call init() on this VP1StdCollection?"); + serialise.save(m_d->matButton->saveState()); + serialise.save(extraWidgetsState());//version 1+ + return serialise.result(); +} diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCollHandle_RefittedTracks.cxx b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCollHandle_RefittedTracks.cxx new file mode 100644 index 000000000..268572a3b --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCollHandle_RefittedTracks.cxx @@ -0,0 +1,62 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class TrackCollHandle_RefittedTracks // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: September 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12TrackSystems/TrackCollHandle_RefittedTracks.h" +#include "VTI12TrackSystems/TrackHandle_TrkTrack.h" +// #include "VP1Utils/VP1JobConfigInfo.h" +#include "VP1Base/IVP1System.h" + +//____________________________________________________________________ +class TrackCollHandle_RefittedTracks::Imp { +public: + QList<const Trk::Track*> fittedtracks; +}; + + +//____________________________________________________________________ +TrackCollHandle_RefittedTracks::TrackCollHandle_RefittedTracks(TrackSysCommonData *cd, + const QString& name, QList<const Trk::Track*> fittedtracks) + : TrackCollHandle_TrkTrack(cd,name,TrackType::RefittedTrack), m_d(new Imp) +{ + m_d->fittedtracks = fittedtracks; +} + +//____________________________________________________________________ +TrackCollHandle_RefittedTracks::~TrackCollHandle_RefittedTracks() +{ + delete m_d; +} + +//____________________________________________________________________ +bool TrackCollHandle_RefittedTracks::load() +{ + hintNumberOfTracksInEvent(m_d->fittedtracks.count()); + int i(0); + foreach (const Trk::Track * trk, m_d->fittedtracks) { + if (trk) { + messageDebug("ADDTRACK."); + addTrackHandle(new TrackHandle_TrkTrack(this,trk)); + } else + messageDebug("WARNING: Ignoring null Trk::Track pointer."); + if (!(i++%100)) + systemBase()->updateGUI(); + } + + //Maybe we need to show measurements, etc.: + //FIXME updateVisibleAssociatedObjects(); ?? + + return true; +} + +//FIXME: These coll's should not have their states saved... diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCollHandle_TrkTrack.cxx b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCollHandle_TrkTrack.cxx new file mode 100644 index 000000000..fdeef8155 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCollHandle_TrkTrack.cxx @@ -0,0 +1,159 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class TrackCollHandle_TrkTrack // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: February 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12TrackSystems/TrackCollHandle_TrkTrack.h" +#include "VTI12TrackSystems/TrackHandle_TrkTrack.h" +#include "VP1Base/IVP1System.h" +#include "VTI12TrackSystems/TrackSystemController.h" +#include "VP1Base/IVP1System.h" +#include "VP1Base/VP1QtUtils.h" +#include "VTI12Utils/VP1JobConfigInfo.h" +#include "VTI12Utils/VP1SGContentsHelper.h" +#include "VTI12Utils/VP1SGAccessHelper.h" + +#include "TrkTrack/Track.h" +#include "TrkTrack/TrackCollection.h" + +#include <QRegExp> + +//____________________________________________________________________ +class TrackCollHandle_TrkTrack::Imp { +public: + static bool isFatrasTruthTrack(const QString& key); + static bool alwaysShowAllTrackColls; + TrackCollHandle_TrkTrack * theclass; + TrackCommonFlags::DETAILLEVEL detailLevel; + +}; + +bool TrackCollHandle_TrkTrack::Imp::alwaysShowAllTrackColls + = VP1QtUtils::environmentVariableIsOn("VP1_ALWAYS_SHOW_ALL_TRACK_COLLECTIONS"); + +//____________________________________________________________________ +QStringList TrackCollHandle_TrkTrack::availableCollections(IVP1System*sys) +{ + //There must be at least one of the trackers available for this to make sense. + if ( ! ( VP1JobConfigInfo::hasSCTGeometry() ) ) { + sys->messageDebug("TrackCollHandle_TrkTrack::availableCollections: " + "SCT geometry not available. Won't look in event store for Trk::Track collections"); + return QStringList(); + } + + QStringList keysInSG; + foreach(QString key,VP1SGContentsHelper(sys).getKeys<TrackCollection>()) { + // if ( key=="CombinedInDetTracks") // Useful for debugging to limit to one collection + keysInSG<<key; + } + + if (keysInSG.isEmpty()||Imp::alwaysShowAllTrackColls) + return keysInSG; + + QRegExp needsAllIDPattern("ExtendedTracks|ResolvedTracks|Tracks|.*Id.*|.*ID.*|.*InDet.*|.*Inner.*"); + + // const bool jobcfgAllID + // = VP1JobConfigInfo::hasPixelGeometry() + // &&VP1JobConfigInfo::hasSCTGeometry() + // &&VP1JobConfigInfo::hasTRTGeometry(); + const bool jobcfgAllID = VP1JobConfigInfo::hasSCTGeometry(); + + QStringList outkeys; + + foreach (QString key, keysInSG) { + if (!jobcfgAllID && needsAllIDPattern.exactMatch(key)) { + sys->messageDebug("TrackCollHandle_TrkTrack::availableCollections: Ignoring key '" + +key+"' since sct geometry is not present in job."); + continue; + } + outkeys<<key; + } + return outkeys; + +} + +//____________________________________________________________________ +TrackCollHandle_TrkTrack::TrackCollHandle_TrkTrack( TrackSysCommonData * cd, + const QString& name, + TrackType::Type type ) + : TrackCollHandleBase(cd,name,type), m_d(new Imp) +{ + m_d->theclass = this; + m_d->detailLevel = TrackCommonFlags::AUTO; +} + +//____________________________________________________________________ +TrackCollHandle_TrkTrack::~TrackCollHandle_TrkTrack() +{ + delete m_d; +} + +//____________________________________________________________________ +bool TrackCollHandle_TrkTrack::Imp::isFatrasTruthTrack(const QString& key) +{ + QString env = VP1QtUtils::environmentVariableValue("VP1_FATRAS_TRACKCOLLS_PATTERN"); + return QRegExp((env.isEmpty()?"*fatras*":env),Qt::CaseInsensitive,QRegExp::Wildcard).exactMatch(key); +} + +//____________________________________________________________________ +void TrackCollHandle_TrkTrack::setupSettingsFromControllerSpecific(TrackSystemController*) +{ + messageVerbose("setupSettingsFromControllerSpecific start"); + messageVerbose("setupSettingsFromControllerSpecific end"); +} + +//____________________________________________________________________ +bool TrackCollHandle_TrkTrack::load() +{ + //Get collection: + const TrackCollection * trackColl(0); + if (!VP1SGAccessHelper(systemBase()).retrieve(trackColl, name())) { + message("Error: Could not retrieve track collection with key="+name()); + return false; + } + + //Make appropriate trk::track handles: + hintNumberOfTracksInEvent(trackColl->size()); + int i(0); + TrackCollection::const_iterator trackItr, trackItrEnd = trackColl->end(); + for ( trackItr = trackColl->begin() ; trackItr != trackItrEnd; ++trackItr) { + if (*trackItr) + addTrackHandle(new TrackHandle_TrkTrack(this,*trackItr)); + else + messageDebug("WARNING: Ignoring null Trk::Track pointer."); + if (!(i++%100)) + systemBase()->updateGUI(); + } + + //Maybe we need to show measurements, etc.: + // updateVisibleAssociatedObjects(); + + return true; +} + +//____________________________________________________________________ +bool TrackCollHandle_TrkTrack::cut(TrackHandleBase* handle) +{ + if (!TrackCollHandleBase::cut(handle)) + return false; + + //fixme: more? + return true; +} + +//____________________________________________________________________ +void TrackCollHandle_TrkTrack::visibleStateUpdated(TrackHandle_TrkTrack* trkhandle) +{ + common()->visTrkTracksToMaterialHelper()->setState(trkhandle->trkTrackPointer(), (trkhandle->visible() ? trkhandle->currentMaterial() : 0 )); +} + + diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCollHandle_TruthTracks.cxx b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCollHandle_TruthTracks.cxx new file mode 100644 index 000000000..3e5a89743 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCollHandle_TruthTracks.cxx @@ -0,0 +1,968 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class TrackCollHandle_TruthTracks // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: March 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12TrackSystems/TrackCollHandle_TruthTracks.h" +#include "VTI12TrackSystems/TrackHandle_TruthTrack.h" +#include "VTI12TrackSystems/SimHitHandleBase.h" +#include "VTI12TrackSystems/SimHitHandle_TrackRecord.h" +#include "VTI12TrackSystems/SimHitHandle_ScintHit.h" +#include "VTI12TrackSystems/SimBarCode.h" +#include "VTI12TrackSystems/TrackSystemController.h" +#include "VP1Base/IVP1System.h" +#include "VP1Base/VP1Msg.h" +#include "VTI12Utils/VP1JobConfigInfo.h" +#include "VTI12Utils/VP1ParticleData.h" + +#include "HepMC/GenEvent.h" +#include "HepMC/GenParticle.h" +#include "HepMC/GenVertex.h" +#include "GeneratorObjects/McEventCollection.h" + +#include "TrackRecord/TrackRecordCollection.h" + +#include "VTI12Utils/VP1SGContentsHelper.h" +#include "VTI12Utils/VP1SGAccessHelper.h" + +#include "ScintSimEvent/ScintHitCollection.h" +// #include "InDetSimEvent/SiHitCollection.h" + +#include "CLHEP/Units/PhysicalConstants.h" + +#include "CLHEP/Vector/LorentzVector.h" + +#include <QStringList> +#include <QTime> + + +//____________________________________________________________________ +class TrackCollHandle_TruthTracks::Imp { +public: + double mag(const HepMC::FourVector& v) const { + return std::sqrt( v.x()*v.x() + v.y()*v.y() + v.z()*v.z() ); + } + + TrackCollHandle_TruthTracks * theclass; + bool loadHitLists(std::map<SimBarCode,SimHitList> & hitLists); + void loadGenParticles( std::map<SimBarCode,const HepMC::GenParticle*> & genParticles, + const HepMC::GenVertex* vtx ); + bool loadGenParticles( std::map<SimBarCode,const HepMC::GenParticle*> & genParticles, + const QString& hepMcCollKey ); + + template <class collT> + void addHitCollections(std::map<SimBarCode,SimHitList> & hitLists); + +// static SimHitHandleBase * createHitHandle( const TrackRecord * h ) { return new SimHitHandle_TrackRecord(h); } + static SimHitHandleBase * createHitHandle( const TrackRecord& h ) { return new SimHitHandle_TrackRecord(&h); } + static SimHitHandleBase * createHitHandle( const ScintHit& h ) { return new SimHitHandle_ScintHit(&h); } + // static SimHitHandleBase * createHitHandle( const SiHit& h ) { return new SimHitHandle_SiHit(&h); } + + static QString nameHepMCAugmentedEnd; + static QString nameAugmentedOnly; + + void createSecondaryHitLists(const SimBarCode& origSimBarCode, + const SimHitList& origHitList, + std::map<SimBarCode,SimHitList> & outlists, + int& newBarCode ); + std::list<SimHitHandleBase*>::iterator closestCompatibleHandleItr(SimHitHandleBase* handle, + const std::list<SimHitHandleBase*>::iterator& itFirst, + std::list<SimHitHandleBase*>& handleList, + const double& massSquared); + + std::map<SimBarCode::ExtBarCode,int> extBarCode2pdg; + + int updateGUICounter; + void possiblyUpdateGUI() { + if (!((updateGUICounter++)%750)) { + theclass->systemBase()->updateGUI(); + } + } + + bool cut_fromIROnly; + bool cut_excludeBarcodeZero; + bool cut_excludeNeutrals; + + bool displayAscObjs; + void updateVisibleAssociatedObjects(); + + bool fixMomentumInfoInSimHits(const HepMC::GenParticle* p,SimHitList& hitlist); + + static const int maxPdgCode = 1000000000; + +}; + +QString TrackCollHandle_TruthTracks::Imp::nameHepMCAugmentedEnd = " [augmented]"; +QString TrackCollHandle_TruthTracks::Imp::nameAugmentedOnly = "Sim hits/trk rec."; + +//____________________________________________________________________ +QStringList TrackCollHandle_TruthTracks::availableCollections( IVP1System*sys ) +{ + QStringList l; + VP1SGContentsHelper sgcont(sys); + + QStringList mcevent_keys = sgcont.getKeys<McEventCollection>(); + QStringList trackrecord_keys = sgcont.getKeys<TrackRecordCollection>(); + + QStringList /*keys_siliconhits,*/ keys_scintillatorhits; + + if (VP1JobConfigInfo::hasVetoGeometry() || + VP1JobConfigInfo::hasTriggerGeometry() || + VP1JobConfigInfo::hasPreshowerGeometry()) + keys_scintillatorhits = sgcont.getKeys<ScintHitCollection>();//"VetoHits", "TriggerHits" and "PreshowerHits" + // if (VP1JobConfigInfo::hasSCTGeometry()) + // keys_siliconhits = sgcont.getKeys<SiHitCollection>();//"SCT_Hits" + + bool extrainfo = ! ( keys_scintillatorhits.empty() && + // keys_siliconhits.empty() && + trackrecord_keys.empty() ); + + if (extrainfo&&mcevent_keys.empty()) { + l << Imp::nameAugmentedOnly; + return l; + } + + foreach (QString mcevent_key,mcevent_keys) { + l << mcevent_key; + if (extrainfo) + l << mcevent_key + Imp::nameHepMCAugmentedEnd; + } + + //Fixme: REMOVE THIS (only for testing!!): + if (extrainfo) + l << Imp::nameAugmentedOnly; + + return l; +} + +//____________________________________________________________________ +TrackCollHandle_TruthTracks::TrackCollHandle_TruthTracks(TrackSysCommonData * cd, + const QString& name) + : TrackCollHandleBase(cd,name,TrackType::TruthTrack), m_d(new Imp) +{ + setHelperClassName("TrackCollHandle_TruthTracks"); + m_d->theclass = this; + m_d->updateGUICounter = 0; + m_d->cut_fromIROnly = false; + m_d->cut_excludeBarcodeZero = false; + m_d->cut_excludeNeutrals = true; + m_d->displayAscObjs = true; +} + +//____________________________________________________________________ +TrackCollHandle_TruthTracks::~TrackCollHandle_TruthTracks() +{ + delete m_d; +} + +//____________________________________________________________________ +void TrackCollHandle_TruthTracks::setupSettingsFromControllerSpecific(TrackSystemController* controller) +{ + connect(controller,SIGNAL(cutTruthFromIROnlyChanged(bool)),this,SLOT(setCutFromIROnly(bool))); + setCutFromIROnly(controller->cutTruthFromIROnly()); + + connect(controller,SIGNAL(cutExcludeBarcodeZeroChanged(bool)),this,SLOT(setCutExcludeBarcodeZero(bool))); + setCutExcludeBarcodeZero(controller->cutExcludeBarcodeZero()); + + connect(controller,SIGNAL(cutTruthExcludeNeutralsChanged(bool)),this,SLOT(setCutExcludeNeutrals(bool))); + setCutExcludeNeutrals(controller->cutTruthExcludeNeutrals()); + + connect(controller,SIGNAL(showTruthAscObjsChanged(bool)),this,SLOT(setShowAscObjs(bool))); + setShowAscObjs(controller->showTruthAscObjs()); +} + +//____________________________________________________________________ +void TrackCollHandle_TruthTracks::setShowAscObjs(bool b) +{ + if (m_d->displayAscObjs==b) + return; + m_d->displayAscObjs=b; + messageVerbose("Associated objects shown flag changed to " + str(b)); + m_d->updateVisibleAssociatedObjects(); +} + +//____________________________________________________________________ +template <class collT> +void TrackCollHandle_TruthTracks::Imp::addHitCollections(std::map<SimBarCode,SimHitList> & hitLists) +{ + std::map<SimBarCode,SimHitList>::iterator itHitList; + + VP1SGAccessHelper sgaccess(theclass->systemBase()); + + foreach (QString key, VP1SGContentsHelper(theclass->systemBase()).getKeys<collT>()) { + const collT * hitColl; + if (!sgaccess.retrieve(hitColl, key)) { + theclass->message("Error: Could not retrieve "+QString(typeid(collT).name())+" collection with key = "+key); + continue; + } + theclass->messageVerbose("Retrieved hit collection of type "+QString(typeid(collT).name())+" with key = "+key); + typename collT::const_iterator it, itE(hitColl->end()); + int itot(0), iadded(0); + for (it=hitColl->begin();it!=itE;++it) { + ++itot; + possiblyUpdateGUI(); + SimHitHandleBase * handle = createHitHandle(*it); + handle->cacheMomentum(); + theclass->fixPDGCode(handle); + SimBarCode trackID = handle->simBarCode(); + if (trackID.pdgCode()>maxPdgCode) { + continue; + } + if (trackID.isNonUniqueSecondary()) { + double absmom = handle->momentum(); + if (absmom>=0&&absmom<1.0*CLHEP::MeV) {//Fixme: Useful? Put it higher?? + // if (VP1Msg::verbose()) + // theclass->messageVerbose("Ignoring low momentum sim hit for non. unique secondary particle"); + delete handle; + continue; + } + } + itHitList = hitLists.find(trackID); + if ( itHitList == hitLists.end() ) { + SimHitList l; + l.push_back(std::pair<double,SimHitHandleBase*>(handle->hitTime(),handle)); + hitLists[trackID] = l; + } else { + itHitList->second.push_back(std::pair<double,SimHitHandleBase*>(handle->hitTime(),handle)); + } + ++iadded; + } + theclass->messageVerbose(" => used "+str(iadded)+" of "+str(itot)+" hits"); + } + +} + +//____________________________________________________________________ +bool TrackCollHandle_TruthTracks::Imp::loadHitLists(std::map<SimBarCode,SimHitList> & hitLists) +{ + //Fixme: Return false if we do not find at least one collection + addHitCollections<TrackRecordCollection>(hitLists); + + //Important that collections which inherently contains pdg codes are loaded first! + + if (VP1JobConfigInfo::hasVetoGeometry() || + VP1JobConfigInfo::hasTriggerGeometry() || + VP1JobConfigInfo::hasPreshowerGeometry()) + // std::cout << "Called addHitCollections" << std::endl; + addHitCollections<ScintHitCollection>(hitLists); + // addHitCollections<SiHitCollection>(hitLists); + + if (VP1Msg::verbose()) + theclass->messageVerbose( "Found " + str( hitLists.size() ) + " lists of sim. hits."); + + //Time to assign all simhits with known pdg code a charge: + std::map<SimBarCode,SimHitList>::iterator it, itE(hitLists.end()); + for (it = hitLists.begin(); it!=itE; ++it) { + if (it->first.unknownPdgCode()) + continue; + bool ok; + double charge = VP1ParticleData::particleCharge(it->first.pdgCode(),ok); + if (!ok) + continue; + SimHitList::iterator itHit(it->second.begin()), itHitE(it->second.end()); + for (;itHit!=itHitE;++itHit) + itHit->second->setCharge(charge); + possiblyUpdateGUI(); + } + + //Fixme: Add hits from muon subsystems. + + //Sort hitLists: + for (it = hitLists.begin(); it!=itE; ++it) { + sort(it->second.begin(),it->second.end()); + possiblyUpdateGUI(); + } + return true; +} + + +//____________________________________________________________________ +void TrackCollHandle_TruthTracks::fixPDGCode(SimHitHandleBase* handle) const +{ + int pdgfromsimhit =handle->actualPDGCodeFromSimHit(); + bool isNonUniqueSecondary = handle->simBarCode().isNonUniqueSecondary(); + SimBarCode::ExtBarCode extBarCode = handle->simBarCode().extBarCode(); + + if (pdgfromsimhit!=SimBarCode::unknownPDG) { + handle->setPDG(handle->actualPDGCodeFromSimHit()); + std::map<SimBarCode::ExtBarCode,int>::const_iterator it = m_d->extBarCode2pdg.find(extBarCode); + if ( !isNonUniqueSecondary && it==m_d->extBarCode2pdg.end()) + m_d->extBarCode2pdg[extBarCode] = pdgfromsimhit; + return; + } + if (isNonUniqueSecondary) + return; + std::map<SimBarCode::ExtBarCode,int>::const_iterator it = m_d->extBarCode2pdg.find(extBarCode); + if (it!=m_d->extBarCode2pdg.end()) { + handle->setPDG(it->second); + } +} + +//____________________________________________________________________ +void TrackCollHandle_TruthTracks::Imp::loadGenParticles( std::map<SimBarCode,const HepMC::GenParticle*> & genParticles, + const HepMC::GenVertex* vtx ) +{ + if (!vtx) + return; + HepMC::GenVertex::particles_out_const_iterator itPart(vtx->particles_out_const_begin()); + HepMC::GenVertex::particles_out_const_iterator itPartEnd(vtx->particles_out_const_end()); + +// HepMC::GenVertex::particle_iterator itPart = vtx->particles_begin(HepMC::children); +// HepMC::GenVertex::particle_iterator itPartEnd = vtx->particles_end(HepMC::children); + for (;itPart!=itPartEnd;++itPart) { + const HepMC::GenParticle* p = *itPart; + if (!p)//fixme: message. + continue; + const HepMC::GenEvent* evt = p->parent_event(); + if (!evt) + continue;//fixme: message. + //Fixme: If verbose: check barcode does not already exists! + SimBarCode simBarCode(p->barcode(),0/*evt->event_number()...fixme: correct??*/,p->pdg_id()); + genParticles[simBarCode] = p; + if (!simBarCode.isNonUniqueSecondary()) + extBarCode2pdg[simBarCode.extBarCode()] = p->pdg_id(); + + loadGenParticles(genParticles,p->end_vertex()); + } +} + +//____________________________________________________________________ +bool TrackCollHandle_TruthTracks::Imp::loadGenParticles( std::map<SimBarCode,const HepMC::GenParticle*> & genParticles, + const QString& hepMcCollKey ) +{ + possiblyUpdateGUI(); + const McEventCollection* mcColl; + if (!VP1SGAccessHelper(theclass->systemBase()).retrieve(mcColl,hepMcCollKey)) { + theclass->message("Error: Could not retrieve "+QString(typeid(McEventCollection).name())+" collection with key = "+hepMcCollKey); + return false;//fixme message + } + + McEventCollection::const_iterator itEvt(mcColl->begin()), itEvtEnd(mcColl->end()); + if (itEvt==itEvtEnd) + return false;//fixme message + + for (;itEvt!=itEvtEnd;++itEvt) { + //NB: Signal is always the first event in collection! + const HepMC::GenEvent * evt = *itEvt; + if (!evt) + continue; + HepMC::GenEvent::vertex_const_iterator itVtx(evt->vertices_begin()), itVtxEnd(evt->vertices_end()); + for(;itVtx!=itVtxEnd;++itVtx) { + loadGenParticles(genParticles,*itVtx); + } + } + + return true; +} + +//____________________________________________________________________ +bool TrackCollHandle_TruthTracks::load() +{ + //Decode name to figure out if we need to load simhits/track records and which HepMC key to use. + bool augmentedonly = name()==Imp::nameAugmentedOnly; + bool augmented = augmentedonly || name().endsWith(Imp::nameHepMCAugmentedEnd); + QString hepmckey; + if (!augmentedonly) { + hepmckey = name(); + if (augmented) + hepmckey.chop(Imp::nameHepMCAugmentedEnd.count()); + } + + //get genparticles (should be done BEFORE we load sim. hits., so the barCode2pdg map gets filled): + std::map<SimBarCode,const HepMC::GenParticle*> genParticles; + if (!hepmckey.isEmpty()) + if (!m_d->loadGenParticles(genParticles,hepmckey)) + return false; + + //get sim hits and track records: + std::map<SimBarCode,SimHitList> hitLists; + if (augmented) { + if (!m_d->loadHitLists(hitLists)) + return false; + messageVerbose("TrackCollHandle_TruthTracks "+name() + +": Found "+str(hitLists.size())+" truth particles from simhits"); + } + + //Finally we need to combine the info we thus found, and construct + //actual track handles: + + //We do this by looping through the simhit list, and checking for + //genparticles with the same SimBarCode. Those gen particles we use + //in this way, we take out of the map (put to null), to indicate we + //already used them. In the final step we add genparticle-only + //handles for the remaining genparticle (unless they have production + //and decay vertices ultra-close to each other): + + std::map<SimBarCode,const HepMC::GenParticle*>::iterator itGenPart, itGenPartEnd(genParticles.end()); + std::map<SimBarCode,SimHitList>::iterator itHitList, itHitListEnd(hitLists.end()), itHitListTemp; + + //First we attempt to sort secondaries with barcode=0 into new lists + //of hits that are likely to have come from the same particle. + + int newBarCode(-1); + std::map<SimBarCode,SimHitList> secondaryHitLists; + messageVerbose("Sorting non-unique secondaries into lists of hits likely to originate from the same track."); + QTime timer;timer.start(); + for (itHitList = hitLists.begin();itHitList!=itHitListEnd;) { + if (itHitList->first.isNonUniqueSecondary()) { + m_d->createSecondaryHitLists(itHitList->first,itHitList->second,secondaryHitLists,newBarCode); + itHitListTemp = itHitList; + ++itHitList; + hitLists.erase(itHitListTemp); + } else { + ++itHitList; + } + } + messageVerbose("Finished sorting non-unique secondaries into lists. Time spent: "+str(timer.elapsed()*0.001)+" seconds"); + std::map<SimBarCode,SimHitList>::iterator itSecondaryList,itSecondaryListEnd(secondaryHitLists.end()); + for (itSecondaryList = secondaryHitLists.begin();itSecondaryList!=itSecondaryListEnd;++itSecondaryList) + hitLists[itSecondaryList->first] = itSecondaryList->second;//Fixme: Check that it does not already exist! + + for (itHitList = hitLists.begin();itHitList!=itHitListEnd;++itHitList) { + if (itHitList->second.empty()) { + message("load WARNING: Ignoring empty hit list."); + continue; + } + itGenPart = genParticles.find(itHitList->first); + const HepMC::GenParticle * p(0); + if (itGenPart!=itGenPartEnd) { + p = itGenPart->second; + itGenPart->second = 0; + } + +// if (!itHitList->first.isNonUniqueSecondary()) continue;//FIXME +// if (!itHitList->first.actualBarCode()==0) continue;//FIXME + m_d->possiblyUpdateGUI(); + + if (m_d->fixMomentumInfoInSimHits(p,itHitList->second))//Provide guesses for momentum in simhits that needs them (and deletes the rest). + addTrackHandle( new TrackHandle_TruthTrack( this, itHitList->first, itHitList->second, p ) ); + } + + const double minSpacialSeparation = 1.0e-3*CLHEP::mm; + const double minSepSq = minSpacialSeparation*minSpacialSeparation; + for (itGenPart=genParticles.begin();itGenPart!=itGenPartEnd;++itGenPart) { + const HepMC::GenParticle * p = itGenPart->second; + if (!p) + continue; + if (abs(p->pdg_id())>=Imp::maxPdgCode)//Internal particle... (fixme: find proper limit!!) + continue; + if (!p->production_vertex()) + continue; + if (p->end_vertex()) { + double dx(p->end_vertex()->position().x()-p->production_vertex()->position().x()); + double dy(p->end_vertex()->position().y()-p->production_vertex()->position().y()); + double dz(p->end_vertex()->position().z()-p->production_vertex()->position().z()); + if ( dx*dx+dy*dy+dz*dz < minSepSq ) + continue; + } + m_d->possiblyUpdateGUI(); + addTrackHandle( new TrackHandle_TruthTrack( this, itGenPart->first, SimHitList(), p ) ); + } + + //Maybe we need to show measurements, etc.: + m_d->updateVisibleAssociatedObjects(); + + return true; +} + +//____________________________________________________________________ +bool TrackCollHandle_TruthTracks::cut(TrackHandleBase* handle) +{ + if (!TrackCollHandleBase::cut(handle)) + return false; + + if (m_d->cut_excludeNeutrals && handle->hasCharge() && handle->charge()==0.0) + return false; + + TrackHandle_TruthTrack * truthhandle = static_cast<TrackHandle_TruthTrack *>(handle); + if (m_d->cut_excludeBarcodeZero && truthhandle->hasBarCodeZero()) + return false; + + if (m_d->cut_fromIROnly && ! truthhandle->hasVertexAtIR(2.8*CLHEP::cm*2.8*CLHEP::cm,50*CLHEP::cm)) + return false; + + return true; +} + +//____________________________________________________________________ +void TrackCollHandle_TruthTracks::setCutFromIROnly(bool b) +{ + if (m_d->cut_fromIROnly == b) + return; + m_d->cut_fromIROnly = b; + if (b) + recheckCutStatusOfAllVisibleHandles(); + else + recheckCutStatusOfAllNotVisibleHandles(); +} + +//____________________________________________________________________ +void TrackCollHandle_TruthTracks::setCutExcludeBarcodeZero(bool b) +{ + if (m_d->cut_excludeBarcodeZero==b) + return; + m_d->cut_excludeBarcodeZero=b; + if (b) + recheckCutStatusOfAllVisibleHandles(); + else + recheckCutStatusOfAllNotVisibleHandles(); +} + +//____________________________________________________________________ +void TrackCollHandle_TruthTracks::setCutExcludeNeutrals(bool b) +{ + if (m_d->cut_excludeNeutrals==b) + return; + m_d->cut_excludeNeutrals=b; + if (b) + recheckCutStatusOfAllVisibleHandles(); + else + recheckCutStatusOfAllNotVisibleHandles(); +} + +//____________________________________________________________________ +void TrackCollHandle_TruthTracks::Imp::createSecondaryHitLists(const SimBarCode& origSimBarCode, + const SimHitList& origHitList, + std::map<SimBarCode,SimHitList> & outlists, + int& newBarCode ) +{ + if (!origSimBarCode.isNonUniqueSecondary()||newBarCode>=0) { + theclass->message("createSecondaryHitLists" + " ERROR: Unexpected input"); + return; + } + + unsigned ntothitinput = origHitList.size(); + HepMcParticleLink::index_type evtIndex = origSimBarCode.evtIndex(); + int pdgCode = origSimBarCode.pdgCode(); + + //////////////////////////////////////////////////////////////////////////// + // Temporarily put the (time,handle) pairs from the vector into a list. // + //////////////////////////////////////////////////////////////////////////// + + SimHitList::const_iterator itOrig(origHitList.begin()),itOrigE(origHitList.end()); + std::list<SimHitHandleBase*> handleList; + for(;itOrig!=itOrigE;++itOrig) + handleList.push_back(itOrig->second); + + //////////////////////////////////////////////////////////////// + // Produce handle lists based on requirements of proximity, // + // decreasing momenta and causality. // + //////////////////////////////////////////////////////////////// + std::set<std::list<SimHitHandleBase*> > outHandleLists; + + bool ok; + double mass = VP1ParticleData::particleMass(pdgCode,ok); + double massSquared( (ok&&mass>=0) ? mass*mass : -1); + while (!handleList.empty()) { + std::list<SimHitHandleBase*> list; + std::list<SimHitHandleBase*>::iterator it(handleList.begin()), itNext, itTemp; + //Take this handle from the list, and increment to next one: + SimHitHandleBase * handle = *it; + list.push_back(handle); + itTemp = it++; + handleList.erase(itTemp); + while ( true ) { + if (it==handleList.end()) + break;//TEST + itNext = closestCompatibleHandleItr(handle,it,handleList,massSquared); + possiblyUpdateGUI(); + if (itNext == handleList.end())//Fixme: cache handleList.end()? Check erase invalidation! + break; + handle = *itNext; + list.push_back(handle); + it = itNext; ++it; + handleList.erase(itNext); + if (it == handleList.end())//Fixme: cache handleList.end()? Check erase invalidation! + break; + } + if (list.size()==1) {//5 is ok for trt, but probably not for silicon! + //We need at least two sim hits//FIXME: 5? + //Fixme: Make minimum number of hits depend on energy? +// theclass->messageVerbose("Ignoring secondary with barCode 0, since it seems to be the only sim. hit. by this track.");//Fixme: We could do something with posStart/posEnd?//fixme: update text to reflect 5 + //FIXME: use this!: delete *(list.begin()); + } else { + outHandleLists.insert(list); + } + } + + /////////////////////////////////////////////////////////////////////////////////// + // Put handle lists in output handle lists, and assign unique new fake barcodes // + /////////////////////////////////////////////////////////////////////////////////// + + //We assign fake negative barcodes to + //secondaries, since negative barcodes are + //by convention reserved for vertices in + //the HepMC collection. + + std::set<std::list<SimHitHandleBase*> >::iterator itOutList(outHandleLists.begin()), itOutListE(outHandleLists.end()); + unsigned totused(0); + for (;itOutList!=itOutListE;++itOutList) { + const SimBarCode fakeBarCode(newBarCode--,evtIndex,pdgCode); + //Fixme: Update barcodes contained in simhithandles!! + const unsigned n = itOutList->size(); + totused += n; + outlists[fakeBarCode] = SimHitList(); + std::map<SimBarCode,SimHitList>::iterator itActualOutList = outlists.find(fakeBarCode); + itActualOutList->second.reserve(n); + + std::list<SimHitHandleBase*>::const_iterator itHandle(itOutList->begin()),itHandleE(itOutList->end()); + for (;itHandle!=itHandleE;++itHandle) + itActualOutList->second.push_back(std::pair<double,SimHitHandleBase*>((*itHandle)->hitTime(),*itHandle)); + + //Should be ok already, but just to be safe: (fixme: don't do this?) + sort(itActualOutList->second.begin(),itActualOutList->second.end()); + } + + if (VP1Msg::verbose()) + theclass->messageVerbose("Grouped "+str(ntothitinput)+" secondaries with pdgCode = " + +str(pdgCode)+" into "+str(outHandleLists.size()) + +" tracks ("+str(ntothitinput-totused)+" went unused)."); +} + + +//____________________________________________________________________ +std::list<SimHitHandleBase*>::iterator TrackCollHandle_TruthTracks::Imp::closestCompatibleHandleItr(SimHitHandleBase* handle, + const std::list<SimHitHandleBase*>::iterator& itFirst, + std::list<SimHitHandleBase*>& handleList, + const double& massSquared) { +// if (itFirst==handleList.end()) +// return handleList.end(); + const double mom = handle->momentum(); + const double momSq = mom*mom; + const double betaSqMax = ( (mom < 0 || massSquared<=0 ? 1 : (momSq/(momSq+massSquared)) )); + const double speedSqMax = 4.0* CLHEP::c_squared * betaSqMax;//NB: The factor of 4 is a fudge factor, not really clear why needed!!! VP1 or GEANT4 bug! + // const double speedSqMax = 1.0001 * c_squared;/*fixme test*/ +// const double speedSqMax = 1.1*betaSqMax*300*300;/*fixme test*/ +// double testmsq=0.511*MeV*0.511*MeV; +// const double speedSqMax = 1.0001 * c_squared * ( (mom < 0 || testmsq<=0 ? 1 : (momSq/(momSq+testmsq)) )); + + unsigned ichecked(0); + unsigned maxchecked(50); + + const double hitTime = handle->hitTime(); + const Amg::Vector3D pos = handle->posStart(); + double mom2, flightTime; + std::list<SimHitHandleBase*>::iterator it(itFirst), itE(handleList.end()); + std::list<SimHitHandleBase*>::iterator itMinDist(itE); + double minDistSq(100*CLHEP::cm*100*CLHEP::cm);//Put to 1.0e99 for no hard limit. + if (mom>0) + if (mom<500*CLHEP::MeV) { + minDistSq = 20*CLHEP::cm*20*CLHEP::cm; + if (mom<100*CLHEP::MeV) { + minDistSq = 10*CLHEP::cm*10*CLHEP::cm; + if (mom<10*CLHEP::MeV) + minDistSq = 5*CLHEP::cm*5*CLHEP::cm; + } + } + + for (;it!=itE;++it) { + ++ichecked; + mom2 = (*it)->momentum(); + //Possible decreasing momentum requirement: + if (mom>=0&&mom2>=0) { + if (mom2>mom) + continue; + if (mom2<0.5*mom)//Guard against delta-rays-ish. + continue; + } + + //Maximal separation requirement: + const double distSquared = ((*it)->posStart()-pos).mag2(); + + //Only investigate if it is the closest one: + if (distSquared>=minDistSq) + continue; + + flightTime = (*it)->hitTime() - hitTime; + if (flightTime<=0||flightTime>100*CLHEP::ns) { + //Second hit comes before (shouldn't happen), or waaaay after the first hit. + if (flightTime<0) + theclass->message("closestCompatibleHandleItr WARNING: Should never happen. T1="+str(hitTime)+", T2="+str((*it)->hitTime())); + continue; + } else { + if (distSquared>flightTime*flightTime*speedSqMax) + continue; + } + + + //Check for coalignment of momenta: + double mindotproduct = -0.5; + if (mom>10.0*CLHEP::MeV) { + mindotproduct = -0.1; + if (mom>1000.0*CLHEP::MeV) { + mindotproduct = 0.5; + if (mom>10000.0*CLHEP::MeV) { + mindotproduct = 0.80; + } + } + } + if (mindotproduct>-1.0) + if (handle->momentumDirection().dot((*it)->momentumDirection())<mindotproduct) + continue; + + // theclass->messageDebug("Test. Hit passed mom and causality."); + + // //Possible minimal separation requirement: //FIXME: Turn this on if momentum is greater than...? + // if (mom2>=0&&massSquared>=0) { + // const double speedSqMin = 0.9999 * c_squared * momSq/(momSq+massSquared); + // const double minDistSquared = flightTimeSq*speedSqMin; + // if (distSquared<minDistSquared) + // continue; + // } + //Fixme: We might also make some requirement that distance should be less than e.g. 20cm?? + + //Hits are in principle compatible. Store it if it is also the closest: + // if (distSquared<minDistSq) { + minDistSq = distSquared; + itMinDist = it; + + if (distSquared<15*15*CLHEP::cm*CLHEP::cm) { + //We already found a very good hit - should not look much further. + if (distSquared<5*5*CLHEP::cm*CLHEP::cm) + maxchecked = ichecked + 5; + else + maxchecked = ichecked + 15; + } + + if (ichecked>maxchecked)//For performance reasons + break; + } + return itMinDist; +} + + +//____________________________________________________________________ +bool TrackCollHandle_TruthTracks::Imp::fixMomentumInfoInSimHits(const HepMC::GenParticle* p,SimHitList& hitlist) { + //Returns false only if we prune down to zero information! + + if (hitlist.empty()) + return true; + + + static double unknown = -1.0e99; + double mom(unknown), time(unknown); + if (p) { + const HepMC::GenVertex * v = p->production_vertex(); + if (v) { + mom = mag(p->momentum()); + time = v->position().t()/CLHEP::c_light; + // theclass->messageDebug("fixMomentumInfoInSimHits genparticle "+str(mom/GeV)+" GeV, time = "+str(time/ns)+" ns"); + } + } + + //First thing we do is to quickly determine if we are in the special + //situation of all hits+genparticle missing momentum information, or + //all hits already including momentum information. + + bool sawhitwithoutmominfo(false); + bool sawhitwithmominfo(mom!=unknown); + SimHitList::iterator it(hitlist.begin()), itE(hitlist.end()); + for (;it!=itE;++it) { + const bool hasinfo = it->second->momentum()>=0.0; + if (hasinfo) + sawhitwithmominfo = true; + else + sawhitwithoutmominfo = true; + if (sawhitwithoutmominfo&&sawhitwithmominfo) + break; + } + + if (!sawhitwithoutmominfo) { + //Already perfectly fine + return true; + } + if (!sawhitwithmominfo) { + //Worst case scenario. Discard all for now. + theclass->messageDebug("Discarding hitlist." ); + SimHitList::iterator it(hitlist.begin()), itE(hitlist.end()); + for (;it!=itE;++it) + delete it->second; + hitlist.clear(); + return false; + } + +// { +// if (time!=unknown) +// theclass->messageDebug("BEFORE STARTS WITH GP time = "+str(time/ns)+" ns, mom = "+str(mom/GeV)+" GeV" ); +// SimHitList::iterator it(hitlist.begin()), itE(hitlist.end()); +// for (;it!=itE;++it) { +// theclass->messageDebug("BEFORE time = "+str(it->second->hitTime()/ns)+" ns, mom = "+str(it->second->momentum()/GeV)+" GeV" ); +// } +// } + + //OK, we have some mom info, but not in all hits. Time to do some dirty work! + + //First (if no genparticle), we check if the hitlist begins with + //hits without momentum information. If it does, we simply supply + //the first hit with an *extrapolated* guess! + if (mom==unknown) { + if (hitlist.at(0).second->momentum()<0.0) { + SimHitList::iterator it(hitlist.begin()), itE(hitlist.end()); + for (;it!=itE;++it) { + if (it->second->momentum()>=0.0) { + hitlist.at(0).second->setFakeMomentum(it->second->momentum()*1.00001);//We make it slightly bigger. Just because. + break; + } + } + if (hitlist.at(0).second->momentum()<0.0) { + theclass->messageDebug("fixMomentumInfoInSimHits ERROR: Should not happen! (1)" ); + //Fixme: clear hitlist. + return false; + } + } + mom = hitlist.at(0).second->momentum(); + time = hitlist.at(0).second->hitTime(); + } + + //Then we check if the hitlist ends with hits without momentum + //information. If it does we simply supply the very last of the hits + //with an *extrapolated* guess! (FIXME: ASSUME 0.01% loss every CLHEP::ns or + //something else that is simple? Or even use the extrapolator to the + //last of those hits?) + unsigned ilast = hitlist.size()-1; + if (hitlist.at(ilast).second->momentum()<0.0) { + for (int iLastWithMom = ilast-1;iLastWithMom>=0;--iLastWithMom) { + if (hitlist.at(iLastWithMom).second->momentum()>0.0) { + hitlist.at(ilast).second->setFakeMomentum(hitlist.at(iLastWithMom).second->momentum()*0.99999);//Slight smaller. Just because. + break; + } + } + if (hitlist.at(ilast).second->momentum()<0.0) { + //Get it from the genparticle: + if (mom==unknown) { + theclass->messageDebug("fixMomentumInfoInSimHits ERROR: Should not happen! (2)" ); + //Fixme: clear hitlist. + return false; + } + hitlist.at(ilast).second->setFakeMomentum(mom*0.99999); + } + } + + //Every unknown momentum is now surrounded in time with momentum information. Time to interpolate!! + if (mom==unknown||time==unknown) { + //No genparticle. Initialise from first hit. + mom = hitlist.at(0).second->momentum(); + time = hitlist.at(0).second->hitTime(); + } + + unsigned iNextWithMom(0); + for (unsigned i = 0; i < hitlist.size(); ++i) { + if (hitlist.at(i).second->momentum()>=0.0) { + mom = hitlist.at(i).second->momentum(); + time = hitlist.at(i).second->hitTime(); + continue; + } + if (iNextWithMom<=i) { + for (unsigned j = i+1;j<hitlist.size();++j) { + if (hitlist.at(j).second->momentum()>=0.0) { + iNextWithMom = j; + break; + } + } + if (iNextWithMom<=i) { + theclass->messageDebug("fixMomentumInfoInSimHits ERROR: Should not happen! (3)" ); + //Fixme: clear hitlist. + return false; + } + } + // + double time2 = hitlist.at(iNextWithMom).second->hitTime(); + double mom2 = hitlist.at(iNextWithMom).second->momentum(); + double t = hitlist.at(i).second->hitTime(); +// theclass->message("ABOUT TO INTERPOLATE time="+str(time/ns)+", t="+str(t/ns)+", time2="+str(time2/ns)+", mom="+str(mom/GeV)+", mom2="+str(mom2/GeV));//fixme + + if (t<=time||t>=time2||time2<=time) + theclass->message("SUSPICIOUS TIME");//fixme + if (mom2>=mom) + theclass->message("SUSPICIOUS MOM mom="+str(mom)+", mom2="+str(mom2));//fixme + mom += (mom2-mom)*(t-time)/(time2-time); + time = t; + hitlist.at(i).second->setFakeMomentum(mom); + } + + + + +// //Now we loop through the list and see what we need to fix, if anything: + +// unsigned iNextWithMom(0); +// for (unsigned i = 1/*already dealt with first*/; i < hitlist.size(); ++i) { +// if (hitlist.at(i).second->momentum()>=0.0) { +// mom = hitlist.at(i).second->momentum(); +// time = hitlist.at(i).second->hitTime(); +// } else { +// if (iNextWithMom<=i) { +// for (unsigned j = i+1;j<hitlist.size();++j) { +// if (hitlist.at(j).second->momentum()>=0.0) { +// iNextWithMom = j; +// break; +// } +// } +// if (iNextWithMom<=i) { +// //Discard end of list!! +// unsigned j = i; +// for (;j<hitlist.size();++j) { +// //TESTdelete hitlist.at(j).second; +// } +// hitlist.resize(j); +// theclass->messageDebug("Discarded "+str(hitlist.size()-i)+" simhits due to missing momentum information at the start of the list"); +// return !hitlist.empty() || !p; +// } +// //Interpolate mom(time) values: +// double time2 = hitlist.at(iNextWithMom).second->hitTime(); +// double mom2 = hitlist.at(iNextWithMom).second->momentum(); +// double t = hitlist.at(i).second->hitTime(); +// if (t<=time||t>=time2||time2<=time) +// theclass->message("SUSPICIOUS TIME");//fixme +// if (mom2>=mom) +// theclass->message("SUSPICIOUS MOM");//fixme +// mom = (t-time)/(time2-time)*(mom2-mom); +// time = t; +// hitlist.at(i).second->setFakeMomentum(mom); +// } +// } +// } + + +// // typedef std::vector<std::pair<double,SimHitHandleBase*> > SimHitList;//hitTime() to SimHitHandle's + + +// { +// SimHitList::iterator it(hitlist.begin()), itE(hitlist.end()); +// for (;it!=itE;++it) { +// theclass->messageDebug("AFTER time = "+str(it->second->hitTime()/ns)+" ns, mom = "+str(it->second->momentum()/GeV)+" GeV" ); +// } +// } + + return true; + +} + + +//If has momentum - Check light-speed consistency given positions and time. +//mom should be decreasing + +//____________________________________________________________________ +void TrackCollHandle_TruthTracks::Imp::updateVisibleAssociatedObjects() +{ + + theclass->message("updateVisibleAssociatedObjects");//fixme + theclass->largeChangesBegin(); + theclass->trackHandleIterationBegin(); + TrackHandle_TruthTrack* handle; + while ((handle=static_cast<TrackHandle_TruthTrack*>(theclass->getNextTrackHandle()))) { + handle->setAscObjsVisible(displayAscObjs); + } + theclass->largeChangesEnd(); +} + diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCollWidget.cxx b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCollWidget.cxx new file mode 100644 index 000000000..3b669a29d --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCollWidget.cxx @@ -0,0 +1,44 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class TrackCollWidget // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: February 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12TrackSystems/TrackCollWidget.h" +#include "VTI12TrackSystems/TrackTypes.h" + +//____________________________________________________________________ +class TrackCollWidget::Imp { +public: + static TrackCollWidget * theclass; + static bool sectionSorting(const QString &s1, const QString &s2) + { + //We sort by the order of the types in the enum. + bool ok1, ok2; + TrackType::Type type1 = TrackType::sectionHeaderToType(s1, ok1); + TrackType::Type type2 = TrackType::sectionHeaderToType(s2, ok2); + if (!ok1&&theclass) + theclass->message("Could not decode section header to type: '"+s1+"'"); + if (!ok2&&theclass) + theclass->message("Could not decode section header to type: '"+s2+"'"); + return static_cast<int>(type1) < static_cast<int>(type2); + } +}; + +TrackCollWidget * TrackCollWidget::Imp::theclass = 0; + +//____________________________________________________________________ +void TrackCollWidget::sortSections(QList<QString>& sections) +{ + Imp::theclass = this;//I guess this is not really threadsafe... + qSort(sections.begin(),sections.end(),Imp::sectionSorting); + Imp::theclass = 0; +} diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCollectionSettingsButton.cxx b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCollectionSettingsButton.cxx new file mode 100644 index 000000000..e66d9382e --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCollectionSettingsButton.cxx @@ -0,0 +1,642 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "VTI12TrackSystems/TrackCollectionSettingsButton.h" +#include "VP1Base/VP1QtInventorUtils.h" +#include "VP1Base/VP1ColorSelectButton.h" +#include "VP1Base/VP1Serialise.h" +#include "VP1Base/VP1Deserialise.h" + +#include "ui_pertrackcollectionsettings_form.h" +#include "ui_settings_cuts_form.h" + +#include "CLHEP/Units/SystemOfUnits.h" + +#include "Inventor/nodes/SoDrawStyle.h" +#include "Inventor/nodes/SoLightModel.h" +#include <iostream> + +#include <QTimer> +#include <QByteArray> +#include <QBuffer> +#include <QDataStream> +#include <QMouseEvent> +#include <QDragEnterEvent> +#include <QDropEvent> +#include <QShortcut> +#include <QMimeData> +#include <QDrag> + + +//____________________________________________________________________ +class TrackCollectionSettingsButton::Imp { +public: + Imp():theclass(0),editwindow(0),matButton(0), trackDrawStyle(0), trackLightModel(0), + last_trackTubeRadius(0.0),last_cutTruthFromIROnly{}, last_cutExcludeBarcodeZero{}, + last_cutTruthExcludeNeutrals{},last_cutOnlyVertexAssocTracks{},last_useDefaultCuts{}, + dim(0), serialization_version(0){ + //nop + } + TrackCollectionSettingsButton * theclass; + QWidget * editwindow; + Ui::TrackCollectionSettingsForm editwindow_ui; + + VP1MaterialButton* matButton; + + SoDrawStyle * trackDrawStyle; + SoLightModel * trackLightModel; + + //GUI - last values + double last_trackTubeRadius; + VP1Interval last_cutAllowedPt; + VP1Interval last_cutAllowedP; + VP1Interval last_cutAllowedEta; + QList<VP1Interval> last_cutAllowedPhi; + QList<unsigned> last_cutRequiredNHits; + bool last_cutTruthFromIROnly; + bool last_cutExcludeBarcodeZero; + bool last_cutTruthExcludeNeutrals; + bool last_cutOnlyVertexAssocTracks; + bool last_useDefaultCuts; + + int dim; + QPoint dragStartPosition; + + void initEditWindow(); + + int serialization_version; +}; + +//____________________________________________________________________ +void TrackCollectionSettingsButton::Imp::initEditWindow() +{ + if (editwindow) + return; + theclass->messageVerbose("Initialising material editor dialog"); + editwindow = new QWidget(0,Qt::WindowStaysOnTopHint); + editwindow_ui.setupUi(editwindow); + matButton = editwindow_ui.pushButton_matButton; +} + +//____________________________________________________________________ +void TrackCollectionSettingsButton::setText(const QString& t) +{ + if (m_d->editwindow) + m_d->editwindow->setWindowTitle(t); + setToolTip(t); +} + +//____________________________________________________________________ +TrackCollectionSettingsButton::TrackCollectionSettingsButton(QWidget * parent,int dim) + : VP1MaterialButtonBase(parent,0,"VP1MaterialButton"), m_d(new Imp) +{ + m_d->dim = dim; + + m_d->theclass = this; + m_d->initEditWindow(); + + // declare the current serialization version number + m_d->serialization_version = 2; + + + //Draw Styles / Complexity: + VP1QtInventorUtils::setLimitsLineWidthSlider(m_d->editwindow_ui.horizontalSlider_trackWidth); + VP1QtInventorUtils::setValueLineWidthSlider(m_d->editwindow_ui.horizontalSlider_trackWidth,1.0); + + m_d->trackDrawStyle = new SoDrawStyle; + m_d->trackDrawStyle->setName("TrackDrawStyle"); + m_d->trackDrawStyle->ref(); + updateTrackDrawStyle(); + connect(m_d->editwindow_ui.horizontalSlider_trackWidth,SIGNAL(valueChanged(int)),this,SLOT(updateTrackDrawStyle())); + + m_d->trackLightModel = new SoLightModel; + m_d->trackLightModel->setName("TrackLightModel"); + m_d->trackLightModel->ref(); + updateTrackLightModel(false); + connect(m_d->editwindow_ui.checkBox_tracksUseBaseLightModel,SIGNAL(toggled(bool)),this,SLOT(updateTrackLightModel(bool))); + + m_d->last_trackTubeRadius=trackTubeRadius(); + connect(m_d->editwindow_ui.checkBox_trackTubes,SIGNAL(toggled(bool)),this,SLOT(updateTrackTubeRadius())); + connect(m_d->editwindow_ui.doubleSpinBox_trackTubesRadiusMM,SIGNAL(valueChanged(double)),this,SLOT(updateTrackTubeRadius())); + + connect(m_d->editwindow_ui.checkBox_hideactualpaths,SIGNAL(toggled(bool)),this,SLOT(updateHideActualTrackPath(bool))); + + // Cuts + connect(m_d->editwindow_ui.checkBox_defaultCuts,SIGNAL(toggled(bool)),this,SLOT(possibleChange_useDefaultCuts())); + m_d->last_useDefaultCuts=m_d->editwindow_ui.checkBox_defaultCuts->isChecked(); + messageVerbose("editwindow_ui.checkBox_defaultCuts->isChecked() L " + str(m_d->editwindow_ui.checkBox_defaultCuts->isChecked())); + + + // -> cutAllowedP/Pt + connect(m_d->editwindow_ui.checkBox_cut_minpt,SIGNAL(toggled(bool)),this,SLOT(possibleChange_cutAllowedPt())); + connect(m_d->editwindow_ui.checkBox_cut_maxpt,SIGNAL(toggled(bool)),this,SLOT(possibleChange_cutAllowedPt())); + connect(m_d->editwindow_ui.doubleSpinBox_cut_minpt_gev,SIGNAL(valueChanged(double)),this,SLOT(possibleChange_cutAllowedPt())); + connect(m_d->editwindow_ui.doubleSpinBox_cut_maxpt_gev,SIGNAL(valueChanged(double)),this,SLOT(possibleChange_cutAllowedPt())); + connect(m_d->editwindow_ui.checkBox_cut_minpt,SIGNAL(toggled(bool)),this,SLOT(possibleChange_cutAllowedPt())); + //connect(m_d->editwindow_ui.comboBox_momtype,SIGNAL(valueChanged(bool)),this,SLOT(possibleChange_cutAllowedPt())); + connect(m_d->editwindow_ui.comboBox_momtype,SIGNAL(currentIndexChanged(int)),this,SLOT(possibleChange_cutAllowedPt())); + + + // -> cutAllowedEta + connect(m_d->editwindow_ui.etaPhiCutWidget,SIGNAL(allowedEtaChanged(const VP1Interval&)),this,SLOT(possibleChange_cutAllowedEta())); + + // -> cutAllowedPhi + connect(m_d->editwindow_ui.etaPhiCutWidget,SIGNAL(allowedPhiChanged(const QList<VP1Interval>&)),this,SLOT(possibleChange_cutAllowedPhi())); + + // -> cutRequiredNHits(); + connect(m_d->editwindow_ui.checkBox_cut_nhits_pixel,SIGNAL(toggled(bool)),this,SLOT(possibleChange_cutRequiredNHits())); + connect(m_d->editwindow_ui.checkBox_cut_nhits_sct,SIGNAL(toggled(bool)),this,SLOT(possibleChange_cutRequiredNHits())); + connect(m_d->editwindow_ui.checkBox_cut_nhits_trt,SIGNAL(toggled(bool)),this,SLOT(possibleChange_cutRequiredNHits())); + connect(m_d->editwindow_ui.checkBox_cut_nhits_muon,SIGNAL(toggled(bool)),this,SLOT(possibleChange_cutRequiredNHits())); + connect(m_d->editwindow_ui.checkBox_cut_nprecisionhits_muon,SIGNAL(toggled(bool)),this,SLOT(possibleChange_cutRequiredNHits())); + connect(m_d->editwindow_ui.spinBox_cut_nhits_pixel,SIGNAL(valueChanged(int)),this,SLOT(possibleChange_cutRequiredNHits())); + connect(m_d->editwindow_ui.spinBox_cut_nhits_sct,SIGNAL(valueChanged(int)),this,SLOT(possibleChange_cutRequiredNHits())); + connect(m_d->editwindow_ui.spinBox_cut_nhits_trt,SIGNAL(valueChanged(int)),this,SLOT(possibleChange_cutRequiredNHits())); + connect(m_d->editwindow_ui.spinBox_cut_nhits_muon,SIGNAL(valueChanged(int)),this,SLOT(possibleChange_cutRequiredNHits())); + connect(m_d->editwindow_ui.spinBox_cut_nprecisionhits_muon,SIGNAL(valueChanged(int)),this,SLOT(possibleChange_cutRequiredNHits())); + + // -> cutTruthFromIROnly + connect(m_d->editwindow_ui.checkBox_cut_truthtracks_creationvertexinIR,SIGNAL(toggled(bool)),this,SLOT(possibleChange_cutTruthFromIROnly())); + + // -> cutExcludeBarcodeZero + connect(m_d->editwindow_ui.checkBox_cut_truthtracks_excludebarcode0,SIGNAL(toggled(bool)),this,SLOT(possibleChange_cutExcludeBarcodeZero())); + + // -> cutTruthExcludeNeutrals + connect(m_d->editwindow_ui.checkBox_cut_truthtracks_excludeneutrals,SIGNAL(toggled(bool)),this,SLOT(possibleChange_cutTruthExcludeNeutrals())); + + // -> cutOnlyVertexAssocTracks + connect(m_d->editwindow_ui.checkBox_vertexAssociated,SIGNAL(toggled(bool)),this,SLOT(possibleChange_cutOnlyVertexAssocTracks())); + + connect(this,SIGNAL(clicked()),this,SLOT(showEditMaterialDialog())); + connect(m_d->editwindow_ui.pushButton_close,SIGNAL(clicked()),this,SLOT(showEditMaterialDialog())); + connect(m_d->matButton,SIGNAL(lastAppliedChanged()),this,SLOT(updateButton())); + connect(m_d->matButton,SIGNAL(lastAppliedChanged()),this,SIGNAL(lastAppliedChanged())); + setAcceptDrops(true); + + QTimer::singleShot(0, this, SLOT(updateButton())); + +} + +// QWidget& TrackCollectionSettingsButton::editWindow() { +// if (!m_d->editwindow) +// initEditWindow(); +// return *(m_d->editwindow); +// } +TrackCollectionSettingsButton::~TrackCollectionSettingsButton() +{ + delete m_d->editwindow; + m_d->trackDrawStyle->unref(); + m_d->trackLightModel->unref(); + delete m_d; +} + +void TrackCollectionSettingsButton::updateButton() +{ + if (objectName().isEmpty()) + setObjectName("TrackCollectionSettingsButton"); + messageVerbose("setColButtonProperties: color=" + str(m_d->matButton->lastAppliedDiffuseColour())); + VP1ColorSelectButton::setColButtonProperties(this,m_d->matButton->lastAppliedDiffuseColour(),m_d->dim); +} + +void TrackCollectionSettingsButton::setDimension(int dim) +{ + if (m_d->dim == dim) + return; + m_d->dim = dim; + updateButton(); +} + +void TrackCollectionSettingsButton::showEditMaterialDialog() +{ + if (!m_d->editwindow) + m_d->initEditWindow(); + + if (m_d->editwindow->isHidden()) + m_d->editwindow->show(); + else + m_d->editwindow->hide(); +} + +bool TrackCollectionSettingsButton::setMaterial(SoMaterial*mat) +{ + if (!m_d->matButton) m_d->initEditWindow(); + m_d->matButton->setMaterial(mat); + return true; +} + +void TrackCollectionSettingsButton::copyValuesFromMaterial(SoMaterial*mat) +{ + if (!m_d->matButton) m_d->initEditWindow(); + m_d->matButton->setMaterial(mat); +} +double TrackCollectionSettingsButton::lastAppliedTransparency() const +{ + if (!m_d->matButton) m_d->initEditWindow(); + return m_d->matButton->lastAppliedTransparency(); +} +double TrackCollectionSettingsButton::lastAppliedShininess() const +{ + if (!m_d->matButton) m_d->initEditWindow(); + return m_d->matButton->lastAppliedShininess(); +} +double TrackCollectionSettingsButton::lastAppliedBrightness() const +{ + if (!m_d->matButton) m_d->initEditWindow(); + return m_d->matButton->lastAppliedBrightness(); +} + +double TrackCollectionSettingsButton::trackTubeRadius() const +{ + return m_d->editwindow_ui.checkBox_trackTubes->isChecked() ? + m_d->editwindow_ui.doubleSpinBox_trackTubesRadiusMM->value()*CLHEP::mm : 0.0; +} + +void TrackCollectionSettingsButton::updateTrackTubeRadius() +{ + if (m_d->last_trackTubeRadius==trackTubeRadius()) return; + m_d->last_trackTubeRadius=trackTubeRadius(); + messageVerbose("TrackTubeRadius changed to "+str(m_d->last_trackTubeRadius)); + emit trackTubeRadiusChanged(m_d->last_trackTubeRadius); + return; +} + +void TrackCollectionSettingsButton::updateTrackDrawStyle() +{ + double val = VP1QtInventorUtils::getValueLineWidthSlider(m_d->editwindow_ui.horizontalSlider_trackWidth); + if (m_d->trackDrawStyle->lineWidth.getValue()!=val) + m_d->trackDrawStyle->lineWidth = val; +} + +void TrackCollectionSettingsButton::updateTrackLightModel(bool base) +{ + if (m_d->trackLightModel->model.getValue()!=(base?SoLightModel::BASE_COLOR:SoLightModel::PHONG)) { + messageVerbose("TrackLightModel changed (base = "+str(base)); + if (base) + m_d->trackLightModel->model.setValue(SoLightModel::BASE_COLOR); + else + m_d->trackLightModel->model.setValue(SoLightModel::PHONG); + } +} + +void TrackCollectionSettingsButton::updateHideActualTrackPath(bool hide) +{ + emit hideActualTrackPathChanged(hide); +} + + +SoDrawStyle * TrackCollectionSettingsButton::trackDrawStyle() const +{ + return m_d->trackDrawStyle; +} + +SoLightModel * TrackCollectionSettingsButton::trackLightModel() const +{ + return m_d->trackLightModel; +} + +bool TrackCollectionSettingsButton::hideActualTrackPath() const +{ + return m_d->editwindow_ui.checkBox_hideactualpaths->isChecked(); +} + + +bool TrackCollectionSettingsButton::useDefaultCuts() const +{ + return m_d->editwindow_ui.checkBox_defaultCuts->isChecked(); +} + +bool TrackCollectionSettingsButton::cutOnlyVertexAssocTracks() const +{ + return m_d->editwindow_ui.checkBox_vertexAssociated->isChecked(); +} + +//____________________________________________________________________ +void TrackCollectionSettingsButton::mousePressEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) + m_d->dragStartPosition = event->pos(); + QPushButton::mousePressEvent(event); +} + +//____________________________________________________________________ +void TrackCollectionSettingsButton::dragEnterEvent(QDragEnterEvent *event) +{ + if (event->source()!=this && event->mimeData()->hasFormat("vp1/material")) + event->acceptProposedAction(); +} + +//____________________________________________________________________ +void TrackCollectionSettingsButton::mouseMoveEvent(QMouseEvent *event) +{ + if (!(event->buttons() & Qt::LeftButton)) + return; + if ((event->pos() - m_d->dragStartPosition).manhattanLength() + < QApplication::startDragDistance()) + return; + + QDrag *drag = new QDrag(this); + QMimeData *mimeData = new QMimeData; + + ///////////////////////////////////////////////////// + // For dragging state onto other material buttons: // + ///////////////////////////////////////////////////// + + QByteArray byteArray = saveState(); + + // buffer.close(); + mimeData->setData("vp1/material", byteArray); + + // //////////////////////////////////////////////////////// + // // For dragging c++ code for defining this material // + // // into e.g. an editor: // + // //////////////////////////////////////////////////////// + // + // QString s = "SoMaterial * mat = new SoMaterial;\n"; + // QString str_ambient = m_d->toSbColTxt(m_d->lastapplied_ambient); + // if (str_ambient!="SbColor(0.2,0.2,0.2)") + // s += "mat->ambientColor.setValue("+str_ambient+");\n"; + // QString str_diffuse = m_d->toSbColTxt(m_d->lastapplied_diffuse); + // if (str_diffuse!="SbColor(0.8,0.8,0.8)") + // s += "mat->diffuseColor.setValue("+str_diffuse+");\n"; + // QString str_specular = m_d->toSbColTxt(m_d->lastapplied_specular); + // if (str_specular!="SbColor(0,0,0)") + // s += "mat->specularColor.setValue("+str_specular+");\n"; + // QString str_emissive = m_d->toSbColTxt(m_d->lastapplied_emissive); + // if (str_emissive!="SbColor(0,0,0)") + // s += "mat->emissiveColor.setValue("+str_emissive+");\n"; + // QString str_shininess = m_d->printFloat(m_d->lastapplied_shininess/100.0); + // if (str_shininess!="0.2") + // s += "mat->shininess.setValue("+str_shininess+");\n"; + // QString str_transparency = m_d->printFloat(m_d->lastapplied_transparency/100.0); + // if (str_transparency!="0") + // s += "mat->transparency.setValue("+str_transparency+");\n"; + // mimeData->setText(s); + + //Execute drag: + drag->setMimeData(mimeData);//drag assumes ownership of mimeData + drag->exec(Qt::CopyAction | Qt::MoveAction); +} + +//____________________________________________________________________ +void TrackCollectionSettingsButton::dropEvent(QDropEvent *event) +{ + QByteArray data = event->mimeData()->data("vp1/material"); + event->acceptProposedAction(); + restoreFromState(data); +} + + +QByteArray TrackCollectionSettingsButton::saveState() const{ + // messageVerbose("getState"); + // if (m_d->editwindow_ui.checkBox_tracksUseBaseLightModel->isChecked()) messageVerbose("checked!"); + + // start serializing data with the current version number, + // which is declared in the contructor + VP1Serialise serialise(m_d->serialization_version/*version*/); + + serialise.save(m_d->matButton); + // serialise.disableUnsavedChecks(); + serialise.save(m_d->editwindow_ui.horizontalSlider_trackWidth); + serialise.save(m_d->editwindow_ui.checkBox_trackTubes); + serialise.save(m_d->editwindow_ui.doubleSpinBox_trackTubesRadiusMM); + serialise.save(m_d->editwindow_ui.checkBox_tracksUseBaseLightModel); + serialise.save(m_d->editwindow_ui.checkBox_hideactualpaths); + serialise.save(m_d->editwindow_ui.checkBox_defaultCuts); + serialise.save(m_d->editwindow_ui.checkBox_defaultCuts); + + serialise.save(m_d->editwindow_ui.checkBox_cut_minpt); + serialise.save(m_d->editwindow_ui.checkBox_cut_maxpt); + serialise.save(m_d->editwindow_ui.doubleSpinBox_cut_minpt_gev); + serialise.save(m_d->editwindow_ui.doubleSpinBox_cut_maxpt_gev); + serialise.save(m_d->editwindow_ui.checkBox_cut_minpt); + serialise.save(m_d->editwindow_ui.comboBox_momtype); + serialise.save(m_d->editwindow_ui.etaPhiCutWidget); + serialise.save(m_d->editwindow_ui.etaPhiCutWidget); + serialise.save(m_d->editwindow_ui.checkBox_cut_nhits_pixel); + serialise.save(m_d->editwindow_ui.checkBox_cut_nhits_sct); + serialise.save(m_d->editwindow_ui.checkBox_cut_nhits_trt); + serialise.save(m_d->editwindow_ui.checkBox_cut_nhits_muon); + serialise.save(m_d->editwindow_ui.checkBox_cut_nprecisionhits_muon); + serialise.save(m_d->editwindow_ui.spinBox_cut_nhits_pixel); + serialise.save(m_d->editwindow_ui.spinBox_cut_nhits_sct); + serialise.save(m_d->editwindow_ui.spinBox_cut_nhits_trt); + serialise.save(m_d->editwindow_ui.spinBox_cut_nhits_muon); + serialise.save(m_d->editwindow_ui.spinBox_cut_nprecisionhits_muon); + serialise.save(m_d->editwindow_ui.checkBox_cut_truthtracks_creationvertexinIR); + serialise.save(m_d->editwindow_ui.checkBox_cut_truthtracks_excludebarcode0); + serialise.save(m_d->editwindow_ui.checkBox_cut_truthtracks_excludeneutrals); + serialise.save(m_d->editwindow_ui.checkBox_vertexAssociated); + + serialise.widgetHandled(this); + serialise.warnUnsaved(this); + return serialise.result(); +} + +void TrackCollectionSettingsButton::restoreFromState( const QByteArray& ba){ + + VP1Deserialise state(ba,systemBase()); + + if (state.version()<0||state.version()>2) { + message("Version of 'TrackCollectionSettingsButton' settings file not recognized: "+QString::number(state.version())+" [current: "+QString::number(m_d->serialization_version)+"]. Ignoring..."); + return;//Ignore silently + } + state.restore(m_d->matButton); + state.restore(m_d->editwindow_ui.horizontalSlider_trackWidth); + state.restore(m_d->editwindow_ui.checkBox_trackTubes); + state.restore(m_d->editwindow_ui.doubleSpinBox_trackTubesRadiusMM); + state.restore(m_d->editwindow_ui.checkBox_tracksUseBaseLightModel); + state.restore(m_d->editwindow_ui.checkBox_hideactualpaths); + state.restore(m_d->editwindow_ui.checkBox_defaultCuts); + + state.restore(m_d->editwindow_ui.checkBox_cut_minpt); + state.restore(m_d->editwindow_ui.checkBox_cut_maxpt); + state.restore(m_d->editwindow_ui.doubleSpinBox_cut_minpt_gev); + state.restore(m_d->editwindow_ui.doubleSpinBox_cut_maxpt_gev); + state.restore(m_d->editwindow_ui.checkBox_cut_minpt); + state.restore(m_d->editwindow_ui.comboBox_momtype); + state.restore(m_d->editwindow_ui.etaPhiCutWidget); + state.restore(m_d->editwindow_ui.etaPhiCutWidget); + state.restore(m_d->editwindow_ui.checkBox_cut_nhits_pixel); + state.restore(m_d->editwindow_ui.checkBox_cut_nhits_sct); + state.restore(m_d->editwindow_ui.checkBox_cut_nhits_trt); + state.restore(m_d->editwindow_ui.checkBox_cut_nhits_muon); + state.restore(m_d->editwindow_ui.checkBox_cut_nprecisionhits_muon); + state.restore(m_d->editwindow_ui.spinBox_cut_nhits_pixel); + state.restore(m_d->editwindow_ui.spinBox_cut_nhits_sct); + state.restore(m_d->editwindow_ui.spinBox_cut_nhits_trt); + state.restore(m_d->editwindow_ui.spinBox_cut_nhits_muon); + state.restore(m_d->editwindow_ui.spinBox_cut_nprecisionhits_muon); + state.restore(m_d->editwindow_ui.checkBox_cut_truthtracks_creationvertexinIR); + state.restore(m_d->editwindow_ui.checkBox_cut_truthtracks_excludebarcode0); + state.restore(m_d->editwindow_ui.checkBox_cut_truthtracks_excludeneutrals); + state.restore(m_d->editwindow_ui.checkBox_vertexAssociated); + + state.widgetHandled(this); + state.warnUnrestored(this); + + updateTrackTubeRadius(); + updateTrackLightModel(m_d->editwindow_ui.checkBox_tracksUseBaseLightModel); + updateButton(); + //FIXME - anything else need updating? +} + +//____________________________________________________________________ +VP1Interval TrackCollectionSettingsButton::cutAllowedPt() const +{ + if (!m_d->editwindow_ui.checkBox_cut_minpt) + return VP1Interval(); + + // will set range to negative if we have momcut=P + // if minCut unset then min=-inf + // if minCut set, and Pt selected, then min=-minCut + // if minCut set, and P selected, then min=-maxCut + // etc + bool isPCut = m_d->editwindow_ui.comboBox_momtype->currentText()=="P"; + + const double minFromInterface=m_d->editwindow_ui.doubleSpinBox_cut_minpt_gev->value()*CLHEP::GeV; + const double maxFromInterface=m_d->editwindow_ui.doubleSpinBox_cut_maxpt_gev->value()*CLHEP::GeV; + + double min=0.0,max=0.0; + if (!isPCut) { + //Pt cut + min = (m_d->editwindow_ui.checkBox_cut_minpt->isChecked() ? minFromInterface : -std::numeric_limits<double>::infinity()); + max = (m_d->editwindow_ui.checkBox_cut_maxpt->isChecked() ? maxFromInterface : std::numeric_limits<double>::infinity()); + } else { + min = (m_d->editwindow_ui.checkBox_cut_maxpt->isChecked() ? -maxFromInterface : -std::numeric_limits<double>::infinity()); + max = (m_d->editwindow_ui.checkBox_cut_minpt->isChecked() ? -minFromInterface : std::numeric_limits<double>::infinity()); + } + + //message("cutAllowedPt: min,max="+QString::number(min)+","+QString::number(max)); + + if (max<min) + return VP1Interval(); + + return VP1Interval( min, max );//fixme: closed interval?? +} + +//____________________________________________________________________ +VP1Interval TrackCollectionSettingsButton::cutAllowedEta() const +{ + return m_d->editwindow_ui.etaPhiCutWidget->allowedEta(); +} + +//____________________________________________________________________ +QList<VP1Interval> TrackCollectionSettingsButton::cutAllowedPhi() const +{ + return m_d->editwindow_ui.etaPhiCutWidget->allowedPhi(); +} + +//____________________________________________________________________ +QList<unsigned> TrackCollectionSettingsButton::cutRequiredNHits() const +{ + unsigned npixel = m_d->editwindow_ui.checkBox_cut_nhits_pixel->isChecked() ? m_d->editwindow_ui.spinBox_cut_nhits_pixel->value() : 0; + unsigned nsct = m_d->editwindow_ui.checkBox_cut_nhits_sct->isChecked() ? m_d->editwindow_ui.spinBox_cut_nhits_sct->value() : 0; + unsigned ntrt = m_d->editwindow_ui.checkBox_cut_nhits_trt->isChecked() ? m_d->editwindow_ui.spinBox_cut_nhits_trt->value() : 0; + unsigned nmuon = m_d->editwindow_ui.checkBox_cut_nhits_muon->isChecked() ? m_d->editwindow_ui.spinBox_cut_nhits_muon->value() : 0; + unsigned nprecmuon = m_d->editwindow_ui.checkBox_cut_nprecisionhits_muon->isChecked() ? m_d->editwindow_ui.spinBox_cut_nprecisionhits_muon->value() : 0; + QList<unsigned> l; + if (!npixel&&!nsct&&!ntrt&&!nmuon&&!nprecmuon) + return l; + l << npixel << nsct << ntrt << nmuon << nprecmuon; + return l; +} + +//____________________________________________________________________ +bool TrackCollectionSettingsButton::cutTruthFromIROnly() const +{ + return m_d->editwindow_ui.checkBox_cut_truthtracks_creationvertexinIR->isChecked(); +} + +//____________________________________________________________________ +bool TrackCollectionSettingsButton::cutExcludeBarcodeZero() const +{ + return m_d->editwindow_ui.checkBox_cut_truthtracks_excludebarcode0->isChecked(); +} + +//____________________________________________________________________ +bool TrackCollectionSettingsButton::cutTruthExcludeNeutrals() const +{ + return m_d->editwindow_ui.checkBox_cut_truthtracks_excludeneutrals->isChecked(); +} + + + +// "POSSIBLECHANGE" SLOTS +//____________________________________________________________________ +void TrackCollectionSettingsButton::possibleChange_useDefaultCuts() +{ + if (m_d->last_useDefaultCuts==useDefaultCuts()) return; + messageVerbose("useDefaultCuts() changed"); + m_d->last_useDefaultCuts= useDefaultCuts(); + emit useDefaultCutsChanged(m_d->last_useDefaultCuts); +} +//____________________________________________________________________ +void TrackCollectionSettingsButton::possibleChange_cutAllowedPt() +{ + messageVerbose("possibleChange_cutAllowedPt() "); + + if (m_d->last_cutAllowedPt==cutAllowedPt()) return; + messageVerbose("cutAllowedPt() changed"); + m_d->last_cutAllowedPt= cutAllowedPt(); + emit cutAllowedPtChanged(m_d->last_cutAllowedPt); +} +//____________________________________________________________________ +void TrackCollectionSettingsButton::possibleChange_cutAllowedEta() +{ + if (m_d->last_cutAllowedEta==cutAllowedEta()) return; + messageVerbose("cutAllowedEta() changed"); + m_d->last_cutAllowedEta=cutAllowedEta(); + emit cutAllowedEtaChanged(m_d->last_cutAllowedEta); +} +//____________________________________________________________________ +void TrackCollectionSettingsButton::possibleChange_cutAllowedPhi() +{ + if (m_d->last_cutAllowedPhi==cutAllowedPhi()) return; + messageVerbose("cutAllowedPhi() changed"); + m_d->last_cutAllowedPhi=cutAllowedPhi(); + emit cutAllowedPhiChanged(m_d->last_cutAllowedPhi); +} +//____________________________________________________________________ +void TrackCollectionSettingsButton::possibleChange_cutRequiredNHits() +{ + messageVerbose("TrackCollectionSettingsButton::possibleChange_cutRequiredNHits"); + if (m_d->last_cutRequiredNHits==cutRequiredNHits()) return; + messageVerbose("cutRequiredNHits() changed"); + m_d->last_cutRequiredNHits=cutRequiredNHits(); + emit cutRequiredNHitsChanged(m_d->last_cutRequiredNHits); +} +//____________________________________________________________________ +void TrackCollectionSettingsButton::possibleChange_cutTruthFromIROnly() +{ + if (m_d->last_cutTruthFromIROnly==cutTruthFromIROnly()) return; + messageVerbose("cutTruthFromIROnly() changed"); + m_d->last_cutTruthFromIROnly=cutTruthFromIROnly(); + emit cutTruthFromIROnlyChanged(m_d->last_cutTruthFromIROnly); +} +//____________________________________________________________________ +void TrackCollectionSettingsButton::possibleChange_cutExcludeBarcodeZero() +{ + if (m_d->last_cutExcludeBarcodeZero==cutExcludeBarcodeZero()) return; + messageVerbose("cutExcludeBarcodeZero() changed"); + m_d->last_cutExcludeBarcodeZero=cutExcludeBarcodeZero(); + emit cutExcludeBarcodeZeroChanged(m_d->last_cutExcludeBarcodeZero); +} + +//____________________________________________________________________ +void TrackCollectionSettingsButton::possibleChange_cutTruthExcludeNeutrals() +{ + if (m_d->last_cutTruthExcludeNeutrals==cutTruthExcludeNeutrals()) return; + messageVerbose("cutTruthExcludeNeutrals() changed"); + m_d->last_cutTruthExcludeNeutrals=cutTruthExcludeNeutrals(); + emit cutTruthExcludeNeutralsChanged(m_d->last_cutTruthExcludeNeutrals); +} + +//____________________________________________________________________ +void TrackCollectionSettingsButton::possibleChange_cutOnlyVertexAssocTracks() +{ + if (m_d->last_cutOnlyVertexAssocTracks==cutOnlyVertexAssocTracks()) return; + messageVerbose("cutOnlyVertexAssocTracks() changed"); + m_d->last_cutOnlyVertexAssocTracks=cutOnlyVertexAssocTracks(); + emit cutOnlyVertexAssocTracksChanged(m_d->last_cutOnlyVertexAssocTracks); +} diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCommonFlags.cxx b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCommonFlags.cxx new file mode 100644 index 000000000..965ef8bc8 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCommonFlags.cxx @@ -0,0 +1,49 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class TrackCommonFlags // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: March 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12TrackSystems/TrackCommonFlags.h" + +//____________________________________________________________________ +QString TrackCommonFlags::toString(const SELECTIONMODE& sm) +{ + switch (sm) { + case SINGLEOBJECT: return "SINGLEOBJECT"; + case MULTITRACK: return "MULTITRACK"; + case TRACKFIT: return "TRACKFIT"; + default: return "Unknown (ERROR)"; + } +} + +QString TrackCommonFlags::toString(const FITTERMODE& sm) +{ + switch (sm) { + case FROMPRDS: return "FROMPRDS"; + case REFITSINGLETRACK: return "REFITSINGLETRACK"; + case EXTENDTRACKWITHPRDS: return "EXTENDTRACKWITHPRDS"; + case COMBINETWOTRACKS: return "COMBINETWOTRACKS"; + default: return "Unknown (ERROR)"; + } +} + + +//____________________________________________________________________ +QString TrackCommonFlags::toString(const DETAILLEVEL& dl ) +{ + switch (dl) { + case AUTO: return "AUTO"; + case SIMPLE: return "SIMPLE"; + case DETAILED: return "DETAILED"; + default: return "Unknown (ERROR)"; + } +} diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackHandleBase.cxx b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackHandleBase.cxx new file mode 100644 index 000000000..96f1ce6ea --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackHandleBase.cxx @@ -0,0 +1,1819 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class TrackHandleBase // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: February 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12TrackSystems/TrackHandleBase.h" +#include "VTI12TrackSystems/TrackCollHandleBase.h" +#include "VTI12TrackSystems/TrackSystemController.h" +#include "VTI12TrackSystems/VP1TrackSystem.h" +#include "VTI12TrackSystems/TrackPropagationHelper.h" +#include "VTI12TrackSystems/TrackLODManager.h" +#include "VTI12TrackSystems/AssociatedObjectHandleBase.h" +#include "VTI12TrackSystems/AscObjSelectionManager.h" +#include "VTI12TrackSystems/VP1TrackSanity.h" +#include "VTI12TrackSystems/SimBarCode.h"//For unknown pdg. Fixme: Use 0 for unknown pdg! +#include "VTI12TrackSystems/AscObj_TSOS.h" +#include "VTI12TrackSystems/TrkObjToString.h" +#include "VTI12Utils/VP1ParticleData.h" +#include "VTI12Utils/VP1LinAlgUtils.h" + +// #include "VP1GuideLineSystems/InDetProjHelper.h" + +#include "VTI12Utils/VP1JobConfigInfo.h" +#include "VP1Base/VP1ExtraSepLayerHelper.h" +#include "VP1Base/VP1Msg.h" +#include "VP1Base/VP1MaterialButton.h" +#include "VP1Base/VP1QtUtils.h" + +#include "TrkTrack/Track.h" +#include "TrkTrack/TrackStateOnSurface.h" +#include "VTI12Utils/SurfaceToSoNode.h" + +#include <Inventor/C/errors/debugerror.h> +#include <Inventor/nodes/SoLineSet.h> +#include <Inventor/nodes/SoVertexProperty.h> +#include <Inventor/nodes/SoSeparator.h> +#include <Inventor/nodes/SoMaterial.h> +#include <Inventor/nodes/SoPickStyle.h> +#include <Inventor/nodes/SoCylinder.h> +#include <Inventor/nodes/SoMatrixTransform.h> +#include <Inventor/SbRotation.h> +#include <Inventor/SbMatrix.h> +#include <Inventor/nodes/SoTranslation.h> +#include <Inventor/nodes/SoText2.h> + +#include "TrkVolumes/Volume.h" +#include "TrkVolumes/CylinderVolumeBounds.h" +#include "GeoPrimitives/AmgStringHelpers.h" +#include "GeoPrimitives/GeoPrimitives.h" + +#include <cassert> + + + +//____________________________________________________________________ +class TrackHandleBase::Imp { +public: + static void convertLineSetToCylinders(SoLineSet*line,SoSeparator*sep, const double& cylradius); + static double dist(const SbVec3f& p1,const SbVec3f& p2); + + static int ntrackhandles; + + Imp(TrackHandleBase*tc) : theclass(tc), + chargeinit(false), + charge(TrackHandleBase::unknown()), + massinit(false), + mass(TrackHandleBase::unknown()), + line(0), + extraRepresentation(0), + extrapSurfaces_sep(0), + extraRepAttached(false), + points_raw(0), points_propagated(0), + points_raw_id_projections(0), + points_propagated_id_projections(0), + randommaterial(0), + pathInfoLoaded(false), + pathInfo_TrkTrack(0), + pathInfo_Points(0), + label_sep(0), + shownTSOSParts(TrackCommonFlags::TSOS_NoObjects), + customColouredTSOSParts(TrackCommonFlags::TSOS_NoObjects), + tsos_ascobjs(0), + m_objBrowseTree(0), + tempMaxPropRadius(0.0){} + ~Imp() { delete tsos_ascobjs; } + TrackHandleBase * theclass; + + bool chargeinit; + double charge; + bool massinit; + double mass; + + SoLineSet * line;//This represents the line(s) representing the track and its projections + SoSeparator * extraRepresentation;//For alternative representations (e.g. tubes for lines) + SoSeparator* extrapSurfaces_sep;//!< for debugging. FIXME! + bool extraRepAttached; + + //For efficiency we cache parameterisations of the various track parts: + + //The next two vectors://=0 when not inited, !=0 but empty means previous attempt to init failed. + std::vector< Amg::Vector3D > * points_raw; + std::vector<Amg::Vector3D > * points_propagated; + //The following sets://=0 when not inited, !=0 and ->front().vector.empty() means previous attempt to init failed. + Amg::SetVectorVector3D * points_raw_id_projections; + // Amg::SetVectorVector3D * points_raw_muon_projections; + Amg::SetVectorVector3D * points_propagated_id_projections; + // Amg::SetVectorVector3D * points_propagated_muon_projections; + + void ensureInitPointsRaw(); + void ensureInitPointsPropagated(); + void ensureInitPointsProjections_InDet( bool raw ); + // void ensureInitPointsProjections_Muon( bool raw ); + + void materialChanged(); + + void rebuild3DObjects(); + void attach3DObjects(); + void detach3DObjects(); + + void addPathToSoLineSetAndSoVertexProperty(const std::vector<Amg::Vector3D >& points, + int & iver, int& numlines, SoLineSet *, SoVertexProperty * ); + void addPathsToSoLineSetAndSoVertexProperty(const Amg::SetVectorVector3D * paths, + int & iver, int& numlines,SoLineSet *, SoVertexProperty * ); + + SoMaterial * determineMaterial(); + SoMaterial * randommaterial; + + QList<AssociatedObjectHandleBase*> associatedObjects; + std::map<std::pair<int,double>,AssocObjAttachmentHandle *> attachmentHandles; + + //We cache path info, but it might get invalidated (if switching off simhits for instance): + bool pathInfoLoaded; + const Trk::Track * pathInfo_TrkTrack; + const std::vector< Amg::Vector3D > * pathInfo_Points; + SoSeparator * label_sep; + void ensureLoadPathInfo(); + + static bool isSane(const Amg::Vector3D& p) + { + if (p.x()!=p.x()||fabs(p.x())>1.0*CLHEP::km) + return false; + if (p.y()!=p.y()||fabs(p.y())>1.0*CLHEP::km) + return false; + if (p.z()!=p.z()||fabs(p.z())>1.0*CLHEP::km) + return false; + return true; + } + + + TrackCommonFlags::TSOSPartsFlags shownTSOSParts; + TrackCommonFlags::TSOSPartsFlags customColouredTSOSParts; + std::vector<AscObj_TSOS*> * tsos_ascobjs; + void ensureInitTSOSs(); + AscObj_TSOS* addTSOS(const Trk::TrackStateOnSurface * tsos,unsigned index); + + QTreeWidgetItem* m_objBrowseTree; + float tempMaxPropRadius; +}; + + +int TrackHandleBase::Imp::ntrackhandles = 0; + +//____________________________________________________________________ +void TrackHandleBase::Imp::ensureLoadPathInfo() +{ + if (pathInfoLoaded) + return; + pathInfoLoaded = true; + pathInfo_TrkTrack = theclass->provide_pathInfoTrkTrack(); + if (pathInfo_TrkTrack) + return; + pathInfo_Points = theclass->provide_pathInfoPoints(); + if (!pathInfo_Points) { + theclass->collHandle()->systemBase()->message("ERROR: No path information for track in collection "+theclass->collHandle()->name()); + } +} + +//____________________________________________________________________ +TrackHandleBase::TrackHandleBase(TrackCollHandleBase*ch) + : m_d(new Imp(this)), m_visible(false), m_collhandle(ch), m_currentmaterial(0) +{ + assert(m_collhandle); + ++Imp::ntrackhandles; +} + +//____________________________________________________________________ +TrackHandleBase::~TrackHandleBase() +{ + if (m_d->extraRepresentation) + common()->unregisterTrack(m_d->extraRepresentation); + + //Fixme: if visible, should we call detach first? + foreach(AssociatedObjectHandleBase*ao,m_d->associatedObjects) + delete ao; + + //Delete points the following way since we might use same points for raw and propagated. + if (m_d->points_propagated != m_d->points_raw) + delete m_d->points_propagated; + delete m_d->points_raw; + if (m_d->points_propagated_id_projections != m_d->points_raw_id_projections) + delete m_d->points_propagated_id_projections; + delete m_d->points_raw_id_projections; + + clearLine(); + if (m_currentmaterial) + m_currentmaterial->unref(); + if (m_d->randommaterial) + m_d->randommaterial->unref(); + if (m_d->label_sep) + m_d->label_sep->unref(); + + std::map<std::pair<int,double>,AssocObjAttachmentHandle *>::iterator it,itE(m_d->attachmentHandles.end()); + for (it = m_d->attachmentHandles.begin();it!=itE;++it) + delete it->second; + + delete m_d; + --Imp::ntrackhandles; +} + +//____________________________________________________________________ +int TrackHandleBase::numberOfInstances() +{ + return Imp::ntrackhandles; +} + +//____________________________________________________________________ +TrackSysCommonData * TrackHandleBase::common() const +{ + return m_collhandle->common(); +} + +//____________________________________________________________________ +void TrackHandleBase::updateShapes_TSOSWithMeasurements() +{ + if (!m_d->tsos_ascobjs) + return; + std::vector<AscObj_TSOS*>::iterator + it(m_d->tsos_ascobjs->begin()), + itE(m_d->tsos_ascobjs->end()); + for (;it!=itE;++it) + if ((*it)->hasMeasurement()) + (*it)->update3DObjects(); +} + +//____________________________________________________________________ +void TrackHandleBase::updateShapes_TSOSWithErrors() +{ + if (!m_d->tsos_ascobjs) + return; + std::vector<AscObj_TSOS*>::iterator + it(m_d->tsos_ascobjs->begin()), + itE(m_d->tsos_ascobjs->end()); + for (;it!=itE;++it) + if ((*it)->hasError()) + (*it)->update3DObjects(); +} + +//____________________________________________________________________ +void TrackHandleBase::updateShapes_TSOSWithMaterialEffects() +{ + if (!m_d->tsos_ascobjs) + return; + std::vector<AscObj_TSOS*>::iterator + it(m_d->tsos_ascobjs->begin()), + itE(m_d->tsos_ascobjs->end()); + for (;it!=itE;++it) + if ((*it)->hasMaterialEffect()) + (*it)->update3DObjects(); +} + +//____________________________________________________________________ +TrackCommonFlags::TSOSPartsFlags TrackHandleBase::shownTSOSParts() const +{ + return m_d->shownTSOSParts;//fixme: inline? +} + +//____________________________________________________________________ +TrackCommonFlags::TSOSPartsFlags TrackHandleBase::customColouredTSOSParts() const +{ + return m_d->customColouredTSOSParts;//fixme: inline? +} + +//____________________________________________________________________ +void TrackHandleBase::setShownTSOSParts(TrackCommonFlags::TSOSPartsFlags f) +{ + VP1Msg::messageDebug(QString("TrackHandleBase::setShownTSOSParts to ")+QString::number(f) ); + + if (m_d->shownTSOSParts==f) + return; + //Figure out changed bits: + TrackCommonFlags::TSOSPartsFlags change(m_d->shownTSOSParts ^ f);//^ is XOR + m_d->shownTSOSParts=f; + if (!m_d->tsos_ascobjs&&(m_d->shownTSOSParts==TrackCommonFlags::TSOS_NoObjects||!visible())) + return; + + m_d->ensureInitTSOSs(); + //Loop over all TSOS objects. Those with changed parts needs shape + //and visibility update: + std::vector<AscObj_TSOS*>::iterator it(m_d->tsos_ascobjs->begin()), itE(m_d->tsos_ascobjs->end()); + for (;it!=itE;++it) { + if (!((*it)->parts()&change)) + continue; + const bool vis = (*it)->parts() & m_d->shownTSOSParts; + if (vis==(*it)->visible()) { + //Just update shape: + (*it)->update3DObjects(); + continue; + } + //Need both shape and visibility updates. + if (vis) { + //update shape and then turn visible: + (*it)->update3DObjects(); + (*it)->setVisible(vis); + } else { + //turn invisible and then update (i.e. invalidate) shape: + (*it)->setVisible(vis); + (*it)->update3DObjects(); + } + } +} + +//____________________________________________________________________ +void TrackHandleBase::setCustomColouredTSOSParts(TrackCommonFlags::TSOSPartsFlags f) +{ + if (m_d->customColouredTSOSParts==f) + return; + //Figure out changed bits: + TrackCommonFlags::TSOSPartsFlags change(m_d->customColouredTSOSParts ^ f);//^ is XOR + m_d->customColouredTSOSParts=f; + + if (!m_d->tsos_ascobjs||m_d->shownTSOSParts==TrackCommonFlags::TSOS_NoObjects) + return; + + TrackCommonFlags::TSOSPartsFlags changedShownParts(change & m_d->shownTSOSParts); + + if (!changedShownParts) + return; + + //redundant m_d->ensureInitTSOSs(); + std::vector<AscObj_TSOS*>::iterator it(m_d->tsos_ascobjs->begin()), itE(m_d->tsos_ascobjs->end()); + for (;it!=itE;++it) { + if ((*it)->parts()&changedShownParts) + (*it)->update3DObjects(); + } +} + +//____________________________________________________________________ +void TrackHandleBase::Imp::ensureInitTSOSs() +{ + if (tsos_ascobjs) + return; + tsos_ascobjs = new std::vector<AscObj_TSOS*>; + ensureLoadPathInfo(); + if (!pathInfo_TrkTrack||!pathInfo_TrkTrack->trackParameters()||pathInfo_TrkTrack->trackParameters()->size()==0) + return; + VP1TrackSanity * sanity = theclass->common()->trackSanityHelper(); + + tsos_ascobjs->reserve(pathInfo_TrkTrack->trackParameters()->size()); + + unsigned parindex(0); + + AscObj_TSOS* ascObjNeedDistToNext(0); + DataVector<const Trk::TrackStateOnSurface>::const_iterator tsos_iter = pathInfo_TrkTrack->trackStateOnSurfaces()->begin(); + DataVector<const Trk::TrackStateOnSurface>::const_iterator tsos_end = pathInfo_TrkTrack->trackStateOnSurfaces()->end(); + const Trk::TrackParameters* trackParam(0); + for (; tsos_iter != tsos_end; ++tsos_iter) { + trackParam = (*tsos_iter)->trackParameters(); + if (!sanity->isSafe(*tsos_iter)) { + parindex++; + continue; + } + if (trackParam&&!sanity->isSafe(trackParam)) { + parindex++; + continue; + } + //Fixme: likewise check that we don't have a bad measurement, material effect, ... + if (ascObjNeedDistToNext&&trackParam) { + ascObjNeedDistToNext->setDistToNextPar((trackParam->position()-ascObjNeedDistToNext->approxCenter()).mag()); + ascObjNeedDistToNext = 0; + } + VP1Msg::messageVerbose("Adding TSOS at index:"+QString::number(parindex)); + ascObjNeedDistToNext = addTSOS(*tsos_iter,parindex++); + } + +} + +//____________________________________________________________________ +AscObj_TSOS* TrackHandleBase::Imp::addTSOS(const Trk::TrackStateOnSurface * tsos,unsigned index) +{ + AscObj_TSOS* ao = new AscObj_TSOS(theclass,tsos,index); + theclass->registerAssocObject(ao); + tsos_ascobjs->push_back(ao); + if (ao->parts()&shownTSOSParts) + ao->setVisible(true); + return ao; +} + +//____________________________________________________________________ +void TrackHandleBase::setVisible(bool vis) +{ + QString tmp = (vis==true)?"True":"False"; + QString tmp2 = (m_visible==true)?"True":"False"; + VP1Msg::messageDebug(QString("TrackHandleBase calling setVisible with vis=")+tmp+QString(", and m_visible=")+tmp2 ); + if (vis==m_visible) + return; + + m_visible=vis; + if (vis) { + m_collhandle->incrementNShownHandles(); + if (!m_d->line) + m_d->rebuild3DObjects();//The call to rebuild also fixes attached state. + else + m_d->attach3DObjects(); + } else { + m_collhandle->decrementNShownHandles(); + m_d->detach3DObjects(); + } + + bool initTSOS(false); + if (!m_d->tsos_ascobjs&&vis&&m_d->shownTSOSParts!=TrackCommonFlags::TSOS_NoObjects) { + m_d->ensureInitTSOSs(); + initTSOS = true; + } + + if (!initTSOS && m_d->tsos_ascobjs) { + std::vector<AscObj_TSOS*>::iterator + it(m_d->tsos_ascobjs->begin()), + itE(m_d->tsos_ascobjs->end()); + if (m_d->shownTSOSParts!=TrackCommonFlags::TSOS_NoObjects) { + for (;it!=itE;++it) { + if ((*it)->visible()!=((*it)->parts() & m_d->shownTSOSParts)) + (*it)->toggleVisible(); + } + } else { + for (;it!=itE;++it) { + if ((*it)->visible()) + (*it)->setVisible(false); + } + } + } + + visibleStateChanged(); + + std::map<std::pair<int,double>,AssocObjAttachmentHandle *>::iterator it,itE(m_d->attachmentHandles.end()); + for (it = m_d->attachmentHandles.begin();it!=itE;++it) + it->second->trackVisibilityChanged(); + + //Label + +} + +//____________________________________________________________________ +void TrackHandleBase::update3DObjects( bool invalidatePropagatedPoints, float maxR ) +{ + VP1Msg::messageVerbose(QString("TrackHandleBase::update3DObject with maxR set to ")+QString::number(maxR) ); + if (maxR>0.0) { + m_d->tempMaxPropRadius=maxR; + } + if ( invalidatePropagatedPoints) { + if (m_d->points_propagated != m_d->points_raw) { + delete m_d->points_propagated;m_d->points_propagated = 0; + } + delete m_d->points_raw;m_d->points_raw = 0; + if (m_d->points_propagated_id_projections) { delete m_d->points_propagated_id_projections; m_d->points_propagated_id_projections = 0; } + } + if (m_visible) { + m_d->rebuild3DObjects(); + } else { + //Simply clear the present 3D objects. They will only be recreated if/when the track becomes visible again. + clearLine(); + } + m_d->tempMaxPropRadius=0.0; +} + +//____________________________________________________________________ +// void TrackHandleBase::updateInDetProjections() +// { +// //Invalidate points of indet projections if already calculated: +// if (m_d->points_raw_id_projections!=m_d->points_propagated_id_projections) +// delete m_d->points_propagated_id_projections; +// delete m_d->points_raw_id_projections; +// m_d->points_raw_id_projections = 0; +// m_d->points_propagated_id_projections = 0; +// //Rebuild 3D objects: +// update3DObjects(); +// } + +//____________________________________________________________________ +void TrackHandleBase::Imp::addPathToSoLineSetAndSoVertexProperty(const std::vector<Amg::Vector3D >& points, + int & iver, int& numlines, + SoLineSet * line, SoVertexProperty * vertices ) +{ + if (points.size()<2) + return; + if (!line) { + theclass->collHandle()->systemBase()->message("TrackHandleBase::Imp::addPathToSoLineSetAndSoVertexProperty (1) ERROR: Unexpected null SoLineSet pointer!"); + return; + } + if (!vertices) { + theclass->collHandle()->systemBase()->message("TrackHandleBase::Imp::addPathToSoLineSetAndSoVertexProperty (1) ERROR: Unexpected null SoVertexPropery pointer!"); + return; + } + std::vector<Amg::Vector3D >::const_iterator pointsIt, pointsItEnd(points.end()); + unsigned npointsused(0); + + + float maxR2=theclass->common()->controller()->propMaxRadius()>0.0?theclass->common()->controller()->propMaxRadius():std::numeric_limits<float>::max(); + if (tempMaxPropRadius>0.0){ + maxR2 = tempMaxPropRadius * tempMaxPropRadius; + theclass->collHandle()->systemBase()->messageVerbose("maxR2 is set to "+VP1Msg::str(maxR2)); + } + float vertexPlanePhi = (theclass->common()->controller()->vertexProjectionAngle())*M_PI/180;// angle of plane to use for vertex projection + vertexPlanePhi-=M_PI; // ATLAS range is -PI to PI + + // theclass->collHandle()->systemBase()->messageVerbose("TrackHandleBase::Imp::addPathToSoLineSetAndSoVertexProperty - adding " + // +VP1Msg::str(points.size())+" points up to R2 of "+VP1Msg::str(maxR2)); + theclass->collHandle()->systemBase()->messageVerbose("Vertex projection is set to "+VP1Msg::str(vertexPlanePhi)); + + // unsigned int count=0; + + //For vertex projection + Amg::Vector3D tempPoint; + + double trkPhi = theclass->momentum().phi(); // some tracks curve between sections otherwise. + double newPhi= vertexPlanePhi+M_PI; + if (cos(vertexPlanePhi-trkPhi)>0) newPhi=vertexPlanePhi; + // theclass->collHandle()->systemBase()->messageVerbose("Vertex projection is set to "+VP1Msg::str(vertexPlanePhi)+" trkPhi= "+VP1Msg::str(trkPhi)+" newPhi="+VP1Msg::str(newPhi)); + + for (pointsIt = points.begin();pointsIt!=pointsItEnd && pointsIt->mag2()<maxR2; ++pointsIt) { + // theclass->collHandle()->systemBase()->messageVerbose(VP1Msg::str(count++)+": point has perp2="+VP1Msg::str(pointsIt->perp2())); + if (!isSane(*pointsIt)) { + theclass->collHandle()->systemBase()->message("WARNING: Ignoring point on track:"+VP1Msg::str( *pointsIt ) ); + continue; + } + + if (theclass->collHandle()->parts() & TrackCommonFlags::VertexProjections){ + tempPoint = *pointsIt; + Amg::setPhi(tempPoint, newPhi); + + // std::cout<<trkPhi<<"\t"<<phi<<"\t"<<r0<<"\t"<<r1<<"\t"<<r2<<"\t"<<r3<<"\t"<<rotatePhi<<"\t"<<tempPoint.getPhi()<<std::endl; + + vertices->vertex.set1Value(iver++,tempPoint.x(),tempPoint.y(),tempPoint.z()); + } else { + vertices->vertex.set1Value(iver++,pointsIt->x(),pointsIt->y(),pointsIt->z()); + } + ++npointsused; + } + line->numVertices.set1Value(numlines++,npointsused); +} + +//____________________________________________________________________ +void TrackHandleBase::Imp::addPathsToSoLineSetAndSoVertexProperty(const Amg::SetVectorVector3D * paths, + int & iver, int& numlines, + SoLineSet * line, SoVertexProperty * vertices ) +{ + if ( !paths || ( paths->size()==1 && paths->begin()->empty()) ) + return; + if (!line) { + theclass->collHandle()->systemBase()->message("TrackHandleBase::Imp::addPathToSoLineSetAndSoVertexProperty (2) ERROR: Unexpected null SoLineSet pointer!"); + return; + } + if (!vertices) { + theclass->collHandle()->systemBase()->message("TrackHandleBase::Imp::addPathToSoLineSetAndSoVertexProperty (2) ERROR: Unexpected null SoVertexPropery pointer!"); + return; + } + Amg::SetVectorVector3D::const_iterator itProjPart, itProjPartEnd(paths->end()); + for (itProjPart = paths->begin();itProjPart!=itProjPartEnd;++itProjPart) + addPathToSoLineSetAndSoVertexProperty(*itProjPart,iver,numlines,line,vertices); +} + +//____________________________________________________________________ +void TrackHandleBase::clearLine() +{ + if (m_d->line) { + common()->unregisterTrack(m_d->line); + m_d->line->unref(); + m_d->line=0; + } +} + +//____________________________________________________________________ +void TrackHandleBase::registerTrack() +{ + if (m_d->line) + common()->registerTrack(m_d->line,this); +} + + +//____________________________________________________________________ +void TrackHandleBase::Imp::rebuild3DObjects() +{ + //Ensure we are always detached while updating. + if (theclass->m_visible) + detach3DObjects(); + + // Make sure we're not going to redraw old surfaces, for this debug mode. + if (theclass->common()->trackPropagationHelper()->showExtrapolationSurfaces()) + theclass->common()->trackPropagationHelper()->getExtrapolationSurfaces().clear(); + + Trk::IExtrapolator * propagator = theclass->collHandle()->propagator(); + + if (propagator) + ensureInitPointsPropagated(); + else + ensureInitPointsRaw(); + + bool id_proj = theclass->collHandle()->parts() & TrackCommonFlags::InDetProjections; + if (id_proj) + ensureInitPointsProjections_InDet(!propagator); + + std::vector<Amg::Vector3D > * points; + Amg::SetVectorVector3D *proj_id; + if (propagator) { + points = points_propagated; + proj_id = points_propagated_id_projections; + } else { + points = points_raw; + proj_id = points_raw_id_projections; + } + + //Put points into an appropriate vertex property. + theclass->clearLine(); //Fixme: Since we are just changing shape - no need to delete line and take it + //out of the tree first. Just edit lineset properties instead. + line = new SoLineSet(); + line->ref(); + theclass->registerTrack(); + + SoVertexProperty * vertices = new SoVertexProperty(); + + int iver(0), numlines(0); + + std::vector<Amg::Vector3D >::const_iterator pointsIt, pointsItEnd; + + //Add various parts to these vertices as appropriate: + if (theclass->collHandle()->parts() & TrackCommonFlags::ActualPath) + addPathToSoLineSetAndSoVertexProperty(*points,iver,numlines,line,vertices); + if (id_proj) + addPathsToSoLineSetAndSoVertexProperty( proj_id, iver, numlines, line, vertices ); + + line->vertexProperty = vertices; + + ////////////////////////////////////////////////////////////// + + +// Add debugging surfaces. + if (theclass->common()->trackPropagationHelper()->showExtrapolationSurfaces()){ + std::vector<Trk::PlaneSurface>& surfaces = theclass->common()->trackPropagationHelper()->getExtrapolationSurfaces(); + std::vector<Trk::PlaneSurface>::const_iterator surfIt=surfaces.begin(), surfEnd=surfaces.end(); + SurfaceToSoNode surfCnv;//fixme: check if need in common() + extrapSurfaces_sep=new SoSeparator; + for (;surfIt!=surfEnd;++surfIt){ + SoNode* theSurfSep = surfCnv.translateSurface(*surfIt); + if (theSurfSep) { + SoNode * nodeToAdd = theSurfSep; + extrapSurfaces_sep->addChild(nodeToAdd); + } + } + } + +// Add labels + if (!points->empty() && theclass->common()->controller()->doTrackLabels() ){ + + // should detach first? This is all fairly suboptimal I'm sure... EJWM. + if (!label_sep){ + label_sep = new SoSeparator; + label_sep->ref(); + } + label_sep->removeAllChildren (); + + SoText2 *labelText = new SoText2; + labelText->ref(); + QStringList text; + TrackSystemController::TrackLabelModes labels=theclass->common()->controller()->trackLabels(); + if (labels&TrackSystemController::P){ + text << "P="+VP1Msg::str(theclass->momentum().mag())+" MeV"; + } + + if (labels&TrackSystemController::Pt){ + text << "|Pt|="+VP1Msg::str(theclass->momentum().perp())+" MeV"; + } + + if (labels&TrackSystemController::Pid){ + int pdg = theclass->pdgCode(); + if (pdg) { + bool ok; + QString name = VP1ParticleData::particleName(pdg,ok); + if (ok) + text << "pdg: "+QString::number(pdg)+" ["+name+"]"; + else + text << "pdg: "+QString::number(pdg); + } + } + + if (labels&TrackSystemController::FitQuality && theclass->getFitQuality()){ + text << TrkObjToString::shortInfo(*theclass->getFitQuality()); + } + + if (labels&TrackSystemController::Hits){ + text <<"SCT["+QString::number(theclass->getNSCTHits())+"]"; + } + + if (labels&TrackSystemController::Direction ){ + Amg::Vector3D mom = theclass->momentum(); + mom /= CLHEP::GeV; + if (mom.mag2()==0.0) { + text << "Momentum : 0 (undefined)"; + } else { + // SoCoin classes don't support Unincode here, apparently. + // text << VP1Msg::str("(")+QChar(0x03B7)+","+QChar(0x03D5)+VP1Msg::str(")=(") + // +VP1Msg::str(mom.pseudoRapidity())+VP1Msg::str(VP1LinAlgUtils::phiFromXY(mom.x(), mom.y() ))+VP1Msg::str(")"); + double pseudoRapidity = mom.eta(); + text << VP1Msg::str("(eta,phi)=(") + +VP1Msg::str(pseudoRapidity)+VP1Msg::str(",")+VP1Msg::str(VP1LinAlgUtils::phiFromXY(mom.x(), mom.y() ))+VP1Msg::str(")"); + } + } + + unsigned int row=0; + foreach(QString str, text){ + QByteArray array = str.toLatin1(); + labelText->string.set1Value(row++,array.data()); + } + + //Position + float labelTrackOffset = theclass->common()->controller()->trackLabelTrkOffset(); + unsigned int point=(points->size()-1)*labelTrackOffset; + Amg::Vector3D labelPos = (*points)[point] ; + +// if (labels&TrackSystemController::PosEndOfTrack) +// labelPos= points->back(); +// else if (labels&TrackSystemController::PosBeginOfTrack) +// labelPos= points->front (); +// else if (labels&TrackSystemController::PosMidOfTrack) +// labelPos= (*points)[points->size()/2]; + + SoTranslation *labelTranslate = new SoTranslation; + float offScale=10.0; + int xOffset = theclass->common()->controller()->labelXOffset() ; + int yOffset = theclass->common()->controller()->labelYOffset() ; + int zOffset = theclass->common()->controller()->labelZOffset() ; + labelTranslate->translation.setValue(labelPos.x()+(xOffset*offScale),labelPos.y()+(yOffset*offScale),labelPos.z()+(zOffset*offScale)); + + SoMaterial *sMat = new SoMaterial(); + SoMFColor sColor; + sColor.setValue(SbColor(0, 0, 1)); + sMat->diffuseColor = sColor; + + label_sep->addChild(labelTranslate); + label_sep->addChild(labelText); + } + + //Attach if visible: + if (theclass->m_visible) + attach3DObjects(); +} + +//____________________________________________________________________ +void TrackHandleBase::Imp::materialChanged() +{ + theclass->currentMaterialChanged(); + std::map<std::pair<int,double>,AssocObjAttachmentHandle *>::iterator it,itE(attachmentHandles.end()); + for (it = attachmentHandles.begin();it!=itE;++it) + it->second->trackMaterialChanged(); +} + +//____________________________________________________________________ +double TrackHandleBase::Imp::dist(const SbVec3f& p1,const SbVec3f& p2)//Fixme: to linalgs.. +{ + float x1,x2,y1,y2,z1,z2; + p1.getValue(x1,y1,z1); + p2.getValue(x2,y2,z2); + return sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)+(z2-z1)*(z2-z1)); +} + +//____________________________________________________________________ +void TrackHandleBase::Imp::convertLineSetToCylinders(SoLineSet*line,SoSeparator*sep,const double& cylradius) +{ + //fixme: belongs in VP1Utils + SoVertexProperty *vertices = static_cast<SoVertexProperty *>(line->vertexProperty.getValue()); + if (!vertices) + return; + int ivert(0); + SbMatrix lastTransf; + lastTransf.makeIdentity(); + + for (int iline=0;iline<line->numVertices.getNum();++iline) { + int nvert=line->numVertices[iline]; + if (nvert<2) { + ivert += nvert; + continue; + } + for (int jvert= ivert; jvert<ivert+nvert-1;++jvert) { + SbVec3f p1 = vertices->vertex[jvert].getValue(); + SbVec3f p2 = vertices->vertex[jvert+1].getValue(); + SoCylinder * cyl = new SoCylinder; + cyl->radius = cylradius; + const double l(dist(p1,p2)); + cyl->height = l; + //First translate (0,l/2,0), then rotate (0,1,0) into (p2-p1), then translate p1.: + SbMatrix m; + m.setTranslate(SbVec3f(0,0.5*l,0)); + SbVec3f v(p2); v -= p1; + SbRotation rot(SbVec3f(0,1,0),v); + SbMatrix m2; m2.setRotate(rot); + m.multRight(m2); + SbMatrix m3; + m3.setTranslate(p1); + m.multRight(m3); + //m is the transform we need in front of our cylinder. However, we need to first add the inverse of all previous transforms. + SbMatrix mat(m); + mat.multRight(lastTransf.inverse()); + SoMatrixTransform * mt = new SoMatrixTransform; + mt->matrix.setValue(mat); + sep->addChild(mt); + sep->addChild(cyl); + lastTransf = m; + } + ivert += nvert; + } +} + +//____________________________________________________________________ +void TrackHandleBase::Imp::attach3DObjects() +{ + // std::cout<<"TrackHandleBase::Imp::attach3DObjects() - 1"<<std::endl; + + if (!theclass->m_currentmaterial) { + theclass->m_currentmaterial = determineMaterial(); + theclass->m_currentmaterial->ref(); + materialChanged(); + } + if (line && theclass->m_collhandle->sephelper()) { + // std::cout<<"TrackHandleBase::Imp::attach3DObjects() - 2"<<std::endl; + theclass->m_collhandle->sephelper()->addNodeUnderMaterial(line,theclass->m_currentmaterial); + double tube_r(theclass->m_collhandle->trackTubeRadius()); + if (tube_r) { + if (extraRepresentation) { + extraRepresentation->removeAllChildren(); + } else { + extraRepresentation = new SoSeparator; + extraRepresentation->ref(); + theclass->common()->registerTrack(extraRepresentation,theclass); + } + convertLineSetToCylinders(line,extraRepresentation,tube_r); + if (!extraRepAttached) { + theclass->m_collhandle->sephelper()->addNodeUnderMaterial(extraRepresentation,theclass->m_currentmaterial); + extraRepAttached=true; + } + } + } + if (label_sep && theclass->common()->textSep() && theclass->common()->controller()->doTrackLabels()) + theclass->common()->textSep()->addChild(label_sep); + + if (extrapSurfaces_sep) theclass->m_collhandle->sephelper()->addNodeUnderMaterial(extrapSurfaces_sep,theclass->m_currentmaterial); +} + +//____________________________________________________________________ +void TrackHandleBase::Imp::detach3DObjects() +{ + if (!theclass->m_currentmaterial) + return;//Can never have been attached! + if (line && theclass->m_collhandle->sephelper()) { + theclass->m_collhandle->sephelper()->removeNodeUnderMaterial(line,theclass->m_currentmaterial); + if (extraRepresentation&&extraRepAttached) { + theclass->m_collhandle->sephelper()->removeNodeUnderMaterial(extraRepresentation,theclass->m_currentmaterial); + extraRepAttached=false; + } + } + if (label_sep && theclass->common()->textSep()) + theclass->common()->textSep()->removeChild(label_sep); + + if (extrapSurfaces_sep) + theclass->m_collhandle->sephelper()->removeNodeUnderMaterial(extrapSurfaces_sep,theclass->m_currentmaterial); +} + +//____________________________________________________________________ +void TrackHandleBase::updateMaterial() +{ + //We need to change the current material. This means we need to + //clear the cache. Only if we are visible do we need to do a + //detach->clear material->attach cycle to trigger attachment under new material. + + if (!m_currentmaterial) + return;//We have no material cached and is thus not attached either. + if (m_visible) { + //See if the material changed. If it did, detach, update the material, attach again. + SoMaterial * newmat = m_d->determineMaterial(); + newmat->ref(); + if (newmat!=m_currentmaterial) { + m_d->detach3DObjects(); + m_currentmaterial->unref(); + m_currentmaterial = newmat; + m_d->attach3DObjects(); + m_d->materialChanged(); + } else { + newmat->unref(); + } + } else { + //Just clear material. + m_currentmaterial->unref(); + m_currentmaterial = 0; + m_d->materialChanged(); + } +} + +//____________________________________________________________________ +void TrackHandleBase::Imp::ensureInitPointsRaw() +{ + theclass->collHandle()->systemBase()->message("ensureInitPointsRaw start" ); + + if (points_raw) + return; + points_raw = new std::vector<Amg::Vector3D >; + + ////////////////////////////////////////////////////////////// + // Get information about this path // + ////////////////////////////////////////////////////////////// + + ensureLoadPathInfo(); + + if (pathInfo_TrkTrack) { + const VP1TrackSanity * sanity = theclass->common()->trackSanityHelper(); + Amg::Vector3D * firstmomentum(0); + //Amg::Vector3D vect3d{0.,0.,0.}; + if (pathInfo_TrkTrack->trackParameters()) + points_raw->reserve(pathInfo_TrkTrack->trackParameters()->size()); + bool unsafeparts(false); + DataVector<const Trk::TrackStateOnSurface>::const_iterator tsos_iter = pathInfo_TrkTrack->trackStateOnSurfaces()->begin(); + DataVector<const Trk::TrackStateOnSurface>::const_iterator tsos_end = pathInfo_TrkTrack->trackStateOnSurfaces()->end(); + const Trk::TrackParameters* trackParam; + for (; tsos_iter != tsos_end; ++tsos_iter) { + if (!sanity->isSafe(*tsos_iter)) { + unsafeparts = true; + continue; + } + if (theclass->collHandle()->ignoreMEOTinProp() && (*tsos_iter)->materialEffectsOnTrack()) + continue; + trackParam = (*tsos_iter)->trackParameters(); + if (trackParam) { + if (!sanity->isSafe(trackParam)) { + unsafeparts = true; + continue; + } + trackParam->position();//test + points_raw->push_back( trackParam->position() ); + if (!firstmomentum) { + //vect3d = + firstmomentum = new Amg::Vector3D(trackParam->momentum()); + } + } + } + if (unsafeparts) + theclass->collHandle()->systemBase()->message("WARNING: Ignored unsafe parts of track!"); + if (points_raw->size()==1) { + if (!firstmomentum) { + theclass->collHandle()->systemBase()->message(" TrackHandleBase ERROR: Unexpected null firstmomentum!"); + firstmomentum = new Amg::Vector3D(0,0,0); + } + if (firstmomentum->mag()==0.0) { + theclass->collHandle()->systemBase()->message("TrackHandleBase ERROR: Only point on track had zero momentum. Can't add second point."); + points_raw->clear(); + } else { + VP1Msg::messageVerbose("TrackHandleBase: Adding second point in direction of initial momentum."); + points_raw->push_back(points_raw->front()+(*firstmomentum)*(1000.0/firstmomentum->mag())); + } + } else if (points_raw->empty()) { + theclass->collHandle()->systemBase()->message("TrackHandleBase ERROR: No points on track."); + } + + //std:: cout << "firstmomentum: " << firstmomentum << std::endl; + delete firstmomentum; + firstmomentum = 0; + return; + } + if (pathInfo_Points) + { + std::copy(pathInfo_Points->begin(), pathInfo_Points->end(), std::back_inserter(*points_raw)); + } + if (points_raw->size()<2) { + theclass->collHandle()->systemBase()->message("TrackHandleBase ERROR: Less than two points on track provided."); + points_raw->clear(); + } else { + VP1Msg::messageVerbose( "TrackHandleBase: Created raw data " + + QString::number(points_raw->size()) + + " points for track."); + } +} + +//____________________________________________________________________ +void TrackHandleBase::Imp::ensureInitPointsPropagated() +{ + if (points_propagated) + return; + + ensureLoadPathInfo(); + + if (pathInfo_TrkTrack) { + points_propagated = new std::vector<Amg::Vector3D >(); + bool ok (false); + if (theclass->hasCharge()&&theclass->charge()!=0.0) + ok = theclass->common()->trackPropagationHelper()->makePointsCharged(*points_propagated,pathInfo_TrkTrack, + theclass->collHandle()->propagator(), + theclass->extrapolationParticleHypothesis(), + !theclass->collHandle()->ignoreMEOTinProp(), + theclass->collHandle()->extendTracks() ? theclass->common()->controller()->extrapolateToThisVolume() : 0 ); + else + ok = theclass->common()->trackPropagationHelper()->makePointsNeutral(*points_propagated,pathInfo_TrkTrack); + + if (!ok) { + delete points_propagated; + ensureInitPointsRaw(); + points_propagated = points_raw; + } + } else { + //We just use the raw points: + ensureInitPointsRaw(); + points_propagated = points_raw; + } +} + +//____________________________________________________________________ +void TrackHandleBase::Imp::ensureInitPointsProjections_InDet( bool raw ) +{ + if (raw?points_raw_id_projections:points_propagated_id_projections) + return; + + raw ? ensureInitPointsRaw() : ensureInitPointsPropagated(); + + //First check if we use same points for raw/propagated modes: + if (points_propagated==points_raw) { + if (raw) { + if (points_propagated_id_projections) { + points_raw_id_projections = points_propagated_id_projections; + return; + } + } else { + if (points_raw_id_projections) { + points_propagated_id_projections = points_raw_id_projections; + return; + } + } + } + + //Time for the hard work: + std::vector<Amg::Vector3D > * points=0; + Amg::SetVectorVector3D* projections=0; + if (raw) { + points_raw_id_projections = new Amg::SetVectorVector3D; + points = points_raw; + projections = points_raw_id_projections; + } else { + points_propagated_id_projections = new Amg::SetVectorVector3D; + points = points_propagated; + projections = points_propagated_id_projections; + } + + if ( !points || points->empty() || points->size()<2 ) { + projections->clear(); + projections->insert(std::vector<Amg::Vector3D >());//error signature + return; + } + + bool oneok(false); + // if (theclass->common()->indetProjHelper_Pixel()) { + // theclass->common()->indetProjHelper_Pixel()->projectPath(*points,*projections); + // oneok = true; + // } + // if (theclass->common()->indetProjHelper_SCT()) { + // theclass->common()->indetProjHelper_SCT()->projectPath(*points,*projections); + // oneok = true; + // } + // if (theclass->common()->indetProjHelper_TRT()) { + // theclass->common()->indetProjHelper_TRT()->projectPath(*points,*projections); + // oneok = true; + // } + + if (!oneok) { + projections->clear(); + projections->insert(std::vector<Amg::Vector3D >());//error signature + } +} + +//____________________________________________________________________ +SoMaterial * TrackHandleBase::Imp::determineMaterial() +{ + // theclass->collHandle()->systemBase()->message("determineMaterial with material = "+QString::number(static_cast<unsigned int>(theclass->collHandle()->colourBy()))); //too verbose. EJWM. + + int pdgcode(0); + switch(theclass->collHandle()->colourBy()) { + case TrackCollHandleBase::COLOUR_BYPID: + pdgcode = theclass->pdgCode(); + return theclass->common()->controller()->getMaterialForPDGCode(pdgcode == SimBarCode::unknownPDG ? 0 : pdgcode); + case TrackCollHandleBase::COLOUR_RANDOM: + if (!randommaterial) { + randommaterial = new SoMaterial; + randommaterial->ref(); + theclass->rerandomiseRandomMaterial(); + } + return randommaterial; + case TrackCollHandleBase::COLOUR_CHARGE: + return theclass->common()->controller()->getMaterialForCharge(theclass->hasCharge()?theclass->charge():0.0); + case TrackCollHandleBase::COLOUR_MOMENTUM: + return theclass->common()->controller()->getMaterialForMomentum(theclass->momentum().mag()); + case TrackCollHandleBase::COLOUR_DISTANCE: + { + // AscObjSelectionManager* selManager= theclass->common()->ascObjSelectionManager(); + // TrackHandleBase* handle = 0; + // if ( selManager ) { + // QList<AssociatedObjectHandleBase*> selection = selManager->currentSelection(); + // if (!selection.empty()) handle = selection[0]->trackHandle(); // Take first at the moment, but should loop and colour by all. FIXME! + // else theclass->collHandle()->systemBase()->message("Empty selection!"); + // } else { + // theclass->collHandle()->systemBase()->message("No AscObjSelectionManager"); + // } + + TrackHandleBase* handle = theclass->common()->lastSelectedTrackHandle(); + if (handle==0) { + //theclass->collHandle()->systemBase()->message("No previously selected track."); + return theclass->collHandle()->material(); // use collection colouring + } + + Amg::Vector3D selectedTrackMom = handle->momentum(); + Amg::Vector3D thisTrackMom = theclass->momentum(); + + float phiDistance = sqrt ( pow( selectedTrackMom.phi() - thisTrackMom.phi(),2) ); + float etaDistance = sqrt ( pow( selectedTrackMom.eta() - thisTrackMom.eta(),2) ); + + //theclass->collHandle()->systemBase()->message("Distance "+QString::number(distance)); + float colScale=std::max(0.0, std::min(1.0,phiDistance/(M_PI))); // means that min scale is reached 0.5 of total possible distance away. + float brightness= std::max(0.2, 1.0-(etaDistance/5.0) ); + //theclass->collHandle()->systemBase()->message("Distance "+QString::number(distance)+"\t brightness "+QString::number(brightness)); + + SoMaterial* mat = new SoMaterial; + mat->ref(); + + // get colour of collection. + const SbColor& col=theclass->collHandle()->material()->diffuseColor[0]; + float r,g,b; + col.getValue(r,g,b); + + double r3,g3,b3; + if (colScale>0.01) { + + //Use QColor to get HSL + QColor tempCol = QColor::fromRgbF( r,g,b ); + double h,s,v; + tempCol.getHsvF(&h,&s,&v); + + //get opposite hue for farthest away points. + h+=0.5; + if (h>1.0) h-=1.0; + tempCol.setHsvF(h,s,v); + double r2,g2,b2; + tempCol.getRgbF(&r2,&g2,&b2); + + // closest will have collection colour - far away will have opposite colour + r3 = r+(r2-r)*colScale; + b3 = b+(b2-b)*colScale; + g3 = g+(g2-g)*colScale; + + } else { + // too close - take default values + r3=r;b3=b;g3=g; + } + + VP1MaterialButton::setMaterialParameters(mat,r3*brightness,g3*brightness,b3*brightness, + theclass->collHandle()->collMaterialBrightness(), + theclass->collHandle()->collMaterialTransparency()); + + return mat; + } + case TrackCollHandleBase::COLOUR_VERTEX: + { + SoMaterial* mat = theclass->common()->system()->materialFromVertex(theclass); + if (mat) + return mat; + else + return theclass->collHandle()->material(); + } + case TrackCollHandleBase::COLOUR_PERCOLLECTION: + default: + return theclass->collHandle()->material(); + } +} + +//____________________________________________________________________ +void TrackHandleBase::rerandomiseRandomMaterial() +{ + if ( !m_d->randommaterial )//We will anyway rerandomize it when we need it + return; + + double r2 = 0.3*0.3; + unsigned i(0); + double r,g,b; + bool ok; + while (true) { + r = (rand() / static_cast<double>(RAND_MAX)); + g = (rand() / static_cast<double>(RAND_MAX)); + b = (rand() / static_cast<double>(RAND_MAX)); + ok = true; + //For now we make sure that we avoid black and red. This should be updated from bgd and highlight col automatically! (fixme). + // -> and we should probably also make sure that tracks close in (eta,phi) are well separated in colour-space. + if ( (r-1.0)*(r-1.0)+g*g+b*b < r2*0.5 )//avoid red (distance) + ok = false; + else if ( r*r/(r*r+g*g+b*b) > 0.8 )//avoid red (angle) + ok = false; + else if ( r*r+g*g+b*b < r2*2.0 )//avoid black + ok = false; + if (ok) + break; + ++i; + if (i>50 ) { + r2 *= 0.99;//To avoid problem in case we add too many forbidden spheres. + if (i>1000) { + //Just a safety + m_d->theclass->collHandle()->systemBase()->message("TrackHandleBase::rerandomiseRandomMaterial Warning: Random colour could" + " not be selected such as to satisfy all separation criterias"); + break; + } + } + } + VP1MaterialButton::setMaterialParameters(m_d->randommaterial,r,g,b, + collHandle()->collMaterialBrightness(), + collHandle()->collMaterialTransparency()); +} + +//____________________________________________________________________ +void TrackHandleBase::updateRandomColourTransparencyAndBrightness() +{ + if ( !m_d->randommaterial )//We will anyway set up correctly when needed. + return; + float r,g,b; + m_d->randommaterial->diffuseColor[0].getValue(r,g,b); + VP1MaterialButton::setMaterialParameters(m_d->randommaterial,r,g,b, + collHandle()->collMaterialBrightness(), + collHandle()->collMaterialTransparency()); +} + + +//____________________________________________________________________ +void TrackHandleBase::registerAssocObject(AssociatedObjectHandleBase* ao) +{ + if (VP1Msg::verbose()) { + if (m_d->associatedObjects.contains(ao)) { + m_d->theclass->collHandle()->systemBase()->message("TrackHandleBase::registerAssocObject ERROR: object already registered!"); + return; + } + } + //Assume ownership of this associated object: + if (!ao) { + m_d->theclass->collHandle()->systemBase()->message("TrackHandleBase::registerAssocObject ERROR: object is null!"); + return; + } + + m_d->associatedObjects << ao; +} + + +//____________________________________________________________________ +AssocObjAttachmentHandle * TrackHandleBase::getAttachmentHandle(int regionIndex, const double&crossoverval) +{ + std::map<std::pair<int,double>,AssocObjAttachmentHandle *>::iterator + it = m_d->attachmentHandles.find(std::make_pair(regionIndex,crossoverval)); + if (it!=m_d->attachmentHandles.end()) + return it->second; + AssocObjAttachmentHandle *attachHandle + = new AssocObjAttachmentHandle(common()->trackLODManager()->getLODHandle(regionIndex,crossoverval),this); + m_d->attachmentHandles[std::make_pair(regionIndex,crossoverval)] = attachHandle; + return attachHandle; +} + +//____________________________________________________________________ +double TrackHandleBase::calculateCharge() const +{ + //look up from pdgCode();//fixme: 0 or -999 means unknown?? + int pdg = pdgCode(); + if (pdg) { + bool ok; + double c = VP1ParticleData::particleCharge(pdg,ok); + if (ok) { + // if (VP1Msg::verbose()) + // VP1Msg::messageVerbose("TrackHandleBase: Determined charge from pdg code "+VP1Msg::str(pdg)+": "+VP1Msg::str(c)); + return c; + } + } + + //Attempt to look at the first trackparameter. + const Trk::Track * trk = provide_pathInfoTrkTrack(); + if (trk&&!trk->trackParameters()->empty()) { + double c = (*(trk->trackParameters()->begin()))->charge(); + // if (VP1Msg::verbose()) + // VP1Msg::messageVerbose("TrackHandleBase: Determined charge from first track parameter: "+VP1Msg::str(c)); + return c; + } + if (VP1Msg::verbose()) + VP1Msg::messageVerbose("Failed to determine charge."); + + return unknown(); +} + +//____________________________________________________________________ +double TrackHandleBase::charge() const +{ + if (m_d->chargeinit) + return m_d->charge; + m_d->chargeinit = true; + m_d->charge = calculateCharge(); + return m_d->charge; +} + +//____________________________________________________________________ +double TrackHandleBase::mass() const +{ + if (m_d->massinit) + return m_d->mass; + m_d->massinit = true; + int pdg = pdgCode(); + if (pdg) { + bool ok; + double m = VP1ParticleData::particleMass(pdg,ok); + if (ok) + m_d->mass = m; + } + return m_d->mass; +} + +//____________________________________________________________________ +Trk::ParticleHypothesis TrackHandleBase::extrapolationParticleHypothesis() const +{ + switch(abs(pdgCode())) { + case 211: return Trk::pion; + case 2212: return Trk::proton; + case 11: return Trk::electron; + case 13: return Trk::muon; + case 321://k+ + case 323://k*+ + return Trk::kaon; + case 0: + default: + return ((hasCharge()&&charge()==0.0) ? Trk::nonInteracting : Trk::muon); + } +} + +//____________________________________________________________________ +QStringList TrackHandleBase::baseInfo() const +{ + QStringList l; + Amg::Vector3D mom = momentum(); + mom /= CLHEP::GeV; + if (mom.mag2()==0.0) { + l << "Momentum : 0 (undefined)"; + } else { + l << "Momentum [GeV]: "+VP1Msg::str(mom); + l << "|Pt|/|P| [GeV]: "+VP1Msg::str(mom.perp())+" / " + VP1Msg::str(mom.mag()); + l << VP1Msg::str("(")+QChar(0x03B7)+","+QChar(0x03D5)+VP1Msg::str(")=(") + +VP1Msg::str(mom.eta())+VP1Msg::str(",")+VP1Msg::str(VP1LinAlgUtils::phiFromXY(mom.x(), mom.y() ))+VP1Msg::str(")"); + + l << "Eta: "+VP1Msg::str(mom.eta()); + l << "Phi: "+VP1Msg::str(VP1LinAlgUtils::phiFromXY(mom.x(), mom.y() )); + } + l<<"Hit summary: SCT["+QString::number(getNSCTHits())+"]."; + + return l; + /** coverity 17186: this code is unreachable + int pdg = pdgCode(); + if (pdg) { + bool ok; + QString name = VP1ParticleData::particleName(pdg,ok); + if (ok) + l << "pdg: "+QString::number(pdg)+" ["+name+"]"; + else + l << "pdg: "+QString::number(pdg); + } + + return l; + **/ +} + +//____________________________________________________________________ +const Amg::Vector3D * TrackHandleBase::startPoint() const +{ + m_d->ensureLoadPathInfo(); + if (m_d->pathInfo_TrkTrack) { + DataVector<const Trk::TrackStateOnSurface>::const_iterator tsos_iter = m_d->pathInfo_TrkTrack->trackStateOnSurfaces()->begin(); + DataVector<const Trk::TrackStateOnSurface>::const_iterator tsos_end = m_d->pathInfo_TrkTrack->trackStateOnSurfaces()->end(); + for (; tsos_iter != tsos_end; ++tsos_iter) { + if (common()->trackSanityHelper()->isSafe(*tsos_iter)) { + const Trk::TrackParameters* trackParam = (*tsos_iter)->trackParameters(); + if (common()->trackSanityHelper()->isSafe(trackParam)) + return &(trackParam->position()); + } + } + } else if (m_d->pathInfo_Points&&!m_d->pathInfo_Points->empty()) { + return &(m_d->pathInfo_Points->at(0)); + } + return 0; +} + +//____________________________________________________________________ +const Amg::Vector3D * TrackHandleBase::endPoint() const +{ + m_d->ensureLoadPathInfo(); + if (m_d->pathInfo_TrkTrack) { + DataVector<const Trk::TrackStateOnSurface>::const_reverse_iterator tsos_iter = m_d->pathInfo_TrkTrack->trackStateOnSurfaces()->rend(); + DataVector<const Trk::TrackStateOnSurface>::const_reverse_iterator tsos_end = m_d->pathInfo_TrkTrack->trackStateOnSurfaces()->rbegin(); + for (; tsos_iter != tsos_end; ++tsos_iter) { + if (common()->trackSanityHelper()->isSafe(*tsos_iter)) { + const Trk::TrackParameters* trackParam = (*tsos_iter)->trackParameters(); + if (common()->trackSanityHelper()->isSafe(trackParam)) + { + // std::cout << "endPoint returning (1): " << trackParam->position() << std::endl; + return &(trackParam->position()); + } + } + } + } else if (m_d->pathInfo_Points&&!m_d->pathInfo_Points->empty()) { + // std::cout << "endPoint returning (2): " << m_d->pathInfo_Points->back() << std::endl; + return &(m_d->pathInfo_Points->back()); + } + // std::cout << "endPoint returning (3) (null position)" << std::endl; + return 0; +} + +//____________________________________________________________________ +QList<AssociatedObjectHandleBase*> TrackHandleBase::getAllAscObjHandles() const +{ + return m_d->associatedObjects; +} + +std::vector< Amg::Vector3D > * TrackHandleBase::hackGetPointsPropagated() +{ + m_d->ensureInitPointsPropagated(); + return m_d->points_propagated; +} + +//____________________________________________________________________ +class AssocObjAttachmentHandle::Imp { +public: + Imp(TrackLODHandle *tlh,TrackHandleBase * th) + : trackhandle(th), + trackmat(0), + lodHandle(tlh), + septrack_simple(0), + septrack_detailed(0), + pickStyleChildIdx(-1), + attached(false) {} + TrackHandleBase * trackhandle; + SoMaterial* trackmat; + TrackLODHandle *lodHandle; + SoSeparator * septrack_simple; + SoSeparator * septrack_detailed; + void ensureInit(); + static SoPickStyle * pickStyle; + int pickStyleChildIdx; + bool attached; + void ensureAttached() + { + if (attached) + return; + attached=true; + if (!septrack_detailed) + return;//We attach in ensureInit in this case! + lodHandle->addNodes(septrack_simple,septrack_detailed); + } + void ensureDetached() + { + if (!attached) + return; + attached=false; + if (!septrack_detailed) + return; + lodHandle->removeNodes(septrack_simple,septrack_detailed); + } + static SoMaterial * dummymaterial; +}; +SoPickStyle * AssocObjAttachmentHandle::Imp::pickStyle = 0; +SoMaterial * AssocObjAttachmentHandle::Imp::dummymaterial = 0; + +//____________________________________________________________________ +void AssocObjAttachmentHandle::trackVisibilityChanged() +{ + bool b = m_d->trackhandle->visible(); + if (b&&!m_d->trackhandle->currentMaterial()) + VP1Msg::message("ERROR: track is visible but has not current material!!"); + if (b) + m_d->ensureAttached(); + else + m_d->ensureDetached(); +} + +//____________________________________________________________________ +AssocObjAttachmentHandle::AssocObjAttachmentHandle(TrackLODHandle * tlh,TrackHandleBase * th) + : m_d ( new Imp(tlh,th) ) +{ + if (!tlh) + VP1Msg::message("AssocObjAttachmentHandle ERROR: constructed with null LOD handle!"); + if (!Imp::dummymaterial) { + Imp::dummymaterial = new SoMaterial; + Imp::dummymaterial->ref(); + } +} + +//____________________________________________________________________ +AssocObjAttachmentHandle::~AssocObjAttachmentHandle() +{ + if (VP1Msg::verbose()) { + if ((m_d->septrack_detailed && m_d->pickStyleChildIdx != m_d->septrack_detailed->findChild(Imp::pickStyle)) + ||(m_d->septrack_simple&&m_d->pickStyleChildIdx != m_d->septrack_simple->findChild(Imp::pickStyle))) { + VP1Msg::message("ERROR: AssocObjAttachmentHandle::setPickableStateOfNodes detected wrong pickStyleChildIdx"); + return; + } + } + + if (Imp::pickStyle) { + Imp::pickStyle->unref(); + if ( Imp::pickStyle->getRefCount()==1 ) { + Imp::pickStyle->unref(); + Imp::pickStyle = 0; + } + } + + if (m_d->septrack_simple) + m_d->septrack_simple->unref(); + if (m_d->septrack_detailed) + m_d->septrack_detailed->unref(); + if (m_d->trackmat) + m_d->trackmat->unref(); + delete m_d; +} + +//____________________________________________________________________ +void AssocObjAttachmentHandle::trackMaterialChanged() +{ + SoMaterial * m = m_d->trackhandle->currentMaterial(); + if (m_d->trackmat==m) + return; + if (!m) { + if (m_d->trackhandle->visible()) + VP1Msg::message("ERROR: track is visible but has no current material!!"); + m = Imp::dummymaterial; + } + m->ref(); + if (m_d->trackmat) { + if ( m_d->septrack_simple && m_d->septrack_simple->findChild(m_d->trackmat) > -1 ) + m_d->septrack_simple->replaceChild(m_d->trackmat,m); + if ( m_d->septrack_detailed && m_d->septrack_detailed->findChild(m_d->trackmat) > -1 ) + m_d->septrack_detailed->replaceChild(m_d->trackmat,m); + m_d->trackmat->unref(); + } + m_d->trackmat = m; +} + +//____________________________________________________________________ +void AssocObjAttachmentHandle::Imp::ensureInit() +{ + if (septrack_simple) + return; + septrack_simple = new SoSeparator; + septrack_detailed = new SoSeparator; + septrack_simple->ref(); + septrack_detailed->ref(); + + if (!pickStyle) { + pickStyle = new SoPickStyle; + pickStyle->style=SoPickStyle::UNPICKABLE; + pickStyle->ref(); + } + pickStyle->ref(); + if (attached) { + attached = false; + ensureAttached(); + } +} + +//____________________________________________________________________ +void AssocObjAttachmentHandle::attachNodes( SoNode*simple, SoNode*detailed, bool unpickable ) +{ + if (!m_d->trackhandle->visible()) + return; + m_d->ensureInit(); + if (!m_d->trackmat) { + SoMaterial * m = m_d->trackhandle->currentMaterial(); + if (!m) + m = Imp::dummymaterial;//For now we attach a dummy material. + m_d->trackmat=m; + m->ref(); + m_d->septrack_simple->addChild(m); + m_d->septrack_detailed->addChild(m); + } + + if (VP1Msg::verbose()) { + if (m_d->pickStyleChildIdx != m_d->septrack_detailed->findChild(Imp::pickStyle) + ||m_d->pickStyleChildIdx != m_d->septrack_simple->findChild(Imp::pickStyle)) { + VP1Msg::message("ERROR: AssocObjAttachmentHandle::attachNodes detected wrong pickStyleChildIdx"); + return; + } + if (m_d->septrack_simple->findChild(simple)>-1||m_d->septrack_detailed->findChild(detailed)>-1) { + VP1Msg::message("ERROR: AssocObjAttachmentHandle::attachNodes Already attached!"); + return; + } + } + if (unpickable) { + if (m_d->pickStyleChildIdx==-1) { + m_d->pickStyleChildIdx = m_d->septrack_simple->getNumChildren(); + m_d->septrack_simple->addChild(Imp::pickStyle); + m_d->septrack_detailed->addChild(Imp::pickStyle); + } + m_d->septrack_simple->addChild(simple); + m_d->septrack_detailed->addChild(detailed); + } else { + if (m_d->pickStyleChildIdx>-1) { + m_d->septrack_simple->insertChild(simple,m_d->pickStyleChildIdx); + m_d->septrack_detailed->insertChild(detailed,m_d->pickStyleChildIdx); + ++(m_d->pickStyleChildIdx); + } else { + m_d->septrack_simple->addChild(simple); + m_d->septrack_detailed->addChild(detailed); + } + } + + //Should we update the overall attachment status?: + if (m_d->trackhandle->visible() && m_d->septrack_simple->getNumChildren() == 2 + (m_d->pickStyleChildIdx==-1?0:1)) { + m_d->ensureAttached(); + } +} + +//____________________________________________________________________ +void AssocObjAttachmentHandle::setPickableStateOfNodes( SoNode*simple, SoNode*detailed, bool unpickable ) +{ + if (VP1Msg::verbose()) { + VP1Msg::messageVerbose("AssocObjAttachmentHandle::setPickableStateOfNodes called with unpickable = " + +QString(unpickable?"true":"false")); + if (!simple||!detailed) { + VP1Msg::messageVerbose("AssocObjAttachmentHandle::setPickableStateOfNodes ERROR: Called with null pointers!"); + return; + } + } + m_d->ensureInit(); + int isimple = m_d->septrack_simple->findChild(simple); + if (VP1Msg::verbose()) { + if (m_d->septrack_simple->getNumChildren()!=m_d->septrack_detailed->getNumChildren()) { + VP1Msg::message("ERROR: AssocObjAttachmentHandle::setPickableStateOfNodes septrack_simple->getNumChildren()" + "!=m_d->septrack_detailed->getNumChildren()."); + return; + } + int idetailed = m_d->septrack_detailed->findChild(detailed); + if (idetailed!=isimple) { + VP1Msg::message("ERROR: AssocObjAttachmentHandle::setPickableStateOfNodes" + " called with simple and detailed nodes that are not at same child idx!"); + return; + } + if (m_d->pickStyleChildIdx != m_d->septrack_detailed->findChild(Imp::pickStyle) + ||m_d->pickStyleChildIdx != m_d->septrack_simple->findChild(Imp::pickStyle)) { + VP1Msg::message("ERROR: AssocObjAttachmentHandle::setPickableStateOfNodes detected wrong pickStyleChildIdx"); + return; + } + } + if (isimple<0) { + VP1Msg::messageDebug( "WARNING: AssocObjAttachmentHandle::setPickableStateOfNodes" + " called with nodes that are not currently children. Calling attachNodes(..)." ); + attachNodes(simple, detailed, unpickable); + return; + } + if (unpickable == (m_d->pickStyleChildIdx>-1&&isimple>m_d->pickStyleChildIdx)) { + VP1Msg::messageDebug("WARNING: AssocObjAttachmentHandle::setPickableStateOfNodes" + " already in correct state."); + return; + } + + simple->ref();//To avoid deletion upon removeChild calls. + detailed->ref(); + if (unpickable) { + m_d->septrack_simple->removeChild(simple); + m_d->septrack_detailed->removeChild(detailed); + if (m_d->pickStyleChildIdx==-1) { + m_d->pickStyleChildIdx = m_d->septrack_simple->getNumChildren(); + m_d->septrack_simple->addChild(Imp::pickStyle); + m_d->septrack_detailed->addChild(Imp::pickStyle); + } else { + --(m_d->pickStyleChildIdx); + } + m_d->septrack_simple->addChild(simple); + m_d->septrack_detailed->addChild(detailed); + } else { + if (m_d->pickStyleChildIdx==-1) { + VP1Msg::message("ERROR: AssocObjAttachmentHandle::setPickableStateOfNodes Inconsistent logic"); + simple->unref(); + detailed->unref(); + return; + } + if (m_d->pickStyleChildIdx==isimple-1&&isimple==m_d->septrack_simple->getNumChildren()-1) { + //pickStyle object no longer needed: + VP1Msg::messageVerbose("AssocObjAttachmentHandle::setPickableStateOfNodes detaching pickstyle"); + m_d->septrack_simple->removeChild(Imp::pickStyle); + m_d->septrack_detailed->removeChild(Imp::pickStyle); + m_d->pickStyleChildIdx = -1; + } else { + //Move children left of the pickstyle object. + m_d->septrack_simple->removeChild(simple); + m_d->septrack_detailed->removeChild(detailed); + m_d->septrack_simple->insertChild(simple,m_d->pickStyleChildIdx); + m_d->septrack_detailed->insertChild(detailed,m_d->pickStyleChildIdx); + ++(m_d->pickStyleChildIdx); + } + } + simple->unref(); + detailed->unref(); +} + +//____________________________________________________________________ +void AssocObjAttachmentHandle::detachNodes( SoNode*simple, SoNode*detailed ) +{ + if (!m_d->trackmat) + return; + int isimple = m_d->septrack_simple->findChild(simple); + if (VP1Msg::verbose()) { + if (!m_d->septrack_simple) { + // VP1Msg::message("ERROR: AssocObjAttachmentHandle::detachNodes Not initialised previously!."); + m_d->ensureInit(); + } + if (!simple||!detailed) { + VP1Msg::messageVerbose("AssocObjAttachmentHandle::detach ERROR: Called with null pointers!"); + return; + } + if (m_d->septrack_simple->getNumChildren()!=m_d->septrack_detailed->getNumChildren()) { + VP1Msg::message("ERROR: AssocObjAttachmentHandle::detachNodes septrack_simple->getNumChildren()" + "!=m_d->septrack_detailed->getNumChildren()."); + return; + } + if (m_d->pickStyleChildIdx != m_d->septrack_detailed->findChild(Imp::pickStyle) + ||m_d->pickStyleChildIdx != m_d->septrack_simple->findChild(Imp::pickStyle)) { + VP1Msg::message("ERROR: AssocObjAttachmentHandle::detachNodes detected wrong pickStyleChildIdx"); + return; + } + if (isimple==-1) { + VP1Msg::message("ERROR: AssocObjAttachmentHandle::detachNodes Not previously attached!"); + return; + } + if (m_d->septrack_detailed->findChild(detailed)!=isimple) { + VP1Msg::message("ERROR: AssocObjAttachmentHandle::setPickableStateOfNodes" + " called with simple and detailed nodes that are not at same child idx!"); + return; + } + } + m_d->septrack_simple->removeChild(simple); + m_d->septrack_detailed->removeChild(detailed); + if ( m_d->pickStyleChildIdx!=-1 + && isimple>m_d->pickStyleChildIdx + && m_d->pickStyleChildIdx==m_d->septrack_simple->getNumChildren()-1 ) { + VP1Msg::messageVerbose("AssocObjAttachmentHandle::detachNodes detaching pickstyle"); + m_d->septrack_simple->removeChild(Imp::pickStyle); + m_d->septrack_detailed->removeChild(Imp::pickStyle); + m_d->pickStyleChildIdx = -1; + } + + //Should we update the overall attachment status?: + if (m_d->trackhandle->visible() && m_d->septrack_simple->getNumChildren() == 1 + (m_d->pickStyleChildIdx==-1?0:1)) + m_d->ensureDetached(); +} + +//____________________________________________________________________ +QList<AssociatedObjectHandleBase*> TrackHandleBase::getVisibleMeasurements() const +{ + QList<AssociatedObjectHandleBase*> l; + if (!m_d->tsos_ascobjs) return l; + std::vector<AscObj_TSOS*>::iterator + it(m_d->tsos_ascobjs->begin()), + itE(m_d->tsos_ascobjs->end()); + for (;it!=itE;++it) + if ((*it)->hasMeasurement()&&(*it)->visible()) + l << (*it); + return l; +} + +void TrackHandleBase::fillObjectBrowser( QList<QTreeWidgetItem *>& listOfItems) { + VP1Msg::messageVerbose("TrackHandleBase::fillObjectBrowser"); + + assert(m_d->m_objBrowseTree==0); + m_d->m_objBrowseTree = new QTreeWidgetItem(); + + QString direction = QString::fromUtf8("(\u03B7,\u03D5)=[") + QString::number(momentum().eta(),'f',2) + ","+QString::number(momentum().phi(),'f',2)+"], "; + QString l = direction + shortInfo(); + m_d->m_objBrowseTree->setText(0, type()+QString(QString::number(listOfItems.size())) ); + m_d->m_objBrowseTree->setText(1, l ); + + if (!visible()) { + m_d->m_objBrowseTree->setFlags(0); // not selectable, not enabled + } + listOfItems << browserTreeItem(); +} + +QTreeWidgetItem* TrackHandleBase::browserTreeItem() const {return m_d->m_objBrowseTree;} + +//____________________________________________________________________ +void TrackHandleBase::visibleStateChanged() +{ + if ( !browserTreeItem()) { + VP1Msg::messageVerbose("visibleStateChanged: No m_objBrowseTree!"); + return; + } + + if (!visible()) { + browserTreeItem()->setFlags(0); // not selectable, not enabled + } else { + browserTreeItem()->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); // selectable, enabled + } + QFont itemFont = browserTreeItem()->font(0); + itemFont.setStrikeOut(!visible()); + browserTreeItem()->setFont(0, itemFont); + browserTreeItem()->setFont(1, itemFont); +} diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackHandle_TrkTrack.cxx b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackHandle_TrkTrack.cxx new file mode 100644 index 000000000..dbcd53e65 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackHandle_TrkTrack.cxx @@ -0,0 +1,342 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class TrackHandle_TrkTrack // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: February 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12TrackSystems/TrackHandle_TrkTrack.h" +#include "VTI12TrackSystems/TrackSystemController.h" +#include "VTI12TrackSystems/TrackCollHandle_TrkTrack.h" +#include "VTI12TrackSystems/VP1TrackSanity.h" +#include "VTI12TrackSystems/TrkObjToString.h" +#include "VTI12Utils/VP1JobConfigInfo.h" +#include "TrkTrack/Track.h" +#include "TrkTrack/TrackStateOnSurface.h" +#include "TrkSurfaces/Surface.h" +#include "TrkMeasurementBase/MeasurementBase.h" +#include "TrkRIO_OnTrack/RIO_OnTrack.h" +#include "TrkCompetingRIOsOnTrack/CompetingRIOsOnTrack.h" +#include "VP1Base/VP1Msg.h"//fixme +#include "VTI12TrackSystems/VP1TrackSummary.h" +#include "VTI12TrackSystems/AscObj_TSOS.h" +#include "VTI12TrackSystems/TrkObjToString.h" +#include <Inventor/nodes/SoSeparator.h> +#include <Inventor/nodes/SoNode.h> + + +//____________________________________________________________________ +TrackHandle_TrkTrack::TrackHandle_TrkTrack(TrackCollHandleBase* ch, const Trk::Track* trk) + : TrackHandleBase(ch), + m_nhits_sct(0), m_hitInfoStatus(-1), m_trk(trk) +{ +} + +//____________________________________________________________________ +TrackHandle_TrkTrack::~TrackHandle_TrkTrack() +{ +} + +//____________________________________________________________________ +QStringList TrackHandle_TrkTrack::clicked() const +{ + // Object browser stuff + QTreeWidget* trkObjBrowser = common()->controller()->trackObjBrowser(); + if (trkObjBrowser){ + trkObjBrowser->setCurrentItem(browserTreeItem()); + trkObjBrowser->scrollToItem(browserTreeItem()); + } + QStringList l; + l << "Trk::Track"; + if (!m_trk) { + l << "ERROR: This TrackHandle_TrkTrack handle has a NULL track pointer!!"; + return l; + } + l << "Author info: " << " "+QString(m_trk->info().dumpInfo().c_str()); + + l << TrackHandleBase::baseInfo(); + if (m_trk->fitQuality()) + l << "Fit quality [Chi^2, nDoF] = ["+QString::number(m_trk->fitQuality()->chiSquared())+", "+QString::number(m_trk->fitQuality()->doubleNumberDoF())+"]. "; + if (common()->controller()->printVerboseInfoOnSingleSelection()) { + l << " ===== dump ====="; + std::ostringstream s; + s << *m_trk; + l << QString(s.str().c_str()).split('\n'); + } + return l; +} + +//____________________________________________________________________ +Amg::Vector3D TrackHandle_TrkTrack::momentum() const +{ + for (const Trk::TrackParameters* param : *m_trk->trackParameters()) { + if (!common()->trackSanityHelper()->isSafe(param)) + continue; + return param->momentum(); + } + return TrackHandleBase::momentum(); +} + +//____________________________________________________________________ +void TrackHandle_TrkTrack::visibleStateChanged() +{ + static_cast<TrackCollHandle_TrkTrack*>(collHandle())->visibleStateUpdated(this); + TrackHandleBase::visibleStateChanged(); +} + +//____________________________________________________________________ +void TrackHandle_TrkTrack::currentMaterialChanged() +{ + if (visible()) + static_cast<TrackCollHandle_TrkTrack*>(collHandle())->visibleStateUpdated(this); +} + +//____________________________________________________________________ +void TrackHandle_TrkTrack::ensureInitSubSysHitInfo() const +{ + if (m_hitInfoStatus==-1) + m_hitInfoStatus = VP1TrackSummary::countHits( m_trk, m_nhits_sct) ? 1 : 0; +} + +void TrackHandle_TrkTrack::fillObjectBrowser( QList<QTreeWidgetItem *>& listOfItems) +{ + TrackHandleBase::fillObjectBrowser(listOfItems); // Obligatory! + + // Fill sub-data. + QList<AssociatedObjectHandleBase*> list = getAllAscObjHandles(); + DataVector< const Trk::TrackStateOnSurface >::const_iterator it = trkTrackPointer()->trackStateOnSurfaces ()->begin(), + itE = trkTrackPointer()->trackStateOnSurfaces ()->end(); + unsigned int i=0; + for (;it!=itE;++it){ +// VP1Msg::messageVerbose("TSOS #"+QString::number(i++)); + + bool visible=false; + QTreeWidgetItem* TSOSitem = new QTreeWidgetItem(browserTreeItem()); + + AscObj_TSOS* asc=0; + if (i<static_cast<unsigned int>(list.size())) asc = dynamic_cast<AscObj_TSOS*>(list.at(i)); + + if (asc) { + asc->setBrowserTreeItem(TSOSitem); + visible=asc->visible(); + } + + if (!visible) { + TSOSitem->setFlags(0);// not selectable, not enabled + QFont itemFont = TSOSitem->font(0); + itemFont.setStrikeOut(true); + TSOSitem->setFont(0, itemFont); + TSOSitem->setFont(1, itemFont); + } + TSOSitem->setText(0, QString("Track State "+QString::number( (int)(it - trkTrackPointer()->trackStateOnSurfaces ()->begin() ) ) ) ); + + QString tsosText; + bool first=true; + const Trk::MeasurementBase* meas = (*it)->measurementOnTrack(); + if ( /**(*it)->type(Trk::TrackStateOnSurface::Measurement) &&*/ meas ){ + QString measName(TrkObjToString::name(*meas)); + tsosText+=measName; + + QTreeWidgetItem* measItem = new QTreeWidgetItem(TSOSitem); + measItem->setExpanded(true); // want it opened so subparams seen easily + measItem->setFlags(Qt::ItemIsEnabled); + measItem->setText(0, measName); + // measItem->setText(1, TrkObjToString::shortInfo(*meas) ); + + QStringList list = TrkObjToString::fullInfo( *((*it)->measurementOnTrack ()) ); + for (int i = 0; i < (list.size()-1); ){ + QTreeWidgetItem* subparamItem = new QTreeWidgetItem(measItem); + subparamItem->setText(0, list.at(i++) ); + subparamItem->setText(1, list.at(i++) ); + subparamItem->setFlags(Qt::ItemIsEnabled); + } + + first=false; + } + if ( (*it)->trackParameters () ) { + if (!first) tsosText.append(" + "); + tsosText.append("Parameters"); + + QTreeWidgetItem* paramItem = new QTreeWidgetItem(TSOSitem); + paramItem->setExpanded(true); // want it opened so subparams seen easily + paramItem->setFlags(Qt::ItemIsEnabled); + paramItem->setText(0, TrkObjToString::name( *((*it)->trackParameters ()) ) ); + // paramItem->setText(1, TrkObjToString::shortInfo( *((*it)->trackParameters ()) ) ); + + QStringList list = TrkObjToString::fullInfo( *((*it)->trackParameters ()) ); + for (int i = 0; i < (list.size()-1); ){ + QTreeWidgetItem* subparamItem = new QTreeWidgetItem(paramItem); + subparamItem->setText(0, list.at(i++) ); + subparamItem->setText(1, list.at(i++) ); + subparamItem->setFlags(Qt::ItemIsEnabled); + } + + first=false; + } + if ( (*it)->materialEffectsOnTrack () ){ + if (!first) tsosText.append(" + "); + tsosText.append("MaterialEffectsOnTrack"); + QTreeWidgetItem* meItem = new QTreeWidgetItem(TSOSitem); + meItem->setExpanded(true); // want it opened so subparams seen easily + meItem->setFlags(Qt::ItemIsEnabled); + + meItem->setText(0, TrkObjToString::name( *((*it)->materialEffectsOnTrack ()) ) ); + meItem->setText(1, TrkObjToString::shortInfo( *((*it)->materialEffectsOnTrack ()) ) ); + + first=false; + } + if ( (*it)->fitQualityOnSurface () ){ + if (!first) tsosText.append(" + "); + tsosText.append("FitQuality"); + QTreeWidgetItem* fqItem = new QTreeWidgetItem(TSOSitem); + fqItem->setExpanded(true); // want it opened so subparams seen easily + fqItem->setFlags(Qt::ItemIsEnabled); + fqItem->setText(0, QString("FitQuality") ); + fqItem->setText(1, TrkObjToString::shortInfo( *((*it)->fitQualityOnSurface ()) ) ); + + first=false; + } + // FIXME - add information about chamber for Muon systems? + + if ( (*it)->type(Trk::TrackStateOnSurface::Outlier) ){ + if (!first) tsosText.append(" + "); + tsosText.append("Outlier"); + } + + if ( (*it)->type(Trk::TrackStateOnSurface::InertMaterial) ){ + if (!first) tsosText.append(" + "); + tsosText.append("InertMaterial"); + } + + if ( (*it)->type(Trk::TrackStateOnSurface::BremPoint) ){ + if (!first) tsosText.append(" + "); + tsosText.append("BremPoint"); + } + + if ( (*it)->type(Trk::TrackStateOnSurface::Perigee) ){ + if (!first) tsosText.append(" + "); + tsosText.append("Perigee"); + } + + if ( (*it)->type(Trk::TrackStateOnSurface::Hole) ){ + if (!first) tsosText.append(" + "); + tsosText.append("Hole"); + } + TSOSitem->setText(1, tsosText ); + } + // listOfItems << browserTreeItem(); +} + +SoNode* TrackHandle_TrkTrack::zoomToTSOS(unsigned int index) +{ + if (trkTrackPointer() && (index<trkTrackPointer()->trackStateOnSurfaces()->size() )){ + const Trk::TrackStateOnSurface* tsos = (*trkTrackPointer()->trackStateOnSurfaces())[index]; + // now find matching AscObj_TSOS + QList<AssociatedObjectHandleBase*> list = getAllAscObjHandles(); + for (int i = 0; i < list.size(); ++i) { + // VP1Msg::messageVerbose("TrackSystemController::objectBrowserClicked: checking ASC "+QString::number(i)); + + AscObj_TSOS* asc = dynamic_cast<AscObj_TSOS*>(list.at(i)); + if (asc) { + if (asc && asc->trackStateOnSurface()==tsos) { + VP1Msg::messageVerbose("TrackSystemController::objectBrowserClicked: this ASC matches "+QString::number(i)); + //asc->zoomView(); + return asc->shapeDetailed(); + } + } + } + } + return 0; +} + +QString TrackHandle_TrkTrack::shortInfo() const +{ + QString l("|P|="+VP1Msg::str(momentum().mag()/CLHEP::GeV)+" [GeV], "); + l+= "SCT["+QString::number(getNSCTHits())+"]"; + return l; +} + + +void TrackHandle_TrkTrack::updateObjectBrowser(){ + + if ( !browserTreeItem()) { + VP1Msg::messageVerbose("updateObjectBrowser: No m_objBrowseTree!"); + return; + } + + // QString tmp = (visible()==true)?"True":"False"; +// VP1Msg::messageVerbose("updateObjectBrowser "+m_objBrowseTree->text(0)+" with visible()="+tmp); + + if (!visible()) { + browserTreeItem()->setFlags(0); // not selectable, not enabled + } else { + browserTreeItem()->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); // selectable, enabled + } + QFont font= browserTreeItem()->font(0); + font.setStrikeOut(!visible()); + browserTreeItem()->setFont(0, font ); + browserTreeItem()->setFont(1, font ); + + + // FIXME! Only do if necessary i.e. if something affecting this TSOS has changed. + + QList<AssociatedObjectHandleBase*> list = getAllAscObjHandles(); + + if (list.size()==0) { + VP1Msg::message("No ASC objects associated with this track - no track components visible yet?"); + return; + } + + DataVector< const Trk::TrackStateOnSurface >::const_iterator it = trkTrackPointer()->trackStateOnSurfaces ()->begin(), + itE = trkTrackPointer()->trackStateOnSurfaces ()->end(); + unsigned int numOfTSOS=0; + for (;it!=itE;++it,++numOfTSOS){ + AscObj_TSOS* asc = dynamic_cast<AscObj_TSOS*>(list.at(numOfTSOS)); + if (!(asc && asc->trackStateOnSurface()==*it && list.size()>0) ) { + // Fallback. + VP1Msg::message("TSOS#"+QString::number(numOfTSOS)+" does not seem to match AscObj_TSOS in list, which has size="+QString::number(list.size())+" Will try fallback."); + for (int i = 0; i < list.size(); ++i) { + AscObj_TSOS* asc = dynamic_cast<AscObj_TSOS*>(list.at(i)); + if (asc && asc->trackStateOnSurface()==*it) { + VP1Msg::message("-> this ASC matches "+QString::number(i)); + } + } + } + if (!asc) { + VP1Msg::message("Could not find matching Asc in list of size "+QString::number(list.size())); + continue; + } + + if (!asc->browserTreeItem() && browserTreeItem()){ + // not set yet - so need to do this now. Can we just use the index? + asc->setBrowserTreeItem(browserTreeItem()->child(numOfTSOS)); + } + + if (!asc->browserTreeItem()){ + VP1Msg::message("Could not find matching browserTreeItem"); + continue; + } + + if (!asc->visible()) { + asc->browserTreeItem()->setFlags(0); // not selectable, not enabled + } else { + asc->browserTreeItem()->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); // selectable, enabled + } + QFont itemFont = asc->browserTreeItem()->font(0); + itemFont.setStrikeOut(!asc->visible()); + asc->browserTreeItem()->setFont(0, itemFont); + asc->browserTreeItem()->setFont(1, itemFont); + } +} + +const Trk::FitQuality* TrackHandle_TrkTrack::getFitQuality() const { + return m_trk ? m_trk->fitQuality ():0; +} + diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackHandle_TruthTrack.cxx b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackHandle_TruthTrack.cxx new file mode 100644 index 000000000..6c9dddcb4 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackHandle_TruthTrack.cxx @@ -0,0 +1,340 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class TrackHandle_TruthTrack // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: March 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12TrackSystems/TrackHandle_TruthTrack.h" +#include "VTI12TrackSystems/AscObj_TruthPoint.h" +#include "VP1Base/VP1Msg.h" + +#include "TrkTrack/Track.h" +#include "HepMC/GenParticle.h" +#include "HepMC/GenVertex.h" +#include "CLHEP/Vector/LorentzVector.h" +#include "TrkTrack/Track.h" +#include "AthContainers/DataVector.h" +#include "TrkParameters/TrackParameters.h" +#include "TrkSurfaces/PlaneSurface.h" +#include "HepMC/GenParticle.h" + +//____________________________________________________________________ +class TrackHandle_TruthTrack::Imp { +public: + Imp(TrackHandle_TruthTrack * tc, + const SimBarCode& sbc,const SimHitList& shl,const HepMC::GenParticle* p) + : theclass(tc), + simBarCode(sbc), + simHitList(shl), + genParticle(p), + ascObjVis(false), + ascObjs(0), + trkTrack(0) {} + TrackHandle_TruthTrack * theclass; + SimBarCode simBarCode; + SimHitList simHitList; + const HepMC::GenParticle* genParticle; + + bool ascObjVis; + std::vector<AscObj_TruthPoint*> * ascObjs; + void ensureInitAscObjs(); + const Trk::Track * trkTrack; + void ensureInitTrkTracks(); + + static Trk::Perigee * createTrkPerigeeFromProdVertex(const HepMC::GenParticle * p, const double& charge ) + { + if (!p) + return 0;//Fixme: message! + const HepMC::GenVertex * v = p->production_vertex(); + if (!v) + return 0;//Fixme: message! + // std::cout << "Creating truth track prod vertex at: " << v->point3d().x() << " " << v->point3d().y() << " " << v->point3d().z() << std::endl; + Amg::Vector3D mom(p->momentum().px(),p->momentum().py(),p->momentum().pz()); + double absmom(mom.mag()); + if (absmom<=0) + return 0;//Fixme: message! + Amg::Vector3D pos(v->point3d().x(),v->point3d().y(),v->point3d().z()); + return new Trk::Perigee(0.,0.,mom.phi(), mom.theta(), charge/absmom, pos); + } + + static Trk::TrackParameters * createTrkParamFromDecayVertex(const HepMC::GenParticle * p, const double& charge ) + { + if (!p) + return 0;//Fixme: message! + const HepMC::GenVertex * v = p->end_vertex(); + if (!v) + return 0;//Fixme: message! + // std::cout << "Creating truth track end vertex at: " << v->point3d().x() << " " << v->point3d().y() << " " << v->point3d().z() << std::endl; + Amg::Vector3D mom(p->momentum().px(),p->momentum().py(),p->momentum().pz()); +// double absmom(mom.mag()); +// if (absmom<=0) +// return 0;//Fixme: message! + Amg::Vector3D pos(v->point3d().x(),v->point3d().y(),v->point3d().z()); + + Amg::Translation3D amgtranslation(pos.x(),pos.y(),pos.z()); + Amg::Transform3D* amgTransf = new Amg::Transform3D(amgtranslation * Amg::RotationMatrix3D::Identity()); + + return new Trk::AtaPlane(pos,mom,charge, *(new Trk::PlaneSurface(amgTransf))); + } + + static Trk::TrackStateOnSurface * createTSOS(const Trk::TrackParameters * pars) + { + return pars ? new Trk::TrackStateOnSurface(0,pars,0,0) : 0; + } + static void addPars(DataVector<const Trk::TrackStateOnSurface>* dv, const Trk::TrackParameters * pars) + { + if (!pars) + return; + Trk::TrackStateOnSurface * tsos = createTSOS(pars); + if (tsos) + dv->push_back(tsos); + } + + void createTrack(DataVector<const Trk::TrackStateOnSurface>* trackStateOnSurfaces) + { + if (!trackStateOnSurfaces) { + VP1Msg::messageDebug("TrackHandle_TruthTrack WARNING: Could not create track due to null TSOS vector"); + return; + } + if (trackStateOnSurfaces->size()==0) { + VP1Msg::messageDebug("TrackHandle_TruthTrack WARNING: Could not create track due to empty TSOS vector"); + delete trackStateOnSurfaces; + return; + } + if (trkTrack) { + VP1Msg::messageDebug("TrackHandle_TruthTrack ERROR: Already create trkTrack previously!"); + delete trackStateOnSurfaces; + return; + } + + Trk::TrackInfo ti(Trk::TrackInfo::Unknown,theclass->extrapolationParticleHypothesis()); + trkTrack = new Trk::Track(ti,trackStateOnSurfaces/*track assumes ownership*/,0/*fitquality*/); + +// if (VP1Msg::verbose()) +// VP1Msg::messageVerbose("TrackHandle_TruthTrack created track with " +// +QString::number(trackStateOnSurfaces->size())+" parameters"); + } + +}; + +//____________________________________________________________________ +TrackHandle_TruthTrack::TrackHandle_TruthTrack( TrackCollHandleBase* ch, + const SimBarCode& simBarCode, + const SimHitList& simHitList, + const HepMC::GenParticle* genPart ) + : TrackHandleBase(ch), m_d(new Imp(this,simBarCode,simHitList,genPart)) +{ + if (VP1Msg::verbose()) { + //Check genparticle barcode is same as in simBarCode. (and event index in parent_event()) + //Check that genparticle has production vertex. + //Check if genparticle has end vertex, that there are no sim hits. + //all pdg codes of simhits and genparticle should be identical. + //all simhits should have same barcode. + //hitTime should be rising in all simhits. NB: Remember to correct hit times with bunch crossing!! + //fixme! + } +} + +//____________________________________________________________________ +TrackHandle_TruthTrack::~TrackHandle_TruthTrack() +{ + //Fixme: delete simhitlist here? + setAscObjsVisible(false); + delete m_d->ascObjs; + delete m_d->trkTrack; + delete m_d; +} + +//____________________________________________________________________ +void TrackHandle_TruthTrack::Imp::ensureInitTrkTracks() +{ + if (trkTrack) + return; + + //The GenParticle part is used if it is available with a production + //vertex. The sim. hits are used if present and the genparticle does + //not have an end vertex: + bool useGenParticle = genParticle && genParticle->production_vertex(); + bool decayedGenParticle = useGenParticle && genParticle->end_vertex(); + bool useSimHits = !decayedGenParticle && !simHitList.empty(); + // std::cout << "TruthTrack useGen, decayedGen, useSim = " << useGenParticle << decayedGenParticle << useSimHits << std::endl; + if (!useGenParticle&&!useSimHits) { + VP1Msg::message("TrackHandle_TruthTrack ERROR: Track has neither a genparticle or sim. hits!!"); + return; + } + + if (!theclass->hasCharge()) { + VP1Msg::message("TrackHandle_TruthTrack ERROR: Could not determine particle charge (pdg=" + +QString::number(theclass->pdgCode())+").");//Fixme: I guess we could show non-extrapolated version? + return; + } + const double charge = theclass->charge(); + + DataVector<const Trk::TrackStateOnSurface>* trackStateOnSurfaces = new DataVector<const Trk::TrackStateOnSurface>; + + if (useGenParticle) { + addPars(trackStateOnSurfaces,createTrkPerigeeFromProdVertex(genParticle,charge)); + + if (decayedGenParticle) { + addPars(trackStateOnSurfaces,createTrkParamFromDecayVertex(genParticle,charge)); + createTrack(trackStateOnSurfaces); + return; + } + } + + if (useSimHits) { + //Add parameters from simhits (yes, if !useGenParticle, we get no perigee). + SimHitList::const_iterator it, itE(simHitList.end()); + for ( it = simHitList.begin(); it != itE; ++it ) { + //Fixme: momentum() < 0 (i.e. not present); + //Fixme: Possibly add points for both posStart() and posEnd() (and use energy loss information to get different momenta?) + addPars(trackStateOnSurfaces,it->second->createTrackParameters()); + } + + } + + createTrack(trackStateOnSurfaces); +} + +//____________________________________________________________________ +QStringList TrackHandle_TruthTrack::clicked() const +{ + + QStringList l; + l << "Truth track"; + l << TrackHandleBase::baseInfo(); + l << "Evt index = "+QString::number(m_d->simBarCode.evtIndex()); + l << "BarCode = "+QString::number(m_d->simBarCode.barCode()); + //fixme - more info + // l << "Truth track clicked [evt index = "+QString::number(m_d->simBarCode.second) + // +", barcode = "+(m_d->simBarCode.barCode<0?QString("Unknown (G4 secondary)"):QString::number(m_d->simBarCode.first))+"]";//fixme - more info + return l; +} + +//____________________________________________________________________ +const Trk::Track * TrackHandle_TruthTrack::provide_pathInfoTrkTrack() const +{ + m_d->ensureInitTrkTracks(); + return m_d->trkTrack; +} + + +//____________________________________________________________________ +int TrackHandle_TruthTrack::pdgCode() const +{ + return m_d->simBarCode.pdgCode(); +} + +//____________________________________________________________________ +bool TrackHandle_TruthTrack::hasBarCodeZero() const +{ + return m_d->simBarCode.isNonUniqueSecondary(); +} + +//____________________________________________________________________ +Amg::Vector3D TrackHandle_TruthTrack::momentum() const +{ + if (m_d->genParticle) { + return Amg::Vector3D(m_d->genParticle->momentum().px(),m_d->genParticle->momentum().py(),m_d->genParticle->momentum().pz()); + } + SimHitList::const_iterator it, itE(m_d->simHitList.end()); + for ( it = m_d->simHitList.begin(); it != itE; ++it ) { + if (it->second->momentum()>=0) { + return (it->second->momentum()) * (it->second->momentumDirection()); + } + } + //Unknown: + return TrackHandleBase::momentum(); +} + +//____________________________________________________________________ +bool TrackHandle_TruthTrack::hasVertexAtIR(const double& rmaxsq, const double& zmax) const +{ + if (!m_d->genParticle) + return false; + const HepMC::GenVertex * v = m_d->genParticle->production_vertex(); + if (!v) + return false; + + double x(v->point3d().x()), y(v->point3d().y()); + if (x*x+y*y>rmaxsq) + return false; + return fabs(v->point3d().z())<=zmax; +} + +//____________________________________________________________________ +void TrackHandle_TruthTrack::visibleStateChanged() +{ + if (visible()&&m_d->ascObjVis&&!m_d->ascObjs) + m_d->ensureInitAscObjs(); +} + +//____________________________________________________________________ +void TrackHandle_TruthTrack::setAscObjsVisible(bool b) +{ + if (m_d->ascObjVis==b) + return; + m_d->ascObjVis=b; +// const bool visnow = visible()&&m_d->ascObjVis; +// const bool visbefore = visible()&&!m_d->ascObjVis; +// if (visnow==visbefore) +// return; +// VP1Msg::messageVerbose("TrackHandle_TruthTrack::AscObjs visible state -> "+VP1Msg::str(b)); + + if (!m_d->ascObjs) { + if (!b||!visible()) + return; + m_d->ensureInitAscObjs(); + } + + std::vector<AscObj_TruthPoint*>::iterator it(m_d->ascObjs->begin()), itE(m_d->ascObjs->end()); + for (;it!=itE;++it) + (*it)->setVisible(b); +} + +//____________________________________________________________________ +void TrackHandle_TruthTrack::Imp::ensureInitAscObjs() +{ + if (ascObjs) + return; + ascObjs = new std::vector<AscObj_TruthPoint*>; + const HepMC::GenVertex * vprod = genParticle ? genParticle->production_vertex() : 0; + const HepMC::GenVertex * vend = genParticle ? genParticle->end_vertex() : 0; + ascObjs->reserve((vprod?1:0)+(vend?1:simHitList.size())); + if (vprod) + ascObjs->push_back(new AscObj_TruthPoint(theclass,vprod,genParticle)); + + if (vend) { + ascObjs->push_back(new AscObj_TruthPoint(theclass,vend,genParticle)); + } else { + SimHitList::const_iterator it, itE(simHitList.end()); + for ( it = simHitList.begin(); it != itE; ++it ) + ascObjs->push_back(new AscObj_TruthPoint(theclass,it->second)); + } + std::vector<AscObj_TruthPoint*>::iterator it, itE(ascObjs->end()); + for (it=ascObjs->begin();it!=itE;++it) + theclass->registerAssocObject(*it); + for (it=ascObjs->begin();it!=itE;++it) + (*it)->setVisible(ascObjVis); +} + +//____________________________________________________________________ +double TrackHandle_TruthTrack::calculateCharge() const +{ + if (!m_d->simHitList.empty()) { + if (m_d->simHitList.at(0).second->hasCharge()) + return m_d->simHitList.at(0).second->charge(); + else + VP1Msg::messageVerbose("TrackHandle_TruthTrack::calculateCharge() WARNING: Simhit did not have charge!"); + } + + return TrackHandleBase::calculateCharge(); +} diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackLODManager.cxx b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackLODManager.cxx new file mode 100644 index 000000000..0a729fa10 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackLODManager.cxx @@ -0,0 +1,364 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class TrackLODManager // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: March 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12TrackSystems/TrackLODManager.h" +#include "VP1Base/VP1Msg.h" +#include "VP1Base/VP1ExtraSepLayerHelper.h" +#include <Inventor/nodes/SoLevelOfDetail.h> +#include <Inventor/nodes/SoSeparator.h> +#include <map> + +//____________________________________________________________________ +class TrackLODManager::Imp { +public: + Imp() : attachnode(0), + attachnode_lod(0), + attachsep_simple(0), + attachsep_detailed(0), + attachHelper_simple(0), + attachHelper_detailed(0), + detailLevel(TrackCommonFlags::AUTO) {} + SoGroup * attachnode; + SoGroup * attachnode_lod; + SoSeparator * attachsep_simple; + SoSeparator * attachsep_detailed; + VP1ExtraSepLayerHelper * attachHelper_simple; + VP1ExtraSepLayerHelper * attachHelper_detailed; + void ensureLODDetached(); + void ensureSimpleDetached(); + void ensureDetailedDetached(); + void updateAttachmentForDetailLevel(TrackCommonFlags::DETAILLEVEL); + + TrackCommonFlags::DETAILLEVEL detailLevel; + std::map<std::pair<int,double>,TrackLODHandle* > id_2_lodhandle; +}; + + +//____________________________________________________________________ +TrackLODManager::TrackLODManager(QObject * parent, IVP1System * sys) + : QObject(parent), VP1HelperClassBase(sys,"TrackLODManager"), m_d(new Imp) +{ +} + +//____________________________________________________________________ +TrackLODManager::~TrackLODManager() +{ + if (m_d->attachnode) { + messageDebug("WARNING: Destructed before event data cleared!"); + eraseEventData(); + } + delete m_d; +} + +//____________________________________________________________________ +void TrackLODManager::Imp::ensureDetailedDetached() +{ + if ( attachnode && attachsep_detailed && attachnode->findChild(attachsep_detailed)>-1) + attachnode->removeChild(attachsep_detailed); +} + +//____________________________________________________________________ +void TrackLODManager::Imp::ensureSimpleDetached() +{ + if ( attachnode && attachsep_simple && attachnode->findChild(attachsep_simple)>-1) + attachnode->removeChild(attachsep_simple); +} + +//____________________________________________________________________ +void TrackLODManager::Imp::ensureLODDetached() +{ + if ( attachnode && attachnode_lod && attachnode->findChild(attachnode_lod)>-1) + attachnode->removeChild(attachnode_lod); +} + +//____________________________________________________________________ +void TrackLODManager::Imp::updateAttachmentForDetailLevel(TrackCommonFlags::DETAILLEVEL dl) +{ + if (dl == TrackCommonFlags::SIMPLE) { + if ( attachnode && attachsep_simple && attachnode->findChild(attachsep_simple)<0) + attachnode->addChild(attachsep_simple); + } else { + ensureSimpleDetached(); + } + + if (dl == TrackCommonFlags::DETAILED) { + if ( attachnode && attachsep_detailed && attachnode->findChild(attachsep_detailed)<0) + attachnode->addChild(attachsep_detailed); + } else { + ensureDetailedDetached(); + } + + if (dl == TrackCommonFlags::AUTO) { + if ( attachnode && attachnode_lod && attachnode->findChild(attachnode_lod)<0) + attachnode->addChild(attachnode_lod); + } else { + ensureLODDetached(); + } +} + +//____________________________________________________________________ +void TrackLODManager::setDetailLevel(TrackCommonFlags::DETAILLEVEL dl) +{ + if (VP1Msg::verbose()) + messageVerbose("signal received in setDetailLevel (old = "+TrackCommonFlags::toString(m_d->detailLevel)+", new = "+TrackCommonFlags::toString(dl)); + if ( m_d->detailLevel == dl ) + return; + m_d->detailLevel = dl; + m_d->updateAttachmentForDetailLevel(dl); +} + +//____________________________________________________________________ +void TrackLODManager::setAttachNode(SoGroup* an) +{ + if (!an) { + message("setAttachNode ERROR: Received null pointer!"); + return; + } + if (m_d->attachnode) { + message("setAttachNode ERROR: Received new attachment group pointer while still having previous one!"); + eraseEventData(); + return; + } + + m_d->attachnode = an; + m_d->attachnode->ref(); + + m_d->attachsep_simple = new SoSeparator; + m_d->attachsep_simple->ref(); + m_d->attachsep_detailed = new SoSeparator; + m_d->attachsep_detailed->ref(); + m_d->attachnode_lod = new SoGroup; + m_d->attachnode_lod->ref(); + + m_d->attachHelper_simple = new VP1ExtraSepLayerHelper(m_d->attachsep_simple); + m_d->attachHelper_detailed = new VP1ExtraSepLayerHelper(m_d->attachsep_detailed); + + m_d->updateAttachmentForDetailLevel(m_d->detailLevel); +} + +//____________________________________________________________________ +void TrackLODManager::eraseEventData() +{ + messageVerbose("eraseEventData start"); + if (!m_d->attachnode) { + messageDebug("eraseEventData WARNING: - called before attachment node was set!"); + return; + } + m_d->ensureSimpleDetached(); + m_d->ensureDetailedDetached(); + m_d->ensureLODDetached(); + + std::map<std::pair<int,double>,TrackLODHandle* >::iterator it, itE(m_d->id_2_lodhandle.end()); + for (it = m_d->id_2_lodhandle.begin(); it!=itE;++it) { + delete it->second; + } + m_d->id_2_lodhandle.clear(); + + if (m_d->attachnode_lod) { + m_d->attachnode_lod->unref(); + m_d->attachnode_lod = 0; + } + + if (m_d->attachsep_simple) { + delete m_d->attachHelper_simple; + m_d->attachHelper_simple = 0; + m_d->attachsep_simple->unref(); + m_d->attachsep_simple = 0; + } + + if (m_d->attachsep_detailed) { + delete m_d->attachHelper_detailed; + m_d->attachHelper_detailed = 0; + m_d->attachsep_detailed->unref(); + m_d->attachsep_detailed = 0; + } + + m_d->attachnode->unref(); + m_d->attachnode = 0; + messageVerbose("eraseEventData end"); + +} + +//____________________________________________________________________ +TrackLODHandle * TrackLODManager::getLODHandle(int regionindex, const double& crossover_value) +{ + std::map<std::pair<int,double>,TrackLODHandle* >::iterator it = m_d->id_2_lodhandle.find(std::make_pair(regionindex,crossover_value)); + if (it!=m_d->id_2_lodhandle.end()) + return it->second; + if (!m_d->attachnode) { + message("getTrackLODHandle ERROR: Called before attachment node was set!"); + return 0; + } + TrackLODHandle * lh = new TrackLODHandle(m_d->attachnode_lod,m_d->attachHelper_simple,m_d->attachHelper_detailed,regionindex,crossover_value); + m_d->id_2_lodhandle[std::make_pair(regionindex,crossover_value)] = lh; + return lh; +} + + +///////////////////////////////////// +// TrackLODHandle implementation // +///////////////////////////////////// + + +//____________________________________________________________________ +class TrackLODHandle::Imp { +public: + Imp( SoGroup* ag, + VP1ExtraSepLayerHelper * shs, + VP1ExtraSepLayerHelper * shd, + int i, const double& c) + : attachGroup_LOD(ag), + attachHelper_simple(shs), + attachHelper_detailed(shd), + regIdx(i), + crossVal(c), + lod(0), + sep_detailed(0), + sep_simple(0) {} + SoGroup* attachGroup_LOD; + VP1ExtraSepLayerHelper * attachHelper_simple; + VP1ExtraSepLayerHelper * attachHelper_detailed; + int regIdx; + double crossVal; + SoLevelOfDetail * lod; + SoSeparator * sep_detailed; + SoSeparator * sep_simple; + void updateCrossOverField() + { + //Fixme: We should scale this with complexity! I.e. multiply the value with 1.0/(complexity+0.5) + // lod->screenArea.setValue(crossVal/sqrt(sep_detailed->getNumChildren()+1.0)); + lod->screenArea.setValue(crossVal*sqrt(sep_detailed->getNumChildren())+0.1); + } +}; + + +//____________________________________________________________________ +TrackLODHandle::TrackLODHandle(SoGroup* attachgroup_LOD, + VP1ExtraSepLayerHelper * sephelper_simple, + VP1ExtraSepLayerHelper * sephelper_detailed, + int regionindex, const double& crossover_value) + : m_d(new Imp(attachgroup_LOD,sephelper_simple,sephelper_detailed,regionindex,crossover_value)) +{ +// if (VP1Msg::verbose()) +// VP1Msg::messageVerbose("TrackLODHandle Constructed with regionIndex = "+QString::number(regionindex) +// +" and nominal crossover value = "+QString::number(crossover_value)); + if (!attachgroup_LOD||!sephelper_simple||!sephelper_detailed) + VP1Msg::messageDebug("TrackLODHandle ERROR: Received null pointer!"); +} + +//____________________________________________________________________ +TrackLODHandle::~TrackLODHandle() +{ + if (m_d->lod) { + if (m_d->attachGroup_LOD->findChild(m_d->lod)>-1) { + m_d->attachGroup_LOD->removeChild(m_d->lod); + m_d->attachHelper_simple->removeNode(m_d->sep_simple); + m_d->attachHelper_detailed->removeNode(m_d->sep_detailed); + } + m_d->lod->unref(); + m_d->sep_detailed->unref(); + m_d->sep_simple->unref(); + } + delete m_d; +} + +//____________________________________________________________________ +void TrackLODHandle::addNodes(SoGroup* simple,SoGroup*detailed ) +{ + if (!m_d->lod) { +// if (VP1Msg::verbose()) +// VP1Msg::messageVerbose( "TrackLODHandle addNodes: Initialising nodes: LOD, sep_detailed and sep_simple."); + m_d->lod = new SoLevelOfDetail; + m_d->sep_detailed = new SoSeparator; + m_d->sep_simple = new SoSeparator; + m_d->lod->ref(); + m_d->sep_detailed->ref(); + m_d->sep_simple->ref(); + m_d->lod->addChild(m_d->sep_detailed); + m_d->lod->addChild(m_d->sep_simple); + } + + if (VP1Msg::verbose()) { + //Extra sanity checks: + if (!detailed) { + VP1Msg::messageVerbose("TrackLODHandle ERROR: addNodes received null pointer for detailed node"); + return; + } + if (!simple) { + VP1Msg::messageVerbose("TrackLODHandle ERROR: addNodes received null pointer for simple node"); + return; + } + if (m_d->sep_detailed->findChild(detailed)>=0) { + VP1Msg::messageVerbose("TrackLODHandle ERROR: addNodes called for detailed node which is already added"); + return; + } + if (m_d->sep_simple->findChild(simple)>=0) { + VP1Msg::messageVerbose("TrackLODHandle ERROR: addNodes called for simple node which is already added"); + return; + } + } + + m_d->sep_detailed->addChild(detailed); + m_d->sep_simple->addChild(simple); + + if (m_d->sep_detailed->getNumChildren()==1) { + //We went from 0 to 1 children! + if (VP1Msg::verbose()&&m_d->attachGroup_LOD->findChild(m_d->lod)>=0) + VP1Msg::messageVerbose("TrackLODHandle ERROR: adding lod, but it is already a child!!"); + m_d->attachGroup_LOD->addChild(m_d->lod); + m_d->attachHelper_simple->addNode(m_d->sep_simple); + m_d->attachHelper_detailed->addNode(m_d->sep_detailed); + } + m_d->updateCrossOverField(); +} + +//____________________________________________________________________ +void TrackLODHandle::removeNodes(SoGroup* simple,SoGroup*detailed ) +{ + if (!m_d->lod) + return; + + if (VP1Msg::verbose()) { + //Extra sanity checks: + if (!detailed) { + VP1Msg::messageVerbose("TrackLODHandle ERROR: removeNodes received null pointer for detailed node"); + return; + } + if (!simple) { + VP1Msg::messageVerbose("TrackLODHandle ERROR: removeNodes received null pointer for simple node"); + return; + } + if (m_d->sep_detailed->findChild(detailed)<0) { + VP1Msg::messageVerbose("TrackLODHandle ERROR: removeNodes called for detailed node which is not already added"); + return; + } + if (m_d->sep_simple->findChild(simple)<0) { + VP1Msg::messageVerbose("TrackLODHandle ERROR: removeNodes called for simple node which is not already added"); + return; + } + } + m_d->sep_detailed->removeChild(detailed); + m_d->sep_simple->removeChild(simple); + + if (m_d->sep_detailed->getNumChildren()<1) { + //We went from 1 to 0 children + if (VP1Msg::verbose()&&m_d->attachGroup_LOD->findChild(m_d->lod)<0) + VP1Msg::messageVerbose("TrackLODHandle ERROR: removing child, but node is not currently a child!!"); + m_d->attachGroup_LOD->removeChild(m_d->lod); + m_d->attachHelper_simple->removeNode(m_d->sep_simple); + m_d->attachHelper_detailed->removeNode(m_d->sep_detailed); + } else { + m_d->updateCrossOverField(); + } +} diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackPropagationHelper.cxx b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackPropagationHelper.cxx new file mode 100644 index 000000000..60a4efb14 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackPropagationHelper.cxx @@ -0,0 +1,544 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ + + + //////////////////////////////////////////////////////////////// + // // + // Implementation of class TrackPropagationHelper // + // // + // Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // + // Initial extrapolation code by Thijs Cornelissen // + // Initial version: February 2008 // + // // + //////////////////////////////////////////////////////////////// + +#include "VTI12TrackSystems/TrackPropagationHelper.h" +#include "TrkExInterfaces/IExtrapolator.h" +#include "TrkTrack/Track.h" +#include "TrkSurfaces/PlaneSurface.h" +#include "TrkParameters/TrackParameters.h" +#include <stdexcept> +//#include "TrkEventPrimitives/GlobalMomentum.h" +#include "VTI12TrackSystems/VP1TrackSanity.h" +#include "TrkEventPrimitives/CurvilinearUVT.h" +#include "TrkVolumes/Volume.h" +#include "TrkVolumes/BoundarySurface.h" +#include "TrkVolumes/VolumeBounds.h" + +#include "CLHEP/Units/PhysicalConstants.h" + +#include "VP1Base/VP1QtUtils.h" +#include "VP1Base/VP1Msg.h" +#include <limits> + +//____________________________________________________________________ +class TrackPropagationHelper::Imp { +public: + Imp(TrackPropagationHelper* tc) + : theclass(tc), + tracksanity(new VP1TrackSanity(tc?tc->systemBase():0)), + maxInDetr(1.1*CLHEP::m), + maxInDetrsq(maxInDetr*maxInDetr), + maxz(3.5*CLHEP::m), + // maxR2(std::numeric_limits<float>::max()), + fallback_flydist(10.0*CLHEP::cm), + showExtrapSurfaces(VP1QtUtils::environmentVariableIsOn("VP1_TRKSYS_SHOWEXTRAPSURFACES")) + { + } + ~Imp() { delete tracksanity; } + + TrackPropagationHelper * theclass; + VP1TrackSanity * tracksanity; + const double maxInDetr; + const double maxInDetrsq; + const double maxz; + // double maxR2; + const double fallback_flydist; + + bool outsideIDVolume(const Amg::Vector3D& p) { + return fabs(p.z())>maxz||p.perp2()>maxInDetrsq; + } + + //Fixme: These are similar to internal methods in InDetProjHelper in guideline system!!: + void movePoint1ToZPlaneAndPoint2( Amg::Vector3D& p1, const Amg::Vector3D& p2, const double& z ) const; + void movePoint1ToInfiniteCylinderAndPoint2( Amg::Vector3D&p1, const Amg::Vector3D&p2, const double& r ) const; + + bool makePointsNeutral_SinglePar( std::vector<Amg::Vector3D >& points, const Trk::Track* ); + bool makePointsCharged_SinglePar( std::vector<Amg::Vector3D >& points, const Trk::Track*, + Trk::IExtrapolator * extrapolator, Trk::ParticleHypothesis hypo ); + bool addPointsBetweenParameters_Charged( std::vector<Amg::Vector3D >& points, const Trk::Track*, + const Trk::TrackParameters * par1, const Trk::TrackParameters * par2, + Trk::IExtrapolator * extrapolator, Trk::ParticleHypothesis hypo ); + + //Will create new track par: + const Trk::TrackParameters * extrapolateToNewPar( Trk::IExtrapolator * extrapolator, + const Trk::Track* trk, + const Trk::TrackParameters * prevpars, + Trk::ParticleHypothesis hypo, + const double& dist ); + //Granularity: + double maxPointDistSq(const Amg::Vector3D& /* p */){ + //Vertex region: + /** all paths return the same number + const double absz(fabs(p.z())), absrsq(p.perp2()); + if ( (absz<2.75*CLHEP::m) and (absrsq<(1.2*CLHEP::m)*(1.2*CLHEP::m)) ) { + if ( (absz<0.67*CLHEP::m) and (absrsq<(0.16*CLHEP::m)*(0.16*CLHEP::m)) ) { + return 2*CLHEP::cm;//inside pixel + } + return 2*CLHEP::cm;//ID outside pixel + } + **/ + return 2*CLHEP::cm;//Outside ID + } + + std::vector<Trk::PlaneSurface> surfaces; //!< For debugging. + bool showExtrapSurfaces; +}; + +std::vector<Trk::PlaneSurface>& TrackPropagationHelper::getExtrapolationSurfaces() const { + return m_d->surfaces; +} + +//____________________________________________________________________ +void TrackPropagationHelper::Imp::movePoint1ToZPlaneAndPoint2( Amg::Vector3D& p1, const Amg::Vector3D& p2, const double& z ) const +{ + double dx(p2.x()-p1.x()), dy(p2.y()-p1.y()), dz(p2.z()-p1.z()); + if (dz==0.0) { + theclass->message("movePoint1ToZPlaneAndPoint2 Error: Points have same z!!"); + return; + } + double s( (z-p1.z())/dz ); + // p1.set( p1.x()+dx*s, p1.y()+dy*s, z ); + p1[0]= p1.x()+dx*s; + p1[1]= p1.y()+dy*s; + p1[2]= z; + +} + + //____________________________________________________________________ +void TrackPropagationHelper::Imp::movePoint1ToInfiniteCylinderAndPoint2( Amg::Vector3D&p1, const Amg::Vector3D&p2, const double& r ) const +{ + //Fixme: what happens here if we don't cross? And how can we be sure + //that we don't move FURTHER than the other point? (i.e. if the + //infinite line with p1 and p2 crosses, but the segment p1p2 does + //not!? + double p1r(p1.perp()); + double dr(p2.perp()-p1r); + if (dr==0.0) { + theclass->message("movePoint1ToInfiniteCylinderAndPoint2 Error: Points have same r!!"); + return; + } + double s((r-p1r)/dr); + double t(1.0-s); + // p1.set( p1.x()*t + p2.x()*s, p1.y()*t + p2.y()*s, p1.z()*t + p2.z()*s ); + p1[0]= p1.x()*t + p2.x()*s; + //p1[1]= p2.y()*s, p1.z()*t; original + p1[1]= p1.y()*t + p2.y()*s; //sroe, compiler warning fix + p1[2]= p1.z()*t + p2.z()*s; +} + + //____________________________________________________________________ +TrackPropagationHelper::TrackPropagationHelper(IVP1System* sys ) + : VP1HelperClassBase(sys,"TrackPropagationHelper"), m_d(new Imp(this)) +{ +} + + //____________________________________________________________________ +TrackPropagationHelper::~TrackPropagationHelper() +{ + delete m_d; +} + + //____________________________________________________________________ +bool TrackPropagationHelper::makePointsNeutral( std::vector<Amg::Vector3D >& points, const Trk::Track* track ) +{ + if (VP1Msg::verbose()) + messageVerbose("makePointsNeutral start"); + + points.clear(); + if (!track) { + message("makePointsNeutral called with null track pointer"); + return false; + } + const unsigned npars = track->trackParameters()->size(); + if (npars==0) { + message("makePointsNeutral Error: No TrackParameters on track!"); + return false; + } + if (npars==1) + return m_d->makePointsNeutral_SinglePar(points,track); + + points.reserve(track->trackParameters()->size()); + + + DataVector<const Trk::TrackStateOnSurface>::const_iterator tsos_iter = track->trackStateOnSurfaces()->begin(); + DataVector<const Trk::TrackStateOnSurface>::const_iterator tsos_end = track->trackStateOnSurfaces()->end(); + bool problems(false); + for (; tsos_iter != tsos_end; ++tsos_iter) { + if (!m_d->tracksanity->isSafe(*tsos_iter)) { + problems = true; + continue; + } + //if ((*tsos_iter)->materialEffectsOnTrack()) + // continue; + const Trk::TrackParameters* trackParam = (*tsos_iter)->trackParameters(); + if (!m_d->tracksanity->isSafe(trackParam)) { + problems = true; + continue; + } + points.push_back(trackParam->position()); + } + if (problems) { + messageDebug("makePointsNeutral WARNING: Track had one or more track parameters which is unsafe to use in job."); + if (points.size()<2) { + messageDebug("makePointsNeutral ERROR: Track did not have at least two safe parameters."); + points.clear(); + return false; + } + } + + if (VP1Msg::verbose()) + messageVerbose("makePointsNeutral_SinglePar end"); + return true; +} + + //____________________________________________________________________ +bool TrackPropagationHelper::Imp::makePointsNeutral_SinglePar( std::vector<Amg::Vector3D >& points, const Trk::Track* track ) +{ + if (VP1Msg::verbose()) + theclass->messageVerbose("makePointsNeutral_SinglePar start"); + points.clear(); + const Trk::TrackParameters * par = *(track->trackParameters()->begin()); + if (!tracksanity->isSafe(par)) { + theclass->messageDebug("makePointsNeutral_SinglePar called with unsafe track parameter"); + return false; + } + Amg::Vector3D u(par->momentum().unit()); + Amg::Vector3D a(par->position()),b; + if (outsideIDVolume(a)) { + //We start outside. We just add fallback_flydist. (fixme: warn?) + b = a +fallback_flydist*u; + } else { + //Make a second point, where trajectory hits maxInDetr,maxz + b = a +999*CLHEP::m*u; + if (b.z()<-maxz) + movePoint1ToZPlaneAndPoint2( b, a, -maxz ); + else + if (b.z()>maxz) + movePoint1ToZPlaneAndPoint2( b, a, maxz ); + if (b.perp2()>maxInDetrsq) + movePoint1ToInfiniteCylinderAndPoint2( b,a, maxInDetr ); + } + points.reserve(2); + points.push_back(a); + points.push_back(b); + if (VP1Msg::verbose()) + theclass->messageVerbose("makePointsNeutral_SinglePar (single track parameter) end"); + return true; +} + + //____________________________________________________________________ +bool TrackPropagationHelper::makePointsCharged( std::vector<Amg::Vector3D >& points, const Trk::Track* track, + Trk::IExtrapolator * extrapolator, Trk::ParticleHypothesis hypo, bool useMEOT,const Trk::Volume* volume ) +{ + if (VP1Msg::verbose()) + messageVerbose("makePointsCharged start with hypo="+str(hypo)+", useMEOT="+str(useMEOT)+", volume=" +str(volume)); + // if (volume) std::cout<<volume->volumeBounds()<<std::endl; + /////////////////////////////////////////////////////////////// + // Clear input points, check/sanitise input and initialise // + /////////////////////////////////////////////////////////////// + + points.clear(); + if (!extrapolator) { + message("makePointsCharged ERROR: Null extrapolator tool provided!"); + return false; + } + if (!track) { + message("makePointsCharged ERROR: Called with null track pointer"); + return false; + } + const unsigned npars = track->trackParameters()->size(); + if (npars==0) { + message("makePointsCharged ERROR: No TrackParameters on track!"); + return false; + } + if (npars==1) + return m_d->makePointsCharged_SinglePar(points,track,extrapolator,hypo); + + points.reserve(npars);//At least we need this. + + //Add a point for each parameter, and add extra points between them where appropriate. + DataVector<const Trk::TrackStateOnSurface>::const_iterator tsos_iter = track->trackStateOnSurfaces()->begin(); + DataVector<const Trk::TrackStateOnSurface>::const_iterator tsos_end = track->trackStateOnSurfaces()->end(); + const Trk::TrackParameters* prevpar(0); + const Trk::TrackParameters* trackParam(0); + bool problems(false); + for (; tsos_iter != tsos_end; ++tsos_iter) { + if (!m_d->tracksanity->isSafe(*tsos_iter)) + continue; + if ((*tsos_iter)->measurementOnTrack()==0 && ( (*tsos_iter)->materialEffectsOnTrack()&&!useMEOT ) ) + continue; + trackParam = (*tsos_iter)->trackParameters(); + if (!m_d->tracksanity->isSafe(trackParam)) + continue; + if (!prevpar) { + //first time. + prevpar = trackParam; + points.push_back(prevpar->position()); + continue; + } + if (!m_d->addPointsBetweenParameters_Charged(points,track,prevpar,trackParam,extrapolator,hypo)) + problems = true; + points.push_back(trackParam->position()); + prevpar = trackParam; + } + + if (problems) + messageDebug("WARNING: Problems encountered adding point(s) between track parameters"); + +// restrict to ID tracks for now. + if (volume && trackParam && !m_d->outsideIDVolume(trackParam->position())) { + messageVerbose("Extending to Volume"); + //get individual surfaces + + //TODO - optimise this! + const std::vector< const Trk::Surface * > * bsurfs = volume->volumeBounds ().decomposeToSurfaces (volume->transform ()); + + if (bsurfs){ + messageVerbose("Has this many surfaces:"+str(bsurfs->size())); + + std::vector< const Trk::Surface * >::const_iterator bSurfsIt = bsurfs->begin(); + for (;bSurfsIt!= bsurfs->end(); bSurfsIt++){ + + messageVerbose("Extrap value:"+str((extrapolator))); + messageVerbose("trackParam:"+str((trackParam))); + const Trk::TrackParameters* trackPar = extrapolator->extrapolate(*trackParam,**bSurfsIt,Trk::alongMomentum,true,hypo); // change this to extrapolate current param to surface. + + if (trackPar){ + messageVerbose("Extrapolation succeeded"); + + if (!m_d->addPointsBetweenParameters_Charged(points,track,trackParam,trackPar,extrapolator,hypo)) + messageDebug("WARNING: Problems encountered adding point(s) between track parameters in extending to Volume"); + } + } + } else { + messageDebug("WARNING: Problems encountered getting boundary surfaces from Volume"); + } + } + if (VP1Msg::verbose()) + messageVerbose("makePointsCharged end with "+str(points.size())+"points"); + return true; +} + + //____________________________________________________________________ +const Trk::TrackParameters * TrackPropagationHelper::Imp::extrapolateToNewPar( Trk::IExtrapolator * extrapolator, + const Trk::Track* trk, + const Trk::TrackParameters * prevpars, + Trk::ParticleHypothesis hypo, + const double& dist ) +{ + if (!trk||!prevpars||!extrapolator) + return 0; + + + //Code from thijs begin + // CLHEP::Hep3Vector dir(prevpars->sinTheta()*prevpars->cosPhi(),prevpars->sinTheta()*prevpars->sinPhi(),prevpars->cosTheta()); + // double theta=prevpars->parameters()[Trk::theta]; + // double newtheta=(theta<M_PI/2.) ? theta+M_PI/2. : theta-M_PI/2.; + // CLHEP::Hep3Vector dir2(sin(newtheta)*prevpars->cosPhi(),sin(newtheta)*prevpars->sinPhi(),cos(newtheta)); + // CLHEP::Hep3Vector dir3=dir.cross(dir2); + // CLHEP::HepRotation rot; + // rot.rotateAxes(dir2,dir3,dir); + // Hep3Vector transl=prevpars->position()+dist*dir; + // HepTransform3D *transf=new HepTransform3D(rot,transl); + // Trk::PlaneSurface plsurf(transf); + //Code from thijs end + // //Alternative test code from thomas begin + // //(shows same issues as thijs' code unfortunately) + // Ed's attempt: + // HepGeom::Rotate3D rotation; + // HepGeom::Scale3D scale; + // HepGeom::Translate3D translation; + // Trk::Surface* surf= prevpars->associatedSurface()->clone(); + // surf->transform ().getDecomposition(scale,rotation,translation); + // translation = HepTranslate3D(prevpars->position()+prevpars->momentum().unit()*dist); + + Trk::CurvilinearUVT uvt(prevpars->momentum().unit()); + + + Amg::Transform3D* t = new Amg::Transform3D(uvt.curvU(),uvt.curvV(),uvt.curvT(), prevpars->position()+(prevpars->momentum().unit()*dist)); + + Trk::PlaneSurface surf(t); + + // Trk::PlaneSurface surf(new HepGeom::Transform3D(CLHEP::HepRotation(uvt.curvU(),uvt.curvV(),uvt.curvT()), + // prevpars->position()+(prevpars->momentum().unit()*dist))); + + if (showExtrapSurfaces) surfaces.push_back(surf); + + // theclass->messageVerbose("extrapolateToNewPar. current position: "+str(prevpars->position())+" ("+str(prevpars->position().mag())+"), dist="+str(dist)); + // theclass->messageVerbose("new position: "+str(surf.center())+", using dir="+str(prevpars->momentum().unit()*dist)); + + // if ((prevpars->position()-surf.center()).mag()<0.01){ + // theclass->messageVerbose("Bugger. Translation didn't work. "); + // return 0; + // } + const Trk::TrackParameters *newpars(0); + try { + // newpars = extrapolator->extrapolate(*trk,surf,Trk::anyDirection,false,hypo); // change this to extrapolate current param to surface. + newpars = extrapolator->extrapolate(*prevpars,surf,Trk::alongMomentum,false,hypo); // change this to extrapolate current param to surface. + } catch (const std::runtime_error& e) { + theclass->message("Failure trying to use extrapolator for track (Exception thrown: " + QString(e.what())+")"); + return 0; + } + if (!newpars) { + theclass->message("Failure trying to use extrapolator for track"); + return 0; + } + + //in case this lead to a large kink, we try a different, less ambitous, method: + // Amg::Vector3D actualdirp((newpars->position()-prevpars->position()).unit()); + // const double dot = actualdirp.x()*dir.x()+actualdirp.y()*dir.y()+actualdirp.z()*dir.z(); + // if (dot<0.866025403784439) {//>30deg + // theclass->messageVerbose("Detected kink. Trying alternative extrapolation)"); + // delete newpars; + // newpars = 0; + // HepTransform3D *transf2=new HepTransform3D(rot,transl); + // Trk::PlaneSurface plsurf2(transf2); + // try { + // newpars = extrapolator->extrapolateDirectly(*prevpars,plsurf2,Trk::anyDirection,false,hypo); + // } catch (std::runtime_error e) { + // theclass->message("Failure trying to use alternative extrapolation method for track (Exception thrown: " + QString(e.what())+")"); + // return 0; + // } + // } + + + if (!newpars) { + theclass->message("Failure trying to use extrapolator for track"); + return 0; + } + return newpars; +} + +bool TrackPropagationHelper::showExtrapolationSurfaces() const { + return m_d->showExtrapSurfaces; +} + +// double TrackPropagationHelper::maxR2ForTracks() const { +// return m_d->maxR2; +// } + + + //____________________________________________________________________ +bool TrackPropagationHelper::Imp::makePointsCharged_SinglePar( std::vector<Amg::Vector3D >& points, const Trk::Track* track, + Trk::IExtrapolator * extrapolator, Trk::ParticleHypothesis hypo ) +{ + if (VP1Msg::verbose()) + theclass->messageVerbose("makePointsCharged_SinglePar start"); + points.clear(); + if (!extrapolator) { + theclass->message("makePointsCharged_SinglePar ERROR: Null extrapolator tool provided!"); + return false; + } + const Trk::TrackParameters * par = *(track->trackParameters()->begin()); + if (!tracksanity->isSafe(par)) { + theclass->messageDebug("makePointsCharged_SinglePar called with unsafe track parameter"); + return false; + } + + Amg::Vector3D p0(par->position()); + points.push_back(p0); + const bool startoutsideID(outsideIDVolume(p0)); + + double distadded(0); + const double maxdistadded = 2*CLHEP::m; + points.reserve(20);//skip a few reallocs + const Trk::TrackParameters * prevpars = par; + const Trk::TrackParameters * temppars(0); + + while (distadded<maxdistadded) { + temppars = extrapolateToNewPar( extrapolator, track, prevpars, hypo, maxPointDistSq(prevpars->position())); + if (temppars) + distadded += (temppars->position()-prevpars->position()).mag(); + if (prevpars!=par) + delete prevpars; + prevpars = 0; + if (!temppars) { + theclass->messageDebug("makePointsCharged_SinglePar ERROR: Failed to use extrapolator for next point"); + if (points.size()<2) { + points.clear(); + return false; + } + return true;//Fixme?? + } + Amg::Vector3D p(temppars->position()); + points.push_back(p); + prevpars = temppars; + temppars = 0; + if (!startoutsideID && outsideIDVolume(p)) { + if (prevpars!=par) + delete prevpars; + prevpars = 0; + break; + } + } + if (prevpars!=par) + delete prevpars; + + if (VP1Msg::verbose()) + theclass->messageVerbose("makePointsCharged_SinglePar end"); + return true; + +} + + //____________________________________________________________________ +bool TrackPropagationHelper::Imp::addPointsBetweenParameters_Charged( std::vector<Amg::Vector3D >& points, const Trk::Track* trk, + const Trk::TrackParameters * par1, const Trk::TrackParameters * par2, + Trk::IExtrapolator * extrapolator, Trk::ParticleHypothesis hypo ) +{ + double distbetween = sqrt((par2->position()-par1->position()).mag2()); + if (distbetween<0.001) { + theclass->messageVerbose("TrackPropagationHelper::Imp::addPointsBetweenParameters_Charged: parameters on top of each other. Skip, but no error."); + return true; + } + // theclass->messageVerbose("TrackPropagationHelper::Imp::addPointsBetweenParameters_Charged: par1=" + // +str(par1->position())+", par2=" +str(par2->position())+", dist="+str(distbetween)); + + Amg::Vector3D p2(par2->position()); + const Trk::TrackParameters * prevpars = par1; + + double olddistsq(1.0e99); + double distadded(0); + const double maxdistadded = std::max(2*CLHEP::m,(par1->position()-p2).mag()*1.5); + while ( (prevpars->position()-p2).mag()> maxPointDistSq(prevpars->position()) && distadded<maxdistadded ) { + + // theclass->messageVerbose("distadded: "+str(distadded)+", distance left="+str(sqrt((prevpars->position()-p2).mag2()))+", jump="+str(maxPointDistSq(prevpars->position()))); + const Trk::TrackParameters * newpars = extrapolateToNewPar( extrapolator, trk, prevpars, hypo, maxPointDistSq(prevpars->position()) ); + if (!newpars){ + if (VP1Msg::verbose()) + theclass->messageVerbose("TrackPropagationHelper::Imp::addPointsBetweenParameters_Charged: Extrapolation failed."); + return false; + } + const double distsq = (par2->position()-newpars->position()).mag2(); + if (distsq>olddistsq) { + delete newpars; + if (VP1Msg::verbose()) + theclass->messageVerbose("TrackPropagationHelper::Imp::addPointsBetweenParameters_Charged: distq("+str(distsq)+")>olddistsq ("+str(olddistsq)+") so overshot?"); + return false; + } + olddistsq = distsq; + // if ((prevpars->position()-newpars->position()).mag2() > 4*maxpointdistsq) { + // delete newpars; + // return false; + // } + points.push_back(newpars->position()); + distadded += (newpars->position()-prevpars->position()).mag(); + if (prevpars!=par1) + delete prevpars; + prevpars = newpars; + } + if (prevpars!=par1) + delete prevpars; + return (distadded<maxdistadded); +} diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackSysCommonData.cxx b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackSysCommonData.cxx new file mode 100644 index 000000000..e34d815c7 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackSysCommonData.cxx @@ -0,0 +1,192 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class TrackSysCommonData // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: April 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12TrackSystems/TrackSysCommonData.h" + +#include "VTI12TrackSystems/VP1TrackSystem.h" +#include "VTI12TrackSystems/AscObjSelectionManager.h" +#include "VTI12TrackSystems/TrackPropagationHelper.h" +#include "VTI12TrackSystems/TrackLODManager.h" +#include "VTI12TrackSystems/TrackSystemController.h" +#include "VTI12TrackSystems/VP1TrackSanity.h" +#include "VTI12TrackSystems/TrackHandle_TrkTrack.h" +#include "VTI12TrackSystems/TrackHandleBase.h" + +// #include "VP1GuideLineSystems/InDetProjHelper.h" + +#include "VP1Base/VisibleObjectToMaterialHelper.h" +#include "VP1Base/VP1Msg.h" + +#include <Inventor/C/errors/debugerror.h> +#include <Inventor/nodes/SoVertexProperty.h> +#include <Inventor/nodes/SoPointSet.h> +#include <Inventor/nodes/SoSeparator.h> + +#include <QTreeWidgetItem> + +#include<map> + +//____________________________________________________________________ +class TrackSysCommonData::Imp { +public: + std::map<SoNode*,TrackHandleBase*> nodeToTrackHandle; +}; + +//____________________________________________________________________ +TrackSysCommonData::TrackSysCommonData(VP1TrackSystem * sys,TrackSystemController * controller) + : VP1HelperClassBase(sys,"TrackSysCommonData"), m_textSep(0), m_d(new Imp), + m_ascObjSelectionManager(0), m_controller(controller), m_lastSelectedTrack(0) +{ + m_3dsystem = sys; + // m_indetProjHelper_Pixel = InDetProjHelper::createPixelHelper(sys); + // m_indetProjHelper_SCT = InDetProjHelper::createSCTHelper(sys); + // m_indetProjHelper_TRT = InDetProjHelper::createTRTHelper(sys); + m_trackPropagationHelper = new TrackPropagationHelper(sys); + m_trackSanity = new VP1TrackSanity(sys); + + m_singlePoint = new SoPointSet; + m_singlePoint->ref(); + SoVertexProperty * vertices = new SoVertexProperty; + vertices->vertex.set1Value(0,0.0f,0.0f,0.0f); + m_singlePoint->numPoints=1; + m_singlePoint->vertexProperty.setValue(vertices); + + m_trackLODManager = new TrackLODManager(0,sys); + QObject::connect( m_controller,SIGNAL(assocObjDetailLevelChanged(TrackCommonFlags::DETAILLEVEL)), + m_trackLODManager,SLOT(setDetailLevel(TrackCommonFlags::DETAILLEVEL)) ); + m_trackLODManager->setDetailLevel(m_controller->assocObjDetailLevel()); + + m_visTrkTracksToMaterialHelper = new VisibleObjectToMaterialHelper<Trk::Track>(0,sys); + m_visTrkSegmentsToMaterialHelper = new VisibleObjectToMaterialHelper<Trk::Segment>(0,sys); + QObject::connect(m_visTrkTracksToMaterialHelper,SIGNAL(visibleObjectsChanged()),sys,SLOT(visibleObjectsChanged())); + QObject::connect(m_visTrkSegmentsToMaterialHelper,SIGNAL(visibleObjectsChanged()),sys,SLOT(visibleObjectsChanged())); +} + +//____________________________________________________________________ +TrackSysCommonData::~TrackSysCommonData() +{ + // delete m_indetProjHelper_Pixel; + // delete m_indetProjHelper_SCT; + // delete m_indetProjHelper_TRT; + delete m_trackPropagationHelper; + delete m_trackLODManager; + delete m_visTrkTracksToMaterialHelper; + delete m_visTrkSegmentsToMaterialHelper; + delete m_trackSanity; + m_singlePoint->unref(); + if (m_textSep) { + m_textSep->unref(); + m_textSep = 0; + } + delete m_d; +} + +//____________________________________________________________________ +void TrackSysCommonData::setEventData(AscObjSelectionManager* aomgr) +{ + m_ascObjSelectionManager = aomgr; +} + +//____________________________________________________________________ +void TrackSysCommonData::clearEventData() +{ + m_ascObjSelectionManager->aboutTodelete();//To allow to emit signals. + delete m_ascObjSelectionManager; + m_ascObjSelectionManager = 0; + m_trackLODManager->eraseEventData(); + m_visTrkTracksToMaterialHelper->setNoVisibleObjects(); + m_visTrkSegmentsToMaterialHelper->setNoVisibleObjects(); + // m_d->nodeToTrackHandle.clear(); TrackHandle destructor already ensures that unregister... below is called. +} + +//____________________________________________________________________ +void TrackSysCommonData::registerTrack(SoNode*node,TrackHandleBase*handle) +{ + if (VP1Msg::verbose()) { + if (!node||!handle) { + message("registerTrack ERROR: Received null pointer!"); + return; + } + std::map<SoNode*,TrackHandleBase*>::iterator it = m_d->nodeToTrackHandle.find(node); + if (it!=m_d->nodeToTrackHandle.end()) + message("registerTrack ERROR: Node already registered!"); + } + m_d->nodeToTrackHandle[node]=handle; +} + +//____________________________________________________________________ +void TrackSysCommonData::unregisterTrack(SoNode*node) +{ + if (VP1Msg::verbose()) { + if (!node) { + message("unregisterTrack ERROR: Received null pointer!"); + return; + } + } + std::map<SoNode*,TrackHandleBase*>::iterator it = m_d->nodeToTrackHandle.find(node); + if (it==m_d->nodeToTrackHandle.end()) { + message("unregisterTrack ERROR: Not previously registered!"); + return; + } + m_d->nodeToTrackHandle.erase(it); +} + +//____________________________________________________________________ +TrackHandleBase* TrackSysCommonData::trackHandle(SoNode*n) +{ + if (!n) + return 0; + std::map<SoNode*,TrackHandleBase*>::iterator it = m_d->nodeToTrackHandle.find(n); + if (it!=m_d->nodeToTrackHandle.end()) + return it->second; + return 0; +} + +//____________________________________________________________________ +SoNode* TrackSysCommonData::node(TrackHandleBase* h) +{ + if (!h) + return 0; + std::map<SoNode*,TrackHandleBase*>::iterator it = m_d->nodeToTrackHandle.begin(), itEnd=m_d->nodeToTrackHandle.end(); + for (; it!=itEnd;++it) + if (it->second==h) return it->first; + return 0; +} + +//____________________________________________________________________ +SoNode* TrackSysCommonData::node(QTreeWidgetItem* item) +{ + if (!item) + return 0; + std::map<SoNode*,TrackHandleBase*>::iterator it = m_d->nodeToTrackHandle.begin(), itEnd=m_d->nodeToTrackHandle.end(); + for (; it!=itEnd;++it) + if (it->second->browserTreeItem()==item) return it->first; + return 0; +} + +const TrackHandleBase* TrackSysCommonData::getHandle(const Trk::Track* trk) +{ + if (!trk) { + messageVerbose("TrackSysCommonData::getHandle(): Received null pointer!"); + return 0; + } +// messageVerbose("TrackSysCommonData::getHandle(): about to loop over this many elements:"+QString::number(m_d->nodeToTrackHandle.size())); + + std::map<SoNode*,TrackHandleBase*>::iterator it = m_d->nodeToTrackHandle.begin(), itEnd=m_d->nodeToTrackHandle.end(); + for (; it!=itEnd;++it){ + const TrackHandle_TrkTrack* trkHandle = dynamic_cast<const TrackHandle_TrkTrack*>(it->second); + if (trkHandle && trkHandle->trkTrackPointer()==trk) return trkHandle; + } + return 0; +} diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackSystemController.cxx b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackSystemController.cxx new file mode 100644 index 000000000..d9aefef6f --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackSystemController.cxx @@ -0,0 +1,2206 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class TrackSystemController // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: February 2008 // +// Updates: Riccardo Maria Bianchi (rbianchi@cern.ch) // +// // +//////////////////////////////////////////////////////////////// + +#define VP1IMPVARNAME m_d + +// FIXME! Remove! +#include <Inventor/C/errors/debugerror.h> +#define protected public +#include <Inventor/nodes/SoSelection.h> +#undef protected + +#include "VTI12TrackSystems/TrackSystemController.h" +#include "VTI12TrackSystems/TrackCollWidget.h" +// #include "VP1TrackSystems/TrackObjectBrowserController.h" +#include "VTI12TrackSystems/AscObjSelectionManager.h" +#include "VTI12TrackSystems/AscObj_TSOS.h" +#include "VTI12TrackSystems/VP1TrackSystem.h" +#include "VTI12TrackSystems/TrackSysCommonData.h" +#include "VTI12TrackSystems/TrackHandle_TrkTrack.h" + +#include "ui_vp1trackcontrollerform.h" +#include "ui_settings_ascobjs_form.h" +#include "ui_settings_colouring_form.h" +#include "ui_settings_extrapolation_form.h" +#include "ui_settings_interactions_form.h" +#include "ui_settings_projections_form.h" +#include "ui_settings_cuts_form.h" +#include "ui_shift_muon_chamber_form.h" +#include "ui_objectbrowser.h" + +#include "VTI12Utils/VP1AvailableToolsHelper.h" +#include "VTI12Utils/VP1ToolAccessHelper.h" +#include "VTI12Utils/VP1JobConfigInfo.h" +#include "VTI12Utils/VP1ParticleData.h" +#include "VP1Base/VP1QtUtils.h" +#include "VP1Base/IVP1System.h" +#include "VP1Base/VP1Serialise.h" +#include "VP1Base/VP1Deserialise.h" +#include "VP1Base/VP1QtInventorUtils.h" +#include "VP1Base/VP1SoMaterialMixer.h" +#include "VP1Base/SoCooperativeSelection.h" + +#include "TrkExInterfaces/IExtrapolator.h" +#include "TrkFitterInterfaces/ITrackFitter.h" +#include "TrkTrack/Track.h" +#include "TrkTrack/TrackStateOnSurface.h" + +#include "TrkVolumes/CylinderVolumeBounds.h" +#include "TrkVolumes/CuboidVolumeBounds.h" +#include "TrkVolumes/Volume.h" + +#include "Inventor/nodes/SoMaterial.h" +#include "Inventor/nodes/SoDrawStyle.h" +#include "Inventor/nodes/SoComplexity.h" +#include "Inventor/nodes/SoLightModel.h" +#include <Inventor/nodes/SoSeparator.h> +#include <Inventor/actions/SoSearchAction.h> + +#include "CLHEP/Units/SystemOfUnits.h" + +#include <QTreeWidget> +#include <QTreeWidgetItem> + + + + +//____________________________________________________________________ +class TrackSystemController::Imp { +public: + TrackSystemController * theclass; + Ui::VP1TrackControllerForm ui; + TrackCollWidget * trackcollwidget; + void initMaterials(); + SoMaterial * createMaterial(const int& r,const int& g,const int& b) const; + SoMaterial * getMat(VP1MaterialButton*) const; + SoMaterial * materialFallback; + // SoDrawStyle * trackDrawStyle; + SoDrawStyle * ascObjDrawStyle; + SoComplexity * ascObjComplexity; + // SoLightModel * trackLightModel; + + QString restoredLastPropagator; + QString restoredLastFitter; + QStringList lastUpdatedAvailableExtrapolators; + QStringList lastUpdatedAvailableFitters; + bool updateComboBoxContents(QComboBox*cb,QStringList l,QString& restoredSelection); + static const QString noneAvailString; + unsigned numberOfSelectedPRDs; + unsigned numberOfSelectedTracks; + void updateFitPRDButtonState(); + + VP1SoMaterialMixer * matmixer; + VP1AvailableToolsHelper * toolhelper_extrapolators; + VP1AvailableToolsHelper * toolhelper_fitters; + VP1ToolAccessHelper * toolaccesshelper; + TrackCommonFlags::TrackPartsFlags last_shownTrackParts; + int last_vertexProjectionAngle; + double last_trackTubeRadius; + TrackLabelModes last_trackLabels; + float last_trackLabelTrkOffset; + QList<int> last_trackLabelPosOffset; + Trk::IExtrapolator * last_propagator; + // bool last_ignoreMeasurementEffectsOnTrackInProp; + PropagationOptionFlags last_propagationOptions; + float last_propMaxRadius; + Trk::ITrackFitter * last_trackFitter; + TrackCommonFlags::SELECTIONMODE last_selectionMode; + bool last_showTruthAscObjs; + TrackCommonFlags::DETAILLEVEL last_assocObjDetailLevel; + TrackCommonFlags::TSOSPartsFlags last_shownTSOSParts; + TrackCommonFlags::TSOSPartsFlags last_customColouredTSOSParts; + bool last_useShortTRTMeasurements; + bool last_useShortMDTMeasurements; + bool last_drawMeasGlobalPositions; + double last_measurementsShorttubesScale; + double last_nStdDevForParamErrors; + bool last_parTubeErrorsDrawCylinders; + int last_numberOfPointsOnCircles; + double last_materialEffectsOnTrackScale; + VP1Interval last_cutAllowedPt; + VP1Interval last_cutAllowedP; + VP1Interval last_cutAllowedEta; + QList<VP1Interval> last_cutAllowedPhi; + QList<unsigned> last_cutRequiredNHits; + bool last_cutTruthFromIROnly; + bool last_cutExcludeBarcodeZero; + bool last_cutTruthExcludeNeutrals; + bool last_cutOnlyVertexAssocTracks; + bool last_showTotMomentumOnMultiTrackSelection; + + Ui::TrackSysSettingsColouringForm ui_col; + Ui::TrackSysSettingsExtrapolationsForm ui_extrap; + Ui::TrackSysSettingsInteractionsForm ui_int; + Ui::TrackSysSettingsProjectionsForm ui_proj; + Ui::TrackSysSettingsCutsForm ui_cuts; + Ui::TrackSysSettingsAscObjsForm ui_ascobjs; + Ui::TrackSysShiftMuonChambersForm ui_shiftmuonchambers; + Ui::ObjectBrowser ui_objBrowser; + + static bool extrapolatorsCreated; + static void ensureExtrapolatorsCreated(IVP1System *); + static bool fittersCreated; + static void ensureFittersCreated(IVP1System *); + + QTreeWidget* objBrowserWidget; + TrackSysCommonData * common; + + // Added because TrackingVolumeSvc doesn't work any more. Can remove when we move to new extrapolator + Trk::Volume* calorimeterEntryLayer; + Trk::Volume* muonSpectrometerEntryLayer; + Trk::Volume* muonSpectrometerExitLayer; +}; + +const QString TrackSystemController::Imp::noneAvailString = QString("None available"); + + +//____________________________________________________________________ +QString TrackSystemController::toString( const QList<unsigned>& l ) +{ + QString s; + foreach(unsigned i,l) { + if (!s.isEmpty()) s+=", "; + s+=QString::number(i); + } + return "["+s+"]"; +} + +//____________________________________________________________________ +QString TrackSystemController::toString( const QList<int>& l ) +{ + QString s; + foreach(int i,l) { + if (!s.isEmpty()) s+=", "; + s+=QString::number(i); + } + return "["+s+"]"; +} + +//____________________________________________________________________ +bool TrackSystemController::Imp::extrapolatorsCreated = false; +void TrackSystemController::Imp::ensureExtrapolatorsCreated(IVP1System * sys) { + if (extrapolatorsCreated||!sys) + return; + extrapolatorsCreated = true; + + //Get available extrapolators: + QString tooltype("Trk::Extrapolator"); + VP1AvailableToolsHelper * availTools = new VP1AvailableToolsHelper(sys); + availTools->addMonitoredType(tooltype); + QStringList existingExtrapolators = availTools->availableTools(); + delete availTools; + + VP1ToolAccessHelper toolaccess(sys); + foreach (QString key,VP1QtUtils::environmentVariableValue("VP1_JOBCFG_EXTRA_VP1_EXTRAPOLATORS").split(';',QString::SkipEmptyParts)) { + if (existingExtrapolators.contains(key)) + continue; + sys->messageDebug("Attempting creation of fitter with tooltype/key "+key); + Trk::IExtrapolator * tool = toolaccess.getToolPointer<Trk::IExtrapolator>(key,false/*silent*/,true/*create if not exists*/); + if (!tool) { + sys->message("WARNING: Could not create tool type/key "+key); + } + + } +} + +//____________________________________________________________________ +bool TrackSystemController::Imp::fittersCreated = false; +void TrackSystemController::Imp::ensureFittersCreated(IVP1System * sys) { + if (fittersCreated||!sys) + return; + fittersCreated = true; + + //Get available extrapolators: + QStringList fittertypes; + fittertypes << "Trk::KalmanFitter" + << "Trk::GlobalChi2Fitter" + << "Trk::GaussianSumFilter" + << "Trk::DistributedKalmanFilter" + << "Trk::DeterministicAnnealingFilter"; + VP1AvailableToolsHelper * availTools = new VP1AvailableToolsHelper(sys); + availTools->addMonitoredTypes(fittertypes); + QStringList existingFitters = availTools->availableTools(); + delete availTools; + + VP1ToolAccessHelper toolaccess(sys); + foreach (QString instance,VP1QtUtils::environmentVariableValue("VP1_JOBCFG_EXTRA_VP1_FITTERS").split(';',QString::SkipEmptyParts)) { + if (existingFitters.contains(instance)) + continue; + sys->messageDebug("Attempting creation of fitter with tooltype/key "+instance); + Trk::ITrackFitter * tool = toolaccess.getToolPointer<Trk::ITrackFitter>(instance,false/*silent*/,true/*create if not exists*/); + if (!tool) { + sys->message("WARNING: Could not create tool with type/key "+instance); + } + } +} + +//____________________________________________________________________ +TrackSystemController::TrackSystemController(IVP1System * sys) + : VP1Controller(sys,"TrackSystemController"), m_d(new Imp) +{ + m_d->theclass = this; + m_d->lastUpdatedAvailableExtrapolators = QStringList("<dummy>");//special. + m_d->lastUpdatedAvailableFitters = QStringList("<dummy>");//special. + + //Stuff with tools waits until ::initTools() is called: + m_d->toolaccesshelper = 0; + m_d->toolhelper_extrapolators = 0; + m_d->toolhelper_fitters = 0; + m_d->matmixer = 0; + + m_d->ui.setupUi(this); + m_d->trackcollwidget = new TrackCollWidget; + setupCollWidgetInScrollArea(m_d->ui.collWidgetScrollArea,m_d->trackcollwidget); + + initDialog(m_d->ui_col, m_d->ui.pushButton_settings_colouring); + initDialog(m_d->ui_extrap, m_d->ui.pushButton_settings_extrapolation); + initDialog(m_d->ui_int, m_d->ui.pushButton_settings_interactions); + initDialog(m_d->ui_proj, m_d->ui.pushButton_settings_projections); + initDialog(m_d->ui_cuts, m_d->ui.pushButton_settings_cuts); + initDialog(m_d->ui_ascobjs, m_d->ui.pushButton_settings_details); + initDialog(m_d->ui_objBrowser, m_d->ui.pushButton_ObjectBrowser); + + //init: + m_d->numberOfSelectedPRDs=1;//anything != 0 + setNumberOfSelectedPRDsAndTracks(0,0); + + m_d->initMaterials(); + + m_d->materialFallback = new SoMaterial; + m_d->materialFallback->ref(); + + m_d->ui_cuts.etaPhiCutWidget->setSystemBasePointer(systemBase()); + + //Draw Styles / Complexity: + m_d->ascObjDrawStyle = new SoDrawStyle; + m_d->ascObjDrawStyle->setName("AscObjDrawStyle"); + m_d->ascObjDrawStyle->ref(); + addUpdateSlot(SLOT(updateAscObjDrawStyle())); + connectToLastUpdateSlot(m_d->ui_ascobjs.horizontalSlider_linewidths); + connectToLastUpdateSlot(m_d->ui_ascobjs.horizontalSlider_pointsizes); + + m_d->ascObjComplexity = new SoComplexity; + m_d->ascObjComplexity->setName("AscObjComplexity"); + m_d->ascObjComplexity->ref(); + addUpdateSlot(SLOT(updateAscObjComplexity())); + connectToLastUpdateSlot(m_d->ui_ascobjs.horizontalSlider_complexity); + + //Refit ui is dependent on env variable: + m_d->ui_int.radioButton_selmode_trackfits->setVisible(VP1QtUtils::environmentVariableIsOn("VP1_DEVEL_ENABLEREFIT")); + m_d->ui_int.groupBox_refitting->setEnabled(VP1QtUtils::environmentVariableIsOn("VP1_DEVEL_ENABLEREFIT")); + connect(m_d->ui_int.comboBox_fitterMode,SIGNAL(currentIndexChanged(int)),this,SLOT(updateFitPRDButtonState())); + + + //Disable elements based on job configuration: + + if (!(VP1JobConfigInfo::hasSCTGeometry())) { + m_d->ui_proj.checkBox_projections_indet->setChecked(false); + m_d->ui_proj.checkBox_projections_indet->setEnabled(false); + } + + //These we init explicitly since we might otherwise trigger a change + //before initlastvars (fixme: is this true and the right fix??) + m_d->last_propagator = 0; + m_d->last_trackFitter = 0; + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Setup connections which monitor changes in the controller so that we may emit signals as appropriate: // + ///////////////////////////////////////////////////////////////////////////////////////////////////////////// + + // -> shownTrackParts + addUpdateSlot(SLOT(possibleChange_shownTrackParts())); + // connectToLastUpdateSlot(m_d->ui_col.checkBox_hideactualpaths); + connectToLastUpdateSlot(m_d->ui_proj.checkBox_projections_indet); + connectToLastUpdateSlot(m_d->ui_proj.groupBox_projections_vertex); + + addUpdateSlot(SLOT(possibleChange_vertexProjectionAngle())); + connectToLastUpdateSlot(m_d->ui_proj.spinBox_projections_vertex); + + + // // -> trackTubeRadius + // addUpdateSlot(SLOT(possibleChange_trackTubeRadius())); + // connectToLastUpdateSlot(m_d->ui_col.checkBox_trackTubes); + // connectToLastUpdateSlot(m_d->ui_col.doubleSpinBox_trackTubesRadiusMM); + + // -> track labels + addUpdateSlot(SLOT(possibleChange_trackLabels())); + connectToLastUpdateSlot(m_d->ui_col.checkBox_trkLabels_Pt); + connectToLastUpdateSlot(m_d->ui_col.checkBox_trkLabels_p); + connectToLastUpdateSlot(m_d->ui_col.checkBox_trkLabels_direction); + connectToLastUpdateSlot(m_d->ui_col.checkBox_trkLabels_hits); + connectToLastUpdateSlot(m_d->ui_col.checkBox_trkLabels_pid); + connectToLastUpdateSlot(m_d->ui_col.checkBox_trkLabels_fitQuality); + connectToLastUpdateSlot(m_d->ui_col.groupBox_labels); + + addUpdateSlot(SLOT(possibleChange_trackLabelTrkOffset())); + connectToLastUpdateSlot(m_d->ui_col.horizontalSlider_labels_trkOffset); + + addUpdateSlot(SLOT(possibleChange_trackLabelPosOffset())); + connectToLastUpdateSlot(m_d->ui_col.horizontalSlider_labels_xOffset); + connectToLastUpdateSlot(m_d->ui_col.horizontalSlider_labels_yOffset); + connectToLastUpdateSlot(m_d->ui_col.horizontalSlider_labels_zOffset); + + + // -> shownTSOSParts + addUpdateSlot(SLOT(possibleChange_shownTSOSParts())); + connectToLastUpdateSlot(m_d->ui_ascobjs.groupBox_measurements); + connectToLastUpdateSlot(m_d->ui_ascobjs.groupBox_parameters); + connectToLastUpdateSlot(m_d->ui_ascobjs.groupBox_errors); + connectToLastUpdateSlot(m_d->ui_ascobjs.checkBox_parametererrors); + connectToLastUpdateSlot(m_d->ui_ascobjs.checkBox_measurementerrors); + connectToLastUpdateSlot(m_d->ui_ascobjs.checkBox_parerror_hideperigeeerrors); + connectToLastUpdateSlot(m_d->ui_ascobjs.groupBox_materialeffectsontrack); + connectToLastUpdateSlot(m_d->ui_ascobjs.checkBox_materialeffectsontrack_hideNoDE); + connectToLastUpdateSlot(m_d->ui_ascobjs.groupBox_surfaces); + connectToLastUpdateSlot(m_d->ui_ascobjs.checkBox_surfaces_hidecustomsurfaces); + connectToLastUpdateSlot(m_d->ui_ascobjs.checkBox_surfaces_hidetubesurfaces); + + addUpdateSlot(SLOT(possibleChange_drawMeasGlobalPositions())); + connectToLastUpdateSlot(m_d->ui_ascobjs.checkBox_measurements_drawGP); + + // -> customColouredTSOSParts + addUpdateSlot(SLOT(possibleChange_customColouredTSOSParts())); + + connectToLastUpdateSlot(m_d->ui_ascobjs.checkBox_usecolour_measurements); + connectToLastUpdateSlot(m_d->ui_ascobjs.checkBox_usecolour_meas_outliers); + connectToLastUpdateSlot(m_d->ui_ascobjs.checkBox_usecolour_parameters); + connectToLastUpdateSlot(m_d->ui_ascobjs.checkBox_useHoleColour_parameters); + connectToLastUpdateSlot(m_d->ui_ascobjs.checkBox_usecolour_parametererrors); + connectToLastUpdateSlot(m_d->ui_ascobjs.checkBox_usecolour_materialeffectsontrack); + connectToLastUpdateSlot(m_d->ui_ascobjs.checkBox_usecolour_surfaces); + + // -> useShortTRTMeasurements + addUpdateSlot(SLOT(possibleChange_useShortTRTMeasurements())); + connectToLastUpdateSlot(m_d->ui_ascobjs.checkBox_measurements_shorttubes_trt); + + // -> useShortMDTMeasurements + addUpdateSlot(SLOT(possibleChange_useShortMDTMeasurements())); + connectToLastUpdateSlot(m_d->ui_ascobjs.checkBox_measurements_shorttubes_mdt); + + // -> useShortMDTMeasurements + addUpdateSlot(SLOT(possibleChange_measurementsShorttubesScale())); + connectToLastUpdateSlot(m_d->ui_ascobjs.doubleSpinBox_measurements_shorttubes_scale); + + // -> nStdDevForParamErrors + addUpdateSlot(SLOT(possibleChange_nStdDevForParamErrors())); + connectToLastUpdateSlot(m_d->ui_ascobjs.doubleSpinBox_parerror_stddev); + + // -> parTubeErrorsDrawCylinders + addUpdateSlot(SLOT(possibleChange_parTubeErrorsDrawCylinders())); + connectToLastUpdateSlot(m_d->ui_ascobjs.checkBox_parerror_drawcylinder); + + // -> numberOfPointsOnCircles + addUpdateSlot(SLOT(possibleChange_numberOfPointsOnCircles())); + connectToLastUpdateSlot(m_d->ui_ascobjs.horizontalSlider_complexity); + + // -> materialEffectsOnTrackScale + addUpdateSlot(SLOT(possibleChange_materialEffectsOnTrackScale())); + connectToLastUpdateSlot(m_d->ui_ascobjs.horizontalSlider_materialeffectsontrack_scale); + + // -> selectionMode + addUpdateSlot(SLOT(possibleChange_selectionMode())); + connectToLastUpdateSlot(m_d->ui_int.radioButton_selmode_single); + connectToLastUpdateSlot(m_d->ui_int.radioButton_selmode_multitracks); + connectToLastUpdateSlot(m_d->ui_int.radioButton_selmode_trackfits); + + // -> showTruthAscObjs + addUpdateSlot(SLOT(possibleChange_showTruthAscObjs())); + connectToLastUpdateSlot(m_d->ui_ascobjs.checkBox_truthtracks_display_points); + + // -> assocObjDetailLevel + addUpdateSlot(SLOT(possibleChange_assocObjDetailLevel())); + connectToLastUpdateSlot(m_d->ui_ascobjs.comboBox_assocobj_detaillevel); + + // -> cutAllowedP/Pt + addUpdateSlot(SLOT(possibleChange_cutAllowedPt())); + connectToLastUpdateSlot(m_d->ui_cuts.checkBox_cut_minpt); + connectToLastUpdateSlot(m_d->ui_cuts.checkBox_cut_maxpt); + connectToLastUpdateSlot(m_d->ui_cuts.doubleSpinBox_cut_minpt_gev); + connectToLastUpdateSlot(m_d->ui_cuts.doubleSpinBox_cut_maxpt_gev); + connectToLastUpdateSlot(m_d->ui_cuts.comboBox_momtype); + + // -> cutAllowedEta + addUpdateSlot(SLOT(possibleChange_cutAllowedEta())); + connectToLastUpdateSlot(m_d->ui_cuts.etaPhiCutWidget,SIGNAL(allowedEtaChanged(const VP1Interval&))); + + // -> cutAllowedPhi + addUpdateSlot(SLOT(possibleChange_cutAllowedPhi())); + connectToLastUpdateSlot(m_d->ui_cuts.etaPhiCutWidget,SIGNAL(allowedPhiChanged(const QList<VP1Interval>&))); + + // -> cutRequiredNHits(); + addUpdateSlot(SLOT(possibleChange_cutRequiredNHits())); + connectToLastUpdateSlot(m_d->ui_cuts.checkBox_cut_nhits_pixel); + connectToLastUpdateSlot(m_d->ui_cuts.checkBox_cut_nhits_sct); + connectToLastUpdateSlot(m_d->ui_cuts.checkBox_cut_nhits_trt); + connectToLastUpdateSlot(m_d->ui_cuts.checkBox_cut_nhits_muon); + connectToLastUpdateSlot(m_d->ui_cuts.checkBox_cut_nprecisionhits_muon); + connectToLastUpdateSlot(m_d->ui_cuts.spinBox_cut_nhits_pixel); + connectToLastUpdateSlot(m_d->ui_cuts.spinBox_cut_nhits_sct); + connectToLastUpdateSlot(m_d->ui_cuts.spinBox_cut_nhits_trt); + connectToLastUpdateSlot(m_d->ui_cuts.spinBox_cut_nhits_muon); + connectToLastUpdateSlot(m_d->ui_cuts.spinBox_cut_nprecisionhits_muon); + + // -> cutTruthFromIROnly + addUpdateSlot(SLOT(possibleChange_cutTruthFromIROnly())); + connectToLastUpdateSlot(m_d->ui_cuts.checkBox_cut_truthtracks_creationvertexinIR); + + // -> cutExcludeBarcodeZero + addUpdateSlot(SLOT(possibleChange_cutExcludeBarcodeZero())); + connectToLastUpdateSlot(m_d->ui_cuts.checkBox_cut_truthtracks_excludebarcode0); + + // -> cutTruthExcludeNeutrals + addUpdateSlot(SLOT(possibleChange_cutTruthExcludeNeutrals())); + connectToLastUpdateSlot(m_d->ui_cuts.checkBox_cut_truthtracks_excludeneutrals); + + // -> cutOnlyVertexAssocTracks + addUpdateSlot(SLOT(possibleChange_cutOnlyVertexAssocTracks())); + connectToLastUpdateSlot(m_d->ui_cuts.checkBox_vertexAssociated); + + // -> showTotMomentumOnMultiTrackSelection + addUpdateSlot(SLOT(possibleChange_showTotMomentumOnMultiTrackSelection())); + connectToLastUpdateSlot(m_d->ui_int.checkBox_sel_showtotmom); + + // Special: -> rerandomise + connect(m_d->ui_col.pushButton_colourbyrandom_rerandomise,SIGNAL(clicked()),this,SLOT(emitRerandomise())); + + // Special: -> refit + connect(m_d->ui_int.pushButton_refit,SIGNAL(clicked()),this,SLOT(emitRefit())); + + // TrackObjBrowser + messageVerbose("Enabling object browser"); + m_d->objBrowserWidget = m_d->ui_objBrowser.treeWidget; + m_d->objBrowserWidget->setSortingEnabled(false); + QStringList l; + l<<"Object"<<"Information"; + m_d->objBrowserWidget->setHeaderLabels(l); + connect(m_d->objBrowserWidget,SIGNAL(itemClicked(QTreeWidgetItem *, int)),this,SLOT(objectBrowserClicked(QTreeWidgetItem *, int))); + + // we want "Print information" on single track selection turned ON by default + m_d->ui_int.checkBox_selsingle_printinfo->setChecked(true); + + // Since TrkVolumesSvc isn't working anymore, hardcode values. (Remove when we move to new extrapolator) + + double hardCodedMaxZ {3500.0}; + double hardCodedMinZ {-2500.0}; + m_d->calorimeterEntryLayer = new Trk::Volume(new Amg::Transform3D(Amg::Translation3D(0.0, 0.0, (hardCodedMaxZ + hardCodedMinZ)/2)), new Trk::CuboidVolumeBounds(300.0, 300.0, (hardCodedMaxZ - hardCodedMinZ)/2)); + // m_d->calorimeterEntryLayer = new Trk::Volume(0, new Trk::CylinderVolumeBounds(1100.0, 3200.0)); + // m_d->muonSpectrometerEntryLayer = new Trk::Volume(0, new Trk::CylinderVolumeBounds(4250.0, 6779.0)); + // m_d->muonSpectrometerExitLayer = new Trk::Volume(0, new Trk::CylinderVolumeBounds(15000.0, 21000.0)); // FIXME! Put in correct values. EJWM + initLastVars(); +} + +//____________________________________________________________________ +void TrackSystemController::initTools() +{ + m_d->toolaccesshelper = new VP1ToolAccessHelper(systemBase()); + + // if (VP1JobConfigInfo::hasSCTGeometry()) { + if (true) { + + //Ensure special VP1 extrapolator and fitters are created: + Imp::ensureExtrapolatorsCreated(systemBase()); + Imp::ensureFittersCreated(systemBase()); + + messageVerbose("Setting up tool helper to monitor extrapolators - start"); + m_d->toolhelper_extrapolators = new VP1AvailableToolsHelper(systemBase(),this); + //Watch for extrapolators (and Fatras extrapolators are no-go!) + m_d->toolhelper_extrapolators->addMonitoredType("Trk::Extrapolator",(QStringList() << "*Fatras*")); + connect(m_d->toolhelper_extrapolators,SIGNAL(availableToolsChanged(const QStringList&)), + this,SLOT(availableExtrapolatorsChanged(const QStringList&))); + availableExtrapolatorsChanged(m_d->toolhelper_extrapolators->availableTools()); + messageVerbose("Setting up tool helper to monitor extrapolators - end"); + + messageVerbose("Setting up tool helper to monitor fitters - start"); + m_d->toolhelper_fitters = new VP1AvailableToolsHelper(systemBase(),this); + QStringList fittertypes; + fittertypes << "Trk::KalmanFitter" + << "Trk::GlobalChi2Fitter" + << "Trk::GaussianSumFilter" + << "Trk::DistributedKalmanFilter" + << "Trk::DeterministicAnnealingFilter"; + m_d->toolhelper_fitters->addMonitoredTypes(fittertypes); + connect(m_d->toolhelper_fitters,SIGNAL(availableToolsChanged(const QStringList&)), + this,SLOT(availableFittersChanged(const QStringList&))); + availableFittersChanged(m_d->toolhelper_fitters->availableTools()); + messageVerbose("Setting up tool helper to monitor fitters - end"); + } else { + m_d->toolhelper_extrapolators = 0; + m_d->toolhelper_fitters = 0; + m_d->ui_extrap.comboBox_propagator->clear(); + m_d->ui_extrap.comboBox_propagator->addItem(Imp::noneAvailString); + m_d->ui_extrap.comboBox_propagator->setEnabled(false); + m_d->ui_extrap.radioButton_athenaExtrapolator->setEnabled(false); + m_d->ui_extrap.radioButton_none->setChecked(true); + m_d->ui_int.comboBox_fitters->clear(); + m_d->ui_int.comboBox_fitters->addItem(Imp::noneAvailString); + m_d->ui_int.comboBox_fitters->setEnabled(false); + //FIXME: Disable radioButton_selmode_trackfits, comboBox_fitters, lineEdit_fittedTrackCollName, pushButton_refit + } + + // -> propagator + // + addUpdateSlot(SLOT(possibleChange_propagator())); + connectToLastUpdateSlot(m_d->ui_extrap.radioButton_none); + connectToLastUpdateSlot(m_d->ui_extrap.radioButton_athenaExtrapolator); + connectToLastUpdateSlot(m_d->ui_extrap.comboBox_propagator); + + addUpdateSlot(SLOT(possibleChange_propagationOptions())); + connectToLastUpdateSlot(m_d->ui_extrap.checkBox_ignoreMEoT); + connectToLastUpdateSlot(m_d->ui_extrap.checkBox_extendAllTracks); + connectToLastUpdateSlot(m_d->ui_extrap.comboBox_extendAllTracksToHere); + m_d->last_propagationOptions=TrackSystemController::NoPropOptions; + if (m_d->ui_extrap.checkBox_ignoreMEoT->isChecked()) m_d->last_propagationOptions |= TrackSystemController::IgnoreMEOT; //!< Really needed here??? FIXME + if (m_d->ui_extrap.checkBox_extendAllTracks->isChecked()) m_d->last_propagationOptions |= TrackSystemController::ExtendTrack; //!< Really needed here??? FIXME + + addUpdateSlot(SLOT(possibleChange_propMaxRadius())); + connectToLastUpdateSlot(m_d->ui_extrap.checkBox_maxRadius); + connectToLastUpdateSlot(m_d->ui_extrap.spinBox_maxRadiusValue); + + connect(m_d->ui_extrap.comboBox_extendAllTracksToHere, SIGNAL(currentIndexChanged(int)),this, SLOT(emitExtrapolateToHereChanged(int))); + // -> trackFitter + addUpdateSlot(SLOT(possibleChange_trackFitter())); + //(Nothing connects directly to this slot) + + //could also use testForChanges() here: + possibleChange_propagator(); + possibleChange_trackFitter(); +} + +//____________________________________________________________________ +SoMaterial * TrackSystemController::Imp::createMaterial(const int& r,const int& g,const int& b) const +{ + return VP1MaterialButton::createMaterial(r/255.0,g/255.0,b/255.0,0.2/*brightness*/); +} + +//____________________________________________________________________ + +void TrackSystemController::Imp::initMaterials() +{ + //By PID => Electrons and muons:. + ui_col.matButton_electrons->setMaterial(createMaterial(255,0,0)); //red; //(205,103,255));//purple + ui_col.matButton_muons->setMaterial(createMaterial(71,255,51));//green + + //By PID => Charged: bluish colours + ui_col.matButton_pions->setMaterial(createMaterial(74,146,255)); + ui_col.matButton_protons->setMaterial(createMaterial(56,49,255)); + ui_col.matButton_chargedkaons->setMaterial(createMaterial(116,255,228)); + ui_col.matButton_othercharged->setMaterial(createMaterial(142,163,255)); + + //By PID => Neutral yellowish colours. + ui_col.matButton_neutrons->setMaterial(createMaterial(245,255,42)); + ui_col.matButton_photons->setMaterial(createMaterial(255,227,82)); + ui_col.matButton_neutrinos->setMaterial(createMaterial(255,152,61)); + ui_col.matButton_otherneutrals->setMaterial(createMaterial(248,255,102)); + + //By charge: + ui_col.matButton_charge_pos->setMaterial(createMaterial(255,71,10)); + ui_col.matButton_charge_neg->setMaterial(createMaterial(116,255,10)); + ui_col.matButton_charge_neutral->setMaterial(createMaterial(255,227,82)); + + //By momentum: + ui_col.matButton_0GeV->setMaterial(createMaterial(0,50,0)); + ui_col.matButton_15GeV->setMaterial(createMaterial(0,255,0)); + + //Associated objects: + ui_ascobjs.matButton_measurements->setMaterial(createMaterial(55,200,55)); + ui_ascobjs.matButton_meas_outliers->setMaterial(createMaterial(155,155,155)); + ui_ascobjs.matButton_parameters->setMaterial(createMaterial(100,150,200)); + ui_ascobjs.matButton_holeParameters->setMaterial(createMaterial(100,100,100)); + ui_ascobjs.matButton_parerrors->setMaterial(createMaterial(255,100,0)); + SoMaterial * materialeffectsontrackMat = createMaterial(200,255,75); + materialeffectsontrackMat->transparency=0.5; + ui_ascobjs.matButton_materialeffectsontrack->setMaterial(materialeffectsontrackMat); + ui_ascobjs.matButton_surfaces->setMaterial(createMaterial(228,210,165)); +} + +//____________________________________________________________________ +TrackSystemController::~TrackSystemController() +{ + messageVerbose("~TrackSystemController begin"); + delete m_d->toolaccesshelper; + delete m_d->matmixer; + m_d->materialFallback->unref(); + // m_d->trackDrawStyle->unref(); + // m_d->trackLightModel->unref(); + m_d->ascObjDrawStyle->unref(); + m_d->ascObjComplexity->unref(); + + delete m_d->calorimeterEntryLayer ; + + // delete m_d->objBrowserWidget; + delete m_d; + messageVerbose("~TrackSystemController end"); +} + +//____________________________________________________________________ +int TrackSystemController::currentSettingsVersion() const +{ + return 17; +} + +//____________________________________________________________________ +void TrackSystemController::actualSaveSettings(VP1Serialise&s) const +{ + messageVerbose("TrackSystemController::actualSaveSettings()"); + + /* + * NOTE!!! Important, about serialization: + * + * - order has to be the same between saving-reading + * + * See: http://www.mimec.org/node/348 + * + */ + + messageDebug("Serialize - current version: "+QString::number( s.version() )); + + // saving a string, which will be checked while restoring the values + s.save(QString("TrackSystemSettings")); + + //versions <= 3 saved an integer here + + //Display options: linewidth: + // s.save(VP1QtInventorUtils::getValueLineWidthSlider(m_d->ui_col.horizontalSlider_trackWidth));//Version 1+ GONE WITH VERSION 17 + // s.widgetHandled(m_d->ui_col.horizontalSlider_trackWidth); + + //Tracks base light model: + // s.save(m_d->ui_col.checkBox_tracksUseBaseLightModel);//version 4+ GONE WITH VERSION 17 + + // --- Projections options --- + s.save(QString("Projections options")); + s.save(m_d->ui_proj.checkBox_projections_indet); + s.save(m_d->ui_proj.checkBox_projections_muonchambers); + s.save(m_d->ui_proj.groupBox_projections_vertex); //v15 + s.save(m_d->ui_proj.spinBox_projections_vertex);//v15 + s.save(m_d->ui_proj.horizontalSlider_projections_vertex);//v15 + // s.save(m_d->ui_col.checkBox_hideactualpaths); GONE WITH VERSION 17 + // --------------------------- + + + //Display options - track tubes + // s.save(m_d->ui_col.checkBox_trackTubes);//version 8+ GONE WITH VERSION 17 + // s.save(m_d->ui_col.doubleSpinBox_trackTubesRadiusMM);//version 8+ GONE WITH VERSION 17 + + //Version <= 3 had bool here + + + // ----- Propagation options ----- + s.save(QString("Propagation options")); + s.save(m_d->ui_extrap.radioButton_none, + m_d->ui_extrap.radioButton_helical, + m_d->ui_extrap.radioButton_athenaExtrapolator);//version 4+ + s.save(m_d->ui_extrap.comboBox_propagator);//NB: We restore this in a slightly special way + // ----------------------------------- + + + + + // ----- Interactions options ----- + s.save(QString("Interactions options")); + s.save(m_d->ui_int.lineEdit_fittedTrackCollName);//version 6+ + s.save(m_d->ui_int.comboBox_fitters);//version 6+ + // ----------------------------------- + + + + //Version <=2 had bool here + + //version 0 output an integer followed by two bools here + + //Display options - Trk::Tracks + //Version <=2 had bool here + s.save(m_d->ui_ascobjs.comboBox_assocobj_detaillevel); + //Version <=2 had two bool here + + //Display options - Truth tracks: + s.save(m_d->ui_ascobjs.checkBox_truthtracks_display_points); + + // --- Display options - Colours --- + s.save(QString("Colour options")); + //Display options - Colour by pdg: + s.save(m_d->ui_col.matButton_electrons); + s.save(m_d->ui_col.matButton_muons); + s.save(m_d->ui_col.matButton_pions); + s.save(m_d->ui_col.matButton_protons); + s.save(m_d->ui_col.matButton_chargedkaons); + s.save(m_d->ui_col.matButton_othercharged); + s.save(m_d->ui_col.matButton_neutrons); + s.save(m_d->ui_col.matButton_photons); + s.save(m_d->ui_col.matButton_neutrinos); + s.save(m_d->ui_col.matButton_otherneutrals); + + //Display options - Colour by charge: + s.save(m_d->ui_col.matButton_charge_neg);//version 2+ + s.save(m_d->ui_col.matButton_charge_pos);//version 2+ + s.save(m_d->ui_col.matButton_charge_neutral);//version 2+ + + //Display options - Colour by momentum: + s.save(m_d->ui_col.matButton_0GeV);//version 2+ + s.save(m_d->ui_col.matButton_15GeV);//version 2+ + // ----------------------------------- + + + + + + + + + // --- Cuts options --- + s.save(QString("Cuts options")); + //Cuts - general: + s.save(m_d->ui_cuts.checkBox_cut_minpt); + s.save(m_d->ui_cuts.doubleSpinBox_cut_minpt_gev); + s.save(m_d->ui_cuts.checkBox_cut_maxpt); + s.save(m_d->ui_cuts.doubleSpinBox_cut_maxpt_gev); + s.save(m_d->ui_cuts.comboBox_momtype);// version 10+ + + s.save(m_d->ui_cuts.etaPhiCutWidget);//Version 7+ + //Versions <=6 had 2*bool, 2*double, 1*bool, 1*obsoletephisectionstate here. + + //Cuts - number of hits: + s.save(m_d->ui_cuts.checkBox_cut_nhits_pixel);//Version 9+ + s.save(m_d->ui_cuts.checkBox_cut_nhits_sct);//Version 9+ + s.save(m_d->ui_cuts.checkBox_cut_nhits_trt);//Version 9+ + s.save(m_d->ui_cuts.checkBox_cut_nhits_muon);//Version 9+ + s.save(m_d->ui_cuts.spinBox_cut_nhits_pixel);//Version 9+ + s.save(m_d->ui_cuts.spinBox_cut_nhits_sct);//Version 9+ + s.save(m_d->ui_cuts.spinBox_cut_nhits_trt);//Version 9+ + s.save(m_d->ui_cuts.spinBox_cut_nhits_muon);//Version 9+ + + //Cuts - truth: + s.save(m_d->ui_cuts.checkBox_cut_truthtracks_creationvertexinIR); + s.save(m_d->ui_cuts.checkBox_cut_truthtracks_excludeneutrals); + s.save(m_d->ui_cuts.checkBox_cut_truthtracks_excludebarcode0); + + s.save(m_d->ui_cuts.checkBox_vertexAssociated);//Version 14+ + // ----------------------------------- + + + + + + + // --- Interactions options --- + s.save(QString("Interactions options")); + //Interactions - selection mode: + s.save(m_d->ui_int.radioButton_selmode_single, + m_d->ui_int.radioButton_selmode_multitracks, + m_d->ui_int.radioButton_selmode_trackfits); + + s.save(m_d->ui_int.checkBox_selsingle_printinfo); + s.save(m_d->ui_int.checkBox_selsingle_printinfo_verbose); + s.save(m_d->ui_int.checkBox_selsingle_orientzoom); + s.save(m_d->ui_int.checkBox_sel_printtotmom); + s.save(m_d->ui_int.checkBox_sel_showtotmom); + s.save(m_d->ui_int.comboBox_fitterMode); // Version 12+ + s.save(m_d->ui_int.checkBox_removeOutliers);// Version 12+ + s.save(m_d->ui_int.comboBox_particleHypo);// Version 12+ + // ----------------------------------- + + + + + // --- AscObjs options --- + s.save(QString("AscObjs options")); + //AscObjs - TSOS: + s.save(m_d->ui_ascobjs.checkBox_materialeffectsontrack_forceposontrack); + s.save(m_d->ui_ascobjs.checkBox_materialeffectsontrack_hideNoDE); + s.save(m_d->ui_ascobjs.checkBox_measurements_shorttubes_mdt); + s.save(m_d->ui_ascobjs.checkBox_measurements_shorttubes_trt); + s.save(m_d->ui_ascobjs.checkBox_measurements_drawGP); // Version 11 + s.save(m_d->ui_ascobjs.checkBox_parerror_drawcylinder); + s.save(m_d->ui_ascobjs.checkBox_parerror_hideperigeeerrors); + s.save(m_d->ui_ascobjs.checkBox_surfaces_hidecustomsurfaces); + s.save(m_d->ui_ascobjs.checkBox_surfaces_hidetubesurfaces); // Version 11 + s.save(m_d->ui_ascobjs.checkBox_usecolour_materialeffectsontrack); + s.save(m_d->ui_ascobjs.checkBox_usecolour_meas_outliers); + s.save(m_d->ui_ascobjs.checkBox_usecolour_measurements); + s.save(m_d->ui_ascobjs.checkBox_usecolour_parametererrors); + s.save(m_d->ui_ascobjs.checkBox_usecolour_parameters); + s.save(m_d->ui_ascobjs.checkBox_useHoleColour_parameters);// Version 14 + s.save(m_d->ui_ascobjs.checkBox_usecolour_surfaces); + + s.save(m_d->ui_ascobjs.doubleSpinBox_parerror_stddev); + s.save(m_d->ui_ascobjs.groupBox_materialeffectsontrack); + s.save(m_d->ui_ascobjs.groupBox_measurements); + s.save(m_d->ui_ascobjs.groupBox_errors);// Version 13 + s.save(m_d->ui_ascobjs.checkBox_parametererrors);// Version 13 + s.save(m_d->ui_ascobjs.checkBox_measurementerrors);// Version 13 + s.save(m_d->ui_ascobjs.groupBox_parameters); + s.save(m_d->ui_ascobjs.groupBox_surfaces); + s.save(m_d->ui_ascobjs.horizontalSlider_complexity); + s.save(m_d->ui_ascobjs.horizontalSlider_linewidths);//FIXME!!! SAVE AS ABOVE INSTEAD!! + s.save(m_d->ui_ascobjs.horizontalSlider_materialeffectsontrack_scale); + s.save(m_d->ui_ascobjs.horizontalSlider_pointsizes);//FIXME!!! SAVE AS ABOVE INSTEAD!! + s.save(m_d->ui_ascobjs.matButton_materialeffectsontrack); + s.save(m_d->ui_ascobjs.matButton_meas_outliers); + s.save(m_d->ui_ascobjs.matButton_measurements); + s.save(m_d->ui_ascobjs.matButton_parameters); + s.save(m_d->ui_ascobjs.matButton_holeParameters);// Version 14 + s.save(m_d->ui_ascobjs.matButton_parerrors); + s.save(m_d->ui_ascobjs.matButton_surfaces); + s.save(m_d->ui_ascobjs.doubleSpinBox_measurements_shorttubes_scale);//Version 5+ + // ----------------------------------- + + + + + // ----- Colouring options ----- + s.save(QString("Colouring options")); + // Version 12 + s.save(m_d->ui_col.groupBox_labels); + s.save(m_d->ui_col.horizontalSlider_labels_trkOffset); + s.save(m_d->ui_col.horizontalSlider_labels_xOffset); + s.save(m_d->ui_col.horizontalSlider_labels_yOffset); + s.save(m_d->ui_col.horizontalSlider_labels_zOffset); + s.save(m_d->ui_col.checkBox_trkLabels_p); + s.save(m_d->ui_col.checkBox_trkLabels_Pt); + s.save(m_d->ui_col.checkBox_trkLabels_pid); + s.save(m_d->ui_col.checkBox_trkLabels_hits); + s.save(m_d->ui_col.checkBox_trkLabels_fitQuality); + s.save(m_d->ui_col.checkBox_trkLabels_direction); + // -------------------------- + + + + + + + // ----- Extrap options ----- + s.save(QString("Extrapolator options")); + s.save(m_d->ui_extrap.checkBox_ignoreMEoT); // Version 14 + s.save(m_d->ui_extrap.checkBox_extendAllTracks); + s.save(m_d->ui_extrap.comboBox_extendAllTracksToHere); + s.save(m_d->ui_extrap.horizontalSlider_granularity); + s.save(m_d->ui_extrap.checkBox_maxRadius); // Version 15 + s.save(m_d->ui_extrap.spinBox_maxRadiusValue); + // -------------------------- + + + messageVerbose("TrackSystemController::actualSaveSettings() - DONE."); + +} + +//____________________________________________________________________ +void TrackSystemController::actualRestoreSettings(VP1Deserialise& s) +{ + messageDebug("TrackSystemController::actualRestoreSettings()"); + + /* + * NOTE!!! Important, about serialization: + * + * - order has to be the same between saving-reading + * + * See: http://www.mimec.org/node/348 + * + */ + + messageDebug("Deserialize - current version: "+QString::number( s.version() )); + + if (s.version()<0||s.version()>currentSettingsVersion()) { + message("Warning: State data in .vp1 file has unsupported version ("+str(s.version())+")"); + return; + } + + if (s.version()<17) { + message("Warning: the VP1 GUI has changed since .vp1 file format version ("+str(s.version())+"), which means you will have lost the line thickness etc. settings formally found in the Colouring pop-up dialogue."); + } + + if (s.version()<17) { + s.ignoreString(); + } else { + QString tt = s.restoreString(); + messageDebug("Check string: " + tt); + if (tt != "TrackSystemSettings") { + messageDebug("\n\nERROR!! Settings order does not match!!"); + return; + } + } + + if (s.version()<=3) + s.ignoreInt(); + + // //Display options: linewidth: + // if (s.version()>=1) { + // VP1QtInventorUtils::setValueLineWidthSlider(m_d->ui_col.horizontalSlider_trackWidth,s.restoreDouble()); + // s.widgetHandled(m_d->ui_col.horizontalSlider_trackWidth); + // } + if (s.version()<17) + s.ignoreInt(); //m_d->ui_col.horizontalSlider_trackWidth + + //Tracks base light model: + // if (s.version()>=4) + // s.restore(m_d->ui_col.checkBox_tracksUseBaseLightModel); + if (s.version()<17) + s.ignoreBool(); //m_d->ui_col.checkBox_tracksUseBaseLightModel + + + + + + // --- Projections options --- + if (s.version()>=17 && s.restoreString() != "Projections options") messageDebug("\n\nERROR! --> 'Projections options'"); + s.restore(m_d->ui_proj.checkBox_projections_indet); + s.restore(m_d->ui_proj.checkBox_projections_muonchambers); + if (s.version()>=15){ + s.restore(m_d->ui_proj.groupBox_projections_vertex); + s.restore(m_d->ui_proj.spinBox_projections_vertex); + s.restore(m_d->ui_proj.horizontalSlider_projections_vertex); + } + // s.restore(m_d->ui_col.checkBox_hideactualpaths); + if (s.version()<17) + s.ignoreBool(); //m_d->ui_col.checkBox_hideactualpaths + // -------------------------------------- + + + + + //Display options - track tubes + // if (s.version()>=8) { + // s.restore(m_d->ui_col.checkBox_trackTubes); + // s.restore(m_d->ui_col.doubleSpinBox_trackTubesRadiusMM); + // } + if (s.version()<17){ + s.ignoreBool(); //m_d->ui_col.checkBox_trackTubes + s.ignoreDouble(); //m_d->ui_col.doubleSpinBox_trackTubesRadiusMM + } + + if (s.version()<=3) + s.ignoreBool(); + + + + + // ----- Propagation options ----- + if (s.version()>=17 && s.restoreString() != "Propagation options") messageDebug("\n\nERROR! --> 'Propagation options'"); + if (s.version()>=4) + s.restore(m_d->ui_extrap.radioButton_none, + m_d->ui_extrap.radioButton_helical, + m_d->ui_extrap.radioButton_athenaExtrapolator); + m_d->restoredLastPropagator = s.restoreString(); + s.widgetHandled(m_d->ui_extrap.comboBox_propagator); + // ----------------------------------- + + + + + // ----- Interactions options ----- + if (s.version()>=17 && s.restoreString() != "Interactions options") messageDebug("\n\nERROR! --> 'Interactions options'"); + if (s.version()>=6) { + s.restore(m_d->ui_int.lineEdit_fittedTrackCollName); + m_d->restoredLastFitter = s.restoreString(); + s.widgetHandled(m_d->ui_int.comboBox_fitters); + } + // ----------------------------------- + + + + + if (s.version()<=2) + s.ignoreBool(); + + if (s.version()==0) { + s.ignoreInt(); + s.ignoreBool(); + s.ignoreBool(); + } + + //Display options - Trk::Tracks + if (s.version()<=2) + s.ignoreBool(); + s.restore(m_d->ui_ascobjs.comboBox_assocobj_detaillevel); + if (s.version()<=2) { + s.ignoreBool(); + s.ignoreBool(); + } + + //Display options - Truth tracks: + s.restore(m_d->ui_ascobjs.checkBox_truthtracks_display_points); + + + // --- Display options - Colours --- + if (s.version()>=17 && s.restoreString() != "Colour options") messageDebug("\n\nERROR! --> 'Colour options'"); + //Display options - Colour by pdg: + s.restore(m_d->ui_col.matButton_electrons); + s.restore(m_d->ui_col.matButton_muons); + s.restore(m_d->ui_col.matButton_pions); + s.restore(m_d->ui_col.matButton_protons); + s.restore(m_d->ui_col.matButton_chargedkaons); + s.restore(m_d->ui_col.matButton_othercharged); + s.restore(m_d->ui_col.matButton_neutrons); + s.restore(m_d->ui_col.matButton_photons); + s.restore(m_d->ui_col.matButton_neutrinos); + s.restore(m_d->ui_col.matButton_otherneutrals); + if (s.version()>=2) { + //Display options - Colour by charge: + s.restore(m_d->ui_col.matButton_charge_neg); + s.restore(m_d->ui_col.matButton_charge_pos); + s.restore(m_d->ui_col.matButton_charge_neutral); + + //Display options - Colour by momentum: + s.restore(m_d->ui_col.matButton_0GeV); + s.restore(m_d->ui_col.matButton_15GeV); + } + // ----------------------------------- + + + + + + // --- Cuts options --- + if (s.version()>=17 && s.restoreString() != "Cuts options") messageDebug("\n\nERROR! --> 'Cuts options'"); + //Cuts - general: + s.restore(m_d->ui_cuts.checkBox_cut_minpt); + s.restore(m_d->ui_cuts.doubleSpinBox_cut_minpt_gev); + s.restore(m_d->ui_cuts.checkBox_cut_maxpt); + s.restore(m_d->ui_cuts.doubleSpinBox_cut_maxpt_gev); + + if (s.version()>=10) { + s.restore(m_d->ui_cuts.comboBox_momtype); + } + + if (s.version()>=7) { + s.restore(m_d->ui_cuts.etaPhiCutWidget); + } else { + s.ignoreBool(); + s.ignoreBool(); + s.ignoreDouble(); + s.ignoreDouble(); + s.ignoreBool(); + s.ignoreObsoletePhiSectionWidgetState(); + } + + if (s.version()>=9) { + s.restore(m_d->ui_cuts.checkBox_cut_nhits_pixel); + s.restore(m_d->ui_cuts.checkBox_cut_nhits_sct); + s.restore(m_d->ui_cuts.checkBox_cut_nhits_trt); + s.restore(m_d->ui_cuts.checkBox_cut_nhits_muon); + s.restore(m_d->ui_cuts.spinBox_cut_nhits_pixel); + s.restore(m_d->ui_cuts.spinBox_cut_nhits_sct); + s.restore(m_d->ui_cuts.spinBox_cut_nhits_trt); + s.restore(m_d->ui_cuts.spinBox_cut_nhits_muon); + } + + //Cuts - truth: + s.restore(m_d->ui_cuts.checkBox_cut_truthtracks_creationvertexinIR); + s.restore(m_d->ui_cuts.checkBox_cut_truthtracks_excludeneutrals); + s.restore(m_d->ui_cuts.checkBox_cut_truthtracks_excludebarcode0); + + if (s.version()>=14) s.restore(m_d->ui_cuts.checkBox_vertexAssociated); + // ----------------------------------- + + + + + + // --- Interactions options --- + if (s.version()>=17 && s.restoreString() != "Interactions options") messageDebug("\n\nERROR! --> 'Interactions options'"); + //Interactions - selection mode: + s.restore(m_d->ui_int.radioButton_selmode_single, + m_d->ui_int.radioButton_selmode_multitracks, + m_d->ui_int.radioButton_selmode_trackfits); + + s.restore(m_d->ui_int.checkBox_selsingle_printinfo); + s.restore(m_d->ui_int.checkBox_selsingle_printinfo_verbose); + s.restore(m_d->ui_int.checkBox_selsingle_orientzoom); + s.restore(m_d->ui_int.checkBox_sel_printtotmom); + s.restore(m_d->ui_int.checkBox_sel_showtotmom); + if (s.version()>=12){ + s.restore(m_d->ui_int.comboBox_fitterMode); + s.restore(m_d->ui_int.checkBox_removeOutliers); + s.restore(m_d->ui_int.comboBox_particleHypo); + } + // ----------------------------------- + + + + + + + + // --- AscObjs options --- + if (s.version()>=17 && s.restoreString() != "AscObjs options") messageDebug("\n\nERROR! --> 'AscObjs options'"); + //AscObjs - TSOS: + s.restore(m_d->ui_ascobjs.checkBox_materialeffectsontrack_forceposontrack); + s.restore(m_d->ui_ascobjs.checkBox_materialeffectsontrack_hideNoDE); + s.restore(m_d->ui_ascobjs.checkBox_measurements_shorttubes_mdt); + s.restore(m_d->ui_ascobjs.checkBox_measurements_shorttubes_trt); + if (s.version()>=11) s.restore(m_d->ui_ascobjs.checkBox_measurements_drawGP); + s.restore(m_d->ui_ascobjs.checkBox_parerror_drawcylinder); + s.restore(m_d->ui_ascobjs.checkBox_parerror_hideperigeeerrors); + s.restore(m_d->ui_ascobjs.checkBox_surfaces_hidecustomsurfaces); + if (s.version()>=11) s.restore(m_d->ui_ascobjs.checkBox_surfaces_hidetubesurfaces); + s.restore(m_d->ui_ascobjs.checkBox_usecolour_materialeffectsontrack); + s.restore(m_d->ui_ascobjs.checkBox_usecolour_meas_outliers); + s.restore(m_d->ui_ascobjs.checkBox_usecolour_measurements); + if (s.version()<12) s.restore(m_d->ui_ascobjs.checkBox_parametererrors); // was groupBox_parametererrors before... + s.restore(m_d->ui_ascobjs.checkBox_usecolour_parametererrors); + s.restore(m_d->ui_ascobjs.checkBox_usecolour_parameters); + if (s.version()>=14) + s.restore(m_d->ui_ascobjs.checkBox_useHoleColour_parameters); + s.restore(m_d->ui_ascobjs.checkBox_usecolour_surfaces); + s.restore(m_d->ui_ascobjs.doubleSpinBox_parerror_stddev); + s.restore(m_d->ui_ascobjs.groupBox_materialeffectsontrack); + s.restore(m_d->ui_ascobjs.groupBox_measurements); + if (s.version()>=12) { + s.restore(m_d->ui_ascobjs.groupBox_errors); + s.restore(m_d->ui_ascobjs.checkBox_parametererrors); + s.restore(m_d->ui_ascobjs.checkBox_measurementerrors); + } + s.restore(m_d->ui_ascobjs.groupBox_parameters); + s.restore(m_d->ui_ascobjs.groupBox_surfaces); + s.restore(m_d->ui_ascobjs.horizontalSlider_complexity); + s.restore(m_d->ui_ascobjs.horizontalSlider_linewidths);//FIXME!!! SAVE AS ABOVE INSTEAD!! + s.restore(m_d->ui_ascobjs.horizontalSlider_materialeffectsontrack_scale); + s.restore(m_d->ui_ascobjs.horizontalSlider_pointsizes);//FIXME!!! SAVE AS ABOVE INSTEAD!! + s.restore(m_d->ui_ascobjs.matButton_materialeffectsontrack); + s.restore(m_d->ui_ascobjs.matButton_meas_outliers); + s.restore(m_d->ui_ascobjs.matButton_measurements); + s.restore(m_d->ui_ascobjs.matButton_parameters); + if (s.version()>=14) + s.restore(m_d->ui_ascobjs.matButton_holeParameters); + s.restore(m_d->ui_ascobjs.matButton_parerrors); + s.restore(m_d->ui_ascobjs.matButton_surfaces); + if (s.version()>=5) + s.restore(m_d->ui_ascobjs.doubleSpinBox_measurements_shorttubes_scale); + // ----------------------------------- + + + + + + + //Interactions - track fits: + + + + // ----- Colouring options ----- + if (s.version()>=17 && s.restoreString() != "Colouring options") messageDebug("\n\nERROR! --> 'Colouring options'"); + if (s.version()>=12){ + s.restore(m_d->ui_col.groupBox_labels); + s.restore(m_d->ui_col.horizontalSlider_labels_trkOffset); + s.restore(m_d->ui_col.horizontalSlider_labels_xOffset); + s.restore(m_d->ui_col.horizontalSlider_labels_yOffset); + s.restore(m_d->ui_col.horizontalSlider_labels_zOffset); + s.restore(m_d->ui_col.checkBox_trkLabels_p); + s.restore(m_d->ui_col.checkBox_trkLabels_Pt); + s.restore(m_d->ui_col.checkBox_trkLabels_pid); + s.restore(m_d->ui_col.checkBox_trkLabels_hits); + s.restore(m_d->ui_col.checkBox_trkLabels_fitQuality); + } + if (s.version()>=16) + s.restore(m_d->ui_col.checkBox_trkLabels_direction); + + + + + + // ----- Extrap options ----- + // Version 14 + if (s.version()>=17 && s.restoreString() != "Extrapolator options") messageDebug("\n\nERROR! --> 'Extrapolator options'"); + if (s.version()>=14){ + s.restore(m_d->ui_extrap.checkBox_ignoreMEoT); + s.restore(m_d->ui_extrap.checkBox_extendAllTracks); + s.restore(m_d->ui_extrap.comboBox_extendAllTracksToHere); + s.restore(m_d->ui_extrap.horizontalSlider_granularity); + } + // version 15 + if (s.version()>=15){ + s.restore(m_d->ui_extrap.checkBox_maxRadius); + s.restore(m_d->ui_extrap.spinBox_maxRadiusValue); + } + // ------------------------------ + + + + messageDebug("TrackSystemController::actualRestoreSettings() - DONE."); + +} + +//____________________________________________________________________ +TrackCollWidget * TrackSystemController::collWidget() const +{ + return m_d->trackcollwidget; +} + +//Access methods: + +//____________________________________________________________________ +SoMaterial * TrackSystemController::Imp::getMat(VP1MaterialButton* mb) const +{ + if (!mb) { + theclass->message("ERROR: Null material button pointer"); + return materialFallback; + } + QList<SoMaterial*> mats = mb->handledMaterials(); + if (mats.count()!=1) { + theclass->message("ERROR: No material in button"); + return materialFallback; + } + return mats.at(0); +} + +//____________________________________________________________________ +SoMaterial * TrackSystemController::getMaterialForPDGCode(const int& pdgCode) const +{ + VP1MaterialButton * matbutton(0); + int abspdg = abs(pdgCode); + switch (abspdg) { + case 211: matbutton = m_d->ui_col.matButton_pions; break; + case 11: matbutton = m_d->ui_col.matButton_electrons; break; + case 22: matbutton = m_d->ui_col.matButton_photons; break; + case 13: matbutton = m_d->ui_col.matButton_muons; break; + case 2212: matbutton = m_d->ui_col.matButton_protons; break; + case 2112: matbutton = m_d->ui_col.matButton_neutrons; break; + case 2: return m_d->materialFallback; + //Only use CHARGED kaons here!! + // case 130://k-long + // case 310://k-short + // case 311://k0 + case 321://k+ + // case 313://k*0 + case 323://k*+ + //Fixme: More (charged) kaon states??? + matbutton = m_d->ui_col.matButton_chargedkaons; break; + case 12://nu_e + case 14://nu_mu + case 16://nu_tau + case 18://fourth gen. neutrino: + matbutton = m_d->ui_col.matButton_neutrinos; break; + default: + bool ok; + double charge; + charge = VP1ParticleData:: particleCharge(abspdg,ok); + if (!ok) { + message("WARNING: Could not look up charge of pdg code "+str(abspdg)+". Assuming charged."); + charge = 1.0; + } + if (charge==0.0) + matbutton = m_d->ui_col.matButton_otherneutrals; + else + matbutton = m_d->ui_col.matButton_othercharged; + break; + } + return m_d->getMat(matbutton); +} + +//____________________________________________________________________ +SoMaterial * TrackSystemController::getMaterialForCharge(const double& charge) const +{ + if (charge>0) + return m_d->getMat(m_d->ui_col.matButton_charge_pos); + else if (charge<0) + return m_d->getMat(m_d->ui_col.matButton_charge_neg); + return m_d->getMat(m_d->ui_col.matButton_charge_neutral); +} + +//____________________________________________________________________ +SoMaterial * TrackSystemController::getMaterialForMomentum(const double& absmom) const +{ + static const double low=0*CLHEP::GeV; + static const double high=15*CLHEP::GeV; + if (absmom<=low) + return m_d->getMat(m_d->ui_col.matButton_0GeV); + else if (absmom>=high) + return m_d->getMat(m_d->ui_col.matButton_15GeV); + + if (!m_d->matmixer) + m_d->matmixer = new VP1SoMaterialMixer(systemBase()); + + const double x = (absmom-low)/(high-low); + return m_d->matmixer->getMixedMaterial( m_d->getMat(m_d->ui_col.matButton_0GeV), 1-x, + m_d->getMat(m_d->ui_col.matButton_15GeV), x ); +} + +//____________________________________________________________________ +SoMaterial * TrackSystemController::customMatMeasurements() const +{ + return m_d->getMat(m_d->ui_ascobjs.matButton_measurements); +} + +//____________________________________________________________________ +SoMaterial * TrackSystemController::customMatMeasurementsOutliers() const +{ + return m_d->getMat(m_d->ui_ascobjs.matButton_meas_outliers); +} + +//____________________________________________________________________ +SoMaterial * TrackSystemController::customMatParameters() const +{ + return m_d->getMat(m_d->ui_ascobjs.matButton_parameters); +} + +//____________________________________________________________________ +SoMaterial * TrackSystemController::customMatHoleParameters() const +{ + return m_d->getMat(m_d->ui_ascobjs.matButton_holeParameters); +} + +//____________________________________________________________________ +SoMaterial * TrackSystemController::customMatParameterErrors() const +{ + return m_d->getMat(m_d->ui_ascobjs.matButton_parerrors); +} + +//____________________________________________________________________ +SoMaterial * TrackSystemController::customMatMaterialEffects() const +{ + return m_d->getMat(m_d->ui_ascobjs.matButton_materialeffectsontrack); +} + +//____________________________________________________________________ +SoMaterial * TrackSystemController::customMatSurfaces() const +{ + return m_d->getMat(m_d->ui_ascobjs.matButton_surfaces); +} + +// //____________________________________________________________________ +// void TrackSystemController::updateTrackDrawStyle() +// { +// double val = VP1QtInventorUtils::getValueLineWidthSlider(m_d->ui_col.horizontalSlider_trackWidth); +// if (m_d->trackDrawStyle->lineWidth.getValue()!=val) +// m_d->trackDrawStyle->lineWidth = val; +// } + +// //____________________________________________________________________ +// void TrackSystemController::updateTrackLightModel() +// { +// bool base = m_d->ui_col.checkBox_tracksUseBaseLightModel->isChecked(); +// if (m_d->trackLightModel->model.getValue()!=(base?SoLightModel::BASE_COLOR:SoLightModel::PHONG)) { +// messageVerbose("TrackLightModel changed (base = "+str(base)); +// if (base) +// m_d->trackLightModel->model.setValue(SoLightModel::BASE_COLOR); +// else +// m_d->trackLightModel->model.setValue(SoLightModel::PHONG); +// } +// } + +//____________________________________________________________________ +void TrackSystemController::updateAscObjDrawStyle() +{ + double val_lw = VP1QtInventorUtils::getValueLineWidthSlider(m_d->ui_ascobjs.horizontalSlider_linewidths); + double val_ps = VP1QtInventorUtils::getValuePointSizeSlider(m_d->ui_ascobjs.horizontalSlider_pointsizes); + if (m_d->ascObjDrawStyle->lineWidth.getValue()!=val_lw) + m_d->ascObjDrawStyle->lineWidth = val_lw; + if (m_d->ascObjDrawStyle->pointSize.getValue()!=val_ps) + m_d->ascObjDrawStyle->pointSize = val_ps; +} + + +//____________________________________________________________________ +void TrackSystemController::updateAscObjComplexity() +{ + //choose complexity in interval [0.01,1.0] + const double val = std::min<double>(1.0,std::max<double>(0.0,0.01+0.991* + (m_d->ui_ascobjs.horizontalSlider_complexity->value() + -m_d->ui_ascobjs.horizontalSlider_complexity->minimum())/ + (m_d->ui_ascobjs.horizontalSlider_complexity->maximum()*1.0))); + if (m_d->ascObjComplexity->value.getValue()!=val) + m_d->ascObjComplexity->value.setValue(val); +} + +// //____________________________________________________________________ +// SoDrawStyle * TrackSystemController::trackDrawStyle() const +// { +// return m_d->trackDrawStyle; +// } + +// //____________________________________________________________________ +// SoLightModel * TrackSystemController::trackLightModel() const +// { +// return m_d->trackLightModel; +// } + +//____________________________________________________________________ +SoDrawStyle * TrackSystemController::ascObjDrawStyle() const +{ + return m_d->ascObjDrawStyle; +} + +//____________________________________________________________________ +SoComplexity * TrackSystemController::ascObjComplexity() const +{ + return m_d->ascObjComplexity; +} + +//____________________________________________________________________ +QString TrackSystemController::nameOfNewlyFittedCollections() const +{ + QString name = m_d->ui_int.lineEdit_fittedTrackCollName->text().simplified(); + return name.isEmpty() ? "<noname>" : name; +} + +//____________________________________________________________________ +TrackCommonFlags::TrackPartsFlags TrackSystemController::shownTrackParts() const +{ + TrackCommonFlags::TrackPartsFlags parts = TrackCommonFlags::NoParts; + // if (!m_d->ui_col.checkBox_hideactualpaths->isChecked()) parts |= TrackCommonFlags::ActualPath; + parts |= TrackCommonFlags::ActualPath; // sensible default. + // if (m_d->ui_proj.checkBox_projections_indet->isChecked()) parts |= TrackCommonFlags::InDetProjections; + if (m_d->ui_proj.groupBox_projections_vertex->isChecked()) parts |= TrackCommonFlags::VertexProjections; + return parts; +} + +int TrackSystemController::vertexProjectionAngle() const{ + messageVerbose("angleForVertexPlane"+str(m_d->ui_proj.spinBox_projections_vertex->value())); + + if (!m_d->ui_proj.groupBox_projections_vertex->isChecked()) return -1; + return m_d->ui_proj.spinBox_projections_vertex->value(); +} + +// //____________________________________________________________________ +// double TrackSystemController::trackTubeRadius() const +// { +// return m_d->ui_col.checkBox_trackTubes->isChecked() ? +// m_d->ui_col.doubleSpinBox_trackTubesRadiusMM->value()*CLHEP::mm : 0.0; +// } + +//____________________________________________________________________ +TrackCommonFlags::TSOSPartsFlags TrackSystemController::shownTSOSParts() const +{ + TrackCommonFlags::TSOSPartsFlags f(TrackCommonFlags::TSOS_NoObjects); + if (m_d->ui_ascobjs.groupBox_parameters->isChecked()) + f |= TrackCommonFlags::TSOS_TrackPars; + if (m_d->ui_ascobjs.groupBox_errors->isChecked()&&m_d->ui_ascobjs.checkBox_parametererrors->isChecked()) { + f |= TrackCommonFlags::TSOS_TrackParsErrorsNotPerigee; + if (!m_d->ui_ascobjs.checkBox_parerror_hideperigeeerrors->isChecked()) + f |= TrackCommonFlags::TSOS_TrackParsErrorsPerigee; + } + if (m_d->ui_ascobjs.groupBox_errors->isChecked()&&m_d->ui_ascobjs.checkBox_measurementerrors->isChecked()) { + f |= TrackCommonFlags::TSOS_MeasError; + } + if (m_d->ui_ascobjs.groupBox_measurements->isChecked()) { + f |= TrackCommonFlags::TSOS_AnyMeasRioOnTrack; + f |= TrackCommonFlags::TSOS_AnyMeasCompetingRioOnTrack; + } + if (m_d->ui_ascobjs.groupBox_surfaces->isChecked()) { + f |= TrackCommonFlags::TSOS_SurfacesDetElem; + if (!m_d->ui_ascobjs.checkBox_surfaces_hidecustomsurfaces->isChecked()) + f |= TrackCommonFlags::TSOS_SurfacesCustom; + if (!m_d->ui_ascobjs.checkBox_surfaces_hidetubesurfaces->isChecked()) + f |= TrackCommonFlags::TSOS_TubeSurfaces; + } + if (m_d->ui_ascobjs.groupBox_materialeffectsontrack->isChecked()) { + f |= TrackCommonFlags::TSOS_MaterialEffects; + if (!m_d->ui_ascobjs.checkBox_materialeffectsontrack_hideNoDE->isChecked()) + f |= TrackCommonFlags::TSOS_MaterialEffectsWithNoDeltaE; + } + + return f; +} + +//____________________________________________________________________ +TrackCommonFlags::TSOSPartsFlags TrackSystemController::customColouredTSOSParts() const +{ + TrackCommonFlags::TSOSPartsFlags f(TrackCommonFlags::TSOS_NoObjects); + if (m_d->ui_ascobjs.checkBox_usecolour_measurements->isChecked()) + f |= TrackCommonFlags::TSOS_AnyMeasurementNotOutlier; + if (m_d->ui_ascobjs.checkBox_usecolour_meas_outliers->isChecked()) + f |= TrackCommonFlags::TSOS_AnyMeasurementOutlier; + if (m_d->ui_ascobjs.checkBox_usecolour_parameters->isChecked()) + f |= TrackCommonFlags::TSOS_TrackPars; + if (m_d->ui_ascobjs.checkBox_useHoleColour_parameters->isChecked()) + f |= TrackCommonFlags::TSOS_Hole; + if (m_d->ui_ascobjs.checkBox_usecolour_parametererrors->isChecked()) + f |= TrackCommonFlags::TSOS_AnyParsErrors; + if (m_d->ui_ascobjs.checkBox_usecolour_materialeffectsontrack->isChecked()) + f |= TrackCommonFlags::TSOS_AnyMaterialEffects; + if (m_d->ui_ascobjs.checkBox_usecolour_surfaces->isChecked()) + f |= TrackCommonFlags::TSOS_AnySurface; + + return f; +} + +//____________________________________________________________________ +bool TrackSystemController::hideTubeSurfaces() const +{ + return m_d->ui_ascobjs.checkBox_surfaces_hidetubesurfaces->isChecked(); +} + +//____________________________________________________________________ +bool TrackSystemController::hideCustomSurfaces() const +{ + return m_d->ui_ascobjs.checkBox_surfaces_hidecustomsurfaces->isChecked(); +} + +//____________________________________________________________________ +bool TrackSystemController::drawMeasGlobalPositions() const +{ + return m_d->ui_ascobjs.checkBox_measurements_drawGP->isChecked(); +} + + +//____________________________________________________________________ +double TrackSystemController::measurementsShorttubesScale() const +{ + return std::max(0.1*CLHEP::mm,m_d->ui_ascobjs.doubleSpinBox_measurements_shorttubes_scale->value()*CLHEP::cm); +} + +//____________________________________________________________________ +double TrackSystemController::nStdDevForParamErrors() const +{ + return std::min<double>(1.0e3,std::max<double>(1.0e-3,m_d->ui_ascobjs.doubleSpinBox_parerror_stddev->value())); +} + +//____________________________________________________________________ +bool TrackSystemController::parTubeErrorsDrawCylinders() const +{ + return m_d->ui_ascobjs.checkBox_parerror_drawcylinder->isChecked(); +} + +//____________________________________________________________________ +int TrackSystemController::numberOfPointsOnCircles() const +{ + const int val(m_d->ui_ascobjs.horizontalSlider_complexity->value()); + const int max(m_d->ui_ascobjs.horizontalSlider_complexity->maximum()); + const int min(m_d->ui_ascobjs.horizontalSlider_complexity->minimum()); + //special cases: + if (val==max) + return 80; + else if (val==min) + return 4; + + //roughly 4..32: + const int n(1+static_cast<int>(0.5+7.0*(val-min)/(1.0*max)));//number between 1 and 8 + return std::min<int>(32,std::max<int>(4,4*n)); +} + +//____________________________________________________________________ +double TrackSystemController::materialEffectsOnTrackScale() const +{ + return m_d->ui_ascobjs.horizontalSlider_materialeffectsontrack_scale->value()/5.0; +} + +//____________________________________________________________________ +Trk::IExtrapolator * TrackSystemController::propagator() const +{ + if (!m_d->toolaccesshelper + ||!m_d->ui_extrap.radioButton_athenaExtrapolator->isChecked() + ||m_d->ui_extrap.comboBox_propagator->count()==0) + return 0; + + QString key = m_d->ui_extrap.comboBox_propagator->currentText(); + if (key==Imp::noneAvailString) + return 0; + return key.isEmpty() ? 0 : m_d->toolaccesshelper->getToolPointer<Trk::IExtrapolator>(key); +} + +TrackSystemController::PropagationOptionFlags TrackSystemController::propagationOptions() const{ + PropagationOptionFlags options=TrackSystemController::NoPropOptions; + if (m_d->ui_extrap.checkBox_ignoreMEoT->isChecked()) options |= TrackSystemController::IgnoreMEOT; + if (m_d->ui_extrap.checkBox_extendAllTracks->isChecked()) options |= TrackSystemController::ExtendTrack; + return options; +} + +float TrackSystemController::propMaxRadius() const{ + if (!m_d->ui_extrap.checkBox_maxRadius->isChecked()) return -1.0; + return m_d->ui_extrap.spinBox_maxRadiusValue->value(); +} + +void TrackSystemController::emitExtrapolateToHereChanged(int /**index*/){ + emit extrapolateToThisVolumeChanged(); +} + +bool TrackSystemController::ignoreMeasurementEffectsOnTrackInProp() +{ + return m_d->ui_extrap.checkBox_ignoreMEoT->isChecked(); +} + +//____________________________________________________________________ +Trk::ITrackFitter * TrackSystemController::trackFitter() const +{ + if (!m_d->toolaccesshelper + ||m_d->ui_int.comboBox_fitters->count()==0) + return 0; + + QString key = m_d->ui_int.comboBox_fitters->currentText(); + if (key==Imp::noneAvailString) + return 0; + return key.isEmpty() ? 0 : m_d->toolaccesshelper->getToolPointer<Trk::ITrackFitter>(key); +} + +// ITrackingVolumesSvc * TrackSystemController::trackingVolumeSvc() const +// { +// return m_trackingVolumesSvc.operator->(); +// } + +const Trk::Volume * TrackSystemController::extrapolateToThisVolume() const +{ + if (m_d->ui_extrap.comboBox_extendAllTracksToHere->currentText()=="Calorimeter") + return m_d->calorimeterEntryLayer; + return 0; +} + +//____________________________________________________________________ +TrackCommonFlags::SELECTIONMODE TrackSystemController::selectionMode() const +{ + if (m_d->ui_int.radioButton_selmode_single->isChecked()) + return TrackCommonFlags::SINGLEOBJECT; + else if (m_d->ui_int.radioButton_selmode_multitracks->isChecked()) + return TrackCommonFlags::MULTITRACK; + else if (m_d->ui_int.radioButton_selmode_trackfits->isChecked()) + return TrackCommonFlags::TRACKFIT; + message("selectionMode ERROR: Inconsistency detected."); + return TrackCommonFlags::SINGLEOBJECT; +} + +TrackCommonFlags::FITTERMODE TrackSystemController::fitterMode() const +{ + if (m_d->ui_int.comboBox_fitterMode->currentText()=="Fit PRDs") + return TrackCommonFlags::FROMPRDS; + else if (m_d->ui_int.comboBox_fitterMode->currentText()=="Refit Track") + return TrackCommonFlags::REFITSINGLETRACK; + else if (m_d->ui_int.comboBox_fitterMode->currentText()=="Extend Track with PRDs") + return TrackCommonFlags::EXTENDTRACKWITHPRDS; + else if (m_d->ui_int.comboBox_fitterMode->currentText()=="Combine Two Tracks") + return TrackCommonFlags::COMBINETWOTRACKS; + + message("fitterMode ERROR: Inconsistency detected. Mode not known."); + + return TrackCommonFlags::FROMPRDS; // FIXME! +} + +bool TrackSystemController::fitterRemoveOutliers() const +{ + return m_d->ui_int.checkBox_removeOutliers->isChecked(); +} + +Trk::ParticleHypothesis TrackSystemController::fitterParticleHypthesis() const +{ + if (m_d->ui_int.comboBox_particleHypo->currentText()=="Pion") + return Trk::pion; + else if (m_d->ui_int.comboBox_particleHypo->currentText()=="Non Interacting") + return Trk::nonInteracting; + else if (m_d->ui_int.comboBox_particleHypo->currentText()=="Electron") + return Trk::electron; + else if (m_d->ui_int.comboBox_particleHypo->currentText()=="Muon") + return Trk::muon; + else if (m_d->ui_int.comboBox_particleHypo->currentText()=="Kaon") + return Trk::kaon; + else if (m_d->ui_int.comboBox_particleHypo->currentText()=="Proton") + return Trk::proton; + else if (m_d->ui_int.comboBox_particleHypo->currentText()=="Photon") + return Trk::photon; + + message("fitterMode ERROR: Inconsistency detected. Mode not known."); + return Trk::undefined; // FIXME! +} + +//____________________________________________________________________ +bool TrackSystemController::showTruthAscObjs() const +{ + return m_d->ui_ascobjs.checkBox_truthtracks_display_points->isChecked(); +} + +//____________________________________________________________________ +TrackCommonFlags::DETAILLEVEL TrackSystemController::assocObjDetailLevel() const +{ + if (m_d->ui_ascobjs.comboBox_assocobj_detaillevel->currentText()=="Auto") + return TrackCommonFlags::AUTO; + else if (m_d->ui_ascobjs.comboBox_assocobj_detaillevel->currentText()=="Simple") + return TrackCommonFlags::SIMPLE; + else + return TrackCommonFlags::DETAILED; +} + +void TrackSystemController::vertexCutsAllowed(bool b){ + if (m_d->ui_cuts.checkBox_vertexAssociated->isEnabled()!=b) { + m_d->ui_cuts.checkBox_vertexAssociated->setEnabled(b); + emit cutOnlyVertexAssocTracksChanged(m_d->ui_cuts.checkBox_vertexAssociated->isChecked()); + } +} + +bool TrackSystemController::cutOnlyVertexAssocTracks() const { + if (!m_d->ui_cuts.checkBox_vertexAssociated->isEnabled()) return false; + return m_d->ui_cuts.checkBox_vertexAssociated->isChecked(); +} + + +//____________________________________________________________________ +VP1Interval TrackSystemController::cutAllowedPt() const +{ + if (!m_d->ui_cuts.checkBox_cut_minpt) + return VP1Interval(); + + // will set range to negative if we have momcut=P + // if minCut unset then min=-inf + // if minCut set, and Pt selected, then min=-minCut + // if minCut set, and P selected, then min=-maxCut + // etc + bool isPCut = m_d->ui_cuts.comboBox_momtype->currentText()=="P"; + + const double minFromInterface=m_d->ui_cuts.doubleSpinBox_cut_minpt_gev->value()*CLHEP::GeV; + const double maxFromInterface=m_d->ui_cuts.doubleSpinBox_cut_maxpt_gev->value()*CLHEP::GeV; + + double min=0.0,max=0.0; + if (!isPCut) { + //Pt cut + min = (m_d->ui_cuts.checkBox_cut_minpt->isChecked() ? minFromInterface : -std::numeric_limits<double>::infinity()); + max = (m_d->ui_cuts.checkBox_cut_maxpt->isChecked() ? maxFromInterface : std::numeric_limits<double>::infinity()); + } else { + min = (m_d->ui_cuts.checkBox_cut_maxpt->isChecked() ? -maxFromInterface : -std::numeric_limits<double>::infinity()); + max = (m_d->ui_cuts.checkBox_cut_minpt->isChecked() ? -minFromInterface : std::numeric_limits<double>::infinity()); + } + + //message("cutAllowedPt: min,max="+QString::number(min)+","+QString::number(max)); + + if (max<min) + return VP1Interval(); + + return VP1Interval( min, max );//fixme: closed interval?? +} + +//____________________________________________________________________ +VP1Interval TrackSystemController::cutAllowedEta() const +{ + return m_d->ui_cuts.etaPhiCutWidget->allowedEta(); +} + +//____________________________________________________________________ +QList<VP1Interval> TrackSystemController::cutAllowedPhi() const +{ + return m_d->ui_cuts.etaPhiCutWidget->allowedPhi(); +} + +//____________________________________________________________________ +QList<unsigned> TrackSystemController::cutRequiredNHits() const +{ + unsigned npixel = m_d->ui_cuts.checkBox_cut_nhits_pixel->isChecked() ? m_d->ui_cuts.spinBox_cut_nhits_pixel->value() : 0; + unsigned nsct = m_d->ui_cuts.checkBox_cut_nhits_sct->isChecked() ? m_d->ui_cuts.spinBox_cut_nhits_sct->value() : 0; + unsigned ntrt = m_d->ui_cuts.checkBox_cut_nhits_trt->isChecked() ? m_d->ui_cuts.spinBox_cut_nhits_trt->value() : 0; + unsigned nmuon = m_d->ui_cuts.checkBox_cut_nhits_muon->isChecked() ? m_d->ui_cuts.spinBox_cut_nhits_muon->value() : 0; + unsigned nprecmuon = m_d->ui_cuts.checkBox_cut_nprecisionhits_muon->isChecked() ? m_d->ui_cuts.spinBox_cut_nprecisionhits_muon->value() : 0; + + QList<unsigned> l; + if (!npixel&&!nsct&&!ntrt&&!nmuon&&!nprecmuon) + return l; + l << npixel << nsct << ntrt << nmuon << nprecmuon; + return l; +} + +//____________________________________________________________________ +bool TrackSystemController::cutTruthFromIROnly() const +{ + return m_d->ui_cuts.checkBox_cut_truthtracks_creationvertexinIR->isChecked(); +} + +//____________________________________________________________________ +bool TrackSystemController::cutExcludeBarcodeZero() const +{ + return m_d->ui_cuts.checkBox_cut_truthtracks_excludebarcode0->isChecked(); +} + +//____________________________________________________________________ +bool TrackSystemController::cutTruthExcludeNeutrals() const +{ + return m_d->ui_cuts.checkBox_cut_truthtracks_excludeneutrals->isChecked(); +} + +//____________________________________________________________________ +//Returns false if "none available" +bool TrackSystemController::Imp::updateComboBoxContents(QComboBox*cb,QStringList l,QString& restoredSelection) +{ + //current selection: + QString ct = cb->currentText(); + if (ct==Imp::noneAvailString) + ct = ""; + + bool save = cb->blockSignals(true); + + cb->clear(); + + bool enabled = false; + if (l.isEmpty()) { + cb->addItem(Imp::noneAvailString); + cb->setEnabled(false); + } else { + cb->addItems(l); + + int i = restoredSelection.isEmpty() ? -1 : cb->findText(restoredSelection); + if (i<0) + i = ct.isEmpty() ? -1 : cb->findText(ct); + restoredSelection = ""; + + if (i>=0) { + cb->setCurrentIndex(i); + } else { + //Let's try to pick the default to be VP1Extrapolater over + //AtlasExtrapolater over... whatever (same for fitters): + int i_vp1(-1), i_atlas(-1); + for (int j = 0; j <cb->count();++j) { + if (i_vp1==-1&&cb->itemText(j).contains("vp1",Qt::CaseInsensitive)) + i_vp1 = j; + if (i_atlas==-1&&cb->itemText(j).contains("atlas",Qt::CaseInsensitive)) + i_atlas = j; + } + if (i_vp1>=0) + cb->setCurrentIndex(i_vp1); + else if (i_atlas>=0) + cb->setCurrentIndex(i_atlas); + } + //m_d->ui_extrap.radioButton_athenaExtrapolator->setEnabled(true); + enabled = true; + cb->setEnabled(true); + } + + if (!save) + cb->blockSignals(false); + return enabled; +} + +//____________________________________________________________________ +void TrackSystemController::availableFittersChanged(const QStringList& af) +{ + if (m_d->lastUpdatedAvailableFitters==af) + return; + m_d->lastUpdatedAvailableFitters=af; + m_d->updateComboBoxContents(m_d->ui_int.comboBox_fitters,af,m_d->restoredLastFitter);//remember return val. + m_d->updateFitPRDButtonState(); + + possibleChange_trackFitter(); +} + +//____________________________________________________________________ +void TrackSystemController::availableExtrapolatorsChanged(const QStringList& ae) +{ + if (m_d->lastUpdatedAvailableExtrapolators==ae) + return; + m_d->lastUpdatedAvailableExtrapolators=ae; + + if (!m_d->updateComboBoxContents(m_d->ui_extrap.comboBox_propagator,ae,m_d->restoredLastPropagator)) { + m_d->ui_extrap.radioButton_athenaExtrapolator->setEnabled(false); + bool save1 = m_d->ui_extrap.radioButton_none->blockSignals(true); + bool save2 = m_d->ui_extrap.radioButton_helical->blockSignals(true); + bool save3 = m_d->ui_extrap.radioButton_athenaExtrapolator->blockSignals(true); + m_d->ui_extrap.radioButton_none->setChecked(true);//Fixme: fall back to the helical instead! + m_d->ui_extrap.radioButton_helical->setChecked(false); + m_d->ui_extrap.radioButton_athenaExtrapolator->setChecked(false); + if (!save1) m_d->ui_extrap.radioButton_none->blockSignals(false); + if (!save2) m_d->ui_extrap.radioButton_helical->blockSignals(false); + if (!save3) m_d->ui_extrap.radioButton_athenaExtrapolator->blockSignals(false); + } else { + m_d->ui_extrap.radioButton_athenaExtrapolator->setEnabled(true); + } + + possibleChange_propagator(); +} + +//____________________________________________________________________ +bool TrackSystemController::orientAndZoomOnSingleSelection() const +{ + return m_d->ui_int.checkBox_selsingle_orientzoom->isChecked(); +} + +//____________________________________________________________________ +bool TrackSystemController::printInfoOnSingleSelection() const +{ + return m_d->ui_int.checkBox_selsingle_printinfo->isChecked(); +} + +//____________________________________________________________________ +bool TrackSystemController::printVerboseInfoOnSingleSelection() const +{ + return printInfoOnSingleSelection() && m_d->ui_int.checkBox_selsingle_printinfo_verbose->isChecked(); +} + +//____________________________________________________________________ +bool TrackSystemController::printTotMomentumOnMultiTrackSelection() const +{ + return m_d->ui_int.checkBox_sel_printtotmom->isChecked(); +} + +//____________________________________________________________________ +bool TrackSystemController::showTotMomentumOnMultiTrackSelection() const +{ + return m_d->ui_int.checkBox_sel_showtotmom->isChecked(); +} + +//____________________________________________________________________ +void TrackSystemController::emitRerandomise() +{ + messageVerbose("Emitting rerandomise"); + emit rerandomise(); +} + +//____________________________________________________________________ +void TrackSystemController::emitRefit() +{ + messageVerbose("Emitting refit"); + emit refit(); +} + +//____________________________________________________________________ +void TrackSystemController::Imp::updateFitPRDButtonState() +{ + switch (theclass->fitterMode()) { + case TrackCommonFlags::FROMPRDS: ui_int.pushButton_refit->setEnabled( numberOfSelectedPRDs>=3 && theclass->trackFitter() );break; + case TrackCommonFlags::REFITSINGLETRACK: ui_int.pushButton_refit->setEnabled( numberOfSelectedTracks>=1 && theclass->trackFitter() );break; + case TrackCommonFlags::EXTENDTRACKWITHPRDS: ui_int.pushButton_refit->setEnabled( numberOfSelectedTracks>=1 && numberOfSelectedPRDs>=1 && theclass->trackFitter() );break; + case TrackCommonFlags::COMBINETWOTRACKS: ui_int.pushButton_refit->setEnabled( numberOfSelectedTracks==2 && theclass->trackFitter() );break; + } +} + +//____________________________________________________________________ +void TrackSystemController::setNumberOfSelectedPRDsAndTracks(unsigned prds, unsigned trks) +{ + if (m_d->numberOfSelectedPRDs==prds && m_d->numberOfSelectedTracks==trks) + return; + m_d->numberOfSelectedPRDs=prds; + m_d->numberOfSelectedTracks=trks; + + switch (fitterMode()) { + case TrackCommonFlags::FROMPRDS: m_d->ui_int.pushButton_refit->setText("Fit track from "+str(prds)+" PRDs");break; + case TrackCommonFlags::REFITSINGLETRACK: m_d->ui_int.pushButton_refit->setText("Fit track");break; + case TrackCommonFlags::EXTENDTRACKWITHPRDS: m_d->ui_int.pushButton_refit->setText("Extend track with "+str(prds)+" PRDs");break; + case TrackCommonFlags::COMBINETWOTRACKS: m_d->ui_int.pushButton_refit->setText("Combine");break; + } + + + // FIXME Need to redo this method so that it can handle all fitter modes + + m_d->updateFitPRDButtonState(); +} + +void TrackSystemController::updateFitPRDButtonState(){ + messageVerbose("updateFitPRDButtonState"); + + switch (fitterMode()) { + case TrackCommonFlags::FROMPRDS: m_d->ui_int.pushButton_refit->setText("Fit track from "+str(m_d->numberOfSelectedPRDs)+" PRDs");break; + case TrackCommonFlags::REFITSINGLETRACK: m_d->ui_int.pushButton_refit->setText("Fit track");break; + case TrackCommonFlags::EXTENDTRACKWITHPRDS: m_d->ui_int.pushButton_refit->setText("Extend track with "+str(m_d->numberOfSelectedPRDs)+" PRDs");break; + case TrackCommonFlags::COMBINETWOTRACKS: m_d->ui_int.pushButton_refit->setText("Combine");break; + } + + m_d->updateFitPRDButtonState(); +} + +QTreeWidget* TrackSystemController::trackObjBrowser() const +{ + return m_d->objBrowserWidget; +} + +TrackSysCommonData * TrackSystemController::common() const { + return m_d->common; +} +void TrackSystemController::setCommonData(TrackSysCommonData * common){ + m_d->common=common; +} + +void TrackSystemController::objectBrowserClicked(QTreeWidgetItem * item, int){ + messageVerbose("objectBrowserClicked for "+item->text(0)); + + VP1TrackSystem* sys = dynamic_cast<VP1TrackSystem*>(systemBase()); + if (!sys){ + messageVerbose("TrackSystemController::objectBrowserClicked: Couldn't get VP1TrackSystem pointer"); + return; + } + + //sys->deselectAll(); // FIXME. necessary? + + SoNode* node = common()->node(item); + if (node) { + // okay, have track + SoCooperativeSelection * sel = sys->selTracks(); + sel->select(node); + } else { + // maybe it's a TSOS? Check first that it has a parent + if (item->parent()) node = common()->node(item->parent()); + if ( !node && item->parent()->parent() ) node = common()->node(item->parent()->parent()); // Try one more up (ugly, but shouldn't ever be deeper than this) + if (node) { + // yes, so now get index within track, as we can hopefully use this to find the AscObj_TSOS + unsigned int index = item->parent()->indexOfChild(item);// should correspond to the TSOS number + messageVerbose("TrackSystemController::objectBrowserClicked: item has index of "+QString::number(index)); + TrackHandle_TrkTrack* trkHandle = dynamic_cast<TrackHandle_TrkTrack*>(common()->trackHandle(node)); + if (trkHandle && trkHandle->trkTrackPointer()) { + if (index<trkHandle->trkTrackPointer()->trackStateOnSurfaces()->size() ){ + // in range + const Trk::TrackStateOnSurface* tsos = (*trkHandle->trkTrackPointer()->trackStateOnSurfaces())[index]; + // now find matching AscObj_TSOS + QList<AssociatedObjectHandleBase*> list = trkHandle->getVisibleMeasurements(); + for (int i = 0; i < list.size(); ++i) { + messageVerbose("TrackSystemController::objectBrowserClicked: checking ASC "+QString::number(i)); + + AscObj_TSOS* asc = dynamic_cast<AscObj_TSOS*>(list.at(i)); + if (asc && asc->trackStateOnSurface()==tsos) { + messageVerbose("TrackSystemController::objectBrowserClicked: this ASC matches "+QString::number(i)); + //asc->zoomView(); + common()->ascObjSelectionManager()->pretendUserClicked(asc); + } else { + messageVerbose("TrackSystemController::objectBrowserClicked: no matching Asc found"); + } + } // for loop + } else { + messageVerbose("TrackSystemController::objectBrowserClicked: index of "+QString::number(index)+" is greater than number of TSOSes:"+QString::number(trkHandle->trkTrackPointer()->trackStateOnSurfaces()->size())); + } + } + } else { + messageVerbose("TrackSystemController::objectBrowserClicked: Couldn't get node pointer. Maybe object not visible?"); + } + } + + + // if (selTrack){ + // SoCooperativeSelection * sel = sys->selTracks(); + // sel->select(node); + // } else { + // common()->ascObjSelectionManager()->pretendUserClicked(); + // } + // + // SoCooperativeSelection * sel = sys->selTracks(); + // SoCooperativeSelection * selAsc = dynamic_cast<SoCooperativeSelection*>(common()->ascObjSelectionManager()->getAscObjAttachSep()); + // SoSeparator* eventRoot = common()->ascObjSelectionManager()->eventRoot(); + // + // SoSearchAction mySearchAction; + // mySearchAction.setNode(node); + // // SoSeparator* eventRoot = common()->ascObjSelectionManager()->eventRoot(); + // mySearchAction.apply(eventRoot); + // SoPath* path=mySearchAction.getPath(); + // if ( !path ) { + // messageVerbose("TrackSystemController::objectBrowserClicked: Couldn't get SoPath"); + // return; + // } else { + // messageVerbose("TrackSystemController::objectBrowserClicked: got SoPath. Will now try to select."); + // messageVerbose("pathlength="+QString::number(path->getLength())); + // } + // + // //sel->select(path); //Doesn't work. + // // messageVerbose("findpath="+QString::number(sel->findPath(path))); + // sel->select(node); // Doesn't work. + // if (sel->getNumSelected()==0){ + // messageVerbose("TrackSystemController::objectBrowserClicked: Couldn't select. Trying with ASC sel node."); + // + // selAsc->select(node); + // if (selAsc->getNumSelected()==0){ + // messageVerbose("TrackSystemController::objectBrowserClicked: Couldn't select. Trying with ASC sel using path."); + // + // selAsc->select(path); + // } + // } + // // messageVerbose("findpath="+QString::number(sel->findPath(path))); + // + // // sel->touch(); + // messageVerbose("numselected="+QString::number(sel->getNumSelected())); + + // path->unref(); +} + +std::vector<double> TrackSystemController::alignmentShiftValue() +{ + std::vector<double> values(6,0.0); + values[0]=m_d->ui_shiftmuonchambers.doubleSpinBox_tra_s->value(); + values[1]=m_d->ui_shiftmuonchambers.doubleSpinBox_tra_z->value(); + values[2]=m_d->ui_shiftmuonchambers.doubleSpinBox_tra_t->value(); + values[3]=m_d->ui_shiftmuonchambers.doubleSpinBox_rot_s->value(); + values[4]=m_d->ui_shiftmuonchambers.doubleSpinBox_rot_z->value(); + values[5]=m_d->ui_shiftmuonchambers.doubleSpinBox_rot_t->value(); + return values; +} +int TrackSystemController::alignmentShiftLevel() +{ + if (m_d->ui_shiftmuonchambers.comboBox_level->currentText()=="Level 0") + return 0; + else if (m_d->ui_shiftmuonchambers.comboBox_level->currentText()=="Level 1") + return 1; + else if (m_d->ui_shiftmuonchambers.comboBox_level->currentText()=="Level 2") + return 2; + else if (m_d->ui_shiftmuonchambers.comboBox_level->currentText()=="Level 3") + return 3; + return 0; +} + +bool TrackSystemController::doTrackLabels() +{ + return m_d->ui_col.groupBox_labels->isChecked(); +} + +float TrackSystemController::trackLabelTrkOffset() +{ + return static_cast<float>(m_d->ui_col.horizontalSlider_labels_trkOffset->value())/static_cast<float>(m_d->ui_col.horizontalSlider_labels_trkOffset->maximum()); +} + +QList<int> TrackSystemController::trackLabelPosOffset() +{ + QList<int> values; + values << m_d->ui_col.horizontalSlider_labels_xOffset->value(); + values << m_d->ui_col.horizontalSlider_labels_yOffset->value(); + values << m_d->ui_col.horizontalSlider_labels_zOffset->value(); + return values; +} + +int TrackSystemController::labelXOffset() +{ + return m_d->ui_col.horizontalSlider_labels_xOffset->value(); +} + +int TrackSystemController::labelYOffset() +{ + return m_d->ui_col.horizontalSlider_labels_yOffset->value(); +} + +int TrackSystemController::labelZOffset() +{ + return m_d->ui_col.horizontalSlider_labels_zOffset->value(); +} + +TrackSystemController::TrackLabelModes TrackSystemController::trackLabels(){ + if (!m_d->ui_col.groupBox_labels->isChecked()) + return TrackSystemController::NoLabels; + + TrackLabelModes labels=TrackSystemController::NoLabels; + if (m_d->ui_col.checkBox_trkLabels_p->isChecked()) labels |= TrackSystemController::P; + if (m_d->ui_col.checkBox_trkLabels_Pt->isChecked()) labels |= TrackSystemController::Pt; + if (m_d->ui_col.checkBox_trkLabels_direction->isChecked()) labels |= TrackSystemController::Direction; + if (m_d->ui_col.checkBox_trkLabels_pid->isChecked()) labels |= TrackSystemController::Pid; + if (m_d->ui_col.checkBox_trkLabels_hits->isChecked()) labels |= TrackSystemController::Hits; + if (m_d->ui_col.checkBox_trkLabels_fitQuality->isChecked()) labels |= TrackSystemController::FitQuality; + return labels; +} + +/////////////////////////////////////////////////////////////////////////// +// Test for possible changes in values and emit signals as appropriate: +// (possibleChange_XXX() slots code provided by macros) +#define VP1CONTROLLERCLASSNAME TrackSystemController +#include "VP1Base/VP1ControllerMacros.h" +POSSIBLECHANGE_IMP(shownTrackParts) +POSSIBLECHANGE_IMP(vertexProjectionAngle) +// POSSIBLECHANGE_IMP(trackTubeRadius) +POSSIBLECHANGE_IMP(trackLabels) +POSSIBLECHANGE_IMP(trackLabelTrkOffset) +POSSIBLECHANGE_IMP(trackLabelPosOffset) +POSSIBLECHANGE_IMP(shownTSOSParts) +POSSIBLECHANGE_IMP(customColouredTSOSParts) +POSSIBLECHANGE_IMP(drawMeasGlobalPositions) +POSSIBLECHANGE_IMP(measurementsShorttubesScale) +POSSIBLECHANGE_IMP(nStdDevForParamErrors) +POSSIBLECHANGE_IMP(parTubeErrorsDrawCylinders) +POSSIBLECHANGE_IMP(numberOfPointsOnCircles) +POSSIBLECHANGE_IMP(materialEffectsOnTrackScale) +POSSIBLECHANGE_IMP(propagator) +POSSIBLECHANGE_IMP(propagationOptions) +POSSIBLECHANGE_IMP(propMaxRadius) +POSSIBLECHANGE_IMP(trackFitter) +POSSIBLECHANGE_IMP(selectionMode) +POSSIBLECHANGE_IMP(showTruthAscObjs) +POSSIBLECHANGE_IMP(assocObjDetailLevel) +POSSIBLECHANGE_IMP(cutAllowedPt) +POSSIBLECHANGE_IMP(cutAllowedEta) +POSSIBLECHANGE_IMP(cutAllowedPhi) +POSSIBLECHANGE_IMP(cutRequiredNHits) +POSSIBLECHANGE_IMP(cutTruthFromIROnly) +POSSIBLECHANGE_IMP(cutExcludeBarcodeZero) +POSSIBLECHANGE_IMP(cutTruthExcludeNeutrals) +POSSIBLECHANGE_IMP(cutOnlyVertexAssocTracks) +POSSIBLECHANGE_IMP(showTotMomentumOnMultiTrackSelection) diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackTypes.cxx b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackTypes.cxx new file mode 100644 index 000000000..371a5b039 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackTypes.cxx @@ -0,0 +1,124 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "VTI12TrackSystems/TrackTypes.h" + +//______________________________________________ +qint32 TrackType::typeToInt(const Type&t) +{ + switch (t) { + case TrkTrack: return 0; + case TrackParticle: return 1; + case TruthTrack: return 3; + case FatrasTruthTrack: return 4; + case TrkSegment: return 5; + case RefittedTrack: return 6; + case AnalysisObject: return 7; + case xAOD: return 9; + case Unknown: return 10; + default: return -1; + } +} + +//______________________________________________ +TrackType::Type TrackType::intToType(const qint32& i) +{ + switch (i) { + case 0: return TrkTrack; + case 1: return TrackParticle; + case 3: return TruthTrack; + case 4: return FatrasTruthTrack; + case 5: return TrkSegment; + case 6: return RefittedTrack; + case 7: return AnalysisObject; + case 9: return xAOD; + case 10: return Unknown; + default: return Unknown; + } +} + +//______________________________________________ +QString TrackType::typeToString(const Type& t) +{ + switch (t) { + case TrkTrack: return "TrkTrack"; + case TrackParticle: return "TrackParticle"; + case TruthTrack: return "TruthTrack"; + case FatrasTruthTrack: return "FatrasTruthTrack"; + case RefittedTrack: return "RefittedTrack"; + case TrkSegment: return "TrkSegment"; + case AnalysisObject: return "AnalysisObject"; + case xAOD: return "xAOD"; + case Unknown: return "Unknown"; + default: return "ERROR"; + } +} + +//______________________________________________ +TrackType::Type TrackType::stringToType(const QString&str, bool & status) +{ + status = true; + if (str=="TrkTrack") return TrkTrack; + if (str=="TrackParticle") return TrackParticle; + if (str=="TruthTrack") return TruthTrack; + if (str=="FatrasTruthTrack") return FatrasTruthTrack; + if (str=="RefittedTrack") return RefittedTrack; + if (str=="TrkSegment") return TrkSegment; + if (str=="AnalysisObject") return AnalysisObject; + if (str=="xAOD") return xAOD; + if (str=="Unknown") return Unknown; + status = false; + return Unknown; +} + +//______________________________________________ +QString TrackType::typeToSectionHeader(const Type& t) +{ + switch (t) { + case TrkTrack: return "Detailed Tracks"; + case TrackParticle: return "Track Particles"; + case TruthTrack: return "Truth Tracks"; + case FatrasTruthTrack: return "Fatras Truth Tracks"; + case RefittedTrack: return "Refitted Tracks"; + case TrkSegment: return "Track Segments"; + case AnalysisObject: return "Analysis Objects"; + case xAOD: return "xAOD"; + case Unknown: return "Unknown"; + default: return "Error"; + } +} + +//______________________________________________ +TrackType::Type TrackType::sectionHeaderToType(const QString&str, bool & status) +{ + status = true; + if (str=="Detailed Tracks") return TrkTrack; + if (str=="Track Particles") return TrackParticle; + if (str=="Truth Tracks") return TruthTrack; + if (str=="Fatras Truth Tracks") return FatrasTruthTrack; + if (str=="Refitted Tracks") return RefittedTrack; + if (str=="Track Segments") return TrkSegment; + if (str=="Analysis Objects") return AnalysisObject; + if (str=="xAOD") return xAOD; + if (str=="Unknown") return Unknown; + status = false; + return Unknown; +} + +//______________________________________________ +QString TrackType::typeToSectionHeaderToolTip(const Type& t) +{ + switch (t) { + case TrkTrack: return "Trk::Track's (detailed track objects as output by reconstruction)"; + case TrackParticle: return "TrackParticle's (summarized track objects, typically found in AOD's)"; + case TruthTrack: return "Truth Tracks (truth tracks, determined by combining the HepMC event record with simulation hits)"; + case FatrasTruthTrack: return "Fatras Truth Tracks (detailed track objects, but constructed directly by Fatras rather than being the output of reconstruction)"; + case RefittedTrack: return "Trk::Track's resulting from interactive refits within VP1"; + case TrkSegment: return "Track Segments (track parts found in a single muon chamber or ID part. These are usually input to higher level global track reconstruction algorithms)"; + case AnalysisObject: return "AOD Analysis Objects (high level reconstruction objects, such as Muons, egamma etc)"; + case xAOD: return "xAOD Analysis Objects (high level reconstruction objects, such as Muons, egamma etc)"; + case Unknown: return "Unknown"; + default: return "Error"; + } +} diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrkObjToString.cxx b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrkObjToString.cxx new file mode 100644 index 000000000..cbe97286d --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrkObjToString.cxx @@ -0,0 +1,424 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "VTI12TrackSystems/TrkObjToString.h" +#include "VP1Base/VP1Msg.h" + +//Parameters +#include "TrkParameters/TrackParameters.h" + +//DetectorElements +#include "ScintReadoutGeometry/ScintDetectorElement.h" +// #include "InDetReadoutGeometry/SiDetectorElement.h" + +//MeasurementBase +#include "TrkMeasurementBase/MeasurementBase.h" + +//ROTs +#include "TrkRIO_OnTrack/RIO_OnTrack.h" +// #include "InDetRIO_OnTrack/PixelClusterOnTrack.h" +// #include "InDetRIO_OnTrack/SCT_ClusterOnTrack.h" +// #include "InDetRIO_OnTrack/TRT_DriftCircleOnTrack.h" +// #include "InDetRIO_OnTrack/SiClusterOnTrack.h" + +//CompetingROTs +#include "TrkCompetingRIOsOnTrack/CompetingRIOsOnTrack.h" + +//Pseudo Measurements +#include "TrkPseudoMeasurementOnTrack/PseudoMeasurementOnTrack.h" + +//Segments +#include "TrkSegment/Segment.h" + +// PRDs +// #include "InDetPrepRawData/PixelCluster.h" +// #include "InDetPrepRawData/SCT_Cluster.h" +// #include "InDetPrepRawData/TRT_DriftCircle.h" + +//TrkMaterialOnTrack +#include "TrkMaterialOnTrack/MaterialEffectsOnTrack.h" +#include "TrkMaterialOnTrack/EnergyLoss.h" +#include "TrkMaterialOnTrack/MaterialEffectsBase.h" +#include "TrkMaterialOnTrack/EstimatedBremOnTrack.h" +#include "TrkMaterialOnTrack/ScatteringAngles.h" + +TrkObjToString::MeasurementType +TrkObjToString::type(const Trk::PrepRawData* /*prd*/) +{ + // if (dynamic_cast<const InDet::PixelCluster*> (prd)) + // {return TrkObjToString::Pixel;} + // if (dynamic_cast<const InDet::SCT_Cluster*> (prd)) + // {return TrkObjToString::SCT;} + + return TrkObjToString::Unknown; // Couldn't cast ROT to anything known +} + +TrkObjToString::MeasurementType +TrkObjToString::type(const Trk::MeasurementBase* meas) +{ + if (dynamic_cast<const Trk::RIO_OnTrack*>(meas)){ + // ROTS + // if (dynamic_cast<const InDet::PixelClusterOnTrack*> (meas)) + // {return TrkObjToString::Pixel;} + // if (dynamic_cast<const InDet::SCT_ClusterOnTrack*> (meas)) + // {return TrkObjToString::SCT;} + } else { + // Other types + if (dynamic_cast<const Trk::CompetingRIOsOnTrack*>(meas) ) + {return TrkObjToString::CompetingROT;} + if (dynamic_cast<const Trk::PseudoMeasurementOnTrack*>(meas) ) + {return TrkObjToString::PseudoMeasurement;} + if (dynamic_cast<const Trk::Segment*>(meas) ) + {return TrkObjToString::Segment;} + } + return TrkObjToString::Unknown; // Couldn't cast ROT to anything known +} + +TrkObjToString::MeasurementType +TrkObjToString::type(const Trk::TrkDetElementBase* /*detEl*/){ + // const InDetDD::SiDetectorElement* siDetEl = dynamic_cast<const InDetDD::SiDetectorElement*> (detEl); + // if (siDetEl){ + // if (siDetEl->isSCT()) {return TrkObjToString::SCT;} + // } + return TrkObjToString::Unknown; // Couldn't cast ROT to anything known +} + +QString TrkObjToString::name(const Trk::MeasurementBase& mb) +{ + MeasurementType tmptype = type(&mb); + std::string tmpname = typeName( tmptype ); + + if (tmptype==CompetingROT) { + const Trk::CompetingRIOsOnTrack* crot = dynamic_cast<const Trk::CompetingRIOsOnTrack *>(&mb); + if (!crot) return QString("Error!"); + tmpname+=" ["; + switch (type (&crot->rioOnTrack(crot->indexOfMaxAssignProb() ) ) ){ + // case Pixel: { tmpname+="Pix"; break; } + case SCT: { tmpname+="SCT"; break; } + case Hole: + case CompetingROT: + case PseudoMeasurement: + case Segment: + case Unknown: + { + tmpname+="Error!"; + break; + } + } + tmpname+="]"; + } + + return QString(tmpname.c_str()); +} + +QString +TrkObjToString::name(const Trk::TrackParameters& tp){ + QString name; + if (tp.covariance()) name="Measured"; + if (dynamic_cast<const Trk::Perigee*>(&tp)) name+="Perigee"; + if (dynamic_cast<const Trk::AtaPlane*>(&tp)) name+="AtaPlane"; + if (dynamic_cast<const Trk::AtaCylinder*>(&tp)) name+="AtaCylinder"; + if (dynamic_cast<const Trk::AtaStraightLine*>(&tp)) name+="AtaStraightLine"; + if (dynamic_cast<const Trk::AtaDisc*>(&tp)) name="AtaDisc"; + if (dynamic_cast<const Trk::AtaCone*>(&tp)) name="AtaCone"; + if (dynamic_cast<const Trk::CurvilinearParameters*>(&tp)) name="Curvilinear"; + if (name=="") std::cout<<"Unknown type of parameter"<<tp<<std::endl; + return name+=QString(" Parameters"); +} + +QString +TrkObjToString::name(const Trk::MaterialEffectsBase& mb){ + QString name("Unknown"); + if (dynamic_cast<const Trk::MaterialEffectsOnTrack*>(&mb)) name="MaterialEffectsOnTrack"; + if (dynamic_cast<const Trk::EstimatedBremOnTrack*>(&mb)) name="EstimatedBremOnTrack"; + return name; +} + +QString +TrkObjToString::name(const Trk::FitQuality& /**mb*/){ + return QString("FitQuality"); +} + +QString +TrkObjToString::shortInfo(const Trk::MeasurementBase& mb) +{ + MeasurementType tmptype = type(&mb); + QString info; + switch (tmptype){ + case SCT: + case Hole: + { + addBaseROTInfo(info,mb); + break; + } + case CompetingROT: + { + info+="Contains "; + const Trk::CompetingRIOsOnTrack* tmpCROT = dynamic_cast<const Trk::CompetingRIOsOnTrack*>(&mb); + if (tmpCROT){ + info+=QString::number(tmpCROT->numberOfContainedROTs()); + info+=QString::number(tmpCROT->numberOfContainedROTs()); + info+=" ROTs"; + } + break; + } + case PseudoMeasurement: + case Segment: + case Unknown: + { + info+="Not yet implemented."; + break; + } + } + return info; +} + +void +TrkObjToString::addBaseROTInfo(QString& info, const Trk::MeasurementBase& mb) +{ + info.append("Local: ("); + info.append( QString::number(mb.localParameters ()[Trk::loc1] ) ); + if (mb.localParameters ().dimension()==2 ) { + info.append(", "); + info.append( QString::number(mb.localParameters ()[Trk::loc2] ) ); + } + info.append(")."); +} + +QString +TrkObjToString::shortInfo(const Trk::TrackParameters& tp){ + const Amg::Vector2D & locPos= tp.localPosition (); + QString info ("Local: ("); + info+= QString::number(locPos[Trk::loc1] ); + info+=", "; + info+= QString::number(locPos[Trk::loc2] ); + info+=") [CLHEP::mm], P="; + info+=VP1Msg::str(tp.momentum()/CLHEP::MeV); + info+=" [MeV], |P|="+VP1Msg::str(tp.momentum().mag()/CLHEP::GeV); + info+=" [GeV], |Pt|="+VP1Msg::str(tp.momentum().perp()/CLHEP::GeV); + info+=" [GeV]"; + + return info; +} + +QString +TrkObjToString::shortInfo(const Trk::MaterialEffectsBase& me){ + QString info; + + const Trk::MaterialEffectsOnTrack* meot = dynamic_cast<const Trk::MaterialEffectsOnTrack*>(&me); + const Trk::EstimatedBremOnTrack* ebot = dynamic_cast<const Trk::EstimatedBremOnTrack*>(&me); + if (meot) { + if (meot->energyLoss()) + { + info.append("Energy loss [MeV]: "); + if (meot->energyLoss()->sigmaPlusDeltaE()==meot->energyLoss()->sigmaMinusDeltaE()){ + info+=QString::number(meot->energyLoss()->deltaE()/CLHEP::MeV); + info.append(" +/- "); + info+=QString::number(meot->energyLoss()->sigmaPlusDeltaE()/CLHEP::MeV); + } else { + info+=QString::number(meot->energyLoss()->deltaE()/CLHEP::MeV); + info.append(" +/- "); + info+=QString::number(meot->energyLoss()->sigmaPlusDeltaE()/CLHEP::MeV); + info+="/"; + info+=QString::number(meot->energyLoss()->sigmaMinusDeltaE()/CLHEP::MeV); + } + } + if (meot->scatteringAngles()) + { + if (meot->energyLoss()) info.append(", "); + info.append("Delta phi: ("); + info+=QString::number(meot->scatteringAngles()->deltaPhi()); + info.append(" +/- "); + info+=QString::number(meot->scatteringAngles()->sigmaDeltaPhi()); + info.append("), Delta theta: ("); + info+=QString::number(meot->scatteringAngles()->deltaTheta()); + info.append(" +/- "); + info+=QString::number(meot->scatteringAngles()->sigmaDeltaTheta()); + info.append(")"); + } + } else if (ebot) { + info="Not yet implemented."; + } else { + info="Not known!"; + } + return info; +} + +QString +TrkObjToString::shortInfo(const Trk::FitQuality& fqos){ + QString info("(Chi^2, DOF)=("); + info+=QString::number(fqos.chiSquared()); + info.append(", "); + info+=QString::number(fqos.numberDoF()); + info.append(")"); + return info; +} + +QStringList +TrkObjToString::fullInfo(const Trk::TrackParameters& tp) +{ + const Amg::Vector2D & locPos= tp.localPosition (); + QStringList info ("Local"); + info+= "("+QString::number(locPos[Trk::loc1] ) +", "+ QString::number(locPos[Trk::loc2] )+") [CLHEP::mm]"; + info+="Momentum"; + info+=VP1Msg::str(tp.momentum()/CLHEP::MeV)+" [MeV], |P|=("+VP1Msg::str(tp.momentum().mag()/CLHEP::GeV)+") [GeV], |Pt|=(" + +VP1Msg::str(tp.momentum().perp()/CLHEP::GeV)+") [GeV]"; + info+="Parameters"; + QString parameters="("; + for (int i = 0; i< tp.parameters().rows(); i++){ + parameters+=VP1Msg::str((tp.parameters())[i]); + if (i<(tp.parameters().rows()-1)) parameters+=", "; + } + info+=parameters+")"; + return info; +} + +QStringList +TrkObjToString::fullInfo(const Trk::FitQuality& fqos){ + QStringList info("Chi^2"); + info+=QString::number(fqos.chiSquared()); + info+="NDF"; + info+=QString::number(fqos.numberDoF()) ; + return info; +} + +QStringList +TrkObjToString::fullInfo(const Trk::MaterialEffectsBase& me){ + QStringList info; + + const Trk::MaterialEffectsOnTrack* meot = dynamic_cast<const Trk::MaterialEffectsOnTrack*>(&me); + const Trk::EstimatedBremOnTrack* ebot = dynamic_cast<const Trk::EstimatedBremOnTrack*>(&me); + if (meot) { + if (meot->energyLoss()) + { + info.append("Energy loss"); + if (meot->energyLoss()->sigmaPlusDeltaE()==meot->energyLoss()->sigmaMinusDeltaE()){ + info+=QString::number(meot->energyLoss()->deltaE()/CLHEP::MeV)+QString(" +/- ")+QString::number(meot->energyLoss()->sigmaPlusDeltaE()/CLHEP::MeV)+QString(" [MeV]"); + } else { + info+=QString::number(meot->energyLoss()->deltaE()/CLHEP::MeV)+QString(" +/- ") + +QString::number(meot->energyLoss()->sigmaPlusDeltaE()/CLHEP::MeV)+QString("/")+QString::number(meot->energyLoss()->sigmaMinusDeltaE()/CLHEP::MeV) + +QString(" [MeV]"); + } + } + if (meot->scatteringAngles()) + { + info.append("Delta phi"); + info+=QString::number(meot->scatteringAngles()->deltaPhi())+QString(" +/- ")+QString::number(meot->scatteringAngles()->sigmaDeltaPhi()); + info+="Delta theta"; + info+=QString::number(meot->scatteringAngles()->deltaTheta())+QString(" +/- ")+QString::number(meot->scatteringAngles()->sigmaDeltaTheta()); + } + } else if (ebot) { + info+="Not yet implemented."; + info+=""; + } else { + info+="Not known!"; + info+=""; + } + return info; +} + +QStringList +TrkObjToString::fullInfo(const Trk::MeasurementBase& meas) +{ + + QStringList info ("Local"); + + QString posInfo = QString("(") + QString::number(meas.localParameters ()[Trk::loc1]) ; + if (meas.localParameters ().dimension()==2 ) { + posInfo.append(", "); + posInfo.append( QString::number(meas.localParameters ()[Trk::loc2] ) ); + } + posInfo.append(") [CLHEP::mm]"); + info+= posInfo; + + const Amg::MatrixX& err = meas.localCovariance(); + info+="Error"; + + int dim= err.rows(); + QString errInfo=QString("(") + QString::number(err(0,0)); + if (dim==1){ + errInfo+=")"; + info+=errInfo; + + } else { + // assuming 2-dim! + errInfo+=","; + errInfo+=QString::number(err(0,1)); + info+=errInfo; + //row 2 + info+=QString(""); + info+=(QString("(") + QString::number(err(1,0))+QString(",")+QString::number(err(1,1))+QString(")")); + } + + // Okay, now let's get specific! + const Trk::RIO_OnTrack* rot = dynamic_cast<const Trk::RIO_OnTrack*>(&meas); + if (rot) addFullInfo(info,rot); + + const Trk::CompetingRIOsOnTrack* crot= dynamic_cast<const Trk::CompetingRIOsOnTrack*>(&meas); + if (crot) addFullInfo(info,crot); + + const Trk::PseudoMeasurementOnTrack* pmeas= dynamic_cast<const Trk::PseudoMeasurementOnTrack*>(&meas); + if (pmeas) addFullInfo(info,pmeas); + + const Trk::Segment* seg= dynamic_cast<const Trk::Segment*>(&meas); + if (seg) addFullInfo(info,seg); + + return info; +} + +void +TrkObjToString::addFullInfo(QStringList& info, const Trk::RIO_OnTrack* rot){ + // ROTS + info+="Identifier"; + info+=QString::number(rot->identify().get_compact()); + info+="Local"; + QString locParams="("+QString::number(rot->localParameters ()[Trk::loc1] ); + if (rot->localParameters ().dimension()==2 ) { + locParams.append(", "); + locParams.append( QString::number(rot->localParameters ()[Trk::loc2] ) ); + } + locParams.append(")"); + info+=locParams; + // const InDet::PixelClusterOnTrack* pix =dynamic_cast<const InDet::PixelClusterOnTrack*> (rot); + // if (pix) { + // info+="Cluster Ambiguity"; + // info+=pix->hasClusterAmbiguity () ? "True": "False"; + // info+="Fake"; + // info+=pix->isFake () ? "True": "False"; + // info+="Energy Loss"; + // info+=QString::number(pix->energyLoss ())+QString(" [Mev]"); + // return; + // } + + // const InDet::SCT_ClusterOnTrack* sct =dynamic_cast<const InDet::SCT_ClusterOnTrack*> (rot); + // if (sct) { + // //Nothing yet + // return; + // } + +} + +void +TrkObjToString::addFullInfo(QStringList& info, const Trk::CompetingRIOsOnTrack* crot) +{ + info+="Contains IDs"; + unsigned int nrio = crot->numberOfContainedROTs(); + QString rots; + for (unsigned int n = 0; n < nrio; n++) + { + rots+=QString::number(crot->rioOnTrack(n).identify().get_compact()); + if (n<(nrio-1)) rots+=", "; + } + info+=rots; +} + +void +TrkObjToString::addFullInfo(QStringList& /**info*/, const Trk::PseudoMeasurementOnTrack*) +{ +} + +void +TrkObjToString::addFullInfo(QStringList& /**info*/, const Trk::Segment*) +{ +} diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/VP1TrackSanity.cxx b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/VP1TrackSanity.cxx new file mode 100644 index 000000000..73b1d6ef0 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/VP1TrackSanity.cxx @@ -0,0 +1,109 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class VP1TrackSanity // +// // +// Authors: Edward Moyse (Edward.Moyse@cern.ch) // +// Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: March 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12TrackSystems/VP1TrackSanity.h" +#include "VTI12Utils/VP1DetInfo.h" +#include "TrkTrack/Track.h" +#include "TrkTrack/TrackStateOnSurface.h" +#include "TrkMeasurementBase/MeasurementBase.h" +#include "TrkRIO_OnTrack/RIO_OnTrack.h" +#include "TrkPrepRawData/PrepRawData.h" +#include "TrkSurfaces/Surface.h" + +//____________________________________________________________________ +class VP1TrackSanity::Imp { +public: +}; + +//____________________________________________________________________ +VP1TrackSanity::VP1TrackSanity(IVP1System*sys) + : VP1HelperClassBase(sys,"VP1TrackSanity"), m_d(new Imp) +{ + messageVerbose("constructor"); + if (sys) + VP1DetInfo::ensureInit(sys); +} + +//____________________________________________________________________ +VP1TrackSanity::~VP1TrackSanity() +{ + delete m_d; +} + +//____________________________________________________________________ +bool VP1TrackSanity::isSafe(const Trk::TrackStateOnSurface* tsos ) const +{ + if (!tsos) + return false; + //Fixme: More! + return true; +} + +//____________________________________________________________________ +bool VP1TrackSanity::isSafe(const Trk::TrackParameters* pars ) const +{ + if (!pars) + return false; + if (!(&pars->associatedSurface())) + return false; + //Fixme: More! + return true; +} + +//____________________________________________________________________ +bool VP1TrackSanity::isSafe(const Trk::MeasurementBase* meas ) const +{ + if (!meas) + return false; + //TK: The following is mainly guess work - we need master Ed to implement really useful stuff! + if (!&meas->associatedSurface()) + return false; + if (!meas->associatedSurface().associatedDetectorElement()) + return false; + if (!meas->associatedSurface().associatedDetectorElementIdentifier().is_valid()) + return false; + const Trk::RIO_OnTrack* rio = dynamic_cast<const Trk::RIO_OnTrack*>(meas); + if (rio) { + if (VP1DetInfo::isUnsafe(rio->identify())) + return false; + if ( !rio->detectorElement() ) + return false; + } + return true; +} + +//____________________________________________________________________ +bool VP1TrackSanity::isSafe(const Trk::RIO_OnTrack* rio ) const +{ + if (!rio) + return false; + //TK: The following is mainly guess work - we need master Ed to implement really useful stuff! + if (VP1DetInfo::isUnsafe(rio->identify())) + return false; + + if (!rio->detectorElement()) + return false; + return true; +} + +//____________________________________________________________________ +bool VP1TrackSanity::isSafe( const Trk::PrepRawData* prd ) const +{ + if (!prd) + return false; + if (VP1DetInfo::isUnsafe(prd->identify())) + return false; + return true; +} diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/VP1TrackSummary.cxx b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/VP1TrackSummary.cxx new file mode 100644 index 000000000..7badd4209 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/VP1TrackSummary.cxx @@ -0,0 +1,101 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class VP1TrackSummary // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: November 2009 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12TrackSystems/VP1TrackSummary.h" +#include "VTI12Utils/VP1DetInfo.h" +#include "FaserDetDescr/FaserDetectorID.h" + +#include "TrkTrack/Track.h" +#include "TrkTrack/TrackStateOnSurface.h" +#include "TrkSurfaces/Surface.h" +#include "TrkMeasurementBase/MeasurementBase.h" +#include "TrkDetElementBase/TrkDetElementBase.h" +#include "TrkRIO_OnTrack/RIO_OnTrack.h" +#include "TrkCompetingRIOsOnTrack/CompetingRIOsOnTrack.h" +#include "TrkSegment/Segment.h" + +#include <iostream> +//____________________________________________________________________ +bool VP1TrackSummary::countHits( const Trk::Track* trk, + unsigned& nSCTHits + ) +{ + nSCTHits = 0; + if (!trk) + return false; + + const FaserDetectorID * idhelper = VP1DetInfo::faserIDHelper(); + if (!idhelper) + return false; + + std::set<const Trk::TrkDetElementBase*> detelems;// Need several to handle #$$%ing cROTs. EJWM + DataVector<const Trk::TrackStateOnSurface>::const_iterator tsos_iter = trk->trackStateOnSurfaces()->begin(); + DataVector<const Trk::TrackStateOnSurface>::const_iterator tsos_end = trk->trackStateOnSurfaces()->end(); + for (; tsos_iter != tsos_end; ++tsos_iter) { + const Trk::MeasurementBase* meas = *tsos_iter ? (*tsos_iter)->measurementOnTrack() : 0; + VP1TrackSummary::addCounts(detelems, meas, idhelper, nSCTHits); + } + return true; +} + +//____________________________________________________________________ +bool VP1TrackSummary::countHits( const Trk::Segment* seg, + unsigned& nSCTHits + ) +{ + nSCTHits = 0; + if (!seg) + return false; + + const FaserDetectorID * idhelper = VP1DetInfo::faserIDHelper(); + if (!idhelper) + return false; + + std::set<const Trk::TrkDetElementBase*> detelems;// Need several to handle #$$%ing cROTs. EJWM + std::vector< const Trk::MeasurementBase * >::const_iterator tsos_iter = seg->containedMeasurements().begin(), tsos_end = seg->containedMeasurements().end(); + for (; tsos_iter != tsos_end; ++tsos_iter) { + const Trk::MeasurementBase* meas = *tsos_iter; + addCounts(detelems, meas, idhelper, nSCTHits); + } + return true; +} + +void VP1TrackSummary::addCounts( std::set<const Trk::TrkDetElementBase*>& detelems, const Trk::MeasurementBase* meas, + const FaserDetectorID * idhelper, + unsigned& nSCTHits + ) +{ + const Trk::CompetingRIOsOnTrack* crot = dynamic_cast<const Trk::CompetingRIOsOnTrack*>(meas); + + if (crot){ + unsigned int i = 0; + for (;i<crot->numberOfContainedROTs();++i){ + detelems.insert(crot->rioOnTrack(i).detectorElement()); + } + }else if (meas) { + const Trk::Surface * surf = &(meas->associatedSurface()); + detelems.insert( surf ? surf->associatedDetectorElement() : 0); + } + + std::set<const Trk::TrkDetElementBase*>::const_iterator it = detelems.begin(), itEnd=detelems.end(); + for (;it!=itEnd;++it){ + const Trk::TrkDetElementBase* detelem=*it; + if (!detelem) continue; + Identifier id = detelem->identify(); + if (!id.is_valid()) + continue; + if (idhelper->is_sct(id)) ++nSCTHits; + } + detelems.clear(); +} diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/VP1TrackSystem.cxx b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/VP1TrackSystem.cxx new file mode 100644 index 000000000..fab021647 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/VP1TrackSystem.cxx @@ -0,0 +1,940 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class VP1TrackSystem // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: February 2008 // +// // +//////////////////////////////////////////////////////////////// + +//TODO: Features in old system that are missing now (+ stuff really needed): +// +// --> short term: +// colour by clicked vertex +// check inner detector projections +// +// --> medium term: +// refit tracks +// +// --> longer term: +// object browser +// sdo's +// +// soonish: detail levels depending on meas. type, and colour-by +// depending on collection. + +#include "VTI12TrackSystems/VP1TrackSystem.h" +#include "VTI12TrackSystems/TrackSystemController.h" +#include "VTI12TrackSystems/TrackHandleBase.h" +#include "VTI12TrackSystems/TrackLODManager.h" +#include "VTI12TrackSystems/TrackCollWidget.h" +#include "VTI12TrackSystems/AscObjSelectionManager.h" +#include "VTI12TrackSystems/AssociatedObjectHandleBase.h" +#include "VTI12TrackSystems/AscObj_TSOS.h" +#include "VTI12TrackSystems/TrackSysCommonData.h" + +#include "VTI12TrackSystems/TrackCollHandle_TrkTrack.h" +// #include "VTI12TrackSystems/TrackCollHandle_TrkSegment.h" +// #include "VP1TrackSystems/TrackCollHandle_FatrasTruthTracks.h" +#include "VTI12TrackSystems/TrackCollHandle_TruthTracks.h" +// #include "VTI12TrackSystems/TrackCollHandle_TrackParticle.h" +// #include "VTI12TrackSystems/TrackCollHandle_xAODTrackParticle.h" +#include "VTI12TrackSystems/TrackHandle_TrkTrack.h" +#include "VTI12TrackSystems/TrackCollHandle_RefittedTracks.h" + +#include "VP1Base/VP1CameraHelper.h" +#include "VP1Base/VisibleObjectToMaterialHelper.h" +#include "VP1Base/SoCooperativeSelection.h" +#include "VP1Base/VP1Serialise.h" +#include "VP1Base/VP1Deserialise.h" +#include "VP1Base/VP1Msg.h" + +#include "VTI12Utils/VP1DetInfo.h" + +// #include "VTI12GuideLineSystems/InDetProjHelper.h" + +#include <Inventor/nodes/SoSeparator.h> +#include <Inventor/nodes/SoMaterial.h> +#include <Inventor/nodes/SoSwitch.h> +#include <Inventor/nodes/SoComplexity.h> +#include <Inventor/nodes/SoLineSet.h> +#include <Inventor/nodes/SoVertexProperty.h> +#include "Inventor/nodes/SoDrawStyle.h" +#include "Inventor/nodes/SoLightModel.h" +#include <Inventor/nodes/SoCylinder.h> +#include <Inventor/SoPath.h> +#include <Inventor/nodes/SoFont.h> + +//#include "TrkEventPrimitives/GlobalPosition.h" +//#include "TrkEventPrimitives/GlobalMomentum.h" +#include "TrkEventPrimitives/FitQuality.h" +#include <sstream> + +#include "StoreGate/StoreGateSvc.h" + +//////////////////////////////////////////////////////// +//FIXME: ONLY HERE TEMPORARILY. WE NEED A HELPER CLASS!! +#include "TrkFitterInterfaces/ITrackFitter.h" +#include "TrkTrack/Track.h" +#include "TrkRIO_OnTrack/RIO_OnTrack.h" +#include "TrkTrack/TrackStateOnSurface.h" +#include "TrkMeasurementBase/MeasurementBase.h" +#include "TrkParameters/TrackParameters.h" +#include "TrkPrepRawData/PrepRawData.h" +#include "VP1Utils/VP1ToolAccessHelper.h" +#include "VP1Utils/VP1AvailableToolsHelper.h" +//////////////////////////////////////////////////////// + + +// FOR DEBUG +//#include "MuonIdHelpers/MdtIdHelper.h" +//#include "MuonIdHelpers/MuonIdHelper.h" + + + +//____________________________________________________________________ +class VP1TrackSystem::Imp { +public: + VP1TrackSystem * theclass; + TrackSysCommonData * common; + SoCooperativeSelection * sel_tracks; + AscObjSelectionManager * ascObjSelManager; + TrackCommonFlags::SELECTIONMODE selMode; + + // InDetProjFlags::DetTypeFlags lastEmittedUsedIDProjections; + // InDetProjFlags::DetTypeFlags currentUsedIDProjections() const; + + SoSeparator * totmomsep; + SoLineSet * totmomline; + Amg::Vector3D totmomgev; + double totmass; + + QList<const Trk::PrepRawData*> selectedPRDs; + + //Return value is number of track handles used for input (e.g. those without valid momentum info are ignored) + unsigned calcTotalMomentumOfSelectedHandles(Amg::Vector3D& totmom, Amg::Vector3D& totpos, double& mass); + + template <class T> + QList<TrackCollHandleBase*> createSpecificCollections() { + QList<TrackCollHandleBase*> l; + foreach (QString name, T::availableCollections(theclass)) { + T * col = new T(common,name); + col->init(); + l << col; + } + return l; + } + QList<TrackCollHandleBase*> createCollections() { + QList<TrackCollHandleBase*> l; + l << createSpecificCollections<TrackCollHandle_TrkTrack>(); + // l << createSpecificCollections<TrackCollHandle_TrkSegment>(); + l << createSpecificCollections<TrackCollHandle_TruthTracks>(); + // l << createSpecificCollections<TrackCollHandle_TrackParticle>(); + // l << createSpecificCollections<TrackCollHandle_xAODTrackParticle>(); + + return l; + } + std::vector<std::map<GeoPVConstLink, float> > chamberT0s; + std::map<const Trk::Track*, SoMaterial*> vertexMaterialForTrackBases; +}; + +//____________________________________________________________________ +VP1TrackSystem::VP1TrackSystem(QString name) + : IVP13DSystemSimple(name, + "System showing all track-like objects.", + "Edward.Moyse@cern.ch, Thomas.Kittelmann@cern.ch"), m_d(new Imp) +{ + m_d->theclass = this; + m_d->sel_tracks = 0; + m_d->common = 0; + m_d->totmomsep = 0; + m_d->totmomline = 0; + m_d->totmomgev = Amg::Vector3D(0,0,0); + m_d->ascObjSelManager = 0; + m_d->selMode = TrackCommonFlags::SINGLEOBJECT; + // m_d->lastEmittedUsedIDProjections = InDetProjFlags::NoDet; +} + +//____________________________________________________________________ +VP1TrackSystem::~VP1TrackSystem() +{ + delete m_d; +} + +//____________________________________________________________________ +void VP1TrackSystem::systemcreate(StoreGateSvc* /*detstore*/) +{ + messageVerbose("systemcreate"); + ensureBuildController(); + m_d->common->controller()->initTools(); + + // connect(m_d->common->controller(),SIGNAL(shownTrackPartsChanged(TrackCommonFlags::TrackPartsFlags)), + // this,SLOT(possiblyEmitUsedIDProjectionsChanged())); + // connect(m_d->common->controller()->collWidget(),SIGNAL(visibleStdCollectionsChanged(const QList<VP1StdCollection*>&)), + // this,SLOT(possiblyEmitUsedIDProjectionsChanged())); + // possiblyEmitUsedIDProjectionsChanged(); + +} + +//____________________________________________________________________ +void VP1TrackSystem::systemuncreate() +{ + messageVerbose("systemuncreate"); + if (m_d->totmomsep) { + m_d->totmomsep->unref(); + m_d->totmomsep=0; + } + if (m_d->totmomline) { + m_d->totmomline->unref(); + m_d->totmomline = 0; + } + delete m_d->common; m_d->common = 0; +} + +//____________________________________________________________________ +QWidget * VP1TrackSystem::buildController() +{ + messageVerbose("buildController start"); + TrackSystemController * controller = new TrackSystemController(this); + m_d->common = new TrackSysCommonData(this,controller);//Fixme: Do this on-demand in buildeventscenegraph!! + controller->setCommonData(m_d->common); + + connect(controller,SIGNAL(selectionModeChanged(TrackCommonFlags::SELECTIONMODE)),this,SLOT(updateSelectionMode())); + updateSelectionMode(); + connect(controller,SIGNAL(showTotMomentumOnMultiTrackSelectionChanged(bool)),this,SLOT(updateShownTotMomentum())); + updateShownTotMomentum(); + + connect(controller,SIGNAL(refit()),this,SLOT(refit()));//temp. + + controller->setNumberOfSelectedPRDsAndTracks(m_d->selectedPRDs.count(),0); + + messageVerbose("buildController end"); + return controller; +} + +//____________________________________________________________________ +void VP1TrackSystem::buildEventSceneGraph(StoreGateSvc* /*sg*/, SoSeparator *root) +{ + messageVerbose("buildEventSceneGraph start2"); + + // set complexity to a lower value, so that e.g. the straws are manageable + SoComplexity * complexity = new SoComplexity; + complexity->value.setValue(0.3f);//Fixme: Hardcoded here and elsewhere (fixme: Recheck all complexity values!) + root->addChild(complexity); + root->addChild(m_d->common->controller()->ascObjDrawStyle()); + root->addChild(m_d->common->controller()->ascObjComplexity());//this will be inherited to the tracks + // (but giving no effect) + + m_d->sel_tracks = new SoCooperativeSelection; + m_d->sel_tracks->activePolicy = SoCooperativeSelection::ACTIVE; + m_d->sel_tracks->ref(); + registerSelectionNode(m_d->sel_tracks); + // m_d->sel_tracks->addChild(m_d->common->controller()->trackLightModel()); + // m_d->sel_tracks->addChild(m_d->common->controller()->trackDrawStyle()); + + m_d->ascObjSelManager = new AscObjSelectionManager (root,this,m_d->common->controller()); + m_d->common->setEventData(m_d->ascObjSelManager);//commondata assumes ownership of ascObjMgr. + m_d->common->trackLODManager()->setAttachNode(m_d->ascObjSelManager->getAscObjAttachSep()); + +// reset last selected trk + m_d->common->setLastSelectedTrack(0); + updateSelectionMode(); + + if (!m_d->common->m_textSep) { + // FIXME! + // std::cout<<"Making new Text sep"<<std::endl; + m_d->common->m_textSep = new SoSeparator; + m_d->common->m_textSep->setName("TextSep"); + m_d->common->m_textSep->ref(); + } + root->addChild(m_d->common->m_textSep); + + // Fixme - what if font is missing? + SoFont *myFont = new SoFont; + myFont->name.setValue("Arial"); + myFont->size.setValue(12.0); + m_d->common->m_textSep->addChild(myFont); + + messageVerbose("createCollections start"); + + //Create collection list based on contents of event store, populate gui and apply states: + m_d->common->controller()->collWidget()->setCollections(m_d->createCollections()); + + //Add collections to event scenegraph: + foreach (VP1StdCollection* col,m_d->common->controller()->collWidget()->collections<VP1StdCollection>()) + m_d->sel_tracks->addChild(col->collSwitch()); + + root->addChild(m_d->sel_tracks); + if (!m_d->totmomsep) { + m_d->totmomsep = new SoSeparator; + m_d->totmomsep->ref(); + } + // m_d->totmomsep->addChild(m_d->common->controller()->trackDrawStyle()); + root->addChild(m_d->totmomsep); + + messageVerbose("buildEventSceneGraph end"); +} + + +//____________________________________________________________________ +void VP1TrackSystem::systemerase() +{ + messageVerbose("systemErase begin"); + + m_d->common->controller()->collWidget()->clear(); + messageVerbose("collWidget cleared"); + + if (m_d->common->controller()->trackObjBrowser()) m_d->common->controller()->trackObjBrowser()->clear(); + + m_d->common->clearEventData(); + if (m_d->sel_tracks) { + unregisterSelectionNode(m_d->sel_tracks); + m_d->sel_tracks->unref(); + m_d->sel_tracks=0; + } + + if (m_d->totmomsep) + m_d->totmomsep->removeAllChildren(); + + if (m_d->common->m_textSep) // FIXME! + m_d->common->m_textSep->removeAllChildren(); + + m_d->totmomgev = Amg::Vector3D(0,0,0); + + if (VP1Msg::verbose()) { + if (AssociatedObjectHandleBase::numberOfInstances()!=0) + message("Warning: "+str(AssociatedObjectHandleBase::numberOfInstances()) + +" instances of AssociatedObjectHandleBase alive at end of systemerase(). " + "(ignore this warning if there is more than one track system instance)."); + if (TrackHandleBase::numberOfInstances()!=0) + message("Warning: "+str(TrackHandleBase::numberOfInstances()) + +" instances of TrackHandleBase alive at end of systemerase(). " + "(ignore this warning if there is more than one track system instance)."); + } + + std::map<const Trk::Track*, SoMaterial*>::iterator itMat = m_d->vertexMaterialForTrackBases.begin(); + std::map<const Trk::Track*, SoMaterial*>::iterator itMatEnd = m_d->vertexMaterialForTrackBases.end(); + for(;itMat!=itMatEnd;++itMat) { + SoMaterial* curmat = itMat->second; + curmat->unref(); + } + m_d->vertexMaterialForTrackBases.clear(); + for (unsigned int i=0;i<m_d->chamberT0s.size();++i) + m_d->chamberT0s.at(i).clear(); + + messageVerbose("systemErase end"); +} + +//____________________________________________________________________ +QByteArray VP1TrackSystem::saveState() +{ + //Version & base state: + VP1Serialise serialise(1/*version*/,this); + serialise.save(IVP13DSystemSimple::saveState());//Info from base class + + // Actual state info: + ensureBuildController(); + serialise.save(m_d->common->controller()->saveSettings()); + serialise.save((VP1CollectionWidget*)m_d->common->controller()->collWidget()); + + serialise.disableUnsavedChecks();//We do the testing in the controller + + return serialise.result(); +} + +//____________________________________________________________________ +void VP1TrackSystem::restoreFromState(QByteArray ba) +{ + //Version & base state: + VP1Deserialise state(ba,this); + if (state.version()==0) { + //We simply won't support .vp1 files from the old track system. + message("Warning: State data has obsolete format - ignoring!"); + return; + } + if (state.version()!=1) { + message("Warning: State data has wrong format - ignoring!"); + return; + } + + ensureBuildController(); + + IVP13DSystemSimple::restoreFromState(state.restoreByteArray()); + + m_d->common->controller()->restoreSettings(state.restoreByteArray()); + state.restore((VP1CollectionWidget*)m_d->common->controller()->collWidget()); + + state.disableUnrestoredChecks();//We do the testing in the controller +} + +//____________________________________________________________________ +void VP1TrackSystem::visibleObjectsChanged() +{ + VisibleObjectToMaterialHelper<Trk::Track>* trackhelper(dynamic_cast< VisibleObjectToMaterialHelper<Trk::Track>* >(sender())); + if (trackhelper) { + //Fixme: For now we re-encode in a vector, to get old signal/slot signatures. We should change that! + // -> and remember not to put const in front of the so materials!! + std::vector< std::pair<const Trk::Track*, const SoMaterial*> > vistracks; + vistracks.reserve(trackhelper->visibleObjects().size()); + std::map<const Trk::Track*,SoMaterial*>::const_iterator it, itE = trackhelper->visibleObjects().end(); + for (it = trackhelper->visibleObjects().begin();it!=itE;++it) + vistracks.push_back(std::pair<const Trk::Track*, const SoMaterial*>(it->first,it->second)); + messageVerbose("Emitting visibleTracksChanged (with nvistracks = "+QString::number(vistracks.size())+")" ); + emit visibleTracksChanged(vistracks); + return; + } + VisibleObjectToMaterialHelper<Trk::Segment>* segmenthelper(dynamic_cast<VisibleObjectToMaterialHelper<Trk::Segment>*>(sender())); + if (segmenthelper) { + //Fixme: For now we re-encode in a vector, to get old signal/slot signatures. We should change that! + // -> and remember not to put const in front of the so materials!! + std::vector< std::pair<const Trk::Segment*, const SoMaterial*> > vissegments; + vissegments.reserve(segmenthelper->visibleObjects().size()); + std::map<const Trk::Segment*,SoMaterial*>::const_iterator it, itE = segmenthelper->visibleObjects().end(); + for (it = segmenthelper->visibleObjects().begin();it!=itE;++it) + vissegments.push_back(std::pair<const Trk::Segment*, const SoMaterial*>(it->first,it->second)); + messageVerbose("Emitting visibleSegmentsChanged (with nvissegments = "+QString::number(vissegments.size())+")" ); + emit visibleSegmentsChanged(vissegments); + return; + } + message("unexpected signal received in visibleObjectsChanged slot"); +} + +// //____________________________________________________________________ +// void VP1TrackSystem::setApplicableIDProjections( InDetProjFlags::InDetProjPartsFlags pixel, +// InDetProjFlags::InDetProjPartsFlags sct, +// InDetProjFlags::InDetProjPartsFlags trt ) +// { +// messageVerbose("Signal received in setApplicableIDProjections slot"); +// ensureBuildController(); +// if (!m_d->common)//After uncreate. +// return; +// bool changes(false); +// if (m_d->common->indetProjHelper_Pixel()->parts() != pixel) { +// m_d->common->indetProjHelper_Pixel()->setParts(pixel); +// changes = true; +// } +// if (m_d->common->indetProjHelper_SCT()->parts() != sct) { +// m_d->common->indetProjHelper_SCT()->setParts(sct); +// changes = true; +// } +// if (m_d->common->indetProjHelper_TRT()->parts() != trt) { +// m_d->common->indetProjHelper_TRT()->setParts(trt); +// changes = true; +// } + +// if (changes) { +// messageVerbose(" => Flags changed."); +// if (m_d->common->controller()) +// foreach( TrackCollHandleBase* collhandle, m_d->common->controller()->collWidget()->collections<TrackCollHandleBase>() ) +// collhandle->updateInDetProjectionsOfAllHandles(); +// } else { +// messageVerbose(" => Flags unchanged."); +// } +// } + + +//____________________________________________________________________ +void VP1TrackSystem::updateSelectionMode() +{ + messageVerbose("updateSelectionMode start"); + if (!m_d->sel_tracks||!m_d->ascObjSelManager) { + messageVerbose("updateSelectionMode Warning: Ignoring due to null pointers."); + return; + } + deselectAll(); + m_d->ascObjSelManager->deselectAll(); + m_d->selMode = m_d->common->controller()->selectionMode();//NB: Don't abort if unchanged (we call this method to init) + if (m_d->selMode==TrackCommonFlags::TRACKFIT) { + messageVerbose("updateSelectionMode => TRACKFIT"); + m_d->sel_tracks->policy = SoCooperativeSelection::SINGLE; + m_d->ascObjSelManager->setMode(AscObjSelectionManager::SHIFT); + } else if (m_d->selMode==TrackCommonFlags::MULTITRACK) { + messageVerbose("updateSelectionMode => MULTITRACK"); + m_d->sel_tracks->policy = SoCooperativeSelection::TOGGLE; + m_d->ascObjSelManager->setMode(AscObjSelectionManager::SINGLE); + } else { + if (m_d->selMode!=TrackCommonFlags::SINGLEOBJECT) + message("updateSelectionMode ERROR: Unexpected selection mode flag"); + messageVerbose("updateSelectionMode => SINGLEOBJECT"); + m_d->sel_tracks->policy = SoCooperativeSelection::SINGLE; + m_d->ascObjSelManager->setMode(AscObjSelectionManager::SINGLE); + } + messageVerbose("updateSelectionMode end"); +} + +//____________________________________________________________________ +void VP1TrackSystem::userPickedNode(SoNode* pickedNode, SoPath* /*pickedPath*/) +{ + messageVerbose("userPickedNode"); + if (pickedNode==m_d->totmomline) { + message("Total momentum of selected tracks [GeV]: p = "+str(m_d->totmomgev)+", m = "+str(m_d->totmass/CLHEP::GeV)); + return; + } + + message("Unknown object clicked"); +} + +//____________________________________________________________________ +void VP1TrackSystem::userSelectedSingleNode( SoCooperativeSelection* sel, SoNode* node, SoPath* pickedPath ) +{ + messageVerbose("userSelectedSingleNode"); + AssociatedObjectHandleBase* pickedHandle(0); + if (!m_d->ascObjSelManager->handleUserSelectedSingleNode(sel,node,pickedPath,pickedHandle)) { + if (sel==m_d->sel_tracks) { + //Hack to get selections working when representing tracks with tubes: + if (node->getTypeId().isDerivedFrom(SoCylinder::getClassTypeId())) { + pickedPath->pop(); + node=pickedPath->getTail(); + } + TrackHandleBase * handle = m_d->common->trackHandle(node); + if (!handle) { + message("ERROR: Unknown track."); + return; + } + TrackHandle_TrkTrack * handle_trktrack = dynamic_cast<TrackHandle_TrkTrack *>(handle); + if (handle_trktrack&&m_d->selMode==TrackCommonFlags::TRACKFIT) { + messageVerbose("userSelectedSingleNode - find measurements for track fit"); + + QList<AssociatedObjectHandleBase*> trackmeas = handle_trktrack->getVisibleMeasurements(); + + if (trackmeas.size()==0) message("In refit mode, but no visible measurements found so can't do anything. Perhaps they're not enabled in 'Details'?"); + QList<AssociatedObjectHandleBase*> currentsel = m_d->ascObjSelManager->currentSelection(); + //If at least one of the track measurements is unselected, we + //select them all. Otherwise we deselect them. + bool oneunselected(false); + foreach(AssociatedObjectHandleBase* meas,trackmeas) { + if (!currentsel.contains(meas)) { + oneunselected = true; + break; + } + } + QList<const Trk::PrepRawData*> prdSet; + if (oneunselected) { + messageVerbose("userSelectedSingleNode - selecting " +QString::number(trackmeas.size()) + " measurements."); + m_d->ascObjSelManager->ensureSelected(trackmeas); + + // Add PRDs. Need to be careful as they might not exist. + foreach(AssociatedObjectHandleBase* meas,trackmeas) { + AscObj_TSOS* tsosAsc = dynamic_cast<AscObj_TSOS*>(meas); + if (tsosAsc && tsosAsc->rioOnTrack() && tsosAsc->rioOnTrack()->prepRawData()) prdSet.append(tsosAsc->rioOnTrack()->prepRawData()); + } + } else { + messageVerbose("userSelectedSingleNode - deselecting " +QString::number(trackmeas.size()) + " measurements."); + m_d->ascObjSelManager->ensureDeselected(trackmeas); + } + setSelectedPRDs(prdSet); // FIXME - maybe I should append/remove from existing list? + + m_d->sel_tracks->deselectAll(); + } else { + if (m_d->common->controller()->printInfoOnSingleSelection()){ + message(handle->clicked()); + messageVerbose("Emitting newTrackSelected "); + m_d->common->setLastSelectedTrack(handle); + emit newTrackSelected(*handle); + m_d->common->controller()->setNumberOfSelectedPRDsAndTracks(m_d->selectedPRDs.count(),1); // FIXME - we can do this more cleanly? + } + } + } else { + message("ERROR: Unknown selection."); + return; + } + } + if (m_d->common->controller()->orientAndZoomOnSingleSelection()) { + if (!pickedHandle||!pickedHandle->initiatesOwnZooms()) { + std::set<SoCamera*> cameras = getCameraList(); + std::set<SoCamera*>::iterator it,itE = cameras.end(); + for (it=cameras.begin();it!=itE;++it) + VP1CameraHelper::animatedZoomToPath(*it,sel,pickedPath,2.0,1.0); + } + } +} + +//____________________________________________________________________ +void VP1TrackSystem::userClickedOnBgd() +{ + messageVerbose("userClickedOnBgd"); + if (m_d->ascObjSelManager) + m_d->ascObjSelManager->userClickedOnBgd(); + m_d->common->setLastSelectedTrack(0); + QList<const Trk::PrepRawData*> prdSet; + setSelectedPRDs(prdSet ); // pass in empty collection. FIXME - this should depend on mode? +} + +//____________________________________________________________________ +void VP1TrackSystem::userDeselectedSingleNode(SoCooperativeSelection*, SoNode* , SoPath*) +{ + messageVerbose("userDeselectedSingleNode"); +} + +//____________________________________________________________________ +unsigned VP1TrackSystem::Imp::calcTotalMomentumOfSelectedHandles(Amg::Vector3D& totmom, Amg::Vector3D& totpos, double& mass) +{ + totmom = Amg::Vector3D(0,0,0); + totpos = Amg::Vector3D(0,0,0); + mass = 0; + if (!sel_tracks) + return 0; + unsigned nused(0); + double totenergy(0); + for (int i = 0; i < sel_tracks->getList()->getLength(); ++i) { + SoFullPath *fPath = static_cast<SoFullPath *>((*(sel_tracks->getList()))[i]); + TrackHandleBase * handle = common->trackHandle(fPath?fPath->getTail():0); + if (!handle) + continue; + Amg::Vector3D mom = handle->momentum(); + if (mom.mag2()==0.0) + continue; + //Fixme: Get actual position of perigee!! + const Amg::Vector3D * pos = handle->startPoint(); + if (!pos) + continue; + ++nused; + totmom += mom; + totpos += *pos; + mass = handle->hasMass() ? handle->mass() : 0; + totenergy += sqrt(mom.mag2() + mass*mass); + } + if (nused>1) { + double msq = totenergy*totenergy - totmom.mag2(); + mass = (msq<0?-1.0:1.0)*sqrt(fabs(msq)); + totpos /= nused; + } + return nused; +} + + +//____________________________________________________________________ +void VP1TrackSystem::updateShownTotMomentum() +{ + messageVerbose("updateShownTotMomentum"); + if (!m_d->common->controller()->showTotMomentumOnMultiTrackSelection()) { + //ensure detach: + messageVerbose(" => detach"); + if (m_d->totmomsep&&m_d->totmomline&&m_d->totmomsep->findChild(m_d->totmomline)>-1) + m_d->totmomsep->removeChild(m_d->totmomline); + return; + } + Amg::Vector3D totmom; + Amg::Vector3D totpos; + double totmass; + unsigned nused = m_d->calcTotalMomentumOfSelectedHandles(totmom,totpos,totmass); + if (nused==0) { + //ensure detach: + messageVerbose(" => detach"); + if (m_d->totmomsep&&m_d->totmomline&&m_d->totmomsep->findChild(m_d->totmomline)>-1) + m_d->totmomsep->removeChild(m_d->totmomline); + } else { + //ensure correct lineset: + Amg::Vector3D p2 = totpos+totmom.unit()*1*CLHEP::m; + if (!m_d->totmomline) { + m_d->totmomline = new SoLineSet; + m_d->totmomline->ref(); + SoVertexProperty * vertices = new SoVertexProperty; + m_d->totmomline->vertexProperty = vertices; + m_d->totmomline->numVertices.set1Value(0,2); + + } + SoVertexProperty * vertices = static_cast<SoVertexProperty*>(m_d->totmomline->vertexProperty.getValue()); + vertices->vertex.set1Value(0,totpos.x(),totpos.y(),totpos.z()); + vertices->vertex.set1Value(1,p2.x(),p2.y(),p2.z()); + m_d->totmomgev = totmom / CLHEP::GeV; + m_d->totmass = totmass; + //ensure attach: + messageVerbose(" => attach"); + if (m_d->totmomsep&&m_d->totmomline&&m_d->totmomsep->findChild(m_d->totmomline)<0) + m_d->totmomsep->addChild(m_d->totmomline); + return; + } + +} + +//____________________________________________________________________ +void VP1TrackSystem::userChangedSelection(SoCooperativeSelection* sel, QSet<SoNode*> /*nodes*/, QSet<SoPath*>/*paths*/) +{ + messageVerbose("userChangedSelection begin"); + if (sel!=m_d->sel_tracks) + return; + messageVerbose("userChangedSelection => sel_tracks!!"); + + + if (m_d->common->controller()->printTotMomentumOnMultiTrackSelection()) { + Amg::Vector3D totmom; + Amg::Vector3D totpos; + double totmass; + if (m_d->calcTotalMomentumOfSelectedHandles(totmom,totpos,totmass)>0) { + Amg::Vector3D totmomgev = totmom; + totmomgev /= CLHEP::GeV; + message("Total momentum [GeV] : "+str(totmomgev));//Fixme: Eta/phi/etc... + message("Total mass [GeV] : "+str(totmass/CLHEP::GeV));//Fixme: Eta/phi/etc... + } + } + + updateShownTotMomentum(); +} + + + + +// //____________________________________________________________________ +// InDetProjFlags::DetTypeFlags VP1TrackSystem::Imp::currentUsedIDProjections() const +// { +// if (common->controller()->collWidget()->visibleStdCollections().isEmpty()) +// return InDetProjFlags::NoDet; +// if (common->controller()->shownTrackParts() & TrackCommonFlags::InDetProjections) +// return InDetProjFlags::TRT_all; +// return InDetProjFlags::NoDet; +// } + +//____________________________________________________________________ +// void VP1TrackSystem::possiblyEmitUsedIDProjectionsChanged() +// { +// InDetProjFlags::DetTypeFlags usedidprojs = m_d->currentUsedIDProjections(); +// if (m_d->lastEmittedUsedIDProjections == usedidprojs) +// return; +// m_d->lastEmittedUsedIDProjections = usedidprojs; +// usedIDProjectionsChanged(usedidprojs); +// } + +//____________________________________________________________________ +void VP1TrackSystem::setSelectedPRDs(const QList<const Trk::PrepRawData*>& s) +{ + m_d->selectedPRDs = s; + if (m_d->common&&m_d->common->controller()) + m_d->common->controller()->setNumberOfSelectedPRDsAndTracks(m_d->selectedPRDs.count(),0); +} + +//____________________________________________________________________ +void VP1TrackSystem::refit() +{ + //FIXME: WE NEED A HELPER CLASS!! + + if (!m_d->common||!m_d->common->controller()||!m_d->sel_tracks)//To check that we are actually refreshed + return; + messageVerbose("Refit requested with mode="+TrackCommonFlags::toString(m_d->common->controller()->fitterMode())); + const Trk::ITrackFitter* currentFitter = m_d->common->controller()->trackFitter(); + if (!currentFitter) { + message("ERROR - Aborting refit as no fitter available."); + return; + } + + QList<const Trk::Track*> fittedtracks; + switch (m_d->common->controller()->fitterMode()) { + case TrackCommonFlags::FROMPRDS: refitFromPRDs(currentFitter, fittedtracks);break; + case TrackCommonFlags::REFITSINGLETRACK: refitSingleTrack(currentFitter, fittedtracks);break; + case TrackCommonFlags::EXTENDTRACKWITHPRDS: message("Not yet implemented");break; + case TrackCommonFlags::COMBINETWOTRACKS: message("Not yet implemented");break; + } + + if (fittedtracks.empty()) return; + + TrackCollHandle_RefittedTracks * newtrackcoll = + new TrackCollHandle_RefittedTracks(m_d->common, + m_d->common->controller()->nameOfNewlyFittedCollections(), + fittedtracks); + newtrackcoll->init(); + + QList<TrackCollHandleBase*> newcols; + newcols << newtrackcoll; + + m_d->common->controller()->collWidget()->addCollections(newcols); + + //Add new collections to event scenegraph and turn them on: + foreach (TrackCollHandleBase* col,newcols) { + m_d->sel_tracks->addChild(col->collSwitch()); + col->setVisible(true); + } +} + +void VP1TrackSystem::refitFromPRDs(const Trk::ITrackFitter* /**currentFitter*/, QList<const Trk::Track*>& /**fittedtracks*/) +{ + // FIXME (or remove, since no one used this I think - EJWM) + + // std::vector<const Trk::PrepRawData*> prdSet; + // prdSet.reserve(m_d->selectedPRDs.count()); + // foreach (const Trk::PrepRawData* prd,m_d->selectedPRDs) + // prdSet.push_back(prd); + // + // if (prdSet.size()==0) { + // message("ERROR - Aborting refit as prdset is empty"); + // return; + // } + // + // //Get direction from PRD locations + // unsigned i1(0),i2(prdSet.size()-1); + // const Amg::Vector3D* globPos0 = prdSet.at(i1)->detectorElement()->surface(prdSet.at(i1)->identify()).localToGlobal(prdSet.at(i1)->localPosition()); + // const Amg::Vector3D* globPos1 = prdSet.at(i2)->detectorElement()->surface(prdSet.at(i2)->identify()).localToGlobal(prdSet.at(i2)->localPosition()); + // Amg::Vector3D globMom = *globPos1 - *globPos0; + // + // // Loop and try several momenta + // double minMom = 3000.0; + // double maxMom = 23000.0; + // int numberIterations = 10; + // double stepSize = (maxMom-minMom)/static_cast<double>(numberIterations); + // + // const Trk::Track* bestTrack=0; + // bool outlier = m_d->common->controller()->fitterRemoveOutliers(); + // Trk::ParticleHypothesis hypo = m_d->common->controller()->fitterParticleHypthesis(); + // for ( double initialMom = minMom ; initialMom<=maxMom ; initialMom+=stepSize){ + // globMom.setMag(initialMom); + // Trk::Perigee params(*globPos0, globMom, 1.0, Amg::Vector3D(0.0,0.0,0.0)); + // + // const Trk::Track* fittedtrk = currentFitter->fit(prdSet, params, outlier,hypo ); + // + // QString mom=QString::number(initialMom); + // if (!fittedtrk || !(fittedtrk->fitQuality() ) ) { + // message("Track fit failed for seed momentum: "+mom+", outlier="+QString::number(outlier)); + // delete fittedtrk; //Discard tracks with no FQ (shouldn't ever happen, but need to test) + // } else { + // if (!bestTrack) { + // bestTrack=fittedtrk; // first valid track + // message("Track fit succeeded for seed momentum:"+mom+", outlier="+QString::number(outlier)+", and is new best track."); + // } else { + // // okay, have valid fit so now compare to previous track... + // const Trk::FitQuality* bestFQ = bestTrack->fitQuality(); + // const Trk::FitQuality* fittedFQ = fittedtrk->fitQuality(); + // if ( (fittedFQ->chiSquared()/fittedFQ->doubleNumberDoF())>(bestFQ->chiSquared()/bestFQ->doubleNumberDoF()) ){ + // delete bestTrack; bestTrack=fittedtrk; // Replace old best track with this one + // message("Track fit succeeded for seed momentum:"+mom+", outlier="+QString::number(outlier)+", and is new best track."); + // } else { + // delete fittedtrk; // fit not as good as previous fit. + // message("Track fit succeeded for seed momentum:"+mom+", outlier="+QString::number(outlier)+", but is not best track."); + // } + // } + // } + // + // } + // + // if (!bestTrack) { + // message("All fits failed - no resulting track."); + // return; + // } + // + // delete globPos0; delete globPos1; + // + // fittedtracks << bestTrack; + // + // std::ostringstream s; + // s << *bestTrack; + // messageVerbose( QString(s.str().c_str()).split('\n')); +} + +void VP1TrackSystem::refitSingleTrack(const Trk::ITrackFitter* currentFitter, QList<const Trk::Track*>& fittedtracks) +{ + const TrackHandleBase* handle = m_d->common->lastSelectedTrackHandle(); + const TrackHandle_TrkTrack* trkhandle = dynamic_cast<const TrackHandle_TrkTrack*>(handle); + if (!trkhandle) return; // shouldn't ever happen + const Trk::Track* track =trkhandle->trkTrackPointer(); + if (!track) return; // shouldn't ever happen + + bool outlier = m_d->common->controller()->fitterRemoveOutliers(); + Trk::ParticleHypothesis hypo = m_d->common->controller()->fitterParticleHypthesis(); + + const Trk::Track* fittedtrk = currentFitter->fit(*track,outlier,hypo); + + if (!fittedtrk) { + message("Fit failed - no resulting track."); + return; + } + + fittedtracks << fittedtrk; + + std::ostringstream s; + s << *fittedtrk; + messageVerbose( QString(s.str().c_str()).split('\n')); +} + +SoCooperativeSelection * VP1TrackSystem::selTracks() +{ + return m_d->sel_tracks; +} + +void VP1TrackSystem::updateAlignment(){ + messageVerbose("updateAlignment"); + + std::vector<double> values = m_d->common->controller()->alignmentShiftValue(); + int level = m_d->common->controller()->alignmentShiftLevel(); + + messageVerbose("updateAlignment called with level="+QString::number(level)); + assert (values.size()==6); + messageVerbose("0="+QString::number(values[0])); + messageVerbose("1="+QString::number(values[1])); + messageVerbose("2="+QString::number(values[2])); + messageVerbose("3="+QString::number(values[3])); + messageVerbose("4="+QString::number(values[4])); + messageVerbose("5="+QString::number(values[5])); + + const Trk::TrkDetElementBase* detEl = 0; + + // Try to find last selected TSOS + if (!m_d->ascObjSelManager) { + // this shouldn't happen! + message ("No selection manager - giving up."); + return; + } + + QList<AssociatedObjectHandleBase*> currentsel = m_d->ascObjSelManager->currentSelection(); + foreach(AssociatedObjectHandleBase* meas,currentsel) { + AscObj_TSOS* tsosAsc = dynamic_cast<AscObj_TSOS*>(meas); + if (tsosAsc){ + if (tsosAsc->rioOnTrack() ) + detEl= tsosAsc->rioOnTrack()->detectorElement (); + else if (tsosAsc->trackStateOnSurface()->trackParameters() ) + detEl= tsosAsc->trackStateOnSurface()->trackParameters()->associatedSurface().associatedDetectorElement (); + } + if (detEl) break; // set, so can skip rest + } + if (!detEl){ + messageVerbose("No det Element found"); + + return;// Abort! + } + + // redraw everything; + // FIXME +} + +void VP1TrackSystem::tracksFromVertexChanged(QList< std::pair<const SoMaterial*, QList< const Trk::Track*> > >& vertexList){ + messageVerbose("VP1TrackSystem::tracksFromVertexChanged. Got a list THIS big! "+QString::number(vertexList.size())); + + // firstly, by default option to cut tracks by vertex is disabled, so enable: + m_d->common->controller()->vertexCutsAllowed(true); + + // do something with vertexList! + std::pair<const SoMaterial*, QList< const Trk::Track*> > it; + foreach(it, vertexList){ + SoMaterial* mat = const_cast<SoMaterial*>(it.first); + messageVerbose("Number of tracks associated with this vertex= "+QString::number(it.second.size())); + + const Trk::Track* trk; + foreach(trk, it.second) { + m_d->vertexMaterialForTrackBases[trk]=mat; + mat->ref(); +// messageVerbose("Adding TrackHandleBase with pointer= "+QString::number((unsigned int)handle)+" for trk="+QString::number((unsigned int)trk)); + } + } + + // update track collections too. + foreach(TrackCollHandleBase* coll, m_d->common->controller()->collWidget()->collections<TrackCollHandleBase>()) + if (coll->allowColourByVertex()) coll->updateMaterialOfAllHandles(); +} + +SoMaterial* VP1TrackSystem::materialFromVertex(const TrackHandleBase* trk) const { + + const TrackHandle_TrkTrack* handle = dynamic_cast<const TrackHandle_TrkTrack*>(trk); + if (handle) { + std::map<const Trk::Track*, SoMaterial*>::const_iterator it = m_d->vertexMaterialForTrackBases.find(handle->trkTrackPointer()); + + if (it!=m_d->vertexMaterialForTrackBases.end()){ + return it->second; + } + } + messageVerbose("VP1TrackSystem::materialFromVertex. No matching track handle for handle with pointer="+QString::number((uintptr_t)trk)); + return 0; +} + + diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/objectbrowser.ui b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/objectbrowser.ui new file mode 100644 index 000000000..627fb4437 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/objectbrowser.ui @@ -0,0 +1,94 @@ +<ui version="4.0" > + <class>ObjectBrowser</class> + <widget class="QWidget" name="ObjectBrowser" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>346</width> + <height>419</height> + </rect> + </property> + <property name="minimumSize" > + <size> + <width>300</width> + <height>400</height> + </size> + </property> + <property name="windowTitle" > + <string>Browser</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout" > + <item> + <widget class="QTreeWidget" name="treeWidget" > + <property name="indentation" > + <number>20</number> + </property> + <property name="wordWrap" > + <bool>true</bool> + </property> + <property name="headerHidden" > + <bool>false</bool> + </property> + <property name="columnCount" > + <number>2</number> + </property> + <column> + <property name="text" > + <string>1</string> + </property> + </column> + <column> + <property name="text" > + <string>2</string> + </property> + </column> + </widget> + </item> + <item> + <widget class="QLabel" name="label" > + <property name="font" > + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="text" > + <string>To enable zooming when clicking on tracks/ track states, turn on 'zoom/orient' in 'Interactions'</string> + </property> + <property name="wordWrap" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout" > + <item> + <spacer name="spacer" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType" > + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>348</width> + <height>17</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_close" > + <property name="text" > + <string>&Close</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/pertrackcollectionsettings_form.ui b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/pertrackcollectionsettings_form.ui new file mode 100644 index 000000000..ded5b5877 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/pertrackcollectionsettings_form.ui @@ -0,0 +1,540 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>TrackCollectionSettingsForm</class> + <widget class="QWidget" name="TrackCollectionSettingsForm"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>492</width> + <height>640</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_5"> + <item> + <widget class="QGroupBox" name="groupBox_4"> + <property name="title"> + <string>Track line options</string> + </property> + <property name="checkable"> + <bool>false</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_4"> + <item> + <widget class="VP1MaterialButton" name="pushButton_matButton"> + <property name="text"> + <string>Material</string> + </property> + </widget> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>Track line widths:</string> + </property> + </widget> + </item> + <item> + <widget class="QSlider" name="horizontalSlider_trackWidth"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>100</width> + <height>0</height> + </size> + </property> + <property name="maximum"> + <number>100</number> + </property> + <property name="singleStep"> + <number>10</number> + </property> + <property name="value"> + <number>20</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QCheckBox" name="checkBox_trackTubes"> + <property name="text"> + <string>Display lines with cylinders</string> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="doubleSpinBox_trackTubesRadiusMM"> + <property name="prefix"> + <string>r = </string> + </property> + <property name="suffix"> + <string> mm</string> + </property> + <property name="minimum"> + <double>0.010000000000000</double> + </property> + <property name="value"> + <double>5.000000000000000</double> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + </layout> + </item> + <item> + <widget class="Line" name="line"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QCheckBox" name="checkBox_tracksUseBaseLightModel"> + <property name="toolTip"> + <string>Use a less advanced light model for the tracks. This might lead to more clearly visible tracks (but transparency will not be taken into account)</string> + </property> + <property name="text"> + <string>Use base lighting</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_hideactualpaths"> + <property name="toolTip"> + <string>Do not display the actual tracks. Projections and other track details (measurements, errors, ...) will still be shown.</string> + </property> + <property name="text"> + <string>Make actual paths invisible</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_defaultCuts"> + <property name="text"> + <string>Use default cuts</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QWidget" name="cuts" native="true"> + <property name="enabled"> + <bool>false</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <widget class="QGroupBox" name="groupBox_cuts_momentum"> + <property name="title"> + <string>Momentum cuts</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_5"> + <item> + <layout class="QGridLayout" name="_5"> + <property name="verticalSpacing"> + <number>4</number> + </property> + <item row="0" column="0"> + <widget class="QCheckBox" name="checkBox_cut_minpt"> + <property name="text"> + <string>Min</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QDoubleSpinBox" name="doubleSpinBox_cut_minpt_gev"> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="suffix"> + <string> GeV</string> + </property> + <property name="maximum"> + <double>999.990000000000009</double> + </property> + <property name="singleStep"> + <double>0.100000000000000</double> + </property> + <property name="value"> + <double>0.500000000000000</double> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QCheckBox" name="checkBox_cut_maxpt"> + <property name="text"> + <string>Max</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QDoubleSpinBox" name="doubleSpinBox_cut_maxpt_gev"> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="suffix"> + <string> GeV</string> + </property> + <property name="maximum"> + <double>999.990000000000009</double> + </property> + <property name="singleStep"> + <double>0.100000000000000</double> + </property> + <property name="value"> + <double>100.000000000000000</double> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QComboBox" name="comboBox_momtype"> + <item> + <property name="text"> + <string>Pt</string> + </property> + </item> + <item> + <property name="text"> + <string>P</string> + </property> + </item> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>13</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="VP1EtaPhiCutWidget" name="etaPhiCutWidget" native="true"/> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_cuts_reconstructed"> + <property name="title"> + <string>Reconstructed tracks</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_6"> + <property name="topMargin"> + <number>4</number> + </property> + <property name="rightMargin"> + <number>7</number> + </property> + <property name="bottomMargin"> + <number>4</number> + </property> + <item> + <layout class="QGridLayout" name="gridLayout_lala"> + <property name="spacing"> + <number>1</number> + </property> + <item row="1" column="0"> + <widget class="QCheckBox" name="checkBox_cut_nhits_pixel"> + <property name="toolTip"> + <string>Hide tracks without this many pixel hits. Only applies to tracks with ID information.</string> + </property> + <property name="text"> + <string>Require Pixel hits:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QSpinBox" name="spinBox_cut_nhits_pixel"/> + </item> + <item row="2" column="0"> + <widget class="QCheckBox" name="checkBox_cut_nhits_sct"> + <property name="toolTip"> + <string>Hide tracks without this many SCT hits. Only applies to tracks with ID information.</string> + </property> + <property name="text"> + <string>Require SCT hits:</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QSpinBox" name="spinBox_cut_nhits_sct"> + <property name="value"> + <number>1</number> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QCheckBox" name="checkBox_cut_nhits_trt"> + <property name="toolTip"> + <string>Hide tracks without this many TRT hits. Only applies to tracks with ID information.</string> + </property> + <property name="text"> + <string>Require TRT hits:</string> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QSpinBox" name="spinBox_cut_nhits_muon"/> + </item> + <item row="3" column="1"> + <widget class="QSpinBox" name="spinBox_cut_nhits_trt"/> + </item> + <item row="4" column="0"> + <widget class="QCheckBox" name="checkBox_cut_nhits_muon"> + <property name="text"> + <string>Require Muon hits:</string> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QCheckBox" name="checkBox_cut_nprecisionhits_muon"> + <property name="text"> + <string>Require Precision Muon hits:</string> + </property> + </widget> + </item> + <item row="5" column="1"> + <widget class="QSpinBox" name="spinBox_cut_nprecisionhits_muon"/> + </item> + </layout> + </item> + <item> + <widget class="QLabel" name="label"> + <property name="autoFillBackground"> + <bool>false</bool> + </property> + <property name="text"> + <string>ID requirements only apply to tracks with ID hits (i.e. not MS standalone tracks)</string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>14</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_cuts_truth_tracks"> + <property name="title"> + <string>Truth tracks</string> + </property> + <layout class="QHBoxLayout" name="_3"> + <item> + <layout class="QVBoxLayout" name="_4"> + <item> + <widget class="QCheckBox" name="checkBox_cut_truthtracks_creationvertexinIR"> + <property name="toolTip"> + <string><html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Secondaries are particles based solely on simhits, or particles with a creation vertex outside the interaction region (|r|&lt;2.8cm, |z|&lt;50cm).</p></body></html></string> + </property> + <property name="text"> + <string>Require creation vertex at IR</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_cut_truthtracks_excludeneutrals"> + <property name="text"> + <string>Exclude neutrals</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_cut_truthtracks_excludebarcode0"> + <property name="toolTip"> + <string><html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Some simhits will be due to secondary particles without an entry in an HepMC record. Such simhits will be marked as coming from a particle with barcode=0.</p></body></html></string> + </property> + <property name="text"> + <string>Exclude simhits with barcode 0</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Preferred</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_vertexAssociated"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="toolTip"> + <string>The vertex system must be enabled for this to be usable.</string> + </property> + <property name="text"> + <string>Only show Vertex associated tracks</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="_2"> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_close"> + <property name="text"> + <string>&Close</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>VP1MaterialButton</class> + <extends>QPushButton</extends> + <header>VP1Base/VP1MaterialButton.h</header> + </customwidget> + <customwidget> + <class>VP1EtaPhiCutWidget</class> + <extends>QWidget</extends> + <header>VP1Base/VP1EtaPhiCutWidget.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections> + <connection> + <sender>checkBox_defaultCuts</sender> + <signal>toggled(bool)</signal> + <receiver>cuts</receiver> + <slot>setDisabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>214</x> + <y>149</y> + </hint> + <hint type="destinationlabel"> + <x>214</x> + <y>358</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/settings_ascobjs_form.ui b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/settings_ascobjs_form.ui new file mode 100644 index 000000000..7718aa3fb --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/settings_ascobjs_form.ui @@ -0,0 +1,940 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>TrackSysSettingsAscObjsForm</class> + <widget class="QWidget" name="TrackSysSettingsAscObjsForm"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>492</width> + <height>552</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string>Associated Track Objects</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="3" column="1"> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Preferred</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>234</width> + <height>17</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="0"> + <widget class="QGroupBox" name="groupBox_7"> + <property name="title"> + <string>General</string> + </property> + <layout class="QGridLayout"> + <property name="margin"> + <number>4</number> + </property> + <item row="0" column="0"> + <layout class="QVBoxLayout"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <layout class="QGridLayout"> + <item row="0" column="0"> + <layout class="QHBoxLayout"> + <item> + <widget class="QLabel" name="label_11"> + <property name="text"> + <string>Details:</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="comboBox_assocobj_detaillevel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="currentIndex"> + <number>0</number> + </property> + <property name="sizeAdjustPolicy"> + <enum>QComboBox::AdjustToContents</enum> + </property> + <item> + <property name="text"> + <string>Auto</string> + </property> + </item> + <item> + <property name="text"> + <string>Simple</string> + </property> + </item> + <item> + <property name="text"> + <string>Detailed</string> + </property> + </item> + </widget> + </item> + </layout> + </item> + <item row="0" column="1"> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>16</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="0" colspan="2"> + <layout class="QGridLayout"> + <property name="verticalSpacing"> + <number>6</number> + </property> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Line widths:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QSlider" name="horizontalSlider_linewidths"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Point sizes:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QSlider" name="horizontalSlider_pointsizes"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_curve_realism"> + <property name="text"> + <string>Curve realism:</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QSlider" name="horizontalSlider_complexity"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximum"> + <number>20</number> + </property> + <property name="value"> + <number>6</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>1</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item row="0" column="1"> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Preferred</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item row="2" column="0"> + <widget class="QGroupBox" name="groupBox_materialeffectsontrack"> + <property name="title"> + <string>Material effects</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>false</bool> + </property> + <layout class="QGridLayout"> + <property name="margin"> + <number>4</number> + </property> + <item row="0" column="0"> + <layout class="QGridLayout"> + <item row="0" column="0" colspan="2"> + <layout class="QHBoxLayout"> + <item> + <widget class="QCheckBox" name="checkBox_usecolour_materialeffectsontrack"> + <property name="text"> + <string>Use colour:</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="VP1MaterialButton" name="matButton_materialeffectsontrack"> + <property name="text"> + <string/> + </property> + </widget> + </item> + </layout> + </item> + <item row="0" column="2"> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="0"> + <layout class="QHBoxLayout"> + <item> + <widget class="QLabel" name="label_mateffects_scale"> + <property name="text"> + <string>Scale:</string> + </property> + </widget> + </item> + <item> + <widget class="QSlider" name="horizontalSlider_materialeffectsontrack_scale"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="value"> + <number>10</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + </layout> + </item> + <item row="1" column="1" colspan="2"> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Preferred</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="2" column="0" colspan="3"> + <widget class="QCheckBox" name="checkBox_materialeffectsontrack_hideNoDE"> + <property name="text"> + <string>Hide effects with no dE</string> + </property> + </widget> + </item> + <item row="3" column="0" colspan="3"> + <widget class="QCheckBox" name="checkBox_materialeffectsontrack_forceposontrack"> + <property name="text"> + <string>Force position on track</string> + </property> + </widget> + </item> + </layout> + </item> + <item row="0" column="1"> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Preferred</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>16</width> + <height>75</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item row="2" column="1"> + <widget class="QGroupBox" name="groupBox_surfaces"> + <property name="title"> + <string>Surfaces</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>false</bool> + </property> + <layout class="QGridLayout"> + <property name="leftMargin"> + <number>4</number> + </property> + <property name="topMargin"> + <number>4</number> + </property> + <property name="rightMargin"> + <number>4</number> + </property> + <item row="0" column="0"> + <layout class="QVBoxLayout"> + <item> + <layout class="QGridLayout"> + <item row="0" column="0"> + <layout class="QHBoxLayout"> + <item> + <widget class="QCheckBox" name="checkBox_usecolour_surfaces"> + <property name="text"> + <string>Use colour:</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="VP1MaterialButton" name="matButton_surfaces"> + <property name="text"> + <string/> + </property> + </widget> + </item> + </layout> + </item> + <item row="0" column="1"> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Preferred</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="0" colspan="2"> + <widget class="QCheckBox" name="checkBox_surfaces_hidecustomsurfaces"> + <property name="text"> + <string>Hide custom surfaces</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QCheckBox" name="checkBox_surfaces_hidetubesurfaces"> + <property name="text"> + <string>Hide tube surfaces</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>1</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item row="0" column="1"> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item row="3" column="0"> + <widget class="QCheckBox" name="checkBox_truthtracks_display_points"> + <property name="text"> + <string>Show truth input points</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QGroupBox" name="groupBox_errors"> + <property name="title"> + <string>Show errors</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>false</bool> + </property> + <layout class="QGridLayout" name="_2"> + <property name="margin"> + <number>4</number> + </property> + <item row="2" column="0"> + <layout class="QVBoxLayout" name="_3"> + <item> + <layout class="QHBoxLayout" name="_4"> + <property name="bottomMargin"> + <number>4</number> + </property> + <item> + <widget class="QCheckBox" name="checkBox_usecolour_parametererrors"> + <property name="text"> + <string>Use colour:</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="VP1MaterialButton" name="matButton_parerrors"> + <property name="text"> + <string/> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="_5"> + <item> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Standard dev.:</string> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="doubleSpinBox_parerror_stddev"> + <property name="value"> + <double>3.000000000000000</double> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QCheckBox" name="checkBox_parerror_drawcylinder"> + <property name="text"> + <string>Draw full error tubes</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_parerror_hideperigeeerrors"> + <property name="text"> + <string>Hide perigee errors</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </item> + <item row="2" column="1"> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>81</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="0"> + <widget class="QCheckBox" name="checkBox_parametererrors"> + <property name="text"> + <string>Parameter errors</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QCheckBox" name="checkBox_measurementerrors"> + <property name="text"> + <string>Measurement errors</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item row="1" column="0"> + <widget class="QGroupBox" name="groupBox_measurements"> + <property name="minimumSize"> + <size> + <width>234</width> + <height>203</height> + </size> + </property> + <property name="title"> + <string>Measurements</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>false</bool> + </property> + <widget class="QWidget" name="layoutWidget"> + <property name="geometry"> + <rect> + <x>8</x> + <y>27</y> + <width>226</width> + <height>172</height> + </rect> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <layout class="QGridLayout" name="_9"> + <property name="horizontalSpacing"> + <number>0</number> + </property> + <property name="verticalSpacing"> + <number>2</number> + </property> + <item row="0" column="0"> + <widget class="QCheckBox" name="checkBox_usecolour_measurements"> + <property name="text"> + <string>Use colour:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="VP1MaterialButton" name="matButton_measurements"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QCheckBox" name="checkBox_usecolour_meas_outliers"> + <property name="text"> + <string>Outlier colour:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="VP1MaterialButton" name="matButton_meas_outliers"> + <property name="text"> + <string/> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Preferred</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>13</width> + <height>53</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QCheckBox" name="checkBox_measurements_drawGP"> + <property name="text"> + <string>Draw Global Positions</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_measurements_shorttubes_trt"> + <property name="text"> + <string>Shorten TRT measurements</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_measurements_shorttubes_mdt"> + <property name="text"> + <string>Shorten MDT measurements</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <layout class="QHBoxLayout" name="_10"> + <item> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>Half length:</string> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="doubleSpinBox_measurements_shorttubes_scale"> + <property name="suffix"> + <string> cm</string> + </property> + <property name="minimum"> + <double>0.010000000000000</double> + </property> + <property name="value"> + <double>2.000000000000000</double> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Preferred</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>13</width> + <height>26</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Preferred</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </widget> + </item> + <item row="0" column="1"> + <widget class="QGroupBox" name="groupBox_parameters"> + <property name="title"> + <string>Show parameters</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>false</bool> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="0"> + <layout class="QVBoxLayout" name="_7"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <layout class="QHBoxLayout" name="_8"> + <item> + <widget class="QCheckBox" name="checkBox_usecolour_parameters"> + <property name="text"> + <string>Use colour:</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="VP1MaterialButton" name="matButton_parameters"> + <property name="text"> + <string/> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item row="0" column="1"> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="0"> + <layout class="QHBoxLayout" name="_11"> + <item> + <widget class="QCheckBox" name="checkBox_useHoleColour_parameters"> + <property name="toolTip"> + <string>'Holes' (missing measurements) are shown in this colour.</string> + </property> + <property name="text"> + <string>Hole colour:</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="VP1MaterialButton" name="matButton_holeParameters"> + <property name="text"> + <string/> + </property> + </widget> + </item> + </layout> + </item> + <item row="1" column="1"> + <spacer name="spacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>55</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="2" column="0"> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>18</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item row="4" column="0" colspan="2"> + <layout class="QHBoxLayout"> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_close"> + <property name="text"> + <string>&Close</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>VP1MaterialButton</class> + <extends>QPushButton</extends> + <header>VP1Base/VP1MaterialButton.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections> + <connection> + <sender>pushButton_close</sender> + <signal>clicked()</signal> + <receiver>TrackSysSettingsAscObjsForm</receiver> + <slot>hide()</slot> + <hints> + <hint type="sourcelabel"> + <x>492</x> + <y>608</y> + </hint> + <hint type="destinationlabel"> + <x>294</x> + <y>58</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/settings_colouring_form.ui b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/settings_colouring_form.ui new file mode 100644 index 000000000..8b82fb7bd --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/settings_colouring_form.ui @@ -0,0 +1,703 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>TrackSysSettingsColouringForm</class> + <widget class="QWidget" name="TrackSysSettingsColouringForm"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>519</width> + <height>520</height> + </rect> + </property> + <property name="font"> + <font> + <weight>50</weight> + <bold>false</bold> + </font> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QGridLayout" name="gridLayout_5"> + <item row="0" column="0" colspan="3"> + <widget class="QGroupBox" name="groupBox_5"> + <property name="title"> + <string>Truth PID Colouring</string> + </property> + <layout class="QHBoxLayout"> + <property name="spacing"> + <number>20</number> + </property> + <property name="leftMargin"> + <number>6</number> + </property> + <property name="topMargin"> + <number>4</number> + </property> + <property name="rightMargin"> + <number>6</number> + </property> + <property name="bottomMargin"> + <number>4</number> + </property> + <item> + <layout class="QGridLayout"> + <property name="horizontalSpacing"> + <number>4</number> + </property> + <property name="verticalSpacing"> + <number>1</number> + </property> + <item row="0" column="0"> + <widget class="VP1MaterialButton" name="matButton_electrons"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLabel" name="label_7"> + <property name="text"> + <string>Electrons</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="VP1MaterialButton" name="matButton_pions"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLabel" name="label_8"> + <property name="text"> + <string>Pions</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="VP1MaterialButton" name="matButton_protons"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLabel" name="label_16"> + <property name="text"> + <string>Protons</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="VP1MaterialButton" name="matButton_neutrinos"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QLabel" name="label_17"> + <property name="text"> + <string>Neutrinos</string> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="VP1MaterialButton" name="matButton_neutrons"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QLabel" name="label_18"> + <property name="text"> + <string>Neutrons</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QGridLayout"> + <property name="horizontalSpacing"> + <number>4</number> + </property> + <property name="verticalSpacing"> + <number>1</number> + </property> + <item row="0" column="0"> + <widget class="VP1MaterialButton" name="matButton_muons"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLabel" name="label_19"> + <property name="text"> + <string>Muons</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="VP1MaterialButton" name="matButton_chargedkaons"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLabel" name="label_20"> + <property name="text"> + <string>Charged kaons</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="VP1MaterialButton" name="matButton_othercharged"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLabel" name="label_21"> + <property name="text"> + <string>Other charged</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="VP1MaterialButton" name="matButton_photons"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QLabel" name="label_22"> + <property name="text"> + <string>Photons</string> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="VP1MaterialButton" name="matButton_otherneutrals"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QLabel" name="label_23"> + <property name="text"> + <string>Other neutrals</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item row="1" column="0" colspan="3"> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Momentum Colouring</string> + </property> + <layout class="QHBoxLayout"> + <property name="leftMargin"> + <number>6</number> + </property> + <property name="topMargin"> + <number>4</number> + </property> + <property name="rightMargin"> + <number>6</number> + </property> + <property name="bottomMargin"> + <number>4</number> + </property> + <item> + <widget class="QLabel" name="label_27"> + <property name="text"> + <string>Fix points:</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout"> + <property name="spacing"> + <number>4</number> + </property> + <item> + <widget class="VP1MaterialButton" name="matButton_0GeV"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>0 GeV</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout"> + <property name="spacing"> + <number>4</number> + </property> + <item> + <widget class="VP1MaterialButton" name="matButton_15GeV"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_6"> + <property name="text"> + <string>15 GeV</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item row="2" column="0" colspan="3"> + <widget class="QGroupBox" name="groupBox_3"> + <property name="title"> + <string>Random Colours</string> + </property> + <layout class="QHBoxLayout"> + <property name="leftMargin"> + <number>6</number> + </property> + <property name="topMargin"> + <number>4</number> + </property> + <property name="rightMargin"> + <number>6</number> + </property> + <property name="bottomMargin"> + <number>4</number> + </property> + <item> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Regenerate random colours:</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pushButton_colourbyrandom_rerandomise"> + <property name="toolTip"> + <string>Re-generate random colours. Note transparency and brightness are inherited from the Uniform colour settings.</string> + </property> + <property name="text"> + <string>Rerandomise</string> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item row="3" column="0" rowspan="2"> + <widget class="QGroupBox" name="groupBox_labels"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="title"> + <string>Labels</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>false</bool> + </property> + <layout class="QGridLayout" name="gridLayout_3"> + <item row="0" column="0"> + <widget class="QCheckBox" name="checkBox_trkLabels_Pt"> + <property name="toolTip"> + <string>Enables the drawing of track labels</string> + </property> + <property name="text"> + <string>Pt</string> + </property> + </widget> + </item> + <item row="0" column="1" rowspan="6"> + <widget class="QGroupBox" name="groupBox_2"> + <property name="title"> + <string>Offset</string> + </property> + <property name="flat"> + <bool>false</bool> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="0"> + <widget class="QLabel" name="label_11"> + <property name="text"> + <string>x</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QSlider" name="horizontalSlider_labels_xOffset"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>32</height> + </size> + </property> + <property name="minimum"> + <number>-100</number> + </property> + <property name="maximum"> + <number>100</number> + </property> + <property name="tracking"> + <bool>true</bool> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="invertedAppearance"> + <bool>false</bool> + </property> + <property name="tickPosition"> + <enum>QSlider::TicksAbove</enum> + </property> + <property name="tickInterval"> + <number>25</number> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>y</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QSlider" name="horizontalSlider_labels_yOffset"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>32</height> + </size> + </property> + <property name="minimum"> + <number>-100</number> + </property> + <property name="maximum"> + <number>100</number> + </property> + <property name="tracking"> + <bool>true</bool> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="invertedAppearance"> + <bool>false</bool> + </property> + <property name="tickPosition"> + <enum>QSlider::TicksAbove</enum> + </property> + <property name="tickInterval"> + <number>25</number> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_9"> + <property name="text"> + <string>z</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QSlider" name="horizontalSlider_labels_zOffset"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>32</height> + </size> + </property> + <property name="minimum"> + <number>-100</number> + </property> + <property name="maximum"> + <number>100</number> + </property> + <property name="tracking"> + <bool>true</bool> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="invertedAppearance"> + <bool>false</bool> + </property> + <property name="tickPosition"> + <enum>QSlider::TicksAbove</enum> + </property> + <property name="tickInterval"> + <number>25</number> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_10"> + <property name="text"> + <string>Track</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QSlider" name="horizontalSlider_labels_trkOffset"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>32</height> + </size> + </property> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>100</number> + </property> + <property name="tracking"> + <bool>true</bool> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="invertedAppearance"> + <bool>false</bool> + </property> + <property name="tickPosition"> + <enum>QSlider::TicksAbove</enum> + </property> + <property name="tickInterval"> + <number>25</number> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item row="1" column="0"> + <widget class="QCheckBox" name="checkBox_trkLabels_p"> + <property name="toolTip"> + <string>Enables the drawing of track labels</string> + </property> + <property name="text"> + <string>P</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QCheckBox" name="checkBox_trkLabels_hits"> + <property name="toolTip"> + <string>Enables the drawing of track labels</string> + </property> + <property name="text"> + <string>Hit counts</string> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QCheckBox" name="checkBox_trkLabels_pid"> + <property name="toolTip"> + <string>Enables the drawing of track labels</string> + </property> + <property name="text"> + <string>Pdg/Hypothesis</string> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QCheckBox" name="checkBox_trkLabels_fitQuality"> + <property name="toolTip"> + <string>Enables the drawing of track labels</string> + </property> + <property name="text"> + <string>Fit Quality</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QCheckBox" name="checkBox_trkLabels_direction"> + <property name="text"> + <string>Eta/Phi</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item row="3" column="1"> + <widget class="QGroupBox" name="groupBox_6"> + <property name="title"> + <string>Charge Colouring</string> + </property> + <layout class="QGridLayout" name="gridLayout_4"> + <item row="0" column="0"> + <widget class="VP1MaterialButton" name="matButton_charge_pos"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLabel" name="label_24"> + <property name="text"> + <string>Positive</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="VP1MaterialButton" name="matButton_charge_neg"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLabel" name="label_25"> + <property name="text"> + <string>Negative</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="VP1MaterialButton" name="matButton_charge_neutral"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLabel" name="label_26"> + <property name="text"> + <string>Neutral</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item row="3" column="2"> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>76</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="4" column="1"> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>42</height> + </size> + </property> + </spacer> + </item> + <item row="5" column="0" colspan="3"> + <layout class="QHBoxLayout"> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_close"> + <property name="text"> + <string>&Close</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>VP1MaterialButton</class> + <extends>QPushButton</extends> + <header>VP1Base/VP1MaterialButton.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/settings_cuts_form.ui b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/settings_cuts_form.ui new file mode 100644 index 000000000..42668f6b7 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/settings_cuts_form.ui @@ -0,0 +1,359 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>TrackSysSettingsCutsForm</class> + <widget class="QWidget" name="TrackSysSettingsCutsForm"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>390</width> + <height>464</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QGroupBox" name="groupBox_cuts_momentum"> + <property name="title"> + <string>Momentum cuts</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <layout class="QGridLayout"> + <property name="verticalSpacing"> + <number>4</number> + </property> + <item row="0" column="0"> + <widget class="QCheckBox" name="checkBox_cut_minpt"> + <property name="text"> + <string>Min</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QDoubleSpinBox" name="doubleSpinBox_cut_minpt_gev"> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="suffix"> + <string> GeV</string> + </property> + <property name="maximum"> + <double>999.990000000000009</double> + </property> + <property name="singleStep"> + <double>0.100000000000000</double> + </property> + <property name="value"> + <double>0.500000000000000</double> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QCheckBox" name="checkBox_cut_maxpt"> + <property name="text"> + <string>Max</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QDoubleSpinBox" name="doubleSpinBox_cut_maxpt_gev"> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="suffix"> + <string> GeV</string> + </property> + <property name="maximum"> + <double>999.990000000000009</double> + </property> + <property name="singleStep"> + <double>0.100000000000000</double> + </property> + <property name="value"> + <double>100.000000000000000</double> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QComboBox" name="comboBox_momtype"> + <item> + <property name="text"> + <string>Pt</string> + </property> + </item> + <item> + <property name="text"> + <string>P</string> + </property> + </item> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>13</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="VP1EtaPhiCutWidget" name="etaPhiCutWidget" native="true"/> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Reconstructed tracks</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <property name="topMargin"> + <number>4</number> + </property> + <property name="rightMargin"> + <number>7</number> + </property> + <property name="bottomMargin"> + <number>4</number> + </property> + <item> + <layout class="QGridLayout" name="gridLayout_lala"> + <property name="spacing"> + <number>1</number> + </property> + <item row="0" column="0"> + <widget class="QCheckBox" name="checkBox_cut_nhits_pixel"> + <property name="toolTip"> + <string>Hide tracks without this many pixel hits. Only applies to tracks with ID information.</string> + </property> + <property name="text"> + <string>Require Pixel hits:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QSpinBox" name="spinBox_cut_nhits_pixel"/> + </item> + <item row="1" column="0"> + <widget class="QCheckBox" name="checkBox_cut_nhits_sct"> + <property name="toolTip"> + <string>Hide tracks without this many SCT hits. Only applies to tracks with ID information.</string> + </property> + <property name="text"> + <string>Require SCT hits:</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QSpinBox" name="spinBox_cut_nhits_sct"> + <property name="value"> + <number>1</number> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QCheckBox" name="checkBox_cut_nhits_trt"> + <property name="toolTip"> + <string>Hide tracks without this many TRT hits. Only applies to tracks with ID information.</string> + </property> + <property name="text"> + <string>Require TRT hits:</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QSpinBox" name="spinBox_cut_nhits_trt"/> + </item> + <item row="3" column="1"> + <widget class="QSpinBox" name="spinBox_cut_nhits_muon"/> + </item> + <item row="3" column="0"> + <widget class="QCheckBox" name="checkBox_cut_nhits_muon"> + <property name="text"> + <string>Require Muon hits:</string> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QCheckBox" name="checkBox_cut_nprecisionhits_muon"> + <property name="text"> + <string>Require Precision Muon hits:</string> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QSpinBox" name="spinBox_cut_nprecisionhits_muon"/> + </item> + </layout> + </item> + <item> + <widget class="QLabel" name="label"> + <property name="autoFillBackground"> + <bool>false</bool> + </property> + <property name="text"> + <string>ID requirements only apply to tracks with ID hits (i.e. not MS standalone tracks)</string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>14</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_cuts_truth_tracks"> + <property name="title"> + <string>Truth tracks</string> + </property> + <layout class="QHBoxLayout"> + <item> + <layout class="QVBoxLayout"> + <item> + <widget class="QCheckBox" name="checkBox_cut_truthtracks_creationvertexinIR"> + <property name="toolTip"> + <string><html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Secondaries are particles based solely on simhits, or particles with a creation vertex outside the interaction region (|r|&lt;2.8cm, |z|&lt;50cm).</p></body></html></string> + </property> + <property name="text"> + <string>Require creation vertex at IR</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_cut_truthtracks_excludeneutrals"> + <property name="text"> + <string>Exclude neutrals</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_cut_truthtracks_excludebarcode0"> + <property name="toolTip"> + <string><html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Some simhits will be due to secondary particles without an entry in an HepMC record. Such simhits will be marked as coming from a particle with barcode=0.</p></body></html></string> + </property> + <property name="text"> + <string>Exclude simhits with barcode 0</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Preferred</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_vertexAssociated"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="toolTip"> + <string>The vertex system must be enabled for this to be usable.</string> + </property> + <property name="text"> + <string>Only show Vertex associated tracks</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout"> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_close"> + <property name="text"> + <string>&Close</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>VP1EtaPhiCutWidget</class> + <extends>QWidget</extends> + <header>VP1Base/VP1EtaPhiCutWidget.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/settings_extrapolation_form.ui b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/settings_extrapolation_form.ui new file mode 100644 index 000000000..07bacfd61 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/settings_extrapolation_form.ui @@ -0,0 +1,252 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>TrackSysSettingsExtrapolationsForm</class> + <widget class="QWidget" name="TrackSysSettingsExtrapolationsForm"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>326</width> + <height>334</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QVBoxLayout"> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Propagation calculations</string> + </property> + <layout class="QVBoxLayout"> + <item> + <widget class="QRadioButton" name="radioButton_none"> + <property name="toolTip"> + <string>Simply 'join the dots'</string> + </property> + <property name="text"> + <string>None [fast, crude]</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_helical"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="toolTip"> + <string>Try to use a simpler method to draw tracks</string> + </property> + <property name="text"> + <string>Spline fit [fast, imprecise]</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioButton_athenaExtrapolator"> + <property name="text"> + <string>Athena extrapolator [slow, precise]</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QComboBox" name="comboBox_propagator"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Shows the available extrapolars.</string> + </property> + <property name="sizeAdjustPolicy"> + <enum>QComboBox::AdjustToContents</enum> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_otheroptions"> + <property name="title"> + <string>Other options:</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QCheckBox" name="checkBox_ignoreMEoT"> + <property name="toolTip"> + <string>If this is set, Track States with only material effects are ignored when drawing lines</string> + </property> + <property name="text"> + <string>Ignore Mat. Effects on Track (scatterers)</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QCheckBox" name="checkBox_extendAllTracks"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="toolTip"> + <string>If this is set, attempt to extend ID tracks to the specified position.</string> + </property> + <property name="text"> + <string>Extend all ID tracks to </string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="comboBox_extendAllTracksToHere"> + <property name="enabled"> + <bool>true</bool> + </property> + <item> + <property name="text"> + <string>Calorimeter</string> + </property> + </item> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QCheckBox" name="checkBox_maxRadius"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="toolTip"> + <string>If this is set, limit radius of Tracks.</string> + </property> + <property name="text"> + <string>Maximum radius [mm]</string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="spinBox_maxRadiusValue"> + <property name="minimum"> + <number>10</number> + </property> + <property name="maximum"> + <number>50000</number> + </property> + <property name="value"> + <number>50</number> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout"> + <item> + <widget class="QLabel" name="label_6"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="toolTip"> + <string>Determines the number of points calculated on each track. A higher setting results in shorter distances between points.</string> + </property> + <property name="text"> + <string>Granularity:</string> + </property> + </widget> + </item> + <item> + <widget class="QSlider" name="horizontalSlider_granularity"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="toolTip"> + <string>Determines the number of points calculated on each track. A higher setting results in shorter distances between points.</string> + </property> + <property name="maximum"> + <number>10</number> + </property> + <property name="pageStep"> + <number>1</number> + </property> + <property name="value"> + <number>1</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QHBoxLayout"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_close"> + <property name="text"> + <string>&Close</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/settings_interactions_form.ui b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/settings_interactions_form.ui new file mode 100644 index 000000000..b217ef879 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/settings_interactions_form.ui @@ -0,0 +1,318 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>TrackSysSettingsInteractionsForm</class> + <widget class="QWidget" name="TrackSysSettingsInteractionsForm"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>319</width> + <height>514</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QGroupBox" name="groupBox_3"> + <property name="title"> + <string>Selection Mode</string> + </property> + <layout class="QVBoxLayout"> + <item> + <widget class="QRadioButton" name="radioButton_selmode_single"> + <property name="text"> + <string>Single object selection</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <layout class="QVBoxLayout"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>20</number> + </property> + <property name="bottomMargin"> + <number>4</number> + </property> + <item> + <layout class="QVBoxLayout"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <widget class="QCheckBox" name="checkBox_selsingle_printinfo"> + <property name="text"> + <string>Print information</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout"> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QCheckBox" name="checkBox_selsingle_printinfo_verbose"> + <property name="text"> + <string>Verbose</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item> + <widget class="QCheckBox" name="checkBox_selsingle_orientzoom"> + <property name="text"> + <string>Orient view/zoom</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QRadioButton" name="radioButton_selmode_multitracks"> + <property name="text"> + <string>Multi track selection</string> + </property> + </widget> + </item> + <item> + <layout class="QVBoxLayout"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>20</number> + </property> + <property name="bottomMargin"> + <number>4</number> + </property> + <item> + <widget class="QCheckBox" name="checkBox_sel_printtotmom"> + <property name="text"> + <string>Print total mom. and mass</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_sel_showtotmom"> + <property name="text"> + <string>Show direction of total mom.</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QRadioButton" name="radioButton_selmode_trackfits"> + <property name="toolTip"> + <string>Particularly useful for refit from PRDs</string> + </property> + <property name="text"> + <string>Select PRDs from Track</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_refitting"> + <property name="title"> + <string>Refitting</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Fitter:</string> + </property> + </widget> + </item> + <item row="0" column="1" colspan="2"> + <widget class="QComboBox" name="comboBox_fitters"> + <property name="toolTip"> + <string>Select from currently available fitters</string> + </property> + </widget> + </item> + <item row="1" column="1" colspan="2"> + <widget class="QComboBox" name="comboBox_fitterMode"> + <property name="toolTip"> + <string>Chooses the mode in which the fitter runs.</string> + </property> + <item> + <property name="text"> + <string>Fit PRDs</string> + </property> + </item> + <item> + <property name="text"> + <string>Refit Track</string> + </property> + </item> + </widget> + </item> + <item row="2" column="1" colspan="2"> + <widget class="QCheckBox" name="checkBox_removeOutliers"> + <property name="text"> + <string>Remove Outliers</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>Particle Hypo:</string> + </property> + </widget> + </item> + <item row="3" column="1" colspan="2"> + <widget class="QComboBox" name="comboBox_particleHypo"> + <property name="toolTip"> + <string>Chooses the mode in which the fitter runs.</string> + </property> + <item> + <property name="text"> + <string>Pion</string> + </property> + </item> + <item> + <property name="text"> + <string>Non Interacting</string> + </property> + </item> + <item> + <property name="text"> + <string>Electron</string> + </property> + </item> + <item> + <property name="text"> + <string>Muon</string> + </property> + </item> + <item> + <property name="text"> + <string>Kaon</string> + </property> + </item> + <item> + <property name="text"> + <string>Proton</string> + </property> + </item> + <item> + <property name="text"> + <string>Photon</string> + </property> + </item> + </widget> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Output name:</string> + </property> + </widget> + </item> + <item row="4" column="1" colspan="2"> + <widget class="QLineEdit" name="lineEdit_fittedTrackCollName"> + <property name="text"> + <string>Fitted track</string> + </property> + </widget> + </item> + <item row="5" column="0"> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Preferred</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>78</width> + <height>24</height> + </size> + </property> + </spacer> + </item> + <item row="5" column="1" colspan="2"> + <widget class="QPushButton" name="pushButton_refit"> + <property name="text"> + <string>Fit track from 0 PRDs</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Mode:</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>98</width> + <height>18</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_close"> + <property name="text"> + <string>&Close</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/settings_projections_form.ui b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/settings_projections_form.ui new file mode 100644 index 000000000..c1956cecc --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/settings_projections_form.ui @@ -0,0 +1,157 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>TrackSysSettingsProjectionsForm</class> + <widget class="QWidget" name="TrackSysSettingsProjectionsForm"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>206</width> + <height>198</height> + </rect> + </property> + <property name="windowTitle"> + <string>Projections</string> + </property> + <layout class="QVBoxLayout"> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Track Projections</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QCheckBox" name="checkBox_projections_muonchambers"> + <property name="toolTip"> + <string><html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Whether to project track objects to either or both of inner detector projection surfaces and muon chamber sides respectively (only takes effect when the appropriate surfaces/chambers are shown).</p></body></html></string> + </property> + <property name="text"> + <string>Muon chamber sides</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox_projections_indet"> + <property name="toolTip"> + <string><html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Whether to project track objects to either or both of inner detector projection surfaces and muon chamber sides respectively (only takes effect when the appropriate surfaces/chambers are shown).</string> + </property> + <property name="text"> + <string>Inner detector surfaces</string> + </property> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_projections_vertex"> + <property name="title"> + <string>Vertex Projection</string> + </property> + <property name="flat"> + <bool>true</bool> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>false</bool> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QSpinBox" name="spinBox_projections_vertex"> + <property name="maximum"> + <number>179</number> + </property> + <property name="value"> + <number>90</number> + </property> + </widget> + </item> + <item> + <widget class="QSlider" name="horizontalSlider_projections_vertex"> + <property name="maximum"> + <number>179</number> + </property> + <property name="pageStep"> + <number>10</number> + </property> + <property name="sliderPosition"> + <number>90</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QHBoxLayout"> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_close"> + <property name="text"> + <string>&Close</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>horizontalSlider_projections_vertex</sender> + <signal>valueChanged(int)</signal> + <receiver>spinBox_projections_vertex</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>164</x> + <y>122</y> + </hint> + <hint type="destinationlabel"> + <x>57</x> + <y>123</y> + </hint> + </hints> + </connection> + <connection> + <sender>spinBox_projections_vertex</sender> + <signal>valueChanged(int)</signal> + <receiver>horizontalSlider_projections_vertex</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>57</x> + <y>123</y> + </hint> + <hint type="destinationlabel"> + <x>160</x> + <y>122</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/shift_muon_chamber_form.ui b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/shift_muon_chamber_form.ui new file mode 100644 index 000000000..cf20357dd --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/shift_muon_chamber_form.ui @@ -0,0 +1,269 @@ +<ui version="4.0" > + <class>TrackSysShiftMuonChambersForm</class> + <widget class="QWidget" name="TrackSysShiftMuonChambersForm" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>198</width> + <height>334</height> + </rect> + </property> + <property name="windowTitle" > + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout" > + <item> + <layout class="QHBoxLayout" name="horizontalLayout" > + <item> + <spacer name="horizontalSpacer_6" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label_7" > + <property name="text" > + <string>Station</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="StationName" > + <property name="text" > + <string>BML</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_5" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="Line" name="line" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3" > + <item> + <spacer name="horizontalSpacer_4" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QGridLayout" name="gridLayout" > + <item row="0" column="0" > + <widget class="QLabel" name="label" > + <property name="text" > + <string>tra_s</string> + </property> + </widget> + </item> + <item row="0" column="1" > + <widget class="QDoubleSpinBox" name="doubleSpinBox_tra_s" /> + </item> + <item row="1" column="0" > + <widget class="QLabel" name="label_2" > + <property name="text" > + <string>tra_z</string> + </property> + </widget> + </item> + <item row="1" column="1" > + <widget class="QDoubleSpinBox" name="doubleSpinBox_tra_z" /> + </item> + <item row="2" column="0" > + <widget class="QLabel" name="label_3" > + <property name="text" > + <string>tra_t</string> + </property> + </widget> + </item> + <item row="2" column="1" > + <widget class="QDoubleSpinBox" name="doubleSpinBox_tra_t" /> + </item> + <item row="3" column="0" > + <widget class="QLabel" name="label_4" > + <property name="text" > + <string>rot_s</string> + </property> + </widget> + </item> + <item row="3" column="1" > + <widget class="QDoubleSpinBox" name="doubleSpinBox_rot_s" /> + </item> + <item row="4" column="0" > + <widget class="QLabel" name="label_5" > + <property name="text" > + <string>rot_z</string> + </property> + </widget> + </item> + <item row="4" column="1" > + <widget class="QDoubleSpinBox" name="doubleSpinBox_rot_z" /> + </item> + <item row="5" column="0" > + <widget class="QLabel" name="label_6" > + <property name="text" > + <string>rot_t</string> + </property> + </widget> + </item> + <item row="5" column="1" > + <widget class="QDoubleSpinBox" name="doubleSpinBox_rot_t" /> + </item> + </layout> + </item> + <item> + <spacer name="horizontalSpacer" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>28</width> + <height>135</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_4" > + <item> + <spacer name="horizontalSpacer_8" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QComboBox" name="comboBox_level" > + <item> + <property name="text" > + <string>Level 0</string> + </property> + </item> + <item> + <property name="text" > + <string>Level 1</string> + </property> + </item> + <item> + <property name="text" > + <string>Level 2</string> + </property> + </item> + <item> + <property name="text" > + <string>Level 3</string> + </property> + </item> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_7" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2" > + <item> + <spacer name="horizontalSpacer_2" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_Update" > + <property name="text" > + <string>Update</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_3" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer" > + <property name="orientation" > + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>20</width> + <height>26</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/vp1trackcontrollerform.ui b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/vp1trackcontrollerform.ui new file mode 100644 index 000000000..4a729ebe1 --- /dev/null +++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/vp1trackcontrollerform.ui @@ -0,0 +1,161 @@ +<ui version="4.0" > + <class>VP1TrackControllerForm</class> + <widget class="QWidget" name="VP1TrackControllerForm" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>332</width> + <height>563</height> + </rect> + </property> + <property name="windowTitle" > + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout" > + <item> + <layout class="QHBoxLayout" name="horizontalLayout" > + <item> + <widget class="QWidget" native="1" name="widget_settingsButtonsPlaceholder" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Fixed" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <layout class="QGridLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>0</number> + </property> + <item row="0" column="0" > + <widget class="QPushButton" name="pushButton_settings_cuts" > + <property name="toolTip" > + <string>Configure track cuts on quantities such as eta, phi and momentum</string> + </property> + <property name="text" > + <string>Cuts</string> + </property> + <property name="checkable" > + <bool>true</bool> + </property> + </widget> + </item> + <item row="0" column="1" > + <widget class="QPushButton" name="pushButton_settings_colouring" > + <property name="toolTip" > + <string>Configure track colours</string> + </property> + <property name="text" > + <string>Colouring</string> + </property> + <property name="checkable" > + <bool>true</bool> + </property> + </widget> + </item> + <item row="0" column="2" > + <widget class="QPushButton" name="pushButton_settings_interactions" > + <property name="toolTip" > + <string>Settings for what happens in response to selections (printout, zooms, ...)</string> + </property> + <property name="text" > + <string>Interactions</string> + </property> + <property name="checkable" > + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="0" > + <widget class="QPushButton" name="pushButton_settings_details" > + <property name="toolTip" > + <string>Configure display of objects (measurements, surfaces, errors, ...) associated with the tracks</string> + </property> + <property name="text" > + <string>Details</string> + </property> + <property name="checkable" > + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="1" > + <widget class="QPushButton" name="pushButton_settings_projections" > + <property name="toolTip" > + <string>Configure projections to muon chamber sides and inner detector surfaces</string> + </property> + <property name="text" > + <string>Projections</string> + </property> + <property name="checkable" > + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="2" > + <widget class="QPushButton" name="pushButton_settings_extrapolation" > + <property name="toolTip" > + <string>Configure how the curves used for visualisation are constructed based on the actual available track parameters</string> + </property> + <property name="text" > + <string>Propagation</string> + </property> + <property name="checkable" > + <bool>true</bool> + </property> + </widget> + </item> + <item row="2" column="0" > + <widget class="QPushButton" name="pushButton_ObjectBrowser" > + <property name="enabled" > + <bool>true</bool> + </property> + <property name="toolTip" > + <string>Browse tracking objects in this event, and use to navigate in 3D view (especially if zooming is turned on in Interactions)</string> + </property> + <property name="text" > + <string>Browser</string> + </property> + <property name="checkable" > + <bool>true</bool> + </property> + <property name="checked" > + <bool>false</bool> + </property> + <property name="flat" > + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType" > + <enum>QSizePolicy::Preferred</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>51</width> + <height>89</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QScrollArea" name="collWidgetScrollArea" /> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/graphics/VTI12/VTI12Utils/CMakeLists.txt b/graphics/VTI12/VTI12Utils/CMakeLists.txt new file mode 100644 index 000000000..ca3fa3a00 --- /dev/null +++ b/graphics/VTI12/VTI12Utils/CMakeLists.txt @@ -0,0 +1,62 @@ +################################################################################ +# Package: VTI12Utils +################################################################################ +# Author: Thomas Kittelmann +# Author: Riccardo Maria BIANCHI <rbianchi@cern.ch> +################################################################################ + +# Declare the package name: +atlas_subdir( VTI12Utils ) + +# Declare the package's dependencies: +atlas_depends_on_subdirs( + PUBLIC + Control/AthenaKernel + Control/StoreGate + DetectorDescription/GeoPrimitives + Event/EventPrimitives + GaudiKernel + graphics/VP1/VP1Base + PRIVATE + Control/CxxUtils + DetectorDescription/FaserDetDescr + DetectorDescription/GeoModel/GeoModelUtilities + DetectorDescription/GeoModel/GeoModelFaserUtilities + DetectorDescription/GeoModel/GeoSpecialShapes + DetectorDescription/Identifier + Scintillator/ScintDetDescr/ScintIdentifier + Scintillator/ScintDetDescr/ScintReadoutGeometry +# InnerDetector/InDetDetDescr/InDetIdentifier +# InnerDetector/InDetDetDescr/InDetReadoutGeometry +# InnerDetector/InDetRecEvent/InDetRIO_OnTrack + Tracking/TrkDetDescr/TrkSurfaces + Tracking/TrkEvent/TrkRIO_OnTrack + graphics/VP1/VP1HEPVis ) + +# External dependencies: +find_package( CLHEP ) # TODO: to be removed when fully migrated to Eigen-based GeoTrf +find_package( Coin3D ) +find_package( Eigen ) +find_package( HepPDT ) +find_package( Qt5 COMPONENTS Core REQUIRED) +find_package( GeoModel ) + +# Generate MOC files automatically: +set( CMAKE_AUTOMOC ON ) + +# Component(s) in the package: +atlas_add_library( VTI12Utils VTI12Utils/*.h src/*.cxx src/*.cpp + PUBLIC_HEADERS VTI12Utils + INCLUDE_DIRS ${CLHEP_INCLUDE_DIRS} + PRIVATE_INCLUDE_DIRS ${HEPPDT_INCLUDE_DIRS} ${COIN3D_INCLUDE_DIRS} + ${EIGEN_INCLUDE_DIRS} + DEFINITIONS ${CLHEP_DEFINITIONS} + LINK_LIBRARIES ${CLHEP_LIBRARIES} ${GEOMODEL_LIBRARIES} EventPrimitives + GaudiKernel VP1Base StoreGateLib SGtests AthDSoCallBacks + GeoPrimitives Qt5::Core + PRIVATE_LINK_LIBRARIES ${HEPPDT_LIBRARIES} ${COIN3D_LIBRARIES} + ${EIGEN_LIBRARIES} CxxUtils FaserDetDescr + GeoModelUtilities GeoModelFaserUtilities GeoSpecialShapes Identifier + ScintIdentifier ScintReadoutGeometry +# InDetIdentifier InDetReadoutGeometry InDetRIO_OnTrack + TrkSurfaces TrkRIO_OnTrack VP1HEPVis ) diff --git a/graphics/VTI12/VTI12Utils/VTI12Utils/HitToSoNode.h b/graphics/VTI12/VTI12Utils/VTI12Utils/HitToSoNode.h new file mode 100644 index 000000000..3f624dd31 --- /dev/null +++ b/graphics/VTI12/VTI12Utils/VTI12Utils/HitToSoNode.h @@ -0,0 +1,64 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +// Update: Riccardo Maria BIANCHI rbianchi@cern.ch Feb 2014 // + +#ifndef VTI12UTILS_HITTOSONODE_H +#define VTI12UTILS_HITTOSONODE_H + +// This class is to allow the PRD and track systems to share the same code for drawing DEs. + +#include "VP1Base/VP1HelperClassBase.h" + +// Eigen Migration +#include "GeoPrimitives/GeoPrimitives.h" +#include "GeoPrimitives/CLHEPtoEigenConverter.h" +#include "GeoPrimitives/GeoPrimitivesHelpers.h" +// new files +#include "GeoPrimitives/CLHEPtoEigenEulerAnglesConverters.h" +#include "GeoPrimitives/EulerAnglesHelpers.h" + + +class SoSeparator; +class SoTransform; + +namespace Trk { + class RIO_OnTrack; + class TrkDetElementBase; +} +class Identifier; + +class HitToSoNode : public VP1HelperClassBase { +public: + + HitToSoNode( IVP1System * sys = 0 );//sys for messages + ~HitToSoNode(); + + SoTransform * createTransform(const Trk::RIO_OnTrack& rio, bool useSurfacePositionOnly) const; + void buildStripShapes(const Trk::RIO_OnTrack& rio, SoSeparator*&shape_simple, SoSeparator*&shape_detailed, bool blockGP); + // void buildTubeShapes(const Trk::RIO_OnTrack& rio, SoSeparator*&shape_simple, SoSeparator*&shape_detailed, bool blockGP, double length, bool doProjection); + +private: + + HitToSoNode( const HitToSoNode & ); + HitToSoNode & operator= ( const HitToSoNode & ); + + // Eigen migration +// void fillValues(Identifier& id, const Trk::TrkDetElementBase* baseDetEl, double& striplength, double& stripWidth, double& stripThickness, Trk::LocalPosition*& localposStrip); +// void fillRPCValues(Identifier& id, const Trk::TrkDetElementBase* baseDetEl, double& striplength, double& stripWidth, double& stripThickness, Trk::LocalPosition*& localposStrip); +// void fillTGCValues(Identifier& id, const Trk::TrkDetElementBase* baseDetEl, double& striplength, double& stripWidth, double& stripThickness, Trk::LocalPosition*& localposStrip); +// void fillCSCValues(Identifier& id, const Trk::TrkDetElementBase* baseDetEl, double& striplength, double& stripWidth, double& stripThickness, Trk::LocalPosition*& localposStrip); +// void fillSTGCValues(Identifier& id, const Trk::TrkDetElementBase* baseDetEl, double& striplength, double& stripWidth, double& stripThickness, Trk::LocalPosition*& localposStrip); +// void fillMMValues(Identifier& id, const Trk::TrkDetElementBase* baseDetEl, double& striplength, double& stripWidth, double& stripThickness, Trk::LocalPosition*& localposStrip); +// void fillSiValues(Identifier& id, const Trk::TrkDetElementBase* baseDetEl, double& striplength, double& stripWidth, double& stripThickness, Trk::LocalPosition*& localposStrip); +// + void fillValues(Identifier& id, const Trk::TrkDetElementBase* baseDetEl, double& striplength, double& stripWidth, double& stripThickness, Amg::Vector2D*& localposStrip); + // void fillSiValues(Identifier& id, const Trk::TrkDetElementBase* baseDetEl, double& striplength, double& stripWidth, double& stripThickness, Amg::Vector2D*& localposStrip); + + class Imp; + Imp * m_d; +}; + +#endif diff --git a/graphics/VTI12/VTI12Utils/VTI12Utils/HitsSoNodeManager.h b/graphics/VTI12/VTI12Utils/VTI12Utils/HitsSoNodeManager.h new file mode 100644 index 000000000..8738dd408 --- /dev/null +++ b/graphics/VTI12/VTI12Utils/VTI12Utils/HitsSoNodeManager.h @@ -0,0 +1,45 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef VTI12UTILS_HITSSONODEMANAGER_H +#define VTI12UTILS_HITSSONODEMANAGER_H + +//This class should as far as possible be used to create all shape +//nodes for hits. This allows for shared instancing and optimal memory +//and rendering performance. +// +//Author: Thomas Kittelmann. +#include "VP1Base/VP1HelperClassBase.h" +class SoNode; +class SoTransform; + +class HitsSoNodeManager : public VP1HelperClassBase { +public: + + HitsSoNodeManager( IVP1System * sys = 0 );//sys for messages + ~HitsSoNodeManager(); + + SoNode* getShapeNode_Point(); + SoNode* getShapeNode_Cross( double extent ); + // SoNode* getShapeNode_Cross( double extent, double x, double y, double z ); + SoNode* getShapeNode_DriftDisc( double radius );//Af flat drift tube. Returns point if radius is 0 + SoNode* getShapeNode_DriftTube( double halfLength, double radius );//Will return an SoCylinder unless radius is 0 - in that case returns a line. + SoNode* getShapeNode_ProjectedDriftTube( double halfLength, double radius, bool inner, bool outer );//Will return SoCylinder(s) unless radius is 0 - in that case returns point(s). + SoNode* getShapeNode_Strip( double length, double width = 0, double depth=0 );//if width & depth are 0, will return a line. If all are 0, will return a point. + SoNode* getShapeNode_Wire( double length, double minWidth = 0, double maxWidth=0, double depth=0 ); + SoNode* getShapeNode_Pad( double length, double minWidth = 0, double maxWidth=0, double depth=0 ); + + SoTransform * getUnitTransform(); + +private: + + HitsSoNodeManager( const HitsSoNodeManager & ); + HitsSoNodeManager & operator= ( const HitsSoNodeManager & ); + + class Imp; + Imp * m_d; + +}; + +#endif diff --git a/graphics/VTI12/VTI12Utils/VTI12Utils/InDetProjFlags.h b/graphics/VTI12/VTI12Utils/VTI12Utils/InDetProjFlags.h new file mode 100644 index 000000000..db1cf1e48 --- /dev/null +++ b/graphics/VTI12/VTI12Utils/VTI12Utils/InDetProjFlags.h @@ -0,0 +1,85 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +//////////////////////////////////////////////////////////////// +// // +// Common flags for Inner Detector projections // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: November 2007 // +// // +//////////////////////////////////////////////////////////////// + +//NB: This header file is intended to be seen by other systems (so +// they can use the flag types as signal parameters) - thus don't add +// extra includes/functionality here! + +#ifndef VTI12UTILS_INDETPROJECTIONFLAGS_H +#define VTI12UTILS_INDETPROJECTIONFLAGS_H + +#include <QFlags> + +class InDetProjFlags { +public: + + //Projected data in which parts of the detector: + enum DetTypeFlag { + NoDet = 0x000000, + SCT_brlpos = 0x000001, + SCT_brlneg = 0x000002, + SCT_ecpos = 0x000004, + SCT_ecneg = 0x000008, + SCT_all = 0x00000F, + Pixel_brlpos = 0x000010, + Pixel_brlneg = 0x000020, + Pixel_ecpos = 0x000040, + Pixel_ecneg = 0x000080, + Pixel_all = 0x0000F0, + TRT_brlpos = 0x000100, + TRT_brlneg = 0x000200, + TRT_ecpos = 0x000400, + TRT_ecneg = 0x000800, + TRT_all = 0x000F00 + }; + Q_DECLARE_FLAGS(DetTypeFlags, DetTypeFlag) + + //Project to which surfaces: + enum InDetProjPartsFlag { + NoProjections = 0x000000, + BarrelPositive = 0x000001, + BarrelNegative = 0x000002, + BarrelCentral = 0x000004, + EndCapOuterPositive = 0x000010, + EndCapOuterNegative = 0x000020, + EndCapInnerPositive = 0x000040, + EndCapInnerNegative = 0x000080, + //TRT only: + TRT_EndCapZToRPositive = 0x000100, + TRT_EndCapZToRNegative = 0x000200, + TRT_EndCapZToRCentral = 0x000400, + //Convenience: + Barrel_All = 0x000007, + Barrel_AllPos = 0x000005, + Barrel_AllNeg = 0x000006, + EndCap_All = 0x0007F0, + EndCap_AllPos = 0x000550, + EndCap_AllNeg = 0x0006A0 + }; + Q_DECLARE_FLAGS(InDetProjPartsFlags, InDetProjPartsFlag) + + //To null out parts of the flags, if the corresponding detector parts are not used: + static void projectionPartsGivenUsedDetectors( InDetProjPartsFlags& proj_pixel, + InDetProjPartsFlags& proj_sct, + InDetProjPartsFlags& proj_trt, + const DetTypeFlags& useddets ); + +private: + InDetProjFlags(); + ~InDetProjFlags(); +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(InDetProjFlags::DetTypeFlags) +Q_DECLARE_OPERATORS_FOR_FLAGS(InDetProjFlags::InDetProjPartsFlags) + +#endif diff --git a/graphics/VTI12/VTI12Utils/VTI12Utils/SbPolyhedrizeAction.h b/graphics/VTI12/VTI12Utils/VTI12Utils/SbPolyhedrizeAction.h new file mode 100644 index 000000000..aee527bbc --- /dev/null +++ b/graphics/VTI12/VTI12Utils/VTI12Utils/SbPolyhedrizeAction.h @@ -0,0 +1,77 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// ---------------------------------------------------------------------// +// // +// GeoPolyhedrizeAction. For internal use by SoVisualizeAction // +// Author: Joe Boudreau // +// // +//----------------------------------------------------------------------// + +#ifndef SbPolyhedrizeAction_h +#define SbPolyhedrizeAction_h 1 +#include "GeoModelKernel/GeoShapeAction.h" +class SbPolyhedron; +class SbPolyhedrizeAction : public GeoShapeAction + +{ + + public: + + SbPolyhedrizeAction(); + + virtual ~SbPolyhedrizeAction(); + + virtual void handleShift(const GeoShapeShift *shift); + + virtual void handleUnion(const GeoShapeUnion *unio); + + virtual void handleIntersection(const GeoShapeIntersection *isect); + + virtual void handleSubtraction(const GeoShapeSubtraction *subtract); + + virtual void handleBox(const GeoBox *box); + + virtual void handleCons(const GeoCons *cons); + + virtual void handlePara(const GeoPara *para); + + virtual void handlePcon(const GeoPcon *pcon); + + virtual void handlePgon(const GeoPgon *pgon); + + virtual void handleTrap(const GeoTrap *trap); + + virtual void handleTrd(const GeoTrd *trd); + + virtual void handleTube(const GeoTube *tube); + + virtual void handleTubs(const GeoTubs *tubs); + + virtual void handleSimplePolygonBrep (const GeoSimplePolygonBrep *brep); + + virtual void handleTessellatedSolid (const GeoTessellatedSolid *tessellated); + + virtual void handleGenericTrap (const GeoGenericTrap *gentrap); + + const SbPolyhedron * getPolyhedron() const; + + + private: + + SbPolyhedrizeAction(const SbPolyhedrizeAction &right); + const SbPolyhedrizeAction & operator=(const SbPolyhedrizeAction &right); + + SbPolyhedron *m_polyhedron; + +}; + + + + + + +#endif + + diff --git a/graphics/VTI12/VTI12Utils/VTI12Utils/SoTools.h b/graphics/VTI12/VTI12Utils/VTI12Utils/SoTools.h new file mode 100644 index 000000000..6e57c7d32 --- /dev/null +++ b/graphics/VTI12/VTI12Utils/VTI12Utils/SoTools.h @@ -0,0 +1,30 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/* + * SoTools.h + * + * Utility functions for Open Inventor nodes and objects + * + * + * Created on: Sep 3, 2014 + * Author: Riccardo Maria BIANCHI - rbianchi@cern.ch + */ + +#ifndef VTI12UTILS_SOTOOLS_H_ +#define VTI12UTILS_SOTOOLS_H_ + +// FWD declarations +class SoNode; + + +class SoTools { +public: + SoTools() {}; + virtual ~SoTools() {}; + + static void dumpNode(SoNode*); +}; + +#endif /* SOTOOLS_H_ */ diff --git a/graphics/VTI12/VTI12Utils/VTI12Utils/SoVisualizeAction.h b/graphics/VTI12/VTI12Utils/VTI12Utils/SoVisualizeAction.h new file mode 100644 index 000000000..f15a2b6e0 --- /dev/null +++ b/graphics/VTI12/VTI12Utils/VTI12Utils/SoVisualizeAction.h @@ -0,0 +1,71 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// ---------------------------------------------------------------------// +// // +// SoVisualizeAction. For internal use only. // +// Author: Joe Boudreau // +// // +//----------------------------------------------------------------------// + +#ifndef VTI12UTILS_SOVISUALIZEACTION_H +#define VTI12UTILS_SOVISUALIZEACTION_H 1 + +#include "GeoModelKernel/GeoShapeAction.h" + +class SoShape; + +class SoVisualizeAction : public GeoShapeAction { + +public: + + SoVisualizeAction(); + + virtual ~SoVisualizeAction(); + + virtual void handleShape(const GeoShape *subtract); + + virtual void handleBox(const GeoBox *box); + + virtual void handleCons(const GeoCons *cons); + + virtual void handlePcon(const GeoPcon *pcon); + + virtual void handleTrap(const GeoTrap *trap); + + virtual void handleTrd(const GeoTrd *trd); + + virtual void handleTube(const GeoTube *tube); + + virtual void handleTubs(const GeoTubs *tubs); + + #ifndef BUILDVP1LIGHT + virtual void handleLArCustom(const LArCustomShape *); + #endif + + virtual void handleSimplePolygonBrep(const GeoSimplePolygonBrep *); + + virtual void handleTessellatedSolid (const GeoTessellatedSolid *); + + virtual void handleGenericTrap (const GeoGenericTrap *); + + SoShape * getShape() { return m_shape; } + void reset() { m_shape = 0; } + +private: + + SoVisualizeAction(const SoVisualizeAction &); + const SoVisualizeAction & operator=(const SoVisualizeAction &); + + SoShape *m_shape; +}; + + + + + + +#endif + + diff --git a/graphics/VTI12/VTI12Utils/VTI12Utils/SurfaceToSoNode.h b/graphics/VTI12/VTI12Utils/VTI12Utils/SurfaceToSoNode.h new file mode 100644 index 000000000..d98f3e5f8 --- /dev/null +++ b/graphics/VTI12/VTI12Utils/VTI12Utils/SurfaceToSoNode.h @@ -0,0 +1,60 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef VTI12UTILS_SURFACETOSONODE_H +#define VTI12UTILS_SURFACETOSONODE_H + +///////////////////////////////////////////////////////////////////////// +// // +// Header file for class SurfaceToSoNode // +// // +// Author: Andreas Salzburger <Andreas.Salzburger@cern.ch> (primary) // +// Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Initial VP1 version: June 2007 // +// // +///////////////////////////////////////////////////////////////////////// + +class SoNode; + +namespace Trk { + class Surface; + class PlaneSurface; + class CylinderSurface; + class DiscSurface; + class StraightLineSurface; + class PerigeeSurface; +} + +class SurfaceToSoNode{ + +public: + // Public type definitions: + + // Default constructor + SurfaceToSoNode(); + + // Destructor + virtual ~SurfaceToSoNode(); + + // the general one, has to do a dynamic cast + SoNode* translateSurface(const Trk::Surface& sf, const bool& simple=false) const; + + // translate a PlaneSurface + SoNode* translatePlaneSurface(const Trk::PlaneSurface& psf ) const; + // translate a CylinderSurface + SoNode* translateCylinderSurface(const Trk::CylinderSurface& csf ) const; + // translate a DiscSurface + SoNode* translateDiscSurface(const Trk::DiscSurface& dsf) const; + // translate a StraightLineSurface + SoNode* translateStraightLineSurface(const Trk::StraightLineSurface& slsf, const bool& simple=false) const; + // translate a PerigeeSurface + SoNode* translatePerigeeSurface(const Trk::PerigeeSurface& persf) const; + + static double surfaceThickness; +}; + +#endif + + diff --git a/graphics/VTI12/VTI12Utils/VTI12Utils/VP1AvailableToolsHelper.h b/graphics/VTI12/VTI12Utils/VTI12Utils/VP1AvailableToolsHelper.h new file mode 100644 index 000000000..cf1ef9862 --- /dev/null +++ b/graphics/VTI12/VTI12Utils/VTI12Utils/VP1AvailableToolsHelper.h @@ -0,0 +1,81 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1AvailableToolsHelper // +// // +// Description: For monitoring the available tools of given // +// tool types, and for automatically taking // +// care of the state of associated gui elements // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: February 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VTI12UTILS_VP1AVAILABLETOOLSHELPER_H +#define VTI12UTILS_VP1AVAILABLETOOLSHELPER_H + +#include "VP1Base/VP1HelperClassBase.h" +#include <QObject> +#include <QStringList> +class IToolSvc; +class IVP1System; +class QComboBox; +class QWidget; + +class VP1AvailableToolsHelper : public QObject, public VP1HelperClassBase { + + Q_OBJECT + +public: + + VP1AvailableToolsHelper(IToolSvc*, QObject * parent = 0);//Use this to get error messages output to stdout. + VP1AvailableToolsHelper(IVP1System*, QObject * parent = 0);//Use this to also get error messages output in VP1 message area. + virtual ~VP1AvailableToolsHelper(); + + ///////////////////////////////////////////////// + // Change the currently monitored tool-types: // + ///////////////////////////////////////////////// + + void addMonitoredType(const QString&, const QStringList& ignoreList = QStringList());//List of (wildcarded) expressions of tool names to ignore (i.e. "*Fatras*") + void addMonitoredTypes(const QStringList&, const QStringList& ignoreList = QStringList()); + void removeMonitoredType(const QString&); + void removeMonitoredTypes(const QStringList&); + void clearMonitoredTypes(const QString&); + QStringList monitoredTypes() const; + + ///////////////////////////////////////////////////////////////////// + // Get list of available tools (calls update behind the scenes): // + ///////////////////////////////////////////////////////////////////// + + QStringList availableTools() const; + + //Convenience methods: + void setComboBoxData(QComboBox*);//Will be filled with a list of available tools (disabled if none are available); + void disableIfNoTools(QWidget*);//widget will be disabled (enabled) if the list of available tools is empty (not empty). + void handleComboBox(QComboBox*);//Calls setComboBoxData on the combobox whenever the list changes. + void handleEnabledState(QWidget*);//Calls disableIfNoTools on the widget whenever the list changes. + + void scheduleImmediateUpdate() const;//Updates immediately after event queue clears (NB: Not necessary in future Gaudi versions). + +signals: + void availableToolsChanged(const QStringList&) const; + +protected: + void timerEvent ( QTimerEvent * event ); +private: + class Imp; + Imp * m_d; + VP1AvailableToolsHelper( const VP1AvailableToolsHelper & ); + VP1AvailableToolsHelper & operator= ( const VP1AvailableToolsHelper & ); + +private slots: + void widgetDeleted(QObject*);//To automatically remove deleted widgets from internal lists. + void update() const;//Called internally every 2 seconds. In future gaudi versions we can instead register callbacks to the toolSvc. +}; + +#endif diff --git a/graphics/VTI12/VTI12Utils/VTI12Utils/VP1DetInfo.h b/graphics/VTI12/VTI12Utils/VTI12Utils/VP1DetInfo.h new file mode 100644 index 000000000..809e43d1f --- /dev/null +++ b/graphics/VTI12/VTI12Utils/VTI12Utils/VP1DetInfo.h @@ -0,0 +1,84 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1DetInfo // +// // +// Description: Convenient and safe access to detector // +// managers and identifier decoding // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: March 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VTI12UTILS_VP1DETINFO_H +#define VTI12UTILS_VP1DETINFO_H + +class IVP1System; +class StoreGateSvc; +// namespace InDetDD { class TRT_DetectorManager; } +// namespace InDetDD { class PixelDetectorManager; } +// namespace InDetDD { class SCT_DetectorManager; } +namespace ScintDD { class VetoDetectorManager; } +namespace ScintDD { class TriggerDetectorManager; } +namespace ScintDD { class PreshowerDetectorManager; } + +class FaserDetectorID; +class ScintDetectorID; +class VetoID; +class TriggerID; +class PreshowerID; +// class PixelID; +// class SCT_ID; +// class TRT_ID; + +class Identifier; + +class VP1DetInfo { +public: + static void ensureInit( IVP1System* ) {} + static void ensureInit( StoreGateSvc* ) {} + + //NB: Any of the methods returning pointers in this class might + //return null. And it is never allowed to delete any of the returned + //pointers! + + static const ScintDD::VetoDetectorManager * vetoDetMgr(); + static const ScintDD::TriggerDetectorManager * triggerDetMgr(); + static const ScintDD::PreshowerDetectorManager * preshowerDetMgr(); + + // static const InDetDD::PixelDetectorManager * pixelDetMgr(); + // static const InDetDD::SCT_DetectorManager * sctDetMgr(); + // static const InDetDD::TRT_DetectorManager * trtDetMgr(); + + //Base identifier helper: + static const FaserDetectorID * faserIDHelper(); + + //Common specialised identifier helpers: + + static const VetoID * vetoIDHelper(); + static const TriggerID * triggerIDHelper(); + static const PreshowerID * preshowerIDHelper(); + + // static const PixelID * pixelIDHelper(); + // static const SCT_ID * sctIDHelper(); + // static const TRT_ID * trtIDHelper(); + //Todo: Add more as needed. + + //Combines use of the atlasIDHelper and VP1JobConfigInfo to spot + //unsafe identifiers (i.e. a pixel identifier is unsafe if the.pixel + //geometry is not lodaded): + static bool isUnsafe(const Identifier&); + +private: + VP1DetInfo(){} + ~VP1DetInfo(){} + class Imp; +}; + + +#endif diff --git a/graphics/VTI12/VTI12Utils/VTI12Utils/VP1ErrorUtils.h b/graphics/VTI12/VTI12Utils/VTI12Utils/VP1ErrorUtils.h new file mode 100644 index 000000000..d476cc775 --- /dev/null +++ b/graphics/VTI12/VTI12Utils/VTI12Utils/VP1ErrorUtils.h @@ -0,0 +1,83 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1ErrorUtils // +// // +// Description: Utilities for drawing errors for various // +// measurements // +// // +// Author: Troels Kofoed Jacobsen // +// Initial version: July 2008 // +// // +// Update: Riccardo Maria BIANCHI Feb 2014 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VTI12UTILS_VP1ERRORUTILS_H +#define VTI12UTILS_VP1ERRORUTILS_H + +//#include "CLHEP/Geometry/Point3D.h" +//#include "TrkParameters/MeasuredTrackParameters.h" +#include "GeoPrimitives/GeoPrimitives.h" +#include "EventPrimitives/EventPrimitives.h"// EDM include(s): + + + +typedef AmgSymMatrix(2) AmgCovMatrix; + +class SoSeparator; +class SoGroup; +class SoLineSet; + +namespace InDet { class PixelCluster; } +namespace Trk { + class Surface; + class CovarianceMatrix; +} + +class VP1ErrorUtils +{ +public: + static void errorAtPlaneSurface( SoSeparator* errSimple, + SoSeparator* errDetailed, + const AmgSymMatrix(5)& tmpCovMat, + const Trk::Surface* theSurface, + const Amg::Vector3D& p1, + const double& nStdDev=3.0, + int numNodes = 12, + const bool& moveToSurface = false, + const bool& force1D=false, + const bool& addTransform=true); + + static void errorAtStraightLineSurface( SoSeparator* errSimple, SoSeparator* errDetailed, + const AmgSymMatrix(5)& tmpcovmat, + const Amg::Vector2D& localPos, + const Trk::Surface* theSurface, + const double& nStdDev=3.0, + const bool& drawZErrCircles=false, + const bool& drawCylinder=false, + int numNodes=12, + const bool& force1D=false, + const bool& addTransform=true); + + static void addRotatedErrorEllipse( SoGroup* gr, + const AmgSymMatrix(5)& covmat, + const double& sigmaScale, + int numNodes=12, + const double& translate=0.0, + const bool& symmetric=false); + + static void addSimple1DError( SoGroup* gr, + const double& error, + const double& sigmaScale, + const double& length); + + static bool covMatrixIsSane( const AmgCovMatrix& covmat); //!< returns false if there is a problem detected with the cov matrix + static bool covMatrixIsSane( const AmgSymMatrix(5)& covmat); //!< returns false if there is a problem detected with the cov matrix +}; + +#endif diff --git a/graphics/VTI12/VTI12Utils/VTI12Utils/VP1JobConfigInfo.h b/graphics/VTI12/VTI12Utils/VTI12Utils/VP1JobConfigInfo.h new file mode 100644 index 000000000..c4bc57979 --- /dev/null +++ b/graphics/VTI12/VTI12Utils/VTI12Utils/VP1JobConfigInfo.h @@ -0,0 +1,52 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1JobConfigInfo // +// // +// Description: Provides convenient and safe information // +// about the configuration of a given job // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: March 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VTI12UTILS_VP1JOBCONFIGINFO_H +#define VTI12UTILS_VP1JOBCONFIGINFO_H + +class IVP1System; +class StoreGateSvc; +class GeoPhysVol; +class GeoPVConstLink; + +class VP1JobConfigInfo { +public: + + static void ensureInit( IVP1System* ) {}//obsolete + static void ensureInit( StoreGateSvc* ) {}//obsolete + + //These next methods tells us what geomodel parts are initialised: + static bool hasGeoModelExperiment();//If GeoModelExperiment/"FASER" can be retrieved + + static bool hasVetoGeometry(); + static bool hasTriggerGeometry(); + static bool hasPreshowerGeometry(); + + // static bool hasPixelGeometry(); + static bool hasSCTGeometry() { return false; } + // static bool hasTRTGeometry(); + + //Top geomodel volume link (not strictly "JobConfig", but here it is): + static const GeoPVConstLink * geoModelWorld();//might return 0 + +private: + VP1JobConfigInfo(){} + ~VP1JobConfigInfo(){} + class Imp; +}; + +#endif diff --git a/graphics/VTI12/VTI12Utils/VTI12Utils/VP1LinAlgUtils.h b/graphics/VTI12/VTI12Utils/VTI12Utils/VP1LinAlgUtils.h new file mode 100644 index 000000000..3246c8100 --- /dev/null +++ b/graphics/VTI12/VTI12Utils/VTI12Utils/VP1LinAlgUtils.h @@ -0,0 +1,97 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1LinAlgUtils // +// // +// Description: Class holding CLHEP/Inventor algebra // +// methods. // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: March 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VTI12UTILS_VP1LINALGUTILS_H +#define VTI12UTILS_VP1LINALGUTILS_H + +class SoTransform; +class SbMatrix; + +#include "CLHEP/Geometry/Transform3D.h" + +// Eigen Migration +// see atlasoff/DetectorDescription/GeoPrimitives/trunk/GeoPrimitives/CLHEPtoEigenConverter.h +#include "GeoPrimitives/CLHEPtoEigenConverter.h" +#include "GeoPrimitives/GeoPrimitives.h" +#include "GeoPrimitives/GeoPrimitivesHelpers.h" + + +#include <QString> + + +class VP1LinAlgUtils { +public: + + static void transformToMatrix(SoTransform * xf, SbMatrix& result); + static void transformToMatrix(const HepGeom::Transform3D &, SbMatrix& result); + + //Will modify (and return) passed SoTransform pointer, unless it is zero. In that case it creates and returns a new SoTransform. + static SoTransform * toSoTransform(const HepGeom::Transform3D &, SoTransform * t = 0); + static SoTransform * toSoTransform(const Amg::Transform3D &, SoTransform * t = 0); + static SoTransform * toSoTransform(const SbMatrix&, SoTransform * t = 0); + + static void decodeTransformation( const SbMatrix&, //NB: Ignores the parts of the matrix related to scaling! + float& translation_x, float& translation_y, float& translation_z, + float& rotaxis_x, float& rotaxis_y, float& rotaxis_z, float& rotangle_radians ); + + //The following tests for sane transformations and will, if + //contextStr!="", print ERRORs to messageDebug. + //If called for a large number of transformations, it might be a + //good idea to only call when in verbose mode. contextStr's are used + //in the output to ease debugging (i.e. use values such as "input + //volume transformation").: + + static bool isSane( const HepGeom::Transform3D &, const QString& contextStr = "" ); + static bool isSane( const Amg::Transform3D &, const QString& contextStr = "" ); + static bool isSane( const SoTransform *, const QString& contextStr = "" ); + static bool isSane( const SbMatrix&, const QString& contextStr = "" ); + + //Misc: + static double phiFromXY(const double& x, const double&y ); + + //Misc. point/line distances: + + static void distPointLineParam(const Amg::Vector3D& point, const Amg::Vector3D& point0, + const Amg::Vector3D& point1, double& s); + //Modifies 's' to contain the + //parameter describing the point 'P' on the line giving the shortest + //distance as P=point0 + s*(point1-point0) + static double distPointLine2(const Amg::Vector3D& point, const Amg::Vector3D& point0, + const Amg::Vector3D& point1, double& s); + //Returns the shortest distance squared between the point 'point' + //and the line passing 'point0' and 'point1'. + + static void distLineLineParam(const Amg::Vector3D& point0, const Amg::Vector3D& point1, + const Amg::Vector3D& point2, const Amg::Vector3D& point3, + double& s, double& t); + //returns void, but modifies 's' and 't' to describe the points 'P' + //and 'Q' giving the shortest distance between the line passing + //point0 and point1 and the line passing point2 and point3. I.e: P = + //point0 + s*(point1 - point0). Q = point2 + t*(point3-point2) + + //FIXME: this should have a corresponding non-void function + //returning the actual distance (squared), e.g. the distance |PQ|, + //but this is omitted as it adds unneeded calculations ( for the + //current usage ). Also rename method. + +private: + VP1LinAlgUtils(){} + ~VP1LinAlgUtils(){} + class Imp; +}; + +#endif diff --git a/graphics/VTI12/VTI12Utils/VTI12Utils/VP1ParticleData.h b/graphics/VTI12/VTI12Utils/VTI12Utils/VP1ParticleData.h new file mode 100644 index 000000000..8824c6b72 --- /dev/null +++ b/graphics/VTI12/VTI12Utils/VTI12Utils/VP1ParticleData.h @@ -0,0 +1,42 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1ParticleData // +// // +// Description: Convenient and efficient access to particle // +// data. // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: March 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VTI12UTILS_VP1PARTICLEDATA_H +#define VTI12UTILS_VP1PARTICLEDATA_H + +#include <QString> +namespace HepPDT { class ParticleData; } + +class VP1ParticleData { +public: + + //Fast and convenient access methods for often accessed data: + + static double particleMass( const int& pdgcode, bool& ok );//ok == false indicates problems + static double particleCharge( const int& pdgcode, bool& ok );//ok == false indicates problems + static QString particleName( const int& pdgcode, bool& ok );//ok == false indicates problems + + //Full information: + static const HepPDT::ParticleData * particleData( const int& pdgcode );//Returns 0 in case of problems + +private: + VP1ParticleData(){} + ~VP1ParticleData(){} + class Imp; +}; + +#endif diff --git a/graphics/VTI12/VTI12Utils/VTI12Utils/VP1SGAccessHelper.h b/graphics/VTI12/VTI12Utils/VTI12Utils/VP1SGAccessHelper.h new file mode 100644 index 000000000..bba20771b --- /dev/null +++ b/graphics/VTI12/VTI12Utils/VTI12Utils/VP1SGAccessHelper.h @@ -0,0 +1,66 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1SGAccessHelper // +// // +// Description: Helper class for safe StoreGate retrieval // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: March 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VTI12UTILS_VP1SGACCESSHELPER_H +#define VTI12UTILS_VP1SGACCESSHELPER_H + +#include "VP1Base/VP1HelperClassBase.h" +#include "StoreGate/StoreGate.h" +#include <stdexcept> +class VP1SGContentsHelper; + +class VP1SGAccessHelper : public VP1HelperClassBase { +public: + + VP1SGAccessHelper( IVP1System *, const bool detStore = false );//For messages in gui (detStore=true takes detector rather than event store) + VP1SGAccessHelper( StoreGateSvc * ); + virtual ~VP1SGAccessHelper(); + + //////////////////////////////////////////////////////////////// + //Retrieve objects by type and key: + template <typename T> + bool retrieve( const T* &, const QString& key ) const;//returns false and sets to null pointer in case of errors + + template <typename T> + const T* retrieve( const QString& key ) const;//returns a null pointer in case of errors + + + //////////////////////////////////////////////////////////////// + // Retrieve all objects of type T (use handles as iterators): + template <typename T> + bool retrieve(const DataHandle<T>& begin, const DataHandle<T>& end, const bool&silent = false );//Returns false in case of errors. + //silent = true means all output will be redirected to verbose level + // -> NB: This DataHandle retrieval is something we should avoid in VP1!!! + // -> If you absolutely need to use it (due to bad implementations + // -> in upstream data providers), please use VP1SGContentsHelper + // -> to check that there is not more than one collection of the + // -> type you re trying to retrieve. If there is, abort! + +private: + + VP1SGAccessHelper( const VP1SGAccessHelper & ); + VP1SGAccessHelper & operator= ( const VP1SGAccessHelper & ); + + class Imp; + Imp * m_d; + + StoreGateSvc * storeGate() const; + bool contains(const CLID& id, const QString&) const; +}; + +#include "VTI12Utils/VP1SGAccessHelper.icc" + +#endif diff --git a/graphics/VTI12/VTI12Utils/VTI12Utils/VP1SGAccessHelper.icc b/graphics/VTI12/VTI12Utils/VTI12Utils/VP1SGAccessHelper.icc new file mode 100644 index 000000000..165c43416 --- /dev/null +++ b/graphics/VTI12/VTI12Utils/VTI12Utils/VP1SGAccessHelper.icc @@ -0,0 +1,98 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ + +#include "VP1Base/VP1Msg.h" + +template <typename T> +inline const T* VP1SGAccessHelper::retrieve( const QString& key ) const +{ + if (VP1Msg::verbose()) + messageVerbose("retrieve(..) called with key = "+key+" for type "+QString(typeid(T).name())); + + if (!storeGate()) { + message("ERROR Does not have StoreGate pointer. Returning null pointer."); + return 0; + } + + if (key.isEmpty()) { + message("ERROR retrieve called with empty key. Returning null pointer."); + return 0; + } + + if (!contains(ClassID_traits<T>::ID(),key)) { + messageDebug("WARNING retrieve called for key="+key+", which is not found in storeGate."); + return 0; + } + + const T* t(0); + bool exception = true; + // StatusCode sc; + try { + t = storeGate()->retrieve<const T>(key.toStdString()); + exception = false; + } catch (const std::runtime_error& e) { + exception = true; + t = 0; + } + if (exception ) { + message("ERROR: Exception thrown during call to StoreGateSvc::retrieve(..) with key="+key); + // sc.isFailure();//To make sure it is checked. + return 0; + } + if (!t) { + message("ERROR: Failed StoreGateSvc::retrieve(..) with key="+key+" claimed to be succesful, but resulted in NULL pointer."); + return 0; + } + if (VP1Msg::verbose()) + messageVerbose("Succesfully retrieved collection "+key); + return t; +} + +template <typename T> +inline bool VP1SGAccessHelper::retrieve( const T* & t, const QString& key ) const +{ + t = retrieve<T>(key); + return t != 0; +} + +template <typename T> +inline bool VP1SGAccessHelper::retrieve(const DataHandle<T>& begin, const DataHandle<T>& end, const bool&silent ) +{ + + if (VP1Msg::verbose()) + messageVerbose("retrieve(DataHandle<"+QString(typeid(T).name())+">,DataHandle<" + +QString(typeid(T).name())+">) called."); + if (!storeGate()) { + QString str("ERROR Does not have StoreGate pointer. Returning null pointer."); + silent ? messageVerbose(str) : message(str); + return false; + } + + bool exception = true; + StatusCode sc; + try { + sc = storeGate()->retrieve(begin,end); + exception = false; + } catch (const std::runtime_error& e) { + exception = true; + } + if (exception) { + QString str("ERROR: Exception thrown during call to StoreGateSvc::retrieve(DataHandle<" + +QString(typeid(T).name())+">,DataHandle<"+QString(typeid(T).name())+">)"); + silent ? messageVerbose(str) : message(str); + sc.isFailure();//To make sure it is checked. + return false; + } + if (sc.isFailure()) { + QString str( "ERROR: Failed StoreGateSvc::retrieve(DataHandle<" + +QString(typeid(T).name())+">,DataHandle<" + +QString(typeid(T).name())+">)"); + silent ? messageVerbose(str) : message(str); + return false; + } + + if (VP1Msg::verbose()) + messageVerbose("Successfully retrieved datahandles to "+QString(typeid(T).name())+"."); + return true; +} diff --git a/graphics/VTI12/VTI12Utils/VTI12Utils/VP1SGContentsHelper.h b/graphics/VTI12/VTI12Utils/VTI12Utils/VP1SGContentsHelper.h new file mode 100644 index 000000000..175b94046 --- /dev/null +++ b/graphics/VTI12/VTI12Utils/VTI12Utils/VP1SGContentsHelper.h @@ -0,0 +1,67 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1SGContentsHelper // +// // +// Description: Helper class for retrieving the available // +// keys in storegate for a given type. // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: March 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VTI12UTILS_VP1SGCONTENTSHELPER_H +#define VTI12UTILS_VP1SGCONTENTSHELPER_H + +#include "VP1Base/VP1HelperClassBase.h" +#include "AthenaKernel/ClassID_traits.h" +#include <QStringList> +class StoreGateSvc; + +class VP1SGContentsHelper : public VP1HelperClassBase { +public: + + VP1SGContentsHelper( IVP1System *, const bool detStore = false );//For messages in gui (detStore=true takes detector rather than event store) + VP1SGContentsHelper( StoreGateSvc * ); + virtual ~VP1SGContentsHelper() {} + + template <typename T> + QStringList getKeys() const; + QStringList getKeys( const CLID& id ) const; + + template <typename T> + bool contains( const QString& key ) const; + bool contains( const CLID& id, const QString& key ) const; + + QList<CLID> getPossibleCLIDs() const; + +private: + + StoreGateSvc * m_sg; + +}; + + +/////////////// +// Inlines // +/////////////// + +template <typename T> +inline QStringList VP1SGContentsHelper::getKeys() const +{ + return getKeys(ClassID_traits<T>::ID()); +} + +template <typename T> +inline bool VP1SGContentsHelper::contains( const QString& key ) const +{ + return contains(ClassID_traits<T>::ID(),key); +} + + +#endif diff --git a/graphics/VTI12/VTI12Utils/VTI12Utils/VP1ToolAccessHelper.h b/graphics/VTI12/VTI12Utils/VTI12Utils/VP1ToolAccessHelper.h new file mode 100644 index 000000000..aa8456d63 --- /dev/null +++ b/graphics/VTI12/VTI12Utils/VTI12Utils/VP1ToolAccessHelper.h @@ -0,0 +1,52 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1ToolAccessHelper // +// // +// Description: For safe retrieval of tools // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: February 2008 // +// // +//////////////////////////////////////////////////////////////// + +#ifndef VTI12UTILS_VP1TOOLACCESSHELPER_H +#define VTI12UTILS_VP1TOOLACCESSHELPER_H + +#include "VP1Base/VP1HelperClassBase.h" +#include "GaudiKernel/IToolSvc.h" +#include "GaudiKernel/ToolHandle.h" +#include <QString> +#include <map> +#include <stdexcept> + +class IVP1System; + +class VP1ToolAccessHelper : public VP1HelperClassBase { +public: + + VP1ToolAccessHelper( IToolSvc* );//Use this to get error messages output to stdout. + VP1ToolAccessHelper( IVP1System* );//Use this to also error messages output in VP1 message area. + ~VP1ToolAccessHelper() {}//Fixme: We should release tools in destructor. + + //NB: toolname should be in the form "ConcreteToolType/ToolInstanceName" + template <class toolT> + toolT * getToolPointer( const QString& toolname, bool silent=false, + bool createIfNotExists = false );//Returns 0 if tool does not exist or in case of errors. + //It never attempts to create the tool. + //If silent is set, problems are only output as verbose messages + +private: + VP1ToolAccessHelper(const VP1ToolAccessHelper & ); + VP1ToolAccessHelper & operator= (const VP1ToolAccessHelper & ); + IToolSvc * m_toolsvc; + std::map<std::pair<QString,QString>, IAlgTool*> m_toolname2pointer;//key is <toolname, typeinfo> +}; + +#include "VTI12Utils/VP1ToolAccessHelper.icc" + +#endif diff --git a/graphics/VTI12/VTI12Utils/VTI12Utils/VP1ToolAccessHelper.icc b/graphics/VTI12/VTI12Utils/VTI12Utils/VP1ToolAccessHelper.icc new file mode 100644 index 000000000..ab6fcbe7c --- /dev/null +++ b/graphics/VTI12/VTI12Utils/VTI12Utils/VP1ToolAccessHelper.icc @@ -0,0 +1,103 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ + +#include "VP1Base/VP1Msg.h" + +template <class toolT> +inline toolT * VP1ToolAccessHelper::getToolPointer( const QString& tooltypeandname, bool silent, bool createIfNotExists ) +{ + //We use the typeid for dynamic type-checking, since, for unknown + //reasons, we have to static_cast through void pointers in order to + //keep correct pointers and avoid dynamic casts to null! + QString typeidstr(typeid(toolT*).name()); + + if (VP1Msg::verbose()) + messageVerbose("getToolPointer(..) called with tool type/name = "+tooltypeandname + +", with return typeid = "+typeidstr); + if (!m_toolsvc) { + messageVerbose("getToolPointer(..) WARNING does not have toolSvc pointer. Returning NULL."); + return 0; + } + if (tooltypeandname.isEmpty()||!tooltypeandname.contains('/')) { + messageDebug("getToolPointer(..) WARNING requested tool name has incorrect format ("+tooltypeandname+")!"); + return 0; + } + + std::pair<QString,QString> id(tooltypeandname,typeidstr); + const typename std::map<std::pair<QString,QString>,IAlgTool*>::iterator it = m_toolname2pointer.find(id); + if (it==m_toolname2pointer.end()) { + //This is the first attempt at retrieval. + + //Fixme/todo: Should we check that tool exists before any attempts + //at retrieval are done?? + + //Create tool handle: + ToolHandle<toolT> toolhandle( tooltypeandname.toStdString(), + 0/*public tools only*/, + createIfNotExists ); + bool exception = true; + bool retrieveok = false; + try { + retrieveok = !toolhandle.retrieve().isFailure(); + exception = false; + } catch (const std::runtime_error& e) { + exception = true; + } + if (exception) { + if (silent) + messageVerbose("ToolHandle<>::retrieve() throws exception."); + else + messageDebug("ToolHandle<>::retrieve() throws exception."); + m_toolname2pointer[id] = 0; + + return 0; + } + if (!retrieveok) { + if (silent) + messageVerbose("getToolPointer(..) ERROR: Failed to retrieve tool: "+tooltypeandname); + else + message("getToolPointer(..) ERROR: Failed to retrieve tool: "+tooltypeandname); + m_toolname2pointer[id] = 0; + return 0; + } + + //Get pointer. + toolT * thetool = &(*toolhandle); + if (!thetool) { + message("getToolPointer(..) ERROR: Tool retrieve claimed to be succesful, but pointer is NULL!"); + return 0; + } + + if (!isValidInterface(thetool)) { + message("getToolPointer(..) ERROR: Tool retrieved is not a valid interface!"); + thetool = 0; + } + if (VP1Msg::verbose()) + messageVerbose("Returning "+str(thetool)+" tool pointer."); + //We need the cast to void ptr to work around some WEIRD pointer + //values introduced by a more straight-forward casting: + void* voidptr = static_cast<void*>(thetool); + IAlgTool* algptr = static_cast<IAlgTool*>(voidptr); + if (VP1Msg::verbose()) + messageVerbose("getToolPointer(..) Storing ptr = "+str(algptr)); + m_toolname2pointer[id] = algptr; + return thetool; + } else { + //Not first attempt: + if (!it->second) { + messageVerbose("getToolPointer(..) Returning null tool pointer since previous retrieval attempts failed))."); + return 0; + } + toolT* pointer = static_cast<toolT*>(static_cast<void*>(it->second)); + if (!pointer) { + //Fixme: Respect silent flag here? + message("getToolPointer(..) ERROR: Could not cast IAlgTool pointer "+str(it->second) + +" to type "+QString(typeid(toolT*).name())+". Returning 0."); + return 0; + } + if (VP1Msg::verbose()) + messageVerbose("getToolPointer(..) Retrieved tool pointer ("+str(pointer)+") succesfully"); + return pointer; + } +} diff --git a/graphics/VTI12/VTI12Utils/src/HitToSodeNode.cxx b/graphics/VTI12/VTI12Utils/src/HitToSodeNode.cxx new file mode 100644 index 000000000..beef5e8c2 --- /dev/null +++ b/graphics/VTI12/VTI12Utils/src/HitToSodeNode.cxx @@ -0,0 +1,218 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +// Update: Riccardo Maria BIANCHI rbianchi@cern.ch Feb 2014 // + +#ifndef BUILDVP1LIGHT + +#include "VTI12Utils/HitToSoNode.h" +#include "VTI12Utils/HitsSoNodeManager.h" +#include "VTI12Utils/VP1LinAlgUtils.h" +#include "VTI12Utils/VP1DetInfo.h" +#include "VP1Base/VP1Msg.h" +#include "VP1HEPVis/nodes/SoTransparency.h" + +#include <Inventor/nodes/SoSeparator.h> +#include <Inventor/nodes/SoTranslation.h> +#include <Inventor/nodes/SoNode.h> +#include <Inventor/nodes/SoTransform.h> +#include <Inventor/nodes/SoPointSet.h> +#include <Inventor/nodes/SoLineSet.h> + +#include "TrkSurfaces/Surface.h" +#include "TrkRIO_OnTrack/RIO_OnTrack.h" + +// #include "InDetRIO_OnTrack/TRT_DriftCircleOnTrack.h" + +#include "ScintReadoutGeometry/ScintDetectorElement.h" +// #include "InDetReadoutGeometry/SiDetectorElement.h" + +#include <sstream> +#include <cmath> + + +#include "EventPrimitives/EventPrimitivesToStringConverter.h" +#include "GeoPrimitives/GeoPrimitivesToStringConverter.h" + +class HitToSoNode::Imp { +public: + Imp() : theclass(0), driftdischeight(0.15) {} + HitToSoNode * theclass; + const double driftdischeight; + HitsSoNodeManager nodeManager; +}; + +HitToSoNode::HitToSoNode(IVP1System * sys) + : VP1HelperClassBase(sys,"HitToSoNode"), m_d(new Imp) +{ + m_d->theclass = this; +} + +//____________________________________________________________________ +HitToSoNode::~HitToSoNode() +{ + messageVerbose("destructor begin"); + delete m_d; + messageVerbose("destructor end"); +} + +//____________________________________________________________________ +SoTransform * HitToSoNode::createTransform(const Trk::RIO_OnTrack& rio, bool useSurfacePositionOnly) const +{ + const Trk::Surface& theSurface = rio.detectorElement()->surface(rio.identify()); + SoTransform * theHitTransform = VP1LinAlgUtils::toSoTransform(theSurface.transform()); + + // const Amg::Vector3D* theHitGPos; + if ( useSurfacePositionOnly ) { + // if (verbose) VP1Msg::message("useSurfacePositionOnly"); + theHitTransform->translation.setValue(theSurface.center()[0], theSurface.center()[1], theSurface.center()[2]); + + } else { + + // for strips, clusters or short tubes, use position of hit. + // FIXME - for DCs, shouldn't this be the d0=0 position, i.e. on the wire? + theHitTransform->translation.setValue(rio.globalPosition()[0], rio.globalPosition()[1], rio.globalPosition()[2]); + } + return theHitTransform; +} + +// void HitToSoNode::buildTubeShapes(const Trk::RIO_OnTrack& rio, SoSeparator*&shape_simple, SoSeparator*&shape_detailed, bool /**blockGP*/, double length, bool doProjection) +// { +// const Trk::CylinderBounds* ccbo = dynamic_cast<const Trk::CylinderBounds*>(&(rio.detectorElement()->surface(rio.identify()).bounds())); +// assert(ccbo!=0); +// if (!ccbo) { +// VP1Msg::message("HitToSoNode::buildTubeShapes ERROR: Trk::CylinderBounds conversion failed"); +// return; +// } + +// double radius = fabs(rio.localParameters().get(Trk::locR)); +// if (radius<0.15) +// radius = 0.0;//radius is so small it is better to collapse to line + +// double halflength(ccbo->halflengthZ()); + +// if (doProjection && dynamic_cast<const InDet::TRT_DriftCircleOnTrack*>(&rio)){ + +// double strawLength=2.0*halflength; +// if (strawLength<160.0) +// strawLength = 2*349.3150-strawLength;//Yeah, we hardcode a lot here... but dimensions of TRT barrel straws are not likely to change. + +// SoPointSet * scatPointSet = new SoPointSet; +// SoVertexProperty * scatVtxProperty = new SoVertexProperty; +// scatVtxProperty->vertex.set1Value(0,0.0f,0.0f,strawLength); +// scatPointSet->numPoints=1; +// scatPointSet->vertexProperty.setValue(scatVtxProperty); + +// shape_detailed->addChild(scatPointSet); +// shape_simple->addChild(scatPointSet); + +// } else { +// if (length!=0.0) { +// halflength = length/2.0; +// // FIXME! translate to z position here instead of in AscObj_TSOS, for symmetry with buildStripShapes +// } +// SoNode * simpleShape = m_d->nodeManager.getShapeNode_DriftTube( halflength, 0.0 ); +// shape_simple->addChild(simpleShape); +// //Detailed shape uses tube (unless negligible radius): +// if (radius==0.0) +// shape_detailed->addChild(simpleShape); +// else +// shape_detailed->addChild(m_d->nodeManager.getShapeNode_DriftTube( halflength, radius )); +// } +// } + +void HitToSoNode::buildStripShapes(const Trk::RIO_OnTrack& rio, SoSeparator*&shape_simple, SoSeparator*&shape_detailed, bool blockGP) +{ + // assuming starting with position being that of centre of surface i.e. always working in local coord system + + + double stripLength =100.0, stripWidth = 10.0, stripThickness=1.0; + const Amg::Vector2D* localposROT=0; + Amg::Vector2D* localposStrip=0; + Identifier id=rio.identify(); + fillValues(id, rio.detectorElement(), stripLength, stripWidth, stripThickness, localposStrip); + + //std::cout<<"Got back: "<<stripLength<<","<<stripWidth<<","<<stripThickness<<std::endl; + //std::cout<<"LocalposStrip="<<*localposStrip<<std::endl; + + // if (static_cast<PRDCollHandle_TGC*>(collHandle())->project()) + // striplength += 300.0;//Fixme: Rough extension for now + double tolerance = 3.; + localposROT = rio.detectorElement()->surface( rio.identify() ).globalToLocal(rio.globalPosition(), tolerance); + + if( !localposROT ) + { + localposROT = new Amg::Vector2D; + VP1Msg::message("Warning: Local hit position was NULL"); + } + + if (!blockGP){ + SoSeparator * gpSep = new SoSeparator; + SoTranslation * localtransGP = new SoTranslation; + localtransGP->translation.setValue(static_cast<float>( (*localposROT)[Trk::locX]), + static_cast<float>( (*localposROT)[Trk::locY]), + 0.0f); + + gpSep->addChild(localtransGP); + gpSep->addChild(m_d->nodeManager.getShapeNode_Cross(10)); + shape_detailed->addChild(gpSep); + } + + + SoTranslation * localtrans0 = new SoTranslation; + localtrans0->translation.setValue(static_cast<float>( (*localposStrip)[Trk::locX]), + static_cast<float>( (*localposStrip)[Trk::locY]), + 0.0f); + + + shape_simple->addChild(localtrans0); + shape_simple->addChild( m_d->nodeManager.getShapeNode_Strip(stripLength)); + + shape_detailed->addChild(localtrans0); + shape_detailed->addChild(m_d->nodeManager.getShapeNode_Strip(stripLength,stripWidth,stripThickness)); + // Transform back to centre of Surface + SoTranslation * localtrans1 = new SoTranslation; + localtrans1->translation.setValue(static_cast<float>( -(*localposStrip)[Trk::locX]), + static_cast<float>( -(*localposStrip)[Trk::locY]), + 0.0f); + shape_simple->addChild(localtrans1); + shape_detailed->addChild(localtrans1); + + delete localposStrip; + delete localposROT; +} + +void HitToSoNode::fillValues(Identifier& /*id*/, const Trk::TrkDetElementBase* /*baseDetEl*/, double& /*striplength*/, double& /*stripWidth*/, double& /*stripThickness*/, Amg::Vector2D*& /*localposStrip*/){ + + const FaserDetectorID * idhelper = VP1DetInfo::faserIDHelper(); + if (!idhelper) return; + // if (idhelper->is_indet(id) && (idhelper->is_pixel(id)||idhelper->is_sct(id))) { + // fillSiValues(id, baseDetEl, striplength, stripWidth, stripThickness, localposStrip); return; + // } + VP1Msg::message("Warning: HitToSoNode::fillValues(...) unknown technology."); + return; +} + + +// void HitToSoNode::fillSiValues(Identifier& id, const Trk::TrkDetElementBase* baseDetEl, double& striplength, double& stripWidth, double& stripThickness, Amg::Vector2D*& localposStrip){ +// const InDetDD::SiDetectorElement* detEl = +// dynamic_cast<const InDetDD::SiDetectorElement*>(baseDetEl); +// if ( !detEl){ +// VP1Msg::message("Could not get Si det element"); +// localposStrip = new Amg::Vector2D; +// return; +// } + +// localposStrip = new Amg::Vector2D(detEl->rawLocalPositionOfCell( id )); +// // (*localPosStrip)[Trk::distPhi] += (idhelper->is_pixel(id) ? m_pixelLorentzAngleTool : m_sctLorentzAngleTool)->getLorentzShift(detEl->identifyHash()); +// // SiLorentzAngleTool cannot be used here because HitToSoNode is not a tool nor algorithm + +// striplength = detEl->etaPitch() ; +// stripWidth = detEl->phiPitch( *localposStrip ); +// stripThickness = detEl->thickness()/10.0; + +// } + +#endif // BUILDVP1LIGHT diff --git a/graphics/VTI12/VTI12Utils/src/HitsSoNodeManager.cxx b/graphics/VTI12/VTI12Utils/src/HitsSoNodeManager.cxx new file mode 100644 index 000000000..745770365 --- /dev/null +++ b/graphics/VTI12/VTI12Utils/src/HitsSoNodeManager.cxx @@ -0,0 +1,463 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "VTI12Utils/HitsSoNodeManager.h" +#include "VP1Base/VP1Msg.h" + +#include <Inventor/C/errors/debugerror.h> +#include <Inventor/nodes/SoVertexProperty.h> +#include <Inventor/nodes/SoLineSet.h> +#include <Inventor/nodes/SoPointSet.h> +#include <Inventor/nodes/SoSeparator.h> +#include <Inventor/nodes/SoCylinder.h> +#include <Inventor/nodes/SoRotationXYZ.h> +#include <Inventor/nodes/SoTranslation.h> +#include <Inventor/nodes/SoInfo.h> +#include <Inventor/nodes/SoTransform.h> + +#include "VP1HEPVis/nodes/SoGenericBox.h" + +#include <map> +#include <iostream> + +#include "CxxUtils/fpcompare.h" + +//____________________________________________________________________ +class HitsSoNodeManager::Imp { +public: + Imp() : theclass(0), driftdischeight(0.15), cachedshape_point(0), cached_unittransform(0) {} + HitsSoNodeManager * theclass; + const double driftdischeight; + std::map<double,SoNode*,CxxUtils::fpcompare_fn::less> cachedshapes_drifttubes; + std::map<double,SoNode*,CxxUtils::fpcompare_fn::less> cachedshapes_driftdiscs; + std::map<double,SoNode*,CxxUtils::fpcompare_fn::less> cachedshapes_projdrifttubes; + std::map<double,SoNode*,CxxUtils::fpcompare_fn::less> cachedshapes_strips; + SoNode * cachedshape_point; + std::map<double,SoNode*,CxxUtils::fpcompare_fn::less> cachedshapes_cross; + SoTransform * cached_unittransform; + + //Util, for cleaning up: + template <class T> + static void unrefValues(T&t) { + typename T::iterator it(t.begin()), itE(t.end()); + for (;it!=itE;++it) + it->second->unref(); + } + + void sanitiseParameterValue( double& x ) { + //Flips sign of parameter if negative, and makes sure it is not of + //negligible size. + if ( x != x ) { + theclass->message("sanitiseParameterValue WARNING - received nan paramter. Putting to 1.0e-5."); + x = 1.0e-5; + return; + } + if ( x <= 1.0e-5 ) { + if ( x < 0.0 ) { + if (VP1Msg::verbose()) + theclass->messageVerbose("sanitiseParameterValue WARNING - received negative parameter. Flipping sign."); + x = - x; + } + if ( x < 1.0e-5 ) + x = 1.0e-5; + } + } + void sanitiseParameterValueAllowZero( double& x ) { + //Flips sign of parameter if negative, and makes sure it, if + //non-zero, that it is not of negligible size. + if ( x != x ) { + theclass->message("sanitiseParameterValue WARNING - received nan paramter. Putting to 1.0e-5."); + x = 1.0e-5; + return; + } + if ( x <= 1.0e-5 ) { + if ( x < 0.0 ) { + if (VP1Msg::verbose()) + theclass->messageVerbose("sanitiseParameterValue WARNING - received negative parameter. Flipping sign."); + x = - x; + } + if ( x < 1.0e-5 && x != 0.0 ) + x = 1.0e-5; + } + } + + void summarise(unsigned n,const QString& shapename) const; + +}; + + +//____________________________________________________________________ +HitsSoNodeManager::HitsSoNodeManager(IVP1System * sys) + : VP1HelperClassBase(sys,"HitsSoNodeManager"), m_d(new Imp) +{ + m_d->theclass = this; + m_d->cachedshape_point = 0; + m_d->cached_unittransform = 0; +} + + +//____________________________________________________________________ +void HitsSoNodeManager::Imp::summarise(unsigned n,const QString& shapename) const +{ + if (n>100) + theclass->messageDebug(" WARNING: Created more than 100 ("+QString::number(n)+") different "+shapename+" shapes."); + else if (VP1Msg::verbose()) + theclass->messageVerbose("Created "+QString::number(n)+" different "+shapename+" shapes."); +} + + +//____________________________________________________________________ +HitsSoNodeManager::~HitsSoNodeManager() +{ + messageVerbose("destructor begin"); + + //Make sure we know if we didn't have efficient shared instancing: + m_d->summarise(m_d->cachedshapes_drifttubes.size(),"drift tube"); + m_d->summarise(m_d->cachedshapes_driftdiscs.size(),"drift disc"); + m_d->summarise(m_d->cachedshapes_projdrifttubes.size(),"projected drift tube"); + m_d->summarise(m_d->cachedshapes_strips.size(),"strip"); + m_d->summarise(m_d->cachedshapes_cross.size(),"cross"); + + //unref kept nodes: + Imp::unrefValues(m_d->cachedshapes_drifttubes); + Imp::unrefValues(m_d->cachedshapes_driftdiscs); + Imp::unrefValues(m_d->cachedshapes_projdrifttubes); + Imp::unrefValues(m_d->cachedshapes_strips); + Imp::unrefValues(m_d->cachedshapes_cross); + if (m_d->cachedshape_point) + m_d->cachedshape_point->unref(); + if (m_d->cached_unittransform) + m_d->cached_unittransform->unref(); + + delete m_d; + messageVerbose("destructor end"); +} + +//____________________________________________________________________ +SoNode* HitsSoNodeManager::getShapeNode_DriftTube( double halfLength, double radius ) +{ + m_d->sanitiseParameterValue(halfLength); + m_d->sanitiseParameterValueAllowZero(radius); + //Fixme: discretize by radius!! + + double id(halfLength-999999999.9*radius); + std::map<double,SoNode*>::const_iterator it = m_d->cachedshapes_drifttubes.find(id); + if (it!=m_d->cachedshapes_drifttubes.end()) + return it->second; + + if (radius>0) { + SoSeparator*sep = new SoSeparator; + SoRotationXYZ * rot = new SoRotationXYZ; + rot->axis.setValue(SoRotationXYZ::X); + rot->angle.setValue(M_PI*0.5f); + sep->addChild(rot); + SoCylinder * cyl = new SoCylinder; + cyl->radius.setValue(radius); + cyl->height.setValue(2.0f*halfLength); + sep->addChild(cyl); + m_d->cachedshapes_drifttubes[id] = sep; + sep->ref(); + return sep; + } else { + SoVertexProperty * scatVtxProperty = new SoVertexProperty(); + scatVtxProperty->vertex.set1Value(0, 0.0f,0.0f,-halfLength); + scatVtxProperty->vertex.set1Value(1, 0.0f,0.0f, halfLength); + SoLineSet * line = new SoLineSet(); + line->numVertices = 2; + line->vertexProperty = scatVtxProperty; + m_d->cachedshapes_drifttubes[id] = line; + line->ref(); + return line; + } + +} + +//____________________________________________________________________ +SoNode* HitsSoNodeManager::getShapeNode_DriftDisc( double radius ) +{ + m_d->sanitiseParameterValueAllowZero(radius); + if (radius==0.0) + return getShapeNode_Point(); + + std::map<double,SoNode*>::const_iterator it = m_d->cachedshapes_driftdiscs.find(radius); + if (it!=m_d->cachedshapes_driftdiscs.end()) + return it->second; + + SoSeparator*sep = new SoSeparator;//fixme: check if sogroup improves performance. + SoRotationXYZ * rot = new SoRotationXYZ; + rot->axis.setValue(SoRotationXYZ::X); + rot->angle.setValue(M_PI*0.5f); + sep->addChild(rot); + SoCylinder * cyl = new SoCylinder; + cyl->radius.setValue(radius); + cyl->height.setValue(m_d->driftdischeight); + sep->addChild(cyl); + + m_d->cachedshapes_driftdiscs[radius] = sep; + sep->ref(); + return sep; +} + +//____________________________________________________________________ +SoNode* HitsSoNodeManager::getShapeNode_ProjectedDriftTube( double halfLength, double radius, + bool inner, bool outer ) +{ + m_d->sanitiseParameterValue(halfLength); + m_d->sanitiseParameterValueAllowZero(radius); + //Fixme: discretize by radius!! + + double id(halfLength-9999.9*radius-(inner?0.0:-9999799.99)-(outer?0.0:-9999997979.99));//something unique + std::map<double,SoNode*>::const_iterator it = m_d->cachedshapes_projdrifttubes.find(id); + if (it!=m_d->cachedshapes_projdrifttubes.end()) + return it->second; + + if (!inner&&!outer) { + //Should probably never be called. But whatever: + SoInfo * info = new SoInfo;//something harmless and lightweight. + info->ref(); + m_d->cachedshapes_projdrifttubes[id] = info; + return info; + } + + //Fix for inner projections to put the hits from short barrel straws onto same z as the long barrel straws: + double halfLengthInner = halfLength<160.0 ? 2*349.3150-halfLength : halfLength; + m_d->sanitiseParameterValue(halfLengthInner); + + if (radius>0) { + SoSeparator*sep = new SoSeparator;//fixme: check if sogroup improves performance. + SoRotationXYZ * rot = new SoRotationXYZ; + rot->axis.setValue(SoRotationXYZ::X); + rot->angle.setValue(M_PI*0.5f); + sep->addChild(rot); + SoCylinder * cyl = new SoCylinder; + cyl->radius.setValue(radius); + cyl->height.setValue(m_d->driftdischeight); + if (inner) { + SoTranslation * trans = new SoTranslation; + trans->translation.setValue(0.0f,halfLengthInner,0.0f); + sep->addChild(trans); + sep->addChild(cyl); + } + if (outer) { + SoTranslation * trans = new SoTranslation; + trans->translation.setValue(0.0f,(inner?-halfLength-halfLengthInner:-halfLength),0.0f); + sep->addChild(trans); + sep->addChild(cyl); + } + m_d->cachedshapes_projdrifttubes[id] = sep; + sep->ref(); + return sep; + } else { + SoPointSet * scatPointSet = new SoPointSet; + SoVertexProperty * scatVtxProperty = new SoVertexProperty; + int i(0); + if (inner) + scatVtxProperty->vertex.set1Value(i++,0.0f,0.0f,halfLengthInner); + if (outer) + scatVtxProperty->vertex.set1Value(i++,0.0f,0.0f,-halfLength); + scatPointSet->numPoints=i; + scatPointSet->vertexProperty.setValue(scatVtxProperty); + m_d->cachedshapes_projdrifttubes[id] = scatPointSet; + scatPointSet->ref(); + return scatPointSet; + } +} + + +//____________________________________________________________________ +SoNode* HitsSoNodeManager::getShapeNode_Strip( double length, double width, double depth ) +{ + //std::cout << "HitsSoNodeManager::getShapeNode_Strip()" << std::endl; + + m_d->sanitiseParameterValueAllowZero(length); + m_d->sanitiseParameterValueAllowZero(width); + m_d->sanitiseParameterValueAllowZero(depth); + + double id(length-width*9999.99-depth*999999799.0);//something unique + std::map<double,SoNode*>::const_iterator it = m_d->cachedshapes_strips.find(id); + if (it!=m_d->cachedshapes_strips.end()) + return it->second; + + if (width==0.0&&depth==0) { + if (length==0.0) { + std::cout << "lengthStrip==0.0, returning a point..." << std::endl; + return getShapeNode_Point(); + } + //Return a line: + SoVertexProperty * scatVtxProperty = new SoVertexProperty(); + scatVtxProperty->vertex.set1Value(0, 0.0f,-length*0.5f,0.0f); + scatVtxProperty->vertex.set1Value(1, 0.0f, length*0.5f,0.0f); + SoLineSet * line = new SoLineSet(); + line->numVertices = 2; + line->vertexProperty = scatVtxProperty; + m_d->cachedshapes_strips[id] = line; + line->ref(); + return line; + } else { + //Return a box. + SoGenericBox::initClass(); + SoGenericBox* cube = new SoGenericBox; + m_d->sanitiseParameterValue(length); + m_d->sanitiseParameterValue(width); + m_d->sanitiseParameterValue(depth); + cube->setParametersForBox(0.5*width,0.5*length,0.5*depth); + m_d->cachedshapes_strips[id] = cube; + cube->drawEdgeLines = true; + cube->ref(); + return cube; + } + /** Can never reach this line (coverity 31149) + std::cout << "Returning zero!" << std::endl; + return 0; + **/ +} + +//____________________________________________________________________ +SoNode* HitsSoNodeManager::getShapeNode_Wire( double length, double minWidth, double maxWidth, double depth ) +{ + + //std::cout << "HitsSoNodeManager::getShapeNode_Wire()" << std::endl; + + m_d->sanitiseParameterValueAllowZero(length); + m_d->sanitiseParameterValueAllowZero(minWidth); + m_d->sanitiseParameterValueAllowZero(maxWidth); + m_d->sanitiseParameterValueAllowZero(depth); + + //double id(length-minWidth*9999.99-depth*999999799.0);//something unique + //std::map<double,SoNode*>::const_iterator it = m_d->cachedshapes_strips.find(id); + //if (it!=m_d->cachedshapes_strips.end()) + // return it->second; + + if (maxWidth==0.0&&depth==0) { + if (length==0.0) { + std::cout << "lengthWire==0.0, returning a point..." << std::endl; + return getShapeNode_Point(); + } + //Return a line: + SoVertexProperty * scatVtxProperty = new SoVertexProperty(); + scatVtxProperty->vertex.set1Value(0, 0.0f,-length*0.5f,0.0f); + scatVtxProperty->vertex.set1Value(1, 0.0f, length*0.5f,0.0f); + SoLineSet * line = new SoLineSet(); + line->numVertices = 2; + line->vertexProperty = scatVtxProperty; + //m_d->cachedshapes_strips[id] = line; + line->ref(); + return line; + } else { + //Return a box. + SoGenericBox::initClass(); + SoGenericBox* trd = new SoGenericBox; + m_d->sanitiseParameterValue(length); + m_d->sanitiseParameterValue(minWidth); + m_d->sanitiseParameterValue(maxWidth); + m_d->sanitiseParameterValue(depth); + trd->setParametersForTrd(0.5*minWidth,0.5*maxWidth,0.5*length,0.5*length,0.5*depth); + //m_d->cachedshapes_strips[id] = trd; + trd->drawEdgeLines = true; + trd->ref(); + return trd; + } +} +//____________________________________________________________________ +SoNode* HitsSoNodeManager::getShapeNode_Pad( double length, double minWidth, double maxWidth, double depth ) +{ + + //std::cout << "HitsSoNodeManager::getShapeNode_Pad()" << std::endl; + + m_d->sanitiseParameterValueAllowZero(length); + m_d->sanitiseParameterValueAllowZero(minWidth); + m_d->sanitiseParameterValueAllowZero(maxWidth); + m_d->sanitiseParameterValueAllowZero(depth); + + //double id(length-minWidth*9999.99-depth*999999799.0);//something unique + //std::map<double,SoNode*>::const_iterator it = m_d->cachedshapes_strips.find(id); + //if (it!=m_d->cachedshapes_strips.end()) + // return it->second; + + if (maxWidth==0.0 && depth==0) { + if (length==0.0) { + std::cout << "maxWidth==0.0 && depth==0 && lengthPad==0.0, returning a point..." << std::endl; + return getShapeNode_Point(); + } + //Return a line: + //std::cout << "maxWidth==0.0 && depth==0, returning a line..." << std::endl; + SoVertexProperty * scatVtxProperty = new SoVertexProperty(); + scatVtxProperty->vertex.set1Value(0, 0.0f,-length*0.5f,0.0f); + scatVtxProperty->vertex.set1Value(1, 0.0f, length*0.5f,0.0f); + SoLineSet * line = new SoLineSet(); + line->numVertices = 2; + line->vertexProperty = scatVtxProperty; + //m_d->cachedshapes_strips[id] = line; + line->ref(); + return line; + } else { + //std::cout << "returning a box..." << std::endl; + //Return a box. + SoGenericBox::initClass(); + SoGenericBox* trd = new SoGenericBox; + m_d->sanitiseParameterValue(length); + m_d->sanitiseParameterValue(minWidth); + m_d->sanitiseParameterValue(maxWidth); + m_d->sanitiseParameterValue(depth); + trd->setParametersForTrd(0.5*minWidth,0.5*maxWidth,0.5*length,0.5*length,0.5*depth); + //m_d->cachedshapes_strips[id] = trd; + trd->drawEdgeLines = true; + trd->ref(); + return trd; + } +} + +//____________________________________________________________________ +SoNode* HitsSoNodeManager::getShapeNode_Point() +{ + if (!m_d->cachedshape_point) { + SoPointSet * scatPointSet = new SoPointSet; + SoVertexProperty * scatVtxProperty = new SoVertexProperty; + scatVtxProperty->vertex.set1Value(0,0.0f,0.0f,0.0f); + scatPointSet->numPoints=1; + scatPointSet->vertexProperty.setValue(scatVtxProperty); + m_d->cachedshape_point = scatPointSet; + m_d->cachedshape_point->ref(); + } + return m_d->cachedshape_point; +} + +//____________________________________________________________________ +SoNode* HitsSoNodeManager::getShapeNode_Cross( double extent ) +{ + std::map<double,SoNode*>::const_iterator it = m_d->cachedshapes_cross.find(extent); + if (it!=m_d->cachedshapes_cross.end()) + return it->second; + + SoVertexProperty * vertices = new SoVertexProperty; + int iver(0); + vertices->vertex.set1Value(iver++,-extent,0.0,0.0); + vertices->vertex.set1Value(iver++,+extent,0.0,0.0); + vertices->vertex.set1Value(iver++,0.0,-extent,0.0); + vertices->vertex.set1Value(iver++,0.0,+extent,0.0); + vertices->vertex.set1Value(iver++,0.0,0.0,-extent); + vertices->vertex.set1Value(iver++,0.0,0.0,+extent); + + SoLineSet * cross = new SoLineSet; + cross->vertexProperty = vertices; + int numlines(0); + cross->numVertices.set1Value(numlines++,2); + cross->numVertices.set1Value(numlines++,2); + cross->numVertices.set1Value(numlines++,2); + + m_d->cachedshapes_cross[extent] = cross; + m_d->cachedshapes_cross[extent]->ref(); + + return m_d->cachedshapes_cross[extent]; +} + +//____________________________________________________________________ +SoTransform * HitsSoNodeManager::getUnitTransform() +{ + if (!m_d->cached_unittransform) { + m_d->cached_unittransform = new SoTransform; + m_d->cached_unittransform->ref(); + } + return m_d->cached_unittransform; +} diff --git a/graphics/VTI12/VTI12Utils/src/InDetProjFlags.cxx b/graphics/VTI12/VTI12Utils/src/InDetProjFlags.cxx new file mode 100644 index 000000000..a54e80d1f --- /dev/null +++ b/graphics/VTI12/VTI12Utils/src/InDetProjFlags.cxx @@ -0,0 +1,86 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class InDetProjFlags // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: February 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12Utils/InDetProjFlags.h" + +void InDetProjFlags::projectionPartsGivenUsedDetectors( InDetProjPartsFlags& proj_pixel, + InDetProjPartsFlags& proj_sct, + InDetProjPartsFlags& proj_trt, + const DetTypeFlags& useddets ) +{ + InDetProjPartsFlags not_allbarrel = ~(BarrelPositive|BarrelNegative|BarrelCentral); + InDetProjPartsFlags not_allendcap = ~(EndCapOuterPositive|EndCapOuterNegative + |EndCapInnerPositive|EndCapInnerNegative + |TRT_EndCapZToRPositive|TRT_EndCapZToRNegative + |TRT_EndCapZToRCentral); + InDetProjPartsFlags not_allendcappos = ~(EndCapOuterPositive|EndCapInnerPositive|TRT_EndCapZToRPositive); + InDetProjPartsFlags not_allendcapneg = ~(EndCapOuterNegative|EndCapInnerNegative|TRT_EndCapZToRNegative); + + if (proj_pixel!=NoProjections) { + if (useddets&Pixel_all) { + if (!(useddets&(Pixel_brlpos|Pixel_brlneg))) { + proj_pixel &= not_allbarrel;//No pixel barrel at all: + } else { + if (!(useddets&Pixel_brlpos)) proj_pixel &= ~BarrelPositive;//No pixel pos barrel + if (!(useddets&Pixel_brlneg)) proj_pixel &= ~BarrelNegative;//No pixel neg barrel + } + if (!(useddets&(Pixel_ecpos|Pixel_ecneg))) { + proj_pixel &= not_allendcap;//No pixel endcaps at all. + } else { + if (!(useddets&Pixel_ecpos)) proj_pixel &= not_allendcappos;//No pixel pos endcap + if (!(useddets&Pixel_ecneg)) proj_pixel &= not_allendcapneg;//No pixel neg endcap + } + } else { + proj_pixel = NoProjections; + } + } + + if (proj_sct!=NoProjections) { + if (useddets&SCT_all) { + if (!(useddets&(SCT_brlpos|SCT_brlneg))) { + proj_sct &= not_allbarrel;//No sct barrel at all: + } else { + if (!(useddets&SCT_brlpos)) proj_sct &= ~BarrelPositive;//No sct pos barrel + if (!(useddets&SCT_brlneg)) proj_sct &= ~BarrelNegative;//No sct neg barrel + } + if (!(useddets&(SCT_ecpos|SCT_ecneg))) { + proj_sct &= not_allendcap;//No sct endcaps at all. + } else { + if (!(useddets&SCT_ecpos)) proj_sct &= not_allendcappos;//No sct pos endcap + if (!(useddets&SCT_ecneg)) proj_sct &= not_allendcapneg;//No sct neg endcap + } + } else { + proj_sct = NoProjections; + } + } + + if (proj_trt!=NoProjections) { + if (useddets&TRT_all) { + if (!(useddets&(TRT_brlpos|TRT_brlneg))) { + proj_trt &= not_allbarrel;//No trt barrel at all: + } else { + if (!(useddets&TRT_brlpos)) proj_trt &= ~BarrelPositive;//No trt pos barrel + if (!(useddets&TRT_brlneg)) proj_trt &= ~BarrelNegative;//No trt neg barrel + } + if (!(useddets&(TRT_ecpos|TRT_ecneg))) { + proj_trt &= not_allendcap;//No trt endcaps at all. + } else { + if (!(useddets&TRT_ecpos)) proj_trt &= not_allendcappos;//No trt pos endcap + if (!(useddets&TRT_ecneg)) proj_trt &= not_allendcapneg;//No trt neg endcap + } + } else { + proj_trt = NoProjections; + } + } +} diff --git a/graphics/VTI12/VTI12Utils/src/SbPolyhedrizeAction.cxx b/graphics/VTI12/VTI12Utils/src/SbPolyhedrizeAction.cxx new file mode 100644 index 000000000..b09115f05 --- /dev/null +++ b/graphics/VTI12/VTI12Utils/src/SbPolyhedrizeAction.cxx @@ -0,0 +1,289 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "GeoPrimitives/GeoPrimitives.h" +#include "GeoModelKernel/GeoShapeShift.h" +#include "GeoModelKernel/GeoShapeIntersection.h" +#include "GeoModelKernel/GeoShapeUnion.h" +#include "GeoModelKernel/GeoShapeSubtraction.h" +#include "GeoModelKernel/GeoBox.h" +#include "GeoModelKernel/GeoCons.h" +#include "GeoModelKernel/GeoPcon.h" +#include "GeoModelKernel/GeoPgon.h" +#include "GeoModelKernel/GeoTrap.h" +#include "GeoModelKernel/GeoTrd.h" +#include "GeoModelKernel/GeoTube.h" +#include "GeoModelKernel/GeoTubs.h" +#include "GeoModelKernel/GeoPara.h" +#include "GeoModelKernel/GeoSimplePolygonBrep.h" +#include "GeoModelKernel/GeoTessellatedSolid.h" +#include "GeoModelKernel/GeoFacet.h" +#include "GeoModelKernel/GeoGenericTrap.h" +#include "GeoModelKernel/GeoDefinitions.h" +#include "VTI12Utils/SbPolyhedrizeAction.h" + +#include "VP1HEPVis/SbPolyhedron.h" + +#include <map> + +SbPolyhedrizeAction::SbPolyhedrizeAction() + : m_polyhedron(NULL) +{ + setDepthLimit(0); +} + + +SbPolyhedrizeAction::~SbPolyhedrizeAction() +{ + delete m_polyhedron; +} + +void SbPolyhedrizeAction::handleShift(const GeoShapeShift *shift) +{ + shift->getOp()->exec(this); + GeoTrf::RotationMatrix3D rotation=shift->getX().rotation(); + GeoTrf::Vector3D translation = shift->getX().translation(); + + // rbianchi - 14.12.2012 +// SbVec3f trx(translation.x(),translation.y(),translation.z()); +// SbRotation rot(SbMatrix(rotation.xx(),rotation.yx(),rotation.zx(),0, +// rotation.xy(),rotation.yy(),rotation.zy(),0, +// rotation.xz(),rotation.yz(),rotation.zz(),0, +// 0,0,0,1)); + SbVec3d trx(translation.x(),translation.y(),translation.z()); + #include <VP1HEPVis/SbRotation.h> //using doubles instead of floats. + HEPVis::SbRotation rot(rotation(0,0),rotation(1,0),rotation(2,0),0, + rotation(0,1),rotation(1,1),rotation(2,1),0, + rotation(0,2),rotation(1,2),rotation(2.2),0, + 0,0,0,1); + //--- + + m_polyhedron->Transform (rot, trx); +} + +void SbPolyhedrizeAction::handleUnion(const GeoShapeUnion *unio) +{ + SbPolyhedrizeAction auxA,auxB; + unio->getOpA()->exec(&auxA); + unio->getOpB()->exec(&auxB); + m_polyhedron = new SbPolyhedron(auxA.getPolyhedron()->add(*auxB.getPolyhedron())); +} + +void SbPolyhedrizeAction::handleIntersection(const GeoShapeIntersection *isect) +{ + SbPolyhedrizeAction auxA,auxB; + isect->getOpA()->exec(&auxA); + isect->getOpB()->exec(&auxB); + m_polyhedron=new SbPolyhedron(auxA.getPolyhedron()->intersect(*auxB.getPolyhedron())); +} + +void SbPolyhedrizeAction::handleSubtraction(const GeoShapeSubtraction *subtract) +{ + SbPolyhedrizeAction auxA,auxB; + subtract->getOpA()->exec(&auxA); + subtract->getOpB()->exec(&auxB); + m_polyhedron=new SbPolyhedron(auxA.getPolyhedron()->subtract(*auxB.getPolyhedron())); +} + +void SbPolyhedrizeAction::handleBox(const GeoBox *box) +{ + m_polyhedron=new SbPolyhedronBox (box->getXHalfLength(), + box->getYHalfLength(), + box->getZHalfLength()); +} + +void SbPolyhedrizeAction::handleCons(const GeoCons *cons) +{ + m_polyhedron = new SbPolyhedronCons (cons->getRMin1(), + cons->getRMax1(), + cons->getRMin2(), + cons->getRMax2(), + cons->getDZ(), + cons->getSPhi(), + cons->getDPhi()); +} + +void SbPolyhedrizeAction::handlePara(const GeoPara *para) +{ + m_polyhedron=new SbPolyhedronPara(para->getXHalfLength(), + para->getYHalfLength(), + para->getZHalfLength(), + para->getAlpha(), + para->getTheta(), + para->getPhi()); +} + +void SbPolyhedrizeAction::handlePcon(const GeoPcon *pcon) +{ + double *z = new double[pcon->getNPlanes ()]; + double *rmn = new double[pcon->getNPlanes ()]; + double *rmx = new double[pcon->getNPlanes ()]; + + for (unsigned s = 0; s < pcon->getNPlanes (); s++) { + z[s] = pcon->getZPlane (s); + rmn[s] = pcon->getRMinPlane (s); + rmx[s] = pcon->getRMaxPlane (s); + } + m_polyhedron = new SbPolyhedronPcon (pcon->getSPhi(), pcon->getDPhi(), pcon->getNPlanes (), z, rmn, rmx); + + delete[]z; + delete[]rmn; + delete[]rmx; +} + +void SbPolyhedrizeAction::handlePgon(const GeoPgon *pgon) +{ + double *z = new double[pgon->getNPlanes ()]; + double *rmn = new double[pgon->getNPlanes ()]; + double *rmx = new double[pgon->getNPlanes ()]; + + for (unsigned s = 0; s < pgon->getNPlanes (); s++) { + z[s] = pgon->getZPlane (s); + rmn[s] = pgon->getRMinPlane (s); + rmx[s] = pgon->getRMaxPlane (s); + } + m_polyhedron = new SbPolyhedronPgon (pgon->getSPhi(), pgon->getDPhi(), pgon->getNSides(), pgon->getNPlanes (), z, rmn, rmx); + + delete[]z; + delete[]rmn; + delete[]rmx; +} + +void SbPolyhedrizeAction::handleTrap(const GeoTrap *trap) +{ + m_polyhedron = new SbPolyhedronTrap (trap->getZHalfLength(), + trap->getTheta(), + trap->getPhi(), + trap->getDydzn(), + trap->getDxdyndzn(), + trap->getDxdypdzn(), 0, + trap->getDydzp(), + trap->getDxdyndzp(), + trap->getDxdypdzp(),0); +} + +void SbPolyhedrizeAction::handleTrd(const GeoTrd *trd) +{ + m_polyhedron = new SbPolyhedronTrd2 (trd->getXHalfLength1(), + trd->getXHalfLength2(), + trd->getYHalfLength1(), + trd->getYHalfLength2(), + trd->getZHalfLength()); +} + +void SbPolyhedrizeAction::handleTube(const GeoTube *tube) +{ + m_polyhedron = new SbPolyhedronTube (tube->getRMin(),tube->getRMax(),tube->getZHalfLength()); +} + +void SbPolyhedrizeAction::handleTubs(const GeoTubs *tubs) +{ + m_polyhedron= new SbPolyhedronTubs (tubs->getRMin(), + tubs->getRMax(), + tubs->getZHalfLength(), + tubs->getSPhi(), + tubs->getDPhi()); +} + +void SbPolyhedrizeAction::handleSimplePolygonBrep(const GeoSimplePolygonBrep *brep) +{ + double dz = brep->getDZ(); + std::vector<double> x, y; + for(unsigned int i=0; i<brep->getNVertices(); i++) + { + x.push_back(brep->getXVertex(i)); + y.push_back(brep->getYVertex(i)); + } + + m_polyhedron = new SbPolyhedronPolygonXSect(x,y,dz); +} + +void SbPolyhedrizeAction::handleTessellatedSolid(const GeoTessellatedSolid *tessellated) +{ + // ______ Perform actions a la SetSolidClosed ________ + double vertTolerance = 1E-15; // kCarTolerance ?? + std::vector<GeoFacetVertex> vertexList; + std::map<GeoFacet*,std::vector<size_t> > facetVertIndInSolid; // Vacet vertex indices in the vertexList + + // Loop over facets in the solid + for(size_t facetIndInSolid = 0; facetIndInSolid<tessellated->getNumberOfFacets(); ++facetIndInSolid) { + GeoFacet* facet = tessellated->getFacet(facetIndInSolid); + + facetVertIndInSolid[facet] = std::vector<size_t>(); + std::vector<size_t>& current = facetVertIndInSolid[facet]; + if(facet->getNumberOfVertices()==3) + current.resize(3,0); + else + current.resize(4,0); + + size_t vertexListSize = vertexList.size(); + GeoFacetVertex vertex(0.,0.,0.); + + // Loop over vertices in the current facet + for(size_t vertexIndInFacet=0; vertexIndInFacet<facet->getNumberOfVertices(); ++vertexIndInFacet) { + vertex = facet->getVertex(vertexIndInFacet); + + // Check if we already have this vertex in our vertexList + bool found = false; + size_t j=0; + while(j<vertexListSize && !found) { + GeoFacetVertex vertexToCheck = vertexList[j]; + found = (vertexToCheck-vertex).mag() < vertTolerance; + if(!found) j++; + } + + if(found) { + current[vertexIndInFacet] = j; + } + else { + vertexList.push_back(vertex); + current[vertexIndInFacet] = vertexList.size()-1; + } + } + } + + // ______ Create Polyhedron itself ______ + SbPolyhedronArbitrary* polyhedron= new SbPolyhedronArbitrary(vertexList.size(),tessellated->getNumberOfFacets()); + + // add vertices from the list + for(size_t vertexInd=0; vertexInd<vertexList.size(); ++vertexInd) { + GeoFacetVertex vertex = vertexList[vertexInd]; + polyhedron->AddVertex(vertex.x(),vertex.y(),vertex.z()); + } + + // add facets + for(size_t facetIndInSolid = 0; facetIndInSolid<tessellated->getNumberOfFacets(); ++facetIndInSolid) { + GeoFacet* facet = tessellated->getFacet(facetIndInSolid); + std::vector<size_t>& current = facetVertIndInSolid[facet]; + + size_t v[4]; + for (size_t j=0; j<4; j++) + v[j] = (j<current.size() ? current[j]+1 : 0); + + polyhedron->AddFacet(v[0],v[1],v[2],v[3]); + } + + polyhedron->Finalize(); + m_polyhedron = polyhedron; +} + +void SbPolyhedrizeAction::handleGenericTrap(const GeoGenericTrap *gentrap) +{ + std::vector<std::pair<double,double> > vertices; + vertices.reserve(8); + for(size_t i=0; i<8; ++i) + vertices.push_back(std::pair<double,double>(gentrap->getVertices()[i].x(),gentrap->getVertices()[i].y())); + m_polyhedron = new SbPolyhedronGenericTrap(gentrap->getZHalfLength(),vertices); +} + +const SbPolyhedron * SbPolyhedrizeAction::getPolyhedron() const +{ + return m_polyhedron; +} + + + + + + diff --git a/graphics/VTI12/VTI12Utils/src/SoTools.cpp b/graphics/VTI12/VTI12Utils/src/SoTools.cpp new file mode 100644 index 000000000..b107908c2 --- /dev/null +++ b/graphics/VTI12/VTI12Utils/src/SoTools.cpp @@ -0,0 +1,37 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/* + * SoTools.cpp + * + * Created on: Sep 3, 2014 + * Author: Riccardo Maria BIANCHI - rbianchi@cern.ch + */ + +// local +#include "VTI12Utils/SoTools.h" + +//VP1 +#include "VP1Base/VP1Msg.h" + +//SoCoin +#include <Inventor/nodes/SoNode.h> +#include <Inventor/actions/SoWriteAction.h> + + + +/* + * Dump the content of a node to the StdOutput + */ +//____________________________________________________________________ +void SoTools::dumpNode(SoNode* node) +{ + VP1Msg::messageVerbose("SoTools::dumpNode()"); + + SoWriteAction writeAction; + + writeAction.apply(node); + + +} diff --git a/graphics/VTI12/VTI12Utils/src/SoVisualizeAction.cxx b/graphics/VTI12/VTI12Utils/src/SoVisualizeAction.cxx new file mode 100644 index 000000000..b3dc3ad94 --- /dev/null +++ b/graphics/VTI12/VTI12Utils/src/SoVisualizeAction.cxx @@ -0,0 +1,338 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "VTI12Utils/SoVisualizeAction.h" +#include "GeoModelKernel/GeoBox.h" +#include "GeoModelKernel/GeoCons.h" +#include "GeoModelKernel/GeoPcon.h" +#include "GeoModelKernel/GeoTrap.h" +#include "GeoModelKernel/GeoTrd.h" +#include "GeoModelKernel/GeoTube.h" +#include "GeoModelKernel/GeoTubs.h" +#include "GeoModelKernel/GeoSimplePolygonBrep.h" +#include "GeoModelKernel/GeoTessellatedSolid.h" +#include "GeoModelKernel/GeoFacet.h" +#include "GeoModelKernel/GeoGenericTrap.h" +#ifndef BUILDVP1LIGHT + #include "GeoSpecialShapes/LArCustomShape.h" + #include "GeoSpecialShapes/LArWheelCalculator.h" +#endif +#include "VP1HEPVis/nodes/SoTubs.h" +#include "VP1HEPVis/nodes/SoCons.h" +#include "VP1HEPVis/nodes/SoGenericBox.h" +#include "VP1HEPVis/nodes/SoPcons.h" +#include "VP1HEPVis/nodes/SoTessellated.h" +#include "VP1HEPVis/SbPolyhedron.h" +#include "VP1HEPVis/nodes/SoLAr.h" +#include "VP1HEPVis/nodes/SoPolyhedron.h" +#include "VP1HEPVis/VP1HEPVisUtils.h" +#include "VTI12Utils/SbPolyhedrizeAction.h" + +// System of units +#ifdef BUILDVP1LIGHT + #include "GeoModelKernel/Units.h" + #define SYSTEM_OF_UNITS GeoModelKernelUnits // --> 'GeoModelKernelUnits::cm' +#else + #include "GaudiKernel/SystemOfUnits.h" + #define SYSTEM_OF_UNITS Gaudi::Units // --> 'Gaudi::Units::cm' +#endif + +#include <iostream> + +SoVisualizeAction::SoVisualizeAction() + : m_shape(0) +{ + VP1HEPVisUtils::initAllCustomClasses(); + setDepthLimit(0); +} + +SoVisualizeAction::~SoVisualizeAction() +{ + // Don't delete. Let ref count take care of the memory. +} + +void SoVisualizeAction::handleShape(const GeoShape *shape) +{ + //qDebug() << "SoVisualizeAction::handleShape"; + // We don't recognize it. Try to polyhedrize it! + SbPolyhedrizeAction a; + shape->exec(&a); + const SbPolyhedron *poly =a.getPolyhedron(); + if (poly) { + SoPolyhedron *myPoly = new SoPolyhedron(poly); + m_shape=myPoly; + } + +} + +void SoVisualizeAction::handleBox(const GeoBox *box) +{ + //qDebug() << "SoVisualizeAction::handleBox"; + SoGenericBox * gb = new SoGenericBox; + gb->setParametersForBox( box->getXHalfLength(),box->getYHalfLength(),box->getZHalfLength() ); + m_shape=gb; +} + +void SoVisualizeAction::handleCons(const GeoCons *cons) +{ + //qDebug() << "SoVisualizeAction::handleCons"; + SoCons::initClass(); + SoCons *socons= new SoCons; + socons->fRmin1 =cons->getRMin1(); + socons->fRmin2 =cons->getRMin2(); + socons->fRmax1 =cons->getRMax1(); + socons->fRmax2 =cons->getRMax2(); + socons->fDz =cons->getDZ(); + socons->fSPhi =cons->getSPhi(); + socons->fDPhi =cons->getDPhi(); + + m_shape=socons; +} + +void SoVisualizeAction::handlePcon(const GeoPcon *pcon) +{ + + //qDebug() << "SoVisualizeAction::handlePcon"; + + //Set up temporary data arrays for profile: + float *z = new float[pcon->getNPlanes()]; + float *rmn= new float[pcon->getNPlanes()]; + float *rmx= new float[pcon->getNPlanes()]; + + for (unsigned s=0;s<pcon->getNPlanes();++s) { + z[s]=pcon->getZPlane(s); + rmn[s]=pcon->getRMinPlane(s); + rmx[s]=pcon->getRMaxPlane(s); + } + + SoPcons::initClass(); + SoPcons *sopcons = new SoPcons(); + sopcons->fSPhi = pcon->getSPhi(); + sopcons->fDPhi = pcon->getDPhi(); + sopcons->fRmin.setValues(0,pcon->getNPlanes(),rmn); + sopcons->fRmax.setValues(0,pcon->getNPlanes(),rmx); + sopcons->fDz.setValues (0,pcon->getNPlanes(),z); + + //Delete temporary arrays: + delete [] z; + delete [] rmn; + delete [] rmx; + + m_shape=sopcons; + +} + +void SoVisualizeAction::handleTrap(const GeoTrap *trap) +{ + //qDebug() << "SoVisualizeAction::handleTrap"; + SoGenericBox * gb = new SoGenericBox; + gb->setParametersForTrapezoid(trap->getZHalfLength(), trap->getTheta(), trap->getPhi(), + trap->getDydzn(), trap->getDxdyndzn(), trap->getDxdypdzn(), + trap->getDydzp(), trap->getDxdyndzp(), trap->getDxdypdzp(), + trap->getAngleydzn(), trap->getAngleydzp()); + m_shape=gb; +} + +void SoVisualizeAction::handleTrd(const GeoTrd *trd) +{ + //qDebug() << "SoVisualizeAction::handleTrd"; + SoGenericBox * gb = new SoGenericBox; + gb->setParametersForTrd( trd->getXHalfLength1(), trd->getXHalfLength2(), + trd->getYHalfLength1(), trd->getYHalfLength2(), + trd->getZHalfLength() ); + m_shape=gb; +} + +void SoVisualizeAction::handleTube(const GeoTube *tube) +{ + //qDebug() << "SoVisualizeAction::handleTube"; + SoTubs *sotubs= new SoTubs; + sotubs->pRMin= tube->getRMin(); + sotubs->pRMax= tube->getRMax(); + sotubs->pDz = tube->getZHalfLength(); + sotubs->pSPhi= 0; + sotubs->pDPhi= 2*M_PI; + m_shape=sotubs; +} + +void SoVisualizeAction::handleTubs(const GeoTubs *tubs) +{ + //qDebug() << "SoVisualizeAction::handleTubs"; + SoTubs *sotubs= new SoTubs; + sotubs->pRMin= tubs->getRMin(); + sotubs->pRMax= tubs->getRMax(); + sotubs->pDz = tubs->getZHalfLength(); + sotubs->pSPhi= tubs->getSPhi(); + sotubs->pDPhi= tubs->getDPhi(); + m_shape=sotubs; +} + +#ifndef BUILDVP1LIGHT +void SoVisualizeAction::handleLArCustom(const LArCustomShape *custom) +{ + //qDebug() << "SoVisualizeAction::handleLArCustom"; + static const double eta_hi = 3.2; + static const double eta_mid = 2.5; + static const double eta_low = 1.375; + + + // static const double zWheelRefPoint = 3689.5*SYSTEM_OF_UNITS::mm; //=endg_z0 + static const double dMechFocaltoWRP = 3691. *SYSTEM_OF_UNITS::mm; //=endg_z1 + // static const double dElecFocaltoWRP = 3689. *SYSTEM_OF_UNITS::mm; //=endg_dcf + static const double dWRPtoFrontFace = 11. *SYSTEM_OF_UNITS::mm; + static const double rOuterCutoff = 2034. *SYSTEM_OF_UNITS::mm; //=endg_rlimit + + + SoLAr::initClass(); + SoLAr *solar = new SoLAr(); + const LArWheelCalculator *calc = custom->calculator(); + LArG4::LArWheelCalculator_t type = calc->type(); + if (type==LArG4::InnerAbsorberWheel || + type==LArG4::InnerElectrodWheel || + type==LArG4::InnerAbsorberModule || + type==LArG4::InnerElectrodModule ) { + float zPlane[2],rInner[2],rOuter[2]; + zPlane[0]=0; + zPlane[1]=calc->GetWheelThickness(); + + double tanThetaInner = 2. * exp(-eta_hi ) / (1. - exp(2.*-eta_hi )); + double tanThetaMid = 2. * exp(-eta_mid) / (1. - exp(2.*-eta_mid)); + double zWheelFrontFace = dMechFocaltoWRP + dWRPtoFrontFace; + double zWheelBackFace = zWheelFrontFace + calc->GetWheelThickness(); + rInner[0] = zWheelFrontFace * tanThetaInner; + rInner[1] = zWheelBackFace * tanThetaInner; + // Note that there is a 3mm gap between the outer surface of the + // inner wheel and the inner surface of the outer wheel. + double HalfGapBetweenWheels = 0.15*SYSTEM_OF_UNITS::cm; // In DB EMECGEOMETRY.DCRACK + rOuter[0] = zWheelFrontFace * tanThetaMid - HalfGapBetweenWheels; + rOuter[1] = zWheelBackFace * tanThetaMid - HalfGapBetweenWheels; + solar->fRmin.setValues(0,2,rInner); + solar->fRmax.setValues(0,2,rOuter); + solar->fDz.setValues (0,2,zPlane); + } + else if (type==LArG4::OuterAbsorberWheel || + type==LArG4::OuterElectrodWheel || + type==LArG4::OuterAbsorberModule || + type==LArG4::OuterElectrodModule ) { + float zPlane[3], rInner[3], rOuter[3]; + zPlane[0] = 0; + zPlane[2] = calc->GetWheelThickness(); + double tanThetaMid = 2. * exp(-eta_mid) / (1. - exp(2.*-eta_mid)); + double tanThetaOuter = 2. * exp(-eta_low) / (1. - exp(2.*-eta_low)); + double zWheelFrontFace = dMechFocaltoWRP + dWRPtoFrontFace; + double zWheelBackFace = zWheelFrontFace + calc->GetWheelThickness(); + // Note that there is a 3mm gap between the outer surface of the + // inner wheel and the inner surface of the outer wheel. + double HalfGapBetweenWheels = 0.15*SYSTEM_OF_UNITS::cm; // In DB! (EMECGEOMETRY.DCRACK); + rInner[0] = zWheelFrontFace * tanThetaMid + HalfGapBetweenWheels; + rInner[2] = zWheelBackFace * tanThetaMid + HalfGapBetweenWheels; + rOuter[0] = zWheelFrontFace * tanThetaOuter; + rOuter[2] = zWheelBackFace * tanThetaOuter; + // If we simply left it at that, the outer wheel would protrude + // beyond the edge of the cryostat. We have to "slice off" the lip + // of the outer wheel to create a shape that's roughtly like a + // bathtub plug. + // Use the endpoints of the outer arrays to define lines in the + // (z,r) plane. + double slopeMin = (rInner[2] - rInner[0]) / (zPlane[2] - zPlane[0]); + double slopeMax = (rOuter[2] - rOuter[0]) / (zPlane[2] - zPlane[0]); + double interceptMin = rInner[0] - slopeMin * zPlane[0]; + double interceptMax = rOuter[0] - slopeMax * zPlane[0]; + // At what value of z does the outer line hit the cutoff? + zPlane[1] = (rOuterCutoff - interceptMax) / slopeMax; + // Calculate the radii at this z: + rInner[1] = slopeMin * zPlane[1] + interceptMin; + rOuter[1] = rOuterCutoff; + // Now override the radius to keep the wheel inside the cryostat: + rOuter[2] = rOuterCutoff; + solar->fRmin.setValues(0,3,rInner); + solar->fRmax.setValues(0,3,rOuter); + solar->fDz.setValues (0,3,zPlane); + } + + solar->fSPhi= 0; + solar->fDPhi= 2*M_PI; + m_shape=solar; +} +#endif + +void SoVisualizeAction::handleSimplePolygonBrep(const GeoSimplePolygonBrep *brep) +{ + //qDebug() << "SoVisualizeAction::handleSimplePolygonBrep"; + //Fixme: Detect if order of vertices is the wrong way around... and reorder if necessary. + + double dz = brep->getDZ(); + std::vector<double> x, y; + for(unsigned int i=0; i<brep->getNVertices(); ++i) + { + x.push_back(brep->getXVertex(i)); + y.push_back(brep->getYVertex(i)); + } + + SbPolyhedronPolygonXSect sbPoly(x,y,dz); + SoPolyhedron* soPoly = new SoPolyhedron(sbPoly); + m_shape = soPoly; +} + +void SoVisualizeAction::handleTessellatedSolid (const GeoTessellatedSolid* geoTessellated) +{ + //qDebug() << "SoVisualizeAction::handleTessellatedSolid"; + + SoTessellated * soTessellated = new SoTessellated; + for(size_t i=0; i<geoTessellated->getNumberOfFacets();++i) { + GeoFacet* facet = geoTessellated->getFacet(i); + if(facet->getNumberOfVertices()==3) { + if(facet->getVertexType()==GeoFacet::ABSOLUTE) + soTessellated->addTriangularFacet(facet->getVertex(0).x(),facet->getVertex(0).y(),facet->getVertex(0).z(), + facet->getVertex(1).x(),facet->getVertex(1).y(),facet->getVertex(1).z(), + facet->getVertex(2).x(),facet->getVertex(2).y(),facet->getVertex(2).z()); + else + soTessellated->addTriangularFacet(facet->getVertex(0).x(),facet->getVertex(0).y(),facet->getVertex(0).z(), + facet->getVertex(0).x()+facet->getVertex(1).x(), + facet->getVertex(0).y()+facet->getVertex(1).y(), + facet->getVertex(0).z()+facet->getVertex(1).z(), + facet->getVertex(0).x()+facet->getVertex(2).x(), + facet->getVertex(0).y()+facet->getVertex(2).y(), + facet->getVertex(0).z()+facet->getVertex(2).z()); + } + else { + if(facet->getVertexType()==GeoFacet::ABSOLUTE) + soTessellated->addQuadrangularFacet(facet->getVertex(0).x(),facet->getVertex(0).y(),facet->getVertex(0).z(), + facet->getVertex(1).x(),facet->getVertex(1).y(),facet->getVertex(1).z(), + facet->getVertex(2).x(),facet->getVertex(2).y(),facet->getVertex(2).z(), + facet->getVertex(3).x(),facet->getVertex(3).y(),facet->getVertex(3).z()); + else + soTessellated->addQuadrangularFacet(facet->getVertex(0).x(),facet->getVertex(0).y(),facet->getVertex(0).z(), + facet->getVertex(0).x()+facet->getVertex(1).x(), + facet->getVertex(0).y()+facet->getVertex(1).y(), + facet->getVertex(0).z()+facet->getVertex(1).z(), + facet->getVertex(0).x()+facet->getVertex(2).x(), + facet->getVertex(0).y()+facet->getVertex(2).y(), + facet->getVertex(0).z()+facet->getVertex(2).z(), + facet->getVertex(0).x()+facet->getVertex(3).x(), + facet->getVertex(0).y()+facet->getVertex(3).y(), + facet->getVertex(0).z()+facet->getVertex(3).z()); + + } + } + soTessellated->finalize(); + m_shape=soTessellated; +} + +void SoVisualizeAction::handleGenericTrap(const GeoGenericTrap *gentrap) +{ + //qDebug() << "SoVisualizeAction::handleGenericTrap"; + SoGenericBox * gb = new SoGenericBox; + const GeoGenericTrapVertices& trapVertices = gentrap->getVertices(); + double dZ = gentrap->getZHalfLength(); + gb->setGenericParameters(trapVertices[0].x(),trapVertices[0].y(),-dZ, + trapVertices[1].x(),trapVertices[1].y(),-dZ, + trapVertices[2].x(),trapVertices[2].y(),-dZ, + trapVertices[3].x(),trapVertices[3].y(),-dZ, + trapVertices[4].x(),trapVertices[4].y(),dZ, + trapVertices[5].x(),trapVertices[5].y(),dZ, + trapVertices[6].x(),trapVertices[6].y(),dZ, + trapVertices[7].x(),trapVertices[7].y(),dZ); + m_shape=gb; +} diff --git a/graphics/VTI12/VTI12Utils/src/SurfaceToSoNode.cxx b/graphics/VTI12/VTI12Utils/src/SurfaceToSoNode.cxx new file mode 100644 index 000000000..5f11b055b --- /dev/null +++ b/graphics/VTI12/VTI12Utils/src/SurfaceToSoNode.cxx @@ -0,0 +1,252 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////////////////// +// // +// Implementation of class SurfaceToSoNode // +// // +// Author: Andreas Salzburger <Andreas.Salzburger@cern.ch> (primary) // +// Thomas Kittelmann <Thomas.Kittelmann@cern.ch> // +// // +// Initial VP1 version: June 2007 // +// // +///////////////////////////////////////////////////////////////////////// + +#include "VTI12Utils/SurfaceToSoNode.h" +#include "VTI12Utils/VP1LinAlgUtils.h" + +#include <Inventor/C/errors/debugerror.h> +//#include <Inventor/nodes/SoNode.h> +#include <Inventor/nodes/SoSeparator.h> +#include <Inventor/nodes/SoTransform.h> +#include <Inventor/nodes/SoVertexProperty.h> +#include <Inventor/nodes/SoLineSet.h> +#include "VP1HEPVis/nodes/SoGenericBox.h" +#include "VP1HEPVis/nodes/SoTubs.h" +#include "VP1HEPVis/nodes/SoPolyhedron.h" +#include "VP1HEPVis/SbPolyhedron.h" + +#include "TrkSurfaces/Surface.h" +#include "TrkSurfaces/CylinderSurface.h" +#include "TrkSurfaces/DiscSurface.h" +#include "TrkSurfaces/PlaneSurface.h" +#include "TrkSurfaces/StraightLineSurface.h" +#include "TrkSurfaces/PerigeeSurface.h" +#include "TrkSurfaces/CylinderBounds.h" +#include "TrkSurfaces/DiscBounds.h" +#include "TrkSurfaces/RectangleBounds.h" +#include "TrkSurfaces/TrapezoidBounds.h" +#include "TrkSurfaces/AnnulusBounds.h" +#include "TrkSurfaces/RotatedTrapezoidBounds.h" +#include "TrkSurfaces/DiamondBounds.h" +#include "TrkSurfaces/NoBounds.h" + +#include "GeoModelKernel/GeoSimplePolygonBrep.h" + +double SurfaceToSoNode::surfaceThickness = 0.1; + +SurfaceToSoNode::SurfaceToSoNode() +{ + SoTubs::initClass(); + SoGenericBox::initClass(); +} + +SurfaceToSoNode::~SurfaceToSoNode(){} + +SoNode* SurfaceToSoNode::translateSurface(const Trk::Surface& sf, const bool& simple) const +{ + + SoNode* sono =0; + const Trk::CylinderSurface* ccsf = dynamic_cast<const Trk::CylinderSurface*>(&sf); + if (ccsf) sono = this->translateCylinderSurface(*ccsf); + + const Trk::DiscSurface* cdsf = sono ? 0 : dynamic_cast<const Trk::DiscSurface*>(&sf); + if (cdsf) sono = this->translateDiscSurface(*cdsf); + + const Trk::PlaneSurface* cpsf = sono ? 0 : dynamic_cast<const Trk::PlaneSurface*>(&sf); + if (cpsf) sono = this->translatePlaneSurface(*cpsf); + + const Trk::StraightLineSurface* cssf = sono ? 0 : dynamic_cast<const Trk::StraightLineSurface*>(&sf); + if (cssf) sono = this->translateStraightLineSurface(*cssf, simple); + + const Trk::PerigeeSurface* cpersf = sono ? 0 : dynamic_cast<const Trk::PerigeeSurface*>(&sf); + if (cpersf) sono = this->translatePerigeeSurface(*cpersf); + + if (!sono) { + std::cout<<"ERROR! Surface unknown!"<<std::endl; + return 0; + } + + // place and transform them + SoSeparator* sosep = new SoSeparator(); + + // Horrible hack for ITK annulus bounds. What should really happen is we draw the surface where the bounds are. But this was never done before. + Amg::Transform3D transform = sf.transform(); + if (cpsf) { + const Trk::AnnulusBounds* cannulus = dynamic_cast<const Trk::AnnulusBounds*>(&(cpsf->bounds())); + if (cannulus){ + Amg::Vector3D vec(0.0,0.5*(cannulus->maxR()+cannulus->minR()),0.0); + transform.translate(vec); + } + } + + SoTransform* sotra = VP1LinAlgUtils::toSoTransform(transform); + sosep->addChild(sotra); + sosep->addChild(sono); + + return sosep; +} + +SoNode* SurfaceToSoNode::translatePlaneSurface(const Trk::PlaneSurface& psf ) const +{ + const Trk::RectangleBounds* crecbo = dynamic_cast<const Trk::RectangleBounds*>(&(psf.bounds())); + if (crecbo){ + SoGenericBox * gb = new SoGenericBox; + gb->setParametersForBox(crecbo->halflengthPhi(),crecbo->halflengthEta(),0.5*surfaceThickness); + gb->drawEdgeLines.setValue(true); + return gb; + } + + const Trk::TrapezoidBounds* ctrabo = dynamic_cast<const Trk::TrapezoidBounds*>(&(psf.bounds())); + if (ctrabo){ + SoGenericBox * gb = new SoGenericBox; + const double hminphi = ctrabo->minHalflengthPhi(); + const double hmaxphi = ctrabo->maxHalflengthPhi(); + const double heta = ctrabo->halflengthEta(); + gb->setParametersForTrapezoid( 0.5*surfaceThickness/*dz*/, 0/*theta*/, 0/*phi*/, heta/*dy1*/, + hminphi/*dx1*/, hmaxphi/*dx2*/, heta/*dy2*/, hminphi/*dx3*/, + hmaxphi/*dx4*/, 0/*alp1*/, 0/*alp2*/ ); + gb->drawEdgeLines.setValue(true); + return gb; + } + const Trk::RotatedTrapezoidBounds* crottrabo = dynamic_cast<const Trk::RotatedTrapezoidBounds*>(&(psf.bounds())); + if (crottrabo){ + SoGenericBox * gb = new SoGenericBox; + const double hminphi = crottrabo->minHalflengthY(); + const double hmaxphi = crottrabo->maxHalflengthY(); + const double heta = crottrabo->halflengthX(); + gb->setParametersForTrapezoid( 0.5*surfaceThickness/*dz*/, 0/*theta*/, 0/*phi*/, heta/*dy1*/, + hminphi/*dx1*/, hmaxphi/*dx2*/, heta/*dy2*/, hminphi/*dx3*/, + hmaxphi/*dx4*/, 0/*alp1*/, 0/*alp2*/ ); + gb->drawEdgeLines.setValue(true); + return gb; + } + const Trk::DiamondBounds* cdiabo = dynamic_cast<const Trk::DiamondBounds*>(&(psf.bounds())); + if (cdiabo){ + double dz=0.25; + std::vector<double> x,y; + x.push_back(cdiabo->minHalflengthX());y.push_back( -2*cdiabo->halflengthY1()); + x.push_back(cdiabo->medHalflengthX());y.push_back( 0.); + if (cdiabo->halflengthY2()>0.) { + x.push_back(cdiabo->maxHalflengthX()); y.push_back( 2*cdiabo->halflengthY2()); + x.push_back(-cdiabo->maxHalflengthX());y.push_back( 2*cdiabo->halflengthY2()); + } + x.push_back(-cdiabo->medHalflengthX());y.push_back( 0.); + x.push_back(-cdiabo->minHalflengthX());y.push_back( -2*cdiabo->halflengthY1()); + + SbPolyhedronPolygonXSect sbPoly(x,y,dz); + return new SoPolyhedron(sbPoly); + } + + const Trk::AnnulusBounds* cannulus = dynamic_cast<const Trk::AnnulusBounds*>(&(psf.bounds())); + if (cannulus){ + SoGenericBox * gb = new SoGenericBox; + const double hminphi = 0.5*cannulus->minR()*cannulus->phi(); + const double hmaxphi = 0.5*cannulus->maxR()*cannulus->phi(); + const double heta = 0.5 * (cannulus->maxR() - cannulus->minR()); + gb->setParametersForTrapezoid( 0.5*surfaceThickness/*dz*/, 0/*theta*/, 0/*phi*/, heta/*dy1*/, + hminphi/*dx1*/, hmaxphi/*dx2*/, heta/*dy2*/, hminphi/*dx3*/, + hmaxphi/*dx4*/, 0/*alp1*/, 0/*alp2*/ ); + gb->drawEdgeLines.setValue(true); + return gb; + } + const Trk::NoBounds* nobo = dynamic_cast<const Trk::NoBounds*>(&(psf.bounds())); + if (nobo){ + SoGenericBox * gb = new SoGenericBox; + gb->setParametersForBox(50.0,50.0,0.5*surfaceThickness); + gb->drawEdgeLines.setValue(false); + return gb; + } + + return 0; +} + +SoNode* SurfaceToSoNode::translateCylinderSurface(const Trk::CylinderSurface& csf ) const +{ + //std::cout<<"translateCylinderSurface"<<std::endl; + + double radius = csf.bounds().r(); + double hlength = csf.bounds().halflengthZ(); + + SoTubs* cylinderSurface = new SoTubs(); + (*cylinderSurface).pRMin = radius-0.25; + (*cylinderSurface).pRMax = radius+0.25; + (*cylinderSurface).pDz = hlength; + + return cylinderSurface; + +} + +SoNode* SurfaceToSoNode::translateDiscSurface(const Trk::DiscSurface& dsf) const +{ + //std::cout<<"translateDiscSurface"<<std::endl; + const Trk::DiscBounds* cdbo = dynamic_cast<const Trk::DiscBounds*>(&(dsf.bounds())); + if (cdbo){ + double iradius = cdbo->rMin(); + double oradius = cdbo->rMax(); + double halfphisec = cdbo->halfPhiSector(); + + SoTubs* discSurface = new SoTubs(); + (*discSurface).pRMin = iradius; + (*discSurface).pRMax = oradius; + (*discSurface).pDz = 0.25; + + if (fabs(halfphisec-M_PI)>10e-5){ + // sweep back the rotation as the sweepangle starts from x-axis + (*discSurface).pSPhi = -halfphisec; + (*discSurface).pDPhi = 2.* halfphisec; + } + + return discSurface; + } + return 0; +} + +SoNode* SurfaceToSoNode::translateStraightLineSurface(const Trk::StraightLineSurface& slsf, const bool& simple ) const +{ + //std::cout<<"translateStraightLineSurface"<<std::endl; + const Trk::CylinderBounds* ccbo = dynamic_cast<const Trk::CylinderBounds*>(&(slsf.bounds())); + if (ccbo){ + double hlength = ccbo->halflengthZ(); + if ( simple ) + { + SoVertexProperty * scatVtxProperty = new SoVertexProperty(); + scatVtxProperty->vertex.set1Value(0, 0.0,0.0,-hlength); + scatVtxProperty->vertex.set1Value(1, 0.0,0.0, hlength); + SoLineSet * lineSurface = new SoLineSet(); + lineSurface->numVertices = 2; + lineSurface->vertexProperty = scatVtxProperty; + return lineSurface; + } + + double radius = ccbo->r(); + SoTubs* lineSurface = new SoTubs(); + (*lineSurface).pRMin = 0.; + (*lineSurface).pRMax = radius; + (*lineSurface).pDz = hlength; + return lineSurface; + } + return 0; +} + +SoNode* SurfaceToSoNode::translatePerigeeSurface(const Trk::PerigeeSurface& /*persf*/) const +{ + //TK: Why do we need depend on the input???? FIXME + //std::cout<<"translatePerigeeSurface"<<std::endl; + SoTubs* perigeeSurface = new SoTubs(); + (*perigeeSurface).pRMin = 0.; + (*perigeeSurface).pRMax = 5.; + (*perigeeSurface).pDz = 4000.; + return perigeeSurface; +} diff --git a/graphics/VTI12/VTI12Utils/src/VP1AvailableToolsHelper.cxx b/graphics/VTI12/VTI12Utils/src/VP1AvailableToolsHelper.cxx new file mode 100644 index 000000000..f0e0eb6a7 --- /dev/null +++ b/graphics/VTI12/VTI12Utils/src/VP1AvailableToolsHelper.cxx @@ -0,0 +1,319 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class VP1AvailableToolsHelper // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: February 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12Utils/VP1AvailableToolsHelper.h" +#include "VP1Base/IVP1System.h" +#include "VP1Base/VP1Msg.h" + +#include "GaudiKernel/IToolSvc.h" +#include <QComboBox> +#include <QTimerEvent> +#include <map> + +//____________________________________________________________________ +class VP1AvailableToolsHelper::Imp { +public: + Imp() : theclass(0), toolsvc(0), timerid(0), updateinterval(5000), silent(false) {} + VP1AvailableToolsHelper * theclass; + IToolSvc* toolsvc; + + QStringList monitoredTypes; + std::map<QString,QStringList> monitoredTypeToIgnoreList; + QStringList ignoreList(const QString& type) { + std::map<QString,QStringList>::const_iterator it = monitoredTypeToIgnoreList.find(type); + return it==monitoredTypeToIgnoreList.end() ? QStringList() : it->second; + } + void removeIgnoreList(const QString& type) { + std::map<QString,QStringList>::iterator it = monitoredTypeToIgnoreList.find(type); + if (it!=monitoredTypeToIgnoreList.end()) + monitoredTypeToIgnoreList.erase(it); + } + QStringList availableTools; + + QStringList actualCurrentlyAvailableTools(); + QList<QComboBox*> handledComboBoxes; + QList<QWidget*> handledWidgets; + + int timerid; + void killTimer() + { + if (timerid) + theclass->killTimer(timerid); + } + void restartTimer(int time) + { + killTimer(); + timerid = theclass->startTimer(time); + } + const int updateinterval; + bool silent; +}; + + +//____________________________________________________________________ +VP1AvailableToolsHelper::VP1AvailableToolsHelper(IToolSvc* ts, QObject * parent) + : QObject(parent), VP1HelperClassBase(0,"VP1AvailableToolsHelper"), m_d(new Imp) +{ + m_d->theclass = this; + m_d->toolsvc = ts; + if (!m_d->toolsvc) + message("ERROR - received NULL ToolSvc Pointer"); + + //Should go away in future gaudi versions: + m_d->restartTimer(0); +} + +//____________________________________________________________________ +VP1AvailableToolsHelper::VP1AvailableToolsHelper(IVP1System* sys, QObject * parent) + : QObject(parent), VP1HelperClassBase(sys,"VP1AvailableToolsHelper"), m_d(new Imp) +{ + m_d->theclass = this; + m_d->toolsvc = sys ? sys->toolSvc() : 0; + if (!sys) + message("ERROR - received NULL system Pointer"); + if (!m_d->toolsvc) + message("ERROR - could not get ToolSvc Pointer"); +} + +//____________________________________________________________________ +VP1AvailableToolsHelper::~VP1AvailableToolsHelper() +{ + delete m_d; +} + +//____________________________________________________________________ +void VP1AvailableToolsHelper::scheduleImmediateUpdate() const +{ + m_d->restartTimer(0); +} + +//____________________________________________________________________ +void VP1AvailableToolsHelper::addMonitoredType(const QString& mt, const QStringList& ignoreList) +{ + m_d->monitoredTypeToIgnoreList[mt] = ignoreList; + if (!m_d->monitoredTypes.contains(mt)) { + m_d->monitoredTypes << mt; + scheduleImmediateUpdate(); + } +} + +//____________________________________________________________________ +void VP1AvailableToolsHelper::addMonitoredTypes(const QStringList& mts, const QStringList& ignoreList) +{ + bool added(false); + foreach (QString mt, mts) { + m_d->monitoredTypeToIgnoreList[mt] = ignoreList; + if (!m_d->monitoredTypes.contains(mt)) { + m_d->monitoredTypes << mt; + added=true; + } + } + if (added) + scheduleImmediateUpdate(); +} + +//____________________________________________________________________ +void VP1AvailableToolsHelper::removeMonitoredType(const QString& mt) +{ + if (m_d->monitoredTypes.contains(mt)) { + m_d->monitoredTypes.removeAll(mt); + m_d->removeIgnoreList(mt); + scheduleImmediateUpdate(); + } +} + +//____________________________________________________________________ +void VP1AvailableToolsHelper::removeMonitoredTypes(const QStringList& mts) +{ + bool removed(false); + foreach (QString mt, mts) { + if (m_d->monitoredTypes.contains(mt)) { + m_d->monitoredTypes.removeAll(mt); + m_d->removeIgnoreList(mt); + removed = true; + } + } + if (removed) + scheduleImmediateUpdate(); +} + +//____________________________________________________________________ +void VP1AvailableToolsHelper::clearMonitoredTypes(const QString&) +{ + if (m_d->monitoredTypes.count()>0) { + m_d->monitoredTypes.clear(); + m_d->monitoredTypeToIgnoreList.clear(); + scheduleImmediateUpdate(); + } +} + +//____________________________________________________________________ +QStringList VP1AvailableToolsHelper::monitoredTypes() const +{ + return m_d->monitoredTypes; +} + +//____________________________________________________________________ +QStringList VP1AvailableToolsHelper::Imp::actualCurrentlyAvailableTools() +{ + QStringList l; + if (toolsvc) { + foreach ( QString tooltype, monitoredTypes ) { + std::vector<std::string> instances; + instances = toolsvc->getInstances( tooltype.toStdString() ); + if (!silent&&VP1Msg::verbose()) + theclass->messageVerbose("Used toolsvc->getInstances(..) to find "+QString::number(instances.size())+" public tools of type "+tooltype ); + for (unsigned i = 0; i < instances.size(); ++i ) { + QString instance(instances.at(i).c_str()); + if (instance.startsWith("ToolSvc.",Qt::CaseInsensitive)) + instance.remove(0,8); + //Check if we ignore this one: + QStringList ignorelist = ignoreList(tooltype); + if (!ignorelist.isEmpty()) { + bool ignore(false); + foreach (QString ignorepattern, ignorelist) { + if (QRegExp(ignorepattern,Qt::CaseSensitive,QRegExp::Wildcard).exactMatch(instance)) { + ignore = true; + break; + } + } + if (ignore) { + if (!silent&&VP1Msg::verbose()) + theclass->messageVerbose(" --> Found but ignoring "+instance ); + continue; + } + } + if (!silent&&VP1Msg::verbose()) + theclass->messageVerbose(" --> Found "+instance ); + l << tooltype+"/"+instance; + if (!silent&&VP1Msg::verbose()) + theclass->messageVerbose(" --> Appended "+tooltype+"/"+instance+" to list" ); + } + } + l.sort(); + } + return l; +} + +//____________________________________________________________________ +void VP1AvailableToolsHelper::update() const +{ + QStringList newtools = m_d->actualCurrentlyAvailableTools(); + if ( newtools == m_d->availableTools ) { + m_d->restartTimer(2000); + return; + } + messageVerbose("update() found changes in tool list!"); + m_d->availableTools = newtools; + bool notempty = ! m_d->availableTools.empty(); + + if (notempty) { + foreach (QComboBox* cb, m_d->handledComboBoxes) { + cb->clear(); + cb->addItems(m_d->availableTools); + } + } + foreach (QWidget* w, m_d->handledWidgets) { + if (w->isEnabled() != notempty) + w->setEnabled(notempty); + } + + messageDebug("Emitting availableToolsChanged (ntools="+QString::number(m_d->availableTools.count())+")"); + availableToolsChanged(m_d->availableTools); + + m_d->restartTimer(2000); +} + +//____________________________________________________________________ +QStringList VP1AvailableToolsHelper::availableTools() const +{ + update(); + return m_d->availableTools; +} + +//____________________________________________________________________ +void VP1AvailableToolsHelper::setComboBoxData(QComboBox* cb) +{ + messageVerbose("setComboBoxData"); + if (!cb) { + message("setComboBoxData ERROR: Null pointer to combobox"); + return; + } + cb->clear(); + cb->addItems(availableTools()); +} + +//____________________________________________________________________ +void VP1AvailableToolsHelper::disableIfNoTools(QWidget* w) +{ + messageVerbose("disableIfNoTools"); + if (!w) { + message("disableIfNoTools ERROR: Null pointer to widget"); + return; + } + w->setEnabled(!availableTools().isEmpty()); +} + +//____________________________________________________________________ +void VP1AvailableToolsHelper::handleComboBox(QComboBox*cb) +{ + messageVerbose("handleComboBox"); + if (!cb) { + message("handleComboBox ERROR: Null pointer to combobox"); + return; + } + if (!m_d->handledComboBoxes.contains(cb)) { + setComboBoxData(cb); + m_d->handledComboBoxes << cb; + connect(cb,SIGNAL(destroyed(QObject*)),this,SLOT(widgetDeleted(QObject*))); + } +} + +//____________________________________________________________________ +void VP1AvailableToolsHelper::handleEnabledState(QWidget*w) +{ + messageVerbose("handleEnabledState"); + if (!w) { + message("handleEnabledState ERROR: Null pointer to widget"); + return; + } + if (!m_d->handledWidgets.contains(w)) { + disableIfNoTools(w); + m_d->handledWidgets << w; + connect(w,SIGNAL(destroyed(QObject*)),this,SLOT(widgetDeleted(QObject*))); + } +} + +//____________________________________________________________________ +void VP1AvailableToolsHelper::widgetDeleted(QObject* o) +{ + if ( o->inherits("QComboBox") && m_d->handledComboBoxes.contains(static_cast<QComboBox*>(o))) + m_d->handledComboBoxes.removeAll(static_cast<QComboBox*>(o)); + if ( o->isWidgetType() && m_d->handledWidgets.contains(static_cast<QWidget*>(o))) + m_d->handledWidgets.removeAll(static_cast<QWidget*>(o)); +} + +//____________________________________________________________________ +void VP1AvailableToolsHelper::timerEvent ( QTimerEvent * event ) +{ + event->accept(); + if (event->timerId()!=m_d->timerid) { + message("ERROR: Bad timer ID!!"); + killTimer(event->timerId()); + } + m_d->silent = true; + update(); + m_d->silent = false; + m_d->restartTimer(3000); +} diff --git a/graphics/VTI12/VTI12Utils/src/VP1DetInfo.cxx b/graphics/VTI12/VTI12Utils/src/VP1DetInfo.cxx new file mode 100644 index 000000000..de53862af --- /dev/null +++ b/graphics/VTI12/VTI12Utils/src/VP1DetInfo.cxx @@ -0,0 +1,174 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class VP1DetInfo // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: March 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12Utils/VP1DetInfo.h" +#include "VTI12Utils/VP1JobConfigInfo.h" +#include "VTI12Utils/VP1SGAccessHelper.h" +#include "VTI12Utils/VP1SGContentsHelper.h" +#include "VP1Base/VP1Msg.h" +#include "VP1Base/IVP1System.h" +#include "VP1Base/VP1AthenaPtrs.h" + +#include "GeoModelKernel/GeoPVConstLink.h" + +#include "ScintReadoutGeometry/VetoDetectorManager.h" + +// #include "InDetReadoutGeometry/TRT_DetectorManager.h" +// #include "InDetReadoutGeometry/PixelDetectorManager.h" +// #include "InDetReadoutGeometry/SCT_DetectorManager.h" + +#include "FaserDetDescr/FaserDetectorID.h" + +#include "ScintIdentifier/VetoID.h" + +// #include "InDetIdentifier/PixelID.h" +// #include "InDetIdentifier/SCT_ID.h" +// #include "InDetIdentifier/TRT_ID.h" + +#include "Identifier/Identifier.h" + +//____________________________________________________________________ +class VP1DetInfo::Imp { +public: + template <class T> + static const T * cachedRetrieve(const T*& cachedPtr, const char* key, const bool& configallows ); + + static bool m_initialised; + static const char m_badInitFlag;//Address of this means bad initialisation. + + static const ScintDD::VetoDetectorManager * m_vetoDetMgr; + static const ScintDD::TriggerDetectorManager * m_triggerDetMgr; + static const ScintDD::PreshowerDetectorManager * m_preshowerDetMgr; + + // static const InDetDD::PixelDetectorManager * m_pixelDetMgr; + // static const InDetDD::SCT_DetectorManager * m_sctDetMgr; + // static const InDetDD::TRT_DetectorManager * m_trtDetMgr; + + static const FaserDetectorID * m_faserIDHelper; + + static const VetoID * m_vetoIDHelper; + static const TriggerID * m_triggerIDHelper; + static const PreshowerID * m_preshowerIDHelper; + + // static const PixelID * m_pixelIDHelper; + // static const SCT_ID * m_sctIDHelper; + // static const TRT_ID * m_trtIDHelper; +}; + +bool VP1DetInfo::Imp::m_initialised = false; +const char VP1DetInfo::Imp::m_badInitFlag = ' '; + +const ScintDD::VetoDetectorManager * VP1DetInfo::Imp::m_vetoDetMgr = 0; +const ScintDD::TriggerDetectorManager * VP1DetInfo::Imp::m_triggerDetMgr = 0; +const ScintDD::PreshowerDetectorManager * VP1DetInfo::Imp::m_preshowerDetMgr = 0; + +// const InDetDD::PixelDetectorManager * VP1DetInfo::Imp::m_pixelDetMgr = 0; +// const InDetDD::SCT_DetectorManager * VP1DetInfo::Imp::m_sctDetMgr = 0; +// const InDetDD::TRT_DetectorManager * VP1DetInfo::Imp::m_trtDetMgr = 0; + +const FaserDetectorID * VP1DetInfo::Imp::m_faserIDHelper = 0; + +const VetoID * VP1DetInfo::Imp::m_vetoIDHelper = 0; +const TriggerID * VP1DetInfo::Imp::m_triggerIDHelper = 0; +const PreshowerID * VP1DetInfo::Imp::m_preshowerIDHelper = 0; + +// const PixelID * VP1DetInfo::Imp::m_pixelIDHelper = 0; +// const SCT_ID * VP1DetInfo::Imp::m_sctIDHelper = 0; +// const TRT_ID * VP1DetInfo::Imp::m_trtIDHelper = 0; + +//____________________________________________________________________ +template <class T> +const T * VP1DetInfo::Imp::cachedRetrieve(const T*& cachedPtr, const char* preferredKey, const bool& configallows ) { + const T * bad = static_cast<const T*>(static_cast<const void*>(&m_badInitFlag)); + if (cachedPtr) + return ( cachedPtr==bad? 0 : cachedPtr ); + QString key(preferredKey); + if (!configallows) { + VP1Msg::messageDebug("VTI12DetInfo WARNING: Will not attempt to get (type="+QString(typeid(T).name())+", key="+key+") due to missing/disabled features in job!"); + cachedPtr = bad; + return 0; + } + if (!VP1SGContentsHelper(VP1AthenaPtrs::detectorStore()).contains<T>(key)) { + //Try to gracefully guess at a different key: + QStringList keys = VP1SGContentsHelper(VP1AthenaPtrs::detectorStore()).getKeys<T>(); + if (keys.empty()) { + VP1Msg::messageDebug("VTI12DetInfo WARNING: Could not find (type="+QString(typeid(T).name())+") in detector store (expected key="+key+")"); + cachedPtr = bad; + return 0; + } + if (keys.count()>1) { + VP1Msg::messageDebug("VTI12DetInfo WARNING: Could not find (type="+QString(typeid(T).name())+", key="+key+") in detector store, and could not uniquely guess at alternate key."); + cachedPtr = bad; + return 0; + } + VP1Msg::messageDebug("VTI12DetInfo WARNING: Could not find (type="+QString(typeid(T).name())+", key="+key+") in detector store. Trying with key="+keys.first()+")"); + key = keys.first(); + } + if (!VP1SGAccessHelper(VP1AthenaPtrs::detectorStore()).retrieve(cachedPtr,key)||!cachedPtr) { + VP1Msg::messageDebug("VTI12DetInfo WARNING: Could not retrieve (type="+QString(typeid(T).name())+", key="+key+") from detector store!"); + cachedPtr = bad; + return 0; + } + VP1Msg::messageVerbose("VTI12DetInfo Succesfully retrieved (type="+QString(typeid(T).name())+", key="+key+") from detector store!"); + return cachedPtr; + +} + +const ScintDD::VetoDetectorManager * VP1DetInfo::vetoDetMgr() { return Imp::cachedRetrieve(Imp::m_vetoDetMgr,"Veto",VP1JobConfigInfo::hasVetoGeometry()); } +const ScintDD::TriggerDetectorManager * VP1DetInfo::triggerDetMgr() { return nullptr; } +const ScintDD::PreshowerDetectorManager * VP1DetInfo::preshowerDetMgr() {return nullptr; } +// const ScintDD::TriggerDetectorManager * VP1DetInfo::triggerDetMgr() { return Imp::cachedRetrieve(Imp::m_triggerDetMgr,"Trigger",VP1JobConfigInfo::hasTriggerGeometry()); } +// const ScintDD::PreshowerDetectorManager * VP1DetInfo::preshowerDetMgr() { return Imp::cachedRetrieve(Imp::m_preshowerDetMgr,"Preshower",VP1JobConfigInfo::hasPreshowerGeometry()); } + +// const InDetDD::PixelDetectorManager * VP1DetInfo::pixelDetMgr() { return Imp::cachedRetrieve(Imp::m_pixelDetMgr,"Pixel",VP1JobConfigInfo::hasPixelGeometry()); } +// const InDetDD::SCT_DetectorManager * VP1DetInfo::sctDetMgr() { return Imp::cachedRetrieve(Imp::m_sctDetMgr,"SCT",VP1JobConfigInfo::hasSCTGeometry()); } +// const InDetDD::TRT_DetectorManager * VP1DetInfo::trtDetMgr() { return Imp::cachedRetrieve(Imp::m_trtDetMgr,"TRT",VP1JobConfigInfo::hasTRTGeometry()); } + +const FaserDetectorID * VP1DetInfo::faserIDHelper() { return Imp::cachedRetrieve(Imp::m_faserIDHelper,"FaserID",true); } + +const VetoID * VP1DetInfo::vetoIDHelper() { return Imp::cachedRetrieve(Imp::m_vetoIDHelper,"VetoID",VP1JobConfigInfo::hasVetoGeometry()); } +const TriggerID * VP1DetInfo::triggerIDHelper() { return nullptr; } +const PreshowerID * VP1DetInfo::preshowerIDHelper() { return nullptr; } +// const TriggerID * VP1DetInfo::triggerIDHelper() { return Imp::cachedRetrieve(Imp::m_triggerIDHelper,"TriggerID",VP1JobConfigInfo::hasTriggerGeometry()); } +// const PreshowerID * VP1DetInfo::preshowerIDHelper() { return Imp::cachedRetrieve(Imp::m_preshowerIDHelper,"PreshowerID",VP1JobConfigInfo::hasPreshowerGeometry()); } + +// const PixelID * VP1DetInfo::pixelIDHelper() { return Imp::cachedRetrieve(Imp::m_pixelIDHelper,"PixelID",VP1JobConfigInfo::hasPixelGeometry()); } +// const SCT_ID * VP1DetInfo::sctIDHelper() { return Imp::cachedRetrieve(Imp::m_sctIDHelper,"SCT_ID",VP1JobConfigInfo::hasSCTGeometry()); } +// const TRT_ID * VP1DetInfo::trtIDHelper() { return Imp::cachedRetrieve(Imp::m_trtIDHelper,"TRT_ID",VP1JobConfigInfo::hasTRTGeometry()); } + +//____________________________________________________________________ +bool VP1DetInfo::isUnsafe( const Identifier& id ) { + + const FaserDetectorID * idhelper = faserIDHelper(); + if ( !idhelper || !id.is_valid() ) + return true; + + if (idhelper->is_scint(id)) { + if (!VP1JobConfigInfo::hasVetoGeometry() && idhelper->is_veto(id)) + return true; + if (!VP1JobConfigInfo::hasTriggerGeometry() && idhelper->is_trigger(id)) + return true; + if (!VP1JobConfigInfo::hasPreshowerGeometry() && idhelper->is_preshower(id)) + return true; + } + + // if (idhelper->is_indet(id)) { + // if (!VP1JobConfigInfo::hasTRTGeometry() && idhelper->is_trt(id)) + // return true; + // if (!VP1JobConfigInfo::hasPixelGeometry() && idhelper->is_pixel(id)) + // return true; + // if (!VP1JobConfigInfo::hasSCTGeometry() && idhelper->is_sct(id)) + // return true; + return false; +} diff --git a/graphics/VTI12/VTI12Utils/src/VP1ErrorUtils.cxx b/graphics/VTI12/VTI12Utils/src/VP1ErrorUtils.cxx new file mode 100644 index 000000000..9dfb4f1fa --- /dev/null +++ b/graphics/VTI12/VTI12Utils/src/VP1ErrorUtils.cxx @@ -0,0 +1,402 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Header file for class VP1ErrorUtils // +// // +// Description: Utilities for drawing errors for various // +// measurements // +// // +// Author: Troels Kofoed Jacobsen // +// Initial version: July 2008 // +// // +// Update: Riccardo Maria BIANCHI Feb 2014 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12Utils/VP1ErrorUtils.h" +#include "VP1Base/VP1Msg.h" +#include "VP1HEPVis/nodes/SoTransparency.h" +#include "VTI12Utils/VP1LinAlgUtils.h" +#include "VP1Base/VP1QtInventorUtils.h" +#include "VTI12Utils/SurfaceToSoNode.h" +#include "VTI12Utils/HitsSoNodeManager.h" + +#include <Inventor/nodes/SoSeparator.h> +#include <Inventor/nodes/SoTranslation.h> +#include <Inventor/nodes/SoRotationXYZ.h> +#include <Inventor/nodes/SoTransform.h> +#include <Inventor/nodes/SoLineSet.h> +#include <Inventor/nodes/SoVertexProperty.h> +#include <Inventor/nodes/SoCylinder.h> +#include <Inventor/nodes/SoComplexity.h> +#include <Inventor/nodes/SoVertexProperty.h> +#include <Inventor/nodes/SoLineSet.h> +#include <Inventor/nodes/SoDrawStyle.h> +#include "VP1HEPVis/nodes/SoGenericBox.h" + +//#include "TrkParameters/AtaStraightLine.h" +//#include "TrkParameters/Perigee.h" + +#include "TrkSurfaces/Surface.h" +#include "TrkSurfaces/RectangleBounds.h" + +#include <cmath> + +#include <Eigen/Eigenvalues> + + +typedef AmgSymMatrix(2) AmgCovMatrix; + + + + +//____________________________________________________________________ +void VP1ErrorUtils::addRotatedErrorEllipse( SoGroup* gr, + const AmgSymMatrix(5)& covmat, + const double& sigmaScale, + int numNodes, + const double& translate, + const bool& symmetric) +{ + VP1Msg::messageVerbose("VP1ErrorUtils::addRotatedErrorEllipse()"); + + if (!covMatrixIsSane(covmat)) { + VP1Msg::message("WARNING in VP1ErrorUtils: covariance matrix isn't sane (i.e. contains NaNs)"); + return; + } + if (sigmaScale!=sigmaScale) VP1Msg::message("WARNING in VP1ErrorUtils: sigmaScale nan"); + if (translate!=translate) VP1Msg::message("WARNING in VP1ErrorUtils: translate nan"); + + // Eigenvalues of covariance matrix (symmetric) + Eigen::SelfAdjointEigenSolver<AmgSymMatrix(5)> eigensolver(covmat); + if (eigensolver.info() != Eigen::Success) { + VP1Msg::message("ERROR! problems with the 'eigensolver'!"); + abort(); + } + double v0 = eigensolver.eigenvalues()[0]; + double v1 = eigensolver.eigenvalues()[1]; + + + if ( (v0-v1)<0.000005 ) { + VP1Msg::message("WARNING in VP1ErrorUtils: v0 or v1 is zero. Not drawing RotatedErrorEllipse"); + return; + } + if (v0!=v0) VP1Msg::message("WARNING in VP1ErrorUtils: v0 nan"); + if (v1!=v1) VP1Msg::message("WARNING in VP1ErrorUtils: v1 nan"); + + // Rotation of error ellipse + if (covmat(0,1) != covmat(0,1)) VP1Msg::message("WARNING in VP1ErrorUtils: covmat(0,1) nan"); + + double theta=0.5*asin(2 * covmat(0,1) / (v0-v1)); + if (theta!=theta) { + VP1Msg::message("WARNING in VP1ErrorUtils: theta NaN. Setting to zero. v0,v1="+QString::number(v0)+","+QString::number(v1)); + theta=0.0; + } + SoNode * ellipse = VP1QtInventorUtils::createEllipse( sigmaScale * sqrt(v0) , + sigmaScale * sqrt(v1) , + numNodes); + + SoRotationXYZ * r1 = new SoRotationXYZ; + r1->axis = SoRotationXYZ::Z; + r1->angle = theta; + gr->addChild( r1 ); + + if (translate != 0.0) + { + SoTranslation * t0 = new SoTranslation; + t0->translation.setValue(0.0,0.0, translate ); + gr->addChild( t0 ); + if (symmetric) + { + gr->addChild( ellipse ); + SoTranslation * t1 = new SoTranslation; + t1->translation.setValue(0.0,0.0, -2*translate ); + gr->addChild( t1 ); + } + } + + gr->addChild( ellipse ); + return; +} + +void VP1ErrorUtils::addSimple1DError( SoGroup* gr, + const double& error, + const double& sigmaScale, + const double& length) +{ + + VP1Msg::messageVerbose("VP1ErrorUtils::addSimple1DError()"); + //Return a box. + // SoGenericBox::initClass(); + // SoGenericBox* cube = new SoGenericBox; + // cube->setParametersForBox(0.5*std::fabs(error*sigmaScale),0.5*std::fabs(length),0.4); + // cube->drawEdgeLines = true; + // gr->addChild( cube ); + + SoVertexProperty * vertices = new SoVertexProperty; + int iver(0); + float xpos=0.5*std::fabs(error*sigmaScale); + float ypos=0.5*std::fabs(length); + + vertices->vertex.set1Value(iver++,-xpos,-ypos,0.0); + vertices->vertex.set1Value(iver++,-xpos,+ypos,0.0); + vertices->vertex.set1Value(iver++,+xpos,-ypos,0.0); + vertices->vertex.set1Value(iver++,+xpos,+ypos,0.0); + + + SoLineSet * errbars = new SoLineSet; + errbars->vertexProperty = vertices; + int numlines(0); + errbars->numVertices.set1Value(numlines++,2); + errbars->numVertices.set1Value(numlines++,2); + gr->addChild( errbars ); + + iver=0; + SoVertexProperty * vertices2 = new SoVertexProperty; + vertices2->vertex.set1Value(iver++,-xpos,0.0,0.0); + vertices2->vertex.set1Value(iver++,+xpos,0.0,0.0); + + SoLineSet * errbarConnection = new SoLineSet; + errbarConnection->vertexProperty = vertices2; + errbarConnection->numVertices.set1Value(0,2); + + SoDrawStyle *drawStyle = new SoDrawStyle; + drawStyle->style.setValue(SoDrawStyle::LINES); + drawStyle->linePattern.setValue(0xFF00); + gr->addChild(drawStyle); + gr->addChild( errbarConnection ); + + return; +} + +//____________________________________________________________________ +void VP1ErrorUtils::errorAtPlaneSurface( SoSeparator* errSimple, + SoSeparator* errDetailed, + const AmgSymMatrix(5)& tmpcovmat, + const Trk::Surface* theSurface, + const Amg::Vector3D& p1, + const double& sigmaScale, + int numNodes, + const bool& moveToSurface, + const bool& force1D, + const bool& addTransform) +{ + VP1Msg::messageVerbose("VP1ErrorUtils::errorAtPlaneSurface()"); + + if (!covMatrixIsSane(tmpcovmat)) { + VP1Msg::message("WARNING in VP1ErrorUtils: covariance matrix isn't sane (i.e. contains NaNs)"); + std::cout<<tmpcovmat<<std::endl; + return; + } + // const Trk::CovarianceMatrix& tmpcovmat = meas->localErrorMatrix().covariance(); + SoSeparator * ellipseGrp = new SoSeparator; + + // Translation used to put the ellipse above the surface + //SoTranslation * t0 = new SoTranslation; + //t0->translation.setValue(0.0,0.0, SurfaceToSoNode::surfaceThickness / 2.0 + 0.001 ); + //ellipseGrp->addChild( t0 ); + + + if (force1D){ + float length=50.0; + // const Trk::RectangleBounds* rBounds = dynamic_cast<const Trk::RectangleBounds*>(&(theSurface->bounds())); + // if (rBounds) length=rBounds->halflengthY ()*2.0; + // FIXME = add more bounds. + addSimple1DError(ellipseGrp, tmpcovmat(0,0), sigmaScale, length ); + } else { + if (moveToSurface) + { + addRotatedErrorEllipse(ellipseGrp, tmpcovmat, sigmaScale,numNodes, SurfaceToSoNode::surfaceThickness / 2.0 + 0.001, true); + } else{ + addRotatedErrorEllipse(ellipseGrp, tmpcovmat, sigmaScale,numNodes, 0.0, false); + } + } + + if(addTransform){ + SoTransform * t1 = VP1LinAlgUtils::toSoTransform(theSurface->transform()); + t1->translation.setValue(p1.x(),p1.y(),p1.z()); + errSimple->addChild( t1 ); + errDetailed->addChild( t1 ); + } + errSimple->addChild( ellipseGrp ); + errDetailed->addChild( ellipseGrp ); + + return; +} + +//____________________________________________________________________ +void VP1ErrorUtils::errorAtStraightLineSurface( SoSeparator* errSimple, + SoSeparator* errDetailed, + const AmgSymMatrix(5)& tmpcovmat, + const Amg::Vector2D& localPos, + const Trk::Surface* theSurface, + const double& sigmaScale, + const bool& drawZErrCircles, + const bool& drawCylinder, + int numNodes, + const bool& force1D, + const bool& addTransform) +{ + VP1Msg::messageVerbose("VP1ErrorUtils::errorAtStraightLineSurface()"); + + // const Trk::CovarianceMatrix& tmpcovmat = meas->localErrorMatrix().covariance(); + + // Global transform (To surface) + if (addTransform){ + SoTransform * t1 = VP1LinAlgUtils::toSoTransform(theSurface->transform()); + errDetailed->addChild( t1 ); + errSimple->addChild( t1 ); + } + + const double sqrtv0 = sqrt( tmpcovmat(0,0) ); + double sqrtv1=0.0; + if (!force1D){ + sqrtv1 = sqrt( tmpcovmat(1,1) ); + } else { + sqrtv1=100;//FIXME! + } + // Needed to get local position + //const Trk::AtaStraightLine * atas = dynamic_cast<const Trk::AtaStraightLine *>(m_pars); + // const Trk::AtaStraightLine * atas = dynamic_cast<const Trk::AtaStraightLine *>(meas); + // const Trk::Perigee * per = dynamic_cast<const Trk::Perigee *>(meas); + // if (!per&&!atas) return; //TODO Print error. + // const Amg::Vector2D& localPos = atas?atas->localPosition():per->localPosition(); + + const double radius = fabs(localPos[Trk::locR]); + const double rp = radius + sigmaScale * sqrtv0; + const double rm = radius - sigmaScale * sqrtv0; + + // Local translation (To get the right Z position on the tube) + SoTranslation * t0 = new SoTranslation; + t0->translation.setValue(0,0,localPos[Trk::locZ]); + + // draw circles + SoSeparator * circleGrp = new SoSeparator; + circleGrp->addChild(t0); + + SoSeparator * circleGrpSimple = new SoSeparator; + circleGrpSimple->addChild(t0); + + SoVertexProperty *vertices = new SoVertexProperty(); + double zz[3]; + int Nzz; + if ( drawZErrCircles ) + { + Nzz = 3; + zz[0] = -sigmaScale * sqrtv1; + zz[1] = 0.0; + zz[2] = +sigmaScale * sqrtv1; + } else + { + Nzz = 1; + zz[0] = 0.0; + } + + double rr[2]; + int Nrr; + if ( rm > 0 ) + { + Nrr = 2; + rr[0] = rp; + rr[1] = rm; + } else + { + Nrr = 1; + rr[0] = rp; + } + + SoLineSet * circles = new SoLineSet(); + SoLineSet * circlesSimple = new SoLineSet(); + int iver(0); + int numlines(0); + int numlinesSimple(0); + for (int k = 0; k<Nrr; k++) + { + for (int j = 0; j<Nzz; j++) + { + vertices->vertex.set1Value(iver++,rr[k],0.0,zz[j]); + for (int i = 1; i < numNodes; i++) + { + vertices->vertex.set1Value(iver++, + cos(2.0*static_cast<double>(i)*M_PI/static_cast<double>(numNodes))*rr[k], + sin(2.0*static_cast<double>(i)*M_PI/static_cast<double>(numNodes))*rr[k], + zz[j]); + } + vertices->vertex.set1Value(iver++,rr[k],0.0,zz[j]); + + circles->numVertices.set1Value(numlines++,numNodes+1); + + if (k==0) + { + circlesSimple->numVertices.set1Value(numlinesSimple++,numNodes+1); + } + } + } + circles->vertexProperty = vertices; + circleGrp->addChild( circles ); + + circlesSimple->vertexProperty = vertices; + circleGrpSimple->addChild( circlesSimple ); + + errDetailed->addChild( circleGrp ); + errSimple->addChild( circleGrpSimple ); + // end of draw circles + + if (drawCylinder) // Outer cylinder + { + SoCylinder * outerCyl = new SoCylinder; + outerCyl->removePart( SoCylinder::TOP ); + outerCyl->removePart( SoCylinder::BOTTOM ); + outerCyl->radius.setValue ( rp ); + outerCyl->height.setValue ( 2.0 * sigmaScale * sqrtv1 ); + + SoSeparator * cylGrp = new SoSeparator; + cylGrp->addChild(t0); + + SoGroup * outCylGrp = new SoGroup; + SoRotationXYZ * outCylRot = new SoRotationXYZ; + outCylRot->axis = SoRotationXYZ::X; + outCylRot->angle = M_PI_2; + outCylGrp->addChild(outCylRot); + outCylGrp->addChild(outerCyl); + cylGrp->addChild(outCylGrp); + + SoTransparency::initClass(); + SoTransparency * trans = new SoTransparency; + errDetailed->addChild( trans ); + errDetailed->addChild( cylGrp ); + } + + return; +} + +bool VP1ErrorUtils::covMatrixIsSane( const AmgCovMatrix& covmat) +{ + VP1Msg::messageVerbose("VP1ErrorUtils::covMatrixIsSane(AmgCovMatrix)"); + + // if (covmat.rows() > 2) VP1Msg::message("VP1ErrorUtils::covMatrixIsSane - covariance matrix is too big (>2)"); + if (covmat.rows()!=covmat.cols()) VP1Msg::message("VP1ErrorUtils::covMatrixIsSane - covariance matrix is not symmetric"); + for ( int row = 0; row < covmat.rows();row++){ + for ( int col = 0; col < covmat.cols();col++){ + if (covmat(row,col) != covmat(row,col)) return false; //NaN + } + } + return true; +} +bool VP1ErrorUtils::covMatrixIsSane( const AmgSymMatrix(5)& covmat) +{ + VP1Msg::messageVerbose("VP1ErrorUtils::covMatrixIsSane(AmgSymMatrix(5))"); + + // if (covmat.rows() > 2) VP1Msg::message("VP1ErrorUtils::covMatrixIsSane - covariance matrix is too big (>2)"); + if (covmat.rows()!=covmat.cols()) VP1Msg::message("VP1ErrorUtils::covMatrixIsSane - covariance matrix is not symmetric"); + for ( int row = 0; row < covmat.rows();row++){ + for ( int col = 0; col < covmat.cols();col++){ + if (covmat(row,col) != covmat(row,col)) return false; //NaN + } + } + return true; +} diff --git a/graphics/VTI12/VTI12Utils/src/VP1JobConfigInfo.cxx b/graphics/VTI12/VTI12Utils/src/VP1JobConfigInfo.cxx new file mode 100644 index 000000000..6e7fe53a7 --- /dev/null +++ b/graphics/VTI12/VTI12Utils/src/VP1JobConfigInfo.cxx @@ -0,0 +1,172 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class VP1JobConfigInfo // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: March 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12Utils/VP1JobConfigInfo.h" +#include "VTI12Utils/VP1DetInfo.h" +#include "VTI12Utils/VP1SGAccessHelper.h" +#include "VTI12Utils/VP1SGContentsHelper.h" +#include "VP1Base/IVP1System.h" +#include "VP1Base/VP1Msg.h" +#include "VP1Base/VP1AthenaPtrs.h" + +#include "GeoModelKernel/GeoVolumeCursor.h" +#include "GeoModelUtilities/GeoModelExperiment.h" +#include "StoreGate/DataHandle.h" + +#include <QString> + +//____________________________________________________________________ +class VP1JobConfigInfo::Imp { +public: + static void ensureInit(); + static bool actualInit(StoreGateSvc* detStore); + static bool initialised; + + static GeoPVConstLink geoModelWorld; + static bool hasGeoModelExperiment; + static bool hasVetoGeometry; + static bool hasTriggerGeometry; + static bool hasPreshowerGeometry; + static bool hasSCTGeometry; + static bool hasEcalGeometry; + static bool hasCavernInfraGeometry; + + static void turnOffAll(); +}; + +GeoPVConstLink VP1JobConfigInfo::Imp::geoModelWorld; +// init default values +bool VP1JobConfigInfo::Imp::initialised = false; +bool VP1JobConfigInfo::Imp::hasGeoModelExperiment = false; +bool VP1JobConfigInfo::Imp::hasVetoGeometry = false; +bool VP1JobConfigInfo::Imp::hasTriggerGeometry = false; +bool VP1JobConfigInfo::Imp::hasPreshowerGeometry = false; +bool VP1JobConfigInfo::Imp::hasSCTGeometry = false; +bool VP1JobConfigInfo::Imp::hasEcalGeometry = false; +bool VP1JobConfigInfo::Imp::hasCavernInfraGeometry = false; + +//____________________________________________________________________ +void VP1JobConfigInfo::Imp::turnOffAll() +{ + hasGeoModelExperiment = false; + hasVetoGeometry = false; + hasTriggerGeometry = false; + hasPreshowerGeometry = false; + hasSCTGeometry = false; + hasEcalGeometry = false; + hasCavernInfraGeometry = false; +} + +//____________________________________________________________________ +void VP1JobConfigInfo::Imp::ensureInit() +{ + if (initialised) + return; + if (VP1Msg::verbose()) + VP1Msg::messageVerbose("VTI12JobConfigInfo initialising"); + initialised = true; + if (!actualInit(VP1AthenaPtrs::detectorStore())) { + VP1Msg::message("VTI12JobConfigInfo ERROR: Problems initialising. Detector store. " + "Will assume all subsystems are off in this job!"); + turnOffAll(); + } + if (VP1Msg::verbose()) { + VP1Msg::messageVerbose("VTI12JobConfigInfo => Found job configuration:"); + VP1Msg::messageVerbose("VTI12JobConfigInfo => hasGeoModelExperiment = "+QString(hasGeoModelExperiment?"On":"Off")); + VP1Msg::messageVerbose("VP1JobConfigInfo => hasVetoGeometry = "+QString(hasVetoGeometry?"On":"Off")); + VP1Msg::messageVerbose("VP1JobConfigInfo => hasTriggerGeometry = "+QString(hasTriggerGeometry?"On":"Off")); + VP1Msg::messageVerbose("VP1JobConfigInfo => hasPreshowerGeometry = "+QString(hasPreshowerGeometry?"On":"Off")); + + // VP1Msg::messageVerbose("VP1JobConfigInfo => hasPixelGeometry = "+QString(hasPixelGeometry?"On":"Off")); + // VP1Msg::messageVerbose("VP1JobConfigInfo => hasSCTGeometry = "+QString(hasSCTGeometry?"On":"Off")); + // VP1Msg::messageVerbose("VP1JobConfigInfo => hasTRTGeometry = "+QString(hasTRTGeometry?"On":"Off")); + } + +} + +//____________________________________________________________________ +bool VP1JobConfigInfo::hasGeoModelExperiment() { if (!Imp::initialised) Imp::ensureInit(); return Imp::hasGeoModelExperiment; } +bool VP1JobConfigInfo::hasVetoGeometry() { if (!Imp::initialised) Imp::ensureInit(); return Imp::hasVetoGeometry; } +bool VP1JobConfigInfo::hasTriggerGeometry() { if (!Imp::initialised) Imp::ensureInit(); return Imp::hasTriggerGeometry; } +bool VP1JobConfigInfo::hasPreshowerGeometry() { if (!Imp::initialised) Imp::ensureInit(); return Imp::hasPreshowerGeometry; } + +// bool VP1JobConfigInfo::hasPixelGeometry() { if (!Imp::initialised) Imp::ensureInit(); return Imp::hasPixelGeometry; } +// bool VP1JobConfigInfo::hasSCTGeometry() { if (!Imp::initialised) Imp::ensureInit(); return Imp::hasSCTGeometry; } +// bool VP1JobConfigInfo::hasTRTGeometry() { if (!Imp::initialised) Imp::ensureInit(); return Imp::hasTRTGeometry; } + +//____________________________________________________________________ +bool VP1JobConfigInfo::Imp::actualInit( StoreGateSvc* detStore ) +{ + if (!detStore) + return false; + + VP1SGContentsHelper sg_contents(detStore); + const QString geomodelkey = "FASER"; // Because it was too hard to make this configurable like the 2151516 other useless options... + if (!sg_contents.contains<GeoModelExperiment>(geomodelkey)) { + if (VP1Msg::verbose()) + VP1Msg::messageVerbose("VTI12JobConfigInfo: No GeoModelExperiment in detectorStore. Concluding all subsystems are off."); + turnOffAll(); + return true; + } + + VP1SGAccessHelper sg_access(detStore); + + const GeoModelExperiment * theExpt; + if (!sg_access.retrieve(theExpt,geomodelkey)) { + if (VP1Msg::verbose()) + VP1Msg::messageVerbose("VTI12JobConfigInfo: No GeoModelExperiment in detectorStore. Concluding all subsystems are off."); + turnOffAll(); + return true; + } + if (VP1Msg::verbose()) + VP1Msg::messageVerbose("VTI12JobConfigInfo: Retrieved GeoModelExperiment/"+geomodelkey); + + const GeoPhysVol * worldPhysVol = theExpt->getPhysVol(); + if (!worldPhysVol) { + VP1Msg::message("VTI12JobConfigInfo: ERROR: GeoModelExperiment has null physical volume."); + turnOffAll(); + return false; + } + if (VP1Msg::verbose()) + VP1Msg::messageVerbose("VTI12JobConfigInfo: Retrieved GeoModelExperiment physical volumes"); + + hasGeoModelExperiment = true; + PVConstLink world(worldPhysVol); + VP1Msg::messageDebug("VTI12JobConfigInfo: called world(worldPhysVol)"); + std::cout << "world :" << world << std::endl; + + GeoVolumeCursor av(world); + + + while (!av.atEnd()) { + std::string name = av.getName(); + if ( !hasVetoGeometry && name=="Veto") hasVetoGeometry = true; + if ( !hasTriggerGeometry && name=="Trigger") hasTriggerGeometry = true; + if ( !hasPreshowerGeometry && name=="Preshower") hasPreshowerGeometry = true; + //FIXME: Look for CavernInfra as well!!! + + av.next(); // increment volume cursor. + } + + Imp::geoModelWorld = worldPhysVol; + + return true; +} + +//____________________________________________________________________ +const GeoPVConstLink * VP1JobConfigInfo::geoModelWorld() +{ + Imp::ensureInit(); + return Imp::geoModelWorld == GeoPVConstLink() ? 0 : &Imp::geoModelWorld; +} diff --git a/graphics/VTI12/VTI12Utils/src/VP1LinAlgUtils.cxx b/graphics/VTI12/VTI12Utils/src/VP1LinAlgUtils.cxx new file mode 100644 index 000000000..6a212a2be --- /dev/null +++ b/graphics/VTI12/VTI12Utils/src/VP1LinAlgUtils.cxx @@ -0,0 +1,455 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class VP1LinAlgUtils // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: March 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12Utils/VP1LinAlgUtils.h" +#include "VP1Base/VP1Msg.h" + +#include <Inventor/C/errors/debugerror.h> +#include <Inventor/nodes/SoTransform.h> + + +#include <math.h> + + +class VP1LinAlgUtils::Imp { +public: + static double atlasR; + static bool isBad( const double& x, const QString& ctxStr, const double& limit = 1.0e20 ) + { + if (x==x && fabs(x) < limit) + return false; + if (!ctxStr.isEmpty()) + VP1Msg::messageDebug("VP1LinAlgUtils ("+ctxStr+") ERROR: Saw suspicious number "+VP1Msg::str(x)); + return true; + } +}; +double VP1LinAlgUtils::Imp::atlasR = 1.0*CLHEP::km; + +//______________________________________________________________________________________ +SoTransform * VP1LinAlgUtils::toSoTransform(const HepGeom::Transform3D & transformation, SoTransform * tin) +{ + HepGeom::Vector3D<double> translation = transformation.getTranslation(); + CLHEP::HepRotation rotation = transformation.getRotation(); + SoTransform *myTransform = tin ? tin : new SoTransform(); + myTransform->translation = SbVec3f(translation.x(), + translation.y(), + translation.z()); + myTransform->rotation = SbRotation(SbMatrix(rotation.xx(),rotation.yx(),rotation.zx(),0, + rotation.xy(),rotation.yy(),rotation.zy(),0, + rotation.xz(),rotation.yz(),rotation.zz(),0, + 0,0,0,1)); + if (VP1Msg::verbose()) { + bool inputok = isSane( transformation, "input HepGeom::Transform3D" ); + bool outputok = isSane( myTransform, "output SoTransform" ); + if (!inputok) + VP1Msg::messageVerbose("VP1LinAlgUtils::toSoTransform ERROR: Problems observed in input HepGeom::Transform3D"); + if (!outputok) + VP1Msg::messageVerbose("VP1LinAlgUtils::toSoTransform ERROR: Problems observed in output SoTransform"); + if (inputok!=outputok) + VP1Msg::messageVerbose("VP1LinAlgUtils::toSoTransform Error introduced in HepGeom::Transform3D -> SoTransform conversion!"); + } + + return myTransform; +} + +//______________________________________________________________________________________ +SoTransform * VP1LinAlgUtils::toSoTransform(const Amg::Transform3D & transformation, SoTransform * tin) +{ + Amg::Vector3D translation = transformation.translation(); + Amg::RotationMatrix3D rotation = transformation.rotation(); + + SoTransform *myTransform = tin ? tin : new SoTransform(); + myTransform->translation = SbVec3f(translation.x(), + translation.y(), + translation.z()); +// myTransform->rotation = SbRotation(SbMatrix(rotation.xx(),rotation.yx(),rotation.zx(),0, +// rotation.xy(),rotation.yy(),rotation.zy(),0, +// rotation.xz(),rotation.yz(),rotation.zz(),0, +// 0,0,0,1)); + myTransform->rotation = SbRotation(SbMatrix(rotation(0,0),rotation(1,0),rotation(2,0),0, + rotation(0,1),rotation(1,1),rotation(2,1),0, + rotation(0,2),rotation(1,2),rotation(2,2),0, + 0,0,0,1)); + + // FIXME: to be updated to Eigen + if (VP1Msg::verbose()) { + bool inputok = isSane( transformation, "input HepGeom::Transform3D" ); + bool outputok = isSane( myTransform, "output SoTransform" ); + if (!inputok) + VP1Msg::messageVerbose("VP1LinAlgUtils::toSoTransform ERROR: Problems observed in input HepGeom::Transform3D"); + if (!outputok) + VP1Msg::messageVerbose("VP1LinAlgUtils::toSoTransform ERROR: Problems observed in output SoTransform"); + if (inputok!=outputok) + VP1Msg::messageVerbose("VP1LinAlgUtils::toSoTransform Error introduced in HepGeom::Transform3D -> SoTransform conversion!"); + } + + return myTransform; +} + +//______________________________________________________________________________________ +void VP1LinAlgUtils::transformToMatrix(SoTransform * xf, SbMatrix& result) { + result.makeIdentity(); + result.setTransform(xf->translation.getValue(), xf->rotation.getValue(), + xf->scaleFactor.getValue(), xf->scaleOrientation.getValue(), xf->center.getValue()); + if (VP1Msg::verbose()) { + bool inputok = isSane( xf, "input SoTransform" ); + bool outputok = isSane( result, "output SbMatrix" ); + if (!inputok) + VP1Msg::messageVerbose("VP1LinAlgUtils::transformToMatrix(SoTransform*,..) ERROR: Problems observed in input SoTransform"); + if (!outputok) + VP1Msg::messageVerbose("VP1LinAlgUtils::transformToMatrix(SoTransform*,..) ERROR: Problems observed in output SbMatrix"); + if (inputok!=outputok) + VP1Msg::messageVerbose("VP1LinAlgUtils::transformToMatrix(SoTransform*,..) Error introduced in SoTransform -> SbMatrix conversion!"); + } +} + +//______________________________________________________________________________________ +void VP1LinAlgUtils::transformToMatrix(const HepGeom::Transform3D & heptr, SbMatrix& result) +{ + result = SbMatrix(heptr.xx(),heptr.yx(),heptr.zx(),0, + heptr.xy(),heptr.yy(),heptr.zy(),0, + heptr.xz(),heptr.yz(),heptr.zz(),0, + heptr.dx(),heptr.dy(),heptr.dz(),1); + if (VP1Msg::verbose()) { + bool inputok = isSane( heptr, "input HepGeom::Transform3D" ); + bool outputok = isSane( result, "output SbMatrix" ); + if (!inputok) + VP1Msg::messageVerbose("VP1LinAlgUtils::transformToMatrix(HepGeom::Transform3D,..) ERROR: Problems observed in input HepGeom::Transform3D"); + if (!outputok) + VP1Msg::messageVerbose("VP1LinAlgUtils::transformToMatrix(HepGeom::Transform3D,..) ERROR: Problems observed in output SbMatrix"); + if (inputok!=outputok) + VP1Msg::messageVerbose("VP1LinAlgUtils::transformToMatrix(HepGeom::Transform3D,..) Error introduced in HepGeom::Transform3D -> SbMatrix conversion!"); + } +} + +//______________________________________________________________________________________ +SoTransform * VP1LinAlgUtils::toSoTransform(const SbMatrix& matr, SoTransform * tin) +{ + SbVec3f translation, scaleFactor; + SbRotation rotation, scaleOrientation; + matr.getTransform(translation, rotation, scaleFactor, scaleOrientation, SbVec3f(0,0,0)); + SoTransform * t = tin ? tin : new SoTransform; + t->translation.setValue(translation); + t->rotation.setValue(rotation); + t->scaleFactor.setValue(scaleFactor); + t->scaleOrientation.setValue(scaleOrientation); + t->center.setValue(0,0,0); + if (VP1Msg::verbose()) { + bool inputok = isSane( matr, "input SbMatrix" ); + bool outputok = isSane( t, "output SoTransform" ); + if (!inputok) + VP1Msg::messageVerbose("VP1LinAlgUtils::toSoTransform ERROR: Problems observed in input SoTransform"); + if (!outputok) + VP1Msg::messageVerbose("VP1LinAlgUtils::toSoTransform ERROR: Problems observed in output SbMatrix"); + if (inputok!=outputok) + VP1Msg::messageVerbose("VP1LinAlgUtils::toSoTransform Error introduced in SoTransform -> SbMatrix conversion!"); + } + return t; +} + +//______________________________________________________________________________________ +void VP1LinAlgUtils::decodeTransformation( const SbMatrix& matr, + float& translation_x, float& translation_y, float& translation_z, + float& rotaxis_x, float& rotaxis_y, float& rotaxis_z, float& rotangle_radians ) +{ + SbVec3f translation, scaleFactor, rotaxis; + SbRotation rotation, scaleOrientation; + matr.getTransform (translation, rotation,scaleFactor,scaleOrientation,SbVec3f(0,0,0)); + translation.getValue(translation_x,translation_y,translation_z); + rotation.getValue(rotaxis,rotangle_radians); + rotaxis.getValue(rotaxis_x,rotaxis_y,rotaxis_z); + if (VP1Msg::verbose()) { + if (!isSane( matr, "input SbMatrix" )) + VP1Msg::messageVerbose("VP1LinAlgUtils::decodeTransformation ERROR: Problems observed in output SbMatrix"); + } +} + +#ifdef BAD +#undef BAD +#endif +#define BAD(x) { ok=false; if (!ctxStr.isEmpty()) VP1Msg::messageVerbose("VP1LinAlgUtils ("+ctxStr+") ERROR: "+QString(x)); }; + +//______________________________________________________________________________________ +bool VP1LinAlgUtils::isSane( const HepGeom::Transform3D & t, const QString& ctxStr ) +{ + + HepGeom::Vector3D<double> translation = t.getTranslation(); + CLHEP::HepRotation rotation = t.getRotation(); + CLHEP::Hep3Vector rotationAxis; + double rotationAngle; + rotation.getAngleAxis(rotationAngle,rotationAxis); + + bool ok(true); + + if (Imp::isBad(t.xx(),ctxStr)||Imp::isBad(t.xy(),ctxStr)||Imp::isBad(t.xz(),ctxStr) + ||Imp::isBad(t.yx(),ctxStr)||Imp::isBad(t.yy(),ctxStr)||Imp::isBad(t.yz(),ctxStr) + ||Imp::isBad(t.zx(),ctxStr)||Imp::isBad(t.zy(),ctxStr)||Imp::isBad(t.zz(),ctxStr) + ||Imp::isBad(t.dx(),ctxStr)||Imp::isBad(t.dy(),ctxStr)||Imp::isBad(t.dz(),ctxStr)) + BAD("Problem in raw 4x4 transformation matrix!"); + if (Imp::isBad(translation.x(),ctxStr)||Imp::isBad(translation.y(),ctxStr)||Imp::isBad(translation.z(),ctxStr)) + BAD("Problem in translation!"); + if (Imp::isBad(rotation.xx(),ctxStr)||Imp::isBad(rotation.xy(),ctxStr)||Imp::isBad(rotation.xz(),ctxStr) + ||Imp::isBad(rotation.yx(),ctxStr)||Imp::isBad(rotation.yy(),ctxStr)||Imp::isBad(rotation.yz(),ctxStr) + ||Imp::isBad(rotation.zx(),ctxStr)||Imp::isBad(rotation.zy(),ctxStr)||Imp::isBad(rotation.zz(),ctxStr)) + BAD("Problem in rotation"); + if (Imp::isBad(rotationAxis.x(),ctxStr)||Imp::isBad(rotationAxis.y(),ctxStr)||Imp::isBad(rotationAxis.z(),ctxStr)) + BAD("Problem in rotationAxis"); + if (Imp::isBad(rotationAngle,ctxStr)) + BAD("Problem in rotationAngle"); + + //Check that input rotation has det=1 + const double det = t.xx()*t.yy()*t.zz() + +t.zx()*t.xy()*t.yz() + +t.xz()*t.yx()*t.zy() + -t.xx()*t.zy()*t.yz() + -t.yx()*t.xy()*t.zz() + -t.zx()*t.yy()*t.xz(); + const double eps = 1.0e-5; + if (det<1.0-eps||det>1.0+eps) + BAD("Determinant of rotation part is not consistent with 1 (det="+QString::number(det)+")!"); + + return ok; +} + + +//______________________________________________________________________________________ +bool VP1LinAlgUtils::isSane( const Amg::Transform3D & t, const QString& ctxStr ) +{ + Amg::Vector3D translation = t.translation(); + + Amg::RotationMatrix3D rotation = t.rotation(); + + double rotationAngle; + Amg::Vector3D rotationAxis; + + Amg::getAngleAxisFromRotation(rotation, rotationAngle, rotationAxis); + +// double xx = rotation(0,0); +// double yy = rotation(1,1); +// double zz = rotation(2,2); +// +// double cosa = 0.5 * (xx + yy + zz - 1); +// double cosa1 = 1 - cosa; +// +// if (cosa1 <= 0) { +// rotationAngle = 0; +// rotationAxis = Amg::Vector3D(0,0,1); +// } +// else{ +// double x=0, y=0, z=0; +// if (xx > cosa) x = sqrt((xx-cosa)/cosa1); +// if (yy > cosa) y = sqrt((yy-cosa)/cosa1); +// if (zz > cosa) z = sqrt((zz-cosa)/cosa1); +// if (rotation(2,1) < rotation(1,2)) x = -x; +// if (rotation(0,2) < rotation(2,0)) y = -y; +// if (rotation(1,0) < rotation(0,1)) z = -z; +// rotationAngle = (cosa < -1.) ? acos(-1.) : acos(cosa); +// rotationAxis = Amg::Vector3D(x,y,z); +// } + + + + + bool ok(true); + + if (Imp::isBad(t(0,0),ctxStr)||Imp::isBad(t(0,1),ctxStr)||Imp::isBad(t(0,2),ctxStr) + ||Imp::isBad(t(1,0),ctxStr)||Imp::isBad(t(1,1),ctxStr)||Imp::isBad(t(1,2),ctxStr) + ||Imp::isBad(t(2,0),ctxStr)||Imp::isBad(t(2,1),ctxStr)||Imp::isBad(t(2,2),ctxStr) +// ||Imp::isBad(t.dx(),ctxStr)||Imp::isBad(t.dy(),ctxStr)||Imp::isBad(t.dz(),ctxStr)) + ||Imp::isBad(t(0,3),ctxStr)||Imp::isBad(t(1,3),ctxStr)||Imp::isBad(t(2,3),ctxStr)) + BAD("Problem in raw 4x4 transformation matrix!"); + if (Imp::isBad(translation.x(),ctxStr)||Imp::isBad(translation.y(),ctxStr)||Imp::isBad(translation.z(),ctxStr)) + BAD("Problem in translation!"); + if (Imp::isBad(rotation(0,0),ctxStr)||Imp::isBad(rotation(0,1),ctxStr)||Imp::isBad(rotation(0,2),ctxStr) + ||Imp::isBad(rotation(1,0),ctxStr)||Imp::isBad(rotation(1,1),ctxStr)||Imp::isBad(rotation(1,2),ctxStr) + ||Imp::isBad(rotation(2,0),ctxStr)||Imp::isBad(rotation(2,1),ctxStr)||Imp::isBad(rotation(2,2),ctxStr)) + BAD("Problem in rotation"); + if (Imp::isBad(rotationAxis.x(),ctxStr)||Imp::isBad(rotationAxis.y(),ctxStr)||Imp::isBad(rotationAxis.z(),ctxStr)) + BAD("Problem in rotationAxis"); + if (Imp::isBad(rotationAngle,ctxStr)) + BAD("Problem in rotationAngle"); + + //Check that input rotation has det=1 +// const double det = t.xx()*t.yy()*t.zz() +// +t.zx()*t.xy()*t.yz() +// +t.xz()*t.yx()*t.zy() +// -t.xx()*t.zy()*t.yz() +// -t.yx()*t.xy()*t.zz() +// -t.zx()*t.yy()*t.xz(); + const double det = t.matrix().determinant(); + const double eps = 1.0e-5; + if ( det < 1.0-eps || det > 1.0+eps ) + BAD("Determinant of rotation part is not consistent with 1 (det="+QString::number(det)+")!"); + + return ok; +} + + +//______________________________________________________________________________________ +bool VP1LinAlgUtils::isSane( const SoTransform * t, const QString& ctxStr ) +{ + if (!t) { + if (!ctxStr.isEmpty()) + VP1Msg::messageVerbose("VP1LinAlgUtils::toSoTransform ("+ctxStr+") ERROR: NULL SoTransform!"); + return false; + } + + bool ok(true); + float q0,q1, q2,q3; + t->rotation.getValue().getValue(q0,q1, q2,q3); + if (Imp::isBad(q0,ctxStr)||Imp::isBad(q1,ctxStr)||Imp::isBad(q2,ctxStr)||Imp::isBad(q3,ctxStr)) + BAD("Problem in quarternion representation of rotation!"); + t->scaleOrientation.getValue().getValue(q0,q1, q2,q3); + if (Imp::isBad(q0,ctxStr)||Imp::isBad(q1,ctxStr)||Imp::isBad(q2,ctxStr)||Imp::isBad(q3,ctxStr)) + BAD("Problem in quarternion representation of scaleOrientation!"); + float x,y,z; + t->translation.getValue().getValue(x,y,z); + if (Imp::isBad(x,ctxStr,Imp::atlasR)||Imp::isBad(y,ctxStr,Imp::atlasR)||Imp::isBad(z,ctxStr,Imp::atlasR)) + BAD("Problem in translation!"); + t->scaleFactor.getValue().getValue(x,y,z); + if (Imp::isBad(x,ctxStr,Imp::atlasR)||Imp::isBad(y,ctxStr,Imp::atlasR)||Imp::isBad(z,ctxStr,Imp::atlasR)) + BAD("Problem in scaleFactor!"); + t->center.getValue().getValue(x,y,z); + if (Imp::isBad(x,ctxStr,Imp::atlasR)||Imp::isBad(y,ctxStr,Imp::atlasR)||Imp::isBad(z,ctxStr,Imp::atlasR)) + BAD("Problem in center!"); + + return ok; +} + +//______________________________________________________________________________________ +bool VP1LinAlgUtils::isSane( const SbMatrix& matr, const QString& ctxStr ) +{ + bool ok(true); + + bool baseok(true); + for (int i = 0; i < 4; ++i) + for (int j = 0; j < 4; ++j) + if (Imp::isBad(matr[i][j],ctxStr)) { + baseok=false; + break; + } + if (!baseok) + BAD("Problem in raw 4x4 matrix!"); + + SbVec3f translation, scaleFactor, rotaxis; + SbRotation rotation, scaleOrientation; + matr.getTransform(translation, rotation,scaleFactor,scaleOrientation,SbVec3f(0,0,0)); + float q0,q1, q2,q3; + rotation.getValue(q0,q1, q2,q3); + if (Imp::isBad(q0,ctxStr)||Imp::isBad(q1,ctxStr)||Imp::isBad(q2,ctxStr)||Imp::isBad(q3,ctxStr)) + BAD("Problem in quarternion representation of rotation!"); + scaleOrientation.getValue(q0,q1, q2,q3); + if (Imp::isBad(q0,ctxStr)||Imp::isBad(q1,ctxStr)||Imp::isBad(q2,ctxStr)||Imp::isBad(q3,ctxStr)) + BAD("Problem in quarternion representation of scaleOrientation!"); + float x,y,z; + translation.getValue(x,y,z); + if (Imp::isBad(x,ctxStr,Imp::atlasR)||Imp::isBad(y,ctxStr,Imp::atlasR)||Imp::isBad(z,ctxStr,Imp::atlasR)) + BAD("Problem in translation!"); + scaleFactor.getValue(x,y,z); + if (Imp::isBad(x,ctxStr,Imp::atlasR)||Imp::isBad(y,ctxStr,Imp::atlasR)||Imp::isBad(z,ctxStr,Imp::atlasR)) + BAD("Problem in scaleFactor!"); + + const float eps = 1.0e-5; + const float det3 = matr.det3(); + if (det3<1.0-eps||det3>1.0+eps) + BAD("Determinant of rotation part is not consistent with 1 (det3="+QString::number(det3)+")!"); + const float det4 = matr.det4(); + if (det4<1.0-eps||det4>1.0+eps) + BAD("Determinant of rotation part is not consistent with 1 (det4="+QString::number(det4)+")!"); + return ok; +} + +//_____________________________________________________________________________________ +double VP1LinAlgUtils::phiFromXY(const double& x, const double&y ) +{ + //Special case: Returns 0 if both x and y are 0 + double phi = (x == 0.0f)? (y==0.0f?0.0:0.5*M_PI) : std::abs(atan(std::abs(y/static_cast<double>(x)))); + if (x>=0.0f&&y<0.0f) + phi = 2*M_PI-phi; + else if (x<0.0f&&y>=0.0f) + phi = M_PI-phi; + else if (x<0.0f&&y<0.0f) + phi = M_PI+phi; + return phi; +} + + +//_____________________________________________________________________________________ +/* http://www.mycplus.com/tutorial.asp?TID=80 */ +void VP1LinAlgUtils::distPointLineParam(const Amg::Vector3D& point, const Amg::Vector3D& point0, const Amg::Vector3D& point1, double& s) +{ +// s = ((point - point0)*(point1 - point0)) / (((point1 - point0)*(point1 - point0))); + + s = ( ((point)[0]-(point0)[0])*((point1)[0]-(point0)[0]) + + ((point)[1]-(point0)[1])*((point1)[1]-(point0)[1]) + + ((point)[2]-(point0)[2])*((point1)[2]-(point0)[2]) ) / + ( ((point1)[0]-(point0)[0])*((point1)[0]-(point0)[0]) + + ((point1)[1]-(point0)[1])*((point1)[1]-(point0)[1]) + + ((point1)[2]-(point0)[2])*((point1)[2]-(point0)[2]) ); + + return; +} + +//_____________________________________________________________________________________ +/* http://www.mycplus.com/tutorial.asp?TID=80 */ +double VP1LinAlgUtils::distPointLine2(const Amg::Vector3D& point, const Amg::Vector3D& point0, const Amg::Vector3D& point1, double& s) +{ + VP1LinAlgUtils::distPointLineParam(point, point0, point1, s); + + // double dx = (*point)[0]-((*point0)[0] + s*((*point1)[0]-(*point0)[0])); + // double dy = (*point)[1]-((*point0)[1] + s*((*point1)[1]-(*point0)[1])); + // double dz = (*point)[2]-((*point0)[2] + s*((*point1)[2]-(*point0)[2])); + + Amg::Vector3D d = point-(point0 + s*(point1-point0)); + + //return dx*dx + dy*dy + dz*dz; + return d.dot(d); +} + +//_____________________________________________________________________________________ +/* http://www.mycplus.com/tutorial.asp?TID=81 */ +void VP1LinAlgUtils::distLineLineParam(const Amg::Vector3D& point0, const Amg::Vector3D& point1, const Amg::Vector3D& point2, const Amg::Vector3D& point3, double& s, double& t) +{ + //Actual distance not calculated, only parameters s and t. + + Amg::Vector3D p32 = point3 - point2; + double d3232 = p32.dot(p32); + Amg::Vector3D p10 = point1 - point0; + double d1010 = p10.dot(p10); + if (d3232==0.0||d1010==0.0||d3232!=d3232||d1010!=d1010) { + //One input line ill-defined: + s=0.5; + t=0.5; + VP1Msg::messageDebug("VP1LinAlgUtils distLineLineParam ERROR: One or both input lines ill defined"); + return; + } + + double d3210 = p32.dot(p10); + double denom = d1010 * d3232 - d3210 * d3210; + Amg::Vector3D p02 = point0 - point2; + double d0232 = p02.dot(p32); + + if (denom==0) { + //Parallel input! + VP1Msg::messageDebug("VP1LinAlgUtils distLineLineParam Warning: Input lines are parallel. Choosing arbitrary point of closest approach"); + s = 0.5;//We choose an arbitrary point on one of the two lines. + } else { + double d0210 = p02.dot(p10); + double numer = d0232 * d3210 - d0210 * d3232; + s = numer / denom; + } + t = (d0232 + d3210 * s) / d3232; + + return; +} diff --git a/graphics/VTI12/VTI12Utils/src/VP1ParticleData.cxx b/graphics/VTI12/VTI12Utils/src/VP1ParticleData.cxx new file mode 100644 index 000000000..e2e510f45 --- /dev/null +++ b/graphics/VTI12/VTI12Utils/src/VP1ParticleData.cxx @@ -0,0 +1,176 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class VP1ParticleData // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: March 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12Utils/VP1ParticleData.h" +#include "VP1Base/VP1Msg.h" + +#include "GaudiKernel/Bootstrap.h" +#include "GaudiKernel/ISvcLocator.h" +#include "GaudiKernel/IPartPropSvc.h" + +#include "HepPDT/ParticleDataTable.hh" +#include "HepPDT/ParticleData.hh" + +//____________________________________________________________________ +class VP1ParticleData::Imp { +public: + static bool m_badInit; + static const HepPDT::ParticleDataTable * m_particleDataTable; + static std::map<int,double> m_particleAbsPDGCodeToMass; + static std::map<int,double> m_particlePDGCodeToCharge; + static std::map<int,QString> m_particleAbsPDGCodeToName; + static const double m_badValue; + static const QString m_badName; +}; + +bool VP1ParticleData::Imp::m_badInit = false; +const HepPDT::ParticleDataTable * VP1ParticleData::Imp::m_particleDataTable = 0; +std::map<int,double> VP1ParticleData::Imp::m_particleAbsPDGCodeToMass; +std::map<int,double> VP1ParticleData::Imp::m_particlePDGCodeToCharge; +std::map<int,QString> VP1ParticleData::Imp::m_particleAbsPDGCodeToName; +const double VP1ParticleData::Imp::m_badValue = -1.0e99; +const QString VP1ParticleData::Imp::m_badName = "_Bad_Name_"; + +//____________________________________________________________________ +const HepPDT::ParticleData * VP1ParticleData::particleData( const int& pdgcode ) +{ + if (Imp::m_badInit) + return 0; + if (!Imp::m_particleDataTable) { + //init + ISvcLocator* svcLocator = Gaudi::svcLocator(); + if (!svcLocator) { + VP1Msg::message("VP1ParticleData ERROR: Could not get svcLocator."); + Imp::m_badInit = true; + return 0; + } + + IPartPropSvc* partPropSvc; + StatusCode status = svcLocator->service( "PartPropSvc",partPropSvc,true/*createifnotthere*/ ); + if(!status.isSuccess()||!partPropSvc) { + VP1Msg::message("VP1ParticleData ERROR: Could not get particle property service."); + Imp::m_badInit = true; + return 0; + } + Imp::m_particleDataTable = partPropSvc->PDT(); + if (!Imp::m_particleDataTable) { + VP1Msg::message("VP1ParticleData ERROR: Could not get particle data table from particle property service."); + Imp::m_badInit = true; + return 0; + } + } + + const HepPDT::ParticleData* particle = + Imp::m_particleDataTable->particle(HepPDT::ParticleID(pdgcode)); + if (!particle&&VP1Msg::verbose()) + VP1Msg::messageVerbose("VP1ParticleData WARNING: Could not get particle data table for pdgcode="+QString::number(pdgcode)); + + return particle; +} + +//____________________________________________________________________ +double VP1ParticleData::particleMass( const int& pdgcode, bool& ok ) +{ + std::map<int,double>::const_iterator it = Imp::m_particleAbsPDGCodeToMass.find(abs(pdgcode)); + if (it!=Imp::m_particleAbsPDGCodeToMass.end()) { + ok = it->second != Imp::m_badValue; + return ok ? it->second : 0; + } + const HepPDT::ParticleData * data = particleData( abs(pdgcode) ); + double m; + if (data) + m = data->mass().value(); + else + m = Imp::m_badValue; + + Imp::m_particleAbsPDGCodeToMass[abs(pdgcode)] = m; + ok = m != Imp::m_badValue; + return m; +} + +//____________________________________________________________________ +double VP1ParticleData::particleCharge( const int& pdgcode, bool& ok ) +{ + if (pdgcode==22) { + ok = true; + return 0.0; + } + std::map<int,double>::const_iterator it = Imp::m_particlePDGCodeToCharge.find(pdgcode); + if (it!=Imp::m_particlePDGCodeToCharge.end()) { + ok = it->second != Imp::m_badValue; + return ok ? it->second : 0; + } + const HepPDT::ParticleData * data = particleData( abs(pdgcode) ); + double c; + if (data) + c = pdgcode >= 0 ? data->charge() : - data->charge(); + else + c = Imp::m_badValue; + + Imp::m_particlePDGCodeToCharge[pdgcode] = c; + ok = c != Imp::m_badValue; + return c; +} + +//____________________________________________________________________ +QString VP1ParticleData::particleName( const int& pdgcode, bool& ok ) +{ + std::map<int,QString>::const_iterator it = Imp::m_particleAbsPDGCodeToName.find(pdgcode); + if (it!=Imp::m_particleAbsPDGCodeToName.end()) { + ok = (it->second != Imp::m_badName); + return ok ? it->second : ""; + } + + QString name; + switch (pdgcode) { + case 21: name = "gluon"; break; + case 22: name = "photon"; break; + case -11: name = "e+"; break; + case 11: name = "e-"; break; + case -13: name = "mu+"; break; + case 13: name = "mu-"; break; + case -15: name = "tau+"; break; + case 15: name = "tau-"; break; + case -211: name = "M_PI-"; break; + case 211: name = "M_PI+"; break; + case 1: name = "d" ; break; + case 2: name = "u" ; break; + case 3: name = "s" ; break; + case 4: name = "c" ; break; + case 5: name = "b" ; break; + case 6: name = "t" ; break; + case -1: name = "dbar" ; break; + case -2: name = "ubar" ; break; + case -3: name = "sbar" ; break; + case -4: name = "cbar" ; break; + case -5: name = "bbar" ; break; + case -6: name = "tbar" ; break; + case 92: name = "frag string" ; break; + default: + break; + } + + if (name.isEmpty()) { + const HepPDT::ParticleData * data = particleData( abs(pdgcode) ); + if (data) + name = (pdgcode<0?"anti-":"")+QString(data->name().c_str());//fixme: anything [[:alpha:]](+|-) we + // change + and - + else + name = Imp::m_badName; + } + + Imp::m_particleAbsPDGCodeToName[pdgcode] = name; + ok = (name != Imp::m_badName); + return name; +} diff --git a/graphics/VTI12/VTI12Utils/src/VP1SGAccessHelper.cxx b/graphics/VTI12/VTI12Utils/src/VP1SGAccessHelper.cxx new file mode 100644 index 000000000..75635d235 --- /dev/null +++ b/graphics/VTI12/VTI12Utils/src/VP1SGAccessHelper.cxx @@ -0,0 +1,67 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class VP1SGAccessHelper // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: March 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12Utils/VP1SGAccessHelper.h" +#include "VTI12Utils/VP1SGContentsHelper.h" +#include "VP1Base/IVP1System.h" + +//____________________________________________________________________ +class VP1SGAccessHelper::Imp { +public: + Imp(IVP1System * sys,const bool detStore) + : sgcontents(sys,detStore),sg(sys?(detStore?sys->detectorStore():sys->storeGate()):0) {} + Imp(StoreGateSvc * the_sg) + : sgcontents(the_sg), sg(the_sg) {} + VP1SGContentsHelper sgcontents; + StoreGateSvc * sg; +}; + + + +//____________________________________________________________________ +VP1SGAccessHelper::VP1SGAccessHelper( IVP1System * sys,const bool detStore ) + : VP1HelperClassBase(sys,"VP1SGAccessHelper"), m_d(new Imp(sys,detStore)) +{ + if (!sys) + message("ERROR: Received null system pointer (won't be able to get StoreGate pointer either)"); + else if (!m_d->sg) + message("ERROR: Could not get "+QString(detStore?"storeGate":"detectorStore")+" pointer from system"); +} + + +//____________________________________________________________________ +VP1SGAccessHelper::VP1SGAccessHelper( StoreGateSvc * sg ) + : VP1HelperClassBase(0,"VP1SGContentsHelper"), m_d(new Imp(sg)) +{ + if (!sg) + message("ERROR: Received null storegate pointer"); +} + +//____________________________________________________________________ +VP1SGAccessHelper::~VP1SGAccessHelper() +{ + delete m_d; +} + +//____________________________________________________________________ +StoreGateSvc * VP1SGAccessHelper::storeGate() const +{ + return m_d->sg; +} + +//____________________________________________________________________ +bool VP1SGAccessHelper::contains(const CLID& id, const QString& key) const +{ + return m_d->sgcontents.contains(id,key); +} diff --git a/graphics/VTI12/VTI12Utils/src/VP1SGContentsHelper.cxx b/graphics/VTI12/VTI12Utils/src/VP1SGContentsHelper.cxx new file mode 100644 index 000000000..9cb6e9021 --- /dev/null +++ b/graphics/VTI12/VTI12Utils/src/VP1SGContentsHelper.cxx @@ -0,0 +1,125 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class VP1SGContentsHelper // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: March 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12Utils/VP1SGContentsHelper.h" +#include "VP1Base/IVP1System.h" +#include "VP1Base/VP1Msg.h" +#include "StoreGate/StoreGateSvc.h" // +#include <stdexcept> +#include <QStringList> +// // +///////////////////////////////////////////////////////////////////////// + +//____________________________________________________________________ +VP1SGContentsHelper::VP1SGContentsHelper( IVP1System * sys, const bool detStore ) + : VP1HelperClassBase(sys,"VP1SGContentsHelper"), m_sg(sys?(detStore?sys->detectorStore():sys->storeGate()):0) +{ + if (!sys) + message("ERROR: Received null system pointer (won't be able to get storeGate pointer either)"); + else if (!m_sg) + message("ERROR: Could not get "+QString(detStore?"storeGate":"detectorStore")+" pointer from system"); +} + +//____________________________________________________________________ +VP1SGContentsHelper::VP1SGContentsHelper( StoreGateSvc * sg ) + : VP1HelperClassBase(0,"VP1SGContentsHelper"), m_sg(sg) +{ + if (!sg) + message("ERROR: Received null storegate pointer"); +} + +//____________________________________________________________________ +bool VP1SGContentsHelper::contains( const CLID& id, const QString& key ) const +{ + if (VP1Msg::verbose()) + messageVerbose("contains(..) called for key = "+key); + if (!m_sg) { + message("ERROR: Does not have StoreGate pointer - returning false."); + return false; + } + if (key.isEmpty()) { + message("ERROR: Passed key is empty. Returning false."); + return false; + } + bool contains = false; + bool exception = true; + try { + contains = m_sg->contains(id,key.toStdString()); + exception = false; + } catch (const std::runtime_error& e) { + exception = true; + } + if (exception) { + message("ERROR: Exception thrown during call to StoreGateSvc::contains(..). Returning false."); + return false; + } + if (VP1Msg::verbose()) + messageVerbose("contains(..) returning "+QString(contains?"true":"false")); + return contains; +} + +//____________________________________________________________________ +QStringList VP1SGContentsHelper::getKeys(const CLID& id) const +{ + messageVerbose("getKeys(..) called"); + if (!m_sg) { + message("ERROR: Does not have StoreGate pointer - returning empty key list"); + return QStringList(); + } + QStringList l; + + std::vector<std::string> keys; + + bool exception = true; + try { + keys = m_sg->keys(id); + exception = false; + } catch (const std::runtime_error& e) { + exception = true; + } + if (exception) { + message("ERROR: Exception thrown during call to StoreGateSvc::keys(..)"); + return QStringList(); + } + std::vector<std::string>::const_iterator it(keys.begin()), itE(keys.end()); + for (;it!=itE;++it) { + if (it->empty()) + continue; + if (contains(id,it->c_str())) + l << it->c_str(); + else if (VP1Msg::verbose()) + messageVerbose("NB: StoreGateSvc::keys() included '"+QString(it->c_str()) + +"' but StoreGateSvc::contains("+QString(it->c_str())+") returns false." ); + } + if (VP1Msg::verbose()) { + messageVerbose("returning "+QString::number(l.count())+" keys:"); + messageVerbose(" => ",l); + } + return l; +} + +//____________________________________________________________________ +QList<CLID> VP1SGContentsHelper::getPossibleCLIDs() const +{ + messageVerbose("getPossibleCLIDs(..) called"); + QList<CLID> l; + if (!m_sg) { + message("ERROR: Does not have StoreGate pointer - returning empty key list"); + return l; + } + + for (CLID id : m_sg->clids()) + l << id; + return l; +} diff --git a/graphics/VTI12/VTI12Utils/src/VP1ToolAccessHelper.cxx b/graphics/VTI12/VTI12Utils/src/VP1ToolAccessHelper.cxx new file mode 100644 index 000000000..c80745e79 --- /dev/null +++ b/graphics/VTI12/VTI12Utils/src/VP1ToolAccessHelper.cxx @@ -0,0 +1,34 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + + +//////////////////////////////////////////////////////////////// +// // +// Implementation of class VP1ToolAccessHelper // +// // +// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) // +// Initial version: February 2008 // +// // +//////////////////////////////////////////////////////////////// + +#include "VTI12Utils/VP1ToolAccessHelper.h" +#include "VP1Base/IVP1System.h" + +//____________________________________________________________________ +VP1ToolAccessHelper::VP1ToolAccessHelper(IToolSvc* ts) + : VP1HelperClassBase(0,"VP1ToolAccessHelper"),m_toolsvc(ts) +{ + if (!m_toolsvc) + message("ERROR: Received null toolSvc pointer!"); +} + +//____________________________________________________________________ +VP1ToolAccessHelper::VP1ToolAccessHelper(IVP1System* sys) + : VP1HelperClassBase(sys,"VP1ToolAccessHelper"),m_toolsvc((sys?sys->toolSvc():0)) +{ + if (!sys) + message("ERROR: Received null system (and thus also null toolSvc) pointer!"); + else if (!m_toolsvc) + message("ERROR: Could not get toolSvc pointer from system!"); +} -- GitLab