From 9726f40494acbe9ddcdc6667e54340a683f341aa Mon Sep 17 00:00:00 2001 From: Markus FRANK <Markus.Frank@cern.ch> Date: Sat, 31 Oct 2020 00:39:38 +0100 Subject: [PATCH] Try to fix reflections for volumes and assemblies --- DDCore/include/DD4hep/DetectorImp.h | 3 + DDCore/include/Parsers/detail/Dimension.h | 4 + DDCore/include/Parsers/detail/Dimension.imp | 2 + DDCore/include/XML/UnicodeValues.h | 1 + DDCore/src/DetectorImp.cpp | 39 +++--- DDCore/src/Volumes.cpp | 20 +-- DDEve/src/Display.cpp | 3 + DDEve/src/Utilities.cpp | 2 - DDG4/include/DDG4/Geant4Converter.h | 20 +-- DDG4/include/DDG4/Geant4HierarchyDump.h | 16 ++- .../Geant4DetectorGeometryConstruction.cpp | 44 +++--- DDG4/python/DDG4.py | 4 +- DDG4/src/Geant4Converter.cpp | 66 ++++++--- DDG4/src/Geant4HierarchyDump.cpp | 54 ++++---- DDG4/src/Geant4ParticleGenerator.cpp | 20 +-- examples/ClientTests/CMakeLists.txt | 2 +- .../compact/NestedBoxReflection.xml | 56 ++++++-- .../ClientTests/scripts/Check_reflection.py | 95 ++++++++++++- .../ClientTests/scripts/Check_shape_vis.mac | 4 +- examples/ClientTests/scripts/SiliconBlock.py | 6 +- .../src/NestedBoxReflection_geo.cpp | 129 +++++++++++------- 21 files changed, 391 insertions(+), 199 deletions(-) diff --git a/DDCore/include/DD4hep/DetectorImp.h b/DDCore/include/DD4hep/DetectorImp.h index 6a5e397ca..c7c2f6e97 100644 --- a/DDCore/include/DD4hep/DetectorImp.h +++ b/DDCore/include/DD4hep/DetectorImp.h @@ -93,6 +93,9 @@ namespace dd4hep { /// Local method (no interface): Load volume manager. void imp_loadVolumeManager(); + /// Build reflections the ROOT way. To be called once the geometry is closed + void buildReflections(); + /// Default constructor used by ROOT I/O DetectorImp(); diff --git a/DDCore/include/Parsers/detail/Dimension.h b/DDCore/include/Parsers/detail/Dimension.h index c3a201e34..ceed06f94 100644 --- a/DDCore/include/Parsers/detail/Dimension.h +++ b/DDCore/include/Parsers/detail/Dimension.h @@ -467,6 +467,10 @@ namespace dd4hep { /// Access attribute values: length double length() const; + /// Access attribute values: level + int level() const; + /// Access attribute values: level + int level(int default_value) const; /// Access attribute values: width double width() const; /// Access attribute values: height diff --git a/DDCore/include/Parsers/detail/Dimension.imp b/DDCore/include/Parsers/detail/Dimension.imp index e0c1fbc14..d7dff15e5 100644 --- a/DDCore/include/Parsers/detail/Dimension.imp +++ b/DDCore/include/Parsers/detail/Dimension.imp @@ -21,6 +21,8 @@ XML_ATTR_ACCESSOR(int, id) XML_ATTR_ACCESSOR_INT(id) +XML_ATTR_ACCESSOR(int, level) +XML_ATTR_ACCESSOR_INT(level) XML_ATTR_ACCESSOR(bool, combineHits) XML_ATTR_ACCESSOR(int, station) diff --git a/DDCore/include/XML/UnicodeValues.h b/DDCore/include/XML/UnicodeValues.h index 9cfbbf03e..083656939 100644 --- a/DDCore/include/XML/UnicodeValues.h +++ b/DDCore/include/XML/UnicodeValues.h @@ -254,6 +254,7 @@ UNICODE (layers); UNICODE (description); UNICODE (lccdd); UNICODE (length); +UNICODE (level); UNICODE (limit); UNICODE (limits); UNICODE (limitset); diff --git a/DDCore/src/DetectorImp.cpp b/DDCore/src/DetectorImp.cpp index 2ec4b8e1d..60306c36d 100644 --- a/DDCore/src/DetectorImp.cpp +++ b/DDCore/src/DetectorImp.cpp @@ -174,6 +174,8 @@ DetectorImp::DetectorImp(const string& name) //if ( gGeoManager ) delete gGeoManager; m_manager = new TGeoManager(name.c_str(), "Detector Geometry"); { + m_manager->AddNavigator(); + m_manager->SetCurrentNavigator(0); gGeoManager = m_manager; #if 1 //FIXME: eventually this should be set to 1 - needs fixes in examples ... TGeoElementTable* table = m_manager->GetElementTable(); @@ -648,23 +650,25 @@ namespace { } } }; - void build_reflections(TGeoManager* mgr) { - TGeoIterator next(mgr->GetTopVolume()); - TGeoNode *node; - while ((node=next())) { - TGeoMatrix* m = node->GetMatrix(); - if (m->IsReflection()) { - Volume vol(node->GetVolume()); - TGeoMatrix* mclone = new TGeoCombiTrans(*m); - mclone->RegisterYourself(); - // Reflect just the rotation component - mclone->ReflectZ(kFALSE, kTRUE); - TGeoNodeMatrix* nodematrix = (TGeoNodeMatrix*)node; - nodematrix->SetMatrix(mclone); - printout(INFO,"Detector","Reflecting volume: %s ",vol.name()); - Volume refl = vol.reflect(vol.sensitiveDetector()); - node->SetVolume(refl.ptr()); - } +} + +/// Build reflections the ROOT way. To be called once the geometry is closed +void DetectorImp::buildReflections() { + TGeoIterator next(manager().GetTopVolume()); + TGeoNode *node; + while ((node=next())) { + TGeoMatrix* m = node->GetMatrix(); + if (m->IsReflection()) { + Volume vol(node->GetVolume()); + TGeoMatrix* mclone = new TGeoCombiTrans(*m); + mclone->RegisterYourself(); + // Reflect just the rotation component + mclone->ReflectZ(kFALSE, kTRUE); + TGeoNodeMatrix* nodematrix = (TGeoNodeMatrix*)node; + nodematrix->SetMatrix(mclone); + printout(INFO,"Detector","Reflecting volume: %s ",vol.name()); + Volume refl = vol.reflect(vol.sensitiveDetector()); + node->SetVolume(refl.ptr()); } } } @@ -690,7 +694,6 @@ void DetectorImp::endDocument(bool close_geometry) { /// Since we allow now for anonymous shapes, /// we will rename them to use the name of the volume they are assigned to mgr->CloseGeometry(); - build_reflections(mgr); } ShapePatcher patcher(m_volManager, m_world); patcher.patchShapes(); diff --git a/DDCore/src/Volumes.cpp b/DDCore/src/Volumes.cpp index bb44dcfe8..454abad2a 100644 --- a/DDCore/src/Volumes.cpp +++ b/DDCore/src/Volumes.cpp @@ -266,6 +266,13 @@ namespace { } return vol; } + + int get_copy_number(TGeoVolume* par) { + TObjArray* a = par ? par->GetNodes() : 0; + int copy_nr = (a ? a->GetEntries() : 0); + return copy_nr; + } + } /// Default constructor @@ -568,12 +575,6 @@ Volume Volume::divide(const std::string& divname, int iaxis, int ndiv, return nullptr; } -Int_t get_copy_number(TGeoVolume* par) { - TObjArray* a = par ? par->GetNodes() : 0; - Int_t copy_nr = (a ? a->GetEntries() : 0); - return copy_nr; -} - PlacedVolume _addNode(TGeoVolume* par, TGeoVolume* daughter, int id, TGeoMatrix* transform) { TGeoVolume* parent = par; if ( !parent ) { @@ -608,7 +609,6 @@ PlacedVolume _addNode(TGeoVolume* par, TGeoVolume* daughter, int id, TGeoMatrix* Double_t det = r[0]*r[4]*r[8] + r[3]*r[7]*r[2] + r[6]*r[1]*r[5] - r[2]*r[4]*r[6] - r[5]*r[7]*r[0] - r[8]*r[1]*r[3]; - /// We have a left handed matrix (determinant < 0). This is a reflection! if ( det < 0e0 ) { transform->SetBit(TGeoMatrix::kGeoReflection); @@ -1014,14 +1014,14 @@ std::string dd4hep::toStringMesh(PlacedVolume place, int prec) { if ( vol->IsA() == TGeoVolumeAssembly::Class() ) { - for(Int_t i=0; i<vol->GetNdaughters(); ++i) { + for(int i=0; i<vol->GetNdaughters(); ++i) { os << toStringMesh(vol->GetNode(i), prec) << endl; } return os.str(); } // Prints shape parameters - Int_t nvert = 0, nsegs = 0, npols = 0; + int nvert = 0, nsegs = 0, npols = 0; sol->GetMeshNumbers(nvert, nsegs, npols); Double_t* points = new Double_t[3*nvert]; sol->SetPoints(points); @@ -1032,7 +1032,7 @@ std::string dd4hep::toStringMesh(PlacedVolume place, int prec) { << " N(mesh)=" << sol->GetNmeshVertices() << " N(vert)=" << nvert << " N(seg)=" << nsegs << " N(pols)=" << npols << endl; - for(Int_t i=0; i<nvert; ++i) { + for(int i=0; i<nvert; ++i) { Double_t* p = points + 3*i; Double_t global[3], local[3] = {p[0], p[1], p[2]}; mat->LocalToMaster(local, global); diff --git a/DDEve/src/Display.cpp b/DDEve/src/Display.cpp index c2344b352..7383a4919 100644 --- a/DDEve/src/Display.cpp +++ b/DDEve/src/Display.cpp @@ -46,6 +46,7 @@ #include "TEveCompound.h" #include "TEveBoxSet.h" #include "TEvePointSet.h" +#include "TEveGeoShape.h" #include "TEveTrackPropagator.h" #include "TGeoManager.h" @@ -94,6 +95,8 @@ Display::Display(TEveManager* eve) EvePgonSetProjectedContextMenu::install(this); ElementListContextMenu::install(this); m_detDesc = &Detector::getInstance(); + TEveGeoShape::GetGeoMangeur()->AddNavigator(); + TEveGeoShape::GetGeoMangeur()->SetCurrentNavigator(0); m_evtHandler = new GenericEventHandler(); m_evtHandler->Subscribe(this); m_detDesc->addExtension<Display>(this); diff --git a/DDEve/src/Utilities.cpp b/DDEve/src/Utilities.cpp index 88b357acc..f5d3d09a0 100644 --- a/DDEve/src/Utilities.cpp +++ b/DDEve/src/Utilities.cpp @@ -195,8 +195,6 @@ std::pair<bool,TEveElement*> Utilities::LoadDetElement(DetElement de,int levels, if (pv.isValid()) { TGeoNode* n = pv.ptr(); TGeoMatrix* matrix = n->GetMatrix(); - gGeoManager = 0; - gGeoManager = new TGeoManager(); std::pair<bool,TEveElement*> e = createEveShape(0, levels, parent, n, *matrix, de.name()); TEveElementList* list = dynamic_cast<TEveElementList*>(e.second); if ( list ) { diff --git a/DDG4/include/DDG4/Geant4Converter.h b/DDG4/include/DDG4/Geant4Converter.h index a71b6810e..d5e097178 100644 --- a/DDG4/include/DDG4/Geant4Converter.h +++ b/DDG4/include/DDG4/Geant4Converter.h @@ -32,24 +32,26 @@ namespace dd4hep { class Geant4Converter : public detail::GeoHandler, public Geant4Mapping { public: /// Property: Flag to debug materials during conversion mechanism - bool debugMaterials = false; + bool debugMaterials = false; /// Property: Flag to debug elements during conversion mechanism - bool debugElements = false; + bool debugElements = false; /// Property: Flag to debug shapes during conversion mechanism - bool debugShapes = false; + bool debugShapes = false; /// Property: Flag to debug volumes during conversion mechanism - bool debugVolumes = false; + bool debugVolumes = false; /// Property: Flag to debug placements during conversion mechanism - bool debugPlacements = false; + bool debugPlacements = false; + /// Property: Flag to debug reflections during conversion mechanism + bool debugReflections = false; /// Property: Flag to debug regions during conversion mechanism - bool debugRegions = false; + bool debugRegions = false; /// Property: Flag to debug surfaces during conversion mechanism - bool debugSurfaces = false; + bool debugSurfaces = false; /// Property: Flag to dump all placements after the conversion procedure - bool printPlacements = false; + bool printPlacements = false; /// Property: Flag to dump all sensitives after the conversion procedure - bool printSensitives = false; + bool printSensitives = false; /// Property: Check geometrical overlaps for volume placements and G4 imprints bool checkOverlaps; diff --git a/DDG4/include/DDG4/Geant4HierarchyDump.h b/DDG4/include/DDG4/Geant4HierarchyDump.h index d9c3305b4..e28ee2400 100644 --- a/DDG4/include/DDG4/Geant4HierarchyDump.h +++ b/DDG4/include/DDG4/Geant4HierarchyDump.h @@ -33,11 +33,23 @@ namespace dd4hep { */ class Geant4HierarchyDump { public: - Detector& m_detDesc; + enum { + G4DUMP_ALL = 0xFFFFFFFF, + G4DUMP_LOGVOL = 1 << 0, + G4DUMP_SOLID = 1 << 1, + G4DUMP_SENSDET = 1 << 2, + G4DUMP_LIMITS = 1 << 3, + G4DUMP_REGION = 1 << 4, + G4DUMP_MATRIX = 1 << 5, + G4DUMP_LAST + }; + + Detector& m_detDesc; + unsigned long m_flags = G4DUMP_ALL; public: /// Initializing Constructor - Geant4HierarchyDump(Detector& description); + Geant4HierarchyDump(Detector& description, unsigned long flags = G4DUMP_ALL); /// Standard destructor virtual ~Geant4HierarchyDump(); /// Dump the volume hierarchy as it is known to geant 4 diff --git a/DDG4/plugins/Geant4DetectorGeometryConstruction.cpp b/DDG4/plugins/Geant4DetectorGeometryConstruction.cpp index 01c13b887..8fa0687e4 100644 --- a/DDG4/plugins/Geant4DetectorGeometryConstruction.cpp +++ b/DDG4/plugins/Geant4DetectorGeometryConstruction.cpp @@ -32,27 +32,29 @@ namespace dd4hep { * \ingroup DD4HEP_SIMULATION */ class Geant4DetectorGeometryConstruction : public Geant4DetectorConstruction { - /// Property: Dump geometry hierarchy - bool m_dumpHierarchy = false; + /// Property: Dump geometry hierarchy if not NULL. Flags can steer actions. + unsigned long m_dumpHierarchy = 0; /// Property: Flag to debug materials during conversion mechanism - bool m_debugMaterials = false; + bool m_debugMaterials = false; /// Property: Flag to debug elements during conversion mechanism - bool m_debugElements = false; + bool m_debugElements = false; /// Property: Flag to debug shapes during conversion mechanism - bool m_debugShapes = false; + bool m_debugShapes = false; /// Property: Flag to debug volumes during conversion mechanism - bool m_debugVolumes = false; + bool m_debugVolumes = false; /// Property: Flag to debug placements during conversion mechanism - bool m_debugPlacements = false; + bool m_debugPlacements = false; + /// Property: Flag to debug reflections during conversion mechanism + bool m_debugReflections = false; /// Property: Flag to debug regions during conversion mechanism - bool m_debugRegions = false; + bool m_debugRegions = false; /// Property: Flag to debug regions during conversion mechanism - bool m_debugSurfaces = false; + bool m_debugSurfaces = false; /// Property: Flag to dump all placements after the conversion procedure - bool m_printPlacements = false; + bool m_printPlacements = false; /// Property: Flag to dump all sensitives after the conversion procedure - bool m_printSensitives = false; + bool m_printSensitives = false; /// Property: Printout level of info object int m_geoInfoPrintLevel; @@ -129,6 +131,7 @@ Geant4DetectorGeometryConstruction::Geant4DetectorGeometryConstruction(Geant4Con declareProperty("DebugShapes", m_debugShapes); declareProperty("DebugVolumes", m_debugVolumes); declareProperty("DebugPlacements", m_debugPlacements); + declareProperty("DebugReflections", m_debugReflections); declareProperty("DebugRegions", m_debugRegions); declareProperty("DebugSurfaces", m_debugSurfaces); @@ -151,13 +154,14 @@ void Geant4DetectorGeometryConstruction::constructGeo(Geant4DetectorConstruction Geant4Mapping& g4map = Geant4Mapping::instance(); DetElement world = ctxt->description.world(); Geant4Converter conv(ctxt->description, outputLevel()); - conv.debugMaterials = m_debugMaterials; - conv.debugElements = m_debugElements; - conv.debugShapes = m_debugShapes; - conv.debugVolumes = m_debugVolumes; - conv.debugPlacements = m_debugPlacements; - conv.debugRegions = m_debugRegions; - conv.debugSurfaces = m_debugSurfaces; + conv.debugMaterials = m_debugMaterials; + conv.debugElements = m_debugElements; + conv.debugShapes = m_debugShapes; + conv.debugVolumes = m_debugVolumes; + conv.debugRegions = m_debugRegions; + conv.debugSurfaces = m_debugSurfaces; + conv.debugPlacements = m_debugPlacements; + conv.debugReflections = m_debugReflections; ctxt->geometry = conv.create(world).detach(); ctxt->geometry->printLevel = outputLevel(); @@ -167,8 +171,8 @@ void Geant4DetectorGeometryConstruction::constructGeo(Geant4DetectorConstruction context()->kernel().setWorld(w); // Create Geant4 volume manager only if not yet available g4map.volumeManager(); - if ( m_dumpHierarchy ) { - Geant4HierarchyDump dmp(ctxt->description); + if ( m_dumpHierarchy != 0 ) { + Geant4HierarchyDump dmp(ctxt->description, m_dumpHierarchy); dmp.dump("",w); } ctxt->world = w; diff --git a/DDG4/python/DDG4.py b/DDG4/python/DDG4.py index a6689f676..07eee9f27 100644 --- a/DDG4/python/DDG4.py +++ b/DDG4/python/DDG4.py @@ -688,9 +688,9 @@ class Geant4: phys.adopt(opt) return opt - def setupGun(self, name, particle, energy, isotrop=True, + def setupGun(self, name, particle, energy, typ="Geant4ParticleGun", isotrop=True, multiplicity=1, position=(0.0, 0.0, 0.0), register=True, **args): - gun = GeneratorAction(self.kernel(), "Geant4ParticleGun/" + name, True) + gun = GeneratorAction(self.kernel(), typ + "/" + name, True) for i in args.items(): setattr(gun, i[0], i[1]) gun.energy = energy diff --git a/DDG4/src/Geant4Converter.cpp b/DDG4/src/Geant4Converter.cpp index c7cfdaebc..5fe2d9b87 100644 --- a/DDG4/src/Geant4Converter.cpp +++ b/DDG4/src/Geant4Converter.cpp @@ -130,12 +130,12 @@ void Geant4AssemblyVolume::imprint(Geant4GeometryInfo& info, G4Transform3D Ta( *(triplets[i].GetRotation()), triplets[i].GetTranslation() ); - if ( triplets[i].IsReflection() ) { Ta = Ta * G4ReflectZ3D(); } + if ( triplets[i].IsReflection() ) { + Ta = Ta * G4ReflectZ3D(); + } G4Transform3D Tfinal = transformation * Ta; - - if ( triplets[i].GetVolume() ) - { + if ( triplets[i].GetVolume() ) { // Generate the unique name for the next PV instance // The name has format: // @@ -161,6 +161,11 @@ void Geant4AssemblyVolume::imprint(Geant4GeometryInfo& info, // (as we allow 3D transformation use G4ReflectionFactory to // take into account eventual reflection) // +#if 0 + printout(INFO,"Geant4Converter","+++ Place %svolume %s in assembly.", + triplets[i].IsReflection() ? "REFLECTED " : "", + detail::tools::placementPath(new_chain).c_str()); +#endif G4PhysicalVolumesPair pvPlaced = G4ReflectionFactory::Instance()->Place( Tfinal, pvName.str().c_str(), @@ -784,11 +789,16 @@ void* Geant4Converter::handleAssembly(const string& name, const TGeoNode* node) MyTransform3D transform(tr->GetTranslation(),tr->IsRotation() ? tr->GetRotationMatrix() : s_identity_rot); if ( is_left_handed(tr) ) { - //transform = transform * G4ReflectZ3D(); - printout(ALWAYS, "Geant4Converter", "+++ Assembly: **** : Placing reflected assembly. dau:%s " - "to mother %s Tr:x=%8.3f y=%8.3f z=%8.3f", + G4Scale3D scale; + G4Rotate3D rot; + G4Translate3D trans; + transform.getDecomposition(scale, rot, trans); + printout(debugReflections ? ALWAYS : lvl, "Geant4Converter", + "+++ Placing reflected ASSEMBLY. dau:%s to mother %s " + "Tr:x=%8.1f y=%8.1f z=%8.1f Scale:x=%4.2f y=%4.2f z=%4.2f", dau_vol->GetName(), mot_vol->GetName(), - transform.dx(), transform.dy(), transform.dz()); + transform.dx(), transform.dy(), transform.dz(), + scale.xx(), scale.yy(), scale.zz()); } if ( dau_vol->IsA() == TGeoVolumeAssembly::Class() ) { @@ -837,6 +847,7 @@ void* Geant4Converter::handlePlacement(const string& name, const TGeoNode* node) printout(lvl, "Geant4Converter", "++ Placement %s not converted [Veto'ed for simulation]",node->GetName()); return 0; } +#if 0 if ( g4 ) { const TGeoNode* old_node = (*g4it).first.ptr(); const TGeoNode* new_node = node; @@ -844,11 +855,13 @@ void* Geant4Converter::handlePlacement(const string& name, const TGeoNode* node) TGeoVolume* new_vol = new_node->GetVolume(); TGeoMatrix* old_tr = old_node->GetMatrix(); TGeoMatrix* new_tr = new_node->GetMatrix(); - printout(ALWAYS, "Geant4Converter", "+++ Placement: **** Reuse: OLD: %s vol: %s %s NEW: %s vol: %s %s", + printout(debugReflections ? ALWAYS : lvl, "Geant4Converter", + "+++ Placement: **** Reuse: OLD: %s vol: %s %s NEW: %s vol: %s %s", old_node->GetName(), old_vol->GetName(), is_left_handed(old_tr) ? " REFLECTED" : "NOT REFLECTED", new_node->GetName(), new_vol->GetName(), is_left_handed(new_tr) ? " REFLECTED" : "NOT REFLECTED"); } - //g4 = nullptr; +#endif + g4 = nullptr; if (!g4) { TGeoVolume* mot_vol = node->GetMotherVolume(); TGeoMatrix* tr = node->GetMatrix(); @@ -861,7 +874,6 @@ void* Geant4Converter::handlePlacement(const string& name, const TGeoNode* node) node->IsA()->GetName(), vol); } else { - G4Transform3D Ta; int copy = node->GetNumber(); bool node_is_reflected = is_left_handed(tr); bool node_is_assembly = vol->IsA() == TGeoVolumeAssembly::Class(); @@ -869,12 +881,6 @@ void* Geant4Converter::handlePlacement(const string& name, const TGeoNode* node) MyTransform3D transform(tr->GetTranslation(),tr->IsRotation() ? tr->GetRotationMatrix() : s_identity_rot); Geant4GeometryMaps::VolumeMap::const_iterator volIt = info.g4Volumes.find(mot_vol); - if ( node_is_reflected ) { - printout(ALWAYS, "Geant4Converter", "+++ Placement: **** : Placing reflected volume. dau:%s " - "to mother %s Tr:x=%8.3f y=%8.3f z=%8.3f", - vol->GetName(), mot_vol->GetName(), - transform.dx(), transform.dy(), transform.dz()); - } if ( mother_is_assembly ) { // // Mother is an assembly: @@ -893,10 +899,16 @@ void* Geant4Converter::handlePlacement(const string& name, const TGeoNode* node) // Node is an assembly: // Imprint the assembly. The mother MUST already be transformed. // - printout(lvl, "Geant4Converter", "+++ Assembly: makeImprint: dau:%s in mother %s " - "Tr:x=%8.3f y=%8.3f z=%8.3f", - node->GetName(), mot_vol ? mot_vol->GetName() : "<unknown>", - transform.dx(), transform.dy(), transform.dz()); + G4Scale3D scale; + G4Rotate3D rot; + G4Translate3D trans; + transform.getDecomposition(scale, rot, trans); + printout(lvl, "Geant4Converter", "+++ Assembly: makeImprint: dau:%-12s %s in mother %-12s " + "Tr:x=%8.1f y=%8.1f z=%8.1f Scale:x=%4.2f y=%4.2f z=%4.2f", + node->GetName(), node_is_reflected ? "(REFLECTED)" : "", + mot_vol ? mot_vol->GetName() : "<unknown>", + transform.dx(), transform.dy(), transform.dz(), + scale.xx(), scale.yy(), scale.zz()); Geant4AssemblyVolume* ass = (Geant4AssemblyVolume*)info.g4AssemblyVolumes[node]; Geant4AssemblyVolume::Chain chain; chain.emplace_back(node); @@ -906,6 +918,9 @@ void* Geant4Converter::handlePlacement(const string& name, const TGeoNode* node) else if ( node != info.manager->GetTopNode() && volIt == info.g4Volumes.end() ) { throw logic_error("Geant4Converter: Invalid mother volume found!"); } + G4Scale3D scale; + G4Rotate3D rot; + G4Translate3D trans; G4LogicalVolume* g4vol = info.g4Volumes[vol]; G4LogicalVolume* g4mot = info.g4Volumes[mot_vol]; G4PhysicalVolumesPair pvPlaced = @@ -916,6 +931,14 @@ void* Geant4Converter::handlePlacement(const string& name, const TGeoNode* node) false, // no boolean operations copy, // its copy number checkOverlaps); + transform.getDecomposition(scale, rot, trans); + printout(debugReflections ? ALWAYS : lvl, "Geant4Converter", + "+++ Place %svolume %-12s in mother %-12s " + "Tr:x=%8.1f y=%8.1f z=%8.1f Scale:x=%4.2f y=%4.2f z=%4.2f", + node_is_reflected ? "REFLECTED " : "", _v.name(), + mot_vol ? mot_vol->GetName() : "<unknown>", + transform.dx(), transform.dy(), transform.dz(), + scale.xx(), scale.yy(), scale.zz()); // First 2 cases can be combined. // Leave them separated for debugging G4ReflectionFactory for now... if ( node_is_reflected && !pvPlaced.second ) @@ -1453,6 +1476,7 @@ Geant4Converter& Geant4Converter::create(DetElement top) { //setPrintLevel(VERBOSE); //debugMaterials = true; //debugElements = true; + debugReflections = true; #if ROOT_VERSION_CODE >= ROOT_VERSION(6,17,0) handleArray(this, geo.manager->GetListOfGDMLMatrices(), &Geant4Converter::handleMaterialProperties); diff --git a/DDG4/src/Geant4HierarchyDump.cpp b/DDG4/src/Geant4HierarchyDump.cpp index 390d45204..190d3480f 100644 --- a/DDG4/src/Geant4HierarchyDump.cpp +++ b/DDG4/src/Geant4HierarchyDump.cpp @@ -67,19 +67,11 @@ static const char* _T(const std::string& str) { return str.c_str(); } -enum { - G4DUMP_ALL = 0xFFFFFFFF, - G4DUMP_LOGVOL = 1 << 0, - G4DUMP_SOLID = 1 << 1, - G4DUMP_SENSDET = 1 << 2, - G4DUMP_LIMITS = 1 << 3, - G4DUMP_REGION = 1 << 4, - G4DUMP_LAST -}; -static unsigned long m_flags = ~0x0UL; - /// Initializing Constructor -Geant4HierarchyDump::Geant4HierarchyDump(Detector& description) : m_detDesc(description) { +Geant4HierarchyDump::Geant4HierarchyDump(Detector& description, unsigned long flags) + : m_detDesc(description), m_flags(flags) +{ + m_flags &= ~G4DUMP_SOLID; } /// Standard destructor @@ -87,24 +79,25 @@ Geant4HierarchyDump::~Geant4HierarchyDump() { } void Geant4HierarchyDump::dump(const string& indent, const G4VPhysicalVolume* v) const { - G4LogicalVolume* lv = v->GetLogicalVolume(); - G4VSensitiveDetector* sd = lv->GetSensitiveDetector(); - G4Material* mat = lv->GetMaterial(); - G4VSolid* sol = lv->GetSolid(); - G4Region* rg = lv->GetRegion(); - G4UserLimits* ul = lv->GetUserLimits(); - G4int ndau = lv->GetNoDaughters(); - char text[32]; + G4LogicalVolume* lv = v->GetLogicalVolume(); + G4VSensitiveDetector* sd = lv->GetSensitiveDetector(); + G4RotationMatrix* rot = v->GetObjectRotation(); + G4Material* mat = lv->GetMaterial(); + G4VSolid* sol = lv->GetSolid(); + G4Region* rg = lv->GetRegion(); + G4UserLimits* ul = lv->GetUserLimits(); + G4int ndau = lv->GetNoDaughters(); stringstream str; + char text[32]; - m_flags &= ~G4DUMP_SOLID; - printout(INFO, "Geant4Hierarchy", "%s -> Placement:%s LV:%s Material:%s Solid:%s # of Daughters:%d", indent.c_str(), - _T(v->GetName()), _T(lv->GetName()), _T(mat->GetName()), _T(sol->GetName()), ndau); + printout(INFO, "Geant4Hierarchy", "%s -> Placement:%s LV:%s Material:%s Solid:%s # of Daughters:%d CopyNo:%d", + _T(indent), _T(v->GetName()), _T(lv->GetName()), _T(mat->GetName()), + _T(sol->GetName()), ndau, v->GetCopyNo()); if (sd && (m_flags & G4DUMP_SOLID)) { str.str(""); sol->StreamInfo(str); - printout(INFO, "Geant4Hierarchy", "%s Solid:%s", indent.c_str(), str.str().c_str()); + printout(INFO, "Geant4Hierarchy", "%s Solid:%s", _T(indent), str.str().c_str()); } if (rg && (m_flags & G4DUMP_LIMITS)) { G4UserLimits* rg_limits = rg->GetUserLimits(); @@ -116,11 +109,20 @@ void Geant4HierarchyDump::dump(const string& indent, const G4VPhysicalVolume* v) printout(INFO, "Geant4Hierarchy", str.str().c_str()); } if (sd && (m_flags & G4DUMP_SENSDET)) { - printout(INFO, "Geant4Hierarchy", "%s Sens.det:%p %s path:%s Active:%-3s #Coll:%d", indent.c_str(), sd, + printout(INFO, "Geant4Hierarchy", "%s Sens.det:%p %s path:%s Active:%-3s #Coll:%d", _T(indent), sd, _T(sd->GetName()), _T(sd->GetFullPathName()), yes_no(sd->isActive()), sd->GetNumberOfCollections()); } if (ul && (m_flags & G4DUMP_LIMITS)) { - printout(INFO, "Geant4Hierarchy", "%s Limits:%s ", indent.c_str(), _T(ul->GetType())); + printout(INFO, "Geant4Hierarchy", "%s Limits:%s ", _T(indent), _T(ul->GetType())); + } + if (rot && (m_flags & G4DUMP_MATRIX)) { + const G4ThreeVector t = v->GetTranslation(); + const G4RotationMatrix& r = *rot; + double det = + r.xx()*r.yy()*r.zz() + r.xy()*r.yz()*r.zx() + r.xz()*r.yx()*r.zy() - + r.zx()*r.yy()*r.xz() - r.zy()*r.yz()*r.xx() - r.zz()*r.yx()*r.xy(); + printout(INFO, "Geant4Hierarchy", "%s Matrix: %sREFLECTED Tr: %8.3g %8.3g %8.3g [mm]", + _T(indent), det > 0e0 ? "NOT " : "", t.x(), t.y(), t.z()); } for (G4int idau = 0; idau < ndau; ++idau) { ::snprintf(text, sizeof(text), " %-3d", idau); diff --git a/DDG4/src/Geant4ParticleGenerator.cpp b/DDG4/src/Geant4ParticleGenerator.cpp index f3002c529..898c2ac7d 100644 --- a/DDG4/src/Geant4ParticleGenerator.cpp +++ b/DDG4/src/Geant4ParticleGenerator.cpp @@ -130,16 +130,16 @@ void Geant4ParticleGenerator::operator()(G4Event*) { Particle* p = new Particle(); direction = m_direction; getParticleDirection(i, direction, momentum); - unit_direction = direction.unit(); - p->id = inter->nextPID(); - p->status |= G4PARTICLE_GEN_STABLE; - p->mask = m_mask; - p->pdgID = m_particle->GetPDGEncoding(); - - p->psx = unit_direction.X()*momentum; - p->psy = unit_direction.Y()*momentum; - p->psz = unit_direction.Z()*momentum; - p->mass = m_particle->GetPDGMass(); + unit_direction = direction.unit(); + p->id = inter->nextPID(); + p->status |= G4PARTICLE_GEN_STABLE; + p->mask = m_mask; + p->pdgID = m_particle->GetPDGEncoding(); + + p->psx = unit_direction.X()*momentum; + p->psy = unit_direction.Y()*momentum; + p->psz = unit_direction.Z()*momentum; + p->mass = m_particle->GetPDGMass(); p->charge = m_particle->GetPDGCharge(); p->spin[0] = 0; p->spin[1] = 0; diff --git a/examples/ClientTests/CMakeLists.txt b/examples/ClientTests/CMakeLists.txt index f77c57512..f5779e4fb 100644 --- a/examples/ClientTests/CMakeLists.txt +++ b/examples/ClientTests/CMakeLists.txt @@ -46,7 +46,7 @@ install(TARGETS multipleGeo RUNTIME DESTINATION bin) # # set(ClientTestsEx_INSTALL ${CMAKE_INSTALL_PREFIX}/examples/ClientTests) -dd4hep_install_dir( compact scripts ref DESTINATION ${ClientTestsEx_INSTALL} ) +dd4hep_install_dir( compact scripts ref eve DESTINATION ${ClientTestsEx_INSTALL} ) #-------------------------------------------------------------------------- #-------------------------------------------------------------------------- diff --git a/examples/ClientTests/compact/NestedBoxReflection.xml b/examples/ClientTests/compact/NestedBoxReflection.xml index de44bad6e..745c5bcc0 100644 --- a/examples/ClientTests/compact/NestedBoxReflection.xml +++ b/examples/ClientTests/compact/NestedBoxReflection.xml @@ -7,20 +7,17 @@ </includes> <define> - <constant name="world_size" value="30*m"/> + <constant name="world_size" value="6*m"/> <constant name="world_x" value="world_size"/> <constant name="world_y" value="world_size"/> <constant name="world_z" value="world_size"/> - <constant name="HcalBarrel_rmin" value="300*cm"/> - <constant name="HcalBarrel_rmax" value="500*cm"/> - <constant name="HcalBarrel_zmax" value="600*cm"/> </define> <display> <vis name="Invisible" showDaughters="false" visible="false"/> <vis name="InvisibleWithChildren" showDaughters="true" visible="false"/> - <vis name="LightGrey" alpha="0.3" r="0.7" g="0.7" b="0.7" showDaughters="true" visible="true"/> - <vis name="DarkGrey" alpha="0.3" r="0.3" g="0.3" b="0.3" showDaughters="true" visible="true"/> + <vis name="VisibleGrey" alpha="0.4" r="0.7" g="0.7" b="0.7" showDaughters="true" visible="true"/> + <vis name="DarkGrey" alpha="0.4" r="0.3" g="0.3" b="0.3" showDaughters="true" visible="true"/> <vis name="VisibleRed" alpha="0.6" r="1.0" g="0.0" b="0.0" showDaughters="true" visible="true"/> <vis name="VisibleBlue" alpha="0.6" r="0.0" g="0.0" b="1.0" showDaughters="true" visible="true"/> <vis name="VisibleYellow" alpha="0.6" r="1.0" g="1.0" b="0.0" showDaughters="true" visible="true"/> @@ -37,24 +34,53 @@ <detector id="1" name="NestedBox" type="NestedBoxReflection" readout="NestedBoxHits" vis="VisibleGreen" limits="cal_limits"> <comment>A box with 3 boxes inside spanning a coordinate system</comment> <assembly/> - <dimensions x="50*cm" y="70*cm" z="90*cm"/> - <xxxreflect_z/> - <no-reflect name="ReflectionY"> - <rotation phiY="270.*deg" thetaY="90.*deg" phiX=" 0.*deg" thetaX="90.*deg" phiZ="0.*deg" thetaZ="0.*deg"/> - <position x="0" y="0" z="-130*cm"/> - </no-reflect> + <dimensions x="50*cm" y="70*cm" z="90*cm" level="2"> + <position x="400*cm" y="0*cm" z="0*cm"/> + </dimensions> <reflect name="ReflectionX"> <rotation phiX="180.*deg" thetaX="90.*deg" phiY="90.*deg" thetaY="90.*deg" phiZ="0.*deg" thetaZ="0.*deg"/> - <position x="0" y="0" z="-130*cm"/> + <position x="200*cm" y="0*cm" z="0*cm"/> </reflect> + <reflect_x x="-200*cm" y="0*cm" z="0*cm"/> - </detector> + <reflect name="ReflectionY"> + <rotation phiY="270.*deg" thetaY="90.*deg" phiX=" 0.*deg" thetaX="90.*deg" phiZ="0.*deg" thetaZ="0.*deg"/> + <position x="0*cm" y="200*cm" z="0*cm"/> + </reflect> + <reflect_y x="0*cm" y="-200*cm" z="0*cm"/> + + <reflect_z x="0*cm" y="0*cm" z="200*cm"/> + <reflect_z x="0*cm" y="0*cm" z="-200*cm"/> +<!-- + <reflect_x x="-200*cm" y="200*cm" z="0*cm"/> + <reflect_x x="-200*cm" y="200*cm" z="200*cm"/> + <reflect_x x="-200*cm" y="200*cm" z="-200*cm"/> + <reflect_x x="-200*cm" y="-200*cm" z="200*cm"/> + <reflect_x x="-200*cm" y="-200*cm" z="-200*cm"/> + <reflect_x x="-200*cm" y="-200*cm" z="0*cm"/> + <reflect_y x="0*cm" y="200*cm" z="200*cm"/> + <reflect_y x="0*cm" y="200*cm" z="-200*cm"/> + <reflect_y x="0*cm" y="-200*cm" z="200*cm"/> + <reflect_y x="0*cm" y="-200*cm" z="-200*cm"/> + <reflect_y x="200*cm" y="0*cm" z="200*cm"/> + <reflect_y x="-200*cm" y="0*cm" z="200*cm"/> + <reflect_y x="200*cm" y="0*cm" z="-200*cm"/> + <reflect_y x="-200*cm" y="0*cm" z="-200*cm"/> + + <reflect_z x="200*cm" y="200*cm" z="0*cm"/> + <reflect_z x="200*cm" y="200*cm" z="200*cm"/> + <reflect_z x="200*cm" y="200*cm" z="-200*cm"/> + <reflect_z x="200*cm" y="-200*cm" z="200*cm"/> + <reflect_z x="200*cm" y="-200*cm" z="-200*cm"/> + <reflect_z x="200*cm" y="-200*cm" z="0*cm"/> +--> + </detector> </detectors> <readouts> <readout name="NestedBoxHits"> - <id>system:8,lvl4:4,lvl3:4,lvl2:4,lvl1:4,lvl0:4</id> + <id>system:8,lvl4:5,lvl3:5,lvl2:5,lvl1:5,lvl0:5</id> </readout> </readouts> diff --git a/examples/ClientTests/scripts/Check_reflection.py b/examples/ClientTests/scripts/Check_reflection.py index 201073c17..21be799d8 100644 --- a/examples/ClientTests/scripts/Check_reflection.py +++ b/examples/ClientTests/scripts/Check_reflection.py @@ -7,10 +7,14 @@ """ from __future__ import absolute_import, unicode_literals import logging +import time import sys +import os +from g4units import TeV, GeV, MeV, mm, cm, m from ddsix.moves import range logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO) +logger = logging.getLogger(__name__) def help(): @@ -23,7 +27,10 @@ def help(): def run(): geo = None vis = False + dump = False batch = False + install_dir = os.environ['DD4hepINSTALL'] + # for i in list(range(len(sys.argv))): c = sys.argv[i].upper() if c.find('BATCH') < 2 and c.find('BATCH') >= 0: @@ -32,6 +39,8 @@ def run(): geo = sys.argv[i + 1] elif c[:4] == '-VIS': vis = True + elif c[:4] == '-DUM': + dump = True if not geo: help() @@ -39,28 +48,102 @@ def run(): import DDG4 kernel = DDG4.Kernel() + description = kernel.detectorDescription() + DDG4.setPrintLevel(DDG4.OutputLevel.INFO) + DDG4.importConstants(description) + # # Configure UI - geant4 = DDG4.Geant4(kernel, tracker='Geant4TrackerCombineAction') + geant4 = DDG4.Geant4(kernel) + ui = None if batch: geant4.setupCshUI(ui=None, vis=None) kernel.UI = 'UI' else: - geant4.setupCshUI(vis=vis) + ui = geant4.setupCshUI(vis=vis) Output = DDG4.OutputLevel + seq, act = geant4.addDetectorConstruction("Geant4DetectorGeometryConstruction/ConstructGeo") + act.DebugReflections = True act.DebugMaterials = False act.DebugElements = False act.DebugVolumes = False act.DebugShapes = False - + if dump: + act.DumpHierarchy = ~0x0 + # kernel.setOutputLevel(str('Geant4Converter'), Output.WARNING) kernel.loadGeometry(geo) + # + geant4.printDetectors() # Configure field geant4.setupTrackingField(prt=True) + logger.info("# Setup random generator") + rndm = DDG4.Action(kernel, 'Geant4Random/Random') + rndm.Seed = 987654321 + rndm.initialize() + # + # Setup detector + seq, act = geant4.setupCalorimeter('NestedBox') + # + # Configure I/O + geant4.setupROOTOutput('RootOutput', 'Reflections_' + time.strftime('%Y-%m-%d_%H-%M'), mc_truth=True) + # + # Setup particle gun + geant4.setupGun(name="Gun", + particle='e-', + energy=1000 * GeV, + multiplicity=2, + position=(0*m,0*m,0*m), + PhiMin=0.0, PhiMax=3.141*2.0, + ThetaMin=0.0, ThetaMax=3.141) + + logger.info("# ....and handle the simulation particles.") + part = DDG4.GeneratorAction(kernel, str('Geant4ParticleHandler/ParticleHandler')) + kernel.generatorAction().adopt(part) + part.MinimalKineticEnergy = 100 * MeV + part.SaveProcesses = ['Decay'] + part.OutputLevel = 5 # generator_output_level + part.enableUI() + user = DDG4.Action(kernel, str('Geant4TCUserParticleHandler/UserParticleHandler')) + user.TrackingVolume_Rmax = 3.0 * m + user.TrackingVolume_Zmax = 2.0 * m + user.enableUI() + part.adopt(user) + # + # + prt = DDG4.EventAction(kernel, str('Geant4ParticlePrint/ParticlePrint')) + prt.OutputLevel = Output.INFO + prt.OutputType = 3 # Print both: table and tree + kernel.eventAction().adopt(prt) + # # Now build the physics list: - geant4.setupPhysics('') - kernel.physicsList().enableUI() - DDG4.setPrintLevel(DDG4.OutputLevel.INFO) + phys = geant4.setupPhysics(str('QGSP_BERT')) + ph = geant4.addPhysics(str('Geant4PhysicsList/Myphysics')) + ph.addPhysicsConstructor(str('G4StepLimiterPhysics')) + ph.addParticleConstructor(str('G4Geantino')) + ph.addParticleConstructor(str('G4BosonConstructor')) + # + # Add special particle types from specialized physics constructor + part = geant4.addPhysics('Geant4ExtraParticles/ExtraParticles') + part.pdgfile = os.path.join(install_dir, 'examples/DDG4/examples/particle.tbl') + # + # Add global range cut + rg = geant4.addPhysics('Geant4DefaultRangeCut/GlobalRangeCut') + rg.RangeCut = 0.7 * mm + # + phys.dump() + # + # + if ui and vis: + cmds = [] + cmds.append('/control/verbose 2') + cmds.append('/run/initialize') + cmds.append('/vis/open OGL') + cmds.append('/vis/verbose errors') + cmds.append('/vis/drawVolume') + cmds.append('/vis/viewer/set/viewpointThetaPhi 55. 45.') + cmds.append('/vis/scene/add/axes 0 0 0 3 m') + ui.Commands = cmds kernel.NumEvents = 0 kernel.configure() kernel.initialize() diff --git a/examples/ClientTests/scripts/Check_shape_vis.mac b/examples/ClientTests/scripts/Check_shape_vis.mac index bdd89275c..33ff74c4f 100644 --- a/examples/ClientTests/scripts/Check_shape_vis.mac +++ b/examples/ClientTests/scripts/Check_shape_vis.mac @@ -4,6 +4,8 @@ /vis/verbose errors /vis/drawVolume /vis/viewer/set/viewpointThetaPhi 55. 45. -/vis/scene/add/axes 0 0 0 1 m +/vis/scene/add/axes 0 0 0 3 m + + /vis/viewer/zoom 2 /vis/viewer/refresh diff --git a/examples/ClientTests/scripts/SiliconBlock.py b/examples/ClientTests/scripts/SiliconBlock.py index bdda06fa0..2f77739ea 100644 --- a/examples/ClientTests/scripts/SiliconBlock.py +++ b/examples/ClientTests/scripts/SiliconBlock.py @@ -75,9 +75,9 @@ def run(): # Now build the physics list: phys = geant4.setupPhysics('QGSP_BERT') - ph = DDG4.PhysicsList(kernel, 'Geant4PhysicsList/Myphysics') - ph.addParticleConstructor('G4Geantino') - ph.addParticleConstructor('G4BosonConstructor') + ph = DDG4.PhysicsList(kernel, str('Geant4PhysicsList/Myphysics')) + ph.addParticleConstructor(str('G4Geantino')) + ph.addParticleConstructor(str('G4BosonConstructor')) ph.enableUI() phys.adopt(ph) phys.dump() diff --git a/examples/ClientTests/src/NestedBoxReflection_geo.cpp b/examples/ClientTests/src/NestedBoxReflection_geo.cpp index 937ab6c3b..1897890ab 100644 --- a/examples/ClientTests/src/NestedBoxReflection_geo.cpp +++ b/examples/ClientTests/src/NestedBoxReflection_geo.cpp @@ -13,8 +13,10 @@ // Framework includes #include "DD4hep/Printout.h" +#include "DD4hep/MatrixHelpers.h" #include "DD4hep/DetFactoryHelper.h" #include "XML/VolumeBuilder.h" +#include "XML/Utilities.h" #include <cmath> using namespace std; @@ -74,12 +76,12 @@ namespace { void place_boxes(int level, Volume vol) { if ( level >= 0 ) { - Box box = vol.solid(); - double line= 0.015; - double bx = box.x(); - double by = box.y(); - double bz = box.z(); - Material mat = vol.material(); + Box box = vol.solid(); + double line = 0.015; + double bx = box.x(); + double by = box.y(); + double bz = box.z(); + Material mat = description.material("Si"); Box small_box(bx*0.2, by*0.2, bz*0.2); const char* cols[4] = {"VisibleRed","VisibleBlue","VisibleGreen","VisibleYellow"}; const char* c; @@ -146,63 +148,84 @@ namespace { printout(INFO,"NestedBoxReflection","++ Volume: %s Color: %s", v.name(), c); } } + + PlacedVolume place(Volume mother, Volume vol, xml_elt_t e, int level, int copyNo, char reflection) { + Position pos; + RotationZYX rot; + xml_dim_t xpos = xml_dim_t(e).child(_U(position), false); + xml_dim_t xrot = xml_dim_t(e).child(_U(rotation), false); + if ( !xpos.ptr() ) xpos = e; + if ( xpos.ptr() ) pos = Position(xpos.x(0),xpos.y(0),xpos.z(0)); + if ( xrot.ptr() ) rot = RotationZYX(xrot.x(0),xrot.y(0),xrot.z(0)); + + TGeoHMatrix* mat = detail::matrix::_transform(pos, rot); + switch(reflection) { + case 'X': + mat->ReflectX(kTRUE, kTRUE); + break; + case 'Y': + mat->ReflectY(kTRUE, kTRUE); + break; + case 'Z': + default: + mat->ReflectZ(kTRUE, kTRUE); + break; + } + PlacedVolume pv = mother.placeVolume(vol, mat); + pv.addPhysVolID(_toString(level,"lvl%d"), copyNo); + return pv; + } Ref_t create() { - xml_dim_t x_box(x_det.dimensions()); - int max_level = 3; - double bx = x_box.x(); - double by = x_box.y(); - double bz = x_box.z(); - Volume v_det; - Box box_solid(bx,by,bz); - Volume box_vol(x_det.nameStr()+"_box",box_solid,description.air()); + xml_dim_t x_box(x_det.dimensions()); + int levels = x_box.level(2); + double bx = x_box.x(); + double by = x_box.y(); + double bz = x_box.z(); + Volume v_det; + Box box_solid(bx,by,bz); + Volume box_vol("nested_box",box_solid,description.air()); PlacedVolume pv; - int cnt = 1; sensitive.setType("tracker"); - box_vol.setAttributes(description,x_det.regionStr(),x_det.limitsStr(),"VisibleGrey"); - - if ( x_det.hasChild(_U(assembly)) ) - v_det = Assembly(x_det.nameStr()+"_det"); + if ( levels != 0 && x_det.hasChild(_U(assembly)) ) + v_det = Assembly("envelope"); else - v_det = Volume(x_det.nameStr()+"_det",Box(2.5*bx,2.5*by,2.5*bz),description.air()); - - place_boxes(max_level-1, box_vol); - pv = v_det.placeVolume(box_vol, Position(0,0,1.1*bz)); - pv.addPhysVolID(_toString(max_level,"lvl%d"), ++cnt); - pv = nullptr; - if ( x_det.hasChild(_U(reflect_x)) ) { - Volume reflect_vol = box_vol.reflect(sensitive); - Position reflect_pos = Position(-1.1*bx,0,0); - pv = v_det.placeVolume(reflect_vol, reflect_pos); - } - else if ( x_det.hasChild(_U(reflect_y)) ) { - Volume reflect_vol = box_vol.reflect(sensitive); - Position reflect_pos = Position(0,-1.1*by,0); - pv = v_det.placeVolume(reflect_vol, reflect_pos); - } - else if ( x_det.hasChild(_U(reflect_z)) ) { - Volume reflect_vol = box_vol.reflect(sensitive); - Position reflect_pos = Position(0,0,-1.1*bz); - pv = v_det.placeVolume(reflect_vol, reflect_pos); + v_det = Volume("envelope",Box(4.5*bx,4.5*by,4.5*bz),description.air()); + + if ( levels == 0 ) { + v_det.setSensitiveDetector(sensitive); } - if ( pv.ptr() ) { - pv.addPhysVolID(_toString(max_level,"lvl%d"), ++cnt); + else if ( levels == 1 ) { + box_vol.setSensitiveDetector(sensitive); + box_vol.setAttributes(description,x_det.regionStr(),x_det.limitsStr(),"VisibleGrey"); } - - if ( x_det.hasChild(_U(reflect)) ) { - Volume reflect_vol = box_vol; - for(xml_coll_t c(x_det,_U(reflect)); c; ++c) { - TGeoCombiTrans* reflect_tr = transform_reflect(c); - pv = v_det.placeVolume(reflect_vol.ptr(), reflect_tr); - pv.addPhysVolID(_toString(max_level,"lvl%d"), ++cnt); - } + else { + int cnt = 1; + Transform3D tr = xml::createTransformation(x_box); + box_vol.setAttributes(description,x_det.regionStr(),x_det.limitsStr(),"VisibleGrey"); + place_boxes(levels-1, box_vol); + pv = v_det.placeVolume(box_vol, tr); + pv.addPhysVolID(_toString(levels,"lvl%d"), ++cnt); + + for(xml_coll_t c(x_det,_U(reflect_x)); c; ++c) + place(v_det, box_vol, c, levels, ++cnt, 'X'); + for(xml_coll_t c(x_det,_U(reflect_y)); c; ++c) + place(v_det, box_vol, c, levels, ++cnt, 'Y'); + for(xml_coll_t c(x_det,_U(reflect_z)); c; ++c) + place(v_det, box_vol, c, levels, ++cnt, 'Z'); + + if ( x_det.hasChild(_U(reflect)) ) { + Volume reflect_vol = box_vol; + for(xml_coll_t c(x_det,_U(reflect)); c; ++c) { + TGeoCombiTrans* reflect_tr = transform_reflect(c); + pv = v_det.placeVolume(reflect_vol.ptr(), reflect_tr); + pv.addPhysVolID(_toString(levels,"lvl%d"), ++cnt); + } + } } - // Place the calo inside the world - pv = description.pickMotherVolume(detector).placeVolume(v_det); - pv.addPhysVolID("system",x_det.id()); - detector.setPlacement(pv); + placeDetector(v_det, x_det).addPhysVolID("system",x_det.id()); return detector; } }; -- GitLab