modified: Calibration.C use both front and back gains

modified:   GainMatchSX3.C changed structure a bit
	modified:   GainMatchSX3Front.C removed some redundant code that I was trying out
This commit is contained in:
Vignesh Sitaraman 2025-10-06 15:11:31 -04:00
parent ecd755e09c
commit 61473ca14e
3 changed files with 69 additions and 175 deletions

View File

@ -97,9 +97,9 @@ void Calibration::Begin(TTree * /*tree*/)
} }
else else
{ {
int id, bk, u, d; int id, bk;
double gain; double gain;
while (infile >> id >> bk >> u >> d >> gain) while (infile >> id >> bk >> gain)
{ {
backGain[id][bk] = gain; backGain[id][bk] = gain;
backGainValid[id][bk] = (gain > 0); backGainValid[id][bk] = (gain > 0);
@ -253,30 +253,27 @@ Bool_t Calibration::Process(Long64_t entry)
int sx3ChUp = -1, sx3ChDn = -1, sx3ChBk = -1; int sx3ChUp = -1, sx3ChDn = -1, sx3ChBk = -1;
float sx3EUp = 0.0f, sx3EDn = 0.0f, sx3EBk = 0.0f; float sx3EUp = 0.0f, sx3EDn = 0.0f, sx3EBk = 0.0f;
for (auto &p : sx3ID) for (size_t i = 0; i < sx3ID.size(); i++)
{ {
int index = p.second; int index = sx3ID[i].second;
int ch = sx3.ch[index];
float e = sx3.e[index];
if (ch < 8) if (sx3.ch[index] < 8)
{ {
if ((ch % 2) == 0) // even -> down if ((sx3.ch[index] % 2) == 0) // even -> down
{ {
sx3ChDn = ch; sx3ChDn = sx3.ch[index];
sx3EDn = e; sx3EDn = sx3.e[index];
} }
else // odd -> up else // odd -> up
{ {
sx3ChUp = ch; sx3ChUp = sx3.ch[index];
sx3EUp = e; sx3EUp = sx3.e[index];
} }
} }
else else
{ {
sx3ChBk = ch; sx3ChBk = sx3.ch[index];
sx3EBk = e; sx3EBk = sx3.e[index];
}
} }
bool haveFrontPair = (sx3ChUp >= 0 || sx3ChDn >= 0); bool haveFrontPair = (sx3ChUp >= 0 || sx3ChDn >= 0);
@ -288,40 +285,41 @@ Bool_t Calibration::Process(Long64_t entry)
// --- ALWAYS fill raw ADC for diagnostics // --- ALWAYS fill raw ADC for diagnostics
// (temporarily use the existing spectrum to confirm fills) // (temporarily use the existing spectrum to confirm fills)
// If you don't want raw values mixed with calibrated later, create a separate _raw array. // If you don't want raw values mixed with calibrated later, create a separate _raw array.
hSX3Spectra[sx3ID[0].first][sx3ChBk][sx3ChUp][sx3ChDn]->Fill(sx3EUp); hSX3Spectra[sx3ID[i].first][sx3ChBk][sx3ChUp][sx3ChDn]->Fill(sx3EUp);
// --- If gain is available, also fill calibrated energy // --- If gain is available, also fill calibrated energy
if (frontGainValid[sx3ID[0].first][sx3ChBk][sx3ChUp][sx3ChDn]) if (frontGainValid[sx3ID[i].first][sx3ChBk][sx3ChUp][sx3ChDn])
{ {
GM_EUp = frontGain[sx3ID[0].first][sx3ChBk][sx3ChUp][sx3ChDn] * sx3EUp; GM_EUp = frontGain[sx3ID[i].first][sx3ChBk][sx3ChUp][sx3ChDn] * sx3EUp;
if (GM_EUp > 50.0) if (GM_EUp > 50.0)
hSX3Spectra[sx3ID[0].first][sx3ChBk][sx3ChUp][sx3ChDn]->Fill(GM_EUp); // optional: mixes raw+calib hSX3Spectra[sx3ID[i].first][sx3ChBk][sx3ChUp][sx3ChDn]->Fill(GM_EUp); // optional: mixes raw+calib
} }
// --- If back gain is available, also fill calibrated energy // --- If back gain is available, also fill calibrated energy
hsx3E_raw->Fill(sx3EBk); hsx3E_raw->Fill(sx3EBk);
if (backGainValid[sx3ID[0].first][sx3ChBk]) if (backGainValid[sx3ID[i].first][sx3ChBk])
{ {
calibEBack = backGain[sx3ID[0].first][sx3ChBk] * sx3EBk; calibEBack = backGain[sx3ID[i].first][sx3ChBk] * sx3EBk;
if (calibEBack > 50.0) if (calibEBack > 50.0)
hsx3E_calib->Fill(calibEBack); // optional: mixes raw+calib hsx3E_calib->Fill(calibEBack); // optional: mixes raw+calib
} }
// Keep the other diagnostic plots // Keep the other diagnostic plots
hsx3IndexVE_gm->Fill(sx3.index[sx3ID[0].second], GM_EUp); hsx3IndexVE_gm->Fill(sx3.index[sx3ID[i].second], GM_EUp);
hSX3->Fill(sx3ChDn + 4, sx3ChBk); hSX3->Fill(sx3ChDn + 4, sx3ChBk);
hSX3->Fill(sx3ChUp, sx3ChBk); hSX3->Fill(sx3ChUp, sx3ChBk);
hSX3FvsB->Fill(sx3EUp + sx3EDn, sx3EBk); hSX3FvsB->Fill(sx3EUp + sx3EDn, sx3EBk);
if (GM_EUp > 50.0 && sx3EBk > 50.0) if (GM_EUp > 50.0 && sx3EBk > 50.0)
{ {
sx3_contr.CalSX3Pos(sx3ID[0].first, sx3ChUp, sx3ChDn, sx3ChBk, GM_EUp, sx3EDn); sx3_contr.CalSX3Pos(sx3ID[i].first, sx3ChUp, sx3ChDn, sx3ChBk, GM_EUp, sx3EDn);
hitPos = sx3_contr.GetHitPos(); hitPos = sx3_contr.GetHitPos();
HitNonZero = true; HitNonZero = true;
} }
} }
} }
} }
}
// ======================= QQQ ======================= // ======================= QQQ =======================
for (int i = 0; i < qqq.multi; i++) for (int i = 0; i < qqq.multi; i++)

