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