File indexing completed on 2026-08-31 08:24:39
0001 #include <TH1D.h>
0002 #include <TCanvas.h>
0003 #include <TLine.h>
0004 #include <TStyle.h>
0005 #include <TFile.h>
0006 #include <TTree.h>
0007 #include <TGraph.h>
0008 #include <TMultiGraph.h>
0009
0010 #include <iostream>
0011 #include <fstream>
0012 #include <iomanip>
0013 #include <string>
0014 #include <cmath>
0015 #include <filesystem>
0016
0017 #include <fun4all/Fun4AllUtils.h>
0018
0019 #include <mbd/MbdCalib.h>
0020 #include <mbd/MbdGeomV2.h>
0021 #include "get_runstr.h"
0022
0023 R__LOAD_LIBRARY(libmbd.so)
0024 R__LOAD_LIBRARY(libmbd_io.so)
0025
0026
0027
0028
0029
0030 void average_timecorr(const std::string& listfile = "tcorr.list")
0031 {
0032 constexpr int NPMT = 128;
0033
0034 MbdGeom* mbdgeom = new MbdGeomV2();
0035
0036
0037 std::vector<std::string> files;
0038 std::vector<int> runs;
0039 {
0040 std::ifstream lf(listfile);
0041 if (!lf.is_open())
0042 {
0043 std::cerr << "Error: Could not open " << listfile << std::endl;
0044 return;
0045 }
0046
0047 auto parse_run = [](const std::string& path) -> int
0048 {
0049 size_t slash2 = path.rfind('/');
0050 size_t slash1 = (slash2 == std::string::npos) ? std::string::npos : path.rfind('/', slash2 - 1);
0051 size_t start = (slash1 == std::string::npos) ? 0 : slash1 + 1;
0052 std::string dir = path.substr(start, (slash2 == std::string::npos ? path.size() : slash2) - start);
0053 size_t dash = dir.find('-');
0054 if (dash == std::string::npos) return -1;
0055 try { return std::stoi(dir.substr(0, dash)); }
0056 catch (...) { return -1; }
0057 };
0058
0059 std::string path;
0060 while (lf >> path)
0061 {
0062 int runno = parse_run(path);
0063 if (runno < 0)
0064 {
0065 std::cerr << "Warning: Could not parse run number from: " << path << std::endl;
0066 continue;
0067 }
0068 files.push_back(path);
0069 runs.push_back(runno);
0070 }
0071 }
0072
0073 if (files.empty())
0074 {
0075 std::cerr << "Error: no valid files in " << listfile << std::endl;
0076 return;
0077 }
0078
0079 int nruns = (int)files.size();
0080
0081
0082 std::vector<MbdCalib*> calibs(files.size());
0083 for (size_t i = 0; i < files.size(); i++)
0084 {
0085 std::cout << "Loading " << files[i] << std::endl;
0086 calibs[i] = new MbdCalib();
0087 calibs[i]->Download_TimeCorr(files[i]);
0088 }
0089
0090
0091 int min_tdc, max_tdc, step;
0092 calibs[0]->get_tcorr_range(0, min_tdc, max_tdc, step);
0093 int ntdc = (max_tdc - min_tdc) / step + 1;
0094 std::cout << "LUT size: " << ntdc << " bins [" << min_tdc << ", " << max_tdc << "] step=" << step << std::endl;
0095
0096
0097 TFile* fout = new TFile("timecorr_avg.root", "RECREATE");
0098 TTree* t = new TTree("t", "TimCorr LUT ratios vs first run");
0099 int t_run;
0100 int t_ch;
0101 double t_ratio;
0102 double t_delta;
0103 t->Branch("run", &t_run, "run/I");
0104 t->Branch("ch", &t_ch, "ch/I");
0105 t->Branch("ratio", &t_ratio, "ratio/D");
0106 t->Branch("delta", &t_delta, "delta/D");
0107
0108
0109 std::vector<std::vector<double>> ratio_by_ch(NPMT, std::vector<double>(files.size(), 0.));
0110 std::vector<std::vector<double>> delta_by_ch(NPMT, std::vector<double>(files.size(), 0.));
0111
0112
0113 std::vector<std::vector<double>> lut_sum(NPMT, std::vector<double>(ntdc, 0.));
0114
0115
0116 for (size_t irun = 0; irun < files.size(); irun++)
0117 {
0118 t_run = runs[irun];
0119 for (int ipmt = 0; ipmt < NPMT; ipmt++)
0120 {
0121 int ifeech = mbdgeom->get_feech(ipmt, 0);
0122
0123 double sum = 0.;
0124 double sum_delta = 0.;
0125 int ngood = 0;
0126 for (int ilut = 0; ilut < ntdc; ilut++)
0127 {
0128 int itdc = ilut*step;
0129 float val = calibs[irun]->get_tcorr(ifeech, itdc);
0130 lut_sum[ipmt][ilut] += val;
0131
0132
0133 if ( itdc<1400. || itdc>13450. )
0134 {
0135 continue;
0136 }
0137
0138 float ref = calibs[0]->get_tcorr(ifeech, itdc);
0139
0140 sum += val / ref;
0141 sum_delta += val - ref;
0142 ngood++;
0143 }
0144
0145 t_ch = ipmt;
0146 t_ratio = (ngood > 0) ? sum / ngood : 0.;
0147 t_delta = (ngood > 0) ? sum_delta / ngood : 0.;
0148 ratio_by_ch[ipmt][irun] = t_ratio;
0149 delta_by_ch[ipmt][irun] = t_delta;
0150 t->Fill();
0151 }
0152 }
0153
0154 fout->cd();
0155 t->Write();
0156 std::cout << "Saved " << t->GetEntries() << " entries to timecorr_avg.root" << std::endl;
0157
0158
0159 std::vector<double> mean_delta(NPMT, 0.);
0160 for (int ipmt = 0; ipmt < NPMT; ipmt++)
0161 {
0162 for (int ir = 0; ir < nruns; ir++) mean_delta[ipmt] += delta_by_ch[ipmt][ir];
0163 mean_delta[ipmt] /= nruns;
0164 }
0165
0166
0167 std::vector<std::vector<double>> avg_lut(NPMT, std::vector<double>(ntdc, 0.));
0168 for (int ipmt = 0; ipmt < NPMT; ipmt++)
0169 {
0170 for (int ilut = 0; ilut < ntdc; ilut++)
0171 {
0172 avg_lut[ipmt][ilut] = lut_sum[ipmt][ilut] / nruns - mean_delta[ipmt];
0173 }
0174 }
0175
0176
0177 {
0178 std::ofstream calout("avg_mbd_timecorr.calib");
0179 calout << std::fixed << std::setprecision(5);
0180 for (int ipmt = 0; ipmt < NPMT; ipmt++)
0181 {
0182 int ifeech = mbdgeom->get_feech(ipmt,0);
0183 calout << ifeech << "\t" << ntdc << "\t" << min_tdc << "\t" << max_tdc << "\n";
0184 for (int ilut = 0; ilut < ntdc; ilut++)
0185 {
0186 calout << avg_lut[ipmt][ilut];
0187 calout << ((ilut % 10 == 9) ? "\n" : " ");
0188 }
0189 if (ntdc % 10 != 0) calout << "\n";
0190 }
0191 std::cout << "Wrote avg_mbd_timecorr.calib" << std::endl;
0192 }
0193
0194
0195
0196
0197 TCanvas* cpdf = new TCanvas("cpdf", "TimCorr Average", 1000, 500);
0198 cpdf->Divide(2, 1);
0199 const TString pdfname = "timecorr_average.pdf";
0200 cpdf->Print(pdfname + "[");
0201
0202
0203 const int NCOLS = 9;
0204 const int cols[NCOLS] = {kBlue, kRed, kGreen+2, kMagenta, kCyan+1,
0205 kOrange+1, kViolet+1, kTeal+1, kPink+1};
0206
0207 for (int ipmt = 0; ipmt < NPMT; ipmt++)
0208 {
0209 int ifeech = mbdgeom->get_feech(ipmt, 0);
0210
0211
0212 TGraph* gratio = new TGraph(nruns);
0213 TString gname = "g_ratio_ch"; gname += ipmt;
0214 TString gtitle = "Ch "; gtitle += ipmt; gtitle += " ratio vs run;Run index;Mean LUT ratio";
0215 gratio->SetName(gname);
0216 gratio->SetTitle(gtitle);
0217 gratio->SetMarkerStyle(20);
0218 gratio->SetMarkerSize(0.7);
0219 for (int ir = 0; ir < nruns; ir++)
0220 gratio->SetPoint(ir, ir, ratio_by_ch[ipmt][ir]);
0221
0222 cpdf->cd(1);
0223 gratio->Draw("AP");
0224
0225
0226
0227 TMultiGraph* mg = new TMultiGraph();
0228 TString mgtitle = "Ch "; mgtitle += ipmt;
0229 mgtitle += " corrected LUT;TDC;Time - <#Delta> (ns)";
0230 mg->SetTitle(mgtitle);
0231
0232 for (size_t irun = 0; irun < files.size(); irun++)
0233 {
0234 TGraph* glut = new TGraph();
0235 for (int ilut = 0; ilut < ntdc; ilut++)
0236 {
0237 int itdc = ilut*step;
0238 if ( itdc>14200. )
0239 {
0240 continue;
0241 }
0242 float val = calibs[irun]->get_tcorr(ifeech, itdc);
0243 glut->AddPoint(itdc, val - mean_delta[ipmt]);
0244 }
0245 int col = cols[irun % NCOLS];
0246 glut->SetLineColor(col);
0247 glut->SetMarkerColor(col);
0248 glut->SetMarkerStyle(1);
0249 mg->Add(glut, "L");
0250 }
0251
0252
0253 TGraph* gavg = new TGraph();
0254 for (int ilut = 0; ilut < ntdc; ilut++)
0255 {
0256 int itdc = ilut*step;
0257 if ( itdc>13450. ) continue;
0258 gavg->AddPoint(itdc, avg_lut[ipmt][ilut]);
0259 }
0260 gavg->SetLineColor(kBlack);
0261 gavg->SetLineWidth(2);
0262 gavg->SetMarkerStyle(1);
0263 mg->Add(gavg, "L");
0264
0265 cpdf->cd(2);
0266 mg->Draw("A");
0267
0268 cpdf->Update();
0269 cpdf->Print(pdfname);
0270
0271 delete gratio;
0272 delete mg;
0273 }
0274
0275 cpdf->Print(pdfname + "]");
0276 std::cout << "Created: " << pdfname << std::endl;
0277 delete cpdf;
0278 }
0279
0280
0281
0282 void timecorr_all(const std::string& listfile = "tcorr.list")
0283 {
0284 constexpr int NPMT = 128;
0285
0286 MbdGeom* mbdgeom = new MbdGeomV2();
0287
0288
0289 std::vector<std::string> files;
0290 std::vector<int> runs;
0291 {
0292 std::ifstream lf(listfile);
0293 if (!lf.is_open())
0294 {
0295 std::cerr << "Error: Could not open " << listfile << std::endl;
0296 return;
0297 }
0298 auto parse_run = [](const std::string& path) -> int
0299 {
0300 size_t slash2 = path.rfind('/');
0301 size_t slash1 = (slash2 == std::string::npos) ? std::string::npos : path.rfind('/', slash2 - 1);
0302 size_t start = (slash1 == std::string::npos) ? 0 : slash1 + 1;
0303 std::string dir = path.substr(start, (slash2 == std::string::npos ? path.size() : slash2) - start);
0304 size_t dash = dir.find('-');
0305 if (dash == std::string::npos) return -1;
0306 try { return std::stoi(dir.substr(0, dash)); }
0307 catch (...) { return -1; }
0308 };
0309 std::string path;
0310 while (lf >> path)
0311 {
0312 int runno = parse_run(path);
0313 if (runno < 0)
0314 {
0315 std::cerr << "Warning: Could not parse run number from: " << path << std::endl;
0316 continue;
0317 }
0318 files.push_back(path);
0319 runs.push_back(runno);
0320 }
0321 }
0322 if (files.empty())
0323 {
0324 std::cerr << "Error: no valid files in " << listfile << std::endl;
0325 return;
0326 }
0327
0328
0329 std::vector<MbdCalib*> calibs(files.size());
0330 for (size_t i = 0; i < files.size(); i++)
0331 {
0332 std::cout << "Loading " << files[i] << std::endl;
0333 calibs[i] = new MbdCalib();
0334 calibs[i]->Download_TimeCorr(files[i]);
0335 }
0336
0337
0338 int min_tdc, max_tdc, step;
0339 calibs[0]->get_tcorr_range(0, min_tdc, max_tdc, step);
0340 int ntdc = (max_tdc - min_tdc) / step + 1;
0341 std::cout << "LUT: " << ntdc << " entries tdc=[" << min_tdc << "," << max_tdc << "] step=" << step << std::endl;
0342
0343
0344 TFile* fout = new TFile("timecorr.root", "RECREATE");
0345 TTree* t = new TTree("t", "Full timecorr LUT dump");
0346
0347 int t_run;
0348 Short_t t_ch;
0349 Short_t t_index;
0350 UShort_t t_tdc;
0351 Float_t t_time;
0352
0353 t->Branch("run", &t_run, "run/I");
0354 t->Branch("ch", &t_ch, "ch/S");
0355 t->Branch("index", &t_index, "index/S");
0356 t->Branch("tdc", &t_tdc, "tdc/s");
0357 t->Branch("time", &t_time, "time/F");
0358
0359 for (size_t irun = 0; irun < files.size(); irun++)
0360 {
0361 t_run = runs[irun];
0362 for (int ipmt = 0; ipmt < NPMT; ipmt++)
0363 {
0364 int ifeech = mbdgeom->get_feech(ipmt, 0);
0365 t_ch = (Short_t)ipmt;
0366 for (int ilut = 0; ilut < ntdc; ilut++)
0367 {
0368 int itdc = min_tdc + ilut * step;
0369 t_index = (Short_t)ilut;
0370 t_tdc = (UShort_t)itdc;
0371 t_time = calibs[irun]->get_tcorr(ifeech, itdc);
0372 t->Fill();
0373 }
0374 }
0375 }
0376
0377 fout->cd();
0378 t->Write();
0379 std::cout << "Saved " << t->GetEntries() << " entries to timecorr.root" << std::endl;
0380
0381 for (auto* c : calibs) delete c;
0382 delete fout;
0383 }
0384
0385
0386 void comp_timecorr(const std::string &file1 = "00065735-0000/mbd_timecorr.calib", const std::string &file2 = "00078986-0000/mbd_timecorr.calib")
0387 {
0388 gStyle->SetOptStat(0);
0389
0390 constexpr int NPMT = 128;
0391 constexpr int NTDC = 1000;
0392 constexpr double BAD_THRESHOLD = 0.1;
0393
0394 int verbose = 0;
0395
0396
0397 int runno1 = Fun4AllUtils::GetRunSegment( std::filesystem::path( std::filesystem::path(file1).parent_path() ).filename().append(".root") ).first;
0398 int runno2 = Fun4AllUtils::GetRunSegment( std::filesystem::path( std::filesystem::path(file2).parent_path() ).filename().append(".root") ).first;
0399 std::cout << "Processing " << runno1 << "\t" << runno2 << std::endl;
0400
0401 MbdGeom *mbdgeom = new MbdGeomV2();
0402
0403
0404
0405 MbdCalib *calib1 = new MbdCalib();
0406 MbdCalib *calib2 = new MbdCalib();
0407
0408 std::cout << "Downloading time corrections from:\n" << " " << file1 << "\n" << " " << file2 << std::endl;
0409
0410 calib1->Download_TimeCorr(file1);
0411 calib2->Download_TimeCorr(file2);
0412
0413 int step1, min1, max1;
0414 int step2, min2, max2;
0415 calib1->get_tcorr_range(0,min1,max1,step1);
0416 calib2->get_tcorr_range(0,min2,max2,step2);
0417 if ( (step1 != step2) || (min1!=min2) || (max1!=max2) )
0418 {
0419 std::cerr << "timecorr shape differs" << std::endl;
0420 std::cerr << "min: " << min1 << "\t" << min2 << std::endl;
0421 std::cerr << "max: " << max1 << "\t" << max2 << std::endl;
0422 std::cerr << "steps: " << step1 << "\t" << step2 << std::endl;
0423 return;
0424 }
0425
0426
0427
0428
0429 TH1 *h_tdiff[NPMT];
0430 TH1 *h_tdifftot;
0431 TString name;
0432 TString title;
0433
0434 int nbins = ((max1-min1)/step1) + 1;
0435 std::cout << nbins << std::endl;
0436 for (int ipmt = 0; ipmt < NPMT; ++ipmt)
0437 {
0438 name = "h_tdiff"; name += ipmt;
0439 title = name; title += ", runs "; title += runno1; title += "-"; title += runno2;
0440 h_tdiff[ipmt] = new TH1F( name, title, nbins, min1-0.5, max1+0.5);
0441 h_tdiff[ipmt]->SetXTitle("TDC");
0442 h_tdiff[ipmt]->SetYTitle("tdiff [ns]");
0443 }
0444 title = "time diffs, all channels and TDCs, runs "; title += runno1; title += "-"; title += runno2;
0445 h_tdifftot = new TH1F( "h_tdifftot", title, 1000, -0.2, 0.2);
0446 h_tdifftot->SetXTitle("tdiff [ns]");
0447
0448
0449
0450
0451 if ( verbose )
0452 {
0453 std::cout << std::fixed << std::setprecision(4);
0454 std::cout << "Ch TDC TimeCorr1 TimeCorr2 Diff" << std::endl;
0455 std::cout << "----------------------------------------" << std::endl;
0456 }
0457 std::ofstream outfile("bad_comp_timecorr.txt");
0458 outfile << std::fixed << std::setprecision(4);
0459 outfile << "Ch TDC TimeCorr1 TimeCorr2 Diff" << std::endl;
0460 outfile << "----------------------------------------" << std::endl;
0461
0462 for (int ipmt = 0; ipmt < NPMT; ++ipmt)
0463 {
0464 int ifeech = mbdgeom->get_feech(ipmt,0);
0465
0466 for (int itdc = 0; itdc < NTDC; ++itdc)
0467 {
0468 float t1 = calib1->get_tcorr(ifeech, itdc);
0469 float t2 = calib2->get_tcorr(ifeech, itdc);
0470 float diff = t2 - t1;
0471
0472 h_tdiff[ipmt]->SetBinContent(itdc+1,diff);
0473 h_tdifftot->Fill(diff);
0474
0475 if (std::abs(diff) > BAD_THRESHOLD)
0476 {
0477 if ( verbose )
0478 {
0479 std::cout << std::setw(3) << ipmt << " "
0480 << std::setw(3) << itdc << " "
0481 << std::setw(10) << t1 << " "
0482 << std::setw(10) << t2 << " "
0483 << std::setw(8) << diff
0484 << std::endl;
0485 }
0486 outfile << std::setw(3) << ipmt << " "
0487 << std::setw(3) << itdc << " "
0488 << std::setw(10) << t1 << " "
0489 << std::setw(10) << t2 << " "
0490 << std::setw(8) << diff
0491 << std::endl;
0492 }
0493 }
0494 }
0495
0496
0497
0498
0499 TCanvas *ac[100];
0500 int icv = 0;
0501
0502 ac[icv] = new TCanvas("ac0", "MBD TimeCorr by PMT", 1200, 600);
0503 TString pdfname = "comp_timecorr_"; pdfname += runno1; pdfname += "_"; pdfname += runno2; pdfname += ".pdf";
0504 ac[icv]->Print(pdfname + "[");
0505
0506
0507 for (int ipmt = 0; ipmt < NPMT; ++ipmt)
0508 {
0509 h_tdiff[ipmt]->Draw("hist");
0510
0511 gPad->Modified();
0512 gPad->Update();
0513 ac[icv]->Print(pdfname);
0514 }
0515
0516
0517 h_tdifftot->Draw();
0518 ac[icv]->Print(pdfname);
0519 ac[icv]->Print(pdfname + "]");
0520
0521 icv++;
0522
0523 outfile.close();
0524 }