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
17
18#include <TGeoManager.h>
19#include <TLorentzVector.h>
20#include <TString.h>
21#include <TVirtualMC.h>
22#include <FairRootManager.h>
23#include <FairVolume.h>
25#include "Framework/Logger.h"
26#include "DetectorsBase/Stack.h"
27#include "FV0Base/Geometry.h"
28
29using namespace o2::fv0;
31
33
35 : o2::base::DetImpl<Detector>("FV0", kTRUE),
36 mHits(o2::utils::createSimVector<o2::fv0::Hit>()),
37 mGeometry(nullptr),
38 mTrackData()
39{
40 // Empty
41}
42
44{
45 if (mHits) {
46 o2::utils::freeSimVector(mHits); // delete mHits;
47 }
48}
49
50Detector::Detector(Bool_t isActive)
51 : o2::base::DetImpl<Detector>("FV0", isActive),
52 mHits(o2::utils::createSimVector<o2::fv0::Hit>()),
53 mGeometry(nullptr),
54 mTrackData()
55{
56 // Empty
57}
58
60{
61 LOG(info) << "FV0: Initializing O2 detector. Adding sensitive volumes.";
62
63 std::string volSensitiveName;
64 for (int i = 0; i < mGeometry->getSensitiveVolumeNames().size(); i++) {
65 volSensitiveName = mGeometry->getSensitiveVolumeNames().at(i);
66 TGeoVolume* volSensitive = gGeoManager->GetVolume(volSensitiveName.c_str());
67 if (!volSensitive) {
68 LOG(fatal) << "FV0: Can't find sensitive volume " << volSensitiveName;
69 } else {
70 AddSensitiveVolume(volSensitive);
71 LOG(info) << "FV0: Sensitive volume added: " << volSensitive->GetName();
72 }
73 }
74}
75
77{
78 // This method is called from the MC stepping
79
80 if (fMC->IsTrackEntering() && !fMC->IsNewTrack() && fMC->TrackCharge() != 0) { // one reference per charged particle, first entry from outside
81 auto o2stack = static_cast<o2::data::Stack*>(fMC->GetStack());
82 if (o2stack->GetCurrentTrackNumber() != mTrackRefLastTrackID) {
83 mTrackRefLastTrackID = o2stack->GetCurrentTrackNumber();
84 o2stack->addTrackReference(o2::TrackReference(*fMC, GetDetId()));
85 }
86 }
87 // Track only charged particles and photons
88 bool isPhotonTrack = false;
89 Int_t particlePdg = fMC->TrackPid();
90 if (particlePdg == 22) { // If particle is standard PDG photon
91 isPhotonTrack = true;
92 }
93 if (!(isPhotonTrack || fMC->TrackCharge())) {
94 return kFALSE;
95 }
96
97 // Check track status to define when hit is started and when it is stopped
98 bool startHit = false, stopHit = false;
99 if ((fMC->IsTrackEntering()) || (fMC->IsTrackInside() && !mTrackData.mHitStarted)) {
100 startHit = true;
101 } else if ((fMC->IsTrackExiting() || fMC->IsTrackOut() || fMC->IsTrackStop())) {
102 stopHit = true;
103 }
104
105 // Increment energy loss at all steps except entrance
106 if (!startHit) {
107 mTrackData.mEnergyLoss += fMC->Edep();
108 }
109
110 // Track is entering or created in the volume
111 // Start registering new hit, defined as the combination of all the steps from a given particle
112 if (startHit) {
113 mTrackData.mHitStarted = true;
114 mTrackData.mEnergyLoss = 0.;
115 fMC->TrackMomentum(mTrackData.mMomentumStart);
116 fMC->TrackPosition(mTrackData.mPositionStart);
117 }
118
119 // Track is exiting or stopped within the volume, finalize recording of this hit and save it
120 if (stopHit) {
121 TLorentzVector positionStop;
122 fMC->TrackPosition(positionStop);
123 Int_t trackID = fMC->GetStack()->GetCurrentTrackNumber();
124
125 // Get unique ID of the detector cell (sensitive volume)
126 Int_t cellId = mGeometry->getCurrentCellId(fMC);
127
128 math_utils::Point3D<float> posStart(mTrackData.mPositionStart.X(), mTrackData.mPositionStart.Y(), mTrackData.mPositionStart.Z());
129 math_utils::Point3D<float> posStop(positionStop.X(), positionStop.Y(), positionStop.Z());
130 math_utils::Vector3D<float> momStart(mTrackData.mMomentumStart.Px(), mTrackData.mMomentumStart.Py(), mTrackData.mMomentumStart.Pz());
131 addHit(trackID, cellId, posStart, posStop, momStart,
132 mTrackData.mMomentumStart.E(), positionStop.T(),
133 mTrackData.mEnergyLoss, particlePdg);
134 } else {
135 return kFALSE; // do noting more
136 }
137
138 return kTRUE;
139}
140
142{
143 // This will create a branch in the output tree called Hit, setting the last
144 // parameter to kFALSE means that this collection will not be written to the file,
145 // it will exist only during the simulation
146
148 FairRootManager::Instance()->RegisterAny(addNameTo("Hit").data(), mHits, kTRUE);
149 }
150}
151
153{
154 if (!o2::utils::ShmManager::Instance().isOperational()) {
155 mHits->clear();
156 }
157 mTrackRefLastTrackID = -1;
158}
159
161{
162 Reset();
163}
164
166{
167 LOG(info) << "FV0: Creating materials";
168
169 // Air mixture
170 const Int_t nAir = 4;
171 Float_t aAir[nAir] = {12.0107, 14.0067, 15.9994, 39.948};
172 Float_t zAir[nAir] = {6, 7, 8, 18};
173 Float_t wAir[nAir] = {0.000124, 0.755267, 0.231781, 0.012827};
174 const Float_t dAir = 0.00120479;
175
176 // EJ-204 scintillator, based on polyvinyltoluene
177 const Int_t nScint = 2;
178 Float_t aScint[nScint] = {1.00784, 12.0107};
179 Float_t zScint[nScint] = {1, 6};
180 Float_t wScint[nScint] = {0.07085, 0.92915}; // based on EJ-204 datasheet: n_atoms/cm3
181 const Float_t dScint = 1.023;
182
183 // PMMA plastic mixture: (C5O2H8)n, same for plastic fiber support and for the fiber core
184 // Fiber cladding is different, but it comprises only 3% of the fiber volume, so it is not included
185 const Int_t nPlast = 3;
186 Float_t aPlast[nPlast] = {1.00784, 12.0107, 15.999};
187 Float_t zPlast[nPlast] = {1, 6, 8};
188 Float_t wPlast[nPlast] = {0.08054, 0.59985, 0.31961};
189 const Float_t dPlast = 1.18;
190
191 // Densities of fiber-equivalent material, for five radially-distributed density regions
192 const Int_t nFiberRings = 5;
193 Float_t dFiberRings[nFiberRings] = {0.035631, 0.059611, 0.074765, 0.079451, 0.054490};
194
195 // Densities of fiber-equivalent material, for five density regions in front of the PMTs
196 const Int_t nFiberPMTs = 5;
197 Float_t dFiberPMTs[nFiberPMTs] = {0.109313, 0.217216, 0.364493, 1.373307, 1.406480};
198
199 // Aluminum
200 Float_t aAlu = 26.981;
201 Float_t zAlu = 13;
202 Float_t dAlu = 2.7;
203
204 // Titanium grade 5 (https://en.wikipedia.org/wiki/Titanium_alloy) without iron and oxygen
205 const Int_t nTitanium = 3;
206 Float_t aTitanium[nTitanium] = {47.87, 26.98, 50.94};
207 Float_t zTitanium[nTitanium] = {22, 13, 23};
208 Float_t wTitanium[nTitanium] = {0.9, 0.06, 0.04};
209 const Float_t dTitanium = 4.42;
210
211 // Mixture of elements found in the PMTs
212 const Int_t nPMT = 14;
213 Float_t aPMT[nPMT] = {63.546, 65.38, 28.085, 15.999, 12.011, 1.008, 14.007, 55.845, 51.996, 10.81, 121.76, 132.91, 9.0122, 26.982};
214 Float_t zPMT[nPMT] = {29, 30, 14, 8, 6, 1, 7, 26, 24, 5, 51, 55, 4, 13};
215 Float_t wPMT[nPMT] = {0.07, 0.02, 0.14, 0.21, 0.11, 0.02, 0.02, 0.04, 0.01, 0.01, 0.00, 0.00, 0.01, 0.34};
216 const Float_t dPMT = Geometry::getPmtDensity();
217
218 Int_t matId = 0; // tmp material id number
219 const Int_t unsens = 0, sens = 1; // sensitive or unsensitive medium
220
221 Float_t tmaxfd = -10.0; // max deflection angle due to magnetic field in one step
222 Float_t stemax = 0.1; // max step allowed [cm]
223 Float_t deemax = 1.0; // maximum fractional energy loss in one step 0<deemax<=1
224 Float_t epsil = 0.03; // tracking precision [cm]
225 Float_t stmin = -0.001; // minimum step due to continuous processes [cm] (negative value: choose it automatically)
226
227 Int_t fieldType;
228 Float_t maxField;
230 LOG(info) << "FV0: createMaterials(): fieldType " << fieldType << ", maxField " << maxField;
231
232 // TODO: Comment out two lines below once tested that the above function assigns field type and max correctly
233 fieldType = 2;
234 maxField = 10.;
235
236 o2::base::Detector::Mixture(++matId, "Air$", aAir, zAir, dAir, nAir, wAir);
237 o2::base::Detector::Medium(Air, "Air$", matId, unsens, fieldType, maxField,
238 tmaxfd, stemax, deemax, epsil, stmin);
239
240 o2::base::Detector::Mixture(++matId, "Scintillator$", aScint, zScint, dScint, nScint, wScint);
241 o2::base::Detector::Medium(Scintillator, "Scintillator$", matId, unsens, fieldType, maxField,
242 tmaxfd, stemax, deemax, epsil, stmin);
243
244 o2::base::Detector::Mixture(++matId, "Plastic$", aPlast, zPlast, dPlast, nPlast, wPlast);
245 o2::base::Detector::Medium(Plastic, "Plastic$", matId, unsens, fieldType, maxField,
246 tmaxfd, stemax, deemax, epsil, stmin);
247
248 for (int i = 0; i < nFiberRings; i++) {
249 o2::base::Detector::Mixture(++matId, Form("FiberRing%i$", i + 1), aPlast, zPlast, dFiberRings[i], nPlast, wPlast);
250 o2::base::Detector::Medium(FiberRing1 + i, Form("FiberRing%i$", i + 1), matId, unsens, fieldType, maxField,
251 tmaxfd, stemax, deemax, epsil, stmin);
252 }
253
254 for (int i = 0; i < nFiberPMTs; i++) {
255 o2::base::Detector::Mixture(++matId, Form("FiberPMT%i$", i + 1), aPlast, zPlast, dFiberPMTs[i], nPlast, wPlast);
256 o2::base::Detector::Medium(FiberPMT1 + i, Form("FiberPMT%i$", i + 1), matId, unsens, fieldType, maxField,
257 tmaxfd, stemax, deemax, epsil, stmin);
258 }
259
260 o2::base::Detector::Material(++matId, "Aluminium$", aAlu, zAlu, dAlu, 8.9, 999);
261 o2::base::Detector::Medium(Aluminium, "Aluminium$", matId, unsens, fieldType, maxField,
262 tmaxfd, stemax, deemax, epsil, stmin);
263
264 o2::base::Detector::Mixture(++matId, "Titanium$", aTitanium, zTitanium, dTitanium, nTitanium, wTitanium);
265 o2::base::Detector::Medium(Titanium, "Titanium$", matId, unsens, fieldType, maxField,
266 tmaxfd, stemax, deemax, epsil, stmin);
267
268 o2::base::Detector::Mixture(++matId, "PMT$", aPMT, zPMT, dPMT, nPMT, wPMT);
269 o2::base::Detector::Medium(PMT, "PMT$", matId, unsens, fieldType, maxField,
270 tmaxfd, stemax, deemax, epsil, stmin);
271
272 LOG(debug) << "FV0 Detector::createMaterials(): matId = " << matId;
273}
274
276{
277 LOG(info) << "FV0: Constructing geometry";
280 // mGeometry->enableComponent(Geometry::eScintillator, false);
281 // mGeometry->enableComponent(Geometry::ePlastics, false);
282 // mGeometry->enableComponent(Geometry::eFibers, false);
283 // mGeometry->enableComponent(Geometry::eScrews, false);
284 // mGeometry->enableComponent(Geometry::eRods, false);
285 // mGeometry->enableComponent(Geometry::eAluminiumContainer, false);
286 mGeometry->buildGeometry();
287}
288
290{
291 //
292 // Creates entries for alignable volumes associating the symbolic volume
293 // name with the corresponding volume path.
294 //
295 // First version (mainly ported from AliRoot)
296 //
297
298 LOG(info) << "FV0: Add alignable volumes";
299
300 if (!gGeoManager) {
301 LOG(fatal) << "TGeoManager doesn't exist!";
302 return;
303 }
304
305 auto addAlignabelVolume = [](const std::string& volPath, const std::string& symName) -> void {
306 LOG(info) << "FV0: Add alignable volume: " << symName << " <-> " << volPath;
307 if (!gGeoManager->SetAlignableEntry(symName.c_str(), volPath.c_str())) {
308 LOG(fatal) << "FV0: Unable to set alignable entry! " << symName << " <-> " << volPath;
309 }
310 };
311
312 addAlignabelVolume("/cave_1/barrel_1/FV0_1/FV0RIGHT_0", Geometry::getDetectorRightSymName());
313 addAlignabelVolume("/cave_1/barrel_1/FV0_1/FV0LEFT_1", Geometry::getDetectorLeftSymName());
314}
315
316o2::fv0::Hit* Detector::addHit(Int_t trackId, Int_t cellId,
317 const math_utils::Point3D<float>& startPos, const math_utils::Point3D<float>& endPos,
318 const math_utils::Vector3D<float>& startMom, double startE,
319 double endTime, double eLoss, Int_t particlePdg)
320{
321 mHits->emplace_back(trackId, cellId, startPos, endPos, startMom, startE, endTime, eLoss, particlePdg);
322 auto stack = (o2::data::Stack*)fMC->GetStack();
323 stack->addHit(GetDetId());
324 return &(mHits->back());
325}
Definition of the Stack class.
std::ostringstream debug
Base definition of FV0 geometry.
Definition of the FV0 detector class.
ClassImp(Detector)
int32_t i
uint32_t stack
Definition RawData.h:1
Int_t GetDetId()
void AddSensitiveVolume(TGeoVolume *v)
TVirtualMC * fMC
flag for initialisation
Definition FairModule.h:160
void RegisterAny(const char *name, T *&obj, Bool_t toFile)
static FairRootManager * Instance()
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
~Detector() override
Default destructor.
Definition Detector.cxx:43
void InitializeO2Detector() override
Initializes the detector (adds sensitive volume)
Definition Detector.cxx:59
void createMaterials()
Registers new materials in o2::base::Detector.
Definition Detector.cxx:165
void EndOfEvent() override
Called at the end of event.
Definition Detector.cxx:160
void Register() override
Registers the produced collections in FAIRRootManager.
Definition Detector.cxx:141
Bool_t ProcessHits(FairVolume *v=nullptr) override
This method is called for each step during simulation (see FairMCApplication::Stepping())
Definition Detector.cxx:76
void ConstructGeometry() override
Creates materials and geometry.
Definition Detector.cxx:275
void addAlignableVolumes() const override
Add alignable volumes.
Definition Detector.cxx:289
Detector()
Default constructor.
Definition Detector.cxx:34
void Reset() override
Has to be called after each event to reset the containers.
Definition Detector.cxx:152
FV0 Geometry.
Definition Geometry.h:51
void buildGeometry() const
Build the geometry.
Definition Geometry.cxx:95
int getCurrentCellId(const TVirtualMC *fMC) const
Definition Geometry.cxx:61
static std::string getDetectorRightSymName()
Definition Geometry.h:136
static std::string getDetectorLeftSymName()
Definition Geometry.h:141
static Geometry * instance(EGeoType initType=eUninitialized)
const std::vector< std::string > & getSensitiveVolumeNames() const
Definition Geometry.h:100
static constexpr float getPmtDensity()
Get the density of the PMTs.
Definition Geometry.h:147
static ShmManager & Instance()
Definition ShmManager.h:62
GLsizeiptr size
Definition glcorearb.h:659
const GLdouble * v
Definition glcorearb.h:832
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"