26#include "FairDetector.h"
27#include <fairlogger/Logger.h>
28#include "FairRootManager.h"
30#include "FairRuntimeDb.h"
31#include "FairVolume.h"
32#include "FairRootManager.h"
34#include "TVirtualMC.h"
35#include "TLorentzVector.h"
38#include <TGeoVolume.h>
39#include <TGeoCompositeShape.h>
40#include <TGeoMedium.h>
42#include <TGeoManager.h>
56 mGeometryTGeo(nullptr),
69 if (baseParam.withMG) {
77 mDzScint = baseParam.dzscint / 2;
78 mDzPlate = baseParam.dzplate;
80 mPlateBehindA = baseParam.plateBehindA;
81 mFullContainer = baseParam.fullContainer;
83 mZA = baseParam.zmodA;
84 mZC = baseParam.zmodC;
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);
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);
114 mTrackData = rhs.mTrackData;
130 LOG(info) <<
"Initialize Forward Detector";
132 defineSensitiveVolumes();
138 if (!(fMC->TrackCharge())) {
143 int volID = fMC->CurrentVolID(detId);
148 int particlePdg = fMC->TrackPid();
149 bool startHit =
false, stopHit =
false;
150 if ((fMC->IsTrackEntering()) || (fMC->IsTrackInside() && !mTrackData.mHitStarted)) {
152 }
else if ((fMC->IsTrackExiting() || fMC->IsTrackOut() || fMC->IsTrackStop())) {
158 mTrackData.mEnergyLoss += fMC->Edep();
160 if (!(startHit | stopHit)) {
165 mTrackData.mHitStarted =
true;
166 mTrackData.mEnergyLoss = 0.;
167 fMC->TrackMomentum(mTrackData.mMomentumStart);
168 fMC->TrackPosition(mTrackData.mPositionStart);
169 mTrackData.mTrkStatusStart =
true;
173 TLorentzVector positionStop;
174 fMC->TrackPosition(positionStop);
175 int trackId =
stack->GetCurrentTrackNumber();
177 math_utils::Point3D<float> posStart(mTrackData.mPositionStart.X(), mTrackData.mPositionStart.Y(), mTrackData.mPositionStart.Z());
179 math_utils::Vector3D<float> momStart(mTrackData.mMomentumStart.Px(), mTrackData.mMomentumStart.Py(), mTrackData.mMomentumStart.Pz());
181 Hit* p =
addHit(trackId, detId, posStart, posStop,
182 momStart, mTrackData.mMomentumStart.E(),
183 positionStop.T(), mTrackData.mEnergyLoss, particlePdg);
184 stack->addHit(GetDetId());
200 mHits->emplace_back(trackId, detId, startPos,
201 endPos, startMom, startE, endTime, eLoss, particlePdg);
202 return &(mHits->back());
222 if (FairRootManager::Instance()) {
223 FairRootManager::Instance()->RegisterAny(
addNameTo(
"Hit").
data(), mHits, kTRUE);
236 float density, as[11], zs[11], ws[11];
237 double radLength, absLength, a_ad, z_ad;
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};
245 const float dScint = 1.023;
253 const int unsens = 0, sens = 1;
256 float maxField = 5.0;
258 float tmaxfd3 = -10.0;
262 float stmin = -0.001;
264 LOG(info) <<
"FD3: CreateMaterials(): fieldType " << fieldType <<
", maxField " << maxField;
268 tmaxfd3, stemax, deemax, epsil, stmin);
272 tmaxfd3, stemax, deemax, epsil, stmin);
277 LOGP(info,
"Creating FD3 geometry");
279 TGeoVolume* vCave = gGeoManager->GetVolume(
"cave");
282 LOG(fatal) <<
"Could not find the top volume!";
285 TGeoVolumeAssembly* vFD3A = buildModuleA();
286 TGeoVolumeAssembly* vFD3C = buildModuleC();
288 vCave->AddNode(vFD3A, 1,
new TGeoTranslation(0., 0., mZA));
289 vCave->AddNode(vFD3C, 2,
new TGeoTranslation(0., 0., mZC));
292TGeoVolumeAssembly* Detector::buildModuleA()
294 TGeoVolumeAssembly* mod =
new TGeoVolumeAssembly(
"FD3A");
296 const TGeoMedium* medium = gGeoManager->GetMedium(
"FD3_Scintillator");
298 float dphiDeg = 360. / mNumberOfSectors;
300 for (
int ir = 0;
ir < mNumberOfRingsA;
ir++) {
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;
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);
316 nod->SetLineColor(kRed - 7);
318 ring->AddNode(nod, cellId);
320 mod->AddNode(ring,
ir + 1);
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));
332 if (mFullContainer) {
333 auto pnod2 =
new TGeoVolume(
"pnod2_FD3A", pvol, pmed);
334 mod->AddNode(pnod2, 1,
new TGeoTranslation(0, 0, -dpz));
340TGeoVolumeAssembly* Detector::buildModuleC()
342 TGeoVolumeAssembly* mod =
new TGeoVolumeAssembly(
"FD3C");
344 const TGeoMedium* medium = gGeoManager->GetMedium(
"FD3_Scintillator");
346 float dphiDeg = 360. / mNumberOfSectors;
348 for (
int ir = 0;
ir < mNumberOfRingsC;
ir++) {
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);
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);
364 nod->SetLineColor(kBlue - 7);
366 ring->AddNode(nod, cellId);
368 mod->AddNode(ring,
ir + 1);
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;
380 mod->AddNode(pnod1, 1,
new TGeoTranslation(0, 0, dpz));
381 mod->AddNode(pnod2, 2,
new TGeoTranslation(0, 0, -dpz));
387void Detector::defineSensitiveVolumes()
389 LOG(info) <<
"Adding FD3 Sentitive Volumes";
394 int nCellsA = mNumberOfRingsA * mNumberOfSectors;
395 int nCellsC = mNumberOfRingsC * mNumberOfSectors;
397 LOG(info) <<
"number of A rings = " << mNumberOfRingsA <<
" number of cells = " << nCellsA;
398 LOG(info) <<
"number of C rings = " << mNumberOfRingsC <<
" number of cells = " << nCellsC;
400 for (
int iv = 0; iv < nCellsA + nCellsC; iv++) {
402 v = gGeoManager->GetVolume(volumeName);
403 LOG(info) <<
"Adding sensitive volume => " <<
v->GetName();
404 AddSensitiveVolume(
v);
408float Detector::ringSize(
float z,
float eta)
410 return z * TMath::Tan(2 * TMath::ATan(TMath::Exp(-eta)));
Definition of the Stack class.
General constants in FV0.
Definition of the MagF class.
Definition of the Detector class.
Detector & operator=(const Detector &)
void Mixture(Int_t imat, const char *name, Float_t *a, Float_t *z, Float_t dens, Int_t nlmat, Float_t *wmat)
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)
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)
std::string addNameTo(const char *ext) const
static const FD3BaseParam & Instance()
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.
void InitializeO2Detector() override
void EndOfEvent() override
void ConstructGeometry() override
bool ProcessHits(FairVolume *v=nullptr) override
static GeometryTGeo * Instance()
static ShmManager & Instance()
GLdouble GLdouble GLdouble z
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)
Common utility functions.
static constexpr unsigned int nringsA_withMG
static constexpr unsigned int nringsC
static constexpr unsigned int nringsA
static constexpr float etaMax
static constexpr float etaMin
static constexpr unsigned int nsect
static constexpr float etaMinA_withMG
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
o2::InteractionRecord ir(0, 0)