wolfhece 2.1.125__py3-none-any.whl → 2.1.127__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.
@@ -17,6 +17,7 @@ from matplotlib.figure import Figure
17
17
  from shapely.geometry import LineString, Point, CAP_STYLE, Polygon
18
18
  from shapely.ops import prep
19
19
  import wx
20
+ from tqdm import tqdm
20
21
 
21
22
  from . import viewer
22
23
  from ..PyWMS import getWalonmap
@@ -41,6 +42,7 @@ class Colors_Lazviewer(Enum):
41
42
  ORTHO_2006_2007 = 2006
42
43
  CODE_2013 = 0
43
44
  CODE_2023 = 2
45
+ CODE_2021_2022 = 3
44
46
  FROM_FILE = 1
45
47
 
46
48
  class Classification_LAZ():
@@ -68,6 +70,18 @@ class Classification_LAZ():
68
70
  9 : ['Eau', 'Eau',Colors.rgb_withalpha_float('aqua',1.)],
69
71
  10 : ['Ponts', 'Ponts',Colors.rgb_withalpha_float('lightyellow1',1.)]}
70
72
 
73
+ def init_2021_2022(self):
74
+
75
+ self.class_name = 'SPW 2021-2022'
76
+ self.classification={
77
+ 0 : ['0', 'Pas de classification', Colors.rgb_withalpha_float('black',.2),],
78
+ 1 : ['Hors-sol', 'building, toits et autres', Colors.rgb_withalpha_float('white',.2),],
79
+ 2 : ['Sol', 'y compris talus et digues', Colors.rgb_withalpha_float('brown',1.)],
80
+ 4 : ['Végétation', 'y compris la végétation linéaire', Colors.rgb_withalpha_float('forestgreen',1.)],
81
+ 9 : ['Eau', 'Eau',Colors.rgb_withalpha_float('aqua',1.)],
82
+ 10 : ['Ponts', 'Ponts',Colors.rgb_withalpha_float('lightyellow1',1.)],
83
+ 15 : ['Ligne hautes-tension', 'Ligne hautes-tension',Colors.rgb_withalpha_float('lightcyan1',0.25)]}
84
+
71
85
  def init_2023(self):
72
86
 
73
87
  self.class_name = 'SPW-Geofit 2023'
@@ -155,8 +169,8 @@ class xyz_laz():
155
169
  parts = last_part.split('_')
156
170
 
157
171
  # L'origine est codée dans le nom de fichier
158
- self.origx = float(parts[2])
159
- self.origy = float(parts[3])
172
+ self.origx = float(parts[-3])
173
+ self.origy = float(parts[-2])
160
174
 
161
175
  dx = 2500.
162
176
  dy = 3500.
@@ -557,6 +571,9 @@ class xyz_laz_grids():
557
571
  return ret
558
572
 
559
573
  def find_files_in_bounds(self, bounds:Union[tuple[tuple[float,float],tuple[float,float]], list[list[float, float],list[float, float]]]):
574
+ """ Find all files in bounds
575
+
576
+ :param bounds: [[xmin,xmax], [ymin,ymax]]"""
560
577
 
561
578
  ret = [(cur.mydir, cur.find_files_in_bounds(bounds)) for cur in self.grids]
562
579
  ret = [cur for cur in ret if len(cur[1])>0]
@@ -569,6 +586,11 @@ class xyz_laz_grids():
569
586
  return ret
570
587
 
571
588
  def copy_files_in_bounds(self, bounds:Union[tuple[tuple[float,float],tuple[float,float]], list[list[float, float],list[float, float]]], dirout:str):
589
+ """ Copy files in bounds to directory
590
+
591
+ :param bounds: [[xmin,xmax], [ymin,ymax]]
592
+ :param dirout: output directory
593
+ """
572
594
 
573
595
  import shutil
574
596
 
@@ -587,10 +609,28 @@ class xyz_laz_grids():
587
609
  shutil.copy(join(curdir,'gridinfo.txt'), locdir / 'gridinfo.txt')
588
610
 
589
611
  def read_dir(self, dir_grids):
