wolfhece 2.1.90__py3-none-any.whl → 2.1.93__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.
@@ -392,16 +392,25 @@ class Polygons_Analyze(Zones):
392
392
  self.linked:Union[dict,list] = None # type is depending on the type of linked arrays
393
393
  self.river_values:dict = None
394
394
 
395
+ # The riverbed axis is the second vector of the first zone
395
396
  self.riverbed = self.get_zone(0).myvectors[1]
396
397
  self.riverbed.prepare_shapely()
397
398
 
398
399
  self.polygons_zone:zone
399
400
  self.polygons_zone = self.get_zone(-1)
400
401
 
402
+ # The curvilinear distance of the polygons is stored in the 'z' attribute of the vertices
401
403
  self.polygons_curvi = {}
402
404
  for curvert in self.polygons_zone.myvectors:
403
405
  self.polygons_curvi[curvert.myname] = curvert.myvertices[0].z
404
406
 
407
+ # The mean center of the polygons
408
+ self.polygons_meanxy = {}
409
+ for curvert in self.polygons_zone.myvectors:
410
+ # Centre du polygone
411
+ centroid = curvert.asshapely_pol().centroid
412
+ self.polygons_meanxy[curvert.myname] = (centroid.x, centroid.y)
413
+
405
414
  for vec in self.polygons_zone.myvectors:
406
415
  vec.myprop.used=False # cache les polygones pour ne pas surcharger l'affichage éventuel
407
416
 
@@ -495,7 +504,9 @@ class Polygons_Analyze(Zones):
495
504
  locdict = self.river_values[curproj][curpoly][curgroup] = {}
496
505
 
497
506
  for cursim, curnparray in curarray.items():
498
- locdict[cursim] = np.array([np.array([ tuple(lst1), np.array(lst2, dtype= np.int32)], dtype=object ) for lst1, lst2 in curnparray], dtype=object)
507
+ vals = curnparray[0]
508
+ xy = curnparray[1]
509
+ locdict[cursim] = (np.array([np.array([ tuple(lst1), np.array(lst2, dtype= np.int32)], dtype=object ) for lst1, lst2 in vals], dtype=object), np.array(xy))
499
510
 
500
511
  elif isinstance(tmp_linked, list):
501
512
  self.linked = [(curlink[0], Wolfresults_2D if curlink[1] == 'CPU' else wolfres2DGPU) for curlink in tmp_linked]
@@ -508,7 +519,9 @@ class Polygons_Analyze(Zones):
508
519
  locdict = self.river_values[curpoly][curgroup] = {}
509
520
 
510
521
  for cursim, curnparray in curarray.items():
511
- locdict[cursim] = np.array([np.array([ tuple(lst1), np.array(lst2, dtype= np.int32)], dtype=object ) for lst1, lst2 in curnparray], dtype=object)
522
+ vals = curnparray[0]
523
+ xy = curnparray[1]
524
+ locdict[cursim] = (np.array([np.array([ tuple(lst1), np.array(lst2, dtype= np.int32)], dtype=object ) for lst1, lst2 in vals], dtype=object), np.array(xy))
512
525
 
513
526
 
514
527
  def compute_distance(self, poly:LineString | vector):
@@ -523,10 +536,8 @@ class Polygons_Analyze(Zones):
523
536
 
524
537
  for curvert in self.polygons_zone.myvectors:
525
538
  # Centre du polygone
526
- centerx = np.sum(np.asarray([cur.x for cur in curvert.myvertices[:4]]))/4.
527
- centery = np.sum(np.asarray([cur.y for cur in curvert.myvertices[:4]]))/4.
528
-
529
- self.polygons_curvi[curvert.myname] = poly.project(Point([centerx,centery]))
539
+ centroid = curvert.asshapely_pol().centroid
540
+ self.polygons_curvi[curvert.myname] = poly.project(Point([centroid.x, centroid.y]))
530
541
 
531
542
  def find_values_inside_parts(self, linked_arrays:Union[dict,list]):
532
543
  """
@@ -560,11 +571,11 @@ class Polygons_Analyze(Zones):
560
571
  if isinstance(linked_arrays, dict):
561
572
  self.river_values={}
562
573
  for curkey, curgroup in linked_arrays.items():
563
- self.river_values[curkey] = curzone.get_all_values_linked_polygon(curgroup, key_idx_names='name')
574
+ self.river_values[curkey] = curzone.get_all_values_linked_polygon(curgroup, key_idx_names='name', getxy=True)
564
575
 
565
576
  elif isinstance(linked_arrays, list):
566
577
 
567
- self.river_values = curzone.get_all_values_linked_polygon(linked_arrays, key_idx_names='name')
578
+ self.river_values = curzone.get_all_values_linked_polygon(linked_arrays, key_idx_names='name', getxy=True)
568
579
 
569
580
  def _get_river_heads(self, which_group= None):
570
581
  """Compute Head
@@ -586,7 +597,9 @@ class Polygons_Analyze(Zones):
586
597
  return head
587
598
 
588
599
  def get_river_values(self,
589
- which_value:Union[stored_values_unk,stored_values_pos],
600
+ which_value:Union[stored_values_unk,
601
+ stored_values_pos,
602
+ stored_values_coords],
590
603
  which_group=None) -> dict:
