]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONQADataMakerRec.cxx
In AliMUONQADataMakerRec:
[u/mrichter/AliRoot.git] / MUON / AliMUONQADataMakerRec.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 // --- MUON header files ---
17 #include "AliMUONQADataMakerRec.h"
18
19 #include "AliMUONCluster.h"  
20 #include "AliMUONRawStreamTracker.h"
21 #include "AliMUONRawStreamTrigger.h"
22 #include "AliMUONConstants.h"  
23 #include "AliMUONVClusterStore.h"
24 #include "AliMUONVCluster.h"
25
26 #include "AliMUONDigitMaker.h"
27 #include "AliMUONVDigitStore.h"
28 #include "AliMUONVTriggerStore.h"
29 #include "AliMUONVDigit.h"
30 #include "AliMUONLocalTrigger.h"
31
32 #include "AliMUONDDLTrigger.h"
33 #include "AliMUONRegHeader.h"
34 #include "AliMUONDarcHeader.h"
35 #include "AliMUONLocalStruct.h"
36
37 #include "AliMUONGeometryTransformer.h"
38
39 #include "AliMpDDLStore.h"
40 #include "AliMpVSegmentation.h"
41 #include "AliMpSegmentation.h"
42 #include "AliMpConstants.h"
43 #include "AliMpPad.h"
44 #include "AliMpBusPatch.h"
45 #include "AliMpTriggerCrate.h"
46 #include "AliMpLocalBoard.h"
47 #include "AliMpCDB.h"
48
49 // --- AliRoot header files ---
50 #include "AliESDEvent.h"
51 #include "AliESDMuonTrack.h"
52 #include "AliESDMuonCluster.h"
53 #include "AliLog.h"
54 #include "AliRawReader.h"
55 #include "AliQAChecker.h"
56
57 // --- ROOT system ---
58 #include <TClonesArray.h>
59 #include <TFile.h> 
60 #include <TH1F.h> 
61 #include <TH1I.h> 
62 #include <TH2F.h>
63 #include <TH3F.h> 
64 #include <TLorentzVector.h>
65 #include <Riostream.h>
66
67 //-----------------------------------------------------------------------------
68 /// \class AliMUONQADataMakerRec
69 ///
70 /// MUON base class for quality assurance data (histo) maker
71 ///
72 /// \author C. Finck
73
74 /// \cond CLASSIMP
75 ClassImp(AliMUONQADataMakerRec)
76 /// \endcond
77            
78 //____________________________________________________________________________ 
79 AliMUONQADataMakerRec::AliMUONQADataMakerRec() : 
80     AliQADataMakerRec(AliQA::GetDetName(AliQA::kMUON), "MUON Quality Assurance Data Maker"),
81     fIsInitRaws(kFALSE),
82     fIsInitRecPoints(kFALSE),
83     fIsInitESDs(kFALSE),
84     fDigitStore(0x0),
85     fTriggerStore(0x0),
86     fDigitMaker(0x0)
87 {
88     /// ctor
89   fDigitStore = AliMUONVDigitStore::Create("AliMUONDigitStoreV1");
90   fDigitMaker = new AliMUONDigitMaker(kTRUE,kFALSE);
91 }
92
93 //____________________________________________________________________________ 
94 AliMUONQADataMakerRec::AliMUONQADataMakerRec(const AliMUONQADataMakerRec& qadm) :
95     AliQADataMakerRec(qadm),
96     fIsInitRaws(kFALSE),
97     fIsInitRecPoints(kFALSE),
98     fIsInitESDs(kFALSE),
99     fDigitStore(0x0),
100     fTriggerStore(0x0),
101     fDigitMaker(0x0)
102 {
103     ///copy ctor 
104     SetName((const char*)qadm.GetName()) ; 
105     SetTitle((const char*)qadm.GetTitle()); 
106
107     // Do not copy the digit store and digit maker, but create its own ones
108     fDigitStore = AliMUONVDigitStore::Create("AliMUONDigitStoreV1");
109     fDigitMaker = new AliMUONDigitMaker(kTRUE,kFALSE);
110 }
111
112 //__________________________________________________________________
113 AliMUONQADataMakerRec& AliMUONQADataMakerRec::operator = (const AliMUONQADataMakerRec& qadm )
114 {
115   /// Assignment operator
116
117   // check assignment to self
118   if (this == &qadm) return *this;
119
120   this->~AliMUONQADataMakerRec();
121   new(this) AliMUONQADataMakerRec(qadm);
122   return *this;
123 }
124
125 //__________________________________________________________________
126 AliMUONQADataMakerRec::~AliMUONQADataMakerRec()
127 {
128     /// dtor
129     delete fDigitStore;
130     delete fTriggerStore;
131     delete fDigitMaker;
132 }
133
134 //____________________________________________________________________________ 
135 void AliMUONQADataMakerRec::EndOfDetectorCycle(AliQA::TASKINDEX_t task, TObjArray* list)
136 {
137     ///Detector specific actions at end of cycle
138
139     // Display trigger histos in a more user friendly way
140     DisplayTriggerInfo(task);
141
142     // do the QA checking
143     AliQAChecker::Instance()->Run(AliQA::kMUON, task, list) ;
144 }
145
146 //____________________________________________________________________________ 
147 void AliMUONQADataMakerRec::InitRaws()
148 {
149     /// create Raws histograms in Raws subdir
150     TH1I* h0 = new TH1I("hRawBusPatch", "buspatch distribution",  1932, 1, 1932); 
151     Add2RawsList(h0, kRawBusPatch);
152
153     TH1I* h1 = new TH1I("hRawCharge", "Charge distribution in rawdata", 4096, 0, 4095); 
154     Add2RawsList(h1, kRawCharge);
155                 
156     for (Int_t iDDL = 0; iDDL < 20; ++iDDL) 
157     {
158       TH1F* h2 = new TH1F(Form("%s%d", "hRawBusPatchDDL", iDDL), Form("%s %d","RAW Buspatch distribution for DDL", iDDL), 50, 0, 49); 
159       Add2RawsList(h2, kRawBuspatchDDL+iDDL);
160     }
161
162     TH3F* h3 = new TH3F("hTriggerScalersBendPlane", "Trigger scalers in bending plane",
163                         4, 10.5, 14.5,
164                         234, 0.5, 234.5,
165                         16, -0.5, 15.5);
166     h3->GetXaxis()->SetTitle("Chamber");
167     h3->GetYaxis()->SetTitle("Board");
168     h3->GetZaxis()->SetTitle("Strip");
169     Add2RawsList(h3, kTriggerScalersBP);
170
171     TH3F* h4 = new TH3F("hTriggerScalersNonBendPlane", "Trigger scalers in non-bending plane",
172                         4, 10.5, 14.5,
173                         234, 0.5, 234.5,
174                         16, -0.5, 15.5);
175     h4->GetXaxis()->SetTitle("Chamber");
176     h4->GetYaxis()->SetTitle("Board");
177     h4->GetZaxis()->SetTitle("Strip");
178     Add2RawsList(h4, kTriggerScalersNBP);
179
180     fIsInitRaws = InitDisplayHistos(AliQA::kRAWS);
181 }
182
183 //____________________________________________________________________________ 
184 void AliMUONQADataMakerRec::InitRecPoints()
185 {
186     /// create Reconstructed Points histograms in RecPoints subdir
187     TH3F* h0 = new TH3F("hTriggerDigitsBendPlane", "Trigger digits in bending plane",
188                         4, 10.5, 14.5,
189                         234, 0.5, 234.5,
190                         16, -0.5, 15.5);
191     h0->GetXaxis()->SetTitle("Chamber");
192     h0->GetYaxis()->SetTitle("Board");
193     h0->GetZaxis()->SetTitle("Strip");
194     Add2RecPointsList(h0, kTriggerDigitsBendPlane);
195
196     TH3F* h1 = new TH3F("hTriggerDigitsNonBendPlane", "Trigger digits in non-bending plane",
197                         4, 10.5, 14.5,
198                         234, 0.5, 234.5,
199                         16, -0.5, 15.5);
200     h1->GetXaxis()->SetTitle("Chamber");
201     h1->GetYaxis()->SetTitle("Board");
202     h1->GetZaxis()->SetTitle("Strip");
203     Add2RecPointsList(h1, kTriggerDigitsNonBendPlane);
204
205     TH1F* h2 = new TH1F("hTriggeredBoards", "Triggered boards", 234, 0.5, 234.5);
206     Add2RecPointsList(h2, kTriggeredBoards);
207
208     fIsInitRecPoints = InitDisplayHistos(AliQA::kRECPOINTS);
209 }
210
211
212 //____________________________________________________________________________ 
213 void AliMUONQADataMakerRec::InitESDs()
214 {
215     ///create ESDs histograms in ESDs subdir
216   TH1F* h0 = new TH1F("hESDnTracks", "ESDs track number distribution", 30, 0., 30.);  
217   Add2ESDsList(h0, kESDnTracks);
218
219   TH1F* h1 = new TH1F("hESDMomentum", "ESDs P distribution", 300, 0., 300) ; 
220   Add2ESDsList(h1, kESDMomentum);
221
222   TH1F* h2 = new TH1F("hESDPt", "ESDs Pt distribution", 200, 0., 50) ; 
223   Add2ESDsList(h2, kESDPt);
224
225   TH1F* h3 = new TH1F("hESDRapidity", "ESDs rapidity distribution", 200, -4.5,-2.) ; 
226   Add2ESDsList(h3, kESDRapidity);
227
228   for (Int_t i = 0; i < AliMUONConstants::NTrackingCh(); ++i) 
229   {
230     TH2F* h4 = new TH2F(Form("%s%d", "hESDClusterHitMap", i), 
231                      Form("%s %d", "ESD Clusters hit distribution for chamber", i),
232                      100, -1*AliMUONConstants::Rmax(i/2), AliMUONConstants::Rmax(i/2),
233                      100, -1*AliMUONConstants::Rmax(i/2), AliMUONConstants::Rmax(i/2)); 
234     Add2ESDsList(h4, kESDClusterHitMap+i);
235   }
236   
237   fIsInitESDs =  kTRUE;
238 }
239
240 //____________________________________________________________________________
241 void AliMUONQADataMakerRec::MakeRaws(AliRawReader* rawReader)
242 {
243     /// make QA for rawdata
244
245     if ( ! fIsInitRaws ) {
246       AliWarningStream() 
247         << "Skipping function due to a failure in Init" << endl;
248       return;
249     }    
250
251     Int_t busPatchId;
252     UShort_t manuId;  
253     UChar_t channelId;
254     UShort_t charge;
255
256     rawReader->Reset();
257     AliMUONRawStreamTracker rawStreamTrack(rawReader);
258     rawStreamTrack.First();
259     while( rawStreamTrack.Next(busPatchId, manuId, channelId, charge) ) {
260   
261       GetRawsData(kRawBusPatch)->Fill(busPatchId);
262       GetRawsData(kRawCharge)->Fill(charge);
263       Int_t iDDL = rawStreamTrack.GetCurentDDL();
264       GetRawsData(kRawBuspatchDDL + iDDL)->Fill(AliMpBusPatch::GetLocalBusID(busPatchId, iDDL));
265                 
266                   
267     } // Next digit
268
269
270     // Get trigger scalers
271
272     Int_t loCircuit=0;
273     AliMpCDB::LoadDDLStore();
274
275     AliMUONRawStreamTrigger rawStreamTrig(rawReader);
276     while (rawStreamTrig.NextDDL()) 
277     {
278       // If not a scaler event, do nothing
279       Bool_t scalerEvent =  rawReader->GetDataHeader()->GetL1TriggerMessage() & 0x1;
280       if(!scalerEvent) break;
281
282       AliMUONDDLTrigger* ddlTrigger = rawStreamTrig.GetDDLTrigger();
283       AliMUONDarcHeader* darcHeader = ddlTrigger->GetDarcHeader();
284
285       Int_t nReg = darcHeader->GetRegHeaderEntries();
286     
287       for(Int_t iReg = 0; iReg < nReg ;iReg++)
288       {   //reg loop
289
290         // crate info  
291         AliMpTriggerCrate* crate = AliMpDDLStore::Instance()->
292           GetTriggerCrate(rawStreamTrig.GetDDL(), iReg);
293
294         AliMUONRegHeader* regHeader =  darcHeader->GetRegHeaderEntry(iReg);
295
296         // loop over local structures
297         Int_t nLocal = regHeader->GetLocalEntries();
298         for(Int_t iLocal = 0; iLocal < nLocal; iLocal++) 
299         {
300           AliMUONLocalStruct* localStruct = regHeader->GetLocalEntry(iLocal);
301         
302           // if card exist
303           if (!localStruct) continue;
304           
305           loCircuit = crate->GetLocalBoardId(localStruct->GetId());
306
307           if ( !loCircuit ) continue; // empty slot
308
309           AliMpLocalBoard* localBoard = AliMpDDLStore::Instance()->GetLocalBoard(loCircuit, false);
310
311           // skip copy cards
312           if( !localBoard->IsNotified()) 
313             continue;
314
315           Int_t cathode = localStruct->GetComptXY()%2;
316
317           ERaw hindex = (cathode==0) ? kTriggerScalersBP : kTriggerScalersNBP;
318
319           // loop over strips
320           for (Int_t ibitxy = 0; ibitxy < 16; ++ibitxy) {
321             if(localStruct->GetXY1(ibitxy) > 0)
322               ((TH3F*)GetRawsData(hindex))->Fill(11+0, loCircuit, ibitxy, 2*localStruct->GetXY1(ibitxy));
323             if(localStruct->GetXY2(ibitxy) > 0)
324               ((TH3F*)GetRawsData(hindex))->Fill(11+1, loCircuit, ibitxy, 2*localStruct->GetXY2(ibitxy));
325             if(localStruct->GetXY3(ibitxy) > 0)
326               ((TH3F*)GetRawsData(hindex))->Fill(11+2, loCircuit, ibitxy, 2*localStruct->GetXY3(ibitxy));
327             if(localStruct->GetXY4(ibitxy) > 0)
328               ((TH3F*)GetRawsData(hindex))->Fill(11+3, loCircuit, ibitxy, 2*localStruct->GetXY4(ibitxy));
329           } // loop on strips
330         } // iLocal
331       } // iReg
332     } // NextDDL
333 }
334
335 //____________________________________________________________________________
336 void AliMUONQADataMakerRec::MakeRecPoints(TTree* clustersTree)
337 {
338   
339     /// makes data from trigger response
340       
341     if ( ! fIsInitRecPoints ) {
342       AliWarningStream() 
343         << "Skipping function due to a failure in Init" << endl;
344       return;
345     }    
346
347     // Fired pads info
348     fDigitStore->Clear();
349
350     if (!fTriggerStore) fTriggerStore = AliMUONVTriggerStore::Create(*clustersTree);
351     fTriggerStore->Clear();
352     fTriggerStore->Connect(*clustersTree, false);
353     clustersTree->GetEvent(0);
354
355     AliMUONLocalTrigger* locTrg;
356     TIter nextLoc(fTriggerStore->CreateLocalIterator());
357
358     while ( ( locTrg = static_cast<AliMUONLocalTrigger*>(nextLoc()) ) ) 
359     {
360       if (locTrg->IsNull()) continue;
361    
362       TArrayS xyPattern[2];
363       locTrg->GetXPattern(xyPattern[0]);
364       locTrg->GetYPattern(xyPattern[1]);
365
366       Int_t nBoard = locTrg->LoCircuit();
367
368       Bool_t xTrig=locTrg->IsTrigX();
369       Bool_t yTrig=locTrg->IsTrigY();
370     
371       if (xTrig && yTrig)
372         ((TH1F*)GetRecPointsData(kTriggeredBoards))->Fill(nBoard);
373
374       fDigitMaker->TriggerDigits(nBoard, xyPattern, *fDigitStore);
375     }
376
377     TIter nextDigit(fDigitStore->CreateIterator());
378     AliMUONVDigit* mDigit;
379     while ( ( mDigit = static_cast<AliMUONVDigit*>(nextDigit()) ) )
380     {
381       Int_t detElemId = mDigit->DetElemId();
382       Int_t ch = detElemId/100;
383       Int_t localBoard = mDigit->ManuId();
384       Int_t channel = mDigit->ManuChannel();
385       Int_t cathode = mDigit->Cathode();
386       ERecPoints hindex 
387         = ( cathode == 0 ) ? kTriggerDigitsBendPlane : kTriggerDigitsNonBendPlane;
388       
389       ((TH3F*)GetRecPointsData(hindex))->Fill(ch, localBoard, channel);
390     }
391 }
392
393 //____________________________________________________________________________
394 void AliMUONQADataMakerRec::MakeESDs(AliESDEvent* esd)
395 {
396     /// make QA data from ESDs
397
398     if ( ! fIsInitESDs ) {
399       AliWarningStream() 
400         << "Skipping function due to a failure in Init" << endl;
401       return;
402     }    
403
404     TLorentzVector v1;
405
406     Int_t nTracks = (Int_t)esd->GetNumberOfMuonTracks() ; 
407     GetESDsData(0)->Fill(nTracks);
408
409     for (Int_t iTrack = 0; iTrack < nTracks; ++iTrack) {
410
411       AliESDMuonTrack* muonTrack = esd->GetMuonTrack(iTrack);
412       muonTrack->LorentzP(v1);
413
414       GetESDsData(1)->Fill(v1.P());
415       GetESDsData(2)->Fill(v1.Pt());
416       GetESDsData(3)->Fill(v1.Rapidity());
417
418       TClonesArray clusters =  muonTrack->GetClusters();
419
420       for (Int_t iCluster = 0; iCluster <clusters.GetEntriesFast(); ++iCluster) {
421         AliESDMuonCluster* cluster = (AliESDMuonCluster*)clusters.At(iCluster);
422         GetESDsData(kESDClusterHitMap+cluster->GetChamberId())
423           ->Fill(cluster->GetX(), cluster->GetY());
424       }
425     }
426 }
427
428 //____________________________________________________________________________ 
429 void AliMUONQADataMakerRec::StartOfDetectorCycle()
430 {
431     /// Detector specific actions at start of cycle
432   
433 }
434
435 //____________________________________________________________________________ 
436 void AliMUONQADataMakerRec::DisplayTriggerInfo(AliQA::TASKINDEX_t task)
437 {
438   //
439   /// Display trigger information in a user-friendly way:
440   /// from local board and strip numbers to their position on chambers
441   //
442   if(task!=AliQA::kRECPOINTS && task!=AliQA::kRAWS) return;
443
444   AliMpCDB::LoadDDLStore();
445
446   Int_t detElemId;
447   Float_t xg1, yg1, zg1, xg2, yg2, zg2, binContent;
448   Float_t xLocal1=0., yLocal1=0., xLocal2=0., yLocal2=0., xWidth=0., yWidth=0.;
449   Float_t x1Label, y1Label, x2Label, y2Label;
450   Int_t x1Int, x2Int, y1Int, y2Int;
451   Int_t binCh, binBoard, binStrip;
452
453   AliMUONGeometryTransformer transform;
454   transform.LoadGeometryData();
455
456   TH3F* histoStrips=0x0;
457   TH2F* histoDisplayStrips=0x0;
458   TH2F* histoDisplayBoards=0x0;
459   TH1F* histoBoards=0x0;
460
461   const Float_t kShift = 0.15;
462
463   for (Int_t iCath = 0; iCath < 2; ++iCath)
464   {
465
466     if(task==AliQA::kRECPOINTS){
467       ERecPoints hindex 
468         = ( iCath == 0 ) ? kTriggerDigitsBendPlane : kTriggerDigitsNonBendPlane;
469       histoStrips = (TH3F*)GetRecPointsData(hindex);
470       histoBoards = (TH1F*)GetRecPointsData(kTriggeredBoards);
471     }
472     else if(task==AliQA::kRAWS){
473       ERaw hindex 
474         = ( iCath == 0 ) ? kTriggerScalersBP : kTriggerScalersNBP;
475       histoStrips = (TH3F*)GetRawsData(hindex);
476       if(histoStrips->GetEntries()==0) return; // No scalers found
477     }
478     
479     // Load mapping
480     if ( ! AliMpSegmentation::Instance(kFALSE) ) {
481       /// Load mapping
482       if ( ! AliMpCDB::LoadDDLStore() ) {
483         AliError("Could not access mapping from OCDB !");
484         return;
485       }
486     }  
487
488     for (Int_t iChamber = 0; iChamber < 4; ++iChamber)
489     {
490       Int_t iCh = iChamber + AliMpConstants::NofTrackingChambers();
491
492       if(task==AliQA::kRECPOINTS){
493         histoDisplayStrips = (TH2F*)GetRecPointsData(kTriggerDigitsDisplay + 4*iCath + iChamber);
494         histoDisplayBoards = (TH2F*)GetRecPointsData(kTriggerBoardsDisplay);
495       }
496       else if(task==AliQA::kRAWS){
497         histoDisplayStrips = (TH2F*)GetRawsData(kTriggerScalersDisplay + 4*iCath + iChamber);
498       }
499
500       for(Int_t iBoard=1; iBoard<=234; iBoard++){
501         // get detElemId
502         detElemId = AliMpDDLStore::Instance()->GetDEfromLocalBoard(iBoard, iCh);
503
504         if (!detElemId) continue;
505
506         AliMpLocalBoard* localBoard = AliMpDDLStore::Instance()->GetLocalBoard(iBoard, false);
507
508         // skip copy cards
509         if( !localBoard->IsNotified()) 
510           continue;
511
512         const AliMpVSegmentation* seg 
513           = AliMpSegmentation::Instance()
514           ->GetMpSegmentation(detElemId, AliMp::GetCathodType(iCath));  
515         
516         // loop over strips
517         for (Int_t ibitxy = 0; ibitxy < 16; ++ibitxy) 
518         {
519           AliMpPad pad = seg->PadByLocation(AliMpIntPair(iBoard,ibitxy),kFALSE);
520                         
521           if (!pad.IsValid())
522             continue;
523
524           if(iCath==0){ // Geometry info from bending plane only
525             if(ibitxy==0) {
526               xLocal1 = pad.Position().X();
527               yLocal1 = pad.Position().Y();
528               xWidth = pad.Dimensions().X();
529               yWidth = pad.Dimensions().Y();
530             }
531             xLocal2 = pad.Position().X();
532             yLocal2 = pad.Position().Y();
533           }
534
535           Float_t dimX = pad.Dimensions().X();
536           Float_t dimY = pad.Dimensions().Y();
537
538           Float_t stripX = pad.Position().X();
539           Float_t stripY = pad.Position().Y();
540                    
541           transform.Local2Global(detElemId, stripX, stripY, 0, xg1, yg1, zg1);
542
543           x1Int = histoDisplayStrips->GetXaxis()->FindBin(xg1 - dimX + kShift);
544           y1Int = histoDisplayStrips->GetYaxis()->FindBin(yg1 - dimY + kShift);
545           x2Int = histoDisplayStrips->GetXaxis()->FindBin(xg1 + dimX - kShift);
546           y2Int = histoDisplayStrips->GetYaxis()->FindBin(yg1 + dimY - kShift);
547
548           binCh = histoStrips->GetXaxis()->FindBin(iCh+1);
549           binBoard = histoStrips->GetYaxis()->FindBin(iBoard);
550           binStrip = histoStrips->GetZaxis()->FindBin(ibitxy);
551           binContent = histoStrips->GetBinContent(binCh, binBoard, binStrip);
552
553           if(binContent==0) continue;
554
555           for(Int_t binX=x1Int; binX<=x2Int; binX++){
556             for(Int_t binY=y1Int; binY<=y2Int; binY++){       
557               histoDisplayStrips->SetBinContent(binX, binY, binContent);
558             }
559           }
560         }// ibitxy
561
562         if(task != AliQA::kRECPOINTS) continue;
563         if(iCath>0 || iChamber>0) continue; // Geometry info from bending plane only
564         transform.Local2Global(detElemId, xLocal1, yLocal1, 0, xg1, yg1, zg1);
565         transform.Local2Global(detElemId, xLocal2, yLocal2, 0, xg2, yg2, zg2);
566
567         // Per board
568         x1Label = TMath::Min(xg1,xg2) - xWidth + kShift;
569         y1Label = TMath::Min(yg1,yg2) - yWidth + kShift;
570         x2Label = TMath::Max(xg1,xg2) + xWidth - kShift;
571         y2Label = TMath::Max(yg1,yg2) + yWidth - kShift;
572
573         x1Int = histoDisplayBoards->GetXaxis()->FindBin(x1Label);
574         y1Int = histoDisplayBoards->GetYaxis()->FindBin(y1Label);
575         x2Int = histoDisplayBoards->GetXaxis()->FindBin(x2Label);
576         y2Int = histoDisplayBoards->GetYaxis()->FindBin(y2Label);
577
578         binBoard = histoBoards->GetXaxis()->FindBin(iBoard);
579         binContent = histoBoards->GetBinContent(binBoard);
580
581         if(binContent==0) continue;
582
583         for(Int_t binX=x1Int; binX<=x2Int; binX++){
584           for(Int_t binY=y1Int; binY<=y2Int; binY++){
585             histoDisplayBoards->SetBinContent(binX, binY, binContent);
586           }
587         }
588       } // iBoard
589     } // iChamber
590   } // iCath
591 }
592
593
594 //____________________________________________________________________________ 
595 Bool_t AliMUONQADataMakerRec::InitDisplayHistos(AliQA::TASKINDEX_t task)
596 {
597   //
598   /// Initialize trigger information display histograms,
599   /// using mapping and geometry
600   //
601   AliMpCDB::LoadDDLStore();
602
603   const Int_t kNumOfBoards = AliMpConstants::NofLocalBoards();
604
605   AliMUONGeometryTransformer transform;
606   transform.LoadGeometryData();
607
608   TString cathCode[2] = {"BendPlane", "NonBendPlane"};
609
610   TArrayF xLocal1[4], yLocal1[4], xLocal2[4], yLocal2[4], xWidth[4], yWidth[4];
611
612   TArrayF xAxisStrip[8];
613   TArrayF yAxisStrip[8];
614   TArrayF xAxisBoard[8];
615   TArrayF yAxisBoard[8];
616
617   TH2F* histoStrips=0x0;
618   TH2F* histoBoards=0x0;
619
620   const Float_t kResetValue=1234567.;
621    
622   for(Int_t ch=0; ch<4; ch++){
623     xLocal1[ch].Set(kNumOfBoards);
624     yLocal1[ch].Set(kNumOfBoards);
625     xLocal2[ch].Set(kNumOfBoards);
626     yLocal2[ch].Set(kNumOfBoards);
627     xWidth[ch].Set(kNumOfBoards);
628     yWidth[ch].Set(kNumOfBoards);
629   }
630
631   for(Int_t cath=0; cath<2; cath++){
632     for(Int_t ch=0; ch<4; ch++){
633       Int_t chCath = 4*cath + ch;
634       xAxisBoard[chCath].Set(60);
635       xAxisBoard[chCath].Reset(kResetValue);
636       yAxisBoard[chCath].Set(60);
637       yAxisBoard[chCath].Reset(kResetValue);
638
639       xAxisStrip[chCath].Set(700);
640       xAxisStrip[chCath].Reset(kResetValue);
641       yAxisStrip[chCath].Set(700);
642       yAxisStrip[chCath].Reset(kResetValue);
643     }
644   }
645    
646   Float_t xg1, yg1, zg1, xg2, yg2, zg2;
647
648   TString histoName, histoTitle;
649
650   const Float_t kShift = 0.;
651
652   // Load mapping
653   if ( ! AliMpSegmentation::Instance(kFALSE) ) {
654     /// Load mapping
655     if ( ! AliMpCDB::LoadDDLStore() ) {
656       AliError("Could not access mapping from OCDB !");
657       return kFALSE;
658     }
659   }  
660
661   for(Int_t iCath=0; iCath<2; iCath++){
662     for (Int_t iChamber = 0; iChamber < 4; ++iChamber) {
663       Int_t iCh = iChamber + AliMpConstants::NofTrackingChambers();
664       for(Int_t iLoc = 0; iLoc < 234; iLoc++) {  
665         Int_t iBoard = iLoc+1;
666         Int_t detElemId = AliMpDDLStore::Instance()->GetDEfromLocalBoard(iBoard, iCh);
667
668         if (!detElemId) continue;
669
670         AliMpLocalBoard* localBoard = AliMpDDLStore::Instance()->GetLocalBoard(iBoard, kFALSE);
671
672         // skip copy cards
673         if( !localBoard->IsNotified()) 
674           continue;
675
676         // get segmentation
677         const AliMpVSegmentation* seg = AliMpSegmentation::Instance()
678           ->GetMpSegmentation(detElemId,
679                               AliMp::GetCathodType(iCath));
680
681         Int_t chCath = 4*iCath + iChamber;
682         // loop over strips
683         for (Int_t ibitxy = 0; ibitxy < 16; ++ibitxy) {
684           // get pad from electronics
685           AliMpPad pad = seg->PadByLocation(AliMpIntPair(iBoard,ibitxy),kFALSE);
686
687           if (!pad.IsValid()) continue;
688
689           if(iCath==0){
690             if(ibitxy==0) {
691               xLocal1[iChamber][iLoc] = pad.Position().X();
692               yLocal1[iChamber][iLoc] = pad.Position().Y();
693               xWidth[iChamber][iLoc] = pad.Dimensions().X();
694               yWidth[iChamber][iLoc] = pad.Dimensions().Y();
695             }
696             xLocal2[iChamber][iLoc] = pad.Position().X();
697             yLocal2[iChamber][iLoc] = pad.Position().Y();
698           }
699
700           // Check fired pads
701           Float_t dimX = pad.Dimensions().X();
702           Float_t dimY = pad.Dimensions().Y();
703      
704           Float_t stripX = pad.Position().X();
705           Float_t stripY = pad.Position().Y();
706
707           transform.Local2Global(detElemId, stripX, stripY, 0, xg1, yg1, zg1);
708
709           AddSortedPoint(xg1 - dimX + kShift, xAxisStrip[chCath], kResetValue);
710           AddSortedPoint(xg1 + dimX - kShift, xAxisStrip[chCath], kResetValue);
711
712           AddSortedPoint(yg1 - dimY + kShift, yAxisStrip[chCath], kResetValue);
713           AddSortedPoint(yg1 + dimY - kShift, yAxisStrip[chCath], kResetValue);
714         } // loop on strips  
715
716         transform.Local2Global(detElemId, xLocal1[iChamber][iLoc], yLocal1[iChamber][iLoc], 0, xg1, yg1, zg1);
717         transform.Local2Global(detElemId, xLocal2[iChamber][iLoc], yLocal2[iChamber][iLoc], 0, xg2, yg2, zg2);
718
719         // Per board
720         AddSortedPoint(TMath::Min(xg1,xg2) - xWidth[iChamber][iLoc] + kShift, xAxisBoard[chCath], kResetValue);
721         AddSortedPoint(TMath::Max(xg1,xg2) + xWidth[iChamber][iLoc] - kShift, xAxisBoard[chCath], kResetValue);
722
723         AddSortedPoint(TMath::Min(yg1,yg2) - yWidth[iChamber][iLoc] + kShift, yAxisBoard[chCath], kResetValue);
724         AddSortedPoint(TMath::Max(yg1,yg2) + yWidth[iChamber][iLoc] - kShift, yAxisBoard[chCath], kResetValue);
725       } // loop on local boards 
726     } // loop on chambers
727   } // loop on cathodes
728
729   const Float_t kMinDiff = 0.1;
730
731   // Book histos
732   for(Int_t iCath=0; iCath<2; iCath++){
733     for(Int_t iChamber=0; iChamber<4; iChamber++){
734       Int_t chCath = 4*iCath + iChamber;
735       Int_t ipoint=0;
736       while(TMath::Abs(xAxisStrip[chCath][ipoint]-kResetValue)>kMinDiff) { ipoint++; }
737       xAxisStrip[chCath].Set(ipoint);
738
739       ipoint = 0;
740       while(TMath::Abs(yAxisStrip[chCath][ipoint]-kResetValue)>kMinDiff) { ipoint++; }
741       yAxisStrip[chCath].Set(ipoint);
742
743       ipoint = 0;
744       while(TMath::Abs(xAxisBoard[chCath][ipoint]-kResetValue)>kMinDiff) { ipoint++; }
745       xAxisBoard[chCath].Set(ipoint);
746
747       ipoint = 0;
748       while(TMath::Abs(yAxisBoard[chCath][ipoint]-kResetValue)>kMinDiff) { ipoint++; }
749       yAxisBoard[chCath].Set(ipoint);
750
751       if(task==AliQA::kRECPOINTS){
752         histoName = Form("hTriggerDigits%sChamber%i", cathCode[iCath].Data(), 11+iChamber);
753         histoTitle = Form("Chamber %i: Fired pads %s", 11+iChamber, cathCode[iCath].Data());
754       }
755       else if(task==AliQA::kRAWS){
756         histoName = Form("hScalers%sChamber%i", cathCode[iCath].Data(), 11+iChamber);
757         histoTitle = Form("Chamber %i: Scalers %s", 11+iChamber, cathCode[iCath].Data());
758       }
759       histoStrips = new TH2F(histoName.Data(), histoTitle.Data(), 
760                              xAxisStrip[chCath].GetSize()-1, xAxisStrip[chCath].GetArray(),
761                              yAxisStrip[chCath].GetSize()-1, yAxisStrip[chCath].GetArray());
762       histoStrips->SetXTitle("X (cm)");
763       histoStrips->SetYTitle("Y (cm)");
764
765       if(task==AliQA::kRECPOINTS){
766         Add2RecPointsList(histoStrips, kTriggerDigitsDisplay + 4*iCath + iChamber);
767       }
768       else if(task==AliQA::kRAWS){
769         Add2RawsList(histoStrips, kTriggerScalersDisplay + 4*iCath + iChamber);
770       }
771
772       if(task != AliQA::kRECPOINTS) continue;
773       if(iCath>0 || iChamber>0) continue;
774
775       histoName = "hFiredBoardsDisplay";
776       histoTitle = "Fired boards";
777       histoBoards = new TH2F(histoName.Data(), histoTitle.Data(), 
778                              xAxisBoard[chCath].GetSize()-1, xAxisBoard[chCath].GetArray(),
779                              yAxisBoard[chCath].GetSize()-1, yAxisBoard[chCath].GetArray());
780       histoBoards->SetXTitle("X (cm)");
781       histoBoards->SetYTitle("Y (cm)");
782
783       Add2RecPointsList(histoBoards, kTriggerBoardsDisplay + 4*iCath + iChamber);
784     } // loop on chamber
785   } // loop on cathode
786   
787   return kTRUE;
788 }
789
790
791 //____________________________________________________________________________ 
792 Bool_t AliMUONQADataMakerRec::AddSortedPoint(Float_t currVal, TArrayF& position, const Float_t kResetValue)
793 {
794   //
795   /// Add sorted point in array according to an increasing order.
796   /// Used to build display histograms axis.
797   //
798   Int_t nEntries = position.GetSize();
799   Float_t tmp1, tmp2;
800   const Float_t kMinDiff = 0.1;
801   for(Int_t i=0; i<nEntries; i++){
802     if(TMath::Abs(position[i]-currVal)<kMinDiff) return kFALSE;
803     if(TMath::Abs(position[i]-kResetValue)<kMinDiff) {
804       position[i] = currVal;
805       return kTRUE;
806     }
807     if(currVal>position[i]) continue;
808     tmp1 = position[i];
809     position[i] = currVal;
810     for(Int_t j=i+1; j<nEntries; j++){
811       tmp2 = position[j];
812       position[j] = tmp1;
813       tmp1 = tmp2;
814       if(tmp1==kResetValue) break;
815     }
816     return kTRUE;
817   }
818   return kFALSE;
819 }
820