25#include "FairDetector.h"
26#include <fairlogger/Logger.h>
27#include "FairModule.h"
28#include "FairRootManager.h"
30#include "FairRuntimeDb.h"
31#include "FairVolume.h"
32#include "FairRootManager.h"
34#include "TGeoManager.h"
35#include "TGeoMedium.h"
38#include "TGeoVolume.h"
41#include "TVirtualMC.h"
42#include "TVirtualMCStack.h"
84 mConverterLayers.clear();
87 LOG(info) <<
"Building FCT Detector: From file";
88 LOG(info) <<
" FCT detector configuration: " << configFileName;
89 std::ifstream ifs(configFileName.c_str());
91 LOG(fatal) <<
" Invalid FCTBase.configFile!";
94 float z_layer, r_in, r_out_l_side, Layerx2X0;
96 int layerNumberSquare = 0;
97 int layerNumberDisk = 0;
101 bool r_toggle =
false;
103 while (std::getline(ifs, tempstr)) {
104 if (tempstr[0] ==
'#') {
105 LOG(info) <<
" Comment: " << tempstr;
106 int loc_r_toggle = tempstr.find(
"r_toggle");
107 if (loc_r_toggle != -1) {
109 LOG(info) <<
" Comment: R toggle activated";
113 std::istringstream iss(tempstr);
117 auto pseurap_to_ang = [](
float eta) {
return 2. * TMath::ATan(TMath::Exp(-eta)); };
118 r_in = TMath::Abs(z_layer) * TMath::Tan(pseurap_to_ang(pseumax));
119 r_out_l_side = TMath::Abs(z_layer) * TMath::Tan(pseurap_to_ang(pseumin));
127 mLayerName.push_back(layerName);
128 if (layerType == 0) {
129 LOG(info) <<
"Adding Disk Layer " << layerName <<
" at z = " << z_layer <<
" ; r_in = " << r_in <<
" ; r_out = " << r_out_l_side <<
" x/X0 = " << Layerx2X0;
131 }
else if (layerType == 1) {
132 LOG(info) <<
"Adding Square Layer " << layerName <<
" at z = " << z_layer <<
" ; r_in = " << r_in <<
" ; l_side = " << r_out_l_side <<
" x/X0 = " << Layerx2X0;
134 }
else if (layerType == 2) {
135 LOG(info) <<
"Adding passive converter Layer " << layerName <<
" at z = " << z_layer <<
" ; r_in = " << r_in <<
" ; r_out = " << r_out_l_side <<
" x/X0 = " << Layerx2X0;
138 if (layerType == 0 || layerType == 1) {
139 mLayers.emplace_back(layerNumber, layerName, z_layer, r_in, r_out_l_side, Layerx2X0, layerType);
140 }
else if (layerType == 2) {
141 mConverterLayers.emplace_back(layerNumber, layerName, z_layer, r_in, r_out_l_side, Layerx2X0, layerType);
146 mNumberOfLayers = layerNumber;
147 LOG(info) <<
" Loaded FCT Detector with " << mNumberOfLayers <<
" layers";
148 LOG(info) <<
" Of which " << layerNumberDisk <<
" are disks";
149 LOG(info) <<
" Of which " << layerNumberSquare <<
" are disks";
157 TString configFileName =
"FCT_layout.cfg";
159 LOG(info) <<
"Exporting FCT Detector layout to " << configFileName;
161 std::ofstream fOut(configFileName, std::ios::out);
163 printf(
"Cannot open file\n");
166 fOut <<
"# z_layer r_in r_out_l_side Layerx2X0" << std::endl;
167 for (
auto layer : mLayers) {
168 if (
layer.getType() == 0) {
169 fOut <<
layer.getZ() <<
" " <<
layer.getInnerRadius() <<
" " <<
layer.getOuterRadius() <<
" " <<
layer.getx2X0() << std::endl;
170 }
else if (
layer.getType() == 1) {
171 fOut <<
layer.getZ() <<
" " <<
layer.getInnerRadius() <<
" " <<
layer.getSideLength() <<
" " <<
layer.getx2X0() << std::endl;
182 LOG(info) <<
"Building FCT Detector: Conical Telescope";
184 auto z_first =
param.z0;
185 auto z_length =
param.zLength;
186 auto etaIn =
param.etaIn;
187 auto etaOut =
param.etaOut;
188 auto Layerx2X0 =
param.Layerx2X0;
189 mNumberOfLayers =
param.nLayers;
194 for (Int_t layerNumber = 0; layerNumber < mNumberOfLayers; layerNumber++) {
196 mLayerName.push_back(layerName);
199 Float_t layerZ = z_first + (layerNumber * z_length / (mNumberOfLayers - 1)) * std::copysign(1, z_first);
200 Float_t rIn = std::abs(layerZ * std::tan(2.f * std::atan(std::exp(-etaIn))));
201 Float_t rOut = std::abs(layerZ * std::tan(2.f * std::atan(std::exp(-etaOut))));
202 mLayers.emplace_back(layerNumber, layerName, layerZ, rIn, rOut, Layerx2X0,
type);
211 LOG(info) <<
"Building FCT Detector: V1";
213 mNumberOfLayers = 11;
216 std::vector<std::array<Float_t, 4>> layersConfig{
217 {442.0, 5.0, 17.0, layersx2X0},
218 {444.0, 5.0, 17.0, layersx2X0},
219 {446.0, 5.0, 17.0, layersx2X0},
220 {448.0, 5.0, 17.0, layersx2X0},
221 {450.0, 5.0, 17.0, layersx2X0},
222 {452.0, 5.0, 17.0, layersx2X0},
223 {460.0, 5.0, 17.0, layersx2X0},
224 {470.0, 5.0, 18.0, layersx2X0},
225 {480.0, 5.0, 18.0, layersx2X0},
226 {490.0, 5.0, 19.0, layersx2X0},
227 {500.0, 5.0, 19.0, layersx2X0}};
235 for (
int layerNumber = 0; layerNumber < mNumberOfLayers; layerNumber++) {
237 mLayerName.push_back(layerName);
238 Float_t z = layersConfig[layerNumber][0];
240 Float_t rIn = layersConfig[layerNumber][1];
241 Float_t rOut = layersConfig[layerNumber][2];
242 Float_t x0 = layersConfig[layerNumber][3];
244 LOG(info) <<
"Adding Layer " << layerName <<
" at z = " <<
z;
246 mLayers.emplace_back(layerNumber, layerName,
z, rIn, rOut,
x0,
type);
266 mLayerID = rhs.mLayerID;
267 mLayerName = rhs.mLayerName;
268 mNumberOfLayers = rhs.mNumberOfLayers;
299 mLayerID = rhs.mLayerID;
300 mLayerName = rhs.mLayerName;
301 mNumberOfLayers = rhs.mNumberOfLayers;
302 mLayers = rhs.mLayers;
303 mTrackData = rhs.mTrackData;
315 LOG(info) <<
"Initialize FCT O2Detector";
319 defineSensitiveVolumes();
326 if (!(fMC->TrackCharge())) {
330 Int_t lay = 0, volID = vol->getMCid();
331 while ((lay <= mLayerID.size()) && (volID != mLayerID[lay])) {
337 bool startHit =
false, stopHit =
false;
338 unsigned char status = 0;
339 if (fMC->IsTrackEntering()) {
340 status |= Hit::kTrackEntering;
342 if (fMC->IsTrackInside()) {
343 status |= Hit::kTrackInside;
345 if (fMC->IsTrackExiting()) {
346 status |= Hit::kTrackExiting;
348 if (fMC->IsTrackOut()) {
349 status |= Hit::kTrackOut;
351 if (fMC->IsTrackStop()) {
352 status |= Hit::kTrackStopped;
354 if (fMC->IsTrackAlive()) {
355 status |= Hit::kTrackAlive;
359 if ((status & Hit::kTrackEntering) || (status & Hit::kTrackInside && !mTrackData.mHitStarted)) {
361 }
else if ((status & (Hit::kTrackExiting | Hit::kTrackOut | Hit::kTrackStopped))) {
367 mTrackData.mEnergyLoss += fMC->Edep();
369 if (!(startHit | stopHit)) {
373 mTrackData.mEnergyLoss = 0.;
374 fMC->TrackMomentum(mTrackData.mMomentumStart);
375 fMC->TrackPosition(mTrackData.mPositionStart);
376 mTrackData.mTrkStatusStart = status;
377 mTrackData.mHitStarted =
true;
380 TLorentzVector positionStop;
381 fMC->TrackPosition(positionStop);
385 Hit* p =
addHit(
stack->GetCurrentTrackNumber(), chipindex, mTrackData.mPositionStart.Vect(), positionStop.Vect(),
386 mTrackData.mMomentumStart.Vect(), mTrackData.mMomentumStart.E(), positionStop.T(),
387 mTrackData.mEnergyLoss, mTrackData.mTrkStatusStart, status);
392 stack->addHit(GetDetId());
399void Detector::createMaterials()
412 Float_t stemaxAir = .10000E+01;
424 Float_t aAir[4] = {12.0107, 14.0067, 15.9994, 39.948};
425 Float_t zAir[4] = {6., 7., 8., 18.};
426 Float_t wAir[4] = {0.000124, 0.755267, 0.231781, 0.012827};
430 o2::base::Detector::Medium(1,
"AIR$", 1, 0, ifield, fieldm, tmaxfdAir, stemaxAir, deemaxAir, epsilAir, stminAir);
434 o2::base::Detector::Medium(3,
"SILICON$", 3, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
438 o2::base::Detector::Medium(2,
"LEAD$", 2, 0, ifield, fieldm, tmaxfdPb, stemaxPb, deemaxPb, epsilPb, stminPb);
451 if (FairRootManager::Instance()) {
452 FairRootManager::Instance()->RegisterAny(
addNameTo(
"Hit").
data(), mHits, kTRUE);
471 if (fctBaseParam.configFile !=
"") {
472 LOG(info) <<
"FCT Geometry configuration file provided. Overriding FCTBase.geoModel configuration.";
475 switch (fctBaseParam.geoModel) {
483 LOG(fatal) <<
"Invalid Geometry.\n";
498void Detector::createGeometry()
508 TGeoVolume* vALIC = gGeoManager->GetVolume(
"barrel");
510 LOG(fatal) <<
"Could not find the top volume";
513 TGeoVolume* A3IPvac = gGeoManager->GetVolume(
"OUT_PIPEVACUUM");
515 LOG(info) <<
"Running simulation with no beam pipe.";
518 LOG(
debug) <<
"FCT createGeometry: "
519 << Form(
"gGeoManager name is %s title is %s", gGeoManager->GetName(), gGeoManager->GetTitle());
521 LOG(info) <<
"Creating FCT layers:";
523 for (Int_t iLayer = 0; iLayer < mLayers.size(); iLayer++) {
524 if (std::abs(mLayers[iLayer].getZ()) < 25) {
525 mLayers[iLayer].createLayer(volIFCT);
527 mLayers[iLayer].createLayer(volFCT);
530 A3IPvac->AddNode(volIFCT, 2,
new TGeoTranslation(0., 0., 0.));
531 vALIC->AddNode(volFCT, 2,
new TGeoTranslation(0., 30., 0.));
533 for (Int_t iLayer = 0; iLayer < mLayers.size(); iLayer++) {
534 mLayers[iLayer].createLayer(volFCT);
536 for (Int_t iLayer = 0; iLayer < mConverterLayers.size(); iLayer++) {
537 mConverterLayers[iLayer].createLayer(volFCT);
539 vALIC->AddNode(volFCT, 2,
new TGeoTranslation(0., 30., 0.));
542 LOG(info) <<
"Registering FCT SensitiveLayerIDs:";
543 for (
int iLayer = 0; iLayer < mLayers.size(); iLayer++) {
545 mLayerID.push_back(layerID);
546 LOG(info) <<
" mLayerID[" << mLayers[iLayer].getLayerNumber() <<
"] = " << layerID;
551void Detector::defineSensitiveVolumes()
553 TGeoManager* geoManager = gGeoManager;
557 LOG(info) <<
"Adding FCT Sensitive Volumes";
560 for (Int_t iLayer = 0; iLayer < mLayers.size(); iLayer++) {
563 LOG(info) <<
"Adding FCT Sensitive Volume => " <<
v->GetName();
564 AddSensitiveVolume(
v);
570 const TVector3& startMom,
double startE,
double endTime,
double eLoss,
unsigned char startStatus,
571 unsigned char endStatus)
573 mHits->emplace_back(trackID, detID, startPos, endPos, startMom, startE, endTime, eLoss, startStatus, endStatus);
574 return &(mHits->back());
Definition of the Stack class.
Definition of the ITSMFT Hit class.
Definition of the FCTLayer 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
static const FCTBaseParam & Instance()
~Detector() override
Default destructor.
void InitializeO2Detector() override
Initialization of the detector is done here.
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 buildBasicFCT(const FCTBaseParam ¶m)
void Register() override
Registers the produced collections in FAIRRootManager.
Bool_t ProcessHits(FairVolume *v=nullptr) override
This method is called for each step during simulation (see FairMCApplication::Stepping())
void buildFCTFromFile(std::string)
void ConstructGeometry() override
Base class to create the detector geometry.
Detector()
Default constructor.
GeometryTGeo * mGeometryTGeo
void Reset() override
Has to be called after each event to reset the containers.
void exportLayout()
access to geometry details
static const char * getFCTVolPattern()
static const char * getFCTInnerVolPattern()
static GeometryTGeo * Instance()
static const char * getFCTLayerPattern()
static const char * getFCTSensorPattern()
static ShmManager & Instance()
GLint GLint GLsizei GLint GLenum GLenum type
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"