Index: trunk/FACT++/src/fitsdump.cc
===================================================================
--- trunk/FACT++/src/fitsdump.cc	(revision 12917)
+++ trunk/FACT++/src/fitsdump.cc	(revision 12943)
@@ -75,4 +75,5 @@
 
     vector<MyColumn> InitColumns(vector<string> list);
+    vector<MyColumn> InitColumnsRoot(vector<string> &list);
 
     double GetDouble(const MyColumn &, size_t) const;
@@ -80,4 +81,5 @@
     ///Display the selected columns values VS time
     void Dump(ofstream &, const vector<MyColumn> &, const string &, size_t, size_t, const string &);
+    void DumpRoot(ofstream &, const vector<string> &, 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);
@@ -215,5 +217,5 @@
         const string val1  = what[5];
 
-        const uint32_t first = val0.empty() ? 0 : atoi(val0.c_str());
+        const uint32_t first = atol(val0.c_str());
         const uint32_t last  = (val0.empty() && delim.empty()) ? col.num-1 : (val1.empty() ? first : atoi(val1.c_str()));
 
@@ -242,10 +244,8 @@
         mycol.first = first;
         mycol.last  = last;
+        mycol.ptr   = SetPtrAddress(name);
 
         vec.push_back(mycol);
     }
-
-    for (auto it=vec.begin(); it!=vec.end(); it++)
-        it->ptr = SetPtrAddress(it->name);
 
     return vec;
@@ -292,7 +292,9 @@
     const fits::Table::Keys &fKeyMap = GetKeys();
 
+#ifdef HAVE_ROOT
     TFormula select;
     if (!filter.empty() && select.Compile(filter.c_str()))
         throw runtime_error("Syntax Error: TFormula::Compile failed for '"+filter+"'");
+#endif
 
     fout << "## --------------------------------------------------------------------------\n";
@@ -303,6 +305,8 @@
     fout << "## NumRows:   \t" << GetInt("NAXIS2") << '\n';
     fout << "## Comment:   \t" << ((fKeyMap.find("COMMENT") != fKeyMap.end()) ? fKeyMap.find("COMMENT")->second.value : "") << '\n';
+#ifdef HAVE_ROOT
     if (!filter.empty())
         fout << "## Selection: \t" << select.GetExpFormula() << '\n';
+#endif
     fout << "## --------------------------------------------------------------------------\n";
     ListKeywords(fout);
@@ -323,5 +327,7 @@
             fout << "[" << it->first << ":" << it->last << "]";
 
-        fout << ": " << it->col.unit << '\n';
+        if (!it->col.unit.empty())
+            fout << ": " << it->col.unit;
+        fout << '\n';
 
         num += it->last-it->first+1;
@@ -331,5 +337,7 @@
     // -----------------------------------------------------------------
 
+#ifdef HAVE_ROOT
     vector<Double_t> data(num);
+#endif
 
     const size_t last = limit ? first + limit : size_t(-1);
@@ -342,4 +350,8 @@
 
         size_t p = 0;
+
+#ifdef HAVE_ROOT
+        data[p++] = first-1;
+#endif
 
         ostringstream out;
@@ -380,6 +392,8 @@
                 }
 
+#ifdef HAVE_ROOT
                 if (!filter.empty())
                     data[p] = GetDouble(*it, i);
+#endif
             }
 
@@ -387,10 +401,198 @@
                 out << "'" << msg << "' ";
         }
-
+#ifdef HAVE_ROOT
         if (!filter.empty() && select.EvalPar(0, data.data())<0.5)
             continue;
-
+#endif
         fout << out.str() << endl;
     }
