File indexing completed on 2025-12-17 09:21:54
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 #include "PHG4GDMLWrite.hh"
0036
0037 #include <Geant4/G4LogicalVolume.hh>
0038 #include <Geant4/G4PVDivision.hh>
0039 #include <Geant4/G4Transform3D.hh>
0040 #include <Geant4/G4Version.hh>
0041
0042 #include <sys/stat.h>
0043 #include <iostream>
0044
0045 G4bool PHG4GDMLWrite::addPointerToName = true;
0046
0047 PHG4GDMLWrite::PHG4GDMLWrite()
0048 : doc(nullptr)
0049 , extElement(nullptr)
0050 , userinfoElement(nullptr)
0051 {
0052 }
0053
0054 G4bool PHG4GDMLWrite::FileExists(const G4String& fname) const
0055 {
0056 struct stat FileInfo{};
0057 return (stat(fname.c_str(), &FileInfo) == 0);
0058 }
0059
0060 PHG4GDMLWrite::VolumeMapType& PHG4GDMLWrite::VolumeMap()
0061 {
0062 static VolumeMapType instance;
0063 return instance;
0064 }
0065
0066 PHG4GDMLWrite::PhysVolumeMapType& PHG4GDMLWrite::PvolumeMap()
0067 {
0068 static PhysVolumeMapType instance;
0069 return instance;
0070 }
0071
0072 PHG4GDMLWrite::DepthMapType& PHG4GDMLWrite::DepthMap()
0073 {
0074 static DepthMapType instance;
0075 return instance;
0076 }
0077
0078 void PHG4GDMLWrite::AddExtension(xercesc::DOMElement* ,
0079 const G4LogicalVolume* const )
0080 {
0081
0082
0083 }
0084
0085 void PHG4GDMLWrite::ExtensionWrite(xercesc::DOMElement* )
0086 {
0087
0088 }
0089
0090 void PHG4GDMLWrite::AddAuxInfo(PHG4GDMLAuxListType* auxInfoList,
0091 xercesc::DOMElement* element)
0092 {
0093 for (const auto & iaux : *auxInfoList)
0094 {
0095 xercesc::DOMElement* auxiliaryElement = NewElement("auxiliary");
0096 element->appendChild(auxiliaryElement);
0097
0098 auxiliaryElement->setAttributeNode(NewAttribute("auxtype", iaux.type));
0099 auxiliaryElement->setAttributeNode(NewAttribute("auxvalue", iaux.value));
0100 if (!iaux.unit.empty())
0101 {
0102 auxiliaryElement->setAttributeNode(NewAttribute("auxunit", iaux.unit));
0103 }
0104
0105 if (iaux.auxList)
0106 {
0107 AddAuxInfo(iaux.auxList, auxiliaryElement);
0108 }
0109 }
0110 return;
0111 }
0112
0113 void PHG4GDMLWrite::UserinfoWrite(xercesc::DOMElement* gdmlElement)
0114 {
0115 if (!auxList.empty())
0116 {
0117 std::cout << "PHG4GDML: Writing userinfo..." << std::endl;
0118
0119 userinfoElement = NewElement("userinfo");
0120 gdmlElement->appendChild(userinfoElement);
0121 AddAuxInfo(&auxList, userinfoElement);
0122 }
0123 }
0124
0125 #if G4VERSION_NUMBER >= 1100
0126 G4String PHG4GDMLWrite::GenerateName(const G4String& name, const void* const ptr)
0127 {
0128 G4String nameOut;
0129 std::stringstream stream;
0130 stream << name;
0131 if (addPointerToName)
0132 {
0133 stream << ptr;
0134 };
0135
0136 nameOut = G4String(stream.str());
0137 std::vector<char> toremove = {' ', '/', ':', '#', '+'};
0138 for (auto c : toremove)
0139 {
0140 if (G4StrUtil::contains(nameOut, c))
0141 {
0142 std::replace(nameOut.begin(), nameOut.end(), c, '_');
0143 }
0144 }
0145 return nameOut;
0146 }
0147 #else
0148 G4String PHG4GDMLWrite::GenerateName(const G4String& name, const void* const ptr)
0149 {
0150 G4String nameOut;
0151 std::stringstream stream;
0152 stream << name;
0153 if (addPointerToName)
0154 {
0155 stream << ptr;
0156 };
0157
0158 nameOut = G4String(stream.str());
0159 if (nameOut.contains(' ')) {
0160 nameOut.erase(std::remove(nameOut.begin(), nameOut.end(), ' '), nameOut.end());
0161 }
0162
0163 return nameOut;
0164 }
0165 #endif
0166
0167 xercesc::DOMAttr* PHG4GDMLWrite::NewAttribute(const G4String& name,
0168 const G4String& value)
0169 {
0170 xercesc::XMLString::transcode(name, tempStr, 9999);
0171 xercesc::DOMAttr* att = doc->createAttribute(tempStr);
0172 xercesc::XMLString::transcode(value, tempStr, 9999);
0173 att->setValue(tempStr);
0174 return att;
0175 }
0176
0177 xercesc::DOMAttr* PHG4GDMLWrite::NewAttribute(const G4String& name,
0178 const G4double& value)
0179 {
0180 xercesc::XMLString::transcode(name, tempStr, 9999);
0181 xercesc::DOMAttr* att = doc->createAttribute(tempStr);
0182 std::ostringstream ostream;
0183 ostream.precision(15);
0184 ostream << value;
0185 G4String str = ostream.str();
0186 xercesc::XMLString::transcode(str, tempStr, 9999);
0187 att->setValue(tempStr);
0188 return att;
0189 }
0190
0191 xercesc::DOMElement* PHG4GDMLWrite::NewElement(const G4String& name)
0192 {
0193 xercesc::XMLString::transcode(name, tempStr, 9999);
0194 return doc->createElement(tempStr);
0195 }
0196
0197 G4Transform3D PHG4GDMLWrite::Write(const G4String& fname,
0198 const G4LogicalVolume* const logvol,
0199 const G4String& setSchemaLocation,
0200 const G4int depth,
0201 G4bool refs)
0202 {
0203 SchemaLocation = setSchemaLocation;
0204 addPointerToName = refs;
0205
0206 if (depth == 0)
0207 {
0208 std::cout << "PHG4GDML: Writing '" << fname << "'..." << std::endl;
0209 }
0210 else
0211 {
0212 std::cout << "PHG4GDML: Writing module '" << fname << "'..." << std::endl;
0213 }
0214
0215 if (FileExists(fname))
0216 {
0217 G4String ErrorMessage = "File '" + fname + "' already exists!";
0218 G4Exception("PHG4GDMLWrite::Write()", "InvalidSetup",
0219 FatalException, ErrorMessage);
0220 }
0221
0222 VolumeMap().clear();
0223
0224
0225 xercesc::XMLString::transcode("LS", tempStr, 9999);
0226 xercesc::DOMImplementationRegistry::getDOMImplementation(tempStr);
0227 xercesc::XMLString::transcode("Range", tempStr, 9999);
0228 xercesc::DOMImplementation* impl =
0229 xercesc::DOMImplementationRegistry::getDOMImplementation(tempStr);
0230 xercesc::XMLString::transcode("gdml", tempStr, 9999);
0231 doc = impl->createDocument(nullptr, tempStr, nullptr);
0232 xercesc::DOMElement* gdml = doc->getDocumentElement();
0233
0234 #if XERCES_VERSION_MAJOR >= 3
0235
0236 xercesc::DOMLSSerializer* writer =
0237 ((xercesc::DOMImplementationLS*) impl)->createLSSerializer();
0238
0239 xercesc::DOMConfiguration* dc = writer->getDomConfig();
0240 dc->setParameter(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint, true);
0241
0242 #else
0243
0244 xercesc::DOMWriter* writer =
0245 ((xercesc::DOMImplementationLS*) impl)->createDOMWriter();
0246
0247 if (writer->canSetFeature(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint, true))
0248 writer->setFeature(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint, true);
0249
0250 #endif
0251
0252 gdml->setAttributeNode(NewAttribute("xmlns:xsi",
0253 "http://www.w3.org/2001/XMLSchema-instance"));
0254 gdml->setAttributeNode(NewAttribute("xsi:noNamespaceSchemaLocation",
0255 SchemaLocation));
0256
0257 ExtensionWrite(gdml);
0258 DefineWrite(gdml);
0259 MaterialsWrite(gdml);
0260 SolidsWrite(gdml);
0261 StructureWrite(gdml);
0262 UserinfoWrite(gdml);
0263 SetupWrite(gdml, logvol);
0264
0265 G4Transform3D R = TraverseVolumeTree(logvol, depth);
0266
0267 SurfacesWrite();
0268 xercesc::XMLFormatTarget* myFormTarget =
0269 new xercesc::LocalFileFormatTarget(fname.c_str());
0270
0271 try
0272 {
0273 #if XERCES_VERSION_MAJOR >= 3
0274
0275 xercesc::DOMLSOutput* theOutput =
0276 ((xercesc::DOMImplementationLS*) impl)->createLSOutput();
0277 theOutput->setByteStream(myFormTarget);
0278 writer->write(doc, theOutput);
0279 #else
0280 writer->writeNode(myFormTarget, *doc);
0281 #endif
0282 }
0283 catch (const xercesc::XMLException& toCatch)
0284 {
0285 char* message = xercesc::XMLString::transcode(toCatch.getMessage());
0286 std::cout << "PHG4GDML: Exception message is: " << message << std::endl;
0287 xercesc::XMLString::release(&message);
0288 return G4Transform3D::Identity;
0289 }
0290 catch (const xercesc::DOMException& toCatch)
0291 {
0292 char* message = xercesc::XMLString::transcode(toCatch.msg);
0293 std::cout << "PHG4GDML: Exception message is: " << message << std::endl;
0294 xercesc::XMLString::release(&message);
0295 return G4Transform3D::Identity;
0296 }
0297 catch (...)
0298 {
0299 std::cout << "PHG4GDML: Unexpected Exception!" << std::endl;
0300 return G4Transform3D::Identity;
0301 }
0302
0303 delete myFormTarget;
0304 writer->release();
0305
0306 if (depth == 0)
0307 {
0308 std::cout << "PHG4GDML: Writing '" << fname << "' done !" << std::endl;
0309 }
0310 else
0311 {
0312 std::cout << "PHG4GDML: Writing module '" << fname << "' done !" << std::endl;
0313 }
0314
0315 return R;
0316 }
0317
0318 void PHG4GDMLWrite::AddModule(const G4VPhysicalVolume* const physvol)
0319 {
0320 if (physvol == nullptr)
0321 {
0322 G4Exception("PHG4GDMLWrite::AddModule()", "InvalidSetup", FatalException,
0323 "Invalid NULL pointer is specified for modularization!");
0324 return;
0325 }
0326 G4String fname = GenerateName(physvol->GetName(), physvol);
0327 std::cout << "PHG4GDML: Adding module '" << fname << "'..." << std::endl;
0328
0329 if (dynamic_cast<const G4PVDivision*>(physvol))
0330 {
0331 G4Exception("PHG4GDMLWrite::AddModule()", "InvalidSetup", FatalException,
0332 "It is not possible to modularize by divisionvol!");
0333 return;
0334 }
0335 if (physvol->IsParameterised())
0336 {
0337 G4Exception("PHG4GDMLWrite::AddModule()", "InvalidSetup", FatalException,
0338 "It is not possible to modularize by parameterised volume!");
0339 return;
0340 }
0341 if (physvol->IsReplicated())
0342 {
0343 G4Exception("PHG4GDMLWrite::AddModule()", "InvalidSetup", FatalException,
0344 "It is not possible to modularize by replicated volume!");
0345 return;
0346 }
0347
0348 PvolumeMap()[physvol] = fname;
0349 }
0350
0351 void PHG4GDMLWrite::AddModule(const G4int depth)
0352 {
0353 if (depth < 0)
0354 {
0355 G4Exception("PHG4GDMLWrite::AddModule()", "InvalidSetup", FatalException,
0356 "Depth must be a positive number!");
0357 }
0358 if (DepthMap().contains(depth))
0359 {
0360 G4Exception("PHG4GDMLWrite::AddModule()", "InvalidSetup", FatalException,
0361 "Adding module(s) at this depth is already requested!");
0362 }
0363 DepthMap()[depth] = 0;
0364 }
0365
0366 G4String PHG4GDMLWrite::Modularize(const G4VPhysicalVolume* const physvol,
0367 const G4int depth)
0368 {
0369 if (PvolumeMap().contains(physvol))
0370 {
0371 return PvolumeMap()[physvol];
0372 }
0373
0374 if (DepthMap().contains(depth))
0375 {
0376 std::stringstream stream;
0377 stream << "depth" << depth << "_module" << DepthMap()[depth] << ".gdml";
0378 DepthMap()[depth]++;
0379 return G4String(stream.str());
0380 }
0381
0382 return G4String("");
0383
0384 }
0385
0386 void PHG4GDMLWrite::AddAuxiliary(const PHG4GDMLAuxStructType& myaux)
0387 {
0388 auxList.push_back(myaux);
0389 }
0390
0391 void PHG4GDMLWrite::SetAddPointerToName(G4bool set)
0392 {
0393 addPointerToName = set;
0394 }