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
wolfhece/PyDraw.py CHANGED
@@ -94,6 +94,7 @@ try:
94
94
  from .images_tiles import ImagesTiles
95
95
  from .PyWMS import Alaro_Navigator, get_Alaro_legend
96
96
  from .PyPictures import PictureCollection
97
+ from .irm_alaro import IRM_Alaro, GribFiles, _convert_col2date_str
97
98
 
98
99
  except ImportError as e:
99
100
  print(e)
@@ -1817,7 +1818,7 @@ class Precomputed_DEM_DTM_Dialog(wx.Dialog):
1817
1818
  self._header.origx = float(int(onzoom[0]))
1818
1819
  self._header.origy = float(int(onzoom[2]))
1819
1820
 
1820
- res = self._resolution.GetSelection()
1821
+ res = self._resolution.GetStringSelection()
1821
1822
  if res == '50cm':
1822
1823
  res = 0.5
1823
1824
  elif res in ['1m', '2m', '5m', '10m']:
@@ -1964,6 +1965,7 @@ class WolfMapViewer(wx.Frame):
1964
1965
  active_drowning: Drowning_victim_Viewer
1965
1966
  active_dike : DikeWolf
1966
1967
  active_picturecollection: PictureCollection
1968
+ active_alaro: IRM_Alaro
1967
1969
 
1968
1970
  active_fig: MplFigViewer
1969
1971
 
@@ -2103,6 +2105,8 @@ class WolfMapViewer(wx.Frame):
2103
2105
  self.menudrowning = None
2104
2106
  self.menudike = None
2105
2107
  self.menupicturecollections = None
2108
+ self.menuqdfidf = None
2109
+ self.menualaro = None
2106
2110
 
2107
2111
  self.alaro_navigator = None
2108
2112
 
@@ -2152,7 +2156,7 @@ class WolfMapViewer(wx.Frame):
2152
2156
  # SIMULATION Hydrologique
2153
2157
 
2154
2158
  self.menu_hydrology = wx.Menu()
2155
- hydrol = self.menu_hydrology.Append(wx.ID_ANY, _('Open Hydrological model'), _('Hydrological simulation'))
2159
+ hydrol = self.menu_hydrology.Append(wx.ID_ANY, _('Create/Open Hydrological model'), _('Hydrological simulation'))
2156
2160
  self.filemenu.Append(wx.ID_ANY,_('Hydrology'),self.menu_hydrology)
2157
2161
 
2158
2162
  self.filemenu.AppendSeparator()
@@ -2182,6 +2186,7 @@ class WolfMapViewer(wx.Frame):
2182
2186
  createbcmanager2D = self.menucreateobj.Append(wx.ID_ANY, _('Create BC manager Wolf2D...'), _('New BC manager 2D'))
2183
2187
  createpartsystem = self.menucreateobj.Append(wx.ID_ANY, _('Create particle system...'), _('Create a particle system - Lagrangian view'))
2184
2188
  create_acceptability = self.menucreateobj.Append(wx.ID_ANY, _('Create acceptability manager...'), _('Create acceptability manager'))
2189
+ create_inbe = self.menucreateobj.Append(wx.ID_ANY, _('Create INBE manager...'), _('Create INBE manager'))
2185
2190
  createdrowning = self.menucreateobj.Append(wx.ID_ANY, _('Create a drowning...'),_('Create a drowning'))
2186
2191
  createdike = self.menucreateobj.Append(wx.ID_ANY, _('Create dike...'), _('New dike'))
2187
2192
 
@@ -2403,6 +2408,8 @@ class WolfMapViewer(wx.Frame):
2403
2408
  self.active_laz = None
2404
2409
  self.active_dike = None
2405
2410
  self.active_picturecollection = None
2411
+ self.active_qdfidf = None
2412
+ self.active_alaro = None
2406
2413
 
2407
2414
  self.active_fig = None
2408
2415
  self.active_drowning = None
@@ -2526,6 +2533,8 @@ class WolfMapViewer(wx.Frame):
2526
2533
  self._distances = Zones(mapviewer=self, idx=_('Distances/Areas'))
2527
2534
  self._distances.add_zone(zone(name='memory distances', parent=self._distances)) # distances memory
2528
2535
 
2536
+ self.menu_alaro_forecasts()
2537
+
2529
2538
  # self._wintab = Wintab(self.GetHandle())
2530
2539
 
2531
2540
  # if self._wintab:
@@ -2813,6 +2822,144 @@ class WolfMapViewer(wx.Frame):
2813
2822
  self.Bind(wx.EVT_MENU, self.action_pictcollections, allvisible)
2814
2823
  self.Bind(wx.EVT_MENU, self.action_pictcollections, extract)
2815
2824
 
2825
+ def menu_qdfidf(self):
2826
+ """ Menu for QDF/IDF files """
2827
+
2828
+ if self.menuqdfidf is None:
2829
+ self.menuqdfidf = wx.Menu()
2830
+ self.menubar.Append(self.menuqdfidf, _('QDF/IDF'))
2831
+
2832
+ download = self.menuqdfidf.Append(wx.ID_ANY, _('Download data'), _('Download all QDF/IDF data for Belgium and preprocess it !'))
2833
+ load = self.menuqdfidf.Append(wx.ID_ANY, _('Load data'), _('Load a QDF/IDF for Belgium'))
2834
+ pick = self.menuqdfidf.Append(wx.ID_ANY, _('Pick municipality'), _('Pick a municipality and show its data'))
2835
+ show_tables = self.menuqdfidf.Append(wx.ID_ANY, _('Show tables'), _('Show tables on viewer'))
2836
+ show_plots = self.menuqdfidf.Append(wx.ID_ANY, _('Show plots'), _('Show plots on viewer'))
2837
+ scale = self.menuqdfidf.Append(wx.ID_ANY, _('Scale images'), _('Scale the QDF/IDF images'))
2838
+
2839
+ self.Bind(wx.EVT_MENU, self.action_qdfidf, download)
2840
+ self.Bind(wx.EVT_MENU, self.action_qdfidf, load)
2841
+ self.Bind(wx.EVT_MENU, self.action_qdfidf, pick)
2842
+ self.Bind(wx.EVT_MENU, self.action_qdfidf, show_tables)
2843
+ self.Bind(wx.EVT_MENU, self.action_qdfidf, show_plots)
2844
+ self.Bind(wx.EVT_MENU, self.action_qdfidf, scale)
2845
+
2846
+ def action_qdfidf(self, event: wx.Event):
2847
+ """ Action for QDF/IDF files """
2848
+
2849
+ item = event.GetEventObject().FindItemById(event.GetId())
2850
+ itemlabel = item.ItemLabel
2851
+
2852
+ if self.active_qdfidf is None and itemlabel != _('Load data') and itemlabel != _('Download data'):
2853
+ logging.warning(_('No active QDF/IDF -- Please load data first'))
2854
+ return
2855
+
2856
+ if itemlabel == _('Load data'):
2857
+
2858
+ from .irm_qdf import QDF_Hydrology_Draw
2859
+
2860
+ dlg_dir = wx.DirDialog(self, _('Choose directory with QDF/IDF files'), style=wx.DD_DEFAULT_STYLE)
2861
+ if dlg_dir.ShowModal() == wx.ID_CANCEL:
2862
+ dlg_dir.Destroy()
2863
+ return
2864
+ dirpath = dlg_dir.GetPath()
2865
+ dlg_dir.Destroy()
2866
+
2867
+ pgbar = wx.ProgressDialog(_('Loading QDF/IDF data'), _('Loading data...'), maximum=100, parent=self, style=wx.PD_APP_MODAL | wx.PD_AUTO_HIDE)
2868
+ pgbar.Pulse(_('Loading QDF/IDF data... (estimated time 10 min.)'))
2869
+
2870
+ self.active_qdfidf = QDF_Hydrology_Draw(dirpath, idx = 'QDF/IDF', mapviewer = self)
2871
+
2872
+ pgbar.Update(100, _('QDF/IDF data loaded'))
2873
+ pgbar.Destroy()
2874
+
2875
+ self.treelist.SetFocus()
2876
+
2877
+ elif itemlabel == _('Download data'):
2878
+
2879
+ from .irm_qdf import QDF_Hydrology_Draw
2880
+
2881
+ dlg_dir = wx.DirDialog(self, _('Choose an empty directory to store QDF/IDF files'), style=wx.DD_DEFAULT_STYLE | wx.DD_NEW_DIR_BUTTON)
2882
+ if dlg_dir.ShowModal() == wx.ID_CANCEL:
2883
+ dlg_dir.Destroy()
2884
+ return
2885
+
2886
+ dirpath = dlg_dir.GetPath()
2887
+ dlg_dir.Destroy()
2888
+
2889
+ # Test if the directory is empty
2890
+ if os.listdir(dirpath):
2891
+ logging.error(_('The directory {} is not empty. Please choose an empty directory.').format(dirpath))
2892
+ wx.MessageBox(_('The directory {} is not empty. Please choose an empty directory.').format(dirpath), _('Error'), wx.OK | wx.ICON_ERROR)
2893
+ return
2894
+
2895
+ pgbar = wx.ProgressDialog(_('Downloading QDF/IDF data'), _('Downloading data...'), maximum=100, parent=self, style=wx.PD_APP_MODAL | wx.PD_AUTO_HIDE)
2896
+ pgbar.Pulse(_('Downloading QDF/IDF data...'))
2897
+
2898
+ try:
2899
+ self.active_qdfidf = QDF_Hydrology_Draw(dirpath, idx = 'QDF/IDF', mapviewer = self)
2900
+ except Exception as e:
2901
+ logging.error(_('Error downloading QDF/IDF data: {}').format(e))
2902
+ wx.MessageBox(_('Error downloading QDF/IDF data: {}').format(e), _('Error'), wx.OK | wx.ICON_ERROR)
2903
+
2904
+ pgbar.Update(100, _('QDF/IDF data loaded and processed'))
2905
+ pgbar.Destroy()
2906
+
2907
+ self.treelist.SetFocus()
2908
+
2909
+ elif itemlabel == _('Pick municipality'):
2910
+ self.action = 'pick municipality'
2911
+ logging.info(_('Pick a municipality from the QDF/IDF data'))
2912
+
2913
+ elif itemlabel == _('Show tables'):
2914
+
2915
+ if self.active_qdfidf is not None:
2916
+
2917
+ pgbar = wx.ProgressDialog(_('Loading QDF/IDF data'), _('Loading data...'), maximum=100, parent=self, style=wx.PD_APP_MODAL | wx.PD_AUTO_HIDE)
2918
+ pgbar.Pulse(_('Loading QDF/IDF data...'))
2919
+
2920
+ self.active_qdfidf.show_plot = False
2921
+ self.active_qdfidf.show_table = True
2922
+ logging.info(_('Show tables for QDF/IDF data'))
2923
+ self.Refresh()
2924
+
2925
+ pgbar.Update(100, _('QDF/IDF data loaded'))
2926
+ pgbar.Destroy()
2927
+ self.treelist.SetFocus()
2928
+
2929
+
2930
+ elif itemlabel == _('Show plots'):
2931
+
2932
+ if self.active_qdfidf is not None:
2933
+
2934
+ pgbar = wx.ProgressDialog(_('Loading QDF/IDF data'), _('Loading data...'), maximum=100, parent=self, style=wx.PD_APP_MODAL | wx.PD_AUTO_HIDE)
2935
+ pgbar.Pulse(_('Loading QDF/IDF data...'))
2936
+
2937
+ self.active_qdfidf.show_table = False
2938
+ self.active_qdfidf.show_plot = True
2939
+ logging.info(_('Show tables for QDF/IDF data'))
2940
+ self.Refresh()
2941
+
2942
+ pgbar.Update(100, _('QDF/IDF data loaded'))
2943
+ pgbar.Destroy()
2944
+ self.treelist.SetFocus()
2945
+
2946
+
2947
+ elif itemlabel == _('Scale images'):
2948
+ if self.active_qdfidf is not None:
2949
+ scalefactor = wx.GetTextFromUser(_('Enter the scale factor (default is 1.0)'), _('Scale factor'), '1.0', self)
2950
+ if scalefactor == '':
2951
+ scalefactor = '1.0'
2952
+ try:
2953
+ scalefactor = float(scalefactor)
2954
+ except ValueError:
2955
+ logging.error(_('Invalid scale factor: {}').format(scalefactor))
2956
+ wx.MessageBox(_('Invalid scale factor: {}').format(scalefactor), _('Error'), wx.OK | wx.ICON_ERROR)
2957
+ return
2958
+
2959
+ self.active_qdfidf.scale_images(scalefactor)
2960
+
2961
+ self.Refresh()
2962
+
2816
2963
  def action_pictcollections(self, event: wx.Event):
