3 * @author Christian Holm Christensen <cholm@nbi.dk>
4 * @date Thu Nov 17 12:08:04 2011
6 * @brief Class to plot QA trends
8 * @ingroup pwglf_forward_qa_scripts
15 # include <TGraphErrors.h>
16 # include <TGraphAsymmErrors.h>
17 # include <TMultiGraph.h>
30 class TGraphAsymmErrors;
41 * Class to plot QA trends
43 * @ingroup pwglf_forward_qa_scripts
45 struct QAPlotter : public QABase
50 struct Ring : public QARing
58 Ring(UShort_t d, Char_t r)
71 fGChi2 = new TGraphAsymmErrors;
72 fGC = new TGraphAsymmErrors;
73 fGDelta = new TGraphAsymmErrors;
74 fGXi = new TGraphAsymmErrors;
75 fGSigma = new TGraphAsymmErrors;
77 fGSingles = new TGraph;
80 fGOccupancy = new TGraphAsymmErrors;
82 SetAtt(fGChi2, "chi2", "#LT#chi^{2}/#nu#GT");
83 SetAtt(fGC, "c", "Constant");
84 SetAtt(fGDelta, "delta", "#LT#Delta_{p}#GT");
85 SetAtt(fGXi, "xi", "#LT#xi#GT");
86 SetAtt(fGSigma, "sigma", "#LT#sigma#GT");
87 SetAtt(fGLow, "low", "# of low statistics bins");
88 SetAtt(fGSingles, "singles", "Fraction of single hits");
89 SetAtt(fGLoss, "loss", "Data lossed due to cuts");
90 SetAtt(fGOccupancy, "occupancy","#LTOccupancy#GT");
91 SetAtt(fGBeta, "beta", "Correlation of methods");
95 * Static member function to get the ring color
97 * @param d Detector number
98 * @param r Ring identifer
102 static Color_t RingColor(UShort_t d, Char_t r)
104 return ((d == 1 ? kRed : (d == 2 ? kGreen : kBlue))
105 + ((r == 'I' || r == 'i') ? 2 : -3));
108 * Set graph attributes
111 * @param name Name of graph
113 void SetAtt(TGraph* g, const char* name, const char* /*title=""*/)
115 Color_t c = RingColor(fD, fR);
116 g->SetName(Form("FMD%d%c_%s", fD, fR, name));
117 // g->SetTitle(Form("FMD%d%c %s", fD, fR,
118 // !title || title[0] == '\0' ? name : title));
119 Int_t marker = 20+(fD-1) + (fR == 'I' ? 0 : 4);
120 g->SetTitle(Form("FMD%d%c", fD, fR));
123 g->SetMarkerColor(c);
124 g->SetMarkerStyle(marker);
127 case 20: g->SetMarkerSize(1.2); break;
128 case 21: g->SetMarkerSize(1.2); break;
129 case 22: g->SetMarkerSize(1.3); break;
130 case 26: g->SetMarkerSize(1.1); break;
134 * Update a graph from a RingQuantity
136 * @param g Graph to update
138 * @param runNo Run number
140 void UpdateGraph(TGraphAsymmErrors* g, RingQuantity& q,
141 UInt_t runNo, UInt_t /* n */)
144 Double_t el = y-q.min;
145 Double_t eh = q.max-y;
146 if (TMath::Abs(y) < 1e-6) return;
148 g->SetPoint(i, runNo, y);
149 g->SetPointError(i, 0, 0, el, eh);
154 * @param n Entry number (not used)
155 * @param runNo Run number
157 * @return true on success
159 Bool_t Update(UInt_t n, UInt_t runNo)
161 UpdateGraph(fGChi2, *fChi2, runNo, n);
162 UpdateGraph(fGC, *fC, runNo, n);
163 UpdateGraph(fGDelta, *fDelta, runNo, n);
164 UpdateGraph(fGXi, *fXi, runNo, n);
165 UpdateGraph(fGSigma, *fSigma, runNo, n);
166 UpdateGraph(fGOccupancy, *fOccupancy, runNo, n);
168 fGLow->SetPoint(n, runNo, fFitStatus->nLow);
170 if (fMerge->one > 1e-6)
171 fGSingles->SetPoint(fGSingles->GetN(), runNo, fMerge->one);
172 if (fCorrelation->beta > 1e-6)
173 fGBeta->SetPoint(fGBeta->GetN(), runNo, fCorrelation->beta);
174 if (-fDataLoss->full > 1e-6)
175 fGLoss->SetPoint(fGLoss->GetN(), runNo, -fDataLoss->full);
178 TGraphAsymmErrors* fGChi2; // Graph of ELoss reduced chi-square
179 TGraphAsymmErrors* fGC; // Graph of ELoss constant
180 TGraphAsymmErrors* fGDelta; // Graph of ELoss MPV
181 TGraphAsymmErrors* fGXi; // Graph of ELoss Landau width
182 TGraphAsymmErrors* fGSigma; // Graph of ELoss Gaus width
183 TGraph* fGLow; // Graph of bins with low statistics
184 TGraph* fGSingles; // Graph of fraction of singles
185 TGraph* fGLoss; // Graph of 'lost' data
186 TGraph* fGBeta; // Graph of Poisson vs ELoss correlation
187 TGraphAsymmErrors* fGOccupancy;// Graph of mean occupancy
197 fFMD1i = new Ring(1, 'I');
198 fFMD2i = new Ring(2, 'I');
199 fFMD2o = new Ring(2, 'O');
200 fFMD3i = new Ring(3, 'I');
201 fFMD3o = new Ring(3, 'O');
202 fNAccepted = new TGraph;
203 fNAccepted->SetName("nAccepted");
204 fNAccepted->SetMarkerStyle(20);
205 fNAccepted->SetLineWidth(2);
207 fVz = new TGraphErrors;
209 fVz->SetMarkerStyle(20);
210 fVz->SetLineWidth(2);
213 * Add a file to be processed
215 * @param filename Name of file
217 void AddFile(const char* filename)
219 fFiles.Add(new TObjString(filename));
224 * @param read If true, read from file
226 * @return True on success
228 Bool_t MakeTree(bool read)
230 if (fFiles.GetEntriesFast() <= 0) return QABase::MakeTree(read);
232 TChain* chain = new TChain("T", "T");
233 if (!chain->AddFileInfoList(&fFiles)) return false;
247 Error("Run", "No input tree");
254 UInt_t nEntries = fTree->GetEntries();
257 for (UInt_t i = 0; i < nEntries; i++) {
260 UInt_t run = fGlobal->runNo;
261 UInt_t nev = fGlobal->nAccepted;
263 fFirst = TMath::Min(run, fFirst);
264 fLast = TMath::Max(run, fLast);
267 Info("Run", "Got run %d with %d accepted events", run, nev);
268 fNAccepted->SetPoint(i, run, nev);
269 fVz->SetPoint(i, run, fGlobal->meanVz);
270 fVz->SetPointError(i, 0, fGlobal->sigmaVz);
272 if (nev <= 100) continue;
273 static_cast<Ring*>(fFMD1i)->Update(j, run);
274 static_cast<Ring*>(fFMD2i)->Update(j, run);
275 static_cast<Ring*>(fFMD2o)->Update(j, run);
276 static_cast<Ring*>(fFMD3i)->Update(j, run);
277 static_cast<Ring*>(fFMD3o)->Update(j, run);
290 fTeXName = Form("trend_%09d_%09d", fFirst, fLast);
291 MakeCanvas(Form("QA trends for runs %d --- %d", fFirst, fLast));
293 CanvasTitle("# of accepted events");
294 fNAccepted->Draw("apl");
295 PutCanvasTitle("# of accepted events");
296 AddRuns(fNAccepted->GetHistogram(), "# of accepted events");
298 TLine* l = new TLine(fFirst, 100, fLast, 100);
299 l->SetLineColor(kRed+2);
302 PrintCanvas("nAccepted");
304 CanvasTitle("#LTv_{z}#GT");
306 PutCanvasTitle("Mean z coordinate of interaction point");
307 AddRuns(fVz->GetHistogram(), "#LTv_{z}#GT");
310 TMultiGraph* chi2 = new TMultiGraph;
311 TMultiGraph* c = new TMultiGraph;
312 TMultiGraph* delta = new TMultiGraph;
313 TMultiGraph* xi = new TMultiGraph;
314 TMultiGraph* sigma = new TMultiGraph;
315 TMultiGraph* low = new TMultiGraph;
316 TMultiGraph* singles = new TMultiGraph;
317 TMultiGraph* loss = new TMultiGraph;
318 TMultiGraph* occ = new TMultiGraph;
319 TMultiGraph* beta = new TMultiGraph;
320 chi2 ->SetName("chi2");
322 delta ->SetName("delta");
324 sigma ->SetName("sigma");
325 low ->SetName("low");
326 singles ->SetName("singles");
327 loss ->SetName("loss");
328 beta ->SetName("beta");
329 occ ->SetName("occupancy");
332 AddToMulti(fFMD1i,chi2, c, delta, xi, sigma, low, singles, loss, beta, occ);
333 AddToMulti(fFMD2i,chi2, c, delta, xi, sigma, low, singles, loss, beta, occ);
334 AddToMulti(fFMD2o,chi2, c, delta, xi, sigma, low, singles, loss, beta, occ);
335 AddToMulti(fFMD3i,chi2, c, delta, xi, sigma, low, singles, loss, beta, occ);
336 AddToMulti(fFMD3o,chi2, c, delta, xi, sigma, low, singles, loss, beta, occ);
338 PlotMulti(chi2, "#LT#chi^{2}/#nu#GT from #Delta fits", true);
339 PlotMulti(c, "#LTc#GT from #Delta fits");
340 PlotMulti(delta, "#LT#Delta_{p}#GT from #Delta fits");
341 PlotMulti(xi, "#LT#xi#GT from #Delta fits");
342 PlotMulti(sigma, "#LT#sigma#GT from #Delta fits");
343 PlotMulti(low, "Bins with too low statistics");
344 PlotMulti(singles, "Fraction of single hits");
345 PlotMulti(loss, "% of hits 'lost' due to merging+cuts");
346 PlotMulti(occ, "#LTOccupancy#GT [%]", true);
347 PlotMulti(beta, "Correlation of methods");
361 Close(false); // Do not delete PNGs
364 * Add graphs from a ring to the multi graphs
367 * @param chi2 ELoss reduced chi-square
368 * @param c ELoss constant
369 * @param delta ELoss MPV
370 * @param xi ELoss Landau width
371 * @param sigma ELoss Gaus width
372 * @param low bins with low statistics
373 * @param singles fraction of singles
374 * @param loss 'lost' data
375 * @param beta Poisson vs ELoss correlation
376 * @param occupancy mean occupancy
378 void AddToMulti(QARing* qr,
385 TMultiGraph* singles,
388 TMultiGraph* occupancy)
390 Ring* r = static_cast<Ring*>(qr);
391 chi2 ->Add(r->fGChi2);
393 delta ->Add(r->fGDelta);
395 sigma ->Add(r->fGSigma);
397 singles ->Add(r->fGSingles);
398 loss ->Add(r->fGLoss);
399 occupancy ->Add(r->fGOccupancy);
400 beta ->Add(r->fGBeta);
405 * @param mg Multi graph
407 * @param logy If true, make @f$\log@f$ scale
409 void PlotMulti(TMultiGraph* mg, const char* title, Bool_t logy=false)
412 // fCanvas->SetBottomMargin(.15);
413 fCanvas->SetLeftMargin(.08);
414 fCanvas->SetTopMargin(.1);
415 fCanvas->SetLogy(logy);
416 // fCanvas->SetRightMargin(.2);
419 TH1* h = mg->GetHistogram();
420 Double_t max = h->GetMaximum();
421 Double_t min = h->GetMinimum();
422 if (h->GetMinimum() == 0) {
423 min = min - .1*(max-min);
426 Int_t x1 = h->GetXaxis()->GetXmin();
427 Int_t x2 = h->GetXaxis()->GetXmax();
429 TLegend* l = new TLegend(.1, .91, .97, .95);
435 TIter next(mg->GetListOfGraphs());
436 mg->GetListOfGraphs();
439 // Get the runs we have here
440 TArrayI runs(fRuns.GetSize());
443 while ((g = static_cast<TGraph*>(next()))) {
444 l->AddEntry(g, g->GetTitle(), "lp");
445 Double_t* xs = g->GetX();
447 for (Int_t i = 0; i < n; i++) {
448 if (FindRun(runs, Int_t(xs[i])) >= 0) continue;
449 runs.SetAt(xs[i], j++);
451 Double_t ymean = g->GetMean(2);
452 Double_t xh = x2 - .03 * Double_t(x2-x1);
453 TLine* lm = new TLine(x1, ymean, xh, ymean);
454 lm->SetLineColor(g->GetLineColor());
458 TLatex* al = new TLatex(xh, ymean, g->GetTitle());
459 al->SetTextColor(g->GetLineColor());
461 al->SetTextSize(.02);
462 al->SetTextAlign(12);
467 AddRuns(h, title, &runs);
469 PrintCanvas(mg->GetName());
474 * @param runs List of runs
475 * @param run Run to find
477 * @return Index of run in run list
479 Int_t FindRun(const TArrayI& runs, Int_t run)
481 std::sort(&(runs.fArray[0]), &(runs.fArray[runs.GetSize()]));
482 Int_t idx = TMath::BinarySearch(runs.GetSize(), runs.fArray, run);
483 if (idx >= runs.GetSize() || idx < 0 || runs[idx] != run) return -1;
487 * Add run labels at appropriate places on the plot
489 * @param h Frame histogram
491 * @param runs List of runs, if any
493 void AddRuns(TH1* h, const char* title, TArrayI* runs=0)
495 h->GetXaxis()->SetNoExponent();
496 // h->GetXaxis()->SetTitleOffset(1);
498 h->SetXTitle("Run #");
500 Int_t r1 = h->GetXaxis()->GetXmin();
501 Int_t r2 = h->GetXaxis()->GetXmax();
503 Double_t tx = .045; // (r2 - r1) / 18;
504 Double_t wx = 1 - fCanvas->GetLeftMargin() - fCanvas->GetRightMargin();
506 Double_t y = fCanvas->GetBottomMargin()+dy;
507 for (Int_t i = 0; i < fRuns.GetSize(); i++) {
509 Double_t x = fCanvas->GetLeftMargin() + wx*Double_t(r-r1)/(r2-r1);
511 // Skip runs out of range
512 if (r < r1 || r > r2) continue;
514 // Skip runs not in the graphs
516 if (FindRun(*runs, r) < 0) {
522 if (TMath::Abs(x - lx) < tx) y += dy;
523 else y = fCanvas->GetBottomMargin() + dy;
526 // Info(h->GetName(), "%6d (x,y)=(%12f,%12f) |lx-x|=|%f-x|=%f",
527 // r, x, y, lx, TMath::Abs(lx-x));
530 Double_t* xa = fNAccepted->GetX();
531 Int_t na = fNAccepted->GetN();
532 Int_t idx = TMath::BinarySearch(na, xa, Double_t(r));
533 Color_t color = kBlue+3;
534 if (idx >= 0 && idx < na && r == xa[idx] &&
535 fNAccepted->GetY()[idx] < 10000)
538 TLatex* ll = new TLatex(x, y, Form("%d", r));
540 ll->SetTextAlign(21);
541 ll->SetTextSize(0.02);
542 ll->SetTextColor(color);
544 // ll->SetTextAngle(90);
546 TLine* tl = new TLine(x, y, x, 1-fCanvas->GetTopMargin());
547 tl->SetBit(TLine::kLineNDC);
549 tl->SetLineColor(color);
554 * Output list of runs
556 * @param o Output stream
558 void WriteRuns(std::ostream& o)
560 o << "<div class='jobid'><!--JOBID--></div>\n"
561 << "<div class='runs'>\n"
563 for (Int_t i = 0; i < fRuns.GetSize(); i++) {
564 o << "<a href='qa_" << Form("%09d", fRuns[i]) << ".html'>"
565 << fRuns[i] << "</a> " << std::flush;
568 << "</div>" << std::endl;
577 QABase::WriteFooter();
580 * Write out image footer
582 * @param o Output stream
583 * @param pngName Name of the PNG file
585 void WriteImageFooter(std::ostream& o, const char* pngName)
588 QABase::WriteImageFooter(o, pngName);
590 TGraph* fNAccepted; // Graph of number of accepted events
591 TGraphErrors* fVz; // Graph of mean vertex
592 UInt_t fFirst; // First run
593 UInt_t fLast; // Last run
594 TArrayI fRuns; // Seen runs