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