2817
2964
  """ Action for picture collections """
2818
2965
 
@@ -3008,22 +3155,355 @@ class WolfMapViewer(wx.Frame):
3008
3155
 
3009
3156
  self.menuwolf2d.Bind(wx.EVT_MENU, self.Onmenuwolf2d)
3010
3157
 
3158
+ def menu_alaro_forecasts(self):
3159
+ """ Menu for Alaro forecasts """
3160
+ if self.menualaro is None:
3161
+
3162
+ self.menualaro = wx.Menu()
3163
+ self.menubar.Append(self.menualaro, _('Alaro forecasts'))
3164
+ self.menualaro_ftp = wx.Menu()
3165
+ self.menualaro.AppendSubMenu(self.menualaro_ftp, _('FTP server'))
3166
+
3167
+ self.menualaro.Bind(wx.EVT_MENU, self.Onmenualaro)
3168
+
3169
+ self.alaro_show_grid = self.menualaro.Append(wx.ID_ANY, _("Show grid"), _("Show the Alaro grid on the viewer"))
3170
+ self.alaro_list_runs = self.menualaro_ftp.Append(wx.ID_ANY, _("List runs on FTP server"), _("List available Alaro runs on the FTP server"))
3171
+ self.alaro_download_runs = self.menualaro_ftp.Append(wx.ID_ANY, _("Download runs"), _("Download Alaro runs"))
3172
+ self.alaro_download_runs_only_rain = self.menualaro_ftp.Append(wx.ID_ANY, _("Download runs - Only Rain and Temperature"), _("Download Alaro runs"))
3173
+ self.alaro_load_run = self.menualaro.Append(wx.ID_ANY, _("Load run"), _("Load an available Alaro run"))
3174
+ self.alaro_show_run = self.menualaro.Append(wx.ID_ANY, _("Add forecast(s) as arry(s)"), _("Show Alaro forecasts on the viewer as WolfArray - Total precipitation [mm]"))
3175
+ self.alaro_show_all = self.menualaro.Append(wx.ID_ANY, _("Add all forecasts as arrays"), _("Show all available Alaro runs on the viewer as WolfArrays - Total precipitation [mm]"))
3176
+ self.alaro_plot_xy = self.menualaro.Append(wx.ID_ANY, _("Plot for XY"), _("Plot the next selected point"))
3177
+
3178
+ self.menualaro_videos = wx.Menu()
3179
+ self.menualaro.AppendSubMenu(self.menualaro_videos, _('Videos'))
3180
+
3181
+ self.alaro_videos_totprec = self.menualaro_videos.Append(wx.ID_ANY, _("Total precip. [mm] - One run"), _("Create a video of the Total Precipitation forecasts for a specific run"))
3182
+ self.alaro_videos_totprec_all = self.menualaro_videos.Append(wx.ID_ANY, _("Total precip. [mm] - Multiple runs"), _("Create videos of the Total Precipitation forecasts for all runs"))
3183
+ self.alaro_videos_comparison = self.menualaro_videos.Append(wx.ID_ANY, _("Rain intensity [mm/h] - Comparison") , _("Create a video comparing the Rain Intensity forecasts of different runs"))
3184
+
3185
+ def Onmenualaro(self, event: wx.Event):
3186
+ """ Action for Alaro forecasts """
3187
+
3188
+ from datetime import timezone as tz
3189
+
3190
+ item = event.GetEventObject().FindItemById(event.GetId())
3191
+ itemlabel = item.ItemLabel
3192
+
3193
+ if self.active_alaro is None:
3194
+ self.active_alaro = IRM_Alaro()
3195
+
3196
+ if itemlabel == _("List runs on FTP server"):
3197
+
3198
+ runs = self.active_alaro.run_dates_str
3199
+
3200
+ for run in runs:
3201
+ logging.info(f'Available Alaro run: {run}')
3202
+
3203
+ dlg = wx.MessageDialog(self, _('Available Alaro runs:\n\n') + '\n'.join(runs), _('Alaro runs'), wx.OK | wx.ICON_INFORMATION)
3204
+ dlg.ShowModal()
3205
+
3206
+ elif itemlabel == _("Rain intensity [mm/h] - Comparison"):
3207
+
3208
+ data_dir = self.active_alaro.data_directory
3209
+ dates = self.active_alaro.list_run_dates_cached()
3210
+
3211
+ dates_str = [datetime.strptime(date, '%Y%m%d%H').replace(tzinfo=tz.utc) for date in dates]
3212
+ dates_str = [date.strftime('%Y-%m-%d %H+00') for date in dates_str]
3213
+
3214
+ dlg = wx.MultiChoiceDialog(self, _('Choose one or multiple Alaro runs to treat'), _('Choose Alaro runs'), choices=dates_str)
3215
+ ret = dlg.ShowModal()
3216
+ if ret == wx.ID_CANCEL:
3217
+ dlg.Destroy()
3218
+ return
3219
+ choices = dlg.GetSelections()
3220
+ dlg.Destroy()
3221
+
3222
+ if len(choices) == 0:
3223
+ logging.warning(_('No Alaro run selected'))
3224
+ return
3225
+
3226
+ dates = [dates[choice] for choice in choices]
3227
+
3228
+ dlg = wx.FileDialog(self, _('Choose output video filename'), wildcard='mp4 (*.mp4)|*.mp4', defaultDir=str(data_dir), defaultFile='Alaro_RainIntensity_Comparison.mp4', style=wx.FD_SAVE)
3229
+ ret = dlg.ShowModal()
3230
+ if ret == wx.ID_OK:
3231
+ output_dir = dlg.GetPath()
3232
+ dlg.Destroy()
3233
+
3234
+ self.active_alaro.reset_gdf()
3235
+
3236
+ pgbar = wx.ProgressDialog(_('Loading Alaro runs'), _('Loading data...'), maximum=100, parent=self, style=wx.PD_APP_MODAL | wx.PD_AUTO_HIDE)
3237
+
3238
+ pgbar.Pulse(_('Creating video...'))
3239
+ outfile = self.active_alaro.video_gradient_cumulated_rain_compare(Path(output_dir), run_dates = dates)
3240
+ pgbar.Update(100, _('Video created'))
3241
+ pgbar.Destroy()
3242
+
3243
+ logging.info(f'Videos: {dates}')
3244
+
3245
+ # Propose to lauch the video
3246
+ dlg = wx.MessageDialog(self, _('Video created: {}\n\nDo you want to launch it ?').format(outfile), _('Video created'), wx.YES_NO | wx.ICON_QUESTION)
3247
+ ret = dlg.ShowModal()
3248
+ if ret == wx.ID_YES:
3249
+ if sys.platform == "win32":
3250
+ os.startfile(outfile)
3251
+ # elif sys.platform == "darwin":
3252
+ # subprocess.call(["open", outfile])
3253
+ # elif sys.platform == "linux":
3254
+ # subprocess.call(["xdg-open", outfile])
3255
+ dlg.Destroy()
3256
+
3257
+ elif itemlabel == _("Total precip. [mm] - One run"):
3258
+
3259
+ data_dir = self.active_alaro.data_directory
3260
+ dates = self.active_alaro.list_run_dates_cached()
3261
+
3262
+ dates_str = [datetime.strptime(date, '%Y%m%d%H').replace(tzinfo=tz.utc) for date in dates]
3263
+ dates_str = [date.strftime('%Y-%m-%d %H+00') for date in dates_str]
3264
+
3265
+ dlg = wx.SingleChoiceDialog(self, _('Choose one Alaro run to treat'), _('Choose Alaro run'), choices=dates_str)
3266
+ ret = dlg.ShowModal()
3267
+ if ret == wx.ID_CANCEL:
3268
+ dlg.Destroy()
3269
+ return
3270
+ choice = dlg.GetSelection()
3271
+ dlg.Destroy()
3272
+
3273
+ if choice == wx.NOT_FOUND:
3274
+ logging.warning(_('No Alaro run selected'))
3275
+ return
3276
+
3277
+ dates = [dates[choice]]
3278
+
3279
+ dlg = wx.FileDialog(self, _('Choose output video filename'), wildcard='mp4 (*.mp4)|*.mp4', defaultDir=str(data_dir), defaultFile=f"Alaro_cumulated_rain_{dates[0]}.mp4", style=wx.FD_SAVE)
3280
+ ret = dlg.ShowModal()
3281
+ if ret == wx.ID_OK:
3282
+ output_dir = dlg.GetPath()
3283
+ dlg.Destroy()
3284
+
3285
+ self.active_alaro.reset_gdf()
3286
+
3287
+ pgbar = wx.ProgressDialog(_('Loading Alaro runs'), _('Loading data...'), maximum=100, parent=self, style=wx.PD_APP_MODAL | wx.PD_AUTO_HIDE)
3288
+
3289
+ pgbar.Pulse(_('Creating video...'))
3290
+ outfile = self.active_alaro.video_cumulated_rain(dates[0], Path(output_dir))
3291
+ pgbar.Update(100, _('Video created'))
3292
+ pgbar.Destroy()
3293
+
3294
+ # Propose to lauch the video
3295
+ dlg = wx.MessageDialog(self, _('Video created: {}\n\nDo you want to launch it ?').format(outfile), _('Video created'), wx.YES_NO | wx.ICON_QUESTION)
3296
+ ret = dlg.ShowModal()
3297
+ if ret == wx.ID_YES:
3298
+ if sys.platform == "win32":
3299
+ os.startfile(outfile)
3300
+ # elif sys.platform == "darwin":
3301
+ # subprocess.call(["open", outfile])
3302
+ # elif sys.platform == "linux":
3303
+ # subprocess.call(["xdg-open", outfile])
3304
+ dlg.Destroy()
3305
+
3306
+ elif itemlabel == _("Total precip. [mm] - Multiple runs"):
3307
+
3308
+ data_dir = self.active_alaro.data_directory
3309
+ dates = self.active_alaro.list_run_dates_cached()
3310
+
3311
+ dates_str = [datetime.strptime(date, '%Y%m%d%H').replace(tzinfo=tz.utc) for date in dates]
3312
+ dates_str = [date.strftime('%Y-%m-%d %H+00') for date in dates_str]
3313
+
3314
+ dlg = wx.MultiChoiceDialog(self, _('Choose multiple Alaro runs to treat'), _('Choose Alaro runs'), choices=dates_str)
3315
+ ret = dlg.ShowModal()
3316
+ if ret == wx.ID_CANCEL:
3317
+ dlg.Destroy()
3318
+ return
3319
+ choices = dlg.GetSelections()
3320
+ dlg.Destroy()
3321
+
3322
+ if len(choices) == 0:
3323
+ logging.warning(_('No Alaro run selected'))
3324
+ return
3325
+
3326
+ dates = [dates[choice] for choice in choices]
3327
+
3328
+ dlg = wx.DirDialog(self, _('Choose output video directory'), defaultPath=str(data_dir), style=wx.DD_DEFAULT_STYLE | wx.DD_DIR_MUST_EXIST)
3329
+ ret = dlg.ShowModal()
3330
+ if ret == wx.ID_OK:
3331
+ output_dir = dlg.GetPath()
3332
+ dlg.Destroy()
3333
+
3334
+ self.active_alaro.reset_gdf()
3335
+
3336
+ pgbar = wx.ProgressDialog(_('Loading Alaro runs'), _('Loading data...'), maximum=100, parent=self, style=wx.PD_APP_MODAL | wx.PD_AUTO_HIDE)
3337
+
3338
+ pgbar.Pulse(_('Creating video...'))
3339
+ outdir = self.active_alaro.videos_cumulated_rain_allforecasts(output_dir, run_dates=dates)
3340
+ pgbar.Update(100, _('Video created'))
3341
+ pgbar.Destroy()
3342
+
3343
+ elif itemlabel == _("Download runs"):
3344
+
3345
+ pgbar = wx.ProgressDialog(_('Downloading Alaro runs'), _('Downloading data...'), maximum=100, parent=self, style=wx.PD_APP_MODAL | wx.PD_AUTO_HIDE)
3346
+ pgbar.Pulse(_('Downloading Alaro runs...'))
3347
+ ret = self.active_alaro.download_all_available_files()
3348
+ pgbar.Update(100, _('Alaro runs downloaded'))
3349
+ pgbar.Destroy()
3350
+
3351
+ for r in ret:
3352
+ logging.info(f'Downloaded Alaro run: {r}')
3353
+
3354
+ elif itemlabel == _("Download runs - Only Rain and Temperature"):
3355
+
3356
+ pgbar = wx.ProgressDialog(_('Downloading Alaro runs'), _('Downloading data...'), maximum=100, parent=self, style=wx.PD_APP_MODAL | wx.PD_AUTO_HIDE)
3357
+ pgbar.Pulse(_('Downloading Alaro runs...'))
3358
+ ret = self.active_alaro.download_TotalPrecipitations_available_files()
3359
+ pgbar.Update(100, _('Alaro runs downloaded'))
3360
+ pgbar.Destroy()
3361
+
3362
+ for r in ret:
3363
+ logging.info(f'Downloaded Alaro run: {r}')
3364
+
3365
+ elif itemlabel == _("Load run"):
3366
+
3367
+ data_dir = self.active_alaro.data_directory
3368
+ dates = self.active_alaro.list_run_dates_cached()
3369
+
3370
+ dates_str = [datetime.strptime(date, '%Y%m%d%H').replace(tzinfo=tz.utc) for date in dates]
3371
+ dates_str = [date.strftime('%Y-%m-%d %H+00') for date in dates_str]
3372
+
3373
+ dlg = wx.MultiChoiceDialog(self, _('Choose one or multiple Alaro runs to load'), _('Choose Alaro runs'), choices=dates_str)
3374
+ ret = dlg.ShowModal()
3375
+ if ret == wx.ID_CANCEL:
3376
+ dlg.Destroy()
3377
+ return
3378
+ choices = dlg.GetSelections()
3379
+ dlg.Destroy()
3380
+
3381
+ if len(choices) == 0:
3382
+ logging.warning(_('No Alaro run selected'))
3383
+ return
3384
+
3385
+ dates = [dates[choice] for choice in choices]
3386
+
3387
+ self.active_alaro.reset_gdf()
3388
+
3389
+ pgbar = wx.ProgressDialog(_('Loading Alaro runs'), _('Loading data...'), maximum=100, parent=self, style=wx.PD_APP_MODAL | wx.PD_AUTO_HIDE)
3390
+ pgbar.Pulse(_('Loading Alaro runs...'))
3391
+ self.active_alaro.load_grib_data_to_gdf(GribFiles.FILE_TotPrecip, dates)
3392
+ pgbar.Update(100, _('Alaro runs loaded'))
3393
+ pgbar.Destroy()
3394
+ logging.info(f'Loaded Alaro run: {dates}')
3395
+
3396
+ elif itemlabel == _("Add forecast(s) as array(s)"):
3397
+
3398
+ if self.active_alaro._gdf is None:
3399
+ logging.warning(_('No Alaro run loaded -- Please load a run first'))
3400
+ return
3401
+
3402
+ columns = self.active_alaro.get_forecast_columns()
3403
+
3404
+ columns_str = [_convert_col2date_str(col) for col in columns]
3405
+
3406
+ dlg = wx.MultiChoiceDialog(self, _('Choose one or multiple Alaro forecast to show'), _('Choose Alaro forecasts'), choices=columns_str)
3407
+ ret = dlg.ShowModal()
3408
+ if ret == wx.ID_CANCEL:
3409
+ dlg.Destroy()
3410
+ return
3411
+
3412
+ choices = dlg.GetSelections()
3413
+ dlg.Destroy()
3414
+
3415
+ if len(choices) == 0:
3416
+ logging.warning(_('No Alaro forecast selected'))
3417
+ return
3418
+
3419
+ columns = [columns[choice] for choice in choices]
3420
+
3421
+ pgbar = wx.ProgressDialog(_('Loading Alaro forecasts'), _('Loading data...'), maximum=100, parent=self, style=wx.PD_APP_MODAL | wx.PD_AUTO_HIDE)
3422
+ pgbar.Pulse(_('Loading Alaro forecasts...'))
3423
+ arrays = self.active_alaro.forecasts_to_arrays(columns)
3424
+ pgbar.Update(100, _('Alaro forecasts loaded'))
3425
+ pgbar.Destroy()
3426
+
3427
+ if len(arrays) == 0:
3428
+ logging.warning(_('No Alaro forecast to show'))
3429
+ return
3430
+
3431
+ for array in arrays:
3432
+ array.array *= 1000.0 # Convert from m to mm
3433
+ self.add_object('array', newobj=array, id=array.idx)
3434
+
3435
+ self.Refresh()
3436
+
3437
+ logging.info(_('Alaro forecasts added to the viewer'))
3438
+
3439
+ elif itemlabel == _("Show grid"):
3440
+
3441
+ if self.active_alaro._zones is None:
3442
+ self.active_alaro._prepare_Zones_from_grib(GribFiles.FILE_TotPrecip, self.active_alaro.run_dates[0])
3443
+
3444
+ self.active_alaro._zones.prep_listogl()
3445
+ self.add_object('vector', newobj=self.active_alaro._zones, id='Alaro_grid')
3446
+ self.Refresh()
3447
+
3448
+ elif itemlabel == _("Add all forecasts as arrays"):
3449
+ if self.active_alaro._gdf is None:
3450
+ logging.warning(_('No Alaro run loaded -- Please load a run first'))
3451
+ return
3452
+
3453
+ pgbar = wx.ProgressDialog(_('Loading Alaro forecasts'), _('Loading data...'), maximum=100, parent=self, style=wx.PD_APP_MODAL | wx.PD_AUTO_HIDE)
3454
+ pgbar.Pulse(_('Loading Alaro forecasts...'))
3455
+ arrays = self.active_alaro.forecasts_to_arrays()
3456
+ pgbar.Update(100, _('Alaro forecasts loaded'))
3457
+ pgbar.Destroy()
3458
+
3459
+ if len(arrays) == 0:
3460
+ logging.warning(_('No Alaro forecast to show'))
3461
+ return
3462
+
3463
+ for array in arrays:
3464
+ array.array *= 1000.0 # Convert from m to mm
3465
+ self.add_object('array', newobj=array, id=array.idx, ToCheck= False)
3466
+
3467
+ self.Refresh()
3468
+ logging.info(_('Alaro forecasts added to the viewer'))
3469
+
3470
+ elif itemlabel == _("Plot for XY"):
3471
+ if self.active_alaro._gdf is None:
3472
+ logging.warning(_('No Alaro run loaded -- Please load a run first'))
3473
+ return
3474
+
3475
+ self.start_action('plot alaro xy', _('Plot Alaro forecasts for a specific point -- Right click to select points'))
3476
+
3011
3477
  def menu_walous(self):
