]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - PWG/CaloTrackCorrBase/AliCaloTrackReader.cxx
Add condition to select events with at least one track
[u/mrichter/AliRoot.git] / PWG / CaloTrackCorrBase / AliCaloTrackReader.cxx
index d2899537fcb29c1b715a056f5a6a5fc651bcd04f..ce26e5b9f193697c03694cf184f014871184a66a 100755 (executable)
@@ -44,6 +44,7 @@
 #include "AliVCaloCells.h"
 #include "AliAnalysisManager.h"
 #include "AliInputEventHandler.h"
+#include "AliAODMCParticle.h"
 
 // ---- Detectors ----
 #include "AliPHOSGeoUtils.h"
@@ -63,9 +64,14 @@ TObject(),                   fEventNumber(-1), //fCurrentFileName(""),
 fDataType(0),                fDebug(0), 
 fFiducialCut(0x0),           fCheckFidCut(kFALSE), 
 fComparePtHardAndJetPt(0),   fPtHardAndJetPtFactor(0),
+fComparePtHardAndClusterPt(0),fPtHardAndClusterPtFactor(0),
 fCTSPtMin(0),                fEMCALPtMin(0),                  fPHOSPtMin(0), 
-fCTSPtMax(0),                fEMCALPtMax(0),                  fPHOSPtMax(0), 
+fCTSPtMax(0),                fEMCALPtMax(0),                  fPHOSPtMax(0),
+fUseEMCALTimeCut(1),         fUseParamTimeCut(0),             fUseTrackTimeCut(0),
 fEMCALTimeCutMin(-10000),    fEMCALTimeCutMax(10000),
+fEMCALParamTimeCutMin(),     fEMCALParamTimeCutMax(),
+fTrackTimeCutMin(-10000),    fTrackTimeCutMax(10000),
+fUseTrackDCACut(0),
 fAODBranchList(0x0),
 fCTSTracks(0x0),             fEMCALClusters(0x0),             fPHOSClusters(0x0),
 fEMCALCells(0x0),            fPHOSCells(0x0),
@@ -74,22 +80,30 @@ fFillCTS(0),                 fFillEMCAL(0),                   fFillPHOS(0),
 fFillEMCALCells(0),          fFillPHOSCells(0), 
 fRecalculateClusters(kFALSE),fSelectEmbeddedClusters(kFALSE),
 fTrackStatus(0),             fTrackFilterMask(0),             
-fESDtrackCuts(0),            fConstrainTrack(kFALSE),          fSelectHybridTracks(0),
-fTrackMult(0),               fTrackMultEtaCut(0.8),
+fESDtrackCuts(0),            fESDtrackComplementaryCuts(0),   fConstrainTrack(kFALSE),
+fSelectHybridTracks(0),      fSelectSPDHitTracks(kFALSE),
+fTrackMult(0),               fTrackMultEtaCut(0.9),
 fReadStack(kFALSE),          fReadAODMCParticles(kFALSE), 
 fDeltaAODFileName(""),       fFiredTriggerClassName(""),      
-fEventTriggerMask(0),        fEventTriggerAtSE(0), 
+fEventTriggerMask(0),        fMixEventTriggerMask(0),         fEventTriggerAtSE(0), 
 fAnaLED(kFALSE),
 fTaskName(""),               fCaloUtils(0x0), 
 fMixedEvent(NULL),           fNMixedEvent(0),                 fVertex(NULL), 
-fListMixedTracksEvents(),    //fListMixedPhotonsEvents(),
-fLastMixedTracksEvent(-1),   //fLastMixedPhotonsEvent(-1),
+fListMixedTracksEvents(),    fListMixedCaloEvents(),
+fLastMixedTracksEvent(-1),   fLastMixedCaloEvent(-1),
 fWriteOutputDeltaAOD(kFALSE),fOldAOD(kFALSE),                 fCaloFilterPatch(kFALSE),
 fEMCALClustersListName(""),  fZvtxCut(0.),                    
 fAcceptFastCluster(kFALSE),  fRemoveLEDEvents(kTRUE), 
-fDoEventSelection(kFALSE),   fDoV0ANDEventSelection(kFALSE),  fUseEventsWithPrimaryVertex(kFALSE),
-fTriggerAnalysis (0x0), 
-fCentralityClass(""),        fCentralityOpt(0),
+fDoEventSelection(kFALSE),   fDoV0ANDEventSelection(kFALSE),
+fDoVertexBCEventSelection(kFALSE),
+fDoRejectNoTrackEvents(kFALSE),
+fUseEventsWithPrimaryVertex(kFALSE),
+fTriggerAnalysis (0x0),      fTimeStampEventSelect(0),
+fTimeStampEventFracMin(0),   fTimeStampEventFracMax(0),
+fTimeStampRunMin(0),         fTimeStampRunMax(0),
+fNPileUpClusters(-1),        fNNonPileUpClusters(-1),         fNPileUpClustersCut(3),
+fVertexBC(-200),             fRecalculateVertexBC(0),
+fCentralityClass(""),            fCentralityOpt(0),
 fEventPlaneMethod(""),       fImportGeometryFromFile(kFALSE), fImportGeometryFilePath("")
 {
   //Ctor
@@ -143,6 +157,7 @@ AliCaloTrackReader::~AliCaloTrackReader()
        }
   
   delete fESDtrackCuts;
+  delete fESDtrackComplementaryCuts;
   delete fTriggerAnalysis;
   
   //  Pointers not owned, done by the analysis frame
@@ -154,12 +169,27 @@ AliCaloTrackReader::~AliCaloTrackReader()
   
 }
 
+//________________________________________________________________________
+Bool_t  AliCaloTrackReader::AcceptDCA(const Float_t pt, const Float_t dca)
+{
+  // Accept track if DCA is smaller than function
+  
+  Float_t cut = fTrackDCACut[0]+fTrackDCACut[1]/TMath::Power(pt,fTrackDCACut[2]);
+  
+  if(TMath::Abs(dca) < cut)
+    return kTRUE;
+  else
+    return kFALSE;
+  
+}
+
 //________________________________________________
 Bool_t AliCaloTrackReader::ComparePtHardAndJetPt()
 {
-  // Check the event, if the requested ptHard is much larger than the jet pT, then there is a problem.
+  // Check the event, if the requested ptHard is much smaller than the jet pT, then there is a problem.
   // Only for PYTHIA.
-  if(!fReadStack) return kTRUE; //Information not filtered to AOD
+  
+  //printf("AliCaloTrackReader::ComparePtHardAndJetPt() - GenHeaderName : %s\n",GetGenEventHeader()->ClassName());
   
   if(!strcmp(GetGenEventHeader()->ClassName(), "AliGenPythiaEventHeader"))
   {
@@ -168,21 +198,27 @@ Bool_t AliCaloTrackReader::ComparePtHardAndJetPt()
     Int_t nTriggerJets =  pygeh->NTriggerJets();
     Float_t ptHard = pygeh->GetPtHard();
     
-    //if(fDebug > 1) printf("AliMCAnalysisUtils::PythiaEventHeader: Njets: %d, pT Hard %f\n",nTriggerJets, ptHard);
+    if(fDebug > 1) 
+      printf("AliCaloTrackReader::ComparePtHardAndJetPt() - Njets: %d, pT Hard %f\n",nTriggerJets, ptHard);
+    
     Float_t tmpjet[]={0,0,0,0};
     for(Int_t ijet = 0; ijet< nTriggerJets; ijet++)
     {
       pygeh->TriggerJet(ijet, tmpjet);
       jet = new TParticle(94, 21, -1, -1, -1, -1, tmpjet[0],tmpjet[1],tmpjet[2],tmpjet[3], 0,0,0,0);
+      
+      if(fDebug > 1) 
+        printf("AliCaloTrackReader::ComparePtHardAndJetPt() - jet %d; pycell jet pT %f\n",ijet, jet->Pt());
+      
       //Compare jet pT and pt Hard
-      //if(fDebug > 1) printf("AliMCAnalysisUtils:: %d pycell jet pT %f\n",ijet, jet->Pt());
       if(jet->Pt() > fPtHardAndJetPtFactor * ptHard)
       {
-        printf("AliMCAnalysisUtils::PythiaEventHeader: Njets: %d, pT Hard %2.2f, pycell jet pT %2.2f, rejection factor %1.1f\n",
-               nTriggerJets, ptHard, jet->Pt(), fPtHardAndJetPtFactor);
+        printf("AliCaloTrackReader::ComparePtHardAndJetPt() - Reject jet event with : pT Hard %2.2f, pycell jet pT %2.2f, rejection factor %1.1f\n",
+                ptHard, jet->Pt(), fPtHardAndJetPtFactor);
         return kFALSE;
       }
     }
+    
     if(jet) delete jet; 
   }
   
@@ -190,6 +226,75 @@ Bool_t AliCaloTrackReader::ComparePtHardAndJetPt()
   
 }
 
