ROOT logo
#include "AliLandauGaus.h"
#include <TSystem.h>
#include <TString.h>
#include <TList.h>
#include <TFile.h>
#include <TMath.h>
#include <TF1.h>
#include <TH1.h>
#include <TH2.h>
#include <TFitResult.h>
#include <TNtuple.h>
#include <TAxis.h>
#include <TMath.h>
#include <TCanvas.h>
#include <TStyle.h>
#include <TLine.h>
#include <TLatex.h>
#include <TPaveStats.h>

//====================================================================
/** 
 * Base class for tests
 * 
 */
struct TestF
{
  //__________________________________________________________________
  /** 
   * Base class for individual tests
   */
  struct Test { 
    /** Source distribution */
    TF1* src;
    /** 
     * Constructor 
     */
    Test() : src(0) {}
    /** 
     * Copy constructor 
     */
    Test(const Test& o) 
      : src(static_cast<TF1*>(o.src ? o.src->Clone() : 0)) {}
    /** 
     * Destructor 
     */
    virtual ~Test() { delete src; }
    /** 
     * Assignment operator  
     */
    Test& operator=(const Test& o) {
      if (&o == this) return *this;
      if (o.src) src = static_cast<TF1*>(o.src->Clone());
      return *this;
    }
    /** 
     * Run the test
     * 
     * @param c     Constant
     * @param delta Most probable value 
     * @param xi    Landau width
     * @param sigma Gaussian smear
     * @param n     Maximum number of particles
     * @param a     Particle weights
     * @param xMin  Least energy loss 
     * @param xMax  Largest energy loss
     */
    void Run(const Double_t  c, 
	     const Double_t  delta, 
	     const Double_t  xi, 
	     const Double_t  sigma, 
	     const Int_t     n, 
	     const Double_t* a,
	     const Double_t  xMin, 
	     const Double_t  xMax) {
      printf("%8.4f | %8.4f | %8.4f | ", delta, xi, sigma);
      fflush(stdout);
      src = AliLandauGaus::MakeFn(c,delta,xi,sigma,0,n,&(a[1]),xMin,xMax);
      src->SetName("src");
      src->SetLineColor(kBlack);
      src->SetNpx(10000);
      // If the constant is 1, then this is a fake distribtion and we
      // need to scale it. 
      if (c >= 1) { 
	Double_t max = src->GetMaximum();
	src->SetParameter(0, c/max);
      }

      // src->Print();
      DoRun();
    }
    /** 
     * @return Source parameter @f$ C@f$
     */
    Double_t C()      const { return src->GetParameter(AliLandauGaus::kC); }
    /** 
     * @return Source parameter @f$\Delta_p@f$ 
     */
    Double_t Delta()  const { return src->GetParameter(AliLandauGaus::kDelta); }
    /** 
     * @return Source parameter @f$\xi@f$ 
     */
    Double_t Xi()     const { return src->GetParameter(AliLandauGaus::kXi); }
    /** 
     * @return Source parameter @f$ \sigma@f$ 
     */
    Double_t Sigma()  const { return src->GetParameter(AliLandauGaus::kSigma); }
    /** 
     * @return Source parameter @f$ \sigma_n@f$
     */
    Double_t SigmaN() const { return src->GetParameter(AliLandauGaus::kSigmaN);}
    /** 
     * @return Source parameter @f$ N@f$
     */
    Double_t N()      const { return src->GetParameter(AliLandauGaus::kN); }
    /** 
     * @return Source parameter @f$ a_i@f$ 
     */
    Double_t A(Int_t i) const { 
      return (i <= 1 ? 1 : src->GetParameter(AliLandauGaus::kN+(i-1))); }
    /** 
     * @return Least energy loss
     */
    Double_t XMin() const { return src->GetXmin(); }
    /** 
     * @return Largest energy loss
     */
    Double_t XMax() const { return src->GetXmax(); }
    /** 
     * Generate single component function for @a i particles
     * 
     * @param c      Constant 
     * @param delta  @f$\Delta_p@f$ 
     * @param xi     @f$\xi@f$ 
     * @param sigma  @f$\sigma@f$ 
     * @param sigmaN @f$\sigma_n@f$
     * @param i      Number of particles 
     * 
     * @return Pointer to function object 
     */
    TF1* Fi(Double_t c, Double_t delta, Double_t xi, Double_t sigma, 
	    Double_t sigmaN, Int_t i) const { 
      return AliLandauGaus::MakeFi(c,delta,xi,sigma,sigmaN,i,XMin(),XMax());
    }
    /** 
     * Generate single component function for @a i particles using
     * source parameters
     * 
     * @param i      Number of particles 
     * 
     * @return Pointer to function object 
     */
    TF1* Fi(Int_t i) { 
      return Fi(C()*A(i),Delta(),Xi(),Sigma(),SigmaN(),i);
    }
    