3012
3478
 
3013
3479
  if self.menuwalous is None:
3014
3480
  self.menuwalous = wx.Menu()
3015
3481
 
3016
- self.menuwalous_crop = self.menuwalous.Append(wx.ID_ANY, _("Crop on active array"), _("Crop active array"))
3017
- self.menuwalous_cropscreen = self.menuwalous.Append(wx.ID_ANY, _("Crop on screen"), _("Crop screen"))
3018
- self.menuwalous_map = self.menuwalous.Append(wx.ID_ANY, _("Map active array"), _("Map active array"))
3019
- self.menuwalous_legend = self.menuwalous.Append(wx.ID_ANY, _("Legend"), _("Legend"))
3020
- self._walous_filepath = None
3482
+ self._uts_menu = wx.Menu()
3483
+ self._ocs_menu = wx.Menu()
3484
+
3485
+ self._uts_crop = self._uts_menu.Append(wx.ID_ANY, _("Crop on active array"), _("Crop active array"))
3486
+ self._uts_cropscreen = self._uts_menu.Append(wx.ID_ANY, _("Crop on screen"), _("Crop screen"))
3487
+ self._uts_map = self._uts_menu.Append(wx.ID_ANY, _("Map active array (WAL_UTS -> Manning)"), _("Map Walous UTS active array to Manning's n"))
3488
+ self._uts_legend = self._uts_menu.Append(wx.ID_ANY, _("Legend"), _("Legend"))
3489
+
3490
+ self._ocs_crop = self._ocs_menu.Append(wx.ID_ANY, _("Crop on active array"), _("Crop active array"))
3491
+ self._ocs_cropscreen = self._ocs_menu.Append(wx.ID_ANY, _("Crop on screen"), _("Crop screen"))
3492
+ self._ocs_map = self._ocs_menu.Append(wx.ID_ANY, _("Map active array (WAL_OCS -> Hydrology)"), _("Map Walous OCS active array to Hydrology's landuse classification"))
3493
+ self._ocs_map = self._ocs_menu.Append(wx.ID_ANY, _("Map active array (WAL_OCS -> Manning)"), _("Map Walous OCS active array to Manning's n"))
3494
+ self._ocs_legend = self._ocs_menu.Append(wx.ID_ANY, _("Legend"), _("Legend"))
3495
+
3496
+ self._walous_UTS_filepath = None
3497
+ self._walous_OCS_filepath = None
3021
3498
  self._walous_layer = None
