]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - MUON/AliMUONTriggerChamberEff.cxx
Intrinsic chamber efficiency calculation performed during reconstruction (Diego)
[u/mrichter/AliRoot.git] / MUON / AliMUONTriggerChamberEff.cxx
index 41b2846b40b0368a9a6be7e9d1a3e52aa1ed8eac..ed1647f0c854ffcdf60aff9aa7afb137c28424d8 100644 (file)
 /// \author Diego Stocco (Torino)
 
 #include "AliMUONTriggerChamberEff.h"
-#include "AliMUONDigit.h"
+#include "AliMUONVDigit.h"
 #include "AliMUONConstants.h"
-#include "AliMUONGlobalTrigger.h"
-#include "AliMUONGeometryTransformer.h"
-#include "AliMUONSegmentation.h"
-#include "AliMUON.h"
-#include "AliMUONData.h"
 #include "AliMUONTriggerTrack.h"
+#include "AliMUONDigitMaker.h"
+#include "AliMUONLocalTrigger.h"
+#include "AliMUONGeometryTransformer.h"
+
+#include "AliMUONTrack.h"
+#include "AliMUONTrackParam.h"
+#include "AliMUONTrackExtrap.h"
+
+#include "AliMUONDigitStoreV1.h"
+#include "AliMUONVDigitStore.h"
+#include "AliMUONVTriggerStore.h"
+#include "AliMUONVTriggerTrackStore.h"
+#include "AliMUONVTrackStore.h"
 
 #include "AliMpVSegmentation.h"
 #include "AliMpSegmentation.h"
 #include "AliMpPad.h"
 #include "AliMpDEIterator.h"
 #include "AliMpPlaneType.h"
+#include "AliMpDEManager.h"
 
-#include "AliRunLoader.h"
-#include "AliRun.h"
+#include "AliLog.h"
 
 #include <Riostream.h>
 #include <TFile.h>
 #include <TH1F.h>
 #include <TMath.h>
 
+#include <TSeqCollection.h>
+#include <TTree.h>
+#include <TROOT.h>
+
+
 /// \cond CLASSIMP
 ClassImp(AliMUONTriggerChamberEff)
 /// \endcond
 
+
 //_____________________________________________________________________________
-AliMUONTriggerChamberEff::AliMUONTriggerChamberEff(const char* galiceFile, 
-                                                  Int_t firstEvent, Int_t lastEvent) 
+AliMUONTriggerChamberEff::AliMUONTriggerChamberEff()
 : TObject(),
-  fFirstEvent(firstEvent),
-  fLastEvent(lastEvent),
-  fFirstRun(-1),
-  fLastRun(-1),
-  fRunLoader(0x0),
-  fData(0x0),
+  fTransformer(0x0),
+  fDigitMaker(0x0),
   fReproduceTrigResponse(kFALSE),
   fPrintInfo(kFALSE),
-  fMUON(0x0),
+  fWriteOnESD(kFALSE),
   fDebugLevel(0),
-  fGaliceDir(0x0)
+  fkMaxDistance(99999.)
 {
 /// Standard constructor
-    SetGaliceFile(galiceFile);
     ResetArrays();
 }
 
+
 //_____________________________________________________________________________
-AliMUONTriggerChamberEff::AliMUONTriggerChamberEff(Int_t firstRun, Int_t lastRun,
-                                                  const char* galiceRunDir, 
-                                                  Int_t firstEvent, Int_t lastEvent) 
+AliMUONTriggerChamberEff::AliMUONTriggerChamberEff(const AliMUONGeometryTransformer* transformer,
+                                                  const AliMUONDigitMaker* digitMaker,
+                                                  Bool_t writeOnESD)
 : TObject(),
-  fFirstEvent(firstEvent),
-  fLastEvent(lastEvent),
-  fFirstRun(firstRun),
-  fLastRun(lastRun),
-  fRunLoader(0x0),
-  fData(0x0),
+  fTransformer(transformer),
+  fDigitMaker(digitMaker),
   fReproduceTrigResponse(kFALSE),
   fPrintInfo(kFALSE),
-  fMUON(0x0),
+  fWriteOnESD(writeOnESD),
   fDebugLevel(0),
-  fGaliceDir(galiceRunDir)
+  fkMaxDistance(99999.)
 {
+/// Standard constructor
     ResetArrays();
-    delete gAlice;
 }
 
+
 //_____________________________________________________________________________
 AliMUONTriggerChamberEff::~AliMUONTriggerChamberEff()
 {
 /// Destructor
-    fRunLoader->UnloadAll();
-    delete fRunLoader;
-    delete fData;
+    Bool_t writeOnESD=fWriteOnESD;
+    fWriteOnESD=kFALSE;
+    if(writeOnESD) SaveInESDFile();
 }
 
+
 //_____________________________________________________________________________
-void AliMUONTriggerChamberEff::SetGaliceFile(const char *galiceFile)
+AliMUONTriggerChamberEff::AliMUONTriggerChamberEff(const AliMUONTriggerChamberEff& other)
+    :TObject(other),
+     fTransformer(0x0),
+     fDigitMaker(0x0),
+     fReproduceTrigResponse(other.fReproduceTrigResponse),
+     fPrintInfo(other.fPrintInfo),
+     fWriteOnESD(other.fWriteOnESD),
+     fDebugLevel(other.fDebugLevel),
+     fkMaxDistance(other.fkMaxDistance)
 {
-    //
-    /// Opens the galice.root and loads tracks and digits.
-    //
-
-    fRunLoader = AliRunLoader::Open(galiceFile,"MUONFolder","READ");
-    if (!fRunLoader) 
-    {
-       AliError(Form("Error opening %s file \n",galiceFile));
-    }  
-    else
-    {
-       fRunLoader->LoadgAlice();
-       gAlice = fRunLoader->GetAliRun();
-       fMUON = (AliMUON*)gAlice->GetModule("MUON");
-
-       if(fLastEvent<=0 || fLastEvent>fRunLoader->GetNumberOfEvents())fLastEvent = fRunLoader->GetNumberOfEvents()-1;
-       if(fFirstEvent<0)fFirstEvent=0;
-
-
-       AliLoader* loader = fRunLoader->GetLoader("MUONLoader");
-       if ( loader )
-       {
-           fData = new AliMUONData(loader,"MUON","MUON");
-           loader->LoadTracks("READ");
-           loader->LoadDigits("READ");
-       }
-       else
-       {
-           AliError(Form("Could get MUONLoader"));
+    for(Int_t ch=0; ch<fgkNchambers; ch++){
+       for(Int_t cath=0; cath<fgkNcathodes; cath++){
+           fTrigger34[ch][cath] = other.fTrigger34[ch][cath];
+           fTrigger44[cath] = other.fTrigger44[cath];
+           for(Int_t slat=0; slat<fgkNslats; slat++){
+               fInefficientSlat[ch][cath][slat] = other.fInefficientSlat[ch][cath][slat];
+               fHitPerSlat[ch][cath][slat] = other.fHitPerSlat[ch][cath][slat];
+           }
+           for(Int_t board=0; board<fgkNboards; board++){
+               fInefficientBoard[ch][cath][board] = other.fInefficientBoard[ch][cath][board];
+               fHitPerBoard[ch][cath][board] = other.fHitPerBoard[ch][cath][board];
+           }
        }
     }
 }
 
+
 //_____________________________________________________________________________
-void AliMUONTriggerChamberEff::CleanGalice()
+AliMUONTriggerChamberEff& AliMUONTriggerChamberEff::operator=(const AliMUONTriggerChamberEff& other)
 {
-    //
-    /// Unload all loaded data
-    //
-    
-    fRunLoader->UnloadAll();
-    delete fRunLoader;
-    fRunLoader = 0;
+    /// Asignment operator
+    // check assignement to self
+    if (this == &other)
+       return *this;
+
+    // base class assignement
+    TObject::operator=(other);
+
+    fTransformer = 0x0;
+    fDigitMaker = 0x0;
+    fReproduceTrigResponse = other.fReproduceTrigResponse;
+    fPrintInfo = other.fPrintInfo;
+    fWriteOnESD = other.fWriteOnESD;
+    fDebugLevel = other.fDebugLevel;
+    //fkMaxDistance = other.fkMaxDistance;
+    return *this;
 }
 
+
 //_____________________________________________________________________________
 void AliMUONTriggerChamberEff::ResetArrays()
 {
@@ -164,85 +173,200 @@ void AliMUONTriggerChamberEff::ResetArrays()
                fInefficientSlat[ch][cath][slat] = 0;
                fHitPerSlat[ch][cath][slat] = 0;
            }
+           for(Int_t board=0; board<fgkNboards; board++){
+               fInefficientBoard[ch][cath][board] = 0;
+               fHitPerBoard[ch][cath][board] = 0;
+           }
        }
     }
 }
 
 
