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