fad032d53d1c4fe855441a67e4cb95b46876d32c
[u/mrichter/AliRoot.git] / PWGPP / TRD / info / AliTRDtrendingManager.cxx
1 ////////////////////////////////////////////////////////////////////////////
2 //                                                                        //
3 //  Trend Value Manager                                                   //
4 //                                                                        //
5 //  Mediates interaction with DB (OCDB ?!)                                //                                                                      //                                                                        //
6 //  Authors:                                                              //
7 //    Alexandru Bercuci <A.Bercuci@gsi.de>                                //
8 //                                                                        //
9 ////////////////////////////////////////////////////////////////////////////
10
11 #include "TFile.h"
12 #include "TKey.h"
13 #include "TObjArray.h"
14 #include "TH1F.h"
15 #include "TAxis.h"
16 #include "TGraph.h"
17 #include "TLine.h"
18 #include "TCanvas.h"
19 #include "TString.h"
20
21 #include "AliLog.h"
22 #include "AliTRDtrendingManager.h"
23
24 ClassImp(AliTRDtrendingManager)
25
26 AliTRDtrendingManager* AliTRDtrendingManager::fgInstance=NULL;
27 Bool_t AliTRDtrendingManager::fgTerminated = kFALSE;
28
29 //____________________________________________
30 AliTRDtrendingManager* AliTRDtrendingManager::Instance()
31 {
32   //
33   // Singleton implementation
34   // Returns an instance of this class, it is created if neccessary
35   //
36   if (fgTerminated != kFALSE) return NULL;
37
38   if (!fgInstance) fgInstance = new AliTRDtrendingManager();
39
40   return fgInstance;
41 }
42
43 //____________________________________________
44 void AliTRDtrendingManager::Terminate()
45 {
46   //
47   // Singleton implementation
48   // Deletes the instance of this class and sets the terminated flag,
49   // instances cannot be requested anymore
50   // This function can be called several times.
51   //
52   
53   fgTerminated = kTRUE;
54   
55   if (fgInstance != NULL) {
56     if(TFile::Open("TRD.Trend.root", "RECREATE")){
57       if(fEntries) fEntries->Write();
58       gFile->Close();
59     }
60     delete fgInstance; fgInstance = NULL;
61   }
62 }
63
64 //____________________________________________
65 AliTRDtrendingManager::AliTRDtrendingManager() 
66   : TObject()
67   ,fEntries(NULL)
68   ,fValue(NULL)
69 {
70 // Constructor
71 //  fRunRange[0] = 0; fRunRange[1] = AliCDBRunRange::Infinity();
72 }
73
74 //____________________________________________
75 AliTRDtrendingManager::~AliTRDtrendingManager()
76 {
77 // Destructor
78   if(fValue) delete fValue;
79   if(fEntries) delete fEntries;
80 }
81
82 //____________________________________________
83 void AliTRDtrendingManager::AddValue(
84    const Char_t *name
85   ,Double_t mean,Double_t sigm
86   ,const Char_t *title
87   ,const Char_t *responsible
88   ,const Char_t *notifiables
89   ,Char_t **messages
90   )
91 {
92 // Expert Function !!!
93 // Add a trend value to the map already loaded
94 // If no map loaded create a new one from scratch
95 //
96 // class_name : name of the performance task 
97 // name       : name of the value to be trended
98 // title      : description of the value to be trended
99 // messages   : array of alarm messages for each alarm level
100 // responsible: name and email of the responsible person. Format "name/email"
101 // notifiables: name and email of the notifiable persons. Format "name1/email1, name2/email2, etc"
102 //
103
104   if(!fEntries){ // if no trending map defined create one
105     AliDebug(1, "No trending map loaded. Create one from scratch.");
106     fEntries = new TObjArray(50);
107     fEntries->SetOwner();
108     fEntries->SetName("values");
109   }
110
111   if(!(fValue = GetValue(name))){
112     // create new trending value`
113     fValue = new AliTRDtrendValue(name, title?title:"");
114     fValue->Set(mean, sigm);
115     if(messages) for(Int_t ilevel(AliTRDtrendValue::kNlevels); ilevel--;) if(messages[ilevel]) fValue->SetAlarm(ilevel, messages[ilevel]);
116     TObjArray *r(NULL);
117     if(responsible){
118       TString s(responsible);
119       r=s.Tokenize("/");
120       if(r->GetEntriesFast()!=2){
121         AliWarning("Responsible name/email incorrectly formated.");
122       } else {
123         fValue->SetResponsible(((TObjString*)r->At(0))->String().Data(), ((TObjString*)r->At(1))->String().Data());
124       }
125       r->Delete(); delete r;
126     }
127     if(notifiables){
128       TString s(notifiables);
129       TObjArray *n=s.Tokenize(",");
130       for(Int_t in(0); in<TMath::Min(AliTRDtrendValue::kNnotifiable, n->GetEntriesFast()); in++){
131         TString ss(((TObjString*)n->At(in))->String());
132         r=ss.Tokenize("/");
133         if(r->GetEntriesFast()!=2){
134           AliWarning(Form("Notifiable person name/email incorrectly formated for [%s].", ss.Data()));
135         } else {
136           fValue->SetNotifiable(((TObjString*)r->At(0))->String().Data(), ((TObjString*)r->At(1))->String().Data());
137         }
138         r->Delete(); delete r;
139       }
140       n->Delete(); delete n;
141     }
142   }
143
144   fEntries->AddLast(new AliTRDtrendValue(*fValue));
145 }
146
147 //____________________________________________
148 AliTRDtrendValue* AliTRDtrendingManager::GetValue(const Char_t *name)
149 {
150 // Search trend value list by value "name" formatted according to "class_name"
151   if(!fEntries){
152     AliError("No trending map defined.");
153     return NULL;
154   }
155   fValue = (AliTRDtrendValue*)fEntries->FindObject(name);
156   return fValue;
157 }
158
159 //____________________________________________
160 TH1* AliTRDtrendingManager::MakeTrends(const char *fileList, TObjArray *dump)
161 {
162 // Make trends with reference to DB for all trend files in "fileList".
163 // The DB should be loaded
164   if(!fEntries){
165     AliWarning("Trending map undefined");
166     return NULL;
167   }
168   Int_t ntv(fEntries->GetEntries());
169
170   FILE *fp(NULL);
171   if(!(fp= fopen(fileList, "rt"))){
172     AliWarning(Form("Can not open file list \"%s\"", fileList));
173     return NULL;
174   }
175   Int_t *na = new Int_t[ntv]; memset(na, 0, ntv*sizeof(Int_t));
176   Float_t *la = new Float_t[ntv]; memset(la, 0, ntv*sizeof(Float_t));
177   Float_t *lm = new Float_t[ntv]; for(Int_t im(0); im<ntv; im++) lm[im] = 1.e5;
178   Float_t *lM = new Float_t[ntv]; for(Int_t im(0); im<ntv; im++) lM[im] = -1.e5;
179   TGraph **g = new TGraph*[ntv]; memset(g, 0, ntv*sizeof(TGraph*));
180   AliTRDtrendValue *TV(NULL), *tv(NULL);
181   TString sfp; Int_t run[10000], nr(0);
182   while(sfp.Gets(fp)){
183     // guess run no from path. Do we need a more robust approach ?
184     TObjArray *afp=sfp.Tokenize("/");
185     Int_t idx = afp->GetEntries()-2;
186     Int_t rno = ((TObjString*)(*afp)[idx])->GetString().Atoi();
187     afp->Delete(); delete afp;
188     if(!TFile::Open(sfp.Data())) continue;
189
190     run[nr] = rno;
191     for(Int_t it(0); it<ntv; it++){
192       if(!(TV = (AliTRDtrendValue*)fEntries->At(it))) continue;
193       if(!(tv = (AliTRDtrendValue*)gFile->Get(TV->GetName()))) {
194         AliWarning(Form("Missing %09d.%s", rno, TV->GetName()));
195         continue;
196       }
197       if(tv->GetVal()<-998. ||
198          (strstr(TV->GetName(), "TRDcheckDET")&&TMath::Abs(tv->GetVal())<1.e-5)) continue;
199       if(IsRelativeMeanSigma()){
200         (*tv)/=(*TV);
201         la[it]+=tv->GetVal(); na[it]++;
202       } else {
203         if(tv->GetVal()<lm[it]) lm[it]=tv->GetVal();
204         if(tv->GetVal()>lM[it])lM[it]=tv->GetVal();
205       }
206       if(!g[it]){
207         g[it] = new TGraph();
208         g[it]->SetNameTitle(TV->GetName(), TV->GetTitle());
209         g[it]->SetMarkerStyle(4);g[it]->SetMarkerSize(1.2);
210         g[it]->SetLineStyle(2);g[it]->SetLineWidth(1);
211       }
212       g[it]->SetPoint(g[it]->GetN(), nr, tv->GetVal());
213     }
214     nr++;
215   }
216
217   // Draw
218   TH1 *hT = new TH1F("hT", ";#bf{RUN};", nr, -0.5, nr-0.5);
219   TAxis *ax = hT->GetXaxis(); ax->SetTitleOffset(2.6);ax->CenterTitle(); ax->SetBit(TAxis::kLabelsVert);
220   TAxis *ay = hT->GetYaxis(); ay->SetTitleOffset(IsRelativeMeanSigma()?0.4:0.75);ay->CenterTitle(); ay->SetAxisColor(kRed); ay->SetDecimals();
221   for(Int_t ir(0); ir<nr; ir++) ax->SetBinLabel(ir+1, Form("%09d", run[ir]));
222
223   TLine *line(NULL);
224   TCanvas *c = new TCanvas("c", "TRD Trend", 1, 1, 2400, 1000);
225   c->SetLeftMargin(IsRelativeMeanSigma()?0.03666361:0.05685619);
226   c->SetRightMargin(0.005499542);
227   c->SetTopMargin(0.02542373);
228   c->SetBottomMargin(0.1758475);
229   for(Int_t it(0); it<ntv; it++){
230     if(!g[it]) continue;
231     c->Clear();
232     if(IsRelativeMeanSigma()){
233       ay->SetRangeUser(-5, 5);
234       ay->SetTitle(Form("#bf{%s [#sigmau]}", g[it]->GetTitle()));
235       line = new TLine(-0.5, na[it]?(la[it]/na[it]):0., nr-0.5, na[it]?(la[it]/na[it]):0.);
236       line->SetLineColor(kBlue);
237     } else {
238       ay->SetRangeUser(lm[it]-0.1*(lM[it]-lm[it]), lM[it]+0.1*(lM[it]-lm[it]));
239       ay->SetTitle(Form("#bf{%s}", g[it]->GetTitle()));
240     }
241     hT->Draw("p");
242     g[it]->Draw("pl");
243     if(line) line->Draw();
244     c->Modified(); c->Update(); c->SaveAs(Form("Trend_%s.gif", g[it]->GetName()));
245     if(dump) dump->Add(g[it]);
246     else delete g[it];
247     if(line) delete line;
248   }
249   delete [] g;
250   delete [] lm;
251   delete [] lM;
252   delete [] la;
253   delete [] na;
254   return hT;
255 }
256
257 //____________________________________________
258 Bool_t AliTRDtrendingManager::ModifyValue(
259   const Char_t *name
260   ,const Char_t *title
261   ,Double_t mean, Double_t sgm
262   ,Char_t **messages
263   ,const Char_t *responsible
264   ,const Char_t *notifiables
265   )
266 {
267 // Expert Function !!!
268 // Modify a trend value in the map already loaded
269 // see function AddValue() for explanation of input format. 
270
271   if(!fEntries){
272     AliError("No trending map loaded.");
273     return kFALSE;
274   }
275   AliWarning("*** EXPERT FUNCTION *** This function is modifying one trending value to the current DB. Continue if you know what yout do!");
276
277   if(!GetValue(name)){
278     AliError(Form("Missing trending value %s", name));
279     return kFALSE;
280   }  
281   
282   fValue->SetTitle(title);
283   fValue->Set(mean, sgm);
284   if(messages){ 
285     for(Int_t ilevel(AliTRDtrendValue::kNlevels); ilevel--;) fValue->SetAlarm(ilevel, messages[ilevel]);
286   }
287   TString s;
288   TObjArray *r(NULL);
289   if(responsible){ 
290     s=responsible;
291     r=s.Tokenize("/");
292     if(r->GetEntriesFast()!=2){ 
293       AliWarning("Responsible name/email incorrectly formated.");
294     } else { 
295       fValue->SetResponsible(((TObjString*)r->At(0))->String().Data(), ((TObjString*)r->At(1))->String().Data());
296     }
297     r->Delete(); delete r;
298   }
299   if(notifiables){
300     s=notifiables;
301     TObjArray *n=s.Tokenize(",");
302     for(Int_t in(0); in<TMath::Min(AliTRDtrendValue::kNnotifiable, n->GetEntriesFast()); in++){
303       TString ss(((TObjString*)n->At(in))->String());
304       r=ss.Tokenize("/");
305       if(r->GetEntriesFast()!=2){ 
306         AliWarning(Form("Notifiable person name/email incorrectly formated for [%s].", ss.Data()));
307       } else { 
308         fValue->SetNotifiable(((TObjString*)r->At(0))->String().Data(), ((TObjString*)r->At(1))->String().Data());
309       }
310       r->Delete(); delete r;
311     }
312     n->Delete(); delete n;
313   }
314   return kTRUE;
315 }
316
317 //____________________________________________
318 void AliTRDtrendingManager::Print(Option_t *o) const
319 {
320 // Dump trend value list
321   if(!fEntries){
322     AliError("No trending map available.");
323     return;
324   }
325
326   for(Int_t iv(0); iv<fEntries->GetEntriesFast(); iv++){
327     ((AliTRDtrendValue*)fEntries->At(iv))->Print(o);
328   }
329 }
330
331 //____________________________________________
332 void AliTRDtrendingManager::Load(const char *fn)
333 {
334 // Load TRD trending DB from $ALICE_ROOT/PWGPP/TRD/data.
335
336   AliDebug(1, "Loading TRD trending ...");
337   if(!TFile::Open(fn)) return;
338
339   TList *tvList = gFile->GetListOfKeys(); TIterator *iter(tvList->MakeIterator()); AliTRDtrendValue *tv(NULL);
340   fEntries = new TObjArray(tvList->GetEntries());
341   fEntries->SetOwner();
342   TKey *ktv(NULL);
343   while((ktv = (TKey*)iter->Next())){
344     tv = (AliTRDtrendValue*)gFile->Get(ktv->GetName());
345     fEntries->AddLast(new AliTRDtrendValue(*tv));
346   }
347 }