]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONTriggerChamberEff.cxx
DP: xz CPV-EMC distance filled to TS
[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 /// \class AliMUONTriggerChamberEff
19 /// implementation of the trigger chamber efficiency determination from
20 /// data, and returns the
21 /// efficiencyCells.dat with the calculated efficiencies
22 /// Author: Diego Stocco (Torino)
23
24 #include "AliMUONTriggerChamberEff.h"
25 #include "AliMUONDigit.h"
26 #include "AliMUONConstants.h"
27 #include "AliMUONGlobalTrigger.h"
28 #include "AliMUONGeometryTransformer.h"
29 #include "AliMUONSegmentation.h"
30 #include "AliMUON.h"
31 #include "AliMUONData.h"
32 #include "AliMUONTriggerTrack.h"
33
34 #include "AliMpVSegmentation.h"
35 #include "AliMpSegmentation.h"
36 #include "AliMpPad.h"
37 #include "AliMpDEIterator.h"
38 #include "AliMpPlaneType.h"
39
40 #include "AliRunLoader.h"
41 #include "AliRun.h"
42
43 #include <Riostream.h>
44 #include <TFile.h>
45 #include <TH1F.h>
46 #include <TMath.h>
47
48 /// \cond CLASSIMP
49 ClassImp(AliMUONTriggerChamberEff)
50 /// \endcond
51
52 //_____________________________________________________________________________
53 AliMUONTriggerChamberEff::AliMUONTriggerChamberEff(const char* galiceFile, 
54                                                    Int_t firstEvent, Int_t lastEvent) 
55 : TObject(),
56   fFirstEvent(firstEvent),
57   fLastEvent(lastEvent),
58   fFirstRun(-1),
59   fLastRun(-1),
60   fRunLoader(0x0),
61   fData(0x0),
62   fReproduceTrigResponse(kFALSE),
63   fPrintInfo(kFALSE),
64   fMUON(0x0),
65   fDebugLevel(0),
66   fGaliceDir(0x0)
67 {
68 /// Standard constructor
69     SetGaliceFile(galiceFile);
70     ResetArrays();
71 }
72
73 //_____________________________________________________________________________
74 AliMUONTriggerChamberEff::AliMUONTriggerChamberEff(Int_t firstRun, Int_t lastRun,
75                                                    const char* galiceRunDir, 
76                                                    Int_t firstEvent, Int_t lastEvent) 
77 : TObject(),
78   fFirstEvent(firstEvent),
79   fLastEvent(lastEvent),
80   fFirstRun(firstRun),
81   fLastRun(lastRun),
82   fRunLoader(0x0),
83   fData(0x0),
84   fReproduceTrigResponse(kFALSE),
85   fPrintInfo(kFALSE),
86   fMUON(0x0),
87   fDebugLevel(0),
88   fGaliceDir(galiceRunDir)
89 {
90     ResetArrays();
91     delete gAlice;
92 }
93
94 //_____________________________________________________________________________
95 AliMUONTriggerChamberEff::~AliMUONTriggerChamberEff()
96 {
97 /// Destructor
98     fRunLoader->UnloadAll();
99     delete fRunLoader;
100     delete fData;
101 }
102
103 //_____________________________________________________________________________
104 void AliMUONTriggerChamberEff::SetGaliceFile(const char *galiceFile)
105 {
106     //
107     /// Opens the galice.root and loads tracks and digits.
108     //
109
110     fRunLoader = AliRunLoader::Open(galiceFile,"MUONFolder","READ");
111     if (!fRunLoader) 
112     {
113         AliError(Form("Error opening %s file \n",galiceFile));
114     }  
115     else
116     {
117         fRunLoader->LoadgAlice();
118         gAlice = fRunLoader->GetAliRun();
119         fMUON = (AliMUON*)gAlice->GetModule("MUON");
120
121         if(fLastEvent<=0 || fLastEvent>fRunLoader->GetNumberOfEvents())fLastEvent = fRunLoader->GetNumberOfEvents()-1;
122         if(fFirstEvent<0)fFirstEvent=0;
123
124
125         AliLoader* loader = fRunLoader->GetLoader("MUONLoader");
126         if ( loader )
127         {
128             fData = new AliMUONData(loader,"MUON","MUON");
129             loader->LoadTracks("READ");
130             loader->LoadDigits("READ");
131         }
132         else
133         {
134             AliError(Form("Could get MUONLoader"));
135         }
136     }
137 }
138
139 //_____________________________________________________________________________
140 void AliMUONTriggerChamberEff::CleanGalice()
141 {
142     //
143     /// Unload all loaded data
144     //
145     
146     fRunLoader->UnloadAll();
147     delete fRunLoader;
148     fRunLoader = 0;
149 }
150
151 //_____________________________________________________________________________
152 void AliMUONTriggerChamberEff::ResetArrays()
153 {
154     //
155     /// Sets the data member counters to 0.
156     //
157
158     for(Int_t ch=0; ch<fgkNchambers; ch++){
159         for(Int_t cath=0; cath<fgkNcathodes; cath++){
160             fTrigger34[ch][cath] = 0;
161             fTrigger44[cath] = 0;
162             for(Int_t slat=0; slat<fgkNslats; slat++){
163                 fInefficientSlat[ch][cath][slat] = 0;
164                 fHitPerSlat[ch][cath][slat] = 0;
165             }
166         }
167     }
168 }
169
170
171 //_____________________________________________________________________________
172 void AliMUONTriggerChamberEff::InfoDigit()
173 {
174     //
175     /// Prints information on digits (for debugging)
176     //
177
178     AliMUONDigit * mDigit=0x0;
179     Int_t firstTrigCh = AliMUONConstants::NTrackingCh();
180     // Addressing
181     Int_t nchambers = AliMUONConstants::NCh();
182     fData->SetTreeAddress("D,GLT");
183     
184     fData->GetDigits();
185     // Loop on chambers
186     for(Int_t ichamber=firstTrigCh; ichamber<nchambers; ichamber++) {
187       TClonesArray* digits = fData->Digits(ichamber);
188       digits->Sort();
189       Int_t ndigits = (Int_t)digits->GetEntriesFast();
190       for(Int_t idigit=0; idigit<ndigits; idigit++) {
191           mDigit = (AliMUONDigit*)digits->At(idigit);
192           mDigit->Print();
193       } // end digit loop
194     } // end chamber loop
195     fData->ResetDigits();
196 }
197
198
199 //_____________________________________________________________________________
200 Bool_t AliMUONTriggerChamberEff::PadMatchTrack(Float_t xPad, Float_t yPad, Float_t dpx, Float_t dpy, 
201                                                Float_t xTrackAtPad, Float_t yTrackAtPad, Int_t chamber)
202 {
203     //
204     /// Decides if the digit belongs to the trigger track.
205     //
206
207     Float_t numOfHalfWidth = 5.;
208     Bool_t match = kFALSE;
209     Float_t maxDistX = dpx;
210     if(fReproduceTrigResponse && chamber>=2) maxDistX = 3.*dpx;// Non-bending plane: check the +- 1 strip between stations
211     if(!fReproduceTrigResponse)maxDistX = numOfHalfWidth*dpx;
212     Float_t maxDistY = dpy;
213     if(fReproduceTrigResponse && chamber%2) maxDistY = 3*dpy;// bending plane: check the +- 1 strip between planes in the same station
214     if(!fReproduceTrigResponse) maxDistY = numOfHalfWidth*dpy;
215     Float_t deltaX = TMath::Abs(xPad-xTrackAtPad);
216     Float_t deltaY = TMath::Abs(yPad-yTrackAtPad);
217     if(deltaX<=maxDistX && deltaY<=maxDistY)match = kTRUE;
218     return match;
219 }
220
221
222 //_____________________________________________________________________________
223 Bool_t AliMUONTriggerChamberEff::IsDiffLocalBoard(Int_t currDetElemId, Int_t iy, Int_t detElemIdP1, Int_t iyDigitP1) const
224 {
225     //
226     /// Determins if the digits belong to the same local board.
227     /// Used only if one wants to reproduce the trigger algorithm result.
228     /// (fReproduceTrigResponse = kTRUE).
229     //
230
231     Bool_t isDiff = kTRUE;
232     if(detElemIdP1<0 || iyDigitP1<0)return kFALSE;
233     Int_t currSlat = currDetElemId%100;
234     Int_t slatP1 = detElemIdP1%100;
235     Int_t currLoc = iy/16;
236     Int_t locP1 = iyDigitP1/16;
237     if(currSlat==slatP1 && currLoc==locP1)isDiff = kFALSE;
238     return isDiff;
239 }
240
241
242 //_____________________________________________________________________________
243 void AliMUONTriggerChamberEff::CalculateEfficiency(Int_t trigger44, Int_t trigger34,
244                                                    Float_t &efficiency, Float_t &error, Bool_t failuresAsInput)
245 {
246     //
247     /// Returns the efficiency.
248     //
249
250     efficiency=-9.;
251     error=0.;
252     if(trigger34>0){
253         efficiency=(Double_t)trigger44/((Double_t)trigger34);
254         if(failuresAsInput)efficiency=1.-(Double_t)trigger44/((Double_t)trigger34);
255     }
256     Double_t q = TMath::Abs(1-efficiency);
257     if(efficiency<0)error=0.0;
258     else error = TMath::Sqrt(efficiency*q/((Double_t)trigger34));
259 }
260
261
262 //_____________________________________________________________________________
263 Int_t AliMUONTriggerChamberEff::DetElemIdFromPos(Float_t x, Float_t y, Int_t chamber, Int_t cathode)
264 {
265     //
266     /// Given the (x,y) position in the chamber,
267     /// it returns the corresponding slat
268     //
269
270     Int_t resultingDetElemId = -1;
271     AliMpDEIterator it;
272     const AliMUONGeometryTransformer *kGeomTransformer = fMUON->GetGeometryTransformer();
273     AliMUONSegmentation *segmentation = fMUON->GetSegmentation();
274     for ( it.First(chamber-1); ! it.IsDone(); it.Next() ){
275         Int_t detElemId = it.CurrentDEId();
276
277         if (  segmentation->HasDE(detElemId) ){
278             const AliMpVSegmentation* seg = 
279                 AliMpSegmentation::Instance()
280                   ->GetMpSegmentation(detElemId,AliMp::GetCathodType(cathode));
281             if (seg){
282                 Float_t deltax = seg->Dimensions().X();
283                 Float_t deltay = seg->Dimensions().Y();
284                 Float_t xlocal1 =  -deltax;
285                 Float_t ylocal1 =  -deltay;
286                 Float_t xlocal2 =  +deltax;
287                 Float_t ylocal2 =  +deltay;
288                 Float_t xg01, yg01, zg1, xg02, yg02, zg2;
289                 kGeomTransformer->Local2Global(detElemId, xlocal1, ylocal1, 0, xg01, yg01, zg1);
290                 kGeomTransformer->Local2Global(detElemId, xlocal2, ylocal2, 0, xg02, yg02, zg2);
291
292                 Float_t xg1 = xg01, xg2 = xg02, yg1 = yg01, yg2 = yg02;
293
294                 if(xg01>xg02){
295                     xg1 = xg02;
296                     xg2 = xg01;
297                 }
298                 if(yg01>yg02){
299                     yg1 = yg02;
300                     yg2 = yg01;
301                 }
302
303                 if(x>=xg1 && x<=xg2 && y>=yg1 && y<=yg2){
304                     resultingDetElemId = detElemId;
305                     break;
306                 }
307             }
308         }
309     }
310     return resultingDetElemId;
311 }
312
313
314 //_____________________________________________________________________________
315 void AliMUONTriggerChamberEff::LocalBoardFromPos(Float_t x, Float_t y, Int_t detElemId, Int_t cathode, Int_t localBoard[4])
316 {
317     //
318     /// Given the (x,y) position in the chamber,
319     /// it returns the corresponding local board
320     //
321
322     for(Int_t loc=0; loc<4; loc++){
323         localBoard[loc]=-1;
324     }
325     const AliMUONGeometryTransformer *kGeomTransformer = fMUON->GetGeometryTransformer();
326     Float_t xl, yl, zl;
327     kGeomTransformer->Global2Local(detElemId, x, y, 0, xl, yl, zl);
328     TVector2 pos(xl,yl);
329     const AliMpVSegmentation* seg = 
330         AliMpSegmentation::Instance()
331           ->GetMpSegmentation(detElemId,AliMp::GetCathodType(cathode));
332     if (seg){
333         AliMpPad pad = seg->PadByPosition(pos,kFALSE);
334         for (Int_t loc=0; loc<pad.GetNofLocations(); loc++){
335             AliMpIntPair location = pad.GetLocation(loc);
336             localBoard[loc] = location.GetFirst();
337         }
338     }
339 }
340
341
342 //_____________________________________________________________________________
343 void AliMUONTriggerChamberEff::PrintTrigger(AliMUONGlobalTrigger *globalTrig)
344 {
345     //
346     /// Print trigger response.
347     //
348
349     printf("===================================================\n");
350     printf(" Global Trigger output\t \tLow pt\tHigh pt\n");
351
352     printf(" number of Single:\t \t"); 
353     printf("%i\t",globalTrig->SingleLpt());
354     printf("%i\t",globalTrig->SingleHpt());
355     printf("\n");
356
357     printf(" number of UnlikeSign pair:\t"); 
358     printf("%i\t",globalTrig->PairUnlikeLpt());
359     printf("%i\t",globalTrig->PairUnlikeHpt());
360     printf("\n");
361
362     printf(" number of LikeSign pair:\t");  
363     printf("%i\t",globalTrig->PairLikeLpt());
364     printf("%i\t",globalTrig->PairLikeHpt());
365     printf("\n");
366     printf("===================================================\n");
367     printf("\n");
368 }
369
370 void AliMUONTriggerChamberEff::PerformTriggerChamberEff(const char* outputDir)
371 {
372     //
373     /// Main method.
374     /// It loops over the the trigger rec. tracks in the event.
375     /// Then it search for matching digits around the track.
376     /// Finally it calculates the efficiency for each trigger board.
377     /// Files with calculated efficiency are placed in the user defined outputDir.
378     //
379
380     enum {kBending, kNonBending};
381     Int_t evtBeforePrint = 1000;
382     Float_t rad2deg = 180./TMath::Pi();
383
384     Int_t chOrder[] = {0,2,1,3};
385     Int_t station[] = {0,0,1,1};
386     Float_t zRealMatch[fgkNchambers] = {0.0};
387     Float_t correctFactor[fgkNcathodes] = {1.};
388
389     Bool_t match[fgkNchambers][fgkNcathodes] = {{kFALSE}};
390
391     TClonesArray *recTrigTracksArray = 0x0;
392     AliMUONTriggerTrack *recTrigTrack = 0x0;
393     AliMUONDigit * mDigit = 0x0;
394
395     Float_t zMeanChamber[fgkNchambers];
396     for(Int_t ch=0; ch<fgkNchambers; ch++){
397         zMeanChamber[ch] = AliMUONConstants::DefaultChamberZ(10+ch);
398     }
399
400     TClonesArray * globalTrigger = 0x0;
401     AliMUONGlobalTrigger * gloTrg = 0x0; 
402
403     Int_t partNumOfTrig[fgkNchambers][fgkNcathodes] = {{0}};
404     Int_t totNumOfTrig[fgkNchambers][fgkNcathodes] = {{0}};
405     Int_t atLeast1MuPerEv[fgkNchambers][fgkNcathodes] = {{0}};
406     Int_t digitPerTrack[fgkNcathodes] = {0};
407
408     Float_t trackIntersectCh[2][fgkNchambers]={{0.0}};
409
410     Int_t slatInPlane1[2][fgkNcathodes];
411     Int_t iyDigitInPlane1[2][fgkNcathodes];
412
413     const Int_t kMaxNumOfTracks = 10;
414     Int_t trigScheme[kMaxNumOfTracks][fgkNchambers][fgkNcathodes]={{{0}}};
415     Int_t triggeredDigits[kMaxNumOfTracks][fgkNchambers][fgkNcathodes] = {{{-1}}};
416     Int_t slatThatTriggered[kMaxNumOfTracks][fgkNchambers][fgkNcathodes]={{{-1}}};
417     Int_t boardThatTriggered[kMaxNumOfTracks][fgkNchambers][fgkNcathodes][4]={{{{-1}}}};
418     Int_t nboard[4]={-1};
419     Int_t ineffBoard[4]={-1};
420
421     const Int_t kMaxNumOfDigits = 20;
422     Int_t detElOfDigitsInData[kMaxNumOfDigits][fgkNchambers][fgkNcathodes] = {{{-1}}};
423
424     char filename[150];
425     FileStat_t fs;
426
427     if(fFirstRun<0)fFirstRun=fLastRun=-1;
428
429     for(Int_t iRun = fFirstRun; iRun <= fLastRun; iRun++){// Loop over runs
430     // open run loader and load gAlice
431     if(fFirstRun>=0){
432         cout<<"\n\nRun = "<<iRun<<endl;
433         sprintf(filename, "%s/run%i/galice.root", fGaliceDir.Data(), iRun);
434         if(gSystem->GetPathInfo(filename,fs)){
435             cout<<"Warning: "<<filename<<" not found. Skip to next one"<<endl;
436             continue;
437         }
438         cout<<"Opening file "<<filename<<endl;
439         SetGaliceFile(filename);
440     }
441
442     for (Int_t ievent=fFirstEvent; ievent<=fLastEvent; ievent++) { // event loop
443         Bool_t isClearEvent = kTRUE;
444
445         for(Int_t ch=0; ch<fgkNchambers; ch++){
446             for(Int_t cath=0; cath<fgkNcathodes; cath++){
447                 partNumOfTrig[ch][cath]=0;
448                 match[ch][cath]=kFALSE;
449                 for(Int_t itrack=0; itrack<kMaxNumOfTracks; itrack++){
450                     triggeredDigits[itrack][ch][cath]=-1;
451                     slatThatTriggered[itrack][ch][cath]=-1;
452                     for(Int_t loc=0; loc<4; loc++){
453                         boardThatTriggered[itrack][ch][cath][loc]=-1;
454                     }
455                 }
456                 for(Int_t idig=0; idig<kMaxNumOfDigits; idig++){
457                     detElOfDigitsInData[idig][ch][cath]=-1;
458                 }
459             }
460         }
461
462         fRunLoader->GetEvent(ievent);
463         if (ievent%evtBeforePrint==0) printf("\t Event = %d\n",ievent);
464
465         fData->SetTreeAddress("RL");
466         fData->GetRecTriggerTracks();
467         recTrigTracksArray = fData->RecTriggerTracks();
468         Int_t nRecTrigTracks = (Int_t) recTrigTracksArray->GetEntriesFast();
469
470         fData->SetTreeAddress("D,GLT");
471         fData->GetDigits();
472
473         const AliMUONGeometryTransformer* kGeomTransformer = fMUON->GetGeometryTransformer();
474
475         for (Int_t iRecTrigTrack=0; iRecTrigTrack<nRecTrigTracks; iRecTrigTrack++) {
476             for(Int_t cath=0; cath<fgkNcathodes; cath++){
477                 digitPerTrack[cath]=0;
478                 for(Int_t sta=0; sta<2; sta++){
479                     slatInPlane1[sta][cath] = -9999;
480                     iyDigitInPlane1[sta][cath] = -9999;
481                 }
482             }
483
484             Bool_t doubleCountTrack = kFALSE;
485
486             // reading info from tracks
487             recTrigTrack = (AliMUONTriggerTrack *)recTrigTracksArray->At(iRecTrigTrack);
488             Float_t x11 = recTrigTrack->GetX11();// x position (info from non-bending plane)
489             Float_t y11 = recTrigTrack->GetY11();// y position (info from bending plane)
490             Float_t thetaX = recTrigTrack->GetThetax();
491             Float_t thetaY = recTrigTrack->GetThetay();
492
493             if(fDebugLevel>=3)printf("\tEvent = %i, Track = %i\npos from track: (x,y) = (%f, %f), (thetaX, thetaY) = (%f, %f)\n",ievent,iRecTrigTrack,x11,y11,thetaX*rad2deg,thetaY*rad2deg);
494
495             for(Int_t ch=0; ch<fgkNchambers; ch++) {
496                 zRealMatch[ch] = zMeanChamber[ch];
497                 for(Int_t cath=0; cath<fgkNcathodes; cath++){
498                     trigScheme[iRecTrigTrack][ch][cath] = 0;
499                 }
500             }
501
502             for(Int_t ch=0; ch<fgkNchambers; ch++) { // chamber loop
503                 Int_t currCh = chOrder[ch];
504                 Int_t ichamber = 10+currCh;
505                 Int_t currStation = station[currCh];
506                 TClonesArray* digits = fData->Digits(ichamber);
507                 digits->Sort();
508                 Int_t ndigits = (Int_t)digits->GetEntriesFast();
509                 if(fDebugLevel>=2){
510                     if(fDebugLevel<3)printf("\tEvent = %i, Track = %i\n", ievent, iRecTrigTrack);
511                     printf("DigitNum: %i digits detected\n",ndigits);
512                 }
513
514                 for(Int_t cath=0; cath<fgkNcathodes; cath++){
515                     correctFactor[cath]=1.;
516                 }
517                 // calculate corrections to trigger track theta
518                 if(ch>=1)correctFactor[kNonBending] = zMeanChamber[0]/zRealMatch[0];// corrects x position
519                 if(ch>=2)correctFactor[kBending] = (zMeanChamber[2] - zMeanChamber[0]) / (zRealMatch[2] - zRealMatch[0]);// corrects y position
520
521                 // searching track intersection with chambers (first approximation)
522                 Float_t deltaZ = zMeanChamber[currCh] - zMeanChamber[0];
523                 trackIntersectCh[0][currCh] = zMeanChamber[currCh] * TMath::Tan(thetaX) * correctFactor[kNonBending];// x position (info from non-bending plane) 
524                 trackIntersectCh[1][currCh] = y11 + deltaZ * TMath::Tan(thetaY) * correctFactor[kBending];// y position (info from bending plane)
525
526                 for(Int_t idigit=0; idigit<ndigits; idigit++) { // digit loop
527                     mDigit = (AliMUONDigit*)digits->At(idigit);
528                     for(Int_t loc=0; loc<4; loc++){
529                         nboard[loc]=-1;
530                     }
531
532                     // searching loaded digit global position and dimension
533                     Int_t detElemId = mDigit->DetElemId();
534                     Int_t cathode = mDigit->Cathode();
535                     Int_t ix = mDigit->PadX();
536                     Int_t iy = mDigit->PadY();
537                     Float_t xpad, ypad, zpad;
538                     if(detElOfDigitsInData[idigit][ch][cathode]==-1)detElOfDigitsInData[idigit][ch][cathode] = detElemId;
539
540                     if(fDebugLevel>=2)printf("cathode = %i\n",cathode);
541                     const AliMpVSegmentation* seg = AliMpSegmentation::Instance()
542                       ->GetMpSegmentation(detElemId,AliMp::GetCathodType(cathode));
543
544                     AliMpPad pad = seg->PadByIndices(AliMpIntPair(ix,iy),kTRUE);
545                     for (Int_t loc=0; loc<pad.GetNofLocations(); loc++){
546                         AliMpIntPair location = pad.GetLocation(loc);
547                         nboard[loc] = location.GetFirst();
548                     }
549
550                     // get the pad position and dimensions
551                     Float_t xlocal1 = pad.Position().X();
552                     Float_t ylocal1 = pad.Position().Y();
553                     Float_t dpx = pad.Dimensions().X();
554                     Float_t dpy = pad.Dimensions().Y();
555
556                     kGeomTransformer->Local2Global(detElemId, xlocal1, ylocal1, 0, xpad, ypad, zpad);
557
558                     if(fDebugLevel>=3)printf("ch = %i\t cath = %i\tpad = (%4.1f, %4.1f, %4.1f)\tsize = (%3.1f, %3.1f)\n",currCh,cathode,xpad,ypad,zpad,dpx,dpy);
559
560                     // searching track intersection with chambers (second approximation)
561                     if(ch>=2){
562                         deltaZ = zpad - zRealMatch[0];
563                         trackIntersectCh[1][currCh] = y11 + deltaZ * TMath::Tan(thetaY) * correctFactor[kBending];// y position (info from bending plane)
564                     }
565
566                     // deciding if digit matches track
567                     Bool_t isDiffLocBoard = kFALSE;
568                     if(fReproduceTrigResponse)isDiffLocBoard = IsDiffLocalBoard(detElemId, iy, slatInPlane1[currStation][cathode], iyDigitInPlane1[currStation][cathode]);
569                     Bool_t matchPad = PadMatchTrack(xpad, ypad, dpx, dpy, trackIntersectCh[0][currCh], trackIntersectCh[1][currCh], currCh);
570
571                     if(matchPad && ch<2){
572                         slatInPlane1[currStation][cathode] = detElemId;
573                         iyDigitInPlane1[currStation][cathode] = iy;
574                         if(fDebugLevel>=3)printf("slatInPlane1[%i][%i] = %i\tiyDigitInPlane1[%i][%i] = %i\n",currStation,cathode,slatInPlane1[currStation][cathode],currStation,cathode,iyDigitInPlane1[currStation][cathode]);
575                     }
576
577                     if(isDiffLocBoard && fDebugLevel>=1)printf("\tDifferent local board\n");
578
579                     match[currCh][cathode] = (matchPad && !isDiffLocBoard);
580
581                     if(match[currCh][cathode]){
582                         digitPerTrack[cathode]++;
583                         trigScheme[iRecTrigTrack][currCh][cathode]++;
584                         triggeredDigits[iRecTrigTrack][currCh][cathode] = idigit;
585                         slatThatTriggered[iRecTrigTrack][currCh][cathode] = detElemId;
586                         for(Int_t loc=0; loc<4; loc++){
587                             boardThatTriggered[iRecTrigTrack][currCh][cathode][loc] = nboard[loc];
588                         }
589                         if(digitPerTrack[cathode]>4 && !fReproduceTrigResponse)isClearEvent = kFALSE;
590                     }
591
592                     // in case of match, store real z position of the chamber
593                     if(matchPad)zRealMatch[currCh] = zpad;
594
595                 } // end digit loop
596             } // end chamber loop
597
598             for(Int_t cath=0; cath<fgkNcathodes; cath++){
599                 if(digitPerTrack[cath]<3 && !fReproduceTrigResponse)isClearEvent = kFALSE;
600             }
601
602             if(!isClearEvent && !fReproduceTrigResponse){ 
603                 fData->ResetDigits();
604                 continue;
605             }
606
607             Int_t commonDigits = 0;
608             Int_t doubleTrack = -1;
609             for(Int_t itrack=0; itrack<iRecTrigTrack; itrack++){
610                 for(Int_t ch=0; ch<fgkNchambers; ch++){
611                     if(triggeredDigits[itrack][ch][kBending]==triggeredDigits[iRecTrigTrack][ch][kBending])commonDigits++;
612                 }
613                 if(commonDigits>=2){
614                     doubleCountTrack=kTRUE;
615                     doubleTrack = itrack;
616                     break;
617                 }
618             }
619
620             for(Int_t cath=0; cath<fgkNcathodes; cath++){
621                 if(!doubleCountTrack || fReproduceTrigResponse){
622                     Int_t is44 = 1;
623                     Bool_t goodForSlatEff=kTRUE;
624                     Bool_t goodForBoardEff=kTRUE;
625                     Int_t firstSlat=slatThatTriggered[iRecTrigTrack][0][cath]%100;
626                     if(firstSlat<0)firstSlat=slatThatTriggered[iRecTrigTrack][1][cath]%100;
627                     Int_t firstBoard=boardThatTriggered[iRecTrigTrack][0][0][0];
628                     if(firstBoard<0)firstBoard=boardThatTriggered[iRecTrigTrack][1][0][0];
629                     for(Int_t ch=0; ch<fgkNchambers; ch++){
630                         is44 *= trigScheme[iRecTrigTrack][ch][cath];
631                         Int_t currSlat=slatThatTriggered[iRecTrigTrack][ch][cath]%100;
632                         if(currSlat<0)continue;
633                         if(currSlat!=firstSlat)goodForSlatEff=kFALSE;
634                         Bool_t atLeastOneLoc=kFALSE;
635                         for(Int_t loc=0; loc<4; loc++){
636                             Int_t currBoard = boardThatTriggered[iRecTrigTrack][ch][cath][loc];
637                             if(currBoard==firstBoard){
638                                 atLeastOneLoc=kTRUE;
639                                 break;
640                             }
641                         }
642                         if(!atLeastOneLoc)goodForBoardEff=kFALSE;
643                     }
644                     if(fDebugLevel==1)printf("\tEvent = %i, Track = %i\n", ievent, iRecTrigTrack);
645                     if(is44==1){
646                         fTrigger44[cath]++;
647                         if(fDebugLevel>=1)printf("Trigger44[%i] = %i\n",cath,fTrigger44[cath]);
648                         if(goodForSlatEff){
649                             for(Int_t ch=0; ch<fgkNchambers; ch++){
650                                 for(Int_t slat=0; slat<fgkNslats; slat++){
651                                     Int_t corrDetEl = (ch+11)*100 + slat;
652                                     if(corrDetEl==slatThatTriggered[iRecTrigTrack][ch][cath]){
653                                         fHitPerSlat[ch][cath][slat]++;
654                                         if(fDebugLevel>=1)printf("Slat that triggered = %i\n",corrDetEl);
655                                         if(goodForBoardEff && firstBoard>0){
656                                             fHitPerBoard[ch][cath][firstBoard-1]++;
657                                             if(fDebugLevel>=1)printf("Board that triggered = %i\n",firstBoard);
658                                         }
659                                         else if(fDebugLevel>=1)printf("Event = %i, Track = %i: Particle crossed different boards: rejected!\n",ievent,iRecTrigTrack);
660                                     }
661                                 }
662                             }
663                         }
664                         else printf("Event = %i, Track = %i: Particle crossed different slats: rejected!\n",ievent,iRecTrigTrack);
665                     }
666                     if(digitPerTrack[cath]==3){
667                         for(Int_t ch=0; ch<fgkNchambers; ch++){
668                             if(match[ch][cath])partNumOfTrig[ch][cath]++;
669                             if(trigScheme[iRecTrigTrack][ch][cath]==0){
670                                 fTrigger34[ch][cath]++;
671                                 if(fDebugLevel>=1)printf("Trigger34[%i][%i] = %i\n",ch,cath,fTrigger34[ch][cath]);
672                                 if(!goodForSlatEff){
673                                     printf("Event %i, Track = %i: Particle crossed different slats: rejected!\n",ievent,iRecTrigTrack);
674                                     continue;
675                                 }
676                                 Int_t ineffSlat = DetElemIdFromPos(trackIntersectCh[0][ch], trackIntersectCh[1][ch], 11+ch, cath);
677                                 if(fDebugLevel>=1)printf("Slat non efficient = %i\n",ineffSlat);
678                                 if(ineffSlat>0){
679                                     Int_t slatInCh = ineffSlat%100;
680                                     fInefficientSlat[ch][cath][slatInCh]++;
681                                     for(Int_t idig=0; idig<kMaxNumOfDigits; idig++){
682                                         if(ineffSlat==detElOfDigitsInData[idig][ch][cath])cout<<"Warning: "<<ineffSlat<<" is not inefficient!!!"<<endl;
683                                     }
684                                     LocalBoardFromPos(trackIntersectCh[0][ch], trackIntersectCh[1][ch], ineffSlat, cath, ineffBoard);
685                                     Int_t boardNonEff=-1;
686                                     for(Int_t loc=0; loc<4; loc++){
687                                         if(ineffBoard[loc]==firstBoard){
688                                             boardNonEff=ineffBoard[loc];
689                                             break;
690                                         }
691                                     }
692                                     if(fDebugLevel>=1)printf("Board non efficient = %i\n",boardNonEff);
693                                     if(boardNonEff>0)fInefficientBoard[ch][cath][boardNonEff-1]++;
694                                     else if(fDebugLevel>=1){
695                                         printf("Inefficient board should be %i.\tBoards found:\n", firstBoard);
696                                         for(Int_t loc=0; loc<4; loc++){
697                                             printf("%i\t",ineffBoard[loc]);
698                                         }
699                                         printf("\n");
700                                     }
701                                     
702                                 }
703                             }
704                         }
705                     }
706                 }
707                 else if(doubleCountTrack){
708                     if(fDebugLevel<=1)printf("\n\tEvent = %i, Track = %i: ", ievent,iRecTrigTrack);
709                     printf("Double Count Track: %i similar to %i. Track rejected!\n",iRecTrigTrack, doubleTrack);
710                 }
711             }
712         }// end trigger tracks loop
713         if(nRecTrigTracks<=0){ 
714             fData->ResetDigits();
715             continue;
716         }
717         for(Int_t ch=0; ch<fgkNchambers; ch++){
718             for(Int_t cath=0; cath<fgkNcathodes; cath++){
719                 totNumOfTrig[ch][cath] += partNumOfTrig[ch][cath];
720                 if(partNumOfTrig[ch][cath]>0)atLeast1MuPerEv[ch][cath]++;
721             }
722         }
723
724         if(fPrintInfo){
725             //Global trigger
726             globalTrigger = fData->GlobalTrigger();
727             Int_t nglobals = (Int_t) globalTrigger->GetEntriesFast(); // should be 1
728
729             for (Int_t iglobal=0; iglobal<nglobals; iglobal++) { // Global Trigger
730                 gloTrg = (AliMUONGlobalTrigger*)globalTrigger->At(iglobal);
731             }
732             PrintTrigger(gloTrg);
733             InfoDigit();
734             cout<<"\n"<<endl;
735         }
736
737         fData->ResetDigits();
738     }// end event loop
739     if(fFirstRun>=0)CleanGalice();
740     } //end loop over run
741     
742     // Write output data
743     WriteEfficiencyMap(outputDir);
744
745     WriteOutput(outputDir, totNumOfTrig, atLeast1MuPerEv);
746 }
747
748 //_____________________________________________________________________________
749 void AliMUONTriggerChamberEff::WriteOutput(const char* outputDir, Int_t totNumOfTrig[4][2], Int_t atLeast1MuPerEv[4][2])
750 {
751     //
752     /// Writes information on calculated efficiency.
753     /// It writes: triggerChamberEff.root file containing efficiency histograms.
754     ///
755     /// In addition a text file triggerChamberEff.out is created,
756     /// with further informations on efficiencies.
757     //
758
759     char *cathodeName[fgkNcathodes]={"Bending plane", "Non-Bending plane"};
760     char *cathCode[fgkNcathodes] = {"bendPlane", "nonBendPlane"};
761
762     char outFileName[100];
763     sprintf(outFileName, "%s/triggerChamberEff.out",outputDir);
764     FILE *outfile = fopen(outFileName, "w");
765     for(Int_t cath=0; cath<fgkNcathodes; cath++){
766         fprintf(outfile,"%s:\n",cathodeName[cath]);
767         for(Int_t ch=0; ch<fgkNchambers; ch++){
768             fprintf(outfile,"Total number of muon triggers chamber 1%i = %i\n",ch+1,totNumOfTrig[ch][cath]);
769         }
770         fprintf(outfile,"\n");
771     }
772     fprintf(outfile,"\n");
773     for(Int_t cath=0; cath<fgkNcathodes; cath++){
774         fprintf(outfile,"%s:\n",cathodeName[cath]);
775         for(Int_t ch=0; ch<fgkNchambers; ch++){
776             fprintf(outfile,"At least 1 muon triggered chamber 1%i = %i\n",ch+1, atLeast1MuPerEv[ch][cath]);
777         }
778         fprintf(outfile,"\n");
779     }
780     fprintf(outfile,"\n\n");
781     for(Int_t cath=0; cath<fgkNcathodes; cath++){
782         fprintf(outfile,"%s:\n",cathodeName[cath]);
783         fprintf(outfile,"Number of triggers where all chambers counted = %i\n",fTrigger44[cath]);
784         fprintf(outfile,"\n");
785     }
786     fprintf(outfile,"\n");
787     for(Int_t cath=0; cath<fgkNcathodes; cath++){
788         fprintf(outfile,"%s:\n",cathodeName[cath]);
789         for(Int_t ch=0; ch<fgkNchambers; ch++){
790             fprintf(outfile,"Number of triggers where chamber 1%i did not count = %i\n",ch+1,fTrigger34[ch][cath]);
791         }
792         fprintf(outfile,"\n");
793     }
794
795     fprintf(outfile,"\n");
796     for(Int_t cath=0; cath<fgkNcathodes; cath++){
797         fprintf(outfile,"%s:\n",cathodeName[cath]);
798         for(Int_t ch=0; ch<fgkNchambers; ch++){
799             Int_t sumIneff = 0, sumHits = 0;
800             fprintf(outfile,"\n Chamber %1i\n", ch+1);
801             for(Int_t slat=0; slat<fgkNslats; slat++){
802                 fprintf(outfile,"Number of triggers where slat %2i - did not count = %5i - was hit (hit%sCh%iSlat%i) = %5i\n",slat,fInefficientSlat[ch][cath][slat],cathCode[cath],11+ch,slat,fHitPerSlat[ch][cath][slat]);
803                 sumIneff += fInefficientSlat[ch][cath][slat];
804                 sumHits += fHitPerSlat[ch][cath][slat];
805             }
806             fprintf(outfile,"Number of triggers where chamber %1i - did not count = %5i - was hit (hit%sCh%i) = %5i\n",ch+1,sumIneff,cathCode[cath],11+ch,sumHits);
807         }
808         fprintf(outfile,"\n");
809     }
810     fclose(outfile);
811
812     sprintf(outFileName, "%s/triggerChamberEff.root",outputDir);
813     TFile *outputHistoFile = new TFile(outFileName,"RECREATE");
814     TDirectory *dir = gDirectory;
815
816     enum {kSlatIn11, kSlatIn12, kSlatIn13, kSlatIn14, kChamberEff};
817     char *yAxisTitle = "trigger efficiency (a.u.)";
818     char *xAxisTitle = "chamber";
819
820     TH1F *histo[fgkNcathodes][fgkNchambers+1];
821     TH1F *histoBoard[fgkNcathodes][fgkNchambers];
822
823     char histoName[30];
824     char histoTitle[90];
825
826     for(Int_t cath=0; cath<fgkNcathodes; cath++){
827         for(Int_t ch=0; ch<fgkNchambers+1; ch++){
828             if(ch==kChamberEff){
829                 sprintf(histoName, "%sChamberEff", cathCode[cath]);
830                 sprintf(histoTitle, "Chamber efficiency %s", cathCode[cath]);
831                 histo[cath][ch] = new TH1F(histoName, histoTitle, fgkNchambers, 11-0.5, 15-0.5);
832                 histo[cath][ch]->SetXTitle(xAxisTitle);
833                 histo[cath][ch]->SetYTitle(yAxisTitle);
834                 histo[cath][ch]->GetXaxis()->SetNdivisions(fgkNchambers);
835             }
836             else {
837                 sprintf(histoName, "%sSlatEffChamber%i", cathCode[cath], 11+ch);
838                 sprintf(histoTitle, "Chamber %i: slat efficiency %s", 11+ch, cathCode[cath]);
839                 histo[cath][ch] = new TH1F(histoName, histoTitle, fgkNslats, 0-0.5, fgkNslats-0.5);
840                 histo[cath][ch]->SetXTitle("slat");
841                 histo[cath][ch]->SetYTitle(yAxisTitle);
842                 histo[cath][ch]->GetXaxis()->SetNdivisions(fgkNslats);
843                 
844                 sprintf(histoName, "%sBoardEffChamber%i", cathCode[cath], 11+ch);
845                 sprintf(histoTitle, "Chamber %i: board efficiency %s", 11+ch, cathCode[cath]);
846                 histoBoard[cath][ch] = new TH1F(histoName, histoTitle, fgkNboards, 1-0.5, fgkNboards+1.-0.5);
847                 histoBoard[cath][ch]->SetXTitle("boards");
848                 histoBoard[cath][ch]->SetYTitle(yAxisTitle);
849                 histoBoard[cath][ch]->GetXaxis()->SetNdivisions(fgkNboards);
850             }
851         }
852     }
853
854     Float_t efficiency, efficiencyError;
855
856     for(Int_t cath=0; cath<fgkNcathodes; cath++){
857         for(Int_t ch=0; ch<fgkNchambers; ch++){
858             for(Int_t slat=0; slat<fgkNslats; slat++){
859                 CalculateEfficiency(fHitPerSlat[ch][cath][slat], fHitPerSlat[ch][cath][slat]+fInefficientSlat[ch][cath][slat], efficiency, efficiencyError, kFALSE);
860                 histo[cath][ch]->SetBinContent(slat+1, efficiency);
861                 histo[cath][ch]->SetBinError(slat+1, efficiencyError);
862             }
863             CalculateEfficiency(fTrigger44[cath], fTrigger34[ch][cath]+fTrigger44[cath], efficiency, efficiencyError, kFALSE);
864             histo[cath][kChamberEff]->SetBinContent(ch+1, efficiency);
865             histo[cath][kChamberEff]->SetBinError(ch+1, efficiencyError);
866
867             for(Int_t board=0; board<fgkNboards; board++){
868                 CalculateEfficiency(fHitPerBoard[ch][cath][board], fHitPerBoard[ch][cath][board]+fInefficientBoard[ch][cath][board], efficiency, efficiencyError, kFALSE);
869                 histoBoard[cath][ch]->SetBinContent(board+1, efficiency);
870                 histoBoard[cath][ch]->SetBinError(board+1, efficiencyError);
871             }
872         }
873     }
874
875 // write all histos
876     outputHistoFile->cd();
877     dir->GetList()->Write();
878     outputHistoFile->Close();
879 }
880
881
882 //_____________________________________________________________________________
883 void AliMUONTriggerChamberEff::WriteEfficiencyMap(const char* outputDir)
884 {
885     //
886     /// Writes the calculated efficiency in the text file efficiencyCells.dat
887     ///
888     /// The file can be further put in $ALICE_ROOT/MUON/data
889     /// and used to run simulations with measured trigger chamber efficiencies.
890     //
891
892     Int_t effOutWidth=4;
893
894     Float_t efficiency, efficiencyError;
895
896     Int_t aCapo[] = {16, 38, 60, 76, 92, 108, 117, 133, 155, 177, 193, 209, 225, 234};
897
898     char filename[70];
899     sprintf(filename, "%s/efficiencyCells.dat", outputDir);
900     ofstream outFile(filename);
901     outFile << "localBoards" << endl;
902     for(Int_t ch=0; ch<fgkNchambers; ch++){
903         //Print information
904         outFile << "\n\ndetElemId:\t" << 11+ch;
905         outFile << "00";
906         for(Int_t cath=0; cath<fgkNcathodes; cath++){
907             outFile << "\n cathode:\t" << cath << endl;
908             Int_t currLine=0;
909             for(Int_t board=0; board<fgkNboards; board++){
910
911                 if(board==aCapo[currLine]){
912                     outFile << endl;
913                     currLine++;
914                 }
915                 CalculateEfficiency(fHitPerBoard[ch][cath][board], fHitPerBoard[ch][cath][board]+fInefficientBoard[ch][cath][board], efficiency, efficiencyError, kFALSE);
916                 outFile << " " << setw(effOutWidth) << efficiency;
917             }// loop on boards
918             outFile << endl;
919         }// loop on cathodes
920     }// loop on chambers    
921 }
922