+//______________________________________________________________________________
+Bool_t 
+AliMUONTriggerChamberEff::TriggerDigits(const AliMUONVTriggerStore& triggerStore,
+                                       AliMUONVDigitStore& digitStore) const
+{
+    //
+    /// make (S)Digit for trigger
+    //
+    digitStore.Clear();
+
+    AliMUONLocalTrigger* locTrg;
+    TIter next(triggerStore.CreateLocalIterator());
+  
+    while ( ( locTrg = static_cast<AliMUONLocalTrigger*>(next()) ) ) 
+    {
+       if (locTrg->IsNull()) continue;
+   
+       TArrayS xyPattern[2];
+       locTrg->GetXPattern(xyPattern[0]);
+       locTrg->GetYPattern(xyPattern[1]);
+    
+       Int_t nBoard = locTrg->LoCircuit();
+       fDigitMaker->TriggerDigits(nBoard, xyPattern, digitStore);
+    }
+    return kTRUE;
+}
+
+
 //_____________________________________________________________________________
-void AliMUONTriggerChamberEff::InfoDigit()
+void AliMUONTriggerChamberEff::InfoDigit(AliMUONVDigitStore& digitStore)
 {
     //
     /// Prints information on digits (for debugging)
     //
-
-    AliMUONDigit * mDigit=0x0;
-    Int_t firstTrigCh = AliMUONConstants::NTrackingCh();
-    // Addressing
-    Int_t nchambers = AliMUONConstants::NCh();
-    fData->SetTreeAddress("D,GLT");
+    TIter next(digitStore.CreateIterator());
+    AliMUONVDigit* mDigit=0x0;
     
-    fData->GetDigits();
-    // Loop on chambers
-    for(Int_t ichamber=firstTrigCh; ichamber<nchambers; ichamber++) {
-      TClonesArray* digits = fData->Digits(ichamber);
-      digits->Sort();
-      Int_t ndigits = (Int_t)digits->GetEntriesFast();
-      for(Int_t idigit=0; idigit<ndigits; idigit++) {
-         mDigit = (AliMUONDigit*)digits->At(idigit);
-         mDigit->Print();
-      } // end digit loop
-    } // end chamber loop
-    fData->ResetDigits();
+    while ( ( mDigit = static_cast<AliMUONVDigit*>(next()) ) )
+    {
+       mDigit->Print();
+    } // end digit loop
+    printf("\n");
 }
 
 
 //_____________________________________________________________________________
-Bool_t AliMUONTriggerChamberEff::PadMatchTrack(Float_t xPad, Float_t yPad, Float_t dpx, Float_t dpy, 
-                                              Float_t xTrackAtPad, Float_t yTrackAtPad, Int_t chamber)
+Int_t AliMUONTriggerChamberEff::MatchingPad(AliMUONVDigitStore& digitStore, Int_t &detElemId,
+                                           Float_t coor[2], Bool_t isMatch[fgkNcathodes],
+                                           Int_t nboard[fgkNcathodes][4],
+                                           Float_t zRealMatch[fgkNchambers], Float_t y11)
 {
     //
-    /// Decides if the digit belongs to the trigger track.
+    /// Check slat and board number of digit matching track
     //
 
-    Float_t numOfHalfWidth = 5.;
-    Bool_t match = kFALSE;
-    Float_t maxDistX = dpx;
-    if(fReproduceTrigResponse && chamber>=2) maxDistX = 3.*dpx;// Non-bending plane: check the +- 1 strip between stations
-    if(!fReproduceTrigResponse)maxDistX = numOfHalfWidth*dpx;
-    Float_t maxDistY = dpy;
-    if(fReproduceTrigResponse && chamber%2) maxDistY = 3*dpy;// bending plane: check the +- 1 strip between planes in the same station
-    if(!fReproduceTrigResponse) maxDistY = numOfHalfWidth*dpy;
-    Float_t deltaX = TMath::Abs(xPad-xTrackAtPad);
-    Float_t deltaY = TMath::Abs(yPad-yTrackAtPad);
-    if(deltaX<=maxDistX && deltaY<=maxDistY)match = kTRUE;
-    return match;
-}
+    enum {kBending, kNonBending};
+
+    Float_t minMatchDist[fgkNcathodes];
+    Int_t padsInCheckArea[fgkNcathodes];
+
+    for(Int_t cath=0; cath<fgkNcathodes; cath++){
+       isMatch[cath] = kFALSE;
+       minMatchDist[cath] = fkMaxDistance/10.;
+       padsInCheckArea[cath] = 0;
+    }
+    Int_t iChamber = AliMpDEManager::GetChamberId(detElemId);
+    Int_t ch = iChamber-10;
+    Float_t oldDeltaZ = AliMUONConstants::DefaultChamberZ(iChamber) - AliMUONConstants::DefaultChamberZ(10);
+    Float_t y = coor[1];
+    Int_t iSlat = detElemId%100;
+    Int_t trigDigitBendPlane = -1;
+    Int_t foundDetElemId = detElemId;
+    Float_t foundZmatch=999.;
+    Float_t yCoorAtPadZ=999.;
+
+    TIter next(digitStore.CreateIterator());
+    AliMUONVDigit* mDigit;
+    Int_t idigit=0;
+    
+    while ( ( mDigit = static_cast<AliMUONVDigit*>(next()) ) )
+    {
+       idigit++;
+       Int_t currDetElemId = mDigit->DetElemId();
+       Int_t currCh = AliMpDEManager::GetChamberId(currDetElemId);
+       if(currCh!=iChamber) continue;
+       Int_t currSlat = currDetElemId%100;
+       Int_t slatDiff = TMath::Abs(currSlat-iSlat);
+       if(slatDiff>1 && slatDiff<17) continue; // Check neighbour slats
+       Int_t cathode = mDigit->Cathode();
+       Int_t ix = mDigit->PadX();
+       Int_t iy = mDigit->PadY();
+       Float_t xpad, ypad, zpad;
+       const AliMpVSegmentation* seg = AliMpSegmentation::Instance()
+           ->GetMpSegmentation(currDetElemId,AliMp::GetCathodType(cathode));
+
+       AliMpPad pad = seg->PadByIndices(AliMpIntPair(ix,iy),kTRUE);
+       Float_t xlocal1 = pad.Position().X();
+       Float_t ylocal1 = pad.Position().Y();
+       Float_t dpx = pad.Dimensions().X();
+       Float_t dpy = pad.Dimensions().Y();
+       fTransformer->Local2Global(currDetElemId, xlocal1, ylocal1, 0, xpad, ypad, zpad);
+       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]);
+       // searching track intersection with chambers (second approximation)
+       if(ch%2==1){
+           //if(iChamber%2==1){
+           Float_t deltaZ = zpad - zRealMatch[0];
+           y = (coor[1]-y11)*deltaZ/oldDeltaZ + y11;
+           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);
+       }
+       Float_t matchDist = PadMatchTrack(xpad, ypad, dpx, dpy, coor[0], y, ch);
+       if(matchDist<fkMaxDistance/2.) padsInCheckArea[cathode]++;
+       if(matchDist>minMatchDist[cathode])continue;
+       isMatch[cathode] = kTRUE;
+       minMatchDist[cathode] = matchDist;
+       foundDetElemId = currDetElemId;
+       foundZmatch=zpad;
+       yCoorAtPadZ=y;
+       if(cathode==kBending) trigDigitBendPlane = idigit;
+       for (Int_t loc=0; loc<pad.GetNofLocations(); loc++){
+           AliMpIntPair location = pad.GetLocation(loc);
+           nboard[cathode][loc] = location.GetFirst();
+       }
+       for(Int_t loc=pad.GetNofLocations(); loc<4; loc++){
+           nboard[cathode][loc]=-1;
+       }
+    }
 
+    for(Int_t cath=0; cath<fgkNcathodes; cath++){
+       if(padsInCheckArea[cath]>2) {
+           if(fDebugLevel>=1) printf("padsInCheckArea[%i] = %i\n",cath,padsInCheckArea[cath]);
+           return -500;
+       }
+    }
+
+    if(isMatch[kBending] || isMatch[kNonBending]){
+       detElemId = foundDetElemId;
+       zRealMatch[ch] = foundZmatch;
+       coor[1] = yCoorAtPadZ;
+       if(fDebugLevel>2){
+           Int_t whichCathode=kBending;
+           if(!isMatch[kBending])whichCathode=kNonBending;
+       }
+    }
+    return trigDigitBendPlane;
+}
 
 //_____________________________________________________________________________
