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
14
15#include "DataFormatsFD3/Hit.h"
19#include "FD3Base/Constants.h"
20
21#include "DetectorsBase/Stack.h"
23#include "Field/MagneticField.h"
24
25// FairRoot includes
26#include "FairDetector.h"
27#include <fairlogger/Logger.h>
28#include "FairRootManager.h"
29#include "FairRun.h"
30#include "FairRuntimeDb.h"
31#include "FairVolume.h"
32#include "FairRootManager.h"
33
34#include "TVirtualMC.h"
35#include "TLorentzVector.h"
36#include "TVector3.h"
37#include <TGeoTube.h>
38#include <TGeoVolume.h>
39#include <TGeoCompositeShape.h>
40#include <TGeoMedium.h>
41#include <TGeoCone.h>
42#include <TGeoManager.h>
43#include "TRandom.h"
44#include <cmath>
45
46class FairModule;
47
48class TGeoMedium;
49
50using namespace o2::fd3;
51using o2::fd3::Hit;
52
54 : o2::base::DetImpl<Detector>("FD3", true),
55 mHits(o2::utils::createSimVector<o2::fd3::Hit>()),
56 mGeometryTGeo(nullptr),
57 mTrackData()
58{
59 mNumberOfRingsC = Constants::nringsC;
60 mNumberOfSectors = Constants::nsect;
61
62 mEtaMinA = Constants::etaMin;
63 mEtaMaxA = Constants::etaMax;
64 mEtaMinC = -Constants::etaMax;
65 mEtaMaxC = -Constants::etaMin;
66
67 auto& baseParam = FD3BaseParam::Instance();
68
69 if (baseParam.withMG) {
70 mNumberOfRingsA = Constants::nringsA_withMG;
72 } else {
73 mNumberOfRingsA = Constants::nringsA;
74 mEtaMinA = Constants::etaMin;
75 }
76
77 mDzScint = baseParam.dzscint / 2;
78 mDzPlate = baseParam.dzplate;
79
80 mPlateBehindA = baseParam.plateBehindA;
81 mFullContainer = baseParam.fullContainer;
82
83 mZA = baseParam.zmodA;
84 mZC = baseParam.zmodC;
85
86 for (int i = 0; i <= mNumberOfRingsA + 1; i++) {
87 float eta = mEtaMaxA - i * (mEtaMaxA - mEtaMinA) / mNumberOfRingsA;
88 float r = ringSize(mZA, eta);
89 mRingSizesA.emplace_back(r);
90 }
91
92 for (int i = 0; i <= mNumberOfRingsC + 1; i++) {
93 float eta = mEtaMinC + i * (mEtaMaxC - mEtaMinC) / mNumberOfRingsC;
94 float r = ringSize(mZC, eta);
95 mRingSizesC.emplace_back(r);
96 }
97}
98
100 : o2::base::DetImpl<Detector>(rhs),
101 mTrackData(),
102 mHits(o2::utils::createSimVector<o2::fd3::Hit>())
103{
104}
105
106Detector& Detector::operator=(const Detector& rhs)
107{
108
109 if (this == &rhs) {
110 return *this;
111 }
112 // base class assignment
114 mTrackData = rhs.mTrackData;
115
116 mHits = nullptr;
117 return *this;
118}
119
121{
122
123 if (mHits) {
125 }
126}
127
129{
130 LOG(info) << "Initialize Forward Detector";
131 mGeometryTGeo = GeometryTGeo::Instance();
132 defineSensitiveVolumes();
133}
134
135bool Detector::ProcessHits(FairVolume* vol)
136{
137 // This method is called from the MC stepping
138 if (!(fMC->TrackCharge())) {
139 return kFALSE;
140 }
141
142 int detId;
143 int volID = fMC->CurrentVolID(detId);
144
145 auto stack = (o2::data::Stack*)fMC->GetStack();
146
147 // Check track status to define when hit is started and when it is stopped
148 int particlePdg = fMC->TrackPid();
149 bool startHit = false, stopHit = false;
150 if ((fMC->IsTrackEntering()) || (fMC->IsTrackInside() && !mTrackData.mHitStarted)) {
151 startHit = true;
152 } else if ((fMC->IsTrackExiting() || fMC->IsTrackOut() || fMC->IsTrackStop())) {
153 stopHit = true;
154 }
155
156 // increment energy loss at all steps except entrance
157 if (!startHit) {
158 mTrackData.mEnergyLoss += fMC->Edep();
159 }
160 if (!(startHit | stopHit)) {
161 return kFALSE; // do noting
162 }
163
164 if (startHit) {
165 mTrackData.mHitStarted = true;
166 mTrackData.mEnergyLoss = 0.;
167 fMC->TrackMomentum(mTrackData.mMomentumStart);
168 fMC->TrackPosition(mTrackData.mPositionStart);
169 mTrackData.mTrkStatusStart = true;
170 }
171
172 if (stopHit) {
173 TLorentzVector positionStop;
174 fMC->TrackPosition(positionStop);
175 int trackId = stack->GetCurrentTrackNumber();
176
177 math_utils::Point3D<float> posStart(mTrackData.mPositionStart.X(), mTrackData.mPositionStart.Y(), mTrackData.mPositionStart.Z());
178 math_utils::Point3D<float> posStop(positionStop.X(), positionStop.Y(), positionStop.Z());
179 math_utils::Vector3D<float> momStart(mTrackData.mMomentumStart.Px(), mTrackData.mMomentumStart.Py(), mTrackData.mMomentumStart.Pz());
180
181 Hit* p = addHit(trackId, detId, posStart, posStop,
182 momStart, mTrackData.mMomentumStart.E(),
183 positionStop.T(), mTrackData.mEnergyLoss, particlePdg);
184 stack->addHit(GetDetId());
185 } else {
186 return false; // do nothing more
187 }
188 return true;
189}
190
191o2::fd3::Hit* Detector::addHit(int trackId, unsigned int detId,
192 const math_utils::Point3D<float>& startPos,
193 const math_utils::Point3D<float>& endPos,
194 const math_utils::Vector3D<float>& startMom,
195 double startE,
196 double endTime,
197 double eLoss,
198 int particlePdg)
199{
200 mHits->emplace_back(trackId, detId, startPos,
201 endPos, startMom, startE, endTime, eLoss, particlePdg);
202 return &(mHits->back());
203}
204
210
212{
213 Reset();
214}
215
217{
218 // This will create a branch in the output tree called Hit, setting the last
219 // parameter to kFALSE means that this collection will not be written to the file,
220 // it will exist only during the simulation
221
222 if (FairRootManager::Instance()) {
223 FairRootManager::Instance()->RegisterAny(addNameTo("Hit").data(), mHits, kTRUE);
224 }
225}
226
228{
229 if (!o2::utils::ShmManager::Instance().isOperational()) {
230 mHits->clear();
231 }
232}
233
235{
236 float density, as[11], zs[11], ws[11];
237 double radLength, absLength, a_ad, z_ad;
238 int id;
239
240 // EJ-204 scintillator, based on polyvinyltoluene
241 const int nScint = 2;
242 float aScint[nScint] = {1.00784, 12.0107};
243 float zScint[nScint] = {1, 6};
244 float wScint[nScint] = {0.07085, 0.92915}; // based on EJ-204 datasheet: n_atoms/cm3
245 const float dScint = 1.023;
246
247 // Aluminium
248 Float_t aAlu = 26.981;
249 Float_t zAlu = 13;
250 Float_t dAlu = 2.7;
251
252 int matId = 0; // tmp material id number
253 const int unsens = 0, sens = 1; // sensitive or unsensitive medium
254 //
255 int fieldType = 3; // Field type
256 float maxField = 5.0; // Field max.
257
258 float tmaxfd3 = -10.0; // max deflection angle due to magnetic field in one step
259 float stemax = 0.1; // max step allowed [cm]
260 float deemax = 1.0; // maximum fractional energy loss in one step 0<deemax<=1
261 float epsil = 0.03; // tracking precision [cm]
262 float stmin = -0.001; // minimum step due to continuous processes [cm] (negative value: choose it automatically)
263
264 LOG(info) << "FD3: CreateMaterials(): fieldType " << fieldType << ", maxField " << maxField;
265
266 o2::base::Detector::Mixture(++matId, "Scintillator", aScint, zScint, dScint, nScint, wScint);
267 o2::base::Detector::Medium(Scintillator, "Scintillator", matId, unsens, fieldType, maxField,
268 tmaxfd3, stemax, deemax, epsil, stmin);
269
270 o2::base::Detector::Material(++matId, "Aluminium", aAlu, zAlu, dAlu, 8.9, 999);
271 o2::base::Detector::Medium(Aluminium, "Aluminium", matId, unsens, fieldType, maxField,
272 tmaxfd3, stemax, deemax, epsil, stmin);
273}
274
276{
277 LOGP(info, "Creating FD3 geometry");
278
279 TGeoVolume* vCave = gGeoManager->GetVolume("cave");
280
281 if (!vCave) {
282 LOG(fatal) << "Could not find the top volume!";
283 }
284
285 TGeoVolumeAssembly* vFD3A = buildModuleA();
286 TGeoVolumeAssembly* vFD3C = buildModuleC();
287
288 vCave->AddNode(vFD3A, 1, new TGeoTranslation(0., 0., mZA));
289 vCave->AddNode(vFD3C, 2, new TGeoTranslation(0., 0., mZC));
290}
291
292TGeoVolumeAssembly* Detector::buildModuleA()
293{
294 TGeoVolumeAssembly* mod = new TGeoVolumeAssembly("FD3A");
295
296 const TGeoMedium* medium = gGeoManager->GetMedium("FD3_Scintillator");
297
298 float dphiDeg = 360. / mNumberOfSectors;
299
300 for (int ir = 0; ir < mNumberOfRingsA; ir++) {
301 std::string rName = "fd3_ring" + std::to_string(ir + 1);
302 TGeoVolumeAssembly* ring = new TGeoVolumeAssembly(rName.c_str());
303 float rmin = mRingSizesA[ir];
304 float rmax = mRingSizesA[ir + 1];
305 LOG(info) << "ring" << ir << ": from " << rmin << " to " << rmax;
306 for (int ic = 0; ic < mNumberOfSectors; ic++) {
307 int cellId = ic + mNumberOfSectors * ir;
308 std::string nodeName = "fd3_node" + std::to_string(cellId);
309 float phimin = dphiDeg * ic;
310 float phimax = dphiDeg * (ic + 1);
311 auto tbs = new TGeoTubeSeg("tbs", rmin, rmax, mDzScint, phimin, phimax);
312 auto nod = new TGeoVolume(nodeName.c_str(), tbs, medium);
313 if ((ir + ic) % 2 == 0) {
314 nod->SetLineColor(kRed);
315 } else {
316 nod->SetLineColor(kRed - 7);
317 }
318 ring->AddNode(nod, cellId);
319 }
320 mod->AddNode(ring, ir + 1);
321 }
322
323 // Aluminium plates on one or both sides of the A side module
324 if (mPlateBehindA || mFullContainer) {
325 LOG(info) << "adding container on A side";
326 auto pmed = (TGeoMedium*)gGeoManager->GetMedium("FD3_Aluminium");
327 auto pvol = new TGeoTube("pvol_fd3a", mRingSizesA[0], mRingSizesA[mNumberOfRingsA], mDzPlate);
328 auto pnod1 = new TGeoVolume("pnod1_FD3A", pvol, pmed);
329 double dpz = 2. + mDzPlate / 2;
330 mod->AddNode(pnod1, 1, new TGeoTranslation(0, 0, dpz));
331
332 if (mFullContainer) {
333 auto pnod2 = new TGeoVolume("pnod2_FD3A", pvol, pmed);
334 mod->AddNode(pnod2, 1, new TGeoTranslation(0, 0, -dpz));
335 }
336 }
337 return mod;
338}
339
340TGeoVolumeAssembly* Detector::buildModuleC()
341{
342 TGeoVolumeAssembly* mod = new TGeoVolumeAssembly("FD3C");
343
344 const TGeoMedium* medium = gGeoManager->GetMedium("FD3_Scintillator");
345
346 float dphiDeg = 360. / mNumberOfSectors;
347
348 for (int ir = 0; ir < mNumberOfRingsC; ir++) {
349 std::string rName = "fd3_ring" + std::to_string(ir + 1 + mNumberOfRingsA);
350 TGeoVolumeAssembly* ring = new TGeoVolumeAssembly(rName.c_str());
351 float rmin = mRingSizesC[ir];
352 float rmax = mRingSizesC[ir + 1];
353 LOG(info) << "ring" << ir + mNumberOfRingsA << ": from " << rmin << " to " << rmax;
354 for (int ic = 0; ic < mNumberOfSectors; ic++) {
355 int cellId = ic + mNumberOfSectors * (ir + mNumberOfRingsA);
356 std::string nodeName = "fd3_node" + std::to_string(cellId);
357 float phimin = dphiDeg * ic;
358 float phimax = dphiDeg * (ic + 1);
359 auto tbs = new TGeoTubeSeg("tbs", rmin, rmax, mDzScint, phimin, phimax);
360 auto nod = new TGeoVolume(nodeName.c_str(), tbs, medium);
361 if ((ir + ic) % 2 == 0) {
362 nod->SetLineColor(kBlue);
363 } else {
364 nod->SetLineColor(kBlue - 7);
365 }
366 ring->AddNode(nod, cellId);
367 }
368 mod->AddNode(ring, ir + 1);
369 }
370
371 // Aluminium plates on both sides of the C side module
372 if (mFullContainer) {
373 LOG(info) << "adding container on C side";
374 auto pmed = (TGeoMedium*)gGeoManager->GetMedium("FD3_Aluminium");
375 auto pvol = new TGeoTube("pvol_fd3c", mRingSizesC[0], mRingSizesC[mNumberOfRingsC], mDzPlate);
376 auto pnod1 = new TGeoVolume("pnod1_FD3C", pvol, pmed);
377 auto pnod2 = new TGeoVolume("pnod2_FD3C", pvol, pmed);
378 double dpz = mDzScint / 2 + mDzPlate / 2;
379
380 mod->AddNode(pnod1, 1, new TGeoTranslation(0, 0, dpz));
381 mod->AddNode(pnod2, 2, new TGeoTranslation(0, 0, -dpz));
382 }
383
384 return mod;
385}
386
387void Detector::defineSensitiveVolumes()
388{
389 LOG(info) << "Adding FD3 Sentitive Volumes";
390
391 TGeoVolume* v;
392 TString volumeName;
393
394 int nCellsA = mNumberOfRingsA * mNumberOfSectors;
395 int nCellsC = mNumberOfRingsC * mNumberOfSectors;
396
397 LOG(info) << "number of A rings = " << mNumberOfRingsA << " number of cells = " << nCellsA;
398 LOG(info) << "number of C rings = " << mNumberOfRingsC << " number of cells = " << nCellsC;
399
400 for (int iv = 0; iv < nCellsA + nCellsC; iv++) {
401 volumeName = "fd3_node" + std::to_string(iv);
402 v = gGeoManager->GetVolume(volumeName);
403 LOG(info) << "Adding sensitive volume => " << v->GetName();
404 AddSensitiveVolume(v);
405 }
406}
407
408float Detector::ringSize(float z, float eta)
409{
410 return z * TMath::Tan(2 * TMath::ATan(TMath::Exp(-eta)));
411}
412
Definition of the FD3 Hit class (based on ITSMFT and FV0)
Definition of the Stack class.
General constants in FV0.
int32_t i
ClassImp(IdPath)
Definition of the MagF class.
uint32_t stack
Definition RawData.h:1
Definition of the Detector class.
Detector & operator=(const Detector &)
Definition Detector.cxx:46
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
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
o2::fd3::Hit * addHit(int trackId, unsigned int detId, const math_utils::Point3D< float > &startPos, const math_utils::Point3D< float > &endPos, const math_utils::Vector3D< float > &startMom, double startE, double endTime, double eLoss, int particlePdg)
This method is an example of how to add your own point of type Hit to the clones array.
Definition Detector.cxx:191
~Detector() override
Definition Detector.cxx:120
void InitializeO2Detector() override
Definition Detector.cxx:128
void EndOfEvent() override
Definition Detector.cxx:211
void Register() override
Definition Detector.cxx:216
void ConstructGeometry() override
Definition Detector.cxx:205
Detector()=default
bool ProcessHits(FairVolume *v=nullptr) override
Definition Detector.cxx:135
void Reset() override
Definition Detector.cxx:227
static GeometryTGeo * Instance()
static ShmManager & Instance()
Definition ShmManager.h:61
const GLdouble * v
Definition glcorearb.h:832
GLboolean * data
Definition glcorearb.h:298
GLboolean r
Definition glcorearb.h:1233
GLuint id
Definition glcorearb.h:650
GLdouble GLdouble GLdouble z
Definition glcorearb.h:843
Definition Hit.h:27
void freeSimVector(std::vector< T > *ptr)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52
Common utility functions.
static constexpr unsigned int nringsA_withMG
Definition Constants.h:32
static constexpr unsigned int nringsC
Definition Constants.h:27
static constexpr unsigned int nringsA
Definition Constants.h:26
static constexpr float etaMax
Definition Constants.h:29
static constexpr float etaMin
Definition Constants.h:30
static constexpr unsigned int nsect
Definition Constants.h:25
static constexpr float etaMinA_withMG
Definition Constants.h:33
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
o2::InteractionRecord ir(0, 0)