Index: trunk/MagicSoft/Mars/Changelog
===================================================================
--- trunk/MagicSoft/Mars/Changelog	(revision 7723)
+++ trunk/MagicSoft/Mars/Changelog	(revision 7724)
@@ -18,4 +18,25 @@
 
                                                  -*-*- END OF LINE -*-*-
+
+ 2006/05/21 Thomas Bretz
+
+   * mfileio/MReadTree.cc:
+     - show all added files only in debug modes or if wildcards are used
+
+   * mfilter/MFEnergySlope.[h,cc]:
+     - added a third constructor which also allows to set fMcEnergyMin
+
+   * mjtrain/MJTrainSeparation.[h,cc]:
+     - updated text output
+     - improved result display
+     - added possibility to set weights and/or pre/post-tasks for
+       train or test only
+
+   * mranforest/MRanForest.cc:
+     - commented out an obsolete check to check whether TMath::Sort
+       has sorted correctly
+     - added some comments
+
+
 
  2006/05/20 Thomas Bretz
Index: trunk/MagicSoft/Mars/mfileio/MReadTree.cc
===================================================================
--- trunk/MagicSoft/Mars/mfileio/MReadTree.cc	(revision 7723)
+++ trunk/MagicSoft/Mars/mfileio/MReadTree.cc	(revision 7724)
@@ -395,5 +395,6 @@
     {
         SetBit(kChainWasChanged);
-        *fLog << inf << GetDescriptor() << ": Added " << fname << " <" << numfiles << ">" << endl;
+        if (numfiles>1 || gLog.GetDebugLevel()>4)
+            *fLog << inf << GetDescriptor() << ": Added " << fname << " <" << numfiles << ">" << endl;
     }
     else
Index: trunk/MagicSoft/Mars/mfilter/MFEnergySlope.cc
===================================================================
--- trunk/MagicSoft/Mars/mfilter/MFEnergySlope.cc	(revision 7723)
+++ trunk/MagicSoft/Mars/mfilter/MFEnergySlope.cc	(revision 7724)
@@ -87,4 +87,15 @@
 // --------------------------------------------------------------------------
 //
+//     Constructor
+//
+MFEnergySlope::MFEnergySlope(Float_t slope, Float_t emin, const char *name, const char *title):
+    fNewSlope(TMath::Abs(slope)), fMcMinEnergy(emin), fMcMaxEnergy(-1.)
+{
+    fName  = name  ? name  : "MFEnergySlope";
+    fTitle = title ? title : "Filter to select energy with given slope";
+}
+
+// --------------------------------------------------------------------------
+//
 //   Preprocess
 //  
Index: trunk/MagicSoft/Mars/mfilter/MFEnergySlope.h
===================================================================
--- trunk/MagicSoft/Mars/mfilter/MFEnergySlope.h	(revision 7723)
+++ trunk/MagicSoft/Mars/mfilter/MFEnergySlope.h	(revision 7724)
@@ -38,4 +38,5 @@
     MFEnergySlope(const char *name=NULL, const char *title=NULL);
     MFEnergySlope(Float_t slope, const char *name=NULL, const char *title=NULL);
+    MFEnergySlope(Float_t slope, Float_t emin, const char *name=NULL, const char *title=NULL);
 
     // Setter
Index: trunk/MagicSoft/Mars/mjtrain/MJTrainSeparation.cc
===================================================================
--- trunk/MagicSoft/Mars/mjtrain/MJTrainSeparation.cc	(revision 7723)
+++ trunk/MagicSoft/Mars/mjtrain/MJTrainSeparation.cc	(revision 7724)
@@ -36,4 +36,5 @@
 #include <TMarker.h>
 #include <TCanvas.h>
+#include <TStopwatch.h>
 #include <TVirtualPad.h>
 
@@ -81,5 +82,5 @@
 using namespace std;
 