3022
3499
  self._walous_map = None
3023
3500
 
3501
+ self.menuwalous.AppendSubMenu(self._uts_menu, _('UTS'))
3502
+ self.menuwalous.AppendSubMenu(self._ocs_menu, _('OCS'))
3024
3503
  self.menubar.Append(self.menuwalous, _('Walous'))
3025
3504
 
3026
- self.menuwalous.Bind(wx.EVT_MENU, self.Onmenuwalous)
3505
+ self._uts_menu.Bind(wx.EVT_MENU, self.Onmenuwalous_uts)
3506
+ self._ocs_menu.Bind(wx.EVT_MENU, self.Onmenuwalous_ocs)
3027
3507
 
3028
3508
  def menu_drowning(self):
3029
3509
 
@@ -3103,21 +3583,22 @@ class WolfMapViewer(wx.Frame):
3103
3583
 
3104
3584
  return [xmin, ymin, xmax, ymax]
3105
3585
 
3106
- def get_bounds(self):
3586
+ def get_bounds(self, gridsize:float = None) -> tuple:
3107
3587
  """
3108
3588
  Retourne les limites de la zone d'affichage, voir aussi get_canvas_bounds
3109
3589
 
3110
3590
  :return: ([xmin, xmax], [ymin, ymax])
3111
3591
  """
3112
- xmin, ymin, xmax, ymax = self.get_canvas_bounds()
3592
+ xmin, ymin, xmax, ymax = self.get_canvas_bounds(gridsize=gridsize)
3593
+
3113
3594
  return ([xmin, xmax], [ymin, ymax])
3114
3595
 
3115
- def get_bounds_as_polygon(self) -> vector:
3596
+ def get_bounds_as_polygon(self, gridsize:float = None) -> vector:
3116
3597
  """
3117
3598
  Retourne les limites de la zone d'affichage sous forme de polygone
3118
3599
  :return: vector
3119
3600
  """
