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 const 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 {
95 LOG(fatal) << "IOTOF layer pattern " << pattern << " not recognized, exiting";
96 }
97 if (itof) { // iTOF
98 const std::string name = GeometryTGeo::getITOFLayerPattern();
99 const int nStaves = itofSegmented ? 24 : 0; // number of staves in segmented case
100 const double staveWidth = itofSegmented ? 5.42 : 0.0; // cm
101 const double staveTiltAngle = itofSegmented ? 3.0 : 0.0; // degrees
102 const int modulesPerStave = itofSegmented ? 10 : 0; // number of modules per stave in segmented case
103 mITOFLayer = ITOFLayer(name,
104 dInnerTof.first, 0.f, dInnerTof.second, 0.f, x2x0, itofSegmented ? ITOFLayer::kBarrelSegmented : ITOFLayer::kBarrel,
105 nStaves, staveWidth, staveTiltAngle, modulesPerStave, itofSegmented ? sensorThickness : 0.0f);
106 }
107 if (otof) { // oTOF
108 const std::string name = GeometryTGeo::getOTOFLayerPattern();
109 const int nStaves = otofSegmented ? 62 : 0; // number of staves in segmented case
110 const double staveWidth = otofSegmented ? 9.74 : 0.0; // cm
111 const double staveTiltAngle = otofSegmented ? 5.0 : 0.0; // degrees
112 const int modulesPerStave = otofSegmented ? 54 : 0; // number of modules per stave in segmented case
113 mOTOFLayer = OTOFLayer(name,
114 dOuterTof.first, 0.f, dOuterTof.second, 0.f, x2x0, otofSegmented ? OTOFLayer::kBarrelSegmented : OTOFLayer::kBarrel,
115 nStaves, staveWidth, staveTiltAngle, modulesPerStave, otofSegmented ? sensorThickness : 0.0f);
116 }
117 if (ftof) {
118 const std::string name = GeometryTGeo::getFTOFLayerPattern();
119 mFTOFLayer = FTOFLayer(name, radiusRangeDiskTof.first, radiusRangeDiskTof.second, 0.f, zForwardTof, x2x0, FTOFLayer::kDisk); // fTOF
120 }
121 if (btof) {
122 const std::string name = GeometryTGeo::getBTOFLayerPattern();
123 mBTOFLayer = BTOFLayer(name, radiusRangeDiskTof.first, radiusRangeDiskTof.second, 0.f, -zForwardTof, x2x0, BTOFLayer::kDisk); // bTOF
124 }
125}
126
130
132{
133 int ifield = 2; // ?
134 float fieldm = 10.0; // ?
136
137 float tmaxfdSi = 0.1; // .10000E+01; // Degree
138 float stemaxSi = 0.0075; // .10000E+01; // cm
139 float deemaxSi = 0.1; // 0.30000E-02; // Fraction of particle's energy 0<deemax<=1
140 float epsilSi = 1.0E-4; // .10000E+01;
141 float stminSi = 0.0; // cm "Default value used"
142
143 float tmaxfdAir = 0.1; // .10000E+01; // Degree
144 float stemaxAir = .10000E+01; // cm
145 float deemaxAir = 0.1; // 0.30000E-02; // Fraction of particle's energy 0<deemax<=1
146 float epsilAir = 1.0E-4; // .10000E+01;
147 float stminAir = 0.0; // cm "Default value used"
148
149 // AIR
150 float aAir[4] = {12.0107, 14.0067, 15.9994, 39.948};
151 float zAir[4] = {6., 7., 8., 18.};
152 float wAir[4] = {0.000124, 0.755267, 0.231781, 0.012827};
153 float dAir = 1.20479E-3;
154
155 o2::base::Detector::Mixture(1, "AIR$", aAir, zAir, dAir, 4, wAir);
156 o2::base::Detector::Medium(1, "AIR$", 1, 0, ifield, fieldm, tmaxfdAir, stemaxAir, deemaxAir, epsilAir, stminAir);
157
158 o2::base::Detector::Material(3, "SILICON$", 0.28086E+02, 0.14000E+02, 0.23300E+01, 0.93600E+01, 0.99900E+03);
159 o2::base::Detector::Medium(3, "SILICON$", 3, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
160}
161
163{
164 TGeoManager* geoManager = gGeoManager;
165 TGeoVolume* vALIC = geoManager->GetVolume("barrel");
166 if (!vALIC) {
167 LOGP(fatal, "Could not find barrel volume while constructing IOTOF geometry");
168 }
169 new TGeoVolumeAssembly(GeometryTGeo::getIOTOFVolPattern());
170 TGeoVolume* vIOTOF = geoManager->GetVolume(GeometryTGeo::getIOTOFVolPattern());
171 vALIC->AddNode(vIOTOF, 2, new TGeoTranslation(0, 30., 0));
172
173 char vstrng[100] = "IOTOFVol";
174 vIOTOF->SetTitle(vstrng);
175
176 auto& iotofPars = IOTOFBaseParam::Instance();
177 if (iotofPars.enableInnerTOF) {
178 mITOFLayer.createLayer(vIOTOF);
179 }
180 if (iotofPars.enableOuterTOF) {
181 mOTOFLayer.createLayer(vIOTOF);
182 }
183 if (iotofPars.enableForwardTOF) {
184 mFTOFLayer.createLayer(vIOTOF);
185 }
186 if (iotofPars.enableBackwardTOF) {
187 mBTOFLayer.createLayer(vIOTOF);
188 }
189}
190
192{
193 LOG(info) << "Initialize IOTOF O2Detector";
194 mGeometryTGeo = GeometryTGeo::Instance();
195 defineSensitiveVolumes();
196}
197
198void Detector::defineSensitiveVolumes()
199{
200 TGeoManager* geoManager = gGeoManager;
201 TGeoVolume* v;
202
203 auto& iotofPars = IOTOFBaseParam::Instance();
204 const bool itof = iotofPars.enableInnerTOF;
205 const bool otof = iotofPars.enableOuterTOF;
206 bool ftof = iotofPars.enableForwardTOF;
207 bool btof = iotofPars.enableBackwardTOF;
208 const std::string pattern = iotofPars.detectorPattern;
209 if (pattern == "") {
210 LOG(info) << "Default pattern";
211 } else if (pattern == "v3b") {
212 ftof = false;
213 btof = false;
214 } else if (pattern == "v3b1a") {
215 } else if (pattern == "v3b1b") {
216 } else if (pattern == "v3b2a") {
217 } else if (pattern == "v3b2b") {
218 } else if (pattern == "v3b3") {
219 } else {
220 LOG(fatal) << "IOTOF layer pattern " << pattern << " not recognized, exiting";
221 }
222
223 // The names of the IOTOF sensitive volumes have the format: IOTOFLayer(0...mLayers.size()-1)
224 if (itof) {
225 for (const std::string& itofSensor : ITOFLayer::mRegister) {
226 v = geoManager->GetVolume(itofSensor.c_str());
227 LOGP(info, "Adding IOTOF Sensitive Volume {}", v->GetName());
228 AddSensitiveVolume(v);
229 }
230 }
231 if (otof) {
232 for (const std::string& otofSensor : OTOFLayer::mRegister) {
233 v = geoManager->GetVolume(otofSensor.c_str());
234 LOGP(info, "Adding IOTOF Sensitive Volume {}", v->GetName());
235 AddSensitiveVolume(v);
236 }
237 }
238 if (ftof) {
239 v = geoManager->GetVolume(GeometryTGeo::getFTOFSensorPattern());
240 LOGP(info, "Adding IOTOF Sensitive Volume {}", v->GetName());
241 AddSensitiveVolume(v);
242 }
243 if (btof) {
244 v = geoManager->GetVolume(GeometryTGeo::getBTOFSensorPattern());
245 LOGP(info, "Adding IOTOF Sensitive Volume {}", v->GetName());
246 AddSensitiveVolume(v);
247 }
248}
249
251
253{
254 // This will create a branch in the output tree called Hit, setting the last
255 // parameter to false means that this collection will not be written to the file,
256 // it will exist only during the simulation
257
258 if (FairRootManager::Instance()) {
259 FairRootManager::Instance()->RegisterAny(addNameTo("Hit").data(), mHits, true);
260 }
261}
262
264{
265 if (!o2::utils::ShmManager::Instance().isOperational()) {
266 mHits->clear();
267 }
268}
269
270bool Detector::ProcessHits(FairVolume* vol)
271{
272 // This method is called from the MC stepping
273 if (!(fMC->TrackCharge())) {
274 return false;
275 }
276
277 int lay = vol->getVolumeId();
278 int volID = vol->getMCid();
279
280 // Is it needed to keep a track reference when the outer volume is encountered?
281 auto stack = (o2::data::Stack*)fMC->GetStack();
282 if (fMC->IsTrackExiting() /*&& (lay == 0 || lay == mLayers.size() - 1)*/) {
283 // Keep the track refs for the innermost and outermost layers only
284 o2::TrackReference tr(*fMC, GetDetId());
285 tr.setTrackID(stack->GetCurrentTrackNumber());
286 tr.setUserId(lay);
287 stack->addTrackReference(tr);
288 }
289 bool startHit = false, stopHit = false;
290 unsigned char status = 0;
291 if (fMC->IsTrackEntering()) {
293 }
294 if (fMC->IsTrackInside()) {
296 }
297 if (fMC->IsTrackExiting()) {
299 }
300 if (fMC->IsTrackOut()) {
302 }
303 if (fMC->IsTrackStop()) {
305 }
306 if (fMC->IsTrackAlive()) {
308 }
309
310 // track is entering or created in the volume
311 if ((status & o2::itsmft::Hit::kTrackEntering) || (status & o2::itsmft::Hit::kTrackInside && !mTrackData.mHitStarted)) {
312 startHit = true;
314 stopHit = true;
315 }
316
317 // increment energy loss at all steps except entrance
318 if (!startHit) {
319 mTrackData.mEnergyLoss += fMC->Edep();
320 }
321 if (!(startHit | stopHit)) {
322 return false; // do noting
323 }
324
325 if (startHit) {
326 mTrackData.mEnergyLoss = 0.;
327 fMC->TrackMomentum(mTrackData.mMomentumStart);
328 fMC->TrackPosition(mTrackData.mPositionStart);
329 mTrackData.mTrkStatusStart = status;
330 mTrackData.mHitStarted = true;
331 }
332 if (stopHit) {
333 TLorentzVector positionStop;
334 fMC->TrackPosition(positionStop);
335 // Retrieve the indices with the volume path
336 int stave(0), chipinmodule(0), module(0);
337 fMC->CurrentVolOffID(1, chipinmodule);
338 fMC->CurrentVolOffID(2, module);
339 fMC->CurrentVolOffID(3, stave);
340
341 int sensorID = lay;
342 auto& iotofPars = IOTOFBaseParam::Instance();
343
344 int layN = -1;
345 if (strstr(vol->GetName(), GeometryTGeo::getITOFSensorPattern()) != nullptr) {
346 layN = 0;
347 } else if (strstr(vol->GetName(), GeometryTGeo::getOTOFSensorPattern())) {
348 layN = 1;
349 }
350 if (iotofPars.segmentedInnerTOF && iotofPars.segmentedOuterTOF) {
351 if (layN > -1) {
352 sensorID = mGeometryTGeo->getIOTOFChipIndex(layN, stave, module, chipinmodule);
353 } else {
354 sensorID += (mGeometryTGeo->getSize() - 1); // temporary as f/b tof is not yet segmented
355 }
356 }
357
358 o2::itsmft::Hit* p = addHit(stack->GetCurrentTrackNumber(), sensorID, mTrackData.mPositionStart.Vect(), positionStop.Vect(),
359 mTrackData.mMomentumStart.Vect(), mTrackData.mMomentumStart.E(), positionStop.T(),
360 mTrackData.mEnergyLoss, mTrackData.mTrkStatusStart, status);
361
362 // RS: not sure this is needed
363 // Increment number of Detector det points in TParticle
364 stack->addHit(GetDetId());
365 }
366
367 return true;
368}
369
370o2::itsmft::Hit* Detector::addHit(int trackID, int detID, const TVector3& startPos, const TVector3& endPos,
371 const TVector3& startMom, double startE, double endTime, double eLoss, unsigned char startStatus,
372 unsigned char endStatus)
373{
374 mHits->emplace_back(trackID, detID, startPos, endPos, startMom, startE, endTime, eLoss, startStatus, endStatus);
375 return &(mHits->back());
376}
377} // namespace iotof
378} // namespace o2
379
Definition of the Stack class.
Definition of the ITSMFT Hit class.
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:263
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:270
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:370
void Register() override
Definition Detector.cxx:252
void ConstructGeometry() override
Definition Detector.cxx:54
void InitializeO2Detector() override
Definition Detector.cxx:191
void EndOfEvent() override
Definition Detector.cxx:250
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