]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONTrackerData.cxx
e3824904fcc82bb9ef4c3a0a3d46e8a0378604d4
[u/mrichter/AliRoot.git] / MUON / AliMUONTrackerData.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 "AliMUONTrackerData.h"
19
20 #include "AliCodeTimer.h"
21 #include "AliDAQ.h"
22 #include "AliLog.h"
23 #include "AliMUON1DArray.h"
24 #include "AliMUON1DMap.h"
25 #include "AliMUON2DMap.h"
26 #include "AliMUONCalibParamND.h"
27 #include "AliMUONSparseHisto.h"
28 #include "AliMUONVStore.h"
29 #include "AliMpBusPatch.h"
30 #include "AliMpConstants.h"
31 #include "AliMpCDB.h"
32 #include "AliMpDDLStore.h"
33 #include "AliMpManuStore.h"
34 #include "AliMpDEIterator.h"
35 #include "AliMpDEManager.h"
36 #include "AliMpDetElement.h"
37 #include "AliMpHVNamer.h"
38 #include "AliMpManuIterator.h"
39 #include <Riostream.h>
40 #include <TClass.h>
41 #include <TMath.h>
42 #include <TObjArray.h>
43 #include <TObjString.h>
44 #include <TString.h>
45 #include <TVector2.h>
46 #include <float.h>
47
48 /// \class AliMUONTrackerData
49 ///
50 /// Implementation of AliMUONVTrackerData class
51 ///
52 /// \author Laurent Aphecetche, Subatech
53
54 ///\cond CLASSIMP
55 ClassImp(AliMUONTrackerData)
56 ///\endcond
57
58 const Int_t AliMUONTrackerData::fgkExtraDimension = 2;
59 const Int_t AliMUONTrackerData::fgkVirtualExtraDimension = 1;
60
61 //_____________________________________________________________________________
62 AliMUONTrackerData::AliMUONTrackerData(const char* name, const char* title,
63                                        Int_t dimension,
64                                        Bool_t issingleevent)
65 : AliMUONVTrackerData(name,title),
66 fIsSingleEvent(issingleevent),
67 fChannelValues(0x0),
68 fManuValues(0x0),
69 fBusPatchValues(0x0),
70 fDEValues(0x0),
71 fChamberValues(0x0),
72 fPCBValues(0x0),
73 fDimension(External2Internal(dimension)+fgkExtraDimension),
74 fNevents(0),
75 fDimensionNames(new TObjArray(fDimension+fgkVirtualExtraDimension)),
76 fExternalDimensionNames(new TObjArray(dimension)),
77 fExternalDimension(dimension),
78 fHistogramming(new Int_t[fExternalDimension]),
79 fHistos(0x0),
80 fXmin(0.0),
81 fXmax(0.0),
82 fIsChannelLevelEnabled(kTRUE),
83 fIsManuLevelEnabled(kTRUE),
84 fNofDDLs(0),
85 fNofEventsPerDDL(0x0)
86 {  
87   /// ctor
88   memset(fHistogramming,0,sizeof(Int_t)); // histogramming is off by default. Use MakeHistogramForDimension to turn it on.
89   fExternalDimensionNames->SetOwner(kTRUE);
90   fDimensionNames->SetOwner(kTRUE);  
91   fDimensionNames->AddAt(new TObjString("occ"),IndexOfOccupancyDimension());
92   fDimensionNames->AddAt(new TObjString("N"),IndexOfNumberDimension());
93   fDimensionNames->AddAt(new TObjString("n"),NumberOfDimensions()-fgkVirtualExtraDimension);
94   Clear();
95 }
96
97 //_____________________________________________________________________________
98 AliMUONTrackerData::~AliMUONTrackerData()
99 {
100   /// dtor
101   delete fChannelValues;
102   delete fManuValues;
103   delete fBusPatchValues;
104   delete fDEValues;
105   delete fChamberValues;
106   delete fPCBValues;
107   delete fDimensionNames;
108   delete fExternalDimensionNames;
109   delete[] fHistogramming;
110   delete fHistos;
111   delete[] fNofEventsPerDDL;
112 }
113
114 //_____________________________________________________________________________
115 Bool_t
116 AliMUONTrackerData::Add(const AliMUONVStore& store, TArrayI* nevents)
117 {
118   /// Add the given external store to our internal store
119   return InternalAdd(store,nevents,kFALSE);
120 }
121
122 //_____________________________________________________________________________
123 Bool_t 
124 AliMUONTrackerData::Add(const AliMUONTrackerData& data)
125 {
126   /// Add data to *this
127   // We do this by looping on all VCalibParam stored in the various containers,
128   // and simply adding the values there.
129   // Same thing for the number of events per DDL.
130   // Same thing for sparsehistograms, if we have some.
131
132   // First cross check we have compatible objects.
133   
134   if ( fIsChannelLevelEnabled != data.fIsChannelLevelEnabled ) 
135   {
136     AliError("Incompatible IsChannelLevelEnabled status");
137     return kFALSE;
138   }
139   
140   if ( fIsManuLevelEnabled != data.fIsManuLevelEnabled ) 
141   {
142     AliError("Incompatible IsManuLevelEnabled status");
143     return kFALSE;
144   }
145   
146   if ( fIsSingleEvent != data.fIsSingleEvent ) 
147   {
148     AliError("Incompatible IsSingleEvent status");
149     return kFALSE;
150   }
151   
152   if ( fDimension != data.fDimension || fExternalDimension != data.fExternalDimension ) 
153   {
154     AliError("Incompatible dimensions");
155     return kFALSE;
156   }
157
158   if ( fNofDDLs != data.fNofDDLs ) 
159   {
160     AliError("Incompatible number of Ddls");
161     return kFALSE;
162   }
163   
164   if ( ( !fHistogramming && data.fHistogramming ) || ( fHistogramming && !data.fHistogramming ) 
165       || fXmin != data.fXmin || fXmax != data.fXmax ) 
166   {
167     AliError(Form("Incompatible histogramming (%x vs %x) (xmax = %e vs %e ; xmin = %e vs %e)",
168              fHistogramming,data.fHistogramming,fXmax,data.fXmax,fXmin,data.fXmin));
169     return kFALSE;
170   }
171
172   if ( fHistogramming )
173   {
174     for ( Int_t i = 0; i < fExternalDimension; ++i ) 
175     {
176       if ( fHistogramming[i] != data.fHistogramming[i] )
177       {
178         AliError(Form("Incompatible histogramming for external dimension %d",i));
179         return kFALSE;
180       }
181     }
182   }
183   
184   // OK. Seems we have compatible objects, so we can proceed with the actual
185   // merging...
186   
187   if ( data.fChannelValues ) 
188   {
189     Add2D(*(data.fChannelValues),*fChannelValues);
190   }
191   
192   if ( data.fManuValues ) 
193   {
194     Add2D(*(data.fManuValues),*fManuValues);
195   }
196   
197   if ( data.fPCBValues ) 
198   {
199     Add2D(*(data.fPCBValues),*fPCBValues);
200   }
201   
202   if ( data.fBusPatchValues ) 
203   {
204     Add1D(*(data.fBusPatchValues),*fBusPatchValues);
205   }
206   
207   if ( data.fDEValues ) 
208   {
209     Add1D(*(data.fDEValues),*fDEValues);
210   }
211   
212   if ( data.fChamberValues ) 
213   {
214     Add1D(*(data.fChamberValues),*fChamberValues);
215   }
216
217   for ( Int_t i = 0; i < fNofDDLs; ++i ) 
218   {
219     fNofEventsPerDDL[i] += data.fNofEventsPerDDL[i];
220   }
221   
222   if ( data.fHistos ) 
223   {
224     TIter nexthisto(data.fHistos->CreateIterator());
225     AliMUONVStore* store;
226     while ( ( store = static_cast<AliMUONVStore*>(nexthisto()) ) )
227     {
228       TIter ns(store->CreateIterator());
229       AliMUONSparseHisto* h;
230       while ( ( h = static_cast<AliMUONSparseHisto*>(ns()) ) )
231       {
232         AliMUONVStore* thisStore = static_cast<AliMUONVStore*>(fHistos->FindObject(store->GetUniqueID()));
233         
234         if (!thisStore)
235         {
236           thisStore = store->Create();
237           thisStore->SetUniqueID(store->GetUniqueID());
238           fHistos->Add(thisStore);
239         }
240         
241         AliMUONSparseHisto* mine = static_cast<AliMUONSparseHisto*>(thisStore->FindObject(h->GetUniqueID()));
242         
243         if (!mine) 
244         {
245           thisStore->Add(h);
246         }
247         else
248         {
249           mine->Add(*h);
250         }
251       }
252     }
253   }
254   
255   return kTRUE;
256 }
257
258 //_____________________________________________________________________________
259 void 
260 AliMUONTrackerData::Add2D(const AliMUONVStore& src, AliMUONVStore& dest) const
261 {
262   /// Add one 2d store to another
263   
264   TIter next(src.CreateIterator());
265   AliMUONVCalibParam* p;
266   
267   while ( ( p = static_cast<AliMUONVCalibParam*>(next()) ) )
268   {
269     AliMUONVCalibParam* a = static_cast<AliMUONVCalibParam*>(dest.FindObject(p->ID0(),p->ID1()));
270     
271     if (!a)
272     {
273       dest.Add(static_cast<AliMUONVCalibParam*>(p->Clone()));
274     }
275     else
276     {
277       AddCalibParams(*p,*a);
278     }
279   }
280 }
281
282 //_____________________________________________________________________________
283 void 
284 AliMUONTrackerData::Add1D(const AliMUONVStore& src, AliMUONVStore& dest) const
285 {
286   /// Add one 1d store to another
287   
288   TIter next(src.CreateIterator());
289   AliMUONVCalibParam* p;
290   
291   while ( ( p = static_cast<AliMUONVCalibParam*>(next()) ) )
292   {
293     AliMUONVCalibParam* a = static_cast<AliMUONVCalibParam*>(dest.FindObject(p->GetUniqueID()));
294     
295     if (!a)
296     {
297       dest.Add(static_cast<AliMUONVCalibParam*>(p->Clone()));
298     }
299     else
300     {
301       AddCalibParams(*p,*a);
302     }
303   }
304 }
305
306 //_____________________________________________________________________________
307 void
308 AliMUONTrackerData::AddCalibParams(const AliMUONVCalibParam& src, AliMUONVCalibParam& dest) const
309 {
310   /// Add src to dest
311   for ( Int_t i = 0; i < src.Size(); ++i ) 
312   {
313     for ( Int_t j = 0; j < src.Dimension(); ++j )
314     {
315       dest.SetValueAsFloat(i,j,src.ValueAsFloat(i,j));
316     }
317   }
318 }
319
320 //_____________________________________________________________________________
321 Bool_t
322 AliMUONTrackerData::Replace(const AliMUONVStore& store)
323 {
324   /// Replace our values by values from the given external store
325   Bool_t rv = InternalAdd(store,0x0,kTRUE);
326   AliMUONVTrackerData::Replace(store);
327   return rv;
328 }
329
330 //_____________________________________________________________________________
331 Bool_t
332 AliMUONTrackerData::InternalAdd(const AliMUONVStore& store, TArrayI* nevents, Bool_t replace)
333 {
334   /// Add the given external store to our internal store
335   
336   AliCodeTimerAuto(GetName());
337     
338   if ( !replace)
339   {
340     if ( IsSingleEvent() && NumberOfEvents(-1) == 1 ) 
341     {
342       AliError(Form("%s is supposed to be single event only",GetName()));
343       return kFALSE;
344     }  
345   }
346
347   if (!fNofDDLs)
348   {
349     fNofDDLs = AliDAQ::NumberOfDdls("MUONTRK");
350     fNofEventsPerDDL = new Int_t[fNofDDLs];
351     for ( Int_t i = 0; i < fNofDDLs; ++i ) 
352     {
353       fNofEventsPerDDL[i] = 0;
354     }
355   }
356     
357   if (nevents)
358   {
359     if (nevents->GetSize() != fNofDDLs ) 
360     {
361       AliError(Form("nof of ddl per event array size is incorrect : got %d, expecting %d",
362                     nevents->GetSize(),fNofDDLs));
363       return kFALSE;
364     }
365     
366     for ( Int_t i = 0 ; i < fNofDDLs; ++i ) 
367     {
368       fNofEventsPerDDL[i] += nevents->At(i);
369       fNevents = TMath::Max(fNevents,fNofEventsPerDDL[i]);
370     }
371   }
372   else
373   {
374     for ( Int_t i = 0 ; i < fNofDDLs; ++i ) 
375     {
376       ++fNofEventsPerDDL[i];
377       fNevents = TMath::Max(fNevents,fNofEventsPerDDL[i]);
378     }
379   }
380   
381   if (!fChamberValues)
382   {
383     Int_t numberOfBusPatches(0);
384     Int_t numberOfDEs(0);
385     
386     // get number of bus patches and number of detection element
387     // to initialize fBusPatchValues and fDEValues below
388     
389     TIter next(AliMpDDLStore::Instance()->CreateBusPatchIterator());
390     while ( next() ) ++numberOfBusPatches;
391     AliMpDEIterator deIt;
392     deIt.First();
393     while (!deIt.IsDone())
394     {
395       ++numberOfDEs;
396       deIt.Next();
397     }
398     
399                 if ( fIsChannelLevelEnabled ) 
400                 {
401                         fChannelValues = new AliMUON2DMap(kTRUE);
402                 }
403     if  ( fIsManuLevelEnabled ) 
404     {
405       fManuValues = new AliMUON2DMap(kTRUE);
406     }
407     fPCBValues = new AliMUON2DMap(kFALSE);
408     fBusPatchValues = new AliMUON1DMap(numberOfBusPatches);
409     fDEValues = new AliMUON1DMap(numberOfDEs);
410     fChamberValues = new AliMUON1DArray;
411   }
412   
413   TIter next(store.CreateIterator());
414   AliMUONVCalibParam* external;
415   
416   Int_t nk(2);
417   
418   if ( IsSingleEvent() ) nk = 1;
419
420   while ( ( external = static_cast<AliMUONVCalibParam*>(next()) ) )
421   {
422     if ( external->Dimension() != ExternalDimension() )
423     {
424       AliError(Form("Incompatible dimensions %d vs %d",
425                     external->Dimension(),ExternalDimension()));
426       return kFALSE;
427     }
428     
429
430     AliMUONVCalibParam* chamber, *de, *busPatch, *pcb, *manu, *channel;
431     AliMpDetElement* mpde;
432     
433     Int_t manuId = GetParts(external,chamber,de,busPatch,pcb,manu,channel,mpde);
434     
435     if ( manuId < 0 ) continue;
436     
437     Int_t detElemId = mpde->GetId();
438     
439     Double_t value[] = { 0.0, 0.0 };
440     
441     Int_t nch = mpde->NofChannelsInManu(manuId);
442     
443     for ( Int_t i = 0; i < external->Size(); ++i ) 
444     {
445       Bool_t existingChannel =  ( nch == AliMpConstants::ManuNofChannels() ? kTRUE
446                                                                            : mpde->IsConnectedChannel(manuId,i));
447       // note we only use IsConnectedChannel method when really needed, as
448       // it costs (some) CPU time...
449       
450       if ( existingChannel ) 
451       {
452         Bool_t validChannel(kFALSE);
453         
454         for ( Int_t j = 0; j < external->Dimension(); ++j )
455         {
456           Double_t vext = external->IsDoublePrecision() ? 
457             external->ValueAsDoubleFast(i,j) :
458             external->ValueAsFloatFast(i,j);
459           
460           if ( vext >= AliMUONVCalibParam::InvalidFloatValue() ) continue;
461           
462           validChannel = kTRUE;
463                     
464           Int_t ix = External2Internal(j);
465           
466           value[0] = vext;
467           value[1] = vext*vext;
468           
469           if ( IsHistogrammed(j) )
470           {
471             FillHisto(detElemId,manuId,i,j,vext);
472           }
473           
474           for ( Int_t k = 0; k < nk; ++k ) 
475           {
476             Double_t e = ( replace && channel ) ? channel->ValueAsDoubleFast(i,ix+k) : 0.0;
477             
478                                                 if ( channel ) 
479                                                 {
480                                                         channel->SetValueAsDoubleFast(i,ix+k,channel->ValueAsDoubleFast(i,ix+k)-e+value[k]);
481                                                 }
482                                                 
483             if (manu)
484             {
485               manu->SetValueAsDoubleFast(0,ix+k,manu->ValueAsDoubleFast(0,ix+k)-e+value[k]);            
486             }
487             
488             busPatch->SetValueAsDoubleFast(0,ix+k,busPatch->ValueAsDoubleFast(0,ix+k)-e+value[k]);
489             
490             de->SetValueAsDoubleFast(0,ix+k,de->ValueAsDoubleFast(0,ix+k)-e+value[k]);
491             
492             chamber->SetValueAsDoubleFast(0,ix+k,chamber->ValueAsDoubleFast(0,ix+k)-e+value[k]);
493             
494             if ( pcb ) 
495             {
496               pcb->SetValueAsDoubleFast(0,ix+k,pcb->ValueAsDoubleFast(0,ix+k)-e+value[k]);
497             }
498           }
499         }
500         
501         if ( validChannel && !replace )
502         {
503                                         if ( channel ) 
504                                         {
505                                                 channel->SetValueAsDoubleFast(i,IndexOfOccupancyDimension(),
506                                                                                                                                                                         channel->ValueAsDoubleFast(i,IndexOfOccupancyDimension())+1.0);
507                                         }
508                                         
509           if (manu)
510           {
511             manu->SetValueAsDoubleFast(0,IndexOfOccupancyDimension(),
512                                        manu->ValueAsDoubleFast(0,IndexOfOccupancyDimension())+1.0);        
513           }
514           
515           busPatch->SetValueAsDoubleFast(0,IndexOfOccupancyDimension(),
516                                                          busPatch->ValueAsDoubleFast(0,IndexOfOccupancyDimension())+1.0);        
517           de->SetValueAsDoubleFast(0,IndexOfOccupancyDimension(),
518                                              de->ValueAsDoubleFast(0,IndexOfOccupancyDimension())+1.0);        
519           chamber->SetValueAsDoubleFast(0,IndexOfOccupancyDimension(),
520                                                        chamber->ValueAsDoubleFast(0,IndexOfOccupancyDimension())+1.0); 
521           if ( pcb ) 
522           {
523             pcb->SetValueAsDoubleFast(0,IndexOfOccupancyDimension(),
524                                       pcb->ValueAsDoubleFast(0,IndexOfOccupancyDimension())+1.0);        
525           }
526         }
527       }
528     }
529   }
530   
531   NumberOfEventsChanged();
532   
533   return kTRUE;
534 }
535
536 //_____________________________________________________________________________
537 Double_t 
538 AliMUONTrackerData::BusPatch(Int_t busPatchId, Int_t dim) const
539 {
540   /// Return the value of a given buspatch for a given dimension
541   /// or 0 if not existing
542   AliMUONVCalibParam* param = BusPatchParam(busPatchId);
543   return param ? Value(*param,0,dim,DdlIdFromBusPatchId(busPatchId)) : 0.0;
544 }
545
546 //_____________________________________________________________________________
547 AliMUONVCalibParam* 
548 AliMUONTrackerData::BusPatchParam(Int_t busPatchId, Bool_t create) const
549 {
550   /// Return (if it exist), the VCalibParam for a given busPatch
551   
552   AliMUONVCalibParam* busPatch = fBusPatchValues ? static_cast<AliMUONVCalibParam*>
553     (fBusPatchValues->FindObject(busPatchId)) : 0x0;
554   
555   if (!busPatch && create && fBusPatchValues)
556   {
557     busPatch = CreateBusPatchParam(busPatchId);
558     fBusPatchValues->Add(busPatch);
559   }
560   
561   return busPatch;
562 }
563
564 //_____________________________________________________________________________
565 AliMUONVCalibParam* 
566 AliMUONTrackerData::CreateBusPatchParam(Int_t busPatchId) const
567 {
568   /// Create storage for one bus patch
569   
570   AliCodeTimerAuto("");
571   
572   AliMpBusPatch* bp = AliMpDDLStore::Instance()->GetBusPatch(busPatchId);
573   
574   if (!bp)
575   {
576     AliError(Form("Got an invalid buspatchId = %d",busPatchId));
577     return 0x0;
578   }
579   
580   AliMUONVCalibParam* busPatch = new AliMUONCalibParamND(Dimension(),1,busPatchId,0,0.0);
581   
582   // set the number of channels in that buspatch
583   
584   Int_t nchannels(0);
585   
586   Int_t detElemId = AliMpDDLStore::Instance()->GetDEfromBus(busPatchId);
587   
588   AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(detElemId);
589   
590   for ( Int_t i = 0; i < bp->GetNofManus(); ++i ) 
591   {
592     Int_t manuId = bp->GetManuId(i);
593     nchannels += de->NofChannelsInManu(manuId);
594   }
595   
596   busPatch->SetValueAsDouble(0,IndexOfNumberDimension(),nchannels);
597   
598   return busPatch;
599 }
600
601 //_____________________________________________________________________________
602 Double_t 
603 AliMUONTrackerData::Chamber(Int_t chamberId, Int_t dim) const
604 {
605   /// Return the value fo a given chamber for a given dimension,
606   /// or zero if not existing
607   
608   // FIXME: is the Value() correct wrt to number of events in the case of
609   // chamber ? Or should we do something custom at the chamber level 
610   // (as it spans several ddls) ?
611   
612   AliMUONVCalibParam* param = ChamberParam(chamberId);
613   return param ? Value(*param,0,dim,DdlIdFromChamberId(chamberId)) : 0.0;
614 }
615
616 //_____________________________________________________________________________
617 AliMUONVCalibParam* 
618 AliMUONTrackerData::ChamberParam(Int_t chamberId, Bool_t create) const
619 {
620   /// Return (if it exist) the VCalibParam for a given chamber
621   
622   AliMUONVCalibParam* chamber =  fChamberValues ? static_cast<AliMUONVCalibParam*>
623   (fChamberValues->FindObject(chamberId)) : 0x0;
624   
625   if (!chamber && create && fChamberValues)
626   {
627     chamber = CreateChamberParam(chamberId);
628     fChamberValues->Add(chamber);
629   }
630     
631   return chamber;
632 }
633
634 //_____________________________________________________________________________
635 AliMUONVCalibParam* 
636 AliMUONTrackerData::CreateChamberParam(Int_t chamberId) const
637 {
638   /// Create storage for one chamber
639   
640   AliCodeTimerAuto("");
641   
642   AliMUONVCalibParam* chamber = new AliMUONCalibParamND(Dimension(),1,chamberId,0,0.0);
643   
644   // set the number of channels in that chamber
645   
646   Int_t nchannels(0);
647   
648   AliMpDEIterator it;
649   
650   it.First(chamberId);
651   
652   while ( !it.IsDone() )
653   {        
654     AliMpDetElement* det = it.CurrentDE();
655     
656     for ( Int_t i = 0; i < det->GetNofBusPatches(); ++i ) 
657     {
658       Int_t busPatchId = det->GetBusPatchId(i);
659       AliMpBusPatch* bp = AliMpDDLStore::Instance()->GetBusPatch(busPatchId);
660       for ( Int_t j = 0; j < bp->GetNofManus(); ++j ) 
661       {
662         Int_t manuId = bp->GetManuId(j);
663         nchannels += det->NofChannelsInManu(manuId);
664       }        
665     }
666     
667     it.Next();
668   }
669   
670   chamber->SetValueAsDouble(0,IndexOfNumberDimension(),nchannels);
671   
672   return chamber;
673 }
674
675 //_____________________________________________________________________________
676 Double_t 
677 AliMUONTrackerData::Channel(Int_t detElemId, Int_t manuId, 
678                             Int_t manuChannel, Int_t dim) const
679 {
680   /// Return the value for a given channel for a given dimension
681   
682   AliMUONVCalibParam* param = ChannelParam(detElemId,manuId);
683   
684   return param ? Value(*param,manuChannel,dim,DdlIdFromDetElemId(detElemId)) : 0.0;
685 }
686
687 //_____________________________________________________________________________
688 AliMUONVCalibParam* 
689 AliMUONTrackerData::ChannelParam(Int_t detElemId, Int_t manuId,
690                                  AliMUONVCalibParam* external) const
691 {
692   /// Return (if it exist) the VCalibParam for a given manu
693   
694   AliMUONVCalibParam* param = fChannelValues ? static_cast<AliMUONVCalibParam*>
695     (fChannelValues->FindObject(detElemId,manuId)) : 0x0 ;
696   
697   if (!param && external && fChannelValues)
698   {
699     param = CreateDouble(*external,detElemId,manuId);
700     fChannelValues->Add(param);
701   }
702   
703   return param;
704 }
705
706 //_____________________________________________________________________________
707 void 
708 AliMUONTrackerData::Clear(Option_t*)
709 {
710   /// Clear all the values
711   if ( fChannelValues ) fChannelValues->Clear();
712   if ( fManuValues ) fManuValues->Clear();
713   if ( fBusPatchValues) fBusPatchValues->Clear();
714   if ( fPCBValues ) fPCBValues->Clear();
715   if ( fDEValues) fDEValues->Clear();
716   if ( fChamberValues ) fChamberValues->Clear();
717   if ( fHistos ) fHistos->Clear();
718   for ( Int_t i = 0; i < fNofDDLs; ++i ) 
719   {
720     fNofEventsPerDDL[i] = 0;
721   }
722   NumberOfEventsChanged();
723 }
724
725 //_____________________________________________________________________________
726 Double_t 
727 AliMUONTrackerData::Count(Int_t detElemId, Int_t manuId, 
728                           Int_t manuChannel) const
729 {
730   /// Return the number of times a given channel had data
731   
732   return Channel(detElemId,manuId,manuChannel,IndexOfNumberDimension());
733 }
734
735 //_____________________________________________________________________________
736 AliMUONVCalibParam*
737 AliMUONTrackerData::CreateDouble(const AliMUONVCalibParam& param, 
738                                  Int_t detElemId, Int_t manuId) const
739 {
740   /// Create a double version of VCalibParam, for internal use
741   
742   AliCodeTimerAuto("");
743   
744   AliMUONVCalibParam* c = new AliMUONCalibParamND(Dimension(),
745                                                   param.Size(),
746                                                   detElemId,
747                                                   manuId,
748                                                   0.0);
749   
750   AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(detElemId,manuId);
751   
752   for ( Int_t i = 0; i < c->Size(); ++i ) 
753   {
754     Double_t value(0.0);
755     
756     if ( de->IsConnectedChannel(manuId,i) ) value = 1.0;
757       
758     c->SetValueAsDouble(i,IndexOfNumberDimension(),value);
759   }
760   
761   return c;
762 }
763
764 //_____________________________________________________________________________
765 Double_t 
766 AliMUONTrackerData::DetectionElement(Int_t detElemId, Int_t dim) const
767 {
768   /// Return the value for a given detection element for a given dimension
769   AliMUONVCalibParam* param = DetectionElementParam(detElemId);
770   return param ? Value(*param,0,dim,DdlIdFromDetElemId(detElemId)) : 0.0;
771
772 }
773
774 //_____________________________________________________________________________
775 AliMUONVCalibParam* 
776 AliMUONTrackerData::DetectionElementParam(Int_t detElemId, Bool_t create) const
777 {
778   /// Return (if it exist) the VCalibParam for a given detection element
779   
780   AliMUONVCalibParam* de = fDEValues ? static_cast<AliMUONVCalibParam*>
781     (fDEValues->FindObject(detElemId)) : 0x0 ;
782   
783   if (!de && create && fDEValues)
784   {
785     de = CreateDetectionElementParam(detElemId);
786     fDEValues->Add(de);
787   }
788   
789   return de;
790   
791 }
792
793 //_____________________________________________________________________________
794 AliMUONVCalibParam* 
795 AliMUONTrackerData::CreateDetectionElementParam(Int_t detElemId) const
796 {
797   /// Create storage for one detection element
798   
799   AliCodeTimerAuto("");
800   
801   AliMUONVCalibParam*  de = new AliMUONCalibParamND(Dimension(),1,detElemId,0,0.0);
802   
803   AliMpDetElement* det = AliMpDDLStore::Instance()->GetDetElement(detElemId);
804   Int_t nchannels(0);
805   
806   for ( Int_t i = 0; i < det->GetNofBusPatches(); ++i ) 
807   {
808     Int_t busPatchId = det->GetBusPatchId(i);
809     AliMpBusPatch* bp = AliMpDDLStore::Instance()->GetBusPatch(busPatchId);
810     for ( Int_t j = 0; j < bp->GetNofManus(); ++j ) 
811     {
812       Int_t manuId = bp->GetManuId(j);
813       nchannels += det->NofChannelsInManu(manuId);
814     }        
815   }
816   
817   de->SetValueAsDouble(0,IndexOfNumberDimension(),nchannels);
818   
819   return de;
820 }
821
822 //_____________________________________________________________________________
823 Int_t 
824 AliMUONTrackerData::DdlIdFromBusPatchId(Int_t buspatchid) const
825 {
826   /// Get the "local" ddlid (0..19) of a given buspatch
827   AliMpBusPatch* bp = AliMpDDLStore::Instance()->GetBusPatch(buspatchid);
828   if (bp)
829   {
830     return bp->GetDdlId();
831   }
832   return -1;
833 }
834
835 //_____________________________________________________________________________
836 Int_t 
837 AliMUONTrackerData::DdlIdFromDetElemId(Int_t detelemid) const
838 {
839   /// Get the "local" ddlid (0..19) of a given detection element
840   AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(detelemid);
841   if (de)
842   {
843     return de->GetDdlId();
844   }
845   return -1;
846 }
847
848 //_____________________________________________________________________________
849 Int_t 
850 AliMUONTrackerData::DdlIdFromChamberId(Int_t chamberid) const
851 {
852   /// Get the "local" ddlid (0..19) of a given chamber
853   /// This has no real meaning (as there are several ddls per chamber),
854   /// so we take the ddlid where we got the max number of events
855   
856   AliMpDEIterator it;
857   
858   it.First(chamberid);
859   Int_t n(0);
860   Int_t d(-1);
861   
862   while (!it.IsDone())
863   {
864     Int_t detElemId = it.CurrentDEId();
865     Int_t ddlId = DdlIdFromDetElemId(detElemId);
866     if ( NumberOfEvents(ddlId) > n ) 
867     {
868       n = NumberOfEvents(ddlId);
869       d = ddlId;
870     }
871     it.Next();
872   }
873   
874   return d;
875 }
876
877 //_____________________________________________________________________________
878 TString 
879 AliMUONTrackerData::DimensionName(Int_t dim) const
880 {
881   /// Get the name of a given dimension
882   TObjString* value = static_cast<TObjString*>(fDimensionNames->At(dim));
883   if ( value ) 
884   {
885     return value->String();
886   }
887   else
888   {
889     return TString("Invalid");
890   }  
891 }
892
893 //_____________________________________________________________________________
894 void 
895 AliMUONTrackerData::DisableChannelLevel()
896
897   /// Disable the storing of data at channel level
898   
899   delete fChannelValues;
900   fChannelValues = 0x0;
901   fIsChannelLevelEnabled = kFALSE; 
902 }
903
904 //_____________________________________________________________________________
905 void 
906 AliMUONTrackerData::DisableManuLevel()
907
908   /// Disable the storing of data at manu level (and below)
909   
910   DisableChannelLevel();
911   delete fManuValues;
912   fManuValues = 0x0;
913   fIsManuLevelEnabled = kFALSE; 
914 }
915
916 //_____________________________________________________________________________
917 Int_t 
918 AliMUONTrackerData::External2Internal(Int_t index) const 
919 {
920   /// From external to internal dimension
921   return IsSingleEvent() ? index : index*2;
922 }
923
924 //_____________________________________________________________________________
925 TString 
926 AliMUONTrackerData::ExternalDimensionName(Int_t dim) const
927 {
928   /// Get the name of a given external dimension
929   
930   TObjString* value = static_cast<TObjString*>(fExternalDimensionNames->At(dim));
931   if ( value ) 
932   {
933     return value->String();
934   }
935   else
936   {
937     return TString("Invalid");
938   }  
939 }
940
941 //_____________________________________________________________________________
942 void
943 AliMUONTrackerData::FillHisto(Int_t detElemId, Int_t manuId, Int_t manuChannel,
944                               Int_t dim, Double_t value)
945 {
946   /// Fill histogram of a given channel
947   
948   AliMUONSparseHisto* h(0x0);
949   
950         if ( fIsChannelLevelEnabled ) 
951         {
952                 h = GetChannelSparseHisto(detElemId, manuId, manuChannel,dim);
953   }
954   else if ( fIsManuLevelEnabled ) 
955   {
956     h = GetManuSparseHisto(detElemId,manuId,dim);
957   }
958   
959   AliDebug(1,Form("DE %04d MANU %04d CH %02d dim %d value %e h %p",detElemId,manuId,manuChannel,dim,value,h));
960   
961   if (h)
962   {
963                 h->Fill(static_cast<Int_t>(TMath::Nint(value)));
964         }
965 }
966
967 //_____________________________________________________________________________
968 AliMUONSparseHisto*
969 AliMUONTrackerData::GetManuSparseHisto(Int_t detElemId, Int_t manuId, 
970                                        Int_t dim) const
971 {
972   /// Get histogram of a given manu
973   
974   if (!fHistos) return 0x0;
975   
976   AliMUON1DArray* m = static_cast<AliMUON1DArray*>(fHistos->FindObject(detElemId,manuId));
977   if (!m) return 0x0;
978   
979   AliMUONSparseHisto* h = static_cast<AliMUONSparseHisto*>(m->FindObject(dim));
980   
981   return h;
982 }
983
984 //_____________________________________________________________________________
985 AliMUONSparseHisto*
986 AliMUONTrackerData::GetManuSparseHisto(Int_t detElemId, Int_t manuId, Int_t dim)
987 {
988   /// Get histogram of a given manu. Create it if necessary
989   
990   if (!fHistos) fHistos = new AliMUON2DMap(kTRUE);
991   
992   AliMUON1DArray* m = static_cast<AliMUON1DArray*>(fHistos->FindObject(detElemId,manuId));
993   if (!m)
994   {
995     m = new AliMUON1DArray(NumberOfDimensions());
996     m->SetUniqueID( ( manuId << 16 ) | detElemId );
997     fHistos->Add(m);
998   }
999     
1000   AliMUONSparseHisto* h = static_cast<AliMUONSparseHisto*>(m->FindObject(dim));
1001   if (!h)
1002   {
1003     h = new AliMUONSparseHisto(fXmin,fXmax);
1004     
1005     h->SetUniqueID(dim);
1006     
1007     m->Add(h);
1008   }
1009   
1010    return h;
1011 }
1012
1013 //_____________________________________________________________________________
1014 AliMUONSparseHisto*
1015 AliMUONTrackerData::GetChannelSparseHisto(Int_t detElemId, Int_t manuId, 
1016                                           Int_t manuChannel, Int_t dim) const
1017 {
1018   /// Get histogram of a given channel
1019   
1020   if (!fHistos) return 0x0;
1021   
1022   AliMUON1DMap* m = static_cast<AliMUON1DMap*>(fHistos->FindObject(detElemId,manuId));
1023   if (!m) return 0x0;
1024   
1025   UInt_t uid = ( manuChannel << 16 ) | dim;
1026   
1027   AliMUONSparseHisto* h = static_cast<AliMUONSparseHisto*>(m->FindObject(uid));
1028   
1029   return h;
1030 }
1031
1032 //_____________________________________________________________________________
1033 AliMUONSparseHisto*
1034 AliMUONTrackerData::GetChannelSparseHisto(Int_t detElemId, Int_t manuId, 
1035                                           Int_t manuChannel, Int_t dim)
1036 {
1037   /// Get histogram of a given channel. Create it if necessary
1038   
1039   if (!fHistos) fHistos = new AliMUON2DMap(kTRUE);
1040   
1041   AliMUON1DMap* m = static_cast<AliMUON1DMap*>(fHistos->FindObject(detElemId,manuId));
1042   if (!m)
1043   {
1044     m = new AliMUON1DMap(AliMpConstants::ManuNofChannels()); // start with only 1 dim
1045     m->SetUniqueID( ( manuId << 16 ) | detElemId );
1046     fHistos->Add(m);
1047   }
1048   
1049   UInt_t uid = ( manuChannel << 16 ) | dim;
1050   
1051   AliMUONSparseHisto* h = static_cast<AliMUONSparseHisto*>(m->FindObject(uid));
1052   if (!h)
1053   {
1054     h = new AliMUONSparseHisto(fXmin,fXmax);
1055     
1056     h->SetUniqueID(uid);
1057     
1058     m->Add(h);
1059   }
1060
1061   return h;
1062 }
1063
1064 //_____________________________________________________________________________
1065 void
1066 AliMUONTrackerData::GetDEManu(const AliMUONVCalibParam& param,
1067                               Int_t& detElemId, Int_t& manuId) const
1068 {
1069   /// Tries to get (detElemId,manuId) of param
1070   
1071   // Load mapping manu store
1072   if ( ! AliMpCDB::LoadManuStore() ) {
1073     AliError("Could not access manu store from OCDB !");
1074     return;
1075   }
1076
1077   if ( param.ID1() <= 0 ) 
1078   {
1079     // we (probably) get a manu serial number
1080     Int_t serial = param.ID0();
1081     AliMpIntPair pair = AliMpManuStore::Instance()->GetDetElemIdManu(serial);
1082     detElemId = pair.GetFirst();
1083     manuId = pair.GetSecond();
1084     if ( !detElemId ) 
1085     {
1086       AliError(Form("DE %d manuId %d from serial %d is not correct !",
1087                     detElemId,manuId,serial));
1088     }
1089   }
1090   else
1091   {
1092     // we get a (de,manu) pair
1093     detElemId = param.ID0();
1094     manuId = param.ID1();
1095   }
1096 }
1097
1098
1099 //_____________________________________________________________________________
1100 Int_t
1101 AliMUONTrackerData::GetParts(AliMUONVCalibParam* external,
1102                              AliMUONVCalibParam*& chamber,
1103                              AliMUONVCalibParam*& de,
1104                              AliMUONVCalibParam*& busPatch,
1105                              AliMUONVCalibParam*& pcb,
1106                              AliMUONVCalibParam*& manu,
1107                              AliMUONVCalibParam*& channel,
1108                              AliMpDetElement*& mpde)
1109 {
1110   /// Get containers at all levels
1111  
1112   AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
1113   
1114   Int_t detElemId;
1115   Int_t manuId;
1116   
1117   GetDEManu(*external,detElemId,manuId);
1118   
1119   mpde = ddlStore->GetDetElement(detElemId);
1120
1121   if (!mpde) // can happen if reading e.g. capacitances store where we have data for non-connected manus
1122   {
1123     return -1;
1124   }
1125   
1126   Int_t chamberId = AliMpDEManager::GetChamberId(detElemId);
1127     
1128   Int_t busPatchId = ddlStore->GetBusPatchId(detElemId,manuId);
1129   
1130   Int_t pcbIndex = -1;
1131   
1132   AliMp::StationType stationType = mpde->GetStationType();
1133   
1134   if ( stationType == AliMp::kStation345 ) 
1135   {
1136     AliMpHVNamer namer;
1137     pcbIndex = namer.ManuId2PCBIndex(detElemId,manuId);
1138   }
1139   
1140   channel = ChannelParam(detElemId,manuId,external);
1141   
1142   manu = ManuParam(detElemId,manuId,kTRUE);
1143   
1144   busPatch = BusPatchParam(busPatchId,kTRUE);
1145   
1146   de = DetectionElementParam(detElemId,kTRUE);
1147   
1148   chamber = ChamberParam(chamberId,kTRUE);
1149   
1150   pcb = 0x0;
1151   
1152   if ( pcbIndex >= 0 ) 
1153   {
1154     pcb = PCBParam(detElemId,pcbIndex,kTRUE);
1155   }
1156   
1157   return manuId;
1158 }
1159
1160 //_____________________________________________________________________________
1161 Bool_t 
1162 AliMUONTrackerData::HasBusPatch(Int_t busPatchId) const
1163 {
1164   /// Whether we have data for a given buspatch
1165   return ( BusPatchParam(busPatchId) != 0 );
1166 }
1167
1168 //_____________________________________________________________________________
1169 Bool_t 
1170 AliMUONTrackerData::HasChamber(Int_t chamberId) const
1171 {
1172   /// Whether we have data for a given chamber
1173   return ( ChamberParam(chamberId) != 0 );
1174 }
1175
1176 //_____________________________________________________________________________
1177 Bool_t 
1178 AliMUONTrackerData::HasDetectionElement(Int_t detElemId) const
1179 {
1180   /// Whether we have data for a given detection element
1181   return ( DetectionElementParam(detElemId) != 0 );
1182 }
1183
1184 //_____________________________________________________________________________
1185 Bool_t
1186 AliMUONTrackerData::HasManu(Int_t detElemId, Int_t manuId) const
1187 {
1188   /// Whether we have data for a given manu
1189   return ( ManuParam(detElemId,manuId) != 0 ); 
1190 }
1191
1192 //_____________________________________________________________________________
1193 Bool_t
1194 AliMUONTrackerData::HasPCB(Int_t detElemId, Int_t pcbIndex) const
1195 {
1196   /// Whether we have data for a given pcb
1197   return ( PCBParam(detElemId,pcbIndex) != 0 ); 
1198 }
1199
1200 //_____________________________________________________________________________
1201 Double_t 
1202 AliMUONTrackerData::Manu(Int_t detElemId, Int_t manuId, Int_t dim) const
1203 {
1204   /// Return the value for a given manu and a given dimension
1205   
1206   AliMUONVCalibParam* param = ManuParam(detElemId,manuId);
1207   return param ? Value(*param,0,dim,DdlIdFromDetElemId(detElemId)) : 0.0;
1208 }
1209
1210 //_____________________________________________________________________________
1211 AliMUONVCalibParam* 
1212 AliMUONTrackerData::ManuParam(Int_t detElemId, Int_t manuId, Bool_t create) const
1213 {
1214   /// Get the VCalibParam for a given manu
1215   
1216   AliMUONVCalibParam* manu = fManuValues ? static_cast<AliMUONVCalibParam*>
1217     (fManuValues->FindObject(detElemId,manuId)) : 0x0 ;
1218   
1219   if (!manu && create && fManuValues)
1220   {
1221     manu = CreateManuParam(detElemId,manuId);
1222     fManuValues->Add(manu);
1223   }
1224   
1225   return manu;
1226 }
1227
1228 //_____________________________________________________________________________
1229 AliMUONVCalibParam* 
1230 AliMUONTrackerData::CreateManuParam(Int_t detElemId, Int_t manuId) const
1231 {
1232   /// Create storage for one manu
1233   
1234   AliCodeTimerAuto("");
1235   
1236   AliMUONVCalibParam* manu = new AliMUONCalibParamND(Dimension(),1,detElemId,manuId,0.0);
1237   
1238   // set the number of channels in that manu
1239   
1240   AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(detElemId);
1241   
1242   manu->SetValueAsDouble(0,IndexOfNumberDimension(),de->NofChannelsInManu(manuId));
1243   
1244   return manu;
1245 }
1246
1247 //_____________________________________________________________________________
1248 Long64_t
1249 AliMUONTrackerData::Merge(TCollection* list)
1250 {
1251   /// Merge this with a list of AliMUONVTrackerData
1252
1253   if (!list) return 0;
1254   
1255   if ( list->IsEmpty() ) return NumberOfEvents(-1);
1256   
1257   TIter next(list);
1258   const TObject* o(0x0);
1259   
1260   while ( ( o = next() ) )
1261   {
1262     const AliMUONTrackerData* data = dynamic_cast<const AliMUONTrackerData*>(o);
1263     if (!o)
1264     {
1265       AliError(Form("Object named %s is not an AliMUONTrackerData ! Skipping it",
1266                     o->GetName()));
1267     }
1268     else
1269     {
1270       Bool_t ok = Add(*data);
1271       if (!ok)
1272       {
1273         AliError("Got incompatible objects");
1274       }
1275     }
1276   }
1277   
1278   return NumberOfEvents(-1);
1279 }
1280
1281 //_____________________________________________________________________________
1282 Int_t 
1283 AliMUONTrackerData::NumberOfDimensions() const
1284 {
1285   /// Number of dimensions we're dealing with
1286   
1287   return fDimension + fgkVirtualExtraDimension; 
1288 }
1289
1290 //_____________________________________________________________________________
1291 Int_t
1292 AliMUONTrackerData::NumberOfEvents(Int_t ddlNumber) const
1293 {
1294   /// Get the number of events we've seen for a given DDL, or the max
1295   /// in case ddlNumber<0
1296
1297   Int_t n(0);
1298   
1299   if ( fNofEventsPerDDL && ddlNumber >= 0 && ddlNumber < fNofDDLs )
1300   {
1301     n = fNofEventsPerDDL[ddlNumber];
1302   }
1303   else
1304   {
1305     // get the max number of events
1306     return fNevents;
1307   }
1308   
1309   return n;
1310 }
1311
1312 //_____________________________________________________________________________
1313 Double_t 
1314 AliMUONTrackerData::PCB(Int_t detElemId, Int_t pcbIndex, Int_t dim) const
1315 {
1316   /// Return the value of a given pcb for a given dimension
1317
1318   AliMUONVCalibParam* param = PCBParam(detElemId,pcbIndex);
1319   
1320   return param ? Value(*param,0,dim,DdlIdFromDetElemId(detElemId)) : 0.0;
1321 }
1322
1323 //_____________________________________________________________________________
1324 AliMUONVCalibParam* 
1325 AliMUONTrackerData::PCBParam(Int_t detElemId, Int_t pcbIndex, Bool_t create) const
1326 {
1327   /// Return (if it exist) the VCalibParam for a given pcb
1328
1329   AliMUONVCalibParam* pcb =  fPCBValues ? static_cast<AliMUONVCalibParam*>
1330     (fPCBValues->FindObject(detElemId,pcbIndex)) : 0x0 ;
1331   
1332   if (create && fPCBValues && !pcb)
1333   {
1334     pcb = CreatePCBParam(detElemId,pcbIndex);
1335     fPCBValues->Add(pcb);
1336   }
1337   
1338   return pcb;
1339 }
1340
1341 //_____________________________________________________________________________
1342 AliMUONVCalibParam* 
1343 AliMUONTrackerData::CreatePCBParam(Int_t detElemId, Int_t pcbIndex) const
1344 {
1345   /// Create storage for one PCB (station345 only)
1346   
1347   AliCodeTimerAuto("");
1348   
1349   AliMpHVNamer namer;
1350   
1351   AliMUONVCalibParam* pcb = new AliMUONCalibParamND(Dimension(),
1352                                                     namer.NumberOfPCBs(detElemId),
1353                                                     detElemId,
1354                                                     pcbIndex,
1355                                                     0.0);
1356   return pcb;
1357 }
1358
1359 //_____________________________________________________________________________
1360 void 
1361 AliMUONTrackerData::Print(Option_t* wildcard, Option_t* opt) const
1362 {
1363   /// Printout
1364   
1365   TNamed::Print(opt);
1366   
1367   if ( !fIsSingleEvent ) 
1368   {
1369     for ( Int_t i = 0; i < fNofDDLs; ++i ) 
1370     {
1371       cout << Form("DDL %04d Nevents=%10d",AliDAQ::DdlID("MUONTRK",i),fNofEventsPerDDL[i]) << endl;
1372     }
1373   }
1374
1375         if ( !fIsChannelLevelEnabled ) 
1376         {
1377                 cout << "Is not storing data at the channel level" << endl;
1378         }
1379
1380   if ( !fIsManuLevelEnabled ) 
1381         {
1382                 cout << "Is not storing data at the manu level" << endl;
1383         }
1384   
1385   for ( Int_t i = 0; i <= fExternalDimensionNames->GetLast(); ++i ) 
1386   {
1387     TObjString* name = static_cast<TObjString*>(fExternalDimensionNames->At(i));
1388     cout << Form("External Dimension %2d Name %s %s",i,
1389                  ( name ? name->String().Data() : "null"),
1390                  ( IsHistogrammed(i) ? "(histogrammed)" : "")) << endl;
1391   }
1392   
1393   for ( Int_t i = 0; i <= fDimensionNames->GetLast(); ++i ) 
1394   {
1395     TObjString* name = static_cast<TObjString*>(fDimensionNames->At(i));
1396     cout << Form("Internal Dimension %2d Name %s",i,
1397                  ( name ? name->String().Data() : "null")) << endl;
1398   }
1399     
1400   TString sopt(opt);
1401   sopt.ToUpper();
1402   
1403   if ( sopt.Contains("CHANNEL") )
1404   {
1405     if ( fIsChannelLevelEnabled ) 
1406     {      
1407       if ( fChannelValues ) fChannelValues->Print(wildcard,opt);
1408     }
1409     else
1410     {
1411       AliWarning("You requested channel values, but they were not stored !");
1412     }
1413   }
1414
1415   if ( sopt.Contains("MANU") )
1416   {
1417     if ( fIsManuLevelEnabled ) 
1418     {
1419       if ( fManuValues ) fManuValues->Print(wildcard,opt);
1420     }
1421     else
1422     {
1423       AliWarning("You requested manu values, but they were not stored !");
1424     }
1425   }
1426
1427   if ( sopt.Contains("BUSPATCH") && fBusPatchValues ) 
1428   {
1429     fBusPatchValues->Print(wildcard,opt);
1430   }
1431
1432   if ( sopt.Contains("DE") && fDEValues ) 
1433   {
1434     fDEValues->Print(wildcard,opt);
1435   }
1436
1437   if ( sopt.Contains("CHAMBER") && fChamberValues ) 
1438   {
1439     fChamberValues->Print(wildcard,opt);
1440   }
1441   
1442 }
1443
1444 //_____________________________________________________________________________
1445 void
1446 AliMUONTrackerData::SetDimensionName(Int_t index, const char* name)
1447 {  
1448   /// Set the name of a given dimension
1449
1450   if ( index >= fExternalDimension ) 
1451   {
1452     AliError(Form("Index out of bounds : %d / %d",index,fExternalDimension));
1453     return;
1454   }
1455   
1456   Int_t ix = External2Internal(index);
1457   
1458   if ( !IsSingleEvent() ) 
1459   {
1460     const char* prefix[] = { "mean", "sigma" };
1461   
1462     for ( Int_t i = 0; i < 2; ++i ) 
1463     {
1464       Int_t j = ix+i;
1465     
1466       SetInternalDimensionName(j,Form("%s of %s",prefix[i],name));
1467     }
1468   }
1469   else
1470   {
1471     SetInternalDimensionName(index,name);
1472   }
1473   
1474   SetExternalDimensionName(index,name);
1475 }
1476
1477 //_____________________________________________________________________________
1478 void 
1479 AliMUONTrackerData::MakeHistogramForDimension(Int_t index, Bool_t value, Double_t xmin, Double_t xmax)
1480 {
1481   /// decide to make histos for a given dimension
1482   if ( index >= ExternalDimension() ) 
1483   {
1484     AliError(Form("Index out of bounds : %d / %d",index,ExternalDimension()));
1485     return;
1486   }
1487   
1488   fHistogramming[index] = value;
1489   fXmin = xmin;
1490   fXmax = xmax;
1491 }
1492
1493 //_____________________________________________________________________________
1494 void 
1495 AliMUONTrackerData::SetInternalDimensionName(Int_t index, const char* value)
1496 {
1497   /// Set the name of a given internal dimension
1498   if ( index >= fDimension ) 
1499   {
1500     AliError(Form("Index out of bounds : %d / %d",index,fDimension));
1501     return;
1502   }
1503   
1504   TObjString* ovalue = static_cast<TObjString*>(fDimensionNames->At(index));
1505     
1506   if ( ovalue ) 
1507   {
1508     fDimensionNames->Remove(ovalue);
1509     delete ovalue;
1510   }
1511   fDimensionNames->AddAt(new TObjString(value),index);
1512 }
1513
1514 //_____________________________________________________________________________
1515 void 
1516 AliMUONTrackerData::SetExternalDimensionName(Int_t index, const char* value)
1517 {
1518   /// Set the name of a given external dimension
1519   if ( index >= fExternalDimension ) 
1520   {
1521     AliError(Form("Index out of bounds : %d / %d",index,fExternalDimension));
1522     return;
1523   }
1524   
1525   TObjString* ovalue = static_cast<TObjString*>(fExternalDimensionNames->At(index));
1526   
1527   if ( ovalue ) 
1528   {
1529     fExternalDimensionNames->Remove(ovalue);
1530     delete ovalue;
1531   }
1532   fExternalDimensionNames->AddAt(new TObjString(value),index);
1533 }
1534
1535 //_____________________________________________________________________________
1536 Double_t 
1537 AliMUONTrackerData::Value(const AliMUONVCalibParam& param, Int_t i, 
1538                           Int_t dim, Int_t ddlId) const
1539 {
1540   /// Compute the value for a given dim, using the internal information we have
1541   /// Basically we're converting sum of weights and sum of squares of weights
1542   /// into means and sigmas, and number of events into occupancy number.
1543
1544   Double_t n = param.ValueAsDouble(i,IndexOfNumberDimension());
1545   
1546   if ( dim == IndexOfNumberDimension() ) return n; // the number of channels in any given element does not depend on the number of events
1547   
1548   Double_t occ = param.ValueAsDouble(i,IndexOfOccupancyDimension());
1549
1550   if ( dim >= fDimension ) 
1551   {
1552     return occ;
1553   }
1554   
1555   if ( dim == IndexOfOccupancyDimension() ) 
1556   {
1557     if ( ddlId < 0 ) AliError("Got a negative ddl id !");
1558     return occ/n/NumberOfEvents(ddlId);
1559   }
1560   
1561   Double_t value = param.ValueAsDouble(i,dim);
1562   
1563   if ( value >= AliMUONVCalibParam::InvalidFloatValue() ) return AliMUONVCalibParam::InvalidFloatValue();
1564   
1565   if ( TMath::Even(dim) || IsSingleEvent() ) 
1566   {
1567                 Double_t x = value/occ;
1568                 
1569                 return ( TMath::Finite(x) ? x : 0.0 ) ;
1570   }
1571   else
1572   {
1573     Double_t nn = occ;
1574     
1575     if ( nn > 1.0 ) 
1576     {
1577       Double_t mean = param.ValueAsDouble(i,dim-1)/nn;
1578     
1579       return TMath::Sqrt(TMath::Abs((value-nn*mean*mean)/(nn-1.0)));
1580     }
1581     else
1582     {
1583       return 0.0;
1584     }
1585   }
1586   
1587   AliError("Why am I here ?");
1588   return 0.0;
1589 }
1590
1591 //_____________________________________________________________________________
1592 void 
1593 AliMUONTrackerData::Streamer(TBuffer &R__b)
1594 {
1595   /// Customized streamer                                                    
1596   
1597   if (R__b.IsReading()) {
1598     AliMUONTrackerData::Class()->ReadBuffer(R__b, this);
1599     if ( !fNofDDLs )
1600     {
1601       // backward compatible mode : we set number of events
1602       // per DDL to the total number of events (the only information
1603       // we had before version 7 of that class)
1604       delete[] fNofEventsPerDDL;
1605       fNofDDLs=20;
1606       fNofEventsPerDDL = new Int_t[fNofDDLs];
1607       for ( Int_t i = 0; i < fNofDDLs; ++i ) 
1608       {
1609         fNofEventsPerDDL[i] = fNevents;
1610       }
1611     }
1612   } 
1613   else {
1614     AliMUONTrackerData::Class()->WriteBuffer(R__b, this);
1615   }
1616 }
1617
1618