3120
- xmin, ymin, xmax, ymax = self.get_canvas_bounds()
3601
+ xmin, ymin, xmax, ymax = self.get_canvas_bounds(gridsize=gridsize)
3121
3602
  poly = vector()
3122
3603
  poly.add_vertex(wolfvertex(xmin, ymin))
3123
3604
  poly.add_vertex(wolfvertex(xmax, ymin))
@@ -3126,8 +3607,169 @@ class WolfMapViewer(wx.Frame):
3126
3607
  poly.force_to_close()
3127
3608
  return poly
3128
3609
 
3129
- def Onmenuwalous(self, event: wx.MenuEvent):
3610
+ def Onmenuwalous_ocs(self, event: wx.MenuEvent):
3611
+ """ Handle the Walous OCS menu events """
3612
+ id = event.GetId()
3613
+ item = self.menubar.FindItemById(event.GetId())
3614
+
3615
+ if item is None:
3616
+ return
3617
+
3618
+ itemlabel = item.ItemLabel
3619
+
3620
+ if itemlabel in [_("Crop on active array"), _("Crop on screen")]:
3621
+
3622
+ if itemlabel == _("Crop on screen"):
3623
+
3624
+ bounds = self.get_canvas_bounds(gridsize=1.)
3625
+
3626
+ def_outdrir = ''
3627
+ spatial_res = 1.
3628
+
3629
+ if self.active_array is not None:
3630
+ spatial_res = self.active_array.dx
3631
+
3632
+ dlg = wx.TextEntryDialog(None,_("Spatial resolution [m] ?"), value = str(spatial_res))
3633
+
3634
+ dlg.ShowModal()
3635
+ try:
3636
+ spatial_res = float(dlg.GetValue())
3637
+ dlg.Destroy()
3638
+ except:
3639
+ dlg.Destroy()
3640
+ logging.warning(_("Bad value -- Rety"))
3641
+ return
3642
+
3643
+ else:
3644
+
3645
+ if self.active_array is None:
3646
+ logging.warning(_('No active array -- Please activate data first'))
3647
+ return
3648
+
3649
+ bounds = self.active_array.get_bounds()
3650
+ def_outdrir = Path(self.active_array.filename).parent
3651
+ spatial_res = self.active_array.dx
3652
+
3653
+ from .pywalous import update_palette_walous_ocs
3654
+
3655
+ if self._walous_OCS_filepath is None:
3656
+ dlg = wx.FileDialog(self, _("Choose the Walous OCS Tif file"), wildcard="Tif file (*.tif)|*.tif|all (*.*)|*.*", style=wx.FD_OPEN)
3657
+ if dlg.ShowModal() == wx.ID_CANCEL:
3658
+ dlg.Destroy()
3659
+ return
3660
+
3661
+ self._walous_OCS_filepath = Path(dlg.GetPath())
3662
+ dlg.Destroy()
3663
+
3664
+
3665
+ dlg = wx.FileDialog(self, _("Choose the output file"), wildcard="Geotif (*.tif)|*.tif|all (*.*)|*.*", style=wx.FD_SAVE, defaultDir=str(def_outdrir))
3666
+ if dlg.ShowModal() == wx.ID_CANCEL:
3667
+ dlg.Destroy()
3668
+ return
3669
+
3670
+ output = Path(dlg.GetPath())
3671
+ dlg.Destroy()
3672
+
3673
+ locwalous = WolfArray(fname=self._walous_OCS_filepath,
3674
+ crop = bounds)
3675
+
3676
+ if Path(output).exists():
3677
+ logging.info(_('File {} created').format(output))
3678
+ else:
3679
+ logging.error(_('File {} not created').format(output))
3680
+ return
3681
+
3682
+ dlg = wx.MessageDialog(self, _('Do you want to load the created file ?'), _('Load file'), wx.YES_NO | wx.ICON_QUESTION)
3683
+ ret = dlg.ShowModal()
3684
+
3685
+ if ret == wx.ID_CANCEL:
3686
+ dlg.Destroy()
3687
+ return
3688
+
3689
+ elif ret == wx.ID_YES:
3690
+ walousarray = WolfArray(fname=output)
3691
+ update_palette_walous_ocs(walousarray.mypal)
3692
+ self.add_object('array', newobj=walousarray, id = 'walous_ocs_crop')
3693
+ dlg.Destroy()
3694
+
3695
+ elif itemlabel == _("Legend"):
3696
+ from .pywalous import Walous_OCS_Legend
3697
+ newlegend = Walous_OCS_Legend(self)
3698
+ newlegend.Show()
3699
+
3700
+ elif itemlabel == _("Map active array (WAL_OCS -> Hydrology)"):
3701
+
3702
+ from .pywalous import DlgMapWalous2Hydrology
3703
+
3704
+ if self.active_array is None:
3705
+ logging.warning(_('No active array -- Please activate data first'))
3706
+ return
3707
+
3708
+ vals = self.active_array.get_unique_values()
3709
+
3710
+ if self._walous_layer is None:
3711
+
3712
+ if vals[0] > 11:
3713
+ logging.error(_('You have values greater than 11 -- Please check your data'))
3714
+ return
3715
+
3716
+ dlg = DlgMapWalous2Hydrology(self,)
3717
+
3718
+ ret = dlg.ShowModal()
3719
+
3720
+ if ret == wx.ID_CANCEL:
3721
+ dlg.Destroy()
3722
+ return
3723
+
3724
+ mapvals = dlg.get_mapping()
3725
+ dlg.Destroy()
3726
+
3727
+ if mapvals == -1:
3728
+ logging.error(_('Bad values -- retry'))
3729
+ return
3730
+
3731
+ self.active_array.map_values(mapvals)
3732
+
3733
+ self.active_array.reset_plot()
3734
+
3735
+ elif itemlabel == _("Map active array (WAL_OCS -> Manning)"):
3736
+
3737
+ from .pywalous import DlgMapWalousOCS2Manning
3738
+
3739
+ if self.active_array is None:
3740
+ logging.warning(_('No active array -- Please activate data first'))
3741
+ return
3742
+
3743
+ vals = self.active_array.get_unique_values()
3744
+
3745
+ if self._walous_layer is None:
3746
+
3747
+ if vals[0] > 11:
3748
+ logging.error(_('You have values greater than 11 -- Please check your data'))
3749
+ return
3750
+
3751
+ dlg = DlgMapWalousOCS2Manning(self,)
3752
+
3753
+ ret = dlg.ShowModal()
3754
+
3755
+ if ret == wx.ID_CANCEL:
3756
+ dlg.Destroy()
3757
+ return
3758
+
3759
+ mapvals = dlg.get_mapping()
3760
+ dlg.Destroy()
3761
+
3762
+ if mapvals == -1:
3763
+ logging.error(_('Bad values -- retry'))
3764
+ return
3765
+
3766
+ self.active_array.map_values(mapvals)
3130
3767
 
3768
+ self.active_array.reset_plot()
3769
+
3770
+
3771
+ def Onmenuwalous_uts(self, event: wx.MenuEvent):
3772
+ """ Handle the Walous UTS menu events """
3131
3773
  id = event.GetId()
3132
3774
  item = self.menubar.FindItemById(event.GetId())
3133
3775
 
@@ -3170,15 +3812,15 @@ class WolfMapViewer(wx.Frame):
3170
3812
  def_outdrir = Path(self.active_array.filename).parent
3171
3813
  spatial_res = self.active_array.dx
3172
3814
 
3173
- from .pywalous import Walous_data, WALOUS2MANNING_MAJ_NIV1, WALOUS2MANNING_MAJ_NIV2, update_palette_walous
3815
+ from .pywalous import Walous_data, WALOUS2MANNING_MAJ_NIV1, WALOUS2MANNING_MAJ_NIV2, update_palette_walous_uts
3174
3816
 
3175
- if self._walous_filepath is None:
3817
+ if self._walous_UTS_filepath is None:
3176
3818
  dlg = wx.FileDialog(self, _("Choose the Walous shape file"), wildcard="Shapefile (*.shp)|*.shp|all (*.*)|*.*", style=wx.FD_OPEN)
3177
3819
  if dlg.ShowModal() == wx.ID_CANCEL:
3178
3820
  dlg.Destroy()
3179
3821
  return
3180
3822
 
3181
- self._walous_filepath = Path(dlg.GetPath())
3823
+ self._walous_UTS_filepath = Path(dlg.GetPath())
3182
3824
  dlg.Destroy()
3183
3825
 
3184
3826
 
@@ -3199,7 +3841,7 @@ class WolfMapViewer(wx.Frame):
3199
3841
 
3200
3842
  self._walous_layer = dlg.GetStringSelection()
3201
3843
 
