Index: /trunk/FACT++/src/fitsdump.cc
===================================================================
--- /trunk/FACT++/src/fitsdump.cc	(revision 11912)
+++ /trunk/FACT++/src/fitsdump.cc	(revision 11913)
@@ -13,4 +13,18 @@
 #include <CCfits/CCfits>
 
+//#define PLOTTING_PLEASE
+
+#ifdef PLOTTING_PLEASE
+#include <qapplication.h>
+#include <qlayout.h>
+#include <qwt_plot.h>
+#include <qwt-qt4/qwt_plot_grid.h>
+#include <QPen>
+#include <qwt-qt4/qwt_plot_curve.h>
+#include <qwt-qt4/qwt_plot_zoomer.h>
+#include <qwt-qt4/qwt_legend.h>
+#include <qwt-qt4/qwt_scale_draw.h>
+#include "Time.h"
+#endif
 using namespace std;
 
@@ -27,4 +41,21 @@
 };
 
+#ifdef PLOTTING_PLEASE
+class TimeScaleDraw: public QwtScaleDraw
+{
+public:
+    virtual QwtText label(double v) const
+    {
+        Time t(v);
+        string time = t.GetAsStr("%H:%M:%S%F");
+        while (time[time.size()-1] == '0' && time.size() > 2)
+        {
+            time = time.substr(0, time.size()-1);
+        }
+        return QwtText(time.c_str());
+    }
+};
+#endif
+
 class FitsDumper
 {
@@ -65,7 +96,11 @@
     void ListKeywords(ostream &);
 
+    bool separateColumnsFromRanges(const vector<string>& list,
+                                   vector<pair<int, int> >& ranges,
+                                   vector<string>& listNamesOnly);
     /// Perform the dumping, based on the current dump list
     bool Dump(const string &, const vector<string> &list, int);
-
+    ///Display the selected columns values VS time
+    int doCurvesDisplay( const vector<string> &list, const string& tableName);
 //    bool Plot(const vector<string> &list);
 
@@ -482,15 +517,8 @@
 }
 
-
-// --------------------------------------------------------------------------
-//
-//! Perform the actual dump, based on the current parameters
-//
-bool FitsDumper::Dump(const string &filename, const vector<string> &list, int precision)
-{
-
-    //first of all, let's separate the columns from their ranges and check that the requested columns are indeed part of the file
-    vector<pair<int, int> > ranges;
-    vector<string> listNamesOnly;
+bool FitsDumper::separateColumnsFromRanges(const vector<string>& list,
+                               vector<pair<int, int> >& ranges,
+                               vector<string>& listNamesOnly)
+{
     for (vector<string>::const_iterator it=list.begin(); it!=list.end(); it++)
     {
@@ -499,5 +527,5 @@
         unsigned long bracketIndex1 = columnNameOnly.find_first_of(']');
         unsigned long colonIndex = columnNameOnly.find_first_of(':');
-        cout << bracketIndex0 << " " << bracketIndex1 << " " << colonIndex << endl;
+//        cout << bracketIndex0 << " " << bracketIndex1 << " " << colonIndex << endl;
         int columnStart = -1;
         int columnEnd = -1;
@@ -549,4 +577,23 @@
         listNamesOnly.push_back(columnNameOnly);
     }
+    return true;
+}
+// --------------------------------------------------------------------------
+//
+//! Perform the actual dump, based on the current parameters
+//
+bool FitsDumper::Dump(const string &filename, const vector<string> &list, int precision)
+{
+
+    //first of all, let's separate the columns from their ranges and check that the requested columns are indeed part of the file
+    vector<pair<int, int> > ranges;
+    vector<string> listNamesOnly;
+
+    if (!separateColumnsFromRanges(list, ranges, listNamesOnly))
+    {
+        cerr << "Something went wrong while extracting the columns names from parameters. Aborting" << endl;
+        return false;
+    }
+
     // FIXME: Maybe do this when opening a table?
     const vector<int> offsets = CalculateOffsets();
@@ -604,31 +651,5 @@
     {
         MyColumn *cCol = static_cast<MyColumn*>(fColMap.find(*it)->second);
-        //CCfits::Column* cCol = fColMap.find(*it)->second;
         columns.push_back(cCol);
-/*        int start, end;
-        if (cCol->width() != 1)
-        {//get the desired range of that column to output
-            cout << "Column " << *it << " has " << cCol->width() << " entries. Please tell us which of them should be outputted. " << endl;
-            cout << "Please enter the first value to dump (min 0, max " << cCol->width()-1 << "): ";
-            cin >> start;
-            while (start < 0 || start > cCol->width()-1)
-            {
-                cout << "value invalid. Please stick to the range 0-" << cCol->width()-1 << ": ";
-                cin >> start;
-            }
-            cout << "Please enter the last value to dump (min " << start << ", max " << cCol->width()-1 << "): ";
-            cin >> end;
-            while (end < start || end > cCol->width()-1)
-            {
-                cout << "value invalid. Please stick to the range " << start << "-" << cCol->width()-1 << ": ";
-                cin >> end;
-            }
-            end++;
-            ranges.push_back(make_pair(start, end));
-        }
-        else
-        {
-            ranges.push_back(make_pair(0, cCol->width()));
-        }*/
     }
     const int size = offsets[offsets.size()-1];
@@ -741,4 +762,5 @@
     }
 
+
     if (conf.Get<bool>("list"))
         List();
@@ -749,4 +771,17 @@
             return -1;
     }