    /** 
     * @{ 
     * @name Overload-able interface 
     */
    /** 
     * Run the test
     */
    virtual void DoRun() = 0;
    /** 
     * Write results to disk 
     * 
     * @param d Directory to write to 
     */
    virtual void WriteOut(TDirectory* d) = 0;
    /** 
     * Draw results in a pad 
     * 
     * @param p Pad to draw in 
     */
    virtual void DrawInPad(TVirtualPad* p) = 0;
    /* @} */
  };
  //__________________________________________________________________
  /** 
   * @{
   * @name Utilities 
   */
  /** 
   * Draw a vertical line 
   * 
   * @param i    Line style
   * @param col  Line color
   * @param x    X value 
   * @param low  Least Y value 
   * @param high Largest Y value 
   * 
   * @return The line 
   */
  static TLine*
  VerticalLine(Int_t i, Color_t col, Double_t x, Double_t low, Double_t high)
  {
    TLine* l = new TLine(x,low,x,high);
    l->SetLineStyle(i);
    l->SetLineColor(col);
    return l;
  }
  //__________________________________________________________________
  virtual ~TestF() {}
  /** 
   * Make a test object - overload
   * 
   * @return The test object
   */
  virtual Test* MakeTest() = 0;
  /** 
   * Do one scan 
   * 
   * @param c        Constant
   * @param delta    Most probable value @f$\Delta_p@f$
   * @param xi       Landau width @f$\xi@f$
   * @param sigma    Gaussian spread @f$\sigma@f$
   * @param n        Maximum number of particles
   * @param a        Particle weights 
   * @param xMin     Least @f$\Delta @f$ 
   * @param xMax     Largest @f$\Delta@f$
   * 
   * @return The test object
   */
  Test* DoOne(const Double_t  c, 
	      const Double_t  delta, 
	      const Double_t  xi, 
	      const Double_t  sigma, 
	      const Int_t     n, 
	      const Double_t* a, 
	      const Double_t  xMin, 
	      const Double_t  xMax,
	      TVirtualPad*    pad=0)
  {
    Test* t = MakeTest();
    t->Run(c, delta, xi, sigma, n, a, xMin, xMax);

    TString name(Form("sigma%04d_xi%04d", Int_t(100*sigma), Int_t(100*xi)));
    TString title(Form("Sigma=%f xi=%f", sigma, xi));
    if (!pad) { 
      TCanvas* can = new TCanvas(name, title, 1200, 900);
      pad = can;
    }
    else 
      pad->Clear();
    t->DrawInPad(pad);

    return t;
  }
  /** 
   * Do a unit scan 
   * 
   * @param sigma @f$\sigma@f$ of the Gaussian
   * @param xi    @f$\xi@f$ width of Landau
   * @param n     Number of particles 
   * @param pad   Possibly existing canvas to plot in 
   *
   * @return Scan object
   */
  Test* DoUnit(const Double_t sigma, 
	       const Double_t xi=1, 
	       const Int_t    n=10,
	       TVirtualPad*   pad=0) 
  { 
    const Double_t c      = 1;
    const Double_t delta  = 10;
    Double_t       idelta = delta;
    Double_t       ixi    = xi;
    Double_t       isigma = sigma;
    AliLandauGaus::IPars(n+1,idelta,ixi, isigma);
    Double_t       up     = idelta + ixi + isigma; // 8*n
    Double_t       a[n];
    a[0] = 1;
    for (Int_t i = 1; i < n; i++) 
      a[i] = TMath::Exp(0.5 - TMath::Sqrt(2)*(i+1));

    return DoOne(c,delta,xi,sigma,n,a,-3,up, pad);
  }
  /** 
   * Do a realistic scan 
   * 
   * @param pad   Possibly existing canvas to plot in 
   * 
   * @return Scan object
   */
  Test* DoRealistic(TVirtualPad* pad=0) 
  {
    Double_t c     = 0.4070;
    Double_t delta = 0.5651;
    Double_t xi    = 0.0643;
    Double_t sigma = 0.0611;
    Int_t    n     = 5;
    Double_t a[]   = {1, 0.1179, 0.0333, 0.0068, 0.0012 };

    return DoOne(c, delta, xi, sigma, n, a, 0.02, n, pad);
  }
  /** 
   * Prefix on output 
   * 
   * 
   * @return 
   */
  virtual const char* Prefix() const = 0;
  /** 
   * Make an output ntuple 
   * 
   * @return Possibly newly allocated NTuple 
   */
  virtual TNtuple* MakeNTuple() { return 0; }
  /** 
   * Setup for scanning 
   * 
   * @param mode   Scanning mode 
   * @param file   Output file 
   * @param canvas Canvas 
   * @param nt     Possible Ntuple 
   */
  virtual void SetupScan(UShort_t  mode, 
			 TFile*&   file, 
			 TCanvas*& canvas, 
			 TNtuple*& nt) 
  {
    TString  base = Form("%s%s", Prefix(), 
			 (mode == 0 ? "SigmaXi" : 
			  mode == 1 ? "Sigma" : "Xi"));
    file   = TFile::Open(Form("%s.root", base.Data()), "RECREATE");
    nt     = MakeNTuple();
    canvas = new TCanvas(base, Form("%s.pdf", base.Data()),
			       TMath::Sqrt(2)*900, 900);
    TString title("pdf Landscape Title:Scan");
    gSystem->RedirectOutput("/dev/null");
    canvas->Print(Form("%s[", canvas->GetTitle()), title);
    gSystem->RedirectOutput(0);
  }
  /** 
   * Print canvas to output PDF 
   * 
   * @param c      Canvas
   * @param title  Title of page 
   * 
   * @return The full title of the page 
   */
  void PrintCanvas(TCanvas* c, Double_t xi, Double_t sigma) {
    TString tit = "pdf Landscape Title:";
    Bool_t  cls = false;
    if (xi > 0 && sigma > 0) {
      tit.Append(Form("xi=%8.4f sigma=%8.4f", xi, sigma));
    }
    else { 
      tit.Append("Results");
      cls = true;
    }
    gSystem->RedirectOutput("/dev/null");
    c->Print(c->GetTitle(), tit);
    if (cls) {
      c->Clear();
      c->Print(Form("%s]", c->GetTitle()), tit);
    }
    gSystem->RedirectOutput(0);
    if (cls)
      ::Info("", "Plots saved in %s", c->GetTitle());
  }
  /** 
   * Executed before loop 
   * 
   * @param mode  Mode
   * @param nVal  Number of values  
   */
  virtual void PreLoop(UShort_t mode, Int_t nVal) = 0;
  /** 
   * Process a single step 
   * 
   * @param mode   Mode 
   * @param i      First index 
   * @param j      Second index (if any)
   * @param n      Number of values
   * @param test   Test result
   */
  virtual void Step(UShort_t mode, 
		    Int_t    i, 
		    Int_t    j, 
		    Int_t    n, 
		    Test*    test,
		    TNtuple* nt) = 0;
  /** 
   * Called after looping 
   * 
   * @param mode Execution mode 
   * @param can  Canvas
   * @param nt   NTuple
   * @param out  Output file 
   */
  virtual void PostLoop(UShort_t mode, 
			TCanvas* can, 
			TNtuple* nt, 
			TFile*   out) = 0;
  /** 
   * Scan over a parameter (@f$\xi@f$ or @f$\sigma@f$) 
   * 
   * @param sigma   If true, scan @f$\sigma@f$, otherwise @f$\xi@f$ 
   * @param n       Number of values
   * @param values  Values of the parameters
   * @param maxN    Number of particles 
   */
  void ScanOne(Bool_t          scanSigma, 
	       Int_t           n, 
	       const Double_t* values, 
	       Int_t           maxN=10) 
  {
    UShort_t mod = scanSigma ? 1 : 2;
    Scan(mod, n, values, maxN);
  }
  /** 
   * Scan over a parameter (@f$\xi@f$ or @f$\sigma@f$) 
   * 
   * @param sigma   If true, scan @f$\sigma@f$, otherwise @f$\xi@f$ 
   * @param values  Values of the parameters
   * @param maxN    Number of particles 
   */
  void ScanOne(Bool_t         scanSigma, 
	       const TArrayD& values, 
	       Int_t          maxN)
  {
    ScanOne(scanSigma, values.GetSize(), values.GetArray(), maxN);
  }
  /** 
   * Scan over both parameter (@f$\xi@f$ and @f$\sigma@f$) 
   * 
   * @param n       Number of parameters 
   * @param values  Values of the parameters
   * @param maxN    Number of particles 
   */
  void ScanTwo(Int_t           n, 
	       const Double_t* values, 
	       Int_t           maxN=10)
  {
    Scan(0, n, values, maxN);
  }
  /** 
   * Scan over both parameter (@f$\xi@f$ and @f$\sigma@f$) 
   * 
   * @param values  Values of the parameters
   * @param maxN    Number of particles 
   */
  void ScanTwo(const TArrayD& values, Int_t maxN)
  {
    ScanTwo(values.GetSize(), values.GetArray(), maxN);
  }
  /** 
   * Do the scan 
   * 
   * @param mode    Mode of operation (0: both, 1: @f$\sigma@f$, or @f$\xi@f$)
   * @param n       Number of values 
   * @param values  Values 
   * @param maxN    Maximum number of particles 
   */
  void Scan(UShort_t        mode, 
	    Int_t           n, 
	    const Double_t* values, 
	    Int_t           maxN)
  {
    TFile*   out = 0;
    TNtuple* nt  = 0;
    TCanvas* can = 0;
    SetupScan(mode, out, can, nt);
    PreLoop(mode, n);

    Test* t  = DoRealistic(can);
    t->WriteOut(out->mkdir("realistic"));
    can->Write();
    PrintCanvas(can, t->Xi(), t->Sigma());
    
    if (mode == 0) LoopTwo(n, values, maxN, can, nt, out);
    else           LoopOne(mode, n, values, maxN, can, nt, out);
    
    PostLoop(mode, can, nt, out);
    out->Write();
    out->Close();

  }
  /** 
   * Loop over one of @f$\xi@f$ or @f$\sigma@f$ 
   * 
   * @param mode    Mode (1: @f$\sigma@f$, otherwise @f$\xi@f$)
   * @param n       Number of values
   * @param values  Values
   * @param maxN    Maximum number of particles 
   * @param can     Canvas to draw in 
   * @param nt      NTuple to fill 
   * @param out     Output directory 
   */
  void LoopOne(UShort_t        mode, 
	       Int_t           n, 
	       const Double_t* values, 
	       Int_t           maxN,
	       TCanvas*        can, 
	       TNtuple*        nt, 
	       TFile*          out) {
    Bool_t      scanSigma = mode == 1;
    const char* var       = (scanSigma ? "sigma" : "xi");
	
    for (Int_t i = 0; i < n; i++) { 
      Double_t    v     = values[i];
      Double_t    sigma = (scanSigma  ? v : 1);
      Double_t    xi    = (!scanSigma ? v : 1);

      StepIt(mode, xi, sigma, maxN, 0, i, n, can, nt, out, var, v);
    }
  }
  /** 
   * Loop over both @f$\xi@f$ and @f$\sigma@f$ 
   * 
   * @param n       Number of values
   * @param values  Values
   * @param maxN    Maximum number of particles 
   * @param can     Canvas to draw in 
   * @param nt      NTuple to fill 
   * @param out     Output directory 
   */
  void LoopTwo(Int_t           n, 
	       const Double_t* values, 
	       Int_t           maxN,
	       TCanvas*        can, 
	       TNtuple*        nt, 
	       TFile*          out) 
  { 
    UShort_t mode = 0;
    for (Int_t i = 0; i < n; i++) { 
      Double_t      xi  = values[i];
      TDirectory*   d   = out->mkdir(Form("xi%04d", Int_t(100*xi)));
      for (Int_t j = 0; j < n; j++) { 
	Double_t    sigma = values[j];
	StepIt(mode, xi, sigma, maxN, i, j, n, can, nt, d, "sigma", sigma);
      }
    }
  }
  /** 
   * 
   * 
   * @param mode   Mode
   * @param xi     @f$\xi@f$ 
   * @param sigma  @f$\sigma@f$ 
   * @param maxN   At most this many particles
   * @param i      First index
   * @param j      Last index 
   * @param n      Number of values
   * @param can    Canvas 
   * @param nt     NTuple 
   * @param p      Parent directory
   * @param pre    Prefix on directory
   * @param v      Current value 
   */
  void StepIt(UShort_t    mode, 
	      Double_t    xi, 
	      Double_t    sigma, 
	      Int_t       maxN, 
	      Int_t       i, 
	      Int_t       j, 
	      Int_t       n, 
	      TCanvas*    can, 
	      TNtuple*    nt, 
	      TDirectory* p, 
	      const char* pre, 
	      Double_t    v)
  {
    TDirectory* d     = p->mkdir(Form("%s%04d", pre, Int_t(100*v)));
    Test*       t     = DoUnit(sigma, xi, maxN, can);
    t->WriteOut(d);
    can->Write();
    PrintCanvas(can, xi, sigma);
      
    Step(mode, i, j, n, t, nt);
  }
};

//====================================================================
#ifdef TEST_SHIFT
#include "WrappedGraph.C"
#include <TGraphErrors.h>
#include <TGraph2DErrors.h>
#include <TMultiGraph.h>
#include <Math/RootFinder.h>

