"""
UI-related class Ops_Array extracted from wolf_array.py.
Operations wx.Frame on WolfArray class -- provides the GUI for selecting,
operating on, masking, interpolating, and visualizing WolfArray data.
Author: HECE - University of Liege, Pierre Archambeau
Date: 2024
Copyright (c) 2024 University of Liege. All rights reserved.
This script and its content are protected by copyright law. Unauthorized
copying or distribution of this file, via any medium, is strictly prohibited.
"""
import os
import glob
import logging
import numpy as np
from pathlib import Path
from typing import TYPE_CHECKING
import wx
try:
from ..PyTranslate import _
except ImportError:
from ..GraphNotebook import PlotPanel
from ..CpGrid import CpGrid
from ..PyVertexvectors import Zones, vector, zone, wolfvertex
from ..wolf_array import OGLRenderer
from .wolf_array_ui import IntValidator
if TYPE_CHECKING:
from ..wolf_array import WolfArray
[docs]
class Ops_Array(wx.Frame):
"""
Operations wx.Frame on WolfArray class
This class is used to perform operations on a WolfArray
"""
def __init__(self, parentarray:"WolfArray", mapviewer=None):
""" Init the Ops_Array class
:param parentarray: WolfArray to operate on
:param mapviewer: WolfMapViewer to update if necessary
"""
[docs]
self.parentarray:WolfArray
self.parentarray = parentarray
from ..PyDraw import WolfMapViewer
[docs]
self.mapviewer:WolfMapViewer
self.mapviewer = mapviewer
[docs]
self.wx_exists = wx.App.Get() is not None
# active objects
[docs]
self.active_vector:vector = None
[docs]
self.active_zone:zone = None
[docs]
self.active_array:WolfArray = self.parentarray
[docs]
self.myzones = Zones(parent=self)
[docs]
self.myzonetmp = zone(name='tmp')
[docs]
self.vectmp = vector(name='tmp')
self.myzonetmp.add_vector(self.vectmp, forceparent=True)
self.myzones.add_zone(self.myzonetmp, forceparent=True)
self.myzones.mapviewer = mapviewer
if self.wx_exists:
self.set_GUI()
@property
[docs]
def usemask(self):
""" Return the usemask Value """
return self.selectrestricttomask.GetValue()
@property
[docs]
def idx(self):
""" Return the idx of the parentarray """
return self.parentarray.idx
[docs]
def get_mapviewer(self):
""" Retourne l'instance WolfMapViewer """
return self.mapviewer
[docs]
def get_linked_arrays(self):
""" Pour compatibilité avec la gestion de vecteur et WolfMapViewer """
if self.is_shared:
comp, diff = self._get_comp_elts_diff()
ret = {}
for elt in comp + diff:
ret[elt.idx] = elt
return ret
else:
return {self.parentarray.idx: self.parentarray}
[docs]
def set_GUI(self):
"""Set the wx GUI"""
super(Ops_Array, self).__init__(None, title=_('Operators'), size=(600, 700),
style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL)
# GUI
self.Bind(wx.EVT_CLOSE, self.onclose)
self.Bind(wx.EVT_SHOW, self.onshow)
self.SetSizeHints(wx.DefaultSize, wx.DefaultSize)
# GUI Notebook
self.array_ops = wx.Notebook(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize)
# panel Selection
# -----------------
self.selection = wx.Panel(self.array_ops, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL)
self.array_ops.AddPage(self.selection, _("Selection"), True)
# panel Operations
# -----------------
self.operation = wx.Panel(self.array_ops, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL)
self.array_ops.AddPage(self.operation, _("Operators"), False)
# panel Mask
# -----------------
self.mask = wx.Panel(self.array_ops, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL)
self.array_ops.AddPage(self.mask, _("Mask"), False)
# panel Interpolation
# ---------------------
# if self.parentarray.nb_blocks>0:
# self.Interpolation = None
# else:
self.Interpolation = wx.Panel(self.array_ops, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL)
self.array_ops.AddPage(self.Interpolation, _("Interpolation"), False)
# panel Tools/Misc
# -----------------
self.tools = wx.Panel(self.array_ops, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL)
self.array_ops.AddPage(self.tools, _("Miscellaneous"), False)
# panel PALETTE de couleurs
# -------------------------
self.Palette = PlotPanel(self.array_ops, wx.ID_ANY, toolbar=False)
self.palgrid = CpGrid(self.Palette, wx.ID_ANY, style=wx.WANTS_CHARS | wx.TE_CENTER)
self.palapply = wx.Button(self.Palette, wx.ID_ANY, _("Apply"), wx.DefaultPosition, wx.DefaultSize, 0)
self.palapply.SetToolTip(_('Apply changes in memory'))
self.palgrid.CreateGrid(16, 4)
self.palauto = wx.CheckBox(self.Palette, wx.ID_ANY, _("Automatic"), wx.DefaultPosition, wx.DefaultSize,
style=wx.CHK_CHECKED)
self.palauto.SetToolTip(_('Activating/Deactivating automatic colormap values distribution'))
self.uniforminparts = wx.CheckBox(self.Palette, wx.ID_ANY, _("Uniform in parts"), wx.DefaultPosition, wx.DefaultSize,
style=wx.CHK_UNCHECKED)
self.uniforminparts.SetToolTip(_('Activating/Deactivating linear interpolation'))
self.palalpha = wx.CheckBox(self.Palette, wx.ID_ANY, _("Opacity"), wx.DefaultPosition, wx.DefaultSize,
style=wx.CHK_CHECKED)
self.palalpha.SetToolTip(_('Activating/Deactivating transparency of the array'))
self.palshader = wx.CheckBox(self.Palette, wx.ID_ANY, _("Hillshade"), wx.DefaultPosition, wx.DefaultSize,
style=wx.CHK_CHECKED)
self.palshader.SetToolTip(_('Activating/Deactivating hillshade on colors and create if necessary a gray map'))
self.palalphaslider = wx.Slider(self.Palette, wx.ID_ANY, 100, 0, 100, wx.DefaultPosition, wx.DefaultSize,
wx.SL_HORIZONTAL, name='palslider')
self.palalphaslider.SetToolTip(_('Global opacity (transparent --> opaque)'))
self.palalphahillshade = wx.Slider(self.Palette, wx.ID_ANY, 100, 0, 100, wx.DefaultPosition, wx.DefaultSize,
wx.SL_HORIZONTAL, name='palalphaslider')
self.palalphahillshade.SetToolTip(_('Hillshade transparency (transparent-->opaque)'))
self.palazimuthhillshade = wx.Slider(self.Palette, wx.ID_ANY, 315, 0, 360, wx.DefaultPosition, wx.DefaultSize,
wx.SL_HORIZONTAL, name='palazimuthslider')
self.palazimuthhillshade.SetToolTip(_('Hillshade azimuth (0-->360)'))
self.palaltitudehillshade = wx.Slider(self.Palette, wx.ID_ANY, 0, 0, 90, wx.DefaultPosition, wx.DefaultSize,
wx.SL_HORIZONTAL, name='palaltitudeslider')
self.palaltitudehillshade.SetToolTip(_('Hillshade altitude (0-->90)'))
self.palsave = wx.Button(self.Palette, wx.ID_ANY, _("Save to file"), wx.DefaultPosition, wx.DefaultSize, 0)
self.palsave.SetToolTip(_('Save colormap on .pal file'))
sizer_loadpal = wx.BoxSizer(wx.HORIZONTAL)
self.palload = wx.Button(self.Palette, wx.ID_ANY, _("Load from file"), wx.DefaultPosition, wx.DefaultSize, 0)
self.palload.SetToolTip(_('Load colormap from .pal file'))
self._default_pal = wx.Button(self.Palette, wx.ID_ANY, _("Load precomputed"), wx.DefaultPosition, wx.DefaultSize, 0)
self._default_pal.SetToolTip(_('Load a default colormap available in the software'))
sizer_loadpal.Add(self.palload, 1, wx.EXPAND)
sizer_loadpal.Add(self._default_pal, 1, wx.EXPAND)
self.palimage = wx.Button(self.Palette, wx.ID_ANY, _("Create image"), wx.DefaultPosition, wx.DefaultSize, 0)
self.palimage.SetToolTip(_('Generate colormap image (horizontal, vertical or both) and save to disk'))
self.paldistribute = wx.Button(self.Palette, wx.ID_ANY, _("Evenly spaced"), wx.DefaultPosition, wx.DefaultSize, 0)
self.paldistribute.SetToolTip(_('Set colormap values based on minimum+maximum or minimum+step'))
if self.parentarray.mypal.automatic:
self.palauto.SetValue(1)
else:
self.palauto.SetValue(0)
if self.parentarray.mypal.interval_cst:
self.uniforminparts.SetValue(1)
else:
self.uniforminparts.SetValue(0)
self.palalpha.SetValue(1)
self.palchoosecolor = wx.Button(self.Palette, wx.ID_ANY, _("Choose color for current value"),
wx.DefaultPosition, wx.DefaultSize)
self.palchoosecolor.SetToolTip(_('Color dialog box for the current selected value in the grid'))
self.Palette.sizerfig.Add(self.palgrid, 1, wx.EXPAND)
self.Palette.sizer.Add(self.palauto, 1, wx.EXPAND)
self.Palette.sizer.Add(self.uniforminparts, 1, wx.EXPAND)
self.Palette.sizer.Add(self.palalpha, 1, wx.EXPAND)
self.Palette.sizer.Add(self.palalphaslider, 1, wx.EXPAND)
self.Palette.sizer.Add(self.palshader, 1, wx.EXPAND)
self.Palette.sizer.Add(self.palalphahillshade, 1, wx.EXPAND)
self.Palette.sizer.Add(self.palazimuthhillshade, 1, wx.EXPAND)
self.Palette.sizer.Add(self.palaltitudehillshade, 1, wx.EXPAND)
self.Palette.sizer.Add(self.palchoosecolor, 1, wx.EXPAND)
self.Palette.sizer.Add(self.palapply, 1, wx.EXPAND)
self.Palette.sizer.Add(sizer_loadpal, 1, wx.EXPAND)
self.Palette.sizer.Add(self.palsave, 1, wx.EXPAND)
self.Palette.sizer.Add(self.palimage, 1, wx.EXPAND)
self.Palette.sizer.Add(self.paldistribute, 1 , wx.EXPAND)
self.array_ops.AddPage(self.Palette, _("Palette"), False)
# HISTOGRAMMES
# ----------------
self.histo = PlotPanel(self.array_ops, wx.ID_ANY, toolbar=True)
self.histoupdate = wx.Button(self.histo, wx.ID_ANY, _("All data..."), wx.DefaultPosition, wx.DefaultSize, 0)
self.histoupdatezoom = wx.Button(self.histo, wx.ID_ANY, _("On zoom..."), wx.DefaultPosition, wx.DefaultSize, 0)
self.histoupdateerase = wx.Button(self.histo, wx.ID_ANY, _("Erase"), wx.DefaultPosition, wx.DefaultSize, 0)
self.histo.sizer.Add(self.histoupdate, 0, wx.EXPAND)
self.histo.sizer.Add(self.histoupdatezoom, 0, wx.EXPAND)
self.histo.sizer.Add(self.histoupdateerase, 0, wx.EXPAND)
self.array_ops.AddPage(self.histo, _("Histogram"), False)
# LINKS
# ----------------
self.links = wx.Panel(self.array_ops, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL)
self.array_ops.AddPage(self.links, _("Links"), False)
# Options
# -----------------
self._rendering_options = wx.Panel(self.array_ops, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL)
self.array_ops.AddPage(self._rendering_options, _("Rendering"), False)
self._rendering_options_sizer = wx.BoxSizer(wx.VERTICAL)
self._rendering_options.SetSizer(self._rendering_options_sizer)
# add a Dropdown list with the rendering options
self._rendering_options_listbox = wx.ListBox(self._rendering_options, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, [_('OpenGL tiled lists (draw only visible part of the array)'),
_('OpenGL Shader (draw all the array by modern shader)')], wx.LB_SINGLE)
self._rendering_options_sizer.Add(self._rendering_options_listbox, 1, wx.EXPAND | wx.ALL, 5)
# bind the listbox to a function that will update the rendering options
self._rendering_options_listbox.Bind(wx.EVT_LISTBOX, self.on_rendering_option_change)
# Interpolation
# ----------------
if self.Interpolation is not None:
gSizer1 = wx.GridSizer(0, 2, 0, 0)
self.interp2D = wx.Button(self.Interpolation, wx.ID_ANY, _("2D Interpolation on selection"), wx.DefaultPosition,
wx.DefaultSize, 0)
self.interp2D.SetToolTip(_('Spatial interpolation based on nodes stored in the named groups. \n The interpolation apply only on the current selection.'))
gSizer1.Add(self.interp2D, 0, wx.EXPAND)
self.interp2D.Bind(wx.EVT_BUTTON, self.interpolation2D)
self.m_button7 = wx.Button(self.Interpolation, wx.ID_ANY, _("Stage/Volume/Surface evaluation"), wx.DefaultPosition,
wx.DefaultSize, 0)
self.m_button7.SetToolTip(_('Evaluate stage-volume-surface relationship.\nResults : csv and array saved on disk\n\n CAUTION : This function will be applied only on the selected area except if you select "all".\nIn the latter case, the computation time could be long if the array are very large.'))
if self.parentarray.nb_blocks>0:
self.m_button7.Disable()
self.m_button7.SetToolTip(_('Evaluate stage-volume-surface relationship.\nResults : arrays and csv file saved on disk\n\nThis function is not available for multi-block arrays.'))
gSizer1.Add(self.m_button7, 0, wx.EXPAND)
self.m_button7.Bind(wx.EVT_BUTTON, self.volumesurface)
self.m_button8 = wx.Button(self.Interpolation, wx.ID_ANY, _("Interpolation on active zone \n polygons"),
wx.DefaultPosition, wx.DefaultSize, 0)
self.m_button8.SetToolTip(_('Spatial interpolation based on all polygons in active zone'))
gSizer1.Add(self.m_button8, 0, wx.EXPAND)
self.m_button8.Bind(wx.EVT_BUTTON, self.interp2Dpolygons)
self.m_button9 = wx.Button(self.Interpolation, wx.ID_ANY, _("Interpolation on active zone \n 3D polylines"),
wx.DefaultPosition, wx.DefaultSize, 0)
self.m_button9.SetToolTip(_('Spatial interpolation based on all polylines in active zone'))
gSizer1.Add(self.m_button9, 0, wx.EXPAND)
self.m_button9.Bind(wx.EVT_BUTTON, self.interp2Dpolylines)
self.m_button10 = wx.Button(self.Interpolation, wx.ID_ANY, _("Interpolation on active vector \n polygon"),
wx.DefaultPosition, wx.DefaultSize, 0)
self.m_button10.SetToolTip(_('Spatial interpolation based on active polygon'))
gSizer1.Add(self.m_button10, 0, wx.EXPAND)
self.m_button10.Bind(wx.EVT_BUTTON, self.interp2Dpolygon)
self.m_button11 = wx.Button(self.Interpolation, wx.ID_ANY, _("Interpolation on active vector \n 3D polyline"),
wx.DefaultPosition, wx.DefaultSize, 0)
self.m_button11.SetToolTip(_('Spatial interpolation based on active polyline'))
gSizer1.Add(self.m_button11, 0, wx.EXPAND)
self.m_button11.Bind(wx.EVT_BUTTON, self.interp2Dpolyline)
self.Interpolation.SetSizer(gSizer1)
self.Interpolation.Layout()
gSizer1.Fit(self.Interpolation)
# Tools
# ----------------
Toolssizer = wx.BoxSizer(wx.VERTICAL)
hbox = wx.BoxSizer(wx.HORIZONTAL)
self.lbl_nullval = wx.StaticText(self.tools,label=_('Null value'))
self.txt_nullval = wx.TextCtrl(self.tools,value=str(self.parentarray.nullvalue), style=wx.TE_CENTER)
self.txt_nullval.SetToolTip(_('Array null value'))
hbox.Add(self.lbl_nullval, 0, wx.EXPAND|wx.ALL)
hbox.Add(self.txt_nullval, 1, wx.EXPAND|wx.ALL)
self.ApplyTools = wx.Button(self.tools, wx.ID_ANY, _("Apply null value"), wx.DefaultPosition,wx.DefaultSize, 0)
self.nullborder = wx.Button(self.tools, wx.ID_ANY, _("Null border"), wx.DefaultPosition,wx.DefaultSize, 0)
self.filter_zone = wx.Button(self.tools, wx.ID_ANY, _("Filter zone"), wx.DefaultPosition,wx.DefaultSize, 0)
self.labelling = wx.Button(self.tools, wx.ID_ANY, _("Labelling"), wx.DefaultPosition,wx.DefaultSize, 0)
stats_sizer = wx.BoxSizer(wx.HORIZONTAL)
stats_sizer2 = wx.BoxSizer(wx.HORIZONTAL)
self.statistics = wx.Button(self.tools, wx.ID_ANY, _("Statistics"), wx.DefaultPosition,wx.DefaultSize, 0)
self.plot_stats = wx.Button(self.tools, wx.ID_ANY, _("Plot statistics\nCurrent zoom"), wx.DefaultPosition,wx.DefaultSize, 0)
self.plot_stats_zone = wx.Button(self.tools, wx.ID_ANY, _("Plot statistics\nCurrent zone"), wx.DefaultPosition,wx.DefaultSize, 0)
self.plot_stats_vector = wx.Button(self.tools, wx.ID_ANY, _("Plot statistics\nCurrent vector"), wx.DefaultPosition,wx.DefaultSize, 0)
stats_sizer.Add(self.statistics, 1, wx.EXPAND)
stats_sizer.Add(self.plot_stats, 1, wx.EXPAND)
stats_sizer2.Add(self.plot_stats_zone, 1, wx.EXPAND)
stats_sizer2.Add(self.plot_stats_vector, 1, wx.EXPAND)
self.clean = wx.Button(self.tools, wx.ID_ANY, _("Clean"), wx.DefaultPosition,wx.DefaultSize, 0)
self.extract_selection = wx.Button(self.tools, wx.ID_ANY, _("Extract selection"), wx.DefaultPosition,wx.DefaultSize, 0)
cont_sizer = wx.BoxSizer(wx.HORIZONTAL)
self._contour_int = wx.Button(self.tools, wx.ID_ANY, _("Contour"), wx.DefaultPosition, wx.DefaultSize, 0)
self._contour_list = wx.Button(self.tools, wx.ID_ANY, _("Contour specific"), wx.DefaultPosition, wx.DefaultSize, 0)
cont_sizer.Add(self._contour_int, 1, wx.EXPAND)
cont_sizer.Add(self._contour_list, 1, wx.EXPAND)
Toolssizer.Add(hbox, 0, wx.EXPAND)
Toolssizer.Add(self.ApplyTools, 1, wx.EXPAND)
Toolssizer.Add(self.nullborder, 1, wx.EXPAND)
Toolssizer.Add(self.filter_zone, 1, wx.EXPAND)
Toolssizer.Add(self.labelling, 1, wx.EXPAND)
Toolssizer.Add(self.clean, 1, wx.EXPAND)
Toolssizer.Add(self.extract_selection, 1, wx.EXPAND)
Toolssizer.Add(stats_sizer, 1, wx.EXPAND)
Toolssizer.Add(stats_sizer2, 1, wx.EXPAND)
Toolssizer.Add(cont_sizer, 1, wx.EXPAND)
self.ApplyTools.SetToolTip(_("Apply Nullvalue into memory/object"))
self.nullborder.SetToolTip(_("Set null value on the border of the array\n\nYou will be asked for the width of the border (in cells)"))
self.filter_zone.SetToolTip(_("Filter the array based on contiguous zones\n\nConservation of the ones which contain selected nodes"))
self.labelling.SetToolTip(_("Labelling of contiguous zones using Scipy.label function\n\nReplacing the current values by the labels"))
self.clean.SetToolTip(_("Clean the array\n\nRemove small isolated patches of data"))
self.extract_selection.SetToolTip(_("Extract the current selection"))
self.statistics.SetToolTip(_("Compute statistics on the array\n\nResults are displayed in a dialog box"))
self.plot_stats.SetToolTip(_("Plot statistics on the array\n\nResults are displayed in a separate figure"))
self.tools.SetSizer(Toolssizer)
self.tools.Layout()
Toolssizer.Fit(self.tools)
# Selection
# ----------------
bSizer15 = wx.BoxSizer(wx.VERTICAL)
bSizer21 = wx.BoxSizer(wx.HORIZONTAL)
bSizer16 = wx.BoxSizer(wx.VERTICAL)
bSizer16_1 = wx.BoxSizer(wx.VERTICAL)
bSizer16_2 = wx.BoxSizer(wx.VERTICAL)
bSizer16_3 = wx.BoxSizer(wx.VERTICAL)
selectmethodChoices = [_("by clicks"),
_("inside active vector"),
_("inside active zone"),
_("inside temporary vector"),
_("along active vector"),
_("along active zone"),
_("along temporary vector"),
# _("outside active vector")
]
self.selectmethod = wx.RadioBox(self.selection, wx.ID_ANY, _("How to select nodes?"), wx.DefaultPosition,
wx.DefaultSize, selectmethodChoices, 1, wx.RA_SPECIFY_COLS)
self.selectmethod.SetSelection(0)
self.selectmethod.SetToolTip(_("Selection mode : \n - one by one (keyboard shortcut N) \n- inside the currently activated polygon (keyboard shortcut V) \n- inside the currently activated zone (multipolygons) \n- inside a temporary polygon (keyboard shortcut B) \n- along the currently activated polyline \n- along the currently activated zone (multipolylines) \n- along a temporary polyline"))
bSizer16.Add(self.selectmethod, 0, wx.ALL, 5)
self.selectrestricttomask = wx.CheckBox(self.selection,wx.ID_ANY,_('Use mask to restrict'))
self.selectrestricttomask.SetValue(True)
self.selectrestricttomask.SetToolTip(_('If checked, the selection will be restricted by the mask data'))
bSizer16.Add(self.selectrestricttomask, 0, wx.ALL, 5)
self.LaunchSelection = wx.Button(self.selection, wx.ID_ANY,
_("Action !"), wx.DefaultPosition,
wx.DefaultSize, 0)
# self.LaunchSelection.SetBackgroundColour((0,128,64,255))
self.LaunchSelection.SetDefault()
# self.LaunchSelection.SetForegroundColour((255,255,255,255))
font = wx.Font(12, wx.FONTFAMILY_DECORATIVE, 0, 90, underline = False,faceName ="")
self.LaunchSelection.SetFont(font)
bSizer16.Add(self.LaunchSelection, 0, wx.EXPAND)
self.AllSelection = wx.Button(self.selection, wx.ID_ANY,
_("Select all nodes"), wx.DefaultPosition,
wx.DefaultSize, 0)
self.AllSelection.SetToolTip(_("Select all nodes in one click - store 'All' in the selection list"))
bSizer16_1.Add(self.AllSelection, 1, wx.EXPAND)
memory_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.MoveSelection = wx.Button(self.selection, wx.ID_ANY,
_("Move selection to..."), wx.DefaultPosition,
wx.DefaultSize, 0)
self.MoveSelection.SetToolTip(_("Store the current selection in an indexed list -- useful for some interpolation methods"))
self.ReselectMemory = wx.Button(self.selection, wx.ID_ANY,
_("Reselect from..."), wx.DefaultPosition,
wx.DefaultSize, 0)
self.ReselectMemory.SetToolTip(_("Reselect the nodes from an indexed list"))
memory_sizer.Add(self.MoveSelection, 1, wx.EXPAND)
memory_sizer.Add(self.ReselectMemory, 1, wx.EXPAND)
bSizer16_1.Add(memory_sizer, 1, wx.EXPAND)
reset_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.ResetSelection = wx.Button(self.selection, wx.ID_ANY,
_("Reset"), wx.DefaultPosition,
wx.DefaultSize, 0)
self.ResetSelection.SetToolTip(_("Reset the current selection list (keyboard shortcut r)"))
self.ResetAllSelection = wx.Button(self.selection, wx.ID_ANY,
_("Reset All"), wx.DefaultPosition,
wx.DefaultSize, 0)
self.ResetAllSelection.SetToolTip(_("Reset the current selection list and the indexed lists (keyboard shortcut R)"))
reset_sizer.Add(self.ResetSelection, 1, wx.EXPAND)
reset_sizer.Add(self.ResetAllSelection, 1, wx.EXPAND)
bSizer16_1.Add(reset_sizer, 1, wx.EXPAND)
save_load_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.SaveSelection = wx.Button(self.selection, wx.ID_ANY,
_("Save"), wx.DefaultPosition,
wx.DefaultSize, 0)
self.SaveSelection.SetToolTip(_("Save the current selection list to disk"))
self.LoadSelection = wx.Button(self.selection, wx.ID_ANY,
_("Load"), wx.DefaultPosition,
wx.DefaultSize, 0)
self.LoadSelection.SetToolTip(_("Load a selection list from disk"))
save_load_sizer.Add(self.SaveSelection, 1, wx.EXPAND)
save_load_sizer.Add(self.LoadSelection, 1, wx.EXPAND)
bSizer16_1.Add(save_load_sizer, 1, wx.EXPAND)
clipboad_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.to_clipboard_str = wx.Button(self.selection, wx.ID_ANY, _("To clipboard (str)"), wx.DefaultPosition,
wx.DefaultSize, 0)
self.to_clipboard_str.SetToolTip(_("Copy the current selection to the clipboard as a string"))
self.to_clipboard_script = wx.Button(self.selection, wx.ID_ANY, _("To clipboard (script)"), wx.DefaultPosition,
wx.DefaultSize, 0)
self.to_clipboard_script.SetToolTip(_("Copy the current selection to the clipboard as a script"))
clipboad_sizer.Add(self.to_clipboard_str, 1, wx.EXPAND)
clipboad_sizer.Add(self.to_clipboard_script, 1, wx.EXPAND)
erode_dilate_sizer = wx.BoxSizer(wx.VERTICAL)
self.expand_selection = wx.Button(self.selection, wx.ID_ANY, _("Dilate"), wx.DefaultPosition,
wx.DefaultSize, 0)
self.expand_selection.SetToolTip(_("Expand the current selection to the nearest nodes"))
self.contract_selection = wx.Button(self.selection, wx.ID_ANY, _("Erode"), wx.DefaultPosition,
wx.DefaultSize, 0)
self.contract_selection.SetToolTip(_("Contract the current selection to the nearest nodes"))
self.expand_unselect_interior = wx.Button(self.selection, wx.ID_ANY, _("Dilate contour"), wx.DefaultPosition,
wx.DefaultSize, 0)
self.expand_unselect_interior.SetToolTip(_("Expand the contour of the current selection and unselect the interior nodes"))
self.unselect_interior = wx.Button(self.selection, wx.ID_ANY, _("Unselect interior"), wx.DefaultPosition,
wx.DefaultSize, 0)
self.unselect_interior.SetToolTip(_("Conserve the contour of the current selection and unselect the interior nodes"))
er_dil_1 = wx.BoxSizer(wx.HORIZONTAL)
er_dil_2 = wx.BoxSizer(wx.HORIZONTAL)
er_dil_1.Add(self.expand_selection, 1, wx.EXPAND)
er_dil_1.Add(self.contract_selection, 1, wx.EXPAND)
er_dil_2.Add(self.expand_unselect_interior, 1, wx.EXPAND)
er_dil_2.Add(self.unselect_interior, 1, wx.EXPAND)
erode_dilate_sizer.Add(er_dil_1, 1, wx.EXPAND)
erode_dilate_sizer.Add(er_dil_2, 1, wx.EXPAND)
erode_dilate_options = wx.BoxSizer(wx.HORIZONTAL)
self._label_passes = wx.StaticText(self.selection, wx.ID_ANY, _("Passes"), wx.DefaultPosition, wx.DefaultSize, 0)
self._erode_dilate_value = wx.TextCtrl(self.selection, wx.ID_ANY, u"1", wx.DefaultPosition, wx.DefaultSize, style=wx.TE_CENTER)
self._erode_dilate_value.SetToolTip(_("Number of passes for the erode/dilate operation"))
self._erode_dilate_value.SetValidator(validator=IntValidator())
erode_dilate_options.Add(self._label_passes, 1, wx.EXPAND)
erode_dilate_options.Add(self._erode_dilate_value, 1, wx.EXPAND)
self._erode_dilate_structure = wx.ComboBox(self.selection, wx.ID_ANY, _("Cross"), wx.DefaultPosition, wx.DefaultSize,
["Cross", "Square"], wx.CB_READONLY)
self._erode_dilate_structure.SetToolTip(_("Structuring shape for the erode/dilate operation -- Cross-shaped is the 4 nearest nodes, Square-shaped is the 8 nearest nodes"))
erode_dilate_options.Add(self._erode_dilate_structure, 1, wx.EXPAND)
erode_dilate_sizer.Add(erode_dilate_options, 1, wx.EXPAND)
# MultiBlocks
# ----------------
# Add a listbox to define the active blocks
if self.parentarray.nb_blocks>0:
self._list = wx.ListBox(self.selection,
wx.ID_ANY,
wx.DefaultPosition,
wx.DefaultSize,
[_('All')] + [str(i) for i in range(1, self.parentarray.nb_blocks+1)],
style = wx.LB_MULTIPLE | wx.LB_NEEDED_SB)
self._list.SetToolTip(_("Active block"))
bSizer16.Add(self._list, 1, wx.EXPAND)
self._list.Bind(wx.EVT_LISTBOX, self.OnBlockSelect)
# self._open_block = wx.Button(self.selection, wx.ID_ANY, _("Open block"), wx.DefaultPosition,
# wx.DefaultSize, 0)
# self._open_block.SetToolTip(_("Open the Operation manager for the selected block"))
# self._open_block.Bind(wx.EVT_BUTTON, self.OnOpenBlock)
# bSizer16.Add(self._open_block, 0, wx.EXPAND)
bSizer16_1.Add(erode_dilate_sizer, 1, wx.EXPAND, 5)
bSizer16_1.Add(clipboad_sizer, 1, wx.EXPAND)
bSizer16.Add(bSizer16_1, 1, wx.EXPAND, 5)
# bSizer16.Add(bSizer16_2, 1, wx.EXPAND, 5)
bSizer21.Add(bSizer16, 1, wx.EXPAND, 5)
# VECTORS Manager
# ----------------
bSizer17 = wx.BoxSizer(wx.VERTICAL)
self.m_button2 = wx.Button(self.selection, wx.ID_ANY, _("Manage vectors"), wx.DefaultPosition, wx.DefaultSize,
0)
self.m_button2.SetToolTip(_("Open the vector manager attached to the array"))
bSizer17.Add(self.m_button2, 0, wx.EXPAND)
self.active_vector_id = wx.StaticText(self.selection, wx.ID_ANY, _("Active vector"), wx.DefaultPosition,
wx.DefaultSize, 0)
self.active_vector_id.Wrap(-1)
bSizer17.Add(self.active_vector_id, 0, wx.EXPAND)
self.CurActiveparent = wx.StaticText(self.selection, wx.ID_ANY, _("Active parent"), wx.DefaultPosition,
wx.DefaultSize, 0)
self.CurActiveparent.Wrap(-1)
bSizer17.Add(self.CurActiveparent, 0, wx.EXPAND)
self.loadvec = wx.Button(self.selection, wx.ID_ANY, _("Load from file..."), wx.DefaultPosition, wx.DefaultSize,
0)
self.loadvec.SetToolTip(_("Load a vector file into the vector manager"))
bSizer17.Add(self.loadvec, 0, wx.EXPAND)
self.saveas = wx.Button(self.selection, wx.ID_ANY, _("Save as..."), wx.DefaultPosition, wx.DefaultSize, 0)
bSizer17.Add(self.saveas, 0, wx.EXPAND)
self.saveas.SetToolTip(_("Save the vector manager to a new vector file"))
self.save = wx.Button(self.selection, wx.ID_ANY, _("Save"), wx.DefaultPosition, wx.DefaultSize, 0)
self.save.SetToolTip(_("Save the vector manager to the kwnown vector file"))
bSizer17.Add(self.save, 0, wx.EXPAND)
bSizer21.Add(bSizer17, 1, wx.EXPAND, 5)
bSizer15.Add(bSizer21, 1, wx.EXPAND, 5)
bSizer22 = wx.BoxSizer(wx.HORIZONTAL)
self.nbselect = wx.StaticText(self.selection, wx.ID_ANY, _("nb"), wx.DefaultPosition, wx.DefaultSize, 0)
self.nbselect.Wrap(-1)
bSizer22.Add(self.nbselect, 1, wx.EXPAND, 10)
self.minx = wx.StaticText(self.selection, wx.ID_ANY, _("xmin"), wx.DefaultPosition, wx.DefaultSize, 0)
self.minx.Wrap(-1)
self.minx.SetToolTip(_("X Mininum"))
bSizer22.Add(self.minx, 1, wx.EXPAND, 10)
self.maxx = wx.StaticText(self.selection, wx.ID_ANY, _("xmax"), wx.DefaultPosition, wx.DefaultSize, 0)
self.maxx.Wrap(-1)
self.maxx.SetToolTip(_("X Maximum"))
bSizer22.Add(self.maxx, 1, wx.EXPAND, 10)
self.miny = wx.StaticText(self.selection, wx.ID_ANY, _("ymin"), wx.DefaultPosition, wx.DefaultSize, 0)
self.miny.Wrap(-1)
self.miny.SetToolTip(_("Y Minimum"))
bSizer22.Add(self.miny, 1, wx.EXPAND, 10)
self.maxy = wx.StaticText(self.selection, wx.ID_ANY, _("ymax"), wx.DefaultPosition, wx.DefaultSize, 0)
self.maxy.Wrap(-1)
self.maxy.SetToolTip(_("Y Maximum"))
bSizer22.Add(self.maxy, 1, wx.EXPAND, 10)
bSizer15.Add(bSizer22, 0, wx.EXPAND, 5)
self.selection.SetSizer(bSizer15)
self.selection.Layout()
bSizer15.Fit(self.selection)
# Mask
sizermask = wx.BoxSizer(wx.VERTICAL)
self.mask.SetSizer(sizermask)
maskdata = wx.Button(self.mask, wx.ID_ANY, _("Mask nodes (only Condition )"), wx.DefaultPosition, wx.DefaultSize, 0)
maskdata.SetToolTip(_("This action will use the condition AND NOT the operator to mask some selected nodes \n If no node selectd --> Nothing to do !!"))
sizermask.Add(maskdata, 1, wx.EXPAND)
maskdata.Bind(wx.EVT_BUTTON, self.Onmask)
sizer_unmask = wx.BoxSizer(wx.HORIZONTAL)
unmaskall = wx.Button(self.mask, wx.ID_ANY, _("Unmask all"), wx.DefaultPosition, wx.DefaultSize, 0)
sizer_unmask.Add(unmaskall, 1, wx.EXPAND)
unmaskall.Bind(wx.EVT_BUTTON, self.Unmaskall)
unmaskall.SetToolTip(_("Unmask all values in the current array"))
unmasksel = wx.Button(self.mask, wx.ID_ANY, _("Unmask selection"), wx.DefaultPosition, wx.DefaultSize, 0)
sizer_unmask.Add(unmasksel, 1, wx.EXPAND)
unmasksel.Bind(wx.EVT_BUTTON, self.Unmask_selection)
unmasksel.SetToolTip(_("Unmask all values in the current selection \n If you wish to unmask some of the currently masked data, you have to first select the desired nodes by unchecking the 'Use mask to retrict' on the 'Selection' panel, otherwise it is impossible to select these nodes"))
sizermask.Add(sizer_unmask, 1, wx.EXPAND)
invertmask = wx.Button(self.mask, wx.ID_ANY, _("Invert mask"), wx.DefaultPosition, wx.DefaultSize, 0)
sizermask.Add(invertmask, 1, wx.EXPAND)
invertmask.Bind(wx.EVT_BUTTON, self.InvertMask)
invertmask.SetToolTip(_("Logical operation on mask -- mask = ~mask"))
sizer_maskunmask_poly = wx.BoxSizer(wx.HORIZONTAL)
mask_in_poly = wx.Button(self.mask, wx.ID_ANY, _("Mask inside active vector (+NoData)"), wx.DefaultPosition, wx.DefaultSize, 0)
sizer_maskunmask_poly.Add(mask_in_poly, 1, wx.EXPAND)
mask_in_poly.Bind(wx.EVT_BUTTON, self.Mask_inside_active_vector)
mask_in_poly.SetToolTip(_("Mask all values inside the active vector and set NoData to masked values"))
mask_out_poly = wx.Button(self.mask, wx.ID_ANY, _("Mask outside active vector (+NoData)"), wx.DefaultPosition, wx.DefaultSize, 0)
sizer_maskunmask_poly.Add(mask_out_poly, 1, wx.EXPAND)
mask_out_poly.Bind(wx.EVT_BUTTON, self.Mask_outside_active_vector)
mask_out_poly.SetToolTip(_("Mask all values outside the active vector and set NoData to masked values"))
sizermask.Add(sizer_maskunmask_poly, 1, wx.EXPAND)
sizer_maskunmask_poly_wonodata = wx.BoxSizer(wx.HORIZONTAL)
mask_in_poly_nodata = wx.Button(self.mask, wx.ID_ANY, _("Mask inside active vector"), wx.DefaultPosition, wx.DefaultSize, 0)
sizer_maskunmask_poly_wonodata.Add(mask_in_poly_nodata, 1, wx.EXPAND)
mask_in_poly_nodata.Bind(wx.EVT_BUTTON, self.Mask_inside_active_vector_wo_nodata)
mask_in_poly_nodata.SetToolTip(_("Mask all values inside the active vector"))
mask_out_poly_nodata = wx.Button(self.mask, wx.ID_ANY, _("Mask outside active vector"), wx.DefaultPosition, wx.DefaultSize, 0)
sizer_maskunmask_poly_wonodata.Add(mask_out_poly_nodata, 1, wx.EXPAND)
mask_out_poly_nodata.Bind(wx.EVT_BUTTON, self.Mask_outside_active_vector_wo_nodata)
mask_out_poly_nodata.SetToolTip(_("Mask all values outside the active vector"))
sizermask.Add(sizer_maskunmask_poly_wonodata, 1, wx.EXPAND)
mask_inside_polys =wx.BoxSizer(wx.HORIZONTAL)
mask_in_polys = wx.Button(self.mask, wx.ID_ANY, _("Mask inside active zone (+NoData)"), wx.DefaultPosition, wx.DefaultSize, 0)
mask_inside_polys.Add(mask_in_polys, 1, wx.EXPAND)
mask_in_polys.Bind(wx.EVT_BUTTON, self.Mask_inside_active_zone)
mask_in_polys.SetToolTip(_("Mask all values inside the active zone and set NoData to masked values"))
mask_inside_polys_nodata = wx.Button(self.mask, wx.ID_ANY, _("Mask inside active zone"), wx.DefaultPosition, wx.DefaultSize, 0)
mask_inside_polys.Add(mask_inside_polys_nodata, 1, wx.EXPAND)
mask_inside_polys_nodata.Bind(wx.EVT_BUTTON, self.Mask_inside_active_zone_wo_nodata)
mask_inside_polys_nodata.SetToolTip(_("Mask all values inside the active zone"))
sizermask.Add(mask_inside_polys, 1, wx.EXPAND)
self.mask.Layout()
sizermask.Fit(self.mask)
# Operations
sizeropgen = wx.BoxSizer(wx.VERTICAL)
sepopcond = wx.BoxSizer(wx.HORIZONTAL)
sizerop = wx.BoxSizer(wx.VERTICAL)
sizercond = wx.BoxSizer(wx.VERTICAL)
# bSizer26 = wx.BoxSizer( wx.VERTICAL )
# bSizer14.Add( bSizer26, 1, wx.EXPAND, 5 )
sepopcond.Add(sizercond, 1, wx.EXPAND)
sepopcond.Add(sizerop, 1, wx.EXPAND)
sizeropgen.Add(sepopcond, 1, wx.EXPAND)
operationChoices = [u"+", u"-", u"*", u"/", _("replace")]
self.choiceop = wx.RadioBox(self.operation, wx.ID_ANY,
_("Operator"), wx.DefaultPosition,
wx.DefaultSize, operationChoices, 1, wx.RA_SPECIFY_COLS)
self.choiceop.SetSelection(4)
sizerop.Add(self.choiceop, 1, wx.EXPAND)
self.opvalue = wx.TextCtrl(self.operation, wx.ID_ANY, u"1",
wx.DefaultPosition, wx.DefaultSize, style=wx.TE_CENTER)
sizerop.Add(self.opvalue, 0, wx.EXPAND)
self.opvalue.SetToolTip(_('Numeric value or "Null"'))
conditionChoices = [u"<", u"<=", u"=", u">=", u">", u"isNaN"]
self.condition = wx.RadioBox(self.operation, wx.ID_ANY, _("Condition"), wx.DefaultPosition, wx.DefaultSize,
conditionChoices, 1, wx.RA_SPECIFY_COLS)
self.condition.SetSelection(2)
sizercond.Add(self.condition, 1, wx.EXPAND)
self.condvalue = wx.TextCtrl(self.operation, wx.ID_ANY, u"0",
wx.DefaultPosition, wx.DefaultSize, style=wx.TE_CENTER)
sizercond.Add(self.condvalue, 0, wx.EXPAND)
self.ApplyOp = wx.Button(self.operation, wx.ID_ANY, _("Apply math operator (Condition and Operator)"), wx.DefaultPosition,
wx.DefaultSize, 0)
sizeropgen.Add(self.ApplyOp, 1, wx.EXPAND)
self.ApplyOp.SetToolTip(_("This action will use the condition AND the operator to manipulate the selected nodes"))
self.SelectOp = wx.Button(self.operation, wx.ID_ANY, _("Select nodes (only Condition)"), wx.DefaultPosition,
wx.DefaultSize, 0)
self.SelectOp.SetToolTip(_("This action will use the condition AND NOT the operator to select some nodes"))
sizeropgen.Add(self.SelectOp, 1, wx.EXPAND)
self.nbselect2 = wx.StaticText(self.operation, wx.ID_ANY, _("nb"), wx.DefaultPosition, wx.DefaultSize, 0)
self.nbselect2.Wrap(-1)
sizeropgen.Add(self.nbselect2, 0, wx.EXPAND)
self.nbselect2.SetToolTip(_("Number of selected nodes"))
self.operation.SetSizer(sizeropgen)
self.operation.Layout()
sizeropgen.Fit(self.operation)
gensizer = wx.BoxSizer(wx.VERTICAL)
gensizer.Add(self.array_ops, 1, wx.EXPAND | wx.ALL)
self.SetSizer(gensizer)
self.Layout()
self.Centre(wx.BOTH)
# Connect Events
self.LaunchSelection.Bind(wx.EVT_BUTTON, self.OnLaunchSelect)
self.AllSelection.Bind(wx.EVT_BUTTON, self.OnAllSelect)
self.MoveSelection.Bind(wx.EVT_BUTTON, self.OnMoveSelect)
self.ReselectMemory.Bind(wx.EVT_BUTTON, self.OnReselectMemory)
self.ResetSelection.Bind(wx.EVT_BUTTON, self.OnResetSelect)
self.ResetAllSelection.Bind(wx.EVT_BUTTON, self.OnResetAllSelect)
self.to_clipboard_str.Bind(wx.EVT_BUTTON, self.OnToClipboardStr)
self.to_clipboard_script.Bind(wx.EVT_BUTTON, self.OnToClipboardStr)
self.SaveSelection.Bind(wx.EVT_BUTTON, self.OnSaveSelection)
self.LoadSelection.Bind(wx.EVT_BUTTON, self.OnLoadSelection)
self.m_button2.Bind(wx.EVT_BUTTON, self.OnManageVectors)
self.loadvec.Bind(wx.EVT_BUTTON, self.OnLoadvec)
self.saveas.Bind(wx.EVT_BUTTON, self.OnSaveasvec)
self.save.Bind(wx.EVT_BUTTON, self.OnSavevec)
self.ApplyOp.Bind(wx.EVT_BUTTON, self.OnApplyOpMath)
self.ApplyTools.Bind(wx.EVT_BUTTON, self.OnApplyNullvalue)
self.nullborder.Bind(wx.EVT_BUTTON, self.OnNullBorder)
self.filter_zone.Bind(wx.EVT_BUTTON, self.OnFilterZone)
self.clean.Bind(wx.EVT_BUTTON, self.OnClean)
self.labelling.Bind(wx.EVT_BUTTON, self.OnLabelling)
self.statistics.Bind(wx.EVT_BUTTON, self.OnStatistics)
self.plot_stats.Bind(wx.EVT_BUTTON, self.OnPlotStatistics)
self.plot_stats_zone.Bind(wx.EVT_BUTTON, self.OnPlotStatisticsZone)
self.plot_stats_vector.Bind(wx.EVT_BUTTON, self.OnPlotStatisticsVector)
self.extract_selection.Bind(wx.EVT_BUTTON, self.OnExtractSelection)
self._contour_int.Bind(wx.EVT_BUTTON, self.OnContourInt)
self._contour_list.Bind(wx.EVT_BUTTON, self.OnContourList)
self.SelectOp.Bind(wx.EVT_BUTTON, self.OnApplyOpSelect)
self.palapply.Bind(wx.EVT_BUTTON, self.Onupdatepal)
self.palsave.Bind(wx.EVT_BUTTON, self.Onsavepal)
self.palload.Bind(wx.EVT_BUTTON, self.Onloadpal)
self._default_pal.Bind(wx.EVT_BUTTON, self.Onloaddefaultpal)
self.palimage.Bind(wx.EVT_BUTTON, self.Onpalimage)
self.paldistribute.Bind(wx.EVT_BUTTON, self.Onpaldistribute)
self.palchoosecolor.Bind(wx.EVT_BUTTON, self.OnClickColorPal)
self.histoupdate.Bind(wx.EVT_BUTTON, self.OnClickHistoUpdate)
self.histoupdatezoom.Bind(wx.EVT_BUTTON, self.OnClickHistoUpdate)
self.histoupdateerase.Bind(wx.EVT_BUTTON, self.OnClickHistoUpdate)
self.contract_selection.Bind(wx.EVT_BUTTON, self.OnContractSelection)
self.expand_selection.Bind(wx.EVT_BUTTON, self.OnExpandSelection)
self.expand_unselect_interior.Bind(wx.EVT_BUTTON, self.OnExpandUnselectInterior)
self.unselect_interior.Bind(wx.EVT_BUTTON, self.OnUnselectInterior)
icon = wx.Icon()
icon_path = Path(__file__).parent.parent / "apps/wolf.ico"
icon.CopyFromBitmap(wx.Bitmap(str(icon_path), wx.BITMAP_TYPE_ANY))
self.SetIcon(icon)
[docs]
def on_rendering_option_change(self, event):
""" Update the rendering of the array when a rendering option is changed """
sel = self._rendering_options_listbox.GetSelection()
rendering = OGLRenderer.get(sel)
self.parentarray.rendering_machine = rendering
[docs]
def update_rendering_machine(self, which=OGLRenderer):
self._rendering_options_listbox.SetSelection(which.value)
[docs]
def OnBlockSelect(self, event):
""" Select block """
self.parentarray.active_blocks = self._list.GetSelections()
# def OnOpenBlock(self, event):
# """ Open block """
# sel = self._list.GetSelections()
# if len(sel)==0:
# logging.info('No block selected')
# return
# elif len(sel)>1:
# logging.info('Only one block can be selected')
# return
# elif sel[0]==0:
# logging.info('All blocks selected -- Choose only one specific block')
# return
# else:
# keyblock = getkeyblock(sel[0], addone=False)
# ops = self.parentarray.myblocks[keyblock].myops
# if ops is not None:
# ops.Show()
[docs]
def interpolation2D(self, event: wx.MouseEvent):
""" calling Interpolation 2D """
keys = list(self.parentarray.SelectionData.selections.keys())
keys = [k for k in keys if len(self.parentarray.SelectionData.selections[k]) >0]
if len(keys) > 0:
if len(keys) == 1:
self.parentarray.interpolation2D(keys[0])
else:
with wx.SingleChoiceDialog(self, 'Choose the selection to interpolate', 'Selections', keys) as dlg:
if dlg.ShowModal() == wx.ID_OK:
selection = dlg.GetStringSelection()
self.parentarray.interpolation2D(selection)
dlg.Destroy()
[docs]
def Unmaskall(self, event: wx.MouseEvent):
"""
Unmask all values in the current array
@author Pierre Archambeau
"""
self.parentarray.mask_reset()
self.refresh_array()
[docs]
def Unmask_selection(self, event:wx.MouseEvent):
"""
Enlève le masque des éléments sélectionnés
@author Pierre Archambeau
"""
self.parentarray.SelectionData.unmask_selection()
[docs]
def InvertMask(self, event: wx.MouseEvent):
""" Invert mask """
self.parentarray.mask_invert()
self.refresh_array()
[docs]
def Mask_inside_active_vector(self, event: wx.MouseEvent):
""" Mask inside the active vector """
if self.active_vector is not None:
self.parentarray.mask_insidepoly(self.active_vector,)
self.refresh_array()
[docs]
def Mask_inside_active_vector_wo_nodata(self, event: wx.MouseEvent):
""" Mask inside the active vector without setting NoData """
if self.active_vector is not None:
self.parentarray.mask_insidepoly(self.active_vector, set_nullvalue=False)
self.refresh_array()
[docs]
def Mask_outside_active_vector(self, event: wx.MouseEvent):
""" Mask outside the active vector """
if self.active_vector is not None:
self.parentarray.mask_outsidepoly(self.active_vector)
self.refresh_array()
[docs]
def Mask_inside_active_zone(self, event: wx.MouseEvent):
""" Mask inside the active zone """
if self.active_zone is not None:
self.parentarray.mask_insidepolys(self.active_zone.myvectors)
self.refresh_array()
[docs]
def Mask_inside_active_zone_wo_nodata(self, event: wx.MouseEvent):
""" Mask inside the active zone without setting NoData """
if self.active_zone is not None:
self.parentarray.mask_insidepolys(self.active_zone.myvectors, set_nullvalue=False)
self.refresh_array()
[docs]
def Mask_outside_active_vector_wo_nodata(self, event: wx.MouseEvent):
""" Mask outside the active vector without setting NoData """
if self.active_vector is not None:
self.parentarray.mask_outsidepoly(self.active_vector, set_nullvalue=False)
self.refresh_array()
[docs]
def interp2Dpolygons(self, event: wx.MouseEvent):
"""
Bouton d'interpolation sous tous les polygones d'une zone
cf WolfArray.interp2Dpolygon
"""
self.parentarray.SelectionData.interp2Dpolygons(self.active_zone)
[docs]
def interp2Dpolygon(self, event: wx.MouseEvent):
"""
Bouton d'interpolation sous un polygone
cf WolfArray.interp2Dpolygon
"""
self.parentarray.SelectionData.interp2Dpolygon(self.active_vector)
[docs]
def interp2Dpolylines(self, event: wx.MouseEvent):
"""
Bouton d'interpolation sous toutes les polylignes de la zone
cf parent.interp2Dpolyline
"""
self.parentarray.SelectionData.interp2Dpolylines(self.active_zone)
[docs]
def interp2Dpolyline(self, event: wx.MouseEvent):
"""
Bouton d'interpolation sous la polyligne active
cf parent.interp2Dpolyline
"""
self.parentarray.SelectionData.interp2Dpolyline(self.active_vector)
[docs]
def volumesurface(self, event):
"""
Click on evaluation of stage-storage-surface relation
"""
self.parentarray.SelectionData.volumesurface()
[docs]
def OnAllSelect(self, event):
"""
Select all --> just put "all" in "myselection"
"""
self.parentarray.SelectionData.select_all()
self.parentarray.myops.nbselect.SetLabelText('All')
self.parentarray.myops.nbselect2.SetLabelText('All')
[docs]
def OnReselectMemory(self, event):
"""
Reselect from memory
"""
if self.parentarray.mngselection is not None:
self.parentarray.mngselection.reselect_from_memory()
[docs]
def OnMoveSelect(self, event):
"""Transfert de la sélection courante dans un dictionnaire"""
dlg = wx.TextEntryDialog(self, 'Choose id', 'id?')
ret = dlg.ShowModal()
if ret == wx.ID_CANCEL:
logging.info('Cancel transfer')
dlg.Destroy()
return
idtxt = dlg.GetValue()
dlg.Destroy()
if self.parentarray.SelectionData is not None:
if self.parentarray.SelectionData.nb > 0:
dlg = wx.ColourDialog(self)
ret = dlg.ShowModal()
if ret == wx.ID_OK:
color = dlg.GetColourData()
color = color.GetColour().Get()
dlg.Destroy()
else:
logging.info('Cancel transfer')
dlg.Destroy()
return
else:
color = (20,20,20,255)
self.parentarray.SelectionData.move_selectionto(idtxt, color)
[docs]
def OnContractSelection(self, event):
""" Contract selection """
nb = int(self._erode_dilate_value.GetValue())
if self._erode_dilate_structure.GetValue() == 'Cross':
structure = np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]])
else:
structure = np.ones((3, 3))
self.parentarray.SelectionData.erode_selection(nb, self.usemask, structure)
self.refresh_array()
[docs]
def OnExpandSelection(self, event):
""" Expand selection """
nb = int(self._erode_dilate_value.GetValue())
if self._erode_dilate_structure.GetValue() == 'Cross':
structure = np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]])
else:
structure = np.ones((3, 3))
self.parentarray.SelectionData.dilate_selection(nb, self.usemask, structure)
self.refresh_array()
[docs]
def OnExpandUnselectInterior(self, event):
""" Expand contour """
nb = int(self._erode_dilate_value.GetValue())
if self._erode_dilate_structure.GetValue() == 'Cross':
structure = np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]])
else:
structure = np.ones((3, 3))
self.parentarray.SelectionData.dilate_contour_selection(nb, self.usemask, structure)
self.refresh_array()
[docs]
def OnUnselectInterior(self, event):
""" Contract contour """
self.parentarray.SelectionData.erode_contour_selection()
self.refresh_array()
[docs]
def reset_selection(self):
"""
Reset of current selection
"""
self.parentarray.SelectionData.reset()
self.nbselect.SetLabelText('0')
self.nbselect2.SetLabelText('0')
self.minx.SetLabelText('0')
self.miny.SetLabelText('0')
self.maxx.SetLabelText('0')
self.maxy.SetLabelText('0')
[docs]
def reset_all_selection(self):
"""
Reset of current selection and stored ones
"""
self.reset_selection()
self.parentarray.SelectionData.reset_all()
[docs]
def OnResetSelect(self, event):
"""
Click on Reset of current selection
"""
self.reset_selection()
self.refresh_array()
[docs]
def OnResetAllSelect(self, event):
"""
Click on reset all
"""
self.reset_all_selection()
self.refresh_array()
[docs]
def OnSaveSelection(self, event):
"""
Save the current selection
"""
self.parentarray.SelectionData.save_selection()
[docs]
def OnLoadSelection(self, event):
"""
Load a selection
"""
self.parentarray.SelectionData.load_selection()
[docs]
def OnToClipboardStr(self, event):
"""
Copy the current selection to the clipboard as a string
"""
if event.GetId() == self.to_clipboard_str.GetId():
whichtype = 'string'
elif event.GetId() == self.to_clipboard_script.GetId():
whichtype = 'script'
if self.parentarray.mngselection is not None:
selectobj = self.parentarray.mngselection
if selectobj.nb > 0:
choices = [_("Current selection")]
for cur in selectobj.selections.items():
choices.append(cur[0])
dlg = wx.MultiChoiceDialog(None, "Choose the selection to copy", "Choices", choices)
ret = dlg.ShowModal()
if ret == wx.ID_CANCEL:
dlg.Destroy()
return
sel = dlg.GetSelections()
dlg.Destroy()
else:
sel = [0]
if len(sel) == 0:
return
elif len(sel) == 1:
sel = int(sel[0])
if sel == 0:
sel = None
else:
sel =choices[sel]
self.parentarray.mngselection.copy_to_clipboard(which = sel, typestr=whichtype)
else:
txt = ''
for cursel in sel:
if cursel == 0:
cursel = None
else:
cursel = choices[cursel]
if whichtype == 'script':
txt += self.parentarray.mngselection.get_script(which = cursel)
else:
txt += self.parentarray.mngselection.get_string(which = cursel)
txt += '\n'
if wx.TheClipboard.Open():
wx.TheClipboard.Clear()
wx.TheClipboard.SetData(wx.TextDataObject(txt))
wx.TheClipboard.Close()
else:
logging.error('Error in OnToClipboardStr')
[docs]
def OnApplyOpSelect(self, event):
""" Select nodes based on condition """
# condition operator
curcond = self.condition.GetSelection()
# condition value
curcondvalue = float(self.condvalue.GetValue())
self.parentarray.SelectionData.condition_select(curcond, curcondvalue, usemask=self.usemask)
self.refresh_array()
[docs]
def OnApplyNullvalue(self, event:wx.MouseEvent):
""" Apply null value to the array """
newnull = self.txt_nullval.Value
if newnull.lower() == 'nan':
newnull = np.nan
else:
newnull = float(newnull)
if self.parentarray.nullvalue!= newnull:
self.parentarray.nullvalue = newnull
self.parentarray.mask_data(newnull)
self.refresh_array()
[docs]
def refresh_array(self):
""" Force refresh of the parent array """
if self.parentarray is not None:
self.parentarray.reset_plot()
[docs]
def OnNullBorder(self, event:wx.MouseEvent):
""" Nullify the border of the array """
dlg = wx.SingleChoiceDialog(None, "Choose the border width [number of nodes]", "Border width", [str(i) for i in range(1, 20)])
ret = dlg.ShowModal()
if ret == wx.ID_CANCEL:
dlg.Destroy()
return
borderwidth = int(dlg.GetStringSelection())
self.parentarray.nullify_border(borderwidth)
[docs]
def OnFilterZone(self, event:wx.MouseEvent):
""" Filter the array based on contiguous zones """
self.parentarray.filter_zone()
dlg = wx.MessageDialog(None, _('Do you want to set null value in the masked data ?'), _('Masked data'), wx.YES_NO | wx.ICON_QUESTION)
ret = dlg.ShowModal()
if ret == wx.ID_YES:
self.parentarray.set_nullvalue_in_mask()
dlg.Destroy()
[docs]
def OnClean(self, event:wx.MouseEvent):
""" Clean the array -- Remove the isolated cells """
dlg = wx.NumberEntryDialog(None, 'Minimum number of nodes for a patch to be kept', 'Minimum number of nodes', 'Minimum number of nodes', 10, 1, 1000)
if dlg.ShowModal() != wx.ID_OK:
dlg.Destroy()
return
minnodes = dlg.GetValue()
self.parentarray.clean_small_patches(minnodes)
dlg.Destroy()
dlg = wx.MessageDialog(None, _('Do you want to set null value in the masked data ?'), _('Masked data'), wx.YES_NO | wx.ICON_QUESTION)
ret = dlg.ShowModal()
if ret == wx.ID_YES:
self.parentarray.set_nullvalue_in_mask()
dlg.Destroy()
[docs]
def OnLabelling(self, event:wx.MouseEvent):
""" Labelling of contiguous zones """
self.parentarray.labelling()
[docs]
def OnStatistics(self, event:wx.MouseEvent):
""" Statistics on the array """
ret = self.parentarray.statistics()
ret_frame = wx.Frame(None, -1, _('Statistics of {} on selected values').format(self.parentarray.idx), size = (300, 200))
icon = wx.Icon()
icon_path = Path(__file__).parent.parent / "apps/wolf.ico"
icon.CopyFromBitmap(wx.Bitmap(str(icon_path), wx.BITMAP_TYPE_ANY))
ret_frame.SetIcon(icon)
ret_panel = wx.Panel(ret_frame, -1)
sizer = wx.BoxSizer(wx.VERTICAL)
# Add a cpGrid and put statistics in it
cp = CpGrid(ret_panel, wx.ID_ANY, style=wx.WANTS_CHARS | wx.TE_CENTER)
cp.CreateGrid(len(ret), 2)
sizer.Add(cp, 1, wx.EXPAND)
for i, (key,val) in enumerate(ret.items()):
if i != len(ret)-1:
cp.SetCellValue(i, 0, key)
cp.SetCellValue(i, 1, str(val))
ret_panel.SetSizer(sizer)
ret_panel.Layout()
ret_frame.SetSize((300, 200))
ret_frame.Centre()
ret_frame.Show()
[docs]
def OnPlotStatistics(self, event:wx.MouseEvent):
""" Plot statistics on the current zoom"""
from ..analyze_poly import Array_analysis_onepolygon
logging.info(_('Plotting statistics on the current zoom'))
if self.parentarray.nbnotnull > 50_000:
logging.info(_('Quite large array - please wait a bit...'))
analyzer = Array_analysis_onepolygon(self.parentarray, self.mapviewer.get_bounds_as_polygon())
try:
analyzer.plot_values(engine = 'plotly')
except:
logging.error(_('Error in plotly engine - Try seaborn engine'))
logging.info(_('If you have not installed plotly, please install it with "pip install plotly"'))
try:
analyzer.plot_values(engine = 'seaborn')
except:
logging.error('Error in seaborn engine')
logging.info(_('Done !'))
[docs]
def OnPlotStatisticsZone(self, event:wx.MouseEvent):
""" Plot statistics on the current zone """
if self.mapviewer is not None:
if self.mapviewer.active_zone is not None:
from ..analyze_poly import Array_analysis_polygons
logging.info(_('Plotting statistics on the current zone'))
analyzer = Array_analysis_polygons(self.parentarray, self.mapviewer.active_zone)
try:
analyzer.plot_values(engine = 'plotly')
except:
logging.error(_('Error in plotly engine - Try seaborn engine'))
logging.info(_('If you have not installed plotly, please install it with "pip install plotly"'))
try:
analyzer.plot_values(engine = 'seaborn')
except:
logging.error('Error in seaborn engine')
logging.info(_('Done !'))
else:
logging.error(_('No active zone to plot statistics'))
logging.info(_('Please select a zone to plot statistics'))
else:
logging.error(_('No active mapviewer to plot statistics'))
[docs]
def OnPlotStatisticsVector(self, event:wx.MouseEvent):
""" Plot statistics on the current vector """
if self.mapviewer is not None:
if self.mapviewer.active_vector is not None:
from ..analyze_poly import Array_analysis_onepolygon
logging.info(_('Plotting statistics on the current vector'))
# Get the active vector
analyzer = Array_analysis_onepolygon(self.parentarray, self.mapviewer.active_vector)
try:
analyzer.plot_values(engine = 'plotly')
except:
logging.error(_('Error in plotly engine - Try seaborn engine'))
logging.info(_('If you have not installed plotly, please install it with "pip install plotly"'))
try:
analyzer.plot_values(engine = 'seaborn')
except:
logging.error('Error in seaborn engine')
logging.info(_('Done !'))
else:
logging.error(_('No active vector to plot statistics'))
logging.info(_('Please select a vector to plot statistics'))
else:
logging.error(_('No active mapviewer to plot statistics'))
[docs]
def OnContourInt(self, event:wx.MouseEvent):
""" Create contour - number of contours """
with wx.NumberEntryDialog(None, 'Number of contours', 'Number of contours', 'Number of contours', 20, 1, 1000) as dlg:
if dlg.ShowModal() == wx.ID_OK:
nbcontours = dlg.GetValue()
logging.info(_('Baking contour'))
cont = self.parentarray.contour(levels = nbcontours)
logging.info(_('Add contour to viewer'))
cont.prep_listogl()
mapv = self.get_mapviewer()
mapv.add_object('vector', newobj = cont, id = cont.idx)
self.get_mapviewer().Paint()
logging.info(_('Done !'))
[docs]
def OnContourList(self, event:wx.MouseEvent):
""" Create contour - list of values """
if self.parentarray is None:
logging.error('No parent array')
logging.info('Nothing to do ! -- Check the routine OnContourList if needed !')
return
with wx.TextEntryDialog(None, 'List of specific values separated by comma or tuple (min;max;step)\n\nValues in tuples must be separated by ";"',
'List of values', f'{self.parentarray.zmin}, {self.parentarray.zmax}') as dlg:
if dlg.ShowModal() == wx.ID_OK:
txt = dlg.GetValue()
self._levels = []
if ',' in txt:
for cur in txt.split(','):
if '(' in cur:
cur = cur.replace('(', '').replace(')', '')
cur = cur.split(';')
if len(cur) == 3:
minval = float(cur[0])
maxval = float(cur[1])
step = float(cur[2])
self._levels.extend(np.arange(minval, maxval, step))
else:
logging.warning('Ignoring tuple with wrong number of values - {}'.format(cur))
else:
try:
self._levels.append(float(cur))
except:
logging.error('Error in chain text to float - {}'.format(cur))
elif '(' in txt:
cur = txt.replace('(', '').replace(')', '')
cur = cur.split(';')
if len(cur) == 3:
minval = float(cur[0])
maxval = float(cur[1])
step = float(cur[2])
self._levels.extend(np.arange(minval, maxval, step))
else:
logging.warning('Ignoring tuple with wrong number of values - {}'.format(cur))
else:
try:
self._levels = [float(txt)]
except:
logging.error('Error in chain text to float - {}'.format(txt))
return
if isinstance(self._levels, list):
if len(self._levels) == 0:
logging.error('Nothing to do !')
return
logging.info(_('Baking contour'))
cont = self.parentarray.contour(levels = self._levels)
logging.info(_('Add contour to viewer'))
cont.prep_listogl()
self.get_mapviewer().add_object('vector', newobj = cont, id = cont.idx)
self.get_mapviewer().Paint()
logging.info(_('Done !'))
[docs]
def OnApplyOpMath(self, event:wx.MouseEvent):
""" Apply math operator to the array """
# operator type
curop = self.choiceop.GetSelection()
# condition type
curcond = self.condition.GetSelection()
# operator value
opval = self.opvalue.GetValue()
if opval.lower() == 'null' or opval.lower() == 'nan' or opval.lower() == 'nul':
curopvalue = self.parentarray.nullvalue
else:
try:
tmp_float = float(opval)
except:
logging.error('Error in float conversion - Do you try to set null value ? - Accepted values : "Null" or "NaN"')
return
curopvalue = tmp_float
# condition value
curcondvalue = self.condvalue.GetValue()
if curcondvalue.lower() == 'null' or curcondvalue.lower() == 'nan' or curcondvalue.lower() == 'nul':
curcondvalue = self.parentarray.nullvalue
else:
try:
tmp_float = float(curcondvalue)
except:
logging.error('Error in float conversion - Do you try to set null value ? - Accepted values : "Null" or "NaN"')
return
curcondvalue = tmp_float
self.parentarray.SelectionData.treat_select(curop, curcond, curopvalue, curcondvalue)
[docs]
def Onmask(self, event:wx.MouseEvent):
""" Mask nodes based on condition """
curop = self.choiceop.GetSelection()
curcond = self.condition.GetSelection()
try:
curopvalue = float(self.opvalue.GetValue())
except:
logging.error('Error in float conversion - operator')
return
try:
curcondvalue = float(self.condvalue.GetValue())
except:
logging.error('Error in float conversion - condition')
return
self.parentarray.SelectionData.mask_condition(curop, curcond, curopvalue, curcondvalue)
self.refresh_array()
[docs]
def OnManageVectors(self, event:wx.MouseEvent):
""" Open vector manager """
self.show_structure_OpsVectors()
[docs]
def show_structure_OpsVectors(self):
""" Show the structure of the vector manager """
if self.mapviewer is not None:
if self.mapviewer.linked:
# The viewer is linked to other viewers
if self.mapviewer.link_shareopsvect:
# The viewer shares the vector manager with the other viewers
if self.myzones.get_mapviewer() in self.mapviewer.linkedList:
# The viewer is in the active linked viewers
self.myzones.showstructure()
return
self.myzones.showstructure()
[docs]
def hide_properties(self):
""" Hide the properties panel """
try:
self.myzones.hide_properties()
self.Hide()
except Exception as e:
logging.error('Error in hide_properties : %s' % e)
@property
[docs]
def is_shared(self):
""" Check if the vector manager is shared """
if self.mapviewer is not None:
if self.mapviewer.linked:
if not self.mapviewer.linkedList is None:
comp = None
for curviewer in self.mapviewer.linkedList:
if curviewer.compare_results is not None:
comp = curviewer.compare_results
break
if comp is not None:
elts = comp.elements
diff = comp.diff
if self.parentarray in elts or self.parentarray in diff and self.mapviewer.link_shareopsvect:
return True
return False
[docs]
def _get_comp_elts_diff(self):
""" Get the elements and the differences of the linked arrays """
if self.mapviewer is not None:
if self.mapviewer.linked:
if not self.mapviewer.linkedList is None:
comp = None
for curviewer in self.mapviewer.linkedList:
if curviewer.compare_results is not None:
comp = curviewer.compare_results
break
if comp is not None:
return comp.elements, comp.diff
return [], []
[docs]
def _link_zones(self):
""" Link the same vector manager to all the linked arrays """
if self.mapviewer is not None:
if self.mapviewer.linked:
if not self.mapviewer.linkedList is None:
comp = None
for curviewer in self.mapviewer.linkedList:
if curviewer.compare_results is not None:
comp = curviewer.compare_results
break
if comp is not None:
elts = comp.elements
for curelt in elts:
if self.parentarray is not curelt:
curelt.myops.myzones = self.myzones
curelt.myops.fnsave = self.fnsave
diff = comp.diff
for curelt in diff:
if self.parentarray is not curelt:
curelt.myops.myzones = self.myzones
curelt.myops.fnsave = self.fnsave
for curviewer in self.mapviewer.linkedList:
curviewer.Refresh()
[docs]
def OnLoadvec(self, event:wx.MouseEvent):
""" Load vector file """
dlg = wx.FileDialog(None, 'Select file',
wildcard='Vec file (*.vec)|*.vec|Vecz file (*.vecz)|*.vecz|Dxf file (*.dxf)|*.dxf|All (*.*)|*.*', style=wx.FD_OPEN)
ret = dlg.ShowModal()
if ret == wx.ID_CANCEL:
dlg.Destroy()
return
self.fnsave = dlg.GetPath()
dlg.Destroy()
self.myzones = Zones(self.fnsave, parent= self, shared= self.is_shared)
# Link the same vector manager to all the linked arrays
if self.mapviewer is not None:
if self.mapviewer.linked:
self._link_zones()
else:
self.mapviewer.Refresh()
[docs]
def OnSaveasvec(self, event:wx.MouseEvent):
""" Save vector file """
dlg = wx.FileDialog(None, 'Select file', wildcard='Vec file (*.vec)|*.vec|Vecz file (*.vecz)|*.vecz|All (*.*)|*.*', style=wx.FD_SAVE)
ret = dlg.ShowModal()
if ret == wx.ID_CANCEL:
dlg.Destroy()
return
self.fnsave = dlg.GetPath()
dlg.Destroy()
self.myzones.saveas(self.fnsave)
# Link the same vector manager to all the linked arrays
#FIXME : only works if the active_array is the good one
if self.mapviewer is not None:
if self.mapviewer.linked:
if not self.mapviewer.linkedList is None:
for curViewer in self.mapviewer.linkedList:
if curViewer.link_shareopsvect:
curViewer.active_array.myops.fnsave = self.fnsave
[docs]
def OnSavevec(self, event:wx.MouseEvent):
""" Save vector file """
if self.fnsave == '':
return
self.myzones.saveas(self.fnsave)
[docs]
def select_node_by_node(self):
"""
Select nodes by individual clicks
Set the right action in the mapviewer who will attend the clicks
"""
if self.mapviewer is not None:
self.mapviewer.start_action('select node by node', _('Please click on the desired nodes...'))
self.mapviewer.active_array = self.parentarray
self.mapviewer.set_label_selecteditem(self.parentarray.idx)
[docs]
def select_zone_inside_manager(self):
"""
Select nodes inside the active zone (manager)
"""
if self.active_zone is None:
logging.warning(_('Please select an active zone !'))
return
for curvec in self.active_zone.myvectors:
self._select_vector_inside_manager(curvec)
self.refresh_array()
[docs]
def select_vector_inside_manager(self):
"""
Select nodes inside the active vector (manager)
"""
if self.active_vector is None:
logging.warning(_('Please select an active vector !'))
return
if self.active_vector.nbvertices == 0:
logging.warning(_('Please add points to vector or select another !'))
return
logging.info(_('Select nodes inside the active polygon/vector...'))
self._select_vector_inside_manager(self.active_vector)
self.refresh_array()
[docs]
def select_vector_outside_manager(self):
""" Select nodes outside the active vector (manager) """
if self.active_vector is None:
logging.warning(_('Please activate a vector !'))
return
if self.active_vector.nbvertices == 0:
logging.warning(_('Please add points to vector or select another !'))
return
logging.info(_('Select nodes outside the active polygon/vector...'))
self._select_vector_outside_manager(self.active_vector)
self.refresh_array()
[docs]
def _select_vector_inside_manager(self, vect: vector):
""" Select nodes inside a vector or set action to add vertices to a vector by clicks"""
if vect.nbvertices > 2:
self.parentarray.SelectionData.select_insidepoly(vect)
elif self.mapviewer is not None:
if vect.nbvertices < 3:
logging.info(_('Please add points to vector !'))
self.mapviewer.start_action('select by vector inside', _('Please draw a polygon...'))
self.mapviewer.active_array = self.parentarray
self.mapviewer.set_label_selecteditem(self.parentarray.idx)
self.Active_vector(vect)
firstvert = wolfvertex(0., 0.)
self.vectmp.add_vertex(firstvert)
[docs]
def _select_vector_outside_manager(self, vect: vector):
""" Select nodes outside a vector or set action to add vertices to a vector by clicks"""
if vect.nbvertices > 2:
self.parentarray.SelectionData.select_outsidepoly(vect)
elif self.mapviewer is not None:
if vect.nbvertices < 3:
logging.info(_('Please add points to vector !'))
self.mapviewer.start_action('select by vector outside', _('Please draw a polygon...'))
self.mapviewer.active_array = self.parentarray
self.mapviewer.set_label_selecteditem(self.parentarray.idx)
self.Active_vector(vect)
firstvert = wolfvertex(0., 0.)
self.vectmp.add_vertex(firstvert)
[docs]
def select_zone_under_manager(self):
""" Select nodes along the active zone (manager) """
if self.active_zone is None:
logging.warning(_('Please activate a zone !'))
return
logging.info(_('Select nodes along the active zone - all polylines...'))
for curvec in self.active_zone.myvectors:
self._select_vector_under_manager(curvec)
self.refresh_array()
[docs]
def select_vector_under_manager(self):
""" Select nodes along the active vector (manager) """
if self.active_vector is None:
logging.warning(_('Please activate a vector !'))
return
logging.info(_('Select nodes along the active polyline/vector...'))
self._select_vector_under_manager(self.active_vector)
self.refresh_array()
[docs]
def _select_vector_under_manager(self, vect: vector):
""" Select nodes along a vector or set action to add vertices to a vector by clicks """
if vect.nbvertices > 1:
self.parentarray.SelectionData.select_underpoly(vect)
elif self.mapviewer is not None:
if vect.nbvertices < 2:
logging.info(_('Please add points to vector by clicks !'))
self.mapviewer.start_action('select by vector along', _('Please draw a polyline...'))
self.mapviewer.active_array = self.parentarray
self.mapviewer.set_label_selecteditem(self.parentarray.idx)
self.Active_vector(vect)
firstvert = wolfvertex(0., 0.)
self.vectmp.add_vertex(firstvert)
[docs]
def select_vector_inside_tmp(self):
""" Select nodes inside the temporary vector """
if self.mapviewer is not None:
logging.info(_('Select nodes inside a temporary polygon/vector...'))
logging.info(_('Please add points to vector by clicks !'))
self.mapviewer.start_action('select by tmp vector inside', _('Please draw a polygon...'))
self.vectmp.reset()
self.Active_vector(self.vectmp)
self.mapviewer.active_array = self.parentarray
self.mapviewer.set_label_selecteditem(self.parentarray.idx)
firstvert = wolfvertex(0., 0.)
self.vectmp.add_vertex(firstvert)
[docs]
def select_vector_under_tmp(self):
""" Select nodes along the temporary vector """
if self.mapviewer is not None:
logging.info(_('Select nodes along a temporary polygon/vector...'))
logging.info(_('Please add points to vector by clicks !'))
self.mapviewer.start_action('select by tmp vector along', _('Please draw a polyline...'))
self.vectmp.reset()
self.Active_vector(self.vectmp)
self.mapviewer.active_array = self.parentarray
self.mapviewer.set_label_selecteditem(self.parentarray.idx)
firstvert = wolfvertex(0., 0.)
self.vectmp.add_vertex(firstvert)
[docs]
def OnLaunchSelect(self, event:wx.MouseEvent):
""" Action button """
id = self.selectmethod.GetSelection()
if id == 0:
logging.info(_('Node selection by individual clicks'))
logging.info(_(''))
logging.info(_(' Clicks on the desired nodes...'))
logging.info(_(''))
self.select_node_by_node()
elif id == 1:
logging.info(_('Node selection inside active vector (manager)'))
self.select_vector_inside_manager()
elif id == 2:
logging.info(_('Node selection inside active zone (manager)'))
self.select_zone_inside_manager()
elif id == 3:
logging.info(_('Node selection inside temporary vector'))
logging.info(_(''))
logging.info(_(' Choose vector by clicks...'))
logging.info(_(''))
self.select_vector_inside_tmp()
elif id == 4:
logging.info(_('Node selection along active vector (manager)'))
self.select_vector_under_manager()
elif id == 5:
logging.info(_('Node selection along active zone (manager)'))
self.select_zone_under_manager()
elif id == 6:
logging.info(_('Node selection along temporary vector'))
logging.info(_(''))
logging.info(_(' Choose vector by clicks...'))
logging.info(_(''))
self.select_vector_under_tmp()
# elif id == 7:
# logging.info(_('Node selection outside active vector (manager)'))
# self.select_vector_outside_manager()
[docs]
def onclose(self, event:wx.MouseEvent):
""" Hide the window """
self.Hide()
[docs]
def onshow(self, event:wx.MouseEvent):
""" Show the window - set string with null value and update palette """
if self.parentarray.nullvalue == np.nan:
self.txt_nullval.Value = 'nan'
else :
self.txt_nullval.Value = str(self.parentarray.nullvalue)
self.update_palette()
[docs]
def Active_vector(self, vect: vector, copyall:bool=True):
""" Set the active vector to vect and forward to mapviewer """
if vect is None:
return
self.active_vector = vect
self.active_vector_id.SetLabelText(vect.myname)
if vect.parentzone is not None:
self.active_zone = vect.parentzone
if self.mapviewer is not None and copyall:
self.mapviewer.Active_vector(vect)
[docs]
def Active_zone(self, target_zone:zone):
""" Set the active zone to target_zone and forward to mapviewer """
self.active_zone = target_zone
if self.mapviewer is not None:
self.mapviewer.Active_zone(target_zone)
[docs]
def update_palette(self):
"""
Update palette
Redraw the palette with Matplotlib and fill the grid with the values and RGB components
"""
self.Palette.add_ax()
fig, ax = self.Palette.get_fig_ax()
self.parentarray.mypal.plot(fig, ax)
fig.canvas.draw()
self.parentarray.mypal.fillgrid(self.palgrid)
[docs]
def Onsavepal(self, event:wx.MouseEvent):
""" Save palette to file """
myarray: WolfArray
myarray = self.parentarray
myarray.mypal.savefile()
[docs]
def Onloadpal(self, event:wx.MouseEvent):
""" Load palette from file """
myarray: WolfArray
myarray = self.parentarray
myarray.mypal.readfile()
myarray.mypal.automatic = False
self.palauto.SetValue(0)
self.refresh_array()
[docs]
def Onloaddefaultpal(self, event:wx.MouseEvent):
""" Load default palette """
import glob
# list of all .pal file in model directory
dirpal = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'models')
listpal = glob.glob(dirpal + '/*.pal')
if len(listpal) == 0:
logging.info('No default palette found')
return
listpal = [os.path.basename(i) for i in listpal]
dlg = wx.SingleChoiceDialog(None, 'Choose the default palette', 'Default palette', listpal)
ret = dlg.ShowModal()
if ret == wx.ID_CANCEL:
dlg.Destroy()
return
self.parentarray.mypal.readfile(dirpal + '/' + dlg.GetStringSelection())
self.parentarray.mypal.automatic = False
self.palauto.SetValue(0)
self.refresh_array()
[docs]
def Onpalimage(self, event:wx.MouseEvent):
""" Create image from palette """
myarray: WolfArray
myarray = self.parentarray
myarray.mypal.export_image()
[docs]
def Onpaldistribute(self, event:wx.MouseEvent):
""" Evenly spaced values in palette """
myarray: WolfArray
myarray = self.parentarray
myarray.mypal.distribute_values()
myarray.mypal.automatic = False
self.palauto.SetValue(0)
self.refresh_array()
[docs]
def Onupdatepal(self, event:wx.MouseEvent):
""" Apply options to palette """
curarray: WolfArray
curarray = self.parentarray
dellists = False
auto = self.palauto.IsChecked()
uni = self.uniforminparts.IsChecked()
oldalpha = curarray.alpha
if self.palalpha.IsChecked():
curarray.alpha=1.
else:
curarray.alpha = float(self.palalphaslider.GetValue()) / 100.
ret = curarray.mypal.updatefromgrid(self.palgrid)
if curarray.mypal.automatic != auto or curarray.alpha != oldalpha or ret or auto != curarray.mypal.automatic or uni != curarray.mypal.interval_cst:
curarray.mypal.automatic = auto
curarray.mypal.interval_cst = uni
curarray.updatepalette(0)
dellists = True
shadehill = self.palshader.IsChecked()
if not curarray.shading and shadehill:
curarray.shading = True
dellists = True
if shadehill:
azim = float(self.palazimuthhillshade.GetValue())
alti = float(self.palaltitudehillshade.GetValue())
if curarray.azimuthhill != azim:
curarray.azimuthhill = azim
curarray.shading = True
if curarray.altitudehill != alti:
curarray.altitudehill = alti
curarray.shading = True
alpha = float(self.palalphahillshade.GetValue()) / 100.
if curarray.shaded is None:
logging.error('No shaded array')
else:
if curarray.shaded.alpha != alpha:
curarray.shaded.alpha = alpha
curarray.shading = True
if dellists:
self.refresh_array()
[docs]
def OnClickHistoUpdate(self, event: wx.Event):
""" Create a histogram of the current array """
itemlabel = event.GetEventObject().GetLabel()
fig, ax = self.histo.get_fig_ax()
if itemlabel == self.histoupdateerase.LabelText:
ax.clear()
fig.canvas.draw()
return
myarray: WolfArray
myarray = self.parentarray
onzoom = []
if itemlabel == self.histoupdatezoom.LabelText:
if self.mapviewer is not None:
onzoom = [self.mapviewer.xmin, self.mapviewer.xmax, self.mapviewer.ymin, self.mapviewer.ymax]
partarray = myarray.get_working_array(onzoom).flatten(order='F') # .sort(axis=-1)
ax: Axis
ax.hist(partarray, 200, density=True)
fig.canvas.draw()
[docs]
def OnClickColorPal(self, event: wx.Event):
""" Edit color of a palette item """
gridto = self.palgrid
k = gridto.GetGridCursorRow()
r = int(gridto.GetCellValue(k, 1))
g = int(gridto.GetCellValue(k, 2))
b = int(gridto.GetCellValue(k, 3))
curcol = wx.ColourData()
curcol.SetChooseFull(True)
curcol.SetColour(wx.Colour(r, g, b))
dlg = wx.ColourDialog(None, curcol)
ret = dlg.ShowModal()
if ret == wx.ID_CANCEL:
dlg.Destroy()
return
curcol = dlg.GetColourData()
rgb = curcol.GetColour()
# k = gridto.GetGridCursorRow()
gridto.SetCellValue(k, 1, str(rgb.red))
gridto.SetCellValue(k, 2, str(rgb.green))
gridto.SetCellValue(k, 3, str(rgb.blue))
# Need to be destroyed after use to avoid memory leak and crash
dlg.Destroy()