+//____________________________________________________________________
+Bool_t AliCaloTrackReader::ComparePtHardAndClusterPt()
+{
+  // Check the event, if the requested ptHard is smaller than the calorimeter cluster E, then there is a problem.
+  // Only for PYTHIA.
+  
+  if(!strcmp(GetGenEventHeader()->ClassName(), "AliGenPythiaEventHeader"))
+  {
+    AliGenPythiaEventHeader* pygeh= (AliGenPythiaEventHeader*) GetGenEventHeader();
+    Float_t ptHard = pygeh->GetPtHard();
+    
+    Int_t nclusters = fInputEvent->GetNumberOfCaloClusters();
+    for (Int_t iclus =  0; iclus <  nclusters; iclus++) 
+    {
+      AliVCluster * clus = fInputEvent->GetCaloCluster(iclus) ; 
+      Float_t ecluster = clus->E();
+      
+      if(ecluster > fPtHardAndClusterPtFactor*ptHard) 
+      {
+        printf("AliCaloTrackReader::ComparePtHardAndClusterPt() - Reject : ecluster %2.2f, calo %d, factor %2.2f, ptHard %f\n",ecluster,clus->GetType(),fPtHardAndClusterPtFactor,ptHard);
+
+        return kFALSE;
+      }
+    }
+    
+  }
+  
+  return kTRUE ;
+  
+}
+
+//_________________________________________________________________
+void AliCaloTrackReader::CorrectMCLabelForAODs(AliVCluster * clus)
+{
+ // AODs filter particles, not anymore correspondance with MC position in array
+ // Check if label is correct and if not, change it
+  
+  Int_t * labels = clus->GetLabels();
+
+  for(UInt_t ilabel = 0; ilabel < clus->GetNLabels(); ilabel++)
+  {
+    Int_t orgLabel = labels[ilabel];
+        
+    TClonesArray * arr = GetAODMCParticles()  ;
+        
+    if(!arr)
+    {
+      printf("AliCaloTrackReader::CorrectMCLabelForAODs() - Input array not available\n");
+      return ;
+    }
+    
+    AliAODMCParticle *  particle = (AliAODMCParticle *)arr->At(orgLabel);
+    
+    if(orgLabel != particle->Label())
+    {
+      // loop on the particles list and check if there is one with the same label
+      for(Int_t ind = 0; ind < arr->GetEntriesFast(); ind++ )
+      {
+        particle = (AliAODMCParticle *) arr->At(ind);
+        
+        if(orgLabel == particle->Label()) labels[ilabel] = ind;
+      }
+    }
+    
+    //if(orgLabel!=labels[ilabel]) printf("\t Label in %d - out %d \n",orgLabel, clus->GetLabels()[ilabel]);
+    
+  }
+}
+
 //____________________________________________
 AliStack* AliCaloTrackReader::GetStack() const 
 {
@@ -236,35 +341,39 @@ AliHeader* AliCaloTrackReader::GetHeader() const
 AliGenEventHeader* AliCaloTrackReader::GetGenEventHeader() const 
 {
   //Return pointer to Generated event header
-  if(fMC)
+  if     (ReadStack() && fMC)
   {
     return fMC->GenEventHeader();
   }
-  else
+  else if(ReadAODMCParticles() && GetAODMCHeader())
   {
-    printf("AliCaloTrackReader::GenEventHeader is not available\n"); 
-    return 0x0 ;
+    //printf("AliCaloTrackReader::GetGenEventHeader() - N headers %d\n",GetAODMCHeader()->GetNCocktailHeaders());
+    if( GetAODMCHeader()->GetNCocktailHeaders() > 0)
+      return GetAODMCHeader()->GetCocktailHeader(0) ;
+    else 
+      return 0x0;
+  }
+  else 
+  {
+    //printf("AliCaloTrackReader::GetGenEventHeader() - MC header not available! \n");
+    return 0;
   }
 }
 
 //____________________________________________________________________
-TClonesArray* AliCaloTrackReader::GetAODMCParticles(Int_t input) const 
+TClonesArray* AliCaloTrackReader::GetAODMCParticles() const 
 {
   //Return list of particles in AOD. Do it for the corresponding input event.
   
   TClonesArray * rv = NULL ; 
   if(fDataType == kAOD)
   {
-    if(input == 0)
-    {
-      //Normal input AOD
-      AliAODEvent * evt = dynamic_cast<AliAODEvent*> (fInputEvent) ;
-      if(evt)
-        rv = (TClonesArray*)evt->FindListObject("mcparticles");
-      else  
-        printf("AliCaloTrackReader::GetAODMCParticles() - wrong AOD input index? %d, or non existing tree? \n",input); 
-    }  
-    
+    //Normal input AOD
+    AliAODEvent * evt = dynamic_cast<AliAODEvent*> (fInputEvent) ;
+    if(evt)
+      rv = (TClonesArray*)evt->FindListObject("mcparticles");
+    else  
+      printf("AliCaloTrackReader::GetAODMCParticles() - Null AOD event \n"); 
   } 
   else 
   {
@@ -274,8 +383,8 @@ TClonesArray* AliCaloTrackReader::GetAODMCParticles(Int_t input) const
   return rv ; 
 }
 
-//___________________________________________________________________
-AliAODMCHeader* AliCaloTrackReader::GetAODMCHeader(Int_t input) const 
+//________________________________________________________
+AliAODMCHeader* AliCaloTrackReader::GetAODMCHeader() const 
 {
   //Return MC header in AOD. Do it for the corresponding input event.
   
@@ -283,15 +392,8 @@ AliAODMCHeader* AliCaloTrackReader::GetAODMCHeader(Int_t input) const
   
   if(fDataType == kAOD)
   {
-    //Normal input AOD
-    if(input == 0) 
-    {
-      mch = (AliAODMCHeader*)((AliAODEvent*)fInputEvent)->FindListObject("mcheader");
-    }
-    else 
-    {
-      printf("AliCaloTrackReader::GetAODMCHeader() - wrong AOD input index, %d\n",input);
-    }
+    AliAODEvent * aod = dynamic_cast<AliAODEvent*> (fInputEvent);
+    if(aod) mch = dynamic_cast<AliAODMCHeader*>(aod->FindListObject("mcHeader"));
   }
   else 
   {
@@ -301,6 +403,54 @@ AliAODMCHeader* AliCaloTrackReader::GetAODMCHeader(Int_t input) const
   return mch;
 }
 
+//___________________________________________________________
+Int_t AliCaloTrackReader::GetVertexBC(const AliVVertex * vtx)
+{
+  // Get the vertex BC
+    
+  Int_t vertexBC=vtx->GetBC();
+  if(!fRecalculateVertexBC) return vertexBC;
+  
+  // In old AODs BC not stored, recalculate it
+  // loop over the global track and select those which have small DCA to primary vertex (e.g. primary).
+  // If at least one of these primaries has valid BC != 0, then this vertex is a pile-up candidate.
+  // Execute after CTS
+  Double_t bz  = fInputEvent->GetMagneticField();
+  Bool_t   bc0 = kFALSE;
+  Int_t    ntr = GetCTSTracks()->GetEntriesFast();
+  //printf("N Tracks %d\n",ntr);
+  
+  for(Int_t i = 0 ; i < ntr ; i++)
+  {
+    AliVTrack * track =  (AliVTrack*) (GetCTSTracks()->At(i));
+    
+    //Check if has TOF info, if not skip
+    ULong_t status  = track->GetStatus();
+    Bool_t  okTOF   = (status & AliVTrack::kTOFout) == AliVTrack::kTOFout ;
+    vertexBC        = track->GetTOFBunchCrossing(bz);
+    Float_t pt      = track->Pt();
+    
+    if(!okTOF) continue;
+    
+    // Get DCA x, y
+    Double_t dca[2]   = {1e6,1e6};
+    Double_t covar[3] = {1e6,1e6,1e6};
+    track->PropagateToDCA(vtx,bz,100.,dca,covar);
+    
+    if(AcceptDCA(pt,dca[0]))
+    {
+      if     (vertexBC !=0 && fVertexBC != AliVTrack::kTOFBCNA) return vertexBC;
+      else if(vertexBC == 0)                                    bc0 = kTRUE;
+    }
+  }
+  
+  if( bc0 ) vertexBC = 0 ;
+  else      vertexBC = AliVTrack::kTOFBCNA ;
+  
+  return vertexBC;
+  
+}
+
 //_____________________________
 void AliCaloTrackReader::Init()
 {
@@ -319,12 +469,15 @@ void AliCaloTrackReader::Init()
   if(fImportGeometryFromFile && !gGeoManager) 
   {
     if(fImportGeometryFilePath=="") // If not specified, set a default location
-    fImportGeometryFilePath = "$ALICE_ROOT/PWGGA/EMCALTasks/macros/geometry.root"; // "$ALICE_ROOT/EVE/alice-data/default_geo.root"
+    fImportGeometryFilePath = "$ALICE_ROOT/OADB/EMCAL/geometry_2011.root"; // "$ALICE_ROOT/EVE/alice-data/default_geo.root"
 
     printf("AliCaloTrackReader::Init() - Import %s\n",fImportGeometryFilePath.Data());
     TGeoManager::Import(fImportGeometryFilePath) ; // default need file "geometry.root" in local dir!!!!
   }
 
+  if(!fESDtrackCuts)
+    fESDtrackCuts = AliESDtrackCuts::GetStandardTPCOnlyTrackCuts(); //initialize with TPC only tracks
+
 }
 
 //_______________________________________
@@ -339,6 +492,12 @@ void AliCaloTrackReader::InitParameters()
   fEMCALPtMax = 1000. ;
   fPHOSPtMax  = 1000. ;
   
+  //Track DCA cuts
+  // dca_xy cut = 0.0105+0.0350/TMath::Power(pt,1.1);
+  fTrackDCACut[0] = 0.0105; 
+  fTrackDCACut[1] = 0.0350; 
+  fTrackDCACut[2] = 1.1;
+  
   //Do not filter the detectors input by default.
   fFillEMCAL      = kFALSE;
   fFillPHOS       = kFALSE;
@@ -351,6 +510,7 @@ void AliCaloTrackReader::InitParameters()
   fDeltaAODFileName      = "deltaAODPartCorr.root";
   fFiredTriggerClassName = "";
   fEventTriggerMask      = AliVEvent::kAny;
+  fMixEventTriggerMask   = AliVEvent::kAnyINT;
   fEventTriggerAtSE      = kTRUE; // Use only events that pass event selection at SE base class
   
   fAcceptFastCluster = kTRUE;
@@ -362,7 +522,8 @@ void AliCaloTrackReader::InitParameters()
   fTrackStatus     = 0;
   fTrackFilterMask = 128; //For AODs, but what is the difference between fTrackStatus and fTrackFilterMask?
   
-  fESDtrackCuts = AliESDtrackCuts::GetStandardTPCOnlyTrackCuts(); //initialize with TPC only tracks 
+  fESDtrackCuts = 0;
+  fESDtrackComplementaryCuts = 0;
   
   fConstrainTrack = kFALSE ; // constrain tracks to vertex
   
@@ -373,8 +534,9 @@ void AliCaloTrackReader::InitParameters()
   
   fNMixedEvent = 1;
   
-  fPtHardAndJetPtFactor = 7;
-  
+  fPtHardAndJetPtFactor     = 7.;
+  fPtHardAndClusterPtFactor = 1.;
+
   //Centrality
   fCentralityClass  = "V0M";
   fCentralityOpt    = 10;
@@ -391,6 +553,109 @@ void AliCaloTrackReader::InitParameters()
 
   fImportGeometryFromFile = kFALSE;
   
+  fPileUpParamSPD[0] = 3   ; fPileUpParamSPD[1] = 0.8 ;
+  fPileUpParamSPD[2] = 3.0 ; fPileUpParamSPD[3] = 2.0 ; fPileUpParamSPD[4] = 5.0;
+  
+  // Parametrized time cut (LHC11d)
+  fEMCALParamTimeCutMin[0] =-5; fEMCALParamTimeCutMin[1] =-1 ; fEMCALParamTimeCutMin[2] = 3.5 ; fEMCALParamTimeCutMin[3] = 1.  ;   
+  fEMCALParamTimeCutMax[0] = 5; fEMCALParamTimeCutMax[1] = 50; fEMCALParamTimeCutMax[2] = 0.45; fEMCALParamTimeCutMax[3] = 1.25;   
+
+  // Parametrized time cut (LHC11c)
+  //fEMCALParamTimeCutMin[0] =-5;   fEMCALParamTimeCutMin[1] =-1 ; fEMCALParamTimeCutMin[2] = 1.87; fEMCALParamTimeCutMin[3] = 0.4;   
+  //fEMCALParamTimeCutMax[0] = 3.5; fEMCALParamTimeCutMax[1] = 50; fEMCALParamTimeCutMax[2] = 0.15; fEMCALParamTimeCutMax[3] = 1.6;
+  
+  fTimeStampRunMin = -1;
+  fTimeStampRunMax = 1e12;
+  fTimeStampEventFracMin = -1;
+  fTimeStampEventFracMax = 2;
+
+  for(Int_t i = 0; i < 19; i++)
+  {
+    fEMCalBCEvent   [i] = 0;
+    fEMCalBCEventCut[i] = 0;
+    fTrackBCEvent   [i] = 0;
+    fTrackBCEventCut[i] = 0;
+  }
+  
+}
+
+//___________________________________________________________
+Bool_t AliCaloTrackReader::IsInTimeWindow(const Double_t tof, const Float_t energy) const
+{
+  // Cluster time selection window
+  
+  // Parametrized cut depending on E
+  if(fUseParamTimeCut)
+  {
+    Float_t minCut= fEMCALParamTimeCutMin[0]+fEMCALParamTimeCutMin[1]*TMath::Exp(-(energy-fEMCALParamTimeCutMin[2])/fEMCALParamTimeCutMin[3]);
+    Float_t maxCut= fEMCALParamTimeCutMax[0]+fEMCALParamTimeCutMax[1]*TMath::Exp(-(energy-fEMCALParamTimeCutMax[2])/fEMCALParamTimeCutMax[3]);
+    //printf("tof %f, minCut %f, maxCut %f\n",tof,minCut,maxCut);
+    if( tof < minCut || tof > maxCut )  return kFALSE ;
+  }
+  
+  //In any case, the time should to be larger than the fixed window ...
+  if( tof < fEMCALTimeCutMin  || tof > fEMCALTimeCutMax )  return kFALSE ;
+  
+  return kTRUE ;
+}
+
+//________________________________________________
+Bool_t AliCaloTrackReader::IsPileUpFromSPD() const
+{
+  // Check if event is from pile-up determined by SPD
+  // Default values: (3, 0.8, 3., 2., 5.)
+  return fInputEvent->IsPileupFromSPD((Int_t) fPileUpParamSPD[0] , fPileUpParamSPD[1] , 
+                                              fPileUpParamSPD[2] , fPileUpParamSPD[3] , fPileUpParamSPD[4] ); 
+  //printf("Param : %d, %2.2f, %2.2f, %2.2f, %2.2f\n",(Int_t) fPileUpParamSPD[0], fPileUpParamSPD[1], fPileUpParamSPD[2], fPileUpParamSPD[3], fPileUpParamSPD[4]);
+
+}
+
+//__________________________________________________
+Bool_t AliCaloTrackReader::IsPileUpFromEMCal() const
+{
+  // Check if event is from pile-up determined by EMCal
+  if(fNPileUpClusters > fNPileUpClustersCut) return kTRUE ;
+  else                                       return kFALSE;
+}
+
+//________________________________________________________
+Bool_t AliCaloTrackReader::IsPileUpFromSPDAndEMCal() const
+{
+  // Check if event is from pile-up determined by SPD and EMCal
+  if( IsPileUpFromSPD() && IsPileUpFromEMCal()) return kTRUE ;
+  else                                          return kFALSE;
+}
+
+//_______________________________________________________
+Bool_t AliCaloTrackReader::IsPileUpFromSPDOrEMCal() const
+{
+  // Check if event is from pile-up determined by SPD or EMCal
+  if( IsPileUpFromSPD() || IsPileUpFromEMCal()) return kTRUE ;
+  else                                          return kFALSE;
+}
+
+//___________________________________________________________
+Bool_t AliCaloTrackReader::IsPileUpFromSPDAndNotEMCal() const
+{
+  // Check if event is from pile-up determined by SPD and not by EMCal
+  if( IsPileUpFromSPD() && !IsPileUpFromEMCal()) return kTRUE ;
+  else                                          return kFALSE;
+}
+
+//___________________________________________________________
+Bool_t AliCaloTrackReader::IsPileUpFromEMCalAndNotSPD() const
+{
+  // Check if event is from pile-up determined by EMCal, not by SPD
+  if( !IsPileUpFromSPD() && IsPileUpFromEMCal()) return kTRUE ;
+  else                                           return kFALSE;
+}
+
+//______________________________________________________________
+Bool_t AliCaloTrackReader::IsPileUpFromNotSPDAndNotEMCal() const
+{
+  // Check if event not from pile-up determined neither by SPD nor by EMCal
+  if( !IsPileUpFromSPD() && !IsPileUpFromEMCal()) return kTRUE ;
+  else                                            return kFALSE;
 }
 
 //________________________________________________________
@@ -417,17 +682,20 @@ void AliCaloTrackReader::Print(const Option_t * opt) const
   printf("Use EMCAL Cells =     %d\n",     fFillEMCALCells) ;
   printf("Use PHOS  Cells =     %d\n",     fFillPHOSCells) ;
   printf("Track status    =     %d\n", (Int_t) fTrackStatus) ;
-  printf("AODs Track filter mask  =  %d or hybrid %d\n", (Int_t) fTrackFilterMask,fSelectHybridTracks) ;
+  printf("AODs Track filter mask  =  %d or hybrid %d, SPD hit %d\n", (Int_t) fTrackFilterMask,fSelectHybridTracks,fSelectSPDHitTracks) ;
   printf("Track Mult Eta Cut =  %d\n", (Int_t) fTrackMultEtaCut) ;
   printf("Write delta AOD =     %d\n",     fWriteOutputDeltaAOD) ;
   printf("Recalculate Clusters = %d\n",    fRecalculateClusters) ;
   
-  printf("Use Triggers selected in SE base class %d; If not what trigger Mask %d? \n", 
-         fEventTriggerAtSE, fEventTriggerMask);
+  printf("Use Triggers selected in SE base class %d; If not what trigger Mask? %d; Trigger max for mixed %d \n", 
+         fEventTriggerAtSE, fEventTriggerMask,fMixEventTriggerMask);
   
-  if(fComparePtHardAndJetPt)
+  if(fComparePtHardAndClusterPt)
          printf("Compare jet pt and pt hard to accept event, factor = %2.2f",fPtHardAndJetPtFactor);
   
+  if(fComparePtHardAndClusterPt)
+         printf("Compare cluster pt and pt hard to accept event, factor = %2.2f",fPtHardAndClusterPtFactor);
+  
   printf("Read Kine from, stack? %d, AOD ? %d \n", fReadStack, fReadAODMCParticles) ;
   printf("Delta AOD File Name =     %s\n", fDeltaAODFileName.Data()) ;
   printf("Centrality: Class %s, Option %d, Bin [%d,%d] \n", fCentralityClass.Data(),fCentralityOpt,fCentralityBin[0], fCentralityBin[1]) ;
@@ -441,7 +709,7 @@ Bool_t AliCaloTrackReader::FillInputEvent(const Int_t iEntry,
                                           const char * /*currentFileName*/) 
 {
   //Fill the event counter and input lists that are needed, called by the analysis maker.
-    
+  
   fEventNumber = iEntry;
   //fCurrentFileName = TString(currentFileName);
   if(!fInputEvent)
@@ -467,41 +735,25 @@ Bool_t AliCaloTrackReader::FillInputEvent(const Int_t iEntry,
   // If clusterzer NxN or V2 it does not help
   //-------------------------------------------------------------------------------------
   Int_t run = fInputEvent->GetRunNumber();
-  if( fRemoveLEDEvents && run > 140000  && run <= 146860 )
+  if( fRemoveLEDEvents && run > 146857  && run < 146861 )
   {
     //printf("Event %d\n",GetEventNumber());
-    for (Int_t i = 0; i < fInputEvent->GetNumberOfCaloClusters(); i++)
-    {
-      AliVCluster *clus = fInputEvent->GetCaloCluster(i);
-      if(clus->IsEMCAL())
-      {               
-        if ((clus->E() > 500 && clus->GetNCells() > 200 ) || clus->GetNCells() > 200) 
-        {
-          Int_t absID = clus->GetCellsAbsId()[0];
-          Int_t sm = GetCaloUtils()->GetEMCALGeometry()->GetSuperModuleNumber(absID);
-          if(fDebug > 0) printf("AliCaloTrackReader::FillInputEvent - reject event %d with cluster : E %f, ncells %d, absId(0) %d, SM %d\n",GetEventNumber(),clus->E(),  clus->GetNCells(),absID, sm);
-          return kFALSE;
-        }
-      }
-    }
     
     // Count number of cells with energy larger than 0.1 in SM3, cut on this number
     Int_t ncellsSM3 = 0;
-    Int_t ncellsSM4 = 0;
     for(Int_t icell = 0; icell < fInputEvent->GetEMCALCells()->GetNumberOfCells(); icell++)
     {
       Int_t absID = fInputEvent->GetEMCALCells()->GetCellNumber(icell);
       Int_t sm    = GetCaloUtils()->GetEMCALGeometry()->GetSuperModuleNumber(absID);
       if(fInputEvent->GetEMCALCells()->GetAmplitude(icell) > 0.1 && sm==3) ncellsSM3++;
-      if(fInputEvent->GetEMCALCells()->GetAmplitude(icell) > 0.1 && sm==4) ncellsSM4++;
     }
     
     Int_t ncellcut = 21;
     if(fFiredTriggerClassName.Contains("EMC")) ncellcut = 35;
     
-    if(ncellsSM3 >= ncellcut || ncellsSM4 >= 100)
+    if(ncellsSM3 >= ncellcut)
     {
-      if(fDebug > 0) printf(" AliCaloTrackReader::FillInputEvent() - reject event with ncells in SM3 %d and SM4 %d\n",ncellsSM3, ncellsSM4);
+      if(fDebug > 0) printf(" AliCaloTrackReader::FillInputEvent() - reject event with ncells in SM3 %d\n",ncellsSM3);
       return kFALSE;
     }
   }// Remove LED events
@@ -541,16 +793,40 @@ Bool_t AliCaloTrackReader::FillInputEvent(const Int_t iEntry,
   }
   
   //In case of analysis of events with jets, skip those with jet pt > 5 pt hard        
-  if(fComparePtHardAndJetPt && GetStack()
+  if(fComparePtHardAndJetPt) 
   {
     if(!ComparePtHardAndJetPt()) return kFALSE ;
   }
   
+  if(fComparePtHardAndClusterPt) 
+  {
+    if(!ComparePtHardAndClusterPt()) return kFALSE ;
+  }
+  
   //Fill Vertex array
   FillVertexArray();
   //Reject events with Z vertex too large, only for SE analysis, if not, cut on the analysis code
   if(!GetMixedEvent() && TMath::Abs(fVertex[0][2]) > fZvtxCut) return kFALSE;  
   
+  //------------------------------------------------------
+  //Event rejection depending on vertex, pileup, v0and
+  //------------------------------------------------------
+  if(fDataType==kESD && fTimeStampEventSelect)
+  {
+    AliESDEvent* esd = dynamic_cast<AliESDEvent*> (fInputEvent);
+    if(esd)
+    {
+      Int_t timeStamp = esd->GetTimeStamp();
+      Float_t timeStampFrac = 1.*(timeStamp-fTimeStampRunMin) / (fTimeStampRunMax-fTimeStampRunMin);
+      
+      //printf("stamp0 %d, max0 %d, frac %f\n", timeStamp-fTimeStampRunMin,fTimeStampRunMax-fTimeStampRunMin, timeStampFrac);
+      
+      if(timeStampFrac < fTimeStampEventFracMin || timeStampFrac > fTimeStampEventFracMax) return kFALSE;
+    }
+    //printf("\t accept time stamp\n");
+  }
+
+  
   //------------------------------------------------------
   //Event rejection depending on vertex, pileup, v0and
   //------------------------------------------------------
@@ -563,13 +839,16 @@ Bool_t AliCaloTrackReader::FillInputEvent(const Int_t iEntry,
         TMath::Abs(fVertex[0][2] ) < 1.e-6    ) return kFALSE;
   }
   
+  //printf("Reader : IsPileUp %d, Multi %d\n",IsPileUpFromSPD(),fInputEvent->IsPileupFromSPDInMultBins());
+  
   if(fDoEventSelection)
   {
     if(!fCaloFilterPatch)
     {
-      //Do not analyze events with pileup
-      Bool_t bPileup = fInputEvent->IsPileupFromSPD(3, 0.8, 3., 2., 5.); //Default values, if not it does not compile
-      //Bool_t bPileup = event->IsPileupFromSPD(); 
+      // Do not analyze events with pileup
+      Bool_t bPileup = IsPileUpFromSPD();
+      //IsPileupFromSPDInMultBins() // method to try
+      //printf("pile-up %d, %d, %2.2f, %2.2f, %2.2f, %2.2f\n",bPileup, (Int_t) fPileUpParamSPD[0], fPileUpParamSPD[1], fPileUpParamSPD[2], fPileUpParamSPD[3], fPileUpParamSPD[4]);
       if(bPileup) return kFALSE;
       
       if(fDoV0ANDEventSelection)
@@ -623,7 +902,7 @@ Bool_t AliCaloTrackReader::FillInputEvent(const Int_t iEntry,
         if(fTrackMult == 0) return kFALSE;
       }// no cluster
     }// CaloFileter patch
-  }// Event selection
+  }// Event selection/AliceSoft/AliRoot/trunk/PWG/CaloTrackCorrBase/AliCaloTrackReader.h
   //------------------------------------------------------
   
   //Check if there is a centrality value, PbPb analysis, and if a centrality bin selection is requested
@@ -633,60 +912,60 @@ Bool_t AliCaloTrackReader::FillInputEvent(const Int_t iEntry,
     Int_t cen = GetEventCentrality();
     if(cen > fCentralityBin[1] || cen < fCentralityBin[0]) return kFALSE; //reject events out of bin.
   }
-  
+    
   //Fill the arrays with cluster/tracks/cells data
   
-  if(fFillEMCALCells) 
-    FillInputEMCALCells();
-  
-  if(fFillPHOSCells)  
-    FillInputPHOSCells();
-  
-  FillInputVZERO();
-  
-  if(fEventTriggerAtSE)
-  {
-    if(fFillCTS)
-    {   
-      FillInputCTS();
-      //Accept events with at least one track
-      if(fTrackMult == 0 && fDoEventSelection) return kFALSE;
-    }
-    if(fFillEMCAL) 
-      FillInputEMCAL();
-    if(fFillPHOS)  
-      FillInputPHOS();
-  }
-  else 
+  if(!fEventTriggerAtSE)
   {
-    // In case of mixing analysis, all triggers accepted, but trigger particles selected 
-    // only for the specific trigered events selected here. Mixing done only for MB events,
-    // tracks array filled also for those events and not the others.
-
+    // In case of mixing analysis, accept MB events, not only Trigger
+    // Track and cluster arrays filled for MB in order to create the pool in the corresponding analysis
+    // via de method in the base class FillMixedEventPool()
+    
     AliAnalysisManager *manager = AliAnalysisManager::GetAnalysisManager();
     AliInputEventHandler *inputHandler = dynamic_cast<AliInputEventHandler*>(manager->GetInputEventHandler());
     
     if(!inputHandler) return kFALSE ;  // to content coverity
     
     UInt_t isTrigger = inputHandler->IsEventSelected() & fEventTriggerMask;
-    UInt_t isMB      = inputHandler->IsEventSelected() & AliVEvent::kMB;
+    UInt_t isMB      = inputHandler->IsEventSelected() & fMixEventTriggerMask;
     
-    if(fFillCTS && (isMB || isTrigger))
-    {   
-      FillInputCTS();
-      //Accept events with at least one track
-      if(fTrackMult == 0 && fDoEventSelection) return kFALSE;
-    }
+    if(!isTrigger && !isMB) return kFALSE;
     
-    if(isTrigger)
-    {
-      if(fFillEMCAL) 
-        FillInputEMCAL();
-      if(fFillPHOS)  
-        FillInputPHOS();
-    } 
+    //printf("Selected triggered event : %s\n",GetFiredTriggerClasses().Data());
+  }
+  
+  // Get the main vertex BC, in case not available
+  // it is calculated in FillCTS checking the BC of tracks
+  // with DCA small (if cut applied, if open)
+  fVertexBC=fInputEvent->GetPrimaryVertex()->GetBC();
+  
+  if(fFillCTS)
+  {
+    FillInputCTS();
+    //Accept events with at least one track
+    if(fTrackMult == 0 && fDoRejectNoTrackEvents) return kFALSE ;
   }
   
+  if(fDoVertexBCEventSelection)
+  {
+    if(fVertexBC!=0 && fVertexBC!=AliVTrack::kTOFBCNA) return kFALSE ;
+  }
+    
+  if(fFillEMCALCells)
+    FillInputEMCALCells();
+  
+  if(fFillPHOSCells)
+    FillInputPHOSCells();
+  
+  if(fFillEMCAL)
+    FillInputEMCAL();
+  
+  if(fFillPHOS)
+    FillInputPHOS();
+  
+  FillInputVZERO();
+
+  
   return kTRUE ;
 }
 
@@ -763,14 +1042,14 @@ Double_t AliCaloTrackReader::GetEventPlaneAngle() const
     
     if(GetEventPlaneMethod()=="Q" && (ep < 0 || ep > TMath::Pi())) 
     {
-      printf("AliCaloTrackReader::GetEventPlaneAngle() -  Bad EP for <Q> method : %f\n",ep);
+      if(fDebug > 0 ) printf("AliCaloTrackReader::GetEventPlaneAngle() -  Bad EP for <Q> method : %f\n",ep);
       return -1000;
     }
     else if(GetEventPlaneMethod().Contains("V0")  ) 
     {
       if((ep > TMath::Pi()/2 || ep < -TMath::Pi()/2))
       {
-        printf("AliCaloTrackReader::GetEventPlaneAngle() -  Bad EP for <%s> method : %f\n",GetEventPlaneMethod().Data(), ep);
+        if(fDebug > 0 ) printf("AliCaloTrackReader::GetEventPlaneAngle() -  Bad EP for <%s> method : %f\n",GetEventPlaneMethod().Data(), ep);
         return -1000;
       }
       
@@ -779,14 +1058,17 @@ Double_t AliCaloTrackReader::GetEventPlaneAngle() const
     }
   
     //printf("AliCaloTrackReader::GetEventPlaneAngle() = %f\n",ep);
-    if     (ep > TMath::Pi()) printf("AliCaloTrackReader::GetEventPlaneAngle() - Too large angle = %f\n",ep);
-    else if(ep < 0          ) printf("AliCaloTrackReader::GetEventPlaneAngle() - Negative angle = %f\n" ,ep);
+    if(fDebug > 0 )
+    {
+      if     (ep > TMath::Pi()) printf("AliCaloTrackReader::GetEventPlaneAngle() - Too large angle = %f\n",ep);
+      else if(ep < 0          ) printf("AliCaloTrackReader::GetEventPlaneAngle() - Negative angle = %f\n" ,ep);
+    }
     
     return ep;
   }
   else
   {
-    printf("AliCaloTrackReader::GetEventPlaneAngle() -  No EP pointer\n");
+    if(fDataType!=kMC && fDebug > 0) printf("AliCaloTrackReader::GetEventPlaneAngle() -  No EP pointer\n");
     return -1000;
   } 
   
@@ -891,40 +1173,73 @@ void AliCaloTrackReader::FillInputCTS()
   Int_t nTracks = fInputEvent->GetNumberOfTracks() ;
   fTrackMult    = 0;
   Int_t nstatus = 0;
+  Double_t bz   = GetInputEvent()->GetMagneticField();
+
+  for(Int_t i = 0; i < 19; i++)
+  {
+    fTrackBCEvent   [i] = 0;
+    fTrackBCEventCut[i] = 0;
+  }
+  
+  Bool_t   bc0  = kFALSE;
+  if(fRecalculateVertexBC) fVertexBC=AliVTrack::kTOFBCNA;
   
-  for (Int_t itrack =  0; itrack <  nTracks; itrack++) 
+  for (Int_t itrack =  0; itrack <  nTracks; itrack++)
   {////////////// track loop
     AliVTrack * track = (AliVTrack*)fInputEvent->GetTrack(itrack) ; // retrieve track from esd
     
     //Select tracks under certain conditions, TPCrefit, ITSrefit ... check the set bits
-    if (fTrackStatus && !((track->GetStatus() & fTrackStatus) == fTrackStatus)) 
+    ULong_t status = track->GetStatus();
+
+    if (fTrackStatus && !((status & fTrackStatus) == fTrackStatus))
       continue ;
     
     nstatus++;
     
+    Float_t dcaTPC =-999;
+    
     if     (fDataType==kESD)
     {
       AliESDtrack* esdTrack = dynamic_cast<AliESDtrack*> (track);
       
-      if(esdTrack && fESDtrackCuts->AcceptTrack(esdTrack))
+      if(esdTrack)
       {
-        track->GetPxPyPz(pTrack) ;
+        if(fESDtrackCuts->AcceptTrack(esdTrack))
+        {
+          track->GetPxPyPz(pTrack) ;
 
-        if(fConstrainTrack)
+          if(fConstrainTrack)
+          {
+            if(esdTrack->GetConstrainedParam())
+            {
+              const AliExternalTrackParam* constrainParam = esdTrack->GetConstrainedParam();
+              esdTrack->Set(constrainParam->GetX(),constrainParam->GetAlpha(),constrainParam->GetParameter(),constrainParam->GetCovariance());
+              esdTrack->GetConstrainedPxPyPz(pTrack);
+            }
+            else continue;
+            
+          } // use constrained tracks
+          
+          if(fSelectSPDHitTracks)
+          {//Not much sense to use with TPC only or Hybrid tracks
+            if(!esdTrack->HasPointOnITSLayer(0) && !esdTrack->HasPointOnITSLayer(1)) continue ;
+          }
+        }
+        // Complementary track to global : Hybrids (make sure that the previous selection is for Global)
+        else  if(fESDtrackComplementaryCuts && fESDtrackComplementaryCuts->AcceptTrack(esdTrack))
         {
+          // constrain the track
           if(esdTrack->GetConstrainedParam())
           {
-            const AliExternalTrackParam* constrainParam = esdTrack->GetConstrainedParam();
-            esdTrack->Set(constrainParam->GetX(),constrainParam->GetAlpha(),constrainParam->GetParameter(),constrainParam->GetCovariance());
-            esdTrack->GetConstrainedPxPyPz(pTrack);
+            esdTrack->Set(esdTrack->GetConstrainedParam()->GetX(),esdTrack->GetConstrainedParam()->GetAlpha(),esdTrack->GetConstrainedParam()->GetParameter(),esdTrack->GetConstrainedParam()->GetCovariance());
+          
+            track->GetPxPyPz(pTrack) ;
+
           }
           else continue;
-          
-        } // use constrained tracks
-        
+        }
+        else continue;
       }
-      else continue;
-      
     } // ESD
     else if(fDataType==kAOD)
     {
@@ -946,10 +1261,19 @@ void AliCaloTrackReader::FillInputCTS()
           if ( aodtrack->TestFilterBit(fTrackFilterMask)==kFALSE) continue ;
         }
         
+        if(fSelectSPDHitTracks)
+        {//Not much sense to use with TPC only or Hybrid tracks
+          if(!aodtrack->HasPointOnITSLayer(0) && !aodtrack->HasPointOnITSLayer(1)) continue ;
+        }
+        
         if (aodtrack->GetType()!= AliAODTrack::kPrimary)          continue ;
         
         if (fDebug > 2 ) printf("AliCaloTrackReader::FillInputCTS(): \t accepted track! \n");
         
+        //In case of AODs, TPC tracks cannot be propagated back to primary vertex,
+        // info stored here
+        dcaTPC = aodtrack->DCA();
+        
         track->GetPxPyPz(pTrack) ;
         
       } // aod track exists
