Project
Loading...
Searching...
No Matches
Detector.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
12#include <FairVolume.h>
13
14#include <TVirtualMC.h>
15#include <TVirtualMCStack.h>
16#include <TGeoVolume.h>
17
18#include "DetectorsBase/Stack.h"
22
23using o2::itsmft::Hit;
24
25namespace o2
26{
27namespace trk
28{
29float getDetLengthFromEta(const float eta, const float radius)
30{
31 return 2. * (10. + radius * std::cos(2 * std::atan(std::exp(-eta))));
32}
33
35 : o2::base::DetImpl<Detector>("TRK", true),
36 mTrackData(),
37 mHits(o2::utils::createSimVector<o2::itsmft::Hit>())
38{
39}
40
42 : o2::base::DetImpl<Detector>("TRK", true),
43 mTrackData(),
44 mHits(o2::utils::createSimVector<o2::itsmft::Hit>())
45{
46 auto& trkPars = TRKBaseParam::Instance();
47
48 if (trkPars.configFile != "") {
49 configFromFile(trkPars.configFile);
50 } else {
54 }
55
56 LOGP(info, "Summary of TRK configuration:");
57 for (auto& layer : mLayers) {
58 LOGP(info, "Layer: {} name: {} r: {} cm | z: {} cm | thickness: {} cm", layer.getNumber(), layer.getName(), layer.getInnerRadius(), layer.getZ(), layer.getChipThickness());
59 }
60}
61
63{
64 if (mHits) {
66 }
67}
68
74
76{
77
78 // Build TRK detector according to the scoping document
79
80 mLayers.clear();
81
82 LOGP(warning, "Loading Scoping Document configuration for ALICE3 TRK");
83 mLayers.emplace_back(0, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(0)}, 0.5f, 50.f, 100.e-4);
84 mLayers.emplace_back(1, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(1)}, 1.2f, 50.f, 100.e-4);
85 mLayers.emplace_back(2, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(2)}, 2.5f, 50.f, 100.e-4);
86 mLayers.emplace_back(3, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(3)}, 3.78f, 124.f, 100.e-3);
87 mLayers.emplace_back(4, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(4)}, 7.f, 124.f, 100.e-3);
88 mLayers.emplace_back(5, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(5)}, 12.f, 124.f, 100.e-3);
89 mLayers.emplace_back(6, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(6)}, 20.f, 124.f, 100.e-3);
90 mLayers.emplace_back(7, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(7)}, 30.f, 124.f, 100.e-3);
91 mLayers.emplace_back(8, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(8)}, 45.f, 258.f, 100.e-3);
92 mLayers.emplace_back(9, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(9)}, 60.f, 258.f, 100.e-3);
93 mLayers.emplace_back(10, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(10)}, 80.f, 258.f, 100.e-3);
94}
95
97{
98 // Build the TRK detector according to changes proposed during
99 // https://indico.cern.ch/event/1407704/
100 // to adhere to the changes that were presented at the ALICE 3 Upgrade days in March 2024
101 // L3 -> 7 cm, L4 -> 9 cm
102
103 mLayers.clear();
104
105 LOGP(warning, "Loading \"After Upgrade Days March 2024\" configuration for ALICE3 TRK");
106 mLayers.emplace_back(0, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(0)}, 0.5f, 50.f, 100.e-4);
107 mLayers.emplace_back(1, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(1)}, 1.2f, 50.f, 100.e-4);
108 mLayers.emplace_back(2, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(2)}, 2.5f, 50.f, 100.e-4);
109 mLayers.emplace_back(3, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(3)}, 7.f, 124.f, 100.e-3);
110 mLayers.emplace_back(4, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(4)}, 9.f, 124.f, 100.e-3);
111 mLayers.emplace_back(5, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(5)}, 12.f, 124.f, 100.e-3);
112 mLayers.emplace_back(6, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(6)}, 20.f, 124.f, 100.e-3);
113 mLayers.emplace_back(7, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(7)}, 30.f, 124.f, 100.e-3);
114 mLayers.emplace_back(8, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(8)}, 45.f, 258.f, 100.e-3);
115 mLayers.emplace_back(9, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(9)}, 60.f, 258.f, 100.e-3);
116 mLayers.emplace_back(10, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(10)}, 80.f, 258.f, 100.e-3);
117
118 auto& trkPars = TRKBaseParam::Instance();
119
120 // Middle layers
121 mLayers[3].setLayout(trkPars.layoutML);
122 mLayers[4].setLayout(trkPars.layoutML);
123 mLayers[5].setLayout(trkPars.layoutML);
124 mLayers[6].setLayout(trkPars.layoutML);
125
126 // Outer tracker
127 mLayers[7].setLayout(trkPars.layoutOL);
128 mLayers[8].setLayout(trkPars.layoutOL);
129 mLayers[9].setLayout(trkPars.layoutOL);
130 mLayers[10].setLayout(trkPars.layoutOL);
131}
132
133void Detector::configFromFile(std::string fileName)
134{
135 // Override the default geometry if config file provided
136 std::ifstream confFile(fileName);
137 if (!confFile.good()) {
138 LOGP(fatal, "File {} not found, aborting.", fileName);
139 }
140
141 mLayers.clear();
142
143 LOGP(info, "Overriding geometry of ALICE3 TRK using {} file.", fileName);
144
145 std::string line;
146 std::vector<float> tmpBuff;
147 int layerCount{0};
148 while (std::getline(confFile, line)) {
149 if (line[0] == '/') {
150 continue;
151 }
152 tmpBuff.clear();
153 std::stringstream ss(line);
154 float val;
155 std::string substr;
156 while (getline(ss, substr, '\t')) {
157 tmpBuff.push_back(std::stof(substr));
158 }
159 mLayers.emplace_back(layerCount, std::string{GeometryTGeo::getTRKLayerPattern() + std::to_string(layerCount)}, tmpBuff[0], tmpBuff[1], tmpBuff[2]);
160 ++layerCount;
161 }
162}
163
164void Detector::configToFile(std::string fileName)
165{
166 LOGP(info, "Exporting TRK Detector layout to {}", fileName);
167 std::ofstream conFile(fileName.c_str(), std::ios::out);
168 conFile << "/// TRK configuration file: inn_radius z_length lay_thickness" << std::endl;
169 for (auto layer : mLayers) {
170 conFile << layer.getInnerRadius() << "\t" << layer.getZ() << "\t" << layer.getChipThickness() << std::endl;
171 }
172}
173
175{
176 mServices = TRKServices{2.6f, 50.f, 150.e-3};
177}
178
180{
181 int ifield = 2; // ?
182 float fieldm = 10.0; // ?
184
185 float tmaxfdSi = 0.1; // .10000E+01; // Degree
186 float stemaxSi = 0.0075; // .10000E+01; // cm
187 float deemaxSi = 0.1; // 0.30000E-02; // Fraction of particle's energy 0<deemax<=1
188 float epsilSi = 1.0E-4; // .10000E+01;
189 float stminSi = 0.0; // cm "Default value used"
190
191 float tmaxfdAir = 0.1; // .10000E+01; // Degree
192 float stemaxAir = .10000E+01; // cm
193 float deemaxAir = 0.1; // 0.30000E-02; // Fraction of particle's energy 0<deemax<=1
194 float epsilAir = 1.0E-4; // .10000E+01;
195 float stminAir = 0.0; // cm "Default value used"
196
197 float tmaxfdCer = 0.1; // .10000E+01; // Degree
198 float stemaxCer = .10000E+01; // cm
199 float deemaxCer = 0.1; // 0.30000E-02; // Fraction of particle's energy 0<deemax<=1
200 float epsilCer = 1.0E-4; // .10000E+01;
201 float stminCer = 0.0; // cm "Default value used"
202
203 // AIR
204 float aAir[4] = {12.0107, 14.0067, 15.9994, 39.948};
205 float zAir[4] = {6., 7., 8., 18.};
206 float wAir[4] = {0.000124, 0.755267, 0.231781, 0.012827};
207 float dAir = 1.20479E-3;
208
209 // Carbon fiber
210 float aCf[2] = {12.0107, 1.00794};
211 float zCf[2] = {6., 1.};
212
213 o2::base::Detector::Mixture(1, "AIR$", aAir, zAir, dAir, 4, wAir);
214 o2::base::Detector::Medium(1, "AIR$", 1, 0, ifield, fieldm, tmaxfdAir, stemaxAir, deemaxAir, epsilAir, stminAir);
215
216 o2::base::Detector::Material(3, "SILICON$", 0.28086E+02, 0.14000E+02, 0.23300E+01, 0.93600E+01, 0.99900E+03);
217 o2::base::Detector::Medium(3, "SILICON$", 3, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
218}
219
221{
222 TGeoManager* geoManager = gGeoManager;
223 TGeoVolume* vALIC = geoManager->GetVolume("barrel");
224 if (!vALIC) {
225 LOGP(fatal, "Could not find barrel volume while constructing TRK geometry");
226 }
227 new TGeoVolumeAssembly(GeometryTGeo::getTRKVolPattern());
228 TGeoVolume* vTRK = geoManager->GetVolume(GeometryTGeo::getTRKVolPattern());
229 vALIC->AddNode(vTRK, 2, new TGeoTranslation(0, 30., 0));
230
231 char vstrng[100] = "TRKVol";
232 vTRK->SetTitle(vstrng);
233
234 for (auto& layer : mLayers) {
235 layer.createLayer(vTRK);
236 }
237
238 // Add service for inner tracker
239 mServices.createServices(vTRK);
240}
241
243{
244 LOG(info) << "Initialize TRK O2Detector";
245 mGeometryTGeo = GeometryTGeo::Instance();
246 defineSensitiveVolumes();
247}
248
249void Detector::defineSensitiveVolumes()
250{
251 TGeoManager* geoManager = gGeoManager;
252 TGeoVolume* v;
253
254 TString volumeName;
255 LOGP(info, "Adding TRK Sensitive Volumes");
256
257 // The names of the TRK sensitive volumes have the format: TRKLayer(0...mLayers.size()-1)
258 for (int j{0}; j < mLayers.size(); j++) {
259 volumeName = GeometryTGeo::getTRKSensorPattern() + TString::Itoa(j, 10);
260 LOGP(info, "Trying {}", volumeName.Data());
261 v = geoManager->GetVolume(volumeName.Data());
262 LOGP(info, "Adding TRK Sensitive Volume {}", v->GetName());
263 AddSensitiveVolume(v);
264 }
265}
266
268
270{
271 // This will create a branch in the output tree called Hit, setting the last
272 // parameter to kFALSE means that this collection will not be written to the file,
273 // it will exist only during the simulation
274
275 if (FairRootManager::Instance()) {
276 FairRootManager::Instance()->RegisterAny(addNameTo("Hit").data(), mHits, true);
277 }
278}
279
281{
282 if (!o2::utils::ShmManager::Instance().isOperational()) {
283 mHits->clear();
284 }
285}
286
287bool Detector::ProcessHits(FairVolume* vol)
288{
289 // This method is called from the MC stepping
290 if (!(fMC->TrackCharge())) {
291 return false;
292 }
293
294 int lay = vol->getVolumeId();
295 int volID = vol->getMCid();
296
297 // Is it needed to keep a track reference when the outer ITS volume is encountered?
298 auto stack = (o2::data::Stack*)fMC->GetStack();
299 if (fMC->IsTrackExiting() && (lay == 0 || lay == mLayers.size() - 1)) {
300 // Keep the track refs for the innermost and outermost layers only
301 o2::TrackReference tr(*fMC, GetDetId());
302 tr.setTrackID(stack->GetCurrentTrackNumber());
303 tr.setUserId(lay);
304 stack->addTrackReference(tr);
305 }
306 bool startHit = false, stopHit = false;
307 unsigned char status = 0;
308 if (fMC->IsTrackEntering()) {
309 status |= Hit::kTrackEntering;
310 }
311 if (fMC->IsTrackInside()) {
312 status |= Hit::kTrackInside;
313 }
314 if (fMC->IsTrackExiting()) {
315 status |= Hit::kTrackExiting;
316 }
317 if (fMC->IsTrackOut()) {
318 status |= Hit::kTrackOut;
319 }
320 if (fMC->IsTrackStop()) {
321 status |= Hit::kTrackStopped;
322 }
323 if (fMC->IsTrackAlive()) {
324 status |= Hit::kTrackAlive;
325 }
326
327 // track is entering or created in the volume
328 if ((status & Hit::kTrackEntering) || (status & Hit::kTrackInside && !mTrackData.mHitStarted)) {
329 startHit = true;
330 } else if ((status & (Hit::kTrackExiting | Hit::kTrackOut | Hit::kTrackStopped))) {
331 stopHit = true;
332 }
333
334 // increment energy loss at all steps except entrance
335 if (!startHit) {
336 mTrackData.mEnergyLoss += fMC->Edep();
337 }
338 if (!(startHit | stopHit)) {
339 return false; // do noting
340 }
341
342 if (startHit) {
343 mTrackData.mEnergyLoss = 0.;
344 fMC->TrackMomentum(mTrackData.mMomentumStart);
345 fMC->TrackPosition(mTrackData.mPositionStart);
346 mTrackData.mTrkStatusStart = status;
347 mTrackData.mHitStarted = true;
348 }
349 if (stopHit) {
350 TLorentzVector positionStop;
351 fMC->TrackPosition(positionStop);
352 // Retrieve the indices with the volume path
353 int stave(0), halfstave(0), chipinmodule(0), module;
354 fMC->CurrentVolOffID(1, chipinmodule);
355 fMC->CurrentVolOffID(2, module);
356 fMC->CurrentVolOffID(3, halfstave);
357 fMC->CurrentVolOffID(4, stave);
358
359 Hit* p = addHit(stack->GetCurrentTrackNumber(), lay, mTrackData.mPositionStart.Vect(), positionStop.Vect(),
360 mTrackData.mMomentumStart.Vect(), mTrackData.mMomentumStart.E(), positionStop.T(),
361 mTrackData.mEnergyLoss, mTrackData.mTrkStatusStart, status);
362 // p->SetTotalEnergy(vmc->Etot());
363
364 // RS: not sure this is needed
365 // Increment number of Detector det points in TParticle
366 stack->addHit(GetDetId());
367 }
368
369 return true;
370}
371
372o2::itsmft::Hit* Detector::addHit(int trackID, int detID, const TVector3& startPos, const TVector3& endPos,
373 const TVector3& startMom, double startE, double endTime, double eLoss, unsigned char startStatus,
374 unsigned char endStatus)
375{
376 mHits->emplace_back(trackID, detID, startPos, endPos, startMom, startE, endTime, eLoss, startStatus, endStatus);
377 return &(mHits->back());
378}
379} // namespace trk
380} // namespace o2
381
383
384// Define Factory method for calling from the outside
385extern "C" {
390}
Definition of the Stack class.
Definition of the ITSMFT Hit class.
uint32_t j
Definition RawData.h:0
uint32_t stack
Definition RawData.h:1
ClassImp(o2::trk::Detector)
o2::base::Detector * create_detector_trk(bool active)
Definition Detector.cxx:386
void setUserId(Int_t userId)
void setTrackID(Int_t track)
void Mixture(Int_t imat, const char *name, Float_t *a, Float_t *z, Float_t dens, Int_t nlmat, Float_t *wmat)
Definition Detector.cxx:66
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)
Definition Detector.cxx:72
static void initFieldTrackingParams(int &mode, float &maxfield)
Definition Detector.cxx:143
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)
Definition Detector.cxx:59
std::string addNameTo(const char *ext) const
Definition Detector.h:150
void Reset() override
Definition Detector.cxx:280
void Register() override
Definition Detector.cxx:269
void ConstructGeometry() override
Definition Detector.cxx:69
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)
Definition Detector.cxx:372
void InitializeO2Detector() override
Definition Detector.cxx:242
void configFromFile(std::string fileName="alice3_TRK_layout.txt")
Definition Detector.cxx:133
void EndOfEvent() override
Definition Detector.cxx:267
static o2::base::Detector * create(bool active)
Definition Detector.h:38
void configToFile(std::string fileName="alice3_TRK_layout.txt")
Definition Detector.cxx:164
void buildTRKNewVacuumVessel()
Definition Detector.cxx:96
bool ProcessHits(FairVolume *v=nullptr) override
Definition Detector.cxx:287
static const char * getTRKSensorPattern()
static GeometryTGeo * Instance()
static const char * getTRKLayerPattern()
static const char * getTRKVolPattern()
void createServices(TGeoVolume *motherVolume)
static ShmManager & Instance()
Definition ShmManager.h:61
const GLdouble * v
Definition glcorearb.h:832
GLboolean * data
Definition glcorearb.h:298
GLuint GLfloat * val
Definition glcorearb.h:1582
GLenum GLuint GLint GLint layer
Definition glcorearb.h:1310
float getDetLengthFromEta(const float eta, const float radius)
Definition Detector.cxx:29
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)
Definition common.h:52
Common utility functions.
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"