Exemple #1
0
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)  {

  //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;
}
Exemple #3
0
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;
}
Exemple #4
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)  {
  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;
}