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 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_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; }