[GRASS-SVN] r57284 - grass/trunk/gui/wxpython/iclass
svn_grass at osgeo.org
svn_grass at osgeo.org
Fri Jul 26 17:04:35 PDT 2013
Author: turek
Date: 2013-07-26 17:04:35 -0700 (Fri, 26 Jul 2013)
New Revision: 57284
Modified:
grass/trunk/gui/wxpython/iclass/dialogs.py
grass/trunk/gui/wxpython/iclass/frame.py
grass/trunk/gui/wxpython/iclass/plots.py
grass/trunk/gui/wxpython/iclass/statistics.py
Log:
wx.iclass: added interface for statistics data
Modified: grass/trunk/gui/wxpython/iclass/dialogs.py
===================================================================
--- grass/trunk/gui/wxpython/iclass/dialogs.py 2013-07-26 18:18:10 UTC (rev 57283)
+++ grass/trunk/gui/wxpython/iclass/dialogs.py 2013-07-27 00:04:35 UTC (rev 57284)
@@ -154,8 +154,8 @@
label = " %s " % _("Classes"))
sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
gridSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
- self.catList = CategoryListCtrl(panel, mapwindow = parent, statistics = parent.statisticsDict,
- statisticsList = parent.statisticsList)
+ self.catList = CategoryListCtrl(panel, mapwindow = parent,
+ stats_data = parent.stats_data)
addButton = wx.Button(panel, id = wx.ID_ADD)
deleteButton = wx.Button(panel, id = wx.ID_DELETE)
@@ -187,8 +187,8 @@
self.Layout()
def OnAddCategory(self, event):
- if self.parent.statisticsList:
- cat = max(self.parent.statisticsList) + 1
+ if self.parent.stats_data.GetCategories():
+ cat = max(self.parent.stats_data.GetCategories()) + 1
else:
cat = 1
defaultName = 'class' + '_' + str(cat) # intentionally not translatable
@@ -221,16 +221,13 @@
when deleting class (category).
It uses virtual data in the terms of @c wx.ListCtrl.
- @todo statistics and categories are managed here directly,
- it could be better to use some interface
@todo delete vector features after deleting class
"""
- def __init__(self, parent, mapwindow, statistics, statisticsList, id = wx.ID_ANY):
+ def __init__(self, parent, mapwindow, stats_data, id = wx.ID_ANY):
"""!
@param parent gui parent
@param mapwindow mapwindow instance with iclass toolbar and remove raster method
- @param statistics dictionary of statistics (defined in statistics.py)
- @param statisticsList list of statistics
+ @param stats_data StatisticsData instance (defined in statistics.py)
@param id wx id
"""
wx.ListCtrl.__init__(self, parent, id,
@@ -239,9 +236,8 @@
(_('Color'), 'color'))
self.Populate(columns = self.columns)
self.mapWindow = mapwindow
- self.statisticsDict = statistics
- self.statisticsList = statisticsList
- self.SetItemCount(len(statisticsList))
+ self.stats_data = stats_data
+ self.SetItemCount(len(self.stats_data.GetCategories()))
self.rightClickedItemIdx = wx.NOT_FOUND
@@ -254,7 +250,15 @@
self.Bind(wx.EVT_COMMAND_RIGHT_CLICK, self.OnClassRightUp) #wxMSW
self.Bind(wx.EVT_RIGHT_UP, self.OnClassRightUp) #wxGTK
-
+
+ self.stats_data.statisticsAdded.connect(self.Update)
+ self.stats_data.statisticsDeleted.connect(self.Update)
+ self.stats_data.allStatisticsDeleted.connect(self.Update)
+ self.stats_data.statisticsSet.connect(self.Update)
+
+ def Update(self):
+ self.SetItemCount(len(self.stats_data.GetCategories()))
+
def SetVirtualData(self, row, column, text):
attr = self.columns[column][1]
if attr == 'name':
@@ -263,7 +267,10 @@
except UnicodeEncodeError:
GMessage(parent = self, message = _("Please use only ASCII characters."))
return
- setattr(self.statisticsDict[self.statisticsList[row]], attr, text)
+
+
+ cat = self.stats_data.GetCategories()[row]
+ self.stats_data.GetStatistics(cat).SetStatistics(stats = {attr : text})
self.UpdateChoice()
toolbar = self.mapWindow.toolbars['iClass']
@@ -284,41 +291,46 @@
def AddCategory(self, cat, name, color):
"""!Add category record (used when importing areas)"""
- st = Statistics()
- st.SetBaseStatistics(cat = cat, name = name, color = color)
- self.statisticsDict[cat] = st
- self.statisticsList.append(cat)
- self.SetItemCount(len(self.statisticsList))
+
+ self.stats_data.AddStatistics(cat, name, color)
+ self.SetItemCount(len(self.stats_data.GetCategories()))
self.UpdateChoice()
self.mapWindow.UpdateChangeState(changes = True)
def DeleteCategory(self):
indexList = sorted(self.GetSelectedIndices(), reverse = True)
- cats = []
+ del_cats = []
+ cats = self.stats_data.GetCategories()
+
for i in indexList:
# remove temporary raster
- name = self.statisticsDict[self.statisticsList[i]].rasterName
+ cat = cats[i]
+ stat = self.stats_data.GetStatistics(cat)
+
+ name = stat.rasterName
self.mapWindow.RemoveTempRaster(name)
- cats.append(self.statisticsList[i])
- del self.statisticsDict[self.statisticsList[i]]
- del self.statisticsList[i]
+ del_cats.append(cat)
+ self.stats_data.DeleteStatistics(cat)
- self.SetItemCount(len(self.statisticsList))
+ self.SetItemCount(len(self.stats_data.GetCategories()))
self.UpdateChoice()
self.mapWindow.UpdateChangeState(changes = True)
- self.mapWindow.DeleteAreas(cats = cats)
+ self.mapWindow.DeleteAreas(cats = del_cats)
def UpdateChoice(self):
toolbar = self.mapWindow.toolbars['iClass']
name = toolbar.GetSelectedCategoryName()
catNames = []
- for cat in self.statisticsList:
- catNames.append(self.statisticsDict[cat].name)
- toolbar.SetCategories(catNames = catNames, catIdx = self.statisticsList)
+
+ cats = self.stats_data.GetCategories()
+ for cat in cats:
+ stat = self.stats_data.GetStatistics(cat)
+ catNames.append(stat.name)
+ toolbar.SetCategories(catNames = catNames, catIdx = cats)
if name in catNames:
toolbar.choice.SetStringSelection(name)
elif catNames:
@@ -361,11 +373,12 @@
def OnCategorySelected(self, event):
"""!Highlight selected areas"""
indexList = self.GetSelectedIndices()
- cats = []
+ sel_cats = []
+ cats = self.stats_data.GetCategories()
for i in indexList:
- cats.append(self.statisticsList[i])
+ sel_cats.append(cats[i])
- self.mapWindow.HighlightCategory(cats)
+ self.mapWindow.HighlightCategory(sel_cats)
if event:
event.Skip()
@@ -388,7 +401,7 @@
def OnZoomToAreasByCat(self, event):
"""!Zoom to areas of given category"""
- cat = self.statisticsList[self.rightClickedItemIdx]
+ cat = self.stats_data.GetCategories()[self.rightClickedItemIdx]
self.mapWindow.ZoomToAreasByCat(cat)
def DeselectAll(self):
@@ -401,8 +414,9 @@
self.OnCategorySelected(None)
def OnGetItemText(self, item, col):
- cat = self.statisticsList[item]
- return getattr(self.statisticsDict[cat], self.columns[col][1])
+ cat = self.stats_data.GetCategories()[item]
+ stat = self.stats_data.GetStatistics(cat)
+ return getattr(stat, self.columns[col][1])
def OnGetItemImage(self, item):
return -1
Modified: grass/trunk/gui/wxpython/iclass/frame.py
===================================================================
--- grass/trunk/gui/wxpython/iclass/frame.py 2013-07-26 18:18:10 UTC (rev 57283)
+++ grass/trunk/gui/wxpython/iclass/frame.py 2013-07-27 00:04:35 UTC (rev 57284)
@@ -57,12 +57,12 @@
from iclass.digit import IClassVDigitWindow, IClassVDigit
from iclass.toolbars import IClassMapToolbar, IClassMiscToolbar,\
IClassToolbar, IClassMapManagerToolbar
-from iclass.statistics import Statistics, BandStatistics
+from iclass.statistics import StatisticsData, Statistics, BandStatistics
from iclass.dialogs import CategoryListCtrl, IClassCategoryManagerDialog,\
IClassGroupDialog, IClassSignatureFileDialog,\
IClassExportAreasDialog, IClassMapDialog
from iclass.plots import PlotPanel
-
+
class IClassMapFrame(DoubleMapFrame):
"""! wxIClass main frame
@@ -158,13 +158,13 @@
# dialogs
self.dialogs = dict()
self.dialogs['classManager'] = None
+ self.dialogs['scatt_plot'] = None
# just to make digitizer happy
self.dialogs['attributes'] = None
self.dialogs['category'] = None
# PyPlot init
- self.plotPanel = PlotPanel(self, statDict = self.statisticsDict,
- statList = self.statisticsList)
+ self.plotPanel = PlotPanel(self, stats_data = self.stats_data)
self._addPanes()
self._mgr.Update()
@@ -193,8 +193,8 @@
I_iclass_free_statistics(st)
self.RemoveTempVector()
- for i in self.statisticsList:
- self.RemoveTempRaster(self.statisticsDict[i].rasterName)
+ for i in self.stats_data.GetCategories():
+ self.RemoveTempRaster(self.stats_data.GetStatistics(i).rasterName)
def OnHelp(self, event):
"""!Show help page"""
@@ -396,8 +396,8 @@
@return 'R:G:B'
"""
- if cat in self.statisticsDict:
- return self.statisticsDict[cat].color
+ if cat in self.stats_data.GetCategories():
+ return self.stats_data.GetStatistics(cat).color
return '0:0:0'
def OnZoomMenu(self, event):
@@ -474,7 +474,7 @@
def OnImportAreas(self, event):
"""!Import training areas"""
# check if we have any changes
- if self.GetAreasCount() or self.statisticsList:
+ if self.GetAreasCount() or self.stats_data.GetCategories():
qdlg = wx.MessageDialog(parent = self,
message = _("All changes will be lost. "
"Do you want to continue?") ,
@@ -558,12 +558,11 @@
self.poMapInfo = self.GetFirstWindow().digit.GetDisplay().poMapInfo
# remove temporary rasters
- for i in self.statisticsList:
- self.RemoveTempRaster(self.statisticsDict[i].rasterName)
+ for cat in self.stats_data.GetCategories():
+ self.RemoveTempRaster(self.stats_data.GetStatistics(cat).rasterName)
# clear current statistics
- self.statisticsDict.clear()
- del self.statisticsList[:] # not ...=[] !
+ self.stats_data.DeleteAllStatistics()
# reset plots
self.plotPanel.Reset()
@@ -658,7 +657,7 @@
if self.ExportAreas(vectorName = vName, withTable = withTable):
GMessage(_("%d training areas (%d classes) exported to vector map <%s>.") % \
- (self.GetAreasCount(), len(self.statisticsList),
+ (self.GetAreasCount(), len(self.stats_data.GetCategories()),
self.exportVector), parent = self)
def ExportAreas(self, vectorName, withTable):
@@ -716,8 +715,8 @@
return False
# populate table
- for cat in self.statisticsList:
- stat = self.statisticsDict[cat]
+ for cat in self.stats_data.GetCategories():
+ stat = self.stats_data.GetStatistics(cat)
self._runDBUpdate(map = vectorName, column = "class", value = stat.name, cat = cat)
self._runDBUpdate(map = vectorName, column = "color", value = stat.color, cat = cat)
@@ -769,13 +768,14 @@
Updates number of stddev, histograms, layer in preview display.
"""
- nstd = self.statisticsDict[currentCat].nstd
+ stat = self.stats_data.GetStatistics(currentCat)
+ nstd = stat.nstd
self.toolbars['iClass'].UpdateStddev(nstd)
self.plotPanel.UpdateCategory(currentCat)
self.plotPanel.OnPlotTypeSelected(None)
- name = self.statisticsDict[currentCat].rasterName
+ name = stat.rasterName
name = self.previewMapManager.GetAlias(name)
if name:
self.previewMapManager.SelectLayer(name)
@@ -804,12 +804,12 @@
def UpdateRasterName(self, newName, cat):
"""!Update alias of raster map when category name is changed"""
- origName = self.statisticsDict[cat].rasterName
+ origName = self.stats_data.GetStatistics(cat).rasterName
self.previewMapManager.SetAlias(origName, newName)
def StddevChanged(self, cat, nstd):
"""!Standard deviation multiplier changed, rerender map, histograms"""
- stat = self.statisticsDict[cat]
+ stat = self.stats_data.GetStatistics(cat)
stat.nstd = nstd
if not stat.IsReady():
@@ -867,8 +867,7 @@
if self.RunAnalysis():
currentCat = self.GetCurrentCategoryIdx()
self.plotPanel.UpdatePlots(group = self.group, currentCat = currentCat,
- statDict = self.statisticsDict,
- statList = self.statisticsList)
+ stats_data = self.stats_data)
def RunAnalysis(self):
"""!Run analysis
@@ -893,9 +892,12 @@
I_free_signatures(self.signatures)
I_iclass_init_signatures(self.signatures, self.refer)
- cats = self.statisticsList[:]
+ # why create copy
+ #cats = self.statisticsList[:]
+
+ cats = self.stats_data.GetCategories()
for i in cats:
- stats = self.statisticsDict[i]
+ stats = self.stats_data.GetStatistics(i)
statistics_obj = IClass_statistics()
statistics = pointer(statistics_obj)
@@ -912,10 +914,12 @@
# tests
self.cStatisticsDict[i] = statistics
- stats.SetStatistics(statistics)
+ stats.SetFromcStatistics(statistics)
stats.SetReady()
- self.statisticsDict[stats.category] = stats
+ # stat is already part of stats_data?
+ #self.statisticsDict[stats.category] = stats
+
self.ConvertToNull(name = stats.rasterName)
self.previewMapManager.AddLayer(name = stats.rasterName,
alias = stats.name, resultsLayer = True)
@@ -977,8 +981,7 @@
self.group = None
self.sigFile = None
- self.statisticsDict = {}
- self.statisticsList = []
+ self.stats_data = StatisticsData()
self.cStatisticsDict = {}
Modified: grass/trunk/gui/wxpython/iclass/plots.py
===================================================================
--- grass/trunk/gui/wxpython/iclass/plots.py 2013-07-26 18:18:10 UTC (rev 57283)
+++ grass/trunk/gui/wxpython/iclass/plots.py 2013-07-27 00:04:35 UTC (rev 57284)
@@ -28,15 +28,14 @@
for each band and for one category. Coincidence plots show min max range
of classes for each band.
"""
- def __init__(self, parent, statDict, statList):
+ def __init__(self, parent, stats_data):
scrolled.ScrolledPanel.__init__(self, parent)
self.SetupScrolling(scroll_x = False, scroll_y = True)
self.parent = parent
self.canvasList = []
self.bandList = []
- self.statDict = statDict
- self.statList = statList
+ self.stats_data = stats_data
self.currentCat = None
self.mainSizer = wx.BoxSizer(wx.VERTICAL)
@@ -60,17 +59,19 @@
return
if self.plotSwitch.GetSelection() == 0:
- if not self.statDict[self.currentCat].IsReady():
+ stat = self.stats_data.GetStatistics(self.currentCat)
+ if not stat.IsReady():
self.ClearPlots()
return
- self.DrawHistograms(self.statDict[self.currentCat])
+ self.DrawHistograms(stat)
else:
self.DrawCoincidencePlots()
def StddevChanged(self):
"""!Standard deviation multiplier changed, redraw histograms"""
if self.plotSwitch.GetSelection() == 0:
- self.UpdateRanges(self.statDict[self.currentCat])
+ stat = self.stats_data.GetStatistics(self.currentCat)
+ self.UpdateRanges(stat)
def EnableZoom(self, type, enable = True):
for canvas in self.canvasList:
@@ -114,22 +115,21 @@
self.SetVirtualSize(self.GetBestVirtualSize())
self.Layout()
- def UpdatePlots(self, group, currentCat, statDict, statList):
+ def UpdatePlots(self, group, currentCat, stats_data):
"""!Update plots after new analysis
@param group imagery group
@param currentCat currently selected category (class)
- @param statDict dictionary with Statistics
- @param statList list of currently used categories
+ @param stats_data StatisticsData instance (defined in statistics.py)
"""
- self.statDict = statDict
- self.statList = statList
+ self.stats_data = stats_data
self.currentCat = currentCat
self.bandList = self.parent.GetGroupLayers(group)
graphType = self.plotSwitch.GetSelection()
-
- if not statDict[currentCat].IsReady() and graphType == 0:
+
+ stat = self.stats_data.GetStatistics(currentCat)
+ if not stat.IsReady() and graphType == 0:
return
self.DestroyPlots()
@@ -146,12 +146,15 @@
lines = []
level = 0.5
lines.append(self.DrawInvisibleLine(level))
- for i, cat in enumerate(self.statList):
- if not self.statDict[cat].IsReady():
+
+ cats = self.stats_data.GetCategories()
+ for i, cat in enumerate(cats):
+ stat = self.stats_data.GetStatistics(cat)
+ if not stat.IsReady():
continue
- color = self.statDict[cat].color
+ color = stat.color
level = i + 1
- line = self.DrawCoincidenceLine(level, color, self.statDict[cat].bands[bandIdx])
+ line = self.DrawCoincidenceLine(level, color, stat.bands[bandIdx])
lines.append(line)
# invisible
Modified: grass/trunk/gui/wxpython/iclass/statistics.py
===================================================================
--- grass/trunk/gui/wxpython/iclass/statistics.py 2013-07-26 18:18:10 UTC (rev 57283)
+++ grass/trunk/gui/wxpython/iclass/statistics.py 2013-07-27 00:04:35 UTC (rev 57284)
@@ -4,10 +4,11 @@
@brief wxIClass classes for storing statistics about cells in training areas.
Classes:
+ - statistics::StatisticsData
- statistics::Statistics
- statistics::BandStatistics
-(C) 2006-2011 by the GRASS Development Team
+(C) 2006-2011, 2013 by the GRASS Development Team
This program is free software under the GNU General Public
License (>=v2). Read the file COPYING that comes with GRASS
for details.
@@ -27,6 +28,50 @@
except ImportError, e:
sys.stderr.write(_("Loading imagery lib failed"))
+from grass.pydispatch.signal import Signal
+
+class StatisticsData:
+ """!Stores all statistics.
+ """
+ def __init__(self):
+ self.statisticsDict = {}
+ self.statisticsList = []
+
+ self.statisticsAdded = Signal("StatisticsData.statisticsAdded")
+ self.statisticsDeleted = Signal("StatisticsData.statisticsDeleted")
+ self.allStatisticsDeleted = Signal("StatisticsData.allStatisticsDeleted")
+
+ self.statisticsSet = Signal("StatisticsData.statisticsSet")
+
+ def GetStatistics(self, cat):
+ return self.statisticsDict[cat]
+
+ def AddStatistics(self, cat, name, color):
+ st = Statistics()
+ st.SetBaseStatistics(cat = cat, name = name, color = color)
+ st.statisticsSet.connect(lambda stats : self.statisticsSet.emit(cat = cat,
+ stats = stats))
+
+ self.statisticsDict[cat] = st
+ self.statisticsList.append(cat)
+
+ self.statisticsAdded.emit(cat = cat, name = name, color = color)
+
+ def DeleteStatistics(self, cat):
+ del self.statisticsDict[cat]
+ self.statisticsList.remove(cat)
+
+ self.statisticsDeleted.emit(cat = cat)
+
+ def GetCategories(self):
+ return self.statisticsList[:]
+
+ def DeleteAllStatistics(self):
+ self.statisticsDict.clear()
+ del self.statisticsList[:] # not ...=[] !
+
+ self.allStatisticsDeleted.emit()
+
class Statistics:
"""! Statistis conected to one class (category).
@@ -44,8 +89,9 @@
self.nstd = 1.5
self.bands = []
self.ready = False
-
-
+
+ self.statisticsSet = Signal("Statistics.statisticsSet")
+
def SetReady(self, ready = True):
self.ready = ready
@@ -68,7 +114,7 @@
name = name.replace(' ', '_')
self.rasterName = name + '_' + os.path.basename(rasterPath)
- def SetStatistics(self, cStatistics):
+ def SetFromcStatistics(self, cStatistics):
"""! Sets all statistical values.
Copies all statistic values from \a cStattistics.
@@ -76,31 +122,40 @@
@param cStatistics pointer to C statistics structure
"""
cat = c_int()
+
+ set_stats = {}
I_iclass_statistics_get_cat(cStatistics, byref(cat))
- self.category = cat.value
-
+ if self.category != cat.value:
+ set_stats["category"] = cat.value
+
name = c_char_p()
I_iclass_statistics_get_name(cStatistics, byref(name))
- self.name = name.value
-
+ if self.name != name.value:
+ set_stats["name"] = name.value
+
color = c_char_p()
I_iclass_statistics_get_color(cStatistics, byref(color))
- self.color = color.value
+ if self.color != color.value:
+ set_stats["color"] = color.value
nbands = c_int()
I_iclass_statistics_get_nbands(cStatistics, byref(nbands))
- self.nbands = nbands.value
+ if self.nbands != nbands.value:
+ set_stats["nbands"] = nbands.value
ncells = c_int()
I_iclass_statistics_get_ncells(cStatistics, byref(ncells))
- self.ncells = ncells.value
-
+ if self.ncells != ncells.value:
+ set_stats["ncells"] = ncells.value
+
nstd = c_float()
I_iclass_statistics_get_nstd(cStatistics, byref(nstd))
- self.nstd = nstd.value
-
+ if self.nstd != nstd.value:
+ set_stats["nstd"] = nstd.value
+
+ self.SetStatistics(set_stats)
self.SetBandStatistics(cStatistics)
-
+
def SetBandStatistics(self, cStatistics):
"""! Sets all band statistics.
@@ -109,9 +164,16 @@
self.bands = []
for i in range(self.nbands):
band = BandStatistics()
- band.SetStatistics(cStatistics, index = i)
+ band.SetFromcStatistics(cStatistics, index = i)
self.bands.append(band)
-
+
+ def SetStatistics(self, stats):
+
+ for st, val in stats.iteritems():
+ setattr(self, st, val)
+
+ self.statisticsSet.emit(stats = stats)
+
class BandStatistics:
"""! Statistis conected to one band within class (category).
@@ -125,7 +187,7 @@
self.histo = [0] * 256 # max categories
- def SetStatistics(self, cStatistics, index):
+ def SetFromcStatistics(self, cStatistics, index):
"""! Sets statistics for one band by given index.
@param cStatistics pointer to C statistics structure
More information about the grass-commit
mailing list