Skip to content

Commit a0f94b4

Browse files
GiorgioAlbertoLuciamaciaccoalibuildnjacazio
authored
[ALICE3] IOTOF: Digitization for the TOF3 (#15372)
* one sensor per chip * one sensor per chip also in second layer * iotof segmentation and parameters. Segmentation parameters are stolen from ALPIDE and probably nonsensical * compute number of chips in IOTOF * fill L2G transformation matrices * fix cmakelist * only fill segmentation details if layout is segmented + add function to retrieve chip index * use proper chip id for segmented barrel * refactoring of segmentation, idependent for inner and outer tof, nonstatic * singleton implementation of the segmentation class * realistic values fot the chip segmentation * hit processing in place, tested on A3Studies/Digitization/testDigitization.cpp * clang format * protect against disks for now * added sanity checks * thickness that matches the values currently in O2 * default init of chipspecifics to zero * double typo (half the honor) * Please consider the following formatting changes * Fix row and column assignment in detector functions * Change return type in segmentation function Updated return statement to remove false return value. * Remove return statement from detectorToLocalUnchecked Updated detectorToLocalUnchecked methods to remove return type. * Remove Mat3D alias from GeometryTGeo class Removed the alias 'Mat3D' for 'o2::math_utils::Transform3D'. * Replace matrix transformation with Transform3D --------- Co-authored-by: maciacco <mario.ciacco@cern.ch> Co-authored-by: ALICE Action Bot <alibuild@cern.ch> Co-authored-by: Nicolò Jacazio <njacazio@users.noreply.github.com>
1 parent 1cb2e46 commit a0f94b4

10 files changed

Lines changed: 627 additions & 14 deletions

File tree

Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/GeometryTGeo.h

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ namespace iotof
2222
class GeometryTGeo : public o2::detectors::DetMatrixCache
2323
{
2424
public:
25+
using DetMatrixCache::getMatrixL2G;
26+
2527
GeometryTGeo(bool build = false, int loadTrans = 0);
2628
void Build(int loadTrans);
2729
void fillMatrixCache(int mask);
@@ -79,7 +81,25 @@ class GeometryTGeo : public o2::detectors::DetMatrixCache
7981
static const char* composeBTOFSymNameChip(int d, int lr);
8082
static const char* composeBTOFSymNameSensor(int d, int layer);
8183

84+
int getIOTOFFirstChipIndex(int lay) const;
85+
int getIOTOFLayer(int index) const;
86+
int getIOTOFChipIndex(int lay, int sta, int mod, int chip) const;
87+
bool getIOTOFChipId(int index, int& lay, int& sta, int& mod, int& chip) const;
88+
89+
/// Get the transformation matrix of the SENSOR (not necessary the same as the chip)
90+
/// for a given chip 'index' by querying the TGeoManager
91+
TGeoHMatrix* extractMatrixSensor(int index) const;
92+
93+
TString getMatrixPath(int index) const;
94+
8295
protected:
96+
// Determine the number of active parts in the geometry
97+
int extractNumberOfStavesIOTOF(int lay) const;
98+
int extractNumberOfModulesIOTOF(int lay) const;
99+
int extractNumberOfChipsPerModuleIOTOF(int lay) const;
100+
int extractNumberOfChipsFTOF() const;
101+
int extractNumberOfChipsBTOF() const;
102+
83103
// i/oTOF mother volume
84104
static std::string sIOTOFVolumeName;
85105

@@ -107,10 +127,24 @@ class GeometryTGeo : public o2::detectors::DetMatrixCache
107127
static std::string sBTOFChipName;
108128
static std::string sBTOFSensorName;
109129

130+
// Inner/outer TOF
131+
int mNumberOfStavesIOTOF[2];
132+
int mNumberOfModulesIOTOF[2];
133+
int mNumberOfChipsPerModuleIOTOF[2];
134+
int mNumberOfChipsPerStaveIOTOF[2];
135+
int mNumberOfChipsIOTOF[2];
136+
int mLastChipIndex[2];
137+
138+
// Forward TOF
139+
int mNumberOfChipsFTOF;
140+
141+
// Backward TOF
142+
int mNumberOfChipsBTOF;
143+
110144
private:
111145
static std::unique_ptr<o2::iotof::GeometryTGeo> sInstance;
112146
};
113147

114148
} // namespace iotof
115149
} // namespace o2
116-
#endif
150+
#endif

