File indexing completed on 2025-01-18 09:15:53
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 BarrelHCAL.placeVolume(
0259 barrel_csector_vol, 0,
0260 Transform3D(RotationZ(sec_rot_angle * dd4hep::deg) * RotationY(180.0 * dd4hep::deg),
0261 Translation3D(0, 0, 0)));
0262 BarrelHCAL.placeVolume(barrel_csector_vol, 1,
0263 Transform3D(RotationY(180.0 * dd4hep::deg), Translation3D(0, 0, 0)));
0264 BarrelHCAL.placeVolume(
0265 barrel_csector_vol, 2,
0266 Transform3D(RotationZ(-sec_rot_angle * dd4hep::deg) * RotationY(180.0 * dd4hep::deg),
0267 Translation3D(0, 0, 0)));
0268 BarrelHCAL.placeVolume(barrel_er_vol, 0,
0269 Transform3D(RotationY(180.0 * dd4hep::deg), Translation3D(0, 0, 0)));
0270 BarrelHCAL.placeVolume(barrel_er_vol, 1,
0271 Transform3D(RotationY(0.0 * dd4hep::deg), Translation3D(0, 0, 0)));
0272
0273
0274
0275 Volume Tile[12];
0276 Volume ChimneyTile[4];
0277
0278 for (int j = 1; j < 17; j++) {
0279
0280 std::string gdmlname;
0281 std::string solid_name;
0282
0283 if (j < 13) {
0284
0285
0286
0287 gdmlname = _toString(j, "tile%d_gdmlfile");
0288 solid_name = _toString(j, "OuterHCalTile%02d");
0289
0290 } else {
0291
0292
0293
0294 gdmlname = _toString(j - 4, "ctile%d_gdmlfile");
0295 solid_name = _toString(j - 4, "OuterHCalChimneyTile%02d");
0296 }
0297
0298
0299 xml_comp_t x_det_tgdmlfile = x_det.child(gdmlname);
0300
0301 std::string tgdml_file = getAttrOrDefault<std::string>(x_det_tgdmlfile, _Unicode(file), " ");
0302 ;
0303 std::string tgdml_material =
0304 getAttrOrDefault<std::string>(x_det_tgdmlfile, _Unicode(material), " ");
0305 std::string tgdml_url = getAttrOrDefault<std::string>(x_det_tgdmlfile, _Unicode(url), " ");
0306 std::string tgdml_cache = getAttrOrDefault<std::string>(x_det_tgdmlfile, _Unicode(cache), " ");
0307
0308 EnsureFileFromURLExists(tgdml_url, tgdml_file, tgdml_cache);
0309 if (!fs::exists(fs::path(tgdml_file))) {
0310 printout(ERROR, "BarrelHCalCalorimeter_geo", "file " + tgdml_file + " does not exist");
0311 printout(ERROR, "BarrelHCalCalorimeter_geo",
0312 "use a FileLoader plugin before the field element");
0313 std::_Exit(EXIT_FAILURE);
0314 }
0315
0316 Volume solidVolume = parser.GDMLReadFile(tgdml_file.c_str());
0317 if (!solidVolume.isValid()) {
0318 printout(WARNING, "BarrelHCalCalorimeter_geo", "%s", tgdml_file.c_str());
0319 printout(WARNING, "BarrelHCalCalorimeter_geo", "solidVolume invalid, GDML parser failed!");
0320 std::_Exit(EXIT_FAILURE);
0321 }
0322 solidVolume.import();
0323 solidVolume.setVisAttributes(description, x_det.visStr());
0324 TessellatedSolid volume_solid = solidVolume.solid();
0325 volume_solid->CloseShape(true, true, true);
0326 Material tile_material = description.material(tgdml_material.c_str());
0327 solidVolume.setMaterial(tile_material);
0328
0329 solidVolume.setSensitiveDetector(sens);
0330
0331
0332
0333
0334 if (solid_name.size() > 0) {
0335
0336 std::string type = solid_name.substr(0, solid_name.size() - 2);
0337
0338 if (type == "OuterHCalTile" || type == "OuterHCalChimneyTile") {
0339
0340 std::string stnum = solid_name.substr(solid_name.size() - 2, solid_name.size());
0341 int tnum = atoi(stnum.c_str()) - 1;
0342
0343
0344
0345 if (type == "OuterHCalTile") {
0346
0347 Tile[11 - tnum] = solidVolume;
0348
0349 } else if ((tnum > 7) && (type == "OuterHCalChimneyTile")) {
0350
0351 ChimneyTile[11 - tnum] = solidVolume;
0352 }
0353
0354 } else
0355 printout(WARNING, "BarrelHCalCalorimeter", "invalid solid_name, not a tile type?");
0356
0357 } else
0358 printout(WARNING, "BarrelHCalCalorimeter", "solid_name.size() invalid! ");
0359 }
0360
0361
0362
0363 double increment_angle = (360.0 / 320.0) * dd4hep::deg;
0364 double increment_offset = -10.01 * increment_angle;
0365
0366 DetElement tile_det("eta0 phi0", det_id);
0367 sens.setType("calorimeter");
0368
0369 for (int i_eta = 0; i_eta < 12; i_eta++) {
0370
0371 int tnum = 11 - i_eta;
0372
0373 for (int i_phi = 0; i_phi < 320; i_phi++) {
0374
0375 if (i_eta > 3) {
0376
0377
0378
0379 PlacedVolume phv1 = BarrelHCAL.placeVolume(
0380 Tile[i_eta], i_phi + i_eta * 320,
0381 RotationZ(i_phi * increment_angle + increment_offset) *
0382 Transform3D(
0383 RotationY(90.0 * dd4hep::deg),
0384 Translation3D(xposOuter[0] * dd4hep::mm, yposOuter[0] * dd4hep::mm, 0.0)) *
0385 RotationX(-tilePlaneRotate * dd4hep::deg) *
0386 Transform3D(
0387 RotationY(180.0 * dd4hep::deg),
0388 Translation3D(-(xposTile[tnum] + (tnum + 1) * tile_tolerance) * dd4hep::mm,
0389 yposTile[tnum] * dd4hep::mm, -zposTile[tnum] * dd4hep::mm)));
0390
0391 phv1.addPhysVolID("eta", i_eta).addPhysVolID("phi", i_phi);
0392 DetElement sd1 = tile_det.clone(_toString(i_eta, "eta%d ") + _toString(i_phi, "phi%d"));
0393 sd1.setPlacement(phv1);
0394 sdet.add(sd1);
0395
0396 PlacedVolume phv0 = BarrelHCAL.placeVolume(
0397 Tile[i_eta], i_phi + (12 + tnum) * 320,
0398 RotationZ(i_phi * increment_angle + increment_offset) *
0399 Transform3D(
0400 RotationY(90.0 * dd4hep::deg),
0401 Translation3D(xposOuter[0] * dd4hep::mm, yposOuter[0] * dd4hep::mm, 0.0)) *
0402 RotationX(-tilePlaneRotate * dd4hep::deg) *
0403 Translation3D((xposTile[tnum] + (tnum + 1) * tile_tolerance) * dd4hep::mm,
0404 yposTile[tnum] * dd4hep::mm, zposTile[tnum] * dd4hep::mm));
0405
0406 phv0.addPhysVolID("eta", (12 + tnum)).addPhysVolID("phi", i_phi);
0407 DetElement sd0 =
0408 tile_det.clone(_toString((12 + tnum), "eta%d ") + _toString(i_phi, "phi%d"));
0409 sd0.setPlacement(phv0);
0410 sdet.add(sd0);
0411
0412 } else {
0413
0414
0415
0416 if (i_phi > 29) {
0417
0418
0419
0420 PlacedVolume phv1 = BarrelHCAL.placeVolume(
0421 Tile[i_eta], i_phi + i_eta * 320,
0422 RotationZ(i_phi * increment_angle + increment_offset) *
0423 Transform3D(
0424 RotationY(90.0 * dd4hep::deg),
0425 Translation3D(xposOuter[0] * dd4hep::mm, yposOuter[0] * dd4hep::mm, 0.0)) *
0426 RotationX(-tilePlaneRotate * dd4hep::deg) *
0427 Translation3D((xposTile[tnum] + (tnum + 1) * tile_tolerance) * dd4hep::mm,
0428 yposTile[tnum] * dd4hep::mm, zposTile[tnum] * dd4hep::mm));
0429
0430 phv1.addPhysVolID("eta", i_eta).addPhysVolID("phi", i_phi);
0431 DetElement sd1 = tile_det.clone(_toString(i_eta, "eta%d ") + _toString(i_phi, "phi%d"));
0432 sd1.setPlacement(phv1);
0433 sdet.add(sd1);
0434
0435 PlacedVolume phv0 = BarrelHCAL.placeVolume(
0436 Tile[i_eta], i_phi + (12 + tnum) * 320,
0437 RotationZ(i_phi * increment_angle + increment_offset) *
0438 Transform3D(
0439 RotationY(90.0 * dd4hep::deg),
0440 Translation3D(xposOuter[0] * dd4hep::mm, yposOuter[0] * dd4hep::mm, 0.0)) *
0441 RotationX(-tilePlaneRotate * dd4hep::deg) *
0442 Transform3D(
0443 RotationY(180.0 * dd4hep::deg),
0444 Translation3D(-(xposTile[tnum] + (tnum + 1) * tile_tolerance) * dd4hep::mm,
0445 yposTile[tnum] * dd4hep::mm, -zposTile[tnum] * dd4hep::mm)));
0446
0447 phv0.addPhysVolID("eta", (12 + tnum)).addPhysVolID("phi", i_phi);
0448 DetElement sd0 =
0449 tile_det.clone(_toString((12 + tnum), "eta%d ") + _toString(i_phi, "phi%d"));
0450 sd0.setPlacement(phv0);
0451 sdet.add(sd0);
0452
0453 } else {
0454
0455
0456
0457 PlacedVolume phv1 = BarrelHCAL.placeVolume(
0458 ChimneyTile[i_eta], i_phi + (12 + tnum) * 320,
0459 RotationZ(i_phi * increment_angle + increment_offset) *
0460 Transform3D(
0461 RotationY(90.0 * dd4hep::deg),
0462 Translation3D(xposOuter[0] * dd4hep::mm, yposOuter[0] * dd4hep::mm, 0.0)) *
0463 RotationX(-tilePlaneRotate * dd4hep::deg) *
0464 Translation3D((xposChimneyTileS[tnum - 8] + (tnum + 1) * tile_tolerance) *
0465 dd4hep::mm,
0466 yposChimneyTileS[tnum - 8] * dd4hep::mm,
0467 zposChimneyTileS[tnum - 8] * dd4hep::mm));
0468
0469 phv1.addPhysVolID("eta", (12 + tnum)).addPhysVolID("phi", i_phi);
0470 DetElement sd1 =
0471 tile_det.clone(_toString((12 + tnum), "eta%d ") + _toString(i_phi, "phi%d"));
0472 sd1.setPlacement(phv1);
0473 sdet.add(sd1);
0474
0475 PlacedVolume phv0 = BarrelHCAL.placeVolume(
0476 Tile[i_eta], i_phi + i_eta * 320,
0477 RotationZ(i_phi * increment_angle + increment_offset) *
0478 Transform3D(
0479 RotationY(90.0 * dd4hep::deg),
0480 Translation3D(xposOuter[0] * dd4hep::mm, yposOuter[0] * dd4hep::mm, 0.0)) *
0481 RotationX(-tilePlaneRotate * dd4hep::deg) *
0482 Translation3D((xposTile[tnum] + (tnum + 1) * tile_tolerance) * dd4hep::mm,
0483 yposTile[tnum] * dd4hep::mm, zposTile[tnum] * dd4hep::mm));
0484
0485 phv0.addPhysVolID("eta", i_eta).addPhysVolID("phi", i_phi);
0486 DetElement sd0 = tile_det.clone(_toString(i_eta, "eta%d ") + _toString(i_phi, "phi%d"));
0487 sd0.setPlacement(phv0);
0488 sdet.add(sd0);
0489 }
0490 }
0491 }
0492 }
0493
0494
0495
0496 envelope.placeVolume(BarrelHCAL, 0, Transform3D(RotationZ(0.0), Translation3D(0, 0, 0)));
0497
0498 std::string env_vis =
0499 getAttrOrDefault<std::string>(x_det, _Unicode(env_vis), "HcalBarrelEnvelopeVis");
0500 envelope.setAttributes(description, x_det.regionStr(), x_det.limitsStr(), env_vis);
0501 return sdet;
0502 }
0503
0504 DECLARE_DETELEMENT(epic_HcalBarrelGDML, create_detector)