Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Detectors/Upgrades/ITS3/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
# granted to it by virtue of its status as an Intergovernmental Organization
# or submit itself to any jurisdiction.

#add_compile_options(-O0 -g -fPIC)
#add_compile_options(-O0 -g -fPIC -fsanitize=address)
#add_link_options(-fsanitize=address)

add_subdirectory(data)
add_subdirectory(simulation)
Expand Down
87 changes: 50 additions & 37 deletions Detectors/Upgrades/ITS3/base/include/ITS3Base/SegmentationMosaix.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@ class SegmentationMosaix
// the more natural row,col layout: Also all the transformation between these
// two. The class provides the transformation from the tile to TGeo
// coordinates.
// In fact there exist three coordinate systems and one is transient.
// 1. The curved coordinate system. The chip's local coordinate system is
// defined with its center at the the mid-point of the tube.
// 2. The flat coordinate system. This is the tube segment projected onto a flat
// surface. In the projection we implicitly assume that the inner and outer
// stretch does not depend on the radius.
// Additionally, there is a difference between the flat geometrical center
// and the phyiscal center defined by the metal layer.
// 3. The detector coordinate system. Defined by the row and column segmentation
// defined at the upper edge in the flat coord.

// row,col=0
// |
Expand All @@ -52,23 +62,32 @@ class SegmentationMosaix
// | | |
// x----------------------x
public:
~SegmentationMosaix() = default;
SegmentationMosaix(const SegmentationMosaix&) = default;
SegmentationMosaix(SegmentationMosaix&&) = delete;
SegmentationMosaix& operator=(const SegmentationMosaix&) = default;
SegmentationMosaix& operator=(SegmentationMosaix&&) = delete;
constexpr SegmentationMosaix(int layer) : mLayer{layer} {}
constexpr SegmentationMosaix(int layer) : mRadius(static_cast<float>(constants::radiiMiddle[layer])) {}
constexpr ~SegmentationMosaix() = default;
constexpr SegmentationMosaix(const SegmentationMosaix&) = default;
constexpr SegmentationMosaix(SegmentationMosaix&&) = delete;
constexpr SegmentationMosaix& operator=(const SegmentationMosaix&) = default;
constexpr SegmentationMosaix& operator=(SegmentationMosaix&&) = delete;

static constexpr int NCols{constants::pixelarray::nCols};
static constexpr int NRows{constants::pixelarray::nRows};
static constexpr int NPixels{NCols * NRows};
static constexpr float Length{constants::pixelarray::length};
static constexpr float LengthH{Length / 2.f};
static constexpr float Width{constants::pixelarray::width};
static constexpr float PitchCol{constants::pixelarray::length / static_cast<float>(NCols)};
static constexpr float PitchRow{constants::pixelarray::width / static_cast<float>(NRows)};
static constexpr float WidthH{Width / 2.f};
static constexpr float PitchCol{constants::pixelarray::pixels::mosaix::pitchZ};
static constexpr float PitchRow{constants::pixelarray::pixels::mosaix::pitchX};
static constexpr float SensorLayerThickness{constants::totalThickness};

/// Transformation from the curved surface to a flat surface
static constexpr float NominalYShift{constants::nominalYShift};

/// Transformation from the curved surface to a flat surface.
/// Additionally a shift in the flat coordinates must be applied because
/// the center of the TGeoShap when projected will be higher than the
/// physical thickness of the chip (we add an additional hull to account for
/// the copper metal interconnection which is in reality part of the chip but in our
/// simulation the silicon and metal layer are separated). Thus we shift the projected center
/// down by this difference to align the coordinate systems.
/// \param xCurved Detector local curved coordinate x in cm with respect to
/// the center of the sensitive volume.
/// \param yCurved Detector local curved coordinate y in cm with respect to
Expand All @@ -77,20 +96,20 @@ class SegmentationMosaix
/// the center of the sensitive volume.
/// \param yFlat Detector local flat coordinate y in cm with respect to
/// the center of the sensitive volume.
void curvedToFlat(const float xCurved, const float yCurved, float& xFlat, float& yFlat) const noexcept
constexpr void curvedToFlat(const float xCurved, const float yCurved, float& xFlat, float& yFlat) const noexcept
{
// MUST align the flat surface with the curved surface with the original pixel array is on and account for metal
// stack
float dist = std::hypot(xCurved, yCurved);
float phi = std::atan2(yCurved, xCurved);
xFlat = (getRadius() * phi) - Width / 2.f;
xFlat = (mRadius * phi) - WidthH;
// the y position is in the silicon volume however we need the chip volume (silicon+metalstack)
// this is accounted by a y shift
yFlat = dist - getRadius() + static_cast<float>(constants::nominalYShift);
yFlat = dist - mRadius + NominalYShift;
}