591
604
  """
592
605
  Get values for the river polygons
@@ -619,15 +632,35 @@ class Polygons_Analyze(Zones):
619
632
 
620
633
  create=False
621
634
  for curarray in curarrays.values():
622
- if len(curarray)>0:
623
- create=True
635
+ # if len(curarray)>0:
636
+ # create=True
637
+ if isinstance(curarray, tuple):
638
+ # on a également repris les coordonnées
639
+ if len(curarray[0])>0:
640
+ create=True
641
+ else:
642
+ if len(curarray)>0:
643
+ create=True
624
644
 
625
645
  if create:
626
646
  for idarray, curarray in enumerate(curarrays.values()):
627
- if len(curarray)>0:
628
- vallist = [curval[pos1][pos2] for curval in curarray]
629
- curdict[part_names[idarray][0]] = vallist
630
-
647
+ # if len(curarray)>0:
648
+ # vallist = [curval[pos1][pos2] for curval in curarray]
649
+ # curdict[part_names[idarray][0]] = vallist
650
+
651
+ if isinstance(curarray, tuple):
652
+ if pos1==-1:
653
+ if len(curarray[1])>0:
654
+ vallist = [curval[pos2] for curval in curarray[1]]
655
+ curdict[part_names[idarray][0]] = vallist
656
+ else:
657
+ if len(curarray[0])>0:
658
+ vallist = [curval[pos1][pos2] for curval in curarray[0]]
659
+ curdict[part_names[idarray][0]] = vallist
660
+ else:
661
+ if len(curarray)>0:
662
+ vallist = [curval[pos1][pos2] for curval in curarray]
663
+ curdict[part_names[idarray][0]] = vallist
631
664
  return locvalues
632
665
 
633
666
  if isinstance(self.linked, dict):
@@ -641,6 +674,9 @@ class Polygons_Analyze(Zones):
641
674
  elif which_value in stored_values_pos:
642
675
  values = fillin(1, which_value.value[0], self.river_values[which_group], self.linked[which_group])
643
676
  return values
677
+ elif which_value in stored_values_coords:
678
+ values = fillin(-1, which_value.value[0], self.river_values[which_group], self.linked[which_group])
679
+ return values
644
680
  else:
645
681
  return None
646
682
  else:
@@ -653,6 +689,8 @@ class Polygons_Analyze(Zones):
653
689
  values[curkey] = fillin(0, which_value.value[0], curgroup, curnames)
654
690
  elif which_value in stored_values_pos:
655
691
  values[curkey] = fillin(1, which_value.value[0], curgroup, curnames)
692
+ elif which_value in stored_values_coords:
693
+ values[curkey] = fillin(-1, which_value.value[0], curgroup, curnames)
656
694
  return values
657
695
  else:
658
696
  if which_value in stored_values_unk:
@@ -666,11 +704,15 @@ class Polygons_Analyze(Zones):
666
704
  elif which_value in stored_values_pos:
667
705
  values = fillin(1, which_value.value[0], self.river_values, self.linked)
668
706
  return values
707
+ elif which_value in stored_values_coords:
708
+ values = fillin(-1, which_value.value[0], self.river_values, self.linked)
669
709
  else:
670
710
  return None
671
711
 
672
712
  def get_river_values_op(self,
673
- which_value:Union[stored_values_unk,stored_values_pos],
713
+ which_value:Union[stored_values_unk,
714
+ stored_values_pos,
715
+ stored_values_coords],
674
716
  which_group=None,
675
717
  operator:operators=operators.MEDIAN) -> dict:
676
718
  """
@@ -741,10 +783,13 @@ class Polygons_Analyze(Zones):
741
783
  return ret
742
784
 
743
785
  def get_s_values(self,
744
- which_value:Union[stored_values_unk,stored_values_pos]=stored_values_unk.WATERLEVEL,
786
+ which_value:Union[stored_values_unk,
787
+ stored_values_pos,
788
+ stored_values_coords]=stored_values_unk.WATERLEVEL,
745
789
  which_group:str=None,
746
790
  which_sim:str=None,
747
791
  operator:operators=operators.MEDIAN):
