]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWGLF/FORWARD/analysis2/qa/QATrender.C
Fixed references from PWG2 -> PWGLF - very efficiently done using ETags.
[u/mrichter/AliRoot.git] / PWGLF / FORWARD / analysis2 / qa / QATrender.C
CommitLineData
2dbde04b 1/**
2 * @file QATrender.C
3 * @author Christian Holm Christensen <cholm@nbi.dk>
4 * @date Thu Nov 17 12:28:17 2011
5 *
6 * @brief Class to make the QA trending tree
7 *
bd6f5206 8 * @ingroup pwglf_forward_qa_scripts
2dbde04b 9 */
10#ifndef __CINT__
11# include <TFile.h>
12# include <TTree.h>
13# include <TH1.h>
14# include <TH2.h>
15# include <TList.h>
16# include <TStyle.h>
17# include <TCanvas.h>
18# include <TPad.h>
19# include <TLatex.h>
20# include <TMath.h>
21# include <THStack.h>
22# include <TLegend.h>
23# include <TLegendEntry.h>
24# include <TLine.h>
25# include <TLinearFitter.h>
26# include <TF1.h>
27# include <TSystem.h>
28# include <fstream>
29# include <TFile.h>
30# include "QAStructs.h"
31# include "QARing.h"
32# include "QABase.h"
33#else
34class TList;
35class TFile;
36class TH1;
37class Quantity;
38class RingQuantity;
39class Merge;
40class FitStatus;
41class Correlation;
42class QARing;
43class QABase;
44class Global;
45class THStack;
46class TLatex;
47class TVirtualPad;
48#endif
49
50
51// --- A quantity ----------------------------------------------------
52/**
53 * Class to make the QA trending tree
54 *
bd6f5206 55 * @ingroup pwglf_forward_qa_scripts
2dbde04b 56 */
57struct QATrender : public QABase
58{
59public:
60 /******************************************************************/
61 /**
62 * A ring object
63 *
64 */
65 struct Ring : public QARing
66 {
67 /**
68 * Constructor
69 *
70 * @param d Detector
71 * @param r Ring
72 */
73 Ring(UShort_t d, Char_t r) : QARing(d, r) {}
74 /**
75 * Get the detector specific list
76 *
77 * @param parent Parent list
78 *
79 * @return Found list or null
80 */
81 TList* GetDetectorList(const TList* parent) const
82 {
83 TObject* o = QATrender::GetSubList(parent, Form("FMD%d%c", fD, fR));
84 return static_cast<TList*>(o);
85 }
86 /**
87 * Calculate numbers from read histograms
88 *
89 * @param parent Parent list
90 * @param name Name of histogram
91 * @param q Qauntity to store in
92 *
93 * @return true on success
94 */
95 Bool_t ExtractYQuantity(const TList* parent, const char* name,
96 Quantity* q)
97 {
98 q->mean = 0;
99 q->var = 0;
100 q->min = 0;
101 q->max = 0;
102
103 TH1* h = QATrender::GetHistogram(parent, name);
104 if (!h) {
105 // Warning("ExtractYQuantity", "Histogram %s not found", name);
106 return false;
107 }
108
109 Double_t sum = 0;
110 Double_t sumw = 0;
111 Double_t min = 1e12;
112 Double_t max = 0;
113 for (Int_t i = 1; i <= h->GetNbinsX(); i++) {
114 Double_t y = h->GetBinContent(i);
115 Double_t e = h->GetBinError(i);
116 Double_t w = 1;
117 if (y <= 1e-12) continue;
118 if (e != 0) w = 1 / (e*e);
119 sum += w * y;
120 sumw += w;
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);
124 }
125 q->min = min;
126 q->max = max;
127 if (sumw <= 1e-6) {
128 // Warning("ExtractYQuantity",
129 // "Sum of weights for %s too small %g<1e-6",
130 // name, sumw);
131 return true;
132 }
133 q->mean = sum / sumw;
134 q->var = TMath::Sqrt(1/sumw);
135 // Info(name, " mean=%f, var=%f", q->mean, q->var);
136 return true;
137 }
138 /**
139 * Process data from the energy loss fits
140 *
141 * @param parent Parent list
142 *
143 * @return true on success
144 */
145 Bool_t ProcessEnergyLoss(const TList* parent)
146 {
147 TList* det = GetDetectorList(parent);
148 if (!det) return false;
149
150 TList* res = QATrender::GetSubList(det, "FitResults");
151 if (!res) return false;
152
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);
158
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));
164
165 return true;
166 }
167 /**
168 * Process data on neighbors
169 *
170 * @param parent Parent list
171 * @param p (optional) Pad to draw
172 *
173 * @return true on success
174 */
175 Bool_t ProcessNeighbors(const TList* parent, TVirtualPad* p)
176 {
177 if (!p) return true; // Case of no drawing
178
179 TList* det = GetDetectorList(parent);
180 if (!det) return false;
181
182 TH1* before = QATrender::GetHistogram(det, "neighborsBefore");
183 TH1* after = QATrender::GetHistogram(det, "neighborsAfter");
184 if (!before || !after) return false;
185
186 if (before->GetMaximum() > 0) p->SetLogz();
187 p->SetFillColor(0);
188 if (fD == 3) p->SetRightMargin(0.15);
189
190 before->SetTitle(Form("FMD%d%c",fD,fR));
191 before->Draw("colz");
192 after->Draw("same box");
193
194 before->GetXaxis()->SetRangeUser(-.5, 2);
195 before->GetYaxis()->SetRangeUser(-.5, 2);
196
197 TLatex* ltx = new TLatex(p->GetLeftMargin()+.01,
198 p->GetBottomMargin()+.01,
199 before->GetTitle());
200 ltx->SetNDC();
201 ltx->SetTextSize(.07);
202 ltx->Draw();
203
204 return true;
205 }
206 /**
207 * Process data on single, double, and triple hits
208 *
209 * @param parent Parent list
210 * @param p (optional) Pad to draw
211 *
212 * @return true on success
213 */
214 Bool_t Process123(const TList* parent, TVirtualPad* p)
215 {
216 TList* det = GetDetectorList(parent);
217 if (!det) return false;
218
219 fMerge->one = 0;
220 fMerge->two = 0;
221 fMerge->three = 0;
222
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;
227
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;
232 if (total > 0) {
233 fMerge->one = Double_t(nOne) / total;
234 fMerge->two = Double_t(nTwo) / total;
235 fMerge->three = Double_t(nThree) / total;
236 }
237
238 if (!p) return true;
239
240 one->SetStats(0);
241 one->SetTitle(Form("FMD%d%c", fD, fR));
242 one->GetXaxis()->SetRangeUser(0, 8);
243
244 if (one->GetMaximum() > 0) p->SetLogy();
245 p->SetFillColor(0);
246 if ((p->GetNumber() % 3) != 1) p->SetLeftMargin(.1);
247
248 one->SetLineStyle(1);
249 two->SetLineStyle(2);
250 three->SetLineStyle(3);
251
252 one->Draw();
253 two->Draw("same");
254 three->Draw("same");
255
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 ...");
260 ltx->SetNDC();
261 ltx->SetTextColor(kBlue+3);
262 ltx->SetTextAlign(13);
263 // ltx->SetTextAlign(33);
264 ltx->SetTextSize(.07);
265 ltx->Draw();
266
267 // y -= .1;
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));
271
272 p->cd();
273
274 return true;
275 }
276 /**
277 * Process energy loss distributions
278 *
279 * @param p1 First parent list (sharing filter)
280 * @param p2 Second parent list (density calculator)
281 * @param p (optional) Pad to draw
282 *
283 * @return true on success
284 */
285 Bool_t ProcessELoss(TList* p1, TList* p2, TVirtualPad* p)
286 {
287 TList* det1 = GetDetectorList(p1);
288 if (!det1) return false;
289
290 TList* det2 = GetDetectorList(p2);
291 if (!det2) return false;
292
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");
297
298 if (!before || !after || !presented || !used) return false;
299
300 const Double_t lowCut = 0.15;
301
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()));
307
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;
314
315 fDataLoss->merge = dba;
316 fDataLoss->density = dau;
317 fDataLoss->full = dbu;
318
319 if (!p) return true;
320
321 if (before->GetMaximum() > 0) p->SetLogy();
322 p->SetFillColor(0);
323 before->SetTitle(Form("FMD%d%c",fD,fR));
324
325 before->SetLineStyle(1);
326 after->SetLineStyle(2);
327 used->SetLineStyle(3);
328
329 before->Draw("");
330 after->Draw("same");
331 presented->Draw("same");
332 used->Draw("same");
333
334 Double_t ts = 0.03;
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));
338 ltx->SetNDC();
339 ltx->SetTextAlign(13);
340 ltx->SetTextSize(ts);
341 ltx->SetTextColor(kBlue+3);
342 // ltx->Draw();
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;
350 l->SetLineWidth(1);
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%%)",
355 dap, dbp));
356 DrawText(ltx, x, y, "Change (use)", Form("%5.1f%% (%5.1f%%)",
357 dpu, dbu));
358 }
359 before->GetXaxis()->SetRangeUser(0, 4);
360 p->cd();
361
362 return true;
363 }
364 /**
365 * Process occupancy information
366 *
367 * @param parent Parent list
368 * @param p (optional) Pad to draw
369 *
370 * @return true on success
371 */
372 Bool_t ProcessOccupancy(const TList* parent, TVirtualPad* p)
373 {
374 TList* det = GetDetectorList(parent);
375 if (!det) return false;
376
377 TH1* occ = QATrender::GetHistogram(det, "occupancy");
378 if (!occ) return false;
379
380 fOccupancy->mean = occ->GetMean();
381 fOccupancy->var = occ->GetRMS();
382 fOccupancy->min = 1;
383 fOccupancy->max = 0;
384
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);
389 break;
390 }
391
392 if (!p) return true;
393 p->SetGridy();
394 p->SetGridx();
395 if (occ->GetMaximum() > 0) p->SetLogy();
396 p->SetFillColor(0);
397 p->SetRightMargin(0.01);
398 occ->Rebin(4);
399 occ->SetTitle(Form("FMD%d%c", fD, fR));
400 occ->Draw("hist");
401
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, "");
406 ltx->SetNDC();
407 ltx->SetTextColor(kBlue+3);
408 ltx->SetTextAlign(13);
409 // ltx->SetTextAlign(33);
410 ltx->SetTextSize(.07);
411 ltx->Draw();
412
413 // y -= .1;
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));
417
418 p->cd();
419
420 return true;
421 }
422 /**
423 * Process method correlations
424 *
425 * @param parent Parent list
426 * @param p (optional) Pad to draw
427 *
428 * @return true on success
429 */
430 Bool_t ProcessCorrelation(const TList* parent, TVirtualPad* p)
431 {
432 TList* det = GetDetectorList(parent);
433 if (!det) return false;
434
435 TH1* co = QATrender::GetHistogram(det, "elossVsPoisson");
436 if (!co) return false;
437 TH2* corr = static_cast<TH2*>(co);
438
439 fCorrelation->alpha = 0;
440 fCorrelation->beta = 0;
441 fCorrelation->a = 0;
442 fCorrelation->ea = 0;
443 fCorrelation->b = 0;
444 fCorrelation->eb = 0;
445 fCorrelation->chi2 = 0;
446
447 Double_t xmin = -1;
448 Double_t xmax = corr->GetXaxis()->GetXmax();
449
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);
461 Double_t delta = 1;
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;
467 }
468
469
470#if 0
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);
482 }
483 }
484 fitter->Eval();
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;
493#endif
494 }
495 if (!p) return true;
496
497 p->SetGridy();
498 p->SetGridx();
499 if (corr->GetMaximum() > 0) p->SetLogz();
500 // if (fD == 3) p->SetRightMargin(0.15);
501 p->SetFillColor(0);
502 corr->GetXaxis()->SetRangeUser(-1,xmax);
503 corr->GetYaxis()->SetRangeUser(-1,xmax);
504 corr->SetTitle(Form("FMD%d%c",fD,fR));
505 corr->Draw("colz");
506
507 TF1* f = new TF1("f", "[0]+[1]*x", xmin, xmax);
508 f->SetParameters(fCorrelation->alpha, fCorrelation->beta);
509 f->SetLineWidth(1);
510 f->SetLineStyle(1);
511 f->Draw("same");
512
513 TLine* l = new TLine(-1,-1,xmax,xmax);
514 l->SetLineWidth(1);
515 l->SetLineStyle(2);
516 l->SetLineColor(kBlack);
517 l->Draw();
518
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");
522 ltx->SetNDC();
523 ltx->SetTextAlign(13);
524 ltx->SetTextSize(0.06);
525 ltx->SetTextColor(kBlue+3);
526 ltx->Draw();
527
528 DrawText(ltx, x, y, "#alpha:", Form("%5.3f", fCorrelation->alpha));
529 DrawText(ltx, x, y, "#beta:", Form("%5.3f", fCorrelation->beta));
530
531#if 0
532 DrawText(ltx, x, y, "A:", Form("%5.3f#pm%5.3f",
533 fCorrelation->a,
534 fCorrelation->ea));
535 DrawText(ltx, x, y, "B:", Form("%5.3f#pm%5.3f",
536 fCorrelation->b,
537 fCorrelation->eb));
538 DrawText(ltx, x, y, "#chi^{2}/#nu:", Form("%5.3f", fCorrelation->chi2));
539#endif
540 p->cd();
541
542 return true;
543 }
544 };
545
546 /******************************************************************/
547 /**
548 * CTOR
549 */
3405bb49 550 QATrender(Bool_t keep=false, Bool_t single=false)
2dbde04b 551 : QABase(single),
552 fCurrentFile(0),
553 fSharingFilter(0),
554 fEventInspector(0),
555 fDensityCalculator(0),
556 fEnergyFitter(0),
3405bb49 557 fFiles(0),
558 fKeep(keep)
2dbde04b 559 {
560 fFMD1i = new Ring(1, 'I');
561 fFMD2i = new Ring(2, 'I');
562 fFMD2o = new Ring(2, 'O');
563 fFMD3i = new Ring(3, 'I');
564 fFMD3o = new Ring(3, 'O');
565 }
566 /**
567 * DTOR
568 */
569 virtual ~QATrender() {}
570 /**
571 * Copy CTOR
572 *
573 */
574 QATrender(const QATrender& o)
575 : QABase(o),
576 fCurrentFile(o.fCurrentFile),
577 fSharingFilter(o.fSharingFilter),
578 fEventInspector(o.fEventInspector),
579 fDensityCalculator(o.fDensityCalculator),
580 fEnergyFitter(o.fEnergyFitter),
3405bb49 581 fFiles(0),
582 fKeep(o.fKeep)
2dbde04b 583 {}
584 /**
585 * Assignment operator
586 *
587 * @return Reference to this
588 */
589 QATrender operator=(const QATrender&) { return *this; }
590
591
592 // --- Interface ---------------------------------------------------
593 /**
594 * Add a file to be processed
595 *
596 * @param filename Name of file
597 */
598 void AddFile(const char* filename)
599 {
600 fFiles.Add(new TObjString(filename));
601 }
602 /**
603 * Run the job
604 *
605 */
bae153e5 606 Bool_t Run()
2dbde04b 607 {
608 Init(false);
609 TIter next(&fFiles);
610 TObject* o = 0;
bae153e5 611 Bool_t ret = true;
2dbde04b 612 while ((o = next())) {
bae153e5 613 if (!ProcessOne(o->GetName())) ret = false;
2dbde04b 614 }
615 Finish();
bae153e5 616 return ret;
2dbde04b 617 }
618 /**
619 * Finish the job
620 *
621 */
622 void Finish()
623 {
624 if (!fOutput) return;
625 fOutput->Write();
626 fOutput->Close();
627 fOutput = 0;
628 fTree = 0;
629 gSystem->Exec(Form("chmod g+rw %s", OutputName()));
630 }
631 /**
632 * Process a single file
633 *
634 * @param filename File to open.
635 *
636 * @return true on success
637 */
638 Bool_t ProcessOne(const char* filename)
639 {
640 if (fCurrentFile) {
641 fCurrentFile->Close();
642 fCurrentFile = 0;
643 }
644
645 fCurrentFile = TFile::Open(filename, "READ");
646 if (!fCurrentFile) {
647 Error("ProcessOne", "Failed to open %s", filename);
648 return false;
649 }
650
651 if (!GetLists()) {
dc8aa359 652 // Error("ProcessOne", "Failed to get lists from %s", filename);
2dbde04b 653 return false;
654 }
655
656 if (!ProcessGlobal()) {
657 Error("ProcessOne", "Failed to get global stuff from %s", filename);
658 return false;
659 }
660 fTeXName = Form("qa_%09d", fGlobal->runNo);
661 MakeCanvas(Form("QA plots for run %d", fGlobal->runNo));
662 Bool_t eloss = ProcessELossFitter();
663 Bool_t merge = ProcessSharingFilter();
664 Bool_t dense = ProcessDensityCalculator();
665 if (fTree) fTree->Fill();
666 CloseCurrent();
667
668 return eloss && merge && dense;
669 }
670 // --- Processing member functions ---------------------------------
671 /**
672 * Get global stuff
673 *
674 * @return true on success
675 */
676 Bool_t ProcessGlobal()
677 {
678 TObject* oRun = GetObject(fEventInspector, "runNo");
679 if (!oRun) return false;
680
681 fGlobal->runNo = oRun->GetUniqueID();
682 TH1* oAcc = GetHistogram(fEventInspector,"nEventsAccepted");
683 if (!oAcc) return false;
684
685 fGlobal->nAccepted = oAcc->GetEntries();
686 fGlobal->meanVz = oAcc->GetMean();
687 fGlobal->sigmaVz = oAcc->GetRMS();
688
689 return true;
690 }
691 /**
692 * Clean a stack for histograms that match @a what
693 *
694 * @param stack Stack to clean
695 * @param what Pattern
696 */
697 void CleanStack(THStack* stack, const char* what)
698 {
699 TList* l = stack->GetHists();
700
701 // Clean up list of histogram. Histograms with no entries or
702 // no functions are deleted. We have to do this using the TObjLink
703 // objects stored in the list since ROOT cannot guaranty the validity
704 // of iterators when removing from a list - tsck. Should just implement
705 // TIter::Remove().
706 TObjLink* lnk = l->FirstLink();
707 while (lnk) {
708 TObject* o = lnk->GetObject();
709 TString s(o->GetName());
710 if (s.Contains(what)) {
711 TObjLink* keep = lnk->Next();
712 l->Remove(lnk);
713 lnk = keep;
714 continue;
715 }
716 lnk = lnk->Next();
717 }
718 }
719 /**
720 * Process the information from the energy loss fitter
721 *
722 *
723 * @return true on succes
724 */
725 Bool_t ProcessELossFitter()
726 {
727 MakeCanvasTitle("Summary of energy loss fits");
728
729 THStack* chi2 = static_cast<THStack*>(GetObject(fEnergyFitter, "chi2"));
730 THStack* c = static_cast<THStack*>(GetObject(fEnergyFitter, "c"));
731 THStack* delta = static_cast<THStack*>(GetObject(fEnergyFitter, "delta"));
732 THStack* xi = static_cast<THStack*>(GetObject(fEnergyFitter, "xi"));
733 THStack* sigma = static_cast<THStack*>(GetObject(fEnergyFitter, "sigma"));
734
735 if (!chi2) return false;
736 if (!c) return false;
737 if (!delta) return false;
738 if (!xi) return false;
739 if (!sigma) return false;
740
741 CleanStack(chi2, "_n");
742 CleanStack(c, "status");
743 if (fCanvas) {
744 const int nL = 3;
745 THStack* stacks[] = { chi2, c, delta, xi, sigma, 0 };
746 for (int i = 0; i < 5; i++) {
747 THStack* stack = stacks[i];
748 TVirtualPad* p = GetPad(i+1);
749 // stack->GetHists()->ls();
750
751 p->SetLeftMargin(.6/nL);
752 p->SetTopMargin(.01);
753 p->SetRightMargin(.01);
754 p->SetFillColor(0);
755 p->SetFillStyle(0);
756 p->SetGridx();
757 stack->Draw("nostack");
758 stack->GetHistogram()->SetYTitle(stack->GetTitle());
759 stack->GetHistogram()->SetXTitle("#eta");
760
761 TAxis* yaxis = stack->GetHistogram()->GetYaxis();
762 if (i == 0) yaxis->SetRangeUser(0,20); // Chi2
763 if (i == 1) stack->SetMaximum(1); // c
764 if (i == 2) stack->SetMaximum(1); // delta
765 if (i == 3) stack->SetMaximum(0.1); // xi
766 if (i == 4) stack->SetMaximum(0.5); // sigma{,n}
767 // if (i == 0) p->SetLogy();
768 yaxis->SetTitleSize(0.3/nL);
769 yaxis->SetLabelSize(0.08);
770 yaxis->SetTitleOffset(3/nL);
771 yaxis->SetNdivisions(5);
772 yaxis->SetTitleFont(42);
773 yaxis->SetLabelFont(42);
774 yaxis->SetDecimals();
775
776 TAxis* xaxis = stack->GetHistogram()->GetXaxis();
777 xaxis->SetTitleSize(0.3/nL);
778 xaxis->SetLabelSize(0.08);
779 xaxis->SetTitleOffset(2./nL);
780 xaxis->SetNdivisions(10);
781 xaxis->SetTitleFont(42);
782 xaxis->SetLabelFont(42);
783 xaxis->SetDecimals();
784
785 stack->Draw("nostack");
786 p->cd();
787 }
788 TVirtualPad* p = GetPad(6);
789 p->SetFillColor(kWhite);
790 Double_t x = .3;
791 Double_t y = .8;
792 TLatex* l = new TLatex(x, y, "Fits to #Delta (energy loss) spectra");
793 l->SetTextColor(kBlue+3);
794 l->SetNDC();
795 l->Draw();
796 x = .05;
797 y -= 2 * 1.2*l->GetTextSize();
798 l->DrawLatex(x, y, "F(#Delta;c,#Delta_{p},#xi,#sigma)="
799 "#frac{c}{#sqrt{2#pi}#sigma}#int_{-#infty}^{#infty}d#Delta'"
800 "L(#Delta;#Delta',#xi) G(#Delta_{p};#Delta',#sigma^{2})");
801 y -= 1.2*l->GetTextSize();
802 x += .1;
803 DrawText(l, x, y, "#chi^{2}/#nu", "Goodness of fit", .2);
804 DrawText(l, x, y, "c", "Overall constant", .2);
805 DrawText(l, x, y, "#Delta_{p}", "Most probable value", .2);
806 DrawText(l, x, y, "#xi", "'Width' of Landau (L)", .2);
807 DrawText(l, x, y, "#sigma", "'Width' of Gaussian (G)", .2);
808
809 // stack->GetHists()->ls();
810
811 PrintCanvas("fitResults", fGlobal->runNo);
812 }
813
814 static_cast<Ring*>(fFMD1i)->ProcessEnergyLoss(fEnergyFitter);
815 static_cast<Ring*>(fFMD2i)->ProcessEnergyLoss(fEnergyFitter);
816 static_cast<Ring*>(fFMD2o)->ProcessEnergyLoss(fEnergyFitter);
817 static_cast<Ring*>(fFMD3i)->ProcessEnergyLoss(fEnergyFitter);
818 static_cast<Ring*>(fFMD3o)->ProcessEnergyLoss(fEnergyFitter);
819
820 return true;
821 }
822 /**
823 * Process the information from the sharing filter
824 *
825 *
826 * @return true on success
827 */
828 Bool_t ProcessSharingFilter()
829 {
830 // --- Neighbors -------------------------------------------------
831 MakeCanvasTitle("Correlation of neighboring strips");
832
833 for (Int_t i = 1; i <= 6; i++) {
834 TVirtualPad* p = GetPad(i);
835
836 Ring* r = GetRing(i);
837 if (!r) continue;
838
839 r->ProcessNeighbors(fSharingFilter, p);
840 }
841 TVirtualPad* p = 0;
842 if ((p = GetPad(4))) {
843 p->SetFillColor(kWhite);
844
845 TLatex* l = new TLatex(.2, .7, "Gradient: before merging");
846 l->SetNDC();
847 l->SetTextColor(kBlue+3);
848 l->Draw();
849 l->DrawText(.2, .6, "Boxes: after merging");
850
851 fCanvas->cd();
852 PrintCanvas("neighbors", fGlobal->runNo);
853 }
854
855 // --- 123 -------------------------------------------------------
856 MakeCanvasTitle("#Delta for singles, doubles, and triples");
857
858 for (Int_t i = 1; i <= 6; i++) {
859 p = GetPad(i);
860
861 Ring* r = GetRing(i);
862 if (!r) continue;
863
864 r->Process123(fSharingFilter, p);
865 }
866 if ((p = GetPad(4))) {
867 TLegend* ll = new TLegend(.2, .2, .8, .8);
868 ll->SetFillColor(0);
869 ll->SetBorderSize(0);
870 TLegendEntry* e = ll->AddEntry("dummy", "Singles", "l");
871 e->SetLineStyle(1);
872 e = ll->AddEntry("dummy", "Doubles", "l");
873 e->SetLineStyle(2);
874 e = ll->AddEntry("dummy", "Triples", "l");
875 e->SetLineStyle(3);
876 ll->Draw();
877
878 PrintCanvas("123", fGlobal->runNo);
879 }
880 return true;
881 }
882 /**
883 * Process the information from the density calculator
884 *
885 *
886 * @return true on success
887 */
888 Bool_t ProcessDensityCalculator()
889 {
890 // --- ELoss -----------------------------------------------------
891 MakeCanvasTitle("Energy loss from ESD, after merging, used");
892
893 for (Int_t i = 1; i <= 6; i++) {
894 TVirtualPad* p = GetPad(i);
895
896 Ring* r = GetRing(i);
897 if (!r) continue;
898
899 r->ProcessELoss(fSharingFilter, fDensityCalculator, p);
900 }
901 TVirtualPad* p = 0;
902 if ((p = GetPad(4))) {
903 TLegend* ll = new TLegend(.2, .2, .8, .8);
904 ll->SetFillColor(0);
905 ll->SetBorderSize(0);
906 TLegendEntry* e = ll->AddEntry("dummy", "From ESDs", "l");
907 e->SetLineStyle(1);
908 e = ll->AddEntry("dummy", "After Merging", "l");
909 e->SetLineStyle(2);
910 e = ll->AddEntry("dummy", "Used", "l");
911 e->SetLineStyle(3);
912 ll->Draw();
913
914 PrintCanvas("recAna", fGlobal->runNo);
915 }
916
917 // --- Occupancy -------------------------------------------------
918 MakeCanvasTitle("Occupancy");
919
920 for (Int_t i = 1; i <= 6; i++) {
921 p = GetPad(i);
922
923 Ring* r = GetRing(i);
924 if (!r) continue;
925
926 r->ProcessOccupancy(fDensityCalculator, p);
927 }
928 if ((p = GetPad(4))) {
929 TLatex* ltx = new TLatex(.2, .8, "Calculated assuming Poisson stat.");
930 ltx->SetNDC();
931 ltx->SetTextColor(kBlue+3);
932 ltx->Draw();
933
934 TObject* etaL = GetObject(fDensityCalculator, "etaLumping");
935 TObject* phiL = GetObject(fDensityCalculator, "phiLumping");
936 if (etaL && phiL)
937 ltx->DrawLatex(.2, .7, Form("Regions of %s strips #times %s sectors",
938 etaL->GetTitle(), phiL->GetTitle()));
939
940 PrintCanvas("occupancy", fGlobal->runNo);
941 }
942
943 // --- Correlation of methods ------------------------------------
944 MakeCanvasTitle("Correlation of N_{ch} methods");
945
946 for (Int_t i = 1; i <= 6; i++) {
947 p = GetPad(i);
948
949 Ring* r = GetRing(i);
950 if (!r) continue;
951
952 r->ProcessCorrelation(fDensityCalculator, p);
953 }
954 if ((p = GetPad(4))) {
955 TLatex* ltx = new TLatex(.2, .8, "Correlation of N_{ch} methods");
956 ltx->SetNDC();
957 ltx->SetTextColor(kBlue+3);
958 ltx->Draw();
959 ltx->DrawLatex(.24, .7, "From #DeltaE fits along x");
960 ltx->DrawLatex(.24, .6, "From Poisson assumption along y");
961 ltx->DrawLatex(.24, .4, "Solid line: regression");
962 ltx->DrawLatex(.24, .3, "Dashed line: x=y to guide the eye");
963
964 PrintCanvas("elossVsPoisson", fGlobal->runNo);
965 }
966
967 return true;
968 }
969
970 // --- Utilities ---------------------------------------------------
971 /**
972 * Close current file if open, and reset other pointers
973 *
974 */
975 void CloseCurrent()
976 {
977 if (fCurrentFile) {
978 fCurrentFile->Close();
979 fCurrentFile = 0;
980 fSharingFilter = 0;
981 fEventInspector = 0;
982 fDensityCalculator = 0;
983 fEnergyFitter = 0;
984 }
3405bb49 985 bool keep = fKeep;
986 if (fSingle) keep = true;
9a684059 987
3405bb49 988 Close(!keep);
2dbde04b 989 }
9a684059 990 /**
991 * Write full job footer
992 *
993 */
994 virtual void WriteLinks()
995 {
996 const char* lbUrl = "https://alice-logbook.cern.ch/logbook/date_online.php";
997 const char* crUrl = "http://alimonitor.cern.ch/configuration/index.jsp";
998 const char* rpUrl = "http://alimonitor.cern.ch/runview/?run=";
999 QABase::WriteLinks();
5c75ba4f 1000
1001 TString resName(fTeXName);
1002 resName.ReplaceAll("qa", "QAresults");
1003 resName.Append(".root");
1004 TFile* results = TFile::Open(resName, "READ");
1005 if (results) {
1006 *fHtml << "<h3>QA results</h3>\n"
1007 << "<ul>\n"
1008 << "<li><a href='" << resName << "'>ROOT file</a></li>\n"
1009 << "</ul>"
1010 << std::endl;
1011 results->Close();
1012 }
1013
9a684059 1014 *fHtml << "<h3>External links</h3>\n"
1015 << "<ul>\n"
1016 << " <li><a target='_blank' href='" << lbUrl
1017 << "?p_cont=rund&p_run=" << fGlobal->runNo
1018 << "&p_tab=dqm&p_dqmagent=FMDQAshifter'>DQM plots</a>"
1019 << " (restricted)</li>\n"
1020 << " <li><a target='_blank' href='" << crUrl
1021 << "?raw_run=" << fGlobal->runNo
1022 << "'>Condition Table</a></li>\n"
1023 << " <li><a target='_blank' href='" << rpUrl << fGlobal->runNo
1024 << "'>Processing Details</a></li>\n"
1025 << "</ul>" << std::endl;
1026 }
1027
2dbde04b 1028 /**
1029 * Get the ring corresponding to a pad
1030 *
1031 * @param padNo Pad number
1032 *
1033 * @return Pointer to ring
1034 */
1035 Ring* GetRing(Int_t padNo)
1036 {
1037 QARing* r = 0;
1038 switch(padNo) {
1039 case 1: r = fFMD1i; break;
1040 case 2: r = fFMD2i; break;
1041 case 3: r = fFMD3i; break;
1042 case 5: r = fFMD2o; break;
1043 case 6: r = fFMD3o; break;
1044 }
1045 if (r) return static_cast<Ring*>(r);
1046 return 0;
1047 }
1048 /**
1049 * Get the pad corresponding to a number. Also clears the pad
1050 *
1051 * @param padNo Pad number to get
1052 *
1053 * @return Pointer to pad or null
1054 */
1055 TVirtualPad* GetPad(Int_t padNo)
1056 {
1057 if (!fCanvas) return 0;
1058 TVirtualPad* p = fCanvas->cd(padNo);
1059 if (!p) return 0;
1060 p->Clear();
1061 p->SetFillColor(kWhite);
1062 return p;
1063 }
1064
1065 /**
1066 * Make canvas title. Canvas is divided into 3x2 pads
1067 *
1068 * @param what Title on canvas
1069 */
1070 void MakeCanvasTitle(const char* what)
1071 {
1072 if (!fCanvas) return;
1073 fCanvas->cd();
1074
1075 CanvasTitle(what);
1076 fCanvas->Divide(3,2,0,0);
1077 }
1078 // --- List utilities ----------------------------------------------
1079 /**
1080 * Get a sub-list from parent list
1081 *
1082 * @param parent Parent list
1083 * @param name Name of sub-list
1084 *
1085 * @return Pointer to the list
1086 */
1087 static TList* GetSubList(const TList* parent, const char* name)
1088 {
1089 TList* tmp = static_cast<TList*>(parent->FindObject(name));
1090 if (!tmp) {
1091 Error("GetLists", "List %s not found in %s", name,
1092 parent->GetName());
1093 return 0;
1094 }
1095 return tmp;
1096 }
1097 /**
1098 * Get the lists from the file
1099 *
1100 *
1101 * @return true on success
1102 */
1103 Bool_t GetLists()
1104 {
1105 if (!fCurrentFile) return 0;
1106
1107 const char* folder = "ForwardResults";
1108 TList* forward = static_cast<TList*>(fCurrentFile->Get(folder));
1109 if (!forward) {
1110 Error("GetLists", "List %s not found in %s", folder,
1111 fCurrentFile->GetName());
1112 return false;
1113 }
1114
1115 fSharingFilter = GetSubList(forward, "fmdSharingFilter");
1116 fEventInspector = GetSubList(forward, "fmdEventInspector");
1117 fDensityCalculator = GetSubList(forward, "fmdDensityCalculator");
1118 fEnergyFitter = GetSubList(forward, "fmdEnergyFitter");
1119
1120 if (!fSharingFilter) return false;
1121 if (!fEventInspector) return false;
1122 if (!fDensityCalculator) return false;
1123 if (!fEnergyFitter) return false;
1124
1125 return true;
1126 }
1127 /**
1128 * Find and object in a list
1129 *
1130 * @param list List to look in
1131 * @param name Name of object
1132 *
1133 * @return Pointer to object or null
1134 */
1135 static TObject* GetObject(const TList* list, const char* name)
1136 {
1137 if (!list) return 0;
1138 TObject* o = list->FindObject(name);
1139 if (!o) {
1140 Error("GetObject", "Failed to find object %s in %s",
1141 name, list->GetName());
1142 return 0;
1143 }
1144 return o;
1145 }
1146 /**
1147 * Get a histogram from a list
1148 *
1149 * @param list List
1150 * @param name Name of histogram
1151 *
1152 * @return Pointer to object or null
1153 */
1154 static TH1* GetHistogram(const TList* list, const char* name)
1155 {
1156 return static_cast<TH1*>(GetObject(list, name));
1157 }
1158 /**
1159 * Draw some text on a pad
1160 *
1161 * @param l LaTeX object to use
1162 * @param x x coordinate
1163 * @param y y coordinate (incremented on return)
1164 * @param c1 First text
1165 * @param c2 Second text
1166 * @param dx Distance between c1 start and c2 start
1167 */
1168 static void
1169 DrawText(TLatex* l, Double_t x, Double_t& y, const char* c1, const char* c2,
1170 Double_t dx=.4)
1171 {
1172 y -= 1.2*l->GetTextSize();
1173 l->DrawLatex(x, y, c1);
1174 l->DrawLatex(x+dx, y, c2);
1175 }
1176
1177
1178 // --- Members -----------------------------------------------------
1179 TFile* fCurrentFile; // Current input file
1180 TList* fSharingFilter; // Sharing filter list
1181 TList* fEventInspector; // Event inspector list
1182 TList* fDensityCalculator; // Density calculator list
1183 TList* fEnergyFitter; // Energy fitter list
1184 TList fFiles; // List of files to process
3405bb49 1185 Bool_t fKeep; // Keep PNGs
2dbde04b 1186};
1187//
1188// EOF
1189//
1190
1191
1192