File indexing completed on 2026-09-17 08:29:23
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include "DD4hep/DetFactoryHelper.h"
0011 #include <XML/Helper.h>
0012 #include <XML/Layering.h>
0013 #include <XML/Utilities.h>
0014
0015 using namespace dd4hep;
0016
0017 static Ref_t createDetector(Detector& desc, xml_h handle, SensitiveDetector sens) {
0018 xml_det_t detElem = handle;
0019 std::string detName = detElem.nameStr();
0020 int detID = detElem.id();
0021
0022 xml_dim_t dim = detElem.dimensions();
0023 double width = dim.x();
0024 double height = dim.y();
0025 double length = dim.z();
0026
0027 xml_comp_t abs_dims = detElem.child("absorber_dimensions");
0028 double absorber_width = abs_dims.attr<double>("width");
0029 double absorber_height = abs_dims.attr<double>("height");
0030
0031 xml_comp_t scint_layout = detElem.child("scintillator_layout");
0032 int nrows_even = scint_layout.attr<int>("nrows_even_layers");
0033 int nrows_odd = scint_layout.attr<int>("nrows_odd_layers");
0034 int ncols_even = scint_layout.attr<int>("ncols_even_layers");
0035 int ncols_odd = scint_layout.attr<int>("ncols_odd_layers");
0036
0037 double tile = scint_layout.attr<double>("tile_side_length");
0038
0039 xml_dim_t pos = detElem.position();
0040 xml_dim_t rot = detElem.rotation();
0041
0042 Material air = desc.material("Air");
0043
0044
0045 Box envelope(width / 2.0, height / 2.0, length / 2.0);
0046
0047
0048 Volume envelopeVol(detName, envelope, air);
0049
0050 envelopeVol.setAttributes(desc, detElem.regionStr(), detElem.limitsStr(), detElem.visStr());
0051
0052 PlacedVolume pv;
0053
0054 double z_distance_traversed = 0.;
0055
0056 int layer_num = 1;
0057
0058
0059 for (xml_coll_t c(detElem, _U(layer)); c; ++c) {
0060 xml_comp_t x_layer = c;
0061 int repeat = x_layer.repeat();
0062 double layer_thickness = x_layer.thickness();
0063
0064
0065 for (int i = 0; i < repeat; i++) {
0066 std::string layer_name = detName + _toString(layer_num, "_layer%d");
0067
0068 Box layer(width / 2., height / 2., layer_thickness / 2.);
0069
0070 Volume layer_vol(layer_name, layer, air);
0071
0072 int slice_num = 1;
0073 double slice_z = -layer_thickness / 2.;
0074
0075
0076 for (xml_coll_t l(x_layer, _U(slice)); l; ++l) {
0077 xml_comp_t x_slice = l;
0078 double slice_thickness = x_slice.thickness();
0079 std::string slice_name = layer_name + _toString(slice_num, "slice%d");
0080 Material slice_mat = desc.material(x_slice.materialStr());
0081 slice_z += slice_thickness / 2.;
0082
0083 double slice_width, slice_height, slice_x, slice_y;
0084 if (x_slice.nameStr() == "ESRFoil_slice" or x_slice.nameStr() == "Scintillator_slice") {
0085 if (i % 2 == 0) {
0086 slice_width = ncols_even * tile;
0087 slice_height = nrows_even * tile;
0088 slice_x = tile / 4;
0089 slice_y = -tile / 4;
0090 }
0091 if (i % 2 == 1) {
0092 slice_width = ncols_odd * tile;
0093 slice_height = nrows_odd * tile;
0094 slice_x = -tile / 4;
0095 slice_y = -tile / 4;
0096 }
0097 } else {
0098 slice_width = absorber_width;
0099 slice_height = absorber_height;
0100 slice_x = 0;
0101 slice_y = (-nrows_even / 2 + 1 / 4) * tile + absorber_height / 2;
0102 }
0103
0104 Box slice(slice_width / 2., slice_height / 2., slice_thickness / 2.);
0105
0106 Volume slice_vol(slice_name, slice, slice_mat);
0107
0108
0109 if (x_slice.isSensitive()) {
0110 sens.setType("calorimeter");
0111 slice_vol.setSensitiveDetector(sens);
0112 }
0113
0114
0115 slice_vol.setAttributes(desc, x_slice.regionStr(), x_slice.limitsStr(), x_slice.visStr());
0116
0117
0118 pv = layer_vol.placeVolume(
0119 slice_vol, Transform3D(RotationZYX(0, 0, 0), Position(slice_x, slice_y, slice_z)));
0120 pv.addPhysVolID("slice", slice_num);
0121 slice_z += slice_thickness / 2.;
0122 z_distance_traversed += slice_thickness;
0123 ++slice_num;
0124 }
0125
0126
0127 layer_vol.setAttributes(desc, x_layer.regionStr(), x_layer.limitsStr(), x_layer.visStr());
0128
0129
0130
0131
0132
0133
0134
0135
0136 pv = envelopeVol.placeVolume(
0137 layer_vol, Transform3D(RotationZYX(0, 0, 0),
0138 Position(0., 0.,
0139 -length / 2. + (z_distance_traversed - layer_thickness) +
0140 layer_thickness / 2.)));
0141 pv.addPhysVolID("layer", layer_num);
0142 layer_num++;
0143 }
0144 }
0145
0146 DetElement det(detName, detID);
0147 Volume motherVol = desc.pickMotherVolume(det);
0148
0149
0150 dd4hep::xml::setDetectorTypeFlag(detElem, det);
0151
0152
0153 auto tr =
0154 Transform3D(RotationZYX(rot.z(), rot.y(), rot.x()), Position(pos.x(), pos.y(), pos.z()));
0155 PlacedVolume phv = motherVol.placeVolume(envelopeVol, tr);
0156 phv.addPhysVolID("system", detID);
0157 det.setPlacement(phv);
0158
0159 return det;
0160 }
0161 DECLARE_DETELEMENT(ZeroDegreeCalorimeterSiPMonTile, createDetector)