]> git.uio.no Git - u/mrichter/AliRoot.git/commitdiff
First commit of V0 QA Task. A long way from perfect but probably ok to catch early...
authorddobrigk <ddobrigk@f7af4fe6-9843-0410-8265-dc069ae4e863>
Sat, 26 Oct 2013 21:28:02 +0000 (21:28 +0000)
committerddobrigk <ddobrigk@f7af4fe6-9843-0410-8265-dc069ae4e863>
Sat, 26 Oct 2013 21:28:02 +0000 (21:28 +0000)
--- David

PWGLF/CMakelibPWGLFQATasks.pkg
PWGLF/PWGLFQATasksLinkDef.h
PWGLF/QATasks/AliAnalysisTaskQAV0.cxx [new file with mode: 0644]
PWGLF/QATasks/AliAnalysisTaskQAV0.h [new file with mode: 0644]
PWGLF/QATasks/macros/AddTaskQAV0.C [new file with mode: 0644]

index 97332aceaeadfdc14ccdf1172c2b7fe73250ff56..bb099959299d88b5e99e5f41444835c2c5dfaa6d 100644 (file)
@@ -29,6 +29,7 @@
 set ( SRCS  
   QATasks/AliAnalysisTaskQAHighPtDeDx.cxx
   QATasks/AliQAProdMultistrange.cxx
+  QATasks/AliAnalysisTaskQAV0.cxx
 )
 
 string ( REPLACE ".cxx" ".h" HDRS "${SRCS}" )
index fe4621911c88ef393fcc6e5bf6a4018eec102179..4c913021f175f12431546a922805b38bea9df97f 100644 (file)
@@ -6,5 +6,6 @@
 
 #pragma link C++ class AliAnalysisTaskQAHighPtDeDx+;
 #pragma link C++ class AliQAProdMultistrange+;
+#pragma link C++ class AliAnalysisTaskQAV0+;
 
 #endif
