wolfhece 2.2.28__py3-none-any.whl → 2.2.30__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/PyConfig.py +27 -3
- wolfhece/PyCrosssections.py +36 -33
- wolfhece/PyDraw.py +204 -20
- wolfhece/PyVertexvectors.py +417 -121
- wolfhece/PyWMS.py +6 -3
- wolfhece/__init__.py +27 -0
- wolfhece/acceptability/acceptability.py +25 -20
- wolfhece/acceptability/acceptability_gui.py +150 -92
- wolfhece/acceptability/func.py +169 -82
- wolfhece/apps/version.py +1 -1
- wolfhece/irm_qdf.py +71 -7
- wolfhece/lb7208_ntv2/__init__.py +0 -0
- wolfhece/lb7208_ntv2/be_ign_README.txt +36 -0
- wolfhece/lb7208_ntv2/be_ign_bd72lb72_etrs89lb08.tif +0 -0
- wolfhece/lb7208_ntv2/be_ign_hBG18.tif +0 -0
- wolfhece/mesh2d/gpu_2d.py +11 -2
- wolfhece/pyshields.py +166 -105
- wolfhece/report/compare_arrays.py +268 -58
- wolfhece/report/simplesimgpu.py +25 -6
- wolfhece/scenario/config_manager.py +243 -7
- wolfhece/ui/wolf_multiselection_collapsiblepane.py +153 -1
- wolfhece/wolf_array.py +67 -62
- wolfhece/wolf_texture.py +4 -0
- {wolfhece-2.2.28.dist-info → wolfhece-2.2.30.dist-info}/METADATA +1 -1
- {wolfhece-2.2.28.dist-info → wolfhece-2.2.30.dist-info}/RECORD +28 -24
- {wolfhece-2.2.28.dist-info → wolfhece-2.2.30.dist-info}/WHEEL +0 -0
- {wolfhece-2.2.28.dist-info → wolfhece-2.2.30.dist-info}/entry_points.txt +0 -0
- {wolfhece-2.2.28.dist-info → wolfhece-2.2.30.dist-info}/top_level.txt +0 -0
@@ -110,6 +110,8 @@ class GPU_2D_file(Enum):
|
|
110
110
|
MANNING = _gpu_file('manning' , np.float32, GPU_2D_file_extensions.NPY.value)
|
111
111
|
COMPUTATION_MASK = _gpu_file('nap' , np.uint8 , GPU_2D_file_extensions.NPY.value)
|
112
112
|
INFILTRATION = _gpu_file('infiltration_zones', np.int32, GPU_2D_file_extensions.NPY.value)
|
113
|
+
ROOF = _gpu_file('bridge_roof' , np.float32, GPU_2D_file_extensions.NPY.value)
|
114
|
+
# DECK = _gpu_file('bridge_deck' , np.float32, GPU_2D_file_extensions.NPY.value)
|
113
115
|
|
114
116
|
# répertoire de sortie des simulations GPU
|
115
117
|
RESULT_DIR = 'simul_gpu_results'
|
@@ -240,6 +242,8 @@ class Config_Manager_2D_GPU:
|
|
240
242
|
self._epsilon = 0.01
|
241
243
|
self._filter_independent = True
|
242
244
|
|
245
|
+
self._active_simulation = None
|
246
|
+
|
243
247
|
self.load_data()
|
244
248
|
|
245
249
|
def find_wolfgpu(self):
|
@@ -559,15 +563,172 @@ class Config_Manager_2D_GPU:
|
|
559
563
|
|
560
564
|
logging.info(_('Hydrographs...'))
|
561
565
|
hydro = self.get_hydrographs()
|
562
|
-
|
566
|
+
if len(hydro) == 0:
|
567
|
+
logging.info(_('No hydrographs found !'))
|
568
|
+
log += _('No hydrographs found !') + '\n'
|
569
|
+
else:
|
570
|
+
try:
|
571
|
+
nb = hydro[0].data.shape[1]
|
572
|
+
|
573
|
+
logging.info(_('Number of hydrographs : {}'.format(len(hydro))))
|
574
|
+
for curhydro in hydro:
|
575
|
+
if curhydro.data.shape[1] != nb:
|
576
|
+
loclog = _('Bad number of columns for {} !'.format(curhydro[0]._filename))
|
577
|
+
log += loclog + '\n'
|
578
|
+
logging.warning(loclog)
|
579
|
+
except Exception as e:
|
580
|
+
logging.error(_('Error while checking hydrographs: {}').format(e))
|
581
|
+
log += _('Error while checking hydrographs: {}').format(e) + '\n'
|
582
|
+
|
583
|
+
return log
|
584
|
+
|
585
|
+
def check_one_simulation(self) -> str:
|
586
|
+
"""
|
587
|
+
Check consistency of one simulation
|
588
|
+
|
589
|
+
"""
|
590
|
+
|
591
|
+
if self._active_simulation is None:
|
592
|
+
logging.error(_('No active simulation !'))
|
593
|
+
return _('No active simulation !')
|
594
|
+
|
595
|
+
logging.info(_('Checking consistency of one simulation...\n'))
|
596
|
+
|
597
|
+
logging.info(_('NPY files...'))
|
598
|
+
numpyfiles = self._active_simulation[GPU_2D_file_extensions.NPY.value]
|
599
|
+
numpynames = [file.name.lower() for file in numpyfiles]
|
600
|
+
|
601
|
+
logging.info(_('Number of numpy files : {}'.format(len(numpyfiles))))
|
602
|
+
|
603
|
+
if self._header.nbx == 0 or self._header.nby == 0:
|
604
|
+
logging.error(_('No header found !'))
|
605
|
+
logging.info(_('Trying to get header from first numpy file...'))
|
606
|
+
try:
|
607
|
+
wa = WolfArray(numpyfiles[0])
|
608
|
+
self._header = wa.get_header()
|
609
|
+
except Exception as e:
|
610
|
+
logging.error(_('Error while getting header from first numpy file: {}').format(e))
|
611
|
+
return _('Error while getting header from first numpy file: {}').format(e)
|
612
|
+
|
613
|
+
log = ''
|
614
|
+
for curnpy in numpyfiles:
|
615
|
+
|
616
|
+
# test if the shape of the numpy file is the same as the tif file
|
617
|
+
# using memmap to avoid loading the whole array in memory -> faster
|
618
|
+
arr = np.lib.format.open_memmap(curnpy, mode='r')
|
563
619
|
|
564
|
-
|
565
|
-
|
566
|
-
if curhydro.data.shape[1] != nb:
|
567
|
-
loclog = _('Bad number of columns for {} !'.format(curhydro[0]._filename))
|
620
|
+
if arr.shape != (self._header.nbx, self._header.nby):
|
621
|
+
loclog = _('Bad shape for {} !'.format(curnpy))
|
568
622
|
log += loclog + '\n'
|
569
623
|
logging.warning(loclog)
|
570
624
|
|
625
|
+
del(arr)
|
626
|
+
|
627
|
+
logging.info(_('Hydrographs...'))
|
628
|
+
hydro = self.get_hydrographs()
|
629
|
+
if len(hydro) == 0:
|
630
|
+
logging.info(_('No hydrographs found !'))
|
631
|
+
log += _('No hydrographs found !') + '\n'
|
632
|
+
else:
|
633
|
+
try:
|
634
|
+
nb = hydro[0].data.shape[1]
|
635
|
+
|
636
|
+
logging.info(_('Number of hydrographs : {}'.format(len(hydro))))
|
637
|
+
for curhydro in hydro:
|
638
|
+
if curhydro.data.shape[1] != nb:
|
639
|
+
loclog = _('Bad number of columns for {} !'.format(curhydro[0]._filename))
|
640
|
+
log += loclog + '\n'
|
641
|
+
logging.warning(loclog)
|
642
|
+
except Exception as e:
|
643
|
+
logging.error(_('Error while checking hydrographs: {}').format(e))
|
644
|
+
log += _('Error while checking hydrographs: {}').format(e) + '\n'
|
645
|
+
|
646
|
+
for curfile in GPU_2D_file:
|
647
|
+
if curfile.value.extension == '.npy':
|
648
|
+
if curfile.value.name + curfile.value.extension not in numpynames:
|
649
|
+
loclog = _('Missing file {} !').format(curfile.value.name + curfile.value.extension)
|
650
|
+
log += loclog + '\n'
|
651
|
+
logging.warning(loclog)
|
652
|
+
else:
|
653
|
+
try:
|
654
|
+
wa = WolfArray(numpyfiles[numpynames.index(curfile.value.name + curfile.value.extension)])
|
655
|
+
if wa.dtype != curfile.value.type:
|
656
|
+
loclog = _('Bad dtype for {} ! Expected {}, got {}').format(
|
657
|
+
curfile.value.name + curfile.value.extension,
|
658
|
+
curfile.value.type, wa.dtype)
|
659
|
+
log += loclog + '\n'
|
660
|
+
logging.warning(loclog)
|
661
|
+
del(wa)
|
662
|
+
except Exception as e:
|
663
|
+
loclog = _('Error while checking {}: {}').format(
|
664
|
+
curfile.value.name + curfile.value.extension, e)
|
665
|
+
log += loclog + '\n'
|
666
|
+
logging.error(loclog)
|
667
|
+
|
668
|
+
if 'nap.npy' in numpynames:
|
669
|
+
nap = WolfArray(numpyfiles[numpynames.index('nap.npy')])
|
670
|
+
else:
|
671
|
+
nap = None
|
672
|
+
logging.error(_('No nap file found !'))
|
673
|
+
log += _('No nap file found !') + '\n'
|
674
|
+
|
675
|
+
if nap is not None:
|
676
|
+
if 'infiltration_zones.npy' in numpynames:
|
677
|
+
# Check if infiltration zones are consistent
|
678
|
+
infil_zones = WolfArray(numpyfiles[numpynames.index('infiltration_zones.npy')])
|
679
|
+
|
680
|
+
if np.any(infil_zones.array[nap.array == 0] != 0):
|
681
|
+
loclog = _('Infiltration zones are not consistent with the nap file !')
|
682
|
+
log += loclog + '\n'
|
683
|
+
|
684
|
+
# find all non zero infiltration zones
|
685
|
+
non_zero_infil_zones = list(set(np.unique(infil_zones.array[nap.array == 1])))
|
686
|
+
if len(non_zero_infil_zones) == 0:
|
687
|
+
loclog = _('No infiltration zones found !')
|
688
|
+
log += loclog + '\n'
|
689
|
+
else:
|
690
|
+
if non_zero_infil_zones[0] == 0:
|
691
|
+
#pop
|
692
|
+
non_zero_infil_zones.pop(0)
|
693
|
+
if len(non_zero_infil_zones) == 0:
|
694
|
+
loclog = _('No infiltration zones found !')
|
695
|
+
log += loclog + '\n'
|
696
|
+
|
697
|
+
elif non_zero_infil_zones[0] !=1:
|
698
|
+
loclog = _('Infiltration zones should start at 1 ! Found {} instead.').format(non_zero_infil_zones[0])
|
699
|
+
log += loclog + '\n'
|
700
|
+
logging.warning(loclog)
|
701
|
+
|
702
|
+
# increments
|
703
|
+
if not all([non_zero_infil_zones[i] - non_zero_infil_zones[i-1] == 1 for i in range(1, len(non_zero_infil_zones))]):
|
704
|
+
loclog = _('Infiltration zones are not consecutive !')
|
705
|
+
log += loclog + '\n'
|
706
|
+
logging.warning(loclog)
|
707
|
+
del(infil_zones)
|
708
|
+
|
709
|
+
if 'bathymetry.npy' in numpynames:
|
710
|
+
# Check if infiltration zones are consistent
|
711
|
+
bath = WolfArray(numpyfiles[numpynames.index('bathymetry.npy')])
|
712
|
+
|
713
|
+
if np.any(bath.array[nap.array == 0] != 99999.):
|
714
|
+
loclog = _("Some bathymetry's cells are different of 99999 outside the computation domain !\n")
|
715
|
+
loclog += _('This may lead to unexpected results !')
|
716
|
+
log += loclog + '\n'
|
717
|
+
|
718
|
+
del(bath)
|
719
|
+
|
720
|
+
for file in ['h.npy', 'qx.npy', 'qy.npy']:
|
721
|
+
if file in numpynames:
|
722
|
+
# Check if infiltration zones are consistent
|
723
|
+
bath = WolfArray(numpyfiles[numpynames.index(file)])
|
724
|
+
|
725
|
+
if np.any(bath.array[nap.array == 0] != 0.):
|
726
|
+
loclog = _("Some cells are different of 0.0 outside the computation domain in {}!\n").format(file)
|
727
|
+
loclog += _('This may lead to unexpected results !')
|
728
|
+
log += loclog + '\n'
|
729
|
+
|
730
|
+
del(bath)
|
731
|
+
|
571
732
|
return log
|
572
733
|
|
573
734
|
# Analyze files
|
@@ -1188,6 +1349,22 @@ class Config_Manager_2D_GPU:
|
|
1188
1349
|
else:
|
1189
1350
|
logging.error(_("No 'bathymetry.tif' file found in the root directory !"))
|
1190
1351
|
|
1352
|
+
def create_void_dtm(self):
|
1353
|
+
""" create void dtm file """
|
1354
|
+
if (self.workingdir / 'bathymetry.tif').exists():
|
1355
|
+
locheader = self.get_header()
|
1356
|
+
dtm = WolfArray(srcheader=locheader, whichtype= WOLF_ARRAY_FULL_SINGLE)
|
1357
|
+
dtm.array.data[:,:] = 99999.
|
1358
|
+
dtm.nullvalue = 99999.
|
1359
|
+
dtm.write_all(str(self.workingdir / 'dtm.tif'))
|
1360
|
+
|
1361
|
+
if (self.workingdir / 'dtm.tif').exists():
|
1362
|
+
logging.info(_('dtm.tif created and set to 99999. ! -- Please edit it !'))
|
1363
|
+
else:
|
1364
|
+
logging.error(_("dtm.tif not created ! -- Does 'bathymetry.tif' or any '.tif' file exist in the root directory ?"))
|
1365
|
+
else:
|
1366
|
+
logging.error(_("No 'bathymetry.tif' file found in the root directory !"))
|
1367
|
+
|
1191
1368
|
def create_void_roof(self):
|
1192
1369
|
""" create void roof file """
|
1193
1370
|
|
@@ -1774,10 +1951,18 @@ class UI_Manager_2D_GPU():
|
|
1774
1951
|
self._reload.Bind(wx.EVT_BUTTON,self.onupdate_structure)
|
1775
1952
|
self._reload.SetToolTip(_('reScan the directory and reload the entire structure'))
|
1776
1953
|
|
1954
|
+
tif_sizer = wx.BoxSizer(wx.HORIZONTAL)
|
1777
1955
|
self._create_void_infil = wx.Button(self._frame,label = _('Create .tif infiltration zones'))
|
1778
1956
|
self._create_void_infil.Bind(wx.EVT_BUTTON,self.oncreate_void_infil)
|
1779
1957
|
self._create_void_infil.SetToolTip(_('Create a void infiltration zones file based on bathymetry.tif'))
|
1780
1958
|
|
1959
|
+
self._create_dtm = wx.Button(self._frame,label = _('Create .tif DTM'))
|
1960
|
+
self._create_dtm.Bind(wx.EVT_BUTTON,self.oncreate_dtm)
|
1961
|
+
self._create_dtm.SetToolTip(_('Create a DTM file based on bathymetry.tif\n\n - bathymetry.tif must be present in the root directory'))
|
1962
|
+
|
1963
|
+
tif_sizer.Add(self._create_void_infil, 1, wx.EXPAND)
|
1964
|
+
tif_sizer.Add(self._create_dtm, 1, wx.EXPAND)
|
1965
|
+
|
1781
1966
|
bridge_sizer = wx.BoxSizer(wx.HORIZONTAL)
|
1782
1967
|
self._create_void_roof = wx.Button(self._frame,label = _('Create .tif bridge/culvert roof elevation'))
|
1783
1968
|
self._create_void_roof.Bind(wx.EVT_BUTTON,self.oncreate_void_roof)
|
@@ -1818,6 +2003,10 @@ class UI_Manager_2D_GPU():
|
|
1818
2003
|
self._checkconsistency.Bind(wx.EVT_BUTTON,self.oncheck_consistency)
|
1819
2004
|
self._checkconsistency.SetToolTip(_('Check consistency of the scenario\n\n - bathymetry.tif\n - manning.tif\n - infiltration.tif\n - hydrographs\n - initial conditions\n - boundary conditions\n - scripts'))
|
1820
2005
|
|
2006
|
+
self._checkonesimulation = wx.Button(self._frame,label = _('Check one simulation'))
|
2007
|
+
self._checkonesimulation.Bind(wx.EVT_BUTTON,self.oncheck_one_simulation)
|
2008
|
+
self._checkonesimulation.SetToolTip(_('Check consistency of one simulation'))
|
2009
|
+
|
1821
2010
|
self._createsim = wx.Button(self._frame,label = _('Create simulation(s)'))
|
1822
2011
|
self._createsim.Bind(wx.EVT_BUTTON,self.oncreate_simulation)
|
1823
2012
|
self._createsim.SetToolTip(_('Create simulation(s) from selected hydrographs'))
|
@@ -1861,14 +2050,19 @@ class UI_Manager_2D_GPU():
|
|
1861
2050
|
|
1862
2051
|
# buttons -> sizer
|
1863
2052
|
sizer_buttons.Add(self._reload,1,wx.EXPAND)
|
1864
|
-
sizer_buttons.Add(
|
2053
|
+
sizer_buttons.Add(tif_sizer,1,wx.EXPAND)
|
1865
2054
|
sizer_buttons.Add(bridge_sizer,1,wx.EXPAND)
|
1866
2055
|
sizer_buttons.Add(self._create_void_scripts,1,wx.EXPAND)
|
1867
2056
|
sizer_buttons.Add(self._check_prefix,1,wx.EXPAND)
|
1868
2057
|
sizer_buttons.Add(self._create_vrt,1,wx.EXPAND)
|
1869
2058
|
sizer_buttons.Add(self._translate_vrt,1,wx.EXPAND)
|
1870
2059
|
sizer_buttons.Add(self._apply_scripts,1,wx.EXPAND)
|
1871
|
-
|
2060
|
+
|
2061
|
+
_sizer_check = wx.BoxSizer(wx.HORIZONTAL)
|
2062
|
+
_sizer_check.Add(self._checkconsistency, 1, wx.EXPAND)
|
2063
|
+
_sizer_check.Add(self._checkonesimulation, 1, wx.EXPAND)
|
2064
|
+
|
2065
|
+
sizer_buttons.Add(_sizer_check,1,wx.EXPAND)
|
1872
2066
|
sizer_buttons.Add(self._create_vec,1,wx.EXPAND)
|
1873
2067
|
sizer_buttons.Add(self.listsims,1,wx.EXPAND)
|
1874
2068
|
sizer_buttons.Add(self._createsim,1,wx.EXPAND)
|
@@ -1931,6 +2125,12 @@ class UI_Manager_2D_GPU():
|
|
1931
2125
|
self._parent.create_void_infil()
|
1932
2126
|
self.reload()
|
1933
2127
|
|
2128
|
+
def oncreate_dtm(self, e:wx.MouseEvent):
|
2129
|
+
""" Création d'un fichier DTM vide """
|
2130
|
+
|
2131
|
+
self._parent.create_void_dtm()
|
2132
|
+
self.reload()
|
2133
|
+
|
1934
2134
|
def oncreate_void_roof(self, e:wx.MouseEvent):
|
1935
2135
|
""" Création d'un fichier de toit de pont vide """
|
1936
2136
|
|
@@ -2122,6 +2322,40 @@ class UI_Manager_2D_GPU():
|
|
2122
2322
|
else:
|
2123
2323
|
self._txtctrl.WriteText(log)
|
2124
2324
|
|
2325
|
+
def oncheck_one_simulation(self, e:wx.MouseEvent):
|
2326
|
+
""" Vérification de la cohérence d'une simulation
|
2327
|
+
"""
|
2328
|
+
self._txtctrl.Clear()
|
2329
|
+
log = self._parent.check_one_simulation()
|
2330
|
+
if log == '':
|
2331
|
+
self._txtctrl.WriteText("\n\n".join([_("All seems fine !")]))
|
2332
|
+
else:
|
2333
|
+
self._txtctrl.WriteText("\n\n".join([log]))
|
2334
|
+
|
2335
|
+
# Info on Python Environment and wolfgpu Path and version
|
2336
|
+
# -------------------------------------------------------
|
2337
|
+
|
2338
|
+
import sys
|
2339
|
+
# Python Environment
|
2340
|
+
self._txtctrl.write(_('\nPython Environment\n'))
|
2341
|
+
self._txtctrl.write('-------------------\n')
|
2342
|
+
self._txtctrl.write('Python version : {}\n'.format(sys.version))
|
2343
|
+
self._txtctrl.write('Python path : {}\n'.format(sys.executable))
|
2344
|
+
self._txtctrl.write('Python version info : {}\n'.format(sys.version_info))
|
2345
|
+
|
2346
|
+
# Test if wolfgpu.exe exists in script directory
|
2347
|
+
# wolfgpu Path and version
|
2348
|
+
self._txtctrl.write('\nWolfgpu Path and version\n')
|
2349
|
+
self._txtctrl.write('------------------------\n')
|
2350
|
+
|
2351
|
+
wolfgpu = self._parent.wolfgpu
|
2352
|
+
if wolfgpu.exists():
|
2353
|
+
self._txtctrl.write('Wolfgpu.exe found in : {}\n'.format(self._parent.wolfgpu.parent))
|
2354
|
+
else:
|
2355
|
+
self._txtctrl.write('Wolfgpu.exe not found !\n')
|
2356
|
+
self._parent.wolfgpu = None
|
2357
|
+
|
2358
|
+
|
2125
2359
|
def oncheck_consistency(self,e:wx.MouseEvent):
|
2126
2360
|
""" Vérification de la cohérence des fichiers """
|
2127
2361
|
|
@@ -2422,10 +2656,12 @@ class UI_Manager_2D_GPU():
|
|
2422
2656
|
self._txtctrl.SetBackgroundColour(wx.WHITE)
|
2423
2657
|
self._txtctrl.SetForegroundColour(wx.BLACK)
|
2424
2658
|
|
2659
|
+
self._parent._active_simulation = None
|
2425
2660
|
if isinstance(mydata, dict):
|
2426
2661
|
self._txtctrl.write(_('Yous have selected : {}\n\n'.format(str(mydata['path']))))
|
2427
2662
|
|
2428
2663
|
if mydata[IS_SIMUL]:
|
2664
|
+
self._parent._active_simulation = mydata
|
2429
2665
|
self._txtctrl.write(_('GPU SIMULATION\n\n'))
|
2430
2666
|
|
2431
2667
|
if ctrl and not shift and not alt:
|
@@ -211,6 +211,8 @@ class Wolf_MultipleSelection(wx.Dialog):
|
|
211
211
|
assert len(self.delete_if_transfer) == len(values_dict), "delete_if_transfer must be a list of len(values_dict)"
|
212
212
|
for i, values in enumerate(values_dict.values()):
|
213
213
|
assert isinstance(self.delete_if_transfer[i], bool), "delete_if_transfer must be a list of boolean"
|
214
|
+
else:
|
215
|
+
self.delete_if_transfer = None
|
214
216
|
|
215
217
|
super().__init__(parent, title=title)
|
216
218
|
|
@@ -339,6 +341,145 @@ class Wolf_MultipleSelection(wx.Dialog):
|
|
339
341
|
if self.callback is not None:
|
340
342
|
self.callback(self)
|
341
343
|
|
344
|
+
class Wolf_CompareArrays_Selection(Wolf_MultipleSelection):
|
345
|
+
"""
|
346
|
+
Dialog with multiple 'collapsiblepanes' containing 2 lists to select multiple items
|
347
|
+
This class is a specific case of Wolf_MultipleSelection for comparing arrays
|
348
|
+
"""
|
349
|
+
def __init__(self,
|
350
|
+
parent,
|
351
|
+
title,
|
352
|
+
values_dict:dict,
|
353
|
+
callback = None,
|
354
|
+
info:str='',
|
355
|
+
cmdApply:bool=False,
|
356
|
+
styles = wx.LB_EXTENDED,
|
357
|
+
destroyOK = False,
|
358
|
+
**kwargs):
|
359
|
+
"""
|
360
|
+
:param parent : wx.Window
|
361
|
+
:param title : str - title of the frame
|
362
|
+
:param values_dict : dict - {'label1':[item1, item2, ...], 'label2':[item1, item2, ...], ...}
|
363
|
+
:param callback : function - callback function when OK or Apply button is pressed
|
364
|
+
:param info : str - information to display upper the collapsiblepanes
|
365
|
+
:param cmdApply : bool - if True, Apply button is displayed
|
366
|
+
:param styles : wx.ListBox styles - wx constant or list of wx constants
|
367
|
+
:param kwargs : dict - other arguments for wx.Frame (example : max_selected_items=[1, 2, 3], delete_if_transfer=[True, False, True])
|
368
|
+
"""
|
369
|
+
super().__init__(parent=parent,
|
370
|
+
title=title,
|
371
|
+
values_dict=values_dict,
|
372
|
+
callback=callback,
|
373
|
+
info=info,
|
374
|
+
cmdApply=cmdApply,
|
375
|
+
styles=styles,
|
376
|
+
destroyOK=destroyOK,
|
377
|
+
max_selected_items=[1]*len(values_dict),
|
378
|
+
delete_if_transfer=[True]*len(values_dict),
|
379
|
+
**kwargs)
|
380
|
+
|
381
|
+
# add some UI specific to the compare arrays selection
|
382
|
+
|
383
|
+
# textbox for a threshold value
|
384
|
+
self.threshold_label = wx.StaticText(self, label="Threshold value [m]:")
|
385
|
+
self.threshold_value = wx.TextCtrl(self, value="0.01", style=wx.TE_PROCESS_ENTER | wx.TE_CENTER)
|
386
|
+
self.threshold_value.Bind(wx.EVT_TEXT_ENTER, self._on_threshold_enter)
|
387
|
+
self.threshold_value.Bind(wx.EVT_KILL_FOCUS, self._on_threshold_enter)
|
388
|
+
self.threshold_value.SetToolTip("Enter a threshold value - All differences below this threshold will be considered as equal")
|
389
|
+
# add the threshold label and value to the sizer
|
390
|
+
sizer = self.GetSizer()
|
391
|
+
|
392
|
+
sizer_threshold = wx.BoxSizer(wx.HORIZONTAL)
|
393
|
+
sizer_threshold.Add(self.threshold_label, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
|
394
|
+
sizer_threshold.Add(self.threshold_value, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
|
395
|
+
sizer.Add(sizer_threshold, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
|
396
|
+
|
397
|
+
# textbox for a minimal area value
|
398
|
+
self.min_area_label = wx.StaticText(self, label="Minimal area value [m²]:")
|
399
|
+
self.min_area_value = wx.TextCtrl(self, value="2.0", style=wx.TE_PROCESS_ENTER | wx.TE_CENTER)
|
400
|
+
self.min_area_value.Bind(wx.EVT_TEXT_ENTER, self._on_min_area_enter)
|
401
|
+
self.min_area_value.Bind(wx.EVT_KILL_FOCUS, self._on_min_area_enter)
|
402
|
+
self.min_area_value.SetToolTip("Enter a minimal area value - All patches below this area will be ignored")
|
403
|
+
# add the minimal area label and value to the sizer
|
404
|
+
sizer_min_area = wx.BoxSizer(wx.HORIZONTAL)
|
405
|
+
sizer_min_area.Add(self.min_area_label, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
|
406
|
+
sizer_min_area.Add(self.min_area_value, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
|
407
|
+
sizer.Add(sizer_min_area, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
|
408
|
+
# Maximum patches to include in the report
|
409
|
+
self.max_patches_label = wx.StaticText(self, label="Maximum patches to include in the report:")
|
410
|
+
self.max_patches_value = wx.TextCtrl(self, value="10", style=wx.TE_PROCESS_ENTER | wx.TE_CENTER)
|
411
|
+
self.max_patches_value.Bind(wx.EVT_TEXT_ENTER, self._on_max_patches_enter)
|
412
|
+
self.max_patches_value.Bind(wx.EVT_KILL_FOCUS, self._on_max_patches_enter)
|
413
|
+
self.max_patches_value.SetToolTip("Enter a maximum number of patches to include in the report - If more patches are found, only the first ones will be included")
|
414
|
+
# add the maximum patches label and value to the sizer
|
415
|
+
sizer_max_patches = wx.BoxSizer(wx.HORIZONTAL)
|
416
|
+
sizer_max_patches.Add(self.max_patches_label, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
|
417
|
+
sizer_max_patches.Add(self.max_patches_value, proportion=1, flag= wx.EXPAND | wx.ALL, border=5)
|
418
|
+
sizer.Add(sizer_max_patches, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
|
419
|
+
# add the sizer to the main sizer
|
420
|
+
self.SetSizer(sizer)
|
421
|
+
self.Fit()
|
422
|
+
self.Layout()
|
423
|
+
|
424
|
+
|
425
|
+
def _on_threshold_enter(self, event):
|
426
|
+
""" Callback when the threshold value is changed """
|
427
|
+
try:
|
428
|
+
value = float(self.threshold_value.GetValue())
|
429
|
+
if value < 0:
|
430
|
+
self.threshold_value.SetValue("0.01")
|
431
|
+
except ValueError as e:
|
432
|
+
wx.MessageBox(f"Invalid threshold value: {e}", "Error", wx.OK | wx.ICON_ERROR)
|
433
|
+
self.threshold_value.SetValue("0.01")
|
434
|
+
event.Skip()
|
435
|
+
|
436
|
+
def _on_min_area_enter(self, event):
|
437
|
+
""" Callback when the minimal area value is changed """
|
438
|
+
try:
|
439
|
+
value = float(self.min_area_value.GetValue())
|
440
|
+
if value < 0:
|
441
|
+
self.min_area_value.SetValue("2.0")
|
442
|
+
except ValueError as e:
|
443
|
+
wx.MessageBox(f"Invalid minimal area value: {e}", "Error", wx.OK | wx.ICON_ERROR)
|
444
|
+
self.min_area_value.SetValue("2.0")
|
445
|
+
event.Skip()
|
446
|
+
|
447
|
+
def _on_max_patches_enter(self, event):
|
448
|
+
""" Callback when the maximum patches value is changed """
|
449
|
+
try:
|
450
|
+
value = int(self.max_patches_value.GetValue())
|
451
|
+
if value < 1:
|
452
|
+
self.max_patches_value.SetValue("10")
|
453
|
+
except ValueError as e:
|
454
|
+
wx.MessageBox(f"Invalid maximum patches value: {e}", "Error", wx.OK | wx.ICON_ERROR)
|
455
|
+
self.max_patches_value.SetValue("10")
|
456
|
+
event.Skip()
|
457
|
+
|
458
|
+
def get_threshold(self):
|
459
|
+
""" Get the threshold value """
|
460
|
+
try:
|
461
|
+
return float(self.threshold_value.GetValue())
|
462
|
+
except ValueError:
|
463
|
+
wx.MessageBox("Invalid threshold value", "Error", wx.OK | wx.ICON_ERROR)
|
464
|
+
return 0.01
|
465
|
+
|
466
|
+
def get_min_area(self):
|
467
|
+
""" Get the minimal area value """
|
468
|
+
try:
|
469
|
+
return float(self.min_area_value.GetValue())
|
470
|
+
except ValueError:
|
471
|
+
wx.MessageBox("Invalid minimal area value", "Error", wx.OK | wx.ICON_ERROR)
|
472
|
+
return 2.0
|
473
|
+
|
474
|
+
def get_max_patches(self):
|
475
|
+
""" Get the maximum patches value """
|
476
|
+
try:
|
477
|
+
return int(self.max_patches_value.GetValue())
|
478
|
+
except ValueError:
|
479
|
+
wx.MessageBox("Invalid maximum patches value", "Error", wx.OK | wx.ICON_ERROR)
|
480
|
+
return 10
|
481
|
+
|
482
|
+
|
342
483
|
if __name__ == "__main__":
|
343
484
|
# Utilisation de la classe Wolf_MultipleSelection
|
344
485
|
app = wx.App()
|
@@ -351,6 +492,17 @@ if __name__ == "__main__":
|
|
351
492
|
callback=None,
|
352
493
|
styles=[wx.LB_SINGLE, wx.LB_EXTENDED, wx.LB_EXTENDED],
|
353
494
|
max_selected_items=[1, -1, -1],)
|
354
|
-
|
495
|
+
|
496
|
+
fram2 = Wolf_CompareArrays_Selection(None,
|
497
|
+
title="Exemple de Wolf_CompareArrays_Selection",
|
498
|
+
values_dict={'domain':["Item 1", "Item 2", "Item 3", "Item 4"],
|
499
|
+
'u':["Item 3", "Item 4", "Item 5", "Item 6"],
|
500
|
+
'v':["Item v1", "Item v2", "Item v3", "Item v4"]},
|
501
|
+
info="You can define : \n - the domain\n - u\n -v",
|
502
|
+
callback=None,
|
503
|
+
styles=[wx.LB_SINGLE, wx.LB_SINGLE, wx.LB_SINGLE],
|
504
|
+
destroyOK=True)
|
505
|
+
|
506
|
+
fram2.ShowModal()
|
355
507
|
pass
|
356
508
|
app.MainLoop()
|
wolfhece/wolf_array.py
CHANGED
@@ -3953,6 +3953,10 @@ class SelectionData():
|
|
3953
3953
|
def get_script(self, which:int = None) -> str:
|
3954
3954
|
""" Get script of the current selection or of a stored one """
|
3955
3955
|
|
3956
|
+
if self.myselection == 'all':
|
3957
|
+
logging.error(_('Cannot create script for "all" selection'))
|
3958
|
+
return ''
|
3959
|
+
|
3956
3960
|
txt = '# script adapted to a WolfGPU script\n'
|
3957
3961
|
txt += '# - (i,j) are 1-based for add_boundary_condition -- Do not forget to adapt BC type, value and direction or use BC Manager\n'
|
3958
3962
|
txt += '# - (i,j) are 0-based for infiltration zones\n\n'
|
@@ -5779,63 +5783,6 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
5779
5783
|
if mapviewer is not None:
|
5780
5784
|
mapviewer.add_object('array', newobj = newarray, ToCheck = True, id = self.idx + '_extracted')
|
5781
5785
|
|
5782
|
-
def crop_array(self, bbox:list[list[float],list[float]], setnull_trx_try:bool = False) -> "WolfArray":
|
5783
|
-
""" Crop the data based on the bounding box.
|
5784
|
-
|
5785
|
-
Beware of the grid:
|
5786
|
-
- If the cropped region is smaller than a cell, then the cropped array
|
5787
|
-
will be empty.
|
5788
|
-
- If the cropped region doesn't align with the source array grid, it
|
5789
|
-
will be forced to do so.
|
5790
|
-
|
5791
|
-
:param bbox: bounding box [[xmin, xmax], [ymin, ymax]].
|
5792
|
-
:param setnull_trx_try: set the translation to 0 if True, origx and
|
5793
|
-
origy will be set to the lower left corner of the bbox. Default is
|
5794
|
-
`False`.
|
5795
|
-
"""
|
5796
|
-
|
5797
|
-
xmin, xmax = bbox[0]
|
5798
|
-
ymin, ymax = bbox[1]
|
5799
|
-
|
5800
|
-
# Make sure the bounding box can be used.
|
5801
|
-
if xmin > xmax:
|
5802
|
-
xmin, xmax = xmax, xmin
|
5803
|
-
if ymin > ymax:
|
5804
|
-
ymin, ymax = ymax, ymin
|
5805
|
-
|
5806
|
-
imin, jmin = self.get_ij_from_xy(xmin, ymin)
|
5807
|
-
imax, jmax = self.get_ij_from_xy(xmax, ymax)
|
5808
|
-
|
5809
|
-
imin = int(imin)
|
5810
|
-
jmin = int(jmin)
|
5811
|
-
imax = int(imax)
|
5812
|
-
jmax = int(jmax)
|
5813
|
-
|
5814
|
-
newheader = header_wolf()
|
5815
|
-
newheader.nbx = imax-imin
|
5816
|
-
newheader.nby = jmax-jmin
|
5817
|
-
newheader.dx = self.dx
|
5818
|
-
newheader.dy = self.dy
|
5819
|
-
newheader.origx, newheader.origy = self.get_xy_from_ij(imin, jmin, abs = setnull_trx_try)
|
5820
|
-
newheader.origx -= self.dx / 2.
|
5821
|
-
newheader.origy -= self.dy / 2.
|
5822
|
-
newheader.translx = self.translx
|
5823
|
-
newheader.transly = self.transly
|
5824
|
-
|
5825
|
-
if setnull_trx_try:
|
5826
|
-
newheader.translx = 0.
|
5827
|
-
newheader.transly = 0.
|
5828
|
-
|
5829
|
-
newarray = WolfArray(srcheader=newheader)
|
5830
|
-
|
5831
|
-
if imin < imax and jmin < jmax:
|
5832
|
-
newarray.array[:,:] = self.array[imin:imax, jmin:jmax]
|
5833
|
-
else:
|
5834
|
-
# One of the dimensions has 0 size => the array is empty
|
5835
|
-
pass
|
5836
|
-
|
5837
|
-
return newarray
|
5838
|
-
|
5839
5786
|
def get_centers(self, usenap:bool = True):
|
5840
5787
|
""" Get the centers of the cells """
|
5841
5788
|
|
@@ -10023,12 +9970,67 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
10023
9970
|
newWolfArray.count()
|
10024
9971
|
return newWolfArray
|
10025
9972
|
|
10026
|
-
def
|
9973
|
+
def crop_array(self, bbox:list[list[float],list[float]], setnull_trx_try:bool = False) -> "WolfArray":
|
9974
|
+
""" Crop the data based on the bounding box.
|
9975
|
+
|
9976
|
+
Beware of the grid:
|
9977
|
+
- If the cropped region is smaller than a cell, then the cropped array
|
9978
|
+
will be empty.
|
9979
|
+
- If the cropped region doesn't align with the source array grid, it
|
9980
|
+
will be forced to do so.
|
9981
|
+
|
9982
|
+
:param bbox: bounding box [[xmin, xmax], [ymin, ymax]].
|
9983
|
+
:param setnull_trx_try: set the translation to 0 if True, origx and
|
9984
|
+
origy will be set to the lower left corner of the bbox. Default is
|
9985
|
+
`False`.
|
9986
|
+
"""
|
9987
|
+
|
9988
|
+
xmin, xmax = bbox[0]
|
9989
|
+
ymin, ymax = bbox[1]
|
9990
|
+
|
9991
|
+
# Make sure the bounding box can be used.
|
9992
|
+
if xmin > xmax:
|
9993
|
+
xmin, xmax = xmax, xmin
|
9994
|
+
if ymin > ymax:
|
9995
|
+
ymin, ymax = ymax, ymin
|
9996
|
+
|
9997
|
+
imin, jmin = self.get_ij_from_xy(xmin, ymin)
|
9998
|
+
imax, jmax = self.get_ij_from_xy(xmax, ymax)
|
9999
|
+
|
10000
|
+
imin = int(imin)
|
10001
|
+
jmin = int(jmin)
|
10002
|
+
imax = int(imax)
|
10003
|
+
jmax = int(jmax)
|
10004
|
+
|
10005
|
+
newheader = header_wolf()
|
10006
|
+
newheader.nbx = imax-imin
|
10007
|
+
newheader.nby = jmax-jmin
|
10008
|
+
newheader.dx = self.dx
|
10009
|
+
newheader.dy = self.dy
|
10010
|
+
newheader.origx, newheader.origy = self.get_xy_from_ij(imin, jmin, abs = setnull_trx_try)
|
10011
|
+
newheader.origx -= self.dx / 2.
|
10012
|
+
newheader.origy -= self.dy / 2.
|
10013
|
+
newheader.translx = self.translx
|
10014
|
+
newheader.transly = self.transly
|
10015
|
+
|
10016
|
+
if setnull_trx_try:
|
10017
|
+
newheader.translx = 0.
|
10018
|
+
newheader.transly = 0.
|
10019
|
+
|
10020
|
+
newarray = WolfArray(srcheader=newheader)
|
10027
10021
|
|
10022
|
+
if imin < imax and jmin < jmax:
|
10023
|
+
newarray.array[:,:] = self.array[imin:imax, jmin:jmax]
|
10024
|
+
else:
|
10025
|
+
# One of the dimensions has 0 size => the array is empty
|
10026
|
+
pass
|
10027
|
+
|
10028
|
+
return newarray
|
10029
|
+
|
10030
|
+
def crop_masked_at_edges(self):
|
10028
10031
|
"""
|
10029
10032
|
Crop the array to remove masked cells at the edges of the array
|
10030
10033
|
:return: cropped array, WolfArray instance
|
10031
|
-
|
10032
10034
|
"""
|
10033
10035
|
|
10034
10036
|
# Get max indexes
|
@@ -10083,9 +10085,9 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
10083
10085
|
newWolfArray.origz = self.origz + float(k_start) * self.dz
|
10084
10086
|
newWolfArray.translz = self.translz
|
10085
10087
|
|
10086
|
-
newWolfArray.array = self.array[i_start:i_start + nbx, j_start:j_start + nby, k_start:k_start + nbz]
|
10088
|
+
newWolfArray.array = self.array[i_start:i_start + nbx, j_start:j_start + nby, k_start:k_start + nbz].copy()
|
10087
10089
|
elif self.nbdims == 2:
|
10088
|
-
newWolfArray.array = self.array[i_start:i_start + nbx, j_start:j_start + nby]
|
10090
|
+
newWolfArray.array = self.array[i_start:i_start + nbx, j_start:j_start + nby].copy()
|
10089
10091
|
|
10090
10092
|
return newWolfArray
|
10091
10093
|
|
@@ -10343,7 +10345,10 @@ class WolfArray(Element_To_Draw, header_wolf):
|
|
10343
10345
|
self._ymax_plot = ymax
|
10344
10346
|
|
10345
10347
|
nbpix = min(sx * self.dx, sy * self.dy)
|
10346
|
-
if nbpix
|
10348
|
+
if nbpix == 0.:
|
10349
|
+
logging.warning(_('WolfArray.plot - No pixels to plot'))
|
10350
|
+
return
|
10351
|
+
elif nbpix >= 1.:
|
10347
10352
|
# si une maille est tracée sur au moins 2 pixels
|
10348
10353
|
curscale = 1
|
10349
10354
|
elif math.ceil(1. / nbpix) <= 3:
|