extra harmonics
[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 "AliMUONConstants.h"
28 #include "AliMUONRejectList.h"
29 #include "AliMUONSparseHisto.h"
30 #include "AliMUONVStore.h"
31 #include "AliMpBusPatch.h"
32 #include "AliMpConstants.h"
33 #include "AliMpCDB.h"
34 #include "AliMpDDLStore.h"
35 #include "AliMpManuStore.h"
36 #include "AliMpDEIterator.h"
37 #include "AliMpDEManager.h"
38 #include "AliMpDetElement.h"
39 #include "AliMpDCSNamer.h"
40 #include "AliMpManuIterator.h"
41 #include "AliMpEncodePair.h"
42 #include "AliMpSegmentation.h"
43 #include <Riostream.h>
44 #include <TClass.h>
45 #include <TMath.h>
46 #include <TObjArray.h>
47 #include <TObjString.h>
48 #include <TString.h>
49 #include <TTimeStamp.h>
50 #include <TVector2.h>
51 #include <cassert>
52 #include <float.h>
53
54 /// \class AliMUONTrackerData
55 ///
56 /// Implementation of AliMUONVTrackerData class
57 ///
58 /// \author Laurent Aphecetche, Subatech
59
60 ///\cond CLASSIMP
61 ClassImp(AliMUONTrackerData)
62 ///\endcond
63
64 const Int_t AliMUONTrackerData::fgkExtraDimension = 2;
65 const Int_t AliMUONTrackerData::fgkVirtualExtraDimension = 1;
66
67 //_____________________________________________________________________________
68 AliMUONTrackerData::AliMUONTrackerData(const char* name, const char* title,
69                                        Int_t dimension,
70                                        Bool_t issingleevent)
71 : AliMUONVTrackerData(name,title),
72 fIsSingleEvent(issingleevent),
73 fChannelValues(0x0),
74 fManuValues(0x0),
75 fBusPatchValues(0x0),
76 fDEValues(0x0),
77 fChamberValues(0x0),
78 fPCBValues(0x0),
79 fDimension(External2Internal(dimension)+fgkExtraDimension),
80 fNevents(0),
81 fDimensionNames(new TObjArray(fDimension+fgkVirtualExtraDimension)),
82 fExternalDimensionNames(new TObjArray(dimension)),
83 fExternalDimension(dimension),
84 fHistogramming(new Int_t[fExternalDimension]),
85 fHistos(0x0),
86 fXmin(0.0),
87 fXmax(0.0),
88 fIsChannelLevelEnabled(kTRUE),
89 fIsManuLevelEnabled(kTRUE),
90 fIsBustPatchLevelEnabled(kTRUE),
91 fIsPCBLevelEnabled(kTRUE),
92 fNofDDLs(0),
93 fNofEventsPerDDL(0x0)
94 {  
95   /// ctor
96   memset(fHistogramming,0,fExternalDimension*sizeof(Int_t)); // histogramming is off by default. Use MakeHistogramForDimension to turn it on.
97   fExternalDimensionNames->SetOwner(kTRUE);
98   fDimensionNames->SetOwner(kTRUE);  
99   fDimensionNames->AddAt(new TObjString("occ"),IndexOfOccupancyDimension());
100   fDimensionNames->AddAt(new TObjString("N"),IndexOfNumberDimension());
101   fDimensionNames->AddAt(new TObjString("n"),NumberOfDimensions()-fgkVirtualExtraDimension);
102   Clear();
103 }
104
105 //_____________________________________________________________________________
106 AliMUONTrackerData::AliMUONTrackerData(const char* name, const char* title,
107                                        const AliMUONVStore& manuValues)
108 : AliMUONVTrackerData(name,title),
109 fIsSingleEvent(kFALSE),
110 fChannelValues(0x0),
111 fManuValues(0x0),
112 fBusPatchValues(0x0),
113 fDEValues(0x0),
114 fChamberValues(0x0),
115 fPCBValues(0x0),
116 fDimension(0),
117 fNevents(0),
118 fDimensionNames(0x0),
119 fExternalDimensionNames(0x0),
120 fExternalDimension(0),
121 fHistogramming(0x0),
122 fHistos(0x0),
123 fXmin(0.0),
124 fXmax(0.0),
125 fIsChannelLevelEnabled(kFALSE),
126 fIsManuLevelEnabled(kTRUE),
127 fIsBustPatchLevelEnabled(kTRUE),
128 fIsPCBLevelEnabled(kTRUE),
129 fNofDDLs(0),
130 fNofEventsPerDDL(0x0)
131 {  
132   /// ctor with pre-computed values at the manu level
133   /// In this case, we force fIsChannelLevelEnabled = kFALSE
134   /// ctor
135   
136   if (manuValues.GetSize()==0)
137   {
138     AliFatal("Cannot create a tracker data from nothing in that case !");
139   }
140   
141   if ( !AliMpDDLStore::Instance(kFALSE) && !AliMpManuStore::Instance(kFALSE) )
142   {
143     AliError("Cannot work without (full) mapping");
144     return;
145   }
146   
147   TIter next(manuValues.CreateIterator());
148   AliMUONVCalibParam* m = static_cast<AliMUONVCalibParam*>(next());
149   
150   Int_t dimension = ( m->Dimension() - fgkExtraDimension - fgkVirtualExtraDimension ) / 2;
151   
152   fDimension = External2Internal(dimension)+fgkExtraDimension;
153   
154   fDimensionNames = new TObjArray(fDimension+fgkVirtualExtraDimension);
155   fExternalDimensionNames = new TObjArray(dimension);
156   fExternalDimension = dimension;
157   fHistogramming = new Int_t[fExternalDimension];
158   memset(fHistogramming,0,fExternalDimension*sizeof(Int_t)); // histogramming is off by default. Use MakeHistogramForDimension to turn it on.
159
160   fExternalDimensionNames->SetOwner(kTRUE);
161   fDimensionNames->SetOwner(kTRUE);  
162   fDimensionNames->AddAt(new TObjString("occ"),IndexOfOccupancyDimension());
163   fDimensionNames->AddAt(new TObjString("N"),IndexOfNumberDimension());
164   fDimensionNames->AddAt(new TObjString("n"),NumberOfDimensions()-fgkVirtualExtraDimension);
165   Clear();
166   TArrayI nevents(AliDAQ::NumberOfDdls("MUONTRK"));
167   AssertStores();
168   
169   next.Reset();
170   AliMUONVCalibParam* external;
171   
172   while ( ( external = static_cast<AliMUONVCalibParam*>(next()) ) )
173   {
174     Int_t detElemId, manuId;
175     
176     GetDEManu(*external,detElemId,manuId);
177     
178     AliMUONVCalibParam* chamber(0x0);
179     AliMUONVCalibParam* de(0x0);
180     AliMUONVCalibParam* busPatch(0x0);
181     AliMUONVCalibParam* pcb(0x0);
182     AliMUONVCalibParam* manu(0x0);
183     AliMUONVCalibParam* channel(0x0);
184     AliMpDetElement* mpde(0x0);
185     
186     AliMUONVCalibParam* wec = new AliMUONCalibParamND(external->Dimension()-1,1,detElemId,manuId,0);
187     // as external, but without event count
188     wec->SetValueAsDouble(0,0,external->ValueAsDouble(0,0));
189     wec->SetValueAsDouble(0,1,external->ValueAsDouble(0,1));
190     wec->SetValueAsDouble(0,2,external->ValueAsDouble(0,2));
191     wec->SetValueAsDouble(0,3,external->ValueAsDouble(0,3));
192     
193     Int_t mid = GetParts(wec,chamber,de,busPatch,pcb,manu,channel,mpde);
194
195     if ( manuId != mid ) 
196     {
197       AliError(Form("Something is wrong for DE %5d : manuId = %d vs mid = %d",detElemId,manuId,mid));
198       continue;
199     }
200     
201     if ( manuId < 0 ) 
202     {
203       AliError("Got a < 0 manuId. Should not happen here !");
204       continue;
205     }
206     
207     assert(channel==0x0);
208     
209     Int_t n1 = manu->ValueAsInt(0,IndexOfNumberDimension());
210     Int_t n2 = external->ValueAsInt(0,IndexOfNumberDimension());
211     if  ( n1 != n2 )
212     {
213       AliError(Form("Incoherent number of manu channels for DE %5d MANU %5d : %d vs %d",
214                     detElemId,manuId,n1,n2));
215     }
216     
217     Int_t nevt = external->ValueAsInt(0,4);
218     
219     Int_t busPatchId = AliMpDDLStore::Instance()->GetBusPatchId(detElemId,manuId);
220
221     Int_t ddl = AliMpDDLStore::Instance()->GetDDLfromBus(busPatchId);
222
223     if ( nevents[ddl] == 0 ) 
224     {
225       nevents[ddl] = nevt;
226     }
227     else
228     {
229       if ( nevents.At(ddl) != nevt ) 
230       {
231         AliError(Form("Nevt mismatch for DE %5d MANU %5d DDL %d : %d vs %d",
232                       detElemId,manuId,ddl,nevents.At(ddl),nevt));
233         continue;
234       }
235     }
236     
237     for ( Int_t i = 0; i < wec->Dimension()-1; ++i ) 
238     {
239       manu->SetValueAsDouble(0,i,manu->ValueAsDouble(0,i) + wec->ValueAsDouble(0,i));
240       
241       busPatch->SetValueAsDouble(0,i,busPatch->ValueAsDouble(0,i) + wec->ValueAsDouble(0,i));
242       
243       de->SetValueAsDouble(0,i,de->ValueAsDouble(0,i) + wec->ValueAsDouble(0,i));
244       
245       chamber->SetValueAsDouble(0,i,chamber->ValueAsDouble(0,i) + wec->ValueAsDouble(0,i));
246     }    
247     delete wec;
248   }  
249   
250   UpdateNumberOfEvents(&nevents);
251
252 }
253
254 //_____________________________________________________________________________
255 AliMUONTrackerData::AliMUONTrackerData(const char* name, const char* title,
256                                        const AliMUONVStore& deValues, Int_t val)
257 : AliMUONVTrackerData(name,title),
258 fIsSingleEvent(kFALSE),
259 fChannelValues(0x0),
260 fManuValues(0x0),
261 fBusPatchValues(0x0),
262 fDEValues(0x0),
263 fChamberValues(0x0),
264 fPCBValues(0x0),
265 fDimension(0),
266 fNevents(0),
267 fDimensionNames(0x0),
268 fExternalDimensionNames(0x0),
269 fExternalDimension(0),
270 fHistogramming(0x0),
271 fHistos(0x0),
272 fXmin(0.0),
273 fXmax(0.0),
274 fIsChannelLevelEnabled(kFALSE),
275 fIsManuLevelEnabled(kFALSE),
276 fIsBustPatchLevelEnabled(kFALSE),
277 fIsPCBLevelEnabled(kFALSE),
278 fNofDDLs(0),
279 fNofEventsPerDDL(0x0)
280 {  
281   /// ctor with values at the detection element level
282   /// In this case, we force fIsChannelLevelEnabled = fIsManuLevelEnabled = kFALSE
283   /// ctor
284   
285   if (deValues.GetSize()==0)
286   {
287     AliFatal("Cannot create a tracker data from nothing in that case !");
288   }
289   
290   if ( val != 1 ) 
291   {
292     AliFatal("Wrong parameter. For DE, must be 1");
293   }
294   
295   if ( !AliMpDDLStore::Instance(kFALSE) && !AliMpManuStore::Instance(kFALSE) )
296   {
297     AliError("Cannot work without (full) mapping");
298     return;
299   }
300   
301   TIter next(deValues.CreateIterator());
302   AliMUONVCalibParam* m = static_cast<AliMUONVCalibParam*>(next());
303   
304   Int_t dimension = ( m->Dimension() - fgkExtraDimension - fgkVirtualExtraDimension ) / 2;
305   
306   fDimension = External2Internal(dimension)+fgkExtraDimension;
307   
308   fDimensionNames = new TObjArray(fDimension+fgkVirtualExtraDimension);
309   fExternalDimensionNames = new TObjArray(dimension);
310   fExternalDimension = dimension;
311   fHistogramming = new Int_t[fExternalDimension];
312   memset(fHistogramming,0,fExternalDimension*sizeof(Int_t)); // histogramming is off by default. Use MakeHistogramForDimension to turn it on.
313   
314   fExternalDimensionNames->SetOwner(kTRUE);
315   fDimensionNames->SetOwner(kTRUE);  
316   fDimensionNames->AddAt(new TObjString("occ"),IndexOfOccupancyDimension());
317   fDimensionNames->AddAt(new TObjString("N"),IndexOfNumberDimension());
318   fDimensionNames->AddAt(new TObjString("n"),NumberOfDimensions()-fgkVirtualExtraDimension);
319   Clear();
320   TArrayI nevents(AliDAQ::NumberOfDdls("MUONTRK"));
321   AssertStores();
322   
323   next.Reset();
324   AliMUONVCalibParam* external;
325   
326   while ( ( external = static_cast<AliMUONVCalibParam*>(next()) ) )
327   {
328     Int_t detElemId = external->ID0();
329
330     AliMpDetElement* mpde = AliMpDDLStore::Instance()->GetDetElement(detElemId,kFALSE);
331     
332     if (!mpde)
333     {
334       AliError(Form("Got an invalid DE (%d) from external store",detElemId));
335       continue;
336     }
337     
338     Int_t chamberId = AliMpDEManager::GetChamberId(detElemId);
339     AliMUONVCalibParam* chamber = ChamberParam(chamberId,kTRUE);
340     AliMUONVCalibParam* de = DetectionElementParam(detElemId,kTRUE);
341
342     AliMUONVCalibParam* wec = new AliMUONCalibParamND(external->Dimension()-1,1,detElemId,0,0);
343     // as external, but without event count
344     wec->SetValueAsDouble(0,0,external->ValueAsDouble(0,0));
345     wec->SetValueAsDouble(0,1,external->ValueAsDouble(0,1));
346     wec->SetValueAsDouble(0,2,external->ValueAsDouble(0,2));
347     wec->SetValueAsDouble(0,3,external->ValueAsDouble(0,3));
348     
349     Int_t n1 = de->ValueAsInt(0,IndexOfNumberDimension());
350     Int_t n2 = external->ValueAsInt(0,IndexOfNumberDimension());
351     if  ( n1 != n2 )
352     {
353       AliError(Form("Incoherent number of dimensions for DE%d : %d vs %d",
354                     detElemId,n1,n2));
355       continue;
356     }
357     
358     Int_t nevt = external->ValueAsInt(0,4);
359     
360     Int_t ddl = mpde->GetDdlId();
361     
362     if ( nevents[ddl] == 0 ) 
363     {
364       nevents[ddl] = nevt;
365     }
366     else
367     {
368       if ( nevents.At(ddl) != nevt ) 
369       {
370         AliError(Form("Nevt mismatch for DE %5d  DDL %d : %d vs %d",
371                       detElemId,ddl,nevents.At(ddl),nevt));
372         continue;
373       }
374     }
375     
376     for ( Int_t i = 0; i < wec->Dimension()-1; ++i ) 
377     {
378       de->SetValueAsDouble(0,i,de->ValueAsDouble(0,i) + wec->ValueAsDouble(0,i));
379       
380       chamber->SetValueAsDouble(0,i,chamber->ValueAsDouble(0,i) + wec->ValueAsDouble(0,i));
381     }    
382     delete wec;
383   }  
384   
385   UpdateNumberOfEvents(&nevents);
386   
387 }
388
389 //_____________________________________________________________________________
390 AliMUONTrackerData::AliMUONTrackerData(const char* name, const char* title,
391                                        const AliMUONRejectList& rejectList)
392 : AliMUONVTrackerData(name,title),
393 fIsSingleEvent(kFALSE),
394 fChannelValues(0x0),
395 fManuValues(0x0),
396 fBusPatchValues(0x0),
397 fDEValues(0x0),
398 fChamberValues(0x0),
399 fPCBValues(0x0),
400 fDimension(External2Internal(1)+fgkExtraDimension),
401 fNevents(0),
402 fDimensionNames(new TObjArray(fDimension+fgkVirtualExtraDimension)),
403 fExternalDimensionNames(new TObjArray(1)),
404 fExternalDimension(1),
405 fHistogramming(new Int_t[fExternalDimension]),
406 fHistos(0x0),
407 fXmin(0.0),
408 fXmax(0.0),
409 fIsChannelLevelEnabled(kTRUE),
410 fIsManuLevelEnabled(kTRUE),
411 fIsBustPatchLevelEnabled(kTRUE),
412 fIsPCBLevelEnabled(kFALSE),
413 fNofDDLs(0),
414 fNofEventsPerDDL(0x0)
415 {  
416   
417    /// ctor with values from the given rejectlist
418     
419   if ( !AliMpDDLStore::Instance(kFALSE) && !AliMpManuStore::Instance(kFALSE) )
420   {
421     AliError("Cannot work without (full) mapping");
422     return;
423   }
424   
425   memset(fHistogramming,0,fExternalDimension*sizeof(Int_t)); // histogramming is off by default. Use MakeHistogramForDimension to turn it on.
426   
427   fExternalDimensionNames->SetOwner(kTRUE);
428   fDimensionNames->SetOwner(kTRUE);  
429   fDimensionNames->AddAt(new TObjString("occ"),IndexOfOccupancyDimension());
430   fDimensionNames->AddAt(new TObjString("N"),IndexOfNumberDimension());
431   fDimensionNames->AddAt(new TObjString("n"),NumberOfDimensions()-fgkVirtualExtraDimension);
432   Clear();
433   TArrayI nevents(AliDAQ::NumberOfDdls("MUONTRK"));
434   AssertStores();
435   
436   
437   for ( Int_t chamberId = 0; chamberId < AliMUONConstants::NCh(); ++chamberId ) 
438   {
439     AliMUONVCalibParam* chamber = ChamberParam(chamberId,kTRUE);
440
441     // FIXME : update the chamber value !
442     
443     AliMpDEIterator deit;
444   
445     deit.First(chamberId);
446
447     while ( !deit.IsDone() ) 
448     {
449       AliMpDetElement* mpde = deit.CurrentDE();
450       
451       Int_t detElemId = mpde->GetId();
452
453       AliMUONVCalibParam* de = DetectionElementParam(detElemId,kTRUE);
454
455       DispatchValue(*de,0,rejectList.DetectionElementProbability(detElemId),0.0,mpde->NofChannels());
456       
457       for ( Int_t iBusPatch = 0; iBusPatch < mpde->GetNofBusPatches(); ++iBusPatch ) 
458       {
459         Int_t busPatchId = mpde->GetBusPatchId(iBusPatch);
460         
461         AliMUONVCalibParam* bp = BusPatchParam(busPatchId,kTRUE);
462
463         AliMpBusPatch* mpbp = AliMpDDLStore::Instance()->GetBusPatch(busPatchId);
464
465         Int_t nch(0);
466         
467         for ( Int_t iManu = 0 ;iManu < mpbp->GetNofManus(); ++iManu )
468         {
469           Int_t manuId = mpbp->GetManuId(iManu);
470           
471           nch += mpde->NofChannelsInManu(manuId);
472           
473           AliMUONVCalibParam* manu = ManuParam(detElemId,manuId,kTRUE);
474           
475           DispatchValue(*manu,0,rejectList.ManuProbability(detElemId,manuId),0.0,mpde->NofChannelsInManu(manuId));
476           
477           AliMUONVCalibParam* c = ChannelParam(detElemId,manuId);
478           
479           if (!c)
480           {
481             c = new AliMUONCalibParamND(Dimension(),
482                                         AliMpConstants::ManuNofChannels(),
483                                         detElemId,
484                                         manuId,
485                                         0.0);
486             fChannelValues->Add(c);
487           }
488           
489           for ( Int_t manuChannel = 0; manuChannel < AliMpConstants::ManuNofChannels(); ++manuChannel )
490           {
491             DispatchValue(*c,manuChannel,rejectList.ChannelProbability(detElemId,manuId,manuChannel),0.0,1);
492           }
493         }
494
495         DispatchValue(*bp,0,rejectList.BusPatchProbability(busPatchId),0.0,nch);
496
497       }
498       
499       deit.Next();
500     }
501  
502   }
503   
504   
505   SetDimensionName(0,"RejectProba");
506
507   UpdateNumberOfEvents(0x0);
508 }
509
510 //_____________________________________________________________________________
511 AliMUONTrackerData::~AliMUONTrackerData()
512 {
513   /// dtor
514   delete fChannelValues;
515   delete fManuValues;
516   delete fBusPatchValues;
517   delete fDEValues;
518   delete fChamberValues;
519   delete fPCBValues;
520   delete fDimensionNames;
521   delete fExternalDimensionNames;
522   delete[] fHistogramming;
523   delete fHistos;
524   delete[] fNofEventsPerDDL;
525 }
526
527 //_____________________________________________________________________________
528 Bool_t
529 AliMUONTrackerData::Add(const AliMUONVStore& store, TArrayI* nevents)
530 {
531   /// Add the given external store to our internal store
532   return InternalAdd(store,nevents,kFALSE);
533 }
534
535 //_____________________________________________________________________________
536 Bool_t 
537 AliMUONTrackerData::Add(const AliMUONTrackerData& data)
538 {
539   /// Add data to *this
540   // We do this by looping on all VCalibParam stored in the various containers,
541   // and simply adding the values there.
542   // Same thing for the number of events per DDL.
543   // Same thing for sparsehistograms, if we have some.
544
545   // First cross check we have compatible objects.
546   
547   if ( fIsChannelLevelEnabled != data.fIsChannelLevelEnabled ) 
548   {
549     AliError("Incompatible IsChannelLevelEnabled status");
550     return kFALSE;
551   }
552   
553   if ( fIsManuLevelEnabled != data.fIsManuLevelEnabled ) 
554   {
555     AliError("Incompatible IsManuLevelEnabled status");
556     return kFALSE;
557   }
558   
559   if ( fIsSingleEvent != data.fIsSingleEvent ) 
560   {
561     AliError("Incompatible IsSingleEvent status");
562     return kFALSE;
563   }
564   
565   if ( fDimension != data.fDimension || fExternalDimension != data.fExternalDimension ) 
566   {
567     AliError("Incompatible dimensions");
568     return kFALSE;
569   }
570
571   if ( fNofDDLs != data.fNofDDLs ) 
572   {
573     AliError("Incompatible number of Ddls");
574     return kFALSE;
575   }
576   
577   if ( ( !fHistogramming && data.fHistogramming ) || ( fHistogramming && !data.fHistogramming ) 
578       || fXmin != data.fXmin || fXmax != data.fXmax ) 
579   {
580     AliError(Form("Incompatible histogramming (%p vs %p) (xmax = %e vs %e ; xmin = %e vs %e)",
581              fHistogramming,data.fHistogramming,fXmax,data.fXmax,fXmin,data.fXmin));
582     return kFALSE;
583   }
584
585   if ( fHistogramming )
586   {
587     for ( Int_t i = 0; i < fExternalDimension; ++i ) 
588     {
589       if ( fHistogramming[i] != data.fHistogramming[i] )
590       {
591         AliError(Form("Incompatible histogramming for external dimension %d",i));
592         return kFALSE;
593       }
594     }
595   }
596   
597   // OK. Seems we have compatible objects, so we can proceed with the actual
598   // merging...
599   
600   if ( data.fChannelValues ) 
601   {
602     Add2D(*(data.fChannelValues),*fChannelValues);
603   }
604   
605   if ( data.fManuValues ) 
606   {
607     Add2D(*(data.fManuValues),*fManuValues);
608   }
609   
610   if ( data.fPCBValues ) 
611   {
612     Add2D(*(data.fPCBValues),*fPCBValues);
613   }
614   
615   if ( data.fBusPatchValues ) 
616   {
617     Add1D(*(data.fBusPatchValues),*fBusPatchValues);
618   }
619   
620   if ( data.fDEValues ) 
621   {
622     Add1D(*(data.fDEValues),*fDEValues);
623   }
624   
625   if ( data.fChamberValues ) 
626   {
627     Add1D(*(data.fChamberValues),*fChamberValues);
628   }
629
630   for ( Int_t i = 0; i < fNofDDLs; ++i ) 
631   {
632     fNofEventsPerDDL[i] += data.fNofEventsPerDDL[i];
633   }
634   
635   if ( data.fHistos ) 
636   {
637     TIter nexthisto(data.fHistos->CreateIterator());
638     AliMUONVStore* store;
639     while ( ( store = static_cast<AliMUONVStore*>(nexthisto()) ) )
640     {
641       TIter ns(store->CreateIterator());
642       AliMUONSparseHisto* h;
643       while ( ( h = static_cast<AliMUONSparseHisto*>(ns()) ) )
644       {
645         AliMUONVStore* thisStore = static_cast<AliMUONVStore*>(fHistos->FindObject(store->GetUniqueID()));
646         
647         if (!thisStore)
648         {
649           thisStore = store->Create();
650           thisStore->SetUniqueID(store->GetUniqueID());
651           fHistos->Add(thisStore);
652         }
653         
654         AliMUONSparseHisto* mine = static_cast<AliMUONSparseHisto*>(thisStore->FindObject(h->GetUniqueID()));
655         
656         if (!mine) 
657         {
658           thisStore->Add(h);
659         }
660         else
661         {
662           mine->Add(*h);
663         }
664       }
665     }
666   }
667   
668   fNevents =  TMath::Max(fNevents,data.fNevents);
669   
670   return kTRUE;
671 }
672
673 //_____________________________________________________________________________
674 void 
675 AliMUONTrackerData::Add2D(const AliMUONVStore& src, AliMUONVStore& dest) const
676 {
677   /// Add one 2d store to another
678   
679   TIter next(src.CreateIterator());
680   AliMUONVCalibParam* p;
681   
682   while ( ( p = static_cast<AliMUONVCalibParam*>(next()) ) )
683   {
684     AliMUONVCalibParam* a = static_cast<AliMUONVCalibParam*>(dest.FindObject(p->ID0(),p->ID1()));
685     
686     if (!a)
687     {
688       dest.Add(static_cast<AliMUONVCalibParam*>(p->Clone()));
689     }
690     else
691     {
692       AddCalibParams(*p,*a);
693     }
694   }
695 }
696
697 //_____________________________________________________________________________
698 void 
699 AliMUONTrackerData::Add1D(const AliMUONVStore& src, AliMUONVStore& dest) const
700 {
701   /// Add one 1d store to another
702   
703   TIter next(src.CreateIterator());
704   AliMUONVCalibParam* p;
705   
706   while ( ( p = static_cast<AliMUONVCalibParam*>(next()) ) )
707   {
708     AliMUONVCalibParam* a = static_cast<AliMUONVCalibParam*>(dest.FindObject(p->GetUniqueID()));
709     
710     if (!a)
711     {
712       dest.Add(static_cast<AliMUONVCalibParam*>(p->Clone()));
713     }
714     else
715     {
716       AddCalibParams(*p,*a);
717     }
718   }
719 }
720
721 //_____________________________________________________________________________
722 void
723 AliMUONTrackerData::AddCalibParams(const AliMUONVCalibParam& src, AliMUONVCalibParam& dest) const
724 {
725   /// Add src to dest
726   for ( Int_t i = 0; i < src.Size(); ++i ) 
727   {
728     for ( Int_t j = 0; j < src.Dimension(); ++j )
729     {
730       dest.SetValueAsFloat(i,j,src.ValueAsFloat(i,j));
731     }
732   }
733 }
734
735 //_____________________________________________________________________________
736 Bool_t
737 AliMUONTrackerData::Replace(const AliMUONVStore& store)
738 {
739   /// Replace our values by values from the given external store
740   Bool_t rv = InternalAdd(store,0x0,kTRUE);
741   AliMUONVTrackerData::Replace(store);
742   return rv;
743 }
744
745 //_____________________________________________________________________________
746 Bool_t
747 AliMUONTrackerData::UpdateNumberOfEvents(TArrayI* nevents)
748 {
749   /// Update the number of events
750   
751   if (!fNofDDLs)
752   {
753     fNofDDLs = AliDAQ::NumberOfDdls("MUONTRK");
754     fNofEventsPerDDL = new Int_t[fNofDDLs];
755     for ( Int_t i = 0; i < fNofDDLs; ++i ) 
756     {
757       fNofEventsPerDDL[i] = 0;
758     }
759   }
760   
761   if (nevents)
762   {
763     if (nevents->GetSize() != fNofDDLs ) 
764     {
765       AliError(Form("nof of ddl per event array size is incorrect : got %d, expecting %d",
766                     nevents->GetSize(),fNofDDLs));
767       return kFALSE;
768     }
769     
770     for ( Int_t i = 0 ; i < fNofDDLs; ++i ) 
771     {
772       fNofEventsPerDDL[i] += nevents->At(i);
773       fNevents = TMath::Max(fNevents,fNofEventsPerDDL[i]);
774     }
775   }
776   else
777   {
778     for ( Int_t i = 0 ; i < fNofDDLs; ++i ) 
779     {
780       ++fNofEventsPerDDL[i];
781       fNevents = TMath::Max(fNevents,fNofEventsPerDDL[i]);
782     }
783   }
784   return kTRUE;
785 }
786
787 //_____________________________________________________________________________
788 void
789 AliMUONTrackerData::AssertStores()
790 {
791   /// Insure our stores are allocated
792   
793   if (!fChamberValues)
794   {
795     Int_t numberOfBusPatches(0);
796     Int_t numberOfDEs(0);
797     
798     // get number of bus patches and number of detection element
799     // to initialize fBusPatchValues and fDEValues below
800     
801     TIter next(AliMpDDLStore::Instance()->CreateBusPatchIterator());
802     while ( next() ) ++numberOfBusPatches;
803     AliMpDEIterator deIt;
804     deIt.First();
805     while (!deIt.IsDone())
806     {
807       ++numberOfDEs;
808       deIt.Next();
809     }
810     
811     if ( fIsChannelLevelEnabled ) 
812     {
813       fChannelValues = new AliMUON2DMap(kTRUE);
814     }
815     if  ( fIsManuLevelEnabled ) 
816     {
817       fManuValues = new AliMUON2DMap(kTRUE);
818     }
819     if ( fIsPCBLevelEnabled )
820     {
821       fPCBValues = new AliMUON2DMap(kFALSE);
822     }
823     if ( fIsBustPatchLevelEnabled )
824     {
825       fBusPatchValues = new AliMUON1DMap(numberOfBusPatches);
826     }
827     fDEValues = new AliMUON1DMap(numberOfDEs);
828     fChamberValues = new AliMUON1DArray;
829   }
830 }
831
832 //_____________________________________________________________________________
833 Bool_t
834 AliMUONTrackerData::InternalAdd(const AliMUONVStore& store, TArrayI* nevents, Bool_t replace)
835 {
836   /// Add the given external store to our internal store
837   
838   AliCodeTimerAuto(GetName(),0);
839     
840   if ( !replace)
841   {
842     if ( IsSingleEvent() && NumberOfEvents(-1) == 1 ) 
843     {
844       AliError(Form("%s is supposed to be single event only",GetName()));
845       return kFALSE;
846     }  
847   }
848
849   UpdateNumberOfEvents(nevents);
850   
851   AssertStores();
852   
853   TIter next(store.CreateIterator());
854   AliMUONVCalibParam* external;
855   
856   Int_t nk(2);
857   
858   if ( IsSingleEvent() ) nk = 1;
859
860   while ( ( external = static_cast<AliMUONVCalibParam*>(next()) ) )
861   {
862     if ( external->Dimension() != ExternalDimension() )
863     {
864       AliError(Form("Incompatible dimensions %d vs %d",
865                     external->Dimension(),ExternalDimension()));
866       return kFALSE;
867     }
868     
869     AliMUONVCalibParam* chamber(0x0);
870     AliMUONVCalibParam* de(0x0);
871     AliMUONVCalibParam* busPatch(0x0);
872     AliMUONVCalibParam* pcb(0x0);
873     AliMUONVCalibParam* manu(0x0);
874     AliMUONVCalibParam* channel(0x0);
875     AliMpDetElement* mpde(0x0);
876     
877     Int_t manuId = GetParts(external,chamber,de,busPatch,pcb,manu,channel,mpde);
878     
879     if ( manuId < 0 ) continue;
880     
881     Int_t detElemId = mpde->GetId();
882     
883     Double_t value[] = { 0.0, 0.0 };
884     
885     Int_t nch = mpde->NofChannelsInManu(manuId);
886     
887     for ( Int_t i = 0; i < external->Size(); ++i ) 
888     {
889       Bool_t existingChannel =  ( nch == AliMpConstants::ManuNofChannels() ? kTRUE
890                                                                            : mpde->IsConnectedChannel(manuId,i));
891       // note we only use IsConnectedChannel method when really needed, as
892       // it costs (some) CPU time...
893       
894       if ( existingChannel ) 
895       {
896         Bool_t validChannel(kFALSE);
897         
898         for ( Int_t j = 0; j < external->Dimension(); ++j )
899         {
900           Double_t vext = external->IsDoublePrecision() ? 
901             external->ValueAsDoubleFast(i,j) :
902             external->ValueAsFloatFast(i,j);
903           
904           if ( vext >= AliMUONVCalibParam::InvalidFloatValue() ) continue;
905           
906           validChannel = kTRUE;
907                     
908           Int_t ix = External2Internal(j);
909           
910           value[0] = vext;
911           value[1] = vext*vext;
912           
913           if ( IsHistogrammed(j) )
914           {
915             FillHisto(detElemId,manuId,i,j,vext);
916           }
917           
918           for ( Int_t k = 0; k < nk; ++k ) 
919           {
920             Double_t e = ( replace && channel ) ? channel->ValueAsDoubleFast(i,ix+k) : 0.0;
921             
922                                                 if ( channel ) 
923                                                 {
924                                                         channel->SetValueAsDoubleFast(i,ix+k,channel->ValueAsDoubleFast(i,ix+k)-e+value[k]);
925                                                 }
926                                                 
927             if (manu)
928             {
929               manu->SetValueAsDoubleFast(0,ix+k,manu->ValueAsDoubleFast(0,ix+k)-e+value[k]);            
930             }
931             
932             busPatch->SetValueAsDoubleFast(0,ix+k,busPatch->ValueAsDoubleFast(0,ix+k)-e+value[k]);
933             
934             de->SetValueAsDoubleFast(0,ix+k,de->ValueAsDoubleFast(0,ix+k)-e+value[k]);
935             
936             chamber->SetValueAsDoubleFast(0,ix+k,chamber->ValueAsDoubleFast(0,ix+k)-e+value[k]);
937             
938             if ( pcb ) 
939             {
940               pcb->SetValueAsDoubleFast(0,ix+k,pcb->ValueAsDoubleFast(0,ix+k)-e+value[k]);
941             }
942           }
943         }
944         
945         if ( validChannel && !replace )
946         {
947                                         if ( channel ) 
948                                         {
949                                                 channel->SetValueAsDoubleFast(i,IndexOfOccupancyDimension(),
950                                                                                                                                                                         channel->ValueAsDoubleFast(i,IndexOfOccupancyDimension())+1.0);
951                                         }
952                                         
953           if (manu)
954           {
955             manu->SetValueAsDoubleFast(0,IndexOfOccupancyDimension(),
956                                        manu->ValueAsDoubleFast(0,IndexOfOccupancyDimension())+1.0);        
957           }
958           
959           busPatch->SetValueAsDoubleFast(0,IndexOfOccupancyDimension(),
960                                                          busPatch->ValueAsDoubleFast(0,IndexOfOccupancyDimension())+1.0);        
961           de->SetValueAsDoubleFast(0,IndexOfOccupancyDimension(),
962                                              de->ValueAsDoubleFast(0,IndexOfOccupancyDimension())+1.0);        
963           chamber->SetValueAsDoubleFast(0,IndexOfOccupancyDimension(),
964                                                        chamber->ValueAsDoubleFast(0,IndexOfOccupancyDimension())+1.0); 
965           if ( pcb ) 
966           {
967             pcb->SetValueAsDoubleFast(0,IndexOfOccupancyDimension(),
968                                       pcb->ValueAsDoubleFast(0,IndexOfOccupancyDimension())+1.0);        
969           }
970         }
971       }
972     }
973   }
974   
975   NumberOfEventsChanged();
976   
977   return kTRUE;
978 }
979
980 //_____________________________________________________________________________
981 Double_t 
982 AliMUONTrackerData::BusPatch(Int_t busPatchId, Int_t dim) const
983 {
984   /// Return the value of a given buspatch for a given dimension
985   /// or 0 if not existing
986   AliMUONVCalibParam* param = BusPatchParam(busPatchId);
987   return param ? Value(*param,0,dim,DdlIdFromBusPatchId(busPatchId)) : 0.0;
988 }
989
990 //_____________________________________________________________________________
991 AliMUONVCalibParam* 
992 AliMUONTrackerData::BusPatchParam(Int_t busPatchId, Bool_t create) const
993 {
994   /// Return (if it exist), the VCalibParam for a given busPatch
995   
996   AliMUONVCalibParam* busPatch = fBusPatchValues ? static_cast<AliMUONVCalibParam*>
997     (fBusPatchValues->FindObject(busPatchId)) : 0x0;
998   
999   if (!busPatch && create && fBusPatchValues)
1000   {
1001     busPatch = CreateBusPatchParam(busPatchId);
1002     fBusPatchValues->Add(busPatch);
1003   }
1004   
1005   return busPatch;
1006 }
1007
1008 //_____________________________________________________________________________
1009 AliMUONVCalibParam* 
1010 AliMUONTrackerData::CreateBusPatchParam(Int_t busPatchId) const
1011 {
1012   /// Create storage for one bus patch
1013   
1014   AliCodeTimerAuto("",0);
1015   
1016   AliMpBusPatch* bp = AliMpDDLStore::Instance()->GetBusPatch(busPatchId);
1017   
1018   if (!bp)
1019   {
1020     AliError(Form("Got an invalid buspatchId = %d",busPatchId));
1021     return 0x0;
1022   }
1023   
1024   AliMUONVCalibParam* busPatch = new AliMUONCalibParamND(Dimension(),1,busPatchId,0,0.0);
1025   
1026   // set the number of channels in that buspatch
1027   
1028   Int_t nchannels(0);
1029   
1030   Int_t detElemId = AliMpDDLStore::Instance()->GetDEfromBus(busPatchId);
1031   
1032   AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(detElemId);
1033   
1034   for ( Int_t i = 0; i < bp->GetNofManus(); ++i ) 
1035   {
1036     Int_t manuId = bp->GetManuId(i);
1037     nchannels += de->NofChannelsInManu(manuId);
1038   }
1039   
1040   busPatch->SetValueAsDouble(0,IndexOfNumberDimension(),nchannels);
1041   
1042   return busPatch;
1043 }
1044
1045 //_____________________________________________________________________________
1046 Double_t 
1047 AliMUONTrackerData::Chamber(Int_t chamberId, Int_t dim) const
1048 {
1049   /// Return the value fo a given chamber for a given dimension,
1050   /// or zero if not existing
1051   
1052   // FIXME: is the Value() correct wrt to number of events in the case of
1053   // chamber ? Or should we do something custom at the chamber level 
1054   // (as it spans several ddls) ?
1055   
1056   AliMUONVCalibParam* param = ChamberParam(chamberId);
1057   return param ? Value(*param,0,dim,DdlIdFromChamberId(chamberId)) : 0.0;
1058 }
1059
1060 //_____________________________________________________________________________
1061 AliMUONVCalibParam* 
1062 AliMUONTrackerData::ChamberParam(Int_t chamberId, Bool_t create) const
1063 {
1064   /// Return (if it exist) the VCalibParam for a given chamber
1065   
1066   AliMUONVCalibParam* chamber =  fChamberValues ? static_cast<AliMUONVCalibParam*>
1067   (fChamberValues->FindObject(chamberId)) : 0x0;
1068   
1069   if (!chamber && create && fChamberValues)
1070   {
1071     chamber = CreateChamberParam(chamberId);
1072     fChamberValues->Add(chamber);
1073   }
1074     
1075   return chamber;
1076 }
1077
1078 //_____________________________________________________________________________
1079 AliMUONVCalibParam* 
1080 AliMUONTrackerData::CreateChamberParam(Int_t chamberId) const
1081 {
1082   /// Create storage for one chamber
1083   
1084   AliCodeTimerAuto("",0);
1085   
1086   AliMUONVCalibParam* chamber = new AliMUONCalibParamND(Dimension(),1,chamberId,0,0.0);
1087   
1088   // set the number of channels in that chamber
1089   
1090   Int_t nchannels(0);
1091   
1092   AliMpDEIterator it;
1093   
1094   it.First(chamberId);
1095   
1096   while ( !it.IsDone() )
1097   {        
1098     AliMpDetElement* det = it.CurrentDE();
1099     
1100     for ( Int_t i = 0; i < det->GetNofBusPatches(); ++i ) 
1101     {
1102       Int_t busPatchId = det->GetBusPatchId(i);
1103       AliMpBusPatch* bp = AliMpDDLStore::Instance()->GetBusPatch(busPatchId);
1104       for ( Int_t j = 0; j < bp->GetNofManus(); ++j ) 
1105       {
1106         Int_t manuId = bp->GetManuId(j);
1107         nchannels += det->NofChannelsInManu(manuId);
1108       }        
1109     }
1110     
1111     it.Next();
1112   }
1113   
1114   chamber->SetValueAsDouble(0,IndexOfNumberDimension(),nchannels);
1115   
1116   return chamber;
1117 }
1118
1119 //_____________________________________________________________________________
1120 Double_t 
1121 AliMUONTrackerData::Channel(Int_t detElemId, Int_t manuId, 
1122                             Int_t manuChannel, Int_t dim) const
1123 {
1124   /// Return the value for a given channel for a given dimension
1125   
1126   AliMUONVCalibParam* param = ChannelParam(detElemId,manuId);
1127   
1128   return param ? Value(*param,manuChannel,dim,DdlIdFromDetElemId(detElemId)) : 0.0;
1129 }
1130
1131 //_____________________________________________________________________________
1132 AliMUONVCalibParam* 
1133 AliMUONTrackerData::ChannelParam(Int_t detElemId, Int_t manuId,
1134                                  const AliMUONVCalibParam* external) const
1135 {
1136   /// Return (if it exist) the VCalibParam for a given manu
1137   
1138   AliMUONVCalibParam* param = fChannelValues ? static_cast<AliMUONVCalibParam*>
1139     (fChannelValues->FindObject(detElemId,manuId)) : 0x0 ;
1140   
1141   if (!param && external && fChannelValues)
1142   {
1143     param = CreateDouble(*external,detElemId,manuId);
1144     fChannelValues->Add(param);
1145   }
1146   
1147   return param;
1148 }
1149
1150 //_____________________________________________________________________________
1151 void 
1152 AliMUONTrackerData::Clear(Option_t*)
1153 {
1154   /// Clear all the values
1155   if ( fChannelValues ) fChannelValues->Clear();
1156   if ( fManuValues ) fManuValues->Clear();
1157   if ( fBusPatchValues) fBusPatchValues->Clear();
1158   if ( fPCBValues ) fPCBValues->Clear();
1159   if ( fDEValues) fDEValues->Clear();
1160   if ( fChamberValues ) fChamberValues->Clear();
1161   if ( fHistos ) fHistos->Clear();
1162   for ( Int_t i = 0; i < fNofDDLs; ++i ) 
1163   {
1164     fNofEventsPerDDL[i] = 0;
1165   }
1166   fNevents = 0;
1167   NumberOfEventsChanged();
1168 }
1169
1170 //_____________________________________________________________________________
1171 Double_t 
1172 AliMUONTrackerData::Count(Int_t detElemId, Int_t manuId, 
1173                           Int_t manuChannel) const
1174 {
1175   /// Return the number of times a given channel had data
1176   
1177   return Channel(detElemId,manuId,manuChannel,IndexOfNumberDimension());
1178 }
1179
1180 //_____________________________________________________________________________
1181 AliMUONVCalibParam*
1182 AliMUONTrackerData::CreateDouble(const AliMUONVCalibParam& param, 
1183                                  Int_t detElemId, Int_t manuId) const
1184 {
1185   /// Create a double version of VCalibParam, for internal use
1186   
1187   AliCodeTimerAuto("",0);
1188   
1189   AliMUONVCalibParam* c = new AliMUONCalibParamND(Dimension(),
1190                                                   param.Size(),
1191                                                   detElemId,
1192                                                   manuId,
1193                                                   0.0);
1194   
1195   AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(detElemId,manuId);
1196   
1197   for ( Int_t i = 0; i < c->Size(); ++i ) 
1198   {
1199     Double_t value(0.0);
1200     
1201     if ( de->IsConnectedChannel(manuId,i) ) value = 1.0;
1202       
1203     c->SetValueAsDouble(i,IndexOfNumberDimension(),value);
1204   }
1205   
1206   return c;
1207 }
1208
1209 //_____________________________________________________________________________
1210 Double_t 
1211 AliMUONTrackerData::DetectionElement(Int_t detElemId, Int_t dim) const
1212 {
1213   /// Return the value for a given detection element for a given dimension
1214   AliMUONVCalibParam* param = DetectionElementParam(detElemId);
1215   return param ? Value(*param,0,dim,DdlIdFromDetElemId(detElemId)) : 0.0;
1216
1217 }
1218
1219 //_____________________________________________________________________________
1220 AliMUONVCalibParam* 
1221 AliMUONTrackerData::DetectionElementParam(Int_t detElemId, Bool_t create) const
1222 {
1223   /// Return (if it exist) the VCalibParam for a given detection element
1224   
1225   AliMUONVCalibParam* de = fDEValues ? static_cast<AliMUONVCalibParam*>
1226     (fDEValues->FindObject(detElemId)) : 0x0 ;
1227   
1228   if (!de && create && fDEValues)
1229   {
1230     de = CreateDetectionElementParam(detElemId);
1231     fDEValues->Add(de);
1232   }
1233   
1234   return de;
1235   
1236 }
1237
1238 //_____________________________________________________________________________
1239 AliMUONVCalibParam* 
1240 AliMUONTrackerData::CreateDetectionElementParam(Int_t detElemId) const
1241 {
1242   /// Create storage for one detection element
1243   
1244   AliCodeTimerAuto("",0);
1245   
1246   AliMUONVCalibParam*  de = new AliMUONCalibParamND(Dimension(),1,detElemId,0,0.0);
1247   
1248   AliMpDetElement* det = AliMpDDLStore::Instance()->GetDetElement(detElemId);
1249   Int_t nchannels(0);
1250   
1251   for ( Int_t i = 0; i < det->GetNofBusPatches(); ++i ) 
1252   {
1253     Int_t busPatchId = det->GetBusPatchId(i);
1254     AliMpBusPatch* bp = AliMpDDLStore::Instance()->GetBusPatch(busPatchId);
1255     for ( Int_t j = 0; j < bp->GetNofManus(); ++j ) 
1256     {
1257       Int_t manuId = bp->GetManuId(j);
1258       nchannels += det->NofChannelsInManu(manuId);
1259     }        
1260   }
1261   
1262   de->SetValueAsDouble(0,IndexOfNumberDimension(),nchannels);
1263   
1264   return de;
1265 }
1266
1267 //_____________________________________________________________________________
1268 Int_t 
1269 AliMUONTrackerData::DdlIdFromBusPatchId(Int_t buspatchid) const
1270 {
1271   /// Get the "local" ddlid (0..19) of a given buspatch
1272   AliMpBusPatch* bp = AliMpDDLStore::Instance()->GetBusPatch(buspatchid);
1273   if (bp)
1274   {
1275     return bp->GetDdlId();
1276   }
1277   return -1;
1278 }
1279
1280 //_____________________________________________________________________________
1281 Int_t 
1282 AliMUONTrackerData::DdlIdFromDetElemId(Int_t detelemid) const
1283 {
1284   /// Get the "local" ddlid (0..19) of a given detection element
1285   AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(detelemid);
1286   if (de)
1287   {
1288     return de->GetDdlId();
1289   }
1290   return -1;
1291 }
1292
1293 //_____________________________________________________________________________
1294 Int_t 
1295 AliMUONTrackerData::DdlIdFromChamberId(Int_t chamberid) const
1296 {
1297   /// Get the "local" ddlid (0..19) of a given chamber
1298   /// This has no real meaning (as there are several ddls per chamber),
1299   /// so we take the ddlid where we got the max number of events
1300   
1301   AliMpDEIterator it;
1302   
1303   it.First(chamberid);
1304   Int_t n(0);
1305   Int_t d(-1);
1306   
1307   while (!it.IsDone())
1308   {
1309     Int_t detElemId = it.CurrentDEId();
1310     Int_t ddlId = DdlIdFromDetElemId(detElemId);
1311     if ( NumberOfEvents(ddlId) > n ) 
1312     {
1313       n = NumberOfEvents(ddlId);
1314       d = ddlId;
1315     }
1316     it.Next();
1317   }
1318   
1319   return d;
1320 }
1321
1322 //_____________________________________________________________________________
1323 TString 
1324 AliMUONTrackerData::DimensionName(Int_t dim) const
1325 {
1326   /// Get the name of a given dimension
1327   TObjString* value = static_cast<TObjString*>(fDimensionNames->At(dim));
1328   if ( value ) 
1329   {
1330     return value->String();
1331   }
1332   else
1333   {
1334     return TString("Invalid");
1335   }  
1336 }
1337
1338 //_____________________________________________________________________________
1339 void 
1340 AliMUONTrackerData::DisableChannelLevel()
1341
1342   /// Disable the storing of data at channel level
1343   
1344   delete fChannelValues;
1345   fChannelValues = 0x0;
1346   fIsChannelLevelEnabled = kFALSE; 
1347 }
1348
1349 //_____________________________________________________________________________
1350 void 
1351 AliMUONTrackerData::DisableManuLevel()
1352
1353   /// Disable the storing of data at manu level (and below)
1354   
1355   DisableChannelLevel();
1356   delete fManuValues;
1357   fManuValues = 0x0;
1358   fIsManuLevelEnabled = kFALSE; 
1359 }
1360
1361 //_____________________________________________________________________________
1362 Int_t 
1363 AliMUONTrackerData::External2Internal(Int_t index) const 
1364 {
1365   /// From external to internal dimension
1366   return IsSingleEvent() ? index : index*2;
1367 }
1368
1369 //_____________________________________________________________________________
1370 TString 
1371 AliMUONTrackerData::ExternalDimensionName(Int_t dim) const
1372 {
1373   /// Get the name of a given external dimension
1374   
1375   TObjString* value = static_cast<TObjString*>(fExternalDimensionNames->At(dim));
1376   if ( value ) 
1377   {
1378     return value->String();
1379   }
1380   else
1381   {
1382     return TString("Invalid");
1383   }  
1384 }
1385
1386 //_____________________________________________________________________________
1387 void
1388 AliMUONTrackerData::FillHisto(Int_t detElemId, Int_t manuId, Int_t manuChannel,
1389                               Int_t dim, Double_t value)
1390 {
1391   /// Fill histogram of a given channel
1392   
1393   AliMUONSparseHisto* h(0x0);
1394   
1395         if ( fIsChannelLevelEnabled ) 
1396         {
1397                 h = GetChannelSparseHisto(detElemId, manuId, manuChannel,dim);
1398   }
1399   else if ( fIsManuLevelEnabled ) 
1400   {
1401     h = GetManuSparseHisto(detElemId,manuId,dim);
1402   }
1403   
1404   AliDebug(1,Form("DE %04d MANU %04d CH %02d dim %d value %e h %p",detElemId,manuId,manuChannel,dim,value,h));
1405   
1406   if (h)
1407   {
1408                 h->Fill(static_cast<Int_t>(TMath::Nint(value)));
1409         }
1410 }
1411
1412 //_____________________________________________________________________________
1413 AliMUONSparseHisto*
1414 AliMUONTrackerData::GetManuSparseHisto(Int_t detElemId, Int_t manuId, 
1415                                        Int_t dim) const
1416 {
1417   /// Get histogram of a given manu
1418   
1419   if (!fHistos) return 0x0;
1420   
1421   AliMUON1DArray* m = static_cast<AliMUON1DArray*>(fHistos->FindObject(detElemId,manuId));
1422   if (!m) return 0x0;
1423   
1424   AliMUONSparseHisto* h = static_cast<AliMUONSparseHisto*>(m->FindObject(dim));
1425   
1426   return h;
1427 }
1428
1429 //_____________________________________________________________________________
1430 AliMUONSparseHisto*
1431 AliMUONTrackerData::GetManuSparseHisto(Int_t detElemId, Int_t manuId, Int_t dim)
1432 {
1433   /// Get histogram of a given manu. Create it if necessary
1434   
1435   if (!fHistos) fHistos = new AliMUON2DMap(kTRUE);
1436   
1437   AliMUON1DArray* m = static_cast<AliMUON1DArray*>(fHistos->FindObject(detElemId,manuId));
1438   if (!m)
1439   {
1440     m = new AliMUON1DArray(NumberOfDimensions());
1441     m->SetUniqueID( ( manuId << 16 ) | detElemId );
1442     fHistos->Add(m);
1443   }
1444     
1445   AliMUONSparseHisto* h = static_cast<AliMUONSparseHisto*>(m->FindObject(dim));
1446   if (!h)
1447   {
1448     h = new AliMUONSparseHisto(fXmin,fXmax);
1449     
1450     h->SetUniqueID(dim);
1451     
1452     m->Add(h);
1453   }
1454   
1455    return h;
1456 }
1457
1458 //_____________________________________________________________________________
1459 AliMUONSparseHisto*
1460 AliMUONTrackerData::GetChannelSparseHisto(Int_t detElemId, Int_t manuId, 
1461                                           Int_t manuChannel, Int_t dim) const
1462 {
1463   /// Get histogram of a given channel
1464   
1465   if (!fHistos) return 0x0;
1466   
1467   AliMUON1DMap* m = static_cast<AliMUON1DMap*>(fHistos->FindObject(detElemId,manuId));
1468   if (!m) return 0x0;
1469   
1470   UInt_t uid = ( manuChannel << 16 ) | dim;
1471   
1472   AliMUONSparseHisto* h = static_cast<AliMUONSparseHisto*>(m->FindObject(uid));
1473   
1474   return h;
1475 }
1476
1477 //_____________________________________________________________________________
1478 AliMUONSparseHisto*
1479 AliMUONTrackerData::GetChannelSparseHisto(Int_t detElemId, Int_t manuId, 
1480                                           Int_t manuChannel, Int_t dim)
1481 {
1482   /// Get histogram of a given channel. Create it if necessary
1483   
1484   if (!fHistos) fHistos = new AliMUON2DMap(kTRUE);
1485   
1486   AliMUON1DMap* m = static_cast<AliMUON1DMap*>(fHistos->FindObject(detElemId,manuId));
1487   if (!m)
1488   {
1489     m = new AliMUON1DMap(AliMpConstants::ManuNofChannels()); // start with only 1 dim
1490     m->SetUniqueID( ( manuId << 16 ) | detElemId );
1491     fHistos->Add(m);
1492   }
1493   
1494   UInt_t uid = ( manuChannel << 16 ) | dim;
1495   
1496   AliMUONSparseHisto* h = static_cast<AliMUONSparseHisto*>(m->FindObject(uid));
1497   if (!h)
1498   {
1499     h = new AliMUONSparseHisto(fXmin,fXmax);
1500     
1501     h->SetUniqueID(uid);
1502     
1503     m->Add(h);
1504   }
1505
1506   return h;
1507 }
1508
1509 //_____________________________________________________________________________
1510 void
1511 AliMUONTrackerData::GetDEManu(const AliMUONVCalibParam& param,
1512                               Int_t& detElemId, Int_t& manuId) const
1513 {
1514   /// Tries to get (detElemId,manuId) of param
1515   
1516   // Load mapping manu store
1517   if ( ! AliMpCDB::LoadManuStore() ) {
1518     AliError("Could not access manu store from OCDB !");
1519     return;
1520   }
1521
1522   if ( param.ID1() <= 0 ) 
1523   {
1524     // we (probably) get a manu serial number
1525     Int_t serial = param.ID0();
1526     MpPair_t pair = AliMpManuStore::Instance()->GetDetElemIdManu(serial);
1527     detElemId = AliMp::PairFirst(pair);
1528     manuId = AliMp::PairSecond(pair);
1529     if ( !detElemId ) 
1530     {
1531       AliDebug(1,Form("DE %d manuId %d from serial %d is not correct !",
1532                       detElemId,manuId,serial));
1533     }
1534   }
1535   else
1536   {
1537     // we get a (de,manu) pair
1538     detElemId = param.ID0();
1539     manuId = param.ID1();
1540   }
1541 }
1542
1543
1544 //_____________________________________________________________________________
1545 Int_t
1546 AliMUONTrackerData::GetParts(AliMUONVCalibParam* external,
1547                              AliMUONVCalibParam*& chamber,
1548                              AliMUONVCalibParam*& de,
1549                              AliMUONVCalibParam*& busPatch,
1550                              AliMUONVCalibParam*& pcb,
1551                              AliMUONVCalibParam*& manu,
1552                              AliMUONVCalibParam*& channel,
1553                              AliMpDetElement*& mpde)
1554 {
1555   /// Get containers at all levels
1556  
1557   chamber = de = busPatch = pcb = manu = channel = 0x0;
1558   mpde = 0x0;
1559   
1560   AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
1561   
1562   Int_t detElemId;
1563   Int_t manuId;
1564   
1565   GetDEManu(*external,detElemId,manuId);
1566   
1567   mpde = ddlStore->GetDetElement(detElemId,kFALSE);
1568
1569   if (!mpde) // can happen if reading e.g. capacitances store where we have data for non-connected manus
1570   {
1571     return -1;
1572   }
1573   
1574   // explicitely check that de,manu is correct
1575   const AliMpVSegmentation* mpseg = AliMpSegmentation::Instance()->GetMpSegmentationByElectronics(detElemId, manuId,kFALSE);
1576   
1577   if (!mpseg)
1578   {
1579     return -1;
1580   }
1581   
1582   Int_t chamberId = AliMpDEManager::GetChamberId(detElemId);
1583     
1584   Int_t busPatchId = ddlStore->GetBusPatchId(detElemId,manuId);
1585   
1586   if ( busPatchId <= 0 )
1587   {
1588     return -1;
1589   }
1590   
1591   Int_t pcbIndex = -1;
1592   
1593   AliMp::StationType stationType = mpde->GetStationType();
1594   
1595   if ( stationType == AliMp::kStation345 ) 
1596   {
1597     AliMpDCSNamer namer("TRACKER");
1598     pcbIndex = namer.ManuId2PCBIndex(detElemId,manuId);
1599   }
1600   
1601   if ( fIsChannelLevelEnabled ) 
1602   {
1603     channel = ChannelParam(detElemId,manuId,external);
1604   }
1605   
1606   manu = ManuParam(detElemId,manuId,kTRUE);
1607   
1608   busPatch = BusPatchParam(busPatchId,kTRUE);
1609   
1610   de = DetectionElementParam(detElemId,kTRUE);
1611   
1612   chamber = ChamberParam(chamberId,kTRUE);
1613   
1614   pcb = 0x0;
1615   
1616   if ( pcbIndex >= 0 ) 
1617   {
1618     pcb = PCBParam(detElemId,pcbIndex,kTRUE);
1619   }
1620   
1621   return manuId;
1622 }
1623
1624 //_____________________________________________________________________________
1625 Bool_t 
1626 AliMUONTrackerData::HasBusPatch(Int_t busPatchId) const
1627 {
1628   /// Whether we have data for a given buspatch
1629   return ( BusPatchParam(busPatchId) != 0 );
1630 }
1631
1632 //_____________________________________________________________________________
1633 Bool_t 
1634 AliMUONTrackerData::HasChamber(Int_t chamberId) const
1635 {
1636   /// Whether we have data for a given chamber
1637   return ( ChamberParam(chamberId) != 0 );
1638 }
1639
1640 //_____________________________________________________________________________
1641 Bool_t 
1642 AliMUONTrackerData::HasDetectionElement(Int_t detElemId) const
1643 {
1644   /// Whether we have data for a given detection element
1645   return ( DetectionElementParam(detElemId) != 0 );
1646 }
1647
1648 //_____________________________________________________________________________
1649 Bool_t
1650 AliMUONTrackerData::HasManu(Int_t detElemId, Int_t manuId) const
1651 {
1652   /// Whether we have data for a given manu
1653   return ( ManuParam(detElemId,manuId) != 0 ); 
1654 }
1655
1656 //_____________________________________________________________________________
1657 Bool_t
1658 AliMUONTrackerData::HasPCB(Int_t detElemId, Int_t pcbIndex) const
1659 {
1660   /// Whether we have data for a given pcb
1661   return ( PCBParam(detElemId,pcbIndex) != 0 ); 
1662 }
1663
1664 //_____________________________________________________________________________
1665 Double_t 
1666 AliMUONTrackerData::Manu(Int_t detElemId, Int_t manuId, Int_t dim) const
1667 {
1668   /// Return the value for a given manu and a given dimension
1669   
1670   AliMUONVCalibParam* param = ManuParam(detElemId,manuId);
1671   return param ? Value(*param,0,dim,DdlIdFromDetElemId(detElemId)) : 0.0;
1672 }
1673
1674 //_____________________________________________________________________________
1675 AliMUONVCalibParam* 
1676 AliMUONTrackerData::ManuParam(Int_t detElemId, Int_t manuId, Bool_t create) const
1677 {
1678   /// Get the VCalibParam for a given manu
1679   
1680   AliMUONVCalibParam* manu = fManuValues ? static_cast<AliMUONVCalibParam*>
1681     (fManuValues->FindObject(detElemId,manuId)) : 0x0 ;
1682   
1683   if (!manu && create && fManuValues)
1684   {
1685     manu = CreateManuParam(detElemId,manuId);
1686     fManuValues->Add(manu);
1687   }
1688   
1689   return manu;
1690 }
1691
1692 //_____________________________________________________________________________
1693 AliMUONVCalibParam* 
1694 AliMUONTrackerData::CreateManuParam(Int_t detElemId, Int_t manuId) const
1695 {
1696   /// Create storage for one manu
1697   
1698   AliCodeTimerAuto("",0);
1699   
1700   AliMUONVCalibParam* manu = new AliMUONCalibParamND(Dimension(),1,detElemId,manuId,0.0);
1701   
1702   // set the number of channels in that manu
1703   
1704   AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(detElemId);
1705   
1706   manu->SetValueAsDouble(0,IndexOfNumberDimension(),de->NofChannelsInManu(manuId));
1707   
1708   return manu;
1709 }
1710
1711 //_____________________________________________________________________________
1712 Long64_t
1713 AliMUONTrackerData::Merge(TCollection* list)
1714 {
1715   /// Merge this with a list of AliMUONVTrackerData
1716
1717   if (!list) return 0;
1718   
1719   if ( list->IsEmpty() ) return NumberOfEvents(-1);
1720   
1721   TIter next(list);
1722   const TObject* o(0x0);
1723   
1724   while ( ( o = next() ) )
1725   {
1726     const AliMUONTrackerData* data = dynamic_cast<const AliMUONTrackerData*>(o);
1727     if (!data)
1728     {
1729       AliError(Form("Object named %s is not an AliMUONTrackerData ! Skipping it",
1730                     o->GetName()));
1731     }
1732     else
1733     {
1734       Bool_t ok = Add(*data);
1735       if (!ok)
1736       {
1737         AliError("Got incompatible objects");
1738       }
1739     }
1740   }
1741   
1742   return NumberOfEvents(-1);
1743 }
1744
1745 //_____________________________________________________________________________
1746 Int_t 
1747 AliMUONTrackerData::NumberOfDimensions() const
1748 {
1749   /// Number of dimensions we're dealing with
1750   
1751   return fDimension + fgkVirtualExtraDimension; 
1752 }
1753
1754 //_____________________________________________________________________________
1755 Int_t
1756 AliMUONTrackerData::NumberOfEvents(Int_t ddlNumber) const
1757 {
1758   /// Get the number of events we've seen for a given DDL, or the max
1759   /// in case ddlNumber<0
1760
1761   Int_t n(0);
1762   
1763   if ( fNofEventsPerDDL && ddlNumber >= 0 && ddlNumber < fNofDDLs )
1764   {
1765     n = fNofEventsPerDDL[ddlNumber];
1766   }
1767   else
1768   {
1769     // get the max number of events
1770     return fNevents;
1771   }
1772   
1773   return n;
1774 }
1775
1776 //_____________________________________________________________________________
1777 Double_t 
1778 AliMUONTrackerData::PCB(Int_t detElemId, Int_t pcbIndex, Int_t dim) const
1779 {
1780   /// Return the value of a given pcb for a given dimension
1781
1782   AliMUONVCalibParam* param = PCBParam(detElemId,pcbIndex);
1783   
1784   return param ? Value(*param,0,dim,DdlIdFromDetElemId(detElemId)) : 0.0;
1785 }
1786
1787 //_____________________________________________________________________________
1788 AliMUONVCalibParam* 
1789 AliMUONTrackerData::PCBParam(Int_t detElemId, Int_t pcbIndex, Bool_t create) const
1790 {
1791   /// Return (if it exist) the VCalibParam for a given pcb
1792
1793   AliMUONVCalibParam* pcb =  fPCBValues ? static_cast<AliMUONVCalibParam*>
1794     (fPCBValues->FindObject(detElemId,pcbIndex)) : 0x0 ;
1795   
1796   if (create && fPCBValues && !pcb)
1797   {
1798     pcb = CreatePCBParam(detElemId,pcbIndex);
1799     fPCBValues->Add(pcb);
1800   }
1801   
1802   return pcb;
1803 }
1804
1805 //_____________________________________________________________________________
1806 AliMUONVCalibParam* 
1807 AliMUONTrackerData::CreatePCBParam(Int_t detElemId, Int_t pcbIndex) const
1808 {
1809   /// Create storage for one PCB (station345 only)
1810   
1811   AliCodeTimerAuto("",0);
1812   
1813   AliMpDCSNamer namer("TRACKER");
1814   
1815   AliMUONVCalibParam* pcb = new AliMUONCalibParamND(Dimension(),
1816                                                     namer.NumberOfPCBs(detElemId),
1817                                                     detElemId,
1818                                                     pcbIndex,
1819                                                     0.0);
1820   return pcb;
1821 }
1822
1823 //_____________________________________________________________________________
1824 void 
1825 AliMUONTrackerData::Print(Option_t* wildcard, Option_t* opt) const
1826 {
1827   /// Printout
1828   
1829   TNamed::Print(opt);
1830   
1831   if ( !fIsSingleEvent ) 
1832   {
1833     for ( Int_t i = 0; i < fNofDDLs; ++i ) 
1834     {
1835       cout << Form("DDL %04d Nevents=%10d",AliDAQ::DdlID("MUONTRK",i),fNofEventsPerDDL[i]) << endl;
1836     }
1837   }
1838
1839         if ( !fIsChannelLevelEnabled ) 
1840         {
1841                 cout << "Is not storing data at the channel level" << endl;
1842         }
1843
1844   if ( !fIsManuLevelEnabled ) 
1845         {
1846                 cout << "Is not storing data at the manu level" << endl;
1847         }
1848   
1849   for ( Int_t i = 0; i <= fExternalDimensionNames->GetLast(); ++i ) 
1850   {
1851     TObjString* name = static_cast<TObjString*>(fExternalDimensionNames->At(i));
1852     cout << Form("External Dimension %2d Name %s %s",i,
1853                  ( name ? name->String().Data() : "null"),
1854                  ( IsHistogrammed(i) ? "(histogrammed)" : "")) << endl;
1855   }
1856   
1857   for ( Int_t i = 0; i <= fDimensionNames->GetLast(); ++i ) 
1858   {
1859     TObjString* name = static_cast<TObjString*>(fDimensionNames->At(i));
1860     cout << Form("Internal Dimension %2d Name %s",i,
1861                  ( name ? name->String().Data() : "null")) << endl;
1862   }
1863     
1864   TString sopt(opt);
1865   sopt.ToUpper();
1866   
1867   if ( sopt.Contains("CHANNEL") )
1868   {
1869     if ( fIsChannelLevelEnabled ) 
1870     {      
1871       if ( fChannelValues ) fChannelValues->Print(wildcard,opt);
1872     }
1873     else
1874     {
1875       AliWarning("You requested channel values, but they were not stored !");
1876     }
1877   }
1878
1879   if ( sopt.Contains("MANU") )
1880   {
1881     if ( fIsManuLevelEnabled ) 
1882     {
1883       if ( fManuValues ) fManuValues->Print(wildcard,opt);
1884     }
1885     else
1886     {
1887       AliWarning("You requested manu values, but they were not stored !");
1888     }
1889   }
1890
1891   if ( sopt.Contains("BUSPATCH") && fBusPatchValues ) 
1892   {
1893     fBusPatchValues->Print(wildcard,opt);
1894   }
1895
1896   if ( sopt.Contains("DE") && fDEValues ) 
1897   {
1898     fDEValues->Print(wildcard,opt);
1899   }
1900
1901   if ( sopt.Contains("CHAMBER") && fChamberValues ) 
1902   {
1903     fChamberValues->Print(wildcard,opt);
1904   }
1905   
1906 }
1907
1908 //_____________________________________________________________________________
1909 void
1910 AliMUONTrackerData::SetDimensionName(Int_t index, const char* name)
1911 {  
1912   /// Set the name of a given dimension
1913
1914   if ( index >= fExternalDimension ) 
1915   {
1916     AliError(Form("%s : dimension %s : Index out of bounds : %d / %d",
1917                   GetName(),
1918                   name,index,fExternalDimension));
1919     return;
1920   }
1921   
1922   Int_t ix = External2Internal(index);
1923   
1924   if ( !IsSingleEvent() ) 
1925   {
1926     const char* prefix[] = { "mean", "sigma" };
1927   
1928     for ( Int_t i = 0; i < 2; ++i ) 
1929     {
1930       Int_t j = ix+i;
1931     
1932       SetInternalDimensionName(j,Form("%s of %s",prefix[i],name));
1933     }
1934   }
1935   else
1936   {
1937     SetInternalDimensionName(index,name);
1938   }
1939   
1940   SetExternalDimensionName(index,name);
1941 }
1942
1943 //_____________________________________________________________________________
1944 void 
1945 AliMUONTrackerData::MakeHistogramForDimension(Int_t index, Bool_t value, Double_t xmin, Double_t xmax)
1946 {
1947   /// decide to make histos for a given dimension
1948   if ( index >= ExternalDimension() ) 
1949   {
1950     AliError(Form("Index out of bounds : %d / %d",index,ExternalDimension()));
1951     return;
1952   }
1953   
1954   AliWarning(Form("Will %s make histogram for data %s index %d : that might ressemble a memory leak depending on the input data",
1955                   value ? "":"not", GetName(),index));
1956   fHistogramming[index] = value;
1957   fXmin = xmin;
1958   fXmax = xmax;
1959 }
1960
1961 //_____________________________________________________________________________
1962 void 
1963 AliMUONTrackerData::SetInternalDimensionName(Int_t index, const char* value)
1964 {
1965   /// Set the name of a given internal dimension
1966   if ( index >= fDimension ) 
1967   {
1968     AliError(Form("Index out of bounds : %d / %d",index,fDimension));
1969     return;
1970   }
1971   
1972   TObjString* ovalue = static_cast<TObjString*>(fDimensionNames->At(index));
1973     
1974   if ( ovalue ) 
1975   {
1976     fDimensionNames->Remove(ovalue);
1977     delete ovalue;
1978   }
1979   fDimensionNames->AddAt(new TObjString(value),index);
1980 }
1981
1982 //_____________________________________________________________________________
1983 void 
1984 AliMUONTrackerData::SetExternalDimensionName(Int_t index, const char* value)
1985 {
1986   /// Set the name of a given external dimension
1987   if ( index >= fExternalDimension ) 
1988   {
1989     AliError(Form("Index out of bounds : %d / %d",index,fExternalDimension));
1990     return;
1991   }
1992   
1993   TObjString* ovalue = static_cast<TObjString*>(fExternalDimensionNames->At(index));
1994   
1995   if ( ovalue ) 
1996   {
1997     fExternalDimensionNames->Remove(ovalue);
1998     delete ovalue;
1999   }
2000   fExternalDimensionNames->AddAt(new TObjString(value),index);
2001 }
2002
2003 //_____________________________________________________________________________
2004 Double_t 
2005 AliMUONTrackerData::Value(const AliMUONVCalibParam& param, Int_t i, 
2006                           Int_t dim, Int_t ddlId) const
2007 {
2008   /// Compute the value for a given dim, using the internal information we have
2009   /// Basically we're converting sum of weights and sum of squares of weights
2010   /// into means and sigmas, and number of events into occupancy number.
2011
2012   Double_t n = param.ValueAsDouble(i,IndexOfNumberDimension());
2013   
2014   if ( dim == IndexOfNumberDimension() ) return n; // the number of channels in any given element does not depend on the number of events
2015   
2016   Double_t occ = param.ValueAsDouble(i,IndexOfOccupancyDimension());
2017
2018   if ( dim >= fDimension ) 
2019   {
2020     return occ;
2021   }
2022   
2023   if ( dim == IndexOfOccupancyDimension() ) 
2024   {
2025     if ( ddlId < 0 ) AliError("Got a negative ddl id !");
2026     return occ/n/NumberOfEvents(ddlId);
2027   }
2028   
2029   Double_t value = param.ValueAsDouble(i,dim);
2030   
2031   if ( value >= AliMUONVCalibParam::InvalidFloatValue() ) return AliMUONVCalibParam::InvalidFloatValue();
2032   
2033   if ( TMath::Even(dim) || IsSingleEvent() ) 
2034   {
2035                 Double_t x = value/occ;
2036                 
2037                 return ( TMath::Finite(x) ? x : 0.0 ) ;
2038   }
2039   else
2040   {
2041     Double_t nn = occ;
2042     
2043     if ( nn > 1.0 ) 
2044     {
2045       Double_t mean = param.ValueAsDouble(i,dim-1)/nn;
2046     
2047       return TMath::Sqrt(TMath::Abs((value-nn*mean*mean)/(nn-1.0)));
2048     }
2049     else
2050     {
2051       return 0.0;
2052     }
2053   }
2054   
2055   AliError("Why am I here ?");
2056   return 0.0;
2057 }
2058
2059 //_____________________________________________________________________________
2060 void 
2061 AliMUONTrackerData::Streamer(TBuffer &R__b)
2062 {
2063   /// Customized streamer                                                    
2064   
2065   if (R__b.IsReading()) {
2066     AliMUONTrackerData::Class()->ReadBuffer(R__b, this);
2067     if ( !fNofDDLs )
2068     {
2069       // backward compatible mode : we set number of events
2070       // per DDL to the total number of events (the only information
2071       // we had before version 7 of that class)
2072       delete[] fNofEventsPerDDL;
2073       fNofDDLs=20;
2074       fNofEventsPerDDL = new Int_t[fNofDDLs];
2075       for ( Int_t i = 0; i < fNofDDLs; ++i ) 
2076       {
2077         fNofEventsPerDDL[i] = fNevents;
2078       }
2079     }
2080   } 
2081   else {
2082     AliMUONTrackerData::Class()->WriteBuffer(R__b, this);
2083   }
2084 }
2085
2086 //_____________________________________________________________________________
2087 Bool_t 
2088 AliMUONTrackerData::ExportAsASCIIOccupancyFile(const char* filename, Int_t runNumber) const
2089 {
2090   /// Export only the occupancy part, in a format compatible with what
2091   /// the online occupancy DA is writing
2092   
2093   if ( ! AliMpDDLStore::Instance(kFALSE) )
2094   {
2095     AliError("Mapping not loaded. Cannot work");
2096     return kFALSE;
2097   }
2098   
2099   if (!fManuValues)
2100   {
2101     AliError("No manu values. Cannot work");
2102     return kFALSE;
2103   }
2104   
2105   ofstream out(filename);
2106   
2107   if (out.bad())
2108   {
2109     AliError(Form("Cannot create file %s",filename));
2110     return kFALSE;
2111   }
2112   
2113   out << "//===========================================================================" << endl;
2114   out << "//  Hit counter exported from $Id$" << endl;
2115   out << "//===========================================================================" << endl;
2116   out << "//" << endl;
2117   out << "//       * Run Number          : " << runNumber << endl;
2118   out << "//       * File Creation Date  : " << TTimeStamp().AsString("l") << endl;
2119   out << "//---------------------------------------------------------------------------" << endl;
2120   out << "//  BP   MANU  SUM_N  NEVENTS" << endl;
2121   out << "//---------------------------------------------------------------------------" << endl;
2122   
2123   TIter next(fManuValues->CreateIterator());
2124   AliMUONVCalibParam* manu;
2125   
2126   while ( ( manu = static_cast<AliMUONVCalibParam*>(next()) ) )
2127   {
2128     Int_t detElemId = manu->ID0();
2129     Int_t manuId = manu->ID1();
2130     Int_t busPatchId = AliMpDDLStore::Instance()->GetBusPatchId(detElemId,manuId);
2131     Int_t ddl = AliMpDDLStore::Instance()->GetDDLfromBus( busPatchId);
2132     if ( busPatchId < 0 || ddl < 0 )
2133     {
2134       AliError(Form("Got invalid (DE,manu,bp,ddl)=(%d,%d,%d,%d). Skipping it",detElemId,manuId,busPatchId,ddl));
2135       continue;
2136     }
2137
2138     Int_t nevents = fNofEventsPerDDL[ddl];
2139     
2140     out << Form("%5d %5d %10d %10d",busPatchId,manuId,manu->ValueAsInt(0,IndexOfOccupancyDimension()),nevents) << endl;
2141   }
2142   
2143   out.close();
2144   return kTRUE;
2145 }
2146   
2147 //_____________________________________________________________________________
2148 void AliMUONTrackerData::DispatchValue(AliMUONVCalibParam& param, 
2149                                        Int_t index,
2150                                        Double_t y, 
2151                                        Double_t ey,
2152                                        Int_t nchannels)
2153 {
2154   /// fills the calibparam with a single value
2155   
2156   Double_t sumn = 1000.0; // or any value strictly above 1
2157   Double_t sumw = sumn*y;
2158   Double_t sumw2 = (sumn-1)*ey*ey+sumw*sumw/sumn;
2159   
2160   param.SetValueAsDouble(index,0,sumw);
2161   param.SetValueAsDouble(index,1,sumw2);
2162   param.SetValueAsDouble(index,2,sumn);
2163   param.SetValueAsDouble(index,3,nchannels);
2164   
2165 }