-void MJTrainSeparation::DisplayResult(MH3 &h31, MH3 &h32)
+void MJTrainSeparation::DisplayResult(MH3 &h31, MH3 &h32, Float_t ontime)
 {
     TH2D &g = (TH2D&)h32.GetHist();
@@ -107,21 +108,29 @@
     gROOT->SetSelectedPad(NULL);
 
+
+    Double_t Stot = 0;
+    Double_t Btot = 0;
+
+    Double_t max2 = -1;
+
     TGraph gr1;
     TGraph gr2;
-    for (int x=0; x<nx; x++)
+    for (int x=nx-1; x>=0; x--)
     {
         TH1 *hx = h.ProjectionY("H_py", x+1, x+1);
         TH1 *gx = g.ProjectionY("G_py", x+1, x+1);
 
+        Double_t S = 0;
+        Double_t B = 0;
+
         Double_t max1 = -1;
-        Double_t max2 = -1;
         Int_t maxy1 = 0;
         Int_t maxy2 = 0;
-        for (int y=0; y<ny; y++)
+        for (int y=ny-1; y>=0; y--)
         {
             const Float_t s = gx->Integral(1, y+1);
             const Float_t b = hx->Integral(1, y+1);
             const Float_t sig1 = MMath::SignificanceLiMa(s+b, b);
-            const Float_t sig2 = s<1 ? 0 : MMath::SignificanceLiMa(s+b, b)*TMath::Log10(s+1);
+            const Float_t sig2 = MMath::SignificanceLiMa(s+Stot+b+Btot, b+Btot)*TMath::Log10(s+Stot+1);
             if (sig1>max1)
             {
@@ -133,4 +142,7 @@
                 maxy2 = y;
                 max2 = sig2;
+
+                S=s;
+                B=b;
             }
 
@@ -138,4 +150,7 @@
         }
 
+        Stot += S;
+        Btot += B;
+
         gr1.SetPoint(x, h.GetXaxis()->GetBinCenter(x+1), h.GetYaxis()->GetBinCenter(maxy1+1));
         gr2.SetPoint(x, h.GetXaxis()->GetBinCenter(x+1), h.GetYaxis()->GetBinCenter(maxy2+1));
@@ -145,4 +160,18 @@
     }
 
+    //cout << "--> " << MMath::SignificanceLiMa(Stot+Btot, Btot) << " ";
+    //cout << Stot << " " << Btot << endl;
+
+
+    Int_t mx1=0;
+    Int_t my1=0;
+    Int_t mx2=0;
+    Int_t my2=0;
+    Int_t s1=0;
+    Int_t b1=0;
+    Int_t s2=0;
+    Int_t b2=0;
+    Double_t sig1=-1;
+    Double_t sig2=-1;
     for (int x=0; x<nx; x++)
     {
@@ -155,4 +184,22 @@
             const Float_t sig = MMath::SignificanceLiMa(s+b, b);
             res2.SetBinContent(x+1, y+1, sig);
+
+            // Search for top-rightmost maximum
+            if (sig>=sig1)
+            {
+                mx1=x+1;
+                my1=y+1;
+                s1 = TMath::Nint(s);
+                b1 = TMath::Nint(b);
+                sig1=sig;
+            }
+            if (TMath::Log10(s)*sig>=sig2)
+            {
+                mx2=x+1;
+                my2=y+1;
+                s2 = TMath::Nint(s);
+                b2 = TMath::Nint(b);
+                sig2=TMath::Log10(s)*sig;
+            }
         }
         delete hx;
@@ -179,60 +226,78 @@
     delete gx;
 
-    TCanvas &c = fDisplay->AddTab("OptCut");
-    c.SetBorderMode(0);
-    c.Divide(2,2);
-
-    c.cd(1);
-    gPad->SetBorderMode(0);
-    gPad->SetFrameBorderMode(0);
-    gPad->SetLogx();
-    gPad->SetGridx();
-    gPad->SetGridy();
-    h.DrawCopy();
-    g.DrawCopy("same");
-    gr1.SetMarkerStyle(kFullDotMedium);
-    gr1.DrawClone("LP")->SetBit(kCanDelete);
-    gr2.SetLineColor(kBlue);
-    gr2.SetMarkerStyle(kFullDotMedium);
-    gr2.DrawClone("LP")->SetBit(kCanDelete);
-
-    c.cd(3);
-    gPad->SetBorderMode(0);
-    gPad->SetFrameBorderMode(0);
-    gPad->SetGridx();
-    gPad->SetGridy();
-    gr4.SetMinimum(0);
-    gr4.SetMarkerStyle(kFullDotMedium);
-    gr4.DrawClone("ALP")->SetBit(kCanDelete);
-    gr3.SetLineColor(kBlue);
-    gr3.SetMarkerStyle(kFullDotMedium);
-    gr3.DrawClone("LP")->SetBit(kCanDelete);
-
-    c.cd(2);
-    gPad->SetBorderMode(0);
-    gPad->SetFrameBorderMode(0);
-    gPad->SetLogx();
-    gPad->SetGridx();
-    gPad->SetGridy();
-    gPad->AddExec("color", "gStyle->SetPalette(1, 0);");
-    res1.SetMaximum(7);
-    res1.DrawCopy("colz");
-
-    c.cd(4);
-    gPad->SetBorderMode(0);
-    gPad->SetFrameBorderMode(0);
-    gPad->SetLogx();
-    gPad->SetGridx();
-    gPad->SetGridy();
-    gPad->AddExec("color", "gStyle->SetPalette(1, 0);");
-    res2.SetMaximum(res2.GetMaximum()*1.05);
-    res2.DrawCopy("colz");
-
-    Int_t mx, my, mz;
-    res2.GetMaximumBin(mx, my, mz);
-
-    TMarker m;
-    m.SetMarkerStyle(kStar);
-    m.DrawMarker(res2.GetXaxis()->GetBinCenter(mx), res2.GetYaxis()->GetBinCenter(my));
+    if (fDisplay)
+    {
+        TCanvas &c = fDisplay->AddTab("OptCut");
+        c.SetBorderMode(0);
+        c.Divide(2,2);
+
+        c.cd(1);
+        gPad->SetBorderMode(0);
+        gPad->SetFrameBorderMode(0);
+        gPad->SetLogx();
+        gPad->SetGridx();
+        gPad->SetGridy();
+        h.DrawCopy();
+        g.DrawCopy("same");
+        gr1.SetMarkerStyle(kFullDotMedium);
+        gr1.DrawClone("LP")->SetBit(kCanDelete);
+        gr2.SetLineColor(kBlue);
+        gr2.SetMarkerStyle(kFullDotMedium);
+        gr2.DrawClone("LP")->SetBit(kCanDelete);
+
+        c.cd(3);
+        gPad->SetBorderMode(0);
+        gPad->SetFrameBorderMode(0);
+        gPad->SetGridx();
+        gPad->SetGridy();
+        gr4.SetMinimum(0);
+        gr4.SetMarkerStyle(kFullDotMedium);
+        gr4.DrawClone("ALP")->SetBit(kCanDelete);
+        gr3.SetLineColor(kBlue);
+        gr3.SetMarkerStyle(kFullDotMedium);
+        gr3.DrawClone("LP")->SetBit(kCanDelete);
+
+        c.cd(2);
+        gPad->SetBorderMode(0);
+        gPad->SetFrameBorderMode(0);
+        gPad->SetLogx();
+        gPad->SetGridx();
+        gPad->SetGridy();
+        gPad->AddExec("color", "gStyle->SetPalette(1, 0);");
+        res1.SetMaximum(7);
+        res1.DrawCopy("colz");
+
+        c.cd(4);
+        gPad->SetBorderMode(0);
+        gPad->SetFrameBorderMode(0);
+        gPad->SetLogx();
+        gPad->SetGridx();
+        gPad->SetGridy();
+        gPad->AddExec("color", "gStyle->SetPalette(1, 0);");
+        res2.SetMaximum(res2.GetMaximum()*1.05);
+        res2.DrawCopy("colz");
+
+        //    Int_t mx, my, mz;
+        //    res2.GetMaximumBin(mx, my, mz);
+
+        TMarker m;
+        m.SetMarkerStyle(kStar);
+        m.DrawMarker(res2.GetXaxis()->GetBinCenter(mx1), res2.GetYaxis()->GetBinCenter(my1));
+        m.SetMarkerStyle(kPlus);
+        m.DrawMarker(res2.GetXaxis()->GetBinCenter(mx2), res2.GetYaxis()->GetBinCenter(my2));
+    }
+
+    *fLog << all << "Observation Time:     " << TMath::Nint(ontime/60) << "min" << endl;
+    *fLog << "Maximum Significance: " << Form("%.1f", sig1) << " [";
+    *fLog << Form("%.1f", sig1/TMath::Sqrt(ontime/3600)) << "/sqrt(h)]";
+    *fLog << endl;
+
+    *fLog << "Significance:         S=" << Form("%.1f", sig1) << " E=" << s1 << " B=" << b1 << " h<";
+    *fLog << Form("%.2f", res2.GetYaxis()->GetBinCenter(my1)) << " s>";
+    *fLog << Form("%3d", TMath::Nint(res2.GetXaxis()->GetBinCenter(mx1))) << endl;
+    *fLog << "Significance*LogE:    S=" << Form("%.1f", sig2/TMath::Log10(s2)) << " E=" << s2 << " B=" << b2 << " h<";
+    *fLog << Form("%.2f", res2.GetYaxis()->GetBinCenter(my2)) << " s>";
+    *fLog << Form("%3d", TMath::Nint(res2.GetXaxis()->GetBinCenter(mx2))) << endl;
+    *fLog << endl;
 }
 
