diff --git a/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/include/DataFormatsIOTOF/Digit.h b/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/include/DataFormatsIOTOF/Digit.h index f1e31b57c6f54..d7af3c1872606 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/include/DataFormatsIOTOF/Digit.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/DataFormatsIOTOF/include/DataFormatsIOTOF/Digit.h @@ -25,6 +25,19 @@ namespace o2::iotof { +struct DigitKey { + ULong64_t high; + UInt_t low; + + bool operator<(const DigitKey& other) const + { + if (high != other.high) { + return high < other.high; + } + return low < other.low; + } +}; + class Digit : public o2::itsmft::Digit { public: @@ -40,11 +53,14 @@ class Digit : public o2::itsmft::Digit ULong64_t getBc() const { return mBc; } Int_t getTdc() const { return mTdc; } - static ULong64_t getOrderingKey(ULong64_t bc, UShort_t row, UShort_t col) + static DigitKey getOrderingKey(ULong64_t bc, UInt_t tdc, uint16_t row, uint16_t col) { + DigitKey key; uint32_t orbit = bc / o2::constants::lhc::LHCMaxBunches; uint16_t bunch = bc % o2::constants::lhc::LHCMaxBunches; - return (static_cast(orbit) << 32) | (static_cast(bunch) << 16) | (static_cast(row) << 8) | static_cast(col); + key.high = (static_cast(orbit) << 32) | (static_cast(bunch) << 16) | (static_cast(tdc) & 0xFFFF); + key.low = (static_cast(row) << 16) | (static_cast(col) & 0xFFFF); + return key; } private: diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Chip.h b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Chip.h index 8e2f2915a2ec5..1849907d6e071 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Chip.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/Chip.h @@ -60,7 +60,7 @@ class Chip /// @param option unused void clear() { mDigits.clear(); } - std::map& getDigits() { return mDigits; } + std::map& getDigits() { return mDigits; } bool isEmpty() const { return mDigits.empty(); } void setChipIndex(Int_t index) { mChipIndex = index; } @@ -74,19 +74,24 @@ class Chip Int_t getNumberOfDigits() const { return mDigits.size(); } /// reset points container - o2::iotof::LabeledDigit* findDigit(ULong64_t key); + o2::iotof::LabeledDigit* findDigit(DigitKey key); + + /// Resize the vector of tdc states + void resizeTDCStates(int const size) { mTDCStates.resize(size); } + std::vector>& getTDCStates() { return mTDCStates; } void addDigit(UShort_t row, UShort_t col, Int_t charge, double time, ULong64_t bc, Int_t tdc, o2::MCCompLabel label); protected: Int_t mChipIndex = -1; ///< Chip ID bool mDisabled = false; ///< Flag to indicate if the chip is disabled (e.g. due to dead channels) - std::map mDigits; ///< Map of fired digits, possibly in multiple frames + std::map mDigits; ///< Map of fired digits, possibly in multiple frames + std::vector> mTDCStates; ///< Vector of the last times the TDC pairs went busy ClassDefNV(Chip, 1); }; -inline o2::iotof::LabeledDigit* Chip::findDigit(ULong64_t key) +inline o2::iotof::LabeledDigit* Chip::findDigit(DigitKey key) { // finds the digit corresponding to global key auto digitentry = mDigits.find(key); diff --git a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h index 7f96b8e509d0c..3d2ed2c995c30 100644 --- a/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h +++ b/Detectors/Upgrades/ALICE3/IOTOF/simulation/include/IOTOFSimulation/DPLDigitizerParam.h @@ -38,6 +38,9 @@ struct DPLDigitizerParam : public o2::conf::ConfigurableParamHelpergetSize(); mChips.resize(numberOfChips); + + const auto& specsConfig = ChipSpecificsParam::Instance(); + const auto& digitizerParams = o2::iotof::DPLDigitizerParam::Instance(); + const int nReadOutCols = specsConfig.NCols / digitizerParams.nColsPerGroup + 1; for (int i = numberOfChips; i--;) { mChips[i].setChipIndex(i); /// Noise map to be implemented @@ -53,9 +57,15 @@ void Digitizer::init() /// mChips[i].disable(mDeadChanMap->isFullChipMasked(i)); /// mChips[i].setDeadChanMap(mDeadChanMap); /// } + + // initialize the vector of TDC states + mChips[i].resizeTDCStates(nReadOutCols); + for (auto& tdcStates : mChips[i].getTDCStates()) { + tdcStates[0] = -999.f; + tdcStates[1] = -999.f; + } } - const auto& digitizerParams = o2::iotof::DPLDigitizerParam::Instance(); if (!digitizerParams.efficiencyFilePath.empty()) { loadEfficiencyMap(digitizerParams.efficiencyFilePath); } @@ -135,7 +145,6 @@ void Digitizer::processHit(const o2::itsmft::Hit& hit, int evID, int srcID) double hitTime = hit.GetTime() * sec2ns; // convert to ns double eventTimeInBC = mEventTime.getTimeOffsetWrtBC(); // event time wrt bc double hitTimeWrtBC = hitTime + eventTimeInBC; // hit time wrt bc - double smearedTime = smearTime(hitTimeWrtBC); // Create the digit with time information o2::MCCompLabel label(hit.GetTrackID(), evID, srcID, false); @@ -168,6 +177,8 @@ void Digitizer::processHit(const o2::itsmft::Hit& hit, int evID, int srcID) const int nElectronsSampled = gRandom->Poisson(electronsPerStep * nEleResp); // Noise can be added here if needed + double smearedTime = smearTime(hitTimeWrtBC); + registerDigits(chip, roFrameAbs, smearedTime, nROF, static_cast(rowIS), static_cast(colIS), nElectronsSampled, label); } @@ -195,7 +206,6 @@ void Digitizer::stepping(const o2::itsmft::Hit& hit, float**& respMatrix, float* const auto& digitizerParams = o2::iotof::DPLDigitizerParam::Instance(); auto stepVector = (xyzPositionEnd - xyzPositionStart) / digitizerParams.nSimSteps; xyzPositionStart = xyzPositionStart + stepVector * 0.5f; // center the start position in the middle of the step - xyzPositionEnd = xyzPositionEnd - stepVector * 0.5f; // center the end position in the middle of the step rowStart = -1; colStart = -1; @@ -404,12 +414,25 @@ void Digitizer::fillOutputContainer() } auto& chipDigits = chip.getDigits(); + auto& tdcStates = chip.getTDCStates(); + for (const auto& [key, digit] : chipDigits) { if (digit.getCharge() < digitizerParams.chargeThreshold) { continue; // skip digits below threshold } + const int colInGroup = digit.getColumn() / digitizerParams.nColsPerGroup; + const double digitTime = digit.getTime(); + if (digitTime - tdcStates[colInGroup][0] < digitizerParams.tdcBusyTime && digitTime - tdcStates[colInGroup][1] < digitizerParams.tdcBusyTime) { + // TODO: improve labels treatment if multiple hits cross the same pixel during + continue; // both tdc pairs are busy + } else if (digitTime - tdcStates[colInGroup][0] > digitizerParams.tdcBusyTime) { + tdcStates[colInGroup][0] = digitTime; + } else if (digitTime - tdcStates[colInGroup][1] > digitizerParams.tdcBusyTime) { + tdcStates[colInGroup][1] = digitTime; + } + int digitID = mDigits->size(); mDigits->emplace_back(digit.getChipIndex(), digit.getRow(), digit.getColumn(), digit.getCharge(), digit.getTime(), digit.getBc(), digit.getTdc()); if (mMCLabels) { @@ -438,7 +461,7 @@ void Digitizer::fillOutputContainer() void Digitizer::registerDigits(Chip& chip, uint32_t roFrame, double time, int nROF, uint16_t row, uint16_t col, int nElectrons, o2::MCCompLabel& label) { - (void)nROF; + // (void)nROF; const auto& digitizerParams = o2::iotof::DPLDigitizerParam::Instance(); @@ -446,10 +469,13 @@ void Digitizer::registerDigits(Chip& chip, uint32_t roFrame, double time, int nR int tdc = int((time - nbc * o2::constants::lhc::LHCBunchSpacingNS) / digitizerParams.tdcBin); nbc += mEventTime.toLong(); - double absoluteTime = tdc * digitizerParams.tdcBin * 1.e-9 + nbc * o2::constants::lhc::LHCBunchSpacingNS; + double absoluteTime = tdc * digitizerParams.tdcBin + nbc * o2::constants::lhc::LHCBunchSpacingNS; - auto key = o2::iotof::Digit::getOrderingKey(nbc, row, col); + auto key = o2::iotof::Digit::getOrderingKey(nbc, tdc, row, col); o2::iotof::LabeledDigit* existingDigit = chip.findDigit(key); + + chip.addDigit(row, col, nElectrons, absoluteTime, nbc, tdc, label); + if (!existingDigit) { // No existing digit, create a new one chip.addDigit(row, col, nElectrons, absoluteTime, nbc, tdc, label);