+}
+
+vector<MyColumn> FitsDumper::InitColumnsRoot(vector<string> &names)
+{
+    static const boost::regex expr("[^\\[]([[:word:].]+)(\\[([[:digit:]]+)\\])?");
+
+    const fits::Table::Columns &cols = GetColumns();
+
+    vector<MyColumn> vec;
+
+    for (auto it=names.begin(); it!=names.end(); it++)
+    {
+        if (it->empty())
+            continue;
+
+        *it = ' '+*it;
+
+        string::const_iterator beg = it->begin();
+        string::const_iterator end = it->end();
+
+        boost::smatch what;
+        while (boost::regex_search(beg, end, what, expr, boost::match_extra))
+        {
+            const string all  = what[0];
+            const string name = what[1];
+            const size_t idx  = atol(string(what[3]).c_str());
+
+            // Check if found colum is valid
+            const auto ic = cols.find(name);
+            if (ic==cols.end())
+            {
+                beg++;
+                //cout << "Column '" << name << "' does not exist." << endl;
+                //return vector<MyColumn>();
+                continue;
+            }
+            if (idx>=ic->second.num)
+            {
+                cout << "Column '" << name << "' has no index " << idx << "." << endl;
+                return vector<MyColumn>();
+            }
+
+            // find index if column already exists
+            size_t p = 0;
+            for (; p<vec.size(); p++)
+                if (vec[p].name==name)
+                    break;
+
+            ostringstream id;
+            id << '[' << p << ']';
+
+            it->replace(beg-it->begin()+what.position(1), what.length()-1, id.str());
+
+            beg = what[0].first+3;
+            end = it->end();
+
+            if (p<vec.size())
+                continue;
+
+            // Column not found, add new column
+            MyColumn mycol;
+
+            mycol.name  = name;
+            mycol.col   = ic->second;
+            mycol.first = idx;
+            mycol.last  = idx;
+            mycol.ptr   = SetPtrAddress(name);
+
+            vec.push_back(mycol);
+        }
+    }
+
+    ostringstream id;
+    id << '[' << vec.size() << ']';
+
+    for (auto it=names.begin(); it!=names.end(); it++)
+    {
+        while (1)
+        {
+            auto p = it->find_first_of('#');
+            if (p==string::npos)
+                break;
+
+            it->replace(p, 1, id.str());
+        }
+    }
+
+    //cout << endl;
+    //for (size_t i=0; i<vec.size(); i++)
+    //    cout << "val[" << i << "] = " << vec[i].name << '[' << vec[i].first << ']' << endl;
+    //cout << endl;
+
+    return vec;
+}
+
+void FitsDumper::DumpRoot(ofstream &fout, const vector<string> &cols, const string &filter, size_t first, size_t limit, const string &filename)
+{
+#ifdef HAVE_ROOT
+    vector<string> names(cols);
+    names.insert(names.begin(), filter);
+
+    const vector<MyColumn> vec = InitColumnsRoot(names);
+    if (vec.size()==0)
+        return;
+
+    vector<TFormula> form(names.size());
+
+    auto ifo = form.begin();
+    for (auto it=names.begin(); it!=names.end(); it++, ifo++)
+    {
+        if (!it->empty() && ifo->Compile(it->c_str()))
+            throw runtime_error("Syntax Error: TFormula::Compile failed for '"+*it+"'");
+    }
+
+    const fits::Table::Keys &fKeyMap = GetKeys();
+
+    fout << "## --------------------------------------------------------------------------\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 << "## --------------------------------------------------------------------------\n";
+    ListKeywords(fout);
+    fout << "## --------------------------------------------------------------------------\n";
+    fout << "##\n";
+    if (!filter.empty())
+        fout << "## Selection: " << form[0].GetExpFormula() << "\n##\n";
+
+    size_t num = 0;
+    for (auto it=vec.begin(); it!=vec.end(); it++, num++)
+    {
+        fout << "## [" << num << "] = " << it->name;
+
+        if (it->first==it->last)
+        {
+            if (it->first!=0)
+                fout << "[" << it->first << "]";
+        }
+        else
+            fout << "[" << it->first << ":" << it->last << "]";
+
+        if (!it->col.unit.empty())
+            fout << ": " << it->col.unit;
+        fout << '\n';
+    }
+    fout << "##\n";
+    fout << "## --------------------------------------------------------------------------\n";
+    fout << "#\n";
+
+    fout << "# ";
+    for (auto it=form.begin()+1; it!=form.end(); it++)
+        fout << " \"" << it->GetExpFormula() << "\"";
+    fout << "\n#" << endl;
+
+    // -----------------------------------------------------------------
+
+    vector<Double_t> data(vec.size()+1);
+
+    const size_t last = limit ? first + limit : size_t(-1);
+
+    while (GetRow(first++))
+    {
+        const size_t row = GetRow();
+        if (row==GetNumRows() || row==last)
+            break;
+
+        //data[p++] = first-1;
+
+        ostringstream out;
+        out.precision(fout.precision());
+
+        size_t p = 0;
+        for (auto it=vec.begin(); it!=vec.end(); it++, p++)
+            data[p] = GetDouble(*it, it->first);
+
+        data[p] = first;
+
+        if (!filter.empty() && form[0].EvalPar(0, data.data())<0.5)
+            continue;
+
+        for (auto iform=form.begin()+1; iform!=form.end(); iform++)
+            out << iform->EvalPar(0, data.data()) << " ";
+
+        fout << out.str() << endl;
+    }
+#endif
 }
 
