"""LU/LC companion for WolfMapViewer.
This companion owns the Landuse/Landcover menu construction, including
Walous submenus. Handlers are routed through this companion to private
viewer helpers to keep behavior identical while completing migration in
small safe steps.
"""
from __future__ import annotations
import logging
from pathlib import Path
from typing import TYPE_CHECKING
import geopandas as gpd
import numpy as np
import wx
from .PyTranslate import _
from .wolf_array import WolfArray, header_wolf, WOLF_ARRAY_FULL_SINGLE
from .pydownloader import toys_dataset
if TYPE_CHECKING:
from .PyDraw import WolfMapViewer
__all__ = ['LulcManager']
[docs]
class LulcManager:
"""Companion object that owns LU/LC menu state and handler routing."""
def __init__(self, viewer: 'WolfMapViewer') -> None:
[docs]
def _handle_importfromfile(self, event: wx.MenuEvent) -> None:
# Keep original handler logic unchanged by aliasing to the viewer instance.
self = self._viewer
""" Handle the Landuse/Landcover import from file menu events """
id = event.GetId()
item = self.menubar.FindItemById(event.GetId())
if item is None:
return
itemlabel = item.ItemLabel
if itemlabel == _("Import vector LU-LC data"):
logging.info("Import vector LU-LC data selected")
dlg = wx.FileDialog(self, _("Choose the vector LU-LC file"), wildcard="Shapefile (*.shp)|*.shp", style=wx.FD_OPEN)
if dlg.ShowModal() == wx.ID_CANCEL:
dlg.Destroy()
return
self._vectorLU_LC_filepath = Path(dlg.GetPath())
dlg.Destroy()
# Import vector LU-LC data
try:
self._vectorLU_LC_data = gpd.read_file(self._vectorLU_LC_filepath)
except Exception as e:
logging.error(f"Error reading shapefile: {e}")
wx.MessageBox(
_("Failed to read the shapefile.\nPlease ensure it is valid."),
_("Error"),
wx.OK | wx.ICON_ERROR
)
return
if self._vectorLU_LC_data.empty:
logging.error(f"Failed to read vector LU-LC data from {self._vectorLU_LC_filepath}")
wx.MessageBox(
_("The shapefile appears to be empty."),
_("Error"),
wx.OK | wx.ICON_ERROR
)
return
else:
logging.info(f"Vector LU-LC data imported from {self._vectorLU_LC_filepath}")
headers = list(self._vectorLU_LC_data.columns)
dlg_attr = wx.SingleChoiceDialog(
self,
message=_("Select the attribute column to use for Manning's mapping:"),
caption=_("Select LU-LC Attribute"),
choices=headers,
style=wx.CHOICEDLG_STYLE
)
if dlg_attr.ShowModal() == wx.ID_OK:
self._selected_LULC_column = dlg_attr.GetStringSelection()
logging.info(f"Selected LU-LC attribute column: {self._selected_LULC_column}")
else:
logging.info("User cancelled attribute column selection.")
dlg_attr.Destroy()
return
dlg_attr.Destroy()
unique_values = sorted(self._vectorLU_LC_data[self._selected_LULC_column].dropna().unique().tolist())
if not unique_values:
wx.MessageBox(
_("No valid attribute values found in the selected column."),
_("Error"),
wx.OK | wx.ICON_ERROR
)
return
dlg_map = wx.Dialog(self, title=_("Map LU-LC Classes to Manning's Coefficients"), size=(500, 400))
panel = wx.Panel(dlg_map)
vbox = wx.BoxSizer(wx.VERTICAL)
info_text = wx.StaticText(
panel,
label=_("Enter Manning's n value for each LU/LC class:")
)
vbox.Add(info_text, 0, wx.ALL, 10)
# Create table for mapping
grid = wx.grid.Grid(panel)
grid.CreateGrid(len(unique_values), 2)
grid.SetColLabelValue(0, _("LU/LC Class"))
grid.SetColLabelValue(1, _("Manning's n"))
grid.EnableEditing(True)
grid.SetColSize(0, 250)
grid.SetColSize(1, 150)
for i, val in enumerate(unique_values):
grid.SetCellValue(i, 0, str(val))
grid.SetReadOnly(i, 0, True) # LU/LC column is not editable
vbox.Add(grid, 1, wx.EXPAND | wx.ALL, 10)
hbox = wx.BoxSizer(wx.HORIZONTAL)
btn_ok = wx.Button(panel, wx.ID_OK, _("OK"))
btn_cancel = wx.Button(panel, wx.ID_CANCEL, _("Cancel"))
hbox.Add(btn_ok, 0, wx.ALL, 5)
hbox.Add(btn_cancel, 0, wx.ALL, 5)
vbox.Add(hbox, 0, wx.ALIGN_CENTER | wx.BOTTOM, 10)
panel.SetSizer(vbox)
dlg_map.Layout()
while True:
if dlg_map.ShowModal() != wx.ID_OK:
logging.info("User cancelled LU-LC to Manning's mapping.")
return
mapping = {}
validation_failed = False
for i, val in enumerate(unique_values):
n_str = grid.GetCellValue(i, 1).strip()
if not n_str:
wx.MessageBox(
_(f"Missing Manning's n value for class '{val}'."),
_("Error"),
wx.OK | wx.ICON_ERROR
)
validation_failed = True
break
try:
n_value = float(n_str)
if n_value <= 0:
wx.MessageBox(
_(f"Invalid Manning's n value for class '{val}'. Must be positive."),
_("Error"),
wx.OK | wx.ICON_ERROR
)
validation_failed = True
break
except ValueError:
wx.MessageBox(
_(f"Invalid Manning's n value for class '{val}'. Must be numeric."),
_("Error"),
wx.OK | wx.ICON_ERROR
)
validation_failed = True
break
mapping[val] = n_value
if validation_failed:
continue
self._lulc_manning_mapping = mapping
logging.info("LU-LC to Manning's mapping completed:")
for k, v in mapping.items():
logging.info(f" {k}: {v}")
break
dlg_map.Destroy()
if hasattr(self, "_lulc_manning_mapping") and self._lulc_manning_mapping:
manning_col_name = "MANNING_N"
self._vectorLU_LC_data[manning_col_name] = self._vectorLU_LC_data[self._selected_LULC_column].map(self._lulc_manning_mapping)
mapped_count = self._vectorLU_LC_data[manning_col_name].notna().sum()
total_count = len(self._vectorLU_LC_data)
logging.info(
f"Applied Manning's coefficients to {mapped_count}/{total_count} features "
f"using attribute '{self._selected_LULC_column}'."
)
wx.MessageBox(
_(
f"Manning's n values assigned to {mapped_count} out of {total_count} features.\n"
f"A new column '{manning_col_name}' has been added."
),
_("Mapping Complete"),
wx.OK | wx.ICON_INFORMATION
)
else:
logging.warning("No Manning's mapping found or user cancelled mapping process.")
export_prompt = wx.MessageDialog(
self,
_(
"Do you want to export the updated LU/LC data (with Manning's n values) "
"to a new file?"
),
_("Export Updated Layer"),
style=wx.YES_NO | wx.ICON_QUESTION
)
if export_prompt.ShowModal() == wx.ID_YES:
export_prompt.Destroy()
save_dlg = wx.FileDialog(self,_("Save updated LU/LC file as"),wildcard="Shapefile (*.shp)|*.shp",style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)
if save_dlg.ShowModal() == wx.ID_CANCEL:
save_dlg.Destroy()
logging.info("User cancelled export.")
return
export_path = Path(save_dlg.GetPath())
save_dlg.Destroy()
try:
driver = "ESRI Shapefile"
self._vectorLU_LC_data.to_file(export_path, driver=driver)
logging.info(f"Exported updated LU/LC data to {export_path}")
wx.MessageBox(_(f"Successfully exported updated LU/LC data to:\n{export_path}"),_("Export Successful"),wx.OK | wx.ICON_INFORMATION)
except Exception as e:
logging.error(f"Failed to export LU/LC data: {e}")
wx.MessageBox(_(f"Error while exporting:\n{e}"), _("Export Error"), wx.OK | wx.ICON_ERROR)
else:
export_prompt.Destroy()
logging.info("User chose not to export updated LU/LC data.")
raster_prompt = wx.MessageDialog(self, _("Do you want to create a raster file from the Manning's n data?"), _("Create Raster"), style=wx.YES_NO | wx.ICON_QUESTION)
if raster_prompt.ShowModal() == wx.ID_YES:
raster_prompt.Destroy()
choices = [_("Use vector bounds"), _("Crop to active array")]
bounds_dlg = wx.SingleChoiceDialog(self, _("Select bounding extent:"), _("Raster Bounds"), choices)
if bounds_dlg.ShowModal() == wx.ID_CANCEL:
bounds_dlg.Destroy()
return
bounds_choice = bounds_dlg.GetStringSelection()
bounds_dlg.Destroy()
if bounds_choice == _("Crop to active array"):
if self.active_array is None:
logging.warning(_("No active array -- Please activate data first"))
wx.MessageBox(_("No active array available.\nCannot crop raster."), _("Error"), wx.OK | wx.ICON_ERROR)
return
bounds_x, bounds_y = self.active_array.get_bounds()
xmin, xmax = bounds_x
ymin, ymax = bounds_y
spatial_res = self.active_array.dx
def_outdir = Path(self.active_array.filename).parent
else:
xmin, ymin, xmax, ymax = self._vectorLU_LC_data.total_bounds
def_outdir = Path(self._vectorLU_LC_filepath).parent
res_dlg = wx.TextEntryDialog(self, _("Enter spatial resolution (m):"), _("Spatial Resolution"), value="10.0")
if res_dlg.ShowModal() == wx.ID_OK:
try:
spatial_res = float(res_dlg.GetValue())
except ValueError:
wx.MessageBox(_("Invalid resolution entered. Must be numeric."), _("Error"), wx.OK | wx.ICON_ERROR)
res_dlg.Destroy()
return
else:
res_dlg.Destroy()
return
res_dlg.Destroy()
save_dlg = wx.FileDialog(
self,
_("Save raster file as"),
defaultDir=str(def_outdir),
wildcard="GeoTIFF (*.tif)|*.tif",
style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT
)
if save_dlg.ShowModal() == wx.ID_CANCEL:
save_dlg.Destroy()
return
raster_path = Path(save_dlg.GetPath())
save_dlg.Destroy()
# Rasterization
import rasterio
from rasterio import features
try:
logging.info("Starting rasterization of Manning's n data...")
width = int((xmax - xmin) / spatial_res)
height = int((ymax - ymin) / spatial_res)
transform = rasterio.transform.from_origin(xmin, ymax, spatial_res, spatial_res)
shapes = zip(
self._vectorLU_LC_data.geometry,
self._vectorLU_LC_data["MANNING_N"]
)
raster_data = features.rasterize(
shapes=shapes,
out_shape=(height, width),
transform=transform,
fill=np.nan,
dtype="float32"
)
new_dataset = rasterio.open(
raster_path,
"w",
driver="GTiff",
height=height,
width=width,
count=1,
dtype="float32",
crs=self._vectorLU_LC_data.crs,
transform=transform,
nodata=np.nan
)
new_dataset.write(raster_data, 1)
new_dataset.close()
logging.info(f"Raster created successfully: {raster_path}")
wx.MessageBox(_(f"Raster file created successfully:\n{raster_path}"), _("Rasterization Complete"), wx.OK | wx.ICON_INFORMATION)
dlg = wx.MessageDialog(self, _('Do you want to load the created file ?'), _('Load file'), wx.YES_NO | wx.ICON_QUESTION)
ret = dlg.ShowModal()
dlg.Destroy()
if ret == wx.ID_CANCEL:
return
if ret == wx.ID_YES:
manning_array = WolfArray(fname=raster_path)
self.add_object('array', newobj=manning_array, id='manning_array')
except Exception as e:
logging.error(f"Error creating raster: {e}")
wx.MessageBox(_(f"Error creating raster:\n{e}"),_("Rasterization Error"),wx.OK | wx.ICON_ERROR)
else:
raster_prompt.Destroy()
logging.info("User skipped raster creation.")
self.Autoscale()
elif itemlabel == _("Import raster LU-LC data"):
logging.info("Import raster LU-LC data selected")
dlg = wx.FileDialog(self, _("Choose the raster LU-LC file"), wildcard="GeoTIFF (*.tif)|*.tif|all (*.*)|*.*", style=wx.FD_OPEN)
if dlg.ShowModal() == wx.ID_CANCEL:
dlg.Destroy()
return
raster_path = Path(dlg.GetPath())
dlg.Destroy()
try:
lu_lc_array = WolfArray(fname=raster_path)
unique_values = sorted(lu_lc_array.get_unique_values())
if not unique_values:
wx.MessageBox(
_("Something went wrong reading unique values from the raster. Please check the file."),
_("Error"),
wx.OK | wx.ICON_ERROR
)
return
dlg_map = wx.Dialog(self, title=_("Map LU-LC Classes to Manning's Coefficients"), size=(500, 400))
panel = wx.Panel(dlg_map)
vbox = wx.BoxSizer(wx.VERTICAL)
info_text = wx.StaticText(
panel,
label=_("Enter Manning's n value for each LU/LC class. \nCheck the file's documentation for class meanings:")
)
vbox.Add(info_text, 0, wx.ALL, 10)
# Create table for mapping
grid = wx.grid.Grid(panel)
grid.CreateGrid(len(unique_values), 2)
grid.SetColLabelValue(0, _("LU/LC Class"))
grid.SetColLabelValue(1, _("Manning's n"))
grid.EnableEditing(True)
grid.SetColSize(0, 150)
grid.SetColSize(1, 150)
for i, val in enumerate(unique_values):
grid.SetCellValue(i, 0, str(val))
grid.SetReadOnly(i, 0, True) # LU/LC column is not editable
vbox.Add(grid, 1, wx.EXPAND | wx.ALL, 10)
hbox = wx.BoxSizer(wx.HORIZONTAL)
btn_ok = wx.Button(panel, wx.ID_OK, _("OK"))
btn_cancel = wx.Button(panel, wx.ID_CANCEL, _("Cancel"))
hbox.Add(btn_ok, 0, wx.ALL, 5)
hbox.Add(btn_cancel, 0, wx.ALL, 5)
vbox.Add(hbox, 0, wx.ALIGN_CENTER | wx.BOTTOM, 10)
panel.SetSizer(vbox)
dlg_map.Layout()
while True:
if dlg_map.ShowModal() != wx.ID_OK:
logging.info("User cancelled LU-LC to Manning's mapping.")
return
mapping = {}
validation_failed = False
for i, val in enumerate(unique_values):
n_str = grid.GetCellValue(i, 1).strip()
if not n_str:
wx.MessageBox(
_(f"Missing Manning's n value for class '{val}'."),
_("Error"),
wx.OK | wx.ICON_ERROR
)
validation_failed = True
break
try:
n_value = float(n_str)
if n_value <= 0:
wx.MessageBox(
_(f"Invalid Manning's n value for class '{val}'. Must be positive."),
_("Error"),
wx.OK | wx.ICON_ERROR
)
validation_failed = True
break
except ValueError:
wx.MessageBox(
_(f"Invalid Manning's n value for class '{val}'. Must be numeric."),
_("Error"),
wx.OK | wx.ICON_ERROR
)
validation_failed = True
break
mapping[val] = n_value
if validation_failed:
continue
self._lulc_manning_mapping = mapping
logging.info("LU-LC to Manning's mapping completed:")
for k, v in self._lulc_manning_mapping.items():
logging.info(f" {k}: {v}")
break
dlg_map.Destroy()
if hasattr(self, "_lulc_manning_mapping") and self._lulc_manning_mapping:
lu_lc_array_copy = lu_lc_array.array.data.copy()
for lu_lc_value, manning_n in self._lulc_manning_mapping.items():
lu_lc_array.array.data[lu_lc_array_copy == lu_lc_value] = manning_n
if self.active_array is not None:
dlg_crop = wx.MessageDialog(
self, _("Do you want to crop the raster to the active array extent?"), _('Crop Raster'), wx.YES_NO | wx.ICON_QUESTION
)
if dlg_crop.ShowModal() == wx.ID_YES:
try:
lu_lc_array = WolfArray(mold=lu_lc_array, crop=self.active_array.get_bounds())
logging.info("Raster cropped to active array extent.")
except Exception as e:
logging.error(f"Error cropping raster: {e}")
dlg_crop.Destroy()
dlg_resample = wx.TextEntryDialog(
self, _(f"Resample the raster to active array resolution ({self.active_array.dx} m) \n or enter desired resolution"),
_("Resample Raster"), value=str(self.active_array.dx)
)
try:
if dlg_resample.ShowModal() == wx.ID_OK:
try:
new_resolution = float(dlg_resample.GetValue())
if new_resolution <= 0:
raise ValueError("Resolution must be positive.")
lu_lc_array.rebin(new_resolution / lu_lc_array.dx, operation='min')
logging.info(f"Raster resampled to {new_resolution} m.")
save_dlg = wx.FileDialog(
self,
_("Save raster file as"),
defaultDir=str(raster_path),
wildcard="GeoTIFF (*.tif)|*.tif",
style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT
)
if save_dlg.ShowModal() == wx.ID_CANCEL:
save_dlg.Destroy()
return
raster_path = Path(save_dlg.GetPath())
save_dlg.Destroy()
lu_lc_array.write_all(raster_path)
logging.info(f"Raster file saved: {raster_path}")
dlg = wx.MessageDialog(self, _('Do you want to load the created array ?'), _('Load file'), wx.YES_NO | wx.ICON_QUESTION)
ret = dlg.ShowModal()
dlg.Destroy()
if ret == wx.ID_CANCEL:
return
if ret == wx.ID_YES:
manning_array = WolfArray(fname=raster_path)
self.add_object('array', newobj=manning_array, id=f'{raster_path.stem}')
except ValueError as e:
wx.MessageBox(
_(f"Invalid resolution value: {e}"),
_("Error"),
wx.OK | wx.ICON_ERROR
)
return
finally:
dlg_resample.Destroy()
else:
logging.info("No active array to resample raster to.")
dlg_resample = wx.TextEntryDialog(
self, _(f"Enter desired spatial resolution (m) for the raster \n Current: {lu_lc_array.dx}"), _("Resample Raster"), value=""
)
try:
if dlg_resample.ShowModal() == wx.ID_OK:
try:
new_resolution = float(dlg_resample.GetValue())
if new_resolution <= 0:
raise ValueError("Resolution must be positive.")
lu_lc_array.rebin(new_resolution / lu_lc_array.dx, operation='min')
logging.info(f"Raster resampled to {new_resolution} m.")
save_dlg = wx.FileDialog(
self,
_("Save raster file as"),
defaultDir=str(raster_path),
wildcard="GeoTIFF (*.tif)|*.tif",
style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT
)
if save_dlg.ShowModal() == wx.ID_CANCEL:
save_dlg.Destroy()
return
raster_path = Path(save_dlg.GetPath())
save_dlg.Destroy()
lu_lc_array.write_all(raster_path)
logging.info(f"Raster file saved: {raster_path}")
dlg = wx.MessageDialog(self, _('Do you want to load the created array ?'), _('Load file'), wx.YES_NO | wx.ICON_QUESTION)
ret = dlg.ShowModal()
dlg.Destroy()
if ret == wx.ID_CANCEL:
return
if ret == wx.ID_YES:
manning_array = WolfArray(fname=raster_path)
self.add_object('array', newobj=manning_array, id=f'{raster_path.stem}')
except ValueError as e:
wx.MessageBox(
_(f"Invalid resolution value: {e}"),
_("Error"),
wx.OK | wx.ICON_ERROR
)
return
finally:
dlg_resample.Destroy()
else:
logging.info("No LU-LC to Manning's mapping available.")
except Exception as e:
logging.error(f"Error: {e}")
self.Autoscale()
[docs]
def _handle_walous_ocs(self, event: wx.MenuEvent) -> None:
"""Handle Walous OCS menu events."""
v = self._viewer
item = v.menubar.FindItemById(event.GetId())
if item is None:
return
itemlabel = item.ItemLabel
if _("Crop on active array") in itemlabel or _("Crop on screen") in itemlabel:
if _("Crop on screen") in itemlabel:
bounds = v.get_canvas_bounds(gridsize=1.0)
def_outdrir = ''
spatial_res = 1.0
if v.active_array is not None:
spatial_res = v.active_array.dx
dlg = wx.TextEntryDialog(None, _("Spatial resolution [m] ?"), value=str(spatial_res))
dlg.ShowModal()
try:
spatial_res = float(dlg.GetValue())
dlg.Destroy()
except Exception:
dlg.Destroy()
logging.warning(_("Bad value -- Rety"))
return
else:
if v.active_array is None:
logging.warning(_('No active array -- Please activate data first'))
return
bounds = v.active_array.get_bounds()
def_outdrir = Path(v.active_array.filename).parent
spatial_res = v.active_array.dx
from .pywalous import update_palette_walous_ocs
if v._walous_OCS_filepath is None:
if itemlabel in [_("Crop on active array (prepared data 10 m - 2023)"), _("Crop on screen (prepared data 10 m - 2023)")]:
v._walous_OCS_filepath = toys_dataset('Walous_OCS', 'WALOUS_2023_lbt72_10m.tif')
elif itemlabel in [_("Crop on active array (prepared data 10 m - 2020)"), _("Crop on screen (prepared data 10 m - 2020)")]:
v._walous_OCS_filepath = toys_dataset('Walous_OCS', 'WALOUS_2020_lbt72_10m.tif')
else:
dlg = wx.FileDialog(v, _("Choose the Walous OCS Tif file"), wildcard="Tif file (*.tif)|*.tif|all (*.*)|*.*", style=wx.FD_OPEN)
if dlg.ShowModal() == wx.ID_CANCEL:
dlg.Destroy()
return
v._walous_OCS_filepath = Path(dlg.GetPath())
dlg.Destroy()
if v._walous_OCS_filepath is None or not Path(v._walous_OCS_filepath).exists():
logging.error(_('No Walous OCS file -- Please set it'))
return
dlg = wx.FileDialog(v, _("Choose the output file"), wildcard="Geotif (*.tif)|*.tif|all (*.*)|*.*", style=wx.FD_SAVE, defaultDir=str(def_outdrir))
if dlg.ShowModal() == wx.ID_CANCEL:
dlg.Destroy()
return
output = Path(dlg.GetPath())
dlg.Destroy()
header_OCS = header_wolf.read_header(v._walous_OCS_filepath)
if header_OCS.dx != spatial_res:
bounds = [list(bounds[0]), list(bounds[1])]
if (bounds[0][0] - header_OCS.origx) % header_OCS.dx != 0:
bounds[0][0] = header_OCS.origx + ((bounds[0][0] - header_OCS.origx) // header_OCS.dx) * header_OCS.dx
if (bounds[0][1] - bounds[0][0]) % header_OCS.dx != 0:
bounds[0][1] = bounds[0][0] + ((bounds[0][1] - bounds[0][0]) // header_OCS.dx + 1) * header_OCS.dx
if (bounds[1][0] - header_OCS.origy) % header_OCS.dy != 0:
bounds[1][0] = header_OCS.origy + ((bounds[1][0] - header_OCS.origy) // header_OCS.dy) * header_OCS.dy
if (bounds[1][1] - bounds[1][0]) % header_OCS.dy != 0:
bounds[1][1] = bounds[1][0] + ((bounds[1][1] - bounds[1][0]) // header_OCS.dy + 1) * header_OCS.dy
locwalous = WolfArray(fname=v._walous_OCS_filepath,
crop=[bounds[0][0], bounds[0][1], bounds[1][0], bounds[1][1]])
if locwalous.dx != spatial_res:
locwalous.rebin(spatial_res / locwalous.dx, operation='min')
logging.info(_('Rebin to {} m because original data are {} m').format(spatial_res, locwalous.dx))
locwalous = WolfArray(mold=locwalous, crop=v.active_array.get_bounds())
locwalous.write_all(output)
if Path(output).exists():
logging.info(_('File {} created').format(output))
else:
logging.error(_('File {} not created').format(output))
return
dlg = wx.MessageDialog(v, _('Do you want to load the created file ?'), _('Load file'), wx.YES_NO | wx.ICON_QUESTION)
ret = dlg.ShowModal()
if ret == wx.ID_CANCEL:
dlg.Destroy()
return
elif ret == wx.ID_YES:
walousarray = WolfArray(fname=output)
update_palette_walous_ocs(walousarray.mypal)
walousarray.reset_plot()
v.add_object('array', newobj=walousarray, id='walous_ocs_crop')
dlg.Destroy()
elif itemlabel == _("Legend"):
from .pywalous import Walous_OCS_Legend
newlegend = Walous_OCS_Legend(v)
newlegend.Show()
elif itemlabel == _("Map active array (WAL_OCS -> Hydrology)"):
from .pywalous import DlgMapWalous2Hydrology
if v.active_array is None:
logging.warning(_('No active array -- Please activate data first'))
return
if v.active_array.wolftype != WOLF_ARRAY_FULL_SINGLE:
logging.error(_('Active array is not a Float32 array -- Please change it to Float32 before mapping'))
return
vals = v.active_array.get_unique_values()
if v._walous_layer is None:
if vals[0] > 11:
logging.error(_('You have values greater than 11 -- Please check your data'))
return
dlg = DlgMapWalous2Hydrology(v)
ret = dlg.ShowModal()
if ret == wx.ID_CANCEL:
dlg.Destroy()
return
mapvals = dlg.get_mapping()
dlg.Destroy()
if mapvals == -1:
logging.error(_('Bad values -- retry'))
return
v.active_array.map_values(mapvals)
v.active_array.reset_plot()
elif itemlabel == _("Map active array (WAL_OCS -> Manning)"):
from .pywalous import DlgMapWalousOCS2Manning
if v.active_array is None:
logging.warning(_('No active array -- Please activate data first'))
return
if v.active_array.wolftype != WOLF_ARRAY_FULL_SINGLE:
logging.error(_('Active array is not a Float32 array -- Please change it to Float32 before mapping'))
return
vals = v.active_array.get_unique_values()
if v._walous_layer is None:
if vals[0] > 11:
logging.error(_('You have values greater than 11 -- Please check your data'))
return
dlg = DlgMapWalousOCS2Manning(v)
ret = dlg.ShowModal()
if ret == wx.ID_CANCEL:
dlg.Destroy()
return
mapvals = dlg.get_mapping()
dlg.Destroy()
if mapvals == -1:
logging.error(_('Bad values -- retry'))
return
v.active_array.map_values(mapvals)
v.active_array.reset_plot()
[docs]
def _handle_walous_uts(self, event: wx.MenuEvent) -> None:
"""Handle Walous UTS menu events."""
v = self._viewer
item = v.menubar.FindItemById(event.GetId())
if item is None:
return
itemlabel = item.ItemLabel
if itemlabel in [_("Crop on active array"), _("Crop on screen")]:
if itemlabel == _("Crop on screen"):
bounds = v.get_canvas_bounds(gridsize=1.)
def_outdrir = ''
spatial_res = 1.
if v.active_array is not None:
spatial_res = v.active_array.dx
dlg = wx.TextEntryDialog(None,_("Spatial resolution [m] ?"), value = str(spatial_res))
dlg.ShowModal()
try:
spatial_res = float(dlg.GetValue())
dlg.Destroy()
except:
dlg.Destroy()
logging.warning(_("Bad value -- Rety"))
return
else:
if v.active_array is None:
logging.warning(_('No active array -- Please activate data first'))
return
bounds = v.active_array.get_bounds()
def_outdrir = Path(v.active_array.filename).parent
spatial_res = v.active_array.dx
from .pywalous import Walous_data, WALOUS_UTS2MANNING_MAJ_NIV1, WALOUS_UTS2MANNING_MAJ_NIV2, update_palette_walous_uts
if v._walous_UTS_filepath is None:
dlg = wx.FileDialog(v, _("Choose the Walous shape file"), wildcard="Geopackage (*.gpkg)|*.gpkg|Shapefile (*.shp)|*.shp|all (*.*)|*.*", style=wx.FD_OPEN)
if dlg.ShowModal() == wx.ID_CANCEL:
dlg.Destroy()
return
v._walous_UTS_filepath = Path(dlg.GetPath())
dlg.Destroy()
dlg = wx.FileDialog(v, _("Choose the output file"), wildcard="Geotif (*.tif)|*.tif|all (*.*)|*.*", style=wx.FD_SAVE, defaultDir=str(def_outdrir))
if dlg.ShowModal() == wx.ID_CANCEL:
dlg.Destroy()
return
output = Path(dlg.GetPath())
dlg.Destroy()
# choix de la couche entre MAJ_NIV1 et MAJ_NIV2
dlg = wx.SingleChoiceDialog(None, _("Choose a layer"), "Choices", ['MAJ_NIV1', 'MAJ_NIV2'])
ret = dlg.ShowModal()
if ret == wx.ID_CANCEL:
dlg.Destroy()
return
v._walous_layer = 'UTS_' + dlg.GetStringSelection()
locwalous = Walous_data(v._walous_UTS_filepath.parent, v._walous_UTS_filepath.name)
ret = locwalous.rasterize(bounds=bounds,
layer=v._walous_layer,
fn_out=output,
pixel_size=spatial_res)
if isinstance(ret, int):
logging.error(_('Error {}').format(ret))
return
if Path(output).exists():
logging.info(_('File {} created').format(output))
else:
logging.error(_('File {} not created').format(output))
return
dlg = wx.MessageDialog(v, _('Do you want to load the created file ?'), _('Load file'), wx.YES_NO | wx.ICON_QUESTION)
ret = dlg.ShowModal()
if ret == wx.ID_CANCEL:
dlg.Destroy()
return
elif ret == wx.ID_YES:
walousarray = WolfArray(fname=output)
update_palette_walous_uts(v._walous_layer, walousarray.mypal)
v.add_object('array', newobj=walousarray, id='walous_uts_crop')
dlg.Destroy()
elif itemlabel == _("Legend"):
from .pywalous import Walous_UTS_Legend
newlegend = Walous_UTS_Legend(v)
newlegend.Show()
elif itemlabel == _("Map active array (WAL_UTS -> Manning)"):
from .pywalous import DlgMapWalous2Manning
if v.active_array is None:
logging.warning(_('No active array -- Please activate data first'))
return
if v.active_array.wolftype != WOLF_ARRAY_FULL_SINGLE:
logging.error(_('Active array is not a Float32 array -- Please change it to Float32 before mapping'))
return
vals = v.active_array.get_unique_values()
if v._walous_layer is None:
if vals[0] > 10:
v._walous_layer = 'UTS_MAJ_NIV2'
else:
v._walous_layer = 'UTS_MAJ_NIV1'
dlg = DlgMapWalous2Manning(v, which=v._walous_layer)
ret = dlg.ShowModal()
if ret == wx.ID_CANCEL:
dlg.Destroy()
return
mapvals = dlg.get_mapping()
dlg.Destroy()
if mapvals == -1:
logging.error(_('Bad values -- retry'))
return
v.active_array.map_values(mapvals)
v.active_array.reset_plot()