Skip to content
Snippets Groups Projects
Commit 8fe82eae authored by Whitney Armstrong's avatar Whitney Armstrong
Browse files

Merge branch 'master' into 'master'

Roman pots

See merge request !26
parents da4b8ecb 957d1503
No related branches found
No related tags found
No related merge requests found
......@@ -28,6 +28,7 @@ dd4hep_add_plugin(GenDetectors
trackers/src/SiliconTrackerBarrel_geo.cpp
trackers/src/SiTrackerRomanPot_geo.cpp
trackers/src/SimpleRomanPot_geo.cpp
trackers/src/RomanPot_geo.cpp # WIP
calorimeters/src/CylindricalEndcapCalorimeter_geo.cpp
calorimeters/src/EcalBarrel_geo.cpp
calorimeters/src/PolyhedraEndcapCalorimeter3_geo.cpp
......
<lccdd xmlns:compact="http://www.lcsim.org/schemas/compact/1.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xs:noNamespaceSchemaLocation="http://www.lcsim.org/schemas/compact/1.0/compact.xsd">
<info name="RomanPot_example" title="Roman Pot detector example"
author="Tomas Polakovic"
url="https://eicweb.phy.anl.gov/EIC/NPDet"
status="development"
version="$Id: compact.xml v1.0 2016-12-21$">
<comment>A simplified Roman pot detector</comment>
</info>
<includes>
<gdmlFile ref="elements.xml"/>
<gdmlFile ref="materials.xml"/>
</includes>
<define>
<constant name="world_side" value="10*m"/>
<constant name="world_x" value="world_side"/>
<constant name="world_y" value="world_side"/>
<constant name="world_z" value="world_side"/>
<constant name="CrossingAngle" value="0.020*rad"/>
</define>
<limits>
<limitset name="cal_limits">
<limit name="step_length_max" particles="*" value="5.0" unit="mm" />
</limitset>
<limitset name="SimpleRomanPotRegionLimitSet">
<limit name="step_length_max" particles="*" value="1.0" unit="mm" />
<limit name="track_length_max" particles="*" value="1.0" unit="mm" />
<limit name="time_max" particles="*" value="0.1" unit="ns" />
<limit name="ekin_min" particles="*" value="0.001" unit="MeV" />
<limit name="range_min" particles="*" value="0.1" unit="mm" />
</limitset>
</limits>
<regions>
<region name="SimpleRomanPotRegion" eunit="MeV" lunit="mm" cut="0.0001" threshold="0.0001">
<limitsetref name="SimpleRomanPotRegionLimitSet"/>
</region>
</regions>
<comment>Common Generic visualization attributes</comment>
<display>
<vis name="InvisibleNoDaughters" showDaughters="false" visible="false"/>
<vis name="InvisibleWithDaughters" showDaughters="true" visible="false"/>
<vis name="GreenVis" alpha="0.5" r= "0.0" g="1.0" b="0.0" showDaughters="true" visible="true"/>
<vis name="RedVis" alpha="0.0" r= "1.0" g="0.0" b="0.0" showDaughters="true" visible="true"/>
<vis name="BlueVis" alpha="0.0" r= "0.0" g="0.0" b="1.0" showDaughters="true" visible="true"/>
<vis name="OrangeVis" alpha="0.5" r= "1.0" g="0.45" b="0.0" showDaughters="true" visible="true"/>
<vis name="RedGreenVis" alpha="0.5" r= "1.0" g="1.0" b="0.0" showDaughters="true" visible="true"/>
<vis name="BlueGreenVis" alpha="0.5" r= "0.0" g="1.0" b="1.0" showDaughters="true" visible="true"/>
<vis name="PurpleVis" alpha="0.5" r= "1.0" g="0.0" b="1.0" showDaughters="true" visible="true"/>
<vis name="DoubleRedG" alpha="0.5" r= "2.0" g=".10" b="0.0" showDaughters="true" visible="true"/>
<vis name="RBG015" alpha="0.5" r= "0.0" g=".2" b="1.0" showDaughters="true" visible="true"/>
<vis name="RBG510" alpha="0.5" r= "1.0" g=".2" b="0.0" showDaughters="true" visible="true"/>
<vis name="RBG" alpha="0.5" r= "1.0" g="1.0" b="1.0" showDaughters="true" visible="true"/>
<vis name="GrayVis" alpha="0.5" r= "0.75" g="0.75" b="0.75" showDaughters="true" visible="true"/>
</display>
<detectors>
<detector id = "1" name = "MyRomanPot" type = "RomanPot" readout =
"ForwardRomanPotHits" vis = "RedVis">
<dimensions x = "3.0*cm" y = "3.0*cm" z = "0.03*cm" delta = "0.005*cm" />
<support z = "1*mm" />
<frame x = "10.0*cm" y = "5.0*cm" z = "2*cm" />
<position z_offset = "0.0*m" rotation = "false" vmax = "10*cm" v = "2.0*cm" />
<layer repeat = "5">
<slice material = "Carbon" thickness = "0.5*mm" vis = "BlueVis" />
<slice material = "Silicon" thickness = "0.03*cm" vis = "GreenVis" sensitive = "true" />
<slice material = "Carbon" thickness = "0.5*mm" vis = "BlueVis" />
<slice material = "Vacuum" thickness = "1.0*mm" vis = "InvisibleWithDaughters" />
</layer>
</detector>
</detectors>
<!-- Definition of the readout segmentation/definition -->
<readouts>
<readout name="ForwardRomanPotHits">
<!-- <id>system:5,element:5,layer:4,module:14,sensor:2,side:32:-2,strip:24</id> -->
<id>system:5,element:5,layer:4,slice:5</id>
</readout>
</readouts>
<plugins>
<!--
<plugin name="DD4hep_GenericSurfaceInstallerPlugin">
<argument value="MyRomanPot"/>
<argument value="dimension=2"/>
<argument value="u_x=-1."/>
<argument value="v_y=-1."/>
<argument value="n_z=1."/>
</plugin>
-->
<plugin name="InstallSurfaceManager"/>
</plugins>
<fields>
<field name="GlobalSolenoid" type="solenoid"
inner_field="4.0*tesla"
outer_field="-0.6*tesla"
zmax="3*m"
outer_radius="2*m">
</field>
</fields>
</lccdd>
#include "DD4hep/DetFactoryHelper.h"
#include "DD4hep/Printout.h"
#include "DD4hep/Shapes.h"
#include "TMath.h"
#include "DDRec/Surface.h"
#include "DDRec/DetectorData.h"
#include "XML/Layering.h"
using namespace std;
using namespace dd4hep;
using namespace dd4hep::rec;
using namespace ROOT::Math;
static Ref_t build_detector(Detector& dtor, xml_h e, SensitiveDetector sens) {
xml_det_t x_det = e;
Layering layering (e);
int det_id = x_det.id();
string det_name = x_det.nameStr();
xml_dim_t dim = x_det.dimensions();
double pixel_x = dim.x();
double pixel_y = dim.y();
double pixel_z = dim.z();
double delta = dim.delta();
xml_dim_t supp = x_det.child(_U(support));
double supp_z = supp.z();
xml_dim_t frame_dim = x_det.child(_U(frame));
double frame_x = frame_dim.x();
double frame_y = frame_dim.y();
double frame_z = frame_dim.z();
xml_dim_t pos = x_det.position();
double zoffset = pos.z_offset();
bool rotated = pos.attr<bool>(_Unicode(rotation));
double pos_out = pos.vmax();
double curr_pos = pos.v();
Material air = dtor.air();
Material vacuum = dtor.material("Vacuum");
Material aluminum = dtor.material("Aluminum");
Material detector_mat = dtor.material("SiliconOxide");
Material support_mat = dtor.material("Carbon");
Material frame_mat = dtor.material("Aluminum");
PlacedVolume pv;
DetElement sdet(det_name, det_id);
Assembly assembly(det_name + "_assembly");
sens.setType("tracker");
string module_name = "RomanPot";
string vis0 = dd4hep::getAttrOrDefault(x_det, _Unicode(vis), "BlueVis");
sdet.setAttributes(dtor, assembly, x_det.regionStr(), x_det.limitsStr(), x_det.visStr());
double rp_detector_tube_length = frame_x + pos_out; // TODO: Shortest possible tube given the RP dimensions. Will probably change in the future.
double rp_detector_tube_thickness = 5.0 * dd4hep::mm;
double rp_detector_tube_radius = 0.5*sqrt(frame_z * frame_z + frame_y * frame_y); // TODO: Tightest possible fit. Will probably change in the future.
Tube rp_detector_vacuum_tube(0.0, rp_detector_tube_radius + rp_detector_tube_thickness, rp_detector_tube_length);
Tube rp_detector_vacuum_tube2(0.0, rp_detector_tube_radius, rp_detector_tube_length);
// These are currently hardcoded. Will probably change in the future.
double rp_chamber_thickness = 5.0 * dd4hep::mm;
double rp_chamber_radius = 5.0 * dd4hep::cm;
double rp_chamber_length = rp_detector_tube_radius;
// All the rotation and translation shenanigans related to RP unit orientation happen here.
// `rot1` and `rot2` are used for in construction of the tubes, `shift_pos1` and `shift_pos2`
// properly transform the RP detector positions.
auto rot1 = rotated ? Rotation3D(RotationX(0.5*M_PI)) : Rotation3D(RotationY(0.5*M_PI));
auto rot2 = rotated ? Rotation3D(RotationX(-0.5*M_PI)) : Rotation3D(RotationY(-0.5*M_PI));
auto shift_pos1 = rotated ? Transform3D(RotationZ(0.5*M_PI) * Translation3D(curr_pos + 0.5*frame_x, 0.0, 0.0)) : Transform3D(Translation3D(curr_pos + 0.5*frame_x, 0, 0));
auto shift_pos2 = rotated ? Transform3D(RotationZ(-0.5*M_PI) * Translation3D(curr_pos + 0.5*frame_x, 0.0, 0.0)) : Transform3D(RotationZ(M_PI) * Translation3D(curr_pos + 0.5*frame_x, 0, 0));
auto det_offset = Position(0.5*(pixel_x + delta - frame_x), 0, 0);
// Construct the RP enclosure shell.
Tube rp_beam_pipe_tube(rp_chamber_radius, rp_chamber_radius + rp_chamber_thickness, rp_chamber_length/2.0);
Tube rp_beam_vacuum_tube(0.0, rp_chamber_radius + rp_chamber_thickness, rp_chamber_length);
Tube rp_beam_vacuum_tube2(0.0, rp_chamber_radius, rp_chamber_length);
UnionSolid rp_chamber_tee_outer1(rp_beam_vacuum_tube, rp_detector_vacuum_tube, rot1);
UnionSolid rp_chamber_tee_outer(rp_chamber_tee_outer1, rp_detector_vacuum_tube, rot2);
UnionSolid rp_chamber_tee_inner1(rp_beam_vacuum_tube2, rp_detector_vacuum_tube2, rot1);
UnionSolid rp_chamber_tee_inner(rp_chamber_tee_inner1, rp_detector_vacuum_tube2, rot2);
SubtractionSolid shell(rp_chamber_tee_inner, rp_chamber_tee_outer);
Volume rp_chamber_vol("rp_chamber_walls_vol", shell, aluminum);
Volume rp_vacuum_vol("rp_chamber_vacuum_vol", rp_chamber_tee_inner, vacuum);
pv = assembly.placeVolume(rp_chamber_vol);
auto vacuum_pv = assembly.placeVolume(rp_vacuum_vol);
vacuum_pv.addPhysVolID("element", 1);
rp_chamber_vol.setVisAttributes(vis0.c_str());
rp_vacuum_vol.setVisAttributes(dtor.invisible());
Box frame_box_full(0.5 * frame_x, 0.5 * frame_y, 0.5 * frame_z); // Make the enclosure box for the detector frame
Box det_cutoff(0.5 * (pixel_x + delta), 0.5 * (pixel_y + delta), 0.5 * frame_z); // Make the cutout where whe detector will sit
SubtractionSolid frame_box(frame_box_full, det_cutoff, det_offset); // The frame with a hole for the detector
// --- d1 ---
Volume frame1_vol("xsensor_frame1", frame_box, frame_mat);
PlacedVolume frame1_pv = rp_vacuum_vol.placeVolume(frame1_vol, shift_pos1);
// Loop over layers
double layer_pos_offset = -0.5*layering.totalThickness();
int layer_num = 1;
for (xml_coll_t c(x_det, _U(layer)); c; ++c) {
xml_comp_t x_layer = c;
int repeat = x_layer.repeat(); // How many times does the layer repeat. Defined in the compact description.
for (int j = 0; j < repeat; j++) {
string layer_name = _toString(layer_num, "layer1_%d");
double layer_thickness = layering.layer(layer_num - 1)->thickness(); // Get the thickness of the current layer.
Position layer_pos = Position(0, 0, layer_pos_offset + 0.5*layer_thickness);
Box layer_box(0.5 * (pixel_x + delta), 0.5 * (pixel_y + delta), layer_thickness);
Volume layer_vol(layer_name, layer_box, vacuum);
DetElement layer(sdet, layer_name, det_id);
// Loop over slices within the layer
double slice_pos_offset = -0.5*layer_thickness;
int slice_num = 1;
for (xml_coll_t si(x_layer, _U(slice)); si; ++si) {
xml_comp_t x_slice = si;
string slice_name = _toString(slice_num, "slice1_%d");
double slice_thickness = x_slice.thickness();
Position slice_pos = Position(0, 0, slice_pos_offset + 0.5 * slice_thickness);
Box slice_box = x_slice.isSensitive() ? Box(0.5 * pixel_x, 0.5 * pixel_y, slice_thickness) : Box(0.5 * (pixel_x + delta), 0.5 * (pixel_y + delta), slice_thickness);
Volume slice_vol(slice_name, slice_box, dtor.material(x_slice.materialStr()));
string slice_vis = dd4hep::getAttrOrDefault(x_slice, _Unicode(vis), "BlueVis");
slice_vol.setVisAttributes(slice_vis.c_str());
DetElement slice(layer, slice_name, det_id);
if (x_slice.isSensitive()) {
slice_vol.setSensitiveDetector(sens);
}
// Place the slice.
PlacedVolume slice_pv = layer_vol.placeVolume(slice_vol, slice_pos);
slice_pv.addPhysVolID("slice", slice_num);
slice.setPlacement(slice_pv);
slice_pos_offset += slice_thickness; // Move the position offset for the next slice.
++slice_num;
}
// Place the layer.
PlacedVolume layer_pv = frame1_vol.placeVolume(layer_vol, layer_pos + det_offset);
layer_pv.addPhysVolID("layer", layer_num);
layer.setPlacement(layer_pv);
layer_pos_offset += layer_thickness;
++layer_num;
}
}
// --- d2 ---
Volume frame2_vol("xsensor_frame2", frame_box, frame_mat);
PlacedVolume frame2_pv = rp_vacuum_vol.placeVolume(frame2_vol, shift_pos2);
// Loop over layers
layer_pos_offset = -0.5*layering.totalThickness();
layer_num = 1;
for (xml_coll_t c(x_det, _U(layer)); c; ++c) {
xml_comp_t x_layer = c;
int repeat = x_layer.repeat(); // How many times does the layer repeat. Defined in the compact description.
for (int j = 0; j < repeat; j++) {
string layer_name = _toString(layer_num, "layer2_%d");
double layer_thickness = layering.layer(layer_num - 1)->thickness(); // Get the thickness of the current layer.
Position layer_pos = Position(0, 0, layer_pos_offset + 0.5*layer_thickness);
Box layer_box(0.5 * (pixel_x + delta), 0.5 * (pixel_y + delta), layer_thickness);
Volume layer_vol(layer_name, layer_box, vacuum);
DetElement layer(sdet, layer_name, det_id);
// Loop over slices within the layer
double slice_pos_offset = -0.5*layer_thickness;
int slice_num = 1;
for (xml_coll_t si(x_layer, _U(slice)); si; ++si) {
xml_comp_t x_slice = si;
string slice_name = _toString(slice_num, "slice2_%d");
double slice_thickness = x_slice.thickness();
Position slice_pos = Position(0, 0, slice_pos_offset + 0.5 * slice_thickness);
Box slice_box = x_slice.isSensitive() ? Box(0.5 * pixel_x, 0.5 * pixel_y, slice_thickness) : Box(0.5 * (pixel_x + delta), 0.5 * (pixel_y + delta), slice_thickness);
Volume slice_vol(slice_name, slice_box, dtor.material(x_slice.materialStr()));
string slice_vis = dd4hep::getAttrOrDefault(x_slice, _Unicode(vis), "BlueVis");
slice_vol.setVisAttributes(slice_vis.c_str());
DetElement slice(layer, slice_name, det_id);
if (x_slice.isSensitive()) {
slice_vol.setSensitiveDetector(sens);
}
// Place the slice.
PlacedVolume slice_pv = layer_vol.placeVolume(slice_vol, slice_pos);
slice_pv.addPhysVolID("slice", slice_num);
slice.setPlacement(slice_pv);
slice_pos_offset += slice_thickness; // Move the position offset for the next slice.
++slice_num;
}
// Place the layer.
PlacedVolume layer_pv = frame2_vol.placeVolume(layer_vol, layer_pos + det_offset);
layer_pv.addPhysVolID("layer", layer_num);
layer.setPlacement(layer_pv);
layer_pos_offset += layer_thickness;
++layer_num;
}
}
pv = dtor.pickMotherVolume(sdet).placeVolume(assembly, Position(0, 0, zoffset));
pv.addPhysVolID("system", det_id);
sdet.setPlacement(pv);
assembly->GetShape()->ComputeBBox();
return sdet;
}
DECLARE_DETELEMENT(RomanPot, build_detector)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment