Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-06 08:19:14

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 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   // Empty implementation. To be overwritten by user for specific extensions
0086   // related to attributes associated to volumes
0087 }
0088 
0089 void PHG4GDMLWrite::ExtensionWrite(xercesc::DOMElement*)
0090 {
0091   // Empty implementation. To be overwritten by user for specific extensions
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();  // The module map is global for all modules,
0228                         // so clear it only at once!
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   // DOM L3 as per Xerces 3.0 API
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     // DOM L3 as per Xerces 3.0 API
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];  // Modularize via physvol
0377   }
0378 
0379   if (DepthMap().find(depth) != DepthMap().end())  // Modularize via depth
0380   {
0381     std::stringstream stream;
0382     stream << "depth" << depth << "_module" << DepthMap()[depth] << ".gdml";
0383     DepthMap()[depth]++;  // There can be more modules at this depth!
0384     return G4String(stream.str());
0385   }
0386 
0387   return G4String("");  // Empty string for module name = no modularization
0388                         // was requested at that level/physvol!
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 }