@@ -392,9 +457,9 @@
 }
 
-Bool_t MJTrainSeparation::AutoTrain(MDataSet &set, UInt_t &seton, UInt_t &setoff)
+Float_t MJTrainSeparation::AutoTrain(MDataSet &set, Type_t  typon, Type_t typof, Float_t flux)
 {
     Double_t num, min, max;
     if (!GetEventsProduced(set, num, min, max))
-        return kFALSE;
+        return -1;
 
     *fLog << inf << "Using build-in radius of 300m to calculate collection area!" << endl;
@@ -402,5 +467,5 @@
     // Target spectrum
     TF1 flx("Flux", "[0]/1000*(x/1000)^(-2.6)", min, max);
-    flx.SetParameter(0, fFlux);
+    flx.SetParameter(0, flux);
 
     // Number n0 of events this spectrum would produce per s and m^2
@@ -412,4 +477,6 @@
     // Rate R of events this spectrum would produce per s
     const Double_t R = n0*A;                       //[Hz]
+
+    *fLog << "Source Spectrum:                                          " << flux << " * (E/TeV)^(-2.6) * TeV*m^2*s" << endl;
 
     *fLog << "Gamma rate from the source inside the MC production area: " << R << "Hz" << endl;
@@ -428,9 +495,10 @@
     Double_t data=0;
     const Double_t r = GetDataRate(set, data); //[Hz]
+    Double_t ontime = data/r;
 
     *fLog << "Events measured per second effective on time:             " << r << "Hz" << endl;
-    *fLog << "Total effective on time:                                  " << data/r  << "s" << endl;
-
-    const Double_t ratio = T*r/data;
+    *fLog << "Total effective on time:                                  " << ontime  << "s" << endl;
+
+    const Double_t ratio = T/ontime;
     *fLog << "Ratio of Monte Carlo to data observation time:            " << ratio << endl;
 
@@ -445,5 +513,5 @@
 
     if (r<0)
-        return kFALSE;
+        return -1;
 
     Double_t nummc = GetNumMC(set);
@@ -460,5 +528,5 @@
         off = TMath::Nint(data);
         *fLog << warn;
-        *fLog << "Not enough data events available... scaling by " << data/n << endl;
+        *fLog << "Not enough data events available... scaling MC to data by " << data/n << endl;
         *fLog << inf;
     }
