Newer
Older
Markus Frank
committed
        Geant4AssemblyVolume::Chain chain;
        chain.emplace_back(node);
        ass->imprint(*this, node, chain, ass, (*volIt).second, transform, copy, checkOverlaps);
      else if ( node != info.manager->GetTopNode() && volIt == info.g4Volumes.end() )  {
        //throw std::logic_error("Geant4Converter: Invalid mother volume found!");
      PlacedVolume pv(node);
      const auto*  pv_data = pv.data();
      G4LogicalVolume* g4vol = info.g4Volumes[vol];
      G4LogicalVolume* g4mot = info.g4Volumes[mot_vol];
      G4PhysicalVolumesPair pvPlaced  { nullptr, nullptr };
      if ( pv_data && pv_data->params && (pv_data->params->flags&Volume::REPLICATED) )   {
Markus Frank
committed
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
        EAxis  axis = kUndefined;
        double width = 0e0, offset = 0e0;
        auto flags = pv_data->params->flags;
        auto count = pv_data->params->trafo1D.second;
        auto start = pv_data->params->start.Translation().Vect();
        auto delta = pv_data->params->trafo1D.first.Translation().Vect();
        if ( flags&Volume::X_axis )
        { axis = kXAxis; width = delta.X(); offset = start.X(); }
        else if ( flags&Volume::Y_axis )
        { axis = kYAxis; width = delta.Y(); offset = start.Y(); }
        else if ( flags&Volume::Z_axis )
        { axis = kZAxis; width = delta.Z(); offset = start.Z(); }
        else
          except("Geant4Converter",
                 "++ Replication around unknown axis is not implemented. flags: %16X", flags);
        printout(INFO,"Geant4Converter","++ Replicate: Axis: %ld Count: %ld offset: %f width: %f",
                 axis, count, offset, width);
        auto* g4pv = new G4PVReplica(name,      // its name
                                     g4vol,     // its logical volume
                                     g4mot,     // its mother (logical) volume
                                     axis,      // its replication axis
                                     count,     // Number of replicas
                                     width,     // Distance between 2 replicas
                                     offset);   // Placement offset in axis direction
        pvPlaced = { g4pv, nullptr };
Markus Frank
committed
        pvPlaced =
          G4ReflectionFactory::Instance()->Replicate(name,      // its name
                                                     g4vol,     // its logical volume
                                                     g4mot,     // its mother (logical) volume
                                                     axis,      // its replication axis
                                                     count,     // Number of replicas
                                                     width,     // Distance between 2 replicas
                                                     offset);   // Placement offset in axis direction
        /// Update replica list to avoid additional conversions...
        auto* g4pv = pvPlaced.second ? pvPlaced.second : pvPlaced.first;
Markus Frank
committed
        for( auto& handle : pv_data->params->placements )
          info.g4Placements[handle.ptr()] = g4pv;
      }
      else if ( pv_data && pv_data->params )   {
Markus Frank
committed
        auto*  g4par = new Geant4PlacementParameterisation(pv);
        auto*  g4pv  = new G4PVParameterised(name,              // its name
                                             g4vol,             // its logical volume
                                             g4mot,             // its mother (logical) volume
                                             g4par->axis(),     // its replication axis
                                             g4par->count(),    // Number of replicas
                                             g4par);            // G4 parametrization
        pvPlaced = { g4pv, nullptr };
        /// Update replica list to avoid additional conversions...
        for( auto& handle : pv_data->params->placements )
          info.g4Placements[handle.ptr()] = g4pv;
      }
      else    {
Markus Frank
committed
        pvPlaced =
          G4ReflectionFactory::Instance()->Place(transform,     // no rotation
                                                 name,          // its name
                                                 g4vol,         // its logical volume
                                                 g4mot,         // its mother (logical) volume
                                                 false,         // no boolean operations
                                                 copy,          // its copy number
                                                 checkOverlaps);
      }
      printout(debugReflections||debugPlacements ? ALWAYS : lvl, "Geant4Converter",
Markus Frank
committed
               "++ Place %svolume %-12s in mother %-12s "
               "Tr:x=%8.1f y=%8.1f z=%8.1f   Scale:x=%4.2f y=%4.2f z=%4.2f",
               node_is_reflected ? "REFLECTED " : "", _v.name(),
               mot_vol ? mot_vol->GetName() : "<unknown>",
               transform.dx(), transform.dy(), transform.dz(),
               scale.xx(), scale.yy(), scale.zz());
      // First 2 cases can be combined.
      // Leave them separated for debugging G4ReflectionFactory for now...
      if ( node_is_reflected  && !pvPlaced.second )
        return info.g4Placements[node] = pvPlaced.first;
      else if ( !node_is_reflected && !pvPlaced.second )
        return info.g4Placements[node] = pvPlaced.first;
      // Now deal with valid pvPlaced.second ...
      if ( node_is_reflected )
        return info.g4Placements[node] = pvPlaced.first;
      else if ( !node_is_reflected )
        return info.g4Placements[node] = pvPlaced.first;
      g4 = pvPlaced.second ? pvPlaced.second : pvPlaced.first;
    info.g4Placements[node] = g4;
    printout(ERROR, "Geant4Converter", "++ DEAD code. Should not end up here!");
/// Convert the geometry type region into the corresponding Geant4 object(s).
Markus Frank
committed
void* Geant4Converter::handleRegion(Region region, const std::set<const TGeoVolume*>& /* volumes */) const {
  G4Region* g4 = data().g4Regions[region];
Markus Frank
committed
    PrintLevel lvl = debugRegions ? ALWAYS : outputLevel;
    Region r = region;
    g4 = new G4Region(region.name());
    // create region info with storeSecondaries flag
Andre Sailer
committed
    if( not r.wasThresholdSet() and r.storeSecondaries() ) {
Markus Frank
committed
      throw std::runtime_error("G4Region: StoreSecondaries is True, but no explicit threshold set:");
Andre Sailer
committed
    }
    printout(lvl, "Geant4Converter", "++ Setting up region: %s", r.name());
    G4UserRegionInformation* info = new G4UserRegionInformation();
    info->region = r;
    info->threshold = r.threshold()*CLHEP::MeV/units::MeV;
    info->storeSecondaries = r.storeSecondaries();
    g4->SetUserInformation(info);
    printout(lvl, "Geant4Converter", "++ Converted region settings of:%s.", r.name());
Markus Frank
committed
    std::vector < std::string > &limits = r.limits();
    G4ProductionCuts* cuts = 0;
    // set production cut
    if( not r.useDefaultCut() ) {
      cuts = new G4ProductionCuts();
      cuts->SetProductionCut(r.cut()*CLHEP::mm/units::mm);
      printout(lvl, "Geant4Converter", "++ %s: Using default cut: %f [mm]",
Markus Frank
committed
               r.name(), r.cut()*CLHEP::mm/units::mm);
    for( const auto& nam : limits )  {
      if ( ls.isValid() ) {
Markus Frank
committed
        const LimitSet::Set& cts = ls.cuts();
        for (const auto& c : cts )   {
          int pid = 0;
          if ( c.particles == "*" ) pid = -1;
          else if ( c.particles == "e-"     ) pid = idxG4ElectronCut;
          else if ( c.particles == "e+"     ) pid = idxG4PositronCut;
          else if ( c.particles == "e[+-]"  ) pid = -idxG4PositronCut-idxG4ElectronCut;
          else if ( c.particles == "e[-+]"  ) pid = -idxG4PositronCut-idxG4ElectronCut;
          else if ( c.particles == "gamma"  ) pid = idxG4GammaCut;
          else if ( c.particles == "proton" ) pid = idxG4ProtonCut;
Markus Frank
committed
          else throw std::runtime_error("G4Region: Invalid production cut particle-type:" + c.particles);
Markus Frank
committed
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
          if ( !cuts ) cuts = new G4ProductionCuts();
          if ( pid == -(idxG4PositronCut+idxG4ElectronCut) )  {
            cuts->SetProductionCut(c.value*CLHEP::mm/units::mm, idxG4PositronCut);
            cuts->SetProductionCut(c.value*CLHEP::mm/units::mm, idxG4ElectronCut);
          }
          else  {
            cuts->SetProductionCut(c.value*CLHEP::mm/units::mm, pid);
          }
          printout(lvl, "Geant4Converter", "++ %s: Set cut  [%s/%d] = %f [mm]",
                   r.name(), c.particles.c_str(), pid, c.value*CLHEP::mm/units::mm);
        }
        bool found = false;
        const auto& lm = data().g4Limits;
        for (const auto& j : lm )   {
          if (nam == j.first->GetName()) {
            g4->SetUserLimits(j.second);
            printout(lvl, "Geant4Converter", "++ %s: Set limits %s to region type %s",
                     r.name(), nam.c_str(), j.second->GetType().c_str());
            found = true;
            break;
          }
        }
        if ( found )   {
          continue;
        }
      except("Geant4Converter", "++ G4Region: Failed to resolve limitset: " + nam);
    /// Assign cuts to region if they were created
    if ( cuts ) g4->SetProductionCuts(cuts);
    data().g4Regions[region] = g4;
  }
  return g4;
}
/// Convert the geometry type LimitSet into the corresponding Geant4 object(s).
Markus Frank
committed
void* Geant4Converter::handleLimitSet(LimitSet limitset, const std::set<const TGeoVolume*>& /* volumes */) const {
  G4UserLimits* g4 = data().g4Limits[limitset];
    PrintLevel lvl = debugLimits || debugRegions ? ALWAYS : outputLevel;
    struct LimitPrint  {
      const LimitSet& ls;
      LimitPrint(const LimitSet& lset) : ls(lset) {}
      const LimitPrint& operator()(const std::string& pref, const Geant4UserLimits::Handler& h)  const {
        if ( !h.particleLimits.empty() )  {
          printout(ALWAYS,"Geant4Converter",
                   "+++ LimitSet: Explicit Limit %s.%s applied for particles:",ls.name(), pref.c_str());
          for(const auto& p : h.particleLimits)
            printout(ALWAYS,"Geant4Converter","+++ LimitSet:    Particle type: %-18s PDG: %-6d : %f",
                     p.first->GetParticleName().c_str(), p.first->GetPDGEncoding(), p.second);
        }
        else if ( h.defaultValue > std::numeric_limits<double>::epsilon() )  {
          printout(ALWAYS,"Geant4Converter",
                   "+++ LimitSet: Implicit Limit %s.%s for wildcard particles: %f",
Markus Frank
committed
                   ls.name(), pref.c_str(), float(h.defaultValue));
        }
        return *this;
      }
    };
    Geant4UserLimits* limits = new Geant4UserLimits(limitset);
    g4 = limits;
    printout(lvl, "Geant4Converter",
             "++ Successfully converted LimitSet: %s [%ld cuts, %ld limits]",
Markus Frank
committed
             limitset.name(), limitset.cuts().size(), limitset.limits().size());
    if ( debugRegions || debugLimits )    {
      LimitPrint print(limitset);
      print("maxTime",    limits->maxTime)
        ("minEKine",      limits->minEKine)
        ("minRange",      limits->minRange)
        ("maxStepLength", limits->maxStepLength)
        ("maxTrackLength",limits->maxTrackLength);
    }
    data().g4Limits[limitset] = g4;
  }
  return g4;
}
/// Convert the geometry visualisation attributes to the corresponding Geant4 object(s).
Markus Frank
committed
void* Geant4Converter::handleVis(const std::string& /* name */, VisAttr attr) const {
  Geant4GeometryInfo& info = data();
  G4VisAttributes*    g4   = info.g4Vis[attr];
  if ( !g4 ) {
    int   style = attr.lineStyle();
    attr.rgb(red, green, blue);
    g4 = new G4VisAttributes(attr.visible(), G4Colour(red, green, blue, attr.alpha()));
    //g4->SetLineWidth(attr->GetLineWidth());
    g4->SetDaughtersInvisible(!attr.showDaughters());
    if ( style == VisAttr::SOLID ) {
      g4->SetLineStyle(G4VisAttributes::unbroken);
      g4->SetForceWireframe(false);
      g4->SetForceSolid(true);
    }
    else if ( style == VisAttr::WIREFRAME || style == VisAttr::DASHED ) {
      g4->SetLineStyle(G4VisAttributes::dashed);
      g4->SetForceSolid(false);
      g4->SetForceWireframe(true);
    }
  }
  return g4;
}
/// Handle the geant 4 specific properties
void Geant4Converter::handleProperties(Detector::Properties& prp) const {
Markus Frank
committed
  std::map < std::string, std::string > processors;
  static int s_idd = 9999999;
  for( const auto& [nam, vals] : prp ) {
    if ( nam.substr(0, 6) == "geant4" ) {
      auto id_it = vals.find("id");
Markus Frank
committed
      std::string id = (id_it == vals.end()) ? _toString(++s_idd,"%d") : (*id_it).second;
      processors.emplace(id, nam);
  for( const auto& p : processors ) {
    const Detector::PropertyValues& vals = prp[p.second];
    auto iter = vals.find("type");
    if ( iter != vals.end() )  {
      std::string type = iter->second;
      std::string tag  = type + "_Geant4_action";
      Detector* det = const_cast<Detector*>(&m_detDesc);
      long      res = PluginService::Create<long>(tag, det, hdlr, &vals);
      if ( 0 == res ) {
        throw std::runtime_error("Failed to locate plugin to interprete files of type"
                                 " \"" + tag + "\" - no factory:" + type);
      }
      res = *(long*)res;
      if ( res != 1 ) {
        throw std::runtime_error("Failed to invoke the plugin " + tag + " of type " + type);
      }
      printout(outputLevel, "Geant4Converter", "+++++ Executed Successfully Geant4 setup module *%s*.", type.c_str());
      continue;
    printout(outputLevel, "Geant4Converter", "+++++ FAILED to execute Geant4 setup module *%s*.", p.second.c_str());    
/// Convert the geometry type material into the corresponding Geant4 object(s).
void* Geant4Converter::handleMaterialProperties(TObject* mtx) const    {
  Geant4GeometryInfo& info   = data();
  TGDMLMatrix*        matrix = (TGDMLMatrix*)mtx;
  const char*         cptr   = ::strstr(matrix->GetName(), GEANT4_TAG_IGNORE);
  Geant4GeometryInfo::PropertyVector* g4 = info.g4OpticalProperties[matrix];
  if ( nullptr != cptr )   {  // Check if the property should not be passed to Geant4
    printout(INFO,"Geant4MaterialProperties","++ Ignore property %s [%s].",
Markus Frank
committed
             matrix->GetName(), matrix->GetTitle());	     
    return nullptr;
  }
  cptr = ::strstr(matrix->GetTitle(), GEANT4_TAG_IGNORE);
  if ( nullptr != cptr )   {  // Check if the property should not be passed to Geant4
    printout(INFO,"Geant4MaterialProperties","++ Ignore property %s [%s].",
Markus Frank
committed
             matrix->GetName(), matrix->GetTitle());
    return nullptr;
  }
  
  if ( !g4 )  {
Markus Frank
committed
    PrintLevel lvl = debugMaterials ? ALWAYS : outputLevel;
    g4 = new Geant4GeometryInfo::PropertyVector();
    std::size_t rows = matrix->GetRows();
    g4->name    = matrix->GetName();
    g4->title   = matrix->GetTitle();
    g4->bins.reserve(rows);
    g4->values.reserve(rows);
    for( std::size_t i=0; i<rows; ++i )   {
      g4->bins.emplace_back(matrix->Get(i,0)  /*   *CLHEP::eV/units::eV   */);
      g4->values.emplace_back(matrix->Get(i,1));
    printout(lvl, "Geant4Converter",
Markus Frank
committed
             "++ Successfully converted material property:%s : %s [%ld rows]",
             matrix->GetName(), matrix->GetTitle(), rows);
    info.g4OpticalProperties[matrix] = g4;
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
  }
  return g4;
}
static G4OpticalSurfaceFinish geant4_surface_finish(TGeoOpticalSurface::ESurfaceFinish f)   {
#define TO_G4_FINISH(x)  case TGeoOpticalSurface::kF##x : return x;
  switch(f)   {
    TO_G4_FINISH(polished);              // smooth perfectly polished surface
    TO_G4_FINISH(polishedfrontpainted);  // smooth top-layer (front) paint
    TO_G4_FINISH(polishedbackpainted);   // same is 'polished' but with a back-paint
 
    TO_G4_FINISH(ground);                // rough surface
    TO_G4_FINISH(groundfrontpainted);    // rough top-layer (front) paint
    TO_G4_FINISH(groundbackpainted);     // same as 'ground' but with a back-paint
    TO_G4_FINISH(polishedlumirrorair);   // mechanically polished surface, with lumirror
    TO_G4_FINISH(polishedlumirrorglue);  // mechanically polished surface, with lumirror & meltmount
    TO_G4_FINISH(polishedair);           // mechanically polished surface
    TO_G4_FINISH(polishedteflonair);     // mechanically polished surface, with teflon
    TO_G4_FINISH(polishedtioair);        // mechanically polished surface, with tio paint
    TO_G4_FINISH(polishedtyvekair);      // mechanically polished surface, with tyvek
    TO_G4_FINISH(polishedvm2000air);     // mechanically polished surface, with esr film
    TO_G4_FINISH(polishedvm2000glue);    // mechanically polished surface, with esr film & meltmount
    TO_G4_FINISH(etchedlumirrorair);     // chemically etched surface, with lumirror
    TO_G4_FINISH(etchedlumirrorglue);    // chemically etched surface, with lumirror & meltmount
    TO_G4_FINISH(etchedair);             // chemically etched surface
    TO_G4_FINISH(etchedteflonair);       // chemically etched surface, with teflon
    TO_G4_FINISH(etchedtioair);          // chemically etched surface, with tio paint
    TO_G4_FINISH(etchedtyvekair);        // chemically etched surface, with tyvek
    TO_G4_FINISH(etchedvm2000air);       // chemically etched surface, with esr film
    TO_G4_FINISH(etchedvm2000glue);      // chemically etched surface, with esr film & meltmount
    TO_G4_FINISH(groundlumirrorair);     // rough-cut surface, with lumirror
    TO_G4_FINISH(groundlumirrorglue);    // rough-cut surface, with lumirror & meltmount
    TO_G4_FINISH(groundair);             // rough-cut surface
    TO_G4_FINISH(groundteflonair);       // rough-cut surface, with teflon
    TO_G4_FINISH(groundtioair);          // rough-cut surface, with tio paint
    TO_G4_FINISH(groundtyvekair);        // rough-cut surface, with tyvek
    TO_G4_FINISH(groundvm2000air);       // rough-cut surface, with esr film
    TO_G4_FINISH(groundvm2000glue);      // rough-cut surface, with esr film & meltmount
    // for DAVIS model
    TO_G4_FINISH(Rough_LUT);             // rough surface
    TO_G4_FINISH(RoughTeflon_LUT);       // rough surface wrapped in Teflon tape
    TO_G4_FINISH(RoughESR_LUT);          // rough surface wrapped with ESR
    TO_G4_FINISH(RoughESRGrease_LUT);    // rough surface wrapped with ESR and coupled with opical grease
    TO_G4_FINISH(Polished_LUT);          // polished surface
    TO_G4_FINISH(PolishedTeflon_LUT);    // polished surface wrapped in Teflon tape
    TO_G4_FINISH(PolishedESR_LUT);       // polished surface wrapped with ESR
    TO_G4_FINISH(PolishedESRGrease_LUT); // polished surface wrapped with ESR and coupled with opical grease
    TO_G4_FINISH(Detector_LUT);          // polished surface with optical grease
  default:
    printout(ERROR,"Geant4Surfaces","++ Unknown finish style: %d [%s]. Assume polished!",
             int(f), TGeoOpticalSurface::FinishToString(f));
    return polished;
  }
#undef TO_G4_FINISH
}
static G4SurfaceType geant4_surface_type(TGeoOpticalSurface::ESurfaceType t)   {
#define TO_G4_TYPE(x)  case TGeoOpticalSurface::kT##x : return x;
  switch(t)   {
    TO_G4_TYPE(dielectric_metal);      // dielectric-metal interface
    TO_G4_TYPE(dielectric_dielectric); // dielectric-dielectric interface
    TO_G4_TYPE(dielectric_LUT);        // dielectric-Look-Up-Table interface
    TO_G4_TYPE(dielectric_LUTDAVIS);   // dielectric-Look-Up-Table DAVIS interface
    TO_G4_TYPE(dielectric_dichroic);   // dichroic filter interface
    TO_G4_TYPE(firsov);                // for Firsov Process
    TO_G4_TYPE(x_ray);                  // for x-ray mirror process
  default:
    printout(ERROR,"Geant4Surfaces","++ Unknown surface type: %d [%s]. Assume dielectric_metal!",
             int(t), TGeoOpticalSurface::TypeToString(t));
    return dielectric_metal;
  }
#undef TO_G4_TYPE
}
static G4OpticalSurfaceModel geant4_surface_model(TGeoOpticalSurface::ESurfaceModel surfMod)   {
#define TO_G4_MODEL(x)  case TGeoOpticalSurface::kM##x : return x;
    TO_G4_MODEL(glisur);   // original GEANT3 model
    TO_G4_MODEL(unified);  // UNIFIED model
    TO_G4_MODEL(LUT);      // Look-Up-Table model
    TO_G4_MODEL(DAVIS);    // DAVIS model
    TO_G4_MODEL(dichroic); // dichroic filter
  default:
    printout(ERROR,"Geant4Surfaces","++ Unknown surface model: %d [%s]. Assume glisur!",
             int(surfMod), TGeoOpticalSurface::ModelToString(surfMod));
    return glisur;
  }
#undef TO_G4_MODEL
}
/// Convert the optical surface to Geant4
void* Geant4Converter::handleOpticalSurface(TObject* surface) const    {
  TGeoOpticalSurface* optSurf    = (TGeoOpticalSurface*)surface;
  Geant4GeometryInfo& info = data();
  G4OpticalSurface*   g4   = info.g4OpticalSurfaces[optSurf];
    G4SurfaceType          type   = geant4_surface_type(optSurf->GetType());
    G4OpticalSurfaceModel  model  = geant4_surface_model(optSurf->GetModel());
    G4OpticalSurfaceFinish finish = geant4_surface_finish(optSurf->GetFinish());
Markus Frank
committed
    std::string name = make_NCName(optSurf->GetName());
Markus Frank
committed
    PrintLevel lvl = debugSurfaces ? ALWAYS : DEBUG;
    g4 = new G4OpticalSurface(name, model, finish, type, optSurf->GetValue());
    g4->SetPolish(optSurf->GetPolish());
Markus Frank
committed
    printout(lvl, "Geant4Converter",
             "++ Created OpticalSurface: %-18s type:%s model:%s finish:%s SigmaAlphs: %.3e Polish: %.3e",
             optSurf->GetName(),
             TGeoOpticalSurface::TypeToString(optSurf->GetType()),
             TGeoOpticalSurface::ModelToString(optSurf->GetModel()),
             TGeoOpticalSurface::FinishToString(optSurf->GetFinish()),
             optSurf->GetSigmaAlpha(), optSurf->GetPolish());
Markus Frank
committed
    ///
    /// Convert non-scalar properties from GDML tables
    G4MaterialPropertiesTable* tab = nullptr;
Markus Frank
committed
    TListIter itp(&optSurf->GetProperties());
    for(TObject* obj = itp.Next(); obj; obj = itp.Next())  {
Markus Frank
committed
      std::string exc_str;
      TNamed*      named  = (TNamed*)obj;
      TGDMLMatrix* matrix = info.manager->GetGDMLMatrix(named->GetTitle());
      const char*  cptr   = ::strstr(matrix->GetName(), GEANT4_TAG_IGNORE);
      if ( nullptr != cptr )  // Check if the property should not be passed to Geant4
Markus Frank
committed
        continue;
        tab = new G4MaterialPropertiesTable();
        g4->SetMaterialPropertiesTable(tab);
      }
      Geant4GeometryInfo::PropertyVector* v =
        (Geant4GeometryInfo::PropertyVector*)handleMaterialProperties(matrix);
      if ( !v )  {  // Error!
        except("Geant4OpticalSurface","++ Failed to convert opt.surface %s. Property table %s is not defined!",
               optSurf->GetName(), named->GetTitle());
      }
Markus Frank
committed
      int idx = -1;
      try   {
        idx = tab->GetPropertyIndex(named->GetName());
      }
      catch(const std::exception& e)   {
        exc_str = e.what();
      }
      catch(...)   {
      }
Markus Frank
committed
        printout(ERROR, "Geant4Converter",
                 "++ UNKNOWN Geant4 Property: %-20s %s [IGNORED]",
                 exc_str.c_str(), named->GetName());
      // We need to convert the property from TGeo units to Geant4 units
      auto conv = g4PropertyConversion(idx);
Markus Frank
committed
      std::vector<double> bins(v->bins), vals(v->values);
      for(std::size_t i=0, count=v->bins.size(); i<count; ++i)
        bins[i] *= conv.first, vals[i] *= conv.second;
      G4MaterialPropertyVector* vec = new G4MaterialPropertyVector(&bins[0], &vals[0], bins.size());
      tab->AddProperty(named->GetName(), vec);
      
Markus Frank
committed
      printout(lvl, "Geant4Converter",
Markus Frank
committed
               "++       Property: %-20s [%ld x %ld] -->  %s",
               named->GetName(), matrix->GetRows(), matrix->GetCols(), named->GetTitle());
      for(std::size_t i=0, count=v->bins.size(); i<count; ++i)
Markus Frank
committed
        printout(lvl, named->GetName(),
                 "  Geant4: %8.3g [MeV]  TGeo: %8.3g [GeV] Conversion: %8.3g",
                 bins[i], v->bins[i], conv.first);
Markus Frank
committed
    ///
    /// Convert scalar properties
#if ROOT_VERSION_CODE >= ROOT_VERSION(6,31,1)
Markus Frank
committed
    TListIter itc(&optSurf->GetConstProperties());
    for(TObject* obj = itc.Next(); obj; obj = itc.Next())  {
Markus Frank
committed
      std::string  exc_str;
Markus Frank
committed
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
      TNamed* named  = (TNamed*)obj;
      const char* cptr = ::strstr(named->GetName(), GEANT4_TAG_IGNORE);
      if ( nullptr != cptr )   {
        printout(INFO, name, "++ Ignore CONST property %s [%s].",
                 named->GetName(), named->GetTitle());
        continue;
      }
      cptr = ::strstr(named->GetTitle(), GEANT4_TAG_IGNORE);
      if ( nullptr != cptr )   {
        printout(INFO, name,"++ Ignore CONST property %s [%s].",
                 named->GetName(), named->GetTitle());
        continue;
      }
      Bool_t   err = kFALSE;
      Double_t value = info.manager->GetProperty(named->GetTitle(),&err);
      if ( err != kFALSE )   {
        except(name,
               "++ FAILED to create G4 material %s [Cannot convert const property: %s]",
               optSurf->GetName(), named->GetName());
      }
      if ( nullptr == tab )  {
        tab = new G4MaterialPropertiesTable();
        g4->SetMaterialPropertiesTable(tab);
      }
      int idx = -1;
      try   {
        idx = tab->GetConstPropertyIndex(named->GetName());
      }
      catch(const std::exception& e)   {
        exc_str = e.what();
      }
      catch(...)   {
      }
      if ( idx < 0 )   {
        printout(ERROR, name,
                 "++ UNKNOWN Geant4 CONST Property: %-20s %s [IGNORED]",
                 exc_str.c_str(), named->GetName());
        continue;
      }
      // We need to convert the property from TGeo units to Geant4 units
      double conv = g4ConstPropertyConversion(idx);
      printout(lvl, name, "++      CONST Property: %-20s %g * %g --> %g ",
               named->GetName(), value, conv, value * conv);
      tab->AddConstProperty(named->GetName(), value * conv);
    }
Markus Frank
committed
#endif  // ROOT_VERSION >= 6.31.1
  }
  return g4;
}
/// Convert the skin surface to Geant4
void* Geant4Converter::handleSkinSurface(TObject* surface) const   {
  TGeoSkinSurface*    surf = (TGeoSkinSurface*)surface;
  Geant4GeometryInfo& info = data();
  G4LogicalSkinSurface* g4 = info.g4SkinSurfaces[surf];
    G4OpticalSurface* optSurf  = info.g4OpticalSurfaces[OpticalSurface(surf->GetSurface())];
    G4LogicalVolume*  v = info.g4Volumes[surf->GetVolume()];
Markus Frank
committed
    std::string name = make_NCName(surf->GetName());
    g4 = new G4LogicalSkinSurface(name, v, optSurf);
Markus Frank
committed
    printout(debugSurfaces ? ALWAYS : DEBUG, "Geant4Converter",
             "++ Created SkinSurface: %-18s  optical:%s",
             surf->GetName(), surf->GetSurface()->GetName());
    info.g4SkinSurfaces[surf] = g4;
  }
  return g4;
}
/// Convert the border surface to Geant4
void* Geant4Converter::handleBorderSurface(TObject* surface) const   {
  TGeoBorderSurface*    surf = (TGeoBorderSurface*)surface;
  Geant4GeometryInfo&   info = data();
  G4LogicalBorderSurface* g4 = info.g4BorderSurfaces[surf];
    G4OpticalSurface*  optSurf = info.g4OpticalSurfaces[OpticalSurface(surf->GetSurface())];
    G4VPhysicalVolume* n1 = info.g4Placements[surf->GetNode1()];
    G4VPhysicalVolume* n2 = info.g4Placements[surf->GetNode2()];
Markus Frank
committed
    std::string name = make_NCName(surf->GetName());
    g4 = new G4LogicalBorderSurface(name, n1, n2, optSurf);
Markus Frank
committed
    printout(debugSurfaces ? ALWAYS : DEBUG, "Geant4Converter",
             "++ Created BorderSurface: %-18s  optical:%s",
             surf->GetName(), surf->GetSurface()->GetName());
    info.g4BorderSurfaces[surf] = g4;
  }
  return g4;
}
/// Convert the geometry type SensitiveDetector into the corresponding Geant4 object(s).
Markus Frank
committed
void Geant4Converter::printSensitive(SensitiveDetector sens_det, const std::set<const TGeoVolume*>& /* volumes */) const {
  Geant4GeometryInfo&          info = data();
  std::set<const TGeoVolume*>& volset = info.sensitives[sens_det];
  SensitiveDetector            sd = sens_det;
  std::stringstream str;
Markus Frank
committed
  printout(INFO, "Geant4Converter", "++ SensitiveDetector: %-18s %-20s Hits:%-16s", sd.name(), ("[" + sd.type() + "]").c_str(),
Markus Frank
committed
           sd.hitsCollection().c_str());
Markus Frank
committed
  str << "                    | " << "Cutoff:" << std::setw(6) << std::left
      << sd.energyCutoff() << std::setw(5) << std::right << volset.size()
      << " volumes ";
  if (sd.region().isValid())
Markus Frank
committed
    str << " Region:" << std::setw(12) << std::left << sd.region().name();
Markus Frank
committed
    str << " Limits:" << std::setw(12) << std::left << sd.limits().name();
Markus Frank
committed
  str << ".";
  printout(INFO, "Geant4Converter", str.str().c_str());
Markus Frank
committed
    std::map<Volume, G4LogicalVolume*>::iterator v = info.g4Volumes.find(i);
    if ( v != info.g4Volumes.end() )   {
      G4LogicalVolume* vol = (*v).second;
      str.str("");
      str << "                                   | " << "Volume:" << std::setw(24) << std::left << vol->GetName() << " "
          << vol->GetNoDaughters() << " daughters.";
      printout(INFO, "Geant4Converter", str.str().c_str());
    }
Markus Frank
committed
std::string printSolid(G4VSolid* sol) {
  std::stringstream str;
  if (typeid(*sol) == typeid(G4Box)) {
    const G4Box* b = (G4Box*) sol;
Markus Frank
committed
    str << "++ Box: x=" << b->GetXHalfLength() << " y=" << b->GetYHalfLength() << " z=" << b->GetZHalfLength();
  else if (typeid(*sol) == typeid(G4Tubs)) {
    const G4Tubs* t = (const G4Tubs*) sol;
    str << " Tubs: Ri=" << t->GetInnerRadius() << " Ra=" << t->GetOuterRadius() << " z/2=" << t->GetZHalfLength() << " Phi="
        << t->GetStartPhiAngle() << "..." << t->GetDeltaPhiAngle();
Markus Frank
committed
  return str.str();
Markus Frank
committed
void* Geant4Converter::printPlacement(const std::string& name, const TGeoNode* node) const {
  Geant4GeometryInfo& info = data();
  G4VPhysicalVolume*  g4   = info.g4Placements[node];
  G4LogicalVolume*    vol  = info.g4Volumes[node->GetVolume()];
  G4LogicalVolume*    mot  = info.g4Volumes[node->GetMotherVolume()];
  G4VSolid*           sol  = vol->GetSolid();
  G4ThreeVector       tr   = g4->GetObjectTranslation();
  G4VSensitiveDetector* sd = vol->GetSensitiveDetector();
Markus Frank
committed
  std::stringstream str;
  str << "G4Cnv::placement: + " << name << " No:" << node->GetNumber() << " Vol:" << vol->GetName() << " Solid:"
      << sol->GetName();
Markus Frank
committed
  printout(outputLevel, "G4Placement", str.str().c_str());
Markus Frank
committed
  str.str("");
  str << "                  |" << " Loc: x=" << tr.x() << " y=" << tr.y() << " z=" << tr.z();
Markus Frank
committed
  printout(outputLevel, "G4Placement", str.str().c_str());
  printout(outputLevel, "G4Placement", printSolid(sol).c_str());
Markus Frank
committed
  str.str("");
  str << "                  |" << " Ndau:" << vol->GetNoDaughters()
      << " physvols." << " Mat:" << vol->GetMaterial()->GetName()
      << " Mother:" << (char*) (mot ? mot->GetName().c_str() : "---");
Markus Frank
committed
  printout(outputLevel, "G4Placement", str.str().c_str());
Markus Frank
committed
  str.str("");
Markus Frank
committed
  printout(outputLevel, "G4Placement", str.str().c_str());
  return g4;
}
/// Create geometry conversion
Markus Frank
committed
Geant4Converter& Geant4Converter::create(DetElement top) {
  typedef std::map<const TGeoNode*, std::vector<TGeoNode*> > _DAU;
  Geant4GeometryInfo& geo = this->init();
  geo.manager = &wrld.detectorDescription().manager();
  this->collect(top, geo);
  this->checkOverlaps = false;
  // We do not have to handle defines etc.
  // All positions and the like are not really named.
  // Hence, start creating the G4 objects for materials, solids and log volumes.
  handleArray(this, geo.manager->GetListOfGDMLMatrices(), &Geant4Converter::handleMaterialProperties);
  handleArray(this, geo.manager->GetListOfOpticalSurfaces(), &Geant4Converter::handleOpticalSurface);
  
  handle(this,     geo.volumes, &Geant4Converter::collectVolume);
  handle(this,     geo.solids,  &Geant4Converter::handleSolid);
Markus Frank
committed
  printout(outputLevel, "Geant4Converter", "++ Handled %ld solids.", geo.solids.size());
  handleRefs(this, geo.vis,     &Geant4Converter::handleVis);
Markus Frank
committed
  printout(outputLevel, "Geant4Converter", "++ Handled %ld visualization attributes.", geo.vis.size());
  handleMap(this,  geo.limits,  &Geant4Converter::handleLimitSet);
Markus Frank
committed
  printout(outputLevel, "Geant4Converter", "++ Handled %ld limit sets.", geo.limits.size());
  handleMap(this,  geo.regions, &Geant4Converter::handleRegion);
Markus Frank
committed
  printout(outputLevel, "Geant4Converter", "++ Handled %ld regions.", geo.regions.size());
  handle(this,     geo.volumes, &Geant4Converter::handleVolume);
Markus Frank
committed
  printout(outputLevel, "Geant4Converter", "++ Handled %ld volumes.", geo.volumes.size());
  handleRMap(this, *m_data,     &Geant4Converter::handleAssembly);
  // Now place all this stuff appropriately
  //handleRMap(this, *m_data,     &Geant4Converter::handlePlacement);
  std::map<int, std::vector<const TGeoNode*> >::const_reverse_iterator i = m_data->rbegin();
  for ( ; i != m_data->rend(); ++i )  {
    for ( const TGeoNode* node : i->second )  {
      this->handlePlacement(node->GetName(), node);
    }
  }
  /// Handle concrete surfaces
  handleArray(this, geo.manager->GetListOfSkinSurfaces(),   &Geant4Converter::handleSkinSurface);
  handleArray(this, geo.manager->GetListOfBorderSurfaces(), &Geant4Converter::handleBorderSurface);
  //==================== Fields
Markus Frank
committed
  if ( printSensitives )  {
    handleMap(this, geo.sensitives, &Geant4Converter::printSensitive);
  }
  if ( printPlacements )  {
    handleRMap(this, *m_data, &Geant4Converter::printPlacement);
  }
  geo.setWorld(top.placement().ptr());
  geo.valid = true;
  TTimeStamp stop;
  printout(INFO, "Geant4Converter",
           "+++  Successfully converted geometry to Geant4. [%7.3f seconds]",
           stop.AsDouble()-start.AsDouble() );
Markus Frank
committed
  return *this;