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