diff --git a/Detectors/TPC/reconstruction/CMakeLists.txt b/Detectors/TPC/reconstruction/CMakeLists.txt index 84d1304afc1cb..a22d9edf000b7 100644 --- a/Detectors/TPC/reconstruction/CMakeLists.txt +++ b/Detectors/TPC/reconstruction/CMakeLists.txt @@ -18,6 +18,7 @@ o2_add_library(TPCReconstruction src/HwClusterer.cxx src/HwClustererParam.cxx src/KrBoxClusterFinder.cxx + src/KrBoxClusterFinderParam.cxx src/RawReader.cxx src/RawReaderCRU.cxx src/RawReaderEventSync.cxx @@ -46,6 +47,7 @@ o2_target_root_dictionary( include/TPCReconstruction/HwClusterer.h include/TPCReconstruction/HwClustererParam.h include/TPCReconstruction/KrBoxClusterFinder.h + include/TPCReconstruction/KrBoxClusterFinderParam.h include/TPCReconstruction/KrCluster.h include/TPCReconstruction/RawReader.h include/TPCReconstruction/RawReaderCRU.h diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/KrBoxClusterFinder.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/KrBoxClusterFinder.h index 6c859769c54c7..8ff72ac94d999 100644 --- a/Detectors/TPC/reconstruction/include/TPCReconstruction/KrBoxClusterFinder.h +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/KrBoxClusterFinder.h @@ -70,6 +70,8 @@ #include "DataFormatsTPC/Digit.h" #include "TPCReconstruction/KrCluster.h" +#include "TPCReconstruction/KrBoxClusterFinderParam.h" + #include "TPCBase/Mapper.h" #include "TPCBase/CalDet.h" @@ -133,6 +135,33 @@ class KrBoxClusterFinder /// ger sector of this instance int getSector() const { return mSector; } + /// initialize the parameters from KrBoxClusterFinderParam + void init(); + + /// Set Function for minimum number of direct neighbours required + void setMinNumberOfNeighbours(int minNumberOfNeighbours) { mMinNumberOfNeighbours = minNumberOfNeighbours; } + + /// Set Function for minimal charge required for maxCharge of a cluster + void setMinQTreshold(int minQThreshold) { mQThresholdMax = minQThreshold; } + + /// Set Function for maximal cluster sizes in different ROCs + void setMaxClusterSize(int maxClusterSizeRowIROC, int maxClusterSizeRowOROC1, int maxClusterSizeRowOROC2, int maxClusterSizeRowOROC3, + int maxClusterSizePadIROC, int maxClusterSizePadOROC1, int maxClusterSizePadOROC2, int maxClusterSizePadOROC3, + int maxClusterSizeTime) + { + mMaxClusterSizeRowIROC = maxClusterSizeRowIROC; + mMaxClusterSizeRowOROC1 = maxClusterSizeRowOROC1; + mMaxClusterSizeRowOROC2 = maxClusterSizeRowOROC2; + mMaxClusterSizeRowOROC3 = maxClusterSizeRowOROC3; + + mMaxClusterSizePadIROC = maxClusterSizePadIROC; + mMaxClusterSizePadOROC1 = maxClusterSizePadOROC1; + mMaxClusterSizePadOROC2 = maxClusterSizePadOROC2; + mMaxClusterSizePadOROC3 = maxClusterSizePadOROC3; + + mMaxClusterSizeTime = maxClusterSizeTime; + } + private: // These variables can be varied // They were choses such that the box in each readout chamber is approx. the same size @@ -150,9 +179,9 @@ class KrBoxClusterFinder int mMaxClusterSizePadOROC2 = 3; ///< The "radius" of a cluster in pad direction in OROC2 int mMaxClusterSizePadOROC3 = 3; ///< The "radius" of a cluster in pad direction in OROC3 - float mQThresholdMax = 10.0; ///< the Maximum charge in a cluster must exceed this value or it is discarded + float mQThresholdMax = 30.0; ///< the Maximum charge in a cluster must exceed this value or it is discarded float mQThreshold = 1.0; ///< every charge which is added to a cluster must exceed this value or it is discarded - int mMinNumberOfNeighbours = 1; ///< amount of direct neighbours required for a cluster maximum + int mMinNumberOfNeighbours = 2; ///< amount of direct neighbours required for a cluster maximum int mSector = -1; ///< sector being processed in this instance std::unique_ptr mGainMap; ///< Gain map object diff --git a/Detectors/TPC/reconstruction/include/TPCReconstruction/KrBoxClusterFinderParam.h b/Detectors/TPC/reconstruction/include/TPCReconstruction/KrBoxClusterFinderParam.h new file mode 100644 index 0000000000000..2101808472a9e --- /dev/null +++ b/Detectors/TPC/reconstruction/include/TPCReconstruction/KrBoxClusterFinderParam.h @@ -0,0 +1,51 @@ +// Copyright CERN and copyright holders of ALICE O2. This software is +// distributed under the terms of the GNU General Public License v3 (GPL +// Version 3), copied verbatim in the file "COPYING". +// +// See http://alice-o2.web.cern.ch/license for full licensing information. +// +// 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 KrBoxClusterFinderParam.h +/// \brief Parameter class for the Kr box cluster finder +/// +/// \author Philip Hauer, hauer@hiskp.uni-bonn.de + +#ifndef ALICEO2_TPC_KrBoxClusterFinderParam_H_ +#define ALICEO2_TPC_KrBoxClusterFinderParam_H_ + +#include "CommonUtils/ConfigurableParam.h" +#include "CommonUtils/ConfigurableParamHelper.h" + +#include "DataFormatsTPC/Defs.h" + +namespace o2 +{ +namespace tpc +{ + +struct KrBoxClusterFinderParam : public o2::conf::ConfigurableParamHelper { + int MaxClusterSizeTime{3}; ///< "radius" of a cluster in time direction + + int MaxClusterSizeRowIROC{3}; ///< "radius" of a cluster in row direction in IROC + int MaxClusterSizeRowOROC1{2}; ///< "radius" of a cluster in row direction in OROC1 + int MaxClusterSizeRowOROC2{2}; ///< "radius" of a cluster in row direction in OROC2 + int MaxClusterSizeRowOROC3{1}; ///< "radius" of a cluster in row direction in OROC3 + + int MaxClusterSizePadIROC{5}; ///< "radius" of a cluster in pad direction in IROC + int MaxClusterSizePadOROC1{3}; ///< "radius" of a cluster in pad direction in OROC1 + int MaxClusterSizePadOROC2{3}; ///< "radius" of a cluster in pad direction in OROC2 + int MaxClusterSizePadOROC3{3}; ///< "radius" of a cluster in pad direction in OROC3 + + float QThresholdMax{30.0}; ///< the Maximum charge in a cluster must exceed this value or it is discarded + float QThreshold{1.0}; ///< every charge which is added to a cluster must exceed this value or it is discarded + int MinNumberOfNeighbours{2}; ///< amount of direct neighbours required for a cluster maximum + + O2ParamDef(KrBoxClusterFinderParam, "TPCKrBoxClusterFinder"); +}; +} // namespace tpc +} // namespace o2 + +#endif // ALICEO2_TPC_KrBoxClusterFinderParam_H_ \ No newline at end of file diff --git a/Detectors/TPC/reconstruction/macro/findKrBoxCluster.C b/Detectors/TPC/reconstruction/macro/findKrBoxCluster.C index 2429eb3a0417a..6212eeb43b5fd 100644 --- a/Detectors/TPC/reconstruction/macro/findKrBoxCluster.C +++ b/Detectors/TPC/reconstruction/macro/findKrBoxCluster.C @@ -27,16 +27,16 @@ #include #endif -void findKrBoxCluster(int lastTimeBin = 1000, int run = -1, int time = -1, std::string_view gainMapFile = "") +void findKrBoxCluster(int lastTimeBin = 1000, int run = -1, int time = -1, std::string_view gainMapFile = "", std::string inputFile = "tpcdigits.root", std::string outputFile = "BoxClusters.root") { // Read the digits: - TFile* file = new TFile("tpcdigits.root"); + TFile* file = new TFile(inputFile.c_str()); TTree* tree = (TTree*)file->Get("o2sim"); Long64_t nEntries = tree->GetEntries(); std::cout << "The Tree has " << nEntries << " Entries." << std::endl; // Initialize File for later writing - TFile* fOut = new TFile("BoxClusters.root", "RECREATE"); + TFile* fOut = new TFile(outputFile.c_str(), "RECREATE"); TTree* tClusters = new TTree("Clusters", "Clusters"); // Create a Branch for each sector: diff --git a/Detectors/TPC/reconstruction/src/KrBoxClusterFinder.cxx b/Detectors/TPC/reconstruction/src/KrBoxClusterFinder.cxx index e48c99ee8cb8b..df4229c36f52c 100644 --- a/Detectors/TPC/reconstruction/src/KrBoxClusterFinder.cxx +++ b/Detectors/TPC/reconstruction/src/KrBoxClusterFinder.cxx @@ -114,29 +114,54 @@ void KrBoxClusterFinder::fillADCValue(int cru, int rowInSector, int padInRow, in mMapOfAllDigits[timeBin][rowInSector][corPad] = adcValue; } +void KrBoxClusterFinder::init() +{ + const auto& param = KrBoxClusterFinderParam::Instance(); + + mMaxClusterSizeTime = param.MaxClusterSizeTime; + + mMaxClusterSizeRowIROC = param.MaxClusterSizeRowIROC; + mMaxClusterSizeRowOROC1 = param.MaxClusterSizeRowOROC1; + mMaxClusterSizeRowOROC2 = param.MaxClusterSizeRowOROC2; + mMaxClusterSizeRowOROC3 = param.MaxClusterSizeRowOROC3; + + mMaxClusterSizePadIROC = param.MaxClusterSizePadIROC; + mMaxClusterSizePadOROC1 = param.MaxClusterSizePadOROC1; + mMaxClusterSizePadOROC2 = param.MaxClusterSizePadOROC2; + mMaxClusterSizePadOROC3 = param.MaxClusterSizePadOROC3; + + mQThresholdMax = param.QThresholdMax; + mQThreshold = param.QThreshold; + mMinNumberOfNeighbours = param.MinNumberOfNeighbours; +} + //################################################# // Function to update the temporal cluster void KrBoxClusterFinder::updateTempClusterFinal() { - const float oneOverQtot = 1. / mTempCluster.totCharge; - mTempCluster.meanPad *= oneOverQtot; - mTempCluster.sigmaPad *= oneOverQtot; - mTempCluster.meanRow *= oneOverQtot; - mTempCluster.sigmaRow *= oneOverQtot; - mTempCluster.meanTime *= oneOverQtot; - mTempCluster.sigmaTime *= oneOverQtot; - mTempCluster.sigmaPad = std::sqrt(std::abs(mTempCluster.sigmaPad - mTempCluster.meanPad * mTempCluster.meanPad)); - mTempCluster.sigmaRow = std::sqrt(std::abs(mTempCluster.sigmaRow - mTempCluster.meanRow * mTempCluster.meanRow)); - mTempCluster.sigmaTime = std::sqrt(std::abs(mTempCluster.sigmaTime - mTempCluster.meanTime * mTempCluster.meanTime)); - - const int corPadsMean = mMapperInstance.getNumberOfPadsInRowSector(int(mTempCluster.meanRow)); - const int corPadsMaxCharge = mMapperInstance.getNumberOfPadsInRowSector(int(mTempCluster.maxChargeRow)); - - // Since every padrow is shifted such that neighbouring pads are indeed neighbours, we have to shift once back: - mTempCluster.meanPad = mTempCluster.meanPad + (corPadsMean / 2.0) - (MaxPads / 2.0); - mTempCluster.maxChargePad = mTempCluster.maxChargePad + (corPadsMaxCharge / 2.0) - (MaxPads / 2.0); - mTempCluster.sector = (decltype(mTempCluster.sector))mSector; + if (mTempCluster.totCharge == 0) { + mTempCluster.reset(); + } else { + const float oneOverQtot = 1. / mTempCluster.totCharge; + mTempCluster.meanPad *= oneOverQtot; + mTempCluster.sigmaPad *= oneOverQtot; + mTempCluster.meanRow *= oneOverQtot; + mTempCluster.sigmaRow *= oneOverQtot; + mTempCluster.meanTime *= oneOverQtot; + mTempCluster.sigmaTime *= oneOverQtot; + mTempCluster.sigmaPad = std::sqrt(std::abs(mTempCluster.sigmaPad - mTempCluster.meanPad * mTempCluster.meanPad)); + mTempCluster.sigmaRow = std::sqrt(std::abs(mTempCluster.sigmaRow - mTempCluster.meanRow * mTempCluster.meanRow)); + mTempCluster.sigmaTime = std::sqrt(std::abs(mTempCluster.sigmaTime - mTempCluster.meanTime * mTempCluster.meanTime)); + + const int corPadsMean = mMapperInstance.getNumberOfPadsInRowSector(int(mTempCluster.meanRow)); + const int corPadsMaxCharge = mMapperInstance.getNumberOfPadsInRowSector(int(mTempCluster.maxChargeRow)); + + // Since every padrow is shifted such that neighbouring pads are indeed neighbours, we have to shift once back: + mTempCluster.meanPad = mTempCluster.meanPad + (corPadsMean / 2.0) - (MaxPads / 2.0); + mTempCluster.maxChargePad = mTempCluster.maxChargePad + (corPadsMaxCharge / 2.0) - (MaxPads / 2.0); + mTempCluster.sector = (decltype(mTempCluster.sector))mSector; + } } // Function to update the temporal cluster. @@ -147,7 +172,12 @@ void KrBoxClusterFinder::updateTempCluster(float tempCharge, int tempPad, int te return; } - mTempCluster.size += 1; + // Some extrem ugly shaped clusters (mostly noise) might lead to an overflow. + // Hence, we have to define an upper limit here: + if (mTempCluster.size < 255) { + mTempCluster.size += 1; + } + mTempCluster.totCharge += tempCharge; mTempCluster.meanPad += tempPad * tempCharge; @@ -176,7 +206,20 @@ std::vector> KrBoxClusterFinder::findLocalMaxima(bool const auto& mapRow = mMapOfAllDigits[iTime]; for (int iRow = 0; iRow < MaxRows; iRow++) { // mapRow.size() // Since pad size is different for each ROC, we take this into account while looking for maxima: - setMaxClusterSize(iRow); + // setMaxClusterSize(iRow); + if (iRow == 0) { + mMaxClusterSizePad = mMaxClusterSizePadIROC; + mMaxClusterSizeRow = mMaxClusterSizeRowIROC; + } else if (iRow == MaxRowsIROC) { + mMaxClusterSizePad = mMaxClusterSizePadOROC1; + mMaxClusterSizeRow = mMaxClusterSizeRowOROC1; + } else if (iRow == MaxRowsIROC + MaxRowsOROC1) { + mMaxClusterSizePad = mMaxClusterSizePadOROC2; + mMaxClusterSizeRow = mMaxClusterSizeRowOROC2; + } else if (iRow == MaxRowsIROC + MaxRowsOROC1 + MaxRowsOROC2) { + mMaxClusterSizePad = mMaxClusterSizePadOROC3; + mMaxClusterSizeRow = mMaxClusterSizeRowOROC3; + } const auto& mapPad = mapRow[iRow]; const int padsInRow = mMapperInstance.getNumberOfPadsInRowSector(iRow); @@ -195,21 +238,39 @@ std::vector> KrBoxClusterFinder::findLocalMaxima(bool // with signal in any direction! int noNeighbours = 0; if ((iPad + 1 < MaxPads) && (mMapOfAllDigits[iTime][iRow][iPad + 1] > mQThreshold)) { + if (mMapOfAllDigits[iTime][iRow][iPad + 1] > qMax) { + continue; + } noNeighbours++; } if ((iPad - 1 >= 0) && (mMapOfAllDigits[iTime][iRow][iPad - 1] > mQThreshold)) { + if (mMapOfAllDigits[iTime][iRow][iPad - 1] > qMax) { + continue; + } noNeighbours++; } - if ((iTime + 1 < MaxTimes) && (mMapOfAllDigits[iTime + 1][iRow][iPad] > mQThreshold)) { + if ((iRow + 1 < MaxRows) && (mMapOfAllDigits[iTime][iRow + 1][iPad] > mQThreshold)) { + if (mMapOfAllDigits[iTime][iRow + 1][iPad] > qMax) { + continue; + } noNeighbours++; } - if ((iTime - 1 >= 0) && (mMapOfAllDigits[iTime - 1][iRow][iPad] > mQThreshold)) { + if ((iRow - 1 >= 0) && (mMapOfAllDigits[iTime][iRow - 1][iPad] > mQThreshold)) { + if (mMapOfAllDigits[iTime][iRow - 1][iPad] > qMax) { + continue; + } noNeighbours++; } - if ((iRow + 1 < MaxRows) && (mMapOfAllDigits[iTime][iRow + 1][iPad] > mQThreshold)) { + if ((iTime + 1 < MaxTimes) && (mMapOfAllDigits[iTime + 1][iRow][iPad] > mQThreshold)) { + if (mMapOfAllDigits[iTime + 1][iRow][iPad] > qMax) { + continue; + } noNeighbours++; } - if ((iRow - 1 >= 0) && (mMapOfAllDigits[iTime][iRow - 1][iPad] > mQThreshold)) { + if ((iTime - 1 >= 0) && (mMapOfAllDigits[iTime - 1][iRow][iPad] > mQThreshold)) { + if (mMapOfAllDigits[iTime - 1][iRow][iPad] > qMax) { + continue; + } noNeighbours++; } if (noNeighbours < mMinNumberOfNeighbours) { @@ -223,16 +284,16 @@ std::vector> KrBoxClusterFinder::findLocalMaxima(bool // -> only the maximum with the smalest indices will be accepted bool thisIsMax = true; - for (int i = -mMaxClusterSizePad; (i <= mMaxClusterSizePad) && thisIsMax; i++) { - if ((iPad + i >= MaxPads) || (iPad + i < 0)) { + for (int j = -mMaxClusterSizeTime; (j <= mMaxClusterSizeTime) && thisIsMax; j++) { + if ((iTime + j >= MaxTimes) || (iTime + j < 0)) { continue; } for (int k = -mMaxClusterSizeRow; (k <= mMaxClusterSizeRow) && thisIsMax; k++) { if ((iRow + k >= MaxRows) || (iRow + k < 0)) { continue; } - for (int j = -mMaxClusterSizeTime; (j <= mMaxClusterSizeTime) && thisIsMax; j++) { - if ((iTime + j >= MaxTimes) || (iTime + j < 0)) { + for (int i = -mMaxClusterSizePad; (i <= mMaxClusterSizePad) && thisIsMax; i++) { + if ((iPad + i >= MaxPads) || (iPad + i < 0)) { continue; } if (mMapOfAllDigits[iTime + j][iRow + k][iPad + i] > qMax) { @@ -250,6 +311,9 @@ std::vector> KrBoxClusterFinder::findLocalMaxima(bool } else { localMaximaCoords.emplace_back(std::make_tuple(iPad, iRow, iTime)); } + + // If we have found a local maximum, we can also skip the next few entries: + iPad += mMaxClusterSizePad; } } } @@ -330,7 +394,6 @@ KrCluster KrBoxClusterFinder::buildCluster(int clusterCenterPad, int clusterCent if (mMapOfAllDigits[clusterCenterTime + iTime][clusterCenterRow + iRow][clusterCenterPad + iPad] <= mQThreshold) { continue; } - // If not, there are several cases which were explained (for 2D) in the header of the code. // The first one is for the diagonal. So, the digit we are investigating here is on the diagonal: if (std::abs(iTime) == std::abs(iPad) && std::abs(iTime) == std::abs(iRow)) { diff --git a/Detectors/TPC/reconstruction/src/KrBoxClusterFinderParam.cxx b/Detectors/TPC/reconstruction/src/KrBoxClusterFinderParam.cxx new file mode 100644 index 0000000000000..57e5c0633ad87 --- /dev/null +++ b/Detectors/TPC/reconstruction/src/KrBoxClusterFinderParam.cxx @@ -0,0 +1,18 @@ +// Copyright CERN and copyright holders of ALICE O2. This software is +// distributed under the terms of the GNU General Public License v3 (GPL +// Version 3), copied verbatim in the file "COPYING". +// +// See http://alice-o2.web.cern.ch/license for full licensing information. +// +// 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 KrBoxClusterFinderParam.cxx +/// \brief Parameter class for the Kr box cluster finder +/// +/// \author Philip Hauer, hauer@hiskp.uni-bonn.de + +#include "TPCReconstruction/KrBoxClusterFinderParam.h" + +O2ParamImpl(o2::tpc::KrBoxClusterFinderParam); \ No newline at end of file diff --git a/Detectors/TPC/reconstruction/src/TPCReconstructionLinkDef.h b/Detectors/TPC/reconstruction/src/TPCReconstructionLinkDef.h index 4417ee16e038f..fa7d11bf22dc7 100644 --- a/Detectors/TPC/reconstruction/src/TPCReconstructionLinkDef.h +++ b/Detectors/TPC/reconstruction/src/TPCReconstructionLinkDef.h @@ -36,6 +36,8 @@ #pragma link C++ class o2::tpc::HwClusterer + ; #pragma link C++ class o2::tpc::HwClustererParam + ; #pragma link C++ class o2::conf::ConfigurableParamHelper < o2::tpc::HwClustererParam > +; +#pragma link C++ class o2::tpc::KrBoxClusterFinderParam + ; +#pragma link C++ class o2::conf::ConfigurableParamHelper < o2::tpc::KrBoxClusterFinderParam > +; #pragma link C++ class o2::tpc::TPCFastTransformHelperO2 + ;