]> git.uio.no Git - u/mrichter/AliRoot.git/commitdiff
- For energy loss fits, add option to store residuals
authorcholm <cholm@f7af4fe6-9843-0410-8265-dc069ae4e863>
Tue, 27 Aug 2013 14:02:07 +0000 (14:02 +0000)
committercholm <cholm@f7af4fe6-9843-0410-8265-dc069ae4e863>
Tue, 27 Aug 2013 14:02:07 +0000 (14:02 +0000)
- For energy loss fits, add option to regularize in case of
  large statistics.
- Fixes to drawers and corr DB browser
- Fixes to analysis scripts

19 files changed:
PWGLF/FORWARD/analysis2/AddTaskFMDELoss.C
PWGLF/FORWARD/analysis2/AliFMDCorrELossFit.cxx
PWGLF/FORWARD/analysis2/AliFMDEnergyFitter.cxx
PWGLF/FORWARD/analysis2/AliFMDEnergyFitter.h
PWGLF/FORWARD/analysis2/AliFMDEnergyFitterTask.cxx
PWGLF/FORWARD/analysis2/AliFMDEventInspector.cxx
PWGLF/FORWARD/analysis2/AliFMDEventInspector.h
PWGLF/FORWARD/analysis2/AliFMDMCEventInspector.cxx
PWGLF/FORWARD/analysis2/AliFMDMCEventInspector.h
PWGLF/FORWARD/analysis2/AliForwardUtil.cxx
PWGLF/FORWARD/analysis2/baseAnalysis.sh
PWGLF/FORWARD/analysis2/corrs/CorrDrawer.C
PWGLF/FORWARD/analysis2/corrs/DrawCorrELoss.C
PWGLF/FORWARD/analysis2/corrs/ForwardOADBGui.C
PWGLF/FORWARD/analysis2/corrs/RerunELossFits.C
PWGLF/FORWARD/analysis2/gridAnalysis.sh
PWGLF/FORWARD/analysis2/scripts/SummaryMCCorrDrawer.C
PWGLF/FORWARD/analysis2/trains/MakeFMDELossTrain.C
PWGLF/FORWARD/analysis2/trains/MakeQATrain.C

index dbfd5af4c9b456b4ae9706e6038b0df46dfe0720..4d46824ea862c18c523bdc6ce842d42f804d3b77 100644 (file)
@@ -28,7 +28,8 @@
  * @ingroup pwglf_forward_eloss
  */
 AliAnalysisTask*
-AddTaskFMDELoss(Bool_t mc, Bool_t useCent, Int_t debug=0)
+AddTaskFMDELoss(Bool_t mc, Bool_t useCent, Int_t debug=0,
+               const Char_t* residuals="")
 {
   // --- Load libraries ----------------------------------------------
   gROOT->LoadClass("AliAODForwardMult", "libPWGLFforward2");
@@ -79,6 +80,20 @@ AddTaskFMDELoss(Bool_t mc, Bool_t useCent, Int_t debug=0)
   // Debug 
   task->SetDebug(debug);
 
+  TString resi(residuals);
+  resi.ToUpper();
+  AliFMDEnergyFitter::EResidualMethod rm = AliFMDEnergyFitter::kNoResiduals;
+  if (!resi.IsNull() && !resi.BeginsWith("no")) {
+    if (resi.BeginsWith("square")) 
+      rm = AliFMDEnergyFitter::kResidualSquareDifference;
+    else if (resi.BeginsWith("scale")) 
+      rm = AliFMDEnergyFitter::kResidualScaledDifference;
+    else // Anything else gives plain difference and errors in errors
+      rm = AliFMDEnergyFitter::kResidualDifference;
+  }
+  Printf("Got residual: \"%s\" -> %d", resi.Data(), rm);
+  task->GetEnergyFitter().SetStoreResiduals(rm);
+
   // --- Set limits on fits the energy -------------------------------
   // DO NOT CHANGE THESE UNLESS YOU KNOW WHAT YOU ARE DOING
   // Maximum relative error on parameters 
index 303e3a79a452c3ae7a547eba0946ee940da3ba58..e1abbd9311b233fd21f8dc3ddaece8bf5cfb9cf1 100644 (file)
@@ -511,15 +511,15 @@ AliFMDCorrELossFit::ELossFit::Draw(Option_t* option)
   
   if (!opt.Contains("SAME")) {
     TH1* frame = new TH1F(GetName(), 
-                         Form("FMD%d%c, eta bin %d",fDet,fRing,fBin),
-                         100, 0, 10);
+                    Form("FMD%d%c, eta bin %d",fDet,fRing,fBin),
+                    100, 0, 10);
     frame->SetMinimum(max/10000);
     frame->SetMaximum(max*1.4);
     frame->SetXTitle("#Delta / #Delta_{mip}");
     frame->Draw();
     opt.Append(" SAME");
   }
-  tot->DrawCopy(opt.Data());
+  TF1* cpy = tot->DrawCopy(opt.Data());
   cleanup.Add(tot);
 
   if (vals) { 
@@ -588,9 +588,13 @@ AliFMDCorrELossFit::ELossFit::Draw(Option_t* option)
     cleanup.Add(f);
   }
   min /= 100;
-  tot->GetHistogram()->SetMaximum(max);
-  tot->GetHistogram()->SetMinimum(min);
-  tot->GetHistogram()->GetYaxis()->SetRangeUser(min, max);
+  if (max <= 0) max = 0.1;
+  if (min <= 0) min = 1e-4;
+  cpy->SetMaximum(max);
+  cpy->SetMinimum(min);
+  cpy->GetHistogram()->SetMaximum(max);
+  cpy->GetHistogram()->SetMinimum(min);
+  cpy->GetHistogram()->GetYaxis()->SetRangeUser(min, max);
   if (l) l->Draw();
 
   gPad->cd();
@@ -643,6 +647,8 @@ AliFMDCorrELossFit::ELossFit::CalculateQuality(Double_t maxChi2nu,
   if (CHECKPAR(fXi,     fEXi,     maxRelError)) qual++;
   if (CHECKPAR(fSigma,  fESigma,  maxRelError)) qual++;
   if (CHECKPAR(fSigmaN, fESigmaN, maxRelError)) qual++;
+  // Large penalty for large sigma - often a bad fit. 
+  if (fSigma > 10*fXi)                          qual -= 4; 
   qual += FindMaxWeight(2*maxRelError, leastWeight, fN);
   fQuality = qual;
 }
index e173467e0cf84084e51981d612ce199ee076e92c..affcc8131404fce608e53f84e896f2d7322e31fc 100644 (file)
@@ -44,7 +44,10 @@ AliFMDEnergyFitter::AliFMDEnergyFitter()
     fMaxRelParError(AliFMDCorrELossFit::ELossFit::fgMaxRelError),
     fMaxChi2PerNDF(AliFMDCorrELossFit::ELossFit::fgMaxChi2nu), 
     fMinWeight(AliFMDCorrELossFit::ELossFit::fgLeastWeight),
-    fDebug(0)
+    fDebug(0),
+    fResidualMethod(kNoResiduals),
+    fSkips(0),
+    fRegularizationCut(3e6)
 {
   // 
   // Default Constructor - do not use 
@@ -71,7 +74,10 @@ AliFMDEnergyFitter::AliFMDEnergyFitter(const char* title)
     fMaxRelParError(AliFMDCorrELossFit::ELossFit::fgMaxRelError),
     fMaxChi2PerNDF(AliFMDCorrELossFit::ELossFit::fgMaxChi2nu), 
     fMinWeight(AliFMDCorrELossFit::ELossFit::fgLeastWeight),
-    fDebug(3)
+    fDebug(3),
+    fResidualMethod(kNoResiduals),
+    fSkips(0),
+    fRegularizationCut(3e6)
 {
   // 
   // Constructor 
@@ -109,7 +115,10 @@ AliFMDEnergyFitter::AliFMDEnergyFitter(const AliFMDEnergyFitter& o)
     fMaxRelParError(o.fMaxRelParError),
     fMaxChi2PerNDF(o.fMaxChi2PerNDF), 
     fMinWeight(o.fMinWeight),
-    fDebug(o.fDebug)
+    fDebug(o.fDebug),
+    fResidualMethod(o.fResidualMethod),
+    fSkips(o.fSkips),
+    fRegularizationCut(o.fRegularizationCut)
 {
   // 
   // Copy constructor 
@@ -168,10 +177,13 @@ AliFMDEnergyFitter::operator=(const AliFMDEnergyFitter& o)
     fCentralityAxis.Set(o.fCentralityAxis.GetNbins(),
                        o.fCentralityAxis.GetXmin(),
                        o.fCentralityAxis.GetXmax());
-  fDebug         = o.fDebug;
-  fMaxRelParError= o.fMaxRelParError;
-  fMaxChi2PerNDF = o.fMaxChi2PerNDF;
-  fMinWeight     = o.fMinWeight;
+  fDebug             = o.fDebug;
+  fMaxRelParError    = o.fMaxRelParError;
+  fMaxChi2PerNDF     = o.fMaxChi2PerNDF;
+  fMinWeight         = o.fMinWeight;
+  fResidualMethod    = o.fResidualMethod;
+  fSkips             = o.fSkips;
+  fRegularizationCut = o.fRegularizationCut;
 
   fRingHistos.Clear();
   TIter    next(&o.fRingHistos);
@@ -371,10 +383,16 @@ AliFMDEnergyFitter::Fit(const TList* dir)
   TIter    next(&fRingHistos);
   RingHistos* o = 0;
   while ((o = static_cast<RingHistos*>(next()))) {
+    if (CheckSkip(o->fDet, o->fRing, fSkips)) {
+      AliWarningF("Skipping FMD%d%c for fitting", o->fDet, o->fRing);
+      continue;
+    }
+    
     TObjArray* l = o->Fit(d, fEtaAxis, fLowCut, fNParticles,
                          fMinEntries, fFitRangeBinWidth,
                          fMaxRelParError, fMaxChi2PerNDF,
-                         fMinWeight);
+                         fMinWeight, fRegularizationCut,
+                         fResidualMethod);
     if (!l) continue;
     for (Int_t i = 0; i < l->GetEntriesFast()-1; i++) { // Last is status 
       stack[i % nStack]->Add(static_cast<TH1*>(l->At(i))); 
@@ -405,6 +423,11 @@ AliFMDEnergyFitter::MakeCorrectionsObject(TList* d)
   TIter    next(&fRingHistos);
   RingHistos* o = 0;
   while ((o = static_cast<RingHistos*>(next()))) {
+    if (CheckSkip(o->fDet, o->fRing, fSkips)) {
+      AliWarningF("Skipping FMD%d%c for correction object", o->fDet, o->fRing);
+      continue;
+    }
+    
     o->FindBestFits(d, *obj, fEtaAxis, fMaxRelParError, 
                    fMaxChi2PerNDF, fMinWeight);
   }
@@ -442,6 +465,7 @@ AliFMDEnergyFitter::CreateOutputObjects(TList* dir)
   d->Add(AliForwardUtil::MakeParameter("maxRelPerError",fMaxRelParError));
   d->Add(AliForwardUtil::MakeParameter("maxChi2PerNDF", fMaxChi2PerNDF));
   d->Add(AliForwardUtil::MakeParameter("minWeight",     fMinWeight));
+  d->Add(AliForwardUtil::MakeParameter("regCut",        fRegularizationCut));
   
   TIter    next(&fRingHistos);
   RingHistos* o = 0;
@@ -466,6 +490,69 @@ AliFMDEnergyFitter::SetDebug(Int_t dbg)
     o->fDebug = dbg;
 }  
 
+//____________________________________________________________________
+namespace {
+  template <typename T>
+  void GetParam(Bool_t& ret, const TCollection* col, 
+               const TString& name, T& var)
+  {
+    TObject* o = col->FindObject(name);              
+    if (o) AliForwardUtil::GetParameter(o,var); 
+    else   ret = false;                                
+  }
+}
+
+//____________________________________________________________________
+Bool_t
+AliFMDEnergyFitter::ReadParameters(const TCollection* col)
+{
+  // Read parameters of this object from a collection
+  //
+  // Parameters:
+  //    col   Collection to read parameters from 
+  // 
+  // Return value:
+  //   true on success, false otherwise 
+  //
+  if (!col) return false;
+  Bool_t ret = true;
+  TAxis* axis = static_cast<TAxis*>(col->FindObject("etaAxis"));
+  if (!axis) ret = false;
+  else {
+    if (axis->GetXbins()->GetArray()) 
+      fEtaAxis.Set(axis->GetNbins(), axis->GetXbins()->GetArray());
+    else 
+      fEtaAxis.Set(axis->GetNbins(), axis->GetXmin(), axis->GetXmax());
+  } 
+  GetParam(ret,col,"lowCut",        fLowCut);
+  GetParam(ret,col,"nParticles",    fNParticles);
+  GetParam(ret,col,"minEntries",    fMinEntries);
+  GetParam(ret,col,"subtractBins",  fFitRangeBinWidth);
+  GetParam(ret,col,"doFits",        fDoFits);
+  GetParam(ret,col,"doObject",      fDoMakeObject);
+  GetParam(ret,col,"maxE",          fMaxE);
+  GetParam(ret,col,"nEbins",        fNEbins);
+  GetParam(ret,col,"increasingBins",fUseIncreasingBins);
+  GetParam(ret,col,"maxRelPerError",fMaxRelParError);
+  GetParam(ret,col,"maxChi2PerNDF", fMaxChi2PerNDF);
+  GetParam(ret,col,"minWeight",     fMinWeight);
+  Bool_t dummy;
+  GetParam(dummy,col,"regCut",      fRegularizationCut);
+
+  return ret;
+}
+
+//____________________________________________________________________
+Bool_t
+AliFMDEnergyFitter::CheckSkip(UShort_t d, Char_t r, UShort_t skips) 
+{
+  UShort_t q  = (r == 'I' || r == 'i' ? 0 : 1);
+  UShort_t c = 1 << (d-1);
+  UShort_t t = 1 << (c+q-1);
+
+  return (t & skips) == t;
+}
+
 //____________________________________________________________________
 void
 AliFMDEnergyFitter::Print(Option_t*) const
@@ -495,7 +582,15 @@ AliFMDEnergyFitter::Print(Option_t*) const
            << (fUseIncreasingBins ?"yes\n" : "no\n")
            << ind << " max(delta p/p):         " << fMaxRelParError << '\n'
            << ind << " max(chi^2/nu):          " << fMaxChi2PerNDF << '\n'
-           << ind << " min(a_i):               " << fMinWeight << std::endl;
+           << ind << " min(a_i):               " << fMinWeight << '\n'
+           << ind << " Residuals:              "; 
+  switch (fResidualMethod) { 
+  case kNoResiduals: std::cout << "None"; break;
+  case kResidualDifference: std::cout << "Difference"; break;
+  case kResidualScaledDifference: std::cout << "Scaled difference"; break;
+  case kResidualSquareDifference: std::cout << "Square difference"; break;
+  }
+  std::cout << std::endl;
 }
   
 //====================================================================
@@ -513,6 +608,7 @@ AliFMDEnergyFitter::RingHistos::RingHistos()
   // Default CTOR
   //
   DGUARD(fDebug, 3, "Default CTOR AliFMDEnergyFitter::RingHistos");
+  fBest.Expand(0);
 }
 
 //____________________________________________________________________
@@ -535,6 +631,7 @@ AliFMDEnergyFitter::RingHistos::RingHistos(UShort_t d, Char_t r)
   //
   DGUARD(fDebug, 3, "Named CTOR AliFMDEnergyFitter::RingHistos: FMD%d%c",
         d, r);
+  fBest.Expand(0);
 }
 //____________________________________________________________________
 AliFMDEnergyFitter::RingHistos::RingHistos(const RingHistos& o)
