Newer
Older
//====================================================================
// AIDA Detector description implementation for LCD
//--------------------------------------------------------------------
//
// Author : M.Frank
//
//====================================================================
#include "DD4hep/LCDD.h"
#include "DD4hep/Plugins.h"
Markus Frank
committed
#include "DD4hep/Printout.h"
#include "DDG4/Geant4Field.h"
#include "DDG4/Geant4Converter.h"
#include "DDG4/Factories.h"
// ROOT includes
#include "TROOT.h"
#include "TColor.h"
Markus Frank
committed
#include "TGeoNode.h"
#include "TGeoShape.h"
#include "TGeoCone.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"
Markus Frank
committed
#include "TGeoParaboloid.h"
Markus Frank
committed
#include "TGeoShapeAssembly.h"
#include "TClass.h"
#include "TMath.h"
#include "G4VSensitiveDetector.hh"
#include "G4VisAttributes.hh"
#include "G4ProductionCuts.hh"
#include "G4VUserRegionInformation.hh"
Markus Frank
committed
#include "G4Assembly.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"
#include "G4ReflectionFactory.hh"
Markus Frank
committed
#include <iostream>
#include <iomanip>
#include <sstream>
using namespace DD4hep::Simulation;
using namespace DD4hep::Geometry;
using namespace DD4hep;
using namespace std;
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#define private public
#include "G4AssemblyVolume.hh"
#undef private
struct Geant4AssemblyVolume : public G4AssemblyVolume {
Geant4AssemblyVolume() {}
size_t placeVolume(G4LogicalVolume* pPlacedVolume,
G4Transform3D& transformation) {
size_t id = fTriplets.size();
this->AddPlacedVolume(pPlacedVolume,transformation);
return id;
}
void imprint( std::vector<G4VPhysicalVolume*>& nodes,
G4LogicalVolume* pMotherLV,
G4Transform3D& transformation,
G4int copyNumBase,
G4bool surfCheck );
};
void Geant4AssemblyVolume::imprint( std::vector<G4VPhysicalVolume*>& nodes,
G4LogicalVolume* pMotherLV,
G4Transform3D& transformation,
G4int copyNumBase,
G4bool surfCheck )
{
G4AssemblyVolume* pAssembly = this;
unsigned int numberOfDaughters;
if( copyNumBase == 0 ) {
numberOfDaughters = pMotherLV->GetNoDaughters();
}
else {
numberOfDaughters = copyNumBase;
}
// We start from the first available index
numberOfDaughters++;
ImprintsCountPlus();
std::vector<G4AssemblyTriplet> triplets = pAssembly->fTriplets;
for( unsigned int i = 0; i < triplets.size(); i++ ) {
G4Transform3D Ta( *(triplets[i].GetRotation()),
triplets[i].GetTranslation() );
if ( triplets[i].IsReflection() ) { Ta = Ta * G4ReflectZ3D(); }
G4Transform3D Tfinal = transformation * Ta;
if ( triplets[i].GetVolume() )
{
// Generate the unique name for the next PV instance
// The name has format:
//
// av_WWW_impr_XXX_YYY_ZZZ
// where the fields mean:
// WWW - assembly volume instance number
// XXX - assembly volume imprint number
// YYY - the name of a log. volume we want to make a placement of
// ZZZ - the log. volume index inside the assembly volume
//
std::stringstream pvName;
pvName << "av_"
<< GetAssemblyID()
<< "_impr_"
<< GetImprintsCount()
<< "_"
<< triplets[i].GetVolume()->GetName().c_str()
<< "_pv_"
<< i
<< std::ends;
// Generate a new physical volume instance inside a mother
// (as we allow 3D transformation use G4ReflectionFactory to
// take into account eventual reflection)
//
G4PhysicalVolumesPair pvPlaced
= G4ReflectionFactory::Instance()->Place( Tfinal,
pvName.str().c_str(),
triplets[i].GetVolume(),
pMotherLV,
false,
numberOfDaughters + i,
surfCheck );
// Register the physical volume created by us so we can delete it later
//
fPVStore.push_back( pvPlaced.first );
nodes.push_back(pvPlaced.first);
if ( pvPlaced.second ) { // Supported by G4, but not by TGeo!
fPVStore.push_back( pvPlaced.second );
G4Exception("G4AssemblyVolume::MakeImprint(..)",
"GeomVol0003", FatalException,
"Fancy construct popping new mother from the stack!");
}
}
else if ( triplets[i].GetAssembly() ) {
// Place volumes in this assembly with composed transformation
G4Exception("G4AssemblyVolume::MakeImprint(..)",
"GeomVol0003", FatalException,
"Assemblies within assembliesare not supported.");
}
else {
G4Exception("G4AssemblyVolume::MakeImprint(..)",
"GeomVol0003", FatalException,
"Triplet has no volume and no assembly");
}
}
}
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;
Markus Frank
committed
printout(DEBUG,"G4","TGeoNode:'%s' Vol:'%s' Shape:'%s' Medium:'%s'",
n->GetName(),v->GetName(),s->GetName(),m->GetName());
class G4UserRegionInformation : public G4VUserRegionInformation {
public:
Region region;
double threshold;
bool storeSecondaries;
G4UserRegionInformation() : threshold(0.0), storeSecondaries(false) {}
virtual ~G4UserRegionInformation() {}
virtual void Print() const {
Markus Frank
committed
if ( region.isValid() )
printout(DEBUG,"Region","Name:%s",region.name());
Markus Frank
committed
Geant4Converter::Geant4Converter( LCDD& lcdd )
: Geant4Mapping(lcdd), m_checkOverlaps(true)
Markus Frank
committed
{
this->Geant4Mapping::init();
Markus Frank
committed
/// Standard destructor
Geant4Converter::~Geant4Converter() {
Markus Frank
committed
/// 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));
Markus Frank
committed
stringstream str;
str << (*g4e);
printout(DEBUG,"Geant4Converter","++ Created G4 %s",str.str().c_str());
}
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);
if ( density < 1e-25 ) density = 1e-25;
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 ) {
Markus Frank
committed
printout(ERROR,"Material","Missing component %s for material %s.",
e->GetName(), mix->GetName());
}
mat->AddElement(g4e,(mix->GetAmixt())[i]/A_total);
mat = new G4Material(name,m->GetZ(),m->GetA(),density,state,
m->GetTemperature(),m->GetPressure());
Markus Frank
committed
stringstream str;
str << (*mat);
printout(DEBUG,"Geant4Converter","++ Created G4 %s",str.str().c_str());
}
data().g4Materials[medium] = mat;
}
return mat;
}
void* Geant4Converter::handleSolid(const string& name, const TGeoShape* shape) const {
Markus Frank
committed
G4VSolid* solid = 0;
if ( shape ) {
if ( 0 != (solid=data().g4Solids[shape]) ) {
return solid;
}
else if ( shape->IsA() == TGeoShapeAssembly::Class() ) {
solid = (G4VSolid*)new G4Assembly();
}
else if ( shape->IsA() == TGeoBBox::Class() ) {
const TGeoBBox* s = (const TGeoBBox*)shape;
Markus Frank
committed
solid = new G4Box(name,s->GetDX()*CM_2_MM,s->GetDY()*CM_2_MM,s->GetDZ()*CM_2_MM);
}
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);
}
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;
Markus Frank
committed
for( Int_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(),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;
Markus Frank
committed
for( Int_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);
}
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
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 {
Geant4GeometryInfo& info = data();
Markus Frank
committed
const TGeoVolume* v = 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 = 0;
bool assembly = s->IsA() == TGeoShapeAssembly::Class();
Markus Frank
committed
SensitiveDetector det = _v.sensitiveDetector();
G4VSensitiveDetector* 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();
Markus Frank
committed
G4UserLimits* user_limits = 0;
Markus Frank
committed
user_limits = info.g4Limits[lim.ptr()];
if ( !user_limits ) {
throw runtime_error("G4Cnv::volume["+name+"]: + FATAL Failed to "
"access Geant4 user limits.");
}
}
VisAttr vis = _v.visAttributes();
G4VisAttributes* vis_attr = 0;
if ( vis.isValid() ) {
vis_attr = (G4VisAttributes*)handleVis(vis.name(),vis.ptr());
Markus Frank
committed
}
Region reg = _v.region();
G4Region* region = 0;
if ( reg.isValid() ) {
region = info.g4Regions[reg.ptr()];
if ( !region ) {
throw runtime_error("G4Cnv::volume["+name+"]: + FATAL Failed to "
"access Geant4 region.");
}
printout(DEBUG,"Geant4Converter","++ Convert Volume %-32s: %p %s/%s assembly:%s sensitive:%s",
n.c_str(),v,s->IsA()->GetName(),v->IsA()->GetName(),(assembly ? "YES" : "NO"),
(det.isValid() ? "YES" : "NO"));
Markus Frank
committed
if ( assembly ) {
vol = (G4LogicalVolume*)new G4AssemblyVolume();
info.g4Volumes[v] = vol;
return vol;
}
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);
}
if ( user_limits ) {
printout(DEBUG,"++ Volume + Apply LIMITS settings:%-24s to volume %s.",lim.name(),_v.name());
}
vol = new G4LogicalVolume(solid,medium,n,0,sd,user_limits);
if ( region ) {
printout(DEBUG,"Geant4Converter","++ Volume + Apply REGION settings: %s to volume %s.",reg.name(),_v.name());
Markus Frank
committed
vol->SetRegion(region);
region->AddRootLogicalVolume(vol);
Markus Frank
committed
if ( vis_attr ) {
vol->SetVisAttributes(vis_attr);
}
if ( sd ) {
printout(DEBUG,"Geant4Converter","++ Volume: + %s <> %s Solid:%s Mat:%s SD:%s",
Markus Frank
committed
name.c_str(),vol->GetName().c_str(),solid->GetName().c_str(),
medium->GetName().c_str(),sd->GetName().c_str());
}
info.g4Volumes[v] = vol;
printout(DEBUG,"Geant4Converter", "++ Volume + %s converted: %p ---> G4: %p",n.c_str(),v,vol);
/// Dump logical volume in GDML format to output stream
Markus Frank
committed
void* Geant4Converter::collectVolume(const string& /* name */, const TGeoVolume* volume) const {
Geant4GeometryInfo& 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 {
static Double_t identity_rot[] = { 1., 0., 0., 0., 1., 0., 0., 0., 1. };
Geant4GeometryInfo& info = data();
PlacementMap::const_iterator g4it = info.g4Placements.find(node);
G4VPhysicalVolume* g4 = (g4it == info.g4Placements.end()) ? 0 : (*g4it).second;
Markus Frank
committed
TGeoVolume* mot_vol = node->GetMotherVolume();
TGeoVolume* vol = node->GetVolume();
TGeoMatrix* trafo = node->GetMatrix();
if ( !trafo ) {
printout(FATAL,"Geant4Converter","++ Attempt to handle placement without transformation:%p %s of type %s vol:%p",
node,node->GetName(),node->IsA()->GetName(),vol);
}
else if ( 0 == vol ) {
printout(FATAL,"Geant4Converter","++ Unknown G4 volume:%p %s of type %s vol:%s ptr:%p",
node,node->GetName(),node->IsA()->GetName(),vol->IsA()->GetName(),vol);
}
else {
int copy = node->GetNumber();
G4LogicalVolume* g4vol = info.g4Volumes[vol];
G4LogicalVolume* g4mot = info.g4Volumes[mot_vol];
Geant4AssemblyVolume* ass_mot = (Geant4AssemblyVolume*)g4mot;
Geant4AssemblyVolume* ass_dau = (Geant4AssemblyVolume*)g4vol;
const Double_t* trans = trafo->GetTranslation();
const Double_t* rot = trafo->IsRotation() ? trafo->GetRotationMatrix() : identity_rot;
bool daughter_is_assembly = vol->IsA() == TGeoVolumeAssembly::Class();
bool mother_is_assembly = mot_vol ? mot_vol->IsA() == TGeoVolumeAssembly::Class() : false;
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);
CLHEP::HepRotation rotmat=transform.getRotation();
Markus Frank
committed
if ( mother_is_assembly ) { // Mother is an assembly:
printout(DEBUG,"Geant4Converter","++ Assembly: AddPlacedVolume: %16p dau:%s "
"Tr:x=%8.3f y=%8.3f z=%8.3f Rot:phi=%7.3f theta=%7.3f psi=%7.3f\n",
ass_mot,g4vol ? g4vol->GetName().c_str() : "---",
transform.dx(),transform.dy(),transform.dz(),
rotmat.getPhi(),rotmat.getTheta(),rotmat.getPsi());
size_t id = ass_mot->placeVolume(g4vol,transform);
info.g4AssemblyChildren[ass_mot].push_back(make_pair(id,node));
Markus Frank
committed
return 0;
}
else if ( daughter_is_assembly ) {
printout(DEBUG,"Geant4Converter","++ Assembly: makeImprint: %16p dau:%s "
"Tr:x=%8.3f y=%8.3f z=%8.3f Rot:phi=%7.3f theta=%7.3f psi=%7.3f\n",
ass_dau,g4mot ? g4mot->GetName().c_str() : "---",
transform.dx(),transform.dy(),transform.dz(),
rotmat.getPhi(),rotmat.getTheta(),rotmat.getPsi());
std::vector<G4VPhysicalVolume*> phys_volumes;
AssemblyChildMap::iterator i = info.g4AssemblyChildren.find(ass_dau);
if ( i == info.g4AssemblyChildren.end() ) {
printout(ERROR, "Geant4Converter", "++ Non-existing assembly [%p]",ass_dau);
}
const AssemblyChildren& v = (*i).second;
ass_dau->imprint(phys_volumes,g4mot,transform,copy,m_checkOverlaps);
if ( v.size() != phys_volumes.size() ) {
printout(ERROR, "Geant4Converter", "++ Unexpected number of placements in assembly: %ld <> %ld.",
v.size(), phys_volumes.size());
}
for(size_t j=0; j<v.size(); ++j) {
info.g4Placements[v[j].second] = phys_volumes[j];
}
Markus Frank
committed
return 0;
}
g4 = new G4PVPlacement(transform, // no rotation
Markus Frank
committed
g4vol, // its logical volume
Markus Frank
committed
g4mot, // its mother (logical) volume
false, // no boolean operations
copy, // its copy number
m_checkOverlaps);
}
info.g4Placements[node] = g4;
printout(ERROR, "Geant4Converter", "++ Attempt to DOUBLE-place physical volume: %s No:%d",
name.c_str(),node->GetNumber());
/// Convert the geometry type region into the corresponding Geant4 object(s).
Markus Frank
committed
void* Geant4Converter::handleRegion(const TNamed* region, const set<const TGeoVolume*>& /* volumes */) const {
G4Region* g4 = data().g4Regions[region];
if ( !g4 ) {
Region r = Ref_t(region);
Markus Frank
committed
g4 = new G4Region(r.name());
// 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);
Markus Frank
committed
printout(INFO, "Geant4Converter", "++ Converted region settings of:%s.",r.name());
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).
Markus Frank
committed
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());
Markus Frank
committed
const set<Limit>& limits = ls.limits();
for(LimitSet::Object::const_iterator i=limits.begin(); i!=limits.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).
Markus Frank
committed
void* Geant4Converter::handleSensitive(const TNamed* sens_det, const set<const TGeoVolume*>& /* volumes */) const {
Geant4GeometryInfo& info = data();
G4VSensitiveDetector* g4 = info.g4SensDets[sens_det];
if ( !g4 ) {
SensitiveDetector sd = Ref_t(sens_det);
g4 = PluginService::Create<G4VSensitiveDetector*>(type,name,&m_lcdd);
if ( !g4 ) {
string tmp = type;
tmp[0] = ::toupper(tmp[0]);
type = "Geant4"+tmp;
g4 = PluginService::Create<G4VSensitiveDetector*>(type,name,&m_lcdd);
if ( !g4 ) {
PluginDebug dbg;
g4 = ROOT::Reflex::PluginService::Create<G4VSensitiveDetector*>(type,name,&m_lcdd);
throw runtime_error("Geant4Converter<SensitiveDetector>: FATAL Failed to "
"create Geant4 sensitive detector factory "+name+" of type "+type+".");
g4->Activate(true);
G4SDManager::GetSDMpointer()->AddNewDetector(g4);
info.g4SensDets[sens_det] = g4;
/// Convert the geometry visualisation attributes to the corresponding Geant4 object(s).
Markus Frank
committed
void* Geant4Converter::handleVis(const string& /* name */, const TNamed* vis) const {
Geant4GeometryInfo& 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 {
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
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);
}
Markus Frank
committed
printout(INFO, "Geant4Converter", "+++++ Executed Successfully Geant4 setup module *%s*.",type.c_str());
/// Convert the geometry type SensitiveDetector into the corresponding Geant4 object(s).
Markus Frank
committed
void* Geant4Converter::printSensitive(const TNamed* sens_det, const set<const TGeoVolume*>& /* volumes */) const {
Geant4GeometryInfo& info = data();
G4VSensitiveDetector* g4 = info.g4SensDets[sens_det];
ConstVolumeSet& volset = info.sensitives[sens_det];
SensitiveDetector sd = Ref_t(sens_det);
Markus Frank
committed
stringstream str;
printout(INFO, "Geant4Converter", "++ SensitiveDetector: %-18s %-20s Hits:%-16s",
sd.name(), ("["+sd.type()+"]").c_str(),sd.hitsCollection().c_str());
str << " | "
<< "Cutoff:" << setw(6) << left << sd.energyCutoff()
<< setw(5) << right << volset.size() << " volumes ";
if ( sd.region().isValid() ) str << " Region:" << setw(12) << left << sd.region().name();
if ( sd.limits().isValid() ) str << " Limits:" << setw(12) << left << sd.limits().name();
str << ".";
printout(INFO, "Geant4Converter", str.str().c_str());
for(ConstVolumeSet::iterator i=volset.begin(); i!=volset.end();++i) {
map<const TGeoVolume*, G4LogicalVolume*>::iterator v = info.g4Volumes.find(*i);
G4LogicalVolume* vol = (*v).second;
Markus Frank
committed
str.str("");
str << " | "
<< "Volume:" << setw(24) << left << vol->GetName()
<< " " << vol->GetNoDaughters() << " daughters.";
printout(INFO, "Geant4Converter", str.str().c_str());
Markus Frank
committed
string printSolid(G4VSolid* sol) {
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();
Markus Frank
committed
else if ( typeid(*sol) == typeid(G4Tubs) ) {
Markus Frank
committed
str << " Tubs: Ri=" << t->GetInnerRadius() << " Ra=" << t->GetOuterRadius()
<< " z/2=" << t->GetZHalfLength() << " Phi=" << t->GetStartPhiAngle()
<< "..." << t->GetDeltaPhiAngle ();
Markus Frank
committed
return str.str();
}
/// Print G4 placement
void* Geant4Converter::printPlacement(const 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();
if ( !sd ) return g4;
Markus Frank
committed
stringstream str;
str << "G4Cnv::placement: + " << name << " No:" << node->GetNumber()
<< " Vol:" << vol->GetName() << " Solid:" << sol->GetName();
printout(DEBUG,"G4Placement",str.str().c_str());
str.str("");
str << " |"
<< " Loc: x=" << tr.x() << " y=" << tr.y() << " z=" << tr.z();
printout(DEBUG,"G4Placement",str.str().c_str());
printout(DEBUG,"G4Placement",printSolid(sol).c_str());
str.str("");
str << " |"
<< " Ndau:" << vol->GetNoDaughters() << " physvols."
<< " Mat:" << vol->GetMaterial()->GetName()
<< " Mother:" << (char*)(mot ? mot->GetName().c_str() : "---");
printout(DEBUG,"G4Placement",str.str().c_str());
str.str("");
str << " |"
<< " SD:" << (char*)(sd ? sd->GetName().c_str() : "---");
printout(DEBUG,"G4Placement",str.str().c_str());
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
Markus Frank
committed
Geant4Converter& Geant4Converter::create(DetElement top) {
Geant4GeometryInfo& geo = this->init();
Markus Frank
committed
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.
Material mat = m_lcdd.material("Argon");
handleMaterial(mat.name(),mat.ptr());
mat = m_lcdd.material("Silicon");
handleMaterial(mat.name(),mat.ptr());
handle(this, geo.volumes, &Geant4Converter::collectVolume);
handle(this, geo.solids, &Geant4Converter::handleSolid);
Markus Frank
committed
printout(INFO,"Geant4Converter","++ Handled %ld solids.",geo.solids.size());
handle(this, geo.vis, &Geant4Converter::handleVis);
Markus Frank
committed
printout(INFO,"Geant4Converter","++ Handled %ld visualization attributes.",geo.vis.size());
handleMap(this, geo.sensitives, &Geant4Converter::handleSensitive);
Markus Frank
committed
printout(INFO,"Geant4Converter","++ Handled %ld sensitive detectors.",geo.sensitives.size());
handleMap(this, geo.limits, &Geant4Converter::handleLimitSet);
Markus Frank
committed
printout(INFO,"Geant4Converter","++ Handled %ld limit sets.",geo.limits.size());
handleMap(this, geo.regions, &Geant4Converter::handleRegion);
Markus Frank
committed
printout(INFO,"Geant4Converter","++ Handled %ld regions.",geo.regions.size());
handle(this, geo.volumes, &Geant4Converter::handleVolume);
Markus Frank
committed
printout(INFO,"Geant4Converter","++ Handled %ld volumes.",geo.volumes.size());
// Now place all this stuff appropriately
handleRMap(this, *m_data, &Geant4Converter::handlePlacement);
//==================== Fields
handleProperties(m_lcdd.properties());
//handleMap(this, geo.sensitives, &Geant4Converter::printSensitive);
//handleRMap(this, *m_data, &Geant4Converter::printPlacement);
geo.valid = true;
Markus Frank
committed
return *this;