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);
356 LOG(info) <<
"Building FT3 Detector: v3 scoping version";
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},
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}};
369 std::vector<std::array<float, 5>> layersConfigASide{
370 {77., 10.0, 35., layersx2X0},
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}};
383 for (
auto direction : {0, 1}) {
384 for (
int layerNumber = 0; layerNumber <
mNumberOfLayers; layerNumber++) {
387 mLayerName[direction][layerNumber] = layerName;
388 float z, rIn, rOut,
x0;
389 if (direction == 0) {
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) {
395 z = layersConfigASide[layerNumber][0];
396 rIn = layersConfigASide[layerNumber][1];
397 rOut = layersConfigASide[layerNumber][2];
398 x0 = layersConfigASide[layerNumber][3];
401 LOG(info) <<
"Adding Layer " << layerName <<
" at z = " <<
z;
403 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName,
z, rIn, rOut,
x0);
413 LOG(info) <<
"Building FT3 Detector: Scoping document version";
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},
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}};
438 for (
auto direction : {0, 1}) {
439 for (
int layerNumber = 0; layerNumber <
mNumberOfLayers; layerNumber++) {
442 mLayerName[direction][layerNumber] = layerName;
443 auto&
z = layersConfig[layerNumber][0];
445 auto& rIn = layersConfig[layerNumber][1];
446 auto& rOut = layersConfig[layerNumber][2];
447 auto&
x0 = layersConfig[layerNumber][3];
449 LOG(info) <<
"Adding Layer " << layerName <<
" at z = " <<
z;
451 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName,
z, rIn, rOut,
x0);
464 auto& ft3BaseParam = FT3BaseParam::Instance();
466 if (ft3BaseParam.configFile !=
"") {
467 LOG(info) <<
"FT3 Geometry configuration file provided. Overriding FT3Base.geoModel configuration.";
468 buildFT3FromFile(ft3BaseParam.configFile);
471 switch (ft3BaseParam.geoModel) {
476 buildBasicFT3(ft3BaseParam);
479 LOG(fatal) <<
"Invalid Geometry.\n";
494 mLayerID = rhs.mLayerID;
495 mLayerName = rhs.mLayerName;
496 mNumberOfLayers = rhs.mNumberOfLayers;
527 mLayerID = rhs.mLayerID;
528 mLayerName = rhs.mLayerName;
529 mNumberOfLayers = rhs.mNumberOfLayers;
530 mLayers = rhs.mLayers;
531 mTrackData = rhs.mTrackData;
543 LOG(info) <<
"Initialize FT3 O2Detector";
547 defineSensitiveVolumes();
554 if (!(fMC->TrackCharge())) {
558 int lay = 0, volID = vol->getMCid();
559 while ((lay <= mLayerID.size()) && (volID != mLayerID[lay])) {
565 bool startHit =
false, stopHit =
false;
566 unsigned char status = 0;
567 if (fMC->IsTrackEntering()) {
568 status |= Hit::kTrackEntering;
570 if (fMC->IsTrackInside()) {
571 status |= Hit::kTrackInside;
573 if (fMC->IsTrackExiting()) {
574 status |= Hit::kTrackExiting;
576 if (fMC->IsTrackOut()) {
577 status |= Hit::kTrackOut;
579 if (fMC->IsTrackStop()) {
580 status |= Hit::kTrackStopped;
582 if (fMC->IsTrackAlive()) {
583 status |= Hit::kTrackAlive;
587 if ((status & Hit::kTrackEntering) || (status & Hit::kTrackInside && !mTrackData.mHitStarted)) {
589 }
else if ((status & (Hit::kTrackExiting | Hit::kTrackOut | Hit::kTrackStopped))) {
595 mTrackData.mEnergyLoss += fMC->Edep();
597 if (!(startHit | stopHit)) {
601 mTrackData.mEnergyLoss = 0.;
602 fMC->TrackMomentum(mTrackData.mMomentumStart);
603 fMC->TrackPosition(mTrackData.mPositionStart);
604 mTrackData.mTrkStatusStart = status;
605 mTrackData.mHitStarted =
true;
608 TLorentzVector positionStop;
609 fMC->TrackPosition(positionStop);
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);
620 stack->addHit(GetDetId());
627void Detector::createMaterials()
633 float tmaxfdSi = 0.1;
634 float stemaxSi = 0.0075;
635 float deemaxSi = 0.1;
636 float epsilSi = 1.0E-4;
639 float tmaxfdAir = 0.1;
640 float stemaxAir = .10000E+01;
641 float deemaxAir = 0.1;
642 float epsilAir = 1.0E-4;
643 float stminAir = 0.0;
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;
652 o2::base::Detector::Medium(1,
"AIR$", 1, 0, ifield, fieldm, tmaxfdAir, stemaxAir, deemaxAir, epsilAir, stminAir);
655 o2::base::Detector::Medium(3,
"SILICON$", 3, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
668 if (FairRootManager::Instance()) {
669 FairRootManager::Instance()->RegisterAny(
addNameTo(
"Hit").
data(), mHits, kTRUE);
692void Detector::createGeometry()
702 TGeoVolume* vALIC = gGeoManager->GetVolume(
"barrel");
704 LOG(fatal) <<
"Could not find the top volume";
707 TGeoVolume* A3IPvac = gGeoManager->GetVolume(
"OUT_PIPEVACUUM");
709 LOG(info) <<
"Running simulation with no beam pipe.";
712 LOG(
debug) <<
"FT3 createGeometry: "
713 << Form(
"gGeoManager name is %s title is %s", gGeoManager->GetName(), gGeoManager->GetTitle());
715 if (mLayers.size() == 2) {
717 for (
int direction : {0, 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);
724 vALIC->AddNode(volFT3, 2,
new TGeoTranslation(0., 30., 0.));
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++) {
731 mLayers[direction][iLayer].createLayer(volIFT3);
733 mLayers[direction][iLayer].createLayer(volFT3);
737 A3IPvac->AddNode(volIFT3, 2,
new TGeoTranslation(0., 0., 0.));
738 vALIC->AddNode(volFT3, 2,
new TGeoTranslation(0., 30., 0.));
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++) {
746 mLayerID.push_back(layerID);
747 LOG(info) <<
" " << directionString <<
" layer " << iLayer <<
" LayerID " << layerID;
752 if (mLayers.size() == 1) {
753 LOG(info) <<
"Creating FT3 layers:";
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);
759 mLayers[0][iLayer].createLayer(volFT3);
762 A3IPvac->AddNode(volIFT3, 2,
new TGeoTranslation(0., 0., 0.));
763 vALIC->AddNode(volFT3, 2,
new TGeoTranslation(0., 30., 0.));
765 for (
int iLayer = 0; iLayer < mLayers[0].size(); iLayer++) {
766 mLayers[0][iLayer].createLayer(volFT3);
768 vALIC->AddNode(volFT3, 2,
new TGeoTranslation(0., 30., 0.));
770 LOG(info) <<
"Registering FT3 LayerIDs:";
771 for (
int iLayer = 0; iLayer < mLayers[0].size(); iLayer++) {
773 mLayerID.push_back(layerID);
774 LOG(info) <<
" mLayerID[" << iLayer <<
"] = " << layerID;
780void Detector::defineSensitiveVolumes()
782 TGeoManager* geoManager = gGeoManager;
786 LOG(info) <<
"Adding FT3 Sensitive Volumes";
789 if (mLayers.size() == 2) {
790 for (
int direction : {0, 1}) {
791 for (
int iLayer = 0; iLayer < mNumberOfLayers; iLayer++) {
795 AddSensitiveVolume(
v);
797 for (
int sensor_count = 0; sensor_count <
MAX_SENSORS; ++sensor_count) {
800 v = geoManager->GetVolume(sensor_name_front.c_str());
802 AddSensitiveVolume(
v);
804 v = geoManager->GetVolume(sensor_name_back.c_str());
806 AddSensitiveVolume(
v);
814 if (mLayers.size() == 1) {
815 for (
int iLayer = 0; iLayer < mLayers[0].size(); iLayer++) {
818 LOG(info) <<
"Adding FT3 Sensitive Volume => " <<
v->GetName();
819 AddSensitiveVolume(
v);
826 const TVector3& startMom,
double startE,
double endTime,
double eLoss,
unsigned char startStatus,
827 unsigned char endStatus)
829 mHits->emplace_back(trackID, detID, startPos, endPos, startMom, startE, endTime, eLoss, startStatus, endStatus);
830 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"