Adding include files where needed for latest ROOT
[u/mrichter/AliRoot.git] / MONITOR / AliMonitorTrend.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 plot for the evolution of a value that is used    //
21 //  tomonitor the quality of the recorded data.                              //
22 //  The trendgram is created and filled by a sub class of AliMonitor.        //
23 //  It can be compared to a reference trendgram. 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 <TH1.h>
31 #include <TLine.h>
32 #include <TMath.h>
33 #include <TVirtualPad.h>
34
35 #include "AliLog.h"
36
37 #include "AliMonitorTrend.h"
38
39
40 ClassImp(AliMonitorTrend) 
41
42
43 Int_t AliMonitorTrend::fgIncSize = 10;
44
45
46 //_____________________________________________________________________________
47 AliMonitorTrend::AliMonitorTrend():
48   AliMonitorPlot(),
49   fLabel(),
50   fMin(0),
51   fMax(0),
52   fData(),
53   fHistoDraw(NULL),
54   fRefMean(0),
55   fRefSigma(-1),
56   fHistoCompare(NULL)
57 {
58 // default contructor
59
60 }
61
62 //_____________________________________________________________________________
63 AliMonitorTrend::AliMonitorTrend(const AliMonitorTrend& trend) :
64   AliMonitorPlot(trend),
65   fLabel(trend.fLabel),
66   fMin(trend.fMin),
67   fMax(trend.fMax),
68   fData(trend.fData),
69   fHistoDraw(NULL),
70   fRefMean(trend.fRefMean),
71   fRefSigma(trend.fRefSigma),
72   fHistoCompare(NULL)
73 {
74 // copy constructor
75
76 }
77
78 //_____________________________________________________________________________
79 AliMonitorTrend& AliMonitorTrend::operator =(const AliMonitorTrend& trend)
80 {
81 // assignment operator
82
83   AliMonitorPlot::operator =(trend);
84
85   fLabel = trend.fLabel;
86   fMin = trend.fMin;
87   fMax = trend.fMax;
88   trend.fData.Copy(fData);
89
90   fHistoDraw = NULL;
91   fRefMean = trend.fRefMean;
92   fRefSigma = trend.fRefSigma;
93   fHistoCompare = NULL;
94
95   return *this;
96 }
97
98 //_____________________________________________________________________________
99 AliMonitorTrend::AliMonitorTrend(const char* name, const char* title,
100                   const char* label, Double_t min, Double_t max) :
101   AliMonitorPlot(name, title),
102   fLabel(label),
103   fMin(min),
104   fMax(max),
105   fData(),
106   fHistoDraw(NULL),
107   fRefMean(0),
108   fRefSigma(0),
109   fHistoCompare(NULL)
110 {
111 // create a monitor trend
112
113 }
114
115 //_____________________________________________________________________________
116 AliMonitorTrend::~AliMonitorTrend()
117 {
118 // delete all histograms
119
120   if (fHistoDraw) delete fHistoDraw;
121   if (fHistoCompare) delete fHistoCompare;
122 }
123
124
125 //_____________________________________________________________________________
126 void AliMonitorTrend::SetReference(TH1* ref)
127 {
128 // set the reference trend for comparison
129
130   Int_t n = ref->GetXaxis()->GetNbins();
131   if (n <= 0) return;
132
133   Double_t sum = 0;
134   Double_t sum2 = 0;
135   for (Int_t i = 1; i <= n; i++) {
136     sum += ref->GetBinContent(i);
137     sum2 += ref->GetBinContent(i) * ref->GetBinContent(i);
138   }
139
140   fRefMean = sum / n;
141   fRefSigma = TMath::Sqrt(sum2 - sum*sum/n) / n;
142 }
143
144 //_____________________________________________________________________________
145 void AliMonitorTrend::SetReference(AliMonitorPlot* ref)
146 {
147 // set the reference trendgram for comparison
148
149   if (!ref->InheritsFrom(AliMonitorTrend::Class())) return;
150   fRefMean = ((AliMonitorTrend*)ref)->GetMean();
151   fRefSigma = ((AliMonitorTrend*)ref)->GetSigma();
152 }
153
154
155 //_____________________________________________________________________________
156 void AliMonitorTrend::Fill(Double_t x)
157 {
158 // add a value to the monitor trend
159
160   if (fNumberOfEvents >= fData.GetSize()) {
161     fData.Set(fNumberOfEvents + fgIncSize);
162   }
163   fData[fNumberOfEvents] = x;
164 }
165
166
167 //_____________________________________________________________________________
168 void AliMonitorTrend::Update()
169 {
170 // update
171
172   fNumberOfEvents++;
173 }
174
175 //_____________________________________________________________________________
176 void AliMonitorTrend::Add(AliMonitorPlot* plot)
177 {
178 // merge the given trend to this one
179
180   if (!plot->InheritsFrom(AliMonitorTrend::Class())) return;
181   AliMonitorTrend* trend = (AliMonitorTrend*) plot;
182
183   Int_t numberOfEvents = fNumberOfEvents + trend->fNumberOfEvents;
184   if (numberOfEvents >=  fData.GetSize()) {
185     fData.Set(numberOfEvents + fgIncSize);
186   }
187   for (Int_t i = 0; i < trend->fNumberOfEvents; i++) {
188     fData[fNumberOfEvents + i] = trend->fData[i];
189   }
190   fNumberOfEvents = numberOfEvents;
191 }
192
193 //_____________________________________________________________________________
194 void AliMonitorTrend::Reset()
195 {
196 // reset the monitor trend for a new run
197
198   fData.Set(fgIncSize);
199   if (fHistoDraw) delete fHistoDraw;
200   fHistoDraw = NULL;
201   if (fHistoCompare) delete fHistoCompare;
202   fHistoCompare = NULL;
203   fNumberOfEvents = 0;
204 }
205
206 //_____________________________________________________________________________
207 void AliMonitorTrend::ResetList()
208 {
209 // reset the the list of monitor histograms
210 // (not applicable for trend)
211
212 }
213
214
215 //_____________________________________________________________________________
216 Bool_t AliMonitorTrend::ComparePlot()
217 {
218 // compare the data trend to the reference
219 // if they deviate by more than fgThreshold standard deviations in a bin,
220 // this bin is set in fHistoCompare and kFALSE is returned
221   
222   if (fRefSigma < 0) return kTRUE;
223   if (fgThreshold <= 0) return kTRUE;
224   if (!fHistoDraw) {
225     AliWarning("no data trend available for comparison\ncall DrawSum or DrawRaw before calling Compare");
226     return kTRUE;
227   }
228
229   Int_t nBins = fHistoDraw->GetXaxis()->GetNbins();
230   if (fHistoCompare) delete fHistoCompare;
231   fHistoCompare = CreateHisto(nBins);
232   fHistoCompare->Reset();
233   fHistoCompare->SetOption("P");
234   fHistoCompare->SetMarkerStyle(kFullCircle);
235   fHistoCompare->SetFillStyle(0);
236   Bool_t result = kTRUE;
237
238   for (Int_t iBin = 1; iBin <= nBins; iBin++) {
239     Double_t delta = TMath::Abs(fHistoDraw->GetBinContent(iBin) - fRefMean);
240     if (delta > fgThreshold*fRefSigma) {
241       fHistoCompare->SetBinContent(iBin, fHistoDraw->GetBinContent(iBin));
242       result = kFALSE;
243     }
244   }
245
246   return result;
247 }
248
249 //_____________________________________________________________________________
250 Bool_t AliMonitorTrend::GetEvent(Int_t)
251 {
252 // there is no single event trend
253
254 //  Info("GetEvent", "there is no trend for single events available");
255   return kFALSE;
256 }
257
258 //_____________________________________________________________________________
259 Bool_t AliMonitorTrend::GetSum(Int_t number)
260 {
261 // get the monitor trend for the last  "number" events
262
263   if (number > fNumberOfEvents) {
264     AliError(Form("requested number of events (%d) exceeds range of available events (%d)\nusing last %d event(s)", 
265           number, fNumberOfEvents, fNumberOfEvents));
266     number = fNumberOfEvents;
267   }
268   if (number <= 0) return kFALSE;
269
270   if (fHistoDraw) delete fHistoDraw;
271   if (fHistoCompare) delete fHistoCompare;
272   fHistoCompare = NULL;
273
274   fHistoDraw = CreateHisto(number);
275   return kTRUE;
276 }
277
278 //_____________________________________________________________________________
279 Bool_t AliMonitorTrend::GetRun()
280 {
281 // get the monitor trend for all monitored events of the current run
282
283   if (fHistoDraw) delete fHistoDraw;
284   if (fHistoCompare) delete fHistoCompare;
285   fHistoCompare = NULL;
286   if (fNumberOfEvents <= 0) return kFALSE;
287
288   fHistoDraw = CreateHisto(fNumberOfEvents);
289   return kTRUE;
290 }
291
292 //_____________________________________________________________________________
293 void AliMonitorTrend::DrawPlot()
294 {
295 // draw the trendgrams
296
297   fHistoDraw->SetMarkerColor(fgColorData);
298   fHistoDraw->SetLineColor(fgColorData);
299   fHistoDraw->SetLineWidth(2);
300   fHistoDraw->DrawCopy();
301
302   if ((fRefSigma > 0) && fgDrawRef) {
303     if ((fRefMean+fRefSigma > fHistoDraw->GetMaximum()) && !(fMax > fMin)) {
304       fHistoDraw->SetMaximum(fRefMean+fRefSigma * 1.1);
305     }
306
307     Double_t xMin = fHistoDraw->GetXaxis()->GetXmin();
308     Double_t xMax = fHistoDraw->GetXaxis()->GetXmax();
309     TLine* mean = new TLine(xMin, fRefMean, xMax, fRefMean);
310     mean->SetLineColor(fgColorRef);
311     mean->SetLineWidth(2);
312     mean->Draw();
313     TLine* high = new TLine(xMin, fRefMean+fRefSigma, 
314                             xMax, fRefMean+fRefSigma);
315     high->SetLineColor(fgColorRef);
316     high->SetLineWidth(2);
317     high->SetLineStyle(2);
318     high->Draw();
319     TLine* low = new TLine(xMin, fRefMean-fRefSigma, 
320                            xMax, fRefMean-fRefSigma);
321     low->SetLineColor(fgColorRef);
322     low->SetLineWidth(2);
323     low->SetLineStyle(2);
324     low->Draw();
325
326 //    char option[256];
327 //    sprintf(option, "%sSAME", fHistoDraw->GetOption());
328 //    fHistoDraw->DrawCopy(option);
329
330     if (fHistoCompare && (fgThreshold > 0)) {
331       char option[256];
332       sprintf(option, "%sSAME", fHistoCompare->GetOption());
333       fHistoCompare->SetMarkerColor(fgColorCompare);
334       fHistoCompare->SetLineColor(fgColorCompare);
335       fHistoCompare->SetLineWidth(2);
336       fHistoCompare->DrawCopy(option);
337     }
338   }
339
340   gPad->Update();
341 }
342
343
344 //_____________________________________________________________________________
345 TH1* AliMonitorTrend::CreateHisto(Int_t nBins)
346 {
347 // create a histogram for a trend plot with the last nBin entries
348
349   TH1* result = new TH1D(GetName(), GetTitle(), nBins, -nBins-0.5, -0.5);
350   result->GetXaxis()->SetTitle("N_{event}");
351   result->GetYaxis()->SetTitle(fLabel.Data());
352   if (fMax > fMin) {
353     result->SetMinimum(fMin);
354     result->SetMaximum(fMax);
355   }
356   result->SetOption("L");
357
358   Double_t sum = 0;
359   Double_t sum2 = 0;
360   for (Int_t i = 0; i < nBins; i++) {
361     Double_t data = fData[fNumberOfEvents-1-i];
362     sum += data;
363     sum2 += data * data;
364     result->SetBinContent(nBins-i, data);
365   }
366   Stat_t stats[4];
367   stats[0] = nBins;
368   stats[1] = nBins * nBins;
369   stats[2] = sum;
370   stats[3] = sum2;
371   result->PutStats(stats);
372
373   return result;
374 }
375
376 //_____________________________________________________________________________
377 Double_t AliMonitorTrend::GetMean() const
378 {
379 // get the mean value
380
381   if (fNumberOfEvents <= 0) return 0;
382
383   Double_t sum = 0;
384   for (Int_t i = 0; i < fNumberOfEvents; i++) {
385     sum += fData[i];
386   }
387   return sum / fNumberOfEvents;
388 }
389
390 //_____________________________________________________________________________
391 Double_t AliMonitorTrend::GetSigma() const
392 {
393 // get the rms value
394
395   if (fNumberOfEvents <= 0) return 0;
396
397   Double_t sum = 0;
398   Double_t sum2 = 0;
399   for (Int_t i = 0; i < fNumberOfEvents; i++) {
400     sum += fData[i];
401     sum2 += fData[i] * fData[i];
402   }
403   return TMath::Sqrt(sum2 - sum*sum/fNumberOfEvents) / fNumberOfEvents;
404 }
405