From 2089a3427283745ff6e1cf8043ec4a3633783187 Mon Sep 17 00:00:00 2001 From: jmcarcell Date: Wed, 2 Aug 2023 21:31:53 +0200 Subject: [PATCH 01/21] Fix two compiler warnings --- DDCore/src/Objects.cpp | 2 +- DDCore/src/Shapes.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DDCore/src/Objects.cpp b/DDCore/src/Objects.cpp index 67b1ccc53..181f07ca7 100644 --- a/DDCore/src/Objects.cpp +++ b/DDCore/src/Objects.cpp @@ -452,7 +452,7 @@ string Limit::toString() const { string res = name + " = " + content; if (!unit.empty()) res += unit + " "; - res + " (" + particles + ")"; + res += " (" + particles + ")"; return res; } diff --git a/DDCore/src/Shapes.cpp b/DDCore/src/Shapes.cpp index c0115d55a..10d4643d5 100644 --- a/DDCore/src/Shapes.cpp +++ b/DDCore/src/Shapes.cpp @@ -89,7 +89,7 @@ template const char* Solid_type::type() const { /// Access the dimensions of the shape: inverse of the setDimensions member function template vector Solid_type::dimensions() { - return move( get_shape_dimensions(this->access()) ); + return get_shape_dimensions(this->access()); } /// Set the shape dimensions. As for the TGeo shape, but angles in rad rather than degrees. From 95689ff4cd78dd600b2f417c555cd64456113013 Mon Sep 17 00:00:00 2001 From: Andre Sailer Date: Thu, 3 Aug 2023 18:21:38 +0200 Subject: [PATCH 02/21] CI: use clang16 for header guards check --- .github/workflows/clang-tidy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/clang-tidy.yml b/.github/workflows/clang-tidy.yml index 20782c675..4a9ff607d 100644 --- a/.github/workflows/clang-tidy.yml +++ b/.github/workflows/clang-tidy.yml @@ -8,7 +8,7 @@ jobs: strategy: fail-fast: false matrix: - LCG: ["dev4/x86_64-centos7-clang12-opt"] + LCG: ["dev4/x86_64-el9-clang16-opt"] steps: - uses: actions/checkout@v3 - uses: cvmfs-contrib/github-action-cvmfs@v3 From 94994604256b248f91e345a109131498fa15dd1a Mon Sep 17 00:00:00 2001 From: Dmitry Kalinkin Date: Mon, 21 Aug 2023 14:41:52 -0400 Subject: [PATCH 03/21] HepMC3FileReader.cpp: avoid double call to `HepMC3::Reader::close()` --- DDG4/hepmc/HepMC3FileReader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DDG4/hepmc/HepMC3FileReader.cpp b/DDG4/hepmc/HepMC3FileReader.cpp index b94897abe..9e0f36daf 100644 --- a/DDG4/hepmc/HepMC3FileReader.cpp +++ b/DDG4/hepmc/HepMC3FileReader.cpp @@ -133,8 +133,8 @@ HEPMC3FileReader::HEPMC3FileReader(const std::string& nam) m_reader->skip(1); // then we get the run info (shared pointer) auto runInfo = m_reader->run_info(); - // and close the reader - m_reader->close(); + // and deallocate the reader + m_reader.reset(); // so we can open the file again from the start m_reader = HepMC3::deduce_reader(nam); // and set the run info object now From 81254eae004f1a54a60d1df5ad06e0db342b04cd Mon Sep 17 00:00:00 2001 From: Wouter Deconinck Date: Mon, 21 Aug 2023 13:17:24 -0500 Subject: [PATCH 04/21] Geant4Output2EDM4hep: allow reuse of collection names... again --- DDG4/edm4hep/Geant4Output2EDM4hep.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/DDG4/edm4hep/Geant4Output2EDM4hep.cpp b/DDG4/edm4hep/Geant4Output2EDM4hep.cpp index 6d4acdcc2..9d9ed446d 100644 --- a/DDG4/edm4hep/Geant4Output2EDM4hep.cpp +++ b/DDG4/edm4hep/Geant4Output2EDM4hep.cpp @@ -505,7 +505,7 @@ void Geant4Output2EDM4hep::saveCollection(OutputContext& /*ctxt*/, G4VH //------------------------------------------------------------------- if( typeid( Geant4Tracker::Hit ) == coll->type().type() ){ // Create the hit container even if there are no entries! - auto& hits = m_trackerHits[colName] = edm4hep::SimTrackerHitCollection(); + auto& hits = m_trackerHits[colName]; for(unsigned i=0 ; i < nhits ; ++i){ auto sth = hits->create(); const Geant4Tracker::Hit* hit = coll->hit(i); @@ -536,8 +536,7 @@ void Geant4Output2EDM4hep::saveCollection(OutputContext& /*ctxt*/, G4VH Geant4Sensitive* sd = coll->sensitive(); int hit_creation_mode = sd->hitCreationMode(); // Create the hit container even if there are no entries! - auto& hits = m_calorimeterHits[colName] = - std::make_pair(edm4hep::SimCalorimeterHitCollection(), edm4hep::CaloHitContributionCollection()); + auto& hits = m_calorimeterHits[colName]; for(unsigned i=0 ; i < nhits ; ++i){ auto sch = hits.first->create(); const Geant4Calorimeter::Hit* hit = coll->hit(i); From efaf431cdcc62e454d40482374c320917536c253 Mon Sep 17 00:00:00 2001 From: Ben Couturier Date: Wed, 23 Aug 2023 14:50:50 +0200 Subject: [PATCH 05/21] Improved _getEnviron to deal with the case when multiple variables are in the string --- DDCore/src/Handle.cpp | 51 ++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/DDCore/src/Handle.cpp b/DDCore/src/Handle.cpp index a7d70c77a..f09d5540a 100644 --- a/DDCore/src/Handle.cpp +++ b/DDCore/src/Handle.cpp @@ -280,26 +280,41 @@ namespace dd4hep { } /// Evaluate string constant using environment stored in the evaluator - string _getEnviron(const string& env) { - size_t id1 = env.find("${"); - size_t id2 = env.rfind("}"); - if ( id1 == string::npos || id2 == string::npos ) { - return ""; - } - else { - stringstream err; - string v = env.substr(id1,id2-id1+1); - auto ret = eval.getEnviron(v, err); - if ( ret.first != tools::Evaluator::OK) { - cerr << env << ": " << err.str() << endl; - throw runtime_error("dd4hep: Severe error during environment lookup of " + env + - " " + err.str()); + string _getEnviron(const string& env) { + // We are trying to deal with the case when several variables are being replaced in the + // string. + size_t current_index = 0; + stringstream processed_variable; + while (true) { + // Looking for the start of a variable use, with the syntax + // "path1/path2/${VAR1}/path3/${VAR2}" + size_t id1 = env.find("${", current_index); + // variable start found, do a greedy search for the variable end + if (id1 != string::npos) { + size_t id2 = env.find("}", id1); + if (id2 == string::npos) { + runtime_error("dd4hep: Syntax error, bas variable syntax: " + env); + } + processed_variable << env.substr(current_index, id1 -current_index ); + string v = env.substr(id1, id2-id1+1); + stringstream err; + auto ret = eval.getEnviron(v, err); + // Checking that the variable lookup worked + if ( ret.first != tools::Evaluator::OK) { + cerr << v << ": " << err.str() << endl; + throw runtime_error("dd4hep: Severe error during environment lookup of " + v + " " + err.str()); + } + // Now adding the variable + processed_variable << ret.second; + current_index = id2 + 1; + } else { + // In this case we did not find the ${ to indicate a start of variable, + // we just copy the rest of the variable to the stringstream and exit + processed_variable << env.substr(current_index); + break; } - v = env.substr(0,id1); - v += ret.second; - v += env.substr(id2+1); - return v; } + return processed_variable.str(); } /// String manipulations: Remove unconditionally all white spaces From 87e34e98796212efdce2ee7ed7a2de74c4eeb4ac Mon Sep 17 00:00:00 2001 From: Ben Couturier Date: Wed, 23 Aug 2023 15:46:34 +0200 Subject: [PATCH 06/21] Applied suggestions from review --- DDCore/src/Handle.cpp | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/DDCore/src/Handle.cpp b/DDCore/src/Handle.cpp index f09d5540a..7cfa46fcb 100644 --- a/DDCore/src/Handle.cpp +++ b/DDCore/src/Handle.cpp @@ -290,29 +290,28 @@ namespace dd4hep { // "path1/path2/${VAR1}/path3/${VAR2}" size_t id1 = env.find("${", current_index); // variable start found, do a greedy search for the variable end - if (id1 != string::npos) { - size_t id2 = env.find("}", id1); - if (id2 == string::npos) { - runtime_error("dd4hep: Syntax error, bas variable syntax: " + env); - } - processed_variable << env.substr(current_index, id1 -current_index ); - string v = env.substr(id1, id2-id1+1); - stringstream err; - auto ret = eval.getEnviron(v, err); - // Checking that the variable lookup worked - if ( ret.first != tools::Evaluator::OK) { - cerr << v << ": " << err.str() << endl; - throw runtime_error("dd4hep: Severe error during environment lookup of " + v + " " + err.str()); - } - // Now adding the variable - processed_variable << ret.second; - current_index = id2 + 1; - } else { - // In this case we did not find the ${ to indicate a start of variable, + if (id1 == string::npos) { + // In this case we did not find the ${ to indicate a start of variable, // we just copy the rest of the variable to the stringstream and exit processed_variable << env.substr(current_index); break; } + size_t id2 = env.find("}", id1); + if (id2 == string::npos) { + runtime_error("dd4hep: Syntax error, bad variable syntax: " + env); + } + processed_variable << env.substr(current_index, id1 -current_index ); + string v = env.substr(id1, id2-id1+1); + stringstream err; + auto ret = eval.getEnviron(v, err); + // Checking that the variable lookup worked + if ( ret.first != tools::Evaluator::OK) { + cerr << v << ": " << err.str() << endl; + throw runtime_error("dd4hep: Severe error during environment lookup of " + v + " " + err.str()); + } + // Now adding the variable + processed_variable << ret.second; + current_index = id2 + 1; } return processed_variable.str(); } From 6c8a96f8095dcec80d8fdbdffa73be944e324921 Mon Sep 17 00:00:00 2001 From: Andre Sailer Date: Wed, 23 Aug 2023 17:10:55 +0200 Subject: [PATCH 07/21] Geant4FastSim: fix typo in docstring --- DDG4/include/DDG4/Geant4FastSimShowerModel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DDG4/include/DDG4/Geant4FastSimShowerModel.h b/DDG4/include/DDG4/Geant4FastSimShowerModel.h index b158999b6..0c93e48d4 100644 --- a/DDG4/include/DDG4/Geant4FastSimShowerModel.h +++ b/DDG4/include/DDG4/Geant4FastSimShowerModel.h @@ -68,7 +68,7 @@ namespace dd4hep { ParticleConfig m_eMax { }; /// Property: Set maximum kinetic energy for particles to be killed ParticleConfig m_eKill { }; - /// Property: Set minmal kinetic energy for particles to trigger the model + /// Property: Set minimal kinetic energy for particles to trigger the model ParticleConfig m_eTriggerNames { }; /// Particle definitions for which this parametrization is applicable From 25fcdf1d258415ec486d9ab868b2df7a89d54c96 Mon Sep 17 00:00:00 2001 From: Andre Sailer Date: Wed, 23 Aug 2023 17:11:29 +0200 Subject: [PATCH 08/21] Example FastSimGFlash: add Emax for some reason, this fixes the nans and error in the test --- examples/ClientTests/scripts/SiliconBlockGFlash.py | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/ClientTests/scripts/SiliconBlockGFlash.py b/examples/ClientTests/scripts/SiliconBlockGFlash.py index 732150184..a07c331a4 100644 --- a/examples/ClientTests/scripts/SiliconBlockGFlash.py +++ b/examples/ClientTests/scripts/SiliconBlockGFlash.py @@ -100,6 +100,7 @@ def run(): model.Enable = True # Energy boundaries are optional: Units are GeV model.Emin = {'e+': 0.1 * GeV, 'e-': 0.1 * GeV} + model.Emax = {'e+': 100 * GeV, 'e-': 100 * GeV} model.Ekill = {'e+': 0.1 * MeV, 'e-': 0.1 * MeV} model.enableUI() seq.adopt(model) From 310736d030f0389ff94a1c8d4ce0ce0a5e395ae8 Mon Sep 17 00:00:00 2001 From: Markus Frank Date: Fri, 11 Aug 2023 13:23:24 +0200 Subject: [PATCH 09/21] Implement correct volume transparency settings for ROOT>=6.29 (https://github.com/AIDASoft/DD4hep/issues/1117) --- DDCore/src/Volumes.cpp | 7 +- examples/ClientTests/compact/visTest.xml | 51 ++++++++++ examples/ClientTests/compact/visTestEx.xml | 57 +++++++++++ examples/ClientTests/scripts/visTest.C | 110 +++++++++++++++++++++ 4 files changed, 223 insertions(+), 2 deletions(-) create mode 100644 examples/ClientTests/compact/visTest.xml create mode 100644 examples/ClientTests/compact/visTestEx.xml create mode 100644 examples/ClientTests/scripts/visTest.C diff --git a/DDCore/src/Volumes.cpp b/DDCore/src/Volumes.cpp index e7e3f18b5..a46861b83 100644 --- a/DDCore/src/Volumes.cpp +++ b/DDCore/src/Volumes.cpp @@ -1155,14 +1155,17 @@ const Volume& Volume::setVisAttributes(const VisAttr& attr) const { if (draw_style == VisAttr::SOLID) { m_element->SetFillStyle(1001); // Root: solid -#if ROOT_VERSION_CODE >= ROOT_VERSION(6,0,0) +#if ROOT_VERSION_CODE >= ROOT_VERSION(6,29,0) + // Set directly transparency to the volume, NOT to the material as for ROOT < 6.29 + m_element->ResetTransparency(Char_t((1.0-vis->alpha)*100)); +#elif ROOT_VERSION_CODE >= ROOT_VERSION(6,0,0) // As suggested by Valentin Volkl https://sft.its.cern.ch/jira/browse/DDFORHEP-20 // // According to https://root.cern.ch/phpBB3/viewtopic.php?t=2309#p66013 // a transparency>50 will make a volume invisible in the normal pad. // Hence: possibly restrict transparency to a maximum of 50. // but let's see first how this behaves. - m_element->SetTransparency((1.0-vis->alpha)*100); + m_element->SetTransparency(Char_t((1.0-vis->alpha)*100)); #endif } else { diff --git a/examples/ClientTests/compact/visTest.xml b/examples/ClientTests/compact/visTest.xml new file mode 100644 index 000000000..0fb65e56b --- /dev/null +++ b/examples/ClientTests/compact/visTest.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/ClientTests/compact/visTestEx.xml b/examples/ClientTests/compact/visTestEx.xml new file mode 100644 index 000000000..b6995e3b7 --- /dev/null +++ b/examples/ClientTests/compact/visTestEx.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/ClientTests/scripts/visTest.C b/examples/ClientTests/scripts/visTest.C new file mode 100644 index 000000000..d9ddce226 --- /dev/null +++ b/examples/ClientTests/scripts/visTest.C @@ -0,0 +1,110 @@ +#include "TROOT.h" +#include "TColor.h" +#include "TGeoCone.h" +#include "TGeoMatrix.h" +#include "TGeoManager.h" +#include "TGeoElement.h" +#include "TGeoMaterial.h" + +#include + + +class Test { +public: + TGeoManager* m_manager = nullptr; + TGeoMaterial* m_vacuum = nullptr; + TGeoMedium* m_air = nullptr; + + TGeoBBox* m_worldShape = nullptr; + TGeoVolume* m_world = nullptr; + + struct Cone { + TGeoMaterial* material = nullptr; + TGeoMedium* medium = nullptr; + TGeoConeSeg* shape = nullptr; + TGeoVolume* volume = nullptr; + TGeoNode* place = nullptr; + void set_color(const char* typ, Float_t alpha, Float_t red, Float_t green, Float_t blue) { + Int_t col = TColor::GetColor(red, green, blue); + TColor* color = gROOT->GetColor(col); + if ( !color ) { + ::printf("+++ %s Failed to allocate Color: r:%02X g:%02X b:%02X\n", + typ, int(red*255.), int(green*255.), int(blue*255)); + } + char text[64]; + ::snprintf(text, sizeof(text), "%p", this); + TColor* colortr = new TColor(gROOT->GetListOfColors()->GetLast()+1, + color->GetRed(), color->GetGreen(), color->GetBlue(), text, alpha); + //colortr->SetAlpha(alpha); + + ::printf("Plot cone %s (col: %d) with transparency %8.3f r:%02X g:%02X b:%02X\n", + typ, col, (1.0-alpha)*100, int(red*255.), int(green*255.), int(blue*255)); + + /// Propagate values to the volume: + int col_num = color->GetNumber(); + int col_tr_num = colortr->GetNumber(); + volume->SetVisibility(kTRUE); + volume->SetVisContainers(kTRUE); + volume->SetVisDaughters(kTRUE); + volume->SetLineWidth(10); + volume->SetFillStyle(1001); + volume->ResetTransparency((1.0-alpha)*100); + volume->SetLineStyle(1); + + /// Set line color + volume->SetLineColor(col_num); + /// Set fill color + volume->SetFillColor(col_tr_num); + } + } cone1, cone2; + +public: + Test() { + } + virtual ~Test() { + } + void build(int version); +}; + +void Test::build(int version) { + m_manager = new TGeoManager("geom","Tube test"); + m_vacuum = new TGeoMaterial("vacuum", 0, 0, 0); + m_air = new TGeoMedium("Vacuum", 0, m_vacuum); + + m_worldShape = new TGeoBBox("WorldBox", 100, 100, 100); + m_world = new TGeoVolume("World", m_worldShape, m_air); + + cone1.material = new TGeoMaterial("Fe1", 55.845, 26, 7.87); + cone1.medium = new TGeoMedium("Iron1", 1, cone1.material); + cone1.shape = new TGeoConeSeg("Cone1Shape", 40, 0e0, 20e0, 0e0, 20e0, 0e0, 360e0); + cone1.volume = new TGeoVolume("Cone1", cone1.shape, cone1.medium); + cone1.set_color("Cone1", + version ? 0.1 : 0.9, + version ? 1e0 : 0e0, + 0e0, + version ? 0e0 : 1e0); + m_world->AddNode(cone1.volume, 1, new TGeoTranslation(-30, -30, 0)); + + cone2.material = version ? new TGeoMaterial("Fe2", 55.845, 26, 7.87) : cone1.material; + cone2.medium = version ? new TGeoMedium("Iron2", 1, cone2.material) : cone1.medium; + cone2.shape = new TGeoConeSeg("Cone2Shape", 40, 0e0, 20e0, 0e0, 20e0, 0e0, 360e0); + cone2.volume = new TGeoVolume("Cone2", cone2.shape, cone2.medium); + cone2.set_color("Cone2", + version ? 0.9 : 0.1, + version ? 0e0 : 0.9, + 0e0, + version ? 0.9 : 0e0); + m_world->AddNode(cone2.volume, 1, new TGeoTranslation(30, 30, 0)); + + m_manager->SetTopVolume(m_world); + m_manager->SetTopVisible(0); + + m_manager->GetTopVolume()->Draw("ogl"); +} + + +Test* visTest(int version=0) { + Test* obj = new Test(); + obj->build(version); + return obj; +} From 8715c52c1c8b3c714d80896cb8540f3f8f888786 Mon Sep 17 00:00:00 2001 From: Andre Sailer Date: Fri, 25 Aug 2023 13:31:56 +0200 Subject: [PATCH 10/21] WebDisplay: RGeomViewer is no longer experimental --- DDEve/root7/WebDisplay.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/DDEve/root7/WebDisplay.cpp b/DDEve/root7/WebDisplay.cpp index 27975f98f..57e835fbf 100644 --- a/DDEve/root7/WebDisplay.cpp +++ b/DDEve/root7/WebDisplay.cpp @@ -19,7 +19,11 @@ #include "ROOT/RDirectory.hxx" #if ROOT_VERSION_CODE >= ROOT_VERSION(6,27,00) #include "ROOT/RGeomViewer.hxx" -using GEOM_VIEWER = ROOT::Experimental::RGeomViewer; +# if ROOT_VERSION_CODE >= ROOT_VERSION(6,29,00) + using GEOM_VIEWER = ROOT::RGeomViewer; +# else + using GEOM_VIEWER = ROOT::Experimental::RGeomViewer; +# endif #else #include "ROOT/REveGeomViewer.hxx" using GEOM_VIEWER = ROOT::Experimental::REveGeomViewer; From ce7bfea294a4daa5bfeb590852fabe3ca87353c4 Mon Sep 17 00:00:00 2001 From: Dmitry Kalinkin Date: Wed, 30 Aug 2023 15:27:56 -0400 Subject: [PATCH 11/21] HepMC3FileReader: fix loading of run info for RootTree HepMC3 input format This is done by actually reading an event instead of skipping one. Skipping may be sufficient for the ASCII reader, however, RootTree reader does not perform a read on skip: https://gitlab.cern.ch/hepmc/HepMC3/-/blob/master/rootIO/src/ReaderRootTree.cc#L76-80 --- DDG4/hepmc/HepMC3FileReader.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/DDG4/hepmc/HepMC3FileReader.cpp b/DDG4/hepmc/HepMC3FileReader.cpp index 9e0f36daf..d2711c817 100644 --- a/DDG4/hepmc/HepMC3FileReader.cpp +++ b/DDG4/hepmc/HepMC3FileReader.cpp @@ -130,7 +130,8 @@ HEPMC3FileReader::HEPMC3FileReader(const std::string& nam) m_reader = HepMC3::deduce_reader(nam); #if HEPMC3_VERSION_CODE >= 3002006 // to get the runInfo in the Ascii reader we have to force HepMC to read the first event - m_reader->skip(1); + HepMC3::GenEvent dummy; + m_reader->read_event(dummy); // then we get the run info (shared pointer) auto runInfo = m_reader->run_info(); // and deallocate the reader From 094aa6cee2c0a38b7db4a9dc0b95f4759f6a1981 Mon Sep 17 00:00:00 2001 From: Wouter Deconinck Date: Thu, 14 Sep 2023 12:16:22 -0500 Subject: [PATCH 12/21] fix: allow for uid without username Since 1.26 (ab9a96e66ac1df6a7b3989b082c043932b77dd33) we are seeing `ddsim` exceptions on certain Open Science Grid nodes/sites. Those sites appear to configure the running of singularity containers in such a way that no usernames are associated with the uid. --- DDG4/python/DDSim/Helper/Meta.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/DDG4/python/DDSim/Helper/Meta.py b/DDG4/python/DDSim/Helper/Meta.py index 7b1e2f2e9..45b406da8 100644 --- a/DDG4/python/DDSim/Helper/Meta.py +++ b/DDG4/python/DDSim/Helper/Meta.py @@ -100,6 +100,9 @@ def addParametersToRunHeader(sim): # add User import getpass - runHeader["User"] = getpass.getuser() + try: + runHeader["User"] = getpass.getuser() + except KeyError: + runHeader["User"] = str(os.getuid()) return runHeader From df6455130d91c3987c7ce59dc51b0fbd16110524 Mon Sep 17 00:00:00 2001 From: jmcarcell Date: Fri, 15 Sep 2023 10:36:26 +0200 Subject: [PATCH 13/21] Check if the CLHEP target exists before creating it, if it does warn --- cmake/DD4hepBuild.cmake | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmake/DD4hepBuild.cmake b/cmake/DD4hepBuild.cmake index ab12d75a7..bcd3407f7 100644 --- a/cmake/DD4hepBuild.cmake +++ b/cmake/DD4hepBuild.cmake @@ -826,7 +826,11 @@ MACRO(DD4HEP_SETUP_GEANT4_TARGETS) if(Geant4_builtin_clhep_FOUND) dd4hep_debug("Using Geant4 internal CLHEP") - ADD_LIBRARY(CLHEP::CLHEP INTERFACE IMPORTED GLOBAL) + if(TARGET CLHEP::CLHEP) + message(WARNING "CLHEP::CLHEP already exists, this may cause problems if there are two different installations of CLHEP, one from Geant4 and one external") + else() + ADD_LIBRARY(CLHEP::CLHEP INTERFACE IMPORTED GLOBAL) + endif() SET_TARGET_PROPERTIES(CLHEP::CLHEP PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${Geant4_INCLUDE_DIRS}" From 9cc3b011e864279e7320ff90963149aeb8c52a7a Mon Sep 17 00:00:00 2001 From: Dmitry Kalinkin Date: Mon, 18 Sep 2023 16:59:53 -0400 Subject: [PATCH 14/21] Evaluator: fix typo: systax -> syntax --- DDParsers/include/Evaluator/Evaluator.h | 2 +- DDParsers/src/Evaluator/Evaluator.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DDParsers/include/Evaluator/Evaluator.h b/DDParsers/include/Evaluator/Evaluator.h index c8a331fa8..80f41c8b6 100644 --- a/DDParsers/include/Evaluator/Evaluator.h +++ b/DDParsers/include/Evaluator/Evaluator.h @@ -57,7 +57,7 @@ namespace dd4hep { WARNING_EXISTING_FUNCTION, /**< Redefinition of existing function */ WARNING_BLANK_STRING, /**< Empty input string */ ERROR_NOT_A_NAME, /**< Not allowed sysmbol in the name of variable or function */ - ERROR_SYNTAX_ERROR, /**< Systax error */ + ERROR_SYNTAX_ERROR, /**< Syntax error */ ERROR_UNPAIRED_PARENTHESIS, /**< Unpaired parenthesis */ ERROR_UNEXPECTED_SYMBOL, /**< Unexpected sysbol */ ERROR_UNKNOWN_VARIABLE, /**< Non-existing variable */ diff --git a/DDParsers/src/Evaluator/Evaluator.cpp b/DDParsers/src/Evaluator/Evaluator.cpp index 5beb6626c..070b2fe0c 100644 --- a/DDParsers/src/Evaluator/Evaluator.cpp +++ b/DDParsers/src/Evaluator/Evaluator.cpp @@ -545,7 +545,7 @@ static int engine(char const* begin, char const* end, double & result, iWhat = SyntaxTable[iPrev][iCur]; iPrev = iCur; switch (iWhat) { - case 0: // systax error + case 0: // syntax error EVAL_EXIT( EVAL::ERROR_SYNTAX_ERROR, pointer ); case 1: // operand: number, variable, function EVAL_STATUS = operand(pointer, end, value, pointer, dictionary); From 8f3eb5649a4bfaad1663dcbf5f1136add948c9ee Mon Sep 17 00:00:00 2001 From: Andre Sailer Date: Tue, 19 Sep 2023 08:40:36 +0200 Subject: [PATCH 15/21] Evaluator: fix typos of symbol --- DDParsers/include/Evaluator/Evaluator.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DDParsers/include/Evaluator/Evaluator.h b/DDParsers/include/Evaluator/Evaluator.h index 80f41c8b6..4dfa6b30f 100644 --- a/DDParsers/include/Evaluator/Evaluator.h +++ b/DDParsers/include/Evaluator/Evaluator.h @@ -56,10 +56,10 @@ namespace dd4hep { WARNING_EXISTING_VARIABLE, /**< Redefinition of existing variable */ WARNING_EXISTING_FUNCTION, /**< Redefinition of existing function */ WARNING_BLANK_STRING, /**< Empty input string */ - ERROR_NOT_A_NAME, /**< Not allowed sysmbol in the name of variable or function */ + ERROR_NOT_A_NAME, /**< Not allowed symbol in the name of variable or function */ ERROR_SYNTAX_ERROR, /**< Syntax error */ ERROR_UNPAIRED_PARENTHESIS, /**< Unpaired parenthesis */ - ERROR_UNEXPECTED_SYMBOL, /**< Unexpected sysbol */ + ERROR_UNEXPECTED_SYMBOL, /**< Unexpected symbol */ ERROR_UNKNOWN_VARIABLE, /**< Non-existing variable */ ERROR_UNKNOWN_FUNCTION, /**< Non-existing function */ ERROR_EMPTY_PARAMETER, /**< Function call has empty parameter */ From 03a54fdb313fb507448327269712851bc809b3ca Mon Sep 17 00:00:00 2001 From: Sebouh Paul Date: Wed, 20 Sep 2023 03:23:41 -0400 Subject: [PATCH 16/21] Added implementation for hexagonal and cartesianXY staggered segmentation (#1161) --- .../DDSegmentation/CartesianGridXYStaggered.h | 150 ++++++++++++++++++ DDCore/include/DDSegmentation/HexGrid.h | 131 +++++++++++++++ .../CartesianGridXYStaggered.cpp | 102 ++++++++++++ DDCore/src/segmentations/HexGrid.cpp | 149 +++++++++++++++++ 4 files changed, 532 insertions(+) create mode 100644 DDCore/include/DDSegmentation/CartesianGridXYStaggered.h create mode 100644 DDCore/include/DDSegmentation/HexGrid.h create mode 100644 DDCore/src/segmentations/CartesianGridXYStaggered.cpp create mode 100644 DDCore/src/segmentations/HexGrid.cpp diff --git a/DDCore/include/DDSegmentation/CartesianGridXYStaggered.h b/DDCore/include/DDSegmentation/CartesianGridXYStaggered.h new file mode 100644 index 000000000..441026adf --- /dev/null +++ b/DDCore/include/DDSegmentation/CartesianGridXYStaggered.h @@ -0,0 +1,150 @@ +//========================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +//========================================================================== + + + + +/* + * CartesianGridXYStaggered.h + * + * Created on: September 15, 2023 + * Author: Sebouh J. Paul, UCR + */ + +#ifndef DDSEGMENTATION_CARTESIANGRIDXYSTAGGERED_H +#define DDSEGMENTATION_CARTESIANGRIDXYSTAGGERED_H + +#include "DDSegmentation/CartesianGrid.h" + +namespace dd4hep { + namespace DDSegmentation { + + /// Segmentation base class describing cartesian grid segmentation in the X-Y plane + class CartesianGridXYStaggered: public CartesianGrid { + public: + /// Default constructor passing the encoding string + CartesianGridXYStaggered(const std::string& cellEncoding = ""); + /// Default constructor used by derived classes passing an existing decoder + CartesianGridXYStaggered(const BitFieldCoder* decoder); + /// destructor + virtual ~CartesianGridXYStaggered(); + + /// determine the position based on the cell ID + virtual Vector3D position(const CellID& cellID) const; + /// determine the cell ID based on the position + virtual CellID cellID(const Vector3D& localPosition, const Vector3D& globalPosition, const VolumeID& volumeID) const; + /// access the grid size in X + double gridSizeX() const { + return _gridSizeX; + } + /// access the grid size in Y + double gridSizeY() const { + return _gridSizeY; + } + /// access the coordinate offset in X + double offsetX() const { + return _offsetX; + } + /// access the coordinate offset in Y + double offsetY() const { + return _offsetY; + } + /// access the field name used for X + const std::string& fieldNameX() const { + return _xId; + } + /// access the field name used for Y + const std::string& fieldNameY() const { + return _yId; + } + /// access the staggering option in X + int staggerX() const { + return _staggerX; + } + /// access the staggering option in Y + int staggerY() const { + return _staggerY; + } + /// access the keyword used to determine which volumes to stagger + const std::string& staggerKeyword() const { + return _staggerKeyword; + } + /// set the grid size in X + void setGridSizeX(double cellSize) { + _gridSizeX = cellSize; + } + /// set the grid size in Y + void setGridSizeY(double cellSize) { + _gridSizeY = cellSize; + } + /// set the coordinate offset in X + void setOffsetX(double offset) { + _offsetX = offset; + } + /// set the coordinate offset in Y + void setOffsetY(double offset) { + _offsetY = offset; + } + /// set the field name used for X + void setFieldNameX(const std::string& fieldName) { + _xId = fieldName; + } + /// set the field name used for Y + void setFieldNameY(const std::string& fieldName) { + _yId = fieldName; + } + /// set the staggering option in X + void setStaggerX(int staggerX) { + _staggerX = staggerX; + } + /// set the staggering option in Y + void setStaggerY(int staggerY) { + _staggerY = staggerY; + } + /// set the keyword used to determine which volumes to stagger + void setStaggerKeyword(const std::string& staggerKeyword) { + _staggerKeyword = staggerKeyword; + } + /** \brief Returns a vector of the cellDimensions of the given cell ID + in natural order of dimensions, e.g., dx/dy/dz, or dr/r*dPhi + + Returns a vector of the cellDimensions of the given cell ID + \param cellID is ignored as all cells have the same dimension + \return std::vector size 2: + -# size in x + -# size in y + */ + virtual std::vector cellDimensions(const CellID& cellID) const; + + protected: + /// the grid size in X + double _gridSizeX; + /// the coordinate offset in X + double _offsetX; + /// staggering option in X. 0 = no staggering. 1 = stagger by _gridSizeX/2.0 in odd layers + int _staggerX; + /// the grid size in Y + double _gridSizeY; + /// the coordinate offset in Y + double _offsetY; + /// staggering option in Y. 0 = no staggering. 1 = stagger by _gridSizeY/2.0 in odd layers + int _staggerY; + /// the field name used for X + std::string _xId; + /// the field name used for Y + std::string _yId; + /// the keyword used to determine which volumes to stagger + std::string _staggerKeyword; + }; + + } /* namespace DDSegmentation */ +} /* namespace dd4hep */ +#endif // DDSEGMENTATION_CARTESIANGRIDXYSTAGGERED_H diff --git a/DDCore/include/DDSegmentation/HexGrid.h b/DDCore/include/DDSegmentation/HexGrid.h new file mode 100644 index 000000000..434177790 --- /dev/null +++ b/DDCore/include/DDSegmentation/HexGrid.h @@ -0,0 +1,131 @@ +//========================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +//========================================================================== + +/* + * HexGrid.h + * + * Created on: August 9, 2023 + * Author: Sebouh J. Paul, UC Riverside + */ + +#ifndef DDSEGMENTATION_HEXGRID_H +#define DDSEGMENTATION_HEXGRID_H + +#include "DDSegmentation/Segmentation.h" + +namespace dd4hep { + namespace DDSegmentation { + + /// Segmentation base class describing hexagonal grid segmentation, with or without staggering + class HexGrid: public Segmentation { + public: + /// Destructor + virtual ~HexGrid(); + //protected: + /// Default constructor used by derived classes passing the encoding string + HexGrid(const std::string& cellEncoding = ""); + /// Default constructor used by derived classes passing an existing decoder + HexGrid(const BitFieldCoder* decoder); + + /// determine the position based on the cell ID + virtual Vector3D position(const CellID& cellID) const; + /// determine the cell ID based on the position + virtual CellID cellID(const Vector3D& localPosition, const Vector3D& globalPosition, const VolumeID& volumeID) const; + // access the stagger mode: 0=no stagger; 1=stagger cycling through 3 offsets + int stagger() const { + return _stagger; + } + + /// access the grid size + double sideLength() const { + return _sideLength; + } + /// access the coordinate offset in X + double offsetX() const { + return _offsetX; + } + /// access the coordinate offset in Y + double offsetY() const { + return _offsetY; + } + /// access the field name used for X + const std::string& fieldNameX() const { + return _xId; + } + /// access the field name used for Y + const std::string& fieldNameY() const { + return _yId; + } + /// access the keyword for staggering + const std::string& staggerKeyword() const { + return _staggerKeyword; + } + + /// set the stagger mode: 0=no stagger; 1=stagger cycling through 3 offsets + void setStagger(int stagger) { + _stagger= stagger; + } + /// set the grid size in X + void setSideLength(double cellSize) { + _sideLength = cellSize; + } + /// set the coordinate offset in X + void setOffsetX(double offset) { + _offsetX = offset; + } + /// set the coordinate offset in Y + void setOffsetY(double offset) { + _offsetY = offset; + } + /// set the field name used for X + void setFieldNameX(const std::string& fieldName) { + _xId = fieldName; + } + /// set the field name used for Y + void setFieldNameY(const std::string& fieldName) { + _yId = fieldName; + } + /// set the keyword used to determine which volumes to stagger + void setStaggerKeyword(const std::string& staggerKeyword) { + _staggerKeyword = staggerKeyword; + } + /** \brief Returns a vector of the cellDimensions of the given cell ID + in natural order of dimensions, e.g., dx/dy/dz, or dr/r*dPhi + + Returns a vector of the cellDimensions of the given cell ID + \param cellID is ignored as all cells have the same dimension + \return std::vector size 2: + -# size in x + -# size in y + */ + virtual std::vector cellDimensions(const CellID& cellID) const; + + protected: + /// the stagger mode: 0=off ; 1=cycle through 3 different offsets (H3) + // 2=cycle through 4 differnt offsets (H4) + int _stagger; + /// the length of one side of a hexagon + double _sideLength; + /// the coordinate offset in X + double _offsetX; + /// the coordinate offset in Y + double _offsetY; + /// the field name used for X + std::string _xId; + /// the field name used for Y + std::string _yId; + /// the keyword used to determine which volumes to stagger + std::string _staggerKeyword; + }; + + } /* namespace DDSegmentation */ +} /* namespace dd4hep */ +#endif // DDSEGMENTATION_HEXGRID_H diff --git a/DDCore/src/segmentations/CartesianGridXYStaggered.cpp b/DDCore/src/segmentations/CartesianGridXYStaggered.cpp new file mode 100644 index 000000000..871958ffe --- /dev/null +++ b/DDCore/src/segmentations/CartesianGridXYStaggered.cpp @@ -0,0 +1,102 @@ +/* + * CartesianGridXYStaggered.cpp + * + * Created on: Sept 15, 2023 + * Author: Sebouh J. Paul, UCR + */ + +#include "DDSegmentation/CartesianGridXYStaggered.h" + +namespace dd4hep { +namespace DDSegmentation { + +/// default constructor using an encoding string +CartesianGridXYStaggered::CartesianGridXYStaggered(const std::string& cellEncoding) : + CartesianGrid(cellEncoding) { + // define type and description + _type = "CartesianGridXYStaggered"; + _description = "Cartesian segmentation in the local XY-plane, with options for staggering"; + + // register all necessary parameters + registerParameter("grid_size_x", "Cell size in X", _gridSizeX, 1., SegmentationParameter::LengthUnit); + registerParameter("grid_size_y", "Cell size in Y", _gridSizeY, 1., SegmentationParameter::LengthUnit); + registerParameter("offset_x", "Cell offset in X", _offsetX, 0., SegmentationParameter::LengthUnit, true); + registerParameter("offset_y", "Cell offset in Y", _offsetY, 0., SegmentationParameter::LengthUnit, true); + registerParameter("stagger_x", "Option to stagger the layers in x (ie, add grid_size_x/2 to offset_x for odd layers)", _staggerX, 0, + SegmentationParameter::NoUnit, true); + registerParameter("stagger_y", "Option to stagger the layers in y (ie, add grid_size_y/2 to offset_y for odd layers)", _staggerY, 0, + SegmentationParameter::NoUnit, true); + registerIdentifier("identifier_x", "Cell ID identifier for X", _xId, "x"); + registerIdentifier("identifier_y", "Cell ID identifier for Y", _yId, "y"); + registerParameter("stagger_keyword", "Volume ID identifier used for determining which volumes to stagger", _staggerKeyword, (std::string)"layer", + SegmentationParameter::NoUnit, true); +} + +/// Default constructor used by derived classes passing an existing decoder +CartesianGridXYStaggered::CartesianGridXYStaggered(const BitFieldCoder* decode) : + CartesianGrid(decode) +{ + // define type and description + _type = "CartesianGridXYStaggered"; + _description = "Cartesian segmentation in the local XY-plane, with options for staggering"; + + // register all necessary parameters + registerParameter("grid_size_x", "Cell size in X", _gridSizeX, 1., SegmentationParameter::LengthUnit); + registerParameter("grid_size_y", "Cell size in Y", _gridSizeY, 1., SegmentationParameter::LengthUnit); + registerParameter("offset_x", "Cell offset in X", _offsetX, 0., SegmentationParameter::LengthUnit, true); + registerParameter("offset_y", "Cell offset in Y", _offsetY, 0., SegmentationParameter::LengthUnit, true); + registerParameter("stagger_x", "Option to stagger the layers in x (ie, add grid_size_x/2 to offset_x for odd layers)", _staggerX, 0, + SegmentationParameter::NoUnit, true); + registerParameter("stagger_y", "Option to stagger the layers in y (ie, add grid_size_y/2 to offset_y for odd layers)", _staggerY, 0, + SegmentationParameter::NoUnit, true); + registerIdentifier("identifier_x", "Cell ID identifier for X", _xId, "x"); + registerIdentifier("identifier_y", "Cell ID identifier for Y", _yId, "y"); + registerParameter("stagger_keyword", "Volume ID identifier used for determining which volumes to stagger", _staggerKeyword, (std::string)"layer", + SegmentationParameter::NoUnit, true); +} + +/// destructor +CartesianGridXYStaggered::~CartesianGridXYStaggered() { + +} + +/// determine the position based on the cell ID +Vector3D CartesianGridXYStaggered::position(const CellID& cID) const { + Vector3D cellPosition; + if (_staggerX || _staggerY){ + int layer= _decoder->get(cID,_staggerKeyword); + cellPosition.X = binToPosition( _decoder->get(cID,_xId ), _gridSizeX, _offsetX+_staggerX*_gridSizeX*(layer%2)/2.); + cellPosition.Y = binToPosition( _decoder->get(cID,_yId ), _gridSizeY, _offsetY+_staggerY*_gridSizeY*(layer%2)/2.); + } else { + cellPosition.X = binToPosition( _decoder->get(cID,_xId ), _gridSizeX, _offsetX); + cellPosition.Y = binToPosition( _decoder->get(cID,_yId ), _gridSizeY, _offsetY); + } + return cellPosition; +} + +/// determine the cell ID based on the position + CellID CartesianGridXYStaggered::cellID(const Vector3D& localPosition, const Vector3D& /* globalPosition */, const VolumeID& vID) const { + CellID cID = vID ; + if (_staggerX || _staggerY){ + int layer= _decoder->get(cID,_staggerKeyword); + _decoder->set( cID,_xId, positionToBin(localPosition.X, _gridSizeX, _offsetX+_staggerX*_gridSizeX*(layer%2)/2) ); + _decoder->set( cID,_yId, positionToBin(localPosition.Y, _gridSizeY, _offsetY+_staggerY*_gridSizeY*(layer%2)/2) ); + } else { + _decoder->set( cID,_xId, positionToBin(localPosition.X, _gridSizeX, _offsetX)); + _decoder->set( cID,_yId, positionToBin(localPosition.Y, _gridSizeY, _offsetY)); + } + return cID ; +} + + +std::vector CartesianGridXYStaggered::cellDimensions(const CellID& cellID) const { + return {_gridSizeX, _gridSizeY}; +} + + +} /* namespace DDSegmentation */ +} /* namespace dd4hep */ + +// This is done DDCore/src/plugins/ReadoutSegmentations.cpp so the plugin is not part of libDDCore +// needs also #include "DD4hep/Factories.h" +// DECLARE_SEGMENTATION(CartesianGridXYStaggered,dd4hep::create_segmentation) diff --git a/DDCore/src/segmentations/HexGrid.cpp b/DDCore/src/segmentations/HexGrid.cpp new file mode 100644 index 000000000..f051a8f61 --- /dev/null +++ b/DDCore/src/segmentations/HexGrid.cpp @@ -0,0 +1,149 @@ +/* + * AIDA Detector description implementation + * + * Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) + * All rights reserved. + * + * For the licensing terms see $DD4hepINSTALL/LICENSE. + * For the list of contributors see $DD4hepINSTALL/doc/CREDITS. + * + * HexGrid.cpp + * + * Created on: August 9, 2023 + * Author: Sebouh J. Paul, UC Riverside + */ +#include "DD4hep/Factories.h" +#include "DDSegmentation/HexGrid.h" + +namespace dd4hep { + namespace DDSegmentation { + + /// Default constructor used by derived classes passing the encoding string + HexGrid::HexGrid(const std::string& cellEncoding) : + Segmentation(cellEncoding) { + _type = "HexGridXY"; + _description = "Hexagonal segmentation in the local XY-plane"; + + // register all necessary parameters + registerParameter("stagger", "stagger mode", _stagger, 1); + registerParameter("side_length", "Cell size", _sideLength, 1., SegmentationParameter::LengthUnit); + registerParameter("offset_x", "Cell offset in X", _offsetX, 0., SegmentationParameter::LengthUnit, true); + registerParameter("offset_y", "Cell offset in Y", _offsetY, 0., SegmentationParameter::LengthUnit, true); + registerIdentifier("identifier_x", "Cell ID identifier for X", _xId, "x"); + registerIdentifier("identifier_y", "Cell ID identifier for Y", _yId, "y"); + registerParameter("stagger_keyword", "Volume ID identifier used for determining which volumes to stagger", _staggerKeyword, (std::string)"layer", SegmentationParameter::NoUnit, true); + } + + /// Default constructor used by derived classes passing an existing decoder + HexGrid::HexGrid(const BitFieldCoder* decode) : Segmentation(decode) { + // define type and description + _type = "HexGridXY"; + _description = "Hexagonal segmentation in the local XY-plane"; + + // register all necessary parameters + registerParameter("stagger", "stagger mode", _stagger, 1); + registerParameter("side_length", "Cell size", _sideLength, 1., SegmentationParameter::LengthUnit); + registerParameter("offset_x", "Cell offset in X", _offsetX, 0., SegmentationParameter::LengthUnit, true); + registerParameter("offset_y", "Cell offset in Y", _offsetY, 0., SegmentationParameter::LengthUnit, true); + registerIdentifier("identifier_x", "Cell ID identifier for X", _xId, "x"); + registerIdentifier("identifier_y", "Cell ID identifier for Y", _yId, "y"); + registerParameter("stagger_keyword", "Volume ID identifier used for determining which volumes to stagger", _staggerKeyword, (std::string)"layer", SegmentationParameter::NoUnit, true); + + } + + /// Destructor + HexGrid::~HexGrid() { + } + + /// determine the position based on the cell ID + Vector3D HexGrid::position(const CellID& cID) const { + int layer=0; + if (_stagger) layer= _decoder->get(cID,_staggerKeyword); + + Vector3D cellPosition; + cellPosition.X = _decoder->get(cID,_xId )*1.5*_sideLength+_offsetX+_sideLength/2.; + cellPosition.Y = _decoder->get(cID,_yId )*std::sqrt(3)/2.*_sideLength+ _offsetY+_sideLength*std::sqrt(3)/2.; + if (_stagger==0) + cellPosition.X+=_sideLength; + else if (_stagger==1) + cellPosition.X+=(layer%3)*_sideLength; + else if (_stagger==2){ + switch (layer%4){ + case 0: + cellPosition.X-=0.75*_sideLength; + break; + case 1: + cellPosition.Y+=std::sqrt(3)/4*_sideLength; + break; + case 2: + cellPosition.Y-=std::sqrt(3)/4*_sideLength; + break; + case 3: + cellPosition.X+=0.75*_sideLength; + break; + } + } + return cellPosition; + } + + inline double positive_modulo(double i, double n) { + return std::fmod(std::fmod(i,n) + n,n); + } + + + /// determine the cell ID based on the position + CellID HexGrid::cellID(const Vector3D& localPosition, const Vector3D& /* globalPosition */, const VolumeID& vID) const { + CellID cID = vID ; + int layer=0; + if (_stagger) layer= _decoder->get(cID,_staggerKeyword); + + double x=localPosition.X-_offsetX; + double y=localPosition.Y-_offsetY; + if (_stagger==0) + x-=_sideLength; + else if (_stagger==1) + x-=(layer%3)*_sideLength; + else if (_stagger==2){ + switch (layer%4){ + case 0: + x+=0.75*_sideLength; + break; + case 1: + y-=std::sqrt(3)/4*_sideLength; + break; + case 2: + y+=std::sqrt(3)/4*_sideLength; + break; + case 3: + x-=0.75*_sideLength; + break; + } + } + + double a=positive_modulo(y/(std::sqrt(3)*_sideLength),1); + double b=positive_modulo(x/(3*_sideLength),1); + int ix = std::floor(x/(3*_sideLength/2.))+ + (b<0.5)*(-abs(a-.5)<(b-.5)*3)+(b>0.5)*(abs(a-.5)-.5<(b-1)*3); + int iy=std::floor(y/(std::sqrt(3)*_sideLength/2.)); + iy-=(ix+iy)&1; + + _decoder->set( cID,_xId, ix ); + _decoder->set( cID,_yId, iy ); + return cID ; + } + + std::vector HexGrid::cellDimensions(const CellID&) const { +#if __cplusplus >= 201103L + return {2*_sideLength, std::sqrt(3)*_sideLength}; +#else + std::vector cellDims(2,0.0); + cellDims[0] = 2*_sideLength; + cellDims[1] = std::sqrt(3)*_sideLength; + return cellDims; +#endif +} + + } /* namespace DDSegmentation */ +} /* namespace dd4hep */ + +DECLARE_SEGMENTATION(HexGrid, create_segmentation) From 1962f7d1ace4484efb8886d66a6759a83c5107a3 Mon Sep 17 00:00:00 2001 From: Dhevan Gangadharan <43478603+dhevang@users.noreply.github.com> Date: Wed, 20 Sep 2023 14:16:58 -0500 Subject: [PATCH 17/21] dumpBField: Extend usage to asymmetric ranges. (#1170) Co-authored-by: Andre Sailer --- UtilityApps/src/dumpBfield.cpp | 65 ++++++++++++++++++++++++++++------ 1 file changed, 55 insertions(+), 10 deletions(-) diff --git a/UtilityApps/src/dumpBfield.cpp b/UtilityApps/src/dumpBfield.cpp index 39d8fb65a..1b582c2d3 100644 --- a/UtilityApps/src/dumpBfield.cpp +++ b/UtilityApps/src/dumpBfield.cpp @@ -29,8 +29,9 @@ using namespace dd4hep::detail; static int invoke_dump_B_field(int argc, char** argv ){ if( argc != 8 ) { - std::cout << " usage: dumpBfield compact.xml x y z dx dy dz [in cm]" << std::endl - << " will dump the B-field in volume [-x:x,-y:y,-z,z] with steps [dx,dy,dz] " + std::cout << " usage: dumpBfield compact.xml xmin[:xmax] ymin[:ymax] zmin[:zmax] dx dy dz [in cm]" << std::endl + << " will dump the B-field in volume (xmin:xmax, ymin:ymax, zmin:zmax) with steps (dx,dy,dz). All values are in cm." + << " If a single value is given for a range, symmetric boundaries are used" << std::endl ; exit(1) ; @@ -41,12 +42,56 @@ static int invoke_dump_B_field(int argc, char** argv ){ std::stringstream sstr ; sstr << argv[2] << " " << argv[3] << " " << argv[4] << " " << argv[5] << " " << argv[6] << " " << argv[7] ; - float xRange , yRange , zRange , dx , dy, dz ; - sstr >> xRange >> yRange >> zRange >> dx >> dy >> dz; + std::string RangeX , RangeY , RangeZ; + float dx , dy, dz ; - xRange *= dd4hep::cm; - yRange *= dd4hep::cm; - zRange *= dd4hep::cm; + sstr >> RangeX >> RangeY >> RangeZ >> dx >> dy >> dz; + + size_t colon_posX = RangeX.find(':'); + size_t colon_posY = RangeY.find(':'); + size_t colon_posZ = RangeZ.find(':'); + + float minX=0, maxX=0, minY=0, maxY=0, minZ=0, maxZ=0; + + if( colon_posX == std::string::npos ) { + std::cout << "X Interval not specified as xmin:xmax" << std::endl + << " setting xmin = -xmax " << std::endl; + maxX = std::stof( RangeX ); + minX = -maxX; + } + else { + minX = std::stof( RangeX.substr(0, colon_posX) ); + maxX = std::stof( RangeX.substr(colon_posX+1) ); + } + + if( colon_posY == std::string::npos ) { + std::cout << "Y Interval not specified as ymin:ymax" << std::endl + << " setting ymin = -ymax " << std::endl; + maxY = std::stof( RangeY ); + minY = -maxY; + } + else { + minY = std::stof( RangeY.substr(0, colon_posY) ); + maxY = std::stof( RangeY.substr(colon_posY+1) ); + } + +if( colon_posZ == std::string::npos ) { + std::cout << "Z Interval not specified as zmin:zmax" << std::endl + << " setting zmin = -zmax " << std::endl; + maxZ = std::stof( RangeZ ); + minZ = -maxZ; + } + else { + minZ = std::stof( RangeZ.substr(0, colon_posZ) ); + maxZ = std::stof( RangeZ.substr(colon_posZ+1) ); + } + + minX *= dd4hep::cm; + maxX *= dd4hep::cm; + minY *= dd4hep::cm; + maxY *= dd4hep::cm; + minZ *= dd4hep::cm; + maxZ *= dd4hep::cm; dx *= dd4hep::cm; dy *= dd4hep::cm; dz *= dd4hep::cm; @@ -57,9 +102,9 @@ static int invoke_dump_B_field(int argc, char** argv ){ printf("#######################################################################################################\n"); printf(" x[cm] y[cm] z[cm] Bx[Tesla] By[Tesla] Bz[Tesla] \n"); - for( float x = -xRange ; x <=xRange ; x += dx ){ - for( float y = -yRange ; y <=yRange ; y += dy ){ - for( float z = -zRange ; z <=zRange ; z += dz ){ + for( float x = minX ; x <= maxX ; x += dx ){ + for( float y = minY ; y <= maxY ; y += dy ){ + for( float z = minZ ; z <= maxZ ; z += dz ){ double posV[3] = { x, y, z } ; double bfieldV[3] ; From 0c222649d04686a5e915da07c5cca8c7d95e4b74 Mon Sep 17 00:00:00 2001 From: Andre Sailer Date: Wed, 11 Oct 2023 14:44:22 +0200 Subject: [PATCH 18/21] G4VTouchable: for Geant4 11.1.ref09 cannot forward declare the class any more --- DDG4/include/DDG4/Geant4SensDetAction.h | 2 +- DDG4/include/DDG4/Geant4TouchableHandler.h | 3 ++- DDG4/include/DDG4/Geant4VolumeManager.h | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/DDG4/include/DDG4/Geant4SensDetAction.h b/DDG4/include/DDG4/Geant4SensDetAction.h index a192bc366..c15040281 100644 --- a/DDG4/include/DDG4/Geant4SensDetAction.h +++ b/DDG4/include/DDG4/Geant4SensDetAction.h @@ -20,6 +20,7 @@ // Geant4 include files #include +#include // C/C++ include files #include @@ -28,7 +29,6 @@ class G4HCofThisEvent; class G4Step; class G4Event; -class G4VTouchable; class G4TouchableHistory; class G4VHitsCollection; class G4VReadOutGeometry; diff --git a/DDG4/include/DDG4/Geant4TouchableHandler.h b/DDG4/include/DDG4/Geant4TouchableHandler.h index 042f30405..0be5a58c1 100644 --- a/DDG4/include/DDG4/Geant4TouchableHandler.h +++ b/DDG4/include/DDG4/Geant4TouchableHandler.h @@ -13,13 +13,14 @@ #ifndef DDG4_GEANT4TOUCHABLEHANDLER_H #define DDG4_GEANT4TOUCHABLEHANDLER_H +#include + // C/C++ include files #include #include // Forward declarations class G4VPhysicalVolume; -class G4VTouchable; class G4Step; /// Namespace for the AIDA detector description toolkit diff --git a/DDG4/include/DDG4/Geant4VolumeManager.h b/DDG4/include/DDG4/Geant4VolumeManager.h index 6cbee9517..02027ad3e 100644 --- a/DDG4/include/DDG4/Geant4VolumeManager.h +++ b/DDG4/include/DDG4/Geant4VolumeManager.h @@ -18,8 +18,8 @@ #include #include +#include // Geant4 forward declarations -class G4VTouchable; class G4VPhysicalVolume; From fbc39bbbcb1e1590dd270dff5ee8cd66879d5a9a Mon Sep 17 00:00:00 2001 From: Markus Frank Date: Mon, 9 Oct 2023 16:28:57 +0200 Subject: [PATCH 19/21] Allow to load CAD files with relative path w/r to declaring xml file (Issue 1166) --- DDCAD/src/plugins/CADPlugins.cpp | 31 +++++++++++++++++-- examples/DDCAD/CMakeLists.txt | 2 +- .../compact/Check_Shape_RelativePath.xml | 30 ++++++++++++++++++ 3 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 examples/DDCAD/compact/Check_Shape_RelativePath.xml diff --git a/DDCAD/src/plugins/CADPlugins.cpp b/DDCAD/src/plugins/CADPlugins.cpp index 8a646ebe9..17f9c037a 100644 --- a/DDCAD/src/plugins/CADPlugins.cpp +++ b/DDCAD/src/plugins/CADPlugins.cpp @@ -20,11 +20,36 @@ #include // C/C++ include files +#include using namespace std; using namespace dd4hep; using namespace dd4hep::detail; +/// If the path to the CAD file does not directly exist try to resolve it: +static string resolve_path(xml_h e, const string& file) { + error_code errc; + std::string fname; + /// Use the xml utilities in the DocumentHandler to resolve the relative path + if ( file.length() > 7 && file.substr(0,7) == "file://" ) + fname = file.substr(7); + else + fname = file; + if ( !filesystem::exists(fname, errc) ) { + string fn = xml::DocumentHandler::system_path(e, fname); + if ( fn.length() > 7 && fn.substr(0,7) == "file://" ) + fn = fn.substr(7); + if ( !std::filesystem::exists(fn, errc) ) { + auto fp = filesystem::path(xml::DocumentHandler::system_path(e)).parent_path(); + except("CAD_Shape","+++ CAD file: %s (= %s + %s) is not accessible [%d: %s]", + fn.c_str(), fp.c_str(), fname.c_str(), + errc.value(), errc.message().c_str()); + } + return fn; + } + return fname; +} + static void* read_CAD_Volume(Detector& dsc, int argc, char** argv) { string fname; double scale = 1.0; @@ -61,7 +86,7 @@ DECLARE_DD4HEP_CONSTRUCTOR(DD4hep_read_CAD_volumes,read_CAD_Volume) static Handle create_CAD_Shape(Detector& dsc, xml_h e) { xml_elt_t elt(e); cad::ASSIMPReader rdr(dsc); - string fname = elt.attr(_U(ref)); + string fname = resolve_path(e, elt.attr(_U(ref))); long flags = elt.hasAttr(_U(flags)) ? elt.attr(_U(flags)) : 0; double unit = elt.hasAttr(_U(unit)) ? elt.attr(_U(unit)) : dd4hep::cm; @@ -97,7 +122,7 @@ DECLARE_XML_SHAPE(CAD_Shape__shape_constructor,create_CAD_Shape) static Handle create_CAD_Assembly(Detector& dsc, xml_h e) { xml_elt_t elt(e); - string fname = elt.attr(_U(ref)); + string fname = resolve_path(e, elt.attr(_U(ref))); double unit = elt.hasAttr(_U(unit)) ? elt.attr(_U(unit)) : dd4hep::cm; auto volumes = cad::ASSIMPReader(dsc).readVolumes(fname, unit); if ( volumes.empty() ) { @@ -159,8 +184,8 @@ DECLARE_XML_VOLUME(CAD_Assembly__volume_constructor,create_CAD_Assembly) */ static Handle create_CAD_Volume(Detector& dsc, xml_h e) { xml_elt_t elt(e); - string fname = elt.attr(_U(ref)); double unit = elt.attr(_U(unit)); + string fname = resolve_path(e, elt.attr(_U(ref))); long flags = elt.hasAttr(_U(flags)) ? elt.attr(_U(flags)) : 0; cad::ASSIMPReader rdr(dsc); diff --git a/examples/DDCAD/CMakeLists.txt b/examples/DDCAD/CMakeLists.txt index 91f2d8a2f..0d9e38ec7 100644 --- a/examples/DDCAD/CMakeLists.txt +++ b/examples/DDCAD/CMakeLists.txt @@ -72,7 +72,7 @@ endforeach() # # Multi-shape tests # Not working: OBJ_spider -list(APPEND DDCAD_Tests_MV COB_dwarf MS3D_jeep) +list(APPEND DDCAD_Tests_MV COB_dwarf MS3D_jeep RelativePath) foreach (test ${DDCAD_Tests_MV}) dd4hep_add_test_reg( DDCAD_Check_Shape_${test} COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_DDCAD.sh" diff --git a/examples/DDCAD/compact/Check_Shape_RelativePath.xml b/examples/DDCAD/compact/Check_Shape_RelativePath.xml new file mode 100644 index 000000000..39b1627b2 --- /dev/null +++ b/examples/DDCAD/compact/Check_Shape_RelativePath.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + From 8e1d0be969e6401a67cd2aa4eb3bdb00db44e86b Mon Sep 17 00:00:00 2001 From: Alvaro Tolosa Delgado Date: Mon, 16 Oct 2023 20:48:35 +0200 Subject: [PATCH 20/21] Typo in printout fixed --- DDG4/python/DDSim/Helper/Gun.py | 2 +- DDTest/python/userSteeringFile.PY | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DDG4/python/DDSim/Helper/Gun.py b/DDG4/python/DDSim/Helper/Gun.py index 608b41f7c..c3cfb7cf7 100644 --- a/DDG4/python/DDSim/Helper/Gun.py +++ b/DDG4/python/DDSim/Helper/Gun.py @@ -35,7 +35,7 @@ def __init__(self): self.momentumMin = 0 * GeV self._momentumMax_EXTRA = {'help': "Maximal momentum when using distribution (default = 0.0)"} self.momentumMax = 10 * GeV - self._energy_EXTRA = {'help': "The kinetic energy for the particle gun.\n\n" + self._energy_EXTRA = {'help': "Total energy (including mass) for the particle gun.\n\n" "If not None, it will overwrite the setting of momentumMin and momentumMax"} self.energy = None diff --git a/DDTest/python/userSteeringFile.PY b/DDTest/python/userSteeringFile.PY index e21e6e66c..11a8eee6e 100644 --- a/DDTest/python/userSteeringFile.PY +++ b/DDTest/python/userSteeringFile.PY @@ -211,7 +211,7 @@ SIM.gun.direction = (0, 0, 1) ## SIM.gun.distribution = None -## The kinetic energy for the particle gun. +## Total energy (including mass) for the particle gun. ## ## If not None, it will overwrite the setting of momentumMin and momentumMax SIM.gun.energy = None From 88ed20d5fbf8970852ac6f462ccc63f8a626dc5d Mon Sep 17 00:00:00 2001 From: Markus Frank Date: Wed, 18 Oct 2023 11:29:28 +0200 Subject: [PATCH 21/21] Allow for XML processing of files relative to xml tag location (See issue https://github.com/AIDASoft/DD4hep/issues/1180 for details) --- DDCore/src/plugins/Compact2Objects.cpp | 33 ++++++++++++++++--- .../ClientTests/compact/IncludePlugins.xml | 4 +++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/DDCore/src/plugins/Compact2Objects.cpp b/DDCore/src/plugins/Compact2Objects.cpp index aae992573..20a286f2b 100644 --- a/DDCore/src/plugins/Compact2Objects.cpp +++ b/DDCore/src/plugins/Compact2Objects.cpp @@ -50,9 +50,10 @@ #include // C/C++ include files -#include +#include #include #include +#include #include using namespace std; @@ -1443,17 +1444,38 @@ template <> void Converter::operator()(xml_h element) const { template <> void Converter::operator()(xml_h element) const { string base = xml::DocumentHandler::system_directory(element); string file = element.attr(_U(ref)); - vector argv{&file[0],&base[0]}; + vector argv{&file[0], &base[0]}; description.apply("DD4hep_JsonProcessor",int(argv.size()), &argv[0]); } /// Read alignment entries from a seperate file in one of the include sections of the geometry template <> void Converter::operator()(xml_h element) const { + PrintLevel level = s_debug.includes ? ALWAYS : DEBUG; string fname = element.attr(_U(ref)); - if ( s_debug.includes ) { - printout(ALWAYS, "Compact","++ Processing xml document %s.", fname.c_str()); + size_t idx = fname.find("://"); + std::error_code ec; + + if ( idx == string::npos && filesystem::exists(fname, ec) ) { + // Regular file without protocol specification + printout(level, "Compact","++ Processing xml document %s.", fname.c_str()); + this->description.fromXML(fname); + } + else if ( idx == string::npos ) { + // File relative to location of xml tag (protocol specification not possible) + string location = xml::DocumentHandler::system_path(element, fname); + printout(level, "Compact","++ Processing xml document %s.", location.c_str()); + this->description.fromXML(location); + } + else if ( idx > 0 ) { + // File with protocol specification: must trust the location and the parser capabilities + printout(level, "Compact","++ Processing xml document %s.", fname.c_str()); + this->description.fromXML(fname); + } + else { + // Are there any other possibilities ? + printout(level, "Compact","++ Processing xml document %s.", fname.c_str()); + this->description.fromXML(fname); } - this->description.fromXML(fname); } /// Read material entries from a seperate file in one of the include sections of the geometry @@ -1716,6 +1738,7 @@ template <> void Converter::operator()(xml_h element) const { } xml_coll_t(compact, _U(plugins)).for_each(_U(plugin), Converter (description)); xml_coll_t(compact, _U(plugins)).for_each(_U(include), Converter (description)); + xml_coll_t(compact, _U(plugins)).for_each(_U(xml), Converter (description)); } #ifdef _WIN32 diff --git a/examples/ClientTests/compact/IncludePlugins.xml b/examples/ClientTests/compact/IncludePlugins.xml index b527abfb0..08a00248b 100644 --- a/examples/ClientTests/compact/IncludePlugins.xml +++ b/examples/ClientTests/compact/IncludePlugins.xml @@ -42,6 +42,10 @@ + + + +