3202
- locwalous = Walous_data(self._walous_filepath.parent, self._walous_filepath.name)
3844
+ locwalous = Walous_data(self._walous_UTS_filepath.parent, self._walous_UTS_filepath.name)
3203
3845
  ret = locwalous.rasterize(bounds=bounds,
3204
3846
  layer=self._walous_layer,
3205
3847
  fn_out=output,
@@ -3224,20 +3866,20 @@ class WolfMapViewer(wx.Frame):
3224
3866
 
3225
3867
  elif ret == wx.ID_YES:
3226
3868
  walousarray = WolfArray(fname=output)
3227
- update_palette_walous(self._walous_layer, walousarray.mypal)
3228
- self.add_object('array', newobj=walousarray, id = 'walous_crop')
3869
+ update_palette_walous_uts(self._walous_layer, walousarray.mypal)
3870
+ self.add_object('array', newobj=walousarray, id = 'walous_uts_crop')
3229
3871
  dlg.Destroy()
3230
3872
 
3231
3873
  elif itemlabel == _("Legend"):
3232
3874
 
3233
- from .pywalous import WalousLegend
3875
+ from .pywalous import Walous_UTS_Legend
3234
3876
 
3235
- newlegend = WalousLegend(self)
3877
+ newlegend = Walous_UTS_Legend(self)
3236
3878
  newlegend.Show()
3237
3879
 
3238
- elif itemlabel == _("Map active array"):
3880
+ elif itemlabel == _("Map active array (WAL_UTS -> Manning)"):
3239
3881
 
3240
- from .pywalous import DlgMapWalous, WALOUS2MANNING_MAJ_NIV1, WALOUS2MANNING_MAJ_NIV2
3882
+ from .pywalous import DlgMapWalous2Manning
3241
3883
 
3242
3884
  if self.active_array is None:
3243
3885
  logging.warning(_('No active array -- Please activate data first'))
@@ -3252,7 +3894,7 @@ class WolfMapViewer(wx.Frame):
3252
3894
  else:
3253
3895
  self._walous_layer = 'MAJ_NIV1'
3254
3896
 
3255
- dlg = DlgMapWalous(self, which=self._walous_layer)
3897
+ dlg = DlgMapWalous2Manning(self, which=self._walous_layer)
3256
3898
 
3257
3899
  ret = dlg.ShowModal()
3258
3900
 
@@ -4888,6 +5530,10 @@ class WolfMapViewer(wx.Frame):
4888
5530
 
4889
5531
  if nb_ticks_x > 10 or nb_ticks_y > 10:
4890
5532
  logging.error(_('Too many ticks for the image. Please raise the ticks size in the global options.'))
5533
+ dlg = wx.MessageDialog(None, _('Too many ticks for the image. Please raise the ticks size in the global options.'), _('Error'), style=wx.OK)
5534
+ dlg.ShowModal()
5535
+ dlg.Destroy()
5536
+ wx.TheClipboard.Close()
4891
5537
  return
4892
5538
 
4893
5539
  # Création d'un graphique Matplotlib
@@ -4964,10 +5610,25 @@ class WolfMapViewer(wx.Frame):
4964
5610
  if palette.values is not None:
4965
5611
  bufpal = io.BytesIO()
4966
5612
  palette.export_image(bufpal,'v')
4967
- bufpal.seek(0)
4968
5613
 
4969
- #lecture du buffer et conversion en image avec PIL
4970
- impal = Image.open(bufpal)
5614
+ try:
5615
+ bufpal.seek(0)
5616
+
5617
+ #lecture du buffer et conversion en image avec PIL
5618
+ impal = Image.open(bufpal)
5619
+
5620
+ except Exception as e:
5621
+
5622
+ text = _('Error while creating the colormap/palette image !')
5623
+ text += '\n'
5624
+ text += _('Please check if an array or a 2D result is active !')
5625
+
5626
+ logging.error(text)
5627
+ dlg = wx.MessageDialog(None, text, _('Error'), style=wx.OK)
5628
+ dlg.ShowModal()
5629
+ dlg.Destroy()
5630
+ return
5631
+
4971
5632
  impal = impal.resize((int(impal.size[0]*im.size[1]*.8/impal.size[1]),int(im.size[1]*.8)))
4972
5633
 
4973
5634
  imnew = Image.new('RGB',(im.size[0]+impal.size[0], im.size[1]), (255,255,255))
@@ -5268,6 +5929,8 @@ class WolfMapViewer(wx.Frame):
5268
5929
  self.menu_1to9 =self.menu_options.Append(wx.ID_ANY, _('Colors for selections 1->9'), _('Selections'))
5269
5930
  self.Bind(wx.EVT_MENU, self.colors1to9.change_colors, self.menu_1to9)
5270
5931
 
5932
+ self.menu_qdfidf()
5933
+
5271
5934
  self.Show(True)
5272
5935
 
5273
5936
  def OnChangeTitle(self, e):
@@ -5356,7 +6019,7 @@ class WolfMapViewer(wx.Frame):
5356
6019
 
5357
6020
  def setbounds(self, updatescale=True):
5358
6021
  """
5359
- Calcule les limites visibles de la fenêtrte graphique sur base des
6022
+ Calcule les limites visibles de la fenêtre graphique sur base des
5360
6023
  facteurs d'échelle courants
5361
6024
  """
5362
6025
 
@@ -5393,12 +6056,14 @@ class WolfMapViewer(wx.Frame):
5393
6056
  self.ymin = self.mousey - self.height / 2.
5394
6057
  self.ymax = self.ymin + self.height
5395
6058
 
6059
+
5396
6060
  self.mybackisloaded = False
5397
6061
  self.myfrontisloaded = False
5398
6062
 
5399
6063
  self.Refresh()
5400
6064
  self.mimicme()
5401
6065
 
6066
+
5402
6067
  def setsizecanvas(self,width,height):
5403
6068
  """ Redimensionne la fenêtre graphique """
5404
6069
  self.canvas.SetClientSize(width, height)
@@ -5560,41 +6225,48 @@ class WolfMapViewer(wx.Frame):
5560
6225
  'Wet_Bulb_Poten_Temper',
5561
6226
  'freezing_level_zeroDegC_isotherm'],