/// Transformation from the flat surface to a curved surface
/// It works only if the detector is not rototraslated
/// It works only if the detector is not rototraslated.
/// \param xFlat Detector local flat coordinate x in cm with respect to
/// the center of the sensitive volume.
/// \param yFlat Detector local flat coordinate y in cm with respect to
Expand All @@ -99,15 +118,15 @@ class SegmentationMosaix
/// the center of the sensitive volume.
/// \param yCurved Detector local curved coordinate y in cm with respect to
/// the center of the sensitive volume.
void flatToCurved(float xFlat, float yFlat, float& xCurved, float& yCurved) const noexcept
constexpr void flatToCurved(float xFlat, float yFlat, float& xCurved, float& yCurved) const noexcept
{
// MUST align the flat surface with the curved surface with the original pixel array is on and account for metal
// stack
// the y position is in the chip volume however we need the silicon volume
// this is accounted by a -y shift
float dist = yFlat + getRadius() - static_cast<float>(constants::nominalYShift);
xCurved = dist * std::cos((xFlat + Width / 2.f) / getRadius());
yCurved = dist * std::sin((xFlat + Width / 2.f) / getRadius());
float dist = yFlat - NominalYShift + mRadius;
xCurved = dist * std::cos((xFlat + WidthH) / mRadius);
yCurved = dist * std::sin((xFlat + WidthH) / mRadius);
}

/// Transformation from Geant detector centered local coordinates (cm) to
Expand All @@ -121,7 +140,7 @@ class SegmentationMosaix
/// the center of the sensitive volume.
/// \param int iRow Detector x cell coordinate.
/// \param int iCol Detector z cell coordinate.
bool localToDetector(float const xRow, float const zCol, int& iRow, int& iCol) const noexcept
constexpr bool localToDetector(float const xRow, float const zCol, int& iRow, int& iCol) const noexcept
{
localToDetectorUnchecked(xRow, zCol, iRow, iCol);
if (!isValid(iRow, iCol)) {
Expand All @@ -132,10 +151,10 @@ class SegmentationMosaix
}

// Same as localToDetector w.o. checks.
void localToDetectorUnchecked(float const xRow, float const zCol, int& iRow, int& iCol) const noexcept
constexpr void localToDetectorUnchecked(float const xRow, float const zCol, int& iRow, int& iCol) const noexcept
{
iRow = std::floor((Width / 2. - xRow) / PitchRow);
iCol = std::floor((zCol + Length / 2.) / PitchCol);
iRow = static_cast<int>(std::floor((WidthH - xRow) / PitchRow));
iCol = static_cast<int>(std::floor((zCol + LengthH) / PitchCol));
}

/// Transformation from Detector cell coordinates to Geant detector centered
Expand All @@ -148,7 +167,7 @@ class SegmentationMosaix
/// center of the sensitive volume.
/// If iRow and or iCol is outside of the segmentation range a value of -0.5*Dx()
/// or -0.5*Dz() is returned.
bool detectorToLocal(int const iRow, int const iCol, float& xRow, float& zCol) const noexcept
constexpr bool detectorToLocal(int const iRow, int const iCol, float& xRow, float& zCol) const noexcept
{
if (!isValid(iRow, iCol)) {
return false;
Expand All @@ -159,10 +178,10 @@ class SegmentationMosaix

// Same as detectorToLocal w.o. checks.
// We position ourself in the middle of the pixel.
void detectorToLocalUnchecked(int const iRow, int const iCol, float& xRow, float& zCol) const noexcept
constexpr void detectorToLocalUnchecked(int const iRow, int const iCol, float& xRow, float& zCol) const noexcept
{
xRow = -(static_cast<float>(iRow) + 0.5f) * PitchRow + Width / 2.f;
zCol = (static_cast<float>(iCol) + 0.5f) * PitchCol - Length / 2.f;
xRow = -(static_cast<float>(iRow) + 0.5f) * PitchRow + WidthH;
zCol = (static_cast<float>(iCol) + 0.5f) * PitchCol - LengthH;
}

bool detectorToLocal(int const row, int const col, math_utils::Point3D<float>& loc) const noexcept
Expand All @@ -171,35 +190,29 @@ class SegmentationMosaix
if (!detectorToLocal(row, col, xRow, zCol)) {
return false;
}
loc.SetCoordinates(xRow, 0., zCol);
loc.SetCoordinates(xRow, NominalYShift, zCol);
return true;
}

void detectorToLocalUnchecked(int const row, int const col, math_utils::Point3D<float>& loc) const noexcept
{
float xRow{0.}, zCol{0.};
detectorToLocalUnchecked(row, col, xRow, zCol);
loc.SetCoordinates(xRow, 0., zCol);
loc.SetCoordinates(xRow, NominalYShift, zCol);
}

private:
template <typename T>
[[nodiscard]] bool isValid(T const row, T const col) const noexcept
[[nodiscard]] constexpr bool isValid(T const row, T const col) const noexcept
{
if constexpr (std::is_floating_point_v<T>) { // compares in local coord.
namespace cp = constants::pixelarray;
return !static_cast<bool>(row <= -cp::width / 2. || cp::width / 2. <= row || col <= -cp::length / 2. || cp::length / 2. <= col);
return (-WidthH < row && row < WidthH && -LengthH < col && col < LengthH);
} else { // compares in rows/cols
return !static_cast<bool>(row < 0 || row >= static_cast<int>(NRows) || col < 0 || col >= static_cast<int>(NCols));
}
}

float getRadius() const noexcept
{
return static_cast<float>(constants::radiiMiddle[mLayer]);
}

int mLayer{0}; ///< chip layer
float mRadius;
};

} // namespace o2::its3
Expand Down
69 changes: 42 additions & 27 deletions Detectors/Upgrades/ITS3/base/include/ITS3Base/SpecsV2.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@

