]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONCalibrationData.cxx
Updating this macro to allow input from a counter collection
[u/mrichter/AliRoot.git] / MUON / AliMUONCalibrationData.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 #include "AliMUONCalibrationData.h"
19
20 #include "AliCDBEntry.h"
21 #include "AliCDBManager.h"
22 #include "AliCodeTimer.h"
23 #include "AliDCSValue.h"
24 #include "AliLog.h"
25 #include "AliMpDCSNamer.h"
26 #include "AliMpIntPair.h"
27 #include "AliMUONGlobalCrateConfig.h"
28 #include "AliMUONRegionalTriggerConfig.h"
29 #include "AliMUONRejectList.h"
30 #include "AliMUONTriggerEfficiencyCells.h"
31 #include "AliMUONTriggerLut.h"
32 #include "AliMUONVCalibParam.h"
33 #include "AliMUONVStore.h"
34 #include "AliMUONVStore.h"
35
36 #include <Riostream.h>
37 #include <TClass.h>
38 #include <TMap.h>
39 #include <TMath.h>
40
41 //-----------------------------------------------------------------------------
42 /// \class AliMUONCalibrationData
43 ///
44 /// For the moment, this class stores pedestals, gains, hv (for tracker)
45 /// and lut, masks and efficiencies (for trigger) that are fetched from the CDB.
46 ///
47 /// This class is to be considered as a convenience class.
48 /// Its aim is to ease retrieval of calibration data from the 
49 /// condition database.
50 ///
51 /// It acts as a "facade" to a bunch of underlying 
52 /// containers/calibration classes.
53 ///
54 /// \author Laurent Aphecetche
55 //-----------------------------------------------------------------------------
56
57 using std::cout;
58 using std::endl;
59 /// \cond CLASSIMP
60 ClassImp(AliMUONCalibrationData)
61 /// \endcond
62
63 AliMUONVStore* AliMUONCalibrationData::fgBypassPedestals(0x0);
64 AliMUONVStore* AliMUONCalibrationData::fgBypassGains(0x0);
65
66 namespace  
67 {
68   void MarkForDeletion(Int_t* indices, Int_t first, Int_t last)
69   {
70     for ( Int_t i = first; i <= last; ++i ) 
71     {
72       indices[i] = 1;
73     }
74   }
75 }
76
77 //_____________________________________________________________________________
78 AliMUONCalibrationData::AliMUONCalibrationData(Int_t runNumber, 
79                                                Bool_t deferredInitialization) 
80 : TObject(), 
81 fIsValid(kTRUE),
82 fRunNumber(runNumber), 
83 fGains(0x0), 
84 fPedestals(0x0),
85 fHV(0x0),
86 fTriggerDCS(0x0),
87 fLocalTriggerBoardMasks(0x0),
88 fRegionalTriggerConfig(0x0),
89 fGlobalTriggerCrateConfig(0x0),
90 fTriggerLut(0x0),
91 fTriggerEfficiency(0x0),
92 fCapacitances(0x0),
93 fNeighbours(0x0),
94 fOccupancyMap(0x0),
95 fRejectList(0x0),
96 fConfig(0x0)
97 {
98 /// Default ctor.
99
100   // If deferredInitialization is false, we read *all* calibrations
101   // at once.
102   // So when using this class to access only one kind of calibrations (e.g.
103   // only pedestals), you should put deferredInitialization to kTRUE, which
104   // will instruct this object to fetch the data only when neeeded.
105
106   if ( deferredInitialization == kFALSE )
107   {
108     Gains();
109     Pedestals();
110     OccupancyMap();
111     RejectList();
112     HV();
113     TriggerDCS();
114     LocalTriggerBoardMasks(0);
115     RegionalTriggerConfig();
116     GlobalTriggerCrateConfig();
117     TriggerLut();
118     TriggerEfficiency();
119     Capacitances();
120     Neighbours();
121     Config();
122   }
123 }
124
125 //_____________________________________________________________________________
126 AliMUONCalibrationData::~AliMUONCalibrationData()
127 {
128   /// Destructor. Note that we're the owner of our pointers if the OCDB cache
129   /// is not set. Otherwise the cache is supposed to take care of them...
130   if (!(AliCDBManager::Instance()->GetCacheFlag())) Reset();
131 }
132
133 //_____________________________________________________________________________
134 AliMUONVStore*
135 AliMUONCalibrationData::Capacitances() const
136 {
137   /// Create (if needed) and return the internal store for capacitances.
138   
139   if (!fCapacitances)
140   {
141     fCapacitances = CreateCapacitances(fRunNumber);
142   }
143   return fCapacitances;
144 }
145
146 //_____________________________________________________________________________
147 AliMUONVStore*
148 AliMUONCalibrationData::CreateCapacitances(Int_t runNumber, Int_t* startOfValidity)
149 {
150   /// Create capa store from OCDB for a given run
151   
152   return dynamic_cast<AliMUONVStore*>(CreateObject(runNumber,"MUON/Calib/Capacitances",startOfValidity));
153 }
154
155 //_____________________________________________________________________________
156 AliMUONVStore*
157 AliMUONCalibrationData::CreateGains(Int_t runNumber, Int_t* startOfValidity)
158 {
159   /// Create a new gain store from the OCDB for a given run
160   return dynamic_cast<AliMUONVStore*>(CreateObject(runNumber,"MUON/Calib/Gains",startOfValidity));
161 }
162
163 //_____________________________________________________________________________
164 AliMUONGlobalCrateConfig*
165 AliMUONCalibrationData::CreateGlobalTriggerCrateConfig(Int_t runNumber, Int_t* startOfValidity)
166 {
167   /// Create the internal store for GlobalTriggerCrateConfig from OCDB
168   
169   return dynamic_cast<AliMUONGlobalCrateConfig*>(CreateObject(runNumber,"MUON/Calib/GlobalTriggerCrateConfig",startOfValidity));
170 }
171
172
173 //______________________________________________________________________________
174 Bool_t AliMUONCalibrationData::CheckHVGroup(TObjArray& values, Int_t first, Int_t last, Double_t& value, Int_t& slope, TString* msg)
175 {
176   // Get the HV of the values between first and last indices
177   // return the HV slope  (in Volt per second) and a message
178   // Return kFALSE if we must discard the group
179   //
180   
181   if (msg) *msg="";
182   
183   if ( last < first ) return kFALSE;
184   if ( last - first < 2 ) return kFALSE;
185   
186   Double_t a(0.0);
187   Double_t b(0.0);
188
189   Float_t HVSAME(1); // 1 volts
190
191   AliDCSValue* vfirst = static_cast<AliDCSValue*>(values.UncheckedAt(first));
192   AliDCSValue* vlast = static_cast<AliDCSValue*>(values.UncheckedAt(last));
193
194   Int_t deltaHV = TMath::Nint(TMath::Abs(vfirst->GetFloat()-vlast->GetFloat()));
195   
196   if ( deltaHV < HVSAME ) return kFALSE;
197
198   for ( Int_t i = first; i <= last; ++i )
199   {
200     AliDCSValue* v = static_cast<AliDCSValue*>(values.UncheckedAt(i));
201
202     Double_t y = v->GetFloat() - vfirst->GetFloat();
203     Double_t x = v->GetTimeStamp() - vfirst->GetTimeStamp();
204   
205     a += x*y;
206     b += x*x;
207   }
208   
209   value = a/b;
210   slope = value > 0 ? 1 : -1;
211   value = TMath::Abs(value);
212   
213   UInt_t deltaTime = vlast->GetTimeStamp() - vfirst->GetTimeStamp();
214   
215   if (msg)
216   {
217     if (slope>0) (*msg) = Form("RU%d[%d:%d](%d)",TMath::Nint(value),first,last,deltaTime);
218     if (slope<0) (*msg) = Form("RD%d[%d:%d](%d)",TMath::Nint(value),first,last,deltaTime);
219     
220     if ( TMath::Nint(value) == 0 )
221     {
222       // this is to protect for the few cases 
223       // (see e.g. MchHvLvLeft/Chamber00Left/Quad2Sect0.actual.vMon in run 134497)
224       // where we can have *lots* of values (2483 in this example) but that
225       // are more or less constant...
226       //
227       // or simply to remove small ramps
228       //
229       slope = 0;
230       value = (vfirst->GetFloat()+vlast->GetFloat())/2.0;
231       *msg = Form("FLUCT%d[%d:%d]",TMath::Nint(value),first,last);
232     }
233   }
234   
235   return kTRUE;
236 }
237
238 //______________________________________________________________________________
239 Bool_t AliMUONCalibrationData::PatchHVValues(TObjArray& values,
240                                              TString* msg,
241                                              Bool_t dryRun)
242 {
243   /// We do here a little bit of massaging of the HV values, if needed.
244   ///
245   /// The main point is to "gather" values that are within a given small amount
246   /// of time (typically 60 seconds) and infer a slope from those values
247   /// slope > 0 means it is a ramp-up, slope < 0 that's a ramp-down
248   ///
249   /// This is to avoid both the "ramp-down-before-end-of-run" and the
250   /// "ramp-up-after-start-of-run" syndroms...
251   ///
252   /// Use dryRun = kTRUE to fill the messages *without* altering the values
253   ///
254   /// Return kFALSE is the kind of HV (trouble) case we have here
255   /// has not been identified...
256   ///
257   
258   UInt_t DELTATIME(60); // in seconds
259   Int_t IENDRU(60); // in seconds
260   
261   // Start by finding groups of values which are not separated (each) by more than
262   // deltaTime
263   
264   Bool_t gather(kFALSE);
265   Int_t ifirst(0);
266   Int_t ilast(0);
267   TObjArray groups;
268   groups.SetOwner(kTRUE);
269   
270   for ( Int_t i = values.GetLast(); i > 0; --i ) 
271   {
272     AliDCSValue* vi = static_cast<AliDCSValue*>(values.UncheckedAt(i));
273     AliDCSValue* vj = static_cast<AliDCSValue*>(values.UncheckedAt(i-1));
274
275     if ( vi->GetTimeStamp() - vj->GetTimeStamp() < DELTATIME )
276     {
277       if ( !gather ) 
278       {
279         gather = kTRUE;
280         ifirst = i;    
281       }
282       ilast=i;
283     }
284     else
285     {
286       if ( gather ) 
287       {
288         ilast=i;
289         
290         groups.Add(new AliMpIntPair(ilast,ifirst));
291       }
292       gather = kFALSE;
293     }
294   }
295   
296   if (gather)
297   {
298     groups.Add(new AliMpIntPair(0,ifirst));
299   }
300                  
301   TIter nextGroup(&groups,kIterBackward);
302   AliMpIntPair* p;
303   TString internalMsg;
304   Int_t ngroups(0);
305
306   Int_t nRU(0);
307   Int_t nRD(0);
308   Int_t nStartRU(0);
309   Int_t nEndAndShortRU(0);
310   Int_t nEndRD(0);
311   Int_t nTripRD(0);
312   Int_t nFluct(0);
313   TObjArray trips;
314   trips.SetOwner(kTRUE);
315   
316   while ( ( p = static_cast<AliMpIntPair*>(nextGroup()) ) )
317   {
318     Double_t value;
319     Int_t slope;
320     
321     TString groupMsg;
322     
323     AliDebugClass(1,Form("group %d:%d",p->GetFirst(),p->GetSecond()));
324     
325     Bool_t ok = CheckHVGroup(values,p->GetFirst(),p->GetSecond(),value,slope,&groupMsg);
326     
327     if (!ok) continue;
328     
329     ++ngroups;
330     
331     if ( slope > 0 )
332     {
333       if ( p->GetFirst() == 0 ) 
334       {
335         // start with a ramp-up
336         ++nStartRU;
337       }
338       else if ( p->GetSecond() == values.GetLast() && TMath::Nint(value) < IENDRU )
339       {
340         ++nEndAndShortRU;
341       }
342       else
343       {
344         // ramp-up in the middle of nowhere...
345         ++nRU;
346       }
347     }
348     else if ( slope < 0 )
349     {
350       if ( p->GetSecond() == values.GetLast() ) 
351       {
352         // end with a ramp-down
353         ++nEndRD;
354       }
355       else
356       {
357         // ramp-down in the middle of nowhere
358         ++nRD;
359       }
360
361       AliDCSValue* d = static_cast<AliDCSValue*>(values.At(p->GetSecond()));
362       
363       if ( d->GetFloat() < AliMpDCSNamer::TrackerHVOFF() )
364       {
365         ++nTripRD;
366         AliDCSValue* tripStart = static_cast<AliDCSValue*>(values.At(p->GetFirst()));        
367         trips.Add(new AliMpIntPair(tripStart->GetTimeStamp(),TMath::Nint(tripStart->GetFloat())));
368       }
369     }
370     else
371     {
372       ++nFluct;
373     }
374     
375     internalMsg += groupMsg;
376     internalMsg += " ";    
377   }
378   
379   /*
380    
381    Once we have "decoded" the groups we try to find out which of 
382    the following cases we're facing :
383   
384    case A = -------- = OK(1)
385   
386    case B = ----
387                 \
388                 \   = OK, once we have removed the ramp-down (2)
389   
390    case C =    ----- 
391               /
392              /       = OK, once we have removed the ramp-up (3)
393   
394    case D =    ----- 
395               /     \
396              /       \ = OK, once we have removed the ramp-down (2) and the ramp-up (3)
397   
398    case E = ----
399                 \
400                  \____ = TRIP = BAD (here the ramp-down slope should be bigger than in case C)
401   
402    case F = ----         
403                 \      ----- = BAD (trip + ramp-up at end of run)
404                  \____/   
405   
406    case G = fluctuations (within a range defined in CheckHVGroup...)
407    
408    case H =            
409                    /
410                   /   = ramp-up right at the end-of-run = OK (4)
411             ------
412    
413    (1) OK means the group is identified correctly, still the value can be below ready...
414    (2) ramp-down values will be removed if the ramp is indeed the last values in the serie
415        i.e. it's really an end-of-run problem (otherwise it's not case B)
416    (3) ramp-up values will be removed if the ramp is indeed the first values in the serie
417        i.e. it's really a start-of-run problem (otherwise it's not case C)
418    (4) OK if short enough...
419    
420    Any other case is unknown and we'll :
421    a) return kFALSE
422    b) assume the channel is OFF.
423   
424   
425   */
426   
427   AliDebugClass(1,Form("msg=%s ngroupds=%d",internalMsg.Data(),ngroups));
428   AliDebugClass(1,Form("nRU %d nRD %d nStartRU %d nEndRD %d nTripRD %d nFluct %d",
429                        nRU,nRD,nStartRU,nEndRD,nTripRD,nFluct));
430   
431   TString hvCase("OTHER");
432   int dummy(0),a(-1),b(-1);
433   char r[81];
434   Int_t nvalues = values.GetSize();  
435   Int_t* indices = new Int_t[nvalues];
436   memset(indices,0,nvalues*sizeof(Int_t));
437          
438   AliDCSValue* vfirst = static_cast<AliDCSValue*>(values.UncheckedAt(0));
439   AliDCSValue* vlast = static_cast<AliDCSValue*>(values.UncheckedAt(values.GetLast()));
440
441   UInt_t meanTimeStamp = ( vfirst->GetTimeStamp() + vlast->GetTimeStamp() ) / 2;
442   
443   if ( ngroups == 0 ) 
444   {
445     hvCase = "A"; 
446   }
447   else if ( nTripRD > 0 )
448   {
449     const Double_t HVLOWTRIP(600); // a trip below this value is considered a "low trip"
450     // i.e. one starting for a non-operational voltage
451     
452     internalMsg += Form("NT:%d ",nTripRD);
453     
454     if ( nRU > 0 && nRD > 0 )
455     {
456       hvCase = "F";
457     }
458     else
459     {
460       hvCase = "E";
461     }
462     
463     for ( Int_t iTrip = 0; iTrip <= trips.GetLast(); ++iTrip )
464     {
465       AliMpIntPair* tripPair = static_cast<AliMpIntPair*>(trips.At(iTrip));
466       TString tripType("TRIP");
467       if ( tripPair->GetSecond() < HVLOWTRIP)
468       {
469         tripType = "LOWTRIP";
470       }
471
472       internalMsg += Form("%s SV:%d TS:%d ",tripType.Data(),tripPair->GetSecond(),tripPair->GetFirst());
473     }
474     
475     // we put here the TRIP value as SV:value
476     // for cases where there's a drop in voltage but the starting point was
477     // below operational voltage, so strictly speaking it's *not* a trip, but
478     // more a big fluctuation
479     if ( !dryRun )
480     {
481       MarkForDeletion(indices,0,values.GetLast());
482       values.Add(new AliDCSValue(static_cast<Float_t>(0),meanTimeStamp));
483     }
484   }
485   else if ( nStartRU > 0 && nRU == 0 && nRD == 0 && nEndRD == 0 )
486   {
487     hvCase = "C";
488     if (!dryRun)
489     {
490       sscanf(internalMsg.Data(),"RU%10d[%10d:%10d]%80s",&dummy,&a,&b,r);
491       MarkForDeletion(indices,a,b);
492     }
493   }
494   else if ( nStartRU > 0 && nEndRD > 0 && nRD == 0 && nRU == 0 )
495   {
496     hvCase = "D";
497     if (!dryRun)
498     {
499       sscanf(internalMsg.Data(),"RU%10d[%10d:%10d]%80s",&dummy,&a,&b,r);
500       MarkForDeletion(indices,a,b-1);
501       Int_t i = internalMsg.Index("RD",strlen("RD"),0,TString::kExact);
502       sscanf(internalMsg(i,internalMsg.Length()-i).Data(),
503              "RD%10d[%10d:%10d]%80s",&dummy,&a,&b,r);
504       MarkForDeletion(indices,a+1,b);
505     }
506   }
507   else if ( nEndRD > 0 && nStartRU == 0 && nRU == 0 && nRD == 0 )
508   {
509     hvCase = "B";
510     if  (!dryRun)
511     {
512       Int_t i = internalMsg.Index("RD",strlen("RD"),0,TString::kExact);
513       sscanf(internalMsg(i,internalMsg.Length()-i).Data(),
514              "RD%10d[%10d:%10d]%80s",&dummy,&a,&b,r);
515       MarkForDeletion(indices,a,b);
516     }
517   }
518   else if ( nFluct > 0 )
519   {
520     hvCase = "G";
521     if (!dryRun)
522     {
523       TObjArray* af = internalMsg.Tokenize(" ");
524       TIter next(af);
525       TObjString* str;
526       while ( ( str = static_cast<TObjString*>(next()) ) )
527       {
528         TString s(str->String());
529         if ( s.BeginsWith("FLUCT") )
530         {
531           sscanf(s.Data(),"FLUCT%d[%d:%d]",&dummy,&a,&b);
532           MarkForDeletion(indices,a,b);
533         }
534       }
535       delete af;
536     }
537   }
538   else if ( nEndAndShortRU > 0 && nStartRU == 0 && nRU == 0 && nRD == 0 && nEndRD == 0 )
539   {
540     hvCase = "H";
541     if (!dryRun)
542     {
543       sscanf(internalMsg.Data(),"RU%10d[%10d:%10d]%80s",&dummy,&a,&b,r);
544       MarkForDeletion(indices,a,b);
545     }
546   }
547   else
548   {
549     // last chance... 
550     // here we know it's not a trip, so let's assume everything is OK
551     // if first and last value are in the same ballpark
552
553     const Double_t HVFLUCT(20); // volts
554     
555     if ( TMath::Abs(vfirst->GetFloat() - vlast->GetFloat()) < HVFLUCT )
556     {
557       hvCase = "Z";
558     }
559     if (!dryRun)
560     {
561       MarkForDeletion(indices,1,nvalues-1);
562     }
563   }
564   
565   if (!dryRun)
566   {
567     for ( Int_t i = 0; i < nvalues; ++i )
568     {
569       if ( indices[i] )
570       {
571         values.RemoveAt(i);
572       }
573     }
574   
575     values.Compress();
576   }
577   
578   delete[] indices;
579   
580   if ( !values.GetEntries() )
581   {
582     AliErrorClass(Form("No value left after patch... Check that !!! initial # of values=%d msg=%s",
583                        nvalues,internalMsg.Data()));
584     hvCase = "OTHER";
585   }
586
587   if (!dryRun)
588   {
589     // take the max of the remaining values
590     TIter nextA(&values);
591     AliDCSValue* val;
592     Float_t maxval(-9999);
593   
594     while ( ( val = static_cast<AliDCSValue*>(nextA()) ) )
595     {
596       if ( val->GetFloat() > maxval )
597       {
598         maxval = val->GetFloat();
599       }
600     }
601   
602     values.Clear();
603   
604     values.Add(new AliDCSValue(maxval,meanTimeStamp));
605   }
606   
607   // once the case is inferred, add a "CASE:%10d",hvCase.Data()
608   // to the msg
609   // so we can them sum up for all channels and get a summary per run...
610   
611   internalMsg += Form("CASE:%s",hvCase.Data());
612  
613   if (msg) *msg = internalMsg.Data();
614   
615   return hvCase=="OTHER" ? kFALSE : kTRUE;
616 }
617
618 //_____________________________________________________________________________
619 TMap*
620 AliMUONCalibrationData::CreateHV(Int_t runNumber, 
621                                  Int_t* startOfValidity, 
622                                  Bool_t patched,
623                                  TList* messages,
624                                  Bool_t dryRun)
625 {
626   /// Create a new HV map from the OCDB for a given run
627   ///
628   /// dryRun is only usefull with patched=kTRUE and non-empty messages) :
629   /// it allow to get the list of messages without altering the values at all
630   /// (A patch without a patch, so to speak...)
631   ///
632   
633   TMap* hvMap = dynamic_cast<TMap*>(CreateObject(runNumber,"MUON/Calib/HV",startOfValidity));
634
635   if (!hvMap) return 0x0;
636   
637   if (patched)
638   {
639     TIter next(hvMap);
640     TObjString* hvChannelName;
641     
642     while ( ( hvChannelName = static_cast<TObjString*>(next()) ) )
643     {
644       TString name(hvChannelName->String());
645       
646       if ( name.Contains("sw") ) continue; // skip switches
647
648       if ( name.Contains("iMon") ) continue; // skip HV currents
649
650       TPair* hvPair = static_cast<TPair*>(hvMap->FindObject(name.Data()));
651       TObjArray* values = static_cast<TObjArray*>(hvPair->Value());
652       if (!values)
653       {
654         AliErrorClass(Form("Could not get values for alias %s",name.Data()));
655       }
656       else
657       {
658         TString msg;
659         
660         AliDebugClass(1,Form("channel %s",name.Data()));
661         Bool_t ok = PatchHVValues(*values,&msg,dryRun);
662         
663         if ( messages ) 
664         {
665           messages->Add(new TObjString(Form("%s %s",hvChannelName->String().Data(),msg.Data())));
666         }
667         
668         if (!ok)
669         {
670           AliErrorClass(Form("PatchHVValue was not successfull ! This is serious ! "
671                              "You'll have to check the logic for channel %s in run %09d",
672                              name.Data(),runNumber));
673         }
674       }
675     }
676     
677   }
678   
679   if ( messages ) 
680   {
681     Int_t a(0),b(0),c(0),d(0),e(0),f(0),g(0),h(0),u(0),z(0);
682     TIter next(messages);
683     TObjString* msg;
684     char hvCase('u');
685     
686     while ( ( msg = static_cast<TObjString*>(next()) ) )
687     {
688       Int_t i = msg->String().Index("CASE",strlen("CASE"),0,TString::kExact);
689       
690       if ( i >= 0 )
691       {
692         sscanf(msg->String()(i,msg->String().Length()-i).Data(),"CASE:%10c",&hvCase);
693       }
694
695       switch (hvCase)
696       {
697         case 'A': ++a; break;
698         case 'B': ++b; break;
699         case 'C': ++c; break;
700         case 'D': ++d; break;
701         case 'E': ++e; break;
702         case 'F': ++f; break;
703         case 'G': ++g; break;
704         case 'H': ++h; break;
705         case 'Z': ++z; break;
706         default: ++u; break;
707       }
708     }
709     
710     messages->Add(new TObjString(Form("SUMMARY : # of cases A(%3d) B(%3d) C(%3d) D(%3d) E(%3d) F(%3d) G(%3d) H(%3d) Z(%3d) OTHER(%3d)",
711                                       a,b,c,d,e,f,g,h,z,u)));
712   }
713   
714   return hvMap;
715 }
716
717 //_____________________________________________________________________________
718 TMap*
719 AliMUONCalibrationData::CreateTriggerDCS(Int_t runNumber, Int_t* startOfValidity)
720 {
721   /// Create a new Trigger HV and curent map from the OCDB for a given run
722   return dynamic_cast<TMap*>(CreateObject(runNumber,"MUON/Calib/TriggerDCS",startOfValidity));
723 }
724
725 //_____________________________________________________________________________
726 AliMUONVStore*
727 AliMUONCalibrationData::CreateLocalTriggerBoardMasks(Int_t runNumber, Int_t* startOfValidity)
728 {
729   /// Get the internal store for LocalTriggerBoardMasks from OCDB
730   
731   return dynamic_cast<AliMUONVStore*>(CreateObject(runNumber,"MUON/Calib/LocalTriggerBoardMasks",startOfValidity));
732 }
733
734 //_____________________________________________________________________________
735 AliMUONVStore*
736 AliMUONCalibrationData::CreateNeighbours(Int_t runNumber, Int_t* startOfValidity)
737 {
738   /// Create a neighbour store from the OCDB for a given run
739   return dynamic_cast<AliMUONVStore*>(CreateObject(runNumber,"MUON/Calib/Neighbours",startOfValidity));
740 }
741
742 //_____________________________________________________________________________
743 TObject*
744 AliMUONCalibrationData::CreateObject(Int_t runNumber, const char* path, Int_t* startOfValidity)
745 {
746   /// Access the CDB for a given path (e.g. MUON/Calib/Pedestals),
747   /// and return the corresponding TObject.
748   
749   AliCodeTimerAutoClass(Form("%09d : %s",runNumber,path),0);
750   
751   AliCDBManager* man = AliCDBManager::Instance();
752   
753   AliCDBEntry* entry =  man->Get(path,runNumber);
754   
755   if (entry)
756   {
757                 if ( startOfValidity ) *startOfValidity = entry->GetId().GetFirstRun();
758                 
759     TObject* object = entry->GetObject();
760     if (!(man->GetCacheFlag()))
761     {
762       entry->SetOwner(kFALSE);
763       delete entry;      
764     }
765 //    else
766 //    {
767 //      entry->SetOwner(kTRUE); //FIXME : this should be done but is causing problems with RecoParams at the end of the reco : investigate why...
768 //    }
769     return object;
770   }
771         else
772         {
773                 if ( startOfValidity )  *startOfValidity = AliCDBRunRange::Infinity();
774   }
775         
776   {
777     
778     AliCodeTimerAutoClass(Form("Failed to get %s for run %09d",path,runNumber),1);
779
780   }
781   
782   return 0x0;
783 }
784
785 //_____________________________________________________________________________
786 AliMUONVStore*
787 AliMUONCalibrationData::CreateOccupancyMap(Int_t runNumber, Int_t* startOfValidity)
788 {
789   /// Create a new occupancy map store from the OCDB for a given run
790   return dynamic_cast<AliMUONVStore*>(CreateObject(runNumber,"MUON/Calib/OccupancyMap",startOfValidity));
791 }
792
793 //_____________________________________________________________________________
794 AliMUONRejectList*
795 AliMUONCalibrationData::CreateRejectList(Int_t runNumber, Int_t* startOfValidity)
796 {
797   /// Create a new rejectlist store from the OCDB for a given run
798   return dynamic_cast<AliMUONRejectList*>(CreateObject(runNumber,"MUON/Calib/RejectList",startOfValidity));
799 }
800
801 //_____________________________________________________________________________
802 AliMUONVStore*
803 AliMUONCalibrationData::CreatePedestals(Int_t runNumber, Int_t* startOfValidity)
804 {
805   /// Create a new pedestal store from the OCDB for a given run
806   return dynamic_cast<AliMUONVStore*>(CreateObject(runNumber,"MUON/Calib/Pedestals",startOfValidity));
807 }
808
809 //_____________________________________________________________________________
810 AliMUONVStore*
811 AliMUONCalibrationData::CreateConfig(Int_t runNumber, Int_t* startOfValidity)
812 {
813   /// Create a new config store from the OCDB for a given run
814   return dynamic_cast<AliMUONVStore*>(CreateObject(runNumber,"MUON/Calib/Config",startOfValidity));
815 }
816
817
818 //_____________________________________________________________________________
819 AliMUONRegionalTriggerConfig*
820 AliMUONCalibrationData::CreateRegionalTriggerConfig(Int_t runNumber, Int_t* startOfValidity)
821 {
822   /// Create the internal store for RegionalTriggerConfig from OCDB
823   
824   return dynamic_cast<AliMUONRegionalTriggerConfig*>(CreateObject(runNumber,"MUON/Calib/RegionalTriggerConfig",startOfValidity));
825 }
826
827 //_____________________________________________________________________________
828 AliMUONTriggerEfficiencyCells* 
829 AliMUONCalibrationData::CreateTriggerEfficiency(Int_t runNumber, Int_t* startOfValidity)
830 {
831   /// Create trigger efficiency object from OCBD
832   
833   return dynamic_cast<AliMUONTriggerEfficiencyCells*>(CreateObject(runNumber,"MUON/Calib/TriggerEfficiency",startOfValidity));
834 }
835
836 //_____________________________________________________________________________
837 AliMUONTriggerLut* 
838 AliMUONCalibrationData::CreateTriggerLut(Int_t runNumber, Int_t* startOfValidity)
839 {
840   /// Create trigger LUT from OCDB
841   
842   return dynamic_cast<AliMUONTriggerLut*>(CreateObject(runNumber,"MUON/Calib/TriggerLut",startOfValidity));
843 }
844
845 //_____________________________________________________________________________
846 AliMUONVStore*
847 AliMUONCalibrationData::Gains() const
848 {
849   /// Create (if needed) and return the internal store for gains.
850   if (fgBypassGains) return fgBypassGains;
851   
852   if (!fGains)
853   {
854     fGains = CreateGains(fRunNumber);
855   }
856   return fGains;
857 }
858  
859 //_____________________________________________________________________________
860 AliMUONVCalibParam*
861 AliMUONCalibrationData::Gains(Int_t detElemId, Int_t manuId) const
862 {
863 /// Return the gains for a given (detElemId, manuId) pair
864 /// Note that, unlike the DeadChannel case, if the result is 0x0, that's an
865 /// error (meaning that we should get gains for all channels).
866
867   AliMUONVStore* gains = Gains();
868   if (!gains)
869   {
870     return 0x0;
871   }
872   
873   return static_cast<AliMUONVCalibParam*>(gains->FindObject(detElemId,manuId));
874 }
875
876 //_____________________________________________________________________________
877 AliMUONGlobalCrateConfig* 
878 AliMUONCalibrationData::GlobalTriggerCrateConfig() const
879 {
880   /// Return the config for the global trigger board.
881   
882   if (!fGlobalTriggerCrateConfig)
883   {
884     fGlobalTriggerCrateConfig = CreateGlobalTriggerCrateConfig(fRunNumber);
885   }
886   return fGlobalTriggerCrateConfig;
887 }
888
889
890 //_____________________________________________________________________________
891 TMap*
892 AliMUONCalibrationData::HV(Bool_t patched) const
893 {
894   /// Return the calibration for a given (detElemId, manuId) pair
895   
896   if (!fHV)
897   {
898     fHV = CreateHV(fRunNumber,0,patched);
899   }
900   return fHV;
901 }
902
903 //_____________________________________________________________________________
904 TMap*
905 AliMUONCalibrationData::TriggerDCS() const
906 {
907   /// Return the calibration for a given (detElemId, manuId) pair
908   
909   if (!fTriggerDCS)
910   {
911     fTriggerDCS = CreateTriggerDCS(fRunNumber);
912   }
913   return fTriggerDCS;
914 }
915
916 //_____________________________________________________________________________
917 AliMUONVStore*
918 AliMUONCalibrationData::Neighbours() const
919 {
920   /// Create (if needed) and return the internal store for neighbours.
921   if (!fNeighbours)
922   {
923     fNeighbours = CreateNeighbours(fRunNumber);
924   }
925   return fNeighbours;
926 }
927
928 //_____________________________________________________________________________
929 AliMUONVCalibParam* 
930 AliMUONCalibrationData::LocalTriggerBoardMasks(Int_t localBoardNumber) const
931 {
932 /// Return the masks for a given trigger local board.
933
934   if (!fLocalTriggerBoardMasks)
935   {
936     fLocalTriggerBoardMasks = CreateLocalTriggerBoardMasks(fRunNumber);
937   }
938
939   if ( fLocalTriggerBoardMasks ) 
940   {
941     AliMUONVCalibParam* ltbm = 
942       static_cast<AliMUONVCalibParam*>(fLocalTriggerBoardMasks->FindObject(localBoardNumber));
943     if (!ltbm)
944     {
945       AliError(Form("Could not get mask for localBoardNumber=%d",localBoardNumber));
946     }
947     return ltbm;  
948   }
949   return 0x0;
950 }
951
952 //_____________________________________________________________________________
953 AliMUONVStore*
954 AliMUONCalibrationData::OccupancyMap() const
955 {
956   /// Get occupancy map
957   if (!fOccupancyMap)
958   {
959     fOccupancyMap = CreateOccupancyMap(fRunNumber);
960   }
961   return fOccupancyMap;
962 }
963
964 //_____________________________________________________________________________
965 AliMUONRejectList*
966 AliMUONCalibrationData::RejectList() const
967 {
968   /// Get reject list
969   if (!fRejectList)
970   {
971     fRejectList = CreateRejectList(fRunNumber);
972   }
973   return fRejectList;
974 }
975
976 //_____________________________________________________________________________
977 void
978 AliMUONCalibrationData::BypassStores(AliMUONVStore* ped, AliMUONVStore* gain)
979 {
980   /// Force the use of those pedestals and gains
981   fgBypassPedestals = ped;
982   fgBypassGains = gain;
983   
984 }
985
986 //_____________________________________________________________________________
987 AliMUONVStore*
988 AliMUONCalibrationData::Pedestals() const
989 {
990   /// Return pedestals
991   
992   if (fgBypassPedestals) return fgBypassPedestals;
993   
994   if (!fPedestals)
995   {
996     fPedestals = CreatePedestals(fRunNumber);
997   }
998   return fPedestals;
999 }
1000
1001 //_____________________________________________________________________________
1002 AliMUONVStore*
1003 AliMUONCalibrationData::Config() const
1004 {
1005   /// Return config
1006   
1007   if (!fConfig)
1008   {
1009     fConfig = CreateConfig(fRunNumber);
1010   }
1011   return fConfig;
1012 }
1013
1014 //_____________________________________________________________________________
1015 AliMUONVCalibParam*
1016 AliMUONCalibrationData::Pedestals(Int_t detElemId, Int_t manuId) const
1017 {
1018   /// Return the pedestals for a given (detElemId, manuId) pair.
1019   /// A return value of 0x0 is considered an error, meaning we should get
1020   /// pedestals for all channels.
1021   
1022   AliMUONVStore* pedestals = Pedestals();
1023   if (!pedestals) 
1024   {
1025     return 0x0;
1026   }
1027   
1028   return static_cast<AliMUONVCalibParam*>(pedestals->FindObject(detElemId,manuId));
1029 }
1030
1031 //_____________________________________________________________________________
1032 void
1033 AliMUONCalibrationData::Print(Option_t*) const
1034 {
1035   /// A very basic dump of our guts.
1036
1037   cout << "RunNumber " << RunNumber()
1038   << " fGains=" << fGains
1039   << " fPedestals=" << fPedestals
1040   << " fConfig=" << fConfig
1041   << " fHV=" << fHV
1042   << " fTriggerDCS=" << fTriggerDCS
1043   << " fLocalTriggerBoardMasks=" << fLocalTriggerBoardMasks
1044   << " fRegionalTriggerConfig=" << fRegionalTriggerConfig
1045   << " fGlobalTriggerCrateConfig=" << fGlobalTriggerCrateConfig
1046   << " fTriggerLut=" << fTriggerLut
1047   << endl;
1048 }
1049
1050
1051 //_____________________________________________________________________________
1052 AliMUONRegionalTriggerConfig* 
1053 AliMUONCalibrationData::RegionalTriggerConfig() const
1054 {
1055   /// Return the config for the regional trigger board.
1056   
1057   if (!fRegionalTriggerConfig)
1058   {
1059     fRegionalTriggerConfig = CreateRegionalTriggerConfig(fRunNumber);
1060     }
1061   return fRegionalTriggerConfig;
1062 }
1063
1064
1065 //_____________________________________________________________________________
1066 AliMUONTriggerEfficiencyCells*
1067 AliMUONCalibrationData::TriggerEfficiency() const
1068 {
1069 /// Return the trigger efficiency.
1070
1071   if (!fTriggerEfficiency)
1072   {
1073     fTriggerEfficiency = CreateTriggerEfficiency(fRunNumber);
1074   }
1075   return fTriggerEfficiency;
1076 }
1077
1078
1079 //_____________________________________________________________________________
1080 AliMUONTriggerLut*
1081 AliMUONCalibrationData::TriggerLut() const
1082 {
1083 /// Return the trigger look up table.
1084
1085   if (!fTriggerLut)
1086   {
1087     fTriggerLut = CreateTriggerLut(fRunNumber);
1088   }
1089   return fTriggerLut;
1090 }
1091
1092 //_____________________________________________________________________________
1093 void
1094 AliMUONCalibrationData::Reset()
1095 {
1096 /// Reset all data
1097
1098   AliCodeTimerAuto("",0);
1099   
1100   delete fConfig;
1101   fConfig = 0x0;
1102   delete fPedestals;
1103   fPedestals = 0x0;
1104   delete fGains;
1105   fGains = 0x0;
1106   delete fHV;
1107   fHV = 0x0;
1108   delete fTriggerDCS;
1109   fTriggerDCS = 0x0;
1110   delete fLocalTriggerBoardMasks;
1111   fLocalTriggerBoardMasks = 0x0;
1112   delete fRegionalTriggerConfig;
1113   fRegionalTriggerConfig = 0x0;
1114   delete fGlobalTriggerCrateConfig;
1115   fGlobalTriggerCrateConfig = 0x0;
1116   
1117   delete fTriggerLut;
1118   fTriggerLut = 0x0;
1119   delete fTriggerEfficiency;
1120   fTriggerEfficiency = 0x0;
1121   delete fCapacitances;
1122   fCapacitances = 0x0;
1123   delete fNeighbours;
1124   fNeighbours = 0x0;
1125 }
1126
1127 //_____________________________________________________________________________
1128 void
1129 AliMUONCalibrationData::Check(Int_t runNumber)
1130 {
1131   /// Self-check to see if we can read all data for a given run 
1132   /// from the current OCDB...
1133   
1134   if ( ! CreateCapacitances(runNumber) )
1135   {
1136     AliErrorClass("Could not read capacitances");
1137   }
1138   else
1139   {
1140     AliInfoClass("Capacitances read OK");
1141   }
1142
1143   if ( ! CreateGains(runNumber) ) 
1144   {
1145     AliErrorClass("Could not read gains");
1146   }
1147   else
1148   {
1149     AliInfoClass("Gains read OK");
1150   }
1151
1152   if ( ! CreateGlobalTriggerCrateConfig(runNumber) ) 
1153   {
1154     AliErrorClass("Could not read Trigger Crate Config");
1155   }
1156   else
1157   {
1158     AliInfoClass("TriggerBoardMasks read OK");
1159   }
1160
1161   if ( !  CreateHV(runNumber) )
1162   {
1163     AliErrorClass("Could not read HV");
1164   }
1165   else
1166   {
1167     AliInfoClass("HV read OK");
1168   }
1169
1170   if ( !  CreateTriggerDCS(runNumber) )
1171   {
1172     AliErrorClass("Could not read Trigger HV and Currents");
1173   }
1174   else
1175   {
1176     AliInfoClass("Trigger HV and Currents read OK");
1177   }
1178
1179   if ( ! CreateNeighbours(runNumber) )
1180   {
1181     AliErrorClass("Could not read Neighbours");
1182   }
1183   else
1184   {
1185     AliInfoClass("Neighbours read OK");
1186   }
1187
1188   if ( !  CreateLocalTriggerBoardMasks(runNumber) )
1189   {
1190     AliErrorClass("Could not read LocalTriggerBoardMasks");
1191   }
1192   else
1193   {
1194     AliInfoClass("LocalTriggerBoardMasks read OK");
1195   }
1196   
1197   if ( ! CreatePedestals(runNumber) )
1198   {
1199     AliErrorClass("Could not read pedestals");
1200   }
1201   else
1202   {
1203     AliInfoClass("Pedestals read OK");
1204   }
1205
1206   if ( ! CreateConfig(runNumber) )
1207   {
1208     AliErrorClass("Could not read config");
1209   }
1210   else
1211   {
1212     AliInfoClass("Config read OK");
1213   }
1214   
1215   if ( ! CreateRegionalTriggerConfig(runNumber) )
1216   {
1217     AliErrorClass("Could not read RegionalTriggerConfig");
1218   }
1219   else
1220   {
1221     AliInfoClass("RegionalTriggerBoardMasks read OK");
1222   }
1223   
1224   if ( ! CreateTriggerLut(runNumber) )
1225   {
1226     AliErrorClass("Could not read TriggerLut");
1227   }
1228   else
1229   {
1230     AliInfoClass("TriggerLut read OK");
1231   }
1232
1233   if ( ! CreateTriggerEfficiency(runNumber) )
1234   {
1235     AliErrorClass("Could not read TriggerEfficiency");
1236   }
1237   else    
1238   {
1239     AliInfoClass("TriggerEfficiency read OK");
1240   }
1241 }