@@ -922,7 +1019,9 @@ AliFMDEnergyFitter::RingHistos::Fit(TList*           dir,
                                    UShort_t         minusBins, 
                                    Double_t         relErrorCut, 
                                    Double_t         chi2nuCut,
-                                   Double_t         minWeight) const
+                                   Double_t         minWeight,
+                                   Double_t         regCut,
+                                   EResidualMethod  residuals) const
 {
   // 
   // Fit each histogram to up to @a nParticles particle responses.
@@ -956,6 +1055,15 @@ AliFMDEnergyFitter::RingHistos::Fit(TList*           dir,
     return 0;
   }
 
+  // Optional container for residuals 
+  TList* resi = 0;
+  if (residuals != kNoResiduals) {
+    resi = new TList();
+    resi->SetName("residuals");
+    resi->SetOwner();
+    l->Add(resi);
+  }
+
   // Container of the fit results histograms 
   TObjArray* pars  = new TObjArray(3+nParticles+1);
   pars->SetName("FitResults");
@@ -1026,14 +1134,15 @@ AliFMDEnergyFitter::RingHistos::Fit(TList*           dir,
     }
 
     // Now fit 
-    AliFMDCorrELossFit::ELossFit* res = FitHist(dist,i+1,lowCut,
-                                               nParticles,minusBins,
-                                               relErrorCut,chi2nuCut,
-                                               minWeight);
+    ELossFit_t* res = FitHist(dist,i+1,lowCut, nParticles,minusBins,
+                             relErrorCut,chi2nuCut,minWeight,regCut);
     if (!res) continue;
     nFitted++;
     fBest.AddAt(res, i+1);
     // dist->GetListOfFunctions()->Add(res);
+    
+    if (residuals != kNoResiduals && resi) 
+      CalculateResiduals(residuals, lowCut, dist, res, resi);
 
     // Store eta limits 
     low   = TMath::Min(low,i+1);
@@ -1080,9 +1189,8 @@ AliFMDEnergyFitter::RingHistos::Fit(TList*           dir,
     Double_t max = total->GetMaximum(); 
     if (max > 0) total->Scale(1/max);
     
-    AliFMDCorrELossFit::ELossFit* resT = 
-      FitHist(total,nDists+1,lowCut, nParticles,minusBins,
-             relErrorCut,chi2nuCut,minWeight);
+    ELossFit_t* resT = FitHist(total,nDists+1,lowCut, nParticles,minusBins,
+                              relErrorCut,chi2nuCut,minWeight,regCut);
     if (resT) { 
       // Make histograms for the result of this fit 
       Double_t chi2 = resT->GetChi2();
@@ -1159,7 +1267,7 @@ AliFMDEnergyFitter::RingHistos::Fit(TList*           dir,
 }
 
 //____________________________________________________________________
-AliFMDCorrELossFit::ELossFit*
+AliFMDEnergyFitter::RingHistos::ELossFit_t*
 AliFMDEnergyFitter::RingHistos::FitHist(TH1*     dist,
                                        UShort_t bin, 
                                        Double_t lowCut, 
@@ -1167,7 +1275,8 @@ AliFMDEnergyFitter::RingHistos::FitHist(TH1*     dist,
                                        UShort_t minusBins, 
                                        Double_t relErrorCut, 
                                        Double_t chi2nuCut,
-                                       Double_t minWeight) const
+                                       Double_t minWeight,
+                                       Double_t regCut) const
 {
   // 
   // Fit a signal histogram.  First, the bin @f$ b_{min}@f$ with
@@ -1201,8 +1310,18 @@ AliFMDEnergyFitter::RingHistos::FitHist(TH1*     dist,
   // Create a fitter object 
   AliForwardUtil::ELossFitter f(lowCut, maxRange, minusBins); 
   f.Clear();
-  f.SetDebug(fDebug > 2);
-  
+  f.SetDebug(fDebug > 2); 
+
+  // regularization cut - should be a parameter of the class 
+  if (dist->GetEntries() > regCut) { 
+    // We should rescale the errors 
+    Double_t s = TMath::Sqrt(dist->GetEntries() / regCut);
+    if (fDebug > 0) printf("Error scale: %f ", s);
+    for (Int_t i = 1; i <= dist->GetNbinsX(); i++) {
+      Double_t e = dist->GetBinError(i);
+      dist->SetBinError(i, e * s);
+    }
+  }
   // If we are only asked to fit a single particle, return this fit, 
   // no matter what. 
   if (nParticles == 1) {
@@ -1210,8 +1329,7 @@ AliFMDEnergyFitter::RingHistos::FitHist(TH1*     dist,
     if (!r) return 0;
     TF1* ff = new TF1(*r);
     dist->GetListOfFunctions()->Add(ff);
-    AliFMDCorrELossFit::ELossFit* ret = 
-      new AliFMDCorrELossFit::ELossFit(0, *ff);
+    ELossFit_t* ret = new ELossFit_t(0, *ff);
     ret->CalculateQuality(chi2nuCut, relErrorCut, minWeight);
     return ret;
   }
@@ -1228,200 +1346,9 @@ AliFMDEnergyFitter::RingHistos::FitHist(TH1*     dist,
 
   // Here, we use the real quality assesor instead of the old
   // `CheckResult' to ensure consitency in all output.
-  AliFMDCorrELossFit::ELossFit* ret = FindBestFit(bin, 
-                                                 dist,
-                                                 relErrorCut, 
-                                                 chi2nuCut,
-                                                 minWeight);
+  ELossFit_t* ret = FindBestFit(bin, dist, relErrorCut, chi2nuCut, minWeight);
   return ret;
 }
-#if 0
-//____________________________________________________________________
-TF1*
-AliFMDEnergyFitter::RingHistos::FitHist(TH1*     dist,
-                                       Double_t lowCut, 
-                                       UShort_t nParticles, 
-                                       UShort_t minusBins, 
-                                       Double_t relErrorCut, 
-                                       Double_t chi2nuCut,
-                                       Double_t minWeight) const
-{
-  // 
-  // Fit a signal histogram.  First, the bin @f$ b_{min}@f$ with
-  // maximum bin content in the range @f$ [E_{min},\infty]@f$ is
-  // found.  Then the fit range is set to the bin range 
-  // @f$ [b_{min}-\Delta b,b_{min}+2\Delta b]@f$, and a 1 
-  // particle signal is fitted to that.  The parameters of that fit 
-  // is then used as seeds for a fit of the @f$ N@f$ particle response 
-  // to the data in the range 
-  // @f$ [b_{min}-\Delta b,N(\Delta_1+\xi_1\log(N))+2N\xi@f$
-  // 
-  // Parameters:
-  //    dist        Histogram to fit 
-  //    lowCut      Lower cut @f$ E_{min}@f$ on signal 
-  //    nParticles  Max number @f$ N@f$ of convolved landaus to fit
-  //    minusBins   Number of bins @f$ \Delta b@f$ from peak to 
-  //                    subtract to get the fit range 
-  //    relErrorCut Cut applied to relative error of parameter. 
-  //                    Note, for multi-particle weights, the cut 
-  //                    is loosend by a factor of 2 
-  //    chi2nuCut   Cut on @f$ \chi^2/\nu@f$ - 
-  //                    the reduced @f$\chi^2@f$ 
-  // 
-  // Return:
-  //    The best fit function 
-  //
-  DGUARD(fDebug, 3, "Fit histogram in AliFMDEnergyFitter::RingHistos: %s",
-        dist->GetName());
-  Double_t maxRange = 10;
-
-  // Create a fitter object 
-  AliForwardUtil::ELossFitter f(lowCut, maxRange, minusBins); 
-  f.Clear();
-  f.SetDebug(fDebug > 2);
-  
-  // If we are only asked to fit a single particle, return this fit, 
-  // no matter what. 
-  if (nParticles == 1) {
-    TF1* r = f.Fit1Particle(dist, 0);
-    if (!r) return 0;
-    TF1* ret = new TF1(*r);
-    dist->GetListOfFunctions()->Add(ret);
-    return ret;
-  }
-
-  // Fit from 2 upto n particles  
-  for (Int_t i = 2; i <= nParticles; i++) f.FitNParticle(dist, i, 0);
-
-
-
-  // Now, we need to select the best fit 
-  Int_t nFits = f.GetFitResults().GetEntriesFast();
-  TF1*  good[nFits];
-  for (Int_t i = nFits-1; i >= 0; i--) { 
-    good[i] = 0;
-    TF1* ff = static_cast<TF1*>(f.GetFunctions().At(i));
-    // ff->SetLineColor(Color());
-    // ff->SetRange(0, maxRange);
-    dist->GetListOfFunctions()->Add(new TF1(*ff));
-    if (CheckResult(static_cast<TFitResult*>(f.GetFitResults().At(i)),
-                   relErrorCut, chi2nuCut, minWeight)) {
-      good[i] = ff;
-      ff->SetLineWidth(2);
-      if (fDebug > 1) { 
-       AliInfoF("Candiate fit: %s", ff->GetName());
-       f.GetFitResults().At(i)->Print("V");
-      }
-    }
-  }
-  // If all else fails, use the 1 particle fit 
-  TF1* ret = static_cast<TF1*>(f.GetFunctions().At(0));
-
-  // Find the fit with the most valid particles 
-  for (Int_t i = nFits-1; i >= 0; i--) {
-    if (!good[i]) continue;
-    if (fDebug > 0) 
-      Printf("%30s: Choosing fit with n=%d %s",
-            dist->GetName(), i+1, good[i]->GetName());
-    if (fDebug >= 3) 
-      f.GetFitResults().At(i)->Print();
-    ret = good[i];
-    break;
-  }
-  // Give a warning if we're using fall-back 
-  if (ret == f.GetFunctions().At(0)) {
-    Printf("%30s: Choosing fall-back 1 particle fit", dist->GetName());
-  }
-  // Copy our result and return (the functions are owned by the fitter)
-  TF1* fret = new TF1(*ret);
-  return fret;
-}
-
-//____________________________________________________________________
-Bool_t
-AliFMDEnergyFitter::RingHistos::CheckResult(TFitResult* r,
-                                           Double_t    relErrorCut, 
-                                           Double_t    chi2nuCut,
-                                           Double_t    minWeight) const
-{
-  // 
-  // Check the result of the fit. Returns true if 
-  // - @f$ \chi^2/\nu < \max{\chi^2/\nu}@f$
-  // - @f$ \Delta p_i/p_i < \delta_e@f$ for all parameters.  Note, 
-  //   for multi-particle fits, this requirement is relaxed by a 
-  //   factor of 2
-  // - @f$ a_{n} > 10^{-7}@f$ when fitting to an @f$ n@f$ 
-  //   particle response 
-  // 
-  // Parameters:
-  //    r           Result to check
-  //    relErrorCut Cut @f$ \delta_e@f$ applied to relative error 
-  //                    of parameter.  
-  //    chi2nuCut   Cut @f$ \max{\chi^2/\nu}@f$ 
-  // 
-  // Return:
-  //    true if fit is good. 
-  //
-  if (fDebug > 10) r->Print();
-  TString  n    = r->GetName();
-  n.ReplaceAll("TFitResult-", "");
-  Double_t chi2 = r->Chi2();
-  Int_t    ndf  = r->Ndf();
-  Double_t red  = (ndf >= 0 ? chi2/ndf : 999);
-  // Double_t prob = r.Prob();
-  Bool_t ret = kTRUE;
-  
-  // Check that the reduced chi square isn't larger than cut
-  if (red > chi2nuCut) { 
-    if (fDebug > 2) {
-      AliWarning(Form("%s: chi^2/ndf=%12.5f/%3d=%12.5f>%12.5f", 
-                     n.Data(), chi2, ndf, (ndf<0 ? 0 : chi2/ndf),
-                     chi2nuCut)); }
-    ret = kFALSE;
-  }
-    
-  // Check each parameter 
-  UShort_t nPar = r->NPar();
-  for (UShort_t i = 0; i < nPar; i++) { 
-    if (i == kN) continue;  // Skip the number parameter 
-    
-    // Get value and error and check value 
-    Double_t v  = r->Parameter(i);
-    Double_t e  = r->ParError(i);
-    if (v == 0) continue;
-
-    // Calculate the relative error and check it 
-    Double_t re  = e / v;
-    Double_t cut = relErrorCut * (i < kN ? 1 : 2);
-    if (re > cut) { 
-      if (fDebug > 2) {
-       AliWarning(Form("%s: Delta %s/%s=%9.5f/%9.5f=%5.1f%%>%5.1f%%",
-                       n.Data(), r->ParName(i).c_str(), 
-                       r->ParName(i).c_str(), e, v, 
-                       100*(v == 0 ? 0 : e/v),
-                       100*(cut))); }
-      ret = kFALSE;
-    }
-  }
-
-  // Check if we have scale parameters 
-  if (nPar > kN) { 
-    
-    // Check that the last particle has a significant contribution 
-    Double_t lastScale = r->Parameter(nPar-1);
-    if (lastScale <= minWeight) { 
-      if (fDebug > 2) {
-       AliWarningF("%s: %s=%9.6f<%g", 
-                   n.Data(), r->ParName(nPar-1).c_str(), 
-                   lastScale, minWeight); 
-      }
-      ret = kFALSE;
-    }
-  }
-  return ret;
-}
-#endif
-
 
 //__________________________________________________________________
 void
@@ -1460,16 +1387,23 @@ AliFMDEnergyFitter::RingHistos::FindBestFits(const TList*        d,
     return;
   }
   Int_t nBin = eta.GetNbins();
-
+  if (fBest.GetEntriesFast() <= 0) { 
+    AliWarningF("No fits found for %s", GetName());
+    return;
+  }
+  
   for (Int_t b = 1; b <= nBin; b++) { 
     TString n(Form(fgkEDistFormat, fName.Data(), b));
     TH1D*   dist = static_cast<TH1D*>(dists->FindObject(n));
     // Ignore empty histograms altoghether 
     if (!dist || dist->GetEntries() <= 0) continue; 
     
-    AliFMDCorrELossFit::ELossFit* best = 
-      static_cast<AliFMDCorrELossFit::ELossFit*>(fBest.At(b));
-      // FindBestFit(b, dist, relErrorCut, chi2nuCut, minWeightCut);
+    ELossFit_t* best = static_cast<ELossFit_t*>(fBest.At(b));
+    if (!best) { 
+      AliErrorF("No best fit found @ %d for %s", b, GetName());
+      continue;
+    }
+    // FindBestFit(b, dist, relErrorCut, chi2nuCut, minWeightCut);
     best->fDet  = fDet; 
     best->fRing = fRing;
     best->fBin  = b; // 
@@ -1479,12 +1413,12 @@ AliFMDEnergyFitter::RingHistos::FindBestFits(const TList*        d,
     }
     // Double_t eta = fAxis->GetBinCenter(b);
     obj.SetFit(fDet, fRing, b, best); 
-    // new AliFMDCorrELossFit::ELossFit(*best));
+    // new ELossFit_t(*best));
   }
 }
 
 //__________________________________________________________________
-AliFMDCorrELossFit::ELossFit* 
+AliFMDEnergyFitter::RingHistos::ELossFit_t* 
 AliFMDEnergyFitter::RingHistos::FindBestFit(UShort_t b, 
                                            const TH1* dist,
                                            Double_t relErrorCut, 
@@ -1515,8 +1449,7 @@ AliFMDEnergyFitter::RingHistos::FindBestFit(UShort_t b,
     printf("Find best fit for %s ... ", dist->GetName());
   // Info("FindBestFit", "%s", dist->GetName());
   while ((func = static_cast<TF1*>(next()))) { 
-    AliFMDCorrELossFit::ELossFit* fit = 
-      new(fFits[i++]) AliFMDCorrELossFit::ELossFit(0,*func);
+    ELossFit_t* fit = new(fFits[i++]) ELossFit_t(0,*func);
     fit->fDet  = fDet;
     fit->fRing = fRing;
     fit->fBin  = b;
@@ -1528,8 +1461,7 @@ AliFMDEnergyFitter::RingHistos::FindBestFit(UShort_t b,
   }
   fFits.Sort();
   if (fDebug > 1) fFits.Print("s");
-  AliFMDCorrELossFit::ELossFit* ret = 
-    static_cast<AliFMDCorrELossFit::ELossFit*>(fFits.At(i-1));
+  ELossFit_t* ret = static_cast<ELossFit_t*>(fFits.At(i-1));
   if (!ret) {
     AliWarningF("No fit found for %s, bin %3d", GetName(), b);
     return 0;
@@ -1541,9 +1473,79 @@ AliFMDEnergyFitter::RingHistos::FindBestFit(UShort_t b,
   }
   // We have to make a copy here, because other wise the clones array
   // will overwrite the address
-  return new AliFMDCorrELossFit::ELossFit(*ret);
+  return new ELossFit_t(*ret);
 }
 
+//____________________________________________________________________
+void
+AliFMDEnergyFitter::RingHistos::CalculateResiduals(EResidualMethod mode, 
+                                                  Double_t        lowCut,
+                                                  TH1*            dist, 
+                                                  ELossFit_t*     fit, 
+                                                  TCollection*    out) const
+{
+
+  // Clone the input, and reset
+  TH1*    resi = static_cast<TH1*>(dist->Clone());
+  TString tit(resi->GetTitle());
+  tit.ReplaceAll("#DeltaE/#DeltaE_{mip}", "Residuals");
+  resi->SetTitle(tit);
+  resi->SetDirectory(0);
+
+  // Set title on Y axis
+  switch (mode) { 
+  case kResidualDifference:       
+    resi->SetYTitle("h_{i}-f(#Delta_{i}) #pm #delta_{i}");
+    break;
+  case kResidualScaledDifference:  
+    resi->SetYTitle("[h_{i}-f(#Delta_{i})]/#delta_{i}"); break;
+  case kResidualSquareDifference:  
+    resi->SetYTitle("#chi_{i}^{2}=[h_{i}-f(#Delta_{i})]^{2}/#delta^{2}_{i}");
+    break;
+  default: 
+    resi->SetYTitle("Unknown");
+    break;
+  }
+  out->Add(resi);
+
+  // Try to find the function 
+  Double_t highCut = dist->GetXaxis()->GetXmax();
+  TString funcName("landau1");
+  if (fit->GetN() > 1) 
+    funcName = Form("nlandau%d", fit->GetN());
+  TF1* func = dist->GetFunction(funcName);
+  if (func) func->GetRange(lowCut, highCut);
+  resi->Reset("ICES");
+  resi->GetListOfFunctions()->Clear();
+  resi->SetUniqueID(mode);
+
+    // Reset histogram
+  Int_t nX = resi->GetNbinsX();
+  for (Int_t i  = 1; i <= nX; i++) { 
+    Double_t x  = dist->GetBinCenter(i);
+    if (x < lowCut)  continue;
+    if (x > highCut) break;
+
+    Double_t h  = dist->GetBinContent(i);
+    Double_t e  = dist->GetBinError(i);
+    Double_t r  = 0;
+    Double_t er = 0;
+    if (h > 0 && e > 0) { 
+      Double_t f = fit->GetC() * fit->Evaluate(x);
+      if (f > 0) { 
+       r  = h-f;
+       switch (mode) { 
+       case kResidualDifference: er = e; break;
+       case kResidualScaledDifference:  r /= e; break;
+       case kResidualSquareDifference:  r *= r; r /= (e*e); break;
+       default: r = 0; break;
+       }
+      }
+    }
+    resi->SetBinContent(i, r);
+    resi->SetBinError(i, er);
+  }  
+}
 
 //____________________________________________________________________
 void
index 5914d3da85cabf84238238b528640e3849d4e5c4..2a019797d927663978327fdc7a8297ababa332b2 100644 (file)
@@ -46,16 +46,64 @@ class TArrayD;
 class AliFMDEnergyFitter : public TNamed
 {
 public: 
-    enum { 
-      kC       = AliForwardUtil::ELossFitter::kC,
-      kDelta   = AliForwardUtil::ELossFitter::kDelta, 
-      kXi      = AliForwardUtil::ELossFitter::kXi, 
-      kSigma   = AliForwardUtil::ELossFitter::kSigma, 
-      kSigmaN  = AliForwardUtil::ELossFitter::kSigmaN,
-      kN       = AliForwardUtil::ELossFitter::kN, 
-      kA       = AliForwardUtil::ELossFitter::kA
-    };
+  /** 
+   * Enumeration of parameters 
+   */
+  enum { 
+    /** Index of pre-constant @f$ C@f$ */
+    kC         = AliForwardUtil::ELossFitter::kC,
+    /** Index of most probable value @f$ \Delta_p@f$ */
+    kDelta     = AliForwardUtil::ELossFitter::kDelta, 
+    /** Index of Landau width @f$ \xi@f$ */
+    kXi                = AliForwardUtil::ELossFitter::kXi, 
+    /** Index of Gaussian width @f$ \sigma@f$ */
+    kSigma     = AliForwardUtil::ELossFitter::kSigma, 
+    /** Index of Gaussian additional width @f$ \sigma_n@f$ */
+    kSigmaN    = AliForwardUtil::ELossFitter::kSigmaN,
+    /** Index of Number of particles @f$ N@f$ */
+    kN         = AliForwardUtil::ELossFitter::kN, 
+    /** Base index of particle strengths @f$ a_i@f$ for 
+       @f$i=2,\ldots,N@f$ */
+    kA         = AliForwardUtil::ELossFitter::kA
+  };
+  /** 
+   * Enumeration of residual methods 
+   */
+  enum EResidualMethod {
+    /** Do not calculate residuals */
+    kNoResiduals = 0, 
+    /** The residuals stored are the difference, and the errors are
+       stored in the error bars of the histogram. */
+    kResidualDifference, 
+    /** The residuals stored are the differences scaled to the error
+       on the data */ 
+    kResidualScaledDifference, 
+    /** The residuals stored are the square difference scale to the
+       square error on the data. */
+    kResidualSquareDifference
+  };
 
+  /**
+   * FMD ring bits for skipping 
+   */
+   enum FMDRingBits { 
+     /** FMD1i */
+     kFMD1I=0x01,
+     /** All of FMD1 */
+     kFMD1 =kFMD1I,
+     /** FMD2i */
+     kFMD2I=0x02,
+     /** FMD2o */
+     kFMD2O=0x04,
+     /** All of FMD2 */
+     kFMD2 =kFMD2I|kFMD2O,
+     /** FMD3i */
+     kFMD3I=0x08,
+     /** FMD3o */
+     kFMD3O=0x10,
+     /** All of FMD3 */
+     kFMD3 =kFMD3I|kFMD3O
+  };
   /** 
    * Destructor
    */
@@ -92,7 +140,7 @@ public:
    * has already been set (using SetEtaAxis), then this parameter will be 
    * ignored
    */
 void SetupForData(const TAxis& etaAxis);
+ void SetupForData(const TAxis& etaAxis);
   /** 
    * Set the eta axis to use.  This will force the code to use this
    * eta axis definition - irrespective of whatever axis is passed to
@@ -204,6 +252,53 @@ public:
    * @param x Wheter to use increasing bin sizes 
    */
   void SetUseIncreasingBins(Bool_t x) { fUseIncreasingBins = x; }
+  /** 
+   * Set whether to make residuals, and in that case how. 
+   *
+   * - Square difference: @f$chi_i^2=(h_i - f(x_i))^2/\delta_i^2@f$ 
+   * - Scaled difference: @f$(h_i - f(x_i))/\delta_i@f$ 
+   * - Difference: @f$(h_i - f(x_i)) \pm\delta_i@f$ 
+   *
+   * where @f$h_i, x_i, \delta_i@f$ is the bin content, bin center,
+   * and bin error for bin @f$i@f$ respectively, and @f$ f@f$ is the
+   * fitted function.
+   * 
+   * @param x Residual method 
+   */
+  void SetStoreResiduals(EResidualMethod x=kResidualDifference) 
+  { 
+    fResidualMethod = x; 
+  }
+  /** 
+   * Set the regularization cut @f$c_{R}@f$.  If a @f$\Delta@f$
+   * distribution has more entries @f$ N_{dist}@f$ than @f$c_{R}@f$,
+   * then we modify the errors of the the distribution with the factor
+   * 
+   * @f[
+   * \sqrt{N_{dist}/c_{R}}
+   * @f]
+   *
+   * to keep the @f$\chi^2/\nu@f$ within resonable limits. 
+   *
+   * The large residuals @f$chi_i^2=(h_i - f(x_i))^2/\delta_i^2@f$
+   * (see also SetStoreResiduals) comes about on the boundary between
+   * the @f$N@f$ and @f$N+1@f$ particle contributions, and seems to
+   * fall off for larger @f$N@f$. This may indicate that there's a
+   * component in the distributions that the function
+   *
+   * @f[
+   *   f(\Delta;\Delta_p,\xi,\sigma,\mathbf{a}) = \sum_i=1^{n} a_i\int
+   *   d\Delta' L(\Delta;\Delta',\xi) G(\Delta';\Delta_p,\sigma)
+   * @f]
+   * 
+   * does not capture.   
+   *
+   * @param cut
+   */
+  void SetRegularizationCut(Double_t cut=3e6) 
+  {
+    fRegularizationCut = cut;
+  }
   /** 
    * Fitter the input AliESDFMD object
    * 
@@ -249,12 +344,22 @@ public:
    * @param option Not used 
    */
   void Print(Option_t* option="") const;
+  /** 
+   * Read the parameters from a list - used when re-running the code 
+   * 
+   * @param list Input list 
+   * 
+   * @return true if the parameter where read 
+   */
+  Bool_t ReadParameters(const TCollection* list);
+  void SetSkips(UShort_t skip) { fSkips = skip; }
 protected:
   /** 
    * Internal data structure to keep track of the histograms
    */
   struct RingHistos : public AliForwardUtil::RingHistos
   { 
+    typedef AliFMDCorrELossFit::ELossFit ELossFit_t;
     /** 
      * Default CTOR
      */
@@ -328,18 +433,22 @@ protected:
      *                    is loosend by a factor of 2 
      * @param chi2nuCut   Cut on @f$ \chi^2/\nu@f$ - 
      *                    the reduced @f$\chi^2@f$ 
+     * @param regCut      Regularization cut-off
+     * @param residuals   Mode for residual plots
      *
      * @return List of fits 
      */
-    TObjArray* Fit(TList*       dir, 
-                  const TAxis& eta,
-                  Double_t     lowCut, 
-                  UShort_t     nParticles,
-                  UShort_t     minEntries,
-                  UShort_t     minusBins,
-                  Double_t     relErrorCut, 
-                  Double_t     chi2nuCut,
-                  Double_t     minWeight) const;
+    TObjArray* Fit(TList*          dir, 
+                  const TAxis&    eta,
+                  Double_t        lowCut, 
+                  UShort_t        nParticles,
+                  UShort_t        minEntries,
+                  UShort_t        minusBins,
+                  Double_t        relErrorCut, 
+                  Double_t        chi2nuCut,
+                  Double_t        minWeight,
+                  Double_t        regCut,
+                  EResidualMethod residuals) const;
     /** 
      * Fit a signal histogram.  First, the bin @f$ b_{min}@f$ with
      * maximum bin content in the range @f$ [E_{min},\infty]@f$ is
@@ -360,49 +469,33 @@ protected:
      *                    is loosend by a factor of 2 
      * @param chi2nuCut   Cut on @f$ \chi^2/\nu@f$ - 
      *                    the reduced @f$\chi^2@f$ 
+     * @param regCut      Regularization cut-off
      * 
      * @return The best fit function 
      */
-    AliFMDCorrELossFit::ELossFit* FitHist(TH1*     dist,
-                                         UShort_t bin, 
-                                         Double_t lowCut, 
-                                         UShort_t nParticles,
-                                         UShort_t minusBins,
-                                         Double_t relErrorCut, 
-                                         Double_t chi2nuCut,
-                                         Double_t minWeight) const;
-#if 0
+    ELossFit_t* FitHist(TH1*     dist,
+                       UShort_t bin, 
+                       Double_t lowCut, 
+                       UShort_t nParticles,
+                       UShort_t minusBins,
+                       Double_t relErrorCut, 
+                       Double_t chi2nuCut,
+                       Double_t minWeight,
+                       Double_t regCut) const;
     /** 
-     * Fit a signal histogram.  First, the bin @f$ b_{min}@f$ with
-     * maximum bin content in the range @f$ [E_{min},\infty]@f$ is
-     * found.  Then the fit range is set to the bin range 
-     * @f$ [b_{min}-\Delta b,b_{min}+2\Delta b]@f$, and a 1 
-     * particle signal is fitted to that.  The parameters of that fit 
-     * is then used as seeds for a fit of the @f$ N@f$ particle response 
-     * to the data in the range 
-     * @f$ [b_{min}-\Delta b,N(\Delta_1+\xi_1\log(N))+2N\xi@f$
-     * 
-     * @param dist        Histogram to fit 
-     * @param lowCut      Lower cut @f$ E_{min}@f$ on signal 
-     * @param nParticles  Max number @f$ N@f$ of convolved landaus to fit
-     * @param minusBins   Number of bins @f$ \Delta b@f$ from peak to 
-     *                    subtract to get the fit range 
-     * @param relErrorCut Cut applied to relative error of parameter. 
-     *                    Note, for multi-particle weights, the cut 
-     *                    is loosend by a factor of 2 
-     * @param chi2nuCut   Cut on @f$ \chi^2/\nu@f$ - 
-     *                    the reduced @f$\chi^2@f$ 
+     * Calculate residuals of the fit 
      * 
-     * @return The best fit function 
+     * @param mode   How to calculate 
+     * @param lowCut Lower cut 
+     * @param dist   Distribution 
+     * @param fit    Function fitted to distribution
+     * @param out    Output list to store residual histogram in
      */
-    TF1* FitHist(TH1*     dist,
-                Double_t lowCut, 
-                UShort_t nParticles,
-                UShort_t minusBins,
-                Double_t relErrorCut, 
-                Double_t chi2nuCut,
-                Double_t minWeight) const;
-#endif
+    void CalculateResiduals(EResidualMethod   mode,
+                           Double_t         lowCut,
+                           TH1*             dist, 
+                           ELossFit_t*      fit, 
+                           TCollection*     out) const;
     /** 
      * Find the best fits 
      * 
@@ -435,11 +528,11 @@ protected:
      * 
      * @return Best fit 
      */
-    AliFMDCorrELossFit::ELossFit* FindBestFit(UShort_t b, 
-                                             const TH1* dist,
-                                             Double_t relErrorCut, 
-                                             Double_t chi2nuCut,
-                                             Double_t minWeightCut) const;
+    ELossFit_t* FindBestFit(UShort_t b, 
+                           const TH1* dist,
+                           Double_t relErrorCut, 
+                           Double_t chi2nuCut,
+                           Double_t minWeightCut) const;
 #if 0
     /** 
      * Check the result of the fit. Returns true if 
@@ -532,6 +625,29 @@ protected:
    * @return Ring histogram container 
    */
   RingHistos* GetRingHistos(UShort_t d, Char_t r) const;
+  /** 
+   * Check if the detector @a d, ring @a r is listed <i>in</i> the @a
+   * skips bit mask.  If the detector/ring is in the mask, return true.
+   * 
+   * That is, use case is 
+   * @code 
+   *  for (UShort_t d=1. d<=3, d++) {
+   *    UShort_t nr = (d == 1 ? 1 : 2);
+   *    for (UShort_t q = 0; q < nr; q++) { 
+   *      Char_t r = (q == 0 ? 'I' : 'O');
+   *      if (CheckSkips(d, r, skips)) continue; 
+   *      // Process detector/ring 
+   *    }
+   *  }
+   * @endcode
+   *
+   * @param d      Detector
+   * @param r      Ring 
+   * @param skips  Mask of detector/rings to skip
+   * 
+   * @return True if detector @a d, ring @a r is in the mask @a skips 
+   */
+  static Bool_t CheckSkip(UShort_t d, Char_t r, UShort_t skips);
 
   TList    fRingHistos;    // List of histogram containers
   Double_t fLowCut;        // Low cut on energy
@@ -549,9 +665,11 @@ protected:
   Double_t fMaxChi2PerNDF; // chi^2/nu cit
   Double_t fMinWeight;     // Minimum weight value 
   Int_t    fDebug;         // Debug level 
-  
+  EResidualMethod fResidualMethod;// Whether to store residuals (debugging)
+  UShort_t        fSkips;         // Rings to skip when fitting 
+  Double_t        fRegularizationCut; // When to regularize the chi^2
 
-  ClassDef(AliFMDEnergyFitter,4); //
+  ClassDef(AliFMDEnergyFitter,5); //
 };
 
 #endif
index 6fb73a32cc1770a10751bf36dff6a3a761a8bc34..42ec959417ca8fa4a9ee834eabf5c079a4f45fd5 100644 (file)
@@ -25,6 +25,7 @@
 #include <TDirectory.h>
 #include <TTree.h>
 #include <TFile.h>
+#include <TROOT.h>
 #include "AliMCEvent.h"
 #include "AliGenHijingEventHeader.h"
 #include "AliHeader.h"
@@ -159,7 +160,7 @@ AliFMDEnergyFitterTask::SetupForData()
   TAxis vAxis(10,-10,10); // Default only 
   fEnergyFitter.SetupForData(eAxis);
   fEventInspector.SetupForData(vAxis);
-
+  Print();
 }
 
 //____________________________________________________________________
@@ -194,21 +195,7 @@ AliFMDEnergyFitterTask::UserExec(Option_t*)
   // cnt++;
   // Get the input data 
   DGUARD(fDebug,3,"Analyse event of AliFMDEnergyFitterTask");
-  
-  AliMCEvent* mcevent = MCEvent();
-  if(mcevent) {
-    AliHeader* header            = mcevent->Header();
-    AliGenHijingEventHeader* hijingHeader = 
-      dynamic_cast<AliGenHijingEventHeader*>(header->GenEventHeader());
-    if(hijingHeader) {
-      Float_t b = hijingHeader->ImpactParameter();
-      if(b<fbLow || b>fbHigh) return;
-      else
-       std::cout<<"Selecting event with impact parameter "<<b<<std::endl;
-    }
     
-  }
-  
   AliESDEvent* esd = dynamic_cast<AliESDEvent*>(InputEvent());
   // AliInfo(Form("Event # %6d (esd=%p)", cnt, esd));
   if (!esd) { 
@@ -221,6 +208,7 @@ AliFMDEnergyFitterTask::UserExec(Option_t*)
 
   // On the first event, initialize the parameters 
   if (fFirstEvent && esd->GetESDRun()) { 
+    fEventInspector.SetMC(MCEvent());
     fEventInspector.ReadRunDetails(esd);
     
     AliInfo(Form("Initializing with parameters from the ESD:\n"
@@ -330,7 +318,7 @@ AliFMDEnergyFitterTask::Terminate(Option_t*)
 
 //____________________________________________________________________
 void
-AliFMDEnergyFitterTask::Print(Option_t*) const
+AliFMDEnergyFitterTask::Print(Option_t* option) const
 {
   // 
   // Print information 
@@ -338,6 +326,13 @@ AliFMDEnergyFitterTask::Print(Option_t*) const
   // Parameters:
   //    option Not used
   //
+  std::cout << ClassName() << ": " << GetName() << std::endl; 
+  gROOT->IncreaseDirLevel();
+
+  fEventInspector.Print(option);
+  fEnergyFitter.Print(option);
+
+  gROOT->DecreaseDirLevel();
 }
 
 //
index 8a8eecff0a402b7af24469429cdd5b13ebbebcf9..c7a88cc619808556c81d0b366e5e984b7f478876 100644 (file)
@@ -58,7 +58,7 @@ AliFMDEventInspector::AliFMDEventInspector()
     fHCentVsQual(0),
     fHStatus(0),
     fHVtxStatus(0),
-    fHTrgStatus(0),
+    fHTrgStatus(0), 
     fLowFluxCut(1000),
     fMaxVzErr(0.2),
     fList(0),
@@ -70,9 +70,9 @@ AliFMDEventInspector::AliFMDEventInspector()
     fVtxAxis(10,-10,10),
     fUseFirstPhysicsVertex(false),
     fUseV0AND(false),
-    fMinPileupContrib(3), 
+  fMinPileupContrib(3), 
   fMinPileupDistance(0.8),
-  fUseDisplacedVertices(false),
+    fUseDisplacedVertices(false),
   fDisplacedVertex(),
   fCollWords(),
   fBgWords(),
@@ -80,7 +80,8 @@ AliFMDEventInspector::AliFMDEventInspector()
   fMinCent(-1.0),
   fMaxCent(-1.0),
   fUsepA2012Vertex(false),
-  fRunNumber(0)
+  fRunNumber(0),
+  fMC(false)
 {
   // 
   // Constructor 
@@ -125,7 +126,8 @@ AliFMDEventInspector::AliFMDEventInspector(const char* name)
   fMinCent(-1.0),
   fMaxCent(-1.0),
   fUsepA2012Vertex(false),
-  fRunNumber(0)
+  fRunNumber(0),
+  fMC(false)
 {
   // 
   // Constructor 
@@ -173,7 +175,8 @@ AliFMDEventInspector::AliFMDEventInspector(const AliFMDEventInspector& o)
   fMinCent(o.fMinCent),
   fMaxCent(o.fMaxCent),
   fUsepA2012Vertex(o.fUsepA2012Vertex),
-  fRunNumber(o.fRunNumber)
+  fRunNumber(o.fRunNumber),
+  fMC(o.fMC)
        
 {
   // 
@@ -244,6 +247,7 @@ AliFMDEventInspector::operator=(const AliFMDEventInspector& o)
   fMaxCent              = o.fMaxCent; 
   fUsepA2012Vertex       = o.fUsepA2012Vertex;
   fRunNumber             = o.fRunNumber;
+  fMC                    = o.fMC;
 
   if (fList) { 
     fList->SetName(GetName());
@@ -675,6 +679,7 @@ AliFMDEventInspector::StoreInformation()
                                           AliForwardUtil::AliROOTRevision()));
   fList->Add(AliForwardUtil::MakeParameter("alirootBranch", 
                                           AliForwardUtil::AliROOTBranch()));
+  fList->Add(AliForwardUtil::MakeParameter("mc", fMC));
 
 }
 
@@ -1004,6 +1009,7 @@ AliFMDEventInspector::CheckFastPartition(bool fastonly) const
   // triggers are fast.
   if (TMath::Abs(fEnergy - 2750.) > 20) return false;
   if (fCollisionSystem != AliForwardUtil::kPP) return false;
+  if (fMC) return false; // All MC events for pp @ 2.76TeV are `fast'
   if (fastonly)
     DMSG(fDebug,1,"Fast trigger in pp @ sqrt(s)=2.76TeV removed");
 
@@ -1367,6 +1373,9 @@ AliFMDEventInspector::Print(Option_t*) const
            << ind << " CMS energy per nucleon: " << sNN << '\n'
            << ind << " Field:                  " <<  field << '\n'
            << ind << " Satellite events:       " << fUseDisplacedVertices<<'\n'
+           << ind << " Use 2012 pA vertex:     " << fUsepA2012Vertex << '\n'
+           << ind << " Use PWG-UD vertex:      " <<fUseFirstPhysicsVertex<<'\n'
+           << ind << " Simulation input:       " << fMC << '\n'
            << ind << " Centrality method:      " << fCentMethod << '\n'
            << std::noboolalpha;
   if (!fCentAxis) { std::cout << std::flush; return; }
index 5552e39c5cf5b79526c498834c41b7d865f14fd0..def7ffa522412205d41e740286cc8587192adeb2 100644 (file)
@@ -318,6 +318,15 @@ public:
    * @param dbg Debug level 
    */
   void SetDebug(Int_t dbg=1) { fDebug = dbg; }
+  /** 
+   * Set whether this is MC or not.  Needed by energy loss fitter task
+   * that never instantices AliFMDMCEventInspector.  In particular, we
+   * need this to make sure we ignore the FAST partition flag in MC
+   * for 2.76TeV pp.
+   * 
+   * @param isMC If true, assume MC input 
+   */
+  void SetMC(Bool_t isMC=true) { fMC = isMC; }
   /** 
    * Fetch our histograms from the passed list 
    * 
@@ -595,8 +604,8 @@ protected:
   Double_t fMaxCent;  //max centrailty
   Bool_t   fUsepA2012Vertex;// flag to use pA2012 Veretx selection
   ULong_t  fRunNumber; // Current run number 
-
-  ClassDef(AliFMDEventInspector,10); // Inspect the event 
+  Bool_t   fMC;        // Is this MC input
+  ClassDef(AliFMDEventInspector,11); // Inspect the event 
 };
 
 #endif
index 44d913089d94805294162a6b37044f0e28690c28..e1367e6dee6037eb004dd05876cd7cd8ad705b7c 100644 (file)
@@ -81,6 +81,7 @@ AliFMDMCEventInspector::AliFMDMCEventInspector(const char* /* name */)
   // Parameters:
   //   name Name of object
   //
+  fMC = true;
 }
 
 //____________________________________________________________________
@@ -255,17 +256,6 @@ AliFMDMCEventInspector::SetupForData(const TAxis& vtxAxis)
   if (fUseDisplacedVertices) fDisplacedVertex.SetupForData(fList, "", true);
 }
 
-//____________________________________________________________________
-void AliFMDMCEventInspector::StoreInformation()
-{
-  // Store information about running conditions in the output list 
-  if (!fList) return;
-  AliFMDEventInspector::StoreInformation();
-  Bool_t mc = true;
-  fList->Add(AliForwardUtil::MakeParameter("mc", mc));
-  // , fProduction.Data());
-}
-
 namespace
 {
   TString& AppendField(TString& s, bool test, const char* f)
index 134917875321d878b7d3588e44f30e69450cb843..fe553386add2922c0819b030487f6d47e1d13379 100644 (file)
@@ -121,16 +121,6 @@ public:
                                Double_t cent,  Double_t mcC,
                                Double_t b,
                                Int_t    npart, Int_t    nbin);
-  /** 
-   * Store information about running conditions in output list 
-   * 
-   * The 3 TNamed objects from AliFMDEventInspector::StoreInformation
-   * are defined.  In addition, a fourth TNamed object is defined.
-   * The presence of this indicate MC data.
-   *
-   * - mc    Nothing special, and unique id is 1
-   */
-  virtual void StoreInformation();
   /** 
    * Read the production details 
    * 
index 8b5119236aad87c639b329d7ac7ab94e9d025e84..c594b828d98ba6af7e9bcc839c2db25482927eca 100644 (file)
@@ -24,6 +24,7 @@
 #include <TMath.h>
 #include <TError.h>
 #include <TROOT.h>
+#define FIT_OPTIONS "RNQS"
 
 //====================================================================
 ULong_t AliForwardUtil::AliROOTRevision()
@@ -352,7 +353,7 @@ void AliForwardUtil::GetParameter(TObject* o, UShort_t& value)
 {
   if (!o) return;
   TParameter<int>* p = static_cast<TParameter<int>*>(o);
-  if (p->TestBit(BIT(17)))
+  if (p->TestBit(BIT(19)))
     value = p->GetVal(); 
   else
     value = o->GetUniqueID();
@@ -362,7 +363,7 @@ void AliForwardUtil::GetParameter(TObject* o, Int_t& value)
 {
   if (!o) return;
   TParameter<int>* p = static_cast<TParameter<int>*>(o);
-  if (p->TestBit(BIT(17)))
+  if (p->TestBit(BIT(19)))
     value = p->GetVal(); 
   else
     value = o->GetUniqueID();
@@ -372,7 +373,7 @@ void AliForwardUtil::GetParameter(TObject* o, ULong_t& value)
 {
   if (!o) return;
   TParameter<Long_t>* p = static_cast<TParameter<Long_t>*>(o);
-  if (p->TestBit(BIT(17)))
+  if (p->TestBit(BIT(19)))
     value = p->GetVal(); 
   else
     value = o->GetUniqueID();
@@ -382,7 +383,7 @@ void AliForwardUtil::GetParameter(TObject* o, Double_t& value)
 {
   if (!o) return;
   TParameter<double>* p = static_cast<TParameter<double>*>(o);
-  if (p->TestBit(BIT(17)))
+  if (p->TestBit(BIT(19)))
     value = p->GetVal(); // o->GetUniqueID();
   else {
     UInt_t  i = o->GetUniqueID();
@@ -395,7 +396,7 @@ void AliForwardUtil::GetParameter(TObject* o, Bool_t& value)
 {
   if (!o) return;
   TParameter<bool>* p = static_cast<TParameter<bool>*>(o);
-  if (p->TestBit(BIT(17)))
+  if (p->TestBit(BIT(19)))
     value = p->GetVal(); // o->GetUniqueID();
   else
     value = o->GetUniqueID();
@@ -1087,7 +1088,7 @@ AliForwardUtil::ELossFitter::Fit1Particle(TH1* dist, Double_t sigman)
   // Do the fit, getting the result object 
   if (fDebug) 
     ::Info("Fit1Particle", "Fitting in the range %f,%f", minE, maxE);
-  TFitResultPtr r = dist->Fit(landau1, "RNQS", "", minE, maxE);
+  TFitResultPtr r = dist->Fit(landau1, FIT_OPTIONS, "", minE, maxE);
   // landau1->SetRange(minE, fMaxRange);
   fFitResults.AddAtAndExpand(new TFitResult(*r), 0);
   fFunctions.AddAtAndExpand(landau1, 0);
@@ -1186,7 +1187,7 @@ AliForwardUtil::ELossFitter::FitNParticle(TH1* dist, UShort_t n,
   // Do the fit 
   if (fDebug) 
     ::Info("FitNParticle", "Fitting in the range %f,%f (%d)", minE, maxEi, n);
-  TFitResultPtr tr = dist->Fit(landaun, "RSQN", "", minE, maxEi);
+  TFitResultPtr tr = dist->Fit(landaun, FIT_OPTIONS, "", minE, maxEi);
   
   // landaun->SetRange(minE, fMaxRange);
   fFitResults.AddAtAndExpand(new TFitResult(*tr), n-1);
@@ -1258,7 +1259,7 @@ AliForwardUtil::ELossFitter::FitComposite(TH1* dist, Double_t sigman)
   // Do the fit, getting the result object 
   if (fDebug) 
     ::Info("FitComposite", "Fitting seed in the range %f,%f", minE, maxE);
-  /* TFitResultPtr r = */ dist->Fit(seed, "RNQS", "", minE, maxE);
+  /* TFitResultPtr r = */ dist->Fit(seed, FIT_OPTIONS, "", minE, maxE);
 
   maxE = dist->GetXaxis()->GetXmax();
   TF1* comp = new TF1("composite", landauGausComposite, 
@@ -1288,7 +1289,7 @@ AliForwardUtil::ELossFitter::FitComposite(TH1* dist, Double_t sigman)
   // Do the fit, getting the result object 
   if (fDebug) 
     ::Info("FitComposite", "Fitting composite in the range %f,%f", minE, maxE);
-  /* TFitResultPtr r = */ dist->Fit(comp, "RNQS", "", minE, maxE);
+  /* TFitResultPtr r = */ dist->Fit(comp, FIT_OPTIONS, "", minE, maxE);
 
 #if 0
   TF1* part1 = static_cast<TF1*>(seed->Clone("part1"));
index ff639cd06b3165389e8390f20ba3e4d9e8eeee3b..1b8e7d04776b32609b3df378a27c43387d6f9242 100755 (executable)
@@ -108,13 +108,20 @@ upload()
 # --- Extract and upload ---------------------------------------------
 extract_upload()
 {
-    dummy extract_upload 
+    echo "=== Download, extract, and uploade in `basename $PWD` ==="
+    _extract
+    upload
 }
 # --- Draw -----------------------------------------------------------
 _draw()
 {
     script $@
 }
+# --- Generic draw ---------------------------------------------------
+draw()
+{
+    _draw $@ 
+}
 # --- Draw dN/deta results -------------------------------------------
 _dndeta_draw()
 {
@@ -124,8 +131,13 @@ _dndeta_draw()
     (cd $d && \
        draw ${fwd_dir}/DrawdNdetaSummary.C && \
        draw ${scr})
+    echo "Back to `pwd`"
+}
+# --- Draw dN/deta ---------------------------------------------------
+dndeta_draw()
+{
+    _dndeta_draw $@ 
 }
-
 # === Task functions =================================================
 # --- Common options help --------------------------------------------
 usage()
@@ -216,6 +228,8 @@ _setup()
        fi
     done
 
+    check setup
+
     # Set the date/time string 
     now=`date '+%Y%m%d_%H%M'` 
 
@@ -241,12 +255,12 @@ _setup()
        ln -sf ${name}_acc_${now} last_${name}_acc
        ln -sf ${name}_corrs_${now} last_${name}_corrs
        cat <<-EOF > ${corrdir}/Browse.C
-       TObject* Browse()
+       TObject* Browse()
        {
          const char* fwd = "$ALICE_ROOT/PWGLF/FORWARD/analysis2";
          if (!gROOT->GetClass("AliOADBForward"))
            gROOT->Macro(Form("%s/scripts/LoadLibs.C", fwd));
-         gROOT->LoadMacro(Form("%s/corrs/ForwardOADBGui.C++g", fwd));
+         gROOT->LoadMacro(Form("%s/corrs/ForwardOADBGui.C", fwd));
          
          AliOADBForward* db = new AliOADBForward;
          db->Open("fmd_corrections.root", "*");
@@ -258,7 +272,7 @@ _setup()
        EOF
        echo "=== Make acceptance corrections" 
        (cd ${name}_acc_${now} && \
-           accGen `$run_for_acc` && \
+           accGen `run_for_acc` && \
            upload )
    fi
    for i in fmd_corrections.root spd_corrections.root deadstrips.C ; do 
@@ -266,6 +280,8 @@ _setup()
        echo "Linking ${corrdir}/$i here"
        ln -fs ${corrdir}/$i . 
    done
+   print 
+
     
 }
 # --- Default implementation -----------------------------------------
@@ -332,7 +348,9 @@ accGen()
     check_token
     local run=$1 
     script ${fwd_dir}/corrs/ExtractAcceptance.C "${run}"
-
+    if test -f deadstrips.C ; then 
+       cp ${here}/${name}_corrs_${now}/
+    fi
 }
 
 # === Check function =================================================
@@ -455,7 +473,9 @@ _allAboard()
     case $type in 
        mc*) mc=1  ;; 
     esac
-           
+
+    opts=
+    url=
     train_opts $mc $type $trig 
     url_opts $mc $type $trig
 
@@ -497,7 +517,7 @@ collect()
            local files=
            case $d in 
                corr)      files="forward_mccorr.pdf" ;; 
-               eloss)     files="corrs*.pdf" ;; 
+               eloss)     files="forward_elossfits.pdf" ;; 
                aod)       files="forward.pdf" ;; 
                dndeta*)   files="forward_dndeta.pdf dNdeta*.pdf" ;; 
                multdists) files="forward_multdists.pdf" ;;
@@ -520,6 +540,8 @@ collect()
        pdfnup -q --nup 2x1 -o ${name}_dndeta_${now}.pdf tmp.pdf && \
        rm -f tmp.pdf)
     echo "Made ${name}_summary_${now}.pdf and ${name}_dndeta_${now}.pdf"
+    rm -f last_${name}_pdfs
+    ln -s ${out} last_${name}_pdfs
 }
 
 _collect_files()
@@ -557,7 +579,7 @@ collect_name()
        */forward.pdf)           tgt=summary_${d}_${M} ;; 
        */forward_dndeta.pdf)    tgt=summary_${d}_${M} ;; 
        */forward_multdists.pdf) tgt=summary_${d}_${M} ;; 
