From bd9a5b8c37e2b3d5c759b79fa310897211d1f1e5 Mon Sep 17 00:00:00 2001 From: skundu692 Date: Mon, 9 Nov 2026 19:56:04 +0100 Subject: [PATCH] Remove width correction and add shift correction in zdc calibrtaion --- .../Common/zdc2stagecalibration.cxx | 160 +++++++++++------- 1 file changed, 95 insertions(+), 65 deletions(-) diff --git a/PWGLF/TableProducer/Common/zdc2stagecalibration.cxx b/PWGLF/TableProducer/Common/zdc2stagecalibration.cxx index effa33e1b0a..7b87fecc482 100644 --- a/PWGLF/TableProducer/Common/zdc2stagecalibration.cxx +++ b/PWGLF/TableProducer/Common/zdc2stagecalibration.cxx @@ -82,10 +82,10 @@ struct zdc2stagecalibration { Configurable confQRecenteringPath{"confQRecenteringPath", "", "CCDB path to the current run-wise Q-vector recentering coefficients"}; Configurable confQRecenteringMultidimPath{"confQRecenteringMultidimPath", "", "CCDB path to the multidimensional cubic Q-vector recentering coefficients"}; Configurable confQRecenteringStructured71Path{"confQRecenteringStructured71Path", "", "CCDB path to the 71-feature structured Q-vector recentering coefficients"}; - Configurable useQWidthEqualization{"useQWidthEqualization", false, "equalize Qx/Qy widths after Structured71 recentering"}; - Configurable confQWidthPath{"confQWidthPath", "", "CCDB path to post-recentering Q-width map"}; - Configurable useQTwist{"useQTwist", false, "apply same-side Qx-Qy twist correction after width equalization"}; + Configurable useQTwist{"useQTwist", false, "apply same-side Qx-Qy correlation de-twist after recentering (no width equalization)"}; Configurable confQTwistPath{"confQTwistPath", "", "CCDB path to the run-wise Q-twist map"}; + Configurable useQShift{"useQShift", false, "apply ZDC azimuthal shift correction after twist"}; + Configurable confQShiftPath{"confQShiftPath", "", "CCDB path to the run-wise Q-shift Fourier map"}; Configurable cfgSpatialCalibBins{ "cfgSpatialCalibBins", 30, "number of bins per cross coordinate for spatial calibration"}; @@ -104,8 +104,8 @@ struct zdc2stagecalibration { TH2D* gainprofile = nullptr; TH3D* spatialprofile = nullptr; TH3D* qRecenteringProfile = nullptr; - TH2D* qWidthProfile = nullptr; TH2D* qTwistProfile = nullptr; + TH2D* qShiftProfile = nullptr; static constexpr int kQRecenteringNFeatures = 21; static constexpr int kQRecenteringNMatrixMoments = kQRecenteringNFeatures * (kQRecenteringNFeatures + 1) / 2; @@ -114,7 +114,7 @@ struct zdc2stagecalibration { static constexpr int kQRecenteringMultidimNFeatures = 35; static constexpr int kQRecenteringMultidimNMatrixMoments = kQRecenteringMultidimNFeatures * (kQRecenteringMultidimNFeatures + 1) / 2; static constexpr int kQRecenteringMultidimNMoments = kQRecenteringMultidimNMatrixMoments + kQRecenteringNComponents * kQRecenteringMultidimNFeatures; - // Additional sufficient statistics for the flatness-constrained multidimensional fit. + // Per conditioning bin store 35 sums of the cubic features followed by // 4 sums of QxA,QyA,QxC,QyC. Feature 0 is unity, so its sum is N. static constexpr int kQRecenteringFlatnessNMoments = kQRecenteringMultidimNFeatures + kQRecenteringNComponents; @@ -128,7 +128,6 @@ struct zdc2stagecalibration { static constexpr int kQRecenteringStructuredNFeatures = kQRecenteringMultidimNFeatures + 4 * kQRecenteringStructuredNKnots; static constexpr int kQRecenteringStructuredNMatrixMoments = kQRecenteringStructuredNFeatures * (kQRecenteringStructuredNFeatures + 1) / 2; static constexpr int kQRecenteringStructuredNMoments = kQRecenteringStructuredNMatrixMoments + kQRecenteringNComponents * kQRecenteringStructuredNFeatures + kQRecenteringNComponents; - // Per conditioning bin store sum(features), sum(Q) and sum(Q^2). static constexpr int kQRecenteringStructuredFlatnessNMoments = kQRecenteringStructuredNFeatures + 2 * kQRecenteringNComponents; void init(o2::framework::InitContext&) @@ -137,11 +136,11 @@ struct zdc2stagecalibration { if (qRecenteringMethod.value != 0 && qRecenteringMethod.value != 1 && qRecenteringMethod.value != 4) { LOGF(fatal, "Unsupported qRecenteringMethod=%d. Use 0 for the current regression, 1 for the multidimensional cubic regression or 4 for the structured71 regression.", qRecenteringMethod.value); } - if (useQWidthEqualization.value && (calibrationStage.value != 2 || !useQRecentering.value || qRecenteringMethod.value != 4 || confQWidthPath.value.empty())) { - LOGF(fatal, "Width equalization requires stage=2, useQRecentering=true, method=4 and confQWidthPath"); + if (useQTwist.value && (calibrationStage.value != 2 || !useQRecentering.value || qRecenteringMethod.value != 4 || confQTwistPath.value.empty())) { + LOGF(fatal, "Twist correction requires stage=2, Structured71 recentering and confQTwistPath"); } - if (useQTwist.value && (!useQWidthEqualization.value || confQTwistPath.value.empty())) { - LOGF(fatal, "Twist correction requires width equalization and confQTwistPath"); + if (useQShift.value && (!useQTwist.value || confQShiftPath.value.empty())) { + LOGF(fatal, "Shift correction requires twist correction and confQShiftPath"); } const int nTimeBins = static_cast(std::ceil(cfgMaxRunHours.value * 60.f / cfgTimeSliceMinutes.value)); AxisSpec timeAxis = {nTimeBins, 0.0, cfgMaxRunHours.value, "time from SOR (h)"}; @@ -151,6 +150,7 @@ struct zdc2stagecalibration { AxisSpec spatialMomentAxis = {6, 0.0, 6.0, "normalized pair regression moment"}; AxisSpec spatialCalibAxis = {cfgSpatialCalibBins.value, -1.0, 1.0, "cross asymmetry"}; AxisSpec phiAxis = {72, -3.14159265358979323846, 3.14159265358979323846, "#phi"}; + AxisSpec phiDerivationAxis = {720, -3.14159265358979323846, 3.14159265358979323846, "#phi"}; AxisSpec crossCoordAxis = {2, 0.0, 2.0, "coordinate"}; AxisSpec ratioAxis = {240, 0.0, 2.4, "#Sigma tower/common"}; AxisSpec qRecenteringMomentAxis = {kQRecenteringNMoments, 0.0, static_cast(kQRecenteringNMoments), "regression moment"}; @@ -268,13 +268,20 @@ struct zdc2stagecalibration { histos.add("QRecenteringQA/pQAfterVsVz", "Q after recentering vs v_{z};v_{z} (cm);Q component;", kTProfile2D, {vertexZAxis, qComponentAxis}); histos.add("ResolutionQA/pCosPsiAPsiCVsCentrality", "ZDC A-C spectator-plane correlation;centrality (%);<#cos(#Psi_{A}-#Psi_{C})>", kTProfile, {resolutionCentralityAxis}); histos.add("ResolutionQA/pCosPsiAPsiCVsCentralityVz", "ZDC A-C correlation;centrality (%);v_{z} (cm); <#cos(#Psi_{A}-#Psi_{C})>", kTProfile2D, {resolutionCentralityAxis, resolutionVzAxis}); - histos.add("QWidthQA/pQAfterWidthEqVsCentrality", "Q after width equalization;centrality (%);Q component;", kTProfile2D, {centralityAxis, qComponentAxis}); + // Fine-bin recentered azimuths allow both twist and shift maps to be derived + // offline from a single recentering-only pass. No Q-magnitude normalization. + histos.add("QTwistQA/hPhiBeforeTwistHighResVsCentralityZNA", "Recentered ZNA #phi for twist/shift derivation;centrality (%);#phi", kTH2F, {centralityAxis, phiDerivationAxis}); + histos.add("QTwistQA/hPhiBeforeTwistHighResVsCentralityZNC", "Recentered ZNC #phi for twist/shift derivation;centrality (%);#phi", kTH2F, {centralityAxis, phiDerivationAxis}); histos.add("QTwistQA/pMomentsBeforeVsCentrality", "Q moments before twist;centrality (%);moment;", kTProfile2D, {centralityAxis, qTwistMomentAxis}); histos.add("QTwistQA/pMomentsAfterVsCentrality", "Q moments after twist;centrality (%);moment;", kTProfile2D, {centralityAxis, qTwistMomentAxis}); histos.add("PhiQA/hPhiAfterTwistVsCentralityZNA", "ZNA #phi after twist;centrality (%);#phi", kTH2F, {centralityAxis, phiAxis}); histos.add("PhiQA/hPhiAfterTwistVsCentralityZNC", "ZNC #phi after twist;centrality (%);#phi", kTH2F, {centralityAxis, phiAxis}); - histos.add("PhiQA/hPhiAfterWidthEqVsCentralityZNA", "ZNA #phi after width equalization;centrality (%);#phi", kTH2F, {centralityAxis, phiAxis}); - histos.add("PhiQA/hPhiAfterWidthEqVsCentralityZNC", "ZNC #phi after width equalization;centrality (%);#phi", kTH2F, {centralityAxis, phiAxis}); + histos.add("QShiftQA/hPhiAfterShiftVsCentralityZNA", "ZNA #phi after shift;centrality (%);#phi", kTH2F, {centralityAxis, phiAxis}); + histos.add("QShiftQA/hPhiAfterShiftVsCentralityZNC", "ZNC #phi after shift;centrality (%);#phi", kTH2F, {centralityAxis, phiAxis}); + histos.add("QShiftQA/pPhiHarmonicsBeforeVsCentralityZNA", "ZNA harmonics before shift: cos,sin n=1..4;centrality (%);harmonic index;", kTProfile2D, {centralityAxis, phiHarmonicAxis}); + histos.add("QShiftQA/pPhiHarmonicsBeforeVsCentralityZNC", "ZNC harmonics before shift: cos,sin n=1..4;centrality (%);harmonic index;", kTProfile2D, {centralityAxis, phiHarmonicAxis}); + histos.add("QShiftQA/pPhiHarmonicsAfterVsCentralityZNA", "ZNA harmonics after shift: cos,sin n=1..4;centrality (%);harmonic index;", kTProfile2D, {centralityAxis, phiHarmonicAxis}); + histos.add("QShiftQA/pPhiHarmonicsAfterVsCentralityZNC", "ZNC harmonics after shift: cos,sin n=1..4;centrality (%);harmonic index;", kTProfile2D, {centralityAxis, phiHarmonicAxis}); histos.add("QRecentering2DQA/pQxAAfterVsCentralityTime", "QxA after recentering;centrality (%);time from SOR (h);", kTProfile2D, {centralityAxis, timeAxis}); histos.add("QRecentering2DQA/pQyAAfterVsCentralityTime", "QyA after recentering;centrality (%);time from SOR (h);", kTProfile2D, {centralityAxis, timeAxis}); histos.add("QRecentering2DQA/pQxCAfterVsCentralityTime", "QxC after recentering;centrality (%);time from SOR (h);", kTProfile2D, {centralityAxis, timeAxis}); @@ -312,7 +319,7 @@ struct zdc2stagecalibration { histos.add("QCorrelationQA/pQACorrelationBeforeVsCentrality", "A-C Q correlations before recentering;centrality (%);correlation component;", kTProfile2D, {centralityAxis, qCorrelationComponentAxis}); histos.add("QCorrelationQA/pQACorrelationAfterVsCentrality", "A-C Q correlations after recentering;centrality (%);correlation component;", kTProfile2D, {centralityAxis, qCorrelationComponentAxis}); - // Final-calibration QA: only filled after recentering, width and twist. + // Final-calibration QA: after recentering, correlation-only twist and optional shift. histos.add("final_calibration/hQxAVsCentrality", "Final QxA vs centrality;centrality (%);Q_{x}^{A}", kTH2F, {centralityAxis, qValueAxis}); histos.add("final_calibration/hQyAVsCentrality", "Final QyA vs centrality;centrality (%);Q_{y}^{A}", kTH2F, {centralityAxis, qValueAxis}); histos.add("final_calibration/hQxCVsCentrality", "Final QxC vs centrality;centrality (%);Q_{x}^{C}", kTH2F, {centralityAxis, qValueAxis}); @@ -359,8 +366,8 @@ struct zdc2stagecalibration { gainprofile = nullptr; spatialprofile = nullptr; qRecenteringProfile = nullptr; - qWidthProfile = nullptr; qTwistProfile = nullptr; + qShiftProfile = nullptr; if (calibrationStage.value == 2 && useGainCallib.value && !confGainPath.value.empty()) { gainprofile = ccdb->getForTimeStamp(confGainPath.value, timestamp); if (!gainprofile) { @@ -390,30 +397,31 @@ struct zdc2stagecalibration { } } } - if (calibrationStage.value == 2 && useQWidthEqualization.value) { - qWidthProfile = ccdb->getForTimeStamp(confQWidthPath.value, timestamp); - if (!qWidthProfile || qWidthProfile->GetNbinsX() != 80 || qWidthProfile->GetNbinsY() != 4) { - LOGF(fatal, "Missing/invalid Q-width map for run %d", runNumber); - } - constexpr std::array labels = {"QxA", "QyA", "QxC", "QyC"}; - for (int i = 0; i < 4; ++i) { - if (std::string(qWidthProfile->GetYaxis()->GetBinLabel(i + 1)) != labels[i]) { - LOGF(fatal, "Incorrect Q-width map component ordering"); - } - } - } if (calibrationStage.value == 2 && useQTwist.value) { qTwistProfile = ccdb->getForTimeStamp(confQTwistPath.value, timestamp); if (!qTwistProfile || qTwistProfile->GetNbinsX() != 80 || qTwistProfile->GetNbinsY() != 6) { LOGF(fatal, "Missing/invalid ZDC twist map for run %d", runNumber); } - constexpr std::array labels = {"MxxA", "MxyA", "MyyA", "MxxC", "MxyC", "MyyC"}; + constexpr std::array labels = {"ShearMxxA", "ShearMxyA", "ShearMyyA", "ShearMxxC", "ShearMxyC", "ShearMyyC"}; for (int i = 0; i < 6; ++i) { if (std::string(qTwistProfile->GetYaxis()->GetBinLabel(i + 1)) != labels[i]) { LOGF(fatal, "Incorrect ZDC twist map component ordering for run %d", runNumber); } } } + if (calibrationStage.value == 2 && useQShift.value) { + qShiftProfile = ccdb->getForTimeStamp(confQShiftPath.value, timestamp); + if (!qShiftProfile || qShiftProfile->GetNbinsX() != 80 || qShiftProfile->GetNbinsY() != 16) { + LOGF(fatal, "Missing/invalid ZDC shift map for run %d", runNumber); + } + constexpr std::array labels = {"cos1A", "sin1A", "cos2A", "sin2A", "cos3A", "sin3A", "cos4A", "sin4A", + "cos1C", "sin1C", "cos2C", "sin2C", "cos3C", "sin3C", "cos4C", "sin4C"}; + for (int i = 0; i < 16; ++i) { + if (std::string(qShiftProfile->GetYaxis()->GetBinLabel(i + 1)) != labels[i]) { + LOGF(fatal, "Incorrect ZDC shift map component ordering for run %d", runNumber); + } + } + } } float getTimeFromSOR(uint64_t globalBC) const @@ -1107,46 +1115,19 @@ struct zdc2stagecalibration { histos.fill(HIST("PhiQA/hPhiAfterRecenteringZNC"), phiRecenteringC); histos.fill(HIST("PhiQA/hPhiAfterRecenteringVsCentralityZNA"), centrality, phiRecenteringA); histos.fill(HIST("PhiQA/hPhiAfterRecenteringVsCentralityZNC"), centrality, phiRecenteringC); - - if (useQWidthEqualization.value) { - const int centBin = qWidthProfile->GetXaxis()->FindFixBin(centrality); - if (centBin < 1 || centBin > qWidthProfile->GetNbinsX()) { - LOGF(fatal, "Invalid ZDC Q-width centrality bin for run %d: centrality=%.6f", runNumber, static_cast(centrality)); - fillTable(false, -999.f, -999.f, -999.f, -999.f); - return; - } - std::array sigma{}; - for (int i = 0; i < 4; ++i) { - sigma[i] = qWidthProfile->GetBinContent(centBin, i + 1); - if (!std::isfinite(sigma[i]) || sigma[i] <= 0.0) { - LOGF(fatal, "Invalid ZDC Q-width sigma for run %d: centrality=%.6f, component=%d, sigma=%.6g", runNumber, static_cast(centrality), i, sigma[i]); - fillTable(false, -999.f, -999.f, -999.f, -999.f); - return; - } - } - const double factorA = std::sqrt(sigma[1] / sigma[0]); - const double factorC = std::sqrt(sigma[3] / sigma[2]); - qValues[0] *= factorA; - qValues[1] /= factorA; - qValues[2] *= factorC; - qValues[3] /= factorC; - for (int i = 0; i < 4; ++i) { - histos.fill(HIST("QWidthQA/pQAfterWidthEqVsCentrality"), centrality, i + 0.5, qValues[i]); - } + if (calibrationStage.value == 2 && useQRecentering.value) { + histos.fill(HIST("QTwistQA/hPhiBeforeTwistHighResVsCentralityZNA"), centrality, phiRecenteringA); + histos.fill(HIST("QTwistQA/hPhiBeforeTwistHighResVsCentralityZNC"), centrality, phiRecenteringC); } - const double phiWidthA = std::atan2(qValues[1], qValues[0]); - const double phiWidthC = std::atan2(qValues[3], qValues[2]); - if (useQWidthEqualization.value) { - histos.fill(HIST("PhiQA/hPhiAfterWidthEqVsCentralityZNA"), centrality, phiWidthA); - histos.fill(HIST("PhiQA/hPhiAfterWidthEqVsCentralityZNC"), centrality, phiWidthC); - } const auto makeTwistMoments = [](const std::array& q) { return std::array{q[0], q[1], q[0] * q[0], q[1] * q[1], q[0] * q[1], q[2], q[3], q[2] * q[2], q[3] * q[3], q[2] * q[3]}; }; const auto momentsBeforeTwist = makeTwistMoments(qValues); - if (useQWidthEqualization.value) { + // Correlation moments are collected directly after recentering, BEFORE twist. + // Derive the run-wise shear map from these same-side moments (no width map). + if (calibrationStage.value == 2 && useQRecentering.value) { for (int i = 0; i < 10; ++i) { histos.fill(HIST("QTwistQA/pMomentsBeforeVsCentrality"), centrality, i + 0.5, momentsBeforeTwist[i]); } @@ -1162,7 +1143,9 @@ struct zdc2stagecalibration { const double mxx = qTwistProfile->GetBinContent(centBin, offset + 1); const double mxy = qTwistProfile->GetBinContent(centBin, offset + 2); const double myy = qTwistProfile->GetBinContent(centBin, offset + 3); - if (!std::isfinite(mxx) || !std::isfinite(mxy) || !std::isfinite(myy) || mxx <= 0.0 || myy <= 0.0 || mxx * myy <= mxy * mxy) { + // Enforce the new shear-map format. Old covariance-whitening maps are incompatible. + if (!std::isfinite(mxx) || !std::isfinite(mxy) || !std::isfinite(myy) || + std::abs(mxx - 1.0) > 1.e-10 || std::abs(myy - 1.0) > 1.e-10 || std::abs(mxy) >= 1.0) { fillTable(false, -999.f, -999.f, -999.f, -999.f); return; } @@ -1183,11 +1166,58 @@ struct zdc2stagecalibration { histos.fill(HIST("QTwistQA/pMomentsAfterVsCentrality"), centrality, i + 0.5, momentsAfterTwist[i]); } } - const double phiFinalA = std::atan2(qValues[1], qValues[0]); - const double phiFinalC = std::atan2(qValues[3], qValues[2]); + double phiFinalA = std::atan2(qValues[1], qValues[0]); + double phiFinalC = std::atan2(qValues[3], qValues[2]); if (useQTwist.value) { histos.fill(HIST("PhiQA/hPhiAfterTwistVsCentralityZNA"), centrality, phiFinalA); histos.fill(HIST("PhiQA/hPhiAfterTwistVsCentralityZNC"), centrality, phiFinalC); + for (int n = 1; n <= 4; ++n) { + histos.fill(HIST("QShiftQA/pPhiHarmonicsBeforeVsCentralityZNA"), centrality, 2 * n - 1.5, std::cos(n * phiFinalA)); + histos.fill(HIST("QShiftQA/pPhiHarmonicsBeforeVsCentralityZNA"), centrality, 2 * n - 0.5, std::sin(n * phiFinalA)); + histos.fill(HIST("QShiftQA/pPhiHarmonicsBeforeVsCentralityZNC"), centrality, 2 * n - 1.5, std::cos(n * phiFinalC)); + histos.fill(HIST("QShiftQA/pPhiHarmonicsBeforeVsCentralityZNC"), centrality, 2 * n - 0.5, std::sin(n * phiFinalC)); + } + } + if (useQShift.value) { + const int centBin = qShiftProfile->GetXaxis()->FindFixBin(centrality); + if (centBin < 1 || centBin > qShiftProfile->GetNbinsX()) { + fillTable(false, -999.f, -999.f, -999.f, -999.f); + return; + } + for (int side = 0; side < 2; ++side) { + const int ix = 2 * side; + const double phi = std::atan2(qValues[ix + 1], qValues[ix]); + const double qMag = std::hypot(qValues[ix], qValues[ix + 1]); + double deltaPhi = 0.0; + for (int n = 1; n <= 4; ++n) { + const double cosMean = qShiftProfile->GetBinContent(centBin, 8 * side + 2 * n - 1); + const double sinMean = qShiftProfile->GetBinContent(centBin, 8 * side + 2 * n); + if (!std::isfinite(cosMean) || !std::isfinite(sinMean)) { + fillTable(false, -999.f, -999.f, -999.f, -999.f); + return; + } + deltaPhi += (2.0 / n) * (cosMean * std::sin(n * phi) - sinMean * std::cos(n * phi)); + } + const double phiNew = phi + deltaPhi; + // Preserve |Q| and rotate both Cartesian components to the shifted angle. + qValues[ix] = qMag * std::cos(phiNew); + qValues[ix + 1] = qMag * std::sin(phiNew); + if (!std::isfinite(qValues[ix]) || !std::isfinite(qValues[ix + 1]) || + !std::isfinite(static_cast(qValues[ix])) || !std::isfinite(static_cast(qValues[ix + 1]))) { + fillTable(false, -999.f, -999.f, -999.f, -999.f); + return; + } + } + phiFinalA = std::atan2(qValues[1], qValues[0]); + phiFinalC = std::atan2(qValues[3], qValues[2]); + histos.fill(HIST("QShiftQA/hPhiAfterShiftVsCentralityZNA"), centrality, phiFinalA); + histos.fill(HIST("QShiftQA/hPhiAfterShiftVsCentralityZNC"), centrality, phiFinalC); + for (int n = 1; n <= 4; ++n) { + histos.fill(HIST("QShiftQA/pPhiHarmonicsAfterVsCentralityZNA"), centrality, 2 * n - 1.5, std::cos(n * phiFinalA)); + histos.fill(HIST("QShiftQA/pPhiHarmonicsAfterVsCentralityZNA"), centrality, 2 * n - 0.5, std::sin(n * phiFinalA)); + histos.fill(HIST("QShiftQA/pPhiHarmonicsAfterVsCentralityZNC"), centrality, 2 * n - 1.5, std::cos(n * phiFinalC)); + histos.fill(HIST("QShiftQA/pPhiHarmonicsAfterVsCentralityZNC"), centrality, 2 * n - 0.5, std::sin(n * phiFinalC)); + } } // ZDC resolution after all enabled corrections const double qMagA = std::hypot(qValues[0], qValues[1]); @@ -1198,7 +1228,7 @@ struct zdc2stagecalibration { histos.fill(HIST("ResolutionQA/pCosPsiAPsiCVsCentralityVz"), centrality, vz, correlation); } - if (calibrationStage.value == 2 && useQRecentering.value && useQWidthEqualization.value && useQTwist.value && qMagA > 0. && qMagC > 0.) { + if (calibrationStage.value == 2 && useQRecentering.value && useQTwist.value && qMagA > 0. && qMagC > 0.) { histos.fill(HIST("final_calibration/hQxAVsCentrality"), centrality, qValues[0]); histos.fill(HIST("final_calibration/hQyAVsCentrality"), centrality, qValues[1]); histos.fill(HIST("final_calibration/hQxCVsCentrality"), centrality, qValues[2]);