diff --git a/DDCore/include/DD4hep/LCDDData.h b/DDCore/include/DD4hep/LCDDData.h index 0cb40975c4606461d628cf52aa1145b45769efb5..081c1705dcca38f19ddc21eb0a46079652b5cec1 100644 --- a/DDCore/include/DD4hep/LCDDData.h +++ b/DDCore/include/DD4hep/LCDDData.h @@ -116,6 +116,9 @@ namespace DD4hep { /// Volume manager reference VolumeManager m_volManager; + /// Flag to inhibit the access to global constants. Value set by constants section 'LCDD_InhibitConstants' + bool m_inhibitConstants; + protected: /// Default constructor LCDDData(); diff --git a/DDCore/include/DD4hep/LCDDHelper.h b/DDCore/include/DD4hep/LCDDHelper.h new file mode 100644 index 0000000000000000000000000000000000000000..4c538981f607d7233f8ff245475fb72904dda2e1 --- /dev/null +++ b/DDCore/include/DD4hep/LCDDHelper.h @@ -0,0 +1,54 @@ +// $Id: Handle.h 1679 2015-03-27 15:24:39Z /DC=ch/DC=cern/OU=Organic Units/OU=Users/CN=sailer/CN=683529/CN=Andre Sailer $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +#ifndef DD4HEP_LCDDHELPER_H +#define DD4HEP_LCDDHELPER_H +#include "DD4hep/LCDD.h" + +/// Namespace for the AIDA detector description toolkit +namespace DD4hep { + + + /// Namespace for the geometry part of the AIDA detector description toolkit + namespace Geometry { + + /// LCDDHelper: class to shortcut certain questions to the DD4hep detector description interface + /** + * + * Note: This class may be extended with additional useful (generic) functionality, + * which requires the use of the main LCDD object. + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_GEOMETRY + */ + class LCDDHelper : public Handle<LCDD> { + public: + /// Default constructor + explicit LCDDHelper() : handle_t() {} + /// Initializing constructor from pointer + explicit LCDDHelper(LCDD* lcdd_ptr) : handle_t(lcdd_ptr) {} + /// Initializing constructor from pointer + explicit LCDDHelper(LCDD& lcdd_ref) : handle_t(&lcdd_ref) {} + /// Copy constructor + explicit LCDDHelper(const handle_t& h) : handle_t(h) {} + /// Default destructor + ~LCDDHelper() {} + /// Access the sensitive detector of a given subdetector (if the sub-detector is sensitive!) + SensitiveDetector sensitiveDetector(const std::string& detector) const; + /// Given a detector element, access it's sensitive detector (if the sub-detector is sensitive!) + SensitiveDetector sensitiveDetector(DetElement detector) const; + /// Find a detector element by it's system ID + DetElement detectorByID(int id) const; + }; + + } /* End namespace Geometry */ +} /* End namespace DD4hep */ + +#endif /* DD4HEP_LCDDHELPER_H */ diff --git a/DDCore/src/Handle.cpp b/DDCore/src/Handle.cpp index 150f7ef2bd38995b5c390300576bfab578634395..3583f89dbb9105f0a752ee786f53cd93e08a4239 100644 --- a/DDCore/src/Handle.cpp +++ b/DDCore/src/Handle.cpp @@ -201,6 +201,7 @@ namespace DD4hep { #include "TMap.h" #include "TColor.h" +DD4HEP_INSTANTIATE_HANDLE_UNNAMED(LCDD); DD4HEP_INSTANTIATE_HANDLE_UNNAMED(TObject); DD4HEP_INSTANTIATE_HANDLE(TNamed); diff --git a/DDCore/src/LCDDData.cpp b/DDCore/src/LCDDData.cpp index d3e2f3287a06c1bfa0c1476c86453ddfd65c5cce..811e962cb657664198f598ca502be0957ee3be86 100644 --- a/DDCore/src/LCDDData.cpp +++ b/DDCore/src/LCDDData.cpp @@ -26,7 +26,8 @@ using namespace std; LCDDData::LCDDData() : m_manager(0), m_world(), m_trackers(), m_worldVol(), m_trackingVol(), m_field("global"), - m_extensions(typeid(LCDDData)), m_volManager() + m_extensions(typeid(LCDDData)), m_volManager(), + m_inhibitConstants(false) { InstanceCount::increment(this); } @@ -63,7 +64,7 @@ void LCDDData::destroyData(bool destroy_mgr) { m_invisibleVis.clear(); m_materialVacuum.clear(); m_materialAir.clear(); - + m_inhibitConstants = false; if ( destroy_mgr ) deletePtr(m_manager); else { @@ -98,10 +99,12 @@ void LCDDData::clearData() { m_materialAir.clear(); m_volManager.clear(); m_manager = 0; + m_inhibitConstants = false; } /// Adopt all data from source structure void LCDDData::adoptData(LCDDData& source) { + m_inhibitConstants = source.m_inhibitConstants; m_extensions = source.m_extensions; m_motherVolumes = source.m_motherVolumes; m_world = source.m_world; diff --git a/DDCore/src/LCDDHelper.cpp b/DDCore/src/LCDDHelper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1a993ceb6648674384d2dac0f365b8f6fb34d124 --- /dev/null +++ b/DDCore/src/LCDDHelper.cpp @@ -0,0 +1,49 @@ +// $Id: Handle.h 1679 2015-03-27 15:24:39Z /DC=ch/DC=cern/OU=Organic Units/OU=Users/CN=sailer/CN=683529/CN=Andre Sailer $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +#include "DD4hep/LCDDHelper.h" + +using namespace std; +using namespace DD4hep::Geometry; + +/// Access the sensitive detector of a given subdetector (if the sub-detector is sensitive!) +SensitiveDetector LCDDHelper::sensitiveDetector(const std::string& detector) const { + const string& det_name = detector; + SensitiveDetector sensitive = ptr()->sensitiveDetector(det_name); + return sensitive; +} + +/// Given a detector element, access it's sensitive detector (if the sub-detector is sensitive!) +SensitiveDetector LCDDHelper::sensitiveDetector(DetElement detector) const { + for(DetElement par = detector; par.isValid(); par = par.parent()) { + if ( par.ptr() != ptr()->world().ptr() ) { + PlacedVolume pv = par.placement(); + if ( pv.isValid() ) { + const PlacedVolume::VolIDs& ids = pv.volIDs(); + for(PlacedVolume::VolIDs::const_iterator i=ids.begin(); i!=ids.end();++i) { + if ( (*i).first == "system" ) { + return sensitiveDetector(par.name()); + } + } + } + } + } + return SensitiveDetector(0); +} + +/// Find a detector element by it's system ID +DetElement LCDDHelper::detectorByID(int id) const { + const LCDD::HandleMap& dets = ptr()->detectors(); + for(LCDD::HandleMap::const_iterator i=dets.begin(); i!=dets.end(); ++i) { + DetElement de = (*i).second; + if ( de.id() == id ) return de; + } + return DetElement(0); +} + diff --git a/DDCore/src/LCDDImp.cpp b/DDCore/src/LCDDImp.cpp index 9e0015c9dcfb4055e89842428bfa9d0fdc3d1a66..6598b500d9279271e86808b1a42b0b7c69d02518 100644 --- a/DDCore/src/LCDDImp.cpp +++ b/DDCore/src/LCDDImp.cpp @@ -10,6 +10,7 @@ #include "DD4hep/Plugins.h" #include "DD4hep/Printout.h" #include "DD4hep/GeoHandler.h" +#include "DD4hep/LCDDHelper.h" #include "DD4hep/InstanceCount.h" #include "DD4hep/objects/VolumeManagerInterna.h" #include "LCDDImp.h" @@ -191,6 +192,19 @@ Volume LCDDImp::pickMotherVolume(const DetElement& de) const { LCDD& LCDDImp::addDetector(const Ref_t& ref_det) { DetElement det_element(ref_det); + LCDDHelper helper(this); + DetElement existing_det = helper.detectorByID(det_element.id()); + + if ( existing_det.isValid() ) { + SensitiveDetector sd = helper.sensitiveDetector(existing_det); + if ( sd.isValid() ) { + stringstream str; + str << "LCDD: The sensitive sub-detectors " << det_element.name() << " and " + << existing_det.name() << " have the identical ID:" << det_element.id() << "."; + printout(ERROR,"LCDD",str.str()); + throw runtime_error(str.str()); + } + } m_detectors.append(ref_det); Volume volume = det_element.placement()->GetMotherVolume(); if ( volume == m_worldVol ) { @@ -208,25 +222,53 @@ LCDD& LCDDImp::addDetector(const Ref_t& ref_det) { return *this; } } - throw runtime_error("LCDD: The detector" + string(det_element.name()) + " has no known parent."); + throw runtime_error("LCDD: The detector " + string(det_element.name()) + " has no known parent."); +} + +/// Add a new constant by named reference to the detector description +LCDD& LCDDImp::addConstant(const Ref_t& x) { + if ( strcmp(x.name(),"LCDD_InhibitConstants") == 0 ) { + const char* title = x->GetTitle(); + char c = ::toupper(title[0]); + m_inhibitConstants = (c=='Y' || c=='T' || c=='1'); + } + m_define.append(x, false); + return *this; +} + +/// Retrieve a constant by it's name from the detector description +Constant LCDDImp::constant(const std::string& name) const { + if ( !m_inhibitConstants ) { + return getRefChild(m_define, name); + } + throw runtime_error("LCDD:constant("+name+"): Access to global constants is inhibited."); } /// Typed access to constants: access string values string LCDDImp::constantAsString(const string& name) const { - Ref_t c = constant(name); - if (c.isValid()) - return c->GetTitle(); - throw runtime_error("LCDD: The constant " + name + " is not known to the system."); + if ( !m_inhibitConstants ) { + Ref_t c = constant(name); + if (c.isValid()) + return c->GetTitle(); + throw runtime_error("LCDD:constantAsString: The constant " + name + " is not known to the system."); + } + throw runtime_error("LCDD:constantAsString("+name+"):: Access to global constants is inhibited."); } /// Typed access to constants: long values long LCDDImp::constantAsLong(const string& name) const { - return _toLong(constantAsString(name)); + if ( !m_inhibitConstants ) { + return _toLong(constantAsString(name)); + } + throw runtime_error("LCDD:constantAsLong("+name+"): Access to global constants is inhibited."); } /// Typed access to constants: double values double LCDDImp::constantAsDouble(const string& name) const { - return _toDouble(constantAsString(name)); + if ( !m_inhibitConstants ) { + return _toDouble(constantAsString(name)); + } + throw runtime_error("LCDD:constantAsDouble("+name+"): Access to global constants is inhibited."); } /// Add a field component by named reference to the detector description diff --git a/DDCore/src/LCDDImp.h b/DDCore/src/LCDDImp.h index 416f93111e3cd7c65116a937e80f6f5373ff15b5..d2026c3c9c6aafe329651cfdac6e156b0dd27bb0 100644 --- a/DDCore/src/LCDDImp.h +++ b/DDCore/src/LCDDImp.h @@ -161,9 +161,8 @@ namespace DD4hep { virtual double constantAsDouble(const std::string& name) const; /// Retrieve a constant by it's name from the detector description - virtual Constant constant(const std::string& name) const { - return getRefChild(m_define, name); - } + virtual Constant constant(const std::string& name) const; + /// Retrieve a limitset by it's name from the detector description virtual LimitSet limitSet(const std::string& name) const { return getRefChild(m_limits, name); @@ -307,10 +306,8 @@ namespace DD4hep { } /// Add a new constant by named reference to the detector description - virtual LCDD& addConstant(const Ref_t& x) { - m_define.append(x, false); - __R; - } + virtual LCDD& addConstant(const Ref_t& x); + /// Add a new limit set by named reference to the detector description virtual LCDD& addLimitSet(const Ref_t& x) { m_limits.append(x); diff --git a/DDCore/src/plugins/LCDDHelperTest.cpp b/DDCore/src/plugins/LCDDHelperTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..45e043aad132d29a2b99df316d4de0d7cfd47858 --- /dev/null +++ b/DDCore/src/plugins/LCDDHelperTest.cpp @@ -0,0 +1,84 @@ +// $Id: TubeSegment_geo.cpp 633 2013-06-21 13:50:50Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/LCDD.h" +#include "DD4hep/Printout.h" +#include "DD4hep/Factories.h" +#include "DD4hep/LCDDHelper.h" + +// C/C++ include files +#include <stdexcept> +#include <algorithm> + +using namespace std; +using namespace DD4hep; +using namespace DD4hep::Geometry; + + +namespace { + + /** @class LCDDHelperTest + * + * Test LCDDHelper handle object to easily access the sensitive detector object of a detector + * using either the subdetector name or the detector element (or one of its children). + * + * This helper recusively searches for all children of a subdetector the sensitive detector. + * + * See: DD4hep/LCDDHelper.h + * Test: geoPluginRun -input file:../DD4hep.trunk/examples/CLICSiD/compact/compact.xml \ + * -plugin CLICSiD_LCDDHelperTest \ + * optional: -<detector-name (default:SiVertexEndcap)> [Note the '-'!!!] + * + * @author M.Frank + * @version 1.0 + */ + struct LCDDHelperTest { + /// Initializing constructor + LCDDHelperTest(LCDD& lcdd, int argc, char** argv) { + LCDDHelper h(&lcdd); + const char* nam = argc>1 ? argv[1]+1 : "SiVertexEndcap"; + printSD(h,nam); + DetElement de = lcdd.detector(nam); + walkSD(h,de); + } + void walkSD(LCDDHelper h, DetElement de) const { + printSD(h,de); + for(DetElement::Children::const_iterator i=de.children().begin(); i!=de.children().end(); ++i) { + DetElement child = (*i).second; + printSD(h,child); + if ( child.children().size() > 0 ) walkSD(h,child); + } + } + void printSD(LCDDHelper h, DetElement de) const { + SensitiveDetector sd = h.sensitiveDetector(de); + printout(INFO,"LCDDHelperTest","Sensitive detector[%s]: %p --> %s",de.path().c_str(),(void*)sd.ptr(), + sd.ptr() ? sd.name() : "????"); + + } + void printSD(LCDDHelper h, const char* nam) const { + SensitiveDetector sd = h.sensitiveDetector(nam); + printout(INFO,"LCDDHelperTest","Sensitive detector[%s]: %p --> %s",nam,(void*)sd.ptr(), + sd.ptr() ? sd.name() : "????"); + + } + /// Default destructor + virtual ~LCDDHelperTest() {} + /// Action routine to execute the test + static long run(LCDD& lcdd,int argc,char** argv) { + LCDDHelperTest test(lcdd,argc,argv); + return 1; + } + }; +} + +namespace DD4hep { + using ::LCDDHelperTest; +} +DECLARE_APPLY(CLICSiD_LCDDHelperTest,LCDDHelperTest::run) diff --git a/doc/release.notes b/doc/release.notes index a8c8086642f78765ca67d0ce960bc60658a06474..d49cc1800f48cf8453520d3521356c2fcdacde80 100644 --- a/doc/release.notes +++ b/doc/release.notes @@ -3,6 +3,25 @@ DD4hep ---- Release Notes ================================= + +2015/06/17 Markus Frank +----------------------- + - Add possibility to block access to constants by name from LCDD. + Functionality enabled by a constant named "LCDD_InhibitConstants" with value "1", "True", "Yes". + Test: geoDisplay -compact file:../DD4hep.trunk/examples/ClientTests/compact/InhibitConstants.xml + + - Add LCDDHelper handle object to easily access the sensitive detector object of a detector + using either the subdetector name or the detector element (or one of its children). + See: DD4hep/LCDDHelper.h + Test: geoPluginRun -input file:../DD4hep.trunk/examples/CLICSiD/compact/compact.xml \ + -plugin CLICSiD_LCDDHelperTest \ + optional: -<detector-name (default:SiVertexEndcap)> [Note the '-'!!!] + + - Check when adding new sub-detector detector elements if a given one already exists. + if yes: exception. + Test: geoDisplay -compact file:../DD4hep.trunk/examples/ClientTests/compact/DuplicateSysID.xml + + -------- | v00-12 | -------- diff --git a/examples/ClientTests/compact/DuplicateSysID.xml b/examples/ClientTests/compact/DuplicateSysID.xml new file mode 100644 index 0000000000000000000000000000000000000000..f8cf0d599639f355d2d139aed7a850c4200c9943 --- /dev/null +++ b/examples/ClientTests/compact/DuplicateSysID.xml @@ -0,0 +1,57 @@ +<lccdd xmlns:compact="http://www.lcsim.org/schemas/compact/1.0" + xmlns:xs="http://www.w3.org/2001/XMLSchema" + xs:noNamespaceSchemaLocation="http://www.lcsim.org/schemas/compact/1.0/compact.xsd"> + + <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"/> + </display> + + <detectors> + <comment>Boxes</comment> + <detector id="3" name="B3" type="DD4hep_BoxSegment" readout="SiliconHits" sensitive="true"> + <comment>Vertical box</comment> + <material name="Steel235"/> + <sensitive type="calo"/> + <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="DD4hep_BoxSegment" readout="SiliconHits" sensitive="true"> + <comment>Vertical box</comment> + <material name="Steel235"/> + <sensitive type="calo"/> + <box x="10" y="20" z="30"/> + <position x="0" y="0" z="0"/> + <rotation x="0" y="0" z="0"/> + </detector> + </detectors> + + <readouts> + <readout name="SiliconHits"> + <id>system:8</id> + </readout> + </readouts> +</lccdd> + diff --git a/examples/ClientTests/compact/InhibitConstants.xml b/examples/ClientTests/compact/InhibitConstants.xml new file mode 100644 index 0000000000000000000000000000000000000000..6a6d0a962587e877b04965b5e53198ea532e9971 --- /dev/null +++ b/examples/ClientTests/compact/InhibitConstants.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<lccdd xmlns:compact="http://www.lcsim.org/schemas/compact/1.0" + xmlns:xs="http://www.w3.org/2001/XMLSchema" + xs:noNamespaceSchemaLocation="http://www.lcsim.org/schemas/compact/1.0/compact.xsd"> + + <define> + <constant name="LCDD_InhibitConstants" value="1"/>; + <constant name="world_side" value="2*m"/> + <constant name="world_x" value="world_side/2"/> + <constant name="world_y" value="world_side/2"/> + <constant name="world_z" value="world_side/2"/> + </define> + <includes> + <gdmlFile ref="${DD4hepINSTALL}/DDDetectors/compact/elements.xml"/> + <gdmlFile ref="${DD4hepINSTALL}/DDDetectors/compact/materials.xml"/> + </includes> + + <include ref="MiniTel.xml"/> +</lccdd> diff --git a/examples/ClientTests/src/MiniTel.cpp b/examples/ClientTests/src/MiniTel.cpp index 563b9eabf8e8c2f9da33a64a9ee724e9a5ca2cf3..626769203c774dee91b721fe2dfd73b116e737b8 100644 --- a/examples/ClientTests/src/MiniTel.cpp +++ b/examples/ClientTests/src/MiniTel.cpp @@ -38,7 +38,6 @@ static Ref_t create_detector(LCDD &lcdd, xml_h e, SensitiveDetector sens) { string det_type = x_det.typeStr(); //det_type is the type of the xml-detelement Assembly assembly (det_name); int detectors_id = x_det.id(); - string visualisation = x_det.visStr(); @@ -112,6 +111,8 @@ static Ref_t create_detector(LCDD &lcdd, xml_h e, SensitiveDetector sens) { m_volume.setSensitiveDetector(sens); } sdet.setPlacement(pv); + // Support additional test if LCDD_InhibitConstants is set to TRUE + lcdd.constant<double>("world_side"); return sdet; } DECLARE_DETELEMENT(MiniTelPixel,create_detector)