@@ -616,12 +818,19 @@
     fout.precision(conf.Get<int>("precision"));
 
+    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>("root"))
+    {
+        DumpRoot(fout, conf.Vec<string>("col"), filter, first, limit, filename);
+        return 0;
+    }
+
     const vector<MyColumn> cols = InitColumns(conf.Vec<string>("col"));
     if (cols.size()==0)
         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"))
@@ -649,4 +858,5 @@
         "Usage: fitsdump [OPTIONS] fitsfile col col ... \n"
         "  or:  fitsdump [OPTIONS]\n";
+
     cout << endl;
 }
@@ -654,5 +864,35 @@
 void PrintHelp()
 {
-    // 
+    cout <<
+        "\n"
+        "To address a column several syntax is possible:\n"
+        "  ColumnName:        Will address all fields of a column\n"
+        "  ColumnName[n]:     Will address the n-th field of a column (starts with 0)\n"
+        "  ColumnName[n1:n2]: Will address all fields between n1 and including n2\n"
+#ifdef HAVE_ROOT
+        "\n"
+        "To select some columns can use --filter\n"
+        "Such a selction is evaluated using TFormula, hence, every "
+        "mathematical operation allowed in TFormula is allowed there, too. "
+        "The reference is the column index as printed in the output stream, "
+        "starting with 1. The index 0 is reserved for the row number.\n"
+        "\n"
+        "Example:\n"
+        "  fitsdump Zd --filter=\"[0]>20 && cos([1])*TMath::RadToDeg()<45\"\n"
+        "\n"
+        "In --root mode, fitsdump support TFormula's syntax for all columns and the filter "
+        "You can then refer to a column or a (single) index of the column just by its name "
+        "If the index is omitted, 0 is assumed\n"
+        "\n"
+
+        "Example:\n"
+        "  fitsdump \"(Zd+Err)*TMath::DegToRad()\" --filter=\"Num>100 && Num<200\"\n"
+        "is identical to\n"
+        "  fitsdump \"(Zd[0]+Err[0])*TMath::DegToRad()\" --filter=\"Num[0]>100 && Num[0]<200\"\n"
+        "A special placeholder exists for the row number:\n"
+        "  fitsdump \"#\" --filter=\"#>10 && #<100\"\n"
+#endif
+        "\n";
+    cout << endl;
 }
 
@@ -678,4 +918,5 @@
         ("limit",       var<size_t>(size_t(0)),     "Limit for the maximum number of rows to read (0=unlimited)")
 #ifdef HAVE_ROOT
+        ("root,r",      po_switch(),                "Enable root mode")
         ("filter,r",    var<string>(""),            "Filter to restrict the selection of events (e.g. '[0]>10 && [0]<20';  does not work with stat and minmax yet)")
 #endif