612
+ """ Read all grids in directory and subdirectories """
613
+
614
+ import asyncio
615
+
590
616
  dirs = listdir(dir_grids)
591
617
 
592
- for curdir in dirs:
593
- self.grids.append(xyz_laz_grid(join(dir_grids,curdir)))
618
+ logging.info(_('Reading grids information -- {} grids'.format(len(dirs))))
619
+
620
+ def init_grid(curdir):
621
+ if (Path(dir_grids) / Path(curdir)).is_dir():
622
+ return xyz_laz_grid(join(dir_grids, curdir))
623
+
624
+ return None
625
+
626
+ async def init_grid_async(curdir):
627
+ return init_grid(curdir)
628
+
629
+ loop = asyncio.get_event_loop()
630
+ tasks = [init_grid_async(curdir) for curdir in dirs]
631
+ self.grids = list(filter(None, loop.run_until_complete(asyncio.gather(*tasks))))
632
+
633
+ logging.info(_('Grids initialized'))
594
634
 
595
635
  def scan_around(self, xy:Union[LineString,list[list[float], list[float]]], length_buffer=5.):
596
636
  """
@@ -707,42 +747,82 @@ class xyz_laz_grids():
707
747
 
708
748
  return figmpl
709
749
 
710
- def create_from_laz(self, dir_laz:str, shape:str, ds:float = 50, force_format = np.float64):
750
+ def create_from_laz(self, dir_laz:str, shape:str=None, ds:float = 50, force_format = np.float64):
711
751
 
712
752
  try:
713
753
  from ..PyVertexvectors import Zones
714
754
  except:
715
755
  from wolfhece.PyVertexvectors import Zones
716
- vecs = Zones(shape)
717
756
 
718
- for entry in scandir(dir_laz):
757
+ vecs = None
758
+ if shape is not None:
759
+ vecs = Zones(shape)
760
+
761
+ dir_laz = Path(dir_laz)
762
+
763
+ for entry in tqdm(dir_laz.glob('**/*.laz')):
719
764
  if entry.is_file():
720
- if entry.name.endswith('.laz'):
721
765
 
722
- file_wo_suf = entry.name.removesuffix('.laz')
723
- dirname = join(self.dir, file_wo_suf)
766
+ file_wo_suf = entry.stem
767
+ dirname = join(self.dir, file_wo_suf)
724
768
 
725
- if not exists(dirname):
726
- makedirs(dirname, exist_ok=True)
769
+ if not exists(dirname):
770
+ makedirs(dirname, exist_ok=True)
727
771
 
728
- newlaz = xyz_laz_grid(mydir=dirname)
772
+ newlaz = xyz_laz_grid(mydir=dirname)
729
773
 
774
+ if vecs is not None:
730
775
  vec = vecs.get_zone(file_wo_suf)
731
776
  bounds = vec.myvectors[0].get_bounds()
777
+ else:
778
+ lazdata = laspy.read(entry)
779
+ bounds = [[lazdata.x.min(), lazdata.y.min()],
780
+ [lazdata.x.max(), lazdata.y.max()]]
781
+
782
+ bounds = [[math.floor(bounds[0][0]/ds)*ds, math.floor(bounds[0][1]/ds)*ds],
783
+ [math.ceil(bounds[1][0]/ds)*ds, math.ceil(bounds[1][1]/ds)*ds]]
784
+
785
+ dx = bounds[1][0] -bounds[0][0]
786
+ dy = bounds[1][1] -bounds[0][1]
787
+ nb = max(int(dx/ds), int(dy/ds))
788
+
789
+ self.grids.append(newlaz._sort_grid_np(entry,
790
+ join(dirname, file_wo_suf),
791
+ bounds=[[bounds[0][0], bounds[1][0]], [bounds[0][1], bounds[1][1]]],
792
+ gridsize=[max(int(dx/ds),1), max(int(dy/ds),1)],
793
+ force_format=force_format))
794
+
795
+ def create_bounds_shape(self, dir_laz:str, out_shape:str):
796
+ """ Create shape from laz files """
797
+ try:
798
+ from ..PyVertexvectors import Zones
799
+ except:
800
+ from wolfhece.PyVertexvectors import Zones
801
+
802
+ dir_laz = Path(dir_laz)
803
+ out_shape = Path(out_shape)
804
+
805
+ vecs = Zones()
732
806
 
733
- bounds = [[math.floor(bounds[0][0]/ds)*ds, math.floor(bounds[0][1]/ds)*ds],
734
- [math.ceil(bounds[1][0]/ds)*ds, math.ceil(bounds[1][1]/ds)*ds]]
807
+ for entry in tqdm(dir_laz.glob('**/*.laz')):
808
+ if entry.is_file():
809
+ lazdata = laspy.read(entry)
810
+
811
+ bounds = [[lazdata.x.min(), lazdata.y.min()],
812
+ [lazdata.x.max(), lazdata.y.max()]]
813
+ loczone = zone(name=entry.stem)
814
+ locvec = vector(name=entry.stem)
735
815
 
736
- dx = bounds[1][0] -bounds[0][0]
737
- dy = bounds[1][1] -bounds[0][1]
738
- nb = max(int(dx/ds), int(dy/ds))
816
+ locvec.add_vertex(wolfvertex(bounds[0][0], bounds[0][1]))
817
+ locvec.add_vertex(wolfvertex(bounds[1][0], bounds[0][1]))
818
+ locvec.add_vertex(wolfvertex(bounds[1][0], bounds[1][1]))
819
+ locvec.add_vertex(wolfvertex(bounds[0][0], bounds[1][1]))
820
+ locvec.close_force()
739
821
 
740
- self.grids.append(newlaz._sort_grid_np(entry.path,
741
- join(dirname, file_wo_suf),
742
- bounds=[[bounds[0][0], bounds[1][0]], [bounds[0][1], bounds[1][1]]],
743
- gridsize=[max(int(dx/ds),1), max(int(dy/ds),1)],
744
- force_format=force_format))
822
+ loczone.add_vector(locvec, forceparent=True)
823
+ vecs.add_zone(loczone, forceparent=True)
745
824
 
825
+ vecs.saveas(Path(self.dir) / out_shape)
746
826
 
747
827
  class Wolf_LAZ_Data(Element_To_Draw):
748
828
  """ Base class for LAZ data which can be imported in Pydraw.Mapviewer.