struct TestShift : public TestF
{
  /** 
   * Our fit function
   *
   * @f[
   *   \Delta_{i,p} - \Delta_{i,r} = 
   *     f(i;c,p,\xi,\sigma) = 
   *     \frac{c u \sigma}{(1+1/i)^{p u^{3/2}}
   * @f]
   *
   * where @f$ u=\sigma/\xi@f$ 
   * 
   * @param xp Independent variables 
   * @param pp Parameters
   * 
   * @return @f$ f(i;c,p,\xi,\sigma)@f$ 
   */
  static Double_t fitFunc(Double_t* xp, Double_t* pp) {
    Double_t x     = *xp;
    Double_t c     = pp[0];
    Double_t p     = pp[1];
    Double_t xi    = pp[2];
    Double_t sigma = pp[3];
    Double_t u     = sigma / xi;
    Double_t a     = c * u * sigma;
    Double_t b     = p * u * TMath::Sqrt(u);
      
    return a / TMath::Power(1+1./x, b);
  }
  /** 
   * Scale a graph 
   * 
   * @param g     Graph to scale
   * @param scale Scale 
   */
  static void ScaleGraph(TGraph* g, Double_t scale)
  {
    // Info("", "Scaling graph %p with %f", g, scale);
    if (scale == 1) return;
    for (Int_t i = 0; i < g->GetN(); i++) 
      g->SetPoint(i,g->GetX()[i], g->GetY()[i] * scale);
  }
  //__________________________________________________________________
  struct Test : public TestF::Test 
  {
    TGraph*  zeros;       // Zeros of the derivatives
    TGraph*  diff;        // Difference from calculated Delta to roots
    TList    comps;       // Components 
    TList    derivs;      // Derivatives 
    TF1*     fit;         // Fit to difference 
    Test() : TestF::Test(), zeros(0), diff(0), fit(0) 
    {
      comps.SetName("components");
      derivs.SetName("derivatives");

    }
    /** 
     * Run the actual test
     */
    void DoRun() 
    { 
      AliLandauGaus::EnableSigmaShift(false); // Disable sigma-shift
      const Int_t n = N();
      zeros = new TGraph(n);
      zeros->SetName("zeros");
      zeros->SetTitle("Zeros of derivatives");
      zeros->SetMarkerStyle(25);
      zeros->SetMarkerSize(1.2);
      zeros->SetMarkerColor(kRed+1);

      diff = new TGraph(n);
      diff->SetName("diff");
      diff->SetTitle("#delta#Delta_{p}");
      diff->SetMarkerStyle(20);
      diff->SetMarkerColor(kBlue+1);

      // Make the components 
      Int_t j = 0;
      for (Int_t i = 1; i <= n; i++, j++) 
	if (!MakeComp(i)) break;
      zeros->Set(j);
      diff->Set(j);

      // Now fit 
      fit = new TF1("fit", &fitFunc, 1, j, 4);
      fit->SetParNames("c", "p", "#xi", "#sigma");
      fit->SetParameter(0, .5);
      fit->SetParameter(1, .5);
      fit->FixParameter(2, Xi());
      fit->FixParameter(3, Sigma());
      
      // fit->SetParNames("c", "#xi", "#sigma");
      // fit->FixParameter(1, xi);


      Int_t ifit = 4;
      do { 
	gSystem->RedirectOutput("/dev/null");
	diff->Fit(fit, Form("MR%s", ifit == 0 ? "Q" : "Q"));
	gSystem->RedirectOutput(0);
	ifit--;
      } while (ifit >= 0);
      Printf("%8.4f | %8.4f %9.5f | %8.4f %9.5f",
	     fit->GetChisquare() / fit->GetNDF(),
	     fit->GetParameter(0), fit->GetParError(0),
	     fit->GetParameter(1), fit->GetParError(1));

    }
    /** 
     * Make a single component 
     * 
     * @param i        Number of particles
     */
    Bool_t MakeComp(const Int_t    i) {
      TF1* fi = Fi(i);
      fi->SetNpx(src->GetNpx());
      // fi->Print();

      TGraph* dF = new TGraph(fi, "d");
      dF->SetName(Form("d%s", fi->GetName()));
      dF->SetTitle(Form("d%s/d#Delta", fi->GetTitle()));
      dF->SetMarkerStyle(1); // A dot 
      // dF->SetMarkerStyle(20+i-1);
      dF->SetMarkerColor(fi->GetLineColor());
      dF->SetLineColor(fi->GetLineColor());

      Double_t max = TMath::MaxElement(dF->GetN(), dF->GetY());
      if (max < 1e-6) return false;

      ScaleGraph(dF, 1./max);
      Double_t delta  = Delta();
      Double_t xi     = Xi();
      Double_t deltaI = i * (delta + xi * TMath::Log(i));
      Double_t xiI    = i * xi;
      Double_t xR     = FindRoot(dF, deltaI-2*xiI, deltaI+2*xiI);
      
      // Printf("Component %2d: Exp: %8.4f  Got: %8.4f  Diff: %9.5f", 
      //        i, deltaI, xR, (xR-deltaI));
      // printf(".");
      comps.Add(fi);
      derivs.Add(dF);
      zeros->SetPoint(i-1, xR, dF->Eval(xR));
      diff->SetPoint(i-1, i, xR - deltaI);

      return true;
    }
    /** 
     * Find the root of a graph
     * 
     * @param g     Graph
     * @param xMin  Least value of scan range 
     * @param xMax  Largest value of scan range 
     * 
     * @return Zero of the graph
     */
    Double_t FindRoot(TGraph* g, Double_t xMin, Double_t xMax) { 
      WrappedGraph* wG = new WrappedGraph(g);
      ROOT::Math::RootFinder rfb(ROOT::Math::RootFinder::kBRENT);
      rfb.SetFunction(*wG, xMin, xMax); 
      rfb.Solve();
      Double_t xR = rfb.Root();
      return xR;
    }
    /** 
     * Draw the results in a pad 
     * 
     * @param body Pad to draw in 
     */
    void DrawInPad(TVirtualPad* body) { 
      body->SetTopMargin(0.01);
      body->SetRightMargin(0.01);
      body->Divide(2,1);
      
      TVirtualPad* p = body->cd(1);
      p->SetTopMargin(0.01);
      p->SetRightMargin(0.01);
      p->Divide(1,2,0,0);
      
      TVirtualPad* q = p->cd(1);
      q->SetRightMargin(0.01);
      q->SetGridx();
      q->SetLogy();
      src->Draw();
      Double_t fmax = src->GetHistogram()->GetMaximum();
      Double_t fmin = src->GetHistogram()->GetMinimum();
      fmin          = TMath::Max(fmin, fmax/1e8);
      src->GetHistogram()->SetMinimum(fmin);
      TLatex*  ltx  = new TLatex(q->GetLeftMargin()+.02, 
				 1-q->GetTopMargin()-.02,
				 Form("#Delta_{p}=%f, #xi=%f, #sigma=%f", 
				      Delta(), Xi(), Sigma()));
      // Printf("%s: Max=%f scale=%f", src->GetName(), fmax, 1/fmax);
      ltx->SetTextFont(42);
      ltx->SetNDC();
      ltx->SetTextAlign(13);
      ltx->Draw();

      q = p->cd(2);
      q->SetRightMargin(0.01);
      q->SetGridx();
      
      Double_t x = 1-q->GetRightMargin()-.02;
      Double_t y = 1-q->GetTopMargin()-.1;
      for (Int_t i = 1; i <= comps.GetEntries(); i++) { 
	p->cd(1);
	TF1* fi = static_cast<TF1*>(comps.At(i-1));
	fi->Draw("same");

	Double_t deltaR = zeros->GetX()[i-1];
	Double_t deltaI = i * (Delta() + Xi() * TMath::Log(i));

	Color_t col = fi->GetLineColor();
	VerticalLine(1,col,deltaI,fmin,fmax)->Draw();
	VerticalLine(3,col,deltaR,fmin,fmax)->Draw();
	
	ltx = new TLatex(x,y,Form("#Delta_{p,%2d}=%8.4f %8.4f",
				  i,deltaI,deltaR));
	ltx->SetTextAlign(33);
	ltx->SetTextFont(42);
	ltx->SetNDC();
	ltx->Draw();
	y -= ltx->GetTextSize() + .01;

	p->cd(2);

	TGraph* df = static_cast<TGraph*>(derivs.At(i-1));
	df->Draw(i == 1 ? "alp" : "lp");
	df->GetHistogram()->GetXaxis()->SetRangeUser(XMin(), XMax());	
	VerticalLine(1,col,deltaI,-.6,1.1)->Draw();
	VerticalLine(3,col,deltaR,-.6,1.1)->Draw();
      }
      p->cd(2);
      zeros->Draw("p");
      
      gStyle->SetOptFit(111111);
      gStyle->SetStatY(.6);
      p = body->cd(2);
      p->SetRightMargin(0.02);
      p->SetTopMargin(0.02);
      diff->Draw("alp");
      diff->GetHistogram()->GetListOfFunctions()->Add(fit);
      diff->GetHistogram()->SetXTitle("N_{particle}");
      diff->GetHistogram()->SetYTitle("#Delta_{r}-#Delta_{p}");
      p->Clear();
      diff->Draw("alp");

      body->Modified();
      body->Update();
      body->cd();
    }
    /** 
     * Write results to disk 
     * 
     * @param dir Directory
     */
    void WriteOut(TDirectory* dir) { 
      dir->cd();
      src->Write();
      zeros->Write();
      diff->Write();
      comps.Write(comps.GetName(),  TObject::kSingleKey);
      derivs.Write(derivs.GetName(),  TObject::kSingleKey);
      fit->Write();
    }
  };
  //__________________________________________________________________
  TGraphErrors*   cs;
  TGraphErrors*   ps;
  TGraph2DErrors* c2s;
  TGraph2DErrors* p2s;
  TMultiGraph*    mcs;
  TMultiGraph*    mps;
  