View File

@ -283,7 +283,7 @@ void GainMatchSX3::Terminate()
continue; // not enough statistics continue; // not enough statistics
// Build graph with errors // Build graph with errors
const double fixedError = 10.0; // ADC channels const double fixedError = 0.0; // ADC channels
std::vector<double> exVals(udE.size(), 0.0); // no x error std::vector<double> exVals(udE.size(), 0.0); // no x error
std::vector<double> eyVals(udE.size(), fixedError); // constant y error std::vector<double> eyVals(udE.size(), fixedError); // constant y error
@ -291,7 +291,7 @@ void GainMatchSX3::Terminate()
exVals.data(), eyVals.data()); exVals.data(), eyVals.data());
TF1 f("f", "[0]*x", 0, 16000); TF1 f("f", "[0]*x", 0, 16000);
f.SetParameter(0, 1.0); // initial slope // f.SetParameter(0, 1.0); // initial slope
if (drawCanvases) if (drawCanvases)
{ {
@ -329,7 +329,7 @@ void GainMatchSX3::Terminate()
g.Fit(&f, "QNR"); g.Fit(&f, "QNR");
} }
double slope = f.GetParameter(0); double slope = 1/f.GetParameter(0);
if (std::abs(slope - 1.0) < 0.3) // sanity check if (std::abs(slope - 1.0) < 0.3) // sanity check
{ {
backSlope[id][bk] = slope; backSlope[id][bk] = slope;

View File

@ -44,17 +44,15 @@ bool frontGainValid[MAX_DET][MAX_BK][MAX_UP][MAX_DOWN] = {{{{false}}}};
double uvdslope[MAX_DET][MAX_BK][MAX_UP][MAX_DOWN] = {{{{0}}}}; double uvdslope[MAX_DET][MAX_BK][MAX_UP][MAX_DOWN] = {{{{0}}}};
// ==== Configuration Flags ==== // ==== Configuration Flags ====
const bool interactiveMode = false; // If true: show canvas + wait for user const bool interactiveMode = false; // If true: show canvas + wait for user
const bool interactiveMode1 = false; // If true: show canvas + wait for user
const bool verboseFit = true; // If true: print fit summary and chi² const bool verboseFit = true; // If true: print fit summary and chi²
const bool drawCanvases = false; // If false: canvases won't be drawn at all const bool drawCanvases = false; // If false: canvases won't be drawn at all
const bool drawCanvases1 = false; // If false: canvases won't be drawn at all
void GainMatchSX3Front::Begin(TTree * /*tree*/) void GainMatchSX3Front::Begin(TTree * /*tree*/)
{ {
TString option = GetOption(); TString option = GetOption();
hSX3FvsB = new TH2F("hSX3FvsB", "SX3 Front vs Back; Front E; Back E", 400, 0, 16000, 400, 0, 16000); hSX3FvsB = new TH2F("hSX3FvsB", "SX3 Front vs Back; Front E; Back E", 800, 0, 16000, 800, 0, 16000);
hSX3FvsB_g = new TH2F("hSX3FvsB_g", "SX3 Front vs Back; Front E; Back E", 400, 0, 16000, 400, 0, 16000); hSX3FvsB_g = new TH2F("hSX3FvsB_g", "SX3 Front vs Back; Front E; Back E", 800, 0, 16000, 800, 0, 16000);
hsx3IndexVE = new TH2F("hsx3IndexVE", "SX3 index vs Energy; sx3 index ; Energy", 24 * 12, 0, 24 * 12, 400, 0, 5000); hsx3IndexVE = new TH2F("hsx3IndexVE", "SX3 index vs Energy; sx3 index ; Energy", 24 * 12, 0, 24 * 12, 400, 0, 5000);
hsx3IndexVE_g = new TH2F("hsx3IndexVE_g", "SX3 index vs Energy; sx3 index ; Energy", 24 * 12, 0, 24 * 12, 400, 0, 5000); hsx3IndexVE_g = new TH2F("hsx3IndexVE_g", "SX3 index vs Energy; sx3 index ; Energy", 24 * 12, 0, 24 * 12, 400, 0, 5000);
hSX3 = new TH2F("hSX3", "SX3 Front v Back; Fronts; Backs", 8, 0, 8, 4, 0, 4); hSX3 = new TH2F("hSX3", "SX3 Front v Back; Fronts; Backs", 8, 0, 8, 4, 0, 4);
@ -84,27 +82,6 @@ void GainMatchSX3Front::Begin(TTree * /*tree*/)
return; return;
} }
cut1->SetName("UvD"); cut1->SetName("UvD");
// std::string filename = "sx3_GainMatchback.txt";
// std::ifstream infile(filename);
// if (!infile.is_open())
// {
// std::cerr << "Error opening " << filename << "!" << std::endl;
// return;
// }
// int id, bk, u, d;
// double gain;
// while (infile >> id >> bk >> u >> d >> gain)
// {
// backGain[id][bk][u][d] = gain;
// if (backGain[id][bk][u][d] > 0)
// backGainValid[id][bk][u][d] = true;
// else
// backGainValid[id][bk][u][d] = false;
// }
// infile.close();
// std::cout << "Loaded back gains from " << filename << std::endl;
std::string filename = "sx3_BackGains.txt"; std::string filename = "sx3_BackGains.txt";
@ -115,7 +92,7 @@ void GainMatchSX3Front::Begin(TTree * /*tree*/)
return; return;
} }
int id, bk, u, d; int id, bk;
double gain; double gain;
while (infile >> id >> bk >> gain) while (infile >> id >> bk >> gain)
{ {
@ -254,10 +231,10 @@ Bool_t GainMatchSX3Front::Process(Long64_t entry)
if (cut && cut->IsInside(sx3EUp + sx3EDn, sx3EBk) && cut1 && cut1->IsInside(sx3EUp / sx3EBk, sx3EDn / sx3EBk)) if (cut && cut->IsInside(sx3EUp + sx3EDn, sx3EBk) && cut1 && cut1->IsInside(sx3EUp / sx3EBk, sx3EDn / sx3EBk))
{ {
// if (backGainValid[sx3.id[i]][sx3ChBk]) if (backGainValid[sx3.id[i]][sx3ChBk])
// { {
// sx3EBk *= backGain[sx3.id[i]][sx3ChBk]; sx3EBk *= backGain[sx3.id[i]][sx3ChBk];
// } }
// Accumulate data for gain matching // Accumulate data for gain matching
dataPoints[{sx3.id[i], sx3ChBk, sx3ChUp, sx3ChDn}].emplace_back(sx3EBk, sx3EUp, sx3EDn); dataPoints[{sx3.id[i], sx3ChBk, sx3ChUp, sx3ChDn}].emplace_back(sx3EBk, sx3EUp, sx3EDn);
} }
@ -290,7 +267,7 @@ void GainMatchSX3Front::Terminate()
auto [id, bk, u, d] = kv.first; auto [id, bk, u, d] = kv.first;
const auto &pts = kv.second; const auto &pts = kv.second;
if (pts.size() < 500) if (pts.size() < 50)
continue; continue;
std::vector<double> uE, dE, udE, corrBkE; std::vector<double> uE, dE, udE, corrBkE;
@ -322,20 +299,20 @@ void GainMatchSX3Front::Terminate()
// Build data with fixed error // Build data with fixed error
for (size_t i = 0; i < udE.size(); ++i) for (size_t i = 0; i < udE.size(); ++i)
{ {
double x = udE[i]; // front energy double x = uE[i]; // front energy
double y = corrBkE[i]; // back energy double y = dE[i]; // back energy
xVals.push_back(x); xVals.push_back(x);
yVals.push_back(y); yVals.push_back(y);
// exVals.push_back(fixedError); // error in front energy exVals.push_back(fixedError); // error in up energy
eyVals.push_back(fixedError); // error in back energy // eyVals.push_back(fixedError); // error in down energy
} }
// Build TGraphErrors with errors // Build TGraphErrors with errors
TGraphErrors g(xVals.size(), xVals.data(), yVals.data(), exVals.data(), eyVals.data()); TGraphErrors g(xVals.size(), xVals.data(), yVals.data(), exVals.data(), eyVals.data());
TF1 f("f", "[0]*x", 0, 16000); TF1 f("f", "[0]*x", 0, 16000);
f.SetParameter(0, 1.0); // Initial guess f.SetParameter(0, -1.0); // Initial guess
if (drawCanvases) if (drawCanvases)
{ {
@ -353,9 +330,9 @@ void GainMatchSX3Front::Terminate()
int ndf = f.GetNDF(); int ndf = f.GetNDF();
double reducedChi2 = (ndf != 0) ? chi2 / ndf : -1; double reducedChi2 = (ndf != 0) ? chi2 / ndf : -1;
// std::cout << Form("Det%d U%d D%d B%d → Gain: %.4f | χ²/ndf = %.2f/%d = %.2f", std::cout << Form("Det%d U%d D%d B%d → Gain: %.4f | χ²/ndf = %.2f/%d = %.2f",
// id, u, d, bk, f.GetParameter(0), chi2, ndf, reducedChi2) id, u, d, bk, f.GetParameter(0), chi2, ndf, reducedChi2)
// << std::endl; << std::endl;
} }
if (interactiveMode) if (interactiveMode)
@ -380,87 +357,6 @@ void GainMatchSX3Front::Terminate()
// printf("Front gain Det%d Back%d Up%dDn%d → %.4f\n", id, bk, u, d, frontGain[id][bk][u][d]); // printf("Front gain Det%d Back%d Up%dDn%d → %.4f\n", id, bk, u, d, frontGain[id][bk][u][d]);
} }
for (const auto &kv : dataPoints)
{
auto [id, bk, u, d] = kv.first;
const auto &pts = kv.second;
std::vector<double> uvals, dvals;
double front = frontGain[id][bk][u][d];
if (pts.size() < 5)
continue;
std::vector<double> uE, dE, udE, corrBkE;
for (const auto &pr : pts)
{
double eBkCorr, eUp, eDn;
std::tie(eBkCorr, eUp, eDn) = pr;
if ((eBkCorr < 100) || (eUp < 100) || (eDn < 100))
continue; // Skip if any energy is zero
eUp *= front;
// eDn *= frontGain[id][bk][u][d];
uE.push_back(eUp / eBkCorr);
dE.push_back(eDn / eBkCorr);
corrBkE.push_back(eBkCorr);
}
for (size_t i = 0; i < uE.size(); ++i)
{
uvals.push_back(uE[i]);
dvals.push_back(dE[i]);
}
TGraph g1(uvals.size(), uvals.data(), dvals.data());
g1.SetMarkerStyle(20);
g1.SetMarkerColor(kBlue);
g1.SetTitle(Form("Det %d: U%d D%d B%d", id, u, d, bk));
// Fit function (straight line through origin)
TF1 f1("f1", "[0]*x+[1]", 0, 16000);
f1.SetParameter(0, -1.0);
if (drawCanvases1)
{
TCanvas *c1 = new TCanvas(Form("c_%d_%d_%d_%d", id, bk, u, d), "Fit", 800, 600);
g1.SetTitle(Form("Detector %d: U%d D%d B%d", id, u, d, bk));
g1.SetMarkerStyle(20);
g1.SetMarkerColor(kBlue);
g1.Draw("AP");
g1.Fit(&f1, interactiveMode1 ? "Q" : "QNR"); // 'R' avoids refit, 'N' skips drawing
if (verboseFit)
{
double chi2 = f1.GetChisquare();
int ndf1 = f1.GetNDF();
double reducedChi2 = (ndf1 != 0) ? chi2 / ndf1 : -1;
std::cout << Form("Det%d U%d D%d B%d → Gain: %.4f | χ²/ndf = %.2f/%d = %.2f",
id, u, d, bk, f1.GetParameter(0), chi2, ndf1, reducedChi2)
<< std::endl;
}
if (interactiveMode1)
{
c1->Update();
gPad->WaitPrimitive();
}
else
{
c1->Close(); // Optionally avoid clutter in batch
}
}
else
{
g1.Fit(&f1, "QNR");
}
// Save slope
uvdslope[id][bk][u][d] = f1.GetParameter(0);
printf("UvD slope Det%d Back%d Up%dDn%d → %.4f\n", id, bk, u, d, uvdslope[id][bk][u][d]);
}
outFile.close(); outFile.close();
std::cout << "Gain matching complete." << std::endl; std::cout << "Gain matching complete." << std::endl;