@@ -469,17 +537,19 @@
     }
 
-    if (seton>0 && seton<on)
-    {
-        setoff = TMath::Nint(off*seton/on);
-        *fLog << "Less MC events requested... scaling by " << seton/on << endl;
+    if (fNum[typon]>0 && fNum[typon]<on)
+    {
+        fNum[typof] = TMath::Nint(off*fNum[typon]/on);
+        ontime *= fNum[typon]/on;
+        *fLog << warn << "Less MC events requested... scaling data to MC by " << fNum[typon]/on << endl;
     }
     else
     {
-        seton  = TMath::Nint(on);
-        setoff = TMath::Nint(off);
-    }
-
-    *fLog << "Target number of MC events:   " << seton  << endl;
-    *fLog << "Target number of data events: " << setoff << endl;
+        fNum[typon] = TMath::Nint(on);
+        fNum[typof] = TMath::Nint(off);
+    }
+
+    *fLog << inf;
+    *fLog << "Target number of MC events:   " << fNum[typon] << endl;
+    *fLog << "Target number of data events: " << fNum[typof] << endl;
 
     /*
@@ -498,5 +568,5 @@
      */
 
-    return kTRUE;
+    return ontime;
 }
 
@@ -520,13 +590,18 @@
     }
 
+    TStopwatch clock;
+    clock.Start();
+
     // ----------------------- Auto Train? ----------------------
 
+    Float_t ontime = -1;
     if (fAutoTrain)
     {
         fLog->Separator("Auto-Training -- Train-Data");
-        if (!AutoTrain(fDataSetTrain, fNumTrainOn, fNumTrainOff))
+        if (AutoTrain(fDataSetTrain, kTrainOn, kTrainOff, fFluxTrain)<0)
             return kFALSE;
         fLog->Separator("Auto-Training -- Test-Data");
-        if (!AutoTrain(fDataSetTest,  fNumTestOn,  fNumTestOff))
+        ontime = AutoTrain(fDataSetTest, kTestOn, kTestOff, fFluxTest);
+        if (ontime<0)
             return kFALSE;
     }
@@ -552,5 +627,5 @@
     MHMatrix train("Train");
     train.AddColumns(fRules);
