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);
136 std::string configFileName =
"FT3_layout.cfg";
138 LOG(info) <<
"Exporting FT3 Detector layout to " << configFileName;
140 std::ofstream fOut(configFileName.c_str(), std::ios::out);
142 printf(
"Cannot open file\n");
145 fOut <<
"# z_layer r_in r_out Layerx2X0" << std::endl;
146 for (
auto layers_dir : mLayers) {
147 for (
auto layer : layers_dir) {
148 fOut <<
layer.getZ() <<
" " <<
layer.getInnerRadius() <<
" " <<
layer.getOuterRadius() <<
" " <<
layer.getx2X0() << std::endl;
159 LOG(info) <<
"Building FT3 Detector: Conical Telescope";
161 auto z_first =
param.z0;
162 auto z_length =
param.zLength;
163 auto etaIn =
param.etaIn;
164 auto etaOut =
param.etaOut;
165 auto Layerx2X0 =
param.Layerx2X0;
173 for (
int direction : {0, 1}) {
174 for (
int layerNumber = 0; layerNumber <
mNumberOfLayers; layerNumber++) {
176 mLayerName[direction][layerNumber] = layerName;
179 float layerZ = z_first + (layerNumber * z_length / (
mNumberOfLayers - 1)) * std::copysign(1, z_first);
180 float rIn = std::abs(layerZ * std::tan(2.f * std::atan(std::exp(-etaIn))));
181 float rOut = std::abs(layerZ * std::tan(2.f * std::atan(std::exp(-etaOut))));
182 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName, layerZ, rIn, rOut, Layerx2X0);
193 LOG(info) <<
"Building FT3 Detector: V1";
196 float sensorThickness = 30.e-4;
197 float layersx2X0 = 1.e-2;
198 std::vector<std::array<float, 5>> layersConfig{
199 {26., .5, 3., 0.1f * layersx2X0},
200 {30., .5, 3., 0.1f * layersx2X0},
201 {34., .5, 3., 0.1f * layersx2X0},
202 {77., 3.5, 35., layersx2X0},
203 {100., 3.5, 35., layersx2X0},
204 {122., 3.5, 35., layersx2X0},
205 {150., 3.5, 80.f, layersx2X0},
206 {180., 3.5, 80.f, layersx2X0},
207 {220., 3.5, 80.f, layersx2X0},
208 {279., 3.5, 80.f, layersx2X0}};
216 for (
auto direction : {0, 1}) {
217 for (
int layerNumber = 0; layerNumber <
mNumberOfLayers; layerNumber++) {
220 mLayerName[direction][layerNumber] = layerName;
221 auto&
z = layersConfig[layerNumber][0];
223 auto& rIn = layersConfig[layerNumber][1];
224 auto& rOut = layersConfig[layerNumber][2];
225 auto&
x0 = layersConfig[layerNumber][3];
227 LOG(info) <<
"Adding Layer " << layerName <<
" at z = " <<
z;
229 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName,
z, rIn, rOut,
x0);
240 LOG(info) <<
"Building FT3 Detector: V3b";
243 float sensorThickness = 30.e-4;
244 float layersx2X0 = 1.e-2;
245 std::vector<std::array<float, 5>> layersConfig{
246 {26., .5, 3., 0.1f * layersx2X0},
247 {30., .5, 3., 0.1f * layersx2X0},
248 {34., .5, 3., 0.1f * layersx2X0},
249 {77., 5.0, 35., layersx2X0},
250 {100., 5.0, 35., layersx2X0},
251 {122., 5.0, 35., layersx2X0},
252 {150., 5.5, 80.f, layersx2X0},
253 {180., 6.6, 80.f, layersx2X0},
254 {220., 8.1, 80.f, layersx2X0},
255 {279., 10.2, 80.f, layersx2X0},
256 {340., 12.5, 80.f, layersx2X0},
257 {400., 14.7, 80.f, layersx2X0}};
265 for (
auto direction : {0, 1}) {
266 for (
int layerNumber = 0; layerNumber <
mNumberOfLayers; layerNumber++) {
269 mLayerName[direction][layerNumber] = layerName;
270 auto&
z = layersConfig[layerNumber][0];
272 auto& rIn = layersConfig[layerNumber][1];
273 auto& rOut = layersConfig[layerNumber][2];
274 auto&
x0 = layersConfig[layerNumber][3];
276 LOG(info) <<
"Adding Layer " << layerName <<
" at z = " <<
z;
278 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName,
z, rIn, rOut,
x0);
292 LOG(info) <<
"Building FT3 Detector: After Upgrade Days March 2024 version";
295 float sensorThickness = 30.e-4;
296 float layersx2X0 = 1.e-2;
297 std::vector<std::array<float, 5>> layersConfigCSide{
298 {77., 7.0, 35., layersx2X0},
299 {100., 7.0, 35., layersx2X0},
300 {122., 7.0, 35., layersx2X0},
301 {150., 7.0, 68.f, layersx2X0},
302 {180., 7.0, 68.f, layersx2X0},
303 {220., 7.0, 68.f, layersx2X0},
304 {260., 7.0, 68.f, layersx2X0},
305 {300., 7.0, 68.f, layersx2X0},
306 {350., 7.0, 68.f, layersx2X0}};
308 std::vector<std::array<float, 5>> layersConfigASide{
309 {77., 5.0, 35., layersx2X0},
310 {100., 5.0, 35., layersx2X0},
311 {122., 5.0, 35., layersx2X0},
312 {150., 5.0, 68.f, layersx2X0},
313 {180., 5.0, 68.f, layersx2X0},
314 {220., 5.0, 68.f, layersx2X0},
315 {260., 5.0, 68.f, layersx2X0},
316 {300., 5.0, 68.f, layersx2X0},
317 {350., 5.0, 68.f, layersx2X0}};
325 for (
auto direction : {0, 1}) {
326 for (
int layerNumber = 0; layerNumber <
mNumberOfLayers; layerNumber++) {
329 mLayerName[direction][layerNumber] = layerName;
330 float z, rIn, rOut,
x0;
331 if (direction == 0) {
332 z = layersConfigCSide[layerNumber][0];
333 rIn = layersConfigCSide[layerNumber][1];
334 rOut = layersConfigCSide[layerNumber][2];
335 x0 = layersConfigCSide[layerNumber][3];
336 }
else if (direction == 1) {
337 z = layersConfigASide[layerNumber][0];
338 rIn = layersConfigASide[layerNumber][1];
339 rOut = layersConfigASide[layerNumber][2];
340 x0 = layersConfigASide[layerNumber][3];
343 LOG(info) <<
"Adding Layer " << layerName <<
" at z = " <<
z;
345 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName,
z, rIn, rOut,
x0);
357 LOG(info) <<
"Building FT3 Detector: v3 scoping version";
360 float sensorThickness = 30.e-4;
361 float layersx2X0 = 1.e-2;
362 std::vector<std::array<float, 5>> layersConfigCSide{
363 {77., 10.0, 35., layersx2X0},
364 {100., 10.0, 35., layersx2X0},
365 {122., 10.0, 35., layersx2X0},
366 {150., 20.0, 68.f, layersx2X0},
367 {180., 20.0, 68.f, layersx2X0},
368 {220., 20.0, 68.f, layersx2X0}};
370 std::vector<std::array<float, 5>> layersConfigASide{
371 {77., 10.0, 35., layersx2X0},
372 {100., 10.0, 35., layersx2X0},
373 {122., 10.0, 35., layersx2X0},
374 {150., 20.0, 68.f, layersx2X0},
375 {180., 20.0, 68.f, layersx2X0},
376 {220., 20.0, 68.f, layersx2X0}};
384 for (
auto direction : {0, 1}) {
385 for (
int layerNumber = 0; layerNumber <
mNumberOfLayers; layerNumber++) {
388 mLayerName[direction][layerNumber] = layerName;
389 float z, rIn, rOut,
x0;
390 if (direction == 0) {
391 z = layersConfigCSide[layerNumber][0];
392 rIn = layersConfigCSide[layerNumber][1];
393 rOut = layersConfigCSide[layerNumber][2];
394 x0 = layersConfigCSide[layerNumber][3];
395 }
else if (direction == 1) {
396 z = layersConfigASide[layerNumber][0];
397 rIn = layersConfigASide[layerNumber][1];
398 rOut = layersConfigASide[layerNumber][2];
399 x0 = layersConfigASide[layerNumber][3];
402 LOG(info) <<
"Adding Layer " << layerName <<
" at z = " <<
z;
404 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName,
z, rIn, rOut,
x0);
414 LOG(info) <<
"Building FT3 Detector: Scoping document version";
417 float sensorThickness = 30.e-4;
418 float layersx2X0 = 1.e-2;
419 std::vector<std::array<float, 5>> layersConfig{
420 {26., .5, 2.5, 0.1f * layersx2X0},
421 {30., .5, 2.5, 0.1f * layersx2X0},
422 {34., .5, 2.5, 0.1f * layersx2X0},
423 {77., 5.0, 35., layersx2X0},
424 {100., 5.0, 35., layersx2X0},
425 {122., 5.0, 35., layersx2X0},
426 {150., 5.0, 68.f, layersx2X0},
427 {180., 5.0, 68.f, layersx2X0},
428 {220., 5.0, 68.f, layersx2X0},
429 {260., 5.0, 68.f, layersx2X0},
430 {300., 5.0, 68.f, layersx2X0},
431 {350., 5.0, 68.f, layersx2X0}};
439 for (
auto direction : {0, 1}) {
440 for (
int layerNumber = 0; layerNumber <
mNumberOfLayers; layerNumber++) {
443 mLayerName[direction][layerNumber] = layerName;
444 auto&
z = layersConfig[layerNumber][0];
446 auto& rIn = layersConfig[layerNumber][1];
447 auto& rOut = layersConfig[layerNumber][2];
448 auto&
x0 = layersConfig[layerNumber][3];
450 LOG(info) <<
"Adding Layer " << layerName <<
" at z = " <<
z;
452 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName,
z, rIn, rOut,
x0);
465 auto& ft3BaseParam = FT3BaseParam::Instance();
467 if (ft3BaseParam.configFile !=
"") {
468 LOG(info) <<
"FT3 Geometry configuration file provided. Overriding FT3Base.geoModel configuration.";
469 buildFT3FromFile(ft3BaseParam.configFile);
472 switch (ft3BaseParam.geoModel) {
477 buildBasicFT3(ft3BaseParam);
480 LOG(fatal) <<
"Invalid Geometry.\n";
495 mLayerID = rhs.mLayerID;
496 mLayerName = rhs.mLayerName;
497 mNumberOfLayers = rhs.mNumberOfLayers;
528 mLayerID = rhs.mLayerID;
529 mLayerName = rhs.mLayerName;
530 mNumberOfLayers = rhs.mNumberOfLayers;
531 mLayers = rhs.mLayers;
532 mTrackData = rhs.mTrackData;
544 LOG(info) <<
"Initialize FT3 O2Detector";
548 defineSensitiveVolumes();
555 if (!(fMC->TrackCharge())) {
559 int lay = 0, volID = vol->getMCid();
560 while ((lay <= mLayerID.size()) && (volID != mLayerID[lay])) {
566 bool startHit =
false, stopHit =
false;
567 unsigned char status = 0;
568 if (fMC->IsTrackEntering()) {
569 status |= Hit::kTrackEntering;
571 if (fMC->IsTrackInside()) {
572 status |= Hit::kTrackInside;
574 if (fMC->IsTrackExiting()) {
575 status |= Hit::kTrackExiting;
577 if (fMC->IsTrackOut()) {
578 status |= Hit::kTrackOut;
580 if (fMC->IsTrackStop()) {
581 status |= Hit::kTrackStopped;
583 if (fMC->IsTrackAlive()) {
584 status |= Hit::kTrackAlive;
588 if ((status & Hit::kTrackEntering) || (status & Hit::kTrackInside && !mTrackData.mHitStarted)) {
590 }
else if ((status & (Hit::kTrackExiting | Hit::kTrackOut | Hit::kTrackStopped))) {
596 mTrackData.mEnergyLoss += fMC->Edep();
598 if (!(startHit | stopHit)) {
602 mTrackData.mEnergyLoss = 0.;
603 fMC->TrackMomentum(mTrackData.mMomentumStart);
604 fMC->TrackPosition(mTrackData.mPositionStart);
605 mTrackData.mTrkStatusStart = status;
606 mTrackData.mHitStarted =
true;
609 TLorentzVector positionStop;
610 fMC->TrackPosition(positionStop);
614 Hit* p = addHit(
stack->GetCurrentTrackNumber(), chipindex, mTrackData.mPositionStart.Vect(), positionStop.Vect(),
615 mTrackData.mMomentumStart.Vect(), mTrackData.mMomentumStart.E(), positionStop.T(),
616 mTrackData.mEnergyLoss, mTrackData.mTrkStatusStart, status);
621 stack->addHit(GetDetId());
628void Detector::createMaterials()
634 float tmaxfdSi = 0.1;
635 float stemaxSi = 0.0075;
636 float deemaxSi = 0.1;
637 float epsilSi = 1.0E-4;
640 float tmaxfdAir = 0.1;
641 float stemaxAir = .10000E+01;
642 float deemaxAir = 0.1;
643 float epsilAir = 1.0E-4;
644 float stminAir = 0.0;
647 float aAir[4] = {12.0107, 14.0067, 15.9994, 39.948};
648 float zAir[4] = {6., 7., 8., 18.};
649 float wAir[4] = {0.000124, 0.755267, 0.231781, 0.012827};
650 float dAir = 1.20479E-3;
653 o2::base::Detector::Medium(1,
"AIR$", 1, 0, ifield, fieldm, tmaxfdAir, stemaxAir, deemaxAir, epsilAir, stminAir);
656 o2::base::Detector::Medium(3,
"SILICON$", 3, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
669 if (FairRootManager::Instance()) {
670 FairRootManager::Instance()->RegisterAny(
addNameTo(
"Hit").
data(), mHits, kTRUE);
693void Detector::createGeometry()
703 TGeoVolume* vALIC = gGeoManager->GetVolume(
"barrel");
705 LOG(fatal) <<
"Could not find the top volume";
708 TGeoVolume* A3IPvac = gGeoManager->GetVolume(
"OUT_PIPEVACUUM");
710 LOG(info) <<
"Running simulation with no beam pipe.";
713 LOG(
debug) <<
"FT3 createGeometry: "
714 << Form(
"gGeoManager name is %s title is %s", gGeoManager->GetName(), gGeoManager->GetTitle());
716 if (mLayers.size() == 2) {
718 for (
int direction : {0, 1}) {
719 std::string directionString = direction ?
"Forward" :
"Backward";
720 LOG(info) <<
"Creating FT3 " << directionString <<
" layers:";
721 for (
int iLayer = 0; iLayer < mLayers[direction].size(); iLayer++) {
722 mLayers[direction][iLayer].createLayer(volFT3);
725 vALIC->AddNode(volFT3, 2,
new TGeoTranslation(0., 30., 0.));
727 for (
int direction : {0, 1}) {
728 std::string directionString = direction ?
"Forward" :
"Backward";
729 LOG(info) <<
"Creating FT3 " << directionString <<
" layers:";
730 for (
int iLayer = 0; iLayer < mLayers[direction].size(); iLayer++) {
732 mLayers[direction][iLayer].createLayer(volIFT3);
734 mLayers[direction][iLayer].createLayer(volFT3);
738 A3IPvac->AddNode(volIFT3, 2,
new TGeoTranslation(0., 0., 0.));
739 vALIC->AddNode(volFT3, 2,
new TGeoTranslation(0., 30., 0.));
742 for (
auto direction : {0, 1}) {
743 std::string directionString = direction ?
"Forward" :
"Backward";
744 LOG(info) <<
"Registering FT3 " << directionString <<
" LayerIDs:";
745 for (
int iLayer = 0; iLayer < mLayers[direction].size(); iLayer++) {
747 mLayerID.push_back(layerID);
748 LOG(info) <<
" " << directionString <<
" layer " << iLayer <<
" LayerID " << layerID;
753 if (mLayers.size() == 1) {
754 LOG(info) <<
"Creating FT3 layers:";
756 for (
int iLayer = 0; iLayer < mLayers[0].size(); iLayer++) {
757 if (std::abs(mLayers[0][iLayer].getZ()) < 25) {
758 mLayers[0][iLayer].createLayer(volIFT3);
760 mLayers[0][iLayer].createLayer(volFT3);
763 A3IPvac->AddNode(volIFT3, 2,
new TGeoTranslation(0., 0., 0.));
764 vALIC->AddNode(volFT3, 2,
new TGeoTranslation(0., 30., 0.));
766 for (
int iLayer = 0; iLayer < mLayers[0].size(); iLayer++) {
767 mLayers[0][iLayer].createLayer(volFT3);
769 vALIC->AddNode(volFT3, 2,
new TGeoTranslation(0., 30., 0.));
771 LOG(info) <<
"Registering FT3 LayerIDs:";
772 for (
int iLayer = 0; iLayer < mLayers[0].size(); iLayer++) {
774 mLayerID.push_back(layerID);
775 LOG(info) <<
" mLayerID[" << iLayer <<
"] = " << layerID;
781void Detector::defineSensitiveVolumes()
783 TGeoManager* geoManager = gGeoManager;
787 LOG(info) <<
"Adding FT3 Sensitive Volumes";
790 if (mLayers.size() == 2) {
791 for (
int direction : {0, 1}) {
792 for (
int iLayer = 0; iLayer < mNumberOfLayers; iLayer++) {
796 AddSensitiveVolume(
v);
798 for (
int sensor_count = 0; sensor_count <
MAX_SENSORS; ++sensor_count) {
801 v = geoManager->GetVolume(sensor_name_front.c_str());
803 AddSensitiveVolume(
v);
805 v = geoManager->GetVolume(sensor_name_back.c_str());
807 AddSensitiveVolume(
v);
815 if (mLayers.size() == 1) {
816 for (
int iLayer = 0; iLayer < mLayers[0].size(); iLayer++) {
819 LOG(info) <<
"Adding FT3 Sensitive Volume => " <<
v->GetName();
820 AddSensitiveVolume(
v);
827 const TVector3& startMom,
double startE,
double endTime,
double eLoss,
unsigned char startStatus,
828 unsigned char endStatus)
830 mHits->emplace_back(trackID, detID, startPos, endPos, startMom, startE, endTime, eLoss, startStatus, endStatus);
831 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"