Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:13:40

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 
0014 // Framework include files
0015 #include <DD4hep/Detector.h>
0016 #include <DD4hep/Memory.h>
0017 #include <DD4hep/DD4hepUI.h>
0018 #include <DD4hep/Factories.h>
0019 #include <DD4hep/Printout.h>
0020 #include <DD4hep/DetectorTools.h>
0021 #include <DD4hep/DetFactoryHelper.h>
0022 #include <XML/DocumentHandler.h>
0023 #include <XML/Utilities.h>
0024 
0025 // ROOT includes
0026 #include <TInterpreter.h>
0027 #include <TGeoElement.h>
0028 #include <TGeoManager.h>
0029 #include <TGDMLParse.h>
0030 #include <TGDMLWrite.h>
0031 #include <TUri.h>
0032 
0033 using namespace std;
0034 using namespace dd4hep;
0035 
0036 /// ROOT GDML reader plugin
0037 /**
0038  *  Factory: DD4hep_ROOTGDMLParse
0039  *
0040  *  \author  M.Frank
0041  *  \version 1.0
0042  *  \date    01/04/2014
0043  */
0044 static long gdml_parse(Detector& description, int argc, char** argv) {
0045   if ( argc > 0 )   {
0046     string input, path;
0047     bool wrld = false;
0048     for(int i = 0; i < argc && argv[i]; ++i)  {
0049       if ( 0 == ::strncmp("-input",argv[i],2) )
0050         input = argv[++i];
0051       else if ( 0 == ::strncmp("-path", argv[i],2) )
0052         path  = argv[++i];
0053       else if ( 0 == ::strncmp("-world", argv[i],2) )
0054         wrld  = true;
0055     }
0056     if ( input.empty() || (path.empty() && !wrld) )   {
0057       cout <<
0058         "Usage: -plugin <name> -arg [-arg]                                                  \n"
0059         "     name:   factory name     DD4hep_ROOTGDMLParse                                 \n"
0060         "     -input  <string>         Input file name.                                     \n"
0061         "     -path   <string>         Path to parent detector element to attach            \n"
0062         "                              top volume from GDML file.                           \n"
0063         "     -world  <string>         Name of the world object if to be imported from gdml.\n"
0064         "     Note: -path and -world options are exclusive.                                 \n"
0065         "\tArguments given: " << arguments(argc,argv) << endl << flush;
0066       ::exit(EINVAL);
0067     }
0068     printout(INFO,"ROOTGDMLParse","+++ Read geometry from GDML file file:%s",input.c_str());
0069     vector<string> elements = detail::tools::pathElements(path);
0070     if ( !wrld && !elements.empty() )   {
0071       DetElement world = description.world();
0072       DetElement parent = world, child;
0073       for(size_t i=0; i < elements.size(); ++i)  {
0074         const auto& e = elements[i];
0075         if ( e == world.name() )
0076           continue;
0077         child = parent.child(e, false);
0078         if ( child.isValid() )  {
0079           parent = child;
0080           continue;
0081         }
0082         child = DetElement(e, 0); // Inactive child, no sensitive detector, no ID
0083         PlacedVolume pv;
0084         Volume mother = (parent==world) ? description.pickMotherVolume(child) : parent.volume();
0085         if ( i == elements.size()-1 )  {
0086           TGDMLParse parser;
0087           TUri uri(input.c_str());
0088           input = uri.GetRelativePart();
0089           Volume vol = parser.GDMLReadFile(input.c_str());
0090           if ( vol.isValid() )   {
0091             vol.import(); // We require the extensions in dd4hep.
0092             pv = mother.placeVolume(vol);
0093             child.setPlacement(pv);
0094             if (parent == world) description.add(child);
0095             else                 parent.add(child);
0096             printout(INFO,"ROOTGDMLParse","+++ Attach GDML volume %s to Element path:%s",
0097                      vol.name(), path.c_str());
0098             return 1;
0099           }
0100           except("ROOTGDMLParse","+++ Failed to parse GDML file:%s for path:%s",
0101                  input.c_str(),path.c_str());
0102         }
0103         pv = mother.placeVolume(Assembly(e));
0104         child.setPlacement(pv);
0105         if (parent == world) description.add(child);
0106         else                 parent.add(child);
0107       }
0108     }
0109     else if ( wrld )   {
0110       TGDMLParse parser;
0111       TUri uri(input.c_str());
0112       input = uri.GetRelativePart();
0113       Volume vol = parser.GDMLReadFile(input.c_str());
0114       if ( vol.isValid() )   {
0115         vol.import(); // We require the extensions in dd4hep.
0116         description.manager().SetTopVolume(vol.ptr());
0117         description.init();
0118         description.endDocument();
0119         printout(INFO,"ROOTGDMLParse","+++ Attach GDML volume %s", vol.name());
0120         return 1;
0121       }
0122       except("ROOTGDMLParse","+++ Failed to parse GDML file:%s for path:%s",
0123              input.c_str(),path.c_str());
0124     }
0125     
0126     except("ROOTGDMLParse","+++ Invalid DetElement path given: %s", path.c_str());
0127   }
0128   except("ROOTGDMLParse","+++ No input file name given.");
0129   return 0;
0130 }
0131 DECLARE_APPLY(DD4hep_ROOTGDMLParse,gdml_parse)
0132 
0133 
0134 /// ROOT GDML writer plugin
0135 /**
0136  *  Factory: DD4hep_ROOTGDMLExtract
0137  *
0138  *  \author  M.Frank
0139  *  \version 1.0
0140  *  \date    01/04/2014
0141  */
0142 static long gdml_extract(Detector& description, int argc, char** argv) {
0143   if ( argc > 0 )   {
0144     bool detector = true, volpath = false;
0145     string output, path;
0146     int precision = 12;
0147     for(int i = 0; i < argc && argv[i]; ++i)  {
0148       if ( 0 == ::strncmp("-output",argv[i],2) )
0149         output = argv[++i];
0150       else if ( 0 == ::strncmp("-path", argv[i],4) )
0151         path  = argv[++i];
0152       else if ( 0 == ::strncmp("-volpath", argv[i],7) )
0153         volpath  = true,  detector = false;
0154       else if ( 0 == ::strncmp("-volname", argv[i],7) )
0155         volpath  = false, detector = false;
0156       else if ( 0 == ::strncmp("-detector", argv[i],8) )
0157         volpath  = false, detector = true;
0158       else if ( 0 == ::strncmp("-precision", argv[i],5) )
0159         precision = ::atol(argv[++i]);
0160     }
0161     if ( output.empty() || path.empty() )   {
0162       cout <<
0163         "Usage: -plugin <name> -arg [-arg]                                            \n"
0164         "     name:   factory name     DD4hep_ROOTGDMLExtract                         \n"
0165         "     -output <string>         Output file name.                              \n"
0166         "     -path   <string>         Path to parent detector element to extract     \n"
0167         "                              top volume to GDML file.                       \n"
0168         "     -detector                Indicate that the path is a DetElement path    \n"
0169         "     -volpath                 Indicate that the path is a volume path        \n"
0170         "     -volname                 Indicate that the path is a volume name prefix \n"
0171         "     -precision <number>      GDML output floating point precision           \n"
0172         "\tArguments given: " << arguments(argc,argv) << endl << flush;
0173       ::exit(EINVAL);
0174     }
0175     if ( detector )   {
0176       printout(INFO,"ROOTGDMLExtract","+++ Write geometry %s to GDML file file:%s",
0177                path.c_str(), output.c_str());
0178       DetElement de = detail::tools::findElement(description,path);
0179       if ( de.isValid() )   {
0180         TGDMLWrite extract;
0181         TUri uri(output.c_str());
0182         description.manager().SetExportPrecision(precision);
0183 #if   ROOT_VERSION_CODE > ROOT_VERSION(6,27,1)
0184         extract.SetIgnoreDummyMaterial(true);
0185         extract.SetNamingSpeed(TGDMLWrite::kfastButUglySufix);
0186         extract.WriteGDMLfile(&description.manager(), de.placement().ptr(), uri.GetRelativePart());
0187 #else
0188         extract.WriteGDMLfile(&description.manager(), de.placement().ptr(), uri.GetRelativePart());
0189 #endif
0190         return 1;
0191       }
0192       except("ROOTGDMLExtract","+++ Invalid DetElement path given: %s", path.c_str());
0193     }
0194     else  {
0195       struct Actor {
0196         bool _volpath;
0197         const string& _path;
0198         TGeoNode*     _node = 0;
0199         Actor(const string& p, bool vp) : _volpath(vp), _path(p)  {}
0200         void scan(TGeoNode* n, const std::string& p="")  {
0201           string nam;
0202           if ( _volpath )  {
0203             nam = p + '/';
0204             nam += n->GetName();
0205             if ( _volpath && nam.find(_path) == 0 )   {
0206               _node = n;
0207             }
0208             for (Int_t idau = 0, ndau = n->GetNdaughters(); _node == 0 && idau < ndau; ++idau)
0209               scan(n->GetDaughter(idau), p);
0210             return;
0211           }
0212           nam = n->GetName();
0213           if ( nam.find(_path) == 0 )   {
0214             _node = n;
0215             printout(ALWAYS,"Check","+++ Found required volume: %s",_path.c_str());
0216             printout(ALWAYS,"Check","+++                     -> %s",nam.c_str());
0217             return;
0218           }
0219           for (Int_t idau = 0, ndau = n->GetNdaughters(); _node == 0 && idau < ndau; ++idau)
0220             scan(n->GetDaughter(idau),nam);
0221         }
0222       };
0223       Volume top = description.worldVolume();
0224       TObjArray* ents = top->GetNodes();
0225       Actor a(path, volpath ? true : false);
0226       for (Int_t i = 0, n = ents->GetEntries(); i < n && a._node == 0; ++i)  {
0227         TGeoNode* node = (TGeoNode*)ents->At(i);
0228         a.scan(node, node->GetName());
0229       }
0230       if ( a._node )    {
0231         TGDMLWrite extract;
0232         TUri uri(output.c_str());
0233         description.manager().SetExportPrecision(precision);
0234 #if ROOT_VERSION_CODE > ROOT_VERSION(6,27,1)
0235         extract.SetIgnoreDummyMaterial(true);
0236         extract.SetNamingSpeed(TGDMLWrite::kfastButUglySufix);
0237         extract.WriteGDMLfile(&description.manager(), a._node, uri.GetRelativePart());
0238 #else
0239         extract.WriteGDMLfile(&description.manager(), a._node, uri.GetRelativePart());
0240 #endif
0241         return 1;
0242       }
0243       except("ROOTGDMLExtract","+++ Invalid volume path/name given: %s", path.c_str());
0244     }
0245   }
0246   except("ROOTGDMLExtract","+++ No output file name given.");
0247   return 0;
0248 }
0249 DECLARE_APPLY(DD4hep_ROOTGDMLExtract,gdml_extract)
0250 
0251 /// Factory for backwards compatibility
0252 static long create_gdml_from_dd4hep(Detector& description, int argc, char** argv) {
0253   if ( argc > 0 )    {
0254     string output = argv[0];
0255     if ( output.substr(0,5) == "file:" ) output = output.substr(6);
0256     const char* av[] = {"DD4hepGeometry2GDML", "-output", output.c_str(), "-path", "/world", 0};
0257     if ( 1 == gdml_extract(description, 5, (char**)av) )   {
0258       printout(INFO,"Geometry2GDML","+++ Successfully extracted GDML to %s",output.c_str());
0259       return 1;
0260     }
0261     except("Geometry2GDML","+++ FAILED to extract GDML file %s.",output.c_str());
0262   }
0263   except("Geometry2GDML","+++ No output file name given.");
0264   return 0;
0265 }
0266 DECLARE_APPLY(DD4hepGeometry2GDML, create_gdml_from_dd4hep)
0267 
0268 /// Factory to import subdetectors from GDML fragment
0269 static Ref_t create_detector(Detector& description, xml_h e, Ref_t /* sens_det */)  {
0270   using namespace dd4hep::detail;
0271   xml_det_t   x_det = e;
0272   int         id    = x_det.hasAttr(_U(id)) ? x_det.id() : 0;
0273   xml_dim_t   x_pos  (x_det.child(_U(position),false));
0274   xml_dim_t   x_rot  (x_det.child(_U(rotation),false));
0275   xml_dim_t   x_gdml (x_det.child(_U(gdmlFile)));
0276   xml_dim_t   x_par  (x_det.child(_U(parent)));
0277   string      name    = x_det.nameStr();
0278   string      par_nam = x_par.nameStr();
0279   string      gdml   = x_gdml.attr<string>(_U(ref));
0280   string      gdml_physvol = dd4hep::getAttrOrDefault<string>(x_gdml, _Unicode(physvol), "");
0281   DetElement  det_parent = description.detector(par_nam);
0282   TGDMLParse parser;
0283   if ( !gdml.empty() && gdml[0] == '/' )  {
0284     TUri uri(gdml.c_str());
0285     gdml = uri.GetRelativePart();
0286   }
0287   else {
0288     string path = xml::DocumentHandler::system_path(e, gdml);
0289     TUri uri(path.c_str());
0290     gdml = uri.GetRelativePart();
0291   }
0292   if ( !det_parent.isValid() )  {
0293     except(name,"+++ Cannot access detector parent: %s",par_nam.c_str());
0294   }  
0295   DetElement  sdet(name, id);
0296   Volume volume = parser.GDMLReadFile(gdml.c_str());
0297   if ( !volume.isValid() )   {
0298     except("ROOTGDMLParse","+++ Failed to parse GDML file:%s",gdml.c_str());
0299   }
0300   volume.import(); // We require the extensions in dd4hep.
0301   printout(INFO,"ROOTGDMLParse","+++ Attach GDML volume %s", volume.name());
0302   Volume mother = det_parent.volume();
0303   PlacedVolume pv;
0304 
0305   if ( !gdml_physvol.empty() ) {
0306     PlacedVolume node = volume->FindNode(gdml_physvol.c_str());
0307     if ( !node.isValid() ) {
0308       printout(ERROR,"ROOTGDMLParse","+++ Invalid gdml placed volume %s", gdml_physvol.c_str());
0309       printout(ERROR,"ROOTGDMLParse","+++ Valid top-level nodes are:");
0310       volume->PrintNodes();
0311       except("ROOTGDMLParse","+++ Failed to parse GDML file:%s for node:%s",
0312         gdml.c_str(), gdml_physvol.c_str());
0313     }
0314     volume = node.volume();
0315   }
0316 
0317   if ( x_pos && x_rot )   {
0318     Rotation3D rot(RotationZYX(x_rot.z(),x_rot.y(),x_rot.x()));
0319     Transform3D transform(rot,Position(x_pos.x(),x_pos.y(),x_pos.z()));
0320     pv = mother.placeVolume(volume,transform);
0321   }
0322   else if ( x_rot )  {
0323     Rotation3D rot(RotationZYX(x_rot.z(),x_rot.y(),x_rot.x()));
0324     Transform3D transform(rot,Position(0,0,0));
0325     pv = mother.placeVolume(volume,transform);
0326   }
0327   else if ( x_pos )   {
0328     pv = mother.placeVolume(volume,Position(x_pos.x(),x_pos.y(),x_pos.z()));
0329   }
0330   else  {
0331     pv = mother.placeVolume(volume);
0332   }
0333   volume.setVisAttributes(description, x_det.visStr());
0334   volume.setLimitSet(description, x_det.limitsStr());
0335   volume.setRegion(description, x_det.regionStr());
0336   if ( id != 0 )  {
0337     pv.addPhysVolID("system", id);
0338   }
0339   sdet.setPlacement(pv);
0340   return sdet;
0341 }
0342 
0343 // first argument is the type from the xml file
0344 DECLARE_DETELEMENT(DD4hep_GdmlDetector,create_detector)