diff --git a/Detectors/MUON/MCH/DigitFiltering/CMakeLists.txt b/Detectors/MUON/MCH/DigitFiltering/CMakeLists.txt index f6d7fbd03701d..14e920debd441 100644 --- a/Detectors/MUON/MCH/DigitFiltering/CMakeLists.txt +++ b/Detectors/MUON/MCH/DigitFiltering/CMakeLists.txt @@ -13,6 +13,8 @@ o2_add_library(MCHDigitFiltering SOURCES src/DigitFilter.cxx src/DigitFilterParam.cxx + src/DigitModifier.cxx + src/DigitModifierParam.cxx src/DigitFilteringSpec.cxx PUBLIC_LINK_LIBRARIES O2::Framework @@ -27,4 +29,4 @@ o2_add_executable( COMPONENT_NAME mch PUBLIC_LINK_LIBRARIES O2::MCHDigitFiltering) -o2_target_root_dictionary(MCHDigitFiltering HEADERS include/MCHDigitFiltering/DigitFilterParam.h) +o2_target_root_dictionary(MCHDigitFiltering HEADERS include/MCHDigitFiltering/DigitFilterParam.h include/MCHDigitFiltering/DigitModifierParam.h) diff --git a/Detectors/MUON/MCH/DigitFiltering/include/MCHDigitFiltering/DigitModifier.h b/Detectors/MUON/MCH/DigitFiltering/include/MCHDigitFiltering/DigitModifier.h new file mode 100644 index 0000000000000..0177ea134ab1d --- /dev/null +++ b/Detectors/MUON/MCH/DigitFiltering/include/MCHDigitFiltering/DigitModifier.h @@ -0,0 +1,28 @@ +// 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. + +#ifndef O2_MCH_DIGITFILTERING_DIGITMODIFIER_H_ +#define O2_MCH_DIGITFILTERING_DIGITMODIFIER_H_ + +#include "DataFormatsMCH/Digit.h" +#include + +namespace o2::mch +{ +typedef std::function DigitModifier; + +DigitModifier createDigitModifier(int runNumber, + bool updateST1, + bool updateST2); + +} // namespace o2::mch + +#endif diff --git a/Detectors/MUON/MCH/DigitFiltering/include/MCHDigitFiltering/DigitModifierParam.h b/Detectors/MUON/MCH/DigitFiltering/include/MCHDigitFiltering/DigitModifierParam.h new file mode 100644 index 0000000000000..dc95396835f33 --- /dev/null +++ b/Detectors/MUON/MCH/DigitFiltering/include/MCHDigitFiltering/DigitModifierParam.h @@ -0,0 +1,35 @@ +// 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. + +#ifndef O2_MCH_DIGITFILTERING_DIGIT_MODIFIER_PARAM_H_ +#define O2_MCH_DIGITFILTERING_DIGIT_MODIFIER_PARAM_H_ + +#include "CommonUtils/ConfigurableParam.h" +#include "CommonUtils/ConfigurableParamHelper.h" + +namespace o2::mch +{ + +/** + * @class DigitModifierParam + * @brief Configurable parameters for the digit updating + */ +struct DigitModifierParam : public o2::conf::ConfigurableParamHelper { + + bool updateST1 = false; ///< whether or not to modify ST1 digits + bool updateST2 = false; ///< whether or not to modify ST2 digits + + O2ParamDef(DigitModifierParam, "MCHDigitModifier"); +}; + +} // namespace o2::mch + +#endif diff --git a/Detectors/MUON/MCH/DigitFiltering/src/DigitFilteringSpec.cxx b/Detectors/MUON/MCH/DigitFiltering/src/DigitFilteringSpec.cxx index fe40659bc9265..f43b04369bc6e 100644 --- a/Detectors/MUON/MCH/DigitFiltering/src/DigitFilteringSpec.cxx +++ b/Detectors/MUON/MCH/DigitFiltering/src/DigitFilteringSpec.cxx @@ -23,6 +23,8 @@ #include "MCHStatus/StatusMap.h" #include "MCHDigitFiltering/DigitFilter.h" #include "MCHDigitFiltering/DigitFilterParam.h" +#include "MCHDigitFiltering/DigitModifier.h" +#include "MCHDigitFiltering/DigitModifierParam.h" #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" #include @@ -48,6 +50,10 @@ class DigitFilteringTask mRejectBackground = DigitFilterParam::Instance().rejectBackground; mStatusMask = DigitFilterParam::Instance().statusMask; mTimeCalib = DigitFilterParam::Instance().timeOffset; + + mUpdateDigitsST1 = DigitModifierParam::Instance().updateST1; + mUpdateDigitsST2 = DigitModifierParam::Instance().updateST2; + auto stop = [this]() { LOG(info) << "digit filtering duration = " << std::chrono::duration(mElapsedTime).count() << " ms"; @@ -82,6 +88,11 @@ class DigitFilteringTask auto tStart = std::chrono::high_resolution_clock::now(); + const auto& tinfo = pc.services().get(); + if (tinfo.runNumber != 0) { + mRunNumber = tinfo.runNumber; + } + if (mSanityCheck) { LOGP(info, "performing sanity checks"); auto error = sanityCheck(iRofs, iDigits); @@ -101,8 +112,12 @@ class DigitFilteringTask auto oLabels = mUseMC ? &pc.outputs().make>(OutputRef{"labels"}) : nullptr; if (!abort) { - bool selectSignal = false; + mDigitModifier = createDigitModifier(mRunNumber, + mUpdateDigitsST1, + mUpdateDigitsST2); + + bool selectSignal = false; mIsGoodDigit = createDigitFilter(mMinADC, mRejectBackground, selectSignal, @@ -114,20 +129,29 @@ class DigitFilteringTask // the clustering resolution will suffer. // That's why we only apply the "reject background" filter, which // is a loose background cut that does not penalize the signal + int cursor{0}; for (const auto& irof : iRofs) { const auto digits = iDigits.subspan(irof.getFirstIdx(), irof.getNEntries()); // filter the digits from the current ROF for (auto i = 0; i < digits.size(); i++) { - const auto& d = digits[i]; - if (mIsGoodDigit(d)) { - oDigits.emplace_back(d); + auto digit = digits[i]; + + // modify the digit if needed + if (mDigitModifier) { + mDigitModifier(digit); + } + + // check the digit quality + if (mIsGoodDigit(digit)) { + oDigits.emplace_back(digit); if (iLabels) { oLabels->addElements(oLabels->getIndexedSize(), iLabels->getLabels(i + irof.getFirstIdx())); } } } + int nofGoodDigits = oDigits.size() - cursor; if (nofGoodDigits > 0) { // we create an ouput ROF only if at least one digit from @@ -160,6 +184,7 @@ class DigitFilteringTask } private: + int mRunNumber{0}; bool mRejectBackground{false}; bool mSanityCheck{false}; bool mUseMC{false}; @@ -167,7 +192,10 @@ class DigitFilteringTask int mMinADC{1}; int32_t mTimeCalib{0}; uint32_t mStatusMask{0}; + bool mUpdateDigitsST1{false}; + bool mUpdateDigitsST2{false}; DigitFilter mIsGoodDigit; + DigitModifier mDigitModifier; std::chrono::duration mElapsedTime{}; }; diff --git a/Detectors/MUON/MCH/DigitFiltering/src/DigitModifier.cxx b/Detectors/MUON/MCH/DigitFiltering/src/DigitModifier.cxx new file mode 100644 index 0000000000000..b2a46bc448aff --- /dev/null +++ b/Detectors/MUON/MCH/DigitFiltering/src/DigitModifier.cxx @@ -0,0 +1,154 @@ +// 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. + +#include "MCHDigitFiltering/DigitModifier.h" + +#include "DataFormatsMCH/Digit.h" +#include "MCHRawElecMap/Mapper.h" +#include "MCHMappingInterface/Segmentation.h" +#include +#include +#include + +namespace +{ + +o2::mch::DigitModifier createST1MappingCorrector(int /*runNumber*/) +{ + return {}; +} + +/** initialization of the pad remapping table for Station 2 DEs + */ +void initST2PadsRemappingTable(std::unordered_map>& padsRemapping) +{ + // Remapping of ST2 DS boards near the rounded part + { + std::array deToRemap{300, 301, 302, 303, 400, 401, 402, 403}; + std::array dsToRemap{99, 100, 101, 102, 103}; + + for (auto deId : deToRemap) { + + const o2::mch::mapping::Segmentation& segment = o2::mch::mapping::segmentation(deId); + for (auto dsId : dsToRemap) { + // double loop on DS channels + // 1. find the minimum pad index of the DS board + int padIdMin = -1; + int channelForPadIdMin = -1; + for (int channel = 0; channel < 64; channel++) { + auto padId = segment.findPadByFEE(dsId, int(channel)); + if (padId < 0) { + // skip non-connected channels + // this should never occur in this specific case, should we rise an exception instead? + continue; + } + if (padIdMin < 0 || padId < padIdMin) { + padIdMin = padId; + channelForPadIdMin = channel; + } + } + + // 2. build the re-mapping table + for (int channel = 0; channel < 64; channel++) { + auto padId = segment.findPadByFEE(dsId, int(channel)); + if (padId < padIdMin) { + // something is wrong here... + continue; + } + int padIdInDS = padId - padIdMin; + int padColumn = padIdInDS / 16; + int padRow = padIdInDS % 16; + + int padIdRemapped = -1; + + switch (padColumn) { + case 0: + // shift right by 3 columns + padIdRemapped = padId + 16 * 3; + break; + case 1: + // shift right by 1 column + padIdRemapped = padId + 16; + break; + case 2: + // shift left by 1 column + padIdRemapped = padId - 16; + break; + case 3: + // shift left by 3 columns + padIdRemapped = padId - 16 * 3; + break; + } + + padsRemapping[deId][padId] = padIdRemapped; + } + } + } + } +} + +o2::mch::DigitModifier createST2MappingCorrector(int runNumber) +{ + constexpr int lastRunToBeFixed = 560402; + // ST2 mapping needs to be corrected only for data collected up to the end of 2024 Pb-Pb + if (runNumber > lastRunToBeFixed) { + // do not modify digits collected after 2024 Pb-Pb + return {}; + } + + static std::unordered_map> padsRemapping; + + if (padsRemapping.empty()) { + initST2PadsRemappingTable(padsRemapping); + } + + return [](o2::mch::Digit& digit) { + // check if the current DE needs some remapping + auto padsRemappingForDe = padsRemapping.find(digit.getDetID()); + if (padsRemappingForDe != padsRemapping.end()) { + // check if the current padID needs to be remapped + auto padIDRemapped = padsRemappingForDe->second.find(digit.getPadID()); + if (padIDRemapped != padsRemappingForDe->second.end()) { + // update the digit + digit.setPadID(padIDRemapped->second); + } + } + }; +} +} // namespace + +namespace o2::mch +{ +DigitModifier createDigitModifier(int runNumber, + bool updateST1, + bool updateST2) +{ + DigitModifier modifierST1 = updateST1 ? createST1MappingCorrector(runNumber) : DigitModifier{}; + DigitModifier modifierST2 = updateST2 ? createST2MappingCorrector(runNumber) : DigitModifier{}; + + if (modifierST1 || modifierST2) { + return [modifierST1, modifierST2](Digit& digit) { + // the ST1/ST2 modifiers are mutually exclusive, depending on the DeID associated to the digit + auto detID = digit.getDetID(); + if (modifierST1 && detID >= 100 && detID < 300) { + modifierST1(digit); + } + if (modifierST2 && detID >= 300 && detID < 500) { + modifierST2(digit); + } + }; + } else { + // return an empty function if none of the modifiers is set + return {}; + } +} + +} // namespace o2::mch diff --git a/Detectors/MUON/MCH/DigitFiltering/src/DigitModifierParam.cxx b/Detectors/MUON/MCH/DigitFiltering/src/DigitModifierParam.cxx new file mode 100644 index 0000000000000..c10a8a87d6bd7 --- /dev/null +++ b/Detectors/MUON/MCH/DigitFiltering/src/DigitModifierParam.cxx @@ -0,0 +1,15 @@ +// 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. + +#include "MCHDigitFiltering/DigitModifierParam.h" +#include "CommonUtils/ConfigurableParam.h" + +O2ParamImpl(o2::mch::DigitModifierParam) diff --git a/Detectors/MUON/MCH/DigitFiltering/src/MCHDigitFilteringLinkDef.h b/Detectors/MUON/MCH/DigitFiltering/src/MCHDigitFilteringLinkDef.h index 1182d37654c37..c4de20393fbe0 100644 --- a/Detectors/MUON/MCH/DigitFiltering/src/MCHDigitFilteringLinkDef.h +++ b/Detectors/MUON/MCH/DigitFiltering/src/MCHDigitFilteringLinkDef.h @@ -18,4 +18,7 @@ #pragma link C++ class o2::mch::DigitFilterParam + ; #pragma link C++ class o2::conf::ConfigurableParamHelper < o2::mch::DigitFilterParam> + ; +#pragma link C++ class o2::mch::DigitModifierParam + ; +#pragma link C++ class o2::conf::ConfigurableParamHelper < o2::mch::DigitModifierParam> + ; + #endif