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