Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-03-14 08:15:02

0001 //==========================================================================
0002 //  AIDA Detector description implementation 
0003 //--------------------------------------------------------------------------
0004 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
0005 // All rights reserved.
0006 //
0007 // For the licensing terms see $DD4hepINSTALL/LICENSE.
0008 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
0009 //
0010 // Author     : M.Frank
0011 //
0012 //==========================================================================
0013 #ifndef DD4HEP_NONE
0014 
0015 // Framework include files
0016 #include <XML/Utilities.h>
0017 #include <DD4hep/Plugins.h>
0018 #include <DD4hep/Detector.h>
0019 #include <DD4hep/Printout.h>
0020 #include <DD4hep/DetFactoryHelper.h>
0021 #include <Math/Polar2D.h>
0022 
0023 // Forward declarations
0024 class TObject;
0025 
0026 using namespace dd4hep::xml::tools;
0027 using dd4hep::printout;
0028 
0029 namespace {
0030   static constexpr const char* TAG_LIMITSETREF     = "limitsetref";
0031   static constexpr const char* TAG_REGIONREF       = "regionref";
0032   static constexpr const char* TAG_VISREF          = "visref";
0033 
0034   static constexpr const char* TAG_COMBINE_HITS    = "combine_hits";
0035   static constexpr const char* TAG_VERBOSE         = "verbose";
0036   static constexpr const char* TAG_TYPE            = "type";
0037   static constexpr const char* TAG_ECUT            = "ecut";
0038   static constexpr const char* TAG_HITS_COLLECTION = "hits_collection";
0039 }
0040 
0041 /// Create layered transformation from xml information
0042 dd4hep::Transform3D dd4hep::xml::createTransformation(xml::Element e)   {
0043   int flag = 0;
0044   Transform3D position, rotation, result;
0045   for( xml_coll_t c(e,_U(star)); c; ++c )    {
0046     std::string tag = c.tag();
0047     xml_dim_t x_elt = c;
0048     if ( tag == "positionRPhiZ" )   {
0049       if      ( flag == 1 ) result = position  * result;
0050       else if ( flag == 2 ) result = (position * rotation) * result;
0051       PositionRhoZPhi pos(x_elt.r(0), x_elt.z(0), x_elt.phi(0));
0052       position = Transform3D(pos);
0053       rotation = Transform3D();
0054       flag = 1;
0055     }
0056     else if ( tag == "position" )   {
0057       if      ( flag == 1 ) result = position  * result;
0058       else if ( flag == 2 ) result = (position * rotation) * result;
0059       Position pos(x_elt.x(0), x_elt.y(0), x_elt.z(0));
0060       position = Transform3D(pos);
0061       rotation = Transform3D();
0062       flag = 1;
0063     }
0064     else if ( tag == "transformation" )   {
0065       if      ( flag == 1 ) result = position  * result;
0066       else if ( flag == 2 ) result = (position * rotation) * result;
0067       Transform3D trafo = createTransformation(c);
0068       result   = trafo * result;
0069       position = Transform3D();
0070       rotation = Transform3D();
0071       flag = 0;
0072     }
0073     else if ( tag == "rotation" )   {
0074       rotation = Transform3D(RotationZYX(x_elt.z(0), x_elt.y(0), x_elt.x(0)));
0075       flag = 2;
0076     }
0077   }
0078   if      ( flag == 1 ) result = position  * result;
0079   else if ( flag == 2 ) result = (position * rotation) * result;
0080   return result;
0081 }
0082 
0083 /// Create a solid shape using the plugin mechanism from the attributes of the XML element
0084 dd4hep::Solid dd4hep::xml::createShape(Detector& description,
0085                                        const std::string& shape_type,
0086                                        xml::Element element)   {
0087   std::string fac  = shape_type + "__shape_constructor";
0088   xml::Handle_t solid_elt = element;
0089   Solid solid = Solid(PluginService::Create<TObject*>(fac, &description, &solid_elt));
0090   if ( !solid.isValid() )  {
0091     PluginDebug dbg;
0092     PluginService::Create<TObject*>(fac, &description, &solid_elt);
0093     dd4hep::except("xml::createShape","Failed to create solid of type %s [%s]", 
0094                    shape_type.c_str(),dbg.missingFactory(shape_type).c_str());
0095   }
0096   return solid;
0097 }
0098 
0099 /// Create a volume using the plugin mechanism from the attributes of the XML element
0100 dd4hep::Volume dd4hep::xml::createStdVolume(Detector& description, xml::Element element)    {
0101   Volume      vol;
0102   xml_dim_t   elt(element);
0103   std::string typ, tag = elt.tag();
0104   PrintLevel  lvl   = ALWAYS;
0105   //PrintLevel  lvl   = DEBUG;
0106 
0107   printout(lvl, "xml::createStdVolume", "++ Processing tag: %-12s", tag.c_str());
0108   if ( elt.hasAttr(_U(material)) )   {
0109     xml_dim_t x_s = elt.child(_U(shape));
0110     Solid     sol = createShape(description, x_s.typeStr(), x_s);
0111     Material  mat = description.material(elt.attr<std::string>(_U(material)));
0112     vol = Volume("volume", sol, mat);
0113     if ( elt.hasAttr(_U(name)) ) vol->SetName(elt.nameStr().c_str());
0114     vol.setAttributes(description,elt.regionStr(),elt.limitsStr(),elt.visStr());
0115     printout(lvl, "xml::createStdVolume", "++ --> name: %s vis: %s region: %s limits: %s",
0116              vol.name(),
0117              elt.visStr("").c_str(),
0118              elt.regionStr("").c_str(),
0119              elt.limitsStr("").c_str());
0120     elt = std::move(x_s);
0121   }
0122   else if ( elt.hasAttr(_U(type)) )  {
0123     typ = elt.typeStr();
0124     if ( typ == "CAD_Assembly" || typ == "CAD_MultiVolume" || typ == "GenVolume" )
0125       vol = xml::createVolume(description, typ, elt);
0126     else if ( typ.substr(1) == "ssembly" )
0127       vol = Assembly("assembly");
0128     if ( elt.hasAttr(_U(name)) ) vol->SetName(elt.nameStr().c_str());
0129     vol.setAttributes(description,elt.regionStr(),elt.limitsStr(),elt.visStr());
0130     printout(lvl, "xml::createStdVolume", "++ --> name: %s vis: %s region: %s limits: %s",
0131              vol.name(),
0132              elt.visStr("").c_str(),
0133              elt.regionStr("").c_str(),
0134              elt.limitsStr("").c_str());
0135   }
0136   if ( vol.isValid() )  {
0137     for( xml_coll_t xv(elt, _U(volume)); xv; ++xv )    {
0138       xml_dim_t xvol = xv;
0139       xml_dim_t xshap = xv.child(_U(shape), false);
0140       /** Trigger on:
0141        *
0142        *  <volume name="..." type="Assembly">
0143        *  or
0144        *  <volume name="..." material="Air">
0145        *
0146        *    <shape  ....  />
0147        *    or 
0148        *    <volume  ....  />
0149        *
0150        *    optional:
0151        *    <position x="0" ... />
0152        *    <rotation x="0" ... />
0153        *  </volume>
0154        */
0155       if ( xvol && ((xvol.hasAttr(_U(material)) && xshap) || xvol.hasAttr(_U(type))) )  {
0156         RotationZYX rot;
0157         Position    pos;
0158         xml_comp_t  x_rot = xvol.child( _U(rotation), false );
0159         xml_comp_t  x_pos = xvol.child( _U(position), false );
0160         Volume      child = xml::createStdVolume( description, xvol );
0161         if ( x_rot ) rot = RotationZYX( x_rot.z(0),x_rot.y(0),x_rot.x(0) );
0162         if ( x_pos ) pos = Position( x_pos.x(0),x_pos.y(0),x_pos.z(0) );
0163         Transform3D trafo(Rotation3D(rot), pos);
0164         vol.placeVolume( child, trafo );
0165       }
0166     }
0167     for( xml_coll_t xs(elt, _U(shape)); xs; ++xs )    {
0168       xml_dim_t xshap = xs;
0169       /** Trigger on:
0170        *  - typical for CAD multi-volume shapes
0171        *
0172        *  <shape name="Assembly" type="Assembly">
0173        *    <shape  ....  />
0174        *    <position x="0" ... />
0175        *    <rotation x="0" ... />
0176        *  </shape>
0177        */
0178       if ( xshap && xshap.hasAttr(_U(type)) )  {
0179         RotationZYX rot;
0180         Position    pos;
0181         xml_comp_t  x_rot = xshap.child( _U(rotation), false );
0182         xml_comp_t  x_pos = xshap.child( _U(position), false );
0183         Volume      child = xml::createStdVolume( description, xshap );
0184         if ( x_rot ) rot = RotationZYX( x_rot.z(0),x_rot.y(0),x_rot.x(0) );
0185         if ( x_pos ) pos = Position( x_pos.x(0),x_pos.y(0),x_pos.z(0) );
0186         Transform3D trafo(Rotation3D(rot), pos);
0187         vol.placeVolume( child, trafo );
0188       }
0189     }
0190     return vol;
0191   }
0192   dd4hep::except("xml::createStdVolume","Failed to create volume. No material specified!");
0193   return Volume();
0194 }
0195 
0196 /// Create a volume using the plugin mechanism from the attributes of the XML element
0197 dd4hep::Volume dd4hep::xml::createVolume(Detector& description,
0198                                          const std::string& typ,
0199                                          xml::Element element)   {
0200   if ( !typ.empty() )   {
0201     xml_dim_t e(element);
0202     std::string fac = typ + "__volume_constructor";
0203     xml::Handle_t elt = element;
0204     TObject* obj = PluginService::Create<TObject*>(fac, &description, &elt);
0205     Volume vol = Volume(dynamic_cast<TGeoVolume*>(obj));
0206     if ( !vol.isValid() )  {
0207       PluginDebug dbg;
0208       PluginService::Create<TObject*>(fac, &description, &elt);
0209       except("xml::createShape","Failed to create volume of type %s [%s]", 
0210              typ.c_str(),dbg.missingFactory(typ).c_str());
0211     }
0212     if ( e.hasAttr(_U(name)) ) vol->SetName(e.attr<std::string>(_U(name)).c_str());
0213     vol.setAttributes(description,e.regionStr(),e.limitsStr(),e.visStr());
0214     return vol;
0215   }
0216   dd4hep::except("xml::createVolume","Failed to create volume. No materiaWNo type specified!");
0217   return Volume();
0218 }
0219 
0220 dd4hep::Volume dd4hep::xml::createPlacedEnvelope( dd4hep::Detector& description,
0221                                                   dd4hep::xml::Handle_t e, 
0222                                                   dd4hep::DetElement sdet)
0223 {  
0224   xml_det_t     x_det     = e;
0225   std::string   det_name  = x_det.nameStr();
0226   
0227   xml_comp_t    x_env     =  x_det.child( dd4hep::xml::Strng_t("envelope") );
0228   xml_comp_t    x_shape   =  x_env.child( _U(shape) ); 
0229 
0230   bool useRot = false;
0231   bool usePos = false; 
0232   Position    pos;
0233   RotationZYX rot;
0234 
0235   if( x_env.hasChild( _U(position) ) ) {
0236     usePos = true;
0237     xml_comp_t env_pos = x_env.position();
0238     pos = Position( env_pos.x(),env_pos.y(),env_pos.z() );  
0239   }
0240   if( x_env.hasChild( _U(rotation) ) ) {
0241     useRot = true;
0242     xml_comp_t    env_rot     = x_env.rotation();
0243     rot = RotationZYX( env_rot.z(),env_rot.y(),env_rot.x() );
0244   }
0245 
0246   Volume  envelope;
0247   if(  x_shape.typeStr() == "Assembly" ){
0248     envelope = Assembly( det_name+"_assembly" );
0249   } else { 
0250     // ---- create a shape from the specified xml element --------
0251     Box  env_solid = xml_comp_t( x_shape ).createShape();
0252     
0253     if( !env_solid.isValid() ){
0254       dd4hep::except("createPlacedEnvelope",
0255                      "Cannot create envelope volume : %s for detector %s.",
0256                      x_shape.typeStr().c_str(), det_name.c_str());
0257     }
0258     Material env_mat   = description.material( x_shape.materialStr() );
0259     envelope = Volume( det_name+"_envelope", env_solid, env_mat );
0260   }
0261   PlacedVolume  env_pv; 
0262   Volume        mother = description.pickMotherVolume(sdet);
0263   // ---- place the envelope into the mother volume 
0264   //      only specify transformations given in xml
0265   //      to allow for optimization 
0266 
0267   if( useRot && usePos ){
0268     env_pv =  mother.placeVolume( envelope , Transform3D( rot, pos )  );
0269   } else if( useRot ){
0270     env_pv =  mother.placeVolume( envelope , rot  );
0271   } else if( usePos ){
0272     env_pv =  mother.placeVolume( envelope , pos  );
0273   } else {
0274     env_pv = mother.placeVolume( envelope );
0275   }
0276 
0277   // ----------------------------------------------
0278   env_pv.addPhysVolID("system", sdet.id());
0279   sdet.setPlacement( env_pv );
0280   envelope.setAttributes( description,x_det.regionStr(),x_det.limitsStr(),x_env.visStr());
0281   return envelope;
0282 }
0283 
0284 void  dd4hep::xml::setDetectorTypeFlag( dd4hep::xml::Handle_t e, dd4hep::DetElement sdet )  {
0285   xml_det_t     x_det     = e;
0286   std::string   det_name  = x_det.nameStr();
0287   
0288   try{
0289     xml_comp_t  x_dettype = x_det.child( dd4hep::xml::Strng_t("type_flags") );
0290     unsigned int typeFlag = x_dettype.type();
0291     printout(DEBUG,"Utilities","+++ setDetectorTypeFlags for detector: %s set to 0x%x", det_name.c_str(), typeFlag );
0292     sdet.setTypeFlag( typeFlag );
0293   }
0294   catch(const std::runtime_error& err)   {
0295     printout(INFO,"Utilities",
0296              "+++ setDetectorTypeFlags for detector: %s not set.",
0297              det_name.c_str() );
0298     printout(DEBUG, "Utilities",
0299              "+++ setDetectorTypeFlags encountered an error:\n%s", err.what());
0300   }
0301 }
0302 
0303 namespace   {
0304   template <typename TYPE>
0305   std::size_t _propagate(bool           debug,
0306                          bool           apply_to_children, 
0307                          dd4hep::Volume vol,
0308                          TYPE           item, 
0309                          const dd4hep::Volume& (dd4hep::Volume::*apply)(const TYPE&)  const)   {
0310     std::size_t count = 0;
0311     if ( !vol->IsAssembly() )  {
0312       printout(debug ? dd4hep::ALWAYS : dd4hep::DEBUG,"VolumeConfig", "++ Volume: %s apply setting %s", vol.name(), item.name());
0313       (vol.*apply)(item);
0314       ++count;
0315     }
0316     if ( apply_to_children )   {
0317       std::set<dd4hep::Volume> handled; 
0318       for (Int_t idau = 0, ndau = vol->GetNdaughters(); idau < ndau; ++idau)   {
0319         dd4hep::Volume v = vol->GetNode(idau)->GetVolume();
0320         if ( handled.find(v) == handled.end() )   {
0321           handled.insert(v);
0322           count += _propagate(debug, apply_to_children, v, item, apply);
0323         }
0324       }
0325     }
0326     return count;
0327   }
0328 }
0329 
0330 /// Configure volume properties from XML element
0331 std::size_t dd4hep::xml::configVolume( dd4hep::Detector&     detector,
0332                                        dd4hep::xml::Handle_t element,
0333                                        dd4hep::Volume        vol,
0334                                        bool                  propagate,
0335                                        bool                  ignore_unknown)
0336 {
0337   std::size_t count = 0;
0338   if ( element )   {
0339     xml::Attribute x_dbg = element.attr_nothrow(_U(debug));
0340     bool           debug = x_dbg ? element.attr<bool>(x_dbg) : false;
0341     PrintLevel     lvl   = debug ? ALWAYS : DEBUG;
0342     for( xml_coll_t coll(element, "*"); coll; coll++ )   {
0343       xml_dim_t      itm = coll;
0344       std::string    nam   = itm.nameStr("UN-NAMED");
0345 
0346       if ( itm.tag() == TAG_REGIONREF )   {
0347         Region region = detector.region(nam);
0348         count += _propagate(debug, propagate, vol.ptr(), region, &Volume::setRegion);
0349         printout(lvl, "VolumeConfig", "++ %-12s: %-10s REGIONs   named '%s'",
0350                  vol.name(), region.isValid() ? "Set" : "Invalidate", nam.c_str());
0351       }
0352       else if ( itm.tag() == TAG_LIMITSETREF )   {
0353         LimitSet limitset = detector.limitSet(nam);      
0354         count += _propagate(debug, propagate, vol.ptr(), limitset, &Volume::setLimitSet);
0355         printout(lvl, "VolumeConfig", "++ %-12s: %-10s LIMITSETs named '%s'",
0356                  vol.name(), limitset.isValid() ? "Set" : "Invalidate", nam.c_str());
0357       }
0358       else if ( itm.tag() == TAG_VISREF )   {
0359         VisAttr attrs = detector.visAttributes(nam);
0360         count += _propagate(debug, propagate, vol.ptr(), attrs, &Volume::setVisAttributes);
0361         printout(lvl, "VolumeConfig", "++ %-12s: %-10s VISATTRs  named '%s'",
0362                  vol.name(), attrs.isValid() ? "Set" : "Invalidate", nam.c_str());
0363       }
0364       else if ( !ignore_unknown )  {
0365         except("VolumeConfig", "++ Unknown Volume property: %s [Ignored]", itm.tag().c_str());
0366       }
0367       else  {
0368         printout(DEBUG, "VolumeConfig", "++ Unknown Volume property: %s [Ignored]", itm.tag().c_str());
0369       }
0370     }
0371     return count;
0372   }
0373   except("VolumeConfig","++ Invalid XML handle to configure DetElement!");
0374   return count;
0375 }
0376 
0377 /// Configure sensitive detector from XML element
0378 std::size_t dd4hep::xml::configSensitiveDetector( dd4hep::Detector&        /* detector */,
0379                                                   dd4hep::SensitiveDetector   sensitive,
0380                                                   dd4hep::xml::Handle_t       element)
0381 {
0382   std::size_t count = 0;
0383   if ( sensitive.isValid() && element )    {
0384     xml::Attribute x_dbg = element.attr_nothrow(_U(debug));
0385     bool           debug = x_dbg ? element.attr<bool>(x_dbg) : false;
0386     PrintLevel     lvl   = debug ? ALWAYS : DEBUG;
0387 
0388     for( xml_coll_t coll(element, "*"); coll; coll++ )   {
0389       xml_dim_t itm = coll;
0390       if ( itm.tag() == TAG_COMBINE_HITS )   {
0391         bool value = itm.attr<bool>(_U(value));
0392         sensitive.setCombineHits(value);
0393         ++count;
0394         printout(lvl, "SensDetConfig", "++ %s Set property 'combine_hits' to %s",
0395                  sensitive.name(), true_false(value));
0396       }
0397       else if ( itm.tag() == TAG_VERBOSE )   {
0398         bool value = itm.attr<bool>(_U(value));
0399         sensitive.setVerbose(value);
0400         ++count;
0401         printout(lvl, "SensDetConfig", "++ %s Set property 'verbose' to %s",
0402                  sensitive.name(), true_false(value));
0403       }
0404       else if ( itm.tag() == TAG_TYPE )   {
0405         std::string value = itm.valueStr();
0406         sensitive.setType(value);
0407         ++count;
0408         printout(lvl, "SensDetConfig", "++ %s Set property 'type' to %s",
0409                  sensitive.name(), value.c_str());
0410       }
0411       else if ( itm.tag() == TAG_ECUT )   {
0412         double value = itm.attr<double>(_U(value));
0413         sensitive.setEnergyCutoff(value);
0414         ++count;
0415         printout(lvl, "SensDetConfig", "++ %s Set property 'ecut' to %f",
0416                  sensitive.name(), value);
0417       }
0418       else if ( itm.tag() == TAG_HITS_COLLECTION )   {
0419         sensitive.setHitsCollection(itm.valueStr());
0420         ++count;
0421         printout(lvl, "SensDetConfig", "++ %s Set property 'hits_collection' to %s",
0422                  sensitive.name(), itm.valueStr().c_str());
0423       }
0424       else   {
0425         except("SensDetConfig",
0426                "++ Unknown Sensitive Detector property: %s [Failure]",
0427                itm.tag().c_str());
0428       }
0429     }
0430     return count;
0431   }
0432   except("SensDetConfig",
0433          "FAILED: No valid sensitive detector. Configuration could not be applied!");
0434   return count;
0435 }
0436 
0437 #endif