[GRASS-SVN] r72528 - grass/trunk/gui/wxpython/tplot

svn_grass at osgeo.org svn_grass at osgeo.org
Fri Mar 23 07:53:38 PDT 2018


Author: lucadelu
Date: 2018-03-23 07:53:38 -0700 (Fri, 23 Mar 2018)
New Revision: 72528

Modified:
   grass/trunk/gui/wxpython/tplot/frame.py
   grass/trunk/gui/wxpython/tplot/g.gui.tplot.py
Log:
g.gui.tplot: added capabilities to export plotted data in CSV file, see #3533

Modified: grass/trunk/gui/wxpython/tplot/frame.py
===================================================================
--- grass/trunk/gui/wxpython/tplot/frame.py	2018-03-23 12:23:59 UTC (rev 72527)
+++ grass/trunk/gui/wxpython/tplot/frame.py	2018-03-23 14:53:38 UTC (rev 72528)
@@ -18,6 +18,7 @@
 @author Luca Delucchi
 @author start stvds support Matej Krejci
 """
+import os
 from itertools import cycle
 import numpy as np
 
@@ -59,6 +60,8 @@
     import wx.lib.agw.flatnotebook as FN
 except ImportError:
     import wx.lib.flatnotebook as FN
+import wx.lib.filebrowsebutton as filebrowse
+
 from gui_core.widgets import GNotebook
 
 ALPHA = 0.5
@@ -100,6 +103,7 @@
         self._giface = giface
         self.datasetsV = None
         self.datasetsR = None
+        self.overwrite = False
         # self.vectorDraw=False
         # self.rasterDraw=False
         self.init()
@@ -297,6 +301,38 @@
         self.ntb.AddPage(page=self.controlPanelLabels, text=_('Labels'),
                          name='Labels')
 
+        # ------------ITEMS IN NOTEBOOK PAGE (EXPORT)------------------------
+        self.controlPanelExport = wx.Panel(parent=self.ntb, id=wx.ID_ANY)
+        self.csvLabel = wx.StaticText(parent=self.controlPanelExport,
+                                      id=wx.ID_ANY,
+                                      label=_('Path for output CSV file '
+                                              'with plotted data'))
+        self.csvButton = filebrowse.FileBrowseButton(parent=self.controlPanelExport,
+                                                     id=wx.ID_ANY,
+                                                     size=globalvar.DIALOG_GSELECT_SIZE,
+                                                     labelText='',
+                                                     dialogTitle=_('CVS path'),
+                                                     buttonText=_('Browse'),
+                                                     startDirectory=os.getcwd(),
+                                                     fileMode=wx.FD_SAVE)
+        self.headerLabel = wx.StaticText(parent=self.controlPanelExport,
+                                         id=wx.ID_ANY,
+                                         label=_('Do you want the CSV header?'
+                                                 ))
+        self.headerCheck = wx.CheckBox(parent=self.controlPanelExport,
+                                         id=wx.ID_ANY)
+        self.controlPanelSizerCheck = wx.BoxSizer(wx.HORIZONTAL)
+        self.controlPanelSizerCheck.Add(self.headerCheck)
+        self.controlPanelSizerCheck.Add(self.headerLabel)
+        self.controlPanelSizerExport = wx.BoxSizer(wx.VERTICAL)
+        self.controlPanelSizerExport.Add(self.csvLabel)
+        self.controlPanelSizerExport.Add(self.csvButton)
+        self.controlPanelSizerExport.Add(self.controlPanelSizerCheck)
+        self.controlPanelExport.SetSizer(self.controlPanelSizerExport)
+        self.controlPanelSizerCheck.Fit(self)
+        self.controlPanelSizerExport.Fit(self)
+        self.ntb.AddPage(page=self.controlPanelExport, text=_('Export'),
+                         name='Export')
 
         # ------------Buttons on the bottom(draw,help)------------
         self.vButtPanel = wx.Panel(self.mainPanel, id=wx.ID_ANY)
@@ -607,8 +643,24 @@
             self.axes2d.set_ylabel(', '.join(self.yticksNames))
         if self.drawTitle != '':
             self.axes2d.set_title(self.drawTitle)
+
+    def _writeCSV(self, x, y):
+        """Used to write CSV file of plotted data"""
+        import csv
+        if len(y) > 1:
+            zipped = zip(x, *y)
+        else:
+            zipped = zip(x, y)
+        with open(self.csvpath, "wb") as fi:
+            writer = csv.writer(fi)
+            if self.header:
+                head = ["Time"]
+                head.extend(self.yticksNames)
+                writer.writerow(head)
+            writer.writerows(zipped)
         
     def drawR(self):
+        ycsv = []
         for i, name in enumerate(self.datasetsR):
             name = name[0]
             # just name; with mapset it would be long
@@ -616,6 +668,7 @@
             self.yticksPos.append(1)  # TODO
             xdata = []
             ydata = []
+            xcsv = []
             for keys, values in self.timeDataR[name].iteritems():
                 if keys in ['temporalType', 'granularity', 'validTopology',
                             'unit', 'temporalDataType']:
@@ -622,6 +675,7 @@
                     continue
                 xdata.append(self.convert(values['start_datetime']))
                 ydata.append(values['value'])
+                xcsv.append(values['start_datetime'])
 
             if len(ydata) == ydata.count(None):
                 GError(parent=self, showTraceback=False,
@@ -634,7 +688,11 @@
             self.plots.append(self.axes2d.plot(xdata, ydata, marker='o',
                                                color=color,
                                                label=self.plotNameListR[i])[0])
+            if self.csvpath:
+                ycsv.append(ydata)
 
+        if self.csvpath:
+            self._writeCSV(xcsv, ycsv)
         self._setLabels(self.timeDataR[name]['granularity'])
         # legend
         handles, labels = self.axes2d.get_legend_handles_labels()
@@ -641,6 +699,7 @@
         self.axes2d.legend(loc=0)
 
     def drawVCats(self):
+        ycsv = []
         for i, name in enumerate(self.plotNameListV):
             # just name; with mapset it would be long
             labelname = name.replace('+', ' ')
@@ -650,6 +709,7 @@
             self.yticksPos.append(1)  # TODO
             xdata = []
             ydata = []
+            xcsv = []
             for keys, values in self.timeDataV[
                     name_cat[0]][
                     name_cat[1]].iteritems():
@@ -661,6 +721,7 @@
                     ydata.append(None)
                 else:
                     ydata.append(values['value'])
+                xcsv.append(values['start_datetime'])
 
             if len(ydata) == ydata.count(None):
                 GError(parent=self, showTraceback=False,
@@ -680,7 +741,11 @@
                     marker='o',
                     color=color,
                     label=labelname)[0])
-        # ============================
+            if self.csvpath:
+                ycsv.append(ydata)
+
+        if self.csvpath:
+            self._writeCSV(xcsv, ycsv)
         self._setLabels(self.timeDataV[name]['granularity'])
 
         # legend
@@ -689,6 +754,7 @@
         self.listWhereConditions = []
 
     def drawV(self):
+        ycsv = []
         for i, name in enumerate(self.plotNameListV):
             # just name; with mapset it would be long
             self.yticksNames.append(self.attribute.GetValue())
@@ -695,6 +761,7 @@
             self.yticksPos.append(0)  # TODO
             xdata = []
             ydata = []
+            xcsv = []
             for keys, values in self.timeDataV[name].iteritems():
                 if keys in ['temporalType', 'granularity', 'validTopology',
                             'unit', 'temporalDataType']:
@@ -701,6 +768,7 @@
                     continue
                 xdata.append(self.convert(values['start_datetime']))
                 ydata.append(values['value'])
+                xcsv.append(values['start_datetime'])
 
             if len(ydata) == ydata.count(None):
                 GError(parent=self, showTraceback=False,
@@ -713,7 +781,11 @@
 
             self.plots.append(self.axes2d.plot(xdata, ydata, marker='o',
                                                color=color, label=name)[0])
-        # ============================
+            if self.csvpath:
+                ycsv.append(ydata)
+
+        if self.csvpath:
+            self._writeCSV(xcsv, ycsv)
         self._setLabels(self.timeDataV[name]['granularity'])
 
         # legend
@@ -723,6 +795,19 @@
 
     def OnRedraw(self, event=None):
         """Required redrawing."""
+        self.csvpath = self.csvButton.GetValue()
+        self.header = self.headerCheck.IsChecked()
+        if (os.path.exists(self.csvpath) and not self.overwrite):
+            dlg = wx.MessageDialog(self, _("{pa} already exists, do you want "
+                                   "to overwrite?".format(pa=self.csvpath)),
+                                   _("File exists"), 
+                                   wx.OK | wx.CANCEL | wx.ICON_QUESTION)
+            if dlg.ShowModal() != wx.ID_OK:
+                dlg.Destroy()
+                GError(parent=self, showTraceback=False,
+                       message=_("Please change name of output CSV file or "))
+                return
+            dlg.Destroy()
         self.init()
         datasetsR = self.datasetSelectR.GetValue().strip()
         datasetsV = self.datasetSelectV.GetValue().strip()
@@ -879,7 +964,7 @@
         RunCommand(prog='g.manual', quiet=True, entry='g.gui.tplot')
 
     def SetDatasets(self, rasters, vectors, coors, cats, attr, title, xlabel,
-                    ylabel):
+                    ylabel, csvfile, head, overwrite):
         """Set the data
         :param list rasters: a list of temporal raster dataset's name
         :param list vectors: a list of temporal vector dataset's name
