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
350{
351 // Build the FT3 detector according to v3 layout
352 // https://indico.cern.ch/event/1596309/contributions/6728167/attachments/3190117/5677220/2025-12-10-AW-ALICE3planning.pdf
353 // Middle disks inner radius 10 cm
354 // Outer disks inner radius 20 cm
355
356 LOG(info) << "Building FT3 Detector: v3 scoping version";
357
358 mNumberOfLayers = 6;
359 float sensorThickness = 30.e-4;
360 float layersx2X0 = 1.e-2;
361 std::vector<std::array<float, 5>> layersConfigCSide{
362 {77., 10.0, 35., layersx2X0}, // {z_layer, r_in, r_out, Layerx2X0}
363 {100., 10.0, 35., layersx2X0},
364 {122., 10.0, 35., layersx2X0},
365 {150., 20.0, 68.f, layersx2X0},
366 {180., 20.0, 68.f, layersx2X0},
367 {220., 20.0, 68.f, layersx2X0}};
368
369 std::vector<std::array<float, 5>> layersConfigASide{
370 {77., 10.0, 35., layersx2X0}, // {z_layer, r_in, r_out, Layerx2X0}
371 {100., 10.0, 35., layersx2X0},
372 {122., 10.0, 35., layersx2X0},
373 {150., 20.0, 68.f, layersx2X0},
374 {180., 20.0, 68.f, layersx2X0},
375 {220., 20.0, 68.f, layersx2X0}};
376
377 mLayerName.resize(2);
378 mLayerName[0].resize(mNumberOfLayers);
379 mLayerName[1].resize(mNumberOfLayers);
380 mLayerID.clear();
381 mLayers.resize(2);
382
383 for (auto direction : {0, 1}) {
384 for (int layerNumber = 0; layerNumber < mNumberOfLayers; layerNumber++) {
385 std::string directionName = std::to_string(direction);
386 std::string layerName = GeometryTGeo::getFT3LayerPattern() + directionName + std::string("_") + std::to_string(layerNumber);
387 mLayerName[direction][layerNumber] = layerName;
388 float z, rIn, rOut, x0;
389 if (direction == 0) { // C-Side
390 z = layersConfigCSide[layerNumber][0];
391 rIn = layersConfigCSide[layerNumber][1];
392 rOut = layersConfigCSide[layerNumber][2];
393 x0 = layersConfigCSide[layerNumber][3];
394 } else if (direction == 1) { // A-Side
395 z = layersConfigASide[layerNumber][0];
396 rIn = layersConfigASide[layerNumber][1];
397 rOut = layersConfigASide[layerNumber][2];
398 x0 = layersConfigASide[layerNumber][3];
399 }
400
401 LOG(info) << "Adding Layer " << layerName << " at z = " << z;
402 // Add layers
403 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName, z, rIn, rOut, x0);
404 }
405 }
406}
407
408//_________________________________________________________________________________________________
410{
411 // Build FT3 detector according to the scoping document
412
413 LOG(info) << "Building FT3 Detector: Scoping document version";
414
415 mNumberOfLayers = 12;
416 float sensorThickness = 30.e-4;
417 float layersx2X0 = 1.e-2;
418 std::vector<std::array<float, 5>> layersConfig{
419 {26., .5, 2.5, 0.1f * layersx2X0}, // {z_layer, r_in, r_out, Layerx2X0}
420 {30., .5, 2.5, 0.1f * layersx2X0},
421 {34., .5, 2.5, 0.1f * layersx2X0},
422 {77., 5.0, 35., layersx2X0},
423 {100., 5.0, 35., layersx2X0},
424 {122., 5.0, 35., layersx2X0},
425 {150., 5.0, 68.f, layersx2X0},
426 {180., 5.0, 68.f, layersx2X0},
427 {220., 5.0, 68.f, layersx2X0},
428 {260., 5.0, 68.f, layersx2X0},
429 {300., 5.0, 68.f, layersx2X0},
430 {350., 5.0, 68.f, layersx2X0}};
431
432 mLayerName.resize(2);
433 mLayerName[0].resize(mNumberOfLayers);
434 mLayerName[1].resize(mNumberOfLayers);
435 mLayerID.clear();
436 mLayers.resize(2);
437
438 for (auto direction : {0, 1}) {
439 for (int layerNumber = 0; layerNumber < mNumberOfLayers; layerNumber++) {
440 std::string directionName = std::to_string(direction);
441 std::string layerName = GeometryTGeo::getFT3LayerPattern() + directionName + std::string("_") + std::to_string(layerNumber);
442 mLayerName[direction][layerNumber] = layerName;
443 auto& z = layersConfig[layerNumber][0];
444
445 auto& rIn = layersConfig[layerNumber][1];
446 auto& rOut = layersConfig[layerNumber][2];
447 auto& x0 = layersConfig[layerNumber][3];
448
449 LOG(info) << "Adding Layer " << layerName << " at z = " << z;
450 // Add layers
451 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName, z, rIn, rOut, x0);
452 }
453 }
454}
455
456//_________________________________________________________________________________________________
458 : o2::base::DetImpl<Detector>("FT3", active),
459 mTrackData(),
460 mHits(o2::utils::createSimVector<o2::itsmft::Hit>())
461{
462
463 // FT3 Base configuration parameters
464 auto& ft3BaseParam = FT3BaseParam::Instance();
465
466 if (ft3BaseParam.configFile != "") {
467 LOG(info) << "FT3 Geometry configuration file provided. Overriding FT3Base.geoModel configuration.";
468 buildFT3FromFile(ft3BaseParam.configFile);
469
470 } else {
471 switch (ft3BaseParam.geoModel) {
472 case Default:
473 buildFT3ScopingV3(); // v3 Dec 25
474 break;
475 case Telescope:
476 buildBasicFT3(ft3BaseParam); // BasicFT3 = Parametrized telescopic detector (equidistant layers)
477 break;
478 default:
479 LOG(fatal) << "Invalid Geometry.\n";
480 break;
481 }
482 }
483 exportLayout();
484}
485
486//_________________________________________________________________________________________________
488 : o2::base::DetImpl<Detector>(rhs),
489 mTrackData(),
490
492 mHits(o2::utils::createSimVector<o2::itsmft::Hit>())
493{
494 mLayerID = rhs.mLayerID;
495 mLayerName = rhs.mLayerName;
496 mNumberOfLayers = rhs.mNumberOfLayers;
497}
498
499//_________________________________________________________________________________________________
501{
502
503 if (mHits) {
504 // delete mHits;
506 }
507}
508
509//_________________________________________________________________________________________________
511{
512 // The standard = operator
513 // Inputs:
514 // Detector &h the sourse of this copy
515 // Outputs:
516 // none.
517 // Return:
518 // A copy of the sourse hit h
519
520 if (this == &rhs) {
521 return *this;
522 }
523
524 // base class assignment
526
527 mLayerID = rhs.mLayerID;
528 mLayerName = rhs.mLayerName;
529 mNumberOfLayers = rhs.mNumberOfLayers;
530 mLayers = rhs.mLayers;
531 mTrackData = rhs.mTrackData;
532
534 mHits = nullptr;
535
536 return *this;
537}
538
539//_________________________________________________________________________________________________
541{
542 // Define the list of sensitive volumes
543 LOG(info) << "Initialize FT3 O2Detector";
544
545 mGeometryTGeo = GeometryTGeo::Instance();
546
547 defineSensitiveVolumes();
548}
549
550//_________________________________________________________________________________________________
551bool Detector::ProcessHits(FairVolume* vol)
552{
553 // This method is called from the MC stepping
554 if (!(fMC->TrackCharge())) {
555 return kFALSE;
556 }
557
558 int lay = 0, volID = vol->getMCid();
559 while ((lay <= mLayerID.size()) && (volID != mLayerID[lay])) {
560 ++lay;
561 }
562
563 auto stack = (o2::data::Stack*)fMC->GetStack();
564
565 bool startHit = false, stopHit = false;
566 unsigned char status = 0;
567 if (fMC->IsTrackEntering()) {
568 status |= Hit::kTrackEntering;
569 }
570 if (fMC->IsTrackInside()) {
571 status |= Hit::kTrackInside;
572 }
573 if (fMC->IsTrackExiting()) {
574 status |= Hit::kTrackExiting;
575 }
576 if (fMC->IsTrackOut()) {
577 status |= Hit::kTrackOut;
578 }
579 if (fMC->IsTrackStop()) {
580 status |= Hit::kTrackStopped;
581 }
582 if (fMC->IsTrackAlive()) {
583 status |= Hit::kTrackAlive;
584 }
585
586 // track is entering or created in the volume
587 if ((status & Hit::kTrackEntering) || (status & Hit::kTrackInside && !mTrackData.mHitStarted)) {
588 startHit = true;
589 } else if ((status & (Hit::kTrackExiting | Hit::kTrackOut | Hit::kTrackStopped))) {
590 stopHit = true;
591 }
592
593 // increment energy loss at all steps except entrance
594 if (!startHit) {
595 mTrackData.mEnergyLoss += fMC->Edep();
596 }
597 if (!(startHit | stopHit)) {
598 return kFALSE; // do noting
599 }
600 if (startHit) {
601 mTrackData.mEnergyLoss = 0.;
602 fMC->TrackMomentum(mTrackData.mMomentumStart);
603 fMC->TrackPosition(mTrackData.mPositionStart);
604 mTrackData.mTrkStatusStart = status;
605 mTrackData.mHitStarted = true;
606 }
607 if (stopHit) {
608 TLorentzVector positionStop;
609 fMC->TrackPosition(positionStop);
610 // Retrieve the indices with the volume path
611 int chipindex = lay;
612
613 Hit* p = addHit(stack->GetCurrentTrackNumber(), chipindex, mTrackData.mPositionStart.Vect(), positionStop.Vect(),
614 mTrackData.mMomentumStart.Vect(), mTrackData.mMomentumStart.E(), positionStop.T(),
615 mTrackData.mEnergyLoss, mTrackData.mTrkStatusStart, status);
616 // p->SetTotalEnergy(vmc->Etot());
617
618 // RS: not sure this is needed
619 // Increment number of Detector det points in TParticle
620 stack->addHit(GetDetId());
621 }
622
623 return kTRUE;
624}
625
626//_________________________________________________________________________________________________
627void Detector::createMaterials()
628{
629 int ifield = 2;
630 float fieldm = 10.0;
632
633 float tmaxfdSi = 0.1; // .10000E+01; // Degree
634 float stemaxSi = 0.0075; // .10000E+01; // cm
635 float deemaxSi = 0.1; // 0.30000E-02; // Fraction of particle's energy 0<deemax<=1
636 float epsilSi = 1.0E-4; // .10000E+01;
637 float stminSi = 0.0; // cm "Default value used"
638
639 float tmaxfdAir = 0.1; // .10000E+01; // Degree
640 float stemaxAir = .10000E+01; // cm
641 float deemaxAir = 0.1; // 0.30000E-02; // Fraction of particle's energy 0<deemax<=1
642 float epsilAir = 1.0E-4; // .10000E+01;
643 float stminAir = 0.0; // cm "Default value used"
644
645 // AIR
646 float aAir[4] = {12.0107, 14.0067, 15.9994, 39.948};
647 float zAir[4] = {6., 7., 8., 18.};
648 float wAir[4] = {0.000124, 0.755267, 0.231781, 0.012827};
649 float dAir = 1.20479E-3;
650
651 o2::base::Detector::Mixture(1, "AIR$", aAir, zAir, dAir, 4, wAir);
652 o2::base::Detector::Medium(1, "AIR$", 1, 0, ifield, fieldm, tmaxfdAir, stemaxAir, deemaxAir, epsilAir, stminAir);
653
654 o2::base::Detector::Material(3, "SILICON$", 0.28086E+02, 0.14000E+02, 0.23300E+01, 0.93600E+01, 0.99900E+03);
655 o2::base::Detector::Medium(3, "SILICON$", 3, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
656}
657
658//_________________________________________________________________________________________________
659void Detector::EndOfEvent() { Reset(); }
660
661//_________________________________________________________________________________________________
663{
664 // This will create a branch in the output tree called Hit, setting the last
665 // parameter to kFALSE means that this collection will not be written to the file,
666 // it will exist only during the simulation
667
668 if (FairRootManager::Instance()) {
669 FairRootManager::Instance()->RegisterAny(addNameTo("Hit").data(), mHits, kTRUE);
670 }
671}
672
673//_________________________________________________________________________________________________
675{
676 if (!o2::utils::ShmManager::Instance().isOperational()) {
677 mHits->clear();
678 }
679}
680
681//_________________________________________________________________________________________________
683{
684 // Create detector materials
685 createMaterials();
686
687 // Construct the detector geometry
688 createGeometry();
689}
690
691//_________________________________________________________________________________________________
692void Detector::createGeometry()
693{
694
695 mGeometryTGeo = GeometryTGeo::Instance();
696
697 TGeoVolume* volFT3 = new TGeoVolumeAssembly(GeometryTGeo::getFT3VolPattern());
698 TGeoVolume* volIFT3 = new TGeoVolumeAssembly(GeometryTGeo::getFT3InnerVolPattern());
699
700 LOG(info) << "GeometryBuilder::buildGeometry volume name = " << GeometryTGeo::getFT3VolPattern();
701
702 TGeoVolume* vALIC = gGeoManager->GetVolume("barrel");
703 if (!vALIC) {
704 LOG(fatal) << "Could not find the top volume";
705 }
706
707 TGeoVolume* A3IPvac = gGeoManager->GetVolume("OUT_PIPEVACUUM");
708 if (!A3IPvac) {
709 LOG(info) << "Running simulation with no beam pipe.";
710 }
711
712 LOG(debug) << "FT3 createGeometry: "
713 << Form("gGeoManager name is %s title is %s", gGeoManager->GetName(), gGeoManager->GetTitle());
714
715 if (mLayers.size() == 2) { // V1 and telescope
716 if (!A3IPvac) {
717 for (int direction : {0, 1}) { // Backward layers at mLayers[0]; Forward layers at mLayers[1]
718 std::string directionString = direction ? "Forward" : "Backward";
719 LOG(info) << "Creating FT3 " << directionString << " layers:";
720 for (int iLayer = 0; iLayer < mLayers[direction].size(); iLayer++) {
721 mLayers[direction][iLayer].createLayer(volFT3);
722 }
723 }
724 vALIC->AddNode(volFT3, 2, new TGeoTranslation(0., 30., 0.));
725 } else { // If beampipe is enabled append inner disks to beampipe filling volume, this should be temporary.
726 for (int direction : {0, 1}) {
727 std::string directionString = direction ? "Forward" : "Backward";
728 LOG(info) << "Creating FT3 " << directionString << " layers:";
729 for (int iLayer = 0; iLayer < mLayers[direction].size(); iLayer++) {
730 if (iLayer < 3) {
731 mLayers[direction][iLayer].createLayer(volIFT3);
732 } else {
733 mLayers[direction][iLayer].createLayer(volFT3);
734 }
735 }
736 }
737 A3IPvac->AddNode(volIFT3, 2, new TGeoTranslation(0., 0., 0.));
738 vALIC->AddNode(volFT3, 2, new TGeoTranslation(0., 30., 0.));
739 }
740
741 for (auto direction : {0, 1}) {
742 std::string directionString = direction ? "Forward" : "Backward";
743 LOG(info) << "Registering FT3 " << directionString << " LayerIDs:";
744 for (int iLayer = 0; iLayer < mLayers[direction].size(); iLayer++) {
745 auto layerID = gMC ? TVirtualMC::GetMC()->VolId(Form("%s_%d_%d", GeometryTGeo::getFT3SensorPattern(), direction, iLayer)) : 0;
746 mLayerID.push_back(layerID);
747 LOG(info) << " " << directionString << " layer " << iLayer << " LayerID " << layerID;
748 }
749 }
750 }
751
752 if (mLayers.size() == 1) { // All layers registered at mLayers[0], used when building from file
753 LOG(info) << "Creating FT3 layers:";
754 if (A3IPvac) {
755 for (int iLayer = 0; iLayer < mLayers[0].size(); iLayer++) {
756 if (std::abs(mLayers[0][iLayer].getZ()) < 25) {
757 mLayers[0][iLayer].createLayer(volIFT3);
758 } else {
759 mLayers[0][iLayer].createLayer(volFT3);
760 }
761 }
762 A3IPvac->AddNode(volIFT3, 2, new TGeoTranslation(0., 0., 0.));
763 vALIC->AddNode(volFT3, 2, new TGeoTranslation(0., 30., 0.));
764 } else {
765 for (int iLayer = 0; iLayer < mLayers[0].size(); iLayer++) {
766 mLayers[0][iLayer].createLayer(volFT3);
767 }
768 vALIC->AddNode(volFT3, 2, new TGeoTranslation(0., 30., 0.));
769 }
770 LOG(info) << "Registering FT3 LayerIDs:";
771 for (int iLayer = 0; iLayer < mLayers[0].size(); iLayer++) {
772 auto layerID = gMC ? TVirtualMC::GetMC()->VolId(Form("%s_%d_%d", GeometryTGeo::getFT3SensorPattern(), 0, iLayer)) : 0;
773 mLayerID.push_back(layerID);
774 LOG(info) << " mLayerID[" << iLayer << "] = " << layerID;
775 }
776 }
777}
778
779//_________________________________________________________________________________________________
780void Detector::defineSensitiveVolumes()
781{
782 TGeoManager* geoManager = gGeoManager;
783 TGeoVolume* v;
784
785 TString volumeName;
786 LOG(info) << "Adding FT3 Sensitive Volumes";
787
788 // The names of the FT3 sensitive volumes have the format: FT3Sensor_(0,1)_(0...sNumberLayers-1)
789 if (mLayers.size() == 2) {
790 for (int direction : {0, 1}) {
791 for (int iLayer = 0; iLayer < mNumberOfLayers; iLayer++) {
793 if (iLayer < 3) { // ML disks
794 v = geoManager->GetVolume(Form("%s_%d_%d", GeometryTGeo::getFT3SensorPattern(), direction, iLayer));
795 AddSensitiveVolume(v);
796 } else { // OT disks
797 for (int sensor_count = 0; sensor_count < MAX_SENSORS; ++sensor_count) {
798 std::string sensor_name_front = "FT3sensor_front_" + std::to_string(iLayer) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
799 std::string sensor_name_back = "FT3sensor_back_" + std::to_string(iLayer) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
800 v = geoManager->GetVolume(sensor_name_front.c_str());
801 if (v) {
802 AddSensitiveVolume(v);
803 }
804 v = geoManager->GetVolume(sensor_name_back.c_str());
805 if (v) {
806 AddSensitiveVolume(v);
807 }
808 }
809 }
810 }
811 }
812 }
813
814 if (mLayers.size() == 1) {
815 for (int iLayer = 0; iLayer < mLayers[0].size(); iLayer++) {
817 v = geoManager->GetVolume(Form("%s_%d_%d", GeometryTGeo::getFT3SensorPattern(), mLayers[0][iLayer].getDirection(), iLayer));
818 LOG(info) << "Adding FT3 Sensitive Volume => " << v->GetName();
819 AddSensitiveVolume(v);
820 }
821 }
822}
823
824//_________________________________________________________________________________________________
825Hit* Detector::addHit(int trackID, int detID, const TVector3& startPos, const TVector3& endPos,
826 const TVector3& startMom, double startE, double endTime, double eLoss, unsigned char startStatus,
827 unsigned char endStatus)
828{
829 mHits->emplace_back(trackID, detID, startPos, endPos, startMom, startE, endTime, eLoss, startStatus, endStatus);
830 return &(mHits->back());
831}
832
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:349
std::vector< std::vector< TString > > mLayerName
Definition Detector.h:128
void EndOfEvent() override
Definition Detector.cxx:659
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:825
void Register() override
Registers the produced collections in FAIRRootManager.
Definition Detector.cxx:662
void buildFT3FromFile(std::string)
Definition Detector.cxx:63
void ConstructGeometry() override
Base class to create the detector geometry.
Definition Detector.cxx:682
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:551
std::vector< Int_t > mLayerID
Definition Detector.h:127
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:674
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"