From 9d17d6a4d28a155c3384a3bf222b4cde0033ee9c Mon Sep 17 00:00:00 2001 From: Markus Frank <markus.frank@cern.ch> Date: Mon, 17 Nov 2014 09:27:06 +0000 Subject: [PATCH] Check region definition conversion from compact --- DDCore/include/DD4hep/Objects.h | 6 - .../include/DD4hep/objects/ObjectsInterna.h | 1 - DDCore/include/XML/XMLDimension.h | 18 ++ DDCore/src/Objects.cpp | 22 -- DDCore/src/XML/XMLDimension.cpp | 6 + DDCore/src/plugins/Compact2Objects.cpp | 56 +++-- DDCore/src/plugins/LCDDConverter.cpp | 4 +- DDCore/src/plugins/VolumeMgrTest.cpp | 194 ++++++++++++++++++ 8 files changed, 263 insertions(+), 44 deletions(-) create mode 100644 DDCore/src/plugins/VolumeMgrTest.cpp diff --git a/DDCore/include/DD4hep/Objects.h b/DDCore/include/DD4hep/Objects.h index 82ead32b3..7ca2cc283 100644 --- a/DDCore/include/DD4hep/Objects.h +++ b/DDCore/include/DD4hep/Objects.h @@ -520,8 +520,6 @@ namespace DD4hep { Region& setStoreSecondaries(bool value); Region& setThreshold(double value); Region& setCut(double value); - Region& setLengthUnit(const std::string& unit); - Region& setEnergyUnit(const std::string& unit); /// Access references to user limits std::vector<std::string>& limits() const; @@ -531,10 +529,6 @@ namespace DD4hep { double threshold() const; /// Access secondaries flag bool storeSecondaries() const; - /// Access the length unit - const std::string& lengthUnit() const; - /// Access the energy unit - const std::string& energyUnit() const; }; } /* End namespace Geometry */ diff --git a/DDCore/include/DD4hep/objects/ObjectsInterna.h b/DDCore/include/DD4hep/objects/ObjectsInterna.h index c30d11515..28667566e 100644 --- a/DDCore/include/DD4hep/objects/ObjectsInterna.h +++ b/DDCore/include/DD4hep/objects/ObjectsInterna.h @@ -85,7 +85,6 @@ namespace DD4hep { double threshold; double cut; bool store_secondaries; - std::string lunit, eunit; std::vector<std::string> user_limits; /// Standard constructor RegionObject(); diff --git a/DDCore/include/XML/XMLDimension.h b/DDCore/include/XML/XMLDimension.h index 3e93304eb..0390645d4 100644 --- a/DDCore/include/XML/XMLDimension.h +++ b/DDCore/include/XML/XMLDimension.h @@ -441,6 +441,24 @@ namespace DD4hep { /// Access attribute values: show_daughters bool show_daughters() const; + /// Access min/max parameters: cut + double cut() const; + /// Access min/max parameters: cut + double cut(double default_value) const; + /// Access min/max parameters: threshold + double threshold() const; + /// Access min/max parameters: threshold + double threshold(double default_value) const; + /// Access min/max parameters: eunit + double eunit() const; + /// Access min/max parameters: eunit + double eunit(double default_value) const; + /// Access min/max parameters: lunit + double lunit() const; + /// Access min/max parameters: lunit + double lunit(double default_value) const; + + /// Access child element with tag "dimensions" as Dimension object Dimension dimensions(bool throw_if_not_present = true) const; /// Child access: position diff --git a/DDCore/src/Objects.cpp b/DDCore/src/Objects.cpp index 520632ba0..3e7bc4a1b 100644 --- a/DDCore/src/Objects.cpp +++ b/DDCore/src/Objects.cpp @@ -428,8 +428,6 @@ Region::Region(const string& name) { p->magic = magic_word(); p->store_secondaries = false; p->threshold = 10.0; - p->lunit = "mm"; - p->eunit = "MeV"; p->cut = 10.0; } @@ -448,16 +446,6 @@ Region& Region::setCut(double value) { return *this; } -Region& Region::setLengthUnit(const string& unit) { - object<Object>().lunit = unit; - return *this; -} - -Region& Region::setEnergyUnit(const string& unit) { - object<Object>().eunit = unit; - return *this; -} - /// Access references to user limits vector<string>& Region::limits() const { return object<Object>().user_limits; @@ -478,16 +466,6 @@ bool Region::storeSecondaries() const { return object<Object>().store_secondaries; } -/// Access the length unit -const std::string& Region::lengthUnit() const { - return object<Object>().lunit; -} - -/// Access the energy unit -const std::string& Region::energyUnit() const { - return object<Object>().eunit; -} - #undef setAttr #if 0 diff --git a/DDCore/src/XML/XMLDimension.cpp b/DDCore/src/XML/XMLDimension.cpp index ffa132d01..d9ed8f069 100644 --- a/DDCore/src/XML/XMLDimension.cpp +++ b/DDCore/src/XML/XMLDimension.cpp @@ -159,6 +159,12 @@ XML_ATTR_ACCESSOR(int, type) XML_ATTR_ACCESSOR(bool, visible) XML_ATTR_ACCESSOR(bool, show_daughters) + +XML_ATTR_ACCESSOR_DOUBLE(cut) +XML_ATTR_ACCESSOR_DOUBLE(threshold) +XML_ATTR_ACCESSOR_DOUBLE(lunit) +XML_ATTR_ACCESSOR_DOUBLE(eunit) + #if 0 XML_ATTR_ACCESSOR(double,) XML_ATTR_ACCESSOR(double,) diff --git a/DDCore/src/plugins/Compact2Objects.cpp b/DDCore/src/plugins/Compact2Objects.cpp index 8b99d8540..d37fe2adb 100644 --- a/DDCore/src/plugins/Compact2Objects.cpp +++ b/DDCore/src/plugins/Compact2Objects.cpp @@ -296,7 +296,7 @@ template <> void Converter<Material>::operator()(xml_h e) const { cout << "degree " << XML::_toDouble(_Unicode(degree)) << endl; #endif //throw 1; - printout(DEBUG, "Compact", "++ Creating material %s", matname); + printout(DEBUG, "Compact", "++ Converting material %s", matname); mat = mix = new TGeoMixture(matname, composites.size(), dens_val); mat->SetRadLen(radlen_val, intlen_val); size_t ifrac = 0; @@ -310,7 +310,7 @@ template <> void Converter<Material>::operator()(xml_h e) const { else if (0 != (comp_elt = table->FindElement(nam.c_str()))) fraction *= comp_elt->A(); else - throw_print("Compact2Objects[ERROR]: Creating material:" + mname + " Element missing: " + nam); + throw_print("Compact2Objects[ERROR]: Converting material:" + mname + " Element missing: " + nam); composite_fractions_total += fraction; composite_fractions.push_back(fraction); } @@ -330,7 +330,7 @@ template <> void Converter<Material>::operator()(xml_h e) const { else if (0 != (comp_elt = table->FindElement(nam.c_str()))) mix->AddElement(comp_elt, fraction); else - throw_print("Compact2Objects[ERROR]: Creating material:" + mname + " Element missing: " + nam); + throw_print("Compact2Objects[ERROR]: Converting material:" + mname + " Element missing: " + nam); } // Update estimated density if not provided. if ( has_density ) { @@ -410,6 +410,8 @@ template <> void Converter<VisAttr>::operator()(xml_h e) const { float r = e.hasAttr(_U(r)) ? e.attr<float>(_U(r)) : 1.0f; float g = e.hasAttr(_U(g)) ? e.attr<float>(_U(g)) : 1.0f; float b = e.hasAttr(_U(b)) ? e.attr<float>(_U(b)) : 1.0f; + + printout(DEBUG, "Compact", "++ Converting VisAttr structure: %s.",attr.name()); attr.setColor(r, g, b); if (e.hasAttr(_U(alpha))) attr.setAlpha(e.attr<float>(_U(alpha))); @@ -476,16 +478,25 @@ template <> void Converter<AlignmentEntry>::operator()(xml_h e) const { /** Specialized converter for compact region objects. * */ -template <> void Converter<Region>::operator()(xml_h e) const { - Region region(e.attr<string>(_U(name))); +template <> void Converter<Region>::operator()(xml_h elt) const { + xml_dim_t e = elt; + Region region(e.nameStr()); vector<string>&limits = region.limits(); - string ene = e.attr<string>(_U(eunit)), len = e.attr<string>(_U(lunit)); + xml_attr_t cut = elt.attr_nothrow(_U(cut)); + xml_attr_t threshold = elt.attr_nothrow(_U(threshold)); + xml_attr_t store_secondaries = elt.attr_nothrow(_U(store_secondaries)); + double ene = e.eunit(1.0), len = e.lunit(1.0); - region.setEnergyUnit(ene); - region.setLengthUnit(len); - region.setCut(_multiply<double>(e.attr<string>(_U(cut)), len)); - region.setThreshold(_multiply<double>(e.attr<string>(_U(threshold)), ene)); - region.setStoreSecondaries(e.attr<bool>(_U(store_secondaries))); + printout(DEBUG, "Compact", "++ Converting region structure: %s.",region.name()); + if ( cut ) { + region.setCut(elt.attr<double>(cut)*len); + } + if ( threshold ) { + region.setThreshold(elt.attr<double>(threshold)*ene); + } + if ( store_secondaries ) { + region.setStoreSecondaries(elt.attr<bool>(store_secondaries)); + } for (xml_coll_t user_limits(e, _U(limitsetref)); user_limits; ++user_limits) limits.push_back(user_limits.attr<string>(_U(name))); lcdd.addRegion(region); @@ -505,7 +516,7 @@ template <> void Converter<Readout>::operator()(xml_h e) const { Readout ro(name); Ref_t idSpec; - printout(DEBUG, "Compact", "++ Creating readout structure: %s.",ro.name()); + printout(DEBUG, "Compact", "++ Converting readout structure: %s.",ro.name()); if (seg) { // Segmentation is not mandatory! string type = seg.attr<string>(_U(type)); Segmentation segment(type, name); @@ -551,6 +562,7 @@ template <> void Converter<Readout>::operator()(xml_h e) const { */ template <> void Converter<LimitSet>::operator()(xml_h e) const { LimitSet ls(e.attr<string>(_U(name))); + printout(DEBUG, "Compact", "++ Converting LimitSet structure: %s.",ls.name()); for (xml_coll_t c(e, _U(limit)); c; ++c) { Limit limit; limit.particles = c.attr<string>(_U(particles)); @@ -722,6 +734,16 @@ template <> void Converter<DetElement>::operator()(xml_h element) const { string name = element.attr<string>(_U(name)); string name_match = ":" + name + ":"; string type_match = ":" + type + ":"; + + // Allow to define readout structures in the local element + xml_coll_t(element, _U(readout)).for_each(Converter < Readout > (this->lcdd)); + // Allow to define region structures in the local element + xml_coll_t(element, _U(region)).for_each(Converter < Region > (this->lcdd)); + // Allow to define limitset structures in the local element + xml_coll_t(element, _U(limitset)).for_each(Converter < LimitSet > (this->lcdd)); + // Allow to define visualization definitions in the local element + xml_coll_t(element,_U(vis)).for_each(Converter < VisAttr > (this->lcdd)); + if (req_dets && !strstr(req_dets, name_match.c_str())) return; if (req_typs && !strstr(req_typs, type_match.c_str())) @@ -800,6 +822,12 @@ template <> void Converter<DetElementInclude>::operator()(xml_h element) const { Converter < Compact > (this->lcdd)(node); else if ( tag == "define" ) xml_coll_t(node, _U(constant)).for_each(Converter < Constant > (this->lcdd)); + else if ( tag == "readouts" ) + xml_coll_t(node, _U(readout)).for_each(Converter < Readout > (this->lcdd)); + else if ( tag == "regions" ) + xml_coll_t(node, _U(region)).for_each(Converter < Region > (this->lcdd)); + else if ( tag == "limitsets" ) + xml_coll_t(node, _U(limitset)).for_each(Converter < LimitSet > (this->lcdd)); else if ( tag == "display" ) xml_coll_t(node,_U(vis)).for_each(Converter < VisAttr > (this->lcdd)); else if ( tag == "detector" ) @@ -825,8 +853,10 @@ template <> void Converter<Compact>::operator()(xml_h element) const { xml_coll_t(compact, _U(limits)).for_each(_U(limitset), Converter < LimitSet > (lcdd)); xml_coll_t(compact, _U(display)).for_each(_U(include), Converter < DetElementInclude > (lcdd)); xml_coll_t(compact, _U(display)).for_each(_U(vis), Converter < VisAttr > (lcdd)); - printout(DEBUG, "Compact", "++ Converting readout structures..."); + printout(DEBUG, "Compact", "++ Converting readout structures..."); xml_coll_t(compact, _U(readouts)).for_each(_U(readout), Converter < Readout > (lcdd)); + printout(DEBUG, "Compact", "++ Converting region structures..."); + xml_coll_t(compact, _U(regions)).for_each(_U(region), Converter < Region > (lcdd)); printout(DEBUG, "Compact", "++ Converting included files with subdetector structures..."); xml_coll_t(compact, _U(detectors)).for_each(_U(include), Converter < DetElementInclude > (lcdd)); printout(DEBUG, "Compact", "++ Converting detector structures..."); diff --git a/DDCore/src/plugins/LCDDConverter.cpp b/DDCore/src/plugins/LCDDConverter.cpp index f26f5f82e..e511dc7ce 100644 --- a/DDCore/src/plugins/LCDDConverter.cpp +++ b/DDCore/src/plugins/LCDDConverter.cpp @@ -780,8 +780,8 @@ xml_h LCDDConverter::handleRegion(const std::string& /* name */, Region region) geo.doc_regions.append(reg = xml_elt_t(geo.doc, _U(region))); reg.setAttr(_U(name), region.name()); reg.setAttr(_U(cut), region.cut()); - reg.setAttr(_U(eunit), region.energyUnit()); - reg.setAttr(_U(lunit), region.lengthUnit()); + reg.setAttr(_U(eunit), "GeV"); // TGeo has energy in GeV + reg.setAttr(_U(lunit), "cm"); // TGeo has lengths in cm reg.setAttr(_U(store_secondaries), region.storeSecondaries()); geo.xmlRegions[region] = reg; } diff --git a/DDCore/src/plugins/VolumeMgrTest.cpp b/DDCore/src/plugins/VolumeMgrTest.cpp new file mode 100644 index 000000000..13701ecf0 --- /dev/null +++ b/DDCore/src/plugins/VolumeMgrTest.cpp @@ -0,0 +1,194 @@ +// $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/IDDescriptor.h" +#include "DD4hep/VolumeManager.h" + +// C/C++ include files +#include <stdexcept> +#include <algorithm> + +using namespace std; +using namespace DD4hep; +using namespace DD4hep::Geometry; + + +namespace { + /** @class VolIDTest + * + * Test the volume manager by scanning the sensitive + * volumes of one or several subdetectors. + * + * @author M.Frank + * @version 1.0 + */ + struct VolIDTest { + typedef vector<PlacedVolume::VolID> VolIDs; + /// Helper to scan volume ids + struct FND { + const string& test; + FND(const string& c) : test(c) {} + bool operator()(const VolIDs::value_type& c) const { return c.first == test; } + }; + IDDescriptor m_iddesc; + VolumeManager m_mgr; + DetElement m_det; + + /// Initializing constructor + VolIDTest(LCDD& lcdd, DetElement sdet, size_t depth); + /// Default destructor + virtual ~VolIDTest() {} + /// Check volume integrity + void checkVolume(DetElement e, PlacedVolume pv, const VolIDs& child_ids) const; + /// Walk through tree of detector elements + void walk(DetElement de, VolIDs ids, size_t depth, size_t mx_depth) const; + /// Walk through tree of volume placements + void walkVolume(DetElement e, PlacedVolume pv, VolIDs ids, size_t depth, size_t mx_depth) const; + + /// Action routine to execute the test + static long run(LCDD& lcdd,int argc,char** argv); + }; +} + +/// Initializing constructor +VolIDTest::VolIDTest(LCDD& lcdd, DetElement sdet, size_t depth) : m_det(sdet) { + m_mgr = lcdd.volumeManager(); + if ( !m_det.isValid() ) { + stringstream err; + err << "The subdetector " << m_det.name() << " is not known to the geometry."; + printout(INFO,"VolIDTest",err.str().c_str()); + throw runtime_error(err.str()); + } + if ( !lcdd.sensitiveDetector(m_det.name()).isValid() ) { + stringstream err; + err << "The sensitive detector of subdetector " << m_det.name() + << " is not known to the geometry."; + printout(INFO,"VolIDTest",err.str().c_str()); + throw runtime_error(err.str()); + } + m_iddesc = lcdd.sensitiveDetector(m_det.name()).readout().idSpec(); + walk(m_det,VolIDs(),0,depth); +} + +/// Check volume integrity +void VolIDTest::checkVolume(DetElement e, PlacedVolume pv, const VolIDs& child_ids) const { + stringstream err, log; + VolumeID vid = m_iddesc.encode(child_ids); + VolumeID mask = 0xFFFFULL; + vid |= mask<<(31+16); + try { + DetElement det = m_mgr.lookupDetector(vid); + DetElement det_elem = m_mgr.lookupDetElement(vid); + PlacedVolume det_place = m_mgr.lookupPlacement(vid); + if ( pv.ptr() != det_place.ptr() ) { + err << "Wrong placement " + << " got " << det_place.name() << " (" << (void*)det_place.ptr() << ")" + << " instead of " << pv.name() << " (" << (void*)pv.ptr() << ") " + << " vid:" << (void*)vid; + } + else if ( det_elem.ptr() != e.ptr() ) { + err << "Wrong associated detector element vid=" << (void*)vid + << " got " << det_elem.path() << " (" << (void*)det_elem.ptr() << ") " + << " instead of " << e.path() << " (" << (void*)e.ptr() << ")" + << " vid:" << (void*)vid; + } + else if ( det.ptr() != m_det.ptr() ) { + err << "Wrong associated detector " + << " vid:" << (void*)vid; + } + } + catch(const exception& ex) { + err << "Lookup " << pv.name() << " id:" << (void*)vid << " path:" << e.path() << " error:" << ex.what(); + } + const IDDescriptor::FieldMap& m = m_iddesc.fields(); + log << "IDS(" << pv.name() << "): "; + for(size_t fi=0; fi<m.size(); ++fi) { + IDDescriptor::Field fld = m_iddesc.field(fi); + if ( find_if(child_ids.begin(),child_ids.end(),FND(fld->name())) == child_ids.end() ) continue; + log << fld->name() << "=" << fld->value(vid) << " "; + } + log << " vid:" << (void*)vid; + if ( !err.str().empty() ) { + printout(ERROR,m_det.name(),err.str()+" "+log.str()); + throw runtime_error(err.str()); + } + printout(INFO,m_det.name(),"OK: "+log.str()); +} + +/// Walk through tree of detector elements +void VolIDTest::walkVolume(DetElement e, PlacedVolume pv, VolIDs ids, size_t depth, size_t mx_depth) const { + if ( depth <= mx_depth ) { + const TGeoNode* current = pv.ptr(); + TObjArray* nodes = current->GetNodes(); + int num_children = nodes ? nodes->GetEntriesFast() : 0; + for(int i=0; i<num_children; ++i) { + TGeoNode* node = (TGeoNode*)nodes->At(i); + PlacedVolume place(node); + VolIDs child_ids(ids); + stringstream err, log; + + child_ids.insert(child_ids.end(),place.volIDs().begin(),place.volIDs().end()); + bool is_sensitive = place.volume().isSensitive(); + if ( is_sensitive ) { + checkVolume(e,place,child_ids); + } + walkVolume(e,place,child_ids,depth+1,mx_depth); + } + } +} + +/// Walk through tree of volume placements +void VolIDTest::walk(DetElement e, VolIDs ids, size_t depth, size_t mx_depth) const { + if ( depth <= mx_depth ) { + DetElement::Children::const_iterator i; + const DetElement::Children& children = e.children(); + PlacedVolume pv = e.placement(); + VolIDs child_ids(ids); + bool is_sensitive = pv.volume().isSensitive(); + child_ids.insert(child_ids.end(),pv.volIDs().begin(),pv.volIDs().end()); + for (i=children.begin(); i!=children.end(); ++i) { + walk((*i).second,child_ids,depth+1,mx_depth); + } + if ( !is_sensitive && children.empty() ) { + walkVolume(e,pv,child_ids,depth+1,mx_depth); + } + else if ( is_sensitive ) { + checkVolume(e, pv,child_ids); + } + } +} + +/// Action routine to execute the test +long VolIDTest::run(LCDD& lcdd,int argc,char** argv) { + cout << "++ Processing plugin...CLICSid_VolMgrTest..." << endl; + for(int i=1; i<argc;++i) { + string name = argv[i]+1; + if ( name == "all" || name == "All" || name == "ALL" ) { + const DetElement::Children& children = lcdd.world().children(); + for (DetElement::Children::const_iterator i=children.begin(); i!=children.end(); ++i) { + DetElement sdet = (*i).second; + cout << "++ Processing subdetector: " << sdet.name() << endl; + VolIDTest test(lcdd,sdet,99); + } + return 1; + } + cout << "++ Processing subdetector: " << name << endl; + VolIDTest test(lcdd,lcdd.detector(name),99); + } + return 1; +} + +namespace DD4hep { + using ::VolIDTest; +} +DECLARE_APPLY(CLICSiD_VolMgrTest,VolIDTest::run) -- GitLab