Index: trunk/FACT++/src/fitsdump.cc
===================================================================
--- trunk/FACT++/src/fitsdump.cc	(revision 12904)
+++ trunk/FACT++/src/fitsdump.cc	(revision 12905)
@@ -17,4 +17,8 @@
 #include "Time.h"
 #include "externals/fits.h"
+
+#ifdef HAVE_ROOT
+#include "TFormula.h"
+#endif
 
 using namespace std;
@@ -72,8 +76,10 @@
     vector<MyColumn> InitColumns(vector<string> list);
 
+    double GetDouble(const MyColumn &, size_t) const;
+
     ///Display the selected columns values VS time
-    void Dump(ofstream &, const vector<MyColumn> &, const string &);
-    void DumpMinMax(ofstream &, const vector<MyColumn> &, bool);
-    void DumpStats(ofstream &, const vector<MyColumn> &);
+    void Dump(ofstream &, const vector<MyColumn> &, const string &, size_t, size_t, const string &);
+    void DumpMinMax(ofstream &, const vector<MyColumn> &, size_t, size_t, bool);
+    void DumpStats(ofstream &, const vector<MyColumn> &, size_t, size_t);
 
 public:
@@ -246,19 +252,57 @@
 }
 
+double FitsDumper::GetDouble(const MyColumn &it, size_t i) const
+{
+    switch (it.col.type)
+    {
+    case 'A':
+        return reinterpret_cast<const char*>(it.ptr)[i];
+
+    case 'L':
+        return reinterpret_cast<const bool*>(it.ptr)[i];
+
+    case 'B':
+        return (unsigned int)reinterpret_cast<const uint8_t*>(it.ptr)[i];
+
+    case 'I':
+        return reinterpret_cast<const int16_t*>(it.ptr)[i];
+
+    case 'J':
+        return reinterpret_cast<const int32_t*>(it.ptr)[i];
+
+    case 'K':
+        return reinterpret_cast<const int64_t*>(it.ptr)[i];
+
+    case 'E':
+        return reinterpret_cast<const float*>(it.ptr)[i];
+
+    case 'D':
+        return reinterpret_cast<const double*>(it.ptr)[i];
+    }
+
+    return 0;
+}
+
 // --------------------------------------------------------------------------
 //
 //! Perform the actual dump, based on the current parameters
 //
