wolfhece 2.1.98__py3-none-any.whl → 2.1.100__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.
- wolfhece/PyDraw.py +506 -35
- wolfhece/PyParams.py +18 -8
- wolfhece/PyVertex.py +12 -5
- wolfhece/PyVertexvectors.py +27 -16
- wolfhece/Results2DGPU.py +23 -7
- wolfhece/acceptability/Parallels.py +2 -2
- wolfhece/acceptability/_add_path.py +23 -0
- wolfhece/acceptability/acceptability.py +594 -563
- wolfhece/acceptability/acceptability_gui.py +564 -331
- wolfhece/acceptability/cli.py +307 -120
- wolfhece/acceptability/func.py +1743 -1597
- wolfhece/analyze_vect.py +177 -0
- wolfhece/apps/version.py +1 -1
- wolfhece/bernoulli/losses.py +75 -22
- wolfhece/bernoulli/losses_jax.py +143 -0
- wolfhece/bernoulli/pipe.py +7 -2
- wolfhece/math_parser/__init__.py +4 -4
- wolfhece/math_parser/calculator.py +50 -9
- wolfhece/matplotlib_fig.py +1980 -0
- wolfhece/mesh2d/simple_2d.py +2399 -0
- wolfhece/mesh2d/wolf2dprev.py +1 -1
- wolfhece/pidcontroller.py +131 -0
- wolfhece/pywalous.py +7 -7
- wolfhece/scenario/config_manager.py +191 -83
- wolfhece/wolf_array.py +162 -109
- wolfhece/wolf_vrt.py +108 -7
- wolfhece/wolfresults_2D.py +109 -4
- wolfhece/xyz_file.py +91 -51
- {wolfhece-2.1.98.dist-info → wolfhece-2.1.100.dist-info}/METADATA +1 -1
- {wolfhece-2.1.98.dist-info → wolfhece-2.1.100.dist-info}/RECORD +33 -27
- {wolfhece-2.1.98.dist-info → wolfhece-2.1.100.dist-info}/WHEEL +1 -1
- {wolfhece-2.1.98.dist-info → wolfhece-2.1.100.dist-info}/entry_points.txt +0 -0
- {wolfhece-2.1.98.dist-info → wolfhece-2.1.100.dist-info}/top_level.txt +0 -0
wolfhece/PyDraw.py
CHANGED
@@ -24,6 +24,7 @@ try:
|
|
24
24
|
import json
|
25
25
|
import glob
|
26
26
|
import traceback
|
27
|
+
from datetime import datetime, timedelta
|
27
28
|
except ImportError as e:
|
28
29
|
print(e)
|
29
30
|
raise ImportError("Error importing wxPython, numpy, PIL, json, glob, traceback. Please check your installation.")
|
@@ -731,6 +732,372 @@ class DragdropFileTarget(wx.FileDropTarget):
|
|
731
732
|
|
732
733
|
return True
|
733
734
|
|
735
|
+
|
736
|
+
class Sim_Explorer(wx.Frame):
|
737
|
+
|
738
|
+
def __init__(self, parent, title, mapviewer:"WolfMapViewer", sim:Wolfresults_2D):
|
739
|
+
|
740
|
+
super(Sim_Explorer, self).__init__(parent, title=title, size=(150, 250), style = wx.DEFAULT_FRAME_STYLE & ~ (wx.MAXIMIZE_BOX | wx.MINIMIZE_BOX))
|
741
|
+
|
742
|
+
self._panel = wx.Panel(self)
|
743
|
+
|
744
|
+
self.mapviewer = mapviewer
|
745
|
+
self.active_res2d:Wolfresults_2D = sim
|
746
|
+
|
747
|
+
main_sizer = wx.BoxSizer(wx.HORIZONTAL)
|
748
|
+
|
749
|
+
left_bar = wx.BoxSizer(wx.VERTICAL)
|
750
|
+
right_bar = wx.BoxSizer(wx.VERTICAL)
|
751
|
+
|
752
|
+
self._all_times_steps = self.active_res2d.get_times_steps()
|
753
|
+
|
754
|
+
# Right bar
|
755
|
+
# ---------
|
756
|
+
|
757
|
+
# Slider
|
758
|
+
self._slider_steps = wx.Slider(self._panel, minValue=1, maxValue=sim.get_nbresults(), style=wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | wx.SL_MIN_MAX_LABELS | wx.SL_LABELS)
|
759
|
+
self._slider_steps.Bind(wx.EVT_SLIDER, self.OnSliderSteps)
|
760
|
+
right_bar.Add(self._slider_steps, 1, wx.EXPAND | wx.ALL, 2)
|
761
|
+
|
762
|
+
# Explore by index
|
763
|
+
self._label_idx = wx.StaticText(self._panel, label=_('Index'))
|
764
|
+
right_bar.Add(self._label_idx, 1, wx.EXPAND | wx.ALL, 2)
|
765
|
+
|
766
|
+
self._step_idx = wx.ListBox(self._panel, choices=[str(i) for i in range(1, sim.get_nbresults()+1)], style=wx.LB_SINGLE)
|
767
|
+
self._step_idx.Bind(wx.EVT_LISTBOX, self.OnSelectIdxStep)
|
768
|
+
right_bar.Add(self._step_idx, 1, wx.EXPAND | wx.ALL, 5)
|
769
|
+
|
770
|
+
# Explore by time
|
771
|
+
self._label_time = wx.StaticText(self._panel, label=_('Time [s]'))
|
772
|
+
right_bar.Add(self._label_time, 1, wx.EXPAND | wx.ALL, 2)
|
773
|
+
|
774
|
+
_now = datetime.now()
|
775
|
+
self._starting_date = datetime(year=_now.year, month=_now.month, day=_now.day, hour=0, minute=0, second=0)
|
776
|
+
self._texttime = wx.TextCtrl(self._panel, value=self._starting_date.strftime('%Y-%m-%d %H:%M:%S'))
|
777
|
+
right_bar.Add(self._texttime, 1, wx.EXPAND | wx.ALL, 5)
|
778
|
+
self._texttime.Bind(wx.EVT_TEXT, self.OnTextTime)
|
779
|
+
|
780
|
+
self._step_time = wx.ListBox(self._panel, choices=['{:.3f} - {}'.format(i, datetime.strftime(self._starting_date + timedelta(seconds=i), '%Y-%m-%d %H:%M:%S')) for i in self._all_times_steps[0]], style=wx.LB_SINGLE)
|
781
|
+
self._step_time.Bind(wx.EVT_LISTBOX, self.OnSelectNumStep)
|
782
|
+
right_bar.Add(self._step_time, 1, wx.EXPAND | wx.ALL, 5)
|
783
|
+
|
784
|
+
# Explore by time step
|
785
|
+
self._label_steps = wx.StaticText(self._panel, label=_('Time step [-]'))
|
786
|
+
right_bar.Add(self._label_steps, 1, wx.EXPAND | wx.ALL, 2)
|
787
|
+
|
788
|
+
self._step_num = wx.ListBox(self._panel, choices=[str(i) for i in self._all_times_steps[1]], style=wx.LB_SINGLE)
|
789
|
+
self._step_num.Bind(wx.EVT_LISTBOX, self.OnSelectCurTime)
|
790
|
+
right_bar.Add(self._step_num, 1, wx.EXPAND | wx.ALL, 5)
|
791
|
+
|
792
|
+
# Left bar
|
793
|
+
# --------
|
794
|
+
|
795
|
+
# Apply selected step
|
796
|
+
self._cmd_apply = wx.Button(self._panel, wx.ID_APPLY, _('Apply'))
|
797
|
+
self._cmd_apply.SetToolTip(_('Apply the selected parameters to the map'))
|
798
|
+
self._cmd_apply.Bind(wx.EVT_BUTTON, self.OnApply)
|
799
|
+
left_bar.Add(self._cmd_apply, 1, wx.EXPAND | wx.ALL, 5)
|
800
|
+
|
801
|
+
# Update listbox from files on disk
|
802
|
+
self._cmd_update = wx.Button(self._panel, wx.ID_REFRESH, _('Update'))
|
803
|
+
self._cmd_update.SetToolTip(_('Update the list of available results based on the files on disk'))
|
804
|
+
self._cmd_update.Bind(wx.EVT_BUTTON, self.OnUpdate)
|
805
|
+
left_bar.Add(self._cmd_update, 1, wx.EXPAND | wx.ALL, 5)
|
806
|
+
|
807
|
+
#Plot
|
808
|
+
self._cmd_plot = wx.Button(self._panel, wx.ID_PREVIEW, _('Plot simulation informations'))
|
809
|
+
self._cmd_plot.SetToolTip(_('Plot synthesis of the simulation (computation time, time step, clock time, mostly dry mesh...)'))
|
810
|
+
self._cmd_plot.Bind(wx.EVT_BUTTON, self.OnPlot)
|
811
|
+
left_bar.Add(self._cmd_plot, 1, wx.EXPAND | wx.ALL, 5)
|
812
|
+
|
813
|
+
# Next step
|
814
|
+
self._cmd_next = wx.Button(self._panel, wx.ID_FORWARD, _('Next'))
|
815
|
+
self._cmd_next.SetToolTip(_('Go to the next step -- using the selected mode'))
|
816
|
+
self._cmd_next.Bind(wx.EVT_BUTTON, self.OnNext)
|
817
|
+
left_bar.Add(self._cmd_next, 1, wx.EXPAND | wx.ALL, 5)
|
818
|
+
|
819
|
+
# Previous step
|
820
|
+
self._cmd_prev = wx.Button(self._panel, wx.ID_BACKWARD, _('Previous'))
|
821
|
+
self._cmd_prev.SetToolTip(_('Go to the previous step -- using the selected mode'))
|
822
|
+
self._cmd_prev.Bind(wx.EVT_BUTTON, self.OnPrev)
|
823
|
+
left_bar.Add(self._cmd_prev, 1, wx.EXPAND | wx.ALL, 5)
|
824
|
+
|
825
|
+
# Check Mode movement
|
826
|
+
self._mode = wx.ListBox(self._panel, choices=['by time [s]', 'by time [hour]', 'by index', 'by time step'], style=wx.LB_SINGLE)
|
827
|
+
self._mode.SetToolTip(_('Select the mode to move through the simulation'))
|
828
|
+
self._mode.SetSelection(2)
|
829
|
+
self._interval = wx.TextCtrl(self._panel, value='1', style=wx.ALIGN_CENTER_HORIZONTAL)
|
830
|
+
self._interval.SetToolTip(_('Interval for the mode selected -- unit depends on the mode'))
|
831
|
+
self._interval.Bind(wx.EVT_TEXT, self.OnInterval)
|
832
|
+
|
833
|
+
left_bar.Add(self._mode, 1, wx.EXPAND | wx.ALL, 5)
|
834
|
+
left_bar.Add(self._interval, 0, wx.EXPAND | wx.ALL, 5)
|
835
|
+
|
836
|
+
self.Bind(wx.EVT_CLOSE, self.OnClose)
|
837
|
+
|
838
|
+
main_sizer.Add(left_bar, 1, wx.EXPAND | wx.ALL, 2)
|
839
|
+
main_sizer.Add(right_bar, 1, wx.EXPAND | wx.ALL, 2)
|
840
|
+
|
841
|
+
self._panel.SetSizer(main_sizer)
|
842
|
+
self._panel.SetAutoLayout(True)
|
843
|
+
|
844
|
+
self.MinSize = (450, 500)
|
845
|
+
|
846
|
+
self.Fit()
|
847
|
+
self.Show()
|
848
|
+
|
849
|
+
self.SetIcon(wx.Icon(str(Path(__file__).parent / "apps/wolf_logo2.bmp")))
|
850
|
+
|
851
|
+
self._set_all(0)
|
852
|
+
|
853
|
+
def OnPlot(self, event):
|
854
|
+
""" Create a scatter plot of all steps.
|
855
|
+
|
856
|
+
Major x_axis is time in seconds, Minor X-axis is time by date.
|
857
|
+
|
858
|
+
Plots:
|
859
|
+
- Computation time step (Dt)
|
860
|
+
- Computation steps (N)
|
861
|
+
- Clock time (s)
|
862
|
+
- Mostly dry mesh (N)
|
863
|
+
|
864
|
+
"""
|
865
|
+
|
866
|
+
main_x = self._all_times_steps[0]
|
867
|
+
second_x = [self._starting_date + timedelta(seconds=i) for i in main_x]
|
868
|
+
|
869
|
+
if isinstance(self.active_res2d, wolfres2DGPU):
|
870
|
+
|
871
|
+
ax:list[Axes]
|
872
|
+
fig, ax= plt.subplots(5, 1, figsize=(10, 8))
|
873
|
+
|
874
|
+
ax[0].plot(main_x, self._all_times_steps[1], 'o-')
|
875
|
+
ax[0].set_ylabel(_('Computation\ntime step (N)'), fontsize=8)
|
876
|
+
ax[0].ticklabel_format(axis='y', style='sci', scilimits=(0,0))
|
877
|
+
|
878
|
+
ax[0].grid(which='both')
|
879
|
+
ax[0].set_xticks(main_x)
|
880
|
+
ax[0].set_xticklabels([])
|
881
|
+
|
882
|
+
secax:Axes = ax[0].secondary_xaxis('top')
|
883
|
+
secax.set_xlabel(_('Real date\n[Y-M-D H:M:S]'), fontsize=8)
|
884
|
+
secax.set_xticks(main_x)
|
885
|
+
secax.set_xticklabels([datetime.strftime(i, '%Y-%m-%d %H:%M') for i in second_x], fontsize=8)
|
886
|
+
secax.tick_params(axis='x', rotation=30)
|
887
|
+
|
888
|
+
ax[1].plot(main_x, self.active_res2d.all_dt, 'o-')
|
889
|
+
ax[1].set_ylabel(_('$\Delta t$ [s]'), fontsize=8)
|
890
|
+
ax[1].grid(which='both')
|
891
|
+
ax[1].set_xticks(main_x)
|
892
|
+
ax[1].set_xticklabels([])
|
893
|
+
ax[1].ticklabel_format(axis='y', style='sci', scilimits=(0,0))
|
894
|
+
|
895
|
+
ctime = self.active_res2d.all_clock_time
|
896
|
+
ax[2].plot(main_x, self.active_res2d.all_clock_time, 'o-')
|
897
|
+
ax[2].set_ylabel(_('Clock time [s]'), fontsize=8)
|
898
|
+
ax[2].grid(which='both')
|
899
|
+
ax[2].set_xticks([])
|
900
|
+
ax[2].set_xticks(main_x)
|
901
|
+
ax[2].set_xticklabels([])
|
902
|
+
ax[2].ticklabel_format(axis='y', style='sci', scilimits=(0,0))
|
903
|
+
|
904
|
+
# Fit a line on the (main_x - clock time) plot
|
905
|
+
# This will give a mean acceleration factor
|
906
|
+
# The inverse of the slope of the line is the accelaration factor
|
907
|
+
# The line is y = slope * x + intercept
|
908
|
+
from scipy.stats import linregress
|
909
|
+
slope, intercept, r_value, p_value, std_err = linregress(main_x, ctime)
|
910
|
+
|
911
|
+
# Plot the info on the ax[2]
|
912
|
+
msg = _('Acceleration factor:')
|
913
|
+
ax[2].text(0.5, 0.5, f'{msg} {1/slope:.2f}', transform=ax[2].transAxes, fontsize=12, verticalalignment='top')
|
914
|
+
|
915
|
+
ax[3].plot(main_x, self.active_res2d.all_wet_meshes, 'o-', color='blue')
|
916
|
+
ax[3].plot(main_x, self.active_res2d.all_mostly_dry_mesh, 'o-', color='green')
|
917
|
+
ax[3].set_ylabel(_('Wet and Mostly dry\nmeshes [N]'), fontsize=8)
|
918
|
+
ax[3].grid(which='both')
|
919
|
+
ax[3].set_xticks(main_x)
|
920
|
+
ax[3].set_xlabel([])
|
921
|
+
ax[3].ticklabel_format(axis='y', style='sci', scilimits=(0,0))
|
922
|
+
|
923
|
+
ax[4].plot(main_x, [i/j*100 if j>0 else 0 for i, j in zip(self.active_res2d.all_mostly_dry_mesh, self.active_res2d.all_wet_meshes)], 'o-', color='red')
|
924
|
+
ax[4].set_ylabel(_('Wet/Mostly dry\nmeshes [%]'), fontsize=8)
|
925
|
+
ax[4].grid(which='both')
|
926
|
+
ax[4].set_xticks(main_x)
|
927
|
+
ax[4].set_xlabel(_('Simulated time [s]'), fontsize=8)
|
928
|
+
ax[4].ticklabel_format(axis='y', style='sci', scilimits=(0,0))
|
929
|
+
|
930
|
+
fig.suptitle('Simulation {}'.format(self.active_res2d.idx), fontsize=10)
|
931
|
+
|
932
|
+
fig.tight_layout()
|
933
|
+
fig.show()
|
934
|
+
|
935
|
+
def OnInterval(self, event):
|
936
|
+
""" Change the interval """
|
937
|
+
|
938
|
+
try:
|
939
|
+
interv = float(self._interval.GetValue())
|
940
|
+
if interv <= 0:
|
941
|
+
interv = 1.
|
942
|
+
self._interval.SetValue('1')
|
943
|
+
except:
|
944
|
+
interv = 1
|
945
|
+
self._interval.SetValue('1')
|
946
|
+
|
947
|
+
def _find_next(self, idx:int):
|
948
|
+
""" Find the next step based on the mode and interval """
|
949
|
+
|
950
|
+
mode = int(self._mode.GetSelection())
|
951
|
+
|
952
|
+
if mode == 0:
|
953
|
+
# By time [s]
|
954
|
+
next_time = self._all_times_steps[0][idx] + float(self._interval.GetValue())
|
955
|
+
diff = [abs(next_time - i) for i in self._all_times_steps[0][idx:]]
|
956
|
+
next_idx = diff.index(min(diff)) + idx
|
957
|
+
|
958
|
+
return next_idx
|
959
|
+
|
960
|
+
elif mode == 1:
|
961
|
+
# By time [hour]
|
962
|
+
next_time = self._all_times_steps[0][idx] + float(self._interval.GetValue())*3600
|
963
|
+
diff = [abs(next_time - i) for i in self._all_times_steps[0][idx:]]
|
964
|
+
next_idx = diff.index(min(diff)) + idx
|
965
|
+
|
966
|
+
return next_idx
|
967
|
+
|
968
|
+
elif mode == 2:
|
969
|
+
# By index
|
970
|
+
next_idx = min(idx + int(self._interval.GetValue()), len(self._all_times_steps[0])-1)
|
971
|
+
|
972
|
+
return next_idx
|
973
|
+
|
974
|
+
elif mode == 3:
|
975
|
+
# By time step
|
976
|
+
next_idx = self._all_times_steps[1].index(self._all_times_steps[1][idx] + int(self._interval.GetValue()))
|
977
|
+
diff = [abs(next_idx - i) for i in self._all_times_steps[1][idx:]]
|
978
|
+
next_idx = diff.index(min(diff)) + idx
|
979
|
+
|
980
|
+
return next_idx
|
981
|
+
|
982
|
+
def _find_prev(self, idx:int):
|
983
|
+
""" Find the previous step based on the mode and interval """
|
984
|
+
|
985
|
+
mode = int(self._mode.GetSelection())
|
986
|
+
|
987
|
+
if mode == 0:
|
988
|
+
# By time [s]
|
989
|
+
prev_time = self._all_times_steps[0][idx] - float(self._interval.GetValue())
|
990
|
+
diff = [abs(prev_time - i) for i in self._all_times_steps[0][:idx]]
|
991
|
+
prev_idx = diff.index(min(diff))
|
992
|
+
|
993
|
+
return prev_idx
|
994
|
+
|
995
|
+
elif mode == 1:
|
996
|
+
# By time [hour]
|
997
|
+
prev_time = self._all_times_steps[0][idx] - float(self._interval.GetValue())*3600
|
998
|
+
diff = [abs(prev_time - i) for i in self._all_times_steps[0][:idx]]
|
999
|
+
prev_idx = diff.index(min(diff))
|
1000
|
+
|
1001
|
+
return prev_idx
|
1002
|
+
|
1003
|
+
elif mode == 2:
|
1004
|
+
# By index
|
1005
|
+
prev_idx = max(idx - int(self._interval.GetValue()), 0)
|
1006
|
+
|
1007
|
+
return prev_idx
|
1008
|
+
|
1009
|
+
elif mode == 3:
|
1010
|
+
# By time step
|
1011
|
+
prev_idx = self._all_times_steps[1].index(self._all_times_steps[1][idx] - int(self._interval.GetValue()))
|
1012
|
+
diff = [abs(prev_idx - i) for i in self._all_times_steps[1][:idx]]
|
1013
|
+
prev_idx = diff.index(min(diff))
|
1014
|
+
|
1015
|
+
return prev_idx
|
1016
|
+
|
1017
|
+
def OnNext(self, event):
|
1018
|
+
""" Go to the next step """
|
1019
|
+
|
1020
|
+
selected_step = self._slider_steps.GetValue()-1
|
1021
|
+
next_idx = self._find_next(selected_step)
|
1022
|
+
|
1023
|
+
if next_idx != selected_step:
|
1024
|
+
self._set_all(next_idx)
|
1025
|
+
self.Refresh(next_idx)
|
1026
|
+
|
1027
|
+
def OnPrev(self, event):
|
1028
|
+
""" Go to the previous step """
|
1029
|
+
|
1030
|
+
selected_step = self._slider_steps.GetValue()-1
|
1031
|
+
prev_idx = self._find_prev(selected_step)
|
1032
|
+
|
1033
|
+
if prev_idx != selected_step:
|
1034
|
+
self._set_all(prev_idx)
|
1035
|
+
self.Refresh(prev_idx)
|
1036
|
+
|
1037
|
+
def OnTextTime(self, event):
|
1038
|
+
try:
|
1039
|
+
self._starting_date = datetime.strptime(self._texttime.GetValue(), '%Y-%m-%d %H:%M:%S')
|
1040
|
+
self._step_time.Set(['{:.3f} - {}'.format(i, datetime.strftime(self._starting_date + timedelta(seconds=i), '%Y-%m-%d %H:%M:%S')) for i in self._all_times_steps[0]])
|
1041
|
+
except:
|
1042
|
+
logging.info('Error while parsing the date')
|
1043
|
+
pass
|
1044
|
+
|
1045
|
+
def OnClose(self, event):
|
1046
|
+
""" Close the simulation explorer """
|
1047
|
+
|
1048
|
+
self.mapviewer._pop_sim_explorer(self.active_res2d)
|
1049
|
+
self.Destroy()
|
1050
|
+
|
1051
|
+
def OnUpdate(self, event):
|
1052
|
+
self._update()
|
1053
|
+
|
1054
|
+
def OnApply(self, event):
|
1055
|
+
selected_step = self._slider_steps.GetValue()-1
|
1056
|
+
|
1057
|
+
self._cmd_apply.SetBackgroundColour(wx.Colour(255, 0, 0)) # Set button color to red
|
1058
|
+
self._cmd_apply.Refresh() # Refresh the button to apply the color change
|
1059
|
+
|
1060
|
+
self.Refresh(selected_step)
|
1061
|
+
|
1062
|
+
self._cmd_apply.SetBackgroundColour(wx.NullColour) # Reset button color to default
|
1063
|
+
self._cmd_apply.Refresh() # Refresh the button to apply the color change
|
1064
|
+
|
1065
|
+
def _set_all(self, idx:int):
|
1066
|
+
self._slider_steps.SetValue(idx+1)
|
1067
|
+
self._step_idx.SetSelection(idx)
|
1068
|
+
self._step_time.SetSelection(idx)
|
1069
|
+
self._step_num.SetSelection(idx)
|
1070
|
+
|
1071
|
+
def Refresh(self, idx:int):
|
1072
|
+
self.active_res2d.read_oneresult(idx)
|
1073
|
+
self.active_res2d.set_currentview()
|
1074
|
+
self.mapviewer.Refresh()
|
1075
|
+
|
1076
|
+
def OnSliderSteps(self, event):
|
1077
|
+
selected_step = self._slider_steps.GetValue()
|
1078
|
+
self._set_all(selected_step-1)
|
1079
|
+
|
1080
|
+
def OnSelectCurTime(self, event):
|
1081
|
+
selected_time = self._step_num.GetSelection()
|
1082
|
+
self._set_all(selected_time)
|
1083
|
+
|
1084
|
+
def OnSelectNumStep(self, event):
|
1085
|
+
selected_step = self._step_time.GetSelection()
|
1086
|
+
self._set_all(selected_step)
|
1087
|
+
|
1088
|
+
def OnSelectIdxStep(self, event):
|
1089
|
+
selected_step = self._step_idx.GetSelection()
|
1090
|
+
self._set_all(selected_step)
|
1091
|
+
|
1092
|
+
def _update(self):
|
1093
|
+
nb = self.active_res2d.get_nbresults()
|
1094
|
+
self._all_times_steps = self.active_res2d.get_times_steps()
|
1095
|
+
|
1096
|
+
self._slider_steps.SetMax(nb)
|
1097
|
+
self._step_idx.Set([str(i) for i in range(1,nb+1)])
|
1098
|
+
self._step_time.Set(['{:.3f} - {}'.format(i, datetime.strftime(self._starting_date + timedelta(seconds=i), '%Y-%m-%d %H:%M:%S')) for i in self._all_times_steps[0]])
|
1099
|
+
self._step_num.Set([str(i) for i in self._all_times_steps[1]])
|
1100
|
+
|
734
1101
|
class WolfMapViewer(wx.Frame):
|
735
1102
|
"""
|
736
1103
|
Fenêtre de visualisation de données WOLF grâce aux WxWidgets
|
@@ -751,6 +1118,7 @@ class WolfMapViewer(wx.Frame):
|
|
751
1118
|
mytiles: list[Tiles]
|
752
1119
|
mypartsystems: list[Particle_system]
|
753
1120
|
myviewers3d:list[Wolf_Viewer3D]
|
1121
|
+
sim_explorers: dict[Wolfresults_2D:Sim_Explorer]
|
754
1122
|
|
755
1123
|
canvas: GLCanvas # canvas OpenGL
|
756
1124
|
context: GLContext # context OpenGL
|
@@ -1450,6 +1818,10 @@ class WolfMapViewer(wx.Frame):
|
|
1450
1818
|
if self.menuwolf2d is None:
|
1451
1819
|
self.menuwolf2d = wx.Menu()
|
1452
1820
|
|
1821
|
+
self.menu2d_explore_results = self.menuwolf2d.Append(wx.ID_ANY, _("Explore time/index results"), _("Open a dialog to explore time/index results"))
|
1822
|
+
|
1823
|
+
self.menuwolf2d.AppendSeparator()
|
1824
|
+
|
1453
1825
|
self.menu2d_curentview = self.menuwolf2d.Append(wx.ID_ANY, _("Change current view"), _("Current view"))
|
1454
1826
|
self.menu2d_lastres = self.menuwolf2d.Append(wx.ID_ANY, _("Read last result"), _("Current view"))
|
1455
1827
|
self.menu2d_epsilon = self.menuwolf2d.Append(wx.ID_ANY, _("Set epsilon water depth"), _("Set the epsilon used in the mask"))
|
@@ -1462,11 +1834,11 @@ class WolfMapViewer(wx.Frame):
|
|
1462
1834
|
self.menuwolf2d.AppendSeparator()
|
1463
1835
|
|
1464
1836
|
self.menu2d_dangermap = self.menuwolf2d.Append(wx.ID_ANY, _("Danger map"), _("Compute the danger map"))
|
1465
|
-
self.menu2d_dangermaph = self.menuwolf2d.Append(wx.ID_ANY, _("Danger map - only h"), _("Compute the danger map"))
|
1837
|
+
self.menu2d_dangermaph = self.menuwolf2d.Append(wx.ID_ANY, _("Danger map - only h"), _("Compute the danger map - only waterdepth"))
|
1466
1838
|
|
1467
1839
|
self.menuwolf2d.AppendSeparator()
|
1468
1840
|
|
1469
|
-
self.menu2d_export_as = self.menuwolf2d.Append(wx.ID_ANY, _("Export results as..."), _("Export results as Geotif or
|
1841
|
+
self.menu2d_export_as = self.menuwolf2d.Append(wx.ID_ANY, _("Export results as..."), _("Export results as Geotif, Shapefile or Numpy arrays"))
|
1470
1842
|
|
1471
1843
|
self.menuwolf2d.AppendSeparator()
|
1472
1844
|
# Possible cache entries will be added after this separator
|
@@ -1659,6 +2031,41 @@ class WolfMapViewer(wx.Frame):
|
|
1659
2031
|
|
1660
2032
|
self.active_array.reset_plot()
|
1661
2033
|
|
2034
|
+
def _add_sim_explorer(self, which:Wolfresults_2D):
|
2035
|
+
""" Add a step chooser """
|
2036
|
+
|
2037
|
+
if which in self.sim_explorers:
|
2038
|
+
logging.warning(_('Step chooser already exists for this result'))
|
2039
|
+
self.sim_explorers[which].Show()
|
2040
|
+
self.sim_explorers[which].Raise()
|
2041
|
+
self.sim_explorers[which].SetFocus()
|
2042
|
+
self.sim_explorers[which].Center()
|
2043
|
+
return
|
2044
|
+
|
2045
|
+
self.sim_explorers[which] = Sim_Explorer(self, which.idx, self, which)
|
2046
|
+
self.sim_explorers[which]._set_all(which.current_result)
|
2047
|
+
|
2048
|
+
def _pop_sim_explorer(self, which:Wolfresults_2D):
|
2049
|
+
""" Pop a step chooser """
|
2050
|
+
|
2051
|
+
if which in self.sim_explorers:
|
2052
|
+
self.sim_explorers.pop(which)
|
2053
|
+
logging.debug(_('Pop step chooser for result {}'.format(which.idx)))
|
2054
|
+
else:
|
2055
|
+
logging.warning(_('No step chooser for this result'))
|
2056
|
+
|
2057
|
+
def _update_sim_explorer(self, which:Wolfresults_2D = None):
|
2058
|
+
|
2059
|
+
if which is None:
|
2060
|
+
if self.active_res2d is None:
|
2061
|
+
logging.warning(_('No active 2D result -- Please activate a 2D result first'))
|
2062
|
+
return
|
2063
|
+
|
2064
|
+
which = self.active_res2d
|
2065
|
+
|
2066
|
+
if which in self.sim_explorers:
|
2067
|
+
self.sim_explorers[which]._set_all(which.current_result)
|
2068
|
+
|
1662
2069
|
def Onmenuwolf2d(self, event: wx.MenuEvent):
|
1663
2070
|
|
1664
2071
|
id = event.GetId()
|
@@ -1678,6 +2085,13 @@ class WolfMapViewer(wx.Frame):
|
|
1678
2085
|
|
1679
2086
|
self.export_results_as()
|
1680
2087
|
|
2088
|
+
elif itemlabel == _("Explore time/index results"):
|
2089
|
+
if self.active_res2d is None:
|
2090
|
+
logging.warning(_('No active 2D result ! -- Please activate a 2D result first'))
|
2091
|
+
return
|
2092
|
+
|
2093
|
+
self._add_sim_explorer(self.active_res2d)
|
2094
|
+
|
1681
2095
|
elif itemlabel == _("Change current view"):
|
1682
2096
|
|
1683
2097
|
# Change view for results
|
@@ -3278,6 +3692,7 @@ class WolfMapViewer(wx.Frame):
|
|
3278
3692
|
self.mywmsfore = []
|
3279
3693
|
self.myres2D = []
|
3280
3694
|
self.myviewers3d = []
|
3695
|
+
self.sim_explorers = {}
|
3281
3696
|
|
3282
3697
|
# liste des éléments modifiable dans l'arbre
|
3283
3698
|
self.all_lists = [self.myarrays, self.myvectors, self.myclouds, self.mytri, self.myothers, self.myviews, self.myres2D, self.mytiles, self.mypartsystems, self.myviewers3d]
|
@@ -4683,6 +5098,8 @@ class WolfMapViewer(wx.Frame):
|
|
4683
5098
|
else:
|
4684
5099
|
return
|
4685
5100
|
|
5101
|
+
logging.info(_('This could take some time for large area...\n Take a coffee and relax!'))
|
5102
|
+
|
4686
5103
|
bounds = array.get_bounds()
|
4687
5104
|
|
4688
5105
|
# align bounds on chunk_size
|
@@ -4776,7 +5193,7 @@ class WolfMapViewer(wx.Frame):
|
|
4776
5193
|
array.reset_plot()
|
4777
5194
|
self.Paint()
|
4778
5195
|
|
4779
|
-
logging.info(_('Filling done'))
|
5196
|
+
logging.info(_('Filling done !'))
|
4780
5197
|
|
4781
5198
|
def count_active_array_from_laz(self, array:WolfArray = None, used_codes:list = [], chunk_size:float = 500.):
|
4782
5199
|
""" Fill active array with laz data
|
@@ -5043,6 +5460,7 @@ class WolfMapViewer(wx.Frame):
|
|
5043
5460
|
|
5044
5461
|
curmodel.read_oneresult()
|
5045
5462
|
curmodel.set_currentview()
|
5463
|
+
self._update_sim_explorer(curmodel)
|
5046
5464
|
|
5047
5465
|
self.Refresh()
|
5048
5466
|
self.currently_readresults = False
|
@@ -5061,6 +5479,8 @@ class WolfMapViewer(wx.Frame):
|
|
5061
5479
|
|
5062
5480
|
curmodel.read_oneresult(which)
|
5063
5481
|
curmodel.set_currentview()
|
5482
|
+
self._update_sim_explorer(curmodel)
|
5483
|
+
|
5064
5484
|
|
5065
5485
|
self.Refresh()
|
5066
5486
|
self.currently_readresults = False
|
@@ -5079,6 +5499,7 @@ class WolfMapViewer(wx.Frame):
|
|
5079
5499
|
|
5080
5500
|
curmodel.read_previous()
|
5081
5501
|
curmodel.set_currentview()
|
5502
|
+
self._update_sim_explorer(curmodel)
|
5082
5503
|
|
5083
5504
|
self.Refresh()
|
5084
5505
|
self.currently_readresults = False
|
@@ -5120,6 +5541,8 @@ class WolfMapViewer(wx.Frame):
|
|
5120
5541
|
|
5121
5542
|
curmodel.read_next()
|
5122
5543
|
curmodel.set_currentview()
|
5544
|
+
self._update_sim_explorer(curmodel)
|
5545
|
+
|
5123
5546
|
|
5124
5547
|
self.Refresh()
|
5125
5548
|
self.currently_readresults = False
|
@@ -5402,6 +5825,8 @@ class WolfMapViewer(wx.Frame):
|
|
5402
5825
|
linkedarrays = self.get_linked_arrays()
|
5403
5826
|
|
5404
5827
|
with wx.MultiChoiceDialog(None, _('Choose the arrays to plot'), _('Arrays'), [curarray for curarray in list(linkedarrays.keys())]) as dlg:
|
5828
|
+
dlg.SetSelections(range(len(linkedarrays)))
|
5829
|
+
|
5405
5830
|
if dlg.ShowModal() == wx.ID_CANCEL:
|
5406
5831
|
dlg.Destroy()
|
5407
5832
|
return
|
@@ -6443,31 +6868,40 @@ class WolfMapViewer(wx.Frame):
|
|
6443
6868
|
|
6444
6869
|
logging.info(_('Filtering done !'))
|
6445
6870
|
|
6446
|
-
def export_results_as(self, which:Literal['geotiff','shape'] = None, multiband:bool = None):
|
6871
|
+
def export_results_as(self, which:Literal['geotiff','shape','numpy'] = None, multiband:bool = None):
|
6447
6872
|
"""
|
6448
|
-
Export des résultats WOLF2D vers
|
6449
|
-
|
6873
|
+
Export des résultats WOLF2D vers différents formats.
|
6874
|
+
Au moins un résultat doit être chargé pour pouvoir être exporté.
|
6450
6875
|
"""
|
6451
6876
|
|
6452
6877
|
dlg = wx.DirDialog(self,_('Choose output directory'), style = wx.DD_DIR_MUST_EXIST)
|
6453
6878
|
ret=dlg.ShowModal()
|
6454
6879
|
|
6455
6880
|
if ret == wx.ID_CANCEL:
|
6881
|
+
logging.warning(_('Abort!'))
|
6456
6882
|
dlg.Destroy()
|
6457
6883
|
return
|
6458
6884
|
|
6459
6885
|
outdir = dlg.GetPath()
|
6460
6886
|
dlg.Destroy()
|
6461
6887
|
|
6462
|
-
if which not in ['geotiff','shape']:
|
6463
|
-
dlg = wx.SingleChoiceDialog(self,_('Choose output format'), _('Format'), ['Geotiff','Shape file'])
|
6464
|
-
dlg.ShowModal()
|
6888
|
+
if which not in ['geotiff','shape','numpy']:
|
6889
|
+
dlg = wx.SingleChoiceDialog(self,_('Choose output format'), _('Format'), ['Geotiff','Shape file','Numpy array'])
|
6890
|
+
ret = dlg.ShowModal()
|
6891
|
+
|
6892
|
+
if ret == wx.ID_CANCEL:
|
6893
|
+
logging.warning(_('Abort!'))
|
6894
|
+
dlg.Destroy()
|
6895
|
+
return
|
6896
|
+
|
6465
6897
|
sel = dlg.GetSelection()
|
6466
6898
|
|
6467
6899
|
if sel == 0:
|
6468
6900
|
which = 'geotiff'
|
6469
|
-
|
6901
|
+
elif sel == 1:
|
6470
6902
|
which = 'shape'
|
6903
|
+
else:
|
6904
|
+
which = 'numpy'
|
6471
6905
|
|
6472
6906
|
dlg.Destroy()
|
6473
6907
|
|
@@ -6490,7 +6924,12 @@ class WolfMapViewer(wx.Frame):
|
|
6490
6924
|
|
6491
6925
|
dlg = wx.MultiChoiceDialog(self,_('Choose results to export'), _('Results'), choices=loaded_res)
|
6492
6926
|
dlg.SetSelections([idx for idx, res in enumerate(loaded_res) if self.get_obj_from_id(res, drawtype=draw_type.RES2D).plotted])
|
6493
|
-
dlg.ShowModal()
|
6927
|
+
ret = dlg.ShowModal()
|
6928
|
+
if ret == wx.ID_CANCEL:
|
6929
|
+
logging.warning(_('Abort!'))
|
6930
|
+
dlg.Destroy()
|
6931
|
+
return
|
6932
|
+
|
6494
6933
|
sel = dlg.GetSelections() # Get a list if integers
|
6495
6934
|
sel_res = [self.get_obj_from_id(loaded_res[cursel], drawtype=draw_type.RES2D) for cursel in sel] # convert to list of objects
|
6496
6935
|
|
@@ -6516,7 +6955,13 @@ class WolfMapViewer(wx.Frame):
|
|
6516
6955
|
|
6517
6956
|
dlg = wx.MultiChoiceDialog(self,_('Choose fields to export'), _('Fields'), choices= [str(field[0]) for field in fields])
|
6518
6957
|
dlg.SetSelections([idx for idx, field in enumerate(fields) if field[1]])
|
6519
|
-
dlg.ShowModal()
|
6958
|
+
ret = dlg.ShowModal()
|
6959
|
+
|
6960
|
+
if ret == wx.ID_CANCEL:
|
6961
|
+
logging.warning(_('Abort!'))
|
6962
|
+
dlg.Destroy()
|
6963
|
+
return
|
6964
|
+
|
6520
6965
|
sel_fields = dlg.GetSelections() # Get a list if integers
|
6521
6966
|
dlg.Destroy()
|
6522
6967
|
|
@@ -7136,16 +7581,27 @@ class WolfMapViewer(wx.Frame):
|
|
7136
7581
|
# myhead.dy = 1.
|
7137
7582
|
|
7138
7583
|
else:
|
7584
|
+
|
7585
|
+
dlg = wx.TextEntryDialog(self,_('Spatial step size (assuming dx == dy) ?'), value='1')
|
7586
|
+
ret=dlg.ShowModal()
|
7587
|
+
|
7588
|
+
if ret == wx.ID_CANCEL:
|
7589
|
+
dlg.Destroy()
|
7590
|
+
return -1
|
7591
|
+
|
7592
|
+
tmpdx = float(dlg.GetValue())
|
7593
|
+
dlg.Destroy()
|
7594
|
+
|
7595
|
+
dy = dx
|
7596
|
+
|
7139
7597
|
myxyz = xyz_scandir(filename, None)
|
7140
7598
|
myhead = header_wolf()
|
7141
7599
|
|
7142
|
-
myhead.origx = np.min(myxyz[:, 0]) - .
|
7143
|
-
myhead.origy = np.min(myxyz[:, 1]) - .
|
7600
|
+
myhead.origx = np.min(myxyz[:, 0]) - dx/2.
|
7601
|
+
myhead.origy = np.min(myxyz[:, 1]) - dy/2.
|
7144
7602
|
|
7145
|
-
myhead.dx =
|
7146
|
-
myhead.dy =
|
7147
|
-
tmpdx = 1.
|
7148
|
-
tmpdy = 1.
|
7603
|
+
myhead.dx = dx
|
7604
|
+
myhead.dy = dy
|
7149
7605
|
|
7150
7606
|
myhead.nbx = int(np.max(myxyz[:, 0]) - myhead.origx) + 1
|
7151
7607
|
myhead.nby = int(np.max(myxyz[:, 1]) - myhead.origy) + 1
|
@@ -7163,10 +7619,6 @@ class WolfMapViewer(wx.Frame):
|
|
7163
7619
|
|
7164
7620
|
newobj.mask_data(newobj.nullvalue)
|
7165
7621
|
|
7166
|
-
# if min(tmpdx, tmpdy) != 1.:
|
7167
|
-
# newobj.rebin(min(tmpdx, tmpdy))
|
7168
|
-
# newobj.mask_data(newobj.nullvalue)
|
7169
|
-
|
7170
7622
|
newobj.change_gui(self)
|
7171
7623
|
newobj.updatepalette(0)
|
7172
7624
|
self.myarrays.append(newobj)
|
@@ -9595,7 +10047,25 @@ class WolfMapViewer(wx.Frame):
|
|
9595
10047
|
logging.debug(_('Alt is down'))
|
9596
10048
|
|
9597
10049
|
if ctrldown or altdown:
|
9598
|
-
if key ==
|
10050
|
+
if key == 60 and shiftdown: #'>'
|
10051
|
+
if self.active_array is not None:
|
10052
|
+
if self.active_array.SelectionData is not None:
|
10053
|
+
self.active_array.SelectionData.dilate_contour_selection(1)
|
10054
|
+
self.active_array.reset_plot()
|
10055
|
+
elif key == 60 and not shiftdown: #'<'
|
10056
|
+
if self.active_array is not None:
|
10057
|
+
if self.active_array.SelectionData is not None:
|
10058
|
+
self.active_array.SelectionData.erode_contour_selection()
|
10059
|
+
self.active_array.reset_plot()
|
10060
|
+
|
10061
|
+
elif key == wx.WXK_F2 and ctrldown and altdown and shiftdown:
|
10062
|
+
|
10063
|
+
if self.active_res2d is None:
|
10064
|
+
logging.info(_('Please activate a simulation before search a specific result'))
|
10065
|
+
|
10066
|
+
self._add_sim_explorer(self.active_res2d)
|
10067
|
+
|
10068
|
+
elif key == wx.WXK_F2 and not shiftdown:
|
9599
10069
|
|
9600
10070
|
if self.active_res2d is not None:
|
9601
10071
|
nb = self.active_res2d.get_nbresults()
|
@@ -9609,20 +10079,11 @@ class WolfMapViewer(wx.Frame):
|
|
9609
10079
|
self.active_res2d.set_currentview()
|
9610
10080
|
self.Refresh()
|
9611
10081
|
|
10082
|
+
self._update_sim_explorer()
|
10083
|
+
|
9612
10084
|
else:
|
9613
10085
|
logging.info(_('Please activate a simulation before search a specific result'))
|
9614
10086
|
|
9615
|
-
elif key == 60 and shiftdown: #'>'
|
9616
|
-
if self.active_array is not None:
|
9617
|
-
if self.active_array.SelectionData is not None:
|
9618
|
-
self.active_array.SelectionData.dilate_contour_selection(1)
|
9619
|
-
self.active_array.reset_plot()
|
9620
|
-
elif key == 60 and not shiftdown: #'<'
|
9621
|
-
if self.active_array is not None:
|
9622
|
-
if self.active_array.SelectionData is not None:
|
9623
|
-
self.active_array.SelectionData.erode_contour_selection()
|
9624
|
-
self.active_array.reset_plot()
|
9625
|
-
|
9626
10087
|
elif key == wx.WXK_F2 and shiftdown:
|
9627
10088
|
|
9628
10089
|
if self.active_res2d is not None:
|
@@ -9648,6 +10109,8 @@ class WolfMapViewer(wx.Frame):
|
|
9648
10109
|
self.active_res2d.set_currentview()
|
9649
10110
|
self.Refresh()
|
9650
10111
|
|
10112
|
+
self._update_sim_explorer()
|
10113
|
+
|
9651
10114
|
else:
|
9652
10115
|
logging.info(_('Please activate a simulation before searching a specific result'))
|
9653
10116
|
|
@@ -9665,6 +10128,7 @@ class WolfMapViewer(wx.Frame):
|
|
9665
10128
|
self.active_particle_system.current_step = nb-1
|
9666
10129
|
self.Refresh()
|
9667
10130
|
self._update_mytooltip()
|
10131
|
+
self._update_sim_explorer()
|
9668
10132
|
|
9669
10133
|
else:
|
9670
10134
|
logging.info(_('Please activate a particle system before searching a specific result'))
|
@@ -9692,6 +10156,7 @@ class WolfMapViewer(wx.Frame):
|
|
9692
10156
|
self.active_particle_system.current_step = choices.index(keyvalue)
|
9693
10157
|
self.Refresh()
|
9694
10158
|
self._update_mytooltip()
|
10159
|
+
self._update_sim_explorer()
|
9695
10160
|
|
9696
10161
|
else:
|
9697
10162
|
logging.info(_('Please activate a simulation before search a specific result'))
|
@@ -10062,7 +10527,13 @@ class WolfMapViewer(wx.Frame):
|
|
10062
10527
|
self.active_array.myops.select_node_by_node()
|
10063
10528
|
|
10064
10529
|
if self.active_res2d is not None:
|
10065
|
-
self.
|
10530
|
+
if self.active_array is not None:
|
10531
|
+
msg = wx.MessageDialog(None, _('Do you want to select the nodes of the active result ?'), _('Select nodes'), wx.YES_NO | wx.ICON_QUESTION)
|
10532
|
+
ret = msg.ShowModal()
|
10533
|
+
if ret == wx.ID_YES:
|
10534
|
+
self.active_res2d.properties.select_node_by_node()
|
10535
|
+
else:
|
10536
|
+
self.active_res2d.properties.select_node_by_node()
|
10066
10537
|
|
10067
10538
|
if self.active_array is None and self.active_res2d is None:
|
10068
10539
|
logging.warning(_('No active array or result 2D to select node by node !'))
|