792
+
748
793
  """ Get the values of the river polygons for a specific simulation
749
794
 
750
795
  :param which_value: value to get
@@ -763,6 +808,10 @@ class Polygons_Analyze(Zones):
763
808
  val.append(curval[which_sim])
764
809
  s.append(self.polygons_curvi[curkey])
765
810
 
811
+ if len(s) != len(val):
812
+ logging.error(_('Error in get_s_values'))
813
+ return [], []
814
+
766
815
  # Tri des valeurs selon l'absisse curviligne
767
816
  ret = sorted(zip(s, val))
768
817
 
@@ -771,6 +820,97 @@ class Polygons_Analyze(Zones):
771
820
 
772
821
  return s, val
773
822
 
823
+ def get_s_xy(self):
824
+ """ Get the centroids of the river polygons """
825
+
826
+ s = []
827
+ x = []
828
+ y = []
829
+
830
+ for curval in self.polygons_curvi.values():
831
+ s.append(curval)
832
+
833
+ for curval in self.polygons_meanxy.values():
834
+ x.append(curval[0])
835
+ y.append(curval[1])
836
+
837
+ if len(s) != len(x) or len(s) != len(y):
838
+ logging.error(_('Error in get_s_centroidsxy'))
839
+ return [], [], []
840
+
841
+ # Tri des valeurs selon l'absisse curviligne
842
+ ret = sorted(zip(s, x, y))
843
+
844
+ # Séparation des listes triées
845
+ s, x, y = zip(*ret)
846
+
847
+ return s, x, y
848
+
849
+ def get_s_xy4sim(self, which_group:str, which_sim:str, operator:operators=operators.MEDIAN):
850
+ """ Get the position for a specific simulation """
851
+
852
+ s1, x = self.get_s_values(which_value= stored_values_coords.X, which_group= which_group, which_sim= which_sim, operator= operator)
853
+ s2, y = self.get_s_values(which_value= stored_values_coords.Y, which_group= which_group, which_sim= which_sim, operator= operator)
854
+
855
+ assert s1 == s2, _('Error in get_s_xy4sim')
856
+
857
+ return s1, x, y
858
+
859
+ def save_xy_s_tofile(self, outputfile:str):
860
+ """ Save the centroids of the river polygons to a file """
861
+
862
+ s, x, y = self.get_s_xy()
863
+
864
+ with open(outputfile, 'w') as f:
865
+ f.write('x,y,s\n')
866
+ for curs, curx, cury in zip(s, x, y):
867
+ f.write('{0},{1},{2}\n'.format(curx, cury, curs))
868
+
869
+ def save_xy_s_tofile_4sim(self, outputfile:str, which_group:str, which_sim:str):
870
+ """ Save the centroids of the river polygons to a file """
871
+
872
+ s, x, y = self.get_s_xy4sim(which_group= which_group, which_sim= which_sim)
873
+
874
+ with open(outputfile, 'w') as f:
875
+ f.write('x,y,s\n')
876
+ for curs, curx, cury in zip(s, x, y):
877
+ f.write('{0},{1},{2}\n'.format(curx, cury, curs))
878
+
879
+ def export_as(self, outputfile:Path, unks:list[stored_values_unk | stored_values_coords], which_group:str, which_sim:str, operator:operators=operators.MEDIAN):
880
+ """ Export the values of the river polygons to a file
881
+
882
+ :param outputfile: output file (supported formats: csv, xlsx)
883
+ :param unks: list of values to export
884
+ :param which_group: group to export
885
+ :param which_sim: simulation to export
886
+ :param operator: operator to use for values (coordinates will be exported as MEDIAN)
887
+ """
888
+
889
+ outputfile = Path(outputfile)
890
+ if not (outputfile.suffix == '.csv' or outputfile.suffix == '.xlsx'):
891
+ logging.error(_('Unsupported format for export -- Must be csv or xlsx'))
892
+ return
893
+
894
+ import pandas as pd
895
+
896
+ s,x,y = self.get_s_xy4sim(which_group, which_sim, operators.MEDIAN)
897
+
898
+ vals = {curunk.value[1]:self.get_s_values(which_value= curunk,
899
+ which_group = which_group,
900
+ which_sim= which_sim,
901
+ operator= operator)[1] for curunk in unks}
902
+
903
+ cols_names = ['s [m]', 'x centroid [m]', 'y centroid [m]']
904
+ vals[cols_names[0]] = s
905
+ vals[cols_names[1]] = x
906
+ vals[cols_names[2]] = y
907
+
908
+ df = pd.DataFrame(vals, columns = [cur for cur in cols_names] + [curunk.value[1] for curunk in unks])
909
+
910
+ if outputfile.suffix == '.csv':
911
+ df.to_csv(outputfile, index=False)
912
+ elif outputfile.suffix == '.xlsx':
913
+ df.to_excel(outputfile, index=False)
774
914
 
775
915
  def plot_unk(self,
776
916
  figax = None,
wolfhece/pyshields.py CHANGED
@@ -278,7 +278,7 @@ def get_Rouse(d:float, q:float, h:float, K:float, rhom:float=2650., rho:float=RH
278
278
  """
279
279
  # tau_cr = (q/K)**2 / h**(7/3) * rho * GRAVITY
280
280
  # shear_vel = math.sqrt(tau_cr/rho)
281
- shear_vel = q/K / h**(7/6)* math.sqrt(GRAVITY)
281
+ shear_vel = q/K / h**(7./6.)* math.sqrt(GRAVITY)
282
282
  ws = get_settling_vel(d,rhom,rho)
283
283
  # von Kármán constant
284
284
  k = 0.40
@@ -513,6 +513,39 @@ def shieldsdia_dim(figax=None) -> tuple[plt.Figure,plt.Axes]:
513
513
 
514
514
  return fig,ax
515
515
 
516
+ def get_friction_slope_2D_Manning(q:float, h:float, n:float) -> float:
517
+ """
518
+ Compute friction slope j for 2D flow with Manning/Strickler friction law
519
+
520
+ :param q : discharge [m3/s]
521
+ :param h : water depth [m]
522
+ :param n : Manning friction coefficient [m-1/3.s]
523
+ """
524
+
525
+ denom = h**(4./3.)
526
+ if denom > 0.:
527
+ j = (q/h * n)**2.0 / denom
528
+ else:
529
+ j = 0.
530
+
531
+ return j
532
+
533
+ def get_shear_velocity_2D_Manning(q:float, h:float, n:float) -> float:
534
+ """
535
+ Compute shear velocity u_* for 2D flow with Manning/Strickler friction law
536
+
537
+ :param j : friction slope [-]
538
+ :param h : water depth [m]
539
+ :param q : discharge [m3/s]
540
+ :param n : Manning friction coefficient [m-1/3.s]
541
+ """
542
+
543
+ j = get_friction_slope_2D_Manning(q,h,n)
544
+
545
+ ushear = (h*j*GRAVITY)**0.5
546
+
547
+ return ushear
548
+
516
549
  def get_Shields_2D_Manning(s:float, d:float, q:float, h:float, n:float) -> float:
