File indexing completed on 2025-12-15 09:29:45
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #include "DD4hep/DetFactoryHelper.h"
0021 #include "DD4hep/Printout.h"
0022 #include "XML/Layering.h"
0023
0024 #include "TVector3.h"
0025 #include "TGDMLParse.h"
0026 #include "FileLoaderHelper.h"
0027
0028 using namespace std;
0029 using namespace dd4hep;
0030 using namespace dd4hep::detail;
0031
0032 static Ref_t create_detector(Detector& description, xml_h e, SensitiveDetector sens) {
0033
0034
0035
0036 xml_det_t x_det = e;
0037 int det_id = x_det.id();
0038 string det_name = x_det.nameStr();
0039 Material air = description.air();
0040
0041 DetElement sdet(det_name, det_id);
0042 Volume motherVol = description.pickMotherVolume(sdet);
0043
0044
0045
0046 double rmin1 = x_det.rmin1();
0047 double rmin2 = x_det.rmin2();
0048 double rmax = x_det.rmax();
0049 double length1 = x_det.z1();
0050 double length2 = x_det.z2();
0051
0052
0053
0054 std::vector<double> rmins = {rmin2 - 0.5 * cm, rmin2 - 0.5 * cm, rmin1 - 1.5 * cm,
0055 rmin1 - 1.5 * cm, rmin2 - 0.5 * cm, rmin2 - 0.5 * cm};
0056
0057
0058 std::vector<double> rmaxs = {rmax + 1.0 * cm, rmax + 1.0 * cm, rmax + 1.0 * cm,
0059 rmax + 1.0 * cm, rmax + 1.0 * cm, rmax + 1.0 * cm};
0060
0061 std::vector<double> zs = {
0062 -length2 / 2. - 8.2 * cm, -length1 / 2., -length1 / 2., length1 / 2., length1 / 2.,
0063 length2 / 2. + 8.2 * cm};
0064
0065
0066
0067 Polycone ptube(0.0, 2.0 * M_PI, rmins, rmaxs, zs);
0068 Volume envelope(det_name, ptube, air);
0069
0070 PlacedVolume env_phv = motherVol.placeVolume(envelope);
0071 env_phv.addPhysVolID("system", det_id);
0072 sdet.setPlacement(env_phv);
0073
0074 xml_comp_t det_define = x_det.child("define");
0075
0076
0077
0078 double tilePlaneRotate = 0.0;
0079 double tile_tolerance = 0.2;
0080
0081
0082 xml_comp_t x_det_sec_gdmlfile = x_det.child("sec_gdmlfile");
0083 std::string sec_gdml_file =
0084 getAttrOrDefault<std::string>(x_det_sec_gdmlfile, _Unicode(file), " ");
0085 ;
0086 std::string sec_gdml_material =
0087 getAttrOrDefault<std::string>(x_det_sec_gdmlfile, _Unicode(material), " ");
0088 std::string sec_gdml_url = getAttrOrDefault<std::string>(x_det_sec_gdmlfile, _Unicode(url), " ");
0089 std::string sec_gdml_cache =
0090 getAttrOrDefault<std::string>(x_det_sec_gdmlfile, _Unicode(cache), " ");
0091
0092 xml_comp_t x_det_csec_gdmlfile = x_det.child("csec_gdmlfile");
0093 std::string csec_gdml_file =
0094 getAttrOrDefault<std::string>(x_det_csec_gdmlfile, _Unicode(file), " ");
0095 ;
0096 std::string csec_gdml_material =
0097 getAttrOrDefault<std::string>(x_det_csec_gdmlfile, _Unicode(material), " ");
0098 std::string csec_gdml_url =
0099 getAttrOrDefault<std::string>(x_det_csec_gdmlfile, _Unicode(url), " ");
0100 std::string csec_gdml_cache =
0101 getAttrOrDefault<std::string>(x_det_csec_gdmlfile, _Unicode(cache), " ");
0102
0103 xml_comp_t x_det_er_gdmlfile = x_det.child("er_gdmlfile");
0104 std::string er_gdml_file = getAttrOrDefault<std::string>(x_det_er_gdmlfile, _Unicode(file), " ");
0105 ;
0106 std::string er_gdml_material =
0107 getAttrOrDefault<std::string>(x_det_er_gdmlfile, _Unicode(material), " ");
0108 std::string er_gdml_url = getAttrOrDefault<std::string>(x_det_er_gdmlfile, _Unicode(url), " ");
0109 std::string er_gdml_cache =
0110 getAttrOrDefault<std::string>(x_det_er_gdmlfile, _Unicode(cache), " ");
0111
0112
0113
0114 for (xml_coll_t i(det_define, _Unicode(constant)); i; ++i) {
0115 xml_comp_t x_const = i;
0116
0117 std::string const_name = getAttrOrDefault<std::string>(x_const, _Unicode(name), " ");
0118
0119 if (const_name == "tilePlaneRotate") {
0120 std::string const_value = getAttrOrDefault<std::string>(x_const, _Unicode(value), " ");
0121 tilePlaneRotate = atof(const_value.c_str());
0122 } else
0123 printout(WARNING, "BarrelHCalCalorimeter", "unrecognized <constant> data!");
0124 }
0125
0126 std::vector<double> xposOuter;
0127 std::vector<double> yposOuter;
0128
0129 std::vector<double> xposTile;
0130 std::vector<double> yposTile;
0131 std::vector<double> zposTile;
0132
0133 std::vector<double> xposChimneyTileS;
0134 std::vector<double> yposChimneyTileS;
0135 std::vector<double> zposChimneyTileS;
0136
0137 for (xml_coll_t i(det_define, _Unicode(matrix)); i; ++i) {
0138 xml_comp_t x_mtrx = i;
0139
0140 std::string mtrx_name = getAttrOrDefault<std::string>(x_mtrx, _Unicode(name), " ");
0141 std::string mtrx_values = getAttrOrDefault<std::string>(x_mtrx, _Unicode(values), " ");
0142
0143 std::vector<double>* aptr = NULL;
0144
0145 if (mtrx_name == "xposOuter")
0146 aptr = &xposOuter;
0147 else if (mtrx_name == "yposOuter")
0148 aptr = &yposOuter;
0149 else if (mtrx_name == "xposTile")
0150 aptr = &xposTile;
0151 else if (mtrx_name == "yposTile")
0152 aptr = &yposTile;
0153 else if (mtrx_name == "zposTile")
0154 aptr = &zposTile;
0155 else if (mtrx_name == "xposChimneyTileS")
0156 aptr = &xposChimneyTileS;
0157 else if (mtrx_name == "yposChimneyTileS")
0158 aptr = &yposChimneyTileS;
0159 else if (mtrx_name == "zposChimneyTileS")
0160 aptr = &zposChimneyTileS;
0161 else {
0162 printout(WARNING, "BarrelHCalCalorimeter", "unknown <matrix> data!");
0163 continue;
0164 }
0165
0166 std::string delimiter = " ";
0167 size_t pos = 0;
0168 std::string token;
0169 while ((pos = mtrx_values.find(delimiter)) != std::string::npos) {
0170 token = mtrx_values.substr(0, pos);
0171 aptr->push_back(atof(token.c_str()));
0172 mtrx_values.erase(0, pos + delimiter.length());
0173 }
0174 aptr->push_back(atof(mtrx_values.c_str()));
0175 }
0176
0177
0178
0179 Assembly BarrelHCAL("BarrelHCAL");
0180 TGDMLParse parser;
0181
0182
0183 EnsureFileFromURLExists(sec_gdml_url, sec_gdml_file, sec_gdml_cache);
0184 if (!fs::exists(fs::path(sec_gdml_file))) {
0185 printout(ERROR, "BarrelHCalCalorimeter_geo", "file " + sec_gdml_file + " does not exist");
0186 printout(ERROR, "BarrelHCalCalorimeter_geo",
0187 "use a FileLoader plugin before the field element");
0188 std::_Exit(EXIT_FAILURE);
0189 }
0190
0191 Volume barrel_sector_vol = parser.GDMLReadFile(sec_gdml_file.c_str());
0192 if (!barrel_sector_vol.isValid()) {
0193 printout(WARNING, "BarrelHCalCalorimeter", "%s", sec_gdml_file.c_str());
0194 printout(WARNING, "BarrelHCalCalorimeter", "barrel_sector_vol invalid, GDML parser failed!");
0195 std::_Exit(EXIT_FAILURE);
0196 }
0197 barrel_sector_vol.import();
0198 barrel_sector_vol.setVisAttributes(description, x_det.visStr());
0199 TessellatedSolid barrel_sector_solid = barrel_sector_vol.solid();
0200 barrel_sector_solid->CloseShape(true, true, true);
0201 Material sector_material = description.material(sec_gdml_material.c_str());
0202 barrel_sector_vol.setMaterial(sector_material);
0203
0204
0205 EnsureFileFromURLExists(csec_gdml_url, csec_gdml_file, csec_gdml_cache);
0206 if (!fs::exists(fs::path(csec_gdml_file))) {
0207 printout(ERROR, "BarrelHCalCalorimeter_geo", "file " + csec_gdml_file + " does not exist");
0208 printout(ERROR, "BarrelHCalCalorimeter_geo",
0209 "use a FileLoader plugin before the field element");
0210 std::_Exit(EXIT_FAILURE);
0211 }
0212
0213 Volume barrel_csector_vol = parser.GDMLReadFile(csec_gdml_file.c_str());
0214 if (!barrel_csector_vol.isValid()) {
0215 printout(WARNING, "BarrelHCalCalorimeter", "%s", csec_gdml_file.c_str());
0216 printout(WARNING, "BarrelHCalCalorimeter", "barrel_csector_vol invalid, GDML parser failed!");
0217 std::_Exit(EXIT_FAILURE);
0218 }
0219 barrel_csector_vol.import();
0220 barrel_csector_vol.setVisAttributes(description, x_det.visStr());
0221 TessellatedSolid barrel_csector_solid = barrel_csector_vol.solid();
0222 barrel_csector_solid->CloseShape(true, true, true);
0223 Material csector_material = description.material(csec_gdml_material.c_str());
0224 barrel_csector_vol.setMaterial(csector_material);
0225
0226
0227 EnsureFileFromURLExists(er_gdml_url, er_gdml_file, er_gdml_cache);
0228 if (!fs::exists(fs::path(er_gdml_file))) {
0229 printout(ERROR, "BarrelHCalCalorimeter_geo", "file " + er_gdml_file + " does not exist");
0230 printout(ERROR, "BarrelHCalCalorimeter_geo",
0231 "use a FileLoader plugin before the field element");
0232 std::_Exit(EXIT_FAILURE);
0233 }
0234
0235 Volume barrel_er_vol = parser.GDMLReadFile(er_gdml_file.c_str());
0236 if (!barrel_er_vol.isValid()) {
0237 printout(WARNING, "BarrelHCalCalorimeter", "%s", er_gdml_file.c_str());
0238 printout(WARNING, "BarrelHCalCalorimeter", "barrel_er_vol invalid, GDML parser failed!");
0239 std::_Exit(EXIT_FAILURE);
0240 }
0241 barrel_er_vol.import();
0242 barrel_er_vol.setVisAttributes(description, x_det.visStr());
0243 TessellatedSolid barrel_er_solid = barrel_er_vol.solid();
0244 barrel_er_solid->CloseShape(true, true, true);
0245 Material er_material = description.material(er_gdml_material.c_str());
0246 barrel_er_vol.setMaterial(er_material);
0247
0248
0249
0250 double sec_rot_angle = 360.0 / 32.0;
0251
0252 for (int k = 0; k < 29; k++) {
0253 BarrelHCAL.placeVolume(
0254 barrel_sector_vol, k,
0255 Transform3D(RotationZ(-k * sec_rot_angle * dd4hep::deg) * RotationY(180.0 * dd4hep::deg),
0256 Translation3D(0, 0, 0)));
0257 }
0258
0259 BarrelHCAL.placeVolume(
0260 barrel_csector_vol, 0,
0261 Transform3D(RotationZ(sec_rot_angle * dd4hep::deg) * RotationY(180.0 * dd4hep::deg),
0262 Translation3D(0, 0, 0)));
0263
0264 BarrelHCAL.placeVolume(barrel_csector_vol, 1,
0265 Transform3D(RotationY(180.0 * dd4hep::deg), Translation3D(0, 0, 0)));
0266
0267 BarrelHCAL.placeVolume(
0268 barrel_csector_vol, 2,
0269 Transform3D(RotationZ(-sec_rot_angle * dd4hep::deg) * RotationY(180.0 * dd4hep::deg),
0270 Translation3D(0, 0, 0)));
0271
0272 BarrelHCAL.placeVolume(barrel_er_vol, 0,
0273 Transform3D(RotationY(180.0 * dd4hep::deg), Translation3D(0, 0, 0)));
0274
0275 BarrelHCAL.placeVolume(barrel_er_vol, 1,
0276 Transform3D(RotationY(0.0 * dd4hep::deg), Translation3D(0, 0, 0)));
0277
0278
0279
0280 Volume Tile[12];
0281 Volume ChimneyTile[4];
0282
0283 for (int j = 1; j < 17; j++) {
0284
0285 std::string gdmlname;
0286 std::string solid_name;
0287
0288 if (j < 13) {
0289
0290
0291
0292 gdmlname = _toString(j, "tile%d_gdmlfile");
0293 solid_name = _toString(j, "OuterHCalTile%02d");
0294
0295 } else {
0296
0297
0298
0299 gdmlname = _toString(j - 4, "ctile%d_gdmlfile");
0300 solid_name = _toString(j - 4, "OuterHCalChimneyTile%02d");
0301 }
0302
0303
0304 xml_comp_t x_det_tgdmlfile = x_det.child(gdmlname);
0305
0306 std::string tgdml_file = getAttrOrDefault<std::string>(x_det_tgdmlfile, _Unicode(file), " ");
0307 ;
0308 std::string tgdml_material =
0309 getAttrOrDefault<std::string>(x_det_tgdmlfile, _Unicode(material), " ");
0310 std::string tgdml_url = getAttrOrDefault<std::string>(x_det_tgdmlfile, _Unicode(url), " ");
0311 std::string tgdml_cache = getAttrOrDefault<std::string>(x_det_tgdmlfile, _Unicode(cache), " ");
0312
0313 EnsureFileFromURLExists(tgdml_url, tgdml_file, tgdml_cache);
0314 if (!fs::exists(fs::path(tgdml_file))) {
0315 printout(ERROR, "BarrelHCalCalorimeter_geo", "file " + tgdml_file + " does not exist");
0316 printout(ERROR, "BarrelHCalCalorimeter_geo",
0317 "use a FileLoader plugin before the field element");
0318 std::_Exit(EXIT_FAILURE);
0319 }
0320
0321 Volume solidVolume = parser.GDMLReadFile(tgdml_file.c_str());
0322 if (!solidVolume.isValid()) {
0323 printout(WARNING, "BarrelHCalCalorimeter_geo", "%s", tgdml_file.c_str());
0324 printout(WARNING, "BarrelHCalCalorimeter_geo", "solidVolume invalid, GDML parser failed!");
0325 std::_Exit(EXIT_FAILURE);
0326 }
0327 solidVolume.import();
0328 solidVolume.setVisAttributes(description, x_det.visStr());
0329 TessellatedSolid volume_solid = solidVolume.solid();
0330 volume_solid->CloseShape(true, true, true);
0331 Material tile_material = description.material(tgdml_material.c_str());
0332 solidVolume.setMaterial(tile_material);
0333
0334 solidVolume.setSensitiveDetector(sens);
0335
0336
0337
0338
0339 if (solid_name.size() > 0) {
0340
0341 std::string type = solid_name.substr(0, solid_name.size() - 2);
0342
0343 if (type == "OuterHCalTile" || type == "OuterHCalChimneyTile") {
0344
0345 std::string stnum = solid_name.substr(solid_name.size() - 2, solid_name.size());
0346 int tnum = atoi(stnum.c_str()) - 1;
0347
0348
0349
0350 if (type == "OuterHCalTile") {
0351
0352 Tile[11 - tnum] = solidVolume;
0353
0354 } else if ((tnum > 7) && (type == "OuterHCalChimneyTile")) {
0355
0356 ChimneyTile[11 - tnum] = solidVolume;
0357 }
0358
0359 } else
0360 printout(WARNING, "BarrelHCalCalorimeter", "invalid solid_name, not a tile type?");
0361
0362 } else
0363 printout(WARNING, "BarrelHCalCalorimeter", "solid_name.size() invalid! ");
0364 }
0365
0366
0367
0368 double increment_angle = (360.0 / 320.0) * dd4hep::deg;
0369 double increment_offset = -10.01 * increment_angle;
0370
0371 DetElement tile_det("eta0 phi0", det_id);
0372 sens.setType("calorimeter");
0373
0374 for (int i_eta = 0; i_eta < 12; i_eta++) {
0375
0376 int tnum = 11 - i_eta;
0377
0378 for (int i_phi = 0; i_phi < 320; i_phi++) {
0379
0380 if (i_eta > 3) {
0381
0382
0383
0384 PlacedVolume phv1 = BarrelHCAL.placeVolume(
0385 Tile[i_eta], i_phi + i_eta * 320,
0386 RotationZ(i_phi * increment_angle + increment_offset) *
0387 Transform3D(
0388 RotationY(90.0 * dd4hep::deg),
0389 Translation3D(xposOuter[0] * dd4hep::mm, yposOuter[0] * dd4hep::mm, 0.0)) *
0390 RotationX(-tilePlaneRotate * dd4hep::deg) *
0391 Transform3D(
0392 RotationY(180.0 * dd4hep::deg),
0393 Translation3D(-(xposTile[tnum] + (tnum + 1) * tile_tolerance) * dd4hep::mm,
0394 yposTile[tnum] * dd4hep::mm, -zposTile[tnum] * dd4hep::mm)));
0395
0396 phv1.addPhysVolID("eta", i_eta).addPhysVolID("phi", i_phi);
0397 DetElement sd1 = tile_det.clone(_toString(i_eta, "eta%d ") + _toString(i_phi, "phi%d"));
0398 sd1.setPlacement(phv1);
0399 sdet.add(sd1);
0400
0401 PlacedVolume phv0 = BarrelHCAL.placeVolume(
0402 Tile[i_eta], i_phi + (12 + tnum) * 320,
0403 RotationZ(i_phi * increment_angle + increment_offset) *
0404 Transform3D(
0405 RotationY(90.0 * dd4hep::deg),
0406 Translation3D(xposOuter[0] * dd4hep::mm, yposOuter[0] * dd4hep::mm, 0.0)) *
0407 RotationX(-tilePlaneRotate * dd4hep::deg) *
0408 Translation3D((xposTile[tnum] + (tnum + 1) * tile_tolerance) * dd4hep::mm,
0409 yposTile[tnum] * dd4hep::mm, zposTile[tnum] * dd4hep::mm));
0410
0411 phv0.addPhysVolID("eta", (12 + tnum)).addPhysVolID("phi", i_phi);
0412 DetElement sd0 =
0413 tile_det.clone(_toString((12 + tnum), "eta%d ") + _toString(i_phi, "phi%d"));
0414 sd0.setPlacement(phv0);
0415 sdet.add(sd0);
0416
0417 } else {
0418
0419
0420
0421 if (i_phi > 29) {
0422
0423
0424
0425 PlacedVolume phv1 = BarrelHCAL.placeVolume(
0426 Tile[i_eta], i_phi + i_eta * 320,
0427 RotationZ(i_phi * increment_angle + increment_offset) *
0428 Transform3D(
0429 RotationY(90.0 * dd4hep::deg),
0430 Translation3D(xposOuter[0] * dd4hep::mm, yposOuter[0] * dd4hep::mm, 0.0)) *
0431 RotationX(-tilePlaneRotate * dd4hep::deg) *
0432 Translation3D(-(xposTile[tnum] + (tnum + 1) * tile_tolerance) * dd4hep::mm,
0433 yposTile[tnum] * dd4hep::mm, -zposTile[tnum] * dd4hep::mm));
0434
0435 phv1.addPhysVolID("eta", i_eta).addPhysVolID("phi", i_phi);
0436 DetElement sd1 = tile_det.clone(_toString(i_eta, "eta%d ") + _toString(i_phi, "phi%d"));
0437 sd1.setPlacement(phv1);
0438 sdet.add(sd1);
0439
0440 PlacedVolume phv0 = BarrelHCAL.placeVolume(
0441 Tile[i_eta], i_phi + (12 + tnum) * 320,
0442 RotationZ(i_phi * increment_angle + increment_offset) *
0443 Transform3D(
0444 RotationY(90.0 * dd4hep::deg),
0445 Translation3D(xposOuter[0] * dd4hep::mm, yposOuter[0] * dd4hep::mm, 0.0)) *
0446 RotationX(-tilePlaneRotate * dd4hep::deg) *
0447 Transform3D(
0448 RotationY(180.0 * dd4hep::deg),
0449 Translation3D((xposTile[tnum] + (tnum + 1) * tile_tolerance) * dd4hep::mm,
0450 yposTile[tnum] * dd4hep::mm, zposTile[tnum] * dd4hep::mm)));
0451
0452 phv0.addPhysVolID("eta", (12 + tnum)).addPhysVolID("phi", i_phi);
0453 DetElement sd0 =
0454 tile_det.clone(_toString((12 + tnum), "eta%d ") + _toString(i_phi, "phi%d"));
0455 sd0.setPlacement(phv0);
0456 sdet.add(sd0);
0457
0458 } else {
0459
0460
0461
0462 PlacedVolume phv1 = BarrelHCAL.placeVolume(
0463 ChimneyTile[i_eta], i_phi + (12 + tnum) * 320,
0464 RotationZ(i_phi * increment_angle + increment_offset) *
0465 Transform3D(
0466 RotationY(90.0 * dd4hep::deg),
0467 Translation3D(xposOuter[0] * dd4hep::mm, yposOuter[0] * dd4hep::mm, 0.0)) *
0468 RotationX(-tilePlaneRotate * dd4hep::deg) *
0469 Translation3D((xposChimneyTileS[tnum - 8] + (tnum + 1) * tile_tolerance) *
0470 dd4hep::mm,
0471 yposChimneyTileS[tnum - 8] * dd4hep::mm,
0472 zposChimneyTileS[tnum - 8] * dd4hep::mm));
0473
0474 phv1.addPhysVolID("eta", (12 + tnum)).addPhysVolID("phi", i_phi);
0475 DetElement sd1 =
0476 tile_det.clone(_toString((12 + tnum), "eta%d ") + _toString(i_phi, "phi%d"));
0477 sd1.setPlacement(phv1);
0478 sdet.add(sd1);
0479
0480 PlacedVolume phv0 = BarrelHCAL.placeVolume(
0481 Tile[i_eta], i_phi + i_eta * 320,
0482 RotationZ(i_phi * increment_angle + increment_offset) *
0483 Transform3D(
0484 RotationY(90.0 * dd4hep::deg),
0485 Translation3D(xposOuter[0] * dd4hep::mm, yposOuter[0] * dd4hep::mm, 0.0)) *
0486 RotationX(-tilePlaneRotate * dd4hep::deg) *
0487 Translation3D(-(xposTile[tnum] + (tnum + 1) * tile_tolerance) * dd4hep::mm,
0488 yposTile[tnum] * dd4hep::mm, -zposTile[tnum] * dd4hep::mm));
0489
0490 phv0.addPhysVolID("eta", i_eta).addPhysVolID("phi", i_phi);
0491 DetElement sd0 = tile_det.clone(_toString(i_eta, "eta%d ") + _toString(i_phi, "phi%d"));
0492 sd0.setPlacement(phv0);
0493 sdet.add(sd0);
0494 }
0495 }
0496 }
0497 }
0498
0499
0500
0501 envelope.placeVolume(BarrelHCAL, 0, Transform3D(RotationZ(0.0), Translation3D(0, 0, 0)));
0502
0503 std::string env_vis =
0504 getAttrOrDefault<std::string>(x_det, _Unicode(env_vis), "HcalBarrelEnvelopeVis");
0505 envelope.setAttributes(description, x_det.regionStr(), x_det.limitsStr(), env_vis);
0506 return sdet;
0507 }
0508
0509 DECLARE_DETELEMENT(epic_HcalBarrelGDML, create_detector)