26#include "FairDetector.h"
27#include "FairRootManager.h"
28#include "FairRootManager.h"
30#include "FairRuntimeDb.h"
31#include "FairVolume.h"
33#include "TGeoManager.h"
36#include "TGeoVolume.h"
38#include "TVirtualMC.h"
39#include "TVirtualMCStack.h"
41#include <fairlogger/Logger.h>
45#define MAX_SENSORS 2000
70 LOG(info) <<
"Building FT3 Detector: Conical Telescope";
72 const int numberOfLayers =
param.nLayers;
73 const auto z_first =
param.z0;
74 const auto z_length =
param.zLength;
75 const auto etaIn =
param.etaIn;
76 const auto etaOut =
param.etaOut;
77 const auto Layerx2X0 =
param.Layerx2X0;
82 for (
int layerNumber = 0; layerNumber < numberOfLayers; layerNumber++) {
84 mLayerName[direction][layerNumber] = layerName;
87 const float layerZ = z_first + (layerNumber * z_length / numberOfLayers) * std::copysign(1, z_first);
88 const float rIn = std::abs(layerZ * std::tan(2.f * std::atan(std::exp(-etaIn))));
89 const float rOut = std::abs(layerZ * std::tan(2.f * std::atan(std::exp(-etaOut))));
90 const bool isMiddleLayer = layerNumber < 3;
91 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName, layerZ, rIn, rOut, Layerx2X0, isMiddleLayer);
102 LOG(info) <<
"Building FT3 Detector: V1";
104 const int numberOfLayers = 10;
105 const float sensorThickness = 30.e-4;
106 const float layersx2X0 = 1.e-2;
107 const std::vector<std::array<float, 4>> layersConfig{
108 {26., .5, 3., 0.1f * layersx2X0},
109 {30., .5, 3., 0.1f * layersx2X0},
110 {34., .5, 3., 0.1f * layersx2X0},
111 {77., 3.5, 35., layersx2X0},
112 {100., 3.5, 35., layersx2X0},
113 {122., 3.5, 35., layersx2X0},
114 {150., 3.5, 80.f, layersx2X0},
115 {180., 3.5, 80.f, layersx2X0},
116 {220., 3.5, 80.f, layersx2X0},
117 {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}};
170 for (
int layerNumber = 0; layerNumber < numberOfLayers; layerNumber++) {
173 mLayerName[direction][layerNumber] = layerName;
174 auto&
z = layersConfig[layerNumber][0];
176 auto& rIn = layersConfig[layerNumber][1];
177 auto& rOut = layersConfig[layerNumber][2];
178 auto&
x0 = layersConfig[layerNumber][3];
180 LOG(info) <<
"Adding Layer " << layerName <<
" at z = " <<
z;
182 const bool isMiddleLayer = layerNumber < 3;
183 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName,
z, rIn, rOut,
x0, isMiddleLayer);
197 LOG(info) <<
"Building FT3 Detector: After Upgrade Days March 2024 version";
199 const int numberOfLayers = 9;
200 const float sensorThickness = 30.e-4;
201 const float layersx2X0 = 1.e-2;
202 const std::vector<std::array<float, 4>> layersConfigCSide{
203 {77., 7.0, 35., layersx2X0},
204 {100., 7.0, 35., layersx2X0},
205 {122., 7.0, 35., layersx2X0},
206 {150., 7.0, 68.f, layersx2X0},
207 {180., 7.0, 68.f, layersx2X0},
208 {220., 7.0, 68.f, layersx2X0},
209 {260., 7.0, 68.f, layersx2X0},
210 {300., 7.0, 68.f, layersx2X0},
211 {350., 7.0, 68.f, layersx2X0}};
213 const std::vector<std::array<float, 4>> layersConfigASide{
214 {77., 5.0, 35., layersx2X0},
215 {100., 5.0, 35., layersx2X0},
216 {122., 5.0, 35., layersx2X0},
217 {150., 5.0, 68.f, layersx2X0},
218 {180., 5.0, 68.f, layersx2X0},
219 {220., 5.0, 68.f, layersx2X0},
220 {260., 5.0, 68.f, layersx2X0},
221 {300., 5.0, 68.f, layersx2X0},
222 {350., 5.0, 68.f, layersx2X0}};
228 for (
int layerNumber = 0; layerNumber < numberOfLayers; layerNumber++) {
231 mLayerName[direction][layerNumber] = layerName;
232 float z, rIn, rOut,
x0;
233 if (direction == 0) {
234 z = layersConfigCSide[layerNumber][0];
235 rIn = layersConfigCSide[layerNumber][1];
236 rOut = layersConfigCSide[layerNumber][2];
237 x0 = layersConfigCSide[layerNumber][3];
238 }
else if (direction == 1) {
239 z = layersConfigASide[layerNumber][0];
240 rIn = layersConfigASide[layerNumber][1];
241 rOut = layersConfigASide[layerNumber][2];
242 x0 = layersConfigASide[layerNumber][3];
245 LOG(info) <<
"Adding Layer " << layerName <<
" at z = " <<
z;
247 const bool isMiddleLayer = layerNumber < 3;
248 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName,
z, rIn, rOut,
x0, isMiddleLayer);
260 LOG(info) <<
"Building FT3 Detector: v3 scoping version";
262 const int numberOfLayers = 6;
263 const float sensorThickness = 30.e-4;
264 const float layersx2X0 = 1.e-2;
265 using LayerConfig = std::array<float, 4>;
266 const std::array<LayerConfig, numberOfLayers> layersConfigCSide{LayerConfig{77., 10.0, 35., layersx2X0},
267 LayerConfig{100., 10.0, 35., layersx2X0},
268 LayerConfig{122., 10.0, 35., layersx2X0},
269 LayerConfig{150., 20.0, 68.f, layersx2X0},
270 LayerConfig{180., 20.0, 68.f, layersx2X0},
271 LayerConfig{220., 20.0, 68.f, layersx2X0}};
273 const std::array<LayerConfig, numberOfLayers> layersConfigASide{LayerConfig{77., 10.0, 35., layersx2X0},
274 LayerConfig{100., 10.0, 35., layersx2X0},
275 LayerConfig{122., 10.0, 35., layersx2X0},
276 LayerConfig{150., 20.0, 68.f, layersx2X0},
277 LayerConfig{180., 20.0, 68.f, layersx2X0},
278 LayerConfig{220., 20.0, 68.f, layersx2X0}};
279 const std::array<bool, numberOfLayers>
enabled{
true,
true,
true,
true,
true,
true};
283 const std::array<LayerConfig, numberOfLayers>& layerConfig = (direction ==
IdxBackwardDisks) ? layersConfigCSide : layersConfigASide;
284 for (
int layerNumber = 0; layerNumber < numberOfLayers; layerNumber++) {
290 mLayerName[direction].push_back(layerName.c_str());
291 const float z = layerConfig[layerNumber][0];
292 const float rIn = layerConfig[layerNumber][1];
293 const float rOut = layerConfig[layerNumber][2];
294 const float x0 = layerConfig[layerNumber][3];
295 LOG(info) <<
"buildFT3ScopingV3 -> Adding Layer " << layerNumber <<
"/" << numberOfLayers <<
" " << layerName <<
" at z = " <<
z;
297 const bool isMiddleLayer = layerNumber < 3;
298 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName,
z, rIn, rOut,
x0, isMiddleLayer);
308 LOG(info) <<
"Building FT3 Detector: Scoping document version";
310 const int numberOfLayers = 12;
311 const float sensorThickness = 30.e-4;
312 const float layersx2X0 = 1.e-2;
313 const std::vector<std::array<float, 4>> layersConfig{
314 {26., .5, 2.5, 0.1f * layersx2X0},
315 {30., .5, 2.5, 0.1f * layersx2X0},
316 {34., .5, 2.5, 0.1f * layersx2X0},
317 {77., 5.0, 35., layersx2X0},
318 {100., 5.0, 35., layersx2X0},
319 {122., 5.0, 35., layersx2X0},
320 {150., 5.0, 68.f, layersx2X0},
321 {180., 5.0, 68.f, layersx2X0},
322 {220., 5.0, 68.f, layersx2X0},
323 {260., 5.0, 68.f, layersx2X0},
324 {300., 5.0, 68.f, layersx2X0},
325 {350., 5.0, 68.f, layersx2X0}};
331 for (
int layerNumber = 0; layerNumber < numberOfLayers; layerNumber++) {
334 mLayerName[direction][layerNumber] = layerName;
335 auto&
z = layersConfig[layerNumber][0];
336 auto& rIn = layersConfig[layerNumber][1];
337 auto& rOut = layersConfig[layerNumber][2];
338 auto&
x0 = layersConfig[layerNumber][3];
340 LOG(info) <<
"Adding Layer " << layerName <<
" at z = " <<
z;
342 const bool isMiddleLayer = layerNumber < 3;
343 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName,
z, rIn, rOut,
x0, isMiddleLayer);
365 mLayerName = rhs.mLayerName;
366 mActiveSensorMap = rhs.mActiveSensorMap;
397 mLayerName = rhs.mLayerName;
398 mActiveSensorMap = rhs.mActiveSensorMap;
399 mLayers = rhs.mLayers;
400 mTrackData = rhs.mTrackData;
412 LOG(info) <<
"Initialize FT3 O2Detector";
414 defineSensitiveVolumes();
421 if (!(fMC->TrackCharge())) {
425 int volID = vol->getMCid();
427 auto it = mActiveSensorMap.find(volID);
428 if (it == mActiveSensorMap.end()) {
432 int lay = it->second;
436 bool startHit =
false, stopHit =
false;
437 unsigned char status = 0;
438 if (fMC->IsTrackEntering()) {
439 status |= Hit::kTrackEntering;
441 if (fMC->IsTrackInside()) {
442 status |= Hit::kTrackInside;
444 if (fMC->IsTrackExiting()) {
445 status |= Hit::kTrackExiting;
447 if (fMC->IsTrackOut()) {
448 status |= Hit::kTrackOut;
450 if (fMC->IsTrackStop()) {
451 status |= Hit::kTrackStopped;
453 if (fMC->IsTrackAlive()) {
454 status |= Hit::kTrackAlive;
458 if ((status & Hit::kTrackEntering) || (status & Hit::kTrackInside && !mTrackData.mHitStarted)) {
460 }
else if ((status & (Hit::kTrackExiting | Hit::kTrackOut | Hit::kTrackStopped))) {
466 mTrackData.mEnergyLoss += fMC->Edep();
468 if (!(startHit | stopHit)) {
472 mTrackData.mEnergyLoss = 0.;
473 fMC->TrackMomentum(mTrackData.mMomentumStart);
474 fMC->TrackPosition(mTrackData.mPositionStart);
475 mTrackData.mTrkStatusStart = status;
476 mTrackData.mHitStarted =
true;
479 TLorentzVector positionStop;
480 fMC->TrackPosition(positionStop);
484 Hit* p = addHit(
stack->GetCurrentTrackNumber(), chipindex, mTrackData.mPositionStart.Vect(), positionStop.Vect(),
485 mTrackData.mMomentumStart.Vect(), mTrackData.mMomentumStart.E(), positionStop.T(),
486 mTrackData.mEnergyLoss, mTrackData.mTrkStatusStart, status);
491 stack->addHit(GetDetId());
498void Detector::createMaterials()
504 float tmaxfdSi = 0.1;
505 float stemaxSi = 0.0075;
506 float deemaxSi = 0.1;
507 float epsilSi = 1.0E-4;
510 float tmaxfdAir = 0.1;
511 float stemaxAir = .10000E+01;
512 float deemaxAir = 0.1;
513 float epsilAir = 1.0E-4;
514 float stminAir = 0.0;
517 float aAir[4] = {12.0107, 14.0067, 15.9994, 39.948};
518 float zAir[4] = {6., 7., 8., 18.};
519 float wAir[4] = {0.000124, 0.755267, 0.231781, 0.012827};
520 float dAir = 1.20479E-3;
523 o2::base::Detector::Medium(1,
"AIR$", 1, 0, ifield, fieldm, tmaxfdAir, stemaxAir, deemaxAir, epsilAir, stminAir);
526 o2::base::Detector::Medium(3,
"SILICON$", 3, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
539 if (FairRootManager::Instance()) {
540 FairRootManager::Instance()->RegisterAny(
addNameTo(
"Hit").
data(), mHits, kTRUE);
563void Detector::createGeometry()
571 TGeoVolume* vALIC = gGeoManager->GetVolume(
"barrel");
573 LOG(fatal) <<
"Could not find the top volume";
576 TGeoVolume* A3IPvac = gGeoManager->GetVolume(
"OUT_PIPEVACUUM");
578 LOG(info) <<
"Running simulation with no beam pipe.";
583 for (
int direction : {IdxBackwardDisks, IdxForwardDisks}) {
584 const std::string directionString = direction ?
"Forward" :
"Backward";
585 LOG(info) <<
" Creating FT3 without beampipe " << directionString <<
" layers:";
586 for (
int iLayer = 0; iLayer < mLayers[direction].size(); iLayer++) {
587 mLayers[direction][iLayer].createLayer(volFT3);
590 vALIC->AddNode(volFT3, 2,
new TGeoTranslation(0., 30., 0.));
592 for (
int direction : {IdxBackwardDisks, IdxForwardDisks}) {
593 const std::string directionString = direction ?
"Forward" :
"Backward";
594 LOG(info) <<
" Creating FT3 " << directionString <<
" layers:";
595 for (
int iLayer = 0; iLayer < mLayers[direction].size(); iLayer++) {
596 LOG(info) <<
" Creating " << directionString <<
" layer " << iLayer;
597 if (mLayers[direction][iLayer].getIsInMiddleLayer()) {
598 mLayers[direction][iLayer].createLayer(volIFT3);
600 mLayers[direction][iLayer].createLayer(volFT3);
604 A3IPvac->AddNode(volIFT3, 2,
new TGeoTranslation(0., 0., 0.));
605 vALIC->AddNode(volFT3, 2,
new TGeoTranslation(0., 30., 0.));
610void Detector::defineSensitiveVolumes()
612 TGeoManager* geoManager = gGeoManager;
615 TObjArray* allVolumes = geoManager->GetListOfVolumes();
616 int nVolumes = allVolumes->GetEntriesFast();
618 LOG(info) <<
"Adding FT3 Sensitive Volumes by iterating over all geometry volumes...";
620 for (
int direction : {IdxBackwardDisks, IdxForwardDisks}) {
621 for (
int iLayer = 0; iLayer < getNumberOfLayers(); iLayer++) {
638 for (
int i = 0;
i < nVolumes; ++
i) {
639 TGeoVolume*
v = (TGeoVolume*)allVolumes->At(
i);
640 std::string vName =
v->GetName();
643 if (vName.find(
"Inactive") != std::string::npos || vName.find(
"inactive") != std::string::npos) {
648 bool isMatch =
false;
651 }
else if (vName.find(sig2) == 0 || vName.find(sig3) == 0 || vName.find(sig4) == 0) {
656 AddSensitiveVolume(
v);
657 int volID = gMC ? TVirtualMC::GetMC()->VolId(vName.c_str()) : 0;
659 mActiveSensorMap[volID] = iLayer;
666 LOG(error) <<
"NO sensitive volume found for direction " << direction <<
", layer " << iLayer;
668 LOG(info) << iSens <<
" sensitive volume(s) added for direction " << direction <<
" layer " << iLayer;
676 const TVector3& startMom,
double startE,
double endTime,
double eLoss,
unsigned char startStatus,
677 unsigned char endStatus)
679 mHits->emplace_back(trackID, detID, startPos, endPos, startMom, startE, endTime, eLoss, startStatus, endStatus);
680 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())
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"