From d6d1f3c7c4ba493ce351df03767da430029e34b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Tue, 31 Mar 2026 18:03:06 +0200 Subject: [PATCH 1/8] Enhance Layer class with sensor thickness handling Added sensor thickness parameter and validation checks. --- .../ALICE3/IOTOF/simulation/src/Layer.cxx | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx index 66d0b2959c8bd..3eaedaad960cb 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx @@ -28,19 +28,20 @@ namespace o2 namespace iotof { Layer::Layer(std::string layerName, float rInn, float rOut, float zLength, float zOffset, float layerX2X0, - int layout, int nStaves, float staveSize, double staveTiltAngle, int modulesPerStave) + int layout, int nStaves, float staveSize, double staveTiltAngle, int modulesPerStave, float sensorThickness) : mLayerName(layerName), mInnerRadius(rInn), mOuterRadius(rOut), mZLength(zLength), mZOffset(zOffset), + mSensorThickness(sensorThickness), mX2X0(layerX2X0), mLayout(layout), mStaves(nStaves, staveSize), mModulesPerStave(modulesPerStave), mTiltAngle(staveTiltAngle) { - const float Si_X0 = 9.5f; + const float Si_X0 = 9.5f; // cm, radiation length of silicon mChipThickness = mX2X0 * Si_X0; std::string name = ""; switch (layout) { @@ -76,6 +77,12 @@ Layer::Layer(std::string layerName, float rInn, float rOut, float zLength, float if ((mTiltAngle < 0.0 || mTiltAngle > 90.0) && (layout == kBarrelSegmented || layout == kDiskSegmented)) { LOG(fatal) << "Invalid configuration: tilt angle " << mTiltAngle << " is too large, it must be between 0 and 90 degrees"; } + if (mSensorThickness < 0.0f || mSensorThickness > mChipThickness) { + LOG(fatal) << "Invalid configuration: sensor thickness " << mSensorThickness << " cm is out of range (0, " << mChipThickness << ") cm"; + } + if (sensorThickness > 0.0f && (layout == kBarrel || layout == kDisk)) { + LOG(fatal) << "Invalid configuration: sensor thickness " << mSensorThickness << " cm is set for non-segmented layout, it should be 0"; + } LOGP(info, "TOF: Creating {} layer: rInner: {} (cm) rOuter: {} (cm) zLength: {} (cm) zOffset: {} x2X0: {}", name.c_str(), mInnerRadius, mOuterRadius, mZLength, mZOffset, mX2X0); } @@ -180,10 +187,13 @@ void ITOFLayer::createLayer(TGeoVolume* motherVolume) setModuleStyle(moduleVol); // Now we create the volume of the chip, which is the same for all modules - const int chipsPerModuleX = 2; // we assume that each module is divided in 2 chips along the x direction - const int chipsPerModuleZ = 2; // we assume that each module is divided in 2 chips along the z direction - const double chipSizeX = moduleSizeX / chipsPerModuleX; // cm - const double chipSizeY = moduleSizeY; // cm + const int chipsPerModuleX = 2; // we assume that each module is divided in 2 chips along the x direction + const int chipsPerModuleZ = 2; // we assume that each module is divided in 2 chips along the z direction + const double chipSizeX = moduleSizeX / chipsPerModuleX; // cm + const double chipSizeY = moduleSizeY - mSensorThickness; // cm + if (chipSizeY <= 0) { + LOG(fatal) << "Invalid configuration: sensor thickness " << mSensorThickness << " cm is too large for module size " << moduleSizeY << " cm, it leaves no space for the chip"; + } const double chipSizeZ = moduleSizeZ / chipsPerModuleZ; // cm TGeoBBox* chip = new TGeoBBox(chipSizeX * 0.5, chipSizeY * 0.5, chipSizeZ * 0.5); TGeoVolume* chipVol = new TGeoVolume(chipName, chip, medSi); @@ -193,7 +203,7 @@ void ITOFLayer::createLayer(TGeoVolume* motherVolume) const int sensorsPerChipX = 2; // we assume that each chip is divided in 2 sensors along the x direction const int sensorsPerChipZ = 2; // we assume that each chip is divided in 2 sensors along the z direction const double sensorSizeX = chipSizeX / sensorsPerChipX; // cm - const double sensorSizeY = chipSizeY; // cm + const double sensorSizeY = mSensorThickness; // cm const double sensorSizeZ = chipSizeZ / sensorsPerChipZ; // cm TGeoBBox* sensor = new TGeoBBox(sensorSizeX * 0.5, sensorSizeY * 0.5, sensorSizeZ * 0.5); TGeoVolume* sensVol = new TGeoVolume(sensName, sensor, medSi); From 15484d690e5d6c45aab2c55c5ef9c5e954c59738 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Tue, 31 Mar 2026 18:03:45 +0200 Subject: [PATCH 2/8] Add sensor thickness to Layer class Added sensor thickness parameter to Layer constructor and updated member variables accordingly. --- .../IOTOF/simulation/include/IOTOFSimulation/Layer.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Layer.h b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Layer.h index 29542810b8021..dc9fedf439a11 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Layer.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Layer.h @@ -26,7 +26,7 @@ class Layer public: Layer() = default; Layer(std::string layerName, float rInn, float rOut, float zLength, float zOffset, float layerX2X0, - int layout = kBarrel, int nStaves = 0, float staveSize = 0.0, double staveTiltAngle = 0.0, int modulesPerStave = 0); + int layout = kBarrel, int nStaves = 0, float staveSize = 0.0, double staveTiltAngle = 0.0, int modulesPerStave = 0, float sensorThickness = 0.0f); ~Layer() = default; auto getInnerRadius() const { return mInnerRadius; } @@ -52,8 +52,9 @@ class Layer float mZLength; float mZOffset{0.f}; // Of use when fwd layers float mX2X0; - float mChipThickness; - int mLayout{kBarrel}; // Identifier of the type of layer layout (barrel, disk, barrel segmented, disk segmented) + float mChipThickness; // Thickness of the chip in cm, derived from mX2X0 and the radiation length of silicon + float mSensorThickness; // Thickness of the sensor in cm, to be subtracted from the chip thickness to get the total module thickness + int mLayout{kBarrel}; // Identifier of the type of layer layout (barrel, disk, barrel segmented, disk segmented) // To be used only in case of the segmented layout, to define the number of staves in phi (for barrel) or in r (for disk) std::pair mStaves{0, 0.0f}; // Number and size of staves in phi (for barrel) or in r (for disk) in case of segmented layout int mModulesPerStave{0}; // Number of modules along a stave @@ -92,4 +93,4 @@ class BTOFLayer : public Layer } // namespace iotof } // namespace o2 -#endif // ALICEO2_IOTOF_LAYER_H \ No newline at end of file +#endif // ALICEO2_IOTOF_LAYER_H From aa6a0bc70d65c772565e0cd40d9ad58384fc0421 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Tue, 31 Mar 2026 18:04:12 +0200 Subject: [PATCH 3/8] Modify configLayers to include sensorThickness Added sensorThickness parameter to configLayers function for ITOF and OTOF layers. --- Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Detector.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Detector.cxx index d6417eba22041..59b914a3dd076 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Detector.cxx @@ -58,7 +58,7 @@ void Detector::ConstructGeometry() } void Detector::configLayers(bool itof, bool otof, bool ftof, bool btof, std::string pattern, bool itofSegmented, bool otofSegmented, - const float x2x0) + const float x2x0, const float sensorThickness) { const std::pair dInnerTof = {21.f, 129.f}; // Radius and length @@ -102,7 +102,7 @@ void Detector::configLayers(bool itof, bool otof, bool ftof, bool btof, std::str const int modulesPerStave = itofSegmented ? 10 : 0; // number of modules per stave in segmented case mITOFLayer = ITOFLayer(name, dInnerTof.first, 0.f, dInnerTof.second, 0.f, x2x0, itofSegmented ? ITOFLayer::kBarrelSegmented : ITOFLayer::kBarrel, - nStaves, staveWidth, staveTiltAngle, modulesPerStave); + nStaves, staveWidth, staveTiltAngle, modulesPerStave, itofSegmented ? sensorThickness : 0.0f); } if (otof) { // oTOF const std::string name = GeometryTGeo::getOTOFLayerPattern(); @@ -112,7 +112,7 @@ void Detector::configLayers(bool itof, bool otof, bool ftof, bool btof, std::str const int modulesPerStave = otofSegmented ? 54 : 0; // number of modules per stave in segmented case mOTOFLayer = OTOFLayer(name, dOuterTof.first, 0.f, dOuterTof.second, 0.f, x2x0, otofSegmented ? OTOFLayer::kBarrelSegmented : OTOFLayer::kBarrel, - nStaves, staveWidth, staveTiltAngle, modulesPerStave); + nStaves, staveWidth, staveTiltAngle, modulesPerStave, otofSegmented ? sensorThickness : 0.0f); } if (ftof) { const std::string name = GeometryTGeo::getFTOFLayerPattern(); From 1b1788917ed4c934afb652e03714a29450571ada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Tue, 31 Mar 2026 18:04:31 +0200 Subject: [PATCH 4/8] Update Detector.h --- .../IOTOF/simulation/include/IOTOFSimulation/Detector.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Detector.h b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Detector.h index acf754e1b1fa8..34097020c42ff 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Detector.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Detector.h @@ -60,7 +60,7 @@ class Detector : public o2::base::DetImpl return nullptr; } - void configLayers(bool itof = true, bool otof = true, bool ftof = true, bool btof = true, std::string pattern = "", bool itofSegmented = false, bool otofSegmented = false, const float x2x0 = 0.02f); + void configLayers(bool itof = true, bool otof = true, bool ftof = true, bool btof = true, std::string pattern = "", bool itofSegmented = false, bool otofSegmented = false, const float x2x0 = 0.02f, const float sensorThickness = 0.0050f); void configServices(); void createMaterials(); @@ -104,4 +104,4 @@ struct UseShm { } // namespace base } // namespace o2 #endif -#endif \ No newline at end of file +#endif From fa9e24c0049029bf477f595bd74316152ab93559 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Tue, 31 Mar 2026 18:04:56 +0200 Subject: [PATCH 5/8] Modify thickness parameters in IOTOFBaseParam.h Updated the radiation length thickness and added sensor thickness parameter. --- .../ALICE3/IOTOF/base/include/IOTOFBase/IOTOFBaseParam.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/IOTOFBaseParam.h b/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/IOTOFBaseParam.h index 1f1a26b79077e..c1a9578484c17 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/IOTOFBaseParam.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/IOTOFBaseParam.h @@ -28,7 +28,8 @@ struct IOTOFBaseParam : public o2::conf::ConfigurableParamHelper std::string detectorPattern = ""; // Layouts of the detector bool segmentedInnerTOF = false; // If the inner TOF layer is segmented bool segmentedOuterTOF = false; // If the outer TOF layer is segmented - float x2x0 = 0.000527f; // thickness expressed in radiation length, for all layers for the moment + float x2x0 = 0.02f; // thickness expressed in radiation length, for all layers for the moment + float sensorThickness = 0.0050f; // thickness of the sensor in cm, for all layers for the moment, the default is set to 50 microns O2ParamDef(IOTOFBaseParam, "IOTOFBase"); }; From c32ce1ea9fdbb8e96d11296de8dd2d663b0ccb33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Tue, 31 Mar 2026 18:06:06 +0200 Subject: [PATCH 6/8] Revise options table in README for IOTOF Updated options table with new sensor thickness parameter and corrected default value for x2x0. --- Detectors/Upgrades/ALICE3/IOTOF/README.md | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/README.md b/Detectors/Upgrades/ALICE3/IOTOF/README.md index d7a954c4718fe..e52b5e2379e9c 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/README.md +++ b/Detectors/Upgrades/ALICE3/IOTOF/README.md @@ -14,16 +14,18 @@ Configurables for various sub-detectors are presented in the following Table: [link to definitions](./base/include/IOTOFBase/IOTOFBaseParam.h) -| Options | Choices | Comments | -| ----------------------------- | ---------------------------------------------------------------- | ---------------------------------------------- | -| `IOTOFBase.enableInnerTOF` | `true` (default), `false` | Enable inner TOF barrel layer | -| `IOTOFBase.enableOuterTOF` | `true` (default), `false` | Enable outer TOF barrel layer | -| `IOTOFBase.enableForwardTOF` | `true` (default), `false` | Enable forward TOF endcap | -| `IOTOFBase.enableBackwardTOF` | `true` (default), `false` | Enable backward TOF endcap | -| `IOTOFBase.segmentedInnerTOF` | `false` (default), `true` | Use segmented geometry for inner TOF | -| `IOTOFBase.segmentedOuterTOF` | `false` (default), `true` | Use segmented geometry for outer TOF | -| `IOTOFBase.detectorPattern` | ` ` (default), `v3b`, `v3b1a`, `v3b1b`, `v3b2a`, `v3b2b`, `v3b3` | Optional layout pattern | -| `IOTOFBase.x2x0` | `0.000527` (default) | Chip thickness in fractions of the rad. lenght | +| Options | Choices | Comments | +| ----------------------------- | ---------------------------------------------------------------- | -------------------------------------------------------------------------- | +| `IOTOFBase.enableInnerTOF` | `true` (default), `false` | Enable inner TOF barrel layer | +| `IOTOFBase.enableOuterTOF` | `true` (default), `false` | Enable outer TOF barrel layer | +| `IOTOFBase.enableForwardTOF` | `true` (default), `false` | Enable forward TOF endcap | +| `IOTOFBase.enableBackwardTOF` | `true` (default), `false` | Enable backward TOF endcap | +| `IOTOFBase.segmentedInnerTOF` | `false` (default), `true` | Use segmented geometry for inner TOF | +| `IOTOFBase.segmentedOuterTOF` | `false` (default), `true` | Use segmented geometry for outer TOF | +| `IOTOFBase.detectorPattern` | ` ` (default), `v3b`, `v3b1a`, `v3b1b`, `v3b2a`, `v3b2b`, `v3b3` | Optional layout pattern | +| `IOTOFBase.x2x0` | `0.02` (default) | Chip thickness in fractions of the rad. lenght | +| `IOTOFBase.sensorThickness` | `0.0050` (default) | Sensor thickness in cm, can be at maximum equivalent to the chip thickness | + For example, a geometry with fully cylindrical tracker barrel (for all layers in VD, ML and OT) can be obtained by From b666bb2c87a42b5be7442cb5bbb494eb41a98029 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Tue, 31 Mar 2026 19:22:08 +0200 Subject: [PATCH 7/8] Simplify chip size calculation in Layer.cxx Removed sensor thickness adjustment for chip size calculation. --- .../Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx index 3eaedaad960cb..44c448b1be40b 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx @@ -187,13 +187,10 @@ void ITOFLayer::createLayer(TGeoVolume* motherVolume) setModuleStyle(moduleVol); // Now we create the volume of the chip, which is the same for all modules - const int chipsPerModuleX = 2; // we assume that each module is divided in 2 chips along the x direction - const int chipsPerModuleZ = 2; // we assume that each module is divided in 2 chips along the z direction - const double chipSizeX = moduleSizeX / chipsPerModuleX; // cm - const double chipSizeY = moduleSizeY - mSensorThickness; // cm - if (chipSizeY <= 0) { - LOG(fatal) << "Invalid configuration: sensor thickness " << mSensorThickness << " cm is too large for module size " << moduleSizeY << " cm, it leaves no space for the chip"; - } + const int chipsPerModuleX = 2; // we assume that each module is divided in 2 chips along the x direction + const int chipsPerModuleZ = 2; // we assume that each module is divided in 2 chips along the z direction + const double chipSizeX = moduleSizeX / chipsPerModuleX; // cm + const double chipSizeY = moduleSizeY; // cm const double chipSizeZ = moduleSizeZ / chipsPerModuleZ; // cm TGeoBBox* chip = new TGeoBBox(chipSizeX * 0.5, chipSizeY * 0.5, chipSizeZ * 0.5); TGeoVolume* chipVol = new TGeoVolume(chipName, chip, medSi); From d4b501593dbccbdeb6d3e958409ddcc84b1743e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Tue, 31 Mar 2026 19:23:45 +0200 Subject: [PATCH 8/8] Update sensor size calculation in Layer.cxx --- Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx index 44c448b1be40b..b603d2a4a423b 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/src/Layer.cxx @@ -334,7 +334,7 @@ void OTOFLayer::createLayer(TGeoVolume* motherVolume) const int sensorsPerChipX = 2; // we assume that each chip is divided in 2 sensors along the x direction const int sensorsPerChipZ = 2; // we assume that each chip is divided in 2 sensors along the z direction const double sensorSizeX = chipSizeX / sensorsPerChipX; // cm - const double sensorSizeY = chipSizeY; // cm + const double sensorSizeY = mSensorThickness; // cm const double sensorSizeZ = chipSizeZ / sensorsPerChipZ; // cm TGeoBBox* sensor = new TGeoBBox(sensorSizeX * 0.5, sensorSizeY * 0.5, sensorSizeZ * 0.5); TGeoVolume* sensVol = new TGeoVolume(sensName, sensor, medSi);