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