23#include "TProfile2D.h"
84 mMCTruthContainerNext[
j] = &(mMCTruthContainer[
j + 1]);
107 if (readoutwindow < mReadoutWindowCurrent && mReadoutWindowCurrent - readoutwindow > max_readout_diff) {
116 checkIfReuseFutureDigits();
120 for (
auto& hit : *hits) {
123 if (hit.GetTime() > max_hit_time) {
148Int_t Digitizer::processHit(
const HitType& hit, Double_t event_time)
155 Int_t detIndOtherPad[5];
159 detIndOtherPad[0] = detInd[0], detIndOtherPad[1] = detInd[1],
160 detIndOtherPad[2] = detInd[2];
163 if (detInd[3] == 0) {
167 Int_t iZshift = otherraw ? 1 : -1;
193 mXLastShift[mNLastHit] = 0;
194 mZLastShift[mNLastHit] = 0;
195 addDigit(channel, istrip,
time, xLocal, zLocal,
charge, 0, 0, detInd[3], trackID, hit.
GetTime(), event_time * 1E3);
199 detIndOtherPad[3] = otherraw;
200 detIndOtherPad[4] = detInd[4];
202 xLocal = deltapos[0];
210 mXLastShift[mNLastHit] = 0;
211 mZLastShift[mNLastHit] = iZshift;
212 addDigit(channel, istrip,
time, xLocal, zLocal,
charge, 0, iZshift, detInd[3], trackID, hit.
GetTime(), event_time * 1E3);
216 detIndOtherPad[3] = detInd[3];
217 detIndOtherPad[4] = detInd[4] - 1;
218 if (detIndOtherPad[4] >= 0) {
221 zLocal = deltapos[2];
224 mXLastShift[mNLastHit] = -1;
225 mZLastShift[mNLastHit] = 0;
226 addDigit(channel, istrip,
time, xLocal, zLocal,
charge, -1, 0, detInd[3], trackID, hit.
GetTime(), event_time * 1E3);
231 detIndOtherPad[3] = detInd[3];
232 detIndOtherPad[4] = detInd[4] + 1;
236 zLocal = deltapos[2];
239 mXLastShift[mNLastHit] = 1;
240 mZLastShift[mNLastHit] = 0;
241 addDigit(channel, istrip,
time, xLocal, zLocal,
charge, 1, 0, detInd[3], trackID, hit.
GetTime(), event_time * 1E3);
246 detIndOtherPad[3] = otherraw;
247 detIndOtherPad[4] = detInd[4] - 1;
248 if (detIndOtherPad[4] >= 0) {
258 mXLastShift[mNLastHit] = -1;
259 mZLastShift[mNLastHit] = iZshift;
260 addDigit(channel, istrip,
time, xLocal, zLocal,
charge, -1, iZshift, detInd[3], trackID, hit.
GetTime(), event_time * 1E3);
265 detIndOtherPad[3] = otherraw;
266 detIndOtherPad[4] = detInd[4] + 1;
277 mXLastShift[mNLastHit] = 1;
278 mZLastShift[mNLastHit] = iZshift;
279 addDigit(channel, istrip,
time, xLocal, zLocal,
charge, 1, iZshift, detInd[3], trackID, hit.
GetTime(), event_time * 1E3);
287 Int_t padZfired, Int_t trackID,
float geanttime,
double t0)
291 if (mCalibApi->
isOff(channel)) {
310 Float_t timewalkX =
x * mTimeWalkeSlope;
316 time += gRandom->Gaus(mTimeDelay, extraTimeSmear);
326 time += TMath::Sqrt(timewalkX * timewalkX + timewalkZ * timewalkZ) - mTimeDelayCorr - mTimeWalkeSlope * 2;
330 if (std::abs(tsCorr) > 200E3) {
331 LOG(error) <<
"Wrong de-calibration correction for ch = " << channel <<
", tot = " << tot <<
" (Skip it)";
335 mTimeLastHit[mNLastHit] =
time;
336 mTotLastHit[mNLastHit] = tot;
359 bool iscurrent =
true;
361 Int_t isIfOverlap = -1;
367 if (isnext == isIfOverlap) {
369 }
else if (isnext < 0 && isIfOverlap >= 0) {
370 isnext = isIfOverlap;
373 isnext = isIfOverlap;
386 lblCurrent = mFutureIevent.size();
387 mFutureIevent.push_back(mEventID);
388 mFutureIsource.push_back(mSrcID);
389 mFutureItrackID.push_back(trackID);
395 lblCurrent = mFutureIevent.size();
396 mFutureIevent.push_back(mEventID);
397 mFutureIsource.push_back(mSrcID);
398 mFutureItrackID.push_back(trackID);
411 std::vector<Strip>* strips;
416 mcTruthContainer = mMCTruthContainerCurrent;
419 mcTruthContainer = mMCTruthContainerNext[isnext - 1];
422 fillDigitsInStrip(strips, mcTruthContainer, channel, tdc, tot, nbc, istrip, trackID, mEventID, mSrcID, geanttime,
t0);
424 if (isIfOverlap > -1 && isIfOverlap <
MAXWINDOWS) {
427 mcTruthContainer = mMCTruthContainerCurrent;
430 mcTruthContainer = mMCTruthContainerNext[isIfOverlap - 1];
433 fillDigitsInStrip(strips, mcTruthContainer, channel, tdc, tot, nbc, istrip, trackID, mEventID, mSrcID, geanttime,
t0);
437void Digitizer::fillDigitsInStrip(std::vector<Strip>* strips,
o2::dataformats::MCTruthContainer<o2::tof::MCLabel>* mcTruthContainer,
int channel,
int tdc,
int tot, uint64_t nbc, UInt_t istrip, Int_t trackID, Int_t eventID, Int_t sourceID,
float geanttime,
double t0)
440 if (mcTruthContainer) {
444 Int_t lbl = (*strips)[istrip].addDigit(channel, tdc, tot, nbc, lblCurrent, 0, 0, geanttime,
t0);
446 if (mcTruthContainer) {
447 if (lbl == lblCurrent) {
455 auto labels = mcTruthContainer->
getLabels(lbl);
456 std::sort(labels.begin(), labels.end(),
465 return time + gRandom->Gaus(0, mShowerResolution);
473 return time + gRandom->Gaus(0, mDigitResolution);
483 return gRandom->Landau(adcMean, adcRms);
499 Float_t efficiency = TMath::Min(effX, effZ);
501 if (gRandom->Rndm() > efficiency) {
514 if (xborder > mBound1) {
516 }
else if (xborder > mBound2) {
517 return mEffBoundary1 + (mEffCenter - mEffBoundary1) * (xborder - mBound2) / (mBound1 - mBound2);
519 return mEffBoundary2 + (mEffBoundary1 - mEffBoundary2) * xborder / mBound2;
523 if (xborder > mBound4) {
525 }
else if (xborder > mBound3) {
526 return mEffBoundary3 - mEffBoundary3 * (xborder - mBound3) / (mBound4 - mBound3);
528 return mEffBoundary2 + (mEffBoundary3 - mEffBoundary2) * xborder / mBound3;
541 if (zborder > mBound1) {
543 }
else if (zborder > mBound2) {
544 return mEffBoundary1 + (mEffCenter - mEffBoundary1) * (zborder - mBound2) / (mBound1 - mBound2);
546 return mEffBoundary2 + (mEffBoundary1 - mEffBoundary2) * zborder / mBound2;
550 if (zborder > mBound4) {
552 }
else if (zborder > mBound3) {
553 return mEffBoundary3 - mEffBoundary3 * (zborder - mBound3) / (mBound4 - mBound3);
555 return mEffBoundary2 + (mEffBoundary3 - mEffBoundary2) * zborder / mBound3;
567 mShowerResolution = 50;
568 if (mTOFresolution > mShowerResolution) {
569 mDigitResolution = TMath::Sqrt(mTOFresolution * mTOFresolution - mShowerResolution * mShowerResolution);
571 mShowerResolution = mTOFresolution;
572 mDigitResolution = 0;
590 mTimeWalkeSlope = 40;
598 mTimeDelayCorr = mTimeDelay / 3.5;
599 if (mShowerResolution > mTimeDelayCorr) {
600 mShowerResolution = TMath::Sqrt(mShowerResolution * mShowerResolution - mTimeDelayCorr * mTimeDelayCorr);
602 mShowerResolution = 0;
605 if (mShowerResolution > mTimeWalkeSlope * 0.8) {
606 mShowerResolution = TMath::Sqrt(mShowerResolution * mShowerResolution - mTimeWalkeSlope * mTimeWalkeSlope * 0.64);
608 mShowerResolution = 0;
621 printf(
"Efficiency in the pad center = %f\n", mEffCenter);
622 printf(
"Efficiency in the pad border = %f\n", mEffBoundary2);
623 printf(
"Time resolution = %f ps (shower=%f, digit=%f)\n", mTOFresolution, mShowerResolution, mDigitResolution);
624 if (mTimeSlope > 0) {
625 printf(
"Degration resolution for pad with signal induced = %f ps/cm x border distance\n", mTimeSlope);
627 if (mTimeDelay > 0) {
628 printf(
"Time delay for pad with signal induced = %f ps\n", mTimeDelay);
630 if (mTimeWalkeSlope > 0) {
631 printf(
"Time walk ON = %f ps/cm\n", mTimeWalkeSlope);
648 Int_t nhit = 1000000;
656 TH1F*
h =
new TH1F(
"hTime",
"Time as from digitizer;time (ps);N", 100, -500, 500);
657 TH1F* h2 =
new TH1F(
"hTot",
"Tot as from digitizer;time (ns);N", 100, 0, 30);
658 TH1F* h3 =
new TH1F(
"hNdig",
"N_{digitis} distribution from one hit;N_{digits};N", 7, -0.5, 6.5);
659 TH1F* h4 =
new TH1F(
"hTimeCorr",
"Time correlation for double digits;#Deltat (ps)", 200, -1000, 1000);
660 TH1F* h5 =
new TH1F(
"hTimeAv",
"Time average for double digits;#Deltat (ps)", 200, -1000, 1000);
663 for (Int_t
i = 0;
i < 3;
i++) {
664 for (Int_t
j = 0;
j < 3;
j++) {
666 new TH1F(Form(
"hpad%i_%i",
i,
j), Form(
"Time as from digitizer, pad(%i,%i);time (ps);N",
i,
j), 100, -500, 500);
670 TProfile2D* hTimeWalk =
new TProfile2D(
"hTimeWalk",
"Time Walk;x (cm);z (cm)", 40, -1.25, 1.25, 40, -1.75, 1.75);
673 hpadAll =
new TH2F(
"hpadAll",
"all hits;x (cm);z (cm)", 40, -1.25, 1.25, 40, -1.75, 1.75);
676 for (Int_t
i = 0;
i < 3;
i++) {
677 for (Int_t
j = 0;
j < 3;
j++) {
678 hpadHit[
i][
j] =
new TH2F(Form(
"hpadHit%i_%i",
i,
j), Form(
"pad(%i,%i) hits;x (cm);z (cm)",
i - 1, 1 -
j), 40,
679 -1.25, 1.25, 40, -1.75, 1.75);
680 hpadEff[
i][
j] =
new TH2F(Form(
"hpadEff%i_%i",
i,
j), Form(
"pad(%i,%i) hits;x (cm);z (cm)",
i - 1, 1 -
j), 40,
681 -1.25, 1.25, 40, -1.75, 1.75);
685 Int_t det1[5] = {0, 0, 0, 1, 23};
686 Int_t det2[5] = {0, 0, 0, 0, 24};
687 Int_t det3[5] = {0, 0, 0, 1, 24};
688 Int_t det4[5] = {0, 0, 0, 0, 47};
712 mod = TMath::Sqrt(pos3[0] * pos3[0] + pos3[1] * pos3[1] + pos3[2] * pos3[2]);
713 vz[0] = pos3[0] / mod;
714 vz[1] = pos3[1] / mod;
715 vz[2] = pos3[2] / mod;
721 mod = TMath::Sqrt(pos4[0] * pos4[0] + pos4[1] * pos4[1] + pos4[2] * pos4[2]);
722 vx[0] = pos4[0] / mod;
723 vx[1] = pos4[1] / mod;
724 vx[2] = pos4[2] / mod;
726 Float_t x[3], dx, dz, xlocal, zlocal;
728 for (Int_t
i = 0;
i < nhit;
i++) {
729 dx = gRandom->Rndm() * 2.5 * 48;
730 dz = gRandom->Rndm() * 3.5 * 2;
732 xlocal = dx - Int_t(dx / 2.5) * 2.5 - 1.25;
733 zlocal = dz - Int_t(dz / 3.5) * 3.5 - 1.75;
738 x[0] =
pos[0] + vx[0] * dx + vz[0] * dz;
739 x[1] =
pos[1] + vx[1] * dx + vz[1] * dz;
740 x[2] =
pos[2] + vx[2] * dx + vz[2] * dz;
751 Int_t ndigits = mNLastHit;
754 hpadAll->Fill(xlocal, zlocal);
755 for (Int_t k = 0; k < ndigits; k++) {
763 hTimeWalk->Fill(xlocal, zlocal * (0.5 - detCur[3]) * 2,
getTimeLastHit(k));
787 hTimeWalk->Draw(
"SURF");
789 TCanvas* cpad =
new TCanvas();
791 for (Int_t
i = 0;
i < 3;
i++) {
792 for (Int_t
j = 0;
j < 3;
j++) {
793 cpad->cd(
j * 3 +
i + 1);
797 TCanvas* cpadH =
new TCanvas();
799 for (Int_t
i = 0;
i < 3;
i++) {
800 for (Int_t
j = 0;
j < 3;
j++) {
801 cpadH->cd(
j * 3 +
i + 1);
802 hpadHit[
i][
j]->Draw(
"colz");
804 hpadHit[
i][
j]->Scale(2);
806 hpadEff[
i][
j]->Divide(hpadHit[
i][
j], hpadAll, 1, 1,
"B");
807 hpadEff[
i][
j]->Draw(
"surf");
808 hpadEff[
i][
j]->SetMaximum(1);
809 hpadEff[
i][
j]->SetMinimum(0);
810 hpadEff[
i][
j]->SetStats(0);
814 printf(
"\nEfficiency = %f\n", (h3->GetEntries() - h3->GetBinContent(1)) / h3->GetEntries());
815 printf(
"Multiple digits fraction = %f\n\n",
816 (h3->GetEntries() - h3->GetBinContent(1) - h3->GetBinContent(2)) / (h3->GetEntries() - h3->GetBinContent(1)));
824 TFile* fHit =
new TFile(hits);
827 TTree* t = (TTree*)fHit->Get(
"o2sim");
828 Int_t nev = t->GetEntriesFast();
834 TH1F*
h =
new TH1F(
"hTime",
"Time as from digitizer;time (ps);N", 100, -500, 500);
835 TH1F* h2 =
new TH1F(
"hTot",
"Tot as from digitizer;time (ns);N", 100, 0, 30);
836 TH1F* h3 =
new TH1F(
"hNdig",
"N_{digitis} distribution from one hit;N_{digits};N", 7, -0.5, 6.5);
838 for (Int_t
i = 0;
i < nev;
i++) {
840 Int_t nhit = t->GetLeaf(
"o2root.TOF.TOFHit_")->GetLen();
842 for (Int_t
j = 0;
j < nhit;
j++) {
844 hit->
SetXYZ(t->GetLeaf(
"o2root.TOF.TOFHit.mPos.fCoordinates.fX")->GetValue(
j),
845 t->GetLeaf(
"o2root.TOF.TOFHit.mPos.fCoordinates.fY")->GetValue(
j),
846 t->GetLeaf(
"o2root.TOF.TOFHit.mPos.fCoordinates.fZ")->GetValue(
j));
848 hit->
SetEnergyLoss(t->GetLeaf(
"o2root.TOF.TOFHit.mELoss")->GetValue(
j));
853 for (Int_t k = 0; k < ndigits; k++) {
871 mMCTruthOutputContainer->
clear();
876 strip.fillOutputContainer(
digits);
877 if (strip.getNumberOfDigits()) {
878 LOG(
debug) <<
"strip size = " << strip.getNumberOfDigits() <<
" - digit size = " <<
digits.size() <<
"\n";
894 float p = gRandom->Rndm();
900 int itrmreached = -1;
905 if (crateProb[
i] > p) {
907 isEmptyCrate[
i] =
true;
909 isEmptyCrate[
i] =
false;
910 int slotreached = -1;
911 const std::vector<std::pair<int, float>>& trmProg = mCalibApi->
getTRMerrorProb();
912 const std::vector<int>& trmErr = mCalibApi->
getTRMmask();
913 for (
int itrm = itrmreached + 1; itrm < trmProg.size(); itrm++) {
914 int crate = trmProg[itrm].first / 100;
916 int slot = trmProg[itrm].first % 100;
917 if (slot != slotreached) {
922 if (trmProg[itrm].second > p) {
928 for (
int ibit = 0; ibit < 28; ibit++) {
929 if (trmErr[itrm] & cbit) {
938 p -= trmProg[itrm].second;
951 std::map<ULong64_t, o2::tof::Digit>& dmap = strip.getDigitMap();
953 std::vector<ULong64_t> keyToBeRemoved;
955 for (
auto [
key, dig] : dmap) {
958 if (isEmptyCrate[crate] || mCalibApi->
isChannelError(dig.getChannel())) {
960 keyToBeRemoved.push_back(
key);
963 for (
auto&
key : keyToBeRemoved) {
967 strip.fillOutputContainer(
digits);
982 if (mMCTruthOutputContainer) {
991 mMCTruthOutputContainerPerTimeFrame.push_back(*mMCTruthOutputContainer);
993 mMCTruthContainerCurrent->
clear();
1007 mMCTruthContainerNext[
i] = &(mMCTruthContainer[k]);
1022 checkIfReuseFutureDigits();
1027 checkIfReuseFutureDigits();
1036 mFutureItrackID.clear();
1037 mFutureIsource.clear();
1038 mFutureIevent.clear();
1041void Digitizer::checkIfReuseFutureDigits()
1043 uint64_t bclimit = 999999999999999999;
1049 if (digit->getBC() > bclimit) {
1057 if (isnext == isIfOverlap) {
1059 }
else if (isnext < 0 && isIfOverlap >= 0) {
1060 isnext = isIfOverlap;
1063 isnext = isIfOverlap;
1068 LOG(info) <<
"Digit lost because we jump too ahead in future. Current RO window=" << isnext <<
"\n";
1071 int labelremoved = digit->getLabel();
1099 mcTruthContainer = mMCTruthContainerNext[isnext - 1];
1102 int trackID = mFutureItrackID[digit->getLabel()];
1103 int sourceID = mFutureIsource[digit->getLabel()];
1104 int eventID = mFutureIevent[digit->getLabel()];
1105 fillDigitsInStrip(strips, mcTruthContainer, digit->getChannel(), digit->getTDC(), digit->getTOT(), digit->getBC(), digit->getChannel() /
Geo::NPADS, trackID, eventID, sourceID, digit->getTgeant());
1107 if (isIfOverlap < 0) {
1109 int labelremoved = digit->getLabel();
1127 bclimit = digit->getBC();
Definition of the GeometryManager class.
Class for time synchronization of RawReader instances.
void SetEnergyLoss(V val)
void SetXYZ(T x, T y, T z)
static void loadGeometry(std::string_view geomFilePath="", bool applyMisalignment=false, bool preferAlignedFile=true)
static const HBFUtils & Instance()
bool isChannelError(int channel) const
const float * getEmptyCratesProb() const
const std::vector< std::pair< int, float > > & getTRMerrorProb() const
void readTimeSlewingParam()
void setTimeStamp(long t)
float getEmptyTOFProb() const
void processError(int crate, int trm, int mask)
float getTimeDecalibration(int ich, float tot) const
const std::vector< int > & getTRMmask() const
int process(const std::vector< HitType > *hits, std::vector< Digit > *digits)
Float_t getEffX(Float_t x)
void flushOutputContainer(std::vector< Digit > &digits)
Double_t getShowerTimeSmeared(Double_t time, Float_t charge)
void test(const char *geo="")
Int_t getXshift(Int_t idigit) const
void fillOutputContainer(std::vector< Digit > &digits)
Float_t getEffZ(Float_t z)
void runFullTestExample(const char *geo="")
void testFromHits(const char *geo="", const char *hits="AliceO2_TGeant3.tof.mc_10_event.root")
Bool_t isFired(Float_t x, Float_t z, Float_t charge)
Double_t getDigitTimeSmeared(Double_t time, Float_t x, Float_t z, Float_t charge)
uint64_t getReadoutWindow(double timeNS) const
Float_t getTotLastHit(Int_t idigit) const
Float_t getCharge(Float_t eDep)
Float_t getTimeLastHit(Int_t idigit) const
Int_t getZshift(Int_t idigit) const
void setCalibApi(CalibApi *calibApi)
Float_t getFractionOfCharge(Float_t x, Float_t z)
static constexpr Float_t ZPAD
static constexpr Float_t XPAD
static constexpr Double_t BC_TIME_INPS
static constexpr Double_t BC_TIME_INPS_INV
static constexpr Float_t NTOTBIN_PER_NS
static constexpr Int_t NPADS
static constexpr Float_t NTDCBIN_PER_PS
number of TDC bins in 1 ns
static constexpr Double_t READOUTWINDOW_INV
static Int_t getCrateFromECH(int ech)
static void getPos(Int_t *det, Float_t *pos)
static constexpr Int_t LATENCYWINDOW_IN_BC
static constexpr Double_t BC_TIME
static constexpr Float_t TOTBIN_NS
static Int_t getIndex(const Int_t *detId)
static constexpr Float_t TDCBIN
TDC bin width [ps].
static void getDetID(Float_t *pos, Int_t *det)
static constexpr int BC_IN_WINDOW
static void getPadDxDyDz(const Float_t *pos, Int_t *det, Float_t *DeltaPos, int sector=-1)
static constexpr Int_t OVERLAP_IN_BC
static constexpr Int_t NPADX
static Int_t getECHFromCH(int chan)
static constexpr int NWINDOW_IN_ORBIT
static constexpr Double_t LATENCYWINDOW
static constexpr Int_t NSTRIPS
int mIcurrentReadoutWindow
uint64_t mReadoutWindowCurrent
std::vector< Strip > mStrips[MAXWINDOWS]
static const int MAXWINDOWS
InteractionTimeRecord mEventTime
std::vector< Strip > * mStripsCurrent
std::vector< Strip > * mStripsNext[MAXWINDOWS - 1]
std::vector< uint8_t > mPatterns
std::vector< Digit > mDigitsPerTimeFrame
void insertDigitInFuture(Int_t channel, Int_t tdc, Int_t tot, uint64_t bc, Int_t label=0, uint32_t triggerorbit=0, uint16_t triggerbunch=0)
std::vector< Digit > mFutureDigits
std::vector< ReadoutWindowData > mReadoutWindowData
InteractionRecord mFirstIR
GLint GLint GLsizei GLint border
GLboolean GLboolean GLboolean b
GLuint GLsizei const GLchar * label
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t0
GLboolean GLboolean GLboolean GLboolean a
GLdouble GLdouble GLdouble z
constexpr int LHCMaxBunches
FIXME: do not use data model tables.
uint16_t bc
bunch crossing ID of interaction
double getTimeOffsetWrtBC() const
double getTimeNS() const
get time in ns from orbit=0/bc=0
void setEmptyCrate(int crate)
void setBCData(int orbit, int bc)
void addedDiagnostic(int crate)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< Digit > digits