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