@@ -1145,6 +1225,8 @@ class Wolf_LAZ_Data(Element_To_Draw):
1145
1225
  logging.warning(_('No classification chosen - Abort !'))
1146
1226
  elif classification == 'SPW 2013-2014':
1147
1227
  self.classification.init_2013()
1228
+ elif classification == 'SPW 2021-2022':
1229
+ self.classification.init_2021_2022()
1148
1230
  else:
1149
1231
  self.classification.init_2023()
1150
1232
 
@@ -1900,6 +1982,34 @@ def get_colors(las:laspy.LasData, which_colors:Colors_Lazviewer, imsize=2000, fn
1900
1982
  name, comment, color = value
1901
1983
  colors[myclass==int(key)] = color
1902
1984
 
1985
+ elif which_colors==Colors_Lazviewer.CODE_2021_2022.value:
1986
+ """
1987
+ - Rebus/non classés - Code 0;
1988
+ - Hors-sol (building, toits et autres) - Code 1;
1989
+ - Sol (y compris talus et digues) - Code 2;
1990
+ - Végétation haute (y compris la végétation linéaire) - Code 4;
1991
+ - Eau - Code 9;
1992
+ - Pont – Code 10;
1993
+ - Ligne hautes-tension - Code 15.
1994
+ """
1995
+ if type(las) is laspy.LasData:
1996
+ myclass = las.classification
1997
+ elif type(las) is list:
1998
+ myclass=[]
1999
+ for curlas in las:
2000
+ myclass.append(curlas.classification)
2001
+ myclass = np.concatenate(myclass)
2002
+ else:
2003
+ myclass = np.int8(las[:,3])
2004
+
2005
+ if palette_classif is None:
2006
+ palette_classif = Classification_LAZ()
2007
+ palette_classif.init_2021_2022()
2008
+
2009
+ for key, value in palette_classif.classification.items():
2010
+ name, comment, color = value
2011
+ colors[myclass==int(key)] = color
2012
+
1903
2013
  elif which_colors==Colors_Lazviewer.CODE_2023.value:
1904
2014
 
1905
2015
  if palette_classif is None:
@@ -116,7 +116,7 @@ class Calculator(wx.Frame):
116
116
  from ..PyDraw import draw_type
117
117
  ids = self._mapviewer.get_list_keys(drawing_type=draw_type.ARRAYS, checked_state=None)
118
118
  for id in ids:
119
- self.memory_txt += id
119
+ self.memory_txt = id
120
120
 
121
121
  def memory_clear_event(self, e):
122
122
  self.memory_clear()
@@ -472,13 +472,13 @@ class Config_Manager_2D_GPU:
472
472
 
473
473
  logging.info(_('Number of tif files : {}'.format(len(list_tif))))
474
474
 
475
- standard_files = ['bathymetry.tif',
476
- 'manning.tif',
477
- 'infiltration.tif',
478
- 'h.tif',
479
- 'qx.tif',
480
- 'qy.tif',
481
- 'roof.tif',
475
+ standard_files = ['bathymetry.tif',
476
+ 'manning.tif',
477
+ 'infiltration.tif',
478
+ 'h.tif',
479
+ 'qx.tif',
480
+ 'qy.tif',
481
+ 'roof.tif',
482
482
  'deck.tif']
483
483
 
484
484
  log = ''
@@ -1217,7 +1217,7 @@ class Config_Manager_2D_GPU:
1217
1217
  logging.error(_("No 'bathymetry.tif' file found in the root directory !"))
1218
1218
 
1219
1219
 
1220
- def combine_bath_roof_deck(self, bathymetry:WolfArray,
1220
+ def combine_bath_roof_deck(self, bathymetry:WolfArray,
1221
1221
  bridge_roof:WolfArray, bridge_deck:WolfArray,
1222
1222
  threshold:float = .05) -> str:
1223
1223
  """ Verify bathymetry, roof and deck """
@@ -1231,7 +1231,7 @@ class Config_Manager_2D_GPU:
1231
1231
  if ret != '':
1232
1232
  logging.error(ret)
1233
1233
  return ret
1234
-
1234
+
1235
1235
  # si la matrice de toit de pont est plus basse que la bathymétrie, on met à 99999
1236
1236
  # la bathymétrie et le toit de pont.
1237
1237
  # Ainsi, ces maille seront infranchissables.
@@ -1257,7 +1257,7 @@ class Config_Manager_2D_GPU:
1257
1257
  ret += _(' -- Bathymetry values will be set to max(bath, deck)\n')
1258
1258
  ret += _(' -- These cells will remain impassable until the water level rises above them\n')
1259
1259
  bridge_roof.array.data[mask] = 99999.
1260
- bathymetry.array.data[mask] = np.maximum(bridge_deck.array.data[mask], bathymetry.array.data[mask])
1260
+ bathymetry.array.data[mask] = np.maximum(bridge_deck.array.data[mask], bathymetry.array.data[mask])
1261
1261
 
1262
1262
  mask = np.where(bridge_roof.array.data - bathymetry.array.data < threshold)
1263
1263
  if mask[0].shape[0] > 0:
@@ -1273,7 +1273,7 @@ class Config_Manager_2D_GPU:
1273
1273
  logging.warning(ret)
1274
1274
 
1275
1275
  return ret
1276
-
1276
+
1277
1277
  def create_simulation(self,
1278
1278
  dir:Path,
1279
1279
  idx_hydros:list[int] = [-1],
@@ -1576,7 +1576,7 @@ class Config_Manager_2D_GPU:
1576
1576
  for cursim in allsims:
1577
1577
  cursim:Path
1578
1578
  batch += 'cd {}\n'.format(str(cursim.parent))
1579
- batch += str(cursim.name) + '\n'
1579
+ batch += 'call ' + str(cursim.name) + '\n'
1580
1580
 
1581
1581
  with open(path, 'w', encoding='utf-8') as f:
1582
1582
  f.write(batch)