[GRASS-SVN] r57530 - sandbox/turek/scatter_plot
svn_grass at osgeo.org
svn_grass at osgeo.org
Wed Aug 28 09:01:32 PDT 2013
Author: turek
Date: 2013-08-28 09:01:30 -0700 (Wed, 28 Aug 2013)
New Revision: 57530
Modified:
sandbox/turek/scatter_plot/testing_patch.diff
Log:
scatter plot: plots rendering memory and speed optimization
Modified: sandbox/turek/scatter_plot/testing_patch.diff
===================================================================
--- sandbox/turek/scatter_plot/testing_patch.diff 2013-08-28 15:01:45 UTC (rev 57529)
+++ sandbox/turek/scatter_plot/testing_patch.diff 2013-08-28 16:01:30 UTC (rev 57530)
@@ -1,47 +1,6 @@
-Index: include/defs/vedit.h
-===================================================================
---- include/defs/vedit.h (revision 57506)
-+++ include/defs/vedit.h (working copy)
-@@ -33,6 +33,8 @@
- int Vedit_merge_lines(struct Map_info *, struct ilist *);
-
- /* move.c */
-+int Vedit_move_areas(struct Map_info *, struct Map_info **, int,
-+ struct ilist *, double, double, double, int, double);
- int Vedit_move_lines(struct Map_info *, struct Map_info **, int,
- struct ilist *, double, double, double, int, double);
-
-Index: include/defs/imagery.h
-===================================================================
---- include/defs/imagery.h (revision 57506)
-+++ include/defs/imagery.h (working copy)
-@@ -110,6 +110,23 @@
- FILE *I_fopen_subgroup_ref_new(const char *, const char *);
- FILE *I_fopen_subgroup_ref_old(const char *, const char *);
-
-+/* scatt_plt.c */
-+void I_sc_init_cats(struct scCats *, int, int);
-+void I_sc_free_cats(struct scCats *);
-+int I_sc_add_cat(struct scCats *);
-+int I_sc_insert_scatt_data(struct scCats *, struct scdScattData *, int, int);
-+
-+void I_scd_init_scatt_data(struct scdScattData *, int, int, void *);
-+
-+int I_compute_scatts(struct Cell_head *, struct scCats *, const char **,
-+ const char **, int, struct scCats *, const char **);
-+
-+int I_create_cat_rast(struct Cell_head *, const char *);
-+int I_insert_patch_to_cat_rast(const char *, struct Cell_head *, const char *);
-+
-+int I_id_scatt_to_bands(const int, const int, int *, int *);
-+int I_bands_to_id_scatt(const int, const int, const int, int *);
-+
- /* sig.c */
- int I_init_signatures(struct Signature *, int);
- int I_new_signature(struct Signature *);
Index: include/imagery.h
===================================================================
---- include/imagery.h (revision 57506)
+--- include/imagery.h (revision 57529)
+++ include/imagery.h (working copy)
@@ -135,6 +135,56 @@
@@ -100,6 +59,717 @@
#define SIGNATURE_TYPE_MIXED 1
#define GROUPFILE "CURGROUP"
+Index: include/defs/vedit.h
+===================================================================
+--- include/defs/vedit.h (revision 57529)
++++ include/defs/vedit.h (working copy)
+@@ -33,6 +33,8 @@
+ int Vedit_merge_lines(struct Map_info *, struct ilist *);
+
+ /* move.c */
++int Vedit_move_areas(struct Map_info *, struct Map_info **, int,
++ struct ilist *, double, double, double, int, double);
+ int Vedit_move_lines(struct Map_info *, struct Map_info **, int,
+ struct ilist *, double, double, double, int, double);
+
+Index: include/defs/imagery.h
+===================================================================
+--- include/defs/imagery.h (revision 57529)
++++ include/defs/imagery.h (working copy)
+@@ -110,6 +110,23 @@
+ FILE *I_fopen_subgroup_ref_new(const char *, const char *);
+ FILE *I_fopen_subgroup_ref_old(const char *, const char *);
+
++/* scatt_plt.c */
++void I_sc_init_cats(struct scCats *, int, int);
++void I_sc_free_cats(struct scCats *);
++int I_sc_add_cat(struct scCats *);
++int I_sc_insert_scatt_data(struct scCats *, struct scdScattData *, int, int);
++
++void I_scd_init_scatt_data(struct scdScattData *, int, int, void *);
++
++int I_compute_scatts(struct Cell_head *, struct scCats *, const char **,
++ const char **, int, struct scCats *, const char **);
++
++int I_create_cat_rast(struct Cell_head *, const char *);
++int I_insert_patch_to_cat_rast(const char *, struct Cell_head *, const char *);
++
++int I_id_scatt_to_bands(const int, const int, int *, int *);
++int I_bands_to_id_scatt(const int, const int, const int, int *);
++
+ /* sig.c */
+ int I_init_signatures(struct Signature *, int);
+ int I_new_signature(struct Signature *);
+Index: gui/wxpython/scatt_plot/core_c.py
+===================================================================
+--- gui/wxpython/scatt_plot/core_c.py (revision 0)
++++ gui/wxpython/scatt_plot/core_c.py (working copy)
+@@ -0,0 +1,166 @@
++"""!
++ at package scatt_plot.scatt_plot
++
++ at brief Functions which work with scatter plot c code.
++
++Classes:
++
++(C) 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.
++
++ at author Stepan Turek <stepan.turek seznam.cz> (mentor: Martin Landa)
++"""
++
++import sys
++from multiprocessing import Process, Queue
++
++from ctypes import *
++try:
++ from grass.lib.imagery import *
++ from grass.lib.gis import Cell_head, G_get_window
++except ImportError, e:
++ sys.stderr.write(_("Loading imagery lib failed"))
++
++from core.gcmd import GException
++
++
++def ComputeScatts(region, scatt_conds, bands, n_bands, scatts, cats_rasts_conds, cats_rasts):
++ q = Queue()
++ p = Process(target=_computeScattsProcess, args=(region, scatt_conds, bands,
++ n_bands, scatts, cats_rasts_conds, cats_rasts, q))
++ p.start()
++ ret = q.get()
++ p.join()
++
++ return ret[0], ret[1]
++
++def UpdateCatRast(patch_rast, region, cat_rast):
++ q = Queue()
++ p = Process(target=_updateCatRastProcess, args=(patch_rast, region, cat_rast, q))
++ p.start()
++ ret = q.get()
++ p.join()
++
++ return ret
++
++def CreateCatRast(region, cat_rast):
++ cell_head = _regionToCellHead(region)
++ I_create_cat_rast(pointer(cell_head), cat_rast)
++
++def _computeScattsProcess(region, scatt_conds, bands, n_bands, scatts, cats_rasts_conds, cats_rasts, output_queue):
++
++ #TODO names for types not 0 and 1?
++ sccats_c, cats_rasts_c, refs = _getComputationStruct(scatts, cats_rasts, 0, n_bands)
++ scatt_conds_c, cats_rasts_conds_c, refs2 = _getComputationStruct(scatt_conds, cats_rasts_conds, 1, n_bands)
++
++ char_bands = _stringListToCharArr(bands)
++
++ cell_head = _regionToCellHead(region)
++
++ ret = I_compute_scatts(pointer(cell_head),
++ pointer(scatt_conds_c),
++ pointer(cats_rasts_conds_c),
++ pointer(char_bands),
++ n_bands,
++ pointer(sccats_c),
++ pointer(cats_rasts_c))
++
++ I_sc_free_cats(pointer(sccats_c))
++ I_sc_free_cats(pointer(scatt_conds_c))
++
++ output_queue.put((ret, scatts))
++
++def _getBandcRange( band_info):
++ band_c_range = struct_Range()
++
++ band_c_range.max = band_info['max']
++ band_c_range.min = band_info['min']
++
++ return band_c_range
++
++def _regionToCellHead(region):
++ cell_head = struct_Cell_head()
++ G_get_window(pointer(cell_head))
++
++ convert_dict = {'n' : 'north', 'e' : 'east',
++ 'w' : 'west', 's' : 'south',
++ 'nsres' : 'ns_res',
++ 'ewres' : 'ew_res'}
++
++ for k, v in region.iteritems():
++ if k in ["rows", "cols", "cells"]:
++ v = int(v)
++ else:
++ v = float(v)
++
++ if convert_dict.has_key(k):
++ k = convert_dict[k]
++
++ setattr(cell_head, k, v)
++
++ return cell_head
++
++def _stringListToCharArr(str_list):
++
++ arr = c_char_p * len(str_list)
++ char_arr = arr()
++ for i, st in enumerate(str_list):
++ if st:
++ char_arr[i] = st
++ else:
++ char_arr[i] = None
++
++ return char_arr
++
++def _getComputationStruct(cats, cats_rasts, cats_type, n_bands):
++
++ sccats = struct_scCats()
++ I_sc_init_cats(pointer(sccats), c_int(n_bands), c_int(cats_type));
++
++ refs = []
++ cats_rasts_core = []
++
++ for cat_id, scatt_ids in cats.iteritems():
++ cat_c_id = I_sc_add_cat(pointer(sccats))
++ cats_rasts_core.append(cats_rasts[cat_id])
++
++ for scatt_id, dt in scatt_ids.iteritems():
++ # if key is missing condition is always True (full scatter plor is computed)
++ vals = dt['np_vals']
++
++ scatt_vals = scdScattData()
++
++ c_void_p = ctypes.POINTER(ctypes.c_void_p)
++
++ if cats_type == SC_SCATT_DATA:
++ vals[:] = 0
++ elif cats_type == SC_SCATT_CONDITIONS:
++ pass
++ else:
++ return None
++ data_p = vals.ctypes.data_as(c_void_p)
++ I_scd_init_scatt_data(pointer(scatt_vals), cats_type, len(vals), data_p)
++
++ refs.append(scatt_vals)
++
++ I_sc_insert_scatt_data(pointer(sccats),
++ pointer(scatt_vals),
++ cat_c_id, scatt_id)
++
++ cats_rasts_c = _stringListToCharArr(cats_rasts_core)
++
++ return sccats, cats_rasts_c, refs
++
++def _updateCatRastProcess(patch_rast, region, cat_rast, output_queue):
++ cell_head = _regionToCellHead(region)
++
++
++ ret = I_insert_patch_to_cat_rast(patch_rast,
++ pointer(cell_head),
++ cat_rast)
++
++ output_queue.put(ret)
++
++
+Index: gui/wxpython/scatt_plot/frame.py
+===================================================================
+--- gui/wxpython/scatt_plot/frame.py (revision 0)
++++ gui/wxpython/scatt_plot/frame.py (working copy)
+@@ -0,0 +1,494 @@
++"""!
++ at package scatt_plot.dialogs
++
++ at brief GUI.
++
++Classes:
++
++(C) 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.
++
++ at author Stepan Turek <stepan.turek seznam.cz> (mentor: Martin Landa)
++"""
++import os
++import sys
++
++import wx
++import wx.lib.scrolledpanel as scrolled
++import wx.lib.mixins.listctrl as listmix
++import wx.lib.flatnotebook as FN
++import wx.aui
++
++from core import globalvar
++from core.gcmd import GException, GError, RunCommand
++
++from gui_core.gselect import Select
++
++from scatt_plot.controllers import ScattsManager
++from scatt_plot.toolbars import MainToolbar, EditingToolbar
++from scatt_plot.scatt_core import idScattToidBands
++from scatt_plot.plots import ScatterPlotWidget
++
++try:
++ from agw import aui
++except ImportError:
++ import wx.lib.agw.aui as aui
++
++class IClassScatterPlotsPanel(wx.Panel):
++ def __init__(self, parent, giface, iclass_mapwin = None,
++ id = wx.ID_ANY, style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs):
++
++ #wx.SplitterWindow.__init__(self, parent = parent, id = id,
++ # style = wx.SP_LIVE_UPDATE)
++ wx.Panel.__init__(self, parent = parent, id = wx.ID_ANY)
++
++ #self.head_panel = wx.Panel(parent = self, id = wx.ID_ANY)
++ self.scatt_mgr = ScattsManager(guiparent = self, giface = giface, iclass_mapwin = iclass_mapwin)
++
++ # toobars
++ self.toolbars = {}
++ self.toolbars['mainToolbar'] = MainToolbar(parent = self, scatt_mgr = self.scatt_mgr)
++ self.toolbars['editingToolbar'] = EditingToolbar(parent = self, scatt_mgr = self.scatt_mgr)
++
++ self._createCategoryPanel(self)
++
++ self.plot_panel = IClassPlotPanel(self, self.scatt_mgr)
++
++ mainsizer = wx.BoxSizer(wx.VERTICAL)
++ mainsizer.Add(item = self.toolbars['mainToolbar'], proportion = 0, flag = wx.EXPAND)
++ mainsizer.Add(item = self.toolbars['editingToolbar'], proportion = 0, flag = wx.EXPAND)
++ mainsizer.Add(item = self.catsPanel, proportion = 0, flag = wx.EXPAND | wx.LEFT | wx.RIGHT , border = 5)
++ mainsizer.Add(item = self.plot_panel, proportion = 1, flag = wx.EXPAND)
++
++ self.catsPanel.Hide()
++ self.toolbars['editingToolbar'].Hide()
++
++ self.SetSizer(mainsizer)
++
++ #self.SetSashGravity(0.5)
++ #self.SplitHorizontally(self.head_panel, self.plot_panel, -50)
++ self.Layout()
++
++ def NewScatterPlot(self, scatt_id):
++ return self.plot_panel.NewScatterPlot(scatt_id)
++
++ def ShowPlotEditingToolbar(self, show):
++ self.toolbars["editingToolbar"].Show(show)
++ self.Layout()
++
++ def ShowCategoryPanel(self, show):
++ self.catsPanel.Show(show)
++
++ #if show:
++ # self.SetSashSize(5)
++ #else:
++ # self.SetSashSize(0)
++ self.plot_panel.SetVirtualSize(self.plot_panel.GetBestVirtualSize())
++ self.Layout()
++
++ def _createCategoryPanel(self, parent):
++ self.catsPanel = wx.Panel(parent = parent)
++ self.cats_list = CategoryListCtrl(parent = self.catsPanel,
++ cats_mgr = self.scatt_mgr.GetCategoriesManager())
++
++ self.catsPanel.SetMaxSize((-1, 150))
++
++ box_capt = wx.StaticBox(parent = self.catsPanel, id = wx.ID_ANY,
++ label = ' %s ' % _("Classes manager for scatter plots"))
++ catsSizer = wx.StaticBoxSizer(box_capt, wx.VERTICAL)
++
++ catsSizer.Add(item = self.cats_list, proportion = 1, flag = wx.EXPAND | wx.ALL)
++ self.catsPanel.SetSizer(catsSizer)
++
++
++class IClassPlotPanel(scrolled.ScrolledPanel):
++ def __init__(self, parent, scatt_mgr, id = wx.ID_ANY):
++
++ scrolled.ScrolledPanel.__init__(self, parent)
++ self.SetupScrolling(scroll_x = False, scroll_y = True, scrollToTop = False)
++
++ self.scatt_mgr = scatt_mgr
++
++ self.mainPanel = wx.Panel(parent = self, id = wx.ID_ANY)
++
++ #self._createCategoryPanel()
++ # Fancy gui
++ self._mgr = aui.AuiManager(self.mainPanel)
++ #self._mgr.SetManagedWindow(self)
++
++ self._mgr.Update()
++
++ self._doLayout()
++ self.Bind(wx.EVT_SCROLLWIN, self.OnScroll)
++ self.Bind(wx.EVT_SCROLL_CHANGED, self.OnScrollChanged)
++
++ self.Bind(aui.EVT_AUI_PANE_CLOSE, self.OnPlotPaneClosed)
++
++ dlgSize = (-1, 400)
++ #self.SetBestSize(dlgSize)
++ #self.SetInitialSize(dlgSize)
++ self.SetAutoLayout(1)
++ #fix goutput's pane size (required for Mac OSX)
++ #if self.gwindow:
++ # self.gwindow.SetSashPosition(int(self.GetSize()[1] * .75))
++ self.ignore_scroll = 0
++ self.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
++
++ def OnMouseWheel(self, event):
++ #TODO very ugly find some better solution
++ self.ignore_scroll = 3
++ event.Skip()
++
++ def ScrollChildIntoView(self, child):
++ #For aui manager it does not work and returns position always to the top -> deactivated.
++ pass
++
++ def OnPlotPaneClosed(self, event):
++ if isinstance(event.pane.window, ScatterPlotWidget):
++ event.pane.window.CleanUp()
++
++ def OnScrollChanged(self, event):
++ print "changed"
++ wx.CallAfter(self.Layout)
++
++
++ def OnScroll(self, event):
++ if self.ignore_scroll > 0:
++ self.ignore_scroll -= 1
++ else:
++ event.Skip()
++
++ #wx.CallAfter(self._mgr.Update)
++ #wx.CallAfter(self.Layout)
++
++ def _doLayout(self):
++
++ mainsizer = wx.BoxSizer(wx.VERTICAL)
++ mainsizer.Add(item = self.mainPanel, proportion = 1, flag = wx.EXPAND)
++ self.SetSizer(mainsizer)
++
++ self.Layout()
++ self.SetupScrolling()
++
++ def OnCloseDialog(self, event):
++ """!Close dialog"""
++ self.scatt_mgr.CleanUp()
++ self.Destroy()
++
++ def OnSettings(self, event):
++ pass
++
++ def NewScatterPlot(self, scatt_id):
++ #TODO needs to be resolved (should be in this class)
++
++ scatt = ScatterPlotWidget(parent = self.mainPanel,
++ scatt_mgr = self.scatt_mgr,
++ scatt_id = scatt_id)
++
++ bands = self.scatt_mgr.GetBands()
++ #TODO too low level
++ b1_id, b2_id = idScattToidBands(scatt_id, len(bands))
++
++ self._mgr.AddPane(scatt,
++ aui.AuiPaneInfo().Dockable(True).Floatable(True).
++ Name("scatter plot %d" % scatt_id).MinSize((-1, 300)).Caption(("%s x: %s y: %s") % (_("scatter plot"), bands[b1_id], bands[b2_id])).
++ Center().Position(1).MaximizeButton(True).
++ MinimizeButton(True).CaptionVisible(True).
++ CloseButton(True).Layer(0))
++
++
++ self._mgr.Update()
++
++ self.SetVirtualSize(self.GetBestVirtualSize())
++ self.Layout()
++
++ return scatt
++
++ def GetScattMgr(self):
++ return self.scatt_mgr
++
++class CategoryListCtrl(wx.ListCtrl,
++ listmix.ListCtrlAutoWidthMixin,
++ listmix.TextEditMixin):
++
++ def __init__(self, parent, cats_mgr, id = wx.ID_ANY):
++
++ wx.ListCtrl.__init__(self, parent, id,
++ style = wx.LC_REPORT|wx.LC_VIRTUAL|wx.LC_HRULES|wx.LC_VRULES)
++ self.columns = ((_('Class name'), 'name'),
++ (_('Color'), 'color'))
++ self.Populate(columns = self.columns)
++
++ self.cats_mgr = cats_mgr
++ self.SetItemCount(len(self.cats_mgr.GetCategories()))
++
++ self.rightClickedItemIdx = wx.NOT_FOUND
++
++ listmix.ListCtrlAutoWidthMixin.__init__(self)
++
++ listmix.TextEditMixin.__init__(self)
++
++ self.Bind(wx.EVT_LIST_BEGIN_LABEL_EDIT, self.OnEdit)
++ self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnSel)
++
++ self.cats_mgr.setCategoryAttrs.connect(self.Update)
++ self.cats_mgr.deletedCategory.connect(self.Update)
++ self.cats_mgr.addedCategory.connect(self.Update)
++
++ def Update(self, **kwargs):
++ self.SetItemCount(len(self.cats_mgr.GetCategories()))
++ self.RefreshItems(0, len(self.cats_mgr.GetCategories()))
++
++ def InitCoreCats(self):
++ self.SetItemCount(len(self.cats_mgr.GetCategories()))
++ self.RefreshItems(0, len(self.cats_mgr.GetCategories()))
++
++ def SetVirtualData(self, row, column, text):
++ attr = self.columns[column][1]
++ if attr == 'name':
++ try:
++ text.encode('ascii')
++ except UnicodeEncodeError:
++ GMessage(parent = self, message = _("Please use only ASCII characters."))
++ return
++
++ cat_id = self.cats_mgr.GetCategories()[row]
++
++ self.cats_mgr.setCategoryAttrs.disconnect(self.Update)
++ self.cats_mgr.SetCategoryAttrs(cat_id, {attr : text})
++ self.cats_mgr.setCategoryAttrs.connect(self.Update)
++
++ self.Select(row)
++
++ def Populate(self, columns):
++ for i, col in enumerate(columns):
++ self.InsertColumn(i, col[0])#wx.LIST_FORMAT_RIGHT
++
++ self.SetColumnWidth(0, 100)
++ self.SetColumnWidth(1, 100)
++
++ def AddCategory(self):
++
++ self.cats_mgr.addedCategory.disconnect(self.Update)
++ cat_id = self.cats_mgr.AddCategory()
++ self.cats_mgr.addedCategory.connect(self.Update)
++
++ if cat_id < 0:
++ GError(_("Maximum limit of categories number was reached."))
++ return
++ self.SetItemCount(len(self.cats_mgr.GetCategories()))
++
++ def DeleteCategory(self):
++ indexList = sorted(self.GetSelectedIndices(), reverse = True)
++ cats = []
++ for i in indexList:
++ # remove temporary raster
++ cat_id = self.cats_mgr.GetCategories()[i]
++
++ cats.append(cat_id)
++
++ self.cats_mgr.deletedCategory.disconnect(self.Update)
++ self.cats_mgr.DeleteCategory(cat_id)
++ self.cats_mgr.deletedCategory.connect(self.Update)
++
++ self.SetItemCount(len(self.cats_mgr.GetCategories()))
++
++ def OnSel(self, event):
++ event.Skip()
++
++ def GetSelectedIndices(self, state = wx.LIST_STATE_SELECTED):
++ indices = []
++ lastFound = -1
++ while True:
++ index = self.GetNextItem(lastFound, wx.LIST_NEXT_ALL, state)
++ if index == -1:
++ break
++ else:
++ lastFound = index
++ indices.append(index)
++ return indices
++
++ def OnEdit(self, event):
++ currentItem = event.m_itemIndex
++ currentCol = event.m_col
++
++ if currentCol == 1:
++ dlg = wx.ColourDialog(self)
++ dlg.GetColourData().SetChooseFull(True)
++
++ if dlg.ShowModal() == wx.ID_OK:
++ color = dlg.GetColourData().GetColour().Get()
++ color = ':'.join(map(str, color))
++ self.SetVirtualData(currentItem, currentCol, color)
++ dlg.Destroy()
++ wx.CallAfter(self.SetFocus)
++
++ event.Skip()
++
++
++ def DeselectAll(self):
++ """!Deselect all items"""
++ indexList = self.GetSelectedIndices()
++ for i in indexList:
++ self.Select(i, on = 0)
++
++ # no highlight
++ self.OnCategorySelected(None)
++
++ def OnGetItemText(self, item, col):
++ attr = self.columns[col][1]
++ cat_id = self.cats_mgr.GetCategories()[item]
++
++ return self.cats_mgr.GetCategoryAttrs(cat_id)[attr]
++
++ def OnGetItemImage(self, item):
++ return -1
++
++ def OnGetItemAttr(self, item):
++ return None
++
++ def OnClassRightUp(self, event):
++ """!Show context menu on right click"""
++ item, flags = self.HitTest((event.GetX(), event.GetY()))
++ if item != wx.NOT_FOUND and flags & wx.LIST_HITTEST_ONITEM:
++ self.rightClickedItemIdx = item
++
++ self.popupZoomtoAreas = wx.NewId()
++ self.Bind(wx.EVT_MENU, self.OnZoomToAreasByCat, id = self.popupZoomtoAreas)
++
++ # generate popup-menu
++ menu = wx.Menu()
++ menu.Append(self.popupZoomtoAreas, _("Zoom to training areas of selected class"))
++
++ self.PopupMenu(menu)
++ menu.Destroy()
++
++ def OnZoomToAreasByCat(self, event):
++ """!Zoom to areas of given category"""
++ cat = self.stats_data.GetCategories()[self.rightClickedItemIdx]
++ self.mapWindow.ZoomToAreasByCat(cat)
++
++class AddScattPlotDialog(wx.Dialog):
++
++ def __init__(self, parent, bands, id = wx.ID_ANY):
++
++ wx.Dialog.__init__(self, parent, title = ("Add scatter plot"), id = id)
++
++ self.bands = bands
++
++ self.scatt_id = None
++
++ self._createWidgets()
++
++ def _createWidgets(self):
++
++ self.labels = {}
++ self.params = {}
++
++ self.band_1_label = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("Band 1:"))
++
++ self.band_1_ch = wx.ComboBox(parent = self, id = wx.ID_ANY,
++ choices = self.bands,
++ style = wx.CB_READONLY, size = (350, 30))
++
++ self.band_2_label = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("Band 2:"))
++
++ self.band_2_ch = wx.ComboBox(parent = self, id = wx.ID_ANY,
++ choices = self.bands,
++ style = wx.CB_READONLY, size = (350, 30))
++
++ # buttons
++ self.btn_close = wx.Button(parent = self, id = wx.ID_CANCEL)
++
++ self.btn_ok = wx.Button(parent = self, id = wx.ID_OK, label = _("&OK"))
++
++ self._layout()
++
++ def _layout(self):
++
++ border = wx.BoxSizer(wx.VERTICAL)
++ dialogSizer = wx.BoxSizer(wx.VERTICAL)
++
++ regionSizer = wx.BoxSizer(wx.HORIZONTAL)
++
++ dialogSizer.Add(item = self._addSelectSizer(title = self.band_1_label,
++ sel = self.band_1_ch))
++
++ dialogSizer.Add(item = self._addSelectSizer(title = self.band_2_label,
++ sel = self.band_2_ch))
++
++ # buttons
++ self.btnsizer = wx.BoxSizer(orient = wx.HORIZONTAL)
++
++ self.btnsizer.Add(item = self.btn_close, proportion = 0,
++ flag = wx.ALL | wx.ALIGN_CENTER,
++ border = 10)
++
++ self.btnsizer.Add(item = self.btn_ok, proportion = 0,
++ flag = wx.ALL | wx.ALIGN_CENTER,
++ border = 10)
++
++ dialogSizer.Add(item = self.btnsizer, proportion = 0,
++ flag = wx.ALIGN_CENTER)
++
++ border.Add(item = dialogSizer, proportion = 0,
++ flag = wx.ALL, border = 5)
++
++ self.SetSizer(border)
++ self.Layout()
++ self.Fit()
++
++ # bindings
++ self.btn_close.Bind(wx.EVT_BUTTON, self.OnClose)
++ self.btn_ok.Bind(wx.EVT_BUTTON, self.OnOk)
++
++ def _addSelectSizer(self, title, sel):
++ """!Helper layout function.
++ """
++ selSizer = wx.BoxSizer(orient = wx.VERTICAL)
++
++ selTitleSizer = wx.BoxSizer(wx.HORIZONTAL)
++ selTitleSizer.Add(item = title, proportion = 1,
++ flag = wx.LEFT | wx.TOP | wx.EXPAND, border = 5)
++
++ selSizer.Add(item = selTitleSizer, proportion = 0,
++ flag = wx.EXPAND)
++
++ selSizer.Add(item = sel, proportion = 1,
++ flag = wx.EXPAND | wx.ALL| wx.ALIGN_CENTER_VERTICAL,
++ border = 5)
++
++ return selSizer
++
++ def OnClose(self, event):
++ """!Close dialog
++ """
++ if not self.IsModal():
++ self.Destroy()
++ event.Skip()
++
++ def OnOk(self, event):
++ """!
++ """
++ band_1 = self.band_1_ch.GetSelection()
++ band_2 = self.band_2_ch.GetSelection()
++
++
++ if band_1 == band_2:
++ GError(_("Selected bands must be different."))
++ return
++
++ #TODO axes selection
++ if band_1 > band_2:
++ tmp_band = band_2
++ band_2 = band_1
++ band_1 = band_2
++
++ self.scatt_id = idBandsToidScatt(band_1, band_2, len(self.bands))
++
++ event.Skip()
++
++ def GetScattId(self):
++ return self.scatt_id
Index: gui/wxpython/scatt_plot/__init__.py
===================================================================
--- gui/wxpython/scatt_plot/__init__.py (revision 0)
@@ -120,7 +790,7 @@
===================================================================
--- gui/wxpython/scatt_plot/plots.py (revision 0)
+++ gui/wxpython/scatt_plot/plots.py (working copy)
-@@ -0,0 +1,502 @@
+@@ -0,0 +1,666 @@
+"""!
+ at package scatt_plot.dialogs
+
@@ -140,6 +810,8 @@
+import random
+from copy import deepcopy
+
++import scipy.misc as misc
++
+try:
+ haveMatPlot = True
+ import matplotlib
@@ -152,10 +824,17 @@
+ from matplotlib.artist import Artist
+ from matplotlib.mlab import dist_point_to_segment
+ from matplotlib.patches import Polygon, Ellipse
++ import matplotlib.image as mi
++ import matplotlib.colors as mcolors
++ import matplotlib.cbook as cbook
+except ImportError:
+ haveMatPlot = False
+from grass.pydispatch.signal import Signal
+
++
++#class PlotImages()?
++
++
+class ScatterPlotWidget(wx.Panel):
+ def __init__(self, parent, scatt_id, scatt_mgr,
+ id = wx.ID_ANY):
@@ -210,7 +889,6 @@
+
+ def SetMode(self, mode):
+ self._deactivateMode()
-+
+ if mode == 'zoom':
+ self.ciddscroll = self.canvas.mpl_connect('scroll_event', self.zoom)
+ elif mode == 'pan':
@@ -224,6 +902,7 @@
+
+ def _deactivateMode(self):
+
++ #TODO do own pan
+ if self.toolbar._active == "PAN":
+ self.toolbar.pan()
+
@@ -232,13 +911,6 @@
+
+ self._stopCategoryEdit()
+
-+ #def _startCategoryEdit(self):
-+ # self.cidpress = self.canvas.mpl_connect(
-+ # 'button_press_event', self.OnPress)
-+ # self.cidrelease = self.canvas.mpl_connect(
-+ # 'button_release_event', self.OnRelease)
-+ #self.cidmotion = self.canvas.mpl_connect(
-+ # 'motion_notify_event', self.OnRelease)
+
+ def OnPress(self, event):
+ 'on button press we will see if the mouse is over us and store some data'
@@ -296,6 +968,9 @@
+ self.axes.clear()
+
+ callafter_list = []
++
++ init = True
++
+ for cat_id, scatt in scatts.iteritems():
+ b1_i = scatt['bands_info']['b1']
+ b2_i = scatt['bands_info']['b2']
@@ -319,20 +994,36 @@
+
+ masked_cat = np.ma.masked_less_equal(scatt['np_vals'], 0)
+
-+ #self.axes.set_xlim((0, 270))
-+ #self.axes.set_ylim((0, 270))
-+ #np.savetxt("/home/ostepok/Desktop/data.txt", scatt['np_vals'], fmt = '%d')
-+
++ vmax = np.amax(masked_cat)
++ masked_cat = masked_cat/ float(vmax)
+
-+ #TODO needs optimization
-+ img = self.axes.imshow(masked_cat, cmap = deepcopy(cmap),
-+ origin = 'lower',
-+ extent = self.full_extend,
-+ interpolation='nearest',
-+ aspect = "auto")
++ colored_cat = np.uint8(cmap(masked_cat) * 255)
++
++ if init:
++ merged_img = colored_cat
++ init = False
++ else:
++ for i in range(4):
++ merged_img[...,i] = np.choose(masked_cat.mask, (colored_cat[...,i], merged_img[...,i]))
+
-+ callafter_list.append([self.axes.draw_artist, [img]])
++ del colored_cat
++ del masked_cat
+
++ img = imshow(self.axes, merged_img,
++ origin = 'lower',
++ extent = self.full_extend,
++ interpolation='nearest',
++ aspect = "auto")
++
++ #TODO needs optimization
++ #img = self.axes.imshow(merged_img,
++ # origin = 'lower',
++ # extent = self.full_extend,
++ # interpolation='nearest',
++ # aspect = "auto")
++
++ callafter_list.append([self.axes.draw_artist, [img]])
++
+ #self.fig.savefig("/home/ostepok/Desktop/data.png")
+
+ for cat_id, e in ellipses.iteritems():
@@ -544,6 +1235,7 @@
+ if len(self.pol.xy) <= 2:
+ self.empty_pol = True
+ self.Show(False)
++ return
+
+ coords = []
+ for i,tup in enumerate(self.pol.xy):
@@ -607,7 +1299,7 @@
+ if self.moving_ver_idx is None: return
+ if event.inaxes is None: return
+ if event.button != 1: return
-+ print "moving %d" % self.it
++
+ self.it += 1
+
+ x,y = event.xdata, event.ydata
@@ -623,6 +1315,149 @@
+ self.canvas.restore_region(self.background)
+
+ self.Redraw()
++
++class ModestImage(mi.AxesImage):
++ """
++ Computationally modest image class.
++
++ ModestImage is an extension of the Matplotlib AxesImage class
++ better suited for the interactive display of larger images. Before
++ drawing, ModestImage resamples the data array based on the screen
++ resolution and view window. This has very little affect on the
++ appearance of the image, but can substantially cut down on
++ computation since calculations of unresolved or clipped pixels
++ are skipped.
++
++ The interface of ModestImage is the same as AxesImage. However, it
++ does not currently support setting the 'extent' property. There
++ may also be weird coordinate warping operations for images that
++ I'm not aware of. Don't expect those to work either.
++
++ Author: Chris Beaumont <beaumont at hawaii.edu>
++ """
++ def __init__(self, *args, **kwargs):
++ #why???
++ #if 'extent' in kwargs and kwargs['extent'] is not None:
++ # raise NotImplementedError("ModestImage does not support extents")
++
++ self._full_res = None
++ self._sx, self._sy = None, None
++ self._bounds = (None, None, None, None)
++ super(ModestImage, self).__init__(*args, **kwargs)
++
++ def set_data(self, A):
++ """
++ Set the image array
++
++ ACCEPTS: numpy/PIL Image A
++ """
++ self._full_res = A
++ self._A = A
++
++ if self._A.dtype != np.uint8 and not np.can_cast(self._A.dtype,
++ np.float):
++ raise TypeError("Image data can not convert to float")
++
++ if (self._A.ndim not in (2, 3) or
++ (self._A.ndim == 3 and self._A.shape[-1] not in (3, 4))):
++ raise TypeError("Invalid dimensions for image data")
++
++ self._imcache =None
++ self._rgbacache = None
++ self._oldxslice = None
++ self._oldyslice = None
++ self._sx, self._sy = None, None
++
++ def get_array(self):
++ """Override to return the full-resolution array"""
++ return self._full_res
++
++ def _scale_to_res(self):
++ """ Change self._A and _extent to render an image whose
++ resolution is matched to the eventual rendering."""
++
++ ax = self.axes
++ ext = ax.transAxes.transform([1, 1]) - ax.transAxes.transform([0, 0])
++ xlim, ylim = ax.get_xlim(), ax.get_ylim()
++ dx, dy = xlim[1] - xlim[0], ylim[1] - ylim[0]
++
++ y0 = max(0, ylim[0] - 5)
++ y1 = min(self._full_res.shape[0], ylim[1] + 5)
++ x0 = max(0, xlim[0] - 5)
++ x1 = min(self._full_res.shape[1], xlim[1] + 5)
++ y0, y1, x0, x1 = map(int, [y0, y1, x0, x1])
++
++ sy = int(max(1, min((y1 - y0) / 5., np.ceil(dy / ext[1]))))
++ sx = int(max(1, min((x1 - x0) / 5., np.ceil(dx / ext[0]))))
++
++ # have we already calculated what we need?
++ if sx == self._sx and sy == self._sy and \
++ x0 == self._bounds[0] and x1 == self._bounds[1] and \
++ y0 == self._bounds[2] and y1 == self._bounds[3]:
++ return
++
++ self._A = self._full_res[y0:y1:sy, x0:x1:sx]
++ self._A = cbook.safe_masked_invalid(self._A)
++ x1 = x0 + self._A.shape[1] * sx
++ y1 = y0 + self._A.shape[0] * sy
++
++ self.set_extent([x0 - .5, x1 - .5, y0 - .5, y1 - .5])
++ self._sx = sx
++ self._sy = sy
++ self._bounds = (x0, x1, y0, y1)
++ self.changed()
++
++ def draw(self, renderer, *args, **kwargs):
++ self._scale_to_res()
++ super(ModestImage, self).draw(renderer, *args, **kwargs)
++
++
++def imshow(axes, X, cmap=None, norm=None, aspect=None,
++ interpolation=None, alpha=None, vmin=None, vmax=None,
++ origin=None, extent=None, shape=None, filternorm=1,
++ filterrad=4.0, imlim=None, resample=None, url=None, **kwargs):
++ """Similar to matplotlib's imshow command, but produces a ModestImage
++
++ Unlike matplotlib version, must explicitly specify axes
++ Author: Chris Beaumont <beaumont at hawaii.edu>
++ """
++
++ if not axes._hold:
++ axes.cla()
++ if norm is not None:
++ assert(isinstance(norm, mcolors.Normalize))
++ if aspect is None:
++ aspect = rcParams['image.aspect']
++ axes.set_aspect(aspect)
++ im = ModestImage(axes, cmap, norm, interpolation, origin, extent,
++ filternorm=filternorm,
++ filterrad=filterrad, resample=resample, **kwargs)
++
++ im.set_data(X)
++ im.set_alpha(alpha)
++ axes._set_artist_props(im)
++
++ if im.get_clip_path() is None:
++ # image does not already have clipping set, clip to axes patch
++ im.set_clip_path(axes.patch)
++
++ #if norm is None and shape is None:
++ # im.set_clim(vmin, vmax)
++ if vmin is not None or vmax is not None:
++ im.set_clim(vmin, vmax)
++ else:
++ im.autoscale_None()
++ im.set_url(url)
++
++ # update ax.dataLim, and, if autoscaling, set viewLim
++ # to tightly fit the image, regardless of dataLim.
++ im.set_extent(im.get_extent())
++
++ axes.images.append(im)
++ im._remove_method = lambda h: axes.images.remove(h)
++
++ return im
+\ No newline at end of file
Index: gui/wxpython/scatt_plot/controllers.py
===================================================================
--- gui/wxpython/scatt_plot/controllers.py (revision 0)
@@ -712,6 +1547,50 @@
+
+ self.Bind(EVT_CMD_DONE, self.OnThreadDone)
+
++ def OnThreadDone(self, event):
++
++ if event.exception:
++ GError(str(event.exception))
++ return
++
++ if event.pid in self.tasks_pids['mapwin_conn']:
++ self.tasks_pids['mapwin_conn'].remove(event.pid)
++ updated_cats = event.ret
++
++ for cat in updated_cats:
++ if cat not in self.cats_to_update:
++ self.cats_to_update.append(cat)
++
++ if not self.tasks_pids['mapwin_conn']:
++ self.tasks_pids['render_plots'] = self.thread.GetId()
++ self.thread.Run(callable = self.core.ComputeCatsScatts,
++ cats_ids = self.cats_to_update[:])
++ del self.cats_to_update[:]
++
++ return
++
++ if self.tasks_pids['render_plots'] == event.pid:
++ self.RenderScattPlts()
++ return
++
++ if event.pid in self.tasks_pids['add_scatt']:
++ self.tasks_pids['add_scatt'].remove(event.pid)
++ self.AddScattPlotDone(event)
++ return
++
++ if self.tasks_pids['set_data'] == event.pid:
++ self.SetDataDone(event)
++ return
++
++ if self.tasks_pids['set_data_add'] == event.pid:
++ self.SetDataDone(event)
++ self.AddScattPlot()
++ return
++
++ if self.tasks_pids['set_edit_cat_data'] == event.pid:
++ self.SetEditCatDataDone(event)
++ return
++
+ def SetData(self, bands):
+ self.data_set = False
+
@@ -814,50 +1693,6 @@
+ scatt.CleanUp()
+ del self.plots[scatt_id]
+
-+ def OnThreadDone(self, event):
-+
-+ if event.exception:
-+ GError(str(event.exception))
-+ return
-+
-+ if event.pid in self.tasks_pids['mapwin_conn']:
-+ self.tasks_pids['mapwin_conn'].remove(event.pid)
-+ updated_cats = event.ret
-+
-+ for cat in updated_cats:
-+ if cat not in self.cats_to_update:
-+ self.cats_to_update.append(cat)
-+
-+ if not self.tasks_pids['mapwin_conn']:
-+ self.tasks_pids['render_plots'] = self.thread.GetId()
-+ self.thread.Run(callable = self.core.ComputeCatsScatts,
-+ cats_ids = self.cats_to_update[:])
-+ del self.cats_to_update[:]
-+
-+ return
-+
-+ if self.tasks_pids['render_plots'] == event.pid:
-+ self.RenderScattPlts()
-+ return
-+
-+ if event.pid in self.tasks_pids['add_scatt']:
-+ self.tasks_pids['add_scatt'].remove(event.pid)
-+ self.AddScattPlotDone(event)
-+ return
-+
-+ if self.tasks_pids['set_data'] == event.pid:
-+ self.SetDataDone(event)
-+ return
-+
-+ if self.tasks_pids['set_data_add'] == event.pid:
-+ self.SetDataDone(event)
-+ self.AddScattPlot()
-+ return
-+
-+ if self.tasks_pids['set_edit_cat_data'] == event.pid:
-+ self.SetEditCatDataDone(event)
-+ return
-+
+ def SetPlotsMode(self, mode):
+
+ self.plot_mode = mode
@@ -1239,7 +2074,7 @@
===================================================================
--- gui/wxpython/scatt_plot/gthreading.py (revision 0)
+++ gui/wxpython/scatt_plot/gthreading.py (working copy)
-@@ -0,0 +1,134 @@
+@@ -0,0 +1,133 @@
+"""!
+ at package scatt_plot.gthreading
+
@@ -1358,8 +2193,7 @@
+ time.sleep(.1)
+
+ if self.receiver:
-+ event = wxCmdDone(type = 'cmd',
-+ kwds = kwds,
++ event = wxCmdDone(kwds = kwds,
+ args = args, #TODO expand args to kwds
+ ret=ret,
+ exception=exception,
@@ -1650,23 +2484,23 @@
+ """
+ self.icons = {
+ 'sel_add' : MetaIcon(img = 'layer-add',
-+ label = _('Include selected areas from category.'),
-+ desc = _('Include selected areas from category.')),
++ label = _('Include selected area to class.'),
++ desc = _('Include selected area to class.')),
+ 'sel_remove' : MetaIcon(img = 'layer-remove',
-+ label = _('Exclude selected areas from category.'),
-+ desc = _('Exclude selected areas from category.')),
++ label = _('Exclude selected area from class.'),
++ desc = _('Exclude selected area from class.')),
+ 'addVertex' : MetaIcon(img = 'vertex-create',
+ label = _('Add new vertex'),
+ desc = _('Add new vertex to polygon boundary scatter plot')),
+ 'editLine' : MetaIcon(img = 'line-edit',
+ label = _('Edit line/boundary'),
-+ desc = _('Add new vertex to last point of the boundary')),
++ desc = _('Add new vertex between last and first points of the boundary')),
+ 'moveVertex' : MetaIcon(img = 'vertex-move',
+ label = _('Move vertex'),
+ desc = _('Move boundary vertex')),
+ 'removeVertex' : MetaIcon(img = 'vertex-delete',
+ label = _('Remove vertex'),
-+ desc = _('Remove vertex.')),
++ desc = _('Remove boundary vertex.')),
+ }
+
+ return self._getToolbarData((
@@ -2495,679 +3329,9 @@
+
+ return scatt_id
+
-Index: gui/wxpython/scatt_plot/core_c.py
-===================================================================
---- gui/wxpython/scatt_plot/core_c.py (revision 0)
-+++ gui/wxpython/scatt_plot/core_c.py (working copy)
-@@ -0,0 +1,166 @@
-+"""!
-+ at package scatt_plot.scatt_plot
-+
-+ at brief Functions which work with scatter plot c code.
-+
-+Classes:
-+
-+(C) 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.
-+
-+ at author Stepan Turek <stepan.turek seznam.cz> (mentor: Martin Landa)
-+"""
-+
-+import sys
-+from multiprocessing import Process, Queue
-+
-+from ctypes import *
-+try:
-+ from grass.lib.imagery import *
-+ from grass.lib.gis import Cell_head, G_get_window
-+except ImportError, e:
-+ sys.stderr.write(_("Loading imagery lib failed"))
-+
-+from core.gcmd import GException
-+
-+
-+def ComputeScatts(region, scatt_conds, bands, n_bands, scatts, cats_rasts_conds, cats_rasts):
-+ q = Queue()
-+ p = Process(target=_computeScattsProcess, args=(region, scatt_conds, bands,
-+ n_bands, scatts, cats_rasts_conds, cats_rasts, q))
-+ p.start()
-+ ret = q.get()
-+ p.join()
-+
-+ return ret[0], ret[1]
-+
-+def UpdateCatRast(patch_rast, region, cat_rast):
-+ q = Queue()
-+ p = Process(target=_updateCatRastProcess, args=(patch_rast, region, cat_rast, q))
-+ p.start()
-+ ret = q.get()
-+ p.join()
-+
-+ return ret
-+
-+def CreateCatRast(region, cat_rast):
-+ cell_head = _regionToCellHead(region)
-+ I_create_cat_rast(pointer(cell_head), cat_rast)
-+
-+def _computeScattsProcess(region, scatt_conds, bands, n_bands, scatts, cats_rasts_conds, cats_rasts, output_queue):
-+
-+ #TODO names for types not 0 and 1?
-+ sccats_c, cats_rasts_c, refs = _getComputationStruct(scatts, cats_rasts, 0, n_bands)
-+ scatt_conds_c, cats_rasts_conds_c, refs2 = _getComputationStruct(scatt_conds, cats_rasts_conds, 1, n_bands)
-+
-+ char_bands = _stringListToCharArr(bands)
-+
-+ cell_head = _regionToCellHead(region)
-+
-+ ret = I_compute_scatts(pointer(cell_head),
-+ pointer(scatt_conds_c),
-+ pointer(cats_rasts_conds_c),
-+ pointer(char_bands),
-+ n_bands,
-+ pointer(sccats_c),
-+ pointer(cats_rasts_c))
-+
-+ I_sc_free_cats(pointer(sccats_c))
-+ I_sc_free_cats(pointer(scatt_conds_c))
-+
-+ output_queue.put((ret, scatts))
-+
-+def _getBandcRange( band_info):
-+ band_c_range = struct_Range()
-+
-+ band_c_range.max = band_info['max']
-+ band_c_range.min = band_info['min']
-+
-+ return band_c_range
-+
-+def _regionToCellHead(region):
-+ cell_head = struct_Cell_head()
-+ G_get_window(pointer(cell_head))
-+
-+ convert_dict = {'n' : 'north', 'e' : 'east',
-+ 'w' : 'west', 's' : 'south',
-+ 'nsres' : 'ns_res',
-+ 'ewres' : 'ew_res'}
-+
-+ for k, v in region.iteritems():
-+ if k in ["rows", "cols", "cells"]:
-+ v = int(v)
-+ else:
-+ v = float(v)
-+
-+ if convert_dict.has_key(k):
-+ k = convert_dict[k]
-+
-+ setattr(cell_head, k, v)
-+
-+ return cell_head
-+
-+def _stringListToCharArr(str_list):
-+
-+ arr = c_char_p * len(str_list)
-+ char_arr = arr()
-+ for i, st in enumerate(str_list):
-+ if st:
-+ char_arr[i] = st
-+ else:
-+ char_arr[i] = None
-+
-+ return char_arr
-+
-+def _getComputationStruct(cats, cats_rasts, cats_type, n_bands):
-+
-+ sccats = struct_scCats()
-+ I_sc_init_cats(pointer(sccats), c_int(n_bands), c_int(cats_type));
-+
-+ refs = []
-+ cats_rasts_core = []
-+
-+ for cat_id, scatt_ids in cats.iteritems():
-+ cat_c_id = I_sc_add_cat(pointer(sccats))
-+ cats_rasts_core.append(cats_rasts[cat_id])
-+
-+ for scatt_id, dt in scatt_ids.iteritems():
-+ # if key is missing condition is always True (full scatter plor is computed)
-+ vals = dt['np_vals']
-+
-+ scatt_vals = scdScattData()
-+
-+ c_void_p = ctypes.POINTER(ctypes.c_void_p)
-+
-+ if cats_type == SC_SCATT_DATA:
-+ vals[:] = 0
-+ elif cats_type == SC_SCATT_CONDITIONS:
-+ pass
-+ else:
-+ return None
-+ data_p = vals.ctypes.data_as(c_void_p)
-+ I_scd_init_scatt_data(pointer(scatt_vals), cats_type, len(vals), data_p)
-+
-+ refs.append(scatt_vals)
-+
-+ I_sc_insert_scatt_data(pointer(sccats),
-+ pointer(scatt_vals),
-+ cat_c_id, scatt_id)
-+
-+ cats_rasts_c = _stringListToCharArr(cats_rasts_core)
-+
-+ return sccats, cats_rasts_c, refs
-+
-+def _updateCatRastProcess(patch_rast, region, cat_rast, output_queue):
-+ cell_head = _regionToCellHead(region)
-+
-+
-+ ret = I_insert_patch_to_cat_rast(patch_rast,
-+ pointer(cell_head),
-+ cat_rast)
-+
-+ output_queue.put(ret)
-+
-+
-Index: gui/wxpython/scatt_plot/frame.py
-===================================================================
---- gui/wxpython/scatt_plot/frame.py (revision 0)
-+++ gui/wxpython/scatt_plot/frame.py (working copy)
-@@ -0,0 +1,494 @@
-+"""!
-+ at package scatt_plot.dialogs
-+
-+ at brief GUI.
-+
-+Classes:
-+
-+(C) 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.
-+
-+ at author Stepan Turek <stepan.turek seznam.cz> (mentor: Martin Landa)
-+"""
-+import os
-+import sys
-+
-+import wx
-+import wx.lib.scrolledpanel as scrolled
-+import wx.lib.mixins.listctrl as listmix
-+import wx.lib.flatnotebook as FN
-+import wx.aui
-+
-+from core import globalvar
-+from core.gcmd import GException, GError, RunCommand
-+
-+from gui_core.gselect import Select
-+
-+from scatt_plot.controllers import ScattsManager
-+from scatt_plot.toolbars import MainToolbar, EditingToolbar
-+from scatt_plot.scatt_core import idScattToidBands
-+from scatt_plot.plots import ScatterPlotWidget
-+
-+try:
-+ from agw import aui
-+except ImportError:
-+ import wx.lib.agw.aui as aui
-+
-+class IClassScatterPlotsPanel(wx.Panel):
-+ def __init__(self, parent, giface, iclass_mapwin = None,
-+ id = wx.ID_ANY, style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs):
-+
-+ #wx.SplitterWindow.__init__(self, parent = parent, id = id,
-+ # style = wx.SP_LIVE_UPDATE)
-+ wx.Panel.__init__(self, parent = parent, id = wx.ID_ANY)
-+
-+ #self.head_panel = wx.Panel(parent = self, id = wx.ID_ANY)
-+ self.scatt_mgr = ScattsManager(guiparent = self, giface = giface, iclass_mapwin = iclass_mapwin)
-+
-+ # toobars
-+ self.toolbars = {}
-+ self.toolbars['mainToolbar'] = MainToolbar(parent = self, scatt_mgr = self.scatt_mgr)
-+ self.toolbars['editingToolbar'] = EditingToolbar(parent = self, scatt_mgr = self.scatt_mgr)
-+
-+ self._createCategoryPanel(self)
-+
-+ self.plot_panel = IClassPlotPanel(self, self.scatt_mgr)
-+
-+ mainsizer = wx.BoxSizer(wx.VERTICAL)
-+ mainsizer.Add(item = self.toolbars['mainToolbar'], proportion = 0, flag = wx.EXPAND)
-+ mainsizer.Add(item = self.toolbars['editingToolbar'], proportion = 0, flag = wx.EXPAND)
-+ mainsizer.Add(item = self.catsPanel, proportion = 0, flag = wx.EXPAND | wx.LEFT | wx.RIGHT , border = 5)
-+ mainsizer.Add(item = self.plot_panel, proportion = 1, flag = wx.EXPAND)
-+
-+ self.catsPanel.Hide()
-+ self.toolbars['editingToolbar'].Hide()
-+
-+ self.SetSizer(mainsizer)
-+
-+ #self.SetSashGravity(0.5)
-+ #self.SplitHorizontally(self.head_panel, self.plot_panel, -50)
-+ self.Layout()
-+
-+ def NewScatterPlot(self, scatt_id):
-+ return self.plot_panel.NewScatterPlot(scatt_id)
-+
-+ def ShowPlotEditingToolbar(self, show):
-+ self.toolbars["editingToolbar"].Show(show)
-+ self.Layout()
-+
-+ def ShowCategoryPanel(self, show):
-+ self.catsPanel.Show(show)
-+
-+ #if show:
-+ # self.SetSashSize(5)
-+ #else:
-+ # self.SetSashSize(0)
-+ self.plot_panel.SetVirtualSize(self.plot_panel.GetBestVirtualSize())
-+ self.Layout()
-+
-+ def _createCategoryPanel(self, parent):
-+ self.catsPanel = wx.Panel(parent = parent)
-+ self.cats_list = CategoryListCtrl(parent = self.catsPanel,
-+ cats_mgr = self.scatt_mgr.GetCategoriesManager())
-+
-+ self.catsPanel.SetMaxSize((-1, 150))
-+
-+ box_capt = wx.StaticBox(parent = self.catsPanel, id = wx.ID_ANY,
-+ label = ' %s ' % _("Classes manager for scatter plots"))
-+ catsSizer = wx.StaticBoxSizer(box_capt, wx.VERTICAL)
-+
-+ catsSizer.Add(item = self.cats_list, proportion = 1, flag = wx.EXPAND | wx.ALL)
-+ self.catsPanel.SetSizer(catsSizer)
-+
-+
-+class IClassPlotPanel(scrolled.ScrolledPanel):
-+ def __init__(self, parent, scatt_mgr, id = wx.ID_ANY):
-+
-+ scrolled.ScrolledPanel.__init__(self, parent)
-+ self.SetupScrolling(scroll_x = False, scroll_y = True, scrollToTop = False)
-+
-+ self.scatt_mgr = scatt_mgr
-+
-+ self.mainPanel = wx.Panel(parent = self, id = wx.ID_ANY)
-+
-+ #self._createCategoryPanel()
-+ # Fancy gui
-+ self._mgr = aui.AuiManager(self.mainPanel)
-+ #self._mgr.SetManagedWindow(self)
-+
-+ self._mgr.Update()
-+
-+ self._doLayout()
-+ self.Bind(wx.EVT_SCROLLWIN, self.OnScroll)
-+ self.Bind(wx.EVT_SCROLL_CHANGED, self.OnScrollChanged)
-+
-+ self.Bind(aui.EVT_AUI_PANE_CLOSE, self.OnPlotPaneClosed)
-+
-+ dlgSize = (-1, 400)
-+ #self.SetBestSize(dlgSize)
-+ #self.SetInitialSize(dlgSize)
-+ self.SetAutoLayout(1)
-+ #fix goutput's pane size (required for Mac OSX)
-+ #if self.gwindow:
-+ # self.gwindow.SetSashPosition(int(self.GetSize()[1] * .75))
-+ self.ignore_scroll = 0
-+ self.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
-+
-+ def OnMouseWheel(self, event):
-+ #TODO very ugly find some better solution
-+ self.ignore_scroll = 3
-+ event.Skip()
-+
-+ def ScrollChildIntoView(self, child):
-+ #For aui manager it does not work and returns position always to the top -> deactivated.
-+ pass
-+
-+ def OnPlotPaneClosed(self, event):
-+ if isinstance(event.pane.window, ScatterPlotWidget):
-+ event.pane.window.CleanUp()
-+
-+ def OnScrollChanged(self, event):
-+ print "changed"
-+ wx.CallAfter(self.Layout)
-+
-+
-+ def OnScroll(self, event):
-+ if self.ignore_scroll > 0:
-+ self.ignore_scroll -= 1
-+ else:
-+ event.Skip()
-+
-+ #wx.CallAfter(self._mgr.Update)
-+ #wx.CallAfter(self.Layout)
-+
-+ def _doLayout(self):
-+
-+ mainsizer = wx.BoxSizer(wx.VERTICAL)
-+ mainsizer.Add(item = self.mainPanel, proportion = 1, flag = wx.EXPAND)
-+ self.SetSizer(mainsizer)
-+
-+ self.Layout()
-+ self.SetupScrolling()
-+
-+ def OnCloseDialog(self, event):
-+ """!Close dialog"""
-+ self.scatt_mgr.CleanUp()
-+ self.Destroy()
-+
-+ def OnSettings(self, event):
-+ pass
-+
-+ def NewScatterPlot(self, scatt_id):
-+ #TODO needs to be resolved (should be in this class)
-+
-+ scatt = ScatterPlotWidget(parent = self.mainPanel,
-+ scatt_mgr = self.scatt_mgr,
-+ scatt_id = scatt_id)
-+
-+ bands = self.scatt_mgr.GetBands()
-+ #TODO too low level
-+ b1_id, b2_id = idScattToidBands(scatt_id, len(bands))
-+
-+ self._mgr.AddPane(scatt,
-+ aui.AuiPaneInfo().Dockable(True).Floatable(True).
-+ Name("scatter plot %d" % scatt_id).MinSize((-1, 300)).Caption(("%s x: %s y: %s") % (_("scatter plot"), bands[b1_id], bands[b2_id])).
-+ Center().Position(1).MaximizeButton(True).
-+ MinimizeButton(True).CaptionVisible(True).
-+ CloseButton(True).Layer(0))
-+
-+
-+ self._mgr.Update()
-+
-+ self.SetVirtualSize(self.GetBestVirtualSize())
-+ self.Layout()
-+
-+ return scatt
-+
-+ def GetScattMgr(self):
-+ return self.scatt_mgr
-+
-+class CategoryListCtrl(wx.ListCtrl,
-+ listmix.ListCtrlAutoWidthMixin,
-+ listmix.TextEditMixin):
-+
-+ def __init__(self, parent, cats_mgr, id = wx.ID_ANY):
-+
-+ wx.ListCtrl.__init__(self, parent, id,
-+ style = wx.LC_REPORT|wx.LC_VIRTUAL|wx.LC_HRULES|wx.LC_VRULES)
-+ self.columns = ((_('Class name'), 'name'),
-+ (_('Color'), 'color'))
-+ self.Populate(columns = self.columns)
-+
-+ self.cats_mgr = cats_mgr
-+ self.SetItemCount(len(self.cats_mgr.GetCategories()))
-+
-+ self.rightClickedItemIdx = wx.NOT_FOUND
-+
-+ listmix.ListCtrlAutoWidthMixin.__init__(self)
-+
-+ listmix.TextEditMixin.__init__(self)
-+
-+ self.Bind(wx.EVT_LIST_BEGIN_LABEL_EDIT, self.OnEdit)
-+ self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnSel)
-+
-+ self.cats_mgr.setCategoryAttrs.connect(self.Update)
-+ self.cats_mgr.deletedCategory.connect(self.Update)
-+ self.cats_mgr.addedCategory.connect(self.Update)
-+
-+ def Update(self, **kwargs):
-+ self.SetItemCount(len(self.cats_mgr.GetCategories()))
-+ self.RefreshItems(0, len(self.cats_mgr.GetCategories()))
-+
-+ def InitCoreCats(self):
-+ self.SetItemCount(len(self.cats_mgr.GetCategories()))
-+ self.RefreshItems(0, len(self.cats_mgr.GetCategories()))
-+
-+ def SetVirtualData(self, row, column, text):
-+ attr = self.columns[column][1]
-+ if attr == 'name':
-+ try:
-+ text.encode('ascii')
-+ except UnicodeEncodeError:
-+ GMessage(parent = self, message = _("Please use only ASCII characters."))
-+ return
-+
-+ cat_id = self.cats_mgr.GetCategories()[row]
-+
-+ self.cats_mgr.setCategoryAttrs.disconnect(self.Update)
-+ self.cats_mgr.SetCategoryAttrs(cat_id, {attr : text})
-+ self.cats_mgr.setCategoryAttrs.connect(self.Update)
-+
-+ self.Select(row)
-+
-+ def Populate(self, columns):
-+ for i, col in enumerate(columns):
-+ self.InsertColumn(i, col[0])#wx.LIST_FORMAT_RIGHT
-+
-+ self.SetColumnWidth(0, 100)
-+ self.SetColumnWidth(1, 100)
-+
-+ def AddCategory(self):
-+
-+ self.cats_mgr.addedCategory.disconnect(self.Update)
-+ cat_id = self.cats_mgr.AddCategory()
-+ self.cats_mgr.addedCategory.connect(self.Update)
-+
-+ if cat_id < 0:
-+ GError(_("Maximum limit of categories number was reached."))
-+ return
-+ self.SetItemCount(len(self.cats_mgr.GetCategories()))
-+
-+ def DeleteCategory(self):
-+ indexList = sorted(self.GetSelectedIndices(), reverse = True)
-+ cats = []
-+ for i in indexList:
-+ # remove temporary raster
-+ cat_id = self.cats_mgr.GetCategories()[i]
-+
-+ cats.append(cat_id)
-+
-+ self.cats_mgr.deletedCategory.disconnect(self.Update)
-+ self.cats_mgr.DeleteCategory(cat_id)
-+ self.cats_mgr.deletedCategory.connect(self.Update)
-+
-+ self.SetItemCount(len(self.cats_mgr.GetCategories()))
-+
-+ def OnSel(self, event):
-+ event.Skip()
-+
-+ def GetSelectedIndices(self, state = wx.LIST_STATE_SELECTED):
-+ indices = []
-+ lastFound = -1
-+ while True:
-+ index = self.GetNextItem(lastFound, wx.LIST_NEXT_ALL, state)
-+ if index == -1:
-+ break
-+ else:
-+ lastFound = index
-+ indices.append(index)
-+ return indices
-+
-+ def OnEdit(self, event):
-+ currentItem = event.m_itemIndex
-+ currentCol = event.m_col
-+
-+ if currentCol == 1:
-+ dlg = wx.ColourDialog(self)
-+ dlg.GetColourData().SetChooseFull(True)
-+
-+ if dlg.ShowModal() == wx.ID_OK:
-+ color = dlg.GetColourData().GetColour().Get()
-+ color = ':'.join(map(str, color))
-+ self.SetVirtualData(currentItem, currentCol, color)
-+ dlg.Destroy()
-+ wx.CallAfter(self.SetFocus)
-+
-+ event.Skip()
-+
-+
-+ def DeselectAll(self):
-+ """!Deselect all items"""
-+ indexList = self.GetSelectedIndices()
-+ for i in indexList:
-+ self.Select(i, on = 0)
-+
-+ # no highlight
-+ self.OnCategorySelected(None)
-+
-+ def OnGetItemText(self, item, col):
-+ attr = self.columns[col][1]
-+ cat_id = self.cats_mgr.GetCategories()[item]
-+
-+ return self.cats_mgr.GetCategoryAttrs(cat_id)[attr]
-+
-+ def OnGetItemImage(self, item):
-+ return -1
-+
-+ def OnGetItemAttr(self, item):
-+ return None
-+
-+ def OnClassRightUp(self, event):
-+ """!Show context menu on right click"""
-+ item, flags = self.HitTest((event.GetX(), event.GetY()))
-+ if item != wx.NOT_FOUND and flags & wx.LIST_HITTEST_ONITEM:
-+ self.rightClickedItemIdx = item
-+
-+ self.popupZoomtoAreas = wx.NewId()
-+ self.Bind(wx.EVT_MENU, self.OnZoomToAreasByCat, id = self.popupZoomtoAreas)
-+
-+ # generate popup-menu
-+ menu = wx.Menu()
-+ menu.Append(self.popupZoomtoAreas, _("Zoom to training areas of selected class"))
-+
-+ self.PopupMenu(menu)
-+ menu.Destroy()
-+
-+ def OnZoomToAreasByCat(self, event):
-+ """!Zoom to areas of given category"""
-+ cat = self.stats_data.GetCategories()[self.rightClickedItemIdx]
-+ self.mapWindow.ZoomToAreasByCat(cat)
-+
-+class AddScattPlotDialog(wx.Dialog):
-+
-+ def __init__(self, parent, bands, id = wx.ID_ANY):
-+
-+ wx.Dialog.__init__(self, parent, title = ("Add scatter plot"), id = id)
-+
-+ self.bands = bands
-+
-+ self.scatt_id = None
-+
-+ self._createWidgets()
-+
-+ def _createWidgets(self):
-+
-+ self.labels = {}
-+ self.params = {}
-+
-+ self.band_1_label = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("Band 1:"))
-+
-+ self.band_1_ch = wx.ComboBox(parent = self, id = wx.ID_ANY,
-+ choices = self.bands,
-+ style = wx.CB_READONLY, size = (350, 30))
-+
-+ self.band_2_label = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("Band 2:"))
-+
-+ self.band_2_ch = wx.ComboBox(parent = self, id = wx.ID_ANY,
-+ choices = self.bands,
-+ style = wx.CB_READONLY, size = (350, 30))
-+
-+ # buttons
-+ self.btn_close = wx.Button(parent = self, id = wx.ID_CANCEL)
-+
-+ self.btn_ok = wx.Button(parent = self, id = wx.ID_OK, label = _("&OK"))
-+
-+ self._layout()
-+
-+ def _layout(self):
-+
-+ border = wx.BoxSizer(wx.VERTICAL)
-+ dialogSizer = wx.BoxSizer(wx.VERTICAL)
-+
-+ regionSizer = wx.BoxSizer(wx.HORIZONTAL)
-+
-+ dialogSizer.Add(item = self._addSelectSizer(title = self.band_1_label,
-+ sel = self.band_1_ch))
-+
-+ dialogSizer.Add(item = self._addSelectSizer(title = self.band_2_label,
-+ sel = self.band_2_ch))
-+
-+ # buttons
-+ self.btnsizer = wx.BoxSizer(orient = wx.HORIZONTAL)
-+
-+ self.btnsizer.Add(item = self.btn_close, proportion = 0,
-+ flag = wx.ALL | wx.ALIGN_CENTER,
-+ border = 10)
-+
-+ self.btnsizer.Add(item = self.btn_ok, proportion = 0,
-+ flag = wx.ALL | wx.ALIGN_CENTER,
-+ border = 10)
-+
-+ dialogSizer.Add(item = self.btnsizer, proportion = 0,
-+ flag = wx.ALIGN_CENTER)
-+
-+ border.Add(item = dialogSizer, proportion = 0,
-+ flag = wx.ALL, border = 5)
-+
-+ self.SetSizer(border)
-+ self.Layout()
-+ self.Fit()
-+
-+ # bindings
-+ self.btn_close.Bind(wx.EVT_BUTTON, self.OnClose)
-+ self.btn_ok.Bind(wx.EVT_BUTTON, self.OnOk)
-+
-+ def _addSelectSizer(self, title, sel):
-+ """!Helper layout function.
-+ """
-+ selSizer = wx.BoxSizer(orient = wx.VERTICAL)
-+
-+ selTitleSizer = wx.BoxSizer(wx.HORIZONTAL)
-+ selTitleSizer.Add(item = title, proportion = 1,
-+ flag = wx.LEFT | wx.TOP | wx.EXPAND, border = 5)
-+
-+ selSizer.Add(item = selTitleSizer, proportion = 0,
-+ flag = wx.EXPAND)
-+
-+ selSizer.Add(item = sel, proportion = 1,
-+ flag = wx.EXPAND | wx.ALL| wx.ALIGN_CENTER_VERTICAL,
-+ border = 5)
-+
-+ return selSizer
-+
-+ def OnClose(self, event):
-+ """!Close dialog
-+ """
-+ if not self.IsModal():
-+ self.Destroy()
-+ event.Skip()
-+
-+ def OnOk(self, event):
-+ """!
-+ """
-+ band_1 = self.band_1_ch.GetSelection()
-+ band_2 = self.band_2_ch.GetSelection()
-+
-+
-+ if band_1 == band_2:
-+ GError(_("Selected bands must be different."))
-+ return
-+
-+ #TODO axes selection
-+ if band_1 > band_2:
-+ tmp_band = band_2
-+ band_2 = band_1
-+ band_1 = band_2
-+
-+ self.scatt_id = idBandsToidScatt(band_1, band_2, len(self.bands))
-+
-+ event.Skip()
-+
-+ def GetScattId(self):
-+ return self.scatt_id
Index: gui/wxpython/Makefile
===================================================================
---- gui/wxpython/Makefile (revision 57506)
+--- gui/wxpython/Makefile (revision 57529)
+++ gui/wxpython/Makefile (working copy)
@@ -13,7 +13,7 @@
$(wildcard animation/* core/*.py dbmgr/* gcp/*.py gmodeler/* \
@@ -3191,7 +3355,7 @@
default: $(DSTFILES)
Index: gui/wxpython/vdigit/wxdigit.py
===================================================================
---- gui/wxpython/vdigit/wxdigit.py (revision 57506)
+--- gui/wxpython/vdigit/wxdigit.py (revision 57529)
+++ gui/wxpython/vdigit/wxdigit.py (working copy)
@@ -17,7 +17,7 @@
(and NumPy would be an excellent candidate for acceleration via
@@ -3711,7 +3875,7 @@
def GetLineCats(self, line):
Index: gui/wxpython/vdigit/toolbars.py
===================================================================
---- gui/wxpython/vdigit/toolbars.py (revision 57506)
+--- gui/wxpython/vdigit/toolbars.py (revision 57529)
+++ gui/wxpython/vdigit/toolbars.py (working copy)
@@ -17,6 +17,7 @@
import wx
@@ -3738,55 +3902,34 @@
return True
def StopEditing(self):
-Index: gui/wxpython/mapdisp/toolbars.py
+Index: gui/wxpython/iclass/dialogs.py
===================================================================
---- gui/wxpython/mapdisp/toolbars.py (revision 57506)
-+++ gui/wxpython/mapdisp/toolbars.py (working copy)
-@@ -239,7 +239,8 @@
- (MapIcons["scatter"], self.parent.OnScatterplot),
- (MapIcons["histogram"], self.parent.OnHistogramPyPlot),
- (BaseIcons["histogramD"], self.parent.OnHistogram),
-- (MapIcons["vnet"], self.parent.OnVNet)))
-+ (MapIcons["vnet"], self.parent.OnVNet),
-+ (MapIcons["scatter"], self.parent.OnScatterplot2)))
-
- def OnDecoration(self, event):
- """!Decorations overlay menu
-Index: gui/wxpython/mapdisp/frame.py
-===================================================================
---- gui/wxpython/mapdisp/frame.py (revision 57506)
-+++ gui/wxpython/mapdisp/frame.py (working copy)
-@@ -225,6 +225,7 @@
- #
- self.dialogs = {}
- self.dialogs['attributes'] = None
-+ self.dialogs['scatt_plot'] = None
- self.dialogs['category'] = None
- self.dialogs['barscale'] = None
- self.dialogs['legend'] = None
-@@ -1168,6 +1169,19 @@
- """!Returns toolbar with zooming tools"""
- return self.toolbars['map']
-
-+ def OnScatterplot2(self, event):
-+ """!Init interactive scatterplot tools
-+ """
-+ if self.dialogs['scatt_plot']:
-+ self.dialogs['scatt_plot'].Raise()
-+ return
+--- gui/wxpython/iclass/dialogs.py (revision 57529)
++++ gui/wxpython/iclass/dialogs.py (working copy)
+@@ -333,13 +333,19 @@
+ toolbar.SetCategories(catNames = catNames, catIdx = cats)
+ if name in catNames:
+ toolbar.choice.SetStringSelection(name)
++ cat = toolbar.GetSelectedCategoryIdx()
+ elif catNames:
+ toolbar.choice.SetSelection(0)
+-
++ cat = toolbar.GetSelectedCategoryIdx()
++ else:
++ cat = None
+
-+ from scatt_plot.dialogs import ScattPlotMainDialog
-+ self.dialogs['scatt_plot'] = ScattPlotMainDialog(parent=self, giface=self._giface)
-+
-+ self.dialogs['scatt_plot'].CenterOnScreen()
-+ self.dialogs['scatt_plot'].Show()
+ if toolbar.choice.IsEmpty():
+ toolbar.EnableControls(False)
+ else:
+ toolbar.EnableControls(True)
+
- def OnVNet(self, event):
- """!Dialog for v.net* modules
- """
++ self.mapWindow.CategoryChanged(cat)
+ # don't forget to update maps, histo, ...
+
+ def GetSelectedIndices(self, state = wx.LIST_STATE_SELECTED):
Index: gui/wxpython/iclass/toolbars.py
===================================================================
---- gui/wxpython/iclass/toolbars.py (revision 57506)
+--- gui/wxpython/iclass/toolbars.py (revision 57529)
+++ gui/wxpython/iclass/toolbars.py (working copy)
@@ -46,9 +46,7 @@
'importAreas' : MetaIcon(img = 'layer-import',
@@ -3822,7 +3965,7 @@
self.parent.OnCategoryManager),
Index: gui/wxpython/iclass/frame.py
===================================================================
---- gui/wxpython/iclass/frame.py (revision 57506)
+--- gui/wxpython/iclass/frame.py (revision 57529)
+++ gui/wxpython/iclass/frame.py (working copy)
@@ -64,6 +64,8 @@
IClassExportAreasDialog, IClassMapDialog
@@ -3942,7 +4085,7 @@
Index: gui/wxpython/iclass/plots.py
===================================================================
---- gui/wxpython/iclass/plots.py (revision 57506)
+--- gui/wxpython/iclass/plots.py (revision 57529)
+++ gui/wxpython/iclass/plots.py (working copy)
@@ -28,7 +28,7 @@
for each band and for one category. Coincidence plots show min max range
@@ -4074,46 +4217,52 @@
def DrawCoincidencePlots(self):
"""!Draw coincidence plots"""
for bandIdx in range(len(self.bandList)):
-Index: gui/wxpython/iclass/dialogs.py
+Index: gui/wxpython/mapdisp/toolbars.py
===================================================================
---- gui/wxpython/iclass/dialogs.py (revision 57506)
-+++ gui/wxpython/iclass/dialogs.py (working copy)
-@@ -333,13 +333,19 @@
- toolbar.SetCategories(catNames = catNames, catIdx = cats)
- if name in catNames:
- toolbar.choice.SetStringSelection(name)
-+ cat = toolbar.GetSelectedCategoryIdx()
- elif catNames:
- toolbar.choice.SetSelection(0)
--
-+ cat = toolbar.GetSelectedCategoryIdx()
-+ else:
-+ cat = None
+--- gui/wxpython/mapdisp/toolbars.py (revision 57529)
++++ gui/wxpython/mapdisp/toolbars.py (working copy)
+@@ -239,7 +239,8 @@
+ (MapIcons["scatter"], self.parent.OnScatterplot),
+ (MapIcons["histogram"], self.parent.OnHistogramPyPlot),
+ (BaseIcons["histogramD"], self.parent.OnHistogram),
+- (MapIcons["vnet"], self.parent.OnVNet)))
++ (MapIcons["vnet"], self.parent.OnVNet),
++ (MapIcons["scatter"], self.parent.OnScatterplot2)))
+
+ def OnDecoration(self, event):
+ """!Decorations overlay menu
+Index: gui/wxpython/mapdisp/frame.py
+===================================================================
+--- gui/wxpython/mapdisp/frame.py (revision 57529)
++++ gui/wxpython/mapdisp/frame.py (working copy)
+@@ -225,6 +225,7 @@
+ #
+ self.dialogs = {}
+ self.dialogs['attributes'] = None
++ self.dialogs['scatt_plot'] = None
+ self.dialogs['category'] = None
+ self.dialogs['barscale'] = None
+ self.dialogs['legend'] = None
+@@ -1168,6 +1169,19 @@
+ """!Returns toolbar with zooming tools"""
+ return self.toolbars['map']
+
++ def OnScatterplot2(self, event):
++ """!Init interactive scatterplot tools
++ """
++ if self.dialogs['scatt_plot']:
++ self.dialogs['scatt_plot'].Raise()
++ return
+
- if toolbar.choice.IsEmpty():
- toolbar.EnableControls(False)
- else:
- toolbar.EnableControls(True)
++ from scatt_plot.dialogs import ScattPlotMainDialog
++ self.dialogs['scatt_plot'] = ScattPlotMainDialog(parent=self, giface=self._giface)
++
++ self.dialogs['scatt_plot'].CenterOnScreen()
++ self.dialogs['scatt_plot'].Show()
+
-+ self.mapWindow.CategoryChanged(cat)
- # don't forget to update maps, histo, ...
-
- def GetSelectedIndices(self, state = wx.LIST_STATE_SELECTED):
-Index: lib/vector/Vlib/open.c
-===================================================================
---- lib/vector/Vlib/open.c (revision 57506)
-+++ lib/vector/Vlib/open.c (working copy)
-@@ -240,7 +240,9 @@
- }
- else {
- char file_path[GPATH_MAX];
--
-+ /* reduce to current mapset if search path was set */
-+ if(strcmp(Map->mapset, "") == 0)
-+ Map->mapset = G_store(G_mapset());
- /* temporary map: reduce to current mapset if search path
- * was set */
- if (strcmp(Map->mapset, "") == 0)
+ def OnVNet(self, event):
+ """!Dialog for v.net* modules
+ """
Index: lib/imagery/scatt.c
===================================================================
--- lib/imagery/scatt.c (revision 0)
@@ -5276,3 +5425,18 @@
+ return 0;
+}
+#endif
+Index: lib/vector/Vlib/open.c
+===================================================================
+--- lib/vector/Vlib/open.c (revision 57529)
++++ lib/vector/Vlib/open.c (working copy)
+@@ -240,7 +240,9 @@
+ }
+ else {
+ char file_path[GPATH_MAX];
+-
++ /* reduce to current mapset if search path was set */
++ if(strcmp(Map->mapset, "") == 0)
++ Map->mapset = G_store(G_mapset());
+ /* temporary map: reduce to current mapset if search path
+ * was set */
+ if (strcmp(Map->mapset, "") == 0)
More information about the grass-commit
mailing list