Small fix (Mikolaj)
[u/mrichter/AliRoot.git] / MONITOR / AliMonitorHisto.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /* $Id$ */
17
18 ///////////////////////////////////////////////////////////////////////////////
19 //                                                                           //
20 //  This class maintains a histogram that is used to monitor the quality     //
21 //  of the recorded data.                                                    //
22 //  The histogram is created and filled by a sub class of AliMonitor.        //
23 //  It can be compared to a reference histogram. For the comparison a        //
24 //  maximal deviation (in standard deviations) can be specified.             //
25 //  The bins where the maximal deviation is exceeded are drawn in red.       //
26 //                                                                           //
27 ///////////////////////////////////////////////////////////////////////////////
28
29
30 #include <TH2.h>
31 #include <TMath.h>
32 #include <TProfile.h>
33 #include <TVirtualPad.h>
34
35 #include "AliLog.h"
36
37 #include "AliMonitorHisto.h"
38
39
40 ClassImp(AliMonitorHisto) 
41
42
43 Int_t   AliMonitorHisto::fgNHistosMax = 10;
44
45
46 //_____________________________________________________________________________
47 AliMonitorHisto::AliMonitorHisto() :
48   AliMonitorPlot(),
49   fHisto(NULL),
50   fHistoList(),
51   fNHistos(0),
52   fHistoRun(NULL),
53   fHistoDraw(NULL),
54   fHistoRef(NULL),
55   fHistoCompare(NULL),
56   fNorm(kNormNone)
57 {
58 // default contructor
59
60 }
61
62 //_____________________________________________________________________________
63 AliMonitorHisto::AliMonitorHisto(const AliMonitorHisto& histo) :
64   AliMonitorPlot(histo),
65   fHisto(NULL),
66   fHistoList(),
67   fNHistos(histo.fNHistos),
68   fHistoRun(NULL),
69   fHistoDraw(NULL),
70   fHistoRef(NULL),
71   fHistoCompare(NULL),
72   fNorm(histo.fNorm)
73 {
74 // copy constructor
75
76   Bool_t addStatus = TH1::AddDirectoryStatus();
77   TH1::AddDirectory(kFALSE);
78   if (histo.fHisto) fHisto = (TH1*) histo.fHisto->Clone();
79   TObjLink* link = histo.fHistoList.FirstLink();
80   for (Int_t i = 0; i < fNHistos; i++) {
81     fHistoList.Add(link->GetObject()->Clone());
82     link = link->Next();
83   }
84   if (histo.fHistoRun) fHistoRun = (TH1*) histo.fHistoRun->Clone();
85   if (histo.fHistoRef) fHistoRef = (TH1*) histo.fHistoRef->Clone();
86   TH1::AddDirectory(addStatus);
87 }
88
89 //_____________________________________________________________________________
90 AliMonitorHisto& AliMonitorHisto::operator =(const AliMonitorHisto& histo)
91 {
92 // assignment operator
93
94   AliMonitorPlot::operator =(histo);
95
96   Bool_t addStatus = TH1::AddDirectoryStatus();
97   TH1::AddDirectory(kFALSE);
98   fHisto = NULL;
99   if (histo.fHisto) fHisto = (TH1*) histo.fHisto->Clone();
100   fNHistos = histo.fNHistos;
101   TObjLink* link = histo.fHistoList.FirstLink();
102   for (Int_t i = 0; i < fNHistos; i++) {
103     fHistoList.Add(link->GetObject()->Clone());
104     link = link->Next();
105   }
106   fHistoRun = NULL;
107   if (histo.fHistoRun) fHistoRun = (TH1*) histo.fHistoRun->Clone();
108   fHistoDraw = NULL;
109   fHistoRef = NULL;
110   if (histo.fHistoRef) fHistoRef = (TH1*) histo.fHistoRef->Clone();
111   fHistoCompare = NULL;
112   fNorm = histo.fNorm;
113   TH1::AddDirectory(addStatus);
114
115   return *this;
116 }
117
118 //_____________________________________________________________________________
119 AliMonitorHisto::AliMonitorHisto(TH1* histo, ENorm norm) :
120   AliMonitorPlot(histo->GetName(), histo->GetTitle()),
121   fHisto(histo),
122   fHistoList(),
123   fNHistos(0),
124   fHistoRun(NULL),
125   fHistoDraw(NULL),
126   fHistoRef(NULL),
127   fHistoCompare(NULL),
128   fNorm(norm)
129 {
130 // create a monitor histogram from the given histogram
131
132   if (histo->GetDimension() > 2) {
133     AliFatal("3 dimensional histograms are not supported");
134   }
135
136   histo->SetDirectory(NULL);
137   histo->Reset();
138   fHisto->Sumw2();
139   Bool_t addStatus = TH1::AddDirectoryStatus();
140   TH1::AddDirectory(kFALSE);
141   fHistoRun = (TH1*) histo->Clone();
142   TH1::AddDirectory(addStatus);
143 }
144
145 //_____________________________________________________________________________
146 AliMonitorHisto::~AliMonitorHisto()
147 {
148 // delete all histograms
149
150   if (fHisto) delete fHisto;
151   fHistoList.Delete();
152   if (fHistoRun) delete fHistoRun;
153   if (fHistoDraw) delete fHistoDraw;
154   if (fHistoCompare) delete fHistoCompare;
155 }
156
157
158 //_____________________________________________________________________________
159 void AliMonitorHisto::SetReference(TH1* ref)
160 {
161 // set the reference histogram for comparison
162
163   if (fHistoRef) delete fHistoRef;
164   Bool_t addStatus = TH1::AddDirectoryStatus();
165   TH1::AddDirectory(kFALSE);
166   TH1::AddDirectory(addStatus);
167   fHistoRef = (TH1*) ref->Clone();
168   if (fHistoCompare) fHistoCompare->Reset();
169 }
170
171 //_____________________________________________________________________________
172 void AliMonitorHisto::SetReference(AliMonitorPlot* ref)
173 {
174 // set the reference histogram for comparison
175
176   if (!ref->InheritsFrom(AliMonitorHisto::Class())) return;
177   ((AliMonitorHisto*)ref)->GetRun();
178   SetReference(((AliMonitorHisto*)ref)->fHistoDraw);
179 }
180
181
182 //_____________________________________________________________________________
183 void AliMonitorHisto::Fill(Axis_t x)
184 {
185 // fill the monitor histogram
186
187   fHisto->Fill(x);
188 }
189
190 //_____________________________________________________________________________
191 void AliMonitorHisto::Fill(Axis_t x, Axis_t y)
192 {
193 // fill the monitor histogram
194
195   fHisto->Fill(x, y);
196 }
197
198 //_____________________________________________________________________________
199 void AliMonitorHisto::Fill(Axis_t x, Axis_t y, Stat_t w)
200 {
201 // fill the monitor histogram
202
203   if (fHisto->InheritsFrom(TH2::Class())) {
204     ((TH2*)fHisto)->Fill(x, y, w);
205   } else if (fHisto->InheritsFrom(TProfile::Class())) {
206     ((TProfile*)fHisto)->Fill(x, y, w);
207   } else {
208     AliError("trying to fill x and y of a 1 dimensinal histogram");
209     return;
210   }
211 }
212
213 //_____________________________________________________________________________
214 void AliMonitorHisto::ScaleErrorBy(Double_t factor)
215 {
216 // multiply the error of each bin by the given factor
217
218   Int_t yMax = 1; 
219   if (fHisto->GetDimension() > 1) 
220     yMax = fHisto->GetYaxis()->GetNbins();
221   Int_t xMax = fHisto->GetXaxis()->GetNbins();
222   for (Int_t iY = 1; iY <= yMax; iY++) {
223     for (Int_t iX = 1; iX <= xMax; iX++) {
224       Int_t iBin = fHisto->GetBin(iX, iY);
225       fHisto->SetBinError(iBin, factor * fHisto->GetBinError(iBin));
226     }
227   }
228 }
229
230
231 //_____________________________________________________________________________
232 void AliMonitorHisto::Update()
233 {
234 // update the normalized data histogram
235
236   Update(fHisto);
237   fHisto->Reset();
238 }
239
240 //_____________________________________________________________________________
241 void AliMonitorHisto::Update(TH1* histo)
242 {
243 // update the normalized data histogram using the given histo instead of fHisto
244
245   fNumberOfEvents++;
246   while (fNHistos >= fgNHistosMax) {
247     fHistoList.Remove(fHistoList.LastLink());
248     fNHistos--;
249   }
250   Bool_t addStatus = TH1::AddDirectoryStatus();
251   TH1::AddDirectory(kFALSE);
252   fHistoList.AddFirst(histo->Clone());
253   TH1::AddDirectory(addStatus);
254   fNHistos++;
255   fHistoRun->Add(histo);
256   fHisto->Reset();
257 }
258
259 //_____________________________________________________________________________
260 void AliMonitorHisto::Add(AliMonitorPlot* plot)
261 {
262 // merge the given histo to this one
263
264   if (!plot->InheritsFrom(AliMonitorHisto::Class())) return;
265   AliMonitorHisto* histo = (AliMonitorHisto*) plot;
266
267   fNumberOfEvents += histo->fNumberOfEvents;
268   Bool_t addStatus = TH1::AddDirectoryStatus();
269   TH1::AddDirectory(kFALSE);
270   TObjLink* link = histo->fHistoList.LastLink();
271   while (link) {
272     fHistoList.AddFirst(link->GetObject()->Clone());
273     link = link->Prev();
274   }
275   TH1::AddDirectory(addStatus);
276   fNHistos += histo->fNHistos;
277   while (fNHistos > fgNHistosMax) {
278     fHistoList.Remove(fHistoList.LastLink());
279     fNHistos--;
280   }
281   fHistoRun->Add(histo->fHistoRun);
282 }
283
284 //_____________________________________________________________________________
285 void AliMonitorHisto::Reset()
286 {
287 // reset the monitor histogram for a new run
288
289   fHisto->Reset();
290   fHistoList.Delete();
291   fNHistos = 0;
292   fHistoRun->Reset();
293   if (fHistoDraw) delete fHistoDraw;
294   fHistoDraw = NULL;
295   if (fHistoCompare) delete fHistoCompare;
296   fHistoCompare = NULL;
297   fNumberOfEvents = 0;
298 }
299
300 //_____________________________________________________________________________
301 void AliMonitorHisto::ResetList()
302 {
303 // reset the the list of monitor histograms
304
305   fHistoList.Delete();
306   fNHistos = 0;
307 }
308
309
310 //_____________________________________________________________________________
311 void AliMonitorHisto::Scale(Int_t nEvents)
312 {
313 // scale the histogram to the correct normalization
314
315   Double_t scale = 1.;
316   switch (fNorm) {
317   case kNormNone    : scale = 1.; break;
318   case kNormEvents  : scale = 1./nEvents; break;
319   case kNormEntries : scale = ((fHistoDraw->GetEntries() > 0) ? 
320                                1./fHistoDraw->GetEntries() : 1.); break;
321   case kNormIntegral: scale = ((fHistoDraw->Integral() > 0) ? 
322                                1./fHistoDraw->Integral() : 1.); break;
323   }
324   fHistoDraw->Scale(scale);
325 }
326
327 //_____________________________________________________________________________
328 Bool_t AliMonitorHisto::ComparePlot()
329 {
330 // compare the data histogram to the reference histogram
331 // if they deviate by more than fgThreshold standard deviations in a bin,
332 // this bin is set in fHistoCompare and kFALSE is returned
333   
334   if (!fHistoRef) return kTRUE;
335   if (fgThreshold <= 0) return kTRUE;
336   if (!fHistoDraw) {
337     AliWarning("no data histogram available for comparison\ncall DrawEvent, DrawSum or DrawRaw before calling Compare");
338     return kTRUE;
339   }
340   if (fHistoCompare) delete fHistoCompare;
341   Bool_t addStatus = TH1::AddDirectoryStatus();
342   TH1::AddDirectory(kFALSE);
343   fHistoCompare = (TH1*) fHistoDraw->Clone();
344   TH1::AddDirectory(addStatus);
345   fHistoCompare->Reset();
346   Bool_t result = kTRUE;
347
348   Int_t yMax = 1; 
349   if (fHistoDraw->GetDimension() > 1) 
350     yMax = fHistoDraw->GetYaxis()->GetNbins();
351   Int_t xMax = fHistoDraw->GetXaxis()->GetNbins();
352   for (Int_t iY = 1; iY <= yMax; iY++) {
353     for (Int_t iX = 1; iX <= xMax; iX++) {
354       Int_t iBin = fHistoDraw->GetBin(iX, iY);
355       Double_t delta = TMath::Abs(fHistoDraw->GetBinContent(iBin) -
356                                   fHistoRef->GetBinContent(iBin));
357       Double_t errorData = fHistoDraw->GetBinError(iBin);
358       Double_t errorRef = fHistoRef->GetBinError(iBin);
359       Double_t sigma = TMath::Sqrt(errorData*errorData + errorRef*errorRef);
360       if (delta > fgThreshold*sigma) {
361         fHistoCompare->SetBinContent(iBin, fHistoDraw->GetBinContent(iBin));
362         fHistoCompare->SetBinError(iBin, errorData);
363         result = kFALSE;
364       }
365     }
366   }
367
368   return result;
369 }
370
371 //_____________________________________________________________________________
372 Bool_t AliMonitorHisto::GetEvent(Int_t number)
373 {
374 // get the normalized monitor histogram for the "number"th last event
375
376   if (fNHistos == 0) {
377     AliWarning("there are no histograms for single events available");
378     return kFALSE;
379   }
380   if (number > fNHistos) {
381     AliError(Form("requested event number (%d) exceeds range of available events (%d)", 
382                   number, fNHistos));
383     return kFALSE;
384   }
385   if (number <= 0) return kFALSE;
386
387   if (fHistoDraw) delete fHistoDraw;
388   if (fHistoCompare) delete fHistoCompare;
389   fHistoCompare = NULL;
390
391   TObjLink* link = fHistoList.FirstLink();
392   for (Int_t i = 1; i < number; i++) link = link->Next();
393   Bool_t addStatus = TH1::AddDirectoryStatus();
394   TH1::AddDirectory(kFALSE);
395   fHistoDraw = (TH1*) link->GetObject()->Clone();
396   TH1::AddDirectory(addStatus);
397
398   Scale(1);
399   return kTRUE;
400 }
401
402 //_____________________________________________________________________________
403 Bool_t AliMonitorHisto::GetSum(Int_t number)
404 {
405 // get the normalized monitor histogram for the sum of the last 
406 // "number" events
407
408   if (fNHistos == 0) {
409     AliWarning("there are no histograms for single events available");
410     return kFALSE;
411   }
412   if (number > fNHistos) {
413     AliError(Form("requested number of events (%d) exceeds range of available events (%d)\nusing last %d event(s)", 
414                   number, fNHistos, fNHistos));
415     number = fNHistos;
416   }
417   if (number <= 0) return kFALSE;
418
419   if (fHistoDraw) delete fHistoDraw;
420   if (fHistoCompare) delete fHistoCompare;
421   fHistoCompare = NULL;
422
423   TObjLink* link = fHistoList.FirstLink();
424   Bool_t addStatus = TH1::AddDirectoryStatus();
425   TH1::AddDirectory(kFALSE);
426   fHistoDraw = (TH1*) link->GetObject()->Clone();
427   TH1::AddDirectory(addStatus);
428   for (Int_t i = 1; i < number; i++) {
429     link = link->Next();
430     fHistoDraw->Add((TH1*) link->GetObject());
431   }
432
433   Scale(number);
434   return kTRUE;
435 }
436
437 //_____________________________________________________________________________
438 Bool_t AliMonitorHisto::GetRun()
439 {
440 // get the normalized monitor histogram for all monitored events 
441 // of the current run
442
443   if (fHistoDraw) delete fHistoDraw;
444   if (fHistoCompare) delete fHistoCompare;
445   fHistoCompare = NULL;
446
447   Bool_t addStatus = TH1::AddDirectoryStatus();
448   TH1::AddDirectory(kFALSE);
449   fHistoDraw = (TH1*) fHistoRun->Clone();
450   TH1::AddDirectory(addStatus);
451
452   Scale(fNumberOfEvents);
453   return kTRUE;
454 }
455
456 //_____________________________________________________________________________
457 void AliMonitorHisto::DrawPlot()
458 {
459 // draw the histograms
460
461   fHistoDraw->SetMarkerColor(fgColorData);
462   fHistoDraw->SetLineColor(fgColorData);
463   fHistoDraw->SetFillColor(fgColorData);
464   fHistoDraw->DrawCopy();
465
466   if (fHistoRef && fgDrawRef) {
467     char option[256];
468     sprintf(option, "%sSAME", fHistoDraw->GetOption());
469
470     if (fHistoRef->GetMaximum() > fHistoDraw->GetMaximum()) {
471       fHistoDraw->SetMaximum(fHistoRef->GetMaximum() * 1.1);
472     }
473
474     fHistoRef->SetMarkerColor(fgColorRef);
475     fHistoRef->SetLineColor(fgColorRef);
476     fHistoRef->SetFillColor(fgColorRef);
477     fHistoRef->DrawCopy(option);
478
479     fHistoDraw->DrawCopy(option);
480
481     if (fHistoCompare && (fgThreshold > 0)) {
482       fHistoCompare->SetMarkerColor(fgColorCompare);
483       fHistoCompare->SetLineColor(fgColorCompare);
484       fHistoCompare->SetFillColor(fgColorCompare);
485       fHistoCompare->DrawCopy(option);
486     }
487   }
488
489   gPad->Update();
490 }