Project
Loading...
Searching...
No Matches
Layer.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 <TGeoBBox.h>
18#include <TGeoMatrix.h>
19#include <TGeoTube.h>
20#include <TGeoVolume.h>
21#include <TMath.h>
22
23#include <algorithm>
24#include <cmath>
25
26namespace o2
27{
28namespace iotof
29{
30Layer::Layer(std::string layerName, float rInn, float rOut, float zLength, float zOffset, float layerX2X0,
31 int layout, int nStaves, float staveSize, double staveTiltAngle, int modulesPerStave, float sensorThickness)
32 : mLayerName(layerName),
33 mInnerRadius(rInn),
34 mOuterRadius(rOut),
35 mZLength(zLength),
36 mZOffset(zOffset),
37 mSensorThickness(sensorThickness),
38 mX2X0(layerX2X0),
39 mLayout(layout),
40 mStaves(nStaves, staveSize),
41 mModulesPerStave(modulesPerStave),
42 mTiltAngle(staveTiltAngle)
43{
44 const float Si_X0 = 9.5f; // cm, radiation length of silicon
45 mChipThickness = mX2X0 * Si_X0;
46 std::string name = "";
47 switch (layout) {
48 case kBarrel:
50 name = "barrel";
52 break;
53 case kDisk:
54 case kDiskSegmented:
55 name = "forward";
57 break;
58 default:
59 LOG(fatal) << "Invalid layout " << layout;
60 }
61 // Sanity checks
63 LOG(fatal) << "Invalid layer dimensions: rInner " << mInnerRadius << " cm is larger than rOuter " << mOuterRadius << " cm";
64 }
65 if ((mStaves.first != 0 || mStaves.second != 0.0f) && (layout != kBarrelSegmented && layout != kDiskSegmented)) {
66 LOG(fatal) << "Invalid configuration: number of segments " << mStaves.first << " is set for non-segmented layout " << layout;
67 }
68 if ((mStaves.first <= 1 || mStaves.second <= 0.0f) && (layout == kBarrelSegmented || layout == kDiskSegmented)) {
69 LOG(fatal) << "Invalid configuration: number of segments " << mStaves.first << " must be positive for segmented layout " << layout;
70 }
71 if (mModulesPerStave <= 0 && (layout == kBarrelSegmented || layout == kDiskSegmented)) {
72 LOG(fatal) << "Invalid configuration: number of sensors per segment " << mModulesPerStave << " must be positive for segmented layout " << layout;
73 }
74 if (std::abs(mTiltAngle) > 0.1 && (layout != kBarrelSegmented && layout != kDiskSegmented)) {
75 LOG(fatal) << "Invalid configuration: tilt angle " << mTiltAngle << " is set for non-segmented layout " << layout;
76 }
77 if ((mTiltAngle < 0.0 || mTiltAngle > 90.0) && (layout == kBarrelSegmented || layout == kDiskSegmented)) {
78 LOG(fatal) << "Invalid configuration: tilt angle " << mTiltAngle << " is too large, it must be between 0 and 90 degrees";
79 }
80 if (mSensorThickness < 0.0f || mSensorThickness > mChipThickness) {
81 LOG(fatal) << "Invalid configuration: sensor thickness " << mSensorThickness << " cm is out of range (0, " << mChipThickness << ") cm";
82 }
83 if (sensorThickness > 0.0f && (layout == kBarrel || layout == kDisk)) {
84 LOG(fatal) << "Invalid configuration: sensor thickness " << mSensorThickness << " cm is set for non-segmented layout, it should be 0";
85 }
86
87 LOGP(info, "TOF: Creating {} layer: rInner: {} (cm) rOuter: {} (cm) zLength: {} (cm) zOffset: {} x2X0: {}", name.c_str(), mInnerRadius, mOuterRadius, mZLength, mZOffset, mX2X0);
88}
89
90void setLayerStyle(TGeoVolume* obj)
91{
92 obj->SetLineColor(kRed - 7);
93 obj->SetFillColor(kRed - 7);
94 obj->SetLineWidth(1);
95 obj->SetTransparency(70);
96}
97void setStaveStyle(TGeoVolume* obj)
98{
99 obj->SetLineColor(kRed - 5);
100 obj->SetFillColor(kRed - 9);
101 obj->SetLineWidth(2);
102 obj->SetTransparency(45);
103}
104void setModuleStyle(TGeoVolume* obj)
105{
106 obj->SetLineColor(kRed - 3);
107 obj->SetFillColor(kRed - 8);
108 obj->SetLineWidth(2);
109 obj->SetTransparency(35);
110}
111void setChipStyle(TGeoVolume* obj)
112{
113 obj->SetLineColor(kOrange);
114 obj->SetFillColor(kOrange - 9);
115 obj->SetLineWidth(3);
116 obj->SetTransparency(15);
117}
118void setSensorStyle(TGeoVolume* obj)
119{
120 obj->SetLineColor(kRed);
121 obj->SetFillColor(kRed - 9);
122 obj->SetLineWidth(3);
123 obj->SetTransparency(5);
124}
125
126std::vector<std::string> ITOFLayer::mRegister;
127void ITOFLayer::createLayer(TGeoVolume* motherVolume)
128{
129 const char* chipName = o2::iotof::GeometryTGeo::getITOFChipPattern();
130 const char* sensName = o2::iotof::GeometryTGeo::getITOFSensorPattern();
131 const char* moduleName = o2::iotof::GeometryTGeo::getITOFModulePattern();
132 const char* staveName = o2::iotof::GeometryTGeo::getITOFStavePattern();
133
134 TGeoMedium* medSi = gGeoManager->GetMedium("TF3_SILICON$");
135 TGeoMedium* medAir = gGeoManager->GetMedium("TF3_AIR$");
136 LOGP(info, "Media: {} {}", (void*)medSi, (void*)medAir);
137
138 switch (mLayout) {
139 case kBarrel: {
140 TGeoTube* sensor = new TGeoTube(mInnerRadius, mOuterRadius, mZLength / 2);
141 TGeoTube* chip = new TGeoTube(mInnerRadius, mOuterRadius, mZLength / 2);
142 TGeoTube* layer = new TGeoTube(mInnerRadius, mOuterRadius, mZLength / 2);
143
144 TGeoVolume* sensVol = new TGeoVolume(sensName, sensor, medSi);
145 TGeoVolume* chipVol = new TGeoVolume(chipName, chip, medSi);
146 TGeoVolume* layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir);
147 setSensorStyle(sensVol);
148 setChipStyle(chipVol);
149 setLayerStyle(layerVol);
150
151 LOGP(info, "Inserting Barrel {} in {} ", sensVol->GetName(), chipVol->GetName());
152 ITOFLayer::mRegister.push_back(sensVol->GetName());
153 chipVol->AddNode(sensVol, 1, nullptr);
154
155 LOGP(info, "Inserting Barrel {} in {} ", chipVol->GetName(), layerVol->GetName());
156 layerVol->AddNode(chipVol, 1, nullptr);
157
158 LOGP(info, "Inserting Barrel {} in {} ", layerVol->GetName(), motherVolume->GetName());
159 motherVolume->AddNode(layerVol, 1, nullptr);
160 return;
161 }
162 case kBarrelSegmented: {
163 // First we create the volume for the whole layer, which will be used as mother volume for the segments
164 const double avgRadius = 0.5 * (mInnerRadius + mOuterRadius);
165 const double staveSizeX = mStaves.second; // cm
166 const double staveSizeY = mOuterRadius - mInnerRadius; // cm
167 const double staveSizeZ = mZLength; // cm
168
169 // Build the mother layer tube from the exact inscribed/outscribed radii of a tilted stave rectangle.
170 const double alpha = mTiltAngle * TMath::DegToRad();
171 const double u0 = -avgRadius * std::cos(alpha);
172 const double v0 = avgRadius * std::sin(alpha);
173 const double uClamped = std::max(-0.5 * staveSizeY, std::min(0.5 * staveSizeY, u0));
174 const double vClamped = std::max(-0.5 * staveSizeX, std::min(0.5 * staveSizeX, v0));
175 const double radiusMin = std::hypot(uClamped - u0, vClamped - v0);
176
177 const double uCorners[4] = {-0.5 * staveSizeY, 0.5 * staveSizeY, 0.5 * staveSizeY, -0.5 * staveSizeY};
178 const double vCorners[4] = {-0.5 * staveSizeX, -0.5 * staveSizeX, 0.5 * staveSizeX, 0.5 * staveSizeX};
179 double radiusMax = 0.0;
180 for (int i = 0; i < 4; ++i) {
181 radiusMax = std::max(radiusMax, std::hypot(uCorners[i] - u0, vCorners[i] - v0));
182 }
183 TGeoTube* layer = new TGeoTube(radiusMin, radiusMax, mZLength / 2); // cm, small margins to ensure staves are fully encapsulated in the layer volume
184 TGeoVolume* layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir);
185 setLayerStyle(layerVol);
186
187 // Now we create the volume for a single stave
188 TGeoBBox* stave = new TGeoBBox(staveSizeX * 0.5, staveSizeY * 0.5, staveSizeZ * 0.5);
189 TGeoVolume* staveVol = new TGeoVolume(staveName, stave, medAir);
190 setStaveStyle(staveVol);
191
192 // Now we create the volume for a single module (sensor + chip)
193 const int modulesPerStaveX = 1; // we assume that each stave is divided in 1 modules along the x direction
194 const double moduleSizeX = staveSizeX / modulesPerStaveX; // cm
195 const double moduleSizeY = staveSizeY; // cm
196 const double moduleSizeZ = staveSizeZ / mModulesPerStave; // cm
197 TGeoBBox* module = new TGeoBBox(moduleSizeX * 0.5, moduleSizeY * 0.5, moduleSizeZ * 0.5);
198 TGeoVolume* moduleVol = new TGeoVolume(moduleName, module, medAir);
199 setModuleStyle(moduleVol);
200
201 // Now we create the volume of the chip, which is the same for all modules
202 const int chipsPerModuleX = 2; // we assume that each module is divided in 2 chips along the x direction
203 const int chipsPerModuleZ = 4; // we assume that each module is divided in 2 chips along the z direction
204 const double chipSizeX = moduleSizeX / chipsPerModuleX; // cm
205 const double chipSizeY = moduleSizeY; // cm
206 const double chipSizeZ = moduleSizeZ / chipsPerModuleZ; // cm
207 TGeoBBox* chip = new TGeoBBox(chipSizeX * 0.5, chipSizeY * 0.5, chipSizeZ * 0.5);
208 TGeoVolume* chipVol = new TGeoVolume(chipName, chip, medSi);
209 setChipStyle(chipVol);
210
211 // Finally we create the volume of the sensor, which is the same for all chips
212 const int sensorsPerChipX = 1; // we assume that each chip is divided in 2 sensors along the x direction
213 const int sensorsPerChipZ = 1; // we assume that each chip is divided in 2 sensors along the z direction
214 const double sensorSizeX = chipSizeX / sensorsPerChipX; // cm
215 const double sensorSizeY = mSensorThickness; // cm
216 const double sensorSizeZ = chipSizeZ / sensorsPerChipZ; // cm
217 TGeoBBox* sensor = new TGeoBBox(sensorSizeX * 0.5, sensorSizeY * 0.5, sensorSizeZ * 0.5);
218 TGeoVolume* sensVol = new TGeoVolume(sensName, sensor, medSi);
219 setSensorStyle(sensVol);
220 ITOFLayer::mRegister.push_back(sensVol->GetName());
221
222 // Now we build a chip from sensors
223 for (int i = 0; i < sensorsPerChipX; ++i) {
224 for (int j = 0; j < sensorsPerChipZ; ++j) {
225 LOGP(info, "iTOF: Creating sensor {}/{} for chip {}/{}", i + 1, sensorsPerChipX, j + 1, sensorsPerChipZ);
226 auto* translation = new TGeoTranslation((i + 0.5) * sensorSizeX - 0.5 * chipSizeX,
227 0.5 * chipSizeY - 0.5 * sensorSizeY,
228 (j + 0.5) * sensorSizeZ - 0.5 * chipSizeZ);
229 chipVol->AddNode(sensVol, 1 + i * sensorsPerChipZ + j, translation);
230 }
231 }
232
233 // Now we build a module from chips
234 for (int i = 0; i < chipsPerModuleX; ++i) {
235 for (int j = 0; j < chipsPerModuleZ; ++j) {
236 LOGP(info, "iTOF: Creating chip {}/{} for module {}/{}", i + 1, chipsPerModuleX, j + 1, chipsPerModuleZ);
237 auto* translation = new TGeoTranslation((i + 0.5) * chipSizeX - 0.5 * moduleSizeX, 0, (j + 0.5) * chipSizeZ - 0.5 * moduleSizeZ);
238 moduleVol->AddNode(chipVol, 1 + i * chipsPerModuleZ + j, translation);
239 }
240 }
241
242 // Now we build a stave from modules
243 for (int i = 0; i < modulesPerStaveX; ++i) {
244 for (int j = 0; j < mModulesPerStave; ++j) {
245 LOGP(info, "iTOF: Creating module {}/{} for stave {}/{}", i + 1, modulesPerStaveX, j + 1, mModulesPerStave);
246 auto* translation = new TGeoTranslation((i + 0.5) * moduleSizeX - 0.5 * staveSizeX, 0, (j + 0.5) * moduleSizeZ - 0.5 * staveSizeZ);
247 staveVol->AddNode(moduleVol, 1 + i * mModulesPerStave + j, translation);
248 }
249 }
250
251 // We finally put all the staves in the layer
252 for (int i = 0; i < mStaves.first; ++i) {
253 LOGP(info, "iTOF: Creating stave {}/{} for layer {}", i + 1, mStaves.first, layerVol->GetName());
254 const double phi = TMath::TwoPi() * i / mStaves.first;
255 const double x = avgRadius * TMath::Cos(phi);
256 const double y = avgRadius * TMath::Sin(phi);
257 auto* rotation = new TGeoRotation(Form("segmentRot%d", i + 1), phi * TMath::RadToDeg() + 90 + mTiltAngle, 0, 0);
258 auto* transformation = new TGeoCombiTrans(x, y, 0, rotation);
259
260 LOGP(info, "Inserting Barrel {} in {} ", chipVol->GetName(), layerVol->GetName());
261 layerVol->AddNode(staveVol, 1 + i, transformation);
262 }
263 LOGP(info, "Inserting Barrel {} in {} at r={} cm", layerVol->GetName(), motherVolume->GetName(), avgRadius);
264 motherVolume->AddNode(layerVol, 1, nullptr);
265 return;
266 }
267 default:
268 LOG(fatal) << "Invalid layout " << mLayout;
269 }
270}
271
272std::vector<std::string> OTOFLayer::mRegister;
273void OTOFLayer::createLayer(TGeoVolume* motherVolume)
274{
275 const char* chipName = o2::iotof::GeometryTGeo::getOTOFChipPattern();
276 const char* sensName = o2::iotof::GeometryTGeo::getOTOFSensorPattern();
277 const char* moduleName = o2::iotof::GeometryTGeo::getOTOFModulePattern();
278 const char* subStaveName = o2::iotof::GeometryTGeo::getOTOFSubStavePattern();
279 const char* staveName = o2::iotof::GeometryTGeo::getOTOFStavePattern();
280
281 TGeoMedium* medSi = gGeoManager->GetMedium("TF3_SILICON$");
282 TGeoMedium* medAir = gGeoManager->GetMedium("TF3_AIR$");
283 LOGP(info, "Media: {} {}", (void*)medSi, (void*)medAir);
284
285 switch (mLayout) {
286 case kBarrel: {
287 TGeoTube* sensor = new TGeoTube(mInnerRadius, mOuterRadius, mZLength / 2);
288 TGeoTube* chip = new TGeoTube(mInnerRadius, mOuterRadius, mZLength / 2);
289 TGeoTube* layer = new TGeoTube(mInnerRadius, mOuterRadius, mZLength / 2);
290
291 TGeoVolume* sensVol = new TGeoVolume(sensName, sensor, medSi);
292 TGeoVolume* chipVol = new TGeoVolume(chipName, chip, medSi);
293 TGeoVolume* layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir);
294 setSensorStyle(sensVol);
295 setChipStyle(chipVol);
296 setLayerStyle(layerVol);
297
298 LOGP(info, "Inserting {} in {} ", sensVol->GetName(), chipVol->GetName());
299 OTOFLayer::mRegister.push_back(sensVol->GetName());
300 chipVol->AddNode(sensVol, 1, nullptr);
301
302 LOGP(info, "Inserting {} in {} ", chipVol->GetName(), layerVol->GetName());
303 layerVol->AddNode(chipVol, 1, nullptr);
304
305 LOGP(info, "Inserting {} in {} ", layerVol->GetName(), motherVolume->GetName());
306 motherVolume->AddNode(layerVol, 1, nullptr);
307 return;
308 }
309 case kBarrelSegmented: {
310 // Additional geometry parameters
311 const double subStavesDistanceY = 0.3; // cm
312 const double subStavesOverlapX = 1.1; // cm
313
314 // First we create the volume for the whole layer, which will be used as mother volume for the segments
315 const double avgRadius = 0.5 * (mInnerRadius + mOuterRadius);
316 const double staveSizeX = mStaves.second; // cm, tangential stave size
317 const double staveSizeY = mOuterRadius - mInnerRadius + subStavesDistanceY; // cm, radial stave size
318 const double staveSizeZ = mZLength; // cm
319 const double subStaveSizeX = 0.5 * mStaves.second + 0.5 * subStavesOverlapX; // cm, tangential substave size
320 const double subStaveSizeY = mOuterRadius - mInnerRadius; // cm, radial substave size
321 const double subStaveSizeZ = mZLength; // cm
322
323 // Build the mother layer tube from the exact inscribed/outscribed radii of a tilted stave rectangle.
324 const double alpha = mTiltAngle * TMath::DegToRad();
325 const double u0 = -avgRadius * std::cos(alpha);
326 const double v0 = avgRadius * std::sin(alpha);
327 const double uClamped = std::max(-0.5 * staveSizeY, std::min(0.5 * staveSizeY, u0));
328 const double vClamped = std::max(-0.5 * staveSizeX, std::min(0.5 * staveSizeX, v0));
329 const double radiusMin = std::hypot(uClamped - u0, vClamped - v0);
330
331 const double uCorners[4] = {-0.5 * staveSizeY, 0.5 * staveSizeY, 0.5 * staveSizeY, -0.5 * staveSizeY};
332 const double vCorners[4] = {-0.5 * staveSizeX, -0.5 * staveSizeX, 0.5 * staveSizeX, 0.5 * staveSizeX};
333 double radiusMax = 0.0;
334 for (int i = 0; i < 4; ++i) {
335 radiusMax = std::max(radiusMax, std::hypot(uCorners[i] - u0, vCorners[i] - v0));
336 }
337 TGeoTube* layer = new TGeoTube(radiusMin, radiusMax, mZLength / 2);
338 TGeoVolume* layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir);
339 setLayerStyle(layerVol);
340
341 // Now we create the volume for a single stave
342 TGeoBBox* stave = new TGeoBBox(staveSizeX * 0.5, staveSizeY * 0.5, staveSizeZ * 0.5);
343 TGeoVolume* staveVol = new TGeoVolume(staveName, stave, medAir);
344 setStaveStyle(staveVol);
345
346 // Now we create the volume for a single stave
347 TGeoBBox* subStave = new TGeoBBox(subStaveSizeX * 0.5, subStaveSizeY * 0.5, subStaveSizeZ * 0.5);
348 TGeoVolume* subStaveVol = new TGeoVolume(subStaveName, subStave, medAir);
349 setStaveStyle(subStaveVol);
350
351 // Now we create the volume for a single module (sensor + chip)
352 // oTOF V2 is a 2xN matrix.
353 const int modulesPerSubStave = mModulesPerStave;
354 const int modulesPerSubStaveX = 1;
355 if (modulesPerSubStave % modulesPerSubStaveX != 0) {
356 LOG(fatal) << "Invalid oTOF module layout: total modules per stave " << modulesPerSubStave
357 << " is not divisible by modulesPerStaveX=" << modulesPerSubStaveX;
358 }
359 const int modulesPerSubStaveZ = modulesPerSubStave / modulesPerSubStaveX;
360 const double moduleSizeX = subStaveSizeX / modulesPerSubStaveX;
361 const double moduleSizeY = subStaveSizeY;
362 const double moduleSizeZ = subStaveSizeZ / modulesPerSubStaveZ;
363 TGeoBBox* module = new TGeoBBox(moduleSizeX * 0.5, moduleSizeY * 0.5, moduleSizeZ * 0.5);
364 TGeoVolume* moduleVol = new TGeoVolume(moduleName, module, medAir);
365 setModuleStyle(moduleVol);
366
367 // Now we create the volume of the chip, which is the same for all modules
368 const int chipsPerModuleX = 2; // we assume that each module is divided in 2 chips along the x direction
369 const int chipsPerModuleZ = 4; // we assume that each module is divided in 2 chips along the z direction
370 const double chipSizeX = moduleSizeX / chipsPerModuleX; // cm
371 const double chipSizeY = moduleSizeY; // cm
372 const double chipSizeZ = moduleSizeZ / chipsPerModuleZ; // cm
373 TGeoBBox* chip = new TGeoBBox(chipSizeX * 0.5, chipSizeY * 0.5, chipSizeZ * 0.5);
374 TGeoVolume* chipVol = new TGeoVolume(chipName, chip, medSi);
375 setChipStyle(chipVol);
376
377 // Finally we create the volume of the sensor, which is the same for all chips
378 const int sensorsPerChipX = 1; // we assume that each chip is divided in 2 sensors along the x direction
379 const int sensorsPerChipZ = 1; // we assume that each chip is divided in 2 sensors along the z direction
380 const double sensorSizeX = chipSizeX / sensorsPerChipX; // cm
381 const double sensorSizeY = mSensorThickness; // cm
382 const double sensorSizeZ = chipSizeZ / sensorsPerChipZ; // cm
383 TGeoBBox* sensor = new TGeoBBox(sensorSizeX * 0.5, sensorSizeY * 0.5, sensorSizeZ * 0.5);
384 TGeoVolume* sensVol = new TGeoVolume(sensName, sensor, medSi);
385 setSensorStyle(sensVol);
386 OTOFLayer::mRegister.push_back(sensVol->GetName());
387
388 // Now we build a chip from sensors
389 for (int i = 0; i < sensorsPerChipX; ++i) {
390 for (int j = 0; j < sensorsPerChipZ; ++j) {
391 LOGP(info, "oTOF: Creating sensor {}/{} for chip {}/{}", i + 1, sensorsPerChipX, j + 1, sensorsPerChipZ);
392 auto* translation = new TGeoTranslation((i + 0.5) * sensorSizeX - 0.5 * chipSizeX,
393 0.5 * chipSizeY - 0.5 * sensorSizeY,
394 (j + 0.5) * sensorSizeZ - 0.5 * chipSizeZ);
395 chipVol->AddNode(sensVol, 1 + i * sensorsPerChipZ + j, translation);
396 }
397 }
398
399 // Now we build a module from chips
400 for (int i = 0; i < chipsPerModuleX; ++i) {
401 for (int j = 0; j < chipsPerModuleZ; ++j) {
402 LOGP(info, "oTOF: Creating chip {}/{} for module {}/{}", i + 1, chipsPerModuleX, j + 1, chipsPerModuleZ);
403 auto* translation = new TGeoTranslation((i + 0.5) * chipSizeX - 0.5 * moduleSizeX, 0, (j + 0.5) * chipSizeZ - 0.5 * moduleSizeZ);
404 moduleVol->AddNode(chipVol, 1 + i * chipsPerModuleZ + j, translation);
405 }
406 }
407
408 // Now we build a sub-stave from modules
409 for (int i = 0; i < modulesPerSubStaveX; ++i) {
410 for (int j = 0; j < modulesPerSubStaveZ; ++j) {
411 LOGP(info, "oTOF: Creating module {}/{} for substave {}/{}", i + 1, modulesPerSubStaveX, j + 1, modulesPerSubStaveZ);
412 const double tx = (i + 0.5) * moduleSizeX - 0.5 * subStaveSizeX;
413 const double tz = -0.5 * subStaveSizeZ + (j + 0.5) * moduleSizeZ;
414 auto* translation = new TGeoTranslation(tx, 0, tz);
415 subStaveVol->AddNode(moduleVol, 1 + i * modulesPerSubStaveZ + j, translation);
416 }
417 }
418
419 // Now we build a stave from two substave
420 for (int i = 0; i < 2; ++i) {
421 LOGP(info, "oTOF: Creating substave {}/{} for stave {}/{}", i + 1, 2, 1, 1);
422 int sign = i > 0 ? 1 : -1;
423 auto* translation2 = new TGeoTranslation(sign * 0.5 * (subStaveSizeX)-sign * 0.5 * subStavesOverlapX, -sign * 0.5 * subStavesDistanceY, 0);
424 staveVol->AddNode(subStaveVol, i + 1, translation2);
425 }
426
427 // We finally put all the staves in the layer
428 for (int i = 0; i < mStaves.first; ++i) {
429 LOGP(info, "oTOF: Creating stave {}/{} for layer {}", i + 1, mStaves.first, layerVol->GetName());
430 const double phi = TMath::TwoPi() * i / mStaves.first;
431 const double x = avgRadius * TMath::Cos(phi);
432 const double y = avgRadius * TMath::Sin(phi);
433 auto* rotation = new TGeoRotation(Form("segmentRot%d", i + 1), phi * TMath::RadToDeg() + 90 + mTiltAngle, 0, 0);
434 auto* transformation = new TGeoCombiTrans(x, y, 0, rotation);
435
436 LOGP(info, "Inserting Barrel {} in {} ", chipVol->GetName(), layerVol->GetName());
437 layerVol->AddNode(staveVol, 1 + i, transformation);
438 }
439 LOGP(info, "Inserting Barrel {} in {} at r={} cm", layerVol->GetName(), motherVolume->GetName(), avgRadius);
440 motherVolume->AddNode(layerVol, 1, nullptr);
441 return;
442 }
443 default:
444 LOG(fatal) << "Invalid layout " << mLayout;
445 }
446}
447
448void FTOFLayer::createLayer(TGeoVolume* motherVolume)
449{
450 std::string chipName = o2::iotof::GeometryTGeo::getFTOFChipPattern(),
452
453 TGeoTube* sensor = new TGeoTube(mInnerRadius, mOuterRadius, mZLength / 2);
454 TGeoTube* chip = new TGeoTube(mInnerRadius, mOuterRadius, mZLength / 2);
455 TGeoTube* layer = new TGeoTube(mInnerRadius, mOuterRadius, mZLength / 2);
456
457 TGeoMedium* medSi = gGeoManager->GetMedium("TF3_SILICON$");
458 TGeoMedium* medAir = gGeoManager->GetMedium("TF3_AIR$");
459
460 TGeoVolume* sensVol = new TGeoVolume(sensName.c_str(), sensor, medSi);
461 TGeoVolume* chipVol = new TGeoVolume(chipName.c_str(), chip, medSi);
462 TGeoVolume* layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir);
463 setSensorStyle(sensVol);
464 setChipStyle(chipVol);
465 setLayerStyle(layerVol);
466
467 LOGP(info, "Inserting {} in {} ", sensVol->GetName(), chipVol->GetName());
468 chipVol->AddNode(sensVol, 1, nullptr);
469
470 LOGP(info, "Inserting {} in {} ", chipVol->GetName(), layerVol->GetName());
471 layerVol->AddNode(chipVol, 1, nullptr);
472
473 auto* fwdTOFRotation = new TGeoRotation("fwdTOFRotation", 0, 0, 180);
474 auto* fwdTOFCombiTrans = new TGeoCombiTrans(0, 0, mZOffset, fwdTOFRotation);
475
476 LOGP(info, "Inserting {} in {} ", layerVol->GetName(), motherVolume->GetName());
477 motherVolume->AddNode(layerVol, 1, fwdTOFCombiTrans);
478}
479
480void BTOFLayer::createLayer(TGeoVolume* motherVolume)
481{
482 std::string chipName = o2::iotof::GeometryTGeo::getBTOFChipPattern(),
484
485 TGeoTube* sensor = new TGeoTube(mInnerRadius, mOuterRadius, mZLength / 2);
486 TGeoTube* chip = new TGeoTube(mInnerRadius, mOuterRadius, mZLength / 2);
487 TGeoTube* layer = new TGeoTube(mInnerRadius, mOuterRadius, mZLength / 2);
488
489 TGeoMedium* medSi = gGeoManager->GetMedium("TF3_SILICON$");
490 TGeoMedium* medAir = gGeoManager->GetMedium("TF3_AIR$");
491
492 TGeoVolume* sensVol = new TGeoVolume(sensName.c_str(), sensor, medSi);
493 TGeoVolume* chipVol = new TGeoVolume(chipName.c_str(), chip, medSi);
494 TGeoVolume* layerVol = new TGeoVolume(mLayerName.c_str(), layer, medAir);
495 setSensorStyle(sensVol);
496 setChipStyle(chipVol);
497 setLayerStyle(layerVol);
498
499 LOGP(info, "Inserting {} in {} ", sensVol->GetName(), chipVol->GetName());
500 chipVol->AddNode(sensVol, 1, nullptr);
501
502 LOGP(info, "Inserting {} in {} ", chipVol->GetName(), layerVol->GetName());
503 layerVol->AddNode(chipVol, 1, nullptr);
504
505 auto* bwdTOFRotation = new TGeoRotation("bwdTOFRotation", 0, 0, 180);
506 auto* fwdTOFCombiTrans = new TGeoCombiTrans(0, 0, mZOffset, bwdTOFRotation);
507
508 LOGP(info, "Inserting {} in {} ", layerVol->GetName(), motherVolume->GetName());
509 motherVolume->AddNode(layerVol, 1, fwdTOFCombiTrans);
510}
511
512} // namespace iotof
513} // namespace o2
int32_t i
uint32_t j
Definition RawData.h:0
virtual void createLayer(TGeoVolume *motherVolume) override
Definition Layer.cxx:480
virtual void createLayer(TGeoVolume *motherVolume) override
Definition Layer.cxx:448
static const char * getITOFChipPattern()
static const char * getFTOFSensorPattern()
static const char * getFTOFChipPattern()
static const char * getBTOFChipPattern()
static const char * getOTOFSubStavePattern()
static const char * getOTOFModulePattern()
static const char * getITOFModulePattern()
static const char * getOTOFSensorPattern()
static const char * getITOFStavePattern()
static const char * getITOFSensorPattern()
static const char * getOTOFStavePattern()
static const char * getOTOFChipPattern()
static const char * getBTOFSensorPattern()
static std::vector< std::string > mRegister
Definition Layer.h:69
virtual void createLayer(TGeoVolume *motherVolume) override
Definition Layer.cxx:127
float mZOffset
Definition Layer.h:53
float mOuterRadius
Definition Layer.h:51
float mZLength
Definition Layer.h:52
int mModulesPerStave
Definition Layer.h:60
static constexpr int kBarrelSegmented
Definition Layer.h:43
static constexpr int kDisk
Definition Layer.h:42
float mSensorThickness
Definition Layer.h:56
float mChipThickness
Definition Layer.h:55
static constexpr int kBarrel
Definition Layer.h:41
static constexpr int kDiskSegmented
Definition Layer.h:44
std::pair< int, float > mStaves
Definition Layer.h:59
std::string mLayerName
Definition Layer.h:49
float mInnerRadius
Definition Layer.h:50
double mTiltAngle
Definition Layer.h:61
float mX2X0
Definition Layer.h:54
virtual void createLayer(TGeoVolume *motherVolume) override
Definition Layer.cxx:273
static std::vector< std::string > mRegister
Definition Layer.h:77
GLfloat GLfloat GLfloat alpha
Definition glcorearb.h:279
GLint GLenum GLint x
Definition glcorearb.h:403
GLuint const GLchar * name
Definition glcorearb.h:781
GLfloat v0
Definition glcorearb.h:811
GLenum GLuint GLint GLint layer
Definition glcorearb.h:1310
void setLayerStyle(TGeoVolume *obj)
Definition Layer.cxx:90
void setModuleStyle(TGeoVolume *obj)
Definition Layer.cxx:104
void setChipStyle(TGeoVolume *obj)
Definition Layer.cxx:111
void setStaveStyle(TGeoVolume *obj)
Definition Layer.cxx:97
void setSensorStyle(TGeoVolume *obj)
Definition Layer.cxx:118
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
auto transformation
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"