517
550
  """
518
551
  Compute Shields dimensionless parameter for 2D flow with Manning/Strickler friction law
@@ -528,11 +561,7 @@ def get_Shields_2D_Manning(s:float, d:float, q:float, h:float, n:float) -> float
528
561
  # calcul de terme de pente de frottement
529
562
 
530
563
  # j = (q/h)**2.0 / K**2. / h**(4./3.)
531
- denom = h**(4./3.)
532
- if denom > 0.:
533
- j = (q/h * n)**2.0 / denom
534
- else:
535
- j = 0.
564
+ j = get_friction_slope_2D_Manning(q,h,n)
536
565
 
537
566
  shields = j*h / (d*(s-1))
538
567
 
wolfhece/rem/REMMaker.py CHANGED
@@ -10,13 +10,13 @@ from osgeo import ogr
10
10
  from shapely.geometry import box # for cropping centerlines to extent of DEM
11
11
  import geopandas as gpd
12
12
  from geopandas import clip, read_file
13
- import osmnx # for querying OpenStreetMaps data to get river centerlines
13
+ import logging
14
+
14
15
  import requests
15
16
  from scipy.spatial import KDTree as KDTree # for finding nearest neighbors/interpolating
16
17
  from itertools import combinations
17
18
  import time
18
19
  from .RasterViz import RasterViz
19
- import logging
20
20
 
21
21
  level = logging.INFO
22
22
  fmt = '[%(levelname)s] %(asctime)s - %(message)s'
@@ -281,6 +281,14 @@ class REMMaker(object):
281
281
 
282
282
  def get_river_centerline(self):
283
283
  """Find centerline of river(s) within DEM area using OSM Ways"""
284
+
285
+ try:
286
+ import osmnx # for querying OpenStreetMaps data to get river centerlines
287
+ except ImportError:
288
+ logging.error("osmnx not installed. Please install osmnx to use this script.")
289
+ logging.error("Install with: 'pip install osmnx' but beware of dependencies especially Shapely, which may be forced to an older version.")
290
+ raise ImportError("osmnx not installed. Please install osmnx to use this script.")
291
+
284
292
  logging.info("Finding river centerline.")
285
293
  # get OSM Ways within bbox of DEM (returns geopandas geodataframe)
286
294
  osmnx.settings.cache_folder = './.osm_cache'
wolfhece/wolf_array.py CHANGED
@@ -1484,6 +1484,8 @@ class Ops_Array(wx.Frame):
1484
1484
 
1485
1485
  self.myzones.mapviewer = mapviewer
1486
1486
 
1487
+ self._levels = []
1488
+
1487
1489
  if self.wx_exists:
1488
1490
  self.set_GUI()
1489
1491
 
@@ -1746,12 +1748,20 @@ class Ops_Array(wx.Frame):
1746
1748
 
1747
1749
  self.extract_selection = wx.Button(self.tools, wx.ID_ANY, _("Extract selection"), wx.DefaultPosition,wx.DefaultSize, 0)
1748
1750
 
1751
+ cont_sizer = wx.BoxSizer(wx.HORIZONTAL)
1752
+ self._contour_int = wx.Button(self.tools, wx.ID_ANY, _("Contour"), wx.DefaultPosition, wx.DefaultSize, 0)
1753
+ self._contour_list = wx.Button(self.tools, wx.ID_ANY, _("Contour specific"), wx.DefaultPosition, wx.DefaultSize, 0)
1754
+
1755
+ cont_sizer.Add(self._contour_int, 1, wx.EXPAND)
1756
+ cont_sizer.Add(self._contour_list, 1, wx.EXPAND)
1757
+
1749
1758
  Toolssizer.Add(hbox, 0, wx.EXPAND)
1750
1759
  Toolssizer.Add(self.ApplyTools, 1, wx.EXPAND)
1751
1760
  Toolssizer.Add(self.nullborder, 1, wx.EXPAND)
1752
1761
  Toolssizer.Add(self.filter_zone, 1, wx.EXPAND)
1753
1762
  Toolssizer.Add(self.labelling, 1, wx.EXPAND)
1754
1763
  Toolssizer.Add(self.extract_selection, 1, wx.EXPAND)
1764
+ Toolssizer.Add(cont_sizer, 1, wx.EXPAND)
1755
1765
 
1756
1766
  self.ApplyTools.SetToolTip(_("Apply Nullvalue into memory/object"))
1757
1767
  self.nullborder.SetToolTip(_("Set null value on the border of the array\n\nYou will be asked for the width of the border (in cells)"))
@@ -2130,6 +2140,8 @@ class Ops_Array(wx.Frame):
2130
2140
  self.filter_zone.Bind(wx.EVT_BUTTON, self.OnFilterZone)
2131
2141
  self.labelling.Bind(wx.EVT_BUTTON, self.OnLabelling)
2132
2142
  self.extract_selection.Bind(wx.EVT_BUTTON, self.OnExtractSelection)
2143
+ self._contour_int.Bind(wx.EVT_BUTTON, self.OnContourInt)
2144
+ self._contour_list.Bind(wx.EVT_BUTTON, self.OnContourList)
2133
2145
 
2134
2146
  self.SelectOp.Bind(wx.EVT_BUTTON, self.OnApplyOpSelect)
2135
2147
  self.palapply.Bind(wx.EVT_BUTTON, self.Onupdatepal)
@@ -2586,6 +2598,70 @@ class Ops_Array(wx.Frame):
2586
2598
 
2587
2599
  self.parentarray.extract_selection()
2588
2600
 
2601
+ def OnContourInt(self, event:wx.MouseEvent):
2602
+ """ Create contour - number of contours """
2603
+
2604
+ with wx.NumberEntryDialog(None, 'Number of contours', 'Number of contours', 'Number of contours', 20, 1, 1000) as dlg:
2605
+ if dlg.ShowModal() == wx.ID_OK:
2606
+ nbcontours = dlg.GetValue()
2607
+
2608
+ logging.info(_('Baking contour'))
2609
+ cont = self.parentarray.contour(levels = nbcontours)
2610
+ logging.info(_('Add contour to viewer'))
2611
+ cont.prep_listogl()
2612
+ mapv = self.get_mapviewer()
2613
+ mapv.add_object('vector', newobj = cont, id = cont.idx)
2614
+ self.get_mapviewer().Paint()
2615
+ logging.info(_('Done !'))
2616
+
2617
+ def OnContourList(self, event:wx.MouseEvent):
2618
+ """ Create contour - list of values """
2619
+
2620
+ with wx.TextEntryDialog(None, 'List of specific values separated by comma or tuple (min;max;step)',
2621
+ 'List of values', f'{self.parentarray.array.min()}, {self.parentarray.array.max()}') as dlg:
2622
+
2623
+ if dlg.ShowModal() == wx.ID_OK:
2624
+ txt = dlg.GetValue()
2625
+
2626
+ self._levels = []
2627
+ if ',' in txt:
2628
+ for cur in txt.split(','):
2629
+ if '(' in cur:
2630
+ cur = cur.replace('(', '').replace(')', '')
2631
+ cur = cur.split(';')
2632
+ if len(cur) == 3:
2633
+ minval = float(cur[0])
2634
+ maxval = float(cur[1])
2635
+ step = float(cur[2])
2636
+ self._levels.extend(np.arange(minval, maxval, step))
2637
+ elif '(' in txt:
2638
+ cur = txt.replace('(', '').replace(')', '')
2639
+ cur = cur.split(';')
2640
+ if len(cur) == 3:
2641
+ minval = float(cur[0])
2642
+ maxval = float(cur[1])
2643
+ step = float(cur[2])
2644
+ self._levels.extend(np.arange(minval, maxval, step))
2645
+ else:
2646
+ try:
2647
+ self._levels = float(txt)
2648
+ except:
2649
+ logging.error('Error in chain text to float')
2650
+ return
2651
+
2652
+ if isinstance(self._levels, list):
2653
+ if len(self._levels) == 0:
2654
+ logging.error('Nothing to do !')
2655
+ return
2656
+
2657
+ logging.info(_('Baking contour'))
2658
+ cont = self.parentarray.contour(levels = self._levels)
2659
+ logging.info(_('Add contour to viewer'))
2660
+ cont.prep_listogl()
2661
+ self.get_mapviewer().add_object('vector', newobj = cont, id = cont.idx)
2662
+ self.get_mapviewer().Paint()
2663
+ logging.info(_('Done !'))
2664
+
2589
2665
  def OnApplyOpMath(self, event:wx.MouseEvent):
2590
2666
  """ Apply math operator to the array """
2591
2667
 
@@ -8978,6 +9054,28 @@ class WolfArray(Element_To_Draw, header_wolf):
8978
9054
  Array3 = WolfArray(output_raster_path, nullvalue=-9999)
8979
9055
  return Array3
8980
9056
 
9057
+ def contour(self, levels:Union[int, list[float]] = 10) -> Zones:
9058
+ """ Compute contour lines """
9059
+
9060
+ if isinstance(levels, int):
9061
+ levels = np.linspace(self.array.min(), self.array.max(), levels)
9062
+
9063
+ x, y = self.meshgrid()
9064
+ cs = plt.contour(x, y, self.array, levels=levels)
9065
+
9066
+ zones = Zones(idx = self.idx + '_contour', mapviewer = self.get_mapviewer())
9067
+ for collection, level in zip(cs.collections, cs.levels):
9068
+ zone_level = zone(name=f'Contour {level}')
9069
+ for idx, path in enumerate(collection.get_paths()):
9070
+ vector_level = vector(name=f'Contour {level} - {idx}')
9071
+ for vertices in path.to_polygons(closed_only=False):
9072
+ for vertex in vertices:
9073
+ vector_level.add_vertex(wolfvertex(vertex[0], vertex[1]))
9074
+ zone_level.add_vector(vector_level, forceparent=True)
9075
+ zones.add_zone(zone_level, forceparent=True)
9076
+
9077
+ return zones
9078
+
8981
9079
  class WolfArrayMB(WolfArray):
8982
9080
  """