  /** 
   * Make a test object - overload
   * 
   * @return The test object
   */
  virtual TestF::Test* MakeTest() { return new Test(); }
  /** 
   * Prefix on output 
   * 
   * @return The string "shift"
   */
  virtual const char* Prefix() const { return "shift"; }
  /** 
   * Make an output ntuple 
   * 
   * @return Possibly newly allocated NTuple 
   */
  virtual TNtuple* MakeNTuple () 
  { 
    return new TNtuple("shift","Shift scan",
		       "Delta:xi:sigma:chi2nu:p:ep:c:ec");
  }
  /** 
   * Set-up for looping 
   * 
   * @param mode 
   * @param nVal 
   */
  virtual void PreLoop(UShort_t mode, Int_t n) 
  { 
    if (mode == 0) {
      c2s = new TGraph2DErrors(n*n);c2s->SetName("cs");
      p2s = new TGraph2DErrors(n*n);p2s->SetName("ps");
      mcs = new TMultiGraph("mcs", "C as function of #sigma/#xi");
      mps = new TMultiGraph("mps", "P as function of #sigma/#xi");
      c2s->SetDirectory(0);
      p2s->SetDirectory(0);
      c2s->SetMarkerStyle(20);
      p2s->SetMarkerStyle(20);
      c2s->SetTitle("c(#xi,#sigma)");
      p2s->SetTitle("p(#xi,#sigma)");
    }
    else {
      const char* var = (mode == 1 ? "#sigma" : "#xi");
      cs = new TGraphErrors(n); cs->SetName("cs");
      ps = new TGraphErrors(n); ps->SetName("ps");
      cs->SetMarkerStyle(20);
      ps->SetMarkerStyle(20);
      cs->SetTitle(Form("c(%s)", var));
      ps->SetTitle(Form("p(%s)", var));
    }
    Printf("%-8s | %-8s | %-8s | %-8s | %-8s %-9s | %-8s %-9s",
	   "Delta_p", "xi", "sigma", "chi^2/nu", "c", "error", "p", "error");
  }
  /** 
   * Fill multi graph
   * 
   * @param mg - multi-graph
   * @param i    First index
   * @param j    Second index
   * @param n    Number of steps in each directon 
   * @param u    @f$\sigma/\xi@f$ 
   * @param y    Value 
   * @param e    Error
   */
  void FillMG(TMultiGraph* mg,
	      Int_t        i, 
	      Int_t        j, 
	      Int_t        n, 
	      Double_t     u, 
	      Double_t     y, 
	      Double_t     e) 
  { 
    TList* l = mg->GetListOfGraphs();
    TGraphErrors* ge = (l ? static_cast<TGraphErrors*>(l->At(i)) : 0);
    if (!ge) { 
      ge = new TGraphErrors(n);
      ge->SetName(Form("%s%02d", mg->GetName(), i));
      ge->SetTitle(Form(Form("%d", i)));
      ge->SetMarkerColor(AliLandauGaus::GetIColor(i));
      ge->SetLineColor(AliLandauGaus::GetIColor(i));
      ge->SetMarkerStyle(20);
      mg->Add(ge);
    }
    ge->SetPoint(j, u, y);
    ge->SetPointError(j, 0, e);
  }
  /** 
   * Process a single step 
   * 
   * @param mode  Mode 
   * @param i     First index
   * @param j     Second index
   * @param n     Number of steps in each direction 
   * @param bt    Test result 
   */
  virtual void Step(UShort_t     mode, 
		    Int_t        i, 
		    Int_t        j, 
		    Int_t        n, 
		    TestF::Test* bt,
		    TNtuple*     nt) 
  { 
    Test* t = static_cast<Test*>(bt);
    Double_t xi    = t->Xi();
    Double_t sigma = t->Sigma();
    Double_t c     = t->fit->GetParameter(0);
    Double_t p     = t->fit->GetParameter(1);
    Double_t ec    = t->fit->GetParError(0);
    Double_t ep    = t->fit->GetParError(1);
    Int_t    idx   = i * n + j;
    if (mode == 0) {
      c2s->SetPoint(idx, xi, sigma, c);
      p2s->SetPoint(idx, xi, sigma, p);
      c2s->SetPointError(idx, 0, 0, ec);
      p2s->SetPointError(idx, 0, 0, ep);
      FillMG(mcs, i, j, n, sigma/xi, c, ec);
      FillMG(mps, i, j, n, sigma/xi, p, ep);
    }
    else { 
      cs->SetPoint(idx, (mode==1 ? sigma : xi), c);
      ps->SetPoint(idx, (mode==1 ? sigma : xi), p);
      cs->SetPointError(idx, 0, ec);
      ps->SetPointError(idx, 0, ep);
    }
    nt->Fill(1,xi,sigma,t->fit->GetChisquare()/t->fit->GetNDF(),c,ec,p,ep);
  }
  /** 
   * Called after end of loop 
   * 
   * @param mode  Mode of operation 
   * @param can   Canvas 
   * @param nt    NTuple 
   * @param out   Output file 
   */
  void PostLoop(UShort_t mode, TCanvas* can, TNtuple* /*nt*/, TFile* out) 
  { 
    can->Clear();
    if (mode == 0) { 
      can->Divide(2,2);
      can->cd(1); c2s->Draw("TRI2Z");
      can->cd(2); p2s->Draw("TRI2Z");
      can->cd(3); mcs->Draw("APL");
      can->cd(4); mps->Draw("APL");
      c2s->GetHistogram()->SetXTitle("#xi");
      p2s->GetHistogram()->SetXTitle("#xi");
      c2s->GetHistogram()->SetYTitle("#sigma");
      p2s->GetHistogram()->SetYTitle("#sigma");
      c2s->GetHistogram()->SetZTitle("c");
      p2s->GetHistogram()->SetZTitle("p");
      mcs->GetHistogram()->SetXTitle("#sigma/#xi");
      mps->GetHistogram()->SetXTitle("#sigma/#xi");
      mcs->GetHistogram()->SetYTitle("c");
      mps->GetHistogram()->SetYTitle("p");

      out->cd();
      c2s->Write();
      p2s->Write();
      can->Write();
      mcs->Write();
      mps->Write();
    } 
    else { 
      can->Divide(2,1);
      can->cd(1); cs->Draw("APL");
      can->cd(2); ps->Draw("APL");

      out->cd();
      can->Write();
      cs->Write();
      ps->Write();
    }
    PrintCanvas(can, 0, 0);
  }
};
#endif

//====================================================================
#ifdef TEST_FITTER
#include "AliLandauGausFitter.h"
#include <TRandom.h>

