wolfhece 2.2.38__py3-none-any.whl → 2.2.40__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. wolfhece/Coordinates_operations.py +5 -0
  2. wolfhece/GraphNotebook.py +72 -1
  3. wolfhece/GraphProfile.py +1 -1
  4. wolfhece/MulticriteriAnalysis.py +1579 -0
  5. wolfhece/PandasGrid.py +62 -1
  6. wolfhece/PyCrosssections.py +194 -43
  7. wolfhece/PyDraw.py +891 -73
  8. wolfhece/PyGui.py +913 -72
  9. wolfhece/PyGuiHydrology.py +528 -74
  10. wolfhece/PyPalette.py +26 -4
  11. wolfhece/PyParams.py +33 -0
  12. wolfhece/PyPictures.py +2 -2
  13. wolfhece/PyVertex.py +25 -0
  14. wolfhece/PyVertexvectors.py +94 -28
  15. wolfhece/PyWMS.py +52 -36
  16. wolfhece/acceptability/acceptability.py +15 -8
  17. wolfhece/acceptability/acceptability_gui.py +507 -360
  18. wolfhece/acceptability/func.py +80 -183
  19. wolfhece/apps/version.py +1 -1
  20. wolfhece/compare_series.py +480 -0
  21. wolfhece/drawing_obj.py +12 -1
  22. wolfhece/hydrology/Catchment.py +228 -162
  23. wolfhece/hydrology/Internal_variables.py +43 -2
  24. wolfhece/hydrology/Models_characteristics.py +69 -67
  25. wolfhece/hydrology/Optimisation.py +893 -182
  26. wolfhece/hydrology/PyWatershed.py +267 -165
  27. wolfhece/hydrology/SubBasin.py +185 -140
  28. wolfhece/hydrology/cst_exchanges.py +76 -1
  29. wolfhece/hydrology/forcedexchanges.py +413 -49
  30. wolfhece/hydrology/read.py +65 -5
  31. wolfhece/hydrometry/kiwis.py +14 -7
  32. wolfhece/insyde_be/INBE_func.py +746 -0
  33. wolfhece/insyde_be/INBE_gui.py +1776 -0
  34. wolfhece/insyde_be/__init__.py +3 -0
  35. wolfhece/interpolating_raster.py +366 -0
  36. wolfhece/irm_alaro.py +1457 -0
  37. wolfhece/irm_qdf.py +889 -57
  38. wolfhece/lazviewer/laz_viewer.py +4 -1
  39. wolfhece/lifewatch.py +6 -3
  40. wolfhece/picc.py +124 -8
  41. wolfhece/pyLandUseFlanders.py +146 -0
  42. wolfhece/pydownloader.py +35 -1
  43. wolfhece/pywalous.py +225 -31
  44. wolfhece/toolshydrology_dll.py +149 -0
  45. wolfhece/wolf_array.py +63 -25
  46. {wolfhece-2.2.38.dist-info → wolfhece-2.2.40.dist-info}/METADATA +3 -1
  47. {wolfhece-2.2.38.dist-info → wolfhece-2.2.40.dist-info}/RECORD +50 -41
  48. {wolfhece-2.2.38.dist-info → wolfhece-2.2.40.dist-info}/WHEEL +0 -0
  49. {wolfhece-2.2.38.dist-info → wolfhece-2.2.40.dist-info}/entry_points.txt +0 -0
  50. {wolfhece-2.2.38.dist-info → wolfhece-2.2.40.dist-info}/top_level.txt +0 -0