5562
6227
  """
5563
- alaro = {'ALARO': {'10m_u_wind_component': '10_m_u__wind_component',
5564
- '10m_v_wind_component': '10_m_v__wind_component',
5565
- '2m_Max_temp_since_ppp': '2_m_Max_temp_since_ppp',
5566
- '2m_Min_temp_since_ppp': '2_m_Min_temp_since_ppp',
5567
- '2m_dewpoint_temperature': '2_m_dewpoint_temperature',
5568
- '2m_temperature': '2_m_temperature',
5569
- '2m_Relative_humidity': '2m_Relative_humidity',
6228
+ # alaro = {'ALARO': {'10m_u_wind_component': '10_m_u__wind_component',
6229
+ # '10m_v_wind_component': '10_m_v__wind_component',
6230
+ # '2m_Max_temp_since_ppp': '2_m_Max_temp_since_ppp',
6231
+ # '2m_Min_temp_since_ppp': '2_m_Min_temp_since_ppp',
6232
+ # '2m_dewpoint_temperature': '2_m_dewpoint_temperature',
6233
+ # '2m_temperature': '2_m_temperature',
6234
+ # '2m_Relative_humidity': '2m_Relative_humidity',
6235
+ # 'Convective_rain': 'Convective_rain',
6236
+ # 'Convective_snow': 'Convective_snow',
6237
+ # 'Geopotential': 'Geopotential',
6238
+ # 'Inst_flx_Conv_Cld_Cover': 'Inst_flx_Conv_Cld_Cover',
6239
+ # 'Inst_flx_High_Cld_Cover': 'Inst_flx_High_Cld_Cover',
6240
+ # 'Inst_flx_Low_Cld_Cover': 'Inst_flx_Low_Cld_Cover',
6241
+ # 'Inst_flx_Medium_Cld_Cover': 'Inst_flx_Medium_Cld_Cover',
6242
+ # 'Inst_flx_Tot_Cld_cover': 'Inst_flx_Tot_Cld_cover',
6243
+ # 'Large_scale_rain': 'Large_scale_rain',
6244
+ # 'Large_scale_snow': 'Large_scale_snow',
6245
+ # 'Mean_sea_level_pressure': 'Mean_sea_level_pressure',
6246
+ # 'Relative_humidity': 'Relative_humidity',
6247
+ # 'Relative_humidity_isobaric': 'Relative_humidity_isobaric',
6248
+ # 'SBL_Meridian_gust': 'SBL_Meridian_gust',
6249
+ # 'SBL_Zonal_gust': 'SBL_Zonal_gust',
6250
+ # 'Specific_humidity': 'Specific_humidity',
6251
+ # 'Surf_Solar_radiation': 'Surf_Solar_radiation',
6252
+ # 'Surf_Thermal_radiation': 'Surf_Thermal_radiation',
6253
+ # 'Surface_CAPE': 'Surface_CAPE',
6254
+ # 'Surface_Temperature': 'Surface_Temperature',
6255
+ # 'Surface_orography': 'Surface_orography',
6256
+ # 'Temperature': 'Temperature',
6257
+ # 'Total_precipitation': 'Total_precipitation',
6258
+ # 'U-velocity': 'U-velocity',
6259
+ # 'V-velocity': 'V-velocity',
6260
+ # 'Vertical_velocity': 'Vertical_velocity',
6261
+ # 'Wet_Bulb_Poten_Temper': 'Wet_Bulb_Poten_Temper',
6262
+ # 'freezing_level_zeroDegC_isotherm': 'freezing_level_zeroDegC_isotherm',}}
6263
+ alaro = {'ALARO': {'2m_temperature': '2_m_temperature',
5570
6264
  'Convective_rain': 'Convective_rain',
5571
6265
  'Convective_snow': 'Convective_snow',
5572
- 'Geopotential': 'Geopotential',
5573
- 'Inst_flx_Conv_Cld_Cover': 'Inst_flx_Conv_Cld_Cover',
5574
- 'Inst_flx_High_Cld_Cover': 'Inst_flx_High_Cld_Cover',
5575
- 'Inst_flx_Low_Cld_Cover': 'Inst_flx_Low_Cld_Cover',
5576
- 'Inst_flx_Medium_Cld_Cover': 'Inst_flx_Medium_Cld_Cover',
5577
- 'Inst_flx_Tot_Cld_cover': 'Inst_flx_Tot_Cld_cover',
5578
6266
  'Large_scale_rain': 'Large_scale_rain',
5579
6267
  'Large_scale_snow': 'Large_scale_snow',
5580
- 'Mean_sea_level_pressure': 'Mean_sea_level_pressure',
5581
- 'Relative_humidity': 'Relative_humidity',
5582
- 'Relative_humidity_isobaric': 'Relative_humidity_isobaric',
5583
- 'SBL_Meridian_gust': 'SBL_Meridian_gust',
5584
- 'SBL_Zonal_gust': 'SBL_Zonal_gust',
5585
- 'Specific_humidity': 'Specific_humidity',
5586
- 'Surf_Solar_radiation': 'Surf_Solar_radiation',
5587
- 'Surf_Thermal_radiation': 'Surf_Thermal_radiation',
5588
- 'Surface_CAPE': 'Surface_CAPE',
5589
6268
  'Surface_Temperature': 'Surface_Temperature',
5590
- 'Surface_orography': 'Surface_orography',
5591
- 'Temperature': 'Temperature',
5592
- 'Total_precipitation': 'Total_precipitation',
5593
- 'U-velocity': 'U-velocity',
5594
- 'V-velocity': 'V-velocity',
5595
- 'Vertical_velocity': 'Vertical_velocity',
5596
- 'Wet_Bulb_Poten_Temper': 'Wet_Bulb_Poten_Temper',
5597
- 'freezing_level_zeroDegC_isotherm': 'freezing_level_zeroDegC_isotherm',}}
6269
+ 'Total_precipitation': 'Total_precipitation',}}
5598
6270
 
5599
6271
 
5600
6272
  for idx, (k, item) in enumerate(orthos.items()):
@@ -9281,7 +9953,7 @@ class WolfMapViewer(wx.Frame):
9281
9953
 
9282
9954
  self.create_2D_GPU_model()
9283
9955
 
9284
- elif itemlabel == _('Open Hydrological model'):
9956
+ elif itemlabel == _('Create/Open Hydrological model'):
9285
9957
 
9286
9958
  self.open_hydrological_model()
9287
9959
 
@@ -9474,6 +10146,13 @@ class WolfMapViewer(wx.Frame):
9474
10146
  newmanager.mapviewer = self
9475
10147
  newmanager.Show()
9476
10148
 
10149
+ elif itemlabel == _('Create INBE manager...'):
10150
+
10151
+ from .insyde_be.INBE_gui import INBEGui
10152
+ newmanager = INBEGui()
10153
+ newmanager.mapviewer = self
10154
+ newmanager.Show()
10155
+
9477
10156
  elif itemlabel==_('Create BC manager Wolf2D...'):
9478
10157
 
9479
10158
  if self.active_array is not None:
@@ -10486,7 +11165,7 @@ class WolfMapViewer(wx.Frame):
10486
11165
 
10487
11166
  if newobj is None:
10488
11167
 
10489
- if filename.endswith('.npz'):
11168
+ if str(filename).endswith('.npz'):
10490
11169
 
10491
11170
  wait = wx.BusyCursor()
10492
11171
  logging.info(_('Start of importing arrays from npz file'))
@@ -11197,7 +11876,7 @@ class WolfMapViewer(wx.Frame):
11197
11876
 
11198
11877
  # curdict[id.lower()] = newobj
11199
11878
  if filename != '':
11200
- newobj._filename_vector = filename.lower() # FIXME useful ??
11879
+ newobj._filename_vector = Path(filename).name.lower() # FIXME useful ??
11201
11880
  newobj.checked = ToCheck
11202
11881
 
11203
11882
  if isinstance(newobj,crosssections):
@@ -11210,24 +11889,113 @@ class WolfMapViewer(wx.Frame):
11210
11889
 
11211
11890
  return 0
11212
11891
 
11892
+ def replace_object(self, id: str, newobj, drawing_type: draw_type = None):
11893
+ """ Replace an object in the list of objects of type drawing_type """
11894
+
11895
+ if drawing_type is None:
11896
+ for curdict in draw_type:
11897
+ keys = self.get_list_keys(curdict, checked_state=None)
11898
+ if id.lower() in keys:
11899
+ # The object exists in the current dictionary
11900
+ obj = self.get_obj_from_id(id, drawing_type=curdict)
11901
+ obj.reset_listogl()
11902
+ # Searching the object in all lists
11903
+ if obj is not None:
11904
+ curlist = self._get_list(drawing_type=curdict)
11905
+ if obj in curlist:
11906
+ pos = curlist.index(obj)
11907
+ if isinstance(newobj, curlist[pos].__class__):
11908
+ # Updating the tree item
11909
+ self.treelist.SetItemData(self.get_treeitem_from_obj(obj), newobj)
11910
+ curlist[pos] = newobj
11911
+ newobj.idx = id.lower()
11912
+ else:
11913
+ logging.error(f'Cannot replace {id} with {newobj.idx} - Different type of object')
11914
+ else:
11915
+ logging.error(f'Object {id} not found in list')
11916
+ else:
11917
+ logging.error(f'Object {id} not found in list')
11918
+ else:
11919
+ logging.error(f'Object {id} not found in dictionary {curdict}')
11920
+ else:
11921
+ keys = self.get_list_keys(drawing_type, checked_state=None)
11922
+ if id.lower() in keys:
11923
+ # The object exists in the current dictionary
11924
+ obj = self.get_obj_from_id(id, drawing_type=drawing_type)
11925
+ obj.reset_listogl()
11926
+ # Searching the object in all lists
11927
+ if obj is not None:
11928
+ curlist = self._get_list(drawing_type=drawing_type)
11929
+ if obj in curlist:
11930
+ pos = curlist.index(obj)
11931
+ if isinstance(newobj, curlist[pos].__class__):
11932
+ # Updating the tree item
11933
+ self.treelist.SetItemData(self.get_treeitem_from_obj(obj), newobj)
11934
+ curlist[pos] = newobj
11935
+ newobj.idx = id.lower()
11936
+ else:
11937
+ logging.error(f'Cannot replace {id} with {newobj.idx} - Different type of object')
11938
+ else:
11939
+ logging.error(f'Object {id} not found in list')
11940
+ else:
11941
+ logging.error(f'Object {id} not found in list')
11942
+ else:
11943
+ logging.error(f'Object {id} not found in dictionary {drawing_type}')
11944
+
11945
+ obj = self.get_obj_from_id(id, drawing_type=drawing_type)
11946
+ obj_from_tree = self.get_obj_from_treeitem(self.get_treeitem_from_id(id, drawing_type=drawing_type))
11947
+ if obj is not None and obj_from_tree is not None:
11948
+ if obj is obj_from_tree:
11949
+ logging.debug(f'Object {id} replaced successfully in the list and tree item')
11950
+ else:
11951
+ logging.error(f'Object {id} replaced in the list but not in the tree item - {obj} != {obj_from_tree}')
11952
+ else:
11953
+ logging.error(f'Object {id} not found in the list or tree item after replacement')
11954
+
11213
11955
  def get_obj_from_treeitem(self, treeitem):
11214
11956
  """ Find the object associated with treeitem """
11215
11957
 
11216
11958
  return self.treelist.GetItemData(treeitem)
11217
11959
 
11218
- def getobj_from_id(self, id: str):
11960
+
11961
+ def get_treeitem_from_id(self, id: str, drawing_type: draw_type = None):
11962
+ """ Find the tree item associated with id """
11963
+
11964
+ obj = self.get_obj_from_id(id, drawing_type=drawing_type)
11965
+ if obj is not None:
11966
+ return self.get_treeitem_from_obj(obj)
11967
+ return None
11968
+
11969
+ def get_treeitem_from_obj(self, obj):
11970
+ """ Find the tree item associated with obj.
11971
+
11972
+ Alias for "gettreeitem".
11973
+ """
11974
+
11975
+ return self.gettreeitem(obj)
11976
+
11977
+ def getobj_from_id(self, id: str, drawing_type: draw_type = None):
11219
11978
  """ Find the object associated with id """
11220
11979
 
11221
- for curdict in draw_type:
11222
- keys = self.get_list_keys(curdict, checked_state=None)
11980
+ if drawing_type is None:
11981
+ for curdict in draw_type:
11982
+ keys = self.get_list_keys(curdict, checked_state=None)
11983
+ if id.lower() in keys:
11984
+ try:
11985
+ idx = keys.index(id.lower())
11986
+ return self.get_list_objects(curdict, checked_state=None)[idx]
11987
+ except:
11988
+ return None
11989
+ else:
11990
+ keys = self.get_list_keys(drawing_type, checked_state=None)
11223
11991
  if id.lower() in keys:
11224
11992
  try:
11225
11993
  idx = keys.index(id.lower())
11226
- return self.get_list_objects(curdict, checked_state=None)[idx]
11994
+ return self.get_list_objects(drawing_type, checked_state=None)[idx]
11227
11995
  except:
11228
11996
  return None
11229
11997
 
11230
- def get_obj_from_id(self, id: str, drawtype: draw_type):
11998
+ def get_obj_from_id(self, id: str, drawing_type: draw_type = None):
11231
11999
  """ Find the object associated with id in a specifid drawtype
