template to access pmd pbpb data: sjena
authorsjena <sjena@cern.ch>
Tue, 16 Dec 2014 21:27:37 +0000 (22:27 +0100)
committersjena <sjena@cern.ch>
Tue, 16 Dec 2014 21:27:37 +0000 (22:27 +0100)
PMD/anal/AddAliPMDAnalysisTaskPbPb.C [new file with mode: 0644]
PMD/anal/AliPMDAnalysisTaskPbPb.cxx [new file with mode: 0644]
PMD/anal/AliPMDAnalysisTaskPbPb.h [new file with mode: 0644]
PMD/anal/CreateAlienHandler.C [new file with mode: 0644]
PMD/anal/runPmdTask.C [new file with mode: 0644]

diff --git a/PMD/anal/AddAliPMDAnalysisTaskPbPb.C b/PMD/anal/AddAliPMDAnalysisTaskPbPb.C
new file mode 100644 (file)
index 0000000..f512602
--- /dev/null
@@ -0,0 +1,51 @@
+//=========================================================================//
+//                                                                         //
+//              A template Analysis AddTask for PMD analysis               //
+//            You can copy it and add features to ir as your need          //
+//                                                                         //
+//                               Satyajit Jena                             //
+//                               sjena@cern.ch                             //
+//                                13/04/2012                               //
+//                                                                         //
+//=========================================================================//
+
+
+void AddAliPMDAnalysisTaskPbPb(const Char_t *taskname="MyTask", Bool_t isMC) {
+
+  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
+  if (!mgr) {
+    ::Error("AddTaskFluctuations", "No analysis manager to connect to.");
+    return NULL;
+  }
+
+  if (!mgr->GetInputEventHandler()) {
+    ::Error("AddTaskFluctuations", "This task requires an input event handler");
+    return NULL;
+  }
+
+    
+  AliPMDAnalysisTaskPbPb *task = new AliPMDAnalysisTaskPbPb(taskname);
+
+  if (!task) {
+    Error("AliPMDAnalysisTaskPbPb", "Task could not be created.");
+    return NULL;
+  }
+  
+  task->SetIsMC(isMC); // Similarly you can add more functions
+                       // See one of my task in aliroot
+  mgr->AddTask(task);
+  TString commonname   = Form("%s:%s", AliAnalysisManager::GetCommonFileName(),taskname);
+
+  // Create containers for input/output
+  AliAnalysisDataContainer *cinput  = mgr->GetCommonInputContainer();
+  AliAnalysisDataContainer *coutput 
+    = mgr->CreateContainer("PMD", TList::Class(),    
+                          AliAnalysisManager::kOutputContainer, commonname);
+
+  // Connect input/output
+  mgr->ConnectInput(task, 0, cinput);
+  mgr->ConnectOutput(task, 1, coutput);
+
+  return;
+};
diff --git a/PMD/anal/AliPMDAnalysisTaskPbPb.cxx b/PMD/anal/AliPMDAnalysisTaskPbPb.cxx
new file mode 100644 (file)
index 0000000..16268f8
--- /dev/null
@@ -0,0 +1,246 @@
+/**************************************************************************
+ * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ *                                                                        *
+ * Author: Satyajit Jena.                                                 *
+ * 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.                  *
+ **************************************************************************/
+/*
+  .
+  .                  A template class to read tracks (PMD Cluster)
+  .                     Runs in Local and Grid Modes
+  .                    Can be used for PbPb PMD analysis
+  .                 Auther: Satyajit Jena <sjena@cern.ch>
+  .                               12/04/2012  
+  .
+  . You are free to ask me anything you want about this code, I will add
+  . a readme shortly to this folder about the running and adjusting the
+  . code   
+**************************************************************************/
+
+
+#include "TChain.h"
+#include "TTree.h"
+#include "TH1F.h"
+#include "TCanvas.h"
+
+#include "AliAnalysisTask.h"
+#include "AliAnalysisTaskSE.h"
+#include "AliAnalysisManager.h"
+
+#include "AliESDPmdTrack.h"
+#include "AliESDEvent.h"
+#include "AliESDInputHandler.h"
+#include "AliESDtrackCuts.h"
+#include "AliPMDAnalysisTaskPbPb.h"
+#include "AliCentrality.h"
+
+
+ClassImp(AliPMDAnalysisTaskPbPb)
+
+//________________________________________________________________________
+AliPMDAnalysisTaskPbPb::AliPMDAnalysisTaskPbPb(const char *name) 
+: AliAnalysisTaskSE(name), fOutputList(0), fTrackCuts(0), fESD(0), fHistPt(0),fHistEta(0),
+  fhEsdXYP(0),
+  fhEsdXYC(0),
+  fIsMC(kFALSE){
+
+  DefineOutput(1, TList::Class());
+}
+
+//________________________________________________________________________
+void AliPMDAnalysisTaskPbPb::CreateOutputObjects()
+{
+  fOutputList = new TList();
+  fOutputList->SetOwner();
+
+  //  fTrackCuts = AliESDtrackCuts::GetStandardITSTPCTrackCuts2010(kTRUE);
+
+  // Track Cut Setup
+  // Tune it accoringly
+  fTrackCuts = new  AliESDtrackCuts("MyTrack Cuts","tracks");
+  
+  fTrackCuts->SetMinNClustersTPC(70);
+  fTrackCuts->SetMaxChi2PerClusterTPC(4);
+  fTrackCuts->SetAcceptKinkDaughters(kFALSE);
+  fTrackCuts->SetRequireTPCRefit(kTRUE);
+  fTrackCuts->SetRequireITSRefit(kTRUE);
+  fTrackCuts->SetClusterRequirementITS(AliESDtrackCuts::kSPD,AliESDtrackCuts::kAny);
+  fTrackCuts->SetMaxDCAToVertexZ(2);
+
+  fTrackCuts->SetDCAToVertex2D(kFALSE);
+  fTrackCuts->SetRequireSigmaToVertex(kFALSE);
+    
+  // Create the histograms as you like. 
+  Int_t etabins = 40;
+  Float_t etalow = -2.0, etaup = 2.0;
+  fHistEta = new TH1F("fHistEta","#eta distribution for reconstructed",etabins, etalow, etaup);
+  fHistEta->GetXaxis()->SetTitle("#eta");
+  fHistEta->GetYaxis()->SetTitle("counts");
+  fHistEta->SetMarkerStyle(kFullCircle);
+  fHistEta->SetMarkerColor(kRed);
+  fOutputList->Add(fHistEta);
+
+  fHistPt = new TH1F("fHistPt", "P_{T} distribution", 100, 0.1, 10.1);
+  fHistPt->GetXaxis()->SetTitle("P_{T} (GeV/c)");
+  fHistPt->GetYaxis()->SetTitle("dN/dP_{T} (c/GeV)");
+  fHistPt->SetMarkerStyle(kFullCircle);
+  fHistPt->SetMarkerColor(kRed);
+  fOutputList->Add(fHistPt);
+  
+  fhEsdXYC = new TH2F("hEsdXYC"," Scattered Plot for CPV (ESD) ",2000,-100.,100.,2000,-100.,100.);
+  fhEsdXYC->GetXaxis()->SetTitle("X-axis");
+  fhEsdXYC->GetYaxis()->SetTitle("Y-axis");
+  fOutputList->Add(fhEsdXYC);
+  
+  fhEsdXYP = new TH2F("hEsdXYP"," Scattered Plot for PRE (ESD) ",2000,-100.,100.,2000,-100.,100.);
+  fhEsdXYP->GetXaxis()->SetTitle("X-axis");
+  fhEsdXYP->GetYaxis()->SetTitle("Y-axis");
+  fOutputList->Add(fhEsdXYP);
+
+
+  PostData(1, fOutputList);
+}
+
+//________________________________________________________________________
+void AliPMDAnalysisTaskPbPb::Exec(Option_t *) 
+{
+  // Main loop
+  // Called for each event
+
+  fESD = dynamic_cast<AliESDEvent*>(InputEvent());
+  if (!fESD) {
+    Printf("ERROR: fESD not available");
+    return;
+  }
+  
+  Bool_t isSelected = (((AliInputEventHandler*)(AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler()))->IsEventSelected() & AliVEvent::kMB);
+  if(!isSelected) return;
+
+   
+  if(!(fESD->GetPrimaryVertex()->GetStatus())) return;
+  // if vertex is from spd vertexZ, require more stringent cut
+  if (fESD->GetPrimaryVertex()->IsFromVertexerZ()) {
+    if (fESD->GetPrimaryVertex()->GetDispersion()>0.02 ||  fESD->GetPrimaryVertex()->GetZRes()>0.25 ) return; // bad vertex from VertexerZ
+  }
+  
+
+ AliCentrality *centrality = fESD->GetCentrality();
+
+ /* If you want to make centrality bining use following */
+ // Double_t nCentrality = -1;
+ // nCentrality = centrality->GetCentralityPercentile("V0M");
+ // printf(" %f \n", nCentrality);
+ // if (nCentrality < 0) return;
+
+ /* otherwise 
+    if you want to cuttoff other centrality and keep a window 
+    for example this is for 0 - 10% centrality with V0M estimator
+*/
+ if(!centrality->IsEventInCentralityClass(0,10,"V0M")) return;  
+  
+  
+  // Track loop for reconstructed event - General purpose
+  // any central analysis can be done.
+
+  Int_t   nGoodTracks = 0;
+  Int_t ntracks = fESD->GetNumberOfTracks();
+  for(Int_t i = 0; i < ntracks; i++) {
+    AliESDtrack* esdtrack = fESD->GetTrack(i); // pointer to reconstructed to track          
+    if(!esdtrack) {
+      AliError(Form("ERROR: Could not retrieve esdtrack %d",i));
+      continue;
+    }
+    
+    if(!fTrackCuts->AcceptTrack(esdtrack)) continue;
+    nGoodTracks++;
+    fHistPt->Fill(esdtrack->Pt());
+    fHistEta->Fill(esdtrack->Eta());
+  } 
+  
+   
+  //_______________________________________________________
+  // Only for PMD part
+  
+  Int_t npmdcl = fESD->GetNumberOfPmdTracks();
+  printf ("Number of PMD Clusters: %8d \n",npmdcl) ;  
+
+  for (Int_t i = 0; i < npmdcl; i++) {
+    AliESDPmdTrack *pmdtr = fESD->GetPmdTrack(i);
+    Int_t   det     = pmdtr->GetDetector();
+    Float_t clsX    = pmdtr->GetClusterX();
+    Float_t clsY    = pmdtr->GetClusterY();
+    
+    if ( det == 0 ) {
+      fhEsdXYP->Fill(clsX,clsY);
+    }
+    else if ( det == 1 ) {
+      fhEsdXYC->Fill(clsX,clsY);
+    }
+  }
+
+
+  PostData(1, fOutputList);
+}      
+
+//________________________________________________________________________
+void AliPMDAnalysisTaskPbPb::Terminate(Option_t *) {
+  // Called once at the end of the query
+
+  fOutputList = dynamic_cast<TList*> (GetOutputData(1));
+  if (!fOutputList) {
+    Printf("ERROR: fHistPt not available");
+    return;
+  }
+
+  fHistPt = dynamic_cast<TH1F*>(fOutputList->FindObject("fHistPt"));
+ TCanvas *c1 = new TCanvas("AliAnalysisTaskPt","Pt",10,10,745,412);
+ c1->SetFillColor(10);
+ c1->SetBorderMode(0);
+ c1->SetBorderSize(0);
+ c1->SetFrameBorderMode(0);
+ c1->cd(1)->SetLogy();
+ fHistPt->DrawCopy("E");
+
+
+  fHistEta = dynamic_cast<TH1F*>(fOutputList->FindObject("fHistEta"));
+  TCanvas *c2 = new TCanvas("eta","Pt",10,10,745,412);
+  c2->SetFillColor(10);
+  c2->SetBorderMode(0);
+  c2->SetBorderSize(0);
+  c2->SetFrameBorderMode(0);
+  c2->cd();
+  fHistEta->DrawCopy("E");
+
+
+  fhEsdXYP = dynamic_cast<TH2F*>(fOutputList->FindObject("hEsdXYP"));
+  TCanvas *c3 = new TCanvas("XYP","Pt",10,10,745,745);
+  c3->SetFillColor(10);
+  c3->SetBorderMode(0);
+  c3->SetBorderSize(0);
+  c3->SetFrameBorderMode(0);
+  c3->cd();
+  fhEsdXYP->DrawCopy();
+
+
+fhEsdXYC = dynamic_cast<TH2F*>(fOutputList->FindObject("hEsdXYC"));
+  TCanvas *c4 = new TCanvas("XYC","Pt",10,10,745,745);
+  c4->SetFillColor(10);
+  c4->SetBorderMode(0);
+  c4->SetBorderSize(0);
+  c4->SetFrameBorderMode(0);
+  c4->cd();
+  fhEsdXYC->DrawCopy();
+
+
+   
+}
+
diff --git a/PMD/anal/AliPMDAnalysisTaskPbPb.h b/PMD/anal/AliPMDAnalysisTaskPbPb.h
new file mode 100644 (file)
index 0000000..aa8a0f4
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef AliPMDAnalysisTaskPbPb_cxx
+#define AliPMDAnalysisTaskPbPb_cxx
+
+ /**************************************************************************
+
+                   A template class to read tracks (PMD Cluster)
+                        Runs in Local and Grid Modes
+                       Can be used for PbPb PMD analysis
+                     Origin: Satyajit Jena <sjena@cern.ch>
+
+ **************************************************************************/
+
+
+class TH1F;
+class AliESDEvent;
+class AliESDtrackCuts;
+
+#include "AliAnalysisTaskSE.h"
+
+class AliPMDAnalysisTaskPbPb : public AliAnalysisTaskSE {
+ public:
+ AliPMDAnalysisTaskPbPb(): AliAnalysisTaskSE(), fOutputList(0), fTrackCuts(0),fESD(0), fHistPt(0), fHistEta(0) {}
+  AliPMDAnalysisTaskPbPb(const char *name);
+  virtual ~AliPMDAnalysisTaskPbPb() {}
+  
+  virtual void   CreateOutputObjects();
+  virtual void   Exec(Option_t *option);
+  virtual void   Terminate(Option_t *);
+
+  void SetIsMC(Bool_t isMC) { fIsMC = isMC; }  
+ private:
+  TList *fOutputList;
+  
+  AliESDtrackCuts *fTrackCuts;
+  AliESDEvent *fESD;     // ESD object
+  TH1F    *fHistPt;  // Pt spectrum
+  TH1F   *fHistEta; // Pt spectrum
+  TH2F   *fhEsdXYP; //
+  TH2F   *fhEsdXYC; //
+
+  Bool_t fIsMC; // MC truth 
+
+  AliPMDAnalysisTaskPbPb(const AliPMDAnalysisTaskPbPb&); // not implemented
+  AliPMDAnalysisTaskPbPb& operator=(const AliPMDAnalysisTaskPbPb&); // not implemented
+  
+  ClassDef(AliPMDAnalysisTaskPbPb, 1); // example of analysis
+};
+
+#endif
diff --git a/PMD/anal/CreateAlienHandler.C b/PMD/anal/CreateAlienHandler.C
new file mode 100644 (file)
index 0000000..86505e2
--- /dev/null
@@ -0,0 +1,65 @@
+//=========================================================================//
+//                                                                         //
+//             A template of CreateAlienHandler for PMD analysis           //
+//            You can copy it and add features to ir as your need          //
+//                      There are many way to do it!!!                     //
+//                               Satyajit Jena                             //
+//                               sjena@cern.ch                             //
+//                                13/04/2012                               //
+//                                                                         //
+//=========================================================================//
+
+
+AliAnalysisGrid* CreateAlienHandler(const char *gridmode) {
+  
+  AliAnalysisAlien *plugin = new AliAnalysisAlien();
+
+  // Set the run mode (can be "full", "test", "offline", "submit" or "terminate")
+  plugin->SetRunMode(gridmode);
+  plugin->SetNtestFiles(1);
+  
+  // Set versions of used packages
+  plugin->SetAPIVersion("V1.1x");
+  plugin->SetROOTVersion("v5-34-08-6");
+  plugin->SetAliROOTVersion("vAN-20141207");
+  
+  // for simulation 
+  //plugin->SetGridDataDir(" /alice/sim/LHC11a10a_bis");
+  // plugin->SetDataPattern("*ESDs.root");
+  
+  plugin->SetGridDataDir("/alice/data/2010/LHC10h");
+  plugin->SetDataPattern("*ESDs/pass2/*ESDs.root");
+  plugin->SetRunPrefix("000"); //  for data only IMPORTANT!
+    
+  //------ Add Run Numbers
+  plugin->AddRunNumber(137161);  
+  plugin->AddRunNumber(137231);  
+
+  // Where to Store Output 
+  //---------------------------------------
+  plugin->SetGridWorkingDir("TestRun/pbpb");
+  plugin->SetGridOutputDir("output"); // In this case will be $HOME/work/output
+  plugin->SetOutputToRunNo();
+  plugin->SetAnalysisSource("AliPMDAnalysisTaskPbPb.cxx");
+  plugin->SetAdditionalLibs("AliPMDAnalysisTaskPbPb.h AliPMDAnalysisTaskPbPb.cxx");
+  plugin->SetDefaultOutputs(kTRUE);
+  plugin->SetAnalysisMacro("pmdPbPbTask.C");
+  plugin->SetExecutable("pmdPbPbTask.sh");
+  plugin->SetJDLName("pmdPbPbTask.jdl"); 
+
+  //  plugin->SetOverwriteMode();
+  
+  // No need to change it 
+  //___________________________________________
+  plugin->SetSplitMaxInputFileNumber(100);
+  plugin->SetTTL(30000);
+  // Optionally set input format (default xml-single)
+  plugin->SetInputFormat("xml-single");
+  // Optionally modify job price (default 1)
+  plugin->SetPrice(1);      
+  // Optionally modify split mode (default 'se')    
+  plugin->SetSplitMode("se");
+  plugin->SetMergeViaJDL(kTRUE);
+  
+  return plugin;
+}
diff --git a/PMD/anal/runPmdTask.C b/PMD/anal/runPmdTask.C
new file mode 100644 (file)
index 0000000..0c7696a
--- /dev/null
@@ -0,0 +1,337 @@
+//=========================================================================//
+//                                                                         //
+//                   A template runPmdTask for PMD analysis                //
+//            You can copy it and add features according to your need      //
+//                                                                         //
+//                               Satyajit Jena                             //
+//                               sjena@cern.ch                             //
+//                                13/04/2012                               //
+//                                                                         //
+//=========================================================================//
+
+const char * incollection = "file.txt";
+//______________________________________________________________________________
+void runPmdTask(Bool_t         isGrid = 0,
+               Bool_t           isMC = 0,
+               const char *gridmode  = "test") {
+
+  if (isGrid) {
+    Printf("Strating the Grid Job ");
+    Printf("Grid Mode %s",gridmode);
+    if (isMC)  Printf("It is Data Type Run");
+    if (!isMC) Printf("It is MC Type Run");
+  }
+    
+  // Load the needed libraries most of 
+  // them already loaded by aliroot
+  //--------------------------------------
+  gSystem->Load("libTree");
+  gSystem->Load("libGeom");
+  gSystem->Load("libVMC");
+  gSystem->Load("libXMLIO");
+  gSystem->Load("libPhysics");
+
+  gSystem->Load("libSTEERBase");
+  gSystem->Load("libESD");
+  gSystem->Load("libAOD");
+  gSystem->Load("libANALYSIS");
+  gSystem->Load("libANALYSISalice");
+
+  // Use AliRoot includes to compile our task                                   
+  gROOT->ProcessLine(".include $ALICE_INSTALL/include");
+  
+  AliAnalysisManager *mgr = new AliAnalysisManager("PMDAnalysis");
+  
+  if(isGrid) {
+    gROOT->LoadMacro("CreateAlienHandler.C");
+    AliAnalysisGrid *alienHandler = CreateAlienHandler(gridmode);  
+    if (!alienHandler) return;
+    mgr->SetGridHandler(alienHandler);
+  }
+    
+  
+  //  TChain *  chain;
+  //  if(!isGrid) {
+  //  gROOT->LoadMacro("CreateESDChain.C"); // use it if you know it
+  //  chain = CreateESDChain("file.txt", 10);
+  //  }
+  TChain *  chain = new TChain("esdTree"); 
+  if(!isGrid) {
+    ifstream file_collect(incollection);
+    TString line;
+    while (line.ReadLine(file_collect) ) {
+      chain->Add(line.Data());
+    }
+  }
+    
+  if(isMC) {
+    AliVEventHandler* esdH = new AliESDInputHandler();
+    mgr->SetInputEventHandler(esdH);
+    AliMCEventHandler *mc = new AliMCEventHandler();
+    //mc->SetReadTR(kTRUE);
+    mgr->SetMCtruthEventHandler(mc);
+    gROOT->LoadMacro("$ALICE_ROOT/ANALYSIS/macros/AddTaskPhysicsSelection.C");
+    AliPhysicsSelectionTask* physicsSelTask = AddTaskPhysicsSelection(isMC);
+    physicsSelTask->GetPhysicsSelection()->SetAnalyzeMC();
+
+    gROOT->LoadMacro("$ALICE_ROOT/ANALYSIS/macros/AddTaskCentrality.C");
+    AliCentralitySelectionTask *centralityTask = AddTaskCentrality();
+  } else {
+    AliVEventHandler* esdH = new AliESDInputHandler();
+    mgr->SetInputEventHandler(esdH);
+    gROOT->LoadMacro("$ALICE_ROOT/ANALYSIS/macros/AddTaskPhysicsSelection.C");
+    AliPhysicsSelectionTask* physicsSelTask = AddTaskPhysicsSelection(isMC);
+    
+    gROOT->LoadMacro("$ALICE_ROOT/ANALYSIS/macros/AddTaskCentrality.C");
+    AliCentralitySelectionTask *centralityTask = AddTaskCentrality();
+  }
+
+  gROOT->LoadMacro("AliPMDAnalysisTaskPbPb.cxx++g");   
+  gROOT->LoadMacro("AddAliPMDAnalysisTaskPbPb.C");
+  AddAliPMDAnalysisTaskPbPb("MyTask",isMC);
+  
+  // Enable debug printouts
+  mgr->SetDebugLevel(0);
+  if (!mgr->InitAnalysis())
+    return;
+  
+ mgr->PrintStatus();
+ if(isGrid)
+   mgr->StartAnalysis("grid");
+ else  
+   mgr->StartAnalysis("local",chain);
+};
+
+
+//__________________________________________________________________________________________
+// This helper macros creates a chain of ESD files for you. Source can be either a text
+// file with the file paths or a directory. In the latter case all ESD files in all subdirectories
+// are considered.
+//
+// Inspired by: Jan.Fiete.Grosse-Oetringhaus@cern.ch
+
+TChain* CreateESDChain(const char* aDataDir = "ESDfiles.txt", Int_t aRuns = 20, Int_t offset = 0, Bool_t addFileName = kFALSE, Bool_t addFriend = kFALSE, const char* check = 0)
+{
+  // creates chain of files in a given directory or file containing a list.
+  // In case of directory the structure is expected as:
+  // <aDataDir>/<dir0>/AliESDs.root
+  // <aDataDir>/<dir1>/AliESDs.root
+  // ...
+  //
+  // if addFileName is true the list only needs to contain the directories that contain the AliESDs.root files
+  // if addFriend is true a file AliESDfriends.root is expected in the same directory and added to the chain as friend
+  // if check is != 0 the files that work are written back into the textfile with the name check
+
+  if (!aDataDir)
+    return 0;
+
+  Long_t id, size, flags, modtime;
+  if (gSystem->GetPathInfo(aDataDir, &id, &size, &flags, &modtime))
+  {
+    printf("%s not found.\n", aDataDir);
+    return 0;
+  }
+
+  TChain* chain = new TChain("esdTree");
+  TChain* chainFriend = 0;
+  
+  if (addFriend)
+    chainFriend = new TChain("esdFriendTree");
+
+  if (flags & 2)
+  {
+    TString execDir(gSystem->pwd());
+    TSystemDirectory* baseDir = new TSystemDirectory(".", aDataDir);
+    TList* dirList            = baseDir->GetListOfFiles();
+    Int_t nDirs               = dirList->GetEntries();
+    gSystem->cd(execDir);
+
+    Int_t count = 0;
+
+    for (Int_t iDir=0; iDir<nDirs; ++iDir)
+    {
+      TSystemFile* presentDir = (TSystemFile*) dirList->At(iDir);
+      if (!presentDir || !presentDir->IsDirectory() || strcmp(presentDir->GetName(), ".") == 0 || strcmp(presentDir->GetName(), "..") == 0)
+        continue;
+
+      if (offset > 0)
+      {
+        --offset;
+        continue;
+      }
+
+      if (count++ == aRuns)
+        break;
+
+      TString presentDirName(aDataDir);
+      presentDirName += "/";
+      presentDirName += presentDir->GetName();
+
+      chain->Add(presentDirName + "/AliESDs.root/esdTree");
+    }
+  }
+  else
+  {
+    // Open the input stream
+    ifstream in;
+    in.open(aDataDir);
+
+    ofstream outfile;
+    if (check)
+      outfile.open(check);
+
+    Int_t count = 0;
+
+    // Read the input list of files and add them to the chain
+    TString line;
+    while (in.good())
+    {
+      in >> line;
+
+      if (line.Length() == 0)
+        continue;
+
+      if (offset > 0)
+      {
+        offset--;
+        continue;
+      }
+
+      if (count++ == aRuns)
+        break;
+
+      TString esdFile(line);
+
+      if (addFileName)
+        esdFile += "/AliESDs.root";
+        
+      TString esdFileFriend(esdFile);
+      esdFileFriend.ReplaceAll("AliESDs.root", "AliESDfriends.root");
+        
+      if (check)
+      {
+        TFile* file = TFile::Open(esdFile);
+        if (!file)
+          continue;
+        file->Close();
+        
+        if (chainFriend)
+        {
+          TFile* file = TFile::Open(esdFileFriend);
+          if (!file)
+            continue;
+          file->Close();
+        }
+        
+        outfile << line.Data() << endl;
+        printf("%s\n", line.Data());
+      }        
+        
+        // add esd file
+      chain->Add(esdFile);
+
+        // add file
+      if (chainFriend)
+        chainFriend->Add(esdFileFriend);
+    }
+
+    in.close();
+    
+    if (check)
+      outfile.close();
+  }
+  
+  if (chainFriend)
+    chain->AddFriend(chainFriend);
+
+  return chain;
+}
+
+void ChainToTextFile(TChain* chain, const char* target)
+{
+  // write a text list of the files in the chain
+  
+  TObjArray* list = chain->GetListOfFiles();
+  TIterator* iter = list->MakeIterator();
+  TObject* obj = 0;
+
+  ofstream outfile;
+  outfile.open(target);
+
+  while ((obj = iter->Next())) {
+    TString fileName(obj->GetTitle());
+    
+    outfile << fileName.Data() << endl;
+  }
+
+  outfile.close();
+
+  delete iter;
+} 
+
+TObjArray* Chain2List(TChain* chain)
+{
+  // returns a TObjArray of TObjStrings of the file names in the chain
+
+  TObjArray* result = new TObjArray;
+
+  for (Int_t i=0; i<chain->GetListOfFiles()->GetEntries(); i++)
+    result->Add(new TObjString(chain->GetListOfFiles()->At(i)->GetTitle()));
+
+  return result;
+}
+
+void LookupWrite(TChain* chain, const char* target)
+{
+  // looks up the chain and writes the remaining files to the text file target
+
+  chain->Lookup();
+
+  ChainToTextFile(chain, target);
+}
+
+TChain* CreateChain(const char* treeName, const char* aDataDir, Int_t aRuns, Int_t offset = 0)
+{
+  // creates chain of files in a given directory or file containing a list.
+
+  if (!treeName || !aDataDir)
+    return 0;
+
+  TChain* chain = new TChain(treeName);
+  
+  // Open the input stream
+  ifstream in;
+  in.open(aDataDir);
+
+  Int_t count = 0;
+
+  // Read the input list of files and add them to the chain
+  TString line;
+  while(in.good()) 
+  {
+    in >> line;
+      
+    if (line.Length() == 0)
+      continue;      
+    
+    if (offset > 0)
+    {
+      --offset;
+      continue;
+    }
+
+    if (count++ == aRuns)
+      break;
+
+    chain->Add(line);
+  }
+
+  in.close();
+
+  return chain;
+}