]>
Commit | Line | Data |
---|---|---|
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 | |
34 | class TList; | |
35 | class TFile; | |
36 | class TH1; | |
37 | class Quantity; | |
38 | class RingQuantity; | |
39 | class Merge; | |
40 | class FitStatus; | |
41 | class Correlation; | |
42 | class QARing; | |
43 | class QABase; | |
44 | class Global; | |
45 | class THStack; | |
46 | class TLatex; | |
47 | class 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 | */ |
57 | struct QATrender : public QABase | |
58 | { | |
59 | public: | |
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 |