Skip to content

Commit 990b8c7

Browse files
committed
ITS3 digitization: parameters, segmentation and container fixes
- Add digitization parameter sets - Fix C2F/F2C conversion in SegmentationMosaix - Set scale function for Alpide as IB - Fix chip digits container initialization - Correct ordering of maxRows and maxCols - Add support for floating row/column numbers in D2L
1 parent 950b8b7 commit 990b8c7

File tree

12 files changed

+522
-139
lines changed

12 files changed

+522
-139
lines changed

Detectors/Upgrades/ITS3/base/include/ITS3Base/SegmentationSuperAlpide.h

Lines changed: 83 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -9,30 +9,39 @@
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

2524
namespace 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

Detectors/Upgrades/ITS3/simulation/CMakeLists.txt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,21 @@ o2_add_library(ITS3Simulation
1414
src/ITS3Services.cxx
1515
src/DescriptorInnerBarrelITS3.cxx
1616
src/Digitizer.cxx
17+
src/DigiParams.cxx
18+
src/ITS3DPLDigitizerParam.cxx
19+
src/ChipDigitsContainer.cxx
1720
PUBLIC_LINK_LIBRARIES O2::SimulationDataFormat
18-
O2::ITSBase O2::ITSMFTSimulation
21+
O2::ITSBase O2::ITSMFTSimulation O2::ITSMFTBase
1922
ROOT::Physics)
2023

2124
o2_target_root_dictionary(ITS3Simulation
2225
HEADERS include/ITS3Simulation/ITS3Layer.h
2326
include/ITS3Simulation/ITS3Services.h
2427
include/ITS3Simulation/DescriptorInnerBarrelITS3.h
2528
include/ITS3Simulation/Digitizer.h
29+
include/ITS3Simulation/DigiParams.h
30+
include/ITS3Simulation/ITS3DPLDigitizerParam.h
31+
include/ITS3Simulation/ChipDigitsContainer.h
2632
)
2733

28-
o2_data_file(COPY data DESTINATION Detectors/ITS3/simulation)
34+
o2_data_file(COPY data DESTINATION Detectors/ITS3/simulation)
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
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+
12+
#ifndef ALICEO2_ITS3_CHIPDIGITSCONTAINER_
13+
#define ALICEO2_ITS3_CHIPDIGITSCONTAINER_
14+
15+
#include "ITSMFTBase/SegmentationAlpide.h" // Base class in o2::itsmft namespace
16+
#include "ITSMFTSimulation/ChipDigitsContainer.h" // Base class in o2::itsmft namespace
17+
#include "ITS3Base/SegmentationMosaix.h" // OB segmentation implementation
18+
#include "ITS3Base/SpecsV2.h" // Provides SpecsV2::isDetITS3() interface
19+
#include "ITS3Simulation/DigiParams.h" // ITS3-specific DigiParams interface
20+
#include <TRandom.h>
21+
22+
namespace o2
23+
{
24+
namespace its3
25+
{
26+
27+
// IB uses the Alpide segmentation,
28+
// OB uses the Mosaix segmentation.
29+
using SegmentationIB = SegmentationMosaix;
30+
using SegmentationOB = o2::itsmft::SegmentationAlpide;
31+
class ChipDigitsContainer : public o2::itsmft::ChipDigitsContainer
32+
{
33+
private:
34+
bool innerBarrel; ///< true if the chip belongs to the inner barrel (IB), false if outer barrel (OB)
35+
int maxRows; ///< maximum number of rows
36+
int maxCols; ///< maximum number of columns
37+
38+
public:
39+
explicit ChipDigitsContainer(UShort_t idx = 0);
40+
41+
/// Returns whether the chip is in the inner barrel (IB)
42+
void setChipIndex(UShort_t idx)
43+
{
44+
o2::itsmft::ChipDigitsContainer::setChipIndex(idx);
45+
innerBarrel = constants::detID::isDetITS3(getChipIndex());
46+
maxRows = innerBarrel ? SegmentationIB::NRows : SegmentationOB::NRows;
47+
maxCols = innerBarrel ? SegmentationIB::NCols : SegmentationOB::NCols;
48+
}
49+
50+
int getMaxRows() const { return maxRows; }
51+
int getMaxCols() const { return maxCols; }
52+
bool isIB() const;
53+
/// Adds noise digits, deleted the one using the itsmft::DigiParams interface
54+
void addNoise(UInt_t rofMin, UInt_t rofMax, const o2::itsmft::DigiParams* params, int maxRows = o2::itsmft::SegmentationAlpide::NRows, int maxCols = o2::itsmft::SegmentationAlpide::NCols) = delete;
55+
void addNoise(UInt_t rofMin, UInt_t rofMax, const o2::its3::DigiParams* params);
56+
57+
ClassDefNV(ChipDigitsContainer, 1);
58+
};
59+
60+
} // namespace its3
61+
} // namespace o2
62+
63+
#endif // ALICEO2_ITS3_CHIPDIGITSCONTAINER_

0 commit comments

Comments
 (0)