]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONTriggerChamberEff.cxx
Initial version (Laurent)
[u/mrichter/AliRoot.git] / MUON / AliMUONTriggerChamberEff.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 //-----------------------------------------------------------------------------
19 /// \class AliMUONTriggerChamberEff
20 /// Implementation of the trigger chamber efficiency determination from
21 /// data, and returns the
22 /// efficiencyCells.dat with the calculated efficiencies
23 ///
24 /// \author Diego Stocco (Torino)
25 //-----------------------------------------------------------------------------
26
27 #include "AliMUONTriggerChamberEff.h"
28 #include "AliMUONVDigit.h"
29 #include "AliMUONConstants.h"
30 #include "AliMUONTriggerTrack.h"
31 #include "AliMUONDigitMaker.h"
32 #include "AliMUONLocalTrigger.h"
33 #include "AliMUONGeometryTransformer.h"
34
35 #include "AliMUONTrack.h"
36 #include "AliMUONTrackParam.h"
37 #include "AliMUONTrackExtrap.h"
38
39 #include "AliMUONDigitStoreV1.h"
40 #include "AliMUONVDigitStore.h"
41 #include "AliMUONVTriggerStore.h"
42 #include "AliMUONVTriggerTrackStore.h"
43 #include "AliMUONVTrackStore.h"
44 #include "AliMUONTriggerEfficiencyCells.h"
45
46 #include "AliMpVSegmentation.h"
47 #include "AliMpSegmentation.h"
48 #include "AliMpPad.h"
49 #include "AliMpDEIterator.h"
50 #include "AliMpPlaneType.h"
51 #include "AliMpDEManager.h"
52 #include "AliMpConstants.h"
53
54 #include "AliLog.h"
55
56 //#include "AliESDEvent.h"
57
58 #include <Riostream.h>
59 #include <TFile.h>
60 #include <TH1F.h>
61 #include <TMath.h>
62
63 #include <TSeqCollection.h>
64 #include <TTree.h>
65 #include <TROOT.h>
66
67 #include <cassert>
68
69 /// \cond CLASSIMP
70 ClassImp(AliMUONTriggerChamberEff)
71 /// \endcond
72
73 //_____________________________________________________________________________
74 AliMUONTriggerChamberEff::AliMUONTriggerChamberEff()
75 : TObject(),
76   fTransformer(0x0),
77   fDigitMaker(0x0),
78   fReproduceTrigResponse(kFALSE),
79   fPrintInfo(kFALSE),
80   fWriteOnESD(kFALSE),
81   fDebugLevel(0),
82   fkMaxDistance(99999.)
83 {
84 /// Default constructor
85
86     CheckConstants();
87     ResetArrays();
88 }
89
90
91 //_____________________________________________________________________________
92 AliMUONTriggerChamberEff::AliMUONTriggerChamberEff(const AliMUONGeometryTransformer* transformer,
93                                                    const AliMUONDigitMaker* digitMaker,
94                                                    Bool_t writeOnESD)
95 : TObject(),
96   fTransformer(transformer),
97   fDigitMaker(digitMaker),
98   fReproduceTrigResponse(kFALSE),
99   fPrintInfo(kFALSE),
100   fWriteOnESD(writeOnESD),
101   fDebugLevel(0),
102   fkMaxDistance(99999.)
103 {
104 /// Standard constructor
105
106     CheckConstants();
107     ResetArrays();
108 }
109
110
111 //_____________________________________________________________________________
112 AliMUONTriggerChamberEff::~AliMUONTriggerChamberEff()
113 {
114 /// Destructor
115     Bool_t writeOnESD=fWriteOnESD;
116     fWriteOnESD=kFALSE;
117     if(writeOnESD) SaveInESDFile();
118 }
119
120
121 //_____________________________________________________________________________
122 AliMUONTriggerChamberEff::AliMUONTriggerChamberEff(const AliMUONTriggerChamberEff& other)
123     :TObject(other),
124      fTransformer(0x0),
125      fDigitMaker(0x0),
126      fReproduceTrigResponse(other.fReproduceTrigResponse),
127      fPrintInfo(other.fPrintInfo),
128      fWriteOnESD(other.fWriteOnESD),
129      fDebugLevel(other.fDebugLevel),
130      fkMaxDistance(other.fkMaxDistance),
131      fTrigger44(other.fTrigger44),
132      fTrigger34(other.fTrigger34)
133 {
134 /// Copy constructor
135
136     for(Int_t chCath=0; chCath<fgkNplanes; chCath++){
137         fInefficientSlat[chCath] = other.fInefficientSlat[chCath];
138         fHitPerSlat[chCath] = other.fHitPerSlat[chCath];
139         fInefficientBoard[chCath] = other.fInefficientBoard[chCath];
140         fHitPerBoard[chCath] = other.fHitPerBoard[chCath];
141     }
142 }
143
144
145 //_____________________________________________________________________________
146 AliMUONTriggerChamberEff& AliMUONTriggerChamberEff::operator=(const AliMUONTriggerChamberEff& other)
147 {
148     /// Asignment operator
149     // check assignement to self
150     if (this == &other)
151         return *this;
152
153     // base class assignement
154     TObject::operator=(other);
155
156     fTransformer = 0x0;
157     fDigitMaker = 0x0;
158     fReproduceTrigResponse = other.fReproduceTrigResponse;
159     fPrintInfo = other.fPrintInfo;
160     fWriteOnESD = other.fWriteOnESD;
161     fDebugLevel = other.fDebugLevel;
162
163     fTrigger44 = other.fTrigger44;
164     fTrigger34 = other.fTrigger34;
165
166     for(Int_t chCath=0; chCath<fgkNplanes; chCath++){
167         fInefficientSlat[chCath] = other.fInefficientSlat[chCath];
168         fHitPerSlat[chCath] = other.fHitPerSlat[chCath];
169         fInefficientBoard[chCath] = other.fInefficientBoard[chCath];
170         fHitPerBoard[chCath] = other.fHitPerBoard[chCath];
171     }
172     return *this;
173 }
174
175
176 //_____________________________________________________________________________
177 void AliMUONTriggerChamberEff::ResetArrays()
178 {
179     //
180     /// Sets the data member counters to 0.
181     //
182
183     fTrigger44.Set(fgkNcathodes);
184     fTrigger34.Set(fgkNplanes);
185
186     for(Int_t chCath=0; chCath<fgkNplanes; chCath++){
187         fInefficientSlat[chCath].Set(fgkNslats);
188         fHitPerSlat[chCath].Set(fgkNslats);
189         fInefficientBoard[chCath].Set(AliMpConstants::NofLocalBoards());
190         fHitPerBoard[chCath].Set(AliMpConstants::NofLocalBoards());
191     }
192
193     fTrigger44.Reset();
194     fTrigger34.Reset();
195
196     for(Int_t chCath=0; chCath<fgkNplanes; chCath++){
197         fInefficientSlat[chCath].Reset();
198         fHitPerSlat[chCath].Reset();
199         fInefficientBoard[chCath].Reset();
200         fHitPerBoard[chCath].Reset();
201     }
202 }
203
204
205 //______________________________________________________________________________
206 Bool_t 
207 AliMUONTriggerChamberEff::TriggerDigits(const AliMUONVTriggerStore& triggerStore,
208                                         AliMUONVDigitStore& digitStore) const
209 {
210     //
211     /// make (S)Digit for trigger
212     //
213     digitStore.Clear();
214
215     AliMUONLocalTrigger* locTrg;
216     TIter next(triggerStore.CreateLocalIterator());
217   
218     while ( ( locTrg = static_cast<AliMUONLocalTrigger*>(next()) ) ) 
219     {
220         if (locTrg->IsNull()) continue;
221    
222         TArrayS xyPattern[fgkNcathodes];
223         locTrg->GetXPattern(xyPattern[0]);
224         locTrg->GetYPattern(xyPattern[1]);
225     
226         Int_t nBoard = locTrg->LoCircuit();
227         fDigitMaker->TriggerDigits(nBoard, xyPattern, digitStore);
228     }
229     return kTRUE;
230 }
231
232
233 //_____________________________________________________________________________
234 void AliMUONTriggerChamberEff::InfoDigit(AliMUONVDigitStore& digitStore)
235 {
236     //
237     /// Prints information on digits (for debugging)
238     //
239     TIter next(digitStore.CreateIterator());
240     AliMUONVDigit* mDigit=0x0;
241     
242     while ( ( mDigit = static_cast<AliMUONVDigit*>(next()) ) )
243     {
244         mDigit->Print();
245     } // end digit loop
246     printf("\n");
247 }
248
249
250 //_____________________________________________________________________________
251 Int_t AliMUONTriggerChamberEff::MatchingPad(AliMUONVDigitStore& digitStore, Int_t &detElemId,
252                                             Float_t coor[2], Bool_t isMatch[2],
253                                             TArrayI nboard[2], TArrayF &zRealMatch, Float_t y11)
254 {
255     //
256     /// Check slat and board number of digit matching track
257     //
258
259     enum {kBending, kNonBending};
260
261     Float_t minMatchDist[fgkNcathodes];
262     Int_t padsInCheckArea[fgkNcathodes];
263
264     for(Int_t cath=0; cath<fgkNcathodes; cath++){
265         isMatch[cath] = kFALSE;
266         minMatchDist[cath] = fkMaxDistance/10.;
267         padsInCheckArea[cath] = 0;
268     }
269     Int_t iChamber = AliMpDEManager::GetChamberId(detElemId);
270     Int_t ch = iChamber-10;
271     Float_t oldDeltaZ = AliMUONConstants::DefaultChamberZ(iChamber) - AliMUONConstants::DefaultChamberZ(10);
272     Float_t y = coor[1];
273     Int_t iSlat = detElemId%100;
274     Int_t trigDigitBendPlane = -1;
275     Int_t foundDetElemId = detElemId;
276     Float_t foundZmatch=999.;
277     Float_t yCoorAtPadZ=999.;
278
279     TIter next(digitStore.CreateIterator());
280     AliMUONVDigit* mDigit;
281     Int_t idigit=0;
282     
283     while ( ( mDigit = static_cast<AliMUONVDigit*>(next()) ) )
284     {
285         idigit++;
286         Int_t currDetElemId = mDigit->DetElemId();
287         Int_t currCh = AliMpDEManager::GetChamberId(currDetElemId);
288         if(currCh!=iChamber) continue;
289         Int_t currSlat = currDetElemId%100;
290         Int_t slatDiff = TMath::Abs(currSlat-iSlat);
291         if(slatDiff>1 && slatDiff<17) continue; // Check neighbour slats
292         Int_t cathode = mDigit->Cathode();
293         Int_t ix = mDigit->PadX();
294         Int_t iy = mDigit->PadY();
295         Float_t xpad, ypad, zpad;
296         const AliMpVSegmentation* seg = AliMpSegmentation::Instance()
297             ->GetMpSegmentation(currDetElemId,AliMp::GetCathodType(cathode));
298
299         AliMpPad pad = seg->PadByIndices(AliMpIntPair(ix,iy),kTRUE);
300         Float_t xlocal1 = pad.Position().X();
301         Float_t ylocal1 = pad.Position().Y();
302         Float_t dpx = pad.Dimensions().X();
303         Float_t dpy = pad.Dimensions().Y();
304         fTransformer->Local2Global(currDetElemId, xlocal1, ylocal1, 0, xpad, ypad, zpad);
305         if(fDebugLevel>2)printf("DetElemId = %i\tCathode = %i\t(x,y) Pad = (%i,%i) = (%.2f,%.2f)\tDim = (%.2f,%.2f)\tTrack = (%.2f,%.2f)\n",currDetElemId,cathode,ix,iy,xpad,ypad,dpx,dpy,coor[0],coor[1]);
306         // searching track intersection with chambers (second approximation)
307         if(ch%2==1){
308             //if(iChamber%2==1){
309             Float_t deltaZ = zpad - zRealMatch[0];
310             y = (coor[1]-y11)*deltaZ/oldDeltaZ + y11;
311             if(fDebugLevel>=3 && TMath::Abs(y-coor[1])>0.1)printf("oldDeltaZ = %7.2f   newDeltaZ = %7.2f\toldY = %7.2f   new y = %7.2f\n",oldDeltaZ,deltaZ,coor[1],y);
312         }
313         Float_t matchDist = PadMatchTrack(xpad, ypad, dpx, dpy, coor[0], y, ch);
314         if(matchDist<fkMaxDistance/2.) padsInCheckArea[cathode]++;
315         if(matchDist>minMatchDist[cathode])continue;
316         isMatch[cathode] = kTRUE;
317         minMatchDist[cathode] = matchDist;
318         foundDetElemId = currDetElemId;
319         foundZmatch=zpad;
320         yCoorAtPadZ=y;
321         if(cathode==kBending) trigDigitBendPlane = idigit;
322         for (Int_t loc=0; loc<pad.GetNofLocations(); loc++){
323             AliMpIntPair location = pad.GetLocation(loc);
324             nboard[cathode][loc] = location.GetFirst();
325         }
326         for(Int_t loc=pad.GetNofLocations(); loc<fgkNlocations; loc++){
327             nboard[cathode][loc]=-1;
328         }
329     }
330
331     for(Int_t cath=0; cath<fgkNcathodes; cath++){
332         if(padsInCheckArea[cath]>2) {
333             if(fDebugLevel>=1) printf("padsInCheckArea[%i] = %i\n",cath,padsInCheckArea[cath]);
334             return -500;
335         }
336     }
337
338     if(isMatch[kBending] || isMatch[kNonBending]){
339         detElemId = foundDetElemId;
340         zRealMatch[ch] = foundZmatch;
341         coor[1] = yCoorAtPadZ;
342         if(fDebugLevel>2){
343             Int_t whichCathode=kBending;
344             if(!isMatch[kBending])whichCathode=kNonBending;
345         }
346     }
347     return trigDigitBendPlane;
348 }
349
350 //_____________________________________________________________________________
351 Float_t AliMUONTriggerChamberEff::PadMatchTrack(Float_t xPad, Float_t yPad,
352                                                 Float_t dpx, Float_t dpy, 
353                                                 Float_t xTrackAtPad, Float_t yTrackAtPad,
354                                                 Int_t chamber)
355 {
356     //
357     /// Decides if the digit belongs to the trigger track.
358     //
359
360     Float_t maxDist = 2.;//3. // cm
361     Float_t maxDistCheckArea = 6.; // cm
362
363     Float_t matchDist = fkMaxDistance;
364
365     Float_t deltaX = TMath::Abs(xPad-xTrackAtPad)-dpx;
366     Float_t deltaY = TMath::Abs(yPad-yTrackAtPad)-dpy;
367     Float_t maxDistX = maxDist;
368     Float_t maxDistY = maxDist;
369     
370     if(fReproduceTrigResponse){
371         maxDistX = dpx;
372         maxDistY = dpy;
373         deltaX = TMath::Abs(xPad-xTrackAtPad);
374         deltaY = TMath::Abs(yPad-yTrackAtPad);
375         if(dpx<dpy && chamber>=2) maxDistX = 3.*dpx;// Non-bending plane: check the +- 1 strip between stations
376         if(dpy<dpx && chamber%2) maxDistY = 3.*dpy;// bending plane: check the +- 1 strip between planes in the same station
377     }
378
379     if(deltaX<=maxDistX && deltaY<=maxDistY) matchDist = TMath::Max(deltaX, deltaY);
380     else if(deltaX<=maxDistCheckArea && deltaY<=maxDistCheckArea) matchDist = fkMaxDistance/5.;
381     return matchDist;
382 }
383
384
385 //_____________________________________________________________________________
386 void AliMUONTriggerChamberEff::CalculateEfficiency(Int_t trigger44, Int_t trigger34,
387                                                    Float_t &efficiency, Float_t &error,
388                                                    Bool_t failuresAsInput)
389 {
390     //
391     /// Returns the efficiency.
392     //
393
394     efficiency=-9.;
395     error=0.;
396     if(trigger34>0){
397         efficiency=(Double_t)trigger44/((Double_t)trigger34);
398         if(failuresAsInput)efficiency=1.-(Double_t)trigger44/((Double_t)trigger34);
399     }
400     Double_t q = TMath::Abs(1-efficiency);
401     if(efficiency<0)error=0.0;
402     else error = TMath::Sqrt(efficiency*q/((Double_t)trigger34));
403 }
404
405
406 //_____________________________________________________________________________
407 Int_t AliMUONTriggerChamberEff::DetElemIdFromPos(Float_t x, Float_t y, 
408                                                  Int_t chamber, Int_t cathode)
409 {
410     //
411     /// Given the (x,y) position in the chamber,
412     /// it returns the corresponding slat
413     //
414
415     Int_t resultingDetElemId = -1;
416     AliMpDEIterator it;
417     Float_t minDist = 999.;
418     for ( it.First(chamber-1); ! it.IsDone(); it.Next() ){
419         Int_t detElemId = it.CurrentDEId();
420         Int_t ich = detElemId/100-10;
421         Float_t tolerance=0.2*((Float_t)ich);
422         Float_t currDist=9999.;
423
424         const AliMpVSegmentation* seg = 
425             AliMpSegmentation::Instance()
426             ->GetMpSegmentation(detElemId,AliMp::GetCathodType(cathode));
427         if (!seg) continue;
428
429         Float_t deltax = seg->Dimensions().X();
430         Float_t deltay = seg->Dimensions().Y();
431         Float_t xlocal1 =  -deltax;
432         Float_t ylocal1 =  -deltay;
433         Float_t xlocal2 =  +deltax;
434         Float_t ylocal2 =  +deltay;
435         Float_t xg01, yg01, zg1, xg02, yg02, zg2;
436         fTransformer->Local2Global(detElemId, xlocal1, ylocal1, 0, xg01, yg01, zg1);
437         fTransformer->Local2Global(detElemId, xlocal2, ylocal2, 0, xg02, yg02, zg2);
438
439         Float_t xg1 = xg01, xg2 = xg02, yg1 = yg01, yg2 = yg02;
440
441         if(xg01>xg02){
442             xg1 = xg02;
443             xg2 = xg01;
444         }
445         if(yg01>yg02){
446             yg1 = yg02;
447             yg2 = yg01;
448         }
449
450         if(x>=xg1-tolerance && x<=xg2+tolerance && y>=yg1-tolerance && y<=yg2+tolerance){ // takes into account errors in extrapolation
451             if(y<yg1) currDist = yg1-y;
452             else if(y>yg2) currDist = y-yg2;
453             if(currDist<minDist) {
454                 resultingDetElemId = detElemId;
455                 minDist=currDist;
456                 continue;
457             }
458             resultingDetElemId = detElemId;
459             break;
460         }
461     } // loop on detElemId
462     return resultingDetElemId;
463 }
464
465
466 //_____________________________________________________________________________
467 void AliMUONTriggerChamberEff::LocalBoardFromPos(Float_t x, Float_t y,
468                                                  Int_t detElemId, Int_t cathode,
469                                                  Int_t localBoard[4])
470 {
471     //
472     /// Given the (x,y) position in the chamber,
473     /// it returns the corresponding local board
474     //
475
476     for(Int_t loc=0; loc<fgkNlocations; loc++){
477         localBoard[loc]=-1;
478     }
479     Float_t xl, yl, zl;
480     fTransformer->Global2Local(detElemId, x, y, 0, xl, yl, zl);
481     TVector2 pos(xl,yl);
482     const AliMpVSegmentation* seg = 
483         AliMpSegmentation::Instance()
484           ->GetMpSegmentation(detElemId,AliMp::GetCathodType(cathode));
485     if (seg){
486         AliMpPad pad = seg->PadByPosition(pos,kFALSE);
487         for (Int_t loc=0; loc<pad.GetNofLocations(); loc++){
488             AliMpIntPair location = pad.GetLocation(loc);
489             localBoard[loc] = location.GetFirst();
490         }
491     }
492 }
493
494
495 //_____________________________________________________________________________
496 void AliMUONTriggerChamberEff::EventChamberEff(const AliMUONVTriggerStore& triggerStore,
497                                                const AliMUONVTriggerTrackStore& trigTrackStore,
498                                                const AliMUONVTrackStore& trackStore)
499 {
500     //
501     /// Main method.
502     /// It loops over the the trigger rec. tracks in the event.
503     /// Then it search for matching digits around the track.
504     /// Finally it calculates the efficiency for each trigger board.
505     /// Files with calculated efficiency are placed in the user defined outputDir.
506     //
507
508     if(!fTransformer || ! fDigitMaker) {
509         AliError(Form("AliMUONGeometryTransformer or AliMUONDigitMaker not properly initialized!!"));
510         return;
511     }
512
513     enum {kBending, kNonBending};
514     Float_t rad2deg = 180./TMath::Pi();
515
516     Int_t chOrder[fgkNchambers] = {0,2,1,3};
517
518     TArrayF zRealMatch(fgkNchambers);
519     TArrayF correctFactor(fgkNcathodes);
520
521     Bool_t match[fgkNchambers][fgkNcathodes];
522     Bool_t matchPad[fgkNcathodes];
523     for(Int_t cath=0; cath<fgkNcathodes; cath++){
524         matchPad[cath] = kFALSE;
525     }
526
527     TArrayF zMeanChamber(fgkNchambers);
528     for(Int_t ch=0; ch<fgkNchambers; ch++){
529         zMeanChamber[ch] = AliMUONConstants::DefaultChamberZ(10+ch);
530     }
531
532     TArrayI digitPerTrack(fgkNcathodes);
533
534     Float_t trackIntersectCh[fgkNchambers][fgkNcathodes];
535
536     TArrayI triggeredDigits[2];
537     for(Int_t itrack=0; itrack<2; itrack++){
538         triggeredDigits[itrack].Set(fgkNchambers);
539         triggeredDigits[itrack].Reset(-1);
540     }
541
542     TArrayI trigScheme[fgkNcathodes];
543     TArrayI slatThatTriggered[fgkNcathodes];
544     for(Int_t cath=0; cath<fgkNcathodes; cath++){
545         trigScheme[cath].Set(fgkNchambers);
546         slatThatTriggered[cath].Set(fgkNchambers);
547     }
548
549     Int_t boardThatTriggered[fgkNchambers][fgkNcathodes][fgkNlocations];
550     TArrayI nboard[fgkNcathodes];
551     for(Int_t cath=0; cath<fgkNcathodes; cath++){
552         nboard[cath].Set(fgkNlocations);
553     }
554     Int_t ineffBoard[fgkNlocations];
555     for(Int_t loc=0; loc<fgkNlocations; loc++){
556         ineffBoard[loc] = -1;
557     }
558
559     AliMUONDigitStoreV1 digitStore;   
560     TriggerDigits(triggerStore,digitStore);
561
562     AliMUONTriggerTrack *recTrigTrack = 0x0;
563
564     TIter next(trigTrackStore.CreateIterator());
565     
566     while ( ( recTrigTrack = static_cast<AliMUONTriggerTrack*>(next()) ) )
567     {
568         if(!IsCleanTrack(recTrigTrack, trackStore)) {
569             if(fDebugLevel>=1) printf("\tTrack %p (%f, %f) don't match tracker track: rejected!\n",(void *)recTrigTrack,recTrigTrack->GetX11(),recTrigTrack->GetY11());
570             continue;
571         }
572
573         digitPerTrack.Reset();
574         for(Int_t ch=0; ch<fgkNchambers; ch++){
575             zRealMatch[ch] = zMeanChamber[ch];
576             for(Int_t cath=0; cath<fgkNcathodes; cath++){
577                 match[ch][cath]=kFALSE;
578                 //slatThatTriggered[ch][cath]=-1;
579                 //trigScheme[ch][cath] = 0;
580                 for(Int_t loc=0; loc<fgkNlocations; loc++){
581                     boardThatTriggered[ch][cath][loc]=-1;
582                 }
583             }
584         }
585
586         for(Int_t cath=0; cath<fgkNcathodes; cath++){
587             slatThatTriggered[cath].Reset(-1);
588             trigScheme[cath].Reset();
589         }
590
591         Bool_t isClearEvent = kTRUE;
592         Bool_t doubleCountTrack = kFALSE;
593
594         Float_t x11 = recTrigTrack->GetX11();// x position (info from non-bending plane)
595         Float_t y11 = recTrigTrack->GetY11();// y position (info from bending plane)
596         Float_t thetaX = recTrigTrack->GetThetax();
597         Float_t thetaY = recTrigTrack->GetThetay();
598
599         if(fDebugLevel>=3) printf("\tTrack = %p\npos from track: (x,y) = (%f, %f), (thetaX, thetaY) = (%f, %f)\n",(void *)recTrigTrack,x11,y11,thetaX*rad2deg,thetaY*rad2deg);
600
601         for(Int_t ch=0; ch<fgkNchambers; ch++) { // chamber loop
602             Int_t currCh = chOrder[ch];
603             if(fDebugLevel>=2)
604                 printf("zMeanChamber[%i] = %.2f\tzRealMatch[0] = %.2f\n",currCh,zMeanChamber[currCh],zRealMatch[0]);
605
606             for(Int_t cath=0; cath<fgkNcathodes; cath++){
607                 correctFactor[cath]=1.;
608             }
609             // calculate corrections to trigger track theta
610             if(ch>=1)correctFactor[kNonBending] = zMeanChamber[0]/zRealMatch[0];// corrects x position
611             if(ch>=2)correctFactor[kBending] = (zMeanChamber[2] - zMeanChamber[0]) / (zRealMatch[2] - zRealMatch[0]);// corrects y position
612
613             // searching track intersection with chambers (first approximation)
614             Float_t deltaZ = zMeanChamber[currCh] - zMeanChamber[0];
615             trackIntersectCh[currCh][0] = zMeanChamber[currCh] * TMath::Tan(thetaX) * correctFactor[kNonBending];// x position (info from non-bending plane) 
616             trackIntersectCh[currCh][1] = y11 + deltaZ * TMath::Tan(thetaY) * correctFactor[kBending];// y position (info from bending plane)
617             Int_t detElemIdFromTrack = DetElemIdFromPos(trackIntersectCh[currCh][0], trackIntersectCh[currCh][1], 11+currCh, 0);
618             if(detElemIdFromTrack<0) {
619                 if(fDebugLevel>1) printf("Warning: trigger track outside trigger chamber\n");
620                 continue;
621             }
622                 
623             triggeredDigits[1][currCh] = MatchingPad(digitStore, detElemIdFromTrack, trackIntersectCh[currCh], matchPad, nboard, zRealMatch, y11);
624
625             // if MatchingPad = -500 => too many digits matching pad =>
626             //                       => Event not clear => Reject track
627             if(triggeredDigits[1][currCh]<-100){
628                 isClearEvent = kFALSE;
629                 if(fDebugLevel>=1) printf("Warning: track = %p (%i) matches many pads. Rejected!\n",(void *)recTrigTrack, detElemIdFromTrack);
630                 break;
631             }
632
633             // deciding if digit matches track
634             Bool_t isDiffLocBoard = kFALSE;
635             if(fReproduceTrigResponse && ch>2){
636                 for(Int_t cath=0; cath<fgkNcathodes; cath++){
637                     if(boardThatTriggered[currCh][cath][0]>=0){
638                         if(boardThatTriggered[currCh][cath][0]!=boardThatTriggered[currCh-1][cath][0]) isDiffLocBoard = kTRUE;
639                     }
640                 }
641             }
642
643             if(isDiffLocBoard && fDebugLevel>=1)printf("\tDifferent local board\n");
644
645             for(Int_t cath=0; cath<fgkNcathodes; cath++){
646                 match[currCh][cath] = (matchPad[cath] && !isDiffLocBoard);
647                 if(!match[currCh][cath]) continue;
648                 digitPerTrack[cath]++;
649                 trigScheme[cath][currCh]++;
650                 slatThatTriggered[cath][currCh] = detElemIdFromTrack;
651                 for(Int_t loc=0; loc<fgkNlocations; loc++){
652                     boardThatTriggered[currCh][cath][loc] = nboard[cath][loc];
653                 }
654             }
655         } // end chamber loop
656
657         for(Int_t cath=0; cath<fgkNcathodes; cath++){
658             if(digitPerTrack[cath]<3)isClearEvent = kFALSE;
659             if(fDebugLevel>=1 && !isClearEvent)printf("Warning: found %i digits for trigger track cathode %i.\nRejecting event\n", digitPerTrack[cath],cath);
660         }
661
662         if(!isClearEvent && !fReproduceTrigResponse) continue;
663
664         Int_t commonDigits = 0;
665         for(Int_t ch=0; ch<fgkNchambers; ch++){
666             if(triggeredDigits[1][ch]==triggeredDigits[0][ch]) commonDigits++; // Compare with previous track
667             triggeredDigits[0][ch] = triggeredDigits[1][ch]; // Store this track parameters for comparison with next one
668         }
669         if(commonDigits>=2){
670             doubleCountTrack=kTRUE;
671         }
672
673         if(!doubleCountTrack || fReproduceTrigResponse){
674             for(Int_t cath=0; cath<fgkNcathodes; cath++){
675                 Int_t is44 = 1;
676                 Bool_t goodForSlatEff = kTRUE;
677                 Bool_t goodForBoardEff = kTRUE;
678                 Int_t ineffSlat = -1;
679                 Int_t ineffDetElId = -1;
680                 Int_t firstSlat = slatThatTriggered[cath][0]%100;
681                 if(firstSlat<0) firstSlat=slatThatTriggered[cath][1]%100;
682                 Int_t firstBoard = boardThatTriggered[0][kBending][0];
683                 if(firstBoard<0) firstBoard=boardThatTriggered[1][kBending][0];
684                 for(Int_t ch=0; ch<fgkNchambers; ch++){
685                     Bool_t isCurrChIneff = kFALSE;
686                     is44 *= trigScheme[cath][ch];
687                     Int_t currSlat = slatThatTriggered[cath][ch]%100;
688                     if(currSlat<0){
689                         ineffDetElId = DetElemIdFromPos(trackIntersectCh[ch][0], trackIntersectCh[ch][1], 11+ch, cath);
690                         currSlat = ineffDetElId%100;
691                         ineffSlat = currSlat;
692                         isCurrChIneff = kTRUE;
693                     }
694                     if(currSlat!=firstSlat)goodForSlatEff=kFALSE;
695                     Bool_t atLeastOneLoc=kFALSE;
696                     if(isCurrChIneff) LocalBoardFromPos(trackIntersectCh[ch][0], trackIntersectCh[ch][1], ineffDetElId, cath, ineffBoard);
697                     for(Int_t loc=0; loc<fgkNlocations; loc++){
698                         Int_t currBoard = boardThatTriggered[ch][cath][loc];
699                         if(isCurrChIneff) currBoard = ineffBoard[loc];
700                         if(currBoard==firstBoard){
701                             atLeastOneLoc=kTRUE;
702                             break;
703                         }
704                     }
705                     if(!atLeastOneLoc)goodForBoardEff=kFALSE;
706                 } // end chamber loop
707
708                 // Trigger 4/4
709                 if(is44==1){
710                     fTrigger44[cath]++;
711                     if(fDebugLevel>=1)printf("Trigger44[%i] = %i\n",cath,fTrigger44[cath]);
712                     if(goodForSlatEff){
713                         for(Int_t ch=0; ch<fgkNchambers; ch++){
714                             Int_t chCath = fgkNchambers*cath + ch;
715                             fHitPerSlat[chCath][firstSlat]++;
716                             if(fDebugLevel>=1)printf("Slat that triggered = %i\n",slatThatTriggered[cath][ch]);
717                             if(goodForBoardEff && firstBoard>0){
718                                 fHitPerBoard[chCath][firstBoard-1]++;
719                                 if(fDebugLevel>=1)printf("Board that triggered = %i\n",firstBoard);
720                             }
721                             else if(fDebugLevel>=1) printf("Track = %p: Particle crossed different boards: rejected!\n",(void *)recTrigTrack);
722                         }
723                     }
724                     else if(fDebugLevel>=1) printf("Track = %p: Particle crossed different slats: rejected!\n",(void *)recTrigTrack);
725                 }
726
727                 // Trigger 3/4
728                 if(ineffDetElId>0){
729                     Int_t ineffCh = ineffDetElId/100-11;
730                     Int_t chCath = fgkNchambers*cath + ineffCh;
731                     fTrigger34[chCath]++;
732                     if(fDebugLevel>=1) printf("Trigger34[%i] = %i\n",chCath,fTrigger34[chCath]);
733                     if(goodForSlatEff){
734                         if(fDebugLevel>=1) printf("Slat non efficient = %i\n",ineffDetElId);
735                         fInefficientSlat[chCath][ineffSlat]++;
736
737                         if(goodForBoardEff && firstBoard>0){
738                             if(fDebugLevel>=1) printf("Board non efficient = %i\n",firstBoard);
739                             fInefficientBoard[chCath][firstBoard-1]++;
740                         }
741                         else if(fDebugLevel>=1) printf("Track = %p: Particle crossed different boards: rejected!\n",(void *)recTrigTrack);
742                     }
743                     else if(fDebugLevel>=1) printf("Track = %p: Particle crossed different slats: rejected!\n",(void *)recTrigTrack);
744                 }
745             } // end loop on cathodes
746         }
747         else if(doubleCountTrack){
748             if(fDebugLevel>=1)
749                 printf("\n\tTrack = %p: \nDouble Count Track: Track rejected!\n",(void *)recTrigTrack);
750         }
751     } // end trigger tracks loop
752
753     if(fPrintInfo) InfoDigit(digitStore);
754 }
755
756 //_____________________________________________________________________________
757 void AliMUONTriggerChamberEff::GetEfficiencyHistos(TList &countList, TList &noCountList)
758 {
759   //
760   /// Gets lists of histograms containing number of 4/4 and 3/4
761   /// for further efficiency calculations.
762   //
763
764   char *cathCode[fgkNcathodes] = {"bendPlane", "nonBendPlane"};
765
766   char *yAxisTitle = "counts";
767
768   const Int_t kNumOfBoards = AliMpConstants::NofLocalBoards();
769
770   enum {kAllChEff, kChNonEff, kNumOfHistoTypes};
771   char *histoTypeName[kNumOfHistoTypes] = {"CountInCh", "NonCountInCh"};
772   char *histoTypeTitle[kNumOfHistoTypes] = {"counted", "non counted"};
773   TH1F *histoCheckChamber[fgkNcathodes][kNumOfHistoTypes];
774   TH1F *histoCheckSlat[fgkNplanes][kNumOfHistoTypes];
775   TH1F *histoCheckBoard[fgkNplanes][kNumOfHistoTypes];
776
777   char histoName[40];
778   char histoTitle[90];
779
780   for(Int_t cath=0; cath<fgkNcathodes; cath++){
781     for(Int_t hType=0; hType<kNumOfHistoTypes; hType++){
782       sprintf(histoName, "%sChamber%s", cathCode[cath], histoTypeName[hType]);
783       sprintf(histoTitle, "%s %s", histoTypeTitle[hType], cathCode[cath]);
784       histoCheckChamber[cath][hType] = new TH1F(histoName, histoTitle, fgkNchambers, 11-0.5, 11+fgkNchambers-0.5);
785       histoCheckChamber[cath][hType]->SetXTitle("chamber");
786       histoCheckChamber[cath][hType]->SetYTitle(yAxisTitle);
787       histoCheckChamber[cath][hType]->GetXaxis()->SetNdivisions(fgkNchambers);
788     }
789     
790     for(Int_t ch=0; ch<fgkNchambers; ch++){
791       Int_t chCath = fgkNchambers*cath + ch;
792       for(Int_t hType=0; hType<kNumOfHistoTypes; hType++){
793         sprintf(histoName, "%sSlat%s%i", cathCode[cath], histoTypeName[hType], 11+ch);
794         sprintf(histoTitle, "Chamber %i: slat %s %s", 11+ch, histoTypeTitle[hType], cathCode[cath]);
795         histoCheckSlat[chCath][hType] = new TH1F(histoName, histoTitle, fgkNslats, 0-0.5, fgkNslats-0.5);
796         histoCheckSlat[chCath][hType]->SetXTitle("slat");
797         histoCheckSlat[chCath][hType]->SetYTitle(yAxisTitle);
798         histoCheckSlat[chCath][hType]->GetXaxis()->SetNdivisions(fgkNslats);
799
800         sprintf(histoName, "%sBoard%s%i", cathCode[cath], histoTypeName[hType], 11+ch);
801         sprintf(histoTitle, "Chamber %i: board %s %s", 11+ch, histoTypeTitle[hType], cathCode[cath]);
802         histoCheckBoard[chCath][hType] = new TH1F(histoName, histoTitle, kNumOfBoards, 1-0.5, kNumOfBoards+1.-0.5);
803         histoCheckBoard[chCath][hType]->SetXTitle("boards");
804         histoCheckBoard[chCath][hType]->SetYTitle(yAxisTitle);
805         histoCheckBoard[chCath][hType]->GetXaxis()->SetNdivisions(kNumOfBoards);
806       }
807     }
808   }
809
810   Int_t bin;
811
812   for(Int_t cath=0; cath<fgkNcathodes; cath++){
813     for(Int_t ch=0; ch<fgkNchambers; ch++){
814       Int_t chCath = fgkNchambers*cath + ch;
815       for(Int_t slat=0; slat<fgkNslats; slat++){
816         bin = histoCheckSlat[chCath][kAllChEff]->FindBin(slat);
817         histoCheckSlat[chCath][kAllChEff]->SetBinContent(bin, fHitPerSlat[chCath][slat]);
818         histoCheckSlat[chCath][kChNonEff]->SetBinContent(bin, fInefficientSlat[chCath][slat]);
819       }
820       bin = histoCheckChamber[cath][kAllChEff]->FindBin(11+ch);
821       histoCheckChamber[cath][kAllChEff]->SetBinContent(bin, fTrigger44[cath]);
822       histoCheckChamber[cath][kChNonEff]->SetBinContent(bin, fTrigger34[chCath]);
823
824       for(Int_t board=0; board<kNumOfBoards; board++){
825         bin = histoCheckBoard[chCath][kAllChEff]->FindBin(board+1);
826         histoCheckBoard[chCath][kAllChEff]->SetBinContent(bin, fHitPerBoard[chCath][board]);
827         histoCheckBoard[chCath][kChNonEff]->SetBinContent(bin, fInefficientBoard[chCath][board]);
828       }
829     }
830   }
831
832   for(Int_t cath=0; cath<fgkNcathodes; cath++){
833     countList.Add(histoCheckChamber[cath][kAllChEff]);
834     noCountList.Add(histoCheckChamber[cath][kChNonEff]);
835   }
836
837   for(Int_t cath=0; cath<fgkNcathodes; cath++){
838     for(Int_t ch=0; ch<fgkNchambers; ch++){
839       Int_t chCath = fgkNchambers*cath + ch;
840       countList.Add(histoCheckSlat[chCath][kAllChEff]);
841       noCountList.Add(histoCheckSlat[chCath][kChNonEff]);
842     }
843   }
844
845   for(Int_t cath=0; cath<fgkNcathodes; cath++){
846     for(Int_t ch=0; ch<fgkNchambers; ch++){
847       Int_t chCath = fgkNchambers*cath + ch;
848       countList.Add(histoCheckBoard[chCath][kAllChEff]);
849       noCountList.Add(histoCheckBoard[chCath][kChNonEff]);
850     }
851   }
852 }
853
854
855 //_____________________________________________________________________________
856 Bool_t AliMUONTriggerChamberEff::IsCleanTrack(AliMUONTriggerTrack *triggerTrack,
857                                               const AliMUONVTrackStore& trackStore)
858 {
859     //
860     /// Try to match track from tracking system with trigger track
861     //
862     const Double_t kDistSigma[3]={1,1,0.02}; // sigma of distributions (trigger-track) X,Y,slopeY
863     const Double_t kMaxChi2MatchTrigger = 16.0;
864   
865     AliMUONTrackParam trackParam; 
866
867     Double_t distTriggerTrack[3];
868     Double_t xTrack, yTrack, ySlopeTrack, chi2;
869   
870     AliMUONTrack* track;
871     TIter next(trackStore.CreateIterator());
872     
873     while ( ( track = static_cast<AliMUONTrack*>(next()) ) )
874     {
875         trackParam = *((AliMUONTrackParam*) (track->GetTrackParamAtHit()->Last()));
876         AliMUONTrackExtrap::ExtrapToZ(&trackParam, AliMUONConstants::DefaultChamberZ(10)); // extrap to 1st trigger chamber
877     
878         xTrack = trackParam.GetNonBendingCoor();
879         yTrack = trackParam.GetBendingCoor();
880         ySlopeTrack = trackParam.GetBendingSlope();
881   
882         distTriggerTrack[0] = (triggerTrack->GetX11()-xTrack)/kDistSigma[0];
883         distTriggerTrack[1] = (triggerTrack->GetY11()-yTrack)/kDistSigma[1];
884         distTriggerTrack[2] = (TMath::Tan(triggerTrack->GetThetay())-ySlopeTrack)/kDistSigma[2];
885         chi2 = 0.;
886         for (Int_t iVar = 0; iVar < 3; iVar++) chi2 += distTriggerTrack[iVar]*distTriggerTrack[iVar];
887         chi2 /= 3.; // Normalized Chi2: 3 degrees of freedom (X,Y,slopeY)
888         if (chi2 < kMaxChi2MatchTrigger) return kTRUE;
889     }
890
891     return kFALSE;
892 }
893
894
895 //_____________________________________________________________________________
896 void AliMUONTriggerChamberEff::SaveInESDFile()
897 {
898   //
899   /// Store AliMUONTriggerChamberEff in esd file
900   //
901   TList countHistoList, noCountHistoList;
902   GetEfficiencyHistos(countHistoList, noCountHistoList);
903   AliMUONTriggerEfficiencyCells *effMap = 
904     new AliMUONTriggerEfficiencyCells(&countHistoList, &noCountHistoList);
905
906   TDirectory *dir = gDirectory;
907
908   TFile *logFile = 0x0;
909   Char_t *esdFileName = "AliESDs.root";
910   TSeqCollection *list = gROOT->GetListOfFiles();
911   Bool_t reopenFile = kFALSE;
912   Int_t n = list->GetEntries();
913   for(Int_t i=0; i<n; i++) {
914     logFile = (TFile*)list->At(i);
915     if (strstr(logFile->GetName(), esdFileName)) break;
916     logFile = 0x0;
917   }
918   if(!logFile) {
919     AliWarning(Form("%s already stored on disk. Re-opening in update mode.",esdFileName));
920     logFile = new TFile(esdFileName, "update");
921     reopenFile = kTRUE;
922   }
923     
924   if(logFile){
925     TTree *esdTree = (TTree*)logFile->Get("esdTree");
926     if(esdTree){
927       if(!esdTree->GetUserInfo()->FindObject("AliMUONTriggerEfficiencyCells")){
928         AliInfo(Form("Adding AliMUONTriggerEfficiencyCells in %s",esdTree->GetName()));
929         esdTree->GetUserInfo()->Add(effMap);
930         esdTree->Write("",TObject::kOverwrite);
931       }
932     }
933     if(reopenFile){
934       logFile->Close();
935     }
936   }
937   dir->cd();
938 }
939
940
941 //_____________________________________________________________________________
942 void AliMUONTriggerChamberEff::CheckConstants() const
943 {
944 /// Check consistence of redefined constants 
945
946   assert(fgkNcathodes == AliMpConstants::NofCathodes());    
947   assert(fgkNchambers == AliMpConstants::NofTriggerChambers());    
948   assert(fgkNplanes == AliMpConstants::NofTriggerChambers() * fgkNcathodes);    
949 }