99// granted to it by virtue of its status as an Intergovernmental Organization
1010// or submit itself to any jurisdiction.
1111
12- // / \file SegmentationSuperAlpide .h
13- // / \brief Definition of the SegmentationSuperAlpide class
12+ // / \file SegmentationMosaix .h
13+ // / \brief Definition of the SegmentationMosaix class
1414// / \author felix.schlepper@cern.ch
1515
16- #ifndef ALICEO2_ITS3_SEGMENTATIONSUPERALPIDE_H_
17- #define ALICEO2_ITS3_SEGMENTATIONSUPERALPIDE_H_
16+ #ifndef ALICEO2_ITS3_SEGMENTATIONMOSAIX_H_
17+ #define ALICEO2_ITS3_SEGMENTATIONMOSAIX_H_
18+
19+ #include < type_traits>
1820
1921#include " MathUtils/Cartesian.h"
2022#include " ITS3Base/SpecsV2.h"
21- #include " Rtypes.h"
22-
23- #include < type_traits>
2423
2524namespace o2 ::its3
2625{
2726
2827// / Segmentation and response for pixels in ITS3 upgrade
29- class SegmentationSuperAlpide
28+ class SegmentationMosaix
3029{
3130 // This class defines the segmenation of the pixelArray in the tile. We define
3231 // two coordinate systems, one width x,z detector local coordianates (cm) and
3332 // the more natural row,col layout: Also all the transformation between these
3433 // two. The class provides the transformation from the tile to TGeo
3534 // coordinates.
35+ // In fact there exist three coordinate systems and one is transient.
36+ // 1. The curved coordinate system. The chip's local coordinate system is
37+ // defined with its center at the the mid-point of the tube.
38+ // 2. The flat coordinate system. This is the tube segment projected onto a flat
39+ // surface. In the projection we implicitly assume that the inner and outer
40+ // stretch does not depend on the radius.
41+ // Additionally, there is a difference between the flat geometrical center
42+ // and the phyiscal center defined by the metal layer.
43+ // 3. The detector coordinate system. Defined by the row and column segmentation
44+ // defined at the upper edge in the flat coord.
3645
3746 // row,col=0
3847 // |
@@ -53,25 +62,32 @@ class SegmentationSuperAlpide
5362 // | | |
5463 // x----------------------x
5564 public:
56- virtual ~SegmentationSuperAlpide () = default ;
57- SegmentationSuperAlpide (const SegmentationSuperAlpide&) = default ;
58- SegmentationSuperAlpide (SegmentationSuperAlpide&&) = delete ;
59- SegmentationSuperAlpide& operator =(const SegmentationSuperAlpide&) = delete ;
60- SegmentationSuperAlpide& operator =(SegmentationSuperAlpide&&) = delete ;
61- constexpr SegmentationSuperAlpide (int layer) : mLayer{layer} {}
62-
63- static constexpr int mNCols {constants::pixelarray::nCols};
64- static constexpr int mNRows {constants::pixelarray::nRows};
65- static constexpr int nPixels{mNCols * mNRows };
66- static constexpr float mLength {constants::pixelarray::length};
67- static constexpr float mWidth {constants::pixelarray::width};
68- static constexpr float mPitchCol {constants::pixelarray::length / static_cast <float >(mNCols )};
69- static constexpr float mPitchRow {constants::pixelarray::width / static_cast <float >(mNRows )};
70- static constexpr float mSensorLayerThickness {constants::thickness};
71- static constexpr float mSensorLayerThicknessEff {constants::effThickness};
72- static constexpr std::array<float , constants::nLayers> mRadii {constants::radii};
73-
74- // / Transformation from the curved surface to a flat surface
65+ constexpr SegmentationMosaix (int layer) : mRadius(static_cast <float >(constants::radiiMiddle[layer])) {}
66+ constexpr ~SegmentationMosaix () = default ;
67+ constexpr SegmentationMosaix (const SegmentationMosaix&) = default;
68+ constexpr SegmentationMosaix (SegmentationMosaix&&) = delete;
69+ constexpr SegmentationMosaix& operator =(const SegmentationMosaix&) = default ;
70+ constexpr SegmentationMosaix& operator =(SegmentationMosaix&&) = delete ;
71+
72+ static constexpr int NCols{constants::pixelarray::nCols};
73+ static constexpr int NRows{constants::pixelarray::nRows};
74+ static constexpr int NPixels{NCols * NRows};
75+ static constexpr float Length{constants::pixelarray::length};
76+ static constexpr float LengthH{Length / 2 .f };
77+ static constexpr float Width{constants::pixelarray::width};
78+ static constexpr float WidthH{Width / 2 .f };
79+ static constexpr float PitchCol{constants::pixelarray::pixels::mosaix::pitchZ};
80+ static constexpr float PitchRow{constants::pixelarray::pixels::mosaix::pitchX};
81+ static constexpr float SensorLayerThickness{constants::totalThickness};
82+ static constexpr float NominalYShift{constants::nominalYShift};
83+
84+ // / Transformation from the curved surface to a flat surface.
85+ // / Additionally a shift in the flat coordinates must be applied because
86+ // / the center of the TGeoShap when projected will be higher than the
87+ // / physical thickness of the chip (we add an additional hull to account for
88+ // / the copper metal interconnection which is in reality part of the chip but in our
89+ // / simulation the silicon and metal layer are separated). Thus we shift the projected center
90+ // / down by this difference to align the coordinate systems.
7591 // / \param xCurved Detector local curved coordinate x in cm with respect to
7692 // / the center of the sensitive volume.
7793 // / \param yCurved Detector local curved coordinate y in cm with respect to
@@ -80,18 +96,20 @@ class SegmentationSuperAlpide
8096 // / the center of the sensitive volume.
8197 // / \param yFlat Detector local flat coordinate y in cm with respect to
8298 // / the center of the sensitive volume.
83- void curvedToFlat (const float xCurved, const float yCurved, float & xFlat, float & yFlat) const noexcept
99+ constexpr void curvedToFlat (const float xCurved, const float yCurved, float & xFlat, float & yFlat) const noexcept
84100 {
85- // MUST align the flat surface with the curved surface with the original pixel array is on
101+ // MUST align the flat surface with the curved surface with the original pixel array is on and account for metal
102+ // stack
86103 float dist = std::hypot (xCurved, yCurved);
87- float phiReadout = constants::tile::readout::width / constants::radii[mLayer ];
88104 float phi = std::atan2 (yCurved, xCurved);
89- xFlat = mRadii [mLayer ] * (phi - phiReadout) - constants::pixelarray::width / 2 .;
90- yFlat = dist - mRadii [mLayer ];
105+ // the y position is in the silicon volume however we need the chip volume (silicon+metalstack)
106+ // this is accounted by a y shift
107+ xFlat = WidthH - mRadius * phi;
108+ yFlat = dist - mRadius + NominalYShift;
91109 }
92110
93111 // / Transformation from the flat surface to a curved surface
94- // / It works only if the detector is not rototraslated
112+ // / It works only if the detector is not rototraslated.
95113 // / \param xFlat Detector local flat coordinate x in cm with respect to
96114 // / the center of the sensitive volume.
97115 // / \param yFlat Detector local flat coordinate y in cm with respect to
@@ -100,13 +118,16 @@ class SegmentationSuperAlpide
100118 // / the center of the sensitive volume.
101119 // / \param yCurved Detector local curved coordinate y in cm with respect to
102120 // / the center of the sensitive volume.
103- void flatToCurved (float xFlat, float yFlat, float & xCurved, float & yCurved) const noexcept
121+ constexpr void flatToCurved (float xFlat, float yFlat, float & xCurved, float & yCurved) const noexcept
104122 {
105- // MUST align the flat surface with the curved surface with the original pixel array is on
106- float dist = yFlat + mRadii [mLayer ];
107- float phiReadout = constants::tile::readout::width / mRadii [mLayer ];
108- xCurved = dist * std::cos (phiReadout + (xFlat + constants::pixelarray::width / 2 .) / mRadii [mLayer ]);
109- yCurved = dist * std::sin (phiReadout + (xFlat + constants::pixelarray::width / 2 .) / mRadii [mLayer ]);
123+ // MUST align the flat surface with the curved surface with the original pixel array is on and account for metal
124+ // stack
125+ float dist = yFlat - NominalYShift + mRadius ;
126+ float phi = (WidthH - xFlat) / mRadius ;
127+ // the y position is in the chip volume however we need the silicon volume
128+ // this is accounted by a -y shift
129+ xCurved = dist * std::cos (phi);
130+ yCurved = dist * std::sin (phi);
110131 }
111132
112133 // / Transformation from Geant detector centered local coordinates (cm) to
@@ -120,7 +141,7 @@ class SegmentationSuperAlpide
120141 // / the center of the sensitive volume.
121142 // / \param int iRow Detector x cell coordinate.
122143 // / \param int iCol Detector z cell coordinate.
123- bool localToDetector (float const xRow, float const zCol, int & iRow, int & iCol) const noexcept
144+ constexpr bool localToDetector (float const xRow, float const zCol, int & iRow, int & iCol) const noexcept
124145 {
125146 localToDetectorUnchecked (xRow, zCol, iRow, iCol);
126147 if (!isValid (iRow, iCol)) {
@@ -131,11 +152,10 @@ class SegmentationSuperAlpide
131152 }
132153
133154 // Same as localToDetector w.o. checks.
134- void localToDetectorUnchecked (float const xRow, float const zCol, int & iRow, int & iCol) const noexcept
155+ constexpr void localToDetectorUnchecked (float const xRow, float const zCol, int & iRow, int & iCol) const noexcept
135156 {
136- namespace cp = constants::pixelarray;
137- iRow = std::floor ((cp::width / 2 . - xRow) / mPitchRow );
138- iCol = std::floor ((zCol + cp::length / 2 .) / mPitchCol );
157+ iRow = static_cast <int >(std::floor ((WidthH - xRow) / PitchRow));
158+ iCol = static_cast <int >(std::floor ((zCol + LengthH) / PitchCol));
139159 }
140160
141161 // / Transformation from Detector cell coordinates to Geant detector centered
@@ -148,60 +168,55 @@ class SegmentationSuperAlpide
148168 // / center of the sensitive volume.
149169 // / If iRow and or iCol is outside of the segmentation range a value of -0.5*Dx()
150170 // / or -0.5*Dz() is returned.
151- bool detectorToLocal ( int const iRow, int const iCol, float & xRow, float & zCol) const noexcept
152- {
153- if (!isValid (iRow, iCol )) {
171+ template < typename T>
172+ constexpr bool detectorToLocal (T const row, T const col, float & xRow, float & zCol) const noexcept {
173+ if (!isValid (row, col )) {
154174 return false ;
155175 }
156- detectorToLocalUnchecked (iRow, iCol , xRow, zCol);
176+ detectorToLocalUnchecked (row, col , xRow, zCol);
157177 return isValid (xRow, zCol);
158178 }
159179
160180 // Same as detectorToLocal w.o. checks.
161181 // We position ourself in the middle of the pixel.
162- void detectorToLocalUnchecked (int const iRow, int const iCol, float & xRow, float & zCol) const noexcept
163- {
164- namespace cp = constants::pixelarray;
165- xRow = -(iRow + 0.5 ) * mPitchRow + cp::width / 2 .;
166- zCol = (iCol + 0.5 ) * mPitchCol - cp::length / 2 .;
182+ template <typename T>
183+ constexpr void detectorToLocalUnchecked (T const row, T const col, float & xRow, float & zCol) const noexcept {
184+ xRow = -(static_cast <float >(row) + 0 .5f ) * PitchRow + WidthH;
185+ zCol = (static_cast <float >(col) + 0 .5f ) * PitchCol - LengthH;
167186 }
168187
169- bool detectorToLocal (int const row, int const col, math_utils::Point3D<float >& loc) const noexcept
170- {
188+
189+ template <typename T>
190+ constexpr bool detectorToLocal (T const row, T const col, math_utils::Point3D<float >& loc) const noexcept {
171191 float xRow{0 .}, zCol{0 .};
172192 if (!detectorToLocal (row, col, xRow, zCol)) {
173193 return false ;
174194 }
175- loc.SetCoordinates (xRow, 0 . , zCol);
195+ loc.SetCoordinates (xRow, NominalYShift , zCol);
176196 return true ;
177197 }
178198
179- void detectorToLocalUnchecked ( int const row, int const col, math_utils::Point3D< float >& loc) const noexcept
180- {
199+ template < typename T>
200+ constexpr void detectorToLocalUnchecked (T const row, T const col, math_utils::Point3D< float >& loc) const noexcept {
181201 float xRow{0 .}, zCol{0 .};
182202 detectorToLocalUnchecked (row, col, xRow, zCol);
183- loc.SetCoordinates (xRow, 0 . , zCol);
203+ loc.SetCoordinates (xRow, NominalYShift , zCol);
184204 }
185205
186206 private:
187207 template <typename T>
188- [[nodiscard]] bool isValid (T const row, T const col) const noexcept
208+ [[nodiscard]] constexpr bool isValid (T const row, T const col) const noexcept
189209 {
190210 if constexpr (std::is_floating_point_v<T>) { // compares in local coord.
191- namespace cp = constants::pixelarray;
192- return !static_cast <bool >(row <= -cp::width / 2 . || cp::width / 2 . <= row || col <= -cp::length / 2 . || cp::length / 2 . <= col);
211+ return (-WidthH < row && row < WidthH && -LengthH < col && col < LengthH);
193212 } else { // compares in rows/cols
194- return !static_cast <bool >(row < 0 || row >= static_cast <int >(mNRows ) || col < 0 || col >= static_cast <int >(mNCols ));
213+ return !static_cast <bool >(row < 0 || row >= static_cast <int >(NRows ) || col < 0 || col >= static_cast <int >(NCols ));
195214 }
196215 }
197216
198- const int mLayer {0 }; // /< chip layer
199-
200- ClassDef (SegmentationSuperAlpide, 1 );
217+ float mRadius ;
201218};
202219
203- // / Segmentation array
204- extern const std::array<SegmentationSuperAlpide, constants::nLayers> SuperSegmentations;
205220} // namespace o2::its3
206221
207222#endif
0 commit comments