示例#1
0
/// Access the placement of a node in the chain of placements for this branch
PlacedVolume GlobalAlignment::nodePlacement(int level)   const   {
  CheckHandle verify_handle(*this);
  PlacedVolume pv = PlacedVolume(ptr()->GetNode(level));
  if ( pv.isValid() ) return pv;
  throw runtime_error("DD4hep: The object chain of "+string(placement().name())+
                      " is too short. [Invalid index]");
}
static void placeStaves(DetElement&   parent,
			DetElement&   stave,
			double        rmin, 
			int           numsides, 
			double        total_thickness, 
			Volume        envelopeVolume, 
			double        innerAngle, 
			Volume        sectVolume)
{
  double innerRotation    = innerAngle;
  double offsetRotation   = -innerRotation / 2;
  double sectCenterRadius = rmin + total_thickness / 2;
  double rotX =  M_PI / 2;
  double rotY = -offsetRotation;
  double posX = -sectCenterRadius  * std::sin(rotY);
  double posY =  sectCenterRadius  * std::cos(rotY);

  for (int module = 1; module <= numsides; ++module)  {
    DetElement det  = module>1 ? stave.clone(_toString(module,"stave%d")) : stave;
    PlacedVolume pv = envelopeVolume.placeVolume(sectVolume,Transform3D(RotationZYX(0,rotY,rotX),
									Translation3D(-posX,-posY,0)));
    // Not a valid volID: pv.addPhysVolID("stave", 0);
    pv.addPhysVolID("module",module);
    det.setPlacement(pv);
    parent.add(det);
    rotY -=  innerRotation;
    posX  = -sectCenterRadius * std::sin(rotY);
    posY  =  sectCenterRadius * std::cos(rotY);
  }
}
示例#3
0
 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;
 }
static Ref_t create_detector(Detector& description, xml_h e, SensitiveDetector sens)   {
  xml_det_t  x_det     = e;
  xml_dim_t  dim       = x_det.dimensions();
  Material   air       = description.air();
  string     det_name  = x_det.nameStr();
  DetElement sdet       (det_name,x_det.id());
  double     z         = dim.outer_z();
  double     rmin      = dim.inner_r();
  double     r         = rmin;
  int        n         = 0;
  Tube       envelope(rmin,2*rmin,2*z);
  Volume     envelopeVol(det_name+"_envelope",envelope,air);
    
  for(xml_coll_t c(x_det,_U(layer)); c; ++c)  {
    xml_comp_t x_layer = c;
    for(int i=0, im=0, repeat=x_layer.repeat(); i<repeat; ++i, im=0)  {
      string layer_name = det_name + _toString(n,"_layer%d");
      double rlayer = r;
      Tube   layer_tub(rmin,rlayer,2*z);
      Volume layer_vol(layer_name,layer_tub,air);
        
      for(xml_coll_t l(x_layer,_U(slice)); l; ++l, ++im)  {
        xml_comp_t x_slice = l;
        double     router = r + x_slice.thickness();
        Material   slice_mat  = description.material(x_slice.materialStr());
        string     slice_name = layer_name + _toString(im,"slice%d");
        Tube       slice_tube(r,router,z*2);
        Volume     slice_vol (slice_name,slice_tube,slice_mat);
          
        if ( x_slice.isSensitive() ) {
          sens.setType("calorimeter");
          slice_vol.setSensitiveDetector(sens);
        }
        r = router;
        slice_vol.setAttributes(description,x_slice.regionStr(),x_slice.limitsStr(),x_slice.visStr());
        // Instantiate physical volume
        layer_vol.placeVolume(slice_vol);
      }
      layer_vol.setVisAttributes(description,x_layer.visStr());
      layer_tub.setDimensions(rlayer,r,z*2,0,2*M_PI);
        
      PlacedVolume layer_physvol = envelopeVol.placeVolume(layer_vol);
      layer_physvol.addPhysVolID("layer",n);
      ++n;
    }
  }
  envelope.setDimensions(rmin,r,2*z);
  // Set region of slice
  envelopeVol.setAttributes(description,x_det.regionStr(),x_det.limitsStr(),x_det.visStr());
    
  PlacedVolume physvol = description.pickMotherVolume(sdet).placeVolume(envelopeVol);
  physvol.addPhysVolID("system",sdet.id()).addPhysVolID(_U(barrel),0);
  sdet.setPlacement(physvol);
  return sdet;
}
示例#5
0
/// Callback to output PlacedVolume information of an single Placement
int VisMaterialProcessor::operator()(PlacedVolume pv, int /* level */)   {
  Volume vol = pv.volume();
  double frac_active = 0.0;
  VisAttr attr;

  for ( Atom atom : activeElements )   {
    frac_active += vol.material().fraction(atom);
  }
  //if ( frac_active >= fraction )
  printout(DEBUG,name,
           "++ Volume:%s [%s] active:%s fraction:%.3f active-vis:%s inactive-vis:%s",
           pv.name(), vol.name(), yes_no(frac_active >= fraction), frac_active,
           yes_no(activeVis.isValid()), yes_no(inactiveVis.isValid()));
  if ( activeVis.isValid() )   {
    if ( frac_active >= fraction )  {
      attr = activeVis;
      ++numActive;
    }
    if ( !attr.isValid() )  {
      for ( Material mat : activeMaterials )  {
        if ( mat.ptr() == vol.material().ptr() )   {
          attr = activeVis;
          ++numActive;
          break;
        }
      }
    }
  }
  // If we get here, the material is definitely inactive
  if ( inactiveVis.isValid() )  {
    if ( !attr.isValid() && setAllInactive )   {
      attr = inactiveVis;
      ++numInactive;
    }
    else if ( frac_active<fraction )   {
      attr = inactiveVis;
      ++numInactive;
    }
    if ( !attr.isValid() && inactiveVis.isValid() )  {
      for ( Material imat : inactiveMaterials )   {
        if ( imat.ptr() == vol.material().ptr() )   {
          attr = inactiveVis;
          ++numInactive;
          break;
        }
      }
    }
  }
  if ( attr.isValid() )  {
    set_attr(vol,attr);
  }
  return 1;
}
示例#6
0
 /// Dump method.
 virtual int operator()(DetElement de,int level)  const  {
   const DetElement::Children& children = de.children();
   PlacedVolume place = de.placement();
   char sens = place.volume().isSensitive() ? 'S' : ' ';
   char fmt[128], tmp[32];
   ::snprintf(tmp,sizeof(tmp),"%03d/",level+1);
   ::snprintf(fmt,sizeof(fmt),"%03d %%-%ds %%s #Dau:%%d VolID:%%08X %%c",level+1,2*level+1);
   printout(INFO,"DetectorDump",fmt,"",de.path().c_str(),int(children.size()),
            (unsigned long)de.volumeID(), sens);
   printer.prefix = string(tmp)+de.name();
   (printer)(de, level);
   return 1;
 }
