Skip to content

Commit 8f131f8

Browse files
committed
Make stave geometry available with middle layer disks as well. Currently use simple calculated values for stave placements, these are subject to change. Hence the existence of kSegmentedOTOnly
1 parent 5118265 commit 8f131f8

4 files changed

Lines changed: 191 additions & 104 deletions

File tree

Detectors/Upgrades/ALICE3/FT3/simulation/include/FT3Simulation/FT3Module.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ class FT3Module
5656

5757
void createModule_staveGeo(
5858
double mZ, int layerNumber, int direction, double Rin,
59-
double Rout, double z_offset_local, TGeoVolume* motherVolume);
59+
double Rout, double z_offset_local, const Constants::StaveConfig& staveConfig,
60+
TGeoVolume* motherVolume);
6061

6162
private:
6263
static void create_layout(
@@ -66,7 +67,8 @@ class FT3Module
6667

6768
void create_layout_staveGeo(
6869
double mZ, int layerNumber, int direction, double Rin,
69-
double Rout, double z_offset_local, TGeoVolume* motherVolume);
70+
double Rout, double z_offset_local, const Constants::StaveConfig& staveConfig,
71+
TGeoVolume* motherVolume);
7072

7173
// Helper functions
7274
void fill_stave(PosNegPositionTypes& y_positions, double Rin, double Rout,

Detectors/Upgrades/ALICE3/FT3/simulation/include/FT3Simulation/FT3ModuleConstants.h

Lines changed: 107 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -59,52 +59,11 @@ namespace o2::ft3::ModuleConstants
5959
return nSensorsPerStack * sensor2x1_height +
6060
(nSensorsPerStack - 1) * sensor2x1_gap;
6161
}
62-
/*
63-
* Constants for staves are written for both positive
64-
* and negative x even though they are just mirrored now,
65-
* because there might be design changes in the future
66-
* that require a non-mirrored layout, making it easier to
67-
* change here if so required, even though it looks uglier now.
68-
*
69-
* The second element in the mapping pair is whether the stave
70-
* with a certain ID should be mirrored around the x-axis.
71-
*/
72-
// map from Stave ID (1-indexed from other documents) to midpoint
73-
// Do NOT add any zero midpoints, this is taken off separately
74-
const std::map<int, std::pair<double, bool>> staveID_to_y_midpoint = {
75-
{-2, {39.0, true}},
76-
{-1, {41.4, true}},
77-
{1, {41.4, true}},
78-
{2, {39.0, true}}
79-
};
80-
// lengths of staves, their midpoint, and their face
81-
const std::vector<double> y_lengths = {
82-
52.8, 66.0, 79.2, 92.4, 99.0, 105.6, 118.8, 118.8,
83-
128.7, 132.0, 132.0, 138.6, 138.6, 56.1, 52.8,
84-
52.8, 56.1, 138.6, 138.6, 132.0, 132.0, 128.7,
85-
118.8, 118.8, 105.6, 99.0, 92.4, 79.2, 66.0, 52.8
86-
};
87-
const std::vector<double> x_midpoints = {
88-
-65.25, -60.75, -56.25, -51.75, -47.25, -42.75, -38.25, // L
89-
-33.75, -29.25, -24.75, -20.25, -15.75, -11.25, -6.75, -2.25, // L
90-
2.25, 6.75, 11.25, 15.75, 20.25, 24.75, 29.25, 33.75, // R
91-
38.25, 42.75, 47.25, 51.75, 56.25, 60.75, 65.25 // R
92-
};
93-
const double x_midpoint_spacing = 4.5; // assume constant for now
94-
// which side of the disc do we place the stave?
95-
// used for kSegmentedMarch26 for front/back face, and for
96-
// kSegmentedStave for staggering staves in z (see z_offsetStave)
97-
// accessed via stave index, NOT stave ID
98-
const std::vector<bool> staveOnFront =
99-
{
100-
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, // L
101-
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 // R
102-
};
10362

