EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PHG4GDMLWrite.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file PHG4GDMLWrite.cc
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 //
27 // $Id: PHG4GDMLWrite.cc 69013 2013-04-15 09:41:13Z gcosmo $
28 //
29 // class PHG4GDMLWrite Implementation
30 //
31 // Original author: Zoltan Torzsok, November 2007
32 //
33 // --------------------------------------------------------------------
34 
35 #include "PHG4GDMLWrite.hh"
36 
37 #include <Geant4/G4LogicalVolume.hh>
38 #include <Geant4/G4PVDivision.hh>
39 #include <Geant4/G4Transform3D.hh>
40 
41 #include <sys/stat.h>
42 #include <iostream>
43 
45 
46 PHG4GDMLWrite::PHG4GDMLWrite() : doc(nullptr), extElement(nullptr), userinfoElement(nullptr)
47 {
48 }
49 
51 {
52 }
53 
54 G4bool PHG4GDMLWrite::FileExists(const G4String& fname) const
55 {
56  struct stat FileInfo;
57  return (stat(fname.c_str(),&FileInfo) == 0);
58 }
59 
61 {
62  static VolumeMapType instance;
63  return instance;
64 }
65 
67 {
68  static PhysVolumeMapType instance;
69  return instance;
70 }
71 
73 {
74  static DepthMapType instance;
75  return instance;
76 }
77 
78 void PHG4GDMLWrite::AddExtension(xercesc::DOMElement*,
79  const G4LogicalVolume* const)
80 {
81  // Empty implementation. To be overwritten by user for specific extensions
82  // related to attributes associated to volumes
83 }
84 
85 void PHG4GDMLWrite::ExtensionWrite(xercesc::DOMElement*)
86 {
87  // Empty implementation. To be overwritten by user for specific extensions
88 }
89 
91  xercesc::DOMElement* element)
92 {
93  for(std::vector<PHG4GDMLAuxStructType>::const_iterator
94  iaux = auxInfoList->begin(); iaux != auxInfoList->end(); ++iaux )
95  {
96  xercesc::DOMElement* auxiliaryElement = NewElement("auxiliary");
97  element->appendChild(auxiliaryElement);
98 
99  auxiliaryElement->setAttributeNode(NewAttribute("auxtype", (*iaux).type));
100  auxiliaryElement->setAttributeNode(NewAttribute("auxvalue", (*iaux).value));
101  if (((*iaux).unit)!="")
102  {
103  auxiliaryElement->setAttributeNode(NewAttribute("auxunit", (*iaux).unit));
104  }
105 
106  if (iaux->auxList) { AddAuxInfo(iaux->auxList, auxiliaryElement); }
107  }
108  return;
109 }
110 
111 void PHG4GDMLWrite::UserinfoWrite(xercesc::DOMElement* gdmlElement)
112 {
113  if(auxList.size()>0)
114  {
115  std::cout << "PHG4GDML: Writing userinfo..." << std::endl;
116 
117  userinfoElement = NewElement("userinfo");
118  gdmlElement->appendChild(userinfoElement);
120  }
121 }
122 
123 G4String PHG4GDMLWrite::GenerateName(const G4String& name, const void* const ptr)
124 {
125  G4String nameOut;
126  std::stringstream stream; stream << name;
127  if (addPointerToName) { stream << ptr; };
128 
129  nameOut=G4String(stream.str());
130  if(nameOut.contains(' '))
131  nameOut.erase(std::remove(nameOut.begin(),nameOut.end(),' '),nameOut.end());
132 
133  return nameOut;
134 }
135 
136 xercesc::DOMAttr* PHG4GDMLWrite::NewAttribute(const G4String& name,
137  const G4String& value)
138 {
139  xercesc::XMLString::transcode(name,tempStr,9999);
140  xercesc::DOMAttr* att = doc->createAttribute(tempStr);
141  xercesc::XMLString::transcode(value,tempStr,9999);
142  att->setValue(tempStr);
143  return att;
144 }
145 
146 xercesc::DOMAttr* PHG4GDMLWrite::NewAttribute(const G4String& name,
147  const G4double& value)
148 {
149  xercesc::XMLString::transcode(name,tempStr,9999);
150  xercesc::DOMAttr* att = doc->createAttribute(tempStr);
151  std::ostringstream ostream;
152  ostream.precision(15);
153  ostream << value;
154  G4String str = ostream.str();
155  xercesc::XMLString::transcode(str,tempStr,9999);
156  att->setValue(tempStr);
157  return att;
158 }
159 
160 xercesc::DOMElement* PHG4GDMLWrite::NewElement(const G4String& name)
161 {
162  xercesc::XMLString::transcode(name,tempStr,9999);
163  return doc->createElement(tempStr);
164 }
165 
166 G4Transform3D PHG4GDMLWrite::Write(const G4String& fname,
167  const G4LogicalVolume* const logvol,
168  const G4String& setSchemaLocation,
169  const G4int depth,
170  G4bool refs)
171 {
172  SchemaLocation = setSchemaLocation;
173  addPointerToName = refs;
174 
175  if (depth==0) { std::cout << "PHG4GDML: Writing '" << fname << "'..." << std::endl; }
176  else { std::cout << "PHG4GDML: Writing module '" << fname << "'..." << std::endl; }
177 
178  if (FileExists(fname))
179  {
180  G4String ErrorMessage = "File '"+fname+"' already exists!";
181  G4Exception("PHG4GDMLWrite::Write()", "InvalidSetup",
182  FatalException, ErrorMessage);
183  }
184 
185  VolumeMap().clear(); // The module map is global for all modules,
186  // so clear it only at once!
187 
188  xercesc::XMLString::transcode("LS", tempStr, 9999);
189  xercesc::DOMImplementationRegistry::getDOMImplementation(tempStr);
190  xercesc::XMLString::transcode("Range", tempStr, 9999);
191  xercesc::DOMImplementation* impl =
192  xercesc::DOMImplementationRegistry::getDOMImplementation(tempStr);
193  xercesc::XMLString::transcode("gdml", tempStr, 9999);
194  doc = impl->createDocument(0,tempStr,0);
195  xercesc::DOMElement* gdml = doc->getDocumentElement();
196 
197 #if XERCES_VERSION_MAJOR >= 3
198  // DOM L3 as per Xerces 3.0 API
199  xercesc::DOMLSSerializer* writer =
200  ((xercesc::DOMImplementationLS*)impl)->createLSSerializer();
201 
202  xercesc::DOMConfiguration *dc = writer->getDomConfig();
203  dc->setParameter(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint, true);
204 
205 #else
206 
207  xercesc::DOMWriter* writer =
208  ((xercesc::DOMImplementationLS*)impl)->createDOMWriter();
209 
210  if (writer->canSetFeature(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint, true))
211  writer->setFeature(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint, true);
212 
213 #endif
214 
215  gdml->setAttributeNode(NewAttribute("xmlns:xsi",
216  "http://www.w3.org/2001/XMLSchema-instance"));
217  gdml->setAttributeNode(NewAttribute("xsi:noNamespaceSchemaLocation",
218  SchemaLocation));
219 
220  ExtensionWrite(gdml);
221  DefineWrite(gdml);
222  MaterialsWrite(gdml);
223  SolidsWrite(gdml);
224  StructureWrite(gdml);
225  UserinfoWrite(gdml);
226  SetupWrite(gdml,logvol);
227 
228  G4Transform3D R = TraverseVolumeTree(logvol,depth);
229 
230  SurfacesWrite();
231  xercesc::XMLFormatTarget *myFormTarget =
232  new xercesc::LocalFileFormatTarget(fname.c_str());
233 
234  try
235  {
236 #if XERCES_VERSION_MAJOR >= 3
237  // DOM L3 as per Xerces 3.0 API
238  xercesc::DOMLSOutput *theOutput =
239  ((xercesc::DOMImplementationLS*)impl)->createLSOutput();
240  theOutput->setByteStream(myFormTarget);
241  writer->write(doc, theOutput);
242 #else
243  writer->writeNode(myFormTarget, *doc);
244 #endif
245  }
246  catch (const xercesc::XMLException& toCatch)
247  {
248  char* message = xercesc::XMLString::transcode(toCatch.getMessage());
249  std::cout << "PHG4GDML: Exception message is: " << message << std::endl;
250  xercesc::XMLString::release(&message);
251  return G4Transform3D::Identity;
252  }
253  catch (const xercesc::DOMException& toCatch)
254  {
255  char* message = xercesc::XMLString::transcode(toCatch.msg);
256  std::cout << "PHG4GDML: Exception message is: " << message << std::endl;
257  xercesc::XMLString::release(&message);
258  return G4Transform3D::Identity;
259  }
260  catch (...)
261  {
262  std::cout << "PHG4GDML: Unexpected Exception!" << std::endl;
263  return G4Transform3D::Identity;
264  }
265 
266  delete myFormTarget;
267  writer->release();
268 
269  if (depth==0)
270  {
271  std::cout << "PHG4GDML: Writing '" << fname << "' done !" << std::endl;
272  }
273  else
274  {
275  std::cout << "PHG4GDML: Writing module '" << fname << "' done !" << std::endl;
276  }
277 
278  return R;
279 }
280 
281 void PHG4GDMLWrite::AddModule(const G4VPhysicalVolume* const physvol)
282 {
283  if (physvol == 0)
284  {
285  G4Exception("PHG4GDMLWrite::AddModule()", "InvalidSetup", FatalException,
286  "Invalid NULL pointer is specified for modularization!");
287  return;
288  }
289  G4String fname = GenerateName(physvol->GetName(),physvol);
290  std::cout << "PHG4GDML: Adding module '" << fname << "'..." << std::endl;
291 
292  if (dynamic_cast<const G4PVDivision*>(physvol))
293  {
294  G4Exception("PHG4GDMLWrite::AddModule()", "InvalidSetup", FatalException,
295  "It is not possible to modularize by divisionvol!");
296  return;
297  }
298  if (physvol->IsParameterised())
299  {
300  G4Exception("PHG4GDMLWrite::AddModule()", "InvalidSetup", FatalException,
301  "It is not possible to modularize by parameterised volume!");
302  return;
303  }
304  if (physvol->IsReplicated())
305  {
306  G4Exception("PHG4GDMLWrite::AddModule()", "InvalidSetup", FatalException,
307  "It is not possible to modularize by replicated volume!");
308  return;
309  }
310 
311  PvolumeMap()[physvol] = fname;
312 }
313 
314 void PHG4GDMLWrite::AddModule(const G4int depth)
315 {
316  if (depth<0)
317  {
318  G4Exception("PHG4GDMLWrite::AddModule()", "InvalidSetup", FatalException,
319  "Depth must be a positive number!");
320  }
321  if (DepthMap().find(depth) != DepthMap().end())
322  {
323  G4Exception("PHG4GDMLWrite::AddModule()", "InvalidSetup", FatalException,
324  "Adding module(s) at this depth is already requested!");
325  }
326  DepthMap()[depth] = 0;
327 }
328 
329 G4String PHG4GDMLWrite::Modularize( const G4VPhysicalVolume* const physvol,
330  const G4int depth )
331 {
332  if (PvolumeMap().find(physvol) != PvolumeMap().end())
333  {
334  return PvolumeMap()[physvol]; // Modularize via physvol
335  }
336 
337  if (DepthMap().find(depth) != DepthMap().end()) // Modularize via depth
338  {
339  std::stringstream stream;
340  stream << "depth" << depth << "_module" << DepthMap()[depth] << ".gdml";
341  DepthMap()[depth]++; // There can be more modules at this depth!
342  return G4String(stream.str());
343  }
344 
345  return G4String(""); // Empty string for module name = no modularization
346  // was requested at that level/physvol!
347 }
348 
350 {
351  auxList.push_back(myaux);
352 }
353 
355 {
356  addPointerToName = set;
357 }