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
20
21#include "DetectorsBase/Stack.h"
23
24// FairRoot includes
25#include "FairDetector.h" // for FairDetector
26#include <fairlogger/Logger.h> // for LOG, LOG_IF
27#include "FairRootManager.h" // for FairRootManager
28#include "FairRun.h" // for FairRun
29#include "FairRuntimeDb.h" // for FairRuntimeDb
30#include "FairVolume.h" // for FairVolume
31#include "FairRootManager.h"
32
33#include "TGeoManager.h" // for TGeoManager, gGeoManager
34#include "TGeoTube.h" // for TGeoTube
35#include "TGeoPcon.h" // for TGeoPcon
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 <cstdio> // for NULL, snprintf
42
43#define MAX_SENSORS 2000
44
45class FairModule;
46
47class TGeoMedium;
48
49class TParticle;
50
51using namespace o2::ft3;
52using o2::itsmft::Hit;
53
54//_________________________________________________________________________________________________
56 : o2::base::DetImpl<Detector>("FT3", kTRUE),
57 mTrackData(),
58 mHits(o2::utils::createSimVector<o2::itsmft::Hit>())
59{
60}
61
62//_________________________________________________________________________________________________
63void Detector::buildFT3FromFile(std::string configFileName)
64{
65 // Geometry description from file. One line per disk
66 // z_layer r_in r_out Layerx2X0
67 // This simple file reader is not failproof. Do not add empty lines!
68
69 /*
70 # Sample FT3 configuration
71 # z_layer r_in r_out Layerx2X0
72 -45.3 2.5 9.26 0.0042
73 -46.7 2.5 9.26 0.0042
74 -48.6 2.5 9.8 0.0042
75 -50.0 2.5 9.8 0.0042
76 -52.4 2.5 10.43 0.0042
77 -53.8 2.5 10.43 0.0042
78 -67.7 3.82 13.01 0.0042
79 -69.1 3.82 13.01 0.0042
80 -76.1 3.92 14.35 0.0042
81 -77.5 3.92 14.35 0.0042
82 */
83
84 mLayerName.clear();
85 mLayers.clear();
86 mLayerID.clear();
87 mLayerName.resize(1);
88 mLayers.resize(1);
89
90 LOG(info) << "Building FT3 Detector: From file";
91 LOG(info) << " FT3 detector configuration: " << configFileName;
92 std::ifstream ifs(configFileName.c_str());
93 if (!ifs.good()) {
94 LOG(fatal) << " Invalid FT3Base.configFile!";
95 }
96 std::string tempstr;
97 float z_layer, r_in, r_out, Layerx2X0;
98 char delimiter;
99 int layerNumber = 0;
100 while (std::getline(ifs, tempstr)) {
101 if (tempstr[0] == '#') {
102 LOG(info) << " Comment: " << tempstr;
103 continue;
104 }
105 std::istringstream iss(tempstr);
106 iss >> z_layer;
107 iss >> r_in;
108 iss >> r_out;
109 iss >> Layerx2X0;
110
111 int direction = 1; // Forwards
112 if (z_layer < 0) {
113 // Backwards
114 direction = 0;
115 }
116
117 std::string directionName = std::to_string(direction);
118 std::string layerName = GeometryTGeo::getFT3LayerPattern() + directionName + std::string("_") + std::to_string(layerNumber);
119 mLayerName[0].push_back(layerName);
120 LOG(info) << "Adding Layer " << layerName << " at z = " << z_layer << " ; direction = " << direction << " ; r_in = " << r_in << " ; r_out = " << r_out << " x/X0 = " << Layerx2X0;
121 auto& thisLayer = mLayers[0].emplace_back(direction, layerNumber, layerName, z_layer, r_in, r_out, Layerx2X0);
122 layerNumber++;
123 }
124
125 mNumberOfLayers = layerNumber;
126 LOG(info) << " Loaded FT3 Detector with " << mNumberOfLayers << " layers";
127}
128
129//_________________________________________________________________________________________________
131{
132 // Export FT3 Layout description to file.
133 // One line per disk:
134 // z_layer r_in r_out Layerx2X0
135
136 std::string configFileName = "FT3_layout.cfg";
137
138 LOG(info) << "Exporting FT3 Detector layout to " << configFileName;
139
140 std::ofstream fOut(configFileName.c_str(), std::ios::out);
141 if (!fOut) {
142 printf("Cannot open file\n");
143 return;
144 }
145 fOut << "# z_layer r_in r_out Layerx2X0" << std::endl;
146 for (auto layers_dir : mLayers) {
147 for (auto layer : layers_dir) {
148 fOut << layer.getZ() << " " << layer.getInnerRadius() << " " << layer.getOuterRadius() << " " << layer.getx2X0() << std::endl;
149 }
150 }
151}
152
153//_________________________________________________________________________________________________
155{
156 // Build a basic parametrized FT3 detector with nLayers equally spaced between z_first and z_first+z_length
157 // Covering pseudo rapidity [etaIn,etaOut]. Silicon thinkness computed to match layer x/X0
158
159 LOG(info) << "Building FT3 Detector: Conical Telescope";
160
161 auto z_first = param.z0;
162 auto z_length = param.zLength;
163 auto etaIn = param.etaIn;
164 auto etaOut = param.etaOut;
165 auto Layerx2X0 = param.Layerx2X0;
166 mNumberOfLayers = param.nLayers;
167 mLayerName.resize(2);
168 mLayerName[0].resize(mNumberOfLayers);
169 mLayerName[1].resize(mNumberOfLayers);
170 mLayerID.clear();
171 mLayers.resize(2);
172
173 for (int direction : {0, 1}) {
174 for (int layerNumber = 0; layerNumber < mNumberOfLayers; layerNumber++) {
175 std::string layerName = GeometryTGeo::getFT3LayerPattern() + std::to_string(layerNumber + mNumberOfLayers * direction);
176 mLayerName[direction][layerNumber] = layerName;
177
178 // Adds evenly spaced layers
179 float layerZ = z_first + (layerNumber * z_length / (mNumberOfLayers - 1)) * std::copysign(1, z_first);
180 float rIn = std::abs(layerZ * std::tan(2.f * std::atan(std::exp(-etaIn))));
181 float rOut = std::abs(layerZ * std::tan(2.f * std::atan(std::exp(-etaOut))));
182 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName, layerZ, rIn, rOut, Layerx2X0);
183 }
184 }
185}
186
187//_________________________________________________________________________________________________
189{
190 // Build FT3 detector according to
191 // https://indico.cern.ch/event/992488/contributions/4174473/attachments/2168881/3661331/tracker_parameters_werner_jan_11_2021.pdf
192
193 LOG(info) << "Building FT3 Detector: V1";
194
195 mNumberOfLayers = 10;
196 float sensorThickness = 30.e-4;
197 float layersx2X0 = 1.e-2;
198 std::vector<std::array<float, 5>> layersConfig{
199 {26., .5, 3., 0.1f * layersx2X0}, // {z_layer, r_in, r_out, Layerx2X0}
200 {30., .5, 3., 0.1f * layersx2X0},
201 {34., .5, 3., 0.1f * layersx2X0},
202 {77., 3.5, 35., layersx2X0},
203 {100., 3.5, 35., layersx2X0},
204 {122., 3.5, 35., layersx2X0},
205 {150., 3.5, 80.f, layersx2X0},
206 {180., 3.5, 80.f, layersx2X0},
207 {220., 3.5, 80.f, layersx2X0},
208 {279., 3.5, 80.f, layersx2X0}};
209
210 mLayerName.resize(2);
211 mLayerName[0].resize(mNumberOfLayers);
212 mLayerName[1].resize(mNumberOfLayers);
213 mLayerID.clear();
214 mLayers.resize(2);
215
216 for (auto direction : {0, 1}) {
217 for (int layerNumber = 0; layerNumber < mNumberOfLayers; layerNumber++) {
218 std::string directionName = std::to_string(direction);
219 std::string layerName = GeometryTGeo::getFT3LayerPattern() + directionName + std::string("_") + std::to_string(layerNumber);
220 mLayerName[direction][layerNumber] = layerName;
221 auto& z = layersConfig[layerNumber][0];
222
223 auto& rIn = layersConfig[layerNumber][1];
224 auto& rOut = layersConfig[layerNumber][2];
225 auto& x0 = layersConfig[layerNumber][3];
226
227 LOG(info) << "Adding Layer " << layerName << " at z = " << z;
228 // Add layers
229 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName, z, rIn, rOut, x0);
230 }
231 }
232}
233
234//_________________________________________________________________________________________________
236{
237 // Build FT3 detector according to
238 // https://www.overleaf.com/project/6051acc870e39aaeb4653621
239
240 LOG(info) << "Building FT3 Detector: V3b";
241
242 mNumberOfLayers = 12;
243 float sensorThickness = 30.e-4;
244 float layersx2X0 = 1.e-2;
245 std::vector<std::array<float, 5>> layersConfig{
246 {26., .5, 3., 0.1f * layersx2X0}, // {z_layer, r_in, r_out, Layerx2X0}
247 {30., .5, 3., 0.1f * layersx2X0},
248 {34., .5, 3., 0.1f * layersx2X0},
249 {77., 5.0, 35., layersx2X0},
250 {100., 5.0, 35., layersx2X0},
251 {122., 5.0, 35., layersx2X0},
252 {150., 5.5, 80.f, layersx2X0},
253 {180., 6.6, 80.f, layersx2X0},
254 {220., 8.1, 80.f, layersx2X0},
255 {279., 10.2, 80.f, layersx2X0},
256 {340., 12.5, 80.f, layersx2X0},
257 {400., 14.7, 80.f, layersx2X0}};
258
259 mLayerName.resize(2);
260 mLayerName[0].resize(mNumberOfLayers);
261 mLayerName[1].resize(mNumberOfLayers);
262 mLayerID.clear();
263 mLayers.resize(2);
264
265 for (auto direction : {0, 1}) {
266 for (int layerNumber = 0; layerNumber < mNumberOfLayers; layerNumber++) {
267 std::string directionName = std::to_string(direction);
268 std::string layerName = GeometryTGeo::getFT3LayerPattern() + directionName + std::string("_") + std::to_string(layerNumber);
269 mLayerName[direction][layerNumber] = layerName;
270 auto& z = layersConfig[layerNumber][0];
271
272 auto& rIn = layersConfig[layerNumber][1];
273 auto& rOut = layersConfig[layerNumber][2];
274 auto& x0 = layersConfig[layerNumber][3];
275
276 LOG(info) << "Adding Layer " << layerName << " at z = " << z;
277 // Add layers
278 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName, z, rIn, rOut, x0);
279 }
280 }
281}
282
284{
285 // Build the FT3 detector according to changes proposed during
286 // https://indico.cern.ch/event/1407704/
287 // to adhere to the changes that were presented at the ALICE 3 Upgrade days in March 2024
288 // Inner radius at C-side to 7 cm
289 // Inner radius at A-side stays at 5 cm
290 // 06.02.2025 update: IRIS layers are now in TRK
291
292 LOG(info) << "Building FT3 Detector: After Upgrade Days March 2024 version";
293
294 mNumberOfLayers = 9;
295 float sensorThickness = 30.e-4;
296 float layersx2X0 = 1.e-2;
297 std::vector<std::array<float, 5>> layersConfigCSide{
298 {77., 7.0, 35., layersx2X0}, // {z_layer, r_in, r_out, Layerx2X0}
299 {100., 7.0, 35., layersx2X0},
300 {122., 7.0, 35., layersx2X0},
301 {150., 7.0, 68.f, layersx2X0},
302 {180., 7.0, 68.f, layersx2X0},
303 {220., 7.0, 68.f, layersx2X0},
304 {260., 7.0, 68.f, layersx2X0},
305 {300., 7.0, 68.f, layersx2X0},
306 {350., 7.0, 68.f, layersx2X0}};
307
308 std::vector<std::array<float, 5>> layersConfigASide{
309 {77., 5.0, 35., layersx2X0}, // {z_layer, r_in, r_out, Layerx2X0}
310 {100., 5.0, 35., layersx2X0},
311 {122., 5.0, 35., layersx2X0},
312 {150., 5.0, 68.f, layersx2X0},
313 {180., 5.0, 68.f, layersx2X0},
314 {220., 5.0, 68.f, layersx2X0},
315 {260., 5.0, 68.f, layersx2X0},
316 {300., 5.0, 68.f, layersx2X0},
317 {350., 5.0, 68.f, layersx2X0}};
318
319 mLayerName.resize(2);
320 mLayerName[0].resize(mNumberOfLayers);
321 mLayerName[1].resize(mNumberOfLayers);
322 mLayerID.clear();
323 mLayers.resize(2);
324
325 for (auto direction : {0, 1}) {
326 for (int layerNumber = 0; layerNumber < mNumberOfLayers; layerNumber++) {
327 std::string directionName = std::to_string(direction);
328 std::string layerName = GeometryTGeo::getFT3LayerPattern() + directionName + std::string("_") + std::to_string(layerNumber);
329 mLayerName[direction][layerNumber] = layerName;
330 float z, rIn, rOut, x0;
331 if (direction == 0) { // C-Side
332 z = layersConfigCSide[layerNumber][0];
333 rIn = layersConfigCSide[layerNumber][1];
334 rOut = layersConfigCSide[layerNumber][2];
335 x0 = layersConfigCSide[layerNumber][3];
336 } else if (direction == 1) { // A-Side
337 z = layersConfigASide[layerNumber][0];
338 rIn = layersConfigASide[layerNumber][1];
339 rOut = layersConfigASide[layerNumber][2];
340 x0 = layersConfigASide[layerNumber][3];
341 }
342
343 LOG(info) << "Adding Layer " << layerName << " at z = " << z;
344 // Add layers
345 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName, z, rIn, rOut, x0);
346 }
347 }
348}
349
351{
352 // Build the FT3 detector according to v3 layout
353 // https://indico.cern.ch/event/1596309/contributions/6728167/attachments/3190117/5677220/2025-12-10-AW-ALICE3planning.pdf
354 // Middle disks inner radius 10 cm
355 // Outer disks inner radius 20 cm
356
357 LOG(info) << "Building FT3 Detector: v3 scoping version";
358
359 mNumberOfLayers = 6;
360 float sensorThickness = 30.e-4;
361 float layersx2X0 = 1.e-2;
362 std::vector<std::array<float, 5>> layersConfigCSide{
363 {77., 10.0, 35., layersx2X0}, // {z_layer, r_in, r_out, Layerx2X0}
364 {100., 10.0, 35., layersx2X0},
365 {122., 10.0, 35., layersx2X0},
366 {150., 20.0, 68.f, layersx2X0},
367 {180., 20.0, 68.f, layersx2X0},
368 {220., 20.0, 68.f, layersx2X0}};
369
370 std::vector<std::array<float, 5>> layersConfigASide{
371 {77., 10.0, 35., layersx2X0}, // {z_layer, r_in, r_out, Layerx2X0}
372 {100., 10.0, 35., layersx2X0},
373 {122., 10.0, 35., layersx2X0},
374 {150., 20.0, 68.f, layersx2X0},
375 {180., 20.0, 68.f, layersx2X0},
376 {220., 20.0, 68.f, layersx2X0}};
377
378 mLayerName.resize(2);
379 mLayerName[0].resize(mNumberOfLayers);
380 mLayerName[1].resize(mNumberOfLayers);
381 mLayerID.clear();
382 mLayers.resize(2);
383
384 for (auto direction : {0, 1}) {
385 for (int layerNumber = 0; layerNumber < mNumberOfLayers; layerNumber++) {
386 std::string directionName = std::to_string(direction);
387 std::string layerName = GeometryTGeo::getFT3LayerPattern() + directionName + std::string("_") + std::to_string(layerNumber);
388 mLayerName[direction][layerNumber] = layerName;
389 float z, rIn, rOut, x0;
390 if (direction == 0) { // C-Side
391 z = layersConfigCSide[layerNumber][0];
392 rIn = layersConfigCSide[layerNumber][1];
393 rOut = layersConfigCSide[layerNumber][2];
394 x0 = layersConfigCSide[layerNumber][3];
395 } else if (direction == 1) { // A-Side
396 z = layersConfigASide[layerNumber][0];
397 rIn = layersConfigASide[layerNumber][1];
398 rOut = layersConfigASide[layerNumber][2];
399 x0 = layersConfigASide[layerNumber][3];
400 }
401
402 LOG(info) << "Adding Layer " << layerName << " at z = " << z;
403 // Add layers
404 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName, z, rIn, rOut, x0);
405 }
406 }
407}
408
409//_________________________________________________________________________________________________
411{
412 // Build FT3 detector according to the scoping document
413
414 LOG(info) << "Building FT3 Detector: Scoping document version";
415
416 mNumberOfLayers = 12;
417 float sensorThickness = 30.e-4;
418 float layersx2X0 = 1.e-2;
419 std::vector<std::array<float, 5>> layersConfig{
420 {26., .5, 2.5, 0.1f * layersx2X0}, // {z_layer, r_in, r_out, Layerx2X0}
421 {30., .5, 2.5, 0.1f * layersx2X0},
422 {34., .5, 2.5, 0.1f * layersx2X0},
423 {77., 5.0, 35., layersx2X0},
424 {100., 5.0, 35., layersx2X0},
425 {122., 5.0, 35., layersx2X0},
426 {150., 5.0, 68.f, layersx2X0},
427 {180., 5.0, 68.f, layersx2X0},
428 {220., 5.0, 68.f, layersx2X0},
429 {260., 5.0, 68.f, layersx2X0},
430 {300., 5.0, 68.f, layersx2X0},
431 {350., 5.0, 68.f, layersx2X0}};
432
433 mLayerName.resize(2);
434 mLayerName[0].resize(mNumberOfLayers);
435 mLayerName[1].resize(mNumberOfLayers);
436 mLayerID.clear();
437 mLayers.resize(2);
438
439 for (auto direction : {0, 1}) {
440 for (int layerNumber = 0; layerNumber < mNumberOfLayers; layerNumber++) {
441 std::string directionName = std::to_string(direction);
442 std::string layerName = GeometryTGeo::getFT3LayerPattern() + directionName + std::string("_") + std::to_string(layerNumber);
443 mLayerName[direction][layerNumber] = layerName;
444 auto& z = layersConfig[layerNumber][0];
445
446 auto& rIn = layersConfig[layerNumber][1];
447 auto& rOut = layersConfig[layerNumber][2];
448 auto& x0 = layersConfig[layerNumber][3];
449
450 LOG(info) << "Adding Layer " << layerName << " at z = " << z;
451 // Add layers
452 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName, z, rIn, rOut, x0);
453 }
454 }
455}
456
457//_________________________________________________________________________________________________
459 : o2::base::DetImpl<Detector>("FT3", active),
460 mTrackData(),
461 mHits(o2::utils::createSimVector<o2::itsmft::Hit>())
462{
463
464 // FT3 Base configuration parameters
465 auto& ft3BaseParam = FT3BaseParam::Instance();
466
467 if (ft3BaseParam.configFile != "") {
468 LOG(info) << "FT3 Geometry configuration file provided. Overriding FT3Base.geoModel configuration.";
469 buildFT3FromFile(ft3BaseParam.configFile);
470
471 } else {
472 switch (ft3BaseParam.geoModel) {
473 case Default:
474 buildFT3ScopingV3(); // v3 Dec 25
475 break;
476 case Telescope:
477 buildBasicFT3(ft3BaseParam); // BasicFT3 = Parametrized telescopic detector (equidistant layers)
478 break;
479 default:
480 LOG(fatal) << "Invalid Geometry.\n";
481 break;
482 }
483 }
484 exportLayout();
485}
486
487//_________________________________________________________________________________________________
489 : o2::base::DetImpl<Detector>(rhs),
490 mTrackData(),
491
493 mHits(o2::utils::createSimVector<o2::itsmft::Hit>())
494{
495 mLayerID = rhs.mLayerID;
496 mLayerName = rhs.mLayerName;
497 mNumberOfLayers = rhs.mNumberOfLayers;
498}
499
500//_________________________________________________________________________________________________
502{
503
504 if (mHits) {
505 // delete mHits;
507 }
508}
509
510//_________________________________________________________________________________________________
512{
513 // The standard = operator
514 // Inputs:
515 // Detector &h the sourse of this copy
516 // Outputs:
517 // none.
518 // Return:
519 // A copy of the sourse hit h
520
521 if (this == &rhs) {
522 return *this;
523 }
524
525 // base class assignment
527
528 mLayerID = rhs.mLayerID;
529 mLayerName = rhs.mLayerName;
530 mNumberOfLayers = rhs.mNumberOfLayers;
531 mLayers = rhs.mLayers;
532 mTrackData = rhs.mTrackData;
533
535 mHits = nullptr;
536
537 return *this;
538}
539
540//_________________________________________________________________________________________________
542{
543 // Define the list of sensitive volumes
544 LOG(info) << "Initialize FT3 O2Detector";
545
546 mGeometryTGeo = GeometryTGeo::Instance();
547
548 defineSensitiveVolumes();
549}
550
551//_________________________________________________________________________________________________
552bool Detector::ProcessHits(FairVolume* vol)
553{
554 // This method is called from the MC stepping
555 if (!(fMC->TrackCharge())) {
556 return kFALSE;
557 }
558
559 int lay = 0, volID = vol->getMCid();
560 while ((lay <= mLayerID.size()) && (volID != mLayerID[lay])) {
561 ++lay;
562 }
563
564 auto stack = (o2::data::Stack*)fMC->GetStack();
565
566 bool startHit = false, stopHit = false;
567 unsigned char status = 0;
568 if (fMC->IsTrackEntering()) {
569 status |= Hit::kTrackEntering;
570 }
571 if (fMC->IsTrackInside()) {
572 status |= Hit::kTrackInside;
573 }
574 if (fMC->IsTrackExiting()) {
575 status |= Hit::kTrackExiting;
576 }
577 if (fMC->IsTrackOut()) {
578 status |= Hit::kTrackOut;
579 }
580 if (fMC->IsTrackStop()) {
581 status |= Hit::kTrackStopped;
582 }
583 if (fMC->IsTrackAlive()) {
584 status |= Hit::kTrackAlive;
585 }
586
587 // track is entering or created in the volume
588 if ((status & Hit::kTrackEntering) || (status & Hit::kTrackInside && !mTrackData.mHitStarted)) {
589 startHit = true;
590 } else if ((status & (Hit::kTrackExiting | Hit::kTrackOut | Hit::kTrackStopped))) {
591 stopHit = true;
592 }
593
594 // increment energy loss at all steps except entrance
595 if (!startHit) {
596 mTrackData.mEnergyLoss += fMC->Edep();
597 }
598 if (!(startHit | stopHit)) {
599 return kFALSE; // do noting
600 }
601 if (startHit) {
602 mTrackData.mEnergyLoss = 0.;
603 fMC->TrackMomentum(mTrackData.mMomentumStart);
604 fMC->TrackPosition(mTrackData.mPositionStart);
605 mTrackData.mTrkStatusStart = status;
606 mTrackData.mHitStarted = true;
607 }
608 if (stopHit) {
609 TLorentzVector positionStop;
610 fMC->TrackPosition(positionStop);
611 // Retrieve the indices with the volume path
612 int chipindex = lay;
613
614 Hit* p = addHit(stack->GetCurrentTrackNumber(), chipindex, mTrackData.mPositionStart.Vect(), positionStop.Vect(),
615 mTrackData.mMomentumStart.Vect(), mTrackData.mMomentumStart.E(), positionStop.T(),
616 mTrackData.mEnergyLoss, mTrackData.mTrkStatusStart, status);
617 // p->SetTotalEnergy(vmc->Etot());
618
619 // RS: not sure this is needed
620 // Increment number of Detector det points in TParticle
621 stack->addHit(GetDetId());
622 }
623
624 return kTRUE;
625}
626
627//_________________________________________________________________________________________________
628void Detector::createMaterials()
629{
630 int ifield = 2;
631 float fieldm = 10.0;
633
634 float tmaxfdSi = 0.1; // .10000E+01; // Degree
635 float stemaxSi = 0.0075; // .10000E+01; // cm
636 float deemaxSi = 0.1; // 0.30000E-02; // Fraction of particle's energy 0<deemax<=1
637 float epsilSi = 1.0E-4; // .10000E+01;
638 float stminSi = 0.0; // cm "Default value used"
639
640 float tmaxfdAir = 0.1; // .10000E+01; // Degree
641 float stemaxAir = .10000E+01; // cm
642 float deemaxAir = 0.1; // 0.30000E-02; // Fraction of particle's energy 0<deemax<=1
643 float epsilAir = 1.0E-4; // .10000E+01;
644 float stminAir = 0.0; // cm "Default value used"
645
646 // AIR
647 float aAir[4] = {12.0107, 14.0067, 15.9994, 39.948};
648 float zAir[4] = {6., 7., 8., 18.};
649 float wAir[4] = {0.000124, 0.755267, 0.231781, 0.012827};
650 float dAir = 1.20479E-3;
651
652 o2::base::Detector::Mixture(1, "AIR$", aAir, zAir, dAir, 4, wAir);
653 o2::base::Detector::Medium(1, "AIR$", 1, 0, ifield, fieldm, tmaxfdAir, stemaxAir, deemaxAir, epsilAir, stminAir);
654
655 o2::base::Detector::Material(3, "SILICON$", 0.28086E+02, 0.14000E+02, 0.23300E+01, 0.93600E+01, 0.99900E+03);
656 o2::base::Detector::Medium(3, "SILICON$", 3, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
657}
658
659//_________________________________________________________________________________________________
660void Detector::EndOfEvent() { Reset(); }
661
662//_________________________________________________________________________________________________
664{
665 // This will create a branch in the output tree called Hit, setting the last
666 // parameter to kFALSE means that this collection will not be written to the file,
667 // it will exist only during the simulation
668
669 if (FairRootManager::Instance()) {
670 FairRootManager::Instance()->RegisterAny(addNameTo("Hit").data(), mHits, kTRUE);
671 }
672}
673
674//_________________________________________________________________________________________________
676{
677 if (!o2::utils::ShmManager::Instance().isOperational()) {
678 mHits->clear();
679 }
680}
681
682//_________________________________________________________________________________________________
684{
685 // Create detector materials
686 createMaterials();
687
688 // Construct the detector geometry
689 createGeometry();
690}
691
692//_________________________________________________________________________________________________
693void Detector::createGeometry()
694{
695
696 mGeometryTGeo = GeometryTGeo::Instance();
697
698 TGeoVolume* volFT3 = new TGeoVolumeAssembly(GeometryTGeo::getFT3VolPattern());
699 TGeoVolume* volIFT3 = new TGeoVolumeAssembly(GeometryTGeo::getFT3InnerVolPattern());
700
701 LOG(info) << "GeometryBuilder::buildGeometry volume name = " << GeometryTGeo::getFT3VolPattern();
702
703 TGeoVolume* vALIC = gGeoManager->GetVolume("barrel");
704 if (!vALIC) {
705 LOG(fatal) << "Could not find the top volume";
706 }
707
708 TGeoVolume* A3IPvac = gGeoManager->GetVolume("OUT_PIPEVACUUM");
709 if (!A3IPvac) {
710 LOG(info) << "Running simulation with no beam pipe.";
711 }
712
713 LOG(debug) << "FT3 createGeometry: "
714 << Form("gGeoManager name is %s title is %s", gGeoManager->GetName(), gGeoManager->GetTitle());
715
716 if (mLayers.size() == 2) { // V1 and telescope
717 if (!A3IPvac) {
718 for (int direction : {0, 1}) { // Backward layers at mLayers[0]; Forward layers at mLayers[1]
719 std::string directionString = direction ? "Forward" : "Backward";
720 LOG(info) << "Creating FT3 " << directionString << " layers:";
721 for (int iLayer = 0; iLayer < mLayers[direction].size(); iLayer++) {
722 mLayers[direction][iLayer].createLayer(volFT3);
723 }
724 }
725 vALIC->AddNode(volFT3, 2, new TGeoTranslation(0., 30., 0.));
726 } else { // If beampipe is enabled append inner disks to beampipe filling volume, this should be temporary.
727 for (int direction : {0, 1}) {
728 std::string directionString = direction ? "Forward" : "Backward";
729 LOG(info) << "Creating FT3 " << directionString << " layers:";
730 for (int iLayer = 0; iLayer < mLayers[direction].size(); iLayer++) {
731 if (iLayer < 3) {
732 mLayers[direction][iLayer].createLayer(volIFT3);
733 } else {
734 mLayers[direction][iLayer].createLayer(volFT3);
735 }
736 }
737 }
738 A3IPvac->AddNode(volIFT3, 2, new TGeoTranslation(0., 0., 0.));
739 vALIC->AddNode(volFT3, 2, new TGeoTranslation(0., 30., 0.));
740 }
741
742 for (auto direction : {0, 1}) {
743 std::string directionString = direction ? "Forward" : "Backward";
744 LOG(info) << "Registering FT3 " << directionString << " LayerIDs:";
745 for (int iLayer = 0; iLayer < mLayers[direction].size(); iLayer++) {
746 auto layerID = gMC ? TVirtualMC::GetMC()->VolId(Form("%s_%d_%d", GeometryTGeo::getFT3SensorPattern(), direction, iLayer)) : 0;
747 mLayerID.push_back(layerID);
748 LOG(info) << " " << directionString << " layer " << iLayer << " LayerID " << layerID;
749 }
750 }
751 }
752
753 if (mLayers.size() == 1) { // All layers registered at mLayers[0], used when building from file
754 LOG(info) << "Creating FT3 layers:";
755 if (A3IPvac) {
756 for (int iLayer = 0; iLayer < mLayers[0].size(); iLayer++) {
757 if (std::abs(mLayers[0][iLayer].getZ()) < 25) {
758 mLayers[0][iLayer].createLayer(volIFT3);
759 } else {
760 mLayers[0][iLayer].createLayer(volFT3);
761 }
762 }
763 A3IPvac->AddNode(volIFT3, 2, new TGeoTranslation(0., 0., 0.));
764 vALIC->AddNode(volFT3, 2, new TGeoTranslation(0., 30., 0.));
765 } else {
766 for (int iLayer = 0; iLayer < mLayers[0].size(); iLayer++) {
767 mLayers[0][iLayer].createLayer(volFT3);
768 }
769 vALIC->AddNode(volFT3, 2, new TGeoTranslation(0., 30., 0.));
770 }
771 LOG(info) << "Registering FT3 LayerIDs:";
772 for (int iLayer = 0; iLayer < mLayers[0].size(); iLayer++) {
773 auto layerID = gMC ? TVirtualMC::GetMC()->VolId(Form("%s_%d_%d", GeometryTGeo::getFT3SensorPattern(), 0, iLayer)) : 0;
774 mLayerID.push_back(layerID);
775 LOG(info) << " mLayerID[" << iLayer << "] = " << layerID;
776 }
777 }
778}
779
780//_________________________________________________________________________________________________
781void Detector::defineSensitiveVolumes()
782{
783 TGeoManager* geoManager = gGeoManager;
784 TGeoVolume* v;
785
786 TString volumeName;
787 LOG(info) << "Adding FT3 Sensitive Volumes";
788
789 // The names of the FT3 sensitive volumes have the format: FT3Sensor_(0,1)_(0...sNumberLayers-1)
790 if (mLayers.size() == 2) {
791 for (int direction : {0, 1}) {
792 for (int iLayer = 0; iLayer < mNumberOfLayers; iLayer++) {
794 if (iLayer < 3) { // ML disks
795 v = geoManager->GetVolume(Form("%s_%d_%d", GeometryTGeo::getFT3SensorPattern(), direction, iLayer));
796 AddSensitiveVolume(v);
797 } else { // OT disks
798 for (int sensor_count = 0; sensor_count < MAX_SENSORS; ++sensor_count) {
799 std::string sensor_name_front = "FT3Sensor_front_" + std::to_string(iLayer) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
800 std::string sensor_name_back = "FT3Sensor_back_" + std::to_string(iLayer) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
801 v = geoManager->GetVolume(sensor_name_front.c_str());
802 if (v) {
803 AddSensitiveVolume(v);
804 }
805 v = geoManager->GetVolume(sensor_name_back.c_str());
806 if (v) {
807 AddSensitiveVolume(v);
808 }
809 }
810 }
811 }
812 }
813 }
814
815 if (mLayers.size() == 1) {
816 for (int iLayer = 0; iLayer < mLayers[0].size(); iLayer++) {
818 v = geoManager->GetVolume(Form("%s_%d_%d", GeometryTGeo::getFT3SensorPattern(), mLayers[0][iLayer].getDirection(), iLayer));
819 LOG(info) << "Adding FT3 Sensitive Volume => " << v->GetName();
820 AddSensitiveVolume(v);
821 }
822 }
823}
824
825//_________________________________________________________________________________________________
826Hit* Detector::addHit(int trackID, int detID, const TVector3& startPos, const TVector3& endPos,
827 const TVector3& startMom, double startE, double endTime, double eLoss, unsigned char startStatus,
828 unsigned char endStatus)
829{
830 mHits->emplace_back(trackID, detID, startPos, endPos, startMom, startE, endTime, eLoss, startStatus, endStatus);
831 return &(mHits->back());
832}
833
Definition of the Stack class.
Definition of the ITSMFT Hit class.
std::ostringstream debug
Definition of the FT3Layer class.
ClassImp(IdPath)
uint32_t stack
Definition RawData.h:1
Definition of the GeometryTGeo class.
Definition of the Detector class.
#define MAX_SENSORS
Definition Detector.cxx:43
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
virtual void InitializeO2Detector()=0
Definition Detector.cxx:98
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
void buildFT3ScopingV3()
Definition Detector.cxx:350
std::vector< std::vector< TString > > mLayerName
Definition Detector.h:128
void EndOfEvent() override
Definition Detector.cxx:660
o2::itsmft::Hit * addHit(int trackID, int detID, const TVector3 &startPos, const TVector3 &endPos, const TVector3 &startMom, double startE, double endTime, double eLoss, unsigned char startStatus, unsigned char endStatus)
This method is an example of how to add your own point of type Hit to the clones array.
Definition Detector.cxx:826
void Register() override
Registers the produced collections in FAIRRootManager.
Definition Detector.cxx:663
void buildFT3FromFile(std::string)
Definition Detector.cxx:63
void ConstructGeometry() override
Base class to create the detector geometry.
Definition Detector.cxx:683
Detector()
Default constructor.
Definition Detector.cxx:55
Bool_t ProcessHits(FairVolume *v=nullptr) override
This method is called for each step during simulation (see FairMCApplication::Stepping())
Definition Detector.cxx:552
std::vector< Int_t > mLayerID
Definition Detector.h:127
void buildBasicFT3(const FT3BaseParam &param)
Definition Detector.cxx:154
void buildFT3NewVacuumVessel()
Definition Detector.cxx:283
void Reset() override
Has to be called after each event to reset the containers.
Definition Detector.cxx:675
void exportLayout()
access to geometry details
Definition Detector.cxx:130
Int_t mNumberOfLayers
Definition Detector.h:129
static const char * getFT3SensorPattern()
static const char * getFT3LayerPattern()
static GeometryTGeo * Instance()
static const char * getFT3VolPattern()
static const char * getFT3InnerVolPattern()
static ShmManager & Instance()
Definition ShmManager.h:61
const GLdouble * v
Definition glcorearb.h:832
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"