10463
// small helper function to get 1-indexed stave ID, counting from the middle outwards,
10564
// with negative IDs on the left and positive IDs on the right
106-
inline const int staveIdxToID(int staveIdx) {
107-
unsigned nStavesOneSide = y_lengths.size() / 2;
65+
inline const int staveIdxToID(int staveIdx, unsigned nStavesPerDisc) {
66+
unsigned nStavesOneSide = nStavesPerDisc / 2;
10867
bool isRight = staveIdx >= nStavesOneSide;
10968
return staveIdx - nStavesOneSide + isRight;
11069
}
@@ -132,15 +91,117 @@ namespace o2::ft3::ModuleConstants
13291
*/
13392
// If midpoint spacing becomes non constant, this becomes a function
13493
// TODO: add some tolerance to avoid overlaps?
135-
const double z_offsetStave =
136-
staveTriangleHeight * (2 - x_midpoint_spacing / ( sensor2x1_width / 2 + staveSensorGap ) );
94+
inline const double z_offsetStave(double x_midpoint_spacing) {
95+
return staveTriangleHeight *
96+
(2 - x_midpoint_spacing / ( sensor2x1_width / 2 + staveSensorGap ) );
97+
}
13798

13899
const int SiColor = kGreen;
139100
const int SiInactiveColor = kRed;
140101
const int glueColor = kBlue;
141102
const int CuColor = kOrange;
142103
const int kaptonColor = kYellow;
143104
const int carbonColor = kBlack;
144-
}
105+
106+
// Struct for stave position configuration (varies between IT/OT)
107+
struct StaveConfig {
108+
/*
109+
* Constants for staves are written for both positive
110+
* and negative x even though they are just mirrored now,
111+
* because there might be design changes in the future
112+
* that require a non-mirrored layout, making it easier to
113+
* change here if so required, even though it looks uglier now.
114+
*
115+
* The second element in the mapping pair is whether the stave
116+
* with a certain ID should be mirrored around the x-axis.
117+
*/
118+
// map from Stave ID (1-indexed from other documents) to midpoint
119+
// Do NOT add any zero midpoints, this is taken off separately
120+
const std::map<int, std::pair<double, bool>>& staveID_to_y_midpoint;
121+
// lengths of staves, their midpoint, and their face
122+
const std::vector<double>& y_lengths;
123+
const std::vector<double>& x_midpoints;
124+
double x_midpoint_spacing;
125+
// which side of the disc do we place the stave?
126+
// kSegmentedStave: staggering staves in z (see z_offsetStave)
127+
// accessed via stave index, NOT stave ID
128+
const std::vector<bool>& staveOnFront;
129+
};
130+
131+
namespace OT_StavePositions {
132+
const std::map<int, std::pair<double, bool>> staveID_to_y_midpoint = {
133+
{-2, {39.0, true}},
134+
{-1, {41.4, true}},
135+
{1, {41.4, true}},
136+
{2, {39.0, true}}
137+
};
138+
const std::vector<double> y_lengths = {
139+
52.8, 66.0, 79.2, 92.4, 99.0, 105.6, 118.8, 118.8,
140+
128.7, 132.0, 132.0, 138.6, 138.6, 56.1, 52.8,
141+
52.8, 56.1, 138.6, 138.6, 132.0, 132.0, 128.7,
142+
118.8, 118.8, 105.6, 99.0, 92.4, 79.2, 66.0, 52.8
143+
};
144+
const std::vector<double> x_midpoints = {
145+
-65.25, -60.75, -56.25, -51.75, -47.25, -42.75, -38.25, // L
146+
-33.75, -29.25, -24.75, -20.25, -15.75, -11.25, -6.75, -2.25, // L
147+
2.25, 6.75, 11.25, 15.75, 20.25, 24.75, 29.25, 33.75, // R
148+
38.25, 42.75, 47.25, 51.75, 56.25, 60.75, 65.25 // R
149+
};
150+
const double x_midpoint_spacing = 4.5; // assume constant for now
151+
const std::vector<bool> staveOnFront =
152+
{
153+
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, // L
154+
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 // R
155+
};
156+
} // namespace OT_StavePositions
157+
158+
namespace ML_StavePositions {
159+
// Use prelim numbers for now, these will change! TODO
160+
const std::map<int, std::pair<double, bool>> staveID_to_y_midpoint = {
161+
{-3, {19.1, true}},
162+
{-2, {21.8, true}},
163+
{-1, {22.5, true}},
164+
{1, {22.5, true}},
165+
{2, {21.8, true}},
166+
{3, {19.1, true}}
167+
};
168+
const std::vector<double> y_lengths = {
169+
30.5, 44.5, 53.6, 60.0, 64.6, 29.5, 25.8, 25.0,
170+
25.0, 25.8, 29.5, 64.6, 60.0, 53.6, 44.5, 30.5
171+
};
172+
const std::vector<double> x_midpoints = {
173+
-33.75, -29.25, -24.75, -20.25, -15.75, -11.25, -6.75, -2.25, // L
174+
2.25, 6.75, 11.25, 15.75, 20.25, 24.75, 29.25, 33.75 // R
175+
};
176+
const double x_midpoint_spacing = 4.5;
177+
const std::vector<bool> staveOnFront =
178+
{
179+
1, 0, 1, 0, 1, 0, 1, 0, // L
180+
0, 1, 0, 1, 0, 1, 0, 1 // R
181+
};
182+
} // namespace ML_StavePositions
183+
184+
// Get stave configuration based on tracker type
185+
inline StaveConfig getStaveConfig(bool isInnerDisk) {
186+
if (isInnerDisk) {
187+
return StaveConfig{
188+
ML_StavePositions::staveID_to_y_midpoint,
189+
ML_StavePositions::y_lengths,
190+
ML_StavePositions::x_midpoints,
191+
ML_StavePositions::x_midpoint_spacing,
192+
ML_StavePositions::staveOnFront
193+
};
194+
} else {
195+
return StaveConfig{
196+
OT_StavePositions::staveID_to_y_midpoint,
197+
OT_StavePositions::y_lengths,
198+
OT_StavePositions::x_midpoints,
199+
OT_StavePositions::x_midpoint_spacing,
200+
OT_StavePositions::staveOnFront
201+
};
202+
}
203+
}
204+
205+
} // namespace o2::ft3::ModuleConstants
145206

