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