25#include "FairDetector.h"
26#include <fairlogger/Logger.h>
27#include "FairRootManager.h"
29#include "FairRuntimeDb.h"
30#include "FairVolume.h"
31#include "FairRootManager.h"
33#include "TGeoManager.h"
36#include "TGeoVolume.h"
38#include "TVirtualMC.h"
39#include "TVirtualMCStack.h"
43#define MAX_SENSORS 2000
68 LOG(info) <<
"Building FT3 Detector: Conical Telescope";
70 const int numberOfLayers =
param.nLayers;
71 const auto z_first =
param.z0;
72 const auto z_length =
param.zLength;
73 const auto etaIn =
param.etaIn;
74 const auto etaOut =
param.etaOut;
75 const auto Layerx2X0 =
param.Layerx2X0;
81 for (
int layerNumber = 0; layerNumber < numberOfLayers; layerNumber++) {
83 mLayerName[direction][layerNumber] = layerName;
86 const float layerZ = z_first + (layerNumber * z_length / numberOfLayers) * std::copysign(1, z_first);
87 const float rIn = std::abs(layerZ * std::tan(2.f * std::atan(std::exp(-etaIn))));
88 const float rOut = std::abs(layerZ * std::tan(2.f * std::atan(std::exp(-etaOut))));
89 const bool isMiddleLayer = layerNumber < 3;
90 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName, layerZ, rIn, rOut, Layerx2X0, isMiddleLayer);
101 LOG(info) <<
"Building FT3 Detector: V1";
103 const int numberOfLayers = 10;
104 const float sensorThickness = 30.e-4;
105 const float layersx2X0 = 1.e-2;
106 const std::vector<std::array<float, 4>> layersConfig{
107 {26., .5, 3., 0.1f * layersx2X0},
108 {30., .5, 3., 0.1f * layersx2X0},
109 {34., .5, 3., 0.1f * layersx2X0},
110 {77., 3.5, 35., layersx2X0},
111 {100., 3.5, 35., layersx2X0},
112 {122., 3.5, 35., layersx2X0},
113 {150., 3.5, 80.f, layersx2X0},
114 {180., 3.5, 80.f, layersx2X0},
115 {220., 3.5, 80.f, layersx2X0},
116 {279., 3.5, 80.f, layersx2X0}};
123 for (
int layerNumber = 0; layerNumber < numberOfLayers; layerNumber++) {
126 mLayerName[direction][layerNumber] = layerName;
127 auto&
z = layersConfig[layerNumber][0];
129 auto& rIn = layersConfig[layerNumber][1];
130 auto& rOut = layersConfig[layerNumber][2];
131 auto&
x0 = layersConfig[layerNumber][3];
133 LOG(info) <<
"Adding Layer " << layerName <<
" at z = " <<
z;
135 const bool isMiddleLayer = layerNumber < 3;
136 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName,
z, rIn, rOut,
x0, isMiddleLayer);
147 LOG(info) <<
"Building FT3 Detector: V3b";
149 const int numberOfLayers = 12;
150 float sensorThickness = 30.e-4;
151 float layersx2X0 = 1.e-2;
152 std::vector<std::array<float, 4>> layersConfig{
153 {26., .5, 3., 0.1f * layersx2X0},
154 {30., .5, 3., 0.1f * layersx2X0},
155 {34., .5, 3., 0.1f * layersx2X0},
156 {77., 5.0, 35., layersx2X0},
157 {100., 5.0, 35., layersx2X0},
158 {122., 5.0, 35., layersx2X0},
159 {150., 5.5, 80.f, layersx2X0},
160 {180., 6.6, 80.f, layersx2X0},
161 {220., 8.1, 80.f, layersx2X0},
162 {279., 10.2, 80.f, layersx2X0},
163 {340., 12.5, 80.f, layersx2X0},
164 {400., 14.7, 80.f, layersx2X0}};
171 for (
int layerNumber = 0; layerNumber < numberOfLayers; layerNumber++) {
174 mLayerName[direction][layerNumber] = layerName;
175 auto&
z = layersConfig[layerNumber][0];
177 auto& rIn = layersConfig[layerNumber][1];
178 auto& rOut = layersConfig[layerNumber][2];
179 auto&
x0 = layersConfig[layerNumber][3];
181 LOG(info) <<
"Adding Layer " << layerName <<
" at z = " <<
z;
183 const bool isMiddleLayer = layerNumber < 3;
184 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName,
z, rIn, rOut,
x0, isMiddleLayer);
198 LOG(info) <<
"Building FT3 Detector: After Upgrade Days March 2024 version";
200 const int numberOfLayers = 9;
201 const float sensorThickness = 30.e-4;
202 const float layersx2X0 = 1.e-2;
203 const std::vector<std::array<float, 4>> layersConfigCSide{
204 {77., 7.0, 35., layersx2X0},
205 {100., 7.0, 35., layersx2X0},
206 {122., 7.0, 35., layersx2X0},
207 {150., 7.0, 68.f, layersx2X0},
208 {180., 7.0, 68.f, layersx2X0},
209 {220., 7.0, 68.f, layersx2X0},
210 {260., 7.0, 68.f, layersx2X0},
211 {300., 7.0, 68.f, layersx2X0},
212 {350., 7.0, 68.f, layersx2X0}};
214 const std::vector<std::array<float, 4>> layersConfigASide{
215 {77., 5.0, 35., layersx2X0},
216 {100., 5.0, 35., layersx2X0},
217 {122., 5.0, 35., layersx2X0},
218 {150., 5.0, 68.f, layersx2X0},
219 {180., 5.0, 68.f, layersx2X0},
220 {220., 5.0, 68.f, layersx2X0},
221 {260., 5.0, 68.f, layersx2X0},
222 {300., 5.0, 68.f, layersx2X0},
223 {350., 5.0, 68.f, layersx2X0}};
230 for (
int layerNumber = 0; layerNumber < numberOfLayers; layerNumber++) {
233 mLayerName[direction][layerNumber] = layerName;
234 float z, rIn, rOut,
x0;
235 if (direction == 0) {
236 z = layersConfigCSide[layerNumber][0];
237 rIn = layersConfigCSide[layerNumber][1];
238 rOut = layersConfigCSide[layerNumber][2];
239 x0 = layersConfigCSide[layerNumber][3];
240 }
else if (direction == 1) {
241 z = layersConfigASide[layerNumber][0];
242 rIn = layersConfigASide[layerNumber][1];
243 rOut = layersConfigASide[layerNumber][2];
244 x0 = layersConfigASide[layerNumber][3];
247 LOG(info) <<
"Adding Layer " << layerName <<
" at z = " <<
z;
249 const bool isMiddleLayer = layerNumber < 3;
250 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName,
z, rIn, rOut,
x0, isMiddleLayer);
262 LOG(info) <<
"Building FT3 Detector: v3 scoping version";
264 const int numberOfLayers = 6;
265 const float sensorThickness = 30.e-4;
266 const float layersx2X0 = 1.e-2;
267 using LayerConfig = std::array<float, 4>;
268 const std::array<LayerConfig, numberOfLayers> layersConfigCSide{LayerConfig{77., 10.0, 35., layersx2X0},
269 LayerConfig{100., 10.0, 35., layersx2X0},
270 LayerConfig{122., 10.0, 35., layersx2X0},
271 LayerConfig{150., 20.0, 68.f, layersx2X0},
272 LayerConfig{180., 20.0, 68.f, layersx2X0},
273 LayerConfig{220., 20.0, 68.f, layersx2X0}};
275 const std::array<LayerConfig, numberOfLayers> layersConfigASide{LayerConfig{77., 10.0, 35., layersx2X0},
276 LayerConfig{100., 10.0, 35., layersx2X0},
277 LayerConfig{122., 10.0, 35., layersx2X0},
278 LayerConfig{150., 20.0, 68.f, layersx2X0},
279 LayerConfig{180., 20.0, 68.f, layersx2X0},
280 LayerConfig{220., 20.0, 68.f, layersx2X0}};
281 const std::array<bool, numberOfLayers>
enabled{
true,
true,
true,
true,
true,
true};
287 const std::array<LayerConfig, numberOfLayers>& layerConfig = (direction ==
IdxBackwardDisks) ? layersConfigCSide : layersConfigASide;
288 for (
int layerNumber = 0; layerNumber < numberOfLayers; layerNumber++) {
294 mLayerName[direction].push_back(layerName.c_str());
295 const float z = layerConfig[layerNumber][0];
296 const float rIn = layerConfig[layerNumber][1];
297 const float rOut = layerConfig[layerNumber][2];
298 const float x0 = layerConfig[layerNumber][3];
299 LOG(info) <<
"buildFT3ScopingV3 -> Adding Layer " << layerNumber <<
"/" << numberOfLayers <<
" " << layerName <<
" at z = " <<
z;
301 const bool isMiddleLayer = layerNumber < 3;
302 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName,
z, rIn, rOut,
x0, isMiddleLayer);
312 LOG(info) <<
"Building FT3 Detector: Scoping document version";
314 const int numberOfLayers = 12;
315 const float sensorThickness = 30.e-4;
316 const float layersx2X0 = 1.e-2;
317 const std::vector<std::array<float, 4>> layersConfig{
318 {26., .5, 2.5, 0.1f * layersx2X0},
319 {30., .5, 2.5, 0.1f * layersx2X0},
320 {34., .5, 2.5, 0.1f * layersx2X0},
321 {77., 5.0, 35., layersx2X0},
322 {100., 5.0, 35., layersx2X0},
323 {122., 5.0, 35., layersx2X0},
324 {150., 5.0, 68.f, layersx2X0},
325 {180., 5.0, 68.f, layersx2X0},
326 {220., 5.0, 68.f, layersx2X0},
327 {260., 5.0, 68.f, layersx2X0},
328 {300., 5.0, 68.f, layersx2X0},
329 {350., 5.0, 68.f, layersx2X0}};
336 for (
int layerNumber = 0; layerNumber < numberOfLayers; layerNumber++) {
339 mLayerName[direction][layerNumber] = layerName;
340 auto&
z = layersConfig[layerNumber][0];
341 auto& rIn = layersConfig[layerNumber][1];
342 auto& rOut = layersConfig[layerNumber][2];
343 auto&
x0 = layersConfig[layerNumber][3];
345 LOG(info) <<
"Adding Layer " << layerName <<
" at z = " <<
z;
347 const bool isMiddleLayer = layerNumber < 3;
348 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName,
z, rIn, rOut,
x0, isMiddleLayer);
370 mLayerID = rhs.mLayerID;
371 mLayerName = rhs.mLayerName;
402 mLayerID = rhs.mLayerID;
403 mLayerName = rhs.mLayerName;
404 mLayers = rhs.mLayers;
405 mTrackData = rhs.mTrackData;
417 LOG(info) <<
"Initialize FT3 O2Detector";
419 defineSensitiveVolumes();
426 if (!(fMC->TrackCharge())) {
430 int lay = 0, volID = vol->getMCid();
431 while ((lay <= mLayerID.size()) && (volID != mLayerID[lay])) {
437 bool startHit =
false, stopHit =
false;
438 unsigned char status = 0;
439 if (fMC->IsTrackEntering()) {
440 status |= Hit::kTrackEntering;
442 if (fMC->IsTrackInside()) {
443 status |= Hit::kTrackInside;
445 if (fMC->IsTrackExiting()) {
446 status |= Hit::kTrackExiting;
448 if (fMC->IsTrackOut()) {
449 status |= Hit::kTrackOut;
451 if (fMC->IsTrackStop()) {
452 status |= Hit::kTrackStopped;
454 if (fMC->IsTrackAlive()) {
455 status |= Hit::kTrackAlive;
459 if ((status & Hit::kTrackEntering) || (status & Hit::kTrackInside && !mTrackData.mHitStarted)) {
461 }
else if ((status & (Hit::kTrackExiting | Hit::kTrackOut | Hit::kTrackStopped))) {
467 mTrackData.mEnergyLoss += fMC->Edep();
469 if (!(startHit | stopHit)) {
473 mTrackData.mEnergyLoss = 0.;
474 fMC->TrackMomentum(mTrackData.mMomentumStart);
475 fMC->TrackPosition(mTrackData.mPositionStart);
476 mTrackData.mTrkStatusStart = status;
477 mTrackData.mHitStarted =
true;
480 TLorentzVector positionStop;
481 fMC->TrackPosition(positionStop);
485 Hit* p = addHit(
stack->GetCurrentTrackNumber(), chipindex, mTrackData.mPositionStart.Vect(), positionStop.Vect(),
486 mTrackData.mMomentumStart.Vect(), mTrackData.mMomentumStart.E(), positionStop.T(),
487 mTrackData.mEnergyLoss, mTrackData.mTrkStatusStart, status);
492 stack->addHit(GetDetId());
499void Detector::createMaterials()
505 float tmaxfdSi = 0.1;
506 float stemaxSi = 0.0075;
507 float deemaxSi = 0.1;
508 float epsilSi = 1.0E-4;
511 float tmaxfdAir = 0.1;
512 float stemaxAir = .10000E+01;
513 float deemaxAir = 0.1;
514 float epsilAir = 1.0E-4;
515 float stminAir = 0.0;
518 float aAir[4] = {12.0107, 14.0067, 15.9994, 39.948};
519 float zAir[4] = {6., 7., 8., 18.};
520 float wAir[4] = {0.000124, 0.755267, 0.231781, 0.012827};
521 float dAir = 1.20479E-3;
524 o2::base::Detector::Medium(1,
"AIR$", 1, 0, ifield, fieldm, tmaxfdAir, stemaxAir, deemaxAir, epsilAir, stminAir);
527 o2::base::Detector::Medium(3,
"SILICON$", 3, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
540 if (FairRootManager::Instance()) {
541 FairRootManager::Instance()->RegisterAny(
addNameTo(
"Hit").
data(), mHits, kTRUE);
564void Detector::createGeometry()
572 TGeoVolume* vALIC = gGeoManager->GetVolume(
"barrel");
574 LOG(fatal) <<
"Could not find the top volume";
577 TGeoVolume* A3IPvac = gGeoManager->GetVolume(
"OUT_PIPEVACUUM");
579 LOG(info) <<
"Running simulation with no beam pipe.";
584 for (
int direction : {IdxBackwardDisks, IdxForwardDisks}) {
585 const std::string directionString = direction ?
"Forward" :
"Backward";
586 LOG(info) <<
" Creating FT3 without beampipe " << directionString <<
" layers:";
587 for (
int iLayer = 0; iLayer < mLayers[direction].size(); iLayer++) {
588 mLayers[direction][iLayer].createLayer(volFT3);
591 vALIC->AddNode(volFT3, 2,
new TGeoTranslation(0., 30., 0.));
593 for (
int direction : {IdxBackwardDisks, IdxForwardDisks}) {
594 const std::string directionString = direction ?
"Forward" :
"Backward";
595 LOG(info) <<
" Creating FT3 " << directionString <<
" layers:";
596 for (
int iLayer = 0; iLayer < mLayers[direction].size(); iLayer++) {
597 LOG(info) <<
" Creating " << directionString <<
" layer " << iLayer;
598 if (mLayers[direction][iLayer].getIsInMiddleLayer()) {
599 mLayers[direction][iLayer].createLayer(volIFT3);
601 mLayers[direction][iLayer].createLayer(volFT3);
605 A3IPvac->AddNode(volIFT3, 2,
new TGeoTranslation(0., 0., 0.));
606 vALIC->AddNode(volFT3, 2,
new TGeoTranslation(0., 30., 0.));
609 for (
auto direction : {IdxBackwardDisks, IdxForwardDisks}) {
610 std::string directionString = direction ?
"Forward" :
"Backward";
611 LOG(info) <<
" Registering FT3 " << directionString <<
" LayerIDs for " << mLayers[direction].size() <<
" layers:";
612 for (
int iLayer = 0; iLayer < mLayers[direction].size(); iLayer++) {
614 mLayerID.push_back(layerID);
615 LOG(info) <<
" " << directionString <<
" layer " << iLayer <<
" LayerID " << layerID;
621void Detector::defineSensitiveVolumes()
623 TGeoManager* geoManager = gGeoManager;
627 LOG(info) <<
"Adding FT3 Sensitive Volumes";
629 for (
int direction : {IdxBackwardDisks, IdxForwardDisks}) {
630 for (
int iLayer = 0; iLayer < getNumberOfLayers(); iLayer++) {
631 LOG(info) <<
"Adding FT3 Sensitive Volume for direction " << direction <<
" layer " << iLayer <<
"/" << getNumberOfLayers();
633 if (mLayers[direction][iLayer].getIsInMiddleLayer()) {
635 v = geoManager->GetVolume(sensorName.c_str());
637 geoManager->GetListOfVolumes()->ls();
638 LOG(fatal) <<
"Could not find volume " << sensorName <<
" for direction " << direction <<
" layer " << iLayer;
640 AddSensitiveVolume(
v);
642 for (
int sensor_count = 0; sensor_count <
MAX_SENSORS; ++sensor_count) {
645 v = geoManager->GetVolume(sensor_name_front.c_str());
647 AddSensitiveVolume(
v);
649 v = geoManager->GetVolume(sensor_name_back.c_str());
651 AddSensitiveVolume(
v);
661 const TVector3& startMom,
double startE,
double endTime,
double eLoss,
unsigned char startStatus,
662 unsigned char endStatus)
664 mHits->emplace_back(trackID, detID, startPos, endPos, startMom, startE, endTime, eLoss, startStatus, endStatus);
665 return &(mHits->back());
Definition of the Stack class.
Definition of the ITSMFT Hit class.
Definition of the FT3Layer class.
Definition of the GeometryTGeo class.
Definition of the Detector class.
Detector & operator=(const Detector &)
void Mixture(Int_t imat, const char *name, Float_t *a, Float_t *z, Float_t dens, Int_t nlmat, Float_t *wmat)
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)
static void initFieldTrackingParams(int &mode, float &maxfield)
virtual void InitializeO2Detector()=0
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)
std::string addNameTo(const char *ext) const
std::array< std::vector< TString >, 2 > mLayerName
static constexpr int IdxBackwardDisks
void EndOfEvent() override
static constexpr int IdxForwardDisks
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.
void Register() override
Registers the produced collections in FAIRRootManager.
void ConstructGeometry() override
Base class to create the detector geometry.
Detector()
Default constructor.
Bool_t ProcessHits(FairVolume *v=nullptr) override
This method is called for each step during simulation (see FairMCApplication::Stepping())
std::vector< Int_t > mLayerID
void buildBasicFT3(const FT3BaseParam ¶m)
void buildFT3NewVacuumVessel()
void Reset() override
Has to be called after each event to reset the containers.
static const char * getFT3SensorPattern()
static const char * getFT3LayerPattern()
static const char * getFT3VolPattern()
static const char * getFT3InnerVolPattern()
static ShmManager & Instance()
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLdouble GLdouble GLdouble z
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)
Common utility functions.
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"