struct TestFit : public TestF
{
  struct Test : public TestF::Test 
  {
    TH1* dist;
    TF1* res;
    TH1* pars;
    Bool_t fDoShift;
    Test() : TestF::Test(), dist(0), res(0), pars(0), fDoShift(true) {}
    /** 
     * Re-implementation of TH1::FillRandom to accept a TF1 pointer 
     * 
     * @param h Histogram to fill 
     * @param f Function to use 
     * @param n Number of samples
     */
    static void FillRandom(TH1* h, TF1* f, Int_t n=1000000) { 
      TAxis* xAxis = h->GetXaxis();

      Int_t first  = xAxis->GetFirst();
      Int_t last   = xAxis->GetLast();
      Int_t nbinsx = last-first+1;

      TArrayD integral(nbinsx+1);
      integral[0] = 0;
      for (Int_t i = 1; i <= nbinsx; i++) {
	Double_t fint = f->Integral(xAxis->GetBinLowEdge(i+first-1),
				    xAxis->GetBinUpEdge(i+first-1));
	integral[i] = integral[i-1] + fint;
      }

      //   - Normalize integral to 1
      if (integral[nbinsx] == 0) {
	Error("FillRandom", "Integral = zero"); 
	return;
      }
      for (Int_t i = 1 ; i <= nbinsx; i++)  
	integral[i] /= integral[nbinsx];

      //   --------------Start main loop ntimes
      for (Int_t i = 0; i < n; i++) {
	Double_t r1 = gRandom->Rndm(i);
	Int_t    j  = TMath::BinarySearch(nbinsx,&integral[0],r1);
	Double_t x  = (xAxis->GetBinLowEdge(j+first) +
		       xAxis->GetBinWidth(j+first) * 
		       (r1-integral[j])/(integral[j+1] - integral[j]));
	h->Fill(x);
      }
    }
    /** 
     * Run the actual test
     */
    void DoRun() 
    {
      AliLandauGaus::EnableSigmaShift(1); // Enable sigma-shift
      Double_t xMin = XMin();
      Double_t xMax = XMax();
      Int_t    n    = N();
      src->SetLineColor(kBlue);
      src->SetLineStyle(2);
      dist = new TH1D("dist", "Landau-Gaus distribution",500,xMin,xMax);
      dist->SetXTitle("#Delta");
      dist->SetYTitle("dN/d#Delta");
      dist->SetFillStyle(3001);
      dist->SetFillColor(kMagenta+1);
      dist->Sumw2();
      dist->SetDirectory(0);
      FillRandom(dist, src);
      
      Int_t    peakBin = dist->GetMaximumBin();
      Double_t max     = dist->GetBinContent(peakBin);
      dist->Scale(1/max);

      AliLandauGaus::EnableSigmaShift(fDoShift); // Disable sigma-shift
      AliLandauGausFitter f(xMin, xMax, 10);
      // f.SetDebug(true);
      
      TF1* r = f.FitNParticle(dist, n);
      if (!r) return;
      r->SetName("fit");

      // Get the status for the covariance calculation: 
      // 0: Not calculatuted 
      // 1: Approximate 
      // 2: Forced positive definite 
      // 3: Accurate 
      Int_t covStatus = 
	static_cast<TFitResult*>(f.GetFitResults().At(n-1))->CovMatrixStatus();
      if (covStatus < 2) ::Warning("", "Fit may not be good");
      
      r->SetRange(xMin, xMax);
      res = static_cast<TF1*>(r->Clone());
      res->SetLineColor(kPink+10);
      res->SetLineStyle(1);
      res->SetLineWidth(3);
      dist->GetListOfFunctions()->Add(res);
      
      Double_t min     = 0.1*dist->GetMinimum();
      TF1*     old     = src; // Tuck away src
      src              = res; // Use fit now
      for (Int_t i = 1; i <= n; i++) { 
	Double_t rDelta  = Delta();
	Double_t rxi     = Xi();
	Double_t rsigma  = Sigma();
	TF1*     comp    = Fi(i);
	comp->SetLineWidth(2);
	comp->SetLineStyle(1);

	// Modifies arguments!
	AliLandauGaus::IPars(i, rDelta, rxi, rsigma);
	TLine* l = VerticalLine(1, comp->GetLineColor(), rDelta, min,
				1.1*old->Eval(rDelta));
	dist->GetListOfFunctions()->Add(comp);
	dist->GetListOfFunctions()->Add(l);
      }
      src = old; // restore 
      
    }
    /** 
     * Draw results in pad 
     * 
     * @param p Pad 
     */
    void DrawInPad(TVirtualPad* p)
    {
      // Double_t scale = src->GetMaximum();
      // src->SetParameter(0, 1/scale);
      p->Clear();
      p->SetTopMargin(0.0);
      p->SetRightMargin(0.0);
      p->SetBottomMargin(0.0);
      p->SetLeftMargin(0.0);
      p->SetFillColor(kGray);
      p->Divide(2,1,0.001,0.001);
      TVirtualPad* q = p->cd(1);
      q->SetLogy();
      q->SetTopMargin(0.01);
      q->SetRightMargin(0.02);
      q->SetFillColor(kWhite);
      gStyle->SetOptStat(0);
      gStyle->SetOptFit(11111);
      gStyle->SetOptTitle(false);
      gStyle->SetStatY(1-q->GetTopMargin());

      dist->DrawCopy("hist");
      dist->DrawCopy("e same");
      AliLandauGaus::EnableSigmaShift(1); // Enable sigma-shift
      src->DrawClone("same");
      AliLandauGaus::EnableSigmaShift(fDoShift); // Disable sigma-shift
      if (!res) return;


      q = p->cd(2);
      q->SetTopMargin(0.01);
      q->SetRightMargin(0.02);
      q->SetFillColor(kWhite);
      Int_t nPar = src->GetNpar();
      pars = new TH1D("pars", "#chi^{2}/#nu & #Deltap_{i}/#deltap_{i}", 
		      nPar+1, 0, nPar+1);
      pars->SetDirectory(0);
      pars->SetFillColor(kCyan+2);
      pars->SetFillStyle(3001);
      pars->SetYTitle("#Deltap_{i}/#deltap_{i}");

      TPaveStats* stats = new TPaveStats(0,0,0,0);
      stats->SetX1NDC(gStyle->GetStatX()-gStyle->GetStatW());      
      stats->SetY1NDC(gStyle->GetStatY()-gStyle->GetStatH());
      stats->SetX2NDC(gStyle->GetStatX());
      stats->SetY2NDC(gStyle->GetStatY());
      stats->SetTextFont(42);
      
      stats->SetBorderSize(1);
      stats->SetFillColor(kWhite);
      stats->AddText("");
      pars->GetListOfFunctions()->Add(stats);
      TString fmt(Form("%%s = %%%s", stats->GetFitFormat()));
      for (Int_t i = 0; i < nPar; i++) { 
	Double_t low, high;
	res->GetParLimits(i, low, high);
	Double_t pSrc = src->GetParameter(i);
	Double_t pRes = res->GetParameter(i);
	Double_t eRes = res->GetParError(i);
	Bool_t   fix  = (low == high && ((pRes == 0 && low == 1) || low==pRes));
	Double_t diff = fix ? 0 : TMath::Abs(pSrc-pRes)/eRes;
	pars->GetXaxis()->SetBinLabel(i+1,res->GetParName(i));
	pars->SetBinContent(i+1, diff);
	stats->AddText(Form(fmt.Data(), res->GetParName(i), pSrc));
      }
      pars->GetXaxis()->SetBinLabel(nPar+1,"#chi^{2}/#nu");
      pars->SetBinContent(nPar+1,res->GetChisquare() / res->GetNDF());
      pars->DrawCopy();
      q->Modified();
      q->Update();

      p->Modified();
      p->Update();
      p->cd();
      
      PrintFs(false);
    }
    /** 
     * Print results 
     * 
     * @param full 
     */
    void PrintFs(Bool_t full=false) {
      if (full) {
	Int_t nPar = src->GetNpar();
	Printf("%-2s %-10s | %-8s | %8s %-9s | %9.5s", 
	       "#", "Name", "Source", "Fit", "Error", "delta");
	for (Int_t i = 0; i < nPar; i++) { 
	  Double_t low, high;
	  res->GetParLimits(i, low, high);
	  Double_t pSrc = src->GetParameter(i);
	  Double_t pRes = res->GetParameter(i);
	  Double_t eRes = res->GetParError(i);
	  Bool_t   fix  = (low == high && ((pRes == 0 && low==1) || low==pRes));
	  Double_t diff = fix ? 0 : TMath::Abs(pSrc-pRes)/eRes;
	  Printf("%2d %10s | %8.4f | %8.4f %9.5f | %9.5f %s", 
		 i, src->GetParName(i), pSrc, pRes, eRes, diff, 
		 (fix ? "fixed" : (diff < 2 ? "ok" : "bad")));
	}
	Printf("chi^2/nu = %8.4f/%-3d = %9.5f", 
	       res->GetChisquare(), res->GetNDF(), 
	       res->GetChisquare() / res->GetNDF());
      }
      else 
	Printf("%8.4f", res->GetChisquare() / res->GetNDF());
    }
    /** 
     * Write results to disk 
     * 
     * @param d Directory to write to 
     */
    virtual void WriteOut(TDirectory* d) 
    {
      d->cd();
      src->Write();
      dist->Write();
      if (res) res->Write();
      if (pars) pars->Write();
    }
    
  };
  //__________________________________________________________________
  TestF::Test* MakeTest() { return new Test(); } 
  const char* Prefix() const { return "fit"; }
  void PreLoop(UShort_t,Int_t) {
    Printf("%-8s | %-8s | %-8s | %-8s ",  "Delta_p", "xi", "sigma", "chi^2/nu");
  }
  void Step(UShort_t,Int_t,Int_t,Int_t,TestF::Test*,TNtuple*) {}
  void PostLoop(UShort_t,TCanvas* c,TNtuple*,TFile*) { PrintCanvas(c,0,0); }
};
#endif
// 
// EOF
//

  
 TestF.C:1
 TestF.C:2
 TestF.C:3
 TestF.C:4
 TestF.C:5
 TestF.C:6
 TestF.C:7
 TestF.C:8
 TestF.C:9
 TestF.C:10
 TestF.C:11
 TestF.C:12
 TestF.C:13
 TestF.C:14
 TestF.C:15
 TestF.C:16
 TestF.C:17
 TestF.C:18
 TestF.C:19
 TestF.C:20
 TestF.C:21
 TestF.C:22
 TestF.C:23
 TestF.C:24
 TestF.C:25
 TestF.C:26
 TestF.C:27
 TestF.C:28
 TestF.C:29
 TestF.C:30
 TestF.C:31
 TestF.C:32
 TestF.C:33
 TestF.C:34
 TestF.C:35
 TestF.C:36
 TestF.C:37
 TestF.C:38
 TestF.C:39
 TestF.C:40
 TestF.C:41
 TestF.C:42
 TestF.C:43
 TestF.C:44
 TestF.C:45
 TestF.C:46
 TestF.C:47
 TestF.C:48
 TestF.C:49
 TestF.C:50
 TestF.C:51
 TestF.C:52
 TestF.C:53
 TestF.C:54
 TestF.C:55
 TestF.C:56
 TestF.C:57
 TestF.C:58
 TestF.C:59
 TestF.C:60
 TestF.C:61
 TestF.C:62
 TestF.C:63
 TestF.C:64
 TestF.C:65
 TestF.C:66
 TestF.C:67
 TestF.C:68
 TestF.C:69
 TestF.C:70
 TestF.C:71
 TestF.C:72
 TestF.C:73
 TestF.C:74
 TestF.C:75
 TestF.C:76
 TestF.C:77
 TestF.C:78
 TestF.C:79
 TestF.C:80
 TestF.C:81
 TestF.C:82
 TestF.C:83
 TestF.C:84
 TestF.C:85
 TestF.C:86
 TestF.C:87
 TestF.C:88
 TestF.C:89
 TestF.C:90
 TestF.C:91
 TestF.C:92
 TestF.C:93
 TestF.C:94
 TestF.C:95
 TestF.C:96
 TestF.C:97
 TestF.C:98
 TestF.C:99
 TestF.C:100
 TestF.C:101
 TestF.C:102
 TestF.C:103
 TestF.C:104
 TestF.C:105
 TestF.C:106
 TestF.C:107
 TestF.C:108
 TestF.C:109
 TestF.C:110
 TestF.C:111
 TestF.C:112
 TestF.C:113
 TestF.C:114
 TestF.C:115
 TestF.C:116
 TestF.C:117
 TestF.C:118
 TestF.C:119
 TestF.C:120
 TestF.C:121
 TestF.C:122
 TestF.C:123
 TestF.C:124
 TestF.C:125
 TestF.C:126
 TestF.C:127
 TestF.C:128
 TestF.C:129
 TestF.C:130
 TestF.C:131
 TestF.C:132
 TestF.C:133
 TestF.C:134
 TestF.C:135
 TestF.C:136
 TestF.C:137
 TestF.C:138
 TestF.C:139
 TestF.C:140
 TestF.C:141
 TestF.C:142
 TestF.C:143
 TestF.C:144
 TestF.C:145
 TestF.C:146
 TestF.C:147
 TestF.C:148
 TestF.C:149
 TestF.C:150
 TestF.C:151
 TestF.C:152
 TestF.C:153
 TestF.C:154
 TestF.C:155
 TestF.C:156
 TestF.C:157
 TestF.C:158
 TestF.C:159
 TestF.C:160
 TestF.C:161
 TestF.C:162
 TestF.C:163
 TestF.C:164
 TestF.C:165
 TestF.C:166
 TestF.C:167
 TestF.C:168
 TestF.C:169
 TestF.C:170
 TestF.C:171
 TestF.C:172
 TestF.C:173
 TestF.C:174
 TestF.C:175
 TestF.C:176
 TestF.C:177
 TestF.C:178
 TestF.C:179
 TestF.C:180
 TestF.C:181
 TestF.C:182
 TestF.C:183
 TestF.C:184
 TestF.C:185
 TestF.C:186
 TestF.C:187
 TestF.C:188
 TestF.C:189
 TestF.C:190
 TestF.C:191
 TestF.C:192
 TestF.C:193
 TestF.C:194
 TestF.C:195
 TestF.C:196
 TestF.C:197
 TestF.C:198
 TestF.C:199
 TestF.C:200
 TestF.C:201
 TestF.C:202
 TestF.C:203
 TestF.C:204
 TestF.C:205
 TestF.C:206
 TestF.C:207
 TestF.C:208
 TestF.C:209
 TestF.C:210
 TestF.C:211
 TestF.C:212
 TestF.C:213
 TestF.C:214
 TestF.C:215
 TestF.C:216
 TestF.C:217
 TestF.C:218
 TestF.C:219
 TestF.C:220
 TestF.C:221
 TestF.C:222
 TestF.C:223
 TestF.C:224
 TestF.C:225
 TestF.C:226
 TestF.C:227
 TestF.C:228
 TestF.C:229
 TestF.C:230
 TestF.C:231
 TestF.C:232
 TestF.C:233
 TestF.C:234
 TestF.C:235
 TestF.C:236
 TestF.C:237
 TestF.C:238
 TestF.C:239
 TestF.C:240
 TestF.C:241
 TestF.C:242
 TestF.C:243
 TestF.C:244
 TestF.C:245
 TestF.C:246
 TestF.C:247
 TestF.C:248
 TestF.C:249
 TestF.C:250
 TestF.C:251
 TestF.C:252
 TestF.C:253
 TestF.C:254
 TestF.C:255
 TestF.C:256
 TestF.C:257
 TestF.C:258
 TestF.C:259
 TestF.C:260
 TestF.C:261
 TestF.C:262
 TestF.C:263
 TestF.C:264
 TestF.C:265
 TestF.C:266
 TestF.C:267
 TestF.C:268
 TestF.C:269
 TestF.C:270
 TestF.C:271
 TestF.C:272
 TestF.C:273
 TestF.C:274
 TestF.C:275
 TestF.C:276
 TestF.C:277
 TestF.C:278
 TestF.C:279
 TestF.C:280
 TestF.C:281
 TestF.C:282
 TestF.C:283
 TestF.C:284
 TestF.C:285
 TestF.C:286
 TestF.C:287
 TestF.C:288
 TestF.C:289
 TestF.C:290
 TestF.C:291
 TestF.C:292
 TestF.C:293
 TestF.C:294
 TestF.C:295
 TestF.C:296
 TestF.C:297
 TestF.C:298
 TestF.C:299
 TestF.C:300
 TestF.C:301
 TestF.C:302
 TestF.C:303
 TestF.C:304
 TestF.C:305
 TestF.C:306
 TestF.C:307
 TestF.C:308
 TestF.C:309
 TestF.C:310
 TestF.C:311
 TestF.C:312
 TestF.C:313
 TestF.C:314
 TestF.C:315
 TestF.C:316
 TestF.C:317
 TestF.C:318
 TestF.C:319
 TestF.C:320
 TestF.C:321
 TestF.C:322
 TestF.C:323
 TestF.C:324
 TestF.C:325
 TestF.C:326
 TestF.C:327
 TestF.C:328
 TestF.C:329
 TestF.C:330
 TestF.C:331
 TestF.C:332
 TestF.C:333
 TestF.C:334
 TestF.C:335
 TestF.C:336
 TestF.C:337
 TestF.C:338
 TestF.C:339
 TestF.C:340
 TestF.C:341
 TestF.C:342
 TestF.C:343
 TestF.C:344
 TestF.C:345
 TestF.C:346
 TestF.C:347
 TestF.C:348
 TestF.C:349
 TestF.C:350
 TestF.C:351
 TestF.C:352
 TestF.C:353
 TestF.C:354
 TestF.C:355
 TestF.C:356
 TestF.C:357
 TestF.C:358
 TestF.C:359
 TestF.C:360
 TestF.C:361
 TestF.C:362
 TestF.C:363
 TestF.C:364
 TestF.C:365
 TestF.C:366
 TestF.C:367
 TestF.C:368
 TestF.C:369
 TestF.C:370
 TestF.C:371
 TestF.C:372
 TestF.C:373
 TestF.C:374
 TestF.C:375
 TestF.C:376
 TestF.C:377
 TestF.C:378
 TestF.C:379
 TestF.C:380
 TestF.C:381
 TestF.C:382
 TestF.C:383
 TestF.C:384
 TestF.C:385
 TestF.C:386
 TestF.C:387
 TestF.C:388
 TestF.C:389
 TestF.C:390
 TestF.C:391
 TestF.C:392
 TestF.C:393
 TestF.C:394
 TestF.C:395
 TestF.C:396
 TestF.C:397
 TestF.C:398
 TestF.C:399
 TestF.C:400
 TestF.C:401
 TestF.C:402
 TestF.C:403
 TestF.C:404
 TestF.C:405
 TestF.C:406
 TestF.C:407
 TestF.C:408
 TestF.C:409
 TestF.C:410
 TestF.C:411
 TestF.C:412
 TestF.C:413
 TestF.C:414
 TestF.C:415
 TestF.C:416
 TestF.C:417
 TestF.C:418
 TestF.C:419
 TestF.C:420
 TestF.C:421
 TestF.C:422
 TestF.C:423
 TestF.C:424
 TestF.C:425
 TestF.C:426
 TestF.C:427
 TestF.C:428
 TestF.C:429
 TestF.C:430
 TestF.C:431
 TestF.C:432
 TestF.C:433
 TestF.C:434
 TestF.C:435
 TestF.C:436
 TestF.C:437
 TestF.C:438
 TestF.C:439
 TestF.C:440
 TestF.C:441
 TestF.C:442
 TestF.C:443
 TestF.C:444
 TestF.C:445
 TestF.C:446
 TestF.C:447
 TestF.C:448
 TestF.C:449
 TestF.C:450
 TestF.C:451
 TestF.C:452
 TestF.C:453
 TestF.C:454
 TestF.C:455
 TestF.C:456
 TestF.C:457
 TestF.C:458
 TestF.C:459
 TestF.C:460
 TestF.C:461
 TestF.C:462
 TestF.C:463
 TestF.C:464
 TestF.C:465
 TestF.C:466
 TestF.C:467
 TestF.C:468
 TestF.C:469
 TestF.C:470
 TestF.C:471
 TestF.C:472
 TestF.C:473
 TestF.C:474
 TestF.C:475
 TestF.C:476
 TestF.C:477
 TestF.C:478
 TestF.C:479
 TestF.C:480
 TestF.C:481
 TestF.C:482
 TestF.C:483
 TestF.C:484
 TestF.C:485
 TestF.C:486
 TestF.C:487
 TestF.C:488
 TestF.C:489
 TestF.C:490
 TestF.C:491
 TestF.C:492
 TestF.C:493
 TestF.C:494
 TestF.C:495
 TestF.C:496
 TestF.C:497
 TestF.C:498
 TestF.C:499
 TestF.C:500
 TestF.C:501
 TestF.C:502
 TestF.C:503
 TestF.C:504
 TestF.C:505
 TestF.C:506
 TestF.C:507
 TestF.C:508
 TestF.C:509
 TestF.C:510
 TestF.C:511
 TestF.C:512
 TestF.C:513
 TestF.C:514
 TestF.C:515
 TestF.C:516
 TestF.C:517
 TestF.C:518
 TestF.C:519
 TestF.C:520
 TestF.C:521
 TestF.C:522
 TestF.C:523
 TestF.C:524
 TestF.C:525
 TestF.C:526
 TestF.C:527
 TestF.C:528
 TestF.C:529
 TestF.C:530
 TestF.C:531
 TestF.C:532
 TestF.C:533
 TestF.C:534
 TestF.C:535
 TestF.C:536
 TestF.C:537
 TestF.C:538
 TestF.C:539
 TestF.C:540
 TestF.C:541
 TestF.C:542
 TestF.C:543
 TestF.C:544
 TestF.C:545
 TestF.C:546
 TestF.C:547
 TestF.C:548
 TestF.C:549
 TestF.C:550
 TestF.C:551
 TestF.C:552
 TestF.C:553
 TestF.C:554
 TestF.C:555
 TestF.C:556
 TestF.C:557
 TestF.C:558
 TestF.C:559
 TestF.C:560
 TestF.C:561
 TestF.C:562
 TestF.C:563
 TestF.C:564
 TestF.C:565
 TestF.C:566
 TestF.C:567
 TestF.C:568
 TestF.C:569
 TestF.C:570
 TestF.C:571
 TestF.C:572
 TestF.C:573
 TestF.C:574
 TestF.C:575
 TestF.C:576
 TestF.C:577
 TestF.C:578
 TestF.C:579
 TestF.C:580
 TestF.C:581
 TestF.C:582
 TestF.C:583
 TestF.C:584
 TestF.C:585
 TestF.C:586
 TestF.C:587
 TestF.C:588
 TestF.C:589
 TestF.C:590
 TestF.C:591
 TestF.C:592
 TestF.C:593
 TestF.C:594
 TestF.C:595
 TestF.C:596
 TestF.C:597
 TestF.C:598
 TestF.C:599
 TestF.C:600
 TestF.C:601
 TestF.C:602
 TestF.C:603
 TestF.C:604
 TestF.C:605
 TestF.C:606
 TestF.C:607
 TestF.C:608
 TestF.C:609
 TestF.C:610
 TestF.C:611
 TestF.C:612
 TestF.C:613
 TestF.C:614
 TestF.C:615
 TestF.C:616
 TestF.C:617
 TestF.C:618
 TestF.C:619
 TestF.C:620
 TestF.C:621
 TestF.C:622
 TestF.C:623
 TestF.C:624
 TestF.C:625
 TestF.C:626
 TestF.C:627
 TestF.C:628
 TestF.C:629
 TestF.C:630
 TestF.C:631
 TestF.C:632
 TestF.C:633
 TestF.C:634
 TestF.C:635
 TestF.C:636
 TestF.C:637
 TestF.C:638
 TestF.C:639
 TestF.C:640
 TestF.C:641
 TestF.C:642
 TestF.C:643
 TestF.C:644
 TestF.C:645
 TestF.C:646
 TestF.C:647
 TestF.C:648
 TestF.C:649
 TestF.C:650
 TestF.C:651
 TestF.C:652
 TestF.C:653
 TestF.C:654
 TestF.C:655
 TestF.C:656
 TestF.C:657
 TestF.C:658
 TestF.C:659
 TestF.C:660
 TestF.C:661
 TestF.C:662
 TestF.C:663
 TestF.C:664
 TestF.C:665
 TestF.C:666
 TestF.C:667
 TestF.C:668
 TestF.C:669
 TestF.C:670
 TestF.C:671
 TestF.C:672
 TestF.C:673
 TestF.C:674
 TestF.C:675
 TestF.C:676
 TestF.C:677
 TestF.C:678
 TestF.C:679
 TestF.C:680
 TestF.C:681
 TestF.C:682
 TestF.C:683
 TestF.C:684
 TestF.C:685
 TestF.C:686
 TestF.C:687
 TestF.C:688
 TestF.C:689
 TestF.C:690
 TestF.C:691
 TestF.C:692
 TestF.C:693
 TestF.C:694
 TestF.C:695
 TestF.C:696
 TestF.C:697
 TestF.C:698
 TestF.C:699
 TestF.C:700
 TestF.C:701
 TestF.C:702
 TestF.C:703
 TestF.C:704
 TestF.C:705
 TestF.C:706
 TestF.C:707
 TestF.C:708
 TestF.C:709
 TestF.C:710
 TestF.C:711
 TestF.C:712
 TestF.C:713
 TestF.C:714
 TestF.C:715
 TestF.C:716
 TestF.C:717
 TestF.C:718
 TestF.C:719
 TestF.C:720
 TestF.C:721
 TestF.C:722
 TestF.C:723
 TestF.C:724
 TestF.C:725
 TestF.C:726
 TestF.C:727
 TestF.C:728
 TestF.C:729
 TestF.C:730
 TestF.C:731
 TestF.C:732
 TestF.C:733
 TestF.C:734
 TestF.C:735
 TestF.C:736
 TestF.C:737
 TestF.C:738
 TestF.C:739
 TestF.C:740
 TestF.C:741
 TestF.C:742
 TestF.C:743
 TestF.C:744
 TestF.C:745
 TestF.C:746
 TestF.C:747
 TestF.C:748
 TestF.C:749
 TestF.C:750
 TestF.C:751
 TestF.C:752
 TestF.C:753
 TestF.C:754
 TestF.C:755
 TestF.C:756
 TestF.C:757
 TestF.C:758
 TestF.C:759
 TestF.C:760
 TestF.C:761
 TestF.C:762
 TestF.C:763
 TestF.C:764
 TestF.C:765
 TestF.C:766
 TestF.C:767
 TestF.C:768
 TestF.C:769
 TestF.C:770
 TestF.C:771
 TestF.C:772
 TestF.C:773
 TestF.C:774
 TestF.C:775
 TestF.C:776
 TestF.C:777
 TestF.C:778
 TestF.C:779
 TestF.C:780
 TestF.C:781
 TestF.C:782
 TestF.C:783
 TestF.C:784
 TestF.C:785
 TestF.C:786
 TestF.C:787
 TestF.C:788
 TestF.C:789
 TestF.C:790
 TestF.C:791
 TestF.C:792
 TestF.C:793
 TestF.C:794
 TestF.C:795
 TestF.C:796
 TestF.C:797
 TestF.C:798
 TestF.C:799
 TestF.C:800
 TestF.C:801
 TestF.C:802
 TestF.C:803
 TestF.C:804
 TestF.C:805
 TestF.C:806
 TestF.C:807
 TestF.C:808
 TestF.C:809
 TestF.C:810
 TestF.C:811
 TestF.C:812
 TestF.C:813
 TestF.C:814
 TestF.C:815
 TestF.C:816
 TestF.C:817
 TestF.C:818
 TestF.C:819
 TestF.C:820
 TestF.C:821
 TestF.C:822
 TestF.C:823
 TestF.C:824
 TestF.C:825
 TestF.C:826
 TestF.C:827
 TestF.C:828
 TestF.C:829
 TestF.C:830
 TestF.C:831
 TestF.C:832
 TestF.C:833
 TestF.C:834
 TestF.C:835
 TestF.C:836
 TestF.C:837
 TestF.C:838
 TestF.C:839
 TestF.C:840
 TestF.C:841
 TestF.C:842
 TestF.C:843
 TestF.C:844
 TestF.C:845
 TestF.C:846
 TestF.C:847
 TestF.C:848
 TestF.C:849
 TestF.C:850
 TestF.C:851
 TestF.C:852
 TestF.C:853
 TestF.C:854
 TestF.C:855
 TestF.C:856
 TestF.C:857
 TestF.C:858
 TestF.C:859
 TestF.C:860
 TestF.C:861
 TestF.C:862
 TestF.C:863
 TestF.C:864
 TestF.C:865
 TestF.C:866
 TestF.C:867
 TestF.C:868
 TestF.C:869
 TestF.C:870
 TestF.C:871
 TestF.C:872
 TestF.C:873
 TestF.C:874
 TestF.C:875
 TestF.C:876
 TestF.C:877
 TestF.C:878
 TestF.C:879
 TestF.C:880
 TestF.C:881
 TestF.C:882
 TestF.C:883
 TestF.C:884
 TestF.C:885
 TestF.C:886
 TestF.C:887
 TestF.C:888
 TestF.C:889
 TestF.C:890
 TestF.C:891
 TestF.C:892
 TestF.C:893
 TestF.C:894
 TestF.C:895
 TestF.C:896
 TestF.C:897
 TestF.C:898
 TestF.C:899
 TestF.C:900
 TestF.C:901
 TestF.C:902
 TestF.C:903
 TestF.C:904
 TestF.C:905
 TestF.C:906
 TestF.C:907
 TestF.C:908
 TestF.C:909
 TestF.C:910
 TestF.C:911
 TestF.C:912
 TestF.C:913
 TestF.C:914
 TestF.C:915
 TestF.C:916
 TestF.C:917
 TestF.C:918
 TestF.C:919
 TestF.C:920
 TestF.C:921
 TestF.C:922
 TestF.C:923
 TestF.C:924
 TestF.C:925
 TestF.C:926
 TestF.C:927
 TestF.C:928
 TestF.C:929
 TestF.C:930
 TestF.C:931
 TestF.C:932
 TestF.C:933
 TestF.C:934
 TestF.C:935
 TestF.C:936
 TestF.C:937
 TestF.C:938
 TestF.C:939
 TestF.C:940
 TestF.C:941
 TestF.C:942
 TestF.C:943
 TestF.C:944
 TestF.C:945
 TestF.C:946
 TestF.C:947
 TestF.C:948
 TestF.C:949
 TestF.C:950
 TestF.C:951
 TestF.C:952
 TestF.C:953
 TestF.C:954
 TestF.C:955
 TestF.C:956
 TestF.C:957
 TestF.C:958
 TestF.C:959
 TestF.C:960
 TestF.C:961
 TestF.C:962
 TestF.C:963
 TestF.C:964
 TestF.C:965
 TestF.C:966
 TestF.C:967
 TestF.C:968
 TestF.C:969
 TestF.C:970
 TestF.C:971
 TestF.C:972
 TestF.C:973
 TestF.C:974
 TestF.C:975
 TestF.C:976
 TestF.C:977
 TestF.C:978
 TestF.C:979
 TestF.C:980
 TestF.C:981
 TestF.C:982
 TestF.C:983
 TestF.C:984
 TestF.C:985
 TestF.C:986
 TestF.C:987
 TestF.C:988
 TestF.C:989
 TestF.C:990
 TestF.C:991
 TestF.C:992
 TestF.C:993
 TestF.C:994
 TestF.C:995
 TestF.C:996
 TestF.C:997
 TestF.C:998
 TestF.C:999
 TestF.C:1000
 TestF.C:1001
 TestF.C:1002
 TestF.C:1003
 TestF.C:1004
 TestF.C:1005
 TestF.C:1006
 TestF.C:1007
 TestF.C:1008
 TestF.C:1009
 TestF.C:1010
 TestF.C:1011
 TestF.C:1012
 TestF.C:1013
 TestF.C:1014
 TestF.C:1015
 TestF.C:1016
 TestF.C:1017
 TestF.C:1018
 TestF.C:1019
 TestF.C:1020
 TestF.C:1021
 TestF.C:1022
 TestF.C:1023
 TestF.C:1024
 TestF.C:1025
 TestF.C:1026
 TestF.C:1027
 TestF.C:1028
 TestF.C:1029
 TestF.C:1030
 TestF.C:1031
 TestF.C:1032
 TestF.C:1033
 TestF.C:1034
 TestF.C:1035
 TestF.C:1036
 TestF.C:1037
 TestF.C:1038
 TestF.C:1039
 TestF.C:1040
 TestF.C:1041
 TestF.C:1042
 TestF.C:1043
 TestF.C:1044
 TestF.C:1045
 TestF.C:1046
 TestF.C:1047
 TestF.C:1048
 TestF.C:1049
 TestF.C:1050
 TestF.C:1051
 TestF.C:1052
 TestF.C:1053
 TestF.C:1054
 TestF.C:1055
 TestF.C:1056
 TestF.C:1057
 TestF.C:1058
 TestF.C:1059
 TestF.C:1060
 TestF.C:1061
 TestF.C:1062
 TestF.C:1063
 TestF.C:1064
 TestF.C:1065
 TestF.C:1066
 TestF.C:1067
 TestF.C:1068
 TestF.C:1069
 TestF.C:1070
 TestF.C:1071
 TestF.C:1072
 TestF.C:1073
 TestF.C:1074
 TestF.C:1075
 TestF.C:1076
 TestF.C:1077
 TestF.C:1078
 TestF.C:1079
 TestF.C:1080
 TestF.C:1081
 TestF.C:1082
 TestF.C:1083
 TestF.C:1084
 TestF.C:1085
 TestF.C:1086
 TestF.C:1087
 TestF.C:1088
 TestF.C:1089
 TestF.C:1090
 TestF.C:1091
 TestF.C:1092
 TestF.C:1093
 TestF.C:1094
 TestF.C:1095
 TestF.C:1096
 TestF.C:1097
 TestF.C:1098
 TestF.C:1099
 TestF.C:1100
 TestF.C:1101
 TestF.C:1102
 TestF.C:1103
 TestF.C:1104
 TestF.C:1105
 TestF.C:1106
 TestF.C:1107
 TestF.C:1108
 TestF.C:1109
 TestF.C:1110
 TestF.C:1111
 TestF.C:1112
 TestF.C:1113
 TestF.C:1114
 TestF.C:1115
 TestF.C:1116
 TestF.C:1117
 TestF.C:1118
 TestF.C:1119
 TestF.C:1120
 TestF.C:1121
 TestF.C:1122
 TestF.C:1123
 TestF.C:1124
 TestF.C:1125
 TestF.C:1126
 TestF.C:1127
 TestF.C:1128
 TestF.C:1129
 TestF.C:1130
 TestF.C:1131
 TestF.C:1132
 TestF.C:1133
 TestF.C:1134
 TestF.C:1135
 TestF.C:1136
 TestF.C:1137
 TestF.C:1138
 TestF.C:1139
 TestF.C:1140
 TestF.C:1141
 TestF.C:1142
 TestF.C:1143
 TestF.C:1144
 TestF.C:1145
 TestF.C:1146
 TestF.C:1147
 TestF.C:1148
 TestF.C:1149
 TestF.C:1150
 TestF.C:1151
 TestF.C:1152
 TestF.C:1153
 TestF.C:1154
 TestF.C:1155
 TestF.C:1156
 TestF.C:1157
 TestF.C:1158
 TestF.C:1159
 TestF.C:1160
 TestF.C:1161
 TestF.C:1162
 TestF.C:1163
 TestF.C:1164
 TestF.C:1165
 TestF.C:1166
 TestF.C:1167
 TestF.C:1168
 TestF.C:1169
 TestF.C:1170
 TestF.C:1171
 TestF.C:1172
 TestF.C:1173
 TestF.C:1174
 TestF.C:1175
 TestF.C:1176
 TestF.C:1177
 TestF.C:1178
 TestF.C:1179
 TestF.C:1180
 TestF.C:1181
 TestF.C:1182
 TestF.C:1183
 TestF.C:1184
 TestF.C:1185
 TestF.C:1186
 TestF.C:1187
 TestF.C:1188
 TestF.C:1189
 TestF.C:1190
 TestF.C:1191
 TestF.C:1192
 TestF.C:1193
 TestF.C:1194
 TestF.C:1195
 TestF.C:1196
 TestF.C:1197
 TestF.C:1198
 TestF.C:1199
 TestF.C:1200
 TestF.C:1201
 TestF.C:1202
 TestF.C:1203
 TestF.C:1204
 TestF.C:1205
 TestF.C:1206
 TestF.C:1207
 TestF.C:1208
 TestF.C:1209
 TestF.C:1210
 TestF.C:1211
 TestF.C:1212
 TestF.C:1213
 TestF.C:1214
 TestF.C:1215
 TestF.C:1216
 TestF.C:1217
 TestF.C:1218
 TestF.C:1219
 TestF.C:1220
 TestF.C:1221
 TestF.C:1222
 TestF.C:1223
 TestF.C:1224
 TestF.C:1225
 TestF.C:1226
 TestF.C:1227
 TestF.C:1228
 TestF.C:1229
 TestF.C:1230
 TestF.C:1231
 TestF.C:1232
 TestF.C:1233
 TestF.C:1234
 TestF.C:1235
 TestF.C:1236
 TestF.C:1237
 TestF.C:1238
 TestF.C:1239
 TestF.C:1240
 TestF.C:1241
 TestF.C:1242
 TestF.C:1243
 TestF.C:1244
 TestF.C:1245
 TestF.C:1246
 TestF.C:1247
 TestF.C:1248
 TestF.C:1249
 TestF.C:1250
 TestF.C:1251
 TestF.C:1252
 TestF.C:1253
 TestF.C:1254
 TestF.C:1255
 TestF.C:1256
 TestF.C:1257
 TestF.C:1258
 TestF.C:1259
 TestF.C:1260
 TestF.C:1261
 TestF.C:1262
 TestF.C:1263
 TestF.C:1264
 TestF.C:1265
 TestF.C:1266
 TestF.C:1267
 TestF.C:1268
 TestF.C:1269
 TestF.C:1270
 TestF.C:1271
 TestF.C:1272
 TestF.C:1273
 TestF.C:1274
 TestF.C:1275
 TestF.C:1276
 TestF.C:1277
 TestF.C:1278
 TestF.C:1279
 TestF.C:1280
 TestF.C:1281
 TestF.C:1282
 TestF.C:1283
 TestF.C:1284
 TestF.C:1285
 TestF.C:1286
 TestF.C:1287
 TestF.C:1288
 TestF.C:1289
 TestF.C:1290
 TestF.C:1291
 TestF.C:1292
 TestF.C:1293
 TestF.C:1294
 TestF.C:1295
 TestF.C:1296
 TestF.C:1297
 TestF.C:1298