#include <array>

// This files defines the design specifications of the chip.
// Each TGeoShape has the following properties
// length: dimension in z-axis
// width: dimension in xy-axes
// color: for visulisation
namespace o2::its3::constants
{
constexpr double cm{1e+2}; // This is the default unit of TGeo so we use this as scale
Expand All @@ -35,27 +40,6 @@ constexpr int nRows{442};
constexpr int nPixels{nRows * nCols};
constexpr EColor color{kGreen};
constexpr double area{width * length};
namespace pixels
{
namespace apts
{
constexpr double pitchX{15.0 * mu};
constexpr double pitchZ{15.0 * mu};
} // namespace apts
namespace moss
{
namespace top
{
constexpr double pitchX{22.5 * mu};
constexpr double pitchZ{22.5 * mu};
} // namespace top
namespace bot
{
constexpr double pitchX{18.0 * mu};
constexpr double pitchZ{18.0 * mu};
} // namespace bot
} // namespace moss
} // namespace pixels
} // namespace pixelarray
namespace tile
{
Expand Down Expand Up @@ -112,7 +96,7 @@ constexpr EColor color{kCyan};
} // namespace rec
constexpr unsigned int nRSUs{12};
constexpr unsigned int nTilesPerSegment{nRSUs * rsu::nTiles};
constexpr double length{nRSUs * rsu::length + lec::length + rec::length};
constexpr double length{(nRSUs * rsu::length) + lec::length + rec::length};
constexpr double lengthSensitive{nRSUs * rsu::length};
} // namespace segment
namespace carbonfoam
Expand All @@ -136,9 +120,9 @@ constexpr EColor color{kBlack};
} // namespace metalstack
namespace silicon
{
constexpr double thickness{45 * mu}; // thickness of silicion
constexpr double radiusInner{(thickness + metalstack::thickness) / 2.}; // inner silicion radius correction
constexpr double radiusOuter{(thickness - metalstack::thickness) / 2.}; // outer silicion radius correction
constexpr double thickness{45 * mu}; // thickness of silicon
constexpr double thicknessIn{(thickness + metalstack::thickness) / 2.}; // inner silicon thickness
constexpr double thicknessOut{(thickness - metalstack::thickness) / 2.}; // outer silicon thickness
} // namespace silicon
constexpr unsigned int nLayers{3};
constexpr unsigned int nTotLayers{7};
Expand All @@ -147,10 +131,41 @@ constexpr double equatorialGap{1 * mm};
constexpr std::array<unsigned int, nLayers> nSegments{3, 4, 5};
constexpr double totalThickness{silicon::thickness + metalstack::thickness}; // total chip thickness
constexpr std::array<double, nLayers> radii{19.0006 * mm, 25.228 * mm, 31.4554 * mm}; // nominal radius
constexpr std::array<double, nLayers> radiiInner{radii[0] - silicon::radiusInner, radii[1] - silicon::radiusInner, radii[2] - silicon::radiusInner}; // inner silicon radius
constexpr std::array<double, nLayers> radiiOuter{radii[0] + silicon::radiusOuter, radii[1] + silicon::radiusOuter, radii[2] + silicon::radiusOuter}; // outer silicon radius
constexpr std::array<double, nLayers> radiiInner{radii[0] - silicon::thicknessIn, radii[1] - silicon::thicknessIn, radii[2] - silicon::thicknessIn}; // inner silicon radius
constexpr std::array<double, nLayers> radiiOuter{radii[0] + silicon::thicknessOut, radii[1] + silicon::thicknessOut, radii[2] + silicon::thicknessOut}; // outer silicon radius
constexpr std::array<double, nLayers> radiiMiddle{(radiiInner[0] + radiiOuter[0]) / 2., (radiiInner[1] + radiiOuter[1]) / 2., (radiiInner[2] + radiiOuter[2]) / 2.}; // middle silicon radius
constexpr double nominalYShift{-metalstack::thickness / 2.}; // shift to position in silicion volume to the chip volume (silicon+metalstack)