-    if (fEnableWeightsOn || fEnableWeightsOff)
+    if (fEnableWeights[kTrainOn] || fEnableWeights[kTrainOff])
         train.AddColumn("MWeight.fVal");
     train.AddColumn("MHadronness.fVal");
@@ -565,7 +640,7 @@
     // Add them to the parameter list
     MParList plistx;
+    plistx.AddToList(this); // take care of fDisplay!
     plistx.AddToList(&had);
     plistx.AddToList(&wgt);
-    plistx.AddToList(this);
 
     // Setup the tool class to fill the matrix
@@ -582,9 +657,9 @@
     // Setup the tool class to read the gammas and read them
     fill.SetName("FillGammas");
-    fill.SetDestMatrix1(&train, fNumTrainOn);
+    fill.SetDestMatrix1(&train, fNum[kTrainOn]);
     fill.SetReader(&read1);
-    fill.AddPreTasks(fPreTasksOn);
+    fill.AddPreTasks(fPreTasksSet[kTrainOn]);
     fill.AddPreTasks(fPreTasks);
-    fill.AddPostTasks(fPostTasksOn);
+    fill.AddPostTasks(fPostTasksSet[kTrainOn]);
     fill.AddPostTasks(fPostTasks);
     if (!fill.Process(plistx))
@@ -616,15 +691,15 @@
     if (fDataSetTrain.IsWobbleMode())
     {
-        fPreTasksOff.AddFirst(&hcalc);
-        fPreTasksOff.AddFirst(&srcrndm);
+        fPreTasksSet[kTrainOff].AddFirst(&hcalc);
+        fPreTasksSet[kTrainOff].AddFirst(&srcrndm);
     }
 
     // Setup the tool class to read the background and read them
     fill.SetName("FillBackground");
-    fill.SetDestMatrix1(&train, fNumTrainOff);
+    fill.SetDestMatrix1(&train, fNum[kTrainOff]);
     fill.SetReader(&read3);
-    fill.AddPreTasks(fPreTasksOff);
+    fill.AddPreTasks(fPreTasksSet[kTrainOff]);
     fill.AddPreTasks(fPreTasks);
-    fill.AddPostTasks(fPostTasksOff);
+    fill.AddPostTasks(fPostTasksSet[kTrainOff]);
     fill.AddPostTasks(fPostTasks);
     if (!fill.Process(plistx))
@@ -646,5 +721,5 @@
     rf.SetNumTry(fNumTry);
     rf.SetNumObsoleteVariables(1);
-    rf.SetLastDataColumnHasWeights(fEnableWeightsOn || fEnableWeightsOff);
+    rf.SetLastDataColumnHasWeights(fEnableWeights[kTrainOn] || fEnableWeights[kTrainOff]);
     rf.SetDebug(fDebug);
     rf.SetDisplay(fDisplay);
@@ -671,7 +746,7 @@
     *fLog << "Training method:" << endl;
     *fLog << " * " << (fUseRegression?"regression":"classification") << endl;
-    if (fEnableWeightsOn)
+    if (fEnableWeights[kTrainOn])
         *fLog << " * weights for on-data" << endl;
-    if (fEnableWeightsOff)
+    if (fEnableWeights[kTrainOff])
         *fLog << " * weights for off-data" << endl;
     if (fDataSetTrain.IsWobbleMode())
@@ -683,6 +758,9 @@
     *fLog << endl;
     *fLog << "Gamma/Background ratio:" << endl;
-    *fLog << " * Requested:  " << (float)fNumTrainOn/fNumTrainOff << endl;
+    *fLog << " * Requested:  " << (float)fNum[kTrainOn]/fNum[kTrainOff] << endl;
     *fLog << " * Result:     " << (float)numgammastrn/numbackgrndtrn << endl;
+    *fLog << endl;
+    *fLog << "Run-Time: " << Form("%.1f", clock.RealTime()/60) << "min (CPU: ";
+    *fLog << Form("%.1f", clock.CpuTime()/60) << "min)" << endl;
 
     // Chekc if testing is requested
@@ -693,8 +771,10 @@
     fLog->Separator("Test");
 
+    clock.Continue();
+
     // Setup parlist and tasklist for testing
     MParList  plist;
     MTaskList tlist;
-    plist.AddToList(this);
+    plist.AddToList(this); // Take care of display
     plist.AddToList(&tlist);
 
@@ -747,5 +827,5 @@
 
     MFEventSelector sel; // FIXME: USING IT (WITH PROB?) in READ will by much faster!!!
-    sel.SetNumSelectEvts(fNumTestOff);
+    sel.SetNumSelectEvts(fNum[kTestOff]);
 
     MContinue c1(&sel);