@@ -957,32 +1281,84 @@ void AliCaloTrackReader::FillInputCTS()
       
     } // AOD
     
-    //Count the tracks in eta < 0.9
-    //printf("Eta %f cut  %f\n",TMath::Abs(track->Eta()),fTrackMultEtaCut);
-    if(TMath::Abs(track->Eta())< fTrackMultEtaCut) fTrackMult++;
-    
     TLorentzVector momentum(pTrack[0],pTrack[1],pTrack[2],0);
     
-    if(fCTSPtMin < momentum.Pt() && fCTSPtMax > momentum.Pt())
+    Bool_t okTOF  = ( (status & AliVTrack::kTOFout) == AliVTrack::kTOFout ) ;
+    Double_t tof  = -1000;
+    Int_t trackBC = -1000 ;
+    
+    if(okTOF)
     {
-      if(fCheckFidCut && !fFiducialCut->IsInFiducialCut(momentum,"CTS")) 
-        continue;
-      
-      if(fDebug > 2 && momentum.Pt() > 0.1) 
-        printf("AliCaloTrackReader::FillInputCTS() - Selected tracks E %3.2f, pt %3.2f, phi %3.2f, eta %3.2f\n",
-               momentum.E(),momentum.Pt(),momentum.Phi()*TMath::RadToDeg(),momentum.Eta());
-      
-      if (fMixedEvent) 
+      trackBC = track->GetTOFBunchCrossing(bz);
+      SetTrackEventBC(trackBC+9);
+
+      tof = track->GetTOFsignal()*1e-3;
+    }
+                
+    if(fUseTrackDCACut)
+    {
+      //normal way to get the dca, cut on dca_xy
+      if(dcaTPC==-999)
       {
-        track->SetID(itrack);
+        Double_t dca[2]   = {1e6,1e6};
+        Double_t covar[3] = {1e6,1e6,1e6};
+        Bool_t okDCA = track->PropagateToDCA(fInputEvent->GetPrimaryVertex(),bz,100.,dca,covar);
+        if( okDCA) okDCA = AcceptDCA(momentum.Pt(),dca[0]);
+        if(!okDCA)
+        {
+          //printf("AliCaloTrackReader::FillInputCTS() - Reject track pt %2.2f, dca_xy %2.4f, BC %d\n",momentum.Pt(),dca[0],trackBC);
+          continue ;
+        }
       }
+    }// DCA cuts
+    
+    if(okTOF)
+    {
+      //SetTrackEventBCcut(bc);
+      SetTrackEventBCcut(trackBC+9);
       
-      fCTSTracks->Add(track);        
+      //After selecting tracks with small DCA, pointing to vertex, set vertex BC depeding on tracks BC
+      if(fRecalculateVertexBC)
+      {
+        if     (trackBC !=0 && trackBC != AliVTrack::kTOFBCNA) fVertexBC = trackBC;
+        else if(trackBC == 0)                                  bc0 = kTRUE;
+      }
+
+      //In any case, the time should to be larger than the fixed window ...
+      if( fUseTrackTimeCut && (trackBC!=0 || tof < fTrackTimeCutMin  || tof > fTrackTimeCutMax) )
+      {
+        //printf("Remove track time %f and bc = %d\n",tof,trackBC);
+        continue ;
+      }
+      //else printf("Accept track time %f and bc = %d\n",tof,trackBC);
       
-    }//Pt and Fiducial cut passed. 
+    }
+    
+    //Count the tracks in eta < 0.9
+    //printf("Eta %f cut  %f\n",TMath::Abs(track->Eta()),fTrackMultEtaCut);
+    if(TMath::Abs(track->Eta())< fTrackMultEtaCut) fTrackMult++;
+    
+    if(fCTSPtMin > momentum.Pt() || fCTSPtMax < momentum.Pt()) continue ;
+    
+    if(fCheckFidCut && !fFiducialCut->IsInFiducialCut(momentum,"CTS")) continue;
+    
+    if(fDebug > 2 && momentum.Pt() > 0.1)
+      printf("AliCaloTrackReader::FillInputCTS() - Selected tracks E %3.2f, pt %3.2f, phi %3.2f, eta %3.2f\n",
+             momentum.E(),momentum.Pt(),momentum.Phi()*TMath::RadToDeg(),momentum.Eta());
+    
+    if (fMixedEvent)  track->SetID(itrack);
+
+    fCTSTracks->Add(track);
+    
   }// track loop
        
