Analysis Software
Documentation for sPHENIX simulation 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 #include <Geant4/G4Version.hh>
41 
42 #include <sys/stat.h>
43 #include <iostream>
44 
46 
48  : doc(nullptr)
49  , extElement(nullptr)
50  , userinfoElement(nullptr)
51 {
52 }
53 
55 {
56 }
57 
58 G4bool PHG4GDMLWrite::FileExists(const G4String& fname) const
59 {
60  struct stat FileInfo;
61  return (stat(fname.c_str(), &FileInfo) == 0);
62 }
63 
65 {
66  static VolumeMapType instance;
67  return instance;
68 }
69 
71 {
72  static PhysVolumeMapType instance;
73  return instance;
74 }
75 
77 {
78  static DepthMapType instance;
79  return instance;
80 }
81 
82 void PHG4GDMLWrite::AddExtension(xercesc::DOMElement*,
83  const G4LogicalVolume* const)
84 {
85  // Empty implementation. To be overwritten by user for specific extensions
86  // related to attributes associated to volumes
87 }
88 
89 void PHG4GDMLWrite::ExtensionWrite(xercesc::DOMElement*)
90 {
91  // Empty implementation. To be overwritten by user for specific extensions
92 }
93 
95  xercesc::DOMElement* element)
96 {
97  for (std::vector<PHG4GDMLAuxStructType>::const_iterator
98  iaux = auxInfoList->begin();
99  iaux != auxInfoList->end(); ++iaux)
100  {
101  xercesc::DOMElement* auxiliaryElement = NewElement("auxiliary");
102  element->appendChild(auxiliaryElement);
103 
104  auxiliaryElement->setAttributeNode(NewAttribute("auxtype", (*iaux).type));
105  auxiliaryElement->setAttributeNode(NewAttribute("auxvalue", (*iaux).value));
106  if (((*iaux).unit) != "")
107  {
108  auxiliaryElement->setAttributeNode(NewAttribute("auxunit", (*iaux).unit));
109  }
110 
111  if (iaux->auxList)
112  {
113  AddAuxInfo(iaux->auxList, auxiliaryElement);
114  }
115  }
116  return;
117 }
118 
119 void PHG4GDMLWrite::UserinfoWrite(xercesc::DOMElement* gdmlElement)
120 {
121  if (auxList.size() > 0)
122  {
123  std::cout << "PHG4GDML: Writing userinfo..." << std::endl;
124 
125  userinfoElement = NewElement("userinfo");
126  gdmlElement->appendChild(userinfoElement);
128  }
129 }
130 
131 #if G4VERSION_NUMBER >= 1100
132 G4String PHG4GDMLWrite::GenerateName(const G4String& name, const void* const ptr)
133 {
134  G4String nameOut;
135  std::stringstream stream;
136  stream << name;
137  if (addPointerToName)
138  {
139  stream << ptr;
140  };
141 
142  nameOut = G4String(stream.str());
143  std::vector<char> toremove = {' ', '/', ':', '#', '+'};
144  for (auto c : toremove)
145  {
146  if (G4StrUtil::contains(nameOut, c))
147  {
148  std::replace(nameOut.begin(), nameOut.end(), c, '_');
149  }
150  }
151  return nameOut;
152 }
153 #else
154 G4String PHG4GDMLWrite::GenerateName(const G4String& name, const void* const ptr)
155 {
156  G4String nameOut;
157  std::stringstream stream;
158  stream << name;
159  if (addPointerToName)
160  {
161  stream << ptr;
162  };
163 
164  nameOut = G4String(stream.str());
165  if (nameOut.contains(' '))
166  nameOut.erase(std::remove(nameOut.begin(), nameOut.end(), ' '), nameOut.end());
167 
168  return nameOut;
169 }
170 #endif
171 
172 xercesc::DOMAttr* PHG4GDMLWrite::NewAttribute(const G4String& name,
173  const G4String& value)
174 {
175  xercesc::XMLString::transcode(name, tempStr, 9999);
176  xercesc::DOMAttr* att = doc->createAttribute(tempStr);
177  xercesc::XMLString::transcode(value, tempStr, 9999);
178  att->setValue(tempStr);
179  return att;
180 }
181 
182 xercesc::DOMAttr* PHG4GDMLWrite::NewAttribute(const G4String& name,
183  const G4double& value)
184 {
185  xercesc::XMLString::transcode(name, tempStr, 9999);
186  xercesc::DOMAttr* att = doc->createAttribute(tempStr);
187  std::ostringstream ostream;
188  ostream.precision(15);
189  ostream << value;
190  G4String str = ostream.str();
191  xercesc::XMLString::transcode(str, tempStr, 9999);
192  att->setValue(tempStr);
193  return att;
194 }
195 
196 xercesc::DOMElement* PHG4GDMLWrite::NewElement(const G4String& name)
197 {
198  xercesc::XMLString::transcode(name, tempStr, 9999);
199  return doc->createElement(tempStr);
200 }
201 
202 G4Transform3D PHG4GDMLWrite::Write(const G4String& fname,
203  const G4LogicalVolume* const logvol,
204  const G4String& setSchemaLocation,
205  const G4int depth,
206  G4bool refs)
207 {
208  SchemaLocation = setSchemaLocation;
209  addPointerToName = refs;
210 
211  if (depth == 0)
212  {
213  std::cout << "PHG4GDML: Writing '" << fname << "'..." << std::endl;
214  }
215  else
216  {
217  std::cout << "PHG4GDML: Writing module '" << fname << "'..." << std::endl;
218  }
219 
220  if (FileExists(fname))
221  {
222  G4String ErrorMessage = "File '" + fname + "' already exists!";
223  G4Exception("PHG4GDMLWrite::Write()", "InvalidSetup",
224  FatalException, ErrorMessage);
225  }
226 
227  VolumeMap().clear(); // The module map is global for all modules,
228  // so clear it only at once!
229 
230  xercesc::XMLString::transcode("LS", tempStr, 9999);
231  xercesc::DOMImplementationRegistry::getDOMImplementation(tempStr);
232  xercesc::XMLString::transcode("Range", tempStr, 9999);
233  xercesc::DOMImplementation* impl =
234  xercesc::DOMImplementationRegistry::getDOMImplementation(tempStr);
235  xercesc::XMLString::transcode("gdml", tempStr, 9999);
236  doc = impl->createDocument(0, tempStr, 0);
237  xercesc::DOMElement* gdml = doc->getDocumentElement();
238 
239 #if XERCES_VERSION_MAJOR >= 3
240  // DOM L3 as per Xerces 3.0 API
241  xercesc::DOMLSSerializer* writer =
242  ((xercesc::DOMImplementationLS*) impl)->createLSSerializer();
243 
244  xercesc::DOMConfiguration* dc = writer->getDomConfig();
245  dc->setParameter(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint, true);
246 
247 #else
248 
249  xercesc::DOMWriter* writer =
250  ((xercesc::DOMImplementationLS*) impl)->createDOMWriter();
251 
252  if (writer->canSetFeature(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint, true))
253  writer->setFeature(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint, true);
254 
255 #endif
256 
257  gdml->setAttributeNode(NewAttribute("xmlns:xsi",
258  "http://www.w3.org/2001/XMLSchema-instance"));
259  gdml->setAttributeNode(NewAttribute("xsi:noNamespaceSchemaLocation",
260  SchemaLocation));
261 
262  ExtensionWrite(gdml);
263  DefineWrite(gdml);
264  MaterialsWrite(gdml);
265  SolidsWrite(gdml);
266  StructureWrite(gdml);
267  UserinfoWrite(gdml);
268  SetupWrite(gdml, logvol);
269 
270  G4Transform3D R = TraverseVolumeTree(logvol, depth);
271 
272  SurfacesWrite();
273  xercesc::XMLFormatTarget* myFormTarget =
274  new xercesc::LocalFileFormatTarget(fname.c_str());
275 
276  try
277  {
278 #if XERCES_VERSION_MAJOR >= 3
279  // DOM L3 as per Xerces 3.0 API
280  xercesc::DOMLSOutput* theOutput =
281  ((xercesc::DOMImplementationLS*) impl)->createLSOutput();
282  theOutput->setByteStream(myFormTarget);
283  writer->write(doc, theOutput);
284 #else
285  writer->writeNode(myFormTarget, *doc);
286 #endif
287  }
288  catch (const xercesc::XMLException& toCatch)
289  {
290  char* message = xercesc::XMLString::transcode(toCatch.getMessage());
291  std::cout << "PHG4GDML: Exception message is: " << message << std::endl;
292  xercesc::XMLString::release(&message);
293  return G4Transform3D::Identity;
294  }
295  catch (const xercesc::DOMException& toCatch)
296  {
297  char* message = xercesc::XMLString::transcode(toCatch.msg);
298  std::cout << "PHG4GDML: Exception message is: " << message << std::endl;
299  xercesc::XMLString::release(&message);
300  return G4Transform3D::Identity;
301  }
302  catch (...)
303  {
304  std::cout << "PHG4GDML: Unexpected Exception!" << std::endl;
305  return G4Transform3D::Identity;
306  }
307 
308  delete myFormTarget;
309  writer->release();
310 
311  if (depth == 0)
312  {
313  std::cout << "PHG4GDML: Writing '" << fname << "' done !" << std::endl;
314  }
315  else
316  {
317  std::cout << "PHG4GDML: Writing module '" << fname << "' done !" << std::endl;
318  }
319 
320  return R;
321 }
322 
323 void PHG4GDMLWrite::AddModule(const G4VPhysicalVolume* const physvol)
324 {
325  if (physvol == 0)
326  {
327  G4Exception("PHG4GDMLWrite::AddModule()", "InvalidSetup", FatalException,
328  "Invalid NULL pointer is specified for modularization!");
329  return;
330  }
331  G4String fname = GenerateName(physvol->GetName(), physvol);
332  std::cout << "PHG4GDML: Adding module '" << fname << "'..." << std::endl;
333 
334  if (dynamic_cast<const G4PVDivision*>(physvol))
335  {
336  G4Exception("PHG4GDMLWrite::AddModule()", "InvalidSetup", FatalException,
337  "It is not possible to modularize by divisionvol!");
338  return;
339  }
340  if (physvol->IsParameterised())
341  {
342  G4Exception("PHG4GDMLWrite::AddModule()", "InvalidSetup", FatalException,
343  "It is not possible to modularize by parameterised volume!");
344  return;
345  }
346  if (physvol->IsReplicated())
347  {
348  G4Exception("PHG4GDMLWrite::AddModule()", "InvalidSetup", FatalException,
349  "It is not possible to modularize by replicated volume!");
350  return;
351  }
352 
353  PvolumeMap()[physvol] = fname;
354 }
355 
357 {
358  if (depth < 0)
359  {
360  G4Exception("PHG4GDMLWrite::AddModule()", "InvalidSetup", FatalException,
361  "Depth must be a positive number!");
362  }
363  if (DepthMap().find(depth) != DepthMap().end())
364  {
365  G4Exception("PHG4GDMLWrite::AddModule()", "InvalidSetup", FatalException,
366  "Adding module(s) at this depth is already requested!");
367  }
368  DepthMap()[depth] = 0;
369 }
370 
371 G4String PHG4GDMLWrite::Modularize(const G4VPhysicalVolume* const physvol,
372  const G4int depth)
373 {
374  if (PvolumeMap().find(physvol) != PvolumeMap().end())
375  {
376  return PvolumeMap()[physvol]; // Modularize via physvol
377  }
378 
379  if (DepthMap().find(depth) != DepthMap().end()) // Modularize via depth
380  {
381  std::stringstream stream;
382  stream << "depth" << depth << "_module" << DepthMap()[depth] << ".gdml";
383  DepthMap()[depth]++; // There can be more modules at this depth!
384  return G4String(stream.str());
385  }
386 
387  return G4String(""); // Empty string for module name = no modularization
388  // was requested at that level/physvol!
389 }
390 
392 {
393  auxList.push_back(myaux);
394 }
395 
397 {
398  addPointerToName = set;
399 }