diff --git a/DataFormats/Detectors/Upgrades/ALICE3/TRKFT3/common/include/DataFormatsTRKFT3/Digit.h b/DataFormats/Detectors/Upgrades/ALICE3/TRKFT3/common/include/DataFormatsTRKFT3/Digit.h index 41aa774a2ea06..cefadca6b266f 100644 --- a/DataFormats/Detectors/Upgrades/ALICE3/TRKFT3/common/include/DataFormatsTRKFT3/Digit.h +++ b/DataFormats/Detectors/Upgrades/ALICE3/TRKFT3/common/include/DataFormatsTRKFT3/Digit.h @@ -22,13 +22,14 @@ namespace o2::trkft3 class Digit { public: - Digit(UShort_t chipindex = 0, UShort_t row = 0, UShort_t col = 0, Int_t charge = 0); + Digit(UShort_t chipindex = 0, UShort_t row = 0, UShort_t col = 0, Int_t charge = 0, float toa = 0); ~Digit() = default; UShort_t getChipIndex() const { return mChipIndex; } UShort_t getColumn() const { return mCol; } UShort_t getRow() const { return mRow; } Int_t getCharge() const { return mCharge; } + float getTimeOfArrival() const { return mToA; } void setChipIndex(UShort_t index) { mChipIndex = index; } void setPixelIndex(UShort_t row, UShort_t col) @@ -38,6 +39,7 @@ class Digit } void setCharge(Int_t charge) { mCharge = charge < USHRT_MAX ? charge : USHRT_MAX; } void addCharge(int charge) { setCharge(charge + int(mCharge)); } + void setToA(float toa) { mToA = toa; } std::ostream& print(std::ostream& output) const; friend std::ostream& operator<<(std::ostream& output, const Digit& digi) @@ -51,8 +53,9 @@ class Digit UShort_t mRow = 0; UShort_t mCol = 0; UShort_t mCharge = 0; + float mToA = 0; // TimeOfArrival, set to float at the moment. TODO: implement correctly the size https://indico.cern.ch/event/1724141/contributions/7252329/attachments/3336751/5980668/data_throughput_estimation.pdf - ClassDefNV(Digit, 1); + ClassDefNV(Digit, 2); }; } // namespace o2::trkft3 diff --git a/DataFormats/Detectors/Upgrades/ALICE3/TRKFT3/common/src/Digit.cxx b/DataFormats/Detectors/Upgrades/ALICE3/TRKFT3/common/src/Digit.cxx index f01d98d1e005d..d339aa5df5f8d 100644 --- a/DataFormats/Detectors/Upgrades/ALICE3/TRKFT3/common/src/Digit.cxx +++ b/DataFormats/Detectors/Upgrades/ALICE3/TRKFT3/common/src/Digit.cxx @@ -16,14 +16,15 @@ ClassImp(o2::trkft3::Digit); using namespace o2::trkft3; -Digit::Digit(UShort_t chipindex, UShort_t row, UShort_t col, Int_t charge) +Digit::Digit(UShort_t chipindex, UShort_t row, UShort_t col, Int_t charge, float toa) : mChipIndex(chipindex), mRow(row), mCol(col) { setCharge(charge); + setToA(toa); } std::ostream& Digit::print(std::ostream& output) const { - output << "TRKFT3Digit chip [" << mChipIndex << "] R:" << mRow << " C:" << mCol << " Q: " << mCharge; + output << "TRKFT3Digit chip [" << mChipIndex << "] R:" << mRow << " C:" << mCol << " Q: " << mCharge << " ToA: " << mToA; return output; } diff --git a/Detectors/Upgrades/ALICE3/TRKFT3/common/simulation/CMakeLists.txt b/Detectors/Upgrades/ALICE3/TRKFT3/common/simulation/CMakeLists.txt index ce9b79217997e..df004fe5eef74 100644 --- a/Detectors/Upgrades/ALICE3/TRKFT3/common/simulation/CMakeLists.txt +++ b/Detectors/Upgrades/ALICE3/TRKFT3/common/simulation/CMakeLists.txt @@ -28,4 +28,5 @@ o2_target_root_dictionary(TRKFT3Simulation include/TRKFT3Simulation/DigiParams.h include/TRKFT3Simulation/Digitizer.h include/TRKFT3Simulation/DPLDigitizerParam.h + include/TRKFT3Simulation/PreDigit.h LINKDEF src/TRKFT3SimulationLinkDef.h) diff --git a/Detectors/Upgrades/ALICE3/TRKFT3/common/simulation/include/TRKFT3Simulation/ChipDigitsContainer.h b/Detectors/Upgrades/ALICE3/TRKFT3/common/simulation/include/TRKFT3Simulation/ChipDigitsContainer.h index 10c55e6163846..0fcbfd2591a0e 100644 --- a/Detectors/Upgrades/ALICE3/TRKFT3/common/simulation/include/TRKFT3Simulation/ChipDigitsContainer.h +++ b/Detectors/Upgrades/ALICE3/TRKFT3/common/simulation/include/TRKFT3Simulation/ChipDigitsContainer.h @@ -12,8 +12,9 @@ #ifndef ALICEO2_TRK_CHIPDIGITSCONTAINER_ #define ALICEO2_TRK_CHIPDIGITSCONTAINER_ -#include "ITSMFTBase/SegmentationAlpide.h" -#include "ITSMFTSimulation/ChipDigitsContainer.h" +#include "TRKFT3Simulation/PreDigit.h" +#include "SimulationDataFormat/MCCompLabel.h" +#include "DataFormatsITSMFT/NoiseMap.h" #include "TRKBase/SegmentationChip.h" #include "TRKBase/Specs.h" #include "TRKFT3Simulation/DigiParams.h" @@ -23,12 +24,29 @@ namespace o2::trkft3 { -class ChipDigitsContainer : public o2::itsmft::ChipDigitsContainer +/// @class ChipDigitsContainer +/// @brief Container for simulated points connected to a given chip + +class ChipDigitsContainer { public: + /// Default constructor explicit ChipDigitsContainer(UShort_t idx = 0); - using Segmentation = o2::trk::SegmentationChip; + /// Destructor + ~ChipDigitsContainer() = default; + + std::map& getPreDigits() { return mDigits; } + bool isEmpty() const { return mDigits.empty(); } + void setNoiseMap(const o2::itsmft::NoiseMap* mp) { mNoiseMap = mp; } + void setDeadChanMap(const o2::itsmft::NoiseMap* mp) { mDeadChanMap = mp; } + void setChipIndex(UShort_t ind) { mChipIndex = ind; } + UShort_t getChipIndex() const { return mChipIndex; } + + o2::trkft3::PreDigit* findDigit(ULong64_t key); + void addDigit(ULong64_t key, UInt_t roframe, UShort_t row, UShort_t col, int charge, o2::MCCompLabel lbl, float toa = 0.f); + template + void addNoise(UInt_t rofMin, UInt_t rofMax, const o2::trkft3::DigiParams* params, int subDetID, int layer); /// Get global ordering key made of readout frame, column and row static ULong64_t getOrderingKey(UInt_t roframe, UShort_t row, UShort_t col) @@ -36,14 +54,34 @@ class ChipDigitsContainer : public o2::itsmft::ChipDigitsContainer return (static_cast(roframe) << (8 * sizeof(UInt_t))) + (static_cast(col) << (8 * sizeof(Short_t))) + row; } - /// Adds noise digits, deleted the one using the itsmft::DigiParams interface - void addNoise(UInt_t rofMin, UInt_t rofMax, const o2::itsmft::DigiParams* params, int maxRows = o2::itsmft::SegmentationAlpide::NRows, int maxCols = o2::itsmft::SegmentationAlpide::NCols) = delete; - template - void addNoise(UInt_t rofMin, UInt_t rofMax, const o2::trkft3::DigiParams* params, int subDetID, int layer); + bool isDisabled() const { return mDisabled; } + void disable(bool v) { mDisabled = v; } - ClassDefNV(ChipDigitsContainer, 1); + protected: + UShort_t mChipIndex = 0; ///< chip index + bool mDisabled = false; + const o2::itsmft::NoiseMap* mNoiseMap = nullptr; + const o2::itsmft::NoiseMap* mDeadChanMap = nullptr; + std::map mDigits; ///< Map of fired pixels, possibly in multiple frames + + ClassDefNV(ChipDigitsContainer, 2); }; +//_______________________________________________________________________ +inline o2::trkft3::PreDigit* ChipDigitsContainer::findDigit(ULong64_t key) +{ + // finds the digit corresponding to global key + auto digitentry = mDigits.find(key); + return digitentry != mDigits.end() ? &(digitentry->second) : nullptr; +} + +//_______________________________________________________________________ +inline void ChipDigitsContainer::addDigit(ULong64_t key, UInt_t roframe, UShort_t row, UShort_t col, + int charge, o2::MCCompLabel lbl, float toa) +{ + mDigits.emplace(key, o2::trkft3::PreDigit(roframe, row, col, charge, lbl, toa)); +} + } // namespace o2::trkft3 template @@ -83,10 +121,10 @@ void o2::trkft3::ChipDigitsContainer::addNoise(UInt_t rofMin, UInt_t rofMax, con } auto key = getOrderingKey(rof, row, col); if (!findDigit(key)) { - addDigit(key, rof, row, col, nel, o2::MCCompLabel(true)); + addDigit(key, rof, row, col, nel, o2::MCCompLabel(true), 0.f); /// TODO: find a better ToA for noise } } } } -#endif // ALICEO2_TRK_CHIPDIGITSCONTAINER_ +#endif /* defined(ALICEO2_TRK_CHIPDIGITSCONTAINER_) */ diff --git a/Detectors/Upgrades/ALICE3/TRKFT3/common/simulation/include/TRKFT3Simulation/Digitizer.h b/Detectors/Upgrades/ALICE3/TRKFT3/common/simulation/include/TRKFT3Simulation/Digitizer.h index 22c61352c03ee..7b06df5601208 100644 --- a/Detectors/Upgrades/ALICE3/TRKFT3/common/simulation/include/TRKFT3Simulation/Digitizer.h +++ b/Detectors/Upgrades/ALICE3/TRKFT3/common/simulation/include/TRKFT3Simulation/Digitizer.h @@ -44,7 +44,7 @@ class Digitizer { static_assert(DetID == o2::detectors::DetID::TRK || DetID == o2::detectors::DetID::FT3, "only TRK and FT3 digitizers are supported"); using GeometryTGeo = std::conditional_t; - using ExtraDig = std::vector; ///< container for extra contributions to PreDigits + using ExtraDig = std::vector; ///< container for extra contributions to PreDigits public: void setDigits(std::vector* dig) { mDigits = dig; } @@ -94,7 +94,7 @@ class Digitizer private: void processHit(const o2::trkft3::Hit& hit, uint32_t& maxFr, int evID, int srcID, int rofLayer); - void registerDigits(o2::trkft3::ChipDigitsContainer& chip, uint32_t roFrame, float tInROF, int nROF, + void registerDigits(o2::trkft3::ChipDigitsContainer& chip, uint32_t roFrame, float toaInROF, int nROF, uint16_t row, uint16_t col, int nEle, o2::MCCompLabel& lbl, int layer); ExtraDig* getExtraDigBuffer(uint32_t roFrame) diff --git a/Detectors/Upgrades/ALICE3/TRKFT3/common/simulation/include/TRKFT3Simulation/PreDigit.h b/Detectors/Upgrades/ALICE3/TRKFT3/common/simulation/include/TRKFT3Simulation/PreDigit.h new file mode 100644 index 0000000000000..893496d41f9fe --- /dev/null +++ b/Detectors/Upgrades/ALICE3/TRKFT3/common/simulation/include/TRKFT3Simulation/PreDigit.h @@ -0,0 +1,52 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file PreDigit.h +/// \brief Definition of the digit contribution from single hit for TRK/FT3 (based on o2::itsmft::PreDigit, with time of arrival) +#ifndef ALICEO2_TRKFT3_PREDIGIT_H +#define ALICEO2_TRKFT3_PREDIGIT_H + +#include "SimulationDataFormat/MCCompLabel.h" + +namespace o2::trkft3 +{ + +// PreDigit is a contribution to the digit from a single hit which happen +// to be registered 1st in given chip row/column/roframe +// Eventual extra contributions will be registered as PreDigitExtra, pointed by +// the "next" index + +// PreDigitExtra registers additional contributions to the same row/column/roframe +struct PreDigitLabelRef { + o2::MCCompLabel label; ///< hit label + int next = -1; ///< eventual next contribution to the same pixel + PreDigitLabelRef(o2::MCCompLabel lbl = 0, int nxt = -1) : label(lbl), next(nxt) {} + + ClassDefNV(PreDigitLabelRef, 1); +}; + +struct PreDigit { + UShort_t row = 0; ///< Pixel index in X + UShort_t col = 0; ///< Pixel index in Z + UInt_t roFrame = 0; ///< Readout frame + int charge = 0; ///< N electrons + float toa = 0.f; ///< Time of arrival in ns (earliest contribution) + PreDigitLabelRef labelRef; ///< label and reference to the next one + + PreDigit(UInt_t rf = 0, UShort_t rw = 0, UShort_t cl = 0, int nele = 0, o2::MCCompLabel lbl = 0, float t = 0.f) + : row(rw), col(cl), roFrame(rf), charge(nele), toa(t), labelRef(lbl) {} + + ClassDefNV(PreDigit, 1); +}; + +} // namespace o2::trkft3 + +#endif /* ALICEO2_TRKFT3_PREDIGIT_H */ diff --git a/Detectors/Upgrades/ALICE3/TRKFT3/common/simulation/src/ChipDigitsContainer.cxx b/Detectors/Upgrades/ALICE3/TRKFT3/common/simulation/src/ChipDigitsContainer.cxx index 8917062923537..f01b3353e16ac 100644 --- a/Detectors/Upgrades/ALICE3/TRKFT3/common/simulation/src/ChipDigitsContainer.cxx +++ b/Detectors/Upgrades/ALICE3/TRKFT3/common/simulation/src/ChipDigitsContainer.cxx @@ -13,5 +13,4 @@ using namespace o2::trkft3; -ChipDigitsContainer::ChipDigitsContainer(UShort_t idx) - : o2::itsmft::ChipDigitsContainer(idx) {} +ChipDigitsContainer::ChipDigitsContainer(UShort_t idx) : mChipIndex(idx) {} diff --git a/Detectors/Upgrades/ALICE3/TRKFT3/common/simulation/src/Digitizer.cxx b/Detectors/Upgrades/ALICE3/TRKFT3/common/simulation/src/Digitizer.cxx index 5e8faca2830fe..493f321c765bc 100644 --- a/Detectors/Upgrades/ALICE3/TRKFT3/common/simulation/src/Digitizer.cxx +++ b/Detectors/Upgrades/ALICE3/TRKFT3/common/simulation/src/Digitizer.cxx @@ -226,8 +226,8 @@ void Digitizer::fillOutputContainer(uint32_t frameLast, int layer) auto& preDig = iter->second; // preDigit if (preDig.charge >= mParams.getChargeThreshold()) { int digID = mDigits->size(); - mDigits->emplace_back(chip.getChipIndex(), preDig.row, preDig.col, preDig.charge); - LOG(debug) << "Adding digit ID: " << digID << " with chipID: " << chip.getChipIndex() << ", row: " << preDig.row << ", col: " << preDig.col << ", charge: " << preDig.charge; + mDigits->emplace_back(chip.getChipIndex(), preDig.row, preDig.col, preDig.charge, preDig.toa); + LOG(debug) << "Adding digit ID: " << digID << " with chipID: " << chip.getChipIndex() << ", row: " << preDig.row << ", col: " << preDig.col << ", charge: " << preDig.charge << ", ToA: " << preDig.toa; mMCLabels->addElement(digID, preDig.labelRef.label); auto& nextRef = preDig.labelRef; // extra contributors are in extra array while (nextRef.next >= 0) { @@ -297,6 +297,9 @@ void Digitizer::processHit(const o2::trkft3::Hit& hit, uint32_t& maxFr, i float tTot = mParams.getSignalShape().getMaxDuration(); // frame of the hit signal start wrt event ROFrame int roFrameRel = int(timeInROF * mParams.getROFrameLengthInv(rofLayer)); + // Time of Arrival w.r.t. the start of the ROF where the signal starts (= w.r.t. roFrameAbs) + float toaInROF = timeInROF - roFrameRel * mParams.getROFrameLength(rofLayer); + // frame of the hit signal end wrt event ROFrame: in the triggered mode we read just 1 frame uint32_t roFrameRelMax = (timeInROF + tTot) * mParams.getROFrameLengthInv(rofLayer); int nFrames = roFrameRelMax + 1 - roFrameRel; @@ -493,24 +496,25 @@ void Digitizer::processHit(const o2::trkft3::Hit& hit, uint32_t& maxFr, i if (mDeadChanMap && mDeadChanMap->isNoisy(chipID, rowIS, colIS)) { continue; } - registerDigits(chip, roFrameAbs, timeInROF, nFrames, rowIS, colIS, nEle, lbl, rofLayer); + registerDigits(chip, roFrameAbs, toaInROF, nFrames, rowIS, colIS, nEle, lbl, rofLayer); } } } //________________________________________________________________________________ template -void Digitizer::registerDigits(o2::trkft3::ChipDigitsContainer& chip, uint32_t roFrame, float tInROF, int nROF, +void Digitizer::registerDigits(o2::trkft3::ChipDigitsContainer& chip, uint32_t roFrame, float toaInROF, int nROF, uint16_t row, uint16_t col, int nEle, o2::MCCompLabel& lbl, int layer) { // Register digits for given pixel, accounting for the possible signal contribution to - // multiple ROFrame. The signal starts at time tInROF wrt the start of provided roFrame + // multiple ROFrame. The signal starts at time toaInROF wrt the start of provided roFrame // In every ROFrame we check the collected signal during strobe LOG(debug) << "Registering digits for chip " << chip.getChipIndex() << " at ROFrame " << roFrame - << " row " << row << " col " << col << " nEle " << nEle << " label " << lbl; - float tStrobe = mParams.getStrobeDelay(layer) - tInROF; // strobe start wrt signal start - for (int i = 0; i < nROF; i++) { // loop on all the ROFs occupied by the same signal to calculate the charge accumulated in that ROF + << " row " << row << " col " << col << " nEle " << nEle << " label " << lbl << " layer " << layer << " toa " << toaInROF; + float tStrobe = mParams.getStrobeDelay(layer) - toaInROF; // strobe start wrt signal start + for (int i = 0; i < nROF; i++) { // loop on all the ROFs occupied by the same signal to calculate the charge accumulated in that ROF uint32_t roFr = roFrame + i; + float toaROF = toaInROF - i * mParams.getROFrameLength(layer); // ToA w.r.t. start of ROF int nEleROF = mParams.getSignalShape().getCollectedCharge(nEle, tStrobe, tStrobe + mParams.getStrobeLength(layer)); tStrobe += mParams.getROFrameLength(layer); // for the next ROF @@ -525,14 +529,15 @@ void Digitizer::registerDigits(o2::trkft3::ChipDigitsContainer& chip, uin mEventROFrameMin = roFr; } auto key = chip.getOrderingKey(roFr, row, col); - o2::itsmft::PreDigit* pd = chip.findDigit(key); + o2::trkft3::PreDigit* pd = chip.findDigit(key); if (!pd) { - chip.addDigit(key, roFr, row, col, nEleROF, lbl); + chip.addDigit(key, roFr, row, col, nEleROF, lbl, toaROF); LOG(debug) << "Added digit with key: " << key << " ROF: " << roFr << " row: " << row << " col: " << col << " charge: " << nEleROF; } else { // there is already a digit at this slot, account as PreDigitExtra contribution LOG(debug) << "Added to pre-digit with key: " << key << " ROF: " << roFr << " row: " << row << " col: " << col << " charge: " << nEleROF; pd->charge += nEleROF; - if (pd->labelRef.label == lbl) { // don't store the same label twice + pd->toa = std::min(pd->toa, toaROF); /// in case of two hits on the same digit in the same ROF, get the first ToA + if (pd->labelRef.label == lbl) { // don't store the same label twice continue; } ExtraDig* extra = getExtraDigBuffer(roFr); diff --git a/Detectors/Upgrades/ALICE3/TRKFT3/common/simulation/src/TRKFT3SimulationLinkDef.h b/Detectors/Upgrades/ALICE3/TRKFT3/common/simulation/src/TRKFT3SimulationLinkDef.h index e11378f471ec3..bb877ae83028c 100644 --- a/Detectors/Upgrades/ALICE3/TRKFT3/common/simulation/src/TRKFT3SimulationLinkDef.h +++ b/Detectors/Upgrades/ALICE3/TRKFT3/common/simulation/src/TRKFT3SimulationLinkDef.h @@ -23,5 +23,7 @@ #pragma link C++ class o2::conf::ConfigurableParamHelper < o2::trkft3::DPLDigitizerParam < o2::detectors::DetID::TRK>> + ; #pragma link C++ class o2::trkft3::DPLDigitizerParam < o2::detectors::DetID::FT3> + ; #pragma link C++ class o2::conf::ConfigurableParamHelper < o2::trkft3::DPLDigitizerParam < o2::detectors::DetID::FT3>> + ; +#pragma link C++ class o2::trkft3::PreDigit + ; +#pragma link C++ class o2::trkft3::PreDigitLabelRef + ; #endif