f77dddbf503e4befcac8e7c499e55b7690e9fdf6
[u/mrichter/AliRoot.git] / STEER / AliQA.cxx
1
2 /**************************************************************************
3  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4  *                                                                        *
5  * Author: The ALICE Off-line Project.                                    *
6  * Contributors are mentioned in the code where appropriate.              *
7  *                                                                        *
8  * Permission to use, copy, modify and distribute this software and its   *
9  * documentation strictly for non-commercial purposes is hereby granted   *
10  * without fee, provided that the above copyright notice appears in all   *
11  * copies and that both the copyright notice and this permission notice   *
12  * appear in the supporting documentation. The authors make no claims     *
13  * about the suitability of this software for any purpose. It is          *
14  * provided "as is" without express or implied warranty.                  *
15  **************************************************************************/
16 /* $Id$ */
17
18 //////////////////////////////////////////////////////////////////////////////
19 //
20 // Quality Assurance Object//_________________________________________________________________________
21 // Quality Assurance object. The QA status is held in one word per detector,
22 // each bit corresponds to a different status.
23 // bit 0-3  : QA raised during simulation      (SIM)
24 // bit 4-7  : QA raised during reconstruction  (REC)
25 // bit 8-11 : QA raised during ESD checking    (ESD)
26 // bit 12-15: QA raised during analysis        (ANA)
27 // Each of the 4 bits corresponds to a severity level of increasing importance
28 // from lower to higher bit (INFO, WARNING, ERROR, FATAL)
29 //
30 //*-- Yves Schutz CERN, July 2007 
31 //////////////////////////////////////////////////////////////////////////////
32
33
34 // --- ROOT system ---
35 #include <TFile.h>
36 #include <TSystem.h>
37 #include <TROOT.h>
38
39 // --- Standard library ---
40
41 // --- AliRoot header files ---
42 #include "AliLog.h"
43 #include "AliQA.h"
44
45
46 ClassImp(AliQA)
47 AliQA    * AliQA::fgQA                   = 0x0 ;
48 TFile    * AliQA::fgQADataFile           = 0x0 ;   
49 TString    AliQA::fgQADataFileName       = "QA" ;  // will transform into Det.QA.run.cycle.root  
50 TFile    * AliQA::fgQARefFile            = 0x0 ;   
51 TString    AliQA::fgQARefDirName             = "" ; 
52 TString    AliQA::fgQARefFileName        = "QA.root" ;
53 TFile    * AliQA::fgQAResultFile         = 0x0 ;  
54 TString    AliQA::fgQAResultDirName      = "" ;  
55 TString    AliQA::fgQAResultFileName     = "QA.root" ; 
56 TString    AliQA::fgDetNames[]           = {"ITS", "TPC", "TRD", "TOF", "PHOS", "HMPID", "EMCAL", "MUON", "FMD",
57                                                                                     "ZDC", "PMD", "T0", "VZERO", "ACORDE", "HLT"} ;   
58 TString       AliQA::fgTaskNames[]       = {"Raws", "Hits", "SDigits", "Digits", "RecPoints", "TrackSegments", "RecParticles", "ESDs"} ;   
59 const TString AliQA::fkgLabLocalFile     = "file://"  ; 
60 const TString AliQA::fkgLabLocalOCDB     = "local://" ;  
61 const TString AliQA::fkgLabAliEnOCDB     = "alien://" ;  
62 const TString AliQA::fkgRefFileName      = "QA.root" ; 
63 const TString AliQA::fkgQAName           = "QA"  ; 
64 const TString AliQA::fkgRefOCDBDirName   = "Ref"  ; 
65 TString AliQA::fkgRefDataDirName   = "Data"  ; 
66 const TString AliQA::fkgQARefOCDBDefault = "alien://folder=/alice/QA/20"  ; 
67 //____________________________________________________________________________
68 AliQA::AliQA() : 
69   TNamed("", ""), 
70   fNdet(kNDET), 
71   fQA(new ULong_t[fNdet]), 
72   fDet(kNULLDET),
73   fTask(kNULLTASK)
74         
75 {
76   // default constructor
77   // beware singleton: not to be used
78   
79   for (Int_t index = 0 ; index < fNdet ; index++) 
80         fQA[index] = 0 ; 
81 }
82
83 //____________________________________________________________________________
84 AliQA::AliQA(const AliQA& qa) :
85   TNamed(qa),
86   fNdet(qa.fNdet), 
87   fQA(qa.fQA), 
88   fDet(qa.fDet),
89   fTask(qa.fTask)
90
91   // cpy ctor
92 }
93
94 //_____________________________________________________________________________
95 AliQA& AliQA::operator = (const AliQA& qa)
96 {
97 // assignment operator
98
99   this->~AliQA();
100   new(this) AliQA(qa);
101   return *this;
102 }
103
104 //_______________________________________________________________
105 AliQA::AliQA(const DETECTORINDEX_t det) :
106   TNamed("QA", "Quality Assurance status"),
107   fNdet(kNDET),  
108   fQA(new ULong_t[fNdet]), 
109   fDet(det),
110   fTask(kNULLTASK) 
111 {
112   // constructor to be used
113   if (! CheckRange(det) ) {
114     fDet = kNULLDET ; 
115     return ;
116   } 
117   Int_t index ; 
118   for (index = 0; index < fNdet; index++) 
119     fQA[index] = 0 ; 
120 }
121   
122 //_______________________________________________________________
123 AliQA::AliQA(const ALITASK_t tsk) :
124   TNamed("QA", "Quality Assurance status"), 
125   fNdet(kNDET),
126   fQA(new ULong_t[fNdet]), 
127   fDet(kNULLDET),
128   fTask(tsk)
129 {
130         AliInfo(Form("TTTTTTTTTTTTTTTTTTTTTTT %d", tsk)) ;      
131   // constructor to be used in the AliRoot module (SIM, REC, ESD or ANA)
132   if (! CheckRange(tsk) ) {
133     fTask = kNULLTASK ; 
134     return ;
135   } 
136   Int_t index ; 
137   for (index = 0; index < fNdet; index++) 
138     fQA[index] = 0 ; 
139 }
140
141 //____________________________________________________________________________
142 AliQA::~AliQA() 
143 {
144   // dtor  
145   delete[] fQA ;
146 }
147
148 //_______________________________________________________________
149 void AliQA::Close() 
150 {
151         // close the open files
152         if (fgQADataFile) 
153                 if (fgQADataFile->IsOpen())
154                         fgQADataFile->Close() ; 
155         if (fgQAResultFile) 
156                 if (fgQAResultFile->IsOpen()) 
157                         fgQAResultFile->Close() ;
158         if (fgQARefFile)
159                 if (fgQARefFile->IsOpen())
160                         fgQARefFile->Close() ; 
161
162
163 //_______________________________________________________________
164 const Bool_t AliQA::CheckFatal() const
165 {
166   // check if any FATAL status is set
167   Bool_t rv = kFALSE ;
168   Int_t index ;
169   for (index = 0; index < kNDET ; index++)
170     rv = rv || IsSet(DETECTORINDEX_t(index), fTask, kFATAL) ;
171   return rv ;
172 }
173
174 //_______________________________________________________________
175 const Bool_t AliQA::CheckRange(DETECTORINDEX_t det) const
176
177   // check if detector is in given detector range: 0-kNDET
178
179   Bool_t rv = ( det < 0 || det > kNDET )  ? kFALSE : kTRUE ;
180   if (!rv)
181     AliFatal(Form("Detector index %d is out of range: 0 <= index <= %d", det, kNDET)) ;
182   return rv ;
183 }
184
185 //_______________________________________________________________
186 const Bool_t AliQA::CheckRange(ALITASK_t task) const
187
188   // check if task is given taskk range: 0:kNTASK
189   Bool_t rv = ( task < kRAW || task > kNTASK )  ? kFALSE : kTRUE ;
190   if (!rv)
191     AliFatal(Form("Module index %d is out of range: 0 <= index <= %d", task, kNTASK)) ;
192   return rv ;
193 }
194
195 //_______________________________________________________________
196 const Bool_t AliQA::CheckRange(QABIT_t bit) const
197
198   // check if bit is in given bit range: 0-kNBit
199
200   Bool_t rv = ( bit < 0 || bit > kNBIT )  ? kFALSE : kTRUE ;
201   if (!rv)
202     AliFatal(Form("Status bit %d is out of range: 0 <= bit <= %d", bit, kNBIT)) ;
203   return rv ;
204 }
205
206
207
208 //_______________________________________________________________
209 const char * AliQA::GetAliTaskName(ALITASK_t tsk)
210 {
211   // returns the char name corresponding to module index
212   TString tskName ;
213   switch (tsk) {
214   case kNULLTASK:
215     break ; 
216   case kRAW:
217     tskName = "RAW" ;
218     break ;  
219   case kSIM:
220     tskName = "SIM" ;
221     break ;
222   case kREC:
223     tskName = "REC" ;
224     break ;
225   case kESD:
226     tskName = "ESD" ;
227     break ;
228   case kANA:
229     tskName = "ANA" ;
230     break ;
231   default:
232     tsk = kNULLTASK ; 
233     break ;
234   }
235   return tskName.Data() ;
236 }
237
238 //_______________________________________________________________
239 const char * AliQA::GetDetName(Int_t det) 
240 {
241         // returns the detector name corresponding to a given index (needed in a loop)
242         
243         if ( det >= 0 &&  det < kNDET) 
244                 return (fgDetNames[det]).Data() ; 
245         else 
246                 return NULL ; 
247 }
248
249 //_______________________________________________________________
250 const AliQA::DETECTORINDEX_t AliQA::GetDetName(const char * name) 
251 {
252         // returns the detector index corresponding to a given name
253         TString sname(name) ; 
254         DETECTORINDEX_t rv = kNULLDET ; 
255         for (Int_t det = 0; det < kNDET ; det++) {
256                 if ( GetDetName(det) == sname ) {
257                         rv = DETECTORINDEX_t(det) ; 
258                         break ; 
259                 }
260         }
261         return rv ;             
262 }
263
264 //_______________________________________________________________
265 TFile * AliQA::GetQADataFile(const char * name, const Int_t run, const Int_t cycle) 
266 {
267   // opens the file to store the detectors Quality Assurance Data Maker results
268         const char * temp = Form("%s.%s.%d.%d.root", name, fgQADataFileName.Data(), run, cycle) ; 
269         TString opt ; 
270         if (! fgQADataFile ) {     
271                 if  (gSystem->AccessPathName(temp))
272                         opt = "NEW" ;
273                 else 
274                         opt = "UPDATE" ; 
275                 fgQADataFile = TFile::Open(temp, opt.Data()) ;
276         } else {
277                 if ( strcmp(temp, fgQADataFile->GetName()) != 0 ) {
278                         fgQADataFile = dynamic_cast<TFile *>(gROOT->FindObject(temp)) ; 
279                         if ( !fgQADataFile ) {
280                                 if  (gSystem->AccessPathName(temp))
281                                         opt = "NEW" ;
282                                 else 
283                                         opt = "UPDATE" ; 
284                                 fgQADataFile = TFile::Open(temp, opt.Data()) ;
285                         }
286                 }
287   }
288         return fgQADataFile ;
289
290
291 //_____________________________________________________________________________
292 TFile * AliQA::GetQADataFile(const char * fileName)
293 {
294   // Open if necessary the Data file and return its pointer
295
296   if (!fgQADataFile) 
297         if (!fileName) 
298                 fileName = AliQA::GetQADataFileName() ; 
299         if  (!gSystem->AccessPathName(fileName)) {
300                 fgQADataFile =  TFile::Open(fileName) ;
301         } else {
302                 printf("File %s not found", fileName) ;
303                 exit(1) ;  
304         }
305   return fgQADataFile ; 
306 }
307
308 //_______________________________________________________________
309 TFile * AliQA::GetQAResultFile() 
310 {
311   // opens the file to store the  Quality Assurance Data Checker results
312         if (fgQAResultFile) 
313                 fgQAResultFile->Close() ; 
314         fgQAResultFile = 0x0 ; 
315 //      if (!fgQAResultFile) { 
316                 TString dirName(fgQAResultDirName) ; 
317                 if ( dirName.Contains(fkgLabLocalFile)) 
318                         dirName.ReplaceAll(fkgLabLocalFile, "") ;
319                 TString fileName(dirName + fgQAResultFileName) ; 
320                 TString opt("") ; 
321                 if ( !gSystem->AccessPathName(fileName) )
322                         opt = "UPDATE" ; 
323                 else { 
324                         if ( gSystem->AccessPathName(dirName) )
325                                 gSystem->mkdir(dirName) ; 
326                         opt = "NEW" ; 
327                 }
328                 fgQAResultFile = TFile::Open(fileName, opt) ;   
329 //      }
330         
331         return fgQAResultFile ;
332 }
333
334 //_______________________________________________________________
335 const Bool_t AliQA::IsSet(DETECTORINDEX_t det, ALITASK_t tsk, QABIT_t bit) const
336 {
337   // Checks is the requested bit is set
338
339   CheckRange(det) ; 
340   CheckRange(tsk) ;
341   CheckRange(bit) ;
342
343   ULong_t offset = Offset(tsk) ;
344   ULong_t status = GetStatus(det) ;
345   offset+= bit ;
346   status = (status & 1 << offset) != 0 ;
347   return status ;
348 }
349
350 //_______________________________________________________________
351 AliQA * AliQA::Instance()
352 {
353   // Get an instance of the singleton.
354   // Object must have been instantiated with Instance(ALITASK) first
355
356   return fgQA ;
357 }
358
359 //_______________________________________________________________
360 AliQA * AliQA::Instance(const DETECTORINDEX_t det)
361 {
362   // Get an instance of the singleton. The only authorized way to call the ctor
363   
364   if ( ! fgQA) {
365     TFile * f = GetQAResultFile() ; 
366         fgQA = dynamic_cast<AliQA *>(f->Get("QA")) ; 
367     if ( ! fgQA ) 
368                 fgQA = new AliQA(det) ;
369   }             
370   fgQA->Set(det) ;
371   return fgQA ;
372 }
373
374 //_______________________________________________________________
375 AliQA * AliQA::Instance(const ALITASK_t tsk)
376 {
377   // get an instance of the singleton.
378
379   if ( ! fgQA)
380     switch (tsk) {
381     case kNULLTASK:
382       break ;
383         case kRAW:
384       fgQA = new AliQA(tsk) ;
385       break ;
386         case kSIM:
387       fgQA = new AliQA(tsk) ;
388       break ;
389     case kREC:
390       printf("fgQA = gAlice->GetQA()") ;
391       break ;
392     case kESD:
393       printf("fgQA = dynamic_cast<AliQA *> (esdFile->Get(\"QA\")") ;
394       break ;
395     case kANA:
396       printf("fgQA = dynamic_cast<AliQA *> (esdFile->Get(\"QA\")") ;
397       break ;
398     case kNTASK:
399       break ;
400     }
401   if (fgQA) 
402     fgQA->Set(tsk) ;
403   return fgQA ;
404 }
405
406 //_______________________________________________________________
407 AliQA *  AliQA::Instance(const TASKINDEX_t tsk) 
408 {
409         // get an instance of the singleton.
410         
411         ALITASK_t index = kNULLTASK ; 
412
413         if ( tsk == kRAWS )
414                 index = kRAW ;
415         else if (tsk < kDIGITS)
416                 index = kSIM ;
417         else if (tsk < kRECPARTICLES)
418                 index = kREC ; 
419         else if (tsk == kESDS) 
420                 index = kESD ; 
421
422         return Instance(index) ; 
423 }
424
425 //_______________________________________________________________
426 const ULong_t AliQA::Offset(ALITASK_t tsk) const
427 {
428   // Calculates the bit offset for a given module (SIM, REC, ESD, ANA)
429
430   CheckRange(tsk) ; 
431
432   ULong_t offset = 0 ;
433   switch (tsk) {
434   case kNULLTASK:
435     break ;
436   case kRAW:
437     offset+= 0 ;
438     break ;
439   case kSIM:
440     offset+= 4 ;
441     break ;
442   case kREC:
443     offset+= 8 ;
444     break ;
445   case kESD:
446     offset+= 12 ;
447     break ;
448   case kANA:
449     offset+= 16 ;
450     break ;
451   case kNTASK:
452     break ;
453   }
454
455   return offset ;
456 }
457
458 //_______________________________________________________________
459 void AliQA::Set(QABIT_t bit)
460 {
461   // Set the status bit of the current detector in the current module
462   
463   SetStatusBit(fDet, fTask, bit) ;
464 }
465
466 //_____________________________________________________________________________
467 void AliQA::SetQARefStorage(const char * name)
468 {
469         // Set the root directory where the QA reference data are stored
470
471         fgQARefDirName = name ; 
472         if ( fgQARefDirName.Contains(fkgLabLocalFile) )
473                 fgQARefFileName =  fkgRefFileName ; 
474         else if ( fgQARefDirName.Contains(fkgLabLocalOCDB) )
475                 fgQARefFileName =  fkgQAName ; 
476         else if ( fgQARefDirName.Contains(fkgLabAliEnOCDB) )
477                 fgQARefFileName =  fkgQAName ; 
478
479   else {
480           printf("ERROR: %s is an invalid storage definition\n", name) ; 
481           fgQARefDirName  = "" ; 
482           fgQARefFileName = "" ; 
483   }     
484         TString tmp(fgQARefDirName) ; // + fgQARefFileName) ;
485         printf("AliQA::SetQARefDir: QA references are in  %s\n", tmp.Data() ) ;
486 }
487
488 //_____________________________________________________________________________
489 void AliQA::SetQAResultDirName(const char * name)
490 {
491   // Set the root directory where to store the QA status object
492
493   fgQAResultDirName.Prepend(name) ; 
494   printf("AliQA::SetQAResultDirName: QA results are in  %s\n", fgQAResultDirName.Data()) ;
495   if ( fgQAResultDirName.Contains(fkgLabLocalFile)) 
496     fgQAResultDirName.ReplaceAll(fkgLabLocalFile, "") ;
497   fgQAResultFileName.Prepend(fgQAResultDirName) ;
498 }
499
500 //_______________________________________________________________
501 void AliQA::SetStatusBit(DETECTORINDEX_t det, ALITASK_t tsk, QABIT_t bit)
502 {
503  // Set the status bit for a given detector and a given task
504
505   CheckRange(det) ;
506   CheckRange(tsk) ;
507   CheckRange(bit) ;
508
509   ULong_t offset = Offset(tsk) ;
510   ULong_t status = GetStatus(det) ;
511   offset+= bit ;
512   status = status | 1 << offset ;
513   SetStatus(det, status) ;
514 }
515
516 //_______________________________________________________________
517 void AliQA::ShowAll() const
518 {
519   // dispplay the QA status word
520   Int_t index ;
521   for (index = 0 ; index < kNDET ; index++)
522     ShowStatus(DETECTORINDEX_t(index)) ;
523 }
524
525 //_______________________________________________________________
526 void AliQA::ShowStatus(DETECTORINDEX_t det) const
527 {
528   // Prints the full QA status of a given detector
529   CheckRange(det) ;
530   ULong_t status = GetStatus(det) ;
531   ULong_t rawStatus = status & 0x0000f ;
532   ULong_t simStatus = status & 0x000f0 ;
533   ULong_t recStatus = status & 0x00f00 ;
534   ULong_t esdStatus = status & 0x0f000 ;
535   ULong_t anaStatus = status & 0xf0000 ;
536
537   AliInfo(Form("QA Status for %8s raw =0x%x, sim=0x%x, rec=0x%x, esd=0x%x, ana=0x%x\n", GetDetName(det).Data(), rawStatus, simStatus, recStatus, esdStatus, anaStatus )) ;
538 }
539
540 //_______________________________________________________________
541 void AliQA::UnSet(QABIT_t bit)
542 {
543         // UnSet the status bit of the current detector in the current module
544         
545         UnSetStatusBit(fDet, fTask, bit) ;
546 }
547
548 //_______________________________________________________________
549 void AliQA::UnSetStatusBit(DETECTORINDEX_t det, ALITASK_t tsk, QABIT_t bit)
550 {
551         // UnSet the status bit for a given detector and a given task
552         
553         CheckRange(det) ;
554         CheckRange(tsk) ;
555         CheckRange(bit) ;
556         
557         ULong_t offset = Offset(tsk) ;
558         ULong_t status = GetStatus(det) ;
559         offset+= bit ;
560         status = status & 0 << offset ;
561         SetStatus(det, status) ;
562 }