-  if(fDebug > 1) 
+  if(fVertexBC ==0 || fVertexBC == AliVTrack::kTOFBCNA)
+  {
+    if( bc0 ) fVertexBC = 0 ;
+    else      fVertexBC = AliVTrack::kTOFBCNA ;
+  }
+  
+  if(fDebug > 1)
     printf("AliCaloTrackReader::FillInputCTS()   - aod entries %d, input tracks %d, pass status %d, multipliticy %d\n", fCTSTracks->GetEntriesFast(), nTracks, nstatus, fTrackMult);//fCTSTracksNormalInputEntries);
   
 }
@@ -1079,16 +1455,30 @@ void AliCaloTrackReader::FillInputEMCALAlgorithm(AliVCluster * clus,
     clus->SetE(rdmEnergy);
   }
   
-  TLorentzVector momentum ;
+  Double_t tof = clus->GetTOF()*1e9;
+
+  Int_t bc = TMath::Nint(tof/50) + 9;
+  //printf("tof %2.2f, bc+5=%d\n",tof,bc);
   
-  clus->GetMomentum(momentum, fVertex[vindex]);      
+  SetEMCalEventBC(bc);
   
-  if(fCheckFidCut && !fFiducialCut->IsInFiducialCut(momentum,"EMCAL")) return;
+  if(fEMCALPtMin > clus->E() || fEMCALPtMax < clus->E()) return ;
+
+  TLorentzVector momentum ;
   
