Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-12-17 09:21:54

0001 //
0002 // ********************************************************************
0003 // * License and Disclaimer                                           *
0004 // *                                                                  *
0005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
0006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
0007 // * conditions of the Geant4 Software License,  included in the file *
0008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
0009 // * include a list of copyright holders.                             *
0010 // *                                                                  *
0011 // * Neither the authors of this software system, nor their employing *
0012 // * institutes,nor the agencies providing financial support for this *
0013 // * work  make  any representation or  warranty, express or implied, *
0014 // * regarding  this  software system or assume any liability for its *
0015 // * use.  Please see the license in the file  LICENSE  and URL above *
0016 // * for the full disclaimer and the limitation of liability.         *
0017 // *                                                                  *
0018 // * This  code  implementation is the result of  the  scientific and *
0019 // * technical work of the GEANT4 collaboration.                      *
0020 // * By using,  copying,  modifying or  distributing the software (or *
0021 // * any work based  on the software)  you  agree  to acknowledge its *
0022 // * use  in  resulting  scientific  publications,  and indicate your *
0023 // * acceptance of all terms of the Geant4 Software license.          *
0024 // ********************************************************************
0025 //
0026 //
0027 // $Id: PHG4GDMLWrite.cc 69013 2013-04-15 09:41:13Z gcosmo $
0028 //
0029 // class PHG4GDMLWrite Implementation
0030 //
0031 // Original author: Zoltan Torzsok, November 2007
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* /*unused*/,
0079                                  const G4LogicalVolume* const /*unused*/)
0080 {
0081   // Empty implementation. To be overwritten by user for specific extensions
0082   // related to attributes associated to volumes
0083 }
0084 
0085 void PHG4GDMLWrite::ExtensionWrite(xercesc::DOMElement* /*unused*/)
0086 {
0087   // Empty implementation. To be overwritten by user for specific extensions
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();  // The module map is global for all modules,
0223                         // so clear it only at once!
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   // DOM L3 as per Xerces 3.0 API
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     // DOM L3 as per Xerces 3.0 API
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];  // Modularize via physvol
0372   }
0373 
0374   if (DepthMap().contains(depth))  // Modularize via depth
0375   {
0376     std::stringstream stream;
0377     stream << "depth" << depth << "_module" << DepthMap()[depth] << ".gdml";
0378     DepthMap()[depth]++;  // There can be more modules at this depth!
0379     return G4String(stream.str());
0380   }
0381 
0382   return G4String("");  // Empty string for module name = no modularization
0383                         // was requested at that level/physvol!
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 }