-
Notifications
You must be signed in to change notification settings - Fork 61
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added a modified version of the Generic Cal Endcap without cutout
- Loading branch information
1 parent
3042e58
commit 8e54df1
Showing
1 changed file
with
253 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,253 @@ | ||
//==================================================================== | ||
// Modified Generic Endcap Driver for the CLIC detector | ||
//-------------------------------------------------------------------- | ||
// | ||
// Author : N.Nikiforou | ||
// Adapted from PolyhedraBarrel Calorimeter by M. Frank | ||
// Note: This driver supports conical inner shape in the endcap controlled by rmin and rmin2 | ||
// | ||
//==================================================================== | ||
#include "DD4hep/DetFactoryHelper.h" | ||
#include "XML/Layering.h" | ||
#include "XML/Utilities.h" | ||
#include "DDRec/DetectorData.h" | ||
#include "DDSegmentation/Segmentation.h" | ||
|
||
|
||
using namespace std; | ||
|
||
using dd4hep::BUILD_ENVELOPE; | ||
using dd4hep::DetElement; | ||
using dd4hep::Detector; | ||
using dd4hep::Layering; | ||
using dd4hep::Material; | ||
using dd4hep::PlacedVolume; | ||
using dd4hep::Cone; | ||
using dd4hep::PolyhedraRegular; | ||
using dd4hep::Position; | ||
using dd4hep::Readout; | ||
using dd4hep::Ref_t; | ||
using dd4hep::RotationZYX; | ||
using dd4hep::Segmentation; | ||
using dd4hep::SensitiveDetector; | ||
using dd4hep::SubtractionSolid; | ||
using dd4hep::Transform3D; | ||
using dd4hep::Volume; | ||
using dd4hep::_toString; | ||
|
||
using dd4hep::rec::LayeredCalorimeterData; | ||
|
||
// workaround for DD4hep v00-14 (and older) | ||
#ifndef DD4HEP_VERSION_GE | ||
#define DD4HEP_VERSION_GE(a,b) 0 | ||
#endif | ||
|
||
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(); | ||
// Second internal radius for the conical cutout | ||
double rmin2 = dim.hasAttr(_U(rmin2)) ? dim.rmin2() : rmin; | ||
|
||
Layering layering(x_det); | ||
double totalThickness = layering.totalThickness(); | ||
int n_layers = layering.layers().size(); | ||
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,0,rmax,totalThickness); | ||
Volume endcapVol("endcap",polyVolume,air); | ||
|
||
|
||
if(rmin2 != rmin){ | ||
Cone cutoutPolyVolume(totalThickness/1.99, 0,rmin, 0,rmin2); | ||
endcapVol=Volume("endcap", SubtractionSolid(polyVolume, cutoutPolyVolume, Position(0,0,0)), 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_rmin = x_layer.rmin(); | ||
|
||
std::cout<<"Number of layers in group "<<layerType<<" : "<<layer_repeat<<std::endl; | ||
|
||
Volume layer_vol(layer_type_name,PolyhedraRegular(nsides_outer,layer_rmin,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,layer_rmin,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; | ||
|
||
} | ||
|
||
DECLARE_DETELEMENT(GenericCalEndcap_o2_v01,create_detector) | ||
|