File indexing completed on 2025-01-30 09:17:30
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <DD4hep/Shapes.h>
0016 #include <DD4hep/Volumes.h>
0017 #include <DD4hep/Plugins.h>
0018 #include <DD4hep/Printout.h>
0019 #include <DD4hep/Detector.h>
0020 #include <DD4hep/DD4hepUnits.h>
0021 #include <DD4hep/PropertyTable.h>
0022 #include <DD4hep/DetectorTools.h>
0023 #include <DD4hep/detail/ShapesInterna.h>
0024 #include <DD4hep/detail/ObjectsInterna.h>
0025 #include <DD4hep/detail/DetectorInterna.h>
0026
0027 #include <DDG4/Geant4Field.h>
0028 #include <DDG4/Geant4Helpers.h>
0029 #include <DDG4/Geant4Converter.h>
0030 #include <DDG4/Geant4UserLimits.h>
0031 #include <DDG4/Geant4AssemblyVolume.h>
0032 #include <DDG4/Geant4PlacementParameterisation.h>
0033 #include "Geant4ShapeConverter.h"
0034
0035
0036 #include <TClass.h>
0037 #include <TTimeStamp.h>
0038 #include <TGeoBoolNode.h>
0039
0040
0041 #include <G4Version.hh>
0042 #include <G4VisAttributes.hh>
0043 #include <G4PVParameterised.hh>
0044 #include <G4ProductionCuts.hh>
0045 #include <G4VUserRegionInformation.hh>
0046
0047 #include <G4Box.hh>
0048 #include <G4Tubs.hh>
0049 #include <G4Ellipsoid.hh>
0050 #include <G4UnionSolid.hh>
0051 #include <G4ReflectedSolid.hh>
0052 #include <G4SubtractionSolid.hh>
0053 #include <G4IntersectionSolid.hh>
0054 #include <G4VSensitiveDetector.hh>
0055
0056 #include <G4Region.hh>
0057 #include <G4Element.hh>
0058 #include <G4Isotope.hh>
0059 #include <G4Material.hh>
0060 #include <G4UserLimits.hh>
0061 #include <G4RegionStore.hh>
0062 #include <G4FieldManager.hh>
0063 #include <G4LogicalVolume.hh>
0064 #include <G4OpticalSurface.hh>
0065 #include <G4ReflectionFactory.hh>
0066 #include <G4LogicalSkinSurface.hh>
0067 #include <G4ElectroMagneticField.hh>
0068 #include <G4LogicalBorderSurface.hh>
0069 #include <G4MaterialPropertiesTable.hh>
0070 #if G4VERSION_NUMBER >= 1040
0071 #include <G4MaterialPropertiesIndex.hh>
0072 #endif
0073 #include <G4ScaledSolid.hh>
0074 #include <CLHEP/Units/SystemOfUnits.h>
0075
0076
0077 #include <iostream>
0078 #include <iomanip>
0079 #include <sstream>
0080 #include <limits>
0081
0082 namespace units = dd4hep;
0083 using namespace dd4hep::sim;
0084 using namespace dd4hep;
0085
0086 namespace {
0087
0088 static constexpr const double CM_2_MM = (CLHEP::centimeter/dd4hep::centimeter);
0089 static constexpr const char* GEANT4_TAG_IGNORE = "Geant4-ignore";
0090 static constexpr const char* GEANT4_TAG_PLUGIN = "Geant4-plugin";
0091 static constexpr const char* GEANT4_TAG_BIRKSCONSTANT = "BirksConstant";
0092 static constexpr const char* GEANT4_TAG_MEE = "MeanExcitationEnergy";
0093 static constexpr const char* GEANT4_TAG_ENE_PER_ION_PAIR = "MeanEnergyPerIonPair";
0094
0095 static std::string indent = "";
0096
0097 template <typename O, typename C, typename F> void handleRefs(const O* o, const C& c, F pmf) {
0098 for (typename C::const_iterator i = c.begin(); i != c.end(); ++i) {
0099
0100 (o->*pmf)("", *i);
0101 }
0102 }
0103
0104 template <typename O, typename C, typename F> void handle(const O* o, const C& c, F pmf) {
0105 for (typename C::const_iterator i = c.begin(); i != c.end(); ++i) {
0106 (o->*pmf)((*i)->GetName(), *i);
0107 }
0108 }
0109
0110 template <typename O, typename F> void handleArray(const O* o, const TObjArray* c, F pmf) {
0111 TObjArrayIter arr(c);
0112 for(TObject* i = arr.Next(); i; i=arr.Next())
0113 (o->*pmf)(i);
0114 }
0115
0116 template <typename O, typename C, typename F> void handleMap(const O* o, const C& c, F pmf) {
0117 for (typename C::const_iterator i = c.begin(); i != c.end(); ++i)
0118 (o->*pmf)((*i).first, (*i).second);
0119 }
0120
0121 template <typename O, typename C, typename F> void handleRMap(const O* o, const C& c, F pmf) {
0122 for (typename C::const_reverse_iterator i = c.rbegin(); i != c.rend(); ++i) {
0123
0124 handle(o, i->second, pmf);
0125 }
0126 }
0127 template <typename O, typename C, typename F> void handleRMap_(const O* o, const C& c, F pmf) {
0128 for (typename C::const_iterator i = c.begin(); i != c.end(); ++i) {
0129 const auto& cc = (*i).second;
0130 for (const auto& j : cc) {
0131 (o->*pmf)(j);
0132 }
0133 }
0134 }
0135
0136 std::string make_NCName(const std::string& in) {
0137 std::string res = detail::str_replace(in, "/", "_");
0138 res = detail::str_replace(res, "#", "_");
0139 return res;
0140 }
0141
0142 bool is_left_handed(const TGeoMatrix* m) {
0143 const Double_t* r = m->GetRotationMatrix();
0144 if ( r ) {
0145 Double_t det =
0146 r[0]*r[4]*r[8] + r[3]*r[7]*r[2] + r[6]*r[1]*r[5] -
0147 r[2]*r[4]*r[6] - r[5]*r[7]*r[0] - r[8]*r[1]*r[3];
0148 return det < 0e0;
0149 }
0150 return false;
0151 }
0152
0153 class G4UserRegionInformation : public G4VUserRegionInformation {
0154 public:
0155 Region region;
0156 double threshold;
0157 bool storeSecondaries;
0158 G4UserRegionInformation()
0159 : threshold(0.0), storeSecondaries(false) {
0160 }
0161 virtual ~G4UserRegionInformation() {
0162 }
0163 virtual void Print() const {
0164 if (region.isValid())
0165 printout(DEBUG, "Region", "Name:%s", region.name());
0166 }
0167 };
0168
0169 std::pair<double,double> g4PropertyConversion(int index) {
0170 #if G4VERSION_NUMBER >= 1040
0171 switch(index) {
0172 case kRINDEX: return std::make_pair(CLHEP::keV/units::keV, 1.0);
0173 case kREFLECTIVITY: return std::make_pair(CLHEP::keV/units::keV, 1.0);
0174 case kREALRINDEX: return std::make_pair(CLHEP::keV/units::keV, 1.0);
0175 case kIMAGINARYRINDEX: return std::make_pair(CLHEP::keV/units::keV, 1.0);
0176 case kEFFICIENCY: return std::make_pair(CLHEP::keV/units::keV, 1.0);
0177 case kTRANSMITTANCE: return std::make_pair(CLHEP::keV/units::keV, 1.0);
0178 case kSPECULARLOBECONSTANT: return std::make_pair(CLHEP::keV/units::keV, 1.0);
0179 case kSPECULARSPIKECONSTANT: return std::make_pair(CLHEP::keV/units::keV, 1.0);
0180 case kBACKSCATTERCONSTANT: return std::make_pair(CLHEP::keV/units::keV, 1.0);
0181 case kGROUPVEL: return std::make_pair(CLHEP::keV/units::keV, (CLHEP::m/CLHEP::s)/(units::m/units::s));
0182 case kMIEHG: return std::make_pair(CLHEP::keV/units::keV, CLHEP::m/units::m);
0183 case kRAYLEIGH: return std::make_pair(CLHEP::keV/units::keV, CLHEP::m/units::m);
0184 case kWLSCOMPONENT: return std::make_pair(CLHEP::keV/units::keV, 1.0);
0185 case kWLSABSLENGTH: return std::make_pair(CLHEP::keV/units::keV, CLHEP::m/units::m);
0186 case kABSLENGTH: return std::make_pair(CLHEP::keV/units::keV, CLHEP::m/units::m);
0187 #if G4VERSION_NUMBER >= 1100
0188 case kWLSCOMPONENT2: return std::make_pair(CLHEP::keV/units::keV, 1.0);
0189 case kWLSABSLENGTH2: return std::make_pair(CLHEP::keV/units::keV, CLHEP::m/units::m);
0190 case kSCINTILLATIONCOMPONENT1: return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
0191 case kSCINTILLATIONCOMPONENT2: return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
0192 case kSCINTILLATIONCOMPONENT3: return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
0193 #else
0194 case kFASTCOMPONENT: return std::make_pair(CLHEP::keV/units::keV, 1.0);
0195 case kSLOWCOMPONENT: return std::make_pair(CLHEP::keV/units::keV, 1.0);
0196 #endif
0197 case kPROTONSCINTILLATIONYIELD: return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
0198 case kDEUTERONSCINTILLATIONYIELD: return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
0199 case kTRITONSCINTILLATIONYIELD: return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
0200 case kALPHASCINTILLATIONYIELD: return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
0201 case kIONSCINTILLATIONYIELD: return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
0202 case kELECTRONSCINTILLATIONYIELD: return std::make_pair(CLHEP::keV/units::keV, units::keV/CLHEP::keV);
0203 default:
0204 break;
0205 }
0206 printout(FATAL,"Geant4Converter", "+++ Cannot convert material property with index: %d", index);
0207 #else
0208 printout(FATAL,"Geant4Converter", "+++ Cannot convert material property with index: %d [Need Geant4 > 10.03]", index);
0209 #endif
0210 return std::make_pair(0e0,0e0);
0211 }
0212
0213 double g4ConstPropertyConversion(int index) {
0214 #if G4VERSION_NUMBER >= 1040
0215 switch(index) {
0216 case kSURFACEROUGHNESS: return CLHEP::m/units::m;
0217 case kISOTHERMAL_COMPRESSIBILITY: return (CLHEP::m3/CLHEP::keV)/(units::m3/CLHEP::keV);
0218 case kRS_SCALE_FACTOR: return 1.0;
0219 case kWLSMEANNUMBERPHOTONS: return 1.0;
0220 case kWLSTIMECONSTANT: return CLHEP::second/units::second;
0221 case kMIEHG_FORWARD: return 1.0;
0222 case kMIEHG_BACKWARD: return 1.0;
0223 case kMIEHG_FORWARD_RATIO: return 1.0;
0224 case kSCINTILLATIONYIELD: return units::keV/CLHEP::keV;
0225 case kRESOLUTIONSCALE: return 1.0;
0226 case kFERMIPOT: return CLHEP::keV/units::keV;
0227 case kDIFFUSION: return 1.0;
0228 case kSPINFLIP: return 1.0;
0229 case kLOSS: return 1.0;
0230 case kLOSSCS: return CLHEP::barn/units::barn;
0231 case kABSCS: return CLHEP::barn/units::barn;
0232 case kSCATCS: return CLHEP::barn/units::barn;
0233 case kMR_NBTHETA: return 1.0;
0234 case kMR_NBE: return 1.0;
0235 case kMR_RRMS: return 1.0;
0236 case kMR_CORRLEN: return CLHEP::m/units::m;
0237 case kMR_THETAMIN: return 1.0;
0238 case kMR_THETAMAX: return 1.0;
0239 case kMR_EMIN: return CLHEP::keV/units::keV;
0240 case kMR_EMAX: return CLHEP::keV/units::keV;
0241 case kMR_ANGNOTHETA: return 1.0;
0242 case kMR_ANGNOPHI: return 1.0;
0243 case kMR_ANGCUT: return 1.0;
0244
0245 #if G4VERSION_NUMBER >= 1100
0246 case kSCINTILLATIONTIMECONSTANT1: return CLHEP::second/units::second;
0247 case kSCINTILLATIONTIMECONSTANT2: return CLHEP::second/units::second;
0248 case kSCINTILLATIONTIMECONSTANT3: return CLHEP::second/units::second;
0249 case kSCINTILLATIONRISETIME1: return CLHEP::second/units::second;
0250 case kSCINTILLATIONRISETIME2: return CLHEP::second/units::second;
0251 case kSCINTILLATIONRISETIME3: return CLHEP::second/units::second;
0252 case kSCINTILLATIONYIELD1: return 1.0;
0253 case kSCINTILLATIONYIELD2: return 1.0;
0254 case kSCINTILLATIONYIELD3: return 1.0;
0255 case kPROTONSCINTILLATIONYIELD1: return 1.0;
0256 case kPROTONSCINTILLATIONYIELD2: return 1.0;
0257 case kPROTONSCINTILLATIONYIELD3: return 1.0;
0258 case kDEUTERONSCINTILLATIONYIELD1: return 1.0;
0259 case kDEUTERONSCINTILLATIONYIELD2: return 1.0;
0260 case kDEUTERONSCINTILLATIONYIELD3: return 1.0;
0261 case kALPHASCINTILLATIONYIELD1: return 1.0;
0262 case kALPHASCINTILLATIONYIELD2: return 1.0;
0263 case kALPHASCINTILLATIONYIELD3: return 1.0;
0264 case kIONSCINTILLATIONYIELD1: return 1.0;
0265 case kIONSCINTILLATIONYIELD2: return 1.0;
0266 case kIONSCINTILLATIONYIELD3: return 1.0;
0267 case kELECTRONSCINTILLATIONYIELD1: return 1.0;
0268 case kELECTRONSCINTILLATIONYIELD2: return 1.0;
0269 case kELECTRONSCINTILLATIONYIELD3: return 1.0;
0270 #else
0271 case kFASTTIMECONSTANT: return CLHEP::second/units::second;
0272 case kFASTSCINTILLATIONRISETIME: return CLHEP::second/units::second;
0273 case kSLOWTIMECONSTANT: return CLHEP::second/units::second;
0274 case kSLOWSCINTILLATIONRISETIME: return CLHEP::second/units::second;
0275 case kYIELDRATIO: return 1.0;
0276 #endif
0277 default:
0278 break;
0279 }
0280 printout(FATAL,"Geant4Converter", "+++ Cannot convert CONST material property with index: %d", index);
0281 #else
0282 printout(FATAL,"Geant4Converter", "+++ Cannot convert material property with index: %d [Need Geant4 > 10.03]", index);
0283 #endif
0284 return 0.0;
0285 }
0286 }
0287
0288
0289 Geant4Converter::Geant4Converter(const Detector& description_ref)
0290 : Geant4Mapping(description_ref), checkOverlaps(true) {
0291 this->Geant4Mapping::init();
0292 m_propagateRegions = true;
0293 outputLevel = PrintLevel(printLevel() - 1);
0294 }
0295
0296
0297 Geant4Converter::Geant4Converter(const Detector& description_ref, PrintLevel level)
0298 : Geant4Mapping(description_ref), outputLevel(level) {
0299 this->Geant4Mapping::init();
0300 m_propagateRegions = true;
0301 }
0302
0303
0304 Geant4Converter::~Geant4Converter() {
0305 }
0306
0307
0308 void* Geant4Converter::handleIsotope(const std::string& , const TGeoIsotope* iso) const {
0309 G4Isotope* g4i = data().g4Isotopes[iso];
0310 if ( !g4i ) {
0311 double a_conv = (CLHEP::g / CLHEP::mole);
0312 g4i = new G4Isotope(iso->GetName(), iso->GetZ(), iso->GetN(), iso->GetA()*a_conv);
0313 printout(debugElements ? ALWAYS : outputLevel,
0314 "Geant4Converter", "++ Created G4 Isotope %s from data: Z=%d N=%d A=%.3f [g/mole]",
0315 iso->GetName(), iso->GetZ(), iso->GetN(), iso->GetA());
0316 data().g4Isotopes[iso] = g4i;
0317 }
0318 return g4i;
0319 }
0320
0321
0322 void* Geant4Converter::handleElement(const std::string& name, const Atom element) const {
0323 G4Element* g4e = data().g4Elements[element];
0324 if ( !g4e ) {
0325 PrintLevel lvl = debugElements ? ALWAYS : outputLevel;
0326 if (element->GetNisotopes() > 0) {
0327 g4e = new G4Element(name, element->GetTitle(), element->GetNisotopes());
0328 for (int i = 0, n = element->GetNisotopes(); i < n; ++i) {
0329 TGeoIsotope* iso = element->GetIsotope(i);
0330 G4Isotope* g4iso = (G4Isotope*)handleIsotope(iso->GetName(), iso);
0331 g4e->AddIsotope(g4iso, element->GetRelativeAbundance(i));
0332 }
0333 }
0334 else {
0335
0336 double a_conv = (CLHEP::g / CLHEP::mole);
0337 g4e = new G4Element(element->GetTitle(), name, element->Z(), element->A()*a_conv);
0338 printout(lvl, "Geant4Converter", "++ Created G4 Isotope %s from data: Z=%d N=%d A=%.3f [g/mole]",
0339 element->GetName(), element->Z(), element->N(), element->A());
0340 }
0341 std::stringstream str;
0342 str << (*g4e) << std::endl;
0343 printout(lvl, "Geant4Converter", "++ Created G4 element %s", str.str().c_str());
0344 data().g4Elements[element] = g4e;
0345 }
0346 return g4e;
0347 }
0348
0349
0350 void* Geant4Converter::handleMaterial(const std::string& name, Material medium) const {
0351 Geant4GeometryInfo& info = data();
0352 G4Material* mat = info.g4Materials[medium];
0353 if ( !mat ) {
0354 PrintLevel lvl = debugMaterials ? ALWAYS : outputLevel;
0355 TGeoMaterial* material = medium->GetMaterial();
0356 G4State state = kStateUndefined;
0357 double density = material->GetDensity() * (CLHEP::gram / CLHEP::cm3);
0358 if ( density < 1e-25 )
0359 density = 1e-25;
0360 switch ( material->GetState() ) {
0361 case TGeoMaterial::kMatStateSolid:
0362 state = kStateSolid;
0363 break;
0364 case TGeoMaterial::kMatStateLiquid:
0365 state = kStateLiquid;
0366 break;
0367 case TGeoMaterial::kMatStateGas:
0368 state = kStateGas;
0369 break;
0370 default:
0371 case TGeoMaterial::kMatStateUndefined:
0372 state = kStateUndefined;
0373 break;
0374 }
0375 printout(lvl,"Geant4Material","+++ Setting up material %s", name.c_str());
0376 if ( material->IsMixture() ) {
0377 double A_total = 0.0;
0378 double W_total = 0.0;
0379 TGeoMixture* mix = (TGeoMixture*) material;
0380 int nElements = mix->GetNelements();
0381 mat = new G4Material(name, density, nElements, state,
0382 material->GetTemperature(), material->GetPressure());
0383 for (int i = 0; i < nElements; ++i) {
0384 A_total += (mix->GetAmixt())[i];
0385 W_total += (mix->GetWmixt())[i];
0386 }
0387 for (int i = 0; i < nElements; ++i) {
0388 TGeoElement* e = mix->GetElement(i);
0389 G4Element* g4e = (G4Element*) handleElement(e->GetName(), Atom(e));
0390 if (!g4e) {
0391 printout(ERROR, name,
0392 "Missing element component %s for material %s. A=%f W=%f",
0393 e->GetName(), mix->GetName(), A_total, W_total);
0394 }
0395
0396 mat->AddElement(g4e, (mix->GetWmixt())[i] / W_total);
0397 }
0398 }
0399 else {
0400 double z = material->GetZ(), a = material->GetA();
0401 if ( z < 1.0000001 ) z = 1.0;
0402 if ( a < 0.5000001 ) a = 1.0;
0403 mat = new G4Material(name, z, a, density, state,
0404 material->GetTemperature(), material->GetPressure());
0405 }
0406
0407 std::string plugin_name { };
0408 double value = 0e0;
0409 double ionisation_mee = -2e100;
0410 double ionisation_birks_constant = -2e100;
0411 double ionisation_ene_per_ion_pair = -2e100;
0412
0413
0414 G4MaterialPropertiesTable* tab = 0;
0415 TListIter propIt(&material->GetProperties());
0416 for(TObject* obj=propIt.Next(); obj; obj = propIt.Next()) {
0417 std::string exc_str;
0418 TNamed* named = (TNamed*)obj;
0419 TGDMLMatrix* matrix = info.manager->GetGDMLMatrix(named->GetTitle());
0420 const char* cptr = ::strstr(matrix->GetName(), GEANT4_TAG_IGNORE);
0421 if ( nullptr != cptr ) {
0422 printout(INFO,name,"++ Ignore property %s [%s]. Not Suitable for Geant4.",
0423 matrix->GetName(), matrix->GetTitle());
0424 continue;
0425 }
0426 cptr = ::strstr(matrix->GetTitle(), GEANT4_TAG_IGNORE);
0427 if ( nullptr != cptr ) {
0428 printout(INFO,name,"++ Ignore property %s [%s]. Not Suitable for Geant4.",
0429 matrix->GetName(), matrix->GetTitle());
0430 continue;
0431 }
0432 Geant4GeometryInfo::PropertyVector* v =
0433 (Geant4GeometryInfo::PropertyVector*)handleMaterialProperties(matrix);
0434 if ( nullptr == v ) {
0435 except("Geant4Converter", "++ FAILED to create G4 material %s [Cannot convert property:%s]",
0436 material->GetName(), named->GetName());
0437 }
0438 if ( nullptr == tab ) {
0439 tab = new G4MaterialPropertiesTable();
0440 mat->SetMaterialPropertiesTable(tab);
0441 }
0442 int idx = -1;
0443 try {
0444 idx = tab->GetPropertyIndex(named->GetName());
0445 }
0446 catch(const std::exception& e) {
0447 exc_str = e.what();
0448 idx = -1;
0449 }
0450 catch(...) {
0451 idx = -1;
0452 }
0453 if ( idx < 0 ) {
0454 printout(ERROR, "Geant4Converter",
0455 "++ UNKNOWN Geant4 Property: %-20s %s [IGNORED]",
0456 exc_str.c_str(), named->GetName());
0457 continue;
0458 }
0459
0460 auto conv = g4PropertyConversion(idx);
0461 std::vector<double> bins(v->bins), vals(v->values);
0462 for(std::size_t i=0, count=bins.size(); i<count; ++i)
0463 bins[i] *= conv.first, vals[i] *= conv.second;
0464
0465 G4MaterialPropertyVector* vec =
0466 new G4MaterialPropertyVector(&bins[0], &vals[0], bins.size());
0467 tab->AddProperty(named->GetName(), vec);
0468 printout(lvl, name, "++ Property: %-20s [%ld x %ld] -> %s ",
0469 named->GetName(), matrix->GetRows(), matrix->GetCols(), named->GetTitle());
0470 for(std::size_t i=0, count=v->bins.size(); i<count; ++i)
0471 printout(lvl, name, " Geant4: %s %8.3g [MeV] TGeo: %8.3g [GeV] Conversion: %8.3g",
0472 named->GetName(), bins[i], v->bins[i], conv.first);
0473 }
0474
0475
0476 TListIter cpropIt(&material->GetConstProperties());
0477 for(TObject* obj=cpropIt.Next(); obj; obj = cpropIt.Next()) {
0478 std::string exc_str;
0479 Bool_t err = kFALSE;
0480 TNamed* named = (TNamed*)obj;
0481
0482 const char* cptr = ::strstr(named->GetName(), GEANT4_TAG_IGNORE);
0483 if ( nullptr != cptr ) {
0484 printout(INFO, name, "++ Ignore CONST property %s [%s].",
0485 named->GetName(), named->GetTitle());
0486 continue;
0487 }
0488 cptr = ::strstr(named->GetTitle(), GEANT4_TAG_IGNORE);
0489 if ( nullptr != cptr ) {
0490 printout(INFO, name,"++ Ignore CONST property %s [%s].",
0491 named->GetName(), named->GetTitle());
0492 continue;
0493 }
0494 cptr = ::strstr(named->GetName(), GEANT4_TAG_PLUGIN);
0495 if ( nullptr != cptr ) {
0496 printout(INFO, name, "++ Ignore CONST property %s [%s] --> Plugin.",
0497 named->GetName(), named->GetTitle());
0498 plugin_name = named->GetTitle();
0499 continue;
0500 }
0501 cptr = ::strstr(named->GetName(), GEANT4_TAG_BIRKSCONSTANT);
0502 if ( nullptr != cptr ) {
0503 err = kFALSE;
0504 value = material->GetConstProperty(GEANT4_TAG_BIRKSCONSTANT,&err);
0505 if ( err == kFALSE ) ionisation_birks_constant = value * (CLHEP::mm/CLHEP::MeV)/(units::mm/units::MeV);
0506 continue;
0507 }
0508 cptr = ::strstr(named->GetName(), GEANT4_TAG_MEE);
0509 if ( nullptr != cptr ) {
0510 err = kFALSE;
0511 value = material->GetConstProperty(GEANT4_TAG_MEE, &err);
0512 if ( err == kFALSE ) ionisation_mee = value * (CLHEP::MeV/units::MeV);
0513 continue;
0514 }
0515 cptr = ::strstr(named->GetName(), GEANT4_TAG_ENE_PER_ION_PAIR);
0516 if ( nullptr != cptr ) {
0517 err = kFALSE;
0518 value = material->GetConstProperty(GEANT4_TAG_ENE_PER_ION_PAIR,&err);
0519 if ( err == kFALSE ) ionisation_ene_per_ion_pair = value * (CLHEP::MeV/units::MeV);
0520 continue;
0521 }
0522
0523 err = kFALSE;
0524 value = info.manager->GetProperty(named->GetTitle(), &err);
0525 if ( err != kFALSE ) {
0526 except(name,
0527 "++ FAILED to create G4 material %s [Cannot convert const property: %s]",
0528 material->GetName(), named->GetName());
0529 }
0530 if ( nullptr == tab ) {
0531 tab = new G4MaterialPropertiesTable();
0532 mat->SetMaterialPropertiesTable(tab);
0533 }
0534 int idx = -1;
0535 try {
0536 idx = tab->GetConstPropertyIndex(named->GetName());
0537 }
0538 catch(const std::exception& e) {
0539 exc_str = e.what();
0540 idx = -1;
0541 }
0542 catch(...) {
0543 idx = -1;
0544 }
0545 if ( idx < 0 ) {
0546 printout(ERROR, name,
0547 "++ UNKNOWN Geant4 CONST Property: %-20s %s [IGNORED]",
0548 exc_str.c_str(), named->GetName());
0549 continue;
0550 }
0551
0552 double conv = g4ConstPropertyConversion(idx);
0553 printout(lvl, name, "++ CONST Property: %-20s %g ", named->GetName(), value);
0554 tab->AddConstProperty(named->GetName(), value * conv);
0555 }
0556
0557
0558 auto* ionisation = mat->GetIonisation();
0559 std::stringstream str;
0560 str << (*mat);
0561 if ( ionisation ) {
0562 if ( ionisation_birks_constant > 0e0 ) {
0563 ionisation->SetBirksConstant(ionisation_birks_constant);
0564 }
0565 if ( ionisation_mee > -1e100 ) {
0566 ionisation->SetMeanExcitationEnergy(ionisation_mee);
0567 }
0568 if ( ionisation_ene_per_ion_pair > 0e0 ) {
0569 ionisation->SetMeanEnergyPerIonPair(ionisation_ene_per_ion_pair);
0570 }
0571 str << " log(MEE): " << std::setprecision(4) << ionisation->GetLogMeanExcEnergy();
0572 if ( ionisation_birks_constant > 0e0 )
0573 str << " Birk's constant: " << std::setprecision(4) << ionisation->GetBirksConstant() << " [mm/MeV]";
0574 if ( ionisation_ene_per_ion_pair > 0e0 )
0575 str << " Mean Energy Per Ion Pair: " << std::setprecision(4) << ionisation->GetMeanEnergyPerIonPair()/CLHEP::eV << " [eV]";
0576 }
0577 else {
0578 str << " No ionisation parameters availible.";
0579 }
0580 printout(lvl, name, "++ Created G4 material %s", str.str().c_str());
0581
0582 if ( !plugin_name.empty() ) {
0583
0584 Detector* det = const_cast<Detector*>(&m_detDesc);
0585 G4Material* extended_mat = PluginService::Create<G4Material*>(plugin_name, det, medium, mat);
0586 if ( !extended_mat ) {
0587 except("G4Cnv::material["+name+"]","++ FATAL Failed to call plugin to create material.");
0588 }
0589 mat = extended_mat;
0590 }
0591 info.g4Materials[medium] = mat;
0592 }
0593 return mat;
0594 }
0595
0596
0597 void* Geant4Converter::handleSolid(const std::string& name, const TGeoShape* shape) const {
0598 G4VSolid* solid = nullptr;
0599 if ( shape ) {
0600 if ( nullptr != (solid = data().g4Solids[shape]) ) {
0601 return solid;
0602 }
0603 TClass* isa = shape->IsA();
0604 PrintLevel lvl = debugShapes ? ALWAYS : outputLevel;
0605 if (isa == TGeoShapeAssembly::Class()) {
0606
0607
0608 data().g4Solids[shape] = solid = convertShape<TGeoShapeAssembly>(shape);
0609 return solid;
0610 }
0611 else if (isa == TGeoBBox::Class())
0612 solid = convertShape<TGeoBBox>(shape);
0613 else if (isa == TGeoTube::Class())
0614 solid = convertShape<TGeoTube>(shape);
0615 else if (isa == TGeoTubeSeg::Class())
0616 solid = convertShape<TGeoTubeSeg>(shape);
0617 else if (isa == TGeoCtub::Class())
0618 solid = convertShape<TGeoCtub>(shape);
0619 else if (isa == TGeoEltu::Class())
0620 solid = convertShape<TGeoEltu>(shape);
0621 else if (isa == TwistedTubeObject::Class())
0622 solid = convertShape<TwistedTubeObject>(shape);
0623 else if (isa == TGeoTrd1::Class())
0624 solid = convertShape<TGeoTrd1>(shape);
0625 else if (isa == TGeoTrd2::Class())
0626 solid = convertShape<TGeoTrd2>(shape);
0627 else if (isa == TGeoHype::Class())
0628 solid = convertShape<TGeoHype>(shape);
0629 else if (isa == TGeoXtru::Class())
0630 solid = convertShape<TGeoXtru>(shape);
0631 else if (isa == TGeoPgon::Class())
0632 solid = convertShape<TGeoPgon>(shape);
0633 else if (isa == TGeoPcon::Class())
0634 solid = convertShape<TGeoPcon>(shape);
0635 else if (isa == TGeoCone::Class())
0636 solid = convertShape<TGeoCone>(shape);
0637 else if (isa == TGeoConeSeg::Class())
0638 solid = convertShape<TGeoConeSeg>(shape);
0639 else if (isa == TGeoParaboloid::Class())
0640 solid = convertShape<TGeoParaboloid>(shape);
0641 else if (isa == TGeoSphere::Class())
0642 solid = convertShape<TGeoSphere>(shape);
0643 else if (isa == TGeoTorus::Class())
0644 solid = convertShape<TGeoTorus>(shape);
0645 else if (isa == TGeoTrap::Class())
0646 solid = convertShape<TGeoTrap>(shape);
0647 else if (isa == TGeoArb8::Class())
0648 solid = convertShape<TGeoArb8>(shape);
0649 else if (isa == TGeoPara::Class())
0650 solid = convertShape<TGeoPara>(shape);
0651 else if (isa == TGeoTessellated::Class())
0652 solid = convertShape<TGeoTessellated>(shape);
0653 else if (isa == TGeoScaledShape::Class()) {
0654 TGeoScaledShape* sh = (TGeoScaledShape*) shape;
0655 TGeoShape* sol = sh->GetShape();
0656 if ( sol->IsA() == TGeoShapeAssembly::Class() ) {
0657 return solid;
0658 }
0659 const double* vals = sh->GetScale()->GetScale();
0660 G4Scale3D scal(vals[0], vals[1], vals[2]);
0661 G4VSolid* g4solid = (G4VSolid*)handleSolid(sol->GetName(), sol);
0662 if ( scal.xx()>0e0 && scal.yy()>0e0 && scal.zz()>0e0 )
0663 solid = new G4ScaledSolid(sh->GetName(), g4solid, scal);
0664 else
0665 solid = new G4ReflectedSolid(g4solid->GetName()+"_refl", g4solid, scal);
0666 }
0667 else if ( isa == TGeoCompositeShape::Class() ) {
0668 const TGeoCompositeShape* sh = (const TGeoCompositeShape*) shape;
0669 const TGeoBoolNode* boolean = sh->GetBoolNode();
0670 TGeoBoolNode::EGeoBoolType oper = boolean->GetBooleanOperator();
0671 TGeoMatrix* matrix = boolean->GetRightMatrix();
0672 G4VSolid* left = (G4VSolid*) handleSolid(name + "_left", boolean->GetLeftShape());
0673 G4VSolid* right = (G4VSolid*) handleSolid(name + "_right", boolean->GetRightShape());
0674
0675 if (!left) {
0676 except("Geant4Converter","++ No left Geant4 Solid present for composite shape: %s",name.c_str());
0677 }
0678 if (!right) {
0679 except("Geant4Converter","++ No right Geant4 Solid present for composite shape: %s",name.c_str());
0680 }
0681
0682 TGeoShape* ls = boolean->GetLeftShape();
0683 TGeoShape* rs = boolean->GetRightShape();
0684 if (strcmp(ls->ClassName(), "TGeoScaledShape") == 0 &&
0685 strcmp(rs->ClassName(), "TGeoBBox") == 0) {
0686 if (strcmp(((TGeoScaledShape *)ls)->GetShape()->ClassName(), "TGeoSphere") == 0) {
0687 if (oper == TGeoBoolNode::kGeoIntersection) {
0688 TGeoScaledShape* lls = (TGeoScaledShape *)ls;
0689 TGeoBBox* rrs = (TGeoBBox*)rs;
0690 double sx = lls->GetScale()->GetScale()[0];
0691 double sy = lls->GetScale()->GetScale()[1];
0692 double radius = ((TGeoSphere *)lls->GetShape())->GetRmax();
0693 double dz = rrs->GetDZ();
0694 double zorig = rrs->GetOrigin()[2];
0695 double zcut2 = dz + zorig;
0696 double zcut1 = 2 * zorig - zcut2;
0697 solid = new G4Ellipsoid(name,
0698 sx * radius * CM_2_MM,
0699 sy * radius * CM_2_MM,
0700 radius * CM_2_MM,
0701 zcut1 * CM_2_MM,
0702 zcut2 * CM_2_MM);
0703 data().g4Solids[shape] = solid;
0704 return solid;
0705 }
0706 }
0707 }
0708
0709 if ( matrix->IsRotation() ) {
0710 G4Transform3D transform;
0711 g4Transform(matrix, transform);
0712 if (oper == TGeoBoolNode::kGeoSubtraction)
0713 solid = new G4SubtractionSolid(name, left, right, transform);
0714 else if (oper == TGeoBoolNode::kGeoUnion)
0715 solid = new G4UnionSolid(name, left, right, transform);
0716 else if (oper == TGeoBoolNode::kGeoIntersection)
0717 solid = new G4IntersectionSolid(name, left, right, transform);
0718 }
0719 else {
0720 const Double_t *t = matrix->GetTranslation();
0721 G4ThreeVector transform(t[0] * CM_2_MM, t[1] * CM_2_MM, t[2] * CM_2_MM);
0722 if (oper == TGeoBoolNode::kGeoSubtraction)
0723 solid = new G4SubtractionSolid(name, left, right, 0, transform);
0724 else if (oper == TGeoBoolNode::kGeoUnion)
0725 solid = new G4UnionSolid(name, left, right, 0, transform);
0726 else if (oper == TGeoBoolNode::kGeoIntersection)
0727 solid = new G4IntersectionSolid(name, left, right, 0, transform);
0728 }
0729 }
0730
0731 if ( !solid )
0732 except("Geant4Converter","++ Failed to handle unknown solid shape: %s of type %s",
0733 name.c_str(), isa->GetName());
0734 printout(lvl,"Geant4Converter","++ Successessfully converted shape [%p] of type:%s to %s.",
0735 solid,isa->GetName(),typeName(typeid(*solid)).c_str());
0736 data().g4Solids[shape] = solid;
0737 }
0738 return solid;
0739 }
0740
0741
0742 void* Geant4Converter::handleVolume(const std::string& name, const TGeoVolume* volume) const {
0743 Volume _v(volume);
0744 Geant4GeometryInfo& info = data();
0745 PrintLevel lvl = debugVolumes ? ALWAYS : outputLevel;
0746 Geant4GeometryMaps::VolumeMap::const_iterator volIt = info.g4Volumes.find(volume);
0747 if ( _v.testFlagBit(Volume::VETO_SIMU) ) {
0748 printout(lvl, "Geant4Converter", "++ Volume %s not converted [Veto'ed for simulation]",volume->GetName());
0749 return nullptr;
0750 }
0751 else if (volIt == info.g4Volumes.end() ) {
0752 const char* vnam = volume->GetName();
0753 TGeoMedium* med = volume->GetMedium();
0754 Solid sh = volume->GetShape();
0755 bool is_assembly = sh->IsA() == TGeoShapeAssembly::Class() || volume->IsAssembly();
0756
0757 printout(lvl, "Geant4Converter", "++ Convert Volume %-32s: %p %s/%s assembly:%s",
0758 vnam, volume, sh.type(), _v.type(), yes_no(is_assembly));
0759 if ( is_assembly ) {
0760 return nullptr;
0761 }
0762 Region reg = _v.region();
0763 LimitSet lim = _v.limitSet();
0764 VisAttr vis = _v.visAttributes();
0765 G4Region* g4region = reg.isValid() ? info.g4Regions[reg] : nullptr;
0766 G4UserLimits* g4limits = lim.isValid() ? info.g4Limits[lim] : nullptr;
0767 G4VSolid* g4solid = (G4VSolid*) handleSolid(sh->GetName(), sh);
0768 G4Material* g4medium = (G4Material*) handleMaterial(med->GetName(), Material(med));
0769
0770 if ( !g4solid ) {
0771 except("G4Converter","++ No Geant4 Solid present for volume: %s", vnam);
0772 }
0773 else if ( !g4medium ) {
0774 except("G4Converter","++ No Geant4 material present for volume: %s", vnam);
0775 }
0776 else if ( reg.isValid() && !g4region ) {
0777 except("G4Cnv::volume["+name+"]"," ++ Failed to access Geant4 region %s.", reg.name());
0778 }
0779 else if ( lim.isValid() && !g4limits ) {
0780 except("G4Cnv::volume["+name+"]","++ FATAL Failed to access Geant4 user limits %s.", lim.name());
0781 }
0782 else if ( g4limits ) {
0783 printout(lvl, "Geant4Converter", "++ Volume + Apply LIMITS settings: %-24s to volume %s.",
0784 lim.name(), vnam);
0785 }
0786
0787 G4LogicalVolume* g4vol = nullptr;
0788 if ( _v.hasProperties() && !_v.getProperty(GEANT4_TAG_PLUGIN,"").empty() ) {
0789 Detector* det = const_cast<Detector*>(&m_detDesc);
0790 std::string plugin = _v.getProperty(GEANT4_TAG_PLUGIN,"");
0791 g4vol = PluginService::Create<G4LogicalVolume*>(plugin, det, _v, g4solid, g4medium);
0792 if ( !g4vol ) {
0793 except("G4Cnv::volume["+name+"]","++ FATAL Failed to call plugin to create logical volume.");
0794 }
0795 }
0796 else {
0797 g4vol = new G4LogicalVolume(g4solid, g4medium, vnam, nullptr, nullptr, nullptr);
0798 }
0799
0800 if ( g4limits ) {
0801 g4vol->SetUserLimits(g4limits);
0802 }
0803 if ( g4region ) {
0804 PrintLevel plevel = (debugVolumes||debugRegions||debugLimits) ? ALWAYS : outputLevel;
0805 printout(plevel, "Geant4Converter", "++ Volume + Apply REGION settings: %-24s to volume %s.",
0806 reg.name(), vnam);
0807
0808
0809
0810 if ( _v == m_detDesc.worldVolume() ) {
0811 const char* wrd_nam = "DefaultRegionForTheWorld";
0812 const char* src_nam = g4region->GetName().c_str();
0813 auto* world_region = G4RegionStore::GetInstance()->GetRegion(wrd_nam, false);
0814 if ( auto* cuts = g4region->GetProductionCuts() ) {
0815 world_region->SetProductionCuts(cuts);
0816 printout(plevel, "Geant4Converter",
0817 "++ Volume %s Region: %s. Apply production cuts from %s",
0818 vnam, wrd_nam, src_nam);
0819 }
0820 if ( auto* lims = g4region->GetUserLimits() ) {
0821 world_region->SetUserLimits(lims);
0822 printout(plevel, "Geant4Converter",
0823 "++ Volume %s Region: %s. Apply user limits from %s",
0824 vnam, wrd_nam, src_nam);
0825 }
0826 }
0827 else {
0828 g4vol->SetRegion(g4region);
0829 g4region->AddRootLogicalVolume(g4vol);
0830 }
0831 }
0832 G4VisAttributes* g4vattr = vis.isValid()
0833 ? (G4VisAttributes*)handleVis(vis.name(), vis) : nullptr;
0834 if ( g4vattr ) {
0835 g4vol->SetVisAttributes(g4vattr);
0836 }
0837 info.g4Volumes[volume] = g4vol;
0838 printout(lvl, "Geant4Converter",
0839 "++ Volume + %s converted: %p ---> G4: %p", vnam, volume, g4vol);
0840 }
0841 return nullptr;
0842 }
0843
0844
0845 void* Geant4Converter::collectVolume(const std::string& , const TGeoVolume* volume) const {
0846 Geant4GeometryInfo& info = data();
0847 Volume _v(volume);
0848 Region reg = _v.region();
0849 LimitSet lim = _v.limitSet();
0850 SensitiveDetector det = _v.sensitiveDetector();
0851 bool world = (volume == m_detDesc.worldVolume().ptr());
0852
0853 if ( !world ) {
0854 if ( lim.isValid() )
0855 info.limits[lim].insert(volume);
0856 if ( reg.isValid() )
0857 info.regions[reg].insert(volume);
0858 if ( det.isValid() )
0859 info.sensitives[det].insert(volume);
0860 }
0861 return (void*)volume;
0862 }
0863
0864
0865 void* Geant4Converter::handleAssembly(const std::string& name, const TGeoNode* node) const {
0866 TGeoVolume* mot_vol = node->GetVolume();
0867 PrintLevel lvl = debugVolumes ? ALWAYS : outputLevel;
0868 if ( mot_vol->IsA() != TGeoVolumeAssembly::Class() ) {
0869 return nullptr;
0870 }
0871 Volume _v(mot_vol);
0872 if ( _v.testFlagBit(Volume::VETO_SIMU) ) {
0873 printout(lvl, "Geant4Converter", "++ AssemblyNode %s not converted [Veto'ed for simulation]",node->GetName());
0874 return nullptr;
0875 }
0876 Geant4GeometryInfo& info = data();
0877 Geant4AssemblyVolume* g4 = info.g4AssemblyVolumes[node];
0878 if ( g4 ) {
0879 printout(ALWAYS, "Geant4Converter", "+++ Assembly: **** : Re-using existing assembly: %s",node->GetName());
0880 }
0881 if ( !g4 ) {
0882 g4 = new Geant4AssemblyVolume();
0883 for(Int_t i=0; i < mot_vol->GetNdaughters(); ++i) {
0884 TGeoNode* dau = mot_vol->GetNode(i);
0885 TGeoVolume* dau_vol = dau->GetVolume();
0886 TGeoMatrix* tr = dau->GetMatrix();
0887 G4Transform3D transform;
0888
0889 g4Transform(tr, transform);
0890 if ( is_left_handed(tr) ) {
0891 G4Scale3D scale;
0892 G4Rotate3D rot;
0893 G4Translate3D trans;
0894 transform.getDecomposition(scale, rot, trans);
0895 printout(debugReflections ? ALWAYS : lvl, "Geant4Converter",
0896 "++ Placing reflected ASSEMBLY. dau:%s to mother %s "
0897 "Tr:x=%8.1f y=%8.1f z=%8.1f Scale:x=%4.2f y=%4.2f z=%4.2f",
0898 dau_vol->GetName(), mot_vol->GetName(),
0899 transform.dx(), transform.dy(), transform.dz(),
0900 scale.xx(), scale.yy(), scale.zz());
0901 }
0902
0903 if ( dau_vol->IsA() == TGeoVolumeAssembly::Class() ) {
0904 Geant4GeometryMaps::AssemblyMap::iterator ia = info.g4AssemblyVolumes.find(dau);
0905 if ( ia == info.g4AssemblyVolumes.end() ) {
0906 printout(FATAL, "Geant4Converter", "+++ Invalid child assembly at %s : %d parent: %s child:%s",
0907 __FILE__, __LINE__, name.c_str(), dau->GetName());
0908 delete g4;
0909 return nullptr;
0910 }
0911 g4->placeAssembly(dau, (*ia).second, transform);
0912 printout(lvl, "Geant4Converter", "+++ Assembly: AddPlacedAssembly %p: dau:%s "
0913 "to mother %s Tr:x=%8.3f y=%8.3f z=%8.3f",
0914 (void*)dau_vol, dau_vol->GetName(), mot_vol->GetName(),
0915 transform.dx(), transform.dy(), transform.dz());
0916 }
0917 else {
0918 Geant4GeometryMaps::VolumeMap::iterator iv = info.g4Volumes.find(dau_vol);
0919 if ( iv == info.g4Volumes.end() ) {
0920 printout(FATAL,"Geant4Converter", "+++ Invalid child volume at %s : %d parent: %s child:%s",
0921 __FILE__, __LINE__, name.c_str(), dau->GetName());
0922 except("Geant4Converter", "+++ Invalid child volume at %s : %d parent: %s child:%s",
0923 __FILE__, __LINE__, name.c_str(), dau->GetName());
0924 }
0925 g4->placeVolume(dau,(*iv).second, transform);
0926 printout(lvl, "Geant4Converter", "+++ Assembly: AddPlacedVolume %p: dau:%s "
0927 "to mother %s Tr:x=%8.3f y=%8.3f z=%8.3f",
0928 (void*)dau_vol, dau_vol->GetName(), mot_vol->GetName(),
0929 transform.dx(), transform.dy(), transform.dz());
0930 }
0931 }
0932 info.g4AssemblyVolumes[node] = g4;
0933 }
0934 return g4;
0935 }
0936
0937
0938 void* Geant4Converter::handlePlacement(const std::string& name, const TGeoNode* node) const {
0939 Geant4GeometryInfo& info = data();
0940 PrintLevel lvl = debugPlacements ? ALWAYS : outputLevel;
0941 Geant4GeometryMaps::PlacementMap::const_iterator g4it = info.g4Placements.find(node);
0942 G4VPhysicalVolume* g4 = (g4it == info.g4Placements.end()) ? 0 : (*g4it).second;
0943 TGeoVolume* vol = node->GetVolume();
0944 Volume _v(vol);
0945
0946 if ( _v.testFlagBit(Volume::VETO_SIMU) ) {
0947 printout(lvl, "Geant4Converter", "++ Placement %s not converted [Veto'ed for simulation]",node->GetName());
0948 return nullptr;
0949 }
0950
0951 if ( !g4 ) {
0952 TGeoVolume* mot_vol = node->GetMotherVolume();
0953 TGeoMatrix* tr = node->GetMatrix();
0954 if ( !tr ) {
0955 except("Geant4Converter",
0956 "++ Attempt to handle placement without transformation:%p %s of type %s vol:%p",
0957 node, node->GetName(), node->IsA()->GetName(), vol);
0958 }
0959 else if (nullptr == vol) {
0960 except("Geant4Converter", "++ Unknown G4 volume:%p %s of type %s ptr:%p",
0961 node, node->GetName(), node->IsA()->GetName(), vol);
0962 }
0963 else {
0964 int copy = node->GetNumber();
0965 bool node_is_reflected = is_left_handed(tr);
0966 bool node_is_assembly = vol->IsA() == TGeoVolumeAssembly::Class();
0967 bool mother_is_assembly = mot_vol ? mot_vol->IsA() == TGeoVolumeAssembly::Class() : false;
0968 G4Transform3D transform;
0969 Geant4GeometryMaps::VolumeMap::const_iterator volIt = info.g4Volumes.find(mot_vol);
0970
0971 g4Transform(tr, transform);
0972 if ( mother_is_assembly ) {
0973
0974
0975
0976
0977
0978
0979 printout(lvl, "Geant4Converter", "+++ Assembly: **** : dau:%s "
0980 "to mother %s Tr:x=%8.3f y=%8.3f z=%8.3f",
0981 vol->GetName(), mot_vol->GetName(),
0982 transform.dx(), transform.dy(), transform.dz());
0983 return nullptr;
0984 }
0985 G4Scale3D scale;
0986 G4Rotate3D rot;
0987 G4Translate3D trans;
0988 transform.getDecomposition(scale, rot, trans);
0989 if ( node_is_assembly ) {
0990
0991
0992
0993
0994 printout(lvl, "Geant4Converter", "++ Assembly: makeImprint: dau:%-12s %s in mother %-12s "
0995 "Tr:x=%8.1f y=%8.1f z=%8.1f Scale:x=%4.2f y=%4.2f z=%4.2f",
0996 node->GetName(), node_is_reflected ? "(REFLECTED)" : "",
0997 mot_vol ? mot_vol->GetName() : "<unknown>",
0998 transform.dx(), transform.dy(), transform.dz(),
0999 scale.xx(), scale.yy(), scale.zz());
1000 Geant4AssemblyVolume* ass = (Geant4AssemblyVolume*)info.g4AssemblyVolumes[node];
1001 Geant4AssemblyVolume::Chain chain;
1002 chain.emplace_back(node);
1003 ass->imprint(*this, node, chain, ass, (*volIt).second, transform, checkOverlaps);
1004 return nullptr;
1005 }
1006 else if ( node != info.manager->GetTopNode() && volIt == info.g4Volumes.end() ) {
1007
1008 }
1009 PlacedVolume pv(node);
1010 const auto* pv_data = pv.data();
1011 G4LogicalVolume* g4vol = info.g4Volumes[vol];
1012 G4LogicalVolume* g4mot = info.g4Volumes[mot_vol];
1013 G4PhysicalVolumesPair pvPlaced { nullptr, nullptr };
1014
1015 if ( pv_data && pv_data->params && (pv_data->params->flags&Volume::REPLICATED) ) {
1016 EAxis axis = kUndefined;
1017 double width = 0e0, offset = 0e0;
1018 auto flags = pv_data->params->flags;
1019 auto count = pv_data->params->trafo1D.second;
1020 auto start = pv_data->params->start.Translation().Vect();
1021 auto delta = pv_data->params->trafo1D.first.Translation().Vect();
1022
1023 if ( flags&Volume::X_axis )
1024 { axis = kXAxis; width = delta.X(); offset = start.X(); }
1025 else if ( flags&Volume::Y_axis )
1026 { axis = kYAxis; width = delta.Y(); offset = start.Y(); }
1027 else if ( flags&Volume::Z_axis )
1028 { axis = kZAxis; width = delta.Z(); offset = start.Z(); }
1029 else
1030 except("Geant4Converter",
1031 "++ Replication around unknown axis is not implemented. flags: %16X", flags);
1032 printout(INFO,"Geant4Converter","++ Replicate: Axis: %ld Count: %ld offset: %f width: %f",
1033 axis, count, offset, width);
1034 auto* g4pv = new G4PVReplica(name,
1035 g4vol,
1036 g4mot,
1037 axis,
1038 count,
1039 width,
1040 offset);
1041 pvPlaced = { g4pv, nullptr };
1042 #if 0
1043 pvPlaced =
1044 G4ReflectionFactory::Instance()->Replicate(name,
1045 g4vol,
1046 g4mot,
1047 axis,
1048 count,
1049 width,
1050 offset);
1051
1052 auto* g4pv = pvPlaced.second ? pvPlaced.second : pvPlaced.first;
1053 #endif
1054 for( auto& handle : pv_data->params->placements )
1055 info.g4Placements[handle.ptr()] = g4pv;
1056 }
1057 else if ( pv_data && pv_data->params ) {
1058 auto* g4par = new Geant4PlacementParameterisation(pv);
1059 auto* g4pv = new G4PVParameterised(name,
1060 g4vol,
1061 g4mot,
1062 g4par->axis(),
1063 g4par->count(),
1064 g4par);
1065 pvPlaced = { g4pv, nullptr };
1066
1067 for( auto& handle : pv_data->params->placements )
1068 info.g4Placements[handle.ptr()] = g4pv;
1069 }
1070 else {
1071 pvPlaced =
1072 G4ReflectionFactory::Instance()->Place(transform,
1073 name,
1074 g4vol,
1075 g4mot,
1076 false,
1077 copy,
1078 checkOverlaps);
1079 }
1080 printout(debugReflections||debugPlacements ? ALWAYS : lvl, "Geant4Converter",
1081 "++ Place %svolume %-12s in mother %-12s "
1082 "Tr:x=%8.1f y=%8.1f z=%8.1f Scale:x=%4.2f y=%4.2f z=%4.2f",
1083 node_is_reflected ? "REFLECTED " : "", _v.name(),
1084 mot_vol ? mot_vol->GetName() : "<unknown>",
1085 transform.dx(), transform.dy(), transform.dz(),
1086 scale.xx(), scale.yy(), scale.zz());
1087
1088
1089 if ( node_is_reflected && !pvPlaced.second )
1090 return info.g4Placements[node] = pvPlaced.first;
1091 else if ( !node_is_reflected && !pvPlaced.second )
1092 return info.g4Placements[node] = pvPlaced.first;
1093
1094 if ( node_is_reflected )
1095 return info.g4Placements[node] = pvPlaced.first;
1096 else if ( !node_is_reflected )
1097 return info.g4Placements[node] = pvPlaced.first;
1098 g4 = pvPlaced.second ? pvPlaced.second : pvPlaced.first;
1099 }
1100 info.g4Placements[node] = g4;
1101 printout(ERROR, "Geant4Converter", "++ DEAD code. Should not end up here!");
1102 }
1103 return g4;
1104 }
1105
1106
1107 void* Geant4Converter::handleRegion(Region region, const std::set<const TGeoVolume*>& ) const {
1108 G4Region* g4 = data().g4Regions[region];
1109 if ( !g4 ) {
1110 PrintLevel lvl = debugRegions ? ALWAYS : outputLevel;
1111 Region r = region;
1112 g4 = new G4Region(region.name());
1113
1114
1115 if( not r.wasThresholdSet() and r.storeSecondaries() ) {
1116 throw std::runtime_error("G4Region: StoreSecondaries is True, but no explicit threshold set:");
1117 }
1118 printout(lvl, "Geant4Converter", "++ Setting up region: %s", r.name());
1119 G4UserRegionInformation* info = new G4UserRegionInformation();
1120 info->region = r;
1121 info->threshold = r.threshold()*CLHEP::MeV/units::MeV;
1122 info->storeSecondaries = r.storeSecondaries();
1123 g4->SetUserInformation(info);
1124
1125 printout(lvl, "Geant4Converter", "++ Converted region settings of:%s.", r.name());
1126 std::vector < std::string > &limits = r.limits();
1127 G4ProductionCuts* cuts = 0;
1128
1129 if( not r.useDefaultCut() ) {
1130 cuts = new G4ProductionCuts();
1131 cuts->SetProductionCut(r.cut()*CLHEP::mm/units::mm);
1132 printout(lvl, "Geant4Converter", "++ %s: Using default cut: %f [mm]",
1133 r.name(), r.cut()*CLHEP::mm/units::mm);
1134 }
1135 for( const auto& nam : limits ) {
1136 LimitSet ls = m_detDesc.limitSet(nam);
1137 if ( ls.isValid() ) {
1138 const LimitSet::Set& cts = ls.cuts();
1139 for (const auto& c : cts ) {
1140 int pid = 0;
1141 if ( c.particles == "*" ) pid = -1;
1142 else if ( c.particles == "e-" ) pid = idxG4ElectronCut;
1143 else if ( c.particles == "e+" ) pid = idxG4PositronCut;
1144 else if ( c.particles == "e[+-]" ) pid = -idxG4PositronCut-idxG4ElectronCut;
1145 else if ( c.particles == "e[-+]" ) pid = -idxG4PositronCut-idxG4ElectronCut;
1146 else if ( c.particles == "gamma" ) pid = idxG4GammaCut;
1147 else if ( c.particles == "proton" ) pid = idxG4ProtonCut;
1148 else throw std::runtime_error("G4Region: Invalid production cut particle-type:" + c.particles);
1149 if ( !cuts ) cuts = new G4ProductionCuts();
1150 if ( pid == -(idxG4PositronCut+idxG4ElectronCut) ) {
1151 cuts->SetProductionCut(c.value*CLHEP::mm/units::mm, idxG4PositronCut);
1152 cuts->SetProductionCut(c.value*CLHEP::mm/units::mm, idxG4ElectronCut);
1153 }
1154 else {
1155 cuts->SetProductionCut(c.value*CLHEP::mm/units::mm, pid);
1156 }
1157 printout(lvl, "Geant4Converter", "++ %s: Set cut [%s/%d] = %f [mm]",
1158 r.name(), c.particles.c_str(), pid, c.value*CLHEP::mm/units::mm);
1159 }
1160 bool found = false;
1161 const auto& lm = data().g4Limits;
1162 for (const auto& j : lm ) {
1163 if (nam == j.first->GetName()) {
1164 g4->SetUserLimits(j.second);
1165 printout(lvl, "Geant4Converter", "++ %s: Set limits %s to region type %s",
1166 r.name(), nam.c_str(), j.second->GetType().c_str());
1167 found = true;
1168 break;
1169 }
1170 }
1171 if ( found ) {
1172 continue;
1173 }
1174 }
1175 except("Geant4Converter", "++ G4Region: Failed to resolve limitset: " + nam);
1176 }
1177
1178 if ( cuts ) g4->SetProductionCuts(cuts);
1179 data().g4Regions[region] = g4;
1180 }
1181 return g4;
1182 }
1183
1184
1185 void* Geant4Converter::handleLimitSet(LimitSet limitset, const std::set<const TGeoVolume*>& ) const {
1186 G4UserLimits* g4 = data().g4Limits[limitset];
1187 if ( !g4 ) {
1188 PrintLevel lvl = debugLimits || debugRegions ? ALWAYS : outputLevel;
1189 struct LimitPrint {
1190 const LimitSet& ls;
1191 LimitPrint(const LimitSet& lset) : ls(lset) {}
1192 const LimitPrint& operator()(const std::string& pref, const Geant4UserLimits::Handler& h) const {
1193 if ( !h.particleLimits.empty() ) {
1194 printout(ALWAYS,"Geant4Converter",
1195 "+++ LimitSet: Explicit Limit %s.%s applied for particles:",ls.name(), pref.c_str());
1196 for(const auto& p : h.particleLimits)
1197 printout(ALWAYS,"Geant4Converter","+++ LimitSet: Particle type: %-18s PDG: %-6d : %f",
1198 p.first->GetParticleName().c_str(), p.first->GetPDGEncoding(), p.second);
1199 }
1200 else if ( h.defaultValue > std::numeric_limits<double>::epsilon() ) {
1201 printout(ALWAYS,"Geant4Converter",
1202 "+++ LimitSet: Implicit Limit %s.%s for wildcard particles: %f",
1203 ls.name(), pref.c_str(), float(h.defaultValue));
1204 }
1205 return *this;
1206 }
1207 };
1208 Geant4UserLimits* limits = new Geant4UserLimits(limitset);
1209 g4 = limits;
1210 printout(lvl, "Geant4Converter",
1211 "++ Successfully converted LimitSet: %s [%ld cuts, %ld limits]",
1212 limitset.name(), limitset.cuts().size(), limitset.limits().size());
1213 if ( debugRegions || debugLimits ) {
1214 LimitPrint print(limitset);
1215 print("maxTime", limits->maxTime)
1216 ("minEKine", limits->minEKine)
1217 ("minRange", limits->minRange)
1218 ("maxStepLength", limits->maxStepLength)
1219 ("maxTrackLength",limits->maxTrackLength);
1220 }
1221 data().g4Limits[limitset] = g4;
1222 }
1223 return g4;
1224 }
1225
1226
1227 void* Geant4Converter::handleVis(const std::string& , VisAttr attr) const {
1228 Geant4GeometryInfo& info = data();
1229 G4VisAttributes* g4 = info.g4Vis[attr];
1230 if ( !g4 ) {
1231 float red = 0, green = 0, blue = 0;
1232 int style = attr.lineStyle();
1233 attr.rgb(red, green, blue);
1234 g4 = new G4VisAttributes(attr.visible(), G4Colour(red, green, blue, attr.alpha()));
1235
1236 g4->SetDaughtersInvisible(!attr.showDaughters());
1237 if ( style == VisAttr::SOLID ) {
1238 g4->SetLineStyle(G4VisAttributes::unbroken);
1239 g4->SetForceWireframe(false);
1240 g4->SetForceSolid(true);
1241 }
1242 else if ( style == VisAttr::WIREFRAME || style == VisAttr::DASHED ) {
1243 g4->SetLineStyle(G4VisAttributes::dashed);
1244 g4->SetForceSolid(false);
1245 g4->SetForceWireframe(true);
1246 }
1247 info.g4Vis[attr] = g4;
1248 }
1249 return g4;
1250 }
1251
1252
1253 void Geant4Converter::handleProperties(Detector::Properties& prp) const {
1254 std::map < std::string, std::string > processors;
1255 static int s_idd = 9999999;
1256 for( const auto& [nam, vals] : prp ) {
1257 if ( nam.substr(0, 6) == "geant4" ) {
1258 auto id_it = vals.find("id");
1259 std::string id = (id_it == vals.end()) ? _toString(++s_idd,"%d") : (*id_it).second;
1260 processors.emplace(id, nam);
1261 }
1262 }
1263 for( const auto& p : processors ) {
1264 const GeoHandler* hdlr = this;
1265 const Detector::PropertyValues& vals = prp[p.second];
1266 auto iter = vals.find("type");
1267 if ( iter != vals.end() ) {
1268 std::string type = iter->second;
1269 std::string tag = type + "_Geant4_action";
1270 Detector* det = const_cast<Detector*>(&m_detDesc);
1271 long res = PluginService::Create<long>(tag, det, hdlr, &vals);
1272 if ( 0 == res ) {
1273 throw std::runtime_error("Failed to locate plugin to interprete files of type"
1274 " \"" + tag + "\" - no factory:" + type);
1275 }
1276 res = *(long*)res;
1277 if ( res != 1 ) {
1278 throw std::runtime_error("Failed to invoke the plugin " + tag + " of type " + type);
1279 }
1280 printout(outputLevel, "Geant4Converter", "+++++ Executed Successfully Geant4 setup module *%s*.", type.c_str());
1281 continue;
1282 }
1283 printout(outputLevel, "Geant4Converter", "+++++ FAILED to execute Geant4 setup module *%s*.", p.second.c_str());
1284 }
1285 }
1286
1287
1288 void* Geant4Converter::handleMaterialProperties(TObject* mtx) const {
1289 Geant4GeometryInfo& info = data();
1290 TGDMLMatrix* matrix = (TGDMLMatrix*)mtx;
1291 const char* cptr = ::strstr(matrix->GetName(), GEANT4_TAG_IGNORE);
1292 Geant4GeometryInfo::PropertyVector* g4 = info.g4OpticalProperties[matrix];
1293
1294 if ( nullptr != cptr ) {
1295 printout(INFO,"Geant4MaterialProperties","++ Ignore property %s [%s].",
1296 matrix->GetName(), matrix->GetTitle());
1297 return nullptr;
1298 }
1299 cptr = ::strstr(matrix->GetTitle(), GEANT4_TAG_IGNORE);
1300 if ( nullptr != cptr ) {
1301 printout(INFO,"Geant4MaterialProperties","++ Ignore property %s [%s].",
1302 matrix->GetName(), matrix->GetTitle());
1303 return nullptr;
1304 }
1305
1306 if ( !g4 ) {
1307 PrintLevel lvl = debugMaterials ? ALWAYS : outputLevel;
1308 g4 = new Geant4GeometryInfo::PropertyVector();
1309 std::size_t rows = matrix->GetRows();
1310 g4->name = matrix->GetName();
1311 g4->title = matrix->GetTitle();
1312 g4->bins.reserve(rows);
1313 g4->values.reserve(rows);
1314 for( std::size_t i=0; i<rows; ++i ) {
1315 g4->bins.emplace_back(matrix->Get(i,0) );
1316 g4->values.emplace_back(matrix->Get(i,1));
1317 }
1318 printout(lvl, "Geant4Converter",
1319 "++ Successfully converted material property:%s : %s [%ld rows]",
1320 matrix->GetName(), matrix->GetTitle(), rows);
1321 info.g4OpticalProperties[matrix] = g4;
1322 }
1323 return g4;
1324 }
1325
1326 static G4OpticalSurfaceFinish geant4_surface_finish(TGeoOpticalSurface::ESurfaceFinish f) {
1327 #define TO_G4_FINISH(x) case TGeoOpticalSurface::kF##x : return x;
1328 switch(f) {
1329 TO_G4_FINISH(polished);
1330 TO_G4_FINISH(polishedfrontpainted);
1331 TO_G4_FINISH(polishedbackpainted);
1332
1333 TO_G4_FINISH(ground);
1334 TO_G4_FINISH(groundfrontpainted);
1335 TO_G4_FINISH(groundbackpainted);
1336
1337 TO_G4_FINISH(polishedlumirrorair);
1338 TO_G4_FINISH(polishedlumirrorglue);
1339 TO_G4_FINISH(polishedair);
1340 TO_G4_FINISH(polishedteflonair);
1341 TO_G4_FINISH(polishedtioair);
1342 TO_G4_FINISH(polishedtyvekair);
1343 TO_G4_FINISH(polishedvm2000air);
1344 TO_G4_FINISH(polishedvm2000glue);
1345
1346 TO_G4_FINISH(etchedlumirrorair);
1347 TO_G4_FINISH(etchedlumirrorglue);
1348 TO_G4_FINISH(etchedair);
1349 TO_G4_FINISH(etchedteflonair);
1350 TO_G4_FINISH(etchedtioair);
1351 TO_G4_FINISH(etchedtyvekair);
1352 TO_G4_FINISH(etchedvm2000air);
1353 TO_G4_FINISH(etchedvm2000glue);
1354
1355 TO_G4_FINISH(groundlumirrorair);
1356 TO_G4_FINISH(groundlumirrorglue);
1357 TO_G4_FINISH(groundair);
1358 TO_G4_FINISH(groundteflonair);
1359 TO_G4_FINISH(groundtioair);
1360 TO_G4_FINISH(groundtyvekair);
1361 TO_G4_FINISH(groundvm2000air);
1362 TO_G4_FINISH(groundvm2000glue);
1363
1364
1365 TO_G4_FINISH(Rough_LUT);
1366 TO_G4_FINISH(RoughTeflon_LUT);
1367 TO_G4_FINISH(RoughESR_LUT);
1368 TO_G4_FINISH(RoughESRGrease_LUT);
1369 TO_G4_FINISH(Polished_LUT);
1370 TO_G4_FINISH(PolishedTeflon_LUT);
1371 TO_G4_FINISH(PolishedESR_LUT);
1372 TO_G4_FINISH(PolishedESRGrease_LUT);
1373 TO_G4_FINISH(Detector_LUT);
1374 default:
1375 printout(ERROR,"Geant4Surfaces","++ Unknown finish style: %d [%s]. Assume polished!",
1376 int(f), TGeoOpticalSurface::FinishToString(f));
1377 return polished;
1378 }
1379 #undef TO_G4_FINISH
1380 }
1381
1382 static G4SurfaceType geant4_surface_type(TGeoOpticalSurface::ESurfaceType t) {
1383 #define TO_G4_TYPE(x) case TGeoOpticalSurface::kT##x : return x;
1384 switch(t) {
1385 TO_G4_TYPE(dielectric_metal);
1386 TO_G4_TYPE(dielectric_dielectric);
1387 TO_G4_TYPE(dielectric_LUT);
1388 TO_G4_TYPE(dielectric_LUTDAVIS);
1389 TO_G4_TYPE(dielectric_dichroic);
1390 TO_G4_TYPE(firsov);
1391 TO_G4_TYPE(x_ray);
1392 default:
1393 printout(ERROR,"Geant4Surfaces","++ Unknown surface type: %d [%s]. Assume dielectric_metal!",
1394 int(t), TGeoOpticalSurface::TypeToString(t));
1395 return dielectric_metal;
1396 }
1397 #undef TO_G4_TYPE
1398 }
1399
1400 static G4OpticalSurfaceModel geant4_surface_model(TGeoOpticalSurface::ESurfaceModel surfMod) {
1401 #define TO_G4_MODEL(x) case TGeoOpticalSurface::kM##x : return x;
1402 switch(surfMod) {
1403 TO_G4_MODEL(glisur);
1404 TO_G4_MODEL(unified);
1405 TO_G4_MODEL(LUT);
1406 TO_G4_MODEL(DAVIS);
1407 TO_G4_MODEL(dichroic);
1408 default:
1409 printout(ERROR,"Geant4Surfaces","++ Unknown surface model: %d [%s]. Assume glisur!",
1410 int(surfMod), TGeoOpticalSurface::ModelToString(surfMod));
1411 return glisur;
1412 }
1413 #undef TO_G4_MODEL
1414 }
1415
1416
1417 void* Geant4Converter::handleOpticalSurface(TObject* surface) const {
1418 TGeoOpticalSurface* optSurf = (TGeoOpticalSurface*)surface;
1419 Geant4GeometryInfo& info = data();
1420 G4OpticalSurface* g4 = info.g4OpticalSurfaces[optSurf];
1421 if ( !g4 ) {
1422 G4SurfaceType type = geant4_surface_type(optSurf->GetType());
1423 G4OpticalSurfaceModel model = geant4_surface_model(optSurf->GetModel());
1424 G4OpticalSurfaceFinish finish = geant4_surface_finish(optSurf->GetFinish());
1425 std::string name = make_NCName(optSurf->GetName());
1426 PrintLevel lvl = debugSurfaces ? ALWAYS : DEBUG;
1427 g4 = new G4OpticalSurface(name, model, finish, type, optSurf->GetValue());
1428 g4->SetSigmaAlpha(optSurf->GetSigmaAlpha());
1429 g4->SetPolish(optSurf->GetPolish());
1430
1431 printout(lvl, "Geant4Converter",
1432 "++ Created OpticalSurface: %-18s type:%s model:%s finish:%s SigmaAlphs: %.3e Polish: %.3e",
1433 optSurf->GetName(),
1434 TGeoOpticalSurface::TypeToString(optSurf->GetType()),
1435 TGeoOpticalSurface::ModelToString(optSurf->GetModel()),
1436 TGeoOpticalSurface::FinishToString(optSurf->GetFinish()),
1437 optSurf->GetSigmaAlpha(), optSurf->GetPolish());
1438
1439
1440 G4MaterialPropertiesTable* tab = nullptr;
1441 TListIter itp(&optSurf->GetProperties());
1442 for(TObject* obj = itp.Next(); obj; obj = itp.Next()) {
1443 std::string exc_str;
1444 TNamed* named = (TNamed*)obj;
1445 TGDMLMatrix* matrix = info.manager->GetGDMLMatrix(named->GetTitle());
1446 const char* cptr = ::strstr(matrix->GetName(), GEANT4_TAG_IGNORE);
1447 if ( nullptr != cptr )
1448 continue;
1449
1450 if ( nullptr == tab ) {
1451 tab = new G4MaterialPropertiesTable();
1452 g4->SetMaterialPropertiesTable(tab);
1453 }
1454
1455 Geant4GeometryInfo::PropertyVector* v =
1456 (Geant4GeometryInfo::PropertyVector*)handleMaterialProperties(matrix);
1457 if ( !v ) {
1458 except("Geant4OpticalSurface","++ Failed to convert opt.surface %s. Property table %s is not defined!",
1459 optSurf->GetName(), named->GetTitle());
1460 }
1461 int idx = -1;
1462 try {
1463 idx = tab->GetPropertyIndex(named->GetName());
1464 }
1465 catch(const std::exception& e) {
1466 exc_str = e.what();
1467 }
1468 catch(...) {
1469 }
1470 if ( idx < 0 ) {
1471 printout(ERROR, "Geant4Converter",
1472 "++ UNKNOWN Geant4 Property: %-20s %s [IGNORED]",
1473 exc_str.c_str(), named->GetName());
1474 continue;
1475 }
1476
1477 auto conv = g4PropertyConversion(idx);
1478 std::vector<double> bins(v->bins), vals(v->values);
1479 for(std::size_t i=0, count=v->bins.size(); i<count; ++i)
1480 bins[i] *= conv.first, vals[i] *= conv.second;
1481 G4MaterialPropertyVector* vec = new G4MaterialPropertyVector(&bins[0], &vals[0], bins.size());
1482 tab->AddProperty(named->GetName(), vec);
1483
1484 printout(lvl, "Geant4Converter",
1485 "++ Property: %-20s [%ld x %ld] --> %s",
1486 named->GetName(), matrix->GetRows(), matrix->GetCols(), named->GetTitle());
1487 for(std::size_t i=0, count=v->bins.size(); i<count; ++i)
1488 printout(lvl, named->GetName(),
1489 " Geant4: %8.3g [MeV] TGeo: %8.3g [GeV] Conversion: %8.3g",
1490 bins[i], v->bins[i], conv.first);
1491 }
1492
1493
1494 #if ROOT_VERSION_CODE >= ROOT_VERSION(6,31,1)
1495 TListIter itc(&optSurf->GetConstProperties());
1496 for(TObject* obj = itc.Next(); obj; obj = itc.Next()) {
1497 std::string exc_str;
1498 TNamed* named = (TNamed*)obj;
1499 const char* cptr = ::strstr(named->GetName(), GEANT4_TAG_IGNORE);
1500 if ( nullptr != cptr ) {
1501 printout(INFO, name, "++ Ignore CONST property %s [%s].",
1502 named->GetName(), named->GetTitle());
1503 continue;
1504 }
1505 cptr = ::strstr(named->GetTitle(), GEANT4_TAG_IGNORE);
1506 if ( nullptr != cptr ) {
1507 printout(INFO, name,"++ Ignore CONST property %s [%s].",
1508 named->GetName(), named->GetTitle());
1509 continue;
1510 }
1511 Bool_t err = kFALSE;
1512 Double_t value = info.manager->GetProperty(named->GetTitle(),&err);
1513 if ( err != kFALSE ) {
1514 except(name,
1515 "++ FAILED to create G4 material %s [Cannot convert const property: %s]",
1516 optSurf->GetName(), named->GetName());
1517 }
1518 if ( nullptr == tab ) {
1519 tab = new G4MaterialPropertiesTable();
1520 g4->SetMaterialPropertiesTable(tab);
1521 }
1522 int idx = -1;
1523 try {
1524 idx = tab->GetConstPropertyIndex(named->GetName());
1525 }
1526 catch(const std::exception& e) {
1527 exc_str = e.what();
1528 }
1529 catch(...) {
1530 }
1531 if ( idx < 0 ) {
1532 printout(ERROR, name,
1533 "++ UNKNOWN Geant4 CONST Property: %-20s %s [IGNORED]",
1534 exc_str.c_str(), named->GetName());
1535 continue;
1536 }
1537
1538 double conv = g4ConstPropertyConversion(idx);
1539 printout(lvl, name, "++ CONST Property: %-20s %g * %g --> %g ",
1540 named->GetName(), value, conv, value * conv);
1541 tab->AddConstProperty(named->GetName(), value * conv);
1542 }
1543 #endif
1544 info.g4OpticalSurfaces[optSurf] = g4;
1545 }
1546 return g4;
1547 }
1548
1549
1550 void* Geant4Converter::handleSkinSurface(TObject* surface) const {
1551 TGeoSkinSurface* surf = (TGeoSkinSurface*)surface;
1552 Geant4GeometryInfo& info = data();
1553 G4LogicalSkinSurface* g4 = info.g4SkinSurfaces[surf];
1554 if ( !g4 ) {
1555 G4OpticalSurface* optSurf = info.g4OpticalSurfaces[OpticalSurface(surf->GetSurface())];
1556 G4LogicalVolume* v = info.g4Volumes[surf->GetVolume()];
1557 std::string name = make_NCName(surf->GetName());
1558 g4 = new G4LogicalSkinSurface(name, v, optSurf);
1559 printout(debugSurfaces ? ALWAYS : DEBUG, "Geant4Converter",
1560 "++ Created SkinSurface: %-18s optical:%s",
1561 surf->GetName(), surf->GetSurface()->GetName());
1562 info.g4SkinSurfaces[surf] = g4;
1563 }
1564 return g4;
1565 }
1566
1567
1568 void* Geant4Converter::handleBorderSurface(TObject* surface) const {
1569 TGeoBorderSurface* surf = (TGeoBorderSurface*)surface;
1570 Geant4GeometryInfo& info = data();
1571 G4LogicalBorderSurface* g4 = info.g4BorderSurfaces[surf];
1572 if ( !g4 ) {
1573 G4OpticalSurface* optSurf = info.g4OpticalSurfaces[OpticalSurface(surf->GetSurface())];
1574 G4VPhysicalVolume* n1 = info.g4Placements[surf->GetNode1()];
1575 G4VPhysicalVolume* n2 = info.g4Placements[surf->GetNode2()];
1576 std::string name = make_NCName(surf->GetName());
1577 g4 = new G4LogicalBorderSurface(name, n1, n2, optSurf);
1578 printout(debugSurfaces ? ALWAYS : DEBUG, "Geant4Converter",
1579 "++ Created BorderSurface: %-18s optical:%s",
1580 surf->GetName(), surf->GetSurface()->GetName());
1581 info.g4BorderSurfaces[surf] = g4;
1582 }
1583 return g4;
1584 }
1585
1586
1587 void Geant4Converter::printSensitive(SensitiveDetector sens_det, const std::set<const TGeoVolume*>& ) const {
1588 Geant4GeometryInfo& info = data();
1589 std::set<const TGeoVolume*>& volset = info.sensitives[sens_det];
1590 SensitiveDetector sd = sens_det;
1591 std::stringstream str;
1592
1593 printout(INFO, "Geant4Converter", "++ SensitiveDetector: %-18s %-20s Hits:%-16s", sd.name(), ("[" + sd.type() + "]").c_str(),
1594 sd.hitsCollection().c_str());
1595 str << " | " << "Cutoff:" << std::setw(6) << std::left
1596 << sd.energyCutoff() << std::setw(5) << std::right << volset.size()
1597 << " volumes ";
1598 if (sd.region().isValid())
1599 str << " Region:" << std::setw(12) << std::left << sd.region().name();
1600 if (sd.limits().isValid())
1601 str << " Limits:" << std::setw(12) << std::left << sd.limits().name();
1602 str << ".";
1603 printout(INFO, "Geant4Converter", str.str().c_str());
1604
1605 for (const auto i : volset ) {
1606 std::map<Volume, G4LogicalVolume*>::iterator v = info.g4Volumes.find(i);
1607 if ( v != info.g4Volumes.end() ) {
1608 G4LogicalVolume* vol = (*v).second;
1609 str.str("");
1610 str << " | " << "Volume:" << std::setw(24) << std::left << vol->GetName() << " "
1611 << vol->GetNoDaughters() << " daughters.";
1612 printout(INFO, "Geant4Converter", str.str().c_str());
1613 }
1614 }
1615 }
1616
1617 std::string printSolid(G4VSolid* sol) {
1618 std::stringstream str;
1619 if (typeid(*sol) == typeid(G4Box)) {
1620 const G4Box* b = (G4Box*) sol;
1621 str << "++ Box: x=" << b->GetXHalfLength() << " y=" << b->GetYHalfLength() << " z=" << b->GetZHalfLength();
1622 }
1623 else if (typeid(*sol) == typeid(G4Tubs)) {
1624 const G4Tubs* t = (const G4Tubs*) sol;
1625 str << " Tubs: Ri=" << t->GetInnerRadius() << " Ra=" << t->GetOuterRadius() << " z/2=" << t->GetZHalfLength() << " Phi="
1626 << t->GetStartPhiAngle() << "..." << t->GetDeltaPhiAngle();
1627 }
1628 return str.str();
1629 }
1630
1631
1632 void* Geant4Converter::printPlacement(const std::string& name, const TGeoNode* node) const {
1633 Geant4GeometryInfo& info = data();
1634 G4VPhysicalVolume* g4 = info.g4Placements[node];
1635 G4LogicalVolume* vol = info.g4Volumes[node->GetVolume()];
1636 G4LogicalVolume* mot = info.g4Volumes[node->GetMotherVolume()];
1637 G4VSolid* sol = vol->GetSolid();
1638 G4ThreeVector tr = g4->GetObjectTranslation();
1639 G4VSensitiveDetector* sd = vol->GetSensitiveDetector();
1640 if ( !sd ) {
1641 return g4;
1642 }
1643 std::stringstream str;
1644 str << "G4Cnv::placement: + " << name << " No:" << node->GetNumber() << " Vol:" << vol->GetName() << " Solid:"
1645 << sol->GetName();
1646 printout(outputLevel, "G4Placement", str.str().c_str());
1647 str.str("");
1648 str << " |" << " Loc: x=" << tr.x() << " y=" << tr.y() << " z=" << tr.z();
1649 printout(outputLevel, "G4Placement", str.str().c_str());
1650 printout(outputLevel, "G4Placement", printSolid(sol).c_str());
1651 str.str("");
1652 str << " |" << " Ndau:" << vol->GetNoDaughters()
1653 << " physvols." << " Mat:" << vol->GetMaterial()->GetName()
1654 << " Mother:" << (char*) (mot ? mot->GetName().c_str() : "---");
1655 printout(outputLevel, "G4Placement", str.str().c_str());
1656 str.str("");
1657 str << " |" << " SD:" << sd->GetName();
1658 printout(outputLevel, "G4Placement", str.str().c_str());
1659 return g4;
1660 }
1661
1662
1663 Geant4Converter& Geant4Converter::create(DetElement top) {
1664 typedef std::map<const TGeoNode*, std::vector<TGeoNode*> > _DAU;
1665 TTimeStamp start;
1666 _DAU daughters;
1667 Geant4GeometryInfo& geo = this->init();
1668 World wrld = top.world();
1669
1670 m_data->clear();
1671 m_set_data->clear();
1672 m_daughters = &daughters;
1673 geo.manager = &wrld.detectorDescription().manager();
1674 this->collect(top, geo);
1675 this->checkOverlaps = false;
1676
1677
1678
1679 handleArray(this, geo.manager->GetListOfGDMLMatrices(), &Geant4Converter::handleMaterialProperties);
1680 handleArray(this, geo.manager->GetListOfOpticalSurfaces(), &Geant4Converter::handleOpticalSurface);
1681
1682 handle(this, geo.volumes, &Geant4Converter::collectVolume);
1683 handle(this, geo.solids, &Geant4Converter::handleSolid);
1684 printout(outputLevel, "Geant4Converter", "++ Handled %ld solids.", geo.solids.size());
1685 handleRefs(this, geo.vis, &Geant4Converter::handleVis);
1686 printout(outputLevel, "Geant4Converter", "++ Handled %ld visualization attributes.", geo.vis.size());
1687 handleMap(this, geo.limits, &Geant4Converter::handleLimitSet);
1688 printout(outputLevel, "Geant4Converter", "++ Handled %ld limit sets.", geo.limits.size());
1689 handleMap(this, geo.regions, &Geant4Converter::handleRegion);
1690 printout(outputLevel, "Geant4Converter", "++ Handled %ld regions.", geo.regions.size());
1691 handle(this, geo.volumes, &Geant4Converter::handleVolume);
1692 printout(outputLevel, "Geant4Converter", "++ Handled %ld volumes.", geo.volumes.size());
1693 handleRMap(this, *m_data, &Geant4Converter::handleAssembly);
1694
1695
1696 std::map<int, std::vector<const TGeoNode*> >::const_reverse_iterator i = m_data->rbegin();
1697 for ( ; i != m_data->rend(); ++i ) {
1698 for ( const TGeoNode* node : i->second ) {
1699 this->handlePlacement(node->GetName(), node);
1700 }
1701 }
1702
1703 handleArray(this, geo.manager->GetListOfSkinSurfaces(), &Geant4Converter::handleSkinSurface);
1704 handleArray(this, geo.manager->GetListOfBorderSurfaces(), &Geant4Converter::handleBorderSurface);
1705
1706 handleProperties(m_detDesc.properties());
1707 if ( printSensitives ) {
1708 handleMap(this, geo.sensitives, &Geant4Converter::printSensitive);
1709 }
1710 if ( printPlacements ) {
1711 handleRMap(this, *m_data, &Geant4Converter::printPlacement);
1712 }
1713
1714 m_daughters = nullptr;
1715 geo.setWorld(top.placement().ptr());
1716 geo.valid = true;
1717 TTimeStamp stop;
1718 printout(INFO, "Geant4Converter",
1719 "+++ Successfully converted geometry to Geant4. [%7.3f seconds]",
1720 stop.AsDouble()-start.AsDouble() );
1721 return *this;
1722 }