Newer
Older
// $Id:$
//====================================================================
// 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 "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);
}
269
270
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
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];
Volume _v = Ref_t(v);
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);
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 ( !g4 ) {
TGeoMatrix* trafo = node->GetMatrix();
const Double_t* trans = trafo->GetTranslation();
int copy = node->GetNumber();
G4LogicalVolume* vol = info.g4Volumes[node->GetVolume()];
G4LogicalVolume* mot = info.g4Volumes[node->GetMotherVolume()];
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 {
cout << "Attempt to DOUBLE-place physical volume:" << name << " No:" << node->GetNumber() << endl;
}
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
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
/// 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;
/// Handle the geant 4 specific properties
void Geant4Converter::handleProperties(LCDD::Properties& prp) const {
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
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;
}
}
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
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
643
644
645
646
647
648
649
650
651
652
653
654
/// 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);
m_data->clear();
collect(top,geo);
// 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;
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;