-  if(fEMCALPtMin > momentum.E() || fEMCALPtMax < momentum.E())         return;
+  clus->GetMomentum(momentum, fVertex[vindex]);
   
-  Double_t tof = clus->GetTOF()*1e9;
-  if(tof < fEMCALTimeCutMin     || tof > fEMCALTimeCutMax)             return;
+  if(fCheckFidCut && !fFiducialCut->IsInFiducialCut(momentum,"EMCAL")) return ;
+  
+  SetEMCalEventBCcut(bc);
+
+  if(!IsInTimeWindow(tof,clus->E()))
+  {
+    fNPileUpClusters++ ;
+    if(fUseEMCALTimeCut) return ;
+  }
+  else
+    fNNonPileUpClusters++;
   
   if(fDebug > 2 && momentum.E() > 0.1) 
     printf("AliCaloTrackReader::FillInputEMCAL() - Selected clusters E %3.2f, pt %3.2f, phi %3.2f, eta %3.2f\n",
@@ -1097,8 +1487,13 @@ void AliCaloTrackReader::FillInputEMCALAlgorithm(AliVCluster * clus,
   if (fMixedEvent) 
     clus->SetID(iclus) ; 
   
-  fEMCALClusters->Add(clus);   
-    
+  //Correct MC label for AODs
+  
+  if(ReadAODMCParticles())
+    CorrectMCLabelForAODs(clus);
+  
+  fEMCALClusters->Add(clus);
+  
 }
 
 //_______________________________________
@@ -1114,6 +1509,14 @@ void AliCaloTrackReader::FillInputEMCAL()
   //                                                          GetEMCALCells(), 
   //                                                          fInputEvent->GetBunchCrossNumber());
   
+  fNPileUpClusters    = 0; // Init counter
+  fNNonPileUpClusters = 0; // Init counter
+  for(Int_t i = 0; i < 19; i++)
+  {
+    fEMCalBCEvent   [i] = 0;
+    fEMCalBCEventCut[i] = 0;
+  }
+  
   //Loop to select clusters in fiducial cut and fill container with aodClusters
   if(fEMCALClustersListName=="")
   {
@@ -1140,23 +1543,17 @@ void AliCaloTrackReader::FillInputEMCAL()
     
     if      (fInputEvent->FindListObject(fEMCALClustersListName))
     {
-      clusterList = dynamic_cast<TClonesArray*> (fInputEvent ->FindListObject(fEMCALClustersListName));
+      clusterList = dynamic_cast<TClonesArray*> (fInputEvent->FindListObject(fEMCALClustersListName));
     }
     else if(fOutputEvent)
-    { 
+    {
       clusterList = dynamic_cast<TClonesArray*> (fOutputEvent->FindListObject(fEMCALClustersListName));
     }
     
     if(!clusterList)
     {
-      //printf("AliCaloTrackReader::FillInputEMCAL() - Wrong name of list with clusters? Try input event <%s>\n",fEMCALClustersListName.Data());
-      //List not in output event, try input event
-      clusterList = dynamic_cast<TClonesArray*> (fInputEvent->FindListObject(fEMCALClustersListName));
-      if(!clusterList)
-      {
         printf("AliCaloTrackReader::FillInputEMCAL() - Wrong name of list with clusters?  <%s>\n",fEMCALClustersListName.Data());
         return;
-      }
     }
     
     Int_t nclusters = clusterList->GetEntriesFast();
@@ -1168,13 +1565,68 @@ void AliCaloTrackReader::FillInputEMCAL()
       else printf("AliCaloTrackReader::FillInputEMCAL() - Null cluster in list!\n");
     }// cluster loop
     
+    // Recalculate the pile-up time, in case long time clusters removed during clusterization
+    //printf("Input event INIT : Pile-up clusters %d, NO pile-up %d\n",fNPileUpClusters,fNNonPileUpClusters);
+
+    fNPileUpClusters    = 0; // Init counter
+    fNNonPileUpClusters = 0; // Init counter
+    for(Int_t i = 0; i < 19; i++)
+    {
+      fEMCalBCEvent   [i] = 0;
+      fEMCalBCEventCut[i] = 0;
+    }
+    
+    for (Int_t iclus =  0; iclus < fInputEvent->GetNumberOfCaloClusters(); iclus++)
+    {
+      AliVCluster * clus = 0;
+      
+      if ( (clus = fInputEvent->GetCaloCluster(iclus)) )
+      {
+        if (IsEMCALCluster(clus))
+        {
+          
+          Float_t  frac     =-1;
+          Int_t    absIdMax = GetCaloUtils()->GetMaxEnergyCell(fEMCALCells, clus,frac);
+          Double_t tof = clus->GetTOF();
+          GetCaloUtils()->GetEMCALRecoUtils()->RecalibrateCellTime(absIdMax,fInputEvent->GetBunchCrossNumber(),tof);
+          tof*=1e9;
+
+          //printf("Input event cluster : AbsIdMax %d, E %2.2f, time %2.2f \n", absIdMax,clus->E(),tof);
+
+          //Reject clusters with bad channels, close to borders and exotic;
+          if(!GetCaloUtils()->GetEMCALRecoUtils()->IsGoodCluster(clus,GetCaloUtils()->GetEMCALGeometry(),GetEMCALCells(),fInputEvent->GetBunchCrossNumber()))  continue;
+
+          Int_t bc = TMath::Nint(tof/50) + 9;
+          SetEMCalEventBC(bc);
+          
+          if(fEMCALPtMin > clus->E() || fEMCALPtMax < clus->E()) continue ;
+
+          TLorentzVector momentum ;
+          
+          clus->GetMomentum(momentum, fVertex[0]);
+          
+          if(fCheckFidCut && !fFiducialCut->IsInFiducialCut(momentum,"EMCAL")) return ;
+
+          SetEMCalEventBCcut(bc);
+
+          if(!IsInTimeWindow(tof,clus->E()))
+            fNPileUpClusters++ ;
+          else
+            fNNonPileUpClusters++;
+          
+        }
+      }
+    }
+    
+    //printf("Input event : Pile-up clusters %d, NO pile-up %d\n",fNPileUpClusters,fNNonPileUpClusters);
+    
     // Recalculate track matching, not necessary if already done in the reclusterization task.
     // in case it was not done ...
     GetCaloUtils()->RecalculateClusterTrackMatching(fInputEvent,clusterList);
     
   }
-  
-  if(fDebug > 1) printf("AliCaloTrackReader::FillInputEMCAL() - aod entries %d\n",  fEMCALClusters->GetEntriesFast());
+    
+  if(fDebug > 1) printf("AliCaloTrackReader::FillInputEMCAL() - aod entries %d, n pile-up clusters %d, n non pile-up %d \n",  fEMCALClusters->GetEntriesFast(),fNPileUpClusters,fNNonPileUpClusters);
   
 }
 
