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
90 LOG(info) <<
"Building FT3 Detector: From file";
91 LOG(info) <<
" FT3 detector configuration: " << configFileName;
92 std::ifstream ifs(configFileName.c_str());
94 LOG(fatal) <<
" Invalid FT3Base.configFile!";
97 float z_layer, r_in, r_out, Layerx2X0;
100 while (std::getline(ifs, tempstr)) {
101 if (tempstr[0] ==
'#') {
102 LOG(info) <<
" Comment: " << tempstr;
105 std::istringstream iss(tempstr);
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);
135 std::string configFileName =
"FT3_layout.cfg";
137 LOG(info) <<
"Exporting FT3 Detector layout to " << configFileName;
139 std::ofstream fOut(configFileName.c_str(), std::ios::out);
141 printf(
"Cannot open file\n");
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;
158 LOG(info) <<
"Building FT3 Detector: Conical Telescope";
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;
172 for (
int direction : {0, 1}) {
173 for (
int layerNumber = 0; layerNumber <
mNumberOfLayers; layerNumber++) {
175 mLayerName[direction][layerNumber] = layerName;
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);
192 LOG(info) <<
"Building FT3 Detector: V1";
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},
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}};
215 for (
auto direction : {0, 1}) {
216 for (
int layerNumber = 0; layerNumber <
mNumberOfLayers; layerNumber++) {
219 mLayerName[direction][layerNumber] = layerName;
220 auto&
z = layersConfig[layerNumber][0];
222 auto& rIn = layersConfig[layerNumber][1];
223 auto& rOut = layersConfig[layerNumber][2];
224 auto&
x0 = layersConfig[layerNumber][3];
226 LOG(info) <<
"Adding Layer " << layerName <<
" at z = " <<
z;
228 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName,
z, rIn, rOut,
x0);
239 LOG(info) <<
"Building FT3 Detector: V3b";
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},
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}};
264 for (
auto direction : {0, 1}) {
265 for (
int layerNumber = 0; layerNumber <
mNumberOfLayers; layerNumber++) {
268 mLayerName[direction][layerNumber] = layerName;
269 auto&
z = layersConfig[layerNumber][0];
271 auto& rIn = layersConfig[layerNumber][1];
272 auto& rOut = layersConfig[layerNumber][2];
273 auto&
x0 = layersConfig[layerNumber][3];
275 LOG(info) <<
"Adding Layer " << layerName <<
" at z = " <<
z;
277 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName,
z, rIn, rOut,
x0);
291 LOG(info) <<
"Building FT3 Detector: After Upgrade Days March 2024 version";
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},
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}};
307 std::vector<std::array<float, 5>> layersConfigASide{
308 {77., 5.0, 35., layersx2X0},
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}};
324 for (
auto direction : {0, 1}) {
325 for (
int layerNumber = 0; layerNumber <
mNumberOfLayers; layerNumber++) {
328 mLayerName[direction][layerNumber] = layerName;
329 float z, rIn, rOut,
x0;
330 if (direction == 0) {
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) {
336 z = layersConfigASide[layerNumber][0];
337 rIn = layersConfigASide[layerNumber][1];
338 rOut = layersConfigASide[layerNumber][2];
339 x0 = layersConfigASide[layerNumber][3];
342 LOG(info) <<
"Adding Layer " << layerName <<
" at z = " <<
z;
344 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName,
z, rIn, rOut,
x0);
354 LOG(info) <<
"Building FT3 Detector: Scoping document version";
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},
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}};
379 for (
auto direction : {0, 1}) {
380 for (
int layerNumber = 0; layerNumber <
mNumberOfLayers; layerNumber++) {
383 mLayerName[direction][layerNumber] = layerName;
384 auto&
z = layersConfig[layerNumber][0];
386 auto& rIn = layersConfig[layerNumber][1];
387 auto& rOut = layersConfig[layerNumber][2];
388 auto&
x0 = layersConfig[layerNumber][3];
390 LOG(info) <<
"Adding Layer " << layerName <<
" at z = " <<
z;
392 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName,
z, rIn, rOut,
x0);
405 auto& ft3BaseParam = FT3BaseParam::Instance();
407 if (ft3BaseParam.configFile !=
"") {
408 LOG(info) <<
"FT3 Geometry configuration file provided. Overriding FT3Base.geoModel configuration.";
409 buildFT3FromFile(ft3BaseParam.configFile);
412 switch (ft3BaseParam.geoModel) {
414 buildFT3NewVacuumVessel();
417 buildBasicFT3(ft3BaseParam);
420 LOG(fatal) <<
"Invalid Geometry.\n";
435 mLayerID = rhs.mLayerID;
436 mLayerName = rhs.mLayerName;
437 mNumberOfLayers = rhs.mNumberOfLayers;
468 mLayerID = rhs.mLayerID;
469 mLayerName = rhs.mLayerName;
470 mNumberOfLayers = rhs.mNumberOfLayers;
471 mLayers = rhs.mLayers;
472 mTrackData = rhs.mTrackData;
484 LOG(info) <<
"Initialize FT3 O2Detector";
488 defineSensitiveVolumes();
495 if (!(fMC->TrackCharge())) {
499 int lay = 0, volID = vol->getMCid();
500 while ((lay <= mLayerID.size()) && (volID != mLayerID[lay])) {
506 bool startHit =
false, stopHit =
false;
507 unsigned char status = 0;
508 if (fMC->IsTrackEntering()) {
509 status |= Hit::kTrackEntering;
511 if (fMC->IsTrackInside()) {
512 status |= Hit::kTrackInside;
514 if (fMC->IsTrackExiting()) {
515 status |= Hit::kTrackExiting;
517 if (fMC->IsTrackOut()) {
518 status |= Hit::kTrackOut;
520 if (fMC->IsTrackStop()) {
521 status |= Hit::kTrackStopped;
523 if (fMC->IsTrackAlive()) {
524 status |= Hit::kTrackAlive;
528 if ((status & Hit::kTrackEntering) || (status & Hit::kTrackInside && !mTrackData.mHitStarted)) {
530 }
else if ((status & (Hit::kTrackExiting | Hit::kTrackOut | Hit::kTrackStopped))) {
536 mTrackData.mEnergyLoss += fMC->Edep();
538 if (!(startHit | stopHit)) {
542 mTrackData.mEnergyLoss = 0.;
543 fMC->TrackMomentum(mTrackData.mMomentumStart);
544 fMC->TrackPosition(mTrackData.mPositionStart);
545 mTrackData.mTrkStatusStart = status;
546 mTrackData.mHitStarted =
true;
549 TLorentzVector positionStop;
550 fMC->TrackPosition(positionStop);
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);
561 stack->addHit(GetDetId());
568void Detector::createMaterials()
574 float tmaxfdSi = 0.1;
575 float stemaxSi = 0.0075;
576 float deemaxSi = 0.1;
577 float epsilSi = 1.0E-4;
580 float tmaxfdAir = 0.1;
581 float stemaxAir = .10000E+01;
582 float deemaxAir = 0.1;
583 float epsilAir = 1.0E-4;
584 float stminAir = 0.0;
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;
593 o2::base::Detector::Medium(1,
"AIR$", 1, 0, ifield, fieldm, tmaxfdAir, stemaxAir, deemaxAir, epsilAir, stminAir);
596 o2::base::Detector::Medium(3,
"SILICON$", 3, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
609 if (FairRootManager::Instance()) {
610 FairRootManager::Instance()->RegisterAny(
addNameTo(
"Hit").
data(), mHits, kTRUE);
633void Detector::createGeometry()
643 TGeoVolume* vALIC = gGeoManager->GetVolume(
"barrel");
645 LOG(fatal) <<
"Could not find the top volume";
648 TGeoVolume* A3IPvac = gGeoManager->GetVolume(
"OUT_PIPEVACUUM");
650 LOG(info) <<
"Running simulation with no beam pipe.";
653 LOG(
debug) <<
"FT3 createGeometry: "
654 << Form(
"gGeoManager name is %s title is %s", gGeoManager->GetName(), gGeoManager->GetTitle());
656 if (mLayers.size() == 2) {
658 for (
int direction : {0, 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);
665 vALIC->AddNode(volFT3, 2,
new TGeoTranslation(0., 30., 0.));
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++) {
672 mLayers[direction][iLayer].createLayer(volIFT3);
674 mLayers[direction][iLayer].createLayer(volFT3);
678 A3IPvac->AddNode(volIFT3, 2,
new TGeoTranslation(0., 0., 0.));
679 vALIC->AddNode(volFT3, 2,
new TGeoTranslation(0., 30., 0.));
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++) {
687 mLayerID.push_back(layerID);
688 LOG(info) <<
" " << directionString <<
" layer " << iLayer <<
" LayerID " << layerID;
693 if (mLayers.size() == 1) {
694 LOG(info) <<
"Creating FT3 layers:";
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);
700 mLayers[0][iLayer].createLayer(volFT3);
703 A3IPvac->AddNode(volIFT3, 2,
new TGeoTranslation(0., 0., 0.));
704 vALIC->AddNode(volFT3, 2,
new TGeoTranslation(0., 30., 0.));
706 for (
int iLayer = 0; iLayer < mLayers[0].size(); iLayer++) {
707 mLayers[0][iLayer].createLayer(volFT3);
709 vALIC->AddNode(volFT3, 2,
new TGeoTranslation(0., 30., 0.));
711 LOG(info) <<
"Registering FT3 LayerIDs:";
712 for (
int iLayer = 0; iLayer < mLayers[0].size(); iLayer++) {
714 mLayerID.push_back(layerID);
715 LOG(info) <<
" mLayerID[" << iLayer <<
"] = " << layerID;
721void Detector::defineSensitiveVolumes()
723 TGeoManager* geoManager = gGeoManager;
727 LOG(info) <<
"Adding FT3 Sensitive Volumes";
730 if (mLayers.size() == 2) {
731 for (
int direction : {0, 1}) {
732 for (
int iLayer = 0; iLayer < mNumberOfLayers; iLayer++) {
736 AddSensitiveVolume(
v);
738 for (
int sensor_count = 0; sensor_count <
MAX_SENSORS; ++sensor_count) {
741 v = geoManager->GetVolume(sensor_name_front.c_str());
743 AddSensitiveVolume(
v);
745 v = geoManager->GetVolume(sensor_name_back.c_str());
747 AddSensitiveVolume(
v);
755 if (mLayers.size() == 1) {
756 for (
int iLayer = 0; iLayer < mLayers[0].size(); iLayer++) {
759 LOG(info) <<
"Adding FT3 Sensitive Volume => " <<
v->GetName();
760 AddSensitiveVolume(
v);
767 const TVector3& startMom,
double startE,
double endTime,
double eLoss,
unsigned char startStatus,
768 unsigned char endStatus)
770 mHits->emplace_back(trackID, detID, startPos, endPos, startMom, startE, endTime, eLoss, startStatus, endStatus);
771 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::vector< std::vector< TString > > mLayerName
void EndOfEvent() override
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 buildFT3FromFile(std::string)
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.
void exportLayout()
access to geometry details
static const char * getFT3SensorPattern()
static const char * getFT3LayerPattern()
static GeometryTGeo * Instance()
static const char * getFT3VolPattern()
static const char * getFT3InnerVolPattern()
static ShmManager & Instance()
GLenum GLuint GLint GLint layer
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"