@@ -73,6 +73,35 @@ inline const int staveIdxToID(int staveIdx, unsigned nStavesPerDisc)
7373 return staveIdx - nStavesOneSide + isRight;
7474}
7575
76+ /*
77+ * Stave x midpoints follow from their number and spacing: they are spread
78+ * symmetrically about x=0, so an even count leaves a gap on the axis rather
79+ * than putting a stave on it. Deriving them keeps the spacing and the
80+ * positions from drifting apart.
81+ */
82+ inline std::vector<double > makeStaveXMidpoints (unsigned nStaves, double spacing)
83+ {
84+ std::vector<double > midpoints (nStaves);
85+ for (unsigned i = 0 ; i < nStaves; i++) {
86+ midpoints[i] = (i - (nStaves - 1 ) / 2.0 ) * spacing;
87+ }
88+ return midpoints;
89+ }
90+
91+ /*
92+ * Staves alternate between the front and the back of the disc so that
93+ * neighbours can overlap in x without touching, staggered in z by
94+ * z_offsetStave. Starting at 0 puts the leftmost stave at the back.
95+ */
96+ inline std::vector<bool > makeStaveOnFront (unsigned nStaves)
97+ {
98+ std::vector<bool > staveOnFront (nStaves);
99+ for (unsigned i = 0 ; i < nStaves; i++) {
100+ staveOnFront[i] = i % 2 ;
101+ }
102+ return staveOnFront;
103+ }
104+
76105// material properties
77106const double siliconThickness = 0.01 ;
78107const double copperThickness = 0.006 ;
@@ -101,6 +130,22 @@ inline const double z_offsetStave(double x_midpoint_spacing)
101130 (2 - x_midpoint_spacing / (sensor2x1_width / 2 + staveSensorGap));
102131}
103132
133+ /*
134+ * One uninterrupted fill of 2xN modules along a stave.
135+ *
136+ * yStart is the y of the BOTTOM edge of the first module; modules follow
137+ * upwards, each separated from the previous one by stackGap. Nothing is
138+ * mirrored: the layout is symmetric about the y-axis (stave +-ID) but NOT
139+ * about the x-axis, so every fill states its own y explicitly.
140+ *
141+ * A stave that the beam pipe cuts in two therefore carries two fills, one
142+ * below the hole and one above it, each with its own yStart.
143+ */
144+ struct StaveFill {
145+ const double yStart;
146+ const std::vector<unsigned > stackHeights;
147+ };
148+
104149// Struct for stave position configuration (varies between ML/OT)
105150struct StaveConfig {
106151 const unsigned isML; // whether this config is for ML or OT
@@ -128,6 +173,13 @@ struct StaveConfig {
128173 // kSegmentedStave: staggering staves in z (see z_offsetStave)
129174 // accessed via stave index, NOT stave ID
130175 const std::vector<bool >& staveOnFront;
176+ /*
177+ * Tabulated module layout, used when FT3Base.useExactStavePlacement is set.
178+ * One entry per stave, indexed like x_midpoints (NOT by stave ID), holding
179+ * that stave's fills: one for a stave reaching across y=0, two for a stave
180+ * split by the beam pipe.
181+ */
182+ const std::vector<std::vector<StaveFill>>& exactStaveFills;
131183};
132184
133185namespace OT_StavePositions
@@ -142,20 +194,21 @@ const std::vector<double> y_lengths = {
142194 128.7 , 132.0 , 132.0 , 138.6 , 138.6 , 56.1 , 52.8 ,
143195 52.8 , 56.1 , 138.6 , 138.6 , 132.0 , 132.0 , 128.7 ,
144196 118.8 , 118.8 , 105.6 , 99.0 , 92.4 , 79.2 , 66.0 , 52.8 };
145- const std::vector<double > x_midpoints = {
146- -65.25 , -60.75 , -56.25 , -51.75 , -47.25 , -42.75 , -38.25 , // L
147- -33.75 , -29.25 , -24.75 , -20.25 , -15.75 , -11.25 , -6.75 , -2.25 , // L
148- 2.25 , 6.75 , 11.25 , 15.75 , 20.25 , 24.75 , 29.25 , 33.75 , // R
149- 38.25 , 42.75 , 47.25 , 51.75 , 56.25 , 60.75 , 65.25 // R
150- };
151- const double x_midpoint_spacing = 4.5 ; // assume constant for now
152- const double maxToleranceInner = 0 .; // default not allowed inwards
197+ const unsigned nStaves = 30 ; // y_lengths, staveOnFront and exactStaveFills follow this
198+ const double x_midpoint_spacing = 4.5 ;
199+ const std::vector<double > x_midpoints = makeStaveXMidpoints(nStaves, x_midpoint_spacing);
200+ const double maxToleranceInner = 9 .; // close but not directly at 10cm yet
153201const double maxToleranceOuter = 3.4 ; // leave 1mm for layer air encapsulation
154- const std::vector<bool > staveOnFront =
155- {
156- 1 , 0 , 1 , 0 , 1 , 0 , 1 , 0 , 1 , 0 , 1 , 0 , 1 , 0 , 1 , // L
157- 0 , 1 , 0 , 1 , 0 , 1 , 0 , 1 , 0 , 1 , 0 , 1 , 0 , 1 , 0 // R
158- };
202+ const std::vector<bool > staveOnFront = makeStaveOnFront(nStaves);
203+ /*
204+ * TODO: fill from the disk optimiser output. One entry per stave, in the same
205+ * order as x_midpoints, and nStaves entries in total before
206+ * useExactStavePlacement works. Each entry lists that stave's fills:
207+ *
208+ * {{{-52.80, {4, 4, 4, 3}}}}, // reaches across y=0
209+ * {{-63.84, {4, 4, 3}}, {8.34, {4, 4, 3}}}, // split by the beam pipe
210+ */
211+ const std::vector<std::vector<StaveFill>> exactStaveFills = {};
159212} // namespace OT_StavePositions
160213
161214namespace ML_StavePositions
@@ -171,18 +224,14 @@ const std::map<int, std::pair<double, bool>> staveID_to_y_midpoint = {
171224const std::vector<double > y_lengths = {
172225 30.5 , 44.5 , 53.6 , 60.0 , 64.6 , 29.5 , 25.8 , 25.0 ,
173226 25.0 , 25.8 , 29.5 , 64.6 , 60.0 , 53.6 , 44.5 , 30.5 };
174- const std::vector<double > x_midpoints = {
175- -33.75 , -29.25 , -24.75 , -20.25 , -15.75 , -11.25 , -6.75 , -2.25 , // L
176- 2.25 , 6.75 , 11.25 , 15.75 , 20.25 , 24.75 , 29.25 , 33.75 // R
177- };
227+ const unsigned nStaves = 16 ; // y_lengths, staveOnFront and exactStaveFills follow this
178228const double x_midpoint_spacing = 4.5 ;
229+ const std::vector<double > x_midpoints = makeStaveXMidpoints(nStaves, x_midpoint_spacing);
179230const double maxToleranceInner = 0 .; // default not allowed inwards
180231const double maxToleranceOuter = 3.4 ; // leave 1mm for layer air encapsulation
181- const std::vector<bool > staveOnFront =
182- {
183- 1 , 0 , 1 , 0 , 1 , 0 , 1 , 0 , // L
184- 1 , 0 , 1 , 0 , 1 , 0 , 1 , 0 // R
185- };
232+ const std::vector<bool > staveOnFront = makeStaveOnFront(nStaves);
233+ // TODO: fill from the disk optimiser output, see OT_StavePositions above.
234+ const std::vector<std::vector<StaveFill>> exactStaveFills = {};
186235} // namespace ML_StavePositions
187236
188237// Get stave configuration based on tracker type
@@ -197,7 +246,8 @@ inline StaveConfig getStaveConfig(bool isInnerDisk)
197246 ML_StavePositions::x_midpoint_spacing,
198247 ML_StavePositions::maxToleranceInner,
199248 ML_StavePositions::maxToleranceOuter,
200- ML_StavePositions::staveOnFront};
249+ ML_StavePositions::staveOnFront,
250+ ML_StavePositions::exactStaveFills};
201251 } else {
202252 return StaveConfig{
203253 false , // isML
@@ -207,7 +257,8 @@ inline StaveConfig getStaveConfig(bool isInnerDisk)
207257 OT_StavePositions::x_midpoint_spacing,
208258 OT_StavePositions::maxToleranceInner,
209259 OT_StavePositions::maxToleranceOuter,
210- OT_StavePositions::staveOnFront};
260+ OT_StavePositions::staveOnFront,
261+ OT_StavePositions::exactStaveFills};
211262 }
212263}
213264
0 commit comments