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