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