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