diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/CalibdEdxTrackTopologyPol.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/CalibdEdxTrackTopologyPol.h index 293e85f21e025..70c40741e3c38 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/CalibdEdxTrackTopologyPol.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/CalibdEdxTrackTopologyPol.h @@ -49,6 +49,8 @@ struct CalibdEdxTrackTopologyPolContainer { float mQTotMax{200}; ///< maximum qTot for which the correction is valid std::vector mScalingFactorsqTot{}; ///< value which is used to scale the result of the polynomial for qTot (can be used for normalization) std::vector mScalingFactorsqMax{}; ///< value which is used to scale the result of the polynomial for qMax (can be used for normalization) + + ClassDefNV(CalibdEdxTrackTopologyPolContainer, 1); }; #endif @@ -206,6 +208,9 @@ class CalibdEdxTrackTopologyPol : public o2::gpu::FlatObject /// sets the polynomials from an input file. The names of the objects have to be the same as in the getPolyName() function /// \param inpf file where the polynomials are stored void setPolynomialsFromFile(TFile& inpf); + + /// setting a default topology correction which just returns 1 + void setDefaultPolynomials(); #endif /// \return returns the name of the polynomial object which can be read in with the setPolynomialsFromFile() function diff --git a/DataFormats/Detectors/TPC/src/CalibdEdxTrackTopologyPol.cxx b/DataFormats/Detectors/TPC/src/CalibdEdxTrackTopologyPol.cxx index 68e8b1fe28b5f..e736eff541b12 100644 --- a/DataFormats/Detectors/TPC/src/CalibdEdxTrackTopologyPol.cxx +++ b/DataFormats/Detectors/TPC/src/CalibdEdxTrackTopologyPol.cxx @@ -131,6 +131,15 @@ void CalibdEdxTrackTopologyPol::construct() } } +void CalibdEdxTrackTopologyPol::setDefaultPolynomials() +{ + for (int i = 0; i < FFits; ++i) { + mCalibPolsqTot[i].setParam(0, 1); + mCalibPolsqMax[i].setParam(0, 1); + } + construct(); +} + void CalibdEdxTrackTopologyPol::writeToFile(TFile& outf, const char* name) const { CalibdEdxTrackTopologyPolContainer cont(mMaxTanTheta, mMaxSinPhi, mThresholdMin, mThresholdMax, mQTotMin, mQTotMax); @@ -187,6 +196,7 @@ void CalibdEdxTrackTopologyPol::setFromContainer(const CalibdEdxTrackTopologyPol mScalingFactorsqTot[i] = container.mScalingFactorsqTot[i]; mScalingFactorsqMax[i] = container.mScalingFactorsqMax[i]; } + construct(); } void CalibdEdxTrackTopologyPol::loadFromFile(const char* fileName, const char* name) @@ -196,7 +206,6 @@ void CalibdEdxTrackTopologyPol::loadFromFile(const char* fileName, const char* n inpf.GetObject(name, polTmp); if (polTmp) { setFromContainer(*polTmp); - construct(); delete polTmp; } else { LOGP(info, fmt::format("couldnt load object {} from input file", name)); diff --git a/Detectors/TPC/base/include/TPCBase/CDBInterface.h b/Detectors/TPC/base/include/TPCBase/CDBInterface.h index fb2e24b3821f8..0233d6020af5a 100644 --- a/Detectors/TPC/base/include/TPCBase/CDBInterface.h +++ b/Detectors/TPC/base/include/TPCBase/CDBInterface.h @@ -49,6 +49,7 @@ enum class CDBType { CalGas, ///< DCS gas measurements CalTemperature, ///< DCS temperature measurements CalHV, ///< DCS HV measurements + CalTopologyGain, ///< Q cluster topology correction /// ConfigFEEPad, ///< FEE pad-by-pad configuration map /// @@ -78,6 +79,7 @@ const std::unordered_map CDBTypeMap{ {CDBType::CalGas, "TPC/Calib/Gas"}, {CDBType::CalTemperature, "TPC/Calib/Temperature"}, {CDBType::CalHV, "TPC/Calib/HV"}, + {CDBType::CalTopologyGain, "TPC/Calib/TopologyGain"}, // {CDBType::ConfigFEEPad, "TPC/Config/FEEPad"}, // diff --git a/GPU/GPUTracking/DataTypes/CalibdEdxContainer.cxx b/GPU/GPUTracking/DataTypes/CalibdEdxContainer.cxx index 9f0a777d777c1..c0a356bbdc9b2 100644 --- a/GPU/GPUTracking/DataTypes/CalibdEdxContainer.cxx +++ b/GPU/GPUTracking/DataTypes/CalibdEdxContainer.cxx @@ -150,6 +150,23 @@ void CalibdEdxContainer::loadSplineTopologyCorrectionFromFile(std::string_view f loadTopologyCorrectionFromFile(fileName, mCalibTrackTopologySpline); } +void CalibdEdxContainer::setPolTopologyCorrection(const CalibdEdxTrackTopologyPol& calibTrackTopology) +{ + setTopologyCorrection(calibTrackTopology, mCalibTrackTopologyPol); +} + +void CalibdEdxContainer::setDefaultPolTopologyCorrection() +{ + CalibdEdxTrackTopologyPol calibTrackTopology; + calibTrackTopology.setDefaultPolynomials(); + setTopologyCorrection(calibTrackTopology, mCalibTrackTopologyPol); +} + +void CalibdEdxContainer::setSplineTopologyCorrection(const CalibdEdxTrackTopologySpline& calibTrackTopology) +{ + setTopologyCorrection(calibTrackTopology, mCalibTrackTopologySpline); +} + void CalibdEdxContainer::loadZeroSupresssionThresholdFromFile(std::string_view fileName, std::string_view objName, const float minCorrectionFactor, const float maxCorrectionFactor) { TFile fInp(fileName.data(), "READ"); @@ -161,10 +178,75 @@ void CalibdEdxContainer::loadZeroSupresssionThresholdFromFile(std::string_view f void CalibdEdxContainer::setZeroSupresssionThreshold(const CalDet& thresholdMap, const float minCorrectionFactor, const float maxCorrectionFactor) { - o2::gpu::TPCPadGainCalib thresholdMapTmp(thresholdMap, minCorrectionFactor, maxCorrectionFactor, false); + const auto thresholdMapProcessed = processThresholdMap(thresholdMap, maxCorrectionFactor); + o2::gpu::TPCPadGainCalib thresholdMapTmp(thresholdMapProcessed, minCorrectionFactor, maxCorrectionFactor, false); mThresholdMap = thresholdMapTmp; } +CalDet CalibdEdxContainer::processThresholdMap(const CalDet& thresholdMap, const float maxThreshold, const int nPadsInRowCl, const int nPadsInPadCl) const +{ + CalDet thresholdMapProcessed(thresholdMap); + + for (int sector = 0; sector < Mapper::NSECTORS; ++sector) { + for (int region = 0; region < Mapper::NREGIONS; ++region) { + const int maxRow = Mapper::ROWSPERREGION[region] - 1; + for (int lrow = 0; lrow <= maxRow; ++lrow) { + // find first row of the cluster + const int rowStart = std::clamp(lrow - nPadsInRowCl, 0, maxRow); + const int rowEnd = std::clamp(lrow + nPadsInRowCl, 0, maxRow); + const int addPadsStart = Mapper::ADDITIONALPADSPERROW[region][lrow]; + + for (int pad = 0; pad < Mapper::PADSPERROW[region][lrow]; ++pad) { + float sumThr = 0; + int countThr = 0; + // loop ove the rows from the cluster + for (int rowCl = rowStart; rowCl <= rowEnd; ++rowCl) { + // shift local pad in row in case current row from the cluster has more pads in the row + const int addPadsCl = Mapper::ADDITIONALPADSPERROW[region][rowCl]; + const int diffAddPads = addPadsCl - addPadsStart; + const int padClCentre = pad + diffAddPads; + + const int maxPad = Mapper::PADSPERROW[region][rowCl] - 1; + const int padStart = std::clamp(padClCentre - nPadsInPadCl, 0, maxPad); + const int padEnd = std::clamp(padClCentre + nPadsInPadCl, 0, maxPad); + for (int padCl = padStart; padCl <= padEnd; ++padCl) { + const int globalPad = Mapper::getGlobalPadNumber(rowCl, padCl, region); + // skip for current cluster position as the charge there is not effected from the thresold + if (padCl == pad && rowCl == lrow) { + continue; + } + + float threshold = thresholdMap.getValue(sector, globalPad); + if (threshold > maxThreshold) { + threshold = maxThreshold; + } + + sumThr += threshold; + ++countThr; + } + } + const float meanThresold = sumThr / countThr; + const int globalPad = Mapper::getGlobalPadNumber(lrow, pad, region); + thresholdMapProcessed.setValue(sector, globalPad, meanThresold); + } + } + } + } + return thresholdMapProcessed; +} + +void CalibdEdxContainer::setGainMap(const CalDet& gainMap, const float minGain, const float maxGain) +{ + o2::gpu::TPCPadGainCalib gainMapTmp(gainMap, minGain, maxGain, false); + mGainMap = gainMapTmp; +} + +void CalibdEdxContainer::setGainMapResidual(const CalDet& gainMapResidual, const float minResidualGain, const float maxResidualGain) +{ + o2::gpu::TPCPadGainCalib gainMapResTmp(gainMapResidual, minResidualGain, maxResidualGain, false); + mGainMapResidual = gainMapResTmp; +} + void CalibdEdxContainer::setDefaultZeroSupresssionThreshold() { const float defaultVal = getMinZeroSupresssionThreshold() + (getMaxZeroSupresssionThreshold() - getMinZeroSupresssionThreshold()) / 2; @@ -180,10 +262,15 @@ void CalibdEdxContainer::setDefaultZeroSupresssionThreshold() template void CalibdEdxContainer::loadTopologyCorrectionFromFile(std::string_view fileName, Type*& obj) { - FlatObject::startConstruction(); - // load and set-up container Type calibTrackTopologyTmp(fileName.data()); + setTopologyCorrection(calibTrackTopologyTmp, obj); +} + +template +void CalibdEdxContainer::setTopologyCorrection(const Type& calibTrackTopologyTmp, Type*& obj) +{ + FlatObject::startConstruction(); // get size of the flat buffer of the splines const std::size_t flatbufferSize = calibTrackTopologyTmp.getFlatBufferSize(); diff --git a/GPU/GPUTracking/DataTypes/CalibdEdxContainer.h b/GPU/GPUTracking/DataTypes/CalibdEdxContainer.h index 938bb9ff01c68..b3c732086495f 100644 --- a/GPU/GPUTracking/DataTypes/CalibdEdxContainer.h +++ b/GPU/GPUTracking/DataTypes/CalibdEdxContainer.h @@ -32,6 +32,22 @@ namespace o2::tpc { +/// flags to set which corrections will be loaded from the CCDB +enum class CalibsdEdx : unsigned short { + CalTopologySpline = 1 << 0, ///< flag for a topology correction using splines + CalTopologyPol = 1 << 1, ///< flag for a topology correction using polynomials + CalThresholdMap = 1 << 2, ///< flag for using threshold map + CalGainMap = 1 << 3, ///< flag for using the gain map to get the correct cluster charge + CalResidualGainMap = 1 << 4, ///< flag for applying residual gain map + CalTimeGain = 1 << 5, ///< flag for residual dE/dx time dependent gain correction +}; + +inline CalibsdEdx operator|(CalibsdEdx a, CalibsdEdx b) { return static_cast(static_cast(a) | static_cast(b)); } + +inline CalibsdEdx operator&(CalibsdEdx a, CalibsdEdx b) { return static_cast(static_cast(a) & static_cast(b)); } + +inline CalibsdEdx operator~(CalibsdEdx a) { return static_cast(~static_cast(a)); } + /// /// This container class contains all necessary corrections for the dE/dx /// Currently it holds the residual dE/dx correction and the track topology correction, which can be either provided by 2D-splines or by 5D-polynomials. @@ -107,6 +123,16 @@ class CalibdEdxContainer : public o2::gpu::FlatObject /// \param row global pad row GPUd() float getZeroSupressionThreshold(const int sector, const gpu::tpccf::Row row, const gpu::tpccf::Pad pad) const { return mThresholdMap.getGainCorrection(sector, row, pad); } + /// \return returns gain from the full gain map + /// \param sector tpc sector + /// \param row global pad row + GPUd() float getGain(const int sector, const gpu::tpccf::Row row, const gpu::tpccf::Pad pad) const { return mGainMap.getGainCorrection(sector, row, pad); } + + /// \return returns gain from residual gain map + /// \param sector tpc sector + /// \param row global pad row + GPUd() float getResidualGain(const int sector, const gpu::tpccf::Row row, const gpu::tpccf::Pad pad) const { return mGainMapResidual.getGainCorrection(sector, row, pad); } + /// \return returns the residual dE/dx correction for the cluster charge /// \param stack ID of the GEM stack /// \param charge type of the charge (qMax or qTot) @@ -114,6 +140,9 @@ class CalibdEdxContainer : public o2::gpu::FlatObject /// \param tgl tracking parameter tgl GPUd() float getResidualCorrection(const StackID& stack, const ChargeType charge, const float z = 0, const float tgl = 0) const { return mCalibResidualdEdx.getCorrection(stack, charge, z, tgl); } + /// \return returns if the full gain map will be used during the calculation of the dE/dx to correct the cluster charge + GPUd() bool isUsageOfFullGainMap() const { return mApplyFullGainMap; } + /// ========== FlatObject functionality, see FlatObject class for description ================= #if !defined(GPUCA_GPUCODE) /// cloning a container object (use newFlatBufferPtr=nullptr for simple copy) @@ -143,32 +172,78 @@ class CalibdEdxContainer : public o2::gpu::FlatObject /// \param fileName input file containing the correction void loadSplineTopologyCorrectionFromFile(std::string_view fileName); + /// set the polynomial track topology + /// \param calibTrackTopology polynomial track topology correction + void setPolTopologyCorrection(const CalibdEdxTrackTopologyPol& calibTrackTopology); + + /// setting a default topology correction which just returns 1 + void setDefaultPolTopologyCorrection(); + + /// set the spline track topology + /// \param calibTrackTopology spline track topology correction + void setSplineTopologyCorrection(const CalibdEdxTrackTopologySpline& calibTrackTopology); + // loading the residual dE/dx correction from a file /// \param fileName input file containing the correction void loadResidualCorrectionFromFile(std::string_view fileName) { mCalibResidualdEdx.loadFromFile(fileName); } + /// setting the residual dEdx correction + /// \param residualCorr residual gain calibration object + void setResidualCorrection(const CalibdEdxCorrection& residualCorr) { mCalibResidualdEdx = residualCorr; } + // loading the zero supression threshold map from a file /// \param fileName input file containing the CalDet map void loadZeroSupresssionThresholdFromFile(std::string_view fileName, std::string_view objName, const float minCorrectionFactor, const float maxCorrectionFactor); - // loading the zero supression threshold map from a file - /// \param fileName input file containing the CalDet map + /// setting the zero supression threshold map from a CalDet + /// \param thresholdMap CalDet containing the zero supression threshold void setZeroSupresssionThreshold(const CalDet& thresholdMap) { setZeroSupresssionThreshold(thresholdMap, getMinZeroSupresssionThreshold(), getMaxZeroSupresssionThreshold()); } - // loading the zero supression threshold map from a file - /// \param fileName input file containing the CalDet map + /// setting the zero supression threshold map from a CalDet + /// \param thresholdMap CalDet containing the zero supression threshold void setZeroSupresssionThreshold(const CalDet& thresholdMap, const float minCorrectionFactor, const float maxCorrectionFactor); + /// setting the gain map map from a CalDet + void setGainMap(const CalDet& gainMap, const float minGain, const float maxGain); + + /// setting the gain map map from a CalDet + void setGainMapResidual(const CalDet& gainMapResidual, const float minResidualGain = 0.7f, const float maxResidualGain = 1.3f); + /// setting default zero supression threshold map (all values are set to getMinZeroSupresssionThreshold()) /// \param fileName input file containing the CalDet map void setDefaultZeroSupresssionThreshold(); + + /// returns status if the spline correction is set + bool isTopologyCorrectionSplinesSet() const { return mCalibTrackTopologySpline ? true : false; } + + /// returns status if the polynomials correction is set + bool isTopologyCorrectionPolynomialsSet() const { return mCalibTrackTopologyPol ? true : false; } + + /// set loading of a correction from CCDB + /// \param calib calibration which will be loaded from CCDB + void setCorrectionCCDB(const CalibsdEdx calib) { mCalibsLoad = calib | mCalibsLoad; } + + /// disable loading of a correction from CCDB + /// \param calib calibration which will not be loaded from CCDB + void disableCorrectionCCDB(const CalibsdEdx calib) { mCalibsLoad = ~calib & mCalibsLoad; } + + /// check if a correction will be loaded from CCDB + /// \param calib calibration which will be loaded from CCDB + bool isCorrectionCCDB(const CalibsdEdx calib) const { return ((mCalibsLoad & calib) == calib) ? true : false; } + + /// \param applyFullGainMap if set to true the cluster charge will be corrected with the full gain map + void setUsageOfFullGainMap(const bool applyFullGainMap) { mApplyFullGainMap = applyFullGainMap; } #endif // !GPUCA_GPUCODE private: - CalibdEdxTrackTopologySpline* mCalibTrackTopologySpline{nullptr}; ///< calibration for the track topology correction (splines) - CalibdEdxTrackTopologyPol* mCalibTrackTopologyPol{nullptr}; ///< calibration for the track topology correction (polynomial) - o2::gpu::TPCPadGainCalib mThresholdMap{}; ///< calibration object containing the zero supression threshold map - CalibdEdxCorrection mCalibResidualdEdx{}; ///< calibration for the residual dE/dx correction + CalibdEdxTrackTopologySpline* mCalibTrackTopologySpline{nullptr}; ///< calibration for the track topology correction (splines) + CalibdEdxTrackTopologyPol* mCalibTrackTopologyPol{nullptr}; ///< calibration for the track topology correction (polynomial) + o2::gpu::TPCPadGainCalib mThresholdMap{}; ///< calibration object containing the zero supression threshold map + o2::gpu::TPCPadGainCalib mGainMap{}; ///< calibration object containing the gain map + o2::gpu::TPCPadGainCalib mGainMapResidual{}; ///< calibration object containing the residual gain map + CalibdEdxCorrection mCalibResidualdEdx{}; ///< calibration for the residual dE/dx correction + bool mApplyFullGainMap{false}; ///< if set to true the cluster charge will be corrected with the full gain map (when the gain map was not applied during the clusterizer) + CalibsdEdx mCalibsLoad{CalibsdEdx::CalTopologyPol | CalibsdEdx::CalThresholdMap | CalibsdEdx::CalGainMap | CalibsdEdx::CalResidualGainMap | CalibsdEdx::CalTimeGain}; ///< flags to set which corrections will be loaded from the CCDB and used during calculation of the dE/dx #if !defined(GPUCA_GPUCODE) template @@ -179,6 +254,9 @@ class CalibdEdxContainer : public o2::gpu::FlatObject template void loadTopologyCorrectionFromFile(std::string_view fileName, Type*& obj); + + template + void setTopologyCorrection(const Type& calibTrackTopologyTmp, Type*& obj); #endif template @@ -190,6 +268,14 @@ class CalibdEdxContainer : public o2::gpu::FlatObject #if !defined(GPUCA_GPUCODE) template void cloneFromObject(Type*& obj, const Type* objOld, char* newFlatBufferPtr, const char* oldFlatBufferPtr); + + /// this functions 'smoothes' a CalDet by calculating for each value in a pad the average value using the neighbouring pads, but do not take into account the current pad + /// \return returns 'smoothed' CalDet object + /// \param thresholdMap zero supression threshold map which will be 'smoothed' + /// \param maxThreshold max threshold value which will be considered for averaging + /// \param nPadsInRowCl number of pads in row direction which will be taken into account (+- nPadsInRowCl) + /// \param nPadsInPadCl number of pads in pad direction which will be taken into account (+- nPadsInPadCl) + CalDet processThresholdMap(const CalDet& thresholdMap, const float maxThreshold, const int nPadsInRowCl = 2, const int nPadsInPadCl = 2) const; #endif #ifndef GPUCA_ALIROOT_LIB diff --git a/GPU/GPUTracking/Definitions/GPUSettingsList.h b/GPU/GPUTracking/Definitions/GPUSettingsList.h index 85d2043df2302..ccbd119b834fa 100644 --- a/GPU/GPUTracking/Definitions/GPUSettingsList.h +++ b/GPU/GPUTracking/Definitions/GPUSettingsList.h @@ -418,9 +418,16 @@ AddOption(rundEdx, int, -1, "", 0, "Enable/disable dEdx processing (-1 for autos AddOption(dEdxSplineTopologyCorrFile, std::string, "", "", 0, "File name of the dE/dx spline track topology correction file") AddOption(dEdxCorrFile, std::string, "", "", 0, "File name of dEdx residual correction file") AddOption(dEdxPolTopologyCorrFile, std::string, "", "", 0, "File name of the dE/dx polynomial track topology correction") +AddOption(dEdxDisableTopologyPol, bool, false, "", 0, "Disable loading of polynomial track topology correction from CCDB") +AddOption(dEdxDisableThresholdMap, bool, false, "", 0, "Disable loading of threshold map from CCDB") +AddOption(dEdxDisableGainMap, bool, false, "", 0, "Disable loading of gain map from CCDB") +AddOption(dEdxDisableResidualGainMap, bool, false, "", 0, "Disable loading of residual gain map from CCDB") +AddOption(dEdxDisableResidualGain, bool, false, "", 0, "Disable loading of residual dE/dx gain correction from CCDB") +AddOption(dEdxUseFullGainMap, bool, false, "", 0, "Enable using the full gain map for correcting the cluster charge during calculation of the dE/dx") AddOption(transformationFile, std::string, "", "", 0, "File name of TPC fast transformation map") AddOption(matLUTFile, std::string, "", "", 0, "File name of material LUT file") AddOption(gainCalibFile, std::string, "", "", 0, "File name of TPC pad gain calibration") +AddOption(gainCalibDisableCCDB, bool, false, "", 0, "Disabling loading the TPC pad gain calibration from the CCDB") AddOption(thresholdCalibFile, std::string, "", "", 0, "File name of TPC zero supression threshold map") AddOption(allocateOutputOnTheFly, bool, true, "", 0, "Allocate shm output buffers on the fly, instead of using preallocated buffer with upper bound size") AddOption(outputBufferSize, unsigned long, 200000000ul, "", 0, "Size of the output buffers to be allocated") diff --git a/GPU/GPUTracking/dEdx/GPUdEdx.h b/GPU/GPUTracking/dEdx/GPUdEdx.h index 0d7af385c1cd7..ee83f0d744888 100644 --- a/GPU/GPUTracking/dEdx/GPUdEdx.h +++ b/GPU/GPUTracking/dEdx/GPUdEdx.h @@ -145,7 +145,16 @@ GPUdnii() void GPUdEdx::fillCluster(float qtot, float qmax, int padRow, unsigned const int region = param.tpcGeometry.GetRegion(padRow); z = CAMath::Abs(z); const float threshold = calibContainer->getZeroSupressionThreshold(slice, padRow, padPos); // TODO: Use the mean zero supresion threshold of all pads in the cluster? - const float qTotIn = CAMath::Clamp(qtot, calibContainer->getMinqTot(), calibContainer->getMaxqTot()); + const bool useFullGainMap = calibContainer->isUsageOfFullGainMap(); + float qTotIn = CAMath::Clamp(qtot, calibContainer->getMinqTot(), calibContainer->getMaxqTot()); + const float fullGainMapGain = calibContainer->getGain(slice, padRow, padPos); + if (useFullGainMap) { + qmax /= fullGainMapGain; + qtot /= fullGainMapGain; + } else { + qTotIn *= fullGainMapGain; + } + const float qMaxTopologyCorr = calibContainer->getTopologyCorrection(region, o2::tpc::ChargeType::Max, tanTheta, snp, z, absRelPad, relTime, threshold, qTotIn); const float qTotTopologyCorr = calibContainer->getTopologyCorrection(region, o2::tpc::ChargeType::Tot, tanTheta, snp, z, absRelPad, relTime, threshold, qTotIn); qmax /= qMaxTopologyCorr; @@ -161,6 +170,10 @@ GPUdnii() void GPUdEdx::fillCluster(float qtot, float qmax, int padRow, unsigned qmax /= qMaxResidualCorr; qtot /= qTotResidualCorr; + const float residualGainMapGain = calibContainer->getResidualGain(slice, padRow, padPos); + qmax /= residualGainMapGain; + qtot /= residualGainMapGain; + mChargeTot[mCount] = (GPUCA_DEDX_STORAGE_TYPE)(qtot * scalingFactor::factor + scalingFactor::round); mChargeMax[mCount++] = (GPUCA_DEDX_STORAGE_TYPE)(qmax * scalingFactor::factor + scalingFactor::round); mNClsROC[roc]++; diff --git a/GPU/TPCFastTransformation/MultivariatePolynomial.h b/GPU/TPCFastTransformation/MultivariatePolynomial.h index 2f30638778116..9a20c68dad4ca 100644 --- a/GPU/TPCFastTransformation/MultivariatePolynomial.h +++ b/GPU/TPCFastTransformation/MultivariatePolynomial.h @@ -101,6 +101,10 @@ class MultivariatePolynomial : public FlatObject, public MultivariatePolynomialH /// \param params parameter for the coefficients void setParams(const float params[/*mNParams*/]) { std::copy(params, params + mNParams, mParams); } + /// \param parameter which will be set + /// \val value of the parameter + void setParam(const unsigned int param, const float val) { mParams[param] = val; }; + /// \return returns the paramaters of the coefficients const float* getParams() const { return mParams; } diff --git a/GPU/Workflow/src/GPUWorkflowSpec.cxx b/GPU/Workflow/src/GPUWorkflowSpec.cxx index 2761359e1eaff..b9a825438555b 100644 --- a/GPU/Workflow/src/GPUWorkflowSpec.cxx +++ b/GPU/Workflow/src/GPUWorkflowSpec.cxx @@ -26,6 +26,7 @@ #include "Framework/SerializationMethods.h" #include "Framework/Logger.h" #include "Framework/CallbackService.h" +#include "Framework/CCDBParamSpec.h" #include "DataFormatsTPC/TPCSectorHeader.h" #include "DataFormatsTPC/ClusterNative.h" #include "DataFormatsTPC/CompressedClusters.h" @@ -53,6 +54,7 @@ #include "DataFormatsParameters/GRPObject.h" #include "TPCBase/Sector.h" #include "TPCBase/Utils.h" +#include "TPCBase/CDBInterface.h" #include "SimulationDataFormat/ConstMCTruthContainer.h" #include "SimulationDataFormat/MCCompLabel.h" #include "Algorithm/Parser.h" @@ -116,6 +118,9 @@ DataProcessorSpec getGPURecoWorkflowSpec(gpuworkflow::CompletionPolicyData* poli bool readyToQuit = false; bool allocateOutputOnTheFly = false; bool suppressOutput = false; + bool updateCalibs = false; + bool updateGainMapCalib = false; + bool updateGainMapCCDB = true; o2::gpu::GPUSettingsTF tfSettings; }; @@ -261,16 +266,60 @@ DataProcessorSpec getGPURecoWorkflowSpec(gpuworkflow::CompletionPolicyData* poli } } + processAttributes->dEdxCalibContainer.reset(new o2::tpc::CalibdEdxContainer()); + + if (confParam.dEdxDisableTopologyPol) { + LOGP(info, "Disabling loading of track topology correction using polynomials from CCDB"); + processAttributes->dEdxCalibContainer->disableCorrectionCCDB(o2::tpc::CalibsdEdx::CalTopologyPol); + } + + if (confParam.dEdxDisableThresholdMap) { + LOGP(info, "Disabling loading of threshold map from CCDB"); + processAttributes->dEdxCalibContainer->disableCorrectionCCDB(o2::tpc::CalibsdEdx::CalThresholdMap); + } + + if (confParam.dEdxDisableGainMap) { + LOGP(info, "Disabling loading of gain map from CCDB"); + processAttributes->dEdxCalibContainer->disableCorrectionCCDB(o2::tpc::CalibsdEdx::CalGainMap); + } + + if (confParam.dEdxDisableResidualGainMap) { + LOGP(info, "Disabling loading of residual gain map from CCDB"); + processAttributes->dEdxCalibContainer->disableCorrectionCCDB(o2::tpc::CalibsdEdx::CalResidualGainMap); + } + + if (confParam.dEdxDisableResidualGain) { + LOGP(info, "Disabling loading of residual gain calibration from CCDB"); + processAttributes->dEdxCalibContainer->disableCorrectionCCDB(o2::tpc::CalibsdEdx::CalTimeGain); + } + + if (confParam.dEdxUseFullGainMap) { + LOGP(info, "Using the full gain map for correcting the cluster charge during calculation of the dE/dx"); + processAttributes->dEdxCalibContainer->setUsageOfFullGainMap(true); + } + + if (confParam.gainCalibDisableCCDB) { + LOGP(info, "Disabling loading the TPC pad gain calibration from the CCDB"); + processAttributes->updateGainMapCCDB = false; + } + // load from file if (!confParam.dEdxPolTopologyCorrFile.empty() || !confParam.dEdxCorrFile.empty() || !confParam.dEdxSplineTopologyCorrFile.empty()) { - processAttributes->dEdxCalibContainer.reset(new o2::tpc::CalibdEdxContainer()); if (!confParam.dEdxPolTopologyCorrFile.empty()) { LOGP(info, "Loading dE/dx polynomial track topology correction from file: {}", confParam.dEdxPolTopologyCorrFile); processAttributes->dEdxCalibContainer->loadPolTopologyCorrectionFromFile(confParam.dEdxPolTopologyCorrFile); + + LOGP(info, "Disabling loading of track topology correction using polynomials from CCDB as it was already loaded from input file"); + processAttributes->dEdxCalibContainer->disableCorrectionCCDB(o2::tpc::CalibsdEdx::CalTopologyPol); + if (std::filesystem::exists(confParam.thresholdCalibFile)) { LOG(info) << "Loading tpc zero supression map from file " << confParam.thresholdCalibFile; const auto* thresholdMap = o2::tpc::utils::readCalPads(confParam.thresholdCalibFile, "ThresholdMap")[0]; processAttributes->dEdxCalibContainer->setZeroSupresssionThreshold(*thresholdMap); + + LOGP(info, "Disabling loading of threshold map from CCDB as it was already loaded from input file"); + processAttributes->dEdxCalibContainer->disableCorrectionCCDB(o2::tpc::CalibsdEdx::CalThresholdMap); + } else { if (not confParam.thresholdCalibFile.empty()) { LOG(warn) << "Couldn't find tpc zero supression file " << confParam.thresholdCalibFile << ". Not setting any zero supression."; @@ -281,14 +330,22 @@ DataProcessorSpec getGPURecoWorkflowSpec(gpuworkflow::CompletionPolicyData* poli } else if (!confParam.dEdxSplineTopologyCorrFile.empty()) { LOGP(info, "Loading dE/dx spline track topology correction from file: {}", confParam.dEdxSplineTopologyCorrFile); processAttributes->dEdxCalibContainer->loadSplineTopologyCorrectionFromFile(confParam.dEdxSplineTopologyCorrFile); + + LOGP(info, "Disabling loading of track topology correction using polynomials from CCDB as splines were loaded from input file"); + processAttributes->dEdxCalibContainer->disableCorrectionCCDB(o2::tpc::CalibsdEdx::CalTopologyPol); } if (!confParam.dEdxCorrFile.empty()) { LOGP(info, "Loading dEdx correction from file: {}", confParam.dEdxCorrFile); processAttributes->dEdxCalibContainer->loadResidualCorrectionFromFile(confParam.dEdxCorrFile); + + LOGP(info, "Disabling loading of residual gain calibration from CCDB as it was already loaded from input file"); + processAttributes->dEdxCalibContainer->disableCorrectionCCDB(o2::tpc::CalibsdEdx::CalTimeGain); } } else { - processAttributes->dEdxCalibContainer.reset(new o2::tpc::CalibdEdxContainer()); + // setting default topology correction to allocate enough memory + LOG(info) << "Setting default dE/dx polynomial track topology correction to allocate enough memory"; + processAttributes->dEdxCalibContainer->setDefaultPolTopologyCorrection(); } config.configCalib.dEdxCalibContainer = processAttributes->dEdxCalibContainer.get(); @@ -296,6 +353,10 @@ DataProcessorSpec getGPURecoWorkflowSpec(gpuworkflow::CompletionPolicyData* poli LOG(info) << "Loading tpc gain correction from file " << confParam.gainCalibFile; const auto* gainMap = o2::tpc::utils::readCalPads(confParam.gainCalibFile, "GainMap")[0]; processAttributes->tpcPadGainCalib = GPUO2Interface::getPadGainCalib(*gainMap); + + LOGP(info, "Disabling loading the TPC gain correction map from the CCDB as it was already loaded from input file"); + processAttributes->updateGainMapCCDB = false; + } else { if (not confParam.gainCalibFile.empty()) { LOG(warn) << "Couldn't find tpc gain correction file " << confParam.gainCalibFile << ". Not applying any gain correction."; @@ -376,6 +437,55 @@ DataProcessorSpec getGPURecoWorkflowSpec(gpuworkflow::CompletionPolicyData* poli }; ic.services().get().set(CallbackService::Id::Stop, printTiming); + auto finaliseCCDB = [processAttributes, specconfig](ConcreteDataMatcher& matcher, void* obj) { + LOGP(info, "checking for newer object...."); + CalibdEdxContainer* dEdxCalibContainer = processAttributes->dEdxCalibContainer.get(); + + if (matcher == ConcreteDataMatcher(gDataOriginTPC, "PADGAINFULL", 0)) { + LOGP(info, "Updating gain map from CCDB"); + const auto* gainMap = static_cast*>(obj); + + if (dEdxCalibContainer->isCorrectionCCDB(CalibsdEdx::CalGainMap) && specconfig.outputTracks) { + const float minGain = 0; + const float maxGain = 2; + processAttributes->dEdxCalibContainer.get()->setGainMap(*gainMap, minGain, maxGain); + processAttributes->updateCalibs = true; + } + + if (processAttributes->updateGainMapCCDB && specconfig.caClusterer) { + processAttributes->tpcPadGainCalib = GPUO2Interface::getPadGainCalib(*gainMap); + processAttributes->updateGainMapCalib = true; + } + + } else if (matcher == ConcreteDataMatcher(gDataOriginTPC, "PADGAINRESIDUAL", 0)) { + LOGP(info, "Updating residual gain map from CCDB"); + const auto* gainMapResidual = static_cast>*>(obj); + const float minResidualGain = 0.7f; + const float maxResidualGain = 1.3f; + processAttributes->dEdxCalibContainer.get()->setGainMapResidual(gainMapResidual->at("GainMap"), minResidualGain, maxResidualGain); + processAttributes->updateCalibs = true; + } else if (matcher == ConcreteDataMatcher(gDataOriginTPC, "PADTHRESHOLD", 0)) { + LOGP(info, "Updating threshold map from CCDB"); + const auto* thresholdMap = static_cast>*>(obj); + processAttributes->dEdxCalibContainer.get()->setZeroSupresssionThreshold(thresholdMap->at("ThresholdMap")); + processAttributes->updateCalibs = true; + } else if (matcher == ConcreteDataMatcher(gDataOriginTPC, "TOPOLOGYGAIN", 0) && !(dEdxCalibContainer->isTopologyCorrectionSplinesSet())) { + LOGP(info, "Updating Q topology correction from CCDB"); + const auto* topologyCorr = static_cast(obj); + CalibdEdxTrackTopologyPol calibTrackTopology; + calibTrackTopology.setFromContainer(*topologyCorr); + dEdxCalibContainer->setPolTopologyCorrection(calibTrackTopology); + processAttributes->updateCalibs = true; + } else if (matcher == ConcreteDataMatcher(gDataOriginTPC, "TIMEGAIN", 0)) { + LOGP(info, "Updating residual gain correction from CCDB"); + const auto* residualCorr = static_cast(obj); + dEdxCalibContainer->setResidualCorrection(*residualCorr); + processAttributes->updateCalibs = true; + } + }; + + ic.services().get().set(CallbackService::Id::CCDBDeserialised, finaliseCCDB); + auto processingFct = [processAttributes, specconfig](ProcessingContext& pc) { if (processAttributes->readyToQuit) { return; @@ -656,6 +766,55 @@ DataProcessorSpec getGPURecoWorkflowSpec(gpuworkflow::CompletionPolicyData* poli } const auto& holdData = TPCTrackingDigitsPreCheck::runPrecheck(&ptrs, processAttributes->config.get()); + + // update calibrations for clustering and tracking + if (specconfig.outputTracks || specconfig.caClusterer) { + const CalibdEdxContainer* dEdxCalibContainer = processAttributes->dEdxCalibContainer.get(); + + // this calibration is defined for clustering and tracking + if (dEdxCalibContainer->isCorrectionCCDB(CalibsdEdx::CalGainMap) || processAttributes->updateGainMapCCDB) { + pc.inputs().get*>("tpcgain"); + } + + // these calibrations are only defined for the tracking + if (specconfig.outputTracks) { + // update the calibration objects in case they changed in the CCDB + if (dEdxCalibContainer->isCorrectionCCDB(CalibsdEdx::CalThresholdMap)) { + pc.inputs().get>*>("tpcthreshold"); + } + + if (dEdxCalibContainer->isCorrectionCCDB(CalibsdEdx::CalResidualGainMap)) { + pc.inputs().get>*>("tpcgainresidual"); + } + + if (dEdxCalibContainer->isCorrectionCCDB(CalibsdEdx::CalTopologyPol)) { + pc.inputs().get("tpctopologygain"); + } + + if (dEdxCalibContainer->isCorrectionCCDB(CalibsdEdx::CalTimeGain)) { + pc.inputs().get("tpctimegain"); + } + } + + if (processAttributes->updateCalibs || processAttributes->updateGainMapCalib) { + // updating the calibration object + GPUCalibObjectsConst newTopologyCalib; + + if (processAttributes->updateCalibs) { + newTopologyCalib.dEdxCalibContainer = dEdxCalibContainer; + processAttributes->updateCalibs = false; + } + + if (processAttributes->updateGainMapCalib) { + newTopologyCalib.tpcPadGain = processAttributes->tpcPadGainCalib.get(); + processAttributes->updateGainMapCalib = false; + } + + auto& tracker = processAttributes->tracker; + tracker->UpdateCalibration(newTopologyCalib); + } + } + int retVal = tracker->RunTracking(&ptrs, &outputRegions); tracker->Clear(false); @@ -794,9 +953,22 @@ DataProcessorSpec getGPURecoWorkflowSpec(gpuworkflow::CompletionPolicyData* poli // e.g. by providing a span of inputs under a certain label auto createInputSpecs = [&tpcsectors, &specconfig, policyData]() { Inputs inputs; + if (specconfig.outputTracks) { + // loading calibration objects from the CCDB + inputs.emplace_back("tpcgain", gDataOriginTPC, "PADGAINFULL", 0, Lifetime::Condition, ccdbParamSpec(CDBTypeMap.at(CDBType::CalPadGainFull))); + inputs.emplace_back("tpcgainresidual", gDataOriginTPC, "PADGAINRESIDUAL", 0, Lifetime::Condition, ccdbParamSpec(CDBTypeMap.at(CDBType::CalPadGainResidual))); + inputs.emplace_back("tpctimegain", gDataOriginTPC, "TIMEGAIN", 0, Lifetime::Condition, ccdbParamSpec(CDBTypeMap.at(CDBType::CalTimeGain))); + inputs.emplace_back("tpctopologygain", gDataOriginTPC, "TOPOLOGYGAIN", 0, Lifetime::Condition, ccdbParamSpec(CDBTypeMap.at(CDBType::CalTopologyGain))); + inputs.emplace_back("tpcthreshold", gDataOriginTPC, "PADTHRESHOLD", 0, Lifetime::Condition, ccdbParamSpec("TPC/Config/FEEPad")); + } if (specconfig.decompressTPC) { inputs.emplace_back(InputSpec{"input", ConcreteDataTypeMatcher{gDataOriginTPC, specconfig.decompressTPCFromROOT ? o2::header::DataDescription("COMPCLUSTERS") : o2::header::DataDescription("COMPCLUSTERSFLAT")}, Lifetime::Timeframe}); } else if (specconfig.caClusterer) { + // if the output type are tracks, then the input spec for the gain map is already defined + if (!specconfig.outputTracks) { + inputs.emplace_back("tpcgain", gDataOriginTPC, "PADGAINFULL", 0, Lifetime::Condition, ccdbParamSpec(CDBTypeMap.at(CDBType::CalPadGainFull))); + } + // We accept digits and MC labels also if we run on ZS Raw data, since they are needed for MC label propagation if ((!specconfig.zsOnTheFly || specconfig.processMC) && !specconfig.zsDecoder) { inputs.emplace_back(InputSpec{"input", ConcreteDataTypeMatcher{gDataOriginTPC, "DIGITS"}, Lifetime::Timeframe});