[GRASS-SVN] r62588 - grass/trunk/gui/wxpython/dbmgr

svn_grass at osgeo.org svn_grass at osgeo.org
Tue Nov 4 04:22:00 PST 2014


Author: martinl
Date: 2014-11-04 04:22:00 -0800 (Tue, 04 Nov 2014)
New Revision: 62588

Modified:
   grass/trunk/gui/wxpython/dbmgr/base.py
Log:
wxGUI/dbmgr: fix ids for contextual menu
             add null/stddev to field statistics
             fix field statistics for DBF driver


Modified: grass/trunk/gui/wxpython/dbmgr/base.py
===================================================================
--- grass/trunk/gui/wxpython/dbmgr/base.py	2014-11-04 07:54:27 UTC (rev 62587)
+++ grass/trunk/gui/wxpython/dbmgr/base.py	2014-11-04 12:22:00 UTC (rev 62588)
@@ -35,6 +35,7 @@
 import tempfile
 import copy
 import types
+import math
 
 from core import globalvar
 import wx
@@ -399,68 +400,66 @@
         
         popupMenu = wx.Menu()
 
-        if not hasattr (self, "popupID1"):
-            #TODO put to dict
-            self.popupID1 = wx.NewId()
-            self.popupID2 = wx.NewId()
-            self.popupID3 = wx.NewId()
-            self.popupID4 = wx.NewId()
-            self.popupID5 = wx.NewId()
-            self.popupID6 = wx.NewId()
-            self.popupID7 = wx.NewId()
-            self.popupID8 = wx.NewId()
-            self.popupID9 = wx.NewId()
-            self.popupID10 = wx.NewId()
-            self.popupID11 = wx.NewId()
-            self.popupID12 = wx.NewId()
-            self.popupID13 = wx.NewId()
-            self.popupID14 = wx.NewId()
-
-        popupMenu.Append(self.popupID1, text = _("Sort ascending"))
-        popupMenu.Append(self.popupID2, text = _("Sort descending"))
+        if not hasattr (self, "popupID"):
+            self.popupId = { 'sortAsc' : wx.NewId(),
+                             'sortDesc' : wx.NewId(),
+                             'calculate' : wx.NewId(),
+                             'area' : wx.NewId(),
+                             'length' : wx.NewId(),
+                             'compact' : wx.NewId(),
+                             'fractal' : wx.NewId(),
+                             'perimeter' : wx.NewId(),
+                             'ncats' : wx.NewId(),
+                             'slope' : wx.NewId(),
+                             'lsin' : wx.NewId(),
+                             'lazimuth' : wx.NewId(),
+                             'calculator' : wx.NewId(),
+                             'stats' : wx.NewId() }
+        
+        popupMenu.Append(self.popupId['sortAsc'], text = _("Sort ascending"))
+        popupMenu.Append(self.popupId['sortDesc'], text = _("Sort descending"))
         popupMenu.AppendSeparator()
         subMenu = wx.Menu()