@@ -755,9 +835,9 @@
     tlist.AddToList(&read2);
     tlist.AddToList(&c1);
-    tlist.AddToList(fPreTasksOff);
+    tlist.AddToList(fPreTasksSet[kTestOff]);
     tlist.AddToList(fPreTasks);
     tlist.AddToList(&c0);
     tlist.AddToList(&rf);
-    tlist.AddToList(fPostTasksOff);
+    tlist.AddToList(fPostTasksSet[kTestOff]);
     tlist.AddToList(fPostTasks);
     tlist.AddToList(&fillh0);
@@ -776,12 +856,18 @@
     if (!loop.Eventloop())
         return kFALSE;
-
+ /*
+    if (!loop.GetDisplay())
+    {
+        gLog << warn << "Display closed by user... execution aborted." << endl << endl;
+        return kFALSE;
+    }
+   */
     // ----- Setup and run eventloop on gammas -----
-    sel.SetNumSelectEvts(fNumTestOn);
+    sel.SetNumSelectEvts(fNum[kTestOn]);
     fillh0.ResetBit(MFillH::kDoNotDisplay);
 
     // Remove PreTasksOff and PostTasksOff from the list
-    tlist.RemoveFromList(fPreTasksOff);
-    tlist.RemoveFromList(fPostTasksOff);
+    tlist.RemoveFromList(fPreTasksSet[kTestOff]);
+    tlist.RemoveFromList(fPostTasksSet[kTestOff]);
 
     // replace the reading task by a new one
@@ -789,8 +875,8 @@
 
     // Add the PreTasksOn directly after the reading task
-    tlist.AddToListAfter(fPreTasksOn, &c1);
+    tlist.AddToListAfter(fPreTasksSet[kTestOn], &c1);
 
     // Add the PostTasksOn after rf
-    tlist.AddToListAfter(fPostTasksOn, &rf);
+    tlist.AddToListAfter(fPostTasksSet[kTestOn], &rf);
 
     // Replace fillh1 by fillh2
@@ -805,11 +891,4 @@
     wgt.SetVal(1);
     if (!loop.Eventloop())
-        return kFALSE;
-
-    // Display the result plots
-    DisplayResult(h31, h32);
-
-    // Write the display
-    if (!WriteDisplay(out))
         return kFALSE;
 
@@ -822,10 +901,11 @@
     *fLog << "Test method:" << endl;
     *fLog << " * Random Forest: " << out << endl;
-    if (fEnableWeightsOn)
+    if (fEnableWeights[kTestOn])
         *fLog << " * weights for on-data" << endl;
-    if (fEnableWeightsOff)
+    if (fEnableWeights[kTestOff])
         *fLog << " * weights for off-data" << endl;
     if (fDataSetTrain.IsWobbleMode())
         *fLog << " * random source position in a distance of 0.4°" << endl;
+    *fLog << endl;
     *fLog << "Events used for test:"   << endl;
     *fLog << " * Gammas:     " << numgammastst   << endl;
@@ -833,6 +913,18 @@
     *fLog << endl;
     *fLog << "Gamma/Background ratio:" << endl;
-    *fLog << " * Requested:  " << (float)fNumTestOn/fNumTestOff << endl;
+    *fLog << " * Requested:  " << (float)fNum[kTestOn]/fNum[kTestOff] << endl;
     *fLog << " * Result:     " << (float)numgammastst/numbackgrndtst << endl;
+    *fLog << endl;
+
+    // Display the result plots
+    DisplayResult(h31, h32, ontime);
+
+    *fLog << "Total Run-Time: " << Form("%.1f", clock.RealTime()/60) << "min (CPU: ";
+    *fLog << Form("%.1f", clock.CpuTime()/60) << "min)" << endl;
+    fLog->Separator();
+
+    // Write the display
+    if (!WriteDisplay(out))
+        return kFALSE;
 
     return kTRUE;
