From 6398c84e2e5a6863dd1c325821db684cc7dfc133 Mon Sep 17 00:00:00 2001 From: Markus Frank <markus.frank@cern.ch> Date: Thu, 21 Feb 2013 20:06:02 +0000 Subject: [PATCH] Use standard plusgin directory and create plugin library --- DDCore/src/plugins/Compact2Objects.cpp | 742 +++++++++++++++++++ DDCore/src/plugins/Geant4XML.cpp | 41 ++ DDCore/src/plugins/LCDD2Output.cpp | 198 +++++ DDCore/src/plugins/LCDDConverter.cpp | 959 +++++++++++++++++++++++++ DDCore/src/plugins/LCDDConverter.h | 171 +++++ DDCore/src/plugins/LCDDFields.cpp | 75 ++ DDCore/src/plugins/StandardPlugins.cpp | 50 ++ 7 files changed, 2236 insertions(+) create mode 100644 DDCore/src/plugins/Compact2Objects.cpp create mode 100644 DDCore/src/plugins/Geant4XML.cpp create mode 100644 DDCore/src/plugins/LCDD2Output.cpp create mode 100644 DDCore/src/plugins/LCDDConverter.cpp create mode 100644 DDCore/src/plugins/LCDDConverter.h create mode 100644 DDCore/src/plugins/LCDDFields.cpp create mode 100644 DDCore/src/plugins/StandardPlugins.cpp diff --git a/DDCore/src/plugins/Compact2Objects.cpp b/DDCore/src/plugins/Compact2Objects.cpp new file mode 100644 index 000000000..9ea6c61c7 --- /dev/null +++ b/DDCore/src/plugins/Compact2Objects.cpp @@ -0,0 +1,742 @@ +// $Id:$ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework includes +#include "DD4hep/DetFactoryHelper.h" +#include "DD4hep/IDDescriptor.h" +#include "DD4hep/FieldTypes.h" +#include "XML/DocumentHandler.h" +#include "XML/Conversions.h" + +// Root/TGeo include files +#include "TGeoManager.h" +#include "TGeoMaterial.h" +#include "Reflex/PluginService.h" + + +#include <climits> +#include <iostream> +#include <iomanip> +#include <set> + +using namespace std; +using namespace DD4hep; +using namespace DD4hep::Geometry; + +namespace DD4hep { + namespace Geometry { + struct Compact; + struct Includes; + struct GdmlFile; + struct Property; + struct AlignmentFile; + } + template <> void Converter<Constant>::operator()(xml_h e) const; + template <> void Converter<Material>::operator()(xml_h e) const; + template <> void Converter<Atom>::operator()(xml_h e) const; + template <> void Converter<VisAttr>::operator()(xml_h e) const; + template <> void Converter<AlignmentEntry>::operator()(xml_h e) const; + template <> void Converter<Region>::operator()(xml_h e) const; + template <> void Converter<Readout>::operator()(xml_h e) const; + template <> void Converter<LimitSet>::operator()(xml_h e) const; + template <> void Converter<Property>::operator()(xml_h e) const; + template <> void Converter<CartesianField>::operator()(xml_h e) const; + template <> void Converter<SensitiveDetector>::operator()(xml_h element) const; + template <> void Converter<DetElement>::operator()(xml_h element) const; + template <> void Converter<GdmlFile>::operator()(xml_h element) const; + template <> void Converter<AlignmentFile>::operator()(xml_h element) const; + template <> void Converter<Header>::operator()(xml_h element) const; + template <> void Converter<Compact>::operator()(xml_h element) const; +} + +namespace { + static UInt_t unique_mat_id = 0xAFFEFEED; +} + +static Ref_t create_GridXYZ(lcdd_t& /* lcdd */, xml_h e) { + GridXYZ obj; + if ( e.hasAttr(_A(gridSizeX)) ) obj.setGridSizeX(e.attr<float>(_A(gridSizeX))); + if ( e.hasAttr(_A(gridSizeY)) ) obj.setGridSizeY(e.attr<float>(_A(gridSizeY))); + if ( e.hasAttr(_A(gridSizeZ)) ) obj.setGridSizeZ(e.attr<float>(_A(gridSizeZ))); + return obj; +} +DECLARE_XMLELEMENT(GridXYZ,create_GridXYZ); + +namespace DD4hep { namespace Geometry { typedef GridXYZ RegularNgonCartesianGridXY; }} +DECLARE_XMLELEMENT(RegularNgonCartesianGridXY,create_GridXYZ); + +static Ref_t create_GlobalGridXY(lcdd_t& /* lcdd */, xml_h e) { + GlobalGridXY obj; + if ( e.hasAttr(_A(gridSizeX)) ) obj.setGridSizeX(e.attr<float>(_A(gridSizeX))); + if ( e.hasAttr(_A(gridSizeY)) ) obj.setGridSizeY(e.attr<float>(_A(gridSizeY))); + return obj; +} +DECLARE_XMLELEMENT(GlobalGridXY,create_GlobalGridXY); + +static Ref_t create_CartesianGridXY(lcdd_t& /* lcdd */, xml_h e) { + CartesianGridXY obj; + if ( e.hasAttr(_A(gridSizeX)) ) obj.setGridSizeX(e.attr<double>(_A(gridSizeX))); + if ( e.hasAttr(_A(gridSizeY)) ) obj.setGridSizeY(e.attr<double>(_A(gridSizeY))); + return obj; +} +DECLARE_XMLELEMENT(CartesianGridXY,create_CartesianGridXY); + +namespace DD4hep { namespace Geometry { typedef CartesianGridXY EcalBarrelCartesianGridXY; }} +DECLARE_XMLELEMENT(EcalBarrelCartesianGridXY,create_CartesianGridXY); + +static Ref_t create_ProjectiveCylinder(lcdd_t& /* lcdd */, xml_h e) { + ProjectiveCylinder obj; + if ( e.hasAttr(_A(phiBins)) ) obj.setPhiBins(e.attr<int>(_A(phiBins))); + if ( e.hasAttr(_A(thetaBins)) ) obj.setThetaBins(e.attr<int>(_A(thetaBins))); + return obj; +} +DECLARE_XMLELEMENT(ProjectiveCylinder,create_ProjectiveCylinder); + +static Ref_t create_NonProjectiveCylinder(lcdd_t& /* lcdd */, xml_h e) { + NonProjectiveCylinder obj; + if ( e.hasAttr(_A(gridSizePhi)) ) obj.setThetaBinSize(e.attr<double>(_A(gridSizePhi))); + if ( e.hasAttr(_A(gridSizeZ)) ) obj.setPhiBinSize(e.attr<double>(_A(gridSizeZ))); + return obj; +} +DECLARE_XMLELEMENT(NonProjectiveCylinder,create_NonProjectiveCylinder); + +static Ref_t create_ProjectiveZPlane(lcdd_t& /* lcdd */, xml_h e) { + ProjectiveZPlane obj; + if ( e.hasAttr(_A(phiBins)) ) obj.setThetaBins(e.attr<int>(_A(phiBins))); + if ( e.hasAttr(_A(thetaBins)) ) obj.setPhiBins(e.attr<int>(_A(thetaBins))); + return obj; +} +DECLARE_XMLELEMENT(ProjectiveZPlane,create_ProjectiveZPlane); + + + +static Ref_t create_ConstantField(lcdd_t& /* lcdd */, xml_h e) { + CartesianField obj; + xml_comp_t field(e), strength(e.child(_X(strength))); + string t = e.attr<string>(_A(field)); + Value<TNamed,ConstantField>* ptr = new Value<TNamed,ConstantField>(); + ptr->type = ::toupper(t[0])=='E' ? CartesianField::ELECTRIC : CartesianField::MAGNETIC; + ptr->direction.SetX(strength.x()); + ptr->direction.SetY(strength.y()); + ptr->direction.SetZ(strength.z()); + obj.assign(ptr,field.nameStr(),field.typeStr()); + return obj; +} +DECLARE_XMLELEMENT(ConstantField,create_ConstantField); + + +static Ref_t create_SolenoidField(lcdd_t& lcdd, xml_h e) { + xml_comp_t c(e); + CartesianField obj; + Value<TNamed,SolenoidField>* ptr = new Value<TNamed,SolenoidField>(); + if ( c.hasAttr(_A(inner_radius)) ) ptr->innerRadius = c.attr<double>(_A(inner_radius)); + else ptr->innerRadius = 0.0; + if ( c.hasAttr(_A(outer_radius)) ) ptr->outerRadius = c.attr<double>(_A(outer_radius)); + else ptr->outerRadius = lcdd.constant<double>("world_side"); + if ( c.hasAttr(_A(inner_field)) ) ptr->innerField = c.attr<double>(_A(inner_field)); + if ( c.hasAttr(_A(outer_field)) ) ptr->outerField = c.attr<double>(_A(outer_field)); + if ( c.hasAttr(_A(zmax)) ) ptr->maxZ = c.attr<double>(_A(zmax)); + else ptr->maxZ = lcdd.constant<double>("world_side"); + if ( c.hasAttr(_A(zmin)) ) ptr->minZ = c.attr<double>(_A(zmin)); + else ptr->minZ = - ptr->maxZ; + obj.assign(ptr,c.nameStr(),c.typeStr()); + return obj; +} +DECLARE_XMLELEMENT(SolenoidMagnet,create_SolenoidField); + +static Ref_t create_DipoleField(lcdd_t& /* lcdd */, xml_h e) { + xml_comp_t c(e); + CartesianField obj; + Value<TNamed,DipoleField>* ptr = new Value<TNamed,DipoleField>(); + double val, lunit = c.attr<double>(_A(lunit)), funit = c.attr<double>(_A(funit)); + + if ( c.hasAttr(_A(zmin)) ) ptr->zmin = _multiply<double>(c.attr<string>(_A(zmin)),lunit); + if ( c.hasAttr(_A(zmax)) ) ptr->zmax = _multiply<double>(c.attr<string>(_A(zmax)),lunit); + if ( c.hasAttr(_A(rmax)) ) ptr->rmax = _multiply<double>(c.attr<string>(_A(rmax)),lunit); + for( xml_coll_t coll(c,_X(dipole_coeff)); coll; ++coll) { + val = funit/pow(lunit,(int)ptr->coefficents.size()); + val = _multiply<double>(coll.value(),val); + ptr->coefficents.push_back(val); + } + obj.assign(ptr,c.nameStr(),c.typeStr()); + return obj; +} +DECLARE_XMLELEMENT(DipoleMagnet,create_DipoleField); + +static long create_Compact(lcdd_t& lcdd, xml_h element) { + Converter<Compact> converter(lcdd); + converter(element); + return 1; +} +DECLARE_XML_DOC_READER(lccdd,create_Compact); + +/** Convert compact constant objects (defines) + * + * + */ +template <> void Converter<Constant>::operator()(xml_h e) const { + xml_ref_t constant(e); + TNamed* obj = new TNamed(constant.attr<string>(_A(name)).c_str(), + constant.attr<string>(_A(value)).c_str()); + Ref_t cons(obj); + _toDictionary(obj->GetName(),obj->GetTitle()); + lcdd.addConstant(cons); +} + +/** Convert compact constant objects (defines) + * + * + */ +template <> void Converter<Header>::operator()(xml_h e) const { + xml_comp_t c(e); + Header h(e.attr<string>(_A(name)),e.attr<string>(_A(title))); + h.setUrl(e.attr<string>(_A(url))); + h.setAuthor(e.attr<string>(_A(author))); + h.setStatus(e.attr<string>(_A(status))); + h.setVersion(e.attr<string>(_A(version))); + h.setComment(e.child(_X(comment)).text()); + lcdd.setHeader(h); +} + +/** Convert compact material/element description objects + * + * Materials: + * <material name="Air"> + * <D type="density" unit="g/cm3" value="0.0012"/> + * <fraction n="0.754" ref="N"/> + * <fraction n="0.234" ref="O"/> + * <fraction n="0.012" ref="Ar"/> + * </material> + * + * Elements: + * <element Z="29" formula="Cu" name="Cu" > + * <atom type="A" unit="g/mol" value="63.5456" /> + * </element> + * + */ +template <> void Converter<Material>::operator()(xml_h e) const { + xml_ref_t m(e); + TGeoManager* mgr = gGeoManager; + xml_tag_t mname = m.name(); + const char* matname = mname.c_str(); + TGeoElementTable* table = mgr->GetElementTable(); + TGeoMaterial* mat = mgr->GetMaterial(matname); + TGeoMixture* mix = dynamic_cast<TGeoMixture*>(mat); + xml_coll_t fractions(m,_X(fraction)); + xml_coll_t composites(m,_X(composite)); + bool has_density = true; + bool mat_created = false; + set<string> elts; + + if ( 0 == mat ) { + xml_h radlen = m.child(_X(RL),false); + xml_h intlen = m.child(_X(NIL),false); + xml_h density = m.child(_X(D),false); + double radlen_val = radlen.ptr() ? radlen.attr<double>(_A(value)) : 0.0; + double intlen_val = intlen.ptr() ? intlen.attr<double>(_A(value)) : 0.0; + double dens_val = density.ptr() ? density.attr<double>(_A(value)) : 0.0; + if ( 0 == mat && !density.ptr() ) { + cout << "Compact2Objects[WARNING]: Material:" << matname << " with NO density." << endl; + has_density = false; + } + if ( mat == 0 ) mat = mix = new TGeoMixture(matname,composites.size(),dens_val); + mat->SetRadLen(radlen_val,intlen_val); + mat_created = true; + //cout << "Compact2Objects[INFO]: Creating material:" << matname << " composites:" << composites.size()+fractions.size() << endl; + } + if ( mat_created ) { + if ( mix ) { + for(Int_t i=0, n=mix->GetNelements(); i<n; ++i) + elts.insert(mix->GetElement(i)->GetName()); + } + for(; composites; ++composites) { + std::string nam = composites.attr<string>(_X(ref)); + TGeoMaterial* comp_mat; + TGeoElement* element; + if ( elts.find(nam) == elts.end() ) { + double fraction = composites.attr<double>(_X(n)); + if ( 0 != (comp_mat=mgr->GetMaterial(nam.c_str())) ) { + mix->AddElement(comp_mat,fraction); + } + else if ( 0 != (element=table->FindElement(nam.c_str())) ) { + mix->AddElement(element,fraction); + } + else { + string msg = "Compact2Objects[ERROR]: Creating material:"+mname+" Element missing: "+nam; + cout << msg << endl; + throw runtime_error(msg); + } + } + } + for(; fractions; ++fractions) { + std::string nam = fractions.attr<string>(_X(ref)); + TGeoMaterial* comp_mat; + TGeoElement* element; + if ( elts.find(nam) == elts.end() ) { + double fraction = fractions.attr<double>(_X(n)); + if ( 0 != (comp_mat=mgr->GetMaterial(nam.c_str())) ) + mix->AddElement(comp_mat,fraction); + else if ( 0 != (element=table->FindElement(nam.c_str())) ) + mix->AddElement(element,fraction); + else { + string msg = "Compact2Objects[ERROR]: Creating material:"+mname+" Element missing: "+nam; + cout << msg << endl; + throw runtime_error(msg); + } + } + } + // Update estimated density if not provided. + if ( !has_density && mix && 0 == mix->GetDensity() ) { + double dens = 0.0; + for(composites.reset(); composites; ++composites) { + std::string nam = composites.attr<string>(_X(ref)); + double fraction = composites.attr<double>(_X(n)); + TGeoMaterial* comp_mat = mgr->GetMaterial(nam.c_str()); + dens += fraction*comp_mat->GetDensity(); + } + for(fractions.reset(); fractions; ++fractions) { + std::string nam = fractions.attr<string>(_X(ref)); + double fraction = fractions.attr<double>(_X(n)); + TGeoMaterial* comp_mat = mgr->GetMaterial(nam.c_str()); + dens += fraction*comp_mat->GetDensity(); + } + cout << "Compact2Objects[WARNING]: Material" << matname << " Set density:" << dens << " g/cm**3 " << endl; + mix->SetDensity(dens); + } + } + TGeoMedium* medium = mgr->GetMedium(matname); + if ( 0 == medium ) { + --unique_mat_id; + medium = new TGeoMedium(matname,unique_mat_id,mat); + medium->SetTitle("material"); + medium->SetUniqueID(unique_mat_id); + } + lcdd.addMaterial(Ref_t(medium)); + + // TGeo has no notion of a material "formula" + // Hence, treat the formula the same way as the material itself + if ( m.hasAttr(_A(formula)) ) { + string form = m.attr<string>(_A(formula)); + if ( form != matname ) { + LCDD::HandleMap::const_iterator im=lcdd.materials().find(form); + if ( im == lcdd.materials().end() ) { + medium = mgr->GetMedium(form.c_str()); + if ( 0 == medium ) { + --unique_mat_id; + medium = new TGeoMedium(form.c_str(),unique_mat_id,mat); + medium->SetTitle("material"); + medium->SetUniqueID(unique_mat_id); + } + lcdd.addMaterial(Ref_t(medium)); + } + } + } +} + +/** Convert compact atom objects + * + * <element Z="29" formula="Cu" name="Cu" > + */ +template <> void Converter<Atom>::operator()(xml_h e) const { + xml_ref_t elem(e); + xml_tag_t eltname = elem.name(); + TGeoManager* mgr = gGeoManager; + TGeoElementTable* tab = mgr->GetElementTable(); + TGeoElement* element = tab->FindElement(eltname.c_str()); + if ( !element ) { + xml_ref_t atom(elem.child(_X(atom))); + tab->AddElement(elem.attr<string>(_A(name)).c_str(), + elem.attr<string>(_A(formula)).c_str(), + elem.attr<int>(_A(Z)), + atom.attr<int>(_A(value)) + ); + element = tab->FindElement(eltname.c_str()); + } +} + +/** Convert compact visualization attribute to LCDD visualization attribute + * + * <vis name="SiVertexBarrelModuleVis" + * alpha="1.0" r="1.0" g="0.75" b="0.76" + * drawingStyle="wireframe" + * showDaughters="false" + * visible="true"/> + */ +template <> void Converter<VisAttr>::operator()(xml_h e) const { + VisAttr attr(e.attr<string>(_A(name))); + float r = e.hasAttr(_A(r)) ? e.attr<float>(_A(r)) : 1.0f; + float g = e.hasAttr(_A(g)) ? e.attr<float>(_A(g)) : 1.0f; + float b = e.hasAttr(_A(b)) ? e.attr<float>(_A(b)) : 1.0f; + attr.setColor(r,g,b); + if ( e.hasAttr(_A(alpha)) ) attr.setAlpha(e.attr<float>(_A(alpha))); + if ( e.hasAttr(_A(visible)) ) attr.setVisible(e.attr<bool>(_A(visible))); + if ( e.hasAttr(_A(lineStyle)) ) { + string ls = e.attr<string>(_A(lineStyle)); + if ( ls == "unbroken" ) attr.setLineStyle(VisAttr::SOLID); + if ( ls == "broken" ) attr.setLineStyle(VisAttr::DASHED); + } + else { + attr.setLineStyle(VisAttr::SOLID); + } + if ( e.hasAttr(_A(drawingStyle)) ) { + string ds = e.attr<string>(_A(drawingStyle)); + if ( ds == "wireframe" ) attr.setDrawingStyle(VisAttr::WIREFRAME); + } + else { + attr.setDrawingStyle(VisAttr::WIREFRAME); + } + if ( e.hasAttr(_A(showDaughters)) ) attr.setShowDaughters(e.attr<bool>(_A(showDaughters))); + lcdd.addVisAttribute(attr); +} + +/** Specialized converter for compact AlignmentEntry objects. + * + * <alignment name="<path/to/object>" shortcut="short_cut_name"> + * <position x="x-value" y="y-value" z="z-value"/> + * <rotation theta="theta-value" phi="phi-value" psi="psi-value"/> + * </alignment> + */ +template <> void Converter<AlignmentEntry>::operator()(xml_h e) const { + xml_comp_t child(e); + string path = e.attr<string>(_A(name)); + bool check = e.hasAttr(_A(check)); + bool overlap = e.hasAttr(_A(overlap)); + AlignmentEntry alignment(path); + Position pos; + Rotation rot; + if ( (child=e.child(_X(position),false)) ) { // Position is not mandatory! + pos.SetXYZ(child.x(),child.y(),child.z()); + } + if ( (child=e.child(_X(rotation),false)) ) { // Rotation is not mandatory + rot.SetComponents(child.z(),child.y(),child.x()); + } + if ( overlap ) { + double ovl = e.attr<double>(_A(overlap)); + alignment.align(pos,rot,check,ovl); + } + else { + alignment.align(pos,rot,check); + } + lcdd.addAlignment(alignment); +} + +/** Specialized converter for compact region objects. + * + */ +template <> void Converter<Region>::operator()(xml_h e) const { + Region region(e.attr<string>(_A(name))); + vector<string>& limits = region.limits(); + string ene = e.attr<string>(_A(eunit)), len = e.attr<string>(_A(lunit)); + + region.setEnergyUnit(ene); + region.setLengthUnit(len); + region.setCut(_multiply<double>(e.attr<string>(_A(cut)),len)); + region.setThreshold(_multiply<double>(e.attr<string>(_A(threshold)),ene)); + region.setStoreSecondaries(e.attr<bool>(_A(store_secondaries))); + for(xml_coll_t user_limits(e,_X(limitsetref)); user_limits; ++user_limits) + limits.push_back(user_limits.attr<string>(_A(name))); + lcdd.addRegion(region); +} + +/** Specialized converter for compact readout objects. + * + * <readout name="HcalBarrelHits"> + * <segmentation type="RegularNgonCartesianGridXY" gridSizeX="3.0*cm" gridSizeY="3.0*cm" /> + * <id>system:6,barrel:3,module:4,layer:8,slice:5,x:32:-16,y:-16</id> + * </readout> + */ +template <> void Converter<Readout>::operator()(xml_h e) const { + xml_h id = e.child(_X(id)); + xml_h seg = e.child(_X(segmentation),false); + string name = e.attr<string>(_A(name)); + Readout ro(name); + + if ( seg ) { // Segmentation is not mandatory! + string type = seg.attr<string>(_A(type)); + Ref_t segment(ROOT::Reflex::PluginService::Create<TNamed*>(type,&lcdd,&seg)); + if ( !segment.isValid() ) throw runtime_error("FAILED to create segmentation:"+type); + ro.setSegmentation(segment); + } + if ( id ) { + // <id>system:6,barrel:3,module:4,layer:8,slice:5,x:32:-16,y:-16</id> + Ref_t idSpec = IDDescriptor(id.text()); + idSpec->SetName(ro.name()); + ro.setIDDescriptor(idSpec); + lcdd.addIDSpecification(idSpec); + } + lcdd.addReadout(ro); +} + +/** Specialized converter for compact LimitSet objects. + * + * <limitset name="...."> + * <limit name="step_length_max" particles="*" value="5.0" unit="mm" /> + * ... </limitset> + */ +template <> void Converter<LimitSet>::operator()(xml_h e) const { + LimitSet ls(e.attr<string>(_A(name))); + for (xml_coll_t c(e,XML::Tag_limit); c; ++c) { + Limit limit; + limit.particles = c.attr<string>(_A(particles)); + limit.name = c.attr<string>(_A(name)); + limit.content = c.attr<string>(_A(value)); + limit.unit = c.attr<string>(_A(unit)); + limit.value = _multiply<double>(limit.content,limit.unit); + ls.addLimit(limit); + } + lcdd.addLimitSet(ls); +} + +/** Specialized converter for generic LCDD properties + * + * <properties> + * <attributes name="key" type="" .... /> + * ... </properties> + */ +template <> void Converter<Property>::operator()(xml_h e) const { + string name = e.attr<string>(_A(name)); + LCDD::Properties& prp = lcdd.properties(); + if ( name.empty() ) { + throw runtime_error("Failed to convert properties. No name given!"); + } + vector<xml_attr_t> a = e.attributes(); + if ( prp.find(name) == prp.end() ) { + prp.insert(make_pair(name,LCDD::PropertyValues())); + } + for( vector<xml_attr_t>::iterator i=a.begin(); i != a.end(); ++i) { + pair<string,string> val(xml_tag_t(e.attr_name(*i)),e.attr<string>(*i)); + prp[name].insert(val); + } +} + +/** Specialized converter for electric and magnetic fields + * + * Uses internally a plugin to allow flexible field descriptions. + * + * <field type="ConstantField" name="Myfield" field="electric"> + * <strength x="0" y="0" z="5"/> + * </field> + */ +template <> void Converter<CartesianField>::operator()(xml_h e) const { + string msg = "updated"; + string name = e.attr<string>(_A(name)); + string type = e.attr<string>(_A(type)); + CartesianField field = lcdd.field(name); + if ( !field.isValid() ) { + // The field is not present: We create it and add it to LCDD + field = Ref_t(ROOT::Reflex::PluginService::Create<TNamed*>(type,&lcdd,&e)); + if ( !field.isValid() ) { + throw runtime_error("Failed to create field object of type "+type); + } + lcdd.addField(field); + msg = "created"; + } + type = field.type(); + // Now update the field structure with the generic part ie. set it's properties + CartesianField::Properties& prp = field.properties(); + for( xml_coll_t c(e,_X(properties)); c; ++c) { + string props_name = c.attr<string>(_A(name)); + vector<xml_attr_t> a = c.attributes(); + if ( prp.find(props_name) == prp.end() ) { + prp.insert(make_pair(props_name,CartesianField::PropertyValues())); + } + for( vector<xml_attr_t>::iterator i=a.begin(); i != a.end(); ++i) { + pair<string,string> val(xml_tag_t(c.attr_name(*i)),c.attr<string>(*i)); + prp[props_name].insert(val); + } + if ( c.hasAttr(_A(global)) && c.attr<bool>(_A(global)) ) { + lcdd.field().properties() = prp; + } + } + cout << "Converted field: Successfully " << msg << " field " << name << " [" << type << "]" << endl; +} + +/** Update sensitive detectors from group tags. + * + * Handle xml sections of the type: + * <sd name="MuonBarrel" + * type="Geant4Calorimeter" + * ecut="100.0*MeV" + * verbose="true" + * hit_aggregation="position" + * limits="limit-set-reference" + * region="region-name-reference"> + * </sd> + * + */ +template <> void Converter<SensitiveDetector>::operator()(xml_h element) const { + string name = element.attr<string>(_A(name)); + try { + DetElement det = lcdd.detector(name); + SensitiveDetector sd = lcdd.sensitiveDetector(name); + + xml_attr_t type = element.attr_nothrow(_A(type)); + if ( type ) { + sd.setType(element.attr<string>(type)); + } + xml_attr_t verbose = element.attr_nothrow(_A(verbose)); + if ( verbose ) { + sd.setVerbose(element.attr<bool>(verbose)); + } + xml_attr_t combine = element.attr_nothrow(_A(combine_hits)); + if ( combine ) { + sd.setCombineHits(element.attr<bool>(combine)); + } + xml_attr_t limits = element.attr_nothrow(_A(limits)); + if ( limits ) { + string l = element.attr<string>(limits); + LimitSet ls = lcdd.limitSet(l); + if ( !ls.isValid() ) { + throw runtime_error("Converter<SensitiveDetector>: Request for non-existing limitset:"+l); + } + sd.setLimitSet(ls); + } + xml_attr_t region = element.attr_nothrow(_A(region)); + if ( region ) { + string r = element.attr<string>(region); + Region reg = lcdd.region(r); + if ( !reg.isValid() ) { + throw runtime_error("Converter<SensitiveDetector>: Request for non-existing region:"+r); + } + sd.setRegion(reg); + } + xml_attr_t hits = element.attr_nothrow(_A(hits_collection)); + if ( hits ) { + sd.setHitsCollection(element.attr<string>(hits)); + } + xml_attr_t ecut = element.attr_nothrow(_A(ecut)); + xml_attr_t eunit = element.attr_nothrow(_A(eunit)); + if ( ecut && eunit ) { + double value = _multiply<double>(_toString(ecut),_toString(eunit)); + sd.setEnergyCutoff(value); + } + else if ( ecut ) { // If no unit is given , we assume the correct Geant4 unit is used! + sd.setEnergyCutoff(element.attr<double>(ecut)); + } + if ( sd.verbose() ) { + cout << "SensitiveDetector-update:" << setw(18) << left << sd.name() + << setw(24) << left << " ["+sd.type()+"] " + << "Hits:" << setw(24) << left << sd.hitsCollection() + << "Cutoff:" << sd.energyCutoff() + << endl; + } + } + catch(const exception& e) { + cout << "FAILED to convert sensitive detector:" << name << ": " << e.what() << endl; + } + catch(...) { + cout << "FAILED to convert sensitive detector:" << name << ": UNKNONW Exception" << endl; + } +} + +void setChildTitles(const pair<string,DetElement>& e) { + DetElement parent = e.second.parent(); + const DetElement::Children& children = e.second.children(); + if ( ::strlen(e.second->GetTitle()) == 0 ) { + e.second->SetTitle(parent.isValid() ? parent.type().c_str() : e.first.c_str()); + } + for_each(children.begin(),children.end(),setChildTitles); +} + +template <> void Converter<DetElement>::operator()(xml_h element) const { + static const char* req_dets = ::getenv("REQUIRED_DETECTORS"); + static const char* req_typs = ::getenv("REQUIRED_DETECTOR_TYPES"); + static const char* ign_dets = ::getenv("IGNORED_DETECTORS"); + static const char* ign_typs = ::getenv("IGNORED_DETECTOR_TYPES"); + string type = element.attr<string>(_A(type)); + string name = element.attr<string>(_A(name)); + string name_match = ":"+name+":"; + string type_match = ":"+type+":"; + if ( req_dets && !strstr(req_dets,name_match.c_str()) ) return; + if ( req_typs && !strstr(req_typs,type_match.c_str()) ) return; + if ( ign_dets && strstr(ign_dets,name_match.c_str()) ) return; + if ( ign_typs && strstr(ign_typs,type_match.c_str()) ) return; + try { + xml_attr_t attr_ro = element.attr_nothrow(_A(readout)); + SensitiveDetector sd; + if ( attr_ro ) { + Readout ro = lcdd.readout(element.attr<string>(attr_ro)); + sd = SensitiveDetector(name,"sensitive"); + sd.setHitsCollection(ro.name()); + sd.setReadout(ro); + lcdd.addSensitiveDetector(sd); + } + Ref_t sens = sd; + DetElement det(Ref_t(ROOT::Reflex::PluginService::Create<TNamed*>(type,&lcdd,&element,&sens))); + if ( det.isValid() ) { + setChildTitles(make_pair(name,det)); + if ( attr_ro ) { + det.setReadout(sd.readout()); + } + } + cout << (det.isValid() ? "Converted" : "FAILED ") + << " subdetector:" << name << " of type " << type; + if ( sd.isValid() ) cout << " [" << sd.type() << "]"; + cout << endl; + lcdd.addDetector(det); + } + catch(const exception& e) { + cout << "FAILED to convert subdetector:" << name << " of type " << type << ": " << e.what() << endl; + } + catch(...) { + cout << "FAILED to convert subdetector:" << name << " of type " << type << ": UNKNONW Exception" << endl; + } +} + +/// Read material entries from a seperate file in one of the include sections of the geometry +template <> void Converter<GdmlFile>::operator()(xml_h element) const { + xml_h materials = XML::DocumentHandler().load(element,element.attr_value(_A(ref))).root(); + xml_coll_t(materials,_X(element) ).for_each(Converter<Atom>(this->lcdd)); + xml_coll_t(materials,_X(material)).for_each(Converter<Material>(this->lcdd)); +} + +/// Read alignment entries from a seperate file in one of the include sections of the geometry +template <> void Converter<AlignmentFile>::operator()(xml_h element) const { + xml_h alignments = XML::DocumentHandler().load(element,element.attr_value(_A(ref))).root(); + xml_coll_t(alignments,_X(alignment)).for_each(Converter<AlignmentEntry>(this->lcdd)); +} + +template <> void Converter<Compact>::operator()(xml_h element) const { + char text[32]; + xml_elt_t compact(element); + xml_coll_t(compact,_X(includes) ).for_each(_X(gdmlFile), Converter<GdmlFile>(lcdd)); + if ( element.hasChild(_X(info)) ) + (Converter<Header>(lcdd))(xml_h(compact.child(_X(info)))); + xml_coll_t(compact,_X(define) ).for_each(_X(constant), Converter<Constant>(lcdd)); + xml_coll_t(compact,_X(materials) ).for_each(_X(element), Converter<Atom>(lcdd)); + xml_coll_t(compact,_X(materials) ).for_each(_X(material), Converter<Material>(lcdd)); + xml_coll_t(compact,_X(properties) ).for_each(_X(attributes),Converter<Property>(lcdd)); + lcdd.init(); + xml_coll_t(compact,_X(limits) ).for_each(_X(limitset), Converter<LimitSet>(lcdd)); + xml_coll_t(compact,_X(display) ).for_each(_X(vis), Converter<VisAttr>(lcdd)); + xml_coll_t(compact,_X(readouts) ).for_each(_X(readout), Converter<Readout>(lcdd)); + xml_coll_t(compact,_X(detectors) ).for_each(_X(detector), Converter<DetElement>(lcdd)); + xml_coll_t(compact,_X(includes) ).for_each(_X(alignment),Converter<AlignmentFile>(lcdd)); + xml_coll_t(compact,_X(alignments) ).for_each(_X(alignment),Converter<AlignmentEntry>(lcdd)); + xml_coll_t(compact,_X(fields) ).for_each(_X(field), Converter<CartesianField>(lcdd)); + xml_coll_t(compact,_X(sensitive_detectors)).for_each(_X(sd),Converter<SensitiveDetector>(lcdd)); + ::sprintf(text,"%u",xml_h(element).checksum(0)); + lcdd.addConstant(Constant("compact_checksum",text)); + lcdd.endDocument(); +} + + +#ifdef _WIN32 +template Converter<Atom>; +template Converter<Compact>; +template Converter<Readout>; +template Converter<VisAttr>; +template Converter<Constant>; +template Converter<LimitSet>; +template Converter<Material>; +template Converter<DetElement>; +template Converter<AlignmentEntry>; +template Converter<SensitiveDetector>; +template Converter<CartesianField>; +#endif diff --git a/DDCore/src/plugins/Geant4XML.cpp b/DDCore/src/plugins/Geant4XML.cpp new file mode 100644 index 000000000..ac3399e0c --- /dev/null +++ b/DDCore/src/plugins/Geant4XML.cpp @@ -0,0 +1,41 @@ +// $Id:$ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#include "XML/Conversions.h" +#include "DD4hep/DetFactoryHelper.h" + +namespace DD4hep { + struct Geant4; + namespace Geometry { + struct GdmlFile; + struct Property; + struct SensitiveDetector; + } +} +using namespace DD4hep; +using namespace DD4hep::Geometry; + +namespace DD4hep { + template <> void Converter<Geant4>::operator()(xml_h e) const; + template <> void Converter<Geometry::GdmlFile>::operator()(xml_h e) const; + template <> void Converter<Geometry::Property>::operator()(xml_h e) const; + template <> void Converter<Geometry::SensitiveDetector>::operator()(xml_h e) const; +} + +template <> void Converter<Geant4>::operator()(xml_h element) const { + xml_elt_t compact(element); + //xml_coll_t(compact,_X(includes) ).for_each(_X(gdmlFile), Converter<Geometry::GdmlFile>(lcdd,param)); + xml_coll_t(compact,_X(properties) ).for_each(_X(attributes),Converter<Geometry::Property>(lcdd,param)); + xml_coll_t(compact,_X(sensitive_detectors)).for_each(_X(sd),Converter<Geometry::SensitiveDetector>(lcdd,param)); +} + +static long create_Geant4(lcdd_t& lcdd, const xml_h& element) { + (Converter<Geant4>(lcdd))(element); + return 1; +} +DECLARE_XML_DOC_READER(geant4,create_Geant4); diff --git a/DDCore/src/plugins/LCDD2Output.cpp b/DDCore/src/plugins/LCDD2Output.cpp new file mode 100644 index 000000000..a2d56a80c --- /dev/null +++ b/DDCore/src/plugins/LCDD2Output.cpp @@ -0,0 +1,198 @@ +// $Id:$ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +#include "XML/Conversions.h" +#include "DD4hep/LCDD.h" +#include "DD4hep/Objects.h" +#include "DD4hep/IDDescriptor.h" + +#include "TMap.h" +#include "TROOT.h" +#include "TColor.h" +#include "TGeoMatrix.h" +#include "TGeoManager.h" +#include <iostream> +#include <iomanip> + +using namespace std; +using namespace DD4hep::Geometry; + +namespace DD4hep { + + template <> void Printer<Constant>::operator()(const Constant& val) const { + os << "++ Constant:" << val.toString() << endl; + } + + template <> void Printer<Material>::operator()(const Material& mat) const { + os << "++ Medium: " << mat.toString() << "| " << endl; + mat->Print(); + } + + template <> void Printer<VisAttr>::operator()(const VisAttr& val) const { + os << "++ VisAttr: " << val.toString() << endl; + } + + template <> void Printer<Readout>::operator()(const Readout& val) const { + os << "++ Readout: "; + val->Print(); + } + + template <> void Printer<Region>::operator()(const Region& val) const { + os << "++ Region: "; + val->Print(); + } + + template <> void Printer<Rotation>::operator()(const Rotation& val) const { + os << "++ Rotation: "; + //val->Print(); + } + + template <> void Printer<Position>::operator()(const Position& val) const { + os << "++ Position: "; + //val->Print(); + } + + template <> void Printer<LimitSet>::operator()(const LimitSet& val) const { + TMap* m = dynamic_cast<TMap*>(val.ptr()); + os << "++ LimitSet: "; + val->TNamed::Print(); + m->TMap::Print(); + } + + template <> void Printer<DetElement>::operator()(const DetElement& val) const { + DetElement::Object* obj = val.data<DetElement::Object>(); + if ( obj ) { + char text[256]; + const DetElement& sd = val; + PlacedVolume plc = sd.placement(); + bool rdo = sd.readout().isValid(); + bool vis = plc.isValid(); + bool env = plc.isValid(); + bool mat = plc.isValid(); + ::sprintf(text,"ID:%-3d Combine Hits:%3s Readout:%s Material:%s Envelope:%s VisAttr:%s", + sd.id(), yes_no(sd.combineHits()), + rdo ? sd.readout()->GetName() : yes_no(rdo), + mat ? plc.material()->GetName() : yes_no(mat), + env ? plc.motherVol()->GetName() : yes_no(env), + yes_no(vis) + ); + os << prefix << "+= DetElement: " << val->GetName() << " " << val.type() << endl; + os << prefix << "| " << text << endl; + + if ( vis ) { + VisAttr attr = plc.volume().visAttributes(); + VisAttr::Object* v = attr.data<VisAttr::Object>(); + TColor* col = gROOT->GetColor(v->color); + char text[256]; + ::sprintf(text," RGB:%-8s [%d] %7.2f Style:%d %d ShowDaughters:%3s Visible:%3s", + col->AsHexString(), v->color, col->GetAlpha(), int(v->drawingStyle), int(v->lineStyle), + v->showDaughters ? "YES" : "NO", v->visible ? "YES" : "NO"); + os << prefix << "| VisAttr: " << setw(32) << left << attr.name() << text << endl; + } + if ( plc.isValid() ) { + Volume vol = plc.volume(); + Solid s = vol.solid(); + Material m = vol.material(); + ::sprintf(text,"Volume:%s Shape:%s Material:%s", + vol->GetName(), s.isValid() ? s.name() : "Unknonw", m.isValid() ? m->GetName() : "Unknown" + ); + os << prefix << "+------------- " << text << endl; + } + const DetElement::Children& ch = sd.children(); + for(DetElement::Children::const_iterator i=ch.begin(); i!=ch.end(); ++i) + Printer<DetElement>(lcdd,os,prefix+"| ")((*i).second); + return; + } + } + + template <typename T> void PrintMap<T>::operator()() const { + Printer<T> p(lcdd,os); + os << "++" << endl << "++ " << text << endl << "++" << endl; + for (LCDD::HandleMap::const_iterator i=cont.begin(); i != cont.end(); ++i) + p((*i).second); + } + + void dumpTopVolume(); + template <> void Printer<const LCDD*>::operator()(const LCDD*const&) const { + //Header(lcdd.header()).fromCompact(doc,compact.child(Tag_info),Strng_t("In memory")); +#if 0 + PrintMap<Constant > (lcdd,os,lcdd.constants(), "List of Constants")(); + PrintMap<Material > (lcdd,os,lcdd.materials(), "List of Materials")(); + PrintMap<VisAttr > (lcdd,os,lcdd.visAttributes(),"List of Visualization attributes")(); + PrintMap<Position > (lcdd,os,lcdd.positions(), "List of Positions")(); + PrintMap<Rotation > (lcdd,os,lcdd.rotations(), "List of Rotations")(); + PrintMap<LimitSet > (lcdd,os,lcdd.readouts(), "List of Readouts")(); + PrintMap<Region > (lcdd,os,lcdd.regions(), "List of Regions")(); + PrintMap<DetElement> (lcdd,os,lcdd.detectors(), "List of DetElements")(); +#endif + //PrintMap<DetElement>(lcdd,os,lcdd.detectors(), "List of DetElements")(); + //PrintMap<VisAttr > (lcdd,os,lcdd.visAttributes(),"List of Visualization attributes")(); + //mpTopVolume(); + } + + void dumpVolume(TGeoVolume* vol, int level); + + void dumpNode(TGeoNode* n, int level) { + TGeoMatrix* mat = n->GetMatrix(); + TGeoVolume* vol = n->GetVolume(); + TGeoMedium* med = vol->GetMedium(); + TGeoShape* shape = vol->GetShape(); + TObjArray* nodes = vol->GetNodes(); + for(int i=0; i<level;++i) cout << " "; + cout << " ++Node:|" << n->GetName() << "| "; + cout << " Volume: " << vol->GetName() + << " material:" << med->GetName() + << " shape:" << shape->GetName() + << endl; + for(int i=0; i<level;++i) cout << " "; + const Double_t* tr = mat->GetTranslation(); + cout << " matrix:|" << mat->GetName() << "|" + << mat->IsTranslation() + << mat->IsRotation() + << mat->IsScale() + << " tr:x=" << tr[0] << " y=" << tr[1] << " z=" << tr[2]; + if ( mat->IsRotation() ) { + Double_t theta,phi,psi; + TGeoRotation rot(*mat); + rot.GetAngles(phi,theta,psi); + cout << " rot: theta:" << theta << " phi:" << phi << " psi:" << psi; + } + cout << endl; + PlacedVolume plv(n); + for(int i=0; i<level;++i) cout << " "; + cout << " volume:" << plv.toString(); + cout << endl; + TIter next(nodes); + TGeoNode *geoNode; + while ((geoNode = (TGeoNode *) next())) { + dumpNode(geoNode,level+1); + } + } + + void dumpVolume(TGeoVolume* vol, int level) { + TObjArray* nodes = vol->GetNodes(); + TGeoMedium* med = vol->GetMedium(); + TGeoShape* shape = vol->GetShape(); + + for(int i=0; i<level;++i) cout << " "; + cout << "++Volume: " << vol->GetName() + << " material:" << med->GetName() + << " shape:" << shape->GetName() + << endl; + TIter next(nodes); + TGeoNode *geoNode; + while ((geoNode = (TGeoNode *) next())) { + dumpNode(geoNode,level+1); + } + } + + void dumpTopVolume() { + dumpVolume(gGeoManager->GetTopVolume(),0); + } +} diff --git a/DDCore/src/plugins/LCDDConverter.cpp b/DDCore/src/plugins/LCDDConverter.cpp new file mode 100644 index 000000000..812f0859f --- /dev/null +++ b/DDCore/src/plugins/LCDDConverter.cpp @@ -0,0 +1,959 @@ +// $Id:$ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework includes +#include "DD4hep/Volumes.h" +#include "DD4hep/FieldTypes.h" +#include "XML/DocumentHandler.h" +#include "LCDDConverter.h" + +// ROOT includes +#include "TROOT.h" +#include "TColor.h" +#include "TGeoShape.h" +#include "TGeoEltu.h" +#include "TGeoCone.h" +#include "TGeoParaboloid.h" +#include "TGeoPara.h" +#include "TGeoPcon.h" +#include "TGeoPgon.h" +#include "TGeoSphere.h" +#include "TGeoTorus.h" +#include "TGeoTube.h" +#include "TGeoTrd1.h" +#include "TGeoTrd2.h" +#include "TGeoArb8.h" +#include "TGeoMatrix.h" +#include "TGeoBoolNode.h" +#include "TGeoCompositeShape.h" +#include "TGeoShapeAssembly.h" +#include "TGeoNode.h" +#include "TClass.h" +#include "TMath.h" +#include "Reflex/PluginService.h" +#include <iostream> +#include <iomanip> + +using namespace DD4hep::Geometry; +using namespace DD4hep; +using namespace std; + +namespace { + typedef Position XYZRotation; + XYZRotation getXYZangles(const Double_t* r) { + static Double_t rad = DEGREE_2_RAD; + Double_t cosb = sqrt(r[0]*r[0] + r[1]*r[1]); + if (cosb > 0.00001) { + return XYZRotation(atan2(r[5], r[8])*rad, atan2(-r[2], cosb)*rad, atan2(r[1], r[0])*rad); + } + return XYZRotation(atan2(-r[7], r[4])*rad,atan2(-r[2], cosb)*rad,0); + } +} + + +void LCDDConverter::GeometryInfo::check(const string& name, const TNamed* n,map<string,const TNamed*>& m) const { + map<string,const TNamed*>::const_iterator i=m.find(name); + if ( i != m.end() ) { + const char* isa = n ? n->IsA()->GetName() : (*i).second ? (*i).second->IsA()->GetName() : "Unknown"; + cout << isa << "(position): duplicate entry with name:" << name + << " " << (void*)n << " " << (void*)(*i).second << endl; + } + m.insert(make_pair(name,n)); +} + +/// Initializing Constructor +LCDDConverter::LCDDConverter( LCDD& lcdd ) : m_lcdd(lcdd) { + m_checkOverlaps = true; +} + +/// Dump element in GDML format to output stream +xml_h LCDDConverter::handleElement(const string& name, const TGeoElement* element) const { + GeometryInfo& geo = data(); + xml_h e = geo.xmlElements[element]; + if ( !e ) { + xml_elt_t atom(geo.doc,_X(atom)); + geo.doc_materials.append(e=xml_elt_t(geo.doc,_X(element))); + e.append(atom); + e.setAttr(_A(name),element->GetName()); + e.setAttr(_A(formula),element->GetName()); + e.setAttr(_A(Z),element->Z()); + atom.setAttr(_A(type),"A"); + atom.setAttr(_A(unit),"g/mol"); + atom.setAttr(_A(value),element->A() /* *(g/mole) */); + geo.xmlElements[element] = e; + } + return e; +} + +/// Dump material in GDML format to output stream +xml_h LCDDConverter::handleMaterial(const string& name, const TGeoMedium* medium) const { + GeometryInfo& geo = data(); + xml_h mat = geo.xmlMaterials[medium]; + if ( !mat ) { + xml_h obj; + TGeoMaterial* m = medium->GetMaterial(); + double d = m->GetDensity(); //*(gram/cm3); + mat = xml_elt_t(geo.doc,_X(material)); + mat.setAttr(_A(name),medium->GetName()); + mat.append(obj=xml_elt_t(geo.doc,_X(D))); + obj.setAttr(_A(value),m->GetDensity() /* *(g/cm3) */); + obj.setAttr(_A(unit),"g/cm3"); + obj.setAttr(_A(type),"density"); + + geo.checkMaterial(name,medium); + + if ( m->IsMixture() ) { + TGeoMixture* mix=(TGeoMixture*)m; + const double *wmix = mix->GetWmixt(); + double sum = 0e0; + for (int i=0, n=mix->GetNelements(); i < n; i++) { + TGeoElement *elt = mix->GetElement(i); + handleElement(elt->GetName(),elt); + sum += wmix[i]; + } + for (int i=0, n=mix->GetNelements(); i < n; i++) { + TGeoElement *elt = mix->GetElement(i); + string formula = elt->GetTitle()+string("_elm"); + mat.append(obj=xml_elt_t(geo.doc,_X(fraction))); + obj.setAttr(_A(n),wmix[i]/sum); + obj.setAttr(_A(ref),elt->GetName()); + } + } + else { + TGeoElement *elt = m->GetElement(0); + xml_elt_t atom(geo.doc,_X(atom)); + handleElement(elt->GetName(),elt); + mat.append(atom); + mat.setAttr(_A(Z),m->GetZ()); + atom.setAttr(_A(type),"A"); + atom.setAttr(_A(unit),"g/mol"); + atom.setAttr(_A(value),m->GetA() /* *(g/mole) */); + } + geo.doc_materials.append(mat); + geo.xmlMaterials[medium] = mat; + } + return mat; +} + +/// Dump solid in GDML format to output stream +xml_h LCDDConverter::handleSolid(const string& name, const TGeoShape* shape) const { + GeometryInfo& geo = data(); + xml_h solid(geo.xmlSolids[shape]); + if ( !solid && shape ) { + xml_h zplane(0); + geo.checkShape(name,shape); + if ( shape->IsA() == TGeoBBox::Class() ) { + const TGeoBBox* s = (const TGeoBBox*)shape; + geo.doc_solids.append(solid = xml_elt_t(geo.doc,_X(box))); + solid.setAttr(_A(name),Unicode(name)); + solid.setAttr(_A(x),s->GetDX()*CM_2_MM); + solid.setAttr(_A(y),s->GetDY()*CM_2_MM); + solid.setAttr(_A(z),s->GetDZ()*CM_2_MM); + solid.setAttr(_A(lunit),"mm"); + } + else if ( shape->IsA() == TGeoTube::Class() ) { + const TGeoTube* s = (const TGeoTube*)shape; + geo.doc_solids.append(solid = xml_elt_t(geo.doc,_X(tube))); + solid.setAttr(_A(name),Unicode(name)); + solid.setAttr(_A(rmin),s->GetRmin()*CM_2_MM); + solid.setAttr(_A(rmax),s->GetRmax()*CM_2_MM); + solid.setAttr(_A(z),s->GetDz()*CM_2_MM); + solid.setAttr(_A(startphi),0e0); + solid.setAttr(_A(deltaphi),2*M_PI); + solid.setAttr(_A(aunit),"rad"); + solid.setAttr(_A(lunit),"mm"); + } + else if ( shape->IsA() == TGeoEltu::Class() ) { + const TGeoEltu* s = (const TGeoEltu*)shape; + geo.doc_solids.append(solid = xml_elt_t(geo.doc,_X(eltube))); + solid.setAttr(_A(name),Unicode(name)); + solid.setAttr(_A(dx),s->GetA()*CM_2_MM); + solid.setAttr(_A(dy),s->GetB()*CM_2_MM); + solid.setAttr(_A(dz),s->GetDz()*CM_2_MM); + solid.setAttr(_A(lunit),"mm"); + } + else if ( shape->IsA() == TGeoTubeSeg::Class() ) { + const TGeoTubeSeg* s = (const TGeoTubeSeg*)shape; + geo.doc_solids.append(solid = xml_elt_t(geo.doc,_X(tube))); + solid.setAttr(_A(name),Unicode(name)); + solid.setAttr(_A(rmin),s->GetRmin()*CM_2_MM); + solid.setAttr(_A(rmax),s->GetRmax()*CM_2_MM); + solid.setAttr(_A(z),s->GetDz()*CM_2_MM); + solid.setAttr(_A(startphi),s->GetPhi1()*DEGREE_2_RAD); + solid.setAttr(_A(deltaphi),s->GetPhi2()*DEGREE_2_RAD); + solid.setAttr(_A(aunit),"rad"); + solid.setAttr(_A(lunit),"mm"); + } + else if ( shape->IsA() == TGeoTrd1::Class() ) { + const TGeoTrd1* s = (const TGeoTrd1*)shape; + geo.doc_solids.append(solid = xml_elt_t(geo.doc,_X(trd))); + solid.setAttr(_A(name),Unicode(name)); + solid.setAttr(_A(x1),s->GetDx1()*CM_2_MM); + solid.setAttr(_A(x2),s->GetDx2()*CM_2_MM); + solid.setAttr(_A(y1),s->GetDy()*CM_2_MM); + solid.setAttr(_A(y2),s->GetDy()*CM_2_MM); + solid.setAttr(_A(z), s->GetDz()*CM_2_MM); + solid.setAttr(_A(lunit),"mm"); + } + else if ( shape->IsA() == TGeoTrd2::Class() ) { + const TGeoTrd2* s = (const TGeoTrd2*)shape; + geo.doc_solids.append(solid = xml_elt_t(geo.doc,_X(trd))); + solid.setAttr(_A(name),Unicode(name)); + solid.setAttr(_A(x1),s->GetDx1()*CM_2_MM); + solid.setAttr(_A(x2),s->GetDx2()*CM_2_MM); + solid.setAttr(_A(y1),s->GetDy1()*CM_2_MM); + solid.setAttr(_A(y2),s->GetDy2()*CM_2_MM); + solid.setAttr(_A(z), s->GetDz()*CM_2_MM); + solid.setAttr(_A(lunit),"mm"); + } + else if ( shape->IsA() == TGeoTrap::Class() ) { + const TGeoTrap* s = (const TGeoTrap*)shape; + geo.doc_solids.append(solid = xml_elt_t(geo.doc,_X(trap))); + solid.setAttr(_A(name),Unicode(name)); + solid.setAttr(_A(x1),s->GetBl1()*CM_2_MM); + solid.setAttr(_A(x2),s->GetTl1()*CM_2_MM); + solid.setAttr(_A(x3),s->GetBl2()*CM_2_MM); + solid.setAttr(_A(x4),s->GetTl2()*CM_2_MM); + solid.setAttr(_A(y1),s->GetH1()*CM_2_MM); + solid.setAttr(_A(y2),s->GetH2()*CM_2_MM); + solid.setAttr(_A(z),s->GetDz()*CM_2_MM); + solid.setAttr(_A(alpha1),s->GetAlpha1()*DEGREE_2_RAD); + solid.setAttr(_A(alpha2),s->GetAlpha2()*DEGREE_2_RAD); + solid.setAttr(_A(theta),s->GetTheta()*DEGREE_2_RAD); + solid.setAttr(_A(phi),s->GetPhi()*DEGREE_2_RAD); + solid.setAttr(_A(aunit),"rad"); + solid.setAttr(_A(lunit),"mm"); + } + else if ( shape->IsA() == TGeoPara::Class() ) { + const TGeoPara* s = (const TGeoPara*)shape; + geo.doc_solids.append(solid = xml_elt_t(geo.doc,_X(para))); + solid.setAttr(_A(name),Unicode(name)); + solid.setAttr(_A(x),s->GetX()*CM_2_MM); + solid.setAttr(_A(y),s->GetY()*CM_2_MM); + solid.setAttr(_A(z),s->GetZ()*CM_2_MM); + solid.setAttr(_A(alpha),s->GetAlpha()*DEGREE_2_RAD); + solid.setAttr(_A(theta),s->GetTheta()*DEGREE_2_RAD); + solid.setAttr(_A(phi),s->GetPhi()*DEGREE_2_RAD); + solid.setAttr(_A(aunit),"rad"); + solid.setAttr(_A(lunit),"mm"); + } + else if ( shape->IsA() == TGeoPgon::Class() ) { + const TGeoPgon* s = (const TGeoPgon*)shape; + geo.doc_solids.append(solid = xml_elt_t(geo.doc,_X(polyhedra))); + solid.setAttr(_A(name),Unicode(name)); + solid.setAttr(_A(startphi),s->GetPhi1()*DEGREE_2_RAD); + solid.setAttr(_A(deltaphi),s->GetDphi()*DEGREE_2_RAD); + solid.setAttr(_A(aunit),"rad"); + solid.setAttr(_A(lunit),"mm"); + for( size_t i=0; i<s->GetNz(); ++i ) { + zplane = xml_elt_t(geo.doc,_X(zplane)); + zplane.setAttr(_A(rmin),s->GetRmin(i)*CM_2_MM); + zplane.setAttr(_A(rmax),s->GetRmax(i)*CM_2_MM); + zplane.setAttr(_A(z),s->GetZ(i)*CM_2_MM); + solid.append(zplane); + } + } + else if ( shape->IsA() == TGeoPcon::Class() ) { + const TGeoPcon* s = (const TGeoPcon*)shape; + geo.doc_solids.append(solid = xml_elt_t(geo.doc,_X(polycone))); + solid.setAttr(_A(name),Unicode(name)); + solid.setAttr(_A(startphi),s->GetPhi1()*DEGREE_2_RAD); + solid.setAttr(_A(deltaphi),s->GetDphi()*DEGREE_2_RAD); + solid.setAttr(_A(aunit),"rad"); + solid.setAttr(_A(lunit),"mm"); + for( size_t i=0; i<s->GetNz(); ++i ) { + zplane = xml_elt_t(geo.doc,_X(zplane)); + zplane.setAttr(_A(rmin),s->GetRmin(i)*CM_2_MM); + zplane.setAttr(_A(rmax),s->GetRmax(i)*CM_2_MM); + zplane.setAttr(_A(z),s->GetZ(i)*CM_2_MM); + solid.append(zplane); + } + } + else if ( shape->IsA() == TGeoCone::Class() ) { + const TGeoCone* s = (const TGeoCone*)shape; + geo.doc_solids.append(solid = xml_elt_t(geo.doc,_X(cone))); + solid.setAttr(_A(name),Unicode(name)); + solid.setAttr(_A(z),s->GetDz()*CM_2_MM); + solid.setAttr(_A(rmin1),s->GetRmin1()*CM_2_MM); + solid.setAttr(_A(rmax1),s->GetRmax1()*CM_2_MM); + solid.setAttr(_A(rmin2),s->GetRmin2()*CM_2_MM); + solid.setAttr(_A(rmax2),s->GetRmax2()*CM_2_MM); + solid.setAttr(_A(z),s->GetDz()*CM_2_MM); + solid.setAttr(_A(startphi),0e0); + solid.setAttr(_A(deltaphi),2*M_PI); + solid.setAttr(_A(aunit),"rad"); + solid.setAttr(_A(lunit),"mm"); + } + else if ( shape->IsA() == TGeoConeSeg::Class() ) { + const TGeoConeSeg* s = (const TGeoConeSeg*)shape; + geo.doc_solids.append(solid = xml_elt_t(geo.doc,_X(cone))); + solid.setAttr(_A(name),Unicode(name)); + solid.setAttr(_A(startphi),s->GetPhi1()*DEGREE_2_RAD); + solid.setAttr(_A(deltaphi),(s->GetPhi2()-s->GetPhi1())*DEGREE_2_RAD); + solid.setAttr(_A(aunit),"rad"); + solid.setAttr(_A(lunit),"mm"); + zplane = xml_elt_t(geo.doc,_X(zplane)); + zplane.setAttr(_A(rmin),s->GetRmin1()*CM_2_MM); + zplane.setAttr(_A(rmax),s->GetRmax1()*CM_2_MM); + zplane.setAttr(_A(z),s->GetDz()*CM_2_MM); + solid.append(zplane); + zplane = xml_elt_t(geo.doc,_X(zplane)); + zplane.setAttr(_A(rmin),s->GetRmin2()*CM_2_MM); + zplane.setAttr(_A(rmax),s->GetRmax2()*CM_2_MM); + zplane.setAttr(_A(z),s->GetDz()*CM_2_MM); + solid.append(zplane); + } + else if ( shape->IsA() == TGeoParaboloid::Class() ) { + const TGeoParaboloid* s = (const TGeoParaboloid*)shape; + geo.doc_solids.append(solid = xml_elt_t(geo.doc,_X(paraboloid))); + solid.setAttr(_A(name),Unicode(name)); + solid.setAttr(_A(rlo),s->GetRlo()*CM_2_MM); + solid.setAttr(_A(rhi),s->GetRhi()*CM_2_MM); + solid.setAttr(_A(dz),s->GetDz()*CM_2_MM); + solid.setAttr(_A(lunit),"mm"); + } + else if ( shape->IsA() == TGeoSphere::Class() ) { + const TGeoSphere* s = (const TGeoSphere*)shape; + geo.doc_solids.append(solid = xml_elt_t(geo.doc,_X(sphere))); + solid.setAttr(_A(name),Unicode(name)); + solid.setAttr(_A(rmin),s->GetRmin()*CM_2_MM); + solid.setAttr(_A(rmax),s->GetRmax()*CM_2_MM); + solid.setAttr(_A(startphi),s->GetPhi1()*DEGREE_2_RAD); + solid.setAttr(_A(deltaphi),(s->GetPhi2()-s->GetPhi1())*DEGREE_2_RAD); + solid.setAttr(_A(starttheta),s->GetTheta1()*DEGREE_2_RAD); + solid.setAttr(_A(deltatheta),(s->GetTheta2()-s->GetTheta1())*DEGREE_2_RAD); + solid.setAttr(_A(aunit),"rad"); + solid.setAttr(_A(lunit),"mm"); + } + else if ( shape->IsA() == TGeoTorus::Class() ) { + const TGeoTorus* s = (const TGeoTorus*)shape; + geo.doc_solids.append(solid = xml_elt_t(geo.doc,_X(torus))); + solid.setAttr(_A(name),Unicode(name)); + solid.setAttr(_A(rtor),s->GetR()); + solid.setAttr(_A(rmin),s->GetRmin()); + solid.setAttr(_A(rmax),s->GetRmax()); + solid.setAttr(_A(startphi),s->GetPhi1()*DEGREE_2_RAD); + solid.setAttr(_A(deltaphi),s->GetDphi()*DEGREE_2_RAD); + solid.setAttr(_A(aunit),"rad"); + solid.setAttr(_A(lunit),"mm"); + } + else if ( shape->IsA() == TGeoShapeAssembly::Class() ) { + TGeoShapeAssembly* s = (TGeoShapeAssembly*)shape; + geo.doc_solids.append(solid = xml_elt_t(geo.doc,_X(assembly))); + solid.setAttr(_A(name),Unicode(name)); + } + else if ( shape->IsA() == TGeoCompositeShape::Class() ) { + const TGeoCompositeShape* s = (const TGeoCompositeShape*)shape; + const TGeoBoolNode* boolean = s->GetBoolNode(); + TGeoBoolNode::EGeoBoolType oper = boolean->GetBooleanOperator(); + TGeoMatrix* m = boolean->GetRightMatrix(); + xml_h left = handleSolid(name+"_left", boolean->GetLeftShape()); + xml_h right = handleSolid(name+"_right",boolean->GetRightShape()); + xml_h first(0), second(0); + if ( !left ) { + throw runtime_error("G4Converter: No left Geant4 Solid present for composite shape:"+name); + } + if ( !right ) { + throw runtime_error("G4Converter: No right Geant4 Solid present for composite shape:"+name); + } + + if ( oper == TGeoBoolNode::kGeoSubtraction ) + solid = xml_elt_t(geo.doc,_X(subtraction)); + else if ( oper == TGeoBoolNode::kGeoUnion ) + solid = xml_elt_t(geo.doc,_X(union)); + else if ( oper == TGeoBoolNode::kGeoIntersection ) + solid = xml_elt_t(geo.doc,_X(intersection)); + + xml_h obj; + solid.append(first=xml_elt_t(geo.doc,_X(first))); + solid.setAttr(_A(name),Unicode(name)); + first.setAttr(_A(ref),name+"_left"); + XYZRotation rot = getXYZangles(boolean->GetLeftMatrix()->Inverse().GetRotationMatrix()); + const double *tr = boolean->GetLeftMatrix()->GetTranslation(); + + if ((tr[0] != 0.0) || (tr[1] != 0.0) || (tr[2] != 0.0)) { + first.append(obj=xml_elt_t(geo.doc,_X(firstposition))); + obj.setAttr(_A(x),tr[0]*CM_2_MM); + obj.setAttr(_A(y),tr[1]*CM_2_MM); + obj.setAttr(_A(z),tr[2]*CM_2_MM); + } + if ((rot.X() != 0.0) || (rot.Y() != 0.0) || (rot.Z() != 0.0)) { + first.append(obj=xml_elt_t(geo.doc,_X(firstrotation))); + obj.setAttr(_A(x),rot.X()); + obj.setAttr(_A(y),rot.Y()); + obj.setAttr(_A(z),rot.Z()); + } + + rot = getXYZangles(boolean->GetRightMatrix()->Inverse().GetRotationMatrix()); + tr = boolean->GetRightMatrix()->GetTranslation(); + solid.append(second=xml_elt_t(geo.doc,_X(second))); + second.setAttr(_A(ref),name+"_right"); + if ((tr[0] != 0.0) || (tr[1] != 0.0) || (tr[2] != 0.0)) { + first.append(obj=xml_elt_t(geo.doc,_X(position))); + obj.setAttr(_A(x),tr[0]*CM_2_MM); + obj.setAttr(_A(y),tr[1]*CM_2_MM); + obj.setAttr(_A(z),tr[2]*CM_2_MM); + } + if ((rot.X() != 0.0) || (rot.Y() != 0.0) || (rot.Z() != 0.0)) { + first.append(obj=xml_elt_t(geo.doc,_X(rotation))); + obj.setAttr(_A(x),rot.X()); + obj.setAttr(_A(y),rot.Y()); + obj.setAttr(_A(z),rot.Z()); + } + } + if ( !solid ) { + string err = "Failed to handle unknown solid shape:" + + name + " of type " + string(shape->IsA()->GetName()); + throw runtime_error(err); + } + data().xmlSolids[shape] = solid; + } + return solid; +} + +/// Convert the Position into the corresponding Xml object(s). +xml_h LCDDConverter::handlePosition(const std::string& name, const TGeoMatrix* trafo) const { + GeometryInfo& geo = data(); + xml_h pos = geo.xmlPositions[trafo]; + if ( !pos ) { + static xml_h identity; + const double* tr = trafo->GetTranslation(); + if ( tr[0] != 0 || tr[1] != 0 || tr[2] != 0 ) { + geo.checkPosition(name,trafo); + geo.doc_define.append(pos=xml_elt_t(geo.doc,_X(position))); + pos.setAttr(_A(name),name); + pos.setAttr(_A(x),tr[0]); + pos.setAttr(_A(y),tr[1]); + pos.setAttr(_A(z),tr[2]); + } + else if ( identity ) { + pos = identity; + } + else { + geo.doc_define.append(identity=xml_elt_t(geo.doc,_X(position))); + identity.setAttr(_A(name),"identity_pos"); + identity.setAttr(_A(x),0); + identity.setAttr(_A(y),0); + identity.setAttr(_A(z),0); + pos = identity; + geo.checkPosition("identity_pos",0); + } + geo.xmlPositions[trafo] = pos; + } + return pos; +} + +/// Convert the Rotation into the corresponding Xml object(s). +xml_h LCDDConverter::handleRotation(const std::string& name, const TGeoMatrix* trafo) const { + GeometryInfo& geo = data(); + xml_h rot = geo.xmlRotations[trafo]; + if ( !rot ) { + static xml_h identity; + XYZRotation r = getXYZangles(trafo->Inverse().GetRotationMatrix()); + if ( r.X() != 0 || r.Y() != 0 || r.Z() != 0 ) { + geo.checkRotation(name,trafo); + geo.doc_define.append(rot=xml_elt_t(geo.doc,_X(rotation))); + rot.setAttr(_A(name),name); + rot.setAttr(_A(x),r.X()); + rot.setAttr(_A(y),r.Y()); + rot.setAttr(_A(z),r.Z()); + } + else if ( identity ) { + rot = identity; + } + else { + geo.doc_define.append(identity=xml_elt_t(geo.doc,_X(rotation))); + identity.setAttr(_A(name),"identity_rot"); + identity.setAttr(_A(x),0); + identity.setAttr(_A(y),0); + identity.setAttr(_A(z),0); + rot = identity; + geo.checkRotation("identity_rot",0); + } + geo.xmlRotations[trafo] = rot; + } + return rot; +} + +/// Dump logical volume in GDML format to output stream +xml_h LCDDConverter::handleVolume(const string& name, const TGeoVolume* volume) const { + GeometryInfo& geo = data(); + xml_h vol = geo.xmlVolumes[volume]; + if ( !vol ) { + const TGeoVolume* v = volume; + Volume _v = Ref_t(v); + string n = v->GetName(); + TGeoMedium* m = v->GetMedium(); + TGeoShape* s = v->GetShape(); + xml_ref_t sol = handleSolid(s->GetName(),s); + + if ( !sol ) + throw runtime_error("G4Converter: No Geant4 Solid present for volume:"+n); + else if ( !m && v->IsA() != TGeoVolumeAssembly::Class() ) + throw runtime_error("G4Converter: No Geant4 material present for volume:"+n); + + geo.checkVolume(name,volume); + geo.doc_structure.append(vol=xml_elt_t(geo.doc,_X(volume))); + vol.setAttr(_A(name),n); + vol.setRef(_X(solidref),sol.name()); + if ( m ) { + xml_ref_t med = handleMaterial(m->GetName(),m); + vol.setRef(_X(materialref),med.name()); + } + if ( dynamic_cast<const Volume::Object*>(volume) ) { + Region reg = _v.region(); + LimitSet lim = _v.limitSet(); + VisAttr vis = _v.visAttributes(); + SensitiveDetector det = _v.sensitiveDetector(); + if ( vis.isValid() ) { + xml_ref_t data = handleVis(vis.name(),vis.ptr()); + vol.setRef(_X(visref),data.name()); + } + if ( lim.isValid() ) { + xml_ref_t data = handleLimitSet(lim.name(),lim.ptr()); + vol.setRef(_X(limitsetref),data.name()); + } + if ( reg.isValid() ) { + xml_ref_t data = handleRegion(reg.name(),reg.ptr()); + vol.setRef(_X(regionref),data.name()); + } + if ( det.isValid() ) { + xml_ref_t data = handleSensitive(det.name(),det.ptr()); + vol.setRef(_X(sdref),data.name()); + } + } + geo.xmlVolumes[v] = vol; + } + return vol; +} + +/// Dump logical volume in GDML format to output stream +void LCDDConverter::collectVolume(const string& name, const TGeoVolume* volume) const { + Volume v = Ref_t(volume); + if ( dynamic_cast<const Volume::Object*>(volume) ) { + GeometryInfo& geo = data(); + Region reg = v.region(); + LimitSet lim = v.limitSet(); + SensitiveDetector det = v.sensitiveDetector(); + if ( lim.isValid() ) geo.limits.insert(lim.ptr()); + if ( reg.isValid() ) geo.regions.insert(reg.ptr()); + if ( det.isValid() ) geo.sensitives.insert(det.ptr()); + } + else { + cout << "LCDDConverter::collectVolume: Skip volume:" << volume->GetName() << endl; + } +} + +void LCDDConverter::checkVolumes(const string& name, const TGeoVolume* volume) const { + NameSet::const_iterator i=m_checkNames.find(name); + if ( i != m_checkNames.end() ) { + Volume v = Ref_t(volume); + cout << "checkVolumes: Volume " << name << " "; + if ( dynamic_cast<const Volume::Object*>(volume) ) { + SensitiveDetector s = v.sensitiveDetector(); + VisAttr vis = v.visAttributes(); + if ( s.isValid() ) { + cout << "of " << s.name() << " "; + } + else if ( vis.isValid() ) { + cout << "with VisAttrs " << vis.name() << " "; + } + } + cout << "has duplicate entries." << endl; + return; + } + m_checkNames.insert(name); +} + +/// Dump volume placement in GDML format to output stream +xml_h LCDDConverter::handlePlacement(const string& name, const TGeoNode* node) const { + GeometryInfo& geo = data(); + xml_h place = geo.xmlPlacements[node]; + if ( !place ) { + TGeoMatrix* t = node->GetMatrix(); + TGeoVolume* v = node->GetVolume(); + xml_ref_t vol = xml_h(geo.xmlVolumes[v]); + xml_h mot = geo.xmlVolumes[node->GetMotherVolume()]; + + place = xml_elt_t(geo.doc,_X(physvol)); + if ( mot ) { // Beware of top level volume! + mot.append(place); + } + place.setRef(_X(volumeref),vol.name()); + if ( t ) { + char text[32]; + ::sprintf(text,"_%p_pos",node); + xml_ref_t pos = handlePosition(name+text,t); + ::sprintf(text,"_%p_rot",node); + xml_ref_t rot = handleRotation(name+text,t); + place.setRef(_X(positionref),pos.name()); + place.setRef(_X(rotationref),rot.name()); + } + if ( dynamic_cast<const PlacedVolume::Object*>(node) ) { + PlacedVolume p = Ref_t(node); + const PlacedVolume::VolIDs& ids = p.volIDs(); + for(PlacedVolume::VolIDs::const_iterator i=ids.begin(); i!=ids.end(); ++i) { + xml_h pvid = xml_elt_t(geo.doc,"physvolid"); + pvid.setAttr(_A(field_name),(*i).first); + pvid.setAttr(_A(value),(*i).second); + place.append(pvid); + } + } + geo.xmlPlacements[node] = place; + } + else { + cout << "Attempt to DOUBLE-place physical volume:" << name << " No:" << node->GetNumber() << endl; + } + return place; +} + +/// Convert the geometry type region into the corresponding Geant4 object(s). +xml_h LCDDConverter::handleRegion(const std::string& name, const TNamed* region) const { + GeometryInfo& geo = data(); + xml_h reg = geo.xmlRegions[region]; + if ( !reg ) { + Region r = Ref_t(region); + geo.doc_regions.append(reg=xml_elt_t(geo.doc,_X(region))); + reg.setAttr(_A(name), r.name()); + reg.setAttr(_A(cut), r.cut()); + reg.setAttr(_A(eunit), r.energyUnit()); + reg.setAttr(_A(lunit), r.lengthUnit()); + reg.setAttr(_A(store_secondaries),r.storeSecondaries()); + geo.xmlRegions[region] = reg; + } + return reg; +} + +/// Convert the geometry type LimitSet into the corresponding Geant4 object(s) +xml_h LCDDConverter::handleLimitSet(const std::string& name, const TNamed* limitset) const { + GeometryInfo& geo = data(); + xml_h xml = geo.xmlLimits[limitset]; + if ( !xml ) { + LimitSet lim = Ref_t(limitset); + geo.doc_limits.append(xml=xml_elt_t(geo.doc,_X(limitset))); + xml.setAttr(_A(name),lim.name()); + const LimitSet::Object& obj = lim.limits(); + for(LimitSet::Object::const_iterator i=obj.begin(); i!=obj.end(); ++i) { + xml_h x = xml_elt_t(geo.doc,_X(limit)); + const Limit& l = *i; + xml.append(x); + x.setAttr(_A(name),l.name); + x.setAttr(_A(unit),l.unit); + x.setAttr(_A(value),l.value); + x.setAttr(_A(particles),l.particles); + } + geo.xmlLimits[limitset] = xml; + } + return xml; +} + +/// Convert the geometry type SensitiveDetector into the corresponding Geant4 object(s). +xml_h LCDDConverter::handleSensitive(const string& name, const TNamed* sens_det) const { + GeometryInfo& geo = data(); + xml_h sensdet = geo.xmlSensDets[sens_det]; + if ( !sensdet ) { + SensitiveDetector sd = Ref_t(sens_det); + string type = sd.type(), name = sd.name(); + geo.doc_detectors.append(sensdet = xml_elt_t(geo.doc,Unicode(type))); + sensdet.setAttr(_A(name),sd.name()); + sensdet.setAttr(_A(ecut),sd.energyCutoff()); + sensdet.setAttr(_A(eunit),"MeV"); + sensdet.setAttr(_A(verbose),sd.verbose()); + sensdet.setAttr(_A(hits_collection),sd.hitsCollection()); + if ( sd.combineHits() ) sensdet.setAttr(_A(combine_hits),sd.combineHits()); + Readout ro = sd.readout(); + if ( ro.isValid() ) { + xml_ref_t ref = handleIdSpec(ro.idSpec().name(),ro.idSpec().ptr()); + sensdet.setRef(_A(idspecref),ref.name()); + } + geo.xmlSensDets[sens_det] = sensdet; + } + return sensdet; +} + +/// Convert the geometry id dictionary entry to the corresponding Xml object(s). +xml_h LCDDConverter::handleIdSpec(const std::string& name, const TNamed* id_spec) const { + GeometryInfo& geo = data(); + xml_h id = geo.xmlIdSpecs[id_spec]; + if ( !id ) { + IDDescriptor desc = Ref_t(id_spec); + geo.doc_idDict.append(id=xml_elt_t(geo.doc,_X(idspec))); + id.setAttr(_A(name),name); + const IDDescriptor::FieldMap& m = desc.fields(); + for(IDDescriptor::FieldMap::const_iterator i=m.begin(); i!=m.end(); ++i) { + xml_h idfield = xml_elt_t(geo.doc,"idfield"); + const IDDescriptor::Field& f = (*i).second; + idfield.setAttr(_A(signed),f.second<0 ? true : false); + idfield.setAttr(_A(label),(*i).first); + idfield.setAttr(_A(length),f.second<0 ? -f.second : f.second); + idfield.setAttr(_A(start),f.first); + id.append(idfield); + } + geo.xmlIdSpecs[id_spec] = id; + } + return id; +} + +/// Convert the geometry visualisation attributes to the corresponding Geant4 object(s). +xml_h LCDDConverter::handleVis(const string& name, const TNamed* v) const { + GeometryInfo& geo = data(); + xml_h vis = geo.xmlVis[v]; + if ( !vis ) { + float r=0, g=0, b=0; + VisAttr attr = Ref_t(v); + int style = attr.lineStyle(); + int draw = attr.drawingStyle(); + + geo.doc_display.append(vis=xml_elt_t(geo.doc,_X(vis))); + vis.setAttr(_A(name),attr.name()); + vis.setAttr(_A(visible),attr.visible()); + vis.setAttr(_A(show_daughters),attr.showDaughters()); + if ( style == VisAttr::SOLID ) + vis.setAttr(_A(line_style),"unbroken"); + else if ( style == VisAttr::DASHED ) + vis.setAttr(_A(line_style),"broken"); + if ( draw == VisAttr::SOLID ) + vis.setAttr(_A(line_style),"solid"); + else if ( draw == VisAttr::WIREFRAME ) + vis.setAttr(_A(line_style),"wireframe"); + + xml_h col = xml_elt_t(geo.doc,_X(color)); + col.setAttr(_A(alpha),attr.alpha()); + col.setAttr(_A(R),r); + col.setAttr(_A(G),g); + col.setAttr(_A(B),b); + vis.append(col); + geo.xmlVis[v] = vis; + } + return vis; +} + +/// Convert the electric or magnetic fields into the corresponding Xml object(s). +xml_h LCDDConverter::handleField(const std::string& name, const TNamed* f) const { + GeometryInfo& geo = data(); + xml_h field = geo.xmlFields[f]; + if ( !field ) { + Ref_t fld(f); + string type = f->GetTitle(); + field=xml_elt_t(geo.doc,_X(field)); + field.setAttr(_A(name),f->GetName()); + field.setAttr(_A(type),type); + fld = ROOT::Reflex::PluginService::Create<TNamed*>(type+"_Convert2LCDD",&m_lcdd,&field,&fld); + cout << (fld.isValid() ? "Converted" : "FAILED to convert ") + << " electromagnetic field:" << f->GetName() << " of type " << f->GetTitle() << endl; + if ( !fld.isValid() ) { + throw runtime_error("Failed to locate plugin to convert electromagnetic field:"+ + string(f->GetName())+" of type "+string(f->GetTitle())); + } + geo.doc_fields.append(field); + } + return field; +} + +/// Handle the geant 4 specific properties +void LCDDConverter::handleProperties(LCDD::Properties& prp) const { + map<string,string> processors; + static int s_idd = 9999999; + string id; + for(LCDD::Properties::const_iterator i=prp.begin(); i!=prp.end(); ++i) { + const string& nam = (*i).first; + const LCDD::PropertyValues& vals = (*i).second; + if ( nam.substr(0,6) == "geant4" ) { + LCDD::PropertyValues::const_iterator id_it = vals.find("id"); + if ( id_it != vals.end() ) { + id= (*id_it).second; + } + else { + char txt[32]; + ::sprintf(txt,"%d",++s_idd); + id = txt; + } + processors.insert(make_pair(id,nam)); + } + } + for(map<string,string>::const_iterator i=processors.begin(); i!=processors.end(); ++i) { + const LCDDConverter* ptr = this; + string nam = (*i).second; + const LCDD::PropertyValues& vals = prp[nam]; + string type = vals.find("type")->second; + string tag = type + "_Geant4_action"; + long result = ROOT::Reflex::PluginService::Create<long>(tag,&m_lcdd,ptr,&vals); + if ( 0 == result ) { + throw runtime_error("Failed to locate plugin to interprete files of type" + " \""+tag+"\" - no factory:"+type); + } + result = *(long*)result; + if ( result != 1 ) { + throw runtime_error("Failed to invoke the plugin "+tag+" of type "+type); + } + cout << "+++++ Executed Successfully Geant4 setup module *" << type << "* ." << endl; + } +} + +/// Add header information in LCDD format +void LCDDConverter::handleHeader() const { + GeometryInfo& geo = data(); + Header hdr = m_lcdd.header(); + xml_h obj; + geo.doc_header.append(obj=xml_elt_t(geo.doc,"detector")); + obj.setAttr(_A(name),hdr.name()); + geo.doc_header.append(obj=xml_elt_t(geo.doc,"generator")); + obj.setAttr(_A(name),"LCDDConverter"); + obj.setAttr(_A(version),hdr.version()); + obj.setAttr(_A(file),hdr.url()); + obj.setAttr(_A(checksum),m_lcdd.constantAsString("compact_checksum")); + geo.doc_header.append(obj=xml_elt_t(geo.doc,"author")); + obj.setAttr(_A(name),hdr.author()); + geo.doc_header.append(obj=xml_elt_t(geo.doc,"comment")); + obj.setText(hdr.comment()); +} + +template <typename O, typename C, typename F> void handle(const O* o, const C& c, F pmf) { + for(typename C::const_iterator i=c.begin(); i != c.end(); ++i) { + string n = (*i)->GetName(); + (o->*pmf)(n,*i); + } +} + +template <typename O, typename C, typename F> void handleMap(const O* o, const C& c, F pmf) { + for(typename C::const_iterator i=c.begin(); i != c.end(); ++i) + (o->*pmf)((*i).first, (*i).second); +} + +template <typename O, typename C, typename F> void handleRMap(const O* o, const C& c, F pmf) { + for(typename C::const_reverse_iterator i=c.rbegin(); i != c.rend(); ++i) + handle(o, (*i).second, pmf); +} + +/// Create geometry conversion +void LCDDConverter::create(DetElement top) { + LCDD& lcdd = m_lcdd; + GeometryInfo& geo = *(m_dataPtr=new GeometryInfo); + m_data->clear(); + collect(top,geo); + m_checkOverlaps = false; + + #define ns_location "http://www.lcsim.org.schemas/lcdd/1.0" + + const char empty_lcdd[] = + "<?xml version=\"1.0\" encoding=\"UTF-8\">\n" + "<!-- \n" + " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n" + " ++++ Linear collider detector description LCDD in C++ ++++\n" + " ++++ DD4hep Detector description generator. ++++\n" + " ++++ ++++\n" + " ++++ M.Frank CERN/LHCb ++++\n" + " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n" + "-->\n" + "<lcdd " + "xmlns:lcdd=\"" ns_location "\"\n" + "xmlns:xs=\"http://www/w3.org/2001/XMLSchema-instance\"\n" + ">\n" + "</lcdd>\0\0"; + + XML::DocumentHandler docH; + xml_elt_t elt(0); + geo.doc = docH.parse(empty_lcdd,sizeof(empty_lcdd)); + //doc->setXmlStandalone(true); + //doc->setStrictErrorChecking(true); + geo.doc_root = geo.doc.root(); + + //Box worldSolid(doc,_X(world_box)); + geo.doc_root.append(geo.doc_header = xml_elt_t(geo.doc,_X(header))); + geo.doc_root.append(geo.doc_idDict = xml_elt_t(geo.doc,_X(iddict))); + geo.doc_root.append(geo.doc_detectors = xml_elt_t(geo.doc,_X(sensitive_detectors))); + geo.doc_root.append(geo.doc_limits = xml_elt_t(geo.doc,_X(limits))); + geo.doc_root.append(geo.doc_regions = xml_elt_t(geo.doc,_X(regions))); + geo.doc_root.append(geo.doc_display = xml_elt_t(geo.doc,_X(display))); + geo.doc_root.append(geo.doc_gdml = xml_elt_t(geo.doc,_X(gdml))); + geo.doc_root.append(geo.doc_fields = xml_elt_t(geo.doc,_X(fields))); + //elt = xml_elt_t(); + + geo.doc_gdml.append(geo.doc_define = xml_elt_t(geo.doc,_X(define))); + geo.doc_gdml.append(geo.doc_materials = xml_elt_t(geo.doc,_X(materials))); + geo.doc_gdml.append(geo.doc_solids = xml_elt_t(geo.doc,_X(solids))); + geo.doc_gdml.append(geo.doc_structure = xml_elt_t(geo.doc,_X(structure))); + geo.doc_gdml.append(geo.doc_setup = xml_elt_t(geo.doc,_X(setup))); + elt = xml_elt_t(geo.doc,_X(world)); + elt.setAttr(_A(ref),lcdd.worldVolume().name()); + geo.doc_setup.append(elt); + + + // Ensure that all required materials are present in the Geant4 material table + const LCDD::HandleMap& mat = lcdd.materials(); + for(LCDD::HandleMap::const_iterator i=mat.begin(); i!=mat.end(); ++i) + geo.materials.insert(dynamic_cast<TGeoMedium*>((*i).second.ptr())); + + const LCDD::HandleMap& fld = lcdd.fields(); + for(LCDD::HandleMap::const_iterator i=fld.begin(); i!=fld.end(); ++i) + geo.fields.insert((*i).second.ptr()); + + handleHeader(); + // Start creating the objects for materials, solids and log volumes. + handle(this, geo.materials, &LCDDConverter::handleMaterial); + cout << "++ Handled " << geo.materials.size() << " materials." << endl; + + handle(this, geo.volumes, &LCDDConverter::collectVolume); + cout << "++ Handled " << geo.volumes.size() << " volumes." << endl; + + handle(this, geo.solids, &LCDDConverter::handleSolid); + cout << "++ Handled " << geo.solids.size() << " solids." << endl; + + handle(this, geo.vis, &LCDDConverter::handleVis); + cout << "++ Handled " << geo.solids.size() << " visualization attributes." << endl; + + handle(this, geo.sensitives, &LCDDConverter::handleSensitive); + cout << "++ Handled " << geo.sensitives.size() << " sensitive detectors." << endl; + + handle(this, geo.limits, &LCDDConverter::handleLimitSet); + cout << "++ Handled " << geo.limits.size() << " limit sets." << endl; + + handle(this, geo.regions, &LCDDConverter::handleRegion); + cout << "++ Handled " << geo.regions.size() << " regions." << endl; + + handle(this, geo.volumes, &LCDDConverter::handleVolume); + cout << "++ Handled " << geo.volumes.size() << " volumes." << endl; + + handle(this, geo.fields, &LCDDConverter::handleField); + cout << "++ Handled " << geo.fields.size() << " fields." << endl; + + // Now place all this stuff appropriately + handleRMap(this, *m_data, &LCDDConverter::handlePlacement); + + m_checkNames.clear(); + handle(this, geo.volumes, &LCDDConverter::checkVolumes); + +#if 0 + //==================== Fields + handleProperties(m_lcdd.properties()); +#endif +} + +LCDDConverter::GeometryInfo::GeometryInfo() + : doc(0), doc_root(0), doc_header(0), doc_idDict(0), doc_detectors(0), doc_limits(0), doc_regions(0), + doc_display(0), doc_gdml(0), doc_fields(0), doc_define(0), doc_materials(0), + doc_solids(0), doc_structure(0),doc_setup(0) +{ +} + +static long create_translator(LCDD& lcdd, int argc, char** argv) { + LCDDConverter wr(lcdd); + FILE* file = argc>0 ? ::fopen(argv[0],"w") : stdout; + wr.create(lcdd.world()); + LCDDConverter::GeometryInfo& geo = wr.data(); + if ( !file ) { + cout << "Failed to open output file:" << argv[0] << endl; + return 0; + } + geo.doc->Print(file); + if ( argc>0 ) ::fclose(file); + return 1; +} + +DECLARE_APPLY(DD4hepGeometry2LCDD,create_translator); diff --git a/DDCore/src/plugins/LCDDConverter.h b/DDCore/src/plugins/LCDDConverter.h new file mode 100644 index 000000000..7c71e1d6f --- /dev/null +++ b/DDCore/src/plugins/LCDDConverter.h @@ -0,0 +1,171 @@ +// $Id:$ +//==================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_GEOMETRY_LCDDCONVERTER_H +#define DD4HEP_GEOMETRY_LCDDCONVERTER_H + +// Framework include files +#include "DD4hep/LCDD.h" +#include "DD4hep/GeoHandler.h" +#include "DD4hep/DetFactoryHelper.h" + +// C/C++ include files +#include <set> +#include <map> +#include <vector> + +// Forward declarations +class TGeoVolume; +class TGeoElement; +class TGeoShape; +class TGeoMedium; +class TGeoNode; +class TGeoMatrix; + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * XML namespace declaration + */ + namespace Geometry { + + /** @class LCDDConverter LCDDConverter.h XML/LCDDConverter.h + * + * Geometry converter from DD4hep to Geant 4. + * + * @author M.Frank + * @version 1.0 + */ + struct LCDDConverter : public GeoHandler { + typedef XML::XmlElement XmlElement; + typedef std::map<const TGeoElement*,XmlElement*> ElementMap; + typedef std::map<const TGeoMedium*, XmlElement*> MaterialMap; + typedef std::map<const TNamed*, XmlElement*> LimitMap; + typedef std::map<const TGeoNode*, XmlElement*> PlacementMap; + typedef std::map<const TNamed*, XmlElement*> RegionMap; + typedef std::map<const TNamed*, XmlElement*> SensDetMap; + typedef std::map<const TGeoVolume*, XmlElement*> VolumeMap; + typedef std::map<const TGeoShape*, XmlElement*> SolidMap; + typedef std::map<const TNamed*, XmlElement*> VisMap; + typedef std::map<const TNamed*, XmlElement*> FieldMap; + typedef std::map<const TNamed*, XmlElement*> IdSpecMap; + typedef std::map<const TGeoMatrix*, XmlElement*> TrafoMap; + struct GeometryInfo : public GeoHandler::GeometryInfo { + ElementMap xmlElements; + MaterialMap xmlMaterials; + SolidMap xmlSolids; + VolumeMap xmlVolumes; + PlacementMap xmlPlacements; + RegionMap xmlRegions; + VisMap xmlVis; + LimitMap xmlLimits; + IdSpecMap xmlIdSpecs; + SensDetMap xmlSensDets; + TrafoMap xmlPositions; + TrafoMap xmlRotations; + FieldMap xmlFields; + ObjectSet sensitives; + ObjectSet regions; + ObjectSet limits; + // These we need for redundancy and checking the data integrity + typedef std::map<std::string,const TNamed*> CheckIter; + struct _checks { + std::map<std::string,const TNamed*> positions, rotations, volumes, solids, materials; + }; + mutable _checks checks; + void check(const std::string& name,const TNamed* n,std::map<std::string,const TNamed*>& array) const; + void checkPosition(const std::string& name,const TNamed* n) const { check(name,n,checks.positions); } + void checkRotation(const std::string& name,const TNamed* n) const { check(name,n,checks.rotations); } + void checkVolume (const std::string& name,const TNamed* n) const { check(name,n,checks.volumes); } + void checkShape (const std::string& name,const TNamed* n) const { check(name,n,checks.solids); } + void checkMaterial(const std::string& name,const TNamed* n) const { check(name,n,checks.materials); } + + xml_doc_t doc; + xml_elt_t doc_root, doc_header, doc_idDict, doc_detectors, doc_limits, doc_regions, + doc_display, doc_gdml, doc_fields, doc_define, doc_materials, doc_solids, doc_structure, doc_setup; + GeometryInfo(); + }; + + LCDD& m_lcdd; + bool m_checkOverlaps; + + typedef std::set<std::string> NameSet; + mutable NameSet m_checkNames; + + GeometryInfo* m_dataPtr; + GeometryInfo& data() const { return *m_dataPtr; } + + + void checkVolumes(const std::string& name, const TGeoVolume* volume) const; + + + /// Initializing Constructor + LCDDConverter( LCDD& lcdd ); + + /// Standard destructor + virtual ~LCDDConverter() {} + + /// Create geometry conversion + void create(DetElement top); + + /// Add header information in LCDD format + virtual void handleHeader() const; + + /// Convert the geometry type material into the corresponding Xml object(s). + virtual xml_h handleMaterial(const std::string& name, const TGeoMedium* medium) const; + + /// Convert the geometry type element into the corresponding Xml object(s). + virtual xml_h handleElement(const std::string& name, const TGeoElement* element) const; + + /// Convert the geometry type solid into the corresponding Xml object(s). + virtual xml_h handleSolid(const std::string& name, const TGeoShape* volume) const; + + /// Convert the geometry type logical volume into the corresponding Xml object(s). + virtual xml_h handleVolume(const std::string& name, const TGeoVolume* volume) const; + virtual void collectVolume(const std::string& name, const TGeoVolume* volume) const; + + /// Convert the geometry type volume placement into the corresponding Xml object(s). + virtual xml_h handlePlacement(const std::string& name, const TGeoNode* node) const; + + /// Convert the geometry type field into the corresponding Xml object(s). + ///virtual xml_h handleField(const std::string& name, Ref_t field) const; + + /// Convert the geometry type region into the corresponding Xml object(s). + virtual xml_h handleRegion(const std::string& name, const TNamed* region) const; + + /// Convert the geometry visualisation attributes to the corresponding Xml object(s). + virtual xml_h handleVis(const std::string& name, const TNamed* vis) const; + + /// Convert the geometry id dictionary entry to the corresponding Xml object(s). + virtual xml_h handleIdSpec(const std::string& name, const TNamed* vis) const; + + /// Convert the geometry type LimitSet into the corresponding Xml object(s). + virtual xml_h handleLimitSet(const std::string& name, const TNamed* limitset) const; + + /// Convert the geometry type SensitiveDetector into the corresponding Xml object(s). + virtual xml_h handleSensitive(const std::string& name, const TNamed* sens_det) const; + + /// Convert the Position into the corresponding Xml object(s). + virtual xml_h handlePosition(const std::string& name, const TGeoMatrix* trafo) const; + + /// Convert the Rotation into the corresponding Xml object(s). + virtual xml_h handleRotation(const std::string& name, const TGeoMatrix* trafo) const; + + /// Convert the electric or magnetic fields into the corresponding Xml object(s). + virtual xml_h handleField(const std::string& name, const TNamed* field) const; + + /// Handle the geant 4 specific properties + void handleProperties(LCDD::Properties& prp) const; + }; + } // End namespace XML +} // End namespace DD4hep + +#endif // DD4HEP_GEOMETRY_LCDDCONVERTER_H diff --git a/DDCore/src/plugins/LCDDFields.cpp b/DDCore/src/plugins/LCDDFields.cpp new file mode 100644 index 000000000..7b5e71ef6 --- /dev/null +++ b/DDCore/src/plugins/LCDDFields.cpp @@ -0,0 +1,75 @@ +// $Id:$ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework includes +#include "DD4hep/FieldTypes.h" +#include "DD4hep/DetFactoryHelper.h" + +using namespace DD4hep::Geometry; + +static Ref_t convert_constant_field(LCDD& lcdd, xml_h field, Ref_t object) { + xml_doc_t doc = xml_elt_t(field).document(); + ConstantField* s = object.data<ConstantField>(); + field.setAttr(_A(lunit),"mm"); + //field.setAttr(_A(funit),"tesla"); + if ( s->type == CartesianField::ELECTRIC ) + field.setAttr(_A(field),"electric"); + else if ( s->type == CartesianField::MAGNETIC ) + field.setAttr(_A(field),"magnetic"); + + xml_elt_t strength = xml_elt_t(doc,_X(strength)); + strength.setAttr(_A(x),s->direction.X()); + strength.setAttr(_A(y),s->direction.Y()); + strength.setAttr(_A(z),s->direction.Z()); + field.append(strength); + return object; +} +DECLARE_XML_PROCESSOR(ConstantField_Convert2LCDD,convert_constant_field); + +static Ref_t convert_solenoid(LCDD& lcdd, xml_h field, Ref_t object) { + char text[128]; + SolenoidField* s = object.data<SolenoidField>(); + field.setAttr(_A(lunit),"mm"); + field.setAttr(_A(funit),"tesla"); + ::sprintf(text,"%g/mm",s->outerRadius); + field.setAttr(_A(outer_radius),_toDouble(text)); + ::sprintf(text,"%g/mm",s->innerRadius); + field.setAttr(_A(inner_radius),_toDouble(text)); + ::sprintf(text,"%g/tesla",s->innerField); + field.setAttr(_A(inner_field),_toDouble(text)); + ::sprintf(text,"%g/tesla",s->outerField); + field.setAttr(_A(outer_field),_toDouble(text)); + field.setAttr(_A(zmin),s->minZ); + field.setAttr(_A(zmax),s->maxZ); + return object; +} +DECLARE_XML_PROCESSOR(SolenoidMagnet_Convert2LCDD,convert_solenoid); + +static Ref_t convert_dipole(LCDD& lcdd, xml_h field, Ref_t object) { + char text[128]; + xml_doc_t doc = xml_elt_t(field).document(); + DipoleField* s = object.data<DipoleField>(); + field.setAttr(_A(lunit),"mm"); + field.setAttr(_A(funit),"tesla"); + ::sprintf(text,"%g/mm",s->rmax); + field.setAttr(_A(rmax),_toDouble(text)); + ::sprintf(text,"%g/mm",s->zmax); + field.setAttr(_A(zmax),_toDouble(text)); + ::sprintf(text,"%g/mm",s->zmin); + field.setAttr(_A(zmin),_toDouble(text)); + DipoleField::Coefficents::const_iterator i=s->coefficents.begin(); + for(; i != s->coefficents.end(); ++i) { + xml_elt_t coeff = xml_elt_t(doc,_X(dipole_coeff)); + coeff.setValue(_toString(*i)); + field.append(coeff); + } + return object; +} +DECLARE_XML_PROCESSOR(DipoleField_Convert2LCDD,convert_dipole); + diff --git a/DDCore/src/plugins/StandardPlugins.cpp b/DDCore/src/plugins/StandardPlugins.cpp new file mode 100644 index 000000000..aa8b0af37 --- /dev/null +++ b/DDCore/src/plugins/StandardPlugins.cpp @@ -0,0 +1,50 @@ +// $Id:$ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Standard plugins necessary for nearly everything. +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/Factories.h" +#include "DD4hep/LCDD.h" +// ROOT includes +#include "TGeoManager.h" +#include "TGeoVolume.h" + +using namespace std; +using namespace DD4hep::Geometry; + +static long display(LCDD& /* lcdd */,int argc,char** argv) { + TGeoManager* mgr = gGeoManager; + const char* opt = "ogl"; + if ( argc > 0 ) { + opt = argv[0]; + } + if ( mgr ) { + mgr->SetVisLevel(4); + mgr->SetVisOption(1); + TGeoVolume* vol = mgr->GetTopVolume(); + if ( vol ) { + vol->Draw(opt); + return 1; + } + } + return 0; +} +DECLARE_APPLY(DD4hepGeometryDisplay,display); + +static long load_compact(LCDD& lcdd,int argc,char** argv) { + for(size_t j=0; j<argc; ++j) { + string input = argv[j]; + cout << "Processing compact input file : " << input << endl; + lcdd.fromCompact(input); + } + return 1; +} +DECLARE_APPLY(DD4hepCompactLoader,load_compact); + -- GitLab