Project
Loading...
Searching...
No Matches
Detector.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
16
17#include "DetectorsBase/Stack.h"
19
23
24// FairRoot includes
25#include "FairDetector.h" // for FairDetector
26#include "FairRootManager.h" // for FairRootManager
27#include "FairRootManager.h"
28#include "FairRun.h" // for FairRun
29#include "FairRuntimeDb.h" // for FairRuntimeDb
30#include "FairVolume.h" // for FairVolume
31
32#include "TGeoManager.h" // for TGeoManager, gGeoManager
33#include "TGeoPcon.h" // for TGeoPcon
34#include "TGeoTube.h" // for TGeoTube
35#include "TGeoVolume.h" // for TGeoVolume, TGeoVolumeAssembly
36#include "TString.h" // for TString, operator+
37#include "TVirtualMC.h" // for gMC, TVirtualMC
38#include "TVirtualMCStack.h" // for TVirtualMCStack
39
40#include <fairlogger/Logger.h> // for LOG, LOG_IF
41
42#include <cstdio> // for NULL, snprintf
43
44#define MAX_SENSORS 2000
45
46class FairModule;
47
48class TGeoMedium;
49
50class TParticle;
51
52using namespace o2::ft3;
53using o2::trkft3::Hit;
54
55//_________________________________________________________________________________________________
57 : o2::base::DetImpl<Detector>("FT3", kTRUE),
58 mTrackData(),
59 mHits(o2::utils::createSimVector<o2::trkft3::Hit>())
60{
61}
62
63//_________________________________________________________________________________________________
65{
66 // Build a basic parametrized FT3 detector with nLayers equally spaced between z_first and z_first+z_length
67 // Covering pseudo rapidity [etaIn,etaOut]. Silicon thinkness computed to match layer x/X0
68
69 LOG(info) << "Building FT3 Detector: Conical Telescope";
70
71 const int numberOfLayers = param.nLayers;
72 const auto z_first = param.z0;
73 const auto z_length = param.zLength;
74 const auto etaIn = param.etaIn;
75 const auto etaOut = param.etaOut;
76 const auto Layerx2X0 = param.Layerx2X0;
77 mLayerName[IdxBackwardDisks].resize(numberOfLayers);
78 mLayerName[IdxForwardDisks].resize(numberOfLayers);
79
80 for (int direction : {IdxBackwardDisks, IdxForwardDisks}) {
81 for (int layerNumber = 0; layerNumber < numberOfLayers; layerNumber++) {
82 std::string layerName = GeometryTGeo::getFT3LayerPattern() + std::to_string(layerNumber + numberOfLayers * direction);
83 mLayerName[direction][layerNumber] = layerName;
84
85 // Adds evenly spaced layers
86 const float layerZ = z_first + (layerNumber * z_length / numberOfLayers) * std::copysign(1, z_first);
87 const float rIn = std::abs(layerZ * std::tan(2.f * std::atan(std::exp(-etaIn))));
88 const float rOut = std::abs(layerZ * std::tan(2.f * std::atan(std::exp(-etaOut))));
89 const bool isMiddleLayer = layerNumber < 3;
90 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName, layerZ, rIn, rOut, Layerx2X0, isMiddleLayer);
91 }
92 }
93}
94
95//_________________________________________________________________________________________________
97{
98 // Build FT3 detector according to
99 // https://indico.cern.ch/event/992488/contributions/4174473/attachments/2168881/3661331/tracker_parameters_werner_jan_11_2021.pdf
100
101 LOG(info) << "Building FT3 Detector: V1";
102
103 const int numberOfLayers = 10;
104 const float sensorThickness = 30.e-4;
105 const float layersx2X0 = 1.e-2;
106 const std::vector<std::array<float, 4>> layersConfig{
107 {26., .5, 3., 0.1f * layersx2X0}, // {z_layer, r_in, r_out, Layerx2X0}
108 {30., .5, 3., 0.1f * layersx2X0},
109 {34., .5, 3., 0.1f * layersx2X0},
110 {77., 3.5, 35., layersx2X0},
111 {100., 3.5, 35., layersx2X0},
112 {122., 3.5, 35., layersx2X0},
113 {150., 3.5, 80.f, layersx2X0},
114 {180., 3.5, 80.f, layersx2X0},
115 {220., 3.5, 80.f, layersx2X0},
116 {279., 3.5, 80.f, layersx2X0}};
117
118 mLayerName[IdxBackwardDisks].resize(numberOfLayers);
119 mLayerName[IdxForwardDisks].resize(numberOfLayers);
120
121 for (auto direction : {IdxBackwardDisks, IdxForwardDisks}) {
122 for (int layerNumber = 0; layerNumber < numberOfLayers; layerNumber++) {
123 std::string directionName = std::to_string(direction);
124 std::string layerName = GeometryTGeo::getFT3LayerPattern() + directionName + std::string("_") + std::to_string(layerNumber);
125 mLayerName[direction][layerNumber] = layerName;
126 auto& z = layersConfig[layerNumber][0];
127
128 auto& rIn = layersConfig[layerNumber][1];
129 auto& rOut = layersConfig[layerNumber][2];
130 auto& x0 = layersConfig[layerNumber][3];
131
132 LOG(info) << "Adding Layer " << layerName << " at z = " << z;
133 // Add layers
134 const bool isMiddleLayer = layerNumber < 3;
135 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName, z, rIn, rOut, x0, isMiddleLayer);
136 }
137 }
138}
139
140//_________________________________________________________________________________________________
142{
143 // Build FT3 detector according to
144 // https://www.overleaf.com/project/6051acc870e39aaeb4653621
145
146 LOG(info) << "Building FT3 Detector: V3b";
147
148 const int numberOfLayers = 12;
149 float sensorThickness = 30.e-4;
150 float layersx2X0 = 1.e-2;
151 std::vector<std::array<float, 4>> layersConfig{
152 {26., .5, 3., 0.1f * layersx2X0}, // {z_layer, r_in, r_out, Layerx2X0}
153 {30., .5, 3., 0.1f * layersx2X0},
154 {34., .5, 3., 0.1f * layersx2X0},
155 {77., 5.0, 35., layersx2X0},
156 {100., 5.0, 35., layersx2X0},
157 {122., 5.0, 35., layersx2X0},
158 {150., 5.5, 80.f, layersx2X0},
159 {180., 6.6, 80.f, layersx2X0},
160 {220., 8.1, 80.f, layersx2X0},
161 {279., 10.2, 80.f, layersx2X0},
162 {340., 12.5, 80.f, layersx2X0},
163 {400., 14.7, 80.f, layersx2X0}};
164
165 mLayerName[IdxBackwardDisks].resize(numberOfLayers);
166 mLayerName[IdxForwardDisks].resize(numberOfLayers);
167
168 for (auto direction : {IdxBackwardDisks, IdxForwardDisks}) {
169 for (int layerNumber = 0; layerNumber < numberOfLayers; layerNumber++) {
170 std::string directionName = std::to_string(direction);
171 std::string layerName = GeometryTGeo::getFT3LayerPattern() + directionName + std::string("_") + std::to_string(layerNumber);
172 mLayerName[direction][layerNumber] = layerName;
173 auto& z = layersConfig[layerNumber][0];
174
175 auto& rIn = layersConfig[layerNumber][1];
176 auto& rOut = layersConfig[layerNumber][2];
177 auto& x0 = layersConfig[layerNumber][3];
178
179 LOG(info) << "Adding Layer " << layerName << " at z = " << z;
180 // Add layers
181 const bool isMiddleLayer = layerNumber < 3;
182 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName, z, rIn, rOut, x0, isMiddleLayer);
183 }
184 }
185}
186
188{
189 // Build the FT3 detector according to changes proposed during
190 // https://indico.cern.ch/event/1407704/
191 // to adhere to the changes that were presented at the ALICE 3 Upgrade days in March 2024
192 // Inner radius at C-side to 7 cm
193 // Inner radius at A-side stays at 5 cm
194 // 06.02.2025 update: IRIS layers are now in TRK
195
196 LOG(info) << "Building FT3 Detector: After Upgrade Days March 2024 version";
197
198 const int numberOfLayers = 9;
199 const float sensorThickness = 30.e-4;
200 const float layersx2X0 = 1.e-2;
201 const std::vector<std::array<float, 4>> layersConfigCSide{
202 {77., 7.0, 35., layersx2X0}, // {z_layer, r_in, r_out, Layerx2X0}
203 {100., 7.0, 35., layersx2X0},
204 {122., 7.0, 35., layersx2X0},
205 {150., 7.0, 68.f, layersx2X0},
206 {180., 7.0, 68.f, layersx2X0},
207 {220., 7.0, 68.f, layersx2X0},
208 {260., 7.0, 68.f, layersx2X0},
209 {300., 7.0, 68.f, layersx2X0},
210 {350., 7.0, 68.f, layersx2X0}};
211
212 const std::vector<std::array<float, 4>> layersConfigASide{
213 {77., 5.0, 35., layersx2X0}, // {z_layer, r_in, r_out, Layerx2X0}
214 {100., 5.0, 35., layersx2X0},
215 {122., 5.0, 35., layersx2X0},
216 {150., 5.0, 68.f, layersx2X0},
217 {180., 5.0, 68.f, layersx2X0},
218 {220., 5.0, 68.f, layersx2X0},
219 {260., 5.0, 68.f, layersx2X0},
220 {300., 5.0, 68.f, layersx2X0},
221 {350., 5.0, 68.f, layersx2X0}};
222
223 mLayerName[IdxBackwardDisks].resize(numberOfLayers);
224 mLayerName[IdxForwardDisks].resize(numberOfLayers);
225
226 for (auto direction : {IdxBackwardDisks, IdxForwardDisks}) {
227 for (int layerNumber = 0; layerNumber < numberOfLayers; layerNumber++) {
228 std::string directionName = std::to_string(direction);
229 std::string layerName = GeometryTGeo::getFT3LayerPattern() + directionName + std::string("_") + std::to_string(layerNumber);
230 mLayerName[direction][layerNumber] = layerName;
231 float z, rIn, rOut, x0;
232 if (direction == 0) { // C-Side
233 z = layersConfigCSide[layerNumber][0];
234 rIn = layersConfigCSide[layerNumber][1];
235 rOut = layersConfigCSide[layerNumber][2];
236 x0 = layersConfigCSide[layerNumber][3];
237 } else if (direction == 1) { // A-Side
238 z = layersConfigASide[layerNumber][0];
239 rIn = layersConfigASide[layerNumber][1];
240 rOut = layersConfigASide[layerNumber][2];
241 x0 = layersConfigASide[layerNumber][3];
242 }
243
244 LOG(info) << "Adding Layer " << layerName << " at z = " << z;
245 // Add layers
246 const bool isMiddleLayer = layerNumber < 3;
247 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName, z, rIn, rOut, x0, isMiddleLayer);
248 }
249 }
250}
251
253{
254 // Build the FT3 detector according to v3 layout
255 // https://indico.cern.ch/event/1596309/contributions/6728167/attachments/3190117/5677220/2025-12-10-AW-ALICE3planning.pdf
256 // Middle disks inner radius 10 cm
257 // Outer disks inner radius 20 cm
258
259 LOG(info) << "Building FT3 Detector: v3 scoping version";
260
261 const int numberOfLayers = 6;
262 const float sensorThickness = 30.e-4;
263 const float layersx2X0 = 1.e-2;
264 using LayerConfig = std::array<float, 4>; // {z_layer, r_in, r_out, Layerx2X0}
265 const std::array<LayerConfig, numberOfLayers> layersConfigCSide{LayerConfig{77., 10.0, 35., layersx2X0},
266 LayerConfig{100., 10.0, 35., layersx2X0},
267 LayerConfig{122., 10.0, 35., layersx2X0},
268 LayerConfig{150., 20.0, 68.f, layersx2X0},
269 LayerConfig{180., 20.0, 68.f, layersx2X0},
270 LayerConfig{220., 20.0, 68.f, layersx2X0}};
271
272 const std::array<LayerConfig, numberOfLayers> layersConfigASide{LayerConfig{77., 10.0, 35., layersx2X0},
273 LayerConfig{100., 10.0, 35., layersx2X0},
274 LayerConfig{122., 10.0, 35., layersx2X0},
275 LayerConfig{150., 20.0, 68.f, layersx2X0},
276 LayerConfig{180., 20.0, 68.f, layersx2X0},
277 LayerConfig{220., 20.0, 68.f, layersx2X0}};
278 const std::array<bool, numberOfLayers> enabled{true, true, true, true, true, true}; // To enable or disable layers for debug purpose
279
280 for (int direction : {IdxBackwardDisks, IdxForwardDisks}) {
281 mLayerName[direction].clear();
282 const std::array<LayerConfig, numberOfLayers>& layerConfig = (direction == IdxBackwardDisks) ? layersConfigCSide : layersConfigASide;
283 for (int layerNumber = 0; layerNumber < numberOfLayers; layerNumber++) {
284 if (!enabled[layerNumber]) {
285 continue;
286 }
287 const std::string directionName = std::to_string(direction);
288 const std::string layerName = GeometryTGeo::getFT3LayerPattern() + directionName + std::string("_") + std::to_string(layerNumber);
289 mLayerName[direction].push_back(layerName.c_str());
290 const float z = layerConfig[layerNumber][0];
291 const float rIn = layerConfig[layerNumber][1];
292 const float rOut = layerConfig[layerNumber][2];
293 const float x0 = layerConfig[layerNumber][3];
294 LOG(info) << "buildFT3ScopingV3 -> Adding Layer " << layerNumber << "/" << numberOfLayers << " " << layerName << " at z = " << z;
295 // Add layers
296 const bool isMiddleLayer = layerNumber < 3;
297 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName, z, rIn, rOut, x0, isMiddleLayer);
298 }
299 }
300}
301
302//_________________________________________________________________________________________________
304{
305 // Build FT3 detector according to the scoping document
306
307 LOG(info) << "Building FT3 Detector: Scoping document version";
308
309 const int numberOfLayers = 12;
310 const float sensorThickness = 30.e-4;
311 const float layersx2X0 = 1.e-2;
312 const std::vector<std::array<float, 4>> layersConfig{
313 {26., .5, 2.5, 0.1f * layersx2X0}, // {z_layer, r_in, r_out, Layerx2X0}
314 {30., .5, 2.5, 0.1f * layersx2X0},
315 {34., .5, 2.5, 0.1f * layersx2X0},
316 {77., 5.0, 35., layersx2X0},
317 {100., 5.0, 35., layersx2X0},
318 {122., 5.0, 35., layersx2X0},
319 {150., 5.0, 68.f, layersx2X0},
320 {180., 5.0, 68.f, layersx2X0},
321 {220., 5.0, 68.f, layersx2X0},
322 {260., 5.0, 68.f, layersx2X0},
323 {300., 5.0, 68.f, layersx2X0},
324 {350., 5.0, 68.f, layersx2X0}};
325
326 mLayerName[IdxBackwardDisks].resize(numberOfLayers);
327 mLayerName[IdxForwardDisks].resize(numberOfLayers);
328
329 for (auto direction : {IdxBackwardDisks, IdxForwardDisks}) {
330 for (int layerNumber = 0; layerNumber < numberOfLayers; layerNumber++) {
331 std::string directionName = std::to_string(direction);
332 std::string layerName = GeometryTGeo::getFT3LayerPattern() + directionName + std::string("_") + std::to_string(layerNumber);
333 mLayerName[direction][layerNumber] = layerName;
334 auto& z = layersConfig[layerNumber][0];
335 auto& rIn = layersConfig[layerNumber][1];
336 auto& rOut = layersConfig[layerNumber][2];
337 auto& x0 = layersConfig[layerNumber][3];
338
339 LOG(info) << "Adding Layer " << layerName << " at z = " << z;
340 // Add layers
341 const bool isMiddleLayer = layerNumber < 3;
342 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName, z, rIn, rOut, x0, isMiddleLayer);
343 }
344 }
345}
346
347//_________________________________________________________________________________________________
349 : o2::base::DetImpl<Detector>("FT3", active),
350 mTrackData(),
351 mHits(o2::utils::createSimVector<o2::trkft3::Hit>())
352{
353 buildFT3ScopingV3(); // v3 Dec 25
354}
355
356//_________________________________________________________________________________________________
358 : o2::base::DetImpl<Detector>(rhs),
359 mTrackData(),
361 mHits(o2::utils::createSimVector<o2::trkft3::Hit>())
362{
363 mLayerName = rhs.mLayerName;
364}
365
366//_________________________________________________________________________________________________
368{
369
370 if (mHits) {
371 // delete mHits;
373 }
374}
375
376//_________________________________________________________________________________________________
378{
379 // The standard = operator
380 // Inputs:
381 // Detector &h the sourse of this copy
382 // Outputs:
383 // none.
384 // Return:
385 // A copy of the sourse hit h
386
387 if (this == &rhs) {
388 return *this;
389 }
390
391 // base class assignment
393
394 mLayerName = rhs.mLayerName;
395 mLayers = rhs.mLayers;
396 mTrackData = rhs.mTrackData;
397
399 mHits = nullptr;
400
401 return *this;
402}
403
404//_________________________________________________________________________________________________
406{
407 // Define the list of sensitive volumes
408 LOG(info) << "Initialize FT3 O2Detector";
409
410 defineSensitiveVolumes();
411}
412
413//_________________________________________________________________________________________________
414bool Detector::ProcessHits(FairVolume* vol)
415{
416 // This method is called from the MC stepping
417 if (!(fMC->TrackCharge())) {
418 return kFALSE;
419 }
420
421 int volID = vol->getMCid();
422
423 auto stack = (o2::data::Stack*)fMC->GetStack();
424
425 bool startHit = false, stopHit = false;
426 unsigned char status = 0;
427 if (fMC->IsTrackEntering()) {
428 status |= Hit::kTrackEntering;
429 }
430 if (fMC->IsTrackInside()) {
431 status |= Hit::kTrackInside;
432 }
433 if (fMC->IsTrackExiting()) {
434 status |= Hit::kTrackExiting;
435 }
436 if (fMC->IsTrackOut()) {
437 status |= Hit::kTrackOut;
438 }
439 if (fMC->IsTrackStop()) {
440 status |= Hit::kTrackStopped;
441 }
442 if (fMC->IsTrackAlive()) {
443 status |= Hit::kTrackAlive;
444 }
445
446 // track is entering or created in the volume
447 if ((status & Hit::kTrackEntering) || (status & Hit::kTrackInside && !mTrackData.mHitStarted)) {
448 startHit = true;
449 } else if ((status & (Hit::kTrackExiting | Hit::kTrackOut | Hit::kTrackStopped))) {
450 stopHit = true;
451 }
452
453 // increment energy loss at all steps except entrance
454 if (!startHit) {
455 mTrackData.mEnergyLoss += fMC->Edep();
456 }
457 if (!(startHit | stopHit)) {
458 return kFALSE; // do noting
459 }
460 if (startHit) {
461 mTrackData.mEnergyLoss = 0.;
462 fMC->TrackMomentum(mTrackData.mMomentumStart);
463 fMC->TrackPosition(mTrackData.mPositionStart);
464 mTrackData.mTrkStatusStart = status;
465 mTrackData.mHitStarted = true;
466 }
467 static auto* geom = GeometryTGeo::Instance();
468 if (stopHit) {
469 TLorentzVector positionStop;
470 fMC->TrackPosition(positionStop);
471 // Retrieve the chip index from the volume name
472 int chipindex = 0;
473 std::string volName = fMC->CurrentVolName();
474 int direction = -1, layer = -1, stave = -1, chip = -1;
475 geom->extractChipIds(volName, direction, layer, stave, chip);
476 chipindex = geom->getChipIndex(direction, layer, stave, chip);
477
478 Hit* p = addHit(stack->GetCurrentTrackNumber(), chipindex, mTrackData.mPositionStart.Vect(), positionStop.Vect(),
479 mTrackData.mMomentumStart.Vect(), mTrackData.mMomentumStart.E(), positionStop.T(),
480 mTrackData.mEnergyLoss, mTrackData.mTrkStatusStart, status);
481 // p->SetTotalEnergy(vmc->Etot());
482
483 // RS: not sure this is needed
484 // Increment number of Detector det points in TParticle
485 stack->addHit(GetDetId());
486 }
487
488 return kTRUE;
489}
490
491//_________________________________________________________________________________________________
493{
494 int ifield = 2;
495 float fieldm = 10.0;
497
498 float tmaxfdSi = 0.1; // .10000E+01; // Degree
499 float stemaxSi = 0.0075; // .10000E+01; // cm
500 float deemaxSi = 0.1; // 0.30000E-02; // Fraction of particle's energy 0<deemax<=1
501 float epsilSi = 1.0E-4; // .10000E+01;
502 float stminSi = 0.0; // cm "Default value used"
503
504 float tmaxfdAir = 0.1; // .10000E+01; // Degree
505 float stemaxAir = .10000E+01; // cm
506 float deemaxAir = 0.1; // 0.30000E-02; // Fraction of particle's energy 0<deemax<=1
507 float epsilAir = 1.0E-4; // .10000E+01;
508 float stminAir = 0.0; // cm "Default value used"
509
510 // AIR
511 float aAir[4] = {12.0107, 14.0067, 15.9994, 39.948};
512 float zAir[4] = {6., 7., 8., 18.};
513 float wAir[4] = {0.000124, 0.755267, 0.231781, 0.012827};
514 float dAir = 1.20479E-3;
515
516 o2::base::Detector::Mixture(1, "AIR$", aAir, zAir, dAir, 4, wAir);
517 o2::base::Detector::Medium(1, "AIR$", 1, 0, ifield, fieldm, tmaxfdAir, stemaxAir, deemaxAir, epsilAir, stminAir);
518
519 o2::base::Detector::Material(3, "SILICON$", 0.28086E+02, 0.14000E+02, 0.23300E+01, 0.93600E+01, 0.99900E+03);
520 o2::base::Detector::Medium(3, "SILICON$", 3, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
521}
522
523//_________________________________________________________________________________________________
525
526//_________________________________________________________________________________________________
528{
529 // This will create a branch in the output tree called Hit, setting the last
530 // parameter to kFALSE means that this collection will not be written to the file,
531 // it will exist only during the simulation
532
533 if (FairRootManager::Instance()) {
534 FairRootManager::Instance()->RegisterAny(addNameTo("Hit").data(), mHits, kTRUE);
535 }
536}
537
538//_________________________________________________________________________________________________
540{
541 if (!o2::utils::ShmManager::Instance().isOperational()) {
542 mHits->clear();
543 }
544}
545
546//_________________________________________________________________________________________________
548{
549 // Create detector materials
551
552 // Construct the detector geometry
554}
555
556//_________________________________________________________________________________________________
558{
559
560 TGeoVolume* volFT3 = new TGeoVolumeAssembly(GeometryTGeo::getFT3VolPattern());
561 TGeoVolume* volIFT3 = new TGeoVolumeAssembly(GeometryTGeo::getFT3InnerVolPattern());
562
563 LOG(info) << "FT3: createGeometry volume name = " << GeometryTGeo::getFT3VolPattern();
564
565 TGeoVolume* vALIC = gGeoManager->GetVolume("barrel");
566 if (!vALIC) {
567 LOG(fatal) << "Could not find the top volume";
568 }
569
570 TGeoVolume* A3IPvac = gGeoManager->GetVolume("OUT_PIPEVACUUM");
571 if (!A3IPvac) {
572 LOG(info) << "Running simulation with no beam pipe.";
573 }
574
575 // This will need to adapt to the new scheme
576 if (!A3IPvac) {
577 for (int direction : {IdxBackwardDisks, IdxForwardDisks}) { // Backward layers at mLayers[0]; Forward layers at mLayers[1]
578 const std::string directionString = direction ? "Forward" : "Backward";
579 LOG(info) << " Creating FT3 without beampipe " << directionString << " layers:";
580 for (int iLayer = 0; iLayer < mLayers[direction].size(); iLayer++) {
581 mLayers[direction][iLayer].createLayer(volFT3);
582 }
583 }
584 vALIC->AddNode(volFT3, 2, new TGeoTranslation(0., 30., 0.));
585 } else { // If beampipe is enabled append inner disks to beampipe filling volume, this should be temporary.
586 for (int direction : {IdxBackwardDisks, IdxForwardDisks}) {
587 const std::string directionString = direction ? "Forward" : "Backward";
588 LOG(info) << " Creating FT3 " << directionString << " layers:";
589 for (int iLayer = 0; iLayer < mLayers[direction].size(); iLayer++) {
590 LOG(info) << " Creating " << directionString << " layer " << iLayer;
591 if (mLayers[direction][iLayer].getIsInMiddleLayer()) { // ML disks
592 mLayers[direction][iLayer].createLayer(volIFT3);
593 } else {
594 mLayers[direction][iLayer].createLayer(volFT3);
595 }
596 }
597 }
598 A3IPvac->AddNode(volIFT3, 2, new TGeoTranslation(0., 0., 0.));
599 vALIC->AddNode(volFT3, 2, new TGeoTranslation(0., 30., 0.));
600 }
601}
602
603//_________________________________________________________________________________________________
604void Detector::defineSensitiveVolumes()
605{
606 TGeoManager* geoManager = gGeoManager;
607
608 // Get the flat list of ALL volumes present in the geometry
609 TObjArray* allVolumes = geoManager->GetListOfVolumes();
610 int nVolumes = allVolumes->GetEntriesFast();
611
612 LOG(info) << "Adding FT3 Sensitive Volumes by iterating over all geometry volumes...";
613 static auto* geom = GeometryTGeo::Instance();
614
615 for (int direction : {IdxBackwardDisks, IdxForwardDisks}) {
616 for (int iLayer = 0; iLayer < getNumberOfLayers(); iLayer++) {
617 int iSens = 0;
618
619 // Build the "signatures" (prefixes) of the names for the various layouts for this specific layer and direction:
620
621 // 1. Trapezoidal/Cylindrical (format: FT3Sensor_<dir>_<layer>)
622 std::string sig1 = Form("%s_%d_%d", GeometryTGeo::getFT3SensorPattern(), direction, iLayer);
623
624 // 2. Segmented front/back (format: FT3Sensor_front_<layer>_<dir>_...)
625 std::string sig2 = "FT3Sensor_front_" + std::to_string(iLayer) + "_" + std::to_string(direction);
626 std::string sig3 = "FT3Sensor_back_" + std::to_string(iLayer) + "_" + std::to_string(direction);
627
628 // 3. SegmentedStave (format: FT3Sensor_<dir>_<layer>_...)
629 // Add the trailing underscore to avoid confusing it with sig1
630 std::string sig4 = "FT3Sensor_Active_" + std::to_string(direction) + "_" + std::to_string(iLayer) + "_";
631
632 // Iterate over all existing volumes to find matches
633 for (int i = 0; i < nVolumes; ++i) {
634 TGeoVolume* v = (TGeoVolume*)allVolumes->At(i);
635 std::string vName = v->GetName();
636
637 // Explicitly exclude the inactive silicon regions created in FT3Module
638 if (vName.find("Inactive") != std::string::npos || vName.find("inactive") != std::string::npos) {
639 continue;
640 }
641
642 // Check if the volume name matches one of our active sensors
643 bool isMatch = false;
644 if (vName == sig1) {
645 isMatch = true; // Exact match for Trapezoidal/Cylindrical layouts
646 } else if (vName.find(sig2) == 0 || vName.find(sig3) == 0 || vName.find(sig4) == 0) {
647 isMatch = true; // Prefix match for Segmented and SegmentedStave layouts
648 }
649
650 if (isMatch) {
651 AddSensitiveVolume(v);
652 iSens++;
653 }
654 }
655
656 if (iSens == 0) {
657 LOG(error) << "NO sensitive volume found for direction " << direction << ", layer " << iLayer;
658 } else {
659 LOG(info) << iSens << " sensitive volume(s) added for direction " << direction << " layer " << iLayer;
660 }
661 }
662 }
663}
664
665//_________________________________________________________________________________________________
666Hit* Detector::addHit(int trackID, int detID, const TVector3& startPos, const TVector3& endPos,
667 const TVector3& startMom, double startE, double endTime, double eLoss, unsigned char startStatus,
668 unsigned char endStatus)
669{
670 mHits->emplace_back(trackID, detID, startPos, endPos, startMom, startE, endTime, eLoss, startStatus, endStatus);
671 return &(mHits->back());
672}
673
Definition of the Stack class.
Definition of the FT3Layer class.
int32_t i
ClassImp(IdPath)
uint32_t stack
Definition RawData.h:1
Definition of the GeometryTGeo class.
Definition of the Detector class.
Detector & operator=(const Detector &)
Definition Detector.cxx:46
void Mixture(Int_t imat, const char *name, Float_t *a, Float_t *z, Float_t dens, Int_t nlmat, Float_t *wmat)
Definition Detector.cxx:66
void Medium(Int_t numed, const char *name, Int_t nmat, Int_t isvol, Int_t ifield, Float_t fieldm, Float_t tmaxfd, Float_t stemax, Float_t deemax, Float_t epsil, Float_t stmin, Float_t *ubuf=nullptr, Int_t nbuf=0)
Definition Detector.cxx:72
static void initFieldTrackingParams(int &mode, float &maxfield)
Definition Detector.cxx:143
void Material(Int_t imat, const char *name, Float_t a, Float_t z, Float_t dens, Float_t radl, Float_t absl, Float_t *buf=nullptr, Int_t nwbuf=0)
Definition Detector.cxx:59
std::string addNameTo(const char *ext) const
Definition Detector.h:150
std::array< std::vector< TString >, 2 > mLayerName
Definition Detector.h:118
void buildFT3ScopingV3()
Definition Detector.cxx:252
static constexpr int IdxBackwardDisks
Definition Detector.h:100
static constexpr int IdxForwardDisks
Definition Detector.h:99
Detector()
Default constructor.
Definition Detector.cxx:56
void buildBasicFT3(const FT3BaseParam &param)
Definition Detector.cxx:64
void buildFT3NewVacuumVessel()
Definition Detector.cxx:187
static const char * getFT3SensorPattern()
static const char * getFT3LayerPattern()
static const char * getFT3VolPattern()
static const char * getFT3InnerVolPattern()
void Reset() override
Definition Detector.cxx:444
void Register() override
Definition Detector.cxx:433
void ConstructGeometry() override
Definition Detector.cxx:84
void InitializeO2Detector() override
Definition Detector.cxx:382
o2::trkft3::Hit * addHit(int trackID, unsigned short detID, const TVector3 &startPos, const TVector3 &endPos, const TVector3 &startMom, double startE, double endTime, double eLoss, unsigned char startStatus, unsigned char endStatus)
Definition Detector.cxx:587
void EndOfEvent() override
Definition Detector.cxx:431
int getNumberOfLayers() const
Number of VD petals.
Definition Detector.h:106
bool ProcessHits(FairVolume *v=nullptr) override
Definition Detector.cxx:463
static GeometryTGeo * Instance()
static ShmManager & Instance()
Definition ShmManager.h:61
const GLdouble * v
Definition glcorearb.h:832
GLenum GLenum GLsizei const GLuint GLboolean enabled
Definition glcorearb.h:2513
GLboolean * data
Definition glcorearb.h:298
GLuint GLfloat x0
Definition glcorearb.h:5034
GLenum GLuint GLint GLint layer
Definition glcorearb.h:1310
GLenum GLfloat param
Definition glcorearb.h:271
GLdouble GLdouble GLdouble z
Definition glcorearb.h:843
void freeSimVector(std::vector< T > *ptr)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52
Common utility functions.
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"