-Bool_t AliMUONTriggerChamberEff::IsDiffLocalBoard(Int_t currDetElemId, Int_t iy, Int_t detElemIdP1, Int_t iyDigitP1) const
+Float_t AliMUONTriggerChamberEff::PadMatchTrack(Float_t xPad, Float_t yPad,
+                                               Float_t dpx, Float_t dpy, 
+                                               Float_t xTrackAtPad, Float_t yTrackAtPad,
+                                               Int_t chamber)
 {
     //
-    /// Determins if the digits belong to the same local board.
-    /// Used only if one wants to reproduce the trigger algorithm result.
-    /// (fReproduceTrigResponse = kTRUE).
+    /// Decides if the digit belongs to the trigger track.
     //
 
-    Bool_t isDiff = kTRUE;
-    if(detElemIdP1<0 || iyDigitP1<0)return kFALSE;
-    Int_t currSlat = currDetElemId%100;
-    Int_t slatP1 = detElemIdP1%100;
-    Int_t currLoc = iy/16;
-    Int_t locP1 = iyDigitP1/16;
-    if(currSlat==slatP1 && currLoc==locP1)isDiff = kFALSE;
-    return isDiff;
+    Float_t maxDist = 2.;//3. // cm
+    Float_t maxDistCheckArea = 6.; // cm
+
+    Float_t matchDist = fkMaxDistance;
+
+    Float_t deltaX = TMath::Abs(xPad-xTrackAtPad)-dpx;
+    Float_t deltaY = TMath::Abs(yPad-yTrackAtPad)-dpy;
+    Float_t maxDistX = maxDist;
+    Float_t maxDistY = maxDist;
+    
+    if(fReproduceTrigResponse){
+       maxDistX = dpx;
+       maxDistY = dpy;
+       deltaX = TMath::Abs(xPad-xTrackAtPad);
+       deltaY = TMath::Abs(yPad-yTrackAtPad);
+       if(dpx<dpy && chamber>=2) maxDistX = 3.*dpx;// Non-bending plane: check the +- 1 strip between stations
+       if(dpy<dpx && chamber%2) maxDistY = 3.*dpy;// bending plane: check the +- 1 strip between planes in the same station
+    }
+
+    if(deltaX<=maxDistX && deltaY<=maxDistY) matchDist = TMath::Max(deltaX, deltaY);
+    else if(deltaX<=maxDistCheckArea && deltaY<=maxDistCheckArea) matchDist = fkMaxDistance/5.;
+    return matchDist;
 }
 
 
 //_____________________________________________________________________________
 void AliMUONTriggerChamberEff::CalculateEfficiency(Int_t trigger44, Int_t trigger34,
-                                                  Float_t &efficiency, Float_t &error, Bool_t failuresAsInput)
+                                                  Float_t &efficiency, Float_t &error,
+                                                  Bool_t failuresAsInput)
 {
     //
     /// Returns the efficiency.
@@ -261,7 +385,8 @@ void AliMUONTriggerChamberEff::CalculateEfficiency(Int_t trigger44, Int_t trigge
 
 
 //_____________________________________________________________________________
-Int_t AliMUONTriggerChamberEff::DetElemIdFromPos(Float_t x, Float_t y, Int_t chamber, Int_t cathode)
+Int_t AliMUONTriggerChamberEff::DetElemIdFromPos(Float_t x, Float_t y, 
+                                                Int_t chamber, Int_t cathode)
 {
     //
     /// Given the (x,y) position in the chamber,
@@ -270,50 +395,59 @@ Int_t AliMUONTriggerChamberEff::DetElemIdFromPos(Float_t x, Float_t y, Int_t cha
 
     Int_t resultingDetElemId = -1;
     AliMpDEIterator it;
-    const AliMUONGeometryTransformer *kGeomTransformer = fMUON->GetGeometryTransformer();
-    AliMUONSegmentation *segmentation = fMUON->GetSegmentation();
+    Float_t minDist = 999.;
     for ( it.First(chamber-1); ! it.IsDone(); it.Next() ){
        Int_t detElemId = it.CurrentDEId();
+       Int_t ich = detElemId/100-10;
+       Float_t tolerance=0.2*((Float_t)ich);
+       Float_t currDist=9999.;
+
+       const AliMpVSegmentation* seg = 
+           AliMpSegmentation::Instance()
+           ->GetMpSegmentation(detElemId,AliMp::GetCathodType(cathode));
+       if (!seg) continue;
+
+       Float_t deltax = seg->Dimensions().X();
+       Float_t deltay = seg->Dimensions().Y();
+       Float_t xlocal1 =  -deltax;
+       Float_t ylocal1 =  -deltay;
+       Float_t xlocal2 =  +deltax;
+       Float_t ylocal2 =  +deltay;
+       Float_t xg01, yg01, zg1, xg02, yg02, zg2;
+       fTransformer->Local2Global(detElemId, xlocal1, ylocal1, 0, xg01, yg01, zg1);
+       fTransformer->Local2Global(detElemId, xlocal2, ylocal2, 0, xg02, yg02, zg2);
+
+       Float_t xg1 = xg01, xg2 = xg02, yg1 = yg01, yg2 = yg02;
+
+       if(xg01>xg02){
+           xg1 = xg02;
+           xg2 = xg01;
+       }
+       if(yg01>yg02){
+           yg1 = yg02;
+           yg2 = yg01;
+       }
 
-       if (  segmentation->HasDE(detElemId) ){
-           const AliMpVSegmentation* seg = 
-               AliMpSegmentation::Instance()
-                  ->GetMpSegmentation(detElemId,AliMp::GetCathodType(cathode));
-           if (seg){
-               Float_t deltax = seg->Dimensions().X();
-               Float_t deltay = seg->Dimensions().Y();
-               Float_t xlocal1 =  -deltax;
-               Float_t ylocal1 =  -deltay;
-               Float_t xlocal2 =  +deltax;
-               Float_t ylocal2 =  +deltay;
-               Float_t xg01, yg01, zg1, xg02, yg02, zg2;
-               kGeomTransformer->Local2Global(detElemId, xlocal1, ylocal1, 0, xg01, yg01, zg1);
-               kGeomTransformer->Local2Global(detElemId, xlocal2, ylocal2, 0, xg02, yg02, zg2);
-
-               Float_t xg1 = xg01, xg2 = xg02, yg1 = yg01, yg2 = yg02;
-
-               if(xg01>xg02){
-                   xg1 = xg02;
-                   xg2 = xg01;
-               }
-               if(yg01>yg02){
-                   yg1 = yg02;
-                   yg2 = yg01;
-               }
-
-               if(x>=xg1 && x<=xg2 && y>=yg1 && y<=yg2){
-                   resultingDetElemId = detElemId;
-                   break;
-               }
+       if(x>=xg1-tolerance && x<=xg2+tolerance && y>=yg1-tolerance && y<=yg2+tolerance){ // takes into account errors in extrapolation
+           if(y<yg1) currDist = yg1-y;
+           else if(y>yg2) currDist = y-yg2;
+           if(currDist<minDist) {
+               resultingDetElemId = detElemId;
+               minDist=currDist;
+               continue;
            }
+           resultingDetElemId = detElemId;
+           break;
        }
-    }
+    } // loop on detElemId
     return resultingDetElemId;
 }
 
 
 //_____________________________________________________________________________
-void AliMUONTriggerChamberEff::LocalBoardFromPos(Float_t x, Float_t y, Int_t detElemId, Int_t cathode, Int_t localBoard[4])
+void AliMUONTriggerChamberEff::LocalBoardFromPos(Float_t x, Float_t y,
+                                                Int_t detElemId, Int_t cathode,
+                                                Int_t localBoard[4])
 {
     //
     /// Given the (x,y) position in the chamber,
@@ -323,9 +457,8 @@ void AliMUONTriggerChamberEff::LocalBoardFromPos(Float_t x, Float_t y, Int_t det
     for(Int_t loc=0; loc<4; loc++){
        localBoard[loc]=-1;
     }
-    const AliMUONGeometryTransformer *kGeomTransformer = fMUON->GetGeometryTransformer();
     Float_t xl, yl, zl;
-    kGeomTransformer->Global2Local(detElemId, x, y, 0, xl, yl, zl);
+    fTransformer->Global2Local(detElemId, x, y, 0, xl, yl, zl);
     TVector2 pos(xl,yl);
     const AliMpVSegmentation* seg = 
        AliMpSegmentation::Instance()
@@ -341,34 +474,9 @@ void AliMUONTriggerChamberEff::LocalBoardFromPos(Float_t x, Float_t y, Int_t det
 
 
 //_____________________________________________________________________________
-void AliMUONTriggerChamberEff::PrintTrigger(AliMUONGlobalTrigger *globalTrig)
-{
-    //
-    /// Print trigger response.
-    //
-
-    printf("===================================================\n");
-    printf(" Global Trigger output\t \tLow pt\tHigh pt\n");
-
-    printf(" number of Single:\t \t"); 
-    printf("%i\t",globalTrig->SingleLpt());
-    printf("%i\t",globalTrig->SingleHpt());
-    printf("\n");
-
-    printf(" number of UnlikeSign pair:\t"); 
-    printf("%i\t",globalTrig->PairUnlikeLpt());
-    printf("%i\t",globalTrig->PairUnlikeHpt());
-    printf("\n");
-
-    printf(" number of LikeSign pair:\t");  
-    printf("%i\t",globalTrig->PairLikeLpt());
-    printf("%i\t",globalTrig->PairLikeHpt());
-    printf("\n");
-    printf("===================================================\n");
-    printf("\n");
-}
-
-void AliMUONTriggerChamberEff::PerformTriggerChamberEff(const char* outputDir)
+void AliMUONTriggerChamberEff::EventChamberEff(const AliMUONVTriggerStore& triggerStore,
+                                              const AliMUONVTriggerTrackStore& trigTrackStore,
+                                              const AliMUONVTrackStore& trackStore)
 {
     //
     /// Main method.
@@ -378,439 +486,257 @@ void AliMUONTriggerChamberEff::PerformTriggerChamberEff(const char* outputDir)
     /// Files with calculated efficiency are placed in the user defined outputDir.
     //
 
+    if(!fTransformer || ! fDigitMaker) {
+       AliError(Form("AliMUONGeometryTransformer or AliMUONDigitMaker not properly initialized!!"));
+       return;
+    }
+
     enum {kBending, kNonBending};
-    Int_t evtBeforePrint = 1000;
     Float_t rad2deg = 180./TMath::Pi();
 
-    Int_t chOrder[] = {0,2,1,3};
-    Int_t station[] = {0,0,1,1};
+    Int_t chOrder[fgkNchambers] = {0,2,1,3};
     Float_t zRealMatch[fgkNchambers] = {0.0};
     Float_t correctFactor[fgkNcathodes] = {1.};
 
     Bool_t match[fgkNchambers][fgkNcathodes] = {{kFALSE}};
+    Bool_t matchPad[fgkNcathodes]={kFALSE};
 
-    TClonesArray *recTrigTracksArray = 0x0;
-    AliMUONTriggerTrack *recTrigTrack = 0x0;
-    AliMUONDigit * mDigit = 0x0;
 
     Float_t zMeanChamber[fgkNchambers];
     for(Int_t ch=0; ch<fgkNchambers; ch++){
        zMeanChamber[ch] = AliMUONConstants::DefaultChamberZ(10+ch);
     }
 
-    TClonesArray * globalTrigger = 0x0;
-    AliMUONGlobalTrigger * gloTrg = 0x0; 
-
-    Int_t partNumOfTrig[fgkNchambers][fgkNcathodes] = {{0}};
-    Int_t totNumOfTrig[fgkNchambers][fgkNcathodes] = {{0}};
-    Int_t atLeast1MuPerEv[fgkNchambers][fgkNcathodes] = {{0}};
     Int_t digitPerTrack[fgkNcathodes] = {0};
 
-    Float_t trackIntersectCh[2][fgkNchambers]={{0.0}};
+    Float_t trackIntersectCh[fgkNchambers][2]={{0.0}};
 
-    Int_t slatInPlane1[2][fgkNcathodes];
-    Int_t iyDigitInPlane1[2][fgkNcathodes];
+    Int_t triggeredDigits[2][fgkNchambers] = {{-1}};
 
-    const Int_t kMaxNumOfTracks = 10;
-    Int_t trigScheme[kMaxNumOfTracks][fgkNchambers][fgkNcathodes]={{{0}}};
-    Int_t triggeredDigits[kMaxNumOfTracks][fgkNchambers][fgkNcathodes] = {{{-1}}};
-    Int_t slatThatTriggered[kMaxNumOfTracks][fgkNchambers][fgkNcathodes]={{{-1}}};
-    Int_t boardThatTriggered[kMaxNumOfTracks][fgkNchambers][fgkNcathodes][4]={{{{-1}}}};
-    Int_t nboard[4]={-1};
+    Int_t trigScheme[fgkNchambers][fgkNcathodes]={{0}};
+    Int_t slatThatTriggered[fgkNchambers][fgkNcathodes]={{-1}};
+    Int_t boardThatTriggered[fgkNchambers][fgkNcathodes][4]={{{-1}}};
+    Int_t nboard[fgkNcathodes][4]={{-1}};
     Int_t ineffBoard[4]={-1};
 
-    const Int_t kMaxNumOfDigits = 20;
-    Int_t detElOfDigitsInData[kMaxNumOfDigits][fgkNchambers][fgkNcathodes] = {{{-1}}};
+    AliMUONDigitStoreV1 digitStore;   
+    TriggerDigits(triggerStore,digitStore);
 
-    char filename[150];
-    FileStat_t fs;
-
-    if(fFirstRun<0)fFirstRun=fLastRun=-1;
-
-    for(Int_t iRun = fFirstRun; iRun <= fLastRun; iRun++){// Loop over runs
-    // open run loader and load gAlice
-    if(fFirstRun>=0){
-       cout<<"\n\nRun = "<<iRun<<endl;
-       sprintf(filename, "%s/run%i/galice.root", fGaliceDir.Data(), iRun);
-       if(gSystem->GetPathInfo(filename,fs)){
-           cout<<"Warning: "<<filename<<" not found. Skip to next one"<<endl;
-           continue;
+    for(Int_t ch=0; ch<fgkNchambers; ch++){
+       for(Int_t itrack=0; itrack<2; itrack++){
+           triggeredDigits[itrack][ch]=-1;
        }
-       cout<<"Opening file "<<filename<<endl;
-       SetGaliceFile(filename);
     }
 
-    for (Int_t ievent=fFirstEvent; ievent<=fLastEvent; ievent++) { // event loop
-       Bool_t isClearEvent = kTRUE;
+    AliMUONTriggerTrack *recTrigTrack = 0x0;
 
+    TIter next(trigTrackStore.CreateIterator());
+    
+    while ( ( recTrigTrack = static_cast<AliMUONTriggerTrack*>(next()) ) )
+    {
+       for(Int_t cath=0; cath<fgkNcathodes; cath++){
+           digitPerTrack[cath]=0;
+       }
        for(Int_t ch=0; ch<fgkNchambers; ch++){
            for(Int_t cath=0; cath<fgkNcathodes; cath++){
-               partNumOfTrig[ch][cath]=0;
                match[ch][cath]=kFALSE;
-               for(Int_t itrack=0; itrack<kMaxNumOfTracks; itrack++){
-                   triggeredDigits[itrack][ch][cath]=-1;
-                   slatThatTriggered[itrack][ch][cath]=-1;
-                   for(Int_t loc=0; loc<4; loc++){
-                       boardThatTriggered[itrack][ch][cath][loc]=-1;
-                   }
-               }
-               for(Int_t idig=0; idig<kMaxNumOfDigits; idig++){
-                   detElOfDigitsInData[idig][ch][cath]=-1;
+               slatThatTriggered[ch][cath]=-1;
+               for(Int_t loc=0; loc<4; loc++){
+                   boardThatTriggered[ch][cath][loc]=-1;
                }
            }
        }
 
-       fRunLoader->GetEvent(ievent);
-       if (ievent%evtBeforePrint==0) printf("\t Event = %d\n",ievent);
+       Bool_t isClearEvent = kTRUE;
+       Bool_t doubleCountTrack = kFALSE;
 
-       fData->SetTreeAddress("RL");
-       fData->GetRecTriggerTracks();
-       recTrigTracksArray = fData->RecTriggerTracks();
-       Int_t nRecTrigTracks = (Int_t) recTrigTracksArray->GetEntriesFast();
+       if(!IsCleanTrack(recTrigTrack, trackStore)) {
+           if(fDebugLevel>=1) printf("\tTrack %p (%f, %f) don't match tracker track: rejected!\n",recTrigTrack,recTrigTrack->GetX11(),recTrigTrack->GetY11());
+           continue;
+       }
 
-       fData->SetTreeAddress("D,GLT");
-       fData->GetDigits();
+       Float_t x11 = recTrigTrack->GetX11();// x position (info from non-bending plane)
+       Float_t y11 = recTrigTrack->GetY11();// y position (info from bending plane)
+       Float_t thetaX = recTrigTrack->GetThetax();
+       Float_t thetaY = recTrigTrack->GetThetay();
 
-       const AliMUONGeometryTransformer* kGeomTransformer = fMUON->GetGeometryTransformer();
+       if(fDebugLevel>=3) printf("\tTrack = %p\npos from track: (x,y) = (%f, %f), (thetaX, thetaY) = (%f, %f)\n",recTrigTrack,x11,y11,thetaX*rad2deg,thetaY*rad2deg);
 
-       for (Int_t iRecTrigTrack=0; iRecTrigTrack<nRecTrigTracks; iRecTrigTrack++) {
+       for(Int_t ch=0; ch<fgkNchambers; ch++) {
+           zRealMatch[ch] = zMeanChamber[ch];
            for(Int_t cath=0; cath<fgkNcathodes; cath++){
-               digitPerTrack[cath]=0;
-               for(Int_t sta=0; sta<2; sta++){
-                   slatInPlane1[sta][cath] = -9999;
-                   iyDigitInPlane1[sta][cath] = -9999;
-               }
+               trigScheme[ch][cath] = 0;
            }
+       }
 
-           Bool_t doubleCountTrack = kFALSE;
-
-           // reading info from tracks
-           recTrigTrack = (AliMUONTriggerTrack *)recTrigTracksArray->At(iRecTrigTrack);
-           Float_t x11 = recTrigTrack->GetX11();// x position (info from non-bending plane)
-           Float_t y11 = recTrigTrack->GetY11();// y position (info from bending plane)
-           Float_t thetaX = recTrigTrack->GetThetax();
-           Float_t thetaY = recTrigTrack->GetThetay();
+       for(Int_t ch=0; ch<fgkNchambers; ch++) { // chamber loop
+           Int_t currCh = chOrder[ch];
+           if(fDebugLevel>=2)
+               printf("zMeanChamber[%i] = %.2f\tzRealMatch[0] = %.2f\n",currCh,zMeanChamber[currCh],zRealMatch[0]);
 
-           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);
+           for(Int_t cath=0; cath<fgkNcathodes; cath++){
+               correctFactor[cath]=1.;
+           }
+           // calculate corrections to trigger track theta
+           if(ch>=1)correctFactor[kNonBending] = zMeanChamber[0]/zRealMatch[0];// corrects x position
+           if(ch>=2)correctFactor[kBending] = (zMeanChamber[2] - zMeanChamber[0]) / (zRealMatch[2] - zRealMatch[0]);// corrects y position
+
+           // searching track intersection with chambers (first approximation)
+           Float_t deltaZ = zMeanChamber[currCh] - zMeanChamber[0];
+           trackIntersectCh[currCh][0] = zMeanChamber[currCh] * TMath::Tan(thetaX) * correctFactor[kNonBending];// x position (info from non-bending plane) 
+           trackIntersectCh[currCh][1] = y11 + deltaZ * TMath::Tan(thetaY) * correctFactor[kBending];// y position (info from bending plane)
+           Int_t detElemIdFromTrack = DetElemIdFromPos(trackIntersectCh[currCh][0], trackIntersectCh[currCh][1], 11+currCh, 0);
+           if(detElemIdFromTrack<0) {
+               if(fDebugLevel>1) printf("Warning: trigger track outside trigger chamber\n");
+               continue;
+           }
+               
+           triggeredDigits[1][currCh] = MatchingPad(digitStore, detElemIdFromTrack, trackIntersectCh[currCh], matchPad, nboard, zRealMatch, y11);
+
+           // if MatchingPad = -500 => too many digits matching pad =>
+           //                       => Event not clear => Reject track
+           if(triggeredDigits[1][currCh]<-100){
+               isClearEvent = kFALSE;
+               if(fDebugLevel>=1) printf("Warning: track = %p (%i) matches many pads. Rejected!\n",recTrigTrack, detElemIdFromTrack);
+               break;
+           }
 
-           for(Int_t ch=0; ch<fgkNchambers; ch++) {
-               zRealMatch[ch] = zMeanChamber[ch];
+           // deciding if digit matches track
+           Bool_t isDiffLocBoard = kFALSE;
+           if(fReproduceTrigResponse && ch>2){
                for(Int_t cath=0; cath<fgkNcathodes; cath++){
-                   trigScheme[iRecTrigTrack][ch][cath] = 0;
+                   if(boardThatTriggered[currCh][cath][0]>=0){
+                       if(boardThatTriggered[currCh][cath][0]!=boardThatTriggered[currCh-1][cath][0]) isDiffLocBoard = kTRUE;
+                   }
                }
            }
 
-           for(Int_t ch=0; ch<fgkNchambers; ch++) { // chamber loop
-               Int_t currCh = chOrder[ch];
-               Int_t ichamber = 10+currCh;
-               Int_t currStation = station[currCh];
-               TClonesArray* digits = fData->Digits(ichamber);
-               digits->Sort();
-               Int_t ndigits = (Int_t)digits->GetEntriesFast();
-               if(fDebugLevel>=2){
-                   if(fDebugLevel<3)printf("\tEvent = %i, Track = %i\n", ievent, iRecTrigTrack);
-                   printf("DigitNum: %i digits detected\n",ndigits);
-               }
+           if(isDiffLocBoard && fDebugLevel>=1)printf("\tDifferent local board\n");
 
-               for(Int_t cath=0; cath<fgkNcathodes; cath++){
-                   correctFactor[cath]=1.;
+           for(Int_t cath=0; cath<fgkNcathodes; cath++){
+               match[currCh][cath] = (matchPad[cath] && !isDiffLocBoard);
+               if(!match[currCh][cath]) continue;
+               digitPerTrack[cath]++;
+               trigScheme[currCh][cath]++;
+               slatThatTriggered[currCh][cath] = detElemIdFromTrack;
+               for(Int_t loc=0; loc<4; loc++){
+                   boardThatTriggered[currCh][cath][loc] = nboard[cath][loc];
                }
-               // calculate corrections to trigger track theta
-               if(ch>=1)correctFactor[kNonBending] = zMeanChamber[0]/zRealMatch[0];// corrects x position
-               if(ch>=2)correctFactor[kBending] = (zMeanChamber[2] - zMeanChamber[0]) / (zRealMatch[2] - zRealMatch[0]);// corrects y position
-
-               // searching track intersection with chambers (first approximation)
-               Float_t deltaZ = zMeanChamber[currCh] - zMeanChamber[0];
-               trackIntersectCh[0][currCh] = zMeanChamber[currCh] * TMath::Tan(thetaX) * correctFactor[kNonBending];// x position (info from non-bending plane) 
-               trackIntersectCh[1][currCh] = y11 + deltaZ * TMath::Tan(thetaY) * correctFactor[kBending];// y position (info from bending plane)
-
-               for(Int_t idigit=0; idigit<ndigits; idigit++) { // digit loop
-                   mDigit = (AliMUONDigit*)digits->At(idigit);
-                   for(Int_t loc=0; loc<4; loc++){
-                       nboard[loc]=-1;
-                   }
-
-                   // searching loaded digit global position and dimension
-                   Int_t detElemId = mDigit->DetElemId();
-                   Int_t cathode = mDigit->Cathode();
-                   Int_t ix = mDigit->PadX();
-                   Int_t iy = mDigit->PadY();
-                   Float_t xpad, ypad, zpad;
-                   if(detElOfDigitsInData[idigit][ch][cathode]==-1)detElOfDigitsInData[idigit][ch][cathode] = detElemId;
-
-                   if(fDebugLevel>=2)printf("cathode = %i\n",cathode);
-                   const AliMpVSegmentation* seg = AliMpSegmentation::Instance()
-                      ->GetMpSegmentation(detElemId,AliMp::GetCathodType(cathode));
-
-                   AliMpPad pad = seg->PadByIndices(AliMpIntPair(ix,iy),kTRUE);
-                   for (Int_t loc=0; loc<pad.GetNofLocations(); loc++){
-                       AliMpIntPair location = pad.GetLocation(loc);
-                       nboard[loc] = location.GetFirst();
-                   }
-
-                   // get the pad position and dimensions
-                   Float_t xlocal1 = pad.Position().X();
-                   Float_t ylocal1 = pad.Position().Y();
-                   Float_t dpx = pad.Dimensions().X();
-                   Float_t dpy = pad.Dimensions().Y();
-
-                   kGeomTransformer->Local2Global(detElemId, xlocal1, ylocal1, 0, xpad, ypad, zpad);
-
-                   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);
-
-                   // searching track intersection with chambers (second approximation)
-                   if(ch>=2){
-                       deltaZ = zpad - zRealMatch[0];
-                       trackIntersectCh[1][currCh] = y11 + deltaZ * TMath::Tan(thetaY) * correctFactor[kBending];// y position (info from bending plane)
-                   }
-
-                   // deciding if digit matches track
-                   Bool_t isDiffLocBoard = kFALSE;
-                   if(fReproduceTrigResponse)isDiffLocBoard = IsDiffLocalBoard(detElemId, iy, slatInPlane1[currStation][cathode], iyDigitInPlane1[currStation][cathode]);
-                   Bool_t matchPad = PadMatchTrack(xpad, ypad, dpx, dpy, trackIntersectCh[0][currCh], trackIntersectCh[1][currCh], currCh);
-
-                   if(matchPad && ch<2){
-                       slatInPlane1[currStation][cathode] = detElemId;
-                       iyDigitInPlane1[currStation][cathode] = iy;
-                       if(fDebugLevel>=3)printf("slatInPlane1[%i][%i] = %i\tiyDigitInPlane1[%i][%i] = %i\n",currStation,cathode,slatInPlane1[currStation][cathode],currStation,cathode,iyDigitInPlane1[currStation][cathode]);
-                   }
-
-                   if(isDiffLocBoard && fDebugLevel>=1)printf("\tDifferent local board\n");
-
-                   match[currCh][cathode] = (matchPad && !isDiffLocBoard);
+           }
+       } // end chamber loop
 
-                   if(match[currCh][cathode]){
-                       digitPerTrack[cathode]++;
-                       trigScheme[iRecTrigTrack][currCh][cathode]++;
-                       triggeredDigits[iRecTrigTrack][currCh][cathode] = idigit;
-                       slatThatTriggered[iRecTrigTrack][currCh][cathode] = detElemId;
-                       for(Int_t loc=0; loc<4; loc++){
-                           boardThatTriggered[iRecTrigTrack][currCh][cathode][loc] = nboard[loc];
-                       }
-                       if(digitPerTrack[cathode]>4 && !fReproduceTrigResponse)isClearEvent = kFALSE;
-                   }
+       for(Int_t cath=0; cath<fgkNcathodes; cath++){
+           if(digitPerTrack[cath]<3)isClearEvent = kFALSE;
+           if(fDebugLevel>=1 && !isClearEvent)printf("Warning: found %i digits for trigger track cathode %i.\nRejecting event\n", digitPerTrack[cath],cath);
+       }
 
-                   // in case of match, store real z position of the chamber
-                   if(matchPad)zRealMatch[currCh] = zpad;
+       if(!isClearEvent && !fReproduceTrigResponse) continue;
 
-               } // end digit loop
-           } // end chamber loop
+       Int_t commonDigits = 0;
+       for(Int_t ch=0; ch<fgkNchambers; ch++){
+           if(triggeredDigits[1][ch]==triggeredDigits[0][ch]) commonDigits++; // Compare with previous track
+           triggeredDigits[0][ch] = triggeredDigits[1][ch]; // Store this track parameters for comparison with next one
+       }
+       if(commonDigits>=2){
+           doubleCountTrack=kTRUE;
+       }
 
+       if(!doubleCountTrack || fReproduceTrigResponse){
            for(Int_t cath=0; cath<fgkNcathodes; cath++){
-               if(digitPerTrack[cath]<3 && !fReproduceTrigResponse)isClearEvent = kFALSE;
-           }
-
-           if(!isClearEvent && !fReproduceTrigResponse){ 
-               fData->ResetDigits();
-               continue;
-           }
-
-           Int_t commonDigits = 0;
-           Int_t doubleTrack = -1;
-           for(Int_t itrack=0; itrack<iRecTrigTrack; itrack++){
+               Int_t is44 = 1;
+               Bool_t goodForSlatEff = kTRUE;
+               Bool_t goodForBoardEff = kTRUE;
+               Int_t ineffSlat = -1;
+               Int_t ineffDetElId = -1;
+               Int_t firstSlat = slatThatTriggered[0][cath]%100;
+               if(firstSlat<0) firstSlat=slatThatTriggered[1][cath]%100;
+               Int_t firstBoard = boardThatTriggered[0][kBending][0];
+               if(firstBoard<0) firstBoard=boardThatTriggered[1][kBending][0];
                for(Int_t ch=0; ch<fgkNchambers; ch++){
-                   if(triggeredDigits[itrack][ch][kBending]==triggeredDigits[iRecTrigTrack][ch][kBending])commonDigits++;
-               }
-               if(commonDigits>=2){
-                   doubleCountTrack=kTRUE;
-                   doubleTrack = itrack;
-                   break;
-               }
-           }
-
-           for(Int_t cath=0; cath<fgkNcathodes; cath++){
-               if(!doubleCountTrack || fReproduceTrigResponse){
-                   Int_t is44 = 1;
-                   Bool_t goodForSlatEff=kTRUE;
-                   Bool_t goodForBoardEff=kTRUE;
-                   Int_t firstSlat=slatThatTriggered[iRecTrigTrack][0][cath]%100;
-                   if(firstSlat<0)firstSlat=slatThatTriggered[iRecTrigTrack][1][cath]%100;
-                   Int_t firstBoard=boardThatTriggered[iRecTrigTrack][0][0][0];
-                   if(firstBoard<0)firstBoard=boardThatTriggered[iRecTrigTrack][1][0][0];
-                   for(Int_t ch=0; ch<fgkNchambers; ch++){
-                       is44 *= trigScheme[iRecTrigTrack][ch][cath];
-                       Int_t currSlat=slatThatTriggered[iRecTrigTrack][ch][cath]%100;
-                       if(currSlat<0)continue;
-                       if(currSlat!=firstSlat)goodForSlatEff=kFALSE;
-                       Bool_t atLeastOneLoc=kFALSE;
-                       for(Int_t loc=0; loc<4; loc++){
-                           Int_t currBoard = boardThatTriggered[iRecTrigTrack][ch][cath][loc];
-                           if(currBoard==firstBoard){
-                               atLeastOneLoc=kTRUE;
-                               break;
-                           }
-                       }
-                       if(!atLeastOneLoc)goodForBoardEff=kFALSE;
+                   Bool_t isCurrChIneff = kFALSE;
+                   is44 *= trigScheme[ch][cath];
+                   Int_t currSlat = slatThatTriggered[ch][cath]%100;
+                   if(currSlat<0){
+                       ineffDetElId = DetElemIdFromPos(trackIntersectCh[ch][0], trackIntersectCh[ch][1], 11+ch, cath);
+                       currSlat = ineffDetElId%100;
+                       ineffSlat = currSlat;
+                       isCurrChIneff = kTRUE;
                    }
-                   if(fDebugLevel==1)printf("\tEvent = %i, Track = %i\n", ievent, iRecTrigTrack);
-                   if(is44==1){
-                       fTrigger44[cath]++;
-                       if(fDebugLevel>=1)printf("Trigger44[%i] = %i\n",cath,fTrigger44[cath]);
-                       if(goodForSlatEff){
-                           for(Int_t ch=0; ch<fgkNchambers; ch++){
-                               for(Int_t slat=0; slat<fgkNslats; slat++){
-                                   Int_t corrDetEl = (ch+11)*100 + slat;
-                                   if(corrDetEl==slatThatTriggered[iRecTrigTrack][ch][cath]){
-                                       fHitPerSlat[ch][cath][slat]++;
-                                       if(fDebugLevel>=1)printf("Slat that triggered = %i\n",corrDetEl);
-                                       if(goodForBoardEff && firstBoard>0){
-                                           fHitPerBoard[ch][cath][firstBoard-1]++;
-                                           if(fDebugLevel>=1)printf("Board that triggered = %i\n",firstBoard);
-                                       }
-                                       else if(fDebugLevel>=1)printf("Event = %i, Track = %i: Particle crossed different boards: rejected!\n",ievent,iRecTrigTrack);
-                                   }
-                               }
-                           }
+                   if(currSlat!=firstSlat)goodForSlatEff=kFALSE;
+                   Bool_t atLeastOneLoc=kFALSE;
+                   if(isCurrChIneff) LocalBoardFromPos(trackIntersectCh[ch][0], trackIntersectCh[ch][1], ineffDetElId, cath, ineffBoard);
+                   for(Int_t loc=0; loc<4; loc++){
+                       Int_t currBoard = boardThatTriggered[ch][cath][loc];
+                       if(isCurrChIneff) currBoard = ineffBoard[loc];
+                       if(currBoard==firstBoard){
+                           atLeastOneLoc=kTRUE;
+                           break;
                        }
-                       else printf("Event = %i, Track = %i: Particle crossed different slats: rejected!\n",ievent,iRecTrigTrack);
                    }
-                   if(digitPerTrack[cath]==3){
+                   if(!atLeastOneLoc)goodForBoardEff=kFALSE;
+               } // end chamber loop
+
+               // Trigger 4/4
+               if(is44==1){
+                   fTrigger44[cath]++;
+                   if(fDebugLevel>=1)printf("Trigger44[%i] = %i\n",cath,fTrigger44[cath]);
+                   if(goodForSlatEff){
                        for(Int_t ch=0; ch<fgkNchambers; ch++){
-                           if(match[ch][cath])partNumOfTrig[ch][cath]++;
-                           if(trigScheme[iRecTrigTrack][ch][cath]==0){
-                               fTrigger34[ch][cath]++;
-                               if(fDebugLevel>=1)printf("Trigger34[%i][%i] = %i\n",ch,cath,fTrigger34[ch][cath]);
-                               if(!goodForSlatEff){
-                                   printf("Event %i, Track = %i: Particle crossed different slats: rejected!\n",ievent,iRecTrigTrack);
-                                   continue;
-                               }
-                               Int_t ineffSlat = DetElemIdFromPos(trackIntersectCh[0][ch], trackIntersectCh[1][ch], 11+ch, cath);
-                               if(fDebugLevel>=1)printf("Slat non efficient = %i\n",ineffSlat);
-                               if(ineffSlat>0){
-                                   Int_t slatInCh = ineffSlat%100;
-                                   fInefficientSlat[ch][cath][slatInCh]++;
-                                   for(Int_t idig=0; idig<kMaxNumOfDigits; idig++){
-                                       if(ineffSlat==detElOfDigitsInData[idig][ch][cath])cout<<"Warning: "<<ineffSlat<<" is not inefficient!!!"<<endl;
-                                   }
-                                   LocalBoardFromPos(trackIntersectCh[0][ch], trackIntersectCh[1][ch], ineffSlat, cath, ineffBoard);
-                                   Int_t boardNonEff=-1;
-                                   for(Int_t loc=0; loc<4; loc++){
-                                       if(ineffBoard[loc]==firstBoard){
-                                           boardNonEff=ineffBoard[loc];
-                                           break;
-                                       }
-                                   }
-                                   if(fDebugLevel>=1)printf("Board non efficient = %i\n",boardNonEff);
-                                   if(boardNonEff>0)fInefficientBoard[ch][cath][boardNonEff-1]++;
-                                   else if(fDebugLevel>=1){
-                                       printf("Inefficient board should be %i.\tBoards found:\n", firstBoard);
-                                       for(Int_t loc=0; loc<4; loc++){
-                                           printf("%i\t",ineffBoard[loc]);
-                                       }
-                                       printf("\n");
-                                   }
-                                   
-                               }
+                           fHitPerSlat[ch][cath][firstSlat]++;
+                           if(fDebugLevel>=1)printf("Slat that triggered = %i\n",slatThatTriggered[ch][cath]);
+                           if(goodForBoardEff && firstBoard>0){
+                               fHitPerBoard[ch][cath][firstBoard-1]++;
+                               if(fDebugLevel>=1)printf("Board that triggered = %i\n",firstBoard);
                            }
+                           else if(fDebugLevel>=1) printf("Track = %p: Particle crossed different boards: rejected!\n",recTrigTrack);
                        }
                    }
+                   else if(fDebugLevel>=1) printf("Track = %p: Particle crossed different slats: rejected!\n",recTrigTrack);
+                   //cout<<"fTrigger44["<<cath<<"] = "<<fTrigger44[cath]<<"\tfHitPerSlat["<<0<<"]["<<cath<<"]["<<firstSlat<<"] = "<<fHitPerSlat[0][cath][firstSlat]<<"\tfHitPerBoard["<<0<<"]["<<cath<<"]["<<firstBoard-1<<"] = "<<fHitPerBoard[0][cath][firstBoard-1]<<endl; //REMEMBER TO CUT
                }
-               else if(doubleCountTrack){
-                   if(fDebugLevel<=1)printf("\n\tEvent = %i, Track = %i: ", ievent,iRecTrigTrack);
-                   printf("Double Count Track: %i similar to %i. Track rejected!\n",iRecTrigTrack, doubleTrack);
+
+               // Trigger 3/4
+               if(ineffDetElId>0){
+                   Int_t ineffCh = ineffDetElId/100-11;
+                   fTrigger34[ineffCh][cath]++;
+                   if(fDebugLevel>=1) printf("Trigger34[%i][%i] = %i\n",ineffCh,cath,fTrigger34[ineffCh][cath]);
+                   if(goodForSlatEff){
+                       if(fDebugLevel>=1) printf("Slat non efficient = %i\n",ineffDetElId);
+                       fInefficientSlat[ineffCh][cath][ineffSlat]++;
+
+                       if(goodForBoardEff && firstBoard>0){
+                           if(fDebugLevel>=1) printf("Board non efficient = %i\n",firstBoard);
+                           fInefficientBoard[ineffCh][cath][firstBoard-1]++;
+                       }
+                       else if(fDebugLevel>=1) printf("Track = %p: Particle crossed different boards: rejected!\n",recTrigTrack);
+                   }
+                   else if(fDebugLevel>=1) printf("Track = %p: Particle crossed different slats: rejected!\n",recTrigTrack);
+                   //cout<<"fTrigger34["<<ineffCh<<"]["<<cath<<"] = "<<fTrigger34[ineffCh][cath]<<"\tfInefficientSlat["<<ineffCh<<"]["<<cath<<"]["<<ineffSlat<<"] = "<<fInefficientSlat[ineffCh][cath][ineffSlat]<<"\tfInefficientBoard["<<ineffCh<<"]["<<cath<<"]["<<firstBoard-1<<"] = "<<fInefficientBoard[ineffCh][cath][firstBoard-1]<<endl; //REMEMBER TO CUT
                }
-           }
-       }// end trigger tracks loop
-       if(nRecTrigTracks<=0){ 
-           fData->ResetDigits();
-           continue;
-       }
-       for(Int_t ch=0; ch<fgkNchambers; ch++){
-           for(Int_t cath=0; cath<fgkNcathodes; cath++){
-               totNumOfTrig[ch][cath] += partNumOfTrig[ch][cath];
-               if(partNumOfTrig[ch][cath]>0)atLeast1MuPerEv[ch][cath]++;
-           }
+           } // end loop on cathodes
        }
-
-       if(fPrintInfo){
-           //Global trigger
-           globalTrigger = fData->GlobalTrigger();
-           Int_t nglobals = (Int_t) globalTrigger->GetEntriesFast(); // should be 1
-
-           for (Int_t iglobal=0; iglobal<nglobals; iglobal++) { // Global Trigger
-               gloTrg = (AliMUONGlobalTrigger*)globalTrigger->At(iglobal);
-           }
-           PrintTrigger(gloTrg);
-           InfoDigit();
-           cout<<"\n"<<endl;
+       else if(doubleCountTrack){
+           if(fDebugLevel>=1)
+               printf("\n\tTrack = %p: \nDouble Count Track: Track rejected!\n",recTrigTrack);
        }
+    } // end trigger tracks loop
 
-       fData->ResetDigits();
-    }// end event loop
-    if(fFirstRun>=0)CleanGalice();
-    } //end loop over run
-    
-    // Write output data
-    WriteEfficiencyMap(outputDir);
-
-    WriteOutput(outputDir, totNumOfTrig, atLeast1MuPerEv);
+    if(fPrintInfo) InfoDigit(digitStore);
 }
 
 //_____________________________________________________________________________
-void AliMUONTriggerChamberEff::WriteOutput(const char* outputDir, Int_t totNumOfTrig[4][2], Int_t atLeast1MuPerEv[4][2])
+void AliMUONTriggerChamberEff::WriteEfficiencyMap(const char* outputDir)
 {
     //
     /// Writes information on calculated efficiency.
     /// It writes: triggerChamberEff.root file containing efficiency histograms.
-    ///
-    /// In addition a text file triggerChamberEff.out is created,
-    /// with further informations on efficiencies.
     //
 
-    char *cathodeName[fgkNcathodes]={"Bending plane", "Non-Bending plane"};
     char *cathCode[fgkNcathodes] = {"bendPlane", "nonBendPlane"};
 
     char outFileName[100];
-    sprintf(outFileName, "%s/triggerChamberEff.out",outputDir);
-    FILE *outfile = fopen(outFileName, "w");
-    for(Int_t cath=0; cath<fgkNcathodes; cath++){
-       fprintf(outfile,"%s:\n",cathodeName[cath]);
-       for(Int_t ch=0; ch<fgkNchambers; ch++){
-           fprintf(outfile,"Total number of muon triggers chamber 1%i = %i\n",ch+1,totNumOfTrig[ch][cath]);
-       }
-       fprintf(outfile,"\n");
-    }
-    fprintf(outfile,"\n");
-    for(Int_t cath=0; cath<fgkNcathodes; cath++){
-       fprintf(outfile,"%s:\n",cathodeName[cath]);
-       for(Int_t ch=0; ch<fgkNchambers; ch++){
-           fprintf(outfile,"At least 1 muon triggered chamber 1%i = %i\n",ch+1, atLeast1MuPerEv[ch][cath]);
-       }
-       fprintf(outfile,"\n");
-    }
-    fprintf(outfile,"\n\n");
-    for(Int_t cath=0; cath<fgkNcathodes; cath++){
-       fprintf(outfile,"%s:\n",cathodeName[cath]);
-       fprintf(outfile,"Number of triggers where all chambers counted = %i\n",fTrigger44[cath]);
-       fprintf(outfile,"\n");
-    }
-    fprintf(outfile,"\n");
-    for(Int_t cath=0; cath<fgkNcathodes; cath++){
-       fprintf(outfile,"%s:\n",cathodeName[cath]);
-       for(Int_t ch=0; ch<fgkNchambers; ch++){
-           fprintf(outfile,"Number of triggers where chamber 1%i did not count = %i\n",ch+1,fTrigger34[ch][cath]);
-       }
-       fprintf(outfile,"\n");
-    }
-
-    fprintf(outfile,"\n");
-    for(Int_t cath=0; cath<fgkNcathodes; cath++){
-       fprintf(outfile,"%s:\n",cathodeName[cath]);
-       for(Int_t ch=0; ch<fgkNchambers; ch++){
-           Int_t sumIneff = 0, sumHits = 0;
-           fprintf(outfile,"\n Chamber %1i\n", ch+1);
-           for(Int_t slat=0; slat<fgkNslats; slat++){
-               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]);
-               sumIneff += fInefficientSlat[ch][cath][slat];
-               sumHits += fHitPerSlat[ch][cath][slat];
-           }
-           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);
-       }
-       fprintf(outfile,"\n");
-    }
-    fclose(outfile);
 
-    sprintf(outFileName, "%s/triggerChamberEff.root",outputDir);
+    sprintf(outFileName, "%s/MUON.TriggerEfficiencyMap.root",outputDir);
     TFile *outputHistoFile = new TFile(outFileName,"RECREATE");
     TDirectory *dir = gDirectory;
 
@@ -821,7 +747,15 @@ void AliMUONTriggerChamberEff::WriteOutput(const char* outputDir, Int_t totNumOf
     TH1F *histo[fgkNcathodes][fgkNchambers+1];
     TH1F *histoBoard[fgkNcathodes][fgkNchambers];
 
-    char histoName[30];
+    // ADDED for check
+    enum {allChEff, chNonEff, numOfHistoTypes};
+    char *histoTypeName[numOfHistoTypes] = {"CountInCh", "NonCountInCh"};
+    char *histoTypeTitle[numOfHistoTypes] = {"counted", "non counted"};
+    TH1F *histoCheckSlat[fgkNcathodes][fgkNchambers][numOfHistoTypes];
+    TH1F *histoCheckBoard[fgkNcathodes][fgkNchambers][numOfHistoTypes];
+    // end ADDED for check
+
+    char histoName[40];
     char histoTitle[90];
 
     for(Int_t cath=0; cath<fgkNcathodes; cath++){
@@ -848,27 +782,57 @@ void AliMUONTriggerChamberEff::WriteOutput(const char* outputDir, Int_t totNumOf
                histoBoard[cath][ch]->SetXTitle("boards");
                histoBoard[cath][ch]->SetYTitle(yAxisTitle);
                histoBoard[cath][ch]->GetXaxis()->SetNdivisions(fgkNboards);
+
+               // ADDED for check
+               for(Int_t hType=0; hType<numOfHistoTypes; hType++){
+                   sprintf(histoName, "%sSlat%s%i", cathCode[cath], histoTypeName[hType], 11+ch);
+                   sprintf(histoTitle, "Chamber %i: slat %s %s", 11+ch, histoTypeTitle[hType], cathCode[cath]);
+                   histoCheckSlat[cath][ch][hType] = new TH1F(histoName, histoTitle, fgkNslats, 0-0.5, fgkNslats-0.5);
+                   histoCheckSlat[cath][ch][hType]->SetXTitle("slat");
+                   histoCheckSlat[cath][ch][hType]->SetYTitle(yAxisTitle);
+                   histoCheckSlat[cath][ch][hType]->GetXaxis()->SetNdivisions(fgkNslats);
+
+                   sprintf(histoName, "%sBoard%s%i", cathCode[cath], histoTypeName[hType], 11+ch);
+                   sprintf(histoTitle, "Chamber %i: board %s %s", 11+ch, histoTypeTitle[hType], cathCode[cath]);
+                   histoCheckBoard[cath][ch][hType] = new TH1F(histoName, histoTitle, fgkNboards, 1-0.5, fgkNboards+1.-0.5);
+                   histoCheckBoard[cath][ch][hType]->SetXTitle("boards");
+                   histoCheckBoard[cath][ch][hType]->SetYTitle(yAxisTitle);
+                   histoCheckBoard[cath][ch][hType]->GetXaxis()->SetNdivisions(fgkNboards);
+               }
+               // end ADDED for check
            }
        }
     }
 
     Float_t efficiency, efficiencyError;
+    Int_t bin;
 
     for(Int_t cath=0; cath<fgkNcathodes; cath++){
        for(Int_t ch=0; ch<fgkNchambers; ch++){
            for(Int_t slat=0; slat<fgkNslats; slat++){
                CalculateEfficiency(fHitPerSlat[ch][cath][slat], fHitPerSlat[ch][cath][slat]+fInefficientSlat[ch][cath][slat], efficiency, efficiencyError, kFALSE);
-               histo[cath][ch]->SetBinContent(slat+1, efficiency);
-               histo[cath][ch]->SetBinError(slat+1, efficiencyError);
+               bin = histo[cath][ch]->FindBin(slat);
+               histo[cath][ch]->SetBinContent(bin, efficiency);
+               histo[cath][ch]->SetBinError(bin, efficiencyError);
+
+               // ADDED for check
+               histoCheckSlat[cath][ch][allChEff]->SetBinContent(bin, fHitPerSlat[ch][cath][slat]);
+               histoCheckSlat[cath][ch][chNonEff]->SetBinContent(bin, fInefficientSlat[ch][cath][slat]);
            }
            CalculateEfficiency(fTrigger44[cath], fTrigger34[ch][cath]+fTrigger44[cath], efficiency, efficiencyError, kFALSE);
-           histo[cath][kChamberEff]->SetBinContent(ch+1, efficiency);
-           histo[cath][kChamberEff]->SetBinError(ch+1, efficiencyError);
+           bin = histo[cath][ch]->FindBin(11+ch);
+           histo[cath][kChamberEff]->SetBinContent(bin, efficiency);
+           histo[cath][kChamberEff]->SetBinError(bin, efficiencyError);
 
            for(Int_t board=0; board<fgkNboards; board++){
                CalculateEfficiency(fHitPerBoard[ch][cath][board], fHitPerBoard[ch][cath][board]+fInefficientBoard[ch][cath][board], efficiency, efficiencyError, kFALSE);
-               histoBoard[cath][ch]->SetBinContent(board+1, efficiency);
-               histoBoard[cath][ch]->SetBinError(board+1, efficiencyError);
+               bin = histoBoard[cath][ch]->FindBin(board+1);
+               histoBoard[cath][ch]->SetBinContent(bin, efficiency);
+               histoBoard[cath][ch]->SetBinError(bin, efficiencyError);
+
+               // ADDED for check
+               histoCheckBoard[cath][ch][allChEff]->SetBinContent(bin, fHitPerBoard[ch][cath][board]);
+               histoCheckBoard[cath][ch][chNonEff]->SetBinContent(bin, fInefficientBoard[ch][cath][board]);
            }
        }
     }
@@ -881,7 +845,7 @@ void AliMUONTriggerChamberEff::WriteOutput(const char* outputDir, Int_t totNumOf
 
 
 //_____________________________________________________________________________
-void AliMUONTriggerChamberEff::WriteEfficiencyMap(const char* outputDir)
+void AliMUONTriggerChamberEff::WriteEfficiencyMapTxt(const char* outputDir)
 {
     //
     /// Writes the calculated efficiency in the text file efficiencyCells.dat
@@ -921,3 +885,70 @@ void AliMUONTriggerChamberEff::WriteEfficiencyMap(const char* outputDir)
     }// loop on chambers    
 }
 
+
+//_____________________________________________________________________________
+Bool_t AliMUONTriggerChamberEff::IsCleanTrack(AliMUONTriggerTrack *triggerTrack,
+                                             const AliMUONVTrackStore& trackStore)
+{
+    //
+    /// Try to match track from tracking system with trigger track
+    //
+    const Double_t kDistSigma[3]={1,1,0.02}; // sigma of distributions (trigger-track) X,Y,slopeY
+    const Double_t kMaxChi2MatchTrigger = 16.0;
+  
+    AliMUONTrackParam trackParam; 
+
+    Double_t distTriggerTrack[3];
+    Double_t xTrack, yTrack, ySlopeTrack, chi2;
+  
+    AliMUONTrack* track;
+    TIter next(trackStore.CreateIterator());
+    
+    while ( ( track = static_cast<AliMUONTrack*>(next()) ) )
+    {
+       trackParam = *((AliMUONTrackParam*) (track->GetTrackParamAtHit()->Last()));
+       AliMUONTrackExtrap::ExtrapToZ(&trackParam, AliMUONConstants::DefaultChamberZ(10)); // extrap to 1st trigger chamber
+    
+       xTrack = trackParam.GetNonBendingCoor();
+       yTrack = trackParam.GetBendingCoor();
+       ySlopeTrack = trackParam.GetBendingSlope();
+  
+       distTriggerTrack[0] = (triggerTrack->GetX11()-xTrack)/kDistSigma[0];
+       distTriggerTrack[1] = (triggerTrack->GetY11()-yTrack)/kDistSigma[1];
+       distTriggerTrack[2] = (TMath::Tan(triggerTrack->GetThetay())-ySlopeTrack)/kDistSigma[2];
+       chi2 = 0.;
+       for (Int_t iVar = 0; iVar < 3; iVar++) chi2 += distTriggerTrack[iVar]*distTriggerTrack[iVar];
+       chi2 /= 3.; // Normalized Chi2: 3 degrees of freedom (X,Y,slopeY)
+       if (chi2 < kMaxChi2MatchTrigger) return kTRUE;
+    }
+
+    return kFALSE;
+}
+
+
+//_____________________________________________________________________________
+void AliMUONTriggerChamberEff::SaveInESDFile()
+{
+    //
+    /// Store AliMUONTriggerChamberEff in esd file
+    //
+    TDirectory *dir = gDirectory;
+    TFile *logFile = 0x0;
+    TSeqCollection *list = gROOT->GetListOfFiles();
+    Int_t n = list->GetEntries();
+    for(Int_t i=0; i<n; i++) {
+       logFile = (TFile*)list->At(i);
+       if (strstr(logFile->GetName(), "AliESDs.root")) break;
+    }
+    if(logFile){
+       TTree *esdTree = (TTree*)logFile->Get("esdTree");
+       if(esdTree){
+           if(!esdTree->GetUserInfo()->FindObject("AliMUONTriggerChamberEff")){
+               AliInfo(Form("Adding AliMUONTrigChamberEff in %s",logFile->GetName()));
+               esdTree->GetUserInfo()->Add(this->Clone());
+               esdTree->Write("",TObject::kOverwrite);
+           }
+       }
+    }
+    dir->cd();
+}