-        popupMenu.AppendMenu(self.popupID3, _("Calculate (only numeric columns)"),
+        popupMenu.AppendMenu(self.popupId['calculate'], _("Calculate (only numeric columns)"),
                              subMenu)
-        popupMenu.Append(self.popupID13, text = _("Field calculator"))
+        popupMenu.Append(self.popupId['calculator'], text = _("Field calculator"))
         popupMenu.AppendSeparator()
-        popupMenu.Append(self.popupID14, text = _("Statistics"))
+        popupMenu.Append(self.popupId['stats'], text = _("Statistics"))
         
         if not self.pages['manageTable']:
             popupMenu.AppendSeparator()
-            self.popupID14 = wx.NewId()
-            popupMenu.Append(self.popupID14, text = _("Add column"))
+            self.popupId['addCol'] = wx.NewId()
+            popupMenu.Append(self.popupId['addCol'], text = _("Add column"))
             if not self.dbMgrData['editable']:
-                popupMenu.Enable(self.popupID14, False)
+                popupMenu.Enable(self.popupId['addCol'], False)
 
         if not self.dbMgrData['editable']:
-            popupMenu.Enable(self.popupID13, False)
+            popupMenu.Enable(self.popupId['calculator'], False)
           
         if not self.dbMgrData['editable'] or \
                 self.columns[self.GetColumn(self._col).GetText()]['ctype'] not in (types.IntType, types.FloatType):
-            popupMenu.Enable(self.popupID3, False)
-            popupMenu.Enable(self.popupID14, False)
+            popupMenu.Enable(self.popupId['calculate'], False)
         
-        subMenu.Append(self.popupID4,  text = _("Area size"))
-        subMenu.Append(self.popupID5,  text = _("Line length"))
-        subMenu.Append(self.popupID6,  text = _("Compactness of an area"))
-        subMenu.Append(self.popupID7,  text = _("Fractal dimension of boundary defining a polygon"))
-        subMenu.Append(self.popupID8,  text = _("Perimeter length of an area"))
-        subMenu.Append(self.popupID9,  text = _("Number of features for each category"))
-        subMenu.Append(self.popupID10, text = _("Slope steepness of 3D line"))
-        subMenu.Append(self.popupID11, text = _("Line sinuousity"))
-        subMenu.Append(self.popupID12, text = _("Line azimuth"))
+        subMenu.Append(self.popupId['area'],  text = _("Area size"))
+        subMenu.Append(self.popupId['length'],  text = _("Line length"))
+        subMenu.Append(self.popupId['compact'],  text = _("Compactness of an area"))
+        subMenu.Append(self.popupId['fractal'],  text = _("Fractal dimension of boundary defining a polygon"))
+        subMenu.Append(self.popupId['perimeter'],  text = _("Perimeter length of an area"))
+        subMenu.Append(self.popupId['ncats'],  text = _("Number of features for each category"))
+        subMenu.Append(self.popupId['slope'], text = _("Slope steepness of 3D line"))
+        subMenu.Append(self.popupId['lsin'], text = _("Line sinuousity"))
+        subMenu.Append(self.popupId['lazimuth'], text = _("Line azimuth"))
         
-        self.Bind (wx.EVT_MENU, self.OnColumnSortAsc, id = self.popupID10)
-        self.Bind (wx.EVT_MENU, self.OnColumnSortDesc, id = self.popupID2)
-        self.Bind(wx.EVT_MENU, self.OnFieldCalculator, id = self.popupID13)
-        self.Bind(wx.EVT_MENU, self.OnFieldStatistics, id = self.popupID14)
+        self.Bind (wx.EVT_MENU, self.OnColumnSortAsc,  id = self.popupId['sortAsc'])
+        self.Bind (wx.EVT_MENU, self.OnColumnSortDesc, id = self.popupId['sortDesc'])
+        self.Bind(wx.EVT_MENU, self.OnFieldCalculator, id = self.popupId['calculator'])
+        self.Bind(wx.EVT_MENU, self.OnFieldStatistics, id = self.popupId['stats'])
         if not self.pages['manageTable']:
-            self.Bind(wx.EVT_MENU, self.OnAddColumn, id = self.popupID14)
+            self.Bind(wx.EVT_MENU, self.OnAddColumn, id = self.popupId['addCol'])
 
-        for id in (self.popupID4, self.popupID5, self.popupID6,
-                   self.popupID7, self.popupID8, self.popupID9,
-                   self.popupID10, self.popupID11, self.popupID12):
+        for id in (self.popupId['area'], self.popupId['length'], self.popupId['compact'],
+                   self.popupId['fractal'], self.popupId['perimeter'], self.popupId['ncats'],
+                   self.popupId['slope'], self.popupId['lsin'], self.popupId['lazimuth']):
             self.Bind(wx.EVT_MENU, self.OnColumnCompute, id = id)
 
         self.PopupMenu(popupMenu)
@@ -489,23 +488,23 @@
         id = event.GetId()
         
         option = None
-        if id == self.popupID4:
+        if id == self.popupId['area']:
             option = 'area'
-        elif id == self.popupID5:
+        elif id == self.popupId['length']:
             option = 'length'
-        elif id == self.popupID6:
+        elif id == self.popupId['compact']:
             option = 'compact'
-        elif id == self.popupID7:
+        elif id == self.popupId['fractal']:
             option = 'fd'
-        elif id == self.popupID8:
+        elif id == self.popupId['perimeter']:
             option = 'perimeter'
-        elif id == self.popupID9:
+        elif id == self.popupId['ncats']:
             option = 'count'
-        elif id == self.popupID10:
+        elif id == self.popupId['slope']:
             option = 'slope'
-        elif id == self.popupID11:
+        elif id == self.popupId['lsin']:
             option = 'sinuous'
-        elif id == self.popupID12:
+        elif id == self.popupId['lazimuth']:
             option = 'azimuth'
         
         if not option:
@@ -3389,17 +3388,21 @@
         """
         self.parent = parent
         wx.Frame.__init__(self, parent, id, style = style, **kwargs)
+        
         self.SetTitle(_("Field statistics"))
+        self.SetIcon(wx.Icon(os.path.join(globalvar.ICONDIR, 'grass_sql.ico'), wx.BITMAP_TYPE_ICO))
+
+        self.panel = wx.Panel(parent = self, id = wx.ID_ANY)
         
-        self.sp = scrolled.ScrolledPanel(parent=self, id=wx.ID_ANY, size=(300, 200),
+        self.sp = scrolled.ScrolledPanel(parent=self.panel, id=wx.ID_ANY, size=(250, 150),
                                          style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER, name="Statistics" )
         self.text = wx.TextCtrl(parent=self.sp, id=wx.ID_ANY, style=wx.TE_MULTILINE|wx.TE_READONLY)
         self.text.SetBackgroundColour("white")
                 
         # buttons
-        self.btnClipboard = wx.Button(self, id = wx.ID_COPY)
+        self.btnClipboard = wx.Button(parent=self.panel, id = wx.ID_COPY)
         self.btnClipboard.SetToolTipString(_("Copy statistics the clipboard (Ctrl+C)"))
-        self.btnCancel = wx.Button(self, wx.ID_CLOSE)
+        self.btnCancel = wx.Button(parent=self.panel, id=wx.ID_CLOSE)
         self.btnCancel.SetDefault()
 
         # bindings
@@ -3423,7 +3426,7 @@
         sizer.Add(item = self.sp, proportion = 1, flag = wx.GROW |
                   wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 3)
 
-        line = wx.StaticLine(parent = self, id = wx.ID_ANY,
+        line = wx.StaticLine(parent = self.panel, id = wx.ID_ANY,
                              size = (20, -1), style = wx.LI_HORIZONTAL)
         sizer.Add(item = line, proportion = 0,
                   flag = wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, border = 3)
@@ -3435,8 +3438,8 @@
                      flag = wx.ALIGN_RIGHT | wx.ALL, border = 5)        
         sizer.Add(item = btnSizer, proportion = 0, flag = wx.ALIGN_RIGHT | wx.ALL, border = 5)
 
-        self.SetSizer(sizer)
-        sizer.Fit(self)
+        self.panel.SetSizer(sizer)
+        sizer.Fit(self.panel)
 
     def OnCopy(self, event):
         """!Copy the statistics to the clipboard
@@ -3456,14 +3459,23 @@
 
     def Update(self, driver, database, table, column):
         """!Update statistics for given column
-
+        
         :param: column column name
         """
+        if driver == 'dbf':
+            GError(parent=self,
+                   message=_("Statistics is not support for DBF tables."))
+            self.Close()
+            return
+        
         fd, sqlFilePath = tempfile.mkstemp(text=True)
         sqlFile = open(sqlFilePath, 'w')
-        stats = ['count', 'min', 'max', 'avg', 'sum']
+        stats = ['count', 'min', 'max', 'avg', 'sum', 'null']
         for fn in stats:
-            sqlFile.write('select %s(%s) from %s;%s' % (fn, column, table, os.linesep))
+            if fn == 'null':
+                sqlFile.write('select count(*) from %s where %s is null;%s' % (table, column, os.linesep))
+            else:
+                sqlFile.write('select %s(%s) from %s;%s' % (fn, column, table, os.linesep))
         sqlFile.close()
         
         dataStr = RunCommand('db.select',
@@ -3474,15 +3486,40 @@
                              driver = driver,
                              database = database)
         if not dataStr:
+            GError(parent = self.parent,
+                   message = _("Unable to calculte statistics."))
+            self.Close()
             return
+        
         dataLines = dataStr.splitlines()
         if len(dataLines) != len(stats):
             GError(parent = self.parent,
                    message = _("Unable to calculte statistics. "
                                "Invalid number of lines %d (should be %d).") % (len(dataLines), len(stats)))
-            
+            self.Close()
+            return
+        
+        # calculate stddev
+        avg = float(dataLines[stats.index('avg')])
+        count = float(dataLines[stats.index('count')])
+        sql = "select (%(column)s - %(avg)f)*(%(column)s - %(avg)f) from %(table)s" % { 'column' : column, 'avg' : avg, 'table' : table }
+        dataVar = RunCommand('db.select',
+                             parent = self.parent,
+                             read = True,
+                             flags='c',
+                             sql = sql,
+                             driver = driver,
+                             database = database)
+        if not dataVar:
+            GWarning(parent = self.parent,
+                     message = _("Unable to calculte standard deviation."))
+        varSum = 0
+        for var in dataVar.splitlines():
+            varSum += float(var)
+        stddev = math.sqrt(varSum/count)
+        
         self.SetTitle(_("Field statistics <%s>") % column)
         self.text.Clear()
         for idx in range(len(stats)):
             self.text.AppendText('%s: %s\n' % (stats[idx], dataLines[idx]))
-                
+        self.text.AppendText('stddev: %f\n' % stddev)



More information about the grass-commit mailing list