Correctly reset the total number of events (for Amore)
[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   fNevents = 0;
900   NumberOfEventsChanged();
901 }
902
903 //_____________________________________________________________________________
904 Double_t 
905 AliMUONTrackerData::Count(Int_t detElemId, Int_t manuId, 
906                           Int_t manuChannel) const
907 {
908   /// Return the number of times a given channel had data
909   
910   return Channel(detElemId,manuId,manuChannel,IndexOfNumberDimension());
911 }
912
913 //_____________________________________________________________________________
914 AliMUONVCalibParam*
915 AliMUONTrackerData::CreateDouble(const AliMUONVCalibParam& param, 
916                                  Int_t detElemId, Int_t manuId) const
917 {
918   /// Create a double version of VCalibParam, for internal use
919   
920   AliCodeTimerAuto("",0);
921   
922   AliMUONVCalibParam* c = new AliMUONCalibParamND(Dimension(),
923                                                   param.Size(),
924                                                   detElemId,
925                                                   manuId,
926                                                   0.0);
927   
928   AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(detElemId,manuId);
929   
930   for ( Int_t i = 0; i < c->Size(); ++i ) 
931   {
932     Double_t value(0.0);
933     
934     if ( de->IsConnectedChannel(manuId,i) ) value = 1.0;
935       
936     c->SetValueAsDouble(i,IndexOfNumberDimension(),value);
937   }
938   
939   return c;
940 }
941
942 //_____________________________________________________________________________
943 Double_t 
944 AliMUONTrackerData::DetectionElement(Int_t detElemId, Int_t dim) const
945 {
946   /// Return the value for a given detection element for a given dimension
947   AliMUONVCalibParam* param = DetectionElementParam(detElemId);
948   return param ? Value(*param,0,dim,DdlIdFromDetElemId(detElemId)) : 0.0;
949
950 }
951
952 //_____________________________________________________________________________
953 AliMUONVCalibParam* 
954 AliMUONTrackerData::DetectionElementParam(Int_t detElemId, Bool_t create) const
955 {
956   /// Return (if it exist) the VCalibParam for a given detection element
957   
958   AliMUONVCalibParam* de = fDEValues ? static_cast<AliMUONVCalibParam*>
959     (fDEValues->FindObject(detElemId)) : 0x0 ;
960   
961   if (!de && create && fDEValues)
962   {
963     de = CreateDetectionElementParam(detElemId);
964     fDEValues->Add(de);
965   }
966   
967   return de;
968   
969 }
970
971 //_____________________________________________________________________________
972 AliMUONVCalibParam* 
973 AliMUONTrackerData::CreateDetectionElementParam(Int_t detElemId) const
974 {
975   /// Create storage for one detection element
976   
977   AliCodeTimerAuto("",0);
978   
979   AliMUONVCalibParam*  de = new AliMUONCalibParamND(Dimension(),1,detElemId,0,0.0);
980   
981   AliMpDetElement* det = AliMpDDLStore::Instance()->GetDetElement(detElemId);
982   Int_t nchannels(0);
983   
984   for ( Int_t i = 0; i < det->GetNofBusPatches(); ++i ) 
985   {
986     Int_t busPatchId = det->GetBusPatchId(i);
987     AliMpBusPatch* bp = AliMpDDLStore::Instance()->GetBusPatch(busPatchId);
988     for ( Int_t j = 0; j < bp->GetNofManus(); ++j ) 
989     {
990       Int_t manuId = bp->GetManuId(j);
991       nchannels += det->NofChannelsInManu(manuId);
992     }        
993   }
994   
995   de->SetValueAsDouble(0,IndexOfNumberDimension(),nchannels);
996   
997   return de;
998 }
999
1000 //_____________________________________________________________________________
1001 Int_t 
1002 AliMUONTrackerData::DdlIdFromBusPatchId(Int_t buspatchid) const
1003 {
1004   /// Get the "local" ddlid (0..19) of a given buspatch
1005   AliMpBusPatch* bp = AliMpDDLStore::Instance()->GetBusPatch(buspatchid);
1006   if (bp)
1007   {
1008     return bp->GetDdlId();
1009   }
1010   return -1;
1011 }
1012
1013 //_____________________________________________________________________________
1014 Int_t 
1015 AliMUONTrackerData::DdlIdFromDetElemId(Int_t detelemid) const
1016 {
1017   /// Get the "local" ddlid (0..19) of a given detection element
1018   AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(detelemid);
1019   if (de)
1020   {
1021     return de->GetDdlId();
1022   }
1023   return -1;
1024 }
1025
1026 //_____________________________________________________________________________
1027 Int_t 
1028 AliMUONTrackerData::DdlIdFromChamberId(Int_t chamberid) const
1029 {
1030   /// Get the "local" ddlid (0..19) of a given chamber
1031   /// This has no real meaning (as there are several ddls per chamber),
1032   /// so we take the ddlid where we got the max number of events
1033   
1034   AliMpDEIterator it;
1035   
1036   it.First(chamberid);
1037   Int_t n(0);
1038   Int_t d(-1);
1039   
1040   while (!it.IsDone())
1041   {
1042     Int_t detElemId = it.CurrentDEId();
1043     Int_t ddlId = DdlIdFromDetElemId(detElemId);
1044     if ( NumberOfEvents(ddlId) > n ) 
1045     {
1046       n = NumberOfEvents(ddlId);
1047       d = ddlId;
1048     }
1049     it.Next();
1050   }
1051   
1052   return d;
1053 }
1054
1055 //_____________________________________________________________________________
1056 TString 
1057 AliMUONTrackerData::DimensionName(Int_t dim) const
1058 {
1059   /// Get the name of a given dimension
1060   TObjString* value = static_cast<TObjString*>(fDimensionNames->At(dim));
1061   if ( value ) 
1062   {
1063     return value->String();
1064   }
1065   else
1066   {
1067     return TString("Invalid");
1068   }  
1069 }
1070
1071 //_____________________________________________________________________________
1072 void 
1073 AliMUONTrackerData::DisableChannelLevel()
1074
1075   /// Disable the storing of data at channel level
1076   
1077   delete fChannelValues;
1078   fChannelValues = 0x0;
1079   fIsChannelLevelEnabled = kFALSE; 
1080 }
1081
1082 //_____________________________________________________________________________
1083 void 
1084 AliMUONTrackerData::DisableManuLevel()
1085
1086   /// Disable the storing of data at manu level (and below)
1087   
1088   DisableChannelLevel();
1089   delete fManuValues;
1090   fManuValues = 0x0;
1091   fIsManuLevelEnabled = kFALSE; 
1092 }
1093
1094 //_____________________________________________________________________________
1095 Int_t 
1096 AliMUONTrackerData::External2Internal(Int_t index) const 
1097 {
1098   /// From external to internal dimension
1099   return IsSingleEvent() ? index : index*2;
1100 }
1101
1102 //_____________________________________________________________________________
1103 TString 
1104 AliMUONTrackerData::ExternalDimensionName(Int_t dim) const
1105 {
1106   /// Get the name of a given external dimension
1107   
1108   TObjString* value = static_cast<TObjString*>(fExternalDimensionNames->At(dim));
1109   if ( value ) 
1110   {
1111     return value->String();
1112   }
1113   else
1114   {
1115     return TString("Invalid");
1116   }  
1117 }
1118
1119 //_____________________________________________________________________________
1120 void
1121 AliMUONTrackerData::FillHisto(Int_t detElemId, Int_t manuId, Int_t manuChannel,
1122                               Int_t dim, Double_t value)
1123 {
1124   /// Fill histogram of a given channel
1125   
1126   AliMUONSparseHisto* h(0x0);
1127   
1128         if ( fIsChannelLevelEnabled ) 
1129         {
1130                 h = GetChannelSparseHisto(detElemId, manuId, manuChannel,dim);
1131   }
1132   else if ( fIsManuLevelEnabled ) 
1133   {
1134     h = GetManuSparseHisto(detElemId,manuId,dim);
1135   }
1136   
1137   AliDebug(1,Form("DE %04d MANU %04d CH %02d dim %d value %e h %p",detElemId,manuId,manuChannel,dim,value,h));
1138   
1139   if (h)
1140   {
1141                 h->Fill(static_cast<Int_t>(TMath::Nint(value)));
1142         }
1143 }
1144
1145 //_____________________________________________________________________________
1146 AliMUONSparseHisto*
1147 AliMUONTrackerData::GetManuSparseHisto(Int_t detElemId, Int_t manuId, 
1148                                        Int_t dim) const
1149 {
1150   /// Get histogram of a given manu
1151   
1152   if (!fHistos) return 0x0;
1153   
1154   AliMUON1DArray* m = static_cast<AliMUON1DArray*>(fHistos->FindObject(detElemId,manuId));
1155   if (!m) return 0x0;
1156   
1157   AliMUONSparseHisto* h = static_cast<AliMUONSparseHisto*>(m->FindObject(dim));
1158   
1159   return h;
1160 }
1161
1162 //_____________________________________________________________________________
1163 AliMUONSparseHisto*
1164 AliMUONTrackerData::GetManuSparseHisto(Int_t detElemId, Int_t manuId, Int_t dim)
1165 {
1166   /// Get histogram of a given manu. Create it if necessary
1167   
1168   if (!fHistos) fHistos = new AliMUON2DMap(kTRUE);
1169   
1170   AliMUON1DArray* m = static_cast<AliMUON1DArray*>(fHistos->FindObject(detElemId,manuId));
1171   if (!m)
1172   {
1173     m = new AliMUON1DArray(NumberOfDimensions());
1174     m->SetUniqueID( ( manuId << 16 ) | detElemId );
1175     fHistos->Add(m);
1176   }
1177     
1178   AliMUONSparseHisto* h = static_cast<AliMUONSparseHisto*>(m->FindObject(dim));
1179   if (!h)
1180   {
1181     h = new AliMUONSparseHisto(fXmin,fXmax);
1182     
1183     h->SetUniqueID(dim);
1184     
1185     m->Add(h);
1186   }
1187   
1188    return h;
1189 }
1190
1191 //_____________________________________________________________________________
1192 AliMUONSparseHisto*
1193 AliMUONTrackerData::GetChannelSparseHisto(Int_t detElemId, Int_t manuId, 
1194                                           Int_t manuChannel, Int_t dim) const
1195 {
1196   /// Get histogram of a given channel
1197   
1198   if (!fHistos) return 0x0;
1199   
1200   AliMUON1DMap* m = static_cast<AliMUON1DMap*>(fHistos->FindObject(detElemId,manuId));
1201   if (!m) return 0x0;
1202   
1203   UInt_t uid = ( manuChannel << 16 ) | dim;
1204   
1205   AliMUONSparseHisto* h = static_cast<AliMUONSparseHisto*>(m->FindObject(uid));
1206   
1207   return h;
1208 }
1209
1210 //_____________________________________________________________________________
1211 AliMUONSparseHisto*
1212 AliMUONTrackerData::GetChannelSparseHisto(Int_t detElemId, Int_t manuId, 
1213                                           Int_t manuChannel, Int_t dim)
1214 {
1215   /// Get histogram of a given channel. Create it if necessary
1216   
1217   if (!fHistos) fHistos = new AliMUON2DMap(kTRUE);
1218   
1219   AliMUON1DMap* m = static_cast<AliMUON1DMap*>(fHistos->FindObject(detElemId,manuId));
1220   if (!m)
1221   {
1222     m = new AliMUON1DMap(AliMpConstants::ManuNofChannels()); // start with only 1 dim
1223     m->SetUniqueID( ( manuId << 16 ) | detElemId );
1224     fHistos->Add(m);
1225   }
1226   
1227   UInt_t uid = ( manuChannel << 16 ) | dim;
1228   
1229   AliMUONSparseHisto* h = static_cast<AliMUONSparseHisto*>(m->FindObject(uid));
1230   if (!h)
1231   {
1232     h = new AliMUONSparseHisto(fXmin,fXmax);
1233     
1234     h->SetUniqueID(uid);
1235     
1236     m->Add(h);
1237   }
1238
1239   return h;
1240 }
1241
1242 //_____________________________________________________________________________
1243 void
1244 AliMUONTrackerData::GetDEManu(const AliMUONVCalibParam& param,
1245                               Int_t& detElemId, Int_t& manuId) const
1246 {
1247   /// Tries to get (detElemId,manuId) of param
1248   
1249   // Load mapping manu store
1250   if ( ! AliMpCDB::LoadManuStore() ) {
1251     AliError("Could not access manu store from OCDB !");
1252     return;
1253   }
1254
1255   if ( param.ID1() <= 0 ) 
1256   {
1257     // we (probably) get a manu serial number
1258     Int_t serial = param.ID0();
1259     MpPair_t pair = AliMpManuStore::Instance()->GetDetElemIdManu(serial);
1260     detElemId = AliMp::PairFirst(pair);
1261     manuId = AliMp::PairSecond(pair);
1262     if ( !detElemId ) 
1263     {
1264       AliDebug(1,Form("DE %d manuId %d from serial %d is not correct !",
1265                       detElemId,manuId,serial));
1266     }
1267   }
1268   else
1269   {
1270     // we get a (de,manu) pair
1271     detElemId = param.ID0();
1272     manuId = param.ID1();
1273   }
1274 }
1275
1276
1277 //_____________________________________________________________________________
1278 Int_t
1279 AliMUONTrackerData::GetParts(AliMUONVCalibParam* external,
1280                              AliMUONVCalibParam*& chamber,
1281                              AliMUONVCalibParam*& de,
1282                              AliMUONVCalibParam*& busPatch,
1283                              AliMUONVCalibParam*& pcb,
1284                              AliMUONVCalibParam*& manu,
1285                              AliMUONVCalibParam*& channel,
1286                              AliMpDetElement*& mpde)
1287 {
1288   /// Get containers at all levels
1289  
1290   chamber = de = busPatch = pcb = manu = channel = 0x0;
1291   mpde = 0x0;
1292   
1293   AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
1294   
1295   Int_t detElemId;
1296   Int_t manuId;
1297   
1298   GetDEManu(*external,detElemId,manuId);
1299   
1300   mpde = ddlStore->GetDetElement(detElemId,kFALSE);
1301
1302   if (!mpde) // can happen if reading e.g. capacitances store where we have data for non-connected manus
1303   {
1304     return -1;
1305   }
1306   
1307   // explicitely check that de,manu is correct
1308   const AliMpVSegmentation* mpseg = AliMpSegmentation::Instance()->GetMpSegmentationByElectronics(detElemId, manuId,kFALSE);
1309   
1310   if (!mpseg)
1311   {
1312     return -1;
1313   }
1314   
1315   Int_t chamberId = AliMpDEManager::GetChamberId(detElemId);
1316     
1317   Int_t busPatchId = ddlStore->GetBusPatchId(detElemId,manuId);
1318   
1319   if ( busPatchId <= 0 )
1320   {
1321     return -1;
1322   }
1323   
1324   Int_t pcbIndex = -1;
1325   
1326   AliMp::StationType stationType = mpde->GetStationType();
1327   
1328   if ( stationType == AliMp::kStation345 ) 
1329   {
1330     AliMpDCSNamer namer("TRACKER");
1331     pcbIndex = namer.ManuId2PCBIndex(detElemId,manuId);
1332   }
1333   
1334   if ( fIsChannelLevelEnabled ) 
1335   {
1336     channel = ChannelParam(detElemId,manuId,external);
1337   }
1338   
1339   manu = ManuParam(detElemId,manuId,kTRUE);
1340   
1341   busPatch = BusPatchParam(busPatchId,kTRUE);
1342   
1343   de = DetectionElementParam(detElemId,kTRUE);
1344   
1345   chamber = ChamberParam(chamberId,kTRUE);
1346   
1347   pcb = 0x0;
1348   
1349   if ( pcbIndex >= 0 ) 
1350   {
1351     pcb = PCBParam(detElemId,pcbIndex,kTRUE);
1352   }
1353   
1354   return manuId;
1355 }
1356
1357 //_____________________________________________________________________________
1358 Bool_t 
1359 AliMUONTrackerData::HasBusPatch(Int_t busPatchId) const
1360 {
1361   /// Whether we have data for a given buspatch
1362   return ( BusPatchParam(busPatchId) != 0 );
1363 }
1364
1365 //_____________________________________________________________________________
1366 Bool_t 
1367 AliMUONTrackerData::HasChamber(Int_t chamberId) const
1368 {
1369   /// Whether we have data for a given chamber
1370   return ( ChamberParam(chamberId) != 0 );
1371 }
1372
1373 //_____________________________________________________________________________
1374 Bool_t 
1375 AliMUONTrackerData::HasDetectionElement(Int_t detElemId) const
1376 {
1377   /// Whether we have data for a given detection element
1378   return ( DetectionElementParam(detElemId) != 0 );
1379 }
1380
1381 //_____________________________________________________________________________
1382 Bool_t
1383 AliMUONTrackerData::HasManu(Int_t detElemId, Int_t manuId) const
1384 {
1385   /// Whether we have data for a given manu
1386   return ( ManuParam(detElemId,manuId) != 0 ); 
1387 }
1388
1389 //_____________________________________________________________________________
1390 Bool_t
1391 AliMUONTrackerData::HasPCB(Int_t detElemId, Int_t pcbIndex) const
1392 {
1393   /// Whether we have data for a given pcb
1394   return ( PCBParam(detElemId,pcbIndex) != 0 ); 
1395 }
1396
1397 //_____________________________________________________________________________
1398 Double_t 
1399 AliMUONTrackerData::Manu(Int_t detElemId, Int_t manuId, Int_t dim) const
1400 {
1401   /// Return the value for a given manu and a given dimension
1402   
1403   AliMUONVCalibParam* param = ManuParam(detElemId,manuId);
1404   return param ? Value(*param,0,dim,DdlIdFromDetElemId(detElemId)) : 0.0;
1405 }
1406
1407 //_____________________________________________________________________________
1408 AliMUONVCalibParam* 
1409 AliMUONTrackerData::ManuParam(Int_t detElemId, Int_t manuId, Bool_t create) const
1410 {
1411   /// Get the VCalibParam for a given manu
1412   
1413   AliMUONVCalibParam* manu = fManuValues ? static_cast<AliMUONVCalibParam*>
1414     (fManuValues->FindObject(detElemId,manuId)) : 0x0 ;
1415   
1416   if (!manu && create && fManuValues)
1417   {
1418     manu = CreateManuParam(detElemId,manuId);
1419     fManuValues->Add(manu);
1420   }
1421   
1422   return manu;
1423 }
1424
1425 //_____________________________________________________________________________
1426 AliMUONVCalibParam* 
1427 AliMUONTrackerData::CreateManuParam(Int_t detElemId, Int_t manuId) const
1428 {
1429   /// Create storage for one manu
1430   
1431   AliCodeTimerAuto("",0);
1432   
1433   AliMUONVCalibParam* manu = new AliMUONCalibParamND(Dimension(),1,detElemId,manuId,0.0);
1434   
1435   // set the number of channels in that manu
1436   
1437   AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(detElemId);
1438   
1439   manu->SetValueAsDouble(0,IndexOfNumberDimension(),de->NofChannelsInManu(manuId));
1440   
1441   return manu;
1442 }
1443
1444 //_____________________________________________________________________________
1445 Long64_t
1446 AliMUONTrackerData::Merge(TCollection* list)
1447 {
1448   /// Merge this with a list of AliMUONVTrackerData
1449
1450   if (!list) return 0;
1451   
1452   if ( list->IsEmpty() ) return NumberOfEvents(-1);
1453   
1454   TIter next(list);
1455   const TObject* o(0x0);
1456   
1457   while ( ( o = next() ) )
1458   {
1459     const AliMUONTrackerData* data = dynamic_cast<const AliMUONTrackerData*>(o);
1460     if (!o)
1461     {
1462       AliError(Form("Object named %s is not an AliMUONTrackerData ! Skipping it",
1463                     o->GetName()));
1464     }
1465     else
1466     {
1467       Bool_t ok = Add(*data);
1468       if (!ok)
1469       {
1470         AliError("Got incompatible objects");
1471       }
1472     }
1473   }
1474   
1475   return NumberOfEvents(-1);
1476 }
1477
1478 //_____________________________________________________________________________
1479 Int_t 
1480 AliMUONTrackerData::NumberOfDimensions() const
1481 {
1482   /// Number of dimensions we're dealing with
1483   
1484   return fDimension + fgkVirtualExtraDimension; 
1485 }
1486
1487 //_____________________________________________________________________________
1488 Int_t
1489 AliMUONTrackerData::NumberOfEvents(Int_t ddlNumber) const
1490 {
1491   /// Get the number of events we've seen for a given DDL, or the max
1492   /// in case ddlNumber<0
1493
1494   Int_t n(0);
1495   
1496   if ( fNofEventsPerDDL && ddlNumber >= 0 && ddlNumber < fNofDDLs )
1497   {
1498     n = fNofEventsPerDDL[ddlNumber];
1499   }
1500   else
1501   {
1502     // get the max number of events
1503     return fNevents;
1504   }
1505   
1506   return n;
1507 }
1508
1509 //_____________________________________________________________________________
1510 Double_t 
1511 AliMUONTrackerData::PCB(Int_t detElemId, Int_t pcbIndex, Int_t dim) const
1512 {
1513   /// Return the value of a given pcb for a given dimension
1514
1515   AliMUONVCalibParam* param = PCBParam(detElemId,pcbIndex);
1516   
1517   return param ? Value(*param,0,dim,DdlIdFromDetElemId(detElemId)) : 0.0;
1518 }
1519
1520 //_____________________________________________________________________________
1521 AliMUONVCalibParam* 
1522 AliMUONTrackerData::PCBParam(Int_t detElemId, Int_t pcbIndex, Bool_t create) const
1523 {
1524   /// Return (if it exist) the VCalibParam for a given pcb
1525
1526   AliMUONVCalibParam* pcb =  fPCBValues ? static_cast<AliMUONVCalibParam*>
1527     (fPCBValues->FindObject(detElemId,pcbIndex)) : 0x0 ;
1528   
1529   if (create && fPCBValues && !pcb)
1530   {
1531     pcb = CreatePCBParam(detElemId,pcbIndex);
1532     fPCBValues->Add(pcb);
1533   }
1534   
1535   return pcb;
1536 }
1537
1538 //_____________________________________________________________________________
1539 AliMUONVCalibParam* 
1540 AliMUONTrackerData::CreatePCBParam(Int_t detElemId, Int_t pcbIndex) const
1541 {
1542   /// Create storage for one PCB (station345 only)
1543   
1544   AliCodeTimerAuto("",0);
1545   
1546   AliMpDCSNamer namer("TRACKER");
1547   
1548   AliMUONVCalibParam* pcb = new AliMUONCalibParamND(Dimension(),
1549                                                     namer.NumberOfPCBs(detElemId),
1550                                                     detElemId,
1551                                                     pcbIndex,
1552                                                     0.0);
1553   return pcb;
1554 }
1555
1556 //_____________________________________________________________________________
1557 void 
1558 AliMUONTrackerData::Print(Option_t* wildcard, Option_t* opt) const
1559 {
1560   /// Printout
1561   
1562   TNamed::Print(opt);
1563   
1564   if ( !fIsSingleEvent ) 
1565   {
1566     for ( Int_t i = 0; i < fNofDDLs; ++i ) 
1567     {
1568       cout << Form("DDL %04d Nevents=%10d",AliDAQ::DdlID("MUONTRK",i),fNofEventsPerDDL[i]) << endl;
1569     }
1570   }
1571
1572         if ( !fIsChannelLevelEnabled ) 
1573         {
1574                 cout << "Is not storing data at the channel level" << endl;
1575         }
1576
1577   if ( !fIsManuLevelEnabled ) 
1578         {
1579                 cout << "Is not storing data at the manu level" << endl;
1580         }
1581   
1582   for ( Int_t i = 0; i <= fExternalDimensionNames->GetLast(); ++i ) 
1583   {
1584     TObjString* name = static_cast<TObjString*>(fExternalDimensionNames->At(i));
1585     cout << Form("External Dimension %2d Name %s %s",i,
1586                  ( name ? name->String().Data() : "null"),
1587                  ( IsHistogrammed(i) ? "(histogrammed)" : "")) << endl;
1588   }
1589   
1590   for ( Int_t i = 0; i <= fDimensionNames->GetLast(); ++i ) 
1591   {
1592     TObjString* name = static_cast<TObjString*>(fDimensionNames->At(i));
1593     cout << Form("Internal Dimension %2d Name %s",i,
1594                  ( name ? name->String().Data() : "null")) << endl;
1595   }
1596     
1597   TString sopt(opt);
1598   sopt.ToUpper();
1599   
1600   if ( sopt.Contains("CHANNEL") )
1601   {
1602     if ( fIsChannelLevelEnabled ) 
1603     {      
1604       if ( fChannelValues ) fChannelValues->Print(wildcard,opt);
1605     }
1606     else
1607     {
1608       AliWarning("You requested channel values, but they were not stored !");
1609     }
1610   }
1611
1612   if ( sopt.Contains("MANU") )
1613   {
1614     if ( fIsManuLevelEnabled ) 
1615     {
1616       if ( fManuValues ) fManuValues->Print(wildcard,opt);
1617     }
1618     else
1619     {
1620       AliWarning("You requested manu values, but they were not stored !");
1621     }
1622   }
1623
1624   if ( sopt.Contains("BUSPATCH") && fBusPatchValues ) 
1625   {
1626     fBusPatchValues->Print(wildcard,opt);
1627   }
1628
1629   if ( sopt.Contains("DE") && fDEValues ) 
1630   {
1631     fDEValues->Print(wildcard,opt);
1632   }
1633
1634   if ( sopt.Contains("CHAMBER") && fChamberValues ) 
1635   {
1636     fChamberValues->Print(wildcard,opt);
1637   }
1638   
1639 }
1640
1641 //_____________________________________________________________________________
1642 void
1643 AliMUONTrackerData::SetDimensionName(Int_t index, const char* name)
1644 {  
1645   /// Set the name of a given dimension
1646
1647   if ( index >= fExternalDimension ) 
1648   {
1649     AliError(Form("%s : dimension %s : Index out of bounds : %d / %d",
1650                   GetName(),
1651                   name,index,fExternalDimension));
1652     return;
1653   }
1654   
1655   Int_t ix = External2Internal(index);
1656   
1657   if ( !IsSingleEvent() ) 
1658   {
1659     const char* prefix[] = { "mean", "sigma" };
1660   
1661     for ( Int_t i = 0; i < 2; ++i ) 
1662     {
1663       Int_t j = ix+i;
1664     
1665       SetInternalDimensionName(j,Form("%s of %s",prefix[i],name));
1666     }
1667   }
1668   else
1669   {
1670     SetInternalDimensionName(index,name);
1671   }
1672   
1673   SetExternalDimensionName(index,name);
1674 }
1675
1676 //_____________________________________________________________________________
1677 void 
1678 AliMUONTrackerData::MakeHistogramForDimension(Int_t index, Bool_t value, Double_t xmin, Double_t xmax)
1679 {
1680   /// decide to make histos for a given dimension
1681   if ( index >= ExternalDimension() ) 
1682   {
1683     AliError(Form("Index out of bounds : %d / %d",index,ExternalDimension()));
1684     return;
1685   }
1686   
1687   AliWarning(Form("Will %s make histogram for data %s index %d : that might ressemble a memory leak depending on the input data",
1688                   value ? "":"not", GetName(),index));
1689   fHistogramming[index] = value;
1690   fXmin = xmin;
1691   fXmax = xmax;
1692 }
1693
1694 //_____________________________________________________________________________
1695 void 
1696 AliMUONTrackerData::SetInternalDimensionName(Int_t index, const char* value)
1697 {
1698   /// Set the name of a given internal dimension
1699   if ( index >= fDimension ) 
1700   {
1701     AliError(Form("Index out of bounds : %d / %d",index,fDimension));
1702     return;
1703   }
1704   
1705   TObjString* ovalue = static_cast<TObjString*>(fDimensionNames->At(index));
1706     
1707   if ( ovalue ) 
1708   {
1709     fDimensionNames->Remove(ovalue);
1710     delete ovalue;
1711   }
1712   fDimensionNames->AddAt(new TObjString(value),index);
1713 }
1714
1715 //_____________________________________________________________________________
1716 void 
1717 AliMUONTrackerData::SetExternalDimensionName(Int_t index, const char* value)
1718 {
1719   /// Set the name of a given external dimension
1720   if ( index >= fExternalDimension ) 
1721   {
1722     AliError(Form("Index out of bounds : %d / %d",index,fExternalDimension));
1723     return;
1724   }
1725   
1726   TObjString* ovalue = static_cast<TObjString*>(fExternalDimensionNames->At(index));
1727   
1728   if ( ovalue ) 
1729   {
1730     fExternalDimensionNames->Remove(ovalue);
1731     delete ovalue;
1732   }
1733   fExternalDimensionNames->AddAt(new TObjString(value),index);
1734 }
1735
1736 //_____________________________________________________________________________
1737 Double_t 
1738 AliMUONTrackerData::Value(const AliMUONVCalibParam& param, Int_t i, 
1739                           Int_t dim, Int_t ddlId) const
1740 {
1741   /// Compute the value for a given dim, using the internal information we have
1742   /// Basically we're converting sum of weights and sum of squares of weights
1743   /// into means and sigmas, and number of events into occupancy number.
1744
1745   Double_t n = param.ValueAsDouble(i,IndexOfNumberDimension());
1746   
1747   if ( dim == IndexOfNumberDimension() ) return n; // the number of channels in any given element does not depend on the number of events
1748   
1749   Double_t occ = param.ValueAsDouble(i,IndexOfOccupancyDimension());
1750
1751   if ( dim >= fDimension ) 
1752   {
1753     return occ;
1754   }
1755   
1756   if ( dim == IndexOfOccupancyDimension() ) 
1757   {
1758     if ( ddlId < 0 ) AliError("Got a negative ddl id !");
1759     return occ/n/NumberOfEvents(ddlId);
1760   }
1761   
1762   Double_t value = param.ValueAsDouble(i,dim);
1763   
1764   if ( value >= AliMUONVCalibParam::InvalidFloatValue() ) return AliMUONVCalibParam::InvalidFloatValue();
1765   
1766   if ( TMath::Even(dim) || IsSingleEvent() ) 
1767   {
1768                 Double_t x = value/occ;
1769                 
1770                 return ( TMath::Finite(x) ? x : 0.0 ) ;
1771   }
1772   else
1773   {
1774     Double_t nn = occ;
1775     
1776     if ( nn > 1.0 ) 
1777     {
1778       Double_t mean = param.ValueAsDouble(i,dim-1)/nn;
1779     
1780       return TMath::Sqrt(TMath::Abs((value-nn*mean*mean)/(nn-1.0)));
1781     }
1782     else
1783     {
1784       return 0.0;
1785     }
1786   }
1787   
1788   AliError("Why am I here ?");
1789   return 0.0;
1790 }
1791
1792 //_____________________________________________________________________________
1793 void 
1794 AliMUONTrackerData::Streamer(TBuffer &R__b)
1795 {
1796   /// Customized streamer                                                    
1797   
1798   if (R__b.IsReading()) {
1799     AliMUONTrackerData::Class()->ReadBuffer(R__b, this);
1800     if ( !fNofDDLs )
1801     {
1802       // backward compatible mode : we set number of events
1803       // per DDL to the total number of events (the only information
1804       // we had before version 7 of that class)
1805       delete[] fNofEventsPerDDL;
1806       fNofDDLs=20;
1807       fNofEventsPerDDL = new Int_t[fNofDDLs];
1808       for ( Int_t i = 0; i < fNofDDLs; ++i ) 
1809       {
1810         fNofEventsPerDDL[i] = fNevents;
1811       }
1812     }
1813   } 
1814   else {
1815     AliMUONTrackerData::Class()->WriteBuffer(R__b, this);
1816   }
1817 }
1818
1819 //_____________________________________________________________________________
1820 Bool_t 
1821 AliMUONTrackerData::ExportAsASCIIOccupancyFile(const char* filename, Int_t runNumber) const
1822 {
1823   /// Export only the occupancy part, in a format compatible with what
1824   /// the online occupancy DA is writing
1825   
1826   if ( ! AliMpDDLStore::Instance(kFALSE) )
1827   {
1828     AliError("Mapping not loaded. Cannot work");
1829     return kFALSE;
1830   }
1831   
1832   if (!fManuValues)
1833   {
1834     AliError("No manu values. Cannot work");
1835     return kFALSE;
1836   }
1837   
1838   ofstream out(filename);
1839   
1840   if (out.bad())
1841   {
1842     AliError(Form("Cannot create file %s",filename));
1843     return kFALSE;
1844   }
1845   
1846   out << "//===========================================================================" << endl;
1847   out << "//  Hit counter exported from $Id$" << endl;
1848   out << "//===========================================================================" << endl;
1849   out << "//" << endl;
1850   out << "//       * Run Number          : " << runNumber << endl;
1851   out << "//       * File Creation Date  : " << TTimeStamp().AsString("l") << endl;
1852   out << "//---------------------------------------------------------------------------" << endl;
1853   out << "//  BP   MANU  SUM_N  NEVENTS" << endl;
1854   out << "//---------------------------------------------------------------------------" << endl;
1855   
1856   TIter next(fManuValues->CreateIterator());
1857   AliMUONVCalibParam* manu;
1858   
1859   while ( ( manu = static_cast<AliMUONVCalibParam*>(next()) ) )
1860   {
1861     Int_t detElemId = manu->ID0();
1862     Int_t manuId = manu->ID1();
1863     Int_t busPatchId = AliMpDDLStore::Instance()->GetBusPatchId(detElemId,manuId);
1864     Int_t ddl = AliMpDDLStore::Instance()->GetDDLfromBus( busPatchId);
1865     if ( busPatchId < 0 || ddl < 0 )
1866     {
1867       AliError(Form("Got invalid (DE,manu,bp,ddl)=(%d,%d,%d,%d). Skipping it",detElemId,manuId,busPatchId,ddl));
1868       continue;
1869     }
1870
1871     Int_t nevents = fNofEventsPerDDL[ddl];
1872     
1873     out << Form("%5d %5d %10d %10d",busPatchId,manuId,manu->ValueAsInt(0,IndexOfOccupancyDimension()),nevents) << endl;
1874   }
1875   
1876   out.close();
1877   return kTRUE;
1878 }
1879
1880