8983
9081
  Matrice multiblocks
@@ -35,7 +35,7 @@ from .drawing_obj import Element_To_Draw
35
35
  from .PyPalette import wolfpalette
36
36
  from .PyTranslate import _
37
37
  from .gpuview import GRID_N, Rectangle, VectorField
38
- from .pyshields import get_d_cr, get_d_cr_susp, izbach_d_cr, get_Shields_2D_Manning
38
+ from .pyshields import get_d_cr, get_d_cr_susp, izbach_d_cr, get_Shields_2D_Manning, get_friction_slope_2D_Manning, get_shear_velocity_2D_Manning
39
39
  from .pyviews import WolfViews
40
40
  from .mesh2d.wolf2dprev import prev_parameters_simul, blocks_file
41
41
  from .GraphNotebook import PlotPanel
@@ -1414,6 +1414,7 @@ class views_2D(Enum):
1414
1414
  TURB_VISC_3D = _('Turbulent viscosity 3D')
1415
1415
  VECTOR_FIELD_Q = _('Discharge vector field')
1416
1416
  VECTOR_FIELD_U = _('Velocity vector field')
1417
+ U_SHEAR = _('Shear velocity [ms-1]')
1417
1418
  SHIELDS_NUMBER = _('Shields number - Manning-Strickler')