// extra information of pixels and their response functions
namespace pixelarray::pixels
{
namespace mosaix
{
constexpr double pitchX{width / static_cast<double>(nRows)};
constexpr double pitchZ{length / static_cast<double>(nCols)};
} // namespace mosaix
namespace apts
{
constexpr double pitchX{15.0 * mu};
constexpr double pitchZ{15.0 * mu};
constexpr double responseUpperLimit{10 * mu};
constexpr double responseYShift{responseUpperLimit - silicon::thicknessOut};
} // namespace apts
namespace moss
{
namespace top
{
constexpr double pitchX{22.5 * mu};
constexpr double pitchZ{22.5 * mu};
} // namespace top
namespace bot
{
constexpr double pitchX{18.0 * mu};
constexpr double pitchZ{18.0 * mu};
} // namespace bot
} // namespace moss
} // namespace pixelarray::pixels

namespace detID
{
constexpr unsigned int mDetIDs{2 * 12 * 12 * 12}; //< 2 Hemispheres * (3,4,5=12 segments in a layer) * 12 RSUs in a segment * 12 Tiles in a RSU
Expand Down
5 changes: 3 additions & 2 deletions Detectors/Upgrades/ITS3/macros/test/CheckClusterSize.C
Original file line number Diff line number Diff line change
Expand Up @@ -255,13 +255,14 @@ void CheckClusterSize(std::string clusFileName = "o2clus_its.root",

auto pattId = cluster.getPatternID();
auto id = cluster.getSensorID();
auto ib = o2::its3::constants::detID::isDetITS3(id);
int clusterSize{-1};
if (pattId == o2::itsmft::CompCluster::InvalidPatternID || dict.isGroup(pattId)) {
if (pattId == o2::itsmft::CompCluster::InvalidPatternID || dict.isGroup(pattId, ib)) {
o2::itsmft::ClusterPattern patt(pattIt);
clusterSize = patt.getNPixels();
continue;
} else {
clusterSize = dict.getNpixels(pattId);
clusterSize = dict.getNpixels(pattId, ib);
}

const auto& label = (clusLabArr->getLabels(clEntry))[0];
Expand Down
Loading