146207
#endif // FT3MODULECONSTANTS_H

Detectors/Upgrades/ALICE3/FT3/simulation/src/FT3Layer.cxx

Lines changed: 57 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ void FT3Layer::createLayer(TGeoVolume* motherVolume)
403403
LOG(info) << "Inserting " << layerVol->GetName() << " inside " << motherVolume->GetName();
404404
motherVolume->AddNode(layerVol, 1, FwdDiskCombiTrans);
405405
} else if (ft3Params.layoutFT3 == kSegmented ||
406-
ft3Params.layoutFT3 == kSegmentedStave) {
406+
(ft3Params.layoutFT3 == kSegmentedStaveOTOnly && mIsMiddleLayer)) {
407407
FT3Module module;
408408

409409
// layer structure
@@ -413,42 +413,64 @@ void FT3Layer::createLayer(TGeoVolume* motherVolume)
413413

414414
TGeoMedium* medAir = gGeoManager->GetMedium("FT3_AIR$");
415415
TGeoVolume* layerVol = nullptr;
416+
// Add a little additional room in radius
417+
TGeoTube* layer = new TGeoTube(mInnerRadius - 0.1, mOuterRadius + 0.1, 1.5);
418+
layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir);
419+
layerVol->SetLineColor(kYellow + 2);
420+
// createSeparationLayer_waterCooling(motherVolume, separationLayerName);
421+
createSeparationLayer(layerVol, separationLayerName);
422+
module.createModule(0, mLayerNumber, mDirection, mInnerRadius, mOuterRadius, 0., "front", "rectangular", layerVol);
423+
module.createModule(0, mLayerNumber, mDirection, mInnerRadius, mOuterRadius, 0., "back", "rectangular", layerVol);
424+
425+
// Finally put everything in the mother volume
426+
auto* FwdDiskRotation = new TGeoRotation("FwdDiskRotation", 0, 0, 180);
427+
// need to shift outwards always, so + forwards and - backwards
428+
auto* FwdDiskCombiTrans = new TGeoCombiTrans(0, 0, mZ + 0, FwdDiskRotation);
429+
430+
LOG(info) << "Inserting " << layerVol->GetName() << " inside " << motherVolume->GetName();
431+
motherVolume->AddNode(layerVol, 1, FwdDiskCombiTrans);
432+
} else if (ft3Params.layoutFT3 == kSegmentedStave ||
433+
ft3Params.layoutFT3 == kSegmentedStaveOTOnly) {
434+
FT3Module module;
435+
436+
// layer structure
437+
std::string frontLayerName = o2::ft3::GeometryTGeo::getFT3LayerPattern() + std::to_string(mDirection) + std::to_string(mLayerNumber) + "_Front";
438+
std::string backLayerName = o2::ft3::GeometryTGeo::getFT3LayerPattern() + std::to_string(mDirection) + std::to_string(mLayerNumber) + "_Back";
439+
std::string separationLayerName = "FT3SeparationLayer" + std::to_string(mDirection) + std::to_string(mLayerNumber);
440+
441+
TGeoMedium* medAir = gGeoManager->GetMedium("FT3_AIR$");
442+
TGeoVolume* layerVol = nullptr;
443+
444+
// set up stave config, differs between ML and OT disks
445+
const Constants::StaveConfig& staveConfig = Constants::getStaveConfig(mIsMiddleLayer);
446+
447+
// need a thicker air layer to encompass the staves (4.5cm high, 1.2cm offsets)
448+
// stave face is at z=0 (or +-z_offset_stave), meaning that volumes are at
449+
// ~-+1cm < z < ~+-6cm, the +- referring forward/backward discs
450+
double z_layer_thickness = // need to shift internally with this
451+
o2::ft3::ModuleConstants::staveTriangleHeight +
452+
o2::ft3::ModuleConstants::z_offsetStave(staveConfig.x_midpoint_spacing) +
453+
o2::ft3::ModuleConstants::siliconThickness +
454+
o2::ft3::ModuleConstants::copperThickness +
455+
o2::ft3::ModuleConstants::kaptonThickness +
456+
o2::ft3::ModuleConstants::epoxyThickness * 2 +
457+
0.5; // add some extra room to ensure all volumes are encapsulated
458+
416459
// shift stave volumes into layer volume, since nominal z_{stave face} = 0
417-
double z_local_offset = 0;
418-
if (ft3Params.layoutFT3 == kSegmented) {
419-
// Add a little additional room in radius
420-
TGeoTube* layer = new TGeoTube(mInnerRadius - 0.1, mOuterRadius + 0.1, 1.5);
421-
layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir);
422-
layerVol->SetLineColor(kYellow + 2);
423-
// createSeparationLayer_waterCooling(motherVolume, separationLayerName);
424-
createSeparationLayer(layerVol, separationLayerName);
425-
module.createModule(0, mLayerNumber, mDirection, mInnerRadius, mOuterRadius, 0., "front", "rectangular", layerVol);
426-
module.createModule(0, mLayerNumber, mDirection, mInnerRadius, mOuterRadius, 0., "back", "rectangular", layerVol);
427-
} else if (ft3Params.layoutFT3 == kSegmentedStave) {
428-
// need a thicker air layer to encompass the staves (4.5cm high, 1.2cm offsets)
429-
// stave face is at z=0 (or +-z_offset_stave), meaning that volumes are at
430-
// ~-+1cm < z < ~+-6cm, the +- referring forward/backward discs
431-
double z_layer_thickness = // need to shift internally with this
432-
o2::ft3::ModuleConstants::staveTriangleHeight +
433-
o2::ft3::ModuleConstants::z_offsetStave +
434-
o2::ft3::ModuleConstants::siliconThickness +
435-
o2::ft3::ModuleConstants::copperThickness +
436-
o2::ft3::ModuleConstants::kaptonThickness +
437-
o2::ft3::ModuleConstants::epoxyThickness * 2 +
438-
0.5; // add some extra room to ensure all volumes are encapsulated
439-
z_local_offset = z_layer_thickness / 2.0;
440-
TGeoTube* layer = new TGeoTube(mInnerRadius - 12, mOuterRadius + 5, z_layer_thickness / 2);
441-
layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir);
442-
if (ft3Params.drawReferenceCircles) {
443-
std::string referenceCirclesName = "ReferenceCircles_Dir" + std::to_string(mDirection)
444-
+ "_Layer" + std::to_string(mLayerNumber);
445-
createReferenceCircles(layerVol, referenceCirclesName); // for visualization purposes
446-
}
447-
// need the -0.5 added to local offset to ensure all sensor modules are inside the layer
448-
module.createModule_staveGeo(0., mLayerNumber, mDirection, mInnerRadius,
449-
mOuterRadius, z_local_offset, layerVol);
460+
double z_local_offset = z_layer_thickness / 2.0;
461+
TGeoTube* layer = new TGeoTube(mInnerRadius - 12, mOuterRadius + 5, z_layer_thickness / 2);
462+
layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir);
463+
464+
if (ft3Params.drawReferenceCircles) {
465+
std::string referenceCirclesName = "ReferenceCircles_Dir" + std::to_string(mDirection)
466+
+ "_Layer" + std::to_string(mLayerNumber);
467+
createReferenceCircles(layerVol, referenceCirclesName); // for visualization purposes
450468
}
451-
// Finally put everything in the mother volume
469+
470+
// need the -0.5 added to local offset to ensure all sensor modules are inside the layer
471+
module.createModule_staveGeo(0., mLayerNumber, mDirection, mInnerRadius,
472+
mOuterRadius, z_local_offset, staveConfig, layerVol);
473+
// Finally put everything in the mother volume
452474
auto* FwdDiskRotation = new TGeoRotation("FwdDiskRotation", 0, 0, 180);
453475
// need to shift outwards always, so + forwards and - backwards
454476
double z_offset_directional = mDirection ? z_local_offset : -z_local_offset;

0 commit comments

Comments
 (0)