DD4hep  1.30.0
Detector Description Toolkit for High Energy Physics
Geant4Converter.cpp
Go to the documentation of this file.
1 //==========================================================================
2 // AIDA Detector description implementation
3 //--------------------------------------------------------------------------
4 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
5 // All rights reserved.
6 //
7 // For the licensing terms see $DD4hepINSTALL/LICENSE.
8 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
9 //
10 // Author : M.Frank
11 //
12 //==========================================================================
13 
14 // Framework include files
15 #include <DD4hep/Shapes.h>
16 #include <DD4hep/Volumes.h>
17 #include <DD4hep/Plugins.h>
18 #include <DD4hep/Printout.h>
19 #include <DD4hep/Detector.h>
20 #include <DD4hep/DD4hepUnits.h>
21 #include <DD4hep/PropertyTable.h>
22 #include <DD4hep/DetectorTools.h>
26 
27 #include <DDG4/Geant4Field.h>
28 #include <DDG4/Geant4Helpers.h>
29 #include <DDG4/Geant4Converter.h>
30 #include <DDG4/Geant4UserLimits.h>
33 #include "Geant4ShapeConverter.h"
34 
35 // ROOT includes
36 #include <TClass.h>
37 #include <TTimeStamp.h>
38 #include <TGeoBoolNode.h>
39 
40 // Geant4 include files
41 #include <G4Version.hh>
42 #include <G4VisAttributes.hh>
43 #include <G4PVParameterised.hh>
44 #include <G4ProductionCuts.hh>
45 #include <G4VUserRegionInformation.hh>
46 
47 #include <G4Box.hh>
48 #include <G4Tubs.hh>
49 #include <G4Ellipsoid.hh>
50 #include <G4UnionSolid.hh>
51 #include <G4ReflectedSolid.hh>
52 #include <G4SubtractionSolid.hh>
53 #include <G4IntersectionSolid.hh>
54 #include <G4VSensitiveDetector.hh>
55 
56 #include <G4Region.hh>
57 #include <G4Element.hh>
58 #include <G4Isotope.hh>
59 #include <G4Material.hh>
60 #include <G4UserLimits.hh>
61 #include <G4RegionStore.hh>
62 #include <G4FieldManager.hh>
63 #include <G4LogicalVolume.hh>
64 #include <G4OpticalSurface.hh>
65 #include <G4ReflectionFactory.hh>
66 #include <G4LogicalSkinSurface.hh>
67 #include <G4ElectroMagneticField.hh>
68 #include <G4LogicalBorderSurface.hh>
69 #include <G4MaterialPropertiesTable.hh>
70 #if G4VERSION_NUMBER >= 1040
71 #include <G4MaterialPropertiesIndex.hh>
72 #endif
73 #include <G4ScaledSolid.hh>
74 #include <CLHEP/Units/SystemOfUnits.h>
75 
76 // C/C++ include files
77 #include <iostream>
78 #include <iomanip>
79 #include <sstream>
80 #include <limits>
81 
82 namespace units = dd4hep;
83 using namespace dd4hep::sim;
84 using namespace dd4hep;
85 
86 namespace {
87 
88  static constexpr const double CM_2_MM = (CLHEP::centimeter/dd4hep::centimeter);
89  static constexpr const char* GEANT4_TAG_IGNORE = "Geant4-ignore";
90  static constexpr const char* GEANT4_TAG_PLUGIN = "Geant4-plugin";
91  static constexpr const char* GEANT4_TAG_BIRKSCONSTANT = "BirksConstant";
92  static constexpr const char* GEANT4_TAG_MEE = "MeanExcitationEnergy";
93  static constexpr const char* GEANT4_TAG_ENE_PER_ION_PAIR = "MeanEnergyPerIonPair";
94 
95  static std::string indent = "";
96 
97  template <typename O, typename C, typename F> void handleRefs(const O* o, const C& c, F pmf) {
98  for (typename C::const_iterator i = c.begin(); i != c.end(); ++i) {
99  //(o->*pmf)((*i)->GetName(), *i);
100  (o->*pmf)("", *i);
101  }
102  }
103 
104  template <typename O, typename C, typename F> void handle(const O* o, const C& c, F pmf) {
105  for (typename C::const_iterator i = c.begin(); i != c.end(); ++i) {
106  (o->*pmf)((*i)->GetName(), *i);
107  }
108  }
109 
110  template <typename O, typename F> void handleArray(const O* o, const TObjArray* c, F pmf) {
111  TObjArrayIter arr(c);
112  for(TObject* i = arr.Next(); i; i=arr.Next())
113  (o->*pmf)(i);
114  }
115 
116  template <typename O, typename C, typename F> void handleMap(const O* o, const C& c, F pmf) {
117  for (typename C::const_iterator i = c.begin(); i != c.end(); ++i)
118  (o->*pmf)((*i).first, (*i).second);
119  }
120 
121  template <typename O, typename C, typename F> void handleRMap(const O* o, const C& c, F pmf) {
122  for (typename C::const_reverse_iterator i = c.rbegin(); i != c.rend(); ++i) {
123  //cout << "Handle RMAP [ " << (*i).first << " ]" << std::endl;
124  handle(o, i->second, pmf);
125  }
126  }
127  template <typename O, typename C, typename F> void handleRMap_(const O* o, const C& c, F pmf) {
128  for (typename C::const_iterator i = c.begin(); i != c.end(); ++i) {
129  const auto& cc = (*i).second;
130  for (const auto& j : cc) {
131  (o->*pmf)(j);
132  }
133  }
134  }
135 
136  std::string make_NCName(const std::string& in) {
137  std::string res = detail::str_replace(in, "/", "_");
138  res = detail::str_replace(res, "#", "_");
139  return res;
140  }
141 
142  bool is_left_handed(const TGeoMatrix* m) {
143  const Double_t* r = m->GetRotationMatrix();
144  if ( r ) {
145  Double_t det =
146  r[0]*r[4]*r[8] + r[3]*r[7]*r[2] + r[6]*r[1]*r[5] -
147  r[2]*r[4]*r[6] - r[5]*r[7]*r[0] - r[8]*r[1]*r[3];
148  return det < 0e0;
149  }
150  return false;
151  }
152 
153  class G4UserRegionInformation : public G4VUserRegionInformation {
154  public:
155  Region region;
156  double threshold;
157  bool storeSecondaries;
158  G4UserRegionInformation()
159  : threshold(0.0), storeSecondaries(false) {
160  }
161  virtual ~G4UserRegionInformation() {
162  }
163  virtual void Print() const {
164  if (region.isValid())
165  printout(DEBUG, "Region", "Name:%s", region.name());
166  }
167  };
168 
169  std::pair<double,double> g4PropertyConversion(int index) {
170 #if G4VERSION_NUMBER >= 1040
171  switch(index) {
172  case kRINDEX: return std::make_pair(CLHEP::keV/units::keV, 1.0);
173  case kREFLECTIVITY: return std::make_pair(CLHEP::keV/units::keV, 1.0);
174  case kREALRINDEX: return std::make_pair(CLHEP::keV/units::keV, 1.0);
175  case kIMAGINARYRINDEX: return std::make_pair(CLHEP::keV/units::keV, 1.0);
176  case kEFFICIENCY: return std::make_pair(CLHEP::keV/units::keV, 1.0);
177  case kTRANSMITTANCE: return std::make_pair(CLHEP::keV/units::keV, 1.0);
178  case kSPECULARLOBECONSTANT: return std::make_pair(CLHEP::keV/units::keV, 1.0);
179  case kSPECULARSPIKECONSTANT: return std::make_pair(CLHEP::keV/units::keV, 1.0);
180  case kBACKSCATTERCONSTANT: return std::make_pair(CLHEP::keV/units::keV, 1.0);
181  case kGROUPVEL: return std::make_pair(CLHEP::keV/units::keV, (CLHEP::m/CLHEP::s)/(units::m/units::s)); // meter/second
182  case kMIEHG: return std::make_pair(CLHEP::keV/units::keV, CLHEP::m/units::m);
183  case kRAYLEIGH: return std::make_pair(CLHEP::keV/units::keV, CLHEP::m/units::m); // ??? says its a length
184  case kWLSCOMPONENT: return std::make_pair(CLHEP::keV/units::keV, 1.0);
185  case kWLSABSLENGTH: return std::make_pair(CLHEP::keV/units::keV, CLHEP::m/units::m);
186  case kABSLENGTH: return std::make_pair(CLHEP::keV/units::keV, CLHEP::m/units::m);
187 #if G4VERSION_NUMBER >= 1100
188  case kWLSCOMPONENT2: return std::make_pair(CLHEP::keV/units::keV, 1.0);
189  case kWLSABSLENGTH2: return std::make_pair(CLHEP::keV/units::keV, CLHEP::m/units::m);
190  case kSCINTILLATIONCOMPONENT1: return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
191  case kSCINTILLATIONCOMPONENT2: return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
192  case kSCINTILLATIONCOMPONENT3: return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
193 #else
194  case kFASTCOMPONENT: return std::make_pair(CLHEP::keV/units::keV, 1.0);
195  case kSLOWCOMPONENT: return std::make_pair(CLHEP::keV/units::keV, 1.0);
196 #endif
197  case kPROTONSCINTILLATIONYIELD: return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV); // Yields: 1/energy
198  case kDEUTERONSCINTILLATIONYIELD: return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
199  case kTRITONSCINTILLATIONYIELD: return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
200  case kALPHASCINTILLATIONYIELD: return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
201  case kIONSCINTILLATIONYIELD: return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
202  case kELECTRONSCINTILLATIONYIELD: return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
203  default:
204  break;
205  }
206  printout(FATAL,"Geant4Converter", "+++ Cannot convert material property with index: %d", index);
207 #else
208  printout(FATAL,"Geant4Converter", "+++ Cannot convert material property with index: %d [Need Geant4 > 10.03]", index);
209 #endif
210  return std::make_pair(0e0,0e0);
211  }
212 
213  double g4ConstPropertyConversion(int index) {
214 #if G4VERSION_NUMBER >= 1040
215  switch(index) {
216  case kSURFACEROUGHNESS: return CLHEP::m/units::m; // Length
217  case kISOTHERMAL_COMPRESSIBILITY: return (CLHEP::m3/CLHEP::keV)/(units::m3/CLHEP::keV); // Volume/Energy
218  case kRS_SCALE_FACTOR: return 1.0; // ??
219  case kWLSMEANNUMBERPHOTONS: return 1.0; // ??
220  case kWLSTIMECONSTANT: return CLHEP::second/units::second; // Time
221  case kMIEHG_FORWARD: return 1.0;
222  case kMIEHG_BACKWARD: return 1.0;
223  case kMIEHG_FORWARD_RATIO: return 1.0;
224  case kSCINTILLATIONYIELD: return units::keV/CLHEP::keV; // Energy
225  case kRESOLUTIONSCALE: return 1.0;
226  case kFERMIPOT: return CLHEP::keV/units::keV; // Energy
227  case kDIFFUSION: return 1.0;
228  case kSPINFLIP: return 1.0;
229  case kLOSS: return 1.0; // ??
230  case kLOSSCS: return CLHEP::barn/units::barn; // ??
231  case kABSCS: return CLHEP::barn/units::barn; // ??
232  case kSCATCS: return CLHEP::barn/units::barn; // ??
233  case kMR_NBTHETA: return 1.0;
234  case kMR_NBE: return 1.0;
235  case kMR_RRMS: return 1.0; // ??
236  case kMR_CORRLEN: return CLHEP::m/units::m; // Length
237  case kMR_THETAMIN: return 1.0;
238  case kMR_THETAMAX: return 1.0;
239  case kMR_EMIN: return CLHEP::keV/units::keV; // Energy
240  case kMR_EMAX: return CLHEP::keV/units::keV; // Energy
241  case kMR_ANGNOTHETA: return 1.0;
242  case kMR_ANGNOPHI: return 1.0;
243  case kMR_ANGCUT: return 1.0;
244 
245 #if G4VERSION_NUMBER >= 1100
246  case kSCINTILLATIONTIMECONSTANT1: return CLHEP::second/units::second; // Time
247  case kSCINTILLATIONTIMECONSTANT2: return CLHEP::second/units::second; // Time
248  case kSCINTILLATIONTIMECONSTANT3: return CLHEP::second/units::second; // Time
249  case kSCINTILLATIONRISETIME1: return CLHEP::second/units::second; // Time
250  case kSCINTILLATIONRISETIME2: return CLHEP::second/units::second; // Time
251  case kSCINTILLATIONRISETIME3: return CLHEP::second/units::second; // Time
252  case kSCINTILLATIONYIELD1: return 1.0;
253  case kSCINTILLATIONYIELD2: return 1.0;
254  case kSCINTILLATIONYIELD3: return 1.0;
255  case kPROTONSCINTILLATIONYIELD1: return 1.0;
256  case kPROTONSCINTILLATIONYIELD2: return 1.0;
257  case kPROTONSCINTILLATIONYIELD3: return 1.0;
258  case kDEUTERONSCINTILLATIONYIELD1: return 1.0;
259  case kDEUTERONSCINTILLATIONYIELD2: return 1.0;
260  case kDEUTERONSCINTILLATIONYIELD3: return 1.0;
261  case kALPHASCINTILLATIONYIELD1: return 1.0;
262  case kALPHASCINTILLATIONYIELD2: return 1.0;
263  case kALPHASCINTILLATIONYIELD3: return 1.0;
264  case kIONSCINTILLATIONYIELD1: return 1.0;
265  case kIONSCINTILLATIONYIELD2: return 1.0;
266  case kIONSCINTILLATIONYIELD3: return 1.0;
267  case kELECTRONSCINTILLATIONYIELD1: return 1.0;
268  case kELECTRONSCINTILLATIONYIELD2: return 1.0;
269  case kELECTRONSCINTILLATIONYIELD3: return 1.0;
270 #else
271  case kFASTTIMECONSTANT: return CLHEP::second/units::second; // Time
272  case kFASTSCINTILLATIONRISETIME: return CLHEP::second/units::second; // Time
273  case kSLOWTIMECONSTANT: return CLHEP::second/units::second; // Time
274  case kSLOWSCINTILLATIONRISETIME: return CLHEP::second/units::second; // Time
275  case kYIELDRATIO: return 1.0;
276 #endif
277  default:
278  break;
279  }
280  printout(FATAL,"Geant4Converter", "+++ Cannot convert CONST material property with index: %d", index);
281 #else
282  printout(FATAL,"Geant4Converter", "+++ Cannot convert material property with index: %d [Need Geant4 > 10.03]", index);
283 #endif
284  return 0.0;
285  }
286 }
287 
290  : Geant4Mapping(description_ref), checkOverlaps(true) {
291  this->Geant4Mapping::init();
292  m_propagateRegions = true;
293  outputLevel = PrintLevel(printLevel() - 1);
294 }
295 
297 Geant4Converter::Geant4Converter(const Detector& description_ref, PrintLevel level)
298  : Geant4Mapping(description_ref), outputLevel(level) {
299  this->Geant4Mapping::init();
300  m_propagateRegions = true;
301 }
302 
305 }
306 
308 void* Geant4Converter::handleIsotope(const std::string& /* name */, const TGeoIsotope* iso) const {
309  G4Isotope* g4i = data().g4Isotopes[iso];
310  if ( !g4i ) {
311  double a_conv = (CLHEP::g / CLHEP::mole);
312  g4i = new G4Isotope(iso->GetName(), iso->GetZ(), iso->GetN(), iso->GetA()*a_conv);
313  printout(debugElements ? ALWAYS : outputLevel,
314  "Geant4Converter", "++ Created G4 Isotope %s from data: Z=%d N=%d A=%.3f [g/mole]",
315  iso->GetName(), iso->GetZ(), iso->GetN(), iso->GetA());
316  data().g4Isotopes[iso] = g4i;
317  }
318  return g4i;
319 }
320 
322 void* Geant4Converter::handleElement(const std::string& name, const Atom element) const {
323  G4Element* g4e = data().g4Elements[element];
324  if ( !g4e ) {
325  PrintLevel lvl = debugElements ? ALWAYS : outputLevel;
326  if (element->GetNisotopes() > 0) {
327  g4e = new G4Element(name, element->GetTitle(), element->GetNisotopes());
328  for (int i = 0, n = element->GetNisotopes(); i < n; ++i) {
329  TGeoIsotope* iso = element->GetIsotope(i);
330  G4Isotope* g4iso = (G4Isotope*)handleIsotope(iso->GetName(), iso);
331  g4e->AddIsotope(g4iso, element->GetRelativeAbundance(i));
332  }
333  }
334  else {
335  // This adds in Geant4 the natural isotopes, which we normally do not want. We want to steer it outselves.
336  double a_conv = (CLHEP::g / CLHEP::mole);
337  g4e = new G4Element(element->GetTitle(), name, element->Z(), element->A()*a_conv);
338  printout(lvl, "Geant4Converter", "++ Created G4 Isotope %s from data: Z=%d N=%d A=%.3f [g/mole]",
339  element->GetName(), element->Z(), element->N(), element->A());
340  }
341  std::stringstream str;
342  str << (*g4e) << std::endl;
343  printout(lvl, "Geant4Converter", "++ Created G4 element %s", str.str().c_str());
344  data().g4Elements[element] = g4e;
345  }
346  return g4e;
347 }
348 
350 void* Geant4Converter::handleMaterial(const std::string& name, Material medium) const {
352  G4Material* mat = info.g4Materials[medium];
353  if ( !mat ) {
354  PrintLevel lvl = debugMaterials ? ALWAYS : outputLevel;
355  TGeoMaterial* material = medium->GetMaterial();
356  G4State state = kStateUndefined;
357  double density = material->GetDensity() * (CLHEP::gram / CLHEP::cm3);
358  if ( density < 1e-25 )
359  density = 1e-25;
360  switch ( material->GetState() ) {
361  case TGeoMaterial::kMatStateSolid:
362  state = kStateSolid;
363  break;
364  case TGeoMaterial::kMatStateLiquid:
365  state = kStateLiquid;
366  break;
367  case TGeoMaterial::kMatStateGas:
368  state = kStateGas;
369  break;
370  default:
371  case TGeoMaterial::kMatStateUndefined:
372  state = kStateUndefined;
373  break;
374  }
375  printout(lvl,"Geant4Material","+++ Setting up material %s", name.c_str());
376  if ( material->IsMixture() ) {
377  double A_total = 0.0;
378  double W_total = 0.0;
379  TGeoMixture* mix = (TGeoMixture*) material;
380  int nElements = mix->GetNelements();
381  mat = new G4Material(name, density, nElements, state,
382  material->GetTemperature(), material->GetPressure());
383  for (int i = 0; i < nElements; ++i) {
384  A_total += (mix->GetAmixt())[i];
385  W_total += (mix->GetWmixt())[i];
386  }
387  for (int i = 0; i < nElements; ++i) {
388  TGeoElement* e = mix->GetElement(i);
389  G4Element* g4e = (G4Element*) handleElement(e->GetName(), Atom(e));
390  if (!g4e) {
391  printout(ERROR, name,
392  "Missing element component %s for material %s. A=%f W=%f",
393  e->GetName(), mix->GetName(), A_total, W_total);
394  }
395  //mat->AddElement(g4e, (mix->GetAmixt())[i] / A_total);
396  mat->AddElement(g4e, (mix->GetWmixt())[i] / W_total);
397  }
398  }
399  else {
400  double z = material->GetZ(), a = material->GetA();
401  if ( z < 1.0000001 ) z = 1.0;
402  if ( a < 0.5000001 ) a = 1.0;
403  mat = new G4Material(name, z, a, density, state,
404  material->GetTemperature(), material->GetPressure());
405  }
406 
407  std::string plugin_name { };
408  double value = 0e0;
409  double ionisation_mee = -2e100;
410  double ionisation_birks_constant = -2e100;
411  double ionisation_ene_per_ion_pair = -2e100;
412 
414  G4MaterialPropertiesTable* tab = 0;
415  TListIter propIt(&material->GetProperties());
416  for(TObject* obj=propIt.Next(); obj; obj = propIt.Next()) {
417  std::string exc_str;
418  TNamed* named = (TNamed*)obj;
419  TGDMLMatrix* matrix = info.manager->GetGDMLMatrix(named->GetTitle());
420  const char* cptr = ::strstr(matrix->GetName(), GEANT4_TAG_IGNORE);
421  if ( nullptr != cptr ) {
422  printout(INFO,name,"++ Ignore property %s [%s]. Not Suitable for Geant4.",
423  matrix->GetName(), matrix->GetTitle());
424  continue;
425  }
426  cptr = ::strstr(matrix->GetTitle(), GEANT4_TAG_IGNORE);
427  if ( nullptr != cptr ) {
428  printout(INFO,name,"++ Ignore property %s [%s]. Not Suitable for Geant4.",
429  matrix->GetName(), matrix->GetTitle());
430  continue;
431  }
434  if ( nullptr == v ) {
435  except("Geant4Converter", "++ FAILED to create G4 material %s [Cannot convert property:%s]",
436  material->GetName(), named->GetName());
437  }
438  if ( nullptr == tab ) {
439  tab = new G4MaterialPropertiesTable();
440  mat->SetMaterialPropertiesTable(tab);
441  }
442  int idx = -1;
443  try {
444  idx = tab->GetPropertyIndex(named->GetName());
445  }
446  catch(const std::exception& e) {
447  exc_str = e.what();
448  idx = -1;
449  }
450  catch(...) {
451  idx = -1;
452  }
453  if ( idx < 0 ) {
454  printout(ERROR, "Geant4Converter",
455  "++ UNKNOWN Geant4 Property: %-20s %s [IGNORED]",
456  exc_str.c_str(), named->GetName());
457  continue;
458  }
459  // We need to convert the property from TGeo units to Geant4 units
460  auto conv = g4PropertyConversion(idx);
461  std::vector<double> bins(v->bins), vals(v->values);
462  for(std::size_t i=0, count=bins.size(); i<count; ++i)
463  bins[i] *= conv.first, vals[i] *= conv.second;
464 
465  G4MaterialPropertyVector* vec =
466  new G4MaterialPropertyVector(&bins[0], &vals[0], bins.size());
467  tab->AddProperty(named->GetName(), vec);
468  printout(lvl, name, "++ Property: %-20s [%ld x %ld] -> %s ",
469  named->GetName(), matrix->GetRows(), matrix->GetCols(), named->GetTitle());
470  for(std::size_t i=0, count=v->bins.size(); i<count; ++i)
471  printout(lvl, name, " Geant4: %s %8.3g [MeV] TGeo: %8.3g [GeV] Conversion: %8.3g",
472  named->GetName(), bins[i], v->bins[i], conv.first);
473  }
474 
476  TListIter cpropIt(&material->GetConstProperties());
477  for(TObject* obj=cpropIt.Next(); obj; obj = cpropIt.Next()) {
478  std::string exc_str;
479  Bool_t err = kFALSE;
480  TNamed* named = (TNamed*)obj;
481 
482  const char* cptr = ::strstr(named->GetName(), GEANT4_TAG_IGNORE);
483  if ( nullptr != cptr ) {
484  printout(INFO, name, "++ Ignore CONST property %s [%s].",
485  named->GetName(), named->GetTitle());
486  continue;
487  }
488  cptr = ::strstr(named->GetTitle(), GEANT4_TAG_IGNORE);
489  if ( nullptr != cptr ) {
490  printout(INFO, name,"++ Ignore CONST property %s [%s].",
491  named->GetName(), named->GetTitle());
492  continue;
493  }
494  cptr = ::strstr(named->GetName(), GEANT4_TAG_PLUGIN);
495  if ( nullptr != cptr ) {
496  printout(INFO, name, "++ Ignore CONST property %s [%s] --> Plugin.",
497  named->GetName(), named->GetTitle());
498  plugin_name = named->GetTitle();
499  continue;
500  }
501  cptr = ::strstr(named->GetName(), GEANT4_TAG_BIRKSCONSTANT);
502  if ( nullptr != cptr ) {
503  err = kFALSE;
504  value = material->GetConstProperty(GEANT4_TAG_BIRKSCONSTANT,&err);
505  if ( err == kFALSE ) ionisation_birks_constant = value * (CLHEP::mm/CLHEP::MeV)/(units::mm/units::MeV);
506  continue;
507  }
508  cptr = ::strstr(named->GetName(), GEANT4_TAG_MEE);
509  if ( nullptr != cptr ) {
510  err = kFALSE;
511  value = material->GetConstProperty(GEANT4_TAG_MEE, &err);
512  if ( err == kFALSE ) ionisation_mee = value * (CLHEP::MeV/units::MeV);
513  continue;
514  }
515  cptr = ::strstr(named->GetName(), GEANT4_TAG_ENE_PER_ION_PAIR);
516  if ( nullptr != cptr ) {
517  err = kFALSE;
518  value = material->GetConstProperty(GEANT4_TAG_ENE_PER_ION_PAIR,&err);
519  if ( err == kFALSE ) ionisation_ene_per_ion_pair = value * (CLHEP::MeV/units::MeV);
520  continue;
521  }
522 
523  err = kFALSE;
524  value = info.manager->GetProperty(named->GetTitle(), &err);
525  if ( err != kFALSE ) {
526  except(name,
527  "++ FAILED to create G4 material %s [Cannot convert const property: %s]",
528  material->GetName(), named->GetName());
529  }
530  if ( nullptr == tab ) {
531  tab = new G4MaterialPropertiesTable();
532  mat->SetMaterialPropertiesTable(tab);
533  }
534  int idx = -1;
535  try {
536  idx = tab->GetConstPropertyIndex(named->GetName());
537  }
538  catch(const std::exception& e) {
539  exc_str = e.what();
540  idx = -1;
541  }
542  catch(...) {
543  idx = -1;
544  }
545  if ( idx < 0 ) {
546  printout(ERROR, name,
547  "++ UNKNOWN Geant4 CONST Property: %-20s %s [IGNORED]",
548  exc_str.c_str(), named->GetName());
549  continue;
550  }
551  // We need to convert the property from TGeo units to Geant4 units
552  double conv = g4ConstPropertyConversion(idx);
553  printout(lvl, name, "++ CONST Property: %-20s %g ", named->GetName(), value);
554  tab->AddConstProperty(named->GetName(), value * conv);
555  }
556  //
557  // Set Birk's constant if it was supplied in the material table of the TGeoMaterial
558  auto* ionisation = mat->GetIonisation();
559  std::stringstream str;
560  str << (*mat);
561  if ( ionisation ) {
562  if ( ionisation_birks_constant > 0e0 ) {
563  ionisation->SetBirksConstant(ionisation_birks_constant);
564  }
565  if ( ionisation_mee > -1e100 ) {
566  ionisation->SetMeanExcitationEnergy(ionisation_mee);
567  }
568  if ( ionisation_ene_per_ion_pair > 0e0 ) {
569  ionisation->SetMeanEnergyPerIonPair(ionisation_ene_per_ion_pair);
570  }
571  str << " log(MEE): " << std::setprecision(4) << ionisation->GetLogMeanExcEnergy();
572  if ( ionisation_birks_constant > 0e0 )
573  str << " Birk's constant: " << std::setprecision(4) << ionisation->GetBirksConstant() << " [mm/MeV]";
574  if ( ionisation_ene_per_ion_pair > 0e0 )
575  str << " Mean Energy Per Ion Pair: " << std::setprecision(4) << ionisation->GetMeanEnergyPerIonPair()/CLHEP::eV << " [eV]";
576  }
577  else {
578  str << " No ionisation parameters availible.";
579  }
580  printout(lvl, name, "++ Created G4 material %s", str.str().c_str());
581 
582  if ( !plugin_name.empty() ) {
583  // Call plugin to create extended material if requested
584  Detector* det = const_cast<Detector*>(&m_detDesc);
585  G4Material* extended_mat = PluginService::Create<G4Material*>(plugin_name, det, medium, mat);
586  if ( !extended_mat ) {
587  except("G4Cnv::material["+name+"]","++ FATAL Failed to call plugin to create material.");
588  }
589  mat = extended_mat;
590  }
591  info.g4Materials[medium] = mat;
592  }
593  return mat;
594 }
595 
597 void* Geant4Converter::handleSolid(const std::string& name, const TGeoShape* shape) const {
598  G4VSolid* solid = nullptr;
599  if ( shape ) {
600  if ( nullptr != (solid = data().g4Solids[shape]) ) {
601  return solid;
602  }
603  TClass* isa = shape->IsA();
604  PrintLevel lvl = debugShapes ? ALWAYS : outputLevel;
605  if (isa == TGeoShapeAssembly::Class()) {
606  // Assemblies have no corresponding 'shape' in Geant4. Ignore the shape translation.
607  // It does not harm, since this 'shape' is never accessed afterwards.
608  data().g4Solids[shape] = solid = convertShape<TGeoShapeAssembly>(shape);
609  return solid;
610  }
611  else if (isa == TGeoBBox::Class())
612  solid = convertShape<TGeoBBox>(shape);
613  else if (isa == TGeoTube::Class())
614  solid = convertShape<TGeoTube>(shape);
615  else if (isa == TGeoTubeSeg::Class())
616  solid = convertShape<TGeoTubeSeg>(shape);
617  else if (isa == TGeoCtub::Class())
618  solid = convertShape<TGeoCtub>(shape);
619  else if (isa == TGeoEltu::Class())
620  solid = convertShape<TGeoEltu>(shape);
621  else if (isa == TwistedTubeObject::Class())
622  solid = convertShape<TwistedTubeObject>(shape);
623  else if (isa == TGeoTrd1::Class())
624  solid = convertShape<TGeoTrd1>(shape);
625  else if (isa == TGeoTrd2::Class())
626  solid = convertShape<TGeoTrd2>(shape);
627  else if (isa == TGeoHype::Class())
628  solid = convertShape<TGeoHype>(shape);
629  else if (isa == TGeoXtru::Class())
630  solid = convertShape<TGeoXtru>(shape);
631  else if (isa == TGeoPgon::Class())
632  solid = convertShape<TGeoPgon>(shape);
633  else if (isa == TGeoPcon::Class())
634  solid = convertShape<TGeoPcon>(shape);
635  else if (isa == TGeoCone::Class())
636  solid = convertShape<TGeoCone>(shape);
637  else if (isa == TGeoConeSeg::Class())
638  solid = convertShape<TGeoConeSeg>(shape);
639  else if (isa == TGeoParaboloid::Class())
640  solid = convertShape<TGeoParaboloid>(shape);
641  else if (isa == TGeoSphere::Class())
642  solid = convertShape<TGeoSphere>(shape);
643  else if (isa == TGeoTorus::Class())
644  solid = convertShape<TGeoTorus>(shape);
645  else if (isa == TGeoTrap::Class())
646  solid = convertShape<TGeoTrap>(shape);
647  else if (isa == TGeoArb8::Class())
648  solid = convertShape<TGeoArb8>(shape);
649  else if (isa == TGeoPara::Class())
650  solid = convertShape<TGeoPara>(shape);
651  else if (isa == TGeoTessellated::Class())
652  solid = convertShape<TGeoTessellated>(shape);
653  else if (isa == TGeoScaledShape::Class()) {
654  TGeoScaledShape* sh = (TGeoScaledShape*) shape;
655  TGeoShape* sol = sh->GetShape();
656  if ( sol->IsA() == TGeoShapeAssembly::Class() ) {
657  return solid;
658  }
659  const double* vals = sh->GetScale()->GetScale();
660  G4Scale3D scal(vals[0], vals[1], vals[2]);
661  G4VSolid* g4solid = (G4VSolid*)handleSolid(sol->GetName(), sol);
662  if ( scal.xx()>0e0 && scal.yy()>0e0 && scal.zz()>0e0 )
663  solid = new G4ScaledSolid(sh->GetName(), g4solid, scal);
664  else
665  solid = new G4ReflectedSolid(g4solid->GetName()+"_refl", g4solid, scal);
666  }
667  else if ( isa == TGeoCompositeShape::Class() ) {
668  const TGeoCompositeShape* sh = (const TGeoCompositeShape*) shape;
669  const TGeoBoolNode* boolean = sh->GetBoolNode();
670  TGeoBoolNode::EGeoBoolType oper = boolean->GetBooleanOperator();
671  TGeoMatrix* matrix = boolean->GetRightMatrix();
672  G4VSolid* left = (G4VSolid*) handleSolid(name + "_left", boolean->GetLeftShape());
673  G4VSolid* right = (G4VSolid*) handleSolid(name + "_right", boolean->GetRightShape());
674 
675  if (!left) {
676  except("Geant4Converter","++ No left Geant4 Solid present for composite shape: %s",name.c_str());
677  }
678  if (!right) {
679  except("Geant4Converter","++ No right Geant4 Solid present for composite shape: %s",name.c_str());
680  }
681 
682  TGeoShape* ls = boolean->GetLeftShape();
683  TGeoShape* rs = boolean->GetRightShape();
684  if (strcmp(ls->ClassName(), "TGeoScaledShape") == 0 &&
685  strcmp(rs->ClassName(), "TGeoBBox") == 0) {
686  if (strcmp(((TGeoScaledShape *)ls)->GetShape()->ClassName(), "TGeoSphere") == 0) {
687  if (oper == TGeoBoolNode::kGeoIntersection) {
688  TGeoScaledShape* lls = (TGeoScaledShape *)ls;
689  TGeoBBox* rrs = (TGeoBBox*)rs;
690  double sx = lls->GetScale()->GetScale()[0];
691  double sy = lls->GetScale()->GetScale()[1];
692  double radius = ((TGeoSphere *)lls->GetShape())->GetRmax();
693  double dz = rrs->GetDZ();
694  double zorig = rrs->GetOrigin()[2];
695  double zcut2 = dz + zorig;
696  double zcut1 = 2 * zorig - zcut2;
697  solid = new G4Ellipsoid(name,
698  sx * radius * CM_2_MM,
699  sy * radius * CM_2_MM,
700  radius * CM_2_MM,
701  zcut1 * CM_2_MM,
702  zcut2 * CM_2_MM);
703  data().g4Solids[shape] = solid;
704  return solid;
705  }
706  }
707  }
708 
709  if ( matrix->IsRotation() ) {
710  G4Transform3D transform;
711  g4Transform(matrix, transform);
712  if (oper == TGeoBoolNode::kGeoSubtraction)
713  solid = new G4SubtractionSolid(name, left, right, transform);
714  else if (oper == TGeoBoolNode::kGeoUnion)
715  solid = new G4UnionSolid(name, left, right, transform);
716  else if (oper == TGeoBoolNode::kGeoIntersection)
717  solid = new G4IntersectionSolid(name, left, right, transform);
718  }
719  else {
720  const Double_t *t = matrix->GetTranslation();
721  G4ThreeVector transform(t[0] * CM_2_MM, t[1] * CM_2_MM, t[2] * CM_2_MM);
722  if (oper == TGeoBoolNode::kGeoSubtraction)
723  solid = new G4SubtractionSolid(name, left, right, 0, transform);
724  else if (oper == TGeoBoolNode::kGeoUnion)
725  solid = new G4UnionSolid(name, left, right, 0, transform);
726  else if (oper == TGeoBoolNode::kGeoIntersection)
727  solid = new G4IntersectionSolid(name, left, right, 0, transform);
728  }
729  }
730 
731  if ( !solid )
732  except("Geant4Converter","++ Failed to handle unknown solid shape: %s of type %s",
733  name.c_str(), isa->GetName());
734  printout(lvl,"Geant4Converter","++ Successessfully converted shape [%p] of type:%s to %s.",
735  solid,isa->GetName(),typeName(typeid(*solid)).c_str());
736  data().g4Solids[shape] = solid;
737  }
738  return solid;
739 }
740 
742 void* Geant4Converter::handleVolume(const std::string& name, const TGeoVolume* volume) const {
743  Volume _v(volume);
745  PrintLevel lvl = debugVolumes ? ALWAYS : outputLevel;
746  Geant4GeometryMaps::VolumeMap::const_iterator volIt = info.g4Volumes.find(volume);
747  if ( _v.testFlagBit(Volume::VETO_SIMU) ) {
748  printout(lvl, "Geant4Converter", "++ Volume %s not converted [Veto'ed for simulation]",volume->GetName());
749  return nullptr;
750  }
751  else if (volIt == info.g4Volumes.end() ) {
752  const char* vnam = volume->GetName();
753  TGeoMedium* med = volume->GetMedium();
754  Solid sh = volume->GetShape();
755  bool is_assembly = sh->IsA() == TGeoShapeAssembly::Class() || volume->IsAssembly();
756 
757  printout(lvl, "Geant4Converter", "++ Convert Volume %-32s: %p %s/%s assembly:%s",
758  vnam, volume, sh.type(), _v.type(), yes_no(is_assembly));
759  if ( is_assembly ) {
760  return nullptr;
761  }
762  Region reg = _v.region();
763  LimitSet lim = _v.limitSet();
764  VisAttr vis = _v.visAttributes();
765  G4Region* g4region = reg.isValid() ? info.g4Regions[reg] : nullptr;
766  G4UserLimits* g4limits = lim.isValid() ? info.g4Limits[lim] : nullptr;
767  G4VSolid* g4solid = (G4VSolid*) handleSolid(sh->GetName(), sh);
768  G4Material* g4medium = (G4Material*) handleMaterial(med->GetName(), Material(med));
770  if ( !g4solid ) {
771  except("G4Converter","++ No Geant4 Solid present for volume: %s", vnam);
772  }
773  else if ( !g4medium ) {
774  except("G4Converter","++ No Geant4 material present for volume: %s", vnam);
775  }
776  else if ( reg.isValid() && !g4region ) {
777  except("G4Cnv::volume["+name+"]"," ++ Failed to access Geant4 region %s.", reg.name());
778  }
779  else if ( lim.isValid() && !g4limits ) {
780  except("G4Cnv::volume["+name+"]","++ FATAL Failed to access Geant4 user limits %s.", lim.name());
781  }
782  else if ( g4limits ) {
783  printout(lvl, "Geant4Converter", "++ Volume + Apply LIMITS settings: %-24s to volume %s.",
784  lim.name(), vnam);
785  }
786 
787  G4LogicalVolume* g4vol = nullptr;
788  if( _v.hasProperties() && !_v.getProperty(GEANT4_TAG_PLUGIN,"").empty() ) {
789  Detector* det = const_cast<Detector*>(&m_detDesc);
790  std::string plugin = _v.getProperty(GEANT4_TAG_PLUGIN,"");
791  g4vol = PluginService::Create<G4LogicalVolume*>(plugin, det, _v, g4solid, g4medium);
792  if ( !g4vol ) {
793  except("G4Cnv::volume["+name+"]","++ FATAL Failed to call plugin to create logical volume.");
794  }
795  }
796  else {
797  g4vol = new G4LogicalVolume(g4solid, g4medium, vnam, nullptr, nullptr, nullptr);
798  }
799  PrintLevel plevel = (debugVolumes||debugRegions||debugLimits) ? ALWAYS : outputLevel;
801  unsigned char smart_less_value = _v.smartlessValue();
802  if( smart_less_value != Volume::NO_SMARTLESS_OPTIMIZATION ) {
803  printout(ALWAYS, "Geant4Converter", "++ Volume %s Set Smartless value to %d",
804  vnam, int(smart_less_value));
805  g4vol->SetSmartless( smart_less_value );
806  }
808  if( g4limits ) {
809  g4vol->SetUserLimits(g4limits);
810  }
811  if( g4region ) {
812  printout(plevel, "Geant4Converter", "++ Volume + Apply REGION settings: %-24s to volume %s.",
813  reg.name(), vnam);
814  // Handle the region settings for the world volume seperately.
815  // Geant4 does NOT WANT any regions assigned to the workd volume.
816  // The world's region is created in the G4RunManagerKernel!
817  if ( _v == m_detDesc.worldVolume() ) {
818  const char* wrd_nam = "DefaultRegionForTheWorld";
819  const char* src_nam = g4region->GetName().c_str();
820  auto* world_region = G4RegionStore::GetInstance()->GetRegion(wrd_nam, false);
821  if ( auto* cuts = g4region->GetProductionCuts() ) {
822  world_region->SetProductionCuts(cuts);
823  printout(plevel, "Geant4Converter",
824  "++ Volume %s Region: %s. Apply production cuts from %s",
825  vnam, wrd_nam, src_nam);
826  }
827  if ( auto* lims = g4region->GetUserLimits() ) {
828  world_region->SetUserLimits(lims);
829  printout(plevel, "Geant4Converter",
830  "++ Volume %s Region: %s. Apply user limits from %s",
831  vnam, wrd_nam, src_nam);
832  }
833  }
834  else {
835  g4vol->SetRegion(g4region);
836  g4region->AddRootLogicalVolume(g4vol);
837  }
838  }
839  G4VisAttributes* g4vattr = vis.isValid()
840  ? (G4VisAttributes*)handleVis(vis.name(), vis) : nullptr;
841  if ( g4vattr ) {
842  g4vol->SetVisAttributes(g4vattr);
843  }
844  info.g4Volumes[volume] = g4vol;
845  printout(lvl, "Geant4Converter",
846  "++ Volume + %s converted: %p ---> G4: %p", vnam, volume, g4vol);
847  }
848  return nullptr;
849 }
850 
852 void* Geant4Converter::collectVolume(const std::string& /* name */, const TGeoVolume* volume) const {
854  Volume _v(volume);
855  Region reg = _v.region();
856  LimitSet lim = _v.limitSet();
858  bool world = (volume == m_detDesc.worldVolume().ptr());
859 
860  if ( !world ) {
861  if ( lim.isValid() )
862  info.limits[lim].insert(volume);
863  if ( reg.isValid() )
864  info.regions[reg].insert(volume);
865  if ( det.isValid() )
866  info.sensitives[det].insert(volume);
867  }
868  return (void*)volume;
869 }
870 
872 void* Geant4Converter::handleAssembly(const std::string& name, const TGeoNode* node) const {
873  TGeoVolume* mot_vol = node->GetVolume();
874  PrintLevel lvl = debugVolumes ? ALWAYS : outputLevel;
875  if ( mot_vol->IsA() != TGeoVolumeAssembly::Class() ) {
876  return nullptr;
877  }
878  Volume _v(mot_vol);
879  if ( _v.testFlagBit(Volume::VETO_SIMU) ) {
880  printout(lvl, "Geant4Converter", "++ AssemblyNode %s not converted [Veto'ed for simulation]",node->GetName());
881  return nullptr;
882  }
884  Geant4AssemblyVolume* g4 = info.g4AssemblyVolumes[node];
885  if ( g4 ) {
886  printout(ALWAYS, "Geant4Converter", "+++ Assembly: **** : Re-using existing assembly: %s",node->GetName());
887  }
888  if ( !g4 ) {
889  g4 = new Geant4AssemblyVolume();
890  for(Int_t i=0; i < mot_vol->GetNdaughters(); ++i) {
891  TGeoNode* dau = mot_vol->GetNode(i);
892  TGeoVolume* dau_vol = dau->GetVolume();
893  TGeoMatrix* tr = dau->GetMatrix();
894  G4Transform3D transform;
895 
896  g4Transform(tr, transform);
897  if ( is_left_handed(tr) ) {
898  G4Scale3D scale;
899  G4Rotate3D rot;
900  G4Translate3D trans;
901  transform.getDecomposition(scale, rot, trans);
902  printout(debugReflections ? ALWAYS : lvl, "Geant4Converter",
903  "++ Placing reflected ASSEMBLY. dau:%s to mother %s "
904  "Tr:x=%8.1f y=%8.1f z=%8.1f Scale:x=%4.2f y=%4.2f z=%4.2f",
905  dau_vol->GetName(), mot_vol->GetName(),
906  transform.dx(), transform.dy(), transform.dz(),
907  scale.xx(), scale.yy(), scale.zz());
908  }
909 
910  if ( dau_vol->IsA() == TGeoVolumeAssembly::Class() ) {
911  Geant4GeometryMaps::AssemblyMap::iterator ia = info.g4AssemblyVolumes.find(dau);
912  if ( ia == info.g4AssemblyVolumes.end() ) {
913  printout(FATAL, "Geant4Converter", "+++ Invalid child assembly at %s : %d parent: %s child:%s",
914  __FILE__, __LINE__, name.c_str(), dau->GetName());
915  delete g4;
916  return nullptr;
917  }
918  g4->placeAssembly(dau, (*ia).second, transform);
919  printout(lvl, "Geant4Converter", "+++ Assembly: AddPlacedAssembly %p: dau:%s "
920  "to mother %s Tr:x=%8.3f y=%8.3f z=%8.3f",
921  (void*)dau_vol, dau_vol->GetName(), mot_vol->GetName(),
922  transform.dx(), transform.dy(), transform.dz());
923  }
924  else {
925  Geant4GeometryMaps::VolumeMap::iterator iv = info.g4Volumes.find(dau_vol);
926  if ( iv == info.g4Volumes.end() ) {
927  printout(FATAL,"Geant4Converter", "+++ Invalid child volume at %s : %d parent: %s child:%s",
928  __FILE__, __LINE__, name.c_str(), dau->GetName());
929  except("Geant4Converter", "+++ Invalid child volume at %s : %d parent: %s child:%s",
930  __FILE__, __LINE__, name.c_str(), dau->GetName());
931  }
932  g4->placeVolume(dau,(*iv).second, transform);
933  printout(lvl, "Geant4Converter", "+++ Assembly: AddPlacedVolume %p: dau:%s "
934  "to mother %s Tr:x=%8.3f y=%8.3f z=%8.3f",
935  (void*)dau_vol, dau_vol->GetName(), mot_vol->GetName(),
936  transform.dx(), transform.dy(), transform.dz());
937  }
938  }
939  info.g4AssemblyVolumes[node] = g4;
940  }
941  return g4;
942 }
943 
945 void* Geant4Converter::handlePlacement(const std::string& name, const TGeoNode* node) const {
947  PrintLevel lvl = debugPlacements ? ALWAYS : outputLevel;
948  Geant4GeometryMaps::PlacementMap::const_iterator g4it = info.g4Placements.find(node);
949  G4VPhysicalVolume* g4 = (g4it == info.g4Placements.end()) ? 0 : (*g4it).second;
950  TGeoVolume* vol = node->GetVolume();
951  Volume _v(vol);
952 
953  if ( _v.testFlagBit(Volume::VETO_SIMU) ) {
954  printout(lvl, "Geant4Converter", "++ Placement %s not converted [Veto'ed for simulation]",node->GetName());
955  return nullptr;
956  }
957  //g4 = nullptr;
958  if ( !g4 ) {
959  TGeoVolume* mot_vol = node->GetMotherVolume();
960  TGeoMatrix* tr = node->GetMatrix();
961  if ( !tr ) {
962  except("Geant4Converter",
963  "++ Attempt to handle placement without transformation:%p %s of type %s vol:%p",
964  node, node->GetName(), node->IsA()->GetName(), vol);
965  }
966  else if (nullptr == vol) {
967  except("Geant4Converter", "++ Unknown G4 volume:%p %s of type %s ptr:%p",
968  node, node->GetName(), node->IsA()->GetName(), vol);
969  }
970  else {
971  int copy = node->GetNumber();
972  bool node_is_reflected = is_left_handed(tr);
973  bool node_is_assembly = vol->IsA() == TGeoVolumeAssembly::Class();
974  bool mother_is_assembly = mot_vol ? mot_vol->IsA() == TGeoVolumeAssembly::Class() : false;
975  G4Transform3D transform;
976  Geant4GeometryMaps::VolumeMap::const_iterator volIt = info.g4Volumes.find(mot_vol);
977 
978  g4Transform(tr, transform);
979  if ( mother_is_assembly ) {
980  //
981  // Mother is an assembly:
982  // Nothing to do here, because:
983  // -- placed volumes were already added before in "handleAssembly"
984  // -- imprint cannot be made, because this requires a logical volume as a mother
985  //
986  printout(lvl, "Geant4Converter", "+++ Assembly: **** : dau:%s "
987  "to mother %s Tr:x=%8.3f y=%8.3f z=%8.3f",
988  vol->GetName(), mot_vol->GetName(),
989  transform.dx(), transform.dy(), transform.dz());
990  return nullptr;
991  }
992  G4Scale3D scale;
993  G4Rotate3D rot;
994  G4Translate3D trans;
995  transform.getDecomposition(scale, rot, trans);
996  if ( node_is_assembly ) {
997  //
998  // Node is an assembly:
999  // Imprint the assembly. The mother MUST already be transformed.
1000  //
1001  printout(lvl, "Geant4Converter", "++ Assembly: makeImprint: dau:%-12s %s in mother %-12s "
1002  "Tr:x=%8.1f y=%8.1f z=%8.1f Scale:x=%4.2f y=%4.2f z=%4.2f",
1003  node->GetName(), node_is_reflected ? "(REFLECTED)" : "",
1004  mot_vol ? mot_vol->GetName() : "<unknown>",
1005  transform.dx(), transform.dy(), transform.dz(),
1006  scale.xx(), scale.yy(), scale.zz());
1007  Geant4AssemblyVolume* ass = (Geant4AssemblyVolume*)info.g4AssemblyVolumes[node];
1009  chain.emplace_back(node);
1010  ass->imprint(*this, node, chain, ass, (*volIt).second, transform, checkOverlaps);
1011  return nullptr;
1012  }
1013  else if ( node != info.manager->GetTopNode() && volIt == info.g4Volumes.end() ) {
1014  //throw std::logic_error("Geant4Converter: Invalid mother volume found!");
1015  }
1016  PlacedVolume pv(node);
1017  const auto* pv_data = pv.data();
1018  G4LogicalVolume* g4vol = info.g4Volumes[vol];
1019  G4LogicalVolume* g4mot = info.g4Volumes[mot_vol];
1020  G4PhysicalVolumesPair pvPlaced { nullptr, nullptr };
1021 
1022  if ( pv_data && pv_data->params && (pv_data->params->flags&Volume::REPLICATED) ) {
1023  EAxis axis = kUndefined;
1024  double width = 0e0, offset = 0e0;
1025  auto flags = pv_data->params->flags;
1026  auto count = pv_data->params->trafo1D.second;
1027  auto start = pv_data->params->start.Translation().Vect();
1028  auto delta = pv_data->params->trafo1D.first.Translation().Vect();
1029 
1030  if ( flags&Volume::X_axis )
1031  { axis = kXAxis; width = delta.X(); offset = start.X(); }
1032  else if ( flags&Volume::Y_axis )
1033  { axis = kYAxis; width = delta.Y(); offset = start.Y(); }
1034  else if ( flags&Volume::Z_axis )
1035  { axis = kZAxis; width = delta.Z(); offset = start.Z(); }
1036  else
1037  except("Geant4Converter",
1038  "++ Replication around unknown axis is not implemented. flags: %16X", flags);
1039  printout(INFO,"Geant4Converter","++ Replicate: Axis: %ld Count: %ld offset: %f width: %f",
1040  axis, count, offset, width);
1041  auto* g4pv = new G4PVReplica(name, // its name
1042  g4vol, // its logical volume
1043  g4mot, // its mother (logical) volume
1044  axis, // its replication axis
1045  count, // Number of replicas
1046  width, // Distance between 2 replicas
1047  offset); // Placement offset in axis direction
1048  pvPlaced = { g4pv, nullptr };
1049 #if 0
1050  pvPlaced =
1051  G4ReflectionFactory::Instance()->Replicate(name, // its name
1052  g4vol, // its logical volume
1053  g4mot, // its mother (logical) volume
1054  axis, // its replication axis
1055  count, // Number of replicas
1056  width, // Distance between 2 replicas
1057  offset); // Placement offset in axis direction
1059  auto* g4pv = pvPlaced.second ? pvPlaced.second : pvPlaced.first;
1060 #endif
1061  for( auto& handle : pv_data->params->placements )
1062  info.g4Placements[handle.ptr()] = g4pv;
1063  }
1064  else if ( pv_data && pv_data->params ) {
1065  auto* g4par = new Geant4PlacementParameterisation(pv);
1066  auto* g4pv = new G4PVParameterised(name, // its name
1067  g4vol, // its logical volume
1068  g4mot, // its mother (logical) volume
1069  g4par->axis(), // its replication axis
1070  g4par->count(), // Number of replicas
1071  g4par); // G4 parametrization
1072  pvPlaced = { g4pv, nullptr };
1074  for( auto& handle : pv_data->params->placements )
1075  info.g4Placements[handle.ptr()] = g4pv;
1076  }
1077  else {
1078  pvPlaced =
1079  G4ReflectionFactory::Instance()->Place(transform, // no rotation
1080  name, // its name
1081  g4vol, // its logical volume
1082  g4mot, // its mother (logical) volume
1083  false, // no boolean operations
1084  copy, // its copy number
1085  checkOverlaps);
1086  }
1087  printout(debugReflections||debugPlacements ? ALWAYS : lvl, "Geant4Converter",
1088  "++ Place %svolume %-12s in mother %-12s "
1089  "Tr:x=%8.1f y=%8.1f z=%8.1f Scale:x=%4.2f y=%4.2f z=%4.2f",
1090  node_is_reflected ? "REFLECTED " : "", _v.name(),
1091  mot_vol ? mot_vol->GetName() : "<unknown>",
1092  transform.dx(), transform.dy(), transform.dz(),
1093  scale.xx(), scale.yy(), scale.zz());
1094  // First 2 cases can be combined.
1095  // Leave them separated for debugging G4ReflectionFactory for now...
1096  if ( node_is_reflected && !pvPlaced.second )
1097  return info.g4Placements[node] = pvPlaced.first;
1098  else if ( !node_is_reflected && !pvPlaced.second )
1099  return info.g4Placements[node] = pvPlaced.first;
1100  // Now deal with valid pvPlaced.second ...
1101  if ( node_is_reflected )
1102  return info.g4Placements[node] = pvPlaced.first;
1103  else if ( !node_is_reflected )
1104  return info.g4Placements[node] = pvPlaced.first;
1105  g4 = pvPlaced.second ? pvPlaced.second : pvPlaced.first;
1106  }
1107  info.g4Placements[node] = g4;
1108  printout(ERROR, "Geant4Converter", "++ DEAD code. Should not end up here!");
1109  }
1110  return g4;
1111 }
1112 
1114 void* Geant4Converter::handleRegion(Region region, const std::set<const TGeoVolume*>& /* volumes */) const {
1115  G4Region* g4 = data().g4Regions[region];
1116  if ( !g4 ) {
1117  PrintLevel lvl = debugRegions ? ALWAYS : outputLevel;
1118  Region r = region;
1119  g4 = new G4Region(region.name());
1120 
1121  // create region info with storeSecondaries flag
1122  if( not r.wasThresholdSet() and r.storeSecondaries() ) {
1123  throw std::runtime_error("G4Region: StoreSecondaries is True, but no explicit threshold set:");
1124  }
1125  printout(lvl, "Geant4Converter", "++ Setting up region: %s", r.name());
1126  G4UserRegionInformation* info = new G4UserRegionInformation();
1127  info->region = r;
1128  info->threshold = r.threshold()*CLHEP::MeV/units::MeV;
1129  info->storeSecondaries = r.storeSecondaries();
1130  g4->SetUserInformation(info);
1131 
1132  printout(lvl, "Geant4Converter", "++ Converted region settings of:%s.", r.name());
1133  std::vector < std::string > &limits = r.limits();
1134  G4ProductionCuts* cuts = 0;
1135  // set production cut
1136  if( not r.useDefaultCut() ) {
1137  cuts = new G4ProductionCuts();
1138  cuts->SetProductionCut(r.cut()*CLHEP::mm/units::mm);
1139  printout(lvl, "Geant4Converter", "++ %s: Using default cut: %f [mm]",
1140  r.name(), r.cut()*CLHEP::mm/units::mm);
1141  }
1142  for( const auto& nam : limits ) {
1143  LimitSet ls = m_detDesc.limitSet(nam);
1144  if ( ls.isValid() ) {
1145  const LimitSet::Set& cts = ls.cuts();
1146  for (const auto& c : cts ) {
1147  int pid = 0;
1148  if ( c.particles == "*" ) pid = -1;
1149  else if ( c.particles == "e-" ) pid = idxG4ElectronCut;
1150  else if ( c.particles == "e+" ) pid = idxG4PositronCut;
1151  else if ( c.particles == "e[+-]" ) pid = -idxG4PositronCut-idxG4ElectronCut;
1152  else if ( c.particles == "e[-+]" ) pid = -idxG4PositronCut-idxG4ElectronCut;
1153  else if ( c.particles == "gamma" ) pid = idxG4GammaCut;
1154  else if ( c.particles == "proton" ) pid = idxG4ProtonCut;
1155  else throw std::runtime_error("G4Region: Invalid production cut particle-type:" + c.particles);
1156  if ( !cuts ) cuts = new G4ProductionCuts();
1157  if ( pid == -(idxG4PositronCut+idxG4ElectronCut) ) {
1158  cuts->SetProductionCut(c.value*CLHEP::mm/units::mm, idxG4PositronCut);
1159  cuts->SetProductionCut(c.value*CLHEP::mm/units::mm, idxG4ElectronCut);
1160  }
1161  else {
1162  cuts->SetProductionCut(c.value*CLHEP::mm/units::mm, pid);
1163  }
1164  printout(lvl, "Geant4Converter", "++ %s: Set cut [%s/%d] = %f [mm]",
1165  r.name(), c.particles.c_str(), pid, c.value*CLHEP::mm/units::mm);
1166  }
1167  bool found = false;
1168  const auto& lm = data().g4Limits;
1169  for (const auto& j : lm ) {
1170  if (nam == j.first->GetName()) {
1171  g4->SetUserLimits(j.second);
1172  printout(lvl, "Geant4Converter", "++ %s: Set limits %s to region type %s",
1173  r.name(), nam.c_str(), j.second->GetType().c_str());
1174  found = true;
1175  break;
1176  }
1177  }
1178  if ( found ) {
1179  continue;
1180  }
1181  }
1182  except("Geant4Converter", "++ G4Region: Failed to resolve limitset: " + nam);
1183  }
1185  if ( cuts ) g4->SetProductionCuts(cuts);
1186  data().g4Regions[region] = g4;
1187  }
1188  return g4;
1189 }
1190 
1192 void* Geant4Converter::handleLimitSet(LimitSet limitset, const std::set<const TGeoVolume*>& /* volumes */) const {
1193  G4UserLimits* g4 = data().g4Limits[limitset];
1194  if ( !g4 ) {
1195  PrintLevel lvl = debugLimits || debugRegions ? ALWAYS : outputLevel;
1196  struct LimitPrint {
1197  const LimitSet& ls;
1198  LimitPrint(const LimitSet& lset) : ls(lset) {}
1199  const LimitPrint& operator()(const std::string& pref, const Geant4UserLimits::Handler& h) const {
1200  if ( !h.particleLimits.empty() ) {
1201  printout(ALWAYS,"Geant4Converter",
1202  "+++ LimitSet: Explicit Limit %s.%s applied for particles:",ls.name(), pref.c_str());
1203  for(const auto& p : h.particleLimits)
1204  printout(ALWAYS,"Geant4Converter","+++ LimitSet: Particle type: %-18s PDG: %-6d : %f",
1205  p.first->GetParticleName().c_str(), p.first->GetPDGEncoding(), p.second);
1206  }
1208  printout(ALWAYS,"Geant4Converter",
1209  "+++ LimitSet: Implicit Limit %s.%s for wildcard particles: %f",
1210  ls.name(), pref.c_str(), float(h.defaultValue));
1211  }
1212  return *this;
1213  }
1214  };
1215  Geant4UserLimits* limits = new Geant4UserLimits(limitset);
1216  g4 = limits;
1217  printout(lvl, "Geant4Converter",
1218  "++ Successfully converted LimitSet: %s [%ld cuts, %ld limits]",
1219  limitset.name(), limitset.cuts().size(), limitset.limits().size());
1220  if ( debugRegions || debugLimits ) {
1221  LimitPrint print(limitset);
1222  print("maxTime", limits->maxTime)
1223  ("minEKine", limits->minEKine)
1224  ("minRange", limits->minRange)
1225  ("maxStepLength", limits->maxStepLength)
1226  ("maxTrackLength",limits->maxTrackLength);
1227  }
1228  data().g4Limits[limitset] = g4;
1229  }
1230  return g4;
1231 }
1232 
1234 void* Geant4Converter::handleVis(const std::string& /* name */, VisAttr attr) const {
1236  G4VisAttributes* g4 = info.g4Vis[attr];
1237  if ( !g4 ) {
1238  float red = 0, green = 0, blue = 0;
1239  int style = attr.lineStyle();
1240  attr.rgb(red, green, blue);
1241  g4 = new G4VisAttributes(attr.visible(), G4Colour(red, green, blue, attr.alpha()));
1242  //g4->SetLineWidth(attr->GetLineWidth());
1243  g4->SetDaughtersInvisible(!attr.showDaughters());
1244  if ( style == VisAttr::SOLID ) {
1245  g4->SetLineStyle(G4VisAttributes::unbroken);
1246  g4->SetForceWireframe(false);
1247  g4->SetForceSolid(true);
1248  }
1249  else if ( style == VisAttr::WIREFRAME || style == VisAttr::DASHED ) {
1250  g4->SetLineStyle(G4VisAttributes::dashed);
1251  g4->SetForceSolid(false);
1252  g4->SetForceWireframe(true);
1253  }
1254  info.g4Vis[attr] = g4;
1255  }
1256  return g4;
1257 }
1258 
1261  std::map < std::string, std::string > processors;
1262  static int s_idd = 9999999;
1263  for( const auto& [nam, vals] : prp ) {
1264  if ( nam.substr(0, 6) == "geant4" ) {
1265  auto id_it = vals.find("id");
1266  std::string id = (id_it == vals.end()) ? _toString(++s_idd,"%d") : (*id_it).second;
1267  processors.emplace(id, nam);
1268  }
1269  }
1270  for( const auto& p : processors ) {
1271  const GeoHandler* hdlr = this;
1272  const Detector::PropertyValues& vals = prp[p.second];
1273  auto iter = vals.find("type");
1274  if ( iter != vals.end() ) {
1275  std::string type = iter->second;
1276  std::string tag = type + "_Geant4_action";
1277  Detector* det = const_cast<Detector*>(&m_detDesc);
1278  long res = PluginService::Create<long>(tag, det, hdlr, &vals);
1279  if ( 0 == res ) {
1280  throw std::runtime_error("Failed to locate plugin to interprete files of type"
1281  " \"" + tag + "\" - no factory:" + type);
1282  }
1283  res = *(long*)res;
1284  if ( res != 1 ) {
1285  throw std::runtime_error("Failed to invoke the plugin " + tag + " of type " + type);
1286  }
1287  printout(outputLevel, "Geant4Converter", "+++++ Executed Successfully Geant4 setup module *%s*.", type.c_str());
1288  continue;
1289  }
1290  printout(outputLevel, "Geant4Converter", "+++++ FAILED to execute Geant4 setup module *%s*.", p.second.c_str());
1291  }
1292 }
1293 
1297  TGDMLMatrix* matrix = (TGDMLMatrix*)mtx;
1298  const char* cptr = ::strstr(matrix->GetName(), GEANT4_TAG_IGNORE);
1299  Geant4GeometryInfo::PropertyVector* g4 = info.g4OpticalProperties[matrix];
1300 
1301  if ( nullptr != cptr ) { // Check if the property should not be passed to Geant4
1302  printout(INFO,"Geant4MaterialProperties","++ Ignore property %s [%s].",
1303  matrix->GetName(), matrix->GetTitle());
1304  return nullptr;
1305  }
1306  cptr = ::strstr(matrix->GetTitle(), GEANT4_TAG_IGNORE);
1307  if ( nullptr != cptr ) { // Check if the property should not be passed to Geant4
1308  printout(INFO,"Geant4MaterialProperties","++ Ignore property %s [%s].",
1309  matrix->GetName(), matrix->GetTitle());
1310  return nullptr;
1311  }
1312 
1313  if ( !g4 ) {
1314  PrintLevel lvl = debugMaterials ? ALWAYS : outputLevel;
1316  std::size_t rows = matrix->GetRows();
1317  g4->name = matrix->GetName();
1318  g4->title = matrix->GetTitle();
1319  g4->bins.reserve(rows);
1320  g4->values.reserve(rows);
1321  for( std::size_t i=0; i<rows; ++i ) {
1322  g4->bins.emplace_back(matrix->Get(i,0) /* *CLHEP::eV/units::eV */);
1323  g4->values.emplace_back(matrix->Get(i,1));
1324  }
1325  printout(lvl, "Geant4Converter",
1326  "++ Successfully converted material property:%s : %s [%ld rows]",
1327  matrix->GetName(), matrix->GetTitle(), rows);
1328  info.g4OpticalProperties[matrix] = g4;
1329  }
1330  return g4;
1331 }
1332 
1333 static G4OpticalSurfaceFinish geant4_surface_finish(TGeoOpticalSurface::ESurfaceFinish f) {
1334 #define TO_G4_FINISH(x) case TGeoOpticalSurface::kF##x : return x;
1335  switch(f) {
1336  TO_G4_FINISH(polished); // smooth perfectly polished surface
1337  TO_G4_FINISH(polishedfrontpainted); // smooth top-layer (front) paint
1338  TO_G4_FINISH(polishedbackpainted); // same is 'polished' but with a back-paint
1339 
1340  TO_G4_FINISH(ground); // rough surface
1341  TO_G4_FINISH(groundfrontpainted); // rough top-layer (front) paint
1342  TO_G4_FINISH(groundbackpainted); // same as 'ground' but with a back-paint
1343 
1344  TO_G4_FINISH(polishedlumirrorair); // mechanically polished surface, with lumirror
1345  TO_G4_FINISH(polishedlumirrorglue); // mechanically polished surface, with lumirror & meltmount
1346  TO_G4_FINISH(polishedair); // mechanically polished surface
1347  TO_G4_FINISH(polishedteflonair); // mechanically polished surface, with teflon
1348  TO_G4_FINISH(polishedtioair); // mechanically polished surface, with tio paint
1349  TO_G4_FINISH(polishedtyvekair); // mechanically polished surface, with tyvek
1350  TO_G4_FINISH(polishedvm2000air); // mechanically polished surface, with esr film
1351  TO_G4_FINISH(polishedvm2000glue); // mechanically polished surface, with esr film & meltmount
1352 
1353  TO_G4_FINISH(etchedlumirrorair); // chemically etched surface, with lumirror
1354  TO_G4_FINISH(etchedlumirrorglue); // chemically etched surface, with lumirror & meltmount
1355  TO_G4_FINISH(etchedair); // chemically etched surface
1356  TO_G4_FINISH(etchedteflonair); // chemically etched surface, with teflon
1357  TO_G4_FINISH(etchedtioair); // chemically etched surface, with tio paint
1358  TO_G4_FINISH(etchedtyvekair); // chemically etched surface, with tyvek
1359  TO_G4_FINISH(etchedvm2000air); // chemically etched surface, with esr film
1360  TO_G4_FINISH(etchedvm2000glue); // chemically etched surface, with esr film & meltmount
1361 
1362  TO_G4_FINISH(groundlumirrorair); // rough-cut surface, with lumirror
1363  TO_G4_FINISH(groundlumirrorglue); // rough-cut surface, with lumirror & meltmount
1364  TO_G4_FINISH(groundair); // rough-cut surface
1365  TO_G4_FINISH(groundteflonair); // rough-cut surface, with teflon
1366  TO_G4_FINISH(groundtioair); // rough-cut surface, with tio paint
1367  TO_G4_FINISH(groundtyvekair); // rough-cut surface, with tyvek
1368  TO_G4_FINISH(groundvm2000air); // rough-cut surface, with esr film
1369  TO_G4_FINISH(groundvm2000glue); // rough-cut surface, with esr film & meltmount
1370 
1371  // for DAVIS model
1372  TO_G4_FINISH(Rough_LUT); // rough surface
1373  TO_G4_FINISH(RoughTeflon_LUT); // rough surface wrapped in Teflon tape
1374  TO_G4_FINISH(RoughESR_LUT); // rough surface wrapped with ESR
1375  TO_G4_FINISH(RoughESRGrease_LUT); // rough surface wrapped with ESR and coupled with opical grease
1376  TO_G4_FINISH(Polished_LUT); // polished surface
1377  TO_G4_FINISH(PolishedTeflon_LUT); // polished surface wrapped in Teflon tape
1378  TO_G4_FINISH(PolishedESR_LUT); // polished surface wrapped with ESR
1379  TO_G4_FINISH(PolishedESRGrease_LUT); // polished surface wrapped with ESR and coupled with opical grease
1380  TO_G4_FINISH(Detector_LUT); // polished surface with optical grease
1381  default:
1382  printout(ERROR,"Geant4Surfaces","++ Unknown finish style: %d [%s]. Assume polished!",
1383  int(f), TGeoOpticalSurface::FinishToString(f));
1384  return polished;
1385  }
1386 #undef TO_G4_FINISH
1387 }
1388 
1389 static G4SurfaceType geant4_surface_type(TGeoOpticalSurface::ESurfaceType t) {
1390 #define TO_G4_TYPE(x) case TGeoOpticalSurface::kT##x : return x;
1391  switch(t) {
1392  TO_G4_TYPE(dielectric_metal); // dielectric-metal interface
1393  TO_G4_TYPE(dielectric_dielectric); // dielectric-dielectric interface
1394  TO_G4_TYPE(dielectric_LUT); // dielectric-Look-Up-Table interface
1395  TO_G4_TYPE(dielectric_LUTDAVIS); // dielectric-Look-Up-Table DAVIS interface
1396  TO_G4_TYPE(dielectric_dichroic); // dichroic filter interface
1397  TO_G4_TYPE(firsov); // for Firsov Process
1398  TO_G4_TYPE(x_ray); // for x-ray mirror process
1399  default:
1400  printout(ERROR,"Geant4Surfaces","++ Unknown surface type: %d [%s]. Assume dielectric_metal!",
1401  int(t), TGeoOpticalSurface::TypeToString(t));
1402  return dielectric_metal;
1403  }
1404 #undef TO_G4_TYPE
1405 }
1406 
1407 static G4OpticalSurfaceModel geant4_surface_model(TGeoOpticalSurface::ESurfaceModel surfMod) {
1408 #define TO_G4_MODEL(x) case TGeoOpticalSurface::kM##x : return x;
1409  switch(surfMod) {
1410  TO_G4_MODEL(glisur); // original GEANT3 model
1411  TO_G4_MODEL(unified); // UNIFIED model
1412  TO_G4_MODEL(LUT); // Look-Up-Table model
1413  TO_G4_MODEL(DAVIS); // DAVIS model
1414  TO_G4_MODEL(dichroic); // dichroic filter
1415  default:
1416  printout(ERROR,"Geant4Surfaces","++ Unknown surface model: %d [%s]. Assume glisur!",
1417  int(surfMod), TGeoOpticalSurface::ModelToString(surfMod));
1418  return glisur;
1419  }
1420 #undef TO_G4_MODEL
1421 }
1422 
1425  TGeoOpticalSurface* optSurf = (TGeoOpticalSurface*)surface;
1427  G4OpticalSurface* g4 = info.g4OpticalSurfaces[optSurf];
1428  if ( !g4 ) {
1429  G4SurfaceType type = geant4_surface_type(optSurf->GetType());
1430  G4OpticalSurfaceModel model = geant4_surface_model(optSurf->GetModel());
1431  G4OpticalSurfaceFinish finish = geant4_surface_finish(optSurf->GetFinish());
1432  std::string name = make_NCName(optSurf->GetName());
1433  PrintLevel lvl = debugSurfaces ? ALWAYS : DEBUG;
1434  g4 = new G4OpticalSurface(name, model, finish, type, optSurf->GetValue());
1435  g4->SetSigmaAlpha(optSurf->GetSigmaAlpha());
1436  g4->SetPolish(optSurf->GetPolish());
1437 
1438  printout(lvl, "Geant4Converter",
1439  "++ Created OpticalSurface: %-18s type:%s model:%s finish:%s SigmaAlphs: %.3e Polish: %.3e",
1440  optSurf->GetName(),
1441  TGeoOpticalSurface::TypeToString(optSurf->GetType()),
1442  TGeoOpticalSurface::ModelToString(optSurf->GetModel()),
1443  TGeoOpticalSurface::FinishToString(optSurf->GetFinish()),
1444  optSurf->GetSigmaAlpha(), optSurf->GetPolish());
1447  G4MaterialPropertiesTable* tab = nullptr;
1448  TListIter itp(&optSurf->GetProperties());
1449  for(TObject* obj = itp.Next(); obj; obj = itp.Next()) {
1450  std::string exc_str;
1451  TNamed* named = (TNamed*)obj;
1452  TGDMLMatrix* matrix = info.manager->GetGDMLMatrix(named->GetTitle());
1453  const char* cptr = ::strstr(matrix->GetName(), GEANT4_TAG_IGNORE);
1454  if ( nullptr != cptr ) // Check if the property should not be passed to Geant4
1455  continue;
1456 
1457  if ( nullptr == tab ) {
1458  tab = new G4MaterialPropertiesTable();
1459  g4->SetMaterialPropertiesTable(tab);
1460  }
1461 
1464  if ( !v ) { // Error!
1465  except("Geant4OpticalSurface","++ Failed to convert opt.surface %s. Property table %s is not defined!",
1466  optSurf->GetName(), named->GetTitle());
1467  }
1468  int idx = -1;
1469  try {
1470  idx = tab->GetPropertyIndex(named->GetName());
1471  }
1472  catch(const std::exception& e) {
1473  exc_str = e.what();
1474  }
1475  catch(...) {
1476  }
1477  if ( idx < 0 ) {
1478  printout(ERROR, "Geant4Converter",
1479  "++ UNKNOWN Geant4 Property: %-20s %s [IGNORED]",
1480  exc_str.c_str(), named->GetName());
1481  continue;
1482  }
1483  // We need to convert the property from TGeo units to Geant4 units
1484  auto conv = g4PropertyConversion(idx);
1485  std::vector<double> bins(v->bins), vals(v->values);
1486  for(std::size_t i=0, count=v->bins.size(); i<count; ++i)
1487  bins[i] *= conv.first, vals[i] *= conv.second;
1488  G4MaterialPropertyVector* vec = new G4MaterialPropertyVector(&bins[0], &vals[0], bins.size());
1489  tab->AddProperty(named->GetName(), vec);
1490 
1491  printout(lvl, "Geant4Converter",
1492  "++ Property: %-20s [%ld x %ld] --> %s",
1493  named->GetName(), matrix->GetRows(), matrix->GetCols(), named->GetTitle());
1494  for(std::size_t i=0, count=v->bins.size(); i<count; ++i)
1495  printout(lvl, named->GetName(),
1496  " Geant4: %8.3g [MeV] TGeo: %8.3g [GeV] Conversion: %8.3g",
1497  bins[i], v->bins[i], conv.first);
1498  }
1501 #if ROOT_VERSION_CODE >= ROOT_VERSION(6,31,1)
1502  TListIter itc(&optSurf->GetConstProperties());
1503  for(TObject* obj = itc.Next(); obj; obj = itc.Next()) {
1504  std::string exc_str;
1505  TNamed* named = (TNamed*)obj;
1506  const char* cptr = ::strstr(named->GetName(), GEANT4_TAG_IGNORE);
1507  if ( nullptr != cptr ) {
1508  printout(INFO, name, "++ Ignore CONST property %s [%s].",
1509  named->GetName(), named->GetTitle());
1510  continue;
1511  }
1512  cptr = ::strstr(named->GetTitle(), GEANT4_TAG_IGNORE);
1513  if ( nullptr != cptr ) {
1514  printout(INFO, name,"++ Ignore CONST property %s [%s].",
1515  named->GetName(), named->GetTitle());
1516  continue;
1517  }
1518  Bool_t err = kFALSE;
1519  Double_t value = info.manager->GetProperty(named->GetTitle(),&err);
1520  if ( err != kFALSE ) {
1521  except(name,
1522  "++ FAILED to create G4 material %s [Cannot convert const property: %s]",
1523  optSurf->GetName(), named->GetName());
1524  }
1525  if ( nullptr == tab ) {
1526  tab = new G4MaterialPropertiesTable();
1527  g4->SetMaterialPropertiesTable(tab);
1528  }
1529  int idx = -1;
1530  try {
1531  idx = tab->GetConstPropertyIndex(named->GetName());
1532  }
1533  catch(const std::exception& e) {
1534  exc_str = e.what();
1535  }
1536  catch(...) {
1537  }
1538  if ( idx < 0 ) {
1539  printout(ERROR, name,
1540  "++ UNKNOWN Geant4 CONST Property: %-20s %s [IGNORED]",
1541  exc_str.c_str(), named->GetName());
1542  continue;
1543  }
1544  // We need to convert the property from TGeo units to Geant4 units
1545  double conv = g4ConstPropertyConversion(idx);
1546  printout(lvl, name, "++ CONST Property: %-20s %g * %g --> %g ",
1547  named->GetName(), value, conv, value * conv);
1548  tab->AddConstProperty(named->GetName(), value * conv);
1549  }
1550 #endif // ROOT_VERSION >= 6.31.1
1551  info.g4OpticalSurfaces[optSurf] = g4;
1552  }
1553  return g4;
1554 }
1555 
1558  TGeoSkinSurface* surf = (TGeoSkinSurface*)surface;
1560  G4LogicalSkinSurface* g4 = info.g4SkinSurfaces[surf];
1561  if ( !g4 ) {
1562  G4OpticalSurface* optSurf = info.g4OpticalSurfaces[OpticalSurface(surf->GetSurface())];
1563  G4LogicalVolume* v = info.g4Volumes[surf->GetVolume()];
1564  std::string name = make_NCName(surf->GetName());
1565  g4 = new G4LogicalSkinSurface(name, v, optSurf);
1566  printout(debugSurfaces ? ALWAYS : DEBUG, "Geant4Converter",
1567  "++ Created SkinSurface: %-18s optical:%s",
1568  surf->GetName(), surf->GetSurface()->GetName());
1569  info.g4SkinSurfaces[surf] = g4;
1570  }
1571  return g4;
1572 }
1573 
1576  TGeoBorderSurface* surf = (TGeoBorderSurface*)surface;
1578  G4LogicalBorderSurface* g4 = info.g4BorderSurfaces[surf];
1579  if ( !g4 ) {
1580  G4OpticalSurface* optSurf = info.g4OpticalSurfaces[OpticalSurface(surf->GetSurface())];
1581  G4VPhysicalVolume* n1 = info.g4Placements[surf->GetNode1()];
1582  G4VPhysicalVolume* n2 = info.g4Placements[surf->GetNode2()];
1583  std::string name = make_NCName(surf->GetName());
1584  g4 = new G4LogicalBorderSurface(name, n1, n2, optSurf);
1585  printout(debugSurfaces ? ALWAYS : DEBUG, "Geant4Converter",
1586  "++ Created BorderSurface: %-18s optical:%s",
1587  surf->GetName(), surf->GetSurface()->GetName());
1588  info.g4BorderSurfaces[surf] = g4;
1589  }
1590  return g4;
1591 }
1592 
1594 void Geant4Converter::printSensitive(SensitiveDetector sens_det, const std::set<const TGeoVolume*>& /* volumes */) const {
1596  std::set<const TGeoVolume*>& volset = info.sensitives[sens_det];
1597  SensitiveDetector sd = sens_det;
1598  std::stringstream str;
1599 
1600  printout(INFO, "Geant4Converter", "++ SensitiveDetector: %-18s %-20s Hits:%-16s", sd.name(), ("[" + sd.type() + "]").c_str(),
1601  sd.hitsCollection().c_str());
1602  str << " | " << "Cutoff:" << std::setw(6) << std::left
1603  << sd.energyCutoff() << std::setw(5) << std::right << volset.size()
1604  << " volumes ";
1605  if (sd.region().isValid())
1606  str << " Region:" << std::setw(12) << std::left << sd.region().name();
1607  if (sd.limits().isValid())
1608  str << " Limits:" << std::setw(12) << std::left << sd.limits().name();
1609  str << ".";
1610  printout(INFO, "Geant4Converter", str.str().c_str());
1611 
1612  for (const auto i : volset ) {
1613  std::map<Volume, G4LogicalVolume*>::iterator v = info.g4Volumes.find(i);
1614  if ( v != info.g4Volumes.end() ) {
1615  G4LogicalVolume* vol = (*v).second;
1616  str.str("");
1617  str << " | " << "Volume:" << std::setw(24) << std::left << vol->GetName() << " "
1618  << vol->GetNoDaughters() << " daughters.";
1619  printout(INFO, "Geant4Converter", str.str().c_str());
1620  }
1621  }
1622 }
1623 
1624 std::string printSolid(G4VSolid* sol) {
1625  std::stringstream str;
1626  if (typeid(*sol) == typeid(G4Box)) {
1627  const G4Box* b = (G4Box*) sol;
1628  str << "++ Box: x=" << b->GetXHalfLength() << " y=" << b->GetYHalfLength() << " z=" << b->GetZHalfLength();
1629  }
1630  else if (typeid(*sol) == typeid(G4Tubs)) {
1631  const G4Tubs* t = (const G4Tubs*) sol;
1632  str << " Tubs: Ri=" << t->GetInnerRadius() << " Ra=" << t->GetOuterRadius() << " z/2=" << t->GetZHalfLength() << " Phi="
1633  << t->GetStartPhiAngle() << "..." << t->GetDeltaPhiAngle();
1634  }
1635  return str.str();
1636 }
1637 
1639 void* Geant4Converter::printPlacement(const std::string& name, const TGeoNode* node) const {
1641  G4VPhysicalVolume* g4 = info.g4Placements[node];
1642  G4LogicalVolume* vol = info.g4Volumes[node->GetVolume()];
1643  G4LogicalVolume* mot = info.g4Volumes[node->GetMotherVolume()];
1644  G4VSolid* sol = vol->GetSolid();
1645  G4ThreeVector tr = g4->GetObjectTranslation();
1646  G4VSensitiveDetector* sd = vol->GetSensitiveDetector();
1647  if ( !sd ) {
1648  return g4;
1649  }
1650  std::stringstream str;
1651  str << "G4Cnv::placement: + " << name << " No:" << node->GetNumber() << " Vol:" << vol->GetName() << " Solid:"
1652  << sol->GetName();
1653  printout(outputLevel, "G4Placement", str.str().c_str());
1654  str.str("");
1655  str << " |" << " Loc: x=" << tr.x() << " y=" << tr.y() << " z=" << tr.z();
1656  printout(outputLevel, "G4Placement", str.str().c_str());
1657  printout(outputLevel, "G4Placement", printSolid(sol).c_str());
1658  str.str("");
1659  str << " |" << " Ndau:" << vol->GetNoDaughters()
1660  << " physvols." << " Mat:" << vol->GetMaterial()->GetName()
1661  << " Mother:" << (char*) (mot ? mot->GetName().c_str() : "---");
1662  printout(outputLevel, "G4Placement", str.str().c_str());
1663  str.str("");
1664  str << " |" << " SD:" << sd->GetName();
1665  printout(outputLevel, "G4Placement", str.str().c_str());
1666  return g4;
1667 }
1668 
1671  typedef std::map<const TGeoNode*, std::vector<TGeoNode*> > _DAU;
1672  TTimeStamp start;
1673  _DAU daughters;
1674  Geant4GeometryInfo& geo = this->init();
1675  World wrld = top.world();
1676 
1677  m_data->clear();
1678  m_set_data->clear();
1679  m_daughters = &daughters;
1680  geo.manager = &wrld.detectorDescription().manager();
1681  this->collect(top, geo);
1682  this->checkOverlaps = false;
1683  // We do not have to handle defines etc.
1684  // All positions and the like are not really named.
1685  // Hence, start creating the G4 objects for materials, solids and log volumes.
1686  handleArray(this, geo.manager->GetListOfGDMLMatrices(), &Geant4Converter::handleMaterialProperties);
1687  handleArray(this, geo.manager->GetListOfOpticalSurfaces(), &Geant4Converter::handleOpticalSurface);
1688 
1691  printout(outputLevel, "Geant4Converter", "++ Handled %ld solids.", geo.solids.size());
1692  handleRefs(this, geo.vis, &Geant4Converter::handleVis);
1693  printout(outputLevel, "Geant4Converter", "++ Handled %ld visualization attributes.", geo.vis.size());
1695  printout(outputLevel, "Geant4Converter", "++ Handled %ld limit sets.", geo.limits.size());
1697  printout(outputLevel, "Geant4Converter", "++ Handled %ld regions.", geo.regions.size());
1699  printout(outputLevel, "Geant4Converter", "++ Handled %ld volumes.", geo.volumes.size());
1701  // Now place all this stuff appropriately
1702  //handleRMap(this, *m_data, &Geant4Converter::handlePlacement);
1703  std::map<int, std::vector<const TGeoNode*> >::const_reverse_iterator i = m_data->rbegin();
1704  for ( ; i != m_data->rend(); ++i ) {
1705  for ( const TGeoNode* node : i->second ) {
1706  this->handlePlacement(node->GetName(), node);
1707  }
1708  }
1710  handleArray(this, geo.manager->GetListOfSkinSurfaces(), &Geant4Converter::handleSkinSurface);
1711  handleArray(this, geo.manager->GetListOfBorderSurfaces(), &Geant4Converter::handleBorderSurface);
1712  //==================== Fields
1714  if ( printSensitives ) {
1716  }
1717  if ( printPlacements ) {
1719  }
1720 
1721  m_daughters = nullptr;
1722  geo.setWorld(top.placement().ptr());
1723  geo.valid = true;
1724  TTimeStamp stop;
1725  printout(INFO, "Geant4Converter",
1726  "+++ Successfully converted geometry to Geant4. [%7.3f seconds]",
1727  stop.AsDouble()-start.AsDouble() );
1728  return *this;
1729 }
dd4hep::World
Handle class to hold the information of the top DetElement object 'world'.
Definition: World.h:31
dd4hep::detail::GeoHandler::m_daughters
std::map< const TGeoNode *, std::vector< TGeoNode * > > * m_daughters
Definition: GeoHandler.h:97
Geant4Field.h
dd4hep::Detector::manager
virtual TGeoManager & manager() const =0
Access the geometry manager of this instance.
dd4hep::sim::Geant4Converter::debugRegions
bool debugRegions
Property: Flag to debug regions during conversion mechanism.
Definition: Geant4Converter.h:47
dd4hep::sim::Geant4GeometryInfo::sensitives
std::map< SensitiveDetector, std::set< const TGeoVolume * > > sensitives
Definition: Geant4GeometryInfo.h:137
dd4hep::sim::convertShape< TGeoTrd2 >
G4VSolid * convertShape< TGeoTrd2 >(const TGeoShape *shape)
Definition: Geant4ShapeConverter.cpp:132
dd4hep::sim::convertShape< TGeoPgon >
G4VSolid * convertShape< TGeoPgon >(const TGeoShape *shape)
Definition: Geant4ShapeConverter.cpp:181
dd4hep::sim::Geant4Converter::debugMaterials
bool debugMaterials
Property: Flag to debug materials during conversion mechanism.
Definition: Geant4Converter.h:35
dd4hep::sim::Geant4UserLimits::minRange
Handler minRange
Handler map for MinRange limit.
Definition: Geant4UserLimits.h:71
dd4hep::Volume::Z_axis
@ Z_axis
Definition: Volumes.h:386
dd4hep::sim::Geant4Mapping::init
Geant4GeometryInfo & init()
Create and attach new data block. Delete old data block if present.
Definition: Geant4Mapping.cpp:48
dd4hep::detail::GeoHandlerTypes::GeometryInfo::solids
std::vector< TGeoShape * > solids
Definition: GeoHandler.h:62
dd4hep::sim::Geant4Converter::handleLimitSet
virtual void * handleLimitSet(LimitSet limitset, const std::set< const TGeoVolume * > &volumes) const
Convert the geometry type LimitSet into the corresponding Geant4 object(s).
Definition: Geant4Converter.cpp:1192
dd4hep::sim::convertShape< TGeoTrd1 >
G4VSolid * convertShape< TGeoTrd1 >(const TGeoShape *shape)
Definition: Geant4ShapeConverter.cpp:124
dd4hep::LimitSet::cuts
const std::set< Limit > & cuts() const
Accessor to limits container.
Definition: Objects.cpp:476
dd4hep::Atom
Handle class describing an element in the periodic table.
Definition: Objects.h:242
dd4hep::sim::Geant4Converter
Geometry converter from dd4hep to Geant 4.
Definition: Geant4Converter.h:32
dd4hep::sim::Geant4Converter::Geant4Converter
Geant4Converter(const Detector &description)
Initializing Constructor.
Definition: Geant4Converter.cpp:289
dd4hep::Region::wasThresholdSet
bool wasThresholdSet() const
Access was_threshold_set flag.
Definition: Objects.cpp:533
Volumes.h
dd4hep::Volume::NO_SMARTLESS_OPTIMIZATION
@ NO_SMARTLESS_OPTIMIZATION
Definition: Volumes.h:391
dd4hep::Volume::hasProperties
bool hasProperties() const
Check for existence of properties.
Definition: Volumes.cpp:1327
dd4hep::World::detectorDescription
Detector & detectorDescription() const
Access the detector descrion tree.
Definition: World.cpp:19
dd4hep::sim::convertShape< TGeoPcon >
G4VSolid * convertShape< TGeoPcon >(const TGeoShape *shape)
Definition: Geant4ShapeConverter.cpp:193
v
View * v
Definition: MultiView.cpp:28
dd4hep::sim::convertShape< TGeoHype >
G4VSolid * convertShape< TGeoHype >(const TGeoShape *shape)
Definition: Geant4ShapeConverter.cpp:140
dd4hep::SensitiveDetector
Handle class to hold the information of a sensitive detector.
Definition: DetElement.h:44
dd4hep::sim::Geant4GeometryInfo::g4Regions
std::map< Region, G4Region * > g4Regions
Definition: Geant4GeometryInfo.h:133
dd4hep::sim::Geant4Converter::debugLimits
bool debugLimits
Property: Flag to debug LimitSets during conversion mechanism.
Definition: Geant4Converter.h:49
Detector.h
dd4hep::sim::Geant4Converter::debugElements
bool debugElements
Property: Flag to debug elements during conversion mechanism.
Definition: Geant4Converter.h:37
dd4hep::sim::convertShape< TGeoBBox >
G4VSolid * convertShape< TGeoBBox >(const TGeoShape *shape)
Definition: Geant4ShapeConverter.cpp:75
dd4hep::info
std::size_t info(const std::string &src, const std::string &msg)
Definition: RootDictionary.h:65
dd4hep::Detector::Properties
std::map< std::string, PropertyValues > Properties
Definition: Detector.h:95
dd4hep::exception
void exception(const std::string &src, const std::string &msg)
Definition: RootDictionary.h:69
dd4hep::sim::Geant4Mapping::data
Geant4GeometryInfo & data() const
Access to the data pointer.
Definition: Geant4Mapping.h:58
dd4hep::sim::convertShape< TGeoTessellated >
G4VSolid * convertShape< TGeoTessellated >(const TGeoShape *shape)
Definition: Geant4ShapeConverter.cpp:253
dd4hep::PlacedVolume
Handle class holding a placed volume (also called physical volume)
Definition: Volumes.h:163
dd4hep::VisAttr
Handle class describing visualization attributes.
Definition: Objects.h:324
dd4hep::Region::storeSecondaries
bool storeSecondaries() const
Access secondaries flag.
Definition: Objects.cpp:525
dd4hep::sim::Geant4PlacementParameterisation
Class to dump the records of the intrinsic Geant4 event model.
Definition: Geant4PlacementParameterisation.h:39
dd4hep::DetElement::placement
PlacedVolume placement() const
Access to the physical volume of this detector element.
Definition: DetElement.cpp:321
dd4hep::sim::Geant4AssemblyVolume
Hack! Wrapper around G4AssemblyVolume to access protected members.
Definition: Geant4AssemblyVolume.h:41
CM_2_MM
#define CM_2_MM
Definition: ParticleActors.cpp:37
dd4hep::LimitSet::limits
const std::set< Limit > & limits() const
Accessor to limits container.
Definition: Objects.cpp:464
dd4hep::sim::Geant4Converter::handleSkinSurface
void * handleSkinSurface(TObject *surface) const
Convert the skin surface to Geant4.
Definition: Geant4Converter.cpp:1557
dd4hep::sim::convertShape< TGeoEltu >
G4VSolid * convertShape< TGeoEltu >(const TGeoShape *shape)
Definition: Geant4ShapeConverter.cpp:103
Geant4ShapeConverter.h
delta
const Delta * delta
Definition: AlignmentsCalculator.cpp:67
printSolid
std::string printSolid(G4VSolid *sol)
Definition: Geant4Converter.cpp:1624
dd4hep::sim::Geant4AssemblyVolume::placeVolume
long placeVolume(const TGeoNode *n, G4LogicalVolume *pPlacedVolume, G4Transform3D &transformation)
Place logical daughter volume into the assembly.
Definition: Geant4AssemblyVolume.cpp:44
dd4hep::sim::Geant4Converter::outputLevel
PrintLevel outputLevel
Property: Output level for debug printing.
Definition: Geant4Converter.h:61
dd4hep::sim::Geant4Converter::debugSurfaces
bool debugSurfaces
Property: Flag to debug surfaces during conversion mechanism.
Definition: Geant4Converter.h:51
dd4hep::Detector::PropertyValues
std::map< std::string, std::string > PropertyValues
Definition: Detector.h:94
dd4hep::Handle::isValid
bool isValid() const
Check the validity of the object held by the handle.
Definition: Handle.h:128
DetectorInterna.h
dd4hep::_toString
std::string _toString(bool value)
String conversions: boolean value to string.
Definition: Handle.cpp:332
dd4hep::sim::Geant4Converter::debugShapes
bool debugShapes
Property: Flag to debug shapes during conversion mechanism.
Definition: Geant4Converter.h:39
dd4hep::sim::Geant4AssemblyVolume::Chain
std::vector< const TGeoNode * > Chain
Definition: Geant4AssemblyVolume.h:45
dd4hep::Solid_type< TGeoShape >
dd4hep::Detector::worldVolume
virtual Volume worldVolume() const =0
Return handle to the world volume containing everything.
dd4hep::detail::GeoHandlerTypes::GeometryInfo::vis
std::set< VisAttr > vis
Definition: GeoHandler.h:66
dd4hep::sim::Geant4GeometryInfo::PropertyVector::bins
std::vector< double > bins
Definition: Geant4GeometryInfo.h:123
dd4hep::Handle::name
const char * name() const
Access the object name (or "" if not supported by the object)
Geant4UserLimits.h
dd4hep::sim::convertShape< TGeoXtru >
G4VSolid * convertShape< TGeoXtru >(const TGeoShape *shape)
Definition: Geant4ShapeConverter.cpp:164
dd4hep::Region::limits
std::vector< std::string > & limits() const
Access references to user limits.
Definition: Objects.cpp:510
dd4hep::sim::Geant4GeometryInfo::manager
TGeoManager * manager
Definition: Geant4GeometryInfo.h:111
dd4hep::sim::convertShape< TGeoCone >
G4VSolid * convertShape< TGeoCone >(const TGeoShape *shape)
Definition: Geant4ShapeConverter.cpp:205
epsilon
const double epsilon
Definition: test_cellid_position_converter.cpp:41
dd4hep::sim::Geant4GeometryInfo::setWorld
void setWorld(const TGeoNode *node)
Set the world volume.
Definition: Geant4GeometryInfo.cpp:59
dd4hep::VisAttr::alpha
float alpha() const
Get alpha value.
Definition: Objects.cpp:371
dd4hep::sim::Geant4UserLimits::minEKine
Handler minEKine
Handler map for MinEKine limit.
Definition: Geant4UserLimits.h:69
dd4hep::sim::Geant4UserLimits::maxTrackLength
Handler maxTrackLength
Handler map for MaxTrackLength limit.
Definition: Geant4UserLimits.h:65
G4UserLimits
Class of the Geant4 toolkit. See http://www-geant4.kek.jp/Reference.
Definition: Geant4Classes.h:23
dd4hep::detail::GeoHandler::m_propagateRegions
bool m_propagateRegions
Definition: GeoHandler.h:90
dd4hep::VisAttr::lineStyle
int lineStyle() const
Get line style.
Definition: Objects.cpp:351
dd4hep::Material
Handle class describing a material.
Definition: Objects.h:272
dd4hep::sim::Geant4AssemblyVolume::imprint
void imprint(const Geant4Converter &cnv, const TGeoNode *n, Chain chain, Geant4AssemblyVolume *pAssembly, G4LogicalVolume *pMotherLV, G4Transform3D &transformation, G4bool surfCheck)
Expand all daughter placements and expand the contained assemblies to imprints.
Definition: Geant4AssemblyVolume.cpp:68
dd4hep::sim::Geant4Converter::debugPlacements
bool debugPlacements
Property: Flag to debug placements during conversion mechanism.
Definition: Geant4Converter.h:43
dd4hep::VisAttr::showDaughters
bool showDaughters() const
Get Flag to show/hide daughter elements.
Definition: Objects.cpp:331
dd4hep::Region::threshold
double threshold() const
Access production threshold.
Definition: Objects.cpp:520
dd4hep::detail::GeoHandler::m_set_data
std::map< int, std::set< const TGeoNode * > > * m_set_data
redundant container with std::set (for lookup purpose)
Definition: GeoHandler.h:95
dd4hep::sim::Geant4GeometryInfo::PropertyVector::title
std::string title
Definition: Geant4GeometryInfo.h:125
dd4hep::sim::Geant4Converter::create
Geant4Converter & create(DetElement top)
Create geometry conversion.
Definition: Geant4Converter.cpp:1670
Geant4AssemblyVolume.h
dd4hep::sim::convertShape< TwistedTubeObject >
G4VSolid * convertShape< TwistedTubeObject >(const TGeoShape *shape)
Definition: Geant4ShapeConverter.cpp:108
dd4hep::DetElement
Handle class describing a detector element.
Definition: DetElement.h:188
dd4hep::sim::Geant4Converter::handleBorderSurface
void * handleBorderSurface(TObject *surface) const
Convert the border surface to Geant4.
Definition: Geant4Converter.cpp:1575
dd4hep::Volume::REPLICATED
@ REPLICATED
Definition: Volumes.h:381
dd4hep::sim::Geant4UserLimits::maxTime
Handler maxTime
Handler map for MaxTime limit.
Definition: Geant4UserLimits.h:67
dd4hep::Volume
Handle class holding a placed volume (also called physical volume)
Definition: Volumes.h:370
dd4hep::Volume::Y_axis
@ Y_axis
Definition: Volumes.h:385
dd4hep::detail::GeoHandler
The base class for all dd4hep geometry crawlers.
Definition: GeoHandler.h:87
dd4hep::sim::Geant4GeometryInfo::limits
std::map< LimitSet, std::set< const TGeoVolume * > > limits
Definition: Geant4GeometryInfo.h:139
dd4hep::sim::Geant4Mapping
Geometry mapping from dd4hep to Geant 4.
Definition: Geant4Mapping.h:35
dd4hep::sim::Geant4Converter::checkOverlaps
bool checkOverlaps
Property: Check geometrical overlaps for volume placements and G4 imprints.
Definition: Geant4Converter.h:59
mix
#define mix(a, b, c)
Definition: Geant4EventSeed.h:113
dd4hep::sim::Geant4Converter::~Geant4Converter
virtual ~Geant4Converter()
Standard destructor.
Definition: Geant4Converter.cpp:304
dd4hep::sim::Geant4GeometryInfo::PropertyVector::values
std::vector< double > values
Definition: Geant4GeometryInfo.h:124
dd4hep::sim::g4Transform
void g4Transform(const double *translation, const double *rotation, G4Transform3D &transform)
These conversions automatically apply the conversion from CM to MM!
Definition: Geant4Helpers.cpp:91
G4VSensitiveDetector
Class of the Geant4 toolkit. See http://www-geant4.kek.jp/Reference.
Definition: Geant4Classes.h:59
dd4hep::LimitSet
Handle class describing a set of limits as they are used for simulation.
Definition: Objects.h:425
dd4hep::sim::Geant4GeometryInfo::PropertyVector::name
std::string name
Definition: Geant4GeometryInfo.h:125
dd4hep::SensitiveDetector::hitsCollection
const std::string & hitsCollection() const
Access the hits collection name.
Definition: DetElement.cpp:447
dd4hep::sim::Geant4Converter::handleMaterial
virtual void * handleMaterial(const std::string &name, Material medium) const
Convert the geometry type material into the corresponding Geant4 object(s).
Definition: Geant4Converter.cpp:350
ShapesInterna.h
dd4hep::Volume::limitSet
LimitSet limitSet() const
Access to the limit set.
Definition: Volumes.cpp:1304
dd4hep::VisAttr::DASHED
@ DASHED
Definition: Objects.h:327
DetectorTools.h
dd4hep::Volume::VETO_SIMU
@ VETO_SIMU
Definition: Volumes.h:375
TO_G4_TYPE
#define TO_G4_TYPE(x)
dd4hep::Volume::region
Region region() const
Access to the handle to the region structure.
Definition: Volumes.cpp:1285
dd4hep::sim::Geant4UserLimits::Handler::particleLimits
std::map< const G4ParticleDefinition *, double > particleLimits
Handler particle ids for the limit (pdgID)
Definition: Geant4UserLimits.h:51
dd4hep::sim::convertShape< TGeoParaboloid >
G4VSolid * convertShape< TGeoParaboloid >(const TGeoShape *shape)
Definition: Geant4ShapeConverter.cpp:219
Geant4PlacementParameterisation.h
TNamed
Class of the ROOT toolkit. See http://root.cern.ch/root/htmldoc/ClassIndex.html.
Definition: ROOTClasses.h:37
dd4hep::Volume::testFlagBit
bool testFlagBit(unsigned int bit) const
Test the user flag bit.
Definition: Volumes.cpp:709
Plugins.h
dd4hep::sim::Geant4Converter::handleProperties
void handleProperties(Detector::Properties &prp) const
Handle the geant 4 specific properties.
Definition: Geant4Converter.cpp:1260
dd4hep::LimitSet::Set
std::set< Limit > Set
Iterator definitions.
Definition: Objects.h:428
dd4hep::Region
Handle class describing a region as used in simulation.
Definition: Objects.h:462
dd4hep::sim::convertShape< TGeoPara >
G4VSolid * convertShape< TGeoPara >(const TGeoShape *shape)
Definition: Geant4ShapeConverter.cpp:156
dd4hep::sim::Geant4Converter::printSensitive
virtual void printSensitive(SensitiveDetector sens_det, const std::set< const TGeoVolume * > &volumes) const
Print the geometry type SensitiveDetector.
Definition: Geant4Converter.cpp:1594
dd4hep::VisAttr::rgb
bool rgb(float &red, float &green, float &blue) const
Get RGB values of the color (if valid)
Definition: Objects.cpp:396
Shapes.h
dd4hep::sim::Geant4GeometryInfo::g4Isotopes
Geant4GeometryMaps::IsotopeMap g4Isotopes
Definition: Geant4GeometryInfo.h:112
dd4hep::detail::GeoHandler::m_data
std::map< int, std::vector< const TGeoNode * > > * m_data
actual container with std::vector (preserves order)
Definition: GeoHandler.h:93
dd4hep::sim::Geant4UserLimits::maxStepLength
Handler maxStepLength
Handler map for MaxStepLength limit.
Definition: Geant4UserLimits.h:63
Geant4Helpers.h
dd4hep::Volume::smartlessValue
unsigned char smartlessValue() const
access the smartless option for G4 voxelization
Definition: Volumes.cpp:736
dd4hep::sim::convertShape< TGeoTrap >
G4VSolid * convertShape< TGeoTrap >(const TGeoShape *shape)
Definition: Geant4ShapeConverter.cpp:237
dd4hep::sim::convertShape< TGeoArb8 >
G4VSolid * convertShape< TGeoArb8 >(const TGeoShape *shape)
Definition: Geant4ShapeConverter.cpp:147
TO_G4_FINISH
#define TO_G4_FINISH(x)
dd4hep::Detector::limitSet
virtual LimitSet limitSet(const std::string &name) const =0
Retrieve a limitset by its name from the detector description.
dd4hep::sim::Geant4UserLimits::Handler::defaultValue
double defaultValue
Default value (either from base class or value if Limit.particles='*')
Definition: Geant4UserLimits.h:49
dd4hep::sim::Geant4Converter::handleOpticalSurface
void * handleOpticalSurface(TObject *surface) const
Convert the optical surface to Geant4.
Definition: Geant4Converter.cpp:1424
dd4hep::sim::convertShape< TGeoShapeAssembly >
G4VSolid * convertShape< TGeoShapeAssembly >(const TGeoShape *)
Definition: Geant4ShapeConverter.cpp:71
dd4hep::sim::convertShape< TGeoConeSeg >
G4VSolid * convertShape< TGeoConeSeg >(const TGeoShape *shape)
Definition: Geant4ShapeConverter.cpp:211
dd4hep::sim::Geant4Converter::handleAssembly
virtual void * handleAssembly(const std::string &name, const TGeoNode *node) const
Dump volume placement in GDML format to output stream.
Definition: Geant4Converter.cpp:872
dd4hep::sim::Geant4Converter::handleVis
virtual void * handleVis(const std::string &name, VisAttr vis) const
Convert the geometry visualisation attributes to the corresponding Geant4 object(s).
Definition: Geant4Converter.cpp:1234
dd4hep::Region::cut
double cut() const
Access cut value.
Definition: Objects.cpp:515
dd4hep::sim::Geant4Converter::handleVolume
virtual void * handleVolume(const std::string &name, const TGeoVolume *volume) const
Convert the geometry type logical volume into the corresponding Geant4 object(s).
Definition: Geant4Converter.cpp:742
dd4hep::SensitiveDetector::limits
LimitSet limits() const
Access to the limit set of the sensitive detector (not mandatory).
Definition: DetElement.cpp:493
dd4hep::sim::convertShape< TGeoCtub >
G4VSolid * convertShape< TGeoCtub >(const TGeoShape *shape)
Definition: Geant4ShapeConverter.cpp:91
dd4hep::sim::convertShape< TGeoTubeSeg >
G4VSolid * convertShape< TGeoTubeSeg >(const TGeoShape *shape)
Definition: Geant4ShapeConverter.cpp:85
dd4hep::sim::Geant4GeometryInfo::g4Limits
std::map< LimitSet, G4UserLimits * > g4Limits
Definition: Geant4GeometryInfo.h:135
dd4hep::sim::Geant4Converter::debugVolumes
bool debugVolumes
Property: Flag to debug volumes during conversion mechanism.
Definition: Geant4Converter.h:41
dd4hep::sim::Geant4Converter::handleSolid
virtual void * handleSolid(const std::string &name, const TGeoShape *volume) const
Convert the geometry type solid into the corresponding Geant4 object(s).
Definition: Geant4Converter.cpp:597
dd4hep::SensitiveDetector::type
std::string type() const
Access the type of the sensitive detector.
Definition: DetElement.cpp:409
dd4hep::sim::Geant4Converter::collectVolume
virtual void * collectVolume(const std::string &name, const TGeoVolume *volume) const
Dump logical volume in GDML format to output stream.
Definition: Geant4Converter.cpp:852
dd4hep::sim::Geant4Mapping::m_detDesc
const Detector & m_detDesc
Definition: Geant4Mapping.h:37
dd4hep::SensitiveDetector::region
Region region() const
Access to the region setting of the sensitive detector (not mandatory)
Definition: DetElement.cpp:482
dd4hep::sim::Geant4Converter::printSensitives
bool printSensitives
Property: Flag to dump all sensitives after the conversion procedure.
Definition: Geant4Converter.h:56
dd4hep::sim::Geant4GeometryInfo::g4Solids
Geant4GeometryMaps::SolidMap g4Solids
Definition: Geant4GeometryInfo.h:115
dd4hep::sim::Geant4GeometryInfo::valid
bool valid
Definition: Geant4GeometryInfo.h:142
dd4hep::sim
Namespace for the Geant4 based simulation part of the AIDA detector description toolkit.
Definition: Geant4Output2EDM4hep.cpp:49
dd4hep::sim::convertShape< TGeoTorus >
G4VSolid * convertShape< TGeoTorus >(const TGeoShape *shape)
Definition: Geant4ShapeConverter.cpp:231
dd4hep::VisAttr::visible
bool visible() const
Get visibility flag.
Definition: Objects.cpp:341
dd4hep::sim::Geant4Converter::handlePlacement
virtual void * handlePlacement(const std::string &name, const TGeoNode *node) const
Convert the geometry type volume placement into the corresponding Geant4 object(s).
Definition: Geant4Converter.cpp:945
dd4hep::sim::Geant4Converter::handleIsotope
virtual void * handleIsotope(const std::string &name, const TGeoIsotope *iso) const
Handle the conversion of isotopes.
Definition: Geant4Converter.cpp:308
dd4hep::sim::Geant4GeometryInfo
Concreate class holding the relation information between geant4 objects and dd4hep objects.
Definition: Geant4GeometryInfo.h:93
dd4hep::VisAttr::SOLID
@ SOLID
Definition: Objects.h:327
dd4hep::Handle::ptr
T * ptr() const
Access to the held object.
Definition: Handle.h:153
ObjectsInterna.h
dd4hep::Volume::type
const char * type() const
Access the object type from the class information.
Definition: Volumes.cpp:663
PropertyTable.h
dd4hep::Region::useDefaultCut
bool useDefaultCut() const
Access use_default_cut flag.
Definition: Objects.cpp:529
dd4hep::SensitiveDetector::energyCutoff
double energyCutoff() const
Access energy cut off.
Definition: DetElement.cpp:436
TObject
Class of the ROOT toolkit. See http://root.cern.ch/root/htmldoc/ClassIndex.html.
Definition: ROOTClasses.h:41
dd4hep::sim::Geant4Converter::handleMaterialProperties
virtual void * handleMaterialProperties(TObject *matrix) const
Convert the geometry type material into the corresponding Geant4 object(s).
Definition: Geant4Converter.cpp:1295
dd4hep
Namespace for the AIDA detector description toolkit.
Definition: AlignmentsCalib.h:28
dd4hep::sim::Geant4Converter::debugReflections
bool debugReflections
Property: Flag to debug reflections during conversion mechanism.
Definition: Geant4Converter.h:45
dd4hep::VisAttr::WIREFRAME
@ WIREFRAME
Definition: Objects.h:327
dd4hep::sim::Geant4Converter::handleRegion
virtual void * handleRegion(Region region, const std::set< const TGeoVolume * > &volumes) const
Convert the geometry type region into the corresponding Geant4 object(s).
Definition: Geant4Converter.cpp:1114
det
DetElement::Object * det
Definition: AlignmentsCalculator.cpp:66
dd4hep::Solid_type::type
const char * type() const
Access to shape type (The TClass name of the ROOT implementation)
Definition: Shapes.cpp:82
dd4hep::PlacedVolume::data
Object * data() const
Check if placement is properly instrumented.
Definition: Volumes.cpp:447
dd4hep::Detector
The main interface to the dd4hep detector description package.
Definition: Detector.h:90
dd4hep::sim::Geant4GeometryInfo::regions
std::map< Region, std::set< const TGeoVolume * > > regions
Definition: Geant4GeometryInfo.h:138
dd4hep::Volume::getProperty
std::string getProperty(const std::string &nam, const std::string &default_val="") const
Access property value. Returns default_value if the property is not present.
Definition: Volumes.cpp:1348
dd4hep::sim::Geant4AssemblyVolume::placeAssembly
long placeAssembly(const TGeoNode *n, Geant4AssemblyVolume *pPlacedVolume, G4Transform3D &transformation)
Place daughter assembly into the assembly
Definition: Geant4AssemblyVolume.cpp:56
TO_G4_MODEL
#define TO_G4_MODEL(x)
dd4hep::detail::tools::copy
void copy(Alignment from, Alignment to)
Copy alignment object from source object.
Definition: AlignmentTools.cpp:43
dd4hep::sim::Geant4GeometryInfo::g4Elements
Geant4GeometryMaps::ElementMap g4Elements
Definition: Geant4GeometryInfo.h:113
dd4hep::sim::Geant4UserLimits
Helper to dump Geant4 volume hierarchy.
Definition: Geant4UserLimits.h:38
dd4hep::Volume::visAttributes
VisAttr visAttributes() const
Access the visualisation attributes.
Definition: Volumes.cpp:1239
DD4hepUnits.h
dd4hep::sim::Geant4Converter::printPlacements
bool printPlacements
Property: Flag to dump all placements after the conversion procedure.
Definition: Geant4Converter.h:54
dd4hep::detail::GeoHandlerTypes::GeometryInfo::volumes
std::vector< Volume > volumes
Definition: GeoHandler.h:65
dd4hep::DetElement::world
DetElement world() const
Access to the world object. Only possible once the geometry is closed.
Definition: DetElement.cpp:245
Printout.h
dd4hep::sim::Geant4GeometryInfo::PropertyVector
Definition: Geant4GeometryInfo.h:122
dd4hep::Volume::X_axis
@ X_axis
Definition: Volumes.h:384
dd4hep::sim::convertShape< TGeoSphere >
G4VSolid * convertShape< TGeoSphere >(const TGeoShape *shape)
Definition: Geant4ShapeConverter.cpp:224
dd4hep::sim::Geant4Converter::handleElement
virtual void * handleElement(const std::string &name, Atom element) const
Convert the geometry type element into the corresponding Geant4 object(s).
Definition: Geant4Converter.cpp:322
Geant4Converter.h
dd4hep::sim::convertShape< TGeoTube >
G4VSolid * convertShape< TGeoTube >(const TGeoShape *shape)
Definition: Geant4ShapeConverter.cpp:80
dd4hep::OpticalSurface
Class to support the handling of optical surfaces.
Definition: OpticalSurfaces.h:42
handle
void handle(const O *o, const C &c, F pmf)
Definition: LCDDConverter.cpp:1105
dd4hep::Volume::sensitiveDetector
Handle< NamedObject > sensitiveDetector() const
Access to the handle to the sensitive detector.
Definition: Volumes.cpp:1316
handleRMap
void handleRMap(const O *o, const C &c, F pmf)
Definition: LCDDConverter.cpp:1117
dd4hep::Detector::properties
virtual Properties & properties() const =0
Access to properties map.
dd4hep::sim::Geant4Converter::printPlacement
virtual void * printPlacement(const std::string &name, const TGeoNode *node) const
Print Geant4 placement.
Definition: Geant4Converter.cpp:1639
dd4hep::detail::GeoHandler::collect
GeoHandler & collect(DetElement top)
Collect geometry information from traversal.
Definition: GeoHandler.cpp:101
handleMap
void handleMap(const O *o, const C &c, F pmf)
Definition: LCDDConverter.cpp:1112
dd4hep::sim::Geant4UserLimits::Handler
Helper class to one limit type.
Definition: Geant4UserLimits.h:46