3 * @author Christian Holm Christensen <cholm@nbi.dk>
4 * @date Thu Nov 17 12:28:17 2011
6 * @brief Class to make the QA trending tree
8 * @ingroup pwglf_forward_qa_scripts
23 # include <TLegendEntry.h>
25 # include <TLinearFitter.h>
30 # include "QAStructs.h"
51 // --- A quantity ----------------------------------------------------
53 * Class to make the QA trending tree
55 * @ingroup pwglf_forward_qa_scripts
57 struct QATrender : public QABase
60 /******************************************************************/
65 struct Ring : public QARing
73 Ring(UShort_t d, Char_t r) : QARing(d, r) {}
75 * Get the detector specific list
77 * @param parent Parent list
79 * @return Found list or null
81 TList* GetDetectorList(const TList* parent) const
83 TObject* o = QATrender::GetSubList(parent, Form("FMD%d%c", fD, fR));
84 return static_cast<TList*>(o);
87 * Calculate numbers from read histograms
89 * @param parent Parent list
90 * @param name Name of histogram
91 * @param q Qauntity to store in
93 * @return true on success
95 Bool_t ExtractYQuantity(const TList* parent, const char* name,
103 TH1* h = QATrender::GetHistogram(parent, name);
105 // Warning("ExtractYQuantity", "Histogram %s not found", name);
113 for (Int_t i = 1; i <= h->GetNbinsX(); i++) {
114 Double_t y = h->GetBinContent(i);
115 Double_t e = h->GetBinError(i);
117 if (y <= 1e-12) continue;
118 if (e != 0) w = 1 / (e*e);
121 min = TMath::Min(min, y);
122 max = TMath::Max(max, y);
123 // Info("", " %s %3d: y=%f,\t e=%f,\t w=%f", name, i, y, e, w);
128 // Warning("ExtractYQuantity",
129 // "Sum of weights for %s too small %g<1e-6",
133 q->mean = sum / sumw;
134 q->var = TMath::Sqrt(1/sumw);
135 // Info(name, " mean=%f, var=%f", q->mean, q->var);
139 * Process data from the energy loss fits
141 * @param parent Parent list
143 * @return true on success
145 Bool_t ProcessEnergyLoss(const TList* parent)
147 TList* det = GetDetectorList(parent);
148 if (!det) return false;
150 TList* res = QATrender::GetSubList(det, "FitResults");
151 if (!res) return false;
153 ExtractYQuantity(res, Form("FMD%d%c_chi2", fD, fR), fChi2);
154 ExtractYQuantity(res, Form("FMD%d%c_c", fD, fR), fC);
155 ExtractYQuantity(res, Form("FMD%d%c_delta", fD, fR), fDelta);
156 ExtractYQuantity(res, Form("FMD%d%c_xi", fD, fR), fXi);
157 ExtractYQuantity(res, Form("FMD%d%c_sigma", fD, fR), fSigma);
159 TH1* status = QATrender::GetHistogram(res, "status");
160 if (!status) return false;
161 fFitStatus->nLow = UShort_t(status->GetBinContent(3));
162 fFitStatus->nCandidates = UShort_t(status->GetBinContent(4));
163 fFitStatus->nFitted = UShort_t(status->GetBinContent(5));
168 * Process data on neighbors
170 * @param parent Parent list
171 * @param p (optional) Pad to draw
173 * @return true on success
175 Bool_t ProcessNeighbors(const TList* parent, TVirtualPad* p)
177 if (!p) return true; // Case of no drawing
179 TList* det = GetDetectorList(parent);
180 if (!det) return false;
182 TH1* before = QATrender::GetHistogram(det, "neighborsBefore");
183 TH1* after = QATrender::GetHistogram(det, "neighborsAfter");
184 if (!before || !after) return false;
186 if (before->GetMaximum() > 0) p->SetLogz();
188 if (fD == 3) p->SetRightMargin(0.15);
190 before->SetTitle(Form("FMD%d%c",fD,fR));
191 before->Draw("colz");
192 after->Draw("same box");
194 before->GetXaxis()->SetRangeUser(-.5, 2);
195 before->GetYaxis()->SetRangeUser(-.5, 2);
197 TLatex* ltx = new TLatex(p->GetLeftMargin()+.01,
198 p->GetBottomMargin()+.01,
201 ltx->SetTextSize(.07);
207 * Process data on single, double, and triple hits
209 * @param parent Parent list
210 * @param p (optional) Pad to draw
212 * @return true on success
214 Bool_t Process123(const TList* parent, TVirtualPad* p)
216 TList* det = GetDetectorList(parent);
217 if (!det) return false;
223 TH1* one = QATrender::GetHistogram(det, "singleEloss");
224 TH1* two = QATrender::GetHistogram(det, "doubleEloss");
225 TH1* three = QATrender::GetHistogram(det, "tripleEloss");
226 if (!one || !two || !three) return false;
228 Int_t nOne = one->GetEntries();
229 Int_t nTwo = two->GetEntries();
230 Int_t nThree = three->GetEntries();
231 Int_t total = nOne + nTwo + nThree;
233 fMerge->one = Double_t(nOne) / total;
234 fMerge->two = Double_t(nTwo) / total;
235 fMerge->three = Double_t(nThree) / total;
241 one->SetTitle(Form("FMD%d%c", fD, fR));
242 one->GetXaxis()->SetRangeUser(0, 8);
244 if (one->GetMaximum() > 0) p->SetLogy();
246 if ((p->GetNumber() % 3) != 1) p->SetLeftMargin(.1);
248 one->SetLineStyle(1);
249 two->SetLineStyle(2);
250 three->SetLineStyle(3);
256 // Double_t ts = 0.03;
257 Double_t y = 1-p->GetTopMargin()-1.2*gStyle->GetTitleH(); // +ts;
258 Double_t x = p->GetLeftMargin() + .25;
259 TLatex* ltx = new TLatex(x, y, "Fraction of ...");
261 ltx->SetTextColor(kBlue+3);
262 ltx->SetTextAlign(13);
263 // ltx->SetTextAlign(33);
264 ltx->SetTextSize(.07);
268 DrawText(ltx, x, y, "Singles:", Form("%5.2f%%", fMerge->one * 100));
269 DrawText(ltx, x, y, "Doubles:", Form("%5.2f%%", fMerge->two * 100));
270 DrawText(ltx, x, y, "Triples:", Form("%5.2f%%", fMerge->three * 100));
277 * Process energy loss distributions
279 * @param p1 First parent list (sharing filter)
280 * @param p2 Second parent list (density calculator)
281 * @param p (optional) Pad to draw
283 * @return true on success
285 Bool_t ProcessELoss(TList* p1, TList* p2, TVirtualPad* p)
287 TList* det1 = GetDetectorList(p1);
288 if (!det1) return false;
290 TList* det2 = GetDetectorList(p2);
291 if (!det2) return false;
293 TH1* before = QATrender::GetHistogram(det1, "esdEloss");
294 TH1* after = QATrender::GetHistogram(det1, "anaEloss");
295 TH1* presented = QATrender::GetHistogram(det2, "eloss");
296 TH1* used = QATrender::GetHistogram(det2, "elossUsed");
298 if (!before || !after || !presented || !used) return false;
300 const Double_t lowCut = 0.15;
302 Int_t low = before->GetXaxis()->FindBin(lowCut);
303 Int_t ib = Int_t(before->Integral(low,before->GetNbinsX()));
304 Int_t ia = Int_t(after->Integral(low,after->GetNbinsX()));
305 Int_t ip = Int_t(presented->Integral(low,presented->GetNbinsX()));
306 Int_t iu = Int_t(used->Integral(low,used->GetNbinsX()));
308 Double_t dba = ib > 0 ? (100.*(ia-ib))/ib : 0;
309 Double_t dbp = ib > 0 ? (100.*(ip-ib))/ib : 0;
310 Double_t dbu = ib > 0 ? (100.*(iu-ib))/ib : 0;
311 Double_t dap = ia > 0 ? (100.*(ip-ia))/ia : 0;
312 Double_t dau = ia > 0 ? (100.*(iu-ia))/ia : 0;
313 Double_t dpu = ip > 0 ? (100.*(iu-ip))/ip : 0;
315 fDataLoss->merge = dba;
316 fDataLoss->density = dau;
317 fDataLoss->full = dbu;
321 if (before->GetMaximum() > 0) p->SetLogy();
323 before->SetTitle(Form("FMD%d%c",fD,fR));
325 before->SetLineStyle(1);
326 after->SetLineStyle(2);
327 used->SetLineStyle(3);
331 presented->Draw("same");
335 Double_t x = p->GetLeftMargin() + .25;
336 Double_t y = 1-p->GetTopMargin()-gStyle->GetTitleH()+ts;
337 TLatex* ltx = new TLatex(x, y, Form("FMD%d%c", fD, fR));
339 ltx->SetTextAlign(13);
340 ltx->SetTextSize(ts);
341 ltx->SetTextColor(kBlue+3);
343 // ltx->SetTextSize(.05);
344 TString inte(Form("Integral [%4.2f,#infty]", lowCut));
345 DrawText(ltx, x, y, Form("%s before:", inte.Data()), Form("%9d", ib));
346 DrawText(ltx, x, y, Form("%s after:", inte.Data()), Form("%9d", ia));
347 DrawText(ltx, x, y, Form("%s input:", inte.Data()), Form("%9d", ip));
348 DrawText(ltx, x, y, Form("%s user:", inte.Data()), Form("%9d", iu));
349 TLine* l = new TLine;
351 l->DrawLineNDC(x, y-0.9*ts, 1-p->GetRightMargin()-0.01, y-0.9*ts);
352 if (ib != 0 && ia != 0) {
353 DrawText(ltx, x, y, "Change (merging)", Form("%5.1f%%", dba));
354 DrawText(ltx, x, y, "Change (input)", Form("%5.1f%% (%5.1f%%)",
356 DrawText(ltx, x, y, "Change (use)", Form("%5.1f%% (%5.1f%%)",
359 before->GetXaxis()->SetRangeUser(0, 4);
365 * Process occupancy information
367 * @param parent Parent list
368 * @param p (optional) Pad to draw
370 * @return true on success
372 Bool_t ProcessOccupancy(const TList* parent, TVirtualPad* p)
374 TList* det = GetDetectorList(parent);
375 if (!det) return false;
377 TH1* occ = QATrender::GetHistogram(det, "occupancy");
378 if (!occ) return false;
380 fOccupancy->mean = occ->GetMean();
381 fOccupancy->var = occ->GetRMS();
385 for (Int_t i = occ->GetNbinsX(); i >= 1; i--) {
386 Double_t y = occ->GetBinContent(i);
387 if (y < 1e-6) continue;
388 fOccupancy->max = occ->GetXaxis()->GetBinUpEdge(i);
395 if (occ->GetMaximum() > 0) p->SetLogy();
397 p->SetRightMargin(0.01);
399 occ->SetTitle(Form("FMD%d%c", fD, fR));
402 // Double_t ts = 0.03;
403 Double_t y = 1-p->GetTopMargin()-1.2*gStyle->GetTitleH(); // +ts;
404 Double_t x = p->GetLeftMargin() + .25;
405 TLatex* ltx = new TLatex(x, y, "");
407 ltx->SetTextColor(kBlue+3);
408 ltx->SetTextAlign(13);
409 // ltx->SetTextAlign(33);
410 ltx->SetTextSize(.07);
414 DrawText(ltx, x, y, "Mean:", Form("%5.2f%%", fOccupancy->mean));
415 DrawText(ltx, x, y, "Variance:", Form("%5.2f%%", fOccupancy->var));
416 DrawText(ltx, x, y, "Max:", Form("%5.2f%%", fOccupancy->max));
423 * Process method correlations
425 * @param parent Parent list
426 * @param p (optional) Pad to draw
428 * @return true on success
430 Bool_t ProcessCorrelation(const TList* parent, TVirtualPad* p)
432 TList* det = GetDetectorList(parent);
433 if (!det) return false;
435 TH1* co = QATrender::GetHistogram(det, "elossVsPoisson");
436 if (!co) return false;
437 TH2* corr = static_cast<TH2*>(co);
439 fCorrelation->alpha = 0;
440 fCorrelation->beta = 0;
442 fCorrelation->ea = 0;
444 fCorrelation->eb = 0;
445 fCorrelation->chi2 = 0;
448 Double_t xmax = corr->GetXaxis()->GetXmax();
450 if (corr->GetEntries() > 0) {
451 // Calculate the linear regression
452 // Double_t dx = (xmax-xmin);
453 // Double_t rxy = corr->GetCorrelationFactor();
454 Double_t sx = corr->GetRMS(1);
455 Double_t sy = corr->GetRMS(2);
456 Double_t sx2 = sx*sx;
457 Double_t sy2 = sy*sy;
458 Double_t cxy = corr->GetCovariance();
459 Double_t mx = corr->GetMean(1);
460 Double_t my = corr->GetMean(2);
462 if (TMath::Abs(cxy) > 1e-6) {
463 fCorrelation->beta = ((sy2 - delta*sx2 +
464 TMath::Sqrt(TMath::Power(sy2-delta*sx2,2) +
465 4*delta*cxy*cxy)) / 2 / cxy);
466 fCorrelation->alpha = my - fCorrelation->beta * mx;
471 TLinearFitter* fitter = new TLinearFitter(1);
472 fitter->SetFormula("1 ++ x");
473 for (Int_t i = 1; i <= corr->GetNbinsX(); i++) {
474 Double_t x = corr->GetXaxis()->GetBinCenter(i);
475 if (x < -1 || x > xmax) continue;
476 for (Int_t j = 1; j <= corr->GetNbinsY(); j++) {
477 Double_t y = corr->GetYaxis()->GetBinCenter(j);
478 if (y < -1 || y > xmax) continue;
479 Double_t c = corr->GetBinContent(i,j);
480 if (c < .1) continue;
481 fitter->AddPoint(&x, y, c);
485 fCorrelation->a = fitter->GetParameter(0);
486 fCorrelation->ea = fitter->GetParError(0);
487 fCorrelation->b = fitter->GetParameter(1);
488 fCorrelation->eb = fitter->GetParError(1);
489 Double_t chi2 = fitter->GetChisquare();
490 Int_t ndf = (fitter->GetNpoints() -
491 fitter->GetNumberFreeParameters() );
492 fCorrelation->chi2 = chi2 / ndf;
499 if (corr->GetMaximum() > 0) p->SetLogz();
500 // if (fD == 3) p->SetRightMargin(0.15);
502 corr->GetXaxis()->SetRangeUser(-1,xmax);
503 corr->GetYaxis()->SetRangeUser(-1,xmax);
504 corr->SetTitle(Form("FMD%d%c",fD,fR));
507 TF1* f = new TF1("f", "[0]+[1]*x", xmin, xmax);
508 f->SetParameters(fCorrelation->alpha, fCorrelation->beta);
513 TLine* l = new TLine(-1,-1,xmax,xmax);
516 l->SetLineColor(kBlack);
519 Double_t x = p->GetLeftMargin() + .05;
520 Double_t y = 1-p->GetTopMargin()-gStyle->GetTitleH(); // +ts;
521 TLatex* ltx = new TLatex(x, y, "Deming regression: y=#alpha+#beta x");
523 ltx->SetTextAlign(13);
524 ltx->SetTextSize(0.06);
525 ltx->SetTextColor(kBlue+3);
528 DrawText(ltx, x, y, "#alpha:", Form("%5.3f", fCorrelation->alpha));
529 DrawText(ltx, x, y, "#beta:", Form("%5.3f", fCorrelation->beta));
532 DrawText(ltx, x, y, "A:", Form("%5.3f#pm%5.3f",
535 DrawText(ltx, x, y, "B:", Form("%5.3f#pm%5.3f",
538 DrawText(ltx, x, y, "#chi^{2}/#nu:", Form("%5.3f", fCorrelation->chi2));
546 /******************************************************************/
550 * @param keep Whehter to keep all info
551 * @param single Single run input
553 QATrender(Bool_t keep=false, Bool_t single=false)
558 fDensityCalculator(0),
563 fFMD1i = new Ring(1, 'I');
564 fFMD2i = new Ring(2, 'I');
565 fFMD2o = new Ring(2, 'O');
566 fFMD3i = new Ring(3, 'I');
567 fFMD3o = new Ring(3, 'O');
572 virtual ~QATrender() {}
576 * @param o Object to copy from
578 QATrender(const QATrender& o)
580 fCurrentFile(o.fCurrentFile),
581 fSharingFilter(o.fSharingFilter),
582 fEventInspector(o.fEventInspector),
583 fDensityCalculator(o.fDensityCalculator),
584 fEnergyFitter(o.fEnergyFitter),
589 * Assignment operator
591 * @return Reference to this
593 QATrender operator=(const QATrender&) { return *this; }
596 // --- Interface ---------------------------------------------------
598 * Add a file to be processed
600 * @param filename Name of file
602 void AddFile(const char* filename)
604 fFiles.Add(new TObjString(filename));
609 * @return true on success
617 while ((o = next())) {
618 if (!ProcessOne(o->GetName())) ret = false;
629 if (!fOutput) return;
634 gSystem->Exec(Form("chmod g+rw %s", OutputName()));
637 * Process a single file
639 * @param filename File to open.
641 * @return true on success
643 Bool_t ProcessOne(const char* filename)
646 fCurrentFile->Close();
650 fCurrentFile = TFile::Open(filename, "READ");
652 Error("ProcessOne", "Failed to open %s", filename);
657 // Error("ProcessOne", "Failed to get lists from %s", filename);
661 if (!ProcessGlobal()) {
662 Error("ProcessOne", "Failed to get global stuff from %s", filename);
665 fTeXName = Form("qa_%09d", fGlobal->runNo);
666 MakeCanvas(Form("QA plots for run %d", fGlobal->runNo));
667 Bool_t eloss = ProcessELossFitter();
668 Bool_t merge = ProcessSharingFilter();
669 Bool_t dense = ProcessDensityCalculator();
670 if (fTree) fTree->Fill();
673 return eloss && merge && dense;
675 // --- Processing member functions ---------------------------------
679 * @return true on success
681 Bool_t ProcessGlobal()
683 TObject* oRun = GetObject(fEventInspector, "runNo");
684 if (!oRun) return false;
686 fGlobal->runNo = oRun->GetUniqueID();
687 TH1* oAcc = GetHistogram(fEventInspector,"nEventsAccepted");
688 if (!oAcc) return false;
690 fGlobal->nAccepted = oAcc->GetEntries();
691 fGlobal->meanVz = oAcc->GetMean();
692 fGlobal->sigmaVz = oAcc->GetRMS();
697 * Clean a stack for histograms that match @a what
699 * @param stack Stack to clean
700 * @param what Pattern
702 void CleanStack(THStack* stack, const char* what)
704 TList* l = stack->GetHists();
706 // Clean up list of histogram. Histograms with no entries or
707 // no functions are deleted. We have to do this using the TObjLink
708 // objects stored in the list since ROOT cannot guaranty the validity
709 // of iterators when removing from a list - tsck. Should just implement
711 TObjLink* lnk = l->FirstLink();
713 TObject* o = lnk->GetObject();
714 TString s(o->GetName());
715 if (s.Contains(what)) {
716 TObjLink* keep = lnk->Next();
725 * Process the information from the energy loss fitter
728 * @return true on succes
730 Bool_t ProcessELossFitter()
732 MakeCanvasTitle("Summary of energy loss fits");
734 THStack* chi2 = static_cast<THStack*>(GetObject(fEnergyFitter, "chi2"));
735 THStack* c = static_cast<THStack*>(GetObject(fEnergyFitter, "c"));
736 THStack* delta = static_cast<THStack*>(GetObject(fEnergyFitter, "delta"));
737 THStack* xi = static_cast<THStack*>(GetObject(fEnergyFitter, "xi"));
738 THStack* sigma = static_cast<THStack*>(GetObject(fEnergyFitter, "sigma"));
740 if (!chi2) return false;
741 if (!c) return false;
742 if (!delta) return false;
743 if (!xi) return false;
744 if (!sigma) return false;
746 CleanStack(chi2, "_n");
747 CleanStack(c, "status");
750 THStack* stacks[] = { chi2, c, delta, xi, sigma, 0 };
751 for (int i = 0; i < 5; i++) {
752 THStack* stack = stacks[i];
753 TVirtualPad* p = GetPad(i+1);
754 // stack->GetHists()->ls();
756 p->SetLeftMargin(.6/nL);
757 p->SetTopMargin(.01);
758 p->SetRightMargin(.01);
762 stack->Draw("nostack");
763 stack->GetHistogram()->SetYTitle(stack->GetTitle());
764 stack->GetHistogram()->SetXTitle("#eta");
766 TAxis* yaxis = stack->GetHistogram()->GetYaxis();
767 if (i == 0) yaxis->SetRangeUser(0,20); // Chi2
768 if (i == 1) stack->SetMaximum(1); // c
769 if (i == 2) stack->SetMaximum(1); // delta
770 if (i == 3) stack->SetMaximum(0.1); // xi
771 if (i == 4) stack->SetMaximum(0.5); // sigma{,n}
772 // if (i == 0) p->SetLogy();
773 yaxis->SetTitleSize(0.3/nL);
774 yaxis->SetLabelSize(0.08);
775 yaxis->SetTitleOffset(3/nL);
776 yaxis->SetNdivisions(5);
777 yaxis->SetTitleFont(42);
778 yaxis->SetLabelFont(42);
779 yaxis->SetDecimals();
781 TAxis* xaxis = stack->GetHistogram()->GetXaxis();
782 xaxis->SetTitleSize(0.3/nL);
783 xaxis->SetLabelSize(0.08);
784 xaxis->SetTitleOffset(2./nL);
785 xaxis->SetNdivisions(10);
786 xaxis->SetTitleFont(42);
787 xaxis->SetLabelFont(42);
788 xaxis->SetDecimals();
790 stack->Draw("nostack");
793 TVirtualPad* p = GetPad(6);
794 p->SetFillColor(kWhite);
797 TLatex* l = new TLatex(x, y, "Fits to #Delta (energy loss) spectra");
798 l->SetTextColor(kBlue+3);
802 y -= 2 * 1.2*l->GetTextSize();
803 l->DrawLatex(x, y, "F(#Delta;c,#Delta_{p},#xi,#sigma)="
804 "#frac{c}{#sqrt{2#pi}#sigma}#int_{-#infty}^{#infty}d#Delta'"
805 "L(#Delta;#Delta',#xi) G(#Delta_{p};#Delta',#sigma^{2})");
806 y -= 1.2*l->GetTextSize();
808 DrawText(l, x, y, "#chi^{2}/#nu", "Goodness of fit", .2);
809 DrawText(l, x, y, "c", "Overall constant", .2);
810 DrawText(l, x, y, "#Delta_{p}", "Most probable value", .2);
811 DrawText(l, x, y, "#xi", "'Width' of Landau (L)", .2);
812 DrawText(l, x, y, "#sigma", "'Width' of Gaussian (G)", .2);
814 // stack->GetHists()->ls();
816 PrintCanvas("fitResults", fGlobal->runNo);
819 static_cast<Ring*>(fFMD1i)->ProcessEnergyLoss(fEnergyFitter);
820 static_cast<Ring*>(fFMD2i)->ProcessEnergyLoss(fEnergyFitter);
821 static_cast<Ring*>(fFMD2o)->ProcessEnergyLoss(fEnergyFitter);
822 static_cast<Ring*>(fFMD3i)->ProcessEnergyLoss(fEnergyFitter);
823 static_cast<Ring*>(fFMD3o)->ProcessEnergyLoss(fEnergyFitter);
828 * Process the information from the sharing filter
831 * @return true on success
833 Bool_t ProcessSharingFilter()
835 // --- Neighbors -------------------------------------------------
836 MakeCanvasTitle("Correlation of neighboring strips");
838 for (Int_t i = 1; i <= 6; i++) {
839 TVirtualPad* p = GetPad(i);
841 Ring* r = GetRing(i);
844 r->ProcessNeighbors(fSharingFilter, p);
847 if ((p = GetPad(4))) {
848 p->SetFillColor(kWhite);
850 TLatex* l = new TLatex(.2, .7, "Gradient: before merging");
852 l->SetTextColor(kBlue+3);
854 l->DrawText(.2, .6, "Boxes: after merging");
857 PrintCanvas("neighbors", fGlobal->runNo);
860 // --- 123 -------------------------------------------------------
861 MakeCanvasTitle("#Delta for singles, doubles, and triples");
863 for (Int_t i = 1; i <= 6; i++) {
866 Ring* r = GetRing(i);
869 r->Process123(fSharingFilter, p);
871 if ((p = GetPad(4))) {
872 TLegend* ll = new TLegend(.2, .2, .8, .8);
874 ll->SetBorderSize(0);
875 TLegendEntry* e = ll->AddEntry("dummy", "Singles", "l");
877 e = ll->AddEntry("dummy", "Doubles", "l");
879 e = ll->AddEntry("dummy", "Triples", "l");
883 PrintCanvas("123", fGlobal->runNo);
888 * Process the information from the density calculator
891 * @return true on success
893 Bool_t ProcessDensityCalculator()
895 // --- ELoss -----------------------------------------------------
896 MakeCanvasTitle("Energy loss from ESD, after merging, used");
898 for (Int_t i = 1; i <= 6; i++) {
899 TVirtualPad* p = GetPad(i);
901 Ring* r = GetRing(i);
904 r->ProcessELoss(fSharingFilter, fDensityCalculator, p);
907 if ((p = GetPad(4))) {
908 TLegend* ll = new TLegend(.2, .2, .8, .8);
910 ll->SetBorderSize(0);
911 TLegendEntry* e = ll->AddEntry("dummy", "From ESDs", "l");
913 e = ll->AddEntry("dummy", "After Merging", "l");
915 e = ll->AddEntry("dummy", "Used", "l");
919 PrintCanvas("recAna", fGlobal->runNo);
922 // --- Occupancy -------------------------------------------------
923 MakeCanvasTitle("Occupancy");
925 for (Int_t i = 1; i <= 6; i++) {
928 Ring* r = GetRing(i);
931 r->ProcessOccupancy(fDensityCalculator, p);
933 if ((p = GetPad(4))) {
934 TLatex* ltx = new TLatex(.2, .8, "Calculated assuming Poisson stat.");
936 ltx->SetTextColor(kBlue+3);
939 TObject* etaL = GetObject(fDensityCalculator, "etaLumping");
940 TObject* phiL = GetObject(fDensityCalculator, "phiLumping");
942 ltx->DrawLatex(.2, .7, Form("Regions of %s strips #times %s sectors",
943 etaL->GetTitle(), phiL->GetTitle()));
945 PrintCanvas("occupancy", fGlobal->runNo);
948 // --- Correlation of methods ------------------------------------
949 MakeCanvasTitle("Correlation of N_{ch} methods");
951 for (Int_t i = 1; i <= 6; i++) {
954 Ring* r = GetRing(i);
957 r->ProcessCorrelation(fDensityCalculator, p);
959 if ((p = GetPad(4))) {
960 TLatex* ltx = new TLatex(.2, .8, "Correlation of N_{ch} methods");
962 ltx->SetTextColor(kBlue+3);
964 ltx->DrawLatex(.24, .7, "From #DeltaE fits along x");
965 ltx->DrawLatex(.24, .6, "From Poisson assumption along y");
966 ltx->DrawLatex(.24, .4, "Solid line: regression");
967 ltx->DrawLatex(.24, .3, "Dashed line: x=y to guide the eye");
969 PrintCanvas("elossVsPoisson", fGlobal->runNo);
975 // --- Utilities ---------------------------------------------------
977 * Close current file if open, and reset other pointers
983 fCurrentFile->Close();
987 fDensityCalculator = 0;
991 if (fSingle) keep = true;
996 * Write full job footer
999 virtual void WriteLinks()
1001 const char* lbUrl = "https://alice-logbook.cern.ch/logbook/date_online.php";
1002 const char* crUrl = "http://alimonitor.cern.ch/configuration/index.jsp";
1003 const char* rpUrl = "http://alimonitor.cern.ch/runview/?run=";
1004 QABase::WriteLinks();
1006 TString resName(fTeXName);
1007 resName.ReplaceAll("qa", "QAresults");
1008 resName.Append(".root");
1009 TFile* results = TFile::Open(resName, "READ");
1011 *fHtml << "<h3>QA results</h3>\n"
1013 << "<li><a href='" << resName << "'>ROOT file</a></li>\n"
1019 *fHtml << "<h3>External links</h3>\n"
1021 << " <li><a target='_blank' href='" << lbUrl
1022 << "?p_cont=rund&p_run=" << fGlobal->runNo
1023 << "&p_tab=dqm&p_dqmagent=FMDQAshifter'>DQM plots</a>"
1024 << " (restricted)</li>\n"
1025 << " <li><a target='_blank' href='" << crUrl
1026 << "?raw_run=" << fGlobal->runNo
1027 << "'>Condition Table</a></li>\n"
1028 << " <li><a target='_blank' href='" << rpUrl << fGlobal->runNo
1029 << "'>Processing Details</a></li>\n"
1030 << "</ul>" << std::endl;
1034 * Get the ring corresponding to a pad
1036 * @param padNo Pad number
1038 * @return Pointer to ring
1040 Ring* GetRing(Int_t padNo)
1044 case 1: r = fFMD1i; break;
1045 case 2: r = fFMD2i; break;
1046 case 3: r = fFMD3i; break;
1047 case 5: r = fFMD2o; break;
1048 case 6: r = fFMD3o; break;
1050 if (r) return static_cast<Ring*>(r);
1054 * Get the pad corresponding to a number. Also clears the pad
1056 * @param padNo Pad number to get
1058 * @return Pointer to pad or null
1060 TVirtualPad* GetPad(Int_t padNo)
1062 if (!fCanvas) return 0;
1063 TVirtualPad* p = fCanvas->cd(padNo);
1066 p->SetFillColor(kWhite);
1071 * Make canvas title. Canvas is divided into 3x2 pads
1073 * @param what Title on canvas
1075 void MakeCanvasTitle(const char* what)
1077 if (!fCanvas) return;
1081 fCanvas->Divide(3,2,0,0);
1083 // --- List utilities ----------------------------------------------
1085 * Get a sub-list from parent list
1087 * @param parent Parent list
1088 * @param name Name of sub-list
1090 * @return Pointer to the list
1092 static TList* GetSubList(const TList* parent, const char* name)
1094 TList* tmp = static_cast<TList*>(parent->FindObject(name));
1096 Error("GetLists", "List %s not found in %s", name,
1103 * Get the lists from the file
1106 * @return true on success
1110 if (!fCurrentFile) return 0;
1112 const char* folder = "ForwardResults";
1113 TList* forward = static_cast<TList*>(fCurrentFile->Get(folder));
1115 Error("GetLists", "List %s not found in %s", folder,
1116 fCurrentFile->GetName());
1120 fSharingFilter = GetSubList(forward, "fmdSharingFilter");
1121 fEventInspector = GetSubList(forward, "fmdEventInspector");
1122 fDensityCalculator = GetSubList(forward, "fmdDensityCalculator");
1123 fEnergyFitter = GetSubList(forward, "fmdEnergyFitter");
1125 if (!fSharingFilter) return false;
1126 if (!fEventInspector) return false;
1127 if (!fDensityCalculator) return false;
1128 if (!fEnergyFitter) return false;
1133 * Find and object in a list
1135 * @param list List to look in
1136 * @param name Name of object
1138 * @return Pointer to object or null
1140 static TObject* GetObject(const TList* list, const char* name)
1142 if (!list) return 0;
1143 TObject* o = list->FindObject(name);
1145 Error("GetObject", "Failed to find object %s in %s",
1146 name, list->GetName());
1152 * Get a histogram from a list
1155 * @param name Name of histogram
1157 * @return Pointer to object or null
1159 static TH1* GetHistogram(const TList* list, const char* name)
1161 return static_cast<TH1*>(GetObject(list, name));
1164 * Draw some text on a pad
1166 * @param l LaTeX object to use
1167 * @param x x coordinate
1168 * @param y y coordinate (incremented on return)
1169 * @param c1 First text
1170 * @param c2 Second text
1171 * @param dx Distance between c1 start and c2 start
1174 DrawText(TLatex* l, Double_t x, Double_t& y, const char* c1, const char* c2,
1177 y -= 1.2*l->GetTextSize();
1178 l->DrawLatex(x, y, c1);
1179 l->DrawLatex(x+dx, y, c2);
1183 // --- Members -----------------------------------------------------
1184 TFile* fCurrentFile; // Current input file
1185 TList* fSharingFilter; // Sharing filter list
1186 TList* fEventInspector; // Event inspector list
1187 TList* fDensityCalculator; // Density calculator list
1188 TList* fEnergyFitter; // Energy fitter list
1189 TList fFiles; // List of files to process
1190 Bool_t fKeep; // Keep PNGs