@@ -9,20 +9,22 @@ copying or distribution of this file, via any medium, is strictly prohibited.
9
9
  """
10
10
 
11
11
  import wx
12
+ from pathlib import Path
12
13
 
13
14
  from .PyTranslate import _
14
- from .PyDraw import WolfMapViewer
15
+ from .PyDraw import WolfMapViewer, draw_type
15
16
  from .RatingCurve import *
16
- from.PyVertexvectors import vector, Zones, zone, getIfromRGB, getRGBfromI
17
+ from .PyVertexvectors import vector, Zones, zone, getIfromRGB, getRGBfromI, wolfvertex as wv
18
+ from .wolf_array import WolfArray
17
19
 
18
20
  import logging
19
21
 
20
22
 
21
- class selectpoint(wx.Frame):
23
+ class selectpoint(wx.Dialog):
22
24
 
23
25
  def __init__(self, parent=None, title="Default Title", w=500, h=200, SPWstations: SPWMIGaugingStations = None,
24
26
  DCENNstations: SPWDCENNGaugingStations = None):
25
- wx.Frame.__init__(self, parent, title=title, size=(w, h), style=wx.DEFAULT_FRAME_STYLE)
27
+ wx.Dialog.__init__(self, parent, title=title, size=(w, h), style=wx.DEFAULT_DIALOG_STYLE)
26
28
 
27
29
  self.SPWMI = SPWstations
28
30
  self.SPWDCENN = DCENNstations
@@ -37,38 +39,64 @@ class selectpoint(wx.Frame):
37
39
  self.rbox = wx.RadioBox(self, label='Which', choices=lblList, majorDimension=1, style=wx.RA_SPECIFY_ROWS)
38
40
  self.rbox.Bind(wx.EVT_RADIOBOX, self.onRadioBox)
39
41
 
42
+ x_sizer = wx.BoxSizer(wx.HORIZONTAL)
40
43
  self.tcoordx = wx.StaticText(self, label="X: ")
41
- self.coordx = wx.TextCtrl(self, value=_("X coordinate"), size=(140, -1))
44
+ self.coordx = wx.TextCtrl(self, value=_("X coordinate"), size=(140, -1), style=wx.TE_CENTER)
45
+ x_sizer.Add(self.tcoordx, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
46
+ x_sizer.Add(self.coordx, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
47
+
48
+ y_sizer = wx.BoxSizer(wx.HORIZONTAL)
42
49
  self.tcoordy = wx.StaticText(self, label="Y: ")
43
- self.coordy = wx.TextCtrl(self, value=_("Y coordinate"), size=(140, -1))
50
+ self.coordy = wx.TextCtrl(self, value=_("Y coordinate"), size=(140, -1), style=wx.TE_CENTER)
51
+ y_sizer.Add(self.tcoordy, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
52
+ y_sizer.Add(self.coordy, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
53
+
44
54
  self.coords = [self.tcoordx, self.coordx, self.tcoordy, self.coordy]
45
55
 
46
- mycodes = [str(x) for x in SPWstations.mystations.keys()] + [str(x) for x in DCENNstations.mystations.keys()]
56
+ mycodes = [str(x) for x, val in SPWstations.mystations.items() if val.x !=0. and val.y != 0.] + [str(x) for x, val in DCENNstations.mystations.items() if val.x !=0. and val.y != 0.]
57
+ # Sort codes alphabetically
58
+ mycodes.sort()
47
59
 
48
60
  myrivers = [*list(SPWstations.myrivers.keys()), *list(DCENNstations.myrivers.keys())]
61
+ # Sort rivers alphabetically
62
+ myrivers.sort()
49
63
 
64
+ station_sizer = wx.BoxSizer(wx.HORIZONTAL)
50
65
  self.tcodestation = wx.StaticText(self, label=_("Code station: "))
51
66
  self.codestation = wx.ComboBox(self, size=(95, -1), choices=mycodes, style=wx.CB_DROPDOWN)
67
+ station_sizer.Add(self.tcodestation, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
68
+ station_sizer.Add(self.codestation, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
69
+
52
70
  self.codes = [self.tcodestation, self.codestation]
53
71
 
72
+ river_sizer = wx.BoxSizer(wx.HORIZONTAL)
54
73
  self.triverstation = wx.StaticText(self, label=_("River: "))
55
- self.riverstation = wx.ComboBox(self, size=(95, -1), choices=myrivers, style=wx.CB_DROPDOWN)
74
+ self.riverstation = wx.ComboBox(self, size=(95, -1), choices=myrivers, style=wx.CB_DROPDOWN | wx.CB_SORT)
75
+ river_sizer.Add(self.triverstation, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
76
+ river_sizer.Add(self.riverstation, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
77
+
78
+ name_sizer = wx.BoxSizer(wx.HORIZONTAL)
56
79
  self.tnamestation = wx.StaticText(self, label=_("Station name: "))
57
- self.namestation = wx.ComboBox(self, size=(95, -1), choices=[], style=wx.CB_DROPDOWN)
80
+ self.namestation = wx.ComboBox(self, size=(95, -1), choices=[], style=wx.CB_DROPDOWN | wx.CB_SORT)
81
+ name_sizer.Add(self.tnamestation, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
82
+ name_sizer.Add(self.namestation, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
83
+
58
84
  self.riverstation.Bind(wx.EVT_COMBOBOX, self.onComboRiver)
59
85
 
60
- self.riversname = [self.triverstation, self.riverstation, self.tnamestation, self.namestation]
86
+ self.riversname = [self.tnamestation, self.namestation, self.triverstation, self.riverstation]
61
87
 
62
88
  self.sizerv.Add(self.rbox, 0, wx.EXPAND)
63
89
 
64
- for curitem in self.coords:
65
- self.sizerv.Add(curitem, 1, wx.EXPAND)
66
- for curitem in self.codes:
67
- self.sizerv.Add(curitem, 1, wx.EXPAND)
68
- curitem.Hide()
69
- for curitem in self.riversname:
70
- self.sizerv.Add(curitem, 1, wx.EXPAND)
71
- curitem.Hide()
90
+ self.sizerv.Add(x_sizer, 1, wx.EXPAND)
91
+ self.sizerv.Add(y_sizer, 1, wx.EXPAND)
92
+ self.sizerv.Add(station_sizer, 1, wx.EXPAND)
93
+ self.sizerv.Add(river_sizer, 1, wx.EXPAND)
94
+ self.sizerv.Add(name_sizer, 1, wx.EXPAND)
95
+
96
+ for item in self.codes:
97
+ item.Hide()
98
+ for item in self.riversname:
99
+ item.Hide()
72
100
 
73
101
  self.sizer.Add(self.sizerv, 1, wx.EXPAND)
74
102
  self.sizer.Add(self.buttonOK, 0, wx.EXPAND)
@@ -81,8 +109,8 @@ class selectpoint(wx.Frame):
81
109
  # affichage de la page
82
110
  self.Show(True)
83
111
 
84
- def Apply(self):
85
- pass
112
+ def Apply(self, event):
113
+ self.Hide()
86
114
 
87
115
  def onComboRiver(self, evt):
88
116
  str = self.riverstation.GetStringSelection()
@@ -98,28 +126,31 @@ class selectpoint(wx.Frame):
98
126
  pass
99
127
 
100
128
  def onRadioBox(self, evt):
129
+ """ Switch between the different options in the radio box """
130
+
101
131
  str = self.rbox.GetStringSelection()
132
+
102
133
  if str == _('Coordinates'):
103
- for curitem in self.coords:
104
- curitem.Show()
105
- for curitem in self.codes:
106
- curitem.Hide()
107
- for curitem in self.riversname:
108
- curitem.Hide()
134
+ for item in self.coords:
135
+ item.Show()
136
+ for item in self.codes:
137
+ item.Hide()
138
+ for item in self.riversname:
139
+ item.Hide()
109
140
  elif str == _('Code station'):
110
- for curitem in self.coords:
111
- curitem.Hide()
112
- for curitem in self.codes:
113
- curitem.Show()
114
- for curitem in self.riversname:
115
- curitem.Hide()
141
+ for item in self.coords:
142
+ item.Hide()
143
+ for item in self.codes:
144
+ item.Show()
145
+ for item in self.riversname:
146
+ item.Hide()
116
147
  elif str == _('River/Name'):
117
- for curitem in self.coords:
118
- curitem.Hide()
119
- for curitem in self.codes:
120
- curitem.Hide()
121
- for curitem in self.riversname:
122
- curitem.Show()
148
+ for item in self.coords:
149
+ item.Hide()
150
+ for item in self.codes:
151
+ item.Hide()
152
+ for item in self.riversname:
153
+ item.Show()
123
154
 
124
155
  self.sizerv.Layout()
125
156
 
@@ -151,36 +182,84 @@ class GuiHydrology(WolfMapViewer):
151
182
 
152
183
  # self.filemenu.Insert(0, wx.ID_ANY, _('New from scratch'), _('Create a new simulation from scratch...'))
153
184
 
154
- self.modelmenu = wx.Menu()
155
- paramgen = self.modelmenu.Append(wx.ID_ANY, _('Choose outlet'), _('Wizard !'))
156
- paramgen = self.modelmenu.Append(wx.ID_ANY, _('Interior points'), _('Interior points'))
157
- paramgen = self.modelmenu.Append(wx.ID_ANY, _('Topology'), _('Topology manager'))
158
- paramgen = self.modelmenu.Append(wx.ID_ANY, _('Main model'), _('General parameters'))
159
- paramgen = self.modelmenu.Append(wx.ID_ANY, _('Basin'), _('Basin parameters'))
160
- paramgen = self.modelmenu.Append(wx.ID_ANY, _('Subbasins'), _('Sub-Basin parameters'))
161
- self.menubar.Append(self.modelmenu, _('&Hydrological model'))
185
+ self._hydrol_modelmenu = wx.Menu()
186
+ self.menubar.Append(self._hydrol_modelmenu, _('&Hydrological model'))
187
+
188
+ self._wizard = self._hydrol_modelmenu.Append(wx.ID_ANY, _('Wizard'), _('Wizard for hydrological model'))
189
+
190
+ self._dtm_menu = wx.Menu()
191
+ self._prepro_menu = wx.Menu()
192
+ self._outlet_menu = wx.Menu()
193
+ self._ip_menu = wx.Menu()
194
+
195
+ self._forced_exchanges_menu = wx.Menu()
196
+
197
+ self._prepro_menu.Append(wx.ID_ANY, _('Outlet...'), self._outlet_menu)
198
+ self._prepro_menu.Append(wx.ID_ANY, _('Interior points...'), self._ip_menu)
199
+ self._prepro_menu.Append(wx.ID_ANY, _('Forced exchanges...'), self._forced_exchanges_menu)
200
+
201
+ self._params_menu = wx.Menu()
202
+
203
+ self._toolsmenu = wx.Menu()
204
+
205
+ self._hydrol_modelmenu.Append(wx.ID_ANY, _('DTM...'), self._dtm_menu)
206
+ self._hydrol_modelmenu.Append(wx.ID_ANY, _('Preprocessing...'), self._prepro_menu)
207
+ self._hydrol_modelmenu.Append(wx.ID_ANY, _('Parameters...'), self._params_menu)
208
+ self._hydrol_modelmenu.Append(wx.ID_ANY, _('Tools...'), self._toolsmenu)
209
+
210
+ # DTM, outlet, interior points, parameters, preprocessing
211
+
212
+ self._dtm_menu.Append(wx.ID_ANY, _('Use active array as DTM'), _('Set the active array as DTM'))
213
+ self._dtm_menu.Append(wx.ID_ANY, _('Crop active array on zoom'), _('Crop the active array on the current zoom and use it as DTM'))
214
+ self._dtm_menu.Append(wx.ID_ANY, _('Crop active array using active vector'), _('Crop the active array based on the active vector and use it as DTM'))
215
+
216
+ # self._outlet_menu.Append(wx.ID_ANY, _('Choose outlet'), _('Outlet - local or general - from database'))
217
+ self._outlet_menu.Append(wx.ID_ANY, _('Pick outlet'), _('Outlet - local or general - by mouse'))
218
+ self._outlet_menu.Append(wx.ID_ANY, _('Convert selection'), _('Outlet - local or general - by mouse'))
219
+
220
+ # self._ip_menu.Append(wx.ID_ANY, _('Choose interior point'), _('Interior point - local or general - from database'))
221
+ self._ip_menu.Append(wx.ID_ANY, _('Pick interior point'), _('Interior point - local or general - by mouse'))
222
+ self._ip_menu.Append(wx.ID_ANY, _('Convert selections'), _('Interior point - local or general - by mouse'))
223
+ self._ip_menu.Append(wx.ID_ANY, _('Edit points'), _('Edit interior points...'))
162
224
 
163
- self.toolsmenu = wx.Menu()
164
- self.toolsmenu.Append(wx.ID_ANY, _('Forced exchanges'), _('Manage the forced exchanges...'))
165
- self.toolsmenu.Append(wx.ID_ANY, _('Crop MNT/MNS'), _('Cropping data...'))
166
- self.toolsmenu.Append(wx.ID_ANY, _('Crop land use (COSW)'), _('Cropping data...'))
167
- self.toolsmenu.Append(wx.ID_ANY, _('Analyze slope'), _('Slope analyzer...'))
168
- self.toolsmenu.Append(wx.ID_ANY, _('IRM - QDF'), _('Manage data...'))
225
+ self._params_menu.Append(wx.ID_ANY, _('Main model'), _('General parameters'))
226
+ self._params_menu.Append(wx.ID_ANY, _('Basin'), _('Basin parameters'))
227
+ self._params_menu.Append(wx.ID_ANY, _('Subbasins'), _('Sub-Basin parameters'))
169
228
 
170
- self.toolsmenu.AppendSeparator()
229
+ self._prepro_menu.Append(wx.ID_ANY, _('Run preprocessing'), _('Run the preprocessing of the hydrology model'))
230
+ # self._prepro_menu.Append(wx.ID_ANY, _('Topology'), _('Show the topology inside the active vector'))
171
231
 
172
- self.toolsmenu.Append(wx.ID_ANY, _('Find upstream watershed'), _('Find upstream watershed based on click...'))
173
- self.toolsmenu.Append(wx.ID_ANY, _('Find upstream watershed - limit to sub'), _('Find upstream watershed based on click but limit to subbasin...'))
232
+ # Forced exchanges menu
174
233
 
175
- self.toolsmenu.AppendSeparator()
234
+ self._forced_exchanges_menu.Append(wx.ID_ANY, _('Pick Forced exchanges'), _('Manage the forced exchanges...'))
235
+ self._forced_exchanges_menu.Append(wx.ID_ANY, _('Convert selection to Forced exchanges'), _('Convert selection to Forced exchanges...'))
236
+ self._forced_exchanges_menu.AppendSeparator()
237
+ self._forced_exchanges_menu.Append(wx.ID_ANY, _('Remove Forced exchanges'), _('Remove Forced exchanges...'))
238
+ self._forced_exchanges_menu.Append(wx.ID_ANY, _('Remove Forced exchanges inside vector'), _('Remove Forced exchanges...'))
239
+ # self._forced_exchanges_menu.AppendSeparator()
240
+ # self._forced_exchanges_menu.Append(wx.ID_ANY, _('Edit Forced exchanges'), _('Edit Forced exchanges...'))
176
241
 
177
- self.toolsmenu.Append(wx.ID_ANY, _('Select upstream watershed'), _('Select upstream watershed based on click...'))
178
- self.toolsmenu.Append(wx.ID_ANY, _('Select upstream watershed - limit to sub'), _('Select upstream watershed based on click but limit to subbasin...'))
179
- self.toolsmenu.Append(wx.ID_ANY, _('Select upstream rivers'), _('Select upstream rivers based on click...'))
180
- self.toolsmenu.Append(wx.ID_ANY, _('Select upstream rivers - limit to sub'), _('Select upstream rivers based on click but limit to subbasin...'))
181
- self.toolsmenu.Append(wx.ID_ANY, _('Select downstream rivers'), _('Select downstream rivers based on click...'))
242
+ # self._toolsmenu.Append(wx.ID_ANY, _('Crop MNT/MNS'), _('Cropping data...'))
243
+ # self._toolsmenu.Append(wx.ID_ANY, _('Crop land use (COSW)'), _('Cropping data...'))
244
+ # self._toolsmenu.Append(wx.ID_ANY, _('Analyze slope'), _('Slope analyzer...'))
245
+ # self._toolsmenu.Append(wx.ID_ANY, _('IRM - QDF'), _('Manage data...'))
182
246
 
183
- self.menubar.Append(self.toolsmenu, _('&Tools Hydrology'))
247
+ # self._toolsmenu.AppendSeparator()
248
+
249
+ self._toolsmenu.Append(wx.ID_ANY, _('Find upstream watershed'), _('Find upstream watershed based on click...'))
250
+ self._toolsmenu.Append(wx.ID_ANY, _('Find upstream watershed - limit to sub'), _('Find upstream watershed based on click but limit to subbasin...'))
251
+
252
+ self._toolsmenu.AppendSeparator()
253
+
254
+ self._toolsmenu.Append(wx.ID_ANY, _('Select upstream watershed'), _('Select upstream watershed based on click...'))
255
+ self._toolsmenu.Append(wx.ID_ANY, _('Select upstream watershed - limit to sub'), _('Select upstream watershed based on click but limit to subbasin...'))
256
+ self._toolsmenu.Append(wx.ID_ANY, _('Select upstream rivers'), _('Select upstream rivers based on click...'))
257
+ self._toolsmenu.Append(wx.ID_ANY, _('Select upstream rivers - limit to sub'), _('Select upstream rivers based on click but limit to subbasin...'))
258
+ self._toolsmenu.Append(wx.ID_ANY, _('Select downstream rivers'), _('Select downstream rivers based on click...'))
259
+
260
+ self._toolsmenu.AppendSeparator()
261
+
262
+ self._toolsmenu.Append(wx.ID_ANY, _('Find Path to outlet'), _('Find path to outlet based on click...'))
184
263
 
185
264
  # self.computemenu = wx.Menu()
186
265
  # paramgen = self.computemenu.Append(1300,_('Calibration/Optimisation'),_('Parameters calibration of the model'))
@@ -192,6 +271,8 @@ class GuiHydrology(WolfMapViewer):
192
271
  # paramgen = self.resultsmenu.Append(1401,_('Plot'),_('Plot'))
193
272
  # self.menubar.Append(self.resultsmenu,_('&Results'))
194
273
 
274
+ self._tmp_vector_exchanges = vector(name='Temporary forced exchanges vector')
275
+
195
276
  @property
196
277
  def watershed(self):
197
278
 
@@ -203,6 +284,86 @@ class GuiHydrology(WolfMapViewer):
203
284
 
204
285
  return self.wolfparent.mycatchment.charact_watrshd
205
286
 
287
+ @property
288
+ def header(self):
289
+ """ Return the header of the watershed """
290
+
291
+ if self.wolfparent is None:
292
+ return None
293
+
294
+ return self.wolfparent.header
295
+
296
+ def _choose_outlet(self):
297
+ """ Choose the outlet of the watershed """
298
+
299
+ myselect = selectpoint(title=_('Outlet'),
300
+ SPWstations=self.wolfparent.SPWstations,
301
+ DCENNstations=self.wolfparent.DCENNstations)
302
+
303
+ ret = myselect.ShowModal()
304
+ if myselect.rbox.GetStringSelection() == _('Coordinates'):
305
+ try:
306
+ x = float(myselect.coordx.GetValue())
307
+ y = float(myselect.coordy.GetValue())
308
+ except ValueError:
309
+ logging.error(_('Invalid coordinates! Please enter valid numbers.'))
310
+ return
311
+
312
+ self.wolfparent.set_outlet(x, y)
313
+
314
+ elif myselect.rbox.GetStringSelection() == _('Code station'):
315
+ try:
316
+ code = myselect.codestation.GetValue()
317
+ except ValueError:
318
+ logging.error(_('Invalid code! Please enter a valid code.'))
319
+ return
320
+
321
+ if code in self.wolfparent.SPWstations.mystations:
322
+ station = self.wolfparent.SPWstations.mystations[code]
323
+ elif code in self.wolfparent.DCENNstations.mystations:
324
+ station = self.wolfparent.DCENNstations.mystations[code]
325
+ else:
326
+ logging.error(_('Invalid code! Please enter a valid code.'))
327
+ return
328
+
329
+ x, y = station.x, station.y
330
+ if x ==0. or y == 0.:
331
+ logging.error(_('Invalid coordinates for the selected code!'))
332
+ return
333
+
334
+ self.wolfparent.set_outlet(x, y)
335
+
336
+ elif myselect.rbox.GetStringSelection() == _('River/Name'):
337
+ try:
338
+ river = myselect.riverstation.GetValue()
339
+ name = myselect.namestation.GetValue()
340
+ except ValueError:
341
+ logging.error(_('Invalid river or name! Please enter valid values.'))
342
+ return
343
+
344
+ if river in self.wolfparent.SPWstations.myrivers:
345
+ if name in self.wolfparent.SPWstations.myrivers[river]:
346
+ x, y = self.wolfparent.SPWstations.myrivers[river][name].x, self.wolfparent.SPWstations.myrivers[river][name].y
347
+ else:
348
+ logging.error(_('Invalid name for the selected river!'))
349
+ return
350
+ elif river in self.wolfparent.DCENNstations.myrivers:
351
+ if name in self.wolfparent.DCENNstations.myrivers[river]:
352
+ x, y = self.wolfparent.DCENNstations.myrivers[river][name].x, self.wolfparent.DCENNstations.myrivers[river][name].y
353
+ else:
354
+ logging.error(_('Invalid name for the selected river!'))
355
+ return
356
+ else:
357
+ logging.error(_('Invalid river! Please enter a valid river.'))
358
+ return
359
+ if x ==0. or y == 0.:
360
+ logging.error(_('Invalid coordinates for the selected river!'))
361
+ return
362
+
363
+ self.wolfparent.set_outlet(x, y)
364
+
365
+ myselect.Destroy()
366
+
206
367
  def OnMenubar(self, event):
207
368
  """ Event handler for the menubar """
208
369
 
@@ -219,16 +380,103 @@ class GuiHydrology(WolfMapViewer):
219
380
  itemlabel = item.ItemLabel
220
381
 
221
382
  if itemlabel == _('Choose outlet'):
222
- myselect = selectpoint(title=_('Outlet'),
223
- SPWstations=self.wolfparent.SPWstations,
224
- DCENNstations=self.wolfparent.DCENNstations)
225
- myselect.Show()
383
+ self._choose_outlet()
226
384
 
227
- elif itemlabel == _('Interior points'):
228
- logging.warning(_('Not yet implemented !'))
385
+ elif itemlabel == _('Pick outlet'):
386
+ self.action = 'Pick outlet'
387
+
388
+ elif itemlabel == _('Pick interior point'):
389
+ self.action = 'Pick interior point'
390
+
391
+ elif itemlabel == _('Convert selection'):
392
+ # Convert the selection to a general outlet
393
+ if self.active_array is not None:
394
+
395
+ xy = self.active_array.SelectionData.myselection
396
+
397
+ if xy is not None and len(xy) == 1:
398
+ x, y = xy[0]
399
+ self.wolfparent.set_outlet(x, y)
400
+ else:
401
+ logging.warning(_('No/Too many selections to convert to general outlet!'))
402
+ else:
403
+ logging.warning(_('No active array to convert selection from!'))
404
+
405
+ elif itemlabel == _('Edit points'):
406
+ # Edit interior points
407
+ if self.wolfparent.interior_points is not None:
408
+ self.wolfparent.interior_points.edit_points()
409
+ else:
410
+ logging.warning(_('No interior points to edit!'))
411
+
412
+ elif itemlabel == _('Convert selections'):
413
+ # Convert the selection to interior point
414
+ if self.active_array is not None:
415
+
416
+ xy = self.active_array.SelectionData.myselection
417
+
418
+ if xy is not None and len(xy) > 0:
419
+ for x,y in xy:
420
+ self.wolfparent.add_interior_point(x, y)
421
+ else:
422
+ logging.warning(_('No/Too many selections to convert to interior point!'))
423
+ else:
424
+ logging.warning(_('No active array to convert selection from!'))
425
+
426
+ elif itemlabel == _('Use active array as DTM'):
427
+
428
+ if self.active_array is not None:
429
+ self.wolfparent.set_active_array_as_dtm(self.active_array)
430
+ else:
431
+ logging.warning(_('No active array to set as DTM!'))
432
+
433
+ elif itemlabel == _('Crop active array on zoom'):
434
+
435
+ if self.active_array is not None:
436
+ [x1, x2], [y1, y2] = self.get_bounds()
437
+ dx = self.active_array.dx
438
+
439
+ x1 = int(x1 / dx) * dx - dx / 2
440
+ x2 = int(x2 / dx) * dx + dx / 2
441
+ y1 = int(y1 / dx) * dx - dx / 2
442
+ y2 = int(y2 / dx) * dx + dx / 2
443
+ anew = WolfArray(mold= self.active_array, crop= [[x1, x2], [y1, y2]])
444
+ self.wolfparent.set_active_array_as_dtm(anew)
445
+ else:
446
+ logging.warning(_('No active array to crop on zoom!'))
447
+
448
+ elif itemlabel == _('Crop active array using active vector'):
449
+
450
+ if self.active_array is not None and self.active_vector is not None:
451
+ bbox = self.active_vector.get_bounds_xx_yy()
452
+ newarray = self.active_array.crop_array(bbox)
453
+
454
+ newarray.mask_outsidepoly(self.active_vector)
455
+
456
+ newarray.nullify_border(width=1)
457
+ self.wolfparent.set_active_array_as_dtm(newarray)
458
+ else:
459
+ logging.warning(_('No active array or active vector to crop!'))
460
+
461
+ elif itemlabel == _('Run preprocessing'):
462
+
463
+ self.wolfparent.set_only_preprocess_data()
464
+ self.wolfparent.run_preprocessing()
465
+
466
+ elif itemlabel == _('Pick interior points'):
467
+ self.action = 'Pick interior point'
229
468
 
230
469
  elif itemlabel == _('Topology'):
231
- logging.warning(_('Not yet implemented !'))
470
+
471
+ if self.active_vector is None:
472
+ logging.warning(_('No active vector to show topology!'))
473
+ return
474
+
475
+ file = self.wolfparent.mycatchment.save_flow_chart()
476
+ self.active_vector.myprop.attachedimage = Path(file)
477
+ self.active_vector.myprop.imagevisible = True
478
+ self.active_vector._reset_listogl()
479
+
232
480
 
233
481
  elif itemlabel == _('Main model'):
234
482
  self.wolfparent.mainparams.Show()
@@ -239,8 +487,53 @@ class GuiHydrology(WolfMapViewer):
239
487
  elif itemlabel == _('Subbasins'):
240
488
  logging.warning(_('Not yet implemented !'))
241
489
 
242
- elif itemlabel == _('Forced exchanges'):
243
- logging.warning(_('Not yet implemented !'))
490
+ elif itemlabel == _('Pick Forced exchanges'):
491
+ self.action = 'Pick Forced exchanges'
492
+ self.check_id('Forced exchanges')
493
+ self.check_id('Up nodes - FE')
494
+ self.check_id('Down nodes - FE')
495
+
496
+ raw_data_elev:WolfArray = None
497
+ raw_data_elev = self.get_obj_from_id('Raw elevation [m]', drawing_type= draw_type.ARRAYS)
498
+ if raw_data_elev is None:
499
+ logging.error(_('No raw elevation array found! Forced exchanges cannot be picked without it.'))
500
+ self.action = None
501
+
502
+ elif itemlabel == _('Convert selection to Forced exchanges'):
503
+ # Convert the selection to Forced exchanges
504
+ if self.active_array is not None:
505
+
506
+ xy_down = self.active_array.SelectionData.myselection
507
+ xy_mem1= self.active_array.SelectionData.selections['1']
508
+
509
+ if xy_down is not None and len(xy_down) ==1 and len(xy_mem1) > 0:
510
+ self.wolfparent.myexchanges.add_pairs_XY(xy_mem1, xy_down)
511
+ else:
512
+ logging.warning(_('No/Too many selections to convert to Forced exchanges!'))
513
+ else:
514
+ logging.warning(_('No active array to convert selection from!'))
515
+
516
+ elif itemlabel == _('Remove Forced exchanges'):
517
+ # Remove Forced exchanges
518
+ if self.wolfparent.myexchanges is not None:
519
+ if self.wolfparent.myexchanges.is_empty():
520
+ logging.warning(_('No Forced exchanges to remove!'))
521
+ else:
522
+ self.action = 'Remove Forced exchanges'
523
+ else:
524
+ logging.warning(_('No Forced exchanges to remove!'))
525
+
526
+ elif itemlabel == _('Remove Forced exchanges inside vector'):
527
+ # Remove Forced exchanges inside the active vector
528
+
529
+ if self.active_vector is None:
530
+ logging.warning(_('No active vector to remove Forced exchanges from!'))
531
+ return
532
+
533
+ if self.wolfparent.myexchanges is not None:
534
+ self.wolfparent.myexchanges.remove_pairs_inside_vector(self.active_vector)
535
+ else:
536
+ logging.warning(_('No Forced exchanges or active vector to remove from!'))
244
537
 
245
538
  elif itemlabel == _('Crop MNT/MNS'):
246
539
  logging.warning(_('Not yet implemented !'))
@@ -260,6 +553,9 @@ class GuiHydrology(WolfMapViewer):
260
553
  elif itemlabel == _('Find upstream watershed - limit to sub'):
261
554
  self.action = 'Find upstream watershed - limit to sub'
262
555
 
556
+ elif itemlabel == _('Find Path to outlet'):
557
+ self.action = 'Find Path to outlet'
558
+
263
559
  elif itemlabel == _('Select upstream watershed'):
264
560
  self.action = 'Select upstream watershed'
265
561
 
@@ -300,11 +596,70 @@ class GuiHydrology(WolfMapViewer):
300
596
  logging.warning(_('No active array !'))
301
597
  return
302
598
 
303
- if not (self.active_array.dx == self.watershed.header.dx and self.active_array.dy == self.watershed.header.dy):
304
- logging.warning(_('Active array and watershed do not have the same resolution !'))
599
+ if self.header is None:
600
+ logging.error(_('No header defined. Cannot retrieve geolocalisation !'))
305
601
  return
306
602
 
307
- if 'Find upstream watershed' in self.action:
603
+ if self.header.dx != 0. and self.header.dy != 0:
604
+ if not (self.active_array.dx == self.header.dx and self.active_array.dy == self.header.dy):
605
+ logging.warning(_('Active array and watershed do not have the same resolution !'))
606
+ return
607
+
608
+ if self.action == 'Pick Forced exchanges':
609
+ tmp_vec = self.wolfparent.myexchanges.temporary_vector
610
+ if tmp_vec.nbvertices == 0:
611
+ tmp_vec.add_vertex(wv(x,y))
612
+ tmp_vec.add_vertex(wv(x,y))
613
+ elif tmp_vec.nbvertices == 2:
614
+ tmp_vec.myvertices[-1].x = x
615
+ tmp_vec.myvertices[-1].y = y
616
+
617
+ raw_data_elev:WolfArray = None
618
+ raw_data_elev = self.get_obj_from_id('Raw elevation [m]', drawing_type= draw_type.ARRAYS)
619
+ if raw_data_elev is not None:
620
+ zup = raw_data_elev.get_value(tmp_vec.myvertices[0].x, tmp_vec.myvertices[0].y)
621
+ zdown = raw_data_elev.get_value(tmp_vec.myvertices[1].x, tmp_vec.myvertices[1].y)
622
+
623
+ txt = _('Do you want to add this forced exchange ?\n\n')
624
+ txt += _('Up node: {:.2f} m\n').format(zup)
625
+ txt += _('Down node: {:.2f} m').format(zdown)
626
+
627
+ dlg = wx.MessageDialog(self, txt,
628
+ _('Forced exchange'),
629
+ wx.YES_NO | wx.ICON_QUESTION)
630
+
631
+ if dlg.ShowModal() == wx.ID_YES:
632
+ # Add the forced exchange to the list
633
+ self.wolfparent.myexchanges.add_pair(tmp_vec.myvertices[0].copy(),
634
+ tmp_vec.myvertices[1].copy())
635
+ # Reset the temporary vector
636
+ tmp_vec.reset()
637
+
638
+ elif self.action == 'Pick interior point':
639
+ # Add an interior point to the watershed
640
+ self.wolfparent.add_interior_point(x, y)
641
+
642
+ elif self.action == 'Remove Forced exchanges':
643
+ # Remove Forced exchanges
644
+ if self.wolfparent.myexchanges is not None:
645
+ if self.wolfparent.myexchanges.is_empty():
646
+ logging.warning(_('No Forced exchanges to remove!'))
647
+ else:
648
+ self.wolfparent.myexchanges.remove_nearest_pair(x, y)
649
+ self.Refresh()
650
+ else:
651
+ logging.warning(_('No Forced exchanges to remove!'))
652
+
653
+
654
+ elif 'Find upstream watershed' in self.action:
655
+
656
+ if self.active_array is None:
657
+ logging.warning(_('No active array - Please select an active array first!'))
658
+ return
659
+
660
+ if self.watershed is None:
661
+ logging.warning(_('No watershed defined - Please define a watershed first!'))
662
+ return
308
663
 
309
664
  starting_node = self.watershed.get_node_from_xy(x,y)
310
665
  up_vect = self.watershed.get_vector_from_upstream_node(starting_node, limit_to_sub='limit to sub' in self.action)
@@ -336,14 +691,69 @@ class GuiHydrology(WolfMapViewer):
336
691
  else:
337
692
  logging.warning(_('No operations frame in the active array!'))
338
693
 
694
+ elif 'Find Path to outlet' in self.action:
695
+
696
+ if self.active_array is None:
697
+ logging.warning(_('No active array - Please select an active array first!'))
698
+ return
699
+
700
+ if self.watershed is None:
701
+ logging.warning(_('No watershed defined - Please define a watershed first!'))
702
+ return
703
+
704
+ down_vect = self.watershed.get_vector_from_xy_to_outlet(x, y)
705
+
706
+ if down_vect is None:
707
+ logging.warning(_('No downstream path found !'))
708
+ return
709
+
710
+ def props_vec(vec:vector):
711
+ vec.myprop.color = getIfromRGB((255,128,192))
712
+ vec.myprop.width = 3
713
+ vec.myprop.transparent = False
714
+ vec.myprop.alpha = 122
715
+ vec.myprop.filled = False
716
+
717
+ if self.active_array.Operations is not None:
718
+ newzone = zone(name = down_vect.myname)
719
+
720
+ self.active_array.Operations.show_structure_OpsVectors()
721
+ self.active_array.Operations.myzones.add_zone(newzone, forceparent=True)
722
+ newzone.add_vector(down_vect, forceparent=True)
723
+
724
+ props_vec(down_vect)
725
+
726
+ self.active_array.Operations.myzones.prep_listogl()
727
+ self.active_array.Operations.myzones.fill_structure()
728
+
729
+ self.Refresh()
730
+ else:
731
+ logging.warning(_('No operations frame in the active array!'))
732
+
339
733
  elif 'Select upstream watershed' in self.action:
340
734
 
735
+ if self.active_array is None:
736
+ logging.warning(_('No active array - Please select an active array first!'))
737
+ return
738
+
739
+ if self.watershed is None:
740
+ logging.warning(_('No watershed defined - Please define a watershed first!'))
741
+ return
742
+
341
743
  xy = self.watershed.get_xy_upstream_node(self.watershed.get_node_from_xy(x,y), limit_to_sub='limit to sub' in self.action)
342
744
  self.active_array.SelectionData.set_selection_from_list_xy(xy)
343
745
  self.Refresh()
344
746
 
345
747
  elif 'Select upstream rivers' in self.action:
346
748
 
749
+ if self.active_array is None:
750
+ logging.warning(_('No active array - Please select an active array first!'))
751
+ return
752
+
753
+ if self.watershed is None:
754
+ logging.warning(_('No watershed defined - Please define a watershed first!'))
755
+ return
756
+
347
757
  xy = self.watershed.get_xy_upstream_node(self.watershed.get_node_from_xy(x,y),
348
758
  limit_to_sub='limit to sub' in self.action,
349
759
  limit_to_river=True)
@@ -353,8 +763,52 @@ class GuiHydrology(WolfMapViewer):
353
763
 
354
764
  elif 'Select downstream rivers' in self.action:
355
765
 
766
+ if self.active_array is None:
767
+ logging.warning(_('No active array - Please select an active array first!'))
768
+ return
769
+
770
+ if self.watershed is None:
771
+ logging.warning(_('No watershed defined - Please define a watershed first!'))
772
+ return
773
+
356
774
  xy = self.watershed.get_xy_downstream_node(self.watershed.get_node_from_xy(x,y))
357
775
  self.active_array.SelectionData.set_selection_from_list_xy(xy)
358
776
  self.Refresh()
359
777
 
778
+ elif 'Pick outlet' in self.action:
779
+
780
+ # Set the outlet in the watershed
781
+ self.wolfparent.set_outlet(x, y)
782
+ self.Refresh()
783
+
784
+ elif 'Pick interior point' in self.action:
785
+
786
+ # Set the interior point in the watershed
787
+ self.wolfparent.add_interior_point(x, y)
788
+ self.Refresh()
789
+
790
+ def On_Mouse_Motion(self, e: wx.MouseEvent):
791
+ """ Handle mouse motion events """
792
+
793
+ # Call the parent event handler
794
+ super().On_Mouse_Motion(e)
795
+
796
+ if self.action is None:
797
+ return
798
+
799
+ pos = e.GetPosition()
800
+ x, y = self.getXY(pos)
801
+
802
+ if self.action == 'Pick Forced exchanges':
803
+ tmp_vec = self.wolfparent.myexchanges.temporary_vector
804
+ if tmp_vec.nbvertices == 2:
805
+ tmp_vec.myvertices[-1].x = x
806
+ tmp_vec.myvertices[-1].y = y
807
+
808
+ self.Refresh()
809
+
810
+ def Paint(self):
811
+ """ Paint the map viewer """
360
812
 
813
+ # Call the parent paint method
814
+ super().Paint()