Project
Loading...
Searching...
No Matches
VDLayer.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
14
15#include "Framework/Logger.h"
16
17#include "TGeoTube.h"
18#include "TGeoBBox.h"
19#include "TGeoVolume.h"
20#include "TGeoMatrix.h"
21#include "TGeoManager.h"
22
23#include "TMath.h"
24
25namespace o2
26{
27namespace trk
28{
29// Base layer constructor
30VDLayer::VDLayer(int layerNumber, const std::string& layerName, double layerX2X0)
31 : mLayerNumber(layerNumber), mLayerName(layerName), mX2X0(layerX2X0), mModuleWidth(4.54)
32{
33 constexpr double kSiX0_cm = 9.5; // Radiation length of Silicon in cm
34 mChipThickness = mX2X0 * kSiX0_cm;
35}
36
37// VDCylindricalLayer constructor
38VDCylindricalLayer::VDCylindricalLayer(int layerNumber, const std::string& layerName, double layerX2X0, double radius,
39 double phiSpanDeg, double lengthZ, double lengthSensZ)
40 : VDLayer(layerNumber, layerName, layerX2X0), mRadius(radius), mPhiSpanDeg(phiSpanDeg), mLengthZ(lengthZ), mLengthSensZ(lengthSensZ)
41{
42 LOGP(info, "Creating VD cylindrical layer: id: {} name: {} x2X0: {} radius: {} phiSpanDeg: {} lengthZ: {} lengthSensZ: {} chipThickness = {} cm",
43 mLayerNumber, layerName, mX2X0, radius, phiSpanDeg, lengthZ, lengthSensZ, mChipThickness);
44}
45
46// VDRectangularLayer constructor
47VDRectangularLayer::VDRectangularLayer(int layerNumber, const std::string& layerName, double layerX2X0,
48 double width, double lengthZ, double lengthSensZ)
49 : VDLayer(layerNumber, layerName, layerX2X0), mWidth(width), mLengthZ(lengthZ), mLengthSensZ(lengthSensZ)
50{
51
52 if (mLengthSensZ <= 0 || mLengthSensZ > mLengthZ) {
53 LOGP(fatal, "Invalid sensor length: sensZ={} layerZ={}", mLengthSensZ, mLengthZ);
54 }
55 LOGP(info, "Creating VD rectangular layer: id: {} name: {} x2X0: {} width: {} lengthZ: {} lengthSensZ: {} chipThickness = {} cm",
56 mLayerNumber, layerName, mX2X0, width, lengthZ, lengthSensZ, mChipThickness);
57}
58
59// VDDiskLayer constructor
60VDDiskLayer::VDDiskLayer(int layerNumber, const std::string& layerName, double layerX2X0, double rMin, double rMax,
61 double phiSpanDeg, double zPos)
62 : VDLayer(layerNumber, layerName, layerX2X0), mRMin(rMin), mRMax(rMax), mPhiSpanDeg(phiSpanDeg), mZPos(zPos)
63{
64
65 LOGP(info, "Creating VD disk layer: id: {} name: {} x2X0: {} rMin: {} rMax: {} phiSpanDeg: {} zPos: {} chipThickness = {} cm",
66 mLayerNumber, layerName, mX2X0, rMin, rMax, phiSpanDeg, zPos, mChipThickness);
67}
68
69/*
70** Create sensor
71*/
72
74{
75 if (!gGeoManager) {
76 LOGP(error, "gGeoManager is null");
77 return nullptr;
78 }
79 auto* medSi = gGeoManager->GetMedium("TRK_SILICON$");
80 if (!medSi) {
81 LOGP(error, "Missing medium TRK_SILICON$");
82 return nullptr;
83 }
84 std::string sensName = Form("%s_%s%d", this->mLayerName.c_str(), GeometryTGeo::getTRKSensorPattern(), this->mLayerNumber);
85 const double rIn = mRadius;
86 const double rOut = mRadius + mChipThickness;
87 const double halfZ = 0.5 * mLengthSensZ;
88 const double halfPhi = 0.5 * mPhiSpanDeg; // degrees
89 auto* shape = new TGeoTubeSeg(rIn, rOut, halfZ, -halfPhi, +halfPhi);
90 auto* vol = new TGeoVolume(sensName.c_str(), shape, medSi);
91 vol->SetLineColor(kYellow);
92 vol->SetTransparency(30);
93 return vol;
94}
95
97{
98 if (!gGeoManager) {
99 LOGP(error, "gGeoManager is null");
100 return nullptr;
101 }
102 auto* medSi = gGeoManager->GetMedium("TRK_SILICON$");
103 if (!medSi) {
104 LOGP(error, "Missing medium TRK_SILICON$");
105 return nullptr;
106 }
107 std::string sensName = Form("%s_%s%d", this->mLayerName.c_str(), GeometryTGeo::getTRKSensorPattern(), this->mLayerNumber);
108 const double hx = 0.5 * mWidth;
109 const double hy = 0.5 * mChipThickness; // thickness in Y
110 const double hz = 0.5 * mLengthSensZ; // <-- use sensor Z length, not full layer
111
112 auto* shape = new TGeoBBox(hx, hy, hz);
113 auto* vol = new TGeoVolume(sensName.c_str(), shape, medSi);
114 vol->SetLineColor(kYellow);
115 vol->SetTransparency(30);
116
117 return vol;
118}
119
120TGeoVolume* VDDiskLayer::createSensor() const
121{
122 if (!gGeoManager) {
123 LOGP(error, "gGeoManager is null");
124 return nullptr;
125 }
126 TGeoMedium* medSi = gGeoManager->GetMedium("TRK_SILICON$");
127 if (!medSi) {
128 LOGP(error, "Missing medium TRK_SILICON$");
129 return nullptr;
130 }
131 if (mRMin < 0 || mRMax <= mRMin || mChipThickness <= 0 || mPhiSpanDeg <= 0 || mPhiSpanDeg > 360.0) {
132 LOGP(error, "Invalid disk sensor dims: rMin={}, rMax={}, t={}, phiSpanDeg={}",
133 mRMin, mRMax, mChipThickness, mPhiSpanDeg);
134 return nullptr;
135 }
136 std::string sensName = Form("%s_%s%d", this->mLayerName.c_str(), GeometryTGeo::getTRKSensorPattern(), this->mLayerNumber);
137 const double halfThickness = 0.5 * mChipThickness; // disk thickness is along Z
138 const double halfPhi = 0.5 * mPhiSpanDeg; // degrees
139
140 // Same geometry as the layer (identical radii + phi span + thickness)
141 auto* shape = new TGeoTubeSeg(mRMin, mRMax, halfThickness, -halfPhi, +halfPhi);
142
143 auto* sensVol = new TGeoVolume(sensName.c_str(), shape, medSi);
144 sensVol->SetLineColor(kYellow);
145 sensVol->SetTransparency(30);
146
147 return sensVol;
148}
149
150/*
151** Create layer
152*/
153
154// Cylindrical layer
155void VDCylindricalLayer::createLayer(TGeoVolume* motherVolume, TGeoMatrix* combiTrans) const
156{
157 if (!motherVolume || !gGeoManager) {
158 LOGP(error, "Null motherVolume or gGeoManager");
159 return;
160 }
161 TGeoMedium* medAir = gGeoManager->GetMedium("TRK_AIR$");
162 if (!medAir) {
163 LOGP(error, "Missing TRK_AIR$");
164 return;
165 }
166
167 // Sanity
168 if (mRadius <= 0 || mChipThickness <= 0 || mLengthZ <= 0 ||
169 mPhiSpanDeg <= 0 || mPhiSpanDeg > 360.0 ||
170 mLengthSensZ <= 0 || mLengthSensZ > mLengthZ) {
171 LOGP(error, "Invalid cylindrical dimensions: r={}, t={}, Z={}, phi={}, sensZ={}",
172 mRadius, mChipThickness, mLengthZ, mPhiSpanDeg, mLengthSensZ);
173 return;
174 }
175
176 // AIR container (layer)
177 const double rIn = mRadius;
178 const double rOut = mRadius + mChipThickness;
179 const double halfZ = 0.5 * mLengthZ;
180 const double halfPhi = 0.5 * mPhiSpanDeg; // degrees
181
182 auto* layerShape = new TGeoTubeSeg(rIn, rOut, halfZ, -halfPhi, +halfPhi);
183 auto* layerVol = new TGeoVolume(mLayerName.c_str(), layerShape, medAir);
184 layerVol->SetLineColor(kYellow);
185 layerVol->SetTransparency(30);
186
187 // Sensor volume (must use mLengthSensZ internally)
188 TGeoVolume* sensorVol = VDCylindricalLayer::createSensor();
189 if (!sensorVol) {
190 LOGP(error, "VDCylindricalLayer::createSensor() returned null");
191 return;
192 }
193 LOGP(info, "Inserting {} in {} ", sensorVol->GetName(), layerVol->GetName());
194 layerVol->AddNode(sensorVol, 1, nullptr);
195
196 // Tiling: edge-to-edge if sensor shorter than layer; else single centered
197 // const auto zCenters = (mLengthSensZ < mLengthZ)
198 // ? centersNoGapZ(mLengthZ, mLengthSensZ)
199 // : std::vector<double>{0.0};
200 //
201 // int copyNo = 1;
202 // for (double zc : zCenters) {
203 // TGeoTranslation tz(0.0, 0.0, zc);
204 // layerVol->AddNode(sensorVol, copyNo++, (zc == 0.0 && zCenters.size() == 1) ? nullptr : &tz);
205 // }
206
207 motherVolume->AddNode(layerVol, 1, combiTrans);
208}
209
210// Rectangular layer
211void VDRectangularLayer::createLayer(TGeoVolume* motherVolume, TGeoMatrix* combiTrans) const
212{
213 if (!motherVolume || !gGeoManager) {
214 LOGP(error, "Null motherVolume or gGeoManager");
215 return;
216 }
217 TGeoMedium* medAir = gGeoManager->GetMedium("TRK_AIR$");
218 if (!medAir) {
219 LOGP(error, "Missing TRK_AIR$");
220 return;
221 }
222
223 if (mWidth <= 0 || mChipThickness <= 0 || mLengthZ <= 0 ||
224 mLengthSensZ <= 0 || mLengthSensZ > mLengthZ) {
225 LOGP(error, "Invalid rectangular dims: W={}, t={}, Z={}, sensZ={}",
226 mWidth, mChipThickness, mLengthZ, mLengthSensZ);
227 return;
228 }
229
230 // AIR container (layer)
231 const double hx = 0.5 * mWidth;
232 const double hy = 0.5 * mChipThickness;
233 const double hz = 0.5 * mLengthZ;
234
235 auto* layerShape = new TGeoBBox(hx, hy, hz);
236 auto* layerVol = new TGeoVolume(mLayerName.c_str(), layerShape, medAir);
237 layerVol->SetLineColor(kYellow);
238 layerVol->SetTransparency(30);
239
240 // Sensor volume (uses mLengthSensZ internally)
241 TGeoVolume* sensorVol = VDRectangularLayer::createSensor();
242 if (!sensorVol) {
243 LOGP(error, "VDRectangularLayer::createSensor() returned null");
244 return;
245 }
246
247 LOGP(info, "Inserting {} in {} ", sensorVol->GetName(), layerVol->GetName());
248 layerVol->AddNode(sensorVol, 1, nullptr);
249
250 // Tiling along Z, edge - to - edge if needed
251 // const auto zCenters = (mLengthSensZ < mLengthZ)
252 // ? centersNoGapZ(mLengthZ, mLengthSensZ)
253 // : std::vector<double>{0.0};
254 //
255 // int copyNo = 1;
256 // for (double zc : zCenters) {
257 // TGeoTranslation tz(0.0, 0.0, zc);
258 // layerVol->AddNode(sensorVol, copyNo++, (zc == 0.0 && zCenters.size() == 1) ? nullptr : &tz);
259 // }
260
261 motherVolume->AddNode(layerVol, 1, combiTrans);
262}
263
264// Disk layer
265void VDDiskLayer::createLayer(TGeoVolume* motherVolume, TGeoMatrix* combiTrans) const
266{
267 if (!motherVolume || !gGeoManager) {
268 LOGP(error, "Null motherVolume or gGeoManager");
269 return;
270 }
271 TGeoMedium* medAir = gGeoManager->GetMedium("TRK_AIR$");
272 if (!medAir) {
273 LOGP(error, "Missing TRK_AIR$");
274 return;
275 }
276
277 if (mRMin < 0 || mRMax <= mRMin || mChipThickness <= 0 ||
278 mPhiSpanDeg <= 0 || mPhiSpanDeg > 360.0) {
279 LOGP(error, "Invalid disk dims: rMin={}, rMax={}, t={}, phi={}",
280 mRMin, mRMax, mChipThickness, mPhiSpanDeg);
281 return;
282 }
283
284 // For disks the thickness is along Z and equals mChipThickness
285 const double halfThickness = 0.5 * mChipThickness;
286 const double halfPhi = 0.5 * mPhiSpanDeg;
287
288 // AIR container (layer)
289 auto* layerShape = new TGeoTubeSeg(mRMin, mRMax, halfThickness, -halfPhi, +halfPhi);
290 auto* layerVol = new TGeoVolume(mLayerName.c_str(), layerShape, medAir);
291 layerVol->SetLineColor(kYellow);
292 layerVol->SetTransparency(30);
293
294 // Sensor (same size & shape as the layer for disks)
295 TGeoVolume* sensorVol = VDDiskLayer::createSensor();
296 if (!sensorVol) {
297 LOGP(error, "VDDiskLayer::createSensor() returned null");
298 return;
299 }
300
301 // Insert single sensor (no Z-segmentation for disks)
302 layerVol->AddNode(sensorVol, 1, nullptr);
303
304 TGeoTranslation tz(0.0, 0.0, mZPos);
305 motherVolume->AddNode(layerVol, 1, combiTrans ? combiTrans : &tz);
306}
307
308// ClassImp(VDLayer);
309// ClassImp(VDCylindricalLayer);
310// ClassImp(VDRectangularLayer);
311// ClassImp(VDDiskLayer);
312
313} // namespace trk
314} // namespace o2
static const char * getTRKSensorPattern()
VDCylindricalLayer(int layerNumber, const std::string &layerName, double layerX2X0, double radius, double phiSpanDeg, double lengthZ, double lengthSensZ)
Definition VDLayer.cxx:38
void createLayer(TGeoVolume *motherVolume, TGeoMatrix *combiTrans=nullptr) const override
Definition VDLayer.cxx:155
TGeoVolume * createSensor() const
Definition VDLayer.cxx:73
void createLayer(TGeoVolume *motherVolume, TGeoMatrix *combiTrans=nullptr) const override
Definition VDLayer.cxx:265
VDDiskLayer(int layerNumber, const std::string &layerName, double layerX2X0, double rMin, double rMax, double phiSpanDeg, double zPos)
Definition VDLayer.cxx:60
TGeoVolume * createSensor() const
Definition VDLayer.cxx:120
std::string mLayerName
Definition VDLayer.h:41
VDLayer()=default
double mChipThickness
Definition VDLayer.h:43
TGeoVolume * createSensor() const
Definition VDLayer.cxx:96
void createLayer(TGeoVolume *motherVolume, TGeoMatrix *combiTrans=nullptr) const override
Definition VDLayer.cxx:211
VDRectangularLayer(int layerNumber, const std::string &layerName, double layerX2X0, double width, double lengthZ, double lengthSensZ)
Definition VDLayer.cxx:47
GLint GLsizei width
Definition glcorearb.h:270
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...