Index: trunk/MagicSoft/Mars/mjtrain/MJTrainSeparation.h
===================================================================
--- trunk/MagicSoft/Mars/mjtrain/MJTrainSeparation.h	(revision 7723)
+++ trunk/MagicSoft/Mars/mjtrain/MJTrainSeparation.h	(revision 7724)
@@ -14,40 +14,38 @@
 class MJTrainSeparation : public MJTrainRanForest
 {
+public:
+    enum Type_t { kTrainOn, kTrainOff, kTestOn, kTestOff };
+
 private:
     MDataSet fDataSetTest;
     MDataSet fDataSetTrain;
 
-    UInt_t fNumTrainOn;
-    UInt_t fNumTrainOff;
+    UInt_t fNum[4];
 
-    UInt_t fNumTestOn;
-    UInt_t fNumTestOff;
-
-    TList fPreTasksOn;
-    TList fPreTasksOff;
-    TList fPostTasksOn;
-    TList fPostTasksOff;
+    TList fPreTasksSet[4];
+    TList fPostTasksSet[4];
 
     Bool_t fAutoTrain;
     Bool_t fUseRegression;
-    Bool_t fEnableWeightsOn;
-    Bool_t fEnableWeightsOff;
 
-    Float_t fFlux;
+    Bool_t fEnableWeights[4];
 
-    void DisplayResult(MH3 &h31, MH3 &h32);
+    Float_t fFluxTrain;
+    Float_t fFluxTest;
 
+    // Result
+    void     DisplayResult(MH3 &h31, MH3 &h32, Float_t ontime);
+
+    // Auto training
     Bool_t   GetEventsProduced(MDataSet &set, Double_t &num, Double_t &min, Double_t &max) const;
     Double_t GetDataRate(MDataSet &set, Double_t &num) const;
     Double_t GetNumMC(MDataSet &set) const;
-    Bool_t   AutoTrain(MDataSet &set, UInt_t &on, UInt_t &off);
+    Float_t  AutoTrain(MDataSet &set, Type_t typon, Type_t typoff, Float_t flux);
 
 public:
     MJTrainSeparation() :
-        fNumTrainOn((UInt_t)-1), fNumTrainOff((UInt_t)-1),
-        fNumTestOn((UInt_t)-1), fNumTestOff((UInt_t)-1),
         fAutoTrain(kFALSE), fUseRegression(kFALSE),
-        fEnableWeightsOn(kFALSE), fEnableWeightsOff(kFALSE), fFlux(2e-7)
-    { }
+        fFluxTrain(2e-7), fFluxTest(2e-7)
+    { for (int i=0; i<4; i++) { fEnableWeights[i]=kFALSE; fNum[i] = (UInt_t)-1; } }
 
     void SetDataSetTrain(const MDataSet &ds, UInt_t non=(UInt_t)-1, UInt_t noff=(UInt_t)-1)
@@ -57,6 +55,6 @@
         fDataSetTrain.SetNumAnalysis(1);
 
-        fNumTrainOn = non;
-        fNumTrainOff = noff;
+        fNum[kTrainOn]  = non;
+        fNum[kTrainOff] = noff;
     }
     void SetDataSetTest(const MDataSet &ds, UInt_t non=(UInt_t)-1, UInt_t noff=(UInt_t)-1)
@@ -66,31 +64,37 @@
         fDataSetTest.SetNumAnalysis(1);
 
-        fNumTestOn = non;
-        fNumTestOff = noff;
+        fNum[kTestOn]  = non;
+        fNum[kTestOff] = noff;
     }
 
-    void AddPreTaskOn(MTask *t)                     { Add(fPreTasksOn,  t); }
-    void AddPreTaskOn(const char *rule,
-                      const char *name="MWeight")   { AddPar(fPreTasksOn, rule, name); }
+    // Deprecated, used for test purpose
+    void AddPreTask(Type_t typ, MTask *t)                                      { Add(fPreTasksSet[typ],  t); }
+    void AddPreTask(Type_t typ, const char *rule, const char *name="MWeight")  { AddPar(fPreTasksSet[typ], rule, name); }
 
-    void AddPreTaskOff(MTask *t)                    { Add(fPreTasksOff, t); }
-    void AddPreTaskOff(const char *rule,
-                       const char *name="MWeight")  { AddPar(fPreTasksOff, rule, name); }
+    void AddPostTask(Type_t typ, MTask *t)                                     { Add(fPostTasksSet[typ],  t); }
+    void AddPostTask(Type_t typ, const char *rule, const char *name="MWeight") { AddPar(fPostTasksSet[typ], rule, name); }
 
-    void AddPostTaskOn(MTask *t)                    { Add(fPostTasksOn,  t); }
-    void AddPostTaskOn(const char *rule,
-                       const char *name="MWeight")  { AddPar(fPostTasksOn, rule, name); }
+    void SetWeights(Type_t typ, const char *rule)  { if (fEnableWeights[typ]) return; fEnableWeights[typ]=kTRUE; AddPostTask(typ, rule); }
+    void SetWeights(Type_t typ, MTask *t)          { if (fEnableWeights[typ]) return; fEnableWeights[typ]=kTRUE; AddPostTask(typ, t); }
 
