ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4ASCIITreeSceneHandler.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4ASCIITreeSceneHandler.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 //
29 // John Allison 5th April 2001
30 // A scene handler to dump geometry hierarchy.
31 // Based on a provisional G4ASCIITreeGraphicsScene (was in modeling).
32 
34 
35 #include "G4ASCIITree.hh"
36 #include "G4ASCIITreeMessenger.hh"
37 #include "G4VSolid.hh"
38 #include "G4PhysicalVolumeModel.hh"
39 #include "G4VPhysicalVolume.hh"
40 #include "G4LogicalVolume.hh"
41 #include "G4VPVParameterisation.hh"
42 #include "G4Polyhedron.hh"
43 #include "G4UnitsTable.hh"
44 #include "G4Material.hh"
45 #include "G4Scene.hh"
46 #include "G4ModelingParameters.hh"
48 #include "G4VSensitiveDetector.hh"
49 #include "G4VReadOutGeometry.hh"
51 #include "G4AttCheck.hh"
52 #include "G4AttValue.hh"
53 
56  const G4String& name):
57  G4VTreeSceneHandler(system, name),
58  fpOutFile(0),
59  fpLastPV(0),
60  fLastCopyNo(-99),
61  fLastNonSequentialCopyNo(-99)
62 {}
63 
65 
67 
68  G4VTreeSceneHandler::BeginModeling (); // To re-use "culling off" code.
69 
70  const G4ASCIITree* pSystem = (G4ASCIITree*)GetGraphicsSystem();
71  const G4String& outFileName = pSystem -> GetOutFileName();
72  if (outFileName == "G4cout") {
73  fpOutFile = &G4cout;
74  } else {
75  fOutFile.open (outFileName);
77  }
78 
79  static G4bool firstTime = true;
80  if (firstTime) {
81  firstTime = false;
82  G4cout << "G4ASCIITreeSceneHandler::BeginModeling: writing to ";
83  if (outFileName == "G4cout") {
84  G4cout << "G4 standard output (G4cout)";
85  } else {
86  G4cout << "file \"" << outFileName << "\"";
87  }
88  G4cout << G4endl;
89 
91  }
92 
93  if (outFileName != "G4cout") {
94  WriteHeader (fOutFile); fOutFile << std::endl;
95  }
96 }
97 
98 void G4ASCIITreeSceneHandler::WriteHeader (std::ostream& os)
99 {
100  const G4ASCIITree* pSystem = (G4ASCIITree*)GetGraphicsSystem();
101  const G4int verbosity = pSystem->GetVerbosity();
102  const G4int detail = verbosity % 10;
103  os << "# Set verbosity with \"/vis/ASCIITree/verbose <verbosity>\":";
104  for (size_t i = 0;
106  os << "\n# " << G4ASCIITreeMessenger::fVerbosityGuidance[i];
107  }
108  os << "\n# Now printing with verbosity " << verbosity;
109  os << "\n# Format is: PV:n";
110  if (detail >= 1) os << " / LV (SD,RO)";
111  if (detail >= 2) os << " / Solid(type)";
112  if (detail >= 3) os << ", volume, density";
113  if (detail >= 5) os << ", daughter-subtracted volume and mass";
114  if (detail >= 6) os << ", physical volume dump";
115  if (detail >= 7) os << ", polyhedron dump";
116  os <<
117  "\n# Abbreviations: PV = Physical Volume, LV = Logical Volume,"
118  "\n# SD = Sensitive Detector, RO = Read Out Geometry.";
119 }
120 
122  const G4ASCIITree* pSystem = (G4ASCIITree*) GetGraphicsSystem();
123  const G4int verbosity = pSystem->GetVerbosity();
124  const G4int detail = verbosity % 10;
125  const G4String& outFileName = pSystem -> GetOutFileName();
126 
127  // Output left over copy number, if any...
129  if (fLastCopyNo == fLastNonSequentialCopyNo + 1) *fpOutFile << ',';
130  else *fpOutFile << '-';
132  }
133  // Output outstanding rest of line, if any...
134  if (!fRestOfLine.str().empty()) *fpOutFile << fRestOfLine.str();
135  fRestOfLine.str("");
136  fpLastPV = 0;
137  fLastPVName.clear();
138  fLastCopyNo = -99;
140 
141  // This detail to G4cout regardless of outFileName...
142  if (detail >= 4) {
143  G4cout << "Calculating mass(es)..." << G4endl;
144  const std::vector<G4Scene::Model>& models = fpScene->GetRunDurationModelList();
145  std::vector<G4Scene::Model>::const_iterator i;
146  for (i = models.begin(); i != models.end(); ++i) {
147  G4PhysicalVolumeModel* pvModel =
148  dynamic_cast<G4PhysicalVolumeModel*>(i->fpModel);
149  if (pvModel) {
150  const G4ModelingParameters* tempMP =
151  pvModel->GetModelingParameters();
152  G4ModelingParameters mp; // Default - no culling.
153  pvModel->SetModelingParameters (&mp);
154  G4PhysicalVolumeMassScene massScene(pvModel);
155  pvModel->DescribeYourselfTo (massScene);
156  G4double volume = massScene.GetVolume();
157  G4double mass = massScene.GetMass();
158 
159  G4cout << "Overall volume of \""
160  << pvModel->GetTopPhysicalVolume()->GetName()
161  << "\":"
162  << pvModel->GetTopPhysicalVolume()->GetCopyNo()
163  << ", is "
164  << G4BestUnit (volume, "Volume")
165  << " and the daughter-included mass";
166  G4int requestedDepth = pvModel->GetRequestedDepth();
167  if (requestedDepth == G4PhysicalVolumeModel::UNLIMITED) {
168  G4cout << " to unlimited depth";
169  } else {
170  G4cout << ", ignoring daughters at depth "
171  << requestedDepth
172  << " and below,";
173  }
174  G4cout << " is " << G4BestUnit (mass, "Mass")
175  << G4endl;
176 
177  pvModel->SetModelingParameters (tempMP);
178  }
179  }
180  }
181 
182  if (outFileName != "G4cout") {
183  fOutFile.close();
184  G4cout << "Output file \"" << outFileName << "\" closed." << G4endl;
185  }
186  fLVSet.clear();
187  fReplicaSet.clear();
188  G4cout << "G4ASCIITreeSceneHandler::EndModeling" << G4endl;
189  G4VTreeSceneHandler::EndModeling (); // To re-use "culling off" code.
190 }
191 
193 
194  G4PhysicalVolumeModel* pPVModel =
195  dynamic_cast<G4PhysicalVolumeModel*>(fpModel);
196  if (!pPVModel) return; // Not from a G4PhysicalVolumeModel.
197 
198  // This call comes from a G4PhysicalVolumeModel. drawnPVPath is
199  // the path of the current drawn (non-culled) volume in terms of
200  // drawn (non-culled) ancestors. Each node is identified by a
201  // PVNodeID object, which is a physical volume and copy number. It
202  // is a vector of PVNodeIDs corresponding to the geometry hierarchy
203  // actually selected, i.e., not culled.
204  // The following typedef's already set in header file...
205  //typedef G4PhysicalVolumeModel::G4PhysicalVolumeNodeID PVNodeID;
206  //typedef std::vector<PVNodeID> PVPath;
207  const PVPath& drawnPVPath = pPVModel->GetDrawnPVPath();
208  //G4int currentDepth = pPVModel->GetCurrentDepth();
209  G4VPhysicalVolume* pCurrentPV = pPVModel->GetCurrentPV();
210  const G4String& currentPVName = pCurrentPV->GetName();
211  const G4int currentCopyNo = pCurrentPV->GetCopyNo();
212  G4LogicalVolume* pCurrentLV = pPVModel->GetCurrentLV();
213  G4Material* pCurrentMaterial = pPVModel->GetCurrentMaterial();
214 
216  G4int verbosity = pSystem->GetVerbosity();
217  G4int detail = verbosity % 10;
218 
219  // If verbosity < 10 suppress unnecessary repeated printing.
220  // Repeated simple replicas can always be suppressed.
221  // Paramaterisations can only be suppressed if verbosity < 3, since their
222  // size, density, etc., are in principle different.
223  const G4bool isParameterised = pCurrentPV->GetParameterisation();
224  const G4bool isSimpleReplica = pCurrentPV->IsReplicated() && !isParameterised;
225  const G4bool isAmenableToSupression =
226  (verbosity < 10 && isSimpleReplica) || (verbosity < 3 && isParameterised);
227  if (isAmenableToSupression) {
228  // See if this has been found before with same mother LV...
229  PVPath::const_reverse_iterator thisID = drawnPVPath.rbegin();
230  PVPath::const_reverse_iterator motherID = ++drawnPVPath.rbegin();
231  G4bool ignore = false;
232  for (ReplicaSetIterator i = fReplicaSet.begin(); i != fReplicaSet.end();
233  ++i) {
234  if (i->back().GetPhysicalVolume()->GetLogicalVolume() ==
235  thisID->GetPhysicalVolume()->GetLogicalVolume()) {
236  // For each one previously found (if more than one, they must
237  // have different mothers)...
238  // To avoid compilation errors on VC++ .Net 7.1...
239  // Previously:
240  // PVNodeID previousMotherID = ++(i->rbegin());
241  // (Should that have been: PVNodeID::const_iterator previousMotherID?)
242  // Replace
243  // previousMotherID == i->rend()
244  // by
245  // i->size() <= 1
246  // Replace
247  // previousMotherID != i->rend()
248  // by
249  // i->size() > 1
250  // Replace
251  // previousMotherID->
252  // by
253  // (*i)[i->size() - 2].
254  if (motherID == drawnPVPath.rend() &&
255  i->size() <= 1)
256  ignore = true; // Both have no mother.
257  if (motherID != drawnPVPath.rend() &&
258  i->size() > 1 &&
259  motherID->GetPhysicalVolume()->GetLogicalVolume() ==
260  (*i)[i->size() - 2].GetPhysicalVolume()->GetLogicalVolume())
261  ignore = true; // Same mother LV...
262  }
263  }
264  if (ignore) {
265  pPVModel->CurtailDescent();
266  return;
267  }
268  }
269 
270  // Now suppress printing for volumes with the same name but different
271  // copy number - but not if they are parameterisations that have not been
272  // taken out above (those that are "amenable to suppression" will have been
273  // taken out).
274  if (verbosity < 10 && !isParameterised &&
275  currentPVName == fLastPVName &&
276  currentCopyNo != fLastCopyNo) {
277  // Check...
278  if (isAmenableToSupression) {
279  G4Exception("G4ASCIITreeSceneHandler::RequestPrimitives",
280  "vistree0001",
281  JustWarning,
282  "Volume amenable to suppressed printing unexpected");
283  }
284  // Check mothers are identical...
285  else if (pCurrentLV == (fpLastPV? fpLastPV->GetLogicalVolume(): 0)) {
286  if (currentCopyNo != fLastCopyNo + 1) {
287  // Non-sequential copy number...
288  *fpOutFile << ',' << currentCopyNo;
289  fLastNonSequentialCopyNo = currentCopyNo;
290  }
291  fLastCopyNo = currentCopyNo;
292  pPVModel->CurtailDescent();
293  return;
294  }
295  }
296  fpLastPV = pCurrentPV;
297 
298  // High verbosity or a new or otherwise non-amenable volume...
299  // Output copy number, if any, from previous invocation...
301  if (fLastCopyNo == fLastNonSequentialCopyNo + 1) *fpOutFile << ',';
302  else *fpOutFile << '-';
304  }
305  // Output rest of line, if any, from previous invocation...
306  if (!fRestOfLine.str().empty()) *fpOutFile << fRestOfLine.str();
307  fRestOfLine.str("");
308  fLastPVName = currentPVName;
309  fLastCopyNo = currentCopyNo;
310  fLastNonSequentialCopyNo = currentCopyNo;
311  // Start next line...
312  // Indent according to drawn path depth...
313  for (size_t i = 0; i < drawnPVPath.size(); i++ ) *fpOutFile << " ";
314  *fpOutFile << "\"" << currentPVName
315  << "\":" << currentCopyNo;
316 
317  if (pCurrentPV->IsReplicated()) {
318  if (verbosity < 10) {
319  // Add printing for replicas (when replicas are ignored)...
320  EAxis axis;
321  G4int nReplicas;
322  G4double width;
324  G4bool consuming;
325  pCurrentPV->GetReplicationData(axis,nReplicas,width,offset,consuming);
326  G4VPVParameterisation* pP = pCurrentPV->GetParameterisation();
327  if (pP) {
328  if (detail < 3) {
329  fReplicaSet.insert(drawnPVPath);
330  if (nReplicas > 2) fRestOfLine << '-';
331  else fRestOfLine << ',';
332  fRestOfLine << nReplicas - 1
333  << " (" << nReplicas << " parametrised volumes)";
334  }
335  }
336  else {
337  fReplicaSet.insert(drawnPVPath);
338  if (nReplicas > 2) fRestOfLine << '-';
339  else fRestOfLine << ',';
340  fRestOfLine << nReplicas - 1
341  << " (" << nReplicas << " replicas)";
342  }
343  }
344  } else {
345  if (fLVSet.find(pCurrentLV) != fLVSet.end()) {
346  if (verbosity < 10) {
347  // Add printing for repeated LV (if it has daughters)...
348  if (pCurrentLV->GetNoDaughters()) fRestOfLine << " (repeated LV)";
349  // ...and curtail descent.
350  pPVModel->CurtailDescent();
351  }
352  }
353  }
354 
355  if (detail >= 1) {
356  fRestOfLine << " / \""
357  << pCurrentLV->GetName() << "\"";
358  G4VSensitiveDetector* sd = pCurrentLV->GetSensitiveDetector();
359  if (sd) {
360  fRestOfLine << " (SD=\"" << sd->GetName() << "\"";
361  G4VReadOutGeometry* roGeom = sd->GetROgeometry();
362  if (roGeom) {
363  fRestOfLine << ",RO=\"" << roGeom->GetName() << "\"";
364  }
365  fRestOfLine << ")";
366  }
367  }
368 
369  if (detail >= 2) {
370  fRestOfLine << " / \""
371  << solid.GetName()
372  << "\"("
373  << solid.GetEntityType() << ")";
374  }
375 
376  if (detail >= 3) {
377  fRestOfLine << ", "
378  << G4BestUnit(((G4VSolid&)solid).GetCubicVolume(),"Volume")
379  << ", ";
380  if (pCurrentMaterial) {
382  << G4BestUnit(pCurrentMaterial->GetDensity(), "Volumic Mass")
383  << " (" << pCurrentMaterial->GetName() << ")";
384  } else {
385  fRestOfLine << "(No material)";
386  }
387  }
388 
389  if (detail >= 5) {
390  if (pCurrentMaterial) {
391  G4Material* pMaterial = const_cast<G4Material*>(pCurrentMaterial);
392  // ...and find daughter-subtracted mass...
393  G4double daughter_subtracted_mass = pCurrentLV->GetMass
394  (pCurrentPV->IsParameterised(), // Force if parametrised.
395  false, // Do not propagate - calculate for this volume minus
396  // volume of daughters.
397  pMaterial);
398  G4double daughter_subtracted_volume =
399  daughter_subtracted_mass / pCurrentMaterial->GetDensity();
400  fRestOfLine << ", "
401  << G4BestUnit(daughter_subtracted_volume,"Volume")
402  << ", "
403  << G4BestUnit(daughter_subtracted_mass,"Mass");
404  }
405  }
406 
407  if (detail >= 6) {
408  std::vector<G4AttValue>* attValues = pPVModel->CreateCurrentAttValues();
409  const std::map<G4String,G4AttDef>* attDefs = pPVModel->GetAttDefs();
410  fRestOfLine << '\n' << G4AttCheck(attValues, attDefs);
411  delete attValues;
412  }
413 
414  if (detail >= 7) {
415  G4Polyhedron* polyhedron = solid.GetPolyhedron();
416  fRestOfLine << "\nLocal polyhedron coordinates:\n" << *polyhedron;
418  polyhedron->Transform(*transform);
419  fRestOfLine << "\nGlobal polyhedron coordinates:\n" << *polyhedron;
420  }
421 
422  if (fLVSet.find(pCurrentLV) == fLVSet.end()) {
423  fLVSet.insert(pCurrentLV); // Record new logical volume.
424  }
425 
426  fRestOfLine << std::endl;
427 
428  return;
429 }