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"
88 LOG(info) <<
"Building FT3 Detector: From file";
89 LOG(info) <<
" FT3 detector configuration: " << configFileName;
90 std::ifstream ifs(configFileName.c_str());
92 LOG(fatal) <<
" Invalid FT3Base.configFile!";
95 float z_layer, r_in, r_out, Layerx2X0;
98 while (std::getline(ifs, tempstr)) {
99 if (tempstr[0] ==
'#') {
100 LOG(info) <<
" Comment: " << tempstr;
103 std::istringstream iss(tempstr);
118 LOG(info) <<
"Adding Layer " << layerName <<
" at z = " << z_layer <<
" ; direction = " << direction <<
" ; r_in = " << r_in <<
" ; r_out = " << r_out <<
" x/X0 = " << Layerx2X0;
119 auto& thisLayer = mLayers[0].emplace_back(direction, layerNumber, layerName, z_layer, r_in, r_out, Layerx2X0);
133 std::string configFileName =
"FT3_layout.cfg";
135 LOG(info) <<
"Exporting FT3 Detector layout to " << configFileName;
137 std::ofstream fOut(configFileName.c_str(), std::ios::out);
139 printf(
"Cannot open file\n");
142 fOut <<
"# z_layer r_in r_out Layerx2X0" << std::endl;
143 for (
auto layers_dir : mLayers) {
144 for (
auto layer : layers_dir) {
145 fOut <<
layer.getZ() <<
" " <<
layer.getInnerRadius() <<
" " <<
layer.getOuterRadius() <<
" " <<
layer.getx2X0() << std::endl;
156 LOG(info) <<
"Building FT3 Detector: Conical Telescope";
158 auto z_first =
param.z0;
159 auto z_length =
param.zLength;
160 auto etaIn =
param.etaIn;
161 auto etaOut =
param.etaOut;
162 auto Layerx2X0 =
param.Layerx2X0;
170 for (
int direction : {0, 1}) {
171 for (
int layerNumber = 0; layerNumber <
mNumberOfLayers; layerNumber++) {
173 mLayerName[direction][layerNumber] = layerName;
176 float layerZ = z_first + (layerNumber * z_length / (
mNumberOfLayers - 1)) * std::copysign(1, z_first);
177 float rIn = std::abs(layerZ * std::tan(2.f * std::atan(std::exp(-etaIn))));
178 float rOut = std::abs(layerZ * std::tan(2.f * std::atan(std::exp(-etaOut))));
179 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName, layerZ, rIn, rOut, Layerx2X0);
190 LOG(info) <<
"Building FT3 Detector: V1";
193 float sensorThickness = 30.e-4;
194 float layersx2X0 = 1.e-2;
195 std::vector<std::array<float, 5>> layersConfig{
196 {26., .5, 3., 0.1f * layersx2X0},
197 {30., .5, 3., 0.1f * layersx2X0},
198 {34., .5, 3., 0.1f * layersx2X0},
199 {77., 3.5, 35., layersx2X0},
200 {100., 3.5, 35., layersx2X0},
201 {122., 3.5, 35., layersx2X0},
202 {150., 3.5, 80.f, layersx2X0},
203 {180., 3.5, 80.f, layersx2X0},
204 {220., 3.5, 80.f, layersx2X0},
205 {279., 3.5, 80.f, layersx2X0}};
213 for (
auto direction : {0, 1}) {
214 for (
int layerNumber = 0; layerNumber <
mNumberOfLayers; layerNumber++) {
217 mLayerName[direction][layerNumber] = layerName;
218 auto&
z = layersConfig[layerNumber][0];
220 auto& rIn = layersConfig[layerNumber][1];
221 auto& rOut = layersConfig[layerNumber][2];
222 auto&
x0 = layersConfig[layerNumber][3];
224 LOG(info) <<
"Adding Layer " << layerName <<
" at z = " <<
z;
226 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName,
z, rIn, rOut,
x0);
237 LOG(info) <<
"Building FT3 Detector: V3b";
240 float sensorThickness = 30.e-4;
241 float layersx2X0 = 1.e-2;
242 std::vector<std::array<float, 5>> layersConfig{
243 {26., .5, 3., 0.1f * layersx2X0},
244 {30., .5, 3., 0.1f * layersx2X0},
245 {34., .5, 3., 0.1f * layersx2X0},
246 {77., 5.0, 35., layersx2X0},
247 {100., 5.0, 35., layersx2X0},
248 {122., 5.0, 35., layersx2X0},
249 {150., 5.5, 80.f, layersx2X0},
250 {180., 6.6, 80.f, layersx2X0},
251 {220., 8.1, 80.f, layersx2X0},
252 {279., 10.2, 80.f, layersx2X0},
253 {340., 12.5, 80.f, layersx2X0},
254 {400., 14.7, 80.f, layersx2X0}};
262 for (
auto direction : {0, 1}) {
263 for (
int layerNumber = 0; layerNumber <
mNumberOfLayers; layerNumber++) {
266 mLayerName[direction][layerNumber] = layerName;
267 auto&
z = layersConfig[layerNumber][0];
269 auto& rIn = layersConfig[layerNumber][1];
270 auto& rOut = layersConfig[layerNumber][2];
271 auto&
x0 = layersConfig[layerNumber][3];
273 LOG(info) <<
"Adding Layer " << layerName <<
" at z = " <<
z;
275 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName,
z, rIn, rOut,
x0);
288 LOG(info) <<
"Building FT3 Detector: After Upgrade Days March 2024 version";
291 float sensorThickness = 30.e-4;
292 float layersx2X0 = 1.e-2;
293 std::vector<std::array<float, 5>> layersConfigCSide{
294 {26., .5, 2.5, 0.1f * layersx2X0},
295 {30., .5, 2.5, 0.1f * layersx2X0},
296 {34., .5, 2.5, 0.1f * layersx2X0},
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 {26., .5, 2.5, 0.1f * layersx2X0},
309 {30., .5, 2.5, 0.1f * layersx2X0},
310 {34., .5, 2.5, 0.1f * layersx2X0},
311 {77., 5.0, 35., layersx2X0},
312 {100., 5.0, 35., layersx2X0},
313 {122., 5.0, 35., layersx2X0},
314 {150., 5.0, 68.f, layersx2X0},
315 {180., 5.0, 68.f, layersx2X0},
316 {220., 5.0, 68.f, layersx2X0},
317 {260., 5.0, 68.f, layersx2X0},
318 {300., 5.0, 68.f, layersx2X0},
319 {350., 5.0, 68.f, layersx2X0}};
327 for (
auto direction : {0, 1}) {
328 for (
int layerNumber = 0; layerNumber <
mNumberOfLayers; layerNumber++) {
331 mLayerName[direction][layerNumber] = layerName;
332 float z, rIn, rOut,
x0;
333 if (direction == 0) {
334 z = layersConfigCSide[layerNumber][0];
335 rIn = layersConfigCSide[layerNumber][1];
336 rOut = layersConfigCSide[layerNumber][2];
337 x0 = layersConfigCSide[layerNumber][3];
338 }
else if (direction == 1) {
339 z = layersConfigASide[layerNumber][0];
340 rIn = layersConfigASide[layerNumber][1];
341 rOut = layersConfigASide[layerNumber][2];
342 x0 = layersConfigASide[layerNumber][3];
345 LOG(info) <<
"Adding Layer " << layerName <<
" at z = " <<
z;
347 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName,
z, rIn, rOut,
x0);
357 LOG(info) <<
"Building FT3 Detector: Scoping document version";
360 float sensorThickness = 30.e-4;
361 float layersx2X0 = 1.e-2;
362 std::vector<std::array<float, 5>> layersConfig{
363 {26., .5, 2.5, 0.1f * layersx2X0},
364 {30., .5, 2.5, 0.1f * layersx2X0},
365 {34., .5, 2.5, 0.1f * layersx2X0},
366 {77., 5.0, 35., layersx2X0},
367 {100., 5.0, 35., layersx2X0},
368 {122., 5.0, 35., layersx2X0},
369 {150., 5.0, 68.f, layersx2X0},
370 {180., 5.0, 68.f, layersx2X0},
371 {220., 5.0, 68.f, layersx2X0},
372 {260., 5.0, 68.f, layersx2X0},
373 {300., 5.0, 68.f, layersx2X0},
374 {350., 5.0, 68.f, layersx2X0}};
382 for (
auto direction : {0, 1}) {
383 for (
int layerNumber = 0; layerNumber <
mNumberOfLayers; layerNumber++) {
386 mLayerName[direction][layerNumber] = layerName;
387 auto&
z = layersConfig[layerNumber][0];
389 auto& rIn = layersConfig[layerNumber][1];
390 auto& rOut = layersConfig[layerNumber][2];
391 auto&
x0 = layersConfig[layerNumber][3];
393 LOG(info) <<
"Adding Layer " << layerName <<
" at z = " <<
z;
395 auto& thisLayer = mLayers[direction].emplace_back(direction, layerNumber, layerName,
z, rIn, rOut,
x0);
408 auto& ft3BaseParam = FT3BaseParam::Instance();
410 if (ft3BaseParam.configFile !=
"") {
411 LOG(info) <<
"FT3 Geometry configuration file provided. Overriding FT3Base.geoModel configuration.";
412 buildFT3FromFile(ft3BaseParam.configFile);
415 switch (ft3BaseParam.geoModel) {
417 buildFT3NewVacuumVessel();
420 buildBasicFT3(ft3BaseParam);
423 LOG(fatal) <<
"Invalid Geometry.\n";
438 mLayerID = rhs.mLayerID;
439 mLayerName = rhs.mLayerName;
440 mNumberOfLayers = rhs.mNumberOfLayers;
471 mLayerID = rhs.mLayerID;
472 mLayerName = rhs.mLayerName;
473 mNumberOfLayers = rhs.mNumberOfLayers;
474 mLayers = rhs.mLayers;
475 mTrackData = rhs.mTrackData;
487 LOG(info) <<
"Initialize FT3 O2Detector";
491 defineSensitiveVolumes();
498 if (!(fMC->TrackCharge())) {
502 int lay = 0, volID = vol->getMCid();
503 while ((lay <= mLayerID.size()) && (volID != mLayerID[lay])) {
509 bool startHit =
false, stopHit =
false;
510 unsigned char status = 0;
511 if (fMC->IsTrackEntering()) {
512 status |= Hit::kTrackEntering;
514 if (fMC->IsTrackInside()) {
515 status |= Hit::kTrackInside;
517 if (fMC->IsTrackExiting()) {
518 status |= Hit::kTrackExiting;
520 if (fMC->IsTrackOut()) {
521 status |= Hit::kTrackOut;
523 if (fMC->IsTrackStop()) {
524 status |= Hit::kTrackStopped;
526 if (fMC->IsTrackAlive()) {
527 status |= Hit::kTrackAlive;
531 if ((status & Hit::kTrackEntering) || (status & Hit::kTrackInside && !mTrackData.mHitStarted)) {
533 }
else if ((status & (Hit::kTrackExiting | Hit::kTrackOut | Hit::kTrackStopped))) {
539 mTrackData.mEnergyLoss += fMC->Edep();
541 if (!(startHit | stopHit)) {
545 mTrackData.mEnergyLoss = 0.;
546 fMC->TrackMomentum(mTrackData.mMomentumStart);
547 fMC->TrackPosition(mTrackData.mPositionStart);
548 mTrackData.mTrkStatusStart = status;
549 mTrackData.mHitStarted =
true;
552 TLorentzVector positionStop;
553 fMC->TrackPosition(positionStop);
557 Hit* p =
addHit(
stack->GetCurrentTrackNumber(), chipindex, mTrackData.mPositionStart.Vect(), positionStop.Vect(),
558 mTrackData.mMomentumStart.Vect(), mTrackData.mMomentumStart.E(), positionStop.T(),
559 mTrackData.mEnergyLoss, mTrackData.mTrkStatusStart, status);
564 stack->addHit(GetDetId());
577 float tmaxfdSi = 0.1;
578 float stemaxSi = 0.0075;
579 float deemaxSi = 0.1;
580 float epsilSi = 1.0E-4;
583 float tmaxfdAir = 0.1;
584 float stemaxAir = .10000E+01;
585 float deemaxAir = 0.1;
586 float epsilAir = 1.0E-4;
587 float stminAir = 0.0;
590 float aAir[4] = {12.0107, 14.0067, 15.9994, 39.948};
591 float zAir[4] = {6., 7., 8., 18.};
592 float wAir[4] = {0.000124, 0.755267, 0.231781, 0.012827};
593 float dAir = 1.20479E-3;
596 o2::base::Detector::Medium(1,
"AIR$", 1, 0, ifield, fieldm, tmaxfdAir, stemaxAir, deemaxAir, epsilAir, stminAir);
599 o2::base::Detector::Medium(3,
"SILICON$", 3, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
612 if (FairRootManager::Instance()) {
613 FairRootManager::Instance()->RegisterAny(
addNameTo(
"Hit").
data(), mHits, kTRUE);
646 TGeoVolume* vALIC = gGeoManager->GetVolume(
"barrel");
648 LOG(fatal) <<
"Could not find the top volume";
651 TGeoVolume* A3IPvac = gGeoManager->GetVolume(
"OUT_PIPEVACUUM");
653 LOG(info) <<
"Running simulation with no beam pipe.";
656 LOG(
debug) <<
"FT3 createGeometry: "
657 << Form(
"gGeoManager name is %s title is %s", gGeoManager->GetName(), gGeoManager->GetTitle());
659 if (mLayers.size() == 2) {
661 for (
int direction : {0, 1}) {
662 std::string directionString = direction ?
"Forward" :
"Backward";
663 LOG(info) <<
"Creating FT3 " << directionString <<
" layers:";
664 for (
int iLayer = 0; iLayer < mLayers[direction].size(); iLayer++) {
665 mLayers[direction][iLayer].createLayer(volFT3);
668 vALIC->AddNode(volFT3, 2,
new TGeoTranslation(0., 30., 0.));
670 for (
int direction : {0, 1}) {
671 std::string directionString = direction ?
"Forward" :
"Backward";
672 LOG(info) <<
"Creating FT3 " << directionString <<
" layers:";
673 for (
int iLayer = 0; iLayer < mLayers[direction].size(); iLayer++) {
675 mLayers[direction][iLayer].createLayer(volIFT3);
677 mLayers[direction][iLayer].createLayer(volFT3);
681 A3IPvac->AddNode(volIFT3, 2,
new TGeoTranslation(0., 0., 0.));
682 vALIC->AddNode(volFT3, 2,
new TGeoTranslation(0., 30., 0.));
685 for (
auto direction : {0, 1}) {
686 std::string directionString = direction ?
"Forward" :
"Backward";
687 LOG(info) <<
"Registering FT3 " << directionString <<
" LayerIDs:";
688 for (
int iLayer = 0; iLayer < mLayers[direction].size(); iLayer++) {
690 mLayerID.push_back(layerID);
691 LOG(info) <<
" " << directionString <<
" layer " << iLayer <<
" LayerID " << layerID;
696 if (mLayers.size() == 1) {
697 LOG(info) <<
"Creating FT3 layers:";
699 for (
int iLayer = 0; iLayer < mLayers[0].size(); iLayer++) {
700 if (std::abs(mLayers[0][iLayer].getZ()) < 25) {
701 mLayers[0][iLayer].createLayer(volIFT3);
703 mLayers[0][iLayer].createLayer(volFT3);
706 A3IPvac->AddNode(volIFT3, 2,
new TGeoTranslation(0., 0., 0.));
707 vALIC->AddNode(volFT3, 2,
new TGeoTranslation(0., 30., 0.));
709 for (
int iLayer = 0; iLayer < mLayers[0].size(); iLayer++) {
710 mLayers[0][iLayer].createLayer(volFT3);
712 vALIC->AddNode(volFT3, 2,
new TGeoTranslation(0., 30., 0.));
714 LOG(info) <<
"Registering FT3 LayerIDs:";
715 for (
int iLayer = 0; iLayer < mLayers[0].size(); iLayer++) {
717 mLayerID.push_back(layerID);
718 LOG(info) <<
" mLayerID[" << iLayer <<
"] = " << layerID;
724void Detector::defineSensitiveVolumes()
726 TGeoManager* geoManager = gGeoManager;
730 LOG(info) <<
"Adding FT3 Sensitive Volumes";
733 if (mLayers.size() == 2) {
734 for (
int direction : {0, 1}) {
735 for (
int iLayer = 0; iLayer < mNumberOfLayers; iLayer++) {
738 LOG(info) <<
"Adding FT3 Sensitive Volume => " <<
v->GetName();
739 AddSensitiveVolume(
v);
744 if (mLayers.size() == 1) {
745 for (
int iLayer = 0; iLayer < mLayers[0].size(); iLayer++) {
748 LOG(info) <<
"Adding FT3 Sensitive Volume => " <<
v->GetName();
749 AddSensitiveVolume(
v);
756 const TVector3& startMom,
double startE,
double endTime,
double eLoss,
unsigned char startStatus,
757 unsigned char endStatus)
759 mHits->emplace_back(trackID, detID, startPos, endPos, startMom, startE, endTime, eLoss, startStatus, endStatus);
760 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)
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 buildFT3FromFile(std::string)
Detector()
Default constructor.
std::vector< Int_t > mLayerID
void buildBasicFT3(const FT3BaseParam ¶m)
void buildFT3NewVacuumVessel()
void exportLayout()
access to geometry details
static const char * getFT3SensorPattern()
static const char * getFT3LayerPattern()
static const char * getFT3VolPattern()
static const char * getFT3InnerVolPattern()
void ConstructGeometry() 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)
void InitializeO2Detector() override
void EndOfEvent() override
bool ProcessHits(FairVolume *v=nullptr) override
static GeometryTGeo * Instance()
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"