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