-    void AddPostTaskOff(MTask *t)                   { Add(fPostTasksOff, t); }
-    void AddPostTaskOff(const char *rule,
-                        const char *name="MWeight") { AddPar(fPostTasksOff, rule, name); }
+    // Standard user interface
+    void AddPreTaskOn(MTask *t)                                       { AddPreTask(kTrainOn, t); AddPreTask(kTestOn, t); }
+    void AddPreTaskOn(const char *rule, const char *name="MWeight")   { AddPreTask(kTrainOn, rule, name); AddPreTask(kTestOn, rule, name); }
+    void AddPreTaskOff(MTask *t)                                      { AddPreTask(kTrainOff, t); AddPreTask(kTestOff, t); }
+    void AddPreTaskOff(const char *rule, const char *name="MWeight")  { AddPreTask(kTrainOff, rule, name); AddPreTask(kTestOff, rule, name); }
 
-    void SetWeightsOn(const char *rule)  { if (fEnableWeightsOn) return;  fEnableWeightsOn=kTRUE;  AddPostTaskOn(rule); }
-    void SetWeightsOn(MTask *t)          { if (fEnableWeightsOn) return;  fEnableWeightsOn=kTRUE;  AddPostTaskOn(t);    }
+    void AddPostTaskOn(MTask *t)                                      { AddPostTask(kTrainOn, t); AddPostTask(kTestOn, t); }
+    void AddPostTaskOn(const char *rule, const char *name="MWeight")  { AddPostTask(kTrainOn, rule, name); AddPostTask(kTestOn, rule, name); }
+    void AddPostTaskOff(MTask *t)                                     { AddPostTask(kTrainOff, t); AddPostTask(kTestOff, t); }
+    void AddPostTaskOff(const char *rule, const char *name="MWeight") { AddPostTask(kTrainOff, rule, name); AddPostTask(kTestOff, rule, name); }
 
-    void SetWeightsOff(const char *rule) { if (fEnableWeightsOff) return; fEnableWeightsOff=kTRUE; AddPostTaskOff(rule); }
-    void SetWeightsOff(MTask *t)         { if (fEnableWeightsOff) return; fEnableWeightsOff=kTRUE; AddPostTaskOff(t);    }
+    void SetWeightsOn(const char *rule)  { SetWeights(kTrainOn, rule); SetWeights(kTestOn, rule); }
+    void SetWeightsOn(MTask *t)          { SetWeights(kTrainOn, t); SetWeights(kTestOn, t); }
+    void SetWeightsOff(const char *rule) { SetWeights(kTrainOff, rule); SetWeights(kTestOff, rule); }
+    void SetWeightsOff(MTask *t)         { SetWeights(kTrainOff, t); SetWeights(kTestOff, t); }
 
-    void SetFlux(Float_t f) { fFlux = f; }
+    void SetFluxTrain(Float_t f) { fFluxTrain = f; }
+    void SetFluxTest(Float_t f)  { fFluxTest  = f; }
+    void SetFlux(Float_t f)      { SetFluxTrain(f); SetFluxTest(f); }
 
     void EnableAutoTrain(Bool_t b=kTRUE)      { fAutoTrain     =  b; }
Index: trunk/MagicSoft/Mars/mranforest/MRanForest.cc
===================================================================
--- trunk/MagicSoft/Mars/mranforest/MRanForest.cc	(revision 7723)
+++ trunk/MagicSoft/Mars/mranforest/MRanForest.cc	(revision 7724)
@@ -590,6 +590,7 @@
 
         // control sorting
-        for(int n=1;n<numdata;n++)
-            if(v[isort[n-1]]>v[isort[n]])
+        /*
+        for(int n=0;n<numdata-1;n++)
+            if(v[isort[n]]>v[isort[n+1]])
             {
                 *fLog << err <<"Event no. "<<n<<", matrix column no. "<<mvar;
@@ -597,5 +598,10 @@
                 return kFALSE;
             }
-
+            */
+
+        // DataRang is similar to the isort index starting from 0 it is
+        // increased by one for each event which is greater, but stays
+        // the same for the same value. (So to say it counts how many
+        // different values we have)
         for(Int_t n=0;n<numdata-1;n++)
         {
@@ -603,4 +609,5 @@
             const Int_t n2=isort[n+1];
 
+            // FIXME: Copying isort[n] to fDataSort[mvar*numdata] can be accelerated!
             fDataSort[mvar*numdata+n]=n1;
             if(n==0) fDataRang[mvar*numdata+n1]=0;
