File indexing completed on 2025-01-18 09:15:55
0001
0002
0003
0004
0005
0006
0007 #include "DD4hep/DetFactoryHelper.h"
0008 #include <XML/Helper.h>
0009 #include <algorithm>
0010 #include <iostream>
0011 #include <tuple>
0012 #include <TVector3.h>
0013
0014 using namespace std;
0015 using namespace dd4hep;
0016
0017
0018 static tuple<Volume, Position> build_specScFiCAL_module(const Detector& description,
0019 const xml::Component& mod_x,
0020 SensitiveDetector& sens);
0021
0022
0023 static Ref_t create_detector(Detector& description, xml_h e, SensitiveDetector sens) {
0024 sens.setType("calorimeter");
0025
0026 xml_det_t x_det = e;
0027 xml_comp_t x_mod = x_det.child(_Unicode(module));
0028 string det_name = x_det.nameStr();
0029 int det_ID = x_det.id();
0030
0031 Material Air = description.material("Air");
0032
0033
0034 DetElement det(det_name, det_ID);
0035
0036
0037 Volume motherVol = description.pickMotherVolume(det);
0038
0039
0040 Assembly assembly(det_name);
0041 assembly.setVisAttributes(description.visAttributes(x_det.attr<std::string>(_Unicode(vis))));
0042
0043 double detSizeXY = getAttrOrDefault(x_det, _Unicode(sizeXY), 180 * mm);
0044 double detSizeZ = getAttrOrDefault(x_det, _Unicode(sizeZ), 180 * mm);
0045 int nmod_perlayer = getAttrOrDefault(x_det, _Unicode(nmod_perlayer), 3);
0046 int nlayer = getAttrOrDefault(x_det, _Unicode(nlayer), 20);
0047
0048
0049 xml_comp_t pos = x_det.position();
0050 xml_comp_t rot = x_det.rotation();
0051
0052
0053 auto [modVol, modSize] = build_specScFiCAL_module(description, x_mod, sens);
0054
0055
0056 xml_comp_t x_layer = x_det.child(_Unicode(layer));
0057
0058 double laySizeX = getAttrOrDefault(x_layer, _Unicode(sizeX), 1.0 * cm);
0059 double laySizeY = getAttrOrDefault(x_layer, _Unicode(sizeY), 1.0 * cm);
0060 double laySizeZ = getAttrOrDefault(x_layer, _Unicode(sizeZ), 1.0 * cm);
0061 double layerCoatSizeX = getAttrOrDefault(x_layer, _Unicode(coatSizeX), 1.0 * cm);
0062 double layerCoatSizeY = getAttrOrDefault(x_layer, _Unicode(coatSizeY), 1.0 * cm);
0063
0064 Material layMat = description.material(x_layer.attr<std::string>(_Unicode(material)));
0065
0066 Box layerBox(laySizeX / 2.0, laySizeY / 2.0, laySizeZ / 2.0);
0067 Volume layerVol("layer", layerBox, layMat);
0068 layerVol.setVisAttributes(description.visAttributes(x_det.attr<std::string>(_Unicode(vis))));
0069
0070
0071 double mod_pos0 = -(detSizeXY / 2.0) + (modSize.x() / 2.0) + layerCoatSizeX;
0072 double layer_pos0 = -(detSizeZ / 2.0) + (modSize.y() / 2.0) + layerCoatSizeY;
0073
0074
0075 for (int mod_id = 0; mod_id < nmod_perlayer; mod_id++) {
0076
0077
0078 double mod_pos_z = 0.0 * cm;
0079 double mod_pos_y = 0.0 * cm;
0080 double mod_pos_x = mod_id * modSize.x() + mod_pos0;
0081
0082 PlacedVolume modPV = layerVol.placeVolume(modVol, Position(mod_pos_x, mod_pos_y, mod_pos_z));
0083 modPV.addPhysVolID("module", mod_id);
0084 }
0085
0086
0087 Box sectorBox(detSizeXY / 2, detSizeXY / 2, detSizeZ / 2);
0088 Volume sectorVol(det_name + "_sector", sectorBox, Air);
0089 sectorVol.setVisAttributes(description.visAttributes(x_mod.attr<std::string>(_Unicode(vis))));
0090
0091
0092 for (int layer_id = 0; layer_id < nlayer; layer_id++) {
0093
0094 double lay_pos_z = -layer_id * (modSize.y() + 2.0 * layerCoatSizeY) - layer_pos0;
0095 double lay_pos_y = 0.0 * cm;
0096 double lay_pos_x = 0.0 * cm;
0097 int orientation = layer_id % 2 == 0;
0098
0099
0100 RotationZYX lay_rot = RotationZYX(0, 0, -90.0 * degree);
0101 if (orientation)
0102 lay_rot *= RotationY(-90.0 * degree);
0103
0104 PlacedVolume layPV = sectorVol.placeVolume(
0105 layerVol, Transform3D(lay_rot, Position(lay_pos_x, lay_pos_y, lay_pos_z)));
0106 layPV.addPhysVolID("layer", layer_id);
0107 }
0108
0109
0110 for (xml_coll_t si(x_det, _Unicode(sector)); si; si++) {
0111
0112 xml_comp_t x_sector(si);
0113 int sector_id = x_sector.id();
0114 xml_comp_t sec_pos = x_sector.position();
0115 xml_comp_t sec_rot = x_sector.rotation();
0116
0117 PlacedVolume secPV = assembly.placeVolume(
0118 sectorVol, Transform3D(RotationZYX(sec_rot.z(), sec_rot.y(), sec_rot.x()),
0119 Position(sec_pos.x(), sec_pos.y(), sec_pos.z())));
0120 secPV.addPhysVolID("sector", sector_id);
0121 }
0122
0123
0124 PlacedVolume detPV =
0125 motherVol.placeVolume(assembly, Transform3D(RotationZYX(rot.z(), rot.y(), rot.x()),
0126 Position(pos.x(), pos.y(), pos.z())));
0127 detPV.addPhysVolID("system", det_ID);
0128
0129 det.setPlacement(detPV);
0130
0131 return det;
0132 }
0133
0134 static tuple<Volume, Position> build_specScFiCAL_module(const Detector& description,
0135 const xml::Component& mod_x,
0136 SensitiveDetector& sens) {
0137
0138
0139 double sx = mod_x.attr<double>(_Unicode(sizex));
0140 double sy = mod_x.attr<double>(_Unicode(sizey));
0141 double sz = mod_x.attr<double>(_Unicode(sizez));
0142
0143 Position modSize(sx, sy, sz);
0144
0145 Box modShape(modSize.x() / 2.0, modSize.y() / 2.0, modSize.z() / 2.0);
0146 auto modMat = description.material(mod_x.attr<std::string>(_Unicode(material)));
0147 Volume modVol("module_vol", modShape, modMat);
0148
0149 modVol.setVisAttributes(description.visAttributes(mod_x.attr<std::string>(_Unicode(vis))));
0150
0151
0152
0153
0154 auto fiber_block = mod_x.child(_Unicode(block));
0155
0156 auto fb_sx = fiber_block.attr<double>(_Unicode(sizeX));
0157 auto fb_sy = fiber_block.attr<double>(_Unicode(sizeY));
0158 auto fb_sz = fiber_block.attr<double>(_Unicode(sizeZ));
0159 auto fb_SpaceXY = fiber_block.attr<double>(_Unicode(SpaceXY));
0160
0161 Position fbSize(fb_sx, fb_sy, fb_sz);
0162
0163
0164 auto fiber_tube = mod_x.child(_Unicode(fiber));
0165
0166 auto fr = fiber_tube.attr<double>(_Unicode(radius));
0167 auto fsx = fiber_tube.attr<double>(_Unicode(spacex));
0168 auto fsy = fiber_tube.attr<double>(_Unicode(spacey));
0169
0170
0171 Box fbShape(fbSize.x() / 2.0, fbSize.y() / 2.0, fbSize.z() / 2.0);
0172 Volume fbVol("fiberblock_volume", fbShape, modMat);
0173 fbVol.setVisAttributes(
0174 description.visAttributes(mod_x.attr<std::string>(_Unicode(vis))));
0175
0176 int num_fbX = int(modSize.x() / (fbSize.x() + 2.0 * fb_SpaceXY));
0177 int num_fbY = int(modSize.y() / (fbSize.y() + 2.0 * fb_SpaceXY));
0178
0179 double fb_xpos0 = -(modSize.x() / 2.0) + (fbSize.x() / 2.0) + fb_SpaceXY;
0180 double fb_ypos0 = -(modSize.y() / 2.0) + (fbSize.y() / 2.0) + fb_SpaceXY;
0181 int nblock = 0;
0182
0183 for (int iy = 0; iy < num_fbY; iy++) {
0184 for (int ix = 0; ix < num_fbX; ix++) {
0185 double fb_pos_x = fb_xpos0 + ix * (fbSize.x() + 2.0 * fb_SpaceXY);
0186 double fb_pos_y = fb_ypos0 + iy * (fbSize.y() + 2.0 * fb_SpaceXY);
0187 double fb_pos_z = 0 * mm;
0188
0189 auto fbPV = modVol.placeVolume(fbVol, nblock, Position{fb_pos_x, fb_pos_y, fb_pos_z});
0190 fbPV.addPhysVolID("block", nblock++);
0191 }
0192 }
0193
0194
0195 auto fiberMat = description.material(fiber_tube.attr<std::string>(_Unicode(material)));
0196 Tube fiberShape(0., fr, fbSize.z() / 2.0);
0197 Volume fiberVol("fiber_vol", fiberShape, fiberMat);
0198 fiberVol.setVisAttributes(description.visAttributes(fiber_tube.attr<std::string>(_Unicode(vis))));
0199 fiberVol.setSensitiveDetector(sens);
0200
0201 int num_fX = int(fbSize.x() / (2 * fr + 2.0 * fsx));
0202 int num_fY = int(fbSize.y() / (2 * fr + 2.0 * fsy));
0203
0204 double fiber_xpos0 = -(fbSize.x() / 2.0) + fr + fsx;
0205 double fiber_ypos0 = -(fbSize.y() / 2.0) + fr + fsy;
0206 int nfibers = 0;
0207
0208
0209 auto fiberholder_x = mod_x.child(_Unicode(fiberholder));
0210 double fh_dz = 0.25 * mm;
0211
0212 double fh_outerbox_y = 2.0 * fr + 2.0 * fsy;
0213 double fh_outerbox_x = 2.0 * fr + 2.0 * fsx;
0214 Box fh_outerbox(fh_outerbox_x / 2.0, fh_outerbox_y / 2.0, fh_dz / 2.0);
0215
0216 double fh_innerbox_y = 2.0 * fr;
0217 double fh_innerbox_x = 2.0 * fr;
0218 Box fh_innerbox(fh_innerbox_x / 2.0, fh_innerbox_y / 2.0, fh_dz / 2.0);
0219
0220 SubtractionSolid fiberholder_solid(fh_outerbox, fh_innerbox, Position(0.0, 0.0, 0.0));
0221 auto fiberholderMat = description.material(fiberholder_x.attr<std::string>(_Unicode(material)));
0222 Volume fiberholderVol("fiberholder_vol", fiberholder_solid, fiberholderMat);
0223 fiberholderVol.setVisAttributes(
0224 description.visAttributes(fiberholder_x.attr<std::string>(_Unicode(vis))));
0225
0226 int nfh = 0;
0227
0228
0229 for (int iy = 0; iy < num_fY; iy++) {
0230 for (int ix = 0; ix < num_fX; ix++) {
0231
0232 double fiber_pos_x = fiber_xpos0 + ix * (2.0 * fr + 2.0 * fsx);
0233 double fiber_pos_y = fiber_ypos0 + iy * (2.0 * fr + 2.0 * fsy);
0234 double fiber_pos_z = 0 * mm;
0235
0236
0237 auto fiberPV =
0238 fbVol.placeVolume(fiberVol, nfibers++, Position{fiber_pos_x, fiber_pos_y, fiber_pos_z});
0239 fiberPV.addPhysVolID("fiber_x", ix + 1).addPhysVolID("fiber_y", iy + 1);
0240
0241
0242 int num_holders = 6;
0243 double fh_pos_z0 = -1 * (fbSize.z() / 2.0) + (fh_dz / 2.0);
0244
0245 for (int iz = 0; iz < num_holders; iz++) {
0246 double fh_pos_z = fh_pos_z0 + iz * ((fbSize.z() - fh_dz) / (num_holders - 1));
0247 fbVol.placeVolume(fiberholderVol, nfh++, Position{fiber_pos_x, fiber_pos_y, fh_pos_z});
0248 }
0249
0250 }
0251 }
0252
0253 return make_tuple(modVol, modSize);
0254
0255 }
0256
0257 DECLARE_DETELEMENT(EcalLumiSpecWScFi, create_detector)