Added protection for NaN
[u/mrichter/AliRoot.git] / MUON / AliMUONTrackerDataHistogrammer.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 "AliMUONTrackerDataHistogrammer.h"
19
20 #include "AliLog.h"
21 #include "AliMUONPainterGroup.h"
22 #include "AliMUONSparseHisto.h"
23 #include "AliMUONVPainter.h"
24 #include "AliMUONVTrackerData.h"
25 #include "AliMpBusPatch.h"
26 #include "AliMpConstants.h"
27 #include "AliMpDDLStore.h"
28 #include "AliMpDEIterator.h"
29 #include "AliMpDetElement.h"
30 #include "AliMpManuUID.h"
31 #include <TClass.h>
32 #include <TH1.h>
33 #include <TObjArray.h>
34 #include <TROOT.h>
35 #include <TMath.h>
36
37 ///\class AliMUONTrackerDataHistogrammer
38 ///
39 /// Class to generate histograms from AliMUONVTrackerData 
40 /// (and AliMUONVPainter) objects
41 ///
42 /// \author Laurent Aphecetche, Subatech
43 ///
44
45 ///\cond CLASSIMP
46 ClassImp(AliMUONTrackerDataHistogrammer)
47 ///\endcond CLASSIMP
48
49 //_____________________________________________________________________________
50 AliMUONTrackerDataHistogrammer::AliMUONTrackerDataHistogrammer(const AliMUONVTrackerData& data,
51                                                                Int_t externalDim,
52                                                                Int_t internalDim)
53 : TObject(),
54 fData(data),
55 fExternalDim(externalDim),
56 fInternalDim(internalDim)
57 {
58   /// ctor
59 }
60
61 //_____________________________________________________________________________
62 AliMUONTrackerDataHistogrammer::~AliMUONTrackerDataHistogrammer()
63 {
64   /// dtor
65 }
66
67 //_____________________________________________________________________________
68 void
69 AliMUONTrackerDataHistogrammer::Add(TH1& h, const AliMUONSparseHisto& sh) const
70 {
71   /// Add sparse histo content to histogram.
72   
73   Double_t entries(h.GetEntries());
74   
75   for ( Int_t i = 0; i < sh.GetNbins(); ++i ) 
76   {
77     Int_t count = sh.GetBinContent(i);
78     
79     h.Fill(sh.GetBinCenter(i),count);
80     
81     entries += count;
82   }
83   
84   h.SetEntries(entries);
85   
86   if (sh.HasUnderflow()) h.SetBinContent(0,1);
87   if (sh.HasOverflow()) h.SetBinContent(h.GetNbinsX()+1,1);
88 }
89
90 //_____________________________________________________________________________
91 void
92 AliMUONTrackerDataHistogrammer::AddBusPatchHisto(TH1& h, Int_t busPatchId) const
93 {
94   /// Add data from one bus patch to the histogram
95   
96   if ( fData.HasBusPatch(busPatchId ) )
97   {
98     AliMpBusPatch* busPatch = AliMpDDLStore::Instance()->GetBusPatch(busPatchId);
99     for ( Int_t i = 0; i < busPatch->GetNofManus(); ++i ) 
100     {
101       Int_t manuId = busPatch->GetManuId(i);
102       AddManuHisto(h,busPatch->GetDEId(),manuId);
103     }
104   }
105 }
106 //_____________________________________________________________________________
107 void
108 AliMUONTrackerDataHistogrammer::AddDEHisto(TH1& h, Int_t detElemId) const
109 {
110   /// Add data from one detection element to the histogram
111   
112   if ( fData.HasDetectionElement(detElemId) )
113   {
114     AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(detElemId);
115     for ( Int_t i = 0; i < de->GetNofBusPatches(); ++ i ) 
116     {
117       Int_t busPatchId = de->GetBusPatchId(i);
118       AddBusPatchHisto(h,busPatchId);
119     }
120   }
121 }
122
123 //_____________________________________________________________________________
124 void
125 AliMUONTrackerDataHistogrammer::AddManuHisto(TH1& h, Int_t detElemId, Int_t manuId) const
126 {
127   /// Add data from a given manu to histogram
128   
129   if ( fData.HasManu(detElemId,manuId) )
130   {
131     for ( Int_t i = 0; i < AliMpConstants::ManuNofChannels(); ++i ) 
132     {
133       if ( fData.HasChannel(detElemId,manuId,i) )
134       {
135         if ( IsInternalMode() ) 
136         {
137           h.Fill(fData.Channel(detElemId,manuId,i,fInternalDim));
138         }
139         else
140         {
141           AliMUONSparseHisto* sh = fData.GetChannelSparseHisto(detElemId,manuId,i);
142         
143           if ( sh ) 
144           {       
145             Add(h,*sh);
146           }
147         }
148       }
149     }
150   }
151 }
152
153 //_____________________________________________________________________________
154 TH1*
155 AliMUONTrackerDataHistogrammer::CreateChannelHisto(Int_t detElemId, 
156                                                    Int_t manuId, 
157                                                    Int_t manuChannel) const
158 {
159   /// Create histogram of a given channel. Note that in order
160   /// to keep memory footprint as low as possible, you should delete
161   /// the returned pointer as soon as possible...
162   
163   if ( fData.HasChannel(detElemId, manuId, manuChannel) && fData.IsHistogrammed(fExternalDim) )
164   {
165     AliMUONSparseHisto* sh = fData.GetChannelSparseHisto(detElemId,manuId,manuChannel);
166     
167     if ( sh ) 
168     {
169       Int_t nbins((1<<sh->Nbits()));
170       Double_t xmin,xmax;
171       fData.HistogramRange(xmin,xmax);
172       
173       TH1* h = CreateHisto(Form("DE%04dMANU%04dCH%02d",detElemId,manuId,manuChannel),
174                            nbins,xmin,xmax);
175       if (h ) 
176       {
177         Add(*h,*sh);
178       }
179       return h;
180     }
181   }
182   return 0x0;
183 }
184
185 //_____________________________________________________________________________
186 TH1*
187 AliMUONTrackerDataHistogrammer::CreateHisto(const char* name,
188                                             Int_t nbins,
189                                             Double_t xmin,
190                                             Double_t xmax) const
191 {
192   /// Create a single histogram
193   
194   TH1* h(0);
195   
196   if ( xmin < xmax ) 
197   {
198     h = new TH1F(name,name,nbins,xmin,xmax);
199     h->SetDirectory(gROOT);
200   }
201         else
202         {
203                 AliError(Form("Cannot create histo for name=%s nbins=%d xmin=%e xmax=%e",name,nbins,xmin,xmax));
204         }
205   return h;
206 }
207
208 //_____________________________________________________________________________
209 TH1* 
210 AliMUONTrackerDataHistogrammer::CreateHisto(const AliMUONVPainter& painter, 
211                                                                                                                                                                                 Int_t externalDim,
212                                                                                                                                                                                 Int_t internalDim)
213 {
214   /// Create an histogram, from given dim of given data, 
215   /// for all the channels handled by painter
216
217   AliMUONPainterGroup* group = painter.Master()->PlotterGroup();
218   
219   if ( !group ) return 0x0; // no data to histogram in this painter
220   
221   AliMUONVTrackerData* data = group->Data();
222   
223   if ( externalDim >= data->ExternalDimension() )
224   {
225     AliErrorClass(Form("externalDim %d is out of bounds",externalDim));
226     return 0x0;
227   }
228
229   if ( internalDim >= data->NumberOfDimensions() )
230   {
231     AliErrorClass(Form("internalDim %d is out of bounds",internalDim));
232     return 0x0;
233   }
234   
235   if ( internalDim < 0 && externalDim < 0 ) 
236   {
237     AliErrorClass("Both internal and external dim are < 0 !!!");
238     return 0x0;
239   }
240   
241   AliMUONTrackerDataHistogrammer tdh(*data,externalDim,internalDim);
242
243   TObjArray manuArray;
244   
245   painter.FillManuList(manuArray);
246
247   AliMpManuUID* mid;
248   TIter next(&manuArray);
249
250   TString basename(Form("%s-%s",painter.PathName().Data(),painter.Attributes().GetName()));
251   TString ext;
252   Int_t nbins((1<<12));
253   Double_t xmin(0.0);
254   Double_t xmax(0.0);
255   
256   if ( !tdh.IsInternalMode() ) 
257   {
258     data->HistogramRange(xmin,xmax);
259     
260     xmin -= 0.5;
261     xmax -= 0.5;
262     
263     ext = data->ExternalDimensionName(externalDim).Data();
264   }
265   else
266   {
267     tdh.GetDataRange(manuArray,xmin,xmax);
268     ext = data->DimensionName(internalDim).Data();
269     nbins = 100;
270   }
271   
272   TString name(Form("%s-%s",basename.Data(),ext.Data()));
273
274   TH1* histo = tdh.CreateHisto(name.Data(),nbins,xmin,xmax);
275
276   if ( histo ) 
277   {
278     while ( ( mid = static_cast<AliMpManuUID*>(next()) ) )
279     {
280       TH1* h = tdh.CreateManuHisto(mid->DetElemId(),mid->ManuId(),nbins,xmin,xmax);
281       if ( h ) 
282       {
283         histo->Add(h);
284       }
285       delete h;
286     }
287   }
288   else
289   {
290     AliErrorClass(Form("Could not create histo for painter %s external dim %d internal dim %d",
291                        painter.PathName().Data(),externalDim,internalDim));
292   }
293   
294   return histo;
295 }
296
297 //_____________________________________________________________________________
298 TH1*
299 AliMUONTrackerDataHistogrammer::CreateManuHisto(Int_t detElemId, Int_t manuId,
300                                                 Int_t nbins,
301                                                 Double_t xmin,
302                                                 Double_t xmax) const
303 {
304   /// Create histogram of a given manu. Note that in order
305   /// to keep memory footprint as low as possible, you should delete
306   /// the returned pointer as soon as possible...
307   
308   TH1* h(0x0);
309   
310   if ( !fData.HasManu(detElemId,manuId) ) return 0x0;
311   
312   if ( ( fExternalDim >= 0 && fData.IsHistogrammed(fExternalDim) ) ||
313        ( fInternalDim >= 0 && fInternalDim < fData.NumberOfDimensions() ) )
314   {
315     h = CreateHisto(Form("DE%04dMANU%04d",detElemId,manuId),
316                     nbins,xmin,xmax);
317     if ( h ) AddManuHisto(*h,detElemId,manuId);
318   }
319   
320   return h;
321 }
322
323 //_____________________________________________________________________________
324 void
325 AliMUONTrackerDataHistogrammer::GetDataRange(const TObjArray& manuArray, 
326                                              Double_t& xmin, Double_t& xmax) const
327 {
328   /// Get data range (in case of InternalMode() only) spanned by the manus in
329   /// manuArray
330   
331   xmin = FLT_MAX;
332   xmax = -FLT_MAX;
333   
334   if (!IsInternalMode())
335   {
336     AliError("Cannot use this method for external mode !");
337   }
338
339   AliMpManuUID* mid;
340   TIter next(&manuArray);
341   
342   while ( ( mid = static_cast<AliMpManuUID*>(next()) ) )
343   {
344     Int_t detElemId = mid->DetElemId();
345     Int_t manuId = mid->ManuId();
346     
347     for ( Int_t i = 0; i < AliMpConstants::ManuNofChannels(); ++i ) 
348     {
349       if ( fData.HasChannel(detElemId,manuId,i) ) 
350       {
351         Double_t value = fData.Channel(detElemId,manuId,i,fInternalDim);
352                                 
353                                 if ( ! TMath::Finite(value) )
354                                 {
355                                         AliError(Form("Got a NaN for DE %d manu %d ch %d",detElemId,manuId,i));
356                                 }
357                                 else
358                                 {
359                                         xmin = TMath::Min(xmin,value);
360                                         xmax = TMath::Max(xmax,value);
361                                 }
362       }
363     }
364   }
365
366 }
367