diff --git a/PWGLF/QATasks/AliAnalysisTaskQAV0.cxx b/PWGLF/QATasks/AliAnalysisTaskQAV0.cxx
new file mode 100644 (file)
index 0000000..d9ceb3e
--- /dev/null
@@ -0,0 +1,682 @@
+/**************************************************************************
+ * Copyright(c) 1998-1999, 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.                  *
+ **************************************************************************/
+
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//
+// QA Task designed to investigate V0 characteristics in any data
+// 
+// Stripped down and adapted from AliAnalysisTaskExtractV0: 
+// --- smaller, more convenient output for debugging
+// --- optional TH3 list of histos to enable a light-weight analysis
+// --- This code is under development, so...
+//
+//  Please Report Any Bugs! 
+//
+//   --- David Dobrigkeit Chinellato
+//        (david.chinellato@gmail.com)
+//
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+class TTree;
+class TParticle;
+class TVector3;
+
+//class AliMCEventHandler;
+//class AliMCEvent;
+//class AliStack;
+
+class AliESDVertex;
+class AliAODVertex;
+class AliESDv0;
+class AliAODv0;
+
+#include <Riostream.h>
+#include "TList.h"
+#include "TH1.h"
+#include "TH2.h"
+#include "TH3.h"
+#include "THnSparse.h"
+#include "TVector3.h"
+#include "TCanvas.h"
+#include "TMath.h"
+#include "TLegend.h"
+#include "AliLog.h"
+#include "AliCentrality.h"
+#include "AliESDEvent.h"
+#include "AliAODEvent.h"
+#include "AliV0vertexer.h"
+#include "AliCascadeVertexer.h"
+#include "AliESDpid.h"
+#include "AliESDtrack.h"
+#include "AliESDtrackCuts.h"
+#include "AliInputEventHandler.h"
+#include "AliAnalysisManager.h"
+#include "AliMCEventHandler.h"
+
+#include "AliCFContainer.h"
+#include "AliMultiplicity.h"
+
+#include "AliESDcascade.h"
+#include "AliAODcascade.h"
+#include "AliESDUtils.h"
+#include "AliESDHeader.h"
+
+#include "AliAnalysisUtils.h"
+#include "AliAnalysisTaskQAV0.h"
+
+//debugging purposes
+#include "TObjectTable.h"
+
+ClassImp(AliAnalysisTaskQAV0)
+
+AliAnalysisTaskQAV0::AliAnalysisTaskQAV0() 
+  : AliAnalysisTaskSE(), 
+  //Output lists
+  fOutput(0), 
+
+  //Histos
+  fHistEvent(0),
+  fHistTopDCANegToPV(0),
+  fHistTopDCAPosToPV(0),
+  fHistTopDCAV0Daughters(0),
+  fHistTopCosinePA(0),
+  fHistTopV0Radius(0),
+  fHistSelectedTopDCANegToPV(0),
+  fHistSelectedTopDCAPosToPV(0),
+  fHistSelectedTopDCAV0Daughters(0),
+  fHistSelectedTopCosinePA(0),
+  fHistSelectedTopV0Radius(0),
+
+  f2dHistInvMassK0Short(0),
+  f2dHistInvMassLambda(0),
+  f2dHistInvMassAntiLambda(0),
+
+  f2dHistInvMassWithdEdxK0Short(0),
+  f2dHistInvMassWithdEdxLambda(0),
+  f2dHistInvMassWithdEdxAntiLambda(0),
+
+  f2dHistResponseNegativeAsPion(0),
+  f2dHistResponseNegativeAsProton(0),
+  f2dHistResponsePositiveAsPion(0),
+  f2dHistResponsePositiveAsProton(0),
+
+  f2dHistdEdxSignalPionFromLambda(0),
+  f2dHistdEdxSignalProtonFromLambda(0),
+  f2dHistResponsePionFromLambda(0),
+  f2dHistResponseProtonFromLambda(0),
+
+
+  //Task Control / Utils
+  fPIDResponse(0),
+  fkRunV0Vertexer ( kFALSE )
+{
+  // Dummy Constructor
+  for(Int_t iV0selIdx   = 0; iV0selIdx   < 7; iV0selIdx++   ) { fV0Sels          [iV0selIdx   ] = -1.; }
+}
+
+AliAnalysisTaskQAV0::AliAnalysisTaskQAV0(const char *name) 
+  : AliAnalysisTaskSE(name), 
+  //Output lists
+  fOutput(0), 
+
+  //Histos
+  fHistEvent(0),
+  fHistTopDCANegToPV(0),
+  fHistTopDCAPosToPV(0),
+  fHistTopDCAV0Daughters(0),
+  fHistTopCosinePA(0),
+  fHistTopV0Radius(0),
+  fHistSelectedTopDCANegToPV(0),
+  fHistSelectedTopDCAPosToPV(0),
+  fHistSelectedTopDCAV0Daughters(0),
+  fHistSelectedTopCosinePA(0),
+  fHistSelectedTopV0Radius(0),
+
+  f2dHistInvMassK0Short(0),
+  f2dHistInvMassLambda(0),
+  f2dHistInvMassAntiLambda(0),
+
+  f2dHistInvMassWithdEdxK0Short(0),
+  f2dHistInvMassWithdEdxLambda(0),
+  f2dHistInvMassWithdEdxAntiLambda(0),
+
+  f2dHistResponseNegativeAsPion(0),
+  f2dHistResponseNegativeAsProton(0),
+  f2dHistResponsePositiveAsPion(0),
+  f2dHistResponsePositiveAsProton(0),
+
+  f2dHistdEdxSignalPionFromLambda(0),
+  f2dHistdEdxSignalProtonFromLambda(0),
+  f2dHistResponsePionFromLambda(0),
+  f2dHistResponseProtonFromLambda(0),
+
+  //Task Control / Utils
+  fPIDResponse(0),
+  fkRunV0Vertexer ( kFALSE )
+{
+  // Constructor
+  //VERTEXER CUTS
+  // REALLY LOOSE? Be careful when attempting to run over PbPb if fkRunV0Vertexer is set! 
+  fV0VertexerSels[0] =  33.  ;  // max allowed chi2
+  fV0VertexerSels[1] =   0.02;  // min allowed impact parameter for the 1st daughter (LHC09a4 : 0.05)
+  fV0VertexerSels[2] =   0.02;  // min allowed impact parameter for the 2nd daughter (LHC09a4 : 0.05)
+  fV0VertexerSels[3] =   2.0 ;  // max allowed DCA between the daughter tracks       (LHC09a4 : 0.5)
+  fV0VertexerSels[4] =   0.95;  // min allowed cosine of V0's pointing angle         (LHC09a4 : 0.99)
+  fV0VertexerSels[5] =   0.5 ;  // min radius of the fiducial volume                 (LHC09a4 : 0.2)
+  fV0VertexerSels[6] = 200.  ;  // max radius of the fiducial volume                 (LHC09a4 : 100.0)
+
+  //SELECTION CUTS
+  // REALLY LOOSE? Be careful when attempting to run over PbPb if fkRunV0Vertexer is set! 
+  fV0Sels[0] =  33.  ;  // max allowed chi2
+  fV0Sels[1] =   0.02;  // min allowed impact parameter for the 1st daughter (LHC09a4 : 0.05)
+  fV0Sels[2] =   0.02;  // min allowed impact parameter for the 2nd daughter (LHC09a4 : 0.05)
+  fV0Sels[3] =   2.0 ;  // max allowed DCA between the daughter tracks       (LHC09a4 : 0.5)
+  fV0Sels[4] =   0.95;  // min allowed cosine of V0's pointing angle         (LHC09a4 : 0.99)
+  fV0Sels[5] =   0.5 ;  // min radius of the fiducial volume                 (LHC09a4 : 0.2)
+  fV0Sels[6] = 200.  ;  // max radius of the fiducial volume                 (LHC09a4 : 100.0)
+
+  // Output slot #0 writes into a TList container (Lambda Histos and fTree)
+  DefineOutput(1, TList::Class());
+}
+
+
+AliAnalysisTaskQAV0::~AliAnalysisTaskQAV0()
+{
+//------------------------------------------------
+// DESTRUCTOR
+//------------------------------------------------
+
+   if (fOutput){
+      delete fOutput;
+      fOutput = 0x0;
+   }
+}
+
+//________________________________________________________________________
+void AliAnalysisTaskQAV0::UserCreateOutputObjects()
+{
+  //Define Output Lists
+  fOutput = new TList();
+  fOutput->SetOwner(); 
+
+  //Histogram Output: Event-by-Event
+  fHistEvent = new TH1D( "fHistEvent", ";Evt. Sel. Step;Count",4,0,4); 
+  fHistEvent->GetXaxis()->SetBinLabel(1, "Processed");
+  fHistEvent->GetXaxis()->SetBinLabel(2, "Phys-Sel");  
+  fHistEvent->GetXaxis()->SetBinLabel(3, "Has Vtx");  
+  fHistEvent->GetXaxis()->SetBinLabel(4, "Vtx |z|<10cm");  
+  fOutput->Add(fHistEvent); 
+
+  //Topological Selection Histograms, 1D 
+  fHistTopDCANegToPV        = new TH1D( "fHistTopDCANegToPV",";DCA Neg. Daughter to PV (cm);Counts",200,0,1); 
+  fHistTopDCAPosToPV        = new TH1D( "fHistTopDCAPosToPV",";DCA Pos. Daughter to PV (cm);Counts",200,0,1); 
+  fHistTopDCAV0Daughters    = new TH1D( "fHistTopDCAV0Daughters",";DCA V0 Daughters (#sigma);Counts",200,0,2); 
+  fHistTopCosinePA          = new TH1D( "fHistTopCosinePA",";Cosine of PA;Counts",200,-1,1); 
+  fHistTopV0Radius          = new TH1D( "fHistTopV0Radius",";Decay Radius (cm);Counts",200,0.,10);
+
+  fOutput->Add( fHistTopDCANegToPV     );
+  fOutput->Add( fHistTopDCAPosToPV     );
+  fOutput->Add( fHistTopDCAV0Daughters );
+  fOutput->Add( fHistTopCosinePA       );
+  fOutput->Add( fHistTopV0Radius       );
+
+  //Zoomed In 
+  fHistSelectedTopDCANegToPV        = new TH1D( "fHistSelectedTopDCANegToPV",";DCA Neg. Daughter to PV (cm);Counts",200,fV0Sels[1],1); 
+  fHistSelectedTopDCAPosToPV        = new TH1D( "fHistSelectedTopDCAPosToPV",";DCA Pos. Daughter to PV (cm);Counts",200,fV0Sels[2],1); 
+  fHistSelectedTopDCAV0Daughters    = new TH1D( "fHistSelectedTopDCAV0Daughters",";DCA V0 Daughters (#sigma);Counts",200,0,fV0Sels[3]); 
+  fHistSelectedTopCosinePA          = new TH1D( "fHistSelectedTopCosinePA",";Cosine of PA;Counts",200,fV0Sels[4],1); 
+  fHistSelectedTopV0Radius          = new TH1D( "fHistSelectedTopV0Radius",";Decay Radius (cm);Counts",200,fV0Sels[5],10);
+
+  fOutput->Add( fHistSelectedTopDCANegToPV     );
+  fOutput->Add( fHistSelectedTopDCAPosToPV     );
+  fOutput->Add( fHistSelectedTopDCAV0Daughters );
+  fOutput->Add( fHistSelectedTopCosinePA       );
+  fOutput->Add( fHistSelectedTopV0Radius       );
+
+  //Invariant Mass Plots
+  f2dHistInvMassK0Short     = new TH2D( "f2dHistInvMassK0Short"   , ";p_{T};M(#pi^{+},#pi^{-})"   ,250,0,25,500,0.25,0.75);
+  f2dHistInvMassLambda      = new TH2D( "f2dHistInvMassLambda"    , ";p_{T};M(p,#pi^{-})"         ,250,0,25,300,1.07,1.115+0.255);
+  f2dHistInvMassAntiLambda  = new TH2D( "f2dHistInvMassAntiLambda", ";p_{T};M(#pi^{+},#bar{p})"   ,250,0,25,300,1.07,1.115+0.255);
+
+  fOutput->Add( f2dHistInvMassK0Short     );
+  fOutput->Add( f2dHistInvMassLambda      );
+  fOutput->Add( f2dHistInvMassAntiLambda  );
+
+  //Invariant Mass Plots, with dEdx
+  f2dHistInvMassWithdEdxK0Short     = new TH2D( "f2dHistInvMassWithdEdxK0Short"   , ";p_{T};M(#pi^{+},#pi^{-})"   ,250,0,25,500,0.25,0.75);
+  f2dHistInvMassWithdEdxLambda      = new TH2D( "f2dHistInvMassWithdEdxLambda"    , ";p_{T};M(p,#pi^{-})"         ,250,0,25,300,1.07,1.115+0.255);
+  f2dHistInvMassWithdEdxAntiLambda  = new TH2D( "f2dHistInvMassWithdEdxAntiLambda", ";p_{T};M(#pi^{+},#bar{p})"   ,250,0,25,300,1.07,1.115+0.255);
+
+  fOutput->Add( f2dHistInvMassWithdEdxK0Short     );
+  fOutput->Add( f2dHistInvMassWithdEdxLambda      );
+  fOutput->Add( f2dHistInvMassWithdEdxAntiLambda  );
+
+  //dE/dx QA for main analysis and for calibration check 
+  f2dHistResponseNegativeAsPion    = new TH2D( "f2dHistResponseNegativeAsPion", ";p_{T}^{V0};N#sigma",500,0,5,400,-20,20);
+  f2dHistResponseNegativeAsProton  = new TH2D( "f2dHistResponseNegativeAsProton", ";p_{T}^{V0};N#sigma",500,0,5,400,-20,20);
+  f2dHistResponsePositiveAsPion    = new TH2D( "f2dHistResponsePositiveAsPion", ";p_{T}^{V0};N#sigma",500,0,5,400,-20,20);
+  f2dHistResponsePositiveAsProton  = new TH2D( "f2dHistResponsePositiveAsProton", ";p_{T}^{V0};N#sigma",500,0,5,400,-20,20);
+
+  //Clean Signal Check from Lambdas: stricter cuts, raw signal check 
+  f2dHistdEdxSignalPionFromLambda    = new TH2D( "f2dHistdEdxSignalPionFromLambda", ";p_{T}^{V0};TPC Signal",500,0,5,8000,0,800);
+  f2dHistdEdxSignalProtonFromLambda  = new TH2D( "f2dHistdEdxSignalProtonFromLambda", ";p_{T}^{V0};TPC Signal",500,0,5,8000,0,800);
+  f2dHistResponsePionFromLambda      = new TH2D( "f2dHistResponsePionFromLambda", ";p_{T}^{V0};N#sigma",500,0,5,400,-20,20);
+  f2dHistResponseProtonFromLambda    = new TH2D( "f2dHistResponseProtonFromLambda", ";p_{T}^{V0};N#sigma",500,0,5,400,-20,20);
+
+
+  fOutput->Add( f2dHistResponseNegativeAsPion        );
+  fOutput->Add( f2dHistResponseNegativeAsProton      );
+  fOutput->Add( f2dHistResponsePositiveAsPion        );
+  fOutput->Add( f2dHistResponsePositiveAsProton      );
+
+  fOutput->Add( f2dHistdEdxSignalPionFromLambda        );
+  fOutput->Add( f2dHistdEdxSignalProtonFromLambda      );
+  fOutput->Add( f2dHistResponsePionFromLambda          );
+  fOutput->Add( f2dHistResponseProtonFromLambda        );
+
+//------------------------------------------------
+// Particle Identification Setup
+//------------------------------------------------
+
+  AliAnalysisManager *man=AliAnalysisManager::GetAnalysisManager();
+  AliInputEventHandler* inputHandler = (AliInputEventHandler*) (man->GetInputEventHandler());
+  fPIDResponse = inputHandler->GetPIDResponse();
+  
+   //Regular output: Histograms
+   PostData(1, fOutput);
+}// end UserCreateOutputObjects
+
+
+//________________________________________________________________________
+void AliAnalysisTaskQAV0::UserExec(Option_t *) 
+{
+   // Main loop
+   // Called for each event
+   //gObjectTable->Print();
+   AliESDEvent *lESDevent = 0x0;
+
+   //AliAODEvent *lAODevent = 0x0;
+   Int_t    nV0s                        = -1;
+
+   Double_t lTrkgPrimaryVtxPos[3]          = {-100.0, -100.0, -100.0};
+   Double_t lBestPrimaryVtxPos[3]          = {-100.0, -100.0, -100.0};
+   Double_t lMagneticField                 = -10.;
+       
+   // Connect to the InputEvent        
+   // After these lines, we should have an ESD/AOD event + the number of cascades in it.
+
+   // Appropriate for ESD analysis! 
+   lESDevent = dynamic_cast<AliESDEvent*>( InputEvent() );
+   if (!lESDevent) {
+      AliWarning("ERROR: lESDevent not available \n");
+      return;
+   }
+  
+  //------------------------------------------------
+  // Rerun V0 vertexer, if asked for
+  // --- WARNING: Be careful when using in PbPb
+  //------------------------------------------------
+  if( fkRunV0Vertexer ){
+    lESDevent->ResetV0s();
+    AliV0vertexer lV0vtxer;
+    lV0vtxer.SetDefaultCuts(fV0VertexerSels);
+    lV0vtxer.Tracks2V0vertices(lESDevent);
+  }
+
+  fHistEvent->Fill(0.5); 
+
+//------------------------------------------------
+// Physics Selection
+//------------------------------------------------
+  
+  // new method
+  UInt_t maskIsSelected = ((AliInputEventHandler*)(AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler()))->IsEventSelected();
+  Bool_t isSelected = 0;
+  isSelected = (maskIsSelected & AliVEvent::kMB) == AliVEvent::kMB;
+  
+  //pA triggering: CINT7
+  //if( fkSwitchINT7 ) isSelected = (maskIsSelected & AliVEvent::kINT7) == AliVEvent::kINT7;
+
+  //Standard Min-Bias Selection
+  if ( !isSelected ) {
+    PostData(1, fOutput);
+    return;
+  }
+  fHistEvent->Fill(1.5); 
+  
+//------------------------------------------------
+// After Trigger Selection
+//------------------------------------------------
+
+
+       nV0s = lESDevent->GetNumberOfV0s();
+  
+//------------------------------------------------
+// Getting: Primary Vertex + MagField Info
+//------------------------------------------------
+
+       const AliESDVertex *lPrimaryTrackingESDVtx = lESDevent->GetPrimaryVertexTracks();
+       // get the vtx stored in ESD found with tracks
+       lPrimaryTrackingESDVtx->GetXYZ( lTrkgPrimaryVtxPos );
+        
+       const AliESDVertex *lPrimaryBestESDVtx = lESDevent->GetPrimaryVertex(); 
+  // get the best primary vertex available for the event
+       // As done in AliCascadeVertexer, we keep the one which is the best one available.
+       // between : Tracking vertex > SPD vertex > TPC vertex > default SPD vertex
+       // This one will be used for next calculations (DCA essentially)
+   lPrimaryBestESDVtx->GetXYZ( lBestPrimaryVtxPos );
+
+   Double_t tPrimaryVtxPosition[3];
+   const AliVVertex *primaryVtx = lESDevent->GetPrimaryVertex();
+   tPrimaryVtxPosition[0] = primaryVtx->GetX();
+   tPrimaryVtxPosition[1] = primaryVtx->GetY();
+   tPrimaryVtxPosition[2] = primaryVtx->GetZ();
+
+  //------------------------------------------------
+  // Primary Vertex Requirements Section:
+  //  ---> pp and PbPb: Only requires |z|<10cm
+  //  ---> pPb: all requirements checked at this stage
+  //------------------------------------------------
+  
+  //Roberto's PV selection criteria, implemented 17th April 2013
+  
+  // vertex selection 
+  Bool_t fHasVertex = kFALSE;
+  const AliESDVertex *vertex = lESDevent->GetPrimaryVertexTracks();
+  if (vertex->GetNContributors() < 1) {
+    vertex = lESDevent->GetPrimaryVertexSPD();
+    if (vertex->GetNContributors() < 1) fHasVertex = kFALSE;
+    else fHasVertex = kTRUE;
+    TString vtxTyp = vertex->GetTitle();
+    Double_t cov[6]={0};
+    vertex->GetCovarianceMatrix(cov);
+    Double_t zRes = TMath::Sqrt(cov[5]);
+    if (vtxTyp.Contains("vertexer:Z") && (zRes>0.25)) fHasVertex = kFALSE;
+  }
+  else fHasVertex = kTRUE;
+  
+  //Is First event in chunk rejection: Still present!
+  if(fHasVertex == kFALSE) {
+    AliWarning("Pb / | PV does not satisfy selection criteria!");
+    PostData(1, fOutput);
+    return;
+  }
+  
+  fHistEvent->Fill(2.5); 
+
+  //17 April Fix: Always do primary vertex Z selection, after pA vertex selection from Roberto
+  if(TMath::Abs(lBestPrimaryVtxPos[2]) > 10.0) {
+    AliWarning("Pb / | Z position of Best Prim Vtx | > 10.0 cm ... return !");
+    PostData(1, fOutput);
+    return;
+  }
+
+  fHistEvent->Fill(3.5); 
+  
+  lMagneticField = lESDevent->GetMagneticField( );
+
+//------------------------------------------------
+// Only look at events with well-established PV
+//------------------------------------------------
+       
+   //const AliESDVertex *lPrimaryTrackingESDVtxCheck = lESDevent->GetPrimaryVertexTracks();
+   const AliESDVertex *lPrimarySPDVtx = lESDevent->GetPrimaryVertexSPD();
+   //if (!lPrimarySPDVtx->GetStatus() && !lPrimaryTrackingESDVtxCheck->GetStatus() ){
+   //   AliWarning("Pb / No SPD prim. vertex nor prim. Tracking vertex ... return !");
+   //   PostData(1, fOutput);
+   //   return;
+   //}
+  
+
+
+//------------------------------------------------
+// MAIN LAMBDA LOOP STARTS HERE
+//------------------------------------------------
+
+//Variable definition
+  Int_t    lOnFlyStatus = 0;// nv0sOn = 0, nv0sOff = 0;
+  Double_t lChi2V0 = 0;
+  Double_t lDcaV0Daughters = 0, lDcaV0ToPrimVertex = 0;
+  Double_t lDcaPosToPrimVertex = 0, lDcaNegToPrimVertex = 0;
+  Double_t lV0CosineOfPointingAngle = 0;
+  Double_t lV0Radius = 0, lPt = 0;
+  Double_t lRapK0Short = 0, lRapLambda = 0;
+  Double_t lInvMassK0s = 0, lInvMassLambda = 0, lInvMassAntiLambda = 0;
+  Double_t lAlphaV0 = 0, lPtArmV0 = 0;
+  Double_t lNegEta = -100, lPosEta = -100;
+  Double_t fMinV0Pt = 0; 
+  Double_t fMaxV0Pt = 100; 
+
+   Int_t nv0s = 0;
+   nv0s = lESDevent->GetNumberOfV0s();
+
+   //for (Int_t iV0 = 0; iV0 < nv0s; iV0++) 
+   for (Int_t iV0 = 0; iV0 < nv0s; iV0++) //extra-crazy test
+   {// This is the begining of the V0 loop
+      AliESDv0 *v0 = ((AliESDEvent*)lESDevent)->GetV0(iV0);
+      if (!v0) continue;
+
+      //Only use Offline Candidates for QA       
+      lOnFlyStatus = v0->GetOnFlyStatus();
+      if( lOnFlyStatus == kTRUE ) continue; 
+
+      Double_t tDecayVertexV0[3]; v0->GetXYZ(tDecayVertexV0[0],tDecayVertexV0[1],tDecayVertexV0[2]); 
+
+      Double_t tV0mom[3];
+      v0->GetPxPyPz( tV0mom[0],tV0mom[1],tV0mom[2] ); 
+      Double_t lV0TotalMomentum = TMath::Sqrt(
+      tV0mom[0]*tV0mom[0]+tV0mom[1]*tV0mom[1]+tV0mom[2]*tV0mom[2] );
+
+      lV0Radius = TMath::Sqrt(tDecayVertexV0[0]*tDecayVertexV0[0]+tDecayVertexV0[1]*tDecayVertexV0[1]);
+
+      lPt = v0->Pt();
+      lRapK0Short = v0->RapK0Short();
+      lRapLambda  = v0->RapLambda();
+      if ((lPt<fMinV0Pt)||(fMaxV0Pt<lPt)) continue;
+
+      UInt_t lKeyPos = (UInt_t)TMath::Abs(v0->GetPindex());
+      UInt_t lKeyNeg = (UInt_t)TMath::Abs(v0->GetNindex());
+
+      Double_t lMomPos[3]; v0->GetPPxPyPz(lMomPos[0],lMomPos[1],lMomPos[2]);
+      Double_t lMomNeg[3]; v0->GetNPxPyPz(lMomNeg[0],lMomNeg[1],lMomNeg[2]);
+
+      AliESDtrack *pTrack=((AliESDEvent*)lESDevent)->GetTrack(lKeyPos);
+      AliESDtrack *nTrack=((AliESDEvent*)lESDevent)->GetTrack(lKeyNeg);
+      if (!pTrack || !nTrack) {
+         Printf("ERROR: Could not retreive one of the daughter track");
+         continue;
+      }
+
+      //Daughter Eta for Eta selection, afterwards
+      lNegEta = nTrack->Eta();
+      lPosEta = pTrack->Eta();
+
+      // Filter like-sign V0 (next: add counter and distribution)
+      if ( pTrack->GetSign() == nTrack->GetSign()){
+         continue;
+      } 
+
+      //________________________________________________________________________
+      // Track quality cuts 
+      Float_t lPosTrackCrossedRows = pTrack->GetTPCClusterInfo(2,1);
+      Float_t lNegTrackCrossedRows = nTrack->GetTPCClusterInfo(2,1);
+      Int_t lLeastNbrCrossedRows = (Int_t) lPosTrackCrossedRows;
+      if( lNegTrackCrossedRows < lLeastNbrCrossedRows )
+         lLeastNbrCrossedRows = (Int_t) lNegTrackCrossedRows;
+
+      // TPC refit condition (done during reconstruction for Offline but not for On-the-fly)
+      if( !(pTrack->GetStatus() & AliESDtrack::kTPCrefit)) continue;
+      if( !(nTrack->GetStatus() & AliESDtrack::kTPCrefit)) continue;
+     
+      //Get status flags
+      //lPosTrackStatus = pTrack->GetStatus();
+      //lNegTrackStatus = nTrack->GetStatus();
+     
+      if ( ( ( pTrack->GetTPCClusterInfo(2,1) ) < 70 ) || ( ( nTrack->GetTPCClusterInfo(2,1) ) < 70 ) ) continue;
+       
+      //GetKinkIndex condition
+      if( pTrack->GetKinkIndex(0)>0 || nTrack->GetKinkIndex(0)>0 ) continue;
+
+      //Findable clusters > 0 condition
+      if( pTrack->GetTPCNclsF()<=0 || nTrack->GetTPCNclsF()<=0 ) continue;
+
+      //Compute ratio Crossed Rows / Findable clusters
+      //Note: above test avoids division by zero! 
+      Float_t lPosTrackCrossedRowsOverFindable = lPosTrackCrossedRows / ((double)(pTrack->GetTPCNclsF())); 
+      Float_t lNegTrackCrossedRowsOverFindable = lNegTrackCrossedRows / ((double)(nTrack->GetTPCNclsF())); 
+
+      Float_t lLeastRatioCrossedRowsOverFindable = lPosTrackCrossedRowsOverFindable;
+      if( lNegTrackCrossedRowsOverFindable < lLeastRatioCrossedRowsOverFindable )
+         lLeastRatioCrossedRowsOverFindable = lNegTrackCrossedRowsOverFindable;
+
+      //Lowest Cut Level for Ratio Crossed Rows / Findable = 0.8, set here
+      if ( lLeastRatioCrossedRowsOverFindable < 0.8 ) continue;
+
+      //End track Quality Cuts
+      //________________________________________________________________________
+
+      lDcaPosToPrimVertex = TMath::Abs(pTrack->GetD(tPrimaryVtxPosition[0],
+                                                       tPrimaryVtxPosition[1],
+                                                       lMagneticField) );
+
+      lDcaNegToPrimVertex = TMath::Abs(nTrack->GetD(tPrimaryVtxPosition[0],
+                                                       tPrimaryVtxPosition[1],
+                                                       lMagneticField) );
+
+
+      lChi2V0 = v0->GetChi2V0();
+      lDcaV0Daughters = v0->GetDcaV0Daughters();
+      lDcaV0ToPrimVertex = v0->GetD(tPrimaryVtxPosition[0],tPrimaryVtxPosition[1],tPrimaryVtxPosition[2]);
+      lV0CosineOfPointingAngle = v0->GetV0CosineOfPointingAngle(tPrimaryVtxPosition[0],tPrimaryVtxPosition[1],tPrimaryVtxPosition[2]);
+      //fTreeVariableV0CosineOfPointingAngle=lV0CosineOfPointingAngle;
+
+      // Getting invariant mass infos directly from ESD
+      v0->ChangeMassHypothesis(310);
+      lInvMassK0s = v0->GetEffMass();
+      v0->ChangeMassHypothesis(3122);
+      lInvMassLambda = v0->GetEffMass();
+      v0->ChangeMassHypothesis(-3122);
+      lInvMassAntiLambda = v0->GetEffMass();
+      lAlphaV0 = v0->AlphaV0();
+      lPtArmV0 = v0->PtArmV0();
+      
+      //Official means of acquiring N-sigmas 
+      Float_t lNSigmasPosProton = fPIDResponse->NumberOfSigmasTPC( pTrack, AliPID::kProton );
+      Float_t lNSigmasPosPion   = fPIDResponse->NumberOfSigmasTPC( pTrack, AliPID::kPion );
+      Float_t lNSigmasNegProton = fPIDResponse->NumberOfSigmasTPC( nTrack, AliPID::kProton );
+      Float_t lNSigmasNegPion   = fPIDResponse->NumberOfSigmasTPC( nTrack, AliPID::kPion );
+
+//This requires an Invariant Mass Hypothesis afterwards
+      Float_t lDistOverTotMom = TMath::Sqrt(
+                                               TMath::Power( tDecayVertexV0[0] - lBestPrimaryVtxPos[0] , 2) +
+                                               TMath::Power( tDecayVertexV0[1] - lBestPrimaryVtxPos[1] , 2) +
+                                               TMath::Power( tDecayVertexV0[2] - lBestPrimaryVtxPos[2] , 2)
+                                       );
+      lDistOverTotMom /= (lV0TotalMomentum+1e-10); //avoid division by zero, to be sure
+
+//------------------------------------------------
+// Fill Main Output Histograms
+//------------------------------------------------
+
+  //Topological Variable Checks, One-Dimensional      
+  fHistTopDCANegToPV      -> Fill( lDcaNegToPrimVertex      ) ; 
+  fHistTopDCAPosToPV      -> Fill( lDcaPosToPrimVertex      ) ; 
+  fHistTopDCAV0Daughters  -> Fill( lDcaV0Daughters          ) ; 
+  fHistTopCosinePA        -> Fill( lV0CosineOfPointingAngle ) ; 
+  fHistTopV0Radius        -> Fill( lV0Radius                ) ; 
+
+
+  if( lDcaNegToPrimVertex > fV0Sels[1] && lDcaPosToPrimVertex > fV0Sels[2]      && 
+      lDcaV0Daughters     < fV0Sels[3] && lV0CosineOfPointingAngle > fV0Sels[4] &&
+      lV0Radius           > fV0Sels[5] && lV0Radius < fV0Sels [6] ){ 
+
+    //Topological Variables zoomed in at selection level (whatever that may be)
+    //May be slightly redundant if no specific extra configuration was done 
+    fHistSelectedTopDCANegToPV      -> Fill( lDcaNegToPrimVertex      ) ; 
+    fHistSelectedTopDCAPosToPV      -> Fill( lDcaPosToPrimVertex      ) ; 
+    fHistSelectedTopDCAV0Daughters  -> Fill( lDcaV0Daughters          ) ; 
+    fHistSelectedTopCosinePA        -> Fill( lV0CosineOfPointingAngle ) ; 
+    fHistSelectedTopV0Radius        -> Fill( lV0Radius                ) ; 
+
+    //Specific fV0Sel selection level, but no dEdx applied 
+    f2dHistInvMassK0Short     -> Fill ( lPt , lInvMassK0s        )   ; 
+    f2dHistInvMassLambda      -> Fill ( lPt , lInvMassLambda     )   ;
+    f2dHistInvMassAntiLambda  -> Fill ( lPt , lInvMassAntiLambda )   ;
+
+    //General dE/dx QA 
+    f2dHistResponseNegativeAsPion     -> Fill( lPt, lNSigmasNegPion      ); 
+    f2dHistResponseNegativeAsProton   -> Fill( lPt, lNSigmasNegProton    ); 
+    f2dHistResponsePositiveAsPion     -> Fill( lPt, lNSigmasPosPion      ); 
+    f2dHistResponsePositiveAsProton   -> Fill( lPt, lNSigmasPosProton    ); 
+
+    //Clean Sample From Lambdas
+    //Very strict cuts to ensure dealing with good Lambdas 
+    if ( lDcaV0Daughters < 1.0 && lV0CosineOfPointingAngle > 0.999 && TMath::Abs( lInvMassK0s - 0.497614 ) > 0.012 
+          && TMath::Abs( lInvMassAntiLambda - 1.115683) > 0.08 && TMath::Abs( lInvMassLambda - 1.115683) < 0.002 ) { 
+      
+      f2dHistdEdxSignalPionFromLambda     -> Fill( lPt, nTrack-> GetTPCsignal() );
+      f2dHistdEdxSignalProtonFromLambda   -> Fill( lPt, pTrack-> GetTPCsignal() );
+      f2dHistResponsePionFromLambda     -> Fill( lPt, lNSigmasNegPion   );
+      f2dHistResponseProtonFromLambda   -> Fill( lPt, lNSigmasPosProton );      
+    }
+
+    //Specific fV0Sel selection level, dE/dx applied
+    if ( TMath::Abs(lNSigmasPosPion)   < 5 && TMath::Abs(lNSigmasNegPion)   < 5 )    f2dHistInvMassWithdEdxK0Short       -> Fill ( lPt , lInvMassK0s        )   ;
+    if ( TMath::Abs(lNSigmasPosProton) < 5 && TMath::Abs(lNSigmasNegPion)   < 5 )    f2dHistInvMassWithdEdxLambda        -> Fill ( lPt , lInvMassLambda     )   ;
+    if ( TMath::Abs(lNSigmasPosPion)   < 5 && TMath::Abs(lNSigmasNegProton) < 5 )    f2dHistInvMassWithdEdxAntiLambda    -> Fill ( lPt , lInvMassAntiLambda )   ;
+
+    
+
+
+  }
+
+
+  //Topological Variable Checks, Two-Dimensional 
+
+//------------------------------------------------
+// End Filling of main Histograms
+//------------------------------------------------
+
+  }// This is the end of the V0 loop
+
+
+  // Post output data.
+  PostData(1, fOutput);
+
+}
+
+//________________________________________________________________________
+void AliAnalysisTaskQAV0::Terminate(Option_t *)
+{
+   // Draw result to the screen
+   // Called once at the end of the query
+   // This will draw the V0 candidate multiplicity, whose 
+   // number of entries corresponds to the number of triggered events. 
+   TList *cRetrievedList = 0x0;
+   cRetrievedList = (TList*)GetOutputData(1);
+   if(!cRetrievedList){
+      Printf("ERROR - AliAnalysisTaskQAV0 : ouput data container list not available\n");
+      return;
+   }           
+   fHistEvent = dynamic_cast<TH1D*> (  cRetrievedList->FindObject("fHistEvent")  );
+   if (!fHistEvent) {
+      Printf("ERROR - AliAnalysisTaskQAV0 : fHistEvent not available");
+      return;
+   }
+   TCanvas *canCheck = new TCanvas("AliAnalysisTaskQAV0","V0 Multiplicity",10,10,510,510);
+   canCheck->cd(1)->SetLogy();
+   fHistEvent->SetMarkerStyle(22);
+   fHistEvent->DrawCopy("E");
+}
diff --git a/PWGLF/QATasks/AliAnalysisTaskQAV0.h b/PWGLF/QATasks/AliAnalysisTaskQAV0.h
new file mode 100644 (file)
index 0000000..1bf8d5d
--- /dev/null
@@ -0,0 +1,150 @@
+#ifndef AliAnalysisTaskQAV0_H
+#define AliAnalysisTaskQAV0_H
+
+/**************************************************************************
+ * Copyright(c) 1998-1999, 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.                  *
+ **************************************************************************/
+
+//-----------------------------------------------------------------
+//      AliAnalysisTaskQAV0 class
+//      -------------------------
+//
+//    Please see cxx file for more details.   
+//             
+//-----------------------------------------------------------------
+
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//
+// --- This version: 23 Oct 2013
+//
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+class TList;
+class TH1F;
+class TH2F;
+class TH3F;
+class TVector3;
+class THnSparse;
+
+class AliESDpid;
+class AliESDtrackCuts;
+class AliAnalysisUtils;
+class AliESDEvent;
+class AliPhysicsSelection;
+class AliCFContainer;
+
+//#include "TString.h"
+//#include "AliESDtrackCuts.h"
+#include "AliAnalysisTaskSE.h"
+
+class AliAnalysisTaskQAV0 : public AliAnalysisTaskSE {
+ public:
+       AliAnalysisTaskQAV0();
+       AliAnalysisTaskQAV0(const char *name);
+       virtual ~AliAnalysisTaskQAV0();
+       
+       virtual void     UserCreateOutputObjects();
+       virtual void     UserExec(Option_t *option);
+       virtual void     Terminate(Option_t *);
+
+//---------------------------------------------------------------------------------------
+  //Task Configuration: Meant to enable quick re-execution of vertexer if needed
+  void SetRunV0Vertexer ( Bool_t lRunV0Vertexer = kTRUE) { fkRunV0Vertexer = lRunV0Vertexer; }
+//---------------------------------------------------------------------------------------
+//Setters for the V0 Vertexer Parameters
+  void SetV0VertexerMaxChisquare   ( Double_t lParameter ){ fV0VertexerSels[0] = lParameter; }
+  void SetV0VertexerDCAFirstToPV   ( Double_t lParameter ){ fV0VertexerSels[1] = lParameter; }
+  void SetV0VertexerDCASecondtoPV  ( Double_t lParameter ){ fV0VertexerSels[2] = lParameter; }
+  void SetV0VertexerDCAV0Daughters ( Double_t lParameter ){ fV0VertexerSels[3] = lParameter; }
+  void SetV0VertexerCosinePA       ( Double_t lParameter ){ fV0VertexerSels[4] = lParameter; }
+  void SetV0VertexerMinRadius      ( Double_t lParameter ){ fV0VertexerSels[5] = lParameter; }
+  void SetV0VertexerMaxRadius      ( Double_t lParameter ){ fV0VertexerSels[6] = lParameter; }
+//---------------------------------------------------------------------------------------
+//Setters for the V0 Extraction
+  void SetV0SelectionMaxChisquare   ( Double_t lParameter ){ fV0Sels[0] = lParameter; }
+  void SetV0SelectionDCAFirstToPV   ( Double_t lParameter ){ fV0Sels[1] = lParameter; }
+  void SetV0SelectionDCASecondtoPV  ( Double_t lParameter ){ fV0Sels[2] = lParameter; }
+  void SetV0SelectionDCAV0Daughters ( Double_t lParameter ){ fV0Sels[3] = lParameter; }
+  void SetV0SelectionCosinePA       ( Double_t lParameter ){ fV0Sels[4] = lParameter; }
+  void SetV0SelectionMinRadius      ( Double_t lParameter ){ fV0Sels[5] = lParameter; }
+  void SetV0SelectionMaxRadius      ( Double_t lParameter ){ fV0Sels[6] = lParameter; }
+//---------------------------------------------------------------------------------------
+  
+ private:
+                               // Note : In ROOT, "//!" means "do not stream the data from Master node to Worker node" ...
+                               // your data member object is created on the worker nodes and streaming is not needed.
+                               // http://root.cern.ch/download/doc/11InputOutput.pdf, page 14
+
+  //Top Structure
+       TList   *fOutput;                     //! List of output objects
+
+  //Per-Event Histograms
+  TH1D* fHistEvent;             //! Event Selection Histogram (no further info)
+
+  //Per-Candidate Histograms
+  
+  //Base Topological Variables for All Reconstructed V0 Vertices
+  TH1D *fHistTopDCANegToPV;       //!
+  TH1D *fHistTopDCAPosToPV;       //!
+  TH1D *fHistTopDCAV0Daughters;   //!
+  TH1D *fHistTopCosinePA;         //!
+  TH1D *fHistTopV0Radius;         //!
+
+  //Zoomed into Selection criteria (fV0Sels)
+  TH1D *fHistSelectedTopDCANegToPV;       //!
+  TH1D *fHistSelectedTopDCAPosToPV;       //!
+  TH1D *fHistSelectedTopDCAV0Daughters;   //!
+  TH1D *fHistSelectedTopCosinePA;         //!
+  TH1D *fHistSelectedTopV0Radius;         //!
+
+  //Histograms for Storing Invariant Mass: 2D 
+  //Stored only if the 5 topological selections in fV0Sels are satisfied 
+  TH2D *f2dHistInvMassK0Short;      //!
+  TH2D *f2dHistInvMassLambda;       //!
+  TH2D *f2dHistInvMassAntiLambda;   //!
+
+  //With dE/dx Selection (extra)
+  TH2D *f2dHistInvMassWithdEdxK0Short;      //!
+  TH2D *f2dHistInvMassWithdEdxLambda;       //!
+  TH2D *f2dHistInvMassWithdEdxAntiLambda;   //!
+
+  //dEdx QA Histograms (extra) 
+  //PIDFrameWork
+  TH2D *f2dHistResponseNegativeAsPion;   //! 
+  TH2D *f2dHistResponseNegativeAsProton; //! 
+  TH2D *f2dHistResponsePositiveAsPion;   //! 
+  TH2D *f2dHistResponsePositiveAsProton; //! 
+
+  //Raw Stuff, Clean Version: Proton and Pion From Lambdas
+  //Potentially useful for checking calibration of dE/dx 
+  TH2D *f2dHistdEdxSignalPionFromLambda;   //! 
+  TH2D *f2dHistdEdxSignalProtonFromLambda; //! 
+  TH2D *f2dHistResponsePionFromLambda;     //! 
+  TH2D *f2dHistResponseProtonFromLambda;   //!
+
+  AliPIDResponse *fPIDResponse;     // PID response object
+
+  //Objects Controlling Task Behaviour: has to be streamed! 
+  Bool_t    fkRunV0Vertexer;      //if true, re-run vertexer with loose cuts. CARE MUST BE TAKEN in PbPb!
+  Double_t  fV0VertexerSels[7];     // Array to store the 7 values for the different selections V0 related
+  Double_t  fV0Sels[7];           // Array to store the 7 values for the different selections V0 related
+
+
+   AliAnalysisTaskQAV0(const AliAnalysisTaskQAV0&);            // not implemented
+   AliAnalysisTaskQAV0& operator=(const AliAnalysisTaskQAV0&); // not implemented
+  
+   ClassDef(AliAnalysisTaskQAV0, 11);
+};
+
+#endif
diff --git a/PWGLF/QATasks/macros/AddTaskQAV0.C b/PWGLF/QATasks/macros/AddTaskQAV0.C
new file mode 100644 (file)
index 0000000..8d98d8b
--- /dev/null
@@ -0,0 +1,45 @@
+AliAnalysisTaskQAV0 *AddTaskQAV0( TString lCustomName = "QA", const TString lMasterJobSessionFlag = "")
+{
+// Creates, configures and attaches to the train a cascades check task.
+   // Get the pointer to the existing analysis manager via the static access method.
+   //==============================================================================
+   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
+   if (!mgr) {
+      ::Error("AddTaskExtractV0", "No analysis manager to connect to.");
+      return NULL;
+   }   
+
+   // Check the analysis type using the event handlers connected to the analysis manager.
+   //==============================================================================
+   if (!mgr->GetInputEventHandler()) {
+      ::Error("AddTaskExtractV0", "This task requires an input event handler");
+      return NULL;
+   }   
+   TString type = mgr->GetInputEventHandler()->GetDataType(); // can be "ESD" or "AOD"
+
+   // Create and configure the task
+        AliAnalysisTaskQAV0 *taskv0extract = new AliAnalysisTaskQAV0("taskv0extract");
+
+   //No Configuration Required at this stage  
+
+   mgr->AddTask(taskv0extract);
+
+   TString outputFileName = AliAnalysisManager::GetCommonFileName();
+   
+   outputFileName += ":PWGLFQAV0";
+   outputFileName += "_";
+   outputFileName += lCustomName.Data(); 
+   //if(lMasterJobSessionFlag.Length()) outputFileName += lMasterJobSessionFlag.Data();
+   
+   Printf("Set OutputFileName : \n %s\n", outputFileName.Data() );
+
+   AliAnalysisDataContainer *coutputList = mgr->CreateContainer("clist",
+                                                            TList::Class(),
+                                                            AliAnalysisManager::kOutputContainer,
+                                                            outputFileName );
+
+   mgr->ConnectInput( taskv0extract, 0, mgr->GetCommonInputContainer());
+   mgr->ConnectOutput(taskv0extract, 1, coutputList);
+   
+   return taskv0extract;
+}