From bb989188e7ae8b54be2abf8978648c538886458c Mon Sep 17 00:00:00 2001 From: maciacco Date: Sat, 1 Aug 2026 19:09:48 +0200 Subject: [PATCH 1/6] add sub-stave architecture in OTOF (changes in chip containers and segmentation yet to be done) --- .../base/include/IOTOFBase/GeometryTGeo.h | 2 + .../ALICE3/IOTOF/base/src/GeometryTGeo.cxx | 1 + .../ALICE3/IOTOF/simulation/src/Layer.cxx | 52 ++++++++++++------- 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/GeometryTGeo.h b/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/GeometryTGeo.h index 616c6409f4577..1ff9ca3a19439 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/GeometryTGeo.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/GeometryTGeo.h @@ -50,6 +50,7 @@ class GeometryTGeo : public o2::detectors::DetMatrixCache const int getOTOFNumberOfChips() const { return mNumberOfChipsIOTOF[1]; } static const char* getOTOFLayerPattern() { return sOTOFLayerName.c_str(); } static const char* getOTOFStavePattern() { return sOTOFStaveName.c_str(); } + static const char* getOTOFSubStavePattern() { return sOTOFSubStaveName.c_str(); } static const char* getOTOFModulePattern() { return sOTOFModuleName.c_str(); } static const char* getOTOFChipPattern() { return sOTOFChipName.c_str(); } static const char* getOTOFSensorPattern() { return sOTOFSensorName.c_str(); } @@ -151,6 +152,7 @@ class GeometryTGeo : public o2::detectors::DetMatrixCache // Outer TOF static std::string sOTOFLayerName; static std::string sOTOFStaveName; + static std::string sOTOFSubStaveName; static std::string sOTOFModuleName; static std::string sOTOFChipName; static std::string sOTOFSensorName; diff --git a/Detectors/Upgrades/ALICE3/IOTOF/base/src/GeometryTGeo.cxx b/Detectors/Upgrades/ALICE3/IOTOF/base/src/GeometryTGeo.cxx index 905da9ddce754..66ccb9abedb09 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/base/src/GeometryTGeo.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/base/src/GeometryTGeo.cxx @@ -34,6 +34,7 @@ std::string GeometryTGeo::sITOFSensorName = "ITOFSensor"; // Outer TOF std::string GeometryTGeo::sOTOFLayerName = "OTOFLayer"; std::string GeometryTGeo::sOTOFStaveName = "OTOFStave"; +std::string GeometryTGeo::sOTOFSubStaveName = "OTOFSubStave"; std::string GeometryTGeo::sOTOFModuleName = "OTOFModule"; std::string GeometryTGeo::sOTOFChipName = "OTOFChip"; std::string GeometryTGeo::sOTOFSensorName = "OTOFSensor"; diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx index f63c93d37ce75..bc01b9969a9ff 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx @@ -263,6 +263,7 @@ void OTOFLayer::createLayer(TGeoVolume* motherVolume) const char* chipName = o2::iotof::GeometryTGeo::getOTOFChipPattern(); const char* sensName = o2::iotof::GeometryTGeo::getOTOFSensorPattern(); const char* moduleName = o2::iotof::GeometryTGeo::getOTOFModulePattern(); + const char* subStaveName = o2::iotof::GeometryTGeo::getOTOFSubStavePattern(); const char* staveName = o2::iotof::GeometryTGeo::getOTOFStavePattern(); TGeoMedium* medSi = gGeoManager->GetMedium("TF3_SILICON$"); @@ -296,9 +297,12 @@ void OTOFLayer::createLayer(TGeoVolume* motherVolume) case kBarrelSegmented: { // First we create the volume for the whole layer, which will be used as mother volume for the segments const double avgRadius = 0.5 * (mInnerRadius + mOuterRadius); - const double staveSizeX = mStaves.second; // cm, tangential stave size - const double staveSizeY = mOuterRadius - mInnerRadius; // cm, radial stave size - const double staveSizeZ = mZLength; // cm + const double staveSizeX = mStaves.second; // cm, tangential stave size + const double staveSizeY = mOuterRadius - mInnerRadius; // cm, radial stave size + const double staveSizeZ = mZLength; // cm + const double subStaveSizeX = 0.5 * mStaves.second + 0.55; // cm, tangential substave size + const double subStaveSizeY = mOuterRadius - mInnerRadius; // cm, radial substave size + const double subStaveSizeZ = mZLength; // cm // Build the mother layer tube from the exact inscribed/outscribed radii of a tilted stave rectangle. const double alpha = mTiltAngle * TMath::DegToRad(); @@ -323,17 +327,23 @@ void OTOFLayer::createLayer(TGeoVolume* motherVolume) TGeoVolume* staveVol = new TGeoVolume(staveName, stave, medAir); setStaveStyle(staveVol); + // Now we create the volume for a single stave + TGeoBBox* subStave = new TGeoBBox(subStaveSizeX * 0.5, subStaveSizeY * 0.5, subStaveSizeZ * 0.5); + TGeoVolume* subStaveVol = new TGeoVolume(subStaveName, subStave, medAir); + setStaveStyle(subStaveVol); + // Now we create the volume for a single module (sensor + chip) // oTOF V2 is a 2xN matrix. - const int modulesPerStaveX = 2; - if (mModulesPerStave % modulesPerStaveX != 0) { - LOG(fatal) << "Invalid oTOF module layout: total modules per stave " << mModulesPerStave - << " is not divisible by modulesPerStaveX=" << modulesPerStaveX; + const int modulesPerSubStave = mModulesPerStave; + const int modulesPerSubStaveX = 1; + if (modulesPerSubStave % modulesPerSubStaveX != 0) { + LOG(fatal) << "Invalid oTOF module layout: total modules per stave " << modulesPerSubStave + << " is not divisible by modulesPerStaveX=" << modulesPerSubStaveX; } - const int modulesPerStaveZ = 2 * mModulesPerStave / modulesPerStaveX; - const double moduleSizeX = staveSizeX / modulesPerStaveX; - const double moduleSizeY = staveSizeY; - const double moduleSizeZ = staveSizeZ / modulesPerStaveZ; + const int modulesPerSubStaveZ = mModulesPerStave / modulesPerSubStaveX; + const double moduleSizeX = subStaveSizeX / modulesPerSubStaveX; + const double moduleSizeY = subStaveSizeY; + const double moduleSizeZ = subStaveSizeZ / modulesPerSubStaveZ; TGeoBBox* module = new TGeoBBox(moduleSizeX * 0.5, moduleSizeY * 0.5, moduleSizeZ * 0.5); TGeoVolume* moduleVol = new TGeoVolume(moduleName, module, medAir); setModuleStyle(moduleVol); @@ -379,17 +389,23 @@ void OTOFLayer::createLayer(TGeoVolume* motherVolume) } } - // Now we build a stave from modules - for (int i = 0; i < modulesPerStaveX; ++i) { - for (int j = 0; j < modulesPerStaveZ; ++j) { - LOGP(info, "oTOF: Creating module {}/{} for stave {}/{}", i + 1, modulesPerStaveX, j + 1, modulesPerStaveZ); - const double tx = (i + 0.5) * moduleSizeX - 0.5 * staveSizeX; - const double tz = -0.5 * staveSizeZ + (j + 0.5) * moduleSizeZ; + // Now we build a sub-stave from modules + for (int i = 0; i < modulesPerSubStaveX; ++i) { + for (int j = 0; j < modulesPerSubStaveZ; ++j) { + LOGP(info, "oTOF: Creating module {}/{} for stave {}/{}", i + 1, modulesPerSubStaveX, j + 1, modulesPerSubStaveZ); + const double tx = (i + 0.5) * moduleSizeX - 0.5 * subStaveSizeX; + const double tz = -0.5 * subStaveSizeZ + (j + 0.5) * moduleSizeZ; auto* translation = new TGeoTranslation(tx, 0, tz); - staveVol->AddNode(moduleVol, 1 + i * modulesPerStaveZ + j, translation); + subStaveVol->AddNode(moduleVol, 1 + i * modulesPerSubStaveZ + j, translation); } } + // Now we build a stave from two substaves + auto* translation1 = new TGeoTranslation(-0.5 * subStaveSizeX, -0.15, 0); + staveVol->AddNode(subStaveVol, 1, translation1); + auto* translation2 = new TGeoTranslation(0.5 * subStaveSizeX, 0.15, 0); + staveVol->AddNode(subStaveVol, 2, translation2); + // We finally put all the staves in the layer for (int i = 0; i < mStaves.first; ++i) { LOGP(info, "oTOF: Creating stave {}/{} for layer {}", i + 1, mStaves.first, layerVol->GetName()); From aeaf896f8d5a0479db2e768a3f4d526a1bcadeed Mon Sep 17 00:00:00 2001 From: maciacco Date: Thu, 6 Aug 2026 14:58:32 +0200 Subject: [PATCH 2/6] adjust geometry parameters + use a single chip parametrization with updated size --- .../base/include/IOTOFBase/GeometryTGeo.h | 7 ++- .../base/include/IOTOFBase/IOTOFBaseParam.h | 50 ++++----------- .../ALICE3/IOTOF/base/src/GeometryTGeo.cxx | 61 +++++++++++++------ .../ALICE3/IOTOF/base/src/IOTOFBaseLinkDef.h | 4 ++ .../ALICE3/IOTOF/base/src/IOTOFBaseParam.cxx | 3 +- .../include/IOTOFSimulation/Segmentation.h | 37 ++++++----- .../ALICE3/IOTOF/simulation/src/Detector.cxx | 24 +++++--- .../ALICE3/IOTOF/simulation/src/Digitizer.cxx | 4 +- .../simulation/src/IOTOFSimulationLinkDef.h | 8 --- .../ALICE3/IOTOF/simulation/src/Layer.cxx | 52 ++++++++++------ .../IOTOF/simulation/src/Segmentation.cxx | 48 +++------------ 11 files changed, 145 insertions(+), 153 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/GeometryTGeo.h b/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/GeometryTGeo.h index 1ff9ca3a19439..c62b5b547d99a 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/GeometryTGeo.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/GeometryTGeo.h @@ -97,8 +97,8 @@ class GeometryTGeo : public o2::detectors::DetMatrixCache int getIOTOFFirstChipIndex(int lay) const; int getIOTOFLayer(int index) const; bool isValidIOTOFChipIndex(int index) const { return index >= 0 && index <= mLastChipIndex[1]; } - int getIOTOFChipIndex(int lay, int sta, int mod, int chip) const; - bool getIOTOFChipId(int index, int& lay, int& sta, int& mod, int& chip) const; + int getIOTOFChipIndex(int lay, int sta, int substa, int mod, int chip) const; + bool getIOTOFChipId(int index, int& lay, int& sta, int& substa, int& mod, int& chip) const; o2::math_utils::Point3D detectorToLocal(int row, int col, int chipId) const; static const ChipSpecifics& getChipSpecifics(int iotofLayer); @@ -134,6 +134,7 @@ class GeometryTGeo : public o2::detectors::DetMatrixCache protected: // Determine the number of active parts in the geometry int extractNumberOfStavesIOTOF(int lay) const; + int extractNumberOfSubStavesIOTOF(int lay) const; int extractNumberOfModulesIOTOF(int lay) const; int extractNumberOfChipsPerModuleIOTOF(int lay) const; int extractNumberOfChipsFTOF() const; @@ -169,9 +170,11 @@ class GeometryTGeo : public o2::detectors::DetMatrixCache // Inner/outer TOF int mNumberOfStavesIOTOF[2]{}; + int mNumberOfSubStavesIOTOF[2]{}; int mNumberOfModulesIOTOF[2]{}; int mNumberOfChipsPerModuleIOTOF[2]{}; int mNumberOfChipsPerStaveIOTOF[2]{}; + int mNumberOfChipsPerSubStaveIOTOF[2]{}; int mNumberOfChipsIOTOF[2]{}; int mLastChipIndex[2]{-1, -1}; diff --git a/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/IOTOFBaseParam.h b/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/IOTOFBaseParam.h index 7d3dbdc1bd1dc..3364fd59d2165 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/IOTOFBaseParam.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/IOTOFBaseParam.h @@ -21,55 +21,27 @@ namespace iotof { struct ChipSpecifics { - int NCols = 0; - int NRows = 0; - float PitchCol = 0.; - float PitchRow = 0.; + int NCols = 129; + int NRows = 271; + float PitchCol = 250.00e-4; + float PitchRow = 100.00e-4; float PassiveEdgeReadOut = 0.; float PassiveEdgeTop = 0.; float PassiveEdgeSide = 0.; - float SensorLayerThicknessEff = 0.; - float SensorLayerThickness = 0.; + float PixelPassiveEdgeX = 0.; + float PixelPassiveEdgeZ = 0.; + float SensorLayerThicknessEff = 50.e-4; + float SensorLayerThickness = 50.e-4; int NPixels() const { return NCols * NRows; } float ActiveMatrixSizeCols() const { return PitchCol * NCols; } float ActiveMatrixSizeRows() const { return PitchRow * NRows; } - float SensorSizeCols() const { return ActiveMatrixSizeCols() + 2 * PassiveEdgeSide; } + float SensorSizeCols() const { return ActiveMatrixSizeCols() + PassiveEdgeSide + PassiveEdgeSide; } float SensorSizeRows() const { return ActiveMatrixSizeRows() + PassiveEdgeTop + PassiveEdgeReadOut; } }; -struct ITOFChipSpecifics : ChipSpecifics { - ITOFChipSpecifics() - { - NCols = 129; - NRows = 271; - PitchCol = 250.00e-4; - PitchRow = 100.00e-4; - SensorLayerThicknessEff = 50.e-4; - SensorLayerThickness = 50.e-4; - } -}; - -struct OTOFChipSpecifics : ChipSpecifics { - OTOFChipSpecifics() - { - NCols = 125; - NRows = 243; - PitchCol = 250.00e-4; - PitchRow = 100.00e-4; - PassiveEdgeTop = 50.e-4; - PassiveEdgeSide = 115.8e-4; - SensorLayerThicknessEff = 50.e-4; - SensorLayerThickness = 50.e-4; - } -}; - -struct ITOFChipSpecificParam : public o2::conf::ConfigurableParamPromoter { - O2ParamDef(ITOFChipSpecificParam, "ITOFChipSpecific"); -}; - -struct OTOFChipSpecificParam : public o2::conf::ConfigurableParamPromoter { - O2ParamDef(OTOFChipSpecificParam, "OTOFChipSpecific"); +struct ChipSpecificsParam : public o2::conf::ConfigurableParamPromoter { + O2ParamDef(ChipSpecificsParam, "ChipSpecificsParam") }; struct IOTOFBaseParam : public o2::conf::ConfigurableParamHelper { diff --git a/Detectors/Upgrades/ALICE3/IOTOF/base/src/GeometryTGeo.cxx b/Detectors/Upgrades/ALICE3/IOTOF/base/src/GeometryTGeo.cxx index 66ccb9abedb09..8c8a36877eca8 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/base/src/GeometryTGeo.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/base/src/GeometryTGeo.cxx @@ -82,11 +82,38 @@ int GeometryTGeo::extractNumberOfStavesIOTOF(int lay) const return numberOfStaves; } +int GeometryTGeo::extractNumberOfSubStavesIOTOF(int lay) const +{ + if (lay == 0) { + return 1; + } + + int numberOfSubStaves{0}; + + std::string staveName = GeometryTGeo::getOTOFStavePattern(); + TGeoVolume* staveV = gGeoManager->GetVolume(staveName.c_str()); + if (staveV == nullptr) { + LOG(fatal) << "Can't find volume " << staveName; + return -1; + } + + TObjArray* nodes = staveV->GetNodes(); + int nNodes = nodes->GetEntriesFast(); + + for (int j{0}; j < nNodes; ++j) { + if (strstr(nodes->At(j)->GetName(), GeometryTGeo::getOTOFSubStavePattern()) != nullptr) { + numberOfSubStaves++; + } + } + + return numberOfSubStaves; +} + int GeometryTGeo::extractNumberOfModulesIOTOF(int lay) const { int numberOfModules{0}; - std::string staveName = lay == 0 ? GeometryTGeo::getITOFStavePattern() : GeometryTGeo::getOTOFStavePattern(); + std::string staveName = lay == 0 ? GeometryTGeo::getITOFStavePattern() : GeometryTGeo::getOTOFSubStavePattern(); TGeoVolume* staveV = gGeoManager->GetVolume(staveName.c_str()); if (staveV == nullptr) { LOG(fatal) << "Can't find volume " << staveName; @@ -152,33 +179,27 @@ int GeometryTGeo::getIOTOFLayer(int index) const return index > mLastChipIndex[0] ? 1 : 0; } -int GeometryTGeo::getIOTOFChipIndex(int lay, int sta, int mod, int chip) const +int GeometryTGeo::getIOTOFChipIndex(int lay, int sta, int substa, int mod, int chip) const { - return getIOTOFFirstChipIndex(lay) + (sta - 1) * mNumberOfChipsPerStaveIOTOF[lay] + (mod - 1) * mNumberOfChipsPerModuleIOTOF[lay] + (chip - 1); + return getIOTOFFirstChipIndex(lay) + (sta - 1) * mNumberOfChipsPerStaveIOTOF[lay] + (substa - 1) * mNumberOfChipsPerSubStaveIOTOF[lay] + (mod - 1) * mNumberOfChipsPerModuleIOTOF[lay] + (chip - 1); } -bool GeometryTGeo::getIOTOFChipId(int index, int& lay, int& sta, int& mod, int& chip) const +bool GeometryTGeo::getIOTOFChipId(int index, int& lay, int& sta, int& substa, int& mod, int& chip) const { lay = getIOTOFLayer(index); index -= getIOTOFFirstChipIndex(lay); sta = mNumberOfStavesIOTOF[lay] > 0 ? index / mNumberOfChipsPerStaveIOTOF[lay] : -1; index %= mNumberOfChipsPerStaveIOTOF[lay]; + substa = mNumberOfSubStavesIOTOF[lay] > 0 ? index / mNumberOfChipsPerSubStaveIOTOF[lay] : -1; + index %= mNumberOfChipsPerSubStaveIOTOF[lay]; mod = mNumberOfModulesIOTOF[lay] > 0 ? index / mNumberOfChipsPerModuleIOTOF[lay] : -1; chip = index % mNumberOfChipsPerModuleIOTOF[lay]; return true; } -const ChipSpecifics& GeometryTGeo::getChipSpecifics(int iotofLayer) -{ - if (iotofLayer == 0) { - return ITOFChipSpecificParam::Instance(); - } - return OTOFChipSpecificParam::Instance(); -} - o2::math_utils::Point3D GeometryTGeo::detectorToLocal(int row, int col, int chipId) const { - const auto& specs = getChipSpecifics(getIOTOFLayer(chipId)); + const auto& specs = ChipSpecificsParam::Instance(); o2::math_utils::Point3D loc; loc.SetCoordinates(0.5f * ((specs.ActiveMatrixSizeRows() - specs.PassiveEdgeTop + specs.PassiveEdgeReadOut) - specs.PitchRow) - row * specs.PitchRow, 0.f, @@ -188,11 +209,12 @@ o2::math_utils::Point3D GeometryTGeo::detectorToLocal(int row, int col, i TString GeometryTGeo::getMatrixPath(int index) const { - int lay, sta, mod, chip; - getIOTOFChipId(index, lay, sta, mod, chip); + int lay, sta, substa, mod, chip; + getIOTOFChipId(index, lay, sta, substa, mod, chip); TString path = Form("/cave_1/barrel_1/%s_2/", GeometryTGeo::getIOTOFVolPattern()); sta += 1; + substa += 1; mod += 1; chip += 1; @@ -212,6 +234,9 @@ TString GeometryTGeo::getMatrixPath(int index) const if (mNumberOfStavesIOTOF[lay] > 0) { path += Form("%s_%d/", GeometryTGeo::getOTOFStavePattern(), sta); } + if (mNumberOfSubStavesIOTOF[lay] > 0) { + path += Form("%s_%d/", GeometryTGeo::getOTOFSubStavePattern(), substa); + } if (mNumberOfModulesIOTOF[lay] > 0) { path += Form("%s_%d/", GeometryTGeo::getOTOFModulePattern(), mod); } @@ -267,6 +292,7 @@ void GeometryTGeo::Build(int loadTrans) // Inner/outer TOF for (int j{0}; j < 2; ++j) { mNumberOfStavesIOTOF[j] = extractNumberOfStavesIOTOF(j); + mNumberOfSubStavesIOTOF[j] = extractNumberOfSubStavesIOTOF(j); mNumberOfModulesIOTOF[j] = extractNumberOfModulesIOTOF(j); mNumberOfChipsPerModuleIOTOF[j] = extractNumberOfChipsPerModuleIOTOF(j); } @@ -279,14 +305,15 @@ void GeometryTGeo::Build(int loadTrans) int numberOfChips{0}; for (int j{0}; j < 2; ++j) { - mNumberOfChipsPerStaveIOTOF[j] = mNumberOfModulesIOTOF[j] * mNumberOfChipsPerModuleIOTOF[j]; + mNumberOfChipsPerStaveIOTOF[j] = mNumberOfSubStavesIOTOF[j] * mNumberOfModulesIOTOF[j] * mNumberOfChipsPerModuleIOTOF[j]; + mNumberOfChipsPerSubStaveIOTOF[j] = mNumberOfModulesIOTOF[j] * mNumberOfChipsPerModuleIOTOF[j]; mNumberOfChipsIOTOF[j] = mNumberOfStavesIOTOF[j] * mNumberOfChipsPerStaveIOTOF[j]; numberOfChips += mNumberOfChipsIOTOF[j]; mLastChipIndex[j] = numberOfChips - 1; } LOG(info) << "TF3 geometry: numberOfChipsITOF = " << mNumberOfChipsIOTOF[0] << ", numberOfChipsOTOF = " - << mNumberOfChipsIOTOF[1] << ", numberOfChips = " << numberOfChips << ", mNumberOfChipesPerStaveITOF" + << mNumberOfChipsIOTOF[1] << ", numberOfChips = " << numberOfChips << ", mNumberOfChipsPerStaveITOF" << mNumberOfChipsPerStaveIOTOF[0]; setSize(numberOfChips); diff --git a/Detectors/Upgrades/ALICE3/IOTOF/base/src/IOTOFBaseLinkDef.h b/Detectors/Upgrades/ALICE3/IOTOF/base/src/IOTOFBaseLinkDef.h index 5cbff299d78c1..a4031323fd3a6 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/base/src/IOTOFBaseLinkDef.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/base/src/IOTOFBaseLinkDef.h @@ -19,4 +19,8 @@ #pragma link C++ class o2::iotof::IOTOFBaseParam + ; #pragma link C++ class o2::conf::ConfigurableParamHelper < o2::iotof::IOTOFBaseParam> + ; +#pragma link C++ class o2::iotof::ChipSpecifics + ; +#pragma link C++ class o2::iotof::ChipSpecificsParam + ; +#pragma link C++ class o2::conf::ConfigurableParamPromoter < o2::iotof::ChipSpecificsParam, o2::iotof::ChipSpecifics> + ; + #endif \ No newline at end of file diff --git a/Detectors/Upgrades/ALICE3/IOTOF/base/src/IOTOFBaseParam.cxx b/Detectors/Upgrades/ALICE3/IOTOF/base/src/IOTOFBaseParam.cxx index f6799f41e3786..394bb22749a1d 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/base/src/IOTOFBaseParam.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/base/src/IOTOFBaseParam.cxx @@ -12,5 +12,4 @@ #include "IOTOFBase/IOTOFBaseParam.h" O2ParamImpl(o2::iotof::IOTOFBaseParam); -O2ParamImpl(o2::iotof::ITOFChipSpecificParam); -O2ParamImpl(o2::iotof::OTOFChipSpecificParam); +O2ParamImpl(o2::iotof::ChipSpecificsParam); diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Segmentation.h b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Segmentation.h index cd0ab55bd03d7..1cca70e2ee1e0 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Segmentation.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Segmentation.h @@ -35,16 +35,11 @@ class Segmentation static std::unique_ptr sInstance; public: - ChipSpecifics mITofSpecsConfig; - ChipSpecifics mOTofSpecsConfig; + ChipSpecifics mIOTOFSpecsConfig; static Segmentation* Instance(); ~Segmentation() = default; - void configChip(const int nCols, const int nRows, const float pitchCol, const float pitchRow, const float passiveEdgeReadOut, const float passiveEdgeTop, - const float passiveEdgeSide, const float sensorLayerThicknessEff, const float sensorLayerThickness, const int subDetectorID); - void configChip(const ChipSpecifics& specsConfig, const int subDetectorID); - /// Transformation from Geant detector centered local coordinates (cm) to /// Pixel cell numbers iRow and iCol. /// Returns kTRUE if point x,z is inside sensitive volume, kFALSE otherwise. @@ -79,7 +74,7 @@ class Segmentation row = col = -1; return; } - const ChipSpecifics& specsConfig = (subDetectorID == 0) ? mITofSpecsConfig : mOTofSpecsConfig; + const ChipSpecifics& specsConfig = mIOTOFSpecsConfig; xRow = getFirstRowCoordinate(subDetectorID) - row * specsConfig.PitchRow; zCol = col * specsConfig.PitchCol + getFirstColCoordinate(subDetectorID); } @@ -90,7 +85,7 @@ class Segmentation row = col = -1; return; } - const ChipSpecifics& specsConfig = (subDetectorID == 0) ? mITofSpecsConfig : mOTofSpecsConfig; + const ChipSpecifics& specsConfig = mIOTOFSpecsConfig; loc.SetCoordinates(getFirstRowCoordinate(subDetectorID) - row * specsConfig.PitchRow, T(0.), col * specsConfig.PitchCol + getFirstColCoordinate(subDetectorID)); } template @@ -100,7 +95,7 @@ class Segmentation row = col = -1; return; } - const ChipSpecifics& specsConfig = (subDetectorID == 0) ? mITofSpecsConfig : mOTofSpecsConfig; + const ChipSpecifics& specsConfig = mIOTOFSpecsConfig; loc[0] = getFirstRowCoordinate(subDetectorID) - row * specsConfig.PitchRow; loc[1] = T(0); loc[2] = col * specsConfig.PitchCol + getFirstColCoordinate(subDetectorID); @@ -115,7 +110,7 @@ class Segmentation row = col = -1; return false; } - const ChipSpecifics& specsConfig = (subDetectorID == 0) ? mITofSpecsConfig : mOTofSpecsConfig; + const ChipSpecifics& specsConfig = mIOTOFSpecsConfig; if (row < 0 || row >= specsConfig.NRows || col < 0 || col >= specsConfig.NCols) { return false; } @@ -130,7 +125,7 @@ class Segmentation row = col = -1; return false; } - const ChipSpecifics& specsConfig = (subDetectorID == 0) ? mITofSpecsConfig : mOTofSpecsConfig; + const ChipSpecifics& specsConfig = mIOTOFSpecsConfig; if (row < 0 || row >= specsConfig.NRows || col < 0 || col >= specsConfig.NCols) { return false; } @@ -144,7 +139,7 @@ class Segmentation row = col = -1; return false; } - const ChipSpecifics& specsConfig = (subDetectorID == 0) ? mITofSpecsConfig : mOTofSpecsConfig; + const ChipSpecifics& specsConfig = mIOTOFSpecsConfig; if (row < 0 || row >= specsConfig.NRows || col < 0 || col >= specsConfig.NCols) { return false; } @@ -154,12 +149,12 @@ class Segmentation float getFirstRowCoordinate(const int subDetectorID) { - const ChipSpecifics& specsConfig = (subDetectorID == 0) ? mITofSpecsConfig : mOTofSpecsConfig; + const ChipSpecifics& specsConfig = mIOTOFSpecsConfig; return 0.5 * ((specsConfig.ActiveMatrixSizeRows() - specsConfig.PassiveEdgeTop + specsConfig.PassiveEdgeReadOut) - specsConfig.PitchRow); } float getFirstColCoordinate(const int subDetectorID) { - const ChipSpecifics& specsConfig = (subDetectorID == 0) ? mITofSpecsConfig : mOTofSpecsConfig; + const ChipSpecifics& specsConfig = mIOTOFSpecsConfig; return 0.5 * (specsConfig.PitchCol - specsConfig.ActiveMatrixSizeCols()); } @@ -176,11 +171,16 @@ inline void Segmentation::localToDetectorUnchecked(float xRow, float zCol, int& iRow = iCol = -1; return; } - const ChipSpecifics& specsConfig = (subDetectorID == 0) ? mITofSpecsConfig : mOTofSpecsConfig; + const ChipSpecifics& specsConfig = mIOTOFSpecsConfig; xRow = 0.5 * (specsConfig.ActiveMatrixSizeRows() - specsConfig.PassiveEdgeTop + specsConfig.PassiveEdgeReadOut) - xRow; // coordinate wrt top edge of Active matrix zCol += 0.5 * specsConfig.ActiveMatrixSizeCols(); // coordinate wrt left edge of Active matrix iRow = int(xRow / specsConfig.PitchRow); iCol = int(zCol / specsConfig.PitchCol); + // check pixel passive region + if (std::abs(xRow - (iRow + 0.5) * specsConfig.PitchRow) > (0.5 * specsConfig.PitchRow - specsConfig.PixelPassiveEdgeX) || std::abs(zCol - (iCol + 0.5) * specsConfig.PitchCol) > (0.5 * specsConfig.PitchCol - specsConfig.PixelPassiveEdgeZ)) { + iRow = iCol = -1; + return; + } if (xRow < 0) { iRow -= 1; } @@ -197,7 +197,7 @@ inline bool Segmentation::localToDetector(float xRow, float zCol, int& iRow, int iRow = iCol = -1; return false; } - const ChipSpecifics& specsConfig = (subDetectorID == 0) ? mITofSpecsConfig : mOTofSpecsConfig; + const ChipSpecifics& specsConfig = mIOTOFSpecsConfig; xRow = 0.5 * (specsConfig.ActiveMatrixSizeRows() - specsConfig.PassiveEdgeTop + specsConfig.PassiveEdgeReadOut) - xRow; // coordinate wrt top edge of Active matrix zCol += 0.5 * specsConfig.ActiveMatrixSizeCols(); // coordinate wrt left edge of Active matrix if (xRow < 0 || xRow >= specsConfig.ActiveMatrixSizeRows() || zCol < 0 || zCol >= specsConfig.ActiveMatrixSizeCols()) { @@ -206,6 +206,11 @@ inline bool Segmentation::localToDetector(float xRow, float zCol, int& iRow, int } iRow = int(xRow / specsConfig.PitchRow); iCol = int(zCol / specsConfig.PitchCol); + // check pixel passive region + if (std::abs(xRow - (iRow + 0.5) * specsConfig.PitchRow) > (0.5 * specsConfig.PitchRow - specsConfig.PixelPassiveEdgeX) || std::abs(zCol - (iCol + 0.5) * specsConfig.PitchCol) > (0.5 * specsConfig.PitchCol - specsConfig.PixelPassiveEdgeZ)) { + iRow = iCol = -1; + return false; + } return true; } diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Detector.cxx index 26ea7f1ae9812..d48fb8fa30e3a 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Detector.cxx @@ -361,23 +361,29 @@ bool Detector::ProcessHits(FairVolume* vol) TLorentzVector positionStop; fMC->TrackPosition(positionStop); // Retrieve the indices with the volume path - int stave(0), chipinmodule(0), module(0); + int layN = -1; + if (strstr(vol->GetName(), GeometryTGeo::getITOFSensorPattern()) != nullptr) { + layN = 0; + } else if (strstr(vol->GetName(), GeometryTGeo::getOTOFSensorPattern()) != nullptr) { + layN = 1; + } + int stave(0), chipinmodule(0), substave(1), module(0); fMC->CurrentVolOffID(1, chipinmodule); fMC->CurrentVolOffID(2, module); - fMC->CurrentVolOffID(3, stave); + if (layN == 0) { + fMC->CurrentVolOffID(3, stave); + } else if (layN == 1) { + fMC->CurrentVolOffID(3, substave); + fMC->CurrentVolOffID(4, stave); + } +LOG(info) << layN << "\t" << stave << "\t" << substave << "\t" << module << "\t" << chipinmodule; int sensorID = lay; auto& iotofPars = IOTOFBaseParam::Instance(); - int layN = -1; - if (strstr(vol->GetName(), GeometryTGeo::getITOFSensorPattern()) != nullptr) { - layN = 0; - } else if (strstr(vol->GetName(), GeometryTGeo::getOTOFSensorPattern())) { - layN = 1; - } if (iotofPars.segmentedInnerTOF && iotofPars.segmentedOuterTOF) { if (layN > -1) { - sensorID = mGeometryTGeo->getIOTOFChipIndex(layN, stave, module, chipinmodule); + sensorID = mGeometryTGeo->getIOTOFChipIndex(layN, stave, substave, module, chipinmodule); } else { sensorID += (mGeometryTGeo->getSize() - 1); // temporary as f/b tof is not yet segmented } diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx index dbcb306911847..bb225bd1842fb 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx @@ -210,8 +210,8 @@ void Digitizer::stepping(const o2::itsmft::Hit& hit, float**& respMatrix, int& r rowStart = std::max(rowStart, 0); colStart = std::max(colStart, 0); - rowEnd = std::min(rowEnd, (subdetectorID == 0 ? sSegmentation->mITofSpecsConfig.NRows : sSegmentation->mOTofSpecsConfig.NRows) - 1); - colEnd = std::min(colEnd, (subdetectorID == 0 ? sSegmentation->mITofSpecsConfig.NCols : sSegmentation->mOTofSpecsConfig.NCols) - 1); + rowEnd = std::min(rowEnd, (sSegmentation->mIOTOFSpecsConfig.NRows) - 1); + colEnd = std::min(colEnd, (sSegmentation->mIOTOFSpecsConfig.NCols) - 1); rowSpan = rowEnd - rowStart + 1; colSpan = colEnd - colStart + 1; diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/IOTOFSimulationLinkDef.h b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/IOTOFSimulationLinkDef.h index 2384d207a03b0..a3cadccfc6d5a 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/IOTOFSimulationLinkDef.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/IOTOFSimulationLinkDef.h @@ -27,12 +27,4 @@ #pragma link C++ class o2::iotof::DPLDigitizerParam + ; #pragma link C++ class o2::conf::ConfigurableParamHelper < o2::iotof::DPLDigitizerParam> + ; -#pragma link C++ class o2::iotof::ChipSpecifics + ; -#pragma link C++ class o2::iotof::ITOFChipSpecifics + ; -#pragma link C++ class o2::iotof::OTOFChipSpecifics + ; -#pragma link C++ class o2::iotof::ITOFChipSpecificParam + ; -#pragma link C++ class o2::conf::ConfigurableParamPromoter < o2::iotof::ITOFChipSpecificParam, o2::iotof::ITOFChipSpecifics> + ; -#pragma link C++ class o2::iotof::OTOFChipSpecificParam + ; -#pragma link C++ class o2::conf::ConfigurableParamPromoter < o2::iotof::OTOFChipSpecificParam, o2::iotof::OTOFChipSpecifics> + ; - #endif diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx index bc01b9969a9ff..84322c807e42e 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx @@ -165,10 +165,22 @@ void ITOFLayer::createLayer(TGeoVolume* motherVolume) const double staveSizeX = mStaves.second; // cm const double staveSizeY = mOuterRadius - mInnerRadius; // cm const double staveSizeZ = mZLength; // cm - const double deltaForTilt = 0.5 * (std::sin(TMath::DegToRad() * mTiltAngle) * staveSizeX + std::cos(TMath::DegToRad() * mTiltAngle) * staveSizeY); // we increase the size of the layer to account for the tilt of the staves - const double radiusMax = std::sqrt(avgRadius * avgRadius + 0.25 * staveSizeX * staveSizeX + 0.25 * staveSizeY * staveSizeY + avgRadius * 2. * deltaForTilt); // we increase the outer radius to account for the tilt of the staves - const double radiusMin = std::sqrt(avgRadius * avgRadius + 0.25 * staveSizeX * staveSizeX + 0.25 * staveSizeY * staveSizeY - avgRadius * 2. * deltaForTilt); // we decrease the inner radius to account for the tilt of the staves - TGeoTube* layer = new TGeoTube(radiusMin - 0.05, radiusMax + 0.05, mZLength / 2); // cm, small margins to ensure staves are fully encapsulated in the layer volume + + // Build the mother layer tube from the exact inscribed/outscribed radii of a tilted stave rectangle. + const double alpha = mTiltAngle * TMath::DegToRad(); + const double u0 = -avgRadius * std::cos(alpha); + const double v0 = avgRadius * std::sin(alpha); + const double uClamped = std::max(-0.5 * staveSizeY, std::min(0.5 * staveSizeY, u0)); + const double vClamped = std::max(-0.5 * staveSizeX, std::min(0.5 * staveSizeX, v0)); + const double radiusMin = std::hypot(uClamped - u0, vClamped - v0); + + const double uCorners[4] = {-0.5 * staveSizeY, 0.5 * staveSizeY, 0.5 * staveSizeY, -0.5 * staveSizeY}; + const double vCorners[4] = {-0.5 * staveSizeX, -0.5 * staveSizeX, 0.5 * staveSizeX, 0.5 * staveSizeX}; + double radiusMax = 0.0; + for (int i = 0; i < 4; ++i) { + radiusMax = std::max(radiusMax, std::hypot(uCorners[i] - u0, vCorners[i] - v0)); + } + TGeoTube* layer = new TGeoTube(radiusMin, radiusMax, mZLength / 2); // cm, small margins to ensure staves are fully encapsulated in the layer volume TGeoVolume* layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir); setLayerStyle(layerVol); @@ -212,7 +224,7 @@ void ITOFLayer::createLayer(TGeoVolume* motherVolume) for (int j = 0; j < sensorsPerChipZ; ++j) { LOGP(info, "iTOF: Creating sensor {}/{} for chip {}/{}", i + 1, sensorsPerChipX, j + 1, sensorsPerChipZ); auto* translation = new TGeoTranslation((i + 0.5) * sensorSizeX - 0.5 * chipSizeX, - 0, + 0.5 * chipSizeY - 0.5 * sensorSizeY, (j + 0.5) * sensorSizeZ - 0.5 * chipSizeZ); chipVol->AddNode(sensVol, 1 + i * sensorsPerChipZ + j, translation); } @@ -295,14 +307,18 @@ void OTOFLayer::createLayer(TGeoVolume* motherVolume) return; } case kBarrelSegmented: { + // Additional geometry parameters + const double subStavesDistanceY = 0.3; // cm + const double subStavesOverlapX = 1.1; // cm + // First we create the volume for the whole layer, which will be used as mother volume for the segments const double avgRadius = 0.5 * (mInnerRadius + mOuterRadius); - const double staveSizeX = mStaves.second; // cm, tangential stave size - const double staveSizeY = mOuterRadius - mInnerRadius; // cm, radial stave size - const double staveSizeZ = mZLength; // cm - const double subStaveSizeX = 0.5 * mStaves.second + 0.55; // cm, tangential substave size - const double subStaveSizeY = mOuterRadius - mInnerRadius; // cm, radial substave size - const double subStaveSizeZ = mZLength; // cm + const double staveSizeX = mStaves.second; // cm, tangential stave size + const double staveSizeY = mOuterRadius - mInnerRadius + subStavesDistanceY; // cm, radial stave size + const double staveSizeZ = mZLength; // cm + const double subStaveSizeX = 0.5 * mStaves.second + 0.5 * subStavesOverlapX; // cm, tangential substave size + const double subStaveSizeY = mOuterRadius - mInnerRadius; // cm, radial substave size + const double subStaveSizeZ = mZLength; // cm // Build the mother layer tube from the exact inscribed/outscribed radii of a tilted stave rectangle. const double alpha = mTiltAngle * TMath::DegToRad(); @@ -340,7 +356,7 @@ void OTOFLayer::createLayer(TGeoVolume* motherVolume) LOG(fatal) << "Invalid oTOF module layout: total modules per stave " << modulesPerSubStave << " is not divisible by modulesPerStaveX=" << modulesPerSubStaveX; } - const int modulesPerSubStaveZ = mModulesPerStave / modulesPerSubStaveX; + const int modulesPerSubStaveZ = modulesPerSubStave / modulesPerSubStaveX; const double moduleSizeX = subStaveSizeX / modulesPerSubStaveX; const double moduleSizeY = subStaveSizeY; const double moduleSizeZ = subStaveSizeZ / modulesPerSubStaveZ; @@ -374,7 +390,7 @@ void OTOFLayer::createLayer(TGeoVolume* motherVolume) for (int j = 0; j < sensorsPerChipZ; ++j) { LOGP(info, "oTOF: Creating sensor {}/{} for chip {}/{}", i + 1, sensorsPerChipX, j + 1, sensorsPerChipZ); auto* translation = new TGeoTranslation((i + 0.5) * sensorSizeX - 0.5 * chipSizeX, - 0, + 0.5 * chipSizeY - 0.5 * sensorSizeY, (j + 0.5) * sensorSizeZ - 0.5 * chipSizeZ); chipVol->AddNode(sensVol, 1 + i * sensorsPerChipZ + j, translation); } @@ -392,7 +408,7 @@ void OTOFLayer::createLayer(TGeoVolume* motherVolume) // Now we build a sub-stave from modules for (int i = 0; i < modulesPerSubStaveX; ++i) { for (int j = 0; j < modulesPerSubStaveZ; ++j) { - LOGP(info, "oTOF: Creating module {}/{} for stave {}/{}", i + 1, modulesPerSubStaveX, j + 1, modulesPerSubStaveZ); + LOGP(info, "oTOF: Creating module {}/{} for substave {}/{}", i + 1, modulesPerSubStaveX, j + 1, modulesPerSubStaveZ); const double tx = (i + 0.5) * moduleSizeX - 0.5 * subStaveSizeX; const double tz = -0.5 * subStaveSizeZ + (j + 0.5) * moduleSizeZ; auto* translation = new TGeoTranslation(tx, 0, tz); @@ -400,10 +416,12 @@ void OTOFLayer::createLayer(TGeoVolume* motherVolume) } } - // Now we build a stave from two substaves - auto* translation1 = new TGeoTranslation(-0.5 * subStaveSizeX, -0.15, 0); + // Now we build a stave from two substave + LOGP(info, "oTOF: Creating substave {}/{} for stave {}/{}", 1, 2, 1, 1); + auto* translation1 = new TGeoTranslation(-0.5 * (subStaveSizeX) + 0.5 * subStavesOverlapX, -0.5 * subStavesDistanceY, 0); staveVol->AddNode(subStaveVol, 1, translation1); - auto* translation2 = new TGeoTranslation(0.5 * subStaveSizeX, 0.15, 0); + LOGP(info, "oTOF: Creating substave {}/{} for stave {}/{}", 2, 2, 1, 1); + auto* translation2 = new TGeoTranslation(0.5 * (subStaveSizeX) - 0.5 * subStavesOverlapX, 0.5 * subStavesDistanceY, 0); staveVol->AddNode(subStaveVol, 2, translation2); // We finally put all the staves in the layer diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Segmentation.cxx b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Segmentation.cxx index ea03b3d317cdc..c5b345381136a 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Segmentation.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Segmentation.cxx @@ -37,52 +37,18 @@ Segmentation::Segmentation() if (sInstance) { printf("Invalid use of public constructor: o2::iotof::Segmentation instance exists\n"); } else { - auto& itofPars = ITOFChipSpecificParam::Instance(); - auto& otofPars = OTOFChipSpecificParam::Instance(); - const ChipSpecifics mITofChipPars(itofPars.NCols, itofPars.NRows, itofPars.PitchCol, itofPars.PitchRow, itofPars.PassiveEdgeReadOut, itofPars.PassiveEdgeTop, itofPars.PassiveEdgeSide, itofPars.SensorLayerThicknessEff, itofPars.SensorLayerThickness); - const ChipSpecifics mOTofChipPars(otofPars.NCols, otofPars.NRows, otofPars.PitchCol, otofPars.PitchRow, otofPars.PassiveEdgeReadOut, otofPars.PassiveEdgeTop, otofPars.PassiveEdgeSide, otofPars.SensorLayerThicknessEff, otofPars.SensorLayerThickness); - - configChip(mITofChipPars, 0 /* subDetectorID for iTOF */); - configChip(mOTofChipPars, 1 /* subDetectorID for oTOF */); - } -} - -void Segmentation::configChip(const int nCols, const int nRows, const float pitchCol, const float pitchRow, const float passiveEdgeReadOut, - const float passiveEdgeTop, const float passiveEdgeSide, const float sensorLayerThicknessEff, const float sensorLayerThickness, const int subDetectorID) -{ - if (subDetectorID == 0) { - mITofSpecsConfig = ChipSpecifics(nCols, nRows, pitchCol, pitchRow, passiveEdgeReadOut, passiveEdgeTop, passiveEdgeSide, sensorLayerThicknessEff, sensorLayerThickness); - } else if (subDetectorID == 1) { - mOTofSpecsConfig = ChipSpecifics(nCols, nRows, pitchCol, pitchRow, passiveEdgeReadOut, passiveEdgeTop, passiveEdgeSide, sensorLayerThicknessEff, sensorLayerThickness); - } else { - printf("Invalid subDetectorID %d. Must be 0 (iTOF) or 1 (oTOF). No configuration applied.\n", subDetectorID); - } -} - -void Segmentation::configChip(const ChipSpecifics& specsConfig, const int subDetectorID) -{ - if (subDetectorID == 0) { - mITofSpecsConfig = specsConfig; - } else if (subDetectorID == 1) { - mOTofSpecsConfig = specsConfig; - } else { - printf("Invalid subDetectorID %d. Must be 0 (iTOF) or 1 (oTOF). No configuration applied.\n", subDetectorID); + auto& iotofChipPars = ChipSpecificsParam::Instance(); + mIOTOFSpecsConfig = ChipSpecifics(iotofChipPars.NCols, iotofChipPars.NRows, iotofChipPars.PitchCol, iotofChipPars.PitchRow, iotofChipPars.PassiveEdgeReadOut, iotofChipPars.PassiveEdgeTop, iotofChipPars.PassiveEdgeSide, iotofChipPars.PixelPassiveEdgeX, iotofChipPars.PixelPassiveEdgeZ, iotofChipPars.SensorLayerThicknessEff, iotofChipPars.SensorLayerThickness); } } void Segmentation::print() { - // iTOF specs - printf("iTOF specs:\n"); - printf("Pixel size: %.2f (along %d rows) %.2f (along %d columns) microns\n", mITofSpecsConfig.PitchRow * 1e4, mITofSpecsConfig.NRows, mITofSpecsConfig.PitchCol * 1e4, mITofSpecsConfig.NCols); - printf("Passive edges: bottom: %.2f, top: %.2f, left/right: %.2f microns\n", mITofSpecsConfig.PassiveEdgeReadOut * 1e4, mITofSpecsConfig.PassiveEdgeTop * 1e4, mITofSpecsConfig.PassiveEdgeSide * 1e4); - printf("Active/Total size: %.6f/%.6f (rows) %.6f/%.6f (cols) cm\n", mITofSpecsConfig.ActiveMatrixSizeRows(), mITofSpecsConfig.SensorSizeRows(), mITofSpecsConfig.ActiveMatrixSizeCols(), mITofSpecsConfig.SensorSizeCols()); - - // oTOF specs - printf("oTOF specs:\n"); - printf("Pixel size: %.2f (along %d rows) %.2f (along %d columns) microns\n", mOTofSpecsConfig.PitchRow * 1e4, mOTofSpecsConfig.NRows, mOTofSpecsConfig.PitchCol * 1e4, mOTofSpecsConfig.NCols); - printf("Passive edges: bottom: %.2f, top: %.2f, left/right: %.2f microns\n", mOTofSpecsConfig.PassiveEdgeReadOut * 1e4, mOTofSpecsConfig.PassiveEdgeTop * 1e4, mOTofSpecsConfig.PassiveEdgeSide * 1e4); - printf("Active/Total size: %.6f/%.6f (rows) %.6f/%.6f (cols) cm\n", mOTofSpecsConfig.ActiveMatrixSizeRows(), mOTofSpecsConfig.SensorSizeRows(), mOTofSpecsConfig.ActiveMatrixSizeCols(), mOTofSpecsConfig.SensorSizeCols()); + // IOTOF specs + printf("IOTOF specs:\n"); + printf("Pixel size: %.2f (along %d rows) %.2f (along %d columns) microns\n", mIOTOFSpecsConfig.PitchRow * 1e4, mIOTOFSpecsConfig.NRows, mIOTOFSpecsConfig.PitchCol * 1e4, mIOTOFSpecsConfig.NCols); + printf("Passive edges: bottom: %.2f, top: %.2f, left/right: %.2f microns\n", mIOTOFSpecsConfig.PassiveEdgeReadOut * 1e4, mIOTOFSpecsConfig.PassiveEdgeTop * 1e4, mIOTOFSpecsConfig.PassiveEdgeSide * 1e4); + printf("Active/Total size: %.6f/%.6f (rows) %.6f/%.6f (cols) cm\n", mIOTOFSpecsConfig.ActiveMatrixSizeRows(), mIOTOFSpecsConfig.SensorSizeRows(), mIOTOFSpecsConfig.ActiveMatrixSizeCols(), mIOTOFSpecsConfig.SensorSizeCols()); } } // namespace iotof From afb1b934f4ae3e2318626cffea598b48a8218cb7 Mon Sep 17 00:00:00 2001 From: maciacco Date: Thu, 6 Aug 2026 15:28:07 +0200 Subject: [PATCH 3/6] remove log print --- Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Detector.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Detector.cxx index d48fb8fa30e3a..568d470d13ed5 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Detector.cxx @@ -377,7 +377,6 @@ bool Detector::ProcessHits(FairVolume* vol) fMC->CurrentVolOffID(4, stave); } -LOG(info) << layN << "\t" << stave << "\t" << substave << "\t" << module << "\t" << chipinmodule; int sensorID = lay; auto& iotofPars = IOTOFBaseParam::Instance(); From 893a2ae59d9ace6a21c6162ace6e51dcf20fbda9 Mon Sep 17 00:00:00 2001 From: maciacco Date: Thu, 6 Aug 2026 16:58:48 +0200 Subject: [PATCH 4/6] avoid duplicatiion of chip parameters --- .../include/IOTOFSimulation/Segmentation.h | 23 ++++++++----------- .../ALICE3/IOTOF/simulation/src/Digitizer.cxx | 5 ++-- .../IOTOF/simulation/src/Segmentation.cxx | 12 ---------- 3 files changed, 13 insertions(+), 27 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Segmentation.h b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Segmentation.h index 1cca70e2ee1e0..ddde28cf7dd7a 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Segmentation.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Segmentation.h @@ -35,7 +35,6 @@ class Segmentation static std::unique_ptr sInstance; public: - ChipSpecifics mIOTOFSpecsConfig; static Segmentation* Instance(); ~Segmentation() = default; @@ -74,7 +73,7 @@ class Segmentation row = col = -1; return; } - const ChipSpecifics& specsConfig = mIOTOFSpecsConfig; + const auto& specsConfig = ChipSpecificsParam::Instance(); xRow = getFirstRowCoordinate(subDetectorID) - row * specsConfig.PitchRow; zCol = col * specsConfig.PitchCol + getFirstColCoordinate(subDetectorID); } @@ -85,7 +84,7 @@ class Segmentation row = col = -1; return; } - const ChipSpecifics& specsConfig = mIOTOFSpecsConfig; + const auto& specsConfig = ChipSpecificsParam::Instance(); loc.SetCoordinates(getFirstRowCoordinate(subDetectorID) - row * specsConfig.PitchRow, T(0.), col * specsConfig.PitchCol + getFirstColCoordinate(subDetectorID)); } template @@ -95,7 +94,7 @@ class Segmentation row = col = -1; return; } - const ChipSpecifics& specsConfig = mIOTOFSpecsConfig; + const auto& specsConfig = ChipSpecificsParam::Instance(); loc[0] = getFirstRowCoordinate(subDetectorID) - row * specsConfig.PitchRow; loc[1] = T(0); loc[2] = col * specsConfig.PitchCol + getFirstColCoordinate(subDetectorID); @@ -110,7 +109,7 @@ class Segmentation row = col = -1; return false; } - const ChipSpecifics& specsConfig = mIOTOFSpecsConfig; + const auto& specsConfig = ChipSpecificsParam::Instance(); if (row < 0 || row >= specsConfig.NRows || col < 0 || col >= specsConfig.NCols) { return false; } @@ -125,7 +124,7 @@ class Segmentation row = col = -1; return false; } - const ChipSpecifics& specsConfig = mIOTOFSpecsConfig; + const auto& specsConfig = ChipSpecificsParam::Instance(); if (row < 0 || row >= specsConfig.NRows || col < 0 || col >= specsConfig.NCols) { return false; } @@ -139,7 +138,7 @@ class Segmentation row = col = -1; return false; } - const ChipSpecifics& specsConfig = mIOTOFSpecsConfig; + const auto& specsConfig = ChipSpecificsParam::Instance(); if (row < 0 || row >= specsConfig.NRows || col < 0 || col >= specsConfig.NCols) { return false; } @@ -149,17 +148,15 @@ class Segmentation float getFirstRowCoordinate(const int subDetectorID) { - const ChipSpecifics& specsConfig = mIOTOFSpecsConfig; + const auto& specsConfig = ChipSpecificsParam::Instance(); return 0.5 * ((specsConfig.ActiveMatrixSizeRows() - specsConfig.PassiveEdgeTop + specsConfig.PassiveEdgeReadOut) - specsConfig.PitchRow); } float getFirstColCoordinate(const int subDetectorID) { - const ChipSpecifics& specsConfig = mIOTOFSpecsConfig; + const auto& specsConfig = ChipSpecificsParam::Instance(); return 0.5 * (specsConfig.PitchCol - specsConfig.ActiveMatrixSizeCols()); } - void print(); - ClassDefNV(Segmentation, 1); // Segmentation class upgrade pixels }; @@ -171,7 +168,7 @@ inline void Segmentation::localToDetectorUnchecked(float xRow, float zCol, int& iRow = iCol = -1; return; } - const ChipSpecifics& specsConfig = mIOTOFSpecsConfig; + const auto& specsConfig = ChipSpecificsParam::Instance(); xRow = 0.5 * (specsConfig.ActiveMatrixSizeRows() - specsConfig.PassiveEdgeTop + specsConfig.PassiveEdgeReadOut) - xRow; // coordinate wrt top edge of Active matrix zCol += 0.5 * specsConfig.ActiveMatrixSizeCols(); // coordinate wrt left edge of Active matrix iRow = int(xRow / specsConfig.PitchRow); @@ -197,7 +194,7 @@ inline bool Segmentation::localToDetector(float xRow, float zCol, int& iRow, int iRow = iCol = -1; return false; } - const ChipSpecifics& specsConfig = mIOTOFSpecsConfig; + const auto& specsConfig = ChipSpecificsParam::Instance(); xRow = 0.5 * (specsConfig.ActiveMatrixSizeRows() - specsConfig.PassiveEdgeTop + specsConfig.PassiveEdgeReadOut) - xRow; // coordinate wrt top edge of Active matrix zCol += 0.5 * specsConfig.ActiveMatrixSizeCols(); // coordinate wrt left edge of Active matrix if (xRow < 0 || xRow >= specsConfig.ActiveMatrixSizeRows() || zCol < 0 || zCol >= specsConfig.ActiveMatrixSizeCols()) { diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx index bb225bd1842fb..5de01639312c4 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Digitizer.cxx @@ -210,8 +210,9 @@ void Digitizer::stepping(const o2::itsmft::Hit& hit, float**& respMatrix, int& r rowStart = std::max(rowStart, 0); colStart = std::max(colStart, 0); - rowEnd = std::min(rowEnd, (sSegmentation->mIOTOFSpecsConfig.NRows) - 1); - colEnd = std::min(colEnd, (sSegmentation->mIOTOFSpecsConfig.NCols) - 1); + const auto& specsConfig = ChipSpecificsParam::Instance(); + rowEnd = std::min(rowEnd, (specsConfig.NRows) - 1); + colEnd = std::min(colEnd, (specsConfig.NCols) - 1); rowSpan = rowEnd - rowStart + 1; colSpan = colEnd - colStart + 1; diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Segmentation.cxx b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Segmentation.cxx index c5b345381136a..a7ec0d708c3b8 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Segmentation.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Segmentation.cxx @@ -36,21 +36,9 @@ Segmentation::Segmentation() { if (sInstance) { printf("Invalid use of public constructor: o2::iotof::Segmentation instance exists\n"); - } else { - auto& iotofChipPars = ChipSpecificsParam::Instance(); - mIOTOFSpecsConfig = ChipSpecifics(iotofChipPars.NCols, iotofChipPars.NRows, iotofChipPars.PitchCol, iotofChipPars.PitchRow, iotofChipPars.PassiveEdgeReadOut, iotofChipPars.PassiveEdgeTop, iotofChipPars.PassiveEdgeSide, iotofChipPars.PixelPassiveEdgeX, iotofChipPars.PixelPassiveEdgeZ, iotofChipPars.SensorLayerThicknessEff, iotofChipPars.SensorLayerThickness); } } -void Segmentation::print() -{ - // IOTOF specs - printf("IOTOF specs:\n"); - printf("Pixel size: %.2f (along %d rows) %.2f (along %d columns) microns\n", mIOTOFSpecsConfig.PitchRow * 1e4, mIOTOFSpecsConfig.NRows, mIOTOFSpecsConfig.PitchCol * 1e4, mIOTOFSpecsConfig.NCols); - printf("Passive edges: bottom: %.2f, top: %.2f, left/right: %.2f microns\n", mIOTOFSpecsConfig.PassiveEdgeReadOut * 1e4, mIOTOFSpecsConfig.PassiveEdgeTop * 1e4, mIOTOFSpecsConfig.PassiveEdgeSide * 1e4); - printf("Active/Total size: %.6f/%.6f (rows) %.6f/%.6f (cols) cm\n", mIOTOFSpecsConfig.ActiveMatrixSizeRows(), mIOTOFSpecsConfig.SensorSizeRows(), mIOTOFSpecsConfig.ActiveMatrixSizeCols(), mIOTOFSpecsConfig.SensorSizeCols()); -} - } // namespace iotof } // namespace o2 From 53c3479e5fe87b0a03cfb53a413d048729a2315e Mon Sep 17 00:00:00 2001 From: maciacco Date: Thu, 6 Aug 2026 17:11:47 +0200 Subject: [PATCH 5/6] build otof stave in a loop --- .../Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx index 84322c807e42e..79b9043d42afd 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx @@ -417,12 +417,12 @@ void OTOFLayer::createLayer(TGeoVolume* motherVolume) } // Now we build a stave from two substave - LOGP(info, "oTOF: Creating substave {}/{} for stave {}/{}", 1, 2, 1, 1); - auto* translation1 = new TGeoTranslation(-0.5 * (subStaveSizeX) + 0.5 * subStavesOverlapX, -0.5 * subStavesDistanceY, 0); - staveVol->AddNode(subStaveVol, 1, translation1); - LOGP(info, "oTOF: Creating substave {}/{} for stave {}/{}", 2, 2, 1, 1); - auto* translation2 = new TGeoTranslation(0.5 * (subStaveSizeX) - 0.5 * subStavesOverlapX, 0.5 * subStavesDistanceY, 0); - staveVol->AddNode(subStaveVol, 2, translation2); + for (int i = 0; i < 2; ++i) { + LOGP(info, "oTOF: Creating substave {}/{} for stave {}/{}", i + 1, 2, 1, 1); + int sign = i > 0 ? 1 : -1; + auto* translation2 = new TGeoTranslation(sign * 0.5 * (subStaveSizeX) - sign * 0.5 * subStavesOverlapX, sign * 0.5 * subStavesDistanceY, 0); + staveVol->AddNode(subStaveVol, i + 1, translation2); + } // We finally put all the staves in the layer for (int i = 0; i < mStaves.first; ++i) { From 6888f7bf9e3c5e2953328bd2558e5e5a58ee18a7 Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Thu, 6 Aug 2026 15:35:02 +0000 Subject: [PATCH 6/6] Please consider the following formatting changes --- Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx index 79b9043d42afd..6db336aba2533 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx @@ -180,7 +180,7 @@ void ITOFLayer::createLayer(TGeoVolume* motherVolume) for (int i = 0; i < 4; ++i) { radiusMax = std::max(radiusMax, std::hypot(uCorners[i] - u0, vCorners[i] - v0)); } - TGeoTube* layer = new TGeoTube(radiusMin, radiusMax, mZLength / 2); // cm, small margins to ensure staves are fully encapsulated in the layer volume + TGeoTube* layer = new TGeoTube(radiusMin, radiusMax, mZLength / 2); // cm, small margins to ensure staves are fully encapsulated in the layer volume TGeoVolume* layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir); setLayerStyle(layerVol); @@ -420,7 +420,7 @@ void OTOFLayer::createLayer(TGeoVolume* motherVolume) for (int i = 0; i < 2; ++i) { LOGP(info, "oTOF: Creating substave {}/{} for stave {}/{}", i + 1, 2, 1, 1); int sign = i > 0 ? 1 : -1; - auto* translation2 = new TGeoTranslation(sign * 0.5 * (subStaveSizeX) - sign * 0.5 * subStavesOverlapX, sign * 0.5 * subStavesDistanceY, 0); + auto* translation2 = new TGeoTranslation(sign * 0.5 * (subStaveSizeX)-sign * 0.5 * subStavesOverlapX, sign * 0.5 * subStavesDistanceY, 0); staveVol->AddNode(subStaveVol, i + 1, translation2); }