o update dielectron package
authorwiechula <wiechula@f7af4fe6-9843-0410-8265-dc069ae4e863>
Thu, 5 Apr 2012 10:45:06 +0000 (10:45 +0000)
committerwiechula <wiechula@f7af4fe6-9843-0410-8265-dc069ae4e863>
Thu, 5 Apr 2012 10:45:06 +0000 (10:45 +0000)
53 files changed:
PWGDQ/CMakelibPWGDQdielectron.pkg
PWGDQ/PWGDQdielectronLinkDef.h
PWGDQ/dielectron/AliAnalysisTaskDielectronFilter.cxx
PWGDQ/dielectron/AliAnalysisTaskDielectronFilter.h
PWGDQ/dielectron/AliAnalysisTaskDielectronME.cxx
PWGDQ/dielectron/AliAnalysisTaskDielectronSE.cxx
PWGDQ/dielectron/AliAnalysisTaskDielectronSE.h
PWGDQ/dielectron/AliAnalysisTaskMultiDielectron.cxx
PWGDQ/dielectron/AliAnalysisTaskMultiDielectron.h
PWGDQ/dielectron/AliAnalysisTaskSingleParticle.cxx [new file with mode: 0644]
PWGDQ/dielectron/AliAnalysisTaskSingleParticle.h [new file with mode: 0644]
PWGDQ/dielectron/AliDielectron.cxx
PWGDQ/dielectron/AliDielectron.h
PWGDQ/dielectron/AliDielectronBtoJPSItoEle.cxx
PWGDQ/dielectron/AliDielectronBtoJPSItoEle.h
PWGDQ/dielectron/AliDielectronBtoJPSItoEleCDFfitFCN.cxx
PWGDQ/dielectron/AliDielectronBtoJPSItoEleCDFfitFCN.h
PWGDQ/dielectron/AliDielectronBtoJPSItoEleCDFfitHandler.cxx
PWGDQ/dielectron/AliDielectronBtoJPSItoEleCDFfitHandler.h
PWGDQ/dielectron/AliDielectronCF.cxx
PWGDQ/dielectron/AliDielectronCF.h
PWGDQ/dielectron/AliDielectronCFdraw.cxx
PWGDQ/dielectron/AliDielectronCFdraw.h
PWGDQ/dielectron/AliDielectronEvent.cxx [new file with mode: 0644]
PWGDQ/dielectron/AliDielectronEvent.h [new file with mode: 0644]
PWGDQ/dielectron/AliDielectronEventCuts.cxx
PWGDQ/dielectron/AliDielectronHelper.cxx
PWGDQ/dielectron/AliDielectronHelper.h
PWGDQ/dielectron/AliDielectronHistos.cxx
PWGDQ/dielectron/AliDielectronHistos.h
PWGDQ/dielectron/AliDielectronMC.cxx
PWGDQ/dielectron/AliDielectronMC.h
PWGDQ/dielectron/AliDielectronMixingHandler.cxx [new file with mode: 0644]
PWGDQ/dielectron/AliDielectronMixingHandler.h [new file with mode: 0644]
PWGDQ/dielectron/AliDielectronPID.cxx
PWGDQ/dielectron/AliDielectronPID.h
PWGDQ/dielectron/AliDielectronPair.cxx
PWGDQ/dielectron/AliDielectronPair.h
PWGDQ/dielectron/AliDielectronSignalBase.cxx
PWGDQ/dielectron/AliDielectronSignalBase.h
PWGDQ/dielectron/AliDielectronSignalExt.cxx
PWGDQ/dielectron/AliDielectronSignalFunc.cxx
PWGDQ/dielectron/AliDielectronSignalFunc.h
PWGDQ/dielectron/AliDielectronSignalMC.cxx
PWGDQ/dielectron/AliDielectronSignalMC.h
PWGDQ/dielectron/AliDielectronTrackCuts.cxx
PWGDQ/dielectron/AliDielectronTrackCuts.h
PWGDQ/dielectron/AliDielectronVarContainer.cxx
PWGDQ/dielectron/AliDielectronVarContainer.h
PWGDQ/dielectron/AliDielectronVarCuts.cxx
PWGDQ/dielectron/AliDielectronVarCuts.h
PWGDQ/dielectron/AliDielectronVarManager.cxx
PWGDQ/dielectron/AliDielectronVarManager.h

index 18cc9c2..c64b543 100644 (file)
 #--------------------------------------------------------------------------------#
 
 set ( SRCS  
-      dielectron/AliDielectron.cxx 
-      dielectron/AliDielectronPair.cxx 
-      dielectron/AliDielectronHistos.cxx 
-      dielectron/AliDielectronCF.cxx 
-      dielectron/AliDielectronCFdraw.cxx 
-      dielectron/AliDielectronMC.cxx 
-      dielectron/AliDielectronVarManager.cxx 
-      dielectron/AliAnalysisTaskDielectronSE.cxx 
-      dielectron/AliAnalysisTaskDielectronME.cxx 
-      dielectron/AliAnalysisTaskDielectronFilter.cxx 
-      dielectron/AliAnalysisTaskDielectronEfficiency.cxx 
-      dielectron/AliAnalysisTaskMultiDielectron.cxx 
-      dielectron/AliDielectronVarCuts.cxx 
-      dielectron/AliDielectronTrackCuts.cxx 
-      dielectron/AliDielectronPairLegCuts.cxx 
-      dielectron/AliDielectronSignalBase.cxx 
-      dielectron/AliDielectronSignalFunc.cxx 
-      dielectron/AliDielectronSignalExt.cxx 
-      dielectron/AliDielectronSpectrum.cxx 
-      dielectron/AliDielectronDebugTree.cxx 
-      dielectron/AliDielectronTrackRotator.cxx 
-      dielectron/AliDielectronPID.cxx 
-      dielectron/AliDielectronCutGroup.cxx 
-      dielectron/AliDielectronEventCuts.cxx 
+      dielectron/AliDielectron.cxx
+      dielectron/AliDielectronPair.cxx
+      dielectron/AliDielectronHistos.cxx
+      dielectron/AliDielectronCF.cxx
+      dielectron/AliDielectronCFdraw.cxx
+      dielectron/AliDielectronMC.cxx
+      dielectron/AliDielectronVarManager.cxx
+      dielectron/AliAnalysisTaskDielectronSE.cxx
+      dielectron/AliAnalysisTaskDielectronME.cxx
+      dielectron/AliAnalysisTaskDielectronFilter.cxx
+      dielectron/AliAnalysisTaskDielectronEfficiency.cxx
+      dielectron/AliAnalysisTaskMultiDielectron.cxx
+      dielectron/AliAnalysisTaskDielectronReadAODBranch.cxx
+      dielectron/AliAnalysisTaskSingleParticle.cxx
+      dielectron/AliDielectronVarCuts.cxx
+      dielectron/AliDielectronTrackCuts.cxx
+      dielectron/AliDielectronPairLegCuts.cxx
+      dielectron/AliDielectronSignalBase.cxx
+      dielectron/AliDielectronSignalFunc.cxx
+      dielectron/AliDielectronSignalExt.cxx
+      dielectron/AliDielectronSpectrum.cxx
+      dielectron/AliDielectronDebugTree.cxx
+      dielectron/AliDielectronTrackRotator.cxx
+      dielectron/AliDielectronPID.cxx
+      dielectron/AliDielectronCutGroup.cxx
+      dielectron/AliDielectronEventCuts.cxx
       dielectron/AliDielectronHelper.cxx
       dielectron/AliDielectronBtoJPSItoEleCDFfitFCN.cxx
       dielectron/AliDielectronBtoJPSItoEleCDFfitHandler.cxx
       dielectron/AliDielectronBtoJPSItoEle.cxx
-      dielectron/AliAnalysisTaskDielectronReadAODBranch.cxx
       dielectron/AliDielectronTRDpidCut.cxx
       dielectron/AliDielectronSignalMC.cxx
+      dielectron/AliDielectronEvent.cxx
+      dielectron/AliDielectronMixingHandler.cxx
 )
 
 string(REPLACE ".cxx" ".h" HDRS "${SRCS}")
index d745438..e30d4bc 100644 (file)
@@ -19,6 +19,7 @@
 #pragma link C++ class AliAnalysisTaskDielectronEfficiency+;
 #pragma link C++ class AliAnalysisTaskMultiDielectron+;
 #pragma link C++ class AliAnalysisTaskDielectronReadAODBranch+;
+#pragma link C++ class AliAnalysisTaskSingleParticle+;
 #pragma link C++ class AliDielectronVarCuts+;
 #pragma link C++ class AliDielectronTrackCuts+;
 #pragma link C++ class AliDielectronPairLegCuts+;
@@ -37,5 +38,7 @@
 #pragma link C++ class AliDielectronBtoJPSItoEle+;
 #pragma link C++ class AliDielectronTRDpidCut+;
 #pragma link C++ class AliDielectronSignalMC+;
+#pragma link C++ class AliDielectronEvent+;
+#pragma link C++ class AliDielectronMixingHandler+;
 
 #endif
index 6fc0465..ab92685 100644 (file)
@@ -28,7 +28,6 @@
 #include <AliAnalysisManager.h>
 #include <AliVEvent.h>
 #include <AliInputEventHandler.h>
-#include <AliESDInputHandler.h>
 #include <AliAODInputHandler.h>
 
 #include "AliDielectron.h"
@@ -46,7 +45,9 @@ fDielectron(0),
 fSelectPhysics(kTRUE),
 fTriggerMask(AliVEvent::kMB),
 fEventStat(0x0),
-fStoreLikeSign(kFALSE)
+fStoreLikeSign(kFALSE),
+fStoreRotatedPairs(kFALSE),
+fEventFilter(0x0)
 {
   //
   // Constructor
@@ -60,7 +61,9 @@ fDielectron(0),
 fSelectPhysics(kTRUE),
 fTriggerMask(AliVEvent::kMB),
 fEventStat(0x0),
-fStoreLikeSign(kFALSE)
+fStoreLikeSign(kFALSE),
+fStoreRotatedPairs(kFALSE),
+fEventFilter(0x0)
 {
   //
   // Constructor
@@ -96,13 +99,15 @@ void AliAnalysisTaskDielectronFilter::UserCreateOutputObjects()
     AliFatal("Dielectron framework class required. Please create and instance with proper cuts and set it via 'SetDielectron' before executing this task!!!");
     return;
   }
+  if(fStoreRotatedPairs) fDielectron->SetStoreRotatedPairs(kTRUE);
   fDielectron->Init();
 
   if (!fEventStat){
-    fEventStat=new TH1D("hEventStat","Event statistics",5,0,5);
+    fEventStat=new TH1D("hEventStat","Event statistics",6,0,6);
     fEventStat->GetXaxis()->SetBinLabel(1,"Before Phys. Sel.");
     fEventStat->GetXaxis()->SetBinLabel(2,"After Phys. Sel.");
-    fEventStat->GetXaxis()->SetBinLabel(3,"After Cand. Sel.");
+    fEventStat->GetXaxis()->SetBinLabel(3,"After Phys. Sel.");
+    fEventStat->GetXaxis()->SetBinLabel(4,"After Cand. Sel.");
   }
   
   PostData(2,fEventStat);
@@ -118,39 +123,17 @@ void AliAnalysisTaskDielectronFilter::UserExec(Option_t *)
   if (!fDielectron) return;
   
   AliAnalysisManager *man=AliAnalysisManager::GetAnalysisManager();
-  AliESDInputHandler *esdHandler=0x0;
-  if ( (esdHandler=dynamic_cast<AliESDInputHandler*>(man->GetInputEventHandler())) && esdHandler->GetESDpid() ){
-    AliDielectronVarManager::SetESDpid(esdHandler->GetESDpid());
+  
+  AliInputEventHandler* inputHandler = (AliInputEventHandler*) (man->GetInputEventHandler());
+  if (!inputHandler) return;
+
+  if ( inputHandler->GetPIDResponse() ){
+    AliDielectronVarManager::SetPIDResponse( inputHandler->GetPIDResponse() );
   } else {
-    //load esd pid bethe bloch parameters depending on the existance of the MC handler
-    // yes: MC parameters
-    // no:  data parameters
-    
-    //ESD case
-    if (man->GetInputEventHandler()->IsA()==AliESDInputHandler::Class()){
-      if (!AliDielectronVarManager::GetESDpid()){
-        
-        if (AliDielectronMC::Instance()->HasMC()) {
-          AliDielectronVarManager::InitESDpid();
-        } else {
-          AliDielectronVarManager::InitESDpid(1);
-        }
-      }
-    }
-    //AOD case
-    if (man->GetInputEventHandler()->IsA()==AliAODInputHandler::Class()){
-      if (!AliDielectronVarManager::GetAODpidUtil()){
-        if (AliDielectronMC::Instance()->HasMC()) {
-          AliDielectronVarManager::InitAODpidUtil();
-        } else {
-          AliDielectronVarManager::InitAODpidUtil(1);
-        }
-      }
-    }
+    AliFatal("This task needs the PID response attached to the input event handler!");
   }
   
   // Was event selected ?
-  AliInputEventHandler* inputHandler = (AliInputEventHandler*) (man->GetInputEventHandler());
   UInt_t isSelected = AliVEvent::kAny;
   if( fSelectPhysics && inputHandler && inputHandler->GetEventSelection() ) {
     isSelected = inputHandler->IsEventSelected();
@@ -165,7 +148,13 @@ void AliAnalysisTaskDielectronFilter::UserExec(Option_t *)
   }
   //after physics selection
   fEventStat->Fill(1.);
-  
+
+  //event filter
+  if (fEventFilter) {
+    if (!fEventFilter->IsSelected(InputEvent())) return;
+  }
+  fEventStat->Fill(2.);
+
   //bz for AliKF
   Double_t bz = InputEvent()->GetMagneticField();
   AliKFParticle::SetField( bz );
@@ -175,6 +164,8 @@ void AliAnalysisTaskDielectronFilter::UserExec(Option_t *)
   Bool_t hasCand = kFALSE;
   if(fStoreLikeSign) hasCand = (fDielectron->HasCandidates() || fDielectron->HasCandidatesLikeSign());
   else hasCand = (fDielectron->HasCandidates());
+
+  if(fStoreRotatedPairs) hasCand = (hasCand || fDielectron->HasCandidatesTR());
   
   if(hasCand){
     AliAODHandler *aodH=(AliAODHandler*)((AliAnalysisManager::GetAnalysisManager())->GetOutputEventHandler());
@@ -182,7 +173,7 @@ void AliAnalysisTaskDielectronFilter::UserExec(Option_t *)
     
     //replace the references of the legs with the AOD references
     TObjArray *obj = 0x0;
-    for(Int_t i=0; i < 10; i++ ){
+    for(Int_t i=0; i < 11; i++ ){
       obj = (TObjArray*)((*(fDielectron->GetPairArraysPointer()))->UncheckedAt(i));
       if(!obj) continue;
       for(int j=0;j<obj->GetEntriesFast();j++){
@@ -212,7 +203,7 @@ void AliAnalysisTaskDielectronFilter::UserExec(Option_t *)
     AliAODExtension *extDielectron = aodH->GetFilteredAOD("AliAOD.Dielectron.root");
     extDielectron->SelectEvent();
     //after candidate selection
-    fEventStat->Fill(2.);
+    fEventStat->Fill(3.);
     
     //see if dielectron candidate branch exists, if not create is
     TTree *t=extDielectron->GetTree();
index 4249ef1..c398bfd 100644 (file)
@@ -51,6 +51,10 @@ public:
   void SetDielectron(AliDielectron * const die) { fDielectron = die; }
 
   void SetStoreLikeSignCandidates(Bool_t storeLS) { fStoreLikeSign = storeLS; }
+  void SetStoreRotatedPairs(Bool_t storeTR) { fStoreRotatedPairs = storeTR; }
+
+  void SetEventFilter(AliAnalysisCuts * const filter) {fEventFilter=filter;}
+
 private:
   
   AliDielectron *fDielectron;             // J/psi framework object
@@ -59,7 +63,11 @@ private:
   UInt_t fTriggerMask;               // Event trigger mask
 
   TH1D *fEventStat;                  //! Histogram with event statistics
+  
   Bool_t fStoreLikeSign;        // flag to store like-sign candidates
+  Bool_t fStoreRotatedPairs;    // flag to store rotation
+
+  AliAnalysisCuts *fEventFilter;     // event filter
   
   AliAnalysisTaskDielectronFilter(const AliAnalysisTaskDielectronFilter &c);
   AliAnalysisTaskDielectronFilter& operator= (const AliAnalysisTaskDielectronFilter &c);
index 3d95e0f..5b4f82a 100644 (file)
@@ -24,7 +24,6 @@
 
 #include <AliCFContainer.h>
 #include <AliInputEventHandler.h>
-#include <AliESDInputHandler.h>
 #include <AliAnalysisManager.h>
 #include <AliVEvent.h>
 
@@ -119,23 +118,16 @@ void AliAnalysisTaskDielectronME::UserExec(Option_t *)
   if (fListHistos.IsEmpty()&&fListCF.IsEmpty()) return;
 
   AliAnalysisManager *man=AliAnalysisManager::GetAnalysisManager();
-  AliESDInputHandler *esdHandler=0x0;
-  if ( (esdHandler=dynamic_cast<AliESDInputHandler*>(man->GetInputEventHandler())) && esdHandler->GetESDpid() ){
-    AliDielectronVarManager::SetESDpid(esdHandler->GetESDpid());
+  AliInputEventHandler* inputHandler = (AliInputEventHandler*) (man->GetInputEventHandler());
+  if (!inputHandler) return;
+
+  if ( inputHandler->GetPIDResponse() ){
+    AliDielectronVarManager::SetPIDResponse( inputHandler->GetPIDResponse() );
   } else {
-    //load esd pid bethe bloch parameters depending on the existance of the MC handler
-    // yes: MC parameters
-    // no:  data parameters
-    if (!AliDielectronVarManager::GetESDpid()){
-      if (AliDielectronMC::Instance()->HasMC()) {
-        AliDielectronVarManager::InitESDpid();
-      } else {
-        AliDielectronVarManager::InitESDpid(1);
-      }
-    }
-  } 
+    AliFatal("This task needs the PID response attached to the input event handler!");
+  }
+
   // Was event selected ?
-  AliInputEventHandler* inputHandler = (AliInputEventHandler*) (man->GetInputEventHandler());
   UInt_t isSelected = AliVEvent::kAny;
   if( fSelectPhysics && inputHandler && inputHandler->GetEventSelection() ) {
     isSelected = inputHandler->IsEventSelected();
index 83b7bfa..24789f2 100644 (file)
@@ -29,6 +29,7 @@
 #include <AliESDInputHandler.h>
 #include <AliAnalysisManager.h>
 #include <AliAODInputHandler.h>
+#include <AliTriggerAnalysis.h>
 
 #include "AliDielectron.h"
 #include "AliDielectronHistos.h"
@@ -43,6 +44,10 @@ AliAnalysisTaskDielectronSE::AliAnalysisTaskDielectronSE() :
   fDielectron(0),
   fSelectPhysics(kFALSE),
   fTriggerMask(AliVEvent::kMB),
+  fTriggerOnV0AND(kFALSE),
+  fRejectPileup(kFALSE),
+  fTriggerAnalysis(0x0),
+  fEventFilter(0x0),
   fEventStat(0x0)
 {
   //
@@ -56,6 +61,10 @@ AliAnalysisTaskDielectronSE::AliAnalysisTaskDielectronSE(const char *name) :
   fDielectron(0),
   fSelectPhysics(kFALSE),
   fTriggerMask(AliVEvent::kMB),
+  fTriggerOnV0AND(kFALSE),
+  fRejectPileup(kFALSE),
+  fTriggerAnalysis(0x0),
+  fEventFilter(0x0),
   fEventStat(0x0)
 {
   //
@@ -90,6 +99,29 @@ void AliAnalysisTaskDielectronSE::UserCreateOutputObjects()
     fEventStat->GetXaxis()->SetBinLabel(1,"Before Phys. Sel.");
     fEventStat->GetXaxis()->SetBinLabel(2,"After Phys. Sel.");
   }
+  Int_t nbins=kNbinsEvent+2;
+  if (!fEventStat){
+    fEventStat=new TH1D("hEventStat","Event statistics",nbins,0,nbins);
+    fEventStat->GetXaxis()->SetBinLabel(1,"Before Phys. Sel.");
+    fEventStat->GetXaxis()->SetBinLabel(2,"After Phys. Sel.");
+
+    //default names
+    fEventStat->GetXaxis()->SetBinLabel(3,"Bin3 not used");
+    fEventStat->GetXaxis()->SetBinLabel(4,"Bin4 not used");
+    fEventStat->GetXaxis()->SetBinLabel(5,"Bin5 not used");
+
+    if(fTriggerOnV0AND) fEventStat->GetXaxis()->SetBinLabel(3,"V0and triggers");
+    if (fEventFilter) fEventStat->GetXaxis()->SetBinLabel(4,"After Event Filter");
+    if (fRejectPileup) fEventStat->GetXaxis()->SetBinLabel(5,"After Pileup rejection");
+
+    fEventStat->GetXaxis()->SetBinLabel((kNbinsEvent+1),Form("#splitline{1 candidate}{%s}",fDielectron->GetName()));
+    fEventStat->GetXaxis()->SetBinLabel((kNbinsEvent+2),Form("#splitline{With >1 candidate}{%s}",fDielectron->GetName()));
+
+  }
+
+  if (!fTriggerAnalysis) fTriggerAnalysis=new AliTriggerAnalysis;
+  fTriggerAnalysis->EnableHistograms();
+  fTriggerAnalysis->SetAnalyzeMC(AliDielectronMC::Instance()->HasMC());
   
   PostData(3,fEventStat);
   
@@ -105,59 +137,97 @@ void AliAnalysisTaskDielectronSE::UserExec(Option_t *)
   if (!fDielectron) return;
   
   AliAnalysisManager *man=AliAnalysisManager::GetAnalysisManager();
-  AliESDInputHandler *esdHandler=0x0;
-  if ( (esdHandler=dynamic_cast<AliESDInputHandler*>(man->GetInputEventHandler())) && esdHandler->GetESDpid() ){
-    AliDielectronVarManager::SetESDpid(esdHandler->GetESDpid());
+  Bool_t isESD=man->GetInputEventHandler()->IsA()==AliESDInputHandler::Class();
+  Bool_t isAOD=man->GetInputEventHandler()->IsA()==AliAODInputHandler::Class();
+
+  AliInputEventHandler* inputHandler = (AliInputEventHandler*) (man->GetInputEventHandler());
+  if (!inputHandler) return;
+
+  if ( inputHandler->GetPIDResponse() ){
+    AliDielectronVarManager::SetPIDResponse( inputHandler->GetPIDResponse() );
   } else {
-    //load esd pid bethe bloch parameters depending on the existance of the MC handler
-    // yes: MC parameters
-    // no:  data parameters
-    
-    //ESD case
-    if (man->GetInputEventHandler()->IsA()==AliESDInputHandler::Class()){
-      if (!AliDielectronVarManager::GetESDpid()){
-        
-        if (AliDielectronMC::Instance()->HasMC()) {
-          AliDielectronVarManager::InitESDpid();
-        } else {
-          AliDielectronVarManager::InitESDpid(1);
-        }
-      }
-    }
-    //AOD case
-    if (man->GetInputEventHandler()->IsA()==AliAODInputHandler::Class()){
-      if (!AliDielectronVarManager::GetAODpidUtil()){
-        if (AliDielectronMC::Instance()->HasMC()) {
-          AliDielectronVarManager::InitAODpidUtil();
-        } else {
-          AliDielectronVarManager::InitAODpidUtil(1);
-        }
-      }
-    }
+    AliFatal("This task needs the PID response attached to the input event handler!");
   }
+
   // Was event selected ?
-  AliInputEventHandler* inputHandler = (AliInputEventHandler*) (man->GetInputEventHandler());
   UInt_t isSelected = AliVEvent::kAny;
-  if( fSelectPhysics && inputHandler && inputHandler->GetEventSelection() ) {
-    isSelected = inputHandler->IsEventSelected();
-    isSelected&=fTriggerMask;
-  }
-  
+  if( fSelectPhysics && inputHandler){
+  if((isESD && inputHandler->GetEventSelection()) || isAOD){
+      isSelected = inputHandler->IsEventSelected();
+      isSelected&=fTriggerMask;
+      }
+   }
+
+
   //Before physics selection
-  fEventStat->Fill(0.);
+  fEventStat->Fill(kAllEvents);
   if (isSelected==0) {
     PostData(3,fEventStat);
     return;
   }
   //after physics selection
-  fEventStat->Fill(1.);
+  fEventStat->Fill(kSelectedEvents);
+
+  //V0and
+  if(fTriggerOnV0AND){
+  if(isESD){if (!fTriggerAnalysis->IsOfflineTriggerFired(static_cast<AliESDEvent*>(InputEvent()), AliTriggerAnalysis::kV0AND))
+            return;}
+  if(isAOD){if(!((static_cast<AliAODEvent*>(InputEvent()))->GetVZEROData()->GetV0ADecision() == AliVVZERO::kV0BB &&
+            (static_cast<AliAODEvent*>(InputEvent()))->GetVZEROData()->GetV0CDecision() == AliVVZERO::kV0BB) )
+            return;}
+   }
+
+
+  fEventStat->Fill(kV0andEvents);
+
+  //Fill Event histograms before the event filter
+  Double_t values[AliDielectronVarManager::kNMaxValues]={0};
+  Double_t valuesMC[AliDielectronVarManager::kNMaxValues]={0};
+  AliDielectronVarManager::Fill(InputEvent(),values);
+  Bool_t hasMC=AliDielectronMC::Instance()->HasMC();
+  if (hasMC) {
+    if (AliDielectronMC::Instance()->ConnectMCEvent())
+      AliDielectronVarManager::Fill(AliDielectronMC::Instance()->GetMCEvent(),valuesMC);
+  }
+  
+  AliDielectronHistos *h=fDielectron->GetHistoManager();
+  if (h){
+    if (h->GetHistogramList()->FindObject("Event_noCuts"))
+      h->FillClass("Event_noCuts",AliDielectronVarManager::kNMaxValues,values);
+    if (hasMC && h->GetHistogramList()->FindObject("MCEvent_noCuts"))
+      h->FillClass("Event_noCuts",AliDielectronVarManager::kNMaxValues,valuesMC);
+  }
+  
+  //event filter
+  if (fEventFilter) {
+    if (!fEventFilter->IsSelected(InputEvent())) return;
+  }
+  fEventStat->Fill(kFilteredEvents);
+  
+  //pileup
+  if (fRejectPileup){
+    if (InputEvent()->IsPileupFromSPD(3,0.8,3.,2.,5.)) return;
+  }
+  fEventStat->Fill(kPileupEvents);
   
   //bz for AliKF
   Double_t bz = InputEvent()->GetMagneticField();
   AliKFParticle::SetField( bz );
-  
+
+  // make an artificial shift in the electron nsigma. Configured in the Config file
+  AliDielectronPID::SetCorrVal((Double_t)InputEvent()->GetRunNumber());
+
+  //
+  // Actual data processing
+  //
   fDielectron->Process(InputEvent());
 
+  //statistics for number of selected candidates
+  Int_t ncandidates=fDielectron->GetPairArray(1)->GetEntriesFast();
+  if (ncandidates==1) fEventStat->Fill((kNbinsEvent));
+  else if (ncandidates>1) fEventStat->Fill((kNbinsEvent+1));
+
+  //Publish the data
   if (fDielectron->GetHistogramList()){
     PostData(1, const_cast<THashList*>(fDielectron->GetHistogramList()));
   }
index 6718328..6ddae5b 100644 (file)
@@ -16,9 +16,9 @@
 //#####################################################
 
 #include "AliAnalysisTaskSE.h"
-#include "AliDielectronPID.h"
 
 class AliDielectron;
+class AliTriggerAnalysis;
 class TH1D;
 
 class AliAnalysisTaskDielectronSE : public AliAnalysisTaskSE {
@@ -30,22 +30,31 @@ public:
 
   virtual void  UserExec(Option_t *option);
   virtual void  UserCreateOutputObjects();
-  //temporary
-  virtual void NotifyRun(){AliDielectronPID::SetCorrVal((Double_t)fCurrentRunNumber);}
   
   void UsePhysicsSelection(Bool_t phy=kTRUE) {fSelectPhysics=phy;}
   void SetTriggerMask(UInt_t mask) {fTriggerMask=mask;}
   UInt_t GetTriggerMask() const { return fTriggerMask; }
+
+  void SetEventFilter(AliAnalysisCuts * const filter) {fEventFilter=filter;}
+  void SetTriggerOnV0AND(Bool_t v0and=kTRUE)    { fTriggerOnV0AND=v0and;    }
+  void SetRejectPileup(Bool_t pileup=kTRUE)     { fRejectPileup=pileup;     }
   
   void SetDielectron(AliDielectron * const die) { fDielectron = die; }
   
 private:
+  enum {kAllEvents=0, kSelectedEvents, kV0andEvents, kFilteredEvents, kPileupEvents, kNbinsEvent};
   
   AliDielectron *fDielectron;             // Dielectron framework object
 
   Bool_t fSelectPhysics;             // Whether to use physics selection
   UInt_t fTriggerMask;               // Event trigger mask
-  
+  Bool_t fTriggerOnV0AND;            // if to trigger on V0and
+  Bool_t fRejectPileup;              // pileup rejection wanted
+
+  AliTriggerAnalysis *fTriggerAnalysis; //! trigger analysis class
+
+  AliAnalysisCuts *fEventFilter;     // event filter
+
   TH1D *fEventStat;                  //! Histogram with event statistics
   
   AliAnalysisTaskDielectronSE(const AliAnalysisTaskDielectronSE &c);
index 597b123..caec68f 100644 (file)
 #include <AliAnalysisManager.h>
 #include <AliVEvent.h>
 #include <AliTriggerAnalysis.h>
+#include <AliPIDResponse.h>
+#include <AliTPCPIDResponse.h>
 
 #include "AliDielectron.h"
 #include "AliDielectronHistos.h"
 #include "AliDielectronCF.h"
 #include "AliDielectronMC.h"
+#include "AliDielectronMixingHandler.h"
 #include "AliAnalysisTaskMultiDielectron.h"
 
 ClassImp(AliAnalysisTaskMultiDielectron)
@@ -46,8 +49,10 @@ AliAnalysisTaskMultiDielectron::AliAnalysisTaskMultiDielectron() :
   fListCF(),
   fSelectPhysics(kFALSE),
   fTriggerMask(AliVEvent::kMB),
+  fExcludeTriggerMask(0),
   fTriggerOnV0AND(kFALSE),
   fRejectPileup(kFALSE),
+  fTriggerLogic(kAny),
   fTriggerAnalysis(0x0),
   fEventFilter(0x0),
   fEventStat(0x0)
@@ -65,8 +70,10 @@ AliAnalysisTaskMultiDielectron::AliAnalysisTaskMultiDielectron(const char *name)
   fListCF(),
   fSelectPhysics(kFALSE),
   fTriggerMask(AliVEvent::kMB),
+  fExcludeTriggerMask(0),
   fTriggerOnV0AND(kFALSE),
   fRejectPileup(kFALSE),
+  fTriggerLogic(kAny),
   fTriggerAnalysis(0x0),
   fEventFilter(0x0),
   fEventStat(0x0)
@@ -85,7 +92,20 @@ AliAnalysisTaskMultiDielectron::AliAnalysisTaskMultiDielectron(const char *name)
   fListCF.SetOwner();
 }
 
+//_________________________________________________________________________________
+AliAnalysisTaskMultiDielectron::~AliAnalysisTaskMultiDielectron()
+{
+  //
+  // Destructor
+  //
 
+  //histograms and CF are owned by the dielectron framework.
+  //however they are streamed to file, so in the first place the
+  //lists need to be owner...
+  fListHistos.SetOwner(kFALSE);
+  fListCF.SetOwner(kFALSE);
+  
+}
 //_________________________________________________________________________________
 void AliAnalysisTaskMultiDielectron::UserCreateOutputObjects()
 {
@@ -95,8 +115,8 @@ void AliAnalysisTaskMultiDielectron::UserCreateOutputObjects()
 
   if (!fListHistos.IsEmpty()||!fListCF.IsEmpty()) return; //already initialised
 
-  AliAnalysisManager *man=AliAnalysisManager::GetAnalysisManager();
-  Bool_t isESD=man->GetInputEventHandler()->IsA()==AliESDInputHandler::Class();
+//   AliAnalysisManager *man=AliAnalysisManager::GetAnalysisManager();
+//   Bool_t isESD=man->GetInputEventHandler()->IsA()==AliESDInputHandler::Class();
 //   Bool_t isAOD=man->GetInputEventHandler()->IsA()==AliAODInputHandler::Class();
   
   TIter nextDie(&fListDielectron);
@@ -119,7 +139,7 @@ void AliAnalysisTaskMultiDielectron::UserCreateOutputObjects()
     fEventStat->GetXaxis()->SetBinLabel(4,"Bin4 not used");
     fEventStat->GetXaxis()->SetBinLabel(5,"Bin5 not used");
     
-    if (fTriggerOnV0AND&&isESD) fEventStat->GetXaxis()->SetBinLabel(3,"V0and triggers");
+    if(fTriggerOnV0AND) fEventStat->GetXaxis()->SetBinLabel(3,"V0and triggers");
     if (fEventFilter) fEventStat->GetXaxis()->SetBinLabel(4,"After Event Filter");
     if (fRejectPileup) fEventStat->GetXaxis()->SetBinLabel(5,"After Pileup rejection");
     
@@ -154,45 +174,31 @@ void AliAnalysisTaskMultiDielectron::UserExec(Option_t *)
   AliInputEventHandler* inputHandler = (AliInputEventHandler*) (man->GetInputEventHandler());
   if (!inputHandler) return;
   
+//   AliPIDResponse *pidRes=inputHandler->GetPIDResponse();
   if ( inputHandler->GetPIDResponse() ){
+    // for the 2.76 pass2 MC private train. Together with a sigma shift of -0.169
+//    pidRes->GetTPCResponse().SetSigma(4.637e-3,2.41332105409873257e+04);
     AliDielectronVarManager::SetPIDResponse( inputHandler->GetPIDResponse() );
   } else {
-    //load esd pid bethe bloch parameters depending on the existance of the MC handler
-    // yes: MC parameters
-    // no:  data parameters
-
-    //ESD case
-    if (isESD){
-      if (!AliDielectronVarManager::GetESDpid()){
-        
-        if (AliDielectronMC::Instance()->HasMC()) {
-          AliDielectronVarManager::InitESDpid();
-        } else {
-          AliDielectronVarManager::InitESDpid(1);
-        }
-      }
-    }
-    //AOD case
-    if (isAOD){
-      if (!AliDielectronVarManager::GetAODpidUtil()){
-        if (AliDielectronMC::Instance()->HasMC()) {
-          AliDielectronVarManager::InitAODpidUtil();
-        } else {
-          AliDielectronVarManager::InitAODpidUtil(1);
-        }
-      }
-    }
-  } 
-  // Was event selected ?
-  UInt_t isSelected = AliVEvent::kAny;
-  if( fSelectPhysics && inputHandler && inputHandler->GetEventSelection() ) {
-    isSelected = inputHandler->IsEventSelected();
-    isSelected&=fTriggerMask;
+    AliFatal("This task needs the PID response attached to the input event handler!");
   }
   
+  // Was event selected ?
+  ULong64_t isSelected = AliVEvent::kAny;
+  Bool_t isRejected = kFALSE;
+  if( fSelectPhysics && inputHandler){
+    if((isESD && inputHandler->GetEventSelection()) || isAOD){
+      isSelected = inputHandler->IsEventSelected();
+      if (fExcludeTriggerMask && (isSelected&fExcludeTriggerMask)) isRejected=kTRUE;
+      if (fTriggerLogic==kAny) isSelected&=fTriggerMask;
+      else if (fTriggerLogic==kExact) isSelected=((isSelected&fTriggerMask)==fTriggerMask);
+    }
+   }
   //Before physics selection
   fEventStat->Fill(kAllEvents);
-  if (isSelected==0) {
+  if (isSelected==0||isRejected) {
     PostData(3,fEventStat);
     return;
   }
@@ -200,10 +206,40 @@ void AliAnalysisTaskMultiDielectron::UserExec(Option_t *)
   fEventStat->Fill(kSelectedEvents);
 
   //V0and
-  if (fTriggerOnV0AND&&isESD){
-    if (!fTriggerAnalysis->IsOfflineTriggerFired(static_cast<AliESDEvent*>(InputEvent()), AliTriggerAnalysis::kV0AND)) return;
-  }
+  if(fTriggerOnV0AND){
+  if(isESD){if (!fTriggerAnalysis->IsOfflineTriggerFired(static_cast<AliESDEvent*>(InputEvent()), AliTriggerAnalysis::kV0AND))
+            return;}
+  if(isAOD){if(!((static_cast<AliAODEvent*>(InputEvent()))->GetVZEROData()->GetV0ADecision() == AliVVZERO::kV0BB &&
+            (static_cast<AliAODEvent*>(InputEvent()))->GetVZEROData()->GetV0CDecision() == AliVVZERO::kV0BB) )
+            return;}
+   }
+  
+
   fEventStat->Fill(kV0andEvents);
+
+  //Fill Event histograms before the event filter
+  TIter nextDie(&fListDielectron);
+  AliDielectron *die=0;
+  Double_t values[AliDielectronVarManager::kNMaxValues]={0};
+  Double_t valuesMC[AliDielectronVarManager::kNMaxValues]={0};
+  AliDielectronVarManager::Fill(InputEvent(),values);
+  AliDielectronVarManager::Fill(InputEvent(),valuesMC);
+  Bool_t hasMC=AliDielectronMC::Instance()->HasMC();
+  if (hasMC) {
+    if (AliDielectronMC::Instance()->ConnectMCEvent())
+      AliDielectronVarManager::Fill(AliDielectronMC::Instance()->GetMCEvent(),valuesMC);
+  }
+
+  while ( (die=static_cast<AliDielectron*>(nextDie())) ){
+    AliDielectronHistos *h=die->GetHistoManager();
+    if (h){
+      if (h->GetHistogramList()->FindObject("Event_noCuts"))
+        h->FillClass("Event_noCuts",AliDielectronVarManager::kNMaxValues,values);
+      if (hasMC && h->GetHistogramList()->FindObject("MCEvent_noCuts"))
+        h->FillClass("Event_noCuts",AliDielectronVarManager::kNMaxValues,valuesMC);
+    }
+  }
+  nextDie.Reset();
   
   //event filter
   if (fEventFilter) {
@@ -224,8 +260,8 @@ void AliAnalysisTaskMultiDielectron::UserExec(Option_t *)
   AliDielectronPID::SetCorrVal((Double_t)InputEvent()->GetRunNumber());
   
   //Process event in all AliDielectron instances
-  TIter nextDie(&fListDielectron);
-  AliDielectron *die=0;
+  //   TIter nextDie(&fListDielectron);
+  //   AliDielectron *die=0;
   Int_t idie=0;
   while ( (die=static_cast<AliDielectron*>(nextDie())) ){
     die->Process(InputEvent());
@@ -252,6 +288,11 @@ void AliAnalysisTaskMultiDielectron::FinishTaskOutput()
   AliDielectron *die=0;
   while ( (die=static_cast<AliDielectron*>(nextDie())) ){
     die->SaveDebugTree();
+    AliDielectronMixingHandler *mix=die->GetMixingHandler();
+//    printf("\n\n\n===============\ncall mix in Terminate: %p (%p)\n=================\n\n",mix,die);
+    if (mix) mix->MixRemaining(die);
   }
+  PostData(1, &fListHistos);
+  PostData(2, &fListCF);
 }
 
index 16ea68f..d3192c5 100644 (file)
@@ -31,7 +31,9 @@ class AliAnalysisTaskMultiDielectron : public AliAnalysisTaskSE {
 public:
   AliAnalysisTaskMultiDielectron();
   AliAnalysisTaskMultiDielectron(const char *name);
-  virtual ~AliAnalysisTaskMultiDielectron(){  }
+  virtual ~AliAnalysisTaskMultiDielectron();
+
+  enum ETriggerLogig {kAny, kExact};
 
   virtual void UserExec(Option_t *option);
   virtual void UserCreateOutputObjects();
@@ -40,8 +42,12 @@ public:
 //   virtual void NotifyRun(){AliDielectronPID::SetCorrVal((Double_t)fCurrentRunNumber);}
   
   void UsePhysicsSelection(Bool_t phy=kTRUE) {fSelectPhysics=phy;}
-  void SetTriggerMask(UInt_t mask) {fTriggerMask=mask;}
+  void SetTriggerMask(ULong64_t mask) {fTriggerMask=mask;}
   UInt_t GetTriggerMask() const { return fTriggerMask; }
+  void SetExcludeTriggerMask(ULong64_t mask) {fExcludeTriggerMask=mask;}
+  UInt_t GetExcludeTriggerMask() const { return fExcludeTriggerMask; }
+  void SetTriggerLogic(ETriggerLogig log) {fTriggerLogic=log;}
+  ETriggerLogig GetTriggerLogic() const {return fTriggerLogic;}
 
   void SetEventFilter(AliAnalysisCuts * const filter) {fEventFilter=filter;}
   void SetTriggerOnV0AND(Bool_t v0and=kTRUE)    { fTriggerOnV0AND=v0and;    }
@@ -56,8 +62,11 @@ protected:
 
   Bool_t fSelectPhysics;             // Whether to use physics selection
   UInt_t fTriggerMask;               // Event trigger mask
+  UInt_t fExcludeTriggerMask;        // Triggers to exclude from the analysis
   Bool_t fTriggerOnV0AND;            // if to trigger on V0and
   Bool_t fRejectPileup;              // pileup rejection wanted
+
+  ETriggerLogig fTriggerLogic;       // trigger logic: any or all bits need to be matching
   
   AliTriggerAnalysis *fTriggerAnalysis; //! trigger analysis class
 
@@ -68,6 +77,6 @@ protected:
   AliAnalysisTaskMultiDielectron(const AliAnalysisTaskMultiDielectron &c);
   AliAnalysisTaskMultiDielectron& operator= (const AliAnalysisTaskMultiDielectron &c);
   
-  ClassDef(AliAnalysisTaskMultiDielectron, 1); //Analysis Task handling multiple instances of AliDielectron
+  ClassDef(AliAnalysisTaskMultiDielectron, 2); //Analysis Task handling multiple instances of AliDielectron
 };
 #endif
diff --git a/PWGDQ/dielectron/AliAnalysisTaskSingleParticle.cxx b/PWGDQ/dielectron/AliAnalysisTaskSingleParticle.cxx
new file mode 100644 (file)
index 0000000..31b3e47
--- /dev/null
@@ -0,0 +1,531 @@
+/*************************************************************************
+* Copyright(c) 1998-2009, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+//     Analysis task for computing single particle efficiencies          //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+#include <TChain.h>
+#include <TH1D.h>
+#include <TList.h>
+#include <THashList.h>
+#include <TString.h>
+
+#include <AliPID.h>
+#include <AliCFContainer.h>
+#include <AliInputEventHandler.h>
+#include <AliESDInputHandler.h>
+#include <AliAODInputHandler.h>
+#include <AliAnalysisManager.h>
+#include <AliVEvent.h>
+#include <AliESDEvent.h>
+#include <AliESDv0.h>
+#include <AliESDv0Cuts.h>
+#include <AliESDv0KineCuts.h>
+#include <AliKFVertex.h>
+#include <AliESDfriendTrack.h>
+#include <AliESDfriend.h>
+#include <../TRD/AliTRDseedV1.h>
+#include <../TRD/AliTRDcluster.h>
+#include <../TRD/AliTRDtrackV1.h>
+
+#include "AliDielectron.h"
+#include "AliDielectronHistos.h"
+#include "AliDielectronPair.h"
+#include "AliDielectronCF.h"
+#include "AliDielectronMC.h"
+#include "AliDielectronHistos.h"
+#include "AliAnalysisTaskSingleParticle.h"
+
+#include <iostream>
+using namespace std;
+
+ClassImp(AliAnalysisTaskSingleParticle)
+
+//_________________________________________________________________________________
+AliAnalysisTaskSingleParticle::AliAnalysisTaskSingleParticle() :
+  AliAnalysisTaskSE(),
+  fCfContainer(0x0),
+  fHistos(0x0),
+  fHistogramList(),
+  fSelectPhysics(kTRUE),
+  fTriggerMask(AliVEvent::kMB),
+  fRejectPileup(kFALSE),
+  fFillTRDfriendPH(kFALSE),
+  fEventFilter(0x0),
+  fTrackFilter(0x0),
+  fPairFilter(0x0),
+  fV0Cuts(0x0),
+  fLambdaFilter(0x0),
+  fK0sFilter(0x0),
+  fV0KineCuts(0x0),
+  fCFNVars(0),
+  fEventStat(0x0)
+{
+  //
+  // Constructor
+  //
+  for(Int_t i=0; i<kNMaxDimensions; ++i) {
+    fCFVarsEnabled[i] = -1; fCFVarsNbins[i] = 0;
+    fCFVarRanges[i][0] = 0.0; fCFVarRanges[i][1] = -1.0;
+    fCFVarBins[i] = "";
+  }
+}
+
+//_________________________________________________________________________________
+AliAnalysisTaskSingleParticle::AliAnalysisTaskSingleParticle(const char *name) :
+  AliAnalysisTaskSE(name),
+  fCfContainer(0x0),
+  fHistos(0x0),
+  fHistogramList(),
+  fSelectPhysics(kTRUE),
+  fTriggerMask(AliVEvent::kMB),
+  fRejectPileup(kFALSE),
+  fFillTRDfriendPH(kFALSE),
+  fEventFilter(0x0),
+  fTrackFilter(0x0),
+  fPairFilter(0x0),
+  fV0Cuts(0x0),
+  fLambdaFilter(0x0),
+  fK0sFilter(0x0),
+  fV0KineCuts(0x0),
+  fCFNVars(0),
+  fEventStat(0x0)
+{
+  //
+  // Constructor
+  //
+  for(Int_t i=0; i<kNMaxDimensions; ++i) {
+    fCFVarsEnabled[i] = -1; fCFVarsNbins[i] = 0;
+    fCFVarRanges[i][0] = 0.0; fCFVarRanges[i][1] = -1.0;
+    fCFVarBins[i] = "";
+  }
+  fHistogramList.SetName("QAhistos");
+  fHistogramList.SetOwner();
+  DefineInput(0, TChain::Class());
+  DefineOutput(1, AliCFContainer::Class());
+  DefineOutput(2, TList::Class());
+  DefineOutput(3, TH1D::Class());
+}
+
+
+//____________________________________________________________________
+AliAnalysisTaskSingleParticle::~AliAnalysisTaskSingleParticle()
+{
+  //
+  // Destructor
+  // 
+  fHistogramList.SetOwner(kFALSE);
+  if(fHistos) delete fHistos;
+  delete fCfContainer;
+}
+
+
+//____________________________________________________________________
+void AliAnalysisTaskSingleParticle::AddCFVar(Int_t var, Int_t nbins, Double_t lowLim, Double_t highLim) {
+  //
+  // Configure variables for the CF container
+  //
+  if(fCFNVars>=kNMaxDimensions) return;
+  fCFVarsEnabled[fCFNVars] = var;
+  fCFVarsNbins[fCFNVars] = nbins;
+  fCFVarRanges[fCFNVars][0] = lowLim;
+  fCFVarRanges[fCFNVars][1] = highLim;
+  ++fCFNVars;
+}
+
+
+//____________________________________________________________________
+void AliAnalysisTaskSingleParticle::AddCFVar(Int_t var, const Char_t* bins) {
+  //
+  // Configure variables for the CF container
+  //
+  if(fCFNVars>=kNMaxDimensions) return;
+  fCFVarsEnabled[fCFNVars] = var;
+  fCFVarBins[fCFNVars] = bins;
+  ++fCFNVars;
+}
+
+
+//_________________________________________________________________________________
+void AliAnalysisTaskSingleParticle::UserCreateOutputObjects()
+{
+  //
+  // Initialize CF container
+  //
+  if(fCfContainer) return;
+  if(!fHistogramList.IsEmpty()) return;
+  
+  if (!fEventStat){
+    fEventStat=new TH1D("hEventStat","Event statistics",4,-0.5,3.5);
+    fEventStat->GetXaxis()->SetBinLabel(1,"Before Phys. Sel.");
+    fEventStat->GetXaxis()->SetBinLabel(2,"After Phys. Sel.");
+    fEventStat->GetXaxis()->SetBinLabel(3,"After event filter");
+    fEventStat->GetXaxis()->SetBinLabel(4,"After pileup rejection");
+  }
+  
+  //Bool_t hasMC = AliDielectronMC::Instance()->HasMC();
+  
+  if(!fCfContainer) {
+    for(Int_t ivar=0; ivar<fCFNVars; ++ivar) {
+      if(fCFVarBins[ivar][0]!='\0') {
+        TObjArray* arr = fCFVarBins[ivar].Tokenize(",");
+        fCFVarsNbins[ivar] = arr->GetEntries()-1;
+      }
+    }
+    fCFVarsNbins[fCFNVars] = AliPID::kSPECIES;
+    //
+    // If fFillTRDfriendPH is toggled then add some predefined variables to the CF
+    // Hardcoded variables and binning !! TODO: Implement them in the VarManager ??
+    // This container is filled for every TRD time bin, and every tracklet from a track
+    Double_t phLimits[2] = {0.0, 2000.}; Int_t phBins = 200;
+    Double_t detLimits[2] = {-0.5, 539.5}; Int_t detBins = 540;
+    const Int_t kNTrdMomBins = 17;
+    Double_t trdMomLimits[kNTrdMomBins+1] = {0.0, 0.5, 0.7, 0.9, 1.1, 1.3, 1.5, 1.7, 1.9, 2.1, 2.5, 3.0, 3.5, 4.0, 5.0, 6.0, 8.0, 10.0};
+    Int_t trdNtb = 30; Double_t trdTbLims[2] = {0.5, 30.5};
+    Int_t trdQtotNbins = 200; Double_t trdQtotLims[2] = {0.0, 10000.};
+    fCFVarsNbins[fCFNVars+1] = kNTrdMomBins;
+    fCFVarsNbins[fCFNVars+2] = detBins;
+    fCFVarsNbins[fCFNVars+3] = trdNtb;
+    fCFVarsNbins[fCFNVars+4] = phBins;
+    fCFVarsNbins[fCFNVars+5] = trdQtotNbins;
+    
+    if(fCFNVars>0 || fFillTRDfriendPH) {
+      fCfContainer = new AliCFContainer("SingleParticle", "Single Particle CF", 1, (fFillTRDfriendPH ? fCFNVars+6 : fCFNVars+1), fCFVarsNbins);
+      for(Int_t ivar=0; ivar<fCFNVars; ++ivar) {
+        if(fCFVarBins[ivar][0]=='\0')
+         fCfContainer->SetBinLimits(ivar, fCFVarRanges[ivar][0], fCFVarRanges[ivar][1]);
+        else {
+         TObjArray* arr = fCFVarBins[ivar].Tokenize(",");
+         if(arr->GetEntries()-1>0) {
+           Double_t* binLims = new Double_t[arr->GetEntries()];
+           for(Int_t ib=0;ib<arr->GetEntries();++ib) {
+             TString binStr = arr->At(ib)->GetName();
+             binLims[ib] = binStr.Atof();
+           }
+           fCfContainer->SetBinLimits(ivar, binLims);
+         }
+        }
+        fCfContainer->SetVarTitle(ivar, AliDielectronVarManager::GetValueName(fCFVarsEnabled[ivar]));
+      }
+      fCfContainer->SetBinLimits(fCFNVars, -0.5+AliPID::kElectron, 0.5+AliPID::kProton);
+      fCfContainer->SetVarTitle(fCFNVars, "specie");
+      if(fFillTRDfriendPH) {
+       fCfContainer->SetBinLimits(fCFNVars+1, trdMomLimits);
+       fCfContainer->SetVarTitle(fCFNVars+1, "TRD_trackletMom");
+       fCfContainer->SetBinLimits(fCFNVars+2, detLimits[0], detLimits[1]);
+       fCfContainer->SetVarTitle(fCFNVars+2, "TRD_detector");
+       fCfContainer->SetBinLimits(fCFNVars+3, trdTbLims[0], trdTbLims[1]);
+       fCfContainer->SetVarTitle(fCFNVars+3, "TRD_tb");
+       fCfContainer->SetBinLimits(fCFNVars+4, phLimits[0], phLimits[1]);
+       fCfContainer->SetVarTitle(fCFNVars+4, "TRD_PH");
+       fCfContainer->SetBinLimits(fCFNVars+5, trdQtotLims[0], trdQtotLims[1]);
+       fCfContainer->SetVarTitle(fCFNVars+5, "TRD_Qtot");
+      }
+      fCfContainer->SetStepTitle(0, "Tracking");
+    }
+  }
+  
+  if(fHistos) {
+    fHistogramList.Add(const_cast<THashList*>(fHistos->GetHistogramList()));
+  }
+  
+  if(fCfContainer) PostData(1, fCfContainer);
+  if(fHistos) PostData(2, &fHistogramList);
+  PostData(3, fEventStat);
+}
+
+//_________________________________________________________________________________
+void AliAnalysisTaskSingleParticle::UserExec(Option_t *)
+{
+  //
+  // Main loop. Called for every event
+  //
+
+  AliAnalysisManager *man=AliAnalysisManager::GetAnalysisManager();
+  //Bool_t isESD=man->GetInputEventHandler()->IsA()==AliESDInputHandler::Class();
+  //Bool_t isAOD=man->GetInputEventHandler()->IsA()==AliAODInputHandler::Class();
+  
+  AliInputEventHandler* inputHandler = (AliInputEventHandler*) (man->GetInputEventHandler());
+  if (!inputHandler) return;
+  
+  if ( inputHandler->GetPIDResponse() ){
+    AliDielectronVarManager::SetPIDResponse( inputHandler->GetPIDResponse() );
+  } else {
+    AliFatal("This task needs the PID response attached to the input event handler!");   
+  } 
+  // Was event selected ?
+  UInt_t isSelected = AliVEvent::kAny;
+  if( fSelectPhysics && inputHandler && inputHandler->GetEventSelection() ) {
+    isSelected = inputHandler->IsEventSelected();
+    isSelected&=fTriggerMask;
+  }
+  
+  //Before physics selection
+  fEventStat->Fill(0);
+  if (isSelected==0) {
+    PostData(3,fEventStat);
+    return;
+  }
+  //after physics selection
+  fEventStat->Fill(1);
+
+  //event filter
+  if (fEventFilter) {
+    if (!fEventFilter->IsSelected(InputEvent())) {PostData(3, fEventStat); return;}
+  }
+  fEventStat->Fill(2);
+  
+  //pileup
+  if (fRejectPileup){
+    if (InputEvent()->IsPileupFromSPD(3,0.8,3.,2.,5.)) {PostData(3, fEventStat); return;}
+  }
+  fEventStat->Fill(3);
+  
+  if(!fCfContainer) {PostData(3, fEventStat); return;}
+  //bz for AliKF
+  Double_t bz = InputEvent()->GetMagneticField();
+  AliKFParticle::SetField( bz );
+
+  AliDielectronPID::SetCorrVal((Double_t)InputEvent()->GetRunNumber());
+  
+  AliESDEvent* esd = (AliESDEvent*)InputEvent();
+  AliDielectronVarManager::SetEvent(esd);
+  
+  Double_t valuesPos[AliDielectronVarManager::kNMaxValues];
+  Double_t valuesNeg[AliDielectronVarManager::kNMaxValues];
+  Double_t valuesPair[AliDielectronVarManager::kNMaxValues];
+  AliDielectronVarManager::Fill(esd, valuesPos);
+  AliDielectronVarManager::Fill(esd, valuesNeg);
+  AliDielectronVarManager::Fill(esd, valuesPair);
+  
+  if(fHistos && fHistos->GetHistogramList()->FindObject("Event"))
+    fHistos->FillClass("Event", AliDielectronVarManager::kNMaxValues, valuesPos);
+  
+  const AliESDVertex *primaryVertex = esd->GetPrimaryVertex();
+  AliKFVertex primaryVertexKF(*primaryVertex);
+    
+  fV0KineCuts->SetEvent(esd);
+  fV0KineCuts->SetPrimaryVertex(&primaryVertexKF);
+  
+  Int_t pdgV0=0; Int_t pdgP=0; Int_t pdgN=0;
+  for(Int_t iV0=0; iV0<InputEvent()->GetNumberOfV0s(); ++iV0) {   // loop over V0s
+    //cout << "iV0 = " << iV0 << endl;
+    AliESDv0 *v0 = esd->GetV0(iV0);
+       
+    AliESDtrack* legPos = esd->GetTrack(v0->GetPindex());
+    AliESDtrack* legNeg = esd->GetTrack(v0->GetNindex());
+    if(legPos->GetSign() == legNeg->GetSign()) {
+      //cout << "V0 rejected: same sign legs" << endl;
+      continue;
+    }
+
+    //To avoid ghosts test of trunk for the refit
+    if(!(legPos->GetStatus() & AliESDtrack::kTPCrefit)) {
+      //cout << "pos leg rejected: no TPCrefit" << endl;
+      continue;
+    }
+    if(!(legNeg->GetStatus() & AliESDtrack::kTPCrefit)) {
+      //cout << "neg leg rejected: no TPCrefit" << endl;
+      continue;
+    }
+    
+    Bool_t v0ChargesAreCorrect = (legPos->GetSign()==+1 ? kTRUE : kFALSE);
+    legPos = (!v0ChargesAreCorrect ? esd->GetTrack(v0->GetNindex()) : legPos);
+    legNeg = (!v0ChargesAreCorrect ? esd->GetTrack(v0->GetPindex()) : legNeg);
+    
+    Bool_t good = fV0KineCuts->ProcessV0(v0, pdgV0, pdgP, pdgN);
+    if(!good) {
+      //cout << "V0KineCuts rejected V0" << endl;
+      continue;
+    }
+    
+    if(!fFillTRDfriendPH) {
+      //cout << "No TRD friend filling" << endl;
+      if(pdgV0!=22) continue;
+      if(TMath::Abs(pdgN)!=11) continue;
+      if(TMath::Abs(pdgP)!=11) continue;
+    }
+    /*
+    // V0 standard cuts
+    if(fV0Cuts) {
+      TList v0List;
+      v0List.Add(v0);
+      v0List.Add(legPos); v0List.Add(legNeg);
+      v0List.Add(const_cast<AliESDVertex*>(primaryVertex));
+      if(!fV0Cuts->IsSelected(&v0List)) continue;
+    }*/
+    
+    // additional track filtering
+    if(fTrackFilter && !fTrackFilter->IsSelected(legPos)) {
+      //cout << "pos leg rejected: track filter" << endl;
+      continue;
+    }
+    if(fTrackFilter && !fTrackFilter->IsSelected(legNeg)) {
+      //cout << "neg leg rejected: track filter" << endl;
+      continue;
+    }
+    
+    AliKFParticle* posKF = (v0ChargesAreCorrect ? new AliKFParticle(*(v0->GetParamP()),pdgP) : new AliKFParticle(*(v0->GetParamN()),pdgN));
+    AliKFParticle* negKF = (v0ChargesAreCorrect ? new AliKFParticle(*(v0->GetParamN()),pdgN) : new AliKFParticle(*(v0->GetParamP()),pdgP));
+    AliDielectronPair pair;
+    pair.SetTracks(posKF, negKF, legPos, legNeg);
+    pair.SetType(1);
+    if(fPairFilter && !fPairFilter->IsSelected(&pair)) {
+      //cout << "diele pair rejected: pair filter" << endl;
+      continue;
+    }
+    
+    // additional filtering on the KF pair (mass, chi2, etc.)
+    // Gamma conversion inclusion cuts
+    /*
+    AliKFParticle* posKFGammaEle = (v0ChargesAreCorrect ? new AliKFParticle(*(v0->GetParamP()),-11) : new AliKFParticle(*(v0->GetParamN()),-11));
+    AliKFParticle* negKFGammaEle = (v0ChargesAreCorrect ? new AliKFParticle(*(v0->GetParamN()),+11) : new AliKFParticle(*(v0->GetParamP()),+11));
+    AliDielectronPair gammaPair;
+    gammaPair.SetTracks(posKFGammaEle, negKFGammaEle, legPos, legNeg);
+    gammaPair.SetType(1);
+    if(fPairFilter && !fPairFilter->IsSelected(&gammaPair)) continue;
+    */
+    /*
+    // Lambda exclusion cuts
+    AliKFParticle* posKFLambdaPro = (v0ChargesAreCorrect ? new AliKFParticle(*(v0->GetParamP()),2212) : new AliKFParticle(*(v0->GetParamN()),2212));
+    AliKFParticle* negKFLambdaPio = (v0ChargesAreCorrect ? new AliKFParticle(*(v0->GetParamN()),-211) : new AliKFParticle(*(v0->GetParamP()),-211));
+    AliDielectronPair lambdaPair;
+    lambdaPair.SetTracks(posKFLambdaPro, negKFLambdaPio, legPos, legNeg);
+    lambdaPair.SetType(1);
+    if(fLambdaFilter && fLambdaFilter->IsSelected(&lambdaPair)) continue;
+    // Anti-Lambda exclusion cuts
+    AliKFParticle* posKFALambdaPio = (v0ChargesAreCorrect ? new AliKFParticle(*(v0->GetParamP()),211) : new AliKFParticle(*(v0->GetParamN()),211));
+    AliKFParticle* negKFALambdaPro = (v0ChargesAreCorrect ? new AliKFParticle(*(v0->GetParamN()),-2212) : new AliKFParticle(*(v0->GetParamP()),-2212));
+    AliDielectronPair alambdaPair;
+    alambdaPair.SetTracks(posKFALambdaPio, negKFALambdaPro, legPos, legNeg);
+    alambdaPair.SetType(1);
+    if(fLambdaFilter && fLambdaFilter->IsSelected(&alambdaPair)) continue;
+    // K0s exclusion cuts
+    AliKFParticle* posKFK0sPio = (v0ChargesAreCorrect ? new AliKFParticle(*(v0->GetParamP()),211) : new AliKFParticle(*(v0->GetParamN()),211));
+    AliKFParticle* negKFK0sPio = (v0ChargesAreCorrect ? new AliKFParticle(*(v0->GetParamN()),-211) : new AliKFParticle(*(v0->GetParamP()),-211));
+    AliDielectronPair k0sPair;
+    k0sPair.SetTracks(posKFK0sPio, negKFK0sPio, legPos, legNeg);
+    k0sPair.SetType(1);
+    if(fK0sFilter && fK0sFilter->IsSelected(&k0sPair)) continue;
+    */
+    
+    //  Fill histograms and the CF container
+    AliDielectronVarManager::Fill(legPos, valuesPos);
+    AliDielectronVarManager::Fill(legNeg, valuesNeg);
+    
+    if(fHistos && fHistos->GetHistogramList()->FindObject("Track_Pos"))
+      fHistos->FillClass("Track_Pos", AliDielectronVarManager::kNMaxValues, valuesPos);
+    if(fHistos && fHistos->GetHistogramList()->FindObject("Track_Neg"))
+      fHistos->FillClass("Track_Neg", AliDielectronVarManager::kNMaxValues, valuesNeg);
+    
+    AliDielectronVarManager::Fill(&pair, valuesPair);
+    if(fHistos && fHistos->GetHistogramList()->FindObject(Form("Pair_%s",AliDielectron::PairClassName(1))))
+      fHistos->FillClass(Form("Pair_%s",AliDielectron::PairClassName(1)), AliDielectronVarManager::kNMaxValues, valuesPair);
+    
+    if(valuesPos[AliDielectronVarManager::kPOut]>=0.5)
+      FillContainer(0, valuesPos, (v0ChargesAreCorrect ? v0->GetPindex() : v0->GetNindex()), (v0ChargesAreCorrect ? pdgP : pdgN));
+    if(valuesNeg[AliDielectronVarManager::kPOut]>=0.5)
+      FillContainer(0, valuesNeg, (v0ChargesAreCorrect ? v0->GetNindex() : v0->GetPindex()), (v0ChargesAreCorrect ? pdgN : pdgP));
+  }   // end loop over online V0s
+
+  //delete gammaPair;
+
+  PostData(1, fCfContainer);
+  PostData(2, &fHistogramList);
+  PostData(3, fEventStat);
+}
+
+//_________________________________________________________________________________
+void AliAnalysisTaskSingleParticle::FinishTaskOutput()
+{
+  //
+  //
+  //
+}
+
+
+//_________________________________________________________________________________
+void AliAnalysisTaskSingleParticle::FillContainer(Int_t step, const Double_t* values, Int_t trackId, Int_t pdg) {
+  //
+  // Fill the CF container
+  //
+  Double_t valuesCF[kNMaxDimensions];
+  for(Int_t i=0; i<fCFNVars; ++i) valuesCF[i] = values[fCFVarsEnabled[i]];
+  
+  Double_t pid = -1.0;
+  if(TMath::Abs(pdg)==11)   pid = AliPID::kElectron;
+  if(TMath::Abs(pdg)==13)   pid = AliPID::kMuon;
+  if(TMath::Abs(pdg)==211)  pid = AliPID::kPion;
+  if(TMath::Abs(pdg)==321)  pid = AliPID::kKaon;
+  if(TMath::Abs(pdg)==2212) pid = AliPID::kProton;
+  valuesCF[fCFNVars] = pid;
+  
+  if(fFillTRDfriendPH) {
+    AliESDfriendTrack* friendTrk = fESDfriend->GetTrack(trackId);
+    if(!friendTrk) return;
+    if(values[AliDielectronVarManager::kTRDntracklets]>0.001) {
+      TObject* o=0x0; Int_t ical = 0; 
+      AliTRDtrackV1* trdTrack=0x0;
+      while(1) {
+       o = friendTrk->GetCalibObject(ical++);
+       if(!o) break;
+       TString objName = o->IsA()->GetName();
+       if(!objName.Contains("AliTRDtrackV1")) continue;
+       trdTrack = dynamic_cast<AliTRDtrackV1*>(o);
+       break;
+      }
+      if(!trdTrack) return;
+      
+      Double_t charge = 0.0;
+      for(Int_t ipl = 0; ipl < 6; ipl++) {  // loop over TRD layers
+       AliTRDseedV1 *tracklet = trdTrack->GetTracklet(ipl);
+       if(!tracklet) continue;
+       if(!tracklet->IsOK()) continue;
+       valuesCF[fCFNVars+1] = tracklet->GetMomentum();
+       valuesCF[fCFNVars+2] = tracklet->GetDetector();
+       charge = 0.0;
+       for(Int_t itb = 0; itb < AliTRDseedV1::kNtb; itb++){
+         AliTRDcluster *c = tracklet->GetClusters(itb);
+         AliTRDcluster *c1 = tracklet->GetClusters(itb + AliTRDseedV1::kNtb);  // second pad row
+         if(c) charge += TMath::Abs(c->GetQ()); //
+         if(c1) charge += TMath::Abs(c1->GetQ());
+       }
+       valuesCF[fCFNVars+5] = charge;
+       
+       for(Int_t itb = 0; itb < AliTRDseedV1::kNtb; itb++){
+         AliTRDcluster *c = tracklet->GetClusters(itb);
+         AliTRDcluster *c1 = tracklet->GetClusters(itb + AliTRDseedV1::kNtb);  // second pad row
+         if(!(c || c1)) continue;
+         AliTRDcluster *cptr = (c ? c : c1);
+         Int_t tcal = cptr->GetLocalTimeBin();
+         Float_t sig = 0;
+         if(c) sig += TMath::Abs(c->GetQ()); //
+         if(c1) sig += TMath::Abs(c1->GetQ());
+         valuesCF[fCFNVars+3] = tcal;
+         valuesCF[fCFNVars+4] = sig;
+         
+         fCfContainer->Fill(valuesCF, step);
+       }        // end loop over time bins
+      }       // end loop over tracklets
+    }      // end if track has TRD tracklets
+  }     // end if fill TRD friend PH
+  if(!fFillTRDfriendPH)
+    fCfContainer->Fill(valuesCF, step);
+}
+
diff --git a/PWGDQ/dielectron/AliAnalysisTaskSingleParticle.h b/PWGDQ/dielectron/AliAnalysisTaskSingleParticle.h
new file mode 100644 (file)
index 0000000..e8de5a4
--- /dev/null
@@ -0,0 +1,92 @@
+#ifndef ALIANALYSISTASKSINGLEPARTICLE_H
+#define ALIANALYSISTASKSINGLEPARTICLE_H
+
+//===============================================================
+//
+// Analysis task for constructing MC or data driven single particle efficiencies
+//
+// Ionut C. Arsene, EMMI-GSI, 2011/12/07 
+//
+//===============================================================
+
+#include "TList.h"
+
+#include "AliAnalysisTaskSE.h"
+
+class TH1D;
+class TList;
+class AliAnalysisCuts;
+class AliCFContainer;
+class AliVEvent;
+class AliDielectronHistos;
+class AliESDv0Cuts;
+class AliESDv0KineCuts;
+
+class AliAnalysisTaskSingleParticle : public AliAnalysisTaskSE {
+  
+public:
+  enum { kNMaxDimensions = 20 };
+    
+  AliAnalysisTaskSingleParticle();
+  AliAnalysisTaskSingleParticle(const char *name);
+  virtual ~AliAnalysisTaskSingleParticle();
+
+  virtual void UserExec(Option_t *option);
+  virtual void UserCreateOutputObjects();
+  virtual void FinishTaskOutput();
+    
+  void SetFillTRDfriendPH(Bool_t fill=kTRUE) {fFillTRDfriendPH = fill;}
+  void UsePhysicsSelection(Bool_t phy=kTRUE) {fSelectPhysics=phy;}
+  void SetTriggerMask(UInt_t mask) {fTriggerMask=mask;}
+  UInt_t GetTriggerMask() const { return fTriggerMask; }
+  void SetRejectPileup(Bool_t pileup=kTRUE)     { fRejectPileup=pileup;     }
+  
+  void SetEventFilter(AliAnalysisCuts * const filter) {fEventFilter=filter;}
+  void SetTrackFilter(AliAnalysisCuts * const filter) {fTrackFilter=filter;}
+  void SetPairFilter(AliAnalysisCuts* const filter) {fPairFilter=filter;}
+  void SetV0Cuts(AliESDv0Cuts* const cuts) {fV0Cuts = cuts;}
+  void SetLambdaFilter(AliAnalysisCuts* const filter) {fLambdaFilter = filter;}
+  void SetK0sFilter(AliAnalysisCuts* const filter) {fK0sFilter = filter;}
+  void SetHistogramManager(AliDielectronHistos * const histos) { fHistos=histos; }
+  void SetV0KineCuts(AliESDv0KineCuts* const v0cuts) {fV0KineCuts = v0cuts;}
+
+  void AddCFVar(Int_t var, Int_t nbins, Double_t lowLim, Double_t highLim);
+  void AddCFVar(Int_t var, const Char_t* bins);
+
+protected:
+//  enum {kAllEvents=0, kPhysicsSelectionEvents, kFilteredEvents, kEventStatBins};
+//  enum {kEventVtxZ=0, kNTracklets, kCentrality, kPt, kPin, kPhi, kEta, kDeltaPt, kDeltaPhi, kDeltaEta, kTPCnCls, kTPCnSigEle, kTPCnSigPio, kTPCnSigPro, kNVariables}; 
+
+  AliCFContainer*  fCfContainer;      //  CF container
+  AliDielectronHistos *fHistos;       // Histogram manager
+  TList            fHistogramList;    // histogram list from the manager
+
+  Bool_t           fSelectPhysics;    // Whether to use physics selection
+  UInt_t           fTriggerMask;      // Event trigger mask
+  Bool_t           fRejectPileup;     // pileup rejection wanted
+  Bool_t           fFillTRDfriendPH;  // use the task to fill a TRD tracklet PH container
+
+  AliAnalysisCuts* fEventFilter;      // event filter
+  AliAnalysisCuts* fTrackFilter;      // tracking filter
+  AliAnalysisCuts* fPairFilter;       // pair filter
+  AliESDv0Cuts*    fV0Cuts;           // v0 standard filter
+  AliAnalysisCuts* fLambdaFilter;     // additional cuts for lambda v0 exclusion
+  AliAnalysisCuts* fK0sFilter;        // additional cuts for K0s v0 exclusion
+  AliESDv0KineCuts* fV0KineCuts;      // V0 kine cuts
+  
+  Int_t            fCFNVars;          // number of CF variables
+  Int_t            fCFVarsEnabled[kNMaxDimensions];    // id for every dimension
+  Int_t            fCFVarsNbins[kNMaxDimensions];      // number of bins for every CF dimension
+  Double_t         fCFVarRanges[kNMaxDimensions][2];   // range for CF dimensions
+  TString          fCFVarBins[kNMaxDimensions];        // bin limits for CF dimensions
+
+  TH1D *fEventStat;                  //! Histogram with event statistics
+  
+  void FillContainer(Int_t step, const Double_t* values, Int_t trackId, Int_t pdg);
+  
+  AliAnalysisTaskSingleParticle(const AliAnalysisTaskSingleParticle &c);
+  AliAnalysisTaskSingleParticle& operator= (const AliAnalysisTaskSingleParticle &c);
+  
+  ClassDef(AliAnalysisTaskSingleParticle, 2); //Analysis Task handling single particle cuts
+};
+#endif
index 0c0a746..a9daf19 100644 (file)
@@ -45,10 +45,13 @@ The names are available via the function PairClassName(Int_t i)
 #include <TString.h>
 #include <TList.h>
 #include <TMath.h>
+#include <TObject.h>
 
 #include <AliESDEvent.h>
 #include <AliESDtrack.h>
+#include <AliKFParticle.h>
 
+#include <AliEventplane.h>
 #include <AliVEvent.h>
 #include <AliVParticle.h>
 #include <AliVTrack.h>
@@ -60,6 +63,7 @@ The names are available via the function PairClassName(Int_t i)
 #include "AliDielectronTrackRotator.h"
 #include "AliDielectronDebugTree.h"
 #include "AliDielectronSignalMC.h"
+#include "AliDielectronMixingHandler.h"
 
 #include "AliDielectron.h"
 
@@ -94,19 +98,27 @@ AliDielectron::AliDielectron() :
   fPairPreFilter("PairPreFilter"),
   fPairPreFilterLegs("PairPreFilterLegs"),
   fPairFilter("PairFilter"),
+  fEventPlanePreFilter("EventPlanePreFilter"),
+  fEventPlanePOIPreFilter("EventPlanePOIPreFilter"),
   fPdgMother(443),
   fPdgLeg1(11),
   fPdgLeg2(11),
   fSignalsMC(0x0),
   fNoPairing(kFALSE),
   fHistos(0x0),
-  fPairCandidates(new TObjArray(10)),
+  fPairCandidates(new TObjArray(11)),
   fCfManagerPair(0x0),
   fTrackRotator(0x0),
   fDebugTree(0x0),
+  fMixing(0x0),
+  fPreFilterEventPlane(kFALSE),
+  fLikeSignSubEvents(kFALSE),
   fPreFilterUnlikeOnly(kFALSE),
   fPreFilterAllSigns(kFALSE),
-  fHasMC(kFALSE)
+  fHasMC(kFALSE),
+  fStoreRotatedPairs(kFALSE),
+  fEstimatorFilename(""),
+  fTRDpidCorrectionFilename("")
 {
   //
   // Default constructor
@@ -122,19 +134,27 @@ AliDielectron::AliDielectron(const char* name, const char* title) :
   fPairPreFilter("PairPreFilter"),
   fPairPreFilterLegs("PairPreFilterLegs"),
   fPairFilter("PairFilter"),
+  fEventPlanePreFilter("EventPlanePreFilter"),
+  fEventPlanePOIPreFilter("EventPlanePOIPreFilter"),
   fPdgMother(443),
   fPdgLeg1(11),
   fPdgLeg2(11),
   fSignalsMC(0x0),
   fNoPairing(kFALSE),
   fHistos(0x0),
-  fPairCandidates(new TObjArray(10)),
+  fPairCandidates(new TObjArray(11)),
   fCfManagerPair(0x0),
   fTrackRotator(0x0),
   fDebugTree(0x0),
+  fMixing(0x0),
+  fPreFilterEventPlane(kFALSE),
+  fLikeSignSubEvents(kFALSE),
   fPreFilterUnlikeOnly(kFALSE),
   fPreFilterAllSigns(kFALSE),
-  fHasMC(kFALSE)
+  fHasMC(kFALSE),
+  fStoreRotatedPairs(kFALSE),
+  fEstimatorFilename(""),
+  fTRDpidCorrectionFilename("")
 {
   //
   // Named constructor
@@ -151,7 +171,9 @@ AliDielectron::~AliDielectron()
   if (fHistos) delete fHistos;
   if (fPairCandidates) delete fPairCandidates;
   if (fDebugTree) delete fDebugTree;
+  if (fMixing) delete fMixing;
   if (fSignalsMC) delete fSignalsMC;
+  if (fCfManagerPair) delete fCfManagerPair;
 }
 
 //________________________________________________________________
@@ -162,7 +184,9 @@ void AliDielectron::Init()
   //
 
   if(GetHasMC()) AliDielectronMC::Instance()->SetHasMC(GetHasMC());
-  
+   
+  InitPairCandidateArrays();
+   
   if (fCfManagerPair) {
     fCfManagerPair->SetSignalsMC(fSignalsMC);
     fCfManagerPair->InitialiseContainer(fPairFilter);
@@ -172,6 +196,10 @@ void AliDielectron::Init()
     fTrackRotator->SetPdgLegs(fPdgLeg1,fPdgLeg2);
   }
   if (fDebugTree) fDebugTree->SetDielectron(this);
+  if(fEstimatorFilename.Contains(".root")) AliDielectronVarManager::InitEstimatorAvg(fEstimatorFilename.Data());
+  if(fTRDpidCorrectionFilename.Contains(".root")) AliDielectronVarManager::InitTRDpidEffHistograms(fTRDpidCorrectionFilename.Data());
+
+  if (fMixing) fMixing->Init(this);
 } 
 
 //________________________________________________________________
@@ -186,16 +214,15 @@ void AliDielectron::Process(AliVEvent *ev1, AliVEvent *ev2)
     AliError("At least first event must be set!");
     return;
   }
-    
   AliDielectronVarManager::SetEvent(ev1);
-   
+
   //in case we have MC load the MC event and process the MC particles
   if (AliDielectronMC::Instance()->HasMC()) {
     if (!AliDielectronMC::Instance()->ConnectMCEvent()){
       AliError("Could not properly connect the MC event, skipping this event!");
       return;
     }
-    ProcessMC();
+    ProcessMC(ev1);
   }
   
   //if candidate array doesn't exist, create it
@@ -213,15 +240,11 @@ void AliDielectron::Process(AliVEvent *ev1, AliVEvent *ev2)
         (ev2&&fEventFilter.IsSelected(ev2)!=selectedMask)) return;
   
   AliDielectronVarManager::SetEvent(ev1);
-  
+
   //fill track arrays for the first event
   if (ev1){
     FillTrackArrays(ev1);
     if (((fPreFilterAllSigns)||(fPreFilterUnlikeOnly)) && ( fPairPreFilter.GetCuts()->GetEntries()>0 )) PairPreFilter(0, 1, fTracks[0], fTracks[1]);
-    if ((fPreFilterAllSigns) && ( fPairPreFilter.GetCuts()->GetEntries()>0 )) {
-                       PairPreFilter(0, 0, fTracks[0], fTracks[0]);
-                       PairPreFilter(1, 1, fTracks[1], fTracks[1]);
-               }               
   }
 
 
@@ -229,12 +252,13 @@ void AliDielectron::Process(AliVEvent *ev1, AliVEvent *ev2)
   if (ev2) {
     FillTrackArrays(ev2,1);
     if (((fPreFilterAllSigns)||(fPreFilterUnlikeOnly)) && ( fPairPreFilter.GetCuts()->GetEntries()>0 )) PairPreFilter(2, 3, fTracks[2], fTracks[3]);
-    if ((fPreFilterAllSigns) && ( fPairPreFilter.GetCuts()->GetEntries()>0 )) {
-                       PairPreFilter(2, 2, fTracks[2], fTracks[2]);
-                       PairPreFilter(3, 3, fTracks[3], fTracks[3]);
-               }               
   }
 
+  // TPC event plane correction
+  AliEventplane *cevplane = new AliEventplane();
+  if (ev1 && fPreFilterEventPlane && ( fEventPlanePreFilter.GetCuts()->GetEntries()>0 || fEventPlanePOIPreFilter.GetCuts()->GetEntries()>0)) 
+    EventPlanePreFilter(0, 1, fTracks[0], fTracks[1], ev1, cevplane);
+  
   if (!fNoPairing){
     // create pairs and fill pair candidate arrays
     for (Int_t itrackArr1=0; itrackArr1<4; ++itrackArr1){
@@ -249,16 +273,27 @@ void AliDielectron::Process(AliVEvent *ev1, AliVEvent *ev2)
       FillPairArrayTR();
     }
   }
-  
-  //in case there is a histogram manager, fill the QA histograms
-  if (fHistos) FillHistograms(ev1);
 
   //fill debug tree if a manager is attached
   if (fDebugTree) FillDebugTree();
+
+  //process event mixing
+  if (fMixing) {
+    fMixing->Fill(ev1,this);
+//     FillHistograms(0x0,kTRUE);
+  }
+
+  //in case there is a histogram manager, fill the QA histograms
+  if (fHistos) FillHistograms(ev1);
+
+  // clear arrays
+//   ClearArrays();
+  AliDielectronVarManager::SetTPCEventPlane(0x0);
+  delete cevplane;
 }
 
 //________________________________________________________________
-void AliDielectron::ProcessMC()
+void AliDielectron::ProcessMC(AliVEvent *ev1)
 {
   //
   // Process the MC data
@@ -266,7 +301,7 @@ void AliDielectron::ProcessMC()
 
   AliDielectronMC *dieMC=AliDielectronMC::Instance();
 
-  if (fHistos) FillHistogramsMC(dieMC->GetMCEvent());
+  if (fHistos) FillHistogramsMC(dieMC->GetMCEvent(), ev1);
 
   if(!fSignalsMC) return;
   //loop over all MC data and Fill the CF container if it exist
@@ -387,42 +422,47 @@ void AliDielectron::FillHistogramsTracks(TObjArray **tracks)
 
 
 //________________________________________________________________
-void AliDielectron::FillHistogramsMC(const AliMCEvent *ev)
+void AliDielectron::FillHistogramsMC(const AliMCEvent *ev, AliVEvent *ev1)
 {
   //
   // Fill Histogram information for MCEvents
   //
 
-  Double_t values[AliDielectronVarManager::kNMaxValues];
+  Double_t values[AliDielectronVarManager::kNMaxValues]={0.};
   // Fill event information
-  AliDielectronVarManager::Fill(ev, values);
+  AliDielectronVarManager::Fill(ev1, values);    // ESD/AOD information
+  AliDielectronVarManager::Fill(ev, values);     // MC truth info
   if (fHistos->GetHistogramList()->FindObject("MCEvent"))
     fHistos->FillClass("MCEvent", AliDielectronVarManager::kNMaxValues, values);
 }
 
 
 //________________________________________________________________
-void AliDielectron::FillHistograms(const AliVEvent *ev)
+void AliDielectron::FillHistograms(const AliVEvent *ev, Bool_t pairInfoOnly)
 {
   //
   // Fill Histogram information for tracks and pairs
   //
   
   TString  className,className2;
-  Double_t values[AliDielectronVarManager::kNMaxValues];
+  Double_t values[AliDielectronVarManager::kNMaxValues]={0.};
   //Fill event information
-  AliDielectronVarManager::Fill(ev, values);
-  if (fHistos->GetHistogramList()->FindObject("Event"))
-    fHistos->FillClass("Event", AliDielectronVarManager::kNMaxValues, values);
+  if (ev){
+    AliDielectronVarManager::Fill(ev, values);
+    if (fHistos->GetHistogramList()->FindObject("Event"))
+      fHistos->FillClass("Event", AliDielectronVarManager::kNMaxValues, values);
+  }
   
   //Fill track information, separately for the track array candidates
-  for (Int_t i=0; i<4; ++i){
-    className.Form("Track_%s",fgkTrackClassNames[i]);
-    if (!fHistos->GetHistogramList()->FindObject(className.Data())) continue;
-    Int_t ntracks=fTracks[i].GetEntriesFast();
-    for (Int_t itrack=0; itrack<ntracks; ++itrack){
-      AliDielectronVarManager::Fill(fTracks[i].UncheckedAt(itrack), values);
-      fHistos->FillClass(className, AliDielectronVarManager::kNMaxValues, values);
+  if (!pairInfoOnly){
+    for (Int_t i=0; i<4; ++i){
+      className.Form("Track_%s",fgkTrackClassNames[i]);
+      if (!fHistos->GetHistogramList()->FindObject(className.Data())) continue;
+      Int_t ntracks=fTracks[i].GetEntriesFast();
+      for (Int_t itrack=0; itrack<ntracks; ++itrack){
+        AliDielectronVarManager::Fill(fTracks[i].UncheckedAt(itrack), values);
+        fHistos->FillClass(className, AliDielectronVarManager::kNMaxValues, values);
+      }
     }
   }
 
@@ -531,7 +571,7 @@ void AliDielectron::FillTrackArrays(AliVEvent * const ev, Int_t eventNr)
     
     //apply track cuts
     if (fTrackFilter.IsSelected(particle)!=selectedMask) continue;
-    
+
     //fill selected particle into the corresponding track arrays
     Short_t charge=particle->Charge();
     if (charge>0)      fTracks[eventNr*2].Add(particle);
@@ -540,58 +580,295 @@ void AliDielectron::FillTrackArrays(AliVEvent * const ev, Int_t eventNr)
 }
 
 //________________________________________________________________
-void AliDielectron::PairPreFilter(Int_t arr1, Int_t arr2, TObjArray &arrTracks1, TObjArray &arrTracks2)
+void AliDielectron::EventPlanePreFilter(Int_t arr1, Int_t arr2, TObjArray arrTracks1, TObjArray arrTracks2, const AliVEvent *ev, AliEventplane *cevplane)
 {
   //
-  // Prefilter tracks from pairs
-  // Needed for datlitz rejections
-  // remove all tracks from the Single track arrays that pass the cuts in this filter
+  // Prefilter tracks and tracks from pairs
+  // Needed for rejection in the Q-Vector of the event plane
+  // remove contribution of all tracks to the Q-vector that are in invariant mass window 
   //
+  AliEventplane *evplane = const_cast<AliVEvent *>(ev)->GetEventplane();
+  if(!evplane) return;
+  
+  // do not change these vectors qref
+  TVector2 *qref  = evplane->GetQVector();
+  if(!qref) return;
+  // random subevents
+  TVector2 *qrsub1 = evplane->GetQsub1();
+  TVector2 *qrsub2 = evplane->GetQsub2();
+
+  // copy references
+  TVector2 *qstd   = dynamic_cast<TVector2 *>(qref->Clone());
+  TVector2 *qssub1 = dynamic_cast<TVector2 *>(qrsub1->Clone());
+  TVector2 *qssub2 = dynamic_cast<TVector2 *>(qrsub2->Clone());
+
+  // subevents by charge separation sub1+ sub2-
+  if(fLikeSignSubEvents) {
+    qssub1 = dynamic_cast<TVector2 *>(qstd->Clone());
+    qssub2 = dynamic_cast<TVector2 *>(qstd->Clone());
+
+    Int_t ntracks=ev->GetNumberOfTracks();
+    
+    // track removals
+    for (Int_t itrack=0; itrack<ntracks; ++itrack){
+      AliVParticle *particle=ev->GetTrack(itrack);
+      AliVTrack *track= static_cast<AliVTrack*>(particle);
+      if (!track) continue;
+
+      Double_t cQX     = evplane->GetQContributionX(track);
+      Double_t cQY     = evplane->GetQContributionY(track);
+      
+      Short_t charge=track->Charge();
+      if (charge<0) qssub1->Set(qssub1->X()-cQX, qssub1->Y()-cQY);
+      if (charge>0) qssub2->Set(qssub2->X()-cQX, qssub2->Y()-cQY);
+    }
+  }
+
+  // subevents eta division sub1+ sub2-
+  Bool_t etagap = kFALSE;
+  for (Int_t iCut=0; iCut<fEventPlanePreFilter.GetCuts()->GetEntries();++iCut) {
+    TString cutName=fEventPlanePreFilter.GetCuts()->At(iCut)->GetName();
+    if(cutName.Contains("eta") || cutName.Contains("Eta")) {
+      etagap=kTRUE;
+
+      qssub1 = dynamic_cast<TVector2 *>(qstd->Clone());
+      qssub2 = dynamic_cast<TVector2 *>(qstd->Clone());
+      
+      Int_t ntracks=ev->GetNumberOfTracks();
+      
+      // track removals
+      for (Int_t itrack=0; itrack<ntracks; ++itrack){
+       AliVParticle *particle=ev->GetTrack(itrack);
+       AliVTrack *track= static_cast<AliVTrack*>(particle);
+       if (!track) continue;
+       
+       Double_t cQX     = evplane->GetQContributionX(track);
+       Double_t cQY     = evplane->GetQContributionY(track);
+      
+       Double_t eta=track->Eta();
+       if (eta<0.0) qssub1->Set(qssub1->X()-cQX, qssub1->Y()-cQY);
+       if (eta>0.0) qssub2->Set(qssub2->X()-cQX, qssub2->Y()-cQY);
+      }
+    }
+  }
+  
+  // apply cuts, e.g. etagap 
+  if(fEventPlanePreFilter.GetCuts()->GetEntries()) {
+    UInt_t selectedMask=(1<<fEventPlanePreFilter.GetCuts()->GetEntries())-1;
+    Int_t ntracks=ev->GetNumberOfTracks();
+    for (Int_t itrack=0; itrack<ntracks; ++itrack){
+      AliVParticle *particle=ev->GetTrack(itrack);
+      AliVTrack *track= static_cast<AliVTrack*>(particle);
+      if (!track) continue;
+      
+      //event plane cuts
+      UInt_t cutMask=fEventPlanePreFilter.IsSelected(track);
+      //apply cut
+      if (cutMask==selectedMask) continue;
+
+      Double_t cQX     = 0.0;
+      Double_t cQY     = 0.0;
+      if(!etagap) {
+       cQX = evplane->GetQContributionX(track);
+       cQY = evplane->GetQContributionY(track);
+      }
+      Double_t cQXsub1 = evplane->GetQContributionXsub1(track);
+      Double_t cQYsub1 = evplane->GetQContributionYsub1(track);
+      Double_t cQXsub2 = evplane->GetQContributionXsub2(track);
+      Double_t cQYsub2 = evplane->GetQContributionYsub2(track);      
+
+      // update Q vectors
+      qstd->Set(qstd->X()-cQX, qstd->Y()-cQY);
+      qssub1->Set(qssub1->X()-cQXsub1, qssub1->Y()-cQYsub1);
+      qssub2->Set(qssub2->X()-cQXsub2, qssub2->Y()-cQYsub2);
+    }
+  }
+
+  if(!qstd || !qssub1 || !qssub2) return;
+
+  TVector2 *qcorr  = dynamic_cast<TVector2 *>(qstd->Clone());
+  TVector2 *qcsub1 = dynamic_cast<TVector2 *>(qssub1->Clone());
+  TVector2 *qcsub2 = dynamic_cast<TVector2 *>(qssub2->Clone());
+
+
+  // POI (particle of interest) rejection
   Int_t pairIndex=GetPairIndex(arr1,arr2);
   
   Int_t ntrack1=arrTracks1.GetEntriesFast();
   Int_t ntrack2=arrTracks2.GetEntriesFast();
-  
   AliDielectronPair candidate;
   
-  UInt_t selectedMask=(1<<fPairPreFilter.GetCuts()->GetEntries())-1;
-  UInt_t selectedMaskPair=(1<<fPairFilter.GetCuts()->GetEntries())-1;
-  
+  UInt_t selectedMask=(1<<fEventPlanePOIPreFilter.GetCuts()->GetEntries())-1;
   for (Int_t itrack1=0; itrack1<ntrack1; ++itrack1){
     Int_t end=ntrack2;
     if (arr1==arr2) end=itrack1;
     Bool_t accepted=kFALSE;
     for (Int_t itrack2=0; itrack2<end; ++itrack2){
-      AliVTrack *track1=static_cast<AliVTrack*>(arrTracks1.UncheckedAt(itrack1));
-      AliVTrack *track2=static_cast<AliVTrack*>(arrTracks2.UncheckedAt(itrack2));
+      TObject *track1=arrTracks1.UncheckedAt(itrack1);
+      TObject *track2=arrTracks2.UncheckedAt(itrack2);
       if (!track1 || !track2) continue;
       //create the pair
-      candidate.SetTracks(track1, fPdgLeg1,
-                          track2, fPdgLeg2);
+      candidate.SetTracks(static_cast<AliVTrack*>(track1), fPdgLeg1,
+                          static_cast<AliVTrack*>(track2), fPdgLeg2);
+      
       candidate.SetType(pairIndex);
       candidate.SetLabel(AliDielectronMC::Instance()->GetLabelMotherWithPdg(&candidate,fPdgMother));
-      //relate to the production vertex
-//       if (AliDielectronVarManager::GetKFVertex()) candidate.SetProductionVertex(*AliDielectronVarManager::GetKFVertex());
-      
-      //pair cuts
-      UInt_t cutMask=fPairPreFilter.IsSelected(&candidate);
       
+      //event plane cuts
+      UInt_t cutMask=fEventPlanePOIPreFilter.IsSelected(&candidate);
       //apply cut
-      if (cutMask!=selectedMask) continue;
-      if (fCfManagerPair) fCfManagerPair->Fill(selectedMaskPair+1 ,&candidate);
+      if (cutMask==selectedMask) continue;
+
       accepted=kTRUE;
-      if (fHistos) FillHistogramsPair(&candidate,kTRUE);
       //remove the tracks from the Track arrays
       arrTracks2.AddAt(0x0,itrack2);
-      //in case of like sign remove the track from both arrays!
-      if (arr1==arr2) arrTracks1.AddAt(0x0, itrack2);
     }
-    if ( accepted ) arrTracks1.AddAt(0x0,itrack1);
+      if ( accepted ) arrTracks1.AddAt(0x0,itrack1);
   }
   //compress the track arrays
+  arrTracks1.Compress();
+  arrTracks2.Compress();
+  
   
+  //Modify the components: subtract the tracks
+  ntrack1=arrTracks1.GetEntriesFast();
+  ntrack2=arrTracks2.GetEntriesFast();
+  
+  // remove leg1 contribution
+  for (Int_t itrack=0; itrack<ntrack1; ++itrack){
+    AliVTrack *track= static_cast<AliVTrack*>(arrTracks1.UncheckedAt(itrack));
+    if (!track) continue;
+    
+    Double_t cQX     = evplane->GetQContributionX(track);
+    Double_t cQY     = evplane->GetQContributionY(track);
+    Double_t cQXsub1 = evplane->GetQContributionXsub1(track);
+    Double_t cQYsub1 = evplane->GetQContributionYsub1(track);
+    Double_t cQXsub2 = evplane->GetQContributionXsub2(track);
+    Double_t cQYsub2 = evplane->GetQContributionYsub2(track);
+    
+    // update Q vectors
+    qcorr->Set(qcorr->X()-cQX, qcorr->Y()-cQY);
+    qcsub1->Set(qcsub1->X()-cQXsub1, qcsub1->Y()-cQYsub1);
+    qcsub2->Set(qcsub2->X()-cQXsub2, qcsub2->Y()-cQYsub2);
+  }
+  // remove leg2 contribution
+  for (Int_t itrack=0; itrack<ntrack2; ++itrack){
+    AliVTrack *track= static_cast<AliVTrack*>(arrTracks2.UncheckedAt(itrack));
+    if (!track) continue;
+    
+    Double_t cQX     = evplane->GetQContributionX(track);
+    Double_t cQY     = evplane->GetQContributionY(track);
+    Double_t cQXsub1 = evplane->GetQContributionXsub1(track);
+    Double_t cQYsub1 = evplane->GetQContributionYsub1(track);
+    Double_t cQXsub2 = evplane->GetQContributionXsub2(track);
+    Double_t cQYsub2 = evplane->GetQContributionYsub2(track);
+    
+    // update Q vectors
+    qcorr->Set(qcorr->X()-cQX, qcorr->Y()-cQY);
+    qcsub1->Set(qcsub1->X()-cQXsub1, qcsub1->Y()-cQYsub1);
+    qcsub2->Set(qcsub2->X()-cQXsub2, qcsub2->Y()-cQYsub2);
+  }
 
+  // set AliEventplane with corrected values
+  cevplane->SetQVector(qcorr);
+  cevplane->SetQsub(qcsub1, qcsub2);
+  AliDielectronVarManager::SetTPCEventPlane(cevplane);
+}
 
+//________________________________________________________________
+void AliDielectron::PairPreFilter(Int_t arr1, Int_t arr2, TObjArray &arrTracks1, TObjArray &arrTracks2)
+{
+  //
+  // Prefilter tracks from pairs
+  // Needed for datlitz rejections
+  // remove all tracks from the Single track arrays that pass the cuts in this filter
+  //
+
+  Int_t ntrack1=arrTracks1.GetEntriesFast();
+  Int_t ntrack2=arrTracks2.GetEntriesFast();
+  AliDielectronPair candidate;
+
+  // flag arrays for track removal
+  Bool_t *bTracks1 = new Bool_t[ntrack1];
+  for (Int_t itrack1=0; itrack1<ntrack1; ++itrack1) bTracks1[itrack1]=kFALSE;
+  Bool_t *bTracks2 = new Bool_t[ntrack2];
+  for (Int_t itrack2=0; itrack2<ntrack2; ++itrack2) bTracks2[itrack2]=kFALSE;
+
+  UInt_t selectedMask=(1<<fPairPreFilter.GetCuts()->GetEntries())-1;
+  UInt_t selectedMaskPair=(1<<fPairFilter.GetCuts()->GetEntries())-1;
+
+  Int_t nRejPasses = 1; //for fPreFilterUnlikeOnly and no set flag 
+  if (fPreFilterAllSigns) nRejPasses = 3;
+
+  for (Int_t iRP=0; iRP < nRejPasses; ++iRP) {
+       Int_t arr1RP=arr1, arr2RP=arr2;
+       TObjArray *arrTracks1RP=&arrTracks1;
+       TObjArray *arrTracks2RP=&arrTracks2;
+       Bool_t *bTracks1RP = bTracks1;
+       Bool_t *bTracks2RP = bTracks2;
+       switch (iRP) {
+               case 1: arr1RP=arr1;arr2RP=arr1;
+                               arrTracks1RP=&arrTracks1;
+                               arrTracks2RP=&arrTracks1;
+                               bTracks1RP = bTracks1;
+                               bTracks2RP = bTracks1;
+                               break;
+               case 2: arr1RP=arr2;arr2RP=arr2;
+                               arrTracks1RP=&arrTracks2;
+                               arrTracks2RP=&arrTracks2;
+                               bTracks1RP = bTracks2;
+                               bTracks2RP = bTracks2;
+                               break;
+               default: ;//nothing to do
+       }
+       Int_t ntrack1RP=(*arrTracks1RP).GetEntriesFast();
+       Int_t ntrack2RP=(*arrTracks2RP).GetEntriesFast();
+
+       Int_t pairIndex=GetPairIndex(arr1RP,arr2RP);
+
+       for (Int_t itrack1=0; itrack1<ntrack1RP; ++itrack1){
+         Int_t end=ntrack2RP;
+         if (arr1RP==arr2RP) end=itrack1;
+         for (Int_t itrack2=0; itrack2<end; ++itrack2){
+               TObject *track1=(*arrTracks1RP).UncheckedAt(itrack1);
+               TObject *track2=(*arrTracks2RP).UncheckedAt(itrack2);
+               if (!track1 || !track2) continue;
+               //create the pair
+               candidate.SetTracks(static_cast<AliVTrack*>(track1), fPdgLeg1,
+                       static_cast<AliVTrack*>(track2), fPdgLeg2);
+
+               candidate.SetType(pairIndex);
+               candidate.SetLabel(AliDielectronMC::Instance()->GetLabelMotherWithPdg(&candidate,fPdgMother));
+               //relate to the production vertex
+               //       if (AliDielectronVarManager::GetKFVertex()) candidate.SetProductionVertex(*AliDielectronVarManager::GetKFVertex());
+
+               //pair cuts
+               UInt_t cutMask=fPairPreFilter.IsSelected(&candidate);
+
+               //apply cut
+               if (cutMask!=selectedMask) continue;
+               if (fCfManagerPair) fCfManagerPair->Fill(selectedMaskPair+1 ,&candidate);
+               if (fHistos) FillHistogramsPair(&candidate,kTRUE);
+               //set flags for track removal
+               bTracks1RP[itrack1]=kTRUE;
+               bTracks2RP[itrack2]=kTRUE;
+         }
+       }
+  }
+
+  //remove the tracks from the Track arrays
+  for (Int_t itrack1=0; itrack1<ntrack1; ++itrack1){
+    if(bTracks1[itrack1]) arrTracks1.AddAt(0x0, itrack1);
+  }
+  for (Int_t itrack2=0; itrack2<ntrack2; ++itrack2){
+    if(bTracks2[itrack2]) arrTracks2.AddAt(0x0, itrack2);
+  }
+
+  // clean up
+  delete [] bTracks1;
+  delete [] bTracks2;
+
+  //compress the track arrays
   arrTracks1.Compress();
   arrTracks2.Compress();
   
@@ -659,7 +936,7 @@ void AliDielectron::FillPairArrays(Int_t arr1, Int_t arr2)
     for (Int_t itrack2=0; itrack2<end; ++itrack2){
       //create the pair
       candidate->SetTracks(static_cast<AliVTrack*>(arrTracks1.UncheckedAt(itrack1)), fPdgLeg1,
-                           static_cast<AliVTrack*>(arrTracks2.UncheckedAt(itrack2)), fPdgLeg2);
+                             static_cast<AliVTrack*>(arrTracks2.UncheckedAt(itrack2)), fPdgLeg2);
       candidate->SetType(pairIndex);
       candidate->SetLabel(AliDielectronMC::Instance()->GetLabelMotherWithPdg(candidate,fPdgMother));
 
@@ -703,7 +980,10 @@ void AliDielectron::FillPairArrayTR()
     if (fCfManagerPair) fCfManagerPair->Fill(cutMask,&candidate);
     
     //apply cut
-    if (cutMask==selectedMask&&fHistos) FillHistogramsPair(&candidate);
+    if (cutMask==selectedMask) {
+     if(fHistos) FillHistogramsPair(&candidate);
+     if(fStoreRotatedPairs) PairArray(10)->Add(new AliDielectronPair(candidate));  
+    } 
   }
 }
 
index 90351ee..b1443a5 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "AliDielectronHistos.h"
 
+class AliEventplane;
 class AliVEvent;
 class AliMCEvent;
 class THashList;
@@ -32,10 +33,13 @@ class AliDielectronDebugTree;
 class AliDielectronTrackRotator;
 class AliDielectronPair;
 class AliDielectronSignalMC;
+class AliDielectronMixingHandler;
 
 //________________________________________________________________
 class AliDielectron : public TNamed {
-  
+
+  friend class AliDielectronMixingHandler; //mixing as friend class
+
 public:
   enum EPairType { kEv1PP=0, kEv1PM, kEv1MM,
       kEv1PEv2P, kEv1MEv2P, kEv2PP,
@@ -60,7 +64,9 @@ public:
   AliAnalysisFilter& GetPairFilter()        { return fPairFilter;        }
   AliAnalysisFilter& GetPairPreFilter()     { return fPairPreFilter;     }
   AliAnalysisFilter& GetPairPreFilterLegs() { return fPairPreFilterLegs; }
-  
+  AliAnalysisFilter& GetEventPlanePreFilter(){ return fEventPlanePreFilter; }
+  AliAnalysisFilter& GetEventPlanePOIPreFilter(){ return fEventPlanePOIPreFilter; }
+
   void  SetMotherPdg( Int_t pdgMother ) { fPdgMother=pdgMother; }
   void  SetLegPdg(Int_t pdgLeg1, Int_t pdgLeg2) { fPdgLeg1=pdgLeg1; fPdgLeg2=pdgLeg2; }
   Int_t GetMotherPdg() const { return fPdgMother; }
@@ -69,7 +75,7 @@ public:
 
   void SetNoPairing(Bool_t noPairing=kTRUE) { fNoPairing=noPairing; }
   const TObjArray* GetTrackArray(Int_t i) const {return (i>=0&&i<4)?&fTracks[i]:0;}
-  const TObjArray* GetPairArray(Int_t i)  const {return (i>=0&&i<10)?
+  const TObjArray* GetPairArray(Int_t i)  const {return (i>=0&&i<11)?
       static_cast<TObjArray*>(fPairCandidates->UncheckedAt(i)):0;}
 
   TObjArray** GetPairArraysPointer() { return &fPairCandidates; }
@@ -83,18 +89,26 @@ public:
     return (GetPairArray(0)&&GetPairArray(2)) ? (GetPairArray(0)->GetEntriesFast()>0 || GetPairArray(2)->GetEntriesFast()>0) : 0;
   }
   
+  Bool_t HasCandidatesTR() const {return GetPairArray(10)?GetPairArray(10)->GetEntriesFast()>0:0;} 
   void SetCFManagerPair(AliDielectronCF * const cf) { fCfManagerPair=cf; }
   AliDielectronCF* GetCFManagerPair() const { return fCfManagerPair; }
 
+  void SetPreFilterEventPlane(Bool_t setValue=kTRUE){fPreFilterEventPlane=setValue;};
+  void SetLikeSignSubEvents(Bool_t setValue=kTRUE){fLikeSignSubEvents=setValue;};
   void SetPreFilterUnlikeOnly(Bool_t setValue=kTRUE){fPreFilterUnlikeOnly=setValue;};
   void SetPreFilterAllSigns(Bool_t setValue=kTRUE){fPreFilterAllSigns=setValue;};
 
   void SetTrackRotator(AliDielectronTrackRotator * const rot) { fTrackRotator=rot; }
   AliDielectronTrackRotator* GetTrackRotator() const { return fTrackRotator; }
 
+  void SetMixingHandler(AliDielectronMixingHandler *mix) { fMixing=mix; }
+  AliDielectronMixingHandler* GetMixingHandler() const { return fMixing; }
+
   void SetHasMC(Bool_t hasMC) { fHasMC = hasMC; }
   Bool_t GetHasMC() const     { return fHasMC;  }
 
+  void SetStoreRotatedPairs(Bool_t storeTR) {fStoreRotatedPairs = storeTR;}
+
   void AddSignalMC(AliDielectronSignalMC* signal);  
 
   void SetDebugTree(AliDielectronDebugTree * const tree) { fDebugTree=tree; }
@@ -103,17 +117,22 @@ public:
   static const char* TrackClassName(Int_t i) { return (i>=0&&i<4)?fgkTrackClassNames[i]:""; }
   static const char* PairClassName(Int_t i)  { return (i>=0&&i<11)?fgkPairClassNames[i]:""; }
 
+  void SetEstimatorFilename(const Char_t* filename) {fEstimatorFilename = filename;}
+  void SetTRDcorrectionFilename(const Char_t* filename) {fTRDpidCorrectionFilename = filename;}
+
+
   void SaveDebugTree();
-  
-private:
 
+private:
   
   AliAnalysisFilter fEventFilter;    // Event cuts
   AliAnalysisFilter fTrackFilter;    // leg cuts
   AliAnalysisFilter fPairPreFilter;  // pair prefilter cuts
   AliAnalysisFilter fPairPreFilterLegs; // Leg filter after the pair prefilter cuts
   AliAnalysisFilter fPairFilter;     // pair cuts
-  
+  AliAnalysisFilter fEventPlanePreFilter;  // event plane prefilter cuts  
+  AliAnalysisFilter fEventPlanePOIPreFilter;  // PoI cuts in the event plane prefilter  
+
   Int_t fPdgMother;     // pdg code of mother tracks
   Int_t fPdgLeg1;       // pdg code leg1
   Int_t fPdgLeg2;       // pdg code leg2
@@ -138,12 +157,17 @@ private:
   AliDielectronCF *fCfManagerPair;//Correction Framework Manager for the Pair
   AliDielectronTrackRotator *fTrackRotator; //Track rotator
   AliDielectronDebugTree *fDebugTree;  // Debug tree output
+  AliDielectronMixingHandler *fMixing; // handler for event mixing
 
+  Bool_t fPreFilterEventPlane;  //Filter for the Eventplane determination in TPC
+  Bool_t fLikeSignSubEvents;    //Option for dividing into subevents, sub1 ++ sub2 --
   Bool_t fPreFilterUnlikeOnly;  //Apply PreFilter either in +- or to ++/--/+- individually
-  Bool_t fPreFilterAllSigns;  //Apply PreFilter find in  ++/--/+- and remove from all
+  Bool_t fPreFilterAllSigns;    //Apply PreFilter find in  ++/--/+- and remove from all
   Bool_t fHasMC;                //If we run with MC, at the moment only needed in AOD
-  
+  Bool_t fStoreRotatedPairs;    //It the rotated pairs should be stored in the pair array 
   void FillTrackArrays(AliVEvent * const ev, Int_t eventNr=0);
+  void EventPlanePreFilter(Int_t arr1, Int_t arr2, TObjArray arrTracks1, TObjArray arrTracks2, const AliVEvent *ev, AliEventplane *cevplane);
   void PairPreFilter(Int_t arr1, Int_t arr2, TObjArray &arrTracks1, TObjArray &arrTracks2);
   void FillPairArrays(Int_t arr1, Int_t arr2);
   void FillPairArrayTR();
@@ -158,15 +182,18 @@ private:
   static const char* fgkTrackClassNames[4];   //Names for track arrays
   static const char* fgkPairClassNames[11];   //Names for pair arrays
 
-  void ProcessMC();
+  TString fEstimatorFilename;                // name for the pp multiplicity estimators filename
+  TString fTRDpidCorrectionFilename;         // name for the file containing the single particle TRD pid corrections
+
+  void ProcessMC(AliVEvent *ev1);
   
-  void  FillHistograms(const AliVEvent *ev);
-  void  FillHistogramsMC(const AliMCEvent *ev);
+  void  FillHistograms(const AliVEvent *ev, Bool_t pairInfoOnly=kFALSE);
+  void  FillHistogramsMC(const AliMCEvent *ev,  AliVEvent *ev1);
   void  FillHistogramsPair(AliDielectronPair *pair,Bool_t fromPreFilter=kFALSE);
   void  FillHistogramsTracks(TObjArray **tracks);
 
   void  FillDebugTree();
-  
+
   AliDielectron(const AliDielectron &c);
   AliDielectron &operator=(const AliDielectron &c);
   
@@ -179,7 +206,7 @@ inline void AliDielectron::InitPairCandidateArrays()
   // initialise all pair candidate arrays
   //
   fPairCandidates->SetOwner();
-  for (Int_t i=0;i<10;++i){
+  for (Int_t i=0;i<11;++i){
     TObjArray *arr=new TObjArray;
     fPairCandidates->AddAt(arr,i);
     arr->SetOwner();
@@ -202,8 +229,8 @@ inline void AliDielectron::ClearArrays()
   for (Int_t i=0;i<4;++i){
     fTracks[i].Clear();
   }
-  for (Int_t i=0;i<10;++i){
-    PairArray(i)->Delete();
+  for (Int_t i=0;i<11;++i){
+    if (PairArray(i)) PairArray(i)->Delete();
   }
 }
 
index be4446c..8550237 100644 (file)
@@ -23,7 +23,8 @@ ClassImp(AliDielectronBtoJPSItoEle)
 AliDielectronBtoJPSItoEle::AliDielectronBtoJPSItoEle() :
 fFCNfunction(0),
 fPtBin(0),
-fMCtemplate(0)
+fMCtemplate(0),
+fResType("FF")
 {
   //
   // default constructor
@@ -34,7 +35,8 @@ AliDielectronBtoJPSItoEle::AliDielectronBtoJPSItoEle(const AliDielectronBtoJPSIt
 TNamed(source),
 fFCNfunction(source.fFCNfunction),
 fPtBin(source.fPtBin),
-fMCtemplate(source.fMCtemplate)
+fMCtemplate(source.fMCtemplate),
+fResType(source.fResType)
 {
   //
   // copy constructor
@@ -64,36 +66,44 @@ AliDielectronBtoJPSItoEle::~AliDielectronBtoJPSItoEle()
   delete fMCtemplate;
 }
 //_________________________________________________________________________________________________
-Int_t AliDielectronBtoJPSItoEle::DoMinimization()
+Int_t AliDielectronBtoJPSItoEle::DoMinimization(Int_t step)
 {
   //
   // performs the minimization
   //
-  Int_t iret=fFCNfunction->DoMinimization();
+  Int_t iret=fFCNfunction->DoMinimization(step);
 
   return iret;
 }
 //_________________________________________________________________________________________________
-void AliDielectronBtoJPSItoEle::ReadCandidates(TNtuple* nt, Double_t* &pseudoproper,Double_t* &invmass, Int_t& ncand)
+void AliDielectronBtoJPSItoEle::ReadCandidates(TNtuple* nt, Double_t* &pseudoproper, Double_t* &invmass, Int_t * &typeCand, Int_t& ncand)
 {
   //
   // Read N-tuple with X and M values
   //
-  Float_t mJPSI = 0; Float_t x = 0;
+  Float_t mJPSI = 0; Float_t x = 0; Float_t type = 0;
   Int_t nentries = 0;
   ncand=0;
+  TString arrType[] = {"SS","FS","FF"};
   nt->SetBranchAddress("Mass",&mJPSI);
   nt->SetBranchAddress("Xdecaytime",&x);
+  //
+  if(!nt->GetListOfBranches()->At(2)) {AliInfo("ERROR: branch with candidate type doesn't exist! \n"); return;}
+  nt->SetBranchAddress("Type",&type);
+  //
   nentries = (Int_t)nt->GetEntries();
   pseudoproper = new Double_t[nentries];
   invmass      = new Double_t[nentries];
+  typeCand     = new Int_t[nentries];
+
   for(Int_t i = 0; i < nentries; i++) {
       nt->GetEntry(i);
+      if(!fResType.Contains(arrType[(Int_t)type])) continue;
+      pseudoproper[ncand]=(Double_t)x;
+      invmass[ncand]=(Double_t)mJPSI;
+      typeCand[ncand] = (Int_t)type;
       ncand++;
-      pseudoproper[i]=(Double_t)(10000*x);
-      invmass[i]=(Double_t)mJPSI;
-    }
-
+      }
  return; 
 }
 //_________________________________________________________________________________________________
@@ -107,13 +117,13 @@ void AliDielectronBtoJPSItoEle::SetCsiMC()
   return;
 }
 //_________________________________________________________________________________________________
-void AliDielectronBtoJPSItoEle::SetFitHandler(Double_t* x /*pseudoproper*/, Double_t* m /*inv mass*/, Int_t ncand /*candidates*/) 
+void AliDielectronBtoJPSItoEle::SetFitHandler(Double_t* x /*pseudoproper*/, Double_t* m /*inv mass*/, Int_t* type /*type*/, Int_t ncand /*candidates*/) 
 {
   //
   // Create the fit handler object to play with different params of the fitting function
   //
 
-  fFCNfunction = new AliDielectronBtoJPSItoEleCDFfitHandler(x,m,ncand);
+  fFCNfunction = new AliDielectronBtoJPSItoEleCDFfitHandler(x,m,type,ncand);
   if(!fFCNfunction) {
 
      AliInfo("fFCNfunction not istanziated  ---> nothing done");
index cdd0fed..e2ef570 100644 (file)
@@ -25,14 +25,15 @@ class AliDielectronBtoJPSItoEle : public TNamed {
                AliDielectronBtoJPSItoEle& operator=(const AliDielectronBtoJPSItoEle& source);\r
                virtual ~AliDielectronBtoJPSItoEle();\r
 \r
-               Int_t DoMinimization();\r
-               void ReadCandidates(TNtuple* nt, Double_t* &x, Double_t* &m, Int_t& n); // primary JPSI + secondary JPSI + bkg couples\r
+               Int_t DoMinimization(Int_t step = 0);\r
+               void ReadCandidates(TNtuple* nt, Double_t* &x, Double_t* &m, Int_t * &typeCand, Int_t& n); // primary JPSI + secondary JPSI + bkg couples\r
 \r
                void SetPtBin(Int_t BinNum) { fPtBin = BinNum ; }\r
                void SetCsiMC();\r
-               void SetFitHandler(Double_t* x /*pseudoproper*/, Double_t* m /*inv mass*/, Int_t ncand /*candidates*/); \r
+               void SetFitHandler(Double_t* x /*pseudoproper*/, Double_t* m /*inv mass*/, Int_t *type /*type*/, Int_t ncand /*candidates*/); \r
                void CloneMCtemplate(const TH1F* MCtemplate) {fMCtemplate = (TH1F*)MCtemplate->Clone("fMCtemplate");}\r
-               Double_t* GetResolutionConstants(Double_t* resolutionConst);\r
+               void SetResTypeAnalysis(TString resType){fResType = resType;}\r
+                Double_t* GetResolutionConstants(Double_t* resolutionConst);\r
                AliDielectronBtoJPSItoEleCDFfitHandler* GetCDFFitHandler() const { return fFCNfunction ; }\r
                Int_t GetPtBin() const { return fPtBin ; }\r
 \r
@@ -40,7 +41,8 @@ class AliDielectronBtoJPSItoEle : public TNamed {
                //\r
                AliDielectronBtoJPSItoEleCDFfitHandler* fFCNfunction; //! pointer to the interface class\r
                Int_t fPtBin;                               // number of pt bin in which the analysis is performes\r
-               TH1F* fMCtemplate;                            //! template of the MC distribution for the x distribution of the secondary J/psi\r
+               TH1F* fMCtemplate;                          //! template of the MC distribution for the x distribution of the secondary J/psi\r
+                TString fResType;                           // string with candidate's types considered\r
 \r
                ClassDef(AliDielectronBtoJPSItoEle,1); // AliDielectronBtoJPSItoEle class\r
 };\r
index 380099b..b10bde5 100644 (file)
  * about the suitability of this software for any purpose. It is          *
  * provided "as is" without express or implied warranty.                  *
  **************************************************************************/
-#include <TFormula.h>
-#include <TF1.h>
-#include <TCanvas.h>
-#include <TMath.h>
-
-#include <AliLog.h>
-
+#include "AliLog.h"
 #include "AliDielectronBtoJPSItoEleCDFfitFCN.h"
+#include "TFormula.h"
+#include "TF1.h"
+#include "TCanvas.h"
+#include "TMath.h"
 
 //_________________________________________________________________________
 //                        Class AliDielectronBtoJPSItoEleCDFfitFCN
@@ -51,9 +49,9 @@ ClassImp(AliDielectronBtoJPSItoEleCDFfitFCN)
        SetCrystalBallFunction(kFALSE);
        SetMassWndHigh(0.2);
        SetMassWndLow(0.5);
-       for(Int_t iPar = 0; iPar < 20; iPar++) fParameters[iPar] = 0.;
-       fParameters[9] = 1.;fParameters[11] = 1.;fParameters[12] = 1.;
-       for(Int_t index=0; index<4; index++) fResolutionConstants[index] = 0.;
+        fWeightType[0] = 1.; fWeightType[1] = 1.; fWeightType[2] = 1.;
+        for(Int_t iPar = 0; iPar < 45; iPar++) fParameters[iPar] = 0.;
+        fParameters[9] = 1.;fParameters[11] = 1.;fParameters[12] = 1.;
        AliInfo("Instance of AliDielectronBtoJPSItoEleCDFfitFCN-class created");
 }
 //_________________________________________________________________________________________________
@@ -67,13 +65,13 @@ AliDielectronBtoJPSItoEleCDFfitFCN::AliDielectronBtoJPSItoEleCDFfitFCN(const Ali
        fhCsiMC(source.fhCsiMC),
        fMassWndHigh(source.fMassWndHigh),
        fMassWndLow(source.fMassWndLow),
-       fCrystalBallParam(source.fCrystalBallParam)
+       fCrystalBallParam(source.fCrystalBallParam) 
 {
        //
        // Copy constructor
        //
-       for(Int_t iPar = 0; iPar < 20; iPar++) fParameters[iPar] = source.fParameters[iPar];
-       for(Int_t index=0; index<4; index++) fResolutionConstants[index] = source.fResolutionConstants[index];
+       for(Int_t iPar = 0; iPar < 45; iPar++) fParameters[iPar] = source.fParameters[iPar];
+        for(Int_t iW=0; iW<2; iW++) fWeightType[iW] = source.fWeightType[iW]; 
 }
 //_________________________________________________________________________________________________
 AliDielectronBtoJPSItoEleCDFfitFCN& AliDielectronBtoJPSItoEleCDFfitFCN::operator=(const AliDielectronBtoJPSItoEleCDFfitFCN& source) 
@@ -90,9 +88,7 @@ AliDielectronBtoJPSItoEleCDFfitFCN& AliDielectronBtoJPSItoEleCDFfitFCN::operator
        fhCsiMC = source.fhCsiMC;
        fCrystalBallParam = source.fCrystalBallParam;
 
-       for(Int_t iPar = 0; iPar < 20; iPar++) fParameters[iPar] = source.fParameters[iPar];
-       for(Int_t index=0; index<4; index++) fResolutionConstants[index] = source.fResolutionConstants[index];
-
+       for(Int_t iPar = 0; iPar < 45; iPar++) fParameters[iPar] = source.fParameters[iPar];
        return *this;
 }  
 //_________________________________________________________________________________________________
@@ -103,12 +99,11 @@ AliDielectronBtoJPSItoEleCDFfitFCN::~AliDielectronBtoJPSItoEleCDFfitFCN()
        //
 
        delete fhCsiMC;
-       for(Int_t iPar = 0; iPar < 20; iPar++) fParameters[iPar] = 0.;
-       for(Int_t index=0; index<4; index++) fResolutionConstants[index] = 0.;
+       for(Int_t iPar = 0; iPar < 45; iPar++) fParameters[iPar] = 0.;
 }
 //_________________________________________________________________________________________________
 Double_t AliDielectronBtoJPSItoEleCDFfitFCN::EvaluateLikelihood(const Double_t* pseudoproperdecaytime,
-               const Double_t* invariantmass, const Int_t ncand) const
+               const Double_t* invariantmass, const Int_t *type, const Int_t ncand) const
 {
        //
        // This function evaluates the Likelihood fnction
@@ -118,11 +113,11 @@ Double_t AliDielectronBtoJPSItoEleCDFfitFCN::EvaluateLikelihood(const Double_t*
        Double_t ret = 0.;
 
        for(Int_t i=0; i < ncand; i++) {
-               f = EvaluateCDFfuncNorm(pseudoproperdecaytime[i],invariantmass[i]);
+               f = EvaluateCDFfuncNorm(pseudoproperdecaytime[i],invariantmass[i],type[i]);
                if(f <= 0.) continue;  
-               ret += -1*TMath::Log(f);  
+                ret += -1*TMath::Log(f);  
        }
-       return ret;
+        return ret;
 }
 //_________________________________________________________________________________________________
 void AliDielectronBtoJPSItoEleCDFfitFCN::SetAllParameters(const Double_t* parameters)
@@ -130,7 +125,7 @@ void AliDielectronBtoJPSItoEleCDFfitFCN::SetAllParameters(const Double_t* parame
        //
        // Sets array of FCN parameters
        //
-       for(Int_t index = 0; index < 20; index++) fParameters[index] = parameters[index];
+       for(Int_t index = 0; index < 45; index++) fParameters[index] = parameters[index];
 }
 //_________________________________________________________________________________________________
 void AliDielectronBtoJPSItoEleCDFfitFCN::ComputeMassIntegral() 
@@ -167,7 +162,8 @@ void AliDielectronBtoJPSItoEleCDFfitFCN::ComputeMassIntegral()
                summMassBkg += EvaluateCDFInvMassBkgDistr(mx);
        }
        intmMassBkg = summMassBkg*stepm;
-       SetIntegralMassBkg(intmMassBkg);
+       if(intmMassBkg < 1.e-05) intmMassBkg = 1.;
+        SetIntegralMassBkg(intmMassBkg);
 }
 //_________________________________________________________________________________________________
 void AliDielectronBtoJPSItoEleCDFfitFCN::PrintStatus()
@@ -205,11 +201,43 @@ void AliDielectronBtoJPSItoEleCDFfitFCN::PrintStatus()
        printf("actual value of meanBkg ----------------------------------------->> | %f \n", GetBkgInvMassMean());
        printf("actual value of slopeBkg ---------------------------------------->> | %f \n", GetBkgInvMassSlope());
        printf("actual value of constBkg ---------------------------------------->> | %f \n", GetBkgInvMassConst());
-       // resolution func
-       printf("actual value of norm1Gauss -------------------------------------->> | %f \n",GetNormGaus1ResFunc());
-       printf("actual value of norm2Gauss -------------------------------------->> | %f \n",GetNormGaus2ResFunc());
-
-       printf("\n");
+       // resolution func (First-First)
+       printf("actual value of norm1Gauss (FF) --------------------------------->> | %f \n", GetNormGaus1ResFunc(2));
+       printf("actual value of norm2Gauss (FF) --------------------------------->> | %f \n", GetNormGaus2ResFunc(2));
+        printf("actual value of fMean1Res (FF) ---------------------------------->> | %f \n", GetResMean1(2));
+        printf("actual value of fSigma1Res (FF) --------------------------------->> | %f \n", GetResSigma1(2));
+        printf("actual value of fMean2Res (FF) ---------------------------------->> | %f \n", GetResMean2(2));
+        printf("actual value of fSigma2Res (FF) --------------------------------->> | %f \n", GetResSigma2(2));
+        
+        printf("actual value of alfaRes (FF) ------------------------------------>> | %f \n", GetResAlfa(2));
+        printf("actual value of lambdaRes (FF) ---------------------------------->> | %f \n", GetResLambda(2)); 
+        printf("actual value of normExpRes (FF) --------------------------------->> | %f \n", GetResNormExp(2)); 
+       
+        // resolution func (First-Second)
+        printf("actual value of norm1Gauss (FS) --------------------------------->> | %f \n", GetNormGaus1ResFunc(1));
+        printf("actual value of norm2Gauss (FS) --------------------------------->> | %f \n", GetNormGaus2ResFunc(1));
+        printf("actual value of fMean1Res (FS) ---------------------------------->> | %f \n", GetResMean1(1));
+        printf("actual value of fSigma1Res (FS) --------------------------------->> | %f \n", GetResSigma1(1));
+        printf("actual value of fMean2Res (FS) ---------------------------------->> | %f \n", GetResMean2(1));
+        printf("actual value of fSigma2Res (FS) --------------------------------->> | %f \n", GetResSigma2(1));
+        
+        printf("actual value of alfaRes (FS) ------------------------------------>> | %f \n", GetResAlfa(1));
+        printf("actual value of lambdaRes (FS) ---------------------------------->> | %f \n", GetResLambda(1));    
+        printf("actual value of normExpRes (FS) --------------------------------->> | %f \n", GetResNormExp(1));    
+        
+        // resolution func (Second-Second) 
+        printf("actual value of norm1Gauss (SS) --------------------------------->> | %f \n", GetNormGaus1ResFunc(0));
+        printf("actual value of norm2Gauss (SS) --------------------------------->> | %f \n", GetNormGaus2ResFunc(0));
+        printf("actual value of fMean1Res (SS) ---------------------------------->> | %f \n", GetResMean1(0));
+        printf("actual value of fSigma1Res (SS) --------------------------------->> | %f \n", GetResSigma1(0));
+        printf("actual value of fMean2Res (SS) ---------------------------------->> | %f \n", GetResMean2(0));
+        printf("actual value of fSigma2Res (SS) --------------------------------->> | %f \n", GetResSigma2(0));
+        
+        printf("actual value of alfaRes (SS) ------------------------------------>> | %f \n", GetResAlfa(0));
+        printf("actual value of lambdaRes (SS) ---------------------------------->> | %f \n", GetResLambda(0));    
+        printf("actual value of normExpRes (SS) --------------------------------->> | %f \n", GetResNormExp(0));    
+
+        printf("\n");
        // integrals constants
        printf("Actual value of normalization integral for MassSig ---------------->> | %f \n", GetIntegralMassSig());
        printf("Actual value of normalization integral for MassBkg ---------------->> | %f \n", GetIntegralMassBkg());
@@ -217,45 +245,56 @@ void AliDielectronBtoJPSItoEleCDFfitFCN::PrintStatus()
        printf("\n");
 }
 //_________________________________________________________________________________________________
-void AliDielectronBtoJPSItoEleCDFfitFCN::SetResolutionConstants(Double_t* resolutionConst)
+void AliDielectronBtoJPSItoEleCDFfitFCN::SetResolutionConstants(Double_t* resolutionConst, Int_t type) 
 {
        //
        // Resolution function is parametrized as the sum of two gaussian
        //
-       fResolutionConstants[0]  = resolutionConst[0]; // mean 1
-       fResolutionConstants[1]  = resolutionConst[1]; // sigma 1
-       fResolutionConstants[2]  = resolutionConst[2]; // mean 2
-       fResolutionConstants[3]  = resolutionConst[3]; // sigma 2
+        Int_t index = (2-type)*9; 
+        fParameters[20+index]=resolutionConst[1]; //mean1
+        fParameters[22+index]=resolutionConst[4]; //mean2
+        fParameters[18+index]=resolutionConst[0]; //norm1
+        fParameters[21+index]=resolutionConst[2]; //sigma1
+        fParameters[23+index]=resolutionConst[5]; //sigma2
+        fParameters[19+index]=resolutionConst[3]; //norm2
+
+        //exp values
+        fParameters[24+index]=resolutionConst[6]; //alfa
+        fParameters[25+index]=resolutionConst[7]; //lambda
+        fParameters[26+index]=resolutionConst[8]; //norm3
+        return;
 }
 
-//_________________________________________________________________________________________________
-Double_t AliDielectronBtoJPSItoEleCDFfitFCN::EvaluateCDFfunc(Double_t x, Double_t m) const 
+//________________________________________________________________________________________________
+Double_t AliDielectronBtoJPSItoEleCDFfitFCN::EvaluateCDFfunc(Double_t x, Double_t m, Int_t type) const 
 {
-       return fParameters[8]*EvaluateCDFfuncSignalPart(x,m) + (1. - fParameters[8])*EvaluateCDFfuncBkgPart(x,m);
+        // evaluate likelihood function
+       return fParameters[8]*EvaluateCDFfuncSignalPart(x,m,type) + (1. - fParameters[8])*EvaluateCDFfuncBkgPart(x,m,type);
 }
 
 //_________________________________________________________________________________________________
-Double_t AliDielectronBtoJPSItoEleCDFfitFCN::EvaluateCDFfuncNorm(Double_t x, Double_t m) const
+Double_t AliDielectronBtoJPSItoEleCDFfitFCN::EvaluateCDFfuncNorm(Double_t x, Double_t m, Int_t type) const
 {
-       return EvaluateCDFfunc(x,m);
+        // evaluate likelihood function
+       return EvaluateCDFfunc(x,m,type);
 }
 
 //_________________________________________________________________________________________________
-Double_t AliDielectronBtoJPSItoEleCDFfitFCN::EvaluateCDFfuncSignalPart(Double_t x, Double_t m) const 
+Double_t AliDielectronBtoJPSItoEleCDFfitFCN::EvaluateCDFfuncSignalPart(Double_t x, Double_t m, Int_t type) const 
 {
-       return EvaluateCDFDecayTimeSigDistr(x)*(EvaluateCDFInvMassSigDistr(m)/fintmMassSig); 
+  // evaluate psproper signal  
+  return EvaluateCDFDecayTimeSigDistr(x,type)*(EvaluateCDFInvMassSigDistr(m)/fintmMassSig); 
 }
 
 //_________________________________________________________________________________________________
-Double_t AliDielectronBtoJPSItoEleCDFfitFCN::EvaluateCDFDecayTimeSigDistr(Double_t x) const
+Double_t AliDielectronBtoJPSItoEleCDFfitFCN::EvaluateCDFDecayTimeSigDistr(Double_t x, Int_t type) const
 {
        //
        // Implementation of the Background part of the Likelyhood function
        // 
-
        Double_t retvalue = 0.;
-       Double_t funBnorm = FunB(x);
-       Double_t funPnorm = ResolutionFunc(x);
+       Double_t funBnorm = FunB(x,type);
+       Double_t funPnorm = ResolutionFunc(x,type);
        retvalue = fParameters[7]*funBnorm + (1. - fParameters[7])*funPnorm;
        return retvalue;
 }
@@ -267,13 +306,11 @@ Double_t AliDielectronBtoJPSItoEleCDFfitFCN::EvaluateCDFInvMassSigDistr(Double_t
        // Parametrization of signal part invariant mass distribution
        // It can be either Crystal Ball function or sum of two Landau
        //
-
        Double_t fitval = 0.;
 
        if(fCrystalBallParam){
                Double_t t = (m-fParameters[9])/fParameters[11]; ;
                if (fParameters[12] < 0) t = -t;
-
                Double_t absAlpha = TMath::Abs((Double_t)fParameters[12]);
 
                if (t >= -absAlpha) {
@@ -294,7 +331,7 @@ Double_t AliDielectronBtoJPSItoEleCDFfitFCN::EvaluateCDFInvMassSigDistr(Double_t
        }
 }
 //_________________________________________________________________________________________________
-Double_t AliDielectronBtoJPSItoEleCDFfitFCN::FunB(Double_t x) const  
+Double_t AliDielectronBtoJPSItoEleCDFfitFCN::FunB(Double_t x, Int_t type) const  
 {
        //  
        // Parameterisation of the fit function for the x part of the Background
@@ -318,19 +355,19 @@ Double_t AliDielectronBtoJPSItoEleCDFfitFCN::FunB(Double_t x) const
                xprime = xlow + (i-.5) * step;
                csiMCxprime = CsiMC(xprime);
                xdiff = xprime - x;
-               resolutionxdiff = ResolutionFunc(xdiff); // normalized value
+               resolutionxdiff = ResolutionFunc(xdiff, type); // normalized value
                sum += csiMCxprime * resolutionxdiff;
        }
 
        return step * sum ;
 }
 //_________________________________________________________________________________________________
-Double_t AliDielectronBtoJPSItoEleCDFfitFCN::FunP(Double_t x) const 
+Double_t AliDielectronBtoJPSItoEleCDFfitFCN::FunP(Double_t x, Int_t type) const 
 {
        //
        //  Parameterisation of the Prompt part for the x distribution
        //
-       return ResolutionFunc(x);
+       return ResolutionFunc(x,type);
 }
 
 
@@ -344,28 +381,28 @@ Double_t AliDielectronBtoJPSItoEleCDFfitFCN::CsiMC(Double_t x) const
        Double_t returnvalue = 0.;
 
        if((fhCsiMC->FindBin(x) > 0) && (fhCsiMC->FindBin(x) < fhCsiMC->GetNbinsX()+1))  
-               returnvalue = fhCsiMC->Interpolate(x);
+       returnvalue = fhCsiMC->Interpolate(x);
 
        return returnvalue;
 }
 
 //_________________________________________________________________________________________________
-Double_t AliDielectronBtoJPSItoEleCDFfitFCN::EvaluateCDFfuncBkgPart(Double_t x,Double_t m) const 
+Double_t AliDielectronBtoJPSItoEleCDFfitFCN::EvaluateCDFfuncBkgPart(Double_t x,Double_t m, Int_t type) const 
 {
        //
        // Return the part of the likelihood function for the background hypothesis
        //
-       return EvaluateCDFDecayTimeBkgDistr(x)*(EvaluateCDFInvMassBkgDistr(m)/fintmMassBkg);
+       return EvaluateCDFDecayTimeBkgDistr(x,type)*(EvaluateCDFInvMassBkgDistr(m)/fintmMassBkg);
 }  
 
 //_________________________________________________________________________________________________
-Double_t AliDielectronBtoJPSItoEleCDFfitFCN::EvaluateCDFDecayTimeBkgDistr(Double_t x) const 
+Double_t AliDielectronBtoJPSItoEleCDFfitFCN::EvaluateCDFDecayTimeBkgDistr(Double_t x, Int_t type) const 
 {
        //
        // it returns the value of the probability to have a given x for the background 
        //
 
-       Double_t ret = fParameters[0]/(fParameters[0]+fParameters[1]+fParameters[2]+fParameters[3])*ResolutionFunc(x) + fParameters[1]/(fParameters[0]+fParameters[1]+fParameters[2]+fParameters[3])*FunBkgPos(x) +  fParameters[2]/(fParameters[0]+fParameters[1]+fParameters[2]+fParameters[3])*FunBkgNeg(x) + fParameters[3]/(fParameters[0]+fParameters[1]+fParameters[2]+fParameters[3])*FunBkgSym(x);
+       Double_t ret = fParameters[0]/(fParameters[0]+fParameters[1]+fParameters[2]+fParameters[3])*ResolutionFunc(x,type) + fParameters[1]/(fParameters[0]+fParameters[1]+fParameters[2]+fParameters[3])*FunBkgPos(x,type) +  fParameters[2]/(fParameters[0]+fParameters[1]+fParameters[2]+fParameters[3])*FunBkgNeg(x,type) + fParameters[3]/(fParameters[0]+fParameters[1]+fParameters[2]+fParameters[3])*FunBkgSym(x,type);
        return ret;
 }
 
@@ -380,12 +417,11 @@ Double_t AliDielectronBtoJPSItoEleCDFfitFCN::EvaluateCDFInvMassBkgDistr(Double_t
        return value;
 }
 //_________________________________________________________________________________________________
-Double_t AliDielectronBtoJPSItoEleCDFfitFCN::FunBkgPos(Double_t x) const 
+Double_t AliDielectronBtoJPSItoEleCDFfitFCN::FunBkgPos(Double_t x,Int_t type) const 
 {
        //
        // exponential with positive slopes for the background part (x)
        //
-
        Double_t np = 1000.0;
        Double_t sc = 10.;      
        Double_t sigma3 = 1000.; // valore usato nella macro 
@@ -400,15 +436,15 @@ Double_t AliDielectronBtoJPSItoEleCDFfitFCN::FunBkgPos(Double_t x) const
 
        for(i=1.0; i<=np/2; i++) {
                xprime = xlow + (i-.5) * step;
-               if (xprime > 0) {sum += fParameters[4] * TMath::Exp(-1*xprime*fParameters[4])*(ResolutionFunc(xprime-x));}
+               if (xprime > 0) {sum += fParameters[4] * TMath::Exp(-1*xprime*fParameters[4])*(ResolutionFunc(xprime-x,type));}
                xprime = xupp - (i-.5) * step;
-               if (xprime > 0) {sum += fParameters[4] * TMath::Exp(-1*xprime*fParameters[4])*(ResolutionFunc(xprime-x));}
+               if (xprime > 0) {sum += fParameters[4] * TMath::Exp(-1*xprime*fParameters[4])*(ResolutionFunc(xprime-x,type));}
        }
 
        return step * sum ;
 }
 //_________________________________________________________________________________________________
-Double_t AliDielectronBtoJPSItoEleCDFfitFCN::FunBkgNeg(Double_t x) const 
+Double_t AliDielectronBtoJPSItoEleCDFfitFCN::FunBkgNeg(Double_t x, Int_t type) const 
 {
        //
        // exponential with negative slopes for the background part (x)
@@ -428,16 +464,16 @@ Double_t AliDielectronBtoJPSItoEleCDFfitFCN::FunBkgNeg(Double_t x) const
        for(i=1.0; i<=np/2; i++) {
 
                xprime = xlow + (i-.5) * step;
-               if (xprime < 0) {sum += fParameters[5] * TMath::Exp(xprime*fParameters[5]) * (ResolutionFunc(xprime-x));}
+               if (xprime < 0) {sum += fParameters[5] * TMath::Exp(xprime*fParameters[5]) * (ResolutionFunc(xprime-x,type));}
 
                xprime = xupp - (i-.5) * step;
-               if (xprime < 0) {sum += fParameters[5] * TMath::Exp(xprime*fParameters[5]) * (ResolutionFunc(xprime-x));}
+               if (xprime < 0) {sum += fParameters[5] * TMath::Exp(xprime*fParameters[5]) * (ResolutionFunc(xprime-x,type));}
        }
 
        return step * sum ;
 }
 //_________________________________________________________________________________________________
-Double_t AliDielectronBtoJPSItoEleCDFfitFCN::FunBkgSym(Double_t x) const 
+Double_t AliDielectronBtoJPSItoEleCDFfitFCN::FunBkgSym(Double_t x, Int_t type) const 
 {
        //
        // exponential with both positive and negative slopes for the background part (x)
@@ -458,64 +494,198 @@ Double_t AliDielectronBtoJPSItoEleCDFfitFCN::FunBkgSym(Double_t x) const
        for(i=1.0; i<=np/2; i++) {
 
                xprime = xlow + (i-.5) * step;
-               if (xprime > 0) {sum1 += 0.5 * fParameters[6]*TMath::Exp(-1*xprime*fParameters[6]) * (ResolutionFunc(xprime-x));}
-               if (xprime < 0) {sum2 += 0.5 * fParameters[6]*TMath::Exp(xprime*fParameters[6]) * (ResolutionFunc(xprime-x));}
+               if (xprime > 0) {sum1 += 0.5 * fParameters[6]*TMath::Exp(-1*xprime*fParameters[6]) * (ResolutionFunc(xprime-x,type));}
+               if (xprime < 0) {sum2 += 0.5 * fParameters[6]*TMath::Exp(xprime*fParameters[6]) * (ResolutionFunc(xprime-x,type));}
 
                xprime = xupp - (i-.5) * step;
-               if (xprime > 0) {sum1 += 0.5 * fParameters[6]*TMath::Exp(-1*xprime*fParameters[6]) * (ResolutionFunc(xprime-x));} 
-               if (xprime < 0) {sum2 += 0.5 * fParameters[6]*TMath::Exp(xprime*fParameters[6]) * (ResolutionFunc(xprime-x));}
+               if (xprime > 0) {sum1 += 0.5 * fParameters[6]*TMath::Exp(-1*xprime*fParameters[6]) * (ResolutionFunc(xprime-x,type));} 
+               if (xprime < 0) {sum2 += 0.5 * fParameters[6]*TMath::Exp(xprime*fParameters[6]) * (ResolutionFunc(xprime-x,type));}
        }
 
        return step*(sum1 + sum2) ;
 }
 //_________________________________________________________________________________________________
-Double_t AliDielectronBtoJPSItoEleCDFfitFCN::ResolutionFunc(Double_t x) const 
+Double_t AliDielectronBtoJPSItoEleCDFfitFCN::ResolutionFunc(Double_t x, Int_t type) const  
 {
        //
        // parametrization with 2 gaus
        //
-       Double_t ret = 0.;
-       Double_t mean1 = fResolutionConstants[0]; 
-       Double_t mean2 = fResolutionConstants[2];
-       Double_t norm1 = fParameters[18];
-       Double_t sigma1 = fResolutionConstants[1];
-       Double_t sigma2 = fResolutionConstants[3]; 
-       Double_t norm2 = fParameters[19];
-
-       ret = (norm1/(norm1+norm2))*((1/(sigma1*TMath::Sqrt(2*TMath::Pi())))*TMath::Exp(-0.5*((x-mean1)/sigma1)*((x-mean1)/sigma1)))+(norm2/(norm1+norm2))*((1/(sigma2*TMath::Sqrt(2*TMath::Pi())))*TMath::Exp(-0.5*((x-mean2)/sigma2)*((x-mean2)/sigma2))); 
-
-       return ret;
-}
+        Int_t index = (2-type)*9;
+        Double_t mean1 = fParameters[20+index];
+        Double_t mean2 = fParameters[22+index];
+        Double_t norm1 = fParameters[18+index];
+       Double_t sigma1 = fParameters[21+index];
+       Double_t sigma2 = fParameters[23+index];
+        Double_t norm2 = fParameters[19+index];
+        //exp values
+        Double_t alfa = fParameters[24+index];
+        Double_t lambda = fParameters[25+index];
+        Double_t norm3 = fParameters[26+index];
+        Double_t ret = 0.; Double_t fitval = 0; 
+        if(TMath::Abs(x)<=alfa) fitval = (lambda-1)/(2*alfa*lambda);
+        else  fitval = ((lambda-1)/(2*alfa*lambda))*TMath::Power(alfa,lambda)*(TMath::Power(TMath::Abs(x),-1*lambda));
+
+        ret = (norm1/(norm1+norm2+norm3))*((1/(sigma1*TMath::Sqrt(2*TMath::Pi())))*TMath::Exp(-0.5*((x-mean1)/sigma1)*((x-mean1)/sigma1))) + (norm2/(norm1+norm2+norm3))*((1/(sigma2*TMath::Sqrt(2*TMath::Pi())))*TMath::Exp(-0.5*((x-mean2)/sigma2)*((x-mean2)/sigma2))) + (norm3/(norm1+norm2+norm3))*fitval;
+
+        return ret;
+}     
 
 //_________________________________________________________________________________________________
-TF1* AliDielectronBtoJPSItoEleCDFfitFCN::GetCsiMC(Double_t xmin, Double_t xmax) 
+TF1* AliDielectronBtoJPSItoEleCDFfitFCN::GetCsiMC(Double_t xmin, Double_t xmax, Double_t normalization) 
 {
        // return the pointer to the templateMC function 
-       TF1* templateMC = new TF1("MCtemplate",this,&AliDielectronBtoJPSItoEleCDFfitFCN::CsiMCfunc,xmin,xmax,0);
-       templateMC->SetNpx(5000);
+       TF1* templateMC = new TF1("MCtemplate",this,&AliDielectronBtoJPSItoEleCDFfitFCN::CsiMCfunc,xmin,xmax,1);
+       templateMC->SetParameter(0,normalization);
+        templateMC->SetNpx(5000);
         return (TF1*)templateMC->Clone();
 }
 
 //__________________________________________________________________________________________________
-TF1* AliDielectronBtoJPSItoEleCDFfitFCN::GetResolutionFunc(Double_t xmin, Double_t xmax){
+TF1* AliDielectronBtoJPSItoEleCDFfitFCN::GetResolutionFunc(Double_t xmin, Double_t xmax, Double_t normalization, Double_t type){
        // return the pointer to the resolution function
-       TF1* resFunc = new TF1("resolutionFunc",this,&AliDielectronBtoJPSItoEleCDFfitFCN::ResolutionFuncf,xmin,xmax,0);
+       TF1* resFunc = new TF1(Form("resolutionFunc_%f",type),this,&AliDielectronBtoJPSItoEleCDFfitFCN::ResolutionFuncf,xmin,xmax,2);
+        resFunc->SetParameter(0,normalization);
+        resFunc->SetParameter(1,type);
        resFunc->SetNpx(5000);
         return (TF1*)resFunc->Clone();
 }
 
+//__________________________________________________________________________________________________
+TF1* AliDielectronBtoJPSItoEleCDFfitFCN::GetResolutionFuncAllTypes(Double_t xmin, Double_t xmax, Double_t normalization){
+        // return the pointer to the resolution function
+        TF1* resFunc = new TF1(Form("resolutionFunc"),this,&AliDielectronBtoJPSItoEleCDFfitFCN::ResolutionFuncAllTypes,xmin,xmax,1);
+        resFunc->SetParameter(0,normalization);
+        resFunc->SetNpx(5000);
+        return (TF1*)resFunc->Clone();
+}
+
 //___________________________________________________________________________________________________
-TF1* AliDielectronBtoJPSItoEleCDFfitFCN::GetEvaluateCDFDecayTimeBkgDistr(Double_t xmin, Double_t xmax){
+TF1* AliDielectronBtoJPSItoEleCDFfitFCN::GetEvaluateCDFDecayTimeBkgDistr(Double_t xmin, Double_t xmax, Double_t normalization, Double_t type){
        // return the pointer to the background x distribution function
-       TF1 *backFunc = new TF1("backFunc",this,&AliDielectronBtoJPSItoEleCDFfitFCN::EvaluateCDFDecayTimeBkgDistrFunc,xmin,xmax,0);
+       TF1 *backFunc = new TF1(Form("backFunc_%f",type),this,&AliDielectronBtoJPSItoEleCDFfitFCN::EvaluateCDFDecayTimeBkgDistrFunc,xmin,xmax,2);
+        backFunc->SetParameter(0,normalization);
+        backFunc->SetParameter(1,type);
        backFunc->SetNpx(5000);
         return (TF1*)backFunc->Clone();
 }
 
+//___________________________________________________________________________________________________
+TF1* AliDielectronBtoJPSItoEleCDFfitFCN::GetEvaluateCDFDecayTimeBkgDistrAllTypes(Double_t xmin, Double_t xmax, Double_t normalization){
+        // return the pointer to the background x distribution function
+        TF1 *backFunc = new TF1(Form("backFunc"),this,&AliDielectronBtoJPSItoEleCDFfitFCN::EvaluateCDFDecayTimeBkgDistrFuncAllTypes,xmin,xmax,1);
+        backFunc->SetParameter(0,normalization);
+        backFunc->SetNpx(5000);
+        return (TF1*)backFunc->Clone();
+}
+
 //__________________________________________________________________________________________________
-TF1* AliDielectronBtoJPSItoEleCDFfitFCN::GetEvaluateCDFDecayTimeSigDistr(Double_t xmin, Double_t xmax){
+TF1* AliDielectronBtoJPSItoEleCDFfitFCN::GetEvaluateCDFDecayTimeSigDistr(Double_t xmin, Double_t xmax, Double_t normalization, Double_t type){
        // return the pointer to the signal x distribution function
-       TF1 *signFunc = new TF1("signalFunc",this,&AliDielectronBtoJPSItoEleCDFfitFCN::EvaluateCDFDecayTimeSigDistrFunc,xmin,xmax,0);
+       TF1 *signFunc = new TF1("signalFunc",this,&AliDielectronBtoJPSItoEleCDFfitFCN::EvaluateCDFDecayTimeSigDistrFunc,xmin,xmax,2);
+        signFunc->SetParameter(0,normalization);
+        signFunc->SetParameter(1,type); 
         signFunc->SetNpx(5000);
        return (TF1*)signFunc->Clone();
 }
+
+//____________________________________________________________________________________________________
+TF1* AliDielectronBtoJPSItoEleCDFfitFCN::GetEvaluateCDFInvMassBkgDistr(Double_t mMin, Double_t mMax, Double_t normalization){
+  // return the pointer to the invariant mass distribution for the background 
+  TF1 * invMassBkg = new TF1("invMassBkg",this,&AliDielectronBtoJPSItoEleCDFfitFCN::EvaluateCDFInvMassBkgDistrFunc,mMin,mMax,1);
+  invMassBkg->SetParameter(0,normalization);
+  invMassBkg->SetNpx(5000);
+  return (TF1*)invMassBkg->Clone();
+}
+
+
+//____________________________________________________________________________________________________
+TF1* AliDielectronBtoJPSItoEleCDFfitFCN::GetEvaluateCDFInvMassSigDistr(Double_t mMin, Double_t mMax, Double_t normalization){
+  // return the pointer to the invariant mass distribution for the signal
+  TF1 * invMassSig = new TF1("invMassSig",this,&AliDielectronBtoJPSItoEleCDFfitFCN::EvaluateCDFInvMassSigDistrFunc,mMin,mMax,1);
+  invMassSig->SetParameter(0,normalization);
+  invMassSig->SetNpx(5000);
+  return (TF1*)invMassSig->Clone();
+}
+
+//____________________________________________________________________________________________________
+TF1 *AliDielectronBtoJPSItoEleCDFfitFCN::GetEvaluateCDFInvMassTotalDistr(Double_t mMin, Double_t mMax, Double_t normalization){
+  // return the pointer to the invariant mass distribution
+  TF1 * invMassTot = new TF1("invMassTot",this,&AliDielectronBtoJPSItoEleCDFfitFCN::EvaluateCDFInvMassTotalDistr,mMin,mMax,1);
+  invMassTot->SetParameter(0,normalization);
+  invMassTot->SetNpx(5000);
+  return (TF1*)invMassTot->Clone();
+}
+
+//____________________________________________________________________________________________________
+Double_t AliDielectronBtoJPSItoEleCDFfitFCN::EvaluateCDFInvMassTotalDistr(const Double_t* x, const Double_t *par) const
+{
+  // evaluate invariant mass total distribution
+  Double_t value = 0;
+  Double_t xx = x[0];
+  value = ((EvaluateCDFInvMassSigDistr(xx)/fintmMassSig)*fParameters[8] + (1-fParameters[8])*(EvaluateCDFInvMassBkgDistr(xx)/fintmMassBkg))*par[0];
+  return value;  
+}
+
+//____________________________________________________________________________________________________
+TF1 *AliDielectronBtoJPSItoEleCDFfitFCN::GetEvaluateCDFDecayTimeTotalDistr(Double_t xMin, Double_t xMax, Double_t normalization,Double_t type){
+ // return the pointer to the pseudoproper distribution for the background
+ TF1 *decayTimeTot = new TF1(Form("decayTimeTot_%f",type),this,&AliDielectronBtoJPSItoEleCDFfitFCN::EvaluateCDFDecayTimeTotalDistr,xMin,xMax,2);
+ decayTimeTot->SetParameter(0,normalization);
+ decayTimeTot->SetParameter(1,type);
+ decayTimeTot->SetNpx(5000);
+ return (TF1*)decayTimeTot->Clone();
+}
+
+//____________________________________________________________________________________________________
+Double_t AliDielectronBtoJPSItoEleCDFfitFCN::EvaluateCDFDecayTimeTotalDistr(const Double_t* x, const Double_t *par) const
+{
+ // evaluate the total pseudoproper distribution for a given candidate's type. par[1] should be the candidate's type.
+ Double_t value = 0;
+ Double_t xx = x[0];
+ value = (fParameters[8]*EvaluateCDFDecayTimeSigDistr(xx,(Int_t)par[1]) + (1-fParameters[8])*EvaluateCDFDecayTimeBkgDistr(xx,(Int_t)par[1]))*par[0];
+ return value;
+}
+
+//____________________________________________________________________________________________________
+Double_t AliDielectronBtoJPSItoEleCDFfitFCN::EvaluateCDFDecayTimeTotalDistrAllTypes(const Double_t* x, const Double_t *par) const
+{
+ // evaluate the total pseudoproper distribution considering all candidate's types
+ Double_t value = 0;
+ Double_t xx = x[0];
+
+ value = (fParameters[8]*(fWeightType[2]*EvaluateCDFDecayTimeSigDistr(xx,2)+fWeightType[1]*EvaluateCDFDecayTimeSigDistr(xx,1)+fWeightType[0]*EvaluateCDFDecayTimeSigDistr(xx,0)))+((1-fParameters[8])*(fWeightType[2]*EvaluateCDFDecayTimeBkgDistr(xx,2) + fWeightType[1]*EvaluateCDFDecayTimeBkgDistr(xx,1)+fWeightType[0]*EvaluateCDFDecayTimeBkgDistr(xx,0))); 
+
+ return value*par[0];
+}
+
+//____________________________________________________________________________________________________
+TF1 *AliDielectronBtoJPSItoEleCDFfitFCN::GetEvaluateCDFDecayTimeTotalDistrAllTypes(Double_t xMin, Double_t xMax, Double_t normalization){
+ // return the pointer to the pseudoproper function for the background considering all candidate's types
+ TF1 *decayTimeTot = new TF1(Form("decayTimeTot"),this,&AliDielectronBtoJPSItoEleCDFfitFCN::EvaluateCDFDecayTimeTotalDistrAllTypes,xMin,xMax,1);
+ decayTimeTot->SetParameter(0,normalization);
+ decayTimeTot->SetNpx(5000);
+ return (TF1*)decayTimeTot->Clone();
+}
+
+
+//____________________________________________________________________________________________________
+TF1 * AliDielectronBtoJPSItoEleCDFfitFCN::GetFunB(Double_t xmin, Double_t xmax, Double_t normalization, Double_t type){
+ // return the pointer to the function that describe secondary jpsi pseudoproper distribution for a given candidate's type
+ TF1* funb = new TF1(Form("secondaryJpsiConvolution_%f",type),this,&AliDielectronBtoJPSItoEleCDFfitFCN::FunBfunc,xmin,xmax,2);
+ funb->SetParameter(0,normalization);
+ funb->SetParameter(1,type);
+ funb->SetNpx(5000);
+ return (TF1*)funb->Clone();
+ }
+
+//____________________________________________________________________________________________________
+TF1 * AliDielectronBtoJPSItoEleCDFfitFCN::GetFunBAllTypes(Double_t xmin, Double_t xmax, Double_t normalization){
+// return the pointer to the function that describe secondary jpsi pseudoproper distribution for all types
+ TF1* funb = new TF1(Form("secondaryJpsiConvolution"),this,&AliDielectronBtoJPSItoEleCDFfitFCN::FunBfuncAllTypes,xmin,xmax,1);
+ funb->SetParameter(0,normalization);
+ funb->SetNpx(5000);
+ return (TF1*)funb->Clone();
+ }
+
+
index e94e61d..9b6ca88 100644 (file)
@@ -15,7 +15,7 @@
 \r
 #include <TNamed.h>\r
 #include <TDatabasePDG.h>\r
-#include <TH1F.h>\r
+#include "TH1F.h"\r
 \r
 class TRandom3;\r
 class TF1;\r
@@ -39,7 +39,7 @@ class AliDielectronBtoJPSItoEleCDFfitFCN : public TNamed {
                virtual ~AliDielectronBtoJPSItoEleCDFfitFCN();\r
 \r
                Double_t EvaluateLikelihood(const Double_t* pseudoproperdecaytime,\r
-                               const Double_t* invariantmass, const Int_t ncand) const;\r
+                               const Double_t* invariantmass, const Int_t* type, const Int_t ncand) const;\r
 \r
                Double_t GetResWeight()                    const { return fParameters[0]; }\r
                Double_t GetFPlus()                        const { return fParameters[1]; }\r
@@ -59,21 +59,39 @@ class AliDielectronBtoJPSItoEleCDFfitFCN : public TNamed {
                Double_t GetBkgInvMassMean()               const { return fParameters[15]; }\r
                Double_t GetBkgInvMassSlope()              const { return fParameters[16]; }  \r
                Double_t GetBkgInvMassConst()              const { return fParameters[17]; } \r
-               Double_t GetNormGaus1ResFunc()             const { return fParameters[18]; }\r
-               Double_t GetNormGaus2ResFunc()             const { return fParameters[19]; }\r
+               Double_t GetNormGaus1ResFunc(Int_t type)   const { return fParameters[18+(2-type)*9]; }\r
+               Double_t GetNormGaus2ResFunc(Int_t type)   const { return fParameters[19+(2-type)*9]; }\r
                Double_t GetIntegralMassSig()              const { return fintmMassSig; }\r
                Double_t GetIntegralMassBkg()              const { return fintmMassBkg; }\r
-               const Double_t* GetResolutionConstants()   const { return fResolutionConstants; }\r
-               Bool_t GetCrystalBallParam()               const { return fCrystalBallParam; }\r
+                Double_t GetResMean1(Int_t type)           const { return fParameters[20+(2-type)*9]; } \r
+                Double_t GetResSigma1(Int_t type)          const { return fParameters[21+(2-type)*9]; }\r
+                Double_t GetResMean2(Int_t type)           const { return fParameters[22+(2-type)*9]; }\r
+                Double_t GetResSigma2(Int_t type)          const { return fParameters[23+(2-type)*9]; }\r
+                \r
+                Double_t GetResAlfa(Int_t type)            const { return fParameters[24+(2-type)*9]; }   \r
+                Double_t GetResLambda(Int_t type)          const { return fParameters[25+(2-type)*9]; } \r
+                Double_t GetResNormExp(Int_t type)         const { return fParameters[26+(2-type)*9]; }\r
+\r
+                Bool_t GetCrystalBallParam()               const { return fCrystalBallParam; }\r
                TH1F * GetCsiMcHisto()                     const { return fhCsiMC; }\r
+                Double_t GetResWeight(Int_t iW)            const { return fWeightType[iW]; }\r
 \r
                // return pointer to likelihood functions  \r
-               TF1* GetCsiMC(Double_t xmin, Double_t xmax);\r
-               TF1* GetResolutionFunc(Double_t xmin, Double_t xmax);\r
-               TF1* GetEvaluateCDFDecayTimeBkgDistr(Double_t xmin, Double_t xmax);\r
-               TF1* GetEvaluateCDFDecayTimeSigDistr(Double_t xmin, Double_t xmax);\r
-\r
-               void SetResWeight (Double_t resWgt) {fParameters[0] = resWgt;}\r
+               TF1* GetCsiMC(Double_t xmin, Double_t xmax,Double_t normalization);\r
+               TF1* GetResolutionFunc(Double_t xmin, Double_t xmax,Double_t normalization, Double_t type=2);\r
+               TF1* GetResolutionFuncAllTypes(Double_t xmin, Double_t xmax,Double_t normalization);\r
+               TF1* GetFunB(Double_t xmin, Double_t xmax, Double_t normalization, Double_t type=2);\r
+                TF1* GetFunBAllTypes(Double_t xmin, Double_t xmax, Double_t normalization);\r
+                TF1* GetEvaluateCDFDecayTimeBkgDistr(Double_t xmin, Double_t xmax, Double_t normalization,Double_t type = 2);\r
+               TF1* GetEvaluateCDFDecayTimeBkgDistrAllTypes(Double_t xmin, Double_t xmax, Double_t normalization);\r
+                TF1* GetEvaluateCDFDecayTimeSigDistr(Double_t xmin, Double_t xmax, Double_t normalization, Double_t type);\r
+                TF1* GetEvaluateCDFInvMassBkgDistr(Double_t mMin, Double_t mMax, Double_t normalization);\r
+                TF1* GetEvaluateCDFInvMassSigDistr(Double_t mMin, Double_t mMax, Double_t normalization);\r
+                TF1* GetEvaluateCDFInvMassTotalDistr(Double_t mMin, Double_t mMax, Double_t normalization);\r
+                TF1* GetEvaluateCDFDecayTimeTotalDistr(Double_t xMin, Double_t xMax, Double_t normalization, Double_t type=2);\r
+                TF1 *GetEvaluateCDFDecayTimeTotalDistrAllTypes(Double_t xMin, Double_t xMax, Double_t normalization);\r
+\r
+               void SetResWeight(Double_t resWgt) {fParameters[0] = resWgt;}\r
                void SetFPlus(Double_t plus) {fParameters[1] = plus;}\r
                void SetFMinus(Double_t minus) {fParameters[2]  = minus;}\r
                void SetFSym(Double_t sym) {fParameters[3] = sym;}\r
@@ -98,11 +116,12 @@ class AliDielectronBtoJPSItoEleCDFfitFCN : public TNamed {
                void SetIntegralMassBkg(Double_t integral) { fintmMassBkg = integral; }\r
                void SetCsiMC(const TH1F* MCtemplate) {fhCsiMC = (TH1F*)MCtemplate->Clone("fhCsiMC");}\r
 \r
-               void SetResolutionConstants(Double_t* resolutionConst);\r
+               void SetResolutionConstants(Double_t* resolutionConst, Int_t type);\r
                void SetMassWndHigh(Double_t limit) { fMassWndHigh = TDatabasePDG::Instance()->GetParticle(443)->Mass() + limit ;}\r
                void SetMassWndLow(Double_t limit) { fMassWndLow = TDatabasePDG::Instance()->GetParticle(443)->Mass() - limit ;}\r
                void SetCrystalBallFunction(Bool_t okCB) {fCrystalBallParam = okCB;}\r
-\r
\r
+                void SetWeightType(Double_t wFF, Double_t wFS, Double_t wSS) {fWeightType[0]= wSS; fWeightType[1]= wFS; fWeightType[2]= wFF;}\r
                void ComputeMassIntegral(); \r
 \r
                void ReadMCtemplates(Int_t BinNum);\r
@@ -110,9 +129,8 @@ class AliDielectronBtoJPSItoEleCDFfitFCN : public TNamed {
                void PrintStatus();\r
 \r
        private:  \r
-               //\r
-               Double_t fParameters[20];        /*  par[0]  = weightRes;                \r
-                                                    par[1]  = fPos;\r
+               Double_t fParameters[45];        /*  par[0]  = weightRes;                \r
+                                                    par[1]  = fPos;\r
                                                     par[2]  = fNeg;\r
                                                     par[3]  = fSym\r
                                                     par[4]  = fOneOvLamPlus;\r
@@ -129,9 +147,34 @@ class AliDielectronBtoJPSItoEleCDFfitFCN : public TNamed {
                                                     par[15] = fBkgMean; \r
                                                     par[16] = fBkgSlope;\r
                                                     par[17] = fBkgConst;\r
-                                                    par[18] = norm1Gaus;\r
-                                                    par[19] = norm2Gaus;*/\r
-\r
+                                                    par[18] = norm1Gaus; // resolution param used for First-First\r
+                                                    par[19] = norm2Gaus;\r
+                                                     par[20] = fMean1ResFunc;\r
+                                                     par[21] = fSigma1ResFunc;\r
+                                                     par[22] = fMean2ResFunc;\r
+                                                     par[23] = fSigma2ResFunc;\r
+                                                     par[24] = fResAlfa;  \r
+                                                     par[25] = fResLambda;\r
+                                                    par[26] = fResNormExp;\r
+                                                     par[27] = norm1Gaus;    // resolution param used for First-Second\r
+                                                     par[28] = norm2Gaus;\r
+                                                     par[29] = fMean1ResFunc;\r
+                                                     par[30] = fSigma1ResFunc;\r
+                                                     par[31] = fMean2ResFunc;\r
+                                                     par[32] = fSigma2ResFunc;\r
+                                                     par[33] = fResAlfa;  \r
+                                                     par[34] = fResLambda;\r
+                                                     par[35] = fResNormExp;\r
+                                                     par[36] = norm1Gaus;    // resolution param used for Second-Second\r
+                                                     par[37] = norm2Gaus;\r
+                                                     par[38] = fMean1ResFunc;\r
+                                                     par[39] = fSigma1ResFunc;\r
+                                                     par[40] = fMean2ResFunc;\r
+                                                     par[41] = fSigma2ResFunc;\r
+                                                     par[42] = fResAlfa; \r
+                                                     par[43] = fResLambda;\r
+                                                     par[44] = fResNormExp;\r
+                                                     */\r
 \r
                Double_t fFPlus;                     // parameters of the log-likelihood function\r
                Double_t fFMinus;                    // Slopes of the x distributions of the background \r
@@ -141,38 +184,48 @@ class AliDielectronBtoJPSItoEleCDFfitFCN : public TNamed {
                Double_t fintmMassBkg;               // integral of invariant mass distribution for the bkg\r
 \r
                TH1F *fhCsiMC;                       // X distribution used as MC template for JPSI from B\r
-               Double_t fResolutionConstants[4];    // constants for the parametrized resolution function R(X)\r
                Double_t fMassWndHigh;               // JPSI Mass window higher limit\r
                Double_t fMassWndLow;                // JPSI Mass window lower limit\r
                Bool_t fCrystalBallParam;            // Boolean to switch to Crystall Ball parameterisation\r
 \r
-               ////\r
+                Double_t fWeightType[3];             // vector with weights of candidates types (used to draw functions)            \r
+                ////\r
 \r
-               Double_t EvaluateCDFfunc(Double_t x, Double_t m) const ;\r
-               Double_t EvaluateCDFfuncNorm(Double_t x, Double_t m) const ;\r
+               Double_t EvaluateCDFfunc(Double_t x, Double_t m, Int_t type) const ;\r
+               Double_t EvaluateCDFfuncNorm(Double_t x, Double_t m, Int_t type) const ;\r
 \r
                ////\r
 \r
-               Double_t EvaluateCDFfuncSignalPart(Double_t x, Double_t m) const ;      // Signal part \r
-               Double_t EvaluateCDFDecayTimeSigDistr(Double_t x) const ;\r
-               Double_t EvaluateCDFDecayTimeSigDistrFunc(const Double_t* x, const Double_t */*par*/) const { return EvaluateCDFDecayTimeSigDistr(x[0]);}\r
+               Double_t EvaluateCDFfuncSignalPart(Double_t x, Double_t m, Int_t type) const ;      // Signal part \r
+               Double_t EvaluateCDFDecayTimeSigDistr(Double_t x, Int_t type) const ;\r
+               Double_t EvaluateCDFDecayTimeSigDistrFunc(const Double_t* x, const Double_t *par) const { return par[0]*EvaluateCDFDecayTimeSigDistr(x[0],(Int_t)par[1]);}\r
                Double_t EvaluateCDFInvMassSigDistr(Double_t m) const ;\r
-               Double_t EvaluateCDFfuncBkgPart(Double_t x,Double_t m) const ;          // Background part\r
-               Double_t EvaluateCDFDecayTimeBkgDistr(Double_t x) const ;\r
-               Double_t EvaluateCDFDecayTimeBkgDistrFunc(const Double_t* x, const Double_t */*par*/) const { return EvaluateCDFDecayTimeBkgDistr(x[0]);}\r
-               Double_t EvaluateCDFInvMassBkgDistr(Double_t m) const ;\r
-\r
-               ////\r
-\r
-               Double_t FunB(Double_t x) const;\r
-               Double_t FunP(Double_t x) const ;\r
+                Double_t EvaluateCDFInvMassSigDistrFunc(const Double_t* x, const Double_t *par) const {return par[0]*EvaluateCDFInvMassSigDistr(x[0])/fintmMassSig;}\r
+               Double_t EvaluateCDFfuncBkgPart(Double_t x,Double_t m,Int_t type) const ;          // Background part\r
+               Double_t EvaluateCDFDecayTimeBkgDistr(Double_t x, Int_t type) const ;\r
+               Double_t EvaluateCDFDecayTimeBkgDistrFunc(const Double_t* x, const Double_t *par) const { return EvaluateCDFDecayTimeBkgDistr(x[0],(Int_t)par[1])*par[0];}\r
+                Double_t EvaluateCDFDecayTimeBkgDistrFuncAllTypes(const Double_t* x, const Double_t *par) const {return (fWeightType[2]*EvaluateCDFDecayTimeBkgDistr(x[0],2)+fWeightType[1]*EvaluateCDFDecayTimeBkgDistr(x[0],1)+fWeightType[0]*EvaluateCDFDecayTimeBkgDistr(x[0],0))*par[0];}\r
+               Double_t EvaluateCDFInvMassBkgDistr(Double_t m) const;\r
+                Double_t EvaluateCDFInvMassBkgDistrFunc(const Double_t* x, const Double_t *par) const {return par[0]*EvaluateCDFInvMassBkgDistr(x[0])/fintmMassBkg;} \r
+                  \r
+                Double_t EvaluateCDFInvMassTotalDistr(const Double_t* x, const Double_t *par) const;\r
+               Double_t EvaluateCDFDecayTimeTotalDistr(const Double_t* x, const Double_t *par) const;  \r
+                ////\r
+                Double_t EvaluateCDFDecayTimeTotalDistrAllTypes(const Double_t* x, const Double_t *par) const;\r
+\r
+               Double_t FunB(Double_t x, Int_t type) const;\r
+               Double_t FunBfunc(const Double_t *x, const Double_t *par) const {return FunB(x[0],(Int_t)par[1])*par[0];}\r
+                Double_t FunBfuncAllTypes(const Double_t *x, const Double_t *par) const {return (fWeightType[2]*FunB(x[0],2)+fWeightType[1]*FunB(x[0],1)+fWeightType[0]*FunB(x[0],0))*par[0];}\r
+                Double_t FunP(Double_t x, Int_t type) const ;\r
                Double_t CsiMC(Double_t x) const;\r
-               Double_t CsiMCfunc(const Double_t* x, const Double_t */*par*/) const {  return CsiMC(x[0]);}\r
-               Double_t FunBkgPos(Double_t x) const ;\r
-               Double_t FunBkgNeg(Double_t x) const ;\r
-               Double_t FunBkgSym(Double_t x) const ;\r
-               Double_t ResolutionFunc(Double_t x) const ;\r
-               Double_t ResolutionFuncf(const Double_t* x, const Double_t */*par*/) const { return ResolutionFunc(x[0]);}\r
+               Double_t CsiMCfunc(const Double_t* x, const Double_t *par) const {  return CsiMC(x[0])*par[0];}\r
+               Double_t FunBkgPos(Double_t x, Int_t type) const ;\r
+               Double_t FunBkgNeg(Double_t x, Int_t type) const ;\r
+               Double_t FunBkgSym(Double_t x, Int_t type) const ;\r
+               Double_t ResolutionFunc(Double_t x, Int_t type) const;\r
+               Double_t ResolutionFuncf(const Double_t* x, const Double_t *par) const { return ResolutionFunc(x[0],(Int_t)par[1])*par[0];}\r
+                Double_t ResolutionFuncAllTypes(const Double_t* x, const Double_t *par) const { return (fWeightType[2]*ResolutionFunc(x[0],2)+fWeightType[1]*ResolutionFunc(x[0],1)+fWeightType[0]*ResolutionFunc(x[0],0))*par[0]; }                 \r
\r
 \r
                ClassDef (AliDielectronBtoJPSItoEleCDFfitFCN,1);         // Unbinned log-likelihood fit \r
 \r
index 6882dd3..8ec5f00 100644 (file)
  * provided "as is" without express or implied warranty.                  *
  **************************************************************************/
 #include <TVirtualFitter.h>
+#include <TFitter.h>
+#include <TMinuit.h>
 #include <TStopwatch.h>
+#include <TCanvas.h>
 #include "AliLog.h"
 #include "AliDielectronBtoJPSItoEleCDFfitHandler.h"
 #include "AliDielectronBtoJPSItoEleCDFfitFCN.h"
@@ -43,35 +46,42 @@ void CDFFunction(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t i
 
 //_________________________________________________________________________________________________
 AliDielectronBtoJPSItoEleCDFfitHandler::AliDielectronBtoJPSItoEleCDFfitHandler():
-       fIsParamFixed(20),
+       fIsParamFixed(45),
        fPrintStatus(kFALSE),
        fUp(0),
        fX(0x0),
        fM(0x0),
-       fLikely(0x0),
-       fNcand(0)
+       fType(0x0),
+        fLikely(0x0),
+       fNcand(0),
+       fContPlot1(0x0),
+       fContPlot2(0x0),
+       fContPlot3(0x0),
+       fitter(0)
 {
        //
        // default constructor
        //
-       for (Int_t i=0; i<20; ++i) fParamStartValues[i]=0x0;
 }
 //_________________________________________________________________________________________________
 AliDielectronBtoJPSItoEleCDFfitHandler::AliDielectronBtoJPSItoEleCDFfitHandler(Double_t* decaytime, 
-               Double_t* invariantmass, Int_t ncand) :
-       fIsParamFixed(20),
+               Double_t* invariantmass, Int_t *type, Int_t ncand) :
+       fIsParamFixed(45),
        fPrintStatus(kFALSE),
        fUp(0),
        fX(decaytime),
        fM(invariantmass),
+        fType(type),
        fLikely(0x0),
-       fNcand(ncand)
+       fNcand(ncand),
+       fContPlot1(0x0),
+       fContPlot2(0x0),
+       fContPlot3(0x0),
+       fitter(0)
 {
        //
        // constructor
        //
-  for (Int_t i=0; i<20; ++i) fParamStartValues[i]=0x0;
-
        AliInfo("\n+++\n+++ Minimization object AliDielectronBtoJPSItoEleCDFfitHandler created\n+++\n");
        fLikely = new AliDielectronBtoJPSItoEleCDFfitFCN();
        AliInfo("\n+++\n+++ CDF fit function object AliDielectronBtoJPSItoEleCDFfitFCN created\n+++\n");
@@ -93,8 +103,33 @@ AliDielectronBtoJPSItoEleCDFfitHandler::AliDielectronBtoJPSItoEleCDFfitHandler(D
        AliInfo("Parameter 15 ----> fBkgMean");
        AliInfo("Parameter 16 ----> fBkgSlope");
        AliInfo("Parameter 17 ----> fBkgConst");
-       AliInfo("Parameter 18 ----> fNormGaus1");
-       AliInfo("Parameter 19 ----> fNormGaus2");
+       AliInfo("Parameter 18 ----> fNormGaus1 (FF)");
+       AliInfo("Parameter 19 ----> fNormGaus2 (FF)");
+        AliInfo("Parameter 20 ----> fMean1Res (FF)");
+        AliInfo("Parameter 21 ----> fsigma1Res (FF)"); 
+        AliInfo("Parameter 22 ----> fMean2Res (FF)");
+        AliInfo("Parameter 23 ----> fsigma2Res (FF)");
+        AliInfo("Parameter 24 ----> fAlfaRes (FF)");
+        AliInfo("Parameter 25 ----> fLambdaRes (FF)");
+        AliInfo("Parameter 26 ----> fNormResExp (FF)");
+        AliInfo("Parameter 27 ----> fNormGaus1 (FS)");
+        AliInfo("Parameter 28 ----> fNormGaus2 (FS)");
+        AliInfo("Parameter 29 ----> fMean1Res (FS)");
+        AliInfo("Parameter 30 ----> fsigma1Res (FS)");
+        AliInfo("Parameter 31 ----> fMean2Res (FS)");
+        AliInfo("Parameter 32 ----> fsigma2Res (FS)");
+        AliInfo("Parameter 33 ----> fAlfaRes (FS)");
+        AliInfo("Parameter 34 ----> fLambdaRes (FS)");
+        AliInfo("Parameter 35 ----> fNormResExp (FS)");
+        AliInfo("Parameter 36 ----> fNormGaus1 (SS)");
+        AliInfo("Parameter 37 ----> fNormGaus2 (SS)");
+        AliInfo("Parameter 38 ----> fMean1Res (SS)");
+        AliInfo("Parameter 39 ----> fsigma1Res (SS)");
+        AliInfo("Parameter 40 ----> fMean2Res (SS)");
+        AliInfo("Parameter 41 ----> fsigma2Res (SS)");
+        AliInfo("Parameter 42 ----> fAlfaRes (SS)");
+        AliInfo("Parameter 43 ----> fLambdaRes (SS)");
+        AliInfo("Parameter 44 ----> fNormResExp (SS)");
 
        AliInfo(Form("\n+++\n+++ Number of candidates ---> %d\n+++\n ", ncand));
 }
@@ -105,14 +140,17 @@ AliDielectronBtoJPSItoEleCDFfitHandler& AliDielectronBtoJPSItoEleCDFfitHandler::
        // Assignment operator
        //
        if (this!=&c) {
-    for (Int_t i=0; i<20; ++i) fParamStartValues[i]=c.fParamStartValues[i];
                fIsParamFixed = c.fIsParamFixed;
                fPrintStatus  = c.fPrintStatus;
                fUp           = c.fUp;
                fX            = c.fX;
                fM            = c.fM;
-               fLikely       = c.fLikely;
+               fType         = c.fType;
+                fLikely       = c.fLikely;
                fNcand        = c.fNcand;
+               fContPlot1    = c.fContPlot1;
+               fContPlot2    = c.fContPlot2;
+               fContPlot3    = c.fContPlot3;
        }
        return *this;
 }
@@ -125,13 +163,17 @@ AliDielectronBtoJPSItoEleCDFfitHandler::AliDielectronBtoJPSItoEleCDFfitHandler(c
        fUp(c.fUp),
        fX(c.fX),
        fM(c.fM),
-       fLikely(c.fLikely),
-       fNcand(c.fNcand)
+       fType(c.fType),
+        fLikely(c.fLikely),
+       fNcand(c.fNcand),
+       fContPlot1(c.fContPlot1),
+       fContPlot2(c.fContPlot2),
+       fContPlot3(c.fContPlot3),
+       fitter(c.fitter)
 {
        //
        // Copy Constructor
        //
-  for (Int_t i=0; i<20; ++i) fParamStartValues[i]=c.fParamStartValues[i];
 }
 //_______________________________________________________________________________________
 AliDielectronBtoJPSItoEleCDFfitHandler::~AliDielectronBtoJPSItoEleCDFfitHandler()
@@ -142,45 +184,111 @@ AliDielectronBtoJPSItoEleCDFfitHandler::~AliDielectronBtoJPSItoEleCDFfitHandler(
        delete fLikely;
 }
 //_______________________________________________________________________________________
-Int_t AliDielectronBtoJPSItoEleCDFfitHandler::DoMinimization()
+Int_t AliDielectronBtoJPSItoEleCDFfitHandler::DoMinimization(Int_t step)
 {
        //
        // performs the minimization
        //
-       static TVirtualFitter *fitter = TVirtualFitter::Fitter(this,20);
-       fitter->SetFCN(CDFFunction);
-
-       fitter->SetParameter(0,"fWeightRes",fParamStartValues[0], 1.e-08, 0., 1.e+06);
-       fitter->SetParameter(1,"fPos",fParamStartValues[1], 1.e-08, 0.,1.e+06);
-       fitter->SetParameter(2,"fNeg",fParamStartValues[2], 1.e-08, 0.,1.e+06);
-       fitter->SetParameter(3,"fSym",fParamStartValues[3], 1.e-08, 0.,1.e+06);
-       fitter->SetParameter(4,"fOneOvLamPlus",fParamStartValues[4], 1.e-10, 0.0000001, 5.e+01);
-       fitter->SetParameter(5,"fOneOvLamMinus",fParamStartValues[5], 1.e-10, 0.00000001, 5.e+01);
-       fitter->SetParameter(6,"fOneOvLamSym",fParamStartValues[6], 1.e-10, 0.00000001, 5.e+01);
-       fitter->SetParameter(7,"fB",fParamStartValues[7], 1.e-10, 0., 1.);
-       fitter->SetParameter(8,"fFsig",fParamStartValues[8], 1.e-10, 0., 1.);
-       fitter->SetParameter(9,"fMmean",fParamStartValues[9], 1.e-08, 0., 1.e+04);
-       fitter->SetParameter(10,"fNexp",fParamStartValues[10], 1.e-08, 0., 1.e+02);
-       fitter->SetParameter(11,"fSigma",fParamStartValues[11], 1.e-08, 0., 1.e+04);
-       fitter->SetParameter(12,"fAlpha",fParamStartValues[12], 1.e-08, 0., 1.e+04);
-       fitter->SetParameter(13,"fNorm",fParamStartValues[13], 1.e-08, 0., 1.e+04);
-       fitter->SetParameter(14,"fBkgNorm",fParamStartValues[14], 1.e-08, 0., 1.e+04);
-       fitter->SetParameter(15,"fBkgMean",fParamStartValues[15], 1.e-08, 0., 1.e+04);
-       fitter->SetParameter(16,"fBkgSlope",fParamStartValues[16], 1.e-08, 0., 1.e+04);
-       fitter->SetParameter(17,"fBkgSlope",fParamStartValues[17], 1.e-08, 0., 1.e+04);
-       fitter->SetParameter(18,"fNormGaus1",fParamStartValues[18], 1.e-08, 0., 1.e+05);
-       fitter->SetParameter(19,"fNormGaus2",fParamStartValues[19], 1.e-08, 0., 1.e+05); 
-
-       for(UInt_t indexparam = 0; indexparam < 20; indexparam++){
-               if(IsParamFixed(indexparam))fitter->FixParameter((Int_t)indexparam);
-       }
+       if(step == 0){ 
+               //fitter = TVirtualFitter::Fitter(this,20);
+               fitter = (TFitter*)TVirtualFitter::Fitter(this,45);
+               fitter->SetFCN(CDFFunction);
+               fitter->SetParameter(0,"fWeightRes",fParamStartValues[0], 1.e-08, 0., 1.e+06);
+               fitter->SetParameter(1,"fPos",fParamStartValues[1], 1.e-08, 0.,1.e+06);
+               fitter->SetParameter(2,"fNeg",fParamStartValues[2], 1.e-08, 0.,1.e+06);
+               fitter->SetParameter(3,"fSym",fParamStartValues[3], 1.e-08, 0.,1.e+06);
+               fitter->SetParameter(4,"fOneOvLamPlus",fParamStartValues[4], 1.e-10, 0.0000001, 5.e+01);
+               fitter->SetParameter(5,"fOneOvLamMinus",fParamStartValues[5], 1.e-10, 0.00000001, 5.e+01);
+               fitter->SetParameter(6,"fOneOvLamSym",fParamStartValues[6], 1.e-10, 0.00000001, 5.e+01);
+               fitter->SetParameter(7,"fB",fParamStartValues[7], 1.e-10, 0., 1.);
+               fitter->SetParameter(8,"fFsig",fParamStartValues[8], 1.e-10, 0., 1.);
+               fitter->SetParameter(9,"fMmean",fParamStartValues[9], 1.e-08, 0., 1.e+04);
+               fitter->SetParameter(10,"fNexp",fParamStartValues[10], 1.e-08, 0., 1.e+02);
+               fitter->SetParameter(11,"fSigma",fParamStartValues[11], 1.e-08, 0., 1.e+04);
+               fitter->SetParameter(12,"fAlpha",fParamStartValues[12], 1.e-08, 0., 1.e+04);
+               fitter->SetParameter(13,"fNorm",fParamStartValues[13], 1.e-08, 0., 1.e+04);
+               fitter->SetParameter(14,"fBkgNorm",fParamStartValues[14], 1.e-08, 0., 1.e+04);
+               fitter->SetParameter(15,"fBkgMean",fParamStartValues[15], 1.e-08, 0., 1.e+04);
+               fitter->SetParameter(16,"fBkgSlope",fParamStartValues[16], 1.e-08, 0., 1.e+04);
+               fitter->SetParameter(17,"fBkgConst",fParamStartValues[17], 1.e-08, 0., 1.e+04);
+               fitter->SetParameter(18,"fNormGaus1FF",fParamStartValues[18], 1.e-08, 0., 1.e+05);
+               fitter->SetParameter(19,"fNormGaus2FF",fParamStartValues[19], 1.e-08, 0., 1.e+05); 
+               fitter->SetParameter(20,"fMean1ResFF",fParamStartValues[20], 1.e-08, 0., 1.e+05);
+                fitter->SetParameter(21,"fSigma1ResFF",fParamStartValues[21], 1.e-08, 0., 1.e+05);
+                fitter->SetParameter(22,"fMean2ResFF",fParamStartValues[22], 1.e-08, 0., 1.e+05);
+                fitter->SetParameter(23,"fSigma2ResFF",fParamStartValues[23], 1.e-08, 0., 1.e+05);
+                fitter->SetParameter(24,"fAlfaResFF",fParamStartValues[24], 1.e-08, 0., 1.e+05);
+                fitter->SetParameter(25,"fLambdaResFF",fParamStartValues[25], 1.e-08, 0., 1.e+05);
+                fitter->SetParameter(26,"fResNormExpFF",fParamStartValues[26], 1.e-08, 0., 1.e+05);
+                fitter->SetParameter(27,"fNormGaus1FS",fParamStartValues[27], 1.e-08, 0., 1.e+05);
+                fitter->SetParameter(28,"fNormGaus2FS",fParamStartValues[28], 1.e-08, 0., 1.e+05);
+                fitter->SetParameter(29,"fMean1ResFS",fParamStartValues[29], 1.e-08, 0., 1.e+05);
+                fitter->SetParameter(30,"fSigma1ResFS",fParamStartValues[30], 1.e-08, 0., 1.e+05);
+                fitter->SetParameter(31,"fMean2ResFS",fParamStartValues[31], 1.e-08, 0., 1.e+05);
+                fitter->SetParameter(32,"fSigma2ResFS",fParamStartValues[32], 1.e-08, 0., 1.e+05);
+                fitter->SetParameter(33,"fAlfaResFS",fParamStartValues[33], 1.e-08, 0., 1.e+05);
+                fitter->SetParameter(34,"fLambdaResFS",fParamStartValues[34], 1.e-08, 0., 1.e+05);
+                fitter->SetParameter(35,"fResNormExpFS",fParamStartValues[35], 1.e-08, 0., 1.e+05);
+                fitter->SetParameter(36,"fNormGaus1SS",fParamStartValues[36], 1.e-08, 0., 1.e+05);
+                fitter->SetParameter(37,"fNormGaus2SS",fParamStartValues[37], 1.e-08, 0., 1.e+05);
+                fitter->SetParameter(38,"fMean1ResSS",fParamStartValues[38], 1.e-08, 0., 1.e+05);
+                fitter->SetParameter(39,"fSigma1ResSS",fParamStartValues[39], 1.e-08, 0., 1.e+05);
+                fitter->SetParameter(40,"fMean2ResSS",fParamStartValues[40], 1.e-08, 0., 1.e+05);
+                fitter->SetParameter(41,"fSigma2ResSS",fParamStartValues[41], 1.e-08, 0., 1.e+05);
+                fitter->SetParameter(42,"fAlfaResSS",fParamStartValues[42], 1.e-08, 0., 1.e+05);
+                fitter->SetParameter(43,"fLambdaResSS",fParamStartValues[43], 1.e-08, 0., 1.e+05);
+                fitter->SetParameter(44,"fResNormExpSS",fParamStartValues[44], 1.e-08, 0., 1.e+05);
+                }
 
-       Double_t arglist[2]={10000,1.0}; 
+       for(UInt_t indexparam = 0; indexparam < 45; indexparam++){
+               if(IsParamFixed(indexparam)) fitter->FixParameter((Int_t)indexparam); 
+               else fitter->ReleaseParameter((Int_t)indexparam);
+       }
+       Double_t arglist[2]={10000,0.1};
+       if(step == 2) {Int_t  iret1 = fitter->ExecuteCommand("MINOS", arglist ,1); return iret1;}
        Int_t iret=fitter->ExecuteCommand("MIGRAD", arglist ,2);
        fitter->PrintResults(4,0);
 
-       AliInfo("Minimization procedure finished\n");
+       if(step == 3) {
+
+               TMinuit* minuitPoint = fitter->GetMinuit(); 
 
+               TCanvas *c2 = new TCanvas("c2","contours",800,800);
+
+               //68.27% (1 sigma) confidence level for 2 parameters (fSIG versus fB)   
+               minuitPoint->SetErrorDef(1.15); // 2.3/2
+               fContPlot1 = (TGraph*)minuitPoint->Contour(100,7,8);
+               fContPlot1->GetXaxis()->SetRange(0,1);
+                fContPlot1->GetYaxis()->SetRange(0,1);
+                fContPlot1->SetLineColor(42);
+               fContPlot1->SetLineWidth(3);
+
+               //95% (2 sigma) confidence level for 2 parameters (fSIG versus fB)   
+               minuitPoint->SetErrorDef(2.995); // 5.99/2
+               fContPlot2 = (TGraph*)minuitPoint->Contour(100,7,8);
+                fContPlot2->GetXaxis()->SetRange(0,1);
+                fContPlot2->GetYaxis()->SetRange(0,1);
+               fContPlot2->SetLineColor(38);
+               fContPlot2->SetLineWidth(3);
+
+               //99.73% (3 sigma) confidence level for 2 parameters (fSIG versus fB)   
+               minuitPoint->SetErrorDef(5.915); // 11.83/2
+               fContPlot3 = (TGraph*)minuitPoint->Contour(100,7,8);
+                fContPlot3->GetXaxis()->SetRange(0,1);
+                fContPlot3->GetXaxis()->SetTitle("f_{B}");
+                fContPlot3->GetYaxis()->SetTitle("f_{Sig}[2.4-4]");
+                fContPlot3->GetYaxis()->SetRange(0,1);
+               fContPlot3->SetLineColor(34);
+               fContPlot3->SetLineWidth(3);
+          
+                fContPlot3->Draw("al");
+                fContPlot2->Draw("l");
+                fContPlot1->Draw("l");
+               
+                c2->Draw();    
+       }
+
+       AliInfo("Minimization procedure finished\n");
        return iret;
 }
 //_______________________________________________________________________________________
@@ -197,7 +305,7 @@ void AliDielectronBtoJPSItoEleCDFfitHandler::CdfFCN(Int_t & /* npar */,
        TStopwatch t;
        t.Start();
 
-       f = fLikely->EvaluateLikelihood(fX,fM,fNcand);
+       f = fLikely->EvaluateLikelihood(fX,fM,fType,fNcand);
 
        t.Stop();
        AliDebug(2,Form("Real time spent to calculate function == %f \n", t.RealTime()));
@@ -207,17 +315,17 @@ void AliDielectronBtoJPSItoEleCDFfitHandler::CdfFCN(Int_t & /* npar */,
        return;
 }
 //_______________________________________________________________________________________
-void AliDielectronBtoJPSItoEleCDFfitHandler::SetParamStartValues(Double_t inputparamvalues[20])
+void AliDielectronBtoJPSItoEleCDFfitHandler::SetParamStartValues(Double_t inputparamvalues[45])
 {
-       for(Int_t index=0; index < 20; index++) fParamStartValues[index] = inputparamvalues[index];
+       for(Int_t index=0; index < 45; index++) fParamStartValues[index] = inputparamvalues[index];
 }
 //_______________________________________________________________________________________
-void AliDielectronBtoJPSItoEleCDFfitHandler::SetResolutionConstants(Double_t* resolutionConst)
+void AliDielectronBtoJPSItoEleCDFfitHandler::SetResolutionConstants(Double_t* resolutionConst, Int_t type)
 {
        //
        // Sets constants for the resolution function
        //
-       fLikely->SetResolutionConstants(resolutionConst);
+       fLikely->SetResolutionConstants(resolutionConst,type);
 
 }
 //_______________________________________________________________________________________
index 7c62e60..4a0b710 100644 (file)
 \r
 #include <TNamed.h>\r
 #include <TBits.h>\r
+#include <TGraph.h>\r
+#include <TFitter.h>\r
 \r
-class AliDielectronBtoJPSItoEleCDFfitFCN;\r
+class AliDielectronBtoJPSItoEleCDFfitFCN ;\r
 \r
 class AliDielectronBtoJPSItoEleCDFfitHandler : public TNamed {\r
        public:\r
@@ -22,7 +24,7 @@ class AliDielectronBtoJPSItoEleCDFfitHandler : public TNamed {
                AliDielectronBtoJPSItoEleCDFfitHandler();\r
                AliDielectronBtoJPSItoEleCDFfitHandler& operator= (const  AliDielectronBtoJPSItoEleCDFfitHandler& c);\r
                AliDielectronBtoJPSItoEleCDFfitHandler(const AliDielectronBtoJPSItoEleCDFfitHandler& c);\r
-               AliDielectronBtoJPSItoEleCDFfitHandler(Double_t* decaytime, Double_t* invariantmass, Int_t ncand);\r
+               AliDielectronBtoJPSItoEleCDFfitHandler(Double_t* decaytime, Double_t* invariantmass, Int_t *type, Int_t ncand);\r
                ~AliDielectronBtoJPSItoEleCDFfitHandler(); \r
                Double_t Up() const { return fUp; }\r
                void SetErrorDef(Double_t up) {fUp = up;}\r
@@ -31,10 +33,14 @@ class AliDielectronBtoJPSItoEleCDFfitHandler : public TNamed {
                void SetParamStartValues (Double_t*);\r
                Double_t* GetStartParamValues() { return fParamStartValues; }\r
                TBits GetFixedParamList() const { return fIsParamFixed; }\r
-               void FixParam(UInt_t param, Bool_t value) { fIsParamFixed.SetBitNumber(param,value); }\r
-               void FixAllParam(Bool_t value) { for(UInt_t par=0;par<20;par++) fIsParamFixed.SetBitNumber(par,value); }\r
+               TFitter *GetFitter() const {return fitter;}\r
+                Double_t GetParameter(Int_t numPar) const {return fitter->GetParameter(numPar);}\r
+                Double_t GetParameterError(Int_t numPar) const {return fitter->GetParError(numPar);}   \r
+\r
+                void FixParam(UInt_t param, Bool_t value) { fIsParamFixed.SetBitNumber(param,value); }\r
+               void FixAllParam(Bool_t value) { for(UInt_t par=0;par<45;par++) fIsParamFixed.SetBitNumber(par,value); }\r
                Bool_t IsParamFixed(UInt_t param) { return fIsParamFixed.TestBitNumber(param); }\r
-               void SetResolutionConstants(Double_t* resolutionConst);\r
+               void SetResolutionConstants(Double_t* resolutionConst, Int_t type);\r
                void SetCrystalBallFunction(Bool_t okCB);\r
                void SetMassWndHigh(Double_t limit);\r
                void SetMassWndLow(Double_t limit);\r
@@ -44,19 +50,26 @@ class AliDielectronBtoJPSItoEleCDFfitHandler : public TNamed {
 \r
                Double_t* Decaytime() const         { return fX; }\r
                Double_t* InvariantMass() const     { return fM; }\r
-               AliDielectronBtoJPSItoEleCDFfitFCN* LikelihoodPointer() const { return fLikely; }\r
-               Int_t DoMinimization();\r
+                Int_t*    TypeCand() const          { return fType;}\r
+               AliDielectronBtoJPSItoEleCDFfitFCN* LikelihoodPointer() const { return fLikely; }\r
+               Int_t DoMinimization(Int_t step = 0);\r
+                \r
 \r
        private:\r
                //\r
                TBits fIsParamFixed;                               //array of bits: 0 = param free; 1 = param fixed;\r
                Bool_t fPrintStatus;                               //flag to enable the prit out of the algorithm at each step\r
-               Double_t fParamStartValues[20];                    //array of parameters input value\r
+               Double_t fParamStartValues[45];                    //array of parameters input value\r
                Double_t fUp;                                      //error definition \r
-               Double_t* fX;                                //pseudo-proper decay time X\r
+               Double_t* fX;                                      //pseudo-proper decay time X\r
                Double_t* fM;                                      //invariant mass M\r
-               AliDielectronBtoJPSItoEleCDFfitFCN* fLikely;                 //Log likelihood function\r
+                Int_t* fType;                                      //candidate type\r
+               AliDielectronBtoJPSItoEleCDFfitFCN* fLikely;       //Log likelihood function\r
                Int_t fNcand;                                      //number of candidates\r
+               TGraph* fContPlot1;                                //contour plot       \r
+               TGraph* fContPlot2;                                //contour plot       \r
+               TGraph* fContPlot3;                                //contour plot       \r
+               TFitter *fitter;                                   //pointer to TFitter object  \r
                //\r
                ClassDef(AliDielectronBtoJPSItoEleCDFfitHandler,1);\r
 \r
index 4f705b4..ec71669 100644 (file)
@@ -1,3 +1,4 @@
+
 /*************************************************************************
 * Copyright(c) 1998-2009, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
@@ -66,6 +67,7 @@ AliDielectronCF::AliDielectronCF() :
   fStepsForCutsIncreasing(kFALSE),
   fStepsForSignal(kTRUE),
   fStepsForBackground(kFALSE),
+  fStepsForMCtruthOnly(kFALSE),
   fNStepMasks(0),
   fPdgMother(-1),
   fSignalsMC(0x0),
@@ -104,6 +106,7 @@ AliDielectronCF::AliDielectronCF(const char* name, const char* title) :
   fStepsForCutsIncreasing(kFALSE),
   fStepsForSignal(kTRUE),
   fStepsForBackground(kFALSE),
+  fStepsForMCtruthOnly(kFALSE),
   fNStepMasks(0),
   fPdgMother(-1),
   fSignalsMC(0x0),
@@ -221,6 +224,7 @@ void AliDielectronCF::InitialiseContainer(const AliAnalysisFilter& filter)
   if (fHasMC){
     if (fStepsForSignal && fSignalsMC) fNAddSteps+=fSignalsMC->GetEntries();
     if (fStepsForBackground) ++fNAddSteps;
+    if (fStepsForMCtruthOnly) --fNAddSteps; // No Step for Pair information
   } else {
     //if 
     fStepForMCtruth=kFALSE;
@@ -228,19 +232,23 @@ void AliDielectronCF::InitialiseContainer(const AliAnalysisFilter& filter)
     fStepsForSignal=kFALSE;
     fStepsForBackground=kFALSE;
   }
-    
+  // consitency checks to not duplicate steps
+  if (fStepsForCutsIncreasing)     fStepForAfterAllCuts=kFALSE;
+  if (fStepsForEachCut&&fNCuts==1) fStepForAfterAllCuts=kFALSE;
+  
   fNSteps=0;
-  if (fStepForMCtruth && fSignalsMC) fNSteps+=fSignalsMC->GetEntries();
+  if (fStepForMCtruth && fSignalsMC)           fNSteps+=fSignalsMC->GetEntries();
   if (fStepForNoCutsMCmotherPid && fSignalsMC) fNSteps+=fSignalsMC->GetEntries();
-  if (fStepForAfterAllCuts) fNSteps+=fNAddSteps;
-
-  if (fStepsForEachCut&&fNCuts>1)        fNSteps+=(fNAddSteps*fNCuts);     //one step for each cut + Signal (MC)
-  if (fStepsForCutsIncreasing&&fNCuts>2) fNSteps+=(fNAddSteps*(fNCuts-2)); //one step for the increasing cuts + Signal (MC)
-                                                      // e.g. cut2&cut3, cut2&cut3&cut4
-  fNSteps+=(fNAddSteps*fNStepMasks);                            // cuts for the additional cut masks
+  if (fStepForAfterAllCuts)                    fNSteps+=fNAddSteps;
+  
+  if (fStepsForEachCut)         fNSteps+=(fNAddSteps*fNCuts); //one step for each cut + Signal (MC)
+  if (fStepsForCutsIncreasing)  fNSteps+=(fNAddSteps*fNCuts); //one step for the increasing cuts + Signal (MC)
+  // e.g. cut1, cut1&cut2, cut1&cut2&cut3, ...
+  
+  fNSteps+=(fNAddSteps*fNStepMasks);                              // cuts for the additional cut masks
 
   if (fStepForPreFilter) fNSteps+=fNAddSteps; //Add at the end for Prefilter (maxcutmask+1)
-
+  
   // create the container
   
   Int_t *nbins=new Int_t[fNVars+2*fNVarsLeg];
@@ -302,40 +310,40 @@ void AliDielectronCF::InitialiseContainer(const AliAnalysisFilter& filter)
   
   TString cutName;
   //Steps for each of the cuts
-  if (fStepsForEachCut&&fNCuts>1){
+  if (fStepsForEachCut){
     for (Int_t iCut=0; iCut<fNCuts;++iCut) {
       cutName=filter.GetCuts()->At(iCut)->GetName(); //TODO: User GetTitle???
-      
-      fCfContainer->SetStepTitle(step++, cutName.Data()); //Step for the cut
-      
+      if (!fStepsForMCtruthOnly) {
+        fCfContainer->SetStepTitle(step++, cutName.Data()); //Step for the cut
+      }
       if (fHasMC){
-       if (fStepsForSignal && fSignalsMC) {
-         for(Int_t i=0; i<fSignalsMC->GetEntries(); i++) {
-           fCfContainer->SetStepTitle(step++, Form("%s (Signal: %s)", cutName.Data(), fSignalsMC->At(i)->GetTitle())); //Step for the cut with MC truth
-         }
-       }
-       if (fStepsForBackground)
+        if (fStepsForSignal && fSignalsMC) {
+          for(Int_t i=0; i<fSignalsMC->GetEntries(); i++) {
+            fCfContainer->SetStepTitle(step++, Form("%s (Signal: %s)", cutName.Data(), fSignalsMC->At(i)->GetTitle())); //Step for  the cut with MC truth
+          } 
+        }
+        if (fStepsForBackground)
           fCfContainer->SetStepTitle(step++, (cutName+" (Background)").Data()); //Step for the cut with MC truth
       }
     }
   }
 
   //Steps for increasing cut match
-  if (fStepsForCutsIncreasing&&fNCuts>2){
-    cutName=filter.GetCuts()->At(0)->GetName(); //TODO: User GetTitle???
-    for (Int_t iCut=1; iCut<fNCuts-1;++iCut) {
-      cutName+="&";
+  if (fStepsForCutsIncreasing){
+    cutName=""; //TODO: User GetTitle???
+    for (Int_t iCut=0; iCut<fNCuts;++iCut) {
+      if (!cutName.IsNull()) cutName+="&";
       cutName+=filter.GetCuts()->At(iCut)->GetName();
-      
-      fCfContainer->SetStepTitle(step++, cutName.Data()); //Step for the cut
-      
+      if (!fStepsForMCtruthOnly) {
+        fCfContainer->SetStepTitle(step++, cutName.Data()); //Step for the cut
+      }
       if (fHasMC){
-       if (fStepsForSignal && fSignalsMC)
-         for(Int_t i=0; i<fSignalsMC->GetEntries(); i++) {
-           fCfContainer->SetStepTitle(step++, Form("%s (Signal: %s)", cutName.Data(), fSignalsMC->At(i)->GetTitle())); //Step for the cut with MC truth
-         }
-        if (fStepsForBackground)
-          fCfContainer->SetStepTitle(step++, (cutName+" (Background)").Data()); //Step for the cut with MC truth
+        if (fStepsForSignal && fSignalsMC)
+          for(Int_t i=0; i<fSignalsMC->GetEntries(); i++) {
+            fCfContainer->SetStepTitle(step++, Form("%s (Signal: %s)", cutName.Data(), fSignalsMC->At(i)->GetTitle())); //Step for the cut with MC truth
+          }
+          if (fStepsForBackground)
+            fCfContainer->SetStepTitle(step++, (cutName+" (Background)").Data()); //Step for the cut with MC truth
       }
     }
   }
@@ -359,9 +367,9 @@ void AliDielectronCF::InitialiseContainer(const AliAnalysisFilter& filter)
     
     if (fHasMC){
       if (fStepsForSignal && fSignalsMC)
-       for(Int_t i=0; i<fSignalsMC->GetEntries(); i++) {
-         fCfContainer->SetStepTitle(step++, Form("%s (Signal: %s)", cutName.Data(), fSignalsMC->At(i)->GetTitle())); //Step for the cut with MC truth
-       }
+        for(Int_t i=0; i<fSignalsMC->GetEntries(); i++) {
+          fCfContainer->SetStepTitle(step++, Form("%s (Signal: %s)", cutName.Data(), fSignalsMC->At(i)->GetTitle())); //Step for the cut with MC truth
+        }
       if (fStepsForBackground)
         fCfContainer->SetStepTitle(step++, (cutName+" (Background)").Data()); //Step for the cut with MC truth
     }
@@ -377,14 +385,16 @@ void AliDielectronCF::InitialiseContainer(const AliAnalysisFilter& filter)
         cutName+=filter.GetCuts()->At(iCut)->GetName();
       }
     }
-    fCfContainer->SetStepTitle(step++, cutName.Data()); //Step for the cut
+    if (!fStepsForMCtruthOnly) {
+      fCfContainer->SetStepTitle(step++, cutName.Data()); //Step for the cut
+    }
     if (fHasMC){
       if (fStepsForSignal && fSignalsMC)
-       for(Int_t i=0; i<fSignalsMC->GetEntries(); i++) {
-         fCfContainer->SetStepTitle(step++, Form("%s (Signal: %s)", cutName.Data(), fSignalsMC->At(i)->GetTitle())); //Step for the cut with MC truth
-       }
-      if (fStepsForBackground)
-        fCfContainer->SetStepTitle(step++, (cutName+" (Background)").Data()); //Step for the cut with MC truth
+        for(Int_t i=0; i<fSignalsMC->GetEntries(); i++) {
+          fCfContainer->SetStepTitle(step++, Form("%s (Signal: %s)", cutName.Data(), fSignalsMC->At(i)->GetTitle())); //Step for the cut with MC truth
+        }
+        if (fStepsForBackground)
+          fCfContainer->SetStepTitle(step++, (cutName+" (Background)").Data()); //Step for the cut with MC truth
     }
   }
 
@@ -394,11 +404,11 @@ void AliDielectronCF::InitialiseContainer(const AliAnalysisFilter& filter)
     fCfContainer->SetStepTitle(step++, cutName.Data()); //Step for the cut
     if (fHasMC){
       if (fStepsForSignal && fSignalsMC)
-       for(Int_t i=0; i<fSignalsMC->GetEntries(); i++) {
-         fCfContainer->SetStepTitle(step++, Form("%s (Signal %s)", cutName.Data(), fSignalsMC->At(i)->GetTitle())); //Step for the cut with MC truth
-       }
-      if (fStepsForBackground)
-        fCfContainer->SetStepTitle(step++, (cutName+" (Background)").Data()); //Step for the cut with MC truth
+        for(Int_t i=0; i<fSignalsMC->GetEntries(); i++) {
+          fCfContainer->SetStepTitle(step++, Form("%s (Signal %s)", cutName.Data(), fSignalsMC->At(i)->GetTitle())); //Step for the cut with MC truth
+        }
+        if (fStepsForBackground)
+          fCfContainer->SetStepTitle(step++, (cutName+" (Background)").Data()); //Step for the cut with MC truth
     }
   }
 
@@ -423,8 +433,12 @@ void AliDielectronCF::Fill(UInt_t mask, const AliDielectronPair *particle)
     for(Int_t i=0; i<fSignalsMC->GetEntries(); i++) isMCTruth[i]=kFALSE;
   }
 
+  //TODO: for the moment don't fill truth information for mixed event paris. No valid MC info is available
+  //      in the mixing handler
+  Bool_t isMixedPair=(particle->GetType()>2&&particle->GetType()<10);
+  
   Bool_t isBackground = kFALSE;
-  if(fHasMC && isMCTruth) {
+  if(fHasMC && isMCTruth && !isMixedPair) {
     for(Int_t i=0; i<fSignalsMC->GetEntries(); ++i) { 
       isMCTruth[i] = AliDielectronMC::Instance()->IsMCTruth(particle, (AliDielectronSignalMC*)fSignalsMC->At(i));
       isBackground = (isBackground || isMCTruth[i]);
@@ -442,9 +456,9 @@ void AliDielectronCF::Fill(UInt_t mask, const AliDielectronPair *particle)
   }
 
   if (fNVarsLeg>0){
-    Double_t valuesLeg1[AliDielectronVarManager::kNMaxValues];
+    Double_t valuesLeg1[AliDielectronVarManager::kNMaxValues]={0};
     AliDielectronVarManager::Fill(particle->GetFirstDaughter(),valuesLeg1);
-    Double_t valuesLeg2[AliDielectronVarManager::kNMaxValues];
+    Double_t valuesLeg2[AliDielectronVarManager::kNMaxValues]={0};
     AliDielectronVarManager::Fill(particle->GetSecondDaughter(),valuesLeg2);
 
     for (Int_t iVar=0; iVar<fNVarsLeg; ++iVar){
@@ -467,27 +481,29 @@ void AliDielectronCF::Fill(UInt_t mask, const AliDielectronPair *particle)
   if (fStepForNoCutsMCmotherPid && isMCTruth){
     for(Int_t i=0; i<fSignalsMC->GetEntries(); ++i) {
       if(isMCTruth[i]) {
-       fCfContainer->Fill(fValues,step);
+        fCfContainer->Fill(fValues,step);
       }
       ++step;
     }
   }
   
   //Steps for each of the cuts
-  if (fStepsForEachCut&&fNCuts>1){
+  if (fStepsForEachCut){
     for (Int_t iCut=0; iCut<fNCuts;++iCut) {
-      if (mask&(1<<iCut)) {
-        fCfContainer->Fill(fValues,step);
-        ++step;
-
+      UInt_t cutMask=1<<iCut;
+      if ((mask&cutMask)==cutMask) {
+        if(!fStepsForMCtruthOnly) {
+          fCfContainer->Fill(fValues,step);
+          ++step;
+        }
         if (fHasMC){
           if ( fStepsForSignal && isMCTruth){
-           for(Int_t i=0; i<fSignalsMC->GetEntries(); ++i) {
-             if(isMCTruth[i]) {
-               fCfContainer->Fill(fValues,step);
-             }
-             ++step;
-           }
+            for(Int_t i=0; i<fSignalsMC->GetEntries(); ++i) {
+              if(isMCTruth[i]) {
+                fCfContainer->Fill(fValues,step);
+              }
+              ++step;
+            }
           }
           if ( fStepsForBackground ){
             if (isBackground) fCfContainer->Fill(fValues,step);
@@ -499,23 +515,26 @@ void AliDielectronCF::Fill(UInt_t mask, const AliDielectronPair *particle)
       }
     }
   }
-
+  
 
   //Steps for increasing cut match
   if (fStepsForCutsIncreasing&&fNCuts>2){
-    for (Int_t iCut=1; iCut<fNCuts-1;++iCut) {
-      if (mask&(1<<((iCut+1)-1))) {
-        fCfContainer->Fill(fValues,step);
-        ++step;
-        
+    for (Int_t iCut=0; iCut<fNCuts;++iCut) {
+      UInt_t cutMask=(1<<(iCut+1))-1;
+      if ((mask&cutMask)==cutMask) {
+        if(!fStepsForMCtruthOnly) {
+          fCfContainer->Fill(fValues,step);
+          ++step;
+        }
+
         if (fHasMC){
-         if ( fStepsForSignal && isMCTruth){
-           for(Int_t i=0; i<fSignalsMC->GetEntries(); ++i) {
-             if(isMCTruth[i]) {
-               fCfContainer->Fill(fValues,step);
-             }
-             ++step;
-           }
+          if ( fStepsForSignal && isMCTruth){
+            for(Int_t i=0; i<fSignalsMC->GetEntries(); ++i) {
+              if(isMCTruth[i]) {
+                fCfContainer->Fill(fValues,step);
+              }
+              ++step;
+            }
           }
           if ( fStepsForBackground ){
             if (isBackground) fCfContainer->Fill(fValues,step);
@@ -531,18 +550,19 @@ void AliDielectronCF::Fill(UInt_t mask, const AliDielectronPair *particle)
   //Steps of user defined cut combinations
   for (UInt_t iComb=0; iComb<fNStepMasks; ++iComb){
     UInt_t userMask=fStepMasks[iComb];
-    if (mask&userMask) {
-      fCfContainer->Fill(fValues,step);
-      ++step;
-      
+    if ((mask&userMask)==userMask) {
+      if(!fStepsForMCtruthOnly) {
+        fCfContainer->Fill(fValues,step);
+        ++step;
+      }
       if (fHasMC){
         if ( fStepsForSignal && isMCTruth){
-         for(Int_t i=0; i<fSignalsMC->GetEntries(); ++i) {
-           if(isMCTruth[i]) {
-             fCfContainer->Fill(fValues,step);
-           }
-           ++step;
-         }
+          for(Int_t i=0; i<fSignalsMC->GetEntries(); ++i) {
+            if(isMCTruth[i]) {
+              fCfContainer->Fill(fValues,step);
+            }
+            ++step;
+          }
         }
         if ( fStepsForBackground ){
           if (isBackground) fCfContainer->Fill(fValues,step);
@@ -557,17 +577,19 @@ void AliDielectronCF::Fill(UInt_t mask, const AliDielectronPair *particle)
   //All cuts
   if (fStepForAfterAllCuts){
     if (mask == selectedMask){
-      fCfContainer->Fill(fValues,step);
-      ++step;
-      
+      if(!fStepsForMCtruthOnly) {
+        fCfContainer->Fill(fValues,step);
+        ++step;
+      }
+
       if (fHasMC){
         if ( fStepsForSignal && isMCTruth){
-         for(Int_t i=0; i<fSignalsMC->GetEntries(); ++i) {
-           if(isMCTruth[i]) {
-             fCfContainer->Fill(fValues,step);
-           }
-           ++step;
-         }
+          for(Int_t i=0; i<fSignalsMC->GetEntries(); ++i) {
+            if(isMCTruth[i]) {
+              fCfContainer->Fill(fValues,step);
+            }
+            ++step;
+          }
         }
         if ( fStepsForBackground ){
           if (isBackground) fCfContainer->Fill(fValues,step);
@@ -578,34 +600,38 @@ void AliDielectronCF::Fill(UInt_t mask, const AliDielectronPair *particle)
       step+=fNAddSteps;
     }
   }
+
+  //prefilter
   if (fStepForPreFilter) {
-       if (mask&(1<<fNCuts)) {
-         fCfContainer->Fill(fValues,step);
-         ++step;
-
-         if (fHasMC){
-           if ( fStepsForSignal && isMCTruth){
-             for(Int_t i=0; i<fSignalsMC->GetEntries(); ++i) {
-               if(isMCTruth[i]) {
-                 fCfContainer->Fill(fValues,step);
-               }
-               ++step;
-             }
-           }
-           if ( fStepsForBackground ){
-             if (isBackground) fCfContainer->Fill(fValues,step);
-             ++step;
-           }
-         }
-       }
-       else {
-         step+=fNAddSteps;
-       }
-  } 
+    if (mask&(1<<fNCuts)) {
+      if(!fStepsForMCtruthOnly) {
+        fCfContainer->Fill(fValues,step);
+        ++step;
+      }
+      if (fHasMC){
+        if ( fStepsForSignal && isMCTruth){
+          for(Int_t i=0; i<fSignalsMC->GetEntries(); ++i) {
+            if(isMCTruth[i]) {
+              fCfContainer->Fill(fValues,step);
+            }
+            ++step;
+          }
+        }
+        if ( fStepsForBackground ){
+          if (isBackground) fCfContainer->Fill(fValues,step);
+          ++step;
+        }
+      }
+    }
+    else {
+      step+=fNAddSteps;
+    }
+  }
+  
   if (step!=fNSteps) {
     AliError("Something went wrong in the step filling!!!");
   }
-  if(isMCTruth) delete [] isMCTruth;  
+  if(isMCTruth) delete [] isMCTruth;
 }
 
 //________________________________________________________________
@@ -623,11 +649,6 @@ void AliDielectronCF::FillMC(const TObject *particle)
   AliVParticle *d2=0x0;
   AliDielectronMC::Instance()->GetDaughters(particle,d1,d2);
   
-  valuesPair[AliDielectronVarManager::kThetaHE]=AliDielectronPair::ThetaPhiCM(d1,d2,kTRUE,kTRUE);
-  valuesPair[AliDielectronVarManager::kPhiHE]=AliDielectronPair::ThetaPhiCM(d1,d2,kTRUE,kFALSE);
-  valuesPair[AliDielectronVarManager::kThetaCS]=AliDielectronPair::ThetaPhiCM(d1,d2,kFALSE,kTRUE);
-  valuesPair[AliDielectronVarManager::kPhiCS]=AliDielectronPair::ThetaPhiCM(d1,d2,kFALSE,kFALSE);
-  
   //TODO: temporary solution, set manually the pair type to 1: unlikesign SE
   valuesPair[AliDielectronVarManager::kPairType]=1;
   
@@ -697,19 +718,15 @@ void AliDielectronCF::FillMC(Int_t label1, Int_t label2, Int_t nSignal) {
   }
 
   Double_t valuesPair[AliDielectronVarManager::kNMaxValues];
+  AliDielectronVarManager::Fill(dieMC->GetMCEvent(), valuesPair);
   AliDielectronVarManager::FillVarMCParticle2(part1,part2,valuesPair);
 
-  valuesPair[AliDielectronVarManager::kThetaHE]=AliDielectronPair::ThetaPhiCM(part1,part2,kTRUE,kTRUE);
-  valuesPair[AliDielectronVarManager::kPhiHE]=AliDielectronPair::ThetaPhiCM(part1,part2,kTRUE,kFALSE);
-  valuesPair[AliDielectronVarManager::kThetaCS]=AliDielectronPair::ThetaPhiCM(part1,part2,kFALSE,kTRUE);
-  valuesPair[AliDielectronVarManager::kPhiCS]=AliDielectronPair::ThetaPhiCM(part1,part2,kFALSE,kFALSE);
-
   if(part1->Charge()*part2->Charge()<0)
     valuesPair[AliDielectronVarManager::kPairType]=1;
   else if(part1->Charge()>0)
     valuesPair[AliDielectronVarManager::kPairType]=0;
   else
-    valuesPair[AliDielectronVarManager::kPairType]=2;
+    valuesPair[AliDielectronVarManager::kPairType]=2; // if one of the two particles is neutral, the pair will go here
 
   for(Int_t iVar=0; iVar<fNVars; ++iVar){
     Int_t var=fVariables[iVar];
index 5b277f3..bae0c6c 100644 (file)
@@ -48,6 +48,7 @@ public:
   void SetStepsForCutsIncreasing(Bool_t steps=kTRUE)   { fStepsForCutsIncreasing=steps;   }
   void SetStepsForSignal(Bool_t steps=kTRUE)           { fStepsForSignal=steps;           }
   void SetStepsForBackground(Bool_t steps=kTRUE)       { fStepsForBackground=steps;       }
+  void SetStepsForMCtruthOnly(Bool_t steps=kTRUE)      { fStepsForMCtruthOnly=steps;       }
   
   void SetPdgMother(Int_t pdg) { fPdgMother=pdg; }
   void SetSignalsMC(TObjArray* array)    {fSignalsMC = array;}
@@ -60,7 +61,13 @@ public:
   void AddVariable(AliDielectronVarManager::ValueTypes type, TVectorD *binLimits, Bool_t leg=kFALSE);
   
   void InitialiseContainer(const AliAnalysisFilter& filter);
-  
+
+  Int_t GetNvarsPair()     const {return fNVars;}
+  Int_t GetNvarsLeg()      const {return fNVarsLeg;}
+
+  UInt_t GetVariablePair(UInt_t var) const {return (var>(UInt_t)AliDielectronVarManager::kNMaxValues)? (UInt_t)AliDielectronVarManager::kNMaxValues+1:fVariables[var];}
+  UInt_t GetVariableLeg(UInt_t var) const {return (var>(UInt_t)AliDielectronVarManager::kNMaxValues)? (UInt_t)AliDielectronVarManager::kNMaxValues+1:fVariablesLeg[var];}
+
 //   void Fill(UInt_t mask, const TObject *particle);
   void Fill(UInt_t mask, const AliDielectronPair *particle);
   void FillMC(const TObject *particle);
@@ -93,6 +100,7 @@ private:
                                         //e.g. cut1&cut2, cut1&cut2&cut3 ...
   Bool_t fStepsForSignal;               //steps for pure signal
   Bool_t fStepsForBackground;           //steps for pure background
+  Bool_t fStepsForMCtruthOnly;          //Switch off all pair steps, allow only MC truth Class
   
   UInt_t fStepMasks[kNmaxAddSteps];      //steps for additional cut combinatons
   UInt_t fNStepMasks;                    //number of configured step masks
index 768f3dd..9d244c4 100644 (file)
@@ -396,11 +396,12 @@ TH1* AliDielectronCFdraw::Project(const Option_t* var, Int_t slice)
     delete arrVars;
     return 0x0;
   }
-  
+
+  TIter next(arrVars);
   TObjString *ostr=0x0;
   Int_t ivar[3]={-1,-1,-1};
   for (Int_t i=entries-1; i>=0; --i){
-    ostr=static_cast<TObjString*>(arrVars->At(i));
+    ostr=static_cast<TObjString*>(next());
     if (ostr->GetString().IsDigit()){
       ivar[i]=ostr->GetString().Atoi();
     } else {
@@ -431,7 +432,7 @@ void AliDielectronCFdraw::DrawEfficiency(const char* varnames, const char* numer
   TIter next(arrVars);
   TObjString *ostr=0x0;
   Int_t ivar[3]={-1,-1,-1};
-  for (Int_t i=0; i<entries; ++i){
+  for (Int_t i=entries-1; i>=0; --i){
     ostr=static_cast<TObjString*>(next());
     if (ostr->GetString().IsDigit()){
       ivar[i]=ostr->GetString().Atoi();
@@ -444,7 +445,7 @@ void AliDielectronCFdraw::DrawEfficiency(const char* varnames, const char* numer
   TString optStr(opt);
   if (optStr.Contains("2")) type=1;
   
-  DrawEfficiency(ivar[2],ivar[1],ivar[0],numerators, denominator,opt,type);
+  DrawEfficiency(ivar[0],ivar[1],ivar[2],numerators, denominator,opt,type);
   delete arrVars;
 }
 
index d5ee6ac..8443e54 100644 (file)
@@ -55,6 +55,7 @@ public:
   void UnsetRangeUser(const char* varname, const char* slices="");
 
   virtual void Draw(const Option_t* varnames = "") { Draw(varnames,"");}
+  virtual void Print(const Option_t*) const { if (fCfContainer) fCfContainer->Print(""); }
   //Draw Projections
   void Draw(const Option_t* varnames, const char* opt, const char* slices="");
   void Draw(Int_t var, const char* opt="", const char* slices="");
diff --git a/PWGDQ/dielectron/AliDielectronEvent.cxx b/PWGDQ/dielectron/AliDielectronEvent.cxx
new file mode 100644 (file)
index 0000000..01cdeb0
--- /dev/null
@@ -0,0 +1,174 @@
+/*************************************************************************
+* Copyright(c) 1998-2009, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+///////////////////////////////////////////////////////////////////////////
+//                Dielectron Event                                  //
+//                                                                       //
+//                                                                       //
+/*
+Detailed description
+
+
+*/
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+#include <TObjArray.h>
+
+#include <AliVTrack.h>
+#include <AliESDtrack.h>
+#include <AliAODTrack.h>
+
+#include "AliDielectronEvent.h"
+
+ClassImp(AliDielectronEvent)
+
+AliDielectronEvent::AliDielectronEvent() :
+  TNamed(),
+  fArrTrackP("AliESDtrack",1000),
+  fArrTrackN("AliESDtrack",1000),
+  fArrPairs("AliKFParticle",0),
+  fNTracksP(0),
+  fNTracksN(0),
+  fIsAOD(kFALSE),
+  fEventData()
+{
+  //
+  // Default Constructor
+  //
+  
+}
+
+//______________________________________________
+AliDielectronEvent::AliDielectronEvent(const char* name, const char* title) :
+  TNamed(name, title),
+  fArrTrackP("AliESDtrack",1000),
+  fArrTrackN("AliESDtrack",1000),
+  fArrPairs("AliKFParticle",0),
+  fNTracksP(0),
+  fNTracksN(0),
+  fIsAOD(kFALSE),
+  fEventData()
+{
+  //
+  // Named Constructor
+  //
+}
+
+//______________________________________________
+AliDielectronEvent::~AliDielectronEvent()
+{
+  //
+  // Default Destructor
+  //
+  fArrTrackP.Delete();
+  fArrTrackN.Delete();
+  fArrPairs.Delete();
+}
+
+//______________________________________________
+void AliDielectronEvent::SetTracks(const TObjArray &arrP, const TObjArray &arrN, const TObjArray &/*arrPairs*/)
+{
+  //
+  // Setup AliKFParticles
+  // assumes that the objects in arrP and arrN are AliVTracks
+  //
+
+  //Clear out old entries before filling new ones
+  Clear();
+  // we keep the tracks buffered to minimise new / delete operations
+  fNTracksN=0;
+  fNTracksP=0;
+
+  //check size of the arrays
+  if (fArrTrackP.GetSize()<arrP.GetSize()) fArrTrackP.Expand(arrP.GetSize());
+  if (fArrTrackN.GetSize()<arrN.GetSize()) fArrTrackN.Expand(arrN.GetSize());
+
+  // fill particles
+  Int_t tracks=0;
+  for (Int_t itrack=0; itrack<arrP.GetEntriesFast(); ++itrack){
+    if (!fIsAOD){
+      AliESDtrack *track=dynamic_cast<AliESDtrack*>(arrP.At(itrack));
+      if (!track) continue;
+      new (fArrTrackP[tracks]) AliESDtrack(*track);
+      ++tracks;
+    } else {
+      AliAODTrack *track=dynamic_cast<AliAODTrack*>(arrP.At(itrack));
+      if (!track) continue;
+      new (fArrTrackP[tracks]) AliAODTrack(*track);
+      ++tracks;
+    }
+  }
+  fNTracksP=tracks;
+
+  tracks=0;
+  for (Int_t itrack=0; itrack<arrN.GetEntriesFast(); ++itrack){
+    if (!fIsAOD){
+      AliESDtrack *track=dynamic_cast<AliESDtrack*>(arrN.At(itrack));
+      if (!track) continue;
+      new (fArrTrackN[tracks]) AliESDtrack(*track);
+      ++tracks;
+    } else {
+      AliAODTrack *track=dynamic_cast<AliAODTrack*>(arrN.At(itrack));
+      if (!track) continue;
+      new (fArrTrackN[tracks]) AliAODTrack(*track);
+      ++tracks;
+    }
+  }
+  fNTracksN=tracks;
+
+  //TODO: pair arrays
+}
+
+//______________________________________________
+void AliDielectronEvent::Clear(Option_t *opt)
+{
+  //
+  // clear arrays
+  //
+//   fArrTrackP.Clear(opt);
+//   fArrTrackN.Clear(opt);
+
+  for (Int_t i=fArrTrackP.GetEntriesFast()-1; i>=0; --i){
+    delete fArrTrackP.RemoveAt(i);
+  }
+  
+  for (Int_t i=fArrTrackN.GetEntriesFast()-1; i>=0; --i){
+    delete fArrTrackN.RemoveAt(i);
+  }
+  
+  fArrPairs.Clear(opt);
+  
+}
+
+//______________________________________________
+void AliDielectronEvent::SetAOD()
+{
+  //
+  // use AOD as input
+  //
+  fArrTrackP.SetClass("AliAODTrack");
+  fArrTrackN.SetClass("AliAODTrack");
+  fIsAOD=kTRUE;
+}
+
+//______________________________________________
+void AliDielectronEvent::SetEventData(const Double_t data[AliDielectronVarManager::kNMaxValues])
+{
+  //
+  // copy only evnet variables
+  //
+  for (Int_t i=AliDielectronVarManager::kPairMax; i<AliDielectronVarManager::kNMaxValues;++i) fEventData[i]=data[i];
+}
\ No newline at end of file
diff --git a/PWGDQ/dielectron/AliDielectronEvent.h b/PWGDQ/dielectron/AliDielectronEvent.h
new file mode 100644 (file)
index 0000000..cf2e53b
--- /dev/null
@@ -0,0 +1,69 @@
+#ifndef ALIDIELECTRONEVENT_H
+#define ALIDIELECTRONEVENT_H
+
+/* Copyright(c) 1998-2009, ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice                               */
+
+//#############################################################
+//#                                                           # 
+//#         Class AliDielectronEvent                     #
+//#                                                           #
+//#  Authors:                                                 #
+//#   Jens      Wiechula, Uni Tübingen / Jens.Wiechula@cern.ch      #
+//#                                                           #
+//#############################################################
+
+#include <TNamed.h>
+#include <TClonesArray.h>
+
+#include "AliDielectronVarManager.h"
+
+
+class TObjArray;
+
+class AliDielectronEvent : public TNamed {
+public:
+  AliDielectronEvent();
+  AliDielectronEvent(const char*name, const char* title);
+
+  virtual ~AliDielectronEvent();
+
+  void SetAOD();
+
+  void SetTracks(const TObjArray &arrP, const TObjArray &arrN, const TObjArray &arrPairs);
+  void SetEventData(const Double_t data[AliDielectronVarManager::kNMaxValues]);
+  const Double_t* GetEventData() const {return fEventData;}
+  
+  
+  const TClonesArray* GetTrackArrayP() const { return &fArrTrackP; }
+  const TClonesArray* GetTrackArrayN() const { return &fArrTrackN; }
+
+  Int_t GetNTracksP() const { return fNTracksP; }
+  Int_t GetNTracksN() const { return fNTracksN; }
+  
+virtual void Clear(Option_t *opt="C");
+
+
+private:
+  TClonesArray fArrTrackP;      //positive tracks
+  TClonesArray fArrTrackN;      //negative tracks
+
+  TClonesArray fArrPairs;       //Pair array
+
+  Int_t fNTracksP;              //number of positive tracks
+  Int_t fNTracksN;              //number of negative tracks
+
+  Bool_t fIsAOD;                // if we deal with AODs
+
+  Double_t fEventData[AliDielectronVarManager::kNMaxValues]; // event informaion from the var manager
+  
+  AliDielectronEvent(const AliDielectronEvent &c);
+  AliDielectronEvent &operator=(const AliDielectronEvent &c);
+
+  
+  ClassDef(AliDielectronEvent,1)         // Dielectron Event
+};
+
+
+
+#endif
index 9c11c26..27dfced 100644 (file)
@@ -25,6 +25,7 @@ Detailed description
 //                                                                       //
 ///////////////////////////////////////////////////////////////////////////
 
+
 #include <AliTriggerAnalysis.h>
 #include <AliESDVertex.h>
 #include <AliESDEvent.h>
@@ -102,6 +103,7 @@ Bool_t AliDielectronEventCuts::IsSelected(TObject* event)
   }
 
   fkVertex=0x0;
+
   switch(fVtxType){
   case kVtxTracks:
   case kVtxTracksOrSPD:
index 60aea63..b9616b9 100644 (file)
@@ -30,6 +30,9 @@
 #include <TObjString.h>
 #include <TObjArray.h>
 #include <TVectorD.h>
+#include <TF1.h>
+#include <TRandom.h>
+#include <TProfile.h>
 
 #include <AliVEvent.h>
 #include <AliVParticle.h>
@@ -42,6 +45,7 @@
 #include <AliMultiplicity.h>
 #include <AliStack.h>
 
+#include "AliDielectronVarManager.h"
 #include "AliDielectronHelper.h"
 
 //_____________________________________________________________________________
@@ -153,7 +157,7 @@ Int_t AliDielectronHelper::GetNch(const AliMCEvent *ev, Double_t etaRange){
 
 
 //_____________________________________________________________________________
-Int_t AliDielectronHelper::GetNaccTrcklts(const AliVEvent *ev){
+Int_t AliDielectronHelper::GetNaccTrcklts(const AliVEvent *ev, Double_t etaRange){
   // Compute the collision multiplicity based on AOD or ESD tracklets
   // Code taken from: AliAnalysisTaskMuonCollisionMultiplicity::ComputeMultiplicity()
 
@@ -161,7 +165,6 @@ Int_t AliDielectronHelper::GetNaccTrcklts(const AliVEvent *ev){
 
   Int_t nTracklets = 0;
   Int_t nAcc = 0;
-  Double_t etaRange = 1.6;
   
   if (ev->IsA() == AliAODEvent::Class()) {
     AliAODTracklets *tracklets = ((AliAODEvent*)ev)->GetTracklets();
@@ -183,6 +186,49 @@ Int_t AliDielectronHelper::GetNaccTrcklts(const AliVEvent *ev){
 }
 
 
+
+//________________________________________________________________
+Double_t AliDielectronHelper::GetNaccTrckltsCorrected(const AliVEvent *event, Double_t uncorrectedNacc, Double_t vtxZ, Int_t type) {
+  //
+  // Correct the number of accepted tracklets based on the period and event vertex
+  //
+
+  Int_t runNo = event->GetRunNumber();
+
+  Int_t period = -1;   // 0-LHC10b, 1-LHC10c, 2-LHC10d, 3-LHC10e
+  Double_t refMult = 0.0;   // reference multiplicity
+  
+  if(runNo>114930 && runNo<117223) period = 0;
+  if(runNo>119158 && runNo<120830) period = 1;
+  if(runNo>122373 && runNo<126438) period = 2;
+  if(runNo>127711 && runNo<130841) period = 3;
+  if(period<0 || period>3) return uncorrectedNacc;
+
+  if(type<0 || type>8) return uncorrectedNacc;
+  if(type == 0) refMult = 5.0;         // SPD tracklets in |eta|<0.5 
+  if(type == 1) refMult = 9.5;         // SPD tracklets in |eta|<1.0
+  if(type == 2) refMult = 13.0;        // SPD tracklets in |eta|<1.6
+  if(type == 3) refMult = 6.0;         // ITSTPC+ in |eta|<0.5
+  if(type == 4) refMult = 12.0;        // ITSTPC+ in |eta|<1.0
+  if(type == 5) refMult = 16.0;        // ITSTPC+ in |eta|<1.6
+  if(type == 6) refMult = 6.0;         // ITSSA+ in |eta|<0.5
+  if(type == 7) refMult = 12.0;        // ITSSA+ in |eta|<1.0
+  if(type == 8) refMult = 15.0;        // ITSSA+ in |eta|<1.6
+
+  if(TMath::Abs(vtxZ)>10.0) return uncorrectedNacc;
+
+  TProfile* estimatorAvg = AliDielectronVarManager::GetEstimatorHistogram(period, type);
+  if(!estimatorAvg) return uncorrectedNacc;
+
+  Double_t localAvg = estimatorAvg->GetBinContent(estimatorAvg->FindBin(vtxZ));
+
+  Double_t deltaM = uncorrectedNacc*(refMult/localAvg - 1);
+
+  Double_t correctedNacc = uncorrectedNacc + (deltaM>0 ? 1 : -1) * gRandom->Poisson(TMath::Abs(deltaM));
+
+  return correctedNacc;
+}
+
 //_____________________________________________________________________________
 Int_t AliDielectronHelper::GetNacc(const AliVEvent */*ev*/){
   // put a robust Nacc definition here
@@ -292,3 +338,50 @@ void AliDielectronHelper::RotateKFParticle(AliKFParticle * kfParticle,Double_t a
   
 }
 
+//_____________________________________________________________________________
+Int_t AliDielectronHelper::GetNMothers(const AliMCEvent *ev, Double_t etaRange, Int_t pdgMother, Int_t pdgDaughter, Int_t prim){
+  // counting number of mother particles generated in given eta range and 2 particle decay
+  if (!ev || ev->IsA()!=AliMCEvent::Class()) return -1;
+  
+  AliStack *stack = ((AliMCEvent*)ev)->Stack();
+  
+  if (!stack) return -1;
+  
+  Int_t nParticles = stack->GetNtrack();
+  Int_t nMothers   = 0;
+  
+  // count..
+  for (Int_t iMc = 0; iMc < nParticles; ++iMc) {
+    
+    TParticle* particle = stack->Particle(iMc);
+    if (!particle) continue;
+    if (particle->GetPdgCode() != pdgMother)               continue;
+    if (TMath::Abs(particle->Eta()) > TMath::Abs(etaRange)) continue;
+
+    if (particle->GetNDaughters() != 2)                 continue;
+    // 1st daugther
+    if (particle->GetFirstDaughter()>=nParticles ||
+       particle->GetFirstDaughter()<0             ) continue;
+    
+    TParticle* dau1 = stack->Particle(particle->GetFirstDaughter());
+    if (TMath::Abs(dau1->GetPdgCode()) != pdgDaughter)     continue;
+    if (TMath::Abs(dau1->Eta()) > TMath::Abs(etaRange)) continue;
+    
+    // 2nd daughter
+    if (particle->GetLastDaughter()>=nParticles ||
+       particle->GetLastDaughter()<0             ) continue;
+
+    TParticle* dau2 = stack->Particle(particle->GetLastDaughter());
+    if (TMath::Abs(dau2->GetPdgCode()) != pdgDaughter)     continue;
+    if (TMath::Abs(dau2->Eta()) > TMath::Abs(etaRange)) continue;
+    
+    // primary
+    if (prim != -1) {
+      if(particle->IsPrimary() != prim) continue;
+    }
+    nMothers++;
+  }
+  return nMothers;
+}
+
+
index 7cc7a97..3d4ce44 100644 (file)
@@ -31,9 +31,11 @@ TVectorD* MakeArbitraryBinning(const char* bins);
 
 Int_t GetNch(const AliMCEvent *ev=0x0, Double_t eta=0.9);
 Int_t GetNacc(const AliVEvent *ev=0x0);
-Int_t GetNaccTrcklts(const AliVEvent *ev=0x0);
+Int_t GetNaccTrcklts(const AliVEvent *ev=0x0, Double_t etaRange=1.6);
+Double_t GetNaccTrckltsCorrected(const AliVEvent *event, Double_t uncorrectedNacc, Double_t vtxZ, Int_t type); 
 
 void RotateKFParticle(AliKFParticle * kfParticle,Double_t angle, const AliVEvent * const ev=0x0);
+Int_t GetNMothers(const AliMCEvent *ev=0x0, Double_t etaRange=0.9, Int_t pdgMother=-999, Int_t pdgDaughter=-999, Int_t prim=-1);
 
 
 }
index 24e4b34..4d18eb5 100644 (file)
 //
 // Authors: 
 //   Jens Wiechula <Jens.Wiechula@cern.ch> 
+//   Julian Book   <Julian.Book@cern.ch> 
 // 
 
 #include <TH1.h>
 #include <TH1F.h>
 #include <TH2.h>
 #include <TH3.h>
+#include <TProfile.h>
+#include <TProfile2D.h>
+#include <TProfile3D.h>
 #include <TCollection.h>
 #include <THashList.h>
 #include <TString.h>
@@ -89,9 +93,10 @@ AliDielectronHistos::~AliDielectronHistos()
 }
 
 //_____________________________________________________________________________
-void AliDielectronHistos::UserHistogram(const char* histClass,const char *name, const char* title,
-                                        Int_t nbinsX, Double_t xmin, Double_t xmax,
-                                        UInt_t valTypeX, Bool_t logBinX)
+void AliDielectronHistos::UserProfile(const char* histClass,const char *name, const char* title,
+                                     UInt_t valTypeP,
+                                     Int_t nbinsX, Double_t xmin, Double_t xmax,
+                                     UInt_t valTypeX, Bool_t logBinX)
 {
   //
   // Default histogram creation 1D case
@@ -104,16 +109,16 @@ void AliDielectronHistos::UserHistogram(const char* histClass,const char *name,
   } else {
     binLimX=AliDielectronHelper::MakeLinBinning(nbinsX, xmin, xmax);
   }
-
-  UserHistogram(histClass,name,title,binLimX,valTypeX);
+  UserProfile(histClass,name,title,valTypeP,binLimX,valTypeX);
 }
 
 //_____________________________________________________________________________
-void AliDielectronHistos::UserHistogram(const char* histClass,const char *name, const char* title,
-                                        Int_t nbinsX, Double_t xmin, Double_t xmax,
-                                        Int_t nbinsY, Double_t ymin, Double_t ymax,
-                                        UInt_t valTypeX, UInt_t valTypeY,
-                                        Bool_t logBinX, Bool_t logBinY)
+void AliDielectronHistos::UserProfile(const char* histClass,const char *name, const char* title,
+                                     UInt_t valTypeP,
+                                     Int_t nbinsX, Double_t xmin, Double_t xmax,
+                                     Int_t nbinsY, Double_t ymin, Double_t ymax,
+                                     UInt_t valTypeX, UInt_t valTypeY,
+                                     Bool_t logBinX, Bool_t logBinY)
 {
   //
   // Default histogram creation 2D case
@@ -133,18 +138,18 @@ void AliDielectronHistos::UserHistogram(const char* histClass,const char *name,
   } else {
     binLimY=AliDielectronHelper::MakeLinBinning(nbinsY, ymin, ymax);
   }
-  
-  UserHistogram(histClass,name,title,binLimX,binLimY,valTypeX,valTypeY);
+  UserProfile(histClass,name,title,valTypeP,binLimX,binLimY,valTypeX,valTypeY);
 }
 
 
 //_____________________________________________________________________________
-void AliDielectronHistos::UserHistogram(const char* histClass,const char *name, const char* title,
-                                        Int_t nbinsX, Double_t xmin, Double_t xmax,
-                                        Int_t nbinsY, Double_t ymin, Double_t ymax,
-                                        Int_t nbinsZ, Double_t zmin, Double_t zmax,
-                                        UInt_t valTypeX, UInt_t valTypeY, UInt_t valTypeZ,
-                                        Bool_t logBinX, Bool_t logBinY, Bool_t logBinZ)
+void AliDielectronHistos::UserProfile(const char* histClass,const char *name, const char* title,
+                                     UInt_t valTypeP,
+                                     Int_t nbinsX, Double_t xmin, Double_t xmax,
+                                     Int_t nbinsY, Double_t ymin, Double_t ymax,
+                                     Int_t nbinsZ, Double_t zmin, Double_t zmax,
+                                     UInt_t valTypeX, UInt_t valTypeY, UInt_t valTypeZ,
+                                     Bool_t logBinX, Bool_t logBinY, Bool_t logBinZ)
 {
   //
   // Default histogram creation 3D case
@@ -173,26 +178,28 @@ void AliDielectronHistos::UserHistogram(const char* histClass,const char *name,
     binLimZ=AliDielectronHelper::MakeLinBinning(nbinsZ, zmin, zmax);
   }
 
-  UserHistogram(histClass,name,title,binLimX,binLimY,binLimZ,valTypeX,valTypeY,valTypeZ);
+  UserProfile(histClass,name,title,valTypeP,binLimX,binLimY,binLimZ,valTypeX,valTypeY,valTypeZ);
 }
 
 //_____________________________________________________________________________
-void AliDielectronHistos::UserHistogram(const char* histClass,const char *name, const char* title,
-                                        const char* binning,
-                                        UInt_t valTypeX)
+void AliDielectronHistos::UserProfile(const char* histClass,const char *name, const char* title,
+                                     UInt_t valTypeP,
+                                     const char* binning,
+                                     UInt_t valTypeX)
 {
   //
   // Histogram creation 1D case with arbitraty binning
   //
 
   TVectorD *binLimX=AliDielectronHelper::MakeArbitraryBinning(binning);
-  UserHistogram(histClass,name,title,binLimX,valTypeX);
+  UserProfile(histClass,name,title,valTypeP,binLimX,valTypeX);
 }
 
 //_____________________________________________________________________________
-void AliDielectronHistos::UserHistogram(const char* histClass,const char *name, const char* title,
-                                        const TVectorD * const binsX,
-                                        UInt_t valTypeX/*=kNoAutoFill*/)
+void AliDielectronHistos::UserProfile(const char* histClass,const char *name, const char* title,
+                                     UInt_t valTypeP,
+                                     const TVectorD * const binsX,
+                                     UInt_t valTypeX/*=kNoAutoFill*/)
 {
   //
   // Histogram creation 1D case with arbitraty binning X
@@ -202,27 +209,38 @@ void AliDielectronHistos::UserHistogram(const char* histClass,const char *name,
   Bool_t isOk=kTRUE;
   isOk&=IsHistogramOk(histClass,name);
   isOk&=(binsX!=0x0);
-
-  if (isOk){
-    TH1* hist=new TH1F(name,title,binsX->GetNrows()-1,binsX->GetMatrixArray());
+  TH1 *hist=0x0;
   
+  if (isOk){
+    if(valTypeP==999)
+      hist=new TH1F(name,title,binsX->GetNrows()-1,binsX->GetMatrixArray());
+    else {
+      hist=new TProfile(name,title,binsX->GetNrows()-1,binsX->GetMatrixArray());
+    }
+
+    // store var for profile in fBits
+    StoreVarForProfile(hist,valTypeP);
+
     Bool_t isReserved=fReservedWords->Contains(histClass);
+    UInt_t uniqueID = valTypeX;
+    if(valTypeP!=999) uniqueID |= 0x80000000; // set last bit to 1 (for profiles only)
     if (isReserved)
-      UserHistogramReservedWords(histClass, hist, valTypeX);
+      UserHistogramReservedWords(histClass, hist, uniqueID);
     else
-      UserHistogram(histClass, hist, valTypeX);
+      UserHistogram(histClass, hist, uniqueID);
   }
   
   delete binsX;
 }
 
 //_____________________________________________________________________________
-void AliDielectronHistos::UserHistogram(const char* histClass,const char *name, const char* title,
-                                        const TVectorD * const binsX, const TVectorD * const binsY,
-                                        UInt_t valTypeX/*=kNoAutoFill*/, UInt_t valTypeY/*=0*/)
+void AliDielectronHistos::UserProfile(const char* histClass,const char *name, const char* title,
+                                     UInt_t valTypeP,
+                                     const TVectorD * const binsX, const TVectorD * const binsY,
+                                     UInt_t valTypeX/*=kNoAutoFill*/, UInt_t valTypeY/*=0*/)
 {
   //
-  // Histogram creation 1D case with arbitraty binning X
+  // Histogram creation 2D case with arbitraty binning X
   // the TVectorD is assumed to be surplus after the creation and will be deleted!!!
   //
 
@@ -230,17 +248,31 @@ void AliDielectronHistos::UserHistogram(const char* histClass,const char *name,
   isOk&=IsHistogramOk(histClass,name);
   isOk&=(binsX!=0x0);
   isOk&=(binsY!=0x0);
+  TH1 *hist=0x0;
 
   if (isOk){
-    TH1* hist=new TH2F(name,title,
-                       binsX->GetNrows()-1,binsX->GetMatrixArray(),
-                       binsY->GetNrows()-1,binsY->GetMatrixArray());
-  
+    if(valTypeP==999) {
+      hist=new TH2F(name,title,
+                    binsX->GetNrows()-1,binsX->GetMatrixArray(),
+                    binsY->GetNrows()-1,binsY->GetMatrixArray()); 
+    }
+    else 
+      hist=new TProfile2D(name,title,
+                          binsX->GetNrows()-1,binsX->GetMatrixArray(),
+                          binsY->GetNrows()-1,binsY->GetMatrixArray());
+    
+    // store var for profile in fBits
+    StoreVarForProfile(hist,valTypeP);
+
     Bool_t isReserved=fReservedWords->Contains(histClass);
+    // switched from 2 digits encoding to 3 digits
+    UInt_t uniqueID = valTypeX+1000*valTypeY;
+    if(valTypeP!=999) uniqueID |= 0x80000000; // set last bit to 1 (for profiles only)
+
     if (isReserved)
-      UserHistogramReservedWords(histClass, hist, valTypeX+100*valTypeY);
+      UserHistogramReservedWords(histClass, hist, uniqueID);
     else
-      UserHistogram(histClass, hist, valTypeX+100*valTypeY);
+      UserHistogram(histClass, hist, uniqueID);
   }
   
   delete binsX;
@@ -249,12 +281,13 @@ void AliDielectronHistos::UserHistogram(const char* histClass,const char *name,
 }
 
 //_____________________________________________________________________________
-void AliDielectronHistos::UserHistogram(const char* histClass,const char *name, const char* title,
-                                        const TVectorD * const binsX, const TVectorD * const binsY, const TVectorD * const binsZ,
-                                        UInt_t valTypeX/*=kNoAutoFill*/, UInt_t valTypeY/*=0*/, UInt_t valTypeZ/*=0*/)
+void AliDielectronHistos::UserProfile(const char* histClass,const char *name, const char* title,
+                                     UInt_t valTypeP,
+                                     const TVectorD * const binsX, const TVectorD * const binsY, const TVectorD * const binsZ,
+                                     UInt_t valTypeX/*=kNoAutoFill*/, UInt_t valTypeY/*=0*/, UInt_t valTypeZ/*=0*/)
 {
   //
-  // Histogram creation 1D case with arbitraty binning X
+  // Histogram creation 3D case with arbitraty binning X
   // the TVectorD is assumed to be surplus after the creation and will be deleted!!!
   //
 
@@ -263,18 +296,32 @@ void AliDielectronHistos::UserHistogram(const char* histClass,const char *name,
   isOk&=(binsX!=0x0);
   isOk&=(binsY!=0x0);
   isOk&=(binsZ!=0x0);
+  TH1 *hist=0x0;
   
   if (isOk){
-    TH1* hist=new TH3F(name,title,
-                       binsX->GetNrows()-1,binsX->GetMatrixArray(),
-                       binsY->GetNrows()-1,binsY->GetMatrixArray(),
-                       binsZ->GetNrows()-1,binsZ->GetMatrixArray());
-  
+    if(valTypeP==999)
+      hist=new TH3F(name,title,
+                   binsX->GetNrows()-1,binsX->GetMatrixArray(),
+                   binsY->GetNrows()-1,binsY->GetMatrixArray(),
+                   binsZ->GetNrows()-1,binsZ->GetMatrixArray());
+    else
+      hist=new TProfile3D(name,title,
+                         binsX->GetNrows()-1,binsX->GetMatrixArray(),
+                         binsY->GetNrows()-1,binsY->GetMatrixArray(),
+                         binsZ->GetNrows()-1,binsZ->GetMatrixArray());
+    
+    // store var for profile in fBits
+    StoreVarForProfile(hist,valTypeP);
+    
     Bool_t isReserved=fReservedWords->Contains(histClass);
+    // switched from 2 digits encoding to 3 digits
+    UInt_t uniqueID = valTypeX+1000*valTypeY+1000000*valTypeZ;
+    if(valTypeP!=999) uniqueID |= 0x80000000; // set last bit to 1 (for profiles only)
+
     if (isReserved)
-      UserHistogramReservedWords(histClass, hist, valTypeX+100*valTypeY+10000*valTypeZ);
+      UserHistogramReservedWords(histClass, hist, uniqueID);
     else
-      UserHistogram(histClass, hist, valTypeX+100*valTypeY+10000*valTypeZ);
+      UserHistogram(histClass, hist, uniqueID);
   }
   
   delete binsX;
@@ -301,6 +348,7 @@ void AliDielectronHistos::UserHistogram(const char* histClass, TH1* hist, UInt_t
   THashList *classTable=(THashList*)fHistoList.FindObject(histClass);
   hist->SetDirectory(0);
   hist->SetUniqueID(valTypes);
+
   classTable->Add(hist);
 }
 
@@ -382,7 +430,7 @@ void AliDielectronHistos::FillClass(const char* histClass, Int_t nValues, const
 {
   //
   // Fill class 'histClass' (by name)
-  //
+  //  
   
   THashList *classTable=(THashList*)fHistoList.FindObject(histClass);
   if (!classTable){
@@ -393,24 +441,30 @@ void AliDielectronHistos::FillClass(const char* histClass, Int_t nValues, const
   TIter nextHist(classTable);
   TH1 *hist=0;
   while ( (hist=(TH1*)nextHist()) ){
-    UInt_t valueTypes=hist->GetUniqueID();
+    UInt_t value4=hist->TestBits(0x00ffffff)>>14;     // get profile var stored in fBits
+    UInt_t valueTypes=hist->GetUniqueID()&0x7fffffff; // ignore "boolean" bit for profiles
+    
     if (valueTypes==(UInt_t)kNoAutoFill) continue;
-    UInt_t value1=valueTypes%100;        //last two digits
-    UInt_t value2=valueTypes/100%100;    //second last two digits
-    UInt_t value3=valueTypes/10000%100;  //third last two digits
-    if (value1>=(UInt_t)nValues||value2>=(UInt_t)nValues||value3>=(UInt_t)nValues) {
-      Warning("FillClass","One of the values is out of range. Not filling histogram '%s/%s'.", histClass, hist->GetName());
+    UInt_t value1=valueTypes%1000;          //last three digits
+    UInt_t value2=valueTypes/1000%1000;     //second last three digits
+    UInt_t value3=valueTypes/1000000%1000;  //third last three digits
+    
+    if (value1>=(UInt_t)nValues||value2>=(UInt_t)nValues||value3>=(UInt_t)nValues||(value4>=(UInt_t)nValues && value4!=999)) {
+      Warning("FillClass","One of the values is out of range. Not filling Histogram '%s/%s'.", histClass, hist->GetName());
       continue;
     }
     switch (hist->GetDimension()){
     case 1:
-      hist->Fill(values[value1]);
+      if(value4==999) hist->Fill(values[value1]);                    // histograms
+      else ((TProfile*)hist)->Fill(values[value1],values[value4]);   // profiles
       break;
     case 2:
-      ((TH2*)hist)->Fill(values[value1],values[value2]);
+      if(value4==999) ((TH2*)hist)->Fill(values[value1],values[value2]);
+      else ((TProfile2D*)hist)->Fill(values[value1],values[value2],values[value4]);
       break;
     case 3:
-      ((TH3*)hist)->Fill(values[value1],values[value2],values[value3]);
+      if(value4==999) ((TH3*)hist)->Fill(values[value1],values[value2],values[value3]);
+      else ((TProfile3D*)hist)->Fill(values[value1],values[value2],values[value3],values[value4]);
       break;
     }
   }
@@ -441,6 +495,7 @@ void AliDielectronHistos::UserHistogramReservedWords(const char* histClass, cons
       TH1 *h=static_cast<TH1*>(hist->Clone());
       h->SetDirectory(0);
       h->SetTitle(Form("%s %s",title.Data(),l->GetName()));
+
       UserHistogram(l->GetName(),h,valTypes);
     }
   }
@@ -781,3 +836,21 @@ void AliDielectronHistos::SetReservedWords(const char* words)
   
   (*fReservedWords)=words;
 }
+
+//_____________________________________________________________________________
+void AliDielectronHistos::StoreVarForProfile(TObject *obj, UInt_t valType)
+{
+  //
+  // store var for TProfiles in TObject::fBits [14-23]
+  //
+  
+  for(UInt_t i=14; i < sizeof(UInt_t)*8; i++) {
+    if(TESTBIT(valType,i-14)) {
+      obj->SetBit(1<<i,kTRUE);
+    }
+  }
+
+  return;
+}
+
+
index 977e295..0d3fbd6 100644 (file)
@@ -13,6 +13,7 @@
 //                                                                                       //
 ///////////////////////////////////////////////////////////////////////////////////////////
 
+#include <Rtypes.h>
 
 #include <TNamed.h>
 // #include <TCollection.h>
@@ -26,43 +27,85 @@ class TList;
 
 class AliDielectronHistos : public TNamed {
 public:
+
   AliDielectronHistos();
   AliDielectronHistos(const char* name, const char* title);
   virtual ~AliDielectronHistos();
 
   
+  void UserProfile(const char* histClass,const char *name, const char* title,
+                  UInt_t valTypeP,
+                  Int_t nbinsX, Double_t xmin, Double_t xmax,
+                  UInt_t valTypeX=kNoAutoFill, Bool_t logBinX=kFALSE);
+
+  void UserProfile(const char* histClass,const char *name, const char* title,
+                  UInt_t valTypeP,
+                  Int_t nbinsX, Double_t xmin, Double_t xmax,
+                  Int_t nbinsY, Double_t ymin, Double_t ymax,
+                  UInt_t valTypeX=kNoAutoFill, UInt_t valTypeY=0,
+                  Bool_t logBinX=kFALSE, Bool_t logBinY=kFALSE);
+  
+  void UserProfile(const char* histClass,const char *name, const char* title,
+                  UInt_t valTypeP,
+                  Int_t nbinsX, Double_t xmin, Double_t xmax,
+                  Int_t nbinsY, Double_t ymin, Double_t ymax,
+                  Int_t nbinsZ, Double_t zmin, Double_t zmax,
+                  UInt_t valTypeX=kNoAutoFill, UInt_t valTypeY=0, UInt_t valTypeZ=0,
+                  Bool_t logBinX=kFALSE, Bool_t logBinY=kFALSE, Bool_t logBinZ=kFALSE);
+  
+  void UserProfile(const char* histClass,const char *name, const char* title,
+                  UInt_t valTypeP,
+                  const char* binning, UInt_t valTypeX=kNoAutoFill);
+  
+  void UserProfile(const char* histClass,const char *name, const char* title,
+                  UInt_t valTypeP,
+                  const TVectorD * const binsX, UInt_t valTypeX=kNoAutoFill);
+  
+  void UserProfile(const char* histClass,const char *name, const char* title,
+                  UInt_t valTypeP,
+                  const TVectorD * const binsX, const TVectorD * const binsY,
+                  UInt_t valTypeX=kNoAutoFill, UInt_t valTypeY=0);
+  
+  void UserProfile(const char* histClass,const char *name, const char* title,
+                  UInt_t valTypeP,
+                  const TVectorD * const binsX, const TVectorD * const binsY, const TVectorD * const binsZ,
+                  UInt_t valTypeX=kNoAutoFill, UInt_t valTypeY=0, UInt_t valTypeZ=0);
+
+
   void UserHistogram(const char* histClass,const char *name, const char* title,
-                     Int_t nbinsX, Double_t xmin, Double_t xmax,
-                     UInt_t valTypeX=kNoAutoFill, Bool_t logBinX=kFALSE);
+                     Int_t nbinsX, Double_t xmin, Double_t xmax, UInt_t valTypeX=kNoAutoFill, Bool_t logBinX=kFALSE) 
+  { UserProfile(histClass,name,title,999,nbinsX,xmin,xmax,valTypeX,logBinX); }
+
   void UserHistogram(const char* histClass,const char *name, const char* title,
-                     Int_t nbinsX, Double_t xmin, Double_t xmax,
-                     Int_t nbinsY, Double_t ymin, Double_t ymax,
-                     UInt_t valTypeX=kNoAutoFill, UInt_t valTypeY=0,
-                     Bool_t logBinX=kFALSE, Bool_t logBinY=kFALSE);
+                     Int_t nbinsX, Double_t xmin, Double_t xmax, Int_t nbinsY, Double_t ymin, Double_t ymax,
+                     UInt_t valTypeX=kNoAutoFill, UInt_t valTypeY=0, Bool_t logBinX=kFALSE, Bool_t logBinY=kFALSE)    
+  { UserProfile(histClass,name,title,999,nbinsX,xmin,xmax,nbinsY,ymin,ymax,valTypeX,valTypeY,logBinX,logBinY); }
+
   void UserHistogram(const char* histClass,const char *name, const char* title,
-                     Int_t nbinsX, Double_t xmin, Double_t xmax,
-                     Int_t nbinsY, Double_t ymin, Double_t ymax,
-                     Int_t nbinsZ, Double_t zmin, Double_t zmax,
-                     UInt_t valTypeX=kNoAutoFill, UInt_t valTypeY=0, UInt_t valTypeZ=0,
-                     Bool_t logBinX=kFALSE, Bool_t logBinY=kFALSE, Bool_t logBinZ=kFALSE);
-  
+                     Int_t nbinsX, Double_t xmin, Double_t xmax, Int_t nbinsY, Double_t ymin, Double_t ymax,
+                     Int_t nbinsZ, Double_t zmin, Double_t zmax, UInt_t valTypeX=kNoAutoFill, UInt_t valTypeY=0, UInt_t valTypeZ=0,
+                     Bool_t logBinX=kFALSE, Bool_t logBinY=kFALSE, Bool_t logBinZ=kFALSE)
+  { UserProfile(histClass,name,title,999,nbinsX,xmin,xmax,nbinsY,ymin,ymax,nbinsZ,zmin,zmax,valTypeX,valTypeY,valTypeZ,logBinX,logBinY,logBinZ); }
+
   void UserHistogram(const char* histClass,const char *name, const char* title,
-                     const char* binning,
-                     UInt_t valTypeX=kNoAutoFill);
+                     const char* binning, UInt_t valTypeX=kNoAutoFill)
+  { UserProfile(histClass,name,title,999,binning,valTypeX); }
 
   void UserHistogram(const char* histClass,const char *name, const char* title,
-                     const TVectorD * const binsX,
-                     UInt_t valTypeX=kNoAutoFill);
+                     const TVectorD * const binsX, UInt_t valTypeX=kNoAutoFill)
+  { UserProfile(histClass,name,title,999,binsX,valTypeX); }
+
   void UserHistogram(const char* histClass,const char *name, const char* title,
-                     const TVectorD * const binsX, const TVectorD * const binsY,
-                     UInt_t valTypeX=kNoAutoFill, UInt_t valTypeY=0);
+                     const TVectorD * const binsX, const TVectorD * const binsY, UInt_t valTypeX=kNoAutoFill, UInt_t valTypeY=0)
+  { UserProfile(histClass,name,title,999,binsX,binsY,valTypeX,valTypeY); }
+
   void UserHistogram(const char* histClass,const char *name, const char* title,
                      const TVectorD * const binsX, const TVectorD * const binsY, const TVectorD * const binsZ,
-                     UInt_t valTypeX=kNoAutoFill, UInt_t valTypeY=0, UInt_t valTypeZ=0);
+                     UInt_t valTypeX=kNoAutoFill, UInt_t valTypeY=0, UInt_t valTypeZ=0)
+  { UserProfile(histClass,name,title,999,binsX,binsY,binsZ,valTypeX,valTypeY,valTypeZ); }
   
   void UserHistogram(const char* histClass, TH1* hist, UInt_t valTypes=kNoAutoFill);
 
-
   void Fill(const char* histClass, const char* name, Double_t xval);
   void Fill(const char* histClass, const char* name, Double_t xval, Double_t yval);
   void Fill(const char* histClass, const char* name, Double_t xval, Double_t yval, Double_t zval);
@@ -91,6 +134,7 @@ public:
   virtual void DrawSame(const char* histName, const Option_t *opt="leg can");
 
   void SetReservedWords(const char* words);
+  void StoreVarForProfile(TObject *obj, UInt_t valType);
 //   virtual void       Add(TObject *obj) {};
 //   virtual void       Clear(Option_t *option="") {};
 //   virtual void       Delete(Option_t *option="") {};
index 5029933..d90e54f 100644 (file)
@@ -38,6 +38,7 @@
 #include <AliLog.h>
 
 #include <TClonesArray.h>
+#include <TParticle.h>
 
 #include "AliDielectronSignalMC.h"
 #include "AliDielectronMC.h"
@@ -686,46 +687,47 @@ Int_t AliDielectronMC::GetPdgFromLabel(Int_t label) const {
 
 
 //________________________________________________________________________________
-Bool_t AliDielectronMC::ComparePDG(Int_t particlePDG, Int_t requiredPDG, Bool_t checkBothCharges) const {
+Bool_t AliDielectronMC::ComparePDG(Int_t particlePDG, Int_t requiredPDG, Bool_t pdgExclusion, Bool_t checkBothCharges) const {
   //
   //  Test the PDG codes of particles with the required ones
   //
   Bool_t result = kTRUE;
   Int_t absRequiredPDG = TMath::Abs(requiredPDG);
+
   switch(absRequiredPDG) {
   case 0:
     result = kTRUE;    // PDG not required (any code will do fine)
     break;
-  case 100:     // all light flavoured mesons
+  case 100:     // light flavoured mesons
     if(checkBothCharges)
-      result = TMath::Abs(particlePDG)>=100 && TMath::Abs(particlePDG)<=299;
+      result = TMath::Abs(particlePDG)>=100 && TMath::Abs(particlePDG)<=199;
     else {
-      if(requiredPDG>0) result = particlePDG>=100 && particlePDG<=299;
-      if(requiredPDG<0) result = particlePDG>=-299 && particlePDG<=-100;
+      if(requiredPDG>0) result = particlePDG>=100 && particlePDG<=199;
+      if(requiredPDG<0) result = particlePDG>=-199 && particlePDG<=-100;
     }
     break;
-  case 1000:     // all light flavoured baryons
+  case 1000:     // light flavoured baryons
     if(checkBothCharges)
-      result = TMath::Abs(particlePDG)>=1000 && TMath::Abs(particlePDG)<=2999;
+      result = TMath::Abs(particlePDG)>=1000 && TMath::Abs(particlePDG)<=1999;
     else {
-      if(requiredPDG>0) result = particlePDG>=1000 && particlePDG<=2999;
-      if(requiredPDG<0) result = particlePDG>=-2999 && particlePDG<=-1000;
+      if(requiredPDG>0) result = particlePDG>=1000 && particlePDG<=1999;
+      if(requiredPDG<0) result = particlePDG>=-1999 && particlePDG<=-1000;
     }
     break;
-  case 200:     // all light flavoured mesons  (as for the 100 case)
+  case 200:     // light flavoured mesons
     if(checkBothCharges)
-      result = TMath::Abs(particlePDG)>=100 && TMath::Abs(particlePDG)<=299;
+      result = TMath::Abs(particlePDG)>=200 && TMath::Abs(particlePDG)<=299;
     else {
-      if(requiredPDG>0)result = particlePDG>=100 && particlePDG<=299;
-      if(requiredPDG<0)result = particlePDG>=-299 && particlePDG<=-100;
+      if(requiredPDG>0)result = particlePDG>=200 && particlePDG<=299;
+      if(requiredPDG<0)result = particlePDG>=-299 && particlePDG<=-200;
     }
     break;
-  case 2000:     // all light flavoured baryons (as for the 1000 case)
+  case 2000:     // light flavoured baryons
     if(checkBothCharges)
-      result = TMath::Abs(particlePDG)>=1000 && TMath::Abs(particlePDG)<=2999;
+      result = TMath::Abs(particlePDG)>=2000 && TMath::Abs(particlePDG)<=2999;
     else {
-      if(requiredPDG>0) result = particlePDG>=1000 && particlePDG<=2999;
-      if(requiredPDG<0) result = particlePDG>=-2999 && particlePDG<=-1000;
+      if(requiredPDG>0) result = particlePDG>=2000 && particlePDG<=2999;
+      if(requiredPDG<0) result = particlePDG>=-2999 && particlePDG<=-2000;
     }
     break;
   case 300:     // all strange mesons
@@ -752,6 +754,36 @@ Bool_t AliDielectronMC::ComparePDG(Int_t particlePDG, Int_t requiredPDG, Bool_t
       if(requiredPDG<0) result = particlePDG>=-499 && particlePDG<=-400;
     }
     break;
+  case 401:     // open charm mesons
+    if(checkBothCharges)
+      result = TMath::Abs(particlePDG)>=400 && TMath::Abs(particlePDG)<=439;
+    else {
+      if(requiredPDG>0) result = particlePDG>=400 && particlePDG<=439;
+      if(requiredPDG<0) result = particlePDG>=-439 && particlePDG<=-400;
+    }
+    break;
+  case 402:     // open charm mesons and baryons together
+    if(checkBothCharges)
+      result = (TMath::Abs(particlePDG)>=400 && TMath::Abs(particlePDG)<=439) ||
+              (TMath::Abs(particlePDG)>=4000 && TMath::Abs(particlePDG)<=4399);
+    else {
+      if(requiredPDG>0) result = (particlePDG>=400 && particlePDG<=439) ||
+                                (particlePDG>=4000 && particlePDG<=4399);
+      if(requiredPDG<0) result = (particlePDG>=-439 && particlePDG<=-400) ||
+                                (particlePDG>=-4399 && particlePDG<=-4000);
+    }
+    break;
+  case 403:     // all charm hadrons
+    if(checkBothCharges)
+      result = (TMath::Abs(particlePDG)>=400 && TMath::Abs(particlePDG)<=499) ||
+              (TMath::Abs(particlePDG)>=4000 && TMath::Abs(particlePDG)<=4999);
+    else {
+      if(requiredPDG>0) result = (particlePDG>=400 && particlePDG<=499) ||
+                                (particlePDG>=4000 && particlePDG<=4999);
+      if(requiredPDG<0) result = (particlePDG>=-499 && particlePDG<=-400) ||
+                                (particlePDG>=-4999 && particlePDG<=-4000);
+    }
+    break;
   case 4000:     // all charmed baryons
     if(checkBothCharges)
       result = TMath::Abs(particlePDG)>=4000 && TMath::Abs(particlePDG)<=4999;
@@ -760,6 +792,14 @@ Bool_t AliDielectronMC::ComparePDG(Int_t particlePDG, Int_t requiredPDG, Bool_t
       if(requiredPDG<0) result = particlePDG>=-4999 && particlePDG<=-4000;
     }
     break;
+  case 4001:     // open charm baryons
+    if(checkBothCharges)
+      result = TMath::Abs(particlePDG)>=4000 && TMath::Abs(particlePDG)<=4399;
+    else {
+      if(requiredPDG>0) result = particlePDG>=4000 && particlePDG<=4399;
+      if(requiredPDG<0) result = particlePDG>=-4399 && particlePDG<=-4000;
+    }
+    break;
   case 500:      // all beauty mesons
     if(checkBothCharges)
       result = TMath::Abs(particlePDG)>=500 && TMath::Abs(particlePDG)<=599;
@@ -768,6 +808,36 @@ Bool_t AliDielectronMC::ComparePDG(Int_t particlePDG, Int_t requiredPDG, Bool_t
       if(requiredPDG<0) result = particlePDG>=-599 && particlePDG<=-500;
     }
     break;
+  case 501:      // open beauty mesons
+    if(checkBothCharges)
+      result = TMath::Abs(particlePDG)>=500 && TMath::Abs(particlePDG)<=549;
+    else {
+      if(requiredPDG>0) result = particlePDG>=500 && particlePDG<=549;
+      if(requiredPDG<0) result = particlePDG>=-549 && particlePDG<=-500;
+    }
+    break;
+  case 502:      // open beauty mesons and baryons
+    if(checkBothCharges)
+      result = (TMath::Abs(particlePDG)>=500 && TMath::Abs(particlePDG)<=549) ||
+              (TMath::Abs(particlePDG)>=5000 && TMath::Abs(particlePDG)<=5499);
+    else {
+      if(requiredPDG>0) result = (particlePDG>=500 && particlePDG<=549) ||
+                                (particlePDG>=5000 && particlePDG<=5499);
+      if(requiredPDG<0) result = (particlePDG>=-549 && particlePDG<=-500) ||
+                                 (particlePDG>=-5499 && particlePDG<=-5000);
+    }
+    break;
+  case 503:      // all beauty hadrons
+    if(checkBothCharges)
+      result = (TMath::Abs(particlePDG)>=500 && TMath::Abs(particlePDG)<=599) ||
+              (TMath::Abs(particlePDG)>=5000 && TMath::Abs(particlePDG)<=5999);
+    else {
+      if(requiredPDG>0) result = (particlePDG>=500 && particlePDG<=599) ||
+                                (particlePDG>=5000 && particlePDG<=5999);
+      if(requiredPDG<0) result = (particlePDG>=-599 && particlePDG<=-500) ||
+                                 (particlePDG>=-5999 && particlePDG<=-5000);
+    }
+    break;
   case 5000:      // all beauty baryons
     if(checkBothCharges)
       result = TMath::Abs(particlePDG)>=5000 && TMath::Abs(particlePDG)<=5999;
@@ -776,6 +846,14 @@ Bool_t AliDielectronMC::ComparePDG(Int_t particlePDG, Int_t requiredPDG, Bool_t
       if(requiredPDG<0) result = particlePDG>=-5999 && particlePDG<=-5000;
     }
     break;
+  case 5001:      // open beauty baryons
+    if(checkBothCharges)
+      result = TMath::Abs(particlePDG)>=5000 && TMath::Abs(particlePDG)<=5499;
+    else {
+      if(requiredPDG>0) result = particlePDG>=5000 && particlePDG<=5499;
+      if(requiredPDG<0) result = particlePDG>=-5499 && particlePDG<=-5000;
+    }
+    break;
   default:          // all specific cases
     if(checkBothCharges)
       result = (absRequiredPDG==TMath::Abs(particlePDG));
@@ -783,11 +861,37 @@ Bool_t AliDielectronMC::ComparePDG(Int_t particlePDG, Int_t requiredPDG, Bool_t
       result = (requiredPDG==particlePDG);
   }
 
+  if(absRequiredPDG!=0 && pdgExclusion) result = !result;
   return result;
 }
 
 
 //________________________________________________________________________________
+Bool_t AliDielectronMC::IsPhysicalPrimary(Int_t label) const {
+  //
+  // Check if the particle with label "label" is a physical primary according to the
+  // definition in AliStack::IsPhysicalPrimary(Int_t label)
+  // Convention for being physical primary:
+  // 1.) particles produced in the collision
+  // 2.) stable particles with respect to strong and electromagnetic interactions
+  // 3.) excludes initial state particles
+  // 4.) includes products of directly produced Sigma0 hyperon decay
+  // 5.) includes products of directly produced pi0 decays
+  // 6.) includes products of directly produced beauty hadron decays
+  //
+  if(label<0) return kFALSE;
+  if(fAnaType==kAOD) {
+    if(!fMcArray) return kFALSE;
+    return (static_cast<AliAODMCParticle*>(GetMCTrackFromMCEvent(label)))->IsPhysicalPrimary();
+  } else if(fAnaType==kESD) {
+    if (!fMCEvent) return kFALSE;
+    return fStack->IsPhysicalPrimary(label);
+  }
+  return kFALSE;
+}
+
+
+//________________________________________________________________________________
 Bool_t AliDielectronMC::CheckParticleSource(Int_t label, AliDielectronSignalMC::ESource source) const {
   //
   //  Check the source for the particle 
@@ -797,21 +901,37 @@ Bool_t AliDielectronMC::CheckParticleSource(Int_t label, AliDielectronSignalMC::
     case AliDielectronSignalMC::kDontCare :
       return kTRUE;
     break;
-    case AliDielectronSignalMC::kPrimary :
-      if(label>=0 && label<GetNPrimary()) return kTRUE;
-      else return kFALSE;
+    case AliDielectronSignalMC::kPrimary :            
+      // true if label is in the list of particles from physics generator 
+      // NOTE: This includes all physics event history (initial state particles,
+      //       exchange bosons, quarks, di-quarks, strings, un-stable particles, final state particles)
+      //       Only the final state particles make it to the detector!!
+      return (label>=0 && label<=GetNPrimary());      
     break;
-    case AliDielectronSignalMC::kSecondary :
-      if(label>=GetNPrimary()) return kTRUE;
-      else return kFALSE;
+    case AliDielectronSignalMC::kFinalState :         
+      // primary particles created in the collision which reach the detectors
+      // These would be:
+      // 1.) particles produced in the collision
+      // 2.) stable particles with respect to strong and electromagnetic interactions
+      // 3.) excludes initial state particles
+      // 4.) includes products of directly produced Sigma0 hyperon decay
+      // 5.) includes products of directly produced pi0 decays
+      // 6.) includes products of directly produced beauty hadron decays
+      return IsPhysicalPrimary(label);
     break;
     case AliDielectronSignalMC::kDirect :
-      if(label>=0 && GetMothersLabel(label)<0) return kTRUE;
-      else return kFALSE;
-    break;
-    case AliDielectronSignalMC::kDecayProduct :
-      if(label>=0 && GetMothersLabel(label)>=0) return kTRUE;
-      else return kFALSE;
+      // Primary particles which do not have any mother
+      // This is the case for:
+      // 1.) Initial state particles (the 2 protons in Pythia pp collisions)
+      // 2.) In some codes, with sudden freeze-out, all particles generated from the fireball are direct.
+      //     There is no history for these particles.
+      // 3.) Certain particles added via MC generator cocktails (e.g. J/psi added to pythia MB events)
+      return (label>=0 && GetMothersLabel(label)<0);
+      break;
+    case AliDielectronSignalMC::kSecondary :          
+      // particles which are created by the interaction of final state primaries with the detector
+      // or particles from strange weakly decaying particles (e.g. lambda, kaons, etc.)
+      return (label>=GetNPrimary() && !IsPhysicalPrimary(label));
     break;
     default :
       return kFALSE;
@@ -830,13 +950,15 @@ Bool_t AliDielectronMC::IsMCTruth(Int_t label, AliDielectronSignalMC* signalMC,
   //        between the ESD and the MC track. The negative labels indicate a poor matching quality
   //if(label<0) return kFALSE;
   if(label<0) label *= -1; 
+
   AliVParticle* part = GetMCTrackFromMCEvent(label);
   if (!part) {
     AliError(Form("Could not find MC particle with label %d",label));
     return kFALSE;
   }
+  
   // check the leg
-  if(!ComparePDG(part->PdgCode(),signalMC->GetLegPDG(branch),signalMC->GetCheckBothChargesLegs(branch))) return kFALSE;
+  if(!ComparePDG(part->PdgCode(),signalMC->GetLegPDG(branch),signalMC->GetLegPDGexclude(branch),signalMC->GetCheckBothChargesLegs(branch))) return kFALSE;
   if(!CheckParticleSource(label, signalMC->GetLegSource(branch))) return kFALSE;
 
   // check the mother
@@ -847,23 +969,23 @@ Bool_t AliDielectronMC::IsMCTruth(Int_t label, AliDielectronSignalMC* signalMC,
       mLabel = GetMothersLabel(label);
       mcMother = GetMCTrackFromMCEvent(mLabel);
     }
-    if(!mcMother) return kFALSE;
+    if(!mcMother && !signalMC->GetMotherPDGexclude(branch)) return kFALSE;
 
-    if(!ComparePDG(mcMother->PdgCode(),signalMC->GetMotherPDG(branch),signalMC->GetCheckBothChargesMothers(branch))) return kFALSE;
+    if(!ComparePDG((mcMother ? mcMother->PdgCode() : 0),signalMC->GetMotherPDG(branch),signalMC->GetMotherPDGexclude(branch),signalMC->GetCheckBothChargesMothers(branch))) return kFALSE;
     if(!CheckParticleSource(mLabel, signalMC->GetMotherSource(branch))) return kFALSE;
   }
-
+  
   // check the grandmother
+  AliVParticle* mcGrandMother=0x0;
   if(signalMC->GetGrandMotherPDG(branch)!=0 || signalMC->GetGrandMotherSource(branch)!=AliDielectronSignalMC::kDontCare) {
-    AliVParticle* mcGrandMother=0x0;
     Int_t gmLabel = -1;
     if(mcMother) {
       gmLabel = GetMothersLabel(mLabel);
       mcGrandMother = static_cast<AliMCParticle*>(GetMCTrackFromMCEvent(gmLabel));
     }
-    if(!mcGrandMother) return kFALSE;
+    if(!mcGrandMother && !signalMC->GetGrandMotherPDGexclude(branch)) return kFALSE;
     
-    if(!ComparePDG(mcGrandMother->PdgCode(),signalMC->GetGrandMotherPDG(branch),signalMC->GetCheckBothChargesGrandMothers(branch))) return kFALSE;
+    if(!ComparePDG((mcGrandMother ? mcGrandMother->PdgCode() : 0),signalMC->GetGrandMotherPDG(branch),signalMC->GetGrandMotherPDGexclude(branch),signalMC->GetCheckBothChargesGrandMothers(branch))) return kFALSE;
     if(!CheckParticleSource(gmLabel, signalMC->GetGrandMotherSource(branch))) return kFALSE;
   }
 
@@ -871,6 +993,7 @@ Bool_t AliDielectronMC::IsMCTruth(Int_t label, AliDielectronSignalMC* signalMC,
 }
 
 
+
 //________________________________________________________________________________
 Bool_t AliDielectronMC::IsMCTruth(const AliDielectronPair* pair, const AliDielectronSignalMC* signalMC) const {
   //
@@ -900,10 +1023,10 @@ Bool_t AliDielectronMC::IsMCTruth(const AliDielectronPair* pair, const AliDielec
   // make direct(1-1 and 2-2) and cross(1-2 and 2-1) comparisons for the whole branch
   Bool_t directTerm = kTRUE;
   // daughters
-  directTerm = directTerm && mcD1 && ComparePDG(d1Pdg,signalMC->GetLegPDG(1),signalMC->GetCheckBothChargesLegs(1)) 
+  directTerm = directTerm && mcD1 && ComparePDG(d1Pdg,signalMC->GetLegPDG(1),signalMC->GetLegPDGexclude(1),signalMC->GetCheckBothChargesLegs(1)) 
                && CheckParticleSource(labelD1, signalMC->GetLegSource(1));
     
-  directTerm = directTerm && mcD2 && ComparePDG(d2Pdg,signalMC->GetLegPDG(2),signalMC->GetCheckBothChargesLegs(2))
+  directTerm = directTerm && mcD2 && ComparePDG(d2Pdg,signalMC->GetLegPDG(2),signalMC->GetLegPDGexclude(2),signalMC->GetCheckBothChargesLegs(2))
                && CheckParticleSource(labelD2, signalMC->GetLegSource(2));
     
   // mothers
@@ -911,8 +1034,8 @@ Bool_t AliDielectronMC::IsMCTruth(const AliDielectronPair* pair, const AliDielec
   if(signalMC->GetMotherPDG(1)!=0 || signalMC->GetMotherSource(1)!=AliDielectronSignalMC::kDontCare) {
     labelM1 = GetMothersLabel(labelD1);
     if(labelD1>-1 && labelM1>-1) mcM1 = GetMCTrackFromMCEvent(labelM1);
-    directTerm = directTerm && mcM1 
-                 && ComparePDG(mcM1->PdgCode(),signalMC->GetMotherPDG(1),signalMC->GetCheckBothChargesMothers(1))
+    directTerm = directTerm && (mcM1 || signalMC->GetMotherPDGexclude(1)) 
+                 && ComparePDG((mcM1 ? mcM1->PdgCode() : 0),signalMC->GetMotherPDG(1),signalMC->GetMotherPDGexclude(1),signalMC->GetCheckBothChargesMothers(1))
                  && CheckParticleSource(labelM1, signalMC->GetMotherSource(1));
   }
   
@@ -920,8 +1043,8 @@ Bool_t AliDielectronMC::IsMCTruth(const AliDielectronPair* pair, const AliDielec
   if(signalMC->GetMotherPDG(2)!=0 || signalMC->GetMotherSource(2)!=AliDielectronSignalMC::kDontCare) {
     labelM2 = GetMothersLabel(labelD2);
     if(labelD2>-1 && labelM2>-1) mcM2 = GetMCTrackFromMCEvent(labelM2);
-    directTerm = directTerm && mcM2 
-                 && ComparePDG(mcM2->PdgCode(),signalMC->GetMotherPDG(2),signalMC->GetCheckBothChargesMothers(2))
+    directTerm = directTerm && (mcM2 || signalMC->GetMotherPDGexclude(2))
+                 && ComparePDG((mcM2 ? mcM2->PdgCode() : 0),signalMC->GetMotherPDG(2),signalMC->GetMotherPDGexclude(2),signalMC->GetCheckBothChargesMothers(2))
                  && CheckParticleSource(labelM2, signalMC->GetMotherSource(2));
   }
  
@@ -930,8 +1053,8 @@ Bool_t AliDielectronMC::IsMCTruth(const AliDielectronPair* pair, const AliDielec
   if(signalMC->GetGrandMotherPDG(1)!=0 || signalMC->GetGrandMotherSource(1)!=AliDielectronSignalMC::kDontCare) {
     labelG1 = GetMothersLabel(labelM1);
     if(mcM1 && labelG1>-1) mcG1 = GetMCTrackFromMCEvent(labelG1);
-    directTerm = directTerm && mcG1 
-                 && ComparePDG(mcG1->PdgCode(),signalMC->GetGrandMotherPDG(1),signalMC->GetCheckBothChargesGrandMothers(1))
+    directTerm = directTerm && (mcG1 || signalMC->GetGrandMotherPDGexclude(1))
+                 && ComparePDG((mcG1 ? mcG1->PdgCode() : 0),signalMC->GetGrandMotherPDG(1),signalMC->GetGrandMotherPDGexclude(1),signalMC->GetCheckBothChargesGrandMothers(1))
                  && CheckParticleSource(labelG1, signalMC->GetGrandMotherSource(1));
   }
 
@@ -939,8 +1062,8 @@ Bool_t AliDielectronMC::IsMCTruth(const AliDielectronPair* pair, const AliDielec
   if(signalMC->GetGrandMotherPDG(2)!=0 || signalMC->GetGrandMotherSource(2)!=AliDielectronSignalMC::kDontCare) {
     labelG2 = GetMothersLabel(labelM2);
     if(mcM2 && labelG2>-1) mcG2 = GetMCTrackFromMCEvent(labelG2);
-    directTerm = directTerm && mcG2 
-                 && ComparePDG(mcG2->PdgCode(),signalMC->GetGrandMotherPDG(2),signalMC->GetCheckBothChargesGrandMothers(2))
+    directTerm = directTerm && (mcG2 || signalMC->GetGrandMotherPDGexclude(2))
+                 && ComparePDG((mcG2 ? mcG2->PdgCode() : 0),signalMC->GetGrandMotherPDG(2),signalMC->GetGrandMotherPDGexclude(2),signalMC->GetCheckBothChargesGrandMothers(2))
                  && CheckParticleSource(labelG2, signalMC->GetGrandMotherSource(2));
   }
 
@@ -948,11 +1071,11 @@ Bool_t AliDielectronMC::IsMCTruth(const AliDielectronPair* pair, const AliDielec
   Bool_t crossTerm = kTRUE;
   // daughters
   crossTerm = crossTerm && mcD2 
-              && ComparePDG(d2Pdg,signalMC->GetLegPDG(1),signalMC->GetCheckBothChargesLegs(1))
+              && ComparePDG(d2Pdg,signalMC->GetLegPDG(1),signalMC->GetLegPDGexclude(1),signalMC->GetCheckBothChargesLegs(1))
               && CheckParticleSource(labelD2, signalMC->GetLegSource(1));
     
   crossTerm = crossTerm && mcD1 
-              && ComparePDG(d1Pdg,signalMC->GetLegPDG(2),signalMC->GetCheckBothChargesLegs(2))
+              && ComparePDG(d1Pdg,signalMC->GetLegPDG(2),signalMC->GetLegPDGexclude(2),signalMC->GetCheckBothChargesLegs(2))
               && CheckParticleSource(labelD1, signalMC->GetLegSource(2));
   
   // mothers  
@@ -961,8 +1084,8 @@ Bool_t AliDielectronMC::IsMCTruth(const AliDielectronPair* pair, const AliDielec
       labelM2 = GetMothersLabel(labelD2);
       if(labelM2>-1) mcM2 = GetMCTrackFromMCEvent(labelM2);
     }
-    crossTerm = crossTerm && mcM2 
-                && ComparePDG(mcM2->PdgCode(),signalMC->GetMotherPDG(1),signalMC->GetCheckBothChargesMothers(1))
+    crossTerm = crossTerm && (mcM2 || signalMC->GetMotherPDGexclude(1)) 
+                && ComparePDG((mcM2 ? mcM2->PdgCode() : 0),signalMC->GetMotherPDG(1),signalMC->GetMotherPDGexclude(1),signalMC->GetCheckBothChargesMothers(1))
                 && CheckParticleSource(labelM2, signalMC->GetMotherSource(1));
   }
   
@@ -971,8 +1094,8 @@ Bool_t AliDielectronMC::IsMCTruth(const AliDielectronPair* pair, const AliDielec
       labelM1 = GetMothersLabel(labelD1);
       if(labelM1>-1) mcM1 = GetMCTrackFromMCEvent(labelM1);  
     }
-    crossTerm = crossTerm && mcM1 
-                && ComparePDG(mcM1->PdgCode(),signalMC->GetMotherPDG(2),signalMC->GetCheckBothChargesMothers(2))
+    crossTerm = crossTerm && (mcM1 || signalMC->GetMotherPDGexclude(2)) 
+                && ComparePDG((mcM1 ? mcM1->PdgCode() : 0),signalMC->GetMotherPDG(2),signalMC->GetMotherPDGexclude(2),signalMC->GetCheckBothChargesMothers(2))
                 && CheckParticleSource(labelM1, signalMC->GetMotherSource(2));
   }
 
@@ -982,8 +1105,8 @@ Bool_t AliDielectronMC::IsMCTruth(const AliDielectronPair* pair, const AliDielec
       labelG2 = GetMothersLabel(labelM2);
       if(labelG2>-1) mcG2 = GetMCTrackFromMCEvent(labelG2);
     }
-    crossTerm = crossTerm && mcG2 
-                && ComparePDG(mcG2->PdgCode(),signalMC->GetGrandMotherPDG(1),signalMC->GetCheckBothChargesGrandMothers(1))
+    crossTerm = crossTerm && (mcG2 || signalMC->GetGrandMotherPDGexclude(1))
+                && ComparePDG((mcG2 ? mcG2->PdgCode() : 0),signalMC->GetGrandMotherPDG(1),signalMC->GetGrandMotherPDGexclude(1),signalMC->GetCheckBothChargesGrandMothers(1))
                 && CheckParticleSource(labelG2, signalMC->GetGrandMotherSource(1));
   }
 
@@ -992,8 +1115,8 @@ Bool_t AliDielectronMC::IsMCTruth(const AliDielectronPair* pair, const AliDielec
       labelG1 = GetMothersLabel(labelM1);
       if(labelG2>-1) mcG1 = GetMCTrackFromMCEvent(labelG1);
     }
-    crossTerm = crossTerm && mcG1 
-                && ComparePDG(mcG1->PdgCode(),signalMC->GetGrandMotherPDG(2),signalMC->GetCheckBothChargesGrandMothers(2))
+    crossTerm = crossTerm && (mcG1 || signalMC->GetGrandMotherPDGexclude(2))
+                && ComparePDG((mcG1 ? mcG1->PdgCode() : 0),signalMC->GetGrandMotherPDG(2),signalMC->GetGrandMotherPDGexclude(2),signalMC->GetCheckBothChargesGrandMothers(2))
                 && CheckParticleSource(labelG1, signalMC->GetGrandMotherSource(2));
   }
 
@@ -1019,6 +1142,7 @@ Bool_t AliDielectronMC::HaveSameMother(const AliDielectronPair * pair) const
 
   const AliVParticle * daughter1 = pair->GetFirstDaughter();
   const AliVParticle * daughter2 = pair->GetSecondDaughter();
+  if (!daughter1 || !daughter2) return 0;
 
   AliVParticle *mcDaughter1=GetMCTrackFromMCEvent(daughter1->GetLabel());
   AliVParticle *mcDaughter2=GetMCTrackFromMCEvent(daughter2->GetLabel());
index 4ce8060..e598716 100644 (file)
@@ -68,12 +68,14 @@ public:
   Int_t GetMothersLabel(Int_t daughterLabel) const;
   Int_t GetPdgFromLabel(Int_t label) const;
 
+  Bool_t IsPhysicalPrimary(Int_t label) const;  // checks if a particle is physical primary
+
   Bool_t HaveSameMother(const AliDielectronPair *pair) const;
   
   Int_t GetLabelMotherWithPdg(const AliDielectronPair* pair, Int_t pdgMother);
   Int_t GetLabelMotherWithPdg(const AliVParticle *particle1, const AliVParticle *particle2, Int_t pdgMother);
   
-  AliVParticle* GetMCTrackFromMCEvent(AliVParticle *track);   // return MC track directly from MC event
+//   AliVParticle* GetMCTrackFromMCEvent(const AliVParticle *track);   // return MC track directly from MC event
   AliVParticle* GetMCTrackFromMCEvent(Int_t itrk) const;           // return MC track directly from MC event
   TParticle* GetMCTrackFromStack(const AliESDtrack* _track);        // return MC track from stack
   AliMCParticle* GetMCTrack(const AliESDtrack* _track);             // return MC track associated with reco track
@@ -116,7 +118,7 @@ private:
   Int_t GetLabelMotherWithPdgESD(const AliVParticle *particle1, const AliVParticle *particle2, Int_t pdgMother);
   Int_t GetLabelMotherWithPdgAOD(const AliVParticle *particle1, const AliVParticle *particle2, Int_t pdgMother);
   
-  Bool_t ComparePDG(Int_t particlePDG, Int_t requiredPDG, Bool_t checkBothCharges) const;
+  Bool_t ComparePDG(Int_t particlePDG, Int_t requiredPDG, Bool_t pdgExclusion, Bool_t checkBothCharges) const;
   Bool_t CheckParticleSource(Int_t label, AliDielectronSignalMC::ESource source) const;
   ClassDef(AliDielectronMC, 0)
 };
diff --git a/PWGDQ/dielectron/AliDielectronMixingHandler.cxx b/PWGDQ/dielectron/AliDielectronMixingHandler.cxx
new file mode 100644 (file)
index 0000000..6b31f2a
--- /dev/null
@@ -0,0 +1,448 @@
+/*************************************************************************
+* Copyright(c) 1998-2009, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+///////////////////////////////////////////////////////////////////////////
+//                Dielectron MixingHandler                                  //
+//                                                                       //
+//                                                                       //
+/*
+Detailed description
+
+
+*/
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+#include <TVectorD.h>
+#include <TH1.h>
+#include <TAxis.h>
+
+#include <AliLog.h>
+#include <AliVTrack.h>
+
+#include "AliDielectron.h"
+#include "AliDielectronHelper.h"
+#include "AliDielectronHistos.h"
+#include "AliDielectronEvent.h"
+
+#include "AliDielectronMixingHandler.h"
+
+ClassImp(AliDielectronMixingHandler)
+
+AliDielectronMixingHandler::AliDielectronMixingHandler() :
+  TNamed(),
+  fDepth(10),
+  fArrPools("TClonesArray"),
+  fAxes(kMaxCuts),
+  fMixType(kOSonly),
+  fMixIncomplete(kTRUE),
+  fMoveToSameVertex(kFALSE)
+{
+  //
+  // Default Constructor
+  //
+  for (Int_t i=0; i<kMaxCuts; ++i){
+    fEventCuts[i]=0;
+  }
+  fAxes.SetOwner(kTRUE);
+}
+
+//______________________________________________
+AliDielectronMixingHandler::AliDielectronMixingHandler(const char* name, const char* title) :
+  TNamed(name, title),
+  fDepth(10),
+  fArrPools("TClonesArray"),
+  fAxes(kMaxCuts),
+  fMixType(kOSonly),
+  fMixIncomplete(kTRUE),
+  fMoveToSameVertex(kFALSE)
+{
+  //
+  // Named Constructor
+  //
+  for (Int_t i=0; i<kMaxCuts; ++i){
+    fEventCuts[i]=0;
+  }
+  fAxes.SetOwner(kTRUE);
+}
+
+//______________________________________________
+AliDielectronMixingHandler::~AliDielectronMixingHandler()
+{
+  //
+  // Default Destructor
+  //
+  fAxes.Delete();
+}
+
+//________________________________________________________________
+void AliDielectronMixingHandler::AddVariable(AliDielectronVarManager::ValueTypes type,
+                                             Int_t nbins, Double_t min, Double_t max, Bool_t log)
+{
+  //
+  // Add a variable to the mixing handler
+  //
+
+  // limit number of variables to kMaxCuts
+  if (fAxes.GetEntriesFast()>=kMaxCuts) return;
+  
+  TVectorD *binLimits=0x0;
+  if (!log) binLimits=AliDielectronHelper::MakeLinBinning(nbins,min,max);
+  else binLimits=AliDielectronHelper::MakeLogBinning(nbins,min,max);
+  if (!binLimits) return;
+
+  Int_t size=fAxes.GetEntriesFast();
+  fEventCuts[size]=(UShort_t)type;
+  fAxes.Add(binLimits);
+}
+
+//________________________________________________________________
+void AliDielectronMixingHandler::AddVariable(AliDielectronVarManager::ValueTypes type,
+                                             const char* binLimitStr)
+{
+  //
+  // Add a variable to the mixing handler with arbitrary binning
+  //
+
+  // limit number of variables to kMaxCuts
+  if (fAxes.GetEntriesFast()>=kMaxCuts) return;
+  
+  TVectorD *binLimits=AliDielectronHelper::MakeArbitraryBinning(binLimitStr);
+  if (!binLimits) return;
+  
+  Int_t size=fAxes.GetEntriesFast();
+  fEventCuts[size]=(UShort_t)type;
+  fAxes.Add(binLimits);
+}
+
+//______________________________________________
+void AliDielectronMixingHandler::Fill(const AliVEvent *ev, AliDielectron *diele)
+{
+  //
+  // fill event buffers and perform mixing if the pool depth is reached
+  //
+
+  //check if there are tracks available
+  if (diele->GetTrackArray(0)->GetEntriesFast()==0 && diele->GetTrackArray(1)->GetEntriesFast()==0) return;
+  
+  //find mixing bin
+  Double_t values[AliDielectronVarManager::kNMaxValues];
+  AliDielectronVarManager::Fill(ev,values);
+
+  TString dim;
+  Int_t bin=FindBin(values,&dim);
+
+  if (bin<0){
+    AliDebug(5,Form("Bin outside range: %s",dim.Data()));
+    return;
+  }
+
+  // get mixing pool, create it if it does not yet exist.
+  TClonesArray *poolp=static_cast<TClonesArray*>(fArrPools.At(bin));
+  if (!poolp){
+    AliDebug(10,Form("New pool at %d (%s)\n",bin,dim.Data()));
+    poolp=new(fArrPools[bin]) TClonesArray("AliDielectronEvent",fDepth);
+  }
+  TClonesArray &pool=*poolp;
+
+  AliDebug(10,Form("new event at %d: %d",bin,pool.GetEntriesFast()));
+  AliDielectronEvent *event=new(pool[pool.GetEntriesFast()]) AliDielectronEvent();
+
+  event->SetTracks(*diele->GetTrackArray(0), *diele->GetTrackArray(1), *diele->GetPairArray(1));
+  event->SetEventData(values);
+  
+  // check if pool depth is reached.
+  if (pool.GetEntriesFast()<fDepth) return;
+
+  // pool depth reached, do mixing
+  DoMixing(pool,diele);
+
+  // increase counter for full bins
+  if (diele->fHistos) {
+    diele->fHistos->Fill("Mixing","Stats",0);
+    diele->fHistos->Fill("Mixing","CompletePools",bin);
+  }
+  
+  //clear the current pool
+  pool.Clear("C");
+}
+
+//______________________________________________
+void AliDielectronMixingHandler::DoMixing(TClonesArray &pool, AliDielectron *diele)
+{
+  //
+  // perform the mixing
+  //
+  
+  //buffer track arrays and copy them back afterwards
+  TObjArray arrTrDummy[4];
+  for (Int_t i=0; i<4; ++i) arrTrDummy[i]=diele->fTracks[i];
+
+  //buffer also global event data
+  Double_t values[AliDielectronVarManager::kNMaxValues]={0};
+  for (Int_t i=AliDielectronVarManager::kPairMax; i<AliDielectronVarManager::kNMaxValues; ++i)
+    values[i]=AliDielectronVarManager::GetValue((AliDielectronVarManager::ValueTypes)i);
+
+  for (Int_t i1=0; i1<pool.GetEntriesFast(); ++i1){
+    AliDielectronEvent *ev1=static_cast<AliDielectronEvent*>(pool.At(i1));
+    //use event data from the first event
+    //both events are in the same mixing bin anyhow...
+    AliDielectronVarManager::SetEventData(ev1->GetEventData());
+
+    TObject *o=0x0;
+    TIter ev1P(ev1->GetTrackArrayP());
+    TIter ev1N(ev1->GetTrackArrayN());
+    
+    for (Int_t i2=i1+1; i2<pool.GetEntriesFast(); ++i2){
+      //clear arryas
+      diele->fTracks[0].Clear();
+      diele->fTracks[1].Clear();
+      diele->fTracks[2].Clear();
+      diele->fTracks[3].Clear();
+      
+      //setup track arrays
+      AliDielectronEvent *ev2=static_cast<AliDielectronEvent*>(pool.At(i2));
+
+      ev1P.Reset();
+      ev1N.Reset();
+      TIter ev2P(ev2->GetTrackArrayP());
+      TIter ev2N(ev2->GetTrackArrayN());
+
+      //
+      //move tracks to the same vertex (vertex of the first event), if requested
+      //
+      if (fMoveToSameVertex){
+        const Double_t *varsFirst=ev1->GetEventData();
+        const Double_t *varsMix=ev2->GetEventData();
+
+        const Double_t vFirst[3]={varsFirst[AliDielectronVarManager::kXvPrim],
+                                  varsFirst[AliDielectronVarManager::kYvPrim],
+                                  varsFirst[AliDielectronVarManager::kZvPrim]};
+
+        const Double_t vMix[3]  ={varsMix[AliDielectronVarManager::kXvPrim],
+                                  varsMix[AliDielectronVarManager::kYvPrim],
+                                  varsMix[AliDielectronVarManager::kZvPrim]};
+                                  
+        //loop over all tracks from the second event and move them to the vertex of the first
+        AliVTrack *vtrack=0x0;
+        while ( ( vtrack=(AliVTrack*)ev2P() ) ){
+          MoveToSameVertex(vtrack, vFirst, vMix);
+        }
+
+        
+        while ( ( vtrack=(AliVTrack*)ev2N() ) ){
+          MoveToSameVertex(vtrack, vFirst, vMix);
+        }
+
+        
+        ev2P.Reset();
+        ev2N.Reset();
+      }
+      
+      //mixing of ev1- ev2+ (pair type4). This is common for all mixing types
+      while ( (o=ev1N()) ) diele->fTracks[1].Add(o);
+      while ( (o=ev2P()) ) diele->fTracks[2].Add(o);
+      diele->FillPairArrays(1,2);
+      
+      if (fMixType==kAll || fMixType==kOSandLS){
+        // all 4 pair arrays will be filled
+        while ( (o=ev1P()) ) diele->fTracks[0].Add(o);
+        while ( (o=ev2N()) ) diele->fTracks[3].Add(o);
+        diele->FillPairArrays(0,2);
+        diele->FillPairArrays(1,3);
+        if (fMixType==kAll) diele->FillPairArrays(0,3);
+      }
+      
+      if (fMixType==kOSonly || fMixType==kOSandLS){
+        //use the pair type of ev1- ev1+ also for ev1+ ev1-
+        diele->fTracks[1].Clear();
+        diele->fTracks[2].Clear();
+        while ( (o=ev1P()) ) diele->fTracks[1].Add(o);
+        while ( (o=ev2N()) ) diele->fTracks[2].Add(o);
+        diele->FillPairArrays(1,2);
+      }
+    }
+  }
+
+  //copy back the tracks
+  for (Int_t i=0; i<4; ++i) {
+    diele->fTracks[i].Clear();
+    diele->fTracks[i]=arrTrDummy[i];
+  }
+
+  //set back global event values
+  AliDielectronVarManager::SetEventData(values);
+}
+
+//______________________________________________
+void AliDielectronMixingHandler::MixRemaining(AliDielectron *diele)
+{
+  //
+  // mix all pools even if they are incomplete
+  //
+
+  //Check if there was any processed data and it is requested to mix incomplete bins
+  if (!diele->PairArray(0) || !fMixIncomplete ) return;
+
+
+  for (Int_t ipool=0; ipool<fArrPools.GetSize(); ++ipool){
+    TClonesArray *poolp=static_cast<TClonesArray*>(fArrPools.At(ipool));
+    if (!poolp) continue;
+    //clear the arrays before the final processing"
+    AliDebug(10,Form("Incomplete: Bin %d (%d)\n",ipool,poolp->GetEntriesFast()));
+    diele->ClearArrays();
+    DoMixing(*poolp,diele);
+
+    diele->FillHistograms(0x0, kTRUE);
+
+    // increase counter for incomplete bins
+    if (diele->fHistos) {
+      diele->fHistos->Fill("Mixing","Stats",1);
+      diele->fHistos->Fill("Mixing","InCompletePools",ipool);
+      diele->fHistos->Fill("Mixing","Entries_InCompletePools",poolp->GetEntriesFast());
+    }
+    
+  }
+}
+
+
+//______________________________________________
+void AliDielectronMixingHandler::Init(const AliDielectron *diele)
+{
+  //
+  // initialise event buffers
+  //
+
+  Int_t size=1;
+  for (Int_t i=0; i<fAxes.GetEntriesFast(); ++i)
+    size*=((static_cast<TVectorD*>(fAxes.At(i)))->GetNrows()-1);
+
+  AliDebug(10,Form("Creating a pool array with size %d \n",size));
+
+  fArrPools.Expand(size);
+
+  //add statics histogram if we have a histogram manager
+  if (diele && diele->fHistos) {
+    diele->fHistos->AddClass("Mixing");
+    diele->fHistos->UserHistogram("Mixing","Stats","Mixing Statistics;;#called bins",2,0,2);
+    TH1* h=diele->fHistos->GetHistogram("Mixing","Stats");
+    h->GetXaxis()->SetBinLabel(1,"Complete");
+    h->GetXaxis()->SetBinLabel(2,"Incomplete");
+
+    diele->fHistos->UserHistogram("Mixing","CompletePools","Mixing Statistics compete pools;bin;#fills",size,0,size);
+    diele->fHistos->UserHistogram("Mixing","InCompletePools","Mixing Statistics incomplete pools;bin;#fills",size,0,size);
+    diele->fHistos->UserHistogram("Mixing","Entries_InCompletePools","#entries in incomplete pools;entries;#fills",fDepth,0,fDepth);
+  }
+
+  TString values;
+  for (Int_t i=0; i<fAxes.GetEntriesFast(); ++i){
+    TVectorD *bins=static_cast<TVectorD*>(fAxes.At(i));
+    Int_t nRows=bins->GetNrows();
+    values+=Form("%s: ",AliDielectronVarManager::GetValueName(fEventCuts[i]));
+    for (Int_t irow=0; irow<nRows; ++irow){
+      values+=Form("%.2f, ",(*bins)[irow]);
+    }
+  }
+
+  AliDebug(10,values.Data());
+}
+
+//______________________________________________
+Int_t AliDielectronMixingHandler::FindBin(const Double_t values[], TString *dim)
+{
+  //
+  // bin bin in mixing stack described by 'values'
+  // if the values are outside the binning range -1 is returned
+  // if dim is non NULL debug info will be stored in the variable
+  //
+
+  if (fAxes.GetEntriesFast()==0) {
+    if (dim) (*dim)="single bin";
+    return 0;
+  }
+  if (dim) (*dim)="";
+  Int_t sizeAdd=1;
+  Int_t bin=0;
+  for (Int_t i=0; i<fAxes.GetEntriesFast(); ++i){
+    Double_t val=values[fEventCuts[i]];
+    TVectorD *bins=static_cast<TVectorD*>(fAxes.At(i));
+    Int_t nRows=bins->GetNrows();
+    if ( (val<(*bins)[0]) || (val>(*bins)[nRows-1]) ) {
+      return -1;
+    }
+
+    Int_t pos=TMath::BinarySearch(nRows,bins->GetMatrixArray(),val);
+    bin+=sizeAdd*pos;
+    if (dim) (*dim)+=Form("%s: %f; ",AliDielectronVarManager::GetValueName(fEventCuts[i]),val);
+    sizeAdd*=nRows;
+  }
+
+  return bin;
+}
+
+//______________________________________________
+void AliDielectronMixingHandler::MoveToSameVertex(AliVTrack * const vtrack, const Double_t *vFirst, const Double_t* vMix)
+{
+  //
+  // move 'track' which belongs to the vertex information of vMix to the vertex of vFirst
+  //
+
+  static Bool_t printed=kFALSE;
+  
+  if (vtrack->IsA()==AliESDtrack::Class()){
+    AliESDtrack *track=(AliESDtrack*)vtrack;
+
+    //get track information
+    Double_t x        = track->GetX();
+    Double_t alpha    = track->GetAlpha();
+    Double_t param[5] = {0};
+    Double_t cov[15]  = {0};
+
+    for (Int_t i=0; i<5;  ++i) param[i]=track->GetParameter()[i];
+    for (Int_t i=0; i<15; ++i) cov[i]  =track->GetCovariance()[i];
+
+    //translation
+    Double_t vt[3] = {vMix[0]-vFirst[0],vMix[1]-vFirst[1],vMix[2]-vFirst[2]};
+    //rotate to the track frame
+    track->Global2LocalPosition(vt,track->GetAlpha());
+
+    //add to track position
+    x        = x       -vt[0];
+    param[0] = param[0]-vt[1];
+    param[1] = param[1]-vt[2];
+    
+    //set updated track information
+    track->Set(x, alpha, param, cov);
+  } else {
+    //             AliAODTrack *track=(AliAODTrack*)vtrack;
+    //             Double_t pos[3]={0};
+    //             track->GetPosition(pos);
+    //             if (pos[0]>-999.){
+      //               pos[0]=pos[0]-vMix[AliDielectronVarManager::kXvPrim]+vFirst[AliDielectronVarManager::kXvPrim];
+      //               pos[1]=pos[1]-vMix[AliDielectronVarManager::kYvPrim]+vFirst[AliDielectronVarManager::kYvPrim];
+      //               pos[2]=pos[2]-vMix[AliDielectronVarManager::kZvPrim]+vFirst[AliDielectronVarManager::kZvPrim];
+      //               track->SetPosition(pos);
+//       AliError("Move To same vertex not yet implemented for AOD!");
+    if (!printed) {
+//       Error("AliDielectronMixingHandler::MoveToSameVertex","Move To same vertex not yet implemented for AOD!");
+      printed=kTRUE;
+    }
+      //
+      // Not that clear how to do it. In AOD track there is fPosition, fPositionAtDCA and "TRef fProdVertex"
+      // where Xv(), Yv(), Zv() returns the position of fProdVertex
+      //
+    }
+    
+}
diff --git a/PWGDQ/dielectron/AliDielectronMixingHandler.h b/PWGDQ/dielectron/AliDielectronMixingHandler.h
new file mode 100644 (file)
index 0000000..bb6615b
--- /dev/null
@@ -0,0 +1,86 @@
+#ifndef ALIDIELECTRONMIXINGHANDLER_H
+#define ALIDIELECTRONMIXINGHANDLER_H
+
+/* Copyright(c) 1998-2009, ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice                               */
+
+//#############################################################
+//#                                                           # 
+//#         Class AliDielectronMixingHandler                  #
+//#                                                           #
+//#  Authors:                                                 #
+//#   Jens Wiechula, Uni-Tübingen / Jens.Wiechula@cern.ch     #
+//#                                                           #
+//#############################################################
+
+#include <TNamed.h>
+#include <TObjArray.h>
+#include <TClonesArray.h>
+
+#include "AliDielectronVarManager.h"
+
+class AliDielectron;
+class AliVTrack;
+class AliVEvent;
+
+class AliDielectronMixingHandler : public TNamed {
+public:
+  enum { kMaxCuts=10 };
+  enum EMixType {
+    kOSonly=0,
+    kOSandLS,
+    kAll
+  };
+  AliDielectronMixingHandler();
+  AliDielectronMixingHandler(const char*name, const char* title);
+
+  virtual ~AliDielectronMixingHandler();
+
+  void AddVariable(AliDielectronVarManager::ValueTypes type, Int_t nbins,
+                   Double_t min, Double_t max, Bool_t log=kFALSE);
+  void AddVariable(AliDielectronVarManager::ValueTypes type, const char* binLimitStr);
+
+  void SetDepth(UShort_t depth) { fDepth=depth; }
+  UShort_t GetDepth()     const { return fDepth; }
+
+  void SetMixType(EMixType type) { fMixType=type; }
+  EMixType GetMixType() const    { return fMixType; }
+
+  void SetMixUncomplete(Bool_t mix) { fMixIncomplete=mix; }
+  Bool_t GetMixUncomplete() const { return fMixIncomplete; }
+
+  void SetMoveToSameVertex(Bool_t move) { fMoveToSameVertex=move; }
+  Bool_t GetMoveToSameVertex() const { return fMoveToSameVertex; }
+
+  Int_t FindBin(const Double_t values[], TString *dim=0x0);
+  void Fill(const AliVEvent *ev, AliDielectron *diele);
+
+  void MixRemaining(AliDielectron *diele);
+
+  void Init(const AliDielectron *diele=0x0);
+  static void MoveToSameVertex(AliVTrack * const vtrack, const Double_t vFirst[3], const Double_t vMix[3]);
+
+private:
+  UShort_t     fDepth;     //Number of events per bin to start the merging
+  TClonesArray fArrPools; //Array of events in bins
+
+  UShort_t  fEventCuts[kMaxCuts]; //cut variables
+  TObjArray fAxes;        //Axis descriptions of the event binning
+
+  EMixType fMixType;      // which combinations to include in the mixing
+
+  Bool_t fMixIncomplete;  // whether to mix uncomplete bins at the end of the processing
+  Bool_t fMoveToSameVertex; //whether to move the mixed tracks to the same vertex position
+
+  void DoMixing(TClonesArray &pool, AliDielectron *diele);
+
+  AliDielectronMixingHandler(const AliDielectronMixingHandler &c);
+  AliDielectronMixingHandler &operator=(const AliDielectronMixingHandler &c);
+
+  
+  ClassDef(AliDielectronMixingHandler,1)         // Dielectron MixingHandler
+};
+
+
+
+#endif
index 4cb68da..0b695e7 100644 (file)
@@ -30,12 +30,11 @@ Detailed description
 #include <TGraph.h>
 
 #include <AliVTrack.h>
+#include <AliVCluster.h>
 #include <AliLog.h>
 #include <AliExternalTrackParam.h>
-#include <AliESDtrack.h>
-#include <AliESDpid.h>
-#include <AliAODpidUtil.h>
-#include <AliAODPid.h>
+#include <AliPIDResponse.h>
+#include <AliESDtrack.h> //!!!!! Remove once Eta correction is treated in the tender
 
 #include "AliDielectronVarManager.h"
 
@@ -45,12 +44,12 @@ ClassImp(AliDielectronPID)
 
 TGraph *AliDielectronPID::fgFitCorr=0x0;
 Double_t AliDielectronPID::fgCorr=0.0;
+TF1 *AliDielectronPID::fgFunEtaCorr=0x0;
 
 AliDielectronPID::AliDielectronPID() :
   AliAnalysisCuts(),
   fNcuts(0),
-  fESDpid(0x0),
-  fAODpidUtil(0x0)
+  fPIDResponse(0x0)
 {
   //
   // Default Constructor
@@ -60,12 +59,13 @@ AliDielectronPID::AliDielectronPID() :
     fPartType[icut]=AliPID::kPion;
     fNsigmaLow[icut]=0;
     fNsigmaUp[icut]=0;
-    fPmin[icut]=0;
-    fPmax[icut]=0;
+    fmin[icut]=0;
+    fmax[icut]=0;
     fExclude[icut]=kFALSE;
     fFunUpperCut[icut]=0x0;
     fFunLowerCut[icut]=0x0;
     fRequirePIDbit[icut]=0;
+    fActiveCuts[icut]=-1;
   }
 }
 
@@ -73,8 +73,7 @@ AliDielectronPID::AliDielectronPID() :
 AliDielectronPID::AliDielectronPID(const char* name, const char* title) :
   AliAnalysisCuts(name, title),
   fNcuts(0),
-  fESDpid(0x0),
-  fAODpidUtil(0x0)
+  fPIDResponse(0x0)
 {
   //
   // Named Constructor
@@ -84,12 +83,13 @@ AliDielectronPID::AliDielectronPID(const char* name, const char* title) :
     fPartType[icut]=AliPID::kPion;
     fNsigmaLow[icut]=0;
     fNsigmaUp[icut]=0;
-    fPmin[icut]=0;
-    fPmax[icut]=0;
+    fmin[icut]=0;
+    fmax[icut]=0;
     fExclude[icut]=kFALSE;
     fFunUpperCut[icut]=0x0;
     fFunLowerCut[icut]=0x0;
     fRequirePIDbit[icut]=0;
+    fActiveCuts[icut]=0;
   }
 }
 
@@ -103,13 +103,13 @@ AliDielectronPID::~AliDielectronPID()
 
 //______________________________________________
 void AliDielectronPID::AddCut(DetType det, AliPID::EParticleType type, Double_t nSigmaLow, Double_t nSigmaUp/*=-99999.*/,
-                              Double_t pMin/*=0*/, Double_t pMax/*=0*/, Bool_t exclude/*=kFALSE*/,
-                              UInt_t pidBitType/*=AliDielectronPID::kRequire*/)
+                              Double_t min/*=0*/, Double_t max/*=0*/, Bool_t exclude/*=kFALSE*/,
+                              UInt_t pidBitType/*=AliDielectronPID::kRequire*/, Int_t var/*=-1*/)
 {
   //
   // Add a pid nsigma cut
-  // use response of detector 'det' in the momentum range ('pMin') to ['pMax']
-  // use a sigma band betwee 'nSigmaLow' and 'nSigmaUp'
+  // use response of detector 'det' in the range ['min'] to ['max'] for var
+  // use a sigma band between 'nSigmaLow' and 'nSigmaUp'
   // if nSigmaUp==-99999. then nSigmaLow will be uesd as a symmetric band +- nSigmaLow
   // specify whether to 'exclude' the given band
   //
@@ -126,18 +126,23 @@ void AliDielectronPID::AddCut(DetType det, AliPID::EParticleType type, Double_t
   fPartType[fNcuts]=type;
   fNsigmaLow[fNcuts]=nSigmaLow;
   fNsigmaUp[fNcuts]=nSigmaUp;
-  fPmin[fNcuts]=pMin;
-  fPmax[fNcuts]=pMax;
+  fmin[fNcuts]=min;
+  fmax[fNcuts]=max;
   fExclude[fNcuts]=exclude;
   fRequirePIDbit[fNcuts]=pidBitType;
-  ++fNcuts;
+  fActiveCuts[fNcuts]=(var==-1 ? AliDielectronVarManager::kP : var);
+
+  AliInfo(Form("Add PID cut %d: sigma [% .1f,% .1f] \t cut [% .1f,% .f] \t var %d->%s \n",
+              fNcuts,nSigmaLow,nSigmaUp,min,max,fActiveCuts[fNcuts],AliDielectronVarManager::GetValueName(fActiveCuts[fNcuts])));  
   
+  ++fNcuts;
+
 }
 
 //______________________________________________
 void AliDielectronPID::AddCut(DetType det, AliPID::EParticleType type, Double_t nSigmaLow, TF1 * const funUp,
-                              Double_t pMin/*=0*/, Double_t pMax/*=0*/, Bool_t exclude/*=kFALSE*/,
-                              UInt_t pidBitType/*=AliDielectronPID::kRequire*/)
+                              Double_t min/*=0*/, Double_t max/*=0*/, Bool_t exclude/*=kFALSE*/,
+                              UInt_t pidBitType/*=AliDielectronPID::kRequire*/, Int_t var/*=-1*/)
 {
   //
   // cut using a TF1 as upper cut
@@ -147,13 +152,13 @@ void AliDielectronPID::AddCut(DetType det, AliPID::EParticleType type, Double_t
     return;
   }
   fFunUpperCut[fNcuts]=funUp;
-  AddCut(det,type,nSigmaLow,0.,pMin,pMax,exclude,pidBitType);
+  AddCut(det,type,nSigmaLow,0.,min,max,exclude,pidBitType,var);
 }
 
 //______________________________________________
 void AliDielectronPID::AddCut(DetType det, AliPID::EParticleType type, TF1 * const funLow, Double_t nSigmaUp,
-                              Double_t pMin/*=0*/, Double_t pMax/*=0*/, Bool_t exclude/*=kFALSE*/,
-                              UInt_t pidBitType/*=AliDielectronPID::kRequire*/)
+                              Double_t min/*=0*/, Double_t max/*=0*/, Bool_t exclude/*=kFALSE*/,
+                              UInt_t pidBitType/*=AliDielectronPID::kRequire*/, Int_t var/*=-1*/)
 {
   //
   // cut using a TF1 as lower cut
@@ -163,13 +168,13 @@ void AliDielectronPID::AddCut(DetType det, AliPID::EParticleType type, TF1 * con
     return;
   }
   fFunLowerCut[fNcuts]=funLow;
-  AddCut(det,type,0.,nSigmaUp,pMin,pMax,exclude,pidBitType);
+  AddCut(det,type,0.,nSigmaUp,min,max,exclude,pidBitType,var);
 }
 
 //______________________________________________
 void AliDielectronPID::AddCut(DetType det, AliPID::EParticleType type, TF1 * const funLow, TF1 * const funUp,
-                              Double_t pMin/*=0*/, Double_t pMax/*=0*/, Bool_t exclude/*=kFALSE*/,
-                              UInt_t pidBitType/*=AliDielectronPID::kRequire*/)
+                              Double_t min/*=0*/, Double_t max/*=0*/, Bool_t exclude/*=kFALSE*/,
+                              UInt_t pidBitType/*=AliDielectronPID::kRequire*/, Int_t var/*=-1*/)
 {
   //
   // cut using a TF1 as lower and upper cut
@@ -180,7 +185,7 @@ void AliDielectronPID::AddCut(DetType det, AliPID::EParticleType type, TF1 * con
   }
   fFunUpperCut[fNcuts]=funUp;
   fFunLowerCut[fNcuts]=funLow;
-  AddCut(det,type,0.,0.,pMin,pMax,exclude,pidBitType);
+  AddCut(det,type,0.,0.,min,max,exclude,pidBitType,var);
 }
 
 //______________________________________________
@@ -192,22 +197,31 @@ Bool_t AliDielectronPID::IsSelected(TObject* track)
 
   //loop over all cuts
   AliVTrack *part=static_cast<AliVTrack*>(track);
-  //TODO: Which momentum to use?
-  //      Different momenta for different detectors?
-  Double_t mom=part->P();
+  AliESDtrack *esdTrack=0x0;
+  Double_t origdEdx=-1;
   
-  Bool_t selected=kFALSE;
-  fESDpid=AliDielectronVarManager::GetESDpid();
-  fAODpidUtil=AliDielectronVarManager::GetAODpidUtil();
-  
-  for (UChar_t icut=0; icut<fNcuts; ++icut){
-    Double_t pMin=fPmin[icut];
-    Double_t pMax=fPmax[icut];
-
-    // test momentum range. In case pMin==pMax use all momenta
-    if ( (TMath::Abs(pMin-pMax)>1e-20) && (mom<=pMin || mom>pMax) ) continue;
+  // apply ETa correction, remove once this is in the tender
+  if( (part->IsA() == AliESDtrack::Class()) && fgFunEtaCorr ){
+    esdTrack=static_cast<AliESDtrack*>(part);
+    origdEdx=esdTrack->GetTPCsignal();
+    esdTrack->SetTPCsignal(origdEdx/GetEtaCorr(esdTrack),esdTrack->GetTPCsignalSigma(),esdTrack->GetTPCsignalN());
+  }
 
+  
+  //Fill values
+  Double_t values[AliDielectronVarManager::kNMaxValues];
+  AliDielectronVarManager::Fill(track,values);
 
+  Bool_t selected=kFALSE;
+  fPIDResponse=AliDielectronVarManager::GetPIDResponse();
+  for (UChar_t icut=0; icut<fNcuts; ++icut){
+    Double_t min=fmin[icut];
+    Double_t max=fmax[icut];
+    Double_t val=values[fActiveCuts[icut]];
+    
+    // test var range. In case min==max do not cut
+    if ( (TMath::Abs(min-max)>1e-20) && (val<min || val>=max) ) continue;
+    
     switch (fDetType[icut]){
     case kITS:
       selected = IsSelectedITS(part,icut);
@@ -218,13 +232,24 @@ Bool_t AliDielectronPID::IsSelected(TObject* track)
     case kTRD:
       selected = IsSelectedTRD(part,icut);
       break;
+    case kTRDeleEff:
+      selected = IsSelectedTRDeleEff(part,icut);
+      break;
     case kTOF:
       selected = IsSelectedTOF(part,icut);
       break;
+    case kEMCAL:
+      selected = IsSelectedEMCAL(part,icut);
+      break;
+    }
+    if (!selected) {
+      if (esdTrack) esdTrack->SetTPCsignal(origdEdx,esdTrack->GetTPCsignalSigma(),esdTrack->GetTPCsignalN());
+
+      return kFALSE;
     }
-    if (!selected) return kFALSE;
   }
 
+  if (esdTrack) esdTrack->SetTPCsignal(origdEdx,esdTrack->GetTPCsignalSigma(),esdTrack->GetTPCsignalN());
   return selected;
 }
 
@@ -235,23 +260,13 @@ Bool_t AliDielectronPID::IsSelectedITS(AliVTrack * const part, Int_t icut)
   // ITS part of the PID check
   // Don't accept the track if there was no pid bit set
   //
-  Float_t numberOfSigmas=-1000.;
   
-  if (fRequirePIDbit[icut]==AliDielectronPID::kRequire&&!(part->GetStatus()&AliESDtrack::kITSpid)) return kFALSE;
-  if (fRequirePIDbit[icut]==AliDielectronPID::kIfAvailable&&!(part->GetStatus()&AliESDtrack::kITSpid)) return kTRUE;
+  if (fRequirePIDbit[icut]==AliDielectronPID::kRequire&&!(part->GetStatus()&AliVTrack::kITSpid)) return kFALSE;
+  if (fRequirePIDbit[icut]==AliDielectronPID::kIfAvailable&&!(part->GetStatus()&AliVTrack::kITSpid)) return kTRUE;
 
   Double_t mom=part->P();
   
-  if (part->IsA()==AliESDtrack::Class()){
-    // ESD case in case the PID bit is not set, don't use this track!
-    AliESDtrack *track=static_cast<AliESDtrack*>(part);
-    numberOfSigmas=fESDpid->NumberOfSigmasITS(track, fPartType[icut]);
-  }else if(part->IsA()==AliAODTrack::Class()){
-    // AOD case
-    // FIXME: Is there a place to check whether the PID is was set in ESD???
-    AliAODTrack *track=static_cast<AliAODTrack*>(part);
-    numberOfSigmas=fAODpidUtil->NumberOfSigmasITS(track, fPartType[icut]);
-  }
+  Float_t numberOfSigmas=fPIDResponse->NumberOfSigmasITS(part, fPartType[icut]);
   
   // test if we are supposed to use a function for the cut
   if (fFunUpperCut[icut]) fNsigmaUp[icut] =fFunUpperCut[icut]->Eval(mom);
@@ -268,27 +283,13 @@ Bool_t AliDielectronPID::IsSelectedTPC(AliVTrack * const part, Int_t icut)
   // TPC part of the PID check
   // Don't accept the track if there was no pid bit set
   //
-  Float_t numberOfSigmas=-1000.;
-  
-  if (fRequirePIDbit[icut]==AliDielectronPID::kRequire&&!(part->GetStatus()&AliESDtrack::kTPCpid)) return kFALSE;
-  if (fRequirePIDbit[icut]==AliDielectronPID::kIfAvailable&&!(part->GetStatus()&AliESDtrack::kTPCpid)) return kTRUE;
+  if (fRequirePIDbit[icut]==AliDielectronPID::kRequire&&!(part->GetStatus()&AliVTrack::kTPCpid)) return kFALSE;
+  if (fRequirePIDbit[icut]==AliDielectronPID::kIfAvailable&&!(part->GetStatus()&AliVTrack::kTPCpid)) return kTRUE;
 
-  Double_t mom=part->P();
+  Double_t mom=part->GetTPCmomentum();
   
-  if (part->IsA()==AliESDtrack::Class()){
-    // ESD case in case the PID bit is not set, don't use this track!
-    AliESDtrack *track=static_cast<AliESDtrack*>(part);
-    const AliExternalTrackParam *in = track->GetInnerParam();
-    if (in) mom = in->GetP();
-    numberOfSigmas=fESDpid->NumberOfSigmasTPC(track, fPartType[icut]);
-  }else if(part->IsA()==AliAODTrack::Class()){
-    // AOD case
-    // FIXME: Is there a place to check whether the PID is was set in ESD???
-    AliAODTrack *track=static_cast<AliAODTrack*>(part);
-    const AliAODPid *pidObj = track->GetDetPid();
-    if (pidObj) mom = pidObj->GetTPCmomentum();
-    numberOfSigmas=fAODpidUtil->NumberOfSigmasTPC(track, fPartType[icut]);
-  }
+  Float_t numberOfSigmas=fPIDResponse->NumberOfSigmasTPC(part, fPartType[icut]);
+
   if (fPartType[icut]==AliPID::kElectron){
     numberOfSigmas-=fgCorr;
   }
@@ -302,12 +303,39 @@ Bool_t AliDielectronPID::IsSelectedTPC(AliVTrack * const part, Int_t icut)
 }
 
 //______________________________________________
-Bool_t AliDielectronPID::IsSelectedTRD(AliVTrack * const /*part*/, Int_t /*icut*/)
+Bool_t AliDielectronPID::IsSelectedTRD(AliVTrack * const part, Int_t icut)
 {
   //   
   // TRD part of the pid check
+  // the TRD checks on the probabilities.
+  //
+
+  if (fRequirePIDbit[icut]==AliDielectronPID::kRequire&&!(part->GetStatus()&AliVTrack::kTRDpid)) return kFALSE;
+  if (fRequirePIDbit[icut]==AliDielectronPID::kIfAvailable&&!(part->GetStatus()&AliVTrack::kTRDpid)) return kTRUE;
+  if (fRequirePIDbit[icut]==AliDielectronPID::kIfAvailable && (part->GetTRDntrackletsPID()<4)) return kTRUE;
+
+  Double_t p[AliPID::kSPECIES]={0.};
+  fPIDResponse->ComputeTRDProbability(part,AliPID::kSPECIES,p);
+  Float_t particleProb=p[fPartType[icut]];
+
+  Bool_t selected=((particleProb>=fNsigmaLow[icut])&&(particleProb<=fNsigmaUp[icut]))^fExclude[icut];
+  return selected;
+}
+
+//______________________________________________
+Bool_t AliDielectronPID::IsSelectedTRDeleEff(AliVTrack * const part, Int_t icut)
+{
   //
-  return kFALSE;
+  // TRD part of the pid check using electron efficiency requirement
+  // in this case the upper limit as well as the particle specie is ignored 
+  //   and the lower limit regarded as the requested electron efficiency
+  //
+
+  if (fRequirePIDbit[icut]==AliDielectronPID::kRequire&&!(part->GetStatus()&AliVTrack::kTRDpid)) return kFALSE;
+  if (fRequirePIDbit[icut]==AliDielectronPID::kIfAvailable&&!(part->GetStatus()&AliVTrack::kTRDpid)) return kTRUE;
+
+  Bool_t selected=fPIDResponse->IdentifiedAsElectronTRD(part,fNsigmaLow[icut])^fExclude[icut];
+  return selected;
 }
 
 //______________________________________________
@@ -317,27 +345,37 @@ Bool_t AliDielectronPID::IsSelectedTOF(AliVTrack * const part, Int_t icut)
   // TOF part of the PID check
   // Don't accept the track if there was no pid bit set
   //
-  Float_t numberOfSigmas=-1000.;
   
-  if (fRequirePIDbit[icut]==AliDielectronPID::kRequire&&!(part->GetStatus()&AliESDtrack::kTOFpid)) return kFALSE;
-  if (fRequirePIDbit[icut]==AliDielectronPID::kIfAvailable&&!(part->GetStatus()&AliESDtrack::kTOFpid)) return kTRUE;
-
-  if (part->IsA()==AliESDtrack::Class()){
-    // ESD case in case the PID bit is not set, don't use this track!
-    AliESDtrack *track=static_cast<AliESDtrack*>(part);
-    numberOfSigmas=fESDpid->NumberOfSigmasTOF(track, fPartType[icut], fESDpid->GetTOFResponse().GetTimeZero());
-  }else if(part->IsA()==AliAODTrack::Class()){
-    // AOD case
-    // FIXME: Is there a place to check whether the PID is was set in ESD???
-    AliAODTrack *track=static_cast<AliAODTrack*>(part);
-    numberOfSigmas=fAODpidUtil->NumberOfSigmasTOF(track, fPartType[icut]);
-  }
+  if (fRequirePIDbit[icut]==AliDielectronPID::kRequire&&!(part->GetStatus()&AliVTrack::kTOFpid)) return kFALSE;
+  if (fRequirePIDbit[icut]==AliDielectronPID::kIfAvailable&&!(part->GetStatus()&AliVTrack::kTOFpid)) return kTRUE;
+
+  Float_t numberOfSigmas=fPIDResponse->NumberOfSigmasTOF(part, fPartType[icut]);
   
   Bool_t selected=((numberOfSigmas>=fNsigmaLow[icut])&&(numberOfSigmas<=fNsigmaUp[icut]))^fExclude[icut];
   return selected;
 }
 
 //______________________________________________
+Bool_t AliDielectronPID::IsSelectedEMCAL(AliVTrack * const part, Int_t icut)
+{
+  //
+  // emcal pid selecttion
+  //
+
+  //TODO: correct way to check for emcal pid?
+  Float_t numberOfSigmas=fPIDResponse->NumberOfSigmasEMCAL(part, fPartType[icut]);
+
+  Bool_t hasPID=numberOfSigmas>-998.;
+
+  if (fRequirePIDbit[icut]==AliDielectronPID::kRequire&&!hasPID) return kFALSE;
+  if (fRequirePIDbit[icut]==AliDielectronPID::kIfAvailable&&!hasPID) return kTRUE;
+
+
+  Bool_t selected=((numberOfSigmas>=fNsigmaLow[icut])&&(numberOfSigmas<=fNsigmaUp[icut]))^fExclude[icut];
+  return selected;
+}
+
+//______________________________________________
 void AliDielectronPID::SetDefaults(Int_t def){
   //
   // initialise default pid strategies
@@ -357,7 +395,6 @@ void AliDielectronPID::SetDefaults(Int_t def){
     // 2sigma bands TPC:
     // - include e 0<p<inf
     // - exclude mu,K,pi,p 0<p<2
-
     AddCut(kTPC,AliPID::kElectron,2.);
     AddCut(kTPC,AliPID::kMuon,-2.,2.,0.,2.,kTRUE);
     AddCut(kTPC,AliPID::kPion,-2.,2.,0.,2.,kTRUE);
@@ -372,7 +409,7 @@ void AliDielectronPID::SetDefaults(Int_t def){
     AddCut(kTPC,AliPID::kPion,-3.,3.,0.,0.,kTRUE);
     AddCut(kTPC,AliPID::kProton,-3.,3.,0.,0.,kTRUE);
 
-  } else if (def==3) {
+  } else if (def==3 || def==4) { // def3 and def4 are the same??
     // include 2sigma e TPC
     // 3sigma bands TOF
     // - exclude K 0<p<1
@@ -382,15 +419,6 @@ void AliDielectronPID::SetDefaults(Int_t def){
     AddCut(kTOF,AliPID::kProton,-6.,6.,0.,1.,kTRUE);
     AddCut(kTOF,AliPID::kProton,-3.,3.,1.,2.,kTRUE);
     
-  } else if (def==4) {
-    // include 2sigma e TPC
-    // 3sigma bands TOF
-    // - exclude K 0<p<1
-    // - exclude P 0<p<2
-    AddCut(kTPC,AliPID::kElectron,2.);
-    AddCut(kTOF,AliPID::kKaon,-3.,3.,0.,1.,kTRUE);
-    AddCut(kTOF,AliPID::kProton,-6.,6.,0.,1.,kTRUE);
-    AddCut(kTOF,AliPID::kProton,-3.,3.,1.,2.,kTRUE);
   } else if (def==5) {
     AddCut(kTPC,AliPID::kElectron,-0.5,3);
     AddCut(kTOF,AliPID::kElectron,-3,3,0,1.5);
@@ -464,3 +492,12 @@ void AliDielectronPID::SetCorrVal(Double_t run)
 //   printf("Corr: %f\n",fgCorr);
 }
 
+//______________________________________________
+Double_t AliDielectronPID::GetEtaCorr(AliVTrack *track)
+{
+  //
+  // return eta correction
+  //
+  if (!fgFunEtaCorr) return 1;
+  return fgFunEtaCorr->Eval(track->Eta());
+}
index 8ffe33c..13b287e 100644 (file)
 //#############################################################
 
 #include <AliPID.h>
-#include <AliAODTrack.h>
-#include <AliAODPid.h>
-
 #include <AliAnalysisCuts.h>
 
 class TF1;
 class TList;
 class AliVTrack;
 class TGraph;
-class AliESDpid;
-class AliAODpidUtil;
+class AliPIDResponse;
+class AliDielectronVarManager;
 
 class AliDielectronPID : public AliAnalysisCuts {
 public:
-  enum DetType {kITS, kTPC, kTRD, kTOF};
-  enum PIDbitTupe {kIgnore=0, kRequire, kIfAvailable};
+  enum DetType {kITS, kTPC, kTRD, kTRDeleEff, kTOF, kEMCAL};
+  enum PIDbitType {kIgnore=0, kRequire, kIfAvailable};
   
   AliDielectronPID();
   AliDielectronPID(const char*name, const char* title);
@@ -43,16 +40,20 @@ public:
   virtual ~AliDielectronPID();
 
   void AddCut(DetType det, AliPID::EParticleType type, Double_t nSigmaLow, Double_t nSigmaUp=-99999.,
-              Double_t pMin=0, Double_t pMax=0, Bool_t exclude=kFALSE, UInt_t pidBitType=AliDielectronPID::kRequire);
+              Double_t min=0, Double_t max=0, Bool_t exclude=kFALSE, UInt_t pidBitType=AliDielectronPID::kRequire, 
+             Int_t var=-1);
 
   void AddCut(DetType det, AliPID::EParticleType type, Double_t nSigmaLow, TF1 * const funUp,
-              Double_t pMin=0, Double_t pMax=0, Bool_t exclude=kFALSE, UInt_t pidBitType=AliDielectronPID::kRequire);
+              Double_t min=0, Double_t max=0, Bool_t exclude=kFALSE, UInt_t pidBitType=AliDielectronPID::kRequire, 
+             Int_t var=-1);
 
   void AddCut(DetType det, AliPID::EParticleType type, TF1 * const funLow, Double_t nSigmaUp,
-              Double_t pMin=0, Double_t pMax=0, Bool_t exclude=kFALSE, UInt_t pidBitType=AliDielectronPID::kRequire);
+              Double_t min=0, Double_t max=0, Bool_t exclude=kFALSE, UInt_t pidBitType=AliDielectronPID::kRequire, 
+             Int_t var=-1);
 
   void AddCut(DetType det, AliPID::EParticleType type, TF1 * const funLow, TF1 * const funUp,
-              Double_t pMin=0, Double_t pMax=0, Bool_t exclude=kFALSE, UInt_t pidBitType=AliDielectronPID::kRequire);
+              Double_t min=0, Double_t max=0, Bool_t exclude=kFALSE, UInt_t pidBitType=AliDielectronPID::kRequire, 
+             Int_t var=-1);
   
   void SetDefaults(Int_t def);
 
@@ -66,33 +67,41 @@ public:
   static void SetCorrVal(Double_t run);
   static Double_t GetCorrVal()   { return fgCorr; }
   static TGraph *GetCorrGraph()  { return fgFitCorr; }
-  
+
+  static void SetEtaCorrFunction(TF1 *fun) {fgFunEtaCorr=fun;}
+  static TF1* GetEtaCorrFunction() { return fgFunEtaCorr; }
+
+  static Double_t GetEtaCorr(AliVTrack *track);
+
 private:
   enum {kNmaxPID=10};
-  
+
   DetType  fDetType[kNmaxPID];    //detector type of nsigma cut
   AliPID::EParticleType fPartType[kNmaxPID]; //particle type
   Float_t  fNsigmaLow[kNmaxPID];  //lower nsigma bound
   Float_t  fNsigmaUp[kNmaxPID];   //upper nsigma bound
-  Double_t fPmin[kNmaxPID];       //lower momentum
-  Double_t fPmax[kNmaxPID];       //upper momentum
+  Double_t fmin[kNmaxPID];        //lower cut limit
+  Double_t fmax[kNmaxPID];        //upper cut limit
   Bool_t   fExclude[kNmaxPID];    //use as exclusion band
   TF1     *fFunUpperCut[kNmaxPID];//use function as upper cut
   TF1     *fFunLowerCut[kNmaxPID];//use function as lower cut
   UChar_t  fNcuts;                //number of cuts
   UChar_t  fRequirePIDbit[kNmaxPID]; //How to make use of the pid bit (see)
+  UShort_t fActiveCuts[kNmaxPID]; // list of activated cuts
 
-  AliESDpid *fESDpid;             //! esd pid object
-  AliAODpidUtil *fAODpidUtil;     //! AOD pid object
+  AliPIDResponse *fPIDResponse;   //! pid response object
   
   static TGraph *fgFitCorr;       //spline fit object to correct the nsigma deviation in the TPC electron band
   static Double_t fgCorr;         //!correction value for current run. Set if fgFitCorr is set and SetCorrVal(run)
                                   // was called
+  static TF1    *fgFunEtaCorr;    //function for eta correction of electron sigma
   
   Bool_t IsSelectedITS(AliVTrack * const part, Int_t icut);
   Bool_t IsSelectedTPC(AliVTrack * const part, Int_t icut);
   Bool_t IsSelectedTRD(AliVTrack * const part, Int_t icut);
+  Bool_t IsSelectedTRDeleEff(AliVTrack * const part, Int_t icut);
   Bool_t IsSelectedTOF(AliVTrack * const part, Int_t icut);
+  Bool_t IsSelectedEMCAL(AliVTrack * const part, Int_t icut);
 
   AliDielectronPID(const AliDielectronPID &c);
   AliDielectronPID &operator=(const AliDielectronPID &c);
index 8d1eb3d..abca10c 100644 (file)
@@ -334,23 +334,23 @@ Double_t AliDielectronPair::ThetaPhiCM(const Bool_t isHE, const Bool_t isTheta)
   }
 }
 
-//______________________________________________
-Double_t AliDielectronPair::GetLXY(const AliVVertex * const vtx) const
-{
-  //
-  // Calculate the decay length in XY taking into account the primary vertex position
-  //
-  if(!vtx) return 0;
-  return ( (Xv()-vtx->GetX()) * Px() + (Yv()-vtx->GetY()) * Py() )/Pt()  ;
-}
+// //______________________________________________
+// Double_t AliDielectronPair::GetLXY(const AliVVertex * const vtx) const
+// {
+//   //
+//   // Calculate the decay length in XY taking into account the primary vertex position
+//   //
+//   if(!vtx) return 0;
+//   return ( (Xv()-vtx->GetX()) * Px() + (Yv()-vtx->GetY()) * Py() )/Pt()  ;
+// }
 
-//______________________________________________
-Double_t AliDielectronPair::GetPseudoProperTime(const AliVVertex * const vtx) const
-{
-  //
-  // Calculate the pseudo proper time
-  //
-  Double_t lxy=GetLXY(vtx);
-  Double_t psProperDecayLength = lxy*(TDatabasePDG::Instance()->GetParticle(443)->Mass())/Pt();
-  return psProperDecayLength;
-}
+// //______________________________________________
+// Double_t AliDielectronPair::GetPseudoProperTime(const AliVVertex * const vtx) const
+// {
+//   //
+//   // Calculate the pseudo proper time
+//   //
+//   Double_t lxy=GetLXY(vtx);
+//   Double_t psProperDecayLength = lxy*(TDatabasePDG::Instance()->GetParticle(443)->Mass())/Pt();
+//   return psProperDecayLength;
+// }
index 8c22e09..1d1c5d0 100644 (file)
@@ -92,8 +92,8 @@ public:
   // Dummy
   Int_t PdgCode() const {return 0;}
   //
-  Double_t GetLXY(const AliVVertex * const vtx) const;
-  Double_t GetPseudoProperTime(const AliVVertex * const vtx) const;
+  // Double_t GetLXY(const AliVVertex * const vtx) const;
+  // Double_t GetPseudoProperTime(const AliVVertex * const vtx) const;
 
 
   UChar_t GetType() const { return fType; }
@@ -104,6 +104,8 @@ public:
   void SetProductionVertex(const AliKFParticle &Vtx) { fPair.SetProductionVertex(Vtx); }
   
   //inter leg information
+  Double_t GetKFChi2()            const { return fPair.GetChi2();                               }
+  Int_t    GetKFNdf()             const { return fPair.GetNDF();                                }
   Double_t OpeningAngle()         const { return fD1.GetAngle(fD2);                             }
   Double_t DistanceDaughters()    const { return fD1.GetDistanceFromParticle(fD2);              }
   Double_t DistanceDaughtersXY()  const { return fD1.GetDistanceFromParticleXY(fD2);            }
index da3cc99..a5fc935 100644 (file)
@@ -42,6 +42,7 @@ AliDielectronSignalBase::AliDielectronSignalBase() :
   fHistDataPM(0),
   fHistDataPP(0),
   fHistDataMM(0),
+  fHistDataME(0),
   fValues(6),
   fErrors(6),
   fIntMin(0),
@@ -68,6 +69,7 @@ AliDielectronSignalBase::AliDielectronSignalBase(const char* name, const char* t
   fHistDataPM(0),
   fHistDataPP(0),
   fHistDataMM(0),
+  fHistDataME(0),
   fValues(6),
   fErrors(6),
   fIntMin(0),
@@ -97,6 +99,7 @@ AliDielectronSignalBase::~AliDielectronSignalBase()
   if (fHistDataPP) delete fHistDataPP;
   if (fHistDataPM) delete fHistDataPM;
   if (fHistDataMM) delete fHistDataMM;
+  if (fHistDataME) delete fHistDataME;
   
 }
 
index 5f937f6..6101810 100644 (file)
@@ -32,7 +32,8 @@ class TH1F;
 class AliDielectronSignalBase : public TNamed {
 public:
   enum EBackgroundMethod {
-    kFitted = 0,
+    kFittedMC = 0,
+       kFitted,
     kLikeSign,
     kLikeSignArithm,
     kEventMixing,
@@ -66,7 +67,7 @@ public:
   Double_t GetMassError()            const { return fErrors(4);}
   Double_t GetMassWidth()            const { return fValues(5);}
   Double_t GetMassWidthError()       const { return fErrors(5);}
-
   TH1* GetSignalHistogram()      const {return fHistSignal;}
   TH1* GetBackgroundHistogram()  const {return fHistBackground;}
   TH1* GetUnlikeSignHistogram()  const {return fHistDataPM;}
@@ -95,24 +96,25 @@ protected:
   TH1 *fHistDataPM;                  // histogram of selected +- pair candidates
   TH1 *fHistDataPP;                  // histogram of selected ++ pair candidates
   TH1 *fHistDataMM;                  // histogram of selected -- pair candidates
+  TH1 *fHistDataME;                  // histogram of selected +- pair candidates from mixed event
 
-  TVectorD fValues;                   // values
-  TVectorD fErrors;                   // value errors
+  TVectorD fValues;                  // values
+  TVectorD fErrors;                  // value errors
 
-  Double_t fIntMin;                   // signal extraction range min
-  Double_t fIntMax;                   // signal extraction range max
-  Double_t fFitMin;                   // fit range lowest inv. mass
-  Double_t fFitMax;                   // fit range highest inv. mass
+  Double_t fIntMin;                  // signal extraction range min
+  Double_t fIntMax;                  // signal extraction range max
+  Double_t fFitMin;                  // fit range lowest inv. mass
+  Double_t fFitMax;                  // fit range highest inv. mass
 
-  Int_t fRebin;                       // histogram rebin factor
-  EBackgroundMethod fMethod;          // method for background substraction
-  Double_t fScaleMin;                 // min for scaling of raw and background histogram
-  Double_t fScaleMax;                 // max for scaling of raw and background histogram
-  Double_t fScaleFactor;              // scale factor of raw to background histogram scaling
+  Int_t fRebin;                      // histogram rebin factor
+  EBackgroundMethod fMethod;         // method for background substraction
+  Double_t fScaleMin;                // min for scaling of raw and background histogram
+  Double_t fScaleMax;                // max for scaling of raw and background histogram
+  Double_t fScaleFactor;             // scale factor of raw to background histogram scaling
   
-  Bool_t fProcessed;                  // flag
+  Bool_t fProcessed;                 // flag
   
-  void SetSignificanceAndSOB();       // calculate the significance and S/B
+  void SetSignificanceAndSOB();      // calculate the significance and S/B
   TPaveText* DrawStats(Double_t x1=0., Double_t y1=0., Double_t x2=0., Double_t y2=0.);
 
   AliDielectronSignalBase(const AliDielectronSignalBase &c);
index 35801b4..1074f0a 100644 (file)
@@ -149,7 +149,12 @@ void AliDielectronSignalExt::ProcessLS(TObjArray* const arrhist)
     fHistBackground->SetBinError(ibin, ebackground);
   }
   //scale histograms to match integral between fScaleMin and fScaleMax
+  // or if fScaleMax <  fScaleMin use fScaleMin as scale factor
   if (fScaleMax>fScaleMin) fScaleFactor=ScaleHistograms(fHistDataPM,fHistBackground,fScaleMin,fScaleMax);
+  else if (fScaleMin>0.){
+    fScaleFactor=fScaleMin;
+    fHistBackground->Scale(fScaleFactor);
+  }
 
   //subract background
   fHistSignal->Add(fHistBackground,-1);
@@ -161,6 +166,7 @@ void AliDielectronSignalExt::ProcessLS(TObjArray* const arrhist)
   fValues(1) = fHistBackground->IntegralAndError(fHistBackground->FindBin(fIntMin),
                                                 fHistBackground->FindBin(fIntMax), 
                                                 fErrors(1));
+  printf("%f  %f\n",fValues(0),fValues(1));
   // S/B and significance
   SetSignificanceAndSOB();
 
@@ -171,10 +177,63 @@ void AliDielectronSignalExt::ProcessLS(TObjArray* const arrhist)
 void AliDielectronSignalExt::ProcessEM(TObjArray* const arrhist)
 {
   //
-  // event mixing. not implemented yet.
+  // event mixing
   //
-  printf("event mixing method is not implemented yet. Like-sign method will be used.\n");
-  ProcessLS(arrhist);
+  fHistDataPM = (TH1*)(arrhist->At(0))->Clone("histPMSE");  // +-    SE
+  fHistDataME = (TH1*)(arrhist->At(1))->Clone("histPMME");  // +-    ME
+  fHistDataPM->Sumw2();
+  fHistDataME->Sumw2();
+  fHistDataPM->SetDirectory(0);
+  fHistDataME->SetDirectory(0);
+
+  // rebin the histograms
+  if (fRebin>1) {
+    fHistDataPM->Rebin(fRebin); 
+    fHistDataME->Rebin(fRebin);
+  }
+
+  fHistSignal = new TH1D("HistSignal", "Mixed events background substracted signal",
+                        fHistDataPM->GetXaxis()->GetNbins(),
+                  fHistDataPM->GetXaxis()->GetXmin(), fHistDataPM->GetXaxis()->GetXmax());
+  fHistSignal->SetDirectory(0);
+  fHistBackground = new TH1D("HistBackground", "background contribution from mixed events",
+                            fHistDataPM->GetXaxis()->GetNbins(),
+                            fHistDataPM->GetXaxis()->GetXmin(), fHistDataPM->GetXaxis()->GetXmax());
+  fHistBackground->SetDirectory(0);
+
+  // fill out background and subtracted histogram
+  for(Int_t ibin=1; ibin<=fHistDataPM->GetXaxis()->GetNbins(); ibin++) {
+    Float_t pm = fHistDataPM->GetBinContent(ibin);
+    Float_t epm = fHistDataPM->GetBinError(ibin);
+    Float_t background = fHistDataME->GetBinContent(ibin);
+    Float_t ebackground = fHistDataME->GetBinError(ibin);
+
+    fHistSignal->SetBinContent(ibin, pm); 
+    fHistSignal->SetBinError(ibin, epm);
+    fHistBackground->SetBinContent(ibin, background);
+    fHistBackground->SetBinError(ibin, ebackground); 
+  }
+
+  if (fScaleMax>fScaleMin) fScaleFactor=ScaleHistograms(fHistDataPM,fHistBackground,fScaleMin,fScaleMax);
+  else if (fScaleMin>0.){    
+    fScaleFactor=fScaleMin;
+    fHistBackground->Scale(fScaleFactor);
+  }
+
+  //subract background  
+  fHistSignal->Add(fHistBackground,-1);
+
+  // signal  
+  fValues(0) = fHistSignal->IntegralAndError(fHistSignal->FindBin(fIntMin),
+                                            fHistSignal->FindBin(fIntMax), fErrors(0));
+  // background
+  fValues(1) = fHistBackground->IntegralAndError(fHistBackground->FindBin(fIntMin),
+                                                fHistBackground->FindBin(fIntMax), 
+                                                fErrors(1));
+  // S/B and significance
+  SetSignificanceAndSOB();
+
+  fProcessed = kTRUE;
 }
 
 //______________________________________________
@@ -206,8 +265,13 @@ void AliDielectronSignalExt::ProcessRotation(TObjArray* const arrhist)
   }
 
   //scale histograms to match integral between fScaleMin and fScaleMax
+  // or if fScaleMax <  fScaleMin use fScaleMin as scale factor
   if (fScaleMax>fScaleMin) fScaleFactor=ScaleHistograms(fHistDataPM,fHistBackground,fScaleMin,fScaleMax);
-  
+  else if (fScaleMin>0.){
+    fScaleFactor=fScaleMin;
+    fHistBackground->Scale(fScaleFactor);
+  }
+
   fHistSignal=(TH1*)fHistDataPM->Clone("histSignal");
   fHistSignal->Add(fHistBackground,-1.);
 
index 17c34a1..5c68176 100644 (file)
@@ -44,6 +44,8 @@ can be used.
 
 ClassImp(AliDielectronSignalFunc)
 
+TH1F* AliDielectronSignalFunc::fgHistSimPM=0x0;
+
 AliDielectronSignalFunc::AliDielectronSignalFunc() :
 AliDielectronSignalBase(),
 fFuncSignal(0x0),
@@ -52,7 +54,9 @@ fFuncSigBack(0x0),
 fParMass(1),
 fParMassWidth(2),
 fFitOpt("SMNQE"),
-fUseIntegral(kFALSE)
+fUseIntegral(kFALSE),
+fPolDeg(0),
+fChi2Dof(0.0)
 {
   //
   // Default Constructor
@@ -69,7 +73,9 @@ fFuncSigBack(0x0),
 fParMass(1),
 fParMassWidth(2),
 fFitOpt("SMNQE"),
-fUseIntegral(kFALSE)
+fUseIntegral(kFALSE),
+fPolDeg(0),
+fChi2Dof(0.0)
 {
   //
   // Named Constructor
@@ -95,6 +101,10 @@ void AliDielectronSignalFunc::Process(TObjArray * const arrhist)
   // Fit the invariant mass histograms and retrieve the signal and background
   //
   switch(fMethod) {
+  case kFittedMC :
+       ProcessFitIKF(arrhist);
+       break;
+                 
   case kFitted :
     ProcessFit(arrhist);
     break;
@@ -112,6 +122,305 @@ void AliDielectronSignalFunc::Process(TObjArray * const arrhist)
   }
 }
 
+//______________________________________________
+void AliDielectronSignalFunc::ProcessFitIKF(TObjArray * const arrhist) {
+  //
+  // Fit the +- invariant mass distribution only
+  // 
+  //
+  
+  const Double_t bigNumber = 100000.;
+  Double_t chi2ndfm1 = bigNumber;
+  Double_t ratiom1   = bigNumber;
+  Double_t chi2ndf   = bigNumber;
+  Int_t nDP =0;
+  
+  Int_t maxPolDeg = 8;
+      
+  fHistDataPM = (TH1F*)(arrhist->At(1))->Clone("histPM");  // +-    SE
+    if(fRebin>1) fHistDataPM->Rebin(fRebin);
+  
+  fgHistSimPM = (TH1F*)(arrhist->At(3))->Clone("histPMsim");  // +- mc shape
+  if (!fgHistSimPM) {
+       AliFatal("No mc peak shape found at idx 3.");
+       return;
+  }
+  if(fRebin>1) fgHistSimPM->Rebin(fRebin);
+  
+  // try out the polynomial degrees
+  for (Int_t iPD=0; iPD<=maxPolDeg; iPD++) {
+    TH1F *hf1 = (TH1F *) fHistDataPM->Clone(Form("hf1_PD%d",iPD));
+       
+       FitOneMinv(hf1, fgHistSimPM, iPD);
+       if (fChi2Dof > 0) chi2ndf = fChi2Dof;
+    AliInfo(Form("nDP: %d, iPD: %d, chi2ndf: %f", nDP, iPD, chi2ndf));
+       
+    ratiom1 = TMath::Abs(fChi2Dof - 1);
+    if (chi2ndfm1 > ratiom1) { // search for the closest to 1.
+      chi2ndfm1 = ratiom1;
+      nDP       = iPD;
+    }
+  }
+    
+  
+  // fit again with the best polynomial degree
+  TH1F *h2 = (TH1F *) fHistDataPM->Clone(Form("h2_PD%d",nDP));
+  
+  FitOneMinv(h2, fgHistSimPM, nDP);
+  AliInfo(Form("Best Fit: PD %d, chi^2/ndf %.3f, S/B %.3f",nDP,fChi2Dof,fValues(3)));
+    
+}
+//______________________________________________
+void AliDielectronSignalFunc::FitOneMinv(TH1F *hMinv, TH1F *hSim, Int_t pod) {
+  //
+  // main function to fit an inv mass spectrum
+  //
+  
+  TObjArray *arrResults = new TObjArray;
+  arrResults->SetOwner();
+  arrResults->AddAt(hMinv,0);
+  
+  // Degree of polynomial
+  fPolDeg = pod;
+    
+  // inclusion and exclusion areas (values)
+  const Double_t kJPMass    = 3.096916;
+  // inclusion and exclusion areas (bin numbers)
+  const Int_t binIntLo = hMinv->FindBin(fIntMin);
+  const Int_t binIntHi = hMinv->FindBin(fIntMax);
+  // for error calculation
+  Double_t intAreaEdgeLo = hMinv->GetBinLowEdge(binIntLo);
+  Double_t intAreaEdgeHi = hMinv->GetBinLowEdge(binIntHi)+hMinv->GetBinWidth(binIntHi);
+  Double_t norm = (binIntHi-binIntLo)/(fIntMax - fIntMin); 
+  
+  TH1F  *hBfit = (TH1F *) hMinv->Clone(); // for bg only fit (excluding peak region)
+  TH1F  *hSigF = (TH1F *) hMinv->Clone(); // signal with subtracted bg
+  TH1F  *hBgrd = (TH1F *) hMinv->Clone(); // bg histogram
+  
+  hBfit->Reset();
+  hSigF->Reset();
+  hBgrd->Reset();
+  
+  // extract start parameter for the MC signal fit
+  Double_t bgvalAv = (hMinv->Integral(1,hMinv->GetNbinsX()+1) - hMinv->Integral(binIntLo,binIntHi)) / (hMinv->GetNbinsX()+1 - (binIntHi-binIntLo));
+  Double_t pkval     = hMinv->GetBinContent(hMinv->FindBin(kJPMass)) - bgvalAv;
+  Double_t heightMC  = hSim->GetBinContent(hSim->FindBin(kJPMass));
+  Double_t peakScale = (heightMC > 0. ? pkval/heightMC : 0.0);
+  
+  Int_t nBgnd = 2 + fPolDeg; // degree + c1st oefficient + higher coefficients
+  Int_t nMinv = nBgnd + 1;  // bgrd + peakscale
+  
+  // Create the spectra without peak region
+  for (Int_t iBin = 0; iBin <= hMinv->GetNbinsX(); iBin++) {
+    if ((iBin < binIntLo) || (iBin > binIntHi)) {
+      hBfit->SetBinContent(iBin,hMinv->GetBinContent(iBin));
+      hBfit->SetBinError(iBin,hMinv->GetBinError(iBin));
+       }
+  }
+    
+  
+  // =======
+  //   1.
+  // =======
+  // Do the fit to the background spectrum
+  TF1 *fBo = new TF1("bgrd_fit",BgndFun,fFitMin,fFitMax,nBgnd);
+  for (Int_t iPar=0; iPar<nBgnd; iPar++) {
+    if (iPar == 0) fBo->FixParameter(0, fPolDeg);
+       if (iPar == 1) fBo->SetParameter(iPar, bgvalAv);
+    if (iPar >= 2) fBo->SetParameter(iPar, 0.);
+  }
+  hBfit->Fit(fBo,"0qR");
+  //hBfit->SetNameTitle("bgrd_fit");
+  arrResults->AddAt(fBo,1);
+  
+  
+  // =======
+  //   2.
+  // =======
+  // Fit the whole spectrum with peak and background
+  TF1 *fSB = new TF1("bgrd_peak_fit",MinvFun,fFitMin,fFitMax,nMinv);
+  fSB->FixParameter(0, fPolDeg);
+  fSB->SetParameter(1, peakScale);
+  // copy the polynomial parameters
+  for (Int_t iPar=0; iPar<=fPolDeg; iPar++) 
+       fSB->SetParameter(2+iPar, fBo->GetParameter(iPar+1));
+  hMinv->Fit(fSB,"0qR");
+  arrResults->AddAt(fSB,2);
+  
+  
+  // =======
+  //   3.
+  // =======
+  // Create the background function
+  TF1 *fB = new TF1("bgrdOnly_fkt",BgndFun,fFitMin,fFitMax,nBgnd);
+  fB->FixParameter(0,fPolDeg);
+  for (Int_t iDeg=0; iDeg<=fPolDeg; iDeg++) {
+       fB->SetParameter(1+iDeg,fSB->GetParameter(2+iDeg));
+       fB->SetParError(1+iDeg,fSB->GetParError(2+iDeg));
+  }
+  // create background histogram from background function
+  hBgrd->Eval(fB);
+  hBgrd->Fit(fB,"0qR");
+  // calculate the integral and integral error from fit function
+  Double_t intc = fB->Integral(intAreaEdgeLo, intAreaEdgeHi) * norm;
+  Double_t inte = fB->IntegralError(intAreaEdgeLo, intAreaEdgeHi) * norm;
+  arrResults->AddAt(fB,3);
+
+  // Fill the background spectrum erros. Use the error from the fit function for the background fB
+  for (Int_t iBin = 0; iBin <= hBgrd->GetNbinsX(); iBin++) {
+    Double_t x = hBgrd->GetBinCenter(iBin);
+    if ((x >= fFitMin) && (x <= fFitMax)) {
+         Double_t binte = inte / TMath::Sqrt((binIntHi-binIntLo)+1);
+         hBgrd->SetBinError(iBin,binte); 
+    }
+  }
+  arrResults->AddAt(hBgrd,4);
+  
+  // =======
+  //   4.
+  // =======
+  // Subtract the background  
+  hSigF->Add(hMinv,hBgrd,1.0,-1.0);
+  for (Int_t iBin = 0; iBin <= hSigF->GetNbinsX(); iBin++) {
+    Double_t x = hSigF->GetBinCenter(iBin);
+    if ((x < fFitMin) || (x > fFitMax)) {
+      hSigF->SetBinContent(iBin,0.0);
+      hSigF->SetBinError(iBin,0.0);
+    }
+  }
+  hSigF->SetNameTitle("peak_only","");
+  arrResults->AddAt(hSigF,5);
+  
+  // =======
+  //   5.
+  // =======
+  // Fit the background-subtracted spectrum
+  TF1 *fS  = new TF1("peakOnly_fit",PeakFunCB,fFitMin,fFitMax,5);
+  fS->SetParameters(-.05,1,kJPMass,.003,700);
+  fS->SetParNames("alpha","n","meanx","sigma","N");
+  hSigF->Fit(fS,"0qR");
+  arrResults->AddAt(fS,6);
+  
+  
+  // connect data members 
+  fFuncSignal     = (TF1*) arrResults->At(6)->Clone();
+  fFuncBackground = (TF1*) arrResults->At(3)->Clone();
+  fFuncSigBack    = (TF1*) arrResults->At(2)->Clone();
+  fHistSignal     = (TH1F*)arrResults->At(5)->Clone();
+  fHistBackground = (TH1F*)arrResults->At(4)->Clone();
+  
+  // fit results
+  Double_t chi2 = fSB->GetChisquare();
+  Int_t    ndf  = fSB->GetNDF();
+  fChi2Dof = chi2/ndf;
+  
+  // signal + signal error
+  fValues(0) = hSigF->IntegralAndError(binIntLo, binIntHi, fErrors(0));
+  fValues(1) = intc; // background
+  fErrors(1) = inte; // background error
+  // S/B (2) and significance (3)
+  SetSignificanceAndSOB();
+  fValues(4) = fS->GetParameter(2); // mass
+  fErrors(4) = fS->GetParError(2);  // mass error
+  fValues(5) = fS->GetParameter(3); // mass wdth
+  fErrors(5) = fS->GetParError(3);  // mass wdth error
+  
+    
+  delete arrResults;
+  
+}
+//______________________________________________________________________________
+Double_t AliDielectronSignalFunc::BgndFun(const Double_t *x, const Double_t *par) {
+  // parameters
+  // [0]:   degree of polynomial
+  // [1]:   constant polynomial coefficient
+  // [2]..: higher polynomial coefficients
+  
+  Int_t    deg   = ((Int_t) par[0]);
+  
+  Double_t f     = 0.0;
+  Double_t yy    = 1.0;
+  Double_t xx    = x[0];
+
+  for (Int_t i = 0; i <= deg; i++) {
+    f  += par[i+1] * yy;
+    yy *= xx;
+  } 
+  
+    
+  return f;
+}
+//______________________________________________________________________________
+Double_t AliDielectronSignalFunc::PeakFun(const Double_t *x, const Double_t *par) {
+  // Fit MC signal shape
+  // parameters
+  // [0]:   scale for simpeak
+  
+  Double_t xx  = x[0];
+  
+  TH1F *hPeak = fgHistSimPM;
+  if (!hPeak) {
+    printf("F-AliDielectronSignalFunc::PeakFun: No histogram for peak fit defined!\n");
+  }
+  
+  Int_t idx = hPeak->FindBin(xx);
+  if ((idx <= 1) ||
+      (idx >= hPeak->GetNbinsX())) {
+    return 0.0;
+  }
+  
+  return (par[0] * hPeak->GetBinContent(idx));
+  
+}
+
+//______________________________________________________________________________
+Double_t AliDielectronSignalFunc::MinvFun(const Double_t *x, const Double_t *par) {
+  // parameters
+  // [0]:   degree of polynomial             -> [0]   for BgndFun
+  // [1]:   scale for simpeak                -> [0]   for PeakFun
+  // [2]:   constant polynomial coefficient  -> [1]   for BgndFun
+  // [3]..: higher polynomial coefficients   -> [2].. for BgndFun
+  
+  Int_t    deg = ((Int_t) par[0]);
+  Double_t parPK[25], parBG[25];
+  
+  parBG[0] = par[0]; // degree of polynomial
+  
+  parPK[0] = par[1]; // MC minv scale
+  for (Int_t i = 0; i <= deg; i++) parBG[i+1] = par[i+2]; // polynomial coefficients
+  
+  Double_t peak = PeakFun(x,parPK);
+  Double_t bgnd = BgndFun(x,parBG);
+  Double_t f    = peak + bgnd;
+  
+  return f;
+}
+
+//______________________________________________________________________________
+Double_t AliDielectronSignalFunc::PeakFunCB(const Double_t *x, const Double_t *par) {
+  // Crystal Ball function fit
+  
+  Double_t alpha = par[0];
+  Double_t     n = par[1];
+  Double_t meanx = par[2];
+  Double_t sigma = par[3];
+  Double_t    nn = par[4];
+   
+  Double_t a = TMath::Power((n/TMath::Abs(alpha)), n) * TMath::Exp(-.5*alpha*alpha);
+  Double_t b = n/TMath::Abs(alpha) - TMath::Abs(alpha);
+  
+  Double_t arg = (x[0] - meanx)/sigma;
+  Double_t fitval = 0;
+  
+  if (arg > -1.*alpha) {
+    fitval = nn * TMath::Exp(-.5*arg*arg);
+  } else {
+    fitval = nn * a * TMath::Power((b-arg), (-1*n));
+  }
+  
+  return fitval;
+}
+
 
 //______________________________________________
 void AliDielectronSignalFunc::ProcessFit(TObjArray * const arrhist) {
@@ -126,10 +435,10 @@ void AliDielectronSignalFunc::ProcessFit(TObjArray * const arrhist) {
   if(fRebin>1)
     fHistDataPM->Rebin(fRebin);
   
-  fHistSignal = new TH1F("HistSignal", "Like-Sign substracted signal",
+  fHistSignal = new TH1F("HistSignal", "Fit substracted signal",
                          fHistDataPM->GetXaxis()->GetNbins(),
                          fHistDataPM->GetXaxis()->GetXmin(), fHistDataPM->GetXaxis()->GetXmax());
-  fHistBackground = new TH1F("HistBackground", "Like-sign contribution",
+  fHistBackground = new TH1F("HistBackground", "Fit contribution",
                              fHistDataPM->GetXaxis()->GetNbins(),
                              fHistDataPM->GetXaxis()->GetXmin(), fHistDataPM->GetXaxis()->GetXmax());
   
@@ -449,7 +758,7 @@ void AliDielectronSignalFunc::Draw(const Option_t* option)
   } else {
     grSig->Draw("f");
   }
-  if(fMethod==kFitted) grBack->Draw("f");
+  if(fMethod==kFitted || fMethod==kFittedMC) grBack->Draw("f");
   fFuncSigBack->Draw("same");
   fFuncSigBack->SetLineWidth(2);
   if(fMethod==kLikeSign) {
@@ -461,7 +770,7 @@ void AliDielectronSignalFunc::Draw(const Option_t* option)
     fHistDataMM->Draw("same");
   }
   
-  if(fMethod==kFitted)
+  if(fMethod==kFitted || fMethod==kFittedMC)
     fFuncBackground->Draw("same");
   
   if (optStat) DrawStats();
index 3797350..c8efe5a 100644 (file)
@@ -66,7 +66,6 @@
   signalProcess->Print();
 */
 
-
 #include <TVectorT.h>
 #include <TString.h>
 #include <TH1F.h>
@@ -83,6 +82,9 @@ public:
   virtual ~AliDielectronSignalFunc();
 
   virtual void Process(TObjArray * const arrhist);
+  void ProcessFitIKF(TObjArray * const arrhist);      // fit the SE +- distribution with mc shape and best chi2/dof
+  void FitOneMinv(TH1F *hMinv, TH1F *hSim, Int_t pod); // fit procedure for one single minv spectrum
+    
   void ProcessFit(TObjArray * const arrhist);      // fit the SE +- distribution
   void ProcessLS(TObjArray * const arrhist);       // substract the fitted SE like-sign background
   void ProcessEM(TObjArray * const arrhist);       // substract the fitted SE+ME like-sign background
@@ -100,9 +102,18 @@ public:
   TF1*  GetBackgroundFunction() const { return fFuncBackground;    }
   TF1*  GetCombinedFunction()   const { return fFuncSigBack;       }
   
+  Int_t GetPolDeg()             const { return fPolDeg;            }
+  Double_t GetChi2Dof()         const { return fChi2Dof;           }
+  
   virtual void Draw(const Option_t* option = "");
   
 private:
+  
+  static Double_t BgndFun(const Double_t *x, const Double_t *par); // polynomial fit function
+  static Double_t PeakFun(const Double_t *x, const Double_t *par); // create peak function from mc shape
+  static Double_t MinvFun(const Double_t *x, const Double_t *par); // combined function of BgndFun + PeakFun
+  static Double_t PeakFunCB(const Double_t *x, const Double_t *par); // crystal ball function for background-subtracted peak fit
+  
 
   TF1 *fFuncSignal;                // Function for the signal description
   TF1 *fFuncBackground;            // Function for the background description
@@ -113,6 +124,10 @@ private:
   TString fFitOpt;             // fit option used
   Bool_t fUseIntegral;         // use the integral of the fitted functions to extract signal and background
 
+  Int_t    fPolDeg;                // polynomial degree of the background function
+  Double_t fChi2Dof;               // chi2/dof of the fitted inv mass spectra
+  static TH1F* fgHistSimPM;         // simulated peak shape 
+  
   ClassDef(AliDielectronSignalFunc,2)         // Dielectron SignalFunc
 };
 
index 991500b..2d9aea5 100644 (file)
@@ -41,6 +41,12 @@ AliDielectronSignalMC::AliDielectronSignalMC() :
   fMother2(0),
   fGrandMother1(0),
   fGrandMother2(0),
+  fLeg1Exclude(kFALSE),      
+  fLeg2Exclude(kFALSE),         
+  fMother1Exclude(kFALSE),       
+  fMother2Exclude(kFALSE),   
+  fGrandMother1Exclude(kFALSE),
+  fGrandMother2Exclude(kFALSE),
   fLeg1Source(kDontCare),
   fLeg2Source(kDontCare),
   fMother1Source(kDontCare),
@@ -71,6 +77,12 @@ AliDielectronSignalMC::AliDielectronSignalMC(const Char_t* name, const Char_t* t
   fMother2(0),
   fGrandMother1(0),
   fGrandMother2(0),
+  fLeg1Exclude(kFALSE),      
+  fLeg2Exclude(kFALSE),         
+  fMother1Exclude(kFALSE),       
+  fMother2Exclude(kFALSE),   
+  fGrandMother1Exclude(kFALSE),
+  fGrandMother2Exclude(kFALSE),
   fLeg1Source(kDontCare),
   fLeg2Source(kDontCare),
   fMother1Source(kDontCare),
index fe72655..efa7fbc 100644 (file)
@@ -5,16 +5,58 @@
 
 
 /*
+   Ionut Cristian Arsene, iarsene@cern.ch
+ */
+
+/*
    Monte Carlo signal definition:
       Leg #1  <-- Mother #1  <--  Grandmother #1
                       |
       Leg #2  <-- Mother #2  <--  Grandmother #2
-   All particles can be classified as:
+  
+   For every leg, mother or grand-mother, a PDG code and a source can be specified.
+
+   1.) For the PDG codes, the PYTHIA standard is used. 
+   A few non-existent PYTHIA codes are used to select more than one PYTHIA code. All these are described below
+   and implemented in AliDielectronMC::ComparePDG() function:
+      0 - default, accepts all PYTHIA codes
+    100 - light unflavoured mesons in the code range 100-199
+    200 -        --"--                               200-299
+    300 - strange mesons in the code range           300-399
+    400 - charmed mesons in the code range           400-499
+    401 - open charm mesons (all D and D* mesons)    400-439
+    402 - open charm mesons and baryons together     400-439, 4000-4399
+    403 - all charm hadrons (mesons and baryons)     400-499, 4000-4999
+    500 - beauty mesons in the code range            500-599
+    501 - open beauty mesons                         500-549
+    502 - open beauty mesons and baryons             500-549, 5000-5499
+    503 - all beauty hadrons                         500-599, 5000-5999
+   1000 - light unflavoured baryons in the code range 1000-1999
+   2000 -        --"--                                2000-2999
+   3000 - strange baryons in the code range           3000-3999
+   4000 - charmed baryons in the code range           4000-4999
+   4001 - open charm baryons                          4000-4399
+   5000 - beauty baryons in the code range            5000-5999
+   5001 - open beauty baryons                         5000-5499
+
+   2.) If the exclusion flags are turned ON then the PDG codes required and the conventional codes described above
+       are used to exclude the selected particles. 
+
+   3.) If the selection of both charges is switched ON then the PDG codes act on both particles and anti-particles.
+
+   4.) Particles sources implemented:
      1. Primary   - particle originating in the physics event
-     2. Secondary - particle created during the GEANT propagation due to interaction of primaries with the material
-     3. Direct    - particle directly created in the collision (has no mother)
-     4. Secondary - particle which is the product of the decay or reinteraction of another particle
-   The 2 legs can originate from the same or different mother particles.
+     2. FinalState- stable(final state) particles which reach the detector -> according to AliStack::IsPhysicalPrimary() 
+     3. Direct    - primary particle which has no mother (e.g. J/psi's added to pythia MC events via generator cocktails,
+                    particles generated in a sudden freeze-out in thermal models, initial state particles)
+     4. Secondary - particle created during the GEANT propagation due to interaction of final state primaries with the material
+
+   5.) The 2 legs can originate from the same or different mother particles. This can be specified via the SetMotherRelation()
+       method call.
+
+   6.) The filling of the pure MC step can be switched on using SetFillPureMCStep() method call. This should be used
+       with care since at the pure MC information level there is no cut applied and for abundant particles the combinatorics
+       can be very high.
 */
 
 
@@ -23,44 +65,62 @@ class AliDielectronSignalMC : public TNamed {
   
  public:
   enum EBranchRelation {kUndefined=0, kSame, kDifferent};
-  enum ESource {kDontCare=0, kPrimary, kSecondary, kDirect, kDecayProduct};
+  enum ESource {kDontCare=0, kPrimary, kFinalState, kDirect, kSecondary};
   
   AliDielectronSignalMC();
   AliDielectronSignalMC(const Char_t* name, const Char_t* title);
   virtual ~AliDielectronSignalMC();
   
-  void SetLegPDGs(Int_t pdg1, Int_t pdg2)                 {fLeg1 = pdg1; fLeg2 = pdg2;}
-  void SetMotherPDGs(Int_t pdg1, Int_t pdg2)              {fMother1 = pdg1; fMother2 = pdg2;}
-  void SetGrandMotherPDGs(Int_t pdg1, Int_t pdg2)         {fGrandMother1 = pdg1; fGrandMother2 = pdg2;}
-  void SetLegSources(ESource s1, ESource s2)              {fLeg1Source = s1; fLeg2Source = s2;}
-  void SetMotherSources(ESource s1, ESource s2)           {fMother1Source = s1; fMother2Source = s2;}
-  void SetGrandMotherSources(ESource s1, ESource s2)      {fGrandMother1Source = s1; fGrandMother2Source = s2;}
-  void SetCheckBothChargesLegs(Bool_t flag1, Bool_t flag2) {fCheckBothChargesLeg1 = flag1; fCheckBothChargesLeg2 = flag2;}
-  void SetCheckBothChargesMothers(Bool_t flag1, Bool_t flag2) {fCheckBothChargesMother1 = flag1; fCheckBothChargesMother2 = flag2;}
+  void SetLegPDGs(Int_t pdg1, Int_t pdg2, Bool_t exclude1=kFALSE, Bool_t exclude2=kFALSE)  
+    {fLeg1 = pdg1; fLeg2 = pdg2; fLeg1Exclude=exclude1; fLeg2Exclude=exclude2;}
+  void SetMotherPDGs(Int_t pdg1, Int_t pdg2, Bool_t exclude1=kFALSE, Bool_t exclude2=kFALSE)              
+    {fMother1 = pdg1; fMother2 = pdg2; fMother1Exclude=exclude1; fMother2Exclude=exclude2;}
+  void SetGrandMotherPDGs(Int_t pdg1, Int_t pdg2, Bool_t exclude1=kFALSE, Bool_t exclude2=kFALSE)         
+    {fGrandMother1 = pdg1; fGrandMother2 = pdg2; fGrandMother1Exclude=exclude1; fGrandMother2Exclude=exclude2;}
+  void SetLegSources(ESource s1, ESource s2)                       {fLeg1Source = s1;                      fLeg2Source = s2;}
+  void SetMotherSources(ESource s1, ESource s2)                    {fMother1Source = s1;                   fMother2Source = s2;}
+  void SetGrandMotherSources(ESource s1, ESource s2)               {fGrandMother1Source = s1;              fGrandMother2Source = s2;}
+  void SetCheckBothChargesLegs(Bool_t flag1, Bool_t flag2)         {fCheckBothChargesLeg1 = flag1;         fCheckBothChargesLeg2 = flag2;}
+  void SetCheckBothChargesMothers(Bool_t flag1, Bool_t flag2)      {fCheckBothChargesMother1 = flag1;      fCheckBothChargesMother2 = flag2;}
   void SetCheckBothChargesGrandMothers(Bool_t flag1, Bool_t flag2) {fCheckBothChargesGrandMother1 = flag1; fCheckBothChargesGrandMother2 = flag2;}
-  void SetMothersRelation(EBranchRelation relation)       {fMothersRelation = relation;}
-  void SetFillPureMCStep(Bool_t fill=kTRUE)               {fFillPureMCStep = fill;}
-
-  Int_t GetLegPDG(Int_t branch) const                     {return (branch==1 ? fLeg1 : fLeg2);}
-  Int_t GetMotherPDG(Int_t branch) const                  {return (branch==1 ? fMother1 : fMother2);}
-  Int_t GetGrandMotherPDG(Int_t branch) const             {return (branch==1 ? fGrandMother1 : fGrandMother2);}
-  ESource GetLegSource(Int_t branch) const                {return (branch==1 ? fLeg1Source : fLeg2Source);}
-  ESource GetMotherSource(Int_t branch) const             {return (branch==1 ? fMother1Source : fMother2Source);}
-  ESource GetGrandMotherSource(Int_t branch) const        {return (branch==1 ? fGrandMother1Source : fGrandMother2Source);}
-  Bool_t GetCheckBothChargesLegs(Int_t branch) const      {return (branch==1 ? fCheckBothChargesLeg1 : fCheckBothChargesLeg2);}
-  Bool_t GetCheckBothChargesMothers(Int_t branch) const   {return (branch==1 ? fCheckBothChargesMother1 : fCheckBothChargesMother2);}
-  Bool_t GetCheckBothChargesGrandMothers(Int_t branch) const   {return (branch==1 ? fCheckBothChargesGrandMother1 : fCheckBothChargesGrandMother2);}
-  EBranchRelation GetMothersRelation() const              {return fMothersRelation;}
-  Bool_t GetFillPureMCStep() const                        {return fFillPureMCStep;}
+  void SetMothersRelation(EBranchRelation relation)                {fMothersRelation = relation;}
+  void SetFillPureMCStep(Bool_t fill=kTRUE)                        {fFillPureMCStep = fill;}
+
+  Int_t GetLegPDG(Int_t branch)                        const {return (branch==1 ? fLeg1 : fLeg2);}
+  Int_t GetMotherPDG(Int_t branch)                     const {return (branch==1 ? fMother1 : fMother2);}
+  Int_t GetGrandMotherPDG(Int_t branch)                const {return (branch==1 ? fGrandMother1 : fGrandMother2);}
+  Bool_t GetLegPDGexclude(Int_t branch)                const {return (branch==1 ? fLeg1Exclude : fLeg2Exclude);}
+  Bool_t GetMotherPDGexclude(Int_t branch)             const {return (branch==1 ? fMother1Exclude : fMother2Exclude);}
+  Bool_t GetGrandMotherPDGexclude(Int_t branch)        const {return (branch==1 ? fGrandMother1Exclude : fGrandMother2Exclude);}
+  ESource GetLegSource(Int_t branch)                   const {return (branch==1 ? fLeg1Source : fLeg2Source);}
+  ESource GetMotherSource(Int_t branch)                const {return (branch==1 ? fMother1Source : fMother2Source);}
+  ESource GetGrandMotherSource(Int_t branch)           const {return (branch==1 ? fGrandMother1Source : fGrandMother2Source);}
+  Bool_t GetCheckBothChargesLegs(Int_t branch)         const {return (branch==1 ? fCheckBothChargesLeg1 : fCheckBothChargesLeg2);}
+  Bool_t GetCheckBothChargesMothers(Int_t branch)      const {return (branch==1 ? fCheckBothChargesMother1 : fCheckBothChargesMother2);}
+  Bool_t GetCheckBothChargesGrandMothers(Int_t branch) const {return (branch==1 ? fCheckBothChargesGrandMother1 : fCheckBothChargesGrandMother2);}
+  EBranchRelation GetMothersRelation()                 const {return fMothersRelation;}
+  Bool_t GetFillPureMCStep()                           const {return fFillPureMCStep;}
 
  private:
+  // PDG codes for legs, mothers and grand-mothers
   Int_t fLeg1;                        // leg 1 PDG
   Int_t fLeg2;                        // leg 2 PDG
   Int_t fMother1;                     // mother 1 PDG
   Int_t fMother2;                     // mother 2 PDG
   Int_t fGrandMother1;                // grandmother 1 PDG
   Int_t fGrandMother2;                // grandmother 2 PDG
+
+  // Toggle on/off the use of the PDG codes as inclusion or exclusion
+  // Example: if fLeg1=211 and fLeg1Exclude=kTRUE than all codes will be accepted for leg 1 with
+  //          the exception of 211 (pions)
+  Bool_t fLeg1Exclude;                // leg 1 
+  Bool_t fLeg2Exclude;                // leg 2 
+  Bool_t fMother1Exclude;             // mother 1 
+  Bool_t fMother2Exclude;             // mother 2 
+  Bool_t fGrandMother1Exclude;        // grandmother 1 
+  Bool_t fGrandMother2Exclude;        // grandmother 2 
     
+  // Particle sources
   ESource fLeg1Source;