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