1418
1419
  CRITICAL_DIAMETER_SHIELDS = _('Critical grain diameter - Shields')
1419
1420
  CRITICAL_DIAMETER_IZBACH = _('Critical grain diameter - Izbach')
@@ -1726,6 +1727,13 @@ class OneWolfResult:
1726
1727
 
1727
1728
  nullvalue = self.waterdepth.nullvalue
1728
1729
 
1730
+ elif which==views_2D.U_SHEAR:
1731
+ self.U_Shear = self.get_u_shear()
1732
+ self._current = self.U_Shear
1733
+ self._view = WolfViews()
1734
+
1735
+ nullvalue = self.waterdepth.nullvalue
1736
+
1729
1737
  elif which==views_2D.SHIELDS_NUMBER:
1730
1738
  if self.ShieldsNumber is None or self._force_update_shields:
1731
1739
  self.ShieldsNumber = self.get_shieldsnumber()
@@ -1891,6 +1899,33 @@ class OneWolfResult:
1891
1899
  logging.info(_('End of computing critical diameters'))
1892
1900
 
1893
1901
  return diamcrit
1902
+
1903
+ def get_u_shear(self) -> WolfArray:
1904
+ """
1905
+ Calcul de la vitesse de cisaillement
1906
+ """
1907
+
1908
+ def compute() -> WolfArray:
1909
+
1910
+ ij = np.argwhere(self.waterdepth.array>0.)
1911
+
1912
+ u_shear = WolfArray(mold=self.waterdepth)
1913
+ qnorm = (self.qx**2.+self.qy**2.)**.5
1914
+ qnorm.array.mask=self.waterdepth.array.mask
1915
+
1916
+ _u_shear = np.asarray([get_shear_velocity_2D_Manning(qnorm.array[i,j],
1917
+ self.waterdepth.array[i,j],
1918
+ self.rough_n.array.data[i,j]) for i,j in ij])
1919
+
1920
+ u_shear.array[ij[:,0],ij[:,1]] = _u_shear
1921
+
1922
+ return u_shear
1923
+
1924
+ logging.info(_('Computing shear velocity'))
1925
+ u_shear = compute()
1926
+ logging.info(_('End of computing shear velocity'))
1927
+
1928
+ return u_shear
1894
1929
 
1895
1930
  def get_shieldsnumber(self) -> WolfArray:
1896
1931
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: wolfhece
3
- Version: 2.1.90
3
+ Version: 2.1.93
4
4
  Author-email: Pierre Archambeau <pierre.archambeau@uliege.be>
5
5
  License: Copyright (c) 2024 University of Liege. All rights reserved.
6
6
  Project-URL: Homepage, https://uee.uliege.be/hece
@@ -51,7 +51,6 @@ Requires-Dist: pygltflib
51
51
  Requires-Dist: ezdxf
52
52
  Requires-Dist: pyvista
53
53
  Requires-Dist: tqdm==4.64.*
54
- Requires-Dist: osmnx
55
54
  Requires-Dist: tifffile
56
55
  Requires-Dist: numba==0.58.*
57
56
  Requires-Dist: xmltodict
@@ -7,11 +7,11 @@ wolfhece/ManageParams.py,sha256=EeuUI5Vvh9ixCvYf8YShMC1s1Yacc7OxOCN7q81gqiQ,517
7
7
  wolfhece/Model1D.py,sha256=SI4oNF_J3MdjiWZoizS8kuRXLMVyymX9dYfYJNVCQVI,476989
8
8
  wolfhece/PyConfig.py,sha256=UNtl5UzZ399JqjJT67-4DWaIkv76sc1FiEsSDJpXlL0,10458
9
9
  wolfhece/PyCrosssections.py,sha256=FnmM9DWY_SAF2EDH9Gu2PojXNtSTRF4-aYQuAAJXBh4,112771
10
- wolfhece/PyDraw.py,sha256=CvnaK7NgeB25hlzlF-BxU38LT7-3ffuPnana6Mm9PDE,427447
10
+ wolfhece/PyDraw.py,sha256=KkqxUazcXhenwBVCE69EHd_lt0g9fiX6R4p3IBS2pnI,442172
11
11
  wolfhece/PyGui.py,sha256=HY0beOMSp1JEyq8-vfVynzVrmKxvaO_sJSMwlNqCNrg,105289
12
12
  wolfhece/PyGuiHydrology.py,sha256=f60E8K9eGTnRq5RDF6yvt-ahf2AYegwQ9t25zZ2Mk1A,14946
13
13
  wolfhece/PyHydrographs.py,sha256=jwtSNMMACwarxrtN1UeQYth99UNrhwPx1IGgUwcooHA,3774
