File indexing completed on 2025-01-18 09:13:40
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
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
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
0037
0038
0039
0040
0041
0042
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);
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();
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();
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
0135
0136
0137
0138
0139
0140
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
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
0269 static Ref_t create_detector(Detector& description, xml_h e, Ref_t ) {
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();
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
0344 DECLARE_DETELEMENT(DD4hep_GdmlDetector,create_detector)