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