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