12#include <FairVolume.h>
14#include <TVirtualMC.h>
15#include <TVirtualMCStack.h>
16#include <TGeoVolume.h>
37 return 2. * (10. + radius * std::cos(2 * std::atan(std::exp(-eta))));
41 :
o2::base::DetImpl<Detector>(
"TRK", true),
47Detector::Detector(
bool active)
48 :
o2::base::DetImpl<Detector>(
"TRK", true),
54 if (trkPars.configFile !=
"") {
55 configFromFile(trkPars.configFile);
57 buildTRKMiddleOuterLayers();
62 LOGP(info,
"Summary of TRK configuration:");
63 for (
auto&
layer : mLayers) {
64 LOGP(info,
"Layer: {} name: {} r: {} cm | z: {} cm | thickness: {} cm",
layer.getNumber(),
layer.getName(),
layer.getInnerRadius(),
layer.getZ(),
layer.getChipThickness());
75void Detector::ConstructGeometry()
81void Detector::configDefault()
88 LOGP(warning,
"Loading Scoping Document configuration for ALICE3 TRK");
89 mLayers.emplace_back(0, GeometryTGeo::getTRKLayerPattern() +
std::to_string(0), 3.78f, 10, 100.e-3);
90 mLayers.emplace_back(1, GeometryTGeo::getTRKLayerPattern() +
std::to_string(1), 7.f, 10, 100.e-3);
91 mLayers.emplace_back(2, GeometryTGeo::getTRKLayerPattern() +
std::to_string(2), 12.f, 10, 100.e-3);
92 mLayers.emplace_back(3, GeometryTGeo::getTRKLayerPattern() +
std::to_string(3), 20.f, 10, 100.e-3);
93 mLayers.emplace_back(4, GeometryTGeo::getTRKLayerPattern() +
std::to_string(4), 30.f, 10, 100.e-3);
94 mLayers.emplace_back(5, GeometryTGeo::getTRKLayerPattern() +
std::to_string(5), 45.f, 20, 100.e-3);
95 mLayers.emplace_back(6, GeometryTGeo::getTRKLayerPattern() +
std::to_string(6), 60.f, 20, 100.e-3);
96 mLayers.emplace_back(7, GeometryTGeo::getTRKLayerPattern() +
std::to_string(7), 80.f, 20, 100.e-3);
99void Detector::buildTRKMiddleOuterLayers()
101 auto& trkPars = TRKBaseParam::Instance();
105 switch (trkPars.overallGeom) {
112 LOGP(warning,
"Loading \"After Upgrade Days March 2024\" configuration for ALICE3 TRK");
113 LOGP(warning,
"Building TRK with new vacuum vessel and L3 at 7 cm, L4 at 9 cm, L5 at 12 cm, L6 at 20 cm");
114 mLayers.emplace_back(0, GeometryTGeo::getTRKLayerPattern() +
std::to_string(0), 7.f, 10, 100.e-3);
115 LOGP(info,
"TRKLayer created. Name: {}", GeometryTGeo::getTRKLayerPattern() +
std::to_string(0));
116 mLayers.emplace_back(1, GeometryTGeo::getTRKLayerPattern() +
std::to_string(1), 9.f, 10, 100.e-3);
117 mLayers.emplace_back(2, GeometryTGeo::getTRKLayerPattern() +
std::to_string(2), 12.f, 10, 100.e-3);
118 mLayers.emplace_back(3, GeometryTGeo::getTRKLayerPattern() +
std::to_string(3), 20.f, 10, 100.e-3);
119 mLayers.emplace_back(4, GeometryTGeo::getTRKLayerPattern() +
std::to_string(4), 30.f, 10, 100.e-3);
120 mLayers.emplace_back(5, GeometryTGeo::getTRKLayerPattern() +
std::to_string(5), 45.f, 20, 100.e-3);
121 mLayers.emplace_back(6, GeometryTGeo::getTRKLayerPattern() +
std::to_string(6), 60.f, 20, 100.e-3);
122 mLayers.emplace_back(7, GeometryTGeo::getTRKLayerPattern() +
std::to_string(7), 80.f, 20, 100.e-3);
125 LOGP(warning,
"Loading \"Alternative\" configuration for ALICE3 TRK");
126 LOGP(warning,
"Building TRK with new vacuum vessel and L3 at 7 cm, L4 at 11 cm, L5 at 15 cm, L6 at 19 cm");
127 mLayers.emplace_back(0, GeometryTGeo::getTRKLayerPattern() +
std::to_string(0), 7.f, 10, 100.e-3);
128 LOGP(info,
"TRKLayer created. Name: {}", GeometryTGeo::getTRKLayerPattern() +
std::to_string(0));
129 mLayers.emplace_back(1, GeometryTGeo::getTRKLayerPattern() +
std::to_string(1), 11.f, 10, 100.e-3);
130 mLayers.emplace_back(2, GeometryTGeo::getTRKLayerPattern() +
std::to_string(2), 15.f, 10, 100.e-3);
131 mLayers.emplace_back(3, GeometryTGeo::getTRKLayerPattern() +
std::to_string(3), 19.f, 10, 100.e-3);
132 mLayers.emplace_back(4, GeometryTGeo::getTRKLayerPattern() +
std::to_string(4), 30.f, 10, 100.e-3);
133 mLayers.emplace_back(5, GeometryTGeo::getTRKLayerPattern() +
std::to_string(5), 45.f, 20, 100.e-3);
134 mLayers.emplace_back(6, GeometryTGeo::getTRKLayerPattern() +
std::to_string(6), 60.f, 20, 100.e-3);
135 mLayers.emplace_back(7, GeometryTGeo::getTRKLayerPattern() +
std::to_string(7), 80.f, 20, 100.e-3);
138 LOGP(fatal,
"Unknown option {} for buildTRKMiddleOuterLayers",
static_cast<int>(trkPars.overallGeom));
143 mLayers[0].setLayout(trkPars.layoutML);
144 mLayers[1].setLayout(trkPars.layoutML);
145 mLayers[2].setLayout(trkPars.layoutML);
146 mLayers[3].setLayout(trkPars.layoutML);
149 mLayers[4].setLayout(trkPars.layoutOL);
150 mLayers[5].setLayout(trkPars.layoutOL);
151 mLayers[6].setLayout(trkPars.layoutOL);
152 mLayers[7].setLayout(trkPars.layoutOL);
155void Detector::configFromFile(std::string fileName)
158 std::ifstream confFile(fileName);
159 if (!confFile.good()) {
160 LOGP(fatal,
"File {} not found, aborting.", fileName);
165 LOGP(info,
"Overriding geometry of ALICE3 TRK using {} file.", fileName);
168 std::vector<float> tmpBuff;
170 while (std::getline(confFile, line)) {
171 if (line[0] ==
'/') {
175 std::stringstream ss(line);
178 while (getline(ss, substr,
'\t')) {
179 tmpBuff.push_back(std::stof(substr));
181 mLayers.emplace_back(layerCount, GeometryTGeo::getTRKLayerPattern() +
std::to_string(layerCount), tmpBuff[0], tmpBuff[1], tmpBuff[2]);
186void Detector::configToFile(std::string fileName)
188 LOGP(info,
"Exporting TRK Detector layout to {}", fileName);
189 std::ofstream conFile(fileName.c_str(), std::ios::out);
190 conFile <<
"/// TRK configuration file: inn_radius z_length lay_thickness" << std::endl;
191 for (
auto layer : mLayers) {
192 conFile <<
layer.getInnerRadius() <<
"\t" <<
layer.getZ() <<
"\t" <<
layer.getChipThickness() << std::endl;
196void Detector::configServices()
201void Detector::createMaterials()
207 float tmaxfdSi = 0.1;
208 float stemaxSi = 0.0075;
209 float deemaxSi = 0.1;
210 float epsilSi = 1.0E-4;
213 float tmaxfdAir = 0.1;
214 float stemaxAir = .10000E+01;
215 float deemaxAir = 0.1;
216 float epsilAir = 1.0E-4;
217 float stminAir = 0.0;
219 float tmaxfdCer = 0.1;
220 float stemaxCer = .10000E+01;
221 float deemaxCer = 0.1;
222 float epsilCer = 1.0E-4;
223 float stminCer = 0.0;
226 float aAir[4] = {12.0107, 14.0067, 15.9994, 39.948};
227 float zAir[4] = {6., 7., 8., 18.};
228 float wAir[4] = {0.000124, 0.755267, 0.231781, 0.012827};
229 float dAir = 1.20479E-3;
232 float aCf[2] = {12.0107, 1.00794};
233 float zCf[2] = {6., 1.};
236 o2::base::Detector::Medium(1,
"AIR$", 1, 0, ifield, fieldm, tmaxfdAir, stemaxAir, deemaxAir, epsilAir, stminAir);
239 o2::base::Detector::Medium(3,
"SILICON$", 3, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
242void Detector::createGeometry()
244 TGeoManager* geoManager = gGeoManager;
245 TGeoVolume* vALIC = geoManager->GetVolume(
"barrel");
247 LOGP(fatal,
"Could not find barrel volume while constructing TRK geometry");
249 new TGeoVolumeAssembly(GeometryTGeo::getTRKVolPattern());
250 TGeoVolume* vTRK = geoManager->GetVolume(GeometryTGeo::getTRKVolPattern());
251 vALIC->AddNode(vTRK, 2,
new TGeoTranslation(0, 30., 0));
253 char vstrng[100] =
"TRKVol";
254 vTRK->SetTitle(vstrng);
256 for (
auto&
layer : mLayers) {
257 layer.createLayer(vTRK);
261 mServices.createServices(vTRK);
273 mNumberOfVolumesVD =
static_cast<int>(regs.size());
274 mNumberOfVolumes = mNumberOfVolumesVD + mLayers.size();
275 mSensorName.resize(mNumberOfVolumes);
279 for (
const auto& sensor : regs) {
280 mSensorName[VDvolume] = sensor.name;
285 for (
int i = 0;
i < mLayers.size();
i++) {
286 mSensorName[VDvolume++].Form(
"%s%d", GeometryTGeo::getTRKSensorPattern(),
i);
289 for (
auto vd : mSensorName) {
290 std::cout <<
"Volume name: " << vd << std::endl;
293 mServices.excavateFromVacuum(
"IRIS_CUTOUTsh");
294 mServices.registerVacuum(vTRK);
297void Detector::InitializeO2Detector()
299 LOG(info) <<
"Initialize TRK O2Detector";
300 mGeometryTGeo = GeometryTGeo::Instance();
301 defineSensitiveVolumes();
303 mSensorID.resize(mNumberOfVolumes);
304 for (
int i = 0;
i < mNumberOfVolumes;
i++) {
305 mSensorID[
i] = gMC ? TVirtualMC::GetMC()->VolId(mSensorName[
i]) : 0;
306 LOGP(info,
"{}: mSensorID={}, mSensorName={}",
i, mSensorID[
i], mSensorName[
i].Data());
310void Detector::defineSensitiveVolumes()
312 TGeoManager* geoManager = gGeoManager;
316 LOGP(info,
"Adding TRK Sensitive Volumes");
319 for (
const auto& s :
o2::trk::vdSensorRegistry()) {
320 TGeoVolume*
v = gGeoManager->GetVolume(s.name.c_str());
322 LOGP(warning,
"VD sensor volume '{}' not found", s.name);
325 LOGP(info,
"Adding VD Sensitive Volume {}",
v->GetName());
326 AddSensitiveVolume(
v);
329 mFirstOrLastLayers.push_back(
s.name);
334 for (
int j{0};
j < mLayers.size();
j++) {
335 volumeName = GeometryTGeo::getTRKSensorPattern() + TString::Itoa(
j, 10);
336 if (
j == mLayers.size() - 1) {
337 mFirstOrLastLayers.push_back(volumeName.Data());
339 LOGP(info,
"Trying {}", volumeName.Data());
340 v = geoManager->GetVolume(volumeName.Data());
341 LOGP(info,
"Adding TRK Sensitive Volume {}",
v->GetName());
342 AddSensitiveVolume(
v);
346void Detector::EndOfEvent() { Reset(); }
348void Detector::Register()
354 if (FairRootManager::Instance()) {
355 FairRootManager::Instance()->RegisterAny(addNameTo(
"Hit").
data(), mHits,
true);
359void Detector::Reset()
366bool Detector::InsideFirstOrLastLayer(std::string layerName)
369 for (
auto& firstOrLastLayer : mFirstOrLastLayers) {
370 if (firstOrLastLayer == layerName) {
378bool Detector::ProcessHits(FairVolume* vol)
381 if (!(fMC->TrackCharge())) {
388 int volID = vol->getMCid();
390 bool notSens =
false;
391 while ((volume < mNumberOfVolumes) && (notSens = (volID != mSensorID[volume]))) {
399 if (volume < mNumberOfVolumesVD) {
403 layer = volume - mNumberOfVolumesVD;
409 if (fMC->IsTrackExiting() && InsideFirstOrLastLayer(vol->GetName())) {
412 tr.setTrackID(
stack->GetCurrentTrackNumber());
413 tr.setUserId(volume);
414 stack->addTrackReference(tr);
416 bool startHit =
false, stopHit =
false;
417 unsigned char status = 0;
418 if (fMC->IsTrackEntering()) {
419 status |= Hit::kTrackEntering;
421 if (fMC->IsTrackInside()) {
422 status |= Hit::kTrackInside;
424 if (fMC->IsTrackExiting()) {
425 status |= Hit::kTrackExiting;
427 if (fMC->IsTrackOut()) {
428 status |= Hit::kTrackOut;
430 if (fMC->IsTrackStop()) {
431 status |= Hit::kTrackStopped;
433 if (fMC->IsTrackAlive()) {
434 status |= Hit::kTrackAlive;
438 if ((status & Hit::kTrackEntering) || (status & Hit::kTrackInside && !mTrackData.mHitStarted)) {
440 }
else if ((status & (Hit::kTrackExiting | Hit::kTrackOut | Hit::kTrackStopped))) {
446 mTrackData.mEnergyLoss += fMC->Edep();
448 if (!(startHit | stopHit)) {
453 mTrackData.mEnergyLoss = 0.;
454 fMC->TrackMomentum(mTrackData.mMomentumStart);
455 fMC->TrackPosition(mTrackData.mPositionStart);
456 mTrackData.mTrkStatusStart = status;
457 mTrackData.mHitStarted =
true;
460 TLorentzVector positionStop;
461 fMC->TrackPosition(positionStop);
463 int stave(0), halfstave(0), mod(0), chip(0);
465 fMC->CurrentVolOffID(1, chip);
466 fMC->CurrentVolOffID(2, mod);
467 if (mGeometryTGeo->getNumberOfHalfStaves(
layer) == 2) {
468 fMC->CurrentVolOffID(3, halfstave);
469 fMC->CurrentVolOffID(4, stave);
470 }
else if (mGeometryTGeo->getNumberOfHalfStaves(
layer) == 1) {
471 fMC->CurrentVolOffID(3, stave);
473 LOGP(fatal,
"Wrong number of halfstaves for layer {}",
layer);
477 unsigned short chipID = mGeometryTGeo->getChipIndex(subDetID, volume,
layer, stave, halfstave, mod, chip);
479 Print(vol, volume, subDetID,
layer, stave, halfstave, mod, chip, chipID);
481 mGeometryTGeo->Print();
483 Hit*
p = addHit(
stack->GetCurrentTrackNumber(), chipID, mTrackData.mPositionStart.Vect(), positionStop.Vect(),
484 mTrackData.mMomentumStart.Vect(), mTrackData.mMomentumStart.E(), positionStop.T(),
485 mTrackData.mEnergyLoss, mTrackData.mTrkStatusStart, status);
490 stack->addHit(GetDetId());
496o2::trk::Hit* Detector::addHit(
int trackID,
unsigned short detID,
const TVector3& startPos,
const TVector3& endPos,
497 const TVector3& startMom,
double startE,
double endTime,
double eLoss,
unsigned char startStatus,
498 unsigned char endStatus)
500 mHits->emplace_back(trackID, detID, startPos, endPos, startMom, startE, endTime, eLoss, startStatus, endStatus);
501 return &(mHits->back());
504void Detector::Print(FairVolume* vol,
int volume,
int subDetID,
int layer,
int stave,
int halfstave,
int mod,
int chip,
int chipID)
const
507 LOG(info) <<
"Current volume name: " << fMC->CurrentVolName() <<
" and ID " << fMC->CurrentVolID(currentVol);
508 LOG(info) <<
"volume: " << volume <<
"/" << mNumberOfVolumes - 1;
509 LOG(info) <<
"off volume name 1 " << fMC->CurrentVolOffName(1) <<
" chip: " << chip;
510 LOG(info) <<
"off volume name 2 " << fMC->CurrentVolOffName(2) <<
" module: " << mod;
511 if (subDetID == 1 && mGeometryTGeo->getNumberOfHalfStaves(
layer) == 2) {
512 LOG(info) <<
"off volume name 3 " << fMC->CurrentVolOffName(3) <<
" halfstave: " << halfstave;
513 LOG(info) <<
"off volume name 4 " << fMC->CurrentVolOffName(4) <<
" stave: " << stave;
514 LOG(info) <<
"SubDetector ID: " << subDetID <<
" Layer: " <<
layer <<
" staveinLayer: " << stave <<
" Chip ID: " << chipID;
515 }
else if (subDetID == 1 && mGeometryTGeo->getNumberOfHalfStaves(
layer) == 1) {
516 LOG(info) <<
"off volume name 3 " << fMC->CurrentVolOffName(3) <<
" stave: " << stave;
517 LOG(info) <<
"SubDetector ID: " << subDetID <<
" Layer: " <<
layer <<
" staveinLayer: " << stave <<
" Chip ID: " << chipID;
519 LOG(info) <<
"SubDetector ID: " << subDetID <<
" Chip ID: " << chipID;
Definition of the Stack class.
Definition of the TRK Hit class.
ClassImp(o2::trk::Detector)
o2::base::Detector * create_detector_trk(bool active)
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)
static const TRKBaseParam & Instance()
static o2::base::Detector * create(bool active)
static ShmManager & Instance()
GLenum GLuint GLint GLint layer
void createGeometry(TGeoManager &geom, TGeoVolume &topVolume)
std::vector< VDSensorDesc > & vdSensorRegistry()
float getDetLengthFromEta(const float eta, const float radius)
void createIRIS4Geometry(TGeoVolume *motherVolume)
void clearVDSensorRegistry()
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"