-void FitsDumper::Dump(ofstream &fout, const vector<MyColumn> &cols, const string &filename)
+void FitsDumper::Dump(ofstream &fout, const vector<MyColumn> &cols, const string &filter, size_t first, size_t limit, const string &filename)
 {
     const fits::Table::Keys &fKeyMap = GetKeys();
 
+    TFormula select;
+    if (!filter.empty() && select.Compile(filter.c_str()))
+        throw runtime_error("Syntax Error: TFormula::Compile failed for '"+filter+"'");
+
     fout << "## --------------------------------------------------------------------------\n";
-    fout << "## Fits file:\t" << fFilename << '\n';
+    fout << "## Fits file:  \t" << fFilename << '\n';
     if (filename!="-")
-        fout << "## File:    \t" << filename << '\n';
-    fout << "## Table:   \t" << fKeyMap.find("EXTNAME")->second.value << '\n';
-    fout << "## NumRows: \t" << GetInt("NAXIS2") << '\n';
-    fout << "## Comment: \t" << ((fKeyMap.find("COMMENT") != fKeyMap.end()) ? fKeyMap.find("COMMENT")->second.value : "") << '\n';
+        fout << "## File:      \t" << filename << '\n';
+    fout << "## Table:     \t" << fKeyMap.find("EXTNAME")->second.value << '\n';
+    fout << "## NumRows:   \t" << GetInt("NAXIS2") << '\n';
+    fout << "## Comment:   \t" << ((fKeyMap.find("COMMENT") != fKeyMap.end()) ? fKeyMap.find("COMMENT")->second.value : "") << '\n';
+    if (!filter.empty())
+        fout << "## Selection: \t" << select.GetExpFormula() << '\n';
     fout << "## --------------------------------------------------------------------------\n";
     ListKeywords(fout);
@@ -266,4 +310,5 @@
     fout << "#\n";
 
+    size_t num = 0;
     for (auto it=cols.begin(); it!=cols.end(); it++)
     {
@@ -279,4 +324,6 @@
 
         fout << ": " << it->col.unit << '\n';
+
+        num += it->last-it->first+1;
     }
     fout << "#" << endl;
@@ -284,14 +331,21 @@
     // -----------------------------------------------------------------
 
-    while (GetNextRow())
+    vector<Double_t> data(num);
+
+    const size_t last = limit ? first + limit : size_t(-1);
+
+    while (GetRow(first++))
     {
         const size_t row = GetRow();
-        if (row==GetNumRows())
-            break;
-
+        if (row==GetNumRows() || row==last)
+            break;
+
+        size_t p = 0;
+
+        ostringstream out;
         for (auto it=cols.begin(); it!=cols.end(); it++)
         {
             string msg;
-            for (uint32_t i=it->first; i<=it->last; i++)
+            for (uint32_t i=it->first; i<=it->last; i++, p++)
             {
                 switch (it->col.type)
@@ -301,45 +355,54 @@
                     break;
                 case 'B':
-                    fout << (unsigned int)reinterpret_cast<const unsigned char*>(it->ptr)[i] << " ";
+                    out << (unsigned int)reinterpret_cast<const unsigned char*>(it->ptr)[i] << " ";
                     break;
                 case 'L':
-                    fout << reinterpret_cast<const bool*>(it->ptr)[i] << " ";
+                    out << reinterpret_cast<const bool*>(it->ptr)[i] << " ";
                     break;
                 case 'I':
-                    fout << reinterpret_cast<const int16_t*>(it->ptr)[i] << " ";
+                    out << reinterpret_cast<const int16_t*>(it->ptr)[i] << " ";
                     break;
                 case 'J':
-                    fout << reinterpret_cast<const int32_t*>(it->ptr)[i] << " ";
+                    out << reinterpret_cast<const int32_t*>(it->ptr)[i] << " ";
                     break;
                 case 'K':
-                    fout << reinterpret_cast<const int64_t*>(it->ptr)[i] << " ";
+                    out << reinterpret_cast<const int64_t*>(it->ptr)[i] << " ";
                     break;
                 case 'E':
-                    fout << reinterpret_cast<const float*>(it->ptr)[i] << " ";
+                    out << reinterpret_cast<const float*>(it->ptr)[i] << " ";
                     break;
                 case 'D':
-                    fout << reinterpret_cast<const double*>(it->ptr)[i] << " ";
+                    out << reinterpret_cast<const double*>(it->ptr)[i] << " ";
                     break;
                 default:
                     ;
                 }
+
+                if (!filter.empty())
+                    data[p] = GetDouble(*it, i);
             }
 
             if (it->col.type=='A')
-                fout << "'" << msg << "' ";
-        }
-        fout << endl;
-    }
-}
-
-void FitsDumper::DumpMinMax(ofstream &fout, const vector<MyColumn> &cols, bool fNoZeroPlease)
+                out << "'" << msg << "' ";
+        }
+
+        if (!filter.empty() && select.EvalPar(0, data.data())<0.5)
+            continue;
+
+        fout << out.str() << endl;
+    }
+}
+
+void FitsDumper::DumpMinMax(ofstream &fout, const vector<MyColumn> &cols, size_t first, size_t limit, bool fNoZeroPlease)
 {
     vector<minMaxStruct> statData(cols.size());
 
     // Loop over all columns in our list of requested columns
-    while (GetNextRow())
+    const size_t last = limit ? first + limit : size_t(-1);
+
+    while (GetRow(first++))
     {
         const size_t row = GetRow();
-        if (row==GetNumRows())
+        if (row==GetNumRows() || row==last)
             break;
 
@@ -360,31 +423,5 @@
             for (uint32_t i=it->first; i<=it->last; i++)
             {
-                double cValue = 0;
-                switch (it->col.type)
-                {
-                case 'L':
-                        cValue = reinterpret_cast<const bool*>(it->ptr)[i];
-                        break;
-                case 'B':
-                        cValue = reinterpret_cast<const int8_t*>(it->ptr)[i];
-                        break;
-                case 'I':
-                        cValue = reinterpret_cast<const int16_t*>(it->ptr)[i];
-                        break;
-                case 'J':
-                        cValue = reinterpret_cast<const int32_t*>(it->ptr)[i];
-                        break;
-                case 'K':
-                        cValue = reinterpret_cast<const int64_t*>(it->ptr)[i];
-                        break;
-                case 'E':
-                        cValue = reinterpret_cast<const float*>(it->ptr)[i];
-                        break;
-                case 'D':
-                        cValue = reinterpret_cast<const double*>(it->ptr)[i];
-                        break;
-                default:
-                    ;
-                }
+                const double cValue = GetDouble(*it, i);
 
                 if (fNoZeroPlease && cValue == 0)
@@ -469,17 +506,23 @@
 }
 
-void FitsDumper::DumpStats(ofstream &fout, const vector<MyColumn> &cols)
+void FitsDumper::DumpStats(ofstream &fout, const vector<MyColumn> &cols, size_t first, size_t limit)
 {
     // Loop over all columns in our list of requested columns
     vector<vector<char>> statData;
 
+    const size_t num = limit==0 || GetNumRows()<limit ? GetNumRows() : limit;
+
     for (auto it=cols.begin(); it!=cols.end(); it++)
-        statData.push_back(vector<char>(it->col.size*GetNumRows()*(it->last-it->first+1)));
-
-    while (GetNextRow())
+        statData.push_back(vector<char>(it->col.size*num*(it->last-it->first+1)));
+
+    // Loop over all columns in our list of requested columns
+    const size_t last = limit ? first + limit : size_t(-1);
+
+    while (GetRow(first++))
     {
         const size_t row = GetRow();
-        if (row==GetNumRows())
-            break;
+        if (row==GetNumRows() || row==last)
+            break;
+
 
         auto statsIt = statData.begin();
@@ -576,7 +619,12 @@
         return false;
 
+    const string filter = conf.Has("filter") ? conf.Get<string>("filter") : "";
+
+    const size_t first  = conf.Get<size_t>("first");
+    const size_t limit  = conf.Get<size_t>("limit");
+
     if (conf.Get<bool>("minmax"))
     {
-        DumpMinMax(fout, cols, conf.Get<bool>("nozero"));
+        DumpMinMax(fout, cols, first, limit, conf.Get<bool>("nozero"));
         return 0;
     }
@@ -584,9 +632,9 @@
     if (conf.Get<bool>("stat"))
     {
-        DumpStats(fout, cols);
+        DumpStats(fout, cols, first, limit);
         return 0;
     }
 
-    Dump(fout, cols, filename);
+    Dump(fout, cols, filter, first, limit, filename);
 
     return 0;
@@ -626,4 +674,9 @@
         ("nozero,z",    po_switch(),                "skip 0 values for stats")
         ("force",       po_switch(),                "Force reading the fits file even if END key is missing")
+        ("first",       var<size_t>(size_t(0)),     "First number of row to read")
+        ("limit",       var<size_t>(size_t(0)),     "Limit for the maximum number of rows to read (0=unlimited)")
+#ifdef HAVE_ROOT
+        ("filter,r",    var<string>(""),            "Filter to restrict the selection of events (does not work with stat and minmax yet)")
+#endif
         ;
 
