Newer
Older
//====================================================================
// AIDA Detector description implementation for LCD
//--------------------------------------------------------------------
//
// Author : M.Frank
//
//====================================================================
#include "DD4hep/LCDD.h"
#include "DDG4/Geant4Field.h"
#include "DDG4/Geant4Converter.h"
// ROOT includes
#include "TROOT.h"
#include "TColor.h"
#include "TGeoShape.h"
#include "TGeoCone.h"
#include "TGeoParaboloid.h"
#include "TGeoPcon.h"
#include "TGeoPgon.h"
#include "TGeoSphere.h"
#include "TGeoTorus.h"
#include "TGeoTube.h"
#include "TGeoTrd1.h"
#include "TGeoTrd2.h"
#include "TGeoArb8.h"
#include "TGeoMatrix.h"
#include "TGeoBoolNode.h"
#include "TGeoCompositeShape.h"
#include "TGeoNode.h"
#include "TClass.h"
#include "TMath.h"
#include "G4VisAttributes.hh"
#include "G4ProductionCuts.hh"
#include "G4VUserRegionInformation.hh"
#include "G4Polycone.hh"
#include "G4Polyhedra.hh"
#include "G4UnionSolid.hh"
#include "G4SubtractionSolid.hh"
#include "G4IntersectionSolid.hh"
#include "G4Region.hh"
#include "G4UserLimits.hh"
#include "G4VSensitiveDetector.hh"
#include "G4LogicalVolume.hh"
#include "G4Material.hh"
#include "G4Element.hh"
#include "G4Isotope.hh"
#include "G4Transform3D.hh"
#include "G4ThreeVector.hh"
#include "G4PVPlacement.hh"
#include "G4ElectroMagneticField.hh"
#include "G4FieldManager.hh"
using namespace DD4hep::Simulation;
using namespace DD4hep::Geometry;
using namespace DD4hep;
using namespace std;
namespace {
static string indent = "";
struct MyTransform3D : public G4Transform3D {
MyTransform3D(double XX, double XY, double XZ, double DX,
double YX, double YY, double YZ, double DY,
double ZX, double ZY, double ZZ, double DZ)
: G4Transform3D(XX,XY,XZ,DX,YX,YY,YZ,DY,ZX,ZY,ZZ,DZ) {}
void handleName(const TGeoNode* n) {
TGeoVolume* v = n->GetVolume();
TGeoMedium* m = v->GetMedium();
TGeoShape* s = v->GetShape();
string nam;
cout << "Node:'" << n->GetName()
<< "' Vol:'" << v->GetName()
<< "' Shape:'" << s->GetName()
<< "' Medium:'" << m->GetName()
<< "'" << endl;
}
class G4UserRegionInformation : public G4VUserRegionInformation {
public:
Region region;
double threshold;
bool storeSecondaries;
G4UserRegionInformation() : threshold(0.0), storeSecondaries(false) {}
virtual ~G4UserRegionInformation() {}
virtual void Print() const {
if ( region.isValid() ) cout << "Region:" << region.name() << endl;
}
};
/// Initializing Constructor
Geant4Converter::Geant4Converter( LCDD& lcdd ) : m_lcdd(lcdd) {
m_checkOverlaps = true;
}
#if 0
/// Dump element in GDML format to output stream
void* Geant4Converter::printElement(const string& name, const TGeoElement* element) const {
G4Element* g4e = G4Element::GetElement(name,false);
}
#endif
/// Dump element in GDML format to output stream
void* Geant4Converter::handleElement(const string& name, const TGeoElement* element) const {
G4Element* g4e = data().g4Elements[element];
if ( !g4e ) {
g4e = G4Element::GetElement(name,false);
if ( !g4e ) {
if ( element->GetNisotopes() > 1 ) {
g4e = new G4Element(name,element->GetTitle(),element->GetNisotopes());
for(int i=0, n=element->GetNisotopes(); i<n; ++i) {
TGeoIsotope* iso = element->GetIsotope(i);
G4Isotope* g4iso = G4Isotope::GetIsotope(iso->GetName(),false);
if ( !g4iso ) {
g4iso = new G4Isotope(iso->GetName(),iso->GetZ(),iso->GetN(),iso->GetA());
}
g4e->AddIsotope(g4iso,element->GetRelativeAbundance(i));
}
}
else {
g4e = new G4Element(element->GetTitle(),name,element->Z(),element->A()*(g/mole));
}
data().g4Elements[element] = g4e;
}
return g4e;
}
/// Dump material in GDML format to output stream
void* Geant4Converter::handleMaterial(const string& name, const TGeoMedium* medium) const {
G4Material* mat = data().g4Materials[medium];
if ( !mat ) {
mat = G4Material::GetMaterial(name,false);
if ( !mat ) {
TGeoMaterial* m = medium->GetMaterial();
G4State state = kStateUndefined;
double density = m->GetDensity()*(gram/cm3);
switch(m->GetState()) {
case TGeoMaterial::kMatStateSolid:
state = kStateSolid;
break;
case TGeoMaterial::kMatStateLiquid:
state = kStateLiquid;
break;
case TGeoMaterial::kMatStateGas:
state = kStateGas;
break;
default:
case TGeoMaterial::kMatStateUndefined:
state = kStateUndefined;
break;
}
double A_total = 0.0;
int nElements = mix->GetNelements();
mat = new G4Material(name,density,nElements,
state,
m->GetTemperature(),
m->GetPressure());
for(int i=0; i<nElements; ++i)
A_total += (mix->GetAmixt())[i];
for(int i=0; i<nElements; ++i) {
TGeoElement* e = mix->GetElement(i);
G4Element* g4e = (G4Element*)handleElement(e->GetName(),e);
if ( !g4e ) {
cout << "ERROR: Missing component " << e->GetName()
<< " for material " << mix->GetName() << endl;
}
mat->AddElement(g4e,(mix->GetAmixt())[i]/A_total);
mat = new G4Material(name,m->GetZ(),m->GetA(),density,state,
m->GetTemperature(),m->GetPressure());
}
data().g4Materials[medium] = mat;
}
return mat;
}
void* Geant4Converter::handleSolid(const string& name, const TGeoShape* shape) const {
G4VSolid* solid = data().g4Solids[shape];
if ( !solid && shape ) {
if ( shape->IsA() == TGeoBBox::Class() ) {
const TGeoBBox* s = (const TGeoBBox*)shape;
G4Box* box = new G4Box(name,s->GetDX()*CM_2_MM,s->GetDY()*CM_2_MM,s->GetDZ()*CM_2_MM);
solid = box;
//::printf("ROOT Box: %s x=%f y=%f z=%f\n",name.c_str(),s->GetDX(),s->GetDY(),s->GetDZ());
//::printf(" +-->G4 Box: %s x=%f y=%f z=%f\n",name.c_str(),box->GetXHalfLength(),box->GetYHalfLength(),box->GetZHalfLength());
}
else if ( shape->IsA() == TGeoTube::Class() ) {
const TGeoTube* s = (const TGeoTube*)shape;
solid = new G4Tubs(name,s->GetRmin()*CM_2_MM,s->GetRmax()*CM_2_MM,s->GetDz()*CM_2_MM,0,2.*M_PI);
//::printf("Convert Tube: %s r=%f r=%f z=%f\n",name.c_str(),s->GetRmin()*CM_2_MM,s->GetRmax()*CM_2_MM,s->GetDz()*CM_2_MM,0,2.*M_PI);
}
else if ( shape->IsA() == TGeoTubeSeg::Class() ) {
const TGeoTubeSeg* s = (const TGeoTubeSeg*)shape;
solid = new G4Tubs(name,s->GetRmin()*CM_2_MM,s->GetRmax()*CM_2_MM,s->GetDz()*CM_2_MM,s->GetPhi1()*DEGREE_2_RAD,s->GetPhi2()*DEGREE_2_RAD);
}
else if ( shape->IsA() == TGeoTrd1::Class() ) {
const TGeoTrd1* s = (const TGeoTrd1*)shape;
solid = new G4Trd(name,s->GetDx1()*CM_2_MM,s->GetDx2()*CM_2_MM,s->GetDy()*CM_2_MM,s->GetDy()*CM_2_MM,s->GetDz()*CM_2_MM);
}
else if ( shape->IsA() == TGeoTrd2::Class() ) {
const TGeoTrd2* s = (const TGeoTrd2*)shape;
solid = new G4Trd(name,s->GetDx1()*CM_2_MM,s->GetDx2()*CM_2_MM,s->GetDy1()*CM_2_MM,s->GetDy2()*CM_2_MM,s->GetDz()*CM_2_MM);
}
else if ( shape->IsA() == TGeoPgon::Class() ) {
const TGeoPgon* s = (const TGeoPgon*)shape;
double phi_start = s->GetPhi1()*DEGREE_2_RAD;
double phi_total = (s->GetDphi()+s->GetPhi1())*DEGREE_2_RAD;
vector<double> rmin, rmax, z;
for( size_t i=0; i<s->GetNz(); ++i ) {
rmin.push_back(s->GetRmin(i)*CM_2_MM);
rmax.push_back(s->GetRmax(i)*CM_2_MM);
z.push_back(s->GetZ(i)*CM_2_MM);
}
solid = new G4Polyhedra(name,phi_start,phi_total,s->GetNedges()-1,s->GetNz(),&z[0],&rmin[0],&rmax[0]);
}
else if ( shape->IsA() == TGeoPcon::Class() ) {
const TGeoPcon* s = (const TGeoPcon*)shape;
double phi_start = s->GetPhi1()*DEGREE_2_RAD;
double phi_total = (s->GetDphi()+s->GetPhi1())*DEGREE_2_RAD;
vector<double> rmin, rmax, z;
for( size_t i=0; i<s->GetNz(); ++i ) {
rmin.push_back(s->GetRmin(i)*CM_2_MM);
rmax.push_back(s->GetRmax(i)*CM_2_MM);
z.push_back(s->GetZ(i)*CM_2_MM);
}
solid = new G4Polycone(name,phi_start,phi_total,s->GetNz(),&z[0],&rmin[0],&rmax[0]);
else if ( shape->IsA() == TGeoConeSeg::Class() ) {
const TGeoConeSeg* s = (const TGeoConeSeg*)shape;
solid = new G4Cons(name,
s->GetRmin1()*CM_2_MM,
s->GetRmax1()*CM_2_MM,
s->GetRmin2()*CM_2_MM,
s->GetRmax2()*CM_2_MM,
s->GetDz()*CM_2_MM,
s->GetPhi1()*DEGREE_2_RAD,
s->GetPhi2()*DEGREE_2_RAD);
}
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
else if ( shape->IsA() == TGeoParaboloid::Class() ) {
const TGeoParaboloid* s = (const TGeoParaboloid*)shape;
solid = new G4Paraboloid(name,s->GetDz()*CM_2_MM,s->GetRlo()*CM_2_MM,s->GetRhi()*CM_2_MM);
}
else if ( shape->IsA() == TGeoSphere::Class() ) {
const TGeoSphere* s = (const TGeoSphere*)shape;
solid = new G4Sphere(name,s->GetRmin()*CM_2_MM,s->GetRmax()*CM_2_MM,
s->GetPhi1()*DEGREE_2_RAD,s->GetPhi2()*DEGREE_2_RAD,
s->GetTheta1()*DEGREE_2_RAD,s->GetTheta2()*DEGREE_2_RAD);
}
else if ( shape->IsA() == TGeoTorus::Class() ) {
const TGeoTorus* s = (const TGeoTorus*)shape;
solid = new G4Torus(name,s->GetRmin()*CM_2_MM,s->GetRmax()*CM_2_MM, s->GetR()*CM_2_MM,
s->GetPhi1()*DEGREE_2_RAD,s->GetDphi()*DEGREE_2_RAD);
}
else if ( shape->IsA() == TGeoCompositeShape::Class() ) {
const TGeoCompositeShape* s = (const TGeoCompositeShape*)shape;
const TGeoBoolNode* boolean = s->GetBoolNode();
TGeoBoolNode::EGeoBoolType oper = boolean->GetBooleanOperator();
TGeoMatrix* m = boolean->GetRightMatrix();
G4VSolid* left = (G4VSolid*)handleSolid(name+"_left", boolean->GetLeftShape());
G4VSolid* right = (G4VSolid*)handleSolid(name+"_right",boolean->GetRightShape());
const Double_t *t = m->GetTranslation();
const Double_t *r = m->GetRotationMatrix();
if ( !left ) {
throw runtime_error("G4Converter: No left Geant4 Solid present for composite shape:"+name);
}
if ( !right ) {
throw runtime_error("G4Converter: No right Geant4 Solid present for composite shape:"+name);
}
if ( m->IsRotation() ) {
MyTransform3D transform(r[0],r[1],r[2],t[0]*CM_2_MM,
r[3],r[4],r[5],t[1]*CM_2_MM,
r[6],r[7],r[8],t[2]*CM_2_MM);
if ( oper == TGeoBoolNode::kGeoSubtraction )
solid = new G4SubtractionSolid(name,left,right,transform);
else if ( oper == TGeoBoolNode::kGeoUnion )
solid = new G4UnionSolid(name,left,right,transform);
else if ( oper == TGeoBoolNode::kGeoIntersection )
solid = new G4IntersectionSolid(name,left,right,transform);
}
else {
G4ThreeVector transform(t[0]*CM_2_MM,t[1]*CM_2_MM,t[2]*CM_2_MM);
if ( oper == TGeoBoolNode::kGeoSubtraction )
solid = new G4SubtractionSolid(name,left,right,0,transform);
else if ( oper == TGeoBoolNode::kGeoUnion )
solid = new G4UnionSolid(name,left,right,0,transform);
else if ( oper == TGeoBoolNode::kGeoIntersection )
solid = new G4IntersectionSolid(name,left,right,0,transform);
}
}
if ( !solid ) {
string err = "Failed to handle unknown solid shape:" +
name + " of type " + string(shape->IsA()->GetName());
throw runtime_error(err);
}
data().g4Solids[shape] = solid;
}
return solid;
}
/// Dump logical volume in GDML format to output stream
void* Geant4Converter::handleVolume(const string& name, const TGeoVolume* volume) const {
G4GeometryInfo& info = data();
G4LogicalVolume* vol = info.g4Volumes[volume];
VisAttr vis = _v.visAttributes();
string n = v->GetName();
TGeoMedium* m = v->GetMedium();
TGeoShape* s = v->GetShape();
G4VSolid* solid = (G4VSolid*)handleSolid(s->GetName(),s);
G4Material* medium = (G4Material*)handleMaterial(m->GetName(),m);
if ( !solid ) {
throw runtime_error("G4Converter: No Geant4 Solid present for volume:"+n);
}
if ( !medium ) {
throw runtime_error("G4Converter: No Geant4 material present for volume:"+n);
}
SensitiveDetector det = _v.sensitiveDetector();
Geant4SensitiveDetector* sd = 0;
if ( det.isValid() ) {
sd = info.g4SensDets[det.ptr()];
if ( !sd ) {
throw runtime_error("G4Cnv::volume["+name+"]: + FATAL Failed to "
"access Geant4 sensitive detector.");
}
sd->Activate(true);
}
LimitSet lim = _v.limitSet();
G4UserLimits* l = 0;
if ( lim.isValid() ) {
l = info.g4Limits[lim.ptr()];
if ( !l ) {
throw runtime_error("G4Cnv::volume["+name+"]: + FATAL Failed to "
"access Geant4 user limits.");
}
}
vol = new G4LogicalVolume(solid,medium,n,0,sd,l);
if ( vis.isValid() ) {
G4VisAttributes* attr = (G4VisAttributes*)handleVis(vis.name(),vis.ptr());
if ( attr ) vol->SetVisAttributes(attr);
}
info.g4Volumes[v] = vol;
if ( sd ) {
cout << "G4Cnv::volume: + " << name << " <> " << vol->GetName()
<< " Solid:" << solid->GetName() << " Mat:" << medium->GetName()
<< " SD:" << sd->GetName()
<< endl;
//cout << "Converted logical volume [" << n << "]:" << v.ptr() << " ---> G4 " << vol << endl;
/// Dump logical volume in GDML format to output stream
void* Geant4Converter::collectVolume(const string& name, const TGeoVolume* volume) const {
G4GeometryInfo& info = data();
const TGeoVolume* v = volume;
Volume _v = Ref_t(v);
Region reg = _v.region();
LimitSet lim = _v.limitSet();
SensitiveDetector det = _v.sensitiveDetector();
if ( lim.isValid() ) info.limits[lim.ptr()].insert(v);
if ( reg.isValid() ) info.regions[reg.ptr()].insert(v);
if ( det.isValid() ) info.sensitives[det.ptr()].insert(v);
return (void*)v;
}
/// Dump volume placement in GDML format to output stream
void* Geant4Converter::handlePlacement(const string& name, const TGeoNode* node) const {
G4GeometryInfo& info = data();
G4PVPlacement* g4 = info.g4Placements[node];
// if the CellID0 volID is defined for the volume we
// use it to overwrite the copy number
// this is then used in the sensitive detector to fill the CellID0
// of the SimTrackerHits
if ( dynamic_cast<const PlacedVolume::Object*>(node) ) {
PlacedVolume p = Ref_t(node);
const PlacedVolume::VolIDs& ids = p.volIDs();
// copy = ids[ "CellID0" ] ;
PlacedVolume::VolIDs::const_iterator it = ids.find("CellID0") ;
if( it != ids.end() )
copy = it->second ;
}
//--------------------------------------------------------
G4LogicalVolume* vol = info.g4Volumes[node->GetVolume()];
G4LogicalVolume* mot = info.g4Volumes[node->GetMotherVolume()];
const Double_t* trans = trafo->GetTranslation();
const Value<TGeoNodeMatrix,PlacedVolume::Object>* obj =
dynamic_cast<const Value<TGeoNodeMatrix,PlacedVolume::Object>* >(node);
cout << "FATAL: Unknown G4 volume:" << (void*)obj << " " << obj->GetName() << endl;
}
else if ( trafo->IsRotation() ) {
const Double_t* rot = trafo->GetRotationMatrix();
MyTransform3D transform(rot[0],rot[1],rot[2],trans[0]*CM_2_MM,
rot[3],rot[4],rot[5],trans[1]*CM_2_MM,
rot[6],rot[7],rot[8],trans[2]*CM_2_MM);
g4 = new G4PVPlacement(transform, // no rotation
G4ThreeVector pos(trans[0]*CM_2_MM,trans[1]*CM_2_MM,trans[2]*CM_2_MM);
g4 = new G4PVPlacement(0, // no rotation
pos, // translation position
else if ( node == s_topPtr ) {
G4ThreeVector pos(0,0,0);
g4 = new G4PVPlacement(0, // no rotation
pos, // translation position
vol, // its logical volume
name, // its name
mot, // its mother (logical) volume
false, // no boolean operations
copy, // its copy number
m_checkOverlaps);
data().g4Placements[node] = g4;
cout << "Attempt to convert TOP Detector node failed." << endl;
}
}
else {
cout << "Attempt to DOUBLE-place physical volume:" << name << " No:" << node->GetNumber() << endl;
}
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
/// Convert the geometry type region into the corresponding Geant4 object(s).
void* Geant4Converter::handleRegion(const TNamed* region, const set<const TGeoVolume*>& volumes) const {
G4Region* g4 = data().g4Regions[region];
if ( !g4 ) {
Region r = Ref_t(region);
g4 = new G4Region(region->GetName());
// set production cut
G4ProductionCuts* cuts = new G4ProductionCuts();
cuts->SetProductionCut(r.cut());
g4->SetProductionCuts(cuts);
// create region info with storeSecondaries flag
G4UserRegionInformation* info = new G4UserRegionInformation();
info->region = r;
info->threshold = r.threshold();
info->storeSecondaries = r.storeSecondaries();
g4->SetUserInformation(info);
vector<string>& limits = r.limits();
for(vector<string>::const_iterator i=limits.begin(); i!=limits.end(); ++i) {
const string& nam = *i;
LimitSet ls = m_lcdd.limitSet(nam);
if ( ls.isValid() ) {
bool found = false;
const LimitMap& lm = data().g4Limits;
for(LimitMap::const_iterator j=lm.begin(); j!=lm.end();++j) {
if ( nam == (*j).first->GetName() ) {
g4->SetUserLimits((*j).second);
found = true;
break;
}
}
if ( found ) continue;
}
throw runtime_error("G4Region: Failed to resolve user limitset:"+*i);
}
data().g4Regions[region] = g4;
}
return g4;
}
/// Convert the geometry type LimitSet into the corresponding Geant4 object(s).
void* Geant4Converter::handleLimitSet(const TNamed* limitset, const set<const TGeoVolume*>& volumes) const {
G4UserLimits* g4 = data().g4Limits[limitset];
if ( !g4 ) {
LimitSet ls = Ref_t(limitset);
g4 = new G4UserLimits(limitset->GetName());
const LimitSet::Object& obj = ls.limits();
for(LimitSet::Object::const_iterator i=obj.begin(); i!=obj.end(); ++i) {
const Limit& l = *i;
if ( l.name == "step_length_max" )
g4->SetMaxAllowedStep(l.value);
else if ( l.name == "track_length_max" )
g4->SetMaxAllowedStep(l.value);
else if ( l.name == "time_max" )
g4->SetUserMaxTime(l.value);
else if ( l.name == "ekin_min" )
g4->SetUserMinEkine(l.value);
else if ( l.name == "range_min" )
g4->SetUserMinRange(l.value);
else
throw runtime_error("Unknown Geant4 user limit: "+l.toString());
}
data().g4Limits[limitset] = g4;
}
return g4;
}
/// Convert the geometry type SensitiveDetector into the corresponding Geant4 object(s).
void* Geant4Converter::handleSensitive(const TNamed* sens_det, const set<const TGeoVolume*>& volumes) const {
G4GeometryInfo& info = data();
Geant4SensitiveDetector* g4 = info.g4SensDets[sens_det];
if ( !g4 ) {
SensitiveDetector sd = Ref_t(sens_det);
g4 = ROOT::Reflex::PluginService::Create<Geant4SensitiveDetector*>(type,name,&m_lcdd);
if ( !g4 ) {
throw runtime_error("Geant4Converter<SensitiveDetector>: FATAL Failed to "
"create Geant4 sensitive detector "+name+" of type "+type+".");
}
G4SDManager::GetSDMpointer()->AddNewDetector(g4);
info.g4SensDets[sens_det] = g4;
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
/// Convert the geometry visualisation attributes to the corresponding Geant4 object(s).
void* Geant4Converter::handleVis(const string& name, const TNamed* vis) const {
G4GeometryInfo& info = data();
G4VisAttributes* g4 = info.g4Vis[vis];
if ( !g4 ) {
float r=0, g=0, b=0;
VisAttr attr = Ref_t(vis);
int style = attr.lineStyle();
attr.rgb(r,g,b);
g4 = new G4VisAttributes(attr.visible(),G4Colour(r,g,b,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);
}
info.g4Vis[vis] = g4;
}
return g4;
}
/// Handle the geant 4 specific properties
void Geant4Converter::handleProperties(LCDD::Properties& prp) const {
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
static int s_idd = 9999999;
string id;
for(LCDD::Properties::const_iterator i=prp.begin(); i!=prp.end(); ++i) {
const string& nam = (*i).first;
const LCDD::PropertyValues& vals = (*i).second;
if ( nam.substr(0,6) == "geant4" ) {
LCDD::PropertyValues::const_iterator id_it = vals.find("id");
if ( id_it != vals.end() ) {
id= (*id_it).second;
}
else {
char txt[32];
::sprintf(txt,"%d",++s_idd);
id = txt;
}
processors.insert(make_pair(id,nam));
}
}
for(map<string,string>::const_iterator i=processors.begin(); i!=processors.end(); ++i) {
const Geant4Converter* ptr = this;
string nam = (*i).second;
const LCDD::PropertyValues& vals = prp[nam];
string type = vals.find("type")->second;
string tag = type + "_Geant4_action";
long result = ROOT::Reflex::PluginService::Create<long>(tag,&m_lcdd,ptr,&vals);
if ( 0 == result ) {
throw runtime_error("Failed to locate plugin to interprete files of type"
" \""+tag+"\" - no factory:"+type);
}
result = *(long*)result;
if ( result != 1 ) {
throw runtime_error("Failed to invoke the plugin "+tag+" of type "+type);
}
cout << "+++++ Executed Successfully Geant4 setup module *" << type << "* ." << endl;
}
}
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
/// Convert the geometry type SensitiveDetector into the corresponding Geant4 object(s).
void* Geant4Converter::printSensitive(const TNamed* sens_det, const set<const TGeoVolume*>& volumes) const {
G4GeometryInfo& info = data();
Geant4SensitiveDetector* g4 = info.g4SensDets[sens_det];
ConstVolumeSet& volset = info.sensitives[sens_det];
SensitiveDetector sd = Ref_t(sens_det);
bool verbose = sd.verbose();
if ( verbose ) {
cout << "Geant4Converter<SensitiveDetector> +" << setw(18) << left << sd.name()
<< setw(20) << left << " ["+sd.type()+"]"
<< " Hits:" << setw(16) << left << sd.hitsCollection() << endl;
cout << " | "
<< "Cutoff:" << setw(6) << left << sd.energyCutoff()
<< setw(5) << right << volset.size() << " volumes ";
if ( sd.region().isValid() ) cout << " Region:" << setw(12) << left << sd.region().name();
if ( sd.limits().isValid() ) cout << " Limits:" << setw(12) << left << sd.limits().name();
cout << "." << endl;
}
for(ConstVolumeSet::iterator i=volset.begin(); i!=volset.end();++i) {
map<const TGeoVolume*, G4LogicalVolume*>::iterator v = info.g4Volumes.find(*i);
G4LogicalVolume* vol = (*v).second;
if ( verbose ) {
cout << " | "
<< "Volume:" << setw(24) << left << vol->GetName()
<< " " << vol->GetNoDaughters() << " daughters."
<< endl;
}
}
return g4;
}
void printSolid(G4VSolid* sol) {
if ( typeid(*sol) == typeid(G4Box) ) {
const G4Box* b = (G4Box*)sol;
cout << " Box: x=" << b->GetXHalfLength() << " y=" << b->GetYHalfLength() << " z=" << b->GetZHalfLength();
}
if ( typeid(*sol) == typeid(G4Tubs) ) {
const G4Tubs* t = (const G4Tubs*)sol;
cout << " Tubs: Ri=" << t->GetInnerRadius() << " Ra=" << t->GetOuterRadius()
<< " z/2=" << t->GetZHalfLength() << " Phi=" << t->GetStartPhiAngle()
<< "..." << t->GetDeltaPhiAngle ();
}
}
/// Print G4 placement
void* Geant4Converter::printPlacement(const string& name, const TGeoNode* node) const {
G4GeometryInfo& info = data();
G4PVPlacement* 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();
if ( !sd ) return g4;
cout << "G4Cnv::placement: + " << name << " No:" << node->GetNumber()
<< " Vol:" << vol->GetName() << " Solid:" << sol->GetName()
<< endl;
cout << " |"
<< " Loc: x=" << tr.x() << " y=" << tr.y() << " z=" << tr.z();
printSolid(sol);
cout << endl;
cout << " |"
<< " Ndau:" << vol->GetNoDaughters() << " physvols."
<< " Mat:" << vol->GetMaterial()->GetName()
<< " Mother:" << (char*)(mot ? mot->GetName().c_str() : "---")
<< endl;
cout << " |"
<< " SD:" << (char*)(sd ? sd->GetName().c_str() : "---")
<< endl;
return g4;
}
template <typename O, typename C, typename F> void handle(const O* o, const C& c, F pmf) {
for(typename C::const_iterator i=c.begin(); i != c.end(); ++i) {
(o->*pmf)((*i)->GetName(),*i);
template <typename O, typename C, typename F> void handleMap(const O* o, const C& c, F pmf) {
for(typename C::const_iterator i=c.begin(); i != c.end(); ++i)
(o->*pmf)((*i).first, (*i).second);
}
template <typename O, typename C, typename F> void handleRMap(const O* o, const C& c, F pmf) {
for(typename C::const_reverse_iterator i=c.rbegin(); i != c.rend(); ++i)
handle(o, (*i).second, pmf);
}
/// Create geometry conversion
void Geant4Converter::create(DetElement top) {
G4GeometryInfo& geo = *(m_dataPtr=new G4GeometryInfo);
// Ensure that all required materials are present in the Geant4 material table
const LCDD::HandleMap& mat = lcdd.materials();
for(LCDD::HandleMap::const_iterator i=mat.begin(); i!=mat.end(); ++i)
geo.materials.insert((TGeoMedium*)(*i).second.ptr());
// 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.
handle(this, geo.materials, &Geant4Converter::handleMaterial);
cout << "++ Handled " << geo.materials.size() << " materials." << endl;
handle(this, geo.volumes, &Geant4Converter::collectVolume);
handle(this, geo.solids, &Geant4Converter::handleSolid);
cout << "++ Handled " << geo.solids.size() << " solids." << endl;
handle(this, geo.vis, &Geant4Converter::handleVis);
cout << "++ Handled " << geo.solids.size() << " visualization attributes." << endl;
handleMap(this, geo.sensitives, &Geant4Converter::handleSensitive);
cout << "++ Handled " << geo.sensitives.size() << " sensitive detectors." << endl;
handleMap(this, geo.limits, &Geant4Converter::handleLimitSet);
cout << "++ Handled " << geo.limits.size() << " limit sets." << endl;
handleMap(this, geo.regions, &Geant4Converter::handleRegion);
cout << "++ Handled " << geo.regions.size() << " regions." << endl;
handle(this, geo.volumes, &Geant4Converter::handleVolume);
cout << "++ Handled " << geo.volumes.size() << " volumes." << endl;
// Now place all this stuff appropriately
handleRMap(this, *m_data, &Geant4Converter::handlePlacement);
//==================== Fields
handleProperties(m_lcdd.properties());
//cout << *(G4Material::GetMaterialTable()) << endl;
//handleMap(this, geo.sensitives, &Geant4Converter::printSensitive);
//handleRMap(this, *m_data, &Geant4Converter::printPlacement);
}
/// Singleton instance
Geant4Converter& Geant4Converter::instance() {
static Geant4Converter* inst = 0;
if ( 0 == inst ) {
Geometry::LCDD& lcdd = LCDD::getInstance();
inst = new Geant4Converter(lcdd);
}
return *inst;