Exemple #1
0
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;
}