Skip to content

Commit 5f7fe5b

Browse files
committed
Add twist correction to zdc qvector
1 parent 7558e7e commit 5f7fe5b

1 file changed

Lines changed: 75 additions & 3 deletions

File tree

‎PWGLF/TableProducer/Common/zdc2stagecalibration.cxx‎

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ struct zdc2stagecalibration {
8484
Configurable<std::string> confQRecenteringStructured71Path{"confQRecenteringStructured71Path", "", "CCDB path to the 71-feature structured Q-vector recentering coefficients"};
8585
Configurable<bool> useQWidthEqualization{"useQWidthEqualization", false, "equalize Qx/Qy widths after Structured71 recentering"};
8686
Configurable<std::string> confQWidthPath{"confQWidthPath", "", "CCDB path to post-recentering Q-width map"};
87+
Configurable<bool> useQTwist{"useQTwist", false, "apply same-side Qx-Qy twist correction after width equalization"};
88+
Configurable<std::string> confQTwistPath{"confQTwistPath", "", "CCDB path to the run-wise Q-twist map"};
8789
Configurable<int> cfgSpatialCalibBins{
8890
"cfgSpatialCalibBins", 30,
8991
"number of bins per cross coordinate for spatial calibration"};
@@ -103,6 +105,7 @@ struct zdc2stagecalibration {
103105
TH3D* spatialprofile = nullptr;
104106
TH3D* qRecenteringProfile = nullptr;
105107
TH2D* qWidthProfile = nullptr;
108+
TH2D* qTwistProfile = nullptr;
106109

107110
static constexpr int kQRecenteringNFeatures = 21;
108111
static constexpr int kQRecenteringNMatrixMoments = kQRecenteringNFeatures * (kQRecenteringNFeatures + 1) / 2;
@@ -137,6 +140,9 @@ struct zdc2stagecalibration {
137140
if (useQWidthEqualization.value && (calibrationStage.value != 2 || !useQRecentering.value || qRecenteringMethod.value != 4 || confQWidthPath.value.empty())) {
138141
LOGF(fatal, "Width equalization requires stage=2, useQRecentering=true, method=4 and confQWidthPath");
139142
}
143+
if (useQTwist.value && (!useQWidthEqualization.value || confQTwistPath.value.empty())) {
144+
LOGF(fatal, "Twist correction requires width equalization and confQTwistPath");
145+
}
140146
const int nTimeBins = static_cast<int>(std::ceil(cfgMaxRunHours.value * 60.f / cfgTimeSliceMinutes.value));
141147
AxisSpec timeAxis = {nTimeBins, 0.0, cfgMaxRunHours.value, "time from SOR (h)"};
142148
AxisSpec towerAxis = {4, 0.0, 4.0, "tower"};
@@ -158,6 +164,7 @@ struct zdc2stagecalibration {
158164
AxisSpec vertexXYAxis = {100, -0.1, 0.1, "vertex x/y (cm)"};
159165
AxisSpec vertexZAxis = {100, -10.0, 10.0, "vertex z (cm)"};
160166
AxisSpec qComponentAxis = {4, 0.0, 4.0, "Q component"};
167+
AxisSpec qTwistMomentAxis = {10, 0.0, 10.0, "Q moments (A: 0-4, C: 5-9)"};
161168
AxisSpec qCorrelationComponentAxis = {4, 0.0, 4.0, "A-C correlation component"};
162169
AxisSpec qValueAxis = {200, -4.0, 4.0, "Q"};
163170

@@ -261,6 +268,10 @@ struct zdc2stagecalibration {
261268
histos.add("ResolutionQA/pCosPsiAPsiCVsCentrality", "ZDC A-C spectator-plane correlation;centrality (%);<#cos(#Psi_{A}-#Psi_{C})>", kTProfile, {resolutionCentralityAxis});
262269
histos.add("ResolutionQA/pCosPsiAPsiCVsCentralityVz", "ZDC A-C correlation;centrality (%);v_{z} (cm); <#cos(#Psi_{A}-#Psi_{C})>", kTProfile2D, {resolutionCentralityAxis, resolutionVzAxis});
263270
histos.add("QWidthQA/pQAfterWidthEqVsCentrality", "Q after width equalization;centrality (%);Q component;<Q>", kTProfile2D, {centralityAxis, qComponentAxis});
271+
histos.add("QTwistQA/pMomentsBeforeVsCentrality", "Q moments before twist;centrality (%);moment;<value>", kTProfile2D, {centralityAxis, qTwistMomentAxis});
272+
histos.add("QTwistQA/pMomentsAfterVsCentrality", "Q moments after twist;centrality (%);moment;<value>", kTProfile2D, {centralityAxis, qTwistMomentAxis});
273+
histos.add("PhiQA/hPhiAfterTwistVsCentralityZNA", "ZNA #phi after twist;centrality (%);#phi", kTH2F, {centralityAxis, phiAxis});
274+
histos.add("PhiQA/hPhiAfterTwistVsCentralityZNC", "ZNC #phi after twist;centrality (%);#phi", kTH2F, {centralityAxis, phiAxis});
264275
histos.add("PhiQA/hPhiAfterWidthEqVsCentralityZNA", "ZNA #phi after width equalization;centrality (%);#phi", kTH2F, {centralityAxis, phiAxis});
265276
histos.add("PhiQA/hPhiAfterWidthEqVsCentralityZNC", "ZNC #phi after width equalization;centrality (%);#phi", kTH2F, {centralityAxis, phiAxis});
266277
histos.add("QRecentering2DQA/pQxAAfterVsCentralityTime", "QxA after recentering;centrality (%);time from SOR (h);<Q_{x}^{A}>", kTProfile2D, {centralityAxis, timeAxis});
@@ -321,6 +332,7 @@ struct zdc2stagecalibration {
321332
spatialprofile = nullptr;
322333
qRecenteringProfile = nullptr;
323334
qWidthProfile = nullptr;
335+
qTwistProfile = nullptr;
324336
if (calibrationStage.value == 2 && useGainCallib.value && !confGainPath.value.empty()) {
325337
gainprofile = ccdb->getForTimeStamp<TH2D>(confGainPath.value, timestamp);
326338
if (!gainprofile) {
@@ -362,6 +374,18 @@ struct zdc2stagecalibration {
362374
}
363375
}
364376
}
377+
if (calibrationStage.value == 2 && useQTwist.value) {
378+
qTwistProfile = ccdb->getForTimeStamp<TH2D>(confQTwistPath.value, timestamp);
379+
if (!qTwistProfile || qTwistProfile->GetNbinsX() != 80 || qTwistProfile->GetNbinsY() != 6) {
380+
LOGF(fatal, "Missing/invalid ZDC twist map for run %d", runNumber);
381+
}
382+
constexpr std::array<const char*, 6> labels = {"MxxA", "MxyA", "MyyA", "MxxC", "MxyC", "MyyC"};
383+
for (int i = 0; i < 6; ++i) {
384+
if (std::string(qTwistProfile->GetYaxis()->GetBinLabel(i + 1)) != labels[i]) {
385+
LOGF(fatal, "Incorrect ZDC twist map component ordering for run %d", runNumber);
386+
}
387+
}
388+
}
365389
}
366390

367391
float getTimeFromSOR(uint64_t globalBC) const
@@ -1083,11 +1107,59 @@ struct zdc2stagecalibration {
10831107
}
10841108
}
10851109

1110+
const double phiWidthA = std::atan2(qValues[1], qValues[0]);
1111+
const double phiWidthC = std::atan2(qValues[3], qValues[2]);
1112+
if (useQWidthEqualization.value) {
1113+
histos.fill(HIST("PhiQA/hPhiAfterWidthEqVsCentralityZNA"), centrality, phiWidthA);
1114+
histos.fill(HIST("PhiQA/hPhiAfterWidthEqVsCentralityZNC"), centrality, phiWidthC);
1115+
}
1116+
const auto makeTwistMoments = [](const std::array<double, 4>& q) {
1117+
return std::array<double, 10>{q[0], q[1], q[0] * q[0], q[1] * q[1], q[0] * q[1],
1118+
q[2], q[3], q[2] * q[2], q[3] * q[3], q[2] * q[3]};
1119+
};
1120+
const auto momentsBeforeTwist = makeTwistMoments(qValues);
1121+
if (useQWidthEqualization.value) {
1122+
for (int i = 0; i < 10; ++i) {
1123+
histos.fill(HIST("QTwistQA/pMomentsBeforeVsCentrality"), centrality, i + 0.5, momentsBeforeTwist[i]);
1124+
}
1125+
}
1126+
if (useQTwist.value) {
1127+
const int centBin = qTwistProfile->GetXaxis()->FindFixBin(centrality);
1128+
if (centBin < 1 || centBin > qTwistProfile->GetNbinsX()) {
1129+
fillTable(false, -999.f, -999.f, -999.f, -999.f);
1130+
return;
1131+
}
1132+
for (int side = 0; side < 2; ++side) {
1133+
const int offset = 3 * side;
1134+
const double mxx = qTwistProfile->GetBinContent(centBin, offset + 1);
1135+
const double mxy = qTwistProfile->GetBinContent(centBin, offset + 2);
1136+
const double myy = qTwistProfile->GetBinContent(centBin, offset + 3);
1137+
if (!std::isfinite(mxx) || !std::isfinite(mxy) || !std::isfinite(myy) || mxx <= 0.0 || myy <= 0.0 || mxx * myy <= mxy * mxy) {
1138+
fillTable(false, -999.f, -999.f, -999.f, -999.f);
1139+
return;
1140+
}
1141+
const int ix = 2 * side;
1142+
const double qx = qValues[ix];
1143+
const double qy = qValues[ix + 1];
1144+
qValues[ix] = mxx * qx + mxy * qy;
1145+
qValues[ix + 1] = mxy * qx + myy * qy;
1146+
}
1147+
for (int i = 0; i < 4; ++i) {
1148+
if (!std::isfinite(qValues[i]) || !std::isfinite(static_cast<float>(qValues[i]))) {
1149+
fillTable(false, -999.f, -999.f, -999.f, -999.f);
1150+
return;
1151+
}
1152+
}
1153+
const auto momentsAfterTwist = makeTwistMoments(qValues);
1154+
for (int i = 0; i < 10; ++i) {
1155+
histos.fill(HIST("QTwistQA/pMomentsAfterVsCentrality"), centrality, i + 0.5, momentsAfterTwist[i]);
1156+
}
1157+
}
10861158
const double phiFinalA = std::atan2(qValues[1], qValues[0]);
10871159
const double phiFinalC = std::atan2(qValues[3], qValues[2]);
1088-
if (useQWidthEqualization.value) {
1089-
histos.fill(HIST("PhiQA/hPhiAfterWidthEqVsCentralityZNA"), centrality, phiFinalA);
1090-
histos.fill(HIST("PhiQA/hPhiAfterWidthEqVsCentralityZNC"), centrality, phiFinalC);
1160+
if (useQTwist.value) {
1161+
histos.fill(HIST("PhiQA/hPhiAfterTwistVsCentralityZNA"), centrality, phiFinalA);
1162+
histos.fill(HIST("PhiQA/hPhiAfterTwistVsCentralityZNC"), centrality, phiFinalC);
10911163
}
10921164
// ZDC resolution after all enabled corrections
10931165
const double qMagA = std::hypot(qValues[0], qValues[1]);

0 commit comments

Comments
 (0)