14
- wolfhece/PyPalette.py,sha256=QCzXBnYlv7YfHjpJWyO_8F-uOLOe7O_RbkyrnMYzgM4,28146
14
+ wolfhece/PyPalette.py,sha256=81n1P-olOe4wElTLv-miSDhqvJU_RHcxgfpHt794dSw,31436
15
15
  wolfhece/PyParams.py,sha256=6fREK5cUCGw84SDyPvuSzidnX-9BXOX3fve5XBG1K_I,98114
16
16
  wolfhece/PyPictures.py,sha256=m1kY0saW6Y9Q0bDCo47lW6XxDkBrbQG-Fd8uVn8G5ic,2514
17
17
  wolfhece/PyTranslate.py,sha256=4appkmNeHHZLFmUtaA_k5_5QL-5ymxnbVN4R2OblmtE,622
@@ -38,23 +38,23 @@ wolfhece/ismember.py,sha256=fkLvaH9fhx-p0QrlEzqa6ySO-ios3ysjAgXVXzLgSpY,2482
38
38
  wolfhece/multiprojects.py,sha256=Sd6Bl6YP33jlR79A6rvSLu23vq8sqbFYL8lWuVPkEpE,21549
39
39
  wolfhece/picc.py,sha256=ueujnw03BQz-nPxKGzfDzZbtruTzvnqd6Gm8lOvBYzw,8802
40
40
  wolfhece/pyGui1D.py,sha256=9g7OS3YiKsqy--6y0cBD7x2gaqTTYFXWkxImpgnTA20,121937
41
- wolfhece/pybridges.py,sha256=xbZPuX40c4EKqws4OKNbUVUBPKIzLTbSdYVyrNf_kIE,57418
41
+ wolfhece/pybridges.py,sha256=EU_r6yRYDf5zKmwwXEBsGYvTKFbSfE3iTxPwusKR-1I,57398
42
42
  wolfhece/pydike.py,sha256=hPBQsmSTW4QAp1wcOzb-TL3L7eet2WT1sJx2q-WNQ-Q,2241
43
43
  wolfhece/pylogging.py,sha256=4TI8hgBB65z-zpvU5Rfa2jkPXPhJaqXjHVPwbcdzTNc,4528
44
- wolfhece/pypolygons_scen.py,sha256=C0qxVUsBHWZVkurZV-DI1GMN1J1B-ul93n2fs16UjoI,39718
45
- wolfhece/pyshields.py,sha256=7k-qe2EJgr9fJE62jyPmlWQwRj8T0DK4iuMU844ZhYs,23281
44
+ wolfhece/pypolygons_scen.py,sha256=vMfAKXKrW6vKR7l9Fl2hEt-jihLwIiMur7qNTNfwRg4,46101
45
+ wolfhece/pyshields.py,sha256=6YncgmcA6QvbyIl4jbFRf24uJVjhiSplQKWtZH42lXI,24108
46
46
  wolfhece/pyviews.py,sha256=5Hqqo9MRw1eiomYkmc7QywNu1KmEkytLJG-wH_aG38Y,13748
47
47
  wolfhece/pywalous.py,sha256=yRaWJjKckXef1d9D5devP0yFHC9uc6kRV4G5x9PNq9k,18972
48
48
  wolfhece/rain_SPWMI.py,sha256=qCfcmF7LajloOaCwnTrrSMzyME03YyilmRUOqrPrv3U,13846
49
49
  wolfhece/textpillow.py,sha256=map7HsGYML_o5NHRdFg2s_TVQed_lDnpYNDv27MM0Vw,14130
50
50
  wolfhece/tools_mpl.py,sha256=gQ3Jg1iuZiecmMqa5Eli2ZLSkttu68VXL8YmMDBaEYU,564
51
- wolfhece/wolf_array.py,sha256=L6OV70nFSmzfO_beNbPRQ_VoklC_cx6fyhoslI3AMXg,401812
51
+ wolfhece/wolf_array.py,sha256=HasKFOCiFzM55YSXPvpWJ7O4tOoxyTm_LHytE2ZQq8o,406444
52
52
  wolfhece/wolf_hist.py,sha256=7jeVrgSkM3ErJO6SRMH_PGzfLjIdw8vTy87kesldggk,3582
53
53
  wolfhece/wolf_texture.py,sha256=DS5eobLxrq9ljyebYfpMSQPn8shkUAZZVfqrOKN_QUU,16951
54
54
  wolfhece/wolf_tiles.py,sha256=2Ho2I20rHRY81KXxjgLOYISdF4OkJ2d6omeY4shDoGI,10386
55
55
  wolfhece/wolf_vrt.py,sha256=89XoDhCJMHiwPQUuOduxtTRKuIa8RDxgNqX65S4xp9M,10569
56
56
  wolfhece/wolf_zi_db.py,sha256=baE0niMCzybWGSvPJc5FNxo9ZxsGfU4p-FmfiavFHAs,12967
57
- wolfhece/wolfresults_2D.py,sha256=5RAvOfO0ua-5hMEdtXKZWznh4NN_q-PLfZdANm7W33M,168478
57
+ wolfhece/wolfresults_2D.py,sha256=p0v3FT6CAzf6aP4AEEXNkuHG01c2Eqbio_a8ghJIt7k,169709
58
58
  wolfhece/xyz_file.py,sha256=Se4nCPwYAYLSA5i0zsbnZUKoAMAD0mK1FJea5WSZUkk,5755