@@ -1231,6 +1683,9 @@ void AliCaloTrackReader::FillInputPHOS()
           clus->SetID(iclus) ; 
         }              
         
+        if(ReadAODMCParticles())
+          CorrectMCLabelForAODs(clus);
+        
         fPHOSClusters->Add(clus);      
         
       }//PHOS cluster
@@ -1351,7 +1806,7 @@ Bool_t AliCaloTrackReader::CheckForPrimaryVertex()
       return kTRUE;
       
     }
-    if(event->GetPrimaryVertexSPD()->GetNContributors() < 1) 
+    if(event->GetPrimaryVertexSPD()->GetNContributors() < 1)
     {
       //      cout<<"bad vertex type::"<< event->GetPrimaryVertex()->GetName() << endl;
       return kFALSE;
@@ -1373,3 +1828,15 @@ void  AliCaloTrackReader::SetTrackCuts(AliESDtrackCuts * cuts)
   
 }                
 
+//_________________________________________________________________________
+void  AliCaloTrackReader::SetTrackComplementaryCuts(AliESDtrackCuts * cuts)
+{
+  // Set Track cuts for complementary tracks (hybrids)
+  
+  if(fESDtrackComplementaryCuts) delete fESDtrackComplementaryCuts ;
+  
+  fESDtrackComplementaryCuts = cuts ;
+  
+}
+
+