diff --git a/DDCore/include/DD4hep/Volumes.h b/DDCore/include/DD4hep/Volumes.h index d91565313bff75b82456e5c5ac11d31673e476fe..4aaa34c93c9ed9513c34fbd4648a7cc22ff8705c 100644 --- a/DDCore/include/DD4hep/Volumes.h +++ b/DDCore/include/DD4hep/Volumes.h @@ -360,6 +360,10 @@ namespace dd4hep { PlacedVolume placeVolume(const Volume& volume, int copy_no, const RotationZYX& rot) const; /// Place rotated daughter volume. The position is automatically the identity position PlacedVolume placeVolume(const Volume& volume, int copy_no, const Rotation3D& rot) const; + /// Place daughter volume with generic TGeo matrix + PlacedVolume placeVolume(const Volume& volume, TGeoMatrix* tr) const; + /// Place daughter volume with generic TGeo matrix + PlacedVolume placeVolume(const Volume& volume, int copy_nr, TGeoMatrix* tr) const; /// Parametrized volume implementation /** Embedding parametrized daughter placements in a mother volume * @param start start transormation for the first placement diff --git a/DDCore/src/Volumes.cpp b/DDCore/src/Volumes.cpp index bbc1e42dd5e6d9c569b406ff3294d860d9cf63dd..2fd8a248858e8cfe6dcaa10cee78e458c1e206e3 100644 --- a/DDCore/src/Volumes.cpp +++ b/DDCore/src/Volumes.cpp @@ -501,7 +501,7 @@ Volume::Object* Volume::data() const { /// Create a reflected volume tree. The reflected volume has left-handed coordinates Volume Volume::reflect() const { - return reflect(SensitiveDetector(0)); + return this->reflect(this->sensitiveDetector()); } /// Create a reflected volume tree. The reflected volume has left-handed coordinates @@ -661,6 +661,16 @@ PlacedVolume _addNode(TGeoVolume* par, Volume daughter, int copy_nr, const Trans return _addNode(par, daughter, copy_nr, matrix.release()); } +/// Place daughter volume with generic TGeo matrix +PlacedVolume Volume::placeVolume(const Volume& volume, TGeoMatrix* tr) const { + return _addNode(m_element, volume, get_copy_number(m_element), tr); +} + +/// Place daughter volume with generic TGeo matrix +PlacedVolume Volume::placeVolume(const Volume& volume, int copy_nr, TGeoMatrix* tr) const { + return _addNode(m_element, volume, copy_nr, tr); +} + /// Place daughter volume according to generic Transform3D PlacedVolume Volume::placeVolume(const Volume& volume, const Transform3D& trans) const { return _addNode(m_element, volume, get_copy_number(m_element), trans); diff --git a/DDG4/src/Geant4Converter.cpp b/DDG4/src/Geant4Converter.cpp index 4ae6eac23747e4d96632e920de40a32e6ff9e4cc..7283d8692d542aaf6fc95425b14ad94506604896 100644 --- a/DDG4/src/Geant4Converter.cpp +++ b/DDG4/src/Geant4Converter.cpp @@ -839,12 +839,13 @@ void* Geant4Converter::handlePlacement(const string& name, const TGeoNode* node) G4Transform3D Ta; int copy = node->GetNumber(); TGeoRotation* rot = tr->IsRotation() ? (TGeoRotation*)tr : 0; + bool node_is_reflected = rot && rot->Determinant() < 0e0; bool node_is_assembly = vol->IsA() == TGeoVolumeAssembly::Class(); bool mother_is_assembly = mot_vol ? mot_vol->IsA() == TGeoVolumeAssembly::Class() : false; MyTransform3D transform(tr->GetTranslation(),tr->IsRotation() ? tr->GetRotationMatrix() : s_identity_rot); Geant4GeometryMaps::VolumeMap::const_iterator volIt = info.g4Volumes.find(mot_vol); - if ( rot && rot->Determinant() < 0e0 ) { + 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(), @@ -891,9 +892,22 @@ void* Geant4Converter::handlePlacement(const string& name, const TGeoNode* node) false, // no boolean operations copy, // its copy number checkOverlaps); + // First 2 cases can be combined. + // Leave them separated for debugging G4ReflectionFactory for now... + if ( node_is_reflected && !pvPlaced.second ) + return info.g4Placements[node] = pvPlaced.first; + else if ( !node_is_reflected && !pvPlaced.second ) + return info.g4Placements[node] = pvPlaced.first; + G4LogicalVolume* g4refMoth = G4ReflectionFactory::Instance()->GetReflectedLV(g4mot); + // Now deal with valid pvPlaced.second ... + if ( node_is_reflected ) + return info.g4Placements[node] = pvPlaced.first; + else if ( !node_is_reflected ) + return info.g4Placements[node] = pvPlaced.first; g4 = pvPlaced.second ? pvPlaced.second : pvPlaced.first; } info.g4Placements[node] = g4; + printout(ERROR, "Geant4Converter", "++ DEAD code. Should not end up here!"); } else { printout(ERROR, "Geant4Converter", "++ Attempt to DOUBLE-place physical volume: %s No:%d", name.c_str(), node->GetNumber()); diff --git a/DDG4/src/Geant4VolumeManager.cpp b/DDG4/src/Geant4VolumeManager.cpp index 98c57e3f827095262d230646a1d38d61908dc81e..a9670cc15d1968a28674a03a9fe891ecad0e70ad 100644 --- a/DDG4/src/Geant4VolumeManager.cpp +++ b/DDG4/src/Geant4VolumeManager.cpp @@ -112,9 +112,10 @@ namespace { IDDescriptor iddesc = ro.idSpec(); VolumeID code = iddesc.encode(ids); Registries::const_iterator i = m_entries.find(code); - PrintLevel print_action = m_geo.printLevel; - PrintLevel print_chain = m_geo.printLevel; - PrintLevel print_res = m_geo.printLevel; + PrintLevel print_level = m_geo.printLevel; + PrintLevel print_action = print_level; + PrintLevel print_chain = print_level; + PrintLevel print_res = print_level; printout(print_action,"Geant4VolumeManager","+++ Add path:%s vid:%016X", detail::tools::placementPath(nodes,false).c_str(),code); diff --git a/examples/ClientTests/compact/BoxTrafos_with_entity.xml b/examples/ClientTests/compact/BoxTrafos_with_entity.xml new file mode 100644 index 0000000000000000000000000000000000000000..0c24808d58a5e8c003d689c2a750a1bab8521042 --- /dev/null +++ b/examples/ClientTests/compact/BoxTrafos_with_entity.xml @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> +<!DOCTYPE lccdd[ + <!ENTITY STEEL "Steel235"> + <!ENTITY TYPE "DD4hep_BoxSegment"> +]> +<lccdd> + +<!-- #========================================================================== + # 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. + # + #========================================================================== +--> + + <info name="alignment_boxes" + title="Alignment test with 2 simple boxes" + author="Markus Frank" + url="http://www.cern.ch/lhcb" + status="development" + version="$Id: compact.xml 513 2013-04-05 14:31:53Z gaede $"> + <comment>Alignment test with 2 simple boxes</comment> + </info> + + <includes> + <gdmlFile ref="${DD4hepINSTALL}/DDDetectors/compact/elements.xml"/> + <gdmlFile ref="${DD4hepINSTALL}/DDDetectors/compact/materials.xml"/> + </includes> + + <define> + <constant name="world_side" value="30000"/> + <constant name="world_x" value="world_side"/> + <constant name="world_y" value="world_side"/> + <constant name="world_z" value="world_side"/> + </define> + + <display> + <vis name="InvisibleNoDaughters" showDaughters="false" visible="false"/> + <vis name="InvisibleWithDaughters" showDaughters="true" visible="false"/> + <vis name="B1_vis" alpha="1.0" r="1" g="0" b="0" showDaughters="true" visible="true"/> + <vis name="B2_vis" alpha="1.0" r="0" g="1" b="0" showDaughters="true" visible="true"/> + </display> + + <detectors> + <comment>Boxes</comment> + <detector id="3" name="B3" type="&TYPE;" vis="B2_vis"> + <comment>Vertical box</comment> + <material name="&STEEL;"/> + <box x="10" y="20" z="30"/> + <position x="-10" y="30" z="10"/> + <rotation x="0" y="0" z="0"/> + </detector> + <detector id="3" name="B4" type="&TYPE;" vis="B1_vis"> + <comment>Vertical box</comment> + <material name="&STEEL;"/> + <box x="10" y="20" z="30"/> + <position x="0" y="0" z="0"/> + <rotation x="0" y="0" z="0"/> + </detector> + </detectors> +</lccdd> diff --git a/examples/ClientTests/compact/NestedBoxReflection.xml b/examples/ClientTests/compact/NestedBoxReflection.xml new file mode 100644 index 0000000000000000000000000000000000000000..abc1dfa743234d84d48c1d6a70de8c5b16345c7d --- /dev/null +++ b/examples/ClientTests/compact/NestedBoxReflection.xml @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="UTF-8"?> +<lccdd> + + <includes> + <gdmlFile ref="${DD4hepINSTALL}/DDDetectors/compact/elements.xml"/> + <gdmlFile ref="${DD4hepINSTALL}/DDDetectors/compact/materials.xml"/> + </includes> + + <define> + <constant name="world_size" value="30*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="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"/> + <vis name="VisibleGreen" alpha="0.6" r="0.0" g="1.0" b="0.0" showDaughters="true" visible="true"/> + </display> + + <limits> + <limitset name="cal_limits"> + <limit name="step_length_max" particles="*" value="5.0" unit="mm" /> + </limitset> + </limits> + + <detectors> + <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> + <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> + <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"/> + </reflect> + + </detector> + + </detectors> + + <readouts> + <readout name="NestedBoxHits"> + <id>system:8,lvl4:4,lvl3:4,lvl2:4,lvl1:4,lvl0:4</id> + </readout> + </readouts> + + <fields> + <field name="GlobalSolenoid" type="solenoid" + inner_field="5.0*tesla" + outer_field="-1.5*tesla" + zmax="2*m" + outer_radius="3*m"> + </field> + </fields> + +</lccdd> diff --git a/examples/ClientTests/scripts/Check_reflection.py b/examples/ClientTests/scripts/Check_reflection.py new file mode 100644 index 0000000000000000000000000000000000000000..55b8da194f262a68843c19539055b4c323e53aa2 --- /dev/null +++ b/examples/ClientTests/scripts/Check_reflection.py @@ -0,0 +1,72 @@ +""" + dd4hep example setup using the python configuration + + \author M.Frank + \version 1.0 + +""" +from __future__ import absolute_import, unicode_literals +import logging +import sys +from ddsix.moves import range + +logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO) + + +def help(): + logging.info("Check_shape.py -option [-option] ") + logging.info(" -geometry <geometry file> Geometry file ") + logging.info(" -vis Enable visualization ") + logging.info(" -batch Batch execution ") + + +def run(): + geo = None + vis = False + batch = False + for i in list(range(len(sys.argv))): + c = sys.argv[i].upper() + if c.find('BATCH') < 2 and c.find('BATCH') >= 0: + batch = True + elif c[:4] == '-GEO': + geo = sys.argv[i + 1] + elif c[:4] == '-VIS': + vis = True + + if not geo: + help() + sys.exit(1) + + import DDG4 + kernel = DDG4.Kernel() + # Configure UI + geant4 = DDG4.Geant4(kernel, tracker='Geant4TrackerCombineAction') + if batch: + ui = geant4.setupCshUI(ui=None, vis=None) + kernel.UI = 'UI' + else: + ui = geant4.setupCshUI(vis=vis) + Output = DDG4.OutputLevel + seq, act = geant4.addDetectorConstruction("Geant4DetectorGeometryConstruction/ConstructGeo") + act.DebugMaterials = False + act.DebugElements = False + act.DebugVolumes = True + act.DebugShapes = True + + kernel.setOutputLevel(str('Geant4Converter'), Output.DEBUG) + kernel.loadGeometry(geo) + # Configure field + geant4.setupTrackingField(prt=True) + # Now build the physics list: + geant4.setupPhysics('') + kernel.physicsList().enableUI() + DDG4.setPrintLevel(DDG4.OutputLevel.DEBUG) + kernel.NumEvents = 0 + kernel.configure() + kernel.initialize() + kernel.run() + kernel.terminate() + + +if __name__ == "__main__": + run() diff --git a/examples/ClientTests/src/NestedBoxReflection_geo.cpp b/examples/ClientTests/src/NestedBoxReflection_geo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f823b68695b862f29fa487d487fe47d4f38e0d48 --- /dev/null +++ b/examples/ClientTests/src/NestedBoxReflection_geo.cpp @@ -0,0 +1,212 @@ +//========================================================================== +// 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. +// +// Author : M.Frank +// +//========================================================================== + +// Framework includes +#include "DD4hep/Printout.h" +#include "DD4hep/DetFactoryHelper.h" +#include "XML/VolumeBuilder.h" +#include <cmath> + +using namespace std; +using namespace dd4hep; +using namespace dd4hep::detail; + + +// makes sure that the RotationMatrix built is +// LEFT-handed coordinate system (i.e. reflected) +namespace { + struct NestedBoxReflection : public xml::tools::VolumeBuilder { + using VolumeBuilder::VolumeBuilder; + + Rotation3D makeRotReflect(double thetaX, double phiX, double thetaY, double phiY, double thetaZ, double phiZ) { + // define 3 unit std::vectors forming the new left-handed axes + Position x(cos(phiX) * sin(thetaX), sin(phiX) * sin(thetaX), cos(thetaX)); + Position y(cos(phiY) * sin(thetaY), sin(phiY) * sin(thetaY), cos(thetaY)); + Position z(cos(phiZ) * sin(thetaZ), sin(phiZ) * sin(thetaZ), cos(thetaZ)); + + constexpr double tol = 1.0e-3; // Geant4 compatible + double check = (x.Cross(y)).Dot(z); // in case of a LEFT-handed orthogonal system this must be -1 + if (abs(1. + check) > tol) { + except("NestedBoxReflection", "+++ FAILED to construct Rotation is not LEFT-handed!"); + } + printout(INFO, "NestedBoxReflection", "+++ Constructed LEFT-handed reflection rotation."); + Rotation3D rotation(x.x(), y.x(), z.x(), x.y(), y.y(), z.y(), x.z(), y.z(), z.z()); + return rotation; + } + + TGeoCombiTrans* createPlacement(const Rotation3D& iRot, const Position& iTrans) { + TGeoRotation r; + double elements[9]; + iRot.GetComponents(elements); + r.SetMatrix(elements); + return new TGeoCombiTrans(TGeoTranslation(iTrans.x(), iTrans.y(), iTrans.z()), r); + } + + //static Transform3D transform_reflect(xml_h element) { + TGeoCombiTrans* transform_reflect(xml_h element) { + xml_dim_t xrot(element.child(_U(rotation))); + xml_dim_t xpos(element.child(_U(position))); + double thetaX = xrot.attr<double>(Unicode("thetaX")); + double phiX = xrot.attr<double>(Unicode("phiX")); + double thetaY = xrot.attr<double>(Unicode("thetaY")); + double phiY = xrot.attr<double>(Unicode("phiY")); + double thetaZ = xrot.attr<double>(Unicode("thetaZ")); + double phiZ = xrot.attr<double>(Unicode("phiZ")); + printout(INFO, "NestedBoxReflection", + "+++ Adding reflection rotation \"%s\": " + "(theta/phi)[rad] X: %6.3f %6.3f Y: %6.3f %6.3f Z: %6.3f %6.3f", + element.attr<string>(_U(name)).c_str(), thetaX, phiX, thetaY, phiY, thetaZ, phiZ); + Rotation3D rot = makeRotReflect(thetaX, phiX, thetaY, phiY, thetaZ, phiZ); + Position pos = Position(xpos.x(),xpos.y(),xpos.z()); + // return Transform3D(rot, pos); + return createPlacement(rot, pos); + } + + void place_boxes(int level, Volume vol) { + if ( level >= 0 ) { + Box box = vol.solid(); + double bx = box.x(); + double by = box.y(); + double bz = box.z(); + Material mat = vol.material(); + Box small_box(bx*0.2, by*0.2, bz*0.2); + const char* cols[4] = {"VisibleRed","VisibleBlue","VisibleGreen","VisibleYellow"}; + const char* c; + PlacedVolume pv; + Volume v; + + c = cols[(0+level)%4]; + v = Volume(_toString(1,"box%d"), small_box, mat); + v.setRegion(vol.region()); + v.setSensitiveDetector(sensitive); + v.setLimitSet(vol.limitSet()); + v.setVisAttributes(description, c); + pv = vol.placeVolume(v, Position(0,0,0)); + pv.addPhysVolID(_toString(level,"lvl%d"), 1); + printout(INFO,"NestedBoxReflection","++ Volume: %s Color: %s", v.name(), c); + place_boxes(level-1, v); + + c = cols[(1+level)%4]; + v = Volume(_toString(2,"box%d"), small_box, mat); + v.setRegion(vol.region()); + v.setSensitiveDetector(sensitive); + v.setLimitSet(vol.limitSet()); + v.setVisAttributes(description, c); + pv = vol.placeVolume(v, Position(0.95*bx,0,0)); + pv.addPhysVolID(_toString(level,"lvl%d"), 2); + printout(INFO,"NestedBoxReflection","++ Volume: %s Color: %s", v.name(), c); + place_boxes(level-1, v); + + v = Volume(_toString(1,"axis_x"), Box(bx*0.25, by*0.03, bz*0.03), mat); + v.setVisAttributes(description, c); + pv = vol.placeVolume(v, Position(0.5*bx,0,0)); + printout(INFO,"NestedBoxReflection","++ Volume: %s Color: %s", v.name(), c); + + c = cols[(2+level)%4]; + v = Volume(_toString(3,"box%d"), small_box, mat); + v.setRegion(vol.region()); + v.setSensitiveDetector(sensitive); + v.setLimitSet(vol.limitSet()); + v.setVisAttributes(description, c); + pv = vol.placeVolume(v, Position(0,0.95*by,0)); + pv.addPhysVolID(_toString(level,"lvl%d"), 3); + printout(INFO,"NestedBoxReflection","++ Volume: %s Color: %s", v.name(), c); + place_boxes(level-1, v); + + v = Volume(_toString(1,"axis_y"), Box(bx*0.03, by*0.25, bz*0.03), mat); + v.setVisAttributes(description, c); + pv = vol.placeVolume(v, Position(0,0.5*by,0)); + printout(INFO,"NestedBoxReflection","++ Volume: %s Color: %s", v.name(), c); + + c = cols[(3+level)%4]; + v = Volume(_toString(4,"box%d"), small_box, mat); + v.setRegion(vol.region()); + v.setSensitiveDetector(sensitive); + v.setLimitSet(vol.limitSet()); + v.setVisAttributes(description, c); + pv = vol.placeVolume(v, Position(0,0,0.95*bz)); + pv.addPhysVolID(_toString(level,"lvl%d"), 4); + printout(INFO,"NestedBoxReflection","++ Volume: %s Color: %s", v.name(), c); + place_boxes(level-1, v); + + v = Volume(_toString(1,"axis_z"), Box(bx*0.03, by*0.03, bz*0.25), mat); + v.setVisAttributes(description, c); + pv = vol.placeVolume(v, Position(0,0,0.5*bz)); + printout(INFO,"NestedBoxReflection","++ Volume: %s Color: %s", v.name(), c); + } + } + + 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(x_det.nameStr()+"_det",Box(5*bx,5*by,5*bz),description.air()); + Assembly v_det(x_det.nameStr()+"_det"); + Box box(bx,by,bz); + Volume vol(x_det.nameStr()+"_box",box,description.air()); + PlacedVolume pv; + int cnt = 1; + + sensitive.setType("tracker"); + vol.setAttributes(description,x_det.regionStr(),x_det.limitsStr(),"VisibleGrey"); + + place_boxes(max_level-1, vol); + pv = v_det.placeVolume(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 = 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 = 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 = vol.reflect(sensitive); + Position reflect_pos = Position(0,0,-1.1*bz); + pv = v_det.placeVolume(reflect_vol, reflect_pos); + } + if ( pv.ptr() ) { + pv.addPhysVolID(_toString(max_level,"lvl%d"), ++cnt); + } + + if ( x_det.hasChild(_U(reflect)) ) { + Volume reflect_vol = 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); + } + } + + // Place the calo inside the world + pv = description.pickMotherVolume(detector).placeVolume(v_det); + pv.addPhysVolID("system",x_det.id()); + detector.setPlacement(pv); + return detector; + } + }; +} + +static Ref_t create_detector(Detector& description, xml_dim_t x_det, SensitiveDetector sens) { + NestedBoxReflection builder(description, x_det, sens); + return builder.create(); +} + + +DECLARE_DETELEMENT(NestedBoxReflection,create_detector)