Detectors/Upgrades/ALICE3/IOTOF/base/include/IOTOFBase/IOTOFBaseParam.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,24 @@ namespace o2
2020
namespace iotof
2121
{
2222

23+
struct ChipSpecifics {
24+
int NCols = 0;
25+
int NRows = 0;
26+
float PitchCol = 0.;
27+
float PitchRow = 0.;
28+
float PassiveEdgeReadOut = 0.;
29+
float PassiveEdgeTop = 0.;
30+
float PassiveEdgeSide = 0.;
31+
float SensorLayerThicknessEff = 0.;
32+
float SensorLayerThickness = 0.;
33+
34+
int NPixels() const { return NCols * NRows; }
35+
float ActiveMatrixSizeCols() const { return PitchCol * NCols; }
36+
float ActiveMatrixSizeRows() const { return PitchRow * NRows; }
37+
float SensorSizeCols() const { return ActiveMatrixSizeCols() + 2 * PassiveEdgeSide; }
38+
float SensorSizeRows() const { return ActiveMatrixSizeRows() + PassiveEdgeTop + PassiveEdgeReadOut; }
39+
};
40+
2341
struct IOTOFBaseParam : public o2::conf::ConfigurableParamHelper<IOTOFBaseParam> {
2442
bool enableInnerTOF = true; // Enable Inner TOF layer
2543
bool enableOuterTOF = true; // Enable Outer TOF layer
@@ -31,6 +49,9 @@ struct IOTOFBaseParam : public o2::conf::ConfigurableParamHelper<IOTOFBaseParam>
3149
float x2x0 = 0.02f; // thickness expressed in radiation length, for all layers for the moment
3250
float sensorThickness = 0.0050f; // thickness of the sensor in cm, for all layers for the moment, the default is set to 50 microns
3351

52+
ChipSpecifics iTofChipSpecifics{258, 271, 250.00e-4, 100.00e-4, 0.00f, 0.00e-4, 0.00e-4, 50.e-4, 50.e-4};
53+
ChipSpecifics oTofChipSpecifics{251, 487, 250.00e-4, 100.00e-4, 0.00f, 0.00e-4, 106.48e-4, 50.e-4, 50.e-4};
54+
3455
O2ParamDef(IOTOFBaseParam, "IOTOFBase");
3556
};
3657

Detectors/Upgrades/ALICE3/IOTOF/base/src/GeometryTGeo.cxx

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
// or submit itself to any jurisdiction.
1111

1212
#include <IOTOFBase/GeometryTGeo.h>
13+
#include <IOTOFBase/IOTOFBaseParam.h>
1314
#include <TGeoManager.h>
1415

1516
namespace o2
@@ -55,6 +56,171 @@ GeometryTGeo::GeometryTGeo(bool build, int loadTrans) : DetMatrixCache()
5556
}
5657
}
5758

