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};
154 std::pair<double, double>& absAllowedYRange)
162 double max_sensor_y_abs = std::min(absAllowedYRange.second, y_ranges.first.second);
166 if (!y_positions.first.empty()) {
169 }
else if (absAllowedYRange.first > 0) {
171 y_top = std::max(absAllowedYRange.first, y_ranges.first.first);
174 y_top = y_ranges.first.first;
177 while ((y_top + sensorStackHeight) <= max_sensor_y_abs) {
178 y_positions.first.emplace_back(y_top, kSensorStack);
179 y_top += sensorAbsStackYShift;
185 if (!y_positions.second.empty()) {
189 }
else if (absAllowedYRange.first > 0) {
191 y_bottom = std::min(-absAllowedYRange.first, y_ranges.second.first);
194 y_bottom = y_ranges.second.first;
197 while ((y_bottom - sensorStackHeight) >= -max_sensor_y_abs) {
198 y_positions.second.emplace_back(y_bottom, kSensorStack);
199 y_bottom -= sensorAbsStackYShift;
229 std::array<double, 3> xv_inner, xv_outer, zv_inner, zv_outer;
233 zv_outer[0] = (direction == 1) ? -H
240 xv_outer[2] = -xv_outer[1];
244 xv_inner[0] = xv_outer[0];
246 zv_inner[0] = (direction == 1) ? zv_outer[0] + z_shift_inner
247 : zv_outer[0] - z_shift_inner;
249 zv_inner[1] = (direction == 1) ? zv_outer[1] - d
252 xv_inner[1] = xv_outer[1] - x_shift_abs;
254 zv_inner[2] = zv_inner[1];
255 xv_inner[2] = -xv_inner[1];
257 return {xv_outer, zv_outer, xv_inner, zv_inner};
264void FT3Module::addStaveVolume(
265 TGeoVolume* motherVolume, std::string volumeName,
int direction,
266 unsigned* volume_count,
double staveLength,
267 std::array<std::array<double, 3>, 4> staveTriangles,
268 std::pair<double, double>& absAllowedYRange,
269 double x_mid,
double y_mid,
double z_stave_shift_forward)
272 if (absAllowedYRange.first < 0 || absAllowedYRange.second < 0 ||
273 absAllowedYRange.first >= absAllowedYRange.second) {
274 LOG(error) <<
"Invalid allowed y range in addStaveVolume(): ("
275 << absAllowedYRange.first <<
", " << absAllowedYRange.second
276 <<
"). Both values must be non-negative and the first "
277 <<
"value must be less than the second value.";
281 double y_lower = y_mid - staveLength / 2;
282 double y_upper = y_mid + staveLength / 2;
283 bool splitStave =
false;
285 y_lower = std::max(y_lower, absAllowedYRange.first);
286 y_upper = std::min(y_upper, absAllowedYRange.second);
287 }
else if (y_upper < 0) {
288 y_lower = std::max(y_lower, -absAllowedYRange.second);
289 y_upper = std::min(y_upper, -absAllowedYRange.first);
292 if (absAllowedYRange.first > 0) {
295 y_lower = absAllowedYRange.first;
298 y_lower = std::max(y_lower, -absAllowedYRange.second);
300 y_upper = std::min(y_upper, absAllowedYRange.second);
302 double staveLengthToUse = y_upper - y_lower;
310 TGeoXtru* staveFull =
new TGeoXtru(2);
311 staveFull->SetName((volumeName +
"_Xtru_outer").c_str());
312 staveFull->DefinePolygon(3, staveTriangles[0].
data(), staveTriangles[1].
data());
313 staveFull->DefineSection(0, 0);
314 staveFull->DefineSection(1, staveLengthToUse);
316 TGeoXtru* staveInner =
new TGeoXtru(2);
317 staveInner->SetName((volumeName +
"_Xtru_inner").c_str());
318 staveInner->DefinePolygon(3, staveTriangles[2].
data(), staveTriangles[3].
data());
319 staveInner->DefineSection(0, 0);
320 staveInner->DefineSection(1, staveLengthToUse);
322 TGeoCompositeShape* staveShape =
new TGeoCompositeShape(
323 (volumeName +
"_shape").c_str(),
324 Form(
"%s - %s", staveFull->GetName(), staveInner->GetName()));
325 TGeoVolume* staveVolume =
new TGeoVolume(
326 (volumeName).c_str(),
332 TGeoRotation* rot =
new TGeoRotation();
346 double z_shift = (direction == 1) ? z_stave_shift_forward : -z_stave_shift_forward;
347 TGeoCombiTrans* combiTrans =
348 new TGeoCombiTrans(x_mid, y_lower, z_shift, rot);
349 motherVolume->AddNode(staveVolume,
356 TGeoCombiTrans* combiTransSplit =
357 new TGeoCombiTrans(x_mid, -y_upper, z_shift, rot);
358 motherVolume->AddNode(staveVolume,
370void FT3Module::addDetectorVolume(
371 TGeoVolume* motherVolume, std::string volumeName,
int color,
372 unsigned* volume_count,
double x_mid,
double y_mid,
double z_mid,
373 double x_half_length,
double y_half_length,
double z_half_length)
375 TGeoManager* geoManager = gGeoManager;
376 TGeoVolume* volume = geoManager->MakeBox(volumeName.c_str(),
siliconMed, x_half_length,
377 y_half_length, z_half_length);
378 volume->SetLineColor(
color);
379 volume->SetFillColorAlpha(
color, 0.4);
380 motherVolume->AddNode(
395void FT3Module::add2x1GlueVolume(
396 TGeoVolume* motherVolume,
int layerNumber,
int direction,
unsigned stave_idx,
397 unsigned* volume_count,
double x_mid,
double y_mid,
double z_mid,
398 std::string element_glued_to)
411void FT3Module::add2x1CopperVolume(
412 TGeoVolume* motherVolume,
int layerNumber,
int direction,
unsigned stave_idx,
413 unsigned* volume_count,
double x_mid,
double y_mid,
double z_mid)
426void FT3Module::add2x1KaptonVolume(
427 TGeoVolume* motherVolume,
int layerNumber,
int direction,
unsigned stave_idx,
428 unsigned* volume_count,
double x_mid,
double y_mid,
double z_mid)
455void FT3Module::addSingleSensorVolume(
456 TGeoVolume* motherVolume,
int layerNumber,
int direction,
unsigned stave_idx,
457 unsigned* volume_count,
double active_x_mid,
double y_mid,
double z_mid,
461 TGeoManager* geoManager = gGeoManager;
468 motherVolume->AddNode(
480 std::string sensor_inactive_name =
486 motherVolume->AddNode(
497void FT3Module::create_layout_staveGeo(
double mZ,
int layerNumber,
int direction,
498 double Rin,
double Rout,
double z_offset_local,
500 TGeoVolume* motherVolume)
502 LOG(
debug) <<
"FT3Module: create_layout_staveGeo - Layer "
503 << layerNumber <<
", Direction " << direction;
528 double totalSensorMaterialThickness =
531 double z_offset_to_carbon_face = z_offset_local - totalSensorMaterialThickness - 0.1;
532 double z_offset_to_glue_Ka =
534 double z_offset_to_kapton =
537 double z_offset_to_copper =
540 double z_offset_to_glue_Si =
543 double z_offset_to_silicon =
549 std::vector<PosNegPositionTypes> y_positionsPosNeg;
550 unsigned volume_count = 0;
554 for (
unsigned i_stave = 0; i_stave < staveConfig.
x_midpoints.size(); i_stave++) {
558 double y_midpoint = 0.;
559 bool mirrorStaveAroundX =
false;
561 double stave_half_length = staveConfig.
y_lengths[i_stave] / 2;
563 if (ft3Params.placeSensorInMiddleOfStave) {
572 -stave_half_length}};
584 y_midpoint = y_midpoint_it->second.first;
585 mirrorStaveAroundX = y_midpoint_it->second.second;
586 y_ranges.first = {y_midpoint - stave_half_length, y_midpoint + stave_half_length};
587 y_ranges.second = {-y_midpoint + stave_half_length, -y_midpoint - stave_half_length};
591 double tolerance_inner = -1000;
592 double tolerance_outer = -1000;
594 if (ft3Params.cutStavesOnNominalRadius_inner) {
595 tolerance_inner = 0.;
597 if (ft3Params.cutStavesOnNominalRadius_outer) {
598 tolerance_outer = 0.;
612 std::pair<double, double> absAllowedYRange =
621 absAllowedYRange.first += tolerance_inner;
622 absAllowedYRange.second -= tolerance_outer;
624 if (absAllowedYRange.first < 0) {
625 absAllowedYRange.first = 0;
627 if (absAllowedYRange.second <= 0) {
628 LOG(warning) <<
"For stave " << i_stave <<
" in layer " << layerNumber
629 <<
" with direction " << direction <<
": no space to place sensors after applying tolerances, skipping stave.";
635 double z_stave_shift_forward =
636 -z_offset_to_carbon_face + z_stave_shift_abs;
637 std::string stave_volume_name =
641 motherVolume, stave_volume_name, direction, &volume_count,
642 staveConfig.
y_lengths[i_stave], staveTriangles, absAllowedYRange,
643 staveConfig.
x_midpoints[i_stave], y_midpoint, z_stave_shift_forward);
645 if (mirrorStaveAroundX) {
647 motherVolume, stave_volume_name +
"_mirrored", direction, &volume_count,
648 staveConfig.
y_lengths[i_stave], staveTriangles, absAllowedYRange,
649 staveConfig.
x_midpoints[i_stave], -y_midpoint, z_stave_shift_forward);
654 fill_stave(y_positionsPosNeg.back(), Rin, Rout, x_left,
661 for (
unsigned i_stave = 0; i_stave < staveConfig.
x_midpoints.size(); i_stave++) {
674 if (direction == 1) {
679 int z_offset_multiplier = (direction == 1) ? -1 : 1;
682 double z_stave_shift = 0;
689 for (
int y_sign = -1; y_sign < 2; y_sign += 2) {
691 const auto& positions = (y_sign == 1) ? y_positionsPosNeg[i_stave].
first
692 : y_positionsPosNeg[i_stave].second;
694 for (
unsigned i_y_pos = 0; i_y_pos < positions.size(); i_y_pos++) {
696 for (
unsigned i_sens = 0; i_sens < positions[i_y_pos].second; i_sens++) {
700 double z_mid = z_offset_to_silicon * z_offset_multiplier + z_stave_shift;
701 addSingleSensorVolume(
702 motherVolume, layerNumber, direction, i_stave, &volume_count,
705 addSingleSensorVolume(
706 motherVolume, layerNumber, direction, i_stave, &volume_count,
709 z_mid = z_offset_to_glue_Si * z_offset_multiplier + z_stave_shift;
711 motherVolume, layerNumber, direction, i_stave, &volume_count,
712 x_mid, y_mid, z_mid,
"SiCu");
714 z_mid = z_offset_to_copper * z_offset_multiplier + z_stave_shift;
716 motherVolume, layerNumber, direction, i_stave, &volume_count,
717 x_mid, y_mid, z_mid);
719 z_mid = z_offset_to_kapton * z_offset_multiplier + z_stave_shift;
721 motherVolume, layerNumber, direction, i_stave, &volume_count,
722 x_mid, y_mid, z_mid);
724 z_mid = z_offset_to_glue_Ka * z_offset_multiplier + z_stave_shift;
726 motherVolume, layerNumber, direction, i_stave, &volume_count,
727 x_mid, y_mid, z_mid,
"CarbonKapton");
736void 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)
739 LOG(
debug) <<
"FT3Module: create_layout - Layer " << layerNumber <<
", Direction " << direction <<
", Face " <<
face;
740 TGeoManager* geoManager = gGeoManager;
749 double sensor_width = 5.0;
750 double sensor_height = 9.6;
755 double silicon_thickness = 0.01;
756 double copper_thickness = 0.006;
757 double kapton_thickness = 0.03;
758 double epoxy_thickness = 0.0012;
760 double carbonFiberThickness = 0.01;
762 double foamSpacingThickness = 1.0;
769 double z_offset = (
face ==
"front") ? -foamSpacingThickness / 2.0 - carbonFiberThickness : foamSpacingThickness / 2.0 + carbonFiberThickness;
772 if (sensor_height == 3.2 && sensor_width == 2.5) {
775 }
else if (sensor_height == 19.2 && sensor_width == 5) {
779 x_offset = sensor_width / 2;
780 y_offset = sensor_height / 2;
783 double x_condition_min = 0;
784 double x_condition_max = 0;
785 double offset_Rin_lower = 0;
786 double offset_Rin_upper = 0;
787 bool adjust_bottom_y_pos =
false;
788 bool adjust_bottom_y_neg =
false;
789 double x_adjust_bottom_y_pos = 0;
790 double bottom_y_pos_value = 0;
791 double bottom_y_neg_value = 0;
793 double Rin_offset = (sensor_height == 19.2) ? 1 : 0;
794 double Rout_offset = (sensor_height == 19.2) ? 1 : 0;
796 if (Rin == 7 && sensor_height == 9.6 && sensor_width == 5) {
797 x_condition_min = -Rin - 2;
798 x_condition_max = Rin;
800 adjust_bottom_y_pos =
true;
801 adjust_bottom_y_neg =
true;
802 x_adjust_bottom_y_pos = 3.5;
803 bottom_y_pos_value = 3.5;
804 bottom_y_neg_value = -3.5;
805 }
else if (Rin == 5 && sensor_height == 9.6 && sensor_width == 5) {
806 x_condition_min = -Rin - 6;
807 x_condition_max = Rin;
808 adjust_bottom_y_pos =
true;
809 adjust_bottom_y_neg =
true;
810 x_adjust_bottom_y_pos = 3.5;
811 bottom_y_pos_value = 3.5;
812 bottom_y_neg_value = -3.5;
813 }
else if ((Rin == 5 || Rin == 7) && sensor_height == 19.2) {
814 x_condition_min = -Rin - 3;
815 x_condition_max = Rin - 0.2;
817 adjust_bottom_y_pos =
false;
818 adjust_bottom_y_neg =
false;
819 }
else if (Rin == 5 && sensor_height == 3.2) {
820 x_condition_min = -(Rin + 2.6);
821 x_condition_max = Rin + 1.5;
822 adjust_bottom_y_pos =
true;
823 adjust_bottom_y_neg =
true;
824 x_adjust_bottom_y_pos = 3.5;
825 bottom_y_pos_value = 3.5;
826 bottom_y_neg_value = -3.5;
827 }
else if (Rin == 7 && sensor_height == 3.2) {
828 x_condition_min = -Rin - 1;
829 x_condition_max = Rin - 0.2;
830 adjust_bottom_y_pos =
true;
831 adjust_bottom_y_neg =
true;
832 x_adjust_bottom_y_pos = 3.5;
833 bottom_y_pos_value = 3.5;
834 bottom_y_neg_value = -3.5;
835 }
else if (Rin == 5 && sensor_height == 9.6 && sensor_width == 2.5) {
836 x_condition_min = -(Rin + 2.6);
837 x_condition_max = Rin;
838 adjust_bottom_y_pos =
true;
839 adjust_bottom_y_neg =
true;
840 x_adjust_bottom_y_pos = 3.5;
841 bottom_y_pos_value = 3.5;
842 bottom_y_neg_value = -3.5;
843 }
else if (Rin == 7 && sensor_height == 9.6 && sensor_width == 2.5) {
844 x_condition_min = -Rin - 2.6;
845 x_condition_max = Rin + 1;
847 adjust_bottom_y_pos =
true;
848 adjust_bottom_y_neg =
true;
849 x_adjust_bottom_y_pos = 5.5;
850 bottom_y_pos_value = 3.5;
851 bottom_y_neg_value = -3.5;
852 }
else if (Rin == 10 && sensor_height == 9.6 && sensor_width == 5.0) {
853 x_condition_min = -Rin - 4;
854 x_condition_max = Rin;
856 adjust_bottom_y_pos =
false;
857 adjust_bottom_y_neg =
false;
858 x_adjust_bottom_y_pos = 3.5;
859 bottom_y_pos_value = 3.5;
860 bottom_y_neg_value = -3.5;
861 }
else if (Rin == 20 && sensor_height == 9.6 && sensor_width == 5.0) {
862 x_condition_min = -Rin - 4;
863 x_condition_max = Rin;
865 adjust_bottom_y_pos =
false;
866 adjust_bottom_y_neg =
false;
867 x_adjust_bottom_y_pos = 3.5;
868 bottom_y_pos_value = 3.5;
869 bottom_y_neg_value = -3.5;
871 LOG(warning) <<
"Different config - to determine offsets needed for " <<
"Rin = " << Rin <<
" ; sensor_height = " << sensor_height <<
" ; sensor_width = " << sensor_width <<
" layer " << layerNumber;
872 x_condition_min = -Rin - sensor_width;
873 x_condition_max = Rin;
874 adjust_bottom_y_pos =
false;
875 adjust_bottom_y_neg =
false;
878 offset_Rin_lower = Rin - Rin_offset;
879 offset_Rin_upper = Rout + Rout_offset;
881 std::set<std::pair<double, double>> placed_sensors;
882 int sensor_count = 0;
884 int placementCounter = 0;
885 bool justSkipped =
false;
887 std::vector<double> X_positions;
888 std::vector<int> justSkipped1;
890 if (sensor_width == 2.5) {
892 if (
face ==
"front") {
893 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,
894 -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,
896 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};
897 }
else if (
face ==
"back") {
898 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,
899 -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,
900 51.6, 54.1, 60.8, 63.3};
901 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};
904 if (Rin == 10 || Rin == 20) {
907 float X_start = -2.0 - 13.5 * (sensor_width - overlap);
908 float X_start_pos = 2.0 - 0.5 * (sensor_width - overlap);
909 if (
face ==
"back") {
910 X_start += (sensor_width - overlap);
911 X_start_pos += (sensor_width - overlap);
913 while (X_start < -2) {
914 X_positions.push_back(X_start);
915 justSkipped1.push_back(1);
916 X_start += 2 * (sensor_width - overlap);
918 while (X_start_pos < Rout + x_offset - sensor_width) {
919 X_positions.push_back(X_start_pos);
920 justSkipped1.push_back(1);
921 X_start_pos += 2 * (sensor_width - overlap);
925 if (
face ==
"front") {
926 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};
927 justSkipped1 = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
928 }
else if (
face ==
"back") {
929 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};
930 justSkipped1 = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
935 if (layout_type ==
"rectangular") {
937 double x_start = -Rout;
940 std::vector<double> x_positions;
941 for (
double x = x_start;
x <= x_end;
x += sensor_width) {
942 x_positions.push_back(
x);
946 const int rowsToAlternate = 2;
948 for (
size_t i = 0;
i < X_positions.size(); ++
i) {
950 double x = X_positions[
i];
951 bool justSkippedValue = justSkipped1[
i];
953 std::vector<double> y_positions_positive;
954 std::vector<double> y_positions_negative;
956 for (
double y = -Rout - Rin_offset;
y <= Rout + Rin_offset;
y += sensor_height) {
957 std::vector<std::pair<double, double>> corners = {
959 {
x + sensor_width,
y},
960 {
x,
y + sensor_height},
961 {
x + sensor_width,
y + sensor_height}};
963 bool within_bounds = std::all_of(corners.begin(), corners.end(), [&](
const std::pair<double, double>& corner) {
964 double cx = corner.first;
965 double cy = corner.second;
966 return (offset_Rin_lower <= std::sqrt(cx * cx + cy * cy) && std::sqrt(cx * cx + cy * cy) <= offset_Rin_upper);
971 y_positions_positive.push_back(
y);
973 y_positions_negative.push_back(
y);
979 if (x_condition_min <=
x &&
x <= x_condition_max && !y_positions_positive.empty()) {
980 double first_y_pos = y_positions_positive.front();
981 double last_y_pos = y_positions_positive.back() - sensor_height;
984 double top_distance_pos = top_y_pos - last_y_pos;
986 if (adjust_bottom_y_pos &&
x > x_adjust_bottom_y_pos) {
987 bottom_y_pos = bottom_y_pos_value;
990 double bottom_distance_pos = first_y_pos - bottom_y_pos;
992 if (std::abs(top_distance_pos + bottom_distance_pos) >= sensor_height) {
993 for (
auto&
y : y_positions_positive) {
994 y -= bottom_distance_pos - 0.2;
996 y_positions_positive.push_back(y_positions_positive.back() + sensor_height);
1001 if (x_condition_min <=
x &&
x <= x_condition_max && !y_positions_negative.empty()) {
1002 double first_y_neg = y_positions_negative.front();
1003 double last_y_neg = y_positions_negative.back() + sensor_height;
1006 double top_distance_neg = -(top_y_neg - first_y_neg);
1008 if (adjust_bottom_y_neg &&
x > x_adjust_bottom_y_pos) {
1009 bottom_y_neg = bottom_y_neg_value;
1012 double bottom_distance_neg = -(last_y_neg - bottom_y_neg);
1014 top_distance_neg = std::abs(top_distance_neg);
1015 bottom_distance_neg = std::abs(bottom_distance_neg);
1016 std::sort(y_positions_negative.begin(), y_positions_negative.end());
1018 if (std::abs(top_distance_neg + bottom_distance_neg) >= sensor_height) {
1019 if (sensor_height == 19.2) {
1020 for (
auto&
y : y_positions_negative) {
1021 y -= bottom_distance_neg;
1024 for (
auto&
y : y_positions_negative) {
1025 y += bottom_distance_neg - 0.2;
1028 y_positions_negative.push_back(y_positions_negative.front() - sensor_height);
1033 if ((x < x_condition_min || x > x_condition_max) && !y_positions_negative.empty() && !y_positions_positive.empty()) {
1034 double first_y_neg = y_positions_negative.front();
1035 double last_y_pos = y_positions_positive.back() + sensor_height;
1037 double bottom_y_pos = -top_y_pos;
1039 double top_distance_pos = std::abs(top_y_pos - last_y_pos);
1040 double bottom_distance_pos = std::abs(first_y_neg - bottom_y_pos);
1042 if (top_distance_pos + bottom_distance_pos >= sensor_height) {
1043 for (
auto&
y : y_positions_positive) {
1044 y += top_distance_pos - 0.2;
1046 for (
auto&
y : y_positions_negative) {
1047 y += top_distance_pos - 0.2;
1049 double new_y = y_positions_negative.front() - sensor_height;
1051 if (
static_cast<int>(new_y) >
static_cast<int>(bottom_y_pos)) {
1052 y_positions_negative.push_back(new_y);
1057 std::sort(y_positions_negative.begin(), y_positions_negative.end());
1058 std::sort(y_positions_positive.begin(), y_positions_positive.end());
1060 double first_y_pos = y_positions_negative.front();
1062 last_y_pos = y_positions_positive.back() + sensor_height;
1065 bottom_y_pos = -top_y_pos;
1066 top_distance_pos = std::abs(top_y_pos - last_y_pos);
1067 bottom_distance_pos = std::abs(first_y_pos - bottom_y_pos);
1069 double Lb = (bottom_distance_pos + top_distance_pos) / 2;
1071 if (top_distance_pos < Lb) {
1072 double shift = Lb - top_distance_pos;
1073 for (
auto&
y : y_positions_negative) {
1076 for (
auto&
y : y_positions_positive) {
1079 }
else if (top_distance_pos > Lb) {
1080 double shift = top_distance_pos - Lb;
1081 for (
auto&
y : y_positions_negative) {
1084 for (
auto&
y : y_positions_positive) {
1090 std::vector<double> y_positions = y_positions_positive;
1091 y_positions.insert(y_positions.end(), y_positions_negative.begin(), y_positions_negative.end());
1093 for (
double y : y_positions) {
1096 double R_material_threshold = 0;
1098 if (placed_sensors.find({x, y}) == placed_sensors.end()) {
1099 placed_sensors.insert({
x,
y});
1103 double left_inactive_x_shift;
1104 double right_inactive_x_shift;
1105 double active_x_shift_sensor;
1107 if (
face ==
"front") {
1109 double active_x_shift, inactive_x_shift;
1111 if (justSkippedValue) {
1123 double inactive_x_shift_left, inactive_x_shift_right;
1125 if (sensor_width == 5.0) {
1128 inactive_x_shift_right =
x + sensor_width / 2;
1131 std::vector<std::pair<double, double>> corners_shifted = {
1133 {
x + sensor_width,
y},
1134 {
x,
y + sensor_height},
1135 {
x + sensor_width,
y + sensor_height}};
1137 bool within_bounds =
true;
1138 for (
const auto& corner : corners_shifted) {
1139 double cx = corner.first;
1140 double cy = corner.second;
1141 double dist = std::sqrt(cx * cx + cy * cy);
1143 if (Rin > dist || dist >= Rout) {
1144 within_bounds =
false;
1149 if (within_bounds) {
1151 double r_squared = (
x + x_offset) * (
x + x_offset) + (
y + y_offset) * (
y + y_offset);
1153 if (r_squared < R_material_threshold * R_material_threshold) {
1154 silicon_thickness = 0.005;
1155 copper_thickness = 0.00475;
1156 kapton_thickness = 0.03;
1157 epoxy_thickness = 0.0012;
1161 silicon_thickness = 0.01;
1162 copper_thickness = 0.006;
1163 kapton_thickness = 0.03;
1164 epoxy_thickness = 0.0012;
1169 if (sensor_width == 2.5) {
1172 sensor = geoManager->MakeBox(sensor_name.c_str(),
siliconMed, active_width / 2, active_height / 2, silicon_thickness / 2);
1173 sensor->SetLineColor(SiColor);
1174 sensor->SetFillColorAlpha(SiColor, 0.4);
1175 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));
1178 sensor = geoManager->MakeBox(inactive_name.c_str(),
siliconMed, (sensor_width - active_width) / 2, sensor_height / 2, silicon_thickness / 2);
1179 sensor->SetLineColor(kRed);
1180 sensor->SetFillColorAlpha(kRed, 1.0);
1181 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));
1186 sensor = geoManager->MakeBox(sensor_name.c_str(),
siliconMed, active_width / 2, sensor_height / 2, silicon_thickness / 2);
1187 sensor->SetLineColor(SiColor);
1188 sensor->SetFillColorAlpha(SiColor, 0.4);
1189 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));
1192 sensor = geoManager->MakeBox(inactive_name_left.c_str(),
siliconMed, inactive_width / 2, sensor_height / 2, silicon_thickness / 2);
1193 sensor->SetLineColor(kRed);
1194 sensor->SetFillColorAlpha(kRed, 1.0);
1195 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));
1198 sensor = geoManager->MakeBox(inactive_name_right.c_str(),
siliconMed, inactive_width / 2, sensor_height / 2, silicon_thickness / 2);
1199 sensor->SetLineColor(kRed);
1200 sensor->SetFillColorAlpha(kRed, 1.0);
1201 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));
1206 sensor = geoManager->MakeBox(glue_up_name.c_str(),
epoxyMed, sensor_width / 2, sensor_height / 2, epoxy_thickness / 2);
1207 sensor->SetLineColor(kBlue);
1208 sensor->SetFillColorAlpha(kBlue, 1.0);
1209 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));
1211 if (r_squared < R_material_threshold * R_material_threshold) {
1213 sensor = geoManager->MakeBox(alu_name.c_str(),
AluminumMed, sensor_width / 2, sensor_height / 2, copper_thickness / 2);
1214 sensor->SetLineColor(kBlack);
1215 sensor->SetFillColorAlpha(kBlack, 0.4);
1216 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));
1220 sensor = geoManager->MakeBox(copper_name.c_str(),
copperMed, sensor_width / 2, sensor_height / 2, copper_thickness / 2);
1221 sensor->SetLineColor(kBlack);
1222 sensor->SetFillColorAlpha(kBlack, 0.4);
1223 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));
1228 sensor = geoManager->MakeBox(fpc_name.c_str(),
kaptonMed, sensor_width / 2, sensor_height / 2, kapton_thickness / 2);
1229 sensor->SetLineColor(kGreen);
1230 sensor->SetFillColorAlpha(kGreen, 0.4);
1231 motherVolume->AddNode(sensor, sensor_count++,
new TGeoTranslation(active_x_shift + x_offset,
y + y_offset, mZ + z_offset - epoxy_thickness - kapton_thickness / 2));
1235 sensor = geoManager->MakeBox(glue_down_name.c_str(),
epoxyMed, sensor_width / 2, sensor_height / 2, epoxy_thickness / 2);
1236 sensor->SetLineColor(kBlue);
1237 sensor->SetFillColorAlpha(kBlue, 1.0);
1238 motherVolume->AddNode(sensor, sensor_count++,
new TGeoTranslation(x_offset + active_x_shift,
y + y_offset, mZ + z_offset - epoxy_thickness / 2));
1241 double x_shifted =
x;
1242 double inactive_x_shift, active_x_shift;
1243 double active_x_shift_sensor;
1245 if (justSkippedValue) {
1257 double inactive_x_shift_left, inactive_x_shift_right;
1259 if (sensor_width == 5.0) {
1262 inactive_x_shift_right =
x + sensor_width / 2;
1265 std::vector<std::pair<double, double>> corners_shifted = {
1267 {x_shifted + sensor_width,
y},
1268 {x_shifted,
y + sensor_height},
1269 {x_shifted + sensor_width,
y + sensor_height}};
1271 bool within_bounds =
true;
1272 for (
const auto& corner : corners_shifted) {
1273 double cx = corner.first;
1274 double cy = corner.second;
1275 double dist = std::sqrt(cx * cx + cy * cy);
1277 if (Rin > dist + dist_offset || dist >= Rout) {
1278 within_bounds =
false;
1283 if (within_bounds) {
1285 double r_squared = (
x + x_offset) * (
x + x_offset) + (
y + y_offset) * (
y + y_offset);
1287 if (r_squared < R_material_threshold * R_material_threshold) {
1288 silicon_thickness = 0.005;
1289 copper_thickness = 0.00475;
1290 kapton_thickness = 0.03;
1291 epoxy_thickness = 0.0006;
1295 silicon_thickness = 0.01;
1296 copper_thickness = 0.006;
1297 kapton_thickness = 0.03;
1298 epoxy_thickness = 0.0012;
1305 sensor = geoManager->MakeBox(glue_down_name.c_str(),
epoxyMed, sensor_width / 2, sensor_height / 2, epoxy_thickness / 2);
1306 sensor->SetLineColor(kBlue);
1307 sensor->SetFillColorAlpha(kBlue, 1.0);
1308 motherVolume->AddNode(sensor, sensor_count++,
new TGeoTranslation(x_offset + active_x_shift,
y + y_offset, mZ + z_offset + epoxy_thickness / 2));
1312 sensor = geoManager->MakeBox(fpc_name.c_str(),
kaptonMed, sensor_width / 2, sensor_height / 2, kapton_thickness / 2);
1313 sensor->SetLineColor(kGreen);
1314 sensor->SetFillColorAlpha(kGreen, 0.4);
1315 motherVolume->AddNode(sensor, sensor_count++,
new TGeoTranslation(active_x_shift + x_offset,
y + y_offset, mZ + z_offset + epoxy_thickness + kapton_thickness / 2));
1317 if (r_squared < R_material_threshold * R_material_threshold) {
1320 sensor = geoManager->MakeBox(alu_name.c_str(),
AluminumMed, sensor_width / 2, sensor_height / 2, copper_thickness / 2);
1321 sensor->SetLineColor(kBlack);
1322 sensor->SetFillColorAlpha(kBlack, 0.4);
1323 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));
1327 sensor = geoManager->MakeBox(copper_name.c_str(),
copperMed, sensor_width / 2, sensor_height / 2, copper_thickness / 2);
1328 sensor->SetLineColor(kBlack);
1329 sensor->SetFillColorAlpha(kBlack, 0.4);
1330 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));
1335 sensor = geoManager->MakeBox(glue_up_name.c_str(),
epoxyMed, sensor_width / 2, sensor_height / 2, epoxy_thickness / 2);
1336 sensor->SetLineColor(kBlue);
1337 sensor->SetFillColorAlpha(kBlue, 1.0);
1338 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));
1340 if (sensor_width == 2.5) {
1343 sensor = geoManager->MakeBox(sensor_name.c_str(),
siliconMed, active_width / 2, active_height / 2, silicon_thickness / 2);
1344 sensor->SetLineColor(SiColor);
1345 sensor->SetFillColorAlpha(SiColor, 0.4);
1346 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));
1349 sensor = geoManager->MakeBox(inactive_name.c_str(),
siliconMed, (sensor_width - active_width) / 2, sensor_height / 2, silicon_thickness / 2);
1350 sensor->SetLineColor(kRed);
1351 sensor->SetFillColorAlpha(kRed, 1.0);
1352 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));
1357 sensor = geoManager->MakeBox(sensor_name.c_str(),
siliconMed, active_width / 2, sensor_height / 2, silicon_thickness / 2);
1358 sensor->SetLineColor(SiColor);
1359 sensor->SetFillColorAlpha(SiColor, 0.4);
1360 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));
1364 sensor = geoManager->MakeBox(inactive_name_left.c_str(),
siliconMed, inactive_width / 2, sensor_height / 2, silicon_thickness / 2);
1365 sensor->SetLineColor(kRed);
1366 sensor->SetFillColorAlpha(kRed, 1.0);
1367 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));
1371 sensor = geoManager->MakeBox(inactive_name_right.c_str(),
siliconMed, inactive_width / 2, sensor_height / 2, silicon_thickness / 2);
1372 sensor->SetLineColor(kRed);
1373 sensor->SetFillColorAlpha(kRed, 1.0);
1374 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));
1384 LOG(
debug) <<
"FT3Module: done create_layout";
1387void 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)
1390 LOG(
debug) <<
"FT3Module: createModule - Layer " << layerNumber <<
", Direction " << direction <<
", Face " <<
face;
1391 create_layout(mZ, layerNumber, direction, Rin, Rout, overlap,
face, layout_type, motherVolume);
1392 LOG(
debug) <<
"FT3Module: done createModule";
1396 double Rin,
double Rout,
double z_offset_local,
1398 TGeoVolume* motherVolume)
1400 LOG(
debug) <<
"FT3Module: createModule_staveGeo - Layer " << layerNumber
1401 <<
" at z=" << mZ <<
", Direction " << direction;
1402 create_layout_staveGeo(mZ, layerNumber, direction, Rin, Rout,
1403 z_offset_local, staveConfig, motherVolume);
1404 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 std::vector< double > & y_lengths
const std::map< int, std::pair< double, bool > > & staveID_to_y_midpoint
const std::vector< bool > & staveOnFront
double x_midpoint_spacing
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"