59
59
  wolfhece/acceptability/Parallels.py,sha256=h4tu3SpC_hR5Hqa68aruxhtAyhs8u666YuZ40_fR5zg,3979
60
60
  wolfhece/acceptability/__init__.py,sha256=hfgoPKLDpX7drN1Vpvux-_5Lfyc_7feT2C2zQr5v-Os,258
@@ -75,7 +75,7 @@ wolfhece/apps/curvedigitizer.py,sha256=Yps4bcayzbsz0AoVc_dkSk35dEhhn_esIBy1Ziefg
75
75
  wolfhece/apps/hydrometry.py,sha256=lhhJsFeb4zGL4bNQTs0co85OQ_6ssL1Oy0OUJCzhfYE,656
76
76
  wolfhece/apps/isocurrent.py,sha256=dagmGR8ja9QQ1gwz_8fU-N052hIw-W0mWGVkzLu6C7I,4247
77
77
  wolfhece/apps/splashscreen.py,sha256=SrustmIQeXnsiD-92OzjdGhBi-S7c_j-cSvuX4T6rtg,2929
78
- wolfhece/apps/version.py,sha256=0ewKEdaYlj_bYhGOPsIk1mktB1LQK_EnKtWL-Vk3Dl8,388
78
+ wolfhece/apps/version.py,sha256=uhn_xV3CTGZbQdI3Z2ZnOh4S6W8nowYt7Tj4x2XrHlo,388
79
79
  wolfhece/apps/wolf.py,sha256=j_CgvsL8rwixbVvVD5Z0s7m7cHZ86gmFLojKGuetMls,729
80
80
  wolfhece/apps/wolf2D.py,sha256=4z_OPQ3IgaLtjexjMKX9ppvqEYyjFLt1hcfFABy3-jU,703
81
81
  wolfhece/apps/wolf_logo.bmp,sha256=ruJ4MA51CpGO_AYUp_dB4SWKHelvhOvd7Q8NrVOjDJk,3126
@@ -254,7 +254,7 @@ wolfhece/pythonfortran/example_numpy_memory.py,sha256=o3hzJDw7YtE4v0FXI3-l2VzupC
254
254
  wolfhece/pythonfortran/tools.py,sha256=oYh9MguRYEGNGKVbHqQW2V9okZJLs3n4Qs-vLWPmBe4,2462
255
255
  wolfhece/radar/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
256
256
  wolfhece/radar/wolfradar.py,sha256=mvsVf6-4KCqVF6kWsKfPuM7KPqRdYHuIZAbb8kzXAZU,10032
257
- wolfhece/rem/REMMaker.py,sha256=k1kOb_69kNw00HRPbTc_E2XTypiyV0mADDbW5etkBAs,31079
257
+ wolfhece/rem/REMMaker.py,sha256=zkiAo36MmusPhgv1qJmpDgtoTWbh_eJ6qJqtCfeC1M8,31480
258
258
  wolfhece/rem/RasterViz.py,sha256=fnyMfAJZDoS-rjagsNRGLndS-UYNUzMY4DgenjD3Y_4,29068
259
259
  wolfhece/rem/__init__.py,sha256=S2-J5uEGK_VaMFjRUYFIdSScJjZyuXH4RmMmnG3OG7I,19
260
260
  wolfhece/report/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -285,8 +285,8 @@ wolfhece/ui/wolf_multiselection_collapsiblepane.py,sha256=8PlMYrb_8jI8h9F0_EagpM
285
285
  wolfhece/ui/wolf_times_selection_comparison_models.py,sha256=ORy7fz4dcp691qKzaOZHrRLZ0uXNhL-LIHxmpDGL6BI,5007
286
286
  wolfhece/wintab/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
287
287
  wolfhece/wintab/wintab.py,sha256=8A-JNONV6ujgsgG3lM5Uw-pVgglPATwKs86oBzzljoc,7179
288
- wolfhece-2.1.90.dist-info/METADATA,sha256=Nf-U-idNQhjOSifNKkIGDY8shuwNX8TV1B3AyAZcXlA,2570
289
- wolfhece-2.1.90.dist-info/WHEEL,sha256=UvcQYKBHoFqaQd6LKyqHw9fxEolWLQnlzP0h_LgJAfI,91
290
- wolfhece-2.1.90.dist-info/entry_points.txt,sha256=ZZ-aSfbpdcmo-wo84lRFzBN7LaSnD1XRGSaAKVX-Gpc,522
291
- wolfhece-2.1.90.dist-info/top_level.txt,sha256=EfqZXMVCn7eILUzx9xsEu2oBbSo9liWPFWjIHik0iCI,9
292
- wolfhece-2.1.90.dist-info/RECORD,,
288
+ wolfhece-2.1.93.dist-info/METADATA,sha256=Rws7W6QN1NdDV2S30eXAeX-vTVauNTaWIzCTfEzkOpk,2548
289
+ wolfhece-2.1.93.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
290
+ wolfhece-2.1.93.dist-info/entry_points.txt,sha256=ZZ-aSfbpdcmo-wo84lRFzBN7LaSnD1XRGSaAKVX-Gpc,522
291
+ wolfhece-2.1.93.dist-info/top_level.txt,sha256=EfqZXMVCn7eILUzx9xsEu2oBbSo9liWPFWjIHik0iCI,9
292
+ wolfhece-2.1.93.dist-info/RECORD,,