59+
int GeometryTGeo::extractNumberOfStavesIOTOF(int lay) const
60+
{
61+
int numberOfStaves{0};
62+
63+
std::string layName = lay == 0 ? GeometryTGeo::getITOFLayerPattern() : GeometryTGeo::getOTOFLayerPattern();
64+
TGeoVolume* layV = gGeoManager->GetVolume(layName.c_str());
65+
if (layV == nullptr) {
66+
LOG(fatal) << "Can't find volume " << layName;
67+
return -1;
68+
}
69+
70+
TObjArray* nodes = layV->GetNodes();
71+
int nNodes = nodes->GetEntriesFast();
72+
73+
for (int j{0}; j < nNodes; ++j) {
74+
if (strstr(nodes->At(j)->GetName(), lay == 0 ? GeometryTGeo::getITOFStavePattern() : GeometryTGeo::getOTOFStavePattern()) != nullptr) {
75+
numberOfStaves++;
76+
}
77+
}
78+
79+
return numberOfStaves;
80+
}
81+
82+
int GeometryTGeo::extractNumberOfModulesIOTOF(int lay) const
83+
{
84+
int numberOfModules{0};
85+
86+
std::string staveName = lay == 0 ? GeometryTGeo::getITOFStavePattern() : GeometryTGeo::getOTOFStavePattern();
87+
TGeoVolume* staveV = gGeoManager->GetVolume(staveName.c_str());
88+
if (staveV == nullptr) {
89+
LOG(fatal) << "Can't find volume " << staveName;
90+
return -1;
91+
}
92+
93+
TObjArray* nodes = staveV->GetNodes();
94+
int nNodes = nodes->GetEntriesFast();
95+
96+
for (int j{0}; j < nNodes; ++j) {
97+
if (strstr(nodes->At(j)->GetName(), lay == 0 ? GeometryTGeo::getITOFModulePattern() : GeometryTGeo::getOTOFModulePattern()) != nullptr) {
98+
numberOfModules++;
99+
}
100+
}
101+
102+
return numberOfModules;
103+
}
104+
105+
int GeometryTGeo::extractNumberOfChipsPerModuleIOTOF(int lay) const
106+
{
107+
int numberOfChips{0};
108+
109+
std::string moduleName = lay == 0 ? GeometryTGeo::getITOFModulePattern() : GeometryTGeo::getOTOFModulePattern();
110+
TGeoVolume* moduleV = gGeoManager->GetVolume(moduleName.c_str());
111+
if (moduleV == nullptr) {
112+
LOG(fatal) << "Can't find volume " << moduleName;
113+
return -1;
114+
}
115+
116+
TObjArray* nodes = moduleV->GetNodes();
117+
int nNodes = nodes->GetEntriesFast();
118+
119+
for (int j{0}; j < nNodes; ++j) {
120+
if (strstr(nodes->At(j)->GetName(), lay == 0 ? GeometryTGeo::getITOFChipPattern() : GeometryTGeo::getOTOFChipPattern()) != nullptr) {
121+
numberOfChips++;
122+
}
123+
}
124+
125+
return numberOfChips;
126+
}
127+
128+
int GeometryTGeo::extractNumberOfChipsFTOF() const
129+
{
130+
return 0;
131+
}
132+
133+
int GeometryTGeo::extractNumberOfChipsBTOF() const
134+
{
135+
return 0;
136+
}
137+
138+
int GeometryTGeo::getIOTOFFirstChipIndex(int lay) const
139+
{
140+
return lay == 0 ? 0 : mLastChipIndex[0] + 1;
141+
}
142+
143+
int GeometryTGeo::getIOTOFLayer(int index) const
144+
{
145+
if (index < 0 || index > mLastChipIndex[1]) {
146+
LOG(fatal) << "Invalid chip index " << index;
147+
return -1;
148+
}
149+
return index > mLastChipIndex[0] ? 1 : 0;
150+
}
151+
152+
int GeometryTGeo::getIOTOFChipIndex(int lay, int sta, int mod, int chip) const
153+
{
154+
return getIOTOFFirstChipIndex(lay) + (sta - 1) * mNumberOfChipsPerStaveIOTOF[lay] + (mod - 1) * mNumberOfChipsPerModuleIOTOF[lay] + (chip - 1);
155+
}
156+
157+
bool GeometryTGeo::getIOTOFChipId(int index, int& lay, int& sta, int& mod, int& chip) const
158+
{
159+
lay = getIOTOFLayer(index);
160+
index -= getIOTOFFirstChipIndex(lay);
161+
sta = mNumberOfStavesIOTOF[lay] > 0 ? index / mNumberOfChipsPerStaveIOTOF[lay] : -1;
162+
index %= mNumberOfChipsPerStaveIOTOF[lay];
163+
mod = mNumberOfModulesIOTOF[lay] > 0 ? index / mNumberOfChipsPerModuleIOTOF[lay] : -1;
164+
chip = index % mNumberOfChipsPerModuleIOTOF[lay];
165+
return true;
166+
}
167+
168+
TString GeometryTGeo::getMatrixPath(int index) const
169+
{
170+
int lay, sta, mod, chip;
171+
getIOTOFChipId(index, lay, sta, mod, chip);
172+
173+
TString path = Form("/cave_1/barrel_1/%s_2/", GeometryTGeo::getIOTOFVolPattern());
174+
sta += 1;
175+
mod += 1;
176+
chip += 1;
177+
178+
if (lay == 0) {
179+
path += Form("%s_1/", GeometryTGeo::getITOFLayerPattern());
180+
if (mNumberOfStavesIOTOF[lay] > 0)
181+
path += Form("%s_%d/", GeometryTGeo::getITOFStavePattern(), sta);
182+
if (mNumberOfModulesIOTOF[lay] > 0)
183+
path += Form("%s_%d/", GeometryTGeo::getITOFModulePattern(), mod);
184+
if (mNumberOfChipsPerModuleIOTOF[lay] > 0)
185+
path += Form("%s_%d/%s_1", GeometryTGeo::getITOFChipPattern(), chip, GeometryTGeo::getITOFSensorPattern());
186+
} else {
187+
path += Form("%s_1/", GeometryTGeo::getOTOFLayerPattern());
188+
if (mNumberOfStavesIOTOF[lay] > 0)
189+
path += Form("%s_%d/", GeometryTGeo::getOTOFStavePattern(), sta);
190+
if (mNumberOfModulesIOTOF[lay] > 0)
191+
path += Form("%s_%d/", GeometryTGeo::getOTOFModulePattern(), mod);
192+
if (mNumberOfChipsPerModuleIOTOF[lay] > 0)
193+
path += Form("%s_%d/%s_1", GeometryTGeo::getOTOFChipPattern(), chip, GeometryTGeo::getOTOFSensorPattern());
194+
}
195+
196+
return path;
197+
}
198+
199+
TGeoHMatrix* GeometryTGeo::extractMatrixSensor(int index) const
200+
{
201+
auto path = getMatrixPath(index);
202+
203+
static TGeoHMatrix matTmp;
204+
gGeoManager->PushPath();
205+
206+
if (!gGeoManager->cd(path.Data())) {
207+
gGeoManager->PopPath();
208+
LOG(error) << "Error in cd-ing to " << path.Data();
209+
return nullptr;
210+
}
211+
212+
matTmp = *gGeoManager->GetCurrentMatrix();
213+
// LOG(info) << "Path = " << path.Data();
214+
215+
// Restore the modeler state
216+
gGeoManager->PopPath();
217+
218+
// account for the difference between physical sensitive layer (where charge collection is simulated) and effective sensor thicknesses
219+
// TODO: apply translation by the effective sensor thickness, not yet done (see ITS)
220+
221+
return &matTmp;
222+
}
223+
58224
void GeometryTGeo::Build(int loadTrans)
59225
{
60226
if (isBuilt()) {
@@ -66,11 +232,58 @@ void GeometryTGeo::Build(int loadTrans)
66232
LOGP(fatal, "Geometry is not loaded");
67233
}
68234

235+
auto& iotofPars = IOTOFBaseParam::Instance();
236+
if (!iotofPars.segmentedInnerTOF && !iotofPars.segmentedOuterTOF) {
237+
return;
238+
}
239+
240+
// Inner/outer TOF
241+
for (int j{0}; j < 2; ++j) {
242+
mNumberOfStavesIOTOF[j] = extractNumberOfStavesIOTOF(j);
243+
mNumberOfModulesIOTOF[j] = extractNumberOfModulesIOTOF(j);
244+
mNumberOfChipsPerModuleIOTOF[j] = extractNumberOfChipsPerModuleIOTOF(j);
245+
}
246+
247+
// Forward TOF
248+
mNumberOfChipsFTOF = extractNumberOfChipsFTOF();
249+
250+
// Backward TOF
251+
mNumberOfChipsBTOF = extractNumberOfChipsBTOF();
252+
253+
int numberOfChips{0};
254+
for (int j{0}; j < 2; ++j) {
255+
mNumberOfChipsPerStaveIOTOF[j] = mNumberOfModulesIOTOF[j] * mNumberOfChipsPerModuleIOTOF[j];
256+
mNumberOfChipsIOTOF[j] = mNumberOfStavesIOTOF[j] * mNumberOfChipsPerStaveIOTOF[j];
257+
numberOfChips += mNumberOfChipsIOTOF[j];
258+
mLastChipIndex[j] = numberOfChips - 1;
259+
}
260+
261+
LOG(info) << "numberOfChipsITOF = " << mNumberOfChipsIOTOF[0] << ", numberOfChipsOTOF = " << mNumberOfChipsIOTOF[1] << ", numberOfChips = " << numberOfChips << ", mNumberOfChipesPerStaveITOF" << mNumberOfChipsPerStaveIOTOF[0];
262+
263+
setSize(numberOfChips);
69264
fillMatrixCache(loadTrans);
265+
// fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::L2G));
70266
}
71267

