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
23namespace o2
24{
25namespace iotof
26{
27
29 : o2::base::DetImpl<Detector>("TF3", true),
30 mTrackData(),
31 mHits(o2::utils::createSimVector<o2::itsmft::Hit>())
32{
33}
34
36 : o2::base::DetImpl<Detector>("TF3", true),
37 mTrackData(),
38 mHits(o2::utils::createSimVector<o2::itsmft::Hit>())
39{
40 auto& iotofPars = IOTOFBaseParam::Instance();
41 configLayers(iotofPars.enableInnerTOF, iotofPars.enableOuterTOF,
42 iotofPars.enableForwardTOF, iotofPars.enableBackwardTOF,
43 iotofPars.detectorPattern,
44 iotofPars.segmentedInnerTOF, iotofPars.segmentedOuterTOF, iotofPars.x2x0);
45}
46
48{
49 if (mHits) {
51 }
52}
53
59
60void Detector::configLayers(bool itof, bool otof, bool ftof, bool btof, std::string pattern, bool itofSegmented, bool otofSegmented,
61 const float x2x0, const float sensorThickness)
62{
63
64 std::pair<float, float> dInnerTof = {21.f, 129.f}; // Radius and length
65 std::pair<float, float> dOuterTof = {92.f, 680.f}; // Radius and length
66 std::pair<float, float> radiusRangeDiskTof = {15.f, 100.f};
67 float zForwardTof = 370.f;
68 LOG(info) << "Configuring IOTOF layers with '" << pattern << "' pattern";
69 if (pattern == "") {
70 LOG(info) << "Default pattern";
71 } else if (pattern == "v3b") {
72 ftof = false;
73 btof = false;
74 } else if (pattern == "v3b1a") {
75 dOuterTof.second = 500.f;
76 zForwardTof = 270.f;
77 radiusRangeDiskTof = {30.f, 100.f};
78 } else if (pattern == "v3b1b") {
79 dOuterTof.second = 500.f;
80 zForwardTof = 200.f;
81 radiusRangeDiskTof = {20.f, 68.f};
82 } else if (pattern == "v3b2a") {
83 dOuterTof.second = 440.f;
84 zForwardTof = 270.f;
85 radiusRangeDiskTof = {30.f, 120.f};
86 } else if (pattern == "v3b2b") {
87 dOuterTof.second = 440.f;
88 zForwardTof = 200.f;
89 radiusRangeDiskTof = {20.f, 68.f};
90 } else if (pattern == "v3b3") {
91 dOuterTof.second = 580.f;
92 zForwardTof = 200.f;
93 radiusRangeDiskTof = {20.f, 68.f};
94 } else if (pattern.rfind("custom/") == 0) { // custom/itof_radius:23/otof_radius:100/
95 if (itofSegmented) {
96 LOG(fatal) << "Custom IOTOF pattern does not support segmented configuration, exiting";
97 }
98 // Handle custom patterns
99 TString patternStr(pattern.c_str());
100 patternStr.ReplaceAll("custom/", ""); // Remove the "custom/" prefix
101 TObjArray* tokens = patternStr.Tokenize("/");
102 for (int i = 0; i < tokens->GetEntries(); ++i) {
103 TString token(tokens->At(i)->GetName());
104 patternStr.ReplaceAll(token, "");
105 if (token.BeginsWith("itof_radius:")) {
106 token.ReplaceAll("itof_radius:", "");
107 dInnerTof.first = token.Atof();
108 LOG(info) << "Custom iTOF radius: " << dInnerTof.first << " cm";
109 } else if (token.BeginsWith("otof_radius:")) {
110 token.ReplaceAll("otof_radius:", "");
111 dOuterTof.first = token.Atof();
112 LOG(info) << "Custom oTOF radius: " << dOuterTof.first << " cm";
113 } else {
114 LOG(fatal) << "Unrecognized token in custom IOTOF pattern: " << token.Data() << ", exiting";
115 }
116 }
117 patternStr.ReplaceAll("/", "");
118 if (!patternStr.IsWhitespace()) {
119 LOG(fatal) << "Unrecognized part in custom IOTOF pattern: " << patternStr.Data() << ", exiting";
120 }
121 } else {
122 LOG(fatal) << "IOTOF layer pattern " << pattern << " not recognized, exiting";
123 }
124 if (itof) { // iTOF
125 const std::string name = GeometryTGeo::getITOFLayerPattern();
126 const int nStaves = itofSegmented ? 24 : 0; // number of staves in segmented case
127 const double staveWidth = itofSegmented ? 5.42 : 0.0; // cm
128 const double staveTiltAngle = itofSegmented ? 3.0 : 0.0; // degrees
129 const int modulesPerStave = itofSegmented ? 10 : 0; // number of modules per stave in segmented case
130 mITOFLayer = ITOFLayer(name,
131 dInnerTof.first, 0.f, dInnerTof.second, 0.f, x2x0, itofSegmented ? ITOFLayer::kBarrelSegmented : ITOFLayer::kBarrel,
132 nStaves, staveWidth, staveTiltAngle, modulesPerStave, itofSegmented ? sensorThickness : 0.0f);
133 }
134 if (otof) { // oTOF
135 const std::string name = GeometryTGeo::getOTOFLayerPattern();
136 const int nStaves = otofSegmented ? 62 : 0; // number of staves in segmented case
137 const double staveWidth = otofSegmented ? 9.74 : 0.0; // cm
138 const double staveTiltAngle = otofSegmented ? 5.0 : 0.0; // degrees
139 const int modulesPerStave = otofSegmented ? 54 : 0; // number of modules per stave in segmented case
140 mOTOFLayer = OTOFLayer(name,
141 dOuterTof.first, 0.f, dOuterTof.second, 0.f, x2x0, otofSegmented ? OTOFLayer::kBarrelSegmented : OTOFLayer::kBarrel,
142 nStaves, staveWidth, staveTiltAngle, modulesPerStave, otofSegmented ? sensorThickness : 0.0f);
143 }
144 if (ftof) {
145 const std::string name = GeometryTGeo::getFTOFLayerPattern();
146 mFTOFLayer = FTOFLayer(name, radiusRangeDiskTof.first, radiusRangeDiskTof.second, 0.f, zForwardTof, x2x0, FTOFLayer::kDisk); // fTOF
147 }
148 if (btof) {
149 const std::string name = GeometryTGeo::getBTOFLayerPattern();
150 mBTOFLayer = BTOFLayer(name, radiusRangeDiskTof.first, radiusRangeDiskTof.second, 0.f, -zForwardTof, x2x0, BTOFLayer::kDisk); // bTOF
151 }
152}
153
157
159{
160 int ifield = 2; // ?
161 float fieldm = 10.0; // ?
163
164 float tmaxfdSi = 0.1; // .10000E+01; // Degree
165 float stemaxSi = 0.0075; // .10000E+01; // cm
166 float deemaxSi = 0.1; // 0.30000E-02; // Fraction of particle's energy 0<deemax<=1
167 float epsilSi = 1.0E-4; // .10000E+01;
168 float stminSi = 0.0; // cm "Default value used"
169
170 float tmaxfdAir = 0.1; // .10000E+01; // Degree
171 float stemaxAir = .10000E+01; // cm
172 float deemaxAir = 0.1; // 0.30000E-02; // Fraction of particle's energy 0<deemax<=1
173 float epsilAir = 1.0E-4; // .10000E+01;
174 float stminAir = 0.0; // cm "Default value used"
175
176 // AIR
177 float aAir[4] = {12.0107, 14.0067, 15.9994, 39.948};
178 float zAir[4] = {6., 7., 8., 18.};
179 float wAir[4] = {0.000124, 0.755267, 0.231781, 0.012827};
180 float dAir = 1.20479E-3;
181
182 o2::base::Detector::Mixture(1, "AIR$", aAir, zAir, dAir, 4, wAir);
183 o2::base::Detector::Medium(1, "AIR$", 1, 0, ifield, fieldm, tmaxfdAir, stemaxAir, deemaxAir, epsilAir, stminAir);
184
185 o2::base::Detector::Material(3, "SILICON$", 0.28086E+02, 0.14000E+02, 0.23300E+01, 0.93600E+01, 0.99900E+03);
186 o2::base::Detector::Medium(3, "SILICON$", 3, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
187}
188
190{
191 TGeoManager* geoManager = gGeoManager;
192 TGeoVolume* vALIC = geoManager->GetVolume("barrel");
193 if (!vALIC) {
194 LOGP(fatal, "Could not find barrel volume while constructing IOTOF geometry");
195 }
196 new TGeoVolumeAssembly(GeometryTGeo::getIOTOFVolPattern());
197 TGeoVolume* vIOTOF = geoManager->GetVolume(GeometryTGeo::getIOTOFVolPattern());
198 vALIC->AddNode(vIOTOF, 2, new TGeoTranslation(0, 30., 0));
199
200 char vstrng[100] = "IOTOFVol";
201 vIOTOF->SetTitle(vstrng);
202
203 auto& iotofPars = IOTOFBaseParam::Instance();
204 if (iotofPars.enableInnerTOF) {
205 mITOFLayer.createLayer(vIOTOF);
206 }
207 if (iotofPars.enableOuterTOF) {
208 mOTOFLayer.createLayer(vIOTOF);
209 }
210 if (iotofPars.enableForwardTOF) {
211 mFTOFLayer.createLayer(vIOTOF);
212 }
213 if (iotofPars.enableBackwardTOF) {
214 mBTOFLayer.createLayer(vIOTOF);
215 }
216}
217
219{
220 LOG(info) << "Initialize IOTOF O2Detector";
221 mGeometryTGeo = GeometryTGeo::Instance();
222 defineSensitiveVolumes();
223}
224
225void Detector::defineSensitiveVolumes()
226{
227 TGeoManager* geoManager = gGeoManager;
228 TGeoVolume* v;
229
230 auto& iotofPars = IOTOFBaseParam::Instance();
231 const bool itof = iotofPars.enableInnerTOF;
232 const bool otof = iotofPars.enableOuterTOF;
233 bool ftof = iotofPars.enableForwardTOF;
234 bool btof = iotofPars.enableBackwardTOF;
235 const std::string pattern = iotofPars.detectorPattern;
236 if (pattern == "") {
237 LOG(info) << "Default pattern";
238 } else if (pattern == "v3b") {
239 ftof = false;
240 btof = false;
241 } else if (pattern == "v3b1a") {
242 } else if (pattern == "v3b1b") {
243 } else if (pattern == "v3b2a") {
244 } else if (pattern == "v3b2b") {
245 } else if (pattern == "v3b3") {
246 } else if (pattern.rfind("custom/") == 0) {
247 } else {
248 LOG(fatal) << "IOTOF layer pattern " << pattern << " not recognized, exiting";
249 }
250
251 // The names of the IOTOF sensitive volumes have the format: IOTOFLayer(0...mLayers.size()-1)
252 if (itof) {
253 for (const std::string& itofSensor : ITOFLayer::mRegister) {
254 v = geoManager->GetVolume(itofSensor.c_str());
255 LOGP(info, "Adding IOTOF Sensitive Volume {}", v->GetName());
256 AddSensitiveVolume(v);
257 }
258 }
259 if (otof) {
260 for (const std::string& otofSensor : OTOFLayer::mRegister) {
261 v = geoManager->GetVolume(otofSensor.c_str());
262 LOGP(info, "Adding IOTOF Sensitive Volume {}", v->GetName());
263 AddSensitiveVolume(v);
264 }
265 }
266 if (ftof) {
267 v = geoManager->GetVolume(GeometryTGeo::getFTOFSensorPattern());
268 LOGP(info, "Adding IOTOF Sensitive Volume {}", v->GetName());
269 AddSensitiveVolume(v);
270 }
271 if (btof) {
272 v = geoManager->GetVolume(GeometryTGeo::getBTOFSensorPattern());
273 LOGP(info, "Adding IOTOF Sensitive Volume {}", v->GetName());
274 AddSensitiveVolume(v);
275 }
276}
277
279
281{
282 // This will create a branch in the output tree called Hit, setting the last
283 // parameter to false means that this collection will not be written to the file,
284 // it will exist only during the simulation
285
286 if (FairRootManager::Instance()) {
287 FairRootManager::Instance()->RegisterAny(addNameTo("Hit").data(), mHits, true);
288 }
289}
290
292{
293 if (!o2::utils::ShmManager::Instance().isOperational()) {
294 mHits->clear();
295 }
296}
297
298bool Detector::ProcessHits(FairVolume* vol)
299{
300 // This method is called from the MC stepping
301 if (!(fMC->TrackCharge())) {
302 return false;
303 }
304
305 int lay = vol->getVolumeId();
306 int volID = vol->getMCid();
307
308 // Is it needed to keep a track reference when the outer volume is encountered?
309 auto stack = (o2::data::Stack*)fMC->GetStack();
310 if (fMC->IsTrackExiting() /*&& (lay == 0 || lay == mLayers.size() - 1)*/) {
311 // Keep the track refs for the innermost and outermost layers only
312 o2::TrackReference tr(*fMC, GetDetId());
313 tr.setTrackID(stack->GetCurrentTrackNumber());
314 tr.setUserId(lay);
315 stack->addTrackReference(tr);
316 }
317 bool startHit = false, stopHit = false;
318 unsigned char status = 0;
319 if (fMC->IsTrackEntering()) {
321 }
322 if (fMC->IsTrackInside()) {
324 }
325 if (fMC->IsTrackExiting()) {
327 }
328 if (fMC->IsTrackOut()) {
330 }
331 if (fMC->IsTrackStop()) {
333 }
334 if (fMC->IsTrackAlive()) {
336 }
337
338 // track is entering or created in the volume
339 if ((status & o2::itsmft::Hit::kTrackEntering) || (status & o2::itsmft::Hit::kTrackInside && !mTrackData.mHitStarted)) {
340 startHit = true;
342 stopHit = true;
343 }
344
345 // increment energy loss at all steps except entrance
346 if (!startHit) {
347 mTrackData.mEnergyLoss += fMC->Edep();
348 }
349 if (!(startHit | stopHit)) {
350 return false; // do noting
351 }
352
353 if (startHit) {
354 mTrackData.mEnergyLoss = 0.;
355 fMC->TrackMomentum(mTrackData.mMomentumStart);
356 fMC->TrackPosition(mTrackData.mPositionStart);
357 mTrackData.mTrkStatusStart = status;
358 mTrackData.mHitStarted = true;
359 }
360 if (stopHit) {
361 TLorentzVector positionStop;
362 fMC->TrackPosition(positionStop);
363 // Retrieve the indices with the volume path
364 int stave(0), chipinmodule(0), module(0);
365 fMC->CurrentVolOffID(1, chipinmodule);
366 fMC->CurrentVolOffID(2, module);
367 fMC->CurrentVolOffID(3, stave);
368
369 int sensorID = lay;
370 auto& iotofPars = IOTOFBaseParam::Instance();
371
372 int layN = -1;
373 if (strstr(vol->GetName(), GeometryTGeo::getITOFSensorPattern()) != nullptr) {
374 layN = 0;
375 } else if (strstr(vol->GetName(), GeometryTGeo::getOTOFSensorPattern())) {
376 layN = 1;
377 }
378 if (iotofPars.segmentedInnerTOF && iotofPars.segmentedOuterTOF) {
379 if (layN > -1) {
380 sensorID = mGeometryTGeo->getIOTOFChipIndex(layN, stave, module, chipinmodule);
381 } else {
382 sensorID += (mGeometryTGeo->getSize() - 1); // temporary as f/b tof is not yet segmented
383 }
384 }
385
386 o2::itsmft::Hit* p = addHit(stack->GetCurrentTrackNumber(), sensorID, mTrackData.mPositionStart.Vect(), positionStop.Vect(),
387 mTrackData.mMomentumStart.Vect(), mTrackData.mMomentumStart.E(), positionStop.T(),
388 mTrackData.mEnergyLoss, mTrackData.mTrkStatusStart, status);
389
390 // RS: not sure this is needed
391 // Increment number of Detector det points in TParticle
392 stack->addHit(GetDetId());
393 }
394
395 return true;
396}
397
398o2::itsmft::Hit* Detector::addHit(int trackID, int detID, const TVector3& startPos, const TVector3& endPos,
399 const TVector3& startMom, double startE, double endTime, double eLoss, unsigned char startStatus,
400 unsigned char endStatus)
401{
402 mHits->emplace_back(trackID, detID, startPos, endPos, startMom, startE, endTime, eLoss, startStatus, endStatus);
403 return &(mHits->back());
404}
405} // namespace iotof
406} // namespace o2
407
Definition of the Stack class.
Definition of the ITSMFT Hit class.
int32_t i
ClassImp(o2::hmpid::Detector)
uint32_t stack
Definition RawData.h:1
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
virtual void createLayer(TGeoVolume *motherVolume) override
Definition Layer.cxx:451
void Reset() override
Definition Detector.cxx:291
void configLayers(bool itof=true, bool otof=true, bool ftof=true, bool btof=true, std::string pattern="", bool itofSegmented=false, bool otofSegmented=false, const float x2x0=0.02f, const float sensorThickness=0.0050f)
Definition Detector.cxx:60
bool ProcessHits(FairVolume *v=nullptr) override
Definition Detector.cxx:298
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:398
void Register() override
Definition Detector.cxx:280
void ConstructGeometry() override
Definition Detector.cxx:54
void InitializeO2Detector() override
Definition Detector.cxx:218
void EndOfEvent() override
Definition Detector.cxx:278
virtual void createLayer(TGeoVolume *motherVolume) override
Definition Layer.cxx:419
static const char * getFTOFLayerPattern()
static const char * getIOTOFVolPattern()
static const char * getOTOFLayerPattern()
static const char * getFTOFSensorPattern()
static const char * getOTOFSensorPattern()
static const char * getITOFSensorPattern()
static const char * getBTOFLayerPattern()
static GeometryTGeo * Instance()
static const char * getITOFLayerPattern()
int getIOTOFChipIndex(int lay, int sta, int mod, int chip) const
static const char * getBTOFSensorPattern()
virtual void createLayer(TGeoVolume *motherVolume) override
Definition Layer.cxx:127
static constexpr int kBarrelSegmented
Definition Layer.h:43
static constexpr int kDisk
Definition Layer.h:42
static constexpr int kBarrel
Definition Layer.h:41
virtual void createLayer(TGeoVolume *motherVolume) override
Definition Layer.cxx:261
@ kTrackStopped
Definition Hit.h:38
@ kTrackInside
Definition Hit.h:35
@ kTrackAlive
Definition Hit.h:39
@ kTrackEntering
Definition Hit.h:34
@ kTrackExiting
Definition Hit.h:36
static ShmManager & Instance()
Definition ShmManager.h:61
const GLdouble * v
Definition glcorearb.h:832
GLuint const GLchar * name
Definition glcorearb.h:781
GLboolean * data
Definition glcorearb.h:298
void freeSimVector(std::vector< T > *ptr)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
Common utility functions.
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::array< uint16_t, 5 > pattern