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