From f60bda1429c4bf6b7a26c909ed42ff8fef7ea007 Mon Sep 17 00:00:00 2001 From: cortesep <57937610+cortesep@users.noreply.github.com> Date: Mon, 4 Dec 2023 13:02:55 +0100 Subject: [PATCH] Updates to ZDC reconstruction (#12365) * Update reconstruction objects (#83) * Update reconstruction objects * Update ZDCTowerParam.cxx * Tune intercalib (#84) * Small update to intercalibration * Small update to intercalibration * Please consider the following formatting changes (#81) --------- Co-authored-by: ALICE Builder * Tuning of intercalibration - WIP * - corrected centroid computation for ZP calorimeters - rms of ZP centroid - updates in Intercalibration - introduction of offsets for energy and amplitud calibration * Please consider the following formatting changes (#85) * Modify offset for channels that are directly calibrated * Fix bug * ADC and TDC offsets * Please consider the following formatting changes (#86) * Fixes * Amplitude cannot be calibrated in GeV. Use RecEventFlat to set unit of measurement * Fixes * Fixes * Fixes * Fixes * Please consider the following formatting changes (#87) --------- Co-authored-by: ALICE Builder --- .../ZDC/include/DataFormatsZDC/RecEventFlat.h | 19 ++ .../Detectors/ZDC/src/RecEventFlat.cxx | 245 ++++++++++++++++-- .../ZDC/base/include/ZDCBase/Constants.h | 64 ++--- .../ZDC/calib/include/ZDCCalib/InterCalib.h | 12 +- .../calib/include/ZDCCalib/InterCalibConfig.h | 37 ++- .../calib/include/ZDCCalib/InterCalibData.h | 6 +- .../calib/include/ZDCCalib/InterCalibEPN.h | 3 + Detectors/ZDC/calib/src/BaselineCalibSpec.cxx | 2 +- Detectors/ZDC/calib/src/InterCalib.cxx | 70 ++++- Detectors/ZDC/calib/src/InterCalibConfig.cxx | 8 +- Detectors/ZDC/calib/src/InterCalibEPN.cxx | 67 ++++- Detectors/ZDC/calib/src/NoiseCalibSpec.cxx | 14 +- Detectors/ZDC/macro/CreateInterCalibConfig.C | 4 +- .../include/ZDCReconstruction/DigiReco.h | 5 +- .../include/ZDCReconstruction/RecoParamZDC.h | 7 +- .../ZDCReconstruction/ZDCEnergyParam.h | 5 +- .../include/ZDCReconstruction/ZDCTDCParam.h | 9 +- .../include/ZDCReconstruction/ZDCTowerParam.h | 7 +- Detectors/ZDC/reconstruction/src/DigiReco.cxx | 40 ++- .../ZDC/reconstruction/src/ZDCEnergyParam.cxx | 32 +++ .../ZDC/reconstruction/src/ZDCTDCParam.cxx | 21 +- .../ZDC/reconstruction/src/ZDCTowerParam.cxx | 33 ++- 22 files changed, 588 insertions(+), 122 deletions(-) diff --git a/DataFormats/Detectors/ZDC/include/DataFormatsZDC/RecEventFlat.h b/DataFormats/Detectors/ZDC/include/DataFormatsZDC/RecEventFlat.h index 744d36d62e2dc..c47ac45373e4b 100644 --- a/DataFormats/Detectors/ZDC/include/DataFormatsZDC/RecEventFlat.h +++ b/DataFormats/Detectors/ZDC/include/DataFormatsZDC/RecEventFlat.h @@ -37,6 +37,21 @@ namespace zdc using FirstEntry = int; using NElem = int; +struct RecEventScale { + static std::array fe; + static std::array fa; + static void reset(); + static void setGeV(); + static void setGeVZN(); + static void setGeVZP(); + static void setTeV(); + static void setTeVZN(); + static void setTeVZP(); + static void setNucleonEnergy(float energy); + static void setNucleonEnergyZN(float energy); + static void setNucleonEnergyZP(float energy); +}; + struct RecEventFlat { // NOLINT: false positive in clang-tidy !! o2::InteractionRecord ir; uint32_t channels = 0; /// pattern of channels acquired @@ -244,12 +259,16 @@ struct RecEventFlat { // NOLINT: false positive in clang-tidy !! // Unit: cm void centroidZNA(float& x, float& y); void centroidZNC(float& x, float& y); + void centroidZPA(float& x, float& rms); + void centroidZPC(float& x, float& rms); float xZNA(); float yZNA(); float xZNC(); float yZNC(); float xZPA(); // Positive float xZPC(); // Negative + float rmsZPA(); + float rmsZPC(); void decodeInfo(uint8_t ch, uint16_t code); void decodeMapInfo(uint32_t ch, uint16_t code); diff --git a/DataFormats/Detectors/ZDC/src/RecEventFlat.cxx b/DataFormats/Detectors/ZDC/src/RecEventFlat.cxx index b5632285fd55f..44b69134bf3d8 100644 --- a/DataFormats/Detectors/ZDC/src/RecEventFlat.cxx +++ b/DataFormats/Detectors/ZDC/src/RecEventFlat.cxx @@ -15,6 +15,133 @@ using namespace o2::zdc; +std::array RecEventScale::fe = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; +std::array RecEventScale::fa = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + +void RecEventScale::reset() +{ + for (int ich = 0; ich < NChannels; ich++) { + fe[ich] = 1; + } + for (int itdc = 0; itdc < NTDCChannels; itdc++) { + fa[itdc] = 1; + } +} + +void RecEventScale::setGeV() +{ + for (int ich = 0; ich < NChannels; ich++) { + fe[ich] = 1; + } + for (int itdc = 0; itdc < NTDCChannels; itdc++) { + fa[itdc] = 1000.; + } +} + +void RecEventScale::setGeVZN() +{ + for (int ich = IdZNAC; ich <= IdZNASum; ich++) { + fe[ich] = 1; + } + for (int ich = IdZNCC; ich <= IdZNCSum; ich++) { + fe[ich] = 1; + } + fa[TDCZNAC] = 1000.; + fa[TDCZNAS] = 1000.; + fa[TDCZNCC] = 1000.; + fa[TDCZNCS] = 1000.; +} + +void RecEventScale::setGeVZP() +{ + for (int ich = IdZPAC; ich <= IdZPASum; ich++) { + fe[ich] = 1; + } + for (int ich = IdZPCC; ich <= IdZPCSum; ich++) { + fe[ich] = 1; + } + fa[TDCZPAC] = 1000.; + fa[TDCZPAS] = 1000.; + fa[TDCZPCC] = 1000.; + fa[TDCZPCS] = 1000.; +} + +void RecEventScale::setTeV() +{ + for (int ich = 0; ich < NChannels; ich++) { + fe[ich] = 0.001; + } + for (int itdc = 0; itdc < NTDCChannels; itdc++) { + fa[itdc] = 1.; + } +}; + +void RecEventScale::setTeVZN() +{ + for (int ich = IdZNAC; ich <= IdZNASum; ich++) { + fe[ich] = 0.001; + } + for (int ich = IdZNCC; ich <= IdZNCSum; ich++) { + fe[ich] = 0.001; + } + fa[TDCZNAC] = 1.; + fa[TDCZNAS] = 1.; + fa[TDCZNCC] = 1.; + fa[TDCZNCS] = 1.; +}; + +void RecEventScale::setTeVZP() +{ + for (int ich = IdZPAC; ich <= IdZPASum; ich++) { + fe[ich] = 0.001; + } + for (int ich = IdZPCC; ich <= IdZPCSum; ich++) { + fe[ich] = 0.001; + } + fa[TDCZPAC] = 1.; + fa[TDCZPAS] = 1.; + fa[TDCZPCC] = 1.; + fa[TDCZPCS] = 1.; +}; + +void RecEventScale::setNucleonEnergy(float energy) +{ // In GeV + for (int ich = 0; ich < NChannels; ich++) { + fe[ich] = 1. / energy; + } + for (int itdc = 0; itdc < NTDCChannels; itdc++) { + fa[itdc] = 1000. / energy; + } +}; + +void RecEventScale::setNucleonEnergyZN(float energy) +{ // In GeV + for (int ich = IdZNAC; ich <= IdZNASum; ich++) { + fe[ich] = 1. / energy; + } + for (int ich = IdZNCC; ich <= IdZNCSum; ich++) { + fe[ich] = 1. / energy; + } + fa[TDCZNAC] = 1000. / energy; + fa[TDCZNAS] = 1000. / energy; + fa[TDCZNCC] = 1000. / energy; + fa[TDCZNCS] = 1000. / energy; +}; + +void RecEventScale::setNucleonEnergyZP(float energy) +{ // In GeV + for (int ich = IdZPAC; ich <= IdZPASum; ich++) { + fe[ich] = 1. / energy; + } + for (int ich = IdZPCC; ich <= IdZPCSum; ich++) { + fe[ich] = 1. / energy; + } + fa[TDCZPAC] = 1000. / energy; + fa[TDCZPAS] = 1000. / energy; + fa[TDCZPCC] = 1000. / energy; + fa[TDCZPCS] = 1000. / energy; +}; + void RecEventFlat::init(const std::vector* RecBC, const std::vector* Energy, const std::vector* TDCData, const std::vector* Info) { mRecBC = *RecBC; @@ -143,7 +270,7 @@ int RecEventFlat::at(int ientry) for (int i = mFirstE; i < mStopE; i++) { auto myenergy = mEnergy[i]; auto ch = myenergy.ch(); - ezdc[ch] = myenergy.energy(); + ezdc[ch] = myenergy.energy() * RecEventScale::fe[ch]; // Assign implicit event info if (adcPedOr[ch] == false && adcPedQC[ch] == false && adcPedMissing[ch] == false) { adcPedEv[ch] = true; @@ -163,7 +290,7 @@ int RecEventFlat::at(int ientry) isEnd[ch] = true; } TDCVal[ch].push_back(mytdc.val); - TDCAmp[ch].push_back(mytdc.amp); + TDCAmp[ch].push_back(mytdc.amp * RecEventScale::fa[ch]); // Assign implicit event info if (tdcPedQC[ch] == false && tdcPedMissing[ch] == false) { tdcPedOr[ch] = true; @@ -386,13 +513,44 @@ float RecEventFlat::yZNC() float RecEventFlat::xZPA() { - // X coordinates of tower centers - // Positive because calorimeter is on the right of ZNA when looking - // from IP - const static float xc[4] = {2.8, 8.4, 14.0, 19.6}; + float x, rms; + centroidZPA(x, rms); + return x; +} + +float RecEventFlat::xZPC() +{ + float x, rms; + centroidZPC(x, rms); + return x; +} + +float RecEventFlat::rmsZPA() +{ + float x, rms; + centroidZPA(x, rms); + return rms; +} + +float RecEventFlat::rmsZPC() +{ + float x, rms; + centroidZPC(x, rms); + return rms; +} + +void RecEventFlat::centroidZPA(float& x, float& rms) +{ + // x coordinates of tower centers + // Negative because ZPA calorimeter is on the left of ZNA when looking from IP + // rms can result from 0 to sqrt((2.8^2+19.6^2)/2-((2.6+19.4)/2)^2) = 8.66 + const static float xc[4] = {-19.6, -14.0, -8.4, -2.8}; + const static float xq[4] = {19.6 * 19.6, 14.0 * 14.0, 8.4 * 8.4, 2.8 * 2.8}; static float c = 0; - if (mComputed[2]) { - return c; + static float d = 0; + if (mComputed[2] == true) { + x = c; + rms = d; } mComputed[2] = true; float e[4], w[4]; @@ -402,35 +560,56 @@ float RecEventFlat::xZPA() e[3] = EZDC(IdZPA4); if (e[0] < -1000000 || e[1] < -1000000 || e[2] < -1000000 || e[3] < -1000000) { c = -std::numeric_limits::infinity(); - return c; + d = -std::numeric_limits::infinity(); + x = c; + rms = d; + return; } float sumw = 0; c = 0; + d = 0; for (int i = 0; i < 4; i++) { if (e[i] < 0) { - e[i] = 0; + w[i] = 0; + } else { + // w[i] = std::sqrt(e[i]); + w[i] = e[i]; } - w[i] = std::sqrt(e[i]); sumw += w[i]; - c += w[i] * xc[i]; + c = c + w[i] * xc[i]; + d = d + w[i] * xq[i]; } if (sumw <= 0) { c = -std::numeric_limits::infinity(); + d = -std::numeric_limits::infinity(); } else { - c /= sumw; + c = c / sumw; + d = d / sumw; + d = d - c * c; // variance + if (d >= 0) { + d = TMath::Sqrt(d); + } else { + LOGF(error, "%s FOP exception @ %d", __FILE__, __LINE__); + d = -std::numeric_limits::infinity(); + } } - return c; + x = c; + rms = d; + return; } -float RecEventFlat::xZPC() +void RecEventFlat::centroidZPC(float& x, float& rms) { - // X coordinates of tower centers - // Negative because calorimeter is on the left of ZNC when looking - // from IP - const static float xc[4] = {-2.8, -8.4, -14.0, -19.6}; + // x coordinates of tower centers + // Positive because ZPC calorimeter is on the right of ZNC when looking from IP + // x can result in a value from 2.8 to 19.6 + const static float xc[4] = {2.8, 8.4, 14.0, 19.6}; + const static float xq[4] = {2.8 * 2.8, 8.4 * 8.4, 14.0 * 14.0, 19.6 * 19.6}; static float c = 0; + static float d = 0; if (mComputed[3]) { - return c; + x = c; + rms = d; } mComputed[3] = true; float e[4], w[4]; @@ -440,24 +619,42 @@ float RecEventFlat::xZPC() e[3] = EZDC(IdZPC4); if (e[0] < -1000000 || e[1] < -1000000 || e[2] < -1000000 || e[3] < -1000000) { c = -std::numeric_limits::infinity(); - return c; + d = -std::numeric_limits::infinity(); + x = c; + rms = d; + return; } float sumw = 0; c = 0; + d = 0; for (int i = 0; i < 4; i++) { if (e[i] < 0) { - e[i] = 0; + w[i] = 0; + } else { + // w[i] = std::sqrt(e[i]); + w[i] = e[i]; } - w[i] = std::sqrt(e[i]); sumw += w[i]; c += w[i] * xc[i]; + d += w[i] * xq[i]; } if (sumw <= 0) { c = -std::numeric_limits::infinity(); + d = -std::numeric_limits::infinity(); } else { c /= sumw; + d /= sumw; + d = d - c * c; // variance + if (d >= 0) { + d = TMath::Sqrt(d); + } else { + LOGF(error, "%s FOP exception @ %d", __FILE__, __LINE__); + d = -std::numeric_limits::infinity(); + } } - return c; + x = c; + rms = d; + return; } void RecEventFlat::print() const diff --git a/Detectors/ZDC/base/include/ZDCBase/Constants.h b/Detectors/ZDC/base/include/ZDCBase/Constants.h index e318b358ae38c..031d576e15eca 100644 --- a/Detectors/ZDC/base/include/ZDCBase/Constants.h +++ b/Detectors/ZDC/base/include/ZDCBase/Constants.h @@ -21,11 +21,12 @@ #include #include #include +#include // Enable debug printout in reconstruction -//#define O2_ZDC_DEBUG +// #define O2_ZDC_DEBUG // TDC arrays in debug output -//#define O2_ZDC_TDC_C_ARRAY +// #define O2_ZDC_TDC_C_ARRAY namespace o2 { @@ -70,7 +71,11 @@ constexpr int NLinks = NModules * 2; constexpr int NDigiChannels = NModules * NChPerModule; constexpr int NWPerBc = 3; constexpr int MaxTriggerChannels = NChannels; + +// Limits constexpr int ADCMin = -2048, ADCMax = 2047, ADCRange = 4096; // 12 bit ADC +constexpr float FInfty = std::numeric_limits::infinity(); +constexpr float DInfty = std::numeric_limits::infinity(); // Encoding of ZDC energy into an uint32_t value // Most significant 5 bits are for channel id, least significant 27 bits are for energy @@ -89,7 +94,7 @@ constexpr int TSL = 6; // number of zeros on the right (and o constexpr int TSN = 200; // Number of interpolated points between each pair = TSN-1 constexpr int TSNH = TSN / 2; // Half of TSN constexpr int NTS = 2 * TSL * TSN + 1; // Tapered sinc function array size -constexpr float FTDCAmp = 1. / 8.; // Multiplication factor in conversion from integer +constexpr float FTDCAmp = 1. / 8.; // Multiplication factor in conversion from integer - TODO increase precision assuming Amplitude>0 constexpr int NIS = NTimeBinsPerBC * TSN; // Number of interpolated samples // With a reference clock of 40 MHz exact this FTDCVal would have been // constexpr float FTDCVal = 1. / TSNS; @@ -141,36 +146,37 @@ constexpr uint32_t MaskZPC = 0x01f00000; constexpr uint32_t MaskAllZPC = 0x03f00000; constexpr std::string_view ChannelNames[] = { - "ZNAC", - "ZNA1", - "ZNA2", - "ZNA3", - "ZNA4", - "ZNAS", + "ZNAC", // 0 + "ZNA1", // 1 + "ZNA2", // 2 + "ZNA3", // 3 + "ZNA4", // 4 + "ZNAS", // 5 // - "ZPAC", - "ZPA1", - "ZPA2", - "ZPA3", - "ZPA4", - "ZPAS", + "ZPAC", // 6 + "ZPA1", // 7 + "ZPA2", // 8 + "ZPA3", // 9 + "ZPA4", // 10 + "ZPAS", // 11 // - "ZEM1", - "ZEM2", + "ZEM1", // 12 + "ZEM2", // 13 // - "ZNCC", - "ZNC1", - "ZNC2", - "ZNC3", - "ZNC4", - "ZNCS", + "ZNCC", // 14 + "ZNC1", // 15 + "ZNC2", // 16 + "ZNC3", // 17 + "ZNC4", // 18 + "ZNCS", // 19 // - "ZPCC", - "ZPC1", - "ZPC2", - "ZPC3", - "ZPC4", - "ZPCS"}; + "ZPCC", // 20 + "ZPC1", // 21 + "ZPC2", // 22 + "ZPC3", // 23 + "ZPC4", // 24 + "ZPCS" // 25 +}; // From TDC ID to signal ID const int TDCSignal[NTDCChannels] = { diff --git a/Detectors/ZDC/calib/include/ZDCCalib/InterCalib.h b/Detectors/ZDC/calib/include/ZDCCalib/InterCalib.h index 20a1eeb997613..d53d3ae1eec0f 100644 --- a/Detectors/ZDC/calib/include/ZDCCalib/InterCalib.h +++ b/Detectors/ZDC/calib/include/ZDCCalib/InterCalib.h @@ -45,6 +45,8 @@ class InterCalib static constexpr int HidZEM = 4; static constexpr int HidZNI = 5; static constexpr int HidZPI = 6; + static constexpr int HidZPAX = 7; + static constexpr int HidZPCX = 8; static constexpr int NH = InterCalibData::NH; static constexpr int NPAR = InterCalibData::NPAR; void clear(int ih = -1); @@ -82,10 +84,12 @@ class InterCalib int getVerbosity() const { return mVerbosity; } // Histograms for intercalibration of side C vs A are duplicate -> No title - static constexpr const char* mHUncN[2 * NH] = {"hZNAS", "hZPAS", "hZNCS", "hZPCS", "hZEM2", "", "", "hZNAC", "hZPAC", "hZNCC", "hZPCC", "hZEM1", "", ""}; - static constexpr const char* mHUncT[2 * NH] = {"ZNA sum", "ZPA sum", "ZNC sum", "ZPC sum", "ZEM2", "", "", "ZNA TC", "ZPA TC", "ZNC TC", "ZPC TC", "ZEM1", "", ""}; - static constexpr const char* mCUncN[NH] = {"cZNA", "cZPA", "cZNC", "cZPC", "cZEM", "cZNI", "cZPI"}; - static constexpr const char* mCUncT[NH] = {"ZNA;TC;SUM", "ZPA;TC;SUM", "ZNC;TC;SUM", "ZPC;TC;SUM", "ZEM;ZEM1;ZEM2", "ZN;ZNAC;ZNCC", "ZP;ZPAC;ZPCC"}; + static constexpr const char* mHUncN[2 * NH] = {"hZNAS", "hZPAS", "hZNCS", "hZPCS", "hZEM2", "", "", "hZPASX", "hZPCSX", + "hZNAC", "hZPAC", "hZNCC", "hZPCC", "hZEM1", "", "", "hZPACX", "hZPCCX"}; + static constexpr const char* mHUncT[2 * NH] = {"ZNA sum", "ZPA sum", "ZNC sum", "ZPC sum", "ZEM2", "", "", "ZPA sum", "ZPC sum", + "ZNA TC", "ZPA TC", "ZNC TC", "ZPC TC", "ZEM1", "", "", "ZPA TC", "ZPC TC"}; + static constexpr const char* mCUncN[NH] = {"cZNA", "cZPA", "cZNC", "cZPC", "cZEM", "cZNI", "cZPI", "cZPAX", "cZPCX"}; + static constexpr const char* mCUncT[NH] = {"ZNA;TC;SUM", "ZPA;TC;SUM", "ZNC;TC;SUM", "ZPC;TC;SUM", "ZEM;ZEM1;ZEM2", "ZN;ZNAC;ZNCC", "ZP;ZPAC;ZPCC", "ZPA (x cut);TC;SUM", "ZPC (x cut);TC;SUM"}; private: std::array*, 2 * NH> mHUnc{}; diff --git a/Detectors/ZDC/calib/include/ZDCCalib/InterCalibConfig.h b/Detectors/ZDC/calib/include/ZDCCalib/InterCalibConfig.h index 1ed7c74d06499..d9e729cd57f3f 100644 --- a/Detectors/ZDC/calib/include/ZDCCalib/InterCalibConfig.h +++ b/Detectors/ZDC/calib/include/ZDCCalib/InterCalibConfig.h @@ -27,22 +27,33 @@ namespace o2 namespace zdc { struct InterCalibConfig { - static constexpr int NH = 7; /// ZNA, ZPA, ZNC, ZPC, ZEM, ZNI, ZPI - bool enabled[NH] = {true, true, true, true, true, true, true}; - double cutLow[NH] = {-std::numeric_limits::infinity(), -std::numeric_limits::infinity(), -std::numeric_limits::infinity(), -std::numeric_limits::infinity(), -std::numeric_limits::infinity(), -std::numeric_limits::infinity(), -std::numeric_limits::infinity()}; - double cutHigh[NH] = {std::numeric_limits::infinity(), std::numeric_limits::infinity(), std::numeric_limits::infinity(), std::numeric_limits::infinity(), std::numeric_limits::infinity(), std::numeric_limits::infinity(), std::numeric_limits::infinity()}; + static constexpr int NH = 9; /// ZNA, ZPA, ZNC, ZPC, ZEM, ZNI, ZPI, ZPAX, ZPCX + bool enabled[NH] = {true, true, true, true, true, true, true, true, true}; + double cutLow[NH] = {-std::numeric_limits::infinity(), -std::numeric_limits::infinity(), -std::numeric_limits::infinity(), -std::numeric_limits::infinity(), -std::numeric_limits::infinity(), -std::numeric_limits::infinity(), -std::numeric_limits::infinity(), -std::numeric_limits::infinity(), -std::numeric_limits::infinity()}; + double cutHigh[NH] = {std::numeric_limits::infinity(), std::numeric_limits::infinity(), std::numeric_limits::infinity(), std::numeric_limits::infinity(), std::numeric_limits::infinity(), std::numeric_limits::infinity(), std::numeric_limits::infinity(), std::numeric_limits::infinity(), std::numeric_limits::infinity()}; + + // Distance from calorimeter side close to the beam (always positive) + // Meaningful values are in the range of tower x centers i.e. from + // 2.8 to 19.6 If one puts less than 2.8 then the computation will be + // the same as for ZPA/ZPC with no cuts + double xcut_ZPA = 6; + double xcut_ZPC = 6; + double tower_cut_ZP = 0; + bool cross_check = false; + int nb1[NH] = {0}; /// 1D histogram: number of bins double amin1[NH] = {0}; /// minimum double amax1[NH] = {0}; /// maximum int nb2[NH] = {0}; /// 2D histogram: number of bins double amin2[NH] = {0}; /// minimum double amax2[NH] = {0}; /// maximum - double l_bnd[NH] = {0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1}; - double u_bnd[NH] = {10., 10., 10., 10., 10., 10., 10.}; - double l_bnd_o[NH] = {-20., -20., -20., -20., -20., -20., -20.}; - double u_bnd_o[NH] = {20., 20., 20., 20., 20., 20., 20.}; - double step_o[NH] = {0., 0., 0., 0., 0., 0., 0.}; - double min_e[NH] = {0., 0., 0., 0., 0., 0., 0.}; + double start[NH] = {0.75, 0.75, 0.75, 0.75, 1., 1., 1., 0.75, 0.75}; + double l_bnd[NH] = {0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1}; + double u_bnd[NH] = {10., 10., 10., 10., 10., 10., 10., 10., 10.}; + double l_bnd_o[NH] = {-20., -20., -20., -20., -20., -20., -20., -20., -20.}; + double u_bnd_o[NH] = {20., 20., 20., 20., 20., 20., 20., 20., 20.}; + double step_o[NH] = {0., 0., 0., 0., 0., 0., 0., 0., 0.}; + double min_e[NH] = {0., 0., 0., 0., 0., 0., 0., 0., 0.}; std::string desc = ""; void print() const; @@ -64,7 +75,7 @@ struct InterCalibConfig { void setBinning1D(int ih, int nb, double amin, double amax); void setBinning2D(int ih, int nb, double amin, double amax); void setDescription(std::string d) { desc = d; } - void enable(bool c0, bool c1, bool c2, bool c3, bool c4, bool c5, bool c6) + void enable(bool c0, bool c1, bool c2, bool c3, bool c4, bool c5, bool c6, bool c7, bool c8) { enabled[0] = c0; enabled[1] = c1; @@ -73,8 +84,10 @@ struct InterCalibConfig { enabled[4] = c4; enabled[5] = c5; enabled[6] = c6; + enabled[7] = c7; + enabled[8] = c8; } - ClassDefNV(InterCalibConfig, 3); + ClassDefNV(InterCalibConfig, 4); }; } // namespace zdc } // namespace o2 diff --git a/Detectors/ZDC/calib/include/ZDCCalib/InterCalibData.h b/Detectors/ZDC/calib/include/ZDCCalib/InterCalibData.h index 13cdb7e2bd0dc..835a428b92ef8 100644 --- a/Detectors/ZDC/calib/include/ZDCCalib/InterCalibData.h +++ b/Detectors/ZDC/calib/include/ZDCCalib/InterCalibData.h @@ -27,16 +27,16 @@ namespace zdc struct InterCalibData { static constexpr int NPAR = 6; /// Dimension of matrix (1 + 4 coefficients + offset) - static constexpr int NH = 7; /// ZNA, ZPA, ZNC, ZPC, ZEM, ZNI, ZPI + static constexpr int NH = 9; /// ZNA, ZPA, ZNC, ZPC, ZEM, ZNI, ZPI, ZPAX, ZPCX double mSum[NH][NPAR][NPAR] = {0}; /// Cumulated sums uint64_t mCTimeBeg = 0; /// Time of processed time frame uint64_t mCTimeEnd = 0; /// Time of processed time frame - static constexpr const char* DN[NH] = {"ZNA", "ZPA", "ZNC", "ZPC", "ZEM", "ZNI", "ZPI"}; + static constexpr const char* DN[NH] = {"ZNA", "ZPA", "ZNC", "ZPC", "ZEM", "ZNI", "ZPI", "ZPAX", "ZPCX"}; InterCalibData& operator+=(const InterCalibData& other); int getEntries(int ih) const; void print() const; void setCreationTime(uint64_t ctime); - ClassDefNV(InterCalibData, 1); + ClassDefNV(InterCalibData, 2); }; } // namespace zdc diff --git a/Detectors/ZDC/calib/include/ZDCCalib/InterCalibEPN.h b/Detectors/ZDC/calib/include/ZDCCalib/InterCalibEPN.h index 0296b0bda40b8..90431e1c11221 100644 --- a/Detectors/ZDC/calib/include/ZDCCalib/InterCalibEPN.h +++ b/Detectors/ZDC/calib/include/ZDCCalib/InterCalibEPN.h @@ -22,6 +22,7 @@ #include "DataFormatsZDC/RecEvent.h" #include "ZDCReconstruction/ZDCEnergyParam.h" #include "ZDCReconstruction/ZDCTowerParam.h" +#include "ZDCCalib/InterCalib.h" #include "ZDCCalib/InterCalibData.h" #include "ZDCCalib/InterCalibConfig.h" #ifndef ALICEO2_ZDC_INTERCALIBEPN_H_ @@ -42,6 +43,8 @@ class InterCalibEPN static constexpr int HidZEM = 4; static constexpr int HidZNI = 5; static constexpr int HidZPI = 6; + static constexpr int HidZPAX = 7; + static constexpr int HidZPCX = 8; static constexpr int NH = InterCalibData::NH; static constexpr int NPAR = InterCalibData::NPAR; void clear(int ih = -1); diff --git a/Detectors/ZDC/calib/src/BaselineCalibSpec.cxx b/Detectors/ZDC/calib/src/BaselineCalibSpec.cxx index 5584ce0731b69..362f118b873de 100644 --- a/Detectors/ZDC/calib/src/BaselineCalibSpec.cxx +++ b/Detectors/ZDC/calib/src/BaselineCalibSpec.cxx @@ -230,7 +230,7 @@ framework::DataProcessorSpec getBaselineCalibSpec() using clbUtils = o2::calibration::Utils; std::vector inputs; - inputs.emplace_back("basecalibdata", "ZDC", "BASECALIBDATA", 0, Lifetime::Timeframe); + inputs.emplace_back("basecalibdata", "ZDC", "BASECALIBDATA", 0, Lifetime::Sporadic); inputs.emplace_back("calibconfig", "ZDC", "BASECALIBCONFIG", 0, Lifetime::Condition, o2::framework::ccdbParamSpec(o2::zdc::CCDBPathBaselineCalibConfig.data())); inputs.emplace_back("moduleconfig", "ZDC", "MODULECONFIG", 0, Lifetime::Condition, o2::framework::ccdbParamSpec(o2::zdc::CCDBPathConfigModule.data())); diff --git a/Detectors/ZDC/calib/src/InterCalib.cxx b/Detectors/ZDC/calib/src/InterCalib.cxx index 3997065bc225a..dc75b172a3aca 100644 --- a/Detectors/ZDC/calib/src/InterCalib.cxx +++ b/Detectors/ZDC/calib/src/InterCalib.cxx @@ -188,6 +188,8 @@ void InterCalib::assign(int ih, bool ismod) int id_4[1] = {IdZEM2}; int id_5[1] = {IdZNCC}; int id_6[1] = {IdZPCC}; + int id_7[4] = {IdZPA1, IdZPA2, IdZPA3, IdZPA4}; + int id_8[4] = {IdZPC1, IdZPC2, IdZPC3, IdZPC4}; int nid = 0; int* id = nullptr; if (ih == 0) { @@ -215,6 +217,24 @@ void InterCalib::assign(int ih, bool ismod) id = id_6; LOG(warn) << "InterCalib::assign unimplemented coefficient ih = " << ih; return; + } else if (ih == 7 || ih == 8) { + nid = 4; + if (ih == 7) { + id = id_7; + } else if (ih == 8) { + id = id_8; + } + // LOG(warn) << "InterCalib::assign MANUAL ASSIGNMENT for ih = " << ih; + // if (mVerbosity > DbgZero) { + // for (int iid = 0; iid < nid; iid++) { + // auto ich = id[iid]; + // auto oldval = mTowerParam->getTowerCalib(ich); + // auto val = oldval; + // val = val * mPar[ih][iid + 1]; + // LOGF(info, "%s MANUAL UPDATING %8.6f -> %8.6f", ChannelNames[ich].data(), oldval, val); + // } + // } + // return; } else { LOG(fatal) << "InterCalib::assign accessing not existing ih = " << ih; } @@ -470,23 +490,50 @@ int InterCalib::mini(int ih) int ierflg = 0; double l_bnd = mInterCalibConfig->l_bnd[ih]; double u_bnd = mInterCalibConfig->u_bnd[ih]; - double start = 1.0; + double start = mInterCalibConfig->start[ih]; double step = 0.1; mMn[ih] = std::make_unique(NPAR); mMn[ih]->SetFCN(fcn); + // We introduce the calibration of the common PM in separate workflows + // Calibration cvoefficient is forced to and step is forced to zero mMn[ih]->mnparm(0, "c0", 1., 0., 1., 1., ierflg); - mMn[ih]->mnparm(1, "c1", start, step, l_bnd, u_bnd, ierflg); + + // Special fit for proton calorimeters: fit least exposed towers with using previous + // fit of all towers + + // Tower 1 + if (ih == HidZPCX) { + mMn[ih]->mnparm(1, "c1", mPar[HidZPC][1], 0, l_bnd, u_bnd, ierflg); + } else { + mMn[ih]->mnparm(1, "c1", start, step, l_bnd, u_bnd, ierflg); + } + + // Tower 2 // Only two ZEM calorimeters: equalize response // Equalize side A and C - if (ih == 4 || ih == 5 || ih == 6) { + if (ih == HidZEM || ih == HidZNI || ih == HidZPI) { l_bnd = 0; u_bnd = 0; start = 0; step = 0; } - mMn[ih]->mnparm(2, "c2", start, step, l_bnd, u_bnd, ierflg); - mMn[ih]->mnparm(3, "c3", start, step, l_bnd, u_bnd, ierflg); - mMn[ih]->mnparm(4, "c4", start, step, l_bnd, u_bnd, ierflg); + + if (ih == HidZPCX) { + mMn[ih]->mnparm(2, "c2", mPar[HidZPC][2], 0, l_bnd, u_bnd, ierflg); + } else { + mMn[ih]->mnparm(2, "c2", start, step, l_bnd, u_bnd, ierflg); + } + + // Towers 3 and 4 + if (ih == HidZPAX) { + mMn[ih]->mnparm(3, "c3", mPar[HidZPA][3], 0, l_bnd, u_bnd, ierflg); + mMn[ih]->mnparm(4, "c4", mPar[HidZPA][4], 0, l_bnd, u_bnd, ierflg); + } else { + mMn[ih]->mnparm(3, "c3", start, step, l_bnd, u_bnd, ierflg); + mMn[ih]->mnparm(4, "c4", start, step, l_bnd, u_bnd, ierflg); + } + + // Offset l_bnd = mInterCalibConfig->l_bnd_o[ih]; u_bnd = mInterCalibConfig->u_bnd_o[ih]; start = 0; @@ -497,7 +544,7 @@ int InterCalib::mini(int ih) mMn[ih]->GetParameter(i, mPar[ih][i], mErr[ih][i]); } // Fallback in case fit fails on proton calorimeters - if (ih == 1 || ih == 3) { + if (ih == 1 || ih == 3 || ih == 7 || ih == 8) { for (int iretry = 0; iretry < 2; iretry++) { bool retry = false; const char* parn[5] = {"c0fix", "c1fix", "c2fix", "c3fix", "c4fix"}; @@ -507,9 +554,9 @@ int InterCalib::mini(int ih) if (TMath::Abs(mPar[ih][i] - l_bnd) < 1e-3 || TMath::Abs(mPar[ih][i] - u_bnd) < 1e-3) { retry = true; LOG(warn) << "ih=" << ih << " par " << i << " too close to boundaries"; - if (ih == 1) { + if (ih == 1 || ih == 7) { mMn[ih]->mnparm(i, parn[i], mTowerParam->tower_calib[IdZPAC + i], 0, l_bnd, u_bnd, ierflg); - } else if (ih == 3) { + } else if (ih == 3 || ih == 8) { mMn[ih]->mnparm(i, parn[i], mTowerParam->tower_calib[IdZPCC + i], 0, l_bnd, u_bnd, ierflg); } else { LOG(fatal) << "ERROR on InterCalib minimization ih=" << ih; @@ -522,6 +569,9 @@ int InterCalib::mini(int ih) for (Int_t i = 0; i < NPAR; i++) { mMn[ih]->GetParameter(i, mPar[ih][i], mErr[ih][i]); } + if (ierflg == 0) { + break; + } } } } @@ -563,7 +613,7 @@ int InterCalib::saveDebugHistos(const std::string fn) } } // Minimization output - const char* mntit[NH] = {"mZNA", "mZPA", "mZNC", "mZPC", "mZEM", "mZNI", "mZPI"}; + const char* mntit[NH] = {"mZNA", "mZPA", "mZNC", "mZPC", "mZEM", "mZNI", "mZPI", "mZPAX", "mZPCX"}; for (int32_t ih = 0; ih < NH; ih++) { if (mMn[ih]) { mMn[ih]->Write(mntit[ih], TObject::kOverwrite); diff --git a/Detectors/ZDC/calib/src/InterCalibConfig.cxx b/Detectors/ZDC/calib/src/InterCalibConfig.cxx index d0caff4c97d40..f70420eb6b67a 100644 --- a/Detectors/ZDC/calib/src/InterCalibConfig.cxx +++ b/Detectors/ZDC/calib/src/InterCalibConfig.cxx @@ -16,7 +16,7 @@ using namespace o2::zdc; void InterCalibConfig::print() const { - const char* hn[NH] = {"ZNA", "ZPA", "ZNC", "ZPC", "ZEM", "ZNI", "ZPI"}; + const char* hn[NH] = {"ZNA", "ZPA", "ZNC", "ZPC", "ZEM", "ZNI", "ZPI", "ZPAX", "ZPCX"}; for (Int_t ih = 0; ih < NH; ih++) { LOG(info) << hn[ih] << " limits = (" << cutLow[ih] << " : " << cutHigh[ih] << ")"; } @@ -26,6 +26,12 @@ void InterCalibConfig::print() const for (Int_t ih = 0; ih < NH; ih++) { LOG(info) << hn[ih] << " booking 2D = (" << nb2[ih] << ", " << amin2[ih] << ", " << amax2[ih] << ")"; } + LOG(info) << "xcut_ZPA = " << xcut_ZPA; + LOG(info) << "xcut_ZPC = " << xcut_ZPC; + LOG(info) << "tower_cut_ZP = " << tower_cut_ZP; + if (cross_check) { + LOG(warn) << "THIS IS A CROSS CHECK CONFIGURATION (vs SUM)"; + } } void InterCalibConfig::setMinEntries(double val) diff --git a/Detectors/ZDC/calib/src/InterCalibEPN.cxx b/Detectors/ZDC/calib/src/InterCalibEPN.cxx index 02107224907b9..3f17d256c042f 100644 --- a/Detectors/ZDC/calib/src/InterCalibEPN.cxx +++ b/Detectors/ZDC/calib/src/InterCalibEPN.cxx @@ -94,18 +94,58 @@ int InterCalibEPN::process(const gsl::span& RecBC, // Skip! continue; } - if ((ev.ezdcDecoded & MaskZNA) == MaskZNA) { - cumulate(HidZNA, ev.EZDC(IdZNAC), ev.EZDC(IdZNA1), ev.EZDC(IdZNA2), ev.EZDC(IdZNA3), ev.EZDC(IdZNA4), 1.); - } - if ((ev.ezdcDecoded & MaskZPA) == MaskZPA) { - cumulate(HidZPA, ev.EZDC(IdZPAC), ev.EZDC(IdZPA1), ev.EZDC(IdZPA2), ev.EZDC(IdZPA3), ev.EZDC(IdZPA4), 1.); - } - if ((ev.ezdcDecoded & MaskZNC) == MaskZNC) { - cumulate(HidZNC, ev.EZDC(IdZNCC), ev.EZDC(IdZNC1), ev.EZDC(IdZNC2), ev.EZDC(IdZNC3), ev.EZDC(IdZNC4), 1.); + // Select hadronic collisions by requiring a signal in ZEM calorimeters + if (ev.TDCVal[TDCZEM1].size() == 0 || ev.TDCVal[TDCZEM2].size() == 0) { + continue; } - if ((ev.ezdcDecoded & MaskZPC) == MaskZPC) { - cumulate(HidZPC, ev.EZDC(IdZPCC), ev.EZDC(IdZPC1), ev.EZDC(IdZPC2), ev.EZDC(IdZPC3), ev.EZDC(IdZPC4), 1.); + if (mInterCalibConfig->cross_check == false) { + if ((ev.ezdcDecoded & MaskZNA) == MaskZNA) { + cumulate(HidZNA, ev.EZDC(IdZNAC), ev.EZDC(IdZNA1), ev.EZDC(IdZNA2), ev.EZDC(IdZNA3), ev.EZDC(IdZNA4), 1.); + } + if ((ev.ezdcDecoded & MaskZPA) == MaskZPA) { + float x, rms; + ev.centroidZPA(x, rms); + cumulate(HidZPA, ev.EZDC(IdZPAC), ev.EZDC(IdZPA1), ev.EZDC(IdZPA2), ev.EZDC(IdZPA3), ev.EZDC(IdZPA4), 1.); + if (x < -(mInterCalibConfig->xcut_ZPA)) { + cumulate(HidZPAX, ev.EZDC(IdZPAC), ev.EZDC(IdZPA1), ev.EZDC(IdZPA2), ev.EZDC(IdZPA3), ev.EZDC(IdZPA4), 1.); + } + } + if ((ev.ezdcDecoded & MaskZNC) == MaskZNC) { + cumulate(HidZNC, ev.EZDC(IdZNCC), ev.EZDC(IdZNC1), ev.EZDC(IdZNC2), ev.EZDC(IdZNC3), ev.EZDC(IdZNC4), 1.); + } + if ((ev.ezdcDecoded & MaskZPC) == MaskZPC) { + float x, rms; + ev.centroidZPC(x, rms); + cumulate(HidZPC, ev.EZDC(IdZPCC), ev.EZDC(IdZPC1), ev.EZDC(IdZPC2), ev.EZDC(IdZPC3), ev.EZDC(IdZPC4), 1.); + if (x > (mInterCalibConfig->xcut_ZPC)) { + cumulate(HidZPCX, ev.EZDC(IdZPCC), ev.EZDC(IdZPC1), ev.EZDC(IdZPC2), ev.EZDC(IdZPC3), ev.EZDC(IdZPC4), 1.); + } + } + } else { + if ((ev.ezdcDecoded & MaskAllZNA) == MaskAllZNA) { + cumulate(HidZNA, ev.EZDC(IdZNASum), ev.EZDC(IdZNA1), ev.EZDC(IdZNA2), ev.EZDC(IdZNA3), ev.EZDC(IdZNA4), 1.); + } + if ((ev.ezdcDecoded & MaskAllZPA) == MaskAllZPA) { + float x, rms; + ev.centroidZPA(x, rms); + cumulate(HidZPA, ev.EZDC(IdZPASum), ev.EZDC(IdZPA1), ev.EZDC(IdZPA2), ev.EZDC(IdZPA3), ev.EZDC(IdZPA4), 1.); + if (x < -(mInterCalibConfig->xcut_ZPA)) { + cumulate(HidZPAX, ev.EZDC(IdZPASum), ev.EZDC(IdZPA1), ev.EZDC(IdZPA2), ev.EZDC(IdZPA3), ev.EZDC(IdZPA4), 1.); + } + } + if ((ev.ezdcDecoded & MaskAllZNC) == MaskAllZNC) { + cumulate(HidZNC, ev.EZDC(IdZNCSum), ev.EZDC(IdZNC1), ev.EZDC(IdZNC2), ev.EZDC(IdZNC3), ev.EZDC(IdZNC4), 1.); + } + if ((ev.ezdcDecoded & MaskAllZPC) == MaskAllZPC) { + float x, rms; + ev.centroidZPC(x, rms); + cumulate(HidZPC, ev.EZDC(IdZPCSum), ev.EZDC(IdZPC1), ev.EZDC(IdZPC2), ev.EZDC(IdZPC3), ev.EZDC(IdZPC4), 1.); + if (x > (mInterCalibConfig->xcut_ZPC)) { + cumulate(HidZPCX, ev.EZDC(IdZPCSum), ev.EZDC(IdZPC1), ev.EZDC(IdZPC2), ev.EZDC(IdZPC3), ev.EZDC(IdZPC4), 1.); + } + } } + if ((ev.ezdcDecoded & MaskZEM) == MaskZEM) { cumulate(HidZEM, ev.EZDC(IdZEM1), ev.EZDC(IdZEM2), 0., 0., 0., 1.); } @@ -165,6 +205,10 @@ int InterCalibEPN::process(const char* hname, int ic) ih = HidZNI; } else if (hn.EqualTo("hZPI")) { ih = HidZPI; + } else if (hn.EqualTo("hZPAX")) { + ih = HidZPAX; + } else if (hn.EqualTo("hZPCX")) { + ih = HidZPCX; } else { LOGF(error, "Not recognized histogram name: %s\n", hname); return -1; @@ -226,6 +270,9 @@ void InterCalibEPN::cumulate(int ih, double tc, double t1, double t2, double t3, if (tc < mInterCalibConfig->cutLow[ih] || tc > mInterCalibConfig->cutHigh[ih]) { return; } + if ((ih == 7 || ih == 8) && (t1 < mInterCalibConfig->tower_cut_ZP || t2 < mInterCalibConfig->tower_cut_ZP || t3 < mInterCalibConfig->tower_cut_ZP || t4 < mInterCalibConfig->tower_cut_ZP)) { + return; + } double val[NPAR] = {0, 0, 0, 0, 0, 1}; val[0] = tc; val[1] = t1; diff --git a/Detectors/ZDC/calib/src/NoiseCalibSpec.cxx b/Detectors/ZDC/calib/src/NoiseCalibSpec.cxx index 035432994dfc7..8b5269ececbe3 100644 --- a/Detectors/ZDC/calib/src/NoiseCalibSpec.cxx +++ b/Detectors/ZDC/calib/src/NoiseCalibSpec.cxx @@ -99,7 +99,7 @@ void NoiseCalibSpec::run(ProcessingContext& pc) mRunNumber = tinfo.runNumber; } { - std::vector filterHisto = {{"noise_1dh", ConcreteDataTypeMatcher{"ZDC", "NOISE_1DH"}, Lifetime::Timeframe}}; + std::vector filterHisto = {{"noise_1dh", ConcreteDataTypeMatcher{"ZDC", "NOISE_1DH"}, Lifetime::Sporadic}}; for (auto const& inputRef : InputRecordWalker(pc.inputs(), filterHisto)) { auto const* dh = framework::DataRefUtils::getHeader(inputRef); o2::dataformats::FlatHisto1D histoView(pc.inputs().get>(inputRef)); @@ -107,7 +107,7 @@ void NoiseCalibSpec::run(ProcessingContext& pc) } } { - std::vector filterHisto = {{"noise_1dh_s", ConcreteDataTypeMatcher{"ZDC", "NOISE_1DH_S"}, Lifetime::Timeframe}}; + std::vector filterHisto = {{"noise_1dh_s", ConcreteDataTypeMatcher{"ZDC", "NOISE_1DH_S"}, Lifetime::Sporadic}}; for (auto const& inputRef : InputRecordWalker(pc.inputs(), filterHisto)) { auto const* dh = framework::DataRefUtils::getHeader(inputRef); o2::dataformats::FlatHisto1D histoView(pc.inputs().get>(inputRef)); @@ -115,7 +115,7 @@ void NoiseCalibSpec::run(ProcessingContext& pc) } } { - std::vector filterHisto = {{"noise_1dh_d", ConcreteDataTypeMatcher{"ZDC", "NOISE_1DH_D"}, Lifetime::Timeframe}}; + std::vector filterHisto = {{"noise_1dh_d", ConcreteDataTypeMatcher{"ZDC", "NOISE_1DH_D"}, Lifetime::Sporadic}}; for (auto const& inputRef : InputRecordWalker(pc.inputs(), filterHisto)) { auto const* dh = framework::DataRefUtils::getHeader(inputRef); o2::dataformats::FlatHisto1D histoView(pc.inputs().get>(inputRef)); @@ -199,11 +199,11 @@ framework::DataProcessorSpec getNoiseCalibSpec() using clbUtils = o2::calibration::Utils; std::vector inputs; - inputs.emplace_back("noisecalibdata", "ZDC", "NOISECALIBDATA", 0, Lifetime::Timeframe); + inputs.emplace_back("noisecalibdata", "ZDC", "NOISECALIBDATA", 0, Lifetime::Sporadic); inputs.emplace_back("moduleconfig", "ZDC", "MODULECONFIG", 0, Lifetime::Condition, o2::framework::ccdbParamSpec(o2::zdc::CCDBPathConfigModule.data())); - inputs.emplace_back("noise_1dh", ConcreteDataTypeMatcher{"ZDC", "NOISE_1DH"}, Lifetime::Timeframe); - inputs.emplace_back("noise_1dh_s", ConcreteDataTypeMatcher{"ZDC", "NOISE_1DH_S"}, Lifetime::Timeframe); - inputs.emplace_back("noise_1dh_d", ConcreteDataTypeMatcher{"ZDC", "NOISE_1DH_D"}, Lifetime::Timeframe); + inputs.emplace_back("noise_1dh", ConcreteDataTypeMatcher{"ZDC", "NOISE_1DH"}, Lifetime::Sporadic); + inputs.emplace_back("noise_1dh_s", ConcreteDataTypeMatcher{"ZDC", "NOISE_1DH_S"}, Lifetime::Sporadic); + inputs.emplace_back("noise_1dh_d", ConcreteDataTypeMatcher{"ZDC", "NOISE_1DH_D"}, Lifetime::Sporadic); std::vector outputs; outputs.emplace_back(ConcreteDataTypeMatcher{o2::calibration::Utils::gDataOriginCDBPayload, "ZDCNoisecalib"}, Lifetime::Sporadic); diff --git a/Detectors/ZDC/macro/CreateInterCalibConfig.C b/Detectors/ZDC/macro/CreateInterCalibConfig.C index c960404f92f46..915b55b42d2eb 100644 --- a/Detectors/ZDC/macro/CreateInterCalibConfig.C +++ b/Detectors/ZDC/macro/CreateInterCalibConfig.C @@ -37,8 +37,8 @@ void CreateInterCalibConfig(long tmin = 0, long tmax = -1, std::string ccdbHost // Enable intercalibration for all calorimeters // If intercalibration is disabled the intercalibration coefficients // are copied from previous valid object and flagged as not modified - // ZNA ZPA ZNC ZPC ZEM2 ZNI ZPI - conf.enable(true, true, true, true, true, false, false); + // ZNA ZPA ZNC ZPC ZEM2 ZNI ZPI ZPAX ZPCX + conf.enable(true, true, true, true, true, false, false, true, true); // The version for this macro considers NO energy calibration, i.e. all coefficients = 1 // It is necessary to set the binning diff --git a/Detectors/ZDC/reconstruction/include/ZDCReconstruction/DigiReco.h b/Detectors/ZDC/reconstruction/include/ZDCReconstruction/DigiReco.h index f611da568b2a8..88fe7b3d21dc4 100644 --- a/Detectors/ZDC/reconstruction/include/ZDCReconstruction/DigiReco.h +++ b/Detectors/ZDC/reconstruction/include/ZDCReconstruction/DigiReco.h @@ -207,8 +207,9 @@ class DigiReco int mLonely[o2::constants::lhc::LHCMaxBunches] = {0}; int mLonelyTrig[o2::constants::lhc::LHCMaxBunches] = {0}; uint32_t mMissingPed[NChannels] = {0}; - int16_t tdc_shift[NTDCChannels] = {0}; /// TDC correction (units of 1/96 ns) - float tdc_calib[NTDCChannels] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; /// TDC correction factor + int16_t tdc_shift[NTDCChannels] = {0}; /// TDC correction (units of 1/96 ns) + float tdc_calib[NTDCChannels] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; /// TDC correction factor + float tdc_offset[NTDCChannels] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /// TDC offset constexpr static uint16_t mMask[NTimeBinsPerBC] = {0x0001, 0x002, 0x004, 0x008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800}; O2_ZDC_DIGIRECO_FLT mAlpha = 3; // Parameter of interpolation function // Configuration of interpolation for current TDC diff --git a/Detectors/ZDC/reconstruction/include/ZDCReconstruction/RecoParamZDC.h b/Detectors/ZDC/reconstruction/include/ZDCReconstruction/RecoParamZDC.h index fe5652da6fc15..e7d1c0f09b561 100644 --- a/Detectors/ZDC/reconstruction/include/ZDCReconstruction/RecoParamZDC.h +++ b/Detectors/ZDC/reconstruction/include/ZDCReconstruction/RecoParamZDC.h @@ -48,6 +48,8 @@ struct RecoParamZDC : public o2::conf::ConfigurableParamHelper { float tdc_calib[NTDCChannels] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; // Correction of TDC amplitude float tdc_search[NTDCChannels] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; // Search zone for a TDC signal ideally 2.5 ns (units of ~10 ps) + float tdc_offset[NTDCChannels] = {-FInfty, -FInfty, -FInfty, -FInfty, -FInfty, -FInfty, -FInfty, -FInfty, -FInfty, -FInfty}; // Compensation of TDC amplitude offset + // Enable extended search at beginning of first bunch bool setExtendedSearch = false; bool doExtendedSearch = false; @@ -69,9 +71,10 @@ struct RecoParamZDC : public o2::conf::ConfigurableParamHelper { float ped_thr_hi[NChannels] = {ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange}; float ped_thr_lo[NChannels] = {ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange, ADCRange}; - // Energy calibration float energy_calib[NChannels] = {0}; // Energy calibration coefficients - float tower_calib[NChannels] = {0}; // Tower calibration coefficients + // Compensation of ADC offset + float adc_offset[NChannels] = {-FInfty, -FInfty, -FInfty, -FInfty, -FInfty, -FInfty, -FInfty, -FInfty, -FInfty, -FInfty, -FInfty, -FInfty, -FInfty, -FInfty, -FInfty, -FInfty, -FInfty, -FInfty, -FInfty, -FInfty, -FInfty, -FInfty, -FInfty, -FInfty, -FInfty, -FInfty}; + float tower_calib[NChannels] = {0}; // Tower calibration coefficients void print(); diff --git a/Detectors/ZDC/reconstruction/include/ZDCReconstruction/ZDCEnergyParam.h b/Detectors/ZDC/reconstruction/include/ZDCReconstruction/ZDCEnergyParam.h index 60331d80b896c..0ebf9e1f37b89 100644 --- a/Detectors/ZDC/reconstruction/include/ZDCReconstruction/ZDCEnergyParam.h +++ b/Detectors/ZDC/reconstruction/include/ZDCReconstruction/ZDCEnergyParam.h @@ -26,10 +26,13 @@ namespace zdc { struct ZDCEnergyParam { float energy_calib[NChannels] = {0}; // Energy calibration coefficients + float adc_offset[NChannels] = {0}; // Compensation of ADC offset void setEnergyCalib(uint32_t ich, float val); float getEnergyCalib(uint32_t ich) const; + void setOffset(uint32_t ich, float val); + float getOffset(uint32_t ich) const; void print() const; - ClassDefNV(ZDCEnergyParam, 1); + ClassDefNV(ZDCEnergyParam, 2); }; } // namespace zdc } // namespace o2 diff --git a/Detectors/ZDC/reconstruction/include/ZDCReconstruction/ZDCTDCParam.h b/Detectors/ZDC/reconstruction/include/ZDCReconstruction/ZDCTDCParam.h index 32f10ccb4036b..6933538650dd1 100644 --- a/Detectors/ZDC/reconstruction/include/ZDCReconstruction/ZDCTDCParam.h +++ b/Detectors/ZDC/reconstruction/include/ZDCReconstruction/ZDCTDCParam.h @@ -25,14 +25,17 @@ namespace o2 namespace zdc { struct ZDCTDCParam { - float tdc_shift[NTDCChannels] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // Correction of TDC position (ns) - float tdc_calib[NTDCChannels] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; // Correction factor of TDC amplitude + float tdc_shift[NTDCChannels] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // Correction of TDC position (ns) + float tdc_calib[NTDCChannels] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; // Correction factor of TDC amplitude + float tdc_offset[NTDCChannels] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // Offset of TDC amplitude calibration void setShift(uint32_t ich, float val); float getShift(uint32_t ich) const; void setFactor(uint32_t ich, float val); float getFactor(uint32_t ich) const; + void setOffset(uint32_t ich, float val); + float getOffset(uint32_t ich) const; void print() const; - ClassDefNV(ZDCTDCParam, 2); + ClassDefNV(ZDCTDCParam, 3); }; } // namespace zdc } // namespace o2 diff --git a/Detectors/ZDC/reconstruction/include/ZDCReconstruction/ZDCTowerParam.h b/Detectors/ZDC/reconstruction/include/ZDCReconstruction/ZDCTowerParam.h index 544c26753839b..11a3ea9d2fbbf 100644 --- a/Detectors/ZDC/reconstruction/include/ZDCReconstruction/ZDCTowerParam.h +++ b/Detectors/ZDC/reconstruction/include/ZDCReconstruction/ZDCTowerParam.h @@ -25,7 +25,8 @@ namespace o2 namespace zdc { struct ZDCTowerParam { - float tower_calib[NChannels] = {0}; // Tower calibration coefficients + float tower_calib[NChannels] = {0}; // Tower calibration coefficients + float tower_offset[NChannels] = {0}; // Tower offset std::array modified{}; ZDCTowerParam() { @@ -34,8 +35,10 @@ struct ZDCTowerParam { void clearFlags(); void setTowerCalib(uint32_t ich, float val, bool ismodified = true); float getTowerCalib(uint32_t ich) const; + void setTowerOffset(uint32_t ich, float val, bool ismodified = true); + float getTowerOffset(uint32_t ich) const; void print() const; - ClassDefNV(ZDCTowerParam, 2); + ClassDefNV(ZDCTowerParam, 3); }; } // namespace zdc } // namespace o2 diff --git a/Detectors/ZDC/reconstruction/src/DigiReco.cxx b/Detectors/ZDC/reconstruction/src/DigiReco.cxx index bdf66c8a45a77..f3e22c9ece54f 100644 --- a/Detectors/ZDC/reconstruction/src/DigiReco.cxx +++ b/Detectors/ZDC/reconstruction/src/DigiReco.cxx @@ -233,7 +233,7 @@ void DigiReco::init() if (fval < 0) { // Check if calibration object is present if (!mTDCParam) { - LOG(fatal) << "TDC " << itdc << " missing configuration object and no manual override"; + LOG(fatal) << "TDC amplitude calibration " << itdc << " missing configuration object and no manual override"; } else { fval = mTDCParam->getFactor(itdc); } @@ -242,8 +242,22 @@ void DigiReco::init() LOG(fatal) << "Correction factor for TDC amplitude " << itdc << " " << fval << " is out of range"; } tdc_calib[itdc] = fval; + fval = ropt.tdc_offset[itdc]; + // If the reconstruction parameters were not manually set + if (fval == -FInfty) { + // Check if calibration object is present + if (!mTDCParam) { + LOG(fatal) << "TDC offset correction " << itdc << " missing configuration object and no manual override"; + } else { + fval = mTDCParam->getOffset(itdc); + } + } + if (fval <= -ADCRange || fval >= ADCRange) { + LOG(fatal) << "TDC offset correction " << itdc << " " << fval << " is out of range"; + } + tdc_offset[itdc] = fval; if (mVerbosity > DbgZero) { - LOG(info) << itdc << " " << ChannelNames[TDCSignal[itdc]] << " factor= " << tdc_calib[itdc]; + LOG(info) << itdc << " " << ChannelNames[TDCSignal[itdc]] << " factor= " << tdc_calib[itdc] << " offset= " << tdc_offset[itdc]; } } @@ -284,6 +298,7 @@ void DigiReco::init() } // Tower calibration (intercalibration of towers) + // Array ChTowerCalib defines which channels use this calibration: ZN and ZP towers + ZEM2 for (int il = 0; il < ChTowerCalib.size(); il++) { if (ropt.tower_calib[ChTowerCalib[il]] > 0) { LOG(info) << "Tower Calibration from command line " << ChannelNames[ChTowerCalib[il]] << " = " << ropt.tower_calib[ChTowerCalib[il]]; @@ -311,6 +326,21 @@ void DigiReco::init() } } + // ADC offset + for (int ic = 0; ic < NChannels; ic++) { + if (ropt.adc_offset[ic] > -FInfty) { + LOG(info) << "ADC offset from command line " << ChannelNames[ic] << " = " << ropt.adc_offset[ic]; + } else if (mEnergyParam && mEnergyParam->adc_offset[ic] > -FInfty) { + ropt.adc_offset[ic] = mEnergyParam->adc_offset[ic]; + if (mVerbosity > DbgZero) { + LOG(info) << "ADC offset from CCDB " << ChannelNames[ic] << " = " << ropt.adc_offset[ic]; + } + } else { + ropt.adc_offset[ic] = 0; + LOG(warning) << "Default ADC offset " << ChannelNames[ic] << " = " << ropt.energy_calib[ic]; + } + } + // Fill maps channel maps for integration for (int ich = 0; ich < NChannels; ich++) { // If the reconstruction parameters were not manually set @@ -1031,7 +1061,7 @@ int DigiReco::reconstruct(int ibeg, int iend) // TODO: manage signal positioned across boundary sum += (myPed - float(mChData[ref[0]].data[is])); } - rec.ezdc[ich] = sum * mRopt->energy_calib[ich]; + rec.ezdc[ich] = (sum - mRopt->adc_offset[ich]) * mRopt->energy_calib[ich]; } else { LOGF(warn, "%d.%-4d CH %2d %s missing pedestal", rec.ir.orbit, rec.ir.bc, ich, ChannelNames[ich].data()); } @@ -1802,7 +1832,7 @@ void DigiReco::assignTDC(int ibun, int ibeg, int iend, int itdc, int tdc, float TDCVal = TDCVal - tdc_shift[itdc]; if (!rec.tdcPedMissing[isig]) { // Cannot correct amplitude if pedestal is missing - TDCAmp = TDCAmp * tdc_calib[itdc]; + TDCAmp = (TDCAmp - tdc_offset[itdc]) * tdc_calib[itdc]; } // Encode amplitude and assign @@ -1833,7 +1863,7 @@ void DigiReco::assignTDC(int ibun, int ibeg, int iend, int itdc, int tdc, float LOG(info) << __func__ << " itdc=" << itdc << " " << ChannelNames[isig] << " @ ibun=" << ibun << " " << mReco[ibun].ir.orbit << "." << mReco[ibun].ir.bc << " " << " tdc=" << tdc << " -> " << TDCValCorr << " shift=" << tdc_shift[itdc] << " -> TDCVal=" << TDCVal << "=" << TDCVal * o2::zdc::FTDCVal << " mSource[" << isig << "] = " << unsigned(mSource[isig]) << " = " << mOffset[isig] - << " amp=" << amp << " -> " << TDCAmpCorr << " calib=" << tdc_calib[itdc] << " -> TDCAmp=" << TDCAmp << "=" << myamp + << " amp=" << amp << " -> " << TDCAmpCorr << " calib=" << tdc_calib[itdc] << " offset=" << tdc_offset[itdc] << " -> TDCAmp=" << TDCAmp << "=" << myamp << (ibun == ibeg ? " B" : "") << (ibun == iend ? " E" : ""); mAssignedTDC[itdc]++; #endif diff --git a/Detectors/ZDC/reconstruction/src/ZDCEnergyParam.cxx b/Detectors/ZDC/reconstruction/src/ZDCEnergyParam.cxx index eecf797b2df24..fb462d7d74b41 100644 --- a/Detectors/ZDC/reconstruction/src/ZDCEnergyParam.cxx +++ b/Detectors/ZDC/reconstruction/src/ZDCEnergyParam.cxx @@ -43,11 +43,43 @@ float ZDCEnergyParam::getEnergyCalib(uint32_t ich) const } } +void ZDCEnergyParam::setOffset(uint32_t ich, float val) +{ + bool in_list = false; + for (int il = 0; il < ChEnergyCalib.size(); il++) { + if (ich == ChEnergyCalib[il]) { + in_list = true; + break; + } + } + if (in_list) { + adc_offset[ich] = val; + } else { + LOG(fatal) << __func__ << " channel " << ich << " not in allowed range"; + for (int il = 0; il < ChEnergyCalib.size(); il++) { + LOG(info) << __func__ << " channel " << ChEnergyCalib[il] << " " << ChannelNames[ChEnergyCalib[il]]; + } + } +} + +float ZDCEnergyParam::getOffset(uint32_t ich) const +{ + if (ich >= 0 && ich < NChannels) { + return adc_offset[ich]; + } else { + LOG(fatal) << __func__ << " channel " << ich << " not in allowed range"; + return 0; + } +} + void ZDCEnergyParam::print() const { for (Int_t ich = 0; ich < NChannels; ich++) { if (energy_calib[ich] > 0) { LOG(info) << ChannelNames[ich] << " calibration factor = " << energy_calib[ich]; } + if (adc_offset[ich] > 0) { + LOG(info) << ChannelNames[ich] << " adc offset = " << adc_offset[ich]; + } } } diff --git a/Detectors/ZDC/reconstruction/src/ZDCTDCParam.cxx b/Detectors/ZDC/reconstruction/src/ZDCTDCParam.cxx index 653898b088b32..f6a02614092ac 100644 --- a/Detectors/ZDC/reconstruction/src/ZDCTDCParam.cxx +++ b/Detectors/ZDC/reconstruction/src/ZDCTDCParam.cxx @@ -52,9 +52,28 @@ float ZDCTDCParam::getFactor(uint32_t ich) const } } +void ZDCTDCParam::setOffset(uint32_t ich, float val) +{ + if (ich >= 0 && ich < NTDCChannels) { + tdc_offset[ich] = val; + } else { + LOG(fatal) << __func__ << " channel " << ich << " not in allowed range"; + } +} + +float ZDCTDCParam::getOffset(uint32_t ich) const +{ + if (ich >= 0 && ich < NTDCChannels) { + return tdc_offset[ich]; + } else { + LOG(fatal) << __func__ << " channel " << ich << " not in allowed range"; + return 0; + } +} + void ZDCTDCParam::print() const { for (int itdc = 0; itdc < o2::zdc::NTDCChannels; itdc++) { - LOG(info) << ChannelNames[TDCSignal[itdc]] << " shift = " << tdc_shift[itdc] << " ns factor = " << tdc_calib[itdc]; + LOG(info) << ChannelNames[TDCSignal[itdc]] << " shift = " << tdc_shift[itdc] << " ns factor = " << tdc_calib[itdc] << " offset = " << tdc_offset[itdc]; } } diff --git a/Detectors/ZDC/reconstruction/src/ZDCTowerParam.cxx b/Detectors/ZDC/reconstruction/src/ZDCTowerParam.cxx index 3a95ef79a61e3..d4be08ce92a34 100644 --- a/Detectors/ZDC/reconstruction/src/ZDCTowerParam.cxx +++ b/Detectors/ZDC/reconstruction/src/ZDCTowerParam.cxx @@ -31,6 +31,33 @@ void ZDCTowerParam::setTowerCalib(uint32_t ich, float val, bool ismodified) if (in_list) { tower_calib[ich] = val; modified[ich] = ismodified; + } else { + LOG(fatal) << __func__ << " channel " << ich << " not in allowed range"; + } +} + +float ZDCTowerParam::getTowerCalib(uint32_t ich) const +{ + if (ich >= 0 && ich < NChannels) { + return tower_calib[ich]; + } else { + LOG(fatal) << __func__ << " channel " << ich << " not in allowed range"; + return 0; + } +} + +void ZDCTowerParam::setTowerOffset(uint32_t ich, float val, bool ismodified) +{ + bool in_list = false; + for (int il = 0; il < ChTowerCalib.size(); il++) { + if (ich == ChTowerCalib[il]) { + in_list = true; + break; + } + } + if (in_list) { + tower_offset[ich] = val; + modified[ich] = ismodified; } else { LOG(fatal) << __func__ << " channel " << ich << " not in allowed range"; for (int il = 0; il < ChTowerCalib.size(); il++) { @@ -39,10 +66,10 @@ void ZDCTowerParam::setTowerCalib(uint32_t ich, float val, bool ismodified) } } -float ZDCTowerParam::getTowerCalib(uint32_t ich) const +float ZDCTowerParam::getTowerOffset(uint32_t ich) const { if (ich >= 0 && ich < NChannels) { - return tower_calib[ich]; + return tower_offset[ich]; } else { LOG(fatal) << __func__ << " channel " << ich << " not in allowed range"; return 0; @@ -53,7 +80,7 @@ void ZDCTowerParam::print() const { for (Int_t ich = 0; ich < NChannels; ich++) { if (tower_calib[ich] > 0) { - LOG(info) << ChannelNames[ich] << (modified[ich] ? " NEW" : " OLD") << " calibration factor = " << tower_calib[ich]; + LOG(info) << ChannelNames[ich] << (modified[ich] ? " NEW" : " OLD") << " calibration factor = " << tower_calib[ich] << " offset = " << tower_offset[ich]; } } }