[GRASS-SVN] r50713 - in grass/trunk/gui/wxpython: docs iclass
svn_grass at osgeo.org
svn_grass at osgeo.org
Tue Feb 7 14:43:32 EST 2012
Author: annakrat
Date: 2012-02-07 11:43:32 -0800 (Tue, 07 Feb 2012)
New Revision: 50713
Modified:
grass/trunk/gui/wxpython/docs/wxGUI.IClass.html
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/toolbars.py
Log:
wxGUI/wxIClass: import/export of training areas implemented
Modified: grass/trunk/gui/wxpython/docs/wxGUI.IClass.html
===================================================================
--- grass/trunk/gui/wxpython/docs/wxGUI.IClass.html 2012-02-07 17:33:43 UTC (rev 50712)
+++ grass/trunk/gui/wxpython/docs/wxGUI.IClass.html 2012-02-07 19:43:32 UTC (rev 50713)
@@ -26,6 +26,8 @@
(within the number of standard deviations specified)</li>
<li>specify color of class</li>
<li>write signature file</li>
+ <li>import vector map</li>
+ <li>export vector map with attribute table</li>
</ul>
Modified: grass/trunk/gui/wxpython/iclass/dialogs.py
===================================================================
--- grass/trunk/gui/wxpython/iclass/dialogs.py 2012-02-07 17:33:43 UTC (rev 50712)
+++ grass/trunk/gui/wxpython/iclass/dialogs.py 2012-02-07 19:43:32 UTC (rev 50713)
@@ -25,6 +25,7 @@
import wx.lib.scrolledpanel as scrolled
from core import globalvar
+from core.settings import UserSettings
from gui_core.dialogs import ElementDialog, GroupDialog
from gui_core import gselect
from iclass.statistics import Statistics, BandStatistics
@@ -80,25 +81,29 @@
dlg.Destroy()
class IClassMapDialog(ElementDialog):
- """!Dialog for adding raster map"""
- def __init__(self, parent, title = _("Add raster map"), id = wx.ID_ANY):
+ """!Dialog for adding raster/vector map"""
+ def __init__(self, parent, title, element):
"""!
Does post init and layout.
@param gui parent
- @param title dialog window title
- @param id wx id
+ @param element element type ('raster', 'vector')
"""
- ElementDialog.__init__(self, parent, title, label = _("Name of raster map:"))
+ if element == 'raster':
+ label = _("Name of raster map:")
+ elif element == 'vector':
+ label = _("Name of vector map:")
- self.element = gselect.Select(parent = self.panel, type = 'raster',
+ ElementDialog.__init__(self, parent, title = title, label = label)
+
+ self.element = gselect.Select(parent = self.panel, type = element,
size = globalvar.DIALOG_GSELECT_SIZE)
self.PostInit()
self.__Layout()
self.SetMinSize(self.GetSize())
-
+
def __Layout(self):
"""!Do layout"""
self.dataSizer.Add(self.element, proportion = 0,
@@ -107,8 +112,8 @@
self.panel.SetSizer(self.sizer)
self.sizer.Fit(self)
- def GetRasterMap(self):
- """!Returns selected raster map"""
+ def GetMap(self):
+ """!Returns selected raster/vector map"""
return self.GetElement()
@@ -127,6 +132,7 @@
"""
wx.Dialog.__init__(self, parent = parent, title = title, id = id)
+ self.parent = parent
panel = wx.Panel(parent = self, id = wx.ID_ANY)
mainSizer = wx.BoxSizer(wx.VERTICAL)
@@ -168,7 +174,13 @@
self.Layout()
def OnAddCategory(self, event):
- self.catList.AddCategory()
+ if self.parent.statisticsList:
+ cat = max(self.parent.statisticsList) + 1
+ else:
+ cat = 1
+ defaultName = 'class' + '_' + str(cat) # intentionally not translatable
+ defaultColor = '0:0:0'
+ self.catList.AddCategory(cat = cat, name = defaultName, color = defaultColor)
def OnDeleteCategory(self, event):
self.catList.DeleteCategory()
@@ -177,11 +189,16 @@
self.catList.DeselectAll()
self.catList.UpdateChoice()
- if not isinstance(event, wx.CloseEvent):
- self.Destroy()
+ self.Hide()
+ #if not isinstance(event, wx.CloseEvent):
+ #self.Destroy()
- event.Skip()
+ #event.Skip()
+ def GetListCtrl(self):
+ """!Returns list widget"""
+ return self.catList
+
class CategoryListCtrl(wx.ListCtrl,
listmix.ListCtrlAutoWidthMixin,
listmix.TextEditMixin):
@@ -246,15 +263,10 @@
self.SetColumnWidth(0, 100)
self.SetColumnWidth(1, 100)
- def AddCategory(self):
+ def AddCategory(self, cat, name, color):
+ """!Add category record (used when importing areas)"""
st = Statistics()
- if self.statisticsList:
- cat = max(self.statisticsList) + 1
- else:
- cat = 1
- defaultName = 'class' + '_' + str(cat) # intentionally not translatable
- defaultColor = '0:0:0'
- st.SetBaseStatistics(cat = cat, name = defaultName, color = defaultColor)
+ st.SetBaseStatistics(cat = cat, name = name, color = color)
self.statisticsDict[cat] = st
self.statisticsList.append(cat)
self.SetItemCount(len(self.statisticsList))
@@ -485,3 +497,106 @@
return os.path.join(self.baseFilePath, self.fileNameCtrl.GetValue())
return self.fileNameCtrl.GetValue()
+
+class IClassExportAreasDialog(wx.Dialog):
+ def __init__(self, parent, vectorName = None, title = _("Export training areas"), id = wx.ID_ANY,
+ style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
+ **kwargs):
+ """!Dialog for export of training areas to vector layer
+
+ @param parent window
+ @param vectorName name of vector layer for export
+ @param title window title
+ """
+ wx.Dialog.__init__(self, parent, id, title, style = style, **kwargs)
+
+ self.vectorName = vectorName
+ self.panel = wx.Panel(parent = self, id = wx.ID_ANY)
+
+ self.btnCancel = wx.Button(parent = self.panel, id = wx.ID_CANCEL)
+ self.btnOK = wx.Button(parent = self.panel, id = wx.ID_OK)
+ self.btnOK.SetDefault()
+ self.btnOK.Enable(False)
+ self.btnOK.Bind(wx.EVT_BUTTON, self.OnOK)
+
+ self.__layout()
+
+ self.vectorNameCtrl.Bind(wx.EVT_TEXT, self.OnTextChanged)
+ self.OnTextChanged(None)
+
+ def OnTextChanged(self, event):
+ """!Name of new vector map given.
+
+ Enable/diable OK button.
+ """
+ file = self.vectorNameCtrl.GetValue()
+ if len(file) > 0:
+ self.btnOK.Enable(True)
+ else:
+ self.btnOK.Enable(False)
+
+ def __layout(self):
+ """!Do layout"""
+ sizer = wx.BoxSizer(wx.VERTICAL)
+
+ dataSizer = wx.BoxSizer(wx.VERTICAL)
+
+ dataSizer.Add(item = wx.StaticText(parent = self.panel, id = wx.ID_ANY,
+ label = _("Enter name of new vector map:")),
+ proportion = 0, flag = wx.ALL, border = 3)
+ self.vectorNameCtrl = wx.TextCtrl(parent = self.panel, id = wx.ID_ANY, size = (400, -1))
+ if self.vectorName:
+ self.vectorNameCtrl.SetValue(self.vectorName)
+ dataSizer.Add(item = self.vectorNameCtrl,
+ proportion = 0, flag = wx.ALL | wx.EXPAND, border = 3)
+ self.withTableCtrl = wx.CheckBox(parent = self.panel, id = wx.ID_ANY,
+ label = _("Export attribute table"))
+ self.withTableCtrl.SetValue(True)
+ self.withTableCtrl.SetToolTipString(_("Export attribute table containing"
+ " computed statistical data"))
+
+ dataSizer.Add(item = self.withTableCtrl,
+ proportion = 0, flag = wx.ALL, border = 3)
+
+ # buttons
+ btnSizer = wx.StdDialogButtonSizer()
+ btnSizer.AddButton(self.btnCancel)
+ btnSizer.AddButton(self.btnOK)
+ btnSizer.Realize()
+
+ sizer.Add(item = dataSizer, proportion = 1,
+ flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
+
+ sizer.Add(item = btnSizer, proportion = 0,
+ flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
+
+ self.panel.SetSizer(sizer)
+ sizer.Fit(self)
+
+ self.SetMinSize(self.GetSize())
+
+ def GetVectorName(self):
+ """!Returns vector name"""
+ return self.vectorNameCtrl.GetValue()
+
+ def WithTable(self):
+ """!Returns true if attribute table should be exported too"""
+ return self.withTableCtrl.IsChecked()
+
+ def OnOK(self, event):
+ """!Checks if map exists and can be overwritten."""
+ overwrite = UserSettings.Get(group = 'cmd', key = 'overwrite', subkey = 'enabled')
+ vName = self.GetVectorName()
+ res = grass.find_file(vName, element = 'vector')
+ if res['fullname'] and overwrite is False:
+ qdlg = wx.MessageDialog(parent = self,
+ message = _("Vector map <%s> already exists."
+ " Do you want to overwrite it?" % vName) ,
+ caption = _("Vector <%s> exists" % vName),
+ style = wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION | wx.CENTRE)
+ if qdlg.ShowModal() == wx.ID_YES:
+ event.Skip()
+ qdlg.Destroy()
+ else:
+ event.Skip()
+
Modified: grass/trunk/gui/wxpython/iclass/frame.py
===================================================================
--- grass/trunk/gui/wxpython/iclass/frame.py 2012-02-07 17:33:43 UTC (rev 50712)
+++ grass/trunk/gui/wxpython/iclass/frame.py 2012-02-07 19:43:32 UTC (rev 50713)
@@ -20,6 +20,7 @@
import os
import sys
import copy
+import tempfile
if __name__ == "__main__":
sys.path.append(os.path.join(os.environ['GISBASE'], "etc", "gui", "wxpython"))
@@ -46,6 +47,7 @@
from core.render import Map, MapLayer
from core.gcmd import RunCommand, GMessage
from gui_core.dialogs import SetOpacityDialog
+from dbmgr.vinfo import VectorDBInfo
import grass.script as grass
from iclass.digit import IClassVDigitWindow, IClassVDigit
@@ -53,7 +55,8 @@
IClassToolbar, IClassMapManagerToolbar
from iclass.statistics import Statistics, BandStatistics
from iclass.dialogs import CategoryListCtrl, IClassCategoryManagerDialog,\
- IClassGroupDialog, IClassSignatureFileDialog
+ IClassGroupDialog, IClassSignatureFileDialog,\
+ IClassExportAreasDialog, IClassMapDialog
from iclass.plots import PlotPanel
class IClassMapFrame(DoubleMapFrame):
@@ -68,7 +71,7 @@
"""
def __init__(self, parent = None, title = _("Supervised Classification Tool"),
toolbars = ["iClassMisc", "iClassMap", "vdigit", "iClass"],
- size = (800, 600), name = 'IClassWindow', **kwargs):
+ size = (875, 600), name = 'IClassWindow', **kwargs):
"""!
@param parent (no parent is expected)
@param title window title
@@ -118,12 +121,6 @@
sb.SbMapScale,
sb.SbGoTo,
sb.SbProjection]
-
- self.statusbarItemsHiddenInNviz = (sb.SbAlignExtent,
- sb.SbDisplayGeometry,
- sb.SbShowRegion,
- sb.SbResolution,
- sb.SbMapScale)
# create statusbar and its manager
statusbar = self.CreateStatusBar(number = 4, style = 0)
@@ -145,7 +142,16 @@
self.InitStatistics()
self.changes = False
+ self.exportVector = None
+ # dialogs
+ self.dialogs = dict()
+ self.dialogs['classManager'] = 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)
@@ -198,7 +204,7 @@
**cmd[1])
if ret != 0:
return False
-
+
return vectorName
def RemoveTempVector(self):
@@ -212,6 +218,8 @@
def RemoveTempRaster(self, raster):
"""!Removes temporary raster maps"""
+ self.trainingMapManager.RemoveTemporaryLayer(raster)
+ self.previewMapManager.RemoveTemporaryLayer(raster)
ret = RunCommand(prog = 'g.remove',
parent = self,
rast = raster)
@@ -416,10 +424,283 @@
dlg.Destroy()
+ def OnImportAreas(self, event):
+ """!Import training areas"""
+ # check if we have any changes
+ if self.GetAreasCount() or self.statisticsList:
+ qdlg = wx.MessageDialog(parent = self,
+ message = _("All changes will be lost. "
+ "Do you want to continue?") ,
+ style = wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION | wx.CENTRE)
+ if qdlg.ShowModal() == wx.ID_NO:
+ qdlg.Destroy()
+ return
+ qdlg.Destroy()
+
+ dlg = IClassMapDialog(self, title = _("Import vector map"), element = 'vector')
+ if dlg.ShowModal() == wx.ID_OK:
+ vName = dlg.GetMap()
+ warning = self._checkImportedTopo(vName)
+ if warning:
+ GMessage(parent = self, message = warning)
+
+ self.ImportAreas(vName)
+
+ dlg.Destroy()
+
+ def _checkImportedTopo(self, vector):
+ """!Check if imported vector map has areas
+
+ @param vector vector map name
+
+ @return warning message (empty if topology is ok)
+ """
+ topo = grass.vector_info_topo(map = vector)
+
+ warning = ''
+ if topo['areas'] == 0:
+ warning = _("No areas in vector map <%s>.\n" % vector)
+ if topo['points'] or topo['lines']:
+ warning +=_("Vector map <%s> contains points or lines, "
+ "these features are ignored." % vector)
+
+ return warning
+
+ def ImportAreas(self, vector):
+ """!Import training areas.
+
+ If table connected, try load certain columns to class manager
+
+ @param vector vector map name
+ """
+ wx.BeginBusyCursor()
+ wx.Yield()
+
+ mapLayer = self.toolbars['vdigit'].mapLayer
+ # set mapLayer temporarily to None
+ # to avoid 'save changes' code in vdigit.toolbars
+ self.toolbars['vdigit'].mapLayer = None
+
+ ret = self.toolbars['vdigit'].StopEditing()
+ if not ret:
+ wx.EndBusyCursor()
+ return False
+
+ ret, msg = RunCommand('g.copy',
+ vect = [vector, self.trainingAreaVector],
+ overwrite = True,
+ getErrorMsg = True)
+ if ret != 0:
+ wx.EndBusyCursor()
+ return False
+
+ ret = self.toolbars['vdigit'].StartEditing(mapLayer)
+ if not ret:
+ wx.EndBusyCursor()
+ return False
+
+ self.poMapInfo = self.GetFirstWindow().digit.GetDisplay().poMapInfo
+
+ # remove temporary rasters
+ for i in self.statisticsList:
+ self.RemoveTempRaster(self.statisticsDict[i].rasterName)
+
+ # clear current statistics
+ self.statisticsDict.clear()
+ del self.statisticsList[:] # not ...=[] !
+
+ # reset plots
+ self.plotPanel.Reset()
+
+ self.GetFirstWindow().UpdateMap(render = False, renderVector = True)
+
+ self.ImportClasses(vector)
+
+ # should be saved in attribute table?
+ self.toolbars['iClass'].UpdateStddev(1.5)
+
+ wx.EndBusyCursor()
+
+ return True
+
+ def ImportClasses(self, vector):
+ """!If imported map has table, try to import certain columns to class manager"""
+ # check connection
+ dbInfo = VectorDBInfo(vector)
+ connected = (len(dbInfo.layers.keys()) > 0)
+
+ # remove attribute table of temporary vector, we don't need it
+ if connected:
+ RunCommand('v.db.droptable',
+ flags = 'f',
+ map = self.trainingAreaVector)
+
+ # we use first layer with table, TODO: user should choose
+ layer = None
+ for key in dbInfo.layers.keys():
+ if dbInfo.GetTable(key):
+ layer = key
+
+ # get columns to check if we can use them
+ # TODO: let user choose which columns mean what
+ if layer is not None:
+ columns = dbInfo.GetColumns(table = dbInfo.GetTable(layer))
+ else:
+ columns = []
+
+ # get class manager
+ if self.dialogs['classManager'] is None:
+ self.dialogs['classManager'] = IClassCategoryManagerDialog(self)
+
+ listCtrl = self.dialogs['classManager'].GetListCtrl()
+
+ # unable to load data (no connection, table, right columns)
+ if not connected or layer is None or \
+ 'class' not in columns or \
+ 'color' not in columns:
+ # no table connected
+ cats = RunCommand('v.category',
+ input = vector,
+ layer = 1, # set layer?
+ # type = ['centroid', 'area'] ?
+ option = "print",
+ read = True)
+ cats = map(int, cats.strip().split())
+ cats = sorted(list(set(cats)))
+
+ for cat in cats:
+ listCtrl.AddCategory(cat = cat, name = 'class_%d' % cat, color = "0:0:0")
+ # connection, table and columns exists
+ else:
+ columns = ['cat', 'class', 'color']
+ ret = RunCommand('v.db.select',
+ quiet = True,
+ parent = self,
+ flags = 'c',
+ map = vector,
+ layer = 1,
+ columns = ','.join(columns),
+ read = True)
+ records = ret.strip().split('\n')
+ for record in records:
+ record = record.split('|')
+ listCtrl.AddCategory(cat = int(record[0]), name = record[1], color = record[2])
+
+ def OnExportAreas(self, event):
+ """!Export training areas"""
+ if self.GetAreasCount() == 0:
+ GMessage(parent = self, message = _("No training areas to export."))
+ return
+
+ dlg = IClassExportAreasDialog(self, vectorName = self.exportVector)
+
+ if dlg.ShowModal() == wx.ID_OK:
+ vName = dlg.GetVectorName()
+ self.exportVector = vName
+ withTable = dlg.WithTable()
+
+ self.ExportAreas(vectorName = vName, withTable = withTable)
+
+ dlg.Destroy()
+
+ def ExportAreas(self, vectorName, withTable):
+ """!Export training areas to new vector map (with attribute table).
+
+ @param vectorName name of exported vector map
+ @param withTable true if attribute table is required
+ """
+ wx.BeginBusyCursor()
+ wx.Yield()
+
+ # build the temporary or the new one?
+ RunCommand('v.build',
+ map = self.trainingAreaVector,
+ quiet = True)
+ # copy temp vector with no table
+ ret, msg = RunCommand('g.copy',
+ vect = [self.trainingAreaVector, vectorName],
+ overwrite = True,
+ getErrorMsg = True)
+ if ret != 0:
+ wx.EndBusyCursor()
+ GMessage(parent = self, message = _("Failed to copy vector map. "
+ "Details:\n%s" % msg))
+ return
+
+ if not withTable:
+ wx.EndBusyCursor()
+ return
+
+ # add table
+ columns = ["class varchar(30)",
+ "color varchar(11)",
+ "n_cells integer",]
+
+ nbands = len(self.GetGroupLayers(self.group))
+ for statistic, format in (("min", "integer"), ("mean", "double precision"), ("max", "integer")):
+ for i in range(nbands):
+ # 10 characters limit?
+ columns.append("band%(band)d_%(stat)s %(format)s" % {'band' : i + 1,
+ 'stat' : statistic,
+ 'format' : format})
+
+ ret, msg = RunCommand('v.db.addtable',
+ map = vectorName,
+ columns = columns,
+ getErrorMsg = True)
+ if ret != 0:
+ wx.EndBusyCursor()
+ GMessage(parent = self, message = _("Failed to add attribute table. "
+ "Details:\n%s" % msg))
+ return
+
+ # populate table
+ for cat in self.statisticsList:
+ stat = self.statisticsDict[cat]
+
+ self._runDBUpdate(map = vectorName, column = "class", value = stat.name, cat = cat)
+ self._runDBUpdate(map = vectorName, column = "color", value = stat.color, cat = cat)
+
+ if not stat.IsReady():
+ continue
+
+ self._runDBUpdate(map = vectorName, column = "n_cells",value = stat.ncells, cat = cat)
+
+ for i in range(nbands):
+ self._runDBUpdate(map = vectorName, column = "band%d_min" % (i + 1), value = stat.bands[i].min, cat = cat)
+ self._runDBUpdate(map = vectorName, column = "band%d_mean" % (i + 1), value = stat.bands[i].mean, cat = cat)
+ self._runDBUpdate(map = vectorName, column = "band%d_max" % (i + 1), value = stat.bands[i].max, cat = cat)
+
+ wx.EndBusyCursor()
+
+ def _runDBUpdate(self, map, column, value, cat):
+ """!Helper function for calling v.db.update.
+
+ @param map vector map name
+ @param column name of updated column
+ @param value new value
+ @param cat which category to update
+
+ @return returncode (0 is OK)
+ """
+ ret = RunCommand('v.db.update',
+ map = map,
+ layer = 1,
+ column = column,
+ value = value,
+ where = "cat = %d" % cat)
+
+ return ret
+
def OnCategoryManager(self, event):
"""!Show category management dialog"""
- dlg = IClassCategoryManagerDialog(self)
- dlg.Show()
+ if self.dialogs['classManager'] is None:
+ dlg = IClassCategoryManagerDialog(self)
+ dlg.Show()
+ self.dialogs['classManager'] = dlg
+ else:
+ if not self.dialogs['classManager'].IsShown():
+ self.dialogs['classManager'].Show()
def CategoryChanged(self, currentCat):
"""!Updates everything which depends on current category.
@@ -485,7 +766,7 @@
def UpdateChangeState(self, changes):
"""!Informs if any important changes happened
- since last analysis computaiton.
+ since last analysis computation.
"""
self.changes = changes
@@ -516,6 +797,7 @@
name = vname, l_active = False)
self.toolbars['vdigit'].StartEditing(mapLayer)
+ self.poMapInfo = self.GetFirstWindow().digit.GetDisplay().poMapInfo
self.Render(self.GetFirstWindow())
def OnRunAnalysis(self, event):
@@ -532,8 +814,6 @@
Calls C functions to compute all statistics and creates raster maps.
Signatures are created but signature file is not.
"""
- #self.firstMapWindow.digit.CloseMap()
- self.poMapInfo = self.firstMapWindow.digit.GetDisplay().poMapInfo
if not self.CheckInput(group = self.group, vector = self.trainingAreaVector):
return
@@ -676,22 +956,22 @@
return False
#check if vector has any areas
- vectorInfo = grass.vector_info(vector)
- numAreas = Vect_get_num_areas(self.poMapInfo)
-
- if numAreas <= 0:
+ if self.GetAreasCount() == 0:
GMessage(parent = self,
message = _("No areas given. "
"Operation canceled."))
return False
# check if vector is inside raster
+ regionBox = bound_box()
+ Vect_get_map_box(self.poMapInfo, byref(regionBox))
+
rasterInfo = grass.raster_info(groupLayers[0])
- if vectorInfo['north'] > rasterInfo['north'] or \
- vectorInfo['south'] < rasterInfo['south'] or \
- vectorInfo['east'] > rasterInfo['east'] or \
- vectorInfo['west'] < rasterInfo['west']:
+ if regionBox.N > rasterInfo['north'] or \
+ regionBox.S < rasterInfo['south'] or \
+ regionBox.E > rasterInfo['east'] or \
+ regionBox.W < rasterInfo['west']:
GMessage(parent = self,
message = _("Vector features are outside raster layers. "
"Operation canceled."))
@@ -699,6 +979,15 @@
return True
+ def GetAreasCount(self):
+ """!Returns number of not dead areas"""
+ count = 0
+ numAreas = Vect_get_num_areas(self.poMapInfo)
+ for i in range(numAreas):
+ if Vect_area_alive(self.poMapInfo, i + 1):
+ count += 1
+ return count
+
def GetGroupLayers(self, group):
"""! Get layers in group
@@ -740,7 +1029,6 @@
super(IClassMapFrame, self).OnPan(event)
self.plotPanel.EnablePan()
-
class MapManager:
"""! Class for managing map renderer.
@@ -792,9 +1080,40 @@
self.toolbar.choice.Insert(name, 0)
self.toolbar.choice.SetSelection(0)
+ def RemoveTemporaryLayer(self, name):
+ """!Removes temporary layer (if exists) from Map and and updates toolbar.
+
+ @param name real name of layer
+ """
+ # check if layer is loaded
+ layers = self.map.GetListOfLayers(l_type = 'raster')
+ idx = None
+ for i, layer in enumerate(layers):
+ if name == layer.GetName():
+ idx = i
+ break
+ if idx is None:
+ return
+ # remove it from Map
+ self.map.RemoveLayer(name = name)
+
+ # update inner list of layers
+ alias = self.GetAlias(name)
+ if alias not in self.layerName:
+ return
+
+ del self.layerName[alias]
+ # update choice
+ idx = self.toolbar.choice.FindString(alias)
+ if idx != wx.NOT_FOUND:
+ self.toolbar.choice.Delete(idx)
+ if not self.toolbar.choice.IsEmpty():
+ self.toolbar.choice.SetSelection(0)
+
+ self.frame.Render(self.mapWindow)
+
def RemoveLayer(self, name, idx):
"""!Removes layer from Map and update toolbar"""
- self.map.GetListOfLayers(l_type = 'raster')
name = self.layerName[name]
self.map.RemoveLayer(name = name)
del self.layerName[name]
Modified: grass/trunk/gui/wxpython/iclass/plots.py
===================================================================
--- grass/trunk/gui/wxpython/iclass/plots.py 2012-02-07 17:33:43 UTC (rev 50712)
+++ grass/trunk/gui/wxpython/iclass/plots.py 2012-02-07 19:43:32 UTC (rev 50713)
@@ -93,6 +93,12 @@
for bandIdx in range(len(self.bandList)):
self.canvasList[bandIdx].Clear()
+ def Reset(self):
+ """!Reset plots (when new map imported)"""
+ self.currentCat = None
+ self.ClearPlots()
+ # bands are still the same
+
def CreatePlotCanvases(self):
"""!Create plot canvases according to the number of bands"""
for band in self.bandList:
Modified: grass/trunk/gui/wxpython/iclass/toolbars.py
===================================================================
--- grass/trunk/gui/wxpython/iclass/toolbars.py 2012-02-07 17:33:43 UTC (rev 50712)
+++ grass/trunk/gui/wxpython/iclass/toolbars.py 2012-02-07 19:43:32 UTC (rev 50713)
@@ -39,6 +39,10 @@
label = _('Save signature file')),
'delCmd' : MetaIcon(img = 'layer-remove',
label = _('Delete selected map layer')),
+ 'exportAreas' : MetaIcon(img = 'layer-export',
+ label = _('Export training areas')),
+ 'importAreas' : MetaIcon(img = 'layer-import',
+ label = _('Import training areas')),
}
class IClassMapToolbar(BaseToolbar):
@@ -154,9 +158,15 @@
(None, ),
("runAnalysis", icons['run'],
self.parent.OnRunAnalysis),
+ (None, ),
+ ("importAreas", icons['importAreas'],
+ self.parent.OnImportAreas),
+ ("exportAreas", icons['exportAreas'],
+ self.parent.OnExportAreas),
("sigFile", icons['sigFile'],
self.parent.OnSaveSigFile),
))
+
def OnSelectCategory(self, event):
idx = self.choice.GetSelection()
cat = self.choice.GetClientData(idx)
@@ -251,9 +261,9 @@
self.mapManager.SelectLayer(name = layer)
def OnAddRast(self, event):
- dlg = IClassMapDialog(self)
+ dlg = IClassMapDialog(self, title = _("Add raster map"), element = 'raster')
if dlg.ShowModal() == wx.ID_OK:
- raster = grass.find_file(name = dlg.GetRasterMap(), element = 'cell')
+ raster = grass.find_file(name = dlg.GetMap(), element = 'cell')
if raster['fullname']:
self.mapManager.AddLayer(name = raster['fullname'])
More information about the grass-commit
mailing list