/** Basic entry point to print out detector type map * * @author M.Frank * @version 1.0 * @date 01/04/2014 */ static long detectortype_cache(LCDD& lcdd, int , char** ) { vector<string> v = lcdd.detectorTypes(); printout(INFO,"DetectorTypes","Detector type dump: %ld types:",long(v.size())); for(vector<string>::const_iterator i=v.begin(); i!=v.end(); ++i) { const vector<DetElement>& vv=lcdd.detectors(*i); printout(INFO,"DetectorTypes","\t --> %ld %s detectors:",long(vv.size()),(*i).c_str()); for(vector<DetElement>::const_iterator j=vv.begin(); j!=vv.end(); ++j) printout(INFO,"DetectorTypes","\t\t %-16s --> %s [%s]",(*i).c_str(),(*j).name(),(*j).type().c_str()); } return 1; }
static long exec_SimpleGDMLWriter(LCDD& lcdd, int argc, char** argv) { if ( argc > 1 ) { string output = argv[1]; ofstream out(output.c_str()+1,ios_base::out); SimpleGDMLWriter dmp(out); dmp.create(lcdd.world()); } else { SimpleGDMLWriter dmp(cout); dmp.create(lcdd.world()); } return 1; }
static long load_compact(LCDD& lcdd, int argc, char** argv) { if ( argc > 0 ) { LCDDBuildType type = BUILD_DEFAULT; string input = argv[0]; if ( argc > 1 ) { type = build_type(argv[1]); printout(INFO,"CompactLoader","+++ Processing compact file: %s with flag %s", input.c_str(), argv[1]); lcdd.fromCompact(input,type); return 1; } printout(INFO,"CompactLoader","+++ Processing compact file: %s",input.c_str()); lcdd.fromCompact(input); return 1; } return 0; }
static Ref_t create_detector(LCDD& lcdd, xml_h e, Ref_t) { xml_det_t x_det = e; string name = x_det.nameStr(); DetElement sdet (name,x_det.id()); Material mat (lcdd.material(x_det.materialStr())); // multiplication factor for ellipse major radius double c0 = 3.5; double rmin = 0.0, rmax = 0.0, z = 0.0; for(xml_coll_t c(x_det,_U(zplane)); c; ++c) { xml_comp_t dim(c); rmin = dim.rmin(); rmax = dim.rmax(); z = dim.z(); } double ra = rmax * c0; // elipse long radius double rb = rmax; // elipse short radius double thick = rmax - rmin; // pipe wall thickness EllipticalTube bpElTubeOut(ra+thick, rb+thick, z); EllipticalTube bpElTubeInn(ra, rb, z+thick); SubtractionSolid bpElTube(bpElTubeOut,bpElTubeInn); Tube bpTube1(rb, rb+thick, z+thick, 3*M_PI/2, M_PI/2); UnionSolid beamTube1(bpElTube,bpTube1); Tube bpTube2(rb+thick, ra+thick, z+thick, 3*M_PI/2, M_PI/2); SubtractionSolid beamTube(beamTube1,bpTube2); Volume volume(name, beamTube, mat); double z_offset = x_det.hasAttr(_U(z_offset)) ? x_det.z_offset() : 0.0; volume.setVisAttributes(lcdd, x_det.visStr()); PlacedVolume pv = lcdd.pickMotherVolume(sdet).placeVolume(volume,Position(0,0,z_offset)); sdet.setPlacement(pv); if ( x_det.hasAttr(_U(id)) ) { int det_id = x_det.id(); pv.addPhysVolID("system",det_id); } return sdet; }
static long display(LCDD& lcdd, int argc, char** argv) { TGeoManager& mgr = lcdd.manager(); const char* opt = "ogl"; if (argc > 0) { opt = argv[0]; } mgr.SetVisLevel(4); mgr.SetVisOption(1); TGeoVolume* vol = mgr.GetTopVolume(); if (vol) { vol->Draw(opt); return 1; } return 0; }
/** Basic entry point to print out the volume hierarchy * * @author M.Frank * @version 1.0 * @date 01/04/2014 */ static long detelement_cache(LCDD& lcdd, int , char** ) { struct Actor { static long cache(DetElement de) { const DetElement::Children& c = de.children(); de.worldTransformation(); de.parentTransformation(); de.placementPath(); de.path(); for (DetElement::Children::const_iterator i = c.begin(); i != c.end(); ++i) cache((*i).second); return 1; } }; return Actor::cache(lcdd.world()); }
/** Basic entry point to print out the detector element hierarchy * * @author M.Frank * @version 1.0 * @date 01/04/2014 */ template <int flag> long dump_detelement_tree(LCDD& lcdd, int argc, char** argv) { struct Actor { static long dump(DetElement de,int level, bool sensitive_only) { const DetElement::Children& c = de.children(); if ( !sensitive_only || 0 != de.volumeID() ) { PlacedVolume place = de.placement(); const TGeoNode* node = place.ptr(); char sens = place.volume().isSensitive() ? 'S' : ' '; int value = flag; char fmt[128]; switch(value) { case 0: ::snprintf(fmt,sizeof(fmt),"%03d %%-%ds %%s #Dau:%%d VolID:%%08X Place:%%p %%c",level+1,2*level+1); printout(INFO,"DetectorDump",fmt,"",de.path().c_str(),int(c.size()), (unsigned long)de.volumeID(), (void*)node, sens); break; case 1: ::snprintf(fmt,sizeof(fmt),"%03d %%-%ds Detector: %%s #Dau:%%d VolID:%%p",level+1,2*level+1); printout(INFO,"DetectorDump", fmt, "", de.path().c_str(), int(c.size()), (void*)de.volumeID()); ::snprintf(fmt,sizeof(fmt),"%03d %%-%ds Placement: %%s %%c",level+1,2*level+3); printout(INFO,"DetectorDump",fmt,"", de.placementPath().c_str(), sens); break; default: break; } } for (DetElement::Children::const_iterator i = c.begin(); i != c.end(); ++i) dump((*i).second,level+1,sensitive_only); return 1; } }; bool sensitive_only = false; for(int i=0; i<argc; ++i) { if ( ::strcmp(argv[i],"--sensitive")==0 ) { sensitive_only = true; } } return Actor::dump(lcdd.world(),0,sensitive_only); }
static long exec_GeometryTreeDump(LCDD& lcdd, int, char** ) { GeometryTreeDump dmp; dmp.create(lcdd.world()); return 1; }
/** Basic entry point to print out the volume hierarchy * * @author M.Frank * @version 1.0 * @date 01/04/2014 */ static long dump_volume_tree(LCDD& lcdd, int argc, char** argv) { struct Actor { typedef PlacedVolume::VolID VID; typedef PlacedVolume::VolIDs VIDs; bool m_printVolIDs; bool m_printPositions; bool m_printSensitivesOnly; Actor(int ac, char** av) : m_printVolIDs(false), m_printPositions(false), m_printSensitivesOnly(false) { for(int i=0; i<ac; ++i) { char c = ::tolower(av[i][0]); if ( c == 'v' ) m_printVolIDs = true; else if ( c == 'p' ) m_printPositions = true; else if ( c == 's' ) m_printSensitivesOnly = true; } } long dump(TGeoNode* ideal, TGeoNode* aligned,int level, VIDs volids) const { char fmt[128]; string opt_info; PlacedVolume pv(ideal); bool sensitive = false; if ( m_printPositions || m_printVolIDs ) { stringstream log; if ( m_printPositions ) { const double* trans = ideal->GetMatrix()->GetTranslation(); ::snprintf(fmt, sizeof(fmt), "Pos: (%f,%f,%f) ",trans[0],trans[1],trans[2]); log << fmt; } // Top level volume! have no volume ids if ( m_printVolIDs && ideal && ideal->GetMotherVolume() ) { VIDs vid = pv.volIDs(); if ( !vid.empty() ) { sensitive = true; log << " VolID: "; volids.std::vector<VID>::insert(volids.end(),vid.begin(),vid.end()); for(VIDs::const_iterator i=volids.begin(); i!=volids.end(); ++i) { ::snprintf(fmt, sizeof(fmt), "%s:%2d ",(*i).first.c_str(), (*i).second); log << fmt; } } } opt_info = log.str(); } TGeoVolume* volume = ideal->GetVolume(); if ( !m_printSensitivesOnly || (m_printSensitivesOnly && sensitive) ) { char sens = pv.volume().isSensitive() ? 'S' : ' '; if ( ideal == aligned ) { ::snprintf(fmt,sizeof(fmt),"%03d %%-%ds %%s (%%s: %%s) \t[%p] %c %%s", level+1,2*level+1,(void*)ideal, sens); } else { ::snprintf(fmt,sizeof(fmt),"%03d %%-%ds %%s (%%s: %%s) Ideal:%p Aligned:%p %c %%s", level+1,2*level+1,(void*)ideal,(void*)aligned, sens); } printout(INFO,"+++",fmt,"", aligned->GetName(), volume->GetTitle(), volume->GetShape()->IsA()->GetName(), opt_info.c_str()); } for (Int_t idau = 0, ndau = aligned->GetNdaughters(); idau < ndau; ++idau) { TGeoNode* ideal_daughter = ideal->GetDaughter(idau); const char* daughter_name = ideal_daughter->GetName(); TGeoNode* aligned_daughter = volume->GetNode(daughter_name); dump(ideal_daughter, aligned_daughter, level+1, volids); } return 1; } }; string place = lcdd.world().placementPath(); DetectorTools::PlacementPath path; DetectorTools::placementPath(lcdd.world(), path); PlacedVolume pv = DetectorTools::findNode(lcdd.world().placement(),place); Actor actor(argc,argv); return actor.dump(lcdd.world().placement().ptr(),pv.ptr(),0,PlacedVolume::VolIDs()); }
static Ref_t create_element(LCDD& lcdd, xml_h e, SensitiveDetector sens) { xml_det_t x_det = e; string det_name = x_det.nameStr(); Material air = lcdd.air(); //Detector envelope of SubDetector DetElement tracker(det_name, x_det.id()); //add Extension to Detlement for the RecoGeometry Det::DetExtension* ex = new Det::DetExtension(); tracker.addExtension<Det::IDetExtension> (ex); //Create the Volume of the Detector envelope DD4hep::XML::Dimension x_det_dim(x_det.dimensions()); double z = x_det_dim.z(); Tube tracker_shape(x_det_dim.rmin(),x_det_dim.rmax(),z); Volume tracker_vol(x_det.nameStr()+"_envelope",tracker_shape, air); //Vizualization tracker_vol.setVisAttributes(lcdd.invisible()); //Set sensitive type tracker sens.setType("tracker"); int layer_num = 0; //Go through layers for (xml_coll_t j(e,_U(layer)); j; ++j ) { xml_comp_t x_layer = j; double rmin = x_layer.inner_r(); double rmax = x_layer.outer_r(); double radius = (rmax+rmin)*0.5; double layer_z = x_layer.z(); //Create Volume and DetElement for Layer string layer_name = det_name + _toString(layer_num,"layer%d"); Volume layer_vol(layer_name,Tube(rmin,rmax,layer_z), lcdd.material(x_layer.materialStr())); DetElement lay_det (tracker,layer_name,layer_num); //Visualization layer_vol.setVisAttributes(lcdd.invisible()); //module in phi // later also loop through modules for different modules xml_comp_t x_module = x_layer.child(_U(module)); int repeat = x_module.repeat(); double deltaphi = 2.*M_PI/repeat; //slices in z xml_comp_t x_slice = x_layer.child(_U(slice)); int zrepeat = x_slice.repeat(); double dz = x_slice.z(); //add Extension to Detlement for the RecoGeometry Det::DetCylinderLayer* detcylinderlayer = new Det::DetCylinderLayer(); lay_det.addExtension<Det::IDetExtension>(detcylinderlayer); int module_num = 0; //Place the Modules in z for (int k = -zrepeat; k<=zrepeat; k++) { string zname = _toString(k,"z%d"); //Place the Modules in phi for (int i = 0; i < repeat; ++i) { //Create Module Volume Volume mod_vol("module", Box(x_module.length(), x_module.width(),x_module.thickness()), air); //Vizualization mod_vol.setVisAttributes(lcdd.invisible()); double phi = deltaphi/dd4hep::rad * i; string module_name = zname + _toString(i,"module%d"); Position trans(radius * cos(phi), radius * sin(phi), k*dz); //Create module Detelement DetElement mod_det(lay_det,module_name,module_num); //add Extension to Detlement for the RecoGeometry Det::DetModule* detmod = new Det::DetModule(); mod_det.addExtension<Det::IDetExtension> (detmod); int comp_num = 0; //go through module components for (xml_coll_t n(x_module,_U(module_component)); n; ++n) { xml_comp_t x_comp = n; Volume comp_vol("component " + x_comp.materialStr(), Box(x_comp.length(),x_comp.width(), x_comp.thickness()),lcdd.material(x_comp.materialStr())); // comp_vol.setVisAttributes(lcdd, x_comp.visStr()); //Set Sensitive Volmes sensitive if (x_comp.isSensitive()) { comp_vol.setSensitiveDetector(sens); } //Create DetElement DetElement comp_det(mod_det, "component, " + x_comp.materialStr(),comp_num); //add Extension comp_det.addExtension<Det::IDetExtension> (ex); //place component in Module xml_comp_t x_pos = x_comp.position(false); Position transComp (x_pos.x(),x_pos.y(),x_pos.z()); PlacedVolume placedcomp = mod_vol.placeVolume(comp_vol,transComp); //assign the placed Volume to the DetElement comp_det.setPlacement(placedcomp); placedcomp.addPhysVolID("component",comp_num); ++comp_num; } //Place Box Volumes in layer PlacedVolume placedmodule = layer_vol.placeVolume(mod_vol, Transform3D(RotationX(0.5*M_PI)*RotationZ(0.5*M_PI)*RotationX(phi-0.6*M_PI),trans)); placedmodule.addPhysVolID("module", module_num); // assign module DetElement to the placed Module volume mod_det.setPlacement(placedmodule); ++module_num; } ++module_num; } //Place Layervolume PlacedVolume placedLayer = tracker_vol.placeVolume(layer_vol); placedLayer.addPhysVolID("layer",layer_num); placedLayer.addPhysVolID("system",x_det.id()); //Assign Layer DetElement to LayerVolume lay_det.setPlacement(placedLayer); ++layer_num; } Volume mother_vol = lcdd.pickMotherVolume(tracker); //Place envelopevolume in mothervolume PlacedVolume placed_env = mother_vol.placeVolume(tracker_vol); //assign tracker DetElement to tracker volume tracker.setPlacement(placed_env); //fuer envelope moeglich return tracker; }
static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens) { typedef vector<PlacedVolume> Placements; xml_det_t x_det = e; Material vacuum = lcdd.vacuum(); int det_id = x_det.id(); string det_name = x_det.nameStr(); bool reflect = x_det.reflect(false); DetElement sdet (det_name,det_id); Assembly assembly (det_name); //Volume assembly (det_name,Box(10000,10000,10000),vacuum); Volume motherVol = lcdd.pickMotherVolume(sdet); int m_id=0, c_id=0, n_sensor=0; map<string,Volume> modules; map<string, Placements> sensitives; PlacedVolume pv; assembly.setVisAttributes(lcdd.invisible()); sens.setType("tracker"); for(xml_coll_t mi(x_det,_U(module)); mi; ++mi, ++m_id) { xml_comp_t x_mod = mi; string m_nam = x_mod.nameStr(); xml_comp_t trd = x_mod.trd(); double posY; double x1 = trd.x1(); double x2 = trd.x2(); double z = trd.z(); double y1, y2, total_thickness=0.; xml_coll_t ci(x_mod,_U(module_component)); for(ci.reset(), total_thickness=0.0; ci; ++ci) total_thickness += xml_comp_t(ci).thickness(); y1 = y2 = total_thickness / 2; Volume m_volume(m_nam, Trapezoid(x1, x2, y1, y2, z), vacuum); m_volume.setVisAttributes(lcdd.visAttributes(x_mod.visStr())); for(ci.reset(), n_sensor=1, c_id=0, posY=-y1; ci; ++ci, ++c_id) { xml_comp_t c = ci; double c_thick = c.thickness(); Material c_mat = lcdd.material(c.materialStr()); string c_name = _toString(c_id,"component%d"); Volume c_vol(c_name, Trapezoid(x1,x2,c_thick/2e0,c_thick/2e0,z), c_mat); c_vol.setVisAttributes(lcdd.visAttributes(c.visStr())); pv = m_volume.placeVolume(c_vol,Position(0,posY+c_thick/2,0)); if ( c.isSensitive() ) { sdet.check(n_sensor > 2,"SiTrackerEndcap2::fromCompact: "+c_name+" Max of 2 modules allowed!"); pv.addPhysVolID("sensor",n_sensor); c_vol.setSensitiveDetector(sens); sensitives[m_nam].push_back(pv); ++n_sensor; } posY += c_thick; } modules[m_nam] = m_volume; } for(xml_coll_t li(x_det,_U(layer)); li; ++li) { xml_comp_t x_layer(li); int l_id = x_layer.id(); int mod_num = 1; for(xml_coll_t ri(x_layer,_U(ring)); ri; ++ri) { xml_comp_t x_ring = ri; double r = x_ring.r(); double phi0 = x_ring.phi0(0); double zstart = x_ring.zstart(); double dz = x_ring.dz(0); int nmodules = x_ring.nmodules(); string m_nam = x_ring.moduleStr(); Volume m_vol = modules[m_nam]; double iphi = 2*M_PI/nmodules; double phi = phi0; Placements& sensVols = sensitives[m_nam]; for(int k=0; k<nmodules; ++k) { string m_base = _toString(l_id,"layer%d") + _toString(mod_num,"_module%d"); double x = -r*std::cos(phi); double y = -r*std::sin(phi); DetElement module(sdet,m_base+"_pos",det_id); pv = assembly.placeVolume(m_vol,Transform3D(RotationZYX(0,-M_PI/2-phi,-M_PI/2),Position(x,y,zstart+dz))); pv.addPhysVolID("side",1).addPhysVolID("layer", l_id).addPhysVolID("module",mod_num); module.setPlacement(pv); for(size_t ic=0; ic<sensVols.size(); ++ic) { PlacedVolume sens_pv = sensVols[ic]; DetElement comp_elt(module,sens_pv.volume().name(),mod_num); comp_elt.setPlacement(sens_pv); } if ( reflect ) { pv = assembly.placeVolume(m_vol,Transform3D(RotationZYX(M_PI,-M_PI/2-phi,-M_PI/2),Position(x,y,-zstart-dz))); pv.addPhysVolID("side",-1).addPhysVolID("layer",l_id).addPhysVolID("module",mod_num); DetElement r_module(sdet,m_base+"_neg",det_id); r_module.setPlacement(pv); for(size_t ic=0; ic<sensVols.size(); ++ic) { PlacedVolume sens_pv = sensVols[ic]; DetElement comp_elt(r_module,sens_pv.volume().name(),mod_num); comp_elt.setPlacement(sens_pv); } } dz = -dz; phi += iphi; ++mod_num; } } } pv = motherVol.placeVolume(assembly); pv.addPhysVolID("system",det_id); sdet.setPlacement(pv); return sdet; }
static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens) { //XML detector object: DDCore/XML/XMLDetector.h DD4hep::XML::DetElement x_det = e; //Create the DetElement for DD4hep DetElement d_det(x_det.nameStr(),x_det.id()); //Pick the mothervolume Volume det_vol = lcdd.pickMotherVolume(d_det); //XML dimension object: DDCore/XML/XMLDimension.h DD4hep::XML::Dimension x_det_dim(x_det.dimensions()); //Tube: DDCore/DD4hep/Shapes.h Tube calo_shape(x_det_dim.rmin(),x_det_dim.rmax(),x_det_dim.z()); //Create the detector mother volume Volume calo_vol(x_det.nameStr()+"_envelope",calo_shape,lcdd.air()); //Set envelope volume attributes calo_vol.setAttributes(lcdd,x_det.regionStr(),x_det.limitsStr(),x_det.visStr()); //Place inside the mother volume PlacedVolume calo_plv = det_vol.placeVolume(calo_vol); calo_plv.addPhysVolID("system",x_det.id()); calo_plv.addPhysVolID("barrel",0); d_det.setPlacement(calo_plv); //Declare this sensitive detector as a calorimeter sens.setType("calorimeter"); int layer_num = 0; float layer_pos_z = 0; double tile_phi = 2*M_PI/x_det_dim.phiBins(); float r = x_det_dim.rmin(); bool debug = false; //Repeat layers until we reach the rmax while(r<x_det_dim.rmax()){ //Loop over layers of type: XML Collection_t object: DDCore/XML/XMLElements.h for(DD4hep::XML::Collection_t layerIt(x_det,_U(layer));layerIt; ++layerIt){ //Build a layer volume DD4hep::XML::Component x_det_layer = layerIt; float dr = x_det_layer.dr(); string layer_name = x_det.nameStr()+_toString(layer_num,"_layer%d"); float x1 = r * tan(tile_phi/2.); float x2 = (r+dr) * tan(tile_phi/2.); float y1 = x_det_dim.z(); float y2 = x_det_dim.z(); float z = x_det_layer.dr(); if(debug){ cout << " r:" << r << " dr:" << dr << " x1:" << x1 << " x2:" << x2 << " y1:" << y1 << " y2:" << y2 << " z:" << z << endl; } //Shape a Trapezoid (tile): DDCore/DD4hep/Shapes.h Trapezoid layer_shape(x1,x2,y1,y2,z); //Create a volume with trapezoid shape Volume layer_vol(layer_name, layer_shape, lcdd.air()); layer_vol.setAttributes(lcdd,x_det.regionStr(),x_det.limitsStr(),x_det_layer.visStr()); //DetElement layer(layer_name,_toString(layer_num,"layer%d"),x_det.id()); //Fill the volume with tiles int tile_number = 0; vector<Volume> tiles; //Repeat slices until we reach the end of the calorimeter for(xml_coll_t k(x_det_layer,_U(slice)); k; ++k) { DD4hep::XML::Component tile_xml = k; string tile_name = layer_name + _toString(tile_number,"_slice%d"); Material tile_material = lcdd.material(tile_xml.materialStr()); float tile_thickness = tile_xml.dz(); float tile_y1 = tile_thickness; float tile_y2 = tile_thickness; float tile_z = x_det_layer.dr(); //Shape a Trapezoid (tile): DDCore/DD4hep/Shapes.h Trapezoid tile_shape(x1,x2,tile_y1,tile_y2,tile_z); //Create a volume with trapezoid shape Volume tile_vol(tile_name,tile_shape,tile_material); if ( tile_xml.isSensitive() ) { tile_vol.setSensitiveDetector(sens); } //Set region, limitset, and visibility settings tile_vol.setAttributes(lcdd,tile_xml.regionStr(),tile_xml.limitsStr(),tile_xml.visStr()); tiles.push_back(tile_vol); tile_number++; } //Place the same volumes inside the envelope float tile_pos_z = -x_det_dim.z()/2.; int slice_num = 0; while(tile_pos_z<x_det_dim.z()/2.){ tile_number=0; for(xml_coll_t k(x_det_layer,_U(slice)); k; ++k) { DD4hep::XML::Component tile_xml = k; float tile_thickness = tile_xml.dz(); //Place the tile inside the layer PlacedVolume tile_plv = layer_vol.placeVolume(tiles.at(tile_number),Position(0,tile_pos_z,0)); tile_plv.addPhysVolID("layer",layer_num); tile_plv.addPhysVolID("slice",slice_num); //Increment the z pos of the tile tile_pos_z += tile_thickness; tile_number++; slice_num++; } } //Place the same layer around the beam axis phiBins times double mod_x_off = r; double mod_y_off = 0; for(int i=0;i<x_det_dim.phiBins();i++){ if(debug) cout << "Layer:" << i << " phi:" << tile_phi << " rotz:" << (tile_phi*i) << endl; double layer_pos_x = mod_x_off * cos(tile_phi*i) - mod_y_off * sin(tile_phi*i); double layer_pos_y = mod_x_off * sin(tile_phi*i) + mod_y_off * cos(tile_phi*i); Transform3D tr(RotationZYX(M_PI*0.5,M_PI*0.5,0)*RotationZYX(0,tile_phi*i,0), Translation3D(layer_pos_x,layer_pos_y,layer_pos_z)); PlacedVolume pv = calo_vol.placeVolume(layer_vol,tr); pv.addPhysVolID("system",x_det.id()); pv.addPhysVolID("barrel",0); pv.addPhysVolID("layer",layer_num); pv.addPhysVolID("module",i+1); //DetElement sd = i==0 ? stave_det : stave_det.clone(_toString(i,"stave%d")); } r += dr; layer_num += 1; } } //Place the calo inside the world return d_det; }
static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens) { //XML detector object: DDCore/XML/XMLDetector.h xml_dim_t x_det = e; //Create the DetElement for DD4hep DetElement d_det(x_det.nameStr(),x_det.id()); //XML dimension object: DDCore/XML/XMLDimension.h xml_dim_t x_det_dim(x_det.dimensions()); //double inner_r = x_det_dim.rmin(); //double outer_r = x_det_dim.rmax(); Assembly calo_vol(x_det.nameStr()+"_envelope"); PlacedVolume pv; //Set envelope volume attributes calo_vol.setAttributes(lcdd,x_det.regionStr(),x_det.limitsStr(),x_det.visStr()); #if 0 //Declare this sensitive detector as a calorimeter Tube tub(inner_r,outer_r,x_det_dim.z()/2.0,0.0,2*M_PI); //Volume tub_vol(x_det.nameStr()+"_tube",tub,lcdd.material("PyrexGlass")); Volume tub_vol(x_det.nameStr()+"_tube",tub,lcdd.material("Iron")); calo_vol.placeVolume(tub_vol); sens.setType("calorimeter"); tub_vol.setSensitiveDetector(sens); d_det.setAttributes(lcdd,tub_vol,x_det.regionStr(),x_det.limitsStr(),x_det.visStr()); #endif #if 1 int layer_num = 0; float layer_pos_z = 0; double tile_phi = 2*M_PI/x_det_dim.phiBins(); float r = x_det_dim.rmin(); bool debug = true; Assembly stave_vol(x_det.nameStr()+"_stave_0"); //Repeat layers until we reach the rmax while(r<x_det_dim.rmax()) { //Loop over layers of type: XML Collection_t object: DDCore/XML/XMLElements.h for(DD4hep::XML::Collection_t layerIt(x_det,_U(layer)); layerIt; ++layerIt, ++layer_num) { //Build a layer volume xml_comp_t x_det_layer = layerIt; float dr = x_det_layer.dr(); string layer_name = x_det.nameStr()+_toString(layer_num,"_layer%d"); float x1 = r * tan(tile_phi/2.); float x2 = (r+dr) * tan(tile_phi/2.); float y1 = x_det_dim.z(); float y2 = x_det_dim.z(); float z = x_det_layer.dr(); if(debug) { cout << " r:" << r << " dr:" << dr << " x1:" << x1 << " x2:" << x2 << " y1:" << y1 << " y2:" << y2 << " z:" << z << endl; } //Shape a Trapezoid (tile): DDCore/DD4hep/Shapes.h Trapezoid layer_shape(x1,x2,y1,y2,z); //Create a volume with trapezoid shape Volume layer_vol(layer_name, layer_shape, lcdd.air()); layer_vol.setAttributes(lcdd,x_det.regionStr(),x_det.limitsStr(),x_det_layer.visStr()); //DetElement layer(layer_name,_toString(layer_num,"layer%d"),x_det.id()); //Fill the volume with tiles vector<Volume> tiles; //Assembly tile_seq(layer_name+"_seq"); Trapezoid tile_seq_shape(x1,x2,x_det_layer.dz(),x_det_layer.dz(),x_det_layer.dr()); Volume tile_seq(layer_name + "_seq",tile_seq_shape,lcdd.air()); double total_thickness = 0; //Repeat slices until we reach the end of the calorimeter int slice_num = 0, tile_number = 0; tile_seq.setVisAttributes(lcdd.visAttributes("VisibleGreen")); for(xml_coll_t k(x_det_layer,_U(slice)); k; ++k, ++slice_num) { xml_comp_t tile_xml = k; string tile_name = layer_name + _toString(tile_number,"_slice%d"); Material tile_material = lcdd.material(tile_xml.materialStr()); float tile_thickness = tile_xml.dz(); float tile_y1 = tile_thickness; float tile_y2 = tile_thickness; float tile_z = x_det_layer.dr(); Trapezoid tile_shape(x1,x2,tile_y1,tile_y2,tile_z); Volume tile_vol(tile_name,tile_shape,tile_material); pv = tile_seq.placeVolume(tile_vol,Position(0,total_thickness,0)); pv.addPhysVolID("slice",slice_num); total_thickness += tile_thickness; if ( tile_xml.isSensitive() ) { cout << "Set volume " << tile_name << " sensitive...." << endl; tile_vol.setSensitiveDetector(sens); } // Set region, limitset, and visibility settings tile_vol.setAttributes(lcdd,tile_xml.regionStr(),tile_xml.limitsStr(),tile_xml.visStr()); tiles.push_back(tile_vol); tile_number++; } // Place the same volumes inside the envelope float tile_pos_z = -x_det_dim.z()/2.; int tile_num = 0; while(tile_pos_z<x_det_dim.z()/2.) { pv = layer_vol.placeVolume(tile_seq,Position(0,tile_pos_z,0)); pv.addPhysVolID("tile",tile_num); tile_pos_z += total_thickness; tile_num++; } // Place the same layer around the beam axis phiBins times Transform3D tr(RotationZYX(M_PI*0.5,M_PI*0.5,0),Translation3D(r,0,layer_pos_z)); pv = stave_vol.placeVolume(layer_vol,tr); pv.addPhysVolID("layer",layer_num); r += dr; cout << "+++ R=" << r << endl; } } //double mod_x_off = outer_r - (outer_r-inner_r)/2.0; //double mod_y_off = 0; int nphi_bins = x_det_dim.phiBins(); for(int i=0; i<nphi_bins; i++) { if(debug) cout << "Layer:" << i << " phi:" << tile_phi << " rotz:" << (tile_phi*i) << endl; double phi = tile_phi*i; //double pos_x = mod_x_off * cos(phi) - mod_y_off * sin(phi); //double pos_y = mod_x_off * sin(phi) + mod_y_off * cos(phi); Transform3D tr(RotationZYX(phi,0,0),Translation3D(0,0,0)); pv = calo_vol.placeVolume(stave_vol,tr); pv.addPhysVolID("stave",i+1); } cout << "Number of layers: " << layer_num << endl; #endif //Place the calo inside the world PlacedVolume calo_plv = lcdd.pickMotherVolume(d_det).placeVolume(calo_vol); calo_plv.addPhysVolID("system",x_det.id()); calo_plv.addPhysVolID("barrel",0); d_det.setPlacement(calo_plv); return d_det; }
static Ref_t create_detector(LCDD& lcdd, xml_h element, SensitiveDetector sens) { xml_det_t x_det = element; Layering layering(x_det.child(_U(layers))); std::string det_name = x_det.nameStr(); std::string det_type = x_det.typeStr(); Material air = lcdd.air(); xml_dim_t dim = x_det.dimensions(); xml_dim_t x_pos (x_det.child(_U(position))); xml_dim_t x_rot (x_det.child(_U(rotation))); Translation3D det_pos(x_pos.x(),x_pos.y(),x_pos.z()); //Rotation is ROOT::Math::RotationZYX //The input is Rotation(z,y,x) RotationZYX det_rot(x_rot.z(),x_rot.y(),x_rot.x()); DetElement sdet(det_name,x_det.id()); Volume motherVol = lcdd.pickMotherVolume(sdet); // ========= Create Hcal Modules envelope ============================ // They will be the volume for placing the Hcal Layers. // Themselves will be placed into the world volume. // ========================================================================== // Hcal module shape double box_half_x = dim.x()/2.0; double box_half_y = dim.y()/2.0; double box_half_z = dim.z()/2.0; Box BoxModule(box_half_x,box_half_y,box_half_z); // define the name of Module std::string envelopeVol_name = det_name+_toString("_envelope"); Volume envelopeVol(envelopeVol_name,BoxModule,air); // Set envelope volume attributes. envelopeVol.setAttributes(lcdd,x_det.regionStr(),x_det.limitsStr(),x_det.visStr()); // ========= Create Hcal Layers===== ============================== // It will be the sub volume for placing the slices. // Itself will be placed into the Hcal modules envelope. // ================================================================ // create Layer (air) and place the slices into it. // place the Layer into the Hcal Modules envelope. // Hcal layer start position double layer_pos_z = - box_half_z; // Create Hcal Chamber without radiator // Place into the Hcal module envelope int layer_num = 0; int module_num = 0; for(xml_coll_t c(x_det.child(_U(layers)),_U(layer)); c; ++c) { xml_comp_t x_layer = c; //Layering layering(x_layer); int repeat = x_layer.repeat(); const Layer* lay = layering.layer(layer_num); // Get the layer from the layering engine. std::string layer_name = det_name+ _toString(module_num,"_module%d_layer"); double layer_thickness = lay->thickness(); DetElement layer(layer_name,"layerModule",x_det.id()); // Layer box & volume double layer_dim_x = box_half_x; double layer_dim_y = box_half_y; double layer_dim_z = layer_thickness/2.0; // Build chamber including air gap // The Layer will be filled with slices, Volume layer_vol(layer_name, Box(layer_dim_x,layer_dim_y,layer_dim_z), air); // ========= Create sublayer slices ========================================= // Create and place the slices into Layer // ========================================================================== // Create the slices (sublayers) within the Hcal Chamber. double slice_pos_z = -(layer_thickness / 2.0); int slice_number = 0; for(xml_coll_t k(x_layer,_U(slice)); k; ++k) { xml_comp_t x_slice = k; std::string slice_name = layer_name + _toString(slice_number,"_slice%d"); double slice_thickness = x_slice.thickness(); Material slice_material = lcdd.material(x_slice.materialStr()); DetElement slice(layer,_toString(slice_number,"slice%d"),x_det.id()); slice_pos_z += slice_thickness / 2.0; // Slice volume & box Volume slice_vol(slice_name,Box(layer_dim_x,layer_dim_y,slice_thickness/2.0),slice_material); if ( x_slice.isSensitive() ) { sens.setType("calorimeter"); slice_vol.setSensitiveDetector(sens); } // Set region, limitset, and vis. slice_vol.setAttributes(lcdd,x_slice.regionStr(),x_slice.limitsStr(),x_slice.visStr()); // slice PlacedVolume PlacedVolume slice_phv = layer_vol.placeVolume(slice_vol,Position(0,0,slice_pos_z)); slice_phv.addPhysVolID("slice",slice_number); slice.setPlacement(slice_phv); // Increment Z position for next slice. slice_pos_z += slice_thickness / 2.0; // Increment slice number. ++slice_number; } // Set region, limitset, and vis. layer_vol.setAttributes(lcdd,x_layer.regionStr(),x_layer.limitsStr(),x_layer.visStr()); // ========= Place the Layer (i.e. Chamber) ================================= // Place the Layer into the Hcal module envelope. // with the right position, and registry the ID layer // ========================================================================== for (int j = 0; j < repeat; j++) { // Layer position in z within the Modules. layer_pos_z += layer_thickness / 2.0; PlacedVolume layer_phv = envelopeVol.placeVolume(layer_vol,Position(0,0,layer_pos_z)); // registry the ID of Layer layer_phv.addPhysVolID("layer",layer_num); layer_phv.addPhysVolID("module",j); // then setPlacement for it. layer.setPlacement(layer_phv); // Increment the layer_pos_z layer_pos_z += layer_thickness / 2.0; ++layer_num; } module_num++; } // for the alignment in the compact XML file Transform3D Tr3D = Transform3D(det_rot,det_pos); PlacedVolume env_phv = motherVol.placeVolume(envelopeVol,Tr3D); env_phv.addPhysVolID("system",x_det.id()); sdet.setPlacement(env_phv); return sdet; }
/// Constructor. The detector element is identified by the name Geant4SensitiveDetector::Geant4SensitiveDetector(const string& nam, LCDD& lcdd) : G4VSensitiveDetector(nam), m_lcdd(lcdd), m_detector(), m_sensitive(), m_readout(), m_hce(0) { m_sensitive = lcdd.sensitiveDetector(nam); m_detector = lcdd.detector(nam); m_readout = m_sensitive.readout(); }
static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens) { xml_det_t x_det = e; xml_dim_t dim = x_det.dimensions(); int det_id = x_det.id(); bool reflect = x_det.reflect(true); string det_name = x_det.nameStr(); Material air = lcdd.air(); int numsides = dim.numsides(); double rmin = dim.rmin(); double rmax = dim.rmax()*std::cos(M_PI/numsides); double zmin = dim.zmin(); Layering layering(x_det); double totalThickness = layering.totalThickness(); Volume endcapVol("endcap",PolyhedraRegular(numsides,rmin,rmax,totalThickness),air); DetElement endcap("endcap",det_id); int l_num = 1; int layerType = 0; double layerZ = -totalThickness/2; endcapVol.setAttributes(lcdd,x_det.regionStr(),x_det.limitsStr(),x_det.visStr()); for(xml_coll_t c(x_det,_U(layer)); c; ++c) { xml_comp_t x_layer = c; double l_thick = layering.layer(l_num-1)->thickness(); string l_name = _toString(layerType,"layer%d"); int l_repeat = x_layer.repeat(); Volume l_vol(l_name,PolyhedraRegular(numsides,rmin,rmax,l_thick),air); vector<PlacedVolume> sensitives; int s_num = 1; double sliceZ = -l_thick/2; for(xml_coll_t s(x_layer,_U(slice)); s; ++s) { xml_comp_t x_slice = s; string s_name = _toString(s_num,"slice%d"); double s_thick = x_slice.thickness(); Material s_mat = lcdd.material(x_slice.materialStr()); Volume s_vol(s_name,PolyhedraRegular(numsides,rmin,rmax,s_thick),s_mat); s_vol.setVisAttributes(lcdd.visAttributes(x_slice.visStr())); sliceZ += s_thick/2; PlacedVolume s_phv = l_vol.placeVolume(s_vol,Position(0,0,sliceZ)); s_phv.addPhysVolID("slice",s_num); if ( x_slice.isSensitive() ) { sens.setType("calorimeter"); s_vol.setSensitiveDetector(sens); sensitives.push_back(s_phv); } sliceZ += s_thick/2; s_num++; } l_vol.setVisAttributes(lcdd.visAttributes(x_layer.visStr())); if ( l_repeat <= 0 ) throw std::runtime_error(x_det.nameStr()+"> Invalid repeat value"); for(int j=0; j<l_repeat; ++j) { string phys_lay = _toString(l_num,"layer%d"); layerZ += l_thick/2; DetElement layer_elt(endcap, phys_lay, l_num); PlacedVolume pv = endcapVol.placeVolume(l_vol,Position(0,0,layerZ)); pv.addPhysVolID("layer", l_num); layer_elt.setPlacement(pv); for(size_t ic=0; ic<sensitives.size(); ++ic) { PlacedVolume sens_pv = sensitives[ic]; DetElement comp_elt(layer_elt,sens_pv.volume().name(),l_num); comp_elt.setPlacement(sens_pv); } layerZ += l_thick/2; ++l_num; } ++layerType; } double z_pos = zmin+totalThickness/2; PlacedVolume pv; // Reflect it. if ( reflect ) { Assembly assembly(det_name); DetElement both_endcaps(det_name,det_id); Volume motherVol = lcdd.pickMotherVolume(both_endcaps); DetElement sdetA = endcap; Ref_t(sdetA)->SetName((det_name+"_A").c_str()); DetElement sdetB = endcap.clone(det_name+"_B",x_det.id()); pv = assembly.placeVolume(endcapVol,Transform3D(RotationZYX(M_PI/numsides,0,0), Position(0,0,z_pos))); pv.addPhysVolID("barrel", 1); sdetA.setPlacement(pv); pv = assembly.placeVolume(endcapVol,Transform3D(RotationZYX(M_PI/numsides,M_PI,0), Position(0,0,-z_pos))); pv.addPhysVolID("barrel", 2); sdetB.setPlacement(pv); pv = motherVol.placeVolume(assembly); pv.addPhysVolID("system", det_id); both_endcaps.setPlacement(pv); both_endcaps.add(sdetA); both_endcaps.add(sdetB); return both_endcaps; } Volume motherVol = lcdd.pickMotherVolume(endcap); pv = motherVol.placeVolume(endcapVol,Transform3D(RotationZYX(M_PI/numsides,0,0), Position(0,0,z_pos))); pv.addPhysVolID("system", det_id); pv.addPhysVolID("barrel", 1); endcap.setPlacement(pv); Ref_t(endcap)->SetName(det_name.c_str()); return endcap; }