void Installer<UserData>::install(DetElement component, PlacedVolume pv)   {
  Volume comp_vol = pv.volume();
  if ( comp_vol.isSensitive() )  {  
    Volume mod_vol = parentVolume(component);
    DD4hep::Geometry::PolyhedraRegular comp_shape(comp_vol.solid()), mod_shape(mod_vol.solid());

    if ( !comp_shape.isValid() || !mod_shape.isValid() )   {
      invalidInstaller("Components and/or modules are not Trapezoid -- invalid shapes");
    }
    else if ( !handleUsingCache(component,comp_vol) )  {
      DetElement par = component.parent();
      const TGeoHMatrix& m = par.worldTransformation();
      double dz = m.GetTranslation()[2];
      const double* trans = placementTranslation(component);
      double half_mod_thickness  = (mod_shape->GetZ(1)-mod_shape->GetZ(0))/2.0;
      double half_comp_thickness = (comp_shape->GetZ(1)-comp_shape->GetZ(0))/2.0;
      double si_position         = trans[2]+half_mod_thickness;
      double outer_thickness = half_mod_thickness - si_position;
      double inner_thickness = half_mod_thickness + si_position;
      Vector3D u(1.,0.,0.), v(0.,1.,0.), n(0.,0.,1.), o(100.,100.,0.);
      std::cout << " Module:    " << mod_shape.toString() << std::endl;
      std::cout << " Component: " << comp_shape.toString() << std::endl;
      std::cout << "dz:" << dz << " Si-pos:" << si_position 
                << " Mod-thickness:" << half_mod_thickness 
                << " Comp-thickness:" << half_comp_thickness 
                << std::endl;
      VolPlane surf(comp_vol,Type(Type::Sensitive,Type::Measurement1D),
                    inner_thickness, outer_thickness, u, v, n, o);
      addSurface(component,surf);
    }
  }
}
示例#8
0
/// Given a detector element, access it's sensitive detector (if the sub-detector is sensitive!)
SensitiveDetector LCDDHelper::sensitiveDetector(DetElement detector) const    {
  for(DetElement par = detector; par.isValid(); par = par.parent())  {
    if ( par.ptr() != ptr()->world().ptr() )  {
      PlacedVolume pv = par.placement();
      if ( pv.isValid() )   {
        const PlacedVolume::VolIDs& ids = pv.volIDs();
        for(PlacedVolume::VolIDs::const_iterator i=ids.begin(); i!=ids.end();++i)  {
          if ( (*i).first == "system" )   {
            return sensitiveDetector(par.name());
          }
        }
      }
    }
  }
  return SensitiveDetector(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;
}
示例#10
0
/// Callback to output PlacedVolume information of an single Placement
int VisDensityProcessor::operator()(PlacedVolume pv, int /* level */)   {
  Volume   vol = pv.volume();
  Material mat = vol.material();
  if ( vol.visAttributes().ptr() != minVis.ptr() )  {
    if ( mat.density() <= minDensity )  {
      vol.setVisAttributes(minVis);
    }
    ++numInactive;
  }
  return 1;
}
示例#11
0
/// Accessfully decoded volume fields  by placement path
void Geant4VolumeManager::volumeDescriptor(const vector<const G4VPhysicalVolume*>& path,
                                           VolIDDescriptor& vol_desc) const
{
  vol_desc.second.clear();
  vol_desc.first = NonExisting;
  if (!path.empty() && checkValidity()) {
    const auto& m = ptr()->g4Paths;
    auto i = m.find(path);
    if (i != m.end()) {
      VolumeID vid = (*i).second;
      G4LogicalVolume* lvol = path[0]->GetLogicalVolume();
      if (lvol->GetSensitiveDetector()) {
        const G4VPhysicalVolume* node = path[0];
        const PlacementMap& pm = ptr()->g4Placements;
        for (PlacementMap::const_iterator ipm = pm.begin(); ipm != pm.end(); ++ipm) {
          if ((*ipm).second == node)  {
            PlacedVolume pv = (*ipm).first;
            SensitiveDetector sd = pv.volume().sensitiveDetector();
            IDDescriptor dsc = sd.readout().idSpec();
            vol_desc.first = vid;
            dsc.decodeFields(vid, vol_desc.second);
            return;
          }
        }
      }
      vol_desc.first = Insensitive;
      return;
    }
    if (!path[0])
      vol_desc.first = InvalidPath;
    else if (!path[0]->GetLogicalVolume()->GetSensitiveDetector())
      vol_desc.first = Insensitive;
    else
      vol_desc.first = NonExisting;
  }
}
示例#12
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;
}
示例#13
0
static DD4hep::Geometry::Ref_t createTkLayoutTrackerBarrel(DD4hep::Geometry::LCDD& lcdd,
                                                           DD4hep::XML::Handle_t xmlElement,
                                                           DD4hep::Geometry::SensitiveDetector sensDet) {
  // shorthands
  DD4hep::XML::DetElement xmlDet = static_cast<DD4hep::XML::DetElement>(xmlElement);
  Dimension dimensions(xmlDet.dimensions());
  // get sensitive detector type from xml
  DD4hep::XML::Dimension sdTyp = xmlElement.child(_Unicode(sensitive));
  // sensitive detector used for all sensitive parts of this detector
  sensDet.setType(sdTyp.typeStr());

  // definition of top volume
  // has min/max dimensions of tracker for visualization etc.
  std::string detectorName = xmlDet.nameStr();
  DetElement topDetElement(detectorName, xmlDet.id());
  Acts::ActsExtension::Config barrelConfig;
  barrelConfig.isBarrel = true;
  // detElement owns extension
  Acts::ActsExtension* detWorldExt = new Acts::ActsExtension(barrelConfig);
  topDetElement.addExtension<Acts::IActsExtension>(detWorldExt);
  DD4hep::Geometry::Tube topVolumeShape(
      dimensions.rmin(), dimensions.rmax(), (dimensions.zmax() - dimensions.zmin()) * 0.5);
  Volume topVolume(detectorName, topVolumeShape, lcdd.air());
  topVolume.setVisAttributes(lcdd.invisible());

  // counts all layers - incremented in the inner loop over repeat - tags
  unsigned int layerCounter = 0;
  double integratedModuleComponentThickness = 0;
  double phi = 0;
  // loop over 'layer' nodes in xml
  DD4hep::XML::Component xLayers = xmlElement.child(_Unicode(layers));
  for (DD4hep::XML::Collection_t xLayerColl(xLayers, _U(layer)); nullptr != xLayerColl; ++xLayerColl) {
    DD4hep::XML::Component xLayer = static_cast<DD4hep::XML::Component>(xLayerColl);
    DD4hep::XML::Component xRods = xLayer.child("rods");
    DD4hep::XML::Component xRodEven = xRods.child("rodOdd");
    DD4hep::XML::Component xRodOdd = xRods.child("rodEven");
    DD4hep::XML::Component xModulesEven = xRodEven.child("modules");
    DD4hep::XML::Component xModulePropertiesOdd = xRodOdd.child("moduleProperties");
    DD4hep::XML::Component xModulesOdd = xRodOdd.child("modules");
    DD4hep::Geometry::Tube layerShape(xLayer.rmin(), xLayer.rmax(), dimensions.zmax());
    Volume layerVolume("layer", layerShape, lcdd.material("Air"));
    layerVolume.setVisAttributes(lcdd.invisible());
    PlacedVolume placedLayerVolume = topVolume.placeVolume(layerVolume);
    placedLayerVolume.addPhysVolID("layer", layerCounter);
    DetElement lay_det(topDetElement, "layer" + std::to_string(layerCounter), layerCounter);
    Acts::ActsExtension::Config layConfig;
    layConfig.isLayer = true;
    // the local coordinate systems of modules in dd4hep and acts differ
    // see http://acts.web.cern.ch/ACTS/latest/doc/group__DD4hepPlugins.html
    layConfig.axes = "XzY"; // correct translation of local x axis in dd4hep to local x axis in acts
    // detElement owns extension
    Acts::ActsExtension* layerExtension = new Acts::ActsExtension(layConfig);
    lay_det.addExtension<Acts::IActsExtension>(layerExtension);
    lay_det.setPlacement(placedLayerVolume);
    DD4hep::XML::Component xModuleComponentsOdd = xModulePropertiesOdd.child("components");
    integratedModuleComponentThickness = 0;
    int moduleCounter = 0;
    Volume moduleVolume;
    for (DD4hep::XML::Collection_t xModuleComponentOddColl(xModuleComponentsOdd, _U(component));
         nullptr != xModuleComponentOddColl;
         ++xModuleComponentOddColl) {
      DD4hep::XML::Component xModuleComponentOdd = static_cast<DD4hep::XML::Component>(xModuleComponentOddColl);
      moduleVolume = Volume("module",
                            DD4hep::Geometry::Box(0.5 * xModulePropertiesOdd.attr<double>("modWidth"),
                                                  0.5 * xModuleComponentOdd.thickness(),
                                                  0.5 * xModulePropertiesOdd.attr<double>("modLength")),
                            lcdd.material(xModuleComponentOdd.materialStr()));
      unsigned int nPhi = xRods.repeat();
      DD4hep::XML::Handle_t currentComp;
      for (unsigned int phiIndex = 0; phiIndex < nPhi; ++phiIndex) {
        double lX = 0;
        double lY = 0;
        double lZ = 0;
        if (0 == phiIndex % 2) {
          phi = 2 * M_PI * static_cast<double>(phiIndex) / static_cast<double>(nPhi);
          currentComp = xModulesEven;
        } else {
          currentComp = xModulesOdd;
        }
        for (DD4hep::XML::Collection_t xModuleColl(currentComp, _U(module)); nullptr != xModuleColl; ++xModuleColl) {
          DD4hep::XML::Component xModule = static_cast<DD4hep::XML::Component>(xModuleColl);
          double currentPhi = atan2(xModule.Y(), xModule.X());
          double componentOffset =  integratedModuleComponentThickness - 0.5 * xModulePropertiesOdd.attr<double>("modThickness") + 0.5 * xModuleComponentOdd.thickness();
          lX = xModule.X() + cos(currentPhi) * componentOffset;
          lY = xModule.Y() + sin(currentPhi) * componentOffset;
          lZ = xModule.Z();
          DD4hep::Geometry::Translation3D moduleOffset(lX, lY, lZ);
          DD4hep::Geometry::Transform3D lTrafo(DD4hep::Geometry::RotationZ(atan2(lY,  lX) + 0.5 * M_PI), moduleOffset);
          DD4hep::Geometry::RotationZ lRotation(phi);
          PlacedVolume placedModuleVolume = layerVolume.placeVolume(moduleVolume, lRotation * lTrafo);
          if (xModuleComponentOdd.isSensitive()) {
            placedModuleVolume.addPhysVolID("module", moduleCounter);
            moduleVolume.setSensitiveDetector(sensDet);
            DetElement mod_det(lay_det, "module" + std::to_string(moduleCounter), moduleCounter);
            mod_det.setPlacement(placedModuleVolume);
            ++moduleCounter;
          }
        }
      }
      integratedModuleComponentThickness += xModuleComponentOdd.thickness();
    }
    ++layerCounter;
  }
  Volume motherVol = lcdd.pickMotherVolume(topDetElement);
  PlacedVolume placedGenericTrackerBarrel = motherVol.placeVolume(topVolume);
  placedGenericTrackerBarrel.addPhysVolID("system", topDetElement.id());
  topDetElement.setPlacement(placedGenericTrackerBarrel);
  return topDetElement;
}
static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector sens)  {
  typedef vector<PlacedVolume> Placements;
  xml_det_t   x_det     = e;
  Material    vacuum    = theDetector.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);
  int         m_id=0, c_id=0, n_sensor=0;
  map<string, Volume> modules;
  map<string, Placements>  sensitives;
  PlacedVolume pv;

  // --- create an envelope volume and position it into the world ---------------------

  Volume envelope = dd4hep::xml::createPlacedEnvelope(theDetector, e, sdet);
  dd4hep::xml::setDetectorTypeFlag(e, sdet);

  if( theDetector.buildType() == BUILD_ENVELOPE ) return sdet;

  //-----------------------------------------------------------------------------------

  envelope.setVisAttributes(theDetector.invisible());
  sens.setType("tracker");

  // Build the sensor units
  // Loop over 'modules' as defined in the XML
  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(theDetector.visAttributes(x_mod.visStr()));

    std::cout << m_nam << ", thickness=" << total_thickness << std::endl;

    // Loop over the module_components ('slices') in the 'module'
    // The first component (top in the XML) is placed at the 'bottom'
    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   = theDetector.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);

      std::cout << " + sensor " << n_sensor << " " << c_name;

      c_vol.setVisAttributes(theDetector.visAttributes(c.visStr()));
      pv = m_volume.placeVolume(c_vol, Position(0, posY + c_thick/2, 0));
      if ( c.isSensitive() ) {
        sdet.check(n_sensor > 2, "SiTrackerEndcap::fromCompact: " + c_name + " Max of 2 modules allowed!");
	pv.addPhysVolID("sensor", n_sensor);
        c_vol.setSensitiveDetector(sens);
        sensitives[m_nam].push_back(pv);
	std::cout << " (" << n_sensor << " is sensitive) ";
        ++n_sensor;
      }
      std::cout << std::endl;
      posY += c_thick;
    }
    modules[m_nam] = m_volume;
  }
  // done building the 2 modules, of 12 layers each

  int mod_count[12] = {0};

  // Build now the detector itself
  // Loop over layers as defined in the XML
  for(xml_coll_t li(x_det, _U(layer)); li; ++li) {
    xml_comp_t x_layer(li);
    int l_id = x_layer.id();
    int ring_num = 0;
    
    std::cout << "Layer " << l_id << ":" << std::endl;

    // Loop over rings, as defined in the XML
    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];

      // This driver version encodes the rings as layers and the
      // petals as modules, such that 'layer' 1 contains all innermost rings
      // and last 'layer' contains the outermost rings in the tracker
      // farthest away on z from the IP (unintuititive, but works)

      std::cout << " Ring " << ring_num << ":" << std::endl;

      // Loop over modules in each ring, modules are either type 1 or 2
      for(int k=0; k < nmodules; ++k) {

        double x = -r*std::cos(phi);
        double y = -r*std::sin(phi);

	for(int s=1-2*int(reflect); s<2; s+=1+int(reflect)){

	  string e_name = _toString(s, "side%d") + _toString(l_id, "_layer%d") + _toString(ring_num, "_ring%d") + _toString(k, "_sensor%d");
	  DetElement module(sdet, e_name, det_id);
	  pv = envelope.placeVolume(m_vol, Transform3D(RotationZYX(0,-M_PI/2-phi,-M_PI/2), Position(x, y, s*(zstart+dz) )));

	  pv.addPhysVolID("side", s).addPhysVolID("layer", ring_num).addPhysVolID("module", mod_count[ring_num] + k);
	  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(), det_id);
	    comp_elt.setPlacement(sens_pv);
	    std::cout << "Name: " << e_name << "_" << sens_pv.volume().name() << std::endl;
	    std::cout << "  ID: side " << s << ", layer " << ring_num << ", module " << mod_count[ring_num] + k << ", sensor" << ic+1 << std::endl;
	  }
	}
        dz = -dz;
        phi += iphi;
      }
      mod_count[ring_num] += nmodules;
      ++ring_num;
    }
  }
  std::cout << "Number of modules per 'layer':" << std::endl;
  for(int ii=0; ii<12; ii++){
    std::cout << " mod_count[" << ii << "] = " << mod_count[ii] << std::endl;
  }

  return sdet;
}
示例#15
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 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;
}
示例#17
0
static DD4hep::Geometry::Ref_t createTkLayoutTrackerEndcap(DD4hep::Geometry::LCDD& lcdd,
        DD4hep::XML::Handle_t xmlElement,
        DD4hep::Geometry::SensitiveDetector sensDet) {
    // shorthands
    DD4hep::XML::DetElement xmlDet = static_cast<DD4hep::XML::DetElement>(xmlElement);
    Dimension dimensions(xmlDet.dimensions());

    // get sensitive detector type from xml
    DD4hep::XML::Dimension sdTyp = xmlElement.child("sensitive");  // retrieve the type
    sensDet.setType(sdTyp.typeStr());  // set for the whole detector

    // definition of top volume
    std::string detName = xmlDet.nameStr();
    DetElement GenericTrackerEndcapWorld(detName, xmlDet.id());

    // envelope volume with the max dimensions of tracker for visualization etc.
    // contains both endcaps, in forward and in backwards direction
    // the part between -z1 and z1 is subtracted from the envelope
    DD4hep::Geometry::Tube posnegEnvelopeShape_add(dimensions.rmin(), dimensions.rmax(), dimensions.zmax());
    // make the negative shape slighly larger in the radial direction
    // to be sure that everything is subtracted between -z1 and z1
    DD4hep::Geometry::Box posnegEnvelopeShape_subtract(
        dimensions.rmax() * 1.001, dimensions.rmax() * 1.001, dimensions.zmin());
    DD4hep::Geometry::SubtractionSolid posnegEnvelopeShape(posnegEnvelopeShape_add, posnegEnvelopeShape_subtract);
    Volume posnegEnvelopeVolume(detName, posnegEnvelopeShape, lcdd.air());
    posnegEnvelopeVolume.setVisAttributes(lcdd.invisible());

    // envelope volume for one of the endcaps, either forward or backward
    DD4hep::Geometry::Tube envelopeShape(
        dimensions.rmin(), dimensions.rmax(), 0.5 * (dimensions.zmax() - dimensions.zmin()));
    Volume envelopeVolume(detName, envelopeShape, lcdd.air());
    envelopeVolume.setVisAttributes(lcdd.invisible());

    Component xDiscs = xmlElement.child("discs");
    Component xFirstDisc = xDiscs.child("discZPls");
    Component xFirstDiscRings = xFirstDisc.child("rings");

    // create disc volume
    double discThickness = (xFirstDisc.zmax() - xFirstDisc.zmin());
    DD4hep::Geometry::Tube discShape(dimensions.rmin(), dimensions.rmax(), 0.5 * discThickness);
    Volume discVolume("disc", discShape, lcdd.air());
    discVolume.setVisAttributes(lcdd.invisible());

    // generate rings and place in  discs
    int moduleCounter = 0;
    for (DD4hep::XML::Collection_t xRingColl(xFirstDiscRings, _U(ring)); nullptr != xRingColl; ++xRingColl) {
        Component xRing = static_cast<Component>(xRingColl);
        Component xRingModules = xRing.child("modules");
        Component xModuleOdd = xRingModules.child("moduleOdd");
        Component xModuleEven = xRingModules.child("moduleEven");
        Component xModuleProperties = xRing.child("moduleProperties");
        Component xModulePropertiesComp = xModuleProperties.child("components");
        Component xSensorProperties = xRing.child("sensorProperties");
        Volume moduleVolume("module",
                            DD4hep::Geometry::Trapezoid(0.5 * xModuleProperties.attr<double>("modWidthMin"),
                                    0.5 * xModuleProperties.attr<double>("modWidthMax"),
                                    0.5 * xModuleProperties.attr<double>("modThickness"),
                                    0.5 * xModuleProperties.attr<double>("modThickness"),
                                    0.5 * xSensorProperties.attr<double>("sensorLength")),
                            lcdd.material("Air"));

        // place components in module
        double integratedCompThickness = 0;
        int componentCounter = 0;
        for (DD4hep::XML::Collection_t xCompColl(xModulePropertiesComp, _U(component)); nullptr != xCompColl; ++xCompColl) {
            Component xComp = static_cast<Component>(xCompColl);
            Volume componentVolume("component",
                                   DD4hep::Geometry::Trapezoid(0.5 * xModuleProperties.attr<double>("modWidthMin"),
                                           0.5 * xModuleProperties.attr<double>("modWidthMax"),
                                           0.5 * xComp.thickness(),
                                           0.5 * xComp.thickness(),
                                           0.5 * xSensorProperties.attr<double>("sensorLength")),
                                   lcdd.material(xComp.materialStr()));
            PlacedVolume placedComponentVolume = moduleVolume.placeVolume(
                    componentVolume,
                    DD4hep::Geometry::Position(
                        0, integratedCompThickness - 0.5 * xModuleProperties.attr<double>("modThickness"), 0));
            placedComponentVolume.addPhysVolID("component", componentCounter);

            componentVolume.setSensitiveDetector(sensDet);
            integratedCompThickness += xComp.thickness();
            ++componentCounter;
        }
        unsigned int nPhi = xRing.attr<int>("nModules");
        double lX, lY, lZ;
        double phi = 0;
        double phiTilt, thetaTilt;
        for (unsigned int phiIndex = 0; phiIndex < nPhi; ++phiIndex) {
            if (0 == phiIndex % 2) {
                // the rotation for the odd module is already taken care
                // of by the position in tklayout xml
                phi = 2 * dd4hep::pi * static_cast<double>(phiIndex) / static_cast<double>(nPhi);
                lX = xModuleEven.X();
                lY = xModuleEven.Y();
                lZ = xModuleEven.Z() - dimensions.zmin() - discThickness * 0.5;
                phiTilt = xModuleEven.attr<double>("phiTilt");
                thetaTilt = xModuleEven.attr<double>("thetaTilt");
            } else {
                lX = xModuleOdd.X();
                lY = xModuleOdd.Y();
                lZ = xModuleOdd.Z() - dimensions.zmin() - discThickness * 0.5;
                phiTilt = xModuleOdd.attr<double>("phiTilt");
                thetaTilt = xModuleOdd.attr<double>("thetaTilt");
            }
            // position module in the x-y plane, smaller end inward
            // and incorporate phi tilt if any
            DD4hep::Geometry::RotationY lRotation1(M_PI * 0.5);
            DD4hep::Geometry::RotationX lRotation2(M_PI * 0.5 + phiTilt);
            // align radially
            DD4hep::Geometry::RotationZ lRotation3(atan(lY / lX));
            // theta tilt, if any -- note the different convention between
            // tklayout and here, thus the subtraction of pi / 2
            DD4hep::Geometry::RotationY lRotation4(thetaTilt - M_PI * 0.5);
            DD4hep::Geometry::RotationZ lRotation_PhiPos(phi);
            // position in  disk
            DD4hep::Geometry::Translation3D lTranslation(lX, lY, lZ);
            DD4hep::Geometry::Transform3D myTrafo(lRotation4 * lRotation3 * lRotation2 * lRotation1, lTranslation);
            PlacedVolume placedModuleVolume = discVolume.placeVolume(moduleVolume, lRotation_PhiPos * myTrafo);
            placedModuleVolume.addPhysVolID("module", moduleCounter);
            ++moduleCounter;
        }
    }

    unsigned int discCounter = 0;
    double currentZ;
    for (DD4hep::XML::Collection_t xDiscColl(xDiscs, "discZPls"); nullptr != xDiscColl; ++xDiscColl) {
        Component xDisc = static_cast<Component>(xDiscColl);
        currentZ = xDisc.z() - dimensions.zmin() - 0.5 * (dimensions.zmax() - dimensions.zmin());
        PlacedVolume placedDiscVolume = envelopeVolume.placeVolume(discVolume, DD4hep::Geometry::Position(0, 0, currentZ));
        placedDiscVolume.addPhysVolID("disc", discCounter);
        ++discCounter;
    }

    // top of the hierarchy
    Volume motherVol = lcdd.pickMotherVolume(GenericTrackerEndcapWorld);
    PlacedVolume placedEnvelopeVolume = motherVol.placeVolume(posnegEnvelopeVolume);
    placedEnvelopeVolume.addPhysVolID("system", xmlDet.id());

    // place everything twice -- forward / backward
    DD4hep::Geometry::Translation3D lTranslation_posEnvelope(
        0, 0, -dimensions.zmin() - 0.5 * (dimensions.zmax() - dimensions.zmin()));
    PlacedVolume placedGenericTrackerEndcap_pos = posnegEnvelopeVolume.placeVolume(
                envelopeVolume,
                DD4hep::Geometry::Position(0, 0, dimensions.zmin() + 0.5 * (dimensions.zmax() - dimensions.zmin())));
    PlacedVolume placedGenericTrackerEndcap_neg = posnegEnvelopeVolume.placeVolume(
                envelopeVolume, lTranslation_posEnvelope * DD4hep::Geometry::RotationX(dd4hep::pi));
    placedGenericTrackerEndcap_pos.addPhysVolID("posneg", 0);
    placedGenericTrackerEndcap_neg.addPhysVolID("posneg", 1);
    GenericTrackerEndcapWorld.setPlacement(placedEnvelopeVolume);
    return GenericTrackerEndcapWorld;
}
示例#18
0
/**
Factory for a configurable, generic tracker endcap.
@author: Valentin Volkl
*/
static DD4hep::Geometry::Ref_t createGenericTrackerEndcap(DD4hep::Geometry::LCDD& lcdd,
                                                          DD4hep::XML::Handle_t xmlElement,
                                                          DD4hep::Geometry::SensitiveDetector sensDet) {
  // shorthands
  DD4hep::XML::DetElement xmlDet = static_cast<DD4hep::XML::DetElement>(xmlElement);
  Dimension dimensions(xmlDet.dimensions());

  // get sensitive detector type from xml
  DD4hep::XML::Dimension sdTyp = xmlElement.child("sensitive");  // retrieve the type
  if (xmlDet.isSensitive()) {
    sensDet.setType(sdTyp.typeStr());  // set for the whole detector
  }

  // definition of top volume
  std::string detName = xmlDet.nameStr();
  DetElement GenericTrackerEndcapWorld(detName, xmlDet.id());

  // envelope volume with the max dimensions of tracker for visualization etc.
  // contains both endcaps, in forward and in backwards direction
  // the part between -z1 and z1 is subtracted from the envelope
  DD4hep::Geometry::Tube posnegEnvelopeShape_add(dimensions.rmin(), dimensions.rmax(), (dimensions.z2()));
  // make the negative shape slighly larger in the radial direction 
  // to be sure that everything is subtracted between -z1 and z1
  DD4hep::Geometry::Box posnegEnvelopeShape_subtract(
      dimensions.rmax() * 1.001, dimensions.rmax() * 1.001, dimensions.z1());
  DD4hep::Geometry::SubtractionSolid posnegEnvelopeShape(posnegEnvelopeShape_add, posnegEnvelopeShape_subtract);
  Volume posnegEnvelopeVolume(detName, posnegEnvelopeShape, lcdd.air());
  posnegEnvelopeVolume.setVisAttributes(lcdd.invisible());

  // envelope volume for one of the endcaps, either forward or backward
  DD4hep::Geometry::Tube envelopeShape(dimensions.rmin(), dimensions.rmax(), 0.5 * (dimensions.z2() - dimensions.z1()));
  Volume envelopeVolume(detName, envelopeShape, lcdd.air());
  envelopeVolume.setVisAttributes(lcdd.invisible());

  // loop over 'layer' nodes in xml
  unsigned int layerCounter = 0;
  for (DD4hep::XML::Collection_t xLayerColl(xmlElement, _U(layers)); nullptr != xLayerColl; ++xLayerColl) {
    DD4hep::XML::Component xLayer = static_cast<DD4hep::XML::Component>(xLayerColl);


    // create petals
    unsigned int nPhi = static_cast<unsigned int>(getAttrValueWithFallback(xLayer, "nPhi", 16));

    const double lModuleTwistAngle = getAttrValueWithFallback(xLayer, "module_twist_angle", 0.05 * M_PI);
    double dr = xLayer.rmax() - xLayer.rmin();
    double dphi = 2 * dd4hep::pi / static_cast<double>(nPhi);
    double tn = tan(dphi);
    Volume petalVolume(
        "petal",
        DD4hep::Geometry::Trapezoid(
            0.5 * xLayer.rmin() * tn, 0.5 * xLayer.rmax() * tn, xLayer.thickness(), xLayer.thickness(), 0.5 * dr),
        lcdd.material("Silicon"));
    petalVolume.setVisAttributes(lcdd, xLayer.visStr());
    petalVolume.setSensitiveDetector(sensDet);

    // handle repeat attribute in xml
    double layerThickness;
    unsigned int numLayers;
    double current_z;
    // "repeat" layers  equidistant between rmin and rmax
    numLayers = xLayer.repeat();
    layerThickness = (xLayer.z2() - xLayer.z1()) / numLayers;
    // create layers.
    for (unsigned int repeatIndex = 0; repeatIndex < numLayers; ++repeatIndex) {
      DD4hep::Geometry::Tube layerShape(xLayer.rmin(), xLayer.rmax(), 0.5 * layerThickness);
      Volume layerVolume("layer" + std::to_string(layerCounter), layerShape, lcdd.air());
      layerVolume.setVisAttributes(lcdd.invisible());
      ++layerCounter;
      // place layers not at center, but at z1 value of containing envelope
      // subtract half of the envelope length
      current_z = (repeatIndex + 0.5) * layerThickness + xLayer.z1() - dimensions.z1();
      PlacedVolume placedLayerVolume = envelopeVolume.placeVolume(
          layerVolume, DD4hep::Geometry::Position(0, 0, current_z - 0.5 * (dimensions.z2() - dimensions.z1())));
      placedLayerVolume.addPhysVolID("layer", layerCounter);

      double phi;
      double r = xLayer.rmin();
      for (unsigned int phiIndex = 0; phiIndex < nPhi; ++phiIndex) {
        phi = 2 * dd4hep::pi * static_cast<double>(phiIndex) / static_cast<double>(nPhi);
        // oriented along z at first
        DD4hep::Geometry::Translation3D lTranslation_ringPhiPos(0, 0, r + 0.5 * dr);
        DD4hep::Geometry::RotationY lRotation_ringPhiPos(phi);
        DD4hep::Geometry::RotationX lRotation_orientRing(0.5 * dd4hep::pi);
        // twist petals slightly so they can overlap
        DD4hep::Geometry::RotationZ lRotation_twist(lModuleTwistAngle);
        PlacedVolume placedPetalVolume = layerVolume.placeVolume(
            petalVolume, lRotation_orientRing * lRotation_ringPhiPos * lTranslation_ringPhiPos * lRotation_twist);
        placedPetalVolume.addPhysVolID("petal", phiIndex);
      }
    }
  }

  // top of the hierarchy
  Volume motherVol = lcdd.pickMotherVolume(GenericTrackerEndcapWorld);
  PlacedVolume placedEnvelopeVolume = motherVol.placeVolume(posnegEnvelopeVolume);
  placedEnvelopeVolume.addPhysVolID("system", xmlDet.id());

  // place everything twice -- forward / backward
  DD4hep::Geometry::Translation3D lTranslation_posEnvelope(
      0, 0, -dimensions.z1() - 0.5 * (dimensions.z2() - dimensions.z1()));
  PlacedVolume placedGenericTrackerEndcap_pos = posnegEnvelopeVolume.placeVolume(
      envelopeVolume, DD4hep::Geometry::Position(0, 0, dimensions.z1() + 0.5 * (dimensions.z2() - dimensions.z1())));
  PlacedVolume placedGenericTrackerEndcap_neg = posnegEnvelopeVolume.placeVolume(
      envelopeVolume, lTranslation_posEnvelope * DD4hep::Geometry::RotationX(dd4hep::pi));
  placedGenericTrackerEndcap_pos.addPhysVolID("posneg", 0);
  placedGenericTrackerEndcap_neg.addPhysVolID("posneg", 1);
  GenericTrackerEndcapWorld.setPlacement(placedEnvelopeVolume);
  return GenericTrackerEndcapWorld;
}
static Ref_t create_element(Detector& theDetector, xml_h element, SensitiveDetector sens)  {
  
  xml_det_t    x_det = element;
  std::string  name  = x_det.nameStr();
  
  DetElement sdet( name, x_det.id()  ) ;
  
  PlacedVolume pv;
  

  // --- create an envelope volume and position it into the world ---------------------
  
  Volume envelope = dd4hep::xml::createPlacedEnvelope( theDetector,  element , sdet ) ;
  
  if( theDetector.buildType() == BUILD_ENVELOPE ) return sdet ;
  
  //-----------------------------------------------------------------------------------
  
  // ----- read xml ----------------------

  xml_dim_t dim = x_det.dimensions();

  double inner_r    =  dim.rmin() ;
  double outer_r    =  dim.rmax() ;
  double z0          = dim.z0() ;
  double z1          = dim.z1() ;
  //  double phi0       =  dim.phi0() ;

  unsigned nsides   =  dim.nsides();
  
  double thick      =  z1 -  z0 ;
  double zpos       =  z0 + thick/2. ;


  Material mat      = envelope.material() ;      
  //--------------------------------------

  sens.setType("tracker");

  // base vectors for surfaces:
  Vector3D u(0,1,0) ;
  Vector3D v(1,0,0) ;
  Vector3D n(0,0,1) ;
  
  
  PolyhedraRegular phSolid ( nsides, inner_r, outer_r , 0.5*thick ) ;

  //==============================================================================

  DetElement fwdDE( sdet, name + std::string( "_fwd" )  , x_det.id() );

  Volume phVol( name + std::string("_vol") , phSolid ,  mat ) ;
    
  phVol.setSensitiveDetector(sens);
  
  //fixme: the drawing of endcap surfaces in a polyhedral shape does not work right now 
  //       -> set surface to be invisible for now
  VolPlane surf( phVol,SurfaceType(SurfaceType::Sensitive, 
                                   SurfaceType::Invisible), 
                 thick/4., thick/4., u,v,n ) ;
  
  volSurfaceList( fwdDE  )->push_back(  surf ) ;

  pv = envelope.placeVolume( phVol , Position( 0., 0., zpos ) ) ;

  pv.addPhysVolID("layer", 0 ).addPhysVolID( "side" , +1 )  ;
    
  fwdDE.setPlacement( pv ) ;

  //==============================================================================

  DetElement bwdDE( sdet, name + std::string( "_bwd" )  , x_det.id() );
  
  //  Volume phVol( name + std::string("_bwd") , phSolid ,  mat ) ;
  
  phVol.setSensitiveDetector(sens);
  
  
  volSurfaceList( bwdDE  )->push_back(  surf ) ;

  pv = envelope.placeVolume( phVol , Position( 0., 0., -zpos ) ) ;

  pv.addPhysVolID("layer", 0 ).addPhysVolID( "side" , -1 )  ;
    
  bwdDE.setPlacement( pv ) ;
  
  //--------------------------------------
  
  return sdet ;
}
示例#20
0
static DD4hep::Geometry::Ref_t createHCal (
  DD4hep::Geometry::LCDD& lcdd,
  xml_h xmlElement,
  DD4hep::Geometry::SensitiveDetector sensDet
  ) {
  // Get the Gaudi message service and message stream:
  ServiceHandle<IMessageSvc> msgSvc("MessageSvc", "HCalConstruction");
  MsgStream lLog(&(*msgSvc), "HCalConstruction");

  xml_det_t xmlDet = xmlElement;
  std::string detName = xmlDet.nameStr();
  //Make DetElement
  DetElement hCal(detName, xmlDet.id());
  // Get status for the RecoGeometry what is status?
  // xml_comp_t xmlStatus = xmlDet.child(_U(status));
  // int status = xmlStatus.id();
  // add Extension to Detlement for the RecoGeometry
  // Let's skip this for now...
  // Det::DetCylinderVolume* detVolume = new Det::DetCylinderVolume(status);
  // hCal.addExtension<Det::IDetExtension>(detVolume);

  // Make volume that envelopes the whole barrel; set material to air
  Dimension dimensions(xmlDet.dimensions());
  DD4hep::Geometry::Tube envelopeShape(dimensions.rmin(), dimensions.rmax(), dimensions.dz());
  Volume envelopeVolume(detName, envelopeShape, lcdd.air());
  // Invisibility seems to be broken in visualisation tags, have to hardcode that
  // envelopeVolume.setVisAttributes(lcdd, dimensions.visStr());
  envelopeVolume.setVisAttributes(lcdd.invisible());

  // set the sensitive detector type to the DD4hep calorimeter
  sensDet.setType("SimpleCalorimeterSD");

  // Add structural support made of steel inside of HCal
  xml_comp_t xFacePlate = xmlElement.child("face_plate");
  double dRhoFacePlate = xFacePlate.thickness();
  double sensitiveBarrelRmin = dimensions.rmin() + dRhoFacePlate;
  DetElement facePlate("facePlate", 0);
  DD4hep::Geometry::Tube facePlateShape(dimensions.rmin(), sensitiveBarrelRmin, dimensions.dz());
  Volume facePlateVol("facePlate", facePlateShape, lcdd.material(xFacePlate.materialStr()));
  facePlateVol.setVisAttributes(lcdd, xFacePlate.visStr());
  PlacedVolume placedFacePlate = envelopeVolume.placeVolume(facePlateVol);
  placedFacePlate.addPhysVolID("facePlate", facePlate.id());
  facePlate.setPlacement(placedFacePlate);


  // Add structural support made of steel at both ends of HCal
  xml_comp_t xEndPlate = xmlElement.child("end_plate");
  double dZEndPlate = xEndPlate.thickness();

  DD4hep::Geometry::Tube endPlateShape(dimensions.rmin(), dimensions.rmax(), dZEndPlate);
  Volume endPlateVol("endPlate", endPlateShape, lcdd.material(xEndPlate.materialStr()));
  endPlateVol.setVisAttributes(lcdd, xEndPlate.visStr());

  DetElement endPlatePos("endPlate", 0);
  DD4hep::Geometry::Position posOffset(0, 0, dimensions.dz() -  dZEndPlate);
  PlacedVolume placedEndPlatePos = envelopeVolume.placeVolume(endPlateVol, posOffset);
  placedEndPlatePos.addPhysVolID("endPlatePos", endPlatePos.id());
  endPlatePos.setPlacement(placedEndPlatePos);

  DetElement endPlateNeg("endPlate", 1);
  DD4hep::Geometry::Position negOffset(0, 0, -dimensions.dz() +  dZEndPlate);
  PlacedVolume placedEndPlateNeg = envelopeVolume.placeVolume(endPlateVol, negOffset);
  placedEndPlateNeg.addPhysVolID("endPlateNeg", endPlateNeg.id());
  endPlateNeg.setPlacement(placedEndPlateNeg);


  // Hard-coded assumption that we have two different sequences for the modules
  std::vector<xml_comp_t> sequences = {xmlElement.child("sequence_a"), xmlElement.child("sequence_b")};
  // NOTE: This assumes that both have the same dimensions!
  Dimension moduleDimensions(sequences[0].dimensions());
  double dzModule = moduleDimensions.dz();

  // calculate the number of modules fitting in phi, Z and Rho
  unsigned int numModulesPhi = moduleDimensions.phiBins();
  unsigned int numModulesZ = static_cast<unsigned>(dimensions.dz() / dzModule);
  unsigned int numModulesR = static_cast<unsigned>((dimensions.rmax() - sensitiveBarrelRmin) / moduleDimensions.dr());
  lLog << MSG::DEBUG << "constructing " << numModulesPhi << " modules per ring in phi, "
                     << numModulesZ << " rings in Z, "
                     << numModulesR << " rings (layers) in Rho"
                     << numModulesR*numModulesZ*numModulesPhi << " modules" << endmsg;

  // Calculate correction along z based on the module size (can only have natural number of modules)
  double dzDetector = numModulesZ * dzModule + dZEndPlate;
  lLog << MSG::INFO << "correction of dz:" << dimensions.dz() - dzDetector << endmsg;

  // calculate the dimensions of one module:
  double dphi = 2 * dd4hep::pi / static_cast<double>(numModulesPhi);
  double tn = tan(dphi / 2.);
  double spacing = moduleDimensions.x();
  double dy0 = moduleDimensions.dz();
  double dz0 = moduleDimensions.dr() / 2.;

  double drWedge = cos(dphi / 2.) * (dimensions.rmax() - sensitiveBarrelRmin) * 0.5;

  double dxWedge1 = tn * sensitiveBarrelRmin - spacing;
  double dxWedge2 = tn * cos(dphi / 2.) * dimensions.rmax() - spacing;

  // First we construct one wedge with width of one module:
  Volume subWedgeVolume("subWedge", DD4hep::Geometry::Trapezoid(
        dxWedge1, dxWedge2, dzModule, dzModule, drWedge
      ), lcdd.material("Air")
  );
  for (unsigned int idxLayer = 0; idxLayer < numModulesR; ++idxLayer) {
    auto layerName = std::string("wedge") + DD4hep::XML::_toString(idxLayer, "layer%d");
    unsigned int sequenceIdx = idxLayer % 2;
    double rminLayer = idxLayer * moduleDimensions.dr();
    double rmaxLayer = (idxLayer + 1) * cos(dphi / 2.) * moduleDimensions.dr();
    double dx1 = tn * (rminLayer + sensitiveBarrelRmin) - spacing;
    double dx2 = tn * cos(dphi / 2.) * (rmaxLayer + sensitiveBarrelRmin) - spacing;
    // -drWedge to place it in the middle of the wedge-volume
    double rMiddle = rminLayer + 0.5 * moduleDimensions.dr() - drWedge;
    Volume moduleVolume(layerName, DD4hep::Geometry::Trapezoid(
        dx1, dx2, dy0, dy0, dz0
      ), lcdd.material("Air")
    );
    moduleVolume.setVisAttributes(lcdd.invisible());
    unsigned int idxSubMod = 0;
    // DetElement moduleDet(wedgeDet, layerName, idxLayer);
    double modCompZOffset = -moduleDimensions.dz();
    for (xml_coll_t xCompColl(sequences[sequenceIdx], _U(module_component)); xCompColl; ++xCompColl, ++idxSubMod) {
      xml_comp_t xComp = xCompColl;
      std::string subModuleName = layerName+DD4hep::XML::_toString(idxSubMod, "module_component%d");
      double dyComp = xComp.thickness();
      Volume modCompVol(subModuleName, DD4hep::Geometry::Trapezoid(
          dx1, dx2, dyComp, dyComp, dz0
        ), lcdd.material(xComp.materialStr())
      );
      if (xComp.isSensitive()) {
        modCompVol.setSensitiveDetector(sensDet);
      }
      modCompVol.setVisAttributes(lcdd, xComp.visStr());
      // modCompVol.setVisAttributes(lcdd.invisible());
      // DetElement modCompDet(wedgeDet, subModuleName, idxSubMod);
      DD4hep::Geometry::Position offset(0, modCompZOffset + dyComp + xComp.y_offset()*2, 0);
      PlacedVolume placedModCompVol = moduleVolume.placeVolume(modCompVol, offset);
      placedModCompVol.addPhysVolID("sub_module", idxSubMod);
      // modCompDet.setPlacement(placedModCompVol);
      modCompZOffset += xComp.thickness()*2 + xComp.y_offset()*2;
    }
    DD4hep::Geometry::Position modOffset(0, 0, rMiddle);
    PlacedVolume placedModuleVol = subWedgeVolume.placeVolume(moduleVolume, modOffset);
    placedModuleVol.addPhysVolID("layer", idxLayer);
    // moduleDet.setPlacement(placedModuleVol);
  }

  // Now we place the components along z within the wedge
  Volume wedgeVolume("wedge", DD4hep::Geometry::Trapezoid(
        dxWedge1, dxWedge2, dzDetector, dzDetector, drWedge
      ), lcdd.material("Air")
  );
  wedgeVolume.setVisAttributes(lcdd.invisible());

  for (unsigned int idxZRow = 0; idxZRow < numModulesZ; ++idxZRow) {
    double zOffset = -dzDetector + dZEndPlate * 2 + (2*idxZRow + 1) * dzModule;
    auto wedgeRowName = DD4hep::XML::_toString(idxZRow, "row%d");
    DD4hep::Geometry::Position wedgeOffset(0, zOffset, 0);
    PlacedVolume placedRowVolume = wedgeVolume.placeVolume(subWedgeVolume, wedgeOffset);
    placedRowVolume.addPhysVolID("row", idxZRow);
    // wedgeDet.setPlacement(placedWedgeVol);
  }

  // Finally we place all the wedges around phi
  for (unsigned int idxPhi = 0; idxPhi < numModulesPhi; ++idxPhi) {
    auto modName = DD4hep::XML::_toString(idxPhi, "mod%d");
    // Volume and DetElement for one row in Z
    DetElement wedgeDet(hCal, modName, idxPhi);
    // moduleVolume.setVisAttributes(lcdd, sequences[sequenceIdx].visStr());
    // moduleVolume.setVisAttributes(lcdd.invisible());
    // calculate position and rotation of this wedge;
    // first rotation due to default rotation of trapezoid
    double phi = 0.5 * dphi - idxPhi * dphi; // 0.5*dphi for middle of module
    double yPosModule = (sensitiveBarrelRmin + drWedge) * cos(phi);
    double xPosModule = (sensitiveBarrelRmin + drWedge) * sin(phi);
    DD4hep::Geometry::Position moduleOffset(xPosModule, yPosModule, 0);
    DD4hep::Geometry::Transform3D trans(
      DD4hep::Geometry::RotationX(-0.5*dd4hep::pi)*
      DD4hep::Geometry::RotationY(phi),
      moduleOffset
    );
    PlacedVolume placedWedgeVol = envelopeVolume.placeVolume(wedgeVolume, trans);
    placedWedgeVol.addPhysVolID("wedge", idxPhi);
    wedgeDet.setPlacement(placedWedgeVol);
  }

  //Place envelope (or barrel) volume
  Volume motherVol = lcdd.pickMotherVolume(hCal);
  PlacedVolume placedHCal = motherVol.placeVolume(envelopeVolume);
  placedHCal.addPhysVolID("system", hCal.id());
  hCal.setPlacement(placedHCal);
  return hCal;

}
示例#21
0
static Ref_t create_detector(Detector& theDetector, xml_h element, SensitiveDetector sens)  {
  static double tolerance = 0e0;

  xml_det_t     x_det     = element;
  string        det_name  = x_det.nameStr();
  Layering      layering (element);

  Material      air       = theDetector.air();
  //unused: Material      vacuum    = theDetector.vacuum();

  int           det_id    = x_det.id();
  xml_comp_t    x_staves  = x_det.staves();
  DetElement    sdet      (det_name,det_id);

  xml_comp_t    x_dim     = x_det.dimensions();
  int           nsides    = x_dim.numsides();
  double        dphi      = (2*M_PI/nsides);
  double        hphi      = dphi/2;


 // --- create an envelope volume and position it into the world ---------------------

  Volume envelope = dd4hep::xml::createPlacedEnvelope( theDetector,  element , sdet ) ;

  dd4hep::xml::setDetectorTypeFlag( element, sdet ) ;
 
  if( theDetector.buildType() == BUILD_ENVELOPE ) return sdet ;

  //-----------------------------------------------------------------------------------


  sens.setType("calorimeter");

  Material stave_material  = theDetector.material(x_staves.materialStr());

  DetElement    stave_det("module0stave0",det_id);

  Readout readout = sens.readout();
  Segmentation seg = readout.segmentation();
  
  // check if we have a WaferGridXY segmentation :
  WaferGridXY* waferSeg = 
    dynamic_cast< WaferGridXY*>( seg.segmentation() ) ;

  std::vector<double> cellSizeVector = seg.segmentation()->cellDimensions(0); //Assume uniform cell sizes, provide dummy cellID
  double cell_sizeX      = cellSizeVector[0];
  double cell_sizeY      = cellSizeVector[1];

//====================================================================
//
// Read all the constant from ILD_o1_v05.xml
// Use them to build HcalBarrel
//
//====================================================================

  int N_FIBERS_W_STRUCTURE = 2; 
  int N_FIBERS_ALVOULUS = 3;

  //  read parametere from compact.xml file
  double Ecal_Alveolus_Air_Gap              = theDetector.constant<double>("Ecal_Alveolus_Air_Gap");
  double Ecal_Slab_shielding                = theDetector.constant<double>("Ecal_Slab_shielding");
  double Ecal_Slab_copper_thickness         = theDetector.constant<double>("Ecal_Slab_copper_thickness");
  double Ecal_Slab_PCB_thickness            = theDetector.constant<double>("Ecal_Slab_PCB_thickness");
  double Ecal_Slab_glue_gap                 = theDetector.constant<double>("Ecal_Slab_glue_gap");
  double Ecal_Slab_ground_thickness         = theDetector.constant<double>("Ecal_Slab_ground_thickness");
  double Ecal_fiber_thickness               = theDetector.constant<double>("Ecal_fiber_thickness");
  double Ecal_Si_thickness                  = theDetector.constant<double>("Ecal_Si_thickness");
  
  double Ecal_inner_radius                  = theDetector.constant<double>("TPC_outer_radius") +theDetector.constant<double>("Ecal_Tpc_gap");
  double Ecal_radiator_thickness1           = theDetector.constant<double>("Ecal_radiator_layers_set1_thickness");
  double Ecal_radiator_thickness2           = theDetector.constant<double>("Ecal_radiator_layers_set2_thickness");
  double Ecal_radiator_thickness3           = theDetector.constant<double>("Ecal_radiator_layers_set3_thickness");
  double Ecal_Barrel_halfZ                  = theDetector.constant<double>("Ecal_Barrel_halfZ");
  
  double Ecal_support_thickness             = theDetector.constant<double>("Ecal_support_thickness");
  double Ecal_front_face_thickness          = theDetector.constant<double>("Ecal_front_face_thickness");
  double Ecal_lateral_face_thickness        = theDetector.constant<double>("Ecal_lateral_face_thickness");
  double Ecal_Slab_H_fiber_thickness        = theDetector.constant<double>("Ecal_Slab_H_fiber_thickness");

  double Ecal_Slab_Sc_PCB_thickness         = theDetector.constant<double>("Ecal_Slab_Sc_PCB_thickness");
  double Ecal_Sc_thickness                  = theDetector.constant<double>("Ecal_Sc_thickness");
  double Ecal_Sc_reflector_thickness        = theDetector.constant<double>("Ecal_Sc_reflector_thickness");

  int    Ecal_nlayers1                      = theDetector.constant<int>("Ecal_nlayers1");
  int    Ecal_nlayers2                      = theDetector.constant<int>("Ecal_nlayers2");
  int    Ecal_nlayers3                      = theDetector.constant<int>("Ecal_nlayers3");
  int    Ecal_barrel_number_of_towers       = theDetector.constant<int>("Ecal_barrel_number_of_towers");
  
  //double      Ecal_cells_size                  = theDetector.constant<double>("Ecal_cells_size");
  double Ecal_guard_ring_size               = theDetector.constant<double>("Ecal_guard_ring_size");
  
//====================================================================
//
// general calculated parameters
//
//====================================================================
  
  double Ecal_total_SiSlab_thickness = 
    Ecal_Slab_shielding + 
    Ecal_Slab_copper_thickness + 
    Ecal_Slab_PCB_thickness +
    Ecal_Slab_glue_gap + 
    Ecal_Si_thickness + 
    Ecal_Slab_ground_thickness +
    Ecal_Alveolus_Air_Gap / 2;
#ifdef VERBOSE
  std::cout << " Ecal_total_SiSlab_thickness = " << Ecal_total_SiSlab_thickness  << std::endl;
#endif
  
  

  double Ecal_total_ScSlab_thickness = 
    Ecal_Slab_shielding + 
    Ecal_Slab_copper_thickness + 
    Ecal_Slab_Sc_PCB_thickness +
    Ecal_Sc_thickness + 
    Ecal_Sc_reflector_thickness * 2 +
    Ecal_Alveolus_Air_Gap / 2;
#ifdef VERBOSE
  std::cout << " Ecal_total_ScSlab_thickness = " << Ecal_total_ScSlab_thickness  << std::endl;
#endif
  

    int Number_of_Si_Layers_in_Barrel = 0;
    int Number_of_Sc_Layers_in_Barrel = 0;


#ifdef VERBOSE
  std::cout << " Ecal total number of Silicon layers = " << Number_of_Si_Layers_in_Barrel  << std::endl;
  std::cout << " Ecal total number of Scintillator layers = " << Number_of_Sc_Layers_in_Barrel  << std::endl;
#endif
  
  // In this release the number of modules is fixed to 5
  double Ecal_Barrel_module_dim_z = 2 * Ecal_Barrel_halfZ / 5. ;
#ifdef VERBOSE
  std::cout << "Ecal_Barrel_module_dim_z  = " << Ecal_Barrel_module_dim_z  << std::endl;
#endif

  // The alveolus size takes in account the module Z size
  // but also 4 fiber layers for the alveoulus wall, the all
  // divided by the number of towers
  double alveolus_dim_z = 
    (Ecal_Barrel_module_dim_z - 2. * Ecal_lateral_face_thickness) /
    Ecal_barrel_number_of_towers - 
    2 * N_FIBERS_ALVOULUS  * Ecal_fiber_thickness  - 
    2 * Ecal_Slab_H_fiber_thickness -
    2 * Ecal_Slab_shielding;


#ifdef VERBOSE
  std::cout << "alveolus_dim_z = " <<  alveolus_dim_z << std::endl;
#endif

  int n_total_layers = Ecal_nlayers1 + Ecal_nlayers2 + Ecal_nlayers3;
  Number_of_Si_Layers_in_Barrel = n_total_layers+1;

  double module_thickness = 
    Ecal_nlayers1 * Ecal_radiator_thickness1 +
    Ecal_nlayers2 * Ecal_radiator_thickness2 +
    Ecal_nlayers3 * Ecal_radiator_thickness3 +
    
    int(n_total_layers/2) * // fiber around W struct layers
    (N_FIBERS_W_STRUCTURE * 2 *  Ecal_fiber_thickness) +
    
    Number_of_Si_Layers_in_Barrel * // Silicon slabs plus fiber around and inside
    (Ecal_total_SiSlab_thickness +
     (N_FIBERS_ALVOULUS + 1 ) * Ecal_fiber_thickness) +
    
    Number_of_Sc_Layers_in_Barrel * // Scintillator slabs plus fiber around and inside
    (Ecal_total_ScSlab_thickness +
     (N_FIBERS_ALVOULUS + 1 ) * Ecal_fiber_thickness) +
    
    Ecal_support_thickness + Ecal_front_face_thickness;
  
#ifdef VERBOSE
  std::cout << "For information : module_thickness = " << module_thickness  << std::endl;
#endif
  
  // module barrel key parameters
  double  bottom_dim_x = 2. * tan(M_PI/8.) * Ecal_inner_radius +
    module_thickness/sin(M_PI/4.);
  
  double top_dim_x = bottom_dim_x - 2 * module_thickness;

  //------------------------------------------------------------------------------------

  LayeredCalorimeterData::Layer caloLayer ;
  caloLayer.cellSize0 = cell_sizeX;
  caloLayer.cellSize1 = cell_sizeY;

  //== For Wafer ===  
  double cell_dim_x = caloLayer.cellSize0;
  double total_Si_dim_z = alveolus_dim_z;

  double util_SI_wafer_dim_z = 
    total_Si_dim_z/2 -  2 * Ecal_guard_ring_size;

  double cell_dim_z =  util_SI_wafer_dim_z/ 
    floor(util_SI_wafer_dim_z/
	  cell_dim_x);

  int N_cells_in_Z = int(util_SI_wafer_dim_z/cell_dim_z);
  int N_cells_in_X = N_cells_in_Z;
  
  cell_dim_x = cell_dim_z;


  
#ifdef VERBOSE
  std::cout << " bottom_dim_x = " << bottom_dim_x  << std::endl;
  std::cout << " top_dim_x = " << top_dim_x << std::endl;
  std::cout << " Ecal total number of Silicon layers = " << Number_of_Si_Layers_in_Barrel  << std::endl;
  std::cout << " Ecal total number of Scintillator layers = " << Number_of_Sc_Layers_in_Barrel  << std::endl;
#endif
  


// ========= Create Ecal Barrel stave   ====================================
//  It will be the volume for palcing the Ecal Barrel alveolus(i.e. Layers).
//  And the structure W plate.
//  Itself will be placed into the world volume.
// ==========================================================================

  // The TOP_X and BOTTOM_X is different in Mokka and DD4hep
  Trapezoid trd(top_dim_x / 2,
		bottom_dim_x / 2, 
		Ecal_Barrel_module_dim_z / 2,
		Ecal_Barrel_module_dim_z / 2,
		module_thickness/2);

  //  Volume mod_vol(det_name+"_module",trd,theDetector.material("g10"));
  Volume mod_vol(det_name+"_module",trd,theDetector.material("CarbonFiber")); // DJeans 5-sep-2016

  // We count the layers starting from IP and from 1,
  // so odd layers should be inside slabs and
  // even ones on the structure.
  // The structure W layers are here big plans, as the 
  // gap between each W plate is too small to create problems 
  // The even W layers are part of H structure placed inside
  // the alveolus.

  // ############################
  //  Dimension of radiator wLog
  //  slice provide the thickness
  // ############################


  double y_floor = 
    Ecal_front_face_thickness +
    N_FIBERS_ALVOULUS * Ecal_fiber_thickness;


  // ############################
  //  Dimension of alveolus
  //  slice provide the thickness
  // ############################
  
    // =====  build Si Slab and put into the Layer volume =====
    // =====  place the layer into the module 5 time for one full layer into the trd module ====
    // =====  build and place barrel structure into trd module ====
    // Parameters for computing the layer X dimension:
    double stave_z  =(Ecal_Barrel_module_dim_z - 2. * Ecal_lateral_face_thickness) / Ecal_barrel_number_of_towers/2.;
    double l_dim_x  = bottom_dim_x/2.;                            // Starting X dimension for the layer.
    double l_pos_z  = module_thickness/2;

    l_dim_x -= y_floor;
    l_pos_z -= y_floor;


    // ------------- create extension objects for reconstruction -----------------
    
    //========== fill data for reconstruction ============================
    LayeredCalorimeterData* caloData = new LayeredCalorimeterData ;
    caloData->layoutType = LayeredCalorimeterData::BarrelLayout ;
    caloData->inner_symmetry = nsides  ;
    //added by Thorben Quast
    caloData->outer_symmetry = nsides  ;
    caloData->phi0 = 0 ; // hardcoded 
    
    /// extent of the calorimeter in the r-z-plane [ rmin, rmax, zmin, zmax ] in mm.
    caloData->extent[0] = Ecal_inner_radius ;
    //line fixed by Thorben Quast since actual conversion is made during the drawing
    caloData->extent[1] = ( Ecal_inner_radius + module_thickness );
    //caloData->extent[1] = ( Ecal_inner_radius + module_thickness ) / cos( M_PI/8. ) ;
    caloData->extent[2] = 0. ;
    caloData->extent[3] = Ecal_Barrel_halfZ ;

    // // base vectors for surfaces:
    // dd4hep::rec::Vector3D u(1,0,0) ;
    // dd4hep::rec::Vector3D v(0,1,0) ;
    // dd4hep::rec::Vector3D n(0,0,1) ;


    //-------------------- start loop over ECAL layers ----------------------
    // Loop over the sets of layer elements in the detector.

    double nRadiationLengths   = 0. ;
    double nInteractionLengths = 0. ;
    double thickness_sum       = 0. ;

    nRadiationLengths   = Ecal_radiator_thickness1/(stave_material.radLength())
      + y_floor/air.radLength();
    nInteractionLengths = Ecal_radiator_thickness1/(stave_material.intLength())
      + y_floor/air.intLength();
    thickness_sum       = Ecal_radiator_thickness1 + y_floor;

    int l_num = 1;
    bool isFirstSens = true;
    int myLayerNum = 0 ;

    for(xml_coll_t li(x_det,_U(layer)); li; ++li)  {
      xml_comp_t x_layer = li;
      int repeat = x_layer.repeat();
      // Loop over number of repeats for this layer.
      for (int j=0; j<repeat; j++)    {
	string l_name = _toString(l_num,"layer%d");
	double l_thickness = layering.layer(l_num-1)->thickness();  // Layer's thickness.
	double xcut = (l_thickness);                     // X dimension for this layer.
	l_dim_x -= xcut;


	Box        l_box(l_dim_x-tolerance,stave_z-tolerance,l_thickness/2.0-tolerance);
	Volume     l_vol(det_name+"_"+l_name,l_box,air);

	l_vol.setVisAttributes(theDetector.visAttributes(x_layer.visStr()));

	//fg: need vector of DetElements for towers ! 
	//    DetElement layer(stave_det, l_name, det_id);
	std::vector< DetElement > layers( Ecal_barrel_number_of_towers )  ;
	
	// place layer 5 times in module. at same layer position (towers !)
	double l_pos_y = Ecal_Barrel_module_dim_z / 2. 
	  - ( Ecal_lateral_face_thickness +
	      Ecal_fiber_thickness * N_FIBERS_ALVOULUS +
	      Ecal_Slab_shielding + 
	      Ecal_Slab_H_fiber_thickness +
	      alveolus_dim_z /2.);						  
       	for (int i=0; i<Ecal_barrel_number_of_towers; i++){ // need four clone

	  layers[i] = DetElement( stave_det, l_name+_toString(i,"tower%02d") , det_id ) ;

	  Position   l_pos(0,l_pos_y,l_pos_z-l_thickness/2.);      // Position of the layer.
	  PlacedVolume layer_phv = mod_vol.placeVolume(l_vol,l_pos);
	  // layer_phv.addPhysVolID("layer", l_num);
	  layer_phv.addPhysVolID("tower", i);

	  layers[i].setPlacement(layer_phv);
	  l_pos_y -= (alveolus_dim_z + 
		      2. * Ecal_fiber_thickness * N_FIBERS_ALVOULUS +
		      2. * Ecal_Slab_H_fiber_thickness +
		      2. * Ecal_Slab_shielding);
	}




	// Loop over the sublayers or slices for this layer.
	int s_num = 1;
	double s_pos_z = l_thickness / 2.;


	//--------------------------------------------------------------------------------
	// BuildBarrelAlveolus: BuildSiliconSlab:
	//--------------------------------------------------------------------------------
	double radiator_dim_y = Ecal_radiator_thickness1; //to be updated with slice radiator thickness 

	for(xml_coll_t si(x_layer,_U(slice)); si; ++si)  {
	  xml_comp_t x_slice = si;
	  string     s_name  =  _toString(s_num,"slice%d");
	  double     s_thick = x_slice.thickness();
	  Material slice_material  = theDetector.material(x_slice.materialStr());
#ifdef VERBOSE
	  std::cout<<"Ecal_barrel_number_of_towers: "<< Ecal_barrel_number_of_towers <<std::endl;
#endif
	  double slab_dim_x = l_dim_x-tolerance;
	  double slab_dim_y = s_thick/2.;
	  double slab_dim_z = stave_z-tolerance;

	  Box        s_box(slab_dim_x,slab_dim_z,slab_dim_y);
	  Volume     s_vol(det_name+"_"+l_name+"_"+s_name,s_box,slice_material);
	  //fg: not needed          DetElement slice(layer,s_name,det_id);

	  s_vol.setVisAttributes(theDetector.visAttributes(x_slice.visStr()));
#ifdef VERBOSE
	  std::cout<<"x_slice.materialStr(): "<< x_slice.materialStr() <<std::endl;
#endif
	  if (x_slice.materialStr().compare(x_staves.materialStr()) == 0){
	    radiator_dim_y = s_thick;
	  // W StructureLayer has the same thickness as W radiator layer in the Alveolus layer
	    
#if DD4HEP_VERSION_GE( 0, 15 )
	    caloLayer.outer_nRadiationLengths   = nRadiationLengths;
	    caloLayer.outer_nInteractionLengths = nInteractionLengths;
	    caloLayer.outer_thickness           = thickness_sum;

	    if (!isFirstSens){ caloData->layers.push_back( caloLayer ) ;
#ifdef VERBOSE
	    std::cout<<" caloLayer.distance: "<< caloLayer.distance <<std::endl;

	    std::cout<<" caloLayer.inner_nRadiationLengths: "<< caloLayer.inner_nRadiationLengths <<std::endl;
	    std::cout<<" caloLayer.inner_nInteractionLengths: "<< caloLayer.inner_nInteractionLengths <<std::endl;
	    std::cout<<" caloLayer.inner_thickness: "<< caloLayer.inner_thickness <<std::endl;
	    std::cout<<" caloLayer.sensitive_thickness: "<< caloLayer.sensitive_thickness <<std::endl;

	    std::cout<<" caloLayer.outer_nRadiationLengths: "<< caloLayer.outer_nRadiationLengths <<std::endl;
	    std::cout<<" caloLayer.outer_nInteractionLengths: "<< caloLayer.outer_nInteractionLengths <<std::endl;
	    std::cout<<" caloLayer.outer_thickness: "<< caloLayer.outer_thickness <<std::endl;

	    std::cout<<" EcalBarrel[1]==>caloLayer.inner_thickness + caloLayer.outer_thickness: "
		     << caloLayer.inner_thickness + caloLayer.outer_thickness <<std::endl;
#endif
	    }
#endif
	    // Init for inner
	    nRadiationLengths   = 0. ;
	    nInteractionLengths = 0. ;
	    thickness_sum       = 0. ;	    
	    isFirstSens         = false;

	  }
	  nRadiationLengths   += s_thick/(2.*slice_material.radLength());
	  nInteractionLengths += s_thick/(2.*slice_material.intLength());
	  thickness_sum       += s_thick/2.;

          if ( x_slice.isSensitive() ) {
	    //s_vol.setSensitiveDetector(sens);

	    // Normal squared wafers
	    double wafer_dim_x = 
	      N_cells_in_X * cell_dim_x;
	    double wafer_dim_z = 
	      N_cells_in_Z * cell_dim_z;
	    Box WaferSiSolid( wafer_dim_x/2,wafer_dim_z/2,slab_dim_y);
	    //Volume WaferSiLog(det_name+"_"+l_name+"_"+s_name+"Wafer",WaferSiSolid,slice_material);
	    //WaferSiLog.setSensitiveDetector(sens);

	    double real_wafer_size_x =
	      wafer_dim_x + 2 * Ecal_guard_ring_size;
      
	    int n_wafers_x =
	      int(floor(slab_dim_x*2 / real_wafer_size_x));
      
	    double wafer_pos_x =
	      -slab_dim_x + 
	      Ecal_guard_ring_size +
	      wafer_dim_x /2 ;
	    int n_wafer_x;
	    int wafer_num = 0;
	    for (n_wafer_x = 1;
		 n_wafer_x < n_wafers_x + 1;
		 n_wafer_x++)
	      {
		double wafer_pos_z =
		  -alveolus_dim_z/2.0 + 
		  Ecal_guard_ring_size +
		  wafer_dim_z /2;
		for (int n_wafer_z = 1;
		     n_wafer_z < 3;
		     n_wafer_z++)
		  {
		    wafer_num++;
		    string Wafer_name  =  _toString(wafer_num,"wafer%d");
		    Volume WaferSiLog(det_name+"_"+l_name+"_"+s_name+"_"+Wafer_name,WaferSiSolid,slice_material);
		    WaferSiLog.setSensitiveDetector(sens);
		    //WaferSiLog.setVisAttributes(theDetector.visAttributes(x_slice.visStr()));
		    PlacedVolume wafer_phv = s_vol.placeVolume(WaferSiLog,Position(wafer_pos_x,
							  wafer_pos_z,
							  0));
		    wafer_phv.addPhysVolID("wafer", wafer_num);

		    // Normal squared wafers, this waferOffsetX is 0.0 
		    waferSeg->setWaferOffsetX(myLayerNum, wafer_num, 0.0);

		    wafer_pos_z +=
		      wafer_dim_z +
		      2 * Ecal_guard_ring_size;
		  }
		wafer_pos_x += 
		  wafer_dim_x +
		  2 * Ecal_guard_ring_size;
	      }

	    // Magic wafers to complete the slab...
	    // (wafers with variable number of cells just
	    // to complete the slab. in reality we think that
	    // we'll have just a few models of special wafers
	    // for that.
	    double resting_dim_x =
	      slab_dim_x*2 - 
	      (wafer_dim_x + 2 * Ecal_guard_ring_size) * 
	      n_wafers_x;

	    if(resting_dim_x >
	       (cell_dim_x + 2 * Ecal_guard_ring_size))
	      {
		int N_cells_x_remaining =
		  int(floor((resting_dim_x - 
			     2 * Ecal_guard_ring_size)
			    /cell_dim_x));
		
		wafer_dim_x =
		  N_cells_x_remaining *
		  cell_dim_x;
		
		Box MagicWaferSiSolid( wafer_dim_x/2,wafer_dim_z/2,slab_dim_y);
		//Volume MagicWaferSiLog(det_name+"_"+l_name+"_"+s_name+"MagicWafer",MagicWaferSiSolid,slice_material);

		// Magic wafers, this waferOffsetX has to be taken care, 0.0 or half cell size in X.
		double thisWaferOffsetX = 0.0;
		if ( N_cells_x_remaining%2 ) thisWaferOffsetX = cell_dim_x/2.0;

		wafer_pos_x =
		  -slab_dim_x +
		  n_wafers_x * real_wafer_size_x +
		  (wafer_dim_x + 2 * Ecal_guard_ring_size)/2;
	  
		real_wafer_size_x =
		  wafer_dim_x + 2 * Ecal_guard_ring_size;
	  
		double wafer_pos_z =
		  -alveolus_dim_z/2.0 + 
		  Ecal_guard_ring_size +
		  wafer_dim_z /2;

		//int MagicWafer_num = 0;
		for (int n_wafer_z = 1;
		     n_wafer_z < 3;
		     n_wafer_z++)
		  {
		    wafer_num++;
		    string MagicWafer_name  =  _toString(wafer_num,"MagicWafer%d");
		    Volume MagicWaferSiLog(det_name+"_"+l_name+"_"+s_name+"_"+MagicWafer_name,MagicWaferSiSolid,slice_material);
		    MagicWaferSiLog.setSensitiveDetector(sens);
		    //MagicWaferSiLog.setVisAttributes(theDetector.visAttributes(x_slice.visStr()));
		    PlacedVolume wafer_phv = s_vol.placeVolume(MagicWaferSiLog,Position(wafer_pos_x,
							       wafer_pos_z,
							       0));
		    wafer_phv.addPhysVolID("wafer", wafer_num);

		    // Magic wafers, set the waferOffsetX for this layer this wafer.
		    waferSeg->setWaferOffsetX(myLayerNum, wafer_num, thisWaferOffsetX);

		    wafer_pos_z +=
		      wafer_dim_z +
		      2 * Ecal_guard_ring_size;
		  }
	      }
	    

#if DD4HEP_VERSION_GE( 0, 15 )
	    //Store "inner" quantities
	    caloLayer.inner_nRadiationLengths   = nRadiationLengths ;
	    caloLayer.inner_nInteractionLengths = nInteractionLengths ;
	    caloLayer.inner_thickness           = thickness_sum ;
	    //Store sensitive slice thickness
	    caloLayer.sensitive_thickness       = s_thick ;
#ifdef VERBOSE	    
	    std::cout<<" l_num: "<<l_num <<std::endl;
	    std::cout<<" s_num: "<<s_num <<std::endl;
	    std::cout<<" Ecal_inner_radius: "<< Ecal_inner_radius <<std::endl;
	    std::cout<<" module_thickness: "<< module_thickness <<std::endl;
	    std::cout<<" l_pos_z: "<< l_pos_z <<std::endl;
	    std::cout<<" l_thickness: "<< l_thickness <<std::endl;
	    std::cout<<" s_pos_z: "<< s_pos_z <<std::endl;
	    std::cout<<" s_thick: "<< s_thick <<std::endl;
	    std::cout<<" radiator_dim_y: "<< radiator_dim_y <<std::endl;
#endif	    
	    //-----------------------------------------------------------------------------------------
	    caloLayer.distance  = Ecal_inner_radius + module_thickness/2.0 - l_pos_z + l_thickness/2. + (s_pos_z+s_thick/2.) 
	      - caloLayer.inner_thickness;
	    caloLayer.absorberThickness = radiator_dim_y ;

	    //-----------------------------------------------------------------------------------------
#endif
	    // Init for outer
	    nRadiationLengths   = 0. ;
	    nInteractionLengths = 0. ;
	    thickness_sum       = 0. ;

	  }

	  nRadiationLengths   += s_thick/(2.*slice_material.radLength());
	  nInteractionLengths += s_thick/(2.*slice_material.intLength());
	  thickness_sum       += s_thick/2;


          // Slice placement.
          PlacedVolume slice_phv = l_vol.placeVolume(s_vol,Position(0,0,s_pos_z-s_thick/2));

          if ( x_slice.isSensitive() ) {
	    slice_phv.addPhysVolID("layer", myLayerNum++ );
	    //	    slice_phv.addPhysVolID("slice",s_num);
	  }

	  //fg: not needed   slice.setPlacement(slice_phv);

          // Increment Z position of slice.
          s_pos_z -= s_thick;
                                        
          // Increment slice number.
          ++s_num;

        }        

#if DD4HEP_VERSION_GE( 0, 15 )
	caloLayer.outer_nRadiationLengths   = nRadiationLengths
	  + (Ecal_fiber_thickness * (N_FIBERS_ALVOULUS + N_FIBERS_W_STRUCTURE))/air.radLength();
	caloLayer.outer_nInteractionLengths = nInteractionLengths
	  + (Ecal_fiber_thickness * (N_FIBERS_ALVOULUS + N_FIBERS_W_STRUCTURE))/air.intLength();
	caloLayer.outer_thickness           = thickness_sum 
	  + (Ecal_fiber_thickness * (N_FIBERS_ALVOULUS + N_FIBERS_W_STRUCTURE));

	if (!isFirstSens) caloData->layers.push_back( caloLayer ) ;
#ifdef VERBOSE
	std::cout<<" caloLayer.distance: "<< caloLayer.distance <<std::endl;
	
	std::cout<<" caloLayer.inner_nRadiationLengths: "<< caloLayer.inner_nRadiationLengths <<std::endl;
	std::cout<<" caloLayer.inner_nInteractionLengths: "<< caloLayer.inner_nInteractionLengths <<std::endl;
	std::cout<<" caloLayer.inner_thickness: "<< caloLayer.inner_thickness <<std::endl;
	std::cout<<" caloLayer.sensitive_thickness: "<< caloLayer.sensitive_thickness <<std::endl;

	std::cout<<" caloLayer.outer_nRadiationLengths: "<< caloLayer.outer_nRadiationLengths <<std::endl;
	std::cout<<" caloLayer.outer_nInteractionLengths: "<< caloLayer.outer_nInteractionLengths <<std::endl;
	std::cout<<" caloLayer.outer_thickness: "<< caloLayer.outer_thickness <<std::endl;

	std::cout<<" EcalBarrel[2]==>caloLayer.inner_thickness + caloLayer.outer_thickness: "
		 << caloLayer.inner_thickness + caloLayer.outer_thickness <<std::endl;
#endif
#endif
	// Init for next double layer
	nRadiationLengths   = radiator_dim_y/(stave_material.radLength())
	  + (Ecal_fiber_thickness * (N_FIBERS_ALVOULUS + N_FIBERS_W_STRUCTURE))/air.radLength();
	nInteractionLengths = radiator_dim_y/(stave_material.intLength())
	  + (Ecal_fiber_thickness * (N_FIBERS_ALVOULUS + N_FIBERS_W_STRUCTURE))/air.intLength();
	thickness_sum       = radiator_dim_y
	  + (Ecal_fiber_thickness * (N_FIBERS_ALVOULUS + N_FIBERS_W_STRUCTURE));
	
	if(radiator_dim_y <= 0) {
	  stringstream err;
	  err << " \n ERROR: The subdetector " << x_det.nameStr() << " geometry parameter -- radiator_dim_y = " << radiator_dim_y ;
	  err << " \n Please check the radiator material name in the subdetector xml file";
	  throw runtime_error(err.str());
	}

	// #########################
	// BuildBarrelStructureLayer
	// #########################


	l_dim_x -=  (radiator_dim_y +  Ecal_fiber_thickness * (N_FIBERS_ALVOULUS + N_FIBERS_W_STRUCTURE));
	double radiator_dim_x = l_dim_x*2.;

#ifdef VERBOSE
	std::cout << "radiator_dim_x = " << radiator_dim_x << std::endl;
#endif  

	double radiator_dim_z =
	  Ecal_Barrel_module_dim_z -
	  2 * Ecal_lateral_face_thickness -
	  2 * N_FIBERS_W_STRUCTURE * Ecal_fiber_thickness;
	
	string bs_name="bs";
	Box        barrelStructureLayer_box(radiator_dim_x/2.,radiator_dim_z/2.,radiator_dim_y/2.);
	Volume     barrelStructureLayer_vol(det_name+"_"+l_name+"_"+bs_name,barrelStructureLayer_box,stave_material);

	barrelStructureLayer_vol.setVisAttributes(theDetector.visAttributes(x_layer.visStr()));	


        // Increment to next layer Z position.
        l_pos_z -= l_thickness;          

	// Without last W StructureLayer, the last part is Si SD even layer.
	// the last number of  Ecal_nlayers1, Ecal_nlayers2 and  Ecal_nlayers3 is odd.
	int even_layer = l_num*2;
	if(even_layer > Ecal_nlayers1 + Ecal_nlayers2 + Ecal_nlayers3) continue;
	//if ( Number_of_Si_Layers_in_Barrel > n_total_layers ) continue;

	double bsl_pos_z = l_pos_z - (radiator_dim_y/2. + Ecal_fiber_thickness * (N_FIBERS_ALVOULUS + N_FIBERS_W_STRUCTURE));
	l_pos_z -= (Ecal_fiber_thickness * (N_FIBERS_ALVOULUS + N_FIBERS_W_STRUCTURE));

	Position   bsl_pos(0,0,bsl_pos_z);      // Position of the layer.
	// PlacedVolume  barrelStructureLayer_phv =
	  mod_vol.placeVolume(barrelStructureLayer_vol,bsl_pos);

	l_dim_x -=  (Ecal_fiber_thickness * (N_FIBERS_ALVOULUS + N_FIBERS_W_STRUCTURE));	
	l_pos_z -= (radiator_dim_y + Ecal_fiber_thickness * (N_FIBERS_ALVOULUS + N_FIBERS_W_STRUCTURE));
	
        ++l_num;

      }
    }
  

    // Set stave visualization.
    if (x_staves)   {
      mod_vol.setVisAttributes(theDetector.visAttributes(x_staves.visStr()));
    }
    
    
    
//====================================================================
// Place ECAL Barrel stave module into the envelope volume
//====================================================================
    double X,Y;
    X = module_thickness * sin(M_PI/4.);
    Y = Ecal_inner_radius + module_thickness / 2.;
    
    for (int stave_id = 1; stave_id <= nsides ; stave_id++)
      for (int module_id = 1; module_id < 6; module_id++)
	{
	  double phirot =  (stave_id-1) * dphi - hphi*3.0;
	  double module_z_offset =  (2 * module_id-6) * Ecal_Barrel_module_dim_z/2.;
	  
	  // And the rotation in Mokka is right hand rule, and the rotation in DD4hep is clockwise rule
	  // So there is a negitive sign when port Mokka into DD4hep 
	  Transform3D tr(RotationZYX(0,phirot,M_PI*0.5),Translation3D(X*cos(phirot)-Y*sin(phirot),
								      X*sin(phirot)+Y*cos(phirot),
								      module_z_offset));
	  PlacedVolume pv = envelope.placeVolume(mod_vol,tr);
	  pv.addPhysVolID("module",module_id);
	  pv.addPhysVolID("stave",stave_id);
	  DetElement sd = (module_id==0&&stave_id==0) ? stave_det : stave_det.clone(_toString(module_id,"module%d")+_toString(stave_id,"stave%d"));
	  sd.setPlacement(pv);
	  sdet.add(sd);
	  
	}
    
    // Set envelope volume attributes.
    envelope.setAttributes(theDetector,x_det.regionStr(),x_det.limitsStr(),x_det.visStr());
    
    sdet.addExtension< LayeredCalorimeterData >( caloData ) ; 


    return sdet;
}
示例#22
0
static DD4hep::Geometry::Ref_t createGenericTrackerBarrel(DD4hep::Geometry::LCDD& lcdd,
                                                          DD4hep::XML::Handle_t xmlElement,
                                                          DD4hep::Geometry::SensitiveDetector sensDet) {
  // shorthands
  DD4hep::XML::DetElement xmlDet = static_cast<DD4hep::XML::DetElement>(xmlElement);
  Dimension dimensions(xmlDet.dimensions());
  // get sensitive detector type from xml
  DD4hep::XML::Dimension sdTyp = xmlElement.child("sensitive");
  if (xmlDet.isSensitive()) {
    // sensitive detector used for all sensitive parts of this detector
    sensDet.setType(sdTyp.typeStr());
  }
  // definition of top volume
  // has min/max dimensions of tracker for visualization etc.
  std::string detectorName = xmlDet.nameStr();
  DetElement topDetElement(detectorName, xmlDet.id());
  DD4hep::Geometry::Tube topVolumeShape(dimensions.rmin(), dimensions.rmax(), dimensions.dz());
  Volume topVolume(detectorName, topVolumeShape, lcdd.air());
  topVolume.setVisAttributes(lcdd.invisible());

  // counts all layers - incremented in the inner loop over repeat - tags
  unsigned int layerCounter = 0;
  // loop over 'layer' nodes in xml
  for (DD4hep::XML::Collection_t xLayerColl(xmlElement, _U(layers)); nullptr != xLayerColl; ++xLayerColl) {
    DD4hep::XML::Component xLayer = static_cast<DD4hep::XML::Component>(xLayerColl);

    DD4hep::XML::Component xModuleComponents = xmlElement.child("module_components");
    DD4hep::XML::Component xModule =
        utils::getNodeByStrAttr(xmlElement, "module", "name", xLayer.attr<std::string>("module"));

    // optional parameters
    double stereo_offset = utils::getAttrValueWithFallback(xLayer, "stereo_offset", 0.0);
    double module_twist_angle = utils::getAttrValueWithFallback(xLayer, "module_twist_angle", 0.1 * M_PI);
    double stereo_module_overlap = utils::getAttrValueWithFallback(xLayer, "stereo_module_overlap", 0.0);

    // get total thickness of module
    unsigned int idxSubMod = 0;
    double totalModuleComponentThickness = 0;
    for (DD4hep::XML::Collection_t xCompColl(xModuleComponents, _U(module_component)); nullptr != xCompColl;
         ++xCompColl, ++idxSubMod) {
      DD4hep::XML::Component xComp = static_cast<DD4hep::XML::Component>(xCompColl);
      totalModuleComponentThickness += xComp.thickness();
    }
    // now that thickness is known: define module components volumes
    idxSubMod = 0;
    double integratedModuleComponentThickness = 0;
    std::vector<Volume> moduleComponentVector;
    for (DD4hep::XML::Collection_t xCompColl(xModuleComponents, _U(module_component)); nullptr != xCompColl;
         ++xCompColl, ++idxSubMod) {
      DD4hep::XML::Component xComp = static_cast<DD4hep::XML::Component>(xCompColl);
      std::string moduleComponentName = "layer" + std::to_string(layerCounter) + "_rod_module_component" +
          std::to_string(idxSubMod) + "_" + xComp.materialStr();
      Volume moduleComponentVolume(moduleComponentName,
                                   DD4hep::Geometry::Box(xModule.width(), xComp.thickness(), xModule.length()),
                                   lcdd.material(xComp.materialStr()));
      moduleComponentVolume.setVisAttributes(lcdd, xComp.visStr());
      if (xComp.isSensitive()) {
        moduleComponentVolume.setSensitiveDetector(sensDet);
      }
      moduleComponentVector.push_back(moduleComponentVolume);
    }

    // definition of module volume (smallest independent subdetector)
    // define the module whose name was given in the "layer" xml Element
    Volume moduleVolume("module", DD4hep::Geometry::Box(xModule.width(), xModule.thickness(), xModule.length()),
                        lcdd.material("Air"));
    moduleVolume.setVisAttributes(lcdd, xModule.visStr());

    // definition of rod volume (longitudinal arrangement of modules)
    Volume rodVolume("GenericTrackerBarrel_layer" + std::to_string(layerCounter) + "_rod",
                     DD4hep::Geometry::Box(xModule.width(), xModule.thickness(), xLayer.dz()),
                     lcdd.material("Air"));
    rodVolume.setVisAttributes(lcdd.invisible());

    /// @todo: allow for more than one type of module components
    // analogous to module
    // place module substructure in module
    std::string moduleComponentName = "moduleComponent";
    idxSubMod = 0;
    for (DD4hep::XML::Collection_t xCompColl(xModuleComponents, _U(module_component)); nullptr != xCompColl;
         ++xCompColl, ++idxSubMod) {
      DD4hep::XML::Component xComp = static_cast<DD4hep::XML::Component>(xCompColl);
      DD4hep::Geometry::Position offset(0, -0.5 * totalModuleComponentThickness + integratedModuleComponentThickness,
                                        0);
      integratedModuleComponentThickness += xComp.thickness();
      PlacedVolume placedModuleComponentVolume = moduleVolume.placeVolume(moduleComponentVector[idxSubMod], offset);
      placedModuleComponentVolume.addPhysVolID("module_component", idxSubMod);
    }

    // handle repeat attribute in xml
    // "repeat" layers  equidistant between rmin and rmax
    double numRepeat = xLayer.repeat();
    double layerThickness = (xLayer.rmax() - xLayer.rmin()) / numRepeat;
    double layer_rmin = xLayer.rmin();
    unsigned int nPhi = 0;
    double r = 0;
    double phi = 0;
    // loop over repeated layers defined by one layer tag
    for (unsigned int repeatIndex = 0; repeatIndex < numRepeat; ++repeatIndex) {
      ++layerCounter;
      // let r be the middle between two equidistant layer boundaries
      r = layer_rmin + (0.5 + repeatIndex) * layerThickness;
      // definition of layer volumes
      DD4hep::Geometry::Tube layerShape(r - 0.5*layerThickness, r + 0.5*layerThickness, xLayer.dz());
      std::string layerName = "layer" + std::to_string(layerCounter);
      Volume layerVolume(layerName, layerShape, lcdd.material("Silicon"));
      layerVolume.setVisAttributes(lcdd.invisible());
      PlacedVolume placedLayerVolume = topVolume.placeVolume(layerVolume);
      placedLayerVolume.addPhysVolID("layer", layerCounter);
      // approximation of tklayout values
      double phiOverlapFactor = utils::getAttrValueWithFallback(xLayer, "phi_overlap_factor", 1.15);
      nPhi = static_cast<unsigned int>( phiOverlapFactor * 2 * M_PI * r / (2 * xModule.width()));
      for (unsigned int phiIndex = 0; phiIndex < nPhi; ++phiIndex) {
        phi = 2 * M_PI * static_cast<double>(phiIndex) / static_cast<double>(nPhi);
        DD4hep::Geometry::Translation3D lTranslation(r * cos(phi), r * sin(phi), 0);
        DD4hep::Geometry::RotationZ lRotation(phi + module_twist_angle + 0.5 * M_PI);
        PlacedVolume placedRodVolume = layerVolume.placeVolume(rodVolume, lTranslation * lRotation);
        placedRodVolume.addPhysVolID("rod", phiIndex);
      }
    }
    // placement of modules within rods
    unsigned int zRepeat = static_cast<int>(xLayer.dz() / (xModule.length() - stereo_module_overlap));
    // stereo overlap
    for (unsigned int zIndex = 0; zIndex < zRepeat; ++zIndex) {
      stereo_offset *= -1.;
      DD4hep::Geometry::Position moduleOffset(0, stereo_offset,
                                              zIndex * 2 * (xModule.length() - stereo_module_overlap) - xLayer.dz() +
                                                  xModule.length() - stereo_module_overlap);
      PlacedVolume placedModuleVolume = rodVolume.placeVolume(moduleVolume, moduleOffset);
      placedModuleVolume.addPhysVolID("module", zIndex);
    }
  }
  Volume motherVol = lcdd.pickMotherVolume(topDetElement);
  PlacedVolume placedGenericTrackerBarrel = motherVol.placeVolume(topVolume);
  placedGenericTrackerBarrel.addPhysVolID("system", topDetElement.id());
  topDetElement.setPlacement(placedGenericTrackerBarrel);
  return topDetElement;
}
示例#23
0
/** 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_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;
}
示例#25
0
static Ref_t create_detector(Detector& description, xml_h e, SensitiveDetector sens)  {
  xml_det_t  x_det     = e;
  Material   air       = description.air();
  string     det_name  = x_det.nameStr();
  bool       reflect   = x_det.reflect();
  DetElement sdet(det_name,x_det.id());
  Assembly   assembly(det_name);
  PlacedVolume pv;
  int l_num = 0;
    
  for(xml_coll_t i(x_det,_U(layer)); i; ++i, ++l_num)  {
    xml_comp_t x_layer = i;
    string l_nam = det_name+_toString(l_num,"_layer%d");
    double  zmin = x_layer.inner_z();
    double  rmin = x_layer.inner_r();
    double  rmax = x_layer.outer_r();
    double  z    = zmin, layerWidth = 0.;
    int     s_num = 0;
      
    for(xml_coll_t j(x_layer,_U(slice)); j; ++j)  {
      double thickness = xml_comp_t(j).thickness();
      layerWidth += thickness;
    }
    Tube    l_tub(rmin,rmax,layerWidth,2*M_PI);
    Volume  l_vol(l_nam,l_tub,air);
    l_vol.setVisAttributes(description,x_layer.visStr());
    for(xml_coll_t j(x_layer,_U(slice)); j; ++j, ++s_num)  {
      xml_comp_t x_slice = j;
      double thick = x_slice.thickness();
      Material mat = description.material(x_slice.materialStr());
      string s_nam = l_nam+_toString(s_num,"_slice%d");
      Volume s_vol(s_nam, Tube(rmin,rmax,thick), mat);
        
      if ( x_slice.isSensitive() ) {
        sens.setType("tracker");
        s_vol.setSensitiveDetector(sens);
      }
      s_vol.setAttributes(description,x_slice.regionStr(),x_slice.limitsStr(),x_slice.visStr());
      pv = l_vol.placeVolume(s_vol,Position(0,0,z-zmin-layerWidth/2+thick/2));
      pv.addPhysVolID("slice",s_num);
    }

    DetElement layer(sdet,l_nam+"_pos",l_num);
    pv = assembly.placeVolume(l_vol,Position(0,0,zmin+layerWidth/2.));
    pv.addPhysVolID("layer",l_num);
    pv.addPhysVolID("barrel",1);
    layer.setPlacement(pv);
    if ( reflect )  {
      pv = assembly.placeVolume(l_vol,Transform3D(RotationY(M_PI),Position(0,0,-zmin-layerWidth/2)));
      pv.addPhysVolID("layer",l_num);
      pv.addPhysVolID("barrel",2);
      DetElement layerR = layer.clone(l_nam+"_neg");
      sdet.add(layerR.setPlacement(pv));
    }
  }
  if ( x_det.hasAttr(_U(combineHits)) ) {
    sdet.setCombineHits(x_det.attr<bool>(_U(combineHits)),sens);
  }
  pv = description.pickMotherVolume(sdet).placeVolume(assembly);
  pv.addPhysVolID("system", x_det.id());      // Set the subdetector system ID.
  sdet.setPlacement(pv);
  return sdet;
}
示例#26
0
文件: BoxTrafos.C 项目: vvolkl/DD4hep
int BoxTrafos()  {
  string xml = "file:";
  xml += gSystem->Getenv("DD4hepINSTALL");
  xml += "/examples/ClientTests/compact/BoxTrafos.xml";
  const char* argv[] = {xml.c_str(), "BUILD_DEFAULT", 0};

  gSystem->Load("libDDCore");
  LCDD& lcdd = LCDD::getInstance();
  lcdd.apply("DD4hepCompactLoader",2,(char**)argv);
  lcdd.apply("DD4hepGeometryDisplay",0,0);


  DetElement de = lcdd.detector("B3");
  PlacedVolume pv = de.placement();
  Volume vol = pv.volume();
  Solid solid = vol.solid();
  TGeoBBox* box = (TGeoBBox*)(solid.ptr());
  Position glob,loc, pos(-10,30,10);

  printf("\n++++  local->world:\n\n");

  loc = Position(-pos.x(),-pos.y(),-pos.z());
  local_to_world("origine",de,pos,loc);

  loc = Position();
  local_to_world("center",de,pos,loc);

  loc = Position(box->GetDX(),box->GetDY(),box->GetDZ());
  local_to_world("top edge",de,pos,loc);

  loc = Position(box->GetDX(),box->GetDY(),-box->GetDZ());
  local_to_world("top edge",de,pos,loc);

  loc = Position(-box->GetDX(),box->GetDY(),box->GetDZ());
  local_to_world("top edge",de,pos,loc);

  loc = Position(-box->GetDX(),box->GetDY(),-box->GetDZ());
  local_to_world("top edge",de,pos,loc);

  loc = Position(box->GetDX(),-box->GetDY(),box->GetDZ());
  local_to_world("bottom edge",de,pos,loc);

  loc = Position(box->GetDX(),-box->GetDY(),-box->GetDZ());
  local_to_world("bottom edge",de,pos,loc);

  loc = Position(-box->GetDX(),-box->GetDY(),box->GetDZ());
  local_to_world("bottom edge",de,pos,loc);

  loc = Position(-box->GetDX(),-box->GetDY(),-box->GetDZ());
  local_to_world("bottom edge",de,pos,loc);

  printf("\n++++  world->local:\n\n");

  glob = Position(0,0,0);
  world_to_local("world center",de,pos,glob);

  glob = Position(pos.x(),pos.y(),pos.z());
  world_to_local("position",de,pos,glob);

  glob = Position( box->GetDX()+pos.x(),  box->GetDY()+pos.y(),  box->GetDZ()+pos.z());
  world_to_local("top edge",de,pos,glob);

  glob = Position( box->GetDX()+pos.x(),  box->GetDY()+pos.y(), -box->GetDZ()+pos.z());
  world_to_local("top edge",de,pos,glob);

  glob = Position(-box->GetDX()+pos.x(),  box->GetDY()+pos.y(),  box->GetDZ()+pos.z());
  world_to_local("top edge",de,pos,glob);

  glob = Position(-box->GetDX()+pos.x(),  box->GetDY()+pos.y(), -box->GetDZ()+pos.z());
  world_to_local("top edge",de,pos,glob);

  glob = Position( box->GetDX()+pos.x(), -box->GetDY()+pos.y(),  box->GetDZ()+pos.z());
  world_to_local("bottom edge",de,pos,glob);

  glob = Position( box->GetDX()+pos.x(), -box->GetDY()+pos.y(), -box->GetDZ()+pos.z());
  world_to_local("bottom edge",de,pos,glob);

  glob = Position(-box->GetDX()+pos.x(), -box->GetDY()+pos.y(),  box->GetDZ()+pos.z());
  world_to_local("bottom edge",de,pos,glob);

  glob = Position(-box->GetDX()+pos.x(), -box->GetDY()+pos.y(), -box->GetDZ()+pos.z());
  world_to_local("bottom edge",de,pos,glob);

  return 1;
}
static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector sens)  {
    xml_det_t   x_det     = e;
    int         det_id    = x_det.id();
    string      det_name  = x_det.nameStr();
    DetElement    sdet      (det_name,det_id);
    
    // --- create an envelope volume and position it into the world ---------------------
    
    Volume envelope = dd4hep::xml::createPlacedEnvelope( theDetector,  e , sdet ) ;
    dd4hep::xml::setDetectorTypeFlag( e, sdet ) ;
    
    if( theDetector.buildType() == BUILD_ENVELOPE ) return sdet ;
    
    //-----------------------------------------------------------------------------------
    
    xml_dim_t   dim       = x_det.dimensions();
    Material    air       = theDetector.air();
    int         nsides_inner = dim.nsides_inner();
    int         nsides_outer = dim.nsides_outer();
    double      rmin      = dim.rmin();
    double      rmax      = dim.rmax(); /// FIXME: IS THIS RIGHT?
    double      zmin      = dim.zmin();
    
    double       rcutout   = dim.hasAttr(_U(rmin2)) ? dim.rmin2() : 0.;
    double       zcutout   = dim.hasAttr(_U(z2)) ? dim.z2() : 0.;
    
    Layering    layering(x_det);
    double      totalThickness = layering.totalThickness();
    Readout readout = sens.readout();
    Segmentation seg = readout.segmentation();
    
    std::vector<double> cellSizeVector = seg.segmentation()->cellDimensions(0); //Assume uniform cell sizes, provide dummy cellID
    double cell_sizeX      = cellSizeVector[0];
    double cell_sizeY      = cellSizeVector[1];
    
    
    PolyhedraRegular polyVolume(nsides_outer,rmin,rmax,totalThickness);
    Volume      endcapVol("endcap",polyVolume,air);
    
    
    if(zcutout >0. || rcutout > 0.){
        PolyhedraRegular cutoutPolyVolume(nsides_inner,0,rmin+rcutout,zcutout);
        Position cutoutPos(0,0,(zcutout-totalThickness)/2.0);
        std::cout<<"Cutout z width will be  "<<zcutout<<std::endl; 
        endcapVol=Volume("endcap",SubtractionSolid(polyVolume,cutoutPolyVolume,cutoutPos),air);
        
    }
    
    
    DetElement  endcapA(sdet,"endcap",det_id);
    Ref_t(endcapA)->SetName((det_name+"_A").c_str());
    
    int layer_num = 0;
    int layerType   = 0;
    double layerZ   = -totalThickness/2;
    
    //Create caloData object to extend driver with data required for reconstruction
    LayeredCalorimeterData* caloData = new LayeredCalorimeterData ;
    caloData->layoutType = LayeredCalorimeterData::EndcapLayout ;
    caloData->inner_symmetry = nsides_inner;
    caloData->outer_symmetry = nsides_outer; 
    
    /** NOTE: phi0=0 means lower face flat parallel to experimental floor
     *  This is achieved by rotating the modules with respect to the envelope
     *  which is assumed to be a Polyhedron and has its axes rotated with respect
     *  to the world by 180/nsides. In any other case (e.g. if you want to have
     *  a tip of the calorimeter touching the ground) this value needs to be computed
     */
    
    caloData->inner_phi0 = 0.; 
    caloData->outer_phi0 = 0.; 
    caloData->gap0 = 0.; //FIXME
    caloData->gap1 = 0.; //FIXME
    caloData->gap2 = 0.; //FIXME  
    
    
    /// extent of the calorimeter in the r-z-plane [ rmin, rmax, zmin, zmax ] in mm.
    caloData->extent[0] = rmin ;
    caloData->extent[1] = rmax ; ///FIXME: CHECK WHAT IS NEEDED (EXSCRIBED?)
    caloData->extent[2] = zmin ;
    caloData->extent[3] = zmin + totalThickness;
    
    endcapVol.setAttributes(theDetector,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           layer_thick  = layering.layer(layer_num)->thickness();
        string           layer_type_name   = _toString(layerType,"layerType%d");
        int              layer_repeat = x_layer.repeat();
        double            layer_rcutout = x_layer.hasAttr(_U(gap)) ? x_layer.gap() : 0;
        
        std::cout<<"Number of layers in group "<<layerType<<" : "<<layer_repeat<<std::endl; 
        
        Volume           layer_vol(layer_type_name,PolyhedraRegular(nsides_outer,rmin+layer_rcutout,rmax,layer_thick),air);
        
        int slice_num = 0;
        double sliceZ = -layer_thick/2;
        
        //Create a caloLayer struct for thiss layer type to store copies of in the parent struct
        LayeredCalorimeterData::Layer caloLayer ;
        caloLayer.cellSize0 = cell_sizeX;
        caloLayer.cellSize1 = cell_sizeY; 
        
        double nRadiationLengths=0.;
        double nInteractionLengths=0.;
        double thickness_sum=0;
        
        for(xml_coll_t s(x_layer,_U(slice)); s; ++s)  {
            xml_comp_t x_slice = s;
            string     slice_name  = _toString(slice_num,"slice%d");
            double     slice_thickness = x_slice.thickness();
            Material   slice_material   = theDetector.material(x_slice.materialStr());
            Volume     slice_vol(slice_name,PolyhedraRegular(nsides_outer,rmin+layer_rcutout,rmax,slice_thickness),slice_material);
            
            slice_vol.setVisAttributes(theDetector.visAttributes(x_slice.visStr()));
            sliceZ += slice_thickness/2;
            layer_vol.placeVolume(slice_vol,Position(0,0,sliceZ));
            
            nRadiationLengths += slice_thickness/(2.*slice_material.radLength());
            nInteractionLengths += slice_thickness/(2.*slice_material.intLength());
            thickness_sum += slice_thickness/2;
            
            if ( x_slice.isSensitive() )  {
                sens.setType("calorimeter");
                slice_vol.setSensitiveDetector(sens);
                
#if DD4HEP_VERSION_GE( 0, 15 )
                //Store "inner" quantities
                caloLayer.inner_nRadiationLengths = nRadiationLengths;
                caloLayer.inner_nInteractionLengths = nInteractionLengths;
                caloLayer.inner_thickness = thickness_sum;
                //Store scintillator thickness
                caloLayer.sensitive_thickness = slice_thickness;
#endif
                //Reset counters to measure "outside" quantitites
                nRadiationLengths=0.;
                nInteractionLengths=0.;
                thickness_sum = 0.;
            } 
            
            nRadiationLengths += slice_thickness/(2.*slice_material.radLength());
            nInteractionLengths += slice_thickness/(2.*slice_material.intLength());
            thickness_sum += slice_thickness/2;

            sliceZ += slice_thickness/2;
            slice_num++;
        }
        
#if DD4HEP_VERSION_GE( 0, 15 )
        //Store "outer" quantities
        caloLayer.outer_nRadiationLengths = nRadiationLengths;
        caloLayer.outer_nInteractionLengths = nInteractionLengths;
        caloLayer.outer_thickness = thickness_sum;
#endif        
        layer_vol.setVisAttributes(theDetector.visAttributes(x_layer.visStr()));
        
        
        if ( layer_repeat <= 0 ) throw std::runtime_error(x_det.nameStr()+"> Invalid repeat value");
        
        for(int j=0; j<layer_repeat; ++j) {
            string phys_lay = _toString(layer_num,"layer%d");
            
            //The rest of the data is constant; only the distance needs to be updated  
            //Store the position up to the inner face of the layer
            caloLayer.distance = zmin +  totalThickness/2 + layerZ;
            //Push back a copy to the caloData structure
            caloData->layers.push_back( caloLayer );
            
            layerZ += layer_thick/2;
            DetElement    layer_elt(endcapA, phys_lay, layer_num);
            PlacedVolume  pv = endcapVol.placeVolume(layer_vol,Position(0,0,layerZ));
            pv.addPhysVolID("layer", layer_num);
            layer_elt.setPlacement(pv);
            
            layerZ += layer_thick/2;
            ++layer_num;
        }
        ++layerType;
    }
    
    double z_pos = zmin+totalThickness/2;
    PlacedVolume pv;
    // Reflect it.
    
    DetElement  endcapB = endcapA.clone(det_name+"_B",x_det.id());
    
    //Removed rotations to align with envelope
    //NOTE: If the envelope is not a polyhedron (eg. if you use a tube)
    //you may need to rotate so the axes match
    
    pv = envelope.placeVolume(endcapVol,Transform3D(RotationZYX(0,0,0),
                                                    Position(0,0,z_pos)));
    pv.addPhysVolID("side", 1);
    endcapA.setPlacement(pv);
    
    //Removed rotations
    pv = envelope.placeVolume(endcapVol,Transform3D(RotationZYX(0,M_PI,0),
                                                    Position(0,0,-z_pos)));
    pv.addPhysVolID("side", 2);
    endcapB.setPlacement(pv);
    
    sdet.add(endcapB);
    
    sdet.addExtension< LayeredCalorimeterData >( caloData ) ;
    
    return sdet;
    
}
static Ref_t create_detector(Detector& theDetector,xml_h e,SensitiveDetector sens){
  typedef vector<PlacedVolume>Placements;
  xml_det_t x_det=e;
  Material vacuum=theDetector.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);
  int m_id=0,c_id=0,n_sensor=0;
  map<string,Volume>modules;
  map<string,Placements>sensitives;
  PlacedVolume pv;
  
  //encoding that was missing  
  
  std::string cellIDEncoding=sens.readout().idSpec().fieldDescription();
  UTIL::BitField64 encoder(cellIDEncoding);
  encoder.reset();
  encoder[lcio::LCTrackerCellID::subdet()]=det_id;
  
  // --- create an envelope volume and position it into the world ---------------------
  
  Volume envelope=dd4hep::xml::createPlacedEnvelope(theDetector,e,sdet);
  dd4hep::xml::setDetectorTypeFlag(e,sdet);
  
  if(theDetector.buildType() == BUILD_ENVELOPE)return sdet;
  
  //-----------------------------------------------------------------------------------
  dd4hep::rec::ZDiskPetalsData* zDiskPetalsData=new dd4hep::rec::ZDiskPetalsData;
  //neighbour surfaces added 
  dd4hep::rec::NeighbourSurfacesData* neighbourSurfacesData=new dd4hep::rec::NeighbourSurfacesData();
  //
  std::map< std::string, double > moduleSensThickness;
  
  envelope.setVisAttributes(theDetector.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(theDetector.visAttributes(x_mod.visStr()));
    // Loop over slices 
    // The first slice (top in the xml) is placed at the "bottom" of the module
    
    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=theDetector.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(theDetector.visAttributes(c.visStr()));
      pv = m_volume.placeVolume(c_vol,Position(0,posY+c_thick/2,0));
      if (c.isSensitive()){
        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=0;
    int ring_num=0;
    double sumZ(0.),innerR(1e100),outerR(0.);
    //loop only to count the number of rings in a disk - it is then needed for looking for neighborous when you are in a "border" cell
    int nrings = 0;
    
    for(xml_coll_t ri(x_layer,_U(ring)); ri; ++ri) { 
      nrings++;
    }
    dd4hep::rec::ZDiskPetalsData::LayerLayout thisLayer;
    
    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];
      Box mod_shape(m_vol.solid());
      
      if(r-mod_shape->GetDZ()<innerR)
	innerR=r-mod_shape->GetDZ();
      if(r+mod_shape->GetDZ()>outerR)
	outerR=r+mod_shape->GetDZ();
      sumZ+=zstart;
      r=r+mod_shape->GetDY();
      
      for(int k=0;k<nmodules;++k){
	string m_base=_toString(l_id,"layer%d")+_toString(mod_num,"_module%d")+_toString(k,"_sensor%d");
	double x=-r*std::cos(phi);
	double y=-r*std::sin(phi);
	DetElement module(sdet,m_base+"_pos",det_id);
	pv=envelope.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).addPhysVolID("sensor",k);
	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 = envelope.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).addPhysVolID("sensor",k);
	  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);
	  }
	}
	
	//modified on  comparison with  TrackerEndcap_o2_v06_geo.cpp
	//get cellID and fill map< cellID of surface, vector of cellID of neighbouring surfaces >
	dd4hep::long64 cellID_reflect;
	if(reflect){
	  encoder[lcio::LCTrackerCellID::side()]=lcio::ILDDetID::bwd;
	  encoder[lcio::LCTrackerCellID::layer()]=l_id;
	  encoder[lcio::LCTrackerCellID::module()]=mod_num;
	  encoder[lcio::LCTrackerCellID::sensor()]=k;
	  
	  cellID_reflect=encoder.lowWord(); // 32 bits
	}
	
	encoder[lcio::LCTrackerCellID::side()]=lcio::ILDDetID::fwd;
	encoder[lcio::LCTrackerCellID::layer()]=l_id;
	encoder[lcio::LCTrackerCellID::module()]=mod_num;
	encoder[lcio::LCTrackerCellID::sensor()]=k;
	
	dd4hep::long64 cellID = encoder.lowWord(); // 32 bits
	
	//compute neighbours 
	
	int n_neighbours_module = 1; // 1 gives the adjacent modules (i do not think we would like to change this)
	int n_neighbours_sensor = 1;
	int newmodule=0,newsensor=0;
	
	for(int imodule=-n_neighbours_module; imodule<=n_neighbours_module; imodule++){ // neighbouring modules
	  for(int isensor=-n_neighbours_sensor; isensor<=n_neighbours_sensor; isensor++){ // neighbouring sensors
	    
	    if (imodule==0 && isensor==0) continue; // cellID we started with
	    newmodule = mod_num + imodule;
		newsensor = k + isensor;
		
		//compute special case at the boundary  
		//general computation to allow (if necessary) more then adiacent neighbours (ie: +-2)
		if (newsensor < 0) newsensor = nmodules + newsensor;
		if (newsensor >= nmodules) newsensor = newsensor - nmodules;
		if (newmodule < 0 || newmodule >= nrings)continue; //out of disk		
		
		//encoding
		encoder[lcio::LCTrackerCellID::module()] = newmodule;
		encoder[lcio::LCTrackerCellID::sensor()] = newsensor;
		    
		neighbourSurfacesData->sameLayer[cellID].push_back(encoder.lowWord());
		
		if (reflect){
		  encoder[lcio::LCTrackerCellID::side()]=lcio::ILDDetID::bwd;
		  encoder[lcio::LCTrackerCellID::layer()]=l_id;
		  encoder[lcio::LCTrackerCellID::module()]=newmodule;
		  encoder[lcio::LCTrackerCellID::sensor()]=newsensor;
		  neighbourSurfacesData->sameLayer[cellID_reflect].push_back(encoder.lowWord());
		}
	  }
	}
	dz   = -dz;
	phi += iphi;
      }
      ++mod_num;
      ++ring_num;
    }
    
    // Only filling what is needed for CED/DDMarlinPandora
    thisLayer.zPosition=sumZ/ring_num; // average z
    thisLayer.distanceSensitive=innerR;
    thisLayer.lengthSensitive=outerR - innerR;
    thisLayer.petalNumber=ring_num; // number of rings in petalNumber, needed for tracking
    zDiskPetalsData->layers.push_back(thisLayer);
  }
  
  sdet.setAttributes(theDetector,envelope,x_det.regionStr(),x_det.limitsStr(),x_det.visStr());
  
  sdet.addExtension<dd4hep::rec::ZDiskPetalsData>(zDiskPetalsData);
  //added extension 
  sdet.addExtension<dd4hep::rec::NeighbourSurfacesData>(neighbourSurfacesData);
  std::cout<<"XXX Tracker endcap layers:"<<zDiskPetalsData->layers.size()<<std::endl;
  
  return sdet;
}
示例#29
0
static Ref_t create_detector(Detector& theDetector,
                             xml_h element,
                             SensitiveDetector sens) {
    
    std::cout << __PRETTY_FUNCTION__  << std::endl;
    std::cout << "Here is my LumiCal"  << std::endl;
    std::cout << " and this is the sensitive detector: " << &sens  << std::endl;
    sens.setType("calorimeter");
    //Materials
    Material air = theDetector.air();
    
    //Access to the XML File
    xml_det_t     xmlLumiCal    = element;
    const std::string detName   = xmlLumiCal.nameStr();
    
    DetElement sdet ( detName, xmlLumiCal.id() );
    
    // --- create an envelope volume and position it into the world ---------------------
    
    Volume envelope = dd4hep::xml::createPlacedEnvelope( theDetector, element , sdet ) ;
    DetElement lumiCalDE_1(sdet,"Calorimeter1",1);
    DetElement lumiCalDE_2(sdet,"Calorimeter2",2);

    sdet.setTypeFlag( DetType::CALORIMETER |  DetType::ENDCAP  | DetType::ELECTROMAGNETIC |  DetType::FORWARD ) ;

    if( theDetector.buildType() == BUILD_ENVELOPE ) return sdet ;
    
    //-----------------------------------------------------------------------------------
    
    dd4hep::xml::Dimension dimensions =  xmlLumiCal.dimensions();
    
    //LumiCal Dimensions
    const double lcalInnerR = dimensions.inner_r();
    const double lcalOuterR = dimensions.outer_r();
    const double lcalInnerZ = dimensions.inner_z();
    const double lcalThickness = Layering(xmlLumiCal).totalThickness();
    const double lcalCentreZ = lcalInnerZ+lcalThickness*0.5;
    
    double LumiCal_cell_size      = theDetector.constant<double>("LumiCal_cell_size");
    //========== fill data for reconstruction ============================
    LayeredCalorimeterData* caloData = new LayeredCalorimeterData ;
    caloData->layoutType = LayeredCalorimeterData::EndcapLayout ;
    caloData->inner_symmetry = 0  ; // hardcoded tube
    caloData->outer_symmetry = 0  ; 
    caloData->phi0 = 0 ;
    
    /// extent of the calorimeter in the r-z-plane [ rmin, rmax, zmin, zmax ] in mm.
    caloData->extent[0] = lcalInnerR ;
    caloData->extent[1] = lcalOuterR ;
    caloData->extent[2] = lcalInnerZ ;
    caloData->extent[3] = lcalInnerZ + lcalThickness ;
    
    // counter for the current layer to be placed
    int thisLayerId = 0;
    
    //Parameters we have to know about
    dd4hep::xml::Component xmlParameter = xmlLumiCal.child(_Unicode(parameter));
    const double fullCrossingAngle  = xmlParameter.attr< double >(_Unicode(crossingangle));
    std::cout << " The crossing angle is: " << fullCrossingAngle << " radian"  << std::endl;
    
    
    //Envelope to place the layers in
    Tube envelopeTube (lcalInnerR, lcalOuterR, lcalThickness*0.5 );
    Volume     envelopeVol(detName+"_module",envelopeTube,air);
    envelopeVol.setVisAttributes(theDetector,xmlLumiCal.visStr());
    
    ////////////////////////////////////////////////////////////////////////////////
    // Create all the layers
    ////////////////////////////////////////////////////////////////////////////////
    
    //Loop over all the layer (repeat=NN) sections
    //This is the starting point to place all layers, we need this when we have more than one layer block
    double referencePosition = -lcalThickness*0.5;
    for(dd4hep::xml::Collection_t coll(xmlLumiCal,_U(layer)); coll; ++coll)  {
        dd4hep::xml::Component xmlLayer(coll); //we know this thing is a layer
        
        
        //This just calculates the total size of a single layer
        //Why no convenience function for this?
        double layerThickness = 0;
        for(dd4hep::xml::Collection_t l(xmlLayer,_U(slice)); l; ++l)
            layerThickness += xml_comp_t(l).thickness();
        
        std::cout << "Total Length "    << lcalThickness/dd4hep::cm  << " cm" << std::endl;
        std::cout << "Layer Thickness " << layerThickness/dd4hep::cm << " cm" << std::endl;
        
        //Loop for repeat=NN
        for(int i=0, repeat=xmlLayer.repeat(); i<repeat; ++i)  {
            
            std::string layer_name = detName + dd4hep::xml::_toString(thisLayerId,"_layer%d");
            Tube layer_base(lcalInnerR,lcalOuterR,layerThickness*0.5);
            
            Volume layer_vol(layer_name,layer_base,air);
            
            
            int sliceID=0;
            double inThisLayerPosition = -layerThickness*0.5;
            
            double nRadiationLengths=0.;
            double nInteractionLengths=0.;
            double thickness_sum=0;
            
            LayeredCalorimeterData::Layer caloLayer ;
            
            for(dd4hep::xml::Collection_t collSlice(xmlLayer,_U(slice)); collSlice; ++collSlice)  {
                dd4hep::xml::Component compSlice = collSlice;
                const double      slice_thickness = compSlice.thickness();
                const std::string sliceName = layer_name + dd4hep::xml::_toString(sliceID,"slice%d");
                Material   slice_material  = theDetector.material(compSlice.materialStr());
                
                Tube sliceBase(lcalInnerR,lcalOuterR,slice_thickness/2);
                
                Volume slice_vol (sliceName,sliceBase,slice_material);
                
                nRadiationLengths += slice_thickness/(2.*slice_material.radLength());
                nInteractionLengths += slice_thickness/(2.*slice_material.intLength());
                thickness_sum += slice_thickness/2;
                
                if ( compSlice.isSensitive() )  {

 #if DD4HEP_VERSION_GE( 0, 15 )
                   //Store "inner" quantities
                    caloLayer.inner_nRadiationLengths = nRadiationLengths;
                    caloLayer.inner_nInteractionLengths = nInteractionLengths;
                    caloLayer.inner_thickness = thickness_sum;
                    //Store scintillator thickness
                    caloLayer.sensitive_thickness = slice_thickness;
#endif                    
                    //Reset counters to measure "outside" quantitites
                    nRadiationLengths=0.;
                    nInteractionLengths=0.;
                    thickness_sum = 0.;
                    slice_vol.setSensitiveDetector(sens);
                }
                
                nRadiationLengths += slice_thickness/(2.*slice_material.radLength());
                nInteractionLengths += slice_thickness/(2.*slice_material.intLength());
                thickness_sum += slice_thickness/2;
                
                slice_vol.setAttributes(theDetector,compSlice.regionStr(),compSlice.limitsStr(),compSlice.visStr());
                layer_vol.placeVolume(slice_vol,Position(0,0,inThisLayerPosition+slice_thickness*0.5));
                    
                inThisLayerPosition += slice_thickness;
                ++sliceID;
            }//For all slices in this layer
            
            //-----------------------------------------------------------------------------------------
            
            ///Needs to be innermost face distance
            caloLayer.distance = lcalCentreZ + referencePosition;

#if DD4HEP_VERSION_GE( 0, 15 )
            caloLayer.outer_nRadiationLengths = nRadiationLengths;
            caloLayer.outer_nInteractionLengths = nInteractionLengths;
            caloLayer.outer_thickness = thickness_sum;
#endif            
            
            caloLayer.cellSize0 = LumiCal_cell_size ;
            caloLayer.cellSize1 = LumiCal_cell_size ;
            
            caloData->layers.push_back( caloLayer ) ;
            //-----------------------------------------------------------------------------------------
            
            //Why are we doing this for each layer, this just needs to be done once and then placed multiple times
            //Do we need unique IDs for each piece?
            layer_vol.setVisAttributes(theDetector,xmlLayer.visStr());
            
            Position layer_pos(0,0,referencePosition+0.5*layerThickness);
            referencePosition += layerThickness;
            PlacedVolume pv = envelopeVol.placeVolume(layer_vol,layer_pos);
            pv.addPhysVolID("layer",thisLayerId);
            
            ++thisLayerId;
            
        }//for all layers
        
    }// for all layer collections
    
    const Position bcForwardPos (std::tan(0.5*fullCrossingAngle)*lcalCentreZ,0.0, lcalCentreZ);
    const Position bcBackwardPos(std::tan(0.5*fullCrossingAngle)*lcalCentreZ,0.0,-lcalCentreZ);
    const Rotation3D bcForwardRot ( RotationY(fullCrossingAngle*0.5 ) );
    const Rotation3D bcBackwardRot( RotationZYX ( (M_PI), (M_PI-fullCrossingAngle*0.5), (0.0)));
    
    PlacedVolume pv =
    envelope.placeVolume(envelopeVol, Transform3D( bcForwardRot, bcForwardPos ) );
    pv.addPhysVolID("barrel", 1);
    lumiCalDE_1.setPlacement(pv);

    PlacedVolume pv2 =
    envelope.placeVolume(envelopeVol, Transform3D( bcBackwardRot, bcBackwardPos ) );
    pv2.addPhysVolID("barrel", 2);
    lumiCalDE_2.setPlacement(pv2);
    
    sdet.addExtension< LayeredCalorimeterData >( caloData ) ;
    
    return sdet;
}
示例#30
0
static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector sens)  {
    typedef vector<PlacedVolume> Placements;
    xml_det_t   x_det     = e;
    Material    air       = theDetector.air();
    int         det_id    = x_det.id();
    string      det_name  = x_det.nameStr();
    DetElement  sdet       (det_name,det_id);
    // Assembly    assembly   (det_name);
    map<string, Volume>    volumes;
    map<string, Placements>  sensitives;
    PlacedVolume pv;
    

    // for encoding
    std::string cellIDEncoding = sens.readout().idSpec().fieldDescription();
    UTIL::BitField64 encoder( cellIDEncoding );
    encoder.reset();
    encoder[lcio::LCTrackerCellID::subdet()] = det_id;
    encoder[lcio::LCTrackerCellID::side()] = lcio::ILDDetID::barrel;


    // --- create an envelope volume and position it into the world ---------------------
    
    Volume envelope = dd4hep::xml::createPlacedEnvelope( theDetector,  e , sdet ) ;
    dd4hep::xml::setDetectorTypeFlag( e, sdet ) ;
    
    if( theDetector.buildType() == BUILD_ENVELOPE ) return sdet ;
    
    //-----------------------------------------------------------------------------------
    ZPlanarData*  zPlanarData = new ZPlanarData() ;
    NeighbourSurfacesData*  neighbourSurfacesData = new NeighbourSurfacesData() ;
    
    sens.setType("tracker");
    
    //NOTE modules are what is defined in compact. Later we call a "module" as a "sensor".
    for(xml_coll_t mi(x_det,_U(module)); mi; ++mi)  {
        xml_comp_t x_mod  = mi;
        xml_comp_t m_env  = x_mod.child(_U(module_envelope));
        string     m_nam  = x_mod.nameStr();

        
        if ( volumes.find(m_nam) != volumes.end() )   {
            printout(ERROR,"TrackerBarrel","Logics error in building modules.");
            throw runtime_error("Logic error in building modules.");
        }

        double module_thickness = 0;
        for(xml_coll_t incl(x_mod,_U(include)); incl; ++incl) {
            dd4hep::xml::DocumentHolder doc(dd4hep::xml::DocumentHandler().load(incl, incl.attr_value(_U(ref))));
            xml_h includes = doc.root();
            xml_det_t incl_stack = includes;
            for (xml_coll_t ci(incl_stack, _U(module_component)); ci; ++ci) {
                xml_comp_t x_comp = ci;
                module_thickness = module_thickness + x_comp.thickness();
            }
        }

        Volume     m_vol(m_nam,Box(m_env.width()/2.,m_env.length()/2.,module_thickness/2.),air);
        volumes[m_nam] = m_vol;
        m_vol.setVisAttributes(theDetector.visAttributes(x_mod.visStr()));
        
        
        int        ncomponents = 0; 
        
        //First component on top of the list is the innermost one. 
        double position_z= -module_thickness/2.;
        for(xml_coll_t incl(x_mod,_U(include)); incl; ++incl) {
            dd4hep::xml::DocumentHolder doc(dd4hep::xml::DocumentHandler().load(incl, incl.attr_value(_U(ref))));
            xml_h includes = doc.root();
            xml_det_t incl_stack = includes;
            for (xml_coll_t ci(incl_stack, _U(module_component)); ci; ++ci, ++ncomponents) {
                xml_comp_t x_comp = ci;
                string c_nam = _toString(ncomponents, "component%d");
                Box c_box(m_env.width() / 2.0, m_env.length() / 2.0, x_comp.thickness() / 2.0);
                Volume c_vol(c_nam, c_box, theDetector.material(x_comp.materialStr()));


                pv = m_vol.placeVolume(c_vol, Position(0, 0, position_z + x_comp.thickness() / 2.0));

                c_vol.setRegion(theDetector, x_comp.regionStr());
                c_vol.setLimitSet(theDetector, x_comp.limitsStr());
                c_vol.setVisAttributes(theDetector, x_comp.visStr());
                if (x_comp.isSensitive()) {
                    //         pv.addPhysVolID("wafer",wafer_number++);
                    c_vol.setSensitiveDetector(sens);
                    sensitives[m_nam].push_back(pv);
                }

                position_z += x_comp.thickness();
            }
        }
    }
    for(xml_coll_t li(x_det,_U(layer)); li; ++li)  {
        xml_comp_t x_layer  = li;
        xml_comp_t x_layout = x_layer.child(_U(rphi_layout));
        xml_comp_t z_layout = x_layer.child(_U(z_layout));      // Get the <z_layout> element.
        int        lay_id   = x_layer.id();
        // int        type     = x_layer.type();
        string     m_nam    = x_layer.moduleStr();
        string     lay_nam  = _toString(x_layer.id(),"layer%d");
        Assembly   lay_vol   (lay_nam);         // Create the layer envelope volume.
        double     phi0     = x_layout.phi0();              // Starting phi of first sensor.
        double     phi_tilt = x_layout.phi_tilt();          // Phi tilt of a sensor.
        double     rc       = x_layout.rc();                // Radius of the sensor center.
        int        nphi     = x_layout.nphi();              // Number of sensors in phi.
        double     rphi_dr  = x_layout.dr();                // The delta radius of every other sensor.
        
        double     phi_incr = (M_PI * 2) / nphi;            // Phi increment for one sensor.
        double     phic     = phi0;                         // Phi of the sensor center.
        double     z0       = z_layout.z0();                // Z position of first sensor in phi.
        double     nz       = z_layout.nz();                // Number of sensors to place in z.
        double     z_dr     = z_layout.dr();                // Radial displacement parameter, of every other sensor.
        Volume     m_env    = volumes[m_nam];
        DetElement lay_elt(sdet,_toString(x_layer.id(),"layer%d"),lay_id);
        Placements& waferVols = sensitives[m_nam];
        
        // Z increment for sensor placement along Z axis.
        // Adjust for z0 at center of sensor rather than
        // the end of cylindrical envelope.
        double z_incr   = nz > 1 ? (2.0 * z0) / (nz - 1) : 0.0;
        // Starting z for sensor placement along Z axis.
        double sensor_z = -z0;
        int module_idx =0;
        
        
        ZPlanarData::LayerLayout thisLayer ;
        
       
        // Loop over the number of sensors in phi.
        for (int ii = 0; ii < nphi; ii++)        {
            double dx = z_dr * std::cos(phic + phi_tilt);        // Delta x of sensor position.
            double dy = z_dr * std::sin(phic + phi_tilt);        // Delta y of sensor position.
            double  x = rc * std::cos(phic);                     // Basic x sensor position.
            double  y = rc * std::sin(phic);                     // Basic y sensor position.
            
            // Loop over the number of sensors in z.
            //Create stave FIXME disable for now
            string module_name = _toString(module_idx,"module%d");
            //       DetElement module_elt(lay_elt,module_name,module_idx);
            int sensor_idx = 0;
            
            for (int j = 0; j < nz; j++)          {
                string sensor_name = _toString(sensor_idx,"sensor%d");

		///////////////////

		//get cellID and fill map< cellID of surface, vector of cellID of neighbouring surfaces >

		//encoding

		encoder[lcio::LCTrackerCellID::layer()] = lay_id;
		encoder[lcio::LCTrackerCellID::module()] = module_idx;
		encoder[lcio::LCTrackerCellID::sensor()] = sensor_idx;

		dd4hep::long64 cellID = encoder.lowWord(); // 32 bits

		//compute neighbours 

		int n_neighbours_module = 1; // 1 gives the adjacent modules (i do not think we would like to change this)
		int n_neighbours_sensor = 1;

		int newmodule=0, newsensor=0;

		for(int imodule=-n_neighbours_module; imodule<=n_neighbours_module; imodule++){ // neighbouring modules
		  for(int isensor=-n_neighbours_sensor; isensor<=n_neighbours_sensor; isensor++){ // neighbouring sensors
		    
		    if (imodule==0 && isensor==0) continue; // cellID we started with
		    newmodule = module_idx + imodule;
		    newsensor = sensor_idx + isensor;

		    //compute special case at the boundary  
		    //general computation to allow (if necessary) more then adjacent neighbours (ie: +-2)
		    
		    if (newmodule < 0) newmodule = nphi + newmodule;
		    if (newmodule >= nphi) newmodule = newmodule - nphi;

		    if (newsensor < 0 || newsensor >= nz) continue; //out of the stave

		    //encoding
		    encoder[lcio::LCTrackerCellID::module()] = newmodule;
		    encoder[lcio::LCTrackerCellID::sensor()] = newsensor;
		    
		    neighbourSurfacesData->sameLayer[cellID].push_back(encoder.lowWord());

		  }
		}

		///////////////////

                
                //FIXME
                sensor_name = module_name + sensor_name;
                
                DetElement sens_elt(lay_elt,sensor_name,sensor_idx);
                // Module PhysicalVolume.
                Transform3D tr(RotationZYX(0,((M_PI/2)-phic-phi_tilt),-M_PI/2),Position(x,y,sensor_z));
                
                //FIXME
                pv = lay_vol.placeVolume(m_env,tr);
                pv.addPhysVolID(_U(module), module_idx);
                pv.addPhysVolID(_U(sensor), sensor_idx);
                sens_elt.setPlacement(pv);
                for(size_t ic=0; ic<waferVols.size(); ++ic)  {
//                     std::cout<<"Layer: "<<lay_id<<" phiIdx: "<<ii<<" zidx: "<<j<<" wafer idx: "<<ic<<std::endl;
                    PlacedVolume wafer_pv = waferVols[ic];
                    DetElement comp_elt(sens_elt,wafer_pv.volume().name(),sensor_idx);
                    comp_elt.setPlacement(wafer_pv);
                    
                    ///GET GEAR INFORMATION FROM FIRST "MODULE" IN Z AND phi
                    ///NOTE WORKS ONLY FOR ONE WAFER
                    if (ii==0 && j==0 && ic==0){
                      
                      Box mod_shape(m_env.solid()), comp_shape(wafer_pv.volume().solid());
                      
                      const double* trans = comp_elt.placement()->GetMatrix()->GetTranslation();
                      double half_module_thickness = mod_shape->GetDZ();
                      double half_silicon_thickness = comp_shape->GetDZ();
                      
                      double sensitive_z_position  = trans[2];
                      
                      double inner_thickness = half_module_thickness - sensitive_z_position;
                      
                      thisLayer.distanceSupport  = rc  ;
                     
                      thisLayer.offsetSupport    =  0; 
                      thisLayer.thicknessSupport = inner_thickness- half_silicon_thickness;
                      thisLayer.zHalfSupport    = z0 + mod_shape->GetDY();
                      thisLayer.widthSupport     = 2*mod_shape->GetDX(); 
                      
                      thisLayer.distanceSensitive = rc+sensitive_z_position; 
                      thisLayer.offsetSensitive  = 0. ;
                      thisLayer.thicknessSensitive = 2*half_silicon_thickness;//Assembled along Z
                      //Changed by Thorben Quast (same applies to zHalfSupport)
                      //z0 = center of most right sensor, comp_shape-GetDY() = half length of one sensitive are of the module
                      thisLayer.zHalfSensitive    = z0 + comp_shape->GetDY();
                      thisLayer.widthSensitive = 2*comp_shape->GetDX();
                      thisLayer.ladderNumber = (int) nphi  ;
                      thisLayer.phi0 =  phic;
                    }
                    
                }
                

                /// Increase counters etc.
                sensor_idx++;
                // Adjust the x and y coordinates of the sensor.
                x += dx;
                y += dy;
                // Flip sign of x and y adjustments.
                dx *= -1;
                dy *= -1;
                // Add z increment to get next z placement pos.
                sensor_z += z_incr;
            }
            module_idx++;
            phic     += phi_incr;      // Increment the phi placement of sensor.
            rc       += rphi_dr;       // Increment the center radius according to dr parameter.
            rphi_dr  *= -1;            // Flip sign of dr parameter.
            sensor_z  = -z0;           // Reset the Z placement parameter for sensor.
        }
        // Create the PhysicalVolume for the layer.
        pv = envelope.placeVolume(lay_vol); // Place layer in mother
        pv.addPhysVolID("layer", lay_id);       // Set the layer ID.
        lay_elt.setAttributes(theDetector,lay_vol,x_layer.regionStr(),x_layer.limitsStr(),x_layer.visStr());
        lay_elt.setPlacement(pv);
        
        zPlanarData->layers.push_back( thisLayer ) ;
        
    }
    sdet.setAttributes(theDetector,envelope,x_det.regionStr(),x_det.limitsStr(),x_det.visStr());
    sdet.addExtension< ZPlanarData >( zPlanarData ) ;
    sdet.addExtension< NeighbourSurfacesData >( neighbourSurfacesData ) ;
    
    //envelope.setVisAttributes(theDetector.invisible());
    /*pv = theDetector.pickMotherVolume(sdet).placeVolume(assembly);
     pv.addPhysVolID("system", det_id);      // Set the subdetector system ID.
     pv.addPhysVolID("barrel", 0);           // Flag this as a barrel subdetector.
     sdet.setPlacement(pv);*/
    return sdet;
}