17#include <TGeoManager.h>
18#include <TGeoMaterial.h>
19#include <TGeoMedium.h>
22#include <TGeoMatrix.h>
23#include <TGeoCompositeShape.h>
52 LOG(
debug) <<
"FT3Module: initialize_materials";
57 TGeoManager* geoManager = gGeoManager;
59 auto* itsH =
new TGeoElement(
"FT3_H",
"Hydrogen", 1, 1.00794);
60 auto* itsC =
new TGeoElement(
"FT3_C",
"Carbon", 6, 12.0107);
61 auto* itsO =
new TGeoElement(
"FT3_O",
"Oxygen", 8, 15.994);
63 siliconMat =
new TGeoMaterial(
"FT3_Silicon", 28.0855, 14, 2.33);
66 copperMat =
new TGeoMaterial(
"FT3_Copper", 63.546, 29, 8.96);
69 kaptonMat =
new TGeoMaterial(
"FT3_Kapton", 13.84, 6.88, 1.346);
77 auto* itsEpoxy =
new TGeoMixture(
"FT3_Epoxy", 3);
78 itsEpoxy->AddElement(itsC, 18);
79 itsEpoxy->AddElement(itsH, 19);
80 itsEpoxy->AddElement(itsO, 3);
81 itsEpoxy->SetDensity(2.186);
83 epoxyMed =
new TGeoMedium(
"FT3_Epoxy", 4, itsEpoxy);
86 AluminumMat =
new TGeoMaterial(
"Aluminum", 26.98, 13, 2.7);
88 LOG(
debug) <<
"FT3Module: done initialize_materials";
93 return (
x *
x < radius * radius) ? std::sqrt(radius * radius -
x *
x) : 0;
97 double x_left,
double x_right,
double Rin,
double Rout)
109 if (x_right < -Rin) {
117 }
else if (x_left < 0) {
122 }
else if (x_left < Rin) {
131 return {min_y_abs, max_y_abs};
153 std::pair<double, double>& absAllowedYRange)
161 double max_sensor_y_abs = std::min(absAllowedYRange.second, y_ranges.first.second);
165 if (!y_positions.first.empty()) {
168 }
else if (absAllowedYRange.first > 0) {
170 y_top = std::max(absAllowedYRange.first, y_ranges.first.first);
173 y_top = y_ranges.first.first;
176 while ((y_top + sensorStackHeight) <= max_sensor_y_abs) {
177 y_positions.first.emplace_back(y_top, kSensorStack);
178 y_top += sensorAbsStackYShift;
184 if (!y_positions.second.empty()) {
188 }
else if (absAllowedYRange.first > 0) {
190 y_bottom = std::min(-absAllowedYRange.first, y_ranges.second.first);
193 y_bottom = y_ranges.second.first;
196 while ((y_bottom - sensorStackHeight) >= -max_sensor_y_abs) {
197 y_positions.second.emplace_back(y_bottom, kSensorStack);
198 y_bottom -= sensorAbsStackYShift;
228 std::array<double, 3> xv_inner, xv_outer, zv_inner, zv_outer;
232 zv_outer[0] = (direction == 1) ? -H
239 xv_outer[2] = -xv_outer[1];
243 xv_inner[0] = xv_outer[0];
245 zv_inner[0] = (direction == 1) ? zv_outer[0] + z_shift_inner
246 : zv_outer[0] - z_shift_inner;
248 zv_inner[1] = (direction == 1) ? zv_outer[1] - d
251 xv_inner[1] = xv_outer[1] - x_shift_abs;
253 zv_inner[2] = zv_inner[1];
254 xv_inner[2] = -xv_inner[1];
256 return {xv_outer, zv_outer, xv_inner, zv_inner};
263void FT3Module::addStaveVolume(
264 TGeoVolume* motherVolume, std::string volumeName,
int direction,
265 unsigned* volume_count,
double staveLength,
266 std::array<std::array<double, 3>, 4> staveTriangles,
267 std::pair<double, double>& absAllowedYRange,
268 double x_mid,
double y_mid,
double z_stave_shift_forward)
271 if (absAllowedYRange.first < 0 || absAllowedYRange.second < 0 ||
272 absAllowedYRange.first >= absAllowedYRange.second) {
273 LOG(error) <<
"Invalid allowed y range in addStaveVolume(): ("
274 << absAllowedYRange.first <<
", " << absAllowedYRange.second
275 <<
"). Both values must be non-negative and the first "
276 <<
"value must be less than the second value.";
280 double y_lower = y_mid - staveLength / 2;
281 double y_upper = y_mid + staveLength / 2;
282 bool splitStave =
false;
284 y_lower = std::max(y_lower, absAllowedYRange.first);
285 y_upper = std::min(y_upper, absAllowedYRange.second);
286 }
else if (y_upper < 0) {
287 y_lower = std::max(y_lower, -absAllowedYRange.second);
288 y_upper = std::min(y_upper, -absAllowedYRange.first);
291 if (absAllowedYRange.first > 0) {
294 y_lower = absAllowedYRange.first;
297 y_lower = std::max(y_lower, -absAllowedYRange.second);
299 y_upper = std::min(y_upper, absAllowedYRange.second);
301 double staveLengthToUse = y_upper - y_lower;
309 TGeoXtru* staveFull =
new TGeoXtru(2);
310 staveFull->SetName((volumeName +
"_Xtru_outer").c_str());
311 staveFull->DefinePolygon(3, staveTriangles[0].
data(), staveTriangles[1].
data());
312 staveFull->DefineSection(0, 0);
313 staveFull->DefineSection(1, staveLengthToUse);
315 TGeoXtru* staveInner =
new TGeoXtru(2);
316 staveInner->SetName((volumeName +
"_Xtru_inner").c_str());
317 staveInner->DefinePolygon(3, staveTriangles[2].
data(), staveTriangles[3].
data());
318 staveInner->DefineSection(0, 0);
319 staveInner->DefineSection(1, staveLengthToUse);
321 TGeoCompositeShape* staveShape =
new TGeoCompositeShape(
322 (volumeName +
"_shape").c_str(),
323 Form(
"%s - %s", staveFull->GetName(), staveInner->GetName()));
324 TGeoVolume* staveVolume =
new TGeoVolume(
325 (volumeName).c_str(),
331 TGeoRotation* rot =
new TGeoRotation();
345 double z_shift = (direction == 1) ? z_stave_shift_forward : -z_stave_shift_forward;
346 TGeoCombiTrans* combiTrans =
347 new TGeoCombiTrans(x_mid, y_lower, z_shift, rot);
348 motherVolume->AddNode(staveVolume,
355 TGeoCombiTrans* combiTransSplit =
356 new TGeoCombiTrans(x_mid, -y_upper, z_shift, rot);
357 motherVolume->AddNode(staveVolume,
369void FT3Module::addDetectorVolume(
370 TGeoVolume* motherVolume, std::string volumeName,
int color,
371 unsigned volume_count,
double x_mid,
double y_mid,
double z_mid,
372 double x_half_length,
double y_half_length,
double z_half_length)
374 TGeoManager* geoManager = gGeoManager;
375 TGeoVolume* volume = geoManager->MakeBox(volumeName.c_str(),
siliconMed, x_half_length,
376 y_half_length, z_half_length);
377 volume->SetLineColor(
color);
378 volume->SetFillColorAlpha(
color, 0.4);
379 motherVolume->AddNode(
393void FT3Module::add2x1GlueVolume(
394 TGeoVolume* motherVolume,
int layerNumber,
int direction,
unsigned stave_idx,
395 unsigned volume_count,
double x_mid,
double y_mid,
double z_mid,
396 std::string element_glued_to)
409void FT3Module::add2x1CopperVolume(
410 TGeoVolume* motherVolume,
int layerNumber,
int direction,
unsigned stave_idx,
411 unsigned volume_count,
double x_mid,
double y_mid,
double z_mid)
424void FT3Module::add2x1KaptonVolume(
425 TGeoVolume* motherVolume,
int layerNumber,
int direction,
unsigned stave_idx,
426 unsigned volume_count,
double x_mid,
double y_mid,
double z_mid)
453void FT3Module::addSingleSensorVolume(
454 TGeoVolume* motherVolume,
int layerNumber,
int direction,
unsigned stave_idx,
455 unsigned volume_count,
double active_x_mid,
double y_mid,
double z_mid,
459 TGeoManager* geoManager = gGeoManager;
466 motherVolume->AddNode(
483 motherVolume->AddNode(
494void FT3Module::create_layout_staveGeo(
double mZ,
int layerNumber,
int direction,
495 double Rin,
double Rout,
double z_offset_local,
497 TGeoVolume* motherVolume)
499 LOG(
debug) <<
"FT3Module: create_layout_staveGeo - Direction "
500 << direction <<
", Layer " << layerNumber;
525 double totalSensorMaterialThickness =
528 double z_offset_to_carbon_face = z_offset_local - totalSensorMaterialThickness - 0.1;
529 double z_offset_to_glue_Ka =
531 double z_offset_to_kapton =
534 double z_offset_to_copper =
537 double z_offset_to_glue_Si =
540 double z_offset_to_silicon =
546 std::vector<PosNegPositionTypes> y_positionsPosNeg;
551 std::vector<std::vector<unsigned>> nSensorStackCountPerStave(
555 unsigned staveVolumeCount = 0;
556 for (
unsigned i_stave = 0; i_stave < staveConfig.
x_midpoints.size(); i_stave++) {
560 double y_midpoint = 0.;
561 bool mirrorStaveAroundX =
false;
563 double stave_half_length = staveConfig.
y_lengths[i_stave] / 2;
565 if (ft3Params.placeSensorStackInMiddleOfStave) {
578 y_ranges = {{-stackHeight / 2, stave_half_length},
591 y_midpoint = y_midpoint_it->second.first;
592 mirrorStaveAroundX = y_midpoint_it->second.second;
593 y_ranges.first = {y_midpoint - stave_half_length, y_midpoint + stave_half_length};
594 y_ranges.second = {-y_midpoint + stave_half_length, -y_midpoint - stave_half_length};
598 double tolerance_inner, tolerance_outer;
599 if (staveConfig.
isML) {
600 tolerance_inner = ft3Params.staveTolMLInner;
601 tolerance_outer = ft3Params.staveTolMLOuter;
603 tolerance_inner = ft3Params.staveTolOTInner;
604 tolerance_outer = ft3Params.staveTolOTOuter;
625 std::pair<double, double> absAllowedYRange =
634 absAllowedYRange.first -= tolerance_inner;
635 absAllowedYRange.second += tolerance_outer;
637 if (absAllowedYRange.first < 0) {
638 absAllowedYRange.first = 0;
640 if (absAllowedYRange.second <= 0) {
641 LOG(warning) <<
"For stave " << i_stave <<
" in layer " << layerNumber
642 <<
" with direction " << direction <<
": no space to place sensors after applying tolerances, skipping stave.";
648 double z_stave_shift_forward =
649 -z_offset_to_carbon_face + z_stave_shift_abs;
650 std::string stave_volume_name =
656 motherVolume, stave_volume_name, direction, &staveVolumeCount,
657 staveConfig.
y_lengths[i_stave], staveTriangles, absAllowedYRange,
658 staveConfig.
x_midpoints[i_stave], y_midpoint, z_stave_shift_forward);
660 if (mirrorStaveAroundX) {
662 motherVolume, stave_volume_name +
"_mirrored", direction, &staveVolumeCount,
663 staveConfig.
y_lengths[i_stave], staveTriangles, absAllowedYRange,
664 staveConfig.
x_midpoints[i_stave], -y_midpoint, z_stave_shift_forward);
669 unsigned nModulesCurr = y_positionsPosNeg.back().first.size() + y_positionsPosNeg.back().second.size();
670 fill_stave(y_positionsPosNeg.back(), Rin, Rout, x_left,
673 unsigned nModulesAdded = y_positionsPosNeg.back().first.size() + y_positionsPosNeg.back().second.size() - nModulesCurr;
674 nSensorStackCountPerStave[i_stave][i_kSens] = nModulesAdded;
675 nSensorStackTotal[i_kSens] += nModulesAdded;
677 std::string moduleDebugStr =
"Module size counts for layer " +
std::to_string(layerNumber) +
" in direction " +
std::to_string(direction) +
":\n";
683 std::string totalModuleInfoStr =
684 "Total module size counts for layer " +
std::to_string(layerNumber) +
689 LOG(info) << totalModuleInfoStr;
692 for (
unsigned i_stave = 0; i_stave < staveConfig.
x_midpoints.size(); i_stave++) {
705 if (direction == 1) {
710 int z_offset_multiplier = (direction == 1) ? -1 : 1;
713 double z_stave_shift = 0;
720 unsigned sensor_count = 0;
721 for (
int y_sign = -1; y_sign < 2; y_sign += 2) {
723 const auto& positions = (y_sign == 1) ? y_positionsPosNeg[i_stave].
first
724 : y_positionsPosNeg[i_stave].second;
726 for (
unsigned i_y_pos = 0; i_y_pos < positions.size(); i_y_pos++) {
728 for (
unsigned i_sens = 0; i_sens < positions[i_y_pos].second; i_sens++) {
732 double z_mid = z_offset_to_silicon * z_offset_multiplier + z_stave_shift;
733 addSingleSensorVolume(
734 motherVolume, layerNumber, direction, i_stave, sensor_count,
737 addSingleSensorVolume(
738 motherVolume, layerNumber, direction, i_stave, sensor_count,
741 z_mid = z_offset_to_glue_Si * z_offset_multiplier + z_stave_shift;
743 motherVolume, layerNumber, direction, i_stave, sensor_count,
744 x_mid, y_mid, z_mid,
"SiCu");
746 z_mid = z_offset_to_copper * z_offset_multiplier + z_stave_shift;
748 motherVolume, layerNumber, direction, i_stave, sensor_count,
749 x_mid, y_mid, z_mid);
751 z_mid = z_offset_to_kapton * z_offset_multiplier + z_stave_shift;
753 motherVolume, layerNumber, direction, i_stave, sensor_count,
754 x_mid, y_mid, z_mid);
756 z_mid = z_offset_to_glue_Ka * z_offset_multiplier + z_stave_shift;
758 motherVolume, layerNumber, direction, i_stave, sensor_count,
759 x_mid, y_mid, z_mid,
"CarbonKapton");
769void FT3Module::create_layout(
double mZ,
int layerNumber,
int direction,
double Rin,
double Rout,
double overlap,
const std::string&
face,
const std::string& layout_type, TGeoVolume* motherVolume)
772 LOG(
debug) <<
"FT3Module: create_layout - Layer " << layerNumber <<
", Direction " << direction <<
", Face " <<
face;
773 TGeoManager* geoManager = gGeoManager;
782 double sensor_width = 5.0;
783 double sensor_height = 9.6;
788 double silicon_thickness = 0.01;
789 double copper_thickness = 0.006;
790 double kapton_thickness = 0.03;
791 double epoxy_thickness = 0.0012;
793 double carbonFiberThickness = 0.01;
795 double foamSpacingThickness = 1.0;
802 double z_offset = (
face ==
"front") ? -foamSpacingThickness / 2.0 - carbonFiberThickness : foamSpacingThickness / 2.0 + carbonFiberThickness;
805 if (sensor_height == 3.2 && sensor_width == 2.5) {
808 }
else if (sensor_height == 19.2 && sensor_width == 5) {
812 x_offset = sensor_width / 2;
813 y_offset = sensor_height / 2;
816 double x_condition_min = 0;
817 double x_condition_max = 0;
818 double offset_Rin_lower = 0;
819 double offset_Rin_upper = 0;
820 bool adjust_bottom_y_pos =
false;
821 bool adjust_bottom_y_neg =
false;
822 double x_adjust_bottom_y_pos = 0;
823 double bottom_y_pos_value = 0;
824 double bottom_y_neg_value = 0;
826 double Rin_offset = (sensor_height == 19.2) ? 1 : 0;
827 double Rout_offset = (sensor_height == 19.2) ? 1 : 0;
829 if (Rin == 7 && sensor_height == 9.6 && sensor_width == 5) {
830 x_condition_min = -Rin - 2;
831 x_condition_max = Rin;
833 adjust_bottom_y_pos =
true;
834 adjust_bottom_y_neg =
true;
835 x_adjust_bottom_y_pos = 3.5;
836 bottom_y_pos_value = 3.5;
837 bottom_y_neg_value = -3.5;
838 }
else if (Rin == 5 && sensor_height == 9.6 && sensor_width == 5) {
839 x_condition_min = -Rin - 6;
840 x_condition_max = Rin;
841 adjust_bottom_y_pos =
true;
842 adjust_bottom_y_neg =
true;
843 x_adjust_bottom_y_pos = 3.5;
844 bottom_y_pos_value = 3.5;
845 bottom_y_neg_value = -3.5;
846 }
else if ((Rin == 5 || Rin == 7) && sensor_height == 19.2) {
847 x_condition_min = -Rin - 3;
848 x_condition_max = Rin - 0.2;
850 adjust_bottom_y_pos =
false;
851 adjust_bottom_y_neg =
false;
852 }
else if (Rin == 5 && sensor_height == 3.2) {
853 x_condition_min = -(Rin + 2.6);
854 x_condition_max = Rin + 1.5;
855 adjust_bottom_y_pos =
true;
856 adjust_bottom_y_neg =
true;
857 x_adjust_bottom_y_pos = 3.5;
858 bottom_y_pos_value = 3.5;
859 bottom_y_neg_value = -3.5;
860 }
else if (Rin == 7 && sensor_height == 3.2) {
861 x_condition_min = -Rin - 1;
862 x_condition_max = Rin - 0.2;
863 adjust_bottom_y_pos =
true;
864 adjust_bottom_y_neg =
true;
865 x_adjust_bottom_y_pos = 3.5;
866 bottom_y_pos_value = 3.5;
867 bottom_y_neg_value = -3.5;
868 }
else if (Rin == 5 && sensor_height == 9.6 && sensor_width == 2.5) {
869 x_condition_min = -(Rin + 2.6);
870 x_condition_max = Rin;
871 adjust_bottom_y_pos =
true;
872 adjust_bottom_y_neg =
true;
873 x_adjust_bottom_y_pos = 3.5;
874 bottom_y_pos_value = 3.5;
875 bottom_y_neg_value = -3.5;
876 }
else if (Rin == 7 && sensor_height == 9.6 && sensor_width == 2.5) {
877 x_condition_min = -Rin - 2.6;
878 x_condition_max = Rin + 1;
880 adjust_bottom_y_pos =
true;
881 adjust_bottom_y_neg =
true;
882 x_adjust_bottom_y_pos = 5.5;
883 bottom_y_pos_value = 3.5;
884 bottom_y_neg_value = -3.5;
885 }
else if (Rin == 10 && sensor_height == 9.6 && sensor_width == 5.0) {
886 x_condition_min = -Rin - 4;
887 x_condition_max = Rin;
889 adjust_bottom_y_pos =
false;
890 adjust_bottom_y_neg =
false;
891 x_adjust_bottom_y_pos = 3.5;
892 bottom_y_pos_value = 3.5;
893 bottom_y_neg_value = -3.5;
894 }
else if (Rin == 20 && sensor_height == 9.6 && sensor_width == 5.0) {
895 x_condition_min = -Rin - 4;
896 x_condition_max = Rin;
898 adjust_bottom_y_pos =
false;
899 adjust_bottom_y_neg =
false;
900 x_adjust_bottom_y_pos = 3.5;
901 bottom_y_pos_value = 3.5;
902 bottom_y_neg_value = -3.5;
904 LOG(warning) <<
"Different config - to determine offsets needed for " <<
"Rin = " << Rin <<
" ; sensor_height = " << sensor_height <<
" ; sensor_width = " << sensor_width <<
" layer " << layerNumber;
905 x_condition_min = -Rin - sensor_width;
906 x_condition_max = Rin;
907 adjust_bottom_y_pos =
false;
908 adjust_bottom_y_neg =
false;
911 offset_Rin_lower = Rin - Rin_offset;
912 offset_Rin_upper = Rout + Rout_offset;
914 std::set<std::pair<double, double>> placed_sensors;
915 int sensor_count = 0;
917 int placementCounter = 0;
918 bool justSkipped =
false;
920 std::vector<double> X_positions;
921 std::vector<int> justSkipped1;
923 if (sensor_width == 2.5) {
925 if (
face ==
"front") {
926 X_positions = {-63.4, -60.9, -54.2, -51.7, -45.0, -42.5, -35.8, -33.3, -26.6, -24.1, -17.4, -14.9,
927 -8.2, -5.7, 1.0, 3.5, 10.2, 12.7, 19.4, 21.9, 28.6, 31.1, 37.8, 40.3, 47.0, 49.5,
929 justSkipped1 = {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1};
930 }
else if (
face ==
"back") {
931 X_positions = {-65.5, -58.8, -56.3, -49.6, -47.1, -40.4, -37.9, -31.2, -28.7, -22.0, -19.5, -12.8,
932 -10.3, -3.6, -1.1, 5.6, 8.1, 14.8, 17.3, 24.0, 26.5, 33.2, 35.7, 42.4, 44.9,
933 51.6, 54.1, 60.8, 63.3};
934 justSkipped1 = {0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0};
937 if (Rin == 10 || Rin == 20) {
940 float X_start = -2.0 - 13.5 * (sensor_width - overlap);
941 float X_start_pos = 2.0 - 0.5 * (sensor_width - overlap);
942 if (
face ==
"back") {
943 X_start += (sensor_width - overlap);
944 X_start_pos += (sensor_width - overlap);
946 while (X_start < -2) {
947 X_positions.push_back(X_start);
948 justSkipped1.push_back(1);
949 X_start += 2 * (sensor_width - overlap);
951 while (X_start_pos < Rout + x_offset - sensor_width) {
952 X_positions.push_back(X_start_pos);
953 justSkipped1.push_back(1);
954 X_start_pos += 2 * (sensor_width - overlap);
958 if (
face ==
"front") {
959 X_positions = {-63.4, -54.2, -45, -35.8, -26.6, -17.4, -8.2, 1., 10.2, 19.4, 28.6, 37.8, 47., 56.2, 65.4};
960 justSkipped1 = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
961 }
else if (
face ==
"back") {
962 X_positions = {-58.8, -49.6, -40.4, -31.2, -22, -12.8, -3.6, 5.6, 14.8, 24, 33.2, 42.4, 51.6, 60.8};
963 justSkipped1 = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
968 if (layout_type ==
"rectangular") {
970 double x_start = -Rout;
973 std::vector<double> x_positions;
974 for (
double x = x_start;
x <= x_end;
x += sensor_width) {
975 x_positions.push_back(
x);
979 const int rowsToAlternate = 2;
981 for (
size_t i = 0;
i < X_positions.size(); ++
i) {
983 double x = X_positions[
i];
984 bool justSkippedValue = justSkipped1[
i];
986 std::vector<double> y_positions_positive;
987 std::vector<double> y_positions_negative;
989 for (
double y = -Rout - Rin_offset;
y <= Rout + Rin_offset;
y += sensor_height) {
990 std::vector<std::pair<double, double>> corners = {
992 {
x + sensor_width,
y},
993 {
x,
y + sensor_height},
994 {
x + sensor_width,
y + sensor_height}};
996 bool within_bounds = std::all_of(corners.begin(), corners.end(), [&](
const std::pair<double, double>& corner) {
997 double cx = corner.first;
998 double cy = corner.second;
999 return (offset_Rin_lower <= std::sqrt(cx * cx + cy * cy) && std::sqrt(cx * cx + cy * cy) <= offset_Rin_upper);
1002 if (within_bounds) {
1004 y_positions_positive.push_back(
y);
1006 y_positions_negative.push_back(
y);
1012 if (x_condition_min <=
x &&
x <= x_condition_max && !y_positions_positive.empty()) {
1013 double first_y_pos = y_positions_positive.front();
1014 double last_y_pos = y_positions_positive.back() - sensor_height;
1017 double top_distance_pos = top_y_pos - last_y_pos;
1019 if (adjust_bottom_y_pos &&
x > x_adjust_bottom_y_pos) {
1020 bottom_y_pos = bottom_y_pos_value;
1023 double bottom_distance_pos = first_y_pos - bottom_y_pos;
1025 if (std::abs(top_distance_pos + bottom_distance_pos) >= sensor_height) {
1026 for (
auto&
y : y_positions_positive) {
1027 y -= bottom_distance_pos - 0.2;
1029 y_positions_positive.push_back(y_positions_positive.back() + sensor_height);
1034 if (x_condition_min <=
x &&
x <= x_condition_max && !y_positions_negative.empty()) {
1035 double first_y_neg = y_positions_negative.front();
1036 double last_y_neg = y_positions_negative.back() + sensor_height;
1039 double top_distance_neg = -(top_y_neg - first_y_neg);
1041 if (adjust_bottom_y_neg &&
x > x_adjust_bottom_y_pos) {
1042 bottom_y_neg = bottom_y_neg_value;
1045 double bottom_distance_neg = -(last_y_neg - bottom_y_neg);
1047 top_distance_neg = std::abs(top_distance_neg);
1048 bottom_distance_neg = std::abs(bottom_distance_neg);
1049 std::sort(y_positions_negative.begin(), y_positions_negative.end());
1051 if (std::abs(top_distance_neg + bottom_distance_neg) >= sensor_height) {
1052 if (sensor_height == 19.2) {
1053 for (
auto&
y : y_positions_negative) {
1054 y -= bottom_distance_neg;
1057 for (
auto&
y : y_positions_negative) {
1058 y += bottom_distance_neg - 0.2;
1061 y_positions_negative.push_back(y_positions_negative.front() - sensor_height);
1066 if ((x < x_condition_min || x > x_condition_max) && !y_positions_negative.empty() && !y_positions_positive.empty()) {
1067 double first_y_neg = y_positions_negative.front();
1068 double last_y_pos = y_positions_positive.back() + sensor_height;
1070 double bottom_y_pos = -top_y_pos;
1072 double top_distance_pos = std::abs(top_y_pos - last_y_pos);
1073 double bottom_distance_pos = std::abs(first_y_neg - bottom_y_pos);
1075 if (top_distance_pos + bottom_distance_pos >= sensor_height) {
1076 for (
auto&
y : y_positions_positive) {
1077 y += top_distance_pos - 0.2;
1079 for (
auto&
y : y_positions_negative) {
1080 y += top_distance_pos - 0.2;
1082 double new_y = y_positions_negative.front() - sensor_height;
1084 if (
static_cast<int>(new_y) >
static_cast<int>(bottom_y_pos)) {
1085 y_positions_negative.push_back(new_y);
1090 std::sort(y_positions_negative.begin(), y_positions_negative.end());
1091 std::sort(y_positions_positive.begin(), y_positions_positive.end());
1093 double first_y_pos = y_positions_negative.front();
1095 last_y_pos = y_positions_positive.back() + sensor_height;
1098 bottom_y_pos = -top_y_pos;
1099 top_distance_pos = std::abs(top_y_pos - last_y_pos);
1100 bottom_distance_pos = std::abs(first_y_pos - bottom_y_pos);
1102 double Lb = (bottom_distance_pos + top_distance_pos) / 2;
1104 if (top_distance_pos < Lb) {
1105 double shift = Lb - top_distance_pos;
1106 for (
auto&
y : y_positions_negative) {
1109 for (
auto&
y : y_positions_positive) {
1112 }
else if (top_distance_pos > Lb) {
1113 double shift = top_distance_pos - Lb;
1114 for (
auto&
y : y_positions_negative) {
1117 for (
auto&
y : y_positions_positive) {
1123 std::vector<double> y_positions = y_positions_positive;
1124 y_positions.insert(y_positions.end(), y_positions_negative.begin(), y_positions_negative.end());
1126 for (
double y : y_positions) {
1129 double R_material_threshold = 0;
1131 if (placed_sensors.find({x, y}) == placed_sensors.end()) {
1132 placed_sensors.insert({
x,
y});
1136 double left_inactive_x_shift;
1137 double right_inactive_x_shift;
1138 double active_x_shift_sensor;
1140 if (
face ==
"front") {
1142 double active_x_shift, inactive_x_shift;
1144 if (justSkippedValue) {
1156 double inactive_x_shift_left, inactive_x_shift_right;
1158 if (sensor_width == 5.0) {
1161 inactive_x_shift_right =
x + sensor_width / 2;
1164 std::vector<std::pair<double, double>> corners_shifted = {
1166 {
x + sensor_width,
y},
1167 {
x,
y + sensor_height},
1168 {
x + sensor_width,
y + sensor_height}};
1170 bool within_bounds =
true;
1171 for (
const auto& corner : corners_shifted) {
1172 double cx = corner.first;
1173 double cy = corner.second;
1174 double dist = std::sqrt(cx * cx + cy * cy);
1176 if (Rin > dist || dist >= Rout) {
1177 within_bounds =
false;
1182 if (within_bounds) {
1184 double r_squared = (
x + x_offset) * (
x + x_offset) + (
y + y_offset) * (
y + y_offset);
1186 if (r_squared < R_material_threshold * R_material_threshold) {
1187 silicon_thickness = 0.005;
1188 copper_thickness = 0.00475;
1189 kapton_thickness = 0.03;
1190 epoxy_thickness = 0.0012;
1194 silicon_thickness = 0.01;
1195 copper_thickness = 0.006;
1196 kapton_thickness = 0.03;
1197 epoxy_thickness = 0.0012;
1202 if (sensor_width == 2.5) {
1205 sensor = geoManager->MakeBox(sensor_name.c_str(),
siliconMed, active_width / 2, active_height / 2, silicon_thickness / 2);
1206 sensor->SetLineColor(SiColor);
1207 sensor->SetFillColorAlpha(SiColor, 0.4);
1208 motherVolume->AddNode(sensor, sensor_count++,
new TGeoTranslation(active_x_shift_sensor + x_offset,
y + y_offset, mZ + z_offset - epoxy_thickness - kapton_thickness - copper_thickness - epoxy_thickness - silicon_thickness / 2));
1211 sensor = geoManager->MakeBox(inactive_name.c_str(),
siliconMed, (sensor_width - active_width) / 2, sensor_height / 2, silicon_thickness / 2);
1212 sensor->SetLineColor(kRed);
1213 sensor->SetFillColorAlpha(kRed, 1.0);
1214 motherVolume->AddNode(sensor, sensor_count++,
new TGeoTranslation(x_offset + inactive_x_shift,
y + y_offset, mZ + z_offset - epoxy_thickness - kapton_thickness - copper_thickness - epoxy_thickness - silicon_thickness / 2));
1219 sensor = geoManager->MakeBox(sensor_name.c_str(),
siliconMed, active_width / 2, sensor_height / 2, silicon_thickness / 2);
1220 sensor->SetLineColor(SiColor);
1221 sensor->SetFillColorAlpha(SiColor, 0.4);
1222 motherVolume->AddNode(sensor, sensor_count++,
new TGeoTranslation(x_offset +
x + inactive_width / 2,
y + y_offset, mZ + z_offset - epoxy_thickness - kapton_thickness - copper_thickness - epoxy_thickness - silicon_thickness / 2));
1225 sensor = geoManager->MakeBox(inactive_name_left.c_str(),
siliconMed, inactive_width / 2, sensor_height / 2, silicon_thickness / 2);
1226 sensor->SetLineColor(kRed);
1227 sensor->SetFillColorAlpha(kRed, 1.0);
1228 motherVolume->AddNode(sensor, sensor_count++,
new TGeoTranslation(x_offset + inactive_x_shift_left,
y + y_offset, mZ + z_offset - epoxy_thickness - kapton_thickness - copper_thickness - epoxy_thickness - silicon_thickness / 2));
1231 sensor = geoManager->MakeBox(inactive_name_right.c_str(),
siliconMed, inactive_width / 2, sensor_height / 2, silicon_thickness / 2);
1232 sensor->SetLineColor(kRed);
1233 sensor->SetFillColorAlpha(kRed, 1.0);
1234 motherVolume->AddNode(sensor, sensor_count++,
new TGeoTranslation(x_offset + inactive_x_shift_right,
y + y_offset, mZ + z_offset - epoxy_thickness - kapton_thickness - copper_thickness - epoxy_thickness - silicon_thickness / 2));
1239 sensor = geoManager->MakeBox(glue_up_name.c_str(),
epoxyMed, sensor_width / 2, sensor_height / 2, epoxy_thickness / 2);
1240 sensor->SetLineColor(kBlue);
1241 sensor->SetFillColorAlpha(kBlue, 1.0);
1242 motherVolume->AddNode(sensor, sensor_count++,
new TGeoTranslation(x_offset + active_x_shift,
y + y_offset, mZ + z_offset - epoxy_thickness - kapton_thickness - copper_thickness - epoxy_thickness / 2));
1244 if (r_squared < R_material_threshold * R_material_threshold) {
1246 sensor = geoManager->MakeBox(alu_name.c_str(),
AluminumMed, sensor_width / 2, sensor_height / 2, copper_thickness / 2);
1247 sensor->SetLineColor(kBlack);
1248 sensor->SetFillColorAlpha(kBlack, 0.4);
1249 motherVolume->AddNode(sensor, sensor_count++,
new TGeoTranslation(active_x_shift + x_offset,
y + y_offset, mZ + z_offset - epoxy_thickness - kapton_thickness - copper_thickness / 2));
1253 sensor = geoManager->MakeBox(copper_name.c_str(),
copperMed, sensor_width / 2, sensor_height / 2, copper_thickness / 2);
1254 sensor->SetLineColor(kBlack);
1255 sensor->SetFillColorAlpha(kBlack, 0.4);
1256 motherVolume->AddNode(sensor, sensor_count++,
new TGeoTranslation(active_x_shift + x_offset,
y + y_offset, mZ + z_offset - epoxy_thickness - kapton_thickness - copper_thickness / 2));
1261 sensor = geoManager->MakeBox(fpc_name.c_str(),
kaptonMed, sensor_width / 2, sensor_height / 2, kapton_thickness / 2);
1262 sensor->SetLineColor(kGreen);
1263 sensor->SetFillColorAlpha(kGreen, 0.4);
1264 motherVolume->AddNode(sensor, sensor_count++,
new TGeoTranslation(active_x_shift + x_offset,
y + y_offset, mZ + z_offset - epoxy_thickness - kapton_thickness / 2));
1268 sensor = geoManager->MakeBox(glue_down_name.c_str(),
epoxyMed, sensor_width / 2, sensor_height / 2, epoxy_thickness / 2);
1269 sensor->SetLineColor(kBlue);
1270 sensor->SetFillColorAlpha(kBlue, 1.0);
1271 motherVolume->AddNode(sensor, sensor_count++,
new TGeoTranslation(x_offset + active_x_shift,
y + y_offset, mZ + z_offset - epoxy_thickness / 2));
1274 double x_shifted =
x;
1275 double inactive_x_shift, active_x_shift;
1276 double active_x_shift_sensor;
1278 if (justSkippedValue) {
1290 double inactive_x_shift_left, inactive_x_shift_right;
1292 if (sensor_width == 5.0) {
1295 inactive_x_shift_right =
x + sensor_width / 2;
1298 std::vector<std::pair<double, double>> corners_shifted = {
1300 {x_shifted + sensor_width,
y},
1301 {x_shifted,
y + sensor_height},
1302 {x_shifted + sensor_width,
y + sensor_height}};
1304 bool within_bounds =
true;
1305 for (
const auto& corner : corners_shifted) {
1306 double cx = corner.first;
1307 double cy = corner.second;
1308 double dist = std::sqrt(cx * cx + cy * cy);
1310 if (Rin > dist + dist_offset || dist >= Rout) {
1311 within_bounds =
false;
1316 if (within_bounds) {
1318 double r_squared = (
x + x_offset) * (
x + x_offset) + (
y + y_offset) * (
y + y_offset);
1320 if (r_squared < R_material_threshold * R_material_threshold) {
1321 silicon_thickness = 0.005;
1322 copper_thickness = 0.00475;
1323 kapton_thickness = 0.03;
1324 epoxy_thickness = 0.0006;
1328 silicon_thickness = 0.01;
1329 copper_thickness = 0.006;
1330 kapton_thickness = 0.03;
1331 epoxy_thickness = 0.0012;
1338 sensor = geoManager->MakeBox(glue_down_name.c_str(),
epoxyMed, sensor_width / 2, sensor_height / 2, epoxy_thickness / 2);
1339 sensor->SetLineColor(kBlue);
1340 sensor->SetFillColorAlpha(kBlue, 1.0);
1341 motherVolume->AddNode(sensor, sensor_count++,
new TGeoTranslation(x_offset + active_x_shift,
y + y_offset, mZ + z_offset + epoxy_thickness / 2));
1345 sensor = geoManager->MakeBox(fpc_name.c_str(),
kaptonMed, sensor_width / 2, sensor_height / 2, kapton_thickness / 2);
1346 sensor->SetLineColor(kGreen);
1347 sensor->SetFillColorAlpha(kGreen, 0.4);
1348 motherVolume->AddNode(sensor, sensor_count++,
new TGeoTranslation(active_x_shift + x_offset,
y + y_offset, mZ + z_offset + epoxy_thickness + kapton_thickness / 2));
1350 if (r_squared < R_material_threshold * R_material_threshold) {
1353 sensor = geoManager->MakeBox(alu_name.c_str(),
AluminumMed, sensor_width / 2, sensor_height / 2, copper_thickness / 2);
1354 sensor->SetLineColor(kBlack);
1355 sensor->SetFillColorAlpha(kBlack, 0.4);
1356 motherVolume->AddNode(sensor, sensor_count++,
new TGeoTranslation(active_x_shift + x_offset,
y + y_offset, mZ + z_offset + epoxy_thickness + kapton_thickness + copper_thickness / 2));
1360 sensor = geoManager->MakeBox(copper_name.c_str(),
copperMed, sensor_width / 2, sensor_height / 2, copper_thickness / 2);
1361 sensor->SetLineColor(kBlack);
1362 sensor->SetFillColorAlpha(kBlack, 0.4);
1363 motherVolume->AddNode(sensor, sensor_count++,
new TGeoTranslation(active_x_shift + x_offset,
y + y_offset, mZ + z_offset + epoxy_thickness + kapton_thickness + copper_thickness / 2));
1368 sensor = geoManager->MakeBox(glue_up_name.c_str(),
epoxyMed, sensor_width / 2, sensor_height / 2, epoxy_thickness / 2);
1369 sensor->SetLineColor(kBlue);
1370 sensor->SetFillColorAlpha(kBlue, 1.0);
1371 motherVolume->AddNode(sensor, sensor_count++,
new TGeoTranslation(x_offset + active_x_shift,
y + y_offset, mZ + z_offset + epoxy_thickness + kapton_thickness + copper_thickness + epoxy_thickness / 2));
1373 if (sensor_width == 2.5) {
1376 sensor = geoManager->MakeBox(sensor_name.c_str(),
siliconMed, active_width / 2, active_height / 2, silicon_thickness / 2);
1377 sensor->SetLineColor(SiColor);
1378 sensor->SetFillColorAlpha(SiColor, 0.4);
1379 motherVolume->AddNode(sensor, sensor_count++,
new TGeoTranslation(active_x_shift_sensor + x_offset,
y + y_offset, mZ + z_offset + epoxy_thickness + kapton_thickness + copper_thickness + epoxy_thickness + silicon_thickness / 2));
1382 sensor = geoManager->MakeBox(inactive_name.c_str(),
siliconMed, (sensor_width - active_width) / 2, sensor_height / 2, silicon_thickness / 2);
1383 sensor->SetLineColor(kRed);
1384 sensor->SetFillColorAlpha(kRed, 1.0);
1385 motherVolume->AddNode(sensor, sensor_count++,
new TGeoTranslation(x_offset + inactive_x_shift,
y + y_offset, mZ + z_offset + epoxy_thickness + kapton_thickness + copper_thickness + epoxy_thickness + silicon_thickness / 2));
1390 sensor = geoManager->MakeBox(sensor_name.c_str(),
siliconMed, active_width / 2, sensor_height / 2, silicon_thickness / 2);
1391 sensor->SetLineColor(SiColor);
1392 sensor->SetFillColorAlpha(SiColor, 0.4);
1393 motherVolume->AddNode(sensor, sensor_count++,
new TGeoTranslation(x_offset + x_shifted + inactive_width / 2,
y + y_offset, mZ + z_offset + epoxy_thickness + kapton_thickness + copper_thickness + epoxy_thickness + silicon_thickness / 2));
1397 sensor = geoManager->MakeBox(inactive_name_left.c_str(),
siliconMed, inactive_width / 2, sensor_height / 2, silicon_thickness / 2);
1398 sensor->SetLineColor(kRed);
1399 sensor->SetFillColorAlpha(kRed, 1.0);
1400 motherVolume->AddNode(sensor, sensor_count++,
new TGeoTranslation(x_offset + inactive_x_shift_left,
y + y_offset, mZ + z_offset + epoxy_thickness + kapton_thickness + copper_thickness + epoxy_thickness + silicon_thickness / 2));
1404 sensor = geoManager->MakeBox(inactive_name_right.c_str(),
siliconMed, inactive_width / 2, sensor_height / 2, silicon_thickness / 2);
1405 sensor->SetLineColor(kRed);
1406 sensor->SetFillColorAlpha(kRed, 1.0);
1407 motherVolume->AddNode(sensor, sensor_count++,
new TGeoTranslation(x_offset + inactive_x_shift_right,
y + y_offset, mZ + z_offset + epoxy_thickness + kapton_thickness + copper_thickness + epoxy_thickness + silicon_thickness / 2));
1417 LOG(
debug) <<
"FT3Module: done create_layout";
1420void FT3Module::createModule(
double mZ,
int layerNumber,
int direction,
double Rin,
double Rout,
double overlap,
const std::string&
face,
const std::string& layout_type, TGeoVolume* motherVolume)
1423 LOG(
debug) <<
"FT3Module: createModule - Layer " << layerNumber <<
", Direction " << direction <<
", Face " <<
face;
1424 create_layout(mZ, layerNumber, direction, Rin, Rout, overlap,
face, layout_type, motherVolume);
1425 LOG(
debug) <<
"FT3Module: done createModule";
1429 double Rin,
double Rout,
double z_offset_local,
1431 TGeoVolume* motherVolume)
1433 LOG(
debug) <<
"FT3Module: createModule_staveGeo - Layer " << layerNumber
1434 <<
" at z=" << mZ <<
", Direction " << direction;
1435 create_layout_staveGeo(mZ, layerNumber, direction, Rin, Rout,
1436 z_offset_local, staveConfig, motherVolume);
1437 LOG(
debug) <<
"FT3Module: done createModule_staveGeo";
std::pair< double, double > calculate_y_range(double x_left, double x_right, double Rin, double Rout)
double calculate_y_circle(double x, double radius)
std::array< std::array< double, 3 >, 4 > buildStaveTriangle(int direction)
Definition of the FT3Module class.
std::pair< std::pair< double, double >, std::pair< double, double > > PositionRangeType
std::vector< PositionType > PositionTypes
std::pair< PositionTypes, PositionTypes > PosNegPositionTypes
void createModule_staveGeo(double mZ, int layerNumber, int direction, double Rin, double Rout, double z_offset_local, const Constants::StaveConfig &staveConfig, TGeoVolume *motherVolume)
static TGeoMedium * carbonFiberMed
static TGeoMedium * epoxyMed
static TGeoMaterial * epoxyMat
static TGeoMaterial * carbonFiberMat
static TGeoMedium * siliconMed
static void createModule(double mZ, int layerNumber, int direction, double Rin, double Rout, double overlap, const std::string &face, const std::string &layout_type, TGeoVolume *motherVolume)
static TGeoMedium * copperMed
static TGeoMaterial * kaptonMat
static TGeoMaterial * copperMat
static TGeoMaterial * siliconMat
static TGeoMedium * AluminumMed
static TGeoMedium * kaptonMed
static TGeoMaterial * AluminumMat
static void initialize_materials()
static const FT3BaseParam & Instance()
GLenum GLuint GLint GLenum face
const double staveSensorGap
const double single_sensor_height
const double epoxyThickness
const double effectiveCarbonThickness_Stave
const double sensor2x1_height
const double z_offsetStave(double x_midpoint_spacing)
const double inactive_width
const double active_width
const int staveIdxToID(int staveIdx, unsigned nStavesPerDisc)
const double active_height
const double sensor2x1_gap
const double sensor2x1_width
const double siliconThickness
const double getStackHeight(unsigned nSensorsPerStack)
const double kaptonThickness
const int carbonFiberColor
const double copperThickness
const int SiInactiveColor
const double staveTriangleHeight
const std::vector< unsigned > kSensorsPerStack
std::string to_string(gsl::span< T, Size > span)
const std::vector< double > & x_midpoints
const double x_midpoint_spacing
const std::vector< double > & y_lengths
const double maxToleranceInner
const std::map< int, std::pair< double, bool > > & staveID_to_y_midpoint
const std::vector< bool > & staveOnFront
const double maxToleranceOuter
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"