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 TGeoMixture*
kaptonMat =
new TGeoMixture(
"FT3_Kapton", 4, 1.346);
71 kaptonMat->DefineElement(0, 12.0107, 6, 0.5641);
72 kaptonMat->DefineElement(1, 1.00794, 1, 0.2564);
73 kaptonMat->DefineElement(2, 14.0067, 7, 0.0513);
74 kaptonMat->DefineElement(3, 15.999, 8, 0.1282);
82 auto* itsEpoxy =
new TGeoMixture(
"FT3_Epoxy", 3);
83 itsEpoxy->AddElement(itsC, 18);
84 itsEpoxy->AddElement(itsH, 19);
85 itsEpoxy->AddElement(itsO, 3);
86 itsEpoxy->SetDensity(2.186);
88 epoxyMed =
new TGeoMedium(
"FT3_Epoxy", 4, itsEpoxy);
91 AluminumMat =
new TGeoMaterial(
"Aluminum", 26.98, 13, 2.7);
93 LOG(
debug) <<
"FT3Module: done initialize_materials";
98 return (
x *
x < radius * radius) ? std::sqrt(radius * radius -
x *
x) : 0;
102 double x_left,
double x_right,
double Rin,
double Rout)
114 if (x_right < -Rin) {
122 }
else if (x_left < 0) {
127 }
else if (x_left < Rin) {
136 return {min_y_abs, max_y_abs};
158 std::pair<double, double>& absAllowedYRange)
166 double max_sensor_y_abs = std::min(absAllowedYRange.second, y_ranges.first.second);
170 if (!y_positions.first.empty()) {
173 }
else if (absAllowedYRange.first > 0) {
175 y_top = std::max(absAllowedYRange.first, y_ranges.first.first);
178 y_top = y_ranges.first.first;
181 while ((y_top + sensorStackHeight) <= max_sensor_y_abs) {
182 y_positions.first.emplace_back(y_top, kSensorStack);
183 y_top += sensorAbsStackYShift;
189 if (!y_positions.second.empty()) {
193 }
else if (absAllowedYRange.first > 0) {
195 y_bottom = std::min(-absAllowedYRange.first, y_ranges.second.first);
198 y_bottom = y_ranges.second.first;
201 while ((y_bottom - sensorStackHeight) >= -max_sensor_y_abs) {
202 y_positions.second.emplace_back(y_bottom, kSensorStack);
203 y_bottom -= sensorAbsStackYShift;
233 std::array<double, 3> xv_inner, xv_outer, zv_inner, zv_outer;
237 zv_outer[0] = (direction == 1) ? -H
244 xv_outer[2] = -xv_outer[1];
248 xv_inner[0] = xv_outer[0];
250 zv_inner[0] = (direction == 1) ? zv_outer[0] + z_shift_inner
251 : zv_outer[0] - z_shift_inner;
253 zv_inner[1] = (direction == 1) ? zv_outer[1] - d
256 xv_inner[1] = xv_outer[1] - x_shift_abs;
258 zv_inner[2] = zv_inner[1];
259 xv_inner[2] = -xv_inner[1];
261 return {xv_outer, zv_outer, xv_inner, zv_inner};
268void FT3Module::addStaveVolume(
269 TGeoVolume* motherVolume, std::string volumeName,
int direction,
270 unsigned* volume_count,
double staveLength,
271 std::array<std::array<double, 3>, 4> staveTriangles,
272 std::pair<double, double>& absAllowedYRange,
273 double x_mid,
double y_mid,
double z_stave_shift_forward)
276 if (absAllowedYRange.first < 0 || absAllowedYRange.second < 0 ||
277 absAllowedYRange.first >= absAllowedYRange.second) {
278 LOG(error) <<
"Invalid allowed y range in addStaveVolume(): ("
279 << absAllowedYRange.first <<
", " << absAllowedYRange.second
280 <<
"). Both values must be non-negative and the first "
281 <<
"value must be less than the second value.";
285 double y_lower = y_mid - staveLength / 2;
286 double y_upper = y_mid + staveLength / 2;
287 bool splitStave =
false;
289 y_lower = std::max(y_lower, absAllowedYRange.first);
290 y_upper = std::min(y_upper, absAllowedYRange.second);
291 }
else if (y_upper < 0) {
292 y_lower = std::max(y_lower, -absAllowedYRange.second);
293 y_upper = std::min(y_upper, -absAllowedYRange.first);
296 if (absAllowedYRange.first > 0) {
299 y_lower = absAllowedYRange.first;
302 y_lower = std::max(y_lower, -absAllowedYRange.second);
304 y_upper = std::min(y_upper, absAllowedYRange.second);
306 double staveLengthToUse = y_upper - y_lower;
314 TGeoXtru* staveFull =
new TGeoXtru(2);
315 staveFull->SetName((volumeName +
"_Xtru_outer").c_str());
316 staveFull->DefinePolygon(3, staveTriangles[0].
data(), staveTriangles[1].
data());
317 staveFull->DefineSection(0, 0);
318 staveFull->DefineSection(1, staveLengthToUse);
320 TGeoXtru* staveInner =
new TGeoXtru(2);
321 staveInner->SetName((volumeName +
"_Xtru_inner").c_str());
322 staveInner->DefinePolygon(3, staveTriangles[2].
data(), staveTriangles[3].
data());
323 staveInner->DefineSection(0, 0);
324 staveInner->DefineSection(1, staveLengthToUse);
326 TGeoCompositeShape* staveShape =
new TGeoCompositeShape(
327 (volumeName +
"_shape").c_str(),
328 Form(
"%s - %s", staveFull->GetName(), staveInner->GetName()));
329 TGeoVolume* staveVolume =
new TGeoVolume(
330 (volumeName).c_str(),
336 TGeoRotation* rot =
new TGeoRotation();
350 double z_shift = (direction == 1) ? z_stave_shift_forward : -z_stave_shift_forward;
351 TGeoCombiTrans* combiTrans =
352 new TGeoCombiTrans(x_mid, y_lower, z_shift, rot);
353 motherVolume->AddNode(staveVolume,
360 TGeoCombiTrans* combiTransSplit =
361 new TGeoCombiTrans(x_mid, -y_upper, z_shift, rot);
362 motherVolume->AddNode(staveVolume,
374void FT3Module::addDetectorVolume(
375 TGeoVolume* motherVolume, std::string volumeName,
int color, TGeoMedium* med,
376 unsigned volume_count,
double x_mid,
double y_mid,
double z_mid,
377 double x_half_length,
double y_half_length,
double z_half_length)
379 TGeoManager* geoManager = gGeoManager;
380 TGeoVolume* volume = geoManager->MakeBox(volumeName.c_str(), med, x_half_length,
381 y_half_length, z_half_length);
382 volume->SetLineColor(
color);
383 volume->SetFillColorAlpha(
color, 0.4);
384 motherVolume->AddNode(
398void FT3Module::add2x1GlueVolume(
399 TGeoVolume* motherVolume,
int layerNumber,
int direction,
unsigned stave_idx,
400 unsigned volume_count,
double x_mid,
double y_mid,
double z_mid,
401 std::string element_glued_to)
414void FT3Module::add2x1CopperVolume(
415 TGeoVolume* motherVolume,
int layerNumber,
int direction,
unsigned stave_idx,
416 unsigned volume_count,
double x_mid,
double y_mid,
double z_mid)
429void FT3Module::add2x1KaptonVolume(
430 TGeoVolume* motherVolume,
int layerNumber,
int direction,
unsigned stave_idx,
431 unsigned volume_count,
double x_mid,
double y_mid,
double z_mid)
458void FT3Module::addSingleSensorVolume(
459 TGeoVolume* motherVolume,
int layerNumber,
int direction,
unsigned stave_idx,
460 unsigned volume_count,
double active_x_mid,
double y_mid,
double z_mid,
464 TGeoManager* geoManager = gGeoManager;
469 volume_count, active_x_mid, y_mid, z_mid,
480 volume_count, inactive_x_mid, y_mid, z_mid,
484void FT3Module::create_layout_staveGeo(
double mZ,
int layerNumber,
int direction,
485 double Rin,
double Rout,
double z_offset_local,
487 TGeoVolume* motherVolume)
489 LOG(
debug) <<
"FT3Module: create_layout_staveGeo - Direction "
490 << direction <<
", Layer " << layerNumber;
515 double totalSensorMaterialThickness =
518 double z_offset_to_carbon_face = z_offset_local - totalSensorMaterialThickness - 0.1;
519 double z_offset_to_glue_Ka =
521 double z_offset_to_kapton =
524 double z_offset_to_copper =
527 double z_offset_to_glue_Si =
530 double z_offset_to_silicon =
536 std::vector<PosNegPositionTypes> y_positionsPosNeg;
541 std::vector<std::vector<unsigned>> nSensorStackCountPerStave(
545 unsigned staveVolumeCount = 0;
546 for (
unsigned i_stave = 0; i_stave < staveConfig.
x_midpoints.size(); i_stave++) {
550 double y_midpoint = 0.;
551 bool mirrorStaveAroundX =
false;
553 double stave_half_length = staveConfig.
y_lengths[i_stave] / 2;
555 if (ft3Params.placeSensorStackInMiddleOfStave) {
568 y_ranges = {{-stackHeight / 2, stave_half_length},
581 y_midpoint = y_midpoint_it->second.first;
582 mirrorStaveAroundX = y_midpoint_it->second.second;
583 y_ranges.first = {y_midpoint - stave_half_length, y_midpoint + stave_half_length};
584 y_ranges.second = {-y_midpoint + stave_half_length, -y_midpoint - stave_half_length};
588 double tolerance_inner, tolerance_outer;
589 if (staveConfig.
isML) {
590 tolerance_inner = ft3Params.staveTolMLInner;
591 tolerance_outer = ft3Params.staveTolMLOuter;
593 tolerance_inner = ft3Params.staveTolOTInner;
594 tolerance_outer = ft3Params.staveTolOTOuter;
615 std::pair<double, double> absAllowedYRange =
624 absAllowedYRange.first -= tolerance_inner;
625 absAllowedYRange.second += tolerance_outer;
627 if (absAllowedYRange.first < 0) {
628 absAllowedYRange.first = 0;
630 if (absAllowedYRange.second <= 0) {
631 LOG(warning) <<
"For stave " << i_stave <<
" in layer " << layerNumber
632 <<
" with direction " << direction <<
": no space to place sensors after applying tolerances, skipping stave.";
638 double z_stave_shift_forward =
639 -z_offset_to_carbon_face + z_stave_shift_abs;
640 std::string stave_volume_name =
646 motherVolume, stave_volume_name, direction, &staveVolumeCount,
647 staveConfig.
y_lengths[i_stave], staveTriangles, absAllowedYRange,
648 staveConfig.
x_midpoints[i_stave], y_midpoint, z_stave_shift_forward);
650 if (mirrorStaveAroundX) {
652 motherVolume, stave_volume_name +
"_mirrored", direction, &staveVolumeCount,
653 staveConfig.
y_lengths[i_stave], staveTriangles, absAllowedYRange,
654 staveConfig.
x_midpoints[i_stave], -y_midpoint, z_stave_shift_forward);
659 unsigned nModulesCurr = y_positionsPosNeg.back().first.size() + y_positionsPosNeg.back().second.size();
660 fill_stave(y_positionsPosNeg.back(), Rin, Rout, x_left,
663 unsigned nModulesAdded = y_positionsPosNeg.back().first.size() + y_positionsPosNeg.back().second.size() - nModulesCurr;
664 nSensorStackCountPerStave[i_stave][i_kSens] = nModulesAdded;
665 nSensorStackTotal[i_kSens] += nModulesAdded;
667 std::string moduleDebugStr =
"Module size counts for layer " +
std::to_string(layerNumber) +
" in direction " +
std::to_string(direction) +
":\n";
673 std::string totalModuleInfoStr =
674 "Total module size counts for layer " +
std::to_string(layerNumber) +
679 LOG(info) << totalModuleInfoStr;
682 for (
unsigned i_stave = 0; i_stave < staveConfig.
x_midpoints.size(); i_stave++) {
695 if (direction == 1) {
700 int z_offset_multiplier = (direction == 1) ? -1 : 1;
703 double z_stave_shift = 0;
710 unsigned sensor_count = 0;
711 for (
int y_sign = -1; y_sign < 2; y_sign += 2) {
713 const auto& positions = (y_sign == 1) ? y_positionsPosNeg[i_stave].
first
714 : y_positionsPosNeg[i_stave].second;
716 for (
unsigned i_y_pos = 0; i_y_pos < positions.size(); i_y_pos++) {
718 for (
unsigned i_sens = 0; i_sens < positions[i_y_pos].second; i_sens++) {
722 double z_mid = z_offset_to_silicon * z_offset_multiplier + z_stave_shift;
723 addSingleSensorVolume(
724 motherVolume, layerNumber, direction, i_stave, sensor_count,
728 addSingleSensorVolume(
729 motherVolume, layerNumber, direction, i_stave, sensor_count + 1,
731 y_mid, z_mid,
false);
733 z_mid = z_offset_to_glue_Si * z_offset_multiplier + z_stave_shift;
735 motherVolume, layerNumber, direction, i_stave, sensor_count,
736 x_mid, y_mid, z_mid,
"SiCu");
738 z_mid = z_offset_to_copper * z_offset_multiplier + z_stave_shift;
740 motherVolume, layerNumber, direction, i_stave, sensor_count,
741 x_mid, y_mid, z_mid);
743 z_mid = z_offset_to_kapton * z_offset_multiplier + z_stave_shift;
745 motherVolume, layerNumber, direction, i_stave, sensor_count,
746 x_mid, y_mid, z_mid);
748 z_mid = z_offset_to_glue_Ka * z_offset_multiplier + z_stave_shift;
750 motherVolume, layerNumber, direction, i_stave, sensor_count,
751 x_mid, y_mid, z_mid,
"CarbonKapton");
761void 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)
764 LOG(
debug) <<
"FT3Module: create_layout - Layer " << layerNumber <<
", Direction " << direction <<
", Face " <<
face;
765 TGeoManager* geoManager = gGeoManager;
774 double sensor_width = 5.0;
775 double sensor_height = 9.6;
780 double silicon_thickness = 0.01;
781 double copper_thickness = 0.006;
782 double kapton_thickness = 0.03;
783 double epoxy_thickness = 0.0012;
785 double carbonFiberThickness = 0.01;
787 double foamSpacingThickness = 1.0;
794 double z_offset = (
face ==
"front") ? -foamSpacingThickness / 2.0 - carbonFiberThickness : foamSpacingThickness / 2.0 + carbonFiberThickness;
797 if (sensor_height == 3.2 && sensor_width == 2.5) {
800 }
else if (sensor_height == 19.2 && sensor_width == 5) {
804 x_offset = sensor_width / 2;
805 y_offset = sensor_height / 2;
808 double x_condition_min = 0;
809 double x_condition_max = 0;
810 double offset_Rin_lower = 0;
811 double offset_Rin_upper = 0;
812 bool adjust_bottom_y_pos =
false;
813 bool adjust_bottom_y_neg =
false;
814 double x_adjust_bottom_y_pos = 0;
815 double bottom_y_pos_value = 0;
816 double bottom_y_neg_value = 0;
818 double Rin_offset = (sensor_height == 19.2) ? 1 : 0;
819 double Rout_offset = (sensor_height == 19.2) ? 1 : 0;
821 if (Rin == 7 && sensor_height == 9.6 && sensor_width == 5) {
822 x_condition_min = -Rin - 2;
823 x_condition_max = Rin;
825 adjust_bottom_y_pos =
true;
826 adjust_bottom_y_neg =
true;
827 x_adjust_bottom_y_pos = 3.5;
828 bottom_y_pos_value = 3.5;
829 bottom_y_neg_value = -3.5;
830 }
else if (Rin == 5 && sensor_height == 9.6 && sensor_width == 5) {
831 x_condition_min = -Rin - 6;
832 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 || Rin == 7) && sensor_height == 19.2) {
839 x_condition_min = -Rin - 3;
840 x_condition_max = Rin - 0.2;
842 adjust_bottom_y_pos =
false;
843 adjust_bottom_y_neg =
false;
844 }
else if (Rin == 5 && sensor_height == 3.2) {
845 x_condition_min = -(Rin + 2.6);
846 x_condition_max = Rin + 1.5;
847 adjust_bottom_y_pos =
true;
848 adjust_bottom_y_neg =
true;
849 x_adjust_bottom_y_pos = 3.5;
850 bottom_y_pos_value = 3.5;
851 bottom_y_neg_value = -3.5;
852 }
else if (Rin == 7 && sensor_height == 3.2) {
853 x_condition_min = -Rin - 1;
854 x_condition_max = Rin - 0.2;
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 == 5 && sensor_height == 9.6 && sensor_width == 2.5) {
861 x_condition_min = -(Rin + 2.6);
862 x_condition_max = Rin;
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 == 7 && sensor_height == 9.6 && sensor_width == 2.5) {
869 x_condition_min = -Rin - 2.6;
870 x_condition_max = Rin + 1;
872 adjust_bottom_y_pos =
true;
873 adjust_bottom_y_neg =
true;
874 x_adjust_bottom_y_pos = 5.5;
875 bottom_y_pos_value = 3.5;
876 bottom_y_neg_value = -3.5;
877 }
else if (Rin == 10 && sensor_height == 9.6 && sensor_width == 5.0) {
878 x_condition_min = -Rin - 4;
879 x_condition_max = Rin;
881 adjust_bottom_y_pos =
false;
882 adjust_bottom_y_neg =
false;
883 x_adjust_bottom_y_pos = 3.5;
884 bottom_y_pos_value = 3.5;
885 bottom_y_neg_value = -3.5;
886 }
else if (Rin == 20 && sensor_height == 9.6 && sensor_width == 5.0) {
887 x_condition_min = -Rin - 4;
888 x_condition_max = Rin;
890 adjust_bottom_y_pos =
false;
891 adjust_bottom_y_neg =
false;
892 x_adjust_bottom_y_pos = 3.5;
893 bottom_y_pos_value = 3.5;
894 bottom_y_neg_value = -3.5;
896 LOG(warning) <<
"Different config - to determine offsets needed for " <<
"Rin = " << Rin <<
" ; sensor_height = " << sensor_height <<
" ; sensor_width = " << sensor_width <<
" layer " << layerNumber;
897 x_condition_min = -Rin - sensor_width;
898 x_condition_max = Rin;
899 adjust_bottom_y_pos =
false;
900 adjust_bottom_y_neg =
false;
903 offset_Rin_lower = Rin - Rin_offset;
904 offset_Rin_upper = Rout + Rout_offset;
906 std::set<std::pair<double, double>> placed_sensors;
907 int sensor_count = 0;
909 int placementCounter = 0;
910 bool justSkipped =
false;
912 std::vector<double> X_positions;
913 std::vector<int> justSkipped1;
915 if (sensor_width == 2.5) {
917 if (
face ==
"front") {
918 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,
919 -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,
921 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};
922 }
else if (
face ==
"back") {
923 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,
924 -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,
925 51.6, 54.1, 60.8, 63.3};
926 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};
929 if (Rin == 10 || Rin == 20) {
932 float X_start = -2.0 - 13.5 * (sensor_width - overlap);
933 float X_start_pos = 2.0 - 0.5 * (sensor_width - overlap);
934 if (
face ==
"back") {
935 X_start += (sensor_width - overlap);
936 X_start_pos += (sensor_width - overlap);
938 while (X_start < -2) {
939 X_positions.push_back(X_start);
940 justSkipped1.push_back(1);
941 X_start += 2 * (sensor_width - overlap);
943 while (X_start_pos < Rout + x_offset - sensor_width) {
944 X_positions.push_back(X_start_pos);
945 justSkipped1.push_back(1);
946 X_start_pos += 2 * (sensor_width - overlap);
950 if (
face ==
"front") {
951 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};
952 justSkipped1 = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
953 }
else if (
face ==
"back") {
954 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};
955 justSkipped1 = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
960 if (layout_type ==
"rectangular") {
962 double x_start = -Rout;
965 std::vector<double> x_positions;
966 for (
double x = x_start;
x <= x_end;
x += sensor_width) {
967 x_positions.push_back(
x);
971 const int rowsToAlternate = 2;
973 for (
size_t i = 0;
i < X_positions.size(); ++
i) {
975 double x = X_positions[
i];
976 bool justSkippedValue = justSkipped1[
i];
978 std::vector<double> y_positions_positive;
979 std::vector<double> y_positions_negative;
981 for (
double y = -Rout - Rin_offset;
y <= Rout + Rin_offset;
y += sensor_height) {
982 std::vector<std::pair<double, double>> corners = {
984 {
x + sensor_width,
y},
985 {
x,
y + sensor_height},
986 {
x + sensor_width,
y + sensor_height}};
988 bool within_bounds = std::all_of(corners.begin(), corners.end(), [&](
const std::pair<double, double>& corner) {
989 double cx = corner.first;
990 double cy = corner.second;
991 return (offset_Rin_lower <= std::sqrt(cx * cx + cy * cy) && std::sqrt(cx * cx + cy * cy) <= offset_Rin_upper);
996 y_positions_positive.push_back(
y);
998 y_positions_negative.push_back(
y);
1004 if (x_condition_min <=
x &&
x <= x_condition_max && !y_positions_positive.empty()) {
1005 double first_y_pos = y_positions_positive.front();
1006 double last_y_pos = y_positions_positive.back() - sensor_height;
1009 double top_distance_pos = top_y_pos - last_y_pos;
1011 if (adjust_bottom_y_pos &&
x > x_adjust_bottom_y_pos) {
1012 bottom_y_pos = bottom_y_pos_value;
1015 double bottom_distance_pos = first_y_pos - bottom_y_pos;
1017 if (std::abs(top_distance_pos + bottom_distance_pos) >= sensor_height) {
1018 for (
auto&
y : y_positions_positive) {
1019 y -= bottom_distance_pos - 0.2;
1021 y_positions_positive.push_back(y_positions_positive.back() + sensor_height);
1026 if (x_condition_min <=
x &&
x <= x_condition_max && !y_positions_negative.empty()) {
1027 double first_y_neg = y_positions_negative.front();
1028 double last_y_neg = y_positions_negative.back() + sensor_height;
1031 double top_distance_neg = -(top_y_neg - first_y_neg);
1033 if (adjust_bottom_y_neg &&
x > x_adjust_bottom_y_pos) {
1034 bottom_y_neg = bottom_y_neg_value;
1037 double bottom_distance_neg = -(last_y_neg - bottom_y_neg);
1039 top_distance_neg = std::abs(top_distance_neg);
1040 bottom_distance_neg = std::abs(bottom_distance_neg);
1041 std::sort(y_positions_negative.begin(), y_positions_negative.end());
1043 if (std::abs(top_distance_neg + bottom_distance_neg) >= sensor_height) {
1044 if (sensor_height == 19.2) {
1045 for (
auto&
y : y_positions_negative) {
1046 y -= bottom_distance_neg;
1049 for (
auto&
y : y_positions_negative) {
1050 y += bottom_distance_neg - 0.2;
1053 y_positions_negative.push_back(y_positions_negative.front() - sensor_height);
1058 if ((x < x_condition_min || x > x_condition_max) && !y_positions_negative.empty() && !y_positions_positive.empty()) {
1059 double first_y_neg = y_positions_negative.front();
1060 double last_y_pos = y_positions_positive.back() + sensor_height;
1062 double bottom_y_pos = -top_y_pos;
1064 double top_distance_pos = std::abs(top_y_pos - last_y_pos);
1065 double bottom_distance_pos = std::abs(first_y_neg - bottom_y_pos);
1067 if (top_distance_pos + bottom_distance_pos >= sensor_height) {
1068 for (
auto&
y : y_positions_positive) {
1069 y += top_distance_pos - 0.2;
1071 for (
auto&
y : y_positions_negative) {
1072 y += top_distance_pos - 0.2;
1074 double new_y = y_positions_negative.front() - sensor_height;
1076 if (
static_cast<int>(new_y) >
static_cast<int>(bottom_y_pos)) {
1077 y_positions_negative.push_back(new_y);
1082 std::sort(y_positions_negative.begin(), y_positions_negative.end());
1083 std::sort(y_positions_positive.begin(), y_positions_positive.end());
1085 double first_y_pos = y_positions_negative.front();
1087 last_y_pos = y_positions_positive.back() + sensor_height;
1090 bottom_y_pos = -top_y_pos;
1091 top_distance_pos = std::abs(top_y_pos - last_y_pos);
1092 bottom_distance_pos = std::abs(first_y_pos - bottom_y_pos);
1094 double Lb = (bottom_distance_pos + top_distance_pos) / 2;
1096 if (top_distance_pos < Lb) {
1097 double shift = Lb - top_distance_pos;
1098 for (
auto&
y : y_positions_negative) {
1101 for (
auto&
y : y_positions_positive) {
1104 }
else if (top_distance_pos > Lb) {
1105 double shift = top_distance_pos - Lb;
1106 for (
auto&
y : y_positions_negative) {
1109 for (
auto&
y : y_positions_positive) {
1115 std::vector<double> y_positions = y_positions_positive;
1116 y_positions.insert(y_positions.end(), y_positions_negative.begin(), y_positions_negative.end());
1118 for (
double y : y_positions) {
1121 double R_material_threshold = 0;
1123 if (placed_sensors.find({x, y}) == placed_sensors.end()) {
1124 placed_sensors.insert({
x,
y});
1128 double left_inactive_x_shift;
1129 double right_inactive_x_shift;
1130 double active_x_shift_sensor;
1132 if (
face ==
"front") {
1134 double active_x_shift, inactive_x_shift;
1136 if (justSkippedValue) {
1148 double inactive_x_shift_left, inactive_x_shift_right;
1150 if (sensor_width == 5.0) {
1153 inactive_x_shift_right =
x + sensor_width / 2;
1156 std::vector<std::pair<double, double>> corners_shifted = {
1158 {
x + sensor_width,
y},
1159 {
x,
y + sensor_height},
1160 {
x + sensor_width,
y + sensor_height}};
1162 bool within_bounds =
true;
1163 for (
const auto& corner : corners_shifted) {
1164 double cx = corner.first;
1165 double cy = corner.second;
1166 double dist = std::sqrt(cx * cx + cy * cy);
1168 if (Rin > dist || dist >= Rout) {
1169 within_bounds =
false;
1174 if (within_bounds) {
1176 double r_squared = (
x + x_offset) * (
x + x_offset) + (
y + y_offset) * (
y + y_offset);
1178 if (r_squared < R_material_threshold * R_material_threshold) {
1179 silicon_thickness = 0.005;
1180 copper_thickness = 0.00475;
1181 kapton_thickness = 0.03;
1182 epoxy_thickness = 0.0012;
1186 silicon_thickness = 0.01;
1187 copper_thickness = 0.006;
1188 kapton_thickness = 0.03;
1189 epoxy_thickness = 0.0012;
1194 if (sensor_width == 2.5) {
1197 sensor = geoManager->MakeBox(sensor_name.c_str(),
siliconMed, active_width / 2, active_height / 2, silicon_thickness / 2);
1198 sensor->SetLineColor(SiColor);
1199 sensor->SetFillColorAlpha(SiColor, 0.4);
1200 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));
1203 sensor = geoManager->MakeBox(inactive_name.c_str(),
siliconMed, (sensor_width - active_width) / 2, sensor_height / 2, silicon_thickness / 2);
1204 sensor->SetLineColor(kRed);
1205 sensor->SetFillColorAlpha(kRed, 1.0);
1206 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));
1211 sensor = geoManager->MakeBox(sensor_name.c_str(),
siliconMed, active_width / 2, sensor_height / 2, silicon_thickness / 2);
1212 sensor->SetLineColor(SiColor);
1213 sensor->SetFillColorAlpha(SiColor, 0.4);
1214 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));
1217 sensor = geoManager->MakeBox(inactive_name_left.c_str(),
siliconMed, inactive_width / 2, sensor_height / 2, silicon_thickness / 2);
1218 sensor->SetLineColor(kRed);
1219 sensor->SetFillColorAlpha(kRed, 1.0);
1220 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));
1223 sensor = geoManager->MakeBox(inactive_name_right.c_str(),
siliconMed, inactive_width / 2, sensor_height / 2, silicon_thickness / 2);
1224 sensor->SetLineColor(kRed);
1225 sensor->SetFillColorAlpha(kRed, 1.0);
1226 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));
1231 sensor = geoManager->MakeBox(glue_up_name.c_str(),
epoxyMed, sensor_width / 2, sensor_height / 2, epoxy_thickness / 2);
1232 sensor->SetLineColor(kBlue);
1233 sensor->SetFillColorAlpha(kBlue, 1.0);
1234 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));
1236 if (r_squared < R_material_threshold * R_material_threshold) {
1238 sensor = geoManager->MakeBox(alu_name.c_str(),
AluminumMed, sensor_width / 2, sensor_height / 2, copper_thickness / 2);
1239 sensor->SetLineColor(kBlack);
1240 sensor->SetFillColorAlpha(kBlack, 0.4);
1241 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));
1245 sensor = geoManager->MakeBox(copper_name.c_str(),
copperMed, sensor_width / 2, sensor_height / 2, copper_thickness / 2);
1246 sensor->SetLineColor(kBlack);
1247 sensor->SetFillColorAlpha(kBlack, 0.4);
1248 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(fpc_name.c_str(),
kaptonMed, sensor_width / 2, sensor_height / 2, kapton_thickness / 2);
1254 sensor->SetLineColor(kGreen);
1255 sensor->SetFillColorAlpha(kGreen, 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 / 2));
1260 sensor = geoManager->MakeBox(glue_down_name.c_str(),
epoxyMed, sensor_width / 2, sensor_height / 2, epoxy_thickness / 2);
1261 sensor->SetLineColor(kBlue);
1262 sensor->SetFillColorAlpha(kBlue, 1.0);
1263 motherVolume->AddNode(sensor, sensor_count++,
new TGeoTranslation(x_offset + active_x_shift,
y + y_offset, mZ + z_offset - epoxy_thickness / 2));
1266 double x_shifted =
x;
1267 double inactive_x_shift, active_x_shift;
1268 double active_x_shift_sensor;
1270 if (justSkippedValue) {
1282 double inactive_x_shift_left, inactive_x_shift_right;
1284 if (sensor_width == 5.0) {
1287 inactive_x_shift_right =
x + sensor_width / 2;
1290 std::vector<std::pair<double, double>> corners_shifted = {
1292 {x_shifted + sensor_width,
y},
1293 {x_shifted,
y + sensor_height},
1294 {x_shifted + sensor_width,
y + sensor_height}};
1296 bool within_bounds =
true;
1297 for (
const auto& corner : corners_shifted) {
1298 double cx = corner.first;
1299 double cy = corner.second;
1300 double dist = std::sqrt(cx * cx + cy * cy);
1302 if (Rin > dist + dist_offset || dist >= Rout) {
1303 within_bounds =
false;
1308 if (within_bounds) {
1310 double r_squared = (
x + x_offset) * (
x + x_offset) + (
y + y_offset) * (
y + y_offset);
1312 if (r_squared < R_material_threshold * R_material_threshold) {
1313 silicon_thickness = 0.005;
1314 copper_thickness = 0.00475;
1315 kapton_thickness = 0.03;
1316 epoxy_thickness = 0.0006;
1320 silicon_thickness = 0.01;
1321 copper_thickness = 0.006;
1322 kapton_thickness = 0.03;
1323 epoxy_thickness = 0.0012;
1330 sensor = geoManager->MakeBox(glue_down_name.c_str(),
epoxyMed, sensor_width / 2, sensor_height / 2, epoxy_thickness / 2);
1331 sensor->SetLineColor(kBlue);
1332 sensor->SetFillColorAlpha(kBlue, 1.0);
1333 motherVolume->AddNode(sensor, sensor_count++,
new TGeoTranslation(x_offset + active_x_shift,
y + y_offset, mZ + z_offset + epoxy_thickness / 2));
1337 sensor = geoManager->MakeBox(fpc_name.c_str(),
kaptonMed, sensor_width / 2, sensor_height / 2, kapton_thickness / 2);
1338 sensor->SetLineColor(kGreen);
1339 sensor->SetFillColorAlpha(kGreen, 0.4);
1340 motherVolume->AddNode(sensor, sensor_count++,
new TGeoTranslation(active_x_shift + x_offset,
y + y_offset, mZ + z_offset + epoxy_thickness + kapton_thickness / 2));
1342 if (r_squared < R_material_threshold * R_material_threshold) {
1345 sensor = geoManager->MakeBox(alu_name.c_str(),
AluminumMed, sensor_width / 2, sensor_height / 2, copper_thickness / 2);
1346 sensor->SetLineColor(kBlack);
1347 sensor->SetFillColorAlpha(kBlack, 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 + copper_thickness / 2));
1352 sensor = geoManager->MakeBox(copper_name.c_str(),
copperMed, sensor_width / 2, sensor_height / 2, copper_thickness / 2);
1353 sensor->SetLineColor(kBlack);
1354 sensor->SetFillColorAlpha(kBlack, 0.4);
1355 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(glue_up_name.c_str(),
epoxyMed, sensor_width / 2, sensor_height / 2, epoxy_thickness / 2);
1361 sensor->SetLineColor(kBlue);
1362 sensor->SetFillColorAlpha(kBlue, 1.0);
1363 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));
1365 if (sensor_width == 2.5) {
1368 sensor = geoManager->MakeBox(sensor_name.c_str(),
siliconMed, active_width / 2, active_height / 2, silicon_thickness / 2);
1369 sensor->SetLineColor(SiColor);
1370 sensor->SetFillColorAlpha(SiColor, 0.4);
1371 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));
1374 sensor = geoManager->MakeBox(inactive_name.c_str(),
siliconMed, (sensor_width - active_width) / 2, sensor_height / 2, silicon_thickness / 2);
1375 sensor->SetLineColor(kRed);
1376 sensor->SetFillColorAlpha(kRed, 1.0);
1377 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));
1382 sensor = geoManager->MakeBox(sensor_name.c_str(),
siliconMed, active_width / 2, sensor_height / 2, silicon_thickness / 2);
1383 sensor->SetLineColor(SiColor);
1384 sensor->SetFillColorAlpha(SiColor, 0.4);
1385 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));
1389 sensor = geoManager->MakeBox(inactive_name_left.c_str(),
siliconMed, inactive_width / 2, sensor_height / 2, silicon_thickness / 2);
1390 sensor->SetLineColor(kRed);
1391 sensor->SetFillColorAlpha(kRed, 1.0);
1392 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));
1396 sensor = geoManager->MakeBox(inactive_name_right.c_str(),
siliconMed, inactive_width / 2, sensor_height / 2, silicon_thickness / 2);
1397 sensor->SetLineColor(kRed);
1398 sensor->SetFillColorAlpha(kRed, 1.0);
1399 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));
1409 LOG(
debug) <<
"FT3Module: done create_layout";
1412void 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)
1415 LOG(
debug) <<
"FT3Module: createModule - Layer " << layerNumber <<
", Direction " << direction <<
", Face " <<
face;
1416 create_layout(mZ, layerNumber, direction, Rin, Rout, overlap,
face, layout_type, motherVolume);
1417 LOG(
debug) <<
"FT3Module: done createModule";
1421 double Rin,
double Rout,
double z_offset_local,
1423 TGeoVolume* motherVolume)
1425 LOG(
debug) <<
"FT3Module: createModule_staveGeo - Layer " << layerNumber
1426 <<
" at z=" << mZ <<
", Direction " << direction;
1427 create_layout_staveGeo(mZ, layerNumber, direction, Rin, Rout,
1428 z_offset_local, staveConfig, motherVolume);
1429 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 TGeoMixture * kaptonMat
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 * 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"