From 3fe84329116582ba25214f7ff5e4a8b6c602b489 Mon Sep 17 00:00:00 2001 From: Sean Murray Date: Mon, 3 Feb 2025 14:05:32 +0100 Subject: [PATCH] TRD add digit phases to CTF encoding, collapse phases on reading. --- .../TRD/include/DataFormatsTRD/Digit.h | 6 +- .../TRD/include/DataFormatsTRD/PHData.h | 60 +++++++++++++++++++ .../Detectors/TRD/src/DataFormatsTRDLinkDef.h | 2 + DataFormats/Detectors/TRD/src/Digit.cxx | 9 ++- .../include/TRDCalibration/PulseHeight.h | 2 + Detectors/TRD/calibration/src/PulseHeight.cxx | 6 ++ Detectors/TRD/qc/src/RawDataManager.cxx | 2 + .../include/TRDReconstruction/CTFCoder.h | 4 +- .../include/TRDReconstruction/CTFHelper.h | 4 +- .../TRD/reconstruction/src/CruRawReader.cxx | 4 ++ .../include/TRDWorkflow/TRDPulseHeightSpec.h | 2 + 11 files changed, 94 insertions(+), 7 deletions(-) diff --git a/DataFormats/Detectors/TRD/include/DataFormatsTRD/Digit.h b/DataFormats/Detectors/TRD/include/DataFormatsTRD/Digit.h index 28ec6c76f4bef..9eba0318a5a13 100644 --- a/DataFormats/Detectors/TRD/include/DataFormatsTRD/Digit.h +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/Digit.h @@ -59,7 +59,7 @@ class Digit Digit(int det, int row, int pad, ArrayADC adc, int phase = 0); Digit(int det, int row, int pad); // add adc data and pretrigger phase in a separate step Digit(int det, int rob, int mcm, int channel, ArrayADC adc, int phase = 0); - Digit(int det, int rob, int mcm, int channel); // add adc data in a seperate step + Digit(int det, int rob, int mcm, int channel, int phase = 0); // add adc data // Copy Digit(const Digit&) = default; @@ -74,9 +74,11 @@ class Digit void setDetector(int det) { mDetector = ((mDetector & 0xf000) | (det & 0xfff)); } void setADC(ArrayADC const& adc) { mADC = adc; } void setADC(const gsl::span& adc) { std::copy(adc.begin(), adc.end(), mADC.begin()); } - void setPreTrigPhase(int phase) { mDetector = (((phase & 0xf) << 12) | (mDetector & 0xfff)); } + // set the trigger phase make sure it is mapped to 2 bits as it can only have 4 valid numbers shifted 0,3,6,9 or 1,4,7,10 etc. + void setPreTrigPhase(int phase); // Get methods int getDetector() const { return mDetector & 0xfff; } + int getDetectorInFull() const { return mDetector; } // return the entire mDetector 16 bits, so far only for CTF encoding. int getHCId() const { return (mDetector & 0xfff) * 2 + (mROB % 2); } int getPadRow() const { return HelperMethods::getPadRowFromMCM(mROB, mMCM); } int getPadCol() const { return HelperMethods::getPadColFromADC(mROB, mMCM, mChannel); } diff --git a/DataFormats/Detectors/TRD/include/DataFormatsTRD/PHData.h b/DataFormats/Detectors/TRD/include/DataFormatsTRD/PHData.h index b8873a5247d03..fc46ca0207993 100644 --- a/DataFormats/Detectors/TRD/include/DataFormatsTRD/PHData.h +++ b/DataFormats/Detectors/TRD/include/DataFormatsTRD/PHData.h @@ -61,6 +61,66 @@ class PHData ClassDefNV(PHData, 1); }; + +/* + This data type is used to send around the information required to fill PH plots per chamber + + |19|18|17|16|15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00| + ------------------------------------------------------------- + |type |nNeighb | time bin | detector number | + ------------------------------------------------------------- +*/ +/* + This data type is used to send around the information required to fill PH plots per chamber + + |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00| + ------------------------------------------------ + | ADC sum for all neigbours | + ------------------------------------------------ +*/ + +class PHDataHD +{ + public: + enum Origin : uint8_t { + ITSTPCTRD, + TPCTRD, + TRACKLET, + OTHER + }; + + PHDataHD() = default; + PHDataHD(int adc, int det, int tb, int nb, int type) { set(adc, det, tb, nb, type); } + + void set(int adc, int det, int tb, int nb, int type) + { + mDetector = det; + mTimeBin = tb; + mType = type; + mNNeighbours = nb; + mADC = adc; + } + + // the ADC sum for given time bin for up to three neighbours + int getADC() const { return mADC; } + // the TRD detector number + int getDetector() const { return mDetector; } + // the given time bin + int getTimebin() const { return mTimeBin; } + // number of neighbouring digits for which the ADC is accumulated + int getNNeighbours() const { return mNNeighbours; } + // the origin of this point: digit on ITS-TPC-TRD track, ... (see enum Origin above) + int getType() const { return mType; } + + private: + uint16_t mDetector{0}; + uint8_t mTimeBin{0}; + uint8_t mType{0}; + uint8_t mNNeighbours{0}; + uint16_t mADC{0}; + + ClassDefNV(PHDataHD, 1); +}; } // namespace o2::trd #endif // ALICEO2_TRD_PHDATA_H_ diff --git a/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h b/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h index 250a33b2c98e2..c6d36a7aee495 100644 --- a/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h +++ b/DataFormats/Detectors/TRD/src/DataFormatsTRDLinkDef.h @@ -43,6 +43,7 @@ #pragma link C++ class o2::trd::ChannelInfo + ; #pragma link C++ class o2::trd::ChannelInfoContainer + ; #pragma link C++ struct o2::trd::PHData + ; +#pragma link C++ struct o2::trd::PHDataHD + ; #pragma link C++ class o2::trd::TRDDataCountersPerTimeFrame + ; #pragma link C++ class o2::trd::DataCountersPerTrigger + ; #pragma link C++ class std::vector < o2::trd::Tracklet64> + ; @@ -56,6 +57,7 @@ #pragma link C++ class std::vector < o2::trd::GainCalibHistos> + ; #pragma link C++ class std::vector < o2::trd::T0FitHistos> + ; #pragma link C++ class std::vector < o2::trd::PHData> + ; +#pragma link C++ class std::vector < o2::trd::PHDataHD> + ; #pragma link C++ class std::vector < o2::trd::KrCluster> + ; #pragma link C++ class std::vector < o2::trd::KrClusterTriggerRecord> + ; #pragma link C++ class std::vector < o2::trd::DataCountersPerTrigger> + ; diff --git a/DataFormats/Detectors/TRD/src/Digit.cxx b/DataFormats/Detectors/TRD/src/Digit.cxx index 9e94fe22068bb..37d6638ac0996 100644 --- a/DataFormats/Detectors/TRD/src/Digit.cxx +++ b/DataFormats/Detectors/TRD/src/Digit.cxx @@ -12,6 +12,7 @@ #include "DataFormatsTRD/Digit.h" #include #include +#include "fairlogger/Logger.h" namespace o2::trd { @@ -46,12 +47,18 @@ Digit::Digit(int det, int rob, int mcm, int channel, ArrayADC adc, int pretrigph setPreTrigPhase(pretrigphase); } -Digit::Digit(int det, int rob, int mcm, int channel) // add adc data in a seperate step +Digit::Digit(int det, int rob, int mcm, int channel, int pretrigphase) // add adc data in a seperate step { setDetector(det); setROB(rob); setMCM(mcm); setChannel(channel); + setPreTrigPhase(pretrigphase); +} + +void Digit::setPreTrigPhase(int phase) +{ + mDetector = ((((phase) & 0x3) << 12) | (mDetector & 0xfff)); } bool Digit::isSharedDigit() const diff --git a/Detectors/TRD/calibration/include/TRDCalibration/PulseHeight.h b/Detectors/TRD/calibration/include/TRDCalibration/PulseHeight.h index 3fc70603da7d5..52305cc585b34 100644 --- a/Detectors/TRD/calibration/include/TRDCalibration/PulseHeight.h +++ b/Detectors/TRD/calibration/include/TRDCalibration/PulseHeight.h @@ -61,6 +61,7 @@ class PulseHeight /// Access to output const std::vector& getPHData() { return mPHValues; } + const std::vector& getPHDataHD() { return mPHValuesHD; } void createOutputFile(); void closeOutputFile(); @@ -77,6 +78,7 @@ class PulseHeight // output std::vector mPHValues, *mPHValuesPtr{&mPHValues}; ///< vector of values used to fill the PH spectra per detector + std::vector mPHValuesHD, *mPHValuesHDPtr{&mPHValuesHD}; ///< vector of values used to fill the High definition PH spectra per detector with pretrigger phase std::vector mDistances, *mDistancesPtr{&mDistances}; ///< pad distance between tracklet column and digit ADC maximum std::unique_ptr mOutFile{nullptr}; ///< output file std::unique_ptr mOutTree{nullptr}; ///< output tree diff --git a/Detectors/TRD/calibration/src/PulseHeight.cxx b/Detectors/TRD/calibration/src/PulseHeight.cxx index 1981fe528f0f5..44446d40df438 100644 --- a/Detectors/TRD/calibration/src/PulseHeight.cxx +++ b/Detectors/TRD/calibration/src/PulseHeight.cxx @@ -23,6 +23,7 @@ using namespace o2::trd::constants; void PulseHeight::reset() { mPHValues.clear(); + mPHValuesHD.clear(); mDistances.clear(); } @@ -39,6 +40,7 @@ void PulseHeight::createOutputFile() } mOutTree = std::make_unique("ph", "Data points for PH histograms"); mOutTree->Branch("values", &mPHValuesPtr); + mOutTree->Branch("valuesHD", &mPHValuesHDPtr); mOutTree->Branch("dist", &mDistancesPtr); mWriteOutput = true; LOG(info) << "Writing PH data points to local file trd_PH.root"; @@ -178,13 +180,17 @@ void PulseHeight::findDigitsForTracklet(const Tracklet64& trklt, const TriggerRe mDistances.push_back(digitTrackletDistance); for (int iTb = 0; iTb < TIMEBINS; ++iTb) { uint16_t phVal = digit.getADC()[iTb]; + uint16_t phValHD = (digit.getADC()[iTb] << 2) + digit.getPreTrigPhase(); if (left) { phVal += digitLeft->getADC()[iTb]; + phValHD += (digitLeft->getADC()[iTb] << 2) + digit.getPreTrigPhase(); } if (right) { phVal += digitRight->getADC()[iTb]; + phValHD += (digitRight->getADC()[iTb] << 2) + digit.getPreTrigPhase(); } mPHValues.emplace_back(phVal, trkltDet, iTb, nNeighbours, type); + mPHValuesHD.emplace_back(phValHD, trkltDet, iTb, nNeighbours, type); } } } diff --git a/Detectors/TRD/qc/src/RawDataManager.cxx b/Detectors/TRD/qc/src/RawDataManager.cxx index 1add53cae12ac..c53cd434e6b7b 100644 --- a/Detectors/TRD/qc/src/RawDataManager.cxx +++ b/Detectors/TRD/qc/src/RawDataManager.cxx @@ -23,6 +23,8 @@ #include #include +#include +#include using namespace o2::trd; diff --git a/Detectors/TRD/reconstruction/include/TRDReconstruction/CTFCoder.h b/Detectors/TRD/reconstruction/include/TRDReconstruction/CTFCoder.h index 107a05a397c00..27e089fcf3555 100644 --- a/Detectors/TRD/reconstruction/include/TRDReconstruction/CTFCoder.h +++ b/Detectors/TRD/reconstruction/include/TRDReconstruction/CTFCoder.h @@ -259,8 +259,8 @@ o2::ctf::CTFIOSize CTFCoder::decode(const CTF::base& ec, VTRG& trigVec, VTRK& tr uint32_t firstEntryDig = digVec.size(); int16_t cid = 0; for (uint32_t id = 0; id < entriesDig[itrig]; id++) { - cid += CIDDig[digCount]; // 1st digit of trigger was encoded with abs CID, then increments - auto& dig = digVec.emplace_back(cid, ROBDig[digCount], MCMDig[digCount], chanDig[digCount]); + cid += CIDDig[digCount]; // as cid has phase, its stored fully not // 1st digit of trigger was encoded with abs CID, then increments + auto& dig = digVec.emplace_back(cid & 0xfff, ROBDig[digCount], MCMDig[digCount], chanDig[digCount], (cid >> 12) & 0x3); dig.setADC({&ADCDig[adcCount], constants::TIMEBINS}); digCount++; adcCount += constants::TIMEBINS; diff --git a/Detectors/TRD/reconstruction/include/TRDReconstruction/CTFHelper.h b/Detectors/TRD/reconstruction/include/TRDReconstruction/CTFHelper.h index 316f2c8a5c7f0..bb41ea9658c9d 100644 --- a/Detectors/TRD/reconstruction/include/TRDReconstruction/CTFHelper.h +++ b/Detectors/TRD/reconstruction/include/TRDReconstruction/CTFHelper.h @@ -288,12 +288,12 @@ class CTFHelper // assume sorting in CID: for the 1st digit of the trigger return the abs CID, for the following ones: difference to previous CID value_type operator*() const { - return (*mTrigStart)[mIndex] ? mData[mIndex].getDetector() : mData[mIndex].getDetector() - mData[mIndex - 1].getDetector(); + return (*mTrigStart)[mIndex] ? mData[mIndex].getDetectorInFull() : mData[mIndex].getDetectorInFull() - mData[mIndex - 1].getDetectorInFull(); } value_type operator[](difference_type i) const { size_t id = mIndex + i; - return (*mTrigStart)[id] ? mData[id].getDetector() : mData[id].getDetector() - mData[id - 1].getDetector(); + return (*mTrigStart)[id] ? mData[id].getDetectorInFull() : mData[id].getDetectorInFull() - mData[id - 1].getDetectorInFull(); } }; diff --git a/Detectors/TRD/reconstruction/src/CruRawReader.cxx b/Detectors/TRD/reconstruction/src/CruRawReader.cxx index b4a37956759b9..05666691370db 100644 --- a/Detectors/TRD/reconstruction/src/CruRawReader.cxx +++ b/Detectors/TRD/reconstruction/src/CruRawReader.cxx @@ -301,6 +301,9 @@ bool CruRawReader::parseDigitHCHeaders(int hcid) DigitHCHeader1 header1; header1.word = headers[headerwordcount]; mPreTriggerPhase = header1.ptrigphase; + mPreTriggerPhase &= 0x0f; + mPreTriggerPhase /= 3; // remove the "gaps" in the pre trigger phase, so we dont have to sort it out later. + LOGP(debug, "Found pretrigger phase of Phase:{:x}", mPreTriggerPhase); headersfound.set(0); if ((header1.numtimebins > TIMEBINS) || (header1.numtimebins < 3) || mTimeBinsFixed && header1.numtimebins != mTimeBins) { @@ -802,6 +805,7 @@ int CruRawReader::parseDigitLinkData(int maxWords32, int hcid, int& wordsRejecte if (exitChannelLoop) { break; } + LOGP(debug, "Adding digit to event record det: {} rob: {} mcm: {} channel: {} Phase:{:x}", hcid / 2, (int)mcmHeader.rob, (int)mcmHeader.mcm, iChannel, mPreTriggerPhase); mEventRecords.getCurrentEventRecord().addDigit(Digit(hcid / 2, (int)mcmHeader.rob, (int)mcmHeader.mcm, iChannel, adcValues, mPreTriggerPhase)); ++mDigitsFound; } // end active channel diff --git a/Detectors/TRD/workflow/include/TRDWorkflow/TRDPulseHeightSpec.h b/Detectors/TRD/workflow/include/TRDWorkflow/TRDPulseHeightSpec.h index 536353c7a9e90..3cfbb16644e54 100644 --- a/Detectors/TRD/workflow/include/TRDWorkflow/TRDPulseHeightSpec.h +++ b/Detectors/TRD/workflow/include/TRDWorkflow/TRDPulseHeightSpec.h @@ -58,6 +58,8 @@ class PuseHeightDevice : public o2::framework::Task if (mRunStopRequested) { std::vector mPHValues{}; // the calibration expects data at every TF, so inject dummy pc.outputs().snapshot(Output{"TRD", "PULSEHEIGHT", 0}, mPHValues); + std::vector mPHValuesHD{}; // the calibration expects data at every TF, so inject dummy + pc.outputs().snapshot(Output{"TRD", "PULSEHEIGHTHD", 0}, mPHValuesHD); return; } RecoContainer recoData;