72268
void GeometryTGeo::fillMatrixCache(int mask)
73269
{
270+
if (mSize < 1) {
271+
LOG(warning) << "The method Build was not called yet";
272+
Build(mask);
273+
return;
274+
}
275+
276+
if ((mask & o2::math_utils::bit2Mask(o2::math_utils::TransformType::L2G)) && !getCacheL2G().isFilled()) {
277+
// Matrices for Local (Sensor!!! rather than the full chip) to Global frame transformation
278+
LOG(info) << "Loading " << getName() << " L2G matrices from TGeo; there are " << mSize << " matrices";
279+
auto& cacheL2G = getCacheL2G();
280+
cacheL2G.setSize(mSize);
281+
282+
for (int i = 0; i < mSize; i++) {
283+
TGeoHMatrix* hm = extractMatrixSensor(i);
284+
cacheL2G.setMatrix(o2::math_utils::Transform3D(*hm), i);
285+
}
286+
}
74287
}
75288

76289
GeometryTGeo* GeometryTGeo::Instance()

Detectors/Upgrades/ALICE3/IOTOF/simulation/CMakeLists.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,15 @@ o2_add_library(IOTOFSimulation
1414
src/Detector.cxx
1515
src/Digitizer.cxx
1616
# src/IOTOFServices.cxx
17+
src/Segmentation.cxx
1718
PUBLIC_LINK_LIBRARIES O2::IOTOFBase
1819
O2::DataFormatsIOTOF
1920
O2::ITSMFTSimulation)
2021

