Project
Loading...
Searching...
No Matches
FT3Module.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
14
16#include <TGeoManager.h>
17#include <TGeoMaterial.h>
18#include <TGeoMedium.h>
19#include <TGeoBBox.h>
20#include <TGeoMatrix.h>
21#include <Framework/Logger.h>
22#include <cmath>
23#include <iostream>
24#include <vector>
25#include <set>
26#include <algorithm>
27
28TGeoMaterial* FT3Module::siliconMat = nullptr;
29TGeoMedium* FT3Module::siliconMed = nullptr;
30
31TGeoMaterial* FT3Module::copperMat = nullptr;
32TGeoMedium* FT3Module::copperMed = nullptr;
33
34TGeoMaterial* FT3Module::kaptonMat = nullptr;
35TGeoMedium* FT3Module::kaptonMed = nullptr;
36
37TGeoMaterial* FT3Module::epoxyMat = nullptr;
38TGeoMedium* FT3Module::epoxyMed = nullptr;
39
40TGeoMaterial* FT3Module::AluminumMat = nullptr;
41TGeoMedium* FT3Module::AluminumMed = nullptr;
42
44{
45 LOG(debug) << "FT3Module: initialize_materials";
46 if (siliconMat) {
47 return;
48 }
49
50 TGeoManager* geoManager = gGeoManager;
51
52 auto* itsH = new TGeoElement("FT3_H", "Hydrogen", 1, 1.00794);
53 auto* itsC = new TGeoElement("FT3_C", "Carbon", 6, 12.0107);
54 auto* itsO = new TGeoElement("FT3_O", "Oxygen", 8, 15.994);
55
56 siliconMat = new TGeoMaterial("FT3_Silicon", 28.0855, 14, 2.33);
57 siliconMed = new TGeoMedium("FT3_Silicon", 1, siliconMat);
58
59 copperMat = new TGeoMaterial("FT3_Copper", 63.546, 29, 8.96);
60 copperMed = new TGeoMedium("FT3_Copper", 2, copperMat);
61
62 kaptonMat = new TGeoMaterial("FT3_Kapton", 13.84, 6.88, 1.346);
63 kaptonMed = new TGeoMedium("FT3_Kapton", 3, kaptonMat);
64
65 // Epoxy: C18 H19 O3
66 auto* itsEpoxy = new TGeoMixture("FT3_Epoxy", 3);
67 itsEpoxy->AddElement(itsC, 18);
68 itsEpoxy->AddElement(itsH, 19);
69 itsEpoxy->AddElement(itsO, 3);
70 itsEpoxy->SetDensity(2.186);
71
72 epoxyMed = new TGeoMedium("FT3_Epoxy", 4, itsEpoxy);
73 epoxyMat = epoxyMed->GetMaterial();
74
75 AluminumMat = new TGeoMaterial("Aluminum", 26.98, 13, 2.7);
76 AluminumMed = new TGeoMedium("Aluminum", 5, AluminumMat);
77 LOG(debug) << "FT3Module: done initialize_materials";
78}
79
80double calculate_y_circle(double x, double radius)
81{
82 return (x * x < radius * radius) ? std::sqrt(radius * radius - x * x) : 0;
83}
84
85void 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)
86{
87
88 LOG(debug) << "FT3Module: create_layout - Layer " << layerNumber << ", Direction " << direction << ", Face " << face;
89 TGeoManager* geoManager = gGeoManager;
90
92
93 // double sensor_width = 2.5;
94 // double sensor_height = 9.6;
95 // double active_width = 2.3;
96 // double active_height = 9.6;
97
98 double sensor_width = 5.0;
99 double sensor_height = 9.6;
100 double inactive_width = 0.2; // per side
101 double active_width = 4.6;
102 double active_height = 9.6;
103
104 double silicon_thickness = 0.01;
105 double copper_thickness = 0.006;
106 double kapton_thickness = 0.03;
107 double epoxy_thickness = 0.0012;
108
109 double carbonFiberThickness = 0.01;
110
111 double foamSpacingThickness = 1.0;
112
113 int dist_offset = 0;
114
115 double x_offset;
116 double y_offset;
117
118 double z_offset = (face == "front") ? -foamSpacingThickness / 2.0 - carbonFiberThickness : foamSpacingThickness / 2.0 + carbonFiberThickness;
119
120 // offset correction
121 if (sensor_height == 3.2 && sensor_width == 2.5) {
122 x_offset = 0.8;
123 y_offset = 1.5;
124 } else if (sensor_height == 19.2 && sensor_width == 5) {
125 x_offset = 0.7;
126 y_offset = 9;
127 } else {
128 x_offset = sensor_width / 2;
129 y_offset = sensor_height / 2;
130 }
131
132 double x_condition_min = 0;
133 double x_condition_max = 0;
134 double offset_Rin_lower = 0;
135 double offset_Rin_upper = 0;
136 bool adjust_bottom_y_pos = false;
137 bool adjust_bottom_y_neg = false;
138 double x_adjust_bottom_y_pos = 0;
139 double bottom_y_pos_value = 0;
140 double bottom_y_neg_value = 0;
141
142 double Rin_offset = (sensor_height == 19.2) ? 1 : 0;
143 double Rout_offset = (sensor_height == 19.2) ? 1 : 0;
144
145 if (Rin == 7 && sensor_height == 9.6 && sensor_width == 5) {
146 x_condition_min = -Rin - 2;
147 x_condition_max = Rin;
148 dist_offset = 2;
149 adjust_bottom_y_pos = true;
150 adjust_bottom_y_neg = true;
151 x_adjust_bottom_y_pos = 3.5;
152 bottom_y_pos_value = 3.5;
153 bottom_y_neg_value = -3.5;
154 } else if (Rin == 5 && sensor_height == 9.6 && sensor_width == 5) {
155 x_condition_min = -Rin - 6;
156 x_condition_max = Rin;
157 adjust_bottom_y_pos = true;
158 adjust_bottom_y_neg = true;
159 x_adjust_bottom_y_pos = 3.5;
160 bottom_y_pos_value = 3.5;
161 bottom_y_neg_value = -3.5;
162 } else if ((Rin == 5 || Rin == 7) && sensor_height == 19.2) {
163 x_condition_min = -Rin - 3;
164 x_condition_max = Rin - 0.2;
165 dist_offset = 2;
166 adjust_bottom_y_pos = false;
167 adjust_bottom_y_neg = false;
168 } else if (Rin == 5 && sensor_height == 3.2) {
169 x_condition_min = -(Rin + 2.6);
170 x_condition_max = Rin + 1.5;
171 adjust_bottom_y_pos = true;
172 adjust_bottom_y_neg = true;
173 x_adjust_bottom_y_pos = 3.5;
174 bottom_y_pos_value = 3.5;
175 bottom_y_neg_value = -3.5;
176 } else if (Rin == 7 && sensor_height == 3.2) {
177 x_condition_min = -Rin - 1;
178 x_condition_max = Rin - 0.2;
179 adjust_bottom_y_pos = true;
180 adjust_bottom_y_neg = true;
181 x_adjust_bottom_y_pos = 3.5;
182 bottom_y_pos_value = 3.5;
183 bottom_y_neg_value = -3.5;
184 } else if (Rin == 5 && sensor_height == 9.6 && sensor_width == 2.5) {
185 x_condition_min = -(Rin + 2.6);
186 x_condition_max = Rin;
187 adjust_bottom_y_pos = true;
188 adjust_bottom_y_neg = true;
189 x_adjust_bottom_y_pos = 3.5;
190 bottom_y_pos_value = 3.5;
191 bottom_y_neg_value = -3.5;
192 } else if (Rin == 7 && sensor_height == 9.6 && sensor_width == 2.5) {
193 x_condition_min = -Rin - 2.6;
194 x_condition_max = Rin + 1;
195 dist_offset = 2;
196 adjust_bottom_y_pos = true;
197 adjust_bottom_y_neg = true;
198 x_adjust_bottom_y_pos = 5.5;
199 bottom_y_pos_value = 3.5;
200 bottom_y_neg_value = -3.5;
201 } else if (Rin == 10 && sensor_height == 9.6 && sensor_width == 5.0) {
202 x_condition_min = -Rin - 4;
203 x_condition_max = Rin;
204 dist_offset = 2;
205 adjust_bottom_y_pos = false;
206 adjust_bottom_y_neg = false;
207 x_adjust_bottom_y_pos = 3.5;
208 bottom_y_pos_value = 3.5;
209 bottom_y_neg_value = -3.5;
210 } else if (Rin == 20 && sensor_height == 9.6 && sensor_width == 5.0) {
211 x_condition_min = -Rin - 4;
212 x_condition_max = Rin;
213 dist_offset = 2;
214 adjust_bottom_y_pos = false;
215 adjust_bottom_y_neg = false;
216 x_adjust_bottom_y_pos = 3.5;
217 bottom_y_pos_value = 3.5;
218 bottom_y_neg_value = -3.5;
219 } else {
220 LOG(warning) << "Different config - to determine offsets needed for " << "Rin = " << Rin << " ; sensor_height = " << sensor_height << " ; sensor_width = " << sensor_width << " layer " << layerNumber;
221 x_condition_min = -Rin - sensor_width;
222 x_condition_max = Rin;
223 adjust_bottom_y_pos = false;
224 adjust_bottom_y_neg = false;
225 }
226
227 offset_Rin_lower = Rin - Rin_offset;
228 offset_Rin_upper = Rout + Rout_offset;
229
230 std::set<std::pair<double, double>> placed_sensors;
231 int sensor_count = 0;
232
233 int placementCounter = 0;
234 bool justSkipped = false;
235
236 std::vector<double> X_positions;
237 std::vector<int> justSkipped1;
238
239 if (sensor_width == 2.5) {
240 // logic for placement - x positions with complete overlap
241 if (face == "front") {
242 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,
243 -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,
244 56.2, 58.7, 65.4};
245 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};
246 } else if (face == "back") {
247 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,
248 -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,
249 51.6, 54.1, 60.8, 63.3};
250 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};
251 }
252 } else {
253 if (Rin == 10 || Rin == 20) { // v3 paving, rough attempt
254 float overlap = 0.3;
255 // NB: these are left edges
256 float X_start = -2.0 - 13.5 * (sensor_width - overlap);
257 float X_start_pos = 2.0 - 0.5 * (sensor_width - overlap);
258 if (face == "back") {
259 X_start += (sensor_width - overlap);
260 X_start_pos += (sensor_width - overlap);
261 }
262 while (X_start < -2) {
263 X_positions.push_back(X_start);
264 justSkipped1.push_back(1);
265 X_start += 2 * (sensor_width - overlap);
266 }
267 while (X_start_pos < Rout + x_offset - sensor_width) {
268 X_positions.push_back(X_start_pos);
269 justSkipped1.push_back(1);
270 X_start_pos += 2 * (sensor_width - overlap);
271 }
272 } else {
273 // filling for sensors with 2x width, each row skipped
274 if (face == "front") {
275 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};
276 justSkipped1 = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
277 } else if (face == "back") {
278 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};
279 justSkipped1 = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
280 }
281 }
282 }
283
284 if (layout_type == "rectangular") {
285
286 double x_start = -Rout;
287 double x_end = Rout;
288
289 std::vector<double> x_positions;
290 for (double x = x_start; x <= x_end; x += sensor_width) {
291 x_positions.push_back(x);
292 }
293
294 int rowCounter = 0;
295 const int rowsToAlternate = 2;
296
297 for (size_t i = 0; i < X_positions.size(); ++i) {
298
299 double x = X_positions[i];
300 bool justSkippedValue = justSkipped1[i];
301
302 std::vector<double> y_positions_positive;
303 std::vector<double> y_positions_negative;
304
305 for (double y = -Rout - Rin_offset; y <= Rout + Rin_offset; y += sensor_height) {
306 std::vector<std::pair<double, double>> corners = {
307 {x, y},
308 {x + sensor_width, y},
309 {x, y + sensor_height},
310 {x + sensor_width, y + sensor_height}};
311
312 bool within_bounds = std::all_of(corners.begin(), corners.end(), [&](const std::pair<double, double>& corner) {
313 double cx = corner.first;
314 double cy = corner.second;
315 return (offset_Rin_lower <= std::sqrt(cx * cx + cy * cy) && std::sqrt(cx * cx + cy * cy) <= offset_Rin_upper);
316 });
317
318 if (within_bounds) {
319 if (y >= 0) {
320 y_positions_positive.push_back(y);
321 } else {
322 y_positions_negative.push_back(y);
323 }
324 }
325 }
326
327 // adjust y positions near inner circle for positive y
328 if (x_condition_min <= x && x <= x_condition_max && !y_positions_positive.empty()) {
329 double first_y_pos = y_positions_positive.front();
330 double last_y_pos = y_positions_positive.back() - sensor_height;
331 double top_y_pos = std::min(calculate_y_circle(x, Rout), calculate_y_circle(x + sensor_width, Rout));
332 double bottom_y_pos = std::max(calculate_y_circle(x, Rin), calculate_y_circle(x + sensor_width, Rin));
333 double top_distance_pos = top_y_pos - last_y_pos;
334
335 if (adjust_bottom_y_pos && x > x_adjust_bottom_y_pos) {
336 bottom_y_pos = bottom_y_pos_value;
337 }
338
339 double bottom_distance_pos = first_y_pos - bottom_y_pos;
340
341 if (std::abs(top_distance_pos + bottom_distance_pos) >= sensor_height) {
342 for (auto& y : y_positions_positive) {
343 y -= bottom_distance_pos - 0.2;
344 }
345 y_positions_positive.push_back(y_positions_positive.back() + sensor_height);
346 }
347 }
348
349 // adjust y positions near inner circle for negative y
350 if (x_condition_min <= x && x <= x_condition_max && !y_positions_negative.empty()) {
351 double first_y_neg = y_positions_negative.front();
352 double last_y_neg = y_positions_negative.back() + sensor_height;
353 double top_y_neg = -std::min(calculate_y_circle(x, Rout), calculate_y_circle(x + sensor_width, Rout));
354 double bottom_y_neg = -std::max(calculate_y_circle(x, Rin), calculate_y_circle(x + sensor_width, Rin));
355 double top_distance_neg = -(top_y_neg - first_y_neg);
356
357 if (adjust_bottom_y_neg && x > x_adjust_bottom_y_pos) {
358 bottom_y_neg = bottom_y_neg_value;
359 }
360
361 double bottom_distance_neg = -(last_y_neg - bottom_y_neg);
362
363 top_distance_neg = std::abs(top_distance_neg);
364 bottom_distance_neg = std::abs(bottom_distance_neg);
365 std::sort(y_positions_negative.begin(), y_positions_negative.end());
366
367 if (std::abs(top_distance_neg + bottom_distance_neg) >= sensor_height) {
368 if (sensor_height == 19.2) {
369 for (auto& y : y_positions_negative) {
370 y -= bottom_distance_neg;
371 }
372 } else {
373 for (auto& y : y_positions_negative) {
374 y += bottom_distance_neg - 0.2;
375 }
376 }
377 y_positions_negative.push_back(y_positions_negative.front() - sensor_height);
378 }
379 }
380
381 // adjust positions for the rest of the disk
382 if ((x < x_condition_min || x > x_condition_max) && !y_positions_negative.empty() && !y_positions_positive.empty()) {
383 double first_y_neg = y_positions_negative.front();
384 double last_y_pos = y_positions_positive.back() + sensor_height;
385 double top_y_pos = std::min(calculate_y_circle(x, Rout), calculate_y_circle(x + sensor_width, Rout));
386 double bottom_y_pos = -top_y_pos;
387
388 double top_distance_pos = std::abs(top_y_pos - last_y_pos);
389 double bottom_distance_pos = std::abs(first_y_neg - bottom_y_pos);
390
391 if (top_distance_pos + bottom_distance_pos >= sensor_height) {
392 for (auto& y : y_positions_positive) {
393 y += top_distance_pos - 0.2;
394 }
395 for (auto& y : y_positions_negative) {
396 y += top_distance_pos - 0.2;
397 }
398 double new_y = y_positions_negative.front() - sensor_height;
399
400 if (static_cast<int>(new_y) > static_cast<int>(bottom_y_pos)) {
401 y_positions_negative.push_back(new_y);
402 }
403 }
404
405 // Make symmetric adjustments
406 std::sort(y_positions_negative.begin(), y_positions_negative.end());
407 std::sort(y_positions_positive.begin(), y_positions_positive.end());
408
409 double first_y_pos = y_positions_negative.front();
410
411 last_y_pos = y_positions_positive.back() + sensor_height;
412
413 top_y_pos = std::min(calculate_y_circle(x, Rout), calculate_y_circle(x + sensor_width, Rout));
414 bottom_y_pos = -top_y_pos;
415 top_distance_pos = std::abs(top_y_pos - last_y_pos);
416 bottom_distance_pos = std::abs(first_y_pos - bottom_y_pos);
417
418 double Lb = (bottom_distance_pos + top_distance_pos) / 2;
419
420 if (top_distance_pos < Lb) {
421 double shift = Lb - top_distance_pos;
422 for (auto& y : y_positions_negative) {
423 y -= shift;
424 }
425 for (auto& y : y_positions_positive) {
426 y -= shift;
427 }
428 } else if (top_distance_pos > Lb) {
429 double shift = top_distance_pos - Lb;
430 for (auto& y : y_positions_negative) {
431 y += shift;
432 }
433 for (auto& y : y_positions_positive) {
434 y += shift;
435 }
436 }
437 }
438
439 std::vector<double> y_positions = y_positions_positive;
440 y_positions.insert(y_positions.end(), y_positions_negative.begin(), y_positions_negative.end());
441
442 for (double y : y_positions) {
443
444 int SiColor;
445 double R_material_threshold = 0;
446
447 if (placed_sensors.find({x, y}) == placed_sensors.end()) {
448 placed_sensors.insert({x, y});
449 TGeoVolume* sensor;
450
451 double inactive_width = (sensor_width - active_width) / 2;
452 double left_inactive_x_shift;
453 double right_inactive_x_shift;
454 double active_x_shift_sensor;
455
456 if (face == "front") {
457
458 double active_x_shift, inactive_x_shift;
459
460 if (justSkippedValue) {
461 active_x_shift = x + inactive_width / 2;
462 active_x_shift_sensor = active_x_shift + inactive_width;
463
464 inactive_x_shift = x - active_width / 2 + inactive_width / 2;
465 } else {
466 active_x_shift = x - inactive_width / 2;
467 active_x_shift_sensor = active_x_shift - inactive_width;
468
469 inactive_x_shift = x + active_width / 2 - inactive_width / 2;
470 }
471
472 double inactive_x_shift_left, inactive_x_shift_right;
473
474 if (sensor_width == 5.0) {
475
476 inactive_x_shift_left = x - sensor_width / 2 + inactive_width;
477 inactive_x_shift_right = x + sensor_width / 2;
478 }
479
480 std::vector<std::pair<double, double>> corners_shifted = {
481 {x, y},
482 {x + sensor_width, y},
483 {x, y + sensor_height},
484 {x + sensor_width, y + sensor_height}};
485
486 bool within_bounds = true;
487 for (const auto& corner : corners_shifted) {
488 double cx = corner.first;
489 double cy = corner.second;
490 double dist = std::sqrt(cx * cx + cy * cy);
491
492 if (Rin > dist || dist >= Rout) {
493 within_bounds = false;
494 break;
495 }
496 }
497
498 if (within_bounds) {
499
500 double r_squared = (x + x_offset) * (x + x_offset) + (y + y_offset) * (y + y_offset);
501
502 if (r_squared < R_material_threshold * R_material_threshold) {
503 silicon_thickness = 0.005;
504 copper_thickness = 0.00475;
505 kapton_thickness = 0.03;
506 epoxy_thickness = 0.0012;
507
508 SiColor = kOrange;
509 } else {
510 silicon_thickness = 0.01;
511 copper_thickness = 0.006;
512 kapton_thickness = 0.03;
513 epoxy_thickness = 0.0012;
514
515 SiColor = kGreen;
516 }
517
518 if (sensor_width == 2.5) {
519 // silicon
520 std::string sensor_name = "FT3Sensor_front_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
521 sensor = geoManager->MakeBox(sensor_name.c_str(), siliconMed, active_width / 2, active_height / 2, silicon_thickness / 2);
522 sensor->SetLineColor(SiColor);
523 sensor->SetFillColorAlpha(SiColor, 0.4);
524 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));
525
526 std::string inactive_name = "FT3inactive_front_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
527 sensor = geoManager->MakeBox(inactive_name.c_str(), siliconMed, (sensor_width - active_width) / 2, sensor_height / 2, silicon_thickness / 2);
528 sensor->SetLineColor(kRed);
529 sensor->SetFillColorAlpha(kRed, 1.0);
530 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));
531
532 } else {
533
534 std::string sensor_name = "FT3Sensor_front_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
535 sensor = geoManager->MakeBox(sensor_name.c_str(), siliconMed, active_width / 2, sensor_height / 2, silicon_thickness / 2);
536 sensor->SetLineColor(SiColor);
537 sensor->SetFillColorAlpha(SiColor, 0.4);
538 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));
539
540 std::string inactive_name_left = "FT3inactive_left_front_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
541 sensor = geoManager->MakeBox(inactive_name_left.c_str(), siliconMed, inactive_width / 2, sensor_height / 2, silicon_thickness / 2);
542 sensor->SetLineColor(kRed);
543 sensor->SetFillColorAlpha(kRed, 1.0);
544 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));
545
546 std::string inactive_name_right = "FT3inactive_right_front_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
547 sensor = geoManager->MakeBox(inactive_name_right.c_str(), siliconMed, inactive_width / 2, sensor_height / 2, silicon_thickness / 2);
548 sensor->SetLineColor(kRed);
549 sensor->SetFillColorAlpha(kRed, 1.0);
550 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));
551 }
552
553 // silicon-to-FPC epoxy glue
554 std::string glue_up_name = "FT3glue_up_front_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
555 sensor = geoManager->MakeBox(glue_up_name.c_str(), epoxyMed, sensor_width / 2, sensor_height / 2, epoxy_thickness / 2);
556 sensor->SetLineColor(kBlue);
557 sensor->SetFillColorAlpha(kBlue, 1.0);
558 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));
559
560 if (r_squared < R_material_threshold * R_material_threshold) {
561 std::string alu_name = "FT3aluminum_front_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
562 sensor = geoManager->MakeBox(alu_name.c_str(), AluminumMed, sensor_width / 2, sensor_height / 2, copper_thickness / 2);
563 sensor->SetLineColor(kBlack);
564 sensor->SetFillColorAlpha(kBlack, 0.4);
565 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));
566
567 } else {
568 std::string copper_name = "FT3copper_front_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
569 sensor = geoManager->MakeBox(copper_name.c_str(), copperMed, sensor_width / 2, sensor_height / 2, copper_thickness / 2);
570 sensor->SetLineColor(kBlack);
571 sensor->SetFillColorAlpha(kBlack, 0.4);
572 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));
573 }
574
575 // kapton
576 std::string fpc_name = "FT3fpc_front_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
577 sensor = geoManager->MakeBox(fpc_name.c_str(), kaptonMed, sensor_width / 2, sensor_height / 2, kapton_thickness / 2);
578 sensor->SetLineColor(kGreen);
579 sensor->SetFillColorAlpha(kGreen, 0.4);
580 motherVolume->AddNode(sensor, sensor_count++, new TGeoTranslation(active_x_shift + x_offset, y + y_offset, mZ + z_offset - epoxy_thickness - kapton_thickness / 2));
581
582 // FPC-to-support epoxy glue
583 std::string glue_down_name = "FT3glue_down_front_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
584 sensor = geoManager->MakeBox(glue_down_name.c_str(), epoxyMed, sensor_width / 2, sensor_height / 2, epoxy_thickness / 2);
585 sensor->SetLineColor(kBlue);
586 sensor->SetFillColorAlpha(kBlue, 1.0);
587 motherVolume->AddNode(sensor, sensor_count++, new TGeoTranslation(x_offset + active_x_shift, y + y_offset, mZ + z_offset - epoxy_thickness / 2));
588 }
589 } else {
590 double x_shifted = x;
591 double inactive_x_shift, active_x_shift;
592 double active_x_shift_sensor;
593
594 if (justSkippedValue) {
595 active_x_shift = x + inactive_width / 2;
596 active_x_shift_sensor = active_x_shift + inactive_width;
597
598 inactive_x_shift = x - active_width / 2 + inactive_width / 2;
599 } else {
600 active_x_shift = x - inactive_width / 2;
601 active_x_shift_sensor = active_x_shift - inactive_width;
602
603 inactive_x_shift = x + active_width / 2 - inactive_width / 2;
604 }
605
606 double inactive_x_shift_left, inactive_x_shift_right;
607
608 if (sensor_width == 5.0) {
609
610 inactive_x_shift_left = x - sensor_width / 2 + inactive_width;
611 inactive_x_shift_right = x + sensor_width / 2;
612 }
613
614 std::vector<std::pair<double, double>> corners_shifted = {
615 {x_shifted, y},
616 {x_shifted + sensor_width, y},
617 {x_shifted, y + sensor_height},
618 {x_shifted + sensor_width, y + sensor_height}};
619
620 bool within_bounds = true;
621 for (const auto& corner : corners_shifted) {
622 double cx = corner.first;
623 double cy = corner.second;
624 double dist = std::sqrt(cx * cx + cy * cy);
625
626 if (Rin > dist + dist_offset || dist >= Rout) {
627 within_bounds = false;
628 break;
629 }
630 }
631
632 if (within_bounds) {
633
634 double r_squared = (x + x_offset) * (x + x_offset) + (y + y_offset) * (y + y_offset);
635
636 if (r_squared < R_material_threshold * R_material_threshold) {
637 silicon_thickness = 0.005;
638 copper_thickness = 0.00475; // thinner -> + replaced by alu
639 kapton_thickness = 0.03;
640 epoxy_thickness = 0.0006;
641
642 SiColor = kOrange;
643 } else {
644 silicon_thickness = 0.01;
645 copper_thickness = 0.006;
646 kapton_thickness = 0.03;
647 epoxy_thickness = 0.0012;
648
649 SiColor = kGreen;
650 }
651
652 // FPC-to-support epoxy glue
653 std::string glue_down_name = "FT3glue_down_back_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
654 sensor = geoManager->MakeBox(glue_down_name.c_str(), epoxyMed, sensor_width / 2, sensor_height / 2, epoxy_thickness / 2);
655 sensor->SetLineColor(kBlue);
656 sensor->SetFillColorAlpha(kBlue, 1.0);
657 motherVolume->AddNode(sensor, sensor_count++, new TGeoTranslation(x_offset + active_x_shift, y + y_offset, mZ + z_offset + epoxy_thickness / 2));
658
659 // Kapton
660 std::string fpc_name = "FT3fpc_back_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
661 sensor = geoManager->MakeBox(fpc_name.c_str(), kaptonMed, sensor_width / 2, sensor_height / 2, kapton_thickness / 2);
662 sensor->SetLineColor(kGreen);
663 sensor->SetFillColorAlpha(kGreen, 0.4);
664 motherVolume->AddNode(sensor, sensor_count++, new TGeoTranslation(active_x_shift + x_offset, y + y_offset, mZ + z_offset + epoxy_thickness + kapton_thickness / 2));
665
666 if (r_squared < R_material_threshold * R_material_threshold) {
667 // replace copper with alu
668 std::string alu_name = "FT3aluminum_back_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
669 sensor = geoManager->MakeBox(alu_name.c_str(), AluminumMed, sensor_width / 2, sensor_height / 2, copper_thickness / 2);
670 sensor->SetLineColor(kBlack);
671 sensor->SetFillColorAlpha(kBlack, 0.4);
672 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));
673
674 } else {
675 std::string copper_name = "FT3copper_back_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
676 sensor = geoManager->MakeBox(copper_name.c_str(), copperMed, sensor_width / 2, sensor_height / 2, copper_thickness / 2);
677 sensor->SetLineColor(kBlack);
678 sensor->SetFillColorAlpha(kBlack, 0.4);
679 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));
680 }
681
682 // silicon-to-FPC epoxy glue
683 std::string glue_up_name = "FT3glue_up_back_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
684 sensor = geoManager->MakeBox(glue_up_name.c_str(), epoxyMed, sensor_width / 2, sensor_height / 2, epoxy_thickness / 2);
685 sensor->SetLineColor(kBlue);
686 sensor->SetFillColorAlpha(kBlue, 1.0);
687 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));
688
689 if (sensor_width == 2.5) {
690
691 std::string sensor_name = "FT3Sensor_back_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
692 sensor = geoManager->MakeBox(sensor_name.c_str(), siliconMed, active_width / 2, active_height / 2, silicon_thickness / 2);
693 sensor->SetLineColor(SiColor);
694 sensor->SetFillColorAlpha(SiColor, 0.4);
695 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));
696
697 std::string inactive_name = "FT3inactive_back_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
698 sensor = geoManager->MakeBox(inactive_name.c_str(), siliconMed, (sensor_width - active_width) / 2, sensor_height / 2, silicon_thickness / 2);
699 sensor->SetLineColor(kRed);
700 sensor->SetFillColorAlpha(kRed, 1.0);
701 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));
702
703 } else {
704 // active (4.6 cm centered)
705 std::string sensor_name = "FT3Sensor_back_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
706 sensor = geoManager->MakeBox(sensor_name.c_str(), siliconMed, active_width / 2, sensor_height / 2, silicon_thickness / 2);
707 sensor->SetLineColor(SiColor);
708 sensor->SetFillColorAlpha(SiColor, 0.4);
709 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));
710
711 // left inactive strip
712 std::string inactive_name_left = "FT3inactive_left_back_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
713 sensor = geoManager->MakeBox(inactive_name_left.c_str(), siliconMed, inactive_width / 2, sensor_height / 2, silicon_thickness / 2);
714 sensor->SetLineColor(kRed);
715 sensor->SetFillColorAlpha(kRed, 1.0);
716 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));
717
718 // right inactive strip
719 std::string inactive_name_right = "FT3inactive_right_back_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
720 sensor = geoManager->MakeBox(inactive_name_right.c_str(), siliconMed, inactive_width / 2, sensor_height / 2, silicon_thickness / 2);
721 sensor->SetLineColor(kRed);
722 sensor->SetFillColorAlpha(kRed, 1.0);
723 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));
724 }
725 }
726 }
727 }
728 }
729
730 rowCounter++;
731 }
732 }
733 LOG(debug) << "FT3Module: done create_layout";
734}
735
736void 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)
737{
738
739 LOG(debug) << "FT3Module: createModule - Layer " << layerNumber << ", Direction " << direction << ", Face " << face;
740 create_layout(mZ, layerNumber, direction, Rin, Rout, overlap, face, layout_type, motherVolume);
741 LOG(debug) << "FT3Module: done createModule";
742}
std::ostringstream debug
double calculate_y_circle(double x, double radius)
Definition FT3Module.cxx:80
Definition of the FT3Module class.
int32_t i
static TGeoMedium * epoxyMed
Definition FT3Module.h:33
static TGeoMaterial * epoxyMat
Definition FT3Module.h:32
static TGeoMedium * siliconMed
Definition FT3Module.h:27
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
Definition FT3Module.h:29
static TGeoMaterial * kaptonMat
Definition FT3Module.h:30
static TGeoMaterial * copperMat
Definition FT3Module.h:28
static TGeoMaterial * siliconMat
Definition FT3Module.h:26
static TGeoMedium * AluminumMed
Definition FT3Module.h:35
static TGeoMedium * kaptonMed
Definition FT3Module.h:31
static TGeoMaterial * AluminumMat
Definition FT3Module.h:34
static void initialize_materials()
Definition FT3Module.cxx:43
GLint GLenum GLint x
Definition glcorearb.h:403
GLenum GLuint GLint GLenum face
Definition glcorearb.h:3184
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"