Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • EIC/detectors/athena
  • zwzhao/athena
  • FernandoTA/athena
  • palspeic/athena
4 results
Show changes
Showing
with 1422 additions and 235 deletions
<lccdd>
<display>
</display>
<define>
</define>
<documentation level="10">
### Silicon tracking configuration
</documentation>
<documentation level="5">
### Tracker subassemblies for ACTS
</documentation>
<detectors>
<detector id="VertexSubAssembly_0_ID"
name="VertexBarrelSubAssembly"
type="DD4hep_SubdetectorAssembly"
vis="TrackerSubAssemblyVis">
<composite name="VertexBarrel" />
</detector>
<detector id="TrackerSubAssembly_0_ID"
name="InnerTrackerSubAssembly"
type="DD4hep_SubdetectorAssembly"
vis="TrackerSubAssemblyVis">
<composite name="InnerTrackerEndcapN"/>
<composite name="InnerTrackerBarrel"/>
<composite name="InnerTrackerEndcapP"/>
</detector>
<detector id="TrackerSubAssembly_1_ID"
name="MedialTrackerSubAssembly"
type="DD4hep_SubdetectorAssembly"
vis="TrackerSubAssemblyVis">
<composite name="MedialTrackerEndcapN"/>
<composite name="MedialTrackerCompositeBarrel"/>
<composite name="MedialTrackerEndcapP"/>
</detector>
<detector id="TrackerSubAssembly_2_ID"
name="OuterTrackerSubAssembly"
type="DD4hep_SubdetectorAssembly"
vis="TrackerSubAssemblyVis">
<composite name="OuterTrackerCompositeEndcapN"/>
<composite name="OuterTrackerBarrel"/>
<composite name="OuterTrackerCompositeEndcapP"/>
</detector>
<!--
<detector id="TrackerSubAssembly_3_ID"
name="EcalBarrelSubAssembly"
type="DD4hep_SubdetectorAssembly"
vis="TrackerSubAssemblyVis">
</detector>
-->
<detector id="TrackerSubAssembly_4_ID"
name="ForwardBackwardTrackerSubAssembly"
type="DD4hep_SubdetectorAssembly"
vis="TrackerSubAssemblyVis">
<composite name="ForwardGEM"/>
<composite name="BackwardNullTracker"/>
</detector>
<detector id="TrackerCompositeBarrel_0_ID"
name="MedialTrackerCompositeBarrel"
type="athena_CompositeTracker"
actsType="barrel"
vis="TrackerSubAssemblyVis">
<position x="0*cm" y="0*cm" z="0*um" />
<composite name="MedialTrackerBarrel"/>
<composite name="BarrelTOF"/>
</detector>
<detector id="TrackerCompositeEndcapN_0_ID"
name="OuterTrackerCompositeEndcapN"
type="athena_CompositeTracker"
actsType="endcap"
vis="TrackerSubAssemblyVis">
<position x="0*cm" y="0*cm" z="-1*um" />
<composite name="OuterTrackerEndcapN"/>
<composite name="GEMEndcapN"/>
</detector>
<detector id="TrackerCompositeEndcapP_0_ID"
name="OuterTrackerCompositeEndcapP"
type="athena_CompositeTracker"
actsType="endcap"
vis="TrackerSubAssemblyVis">
<position x="0*cm" y="0*cm" z="0*cm" />
<composite name="OuterTrackerEndcapP"/>
<composite name="GEMEndcapP"/>
</detector>
<detector id="TrackerCompositeEndcapN_1_ID"
name="BackwardNullTracker"
type="athena_CompositeTracker"
actsType="endcap"
vis="TrackerSubAssemblyVis">
<position x="0*cm" y="0*cm" z="-1*um" />
</detector>
</detectors>
<documentation>
### Material map for ACTS
https://eicweb.phy.anl.gov/EIC/detectors/athena/-/issues/127
</documentation>
<plugins>
<plugin name="FileLoader">
<arg value="cache:$DETECTOR_PATH"/>
<arg value="file:calibrations/materials-map.cbor"/>
<arg value="url:https://eicweb.phy.anl.gov/EIC/detectors/athena/uploads/4a4e7c8eb6089b634d762d112c89bd5d/material-maps.cbor"/>
</plugin>
</plugins>
<include ref="vertex_tracker_3layers.xml"/>
<include ref="central_tracker_hybrid_v2.xml"/>
</lccdd>
......@@ -60,32 +60,29 @@
<lines sector="2" mirrorx="true" mirrory="true">
<module sizex="GlassModule_sx" sizey="GlassModule_sy" sizez="GlassModule_sz" material="PbGlass" vis="EcalEndcapNModuleVis"/>
<wrapper thickness="GlassModule_wrap" material="Epoxy" vis="InvisibleWithDaughters"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*1/2." z="GlassModule_z0" begin="13" nmods="13"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*3/2." z="GlassModule_z0" begin="13" nmods="13"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*5/2." z="GlassModule_z0" begin="13" nmods="13"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*7/2." z="GlassModule_z0" begin="12" nmods="14"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*9/2." z="GlassModule_z0" begin="12" nmods="14"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*11/2." z="GlassModule_z0" begin="12" nmods="14"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*13/2." z="GlassModule_z0" begin="11" nmods="15"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*15/2." z="GlassModule_z0" begin="10" nmods="15"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*17/2." z="GlassModule_z0" begin="9" nmods="15"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*19/2." z="GlassModule_z0" begin="8" nmods="16"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*21/2." z="GlassModule_z0" begin="7" nmods="16"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*23/2." z="GlassModule_z0" begin="6" nmods="17"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*25/2." z="GlassModule_z0" begin="3" nmods="19"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*27/2." z="GlassModule_z0" begin="0" nmods="22"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*29/2." z="GlassModule_z0" begin="0" nmods="21"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*31/2." z="GlassModule_z0" begin="0" nmods="20"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*33/2." z="GlassModule_z0" begin="0" nmods="20"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*35/2." z="GlassModule_z0" begin="0" nmods="19"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*37/2." z="GlassModule_z0" begin="0" nmods="19"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*39/2." z="GlassModule_z0" begin="0" nmods="17"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*41/2." z="GlassModule_z0" begin="0" nmods="15"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*43/2." z="GlassModule_z0" begin="0" nmods="14"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*45/2." z="GlassModule_z0" begin="0" nmods="12"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*47/2." z="GlassModule_z0" begin="0" nmods="10"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*49/2." z="GlassModule_z0" begin="0" nmods="8"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*51/2." z="GlassModule_z0" begin="0" nmods="7"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*1/2." z="GlassModule_z0" begin="13" nmods="10"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*3/2." z="GlassModule_z0" begin="13" nmods="10"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*5/2." z="GlassModule_z0" begin="13" nmods="10"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*7/2." z="GlassModule_z0" begin="12" nmods="10"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*9/2." z="GlassModule_z0" begin="12" nmods="10"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*11/2." z="GlassModule_z0" begin="12" nmods="10"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*13/2." z="GlassModule_z0" begin="11" nmods="11"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*15/2." z="GlassModule_z0" begin="10" nmods="11"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*17/2." z="GlassModule_z0" begin="9" nmods="12"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*19/2." z="GlassModule_z0" begin="8" nmods="13"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*21/2." z="GlassModule_z0" begin="7" nmods="13"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*23/2." z="GlassModule_z0" begin="6" nmods="14"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*25/2." z="GlassModule_z0" begin="3" nmods="16"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*27/2." z="GlassModule_z0" begin="0" nmods="18"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*29/2." z="GlassModule_z0" begin="0" nmods="18"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*31/2." z="GlassModule_z0" begin="0" nmods="16"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*33/2." z="GlassModule_z0" begin="0" nmods="16"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*35/2." z="GlassModule_z0" begin="0" nmods="14"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*37/2." z="GlassModule_z0" begin="0" nmods="13"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*39/2." z="GlassModule_z0" begin="0" nmods="11"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*41/2." z="GlassModule_z0" begin="0" nmods="10"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*43/2." z="GlassModule_z0" begin="0" nmods="7"/>
<line axis="x" x="GlassModule_dx/2." y="GlassModule_dy*45/2." z="GlassModule_z0" begin="0" nmods="3"/>
</lines>
</placements>
</detector>
......
......@@ -32,7 +32,7 @@
<constant name="EcalBarrel_ModRepeat" value="CaloSides"/>
<constant name="EcalBarrel_ModLength" value="0.5*m"/>
<constant name="EcalBarrel_ModWidth" value="0.5*m"/>
<constant name="EcalBarrel_AvailThickness" value="EcalBarrel_TotalThickness-EcalBarrel_Support_thickness"/>
<constant name="EcalBarrel_AvailThickness" value="EcalBarrelEnvelope_thickness-EcalBarrel_Support_thickness"/>
<constant name="EcalBarrel_ImagingLayerThickness"
value="EcalBarrel_SiliconThickness
+ EcalBarrel_ElectronicsThickness
......
<lccdd>
<define>
<constant name="EcalEndcapP_rmax" value="Solenoid_rmax "/>
</define>
......
<lccdd>
<comment> MRICH (alternative design) </comment>
<define>
<constant name="MRICH_rmin" value="10*cm"/>
<constant name="MRICH_rmax" value="BackwardPIDRegion_rmax"/>
<constant name="MRICH_length" value="BackwardPIDRegion_length"/>
<constant name="MRICH_zmin" value="BackwardPIDRegion_zmin"/>
<constant name="MRICHAerogel_thickness" value="30.0*mm"/>
<constant name="MRICHAerogel_width" value="126.5*mm"/>
<constant name="MRICHFoam_thickness" value="2*mm"/>
<constant name="MRICHFresnelLens_thickness" value="0.06*inch"/>
<constant name="MRICHAerogelLensGap_thickness" value="2*mm"/>
<constant name="MRICHPhotoDet_thickness" value="1.5*mm"/>
<constant name="MRICHPhotoDet_length" value="48.5*mm"/>
<constant name="MRICHGlassWindow_width" value="103.5*mm"/>
<constant name="MRICHGlassPhotoDet_thickness" value="5.0*mm"/>
<constant name="MRICHPhotoDetMCPlate_thickness" value="0.3*mm"/> <!-- FIXME: should be 1.2*mm with PyrexGlass25 -->
<constant name="MRICHPhotoDetAnode_thickness" value="3.8*mm"/>
<constant name="MRICHPhotoDetPCB_thickness" value="2.0*mm"/>
<constant name="MRICHPhotoDetCopper_thickness" value="0.1*mm"/>
<constant name="MRICHPhotoDetKapton_thickness" value="0.2*mm"/>
<constant name="MRICHRearExtraSpace_thickness" value="0.3*mm"/>
<constant name="MRICHLensPhotoDet_length" value="136.4*mm"/>
<constant name="MRICHFresnelLensEffectiveDiameter" value="6.0*inch"/>
<constant name="MRICHFresnelLensGroove_pitch" value="inch/125"/>
<constant name="MRICHCarbonFrame_thickness" value="1.0*mm"/>
<constant name="MRICHCarbonFrame_width" value="MRICHAerogel_width+2.0*MRICHFoam_thickness + 2.0*MRICHCarbonFrame_thickness"/>
<constant name="MRICHModules_nx" value="floor((MRICH_rmax-MRICH_rmin)/MRICHCarbonFrame_width)"/>
<constant name="MRICHModules_ny" value="floor((MRICH_rmax-MRICH_rmin)/MRICHCarbonFrame_width)"/>
<constant name="MRICHCarbonFrame_length"
value="MRICHAerogel_thickness
+ 2.0*MRICHCarbonFrame_thickness
+ 2.0*MRICHFoam_thickness
+ MRICHAerogelLensGap_thickness
+ MRICHFresnelLens_thickness
+ MRICHLensPhotoDet_length
+ MRICHGlassPhotoDet_thickness
+ 2.0*MRICHPhotoDetMCPlate_thickness
+ MRICHPhotoDetAnode_thickness
+ MRICHPhotoDetPCB_thickness
+ MRICHPhotoDetCopper_thickness
+ MRICHPhotoDetKapton_thickness
+ MRICHRearExtraSpace_thickness "/>
</define>
<limits>
</limits>
<regions>
</regions>
<display>
</display>
<detectors>
<detector id="MRICH_ID" name="MRICH" type="athena_MRICH"
readout="MRICHHits"
reflect="true"
projective="false"
vis="InvisibleWithDaughters"
material="Air">
<dimensions rmin="MRICH_rmin" rmax="MRICH_rmax" length="abs(MRICH_length)" zmin="MRICH_zmin"/>
<envelope thickness="MRICHCarbonFrame_thickness" material="CarbonFiber"/>
<module name="MRICH_module1"
vis="InvisibleWithDaughters"
width="MRICHCarbonFrame_width"
height="MRICHCarbonFrame_width"
length="MRICHCarbonFrame_length">
<aerogel vis="MRICH_aerogel_vis"
length="MRICHAerogel_thickness"
width="MRICHAerogel_width"
material="AerogelOptical">
<frame vis="MRICH_frame_vis" thickness="MRICHFoam_thickness" material="PolystyreneFoam" />
</aerogel>
<lens vis="MRICH_lens_vis" thickness="MRICHFresnelLens_thickness"
pitch="MRICHFresnelLensGroove_pitch" focal_length="6.0*inch"
effective_diameter="MRICHFresnelLensEffectiveDiameter"
width="MRICHAerogel_width"
material="AcrylicOptical"/>
<space thickness="MRICHLensPhotoDet_length"/>
<photodet width="MRICHGlassWindow_width" thickness="MRICHGlassPhotoDet_thickness" material="PyrexGlassOptical">
<sensor nx="2" ny="2" thickness="MRICHPhotoDet_thickness" width="MRICHPhotoDet_length" material="SiliconOxide"/>
<layer thickness="MRICHPhotoDetMCPlate_thickness" material="PyrexGlass"/> <!-- FIXME: should be PyrexGlass25 with 1.2*mm thickness -->
<layer thickness="MRICHPhotoDetMCPlate_thickness" material="PyrexGlass"/> <!-- FIXME: should be PyrexGlass25 with 1.2*mm thickness -->
<layer thickness="MRICHPhotoDetAnode_thickness" material="AluminumOxide"/>
<layer thickness="MRICHPhotoDetPCB_thickness" material="Fr4"/>
<layer thickness="MRICHPhotoDetCopper_thickness" material="Copper"/>
<layer thickness="MRICHPhotoDetKapton_thickness" material="Kapton"/>
</photodet>
</module>
</detector>
</detectors>
<readouts>
<readout name="MRICHHits">
<segmentation type="CartesianGridXY" grid_size_x="3*mm" grid_size_y="3*mm" />
<id>system:8,module:14,sensor:8,x:32:-16,y:-16</id>
</readout>
</readouts>
<!--Globals>
<Parameter Name="mrichInfo" Value="mrichmod/mrich_1_geoparams-0-0-4294967295-1527211159.xml"/>
</Globals-->
</lccdd>
......@@ -5,8 +5,8 @@
THis value probably can live in the file that includes this one.
</comment>
<constant name="ITS3Thickness" value="40*um"/>
<constant name="TrackerCarbon_thickness" value="0.12*mm"/>
<constant name="TrackerEndcapAluminum_thickness" value="0.15*mm"/>
<constant name="VertexCarbon_thickness" value="0.12*mm"/>
<constant name="VertexEndcapAluminumThickness" value="0.15*mm"/>
<documentation>
#### Vertex Tracker Barrel Parameters
......@@ -27,7 +27,14 @@ Simple carbon fiber support shell.
</documentation>
<constant name="VertexBarrel_length" value="VertexTrackerBarrel_length"/>
<constant name="VertexBarrel_length" value="300.0*mm"/>
<constant name="VertexTrackerEndcapP_rmin" value="VertexTrackingRegion_rmin"/>
<constant name="VertexTrackerEndcapN_rmin" value="VertexTrackingRegion_rmin"/>
<constant name="VertexTrackerEndcapP_rmax" value="VertexTrackingRegion_rmax"/>
<constant name="VertexTrackerEndcapN_rmax" value="VertexTrackingRegion_rmax"/>
<constant name="VertexTrackerEndcapP_zmax" value="VertexTrackingRegionP_zmax"/>
<constant name="VertexTrackerEndcapN_zmax" value="VertexTrackingRegionN_zmax"/>
<constant name="VertexBarrelLayer_length" value="VertexBarrel_length - 1*mm"/>
<constant name="VertexBarrelMod_length" value="VertexBarrel_length - 2*mm"/>
......@@ -54,19 +61,36 @@ Simple carbon fiber support shell.
<constant name="VertexBarrelSupport_rmax" value="VertexBarrelSupport_rmin + VertexBarrelSupport_thickness"/>
<constant name="VertexBarrelSupport_length" value="VertexBarrelLayer_length"/>
<constant name="VertexTrackerEndcapN_zmin" value="VertexTrackerBarrel_zmax"/>
<constant name="VertexTrackerEndcapP_zmin" value="VertexTrackerBarrel_zmax"/>
<constant name="VertexTrackerEndcapN_zmin" value="25*cm"/>
<constant name="VertexTrackerEndcapP_zmin" value="25*cm"/>
<constant name="VertexEndcap_NLayers" value="1"/>
<constant name="VertexTrackerEndcap_delta" value="(VertexTrackerEndcapP_zmax - VertexTrackerEndcapP_zmin)/VertexEndcap_NLayers"/>
<constant name="VertexEndcapLayer_dz" value="(VertexTrackerEndcapP_zmax - VertexTrackerEndcapP_zmin)/VertexEndcap_NLayers"/>
<constant name="VertexEndcapLayer_thickness" value="min(5*cm,VertexEndcapLayer_dz)"/>
<constant name="VertexEndcapLayer_dz" value="2*cm"/>
<constant name="VertexEndcapLayer_thickness" value="min(3*cm,VertexEndcapLayer_dz-0.5*cm)"/>
<constant name="VertexEndcapModOpeningAngle" value="30.0*degree"/>
<constant name="VertexEndcap_NModules" value="12"/>
<constant name="VertexEndcapMod_dz" value="2.5*mm"/>
<constant name="VertexEndcapModOpeningAngle" value="360.0/VertexEndcap_NModules*degree + 0.5*degree"/>
<constant name="VertexEndcapMod1_x1" value="2.0*VertexTrackerEndcapP_rmin*sin(VertexEndcapModOpeningAngle/2.0)"/>
<constant name="VertexEndcapMod1_x2" value="2.0*VertexTrackerEndcapP_rmax*sin(VertexEndcapModOpeningAngle/2.0)"/>
<constant name="VertexEndcapMod1_y" value="VertexTrackerEndcapP_rmax*cos(VertexEndcapModOpeningAngle/2.0) - VertexTrackerEndcapP_rmin"/>
<comment> cone connecting vertex barrel to endcap </comment>
<!-- <constant name="VertexEndcapCone_zmax" value="VertexEndcapShell_zmin-0.2*cm"/> -->
<constant name="VertexSupportCarbon_thickness" value="2*mm"/>
<constant name="VertexEndcapCone_zmin" value="VertexBarrelLayer_length/2.0 + 0.1*cm"/>
<constant name="VertexEndcapCone_zmax" value="VertexTrackerEndcapN_zmin - 0.1*cm"/>
<constant name="VertexEndcapCone_rmin1" value="VertexEndcapCone_zmin * 36.26/49"/>
<!-- <constant name="VertexEndcapCone_rmin1" value="TrackerEndcapInner_rmax1"/> -->
<constant name="VertexEndcapCone_rmin2" value="VertexTrackerEndcapP_rmax"/>
<constant name="VertexEndcapConeService_rmin1" value="VertexEndcapCone_rmin1+VertexSupportCarbon_thickness+0.1*mm"/>
<constant name="VertexEndcapConeService_rmin2" value="VertexEndcapCone_rmin2+VertexSupportCarbon_thickness+0.1*mm"/>
<constant name="VertexEndcapConeService_thickness" value="0.6*mm"/>
<constant name="VertexEndcapCone_length" value="VertexEndcapCone_zmax - VertexEndcapCone_zmin"/>
<comment>
Extra parameters to approximate a cylinder as a set of skinny staves
due to ACTS limitations.
......@@ -81,8 +105,11 @@ Simple carbon fiber support shell.
</display>
<detectors>
<documentation level="5">
### Actual detectors
</documentation>
<detector
id="VertexBarrel_ID"
id="VertexBarrel_0_ID"
name="VertexBarrel"
type="athena_VertexBarrel"
readout="VertexBarrelHits"
......@@ -113,11 +140,11 @@ Simple carbon fiber support shell.
<module name="SupportShell" vis="VertexSupportVis">
<module_component name="CF Shell"
material="CarbonFiber"
sensitive="true"
sensitive="false"
width="VertexBarrelShellStave_width"
length="VertexBarrelShell_length"
thickness="VertexBarrelShell_thickness"
vis="VertexLayerVis" />
vis="VertexSupportVis" />
</module>
<comment> Layers composed of many arrayed modules </comment>
<layer module="Module1" id="1" vis="VertexLayerVis">
......@@ -125,6 +152,7 @@ Simple carbon fiber support shell.
inner_r="VertexBarrelLayer_rmin1"
outer_r="VertexBarrelLayer_rmax1"
z_length="VertexBarrelLayer_length" />
<layer_material surface="outer" binning="binPhi,binZ" bins0="VertexBarrelStave_count" bins1="100" />
<comment>
phi0 : Starting phi of first module.
phi_tilt : Phi tilt of a module.
......@@ -143,6 +171,7 @@ Simple carbon fiber support shell.
inner_r="VertexBarrelLayer_rmin2"
outer_r="VertexBarrelLayer_rmax2"
z_length="VertexBarrelLayer_length" />
<layer_material surface="outer" binning="binPhi,binZ" bins0="VertexBarrelStave_count" bins1="100" />
<rphi_layout phi_tilt="0.0*degree" nphi="VertexBarrelStave_count" phi0="0.0" rc="VertexBarrelMod2_rmin" dr="0.0 * mm"/>
<z_layout dr="0.0 * mm" z0="0.0 * mm" nz="1"/>
</layer>
......@@ -151,126 +180,106 @@ Simple carbon fiber support shell.
inner_r="VertexBarrelSupport_rmin"
outer_r="VertexBarrelSupport_rmax"
z_length="VertexBarrelSupport_length" />
<layer_material surface="outer" binning="binPhi,binZ" bins0="VertexBarrelStave_count" bins1="100" />
<rphi_layout phi_tilt="0.0*degree" nphi="VertexBarrelStave_count" phi0="0.0" rc="VertexBarrelShell_rmin" dr="0.0 * mm"/>
<z_layout dr="0.0 * mm" z0="0.0 * mm" nz="1"/>
</layer>
</detector>
<detector
id="VertexEndcapP_ID"
id="VertexEndcapP_0_ID"
name="VertexEndcapP"
type="athena_TrapEndcapTracker"
readout="VertexEndcapHits"
vis="AnlRed"
vis="TrackerVis"
reflect="false">
<support material="CarbonFiber" name="sup_cone" vis="TrackerSupportVis">
<shape type="Cone"
rmin1="VertexEndcapCone_rmin1" rmax1="VertexEndcapCone_rmin1+VertexSupportCarbon_thickness"
rmin2="VertexEndcapCone_rmin2" rmax2="VertexEndcapCone_rmin2+VertexSupportCarbon_thickness" z="VertexEndcapCone_length/2.0"/>
<position x="0*cm" y="0*cm" z="(VertexEndcapCone_zmin+VertexEndcapCone_zmax)/2.0"/>
</support>
<support material="Aluminum" name="sup_cone_service" vis="TrackerSupportVis">
<shape type="Cone"
rmin1="VertexEndcapConeService_rmin1" rmax1="VertexEndcapConeService_rmin1+VertexEndcapConeService_thickness"
rmin2="VertexEndcapConeService_rmin2" rmax2="VertexEndcapConeService_rmin2+VertexEndcapConeService_thickness" z="VertexEndcapCone_length/2.0"/>
<position x="0*cm" y="0*cm" z="(VertexEndcapCone_zmin+VertexEndcapCone_zmax)/2.0"/>
</support>
<module name="Module1" vis="AnlProcess_Blue">
<trd x1="VertexEndcapMod1_x1/2.0" x2="VertexEndcapMod1_x2/2.0" z="VertexEndcapMod1_y/2"/>
<module_component thickness="ITS3Thickness" material="Silicon" sensitive="true"/>
<module_component thickness="TrackerEndcapAluminum_thickness" material="Aluminum"/>
<module_component thickness="TrackerCarbon_thickness" material="CarbonFiber"/>
<module_component thickness="VertexEndcapAluminumThickness" material="Aluminum"/>
<module_component thickness="VertexCarbon_thickness" material="CarbonFiber"/>
</module>
<layer id="1">
<envelope vis="AnlRed"
<envelope vis="TrackerVis"
rmin="VertexTrackerEndcapP_rmin"
rmax="VertexTrackerEndcapP_rmax"
length="VertexEndcapLayer_thickness"
zstart="VertexTrackerEndcapP_zmin + VertexEndcapLayer_dz/2.0" />
<ring vis="AnlRed"
<layer_material surface="representing" binning="binPhi,binR" bins0="20*VertexEndcap_NModules" bins1="256"/>
<ring vis="TrackerVis"
r="VertexTrackerEndcapP_rmin+VertexEndcapMod1_y/2.0"
zstart="0.0"
nmodules="12" dz="2.5 * mm" module="Module1" />
nmodules="VertexEndcap_NModules" dz="VertexEndcapMod_dz" module="Module1" />
</layer>
</detector>
<detector
id="VertexEndcapN_ID"
id="VertexEndcapN_0_ID"
name="VertexEndcapN"
type="athena_TrapEndcapTracker"
readout="VertexEndcapHits"
vis="AnlRed"
vis="TrackerVis"
reflect="true">
<support material="CarbonFiber" name="sup_cone" vis="TrackerSupportVis">
<shape type="Cone"
rmin2="VertexEndcapCone_rmin1" rmax2="VertexEndcapCone_rmin1+VertexSupportCarbon_thickness"
rmin1="VertexEndcapCone_rmin2" rmax1="VertexEndcapCone_rmin2+VertexSupportCarbon_thickness" z="VertexEndcapCone_length/2.0"/>
<position x="0*cm" y="0*cm" z="-1.0*(VertexEndcapCone_zmin+VertexEndcapCone_zmax)/2.0"/>
</support>
<support material="Aluminum" name="sup_cone_service" vis="TrackerSupportVis">
<shape type="Cone"
rmin2="VertexEndcapConeService_rmin1" rmax2="VertexEndcapConeService_rmin1+VertexEndcapConeService_thickness"
rmin1="VertexEndcapConeService_rmin2" rmax1="VertexEndcapConeService_rmin2+VertexEndcapConeService_thickness" z="VertexEndcapCone_length/2.0"/>
<position x="0*cm" y="0*cm" z="-1.0*(VertexEndcapCone_zmin+VertexEndcapCone_zmax)/2.0"/>
</support>
<module name="Module1" vis="AnlProcess_Blue">
<trd x1="VertexEndcapMod1_x1/2.0" x2="VertexEndcapMod1_x2/2.0" z="VertexEndcapMod1_y/2"/>
<module_component thickness="ITS3Thickness" material="Silicon" sensitive="true"/>
<module_component thickness="TrackerEndcapAluminum_thickness" material="Aluminum"/>
<module_component thickness="TrackerCarbon_thickness" material="CarbonFiber"/>
<module_component thickness="VertexEndcapAluminumThickness" material="Aluminum"/>
<module_component thickness="VertexCarbon_thickness" material="CarbonFiber"/>
</module>
<layer id="1">
<envelope vis="AnlRed"
<envelope vis="TrackerVis"
rmin="VertexTrackerEndcapN_rmin"
rmax="VertexTrackerEndcapN_rmax"
length="VertexEndcapLayer_thickness"
zstart="VertexTrackerEndcapN_zmin + VertexEndcapLayer_dz/2.0" />
<ring vis="AnlRed"
<layer_material surface="representing" binning="binPhi,binR" bins0="20*VertexEndcap_NModules" bins1="256"/>
<ring vis="TrackerVis"
r="VertexTrackerEndcapN_rmin+VertexEndcapMod1_y/2.0"
zstart="0.0"
nmodules="12" dz="2.5 * mm" module="Module1" />
nmodules="VertexEndcap_NModules" dz="VertexEndcapMod_dz" module="Module1" />
</layer>
</detector>
<!--
<detector id="VertexEndcapP_ID"
name="VertexEndcapP"
type="athena_SimpleDiskTracker"
readout="VertexEndcapHits"
insideTrackingVolume="true"
reflect="false" vis="AnlRed">
<position x="0" y="0" z="0.0*mm"/>
<layer id="1" vis="AnlOrange"
inner_z="VertexTrackerEndcapP_zmin + 0.5*VertexTrackerEndcap_delta"
inner_r="VertexTrackerEndcapP_rmin-3*mm"
outer_r="VertexTrackerEndcapP_rmax">
<slice material="Air" thickness="1.0*mm" vis="AnlOrange" />
<slice material="Silicon" thickness="1.0*mm" vis="AnlOrange" sensitive="true"/>
<slice material="Air" thickness="1.0*mm" vis="AnlOrange" />
</layer>
<layer id="2" vis="AnlOrange"
inner_z="VertexTrackerEndcapP_zmin + 1.5*VertexTrackerEndcap_delta"
inner_r="VertexTrackerEndcapP_rmin"
outer_r="VertexTrackerEndcapP_rmax">
<slice material="Air" thickness="1.0*mm" vis="AnlOrange" />
<slice material="Silicon" thickness="1.0*mm" vis="AnlOrange" sensitive="true"/>
<slice material="Air" thickness="1.0*mm" vis="AnlOrange" />
</layer>
</detector>
<detector id="VertexEndcapN_ID"
name="VertexEndcapN"
type="athena_SimpleDiskTracker"
readout="VertexEndcapHits"
insideTrackingVolume="true"
reflect="true" vis="AnlRed">
<position x="0" y="0" z="-0.0*mm-1.0e-9*mm"/>
<layer id="1" vis="AnlOrange"
inner_z="VertexTrackerEndcapN_zmin + 0.5*VertexTrackerEndcap_delta"
inner_r="VertexTrackerEndcapN_rmin"
outer_r="VertexTrackerEndcapN_rmax">
<slice material="Air" thickness="1.0*mm" vis="AnlOrange" />
<slice material="Silicon" thickness="1.0*mm" vis="AnlOrange" sensitive="true"/>
<slice material="Air" thickness="1.0*mm" vis="AnlOrange" />
</layer>
<layer id="2" vis="AnlOrange"
inner_z="VertexTrackerEndcapN_zmin + 1.5*VertexTrackerEndcap_delta"
inner_r="VertexTrackerEndcapN_rmin"
outer_r="VertexTrackerEndcapN_rmax">
<slice material="Air" thickness="1.0*mm" vis="AnlOrange" />
<slice material="Silicon" thickness="1.0*mm" vis="AnlOrange" sensitive="true"/>
<slice material="Air" thickness="1.0*mm" vis="AnlOrange" />
</layer>
</detector>
-->
</detectors>
<readouts>
<readout name="VertexBarrelHits">
<segmentation type="CartesianGridXY" grid_size_x="0.010*mm" grid_size_y="0.010*mm" />
<id>system:8,barrel:2,layer:4,module:12,sensor:2,x:32:-16,y:-16</id>
<id>system:8,layer:4,module:12,sensor:2,x:32:-16,y:-16</id>
</readout>
<readout name="VertexEndcapHits">
<segmentation type="CartesianGridXZ" grid_size_x="0.20*mm" grid_size_z="0.20*mm" />
<id>system:8,barrel:2,layer:4,module:12,sensor:2,x:32:-16,z:-16</id>
<segmentation type="CartesianGridXZ" grid_size_x="0.010*mm" grid_size_z="0.010*mm" />
<id>system:8,layer:4,module:12,sensor:2,x:32:-16,z:-16</id>
</readout>
</readouts>
......
<?xml version="1.0" encoding="UTF-8"?>
<lccdd>
<define>
<comment>
Main parameters
</comment>
<constant name="SiVertexSensor_thickness" value="40*um"/>
<constant name="VertexBarrelMod_length" value="280.0*mm"/>
<constant name="VertexBarrelMod_rmin" value="3.3*cm"/>
<constant name="VertexBarrelMod_offset" value="1.05*cm"/>
<constant name="VertexBarrelMod_count" value="3"/>
<constant name="VertexBarrelShell_thickness" value="300.0*um"/>
<documentation>
#### Vertex Tracker Barrel Parameters
- The sensor modules are 2 half-cylinders.
- There are 2 sensitive layers
- Each sensor has a thickness is 40um
- There is an outer shell for structural support 300um thick.
- The ID of this shell is set (arbitrarily) to 10 cm.
##### Sensor layers
Currently there are 2 sensor layers. Each is composed of 2 half-cylinders modules with only 40um of silicon thickness.
##### Support shell
Simple carbon fiber support shell.
</documentation>
<constant name="VertexBarrelEnvelope_length" value="VertexTrackingRegion_length"/>
<constant name="VertexBarrelLayer_length" value="VertexBarrelMod_length + 1*um"/>
<constant name="VertexBarrelLayer_thickness" value="0.2*cm"/>
<constant name="VertexBarrelMod_thickness" value="0.1*cm"/>
<constant name="VertexBarrelMod1_rmin" value="VertexBarrelMod_rmin"/>
<constant name="VertexBarrelMod2_rmin" value="VertexBarrelMod_rmin + 1 * VertexBarrelMod_offset"/>
<constant name="VertexBarrelMod3_rmin" value="VertexBarrelMod_rmin + 2 * VertexBarrelMod_offset"/>
<constant name="VertexBarrelLayer1_rmin" value="VertexBarrelMod_rmin - VertexBarrelLayer_thickness/2.0"/>
<constant name="VertexBarrelLayer1_rmax" value="VertexBarrelLayer1_rmin + VertexBarrelLayer_thickness"/>
<constant name="VertexBarrelLayer2_rmin" value="VertexBarrelLayer1_rmin + 1 * VertexBarrelMod_offset"/>
<constant name="VertexBarrelLayer2_rmax" value="VertexBarrelLayer2_rmin + VertexBarrelLayer_thickness"/>
<constant name="VertexBarrelLayer3_rmin" value="VertexBarrelLayer1_rmin + 2 * VertexBarrelMod_offset"/>
<constant name="VertexBarrelLayer3_rmax" value="VertexBarrelLayer3_rmin + VertexBarrelLayer_thickness"/>
<comment>
"Support" is to "shell" like "layer" is to "module", and is need for the flat stave barrel implementation.
</comment>
<constant name="VertexBarrelShell_rmin" value="VertexBarrelMod_rmin + VertexBarrelMod_count * VertexBarrelMod_offset"/>
<constant name="VertexBarrelShell_rmax" value="VertexBarrelShell_rmin + VertexBarrelShell_thickness"/>
<constant name="VertexBarrelShell_length" value="VertexBarrelMod_length"/>
<constant name="VertexBarrelSupport_thickness" value="0.1*cm"/>
<constant name="VertexBarrelSupport_rmin" value="VertexBarrelShell_rmin-VertexBarrelSupport_thickness/2.0"/>
<constant name="VertexBarrelSupport_rmax" value="VertexBarrelSupport_rmin + VertexBarrelSupport_thickness"/>
<constant name="VertexBarrelSupport_length" value="VertexBarrelLayer_length"/>
<comment>
Extra parameters to approximate a cylinder as a set of skinny staves
due to ACTS limitations.
</comment>
<constant name="VertexBarrelStave_count" value="128"/>
<constant name="VertexBarrelStave1_width" value="2*VertexBarrelMod1_rmin * tan(180*degree/VertexBarrelStave_count)"/>
<constant name="VertexBarrelStave2_width" value="2*VertexBarrelMod2_rmin * tan(180*degree/VertexBarrelStave_count)"/>
<constant name="VertexBarrelStave3_width" value="2*VertexBarrelMod3_rmin * tan(180*degree/VertexBarrelStave_count)"/>
<constant name="VertexBarrelShellStave_width" value="2*VertexBarrelShell_rmin * tan(180*degree/VertexBarrelStave_count)"/>
</define>
<display>
</display>
<detectors>
<documentation level="5">
### Actual detectors
</documentation>
<detector
id="VertexBarrel_0_ID"
name="VertexBarrel"
type="athena_VertexBarrel"
readout="VertexBarrelHits"
insideTrackingVolume="true">
<dimensions
rmin="VertexBarrelLayer1_rmin"
rmax="VertexBarrelSupport_rmax"
length="VertexBarrelEnvelope_length" />
<comment>Vertex Barrel Modules</comment>
<module name="Module1" vis="VertexLayerVis">
<module_component name="ITS3"
material="Silicon"
sensitive="true"
width="VertexBarrelStave1_width"
length="VertexBarrelMod_length"
thickness="SiVertexSensor_thickness"
vis="VertexLayerVis" />
</module>
<module name="Module2" vis="VertexLayerVis">
<module_component name="ITS3"
material="Silicon"
sensitive="true"
width="VertexBarrelStave2_width"
length="VertexBarrelMod_length"
thickness="SiVertexSensor_thickness"
vis="VertexLayerVis" />
</module>
<module name="Module3" vis="VertexLayerVis">
<module_component name="ITS3"
material="Silicon"
sensitive="true"
width="VertexBarrelStave3_width"
length="VertexBarrelMod_length"
thickness="SiVertexSensor_thickness"
vis="VertexLayerVis" />
</module>
<module name="SupportShell" vis="VertexSupportVis">
<module_component name="CF Shell"
material="CarbonFiber"
sensitive="false"
width="VertexBarrelShellStave_width"
length="VertexBarrelShell_length"
thickness="VertexBarrelShell_thickness"
vis="VertexSupportVis" />
</module>
<comment> Layers composed of many arrayed modules </comment>
<layer module="Module1" id="1" vis="VertexLayerVis">
<barrel_envelope
inner_r="VertexBarrelLayer1_rmin"
outer_r="VertexBarrelLayer1_rmax"
z_length="VertexBarrelLayer_length" />
<layer_material surface="outer" binning="binPhi,binZ" bins0="VertexBarrelStave_count" bins1="100" />
<comment>
phi0 : Starting phi of first module.
phi_tilt : Phi tilt of a module.
rc : Radius of the module center.
nphi : Number of modules in phi.
rphi_dr : The delta radius of every other module.
z0 : Z position of first module in phi.
nz : Number of modules to place in z.
dr : Radial displacement parameter, of every other module.
</comment>
<rphi_layout phi_tilt="0.0*degree" nphi="VertexBarrelStave_count" phi0="0.0" rc="VertexBarrelMod1_rmin" dr="0.0 * mm"/>
<z_layout dr="0.0 * mm" z0="0.0 * mm" nz="1"/>
</layer>
<layer module="Module2" id="2" vis="VertexLayerVis">
<barrel_envelope
inner_r="VertexBarrelLayer2_rmin"
outer_r="VertexBarrelLayer2_rmax"
z_length="VertexBarrelLayer_length" />
<layer_material surface="outer" binning="binPhi,binZ" bins0="VertexBarrelStave_count" bins1="100" />
<rphi_layout phi_tilt="0.0*degree" nphi="VertexBarrelStave_count" phi0="0.0" rc="VertexBarrelMod2_rmin" dr="0.0 * mm"/>
<z_layout dr="0.0 * mm" z0="0.0 * mm" nz="1"/>
</layer>
<layer module="Module3" id="3" vis="VertexLayerVis">
<barrel_envelope
inner_r="VertexBarrelLayer3_rmin"
outer_r="VertexBarrelLayer3_rmax"
z_length="VertexBarrelLayer_length" />
<layer_material surface="outer" binning="binPhi,binZ" bins0="VertexBarrelStave_count" bins1="100" />
<rphi_layout phi_tilt="0.0*degree" nphi="VertexBarrelStave_count" phi0="0.0" rc="VertexBarrelMod3_rmin" dr="0.0 * mm"/>
<z_layout dr="0.0 * mm" z0="0.0 * mm" nz="1"/>
</layer>
<layer module="SupportShell" id="VertexBarrelMod_count + 1" vis="VertexSupportLayerVis">
<barrel_envelope
inner_r="VertexBarrelSupport_rmin"
outer_r="VertexBarrelSupport_rmax"
z_length="VertexBarrelSupport_length" />
<layer_material surface="outer" binning="binPhi,binZ" bins0="VertexBarrelStave_count" bins1="100" />
<rphi_layout phi_tilt="0.0*degree" nphi="VertexBarrelStave_count" phi0="0.0" rc="VertexBarrelShell_rmin" dr="0.0 * mm"/>
<z_layout dr="0.0 * mm" z0="0.0 * mm" nz="1"/>
</layer>
</detector>
</detectors>
<readouts>
<readout name="VertexBarrelHits">
<segmentation type="CartesianGridXY" grid_size_x="0.010*mm" grid_size_y="0.010*mm" />
<id>system:8,layer:4,module:12,sensor:2,x:32:-16,y:-16</id>
</readout>
</readouts>
</lccdd>
......@@ -62,7 +62,7 @@ pdftoppm ${FILE_TAG}.pdf ${FILE_TAG} -png -singlefile -cropbox -thinlinemode sol
#dawncut 0 -1 0 1 ${INPUT_FILE} ${FILE_TAG}.prim
dawncut 0 1 0 1 ${INPUT_FILE} ${FILE_TAG}_temp0.prim
dawncut 0 -1 0 1 ${FILE_TAG}_temp0.prim ${FILE_TAG}.prim
../../bin/dawn_tweak --mag 10 --draw 1 --theta 270 --phi 90
../../bin/dawn_tweak --mag 10 --draw 1 --theta 90 --phi 90
dawn -d ${FILE_TAG}.prim
ps2pdf ${FILE_TAG}.eps ${FILE_TAG}_top_full.pdf
gs -o ${FILE_TAG}_top.pdf -sDEVICE=pdfwrite \
......
......@@ -47,7 +47,7 @@ set -- "${POSITIONAL[@]}" # restore positional parameters
# Top view with a thin slice down the middle
dawncut 0 1 0 1 ${INPUT_FILE} ${FILE_TAG}_top_temp0.prim
dawncut 0 -1 0 1 ${FILE_TAG}_top_temp0.prim ${FILE_TAG}_top.prim
../../bin/dawn_tweak --mag 2 --draw 1 --theta 270 --phi 90
../../bin/dawn_tweak --mag 2 --draw 1 --theta 90 --phi 90
dawn -d ${FILE_TAG}_top.prim
ps2pdf ${FILE_TAG}_top.eps ${FILE_TAG}_top_full.pdf
gs -o ${FILE_TAG}_top.pdf -sDEVICE=pdfwrite \
......
......@@ -16,6 +16,7 @@
#include "DDRec/DetectorData.h"
#include "DDRec/Surface.h"
#include "XML/Layering.h"
#include <array>
using namespace std;
using namespace dd4hep;
......@@ -241,7 +242,6 @@ static Ref_t create_BarrelBarDetectorWithSideFrame(Detector& description, xml_h
assembly.setVisAttributes(description.invisible());
pv = description.pickMotherVolume(sdet).placeVolume(assembly, Position(0, 0, dirc_pos.z()));
pv.addPhysVolID("system", det_id); // Set the subdetector system ID.
pv.addPhysVolID("barrel", 1); // Flag this as a barrel subdetector.
sdet.setPlacement(pv);
return sdet;
}
......
......@@ -21,7 +21,7 @@ using namespace dd4hep;
using namespace dd4hep::detail;
typedef ROOT::Math::XYPoint Point;
// fiber placement helpers, defined in BarrelCalorimeterHybrid_geo
// fiber placement helpers, defined below
vector<vector<Point>> fiberPositions(double radius, double x_spacing, double z_spacing,
double x, double z, double phi, double spacing_tol = 1e-2);
std::pair<int, int> getNdivisions(double x, double z, double dx, double dz);
......@@ -277,23 +277,22 @@ void buildSupport(Detector& desc, Volume &mod_vol, xml_comp_t x_support,
double beam_width = 2. * trd_x1_support / (n_beams + 1); // quick hack to make some gap between T beams
double beam_gap = getAttrOrDefault(x_support, _Unicode(beam_gap), 3.*cm);
// build H-shape beam
// build T-shape beam
double beam_space_x = beam_width + beam_gap;
double beam_space_z = support_thickness - beam_thickness;
double cross_thickness = support_thickness - 2.*beam_thickness;
double beam_pos_z = -beam_thickness / 2.;
double beam_center_z = support_thickness / 2. + beam_pos_z;
double cross_thickness = support_thickness - beam_thickness;
double beam_pos_z = beam_thickness / 2.;
double beam_center_z = support_thickness / 2. - beam_pos_z;
Box beam_vert_s(beam_thickness / 2. , trd_y, cross_thickness / 2.);
Box beam_vert_s(beam_thickness / 2., trd_y, cross_thickness / 2.);
Box beam_hori_s(beam_width / 2., trd_y, beam_thickness / 2.);
UnionSolid T_beam_s(beam_hori_s, beam_vert_s, Position(0., 0., beam_space_z / 2.));
UnionSolid H_beam_s(T_beam_s, beam_hori_s, Position(0., 0., support_thickness - beam_thickness));
Volume H_beam_vol("H_beam", H_beam_s, desc.material(x_support.materialStr()));
UnionSolid T_beam_s(beam_hori_s, beam_vert_s, Position(0., 0., support_thickness / 2.));
Volume H_beam_vol("H_beam", T_beam_s, desc.material(x_support.materialStr()));
H_beam_vol.setVisAttributes(desc, x_support.visStr());
// place H beams first
double beam_start_x = - (n_beams - 1) * (beam_width + beam_gap) / 2.;
for (int i = 0; i < n_beams; ++i) {
Position beam_pos(beam_start_x + i * (beam_width + beam_gap), 0., - support_thickness / 2. - beam_pos_z);
Position beam_pos(beam_start_x + i * (beam_width + beam_gap), 0., - support_thickness / 2. + beam_pos_z);
env_vol.placeVolume(H_beam_vol, beam_pos);
}
......@@ -303,10 +302,10 @@ void buildSupport(Detector& desc, Volume &mod_vol, xml_comp_t x_support,
Volume cross_vol("cross_center_beam", cross_s, desc.material(x_support.materialStr()));
cross_vol.setVisAttributes(desc, x_support.visStr());
for (int i = 0; i < n_beams - 1; ++i) {
env_vol.placeVolume(cross_vol, Position(beam_start_x + beam_space_x * (i + 0.5), 0., 0.));
env_vol.placeVolume(cross_vol, Position(beam_start_x + beam_space_x * (i + 0.5), 0., beam_pos_z));
for (int j = 1; j < n_cross_supports; j++) {
env_vol.placeVolume(cross_vol, Position(beam_start_x + beam_space_x * (i + 0.5), -j * grid_size, 0.));
env_vol.placeVolume(cross_vol, Position(beam_start_x + beam_space_x * (i + 0.5), j * grid_size, 0.));
env_vol.placeVolume(cross_vol, Position(beam_start_x + beam_space_x * (i + 0.5), -j * grid_size, beam_pos_z));
env_vol.placeVolume(cross_vol, Position(beam_start_x + beam_space_x * (i + 0.5), j * grid_size, beam_pos_z));
}
}
......@@ -315,24 +314,135 @@ void buildSupport(Detector& desc, Volume &mod_vol, xml_comp_t x_support,
double cross_edge_x = trd_x1_support + beam_start_x - beam_thickness / 2.;
double cross_trd_x1 = cross_edge_x + std::tan(hphi) * beam_thickness;
double cross_trd_x2 = cross_trd_x1 + 2.* std::tan(hphi) * cross_thickness;
double edge_pos_x = beam_start_x - beam_thickness / 2. - cross_trd_x1 / 2.;
double edge_pos_x = beam_start_x - cross_trd_x1 / 2. - beam_thickness / 2;
Trapezoid cross_s2_trd (cross_trd_x1 / 2., cross_trd_x2 / 2.,
beam_thickness / 2., beam_thickness / 2., cross_thickness / 2.);
Box cross_s2_box ((cross_trd_x2 - cross_trd_x1)/2., beam_thickness / 2., cross_thickness / 2.);
SubtractionSolid cross_s2(cross_s2_trd, cross_s2_box, Position((cross_trd_x1 + cross_trd_x2) / 4., 0., 0.));
Box cross_s2_box ((cross_trd_x2 - cross_trd_x1)/4., beam_thickness / 2., cross_thickness / 2.);
SubtractionSolid cross_s2(cross_s2_trd, cross_s2_box, Position((cross_trd_x2 + cross_trd_x1)/4., 0., 0.));
Volume cross_vol2("cross_edge_beam", cross_s2, desc.material(x_support.materialStr()));
cross_vol2.setVisAttributes(desc, x_support.visStr());
env_vol.placeVolume(cross_vol2, Position(edge_pos_x, 0., 0.));
env_vol.placeVolume(cross_vol2, Transform3D(Translation3D(-edge_pos_x, 0., 0.) * RotationZ(M_PI)));
env_vol.placeVolume(cross_vol2, Position(edge_pos_x, 0., beam_pos_z));
env_vol.placeVolume(cross_vol2, Transform3D(Translation3D(-edge_pos_x, 0., beam_pos_z) * RotationZ(M_PI)));
for (int j = 1; j < n_cross_supports; j++) {
env_vol.placeVolume(cross_vol2, Position(edge_pos_x, -j * grid_size, 0.));
env_vol.placeVolume(cross_vol2, Position(edge_pos_x, j * grid_size, 0.));
env_vol.placeVolume(cross_vol2, Transform3D(Translation3D(-edge_pos_x, -j * grid_size, 0.) * RotationZ(M_PI)));
env_vol.placeVolume(cross_vol2, Transform3D(Translation3D(-edge_pos_x, j * grid_size, 0.) * RotationZ(M_PI)));
env_vol.placeVolume(cross_vol2, Position(edge_pos_x, -j * grid_size, beam_pos_z));
env_vol.placeVolume(cross_vol2, Position(edge_pos_x, j * grid_size, beam_pos_z));
env_vol.placeVolume(cross_vol2, Transform3D(Translation3D(-edge_pos_x, -j * grid_size, beam_pos_z) * RotationZ(M_PI)));
env_vol.placeVolume(cross_vol2, Transform3D(Translation3D(-edge_pos_x, j * grid_size, beam_pos_z) * RotationZ(M_PI)));
}
mod_vol.placeVolume(env_vol, Position(0.0, 0.0, l_pos_z + support_thickness/2.));
}
// Fill fiber lattice into trapezoid starting from position (0,0) in x-z coordinate system
vector<vector<Point>> fiberPositions(double radius, double x_spacing, double z_spacing, double x, double z, double phi,
double spacing_tol)
{
// z_spacing - distance between fiber layers in z
// x_spacing - distance between fiber centers in x
// x - half-length of the shorter (bottom) base of the trapezoid
// z - height of the trapezoid
// phi - angle between z and trapezoid arm
vector<vector<Point>> positions;
int z_layers = floor((z / 2 - radius - spacing_tol) / z_spacing); // number of layers that fit in z/2
double z_pos = 0.;
double x_pos = 0.;
for (int l = -z_layers; l < z_layers + 1; l++) {
vector<Point> xline;
z_pos = l * z_spacing;
double x_max = x + (z / 2. + z_pos) * tan(phi) - spacing_tol; // calculate max x at particular z_pos
(l % 2 == 0) ? x_pos = 0. : x_pos = x_spacing / 2; // account for spacing/2 shift
while (x_pos < (x_max - radius)) {
xline.push_back(Point(x_pos, z_pos));
if (x_pos != 0.)
xline.push_back(Point(-x_pos, z_pos)); // using symmetry around x=0
x_pos += x_spacing;
}
// Sort fiber IDs for a better organization
sort(xline.begin(), xline.end(), [](const Point& p1, const Point& p2) { return p1.x() < p2.x(); });
positions.emplace_back(std::move(xline));
}
return positions;
}
// Calculate number of divisions for the readout grid for the fiber layers
std::pair<int, int> getNdivisions(double x, double z, double dx, double dz)
{
// x and z defined as in vector<Point> fiberPositions
// dx, dz - size of the grid in x and z we want to get close to with the polygons
// See also descripltion when the function is called
double SiPMsize = 13.0 * mm;
double grid_min = SiPMsize + 3.0 * mm;
if (dz < grid_min) {
dz = grid_min;
}
if (dx < grid_min) {
dx = grid_min;
}
int nfit_cells_z = floor(z / dz);
int n_cells_z = nfit_cells_z;
if (nfit_cells_z == 0)
n_cells_z++;
int nfit_cells_x = floor((2 * x) / dx);
int n_cells_x = nfit_cells_x;
if (nfit_cells_x == 0)
n_cells_x++;
return std::make_pair(n_cells_x, n_cells_z);
}
// Calculate dimensions of the polygonal grid in the cartesian coordinate system x-z
vector<tuple<int, Point, Point, Point, Point>> gridPoints(int div_x, int div_z, double x, double z, double phi)
{
// x, z and phi defined as in vector<Point> fiberPositions
// div_x, div_z - number of divisions in x and z
double dz = z / div_z;
std::vector<std::tuple<int, Point, Point, Point, Point>> points;
for (int iz = 0; iz < div_z + 1; iz++) {
for (int ix = 0; ix < div_x + 1; ix++) {
double A_z = -z / 2 + iz * dz;
double B_z = -z / 2 + (iz + 1) * dz;
double len_x_for_z = 2 * (x + iz * dz * tan(phi));
double len_x_for_z_plus_1 = 2 * (x + (iz + 1) * dz * tan(phi));
double dx_for_z = len_x_for_z / div_x;
double dx_for_z_plus_1 = len_x_for_z_plus_1 / div_x;
double A_x = -len_x_for_z / 2. + ix * dx_for_z;
double B_x = -len_x_for_z_plus_1 / 2. + ix * dx_for_z_plus_1;
double C_z = B_z;
double D_z = A_z;
double C_x = B_x + dx_for_z_plus_1;
double D_x = A_x + dx_for_z;
int id = ix + div_x * iz;
auto A = Point(A_x, A_z);
auto B = Point(B_x, B_z);
auto C = Point(C_x, C_z);
auto D = Point(D_x, D_z);
// vertex points filled in the clock-wise direction
points.push_back(make_tuple(id, A, B, C, D));
}
}
return points;
}
DECLARE_DETELEMENT(athena_EcalBarrelInterlayers, create_detector)
/** \addtogroup VertexTracker Vertex Trackers
* \brief Type: **SiVertexBarrel**.
/** \addtogroup Trackers Trackers
* \brief Type: **BarrelTrackerWithFrame**.
* \author W. Armstrong
*
* \ingroup trackers
*
*
* \code
* \endcode
*
* @{
*/
#include "DD4hep/DetFactoryHelper.h"
......@@ -16,12 +12,16 @@
#include "DDRec/Surface.h"
#include "DDRec/DetectorData.h"
#include "XML/Layering.h"
#include "Acts/Plugins/DD4hep/ActsExtension.hpp"
#include "Acts/Surfaces/PlanarBounds.hpp"
#include "Acts/Surfaces/RectangleBounds.hpp"
#include "Acts/Surfaces/TrapezoidBounds.hpp"
#include "Acts/Definitions/Units.hpp"
#include "XML/Utilities.h"
#include <array>
#if defined(USE_ACTSDD4HEP)
#include "ActsDD4hep/ActsExtension.hpp"
#include "ActsDD4hep/ConvertMaterial.hpp"
#else
#include "Acts/Plugins/DD4hep/ActsExtension.hpp"
#include "Acts/Plugins/DD4hep/ConvertDD4hepMaterial.hpp"
#endif
using namespace std;
using namespace dd4hep;
......@@ -31,10 +31,23 @@ using namespace dd4hep::detail;
/** Barrel Tracker with space frame.
*
* - Optional "frame" tag within the module element.
* - Optional "support" tag within the detector element.
*
* The shapes are created using createShape which can be one of many basic geomtries.
* See the examples Check_shape_*.xml in
* [dd4hep's examples/ClientTests/compact](https://github.com/AIDASoft/DD4hep/tree/master/examples/ClientTests/compact)
* directory.
*
*
* - Optional "frame" tag within the module element.
*
* \ingroup trackers
*
* \code
* \endcode
*
*
* @author Whitney Armstrong
*/
static Ref_t create_BarrelTrackerWithFrame(Detector& description, xml_h e, SensitiveDetector sens) {
typedef vector<PlacedVolume> Placements;
......@@ -43,54 +56,71 @@ static Ref_t create_BarrelTrackerWithFrame(Detector& description, xml_h e, Sensi
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;
map<string, std::vector<VolPlane>> volplane_surfaces;
//map<string, xml_h> xmleles;
PlacedVolume pv;
dd4hep::xml::Dimension dimensions(x_det.dimensions());
map<string, Volume> volumes;
map<string, Placements> sensitives;
map<string, std::vector<VolPlane>> volplane_surfaces;
map<string, std::array<double, 2>> module_thicknesses;
Acts::ActsExtension* detWorldExt = new Acts::ActsExtension();
detWorldExt->addType("barrel", "detector");
sdet.addExtension<Acts::ActsExtension>(detWorldExt);
Tube topVolumeShape(dimensions.rmin(), dimensions.rmax(), dimensions.length() * 0.5);
Volume assembly(det_name,topVolumeShape,air);
// The Cold Plate is approximately 30 mm wide and is based on the same carbon-ply layup
//as for the IB Stave. Two pipes with an inner diameter of 2.67 mm and a wall thickness
//of 64 μm have been used. The two pipes are interconnected at one end of the Cold Plate
//providing a loop, whose inlet and outlet are on the same side and correspond to the
//
//requirements have led to an equilateral section of the frame with a 42 mm wide side, that
//provides almost the same rigidity for all the possible Stave positions.
//
// module mat um
//
//Aluminium 50
//Polyimide 100
//Carbon fibre 120
//Silicon 50
//Eccobond-45 100
//
//Metal layers Aluminium 200
//Insulating layers Polyimide 200
//Glue Cooling tube wall Eccobond-45 100
//
//Carbon fleece 40
//Carbon paper 30
//Polyimide 64
//Water
//Carbon fibre 120
//Eccobond-45 100
PlacedVolume pv;
dd4hep::xml::Dimension dimensions(x_det.dimensions());
// ACTS extension
{
Acts::ActsExtension* detWorldExt = new Acts::ActsExtension();
detWorldExt->addType("barrel", "detector");
// Add the volume boundary material if configured
for (xml_coll_t bmat(x_det, _Unicode(boundary_material)); bmat; ++bmat) {
xml_comp_t x_boundary_material = bmat;
Acts::xmlToProtoSurfaceMaterial(x_boundary_material, *detWorldExt, "boundary_material");
}
sdet.addExtension<Acts::ActsExtension>(detWorldExt);
}
Tube topVolumeShape(dimensions.rmin(), dimensions.rmax(), dimensions.length() * 0.5);
Volume assembly(det_name,topVolumeShape,air);
sens.setType("tracker");
// Loop over the suports
for (xml_coll_t su(x_det, _U(support)); su; ++su) {
xml_comp_t x_support = su;
double support_thickness = getAttrOrDefault(x_support, _U(thickness), 2.0 * mm);
double support_length = getAttrOrDefault(x_support, _U(length), 2.0 * mm);
double support_rmin = getAttrOrDefault(x_support, _U(rmin), 2.0 * mm);
double support_zstart = getAttrOrDefault(x_support, _U(zstart), 2.0 * mm);
std::string support_name = getAttrOrDefault<std::string>(x_support, _Unicode(name), "support_tube");
std::string support_vis = getAttrOrDefault<std::string>(x_support, _Unicode(vis), "AnlRed");
xml_dim_t pos (x_support.child(_U(position), false));
xml_dim_t rot (x_support.child(_U(rotation), false));
Solid support_solid;
if(x_support.hasChild("shape")){
xml_comp_t shape(x_support.child(_U(shape)));
string shape_type = shape.typeStr();
support_solid = xml::createShape(description, shape_type, shape);
} else {
support_solid = Tube(support_rmin, support_rmin + support_thickness, support_length / 2);
}
Transform3D tr = Transform3D(Rotation3D(),Position(0,0,(support_zstart + support_length / 2)));
if ( pos.ptr() && rot.ptr() ) {
Rotation3D rot3D(RotationZYX(rot.z(0),rot.y(0),rot.x(0)));
Position pos3D(pos.x(0),pos.y(0),pos.z(0));
tr = Transform3D(rot3D, pos3D);
}
else if ( pos.ptr() ) {
tr = Transform3D(Rotation3D(),Position(pos.x(0),pos.y(0),pos.z(0)));
}
else if ( rot.ptr() ) {
Rotation3D rot3D(RotationZYX(rot.z(0),rot.y(0),rot.x(0)));
tr = Transform3D(rot3D,Position());
}
Material support_mat = description.material(x_support.materialStr());
Volume support_vol(support_name, support_solid, support_mat);
support_vol.setVisAttributes(description.visAttributes(support_vis));
pv = assembly.placeVolume(support_vol, tr);
// pv = assembly.placeVolume(support_vol, Position(0, 0, support_zstart + support_length / 2));
}
// loop over the modules
for (xml_coll_t mi(x_det, _U(module)); mi; ++mi) {
xml_comp_t x_mod = mi;
......@@ -141,24 +171,26 @@ static Ref_t create_BarrelTrackerWithFrame(Detector& description, xml_h e, Sensi
double thickness_so_far = 0.0;
double thickness_sum = -total_thickness/2.0;
for (xml_coll_t ci(x_mod, _U(module_component)); ci; ++ci, ++ncomponents) {
xml_comp_t x_comp = ci;
xml_comp_t x_pos = x_comp.position(false);
xml_comp_t x_rot = x_comp.rotation(false);
string c_nam = _toString(ncomponents, "component%d");
Box c_box(x_comp.width() / 2, x_comp.length() / 2, x_comp.thickness() / 2);
Volume c_vol(c_nam, c_box, description.material(x_comp.materialStr()));
xml_comp_t x_comp = ci;
xml_comp_t x_pos = x_comp.position(false);
xml_comp_t x_rot = x_comp.rotation(false);
const string c_nam = _toString(ncomponents, "component%d");
Box c_box(x_comp.width() / 2, x_comp.length() / 2, x_comp.thickness() / 2);
Volume c_vol(c_nam, c_box, description.material(x_comp.materialStr()));
// Utility variable for the relative z-offset based off the previous components
const double zoff = thickness_sum+x_comp.thickness() / 2.0;
if (x_pos && x_rot) {
Position c_pos(x_pos.x(0), x_pos.y(0), x_pos.z(0));
Position c_pos(x_pos.x(0), x_pos.y(0), x_pos.z(0) + zoff);
RotationZYX c_rot(x_rot.z(0), x_rot.y(0), x_rot.x(0));
pv = m_vol.placeVolume(c_vol, Transform3D(c_rot, c_pos));
} else if (x_rot) {
Position c_pos(0, 0, thickness_sum + x_comp.thickness() / 2.0);
pv = m_vol.placeVolume(c_vol, Transform3D(RotationZYX(x_rot.z(0), x_rot.y(0), x_rot.x(0)),c_pos));
Position c_pos(0, 0, zoff);
pv = m_vol.placeVolume(c_vol, Transform3D(RotationZYX(x_rot.z(0), x_rot.y(0), x_rot.x(0)), c_pos));
} else if (x_pos) {
pv = m_vol.placeVolume(c_vol, Position(x_pos.x(0), x_pos.y(0), x_pos.z(0)));
pv = m_vol.placeVolume(c_vol, Position(x_pos.x(0), x_pos.y(0), x_pos.z(0) + zoff));
} else {
pv = m_vol.placeVolume(c_vol, Position(0,0,thickness_sum+x_comp.thickness()/2.0));
pv = m_vol.placeVolume(c_vol, Position(0, 0, zoff));
}
c_vol.setRegion(description, x_comp.regionStr());
c_vol.setLimitSet(description, x_comp.limitsStr());
......@@ -169,32 +201,34 @@ static Ref_t create_BarrelTrackerWithFrame(Detector& description, xml_h e, Sensi
sensitives[m_nam].push_back(pv);
module_thicknesses[m_nam] = {thickness_so_far + x_comp.thickness()/2.0, total_thickness-thickness_so_far - x_comp.thickness()/2.0};
// -------- create a measurement plane for the tracking surface attched to the sensitive volume -----
Vector3D u(-1., 0., 0.);
Vector3D v(0., -1., 0.);
Vector3D n(0., 0., 1.);
// Vector3D o( 0. , 0. , 0. ) ;
// -------- create a measurement plane for the tracking surface attched to the sensitive volume -----
Vector3D u( 0. , 1. , 0. ) ;
Vector3D v( 0. , 0. , 1. ) ;
Vector3D n( 1. , 0. , 0. ) ;
// Vector3D o( 0. , 0. , 0. ) ;
// compute the inner and outer thicknesses that need to be assigned to the tracking surface
// depending on wether the support is above or below the sensor
double inner_thickness = module_thicknesses[m_nam][0];
double outer_thickness = module_thicknesses[m_nam][1];
SurfaceType type( SurfaceType::Sensitive ) ;
// compute the inner and outer thicknesses that need to be assigned to the tracking surface
// depending on wether the support is above or below the sensor
double inner_thickness = module_thicknesses[m_nam][0];
double outer_thickness = module_thicknesses[m_nam][1];
//if( isStripDetector )
// type.setProperty( SurfaceType::Measurement1D , true ) ;
SurfaceType type(SurfaceType::Sensitive);
VolPlane surf( c_vol , type , inner_thickness , outer_thickness , u,v,n ) ; //,o ) ;
volplane_surfaces[m_nam].push_back(surf);
//--------------------------------------------
// if( isStripDetector )
// type.setProperty( SurfaceType::Measurement1D , true ) ;
VolPlane surf(c_vol, type, inner_thickness, outer_thickness, u, v, n); //,o ) ;
volplane_surfaces[m_nam].push_back(surf);
//--------------------------------------------
}
thickness_sum += x_comp.thickness();
thickness_so_far += x_comp.thickness();
// apply relative offsets in z-position used to stack components side-by-side
if (x_pos) {
thickness_sum += x_pos.z(0);
thickness_so_far += x_pos.z(0);
}
}
}
......@@ -223,19 +257,22 @@ static Ref_t create_BarrelTrackerWithFrame(Detector& description, xml_h e, Sensi
double z_dr = z_layout.dr(); // Radial displacement parameter, of every other module.
Volume module_env = volumes[m_nam];
DetElement lay_elt(sdet, _toString(x_layer.id(), "layer%d"), lay_id);
DetElement lay_elt(sdet, lay_nam, lay_id);
Placements& sensVols = sensitives[m_nam];
// the local coordinate systems of modules in dd4hep and acts differ
// see http://acts.web.cern.ch/ACTS/latest/doc/group__DD4hepPlugins.html
Acts::ActsExtension* layerExtension = new Acts::ActsExtension();
layerExtension->addType("sensitive cylinder", "layer");
//layerExtension->addValue(0, "r_min", "envelope");
//layerExtension->addValue(0, "r_max", "envelope");
//layerExtension->addValue(0, "z_min", "envelope");
//layerExtension->addValue(0, "z_max", "envelope");
//layerExtension->addType("axes", "definitions", "XzY");
lay_elt.addExtension<Acts::ActsExtension>(layerExtension);
{
Acts::ActsExtension* layerExtension = new Acts::ActsExtension();
// layer is simple tube so no need to set envelope
layerExtension->addType("sensitive cylinder", "layer");
// Add the proto layer material
for(xml_coll_t lmat(x_layer, _Unicode(layer_material)); lmat; ++lmat) {
xml_comp_t x_layer_material = lmat;
xmlToProtoSurfaceMaterial(x_layer_material, *layerExtension, "layer_material");
}
lay_elt.addExtension<Acts::ActsExtension>(layerExtension);
}
// Z increment for module placement along Z axis.
// Adjust for z0 at center of module rather than
......@@ -267,16 +304,17 @@ static Ref_t create_BarrelTrackerWithFrame(Detector& description, xml_h e, Sensi
PlacedVolume sens_pv = sensVols[ic];
DetElement comp_de(mod_elt, std::string("de_") + sens_pv.volume().name(), module);
comp_de.setPlacement(sens_pv);
Acts::ActsExtension* sensorExtension = new Acts::ActsExtension();
//sensorExtension->addType("sensor", "detector");
comp_de.addExtension<Acts::ActsExtension>(sensorExtension);
// ACTS extension
{
Acts::ActsExtension* sensorExtension = new Acts::ActsExtension();
//sensorExtension->addType("sensor", "detector");
comp_de.addExtension<Acts::ActsExtension>(sensorExtension);
}
//comp_de.setAttributes(description, sens_pv.volume(), x_layer.regionStr(), x_layer.limitsStr(),
// xml_det_t(xmleles[m_nam]).visStr());
//
volSurfaceList( comp_de )->push_back( volplane_surfaces[m_nam][ic] ) ;
volSurfaceList(comp_de)->push_back(volplane_surfaces[m_nam][ic]);
}
/// Increase counters etc.
......@@ -306,7 +344,6 @@ static Ref_t create_BarrelTrackerWithFrame(Detector& description, xml_h e, Sensi
assembly.setVisAttributes(description.invisible());
pv = description.pickMotherVolume(sdet).placeVolume(assembly);
pv.addPhysVolID("system", det_id); // Set the subdetector system ID.
pv.addPhysVolID("barrel", 1); // Flag this as a barrel subdetector.
sdet.setPlacement(pv);
return sdet;
}
......@@ -316,3 +353,4 @@ static Ref_t create_BarrelTrackerWithFrame(Detector& description, xml_h e, Sensi
DECLARE_DETELEMENT(BarrelTrackerWithFrame, create_BarrelTrackerWithFrame)
DECLARE_DETELEMENT(athena_TrackerBarrel, create_BarrelTrackerWithFrame)
DECLARE_DETELEMENT(athena_VertexBarrel, create_BarrelTrackerWithFrame)
DECLARE_DETELEMENT(athena_TOFBarrel, create_BarrelTrackerWithFrame)
//==========================================================================
// Based off DD4hep_SubDetectorAssembly
//
// This is a simple plugin to allow compositing different detectors
// into a single barrel or endcap for ACTS
// Note: positive/negative position strings differentiate between
// positive/negative endcaps
//--------------------------------------------------------------------------
#include "DD4hep/DetFactoryHelper.h"
#include "DD4hep/Printout.h"
#include "XML/Utilities.h"
#if defined(USE_ACTSDD4HEP)
#include "ActsDD4hep/ActsExtension.hpp"
#else
#include "Acts/Plugins/DD4hep/ActsExtension.hpp"
#endif
using namespace dd4hep;
using namespace dd4hep::detail;
static Ref_t create_element(Detector& description, xml_h e, Ref_t)
{
xml_det_t x_det(e);
const std::string det_name = x_det.nameStr();
DetElement sdet(det_name, x_det.id());
Volume vol;
Position pos;
const bool usePos = x_det.hasChild(_U(position));
sdet.setType("compound");
xml::setDetectorTypeFlag(e, sdet);
const std::string actsType = getAttrOrDefault(x_det, _Unicode(actsType), "endcap");
printout(DEBUG, det_name, "+++ Creating composite tracking detector (type: " + actsType + ")");
assert(actsType == "barrel" || actsType == "endcap");
// ACTS extension
{
Acts::ActsExtension* detWorldExt = new Acts::ActsExtension();
detWorldExt->addType(actsType, "detector");
sdet.addExtension<Acts::ActsExtension>(detWorldExt);
}
if (usePos) {
pos = Position(x_det.position().x(), x_det.position().y(), x_det.position().z());
}
vol = Assembly(det_name);
vol.setAttributes(description, x_det.regionStr(), x_det.limitsStr(), x_det.visStr());
Volume mother = description.pickMotherVolume(sdet);
PlacedVolume pv;
if (usePos) {
pv = mother.placeVolume(vol, pos);
} else {
pv = mother.placeVolume(vol);
}
sdet.setPlacement(pv);
for (xml_coll_t c(x_det, _U(composite)); c; ++c) {
xml_dim_t component = c;
const std::string nam = component.nameStr();
description.declareParent(nam, sdet);
}
return sdet;
}
DECLARE_DETELEMENT(athena_CompositeTracker, create_element)
......@@ -2,11 +2,17 @@
// Specialized generic detector constructor
//==========================================================================
#include "Acts/Plugins/DD4hep/ActsExtension.hpp"
#include "Acts/Plugins/DD4hep/ConvertDD4hepMaterial.hpp"
#include "DD4hep/DetFactoryHelper.h"
#include "DD4hep/Printout.h"
#if defined(USE_ACTSDD4HEP)
#include "ActsDD4hep/ActsExtension.hpp"
#include "ActsDD4hep/ConvertMaterial.hpp"
#else
#include "Acts/Plugins/DD4hep/ActsExtension.hpp"
#include "Acts/Plugins/DD4hep/ConvertDD4hepMaterial.hpp"
#endif
using namespace std;
using namespace dd4hep;
using namespace dd4hep::detail;
......
......@@ -162,7 +162,7 @@ static Ref_t createDetector(Detector& desc, xml_h e, SensitiveDetector sens)
Volume lGlue("lGlue", gGlue, desc.material(xml_glue.materialStr()));
lGlue.setVisAttributes(desc.visAttributes(xml_glue.visStr()));
sens.setType("photoncounter");
sens.setType("tracker");
lBar.setSensitiveDetector(sens);
int bars_repeat_z = 4; // TODO parametrize!
......@@ -320,7 +320,7 @@ static Ref_t createDetector(Detector& desc, xml_h e, SensitiveDetector sens)
// Box bar_geo(bar_thicknes / 2., bar_width / 2., bar_length / 2.);
// Volume bar_volume("cb_DIRC_bars_Logix", bar_geo, bar_material);
// bar_volume.setVisAttributes(desc.visAttributes(xml_det.visStr()));
// sens.setType("photoncounter");
// sens.setType("tracker");
// bar_volume.setSensitiveDetector(sens);
// for (int ia = 0; ia < bar_count; ia++) {
......
......@@ -4,7 +4,7 @@
//
// Author: Christopher Dilks (Duke University)
//
// - Design Adapted from Standalone Fun4all and GEMC implementations
// - Design Adapted from Standalone Fun4all and GEMC implementations
// [ Evaristo Cisbani, Cristiano Fanelli, Alessio Del Dotto, et al. ]
//
//==========================================================================
......@@ -20,7 +20,6 @@
#include "DD4hep/DetFactoryHelper.h"
#include "DD4hep/Printout.h"
using namespace std;
using namespace dd4hep;
using namespace dd4hep::rec;
......@@ -35,88 +34,105 @@ static Ref_t createDetector(Detector& desc, xml::Handle_t handle, SensitiveDetec
OpticalSurfaceManager surfMgr = desc.surfaceManager();
// attributes -----------------------------------------------------------
// TODO [low priority]: some attributes have default values, some do not;
// make this more consistent
// - vessel
double vesselZ0 = dims.attr<double>(_Unicode(z0));
double vesselLength = dims.attr<double>(_Unicode(length));
double vesselRmin0 = dims.attr<double>(_Unicode(rmin0));
double vesselRmin1 = dims.attr<double>(_Unicode(rmin1));
double vesselRmax0 = dims.attr<double>(_Unicode(rmax0));
double vesselRmax1 = dims.attr<double>(_Unicode(rmax1));
double vesselRmax2 = dims.attr<double>(_Unicode(rmax2));
double snoutLength = dims.attr<double>(_Unicode(snout_length));
int nSectors = getAttrOrDefault<int>(dims, _Unicode(nsectors), 6);
double wallThickness = getAttrOrDefault<double>(dims, _Unicode(wall_thickness), 0.5*cm);
double windowThickness = getAttrOrDefault<double>(dims, _Unicode(window_thickness), 0.1*cm);
auto vesselMat = desc.material(getAttrOrDefault(detElem, _Unicode(material), "Aluminum"));
auto gasvolMat = desc.material(getAttrOrDefault(detElem, _Unicode(gas), "AirOptical"));
auto vesselVis = desc.visAttributes(detElem.attr<std::string>(_Unicode(vis_vessel)));
auto gasvolVis = desc.visAttributes(detElem.attr<std::string>(_Unicode(vis_gas)));
double vesselZmin = dims.attr<double>(_Unicode(zmin));
double vesselLength = dims.attr<double>(_Unicode(length));
double vesselRmin0 = dims.attr<double>(_Unicode(rmin0));
double vesselRmin1 = dims.attr<double>(_Unicode(rmin1));
double vesselRmax0 = dims.attr<double>(_Unicode(rmax0));
double vesselRmax1 = dims.attr<double>(_Unicode(rmax1));
double vesselRmax2 = dims.attr<double>(_Unicode(rmax2));
double snoutLength = dims.attr<double>(_Unicode(snout_length));
int nSectors = dims.attr<int>(_Unicode(nsectors));
double wallThickness = dims.attr<double>(_Unicode(wall_thickness));
double windowThickness = dims.attr<double>(_Unicode(window_thickness));
auto vesselMat = desc.material(detElem.attr<std::string>(_Unicode(material)));
auto gasvolMat = desc.material(detElem.attr<std::string>(_Unicode(gas)));
auto vesselVis = desc.visAttributes(detElem.attr<std::string>(_Unicode(vis_vessel)));
auto gasvolVis = desc.visAttributes(detElem.attr<std::string>(_Unicode(vis_gas)));
// - radiator (applies to aerogel and filter)
auto radiatorElem = detElem.child(_Unicode(radiator));
double radiatorRmin = getAttrOrDefault<double>(radiatorElem, _Unicode(rmin), 10.*cm);
double radiatorRmax = getAttrOrDefault<double>(radiatorElem, _Unicode(rmax), 80.*cm);
double radiatorPhiw = getAttrOrDefault<double>(radiatorElem, _Unicode(phiw), 2*M_PI/nSectors);
double radiatorPitch = getAttrOrDefault<double>(radiatorElem, _Unicode(pitch), 0.*degree);
double radiatorFrontplane = getAttrOrDefault<double>(radiatorElem, _Unicode(frontplane), 2.5*cm);
auto radiatorElem = detElem.child(_Unicode(radiator));
double radiatorRmin = radiatorElem.attr<double>(_Unicode(rmin));
double radiatorRmax = radiatorElem.attr<double>(_Unicode(rmax));
double radiatorPhiw = radiatorElem.attr<double>(_Unicode(phiw));
double radiatorPitch = radiatorElem.attr<double>(_Unicode(pitch));
double radiatorFrontplane = radiatorElem.attr<double>(_Unicode(frontplane));
// - aerogel
auto aerogelElem = radiatorElem.child(_Unicode(aerogel));
auto aerogelMat = desc.material(aerogelElem.attr<std::string>(_Unicode(material)));
auto aerogelVis = desc.visAttributes(aerogelElem.attr<std::string>(_Unicode(vis)));
double aerogelThickness = getAttrOrDefault<double>(aerogelElem, _Unicode(thickness), 2.5*cm);
auto aerogelElem = radiatorElem.child(_Unicode(aerogel));
auto aerogelMat = desc.material(aerogelElem.attr<std::string>(_Unicode(material)));
auto aerogelVis = desc.visAttributes(aerogelElem.attr<std::string>(_Unicode(vis)));
double aerogelThickness = aerogelElem.attr<double>(_Unicode(thickness));
// - filter
auto filterElem = radiatorElem.child(_Unicode(filter));
auto filterMat = desc.material(filterElem.attr<std::string>(_Unicode(material)));
auto filterVis = desc.visAttributes(filterElem.attr<std::string>(_Unicode(vis)));
double filterThickness = getAttrOrDefault<double>(filterElem, _Unicode(thickness), 2.5*cm);
auto filterElem = radiatorElem.child(_Unicode(filter));
auto filterMat = desc.material(filterElem.attr<std::string>(_Unicode(material)));
auto filterVis = desc.visAttributes(filterElem.attr<std::string>(_Unicode(vis)));
double filterThickness = filterElem.attr<double>(_Unicode(thickness));
// - mirror
auto mirrorElem = detElem.child(_Unicode(mirror));
auto mirrorMat = desc.material(mirrorElem.attr<std::string>(_Unicode(material)));
auto mirrorVis = desc.visAttributes(mirrorElem.attr<std::string>(_Unicode(vis)));
auto mirrorSurf = surfMgr.opticalSurface(getAttrOrDefault(mirrorElem, _Unicode(surface), "MirrorOpticalSurface"));
double mirrorBackplane = getAttrOrDefault<double>(mirrorElem, _Unicode(backplane), 240.*cm);
double mirrorThickness = getAttrOrDefault<double>(mirrorElem, _Unicode(thickness), 2.*mm);
double mirrorRadius = getAttrOrDefault<double>(mirrorElem, _Unicode(radius), 190*cm);
double mirrorCenterX = getAttrOrDefault<double>(mirrorElem, _Unicode(centerx), 95*cm);
double mirrorRmin = getAttrOrDefault<double>(mirrorElem, _Unicode(rmin), 10.*cm);
double mirrorRmax = getAttrOrDefault<double>(mirrorElem, _Unicode(rmax), 150.*cm);
double mirrorPhiw = getAttrOrDefault<double>(mirrorElem, _Unicode(phiw), 2*M_PI/nSectors);
int mirrorDebug = getAttrOrDefault<int>(mirrorElem, _Unicode(debug), 0);
auto mirrorElem = detElem.child(_Unicode(mirror));
auto mirrorMat = desc.material(mirrorElem.attr<std::string>(_Unicode(material)));
auto mirrorVis = desc.visAttributes(mirrorElem.attr<std::string>(_Unicode(vis)));
auto mirrorSurf = surfMgr.opticalSurface(mirrorElem.attr<std::string>(_Unicode(surface)));
double mirrorBackplane = mirrorElem.attr<double>(_Unicode(backplane));
double mirrorThickness = mirrorElem.attr<double>(_Unicode(thickness));
double mirrorRmin = mirrorElem.attr<double>(_Unicode(rmin));
double mirrorRmax = mirrorElem.attr<double>(_Unicode(rmax));
double mirrorPhiw = mirrorElem.attr<double>(_Unicode(phiw));
double focusTuneZ = mirrorElem.attr<double>(_Unicode(focus_tune_z));
double focusTuneX = mirrorElem.attr<double>(_Unicode(focus_tune_x));
// - sensor module
auto sensorElem = detElem.child(_Unicode(sensors)).child(_Unicode(module));
auto sensorMat = desc.material(sensorElem.attr<std::string>(_Unicode(material)));
auto sensorVis = desc.visAttributes(sensorElem.attr<std::string>(_Unicode(vis)));
auto sensorSurf = surfMgr.opticalSurface(getAttrOrDefault(sensorElem, _Unicode(surface), "MirrorOpticalSurface"));
double sensorSide = sensorElem.attr<double>(_Unicode(side));
double sensorGap = sensorElem.attr<double>(_Unicode(gap));
double sensorThickness = sensorElem.attr<double>(_Unicode(thickness));
auto sensorElem = detElem.child(_Unicode(sensors)).child(_Unicode(module));
auto sensorMat = desc.material(sensorElem.attr<std::string>(_Unicode(material)));
auto sensorVis = desc.visAttributes(sensorElem.attr<std::string>(_Unicode(vis)));
auto sensorSurf = surfMgr.opticalSurface(sensorElem.attr<std::string>(_Unicode(surface)));
double sensorSide = sensorElem.attr<double>(_Unicode(side));
double sensorGap = sensorElem.attr<double>(_Unicode(gap));
double sensorThickness = sensorElem.attr<double>(_Unicode(thickness));
// - sensor sphere
auto sensorSphElem = detElem.child(_Unicode(sensors)).child(_Unicode(sphere));
double sensorSphRadius = sensorSphElem.attr<double>(_Unicode(radius));
double sensorSphCenterX = sensorSphElem.attr<double>(_Unicode(centerx));
double sensorSphCenterY = sensorSphElem.attr<double>(_Unicode(centery));
double sensorSphCenterZ = sensorSphElem.attr<double>(_Unicode(centerz));
int sensorSphDebug = getAttrOrDefault<int>(sensorSphElem, _Unicode(debug), 0);
auto sensorSphElem = detElem.child(_Unicode(sensors)).child(_Unicode(sphere));
double sensorSphRadius = sensorSphElem.attr<double>(_Unicode(radius));
double sensorSphCenterX = sensorSphElem.attr<double>(_Unicode(centerx));
double sensorSphCenterZ = sensorSphElem.attr<double>(_Unicode(centerz));
// - sensor sphere patch cuts
auto sensorSphPatchElem = detElem.child(_Unicode(sensors)).child(_Unicode(sphericalpatch));
double sensorSphPatchThetaMin = sensorSphPatchElem.attr<double>(_Unicode(thetamin));
double sensorSphPatchThetaMax = sensorSphPatchElem.attr<double>(_Unicode(thetamax));
double sensorSphPatchWidthFactor = sensorSphPatchElem.attr<double>(_Unicode(widthfactor));
double sensorSphPatchTaper = sensorSphPatchElem.attr<double>(_Unicode(taper));
auto sensorSphPatchElem = detElem.child(_Unicode(sensors)).child(_Unicode(sphericalpatch));
double sensorSphPatchPhiw = sensorSphPatchElem.attr<double>(_Unicode(phiw));
double sensorSphPatchRmin = sensorSphPatchElem.attr<double>(_Unicode(rmin));
double sensorSphPatchRmax = sensorSphPatchElem.attr<double>(_Unicode(rmax));
double sensorSphPatchZmin = sensorSphPatchElem.attr<double>(_Unicode(zmin));
// - debugging switches
int debug_optics_mode = detElem.attr<int>(_Unicode(debug_optics));
bool debug_mirror = mirrorElem.attr<bool>(_Unicode(debug));
bool debug_sensors = sensorSphElem.attr<bool>(_Unicode(debug));
// if debugging optics, override some settings
bool debug_optics = debug_optics_mode > 0;
if(debug_optics) {
printout(WARNING,"DRich_geo","DEBUGGING DRICH OPTICS");
switch(debug_optics_mode) {
case 1: vesselMat = aerogelMat = filterMat = sensorMat = gasvolMat = desc.material("VacuumOptical"); break;
case 2: vesselMat = aerogelMat = filterMat = sensorMat = desc.material("VacuumOptical"); break;
default: printout(FATAL,"DRich_geo","UNKNOWN debug_optics_mode"); return det;
};
aerogelVis = sensorVis = mirrorVis;
gasvolVis = vesselVis = desc.invisible();
};
// BUILD VESSEL ====================================================================
/* - `vessel`: aluminum enclosure, the mother volume of the dRICh
* - `gasvol`: gas volume, which fills `vessel`; all other volumes defined below
* are children of `gasvol`
* - the dRICh vessel geometry has two regions: the snout refers to the conic region
* - the dRICh vessel geometry has two regions: the snout refers to the conic region
* in the front, housing the aerogel, while the tank refers to the cylindrical
* region, housing the rest of the detector components
*/
// derived attributes
double tankLength = vesselLength - snoutLength;
double vesselZmax = vesselZmin + vesselLength;
// snout solids
double boreDelta = vesselRmin1 - vesselRmin0;
double snoutDelta = vesselRmax1 - vesselRmax0;
Cone vesselSnout(
snoutLength/2.0,
vesselRmin0,
......@@ -139,14 +155,14 @@ static Ref_t createDetector(Detector& desc, xml::Handle_t handle, SensitiveDetec
// tank solids
Cone vesselTank(
(vesselLength - snoutLength)/2.0,
tankLength/2.0,
vesselSnout.rMin2(),
vesselRmax2,
vesselRmin1,
vesselRmax2
);
Cone gasvolTank(
(vesselLength - snoutLength)/2.0 - windowThickness,
tankLength/2.0 - windowThickness,
gasvolSnout.rMin2(),
vesselRmax2 - wallThickness,
vesselRmin1 + wallThickness,
......@@ -154,126 +170,135 @@ static Ref_t createDetector(Detector& desc, xml::Handle_t handle, SensitiveDetec
);
// snout + tank solids
UnionSolid vesselSolid(
UnionSolid vesselUnion(
vesselTank,
vesselSnout,
Position(0., 0., -vesselLength/2.)
);
UnionSolid gasvolSolid(
UnionSolid gasvolUnion(
gasvolTank,
gasvolSnout,
Position(0., 0., -vesselLength/2. + windowThickness)
);
// extra solids for `debug_optics` only
Box vesselBox(1001,1001,1001);
Box gasvolBox(1000,1000,1000);
// choose vessel and gasvol solids (depending on `debug_optics_mode` (0=disabled))
Solid vesselSolid, gasvolSolid;
switch(debug_optics_mode) {
case 0: vesselSolid=vesselUnion; gasvolSolid=gasvolUnion; break; // `!debug_optics`
case 1: vesselSolid=vesselBox; gasvolSolid=gasvolBox; break;
case 2: vesselSolid=vesselBox; gasvolSolid=gasvolUnion; break;
};
// volumes
Volume vesselVol(detName, vesselSolid, vesselMat);
Volume gasvolVol(detName + "_gas", gasvolSolid, gasvolMat);
Volume gasvolVol(detName+"_gas", gasvolSolid, gasvolMat);
vesselVol.setVisAttributes(vesselVis);
gasvolVol.setVisAttributes(gasvolVis);
// reference position
auto snoutFront = Position(0., 0., -(vesselLength + snoutLength)/2.);
// reference positions
// - the vessel is created such that the center of the cylindrical tank volume
// coincides with the origin; this is called the "origin position" of the vessel
// - when the vessel (and its children volumes) is placed, it is translated in
// the z-direction to be in the proper ATHENA-integration location
// - these reference positions are for the frontplane and backplane of the vessel,
// with respect to the vessel origin position
auto originFront = Position(0., 0., -tankLength/2.0 - snoutLength );
auto originBack = Position(0., 0., tankLength/2.0 );
// initialize sensor centroids (used for mirror parameterization below); this is
// the average (x,y,z) of the placed sensors, w.r.t. originFront
double sensorCentroidX = 0;
double sensorCentroidZ = 0;
int sensorCount = 0;
// sensitive detector type
sens.setType("photoncounter");
sens.setType("tracker");
// SECTOR LOOP //////////////////////////////////
for(int isec=0; isec<nSectors; isec++) {
// BUILD RADIATOR ====================================================================
if(mirrorDebug*isec>0 || sensorSphDebug*isec>0) continue; // if debugging, draw only 1 sector
double sectorRotation = isec * 360/nSectors * degree; // sector rotation about z axis
// attributes
double airGap = 0.01*mm; // air gap between aerogel and filter (FIXME? actually it's currently a gas gap)
// BUILD RADIATOR ====================================================================
// derived attributes
auto radiatorPos = Position(0., 0., radiatorFrontplane) + snoutFront;
// solid and volume: create aerogel and filter
Cone aerogelSolid(
aerogelThickness/2,
radiatorRmin,
radiatorRmax,
radiatorRmin + boreDelta * aerogelThickness / vesselLength,
radiatorRmax + snoutDelta * aerogelThickness / snoutLength
);
Cone filterSolid(
filterThickness/2,
radiatorRmin + boreDelta * (aerogelThickness + airGap) / vesselLength,
radiatorRmax + snoutDelta * (aerogelThickness + airGap) / snoutLength,
radiatorRmin + boreDelta * (aerogelThickness + airGap + filterThickness) / vesselLength,
radiatorRmax + snoutDelta * (aerogelThickness + airGap + filterThickness) / snoutLength
);
// solid and volume: create aerogel and filter sectors
Tube aerogelSolid(radiatorRmin, radiatorRmax, aerogelThickness/2, -radiatorPhiw/2.0, radiatorPhiw/2.0);
Tube filterSolid( radiatorRmin, radiatorRmax, filterThickness/2, -radiatorPhiw/2.0, radiatorPhiw/2.0);
Volume aerogelVol("aerogel_v", aerogelSolid, aerogelMat);
Volume filterVol( "filter_v", filterSolid, filterMat);
aerogelVol.setVisAttributes(aerogelVis);
filterVol.setVisAttributes(filterVis);
Volume aerogelVol( detName+"_aerogel", aerogelSolid, aerogelMat );
Volume filterVol( detName+"_filter", filterSolid, filterMat );
aerogelVol.setVisAttributes(aerogelVis);
filterVol.setVisAttributes(filterVis);
// aerogel placement and surface properties
// TODO [low-priority]: define skin properties for aerogel and filter
auto radiatorPos = Position(0., 0., radiatorFrontplane) + originFront;
auto aerogelPV = gasvolVol.placeVolume(aerogelVol,
Translation3D(radiatorPos.x(), radiatorPos.y(), radiatorPos.z()) // re-center to originFront
* RotationY(radiatorPitch) // change polar angle to specified pitch // FIXME: probably broken (not yet in use anyway)
);
DetElement aerogelDE(det, "aerogel_de", 0);
aerogelDE.setPlacement(aerogelPV);
//SkinSurface aerogelSkin(desc, aerogelDE, "mirror_optical_surface", aerogelSurf, aerogelVol);
//aerogelSkin.isValid();
// placement
auto aerogelPV = gasvolVol.placeVolume(aerogelVol,
RotationZ(sectorRotation) // rotate about beam axis to sector
* Translation3D(radiatorPos.x(), radiatorPos.y(), radiatorPos.z()) // re-center to snoutFront
* RotationY(radiatorPitch) // change polar angle to specified pitch
);
// filter placement and surface properties
if(!debug_optics) {
auto filterPV = gasvolVol.placeVolume(filterVol,
RotationZ(sectorRotation) // rotate about beam axis to sector
* Translation3D(radiatorPos.x(), radiatorPos.y(), radiatorPos.z()) // re-center to snoutFront
* RotationY(radiatorPitch) // change polar angle
* Translation3D(0., 0., (aerogelThickness+filterThickness)/2.) // move to aerogel backplane
);
// properties
// TODO [critical]: define skin properties for aerogel and filter
DetElement aerogelDE(det, Form("aerogel_de%d", isec), isec);
aerogelDE.setPlacement(aerogelPV);
//SkinSurface aerogelSkin(desc, aerogelDE, Form("mirror_optical_surface%d", isec), aerogelSurf, aerogelVol);
//aerogelSkin.isValid();
DetElement filterDE(det, Form("filter_de%d", isec), isec);
Translation3D(0., 0., airGap) // add an air gap
* Translation3D(radiatorPos.x(), radiatorPos.y(), radiatorPos.z()) // re-center to originFront
* RotationY(radiatorPitch) // change polar angle
* Translation3D(0., 0., (aerogelThickness+filterThickness)/2.) // move to aerogel backplane
);
DetElement filterDE(det, "filter_de", 0);
filterDE.setPlacement(filterPV);
//SkinSurface filterSkin(desc, filterDE, Form("mirror_optical_surface%d", isec), filterSurf, filterVol);
//SkinSurface filterSkin(desc, filterDE, "mirror_optical_surface", filterSurf, filterVol);
//filterSkin.isValid();
};
// BUILD MIRROR ====================================================================
// SECTOR LOOP //////////////////////////////////
for(int isec=0; isec<nSectors; isec++) {
// derived attributes
auto mirrorPos = Position(mirrorCenterX, 0., mirrorBackplane) + snoutFront;
double mirrorThetaRot = std::asin(mirrorCenterX/mirrorRadius);
double mirrorTheta1 = mirrorThetaRot - std::asin((mirrorCenterX-mirrorRmin)/mirrorRadius);
double mirrorTheta2 = mirrorThetaRot + std::asin((mirrorRmax-mirrorCenterX)/mirrorRadius);
// debugging filters, limiting the number of sectors
if( (debug_mirror||debug_sensors||debug_optics) && isec!=0) continue;
// if debugging, draw full sphere
if(mirrorDebug>0) { mirrorTheta1=0; mirrorTheta2=M_PI; mirrorPhiw=2*M_PI; };
// solid and volume: create sphere at origin, with specified angular limits
Sphere mirrorSolid(
mirrorRadius-mirrorThickness,
mirrorRadius,
mirrorTheta1,
mirrorTheta2,
-mirrorPhiw/2.0,
mirrorPhiw/2.0
);
Volume mirrorVol("mirror_v", mirrorSolid, mirrorMat);
mirrorVol.setVisAttributes(mirrorVis);
// sector rotation about z axis
double sectorRotation = isec * 360/nSectors * degree;
std::string secName = "sec" + std::to_string(isec);
// placement (note: transformations are in reverse order)
auto mirrorPV = gasvolVol.placeVolume(mirrorVol,
RotationZ(sectorRotation) // rotate about beam axis to sector
* Translation3D(0,0,-mirrorRadius) // move longitudinally so it intersects snoutFront
* Translation3D(mirrorPos.x(), mirrorPos.y(), mirrorPos.z()) // re-center to snoutFront
* RotationY(-mirrorThetaRot) // rotate about origin
);
// properties
DetElement mirrorDE(det, Form("mirror_de%d", isec), isec);
mirrorDE.setPlacement(mirrorPV);
SkinSurface mirrorSkin(desc, mirrorDE, Form("mirror_optical_surface%d", isec), mirrorSurf, mirrorVol);
mirrorSkin.isValid();
// BUILD SENSORS ====================================================================
// if debugging sphere properties, restrict number of sensors drawn
if(sensorSphDebug>0) { sensorSide = 2*M_PI*sensorSphRadius / 64; };
if(debug_sensors) { sensorSide = 2*M_PI*sensorSphRadius / 64; };
// solid and volume: single sensor module
Box sensorSolid(sensorSide/2., sensorSide/2., sensorThickness/2.);
Volume sensorVol("sensor_v", sensorSolid, sensorMat);
Volume sensorVol(detName+"_sensor_"+secName, sensorSolid, sensorMat);
sensorVol.setVisAttributes(sensorVis);
auto sensorSphPos = Position(sensorSphCenterX, 0., sensorSphCenterZ) + originFront;
// sensitivity
sensorVol.setSensitiveDetector(sens);
if(!debug_optics) sensorVol.setSensitiveDetector(sens);
// SENSOR MODULE LOOP ------------------------
/* ALGORITHM: generate sphere of positions
......@@ -299,13 +324,13 @@ static Ref_t createDetector(Detector& desc, xml::Handle_t handle, SensitiveDetec
int imod=0;
// thetaGen loop: iterate less than "0.5 circumference / sensor size" times
double nTheta = M_PI*sensorSphRadius / (sensorSide+sensorGap);
double nTheta = M_PI*sensorSphRadius / (sensorSide+sensorGap);
for(int t=0; t<(int)(nTheta+0.5); t++) {
double thetaGen = t/((double)nTheta) * M_PI;
// phiGen loop: iterate less than "circumference at this latitude / sensor size" times
double nPhi = 2*M_PI * sensorSphRadius * std::sin(thetaGen) / (sensorSide+sensorGap);
for(int p=0; p<(int)(nPhi+0.5); p++) {
double nPhi = 2*M_PI * sensorSphRadius * std::sin(thetaGen) / (sensorSide+sensorGap);
for(int p=0; p<(int)(nPhi+0.5); p++) {
double phiGen = p/((double)nPhi) * 2*M_PI - M_PI; // shift to [-pi,pi]
// determine global phi and theta
......@@ -321,35 +346,35 @@ static Ref_t createDetector(Detector& desc, xml::Handle_t handle, SensitiveDetec
double phi = std::atan2(y,x);
double theta = std::acos(z/sensorSphRadius);
// cut spherical patch
// TODO [low priority]: instead of cutting a patch with complicated parameters,
// can we use something simpler such as Union or
// Intersection of solids?
// - applied on global coordinates
// - theta cuts are signed, since we will offset the patch along +x;
// from the offset position, toward barrel is positive, toward beam is negative
double thetaSigned = (x<0?-1:1) * theta;
// - position of yz planes, associated to theta cuts
double xmin = sensorSphRadius * std::sin(sensorSphPatchThetaMin/2);
double xmax = sensorSphRadius * std::sin(sensorSphPatchThetaMax/2);
// - we want a phi wedge, but offset from the origin to allow more width, so
// define phiCheck to account for the offset; the amount of the offset,
// and hence the width, is controlled by `sensorSphPatchWidthFactor`
double phiCheck = std::atan2(y,(x+sensorSphCenterX)/sensorSphPatchWidthFactor);
// - apply cuts (only if not debugging)
// - NOTE: use `x<xmax` for straight cuts, or `theta<sensorSphPatchThetaMax` for
// rounded cuts (which allows for more sensors)
if( ( std::fabs(phiCheck)<sensorSphPatchTaper && x>xmin && theta<sensorSphPatchThetaMax && z>0 )
|| sensorSphDebug>0
) {
// shift global coordinates so we can apply spherical patch cuts
double zCheck = z + sensorSphCenterZ;
double xCheck = x + sensorSphCenterX;
double yCheck = y;
double rCheck = std::hypot(xCheck,yCheck);
double phiCheck = std::atan2(yCheck,xCheck);
// patch cut
bool patchCut =
std::fabs(phiCheck) < sensorSphPatchPhiw
&& zCheck > sensorSphPatchZmin
&& rCheck > sensorSphPatchRmin
&& rCheck < sensorSphPatchRmax;
if(debug_sensors) patchCut = std::fabs(phiCheck) < sensorSphPatchPhiw;
if(patchCut) {
// append sensor position to centroid calculation
if(isec==0) {
sensorCentroidX += xCheck;
sensorCentroidZ += zCheck;
sensorCount++;
};
// placement (note: transformations are in reverse order)
// - transformations operate on global coordinates; the corresponding
// generator coordinates are provided in the comments
auto sensorPV = gasvolVol.placeVolume(sensorVol,
RotationZ(sectorRotation) // rotate about beam axis to sector
* Translation3D(sensorSphCenterX, sensorSphCenterY, sensorSphCenterZ) // move sphere to specified center
* Translation3D(snoutFront.x(), snoutFront.y(), snoutFront.z()) // move sphere to reference position
* Translation3D(sensorSphPos.x(), sensorSphPos.y(), sensorSphPos.z()) // move sphere to reference position
* RotationX(phiGen) // rotate about `zGen`
* RotationZ(thetaGen) // rotate about `yGen`
* Translation3D(sensorSphRadius, 0., 0.) // push radially to spherical surface
......@@ -357,15 +382,17 @@ static Ref_t createDetector(Detector& desc, xml::Handle_t handle, SensitiveDetec
* RotationZ(-M_PI/2) // correction for readout segmentation mapping
);
// generate LUT for module number -> sensor position, for readout mapping tests
//if(isec==0) printf("%d %f %f\n",imod,sensorPV.position().x(),sensorPV.position().y());
// generate LUT for module number -> sensor position, for readout mapping tests
//if(isec==0) printf("%d %f %f\n",imod,sensorPV.position().x(),sensorPV.position().y());
// properties
sensorPV.addPhysVolID("sector", isec).addPhysVolID("module", imod);
DetElement sensorDE(det, Form("sensor_de%d_%d", isec, imod), 10000*isec+imod);
DetElement sensorDE(det, Form("sensor_de%d_%d", isec, imod), (imod<<3)|isec ); // id must match IRTAlgorithm usage
sensorDE.setPlacement(sensorPV);
SkinSurface sensorSkin(desc, sensorDE, Form("sensor_optical_surface%d", isec), sensorSurf, sensorVol);
sensorSkin.isValid();
if(!debug_optics) {
SkinSurface sensorSkin(desc, sensorDE, Form("sensor_optical_surface%d", isec), sensorSurf, sensorVol);
sensorSkin.isValid();
};
// increment sensor module number
imod++;
......@@ -373,9 +400,132 @@ static Ref_t createDetector(Detector& desc, xml::Handle_t handle, SensitiveDetec
}; // end patch cuts
}; // end phiGen loop
}; // end thetaGen loop
// calculate centroid sensor position
if(isec==0) {
sensorCentroidX /= sensorCount;
sensorCentroidZ /= sensorCount;
};
// END SENSOR MODULE LOOP ------------------------
// BUILD MIRRORS ====================================================================
// derive spherical mirror parameters `(zM,xM,rM)`, for given image point
// coordinates `(zI,xI)` and `dO`, defined as the z-distance between the
// object and the mirror surface
// - all coordinates are specified w.r.t. the object point coordinates
// - this is point-to-point focusing, but it can be used to effectively steer
// parallel-to-point focusing
double zM,xM,rM;
auto FocusMirror = [&zM,&xM,&rM](double zI, double xI, double dO) {
zM = dO*zI / (2*dO-zI);
xM = dO*xI / (2*dO-zI);
rM = dO - zM;
};
// attributes, re-defined w.r.t. IP, needed for mirror positioning
double zS = sensorSphCenterZ + vesselZmin; // sensor sphere attributes
double xS = sensorSphCenterX;
double rS = sensorSphRadius;
double B = vesselZmax - mirrorBackplane; // distance between IP and mirror back plane
// focus 1: set mirror to focus IP on center of sensor sphere `(zS,xS)`
/*double zF = zS;
double xF = xS;
FocusMirror(zF,xF,B);*/
// focus 2: move focal region along sensor sphere radius, according to `focusTuneLong`
// - specifically, along the radial line which passes through the approximate centroid
// of the sensor region `(sensorCentroidZ,sensorCentroidX)`
// - `focusTuneLong` is the distance to move, given as a fraction of `sensorSphRadius`
// - `focusTuneLong==0` means `(zF,xF)==(zS,xS)`
// - `focusTuneLong==1` means `(zF,xF)` will be on the sensor sphere, near the centroid
/*
double zC = sensorCentroidZ + vesselZmin;
double xC = sensorCentroidX;
double slopeF = (xC-xS) / (zC-zS);
double thetaF = std::atan(std::fabs(slopeF));
double zF = zS + focusTuneLong * sensorSphRadius * std::cos(thetaF);
double xF = xS - focusTuneLong * sensorSphRadius * std::sin(thetaF);
//FocusMirror(zF,xF,B);
// focus 3: move along line perpendicular to focus 2's radial line,
// according to `focusTunePerp`, with the same numerical scale as `focusTuneLong`
zF += focusTunePerp * sensorSphRadius * std::cos(M_PI/2-thetaF);
xF += focusTunePerp * sensorSphRadius * std::sin(M_PI/2-thetaF);
FocusMirror(zF,xF,B);
*/
// focus 4: use (z,x) coordinates for tune parameters
double zF = zS + focusTuneZ;
double xF = xS + focusTuneX;
FocusMirror(zF,xF,B);
// re-define mirror attributes to be w.r.t vessel front plane
double mirrorCenterZ = zM - vesselZmin;
double mirrorCenterX = xM;
double mirrorRadius = rM;
// spherical mirror patch cuts and rotation
double mirrorThetaRot = std::asin(mirrorCenterX/mirrorRadius);
double mirrorTheta1 = mirrorThetaRot - std::asin((mirrorCenterX-mirrorRmin)/mirrorRadius);
double mirrorTheta2 = mirrorThetaRot + std::asin((mirrorRmax-mirrorCenterX)/mirrorRadius);
// if debugging, draw full sphere
if(debug_mirror) { mirrorTheta1=0; mirrorTheta2=M_PI; /*mirrorPhiw=2*M_PI;*/ };
// solid : create sphere at origin, with specified angular limits;
// phi limits are increased to fill gaps (overlaps are cut away later)
Sphere mirrorSolid1(
mirrorRadius,
mirrorRadius + mirrorThickness,
mirrorTheta1,
mirrorTheta2,
-40*degree,
40*degree
);
/* CAUTION: if any of the relative placements or boolean operations below
* are changed, you MUST make sure this does not break access to the sphere
* primitive and positioning in Juggler `IRTAlgorithm`; cross check the
* mirror sphere attributes carefully!
*/
/*
// PRINT MIRROR ATTRIBUTES (before any sector z-rotation)
printf("zM = %f\n",zM); // sphere centerZ, w.r.t. IP
printf("xM = %f\n",xM); // sphere centerX, w.r.t. IP
printf("rM = %f\n",rM); // sphere radius
*/
// mirror placement transformation (note: transformations are in reverse order)
auto mirrorPos = Position(mirrorCenterX, 0., mirrorCenterZ) + originFront;
Transform3D mirrorPlacement(
Translation3D(mirrorPos.x(), mirrorPos.y(), mirrorPos.z()) // re-center to specified position
* RotationY(-mirrorThetaRot) // rotate about vertical axis, to be within vessel radial walls
);
// cut overlaps with other sectors using "pie slice" wedges, to the extent specified
// by `mirrorPhiw`
Tube pieSlice( 0.01*cm, vesselRmax2, tankLength/2.0, -mirrorPhiw/2.0, mirrorPhiw/2.0);
IntersectionSolid mirrorSolid2( pieSlice, mirrorSolid1, mirrorPlacement );
// mirror volume, attributes, and placement
Volume mirrorVol(detName+"_mirror_"+secName, mirrorSolid2, mirrorMat);
mirrorVol.setVisAttributes(mirrorVis);
auto mirrorPV2 = gasvolVol.placeVolume(mirrorVol,
RotationZ(sectorRotation) // rotate about beam axis to sector
* Translation3D(0,0,0)
);
// properties
DetElement mirrorDE(det, Form("mirror_de%d", isec), isec);
mirrorDE.setPlacement(mirrorPV2);
SkinSurface mirrorSkin(desc, mirrorDE, Form("mirror_optical_surface%d", isec), mirrorSurf, mirrorVol);
mirrorSkin.isValid();
}; // END SECTOR LOOP //////////////////////////
......@@ -387,7 +537,7 @@ static Ref_t createDetector(Detector& desc, xml::Handle_t handle, SensitiveDetec
// place mother volume (vessel)
Volume motherVol = desc.pickMotherVolume(det);
PlacedVolume vesselPV = motherVol.placeVolume(vesselVol,
Position(0, 0, vesselZ0) - snoutFront
Position(0, 0, vesselZmin) - originFront
);
vesselPV.addPhysVolID("system", detID);
det.setPlacement(vesselPV);
......