-       */eloss*.pdf)            tgt=summary_${d}_${M} ;; 
+       */forward_elossfits.pdf) tgt=summary_${d}_${M} ;; 
        */dNdeta*.pdf)           tgt=${d}_${M} ;;
        *) echo "Don't know how to deal with $ff" >/dev/stderr 
     esac
index 51677d632ac825fd7e7bc70346bd63fc1c835101..ca5fded0b5824119f7fb4fdc3f6ca649e73b4aab 100644 (file)
@@ -9,11 +9,13 @@
 # include <TString.h>
 # include <TError.h>
 #else
-// class SummaryDrawer;
+class SummaryDrawer;
+class TObject;
 // class TAxis;
-// class AliFMDCorrAcceptance;
-// class AliFMDCorrSecondaryMap;
-// class AliFMDCorrELossFit;
+class AliFMDCorrAcceptance;
+class AliFMDCorrSecondaryMap;
+class AliFMDCorrELossFit;
+#include <TString.h>
 #endif
 
 class CorrDrawer : public SummaryDrawer
@@ -59,6 +61,8 @@ public:
                           Bool_t          mc=false, 
                           Bool_t          sat=false)
   {
+    out = TString::Format("forward_%s.pdf", prefix.Data());
+#if 0
     out = TString::Format("%s_run%09lu_%s_%04dGeV_%c%dkG_%s_%s.pdf",
                          prefix.Data(), runNo, 
                          (sys == 1 ? "pp" : 
@@ -67,6 +71,7 @@ public:
                          (field >= 0 ? 'p' : 'm'), TMath::Abs(field), 
                          (mc ? "MC" : "real"),
                          (sat ? "satellite" : "nominal"));
+#endif
   }
   /** 
    * Draw corrections using the correction manager to get them 
@@ -213,7 +218,7 @@ public:
    * 
    * @param o Object to draw
    */
-  void Draw(const TObject* o) 
+  virtual void Draw(const TObject* o) 
   {
     if (!o) return;
     Warning("CorrDrawer", "Don't know how to draw a %s object", 
@@ -224,19 +229,19 @@ public:
    * 
    * @param acc Acceptance correction
    */
-  void Draw(const AliFMDCorrAcceptance* acc) { Summarize(acc, false); }
+  virtual void Draw(const AliFMDCorrAcceptance* acc) { Summarize(acc, false); }
   /** 
    * Draw a single plot of the mean secondary correction 
    * 
    * @param sec Secondary correction
    */
-  void Draw(const AliFMDCorrSecondaryMap* sec) { Summarize(sec, false); }
+  virtual void Draw(const AliFMDCorrSecondaryMap* sec) { Summarize(sec, false);}
   /** 
    * Draw a single plot summarizing the energy loss fits
    * 
    * @param sec Energy loss fits
    */
-  void Draw(const AliFMDCorrELossFit* fits) { Summarize(fits, false); }
+  virtual void Draw(const AliFMDCorrELossFit* fits) { Summarize(fits, false); }
   /** 
    * A generalized entry to the summarization functions
    * 
@@ -250,15 +255,15 @@ public:
    * @param options Options 
    * @param local   Local storage
    */
-  void Summarize(const TString& what, 
-                ULong_t        runNo, 
-                const Char_t*  sys, 
-                UShort_t       sNN, 
-                Short_t        field,
-                Bool_t         mc=false, 
-                Bool_t         sat=false,
-                Option_t*      options="",
-                const char*    local="")
+  virtual void Summarize(const TString& what, 
+                        ULong_t        runNo, 
+                        const Char_t*  sys, 
+                        UShort_t       sNN, 
+                        Short_t        field,
+                        Bool_t         mc=false, 
+                        Bool_t         sat=false,
+                        Option_t*      options="",
+                        const char*    local="")
   {
     Summarize(AliForwardCorrectionManager::ParseFields(what), 
              runNo, AliForwardUtil::ParseCollisionSystem(sys), 
@@ -277,15 +282,15 @@ public:
    * @param options Options 
    * @param local   Local storage
    */
-  void Summarize(UShort_t    what, 
-                ULong_t     runNo, 
-                UShort_t    sys, 
-                UShort_t    sNN, 
-                Short_t     field,
-                Bool_t      mc=false, 
-                Bool_t      sat=false,
-                Option_t*   options="",
-                const char* local="")
+  virtual void Summarize(UShort_t    what, 
+                        ULong_t     runNo, 
+                        UShort_t    sys, 
+                        UShort_t    sNN, 
+                        Short_t     field,
+                        Bool_t      mc=false, 
+                        Bool_t      sat=false,
+                        Option_t*   options="",
+                        const char* local="")
   {
     AliForwardCorrectionManager& mgr = AliForwardCorrectionManager::Instance();
     mgr.SetDebug(true);
@@ -369,7 +374,7 @@ public:
    * @param o Object to draw
    * @param pdf Not used
    */
-  void Summarize(const TObject* o, Bool_t pdf=true) 
+  virtual void Summarize(const TObject* o, Bool_t pdf=true) 
   {
     if (!o) return;
     Warning("CorrDrawer", "Don't know how to draw a %s object", 
@@ -382,7 +387,7 @@ public:
    * @param acc Acceptance correction
    * @param pdf If true, do multiple plots. Otherwise a single summary plot
    */
-  void Summarize(const AliFMDCorrAcceptance* acc, Bool_t pdf=true) 
+  virtual void Summarize(const AliFMDCorrAcceptance* acc, Bool_t pdf=true) 
   { 
     CreateCanvas("acceptance.pdf", false, pdf);
     DrawIt(acc, pdf); 
@@ -395,7 +400,7 @@ public:
    * @param sec Secondary correction
    * @param pdf If true, do multiple plots. Otherwise a single summary plot
    */
-  void Summarize(const AliFMDCorrSecondaryMap* sec, Bool_t pdf=true
+  virtual void Summarize(const AliFMDCorrSecondaryMap* sec, Bool_t pdf
   { 
     CreateCanvas("scondarymap.pdf", false, pdf);
     DrawIt(sec, pdf); 
@@ -408,17 +413,17 @@ public:
    * @param sec Energy loss fits
    * @param pdf If true, do multiple plots. Otherwise a single summary plot
    */
-  void Summarize(const AliFMDCorrELossFit* fits, Bool_t pdf=true
+  virtual void Summarize(const AliFMDCorrELossFit* fits, Bool_t pdf
   { 
     CreateCanvas("elossfits.pdf", false, pdf);
     DrawIt(fits, pdf); 
     if (pdf) CloseCanvas();
   }
 
-  static void Summarize(const TString& what   = ""
+  static void Summarize(const TString& what   = TString("")
                        Bool_t         mc     = false,
-                       const TString& output = "forward_eloss.root"
-                       const TString& local  = "fmd_corrections.root",
+                       const TString& output = TString("forward_eloss.root")
+                       const TString& local  = TString("fmd_corrections.root"),
                        Option_t*      options= "")
   {
     Summarize(AliForwardCorrectionManager::ParseFields(what), mc, 
@@ -462,7 +467,7 @@ protected:
    * 
    * @param o Object to summarize
    */
-  void DrawIt(const TObject* o) 
+  virtual void DrawIt(const TObject* o) 
   {
     if (!o) return;
     Warning("CorrDrawer", "Don't know how to summarize a %s object", 
@@ -474,7 +479,7 @@ protected:
    * @param corr    Correction
    * @param details If true, make a multipage PDF, otherwise plot the mean. 
    */
-  void DrawIt(const AliFMDCorrAcceptance* corr, Bool_t details=true)
+  virtual void DrawIt(const AliFMDCorrAcceptance* corr, Bool_t details=true)
   {
     if (!corr || !fCanvas) return;
 
@@ -589,7 +594,7 @@ protected:
    * @param corr       Correction
    * @param details If true, make a multipage PDF, otherwise plot the mean. 
    */
-  void DrawIt(const AliFMDCorrSecondaryMap* corr, bool details=true
+  virtual void DrawIt(const AliFMDCorrSecondaryMap* corr, bool details
   {
     if (!corr || !fCanvas) return;
     
@@ -680,7 +685,7 @@ protected:
    * @param details If true, make a multipage PDF, 
    *                   otherwise plot the parameters. 
    */
-  void DrawIt(const AliFMDCorrELossFit* corr, bool details=true
+  virtual void DrawIt(const AliFMDCorrELossFit* corr, bool details
   {
     if (!corr || !fCanvas) return;
 
@@ -706,7 +711,8 @@ protected:
        savDir->cd();
       }
       fBody->cd();
-      TLatex* ll = new TLatex(.5,.8, fCanvas->GetTitle());
+      TLatex* ll = new TLatex(.5,.8, "ESD #rightarrow #Delta-fits"
+                             /* fCanvas->GetTitle() */);
       ll->SetTextAlign(22);
       ll->SetTextSize(0.05);
       ll->SetNDC();
@@ -764,6 +770,7 @@ protected:
       for (UShort_t q = 0; q < nQ; q++) { 
        Char_t r = (q == 0 ? 'I' : 'O');
        TList* dists = 0;
+       TList* resis = 0;
        if (fitter) { 
          // Info("", "Fitter: %s", fitter->GetName());
          TList* dl = 
@@ -773,6 +780,7 @@ protected:
            // Info("", "Detector list: %s", dl->GetName());
            dists = static_cast<TList*>(dl->FindObject("EDists"));
            // Info("", "Got distributions -> %p", dists);
+           resis = static_cast<TList*>(dl->FindObject("residuals"));
          }
        }
        
@@ -780,7 +788,7 @@ protected:
        ClearCanvas();
        TObjArray*  ra = fits->GetRingArray(d, r);
        if (!ra) continue;
-       DrawELossFits(d, r, ra, dists);
+       DrawELossFits(d, r, ra, dists, resis);
       }
     }
   }
@@ -792,7 +800,8 @@ protected:
    * @param r 
    * @param ra 
    */
-  void DrawELossFits(UShort_t d, Char_t r, TObjArray* ra, TList* dists)
+  void DrawELossFits(UShort_t d, Char_t r, TObjArray* ra, 
+                    TList* dists, TList* resis)
   {
     Int_t nPad = 6;
     AliFMDCorrELossFit::ELossFit* fit = 0;
@@ -804,21 +813,60 @@ protected:
       Bool_t last = j == nPad-1;
       if (j == 0) DivideForRings(true, true);
 
-      Bool_t same = false;
+      Bool_t        same    = false;
+      TVirtualPad*  drawPad = fBody->GetPad(j+1);
+      Int_t         subPad  = 0;
       if (dists) { 
        // Info("", "Distributions: %s", dists->GetName());
-       TH1* dist = 
-         static_cast<TH1*>(dists->FindObject(Form("FMD%d%c_etabin%03d", 
-                                                  d,r,fit->GetBin())));
+       TString hName(Form("FMD%d%c_etabin%03d", d,r,fit->GetBin()));
+       TH1* dist = static_cast<TH1*>(dists->FindObject(hName));
+       TH1* resi = 0;
+       if (resis) resi = static_cast<TH1*>(resis->FindObject(hName));
        // Info("", "Got histogram -> %p", dist);
+       if (resi) { 
+         Bool_t err = resi->GetUniqueID() <= 1;
+         drawPad->SetGridx();
+         if (err) {
+           resi->SetYTitle("#chi^{2}_{bin}=(h-f)^{2}/#delta^{2}h");
+           for (Int_t k=1; k<=resi->GetNbinsX(); k++) { 
+             Double_t c = resi->GetBinContent(k);
+             Double_t e = resi->GetBinError(k);
+             if (e <= 0) continue;
+             c          *= c;
+             c          /= (e*e);
+             resi->SetBinContent(k, c);
+             resi->SetBinError(k, 0);
+           }
+         }
+         drawPad->Divide(1,2,0,0);
+         DrawInPad(drawPad, 2, resi, "HIST", 0x100);
+         subPad = 1;
+         Double_t red = fit->GetNu() > 0 ? fit->GetChi2() / fit->GetNu() : 0;
+         if (red > 0) {
+           drawPad->cd(2);
+           TLine* l = new TLine(resi->GetXaxis()->GetXmin(), red,
+                                resi->GetXaxis()->GetXmax(), red);
+           l->SetLineWidth(2);
+           l->SetLineStyle(2);
+           l->Draw();
+           TLatex* cltx = new TLatex(0.5, 0.5,
+                                     Form("#chi^{2}/#nu=%6.2f", red));
+           cltx->SetNDC();
+           cltx->SetTextAlign(22);
+           cltx->SetTextFont(42);
+           cltx->SetTextSize(0.07);
+           cltx->Draw();
+           cltx->DrawLatex(0.5,0.4,Form("%g", dist->GetEntries()));
+         }
+       }
        if (dist) { 
          // Info("", "Histogram: %s", dist->GetName());
-         DrawInPad(fBody, j+1, dist, "HIST", 0x2);
+         DrawInPad(drawPad, subPad, dist, "HIST E", (subPad * 0x100) + 0x2);
          same = true;    
        }
       }
       // if (same)
-      DrawInPad(fBody, j+1, fit, 
+      DrawInPad(drawPad, subPad, fit, 
                Form("comp good values legend %s", (same ? "same" : "")),
                0x2);
       if (fit->GetQuality() < fMinQuality) { 
index 5e685764bfd4886122dca469c7bbca6f8bf47f4d..35b100908834c9cb857d9b952283cf484755cb53 100644 (file)
@@ -5,6 +5,18 @@
  *
  * @ingroup pwglf_forward_scripts_corr
  */
+void Setup(Bool_t compile)
+{
+  const char* post = (compile ? "++g" : "");
+  const char* fwd  = "$ALICE_ROOT/PWGLF/FORWARD/analysis2";
+  if (!gROOT->GetClass("AliFMDCorrELossFit"))
+    gROOT->Macro(Form("%s/scripts/LoadLibs.C", fwd));
+  gSystem->AddIncludePath(Form("-I%s/scripts -I%s/corrs -I%s "
+                              "-I$ALICE_ROOT/include", fwd, fwd, fwd));
+  gROOT->LoadMacro(Form("%s/scripts/SummaryDrawer.C%s", fwd, post));
+  gROOT->LoadMacro(Form("%s/corrs/CorrDrawer.C%s", fwd, post));
+
+}
 /** 
  * Draw energy loss fits to a multi-page PDF. 
  *
@@ -30,10 +42,7 @@ DrawCorrELoss(ULong_t runNo, UShort_t sys, UShort_t sNN, Short_t field,
   //__________________________________________________________________
   // Load libraries and object 
   // const char* fwd = "$ALICE_ROOT/PWGLF/FORWARD/analysis2";
-  const char* fwd = "$ALICE_ROOT/PWGLF/FORWARD/analysis2";
-  gROOT->Macro(Form("%s/scripts/LoadLibs.C", fwd));
-  gROOT->LoadMacro(Form("%s/scripts/SummaryDrawer.C", fwd));
-  gROOT->LoadMacro(Form("%s/corrs/CorrDrawer.C", fwd));
+  Setup(false);
 
   CorrDrawer d;
   d.Summarize(AliForwardCorrectionManager::kELossFits, runNo, sys, sNN, field, 
@@ -44,10 +53,7 @@ DrawCorrELoss(Bool_t      mc,
              const char* file="forward_eloss.root", 
              const char* local="fmd_corrections.root")
 {
-  const char* fwd = "$ALICE_ROOT/PWGLF/FORWARD/analysis2";
-  gROOT->Macro(Form("%s/scripts/LoadLibs.C", fwd));
-  gROOT->LoadMacro(Form("%s/scripts/SummaryDrawer.C", fwd));
-  gROOT->LoadMacro(Form("%s/corrs/CorrDrawer.C", fwd));
+  Setup(true);
 
   CorrDrawer::Summarize(AliForwardCorrectionManager::kELossFits, 
                        mc, file, local);
@@ -57,12 +63,9 @@ void
 DrawCorrELoss(Bool_t mc, Bool_t dummy, 
              const char* file="forward_eloss_rerun.root")
 {
-  const char* fwd = "$ALICE_ROOT/PWGLF/FORWARD/analysis2";
-  if (!gROOT->GetClass("AliAODForwardMult"))
-    gROOT->Macro(Form("%s/scripts/LoadLibs.C", fwd));
-  gROOT->LoadMacro(Form("%s/scripts/SummaryDrawer.C", fwd));
-  gROOT->LoadMacro(Form("%s/corrs/CorrDrawer.C", fwd));
+  Setup(true);
 
+  Printf("Drawing fit results from %s", file);
   TFile* hist = TFile::Open(file, "READ");
   if (!hist) { 
     Error("DrawCorrELoss", "Failed to open %s", file);
@@ -91,7 +94,7 @@ DrawCorrELoss(Bool_t mc, Bool_t dummy,
   CorrDrawer* cd = new CorrDrawer;
   cd->fELossExtra = file;
   cd->fMinQuality = 8;
-  cd->Summarize(fits);
+  cd->Summarize(const_cast<const AliFMDCorrELossFit*>(fits), true);
 }
 
 //
index 96982f683dfd9fa0a503f0f1c8bfa0c4f913890d..6fd9db842e05a6136b7e62af3bcfabec7b2b460f 100644 (file)
@@ -20,6 +20,7 @@
 #include <TDatime.h>
 #include <TParameter.h>
 #include <TPaveText.h>
+#include <TBrowser.h>
 
 namespace {
   void 
@@ -42,8 +43,9 @@ namespace {
 #else 
 class AliOADBForward;
 class AliOADBForward::Entry;
+#if 0
 class TGFrame;
-class TGLVEtry;
+class TGLVEntry;
 class TGHorizontalFrame;
 class TGTextButton;
 class TGTextEntry;
@@ -57,6 +59,7 @@ class TGHButtonGroup;
 class TGLayoutHints;
 class TGNumberEntry;
 #endif
+#endif
 
 struct ForwardOADBGUI
 {
@@ -333,11 +336,12 @@ struct ForwardOADBGUI
   void HandleOpen()
   {
     if (fDB) HandleClose();
-    fDB = new AliOADBForward();
+    fDB = new AliOADBForward;
     Info("HandleOpen", "Opening DB file %s for tables %s", 
         fFileText.GetText(), fTablesText.GetText());
-    if (!fDB->Open(fFileText.GetText(), fTablesText.GetText(), 
-                  false, true, true)) { 
+    TString fn(fFileText.GetText());
+    TString tn(fTablesText.GetText());
+    if (!fDB->Open(fn, tn, false, true, true)) { 
       Error("HandleOpen", "Failed to open database");
       delete fDB;
       fDB = 0;
@@ -655,9 +659,9 @@ struct ForwardOADBGUI
 TGMainFrame* ForwardOADBGui(AliOADBForward* db=0)
 {
   const char* fwd = "$ALICE_ROOT/PWGLF/FORWARD/analysis2";
-  // if (!gROOT->GetClass("AliOADBForward")) 
-  // gSystem->Load("libGui");
-  gROOT->Macro(Form("%s/scripts/LoadLibs.C", fwd));
+  if (!gROOT->GetClass("AliOADBForward")) 
+    // gSystem->Load("libGui");
+    gROOT->Macro(Form("%s/scripts/LoadLibs.C", fwd));
   
   // gSystem->AddIncludePath(Form("-I%s", fwd));
   // gROOT->LoadMacro(Form("%s/corrs/ForwardOADBGUI.C", fwd));
index 14d986e01c0437115e8ab9d9845b7b146e48229f..ff7dd78d7791c0e94eef63b3a96bc5a6e0dbafc8 100644 (file)
@@ -74,14 +74,20 @@ TCollection* GetCollection(const TCollection* parent, const TString& name)
  * to.  If this is not specified, it defaults to the name of the input
  * file with "_rerun" attached to the base name
  */
-void RerunELossFits(const TString& input="forward_eloss.root", 
+void RerunELossFits(Bool_t forceSet=false, 
+                   const TString& input="forward_eloss.root", 
                    const TString& output="")
 {
   const char* fwd = "$ALICE_ROOT/PWGLF/FORWARD/analysis2";
   gROOT->Macro(Form("%s/scripts/LoadLibs.C", fwd));
 
-  TFile* inFile  = 0;
-  TFile* outFile = 0;
+  TFile*  inFile  = 0;
+  TFile*  outFile = 0;
+  TString outName(output);
+  if (outName.IsNull()) {
+    outName = input;
+    outName.ReplaceAll(".root", "_rerun.root");
+  }
 
   try {
     // --- Open input file ---------------------------------------------
@@ -102,18 +108,10 @@ void RerunELossFits(const TString& input="forward_eloss.root",
     TCollection* inEFRes = GetCollection(inFwdRes, "fmdEnergyFitter");
     if (!inEFRes) throw TString("Cannot proceed without previous results");
 
-    const TAxis* etaAxis = static_cast<TAxis*>(GetObject(inEFSum, "etaAxis"));
-    if (!etaAxis) throw TString("Cannot proceed without eta axis");
-
     // --- Open output file --------------------------------------------
-    TString outName(output);
-    if (outName.IsNull()) {
-      outName = input;
-      outName.ReplaceAll(".root", "_rerun.root");
-    }
     outFile = TFile::Open(outName, "RECREATE");
     if (!outFile)
-      throw TString::Format("Failed to open %s", input.Data());
+      throw TString::Format("Failed to open %s", outName.Data());
 
     // --- Write copy of sum collection to output --------------------
     TCollection* outFwdSum = static_cast<TCollection*>(inFwdSum->Clone());
@@ -122,33 +120,43 @@ void RerunELossFits(const TString& input="forward_eloss.root",
     
     // --- Make our fitter object ------------------------------------
     AliFMDEnergyFitter* fitter = new AliFMDEnergyFitter("energy");
-    fitter->SetEtaAxis(*etaAxis);
-    // Here, we should get the parameters from the file, but since
-    // that isn't implemented yet, we do it by hand
+    if (forceSet || !fitter->ReadParameters(inEFSum)) {
 
-    // Set maximum energy loss to consider 
-    fitter->SetMaxE(15); 
-    // Set number of energy loss bins 
-    fitter->SetNEbins(500);
-    // Set whether to use increasing bin sizes 
-    // fitter->SetUseIncreasingBins(true);
-    // Set whether to do fit the energy distributions 
-    fitter->SetDoFits(kTRUE);
-    // Set whether to make the correction object 
-    fitter->SetDoMakeObject(kTRUE);
-    // Set the low cut used for energy
-    fitter->SetLowCut(0.4);
+      const TAxis* etaAxis = static_cast<TAxis*>(GetObject(inEFSum,"etaAxis"));
+      if (!etaAxis) throw TString("Cannot proceed without eta axis");
+      fitter->SetEtaAxis(*etaAxis);
+      
+      // Set maximum energy loss to consider 
+      fitter->SetMaxE(15); 
+      // Set number of energy loss bins 
+      fitter->SetNEbins(500);
+      // Set whether to use increasing bin sizes 
+      // fitter->SetUseIncreasingBins(true);
+      // Set whether to do fit the energy distributions 
+      fitter->SetDoFits(kTRUE);
+      // Set whether to make the correction object 
+      fitter->SetDoMakeObject(kTRUE);
+      // Set the low cut used for energy
+      fitter->SetLowCut(0.4);
+      // Set the number of bins to subtract from maximum of distributions
+      // to get the lower bound of the fit range
+      fitter->SetFitRangeBinWidth(4);
+      // Set the maximum number of landaus to try to fit (max 5)
+      fitter->SetNParticles(5);
+      // Set the minimum number of entries in the distribution before
+      // trying to fit to the data - 10k seems the least we can do
+      fitter->SetMinEntries(10000);
+      // fitter->SetMaxChi2PerNDF(10);
+      // Enable debug 
+    }
+    fitter->SetDebug(1);
+    fitter->SetStoreResiduals(AliFMDEnergyFitter::kResidualSquareDifference);
+    // fitter->SetRegularizationCut(3e6);
     // Set the number of bins to subtract from maximum of distributions
     // to get the lower bound of the fit range
-    fitter->SetFitRangeBinWidth(4);
-    // Set the maximum number of landaus to try to fit (max 5)
-    fitter->SetNParticles(5);
-    // Set the minimum number of entries in the distribution before
-    // trying to fit to the data - 10k seems the least we can do
-    fitter->SetMinEntries(10000);
-    // fitter->SetMaxChi2PerNDF(10);
-    // Enable debug 
-    fitter->SetDebug(1);
+    // fitter->SetFitRangeBinWidth(2);
+    // Skip all of FMD2 and 3 
+    // fitter->SetSkips(AliFMDEnergyFitter::kFMD2|AliFMDEnergyFitter::kFMD3);
 
     // --- Now do the fits -------------------------------------------
     fitter->Print();
@@ -168,14 +176,19 @@ void RerunELossFits(const TString& input="forward_eloss.root",
     // --- Write out new results folder ------------------------------
     outFile->cd();
     outFwdRes->Write("ForwardResults", TObject::kSingleKey);
+    Printf("Wrote results to \"%s\" (%s)", outName.Data(), outFile->GetName());
   }
   catch (const TString& e) {
     Error("RerunELossFits", e);
   }
   if (inFile)  inFile->Close();
-  if (outFile) outFile->Close();
+  if (outFile) {
+    Printf("Wrote new output to \"%s\"", outName.Data());
+    outFile->Close();
+  }
     
-  gROOT->Macro(Form("%s/corrs/DrawCorrELoss.C(false,false)", fwd));
+  gROOT->Macro(Form("%s/corrs/DrawCorrELoss.C(false,false,\"%s\")", 
+                   fwd, outName.Data()));
 }
 
 
index 1c586eda0cacb73d34e4076492efe92f27f11d85..d276e8c2a670a468f9b3330fd808309b1a9871be 100755 (executable)
@@ -164,7 +164,7 @@ extract_upload()
            unzip ../$i > /dev/null 2>&1
            touch .zip 
        fi
-       extract ../Extract.C 
+       _extract ../Extract.C 
        upload
        cd ..
     done
@@ -173,12 +173,19 @@ extract_upload()
 # --- Draw -----------------------------------------------------------
 draw()
 {
-    local scr=$1  ; shift
+    local dd=`pwd` 
+    dd=`basename $dd` 
+    echo "=== Drawing in $dd using $1"
+    local scr=$1  ; shift    
+    case x$scr in 
+       x/*) ;; 
+       x*)  scr=../$scr ;; 
+    esac
     # local args=$1 ; shift
     download 
     for i in *.zip ; do 
        if test "X$i" = "X*.zip" ; then continue ; fi
-       echo "Will extract $i"
+       echo "--- Will extract $i in $dd"
        d=`basename $i .zip` 
        if test ! -d $d ; then 
            mkdir -p $d 
@@ -189,25 +196,32 @@ draw()
 }
 dndeta_draw()
 {
+    echo "=== Drawing dN/deta in $1"
+    local top=$1 ; shift 
+    cd $top
     download 
     for i in *.zip ; do 
        if test "X$i" = "X*.zip" ; then continue ; fi
-       echo "Will extract $i"
+       echo "--- Will extract $i"
        d=`basename $i .zip` 
        if test ! -d $d ; then 
            mkdir -p $d 
            unzip $i -d $d
        fi
-       _dndeta_draw $d ../Draw.C $@
+       (cd $d && \
+           script ${fwd_dir}/DrawdNdetaSummary.C && \
+           script ../Draw.C)
     done
+    cd ..
 }
 
 # === Script specific functions ======================================
 # --- Extract corrections --------------------------------------------
 download()
 {
+    echo "=== Executing download in `pwd`"
     if test -f .download ; then 
-       echo "Already downloaded in `basename $PWD`"
+       echo "--- Already downloaded in `basename $PWD`"
        return 0 
     fi
     script Download.C 
@@ -230,7 +244,7 @@ EOF`
 
 run_for_acc()
 {
-    local r=`grep -v ^# $runs | awk '{FS=" \n\t"}{printf "%d\n", $1}' | head -n 1` 
+    local r=`grep -v ^# ../$runs | awk '{FS=" \n\t"}{printf "%d\n", $1}' | head -n 1` 
     if test x$r = "x" || test $r -lt 1; then 
        echo "No run for acceptance correction specified" > /dev/stderr 
        exit 1
@@ -372,8 +386,7 @@ allAboard()
 {
     local type=$1 ; shift
     local trig=$1 ; shift
-    opts="--batch"
-    _allAboard "$type" "$trig" $@ 
+    _allAboard "$type" "$trig" --batch $@ 
 
     if test $watch -lt 1 ; then 
        cat <<-EOF
index ba6d86335472c5ff969fb03904ea24eb18289e94..4c33c07a44909017174ce130d3c37aa3e18fe967 100644 (file)
@@ -57,8 +57,11 @@ public:
     // --- Make our canvas -------------------------------------------
     TString pdfName(filename);
     pdfName.ReplaceAll(".root", ".pdf");
-    CreateCanvas(pdfName, what & 0x100);
+    CreateCanvas(pdfName, what & kLandscape);
 
+    // --- Make a Title page -------------------------------------------
+    DrawTitlePage(file);
+    
     // --- Possibly make a chapter here ------------------------------
     if (what & kCentral && GetCollection(file, "CentralCorrSums")) 
       MakeChapter("Forward");
@@ -101,6 +104,47 @@ public:
     CloseCanvas();
   }
 protected:
+  //____________________________________________________________________
+  void DrawTitlePage(TFile* file)
+  {
+    TCollection* c   = GetCollection(file, "ForwardCorrResults");
+
+    fBody->cd();
+    
+    Double_t y = .9;
+    TLatex* ltx = new TLatex(.5, y, "ESD+MC #rightarrow Corrections");
+    ltx->SetTextSize(0.07);
+    ltx->SetTextFont(42);
+    ltx->SetTextAlign(22);
+    ltx->SetNDC();
+    ltx->Draw();
+    y -= .075;
+
+    TCollection* ei = GetCollection(c, "fmdEventInspector");
+    if (ei) { 
+      Int_t sys=0, sNN=0, field=0, runNo=0;
+
+      if (GetParameter(ei, "sys", sys))
+       DrawParameter(y, "System", (sys == 1 ? "pp" : sys == 2 ? "PbPb" : 
+                                   sys == 3 ? "pPb" : "unknown"));
+      if (GetParameter(ei, "sNN", sNN)) {
+       TString tsNN = TString::Format("%dGeV", sNN);
+       if (sNN >= 10000) 
+         tsNN = TString::Format("%5.2f", float(sNN)/1000);
+       else if (sNN >= 1000) 
+         tsNN = TString::Format("%4.2f", float(sNN)/1000);
+       DrawParameter(y, "#sqrt{s_{NN}}", tsNN);
+      }
+
+      if (GetParameter(ei, "field", field))
+       DrawParameter(y, "L3 B field", Form("%+2dkG", field));
+
+      if (GetParameter(ei, "runNo", runNo))
+       DrawParameter(y, "Run #", Form("%6d", runNo));
+    }
+
+    PrintCanvas("MC Corrections");
+  }
   //____________________________________________________________________
   TCollection* GetVertexList(TCollection* parent, const TAxis& axis, Int_t bin)
   {
index 0fe0364a78186ce1d489fef6fa5546a5b52a08f7..3887cfc392600a4a77171b65369abc60b45312ca 100644 (file)
@@ -29,6 +29,8 @@ public:
     : TrainSetup(name)
   {
     fOptions.Add("cent", "Use centrality");
+    fOptions.Add("residuals", "MODE", "Optional calculation of residuals", "");
+    fOptions.Set("type", "ESD");
   }
 protected:
   //------------------------------------------------------------------
@@ -64,12 +66,15 @@ protected:
                             gROOT->GetMacroPath()));
 
     // --- Check if this is MC ---------------------------------------
-    Bool_t mc   = mgr->GetMCtruthEventHandler() != 0;
-    Bool_t cent = fOptions.Has("cent");
-    Int_t  verb = fOptions.AsInt("verbose");
+    Bool_t   mc   = mgr->GetMCtruthEventHandler() != 0;
+    Bool_t   cent = fOptions.Has("cent");
+    Int_t    verb = fOptions.AsInt("verbose");
+    TString  resi = "";
+    if (fOptions.Has("residuals")) resi = fOptions.Get("residuals"); 
 
     // --- Add the task ----------------------------------------------
-    gROOT->Macro(Form("AddTaskFMDELoss.C(%d,%d,%d)", mc, cent, verb));
+    gROOT->Macro(Form("AddTaskFMDELoss.C(%d,%d,%d,\"%s\")", 
+                     mc, cent, verb, resi.Data()));
   }
   /** 
    * Create entrality selection if enabled 
index 1d908d03cb6f5c0cea49caaf6e7da0c4bb577f05..ce00615e5ab7e6dbaa0e9c39e747f252687c2f09 100644 (file)
@@ -31,6 +31,7 @@ public:
   {
     fOptions.Add("cent", "Use centrality");
     fOptions.Set("type", "ESD");
+    fOptions.Add("corr", "DIR", "Corrections dir", "");
   }
 protected:
   //__________________________________________________________________
@@ -64,6 +65,12 @@ protected:
                 Form("%d,%d", mc, fOptions.Has("cent"))))
       Fatal("CreateTasks", "Failed to add ForwardQA task");
 #endif
+
+    TString  cor = "";
+    if (fOptions.Has("corr")) cor = fOptions.Get("corr"); 
+    if (!cor.IsNull()) {
+      fHelper->LoadAux(Form("%s/fmd_corrections.root",cor.Data()), true);
+    }
   }
   /** 
    * Create entrality selection if enabled