]> git.uio.no Git - u/mrichter/AliRoot.git/commitdiff
Added first go at a QA task
authorcholm <cholm@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 8 Jul 2011 14:34:03 +0000 (14:34 +0000)
committercholm <cholm@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 8 Jul 2011 14:34:03 +0000 (14:34 +0000)
PWG2/FORWARD/analysis2/AddTaskForwardQA.C [new file with mode: 0644]
PWG2/FORWARD/analysis2/AliForwardQATask.cxx [new file with mode: 0644]
PWG2/FORWARD/analysis2/AliForwardQATask.h [new file with mode: 0644]
PWG2/FORWARD/analysis2/trains/MakeQATrain.C [new file with mode: 0644]

diff --git a/PWG2/FORWARD/analysis2/AddTaskForwardQA.C b/PWG2/FORWARD/analysis2/AddTaskForwardQA.C
new file mode 100644 (file)
index 0000000..94c988e
--- /dev/null
@@ -0,0 +1,132 @@
+/**
+ * @file   AddTaskForwardQA.C
+ * @author Christian Holm Christensen <cholm@dalsgaard.hehi.nbi.dk>
+ * @date   Wed Mar 23 12:14:03 2011
+ * 
+ * @brief  
+ * 
+ * 
+ * @ingroup pwg2_forward_scripts_tasks
+ */
+/**
+ * @defgroup pwg2_forward_eloss Energy Loss Fits
+ * @ingroup pwg2_forward_topical
+ */
+
+/**
+ * This is the macro to include the FMD energy fitter in a train.  
+ * 
+ * @ingroup pwg2_forward_eloss
+ */
+AliAnalysisTask*
+AddTaskForwardQA(Bool_t mc, Bool_t useCent)
+{
+  gSystem->Load("libPWG2forward2");
+
+  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
+  if (!mgr) {
+    Error("AddTaskForwardQA", "No analysis manager to connect to.");
+    return NULL;
+  }   
+  
+  // --- Make the task and add it to the manager ---------------------
+  AliForwardQATask* task = new AliForwardQATask("forwardQA");
+  // task->SetBLow(blow);
+  // task->SetBLow(bhigh);
+  mgr->AddTask(task);
+
+  Double_t nXi = mc ? 2 : 2;   //HHD test
+  Bool_t   includeSigma = false; //true;
+
+  AliFMDMultCuts cDensity;
+  //c2.SetNXi(mc ? 1 : 1);
+  //  c2.SetIncludeSigma(false);
+  //c2.SetMPVFraction(0.5);
+  //Double_t factor = 1.2;
+  cDensity.SetMultCuts(0.3, 0.3, 0.3, 0.3, 0.3);
+  
+  // --- Set parameters on the algorithms ----------------------------
+  // Set the number of SPD tracklets for which we consider the event a
+  // low flux event
+  task->GetEventInspector().SetLowFluxCut(1000); 
+  // Set the maximum error on v_z [cm]
+  task->GetEventInspector().SetMaxVzErr(0.2);
+
+  // --- Set parameters on energy loss fitter ------------------------
+  // Set the eta axis to use - note, this overrides whatever is used
+  // by the rest of the algorithms - but only for the energy fitter
+  // algorithm. 
+  task->GetEnergyFitter().SetEtaAxis(200, -4, 6);
+  // Set maximum energy loss to consider 
+  task->GetEnergyFitter().SetMaxE(15); 
+  // Set number of energy loss bins 
+  task->GetEnergyFitter().SetNEbins(500);
+  // Set whether to use increasing bin sizes 
+  task->GetEnergyFitter().SetUseIncreasingBins(true);
+  // Set whether to do fit the energy distributions 
+  task->GetEnergyFitter().SetDoFits(kTRUE);
+  // Set whether to make the correction object 
+  task->GetEnergyFitter().SetDoMakeObject(kFALSE);
+  // Set the low cut used for energy
+  task->GetEnergyFitter().SetLowCut(0.4);
+  // Set the number of bins to subtract from maximum of distributions
+  // to get the lower bound of the fit range
+  task->GetEnergyFitter().SetFitRangeBinWidth(4);
+  // Set the minimum number of entries in the distribution before
+  // trying to fit to the data
+  task->GetEnergyFitter().SetMinEntries(1000);
+
+  // --- Sharing filter ----------------------------------------------
+  // Enable use of angle corrected signals in the algorithm 
+  task->GetSharingFilter().SetUseAngleCorrectedSignals(true);
+  // Disable use of angle corrected signals in the algorithm 
+  task->GetSharingFilter().SetZeroSharedHitsBelowThreshold(false);
+  // Enable use of angle corrected signals in the algorithm 
+  task->GetSharingFilter().GetHCuts().SetMultCuts(-1);
+  // Set the number of xi's (width of landau peak) to stop at 
+  task->GetSharingFilter().GetHCuts().SetNXi(nXi);
+  // Set whether or not to include sigma in cut
+  task->GetSharingFilter().GetHCuts().SetIncludeSigma(includeSigma);
+  // Enable use of angle corrected signals in the algorithm 
+  task->GetSharingFilter().SetLCuts(cDensity);
+
+  // --- Density calculator ------------------------------------------
+  // Set the maximum number of particle to try to reconstruct 
+  task->GetDensityCalculator().SetMaxParticles(10);
+  // Wet whether to use poisson statistics to estimate N_ch
+  task->GetDensityCalculator().SetUsePoisson(true);
+  // Set whether or not to include sigma in cut
+  task->GetDensityCalculator().SetCuts(cDensity);
+  // Set whether or not to use the phi acceptance
+  //   AliFMDDensityCalculator::kPhiNoCorrect
+  //   AliFMDDensityCalculator::kPhiCorrectNch
+  //   AliFMDDensityCalculator::kPhiCorrectELoss
+  task->GetDensityCalculator()
+    .SetUsePhiAcceptance(AliFMDDensityCalculator::kPhiCorrectNch);
+  // --- Set limits on fits the energy -------------------------------
+  // Maximum relative error on parameters 
+  AliFMDCorrELossFit::ELossFit::fgMaxRelError = .12;
+  // Least weight to use 
+  AliFMDCorrELossFit::ELossFit::fgLeastWeight = 1e-5;
+  // Maximum value of reduced chi^2 
+  AliFMDCorrELossFit::ELossFit::fgMaxChi2nu   = 20;
+    
+  // --- Make the output container and connect it --------------------
+  // TString outputfile = ;
+  // outputfile += ":PWG2forwardDnDeta"; 
+  // Form(":%s",pars->GetDndetaAnalysisName());
+  AliAnalysisDataContainer* histOut = 
+    mgr->CreateContainer("Forward", TList::Class(), 
+                        AliAnalysisManager::kOutputContainer,
+                        AliAnalysisManager::GetCommonFileName());
+  AliAnalysisDataContainer *output = 
+    mgr->CreateContainer("ForwardResults", TList::Class(), 
+                        AliAnalysisManager::kParamContainer, 
+                        AliAnalysisManager::GetCommonFileName());
+  mgr->ConnectInput(task, 0, mgr->GetCommonInputContainer());
+  mgr->ConnectOutput(task, 1, histOut);
+  mgr->ConnectOutput(task, 2, output);
+
+
+  return task;
+}
diff --git a/PWG2/FORWARD/analysis2/AliForwardQATask.cxx b/PWG2/FORWARD/analysis2/AliForwardQATask.cxx
new file mode 100644 (file)
index 0000000..5c0eb31
--- /dev/null
@@ -0,0 +1,432 @@
+// 
+// Calculate the multiplicity in the forward regions event-by-event 
+// 
+// Inputs: 
+//   - AliESDEvent 
+//
+// Outputs: 
+//   - AliAODForwardMult 
+// 
+// Histograms 
+//   
+// Corrections used 
+//
+#include "AliForwardQATask.h"
+#include "AliForwardUtil.h"
+#include "AliTriggerAnalysis.h"
+#include "AliPhysicsSelection.h"
+#include "AliLog.h"
+#include "AliESDEvent.h"
+#include "AliAODHandler.h"
+#include "AliMultiplicity.h"
+#include "AliInputEventHandler.h"
+#include "AliForwardCorrectionManager.h"
+#include "AliAnalysisManager.h"
+#include "AliAODForwardMult.h"
+#include <TH1.h>
+#include <TDirectory.h>
+#include <TTree.h>
+#include <TROOT.h>
+
+
+//====================================================================
+AliForwardQATask::AliForwardQATask()
+  : AliAnalysisTaskSE(),
+    fEnableLowFlux(false), 
+    fFirstEvent(true),
+    fCorrManager(0),
+    fESDFMD(),
+    fHistos(),
+    fEventInspector(),
+    fEnergyFitter(),
+    fSharingFilter(),
+    fDensityCalculator(),
+    fList(0)
+{
+  // 
+  // Constructor
+  //
+}
+
+//____________________________________________________________________
+AliForwardQATask::AliForwardQATask(const char* name)
+  : AliAnalysisTaskSE(name),
+    fEnableLowFlux(false), 
+    fFirstEvent(true),
+    fCorrManager(0),
+    fESDFMD(),
+    fHistos(),
+    fEventInspector("event"),
+    fEnergyFitter("energy"),
+    fSharingFilter("sharing"), 
+    fDensityCalculator("density"),
+    fList(0)
+{
+  // 
+  // Constructor 
+  // 
+  // Parameters:
+  //    name Name of task 
+  //
+  DefineOutput(1, TList::Class());
+  DefineOutput(2, TList::Class());
+  fCorrManager = &AliForwardCorrectionManager::Instance(); 
+  fEnergyFitter.SetNParticles(1); // Just find the 1st peak 
+  fEnergyFitter.SetDoMakeObject(false); 
+  fEnergyFitter.SetUseIncreasingBins(true);
+  fEnergyFitter.SetDoFits(kTRUE);
+  fEnergyFitter.SetLowCut(0.4);
+  fEnergyFitter.SetFitRangeBinWidth(4);
+  fEnergyFitter.SetMinEntries(1000);
+}
+
+//____________________________________________________________________
+AliForwardQATask::AliForwardQATask(const AliForwardQATask& o)
+  : AliAnalysisTaskSE(o),
+    fEnableLowFlux(o.fEnableLowFlux), 
+    fFirstEvent(o.fFirstEvent),
+    fCorrManager(o.fCorrManager),
+    fESDFMD(o.fESDFMD),
+    fHistos(o.fHistos),
+    fEventInspector(o.fEventInspector),
+    fEnergyFitter(o.fEnergyFitter),
+    fSharingFilter(o.fSharingFilter),
+    fDensityCalculator(o.fDensityCalculator),
+    fList(o.fList) 
+{
+  // 
+  // Copy constructor 
+  // 
+  // Parameters:
+  //    o Object to copy from 
+  //
+  DefineOutput(1, TList::Class());
+  DefineOutput(2, TList::Class());
+}
+
+//____________________________________________________________________
+AliForwardQATask&
+AliForwardQATask::operator=(const AliForwardQATask& o)
+{
+  // 
+  // Assignment operator 
+  // 
+  // Parameters:
+  //    o Object to assign from 
+  // 
+  // Return:
+  //    Reference to this object 
+  //
+  AliAnalysisTaskSE::operator=(o);
+
+  fEnableLowFlux     = o.fEnableLowFlux;
+  fFirstEvent        = o.fFirstEvent;
+  fCorrManager       = o.fCorrManager;
+  fEventInspector    = o.fEventInspector;
+  fEnergyFitter      = o.fEnergyFitter;
+  fSharingFilter     = o.fSharingFilter;
+  fDensityCalculator = o.fDensityCalculator;
+  fHistos            = o.fHistos;
+  fList              = o.fList;
+
+  return *this;
+}
+
+//____________________________________________________________________
+void
+AliForwardQATask::SetDebug(Int_t dbg)
+{
+  // 
+  // Set debug level 
+  // 
+  // Parameters:
+  //    dbg Debug level
+  //
+  fEventInspector.SetDebug(dbg);
+  fEnergyFitter.SetDebug(dbg);
+  fSharingFilter.SetDebug(dbg);
+  fDensityCalculator.SetDebug(dbg);
+}
+
+//____________________________________________________________________
+Bool_t 
+AliForwardQATask::CheckCorrections(UInt_t what) const
+{
+  // 
+  // Check if all needed corrections are there and accounted for.  If not,
+  // do a Fatal exit 
+  // 
+  // Parameters:
+  //    what Which corrections is needed
+  // 
+  // Return:
+  //    true if all present, false otherwise
+  //  
+
+  AliForwardCorrectionManager& fcm = AliForwardCorrectionManager::Instance();
+  // Check that we have the energy loss fits, needed by 
+  //   AliFMDSharingFilter 
+  //   AliFMDDensityCalculator 
+  if (what & AliForwardCorrectionManager::kELossFits && !fcm.GetELossFit()) { 
+    AliFatal(Form("No energy loss fits"));
+    return false;
+  }
+  return true;
+}
+
+//____________________________________________________________________
+Bool_t
+AliForwardQATask::ReadCorrections(const TAxis*& pe, 
+                                 const TAxis*& pv, 
+                                 Bool_t        mc)
+{
+  //
+  // Read corrections
+  //
+  //
+  UInt_t what = AliForwardCorrectionManager::kAll;
+  what ^= AliForwardCorrectionManager::kDoubleHit;
+  what ^= AliForwardCorrectionManager::kVertexBias;
+  what ^= AliForwardCorrectionManager::kAcceptance;
+  what ^= AliForwardCorrectionManager::kMergingEfficiency;
+
+  AliForwardCorrectionManager& fcm = AliForwardCorrectionManager::Instance();
+  if (!fcm.Init(GetEventInspector().GetCollisionSystem(),
+               GetEventInspector().GetEnergy(),
+               GetEventInspector().GetField(),
+               mc,
+               what)) return false;
+  if (!CheckCorrections(what)) return false;
+
+  // Sett our persistency pointer 
+  // fCorrManager = &fcm;
+
+  // Get the eta axis from the secondary maps - if read in
+  if (!pe) {
+    pe = fcm.GetEtaAxis();
+    if (!pe) AliFatal("No eta axis defined");
+  }
+  // Get the vertex axis from the secondary maps - if read in
+  if (!pv) {
+    pv = fcm.GetVertexAxis();
+    if (!pv) AliFatal("No vertex axis defined");
+  }
+
+  return true;
+}
+
+//____________________________________________________________________
+AliESDEvent*
+AliForwardQATask::GetESDEvent()
+{
+  //
+  // Get the ESD event. IF this is the first event, initialise
+  //
+  AliESDEvent* esd = dynamic_cast<AliESDEvent*>(InputEvent());
+  if (!esd) {
+    AliWarning("No ESD event found for input event");
+    return 0;
+  }
+
+  // On the first event, initialize the parameters
+  if (fFirstEvent && esd->GetESDRun()) {
+    GetEventInspector().ReadRunDetails(esd);
+
+    AliInfo(Form("Initializing with parameters from the ESD:\n"
+                 "         AliESDEvent::GetBeamEnergy()   ->%f\n"
+                 "         AliESDEvent::GetBeamType()     ->%s\n"
+                 "         AliESDEvent::GetCurrentL3()    ->%f\n"
+                 "         AliESDEvent::GetMagneticField()->%f\n"
+                 "         AliESDEvent::GetRunNumber()    ->%d\n",
+                 esd->GetBeamEnergy(),
+                 esd->GetBeamType(),
+                 esd->GetCurrentL3(),
+                 esd->GetMagneticField(),
+                 esd->GetRunNumber()));
+
+    fFirstEvent = false;
+
+    InitializeSubs();
+  }
+  return esd;
+}
+//____________________________________________________________________
+void
+AliForwardQATask::InitializeSubs()
+{
+  // 
+  // Initialise the sub objects and stuff.  Called on first event 
+  // 
+  //
+  const TAxis* pe = 0;
+  const TAxis* pv = 0;
+
+  if (!ReadCorrections(pe,pv)) return;
+
+  fHistos.Init(*pe);
+
+  fEventInspector.Init(*pv);
+  fEnergyFitter.Init(*pe);
+  fSharingFilter.Init();
+  fDensityCalculator.Init(*pe);
+
+  this->Print();
+}
+
+//____________________________________________________________________
+void
+AliForwardQATask::UserCreateOutputObjects()
+{
+  // 
+  // Create output objects 
+  // 
+  //
+  fList = new TList;
+  fList->SetOwner();
+  
+  fEventInspector.DefineOutput(fList);
+  fEnergyFitter.DefineOutput(fList);
+  fSharingFilter.DefineOutput(fList);
+  fDensityCalculator.DefineOutput(fList);
+
+  PostData(1, fList);
+}
+//____________________________________________________________________
+void
+AliForwardQATask::UserExec(Option_t*)
+{
+  // 
+  // Process each event 
+  // 
+  // Parameters:
+  //    option Not used
+  //  
+
+  // static Int_t cnt = 0;
+  // cnt++;
+  // Get the input data 
+  AliESDEvent* esd = GetESDEvent();
+
+  // Clear stuff 
+  fHistos.Clear();
+  fESDFMD.Clear();
+  
+  Bool_t   lowFlux   = kFALSE;
+  UInt_t   triggers  = 0;
+  UShort_t ivz       = 0;
+  Double_t vz        = 0;
+  Double_t cent      = -1;
+  UShort_t nClusters = 0;
+  UInt_t   found     = fEventInspector.Process(esd, triggers, lowFlux, 
+                                              ivz, vz, cent, nClusters);
+  
+  if (found & AliFMDEventInspector::kNoEvent)    return;
+  if (found & AliFMDEventInspector::kNoTriggers) return;
+  if (found & AliFMDEventInspector::kNoSPD)      return;
+  if (found & AliFMDEventInspector::kNoFMD)      return;
+  if (found & AliFMDEventInspector::kNoVertex)   return;
+  if (triggers & AliAODForwardMult::kPileUp)     return;
+  if (found & AliFMDEventInspector::kBadVertex)  return;
+
+  // We we do not want to use low flux specific code, we disable it here. 
+  if (!fEnableLowFlux) lowFlux = false;
+
+  // Get FMD data 
+  AliESDFMD* esdFMD = esd->GetFMDData();
+  
+  // Run the energy loss fitter 
+  if (!fEnergyFitter.Accumulate(*esdFMD, cent, 
+                               triggers & AliAODForwardMult::kEmpty)) {
+    AliWarning("Energy fitter failed");
+    return;
+  }
+    
+  //  // Apply the sharing filter (or hit merging or clustering if you like)
+  if (!fSharingFilter.Filter(*esdFMD, lowFlux, fESDFMD)) { 
+    AliWarning("Sharing filter failed!");
+    return;
+  }
+
+  // Calculate the inclusive charged particle density 
+  if (!fDensityCalculator.Calculate(fESDFMD, fHistos, ivz, lowFlux)) { 
+    // if (!fDensityCalculator.Calculate(*esdFMD, fHistos, ivz, lowFlux)) { 
+    AliWarning("Density calculator failed!");
+    return;
+  }
+  PostData(1, fList);
+}
+
+//____________________________________________________________________
+void
+AliForwardQATask::Terminate(Option_t*)
+{
+  // 
+  // End of job
+  // 
+  // Parameters:
+  //    option Not used 
+  //
+
+  TList* list = dynamic_cast<TList*>(GetOutputData(1));
+  if (!list) {
+    AliError(Form("No output list defined (%p)", GetOutputData(1)));
+    if (GetOutputData(1)) GetOutputData(1)->Print();
+    return;
+  }
+  
+  // Get our histograms from the container 
+  TH1I* hEventsTr    = 0;//static_cast<TH1I*>(list->FindObject("nEventsTr"));
+  TH1I* hEventsTrVtx = 0;//static_cast<TH1I*>(list->FindObject("nEventsTrVtx"));
+  TH1I* hTriggers    = 0;
+  if (!fEventInspector.FetchHistograms(list, hEventsTr, 
+                                      hEventsTrVtx, hTriggers)) { 
+    AliError(Form("Didn't get histograms from event selector "
+                 "(hEventsTr=%p,hEventsTrVtx=%p)", 
+                 hEventsTr, hEventsTrVtx));
+    return;
+  }
+
+  fEnergyFitter.Fit(list);
+
+  fSharingFilter.ScaleHistograms(list,Int_t(hEventsTr->Integral()));
+  fDensityCalculator.ScaleHistograms(list,Int_t(hEventsTrVtx->Integral()));
+
+  // Make a deep copy and post that as output 2 
+  TList* list2 = static_cast<TList*>(list->Clone(Form("%sResults", 
+                                                     list->GetName())));
+  list2->SetOwner();
+  PostData(2, list2);
+
+}
+
+//____________________________________________________________________
+void
+AliForwardQATask::Print(Option_t* option) const
+{
+  // 
+  // Print information 
+  // 
+  // Parameters:
+  //    option Not used
+  //
+  
+  std::cout << ClassName() << ": " << GetName() << "\n" 
+           << "  Enable low flux code:   " << (fEnableLowFlux ? "yes" : "no") 
+           << "\n"
+           << "  Off-line trigger mask:  0x" 
+           << std::hex     << std::setfill('0') 
+           << std::setw (8) << fOfflineTriggerMask 
+           << std::dec     << std::setfill (' ') << std::endl;
+  gROOT->IncreaseDirLevel();
+  if (fCorrManager) fCorrManager->Print();
+  else  
+    std::cout << "  Correction manager not set yet" << std::endl;
+  GetEventInspector()   .Print(option);
+  GetEnergyFitter()     .Print(option);
+  GetSharingFilter()    .Print(option);
+  gROOT->DecreaseDirLevel();
+}
+
+//
+// EOF
+//
diff --git a/PWG2/FORWARD/analysis2/AliForwardQATask.h b/PWG2/FORWARD/analysis2/AliForwardQATask.h
new file mode 100644 (file)
index 0000000..af360a8
--- /dev/null
@@ -0,0 +1,211 @@
+// 
+// Calculate the qa in the forward regions event-by-event 
+// 
+#ifndef ALIFORWARDQATASK_H
+#define ALIFORWARDQATASK_H
+/**
+ * @file   AliForwardQATask.h
+ * @author Christian Holm Christensen <cholm@dalsgaard.hehi.nbi.dk>
+ * @date   Wed Mar 23 14:06:42 2011
+ * 
+ * @brief  
+ * 
+ * 
+ * @ingroup pwg2_forward_aod
+ */
+#include <AliAnalysisTaskSE.h>
+#include "AliFMDEventInspector.h"
+#include "AliFMDSharingFilter.h"
+#include "AliFMDDensityCalculator.h"
+#include "AliFMDEnergyFitter.h"
+#include <AliESDFMD.h>
+class AliForwardCorrectionManager;
+class AliESDEvent;
+class TH2D;
+class TList;
+class TAxis;
+
+/** 
+ * Calculate the QA in the forward regions
+ * 
+ * @par Inputs: 
+ *   - AliESDEvent 
+ *
+ * @par Outputs: 
+ *   - Histograms 
+ * 
+ * @par Histograms 
+ *   
+ * @par Corrections used 
+ * 
+ * @ingroup pwg2_forward_tasks
+ * 
+ */
+class AliForwardQATask : public AliAnalysisTaskSE
+{
+public:
+  /** 
+   * Constructor 
+   * 
+   * @param name Name of task 
+   */
+  AliForwardQATask(const char* name);
+  /** 
+   * Constructor
+   */
+  AliForwardQATask();
+  /** 
+   * Copy constructor 
+   * 
+   * @param o Object to copy from 
+   */
+  AliForwardQATask(const AliForwardQATask& o);
+  /** 
+   * Assignment operator 
+   * 
+   * @param o Object to assign from 
+   * 
+   * @return Reference to this object 
+   */
+  AliForwardQATask& operator=(const AliForwardQATask& o);
+  /** 
+   * @{ 
+   * @name Interface methods 
+   */
+  /** 
+   * Create output objects 
+   * 
+   */
+  virtual void UserCreateOutputObjects();
+  /** 
+   * Process each event 
+   *
+   * @param option Not used
+   */  
+  virtual void UserExec(Option_t* option);
+  /** 
+   * End of job
+   * 
+   * @param option Not used 
+   */
+  virtual void Terminate(Option_t* option);
+  /** 
+   * @} 
+   */
+  /** 
+   * @{ 
+   * @name Access to sub-algorithms 
+   */
+  /**
+   * Get reference to the EventInspector algorithm 
+   * 
+   * @return Reference to AliFMDEventInspector object 
+   */
+  AliFMDEventInspector& GetEventInspector() { return fEventInspector; }
+  /**
+   * Get reference to the EnergyFitter algorithm 
+   * 
+   * @return Reference to AliFMDEnergyFitter object 
+   */
+  AliFMDEnergyFitter& GetEnergyFitter() { return fEnergyFitter; }
+  /**
+   * Get reference to the SharingFilter algorithm 
+   * 
+   * @return Reference to AliFMDSharingFilter object 
+   */
+  AliFMDSharingFilter& GetSharingFilter() { return fSharingFilter; }
+  /**
+   * Get reference to the DensityCalculator algorithm 
+   * 
+   * @return Reference to AliFMDDensityCalculator object 
+   */
+  AliFMDDensityCalculator& GetDensityCalculator() { return fDensityCalculator; }
+  /**
+   * Get reference to the EventInspector algorithm 
+   * 
+   * @return Reference to AliFMDEventInspector object 
+   */
+  const AliFMDEventInspector& GetEventInspector() const { return fEventInspector; }
+  /**
+   * Get reference to the EnergyFitter algorithm 
+   * 
+   * @return Reference to AliFMDEnergyFitter object 
+   */
+  const AliFMDEnergyFitter& GetEnergyFitter() const { return fEnergyFitter; }
+  /**
+   * Get reference to the SharingFilter algorithm 
+   * 
+   * @return Reference to AliFMDSharingFilter object 
+   */
+  const AliFMDSharingFilter& GetSharingFilter() const { return fSharingFilter; }
+  /**
+   * Get reference to the DensityCalculator algorithm 
+   * 
+   * @return Reference to AliFMDDensityCalculator object 
+   */
+  const AliFMDDensityCalculator& GetDensityCalculator() const { return fDensityCalculator; }
+  /** 
+   * @} 
+   */
+  /** 
+   * Set debug level 
+   * 
+   * @param dbg Debug level
+   */
+  void SetDebug(Int_t dbg);
+  void Print(Option_t* option="") const;
+protected: 
+  /** 
+   * Check if all needed corrections are there and accounted for.  If not,
+   * do a Fatal exit 
+   * 
+   * @param what Which corrections is needed
+   * 
+   * @return true if all present, false otherwise
+   */  
+  Bool_t CheckCorrections(UInt_t what) const;
+  /**
+   * Read corrections
+   *
+   */
+  virtual Bool_t ReadCorrections(const TAxis*& pe, 
+                                const TAxis*& pv,
+                                Bool_t mc=false);
+  /**
+   * Get the ESD event. IF this is the first event, initialise
+   */
+  virtual AliESDEvent* GetESDEvent();
+  /** 
+   * Initialise the sub objects and stuff.  Called on first event 
+   * 
+   */
+  virtual void   InitializeSubs();
+
+  Bool_t fEnableLowFlux;// Whether to use low-flux specific code
+  Bool_t fFirstEvent;   // Whether the event is the first seen 
+  /**
+   * A pointer to the corrections manager.  This is here to make the
+   * corrections manager persistent - that is, when we write the
+   * analysis train to a file (as done in PROOF) we should also write
+   * down the corrections mananger.   This pointer ensures that. 
+   */
+  AliForwardCorrectionManager* fCorrManager; // Pointer to corrections manager
+
+  AliESDFMD              fESDFMD;       // Sharing corrected ESD object
+  AliForwardUtil::Histos fHistos;       // Cache histograms 
+
+  AliFMDEventInspector    fEventInspector;    // Algorithm
+  AliFMDEnergyFitter      fEnergyFitter;      // Algorithm
+  AliFMDSharingFilter     fSharingFilter;     // Algorithm
+  AliFMDDensityCalculator fDensityCalculator; // Algorithm
+
+  TList* fList; // Output list 
+
+  ClassDef(AliForwardQATask,1) // Forward QA class
+};
+
+#endif
+// Local Variables:
+//  mode: C++
+// End:
+
diff --git a/PWG2/FORWARD/analysis2/trains/MakeQATrain.C b/PWG2/FORWARD/analysis2/trains/MakeQATrain.C
new file mode 100644 (file)
index 0000000..9972a6f
--- /dev/null
@@ -0,0 +1,121 @@
+#include "TrainSetup.C"
+
+//====================================================================
+/**
+ * Analysis train to do energy loss fits
+ * 
+ * @ingroup pwg2_forward_trains
+ */
+class MakeQATrain : public TrainSetup
+{
+public:
+  /** 
+   * Constructor.  Date and time must be specified when running this
+   * in Termiante mode on Grid
+   * 
+   * @param name     Name of train 
+   * @param useCent  Whether to use centrality or not 
+   * @param dateTime Append date and time to name
+   * @param year     Year
+   * @param month    Month 
+   * @param day      Day
+   * @param hour     Hour 
+   * @param min      Minutes
+   */
+  MakeQATrain(const char* name  = "Forward QA",
+             Bool_t   useCent  = false,
+             Bool_t   dateTime = false, 
+             UShort_t year     = 0, 
+             UShort_t month    = 0, 
+             UShort_t day      = 0, 
+             UShort_t hour     = 0, 
+             UShort_t min      = 0) 
+    : TrainSetup(name, dateTime, year, month, day, hour, min), 
+      fUseCent(useCent)
+  {}
+  //__________________________________________________________________
+  /** 
+   * Run this analysis 
+   * 
+   * @param mode     Mode
+   * @param oper     Operation
+   * @param nEvents  Number of events (negative means all)
+   * @param mc       If true, assume simulated events 
+   * @param par      IF true, use par files 
+   */
+  void Run(const char* mode, const char* oper, 
+          Int_t nEvents=-1, Bool_t mc=false, Bool_t par=false)
+  {
+    Exec("ESD", mode, oper, nEvents, mc, par);
+  }
+  //__________________________________________________________________
+  /** 
+   * Run this analysis 
+   * 
+   * @param mode     Mode
+   * @param oper     Operation
+   * @param nEvents  Number of events (negative means all)
+   * @param mc       If true, assume simulated events 
+   * @param par      IF true, use par files 
+   */
+  void Run(EMode mode, EOper oper, Int_t nEvents=-1, Bool_t mc=false,
+          Bool_t par=false)
+  {
+    Exec(kESD, mode, oper, nEvents, mc, par);
+  }
+protected:
+  //__________________________________________________________________
+  /** 
+   * Create the tasks 
+   * 
+   * @param mode Processing mode
+   * @param par  Whether to use par files 
+   * @param mgr  Analysis manager 
+   */
+  void CreateTasks(EMode mode, Bool_t par, AliAnalysisManager* mgr)
+  {
+    // --- Output file name ------------------------------------------
+    AliAnalysisManager::SetCommonFileName("forward_eloss.root");
+
+    // --- Load libraries/pars ---------------------------------------
+    LoadLibrary("PWG2forward2", mode, par, true);
+    
+    // --- Set load path ---------------------------------------------
+    gROOT->SetMacroPath(Form("%s:$(ALICE_ROOT)/PWG2/FORWARD/analysis2",
+                            gROOT->GetMacroPath()));
+
+    // --- Check if this is MC ---------------------------------------
+    Bool_t mc = mgr->GetMCtruthEventHandler() != 0;
+
+    // --- Add the task ----------------------------------------------
+    gROOT->Macro(Form("AddTaskForwardQA.C(%d,%d)", mc, fUseCent));
+  }
+  /** 
+   * Create entrality selection if enabled 
+   * 
+   * @param mc   Whether this is MC or not
+   * @param mgr  Analysis manager 
+   */
+  virtual void CreateCentralitySelection(Bool_t mc, AliAnalysisManager* mgr)
+  {
+    if (!fUseCent) return;
+
+    gROOT->Macro("AddTaskCentrality.C");
+    AliCentralitySelectionTask* ctask = 
+      dynamic_cast<AliCentralitySelectionTask*>(mgr->GetTask("CentralitySelection"));
+    if (!ctask) return;
+    ctask->SetPass(fESDPass);
+    if (mc) ctask->SetMCInput();
+  }
+  /** 
+   * Crete output handler - we don't want one here. 
+   * 
+   * @return 0
+   */
+  AliVEventHandler* CreateOutputHandler(EType) { return 0; }
+  Bool_t fUseCent; // Whether to use centrality or not 
+};
+
+//
+// EOF
+//