@@ -927,6 +1012,10 @@
             self.x.SetValue(xlabel)
         if ylabel:
             self.y.SetValue(ylabel)
+        if csvfile:
+            self.csvpath = csvfile
+        self.header = head
+        self.overwrite = overwrite
         self._redraw()
 
     def OnVectorSelected(self, event):

Modified: grass/trunk/gui/wxpython/tplot/g.gui.tplot.py
===================================================================
--- grass/trunk/gui/wxpython/tplot/g.gui.tplot.py	2018-03-23 12:23:59 UTC (rev 72527)
+++ grass/trunk/gui/wxpython/tplot/g.gui.tplot.py	2018-03-23 14:53:38 UTC (rev 72528)
@@ -27,6 +27,11 @@
 #% keywords: temporal
 #%end
 
+#%flag
+#% key: h
+#% description: Set the header of CSV file, to be used with csv option
+#%end
+
 #%option G_OPT_STVDS_INPUTS
 #% key: stvds
 #% required: no
@@ -58,10 +63,17 @@
 
 #%option G_OPT_F_OUTPUT
 #% required: no
-#% label: Name for output file
-#% description: Add extension to specify format (.png, .pdf, .svg)
+#% label: Name for output graphical file
+#% description: Full path for output file containing the plot, ddd extension to specify format (.png, .pdf, .svg)
 #%end
 
+#%option G_OPT_F_OUTPUT
+#% key: csv
+#% required: no
+#% label: Name for output CSV file
+#% description: Full path for the CSV file containing the plotted data
+#%end
+
 #%option
 #% key: title
 #% label: Title for plot
@@ -141,10 +153,13 @@
     ylabel = None
     if options['ylabel']:
         ylabel = options['ylabel']
+    csvfile = None
+    if options['csv']:
+        csvfile = options['csv']
     app = wx.App()
     frame = TplotFrame(parent=None, giface=StandaloneGrassInterface())
     frame.SetDatasets(rasters, vectors, coords, cats, attr, title, xlabel,
-                      ylabel)
+                      ylabel, csvfile, flags['h'], gscript .overwrite)
     if output:
         frame.OnRedraw()
         if options['size']:



More information about the grass-commit mailing list