new functionality and new class added
[u/mrichter/AliRoot.git] / MUON / AliMUONTriggerDisplay.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 // --- MUON header files ---
19 #include "AliMUONTriggerDisplay.h"
20
21 #include "AliMpDDLStore.h"
22 #include "AliMpVSegmentation.h"
23 #include "AliMpSegmentation.h"
24 #include "AliMpConstants.h"
25 #include "AliMpPad.h"
26 #include "AliMpLocalBoard.h"
27 #include "AliMpCDB.h"
28
29 // --- AliRoot header files ---
30 #include "AliLog.h"
31
32 // --- ROOT system ---
33 #include <TH1.h> 
34 #include <TH2.h>
35
36 //-----------------------------------------------------------------------------
37 /// \class AliMUONTriggerDisplay
38 ///
39 /// MUON base class for converting histos as a function of strip/board/slat number
40 /// into display histos showing the detection element position in the 
41 /// trigger chamber.
42 ///
43 /// Input histos can be given as:
44 ///  - TH2 with x -> board # [1-234]  and   y -> strip # in board [0-15].  Option: kDisplayStrips
45 ///  - TH1 with x -> board # [1-234]                                       Option: kDisplayBoards
46 ///  - TH1 with x -> slat #  [0-17]                                        Option: kDisplaySlats
47 ///
48 /// \author D. Stocco
49
50 /// \cond CLASSIMP
51 ClassImp(AliMUONTriggerDisplay)
52 /// \endcond
53            
54 //____________________________________________________________________________ 
55 AliMUONTriggerDisplay::AliMUONTriggerDisplay() : 
56 TObject()
57 {
58   /// ctor
59 }
60
61 //__________________________________________________________________
62 AliMUONTriggerDisplay::~AliMUONTriggerDisplay()
63 {
64   /// dtor
65 }
66
67
68 //____________________________________________________________________________ 
69 TH2* AliMUONTriggerDisplay::GetEmptyDisplayHisto(TString displayHistoName, EDisplayType displayType,
70                                                  Int_t cathode, Int_t chamber,
71                                                  TString displayHistoTitle)
72 {
73   //
74   /// Return the display histogram with optimized binning
75   /// but do not fill it.
76   //
77   TH2F* displayHisto = new TH2F();
78   
79   InitOrDisplayTriggerInfo(0x0, displayHisto, displayType,
80                            cathode, chamber, displayHistoName, displayHistoTitle);
81   
82   return displayHisto;
83 }
84
85
86 //____________________________________________________________________________ 
87 TH2* AliMUONTriggerDisplay::GetBoardNumberHisto(TString displayHistoName,
88                                                 Int_t chamber,
89                                                 TString displayHistoTitle)
90 {
91   //
92   /// Return the display histogram with optimized binning
93   /// and fill it with the board number
94   //
95
96   const Int_t kNboards = AliMpConstants::NofLocalBoards();
97   TH1F* inputHisto = new TH1F("boardNumbers","Board Numbers",kNboards,0.5,(Float_t)kNboards + 0.5);
98   for(Int_t ibin=1; ibin<=kNboards; ibin++){
99     inputHisto->Fill(ibin,ibin);
100   }
101
102   TH2F* displayHisto = (TH2F*)GetEmptyDisplayHisto(displayHistoName, kDisplayBoards, 0, chamber, displayHistoTitle);
103   FillDisplayHistogram(inputHisto,displayHisto,kDisplayBoards,0,chamber,kNumbered);
104   
105   delete inputHisto;
106
107   displayHisto->SetStats(kFALSE);
108   return displayHisto;
109 }
110
111
112 //____________________________________________________________________________ 
113 TH2* AliMUONTriggerDisplay::GetDisplayHistogram(TH1* inputHisto, TString displayHistoName,
114                                                 EDisplayType displayType, Int_t cathode,
115                                                 Int_t chamber, TString displayHistoTitle,
116                                                 EDisplayOption displayOpt)
117 {
118   //
119   /// Get histogram displaying the information contained in the input histogram
120   //
121   TH2* displayHisto = GetEmptyDisplayHisto(displayHistoName, displayType,
122                                            cathode, chamber, displayHistoTitle);
123
124   FillDisplayHistogram(inputHisto, displayHisto, displayType, cathode, chamber, displayOpt);
125
126   return displayHisto;
127 }
128
129 //____________________________________________________________________________ 
130 Bool_t AliMUONTriggerDisplay::FillDisplayHistogram(TH1* inputHisto, TH2* displayHisto,
131                                                    EDisplayType displayType, Int_t cathode,
132                                                    Int_t chamber, EDisplayOption displayOpt)
133 {
134   //
135   /// Fill a previously initialized display histogram 
136   /// with the information contained in inputHisto.
137   /// To get initialized display, please use GetEmptyDisplayHisto method
138   //
139   return InitOrDisplayTriggerInfo(inputHisto, displayHisto, displayType,
140                                   cathode, chamber, "", "",displayOpt);
141 }
142
143 //____________________________________________________________________________ 
144 Bool_t AliMUONTriggerDisplay::InitOrDisplayTriggerInfo(TH1* inputHisto, TH2* displayHisto,
145                                                        EDisplayType displayType,
146                                                        Int_t cathode, Int_t chamber,
147                                                        TString displayHistoName, TString displayHistoTitle,
148                                                        EDisplayOption displayOpt)
149 {
150   //
151   /// Initialize trigger information display histograms using mapping
152   /// Trigger information is displayed in a user-friendly way:
153   /// from local board and strip numbers to their position on chambers.
154   //
155
156   // Load mapping
157   if ( ! AliMpSegmentation::Instance(kFALSE) ) {
158     /// Load mapping
159     if ( ! AliMpCDB::LoadDDLStore() ) {
160       AliError("Could not access mapping from OCDB !");
161       AliError("Histograms are not initialized !");
162       return kFALSE;
163     }
164   }
165
166   Int_t iCh = (chamber > AliMpConstants::NofTrackingChambers()) ? chamber - 11 : chamber;
167   Int_t iCath = cathode;
168
169   TArrayD xAxisStrip;
170   TArrayD yAxisStrip;
171   TArrayD xAxisBoard;
172   TArrayD yAxisBoard;
173
174   Float_t yOffsetLine, xOffsetLine = 0.;
175
176   const Float_t kResetValue=1234567.;
177
178   if(!inputHisto){
179     xAxisBoard.Set(55);
180     xAxisBoard.Reset(kResetValue);
181     yAxisBoard.Set(50);
182     yAxisBoard.Reset(kResetValue);
183
184     xAxisStrip.Set(420);
185     xAxisStrip.Reset(kResetValue);
186     yAxisStrip.Set(710);
187     yAxisStrip.Reset(kResetValue);
188   }
189   else if(!displayHisto){
190       AliWarning("Display histogram not initialized. Please initialize it first!");
191       return kFALSE;
192   }
193   else if ( inputHisto->GetEntries() == 0 ) {
194     return kTRUE;
195   }
196
197   Float_t xWidth, yWidth, yWidthSlat=0., xWidthCol=0.;
198   Float_t x1,x2,y1,y2;
199   Float_t x1b=0., x2b=0., y1b=0., y2b=0.;
200   Float_t xcPad, ycPad;
201   Int_t line=0, slat;
202   Float_t sign = 1.;
203
204   const Float_t kShiftB = 0.5;
205   const Float_t kShiftS = 0.1;
206
207   const Float_t kShiftX = (iCath==0) ? kShiftB : kShiftS;
208   const Float_t kShiftY = (iCath==0) ? kShiftS : kShiftB;
209   const Float_t kShiftEl = (displayType==kDisplaySlats) ? 0.01 : kShiftB;
210
211   Int_t iChamber = iCh + AliMpConstants::NofTrackingChambers();
212   for(Int_t iLoc = 0; iLoc < AliMpConstants::NofLocalBoards(); iLoc++) {  
213     Int_t iBoard = iLoc+1;
214     Int_t detElemId = AliMpDDLStore::Instance()->GetDEfromLocalBoard(iBoard, iChamber);
215
216     if (!detElemId) continue;
217
218     AliMpLocalBoard* localBoard = AliMpDDLStore::Instance()->GetLocalBoard(iBoard, kFALSE);
219
220     // skip copy cards
221     if( !localBoard->IsNotified()) 
222       continue;
223
224     // get segmentation
225     const AliMpVSegmentation* seg[2] = {
226       AliMpSegmentation::Instance()->GetMpSegmentation(detElemId, AliMp::GetCathodType(0)),
227       AliMpSegmentation::Instance()->GetMpSegmentation(detElemId, AliMp::GetCathodType(1))};
228
229     if(iLoc==0){
230       AliMpPad pad1 = seg[1]->PadByLocation(iBoard,0,kFALSE);
231       yWidthSlat = pad1.GetDimensionY();
232       AliMpPad pad0 = seg[0]->PadByLocation(iBoard,0,kFALSE);
233       xOffsetLine = TMath::Abs(pad0.GetPositionX()) + pad0.GetDimensionX();
234       xWidthCol = 2.* pad0.GetDimensionX();
235     }
236
237     // Get ideal global position of DetElemId center
238     slat = detElemId%100;
239     line = (4 + slat)%18;
240     sign = 1.;
241     if(line>8) {
242       line = 17 - line;
243       sign = -1.;
244     }
245     yOffsetLine = (Float_t)(line - 4) * 2. * yWidthSlat;
246
247     for(Int_t cath=0; cath<AliMpConstants::NofCathodes(); cath++){
248       // Loop on cathodes: 
249       // necessary because strip info is read for each cathode
250       // board info is read only from cathode 0
251
252       // loop over strips
253       for (Int_t iStrip = 0; iStrip < 16; ++iStrip) {
254         // get pad from electronics
255
256         Int_t offset = 0;
257         if (cath && localBoard->GetSwitch(AliMpLocalBoard::kZeroAllYLSB)) offset = -8;
258
259         AliMpPad pad = seg[cath]->PadByLocation(iBoard,iStrip+offset,kFALSE);
260
261         if (!pad.IsValid()) continue;
262
263         xWidth = pad.GetDimensionX();
264         yWidth = pad.GetDimensionY();
265         xcPad = sign * (pad.GetPositionX() + xOffsetLine);
266         if(line==4) xcPad += 0.75 * sign * xWidthCol;
267         ycPad = pad.GetPositionY() + yOffsetLine;
268
269         if(cath==iCath){
270           x1 = xcPad - xWidth + kShiftX;
271           y1 = ycPad - yWidth + kShiftY;
272           x2 = xcPad + xWidth - kShiftX;
273           y2 = ycPad + yWidth - kShiftY;
274
275           if(!inputHisto){
276             AddSortedPoint(x1, xAxisStrip, kResetValue);
277             AddSortedPoint(x2, xAxisStrip, kResetValue);
278
279             AddSortedPoint(y1, yAxisStrip, kResetValue);
280             AddSortedPoint(y2, yAxisStrip, kResetValue);
281           }
282           else if(displayType==kDisplayStrips) 
283             FillBins(inputHisto, displayHisto, iBoard, iStrip, x1, x2, y1, y2, kShiftX, kShiftY, displayOpt);
284         }
285
286         if(cath==0){
287           if(iStrip+offset==0) {
288             x1b = xcPad - xWidth + kShiftEl;
289             y1b = ycPad - yWidth + kShiftEl;
290           }
291           x2b = xcPad + xWidth - kShiftEl;
292           y2b = ycPad + yWidth - kShiftEl;
293         }
294       } // loop on strips
295
296       // if iCath==0 strip info and board info are both filled -> break!
297       // if iCath==1 board info is filled at cath==0. Strip info to be filled at cath==1
298       if(iCath==0) break;
299     } // loop on cathodes
300
301     if(!inputHisto){
302       // Per board
303       AddSortedPoint(x1b, xAxisBoard, kResetValue);
304       AddSortedPoint(x2b, xAxisBoard, kResetValue);
305
306       AddSortedPoint(y1b, yAxisBoard, kResetValue);
307       AddSortedPoint(y2b, yAxisBoard, kResetValue);
308     }
309     else if(displayType==kDisplayBoards) 
310       FillBins(inputHisto, displayHisto, iBoard, -1, x1b, x2b, y1b, y2b, kShiftEl, kShiftEl, displayOpt);
311     else if(displayType==kDisplaySlats) 
312       FillBins(inputHisto, displayHisto, slat, -1, x1b, x2b, y1b, y2b, kShiftEl, kShiftEl, displayOpt);
313   } // loop on local boards
314
315   if(inputHisto) return kTRUE;
316
317   displayHisto->Reset();
318
319   // Book histos
320   const Float_t kMinDiff = 0.1;
321
322   TArrayD* currArray[4] = {&xAxisStrip, &yAxisStrip, 
323                            &xAxisBoard, &yAxisBoard};
324   for(Int_t iaxis=0; iaxis<4; iaxis++){
325     Int_t ipoint=0;
326     while(TMath::Abs((*currArray[iaxis])[ipoint]-kResetValue)>kMinDiff) { 
327       ipoint++;
328     }
329     if(ipoint>currArray[iaxis]->GetSize()-2) 
330       AliWarning(Form("Array size (%i) lower than the number of points!", currArray[iaxis]->GetSize()));
331     currArray[iaxis]->Set(ipoint);
332   }
333
334   switch(displayType){
335   case kDisplayStrips:
336     displayHisto->SetBins(xAxisStrip.GetSize()-1, xAxisStrip.GetArray(),
337                           yAxisStrip.GetSize()-1, yAxisStrip.GetArray());
338     break;
339   case kDisplayBoards:
340   case kDisplaySlats:
341     displayHisto->SetBins(xAxisBoard.GetSize()-1, xAxisBoard.GetArray(),
342                           yAxisBoard.GetSize()-1, yAxisBoard.GetArray());
343     break;
344   }
345
346   displayHisto->SetName(displayHistoName.Data());
347   displayHisto->SetTitle(displayHistoTitle.Data());
348   displayHisto->SetXTitle("X (cm)");
349   displayHisto->SetYTitle("Y (cm)");
350   //displayHisto->SetStats(kFALSE);
351
352   return kTRUE;
353 }
354
355
356 //____________________________________________________________________________ 
357 Bool_t AliMUONTriggerDisplay::AddSortedPoint(Float_t currVal, TArrayD& position, const Float_t kResetValue)
358 {
359   //
360   /// Add sorted point in array according to an increasing order.
361   /// Used to build display histograms axis.
362   //
363   Int_t nEntries = position.GetSize()-1;
364   Float_t tmp1, tmp2;
365   const Float_t kMinDiff = 0.1;
366   for(Int_t i=0; i<nEntries; i++){
367     if(TMath::Abs(position[i]-currVal)<kMinDiff) return kFALSE;
368     if(TMath::Abs(position[i]-kResetValue)<kMinDiff) {
369       position[i] = currVal;
370       return kTRUE;
371     }
372     if(currVal>position[i]) continue;
373     tmp1 = position[i];
374     position[i] = currVal;
375     for(Int_t j=i+1; j<nEntries; j++){
376       tmp2 = position[j];
377       position[j] = tmp1;
378       tmp1 = tmp2;
379       if(tmp1==kResetValue) break;
380     }
381     return kTRUE;
382   }
383   return kFALSE;
384 }
385
386
387 //____________________________________________________________________________ 
388 void AliMUONTriggerDisplay::FillBins(TH1* inputHisto, TH2* displayHisto,
389                                      Int_t iElement1, Int_t iElement2,
390                                      Float_t x1, Float_t x2, Float_t y1, Float_t y2,
391                                      const Float_t kShiftX, const Float_t kShiftY,
392                                      EDisplayOption displayOpt)
393 {
394   //
395   /// Given the bin in inputHisto, search the corresponding bins
396   /// in display histo and fill it.
397   //
398   TString className = inputHisto->ClassName();
399   Int_t binY=0;
400   Float_t binContent=0;
401   Int_t binX = inputHisto->GetXaxis()->FindBin(iElement1);
402   if(className.Contains("2")) {
403     binY = inputHisto->GetYaxis()->FindBin(iElement2);
404     binContent = inputHisto->GetBinContent(binX, binY);
405   }
406   else binContent = inputHisto->GetBinContent(binX);
407
408   if(binContent==0) {
409     if(displayOpt==kShowZeroes) binContent = 1e-5;
410     else return;
411   }
412
413   Int_t binX1 = displayHisto->GetXaxis()->FindBin(x1 + 0.01*kShiftX);
414   Int_t binX2 = displayHisto->GetXaxis()->FindBin(x2 - 0.01*kShiftX);
415   Int_t binY1 = displayHisto->GetYaxis()->FindBin(y1 + 0.01*kShiftY);
416   Int_t binY2 = displayHisto->GetYaxis()->FindBin(y2 - 0.01*kShiftY);
417
418   if(displayOpt==kNumbered) {
419     Int_t meanBin = (binX1+binX2)/2;
420     binX1 = meanBin;
421     binX2 = meanBin;
422     
423     meanBin = (binY1+binY2)/2;
424     binY1 = meanBin;
425     binY2 = meanBin;
426   }
427
428   Float_t elementArea = 1.;
429   if(displayOpt == kNormalizeToArea) {
430     elementArea = (x2 - x1 + 2*kShiftX) * 
431       (y2 - y1 + 2*kShiftY); // In InitOrDisplayTriggerInfo: 
432                              // x2 = x_c + xHalfWidth - kShiftX
433                              // x1 = x_c - xHalfWidth + kShiftX
434                              // so x2 - x1 + 2*kShiftX returns the element width.
435
436   }
437
438   for(Int_t ibinx=binX1; ibinx<=binX2; ibinx++){
439     for(Int_t ibiny=binY1; ibiny<=binY2; ibiny++){
440       displayHisto->SetBinContent(ibinx,ibiny,binContent/elementArea);
441     }
442   }
443 }
444