File indexing completed on 2025-08-03 08:15:36
0001 #include "SpinDBQA.h"
0002
0003 #include <TFile.h>
0004 #include <TH1D.h>
0005 #include <TH1F.h>
0006 #include <TGraphErrors.h>
0007
0008 #include <boost/format.hpp>
0009
0010 #include <regex>
0011 #include <filesystem>
0012 #include <iostream>
0013 #include <fstream>
0014 #include <vector>
0015 #include <string>
0016 #include <iterator>
0017
0018
0019 SpinDBQA::SpinDBQA()
0020 : spin_cont(),
0021 spin_out("phnxrc"),
0022 spin_in()
0023 {
0024 locpolbf = new TGraphErrors();
0025 locpolbf->SetName("locpolbf");
0026 locpolbb = new TGraphErrors();
0027 locpolbb->SetName("locpolbb");
0028 locpolyf = new TGraphErrors();
0029 locpolyf->SetName("locpolyf");
0030 locpolyb = new TGraphErrors();
0031 locpolyb->SetName("locpolyb");
0032
0033 locpolphasebf = new TGraphErrors();
0034 locpolphasebf->SetName("locpolphasebf");
0035 locpolphasebb = new TGraphErrors();
0036 locpolphasebb->SetName("locpolphasebb");
0037 locpolphaseyf = new TGraphErrors();
0038 locpolphaseyf->SetName("locpolphaseyf");
0039 locpolphaseyb = new TGraphErrors();
0040 locpolphaseyb->SetName("locpolphaseyb");
0041
0042 }
0043
0044
0045 void SpinDBQA::SetRunList(std::string runlist)
0046 {
0047 std::string line;
0048 std::ifstream irunlist;
0049 irunlist.open(runlist);
0050 if(!irunlist)
0051 {
0052 std::cout << "failed to open runlist " << std::endl;
0053 exit(1);
0054 }
0055 while (std::getline(irunlist, line)) {
0056 runlistvect.push_back(std::stoi(line));
0057 }
0058 irunlist.close();
0059 }
0060
0061 void SpinDBQA::ReadSpinDBData()
0062 {
0063 std::cout << "Reading data from spin database." << std::endl;
0064 std::cout << "There are " << runlistvect.size() << " runs. This may take several minutes..." << std::endl;
0065 int ite = 0;
0066
0067 if (b_defaultQA)
0068 {
0069 spin_out.StoreDBContent(runlistvect.front(),runlistvect.back());
0070 }
0071 else
0072 {
0073 spin_out.StoreDBContent(runlistvect.front(),runlistvect.back(), qalevel);
0074 }
0075
0076 for (const auto &run : runlistvect)
0077 {
0078 runnumber = run;
0079 int runexists = spin_out.GetDBContentStore(spin_cont,runnumber);
0080 if (runexists == 0)
0081 {
0082 map_fillnumber[runnumber] = -999;
0083 continue;
0084 }
0085
0086 map_fillnumber[runnumber] = spin_cont.GetFillNumber();
0087 map_qa_level[runnumber] = spin_cont.GetQALevel();
0088 map_crossingshift[runnumber] = spin_cont.GetCrossingShift();
0089
0090 for (int i = 0; i < 120; i++)
0091 {
0092 map_bluespin[runnumber].push_back(spin_cont.GetSpinPatternBlue(i));
0093 map_yellspin[runnumber].push_back(spin_cont.GetSpinPatternYellow(i));
0094 map_mbdns[runnumber].push_back(spin_cont.GetScalerMbdNoCut(i));
0095 map_mbdvtx[runnumber].push_back(spin_cont.GetScalerMbdVertexCut(i));
0096 map_zdcns[runnumber].push_back(spin_cont.GetScalerZdcNoCut(i));
0097 }
0098
0099 spin_cont.GetPolarizationBlue(0, map_bluepol[runnumber], map_bluepolerr[runnumber]);
0100 spin_cont.GetPolarizationYellow(0, map_yellpol[runnumber], map_yellpolerr[runnumber]);
0101 map_badrunqa[runnumber] = spin_cont.GetBadRunFlag();
0102 map_crossingangle[runnumber] = spin_cont.GetCrossAngle();
0103 map_crossanglestd[runnumber] = spin_cont.GetCrossAngleStd();
0104 map_crossanglemin[runnumber] = spin_cont.GetCrossAngleMin();
0105 map_crossanglemax[runnumber] = spin_cont.GetCrossAngleMax();
0106 spin_cont.GetAsymBlueForward(map_asymbf[runnumber], map_asymerrbf[runnumber]);
0107 spin_cont.GetAsymBlueBackward(map_asymbb[runnumber], map_asymerrbb[runnumber]);
0108 spin_cont.GetAsymYellowForward(map_asymyf[runnumber], map_asymerryf[runnumber]);
0109 spin_cont.GetAsymYellowBackward(map_asymyb[runnumber], map_asymerryb[runnumber]);
0110 spin_cont.GetPhaseBlueForward(map_phasebf[runnumber], map_phaseerrbf[runnumber]);
0111 spin_cont.GetPhaseBlueBackward(map_phasebb[runnumber], map_phaseerrbb[runnumber]);
0112 spin_cont.GetPhaseYellowForward(map_phaseyf[runnumber], map_phaseerryf[runnumber]);
0113 spin_cont.GetPhaseYellowBackward(map_phaseyb[runnumber], map_phaseerryb[runnumber]);
0114
0115 ++ite;
0116 }
0117 return;
0118 }
0119
0120 void SpinDBQA::doQA()
0121 {
0122 for (const auto &run : runlistvect)
0123 {
0124 runnumber = run;
0125 std::cout << "Processing QA on run: " << runnumber << std::endl;
0126 std::string stringMarkdown = "";
0127 std::string stringHtml = "";
0128 if (map_fillnumber[runnumber] == -999)
0129 {
0130 stringHtml += "Run does not exist at this qa_level";
0131 }
0132 else
0133 {
0134 CNIHjetQA(stringMarkdown,stringHtml);
0135 if (runnumber >= 45236){GL1pScalersQA(stringMarkdown,stringHtml);}
0136 else{stringHtml += "GL1p Scalers: <font color=\"#800080\">NOT AVAILABLE</font>; ";}
0137 LocalPolQA(stringMarkdown,stringHtml);
0138 CrossingAngleQA(stringMarkdown,stringHtml);
0139 map_spindbqa_markdown[stringMarkdown].push_back(runnumber);
0140 }
0141
0142 map_spindbqa_html[stringHtml].push_back(runnumber);
0143 }
0144 return;
0145 }
0146
0147 void SpinDBQA::CNIHjetQA(std::string &stringMarkdown, std::string &stringHtml)
0148 {
0149
0150 std::string filename = (boost::format("%s/fill_%d/DST_%d.root") % _cnipathname % map_fillnumber[runnumber] % map_fillnumber[runnumber]).str();
0151 std::ifstream file(filename.c_str());
0152 if (!file)
0153 {
0154 std::cerr << "File does not exist: " << filename << std::endl;
0155 stringMarkdown += ("\u274C CNI measurement exists ");
0156 stringHtml += ("Beam polarization: <font color=\"#800080\">NOT AVAILABLE</font>; Spin patterns: <font color=\"#800080\">NOT AVAILABLE</font>; ");
0157 }
0158 else if (map_bluepol[runnumber] == -999 || map_yellpol[runnumber] == -999)
0159 {
0160 stringMarkdown += ("\u274C CNI measurement exists ");
0161 stringHtml += ("Beam polarization: <font color=\"#800080\">NOT AVAILABLE</font>; Spin patterns: <font color=\"#800080\">NOT AVAILABLE</font>; ");
0162 }
0163 else
0164 {
0165 TFile *cnipol = new TFile(filename.c_str());
0166 if (!cnipol || cnipol->IsZombie())
0167 {
0168 std::cout << "Failed to open file: " << filename << std::endl;
0169 stringMarkdown += ("\u274C CNI measurement exists ");
0170 stringHtml += ("Beam polarization: <font color=\"#800080\">NOT AVAILABLE</font>; Spin patterns: <font color=\"#800080\">NOT AVAILABLE</font>; ");
0171 }
0172 else
0173 {
0174 stringMarkdown += ("\u2705 CNI measurement exists ");
0175
0176 TH1D *h_results = (TH1D*)cnipol->Get("h_results");
0177 h_results->SetDirectory(0);
0178
0179 TH1D *hcnipatternYellow = (TH1D*)cnipol->Get("h_polYellow");
0180 TH1D *hcnipatternBlue = (TH1D*)cnipol->Get("h_polBlue");
0181 hcnipatternYellow->SetDirectory(0);
0182 hcnipatternBlue->SetDirectory(0);
0183
0184 cnipol->Close();
0185 delete cnipol;
0186
0187
0188 float cnibeampol_yellow = h_results->GetBinContent(9);
0189 float cnibeampol_blue = h_results->GetBinContent(10);
0190
0191
0192
0193
0194 stringMarkdown += (cnibeampol_yellow < 0 || cnibeampol_yellow > 1 || cnibeampol_blue < 0 || cnibeampol_blue > 0) ?
0195 "\u2705 CNI beam polarization " : "\u274C CNI beam polarization ";
0196 stringHtml += (cnibeampol_yellow < 0 || cnibeampol_yellow > 1 || cnibeampol_blue < 0 || cnibeampol_blue > 0) ?
0197 "Beam polarization: <font color=\"#11cf17\">GOOD</font>; " : " Beam polarization: <font color=\"#ff0000\">BAD</font>; ";
0198
0199
0200 int abortgaplength = 8;
0201 int currentCountYell = 0;
0202 int currentCountBlue = 0;
0203 int lastAgBunchIndexYell = -1;
0204 int lastAgBunchIndexBlue = -1;
0205
0206 for (size_t i = 0; i < 120; ++i) {
0207 if (hcnipatternYellow->GetBinContent(i+1) == 0) {
0208 currentCountYell++;
0209 if (currentCountYell > abortgaplength) {
0210 abortgaplength = currentCountYell;
0211 lastAgBunchIndexYell = i;
0212 }
0213 } else {
0214 currentCountYell = 0;
0215 }
0216
0217 if (hcnipatternBlue->GetBinContent(i+1) == 0) {
0218 currentCountBlue++;
0219 if (currentCountBlue > abortgaplength) {
0220 abortgaplength = currentCountBlue;
0221 lastAgBunchIndexBlue = i;
0222 }
0223 } else {
0224 currentCountBlue = 0;
0225 }
0226 }
0227
0228 int xingshift_cniYell = 119-lastAgBunchIndexYell;
0229 int xingshift_cniBlue = 119-lastAgBunchIndexBlue;
0230
0231 for (int i = 0; i < 120; i++)
0232 {
0233 int cniyellowbunchspin = hcnipatternYellow->GetBinContent((i+120-xingshift_cniYell)%120+1);
0234 int cnibluebunchspin = hcnipatternBlue->GetBinContent((i+120-xingshift_cniBlue)%120+1);
0235 if (cniyellowbunchspin == 0)
0236 {
0237 cniyellowbunchspin = 10;
0238 }
0239 if (cnibluebunchspin == 0)
0240 {
0241 cnibluebunchspin = 10;
0242 }
0243 if (cniyellowbunchspin != map_yellspin[runnumber].at(i) || cnibluebunchspin != map_bluespin[runnumber].at(i))
0244 {
0245
0246 stringMarkdown += "\u274C CNI spin pattern match ";
0247 stringHtml += "Spin patterns: <font color=\"#ff0000\">BAD</font>; ";
0248 break;
0249 }
0250 else if (i == 119)
0251 {
0252 stringMarkdown += "\u2705 CNI spin pattern match ";
0253 stringHtml += "Spin patterns: <font color=\"#11cf17\">GOOD</font>; ";
0254 }
0255 }
0256 }
0257 }
0258 return;
0259
0260 }
0261
0262
0263 void SpinDBQA::GL1pScalersQA(std::string &stringMarkdown, std::string &stringHtml)
0264 {
0265
0266 if (map_crossingshift[runnumber] == -999)
0267 {
0268 stringMarkdown += "\u274C GL1p abort gaps ";
0269 stringHtml += "GL1p Scalers: <font color=\"#ff0000\">BAD</font>; ";
0270 return;
0271 }
0272
0273
0274 if (map_fillnumber[runnumber] == 34897 || map_fillnumber[runnumber] == 34886 || map_fillnumber[runnumber] == 35020)
0275 {
0276 stringMarkdown += "\u2705 Crossing shift ";
0277 stringHtml += "GL1p Scalers: <font color=\"#11cf17\">GOOD</font>; ";
0278 return;
0279 }
0280
0281 int sum_mbdns = 0; int sum_mbdvtx = 0; int sum_zdcns = 0;
0282 int min_sum_mbdns = std::numeric_limits<int>::max();
0283 int min_sum_mbdvtx = std::numeric_limits<int>::max();
0284 int min_sum_zdcns = std::numeric_limits<int>::max();
0285 int min_index_mbdns = -1; int min_index_mbdvtx = -1; int min_index_zdcns = -1;
0286
0287 for (int i = 0; i < 120 + 9; ++i)
0288 {
0289 int ite = i % 120;
0290 sum_mbdns += map_mbdns[runnumber].at(ite);
0291 sum_mbdvtx += map_mbdvtx[runnumber].at(ite);
0292 sum_zdcns += map_zdcns[runnumber].at(ite);
0293
0294 if (i >= 8)
0295 {
0296 if (sum_mbdns < min_sum_mbdns)
0297 {
0298 min_sum_mbdns = sum_mbdns;
0299 min_index_mbdns = (i - 8) % 120;
0300 }
0301 if (sum_mbdvtx < min_sum_mbdvtx)
0302 {
0303 min_sum_mbdvtx = sum_mbdvtx;
0304 min_index_mbdvtx = (i - 8) % 120;
0305 }
0306 if (sum_zdcns < min_sum_zdcns)
0307 {
0308 min_sum_zdcns = sum_zdcns;
0309 min_index_zdcns = (i - 8) % 120;
0310 }
0311 sum_mbdns -= map_mbdns[runnumber].at((i - 8) % 120);
0312 sum_mbdvtx -= map_mbdvtx[runnumber].at((i - 8) % 120);
0313 sum_zdcns -= map_zdcns[runnumber].at((i - 8) % 120);
0314 }
0315 }
0316
0317 if (min_index_mbdns != min_index_mbdvtx || min_index_mbdns != min_index_zdcns)
0318 {
0319 stringMarkdown += "\u274C GL1p abort gaps ";
0320 stringHtml += "GL1p Scalers: <font color=\"#ff0000\">BAD</font>; ";
0321 }
0322 else
0323 {
0324 stringMarkdown += "\u2705 GL1p abort gaps ";
0325 int end_of_ag = (min_index_mbdns+9)%120;
0326 int xingshift_needed = (120-end_of_ag)%120;
0327 stringMarkdown += (map_crossingshift[runnumber] == xingshift_needed) ? "\u2705 Crossing shift " : "\u274C Crossing shift ";
0328 stringHtml += (map_crossingshift[runnumber] == xingshift_needed) ? "GL1p Scalers: <font color=\"#11cf17\">GOOD</font>; " : "GL1p Scalers: <font color=\"#ff0000\">BAD</font>; ";
0329 }
0330 return;
0331 }
0332
0333 void SpinDBQA::LocalPolQA(std::string &stringMarkdown, std::string &stringHtml)
0334 {
0335 if (map_asymbf[runnumber] == 0 && map_asymbb[runnumber] == 0 && map_asymyf[runnumber] == 0
0336 && map_asymyb[runnumber] == 0 && map_phasebf[runnumber] == 0 && map_phasebb[runnumber] == 0
0337 && map_phaseyf[runnumber] == 0 && map_phaseyb[runnumber] == 0)
0338 {
0339 stringMarkdown += "\u274C Local polarimetry exists ";
0340 stringHtml += "Local Polarimetry: <font color=\"#800080\">NOT AVAILABLE</font>; ";
0341 }
0342 else
0343 {
0344 stringMarkdown += "\u2705 Local polarimetry exists ";
0345
0346 locpolbf->SetPoint(locpolbf->GetN(),runnumber,map_asymbf[runnumber]);
0347 locpolbf->SetPointError(locpolbf->GetN()-1,0,map_asymerrbf[runnumber]);
0348 locpolbb->SetPoint(locpolbb->GetN(),runnumber,map_asymbb[runnumber]);
0349 locpolbb->SetPointError(locpolbb->GetN()-1,0,map_asymerrbb[runnumber]);
0350 locpolyf->SetPoint(locpolyf->GetN(),runnumber,map_asymyf[runnumber]);
0351 locpolyf->SetPointError(locpolyf->GetN()-1,0,map_asymerryf[runnumber]);
0352 locpolyb->SetPoint(locpolyb->GetN(),runnumber,map_asymyb[runnumber]);
0353 locpolyb->SetPointError(locpolyb->GetN()-1,0,map_asymerryb[runnumber]);
0354
0355 locpolphasebf->SetPoint(locpolphasebf->GetN(),runnumber,map_phasebf[runnumber]);
0356 locpolphasebf->SetPointError(locpolphasebf->GetN()-1,0,map_phaseerrbf[runnumber]);
0357 locpolphasebb->SetPoint(locpolphasebb->GetN(),runnumber,map_phasebb[runnumber]);
0358 locpolphasebb->SetPointError(locpolphasebb->GetN()-1,0,map_phaseerrbb[runnumber]);
0359 locpolphaseyf->SetPoint(locpolphaseyf->GetN(),runnumber,map_phaseyf[runnumber]);
0360 locpolphaseyf->SetPointError(locpolphaseyf->GetN()-1,0,map_phaseerryf[runnumber]);
0361 locpolphaseyb->SetPoint(locpolphaseyb->GetN(),runnumber,map_phaseyb[runnumber]);
0362 locpolphaseyb->SetPointError(locpolphaseyb->GetN()-1,0,map_phaseerryb[runnumber]);
0363
0364
0365 float bf_distancefromband = map_asymbf[runnumber] > bf_mean ? map_asymbf[runnumber]-(bf_mean+bf_rmse) : (bf_mean-bf_rmse)-map_asymbf[runnumber];
0366 float yf_distancefromband = map_asymyf[runnumber] > yf_mean ? map_asymyf[runnumber]-(yf_mean+yf_rmse) : (yf_mean-yf_rmse)-map_asymyf[runnumber];
0367
0368
0369 float bf_phase_distancefromband = map_phasebf[runnumber] > bf_phase_mean ? map_phasebf[runnumber]-(bf_phase_mean+bf_phase_rmse) : (bf_phase_mean-bf_phase_rmse)-map_phasebf[runnumber];
0370 float yf_phase_distancefromband = map_phaseyf[runnumber] > yf_phase_mean ? map_phaseyf[runnumber]-(yf_phase_mean+yf_phase_rmse) : (yf_phase_mean-yf_phase_rmse)-map_phaseyf[runnumber];
0371
0372
0373 if (bf_distancefromband > map_asymerrbf[runnumber] || yf_distancefromband > map_asymerryf[runnumber]
0374 || bf_phase_distancefromband > map_phaseerrbf[runnumber] || yf_phase_distancefromband > map_phaseerryf[runnumber])
0375 {
0376 stringMarkdown += "\u274C Local Polarimetry ";
0377 stringHtml += "Local Polarimetry: <font color=\"#ff0000\">BAD</font>; ";
0378 }
0379 else
0380 {
0381 stringMarkdown += "\u2705 Local Polarimetry ";
0382 stringHtml += "Local Polarimetry: <font color=\"#11cf17\">GOOD</font>; ";
0383 }
0384 }
0385
0386 }
0387
0388 void SpinDBQA::CrossingAngleQA(std::string &stringMarkdown, std::string &stringHtml) {
0389
0390
0391
0392
0393 if (map_crossanglestd[runnumber] > _crossanglestdthreshold)
0394 {
0395 stringMarkdown += "\u274C Crossing angle variation ";
0396 stringHtml += "Crossing angle variation: <font color=\"#ff0000\">BAD</font>; ";
0397 }
0398 else
0399 {
0400 stringMarkdown += "\u2705 Crossing angle variation ";
0401 stringHtml += "Crossing angle variation: <font color=\"#11cf17\">GOOD</font>; ";
0402 }
0403 }
0404
0405 void SpinDBQA::WriteNewQALevel(int newqalevel)
0406 {
0407 std::cout << "Writing new QA level..." << std::endl;
0408 if (newqalevel < 0)
0409 {
0410 std::cout << "Please select a new qa level > 0 to write to!" << std::endl;
0411 return;
0412 }
0413
0414
0415 PrepareUpdatedBeamPolarizations();
0416 PrepareUpdatedCrossingShifts();
0417 PrepareUpdatedSpinPatterns();
0418
0419
0420 for (const auto &run : runlistvect)
0421 {
0422 int badrunqa = 0;
0423 runnumber = run;
0424
0425
0426
0427
0428 if(spin_in.CheckRunRow(runnumber,newqalevel)==0)
0429 {
0430 spin_in.CreateRunRow(runnumber,newqalevel);
0431 printf("\n\nCreated Row for run %d with qa level %d\n\n",runnumber,newqalevel);
0432 }
0433 spin_cont.SetRunNumber(runnumber);
0434 spin_cont.SetQALevel(newqalevel);
0435
0436
0437
0438
0439 spin_cont.SetFillNumber(map_fillnumber[runnumber]);
0440
0441
0442
0443
0444 if (map_crossingshift[runnumber] == -999)
0445 {
0446 badrunqa = 1;
0447 }
0448 spin_cont.SetCrossingShift(map_crossingshift[runnumber]);
0449
0450
0451
0452
0453
0454 for (int i = 0; i < 120; i++)
0455 {
0456 spin_cont.SetSpinPatternBlue(i,map_bluespin[runnumber].at(i));
0457 }
0458 for (int i = 0; i < 120; i++)
0459 {
0460 spin_cont.SetSpinPatternYellow(i,map_yellspin[runnumber].at(i));
0461 }
0462
0463
0464
0465
0466
0467 if (map_bluepolbyfill.count(map_fillnumber[runnumber]) == 0 || map_yellpolbyfill.count(map_fillnumber[runnumber]) == 0)
0468 {
0469 badrunqa = 1;
0470 spin_cont.SetPolarizationBlue(0, -999., -999.);
0471 spin_cont.SetPolarizationYellow(0, -999., -999.);
0472 }
0473 else
0474 {
0475 spin_cont.SetPolarizationBlue(0, map_bluepolbyfill[map_fillnumber[runnumber]], map_bluepolbyfillerr[map_fillnumber[runnumber]]);
0476 spin_cont.SetPolarizationYellow(0, map_yellpolbyfill[map_fillnumber[runnumber]], map_yellpolbyfillerr[map_fillnumber[runnumber]]);
0477 }
0478
0479
0480
0481
0482
0483 for (int i = 0; i < 120; i++)
0484 {
0485 spin_cont.SetScalerMbdNoCut(i,map_mbdns[runnumber].at(i));
0486 }
0487
0488
0489
0490
0491 for (int i = 0; i < 120; i++)
0492 {
0493 spin_cont.SetScalerMbdVertexCut(i,map_mbdvtx[runnumber].at(i));
0494 }
0495
0496
0497
0498
0499 for (int i = 0; i < 120; i++)
0500 {
0501 spin_cont.SetScalerZdcNoCut(i,map_zdcns[runnumber].at(i));
0502 }
0503
0504
0505
0506
0507 if (map_crossanglestd[runnumber] > _crossanglestdthreshold)
0508 {
0509 badrunqa = 1;
0510 }
0511 spin_cont.SetCrossAngle(map_crossingangle[runnumber]);
0512 spin_cont.SetCrossAngleStd(map_crossanglestd[runnumber]);
0513 spin_cont.SetCrossAngleMin(map_crossanglemin[runnumber]);
0514 spin_cont.SetCrossAngleMax(map_crossanglemax[runnumber]);
0515
0516
0517
0518
0519 float bf_distancefromband = map_asymbf[runnumber] > bf_mean ? map_asymbf[runnumber]-(bf_mean+bf_rmse) : (bf_mean-bf_rmse)-map_asymbf[runnumber];
0520 float yf_distancefromband = map_asymyf[runnumber] > yf_mean ? map_asymyf[runnumber]-(yf_mean+yf_rmse) : (yf_mean-yf_rmse)-map_asymyf[runnumber];
0521 float bf_phase_distancefromband = map_phasebf[runnumber] > bf_phase_mean ? map_phasebf[runnumber]-(bf_phase_mean+bf_phase_rmse) : (bf_phase_mean-bf_phase_rmse)-map_phasebf[runnumber];
0522 float yf_phase_distancefromband = map_phaseyf[runnumber] > yf_phase_mean ? map_phaseyf[runnumber]-(yf_phase_mean+yf_phase_rmse) : (yf_phase_mean-yf_phase_rmse)-map_phaseyf[runnumber];
0523
0524
0525 if (map_asymbf[runnumber] != 0 || map_asymbb[runnumber] != 0 || map_asymyf[runnumber] != 0
0526 || map_asymyb[runnumber] != 0 || map_phasebf[runnumber] != 0 || map_phasebb[runnumber] != 0
0527 || map_phaseyf[runnumber] != 0 || map_phaseyb[runnumber] != 0)
0528 {
0529 if (bf_distancefromband > map_asymerrbf[runnumber] || yf_distancefromband > map_asymerryf[runnumber]
0530 || bf_phase_distancefromband > map_phaseerrbf[runnumber] || yf_phase_distancefromband > map_phaseerryf[runnumber])
0531 {
0532 badrunqa = 1;
0533 }
0534 }
0535
0536
0537
0538 spin_cont.SetAsymBlueForward(map_asymbf[runnumber], map_asymerrbf[runnumber]);
0539 spin_cont.SetAsymBlueBackward(map_asymbb[runnumber], map_asymerrbb[runnumber]);
0540 spin_cont.SetAsymYellowForward(map_asymyf[runnumber], map_asymerryf[runnumber]);
0541 spin_cont.SetAsymYellowBackward(map_asymyb[runnumber], map_asymerryb[runnumber]);
0542 spin_cont.SetPhaseBlueForward(map_phasebf[runnumber], map_phaseerrbf[runnumber]);
0543 spin_cont.SetPhaseBlueBackward(map_phasebb[runnumber], map_phaseerrbb[runnumber]);
0544 spin_cont.SetPhaseYellowForward(map_phaseyf[runnumber], map_phaseerryf[runnumber]);
0545 spin_cont.SetPhaseYellowBackward(map_phaseyb[runnumber], map_phaseerryb[runnumber]);
0546
0547
0548
0549
0550 spin_cont.SetBadRunFlag(badrunqa);
0551
0552
0553
0554 spin_in.UpdateDBContent(spin_cont);
0555 spin_in.SetDefaultQA(spin_cont);
0556
0557
0558
0559 }
0560
0561 }
0562
0563
0564 void SpinDBQA::PrepareUpdatedCrossingShifts()
0565 {
0566 std::ifstream shiftsFile("../updatedcrossingshifts.dat");
0567 if (!shiftsFile.is_open())
0568 {
0569 std::cout << "Error: Could not open updatedcrossingshifts.dat" << std::endl;
0570 return;
0571 }
0572
0573 std::string line;
0574 while (getline(shiftsFile, line))
0575 {
0576 if (line.empty())
0577 {
0578 continue;
0579 }
0580 std::istringstream iss(line);
0581 int RunNumber;
0582 int crossingshift;
0583
0584 if (!(iss >> RunNumber >> crossingshift))
0585 {
0586 std::cout << "Skipping invalid line: " << line << std::endl;
0587 continue;
0588 }
0589
0590 map_crossingshift[RunNumber] = crossingshift;
0591
0592 }
0593 shiftsFile.close();
0594 }
0595
0596 void SpinDBQA::PrepareUpdatedBeamPolarizations()
0597 {
0598 std::ifstream polarizationsFile("../updatedbeampolarizations.dat");
0599 if (!polarizationsFile.is_open())
0600 {
0601 std::cout << "Error: Could not open updatedbeampolarizations.dat" << std::endl;
0602 return;
0603 }
0604
0605 std::string line;
0606 while (getline(polarizationsFile, line))
0607 {
0608 if (line.empty())
0609 {
0610 continue;
0611 }
0612 std::istringstream iss(line);
0613 int FillNumber;
0614 float bluepol;
0615 float bluepolerr;
0616 float yellpol;
0617 float yellpolerr;
0618
0619 if (!(iss >> FillNumber >> bluepol >> bluepolerr >> yellpol >> yellpolerr))
0620 {
0621 std::cout << "Skipping invalid line: " << line << std::endl;
0622 continue;
0623 }
0624
0625 map_bluepolbyfill[FillNumber] = bluepol;
0626 map_bluepolbyfillerr[FillNumber] = bluepolerr;
0627 map_yellpolbyfill[FillNumber] = yellpol;
0628 map_yellpolbyfillerr[FillNumber] = yellpolerr;
0629
0630 }
0631 polarizationsFile.close();
0632 }
0633
0634 void SpinDBQA::PrepareUpdatedSpinPatterns()
0635 {
0636 std::ifstream patternsFile("../updatedspinpatterns.dat");
0637 if (!patternsFile.is_open())
0638 {
0639 std::cout << "Error: Could not open correctedspinpatterns.dat" << std::endl;
0640 return;
0641 }
0642
0643 std::string line;
0644 while (getline(patternsFile, line))
0645 {
0646 if (line.empty())
0647 {
0648 continue;
0649 }
0650 std::istringstream iss(line);
0651 int RunNumber;
0652 std::string s_pattern_blue;
0653 std::string s_pattern_yell;
0654
0655 if (!(iss >> RunNumber >> s_pattern_blue >> s_pattern_yell))
0656 {
0657 std::cout << "Skipping invalid line: " << line << std::endl;
0658 continue;
0659 }
0660
0661 for (int i = 0; i < 120; ++i)
0662 {
0663 if (s_pattern_blue.at(i) == '-')
0664 {
0665 map_bluespin[RunNumber].at(i) = -1;
0666 }
0667 else if (s_pattern_blue.at(i) == '+')
0668 {
0669 map_bluespin[RunNumber].at(i) = 1;
0670 }
0671 else if (s_pattern_blue.at(i) == 'o')
0672 {
0673 map_bluespin[RunNumber].at(i) = 10;
0674 }
0675
0676 if (s_pattern_yell.at(i) == '-')
0677 {
0678 map_yellspin[RunNumber].at(i) = -1;
0679 }
0680 else if (s_pattern_yell.at(i) == '+')
0681 {
0682 map_yellspin[RunNumber].at(i) = 1;
0683 }
0684 else if (s_pattern_yell.at(i) == 'o')
0685 {
0686 map_yellspin[RunNumber].at(i) = 10;
0687 }
0688 }
0689 }
0690 patternsFile.close();
0691 }
0692
0693
0694 void SpinDBQA::WriteRootFile()
0695 {
0696 TFile *outfile = new TFile(_rootfilename.c_str(),"RECREATE");
0697 locpolbf->Write();
0698 locpolbb->Write();
0699 locpolyf->Write();
0700 locpolyb->Write();
0701 locpolphasebf->Write();
0702 locpolphasebb->Write();
0703 locpolphaseyf->Write();
0704 locpolphaseyb->Write();
0705 outfile->Write();
0706 outfile->Close();
0707 }
0708
0709 void SpinDBQA::WriteMarkdown()
0710 {
0711 std::cout << "Writing to Markdown!" << std::endl;
0712
0713 std::ofstream f_md(_markdownfilename);
0714 if (!f_md.is_open())
0715 {
0716 std::cerr << "Error: Could not open the file for writing!" << std::endl;
0717 }
0718 else
0719 {
0720 for (auto& [statements, runs] : map_spindbqa_markdown)
0721 {
0722 std::sort(runs.begin(), runs.end());
0723 f_md << "**" << statements << "**\n\n> ";
0724 for (int run : runs) {
0725 f_md << run << " ";
0726 }
0727 f_md << "\n\n";
0728 }
0729 }
0730 f_md.close();
0731 return;
0732 }
0733
0734 void SpinDBQA::WriteHtml()
0735 {
0736
0737 std::cout << "Writing to HTML!" << std::endl;
0738 if (!std::filesystem::exists(_htmlfilename))
0739 {
0740 std::cerr << "HTML file does not exist! Preparing new HTML." << std::endl;
0741 PrepareHtml();
0742 }
0743
0744
0745 std::ifstream f_html(_htmlfilename);
0746 if (!f_html.is_open())
0747 {
0748 std::cerr << "WriteHtml: Could not open HTML file!" << std::endl;
0749 return;
0750 }
0751
0752 std::string s_html((std::istreambuf_iterator<char>(f_html)), std::istreambuf_iterator<char>());
0753 f_html.close();
0754
0755 std::string tabButtonOld = R"REGEX(<button[^>]*class="tab-button active"[^>]*onclick="openTab\(event,\s*'default'\)"[^>]*>QA Level: Default</button>)REGEX";
0756 std::string tabButtonNew = R"BUTTON(<button class="tab-button active" onclick="openTab(event, 'default')">QA Level: Default</button>)BUTTON";
0757 std::string tabContentOld = R"CONTENT(<div\s+id="default"[^>]*>([\s\S]*?)</div>)CONTENT";
0758 std::string tabContentNew = HtmlContent();
0759
0760 std::string placeholderButton = "<!-- TAB BUTTONS WILL GO HERE -->";
0761 std::string placeholderContent = "<!-- TAB CONTENT WILL GO HERE -->";
0762
0763 if (!b_defaultQA)
0764 {
0765 std::regex patternButtonOld(tabButtonOld);
0766 std::smatch matchResultButtonOld;
0767 std::regex patternContentOld(tabContentOld);
0768 std::smatch matchResultContentOld;
0769 if (std::regex_search(s_html, matchResultButtonOld, patternButtonOld))
0770 {
0771 placeholderButton = matchResultButtonOld[0].str();
0772 }
0773 if (std::regex_search(s_html, matchResultContentOld, patternContentOld))
0774 {
0775 placeholderContent = matchResultContentOld[0].str();
0776 }
0777
0778 std::string s_qa = "qa" + std::to_string(qalevel);
0779 std::string s_title = "QA Level: " + std::to_string(qalevel);
0780 if (qalevel == 0xFFFF){
0781 std::stringstream ss;
0782 ss << std::hex << qalevel;
0783 s_title = "QA Level: 0x" + ss.str();
0784 }
0785 tabButtonNew = std::regex_replace(tabButtonNew, std::regex("default"), s_qa);
0786 tabButtonOld = std::regex_replace(tabButtonOld, std::regex("default"), s_qa);
0787 tabContentOld = std::regex_replace(tabContentOld, std::regex("default"), s_qa);
0788 tabButtonNew = std::regex_replace(tabButtonNew, std::regex("QA Level: Default"), s_title);
0789 tabButtonOld = std::regex_replace(tabButtonOld, std::regex("QA Level: Default"), s_title);
0790 tabButtonNew = std::regex_replace(tabButtonNew, std::regex("tab-button active"), "tab-button");
0791 tabButtonOld = std::regex_replace(tabButtonOld, std::regex("tab-button active"), "tab-button");
0792 tabContentNew = std::regex_replace(tabContentNew, std::regex("tab-content active"), "tab-content");
0793 }
0794
0795
0796 std::regex defaultButtonRegex(tabButtonOld + R"(\s*)");
0797 s_html = std::regex_replace(s_html, defaultButtonRegex, "");
0798 size_t posButton = s_html.find(placeholderButton);
0799 if (posButton != std::string::npos)
0800 {
0801 s_html.insert(posButton + placeholderButton.length(), "\n " + tabButtonNew);
0802 }
0803
0804
0805 std::regex defaultContentRegex(tabContentOld + R"(\s*)");
0806 s_html = std::regex_replace(s_html, defaultContentRegex, "");
0807 size_t posContent = s_html.find(placeholderContent);
0808 if (posContent != std::string::npos)
0809 {
0810 s_html.insert(posContent + placeholderContent.length(), "\n " + tabContentNew);
0811 }
0812
0813
0814 std::ofstream f_html_out(_htmlfilename);
0815 if (!f_html_out.is_open()) {
0816 std::cerr << "Error: Could not open the HTML file for writing!" << std::endl;
0817 return;
0818 }
0819
0820 f_html_out << s_html;
0821 f_html_out.close();
0822
0823 return;
0824 }
0825
0826 std::string SpinDBQA::HtmlContent()
0827 {
0828 std::ostringstream stream_html;
0829
0830 size_t totalRuns = 0;
0831 for (const auto &pair : map_spindbqa_html)
0832 {
0833 totalRuns += pair.second.size();
0834 }
0835
0836 stream_html << R"(<div id="default" class="tab-content active">)" << "\n"
0837 << " <table style=\"text-align: center;\">\n"
0838 << " <tr>\n"
0839 << " <th style=\"width: 1500px;\">Run Status</th>\n"
0840 << " <th style=\"width: 50px;\">Number of Runs</th>\n"
0841 << " <th style=\"width: 50px;\">Fraction</th>\n"
0842 << " </tr>\n"
0843 << " <tr>\n"
0844 << " <td>" << "Total number of runs" << "</td>\n"
0845 << " <td>" << totalRuns << "</td>\n"
0846 << " <td>" << "-" << "</td>\n"
0847 << " </tr>\n";
0848
0849 for (auto& [statement, runs] : map_spindbqa_html)
0850 {
0851 size_t count = runs.size();
0852
0853 double fraction = 0.0;
0854 if (totalRuns > 0)
0855 {
0856 fraction = (static_cast<double>(count) / static_cast<double>(totalRuns)) * 100.0;
0857 }
0858
0859 std::ostringstream fractionStr;
0860 fractionStr << std::fixed << std::setprecision(2) << fraction << "%";
0861
0862 stream_html << " <tr>\n"
0863 << " <td>" << statement << "</td>\n"
0864 << " <td>" << count << "</td>\n"
0865 << " <td>" << fractionStr.str() << "</td>\n"
0866 << " </tr>\n";
0867
0868 }
0869 stream_html << " </table>\n";
0870
0871 for (auto& [statement, runs] : map_spindbqa_html)
0872 {
0873 std::sort(runs.begin(), runs.end());
0874 stream_html << "<strong>" << statement << "</strong><br>\n";
0875 for (int run : runs) {
0876 stream_html << run << " ";
0877 }
0878 stream_html << "<br><br>\n";
0879 }
0880
0881 stream_html << "</div>";
0882
0883 std::string s_stream_html = stream_html.str();
0884 std::string s_qa = "qa" + std::to_string(qalevel);
0885 if (!b_defaultQA)
0886 {
0887 s_stream_html = std::regex_replace(s_stream_html, std::regex("default"), s_qa);
0888 s_stream_html = std::regex_replace(s_stream_html, std::regex("tab-content active"), "tab-content");
0889 }
0890
0891 return s_stream_html;
0892
0893 }
0894
0895 void SpinDBQA::PrepareHtml()
0896 {
0897 std::ofstream f_html(_htmlfilename);
0898 if (!f_html.is_open())
0899 {
0900 std::cerr << "PrepareHtml: Could not open HTML file!" << std::endl;
0901 }
0902 else
0903 {
0904 f_html << R"(<!DOCTYPE html>
0905 <html lang="en">
0906 <head>
0907 <meta charset="UTF-8">
0908 <meta name="viewport" content="width=device-width, initial-scale=1.0">
0909 <title>Spin QA Run Summary</title>
0910 <style>
0911 body {
0912 font-family: 'Arial', sans-serif;
0913 margin: 0;
0914 padding: 20px;
0915 background-color: #f4f7f9;
0916 color: #333;
0917 }
0918 h2 {
0919 text-align: center;
0920 font-size: 2em;
0921 color: #4D89C6;
0922 margin-bottom: 20px;
0923 }
0924
0925 .top-right-image {
0926 position: absolute;
0927 top: 10px;
0928 right: 10px;
0929 }
0930
0931 .tabs {
0932 display: flex;
0933 justify-content: center;
0934 margin-bottom: 20px;
0935 }
0936 .tab-button {
0937 background-color: #ddd;
0938 border: none;
0939 padding: 10px 20px;
0940 cursor: pointer;
0941 font-size: 1em;
0942 transition: background-color 0.3s ease;
0943 }
0944 .tab-button.active {
0945 background-color: #4D89C6;
0946 color: white;
0947 }
0948 .tab-button:hover {
0949 background-color: #bbb;
0950 }
0951 .tab-content {
0952 display: none;
0953 padding: 20px;
0954 background-color: white;
0955 box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
0956 }
0957 .tab-content.active {
0958 display: block;
0959 }
0960 .run-list {
0961 font-size: 1em;
0962 margin-bottom: 10px;
0963 padding: 10px;
0964 border: 1px solid #ddd;
0965 background-color: #f9f9f9;
0966 }
0967 </style>
0968 </head>
0969 <body>
0970
0971 <img src="sphenix-logo-white-bg.png" width="200" alt="Logo" class="top-right-image">
0972
0973 <h2>Spin QA Run Summary</h2>
0974
0975 <!-- Placeholder for the tab buttons -->
0976 <div class="tabs">
0977 <!-- TAB BUTTONS WILL GO HERE -->
0978 </div>
0979
0980 <!-- Placeholder for the tab content -->
0981 <style>
0982 table {
0983 border-collapse: collapse;
0984 text-align: center;
0985 }
0986 th, td {
0987 padding: 8px;
0988 }
0989 tr {
0990 border-bottom: 1px solid black;
0991 }
0992 </style>
0993 <!-- TAB CONTENT WILL GO HERE -->
0994
0995 <script>
0996 function openTab(event, tabName) {
0997 var tabContent = document.getElementsByClassName("tab-content");
0998 for (var i = 0; i < tabContent.length; i++) {
0999 tabContent[i].style.display = "none";
1000 tabContent[i].classList.remove("active");
1001 }
1002 var tabButtons = document.getElementsByClassName("tab-button");
1003 for (var i = 0; i < tabButtons.length; i++) {
1004 tabButtons[i].classList.remove("active");
1005 }
1006 document.getElementById(tabName).style.display = "block";
1007 document.getElementById(tabName).classList.add("active");
1008 event.currentTarget.classList.add("active");
1009 }
1010 </script>
1011
1012 </body>
1013 </html>)";
1014
1015 }
1016 f_html.close();
1017 return;
1018 }