27#include <fairlogger/Logger.h>
33#include "TVirtualMC.h"
34#include "TLorentzVector.h"
37#include <TGeoVolume.h>
38#include <TGeoCompositeShape.h>
39#include <TGeoMedium.h>
41#include <TGeoManager.h>
55 mGeometryTGeo(nullptr),
58 mNumberOfRingsC = Constants::nringsC;
59 mNumberOfSectors = Constants::nsect;
61 mEtaMinA = Constants::etaMin;
62 mEtaMaxA = Constants::etaMax;
63 mEtaMinC = -Constants::etaMax;
64 mEtaMaxC = -Constants::etaMin;
68 if (baseParam.withMG) {
69 mNumberOfRingsA = Constants::nringsA_withMG;
70 mEtaMinA = Constants::etaMinA_withMG;
72 mNumberOfRingsA = Constants::nringsA;
73 mEtaMinA = Constants::etaMin;
76 mDzScint = baseParam.dzscint / 2;
77 mDzPlate = baseParam.dzplate;
79 mPlateBehindA = baseParam.plateBehindA;
80 mFullContainer = baseParam.fullContainer;
82 mZA = baseParam.zmodA;
83 mZC = baseParam.zmodC;
85 for (
int i = 0;
i <= mNumberOfRingsA + 1;
i++) {
86 float eta = mEtaMaxA -
i * (mEtaMaxA - mEtaMinA) / mNumberOfRingsA;
87 float r = ringSize(mZA, eta);
88 mRingSizesA.emplace_back(
r);
91 for (
int i = 0;
i <= mNumberOfRingsC + 1;
i++) {
92 float eta = mEtaMinC +
i * (mEtaMaxC - mEtaMinC) / mNumberOfRingsC;
93 float r = ringSize(mZC, eta);
94 mRingSizesC.emplace_back(
r);
113 mTrackData = rhs.mTrackData;
129 LOG(info) <<
"Initialize Forward Detector";
131 defineSensitiveVolumes();
137 if (!(
fMC->TrackCharge())) {
142 int volID =
fMC->CurrentVolID(detId);
147 int particlePdg =
fMC->TrackPid();
148 bool startHit =
false, stopHit =
false;
149 if ((
fMC->IsTrackEntering()) || (
fMC->IsTrackInside() && !mTrackData.mHitStarted)) {
151 }
else if ((
fMC->IsTrackExiting() ||
fMC->IsTrackOut() ||
fMC->IsTrackStop())) {
157 mTrackData.mEnergyLoss +=
fMC->Edep();
159 if (!(startHit | stopHit)) {
164 mTrackData.mHitStarted =
true;
165 mTrackData.mEnergyLoss = 0.;
166 fMC->TrackMomentum(mTrackData.mMomentumStart);
167 fMC->TrackPosition(mTrackData.mPositionStart);
168 mTrackData.mTrkStatusStart =
true;
172 TLorentzVector positionStop;
173 fMC->TrackPosition(positionStop);
174 int trackId =
stack->GetCurrentTrackNumber();
176 math_utils::Point3D<float> posStart(mTrackData.mPositionStart.X(), mTrackData.mPositionStart.Y(), mTrackData.mPositionStart.Z());
177 math_utils::Point3D<float> posStop(positionStop.X(), positionStop.Y(), positionStop.Z());
178 math_utils::Vector3D<float> momStart(mTrackData.mMomentumStart.Px(), mTrackData.mMomentumStart.Py(), mTrackData.mMomentumStart.Pz());
180 Hit* p =
addHit(trackId, detId, posStart, posStop,
181 momStart, mTrackData.mMomentumStart.E(),
182 positionStop.T(), mTrackData.mEnergyLoss, particlePdg);
191 const math_utils::Point3D<float>& startPos,
192 const math_utils::Point3D<float>& endPos,
193 const math_utils::Vector3D<float>& startMom,
199 mHits->emplace_back(trackId, detId, startPos,
200 endPos, startMom, startE, endTime, eLoss, particlePdg);
201 return &(mHits->back());
235 float density, as[11], zs[11], ws[11];
236 double radLength, absLength, a_ad, z_ad;
240 const int nScint = 2;
241 float aScint[nScint] = {1.00784, 12.0107};
242 float zScint[nScint] = {1, 6};
243 float wScint[nScint] = {0.07085, 0.92915};
244 const float dScint = 1.023;
252 const int unsens = 0, sens = 1;
255 float maxField = 5.0;
257 float tmaxfd3 = -10.0;
261 float stmin = -0.001;
263 LOG(info) <<
"FD3: CreateMaterials(): fieldType " << fieldType <<
", maxField " << maxField;
267 tmaxfd3, stemax, deemax, epsil, stmin);
271 tmaxfd3, stemax, deemax, epsil, stmin);
276 LOGP(info,
"Creating FD3 geometry");
278 TGeoVolume* vCave = gGeoManager->GetVolume(
"cave");
281 LOG(fatal) <<
"Could not find the top volume!";
284 TGeoVolumeAssembly* vFD3A = buildModuleA();
285 TGeoVolumeAssembly* vFD3C = buildModuleC();
287 vCave->AddNode(vFD3A, 1,
new TGeoTranslation(0., 0., mZA));
288 vCave->AddNode(vFD3C, 2,
new TGeoTranslation(0., 0., mZC));
291TGeoVolumeAssembly* Detector::buildModuleA()
293 TGeoVolumeAssembly* mod =
new TGeoVolumeAssembly(
"FD3A");
295 const TGeoMedium* medium = gGeoManager->GetMedium(
"FD3_Scintillator");
297 float dphiDeg = 360. / mNumberOfSectors;
299 for (
int ir = 0;
ir < mNumberOfRingsA;
ir++) {
301 TGeoVolumeAssembly* ring =
new TGeoVolumeAssembly(rName.c_str());
302 float rmin = mRingSizesA[
ir];
303 float rmax = mRingSizesA[
ir + 1];
304 LOG(info) <<
"ring" <<
ir <<
": from " << rmin <<
" to " << rmax;
305 for (
int ic = 0; ic < mNumberOfSectors; ic++) {
306 int cellId = ic + mNumberOfSectors *
ir;
308 float phimin = dphiDeg * ic;
309 float phimax = dphiDeg * (ic + 1);
310 auto tbs =
new TGeoTubeSeg(
"tbs", rmin, rmax, mDzScint, phimin, phimax);
311 auto nod =
new TGeoVolume(nodeName.c_str(), tbs, medium);
312 if ((
ir + ic) % 2 == 0) {
313 nod->SetLineColor(kRed);
315 nod->SetLineColor(kRed - 7);
317 ring->AddNode(nod, cellId);
319 mod->AddNode(ring,
ir + 1);
323 if (mPlateBehindA || mFullContainer) {
324 LOG(info) <<
"adding container on A side";
325 auto pmed = (TGeoMedium*)gGeoManager->GetMedium(
"FD3_Aluminium");
326 auto pvol =
new TGeoTube(
"pvol_fd3a", mRingSizesA[0], mRingSizesA[mNumberOfRingsA], mDzPlate);
327 auto pnod1 =
new TGeoVolume(
"pnod1_FD3A", pvol, pmed);
328 double dpz = 2. + mDzPlate / 2;
329 mod->AddNode(pnod1, 1,
new TGeoTranslation(0, 0, dpz));
331 if (mFullContainer) {
332 auto pnod2 =
new TGeoVolume(
"pnod2_FD3A", pvol, pmed);
333 mod->AddNode(pnod2, 1,
new TGeoTranslation(0, 0, -dpz));
339TGeoVolumeAssembly* Detector::buildModuleC()
341 TGeoVolumeAssembly* mod =
new TGeoVolumeAssembly(
"FD3C");
343 const TGeoMedium* medium = gGeoManager->GetMedium(
"FD3_Scintillator");
345 float dphiDeg = 360. / mNumberOfSectors;
347 for (
int ir = 0;
ir < mNumberOfRingsC;
ir++) {
349 TGeoVolumeAssembly* ring =
new TGeoVolumeAssembly(rName.c_str());
350 float rmin = mRingSizesC[
ir];
351 float rmax = mRingSizesC[
ir + 1];
352 LOG(info) <<
"ring" <<
ir + mNumberOfRingsA <<
": from " << rmin <<
" to " << rmax;
353 for (
int ic = 0; ic < mNumberOfSectors; ic++) {
354 int cellId = ic + mNumberOfSectors * (
ir + mNumberOfRingsA);
356 float phimin = dphiDeg * ic;
357 float phimax = dphiDeg * (ic + 1);
358 auto tbs =
new TGeoTubeSeg(
"tbs", rmin, rmax, mDzScint, phimin, phimax);
359 auto nod =
new TGeoVolume(nodeName.c_str(), tbs, medium);
360 if ((
ir + ic) % 2 == 0) {
361 nod->SetLineColor(kBlue);
363 nod->SetLineColor(kBlue - 7);
365 ring->AddNode(nod, cellId);
367 mod->AddNode(ring,
ir + 1);
371 if (mFullContainer) {
372 LOG(info) <<
"adding container on C side";
373 auto pmed = (TGeoMedium*)gGeoManager->GetMedium(
"FD3_Aluminium");
374 auto pvol =
new TGeoTube(
"pvol_fd3c", mRingSizesC[0], mRingSizesC[mNumberOfRingsC], mDzPlate);
375 auto pnod1 =
new TGeoVolume(
"pnod1_FD3C", pvol, pmed);
376 auto pnod2 =
new TGeoVolume(
"pnod2_FD3C", pvol, pmed);
377 double dpz = mDzScint / 2 + mDzPlate / 2;
379 mod->AddNode(pnod1, 1,
new TGeoTranslation(0, 0, dpz));
380 mod->AddNode(pnod2, 2,
new TGeoTranslation(0, 0, -dpz));
386void Detector::defineSensitiveVolumes()
388 LOG(info) <<
"Adding FD3 Sentitive Volumes";
393 int nCellsA = mNumberOfRingsA * mNumberOfSectors;
394 int nCellsC = mNumberOfRingsC * mNumberOfSectors;
396 LOG(info) <<
"number of A rings = " << mNumberOfRingsA <<
" number of cells = " << nCellsA;
397 LOG(info) <<
"number of C rings = " << mNumberOfRingsC <<
" number of cells = " << nCellsC;
399 for (
int iv = 0; iv < nCellsA + nCellsC; iv++) {
401 v = gGeoManager->GetVolume(volumeName);
402 LOG(info) <<
"Adding sensitive volume => " <<
v->GetName();
407float Detector::ringSize(
float z,
float eta)
409 return z * TMath::Tan(2 * TMath::ATan(TMath::Exp(-eta)));
Definition of the Stack class.
General constants in FV0.
configStandalone Reconstruction rec_tpc multiplier for the combined cluster track error during track following area in cm for the search of for z only used if decrease removal by when above this local occupancy rowx Shift of TPC revert cluster flag edge bit distance to edge exceeds this ZOffset for secondary multiple of radius max P of electron K BB bands crossing max P of electron p BB bands crossing max P of electron d BB bands crossing max P of electron t BB bands crossing min accepted dEdxMaxTPC of the track Additive extra cluster error for Y2 if edge flag set Additive extra cluster error for Y2 if single set Additive extra cluster error for Y2 if or single set Additive extra cluster error for Z2 if or single set Extra errors to add to track when crossing depending on addErrorsCECrossing Inner portion of y range in sector that is not used in searching for extrapolated track candidates factor2YS for track merging factor2K for track merging Margin in cm of Y position when rejecting edge clusters based on uncorrected track Y Max fraction of shared clusters for tracklet Except pad from cluster finding if total number of charges in a fragment is above this Except pad from cluster finding if number of consecutive charges in a fragment is above this Threshold where a timebin is considered disabling the noisy pad check for that pad Treat signal above this minimum as saturated Smoothing factor for the exponential Highly Ionising Particle tail filter Number of timebins to use for the averaging Add additional custom track errors when crossing relative as fraction of Do N fit passes in final fit of< 0:reject at max -n hits") AddOptionRTC(rejectIFCLowRadiusCluster, uint8_t, 1, "", 0, "Reject clusters that get the IFC mask error during refit") AddOptionRTC(dEdxTruncLow, uint8_t, 2, "", 0, "Low truncation threshold, fraction of 128") AddOptionRTC(dEdxTruncHigh, uint8_t, 77, "", 0, "High truncation threshold, fraction of 128") AddOptionRTC(extrapolationTracking, int8_t, 1, "", 0, "Enable Extrapolation Tracking(prolong tracks to adjacent sectors to find short segments)") AddOptionRTC(disableRefitAttachment, uint8_t, 0, "", 0, "Bitmask to disable certain attachment steps during refit(1:attachment, 2:propagation, 4:loop following, 8:mirroring)") AddOptionRTC(rejectionStrategy, uint8_t, o2::gpu::GPUSettings::RejectionStrategyA, "", 0, "Enable rejection of TPC clusters for compression(0=no, 1=strategy A, 2=strategy B)") AddOptionRTC(mergeLoopersAfterburner, uint8_t, 1, "", 0, "Run afterburner for additional looper merging") AddOptionRTC(compressionTypeMask, uint8_t, o2::gpu::GPUSettings::CompressionFull, "", 0, "TPC Compression mode bits(1=truncate charge/width LSB, 2=differences, 4=track-model)") AddOptionRTC(compressionSortOrder, uint8_t, o2::gpu::GPUSettings::SortTime, "", 0, "Sort order of TPC compression(0=time, 1=pad, 2=Z-time-pad, 3=Z-pad-time, 4=no sorting(use incoming order))") AddOptionRTC(sigBitsCharge, uint8_t, 4, "", 0, "Number of significant bits for TPC cluster charge in compression mode 1") AddOptionRTC(sigBitsWidth, uint8_t, 3, "", 0, "Number of significant bits for TPC cluster width in compression mode 1") AddOptionRTC(dropLoopers, uint8_t, 0, "", 0, "Drop looping tracks starting from second loop") AddOptionRTC(mergerInterpolateErrors, uint8_t, 1, "", 0, "Use interpolation instead of extrapolation for chi2 based cluster rejection") AddOptionRTC(mergerInterpolateRejectAlsoOnCurrentPosition, uint8_t, 1, "", 0, "When using mergerInterpolateErrors, reject based on chi2 twice computed with interpolated and current track position starting from NDF > mergerNonInterpolateRejectMinNDF Merge tracks accross the central electrode Enable PID response Add sub threshold clusters in TPC dEdx computation OR mask of TPC flags that will reject the cluster in alternative dEdx Reject edge clusters based on uncorrected track Y during track fit Increase decrease removal by when on this number of pads from the edge h configStandalone Reconstruction rec_trd Max chi2 for TRD tracklets to be matched to a track Chi2 cut for strict matching mode Number of sigmas for ITS TPC track time error estimate Addition to search road around track prolongation along Y in cm Optimal tracklet rphi resolution in maximum chi2 per attached tracklet for TRD tracks take into account the full likelihood of the slope including exponential tails Tracks with less attached tracklets are discarded after the tracking Post trigger Pile up integration time in BCs fits all iterations but the last one in projections Use material lookup table for TPC refit Apply workarounds to avoid cyclic merge should not be needed tpc dyn configStandalone Processing proc_rtc true
Definition of the MagF class.
Definition of the Detector class.
void AddSensitiveVolume(TGeoVolume *v)
TVirtualMC * fMC
flag for initialisation
void RegisterAny(const char *name, T *&obj, Bool_t toFile)
static FairRootManager * Instance()
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.
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
o2::InteractionRecord ir(0, 0)