11232
12000
 
11233
12001
  If you want to search in all drawtypes, use getobj_from_id instead.
@@ -11237,11 +12005,11 @@ class WolfMapViewer(wx.Frame):
11237
12005
 
11238
12006
  """
11239
12007
 
11240
- keys = self.get_list_keys(drawtype, checked_state=None)
12008
+ keys = self.get_list_keys(drawing_type, checked_state=None)
11241
12009
  if id.lower() in keys:
11242
12010
  try:
11243
12011
  idx = keys.index(id.lower())
11244
- return self.get_list_objects(drawtype, checked_state=None)[idx]
12012
+ return self.get_list_objects(drawing_type, checked_state=None)[idx]
11245
12013
  except:
11246
12014
  return None
11247
12015
 
@@ -11304,7 +12072,9 @@ class WolfMapViewer(wx.Frame):
11304
12072
  return None
11305
12073
 
11306
12074
  def get_list_keys(self, drawing_type:draw_type = None, checked_state:bool=True):
11307
- """ Create a list of keys of type draw_type
12075
+ """ Create a list of keys of type draw_type.
12076
+
12077
+ Return a list of keys (idx) in LOWER CASE of objects of type draw_type.
11308
12078
 
11309
12079
  :param drawing_type: type of object to search - If None, return all objects
11310
12080
  :param checked_state: if True/False, return only keys of objects that are plotted or not. None return all objects.
@@ -11321,7 +12091,9 @@ class WolfMapViewer(wx.Frame):
11321
12091
  return self.get_list_keys(drawing_type, checked_state)
11322
12092
 
11323
12093
  def get_list_objects(self, drawing_type:draw_type = None, checked_state:bool=True):
11324
- """ Create a list of objects of type draw_type
12094
+ """ Create a list of objects of type draw_type.
12095
+
12096
+ Return a list of keys (idx) in LOWER CASE of objects of type draw_type.
11325
12097
 
11326
12098
  :param drawing_type: type of object to search -- If None, return all objects.
11327
12099
  :param checked_state: if True/False, return only objects that are plotted or not. None return all objects.
@@ -11444,7 +12216,7 @@ class WolfMapViewer(wx.Frame):
11444
12216
  self.treelist.CheckItem(self.selected_treeitem, False)
11445
12217
  myobj.uncheck_plot()
11446
12218
 
11447
- def removeobj_from_id(self, id:str):
12219
+ def removeobj_from_id(self, id:str, draw_type:draw_type = None):
11448
12220
  """ Remove object from id """
11449
12221
 
11450
12222
  myobj = self.getobj_from_id(id)
@@ -11646,14 +12418,26 @@ class WolfMapViewer(wx.Frame):
11646
12418
 
11647
12419
  elif text == _('Rename'):
11648
12420
  #Modification du nom de l'objet sélectionné
12421
+
11649
12422
  if self.selected_object is not None:
11650
12423
  #récupération de l'id courant
12424
+ all_ids = self.get_list_ids(checked_state=None)
12425
+
11651
12426
  label = self.selected_object.idx
12427
+
12428
+ all_ids.remove(label.lower())
12429
+
11652
12430
  dlg = wx.TextEntryDialog(self, message=_('Chose a new label :'), value=label)
11653
12431
  ret=dlg.ShowModal()
11654
12432
 
11655
12433
  if ret == wx.ID_OK:
11656
12434
  newlab = dlg.GetValue()
12435
+
12436
+ if newlab.lower() in all_ids:
12437
+ wx.MessageBox(_('This label already exists. Please choose another one.'), _('Error'), wx.OK | wx.ICON_ERROR)
12438
+ dlg.Destroy()
12439
+ return
12440
+
11657
12441
  #MAJ de l'id dans l'objet
11658
12442
  self.selected_object.idx = newlab
11659
12443
  #MAJ de l'arbre
@@ -11806,6 +12590,15 @@ class WolfMapViewer(wx.Frame):
11806
12590
  elif isinstance(self.selected_object, Drowning_victim_Viewer):
11807
12591
  self.selected_object.saveas()
11808
12592
 
12593
+ elif isinstance(self.selected_object, crosssections):
12594
+ filterArray = "vecz (*.vecz)|*.vecz|SXY (*.sxy)|*.sxy"
12595
+ fdlg = wx.FileDialog(self, "Choose file name for Cross Sections :" + self.selected_object.idx, wildcard=filterArray,
12596
+ style=wx.FD_SAVE)
12597
+ ret = fdlg.ShowModal()
12598
+ if ret == wx.ID_OK:
12599
+ self.selected_object.saveas(fdlg.GetPath())
12600
+ fdlg.Destroy()
12601
+
11809
12602
  elif text == _('Properties'):
11810
12603
 
11811
12604
  myobj = self.selected_object
@@ -12426,8 +13219,9 @@ class WolfMapViewer(wx.Frame):
12426
13219
  """ Show images of the checked alaro layers"""
12427
13220
  objs = self.get_list_objects(drawing_type=draw_type.WMSFORE, checked_state=True)
12428
13221
  for obj in objs:
12429
- img = Image.open(get_Alaro_legend(obj.idx.replace('alaro ', '')))
12430
- img.show()
13222
+ if obj.category == 'ALARO':
13223
+ img = Image.open(get_Alaro_legend(obj.idx.replace('alaro ', '')))
13224
+ img.show()
12431
13225
 
12432
13226
  def getXY(self, pospix):
12433
13227
 
@@ -12536,6 +13330,15 @@ class WolfMapViewer(wx.Frame):
12536
13330
 
12537
13331
  self.rightdown = (x, y)
12538
13332
 
13333
+ elif self.action == 'plot alaro xy':
13334
+
13335
+ if self.active_alaro._gdf is None:
13336
+ logging.warning(_('No Alaro run loaded -- Please load a run first'))
13337
+ return
13338
+
13339
+ fig = self.active_alaro.plot_Rain_and_TotPrecip4XY(x, y)
13340
+ fig.show()
13341
+
12539
13342
  elif self.action == 'distance along vector':
12540
13343
 
12541
13344
  # add a vertex to the vector
@@ -12602,6 +13405,14 @@ class WolfMapViewer(wx.Frame):
12602
13405
  self.active_landmap.load_texture(x,y, which='low')
12603
13406
  self.Refresh()
12604
13407
 
13408
+ elif self.action == 'pick municipality':
13409
+ # Pick a municipality if loaded
13410
+ if self.active_qdfidf is None:
13411
+ logging.warning(_('No municipality data available -- Please activate the data and retry !'))
13412
+ return
13413
+
13414
+ self.active_qdfidf.pick_municipality(x, y, self.get_canvas_bounds())
13415
+
12605
13416
  elif self.action == 'pick a picture':
12606
13417
  # Pick a picture
12607
13418
 
@@ -15454,6 +16265,13 @@ class WolfMapViewer(wx.Frame):
15454
16265
  # Dessin des images
15455
16266
  self._plotting(draw_type.PICTURECOLLECTION)
15456
16267
 
16268
+ # Dessin des QDF/IDF
16269
+ if self.active_qdfidf is not None:
16270
+ self.active_qdfidf.plot(sx = self.sx, sy=self.sy,
16271
+ xmin=self.xmin, ymin=self.ymin,
16272
+ xmax=self.xmax, ymax=self.ymax,
16273
+ size = (self.xmax - self.xmin) / 100.)
16274
+
15457
16275
  # Gestion des BC (si actif)
15458
16276
  if self.active_bc is not None:
15459
16277
  self.active_bc.plot()