]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONTrackerData.cxx
AliMUONDigitCalibrator
[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 "AliLog.h"
22 #include "AliMUON1DArray.h"
23 #include "AliMUON1DMap.h"
24 #include "AliMUON2DMap.h"
25 #include "AliMUONCalibParamND.h"
26 #include "AliMUONSparseHisto.h"
27 #include "AliMUONVStore.h"
28 #include "AliMpBusPatch.h"
29 #include "AliMpConstants.h"
30 #include "AliMpDDLStore.h"
31 #include "AliMpDEIterator.h"
32 #include "AliMpDEManager.h"
33 #include "AliMpDetElement.h"
34 #include "AliMpHVNamer.h"
35 #include "AliMpManuIterator.h"
36 #include <Riostream.h>
37 #include <TMath.h>
38 #include <TObjArray.h>
39 #include <TObjString.h>
40 #include <TString.h>
41 #include <TVector2.h>
42 #include <float.h>
43
44 /// \class AliMUONTrackerData
45 ///
46 /// Implementation of AliMUONVTrackerData class
47 ///
48 /// \author Laurent Aphecetche, Subatech
49
50 ///\cond CLASSIMP
51 ClassImp(AliMUONTrackerData)
52 ///\endcond
53
54 const Int_t AliMUONTrackerData::fgkExtraDimension = 2;
55 const Int_t AliMUONTrackerData::fgkVirtualExtraDimension = 1;
56
57 //_____________________________________________________________________________
58 AliMUONTrackerData::AliMUONTrackerData(const char* name, const char* title,
59                                        Int_t dimension,
60                                        Bool_t issingleevent)
61 : AliMUONVTrackerData(name,title),
62 fIsSingleEvent(issingleevent),
63 fChannelValues(0x0),
64 fManuValues(0x0),
65 fBusPatchValues(0x0),
66 fDEValues(0x0),
67 fChamberValues(0x0),
68 fPCBValues(0x0),
69 fDimension(External2Internal(dimension)+fgkExtraDimension),
70 fNevents(0x0),
71 fDimensionNames(new TObjArray(fDimension+fgkVirtualExtraDimension)),
72 fExternalDimensionNames(new TObjArray(dimension)),
73 fExternalDimension(dimension),
74 fHistogramming(new Int_t[fExternalDimension]),
75 fChannelHistos(0x0),
76 fXmin(0.0),
77 fXmax(0.0)
78 {  
79   /// ctor
80   memset(fHistogramming,0,sizeof(Int_t)); // histogramming is off by default. Use MakeHistogramForDimension to turn it on.
81   fExternalDimensionNames->SetOwner(kTRUE);
82   fDimensionNames->SetOwner(kTRUE);  
83   fDimensionNames->AddAt(new TObjString("occ"),IndexOfOccupancyDimension());
84   fDimensionNames->AddAt(new TObjString("N"),IndexOfNumberDimension());
85   fDimensionNames->AddAt(new TObjString("n"),NumberOfDimensions()-fgkVirtualExtraDimension);
86   Clear();
87 }
88
89 //_____________________________________________________________________________
90 AliMUONTrackerData::~AliMUONTrackerData()
91 {
92   /// dtor
93   delete fChannelValues;
94   delete fManuValues;
95   delete fBusPatchValues;
96   delete fDEValues;
97   delete fChamberValues;
98   delete fPCBValues;
99   delete fDimensionNames;
100   delete fExternalDimensionNames;
101   delete[] fHistogramming;
102   delete fChannelHistos;
103 }
104
105 //_____________________________________________________________________________
106 Bool_t
107 AliMUONTrackerData::Add(const AliMUONVStore& store)
108 {
109   /// Add the given external store to our internal store
110   
111   AliCodeTimerAuto(GetName());
112     
113   if ( IsSingleEvent() && fNevents == 1 ) 
114   {
115     AliError(Form("%s is supposed to be single event only",GetName()));
116     return kFALSE;
117   }
118   
119   ++fNevents;
120   
121   NumberOfEventsChanged();
122   
123   if (!fChannelValues)
124   {
125     Int_t numberOfBusPatches(0);
126     Int_t numberOfDEs(0);
127     
128     // get number of bus patches and number of detection element
129     // to initialize fBusPatchValues and fDEValues below
130     
131     TIter next(AliMpDDLStore::Instance()->CreateBusPatchIterator());
132     while ( next() ) ++numberOfBusPatches;
133     AliMpDEIterator deIt;
134     deIt.First();
135     while (!deIt.IsDone())
136     {
137       ++numberOfDEs;
138       deIt.Next();
139     }
140     
141     fChannelValues = new AliMUON2DMap(kTRUE);
142     fManuValues = new AliMUON2DMap(kTRUE);
143     fPCBValues = new AliMUON2DMap(kFALSE);
144     fBusPatchValues = new AliMUON1DMap(numberOfBusPatches);
145     fDEValues = new AliMUON1DMap(numberOfDEs);
146     fChamberValues = new AliMUON1DArray;
147   }
148   
149   TIter next(store.CreateIterator());
150   AliMUONVCalibParam* external;
151   
152   Int_t nk(2);
153   
154   if ( IsSingleEvent() ) nk = 1;
155
156   while ( ( external = static_cast<AliMUONVCalibParam*>(next()) ) )
157   {
158     if ( external->Dimension() != ExternalDimension() )
159     {
160       AliError(Form("Incompatible dimensions %d vs %d",
161                     external->Dimension(),ExternalDimension()));
162       return kFALSE;
163     }
164     
165
166     AliMUONVCalibParam* chamber, *de, *busPatch, *pcb, *manu, *channel;
167     AliMpDetElement* mpde;
168     
169     Int_t manuId = GetParts(external,chamber,de,busPatch,pcb,manu,channel,mpde);
170     
171     if ( manuId < 0 ) continue;
172     
173     Int_t detElemId = mpde->GetId();
174     
175     Double_t value[] = { 0.0, 0.0 };
176     
177     Int_t nch = mpde->NofChannelsInManu(manuId);
178     
179     for ( Int_t i = 0; i < external->Size(); ++i ) 
180     {
181       Bool_t existingChannel =  ( nch == AliMpConstants::ManuNofChannels() ? kTRUE
182                                                                            : mpde->IsConnectedChannel(manuId,i));
183       // note we only use IsConnectedChannel method when really needed, as
184       // it costs (some) CPU time...
185       
186       if ( existingChannel ) 
187       {
188         Bool_t validChannel(kFALSE);
189         
190         for ( Int_t j = 0; j < external->Dimension(); ++j )
191         {
192           Double_t vext = external->IsDoublePrecision() ? 
193             external->ValueAsDoubleFast(i,j) :
194             external->ValueAsFloatFast(i,j);
195           
196           if ( vext >= AliMUONVCalibParam::InvalidFloatValue() ) continue;
197           
198           validChannel = kTRUE;
199                     
200           Int_t ix = External2Internal(j);
201           
202           value[0] = vext;
203           value[1] = vext*vext;
204           
205           if ( IsHistogrammed(j) )
206           {
207             FillChannel(detElemId,manuId,i,j,vext);
208           }
209           
210           for ( Int_t k = 0; k < nk; ++k ) 
211           {
212             channel->SetValueAsDoubleFast(i,ix+k,channel->ValueAsDoubleFast(i,ix+k)+value[k]);
213
214             manu->SetValueAsDoubleFast(0,ix+k,manu->ValueAsDoubleFast(0,ix+k)+value[k]);            
215             
216             busPatch->SetValueAsDoubleFast(0,ix+k,busPatch->ValueAsDoubleFast(0,ix+k)+value[k]);
217           
218             de->SetValueAsDoubleFast(0,ix+k,de->ValueAsDoubleFast(0,ix+k)+value[k]);
219           
220             chamber->SetValueAsDoubleFast(0,ix+k,chamber->ValueAsDoubleFast(0,ix+k)+value[k]);
221           
222             if ( pcb ) 
223             {
224               pcb->SetValueAsDoubleFast(0,ix+k,pcb->ValueAsDoubleFast(0,ix+k)+value[k]);
225             }
226           }
227         }
228         
229         if ( validChannel )
230         {
231           channel->SetValueAsDoubleFast(i,IndexOfOccupancyDimension(),
232                                         channel->ValueAsDoubleFast(i,IndexOfOccupancyDimension())+1.0);
233           manu->SetValueAsDoubleFast(0,IndexOfOccupancyDimension(),
234                                                  manu->ValueAsDoubleFast(0,IndexOfOccupancyDimension())+1.0);        
235           busPatch->SetValueAsDoubleFast(0,IndexOfOccupancyDimension(),
236                                                          busPatch->ValueAsDoubleFast(0,IndexOfOccupancyDimension())+1.0);        
237           de->SetValueAsDoubleFast(0,IndexOfOccupancyDimension(),
238                                              de->ValueAsDoubleFast(0,IndexOfOccupancyDimension())+1.0);        
239           chamber->SetValueAsDoubleFast(0,IndexOfOccupancyDimension(),
240                                                        chamber->ValueAsDoubleFast(0,IndexOfOccupancyDimension())+1.0); 
241           if ( pcb ) 
242           {
243             pcb->SetValueAsDoubleFast(0,IndexOfOccupancyDimension(),
244                                       pcb->ValueAsDoubleFast(0,IndexOfOccupancyDimension())+1.0);        
245           }
246         }
247       }
248     }
249   }
250   
251   return kTRUE;
252 }
253
254 //_____________________________________________________________________________
255 Double_t 
256 AliMUONTrackerData::BusPatch(Int_t busPatchId, Int_t dim) const
257 {
258   /// Return the value of a given buspatch for a given dimension
259   /// or 0 if not existing
260   AliMUONVCalibParam* param = BusPatchParam(busPatchId);
261   return param ? Value(*param,0,dim) : 0.0;
262 }
263
264 //_____________________________________________________________________________
265 AliMUONVCalibParam* 
266 AliMUONTrackerData::BusPatchParam(Int_t busPatchId, Bool_t create) const
267 {
268   /// Return (if it exist), the VCalibParam for a given busPatch
269   
270   AliMUONVCalibParam* busPatch = fBusPatchValues ? static_cast<AliMUONVCalibParam*>
271     (fBusPatchValues->FindObject(busPatchId)) : 0x0;
272   
273   if (!busPatch && create && fBusPatchValues)
274   {
275     busPatch = CreateBusPatchParam(busPatchId);
276     fBusPatchValues->Add(busPatch);
277   }
278   
279   return busPatch;
280 }
281
282 //_____________________________________________________________________________
283 AliMUONVCalibParam* 
284 AliMUONTrackerData::CreateBusPatchParam(Int_t busPatchId) const
285 {
286   /// Create storage for one bus patch
287   
288   AliCodeTimerAuto("");
289   
290   AliMpBusPatch* bp = AliMpDDLStore::Instance()->GetBusPatch(busPatchId);
291   
292   if (!bp)
293   {
294     AliError(Form("Got an invalid buspatchId = %d",busPatchId));
295     return 0x0;
296   }
297   
298   AliMUONVCalibParam* busPatch = new AliMUONCalibParamND(Dimension(),1,busPatchId,0,0.0);
299   
300   // set the number of channels in that buspatch
301   
302   Int_t nchannels(0);
303   
304   Int_t detElemId = AliMpDDLStore::Instance()->GetDEfromBus(busPatchId);
305   
306   AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(detElemId);
307   
308   for ( Int_t i = 0; i < bp->GetNofManus(); ++i ) 
309   {
310     Int_t manuId = bp->GetManuId(i);
311     nchannels += de->NofChannelsInManu(manuId);
312   }
313   
314   busPatch->SetValueAsDouble(0,IndexOfNumberDimension(),nchannels);
315   
316   return busPatch;
317 }
318
319 //_____________________________________________________________________________
320 Double_t 
321 AliMUONTrackerData::Chamber(Int_t chamberId, Int_t dim) const
322 {
323   /// Return the value fo a given chamber for a given dimension,
324   /// or zero if not existing
325   AliMUONVCalibParam* param = ChamberParam(chamberId);
326   return param ? Value(*param,0,dim) : 0.0;
327 }
328
329 //_____________________________________________________________________________
330 AliMUONVCalibParam* 
331 AliMUONTrackerData::ChamberParam(Int_t chamberId, Bool_t create) const
332 {
333   /// Return (if it exist) the VCalibParam for a given chamber
334   
335   AliMUONVCalibParam* chamber =  fChamberValues ? static_cast<AliMUONVCalibParam*>
336   (fChamberValues->FindObject(chamberId)) : 0x0;
337   
338   if (!chamber && create && fChamberValues)
339   {
340     chamber = CreateChamberParam(chamberId);
341     fChamberValues->Add(chamber);
342   }
343     
344   return chamber;
345 }
346
347 //_____________________________________________________________________________
348 AliMUONVCalibParam* 
349 AliMUONTrackerData::CreateChamberParam(Int_t chamberId) const
350 {
351   /// Create storage for one chamber
352   
353   AliCodeTimerAuto("");
354   
355   AliMUONVCalibParam* chamber = new AliMUONCalibParamND(Dimension(),1,chamberId,0,0.0);
356   
357   // set the number of channels in that chamber
358   
359   Int_t nchannels(0);
360   
361   AliMpDEIterator it;
362   
363   it.First(chamberId);
364   
365   while ( !it.IsDone() )
366   {        
367     AliMpDetElement* det = it.CurrentDE();
368     
369     for ( Int_t i = 0; i < det->GetNofBusPatches(); ++i ) 
370     {
371       Int_t busPatchId = det->GetBusPatchId(i);
372       AliMpBusPatch* bp = AliMpDDLStore::Instance()->GetBusPatch(busPatchId);
373       for ( Int_t j = 0; j < bp->GetNofManus(); ++j ) 
374       {
375         Int_t manuId = bp->GetManuId(j);
376         nchannels += det->NofChannelsInManu(manuId);
377       }        
378     }
379     
380     it.Next();
381   }
382   
383   chamber->SetValueAsDouble(0,IndexOfNumberDimension(),nchannels);
384   
385   return chamber;
386 }
387
388 //_____________________________________________________________________________
389 Double_t 
390 AliMUONTrackerData::Channel(Int_t detElemId, Int_t manuId, 
391                             Int_t manuChannel, Int_t dim) const
392 {
393   /// Return the value for a given channel for a given dimension
394   
395   AliMUONVCalibParam* param = ChannelParam(detElemId,manuId);
396   
397   return param ? Value(*param,manuChannel,dim) : 0.0;
398 }
399
400 //_____________________________________________________________________________
401 AliMUONVCalibParam* 
402 AliMUONTrackerData::ChannelParam(Int_t detElemId, Int_t manuId,
403                                  AliMUONVCalibParam* external) const
404 {
405   /// Return (if it exist) the VCalibParam for a given manu
406   
407   AliMUONVCalibParam* param = fChannelValues ? static_cast<AliMUONVCalibParam*>
408     (fChannelValues->FindObject(detElemId,manuId)) : 0x0 ;
409   
410   if (!param && external && fChannelValues)
411   {
412     param = CreateDouble(*external,detElemId,manuId);
413     fChannelValues->Add(param);
414   }
415   
416   return param;
417 }
418
419 //_____________________________________________________________________________
420 void 
421 AliMUONTrackerData::Clear(Option_t*)
422 {
423   /// Clear all the values
424   if ( fChannelValues ) fChannelValues->Clear();
425   if ( fManuValues ) fManuValues->Clear();
426   if ( fBusPatchValues) fBusPatchValues->Clear();
427   if ( fPCBValues ) fPCBValues->Clear();
428   if ( fDEValues) fDEValues->Clear();
429   if ( fChamberValues ) fChamberValues->Clear();
430   if ( fChannelHistos ) fChannelHistos->Clear();
431   fNevents = 0;
432   NumberOfEventsChanged();
433 }
434
435 //_____________________________________________________________________________
436 Double_t 
437 AliMUONTrackerData::Count(Int_t detElemId, Int_t manuId, 
438                           Int_t manuChannel) const
439 {
440   /// Return the number of times a given channel had data
441   
442   return Channel(detElemId,manuId,manuChannel,IndexOfNumberDimension());
443 }
444
445 //_____________________________________________________________________________
446 AliMUONVCalibParam*
447 AliMUONTrackerData::CreateDouble(const AliMUONVCalibParam& param, 
448                                  Int_t detElemId, Int_t manuId) const
449 {
450   /// Create a double version of VCalibParam, for internal use
451   
452   AliCodeTimerAuto("");
453   
454   AliMUONVCalibParam* c = new AliMUONCalibParamND(Dimension(),
455                                                   param.Size(),
456                                                   detElemId,
457                                                   manuId,
458                                                   0.0);
459   
460   AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(detElemId,manuId);
461   
462   for ( Int_t i = 0; i < c->Size(); ++i ) 
463   {
464     Double_t value(0.0);
465     
466     if ( de->IsConnectedChannel(manuId,i) ) value = 1.0;
467       
468     c->SetValueAsDouble(i,IndexOfNumberDimension(),value);
469   }
470   
471   return c;
472 }
473
474 //_____________________________________________________________________________
475 Double_t 
476 AliMUONTrackerData::DetectionElement(Int_t detElemId, Int_t dim) const
477 {
478   /// Return the value for a given detection element for a given dimension
479   AliMUONVCalibParam* param = DetectionElementParam(detElemId);
480   return param ? Value(*param,0,dim) : 0.0;
481
482 }
483
484 //_____________________________________________________________________________
485 AliMUONVCalibParam* 
486 AliMUONTrackerData::DetectionElementParam(Int_t detElemId, Bool_t create) const
487 {
488   /// Return (if it exist) the VCalibParam for a given detection element
489   
490   AliMUONVCalibParam* de = fDEValues ? static_cast<AliMUONVCalibParam*>
491     (fDEValues->FindObject(detElemId)) : 0x0 ;
492   
493   if (!de && create && fDEValues)
494   {
495     de = CreateDetectionElementParam(detElemId);
496     fDEValues->Add(de);
497   }
498   
499   return de;
500   
501 }
502
503 //_____________________________________________________________________________
504 AliMUONVCalibParam* 
505 AliMUONTrackerData::CreateDetectionElementParam(Int_t detElemId) const
506 {
507   /// Create storage for one detection element
508   
509   AliCodeTimerAuto("");
510   
511   AliMUONVCalibParam*  de = new AliMUONCalibParamND(Dimension(),1,detElemId,0,0.0);
512   
513   AliMpDetElement* det = AliMpDDLStore::Instance()->GetDetElement(detElemId);
514   Int_t nchannels(0);
515   
516   for ( Int_t i = 0; i < det->GetNofBusPatches(); ++i ) 
517   {
518     Int_t busPatchId = det->GetBusPatchId(i);
519     AliMpBusPatch* bp = AliMpDDLStore::Instance()->GetBusPatch(busPatchId);
520     for ( Int_t j = 0; j < bp->GetNofManus(); ++j ) 
521     {
522       Int_t manuId = bp->GetManuId(j);
523       nchannels += det->NofChannelsInManu(manuId);
524     }        
525   }
526   
527   de->SetValueAsDouble(0,IndexOfNumberDimension(),nchannels);
528   
529   return de;
530 }
531
532 //_____________________________________________________________________________
533 TString 
534 AliMUONTrackerData::DimensionName(Int_t dim) const
535 {
536   /// Get the name of a given dimension
537   TObjString* value = static_cast<TObjString*>(fDimensionNames->At(dim));
538   if ( value ) 
539   {
540     return value->String();
541   }
542   else
543   {
544     return TString("Invalid");
545   }  
546 }
547
548 //_____________________________________________________________________________
549 Int_t 
550 AliMUONTrackerData::External2Internal(Int_t index) const 
551 {
552   /// From external to internal dimension
553   return IsSingleEvent() ? index : index*2;
554 }
555
556 //_____________________________________________________________________________
557 TString 
558 AliMUONTrackerData::ExternalDimensionName(Int_t dim) const
559 {
560   /// Get the name of a given external dimension
561   
562   TObjString* value = static_cast<TObjString*>(fExternalDimensionNames->At(dim));
563   if ( value ) 
564   {
565     return value->String();
566   }
567   else
568   {
569     return TString("Invalid");
570   }  
571 }
572
573 //_____________________________________________________________________________
574 void
575 AliMUONTrackerData::FillChannel(Int_t detElemId, Int_t manuId, Int_t manuChannel,
576                                 Int_t dim, Double_t value)
577 {
578   /// Fill histogram of a given channel
579   
580   AliMUONSparseHisto* h = GetChannelSparseHisto(detElemId, manuId, manuChannel,dim);
581  
582   h->Fill(static_cast<Int_t>(TMath::Nint(value)));
583 }
584
585 //_____________________________________________________________________________
586 AliMUONSparseHisto*
587 AliMUONTrackerData::GetChannelSparseHisto(Int_t detElemId, Int_t manuId, 
588                                           Int_t manuChannel, Int_t dim) const
589 {
590   /// Get histogram of a given channel
591   
592   if (!fChannelHistos) return 0x0;
593   
594   AliMUON1DMap* m = static_cast<AliMUON1DMap*>(fChannelHistos->FindObject(detElemId,manuId));
595   if (!m) return 0x0;
596   
597   UInt_t uid = ( manuChannel << 16 ) | dim;
598   
599   AliMUONSparseHisto* h = static_cast<AliMUONSparseHisto*>(m->FindObject(uid));
600   
601   return h;
602 }
603
604 //_____________________________________________________________________________
605 AliMUONSparseHisto*
606 AliMUONTrackerData::GetChannelSparseHisto(Int_t detElemId, Int_t manuId, 
607                                           Int_t manuChannel, Int_t dim)
608 {
609   /// Get histogram of a given channel. Create it if necessary
610   
611   if (!fChannelHistos) fChannelHistos = new AliMUON2DMap(kTRUE);
612   
613   AliMUON1DMap* m = static_cast<AliMUON1DMap*>(fChannelHistos->FindObject(detElemId,manuId));
614   if (!m)
615   {
616     m = new AliMUON1DMap(AliMpConstants::ManuNofChannels()); // start with only 1 dim
617     m->SetUniqueID( ( manuId << 16 ) | detElemId );
618     fChannelHistos->Add(m);
619   }
620   
621   UInt_t uid = ( manuChannel << 16 ) | dim;
622   
623   AliMUONSparseHisto* h = static_cast<AliMUONSparseHisto*>(m->FindObject(uid));
624   if (!h)
625   {
626     h = new AliMUONSparseHisto(fXmin,fXmax);
627     
628     h->SetUniqueID(uid);
629     
630     m->Add(h);
631   }
632
633   return h;
634 }
635
636 //_____________________________________________________________________________
637 Int_t
638 AliMUONTrackerData::GetParts(AliMUONVCalibParam* external,
639                              AliMUONVCalibParam*& chamber,
640                              AliMUONVCalibParam*& de,
641                              AliMUONVCalibParam*& busPatch,
642                              AliMUONVCalibParam*& pcb,
643                              AliMUONVCalibParam*& manu,
644                              AliMUONVCalibParam*& channel,
645                              AliMpDetElement*& mpde)
646 {
647   /// Get containers at all levels
648  
649   AliMpDDLStore* ddlStore = AliMpDDLStore::Instance();
650   
651   Int_t detElemId;
652   Int_t manuId;
653   
654   if ( external->ID1() <= 0 ) 
655   {
656     // we get a manu serial number
657     Int_t serial = external->ID0();
658     AliMpIntPair pair = ddlStore->GetDetElemIdManu(serial);
659     detElemId = pair.GetFirst();
660     manuId = pair.GetSecond();
661     if ( !detElemId ) 
662     {
663       AliError(Form("DE %d manuId %d from serial %d is not correct !",
664                     detElemId,manuId,serial));
665       return -1;
666     }
667   }
668   else
669   {
670     // we get a (de,manu) pair
671     detElemId = external->ID0();
672     manuId = external->ID1();
673   }
674
675   mpde = ddlStore->GetDetElement(detElemId);
676
677   Int_t chamberId = AliMpDEManager::GetChamberId(detElemId);
678     
679   Int_t busPatchId = ddlStore->GetBusPatchId(detElemId,manuId);
680   
681   Int_t pcbIndex = -1;
682   
683   AliMp::StationType stationType = mpde->GetStationType();
684   
685   if ( stationType == AliMp::kStation345 ) 
686   {
687     AliMpHVNamer namer;
688     pcbIndex = namer.ManuId2PCBIndex(detElemId,manuId);
689   }
690   
691   channel = ChannelParam(detElemId,manuId,external);
692   
693   manu = ManuParam(detElemId,manuId,kTRUE);
694   
695   busPatch = BusPatchParam(busPatchId,kTRUE);
696   
697   de = DetectionElementParam(detElemId,kTRUE);
698   
699   chamber = ChamberParam(chamberId,kTRUE);
700   
701   pcb = 0x0;
702   
703   if ( pcbIndex >= 0 ) 
704   {
705     pcb = PCBParam(detElemId,pcbIndex,kTRUE);
706   }
707   
708   return manuId;
709 }
710
711 //_____________________________________________________________________________
712 Bool_t 
713 AliMUONTrackerData::HasBusPatch(Int_t busPatchId) const
714 {
715   /// Whether we have data for a given buspatch
716   return ( BusPatchParam(busPatchId) != 0 );
717 }
718
719 //_____________________________________________________________________________
720 Bool_t 
721 AliMUONTrackerData::HasChamber(Int_t chamberId) const
722 {
723   /// Whether we have data for a given chamber
724   return ( ChamberParam(chamberId) != 0 );
725 }
726
727 //_____________________________________________________________________________
728 Bool_t 
729 AliMUONTrackerData::HasDetectionElement(Int_t detElemId) const
730 {
731   /// Whether we have data for a given detection element
732   return ( DetectionElementParam(detElemId) != 0 );
733 }
734
735 //_____________________________________________________________________________
736 Bool_t
737 AliMUONTrackerData::HasManu(Int_t detElemId, Int_t manuId) const
738 {
739   /// Whether we have data for a given manu
740   return ( ManuParam(detElemId,manuId) != 0 ); 
741 }
742
743 //_____________________________________________________________________________
744 Bool_t
745 AliMUONTrackerData::HasPCB(Int_t detElemId, Int_t pcbIndex) const
746 {
747   /// Whether we have data for a given pcb
748   return ( PCBParam(detElemId,pcbIndex) != 0 ); 
749 }
750
751 //_____________________________________________________________________________
752 Double_t 
753 AliMUONTrackerData::Manu(Int_t detElemId, Int_t manuId, Int_t dim) const
754 {
755   /// Return the value for a given manu and a given dimension
756   
757   AliMUONVCalibParam* param = ManuParam(detElemId,manuId);
758   return param ? Value(*param,0,dim) : 0.0;
759 }
760
761 //_____________________________________________________________________________
762 AliMUONVCalibParam* 
763 AliMUONTrackerData::ManuParam(Int_t detElemId, Int_t manuId, Bool_t create) const
764 {
765   /// Get the VCalibParam for a given manu
766   
767   AliMUONVCalibParam* manu = fManuValues ? static_cast<AliMUONVCalibParam*>
768     (fManuValues->FindObject(detElemId,manuId)) : 0x0 ;
769   
770   if (!manu && create && fManuValues)
771   {
772     manu = CreateManuParam(detElemId,manuId);
773     fManuValues->Add(manu);
774   }
775   
776   return manu;
777 }
778
779 //_____________________________________________________________________________
780 AliMUONVCalibParam* 
781 AliMUONTrackerData::CreateManuParam(Int_t detElemId, Int_t manuId) const
782 {
783   /// Create storage for one manu
784   
785   AliCodeTimerAuto("");
786   
787   AliMUONVCalibParam* manu = new AliMUONCalibParamND(Dimension(),1,detElemId,manuId,0.0);
788   
789   // set the number of channels in that manu
790   
791   AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(detElemId);
792   
793   manu->SetValueAsDouble(0,IndexOfNumberDimension(),de->NofChannelsInManu(manuId));
794   
795   return manu;
796 }
797
798 //_____________________________________________________________________________
799 Long64_t
800 AliMUONTrackerData::Merge(TCollection*)
801 {
802   /// Merge all tracker data objects from li into a single one.
803   
804   AliError("Not implemented yet");
805   
806   return 0;
807 }
808
809 //_____________________________________________________________________________
810 Int_t 
811 AliMUONTrackerData::NumberOfDimensions() const
812 {
813   /// Number of dimensions we're dealing with
814   
815   return fDimension + fgkVirtualExtraDimension; 
816 }
817
818 //_____________________________________________________________________________
819 Double_t 
820 AliMUONTrackerData::PCB(Int_t detElemId, Int_t pcbIndex, Int_t dim) const
821 {
822   /// Return the value of a given pcb for a given dimension
823
824   AliMUONVCalibParam* param = PCBParam(detElemId,pcbIndex);
825   
826   return param ? Value(*param,pcbIndex,dim) : 0.0;
827 }
828
829 //_____________________________________________________________________________
830 AliMUONVCalibParam* 
831 AliMUONTrackerData::PCBParam(Int_t detElemId, Int_t pcbIndex, Bool_t create) const
832 {
833   /// Return (if it exist) the VCalibParam for a given pcb
834
835   AliMUONVCalibParam* pcb =  fPCBValues ? static_cast<AliMUONVCalibParam*>
836     (fPCBValues->FindObject(detElemId,pcbIndex)) : 0x0 ;
837   
838   if (create && fPCBValues && !pcb)
839   {
840     pcb = CreatePCBParam(detElemId,pcbIndex);
841     fPCBValues->Add(pcb);
842   }
843   
844   return pcb;
845 }
846
847 //_____________________________________________________________________________
848 AliMUONVCalibParam* 
849 AliMUONTrackerData::CreatePCBParam(Int_t detElemId, Int_t pcbIndex) const
850 {
851   /// Create storage for one PCB (station345 only)
852   
853   AliCodeTimerAuto("");
854   
855   AliMpHVNamer namer;
856   
857   AliMUONVCalibParam* pcb = new AliMUONCalibParamND(Dimension(),
858                                                     namer.NumberOfPCBs(detElemId),
859                                                     detElemId,
860                                                     pcbIndex,
861                                                     0.0);
862   return pcb;
863 }
864
865 //_____________________________________________________________________________
866 void 
867 AliMUONTrackerData::Print(Option_t* wildcard, Option_t* opt) const
868 {
869   /// Printout
870   
871   TNamed::Print(opt);
872   
873   if ( !fIsSingleEvent ) 
874   {
875     cout << " Nevents=" << fNevents << endl;
876   }
877
878   for ( Int_t i = 0; i <= fExternalDimensionNames->GetLast(); ++i ) 
879   {
880     TObjString* name = static_cast<TObjString*>(fExternalDimensionNames->At(i));
881     cout << Form("External Dimension %2d Name %s %s",i,
882                  ( name ? name->String().Data() : "null"),
883                  ( IsHistogrammed(i) ? "(histogrammed)" : "")) << endl;
884   }
885   
886   for ( Int_t i = 0; i <= fDimensionNames->GetLast(); ++i ) 
887   {
888     TObjString* name = static_cast<TObjString*>(fDimensionNames->At(i));
889     cout << Form("Internal Dimension %2d Name %s",i,
890                  ( name ? name->String().Data() : "null")) << endl;
891   }
892     
893   TString sopt(opt);
894   sopt.ToUpper();
895   
896   if ( sopt.Contains("CHANNEL") && fChannelValues ) 
897   {
898     fChannelValues->Print(wildcard,opt);
899   }
900
901   if ( sopt.Contains("MANU") && fManuValues ) 
902   {
903     fManuValues->Print(wildcard,opt);
904   }
905
906   if ( sopt.Contains("BUSPATCH") && fBusPatchValues ) 
907   {
908     fBusPatchValues->Print(wildcard,opt);
909   }
910
911   if ( sopt.Contains("DE") && fDEValues ) 
912   {
913     fDEValues->Print(wildcard,opt);
914   }
915
916   if ( sopt.Contains("CHAMBER") && fChamberValues ) 
917   {
918     fChamberValues->Print(wildcard,opt);
919   }
920   
921 }
922
923 //_____________________________________________________________________________
924 void
925 AliMUONTrackerData::SetDimensionName(Int_t index, const char* name)
926 {  
927   /// Set the name of a given dimension
928
929   if ( index >= fExternalDimension ) 
930   {
931     AliError(Form("Index out of bounds : %d / %d",index,fExternalDimension));
932     return;
933   }
934   
935   Int_t ix = External2Internal(index);
936   
937   if ( !IsSingleEvent() ) 
938   {
939     const char* prefix[] = { "mean", "sigma" };
940   
941     for ( Int_t i = 0; i < 2; ++i ) 
942     {
943       Int_t j = ix+i;
944     
945       SetInternalDimensionName(j,Form("%s of %s",prefix[i],name));
946     }
947   }
948   else
949   {
950     SetInternalDimensionName(index,name);
951   }
952   
953   SetExternalDimensionName(index,name);
954 }
955
956 //_____________________________________________________________________________
957 void 
958 AliMUONTrackerData::MakeHistogramForDimension(Int_t index, Bool_t value, Double_t xmin, Double_t xmax)
959 {
960   /// decide to make histos for a given dimension
961   if ( index >= ExternalDimension() ) 
962   {
963     AliError(Form("Index out of bounds : %d / %d",index,ExternalDimension()));
964     return;
965   }
966   
967   fHistogramming[index] = value;
968   fXmin = xmin;
969   fXmax = xmax;
970 }
971
972 //_____________________________________________________________________________
973 void 
974 AliMUONTrackerData::SetInternalDimensionName(Int_t index, const char* value)
975 {
976   /// Set the name of a given internal dimension
977   if ( index >= fDimension ) 
978   {
979     AliError(Form("Index out of bounds : %d / %d",index,fDimension));
980     return;
981   }
982   
983   TObjString* ovalue = static_cast<TObjString*>(fDimensionNames->At(index));
984     
985   if ( ovalue ) 
986   {
987     fDimensionNames->Remove(ovalue);
988     delete ovalue;
989   }
990   fDimensionNames->AddAt(new TObjString(value),index);
991 }
992
993 //_____________________________________________________________________________
994 void 
995 AliMUONTrackerData::SetExternalDimensionName(Int_t index, const char* value)
996 {
997   /// Set the name of a given external dimension
998   if ( index >= fExternalDimension ) 
999   {
1000     AliError(Form("Index out of bounds : %d / %d",index,fExternalDimension));
1001     return;
1002   }
1003   
1004   TObjString* ovalue = static_cast<TObjString*>(fExternalDimensionNames->At(index));
1005   
1006   if ( ovalue ) 
1007   {
1008     fExternalDimensionNames->Remove(ovalue);
1009     delete ovalue;
1010   }
1011   fExternalDimensionNames->AddAt(new TObjString(value),index);
1012 }
1013
1014 //_____________________________________________________________________________
1015 Double_t 
1016 AliMUONTrackerData::Value(const AliMUONVCalibParam& param, Int_t i, Int_t dim) const
1017 {
1018   /// Compute the value for a given dim, using the internal information we have
1019   /// Basically we're converting sum of weights and sum of squares of weights
1020   /// into means and sigmas, and number of events into occupancy number.
1021
1022   Double_t n = param.ValueAsDouble(i,IndexOfNumberDimension());
1023   
1024   if ( dim == IndexOfNumberDimension() ) return n; // the number of channels in any given element does not depend on the number of events
1025   
1026   Double_t occ = param.ValueAsDouble(i,IndexOfOccupancyDimension());
1027
1028   if ( dim >= fDimension ) 
1029   {
1030     return occ;
1031   }
1032   
1033   if ( dim == IndexOfOccupancyDimension() ) return occ/n/NumberOfEvents();
1034   
1035   Double_t value = param.ValueAsDouble(i,dim);
1036   
1037   if ( value >= AliMUONVCalibParam::InvalidFloatValue() ) return AliMUONVCalibParam::InvalidFloatValue();
1038   
1039   if ( TMath::Even(dim) || IsSingleEvent() ) 
1040   {
1041     return value/occ;
1042   }
1043   else
1044   {
1045     Double_t nn = occ;
1046     
1047     if ( nn > 1.0 ) 
1048     {
1049       Double_t mean = param.ValueAsDouble(i,dim-1)/nn;
1050     
1051       return TMath::Sqrt(TMath::Abs((value-nn*mean*mean)/(nn-1.0)));
1052     }
1053     else
1054     {
1055       return 0.0;
1056     }
1057   }
1058   
1059   AliError("Why am I here ?");
1060   return 0.0;
1061 }
1062