+
+    if (conf.Get<bool>("graph"))
+    {
+        if (!conf.Has("col"))
+        {
+            cout << "Please specify the columns that should be dumped as arguments. Aborting" << endl;
+            return 0;
+        }
+        doCurvesDisplay(conf.Get<vector<string>>("col"),
+                        conf.Get<string>("tablename"));
+        return 1;
+    }
+
 
     if (conf.Get<bool>("header"))
@@ -768,4 +803,5 @@
             return -1;
     }
+
 
     return 0;
@@ -786,5 +822,214 @@
     // 
 }
-
+#ifdef PLOTTING_PLEASE
+int FitsDumper::doCurvesDisplay( const vector<string> &list, const string& tableName)
+{
+    //first of all, let's separate the columns from their ranges and check that the requested columns are indeed part of the file
+     vector<pair<int, int> > ranges;
+     vector<string> listNamesOnly;
+     if (!separateColumnsFromRanges(list, ranges, listNamesOnly))
+     {
+         cerr << "Something went wrong while extracting the columns names from parameters. Aborting" << endl;
+         return false;
+     }
+     vector<string> curvesNames;
+     stringstream str;
+     for (auto it=ranges.begin(), jt=listNamesOnly.begin(); it != ranges.end(); it++, jt++)
+     {
+         for (int i=it->first; i<it->second;i++)
+         {
+                 str.str("");
+                 str << *jt << "[" << i << "]";
+                 curvesNames.push_back(str.str());
+         }
+     }
+     char* handle = new char[17];
+     sprintf(handle,"FitsDump Display");
+//    Qt::HANDLE h = *handle;//NULL
+    int argc = 1;
+    char ** argv = &handle;
+    QApplication a(argc, argv);
+
+
+
+    QwtPlot* plot = new QwtPlot();
+    QwtPlotGrid* grid = new QwtPlotGrid;
+    grid->enableX(false);
+    grid->enableY(true);
+    grid->enableXMin(false);
+    grid->enableYMin(false);
+    grid->setMajPen(QPen(Qt::black, 0, Qt::DotLine));
+    grid->attach(plot);
+    plot->setAutoReplot(true);
+    string title = tableName;
+    plot->setAxisScaleDraw(  QwtPlot::xBottom, new TimeScaleDraw());
+
+    QWidget window;
+    QHBoxLayout* layout = new QHBoxLayout(&window);
+    layout->setContentsMargins(0,0,0,0);
+    layout->addWidget(plot);
+
+    QwtPlotZoomer zoom(plot->canvas());
+    zoom.setRubberBandPen(QPen(Qt::gray, 2, Qt::DotLine));
+    zoom.setTrackerPen(QPen(Qt::gray));
+    int totalSize = 0;
+    for (unsigned int i=0;i<list.size();i++)
+        totalSize += ranges[i].second - ranges[i].first;
+    cout << "Total size: " << totalSize << endl;
+    vector<QwtPlotCurve*> curves(totalSize);
+    int ii=0;
+    for (auto it = curves.begin(), jt=curvesNames.begin(); it != curves.end(); it++, jt++)
+    {
+        *it = new QwtPlotCurve(jt->c_str());
+        switch (ii%6)
+        {
+        case 0:
+            (*it)->setPen(QColor(255,0,0));
+            break;
+        case 1:
+            (*it)->setPen(QColor(0,255,0));
+            break;
+        case 2:
+            (*it)->setPen(QColor(0,0,255));
+            break;
+        case 3:
+            (*it)->setPen(QColor(255,255,0));
+            break;
+        case 4:
+            (*it)->setPen(QColor(0,255,255));
+            break;
+        case 5:
+            (*it)->setPen(QColor(255,0,255));
+            break;
+        default:
+            (*it)->setPen(QColor(0,0,0));
+        };
+        ii++;
+        (*it)->setStyle(QwtPlotCurve::Lines);
+        (*it)->attach(plot);
+    }
+    plot->insertLegend(new QwtLegend(), QwtPlot::RightLegend);
+
+     const vector<int> offsets = CalculateOffsets();
+     if (offsets.size()==0)
+         return false;
+
+
+     // Loop over all columns in our list of requested columns
+      vector<MyColumn*> columns;
+      for (vector<string>::const_iterator it=listNamesOnly.begin(); it!=listNamesOnly.end(); it++)
+      {
+          MyColumn *cCol = static_cast<MyColumn*>(fColMap.find(*it)->second);
+          columns.push_back(cCol);
+      }
+      //add the time column to the given columns
+      MyColumn* timeCol = static_cast<MyColumn*>(fColMap.find("Time")->second);
+      if (!timeCol)
+      {
+          cerr << "Error: time column could not be found in given table. Aborting" << endl;
+          return false;
+      }
+      columns.push_back(timeCol);
+      ranges.push_back(make_pair(0,1));
+      /////
+      const int size = offsets[offsets.size()-1];
+      unsigned char* fitsBuffer = new unsigned char[size];
+
+//      stringstream str;
+      str.str("");
+      int status = 0;
+
+      vector<double*> xValues(totalSize);
+      double* yValues;
+      cout.precision(10);
+      str.precision(20);
+      for (auto it=xValues.begin(); it!=xValues.end(); it++)
+          *it = new double[fTable->rows()];
+
+      yValues = new double[fTable->rows()];
+
+      for (int i=1; i<=fTable->rows(); i++)
+      {
+          fits_read_tblbytes(fFile->fitsPointer(), i, 1, size, fitsBuffer, &status);
+          if (status)
+          {
+              cerr << "An error occurred while reading fits row #" << i << " error code: " << status << endl;
+              break;
+          }
+          if (WriteRow(str, columns, offsets, fitsBuffer, ranges)<0)
+          {
+              status=1;
+              cerr << "An Error occured while reading the fits row " << i << endl;
+              return -1;
+          }
+//          yValues[i-1] = i;
+          for (auto it=xValues.begin(); it!= xValues.end(); it++)
+          {
+              str >> (*it)[i-1];
+              cout << (*it)[i-1] << " ";
+          }
+          str >> yValues[i-1];
+          if (i==1)
+          {
+              Time t(yValues[0]);
+              title += " - " + t.GetAsStr("%Y-%m-%d");
+              plot->setTitle(title.c_str());
+          }
+          cout << yValues[i-1] << " ";
+          cout << endl;
+      }
+      //set the actual data.
+      auto jt = xValues.begin();
+      for (auto it=curves.begin(); it != curves.end(); it++, jt++)
+          (*it)->setRawData(yValues, *jt, fTable->rows());
+
+      QStack<QRectF> stack;
+      double minX, minY, maxX, maxY;
+      minX = minY = 1e10;
+      maxX = maxY = -1e10;
+      QRectF rect;
+      QPointF point;
+      for (auto it=curves.begin(); it!= curves.end(); it++)
+      {
+          rect = (*it)->boundingRect();
+          point = rect.bottomRight();
+          if (point.x() < minX) minX = point.x();
+          if (point.y() < minY) minY = point.y();
+          if (point.x() > maxX) maxX = point.x();
+          if (point.y() > maxY) maxY = point.y();
+          point = rect.topLeft();
+          if (point.x() < minX) minX = point.x();
+          if (point.y() < minY) minY = point.y();
+          if (point.x() > maxX) maxX = point.x();
+          if (point.y() > maxY) maxY = point.y();
+      }
+      QPointF bottomRight(maxX, minY);
+      QPointF topLeft(minX, maxY);
+      QPointF center((bottomRight+topLeft)/2.f);
+      stack.push(QRectF(topLeft + (topLeft-center)*(.5f),bottomRight + (bottomRight-center)*(.5f)));
+      zoom.setZoomStack(stack);
+
+      delete[] fitsBuffer;
+    window.resize(600, 400);
+    window.show();
+
+    a.exec();
+
+    for (auto it = curves.begin(); it != curves.end(); it++)
+        delete *it;
+    for (auto it = xValues.begin(); it != xValues.end(); it++)
+        delete[] *it;
+    delete[] yValues;
+    delete[] handle;
+    return 0;
+}
+#else
+int FitsDumper::doCurvesDisplay( const vector<string> &list, const string& tableName)
+{
+    cerr << "Sorry, but plotting features seem to have been disabled at compilation time." << endl;
+    cerr << "Please recompile with PLOTTING_PLEASE defined and try again." << endl;
+    return 0;
+}
+#endif
 void SetupConfiguration(Configuration& conf)
 {
@@ -806,4 +1051,5 @@
         ("list,l",      po_switch(),                "List all tables and columns in file")
         ("header,h",    po_switch(),                "Dump header of given table")
+        ("graph,g",      po_switch(),                "Plot the columns instead of dumping them")
         ;
 
