DD4hep  1.31.0
Detector Description Toolkit for High Energy Physics
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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",
749  "++ Volume %s not converted [Veto'ed for simulation]",
750  volume->GetName());
751  return nullptr;
752  }
753  else if (volIt == info.g4Volumes.end() ) {
754  const char* vnam = volume->GetName();
755  TGeoMedium* med = volume->GetMedium();
756  Solid sh = volume->GetShape();
757  bool is_assembly = sh->IsA() == TGeoShapeAssembly::Class() || volume->IsAssembly();
758 
759  printout(lvl, "Geant4Converter", "++ Convert Volume %-32s: %p %s/%s assembly:%s",
760  vnam, volume, sh.type(), _v.type(), yes_no(is_assembly));
761  if ( is_assembly ) {
762  return nullptr;
763  }
764  Region reg = _v.region();
765  LimitSet lim = _v.limitSet();
766  VisAttr vis = _v.visAttributes();
767  G4Region* g4region = reg.isValid() ? info.g4Regions[reg] : nullptr;
768  G4UserLimits* g4limits = lim.isValid() ? info.g4Limits[lim] : nullptr;
769  G4VSolid* g4solid = (G4VSolid*) handleSolid(sh->GetName(), sh);
770  G4Material* g4medium = (G4Material*) handleMaterial(med->GetName(), Material(med));
772  if ( !g4solid ) {
773  except("G4Converter","++ No Geant4 Solid present for volume: %s", vnam);
774  }
775  else if ( !g4medium ) {
776  except("G4Converter","++ No Geant4 material present for volume: %s", vnam);
777  }
778  else if ( reg.isValid() && !g4region ) {
779  except("G4Cnv::volume["+name+"]"," ++ Failed to access Geant4 region %s.", reg.name());
780  }
781  else if ( lim.isValid() && !g4limits ) {
782  except("G4Cnv::volume["+name+"]","++ FATAL Failed to access Geant4 user limits %s.", lim.name());
783  }
784  else if ( g4limits ) {
785  printout(lvl, "Geant4Converter", "++ Volume + Apply LIMITS settings: %-24s to volume %s.",
786  lim.name(), vnam);
787  }
788 
789  G4LogicalVolume* g4vol = nullptr;
790  if( _v.hasProperties() && !_v.getProperty(GEANT4_TAG_PLUGIN,"").empty() ) {
791  Detector* det = const_cast<Detector*>(&m_detDesc);
792  std::string plugin = _v.getProperty(GEANT4_TAG_PLUGIN,"");
793  g4vol = PluginService::Create<G4LogicalVolume*>(plugin, det, _v, g4solid, g4medium);
794  if ( !g4vol ) {
795  except("G4Cnv::volume["+name+"]","++ FATAL Failed to call plugin to create logical volume.");
796  }
797  }
798  else {
799  g4vol = new G4LogicalVolume(g4solid, g4medium, vnam, nullptr, nullptr, nullptr);
800  }
801  PrintLevel plevel = (debugVolumes||debugRegions||debugLimits) ? ALWAYS : outputLevel;
803  unsigned char smart_less_value = _v.smartlessValue();
804  if( smart_less_value != Volume::NO_SMARTLESS_OPTIMIZATION ) {
805  printout(ALWAYS, "Geant4Converter",
806  "++ Volume %s Set Smartless value to %d",
807  vnam, int(smart_less_value));
808  g4vol->SetSmartless( smart_less_value );
809  }
811  if( g4limits ) {
812  g4vol->SetUserLimits(g4limits);
813  }
814  if( g4region ) {
815  printout(plevel, "Geant4Converter",
816  "++ Volume + Apply REGION settings: %-24s to volume %s.",
817  reg.name(), vnam);
818  // Handle the region settings for the world volume seperately.
819  // Geant4 does NOT WANT any regions assigned to the workd volume.
820  // The world's region is created in the G4RunManagerKernel!
821  if ( _v == m_detDesc.worldVolume() ) {
822  const char* wrd_nam = "DefaultRegionForTheWorld";
823  const char* src_nam = g4region->GetName().c_str();
824  auto* world_region = G4RegionStore::GetInstance()->GetRegion(wrd_nam, false);
825  if ( auto* cuts = g4region->GetProductionCuts() ) {
826  world_region->SetProductionCuts(cuts);
827  printout(plevel, "Geant4Converter",
828  "++ Volume %s Region: %s. Apply production cuts from %s",
829  vnam, wrd_nam, src_nam);
830  }
831  if ( auto* lims = g4region->GetUserLimits() ) {
832  world_region->SetUserLimits(lims);
833  printout(plevel, "Geant4Converter",
834  "++ Volume %s Region: %s. Apply user limits from %s",
835  vnam, wrd_nam, src_nam);
836  }
837  }
838  else {
839  g4vol->SetRegion(g4region);
840  g4region->AddRootLogicalVolume(g4vol);
841  }
842  }
843  G4VisAttributes* g4vattr = vis.isValid()
844  ? (G4VisAttributes*)handleVis(vis.name(), vis) : nullptr;
845  if ( g4vattr ) {
846  g4vol->SetVisAttributes(g4vattr);
847  }
848  info.g4Volumes[volume] = g4vol;
849  printout(lvl, "Geant4Converter",
850  "++ Volume + %s converted: %p ---> G4: %p", vnam, volume, g4vol);
851  }
852  return nullptr;
853 }
854 
856 void* Geant4Converter::collectVolume(const std::string& /* name */, const TGeoVolume* volume) const {
858  Volume _v(volume);
859  Region reg = _v.region();
860  LimitSet lim = _v.limitSet();
862  bool world = (volume == m_detDesc.worldVolume().ptr());
863 
864  if ( !world ) {
865  if ( lim.isValid() )
866  info.limits[lim].insert(volume);
867  if ( reg.isValid() )
868  info.regions[reg].insert(volume);
869  if ( det.isValid() )
870  info.sensitives[det].insert(volume);
871  }
872  return (void*)volume;
873 }
874 
876 void* Geant4Converter::handleAssembly(const std::string& name, const TGeoNode* node) const {
877  TGeoVolume* mot_vol = node->GetVolume();
878  PrintLevel lvl = debugVolumes ? ALWAYS : outputLevel;
879  if ( mot_vol->IsA() != TGeoVolumeAssembly::Class() ) {
880  return nullptr;
881  }
882  Volume _v(mot_vol);
883  if ( _v.testFlagBit(Volume::VETO_SIMU) ) {
884  printout(lvl, "Geant4Converter", "++ AssemblyNode %s not converted [Veto'ed for simulation]",node->GetName());
885  return nullptr;
886  }
888  Geant4AssemblyVolume* g4 = info.g4AssemblyVolumes[node];
889  if ( g4 ) {
890  printout(ALWAYS, "Geant4Converter", "+++ Assembly: **** : Re-using existing assembly: %s",node->GetName());
891  }
892  if ( !g4 ) {
893  g4 = new Geant4AssemblyVolume();
894  for(Int_t i=0; i < mot_vol->GetNdaughters(); ++i) {
895  TGeoNode* dau = mot_vol->GetNode(i);
896  TGeoVolume* dau_vol = dau->GetVolume();
897  TGeoMatrix* tr = dau->GetMatrix();
898  G4Transform3D transform;
899 
900  g4Transform(tr, transform);
901  if ( is_left_handed(tr) ) {
902  G4Scale3D scale;
903  G4Rotate3D rot;
904  G4Translate3D trans;
905  transform.getDecomposition(scale, rot, trans);
906  printout(debugReflections ? ALWAYS : lvl, "Geant4Converter",
907  "++ Placing reflected ASSEMBLY. dau:%s to mother %s "
908  "Tr:x=%8.1f y=%8.1f z=%8.1f Scale:x=%4.2f y=%4.2f z=%4.2f",
909  dau_vol->GetName(), mot_vol->GetName(),
910  transform.dx(), transform.dy(), transform.dz(),
911  scale.xx(), scale.yy(), scale.zz());
912  }
913 
914  if ( dau_vol->IsA() == TGeoVolumeAssembly::Class() ) {
915  Geant4GeometryMaps::AssemblyMap::iterator ia = info.g4AssemblyVolumes.find(dau);
916  if ( ia == info.g4AssemblyVolumes.end() ) {
917  printout(FATAL, "Geant4Converter", "+++ Invalid child assembly at %s : %d parent: %s child:%s",
918  __FILE__, __LINE__, name.c_str(), dau->GetName());
919  delete g4;
920  return nullptr;
921  }
922  g4->placeAssembly(dau, (*ia).second, transform);
923  printout(lvl, "Geant4Converter", "+++ Assembly: AddPlacedAssembly %p: dau:%s "
924  "to mother %s Tr:x=%8.3f y=%8.3f z=%8.3f",
925  (void*)dau_vol, dau_vol->GetName(), mot_vol->GetName(),
926  transform.dx(), transform.dy(), transform.dz());
927  }
928  else {
929  Geant4GeometryMaps::VolumeMap::iterator iv = info.g4Volumes.find(dau_vol);
930  if ( iv == info.g4Volumes.end() ) {
931  printout(FATAL,"Geant4Converter", "+++ Invalid child volume at %s : %d parent: %s child:%s",
932  __FILE__, __LINE__, name.c_str(), dau->GetName());
933  except("Geant4Converter", "+++ Invalid child volume at %s : %d parent: %s child:%s",
934  __FILE__, __LINE__, name.c_str(), dau->GetName());
935  }
936  g4->placeVolume(dau,(*iv).second, transform);
937  printout(lvl, "Geant4Converter", "+++ Assembly: AddPlacedVolume %p: dau:%s "
938  "to mother %s Tr:x=%8.3f y=%8.3f z=%8.3f",
939  (void*)dau_vol, dau_vol->GetName(), mot_vol->GetName(),
940  transform.dx(), transform.dy(), transform.dz());
941  }
942  }
943  info.g4AssemblyVolumes[node] = g4;
944  }
945  return g4;
946 }
947 
949 void* Geant4Converter::handlePlacement(const std::string& name, const TGeoNode* node) const {
951  PrintLevel lvl = debugPlacements ? ALWAYS : outputLevel;
952  Geant4GeometryMaps::PlacementMap::const_iterator g4it = info.g4Placements.find(node);
953  G4VPhysicalVolume* g4 = (g4it == info.g4Placements.end()) ? 0 : (*g4it).second;
954  TGeoVolume* vol = node->GetVolume();
955  Volume _v(vol);
956 
957  if ( _v.testFlagBit(Volume::VETO_SIMU) ) {
958  printout(lvl, "Geant4Converter", "++ Placement %s not converted [Veto'ed for simulation]",node->GetName());
959  return nullptr;
960  }
961  //g4 = nullptr;
962  if ( !g4 ) {
963  TGeoVolume* mot_vol = node->GetMotherVolume();
964  TGeoMatrix* tr = node->GetMatrix();
965  if ( !tr ) {
966  except("Geant4Converter",
967  "++ Attempt to handle placement without transformation:%p %s of type %s vol:%p",
968  node, node->GetName(), node->IsA()->GetName(), vol);
969  }
970  else if (nullptr == vol) {
971  except("Geant4Converter", "++ Unknown G4 volume:%p %s of type %s ptr:%p",
972  node, node->GetName(), node->IsA()->GetName(), vol);
973  }
974  else {
975  int copy = node->GetNumber();
976  bool node_is_reflected = is_left_handed(tr);
977  bool node_is_assembly = vol->IsA() == TGeoVolumeAssembly::Class();
978  bool mother_is_assembly = mot_vol ? mot_vol->IsA() == TGeoVolumeAssembly::Class() : false;
979  G4Transform3D transform;
980  Geant4GeometryMaps::VolumeMap::const_iterator volIt = info.g4Volumes.find(mot_vol);
981 
982  g4Transform(tr, transform);
983  if ( mother_is_assembly ) {
984  //
985  // Mother is an assembly:
986  // Nothing to do here, because:
987  // -- placed volumes were already added before in "handleAssembly"
988  // -- imprint cannot be made, because this requires a logical volume as a mother
989  //
990  printout(lvl, "Geant4Converter", "+++ Assembly: **** : dau:%s "
991  "to mother %s Tr:x=%8.3f y=%8.3f z=%8.3f",
992  vol->GetName(), mot_vol->GetName(),
993  transform.dx(), transform.dy(), transform.dz());
994  return nullptr;
995  }
996  G4Scale3D scale;
997  G4Rotate3D rot;
998  G4Translate3D trans;
999  transform.getDecomposition(scale, rot, trans);
1000  if ( node_is_assembly ) {
1001  //
1002  // Node is an assembly:
1003  // Imprint the assembly. The mother MUST already be transformed.
1004  //
1005  printout(lvl, "Geant4Converter", "++ Assembly: makeImprint: dau:%-12s %s in mother %-12s "
1006  "Tr:x=%8.1f y=%8.1f z=%8.1f Scale:x=%4.2f y=%4.2f z=%4.2f",
1007  node->GetName(), node_is_reflected ? "(REFLECTED)" : "",
1008  mot_vol ? mot_vol->GetName() : "<unknown>",
1009  transform.dx(), transform.dy(), transform.dz(),
1010  scale.xx(), scale.yy(), scale.zz());
1011  Geant4AssemblyVolume* ass = (Geant4AssemblyVolume*)info.g4AssemblyVolumes[node];
1013  chain.emplace_back(node);
1014  ass->imprint(*this, node, chain, ass, (*volIt).second, transform, checkOverlaps);
1015  return nullptr;
1016  }
1017  else if ( node != info.manager->GetTopNode() && volIt == info.g4Volumes.end() ) {
1018  //throw std::logic_error("Geant4Converter: Invalid mother volume found!");
1019  }
1020  PlacedVolume pv(node);
1021  const auto* pv_data = pv.data();
1022  G4LogicalVolume* g4vol = info.g4Volumes[vol];
1023  G4LogicalVolume* g4mot = info.g4Volumes[mot_vol];
1024  G4PhysicalVolumesPair pvPlaced { nullptr, nullptr };
1025 
1026  if ( pv_data && pv_data->params && (pv_data->params->flags&Volume::REPLICATED) ) {
1027  EAxis axis = kUndefined;
1028  double width = 0e0, offset = 0e0;
1029  auto flags = pv_data->params->flags;
1030  auto count = pv_data->params->trafo1D.second;
1031  auto start = pv_data->params->start.Translation().Vect();
1032  auto delta = pv_data->params->trafo1D.first.Translation().Vect();
1033 
1034  if ( flags&Volume::X_axis )
1035  { axis = kXAxis; width = delta.X(); offset = start.X(); }
1036  else if ( flags&Volume::Y_axis )
1037  { axis = kYAxis; width = delta.Y(); offset = start.Y(); }
1038  else if ( flags&Volume::Z_axis )
1039  { axis = kZAxis; width = delta.Z(); offset = start.Z(); }
1040  else
1041  except("Geant4Converter",
1042  "++ Replication around unknown axis is not implemented. flags: %16X", flags);
1043  printout(INFO,"Geant4Converter","++ Replicate: Axis: %ld Count: %ld offset: %f width: %f",
1044  axis, count, offset, width);
1045  auto* g4pv = new G4PVReplica(name, // its name
1046  g4vol, // its logical volume
1047  g4mot, // its mother (logical) volume
1048  axis, // its replication axis
1049  count, // Number of replicas
1050  width, // Distance between 2 replicas
1051  offset); // Placement offset in axis direction
1052  pvPlaced = { g4pv, nullptr };
1053 #if 0
1054  pvPlaced =
1055  G4ReflectionFactory::Instance()->Replicate(name, // its name
1056  g4vol, // its logical volume
1057  g4mot, // its mother (logical) volume
1058  axis, // its replication axis
1059  count, // Number of replicas
1060  width, // Distance between 2 replicas
1061  offset); // Placement offset in axis direction
1063  auto* g4pv = pvPlaced.second ? pvPlaced.second : pvPlaced.first;
1064 #endif
1065  for( auto& handle : pv_data->params->placements )
1066  info.g4Placements[handle.ptr()] = g4pv;
1067  }
1068  else if ( pv_data && pv_data->params ) {
1069  auto* g4par = new Geant4PlacementParameterisation(pv);
1070  auto* g4pv = new G4PVParameterised(name, // its name
1071  g4vol, // its logical volume
1072  g4mot, // its mother (logical) volume
1073  g4par->axis(), // its replication axis
1074  g4par->count(), // Number of replicas
1075  g4par); // G4 parametrization
1076  pvPlaced = { g4pv, nullptr };
1078  for( auto& handle : pv_data->params->placements )
1079  info.g4Placements[handle.ptr()] = g4pv;
1080  }
1081  else {
1082  pvPlaced =
1083  G4ReflectionFactory::Instance()->Place(transform, // no rotation
1084  name, // its name
1085  g4vol, // its logical volume
1086  g4mot, // its mother (logical) volume
1087  false, // no boolean operations
1088  copy, // its copy number
1089  checkOverlaps);
1090  }
1091  printout(debugReflections||debugPlacements ? ALWAYS : lvl, "Geant4Converter",
1092  "++ Place %svolume %-12s in mother %-12s "
1093  "Tr:x=%8.1f y=%8.1f z=%8.1f Scale:x=%4.2f y=%4.2f z=%4.2f",
1094  node_is_reflected ? "REFLECTED " : "", _v.name(),
1095  mot_vol ? mot_vol->GetName() : "<unknown>",
1096  transform.dx(), transform.dy(), transform.dz(),
1097  scale.xx(), scale.yy(), scale.zz());
1098  // First 2 cases can be combined.
1099  // Leave them separated for debugging G4ReflectionFactory for now...
1100  if ( node_is_reflected && !pvPlaced.second )
1101  return info.g4Placements[node] = pvPlaced.first;
1102  else if ( !node_is_reflected && !pvPlaced.second )
1103  return info.g4Placements[node] = pvPlaced.first;
1104  // Now deal with valid pvPlaced.second ...
1105  if ( node_is_reflected )
1106  return info.g4Placements[node] = pvPlaced.first;
1107  else if ( !node_is_reflected )
1108  return info.g4Placements[node] = pvPlaced.first;
1109  g4 = pvPlaced.second ? pvPlaced.second : pvPlaced.first;
1110  }
1111  info.g4Placements[node] = g4;
1112  printout(ERROR, "Geant4Converter", "++ DEAD code. Should not end up here!");
1113  }
1114  return g4;
1115 }
1116 
1118 void* Geant4Converter::handleRegion(Region region, const std::set<const TGeoVolume*>& /* volumes */) const {
1119  G4Region* g4 = data().g4Regions[region];
1120  if ( !g4 ) {
1121  PrintLevel lvl = debugRegions ? ALWAYS : outputLevel;
1122  Region r = region;
1123  g4 = new G4Region(region.name());
1124 
1125  // create region info with storeSecondaries flag
1126  if( not r.wasThresholdSet() and r.storeSecondaries() ) {
1127  throw std::runtime_error("G4Region: StoreSecondaries is True, but no explicit threshold set:");
1128  }
1129  printout(lvl, "Geant4Converter", "++ Setting up region: %s", r.name());
1130  G4UserRegionInformation* info = new G4UserRegionInformation();
1131  info->region = r;
1132  info->threshold = r.threshold()*CLHEP::MeV/units::MeV;
1133  info->storeSecondaries = r.storeSecondaries();
1134  g4->SetUserInformation(info);
1135 
1136  printout(lvl, "Geant4Converter", "++ Converted region settings of:%s.", r.name());
1137  std::vector < std::string > &limits = r.limits();
1138  G4ProductionCuts* cuts = 0;
1139  // set production cut
1140  if( not r.useDefaultCut() ) {
1141  cuts = new G4ProductionCuts();
1142  cuts->SetProductionCut(r.cut()*CLHEP::mm/units::mm);
1143  printout(lvl, "Geant4Converter", "++ %s: Using default cut: %f [mm]",
1144  r.name(), r.cut()*CLHEP::mm/units::mm);
1145  }
1146  for( const auto& nam : limits ) {
1147  LimitSet ls = m_detDesc.limitSet(nam);
1148  if ( ls.isValid() ) {
1149  const LimitSet::Set& cts = ls.cuts();
1150  for (const auto& c : cts ) {
1151  int pid = 0;
1152  if ( c.particles == "*" ) pid = -1;
1153  else if ( c.particles == "e-" ) pid = idxG4ElectronCut;
1154  else if ( c.particles == "e+" ) pid = idxG4PositronCut;
1155  else if ( c.particles == "e[+-]" ) pid = -idxG4PositronCut-idxG4ElectronCut;
1156  else if ( c.particles == "e[-+]" ) pid = -idxG4PositronCut-idxG4ElectronCut;
1157  else if ( c.particles == "gamma" ) pid = idxG4GammaCut;
1158  else if ( c.particles == "proton" ) pid = idxG4ProtonCut;
1159  else throw std::runtime_error("G4Region: Invalid production cut particle-type:" + c.particles);
1160  if ( !cuts ) cuts = new G4ProductionCuts();
1161  if ( pid == -(idxG4PositronCut+idxG4ElectronCut) ) {
1162  cuts->SetProductionCut(c.value*CLHEP::mm/units::mm, idxG4PositronCut);
1163  cuts->SetProductionCut(c.value*CLHEP::mm/units::mm, idxG4ElectronCut);
1164  }
1165  else {
1166  cuts->SetProductionCut(c.value*CLHEP::mm/units::mm, pid);
1167  }
1168  printout(lvl, "Geant4Converter", "++ %s: Set cut [%s/%d] = %f [mm]",
1169  r.name(), c.particles.c_str(), pid, c.value*CLHEP::mm/units::mm);
1170  }
1171  bool found = false;
1172  const auto& lm = data().g4Limits;
1173  for (const auto& j : lm ) {
1174  if (nam == j.first->GetName()) {
1175  g4->SetUserLimits(j.second);
1176  printout(lvl, "Geant4Converter", "++ %s: Set limits %s to region type %s",
1177  r.name(), nam.c_str(), j.second->GetType().c_str());
1178  found = true;
1179  break;
1180  }
1181  }
1182  if ( found ) {
1183  continue;
1184  }
1185  }
1186  except("Geant4Converter", "++ G4Region: Failed to resolve limitset: " + nam);
1187  }
1189  if ( cuts ) g4->SetProductionCuts(cuts);
1190  data().g4Regions[region] = g4;
1191  }
1192  return g4;
1193 }
1194 
1196 void* Geant4Converter::handleLimitSet(LimitSet limitset, const std::set<const TGeoVolume*>& /* volumes */) const {
1197  G4UserLimits* g4 = data().g4Limits[limitset];
1198  if ( !g4 ) {
1199  PrintLevel lvl = debugLimits || debugRegions ? ALWAYS : outputLevel;
1200  struct LimitPrint {
1201  const LimitSet& ls;
1202  LimitPrint(const LimitSet& lset) : ls(lset) {}
1203  const LimitPrint& operator()(const std::string& pref, const Geant4UserLimits::Handler& h) const {
1204  if ( !h.particleLimits.empty() ) {
1205  printout(ALWAYS,"Geant4Converter",
1206  "+++ LimitSet: Explicit Limit %s.%s applied for particles:",ls.name(), pref.c_str());
1207  for(const auto& p : h.particleLimits)
1208  printout(ALWAYS,"Geant4Converter","+++ LimitSet: Particle type: %-18s PDG: %-6d : %f",
1209  p.first->GetParticleName().c_str(), p.first->GetPDGEncoding(), p.second);
1210  }
1212  printout(ALWAYS,"Geant4Converter",
1213  "+++ LimitSet: Implicit Limit %s.%s for wildcard particles: %f",
1214  ls.name(), pref.c_str(), float(h.defaultValue));
1215  }
1216  return *this;
1217  }
1218  };
1219  Geant4UserLimits* limits = new Geant4UserLimits(limitset);
1220  g4 = limits;
1221  printout(lvl, "Geant4Converter",
1222  "++ Successfully converted LimitSet: %s [%ld cuts, %ld limits]",
1223  limitset.name(), limitset.cuts().size(), limitset.limits().size());
1224  if ( debugRegions || debugLimits ) {
1225  LimitPrint print(limitset);
1226  print("maxTime", limits->maxTime)
1227  ("minEKine", limits->minEKine)
1228  ("minRange", limits->minRange)
1229  ("maxStepLength", limits->maxStepLength)
1230  ("maxTrackLength",limits->maxTrackLength);
1231  }
1232  data().g4Limits[limitset] = g4;
1233  }
1234  return g4;
1235 }
1236 
1238 void* Geant4Converter::handleVis(const std::string& /* name */, VisAttr attr) const {
1240  G4VisAttributes* g4 = info.g4Vis[attr];
1241  if ( !g4 ) {
1242  float red = 0, green = 0, blue = 0;
1243  int style = attr.lineStyle();
1244  attr.rgb(red, green, blue);
1245  g4 = new G4VisAttributes(attr.visible(), G4Colour(red, green, blue, attr.alpha()));
1246  //g4->SetLineWidth(attr->GetLineWidth());
1247  g4->SetDaughtersInvisible(!attr.showDaughters());
1248  if ( style == VisAttr::SOLID ) {
1249  g4->SetLineStyle(G4VisAttributes::unbroken);
1250  g4->SetForceWireframe(false);
1251  g4->SetForceSolid(true);
1252  }
1253  else if ( style == VisAttr::WIREFRAME || style == VisAttr::DASHED ) {
1254  g4->SetLineStyle(G4VisAttributes::dashed);
1255  g4->SetForceSolid(false);
1256  g4->SetForceWireframe(true);
1257  }
1258  info.g4Vis[attr] = g4;
1259  }
1260  return g4;
1261 }
1262 
1265  std::map < std::string, std::string > processors;
1266  static int s_idd = 9999999;
1267  for( const auto& [nam, vals] : prp ) {
1268  if ( nam.substr(0, 6) == "geant4" ) {
1269  auto id_it = vals.find("id");
1270  std::string id = (id_it == vals.end()) ? _toString(++s_idd,"%d") : (*id_it).second;
1271  processors.emplace(id, nam);
1272  }
1273  }
1274  for( const auto& p : processors ) {
1275  const GeoHandler* hdlr = this;
1276  const Detector::PropertyValues& vals = prp[p.second];
1277  auto iter = vals.find("type");
1278  if ( iter != vals.end() ) {
1279  std::string type = iter->second;
1280  std::string tag = type + "_Geant4_action";
1281  Detector* det = const_cast<Detector*>(&m_detDesc);
1282  long res = PluginService::Create<long>(tag, det, hdlr, &vals);
1283  if ( 0 == res ) {
1284  throw std::runtime_error("Failed to locate plugin to interprete files of type"
1285  " \"" + tag + "\" - no factory:" + type);
1286  }
1287  res = *(long*)res;
1288  if ( res != 1 ) {
1289  throw std::runtime_error("Failed to invoke the plugin " + tag + " of type " + type);
1290  }
1291  printout(outputLevel, "Geant4Converter", "+++++ Executed Successfully Geant4 setup module *%s*.", type.c_str());
1292  continue;
1293  }
1294  printout(outputLevel, "Geant4Converter", "+++++ FAILED to execute Geant4 setup module *%s*.", p.second.c_str());
1295  }
1296 }
1297 
1301  TGDMLMatrix* matrix = (TGDMLMatrix*)mtx;
1302  const char* cptr = ::strstr(matrix->GetName(), GEANT4_TAG_IGNORE);
1303  Geant4GeometryInfo::PropertyVector* g4 = info.g4OpticalProperties[matrix];
1304 
1305  if ( nullptr != cptr ) { // Check if the property should not be passed to Geant4
1306  printout(INFO,"Geant4MaterialProperties","++ Ignore property %s [%s].",
1307  matrix->GetName(), matrix->GetTitle());
1308  return nullptr;
1309  }
1310  cptr = ::strstr(matrix->GetTitle(), GEANT4_TAG_IGNORE);
1311  if ( nullptr != cptr ) { // Check if the property should not be passed to Geant4
1312  printout(INFO,"Geant4MaterialProperties","++ Ignore property %s [%s].",
1313  matrix->GetName(), matrix->GetTitle());
1314  return nullptr;
1315  }
1316 
1317  if ( !g4 ) {
1318  PrintLevel lvl = debugMaterials ? ALWAYS : outputLevel;
1320  std::size_t rows = matrix->GetRows();
1321  g4->name = matrix->GetName();
1322  g4->title = matrix->GetTitle();
1323  g4->bins.reserve(rows);
1324  g4->values.reserve(rows);
1325  for( std::size_t i=0; i<rows; ++i ) {
1326  g4->bins.emplace_back(matrix->Get(i,0) /* *CLHEP::eV/units::eV */);
1327  g4->values.emplace_back(matrix->Get(i,1));
1328  }
1329  printout(lvl, "Geant4Converter",
1330  "++ Successfully converted material property:%s : %s [%ld rows]",
1331  matrix->GetName(), matrix->GetTitle(), rows);
1332  info.g4OpticalProperties[matrix] = g4;
1333  }
1334  return g4;
1335 }
1336 
1337 static G4OpticalSurfaceFinish geant4_surface_finish(TGeoOpticalSurface::ESurfaceFinish f) {
1338 #define TO_G4_FINISH(x) case TGeoOpticalSurface::kF##x : return x;
1339  switch(f) {
1340  TO_G4_FINISH(polished); // smooth perfectly polished surface
1341  TO_G4_FINISH(polishedfrontpainted); // smooth top-layer (front) paint
1342  TO_G4_FINISH(polishedbackpainted); // same is 'polished' but with a back-paint
1343 
1344  TO_G4_FINISH(ground); // rough surface
1345  TO_G4_FINISH(groundfrontpainted); // rough top-layer (front) paint
1346  TO_G4_FINISH(groundbackpainted); // same as 'ground' but with a back-paint
1347 
1348  TO_G4_FINISH(polishedlumirrorair); // mechanically polished surface, with lumirror
1349  TO_G4_FINISH(polishedlumirrorglue); // mechanically polished surface, with lumirror & meltmount
1350  TO_G4_FINISH(polishedair); // mechanically polished surface
1351  TO_G4_FINISH(polishedteflonair); // mechanically polished surface, with teflon
1352  TO_G4_FINISH(polishedtioair); // mechanically polished surface, with tio paint
1353  TO_G4_FINISH(polishedtyvekair); // mechanically polished surface, with tyvek
1354  TO_G4_FINISH(polishedvm2000air); // mechanically polished surface, with esr film
1355  TO_G4_FINISH(polishedvm2000glue); // mechanically polished surface, with esr film & meltmount
1356 
1357  TO_G4_FINISH(etchedlumirrorair); // chemically etched surface, with lumirror
1358  TO_G4_FINISH(etchedlumirrorglue); // chemically etched surface, with lumirror & meltmount
1359  TO_G4_FINISH(etchedair); // chemically etched surface
1360  TO_G4_FINISH(etchedteflonair); // chemically etched surface, with teflon
1361  TO_G4_FINISH(etchedtioair); // chemically etched surface, with tio paint
1362  TO_G4_FINISH(etchedtyvekair); // chemically etched surface, with tyvek
1363  TO_G4_FINISH(etchedvm2000air); // chemically etched surface, with esr film
1364  TO_G4_FINISH(etchedvm2000glue); // chemically etched surface, with esr film & meltmount
1365 
1366  TO_G4_FINISH(groundlumirrorair); // rough-cut surface, with lumirror
1367  TO_G4_FINISH(groundlumirrorglue); // rough-cut surface, with lumirror & meltmount
1368  TO_G4_FINISH(groundair); // rough-cut surface
1369  TO_G4_FINISH(groundteflonair); // rough-cut surface, with teflon
1370  TO_G4_FINISH(groundtioair); // rough-cut surface, with tio paint
1371  TO_G4_FINISH(groundtyvekair); // rough-cut surface, with tyvek
1372  TO_G4_FINISH(groundvm2000air); // rough-cut surface, with esr film
1373  TO_G4_FINISH(groundvm2000glue); // rough-cut surface, with esr film & meltmount
1374 
1375  // for DAVIS model
1376  TO_G4_FINISH(Rough_LUT); // rough surface
1377  TO_G4_FINISH(RoughTeflon_LUT); // rough surface wrapped in Teflon tape
1378  TO_G4_FINISH(RoughESR_LUT); // rough surface wrapped with ESR
1379  TO_G4_FINISH(RoughESRGrease_LUT); // rough surface wrapped with ESR and coupled with opical grease
1380  TO_G4_FINISH(Polished_LUT); // polished surface
1381  TO_G4_FINISH(PolishedTeflon_LUT); // polished surface wrapped in Teflon tape
1382  TO_G4_FINISH(PolishedESR_LUT); // polished surface wrapped with ESR
1383  TO_G4_FINISH(PolishedESRGrease_LUT); // polished surface wrapped with ESR and coupled with opical grease
1384  TO_G4_FINISH(Detector_LUT); // polished surface with optical grease
1385  default:
1386  printout(ERROR,"Geant4Surfaces","++ Unknown finish style: %d [%s]. Assume polished!",
1387  int(f), TGeoOpticalSurface::FinishToString(f));
1388  return polished;
1389  }
1390 #undef TO_G4_FINISH
1391 }
1392 
1393 static G4SurfaceType geant4_surface_type(TGeoOpticalSurface::ESurfaceType t) {
1394 #define TO_G4_TYPE(x) case TGeoOpticalSurface::kT##x : return x;
1395  switch(t) {
1396  TO_G4_TYPE(dielectric_metal); // dielectric-metal interface
1397  TO_G4_TYPE(dielectric_dielectric); // dielectric-dielectric interface
1398  TO_G4_TYPE(dielectric_LUT); // dielectric-Look-Up-Table interface
1399  TO_G4_TYPE(dielectric_LUTDAVIS); // dielectric-Look-Up-Table DAVIS interface
1400  TO_G4_TYPE(dielectric_dichroic); // dichroic filter interface
1401  TO_G4_TYPE(firsov); // for Firsov Process
1402  TO_G4_TYPE(x_ray); // for x-ray mirror process
1403  default:
1404  printout(ERROR,"Geant4Surfaces","++ Unknown surface type: %d [%s]. Assume dielectric_metal!",
1405  int(t), TGeoOpticalSurface::TypeToString(t));
1406  return dielectric_metal;
1407  }
1408 #undef TO_G4_TYPE
1409 }
1410 
1411 static G4OpticalSurfaceModel geant4_surface_model(TGeoOpticalSurface::ESurfaceModel surfMod) {
1412 #define TO_G4_MODEL(x) case TGeoOpticalSurface::kM##x : return x;
1413  switch(surfMod) {
1414  TO_G4_MODEL(glisur); // original GEANT3 model
1415  TO_G4_MODEL(unified); // UNIFIED model
1416  TO_G4_MODEL(LUT); // Look-Up-Table model
1417  TO_G4_MODEL(DAVIS); // DAVIS model
1418  TO_G4_MODEL(dichroic); // dichroic filter
1419  default:
1420  printout(ERROR,"Geant4Surfaces","++ Unknown surface model: %d [%s]. Assume glisur!",
1421  int(surfMod), TGeoOpticalSurface::ModelToString(surfMod));
1422  return glisur;
1423  }
1424 #undef TO_G4_MODEL
1425 }
1426 
1429  TGeoOpticalSurface* optSurf = (TGeoOpticalSurface*)surface;
1431  G4OpticalSurface* g4 = info.g4OpticalSurfaces[optSurf];
1432  if ( !g4 ) {
1433  G4SurfaceType type = geant4_surface_type(optSurf->GetType());
1434  G4OpticalSurfaceModel model = geant4_surface_model(optSurf->GetModel());
1435  G4OpticalSurfaceFinish finish = geant4_surface_finish(optSurf->GetFinish());
1436  std::string name = make_NCName(optSurf->GetName());
1437  PrintLevel lvl = debugSurfaces ? ALWAYS : DEBUG;
1438  g4 = new G4OpticalSurface(name, model, finish, type, optSurf->GetValue());
1439  g4->SetSigmaAlpha(optSurf->GetSigmaAlpha());
1440  g4->SetPolish(optSurf->GetPolish());
1441 
1442  printout(lvl, "Geant4Converter",
1443  "++ Created OpticalSurface: %-18s type:%s model:%s finish:%s SigmaAlphs: %.3e Polish: %.3e",
1444  optSurf->GetName(),
1445  TGeoOpticalSurface::TypeToString(optSurf->GetType()),
1446  TGeoOpticalSurface::ModelToString(optSurf->GetModel()),
1447  TGeoOpticalSurface::FinishToString(optSurf->GetFinish()),
1448  optSurf->GetSigmaAlpha(), optSurf->GetPolish());
1451  G4MaterialPropertiesTable* tab = nullptr;
1452  TListIter itp(&optSurf->GetProperties());
1453  for(TObject* obj = itp.Next(); obj; obj = itp.Next()) {
1454  std::string exc_str;
1455  TNamed* named = (TNamed*)obj;
1456  TGDMLMatrix* matrix = info.manager->GetGDMLMatrix(named->GetTitle());
1457  const char* cptr = ::strstr(matrix->GetName(), GEANT4_TAG_IGNORE);
1458  if ( nullptr != cptr ) // Check if the property should not be passed to Geant4
1459  continue;
1460 
1461  if ( nullptr == tab ) {
1462  tab = new G4MaterialPropertiesTable();
1463  g4->SetMaterialPropertiesTable(tab);
1464  }
1465 
1468  if ( !v ) { // Error!
1469  except("Geant4OpticalSurface","++ Failed to convert opt.surface %s. Property table %s is not defined!",
1470  optSurf->GetName(), named->GetTitle());
1471  }
1472  int idx = -1;
1473  try {
1474  idx = tab->GetPropertyIndex(named->GetName());
1475  }
1476  catch(const std::exception& e) {
1477  exc_str = e.what();
1478  }
1479  catch(...) {
1480  }
1481  if ( idx < 0 ) {
1482  printout(ERROR, "Geant4Converter",
1483  "++ UNKNOWN Geant4 Property: %-20s %s [IGNORED]",
1484  exc_str.c_str(), named->GetName());
1485  continue;
1486  }
1487  // We need to convert the property from TGeo units to Geant4 units
1488  auto conv = g4PropertyConversion(idx);
1489  std::vector<double> bins(v->bins), vals(v->values);
1490  for(std::size_t i=0, count=v->bins.size(); i<count; ++i)
1491  bins[i] *= conv.first, vals[i] *= conv.second;
1492  G4MaterialPropertyVector* vec = new G4MaterialPropertyVector(&bins[0], &vals[0], bins.size());
1493  tab->AddProperty(named->GetName(), vec);
1494 
1495  printout(lvl, "Geant4Converter",
1496  "++ Property: %-20s [%ld x %ld] --> %s",
1497  named->GetName(), matrix->GetRows(), matrix->GetCols(), named->GetTitle());
1498  for(std::size_t i=0, count=v->bins.size(); i<count; ++i)
1499  printout(lvl, named->GetName(),
1500  " Geant4: %8.3g [MeV] TGeo: %8.3g [GeV] Conversion: %8.3g",
1501  bins[i], v->bins[i], conv.first);
1502  }
1505 #if ROOT_VERSION_CODE >= ROOT_VERSION(6,31,1)
1506  TListIter itc(&optSurf->GetConstProperties());
1507  for(TObject* obj = itc.Next(); obj; obj = itc.Next()) {
1508  std::string exc_str;
1509  TNamed* named = (TNamed*)obj;
1510  const char* cptr = ::strstr(named->GetName(), GEANT4_TAG_IGNORE);
1511  if ( nullptr != cptr ) {
1512  printout(INFO, name, "++ Ignore CONST property %s [%s].",
1513  named->GetName(), named->GetTitle());
1514  continue;
1515  }
1516  cptr = ::strstr(named->GetTitle(), GEANT4_TAG_IGNORE);
1517  if ( nullptr != cptr ) {
1518  printout(INFO, name,"++ Ignore CONST property %s [%s].",
1519  named->GetName(), named->GetTitle());
1520  continue;
1521  }
1522  Bool_t err = kFALSE;
1523  Double_t value = info.manager->GetProperty(named->GetTitle(),&err);
1524  if ( err != kFALSE ) {
1525  except(name,
1526  "++ FAILED to create G4 material %s [Cannot convert const property: %s]",
1527  optSurf->GetName(), named->GetName());
1528  }
1529  if ( nullptr == tab ) {
1530  tab = new G4MaterialPropertiesTable();
1531  g4->SetMaterialPropertiesTable(tab);
1532  }
1533  int idx = -1;
1534  try {
1535  idx = tab->GetConstPropertyIndex(named->GetName());
1536  }
1537  catch(const std::exception& e) {
1538  exc_str = e.what();
1539  }
1540  catch(...) {
1541  }
1542  if ( idx < 0 ) {
1543  printout(ERROR, name,
1544  "++ UNKNOWN Geant4 CONST Property: %-20s %s [IGNORED]",
1545  exc_str.c_str(), named->GetName());
1546  continue;
1547  }
1548  // We need to convert the property from TGeo units to Geant4 units
1549  double conv = g4ConstPropertyConversion(idx);
1550  printout(lvl, name, "++ CONST Property: %-20s %g * %g --> %g ",
1551  named->GetName(), value, conv, value * conv);
1552  tab->AddConstProperty(named->GetName(), value * conv);
1553  }
1554 #endif // ROOT_VERSION >= 6.31.1
1555  info.g4OpticalSurfaces[optSurf] = g4;
1556  }
1557  return g4;
1558 }
1559 
1562  TGeoSkinSurface* surf = (TGeoSkinSurface*)surface;
1564  G4LogicalSkinSurface* g4 = info.g4SkinSurfaces[surf];
1565  if ( !g4 ) {
1566  G4OpticalSurface* optSurf = info.g4OpticalSurfaces[OpticalSurface(surf->GetSurface())];
1567  G4LogicalVolume* v = info.g4Volumes[surf->GetVolume()];
1568  std::string name = make_NCName(surf->GetName());
1569  g4 = new G4LogicalSkinSurface(name, v, optSurf);
1570  printout(debugSurfaces ? ALWAYS : DEBUG, "Geant4Converter",
1571  "++ Created SkinSurface: %-18s optical:%s",
1572  surf->GetName(), surf->GetSurface()->GetName());
1573  info.g4SkinSurfaces[surf] = g4;
1574  }
1575  return g4;
1576 }
1577 
1580  TGeoBorderSurface* surf = (TGeoBorderSurface*)surface;
1582  G4LogicalBorderSurface* g4 = info.g4BorderSurfaces[surf];
1583  if ( !g4 ) {
1584  G4OpticalSurface* optSurf = info.g4OpticalSurfaces[OpticalSurface(surf->GetSurface())];
1585  G4VPhysicalVolume* n1 = info.g4Placements[surf->GetNode1()];
1586  G4VPhysicalVolume* n2 = info.g4Placements[surf->GetNode2()];
1587  std::string name = make_NCName(surf->GetName());
1588  g4 = new G4LogicalBorderSurface(name, n1, n2, optSurf);
1589  printout(debugSurfaces ? ALWAYS : DEBUG, "Geant4Converter",
1590  "++ Created BorderSurface: %-18s optical:%s",
1591  surf->GetName(), surf->GetSurface()->GetName());
1592  info.g4BorderSurfaces[surf] = g4;
1593  }
1594  return g4;
1595 }
1596 
1598 void Geant4Converter::printSensitive(SensitiveDetector sens_det, const std::set<const TGeoVolume*>& /* volumes */) const {
1600  std::set<const TGeoVolume*>& volset = info.sensitives[sens_det];
1601  SensitiveDetector sd = sens_det;
1602  std::stringstream str;
1603 
1604  printout(INFO, "Geant4Converter", "++ SensitiveDetector: %-18s %-20s Hits:%-16s", sd.name(), ("[" + sd.type() + "]").c_str(),
1605  sd.hitsCollection().c_str());
1606  str << " | " << "Cutoff:" << std::setw(6) << std::left
1607  << sd.energyCutoff() << std::setw(5) << std::right << volset.size()
1608  << " volumes ";
1609  if (sd.region().isValid())
1610  str << " Region:" << std::setw(12) << std::left << sd.region().name();
1611  if (sd.limits().isValid())
1612  str << " Limits:" << std::setw(12) << std::left << sd.limits().name();
1613  str << ".";
1614  printout(INFO, "Geant4Converter", str.str().c_str());
1615 
1616  for (const auto i : volset ) {
1617  std::map<Volume, G4LogicalVolume*>::iterator v = info.g4Volumes.find(i);
1618  if ( v != info.g4Volumes.end() ) {
1619  G4LogicalVolume* vol = (*v).second;
1620  str.str("");
1621  str << " | " << "Volume:" << std::setw(24) << std::left << vol->GetName() << " "
1622  << vol->GetNoDaughters() << " daughters.";
1623  printout(INFO, "Geant4Converter", str.str().c_str());
1624  }
1625  }
1626 }
1627 
1628 std::string printSolid(G4VSolid* sol) {
1629  std::stringstream str;
1630  if (typeid(*sol) == typeid(G4Box)) {
1631  const G4Box* b = (G4Box*) sol;
1632  str << "++ Box: x=" << b->GetXHalfLength() << " y=" << b->GetYHalfLength() << " z=" << b->GetZHalfLength();
1633  }
1634  else if (typeid(*sol) == typeid(G4Tubs)) {
1635  const G4Tubs* t = (const G4Tubs*) sol;
1636  str << " Tubs: Ri=" << t->GetInnerRadius() << " Ra=" << t->GetOuterRadius() << " z/2=" << t->GetZHalfLength() << " Phi="
1637  << t->GetStartPhiAngle() << "..." << t->GetDeltaPhiAngle();
1638  }
1639  return str.str();
1640 }
1641 
1643 void* Geant4Converter::printPlacement(const std::string& name, const TGeoNode* node) const {
1645  G4VPhysicalVolume* g4 = info.g4Placements[node];
1646  G4LogicalVolume* vol = info.g4Volumes[node->GetVolume()];
1647  G4LogicalVolume* mot = info.g4Volumes[node->GetMotherVolume()];
1648  G4VSolid* sol = vol->GetSolid();
1649  G4ThreeVector tr = g4->GetObjectTranslation();
1650  G4VSensitiveDetector* sd = vol->GetSensitiveDetector();
1651  if ( !sd ) {
1652  return g4;
1653  }
1654  std::stringstream str;
1655  str << "G4Cnv::placement: + " << name << " No:" << node->GetNumber() << " Vol:" << vol->GetName() << " Solid:"
1656  << sol->GetName();
1657  printout(outputLevel, "G4Placement", str.str().c_str());
1658  str.str("");
1659  str << " |" << " Loc: x=" << tr.x() << " y=" << tr.y() << " z=" << tr.z();
1660  printout(outputLevel, "G4Placement", str.str().c_str());
1661  printout(outputLevel, "G4Placement", printSolid(sol).c_str());
1662  str.str("");
1663  str << " |" << " Ndau:" << vol->GetNoDaughters()
1664  << " physvols." << " Mat:" << vol->GetMaterial()->GetName()
1665  << " Mother:" << (char*) (mot ? mot->GetName().c_str() : "---");
1666  printout(outputLevel, "G4Placement", str.str().c_str());
1667  str.str("");
1668  str << " |" << " SD:" << sd->GetName();
1669  printout(outputLevel, "G4Placement", str.str().c_str());
1670  return g4;
1671 }
1672 
1675  typedef std::map<const TGeoNode*, std::vector<TGeoNode*> > _DAU;
1676  TTimeStamp start;
1677  _DAU daughters;
1678  Geant4GeometryInfo& geo = this->init();
1679  World wrld = top.world();
1680 
1681  m_data->clear();
1682  m_set_data->clear();
1683  m_daughters = &daughters;
1684  geo.manager = &wrld.detectorDescription().manager();
1685  this->collect(top, geo);
1686  this->checkOverlaps = false;
1687  // We do not have to handle defines etc.
1688  // All positions and the like are not really named.
1689  // Hence, start creating the G4 objects for materials, solids and log volumes.
1690  handleArray(this, geo.manager->GetListOfGDMLMatrices(), &Geant4Converter::handleMaterialProperties);
1691  handleArray(this, geo.manager->GetListOfOpticalSurfaces(), &Geant4Converter::handleOpticalSurface);
1692 
1695  printout(outputLevel, "Geant4Converter", "++ Handled %ld solids.", geo.solids.size());
1696  handleRefs(this, geo.vis, &Geant4Converter::handleVis);
1697  printout(outputLevel, "Geant4Converter", "++ Handled %ld visualization attributes.", geo.vis.size());
1699  printout(outputLevel, "Geant4Converter", "++ Handled %ld limit sets.", geo.limits.size());
1701  printout(outputLevel, "Geant4Converter", "++ Handled %ld regions.", geo.regions.size());
1703  printout(outputLevel, "Geant4Converter", "++ Handled %ld volumes.", geo.volumes.size());
1705  // Now place all this stuff appropriately
1706  //handleRMap(this, *m_data, &Geant4Converter::handlePlacement);
1707  std::map<int, std::vector<const TGeoNode*> >::const_reverse_iterator i = m_data->rbegin();
1708  for ( ; i != m_data->rend(); ++i ) {
1709  for ( const TGeoNode* node : i->second ) {
1710  this->handlePlacement(node->GetName(), node);
1711  }
1712  }
1714  handleArray(this, geo.manager->GetListOfSkinSurfaces(), &Geant4Converter::handleSkinSurface);
1715  handleArray(this, geo.manager->GetListOfBorderSurfaces(), &Geant4Converter::handleBorderSurface);
1716  //==================== Fields
1718  if ( printSensitives ) {
1720  }
1721  if ( printPlacements ) {
1723  }
1724 
1725  m_daughters = nullptr;
1726  geo.setWorld(top.placement().ptr());
1727  geo.valid = true;
1728  TTimeStamp stop;
1729  printout(INFO, "Geant4Converter",
1730  "+++ Successfully converted geometry to Geant4. [%7.3f seconds]",
1731  stop.AsDouble()-start.AsDouble() );
1732  return *this;
1733 }
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:135
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:387
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:1196
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:475
dd4hep::Atom
Handle class describing an element in the periodic table.
Definition: Objects.h:241
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:532
Volumes.h
dd4hep::Volume::NO_SMARTLESS_OPTIMIZATION
@ NO_SMARTLESS_OPTIMIZATION
Definition: Volumes.h:392
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:43
dd4hep::sim::Geant4GeometryInfo::g4Regions
std::map< Region, G4Region * > g4Regions
Definition: Geant4GeometryInfo.h:131
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:164
dd4hep::VisAttr
Handle class describing visualization attributes.
Definition: Objects.h:323
dd4hep::Region::storeSecondaries
bool storeSecondaries() const
Access secondaries flag.
Definition: Objects.cpp:524
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:463
dd4hep::sim::Geant4Converter::handleSkinSurface
void * handleSkinSurface(TObject *surface) const
Convert the skin surface to Geant4.
Definition: Geant4Converter.cpp:1561
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:1628
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:126
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:121
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:509
dd4hep::sim::Geant4GeometryInfo::manager
TGeoManager * manager
Definition: Geant4GeometryInfo.h:108
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:44
dd4hep::VisAttr::alpha
float alpha() const
Get alpha value.
Definition: Objects.cpp:370
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:350
dd4hep::Material
Handle class describing a material.
Definition: Objects.h:271
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:330
dd4hep::Region::threshold
double threshold() const
Access production threshold.
Definition: Objects.cpp:519
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:123
dd4hep::sim::Geant4Converter::create
Geant4Converter & create(DetElement top)
Create geometry conversion.
Definition: Geant4Converter.cpp:1674
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:187
dd4hep::sim::Geant4Converter::handleBorderSurface
void * handleBorderSurface(TObject *surface) const
Convert the border surface to Geant4.
Definition: Geant4Converter.cpp:1579
dd4hep::Volume::REPLICATED
@ REPLICATED
Definition: Volumes.h:382
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:371
dd4hep::Volume::Y_axis
@ Y_axis
Definition: Volumes.h:386
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:137
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:122
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:424
dd4hep::sim::Geant4GeometryInfo::PropertyVector::name
std::string name
Definition: Geant4GeometryInfo.h:123
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:326
DetectorTools.h
dd4hep::Volume::VETO_SIMU
@ VETO_SIMU
Definition: Volumes.h:376
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:1264
dd4hep::LimitSet::Set
std::set< Limit > Set
Iterator definitions.
Definition: Objects.h:427
dd4hep::Region
Handle class describing a region as used in simulation.
Definition: Objects.h:461
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:1598
dd4hep::VisAttr::rgb
bool rgb(float &red, float &green, float &blue) const
Get RGB values of the color (if valid)
Definition: Objects.cpp:395
Shapes.h
dd4hep::sim::Geant4GeometryInfo::g4Isotopes
Geant4GeometryMaps::IsotopeMap g4Isotopes
Definition: Geant4GeometryInfo.h:110
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:1428
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:876
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:1238
dd4hep::Region::cut
double cut() const
Access cut value.
Definition: Objects.cpp:514
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:133
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:856
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:113
dd4hep::sim::Geant4GeometryInfo::valid
bool valid
Definition: Geant4GeometryInfo.h:141
dd4hep::sim
Namespace for the Geant4 based simulation part of the AIDA detector description toolkit.
Definition: EDM4hepFileReader.cpp:41
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:340
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:949
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:91
dd4hep::VisAttr::SOLID
@ SOLID
Definition: Objects.h:326
dd4hep::Handle::ptr
T * ptr() const
Access to the held object.
Definition: Handle.h:151
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:528
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:1299
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:326
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:1118
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:136
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:111
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:120
dd4hep::Volume::X_axis
@ X_axis
Definition: Volumes.h:385
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:1104
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:1116
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:1643
dd4hep::detail::GeoHandler::collect
GeoHandler & collect(DetElement top)
Collect geometry information from traversal.
Definition: GeoHandler.cpp:99
handleMap
void handleMap(const O *o, const C &c, F pmf)
Definition: LCDDConverter.cpp:1111
dd4hep::sim::Geant4UserLimits::Handler
Helper class to one limit type.
Definition: Geant4UserLimits.h:46