2122
o2_target_root_dictionary(IOTOFSimulation
2223
HEADERS include/IOTOFSimulation/Detector.h
2324
include/IOTOFSimulation/Layer.h
24-
include/IOTOFSimulation/Digitizer.h)
25-
# include/IOTOFSimulation/IOTOFServices.h)
25+
include/IOTOFSimulation/Digitizer.h
26+
# include/IOTOFSimulation/IOTOFServices.h
27+
include/IOTOFSimulation/Segmentation.h
28+
)

Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Digitizer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "SimulationDataFormat/MCCompLabel.h"
2828
#include "SimulationDataFormat/MCTruthContainer.h"
2929
#include "IOTOFBase/GeometryTGeo.h"
30+
#include "IOTOFSimulation/Segmentation.h"
3031

3132
namespace o2::iotof
3233
{
@@ -105,6 +106,8 @@ class Digitizer
105106
float mTimeResolution = 0.020f; ///< time resolution sigma in ns (20 ps default)
106107
float mEfficiency = 0.98f; ///< detection efficiency
107108
float mEnergyToCharge = 3.6e-9f; ///< energy loss to electrons conversion (3.6 eV per e-h pair in Si)
109+
110+
static o2::iotof::Segmentation* sSegmentation; ///< IOTOF segmentation instance (singleton)
108111
};
109112
} // namespace o2::iotof
110113

0 commit comments

Comments
 (0)