wolfhece 2.1.100__py3-none-any.whl → 2.1.102__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/wolf_array.py CHANGED
@@ -22,6 +22,7 @@ import logging
22
22
  import json
23
23
  import tempfile
24
24
  from pathlib import Path
25
+ from tqdm import tqdm
25
26
 
26
27
  try:
27
28
  from OpenGL.GL import *
@@ -115,6 +116,7 @@ WOLF_ARRAY_CSR_DOUBLE = 5
115
116
  WOLF_ARRAY_FULL_INTEGER = 6
116
117
  WOLF_ARRAY_FULL_SINGLE_3D = 7
117
118
  WOLF_ARRAY_FULL_INTEGER8 = 8
119
+ WOLF_ARRAY_FULL_UINTEGER8 = 88
118
120
 
119
121
  WOLF_ARRAY_MB_SINGLE = 3
120
122
  WOLF_ARRAY_MB_INTEGER = 9
@@ -866,7 +868,7 @@ class header_wolf():
866
868
  elif dtype == np.int16:
867
869
  self.wolftype = WOLF_ARRAY_FULL_INTEGER16
868
870
  elif dtype == np.uint8:
869
- self.wolftype = WOLF_ARRAY_FULL_INTEGER8
871
+ self.wolftype = WOLF_ARRAY_FULL_UINTEGER8
870
872
  elif dtype == np.int8:
871
873
  self.wolftype = WOLF_ARRAY_FULL_INTEGER8
872
874
  else:
@@ -999,7 +1001,9 @@ class header_wolf():
999
1001
  :param forceupdate: if True, the file is rewritten even if it already exists
1000
1002
  """
1001
1003
 
1002
- assert wolftype in [WOLF_ARRAY_CSR_DOUBLE, WOLF_ARRAY_FULL_SINGLE, WOLF_ARRAY_FULL_DOUBLE, WOLF_ARRAY_SYM_DOUBLE, WOLF_ARRAY_FULL_LOGICAL, WOLF_ARRAY_CSR_DOUBLE, WOLF_ARRAY_FULL_INTEGER, WOLF_ARRAY_FULL_SINGLE_3D, WOLF_ARRAY_FULL_INTEGER8, WOLF_ARRAY_MB_SINGLE, WOLF_ARRAY_MB_INTEGER, WOLF_ARRAY_FULL_INTEGER16, WOLF_ARRAY_MNAP_INTEGER, WOLF_ARRAY_FULL_INTEGER16_2], _('The type of array is not correct')
1004
+ assert wolftype in [WOLF_ARRAY_CSR_DOUBLE, WOLF_ARRAY_FULL_SINGLE, WOLF_ARRAY_FULL_DOUBLE, WOLF_ARRAY_SYM_DOUBLE, WOLF_ARRAY_FULL_LOGICAL,
1005
+ WOLF_ARRAY_CSR_DOUBLE, WOLF_ARRAY_FULL_INTEGER, WOLF_ARRAY_FULL_SINGLE_3D, WOLF_ARRAY_FULL_INTEGER8, WOLF_ARRAY_FULL_UINTEGER8,
1006
+ WOLF_ARRAY_MB_SINGLE, WOLF_ARRAY_MB_INTEGER, WOLF_ARRAY_FULL_INTEGER16, WOLF_ARRAY_MNAP_INTEGER, WOLF_ARRAY_FULL_INTEGER16_2], _('The type of array is not correct')
1003
1007
 
1004
1008
  if not os.path.exists(filename) or forceupdate:
1005
1009
  with open(filename,'w') as f:
@@ -1685,11 +1689,11 @@ class Ops_Array(wx.Frame):
1685
1689
 
1686
1690
  self.m_button7 = wx.Button(self.Interpolation, wx.ID_ANY, _("Stage/Volume/Surface evaluation"), wx.DefaultPosition,
1687
1691
  wx.DefaultSize, 0)
1688
- self.m_button7.SetToolTip(_('Evaluate stage-volume-surface relationship. \n Results : plots and arrays saved on disk'))
1692
+ self.m_button7.SetToolTip(_('Evaluate stage-volume-surface relationship.\nResults : csv and array saved on disk\n\n CAUTION : This function will be applied only on the selected area except if you select "all".\nIn the latter case, the computation time could be long if the array are very large.'))
1689
1693
 
1690
1694
  if self.parentarray.nb_blocks>0:
1691
1695
  self.m_button7.Disable()
1692
- self.m_button7.SetToolTip(_('Evaluate stage-volume-surface relationship. \n Results : plots and arrays saved on disk\n\nThis function is not available for multi-block arrays.'))
1696
+ self.m_button7.SetToolTip(_('Evaluate stage-volume-surface relationship.\nResults : arrays and csv file saved on disk\n\nThis function is not available for multi-block arrays.'))
1693
1697
 
1694
1698
  gSizer1.Add(self.m_button7, 0, wx.EXPAND)
1695
1699
  self.m_button7.Bind(wx.EVT_BUTTON, self.volumesurface)
@@ -2674,17 +2678,29 @@ class Ops_Array(wx.Frame):
2674
2678
 
2675
2679
  # operator value
2676
2680
  opval = self.opvalue.GetValue()
2677
- if opval.lower() == 'null' or opval.lower() == 'nan':
2681
+ if opval.lower() == 'null' or opval.lower() == 'nan' or opval.lower() == 'nul':
2678
2682
  curopvalue = self.parentarray.nullvalue
2679
2683
  else:
2680
- curopvalue = float(opval)
2684
+ try:
2685
+ tmp_float = float(opval)
2686
+ except:
2687
+ logging.error('Error in float conversion - Do you try to set null value ? - Accepted values : "Null" or "NaN"')
2688
+ return
2689
+
2690
+ curopvalue = tmp_float
2681
2691
 
2682
2692
  # condition value
2683
2693
  curcondvalue = self.condvalue.GetValue()
2684
- if curcondvalue.lower() == 'null' or curcondvalue.lower() == 'nan':
2694
+ if curcondvalue.lower() == 'null' or curcondvalue.lower() == 'nan' or curcondvalue.lower() == 'nul':
2685
2695
  curcondvalue = self.parentarray.nullvalue
2686
2696
  else:
2687
- curcondvalue = float(curcondvalue)
2697
+ try:
2698
+ tmp_float = float(curcondvalue)
2699
+ except:
2700
+ logging.error('Error in float conversion - Do you try to set null value ? - Accepted values : "Null" or "NaN"')
2701
+ return
2702
+
2703
+ curcondvalue = tmp_float
2688
2704
 
2689
2705
  self.parentarray.SelectionData.treat_select(curop, curcond, curopvalue, curcondvalue)
2690
2706
 
@@ -2694,8 +2710,16 @@ class Ops_Array(wx.Frame):
2694
2710
  curop = self.choiceop.GetSelection()
2695
2711
  curcond = self.condition.GetSelection()
2696
2712
 
2697
- curopvalue = float(self.opvalue.GetValue())
2698
- curcondvalue = float(self.condvalue.GetValue())
2713
+ try:
2714
+ curopvalue = float(self.opvalue.GetValue())
2715
+ except:
2716
+ logging.error('Error in float conversion - operator')
2717
+ return
2718
+ try:
2719
+ curcondvalue = float(self.condvalue.GetValue())
2720
+ except:
2721
+ logging.error('Error in float conversion - condition')
2722
+ return
2699
2723
 
2700
2724
  self.parentarray.SelectionData.mask_condition(curop, curcond, curopvalue, curcondvalue)
2701
2725
  self.refresh_array()
@@ -4464,8 +4488,10 @@ class SelectionData():
4464
4488
  if self.nb == 0:
4465
4489
  return None
4466
4490
 
4467
- newarray = WolfArray()
4491
+ if self.myselection == 'all':
4492
+ return WolfArray(mold=self.parent)
4468
4493
 
4494
+ newarray = WolfArray()
4469
4495
  lochead = self._get_header()
4470
4496
  if lochead is None:
4471
4497
  logging.error(_('Error in get_newarray !'))
@@ -4588,33 +4614,35 @@ class SelectionData():
4588
4614
 
4589
4615
  if self.nb == 0 or self.myselection == 'all':
4590
4616
  myarray = array1
4591
- axs = myarray.volume_estimation()
4617
+ fig, axs = myarray.volume_estimation()
4592
4618
 
4593
4619
  myarray = array2
4594
- axs = myarray.volume_estimation(axs)
4620
+ fig, axs = myarray.volume_estimation(axs)
4595
4621
  else:
4596
4622
  myarray = array1.mngselection.get_newarray()
4597
- axs = myarray.volume_estimation()
4623
+ fig, axs = myarray.volume_estimation()
4598
4624
 
4599
4625
  myarray = array2.mngselection.get_newarray()
4600
- axs = myarray.volume_estimation(axs)
4626
+ fig, axs = myarray.volume_estimation(axs)
4601
4627
  else:
4602
4628
  if len(self.parent.mngselection.myselection) == 0 or self.parent.mngselection.myselection == 'all':
4603
4629
  myarray = self.parent
4604
4630
  else:
4605
4631
  myarray = self.parent.mngselection.get_newarray()
4632
+ myarray.SelectionData.selections = self.parent.mngselection.selections.copy()
4606
4633
 
4607
- myarray.volume_estimation()
4634
+ fig, axs = myarray.volume_estimation()
4608
4635
  else:
4609
4636
  if self.nb == 0 or self.myselection == 'all':
4610
4637
  myarray = self.parent
4611
4638
  else:
4612
4639
  myarray = self.get_newarray()
4640
+ myarray.SelectionData.selections = self.selections.copy()
4613
4641
 
4614
- myarray.volume_estimation()
4642
+ fig, axs = myarray.volume_estimation()
4615
4643
 
4616
4644
  if show:
4617
- plt.show()
4645
+ fig.show()
4618
4646
 
4619
4647
  class SelectionDataMB(SelectionData):
4620
4648
  """ Extension of SelectionData to manage multiple blocks """
@@ -4877,6 +4905,7 @@ class WolfArray(Element_To_Draw, header_wolf):
4877
4905
  plotted:bool = False,
4878
4906
  need_for_wx:bool = False,
4879
4907
  mask_source:np.ndarray = None,
4908
+ np_source:np.ndarray = None,
4880
4909
  ) -> None:
4881
4910
  """
4882
4911
  Constructor of the WolfArray class
@@ -4895,6 +4924,7 @@ class WolfArray(Element_To_Draw, header_wolf):
4895
4924
  :param plotted: True = will be plotted if required by the mapviewer
4896
4925
  :param need_for_wx: True = a wxApp is required (if no application is underway --> Error)
4897
4926
  :param mask_source: mask to link to the data
4927
+ :param np_source: numpy array to link to the data
4898
4928
 
4899
4929
  """
4900
4930
  try:
@@ -4982,7 +5012,16 @@ class WolfArray(Element_To_Draw, header_wolf):
4982
5012
  if self.nb_blocks>0:
4983
5013
  self.myblocks = {}
4984
5014
 
4985
- self.allocate_ressources()
5015
+ if np_source is None:
5016
+ self.allocate_ressources()
5017
+ else:
5018
+ assert np_source.shape == (self.nbx, self.nby), _('Shape of np_source is not compatible with header')
5019
+
5020
+ if self.dtype != np_source.dtype:
5021
+ logging.warning(_('dtype of np_source is not compatible with header -- Conversion will be done'))
5022
+ np_source = np_source.astype(self.dtype)
5023
+
5024
+ self.array = ma.MaskedArray(np_source, mask= np_source[:,:] == self.nullvalue, copy=False, order='C')
4986
5025
 
4987
5026
  # # FIXME Why not initialize with nullvalue ?
4988
5027
  # self.array = ma.MaskedArray(np.ones((self.nbx, self.nby), order='F', dtype=self.dtype))
@@ -5054,6 +5093,7 @@ class WolfArray(Element_To_Draw, header_wolf):
5054
5093
  else:
5055
5094
  self.init_from_new(new)
5056
5095
 
5096
+
5057
5097
  self.add_ops_sel() # Ajout d'un gestionnaire de sélection et d'opérations
5058
5098
 
5059
5099
  def set_opacity(self, alpha:float):
@@ -5094,7 +5134,7 @@ class WolfArray(Element_To_Draw, header_wolf):
5094
5134
  return size * 4
5095
5135
  elif self.wolftype in [WOLF_ARRAY_FULL_INTEGER16, WOLF_ARRAY_FULL_INTEGER16_2]:
5096
5136
  return size * 2
5097
- elif self.wolftype == WOLF_ARRAY_FULL_INTEGER8:
5137
+ elif self.wolftype in [WOLF_ARRAY_FULL_INTEGER8, WOLF_ARRAY_FULL_UINTEGER8]:
5098
5138
  return size
5099
5139
  else:
5100
5140
  return size * 4
@@ -5355,6 +5395,8 @@ class WolfArray(Element_To_Draw, header_wolf):
5355
5395
  dtype = np.int16
5356
5396
  elif self.wolftype == WOLF_ARRAY_FULL_INTEGER8:
5357
5397
  dtype = np.int8
5398
+ elif self.wolftype == WOLF_ARRAY_FULL_UINTEGER8:
5399
+ dtype = np.uint8
5358
5400
  elif self.wolftype == WOLF_ARRAY_FULL_LOGICAL:
5359
5401
  dtype = np.int16
5360
5402
 
@@ -5374,6 +5416,8 @@ class WolfArray(Element_To_Draw, header_wolf):
5374
5416
  dtype = gdal.GDT_Int16
5375
5417
  elif self.wolftype == WOLF_ARRAY_FULL_INTEGER8:
5376
5418
  dtype = gdal.GDT_Byte
5419
+ elif self.wolftype == WOLF_ARRAY_FULL_UINTEGER8:
5420
+ dtype = gdal.GDT_Byte
5377
5421
  elif self.wolftype == WOLF_ARRAY_FULL_LOGICAL:
5378
5422
  dtype = gdal.GDT_Int16
5379
5423
 
@@ -5404,6 +5448,8 @@ class WolfArray(Element_To_Draw, header_wolf):
5404
5448
  dtype = _('int16 - 2 bytes per values')
5405
5449
  elif self.wolftype == WOLF_ARRAY_FULL_INTEGER8:
5406
5450
  dtype = _('int8 - 1 byte per values')
5451
+ elif self.wolftype == WOLF_ARRAY_FULL_UINTEGER8:
5452
+ dtype = _('uint8 - 1 byte per values')
5407
5453
  elif self.wolftype == WOLF_ARRAY_FULL_LOGICAL:
5408
5454
  dtype = _('int16 - 2 bytes per values')
5409
5455
 
@@ -6062,7 +6108,7 @@ class WolfArray(Element_To_Draw, header_wolf):
6062
6108
  - uniquement dans les mailles sélectionnées si elles existent
6063
6109
  - dans les mailles contenues dans le polygone sinon
6064
6110
 
6065
- On utilise ensuite "griddata" pour interpoler les altitudes des mailles
6111
+ On utilise ensuite "griddata" de Scipy pour interpoler les altitudes des mailles
6066
6112
  depuis les vertices 3D du polygone
6067
6113
  """
6068
6114
 
@@ -6125,17 +6171,27 @@ class WolfArray(Element_To_Draw, header_wolf):
6125
6171
  self.array.data[allij[:, 0], allij[:, 1]] = newz
6126
6172
 
6127
6173
  def interpolate_on_polylines(self, working_zone:zone, usemask=True):
6174
+ """ Interpolation sous toutes les polylignes d'une même zone """
6128
6175
 
6129
6176
  for curvec in working_zone.myvectors:
6130
6177
  self.interpolate_on_polyline(curvec, usemask)
6131
6178
 
6132
6179
 
6133
- def interpolate_on_cloud(self, xy:np.ndarray, z:np.ndarray, method='linear'):
6180
+ def interpolate_on_cloud(self, xy:np.ndarray, z:np.ndarray, method:Literal['linear', 'nearest', 'cubic']= 'linear'):
6134
6181
  """
6135
- See : https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.griddata.html
6182
+ Interpolation sur un nuage de points.
6183
+
6184
+ L'interpolation a lieu :
6185
+ - uniquement dans les mailles sélectionnées si elles existent
6186
+ - dans les mailles contenues dans le polygone convexe contenant les points sinon
6136
6187
 
6137
- method == nearest, linear or cubic
6188
+ Using griddata from Scipy.
6138
6189
 
6190
+ :param xy: numpy.array of vertices - shape (n,2)
6191
+ :param z: numpy.array of values - shape (n,)
6192
+ :param method: method for the interpolation -- 'nearest', 'linear' or 'cubic'
6193
+
6194
+ See : https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.griddata.html
6139
6195
  """
6140
6196
 
6141
6197
  if self.mngselection.myselection == [] or self.mngselection.myselection == 'all':
@@ -6159,18 +6215,36 @@ class WolfArray(Element_To_Draw, header_wolf):
6159
6215
 
6160
6216
  self.reset_plot()
6161
6217
 
6162
- def interpolate_on_triangulation(self, coords, triangles, grid_x=None, grid_y = None, mask_tri=None, interp_method = 'matplotlib'):
6163
- import matplotlib.tri as mtri
6218
+ def interpolate_on_triangulation(self, coords, triangles,
6219
+ grid_x=None, grid_y = None,
6220
+ mask_tri=None, interp_method:Literal['matplotlib','scipy'] = 'matplotlib'):
6164
6221
  """
6165
- See : https://matplotlib.org/stable/gallery/images_contours_and_fields/triinterp_demo.html
6222
+ Interpolation sur une triangulation.
6223
+
6224
+ L'interpolation a lieu :
6225
+ - uniquement dans les mailles sélectionnées si elles existent
6226
+ - dans les mailles contenues dans la triangulation sinon
6227
+
6228
+ Matplotlib is used by default, but Scipy(griddata) can be used as well. If Matplotlib crashes, try with Scipy.
6229
+ Matplotlib is more strict on the quality of the triangulation.
6166
6230
 
6167
- method == linear
6231
+ :param coords: numpy.array of vertices - shape (n,3)
6232
+ :param triangles: numpy.array of triangles - shape (m,3)
6233
+ :param grid_x: numpy.array of x values where the interpolation will be done -- if None, the grid is created from the array
6234
+ :param grid_y: numpy.array of y values where the interpolation will be done -- if None, the grid is created from the array
6235
+ :param mask_tri: numpy.array of mask for the triangles
6236
+ :param interp_method: method for the interpolation -- 'matplotlib' or 'scipy'
6237
+
6238
+ For matplotlib algo, see : https://matplotlib.org/stable/gallery/images_contours_and_fields/triinterp_demo.html
6239
+ For scipy algo, see : https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.griddata.html
6168
6240
 
6169
6241
  """
6170
6242
 
6171
6243
 
6172
6244
  if interp_method =='matplotlib':
6173
6245
 
6246
+ import matplotlib.tri as mtri
6247
+
6174
6248
  use_scipy=False
6175
6249
 
6176
6250
  try:
@@ -6291,10 +6365,16 @@ class WolfArray(Element_To_Draw, header_wolf):
6291
6365
  self.reset_plot()
6292
6366
  return
6293
6367
 
6294
- def import_from_gltf(self, fn:str='', fnpos:str='', interp_method:Literal['matplotlib','numpy'] = 'matplotlib'):
6368
+ def import_from_gltf(self, fn:str='', fnpos:str='', interp_method:Literal['matplotlib','scipy'] = 'matplotlib'):
6295
6369
  """
6296
- interp_method == 'matplotlib' or 'griddata'
6370
+ Import from GLTF/GLB format
6371
+
6372
+ :param fn: filename
6373
+ :param fnpos: filename for the position's information
6374
+ :param interp_method: method for the interpolation -- 'matplotlib' or 'scipy'
6375
+
6297
6376
  """
6377
+ #FIXME : add the possibility to use PyVista
6298
6378
 
6299
6379
  if fn == '' or fnpos == '':
6300
6380
  logging.info(_('Retry !! -- Bad files'))
@@ -6459,7 +6539,6 @@ class WolfArray(Element_To_Draw, header_wolf):
6459
6539
  triangles.append([[i + decal, i + decal + 1, i + decal + nby] for i in range(nby - 1)])
6460
6540
  triangles.append([[i + decal + nby, i + decal + 1, i + decal + nby + 1] for i in range(nby - 1)])
6461
6541
 
6462
- from tqdm import tqdm
6463
6542
  for k in tqdm(range(1, nbx - 1)):
6464
6543
  decal = k * nby
6465
6544
  triangles.append([[i + decal, i + decal + 1, i + decal + nby] for i in range(nby - 1)])
@@ -6499,7 +6578,7 @@ class WolfArray(Element_To_Draw, header_wolf):
6499
6578
 
6500
6579
  return mylap
6501
6580
 
6502
- def volume_estimation(self, axs=None):
6581
+ def volume_estimation(self, axs:plt.Axes= None):
6503
6582
  """ Estimation of the volume of the selected zone """
6504
6583
 
6505
6584
  vect = self.array[np.logical_not(self.array.mask)].flatten()
@@ -6529,58 +6608,125 @@ class WolfArray(Element_To_Draw, header_wolf):
6529
6608
  deltaz = (zmax - zmin) / nb
6530
6609
  curz = zmin
6531
6610
  nbgroupement = []
6532
- longueur = []
6611
+ labeled_areas = []
6533
6612
  stockage = []
6534
6613
  z = []
6535
6614
 
6536
- dlg = wx.MessageDialog(None, _("Would you like to calculate relationships on the basis of the largest area ? \n if Yes, no guarantee on the volume increase"), style = wx.YES_NO|wx.YES_DEFAULT)
6615
+ methods = [_("All cells below the elevation (even if cells are disconnected)"),
6616
+ _("Only the largest connected area below the elevation (not necessarily the same for each elevation)"),
6617
+ _("Only the area below the elevation (if containing the cells stored in memory selection)")]
6618
+
6619
+ keys_select = list(self.SelectionData.selections.keys())
6620
+ if len(keys_select) == 0:
6621
+ methods = methods[:2]
6622
+ use_memory = False
6623
+
6624
+ dlg = wx.SingleChoiceDialog(None, _("Choose a method for selecting the area to integrate"), _("Labeling?"), methods)
6537
6625
  ret = dlg.ShowModal()
6538
- if ret == wx.ID_YES:
6539
- labeled= True
6540
- dlg.Destroy()
6626
+
6627
+ if ret == wx.ID_CANCEL:
6628
+ dlg.Destroy()
6629
+ return
6630
+
6631
+ if dlg.GetSelection() == 0:
6632
+ labeled = False
6633
+ else:
6634
+ labeled = True
6635
+ if dlg.GetSelection() == 1:
6636
+ use_memory = False
6637
+ else:
6638
+ if len(keys_select) >1:
6639
+ dlg = wx.SingleChoiceDialog(None, _("Choose a memory selection"), _("Memory selection?"), keys_select)
6640
+ ret = dlg.ShowModal()
6641
+
6642
+ if ret == wx.ID_CANCEL:
6643
+ dlg.Destroy()
6644
+ return
6645
+
6646
+ key = keys_select[dlg.GetSelection()]
6647
+ else:
6648
+ key = keys_select[0]
6649
+
6650
+ xy_key = self.SelectionData.selections[key]['select']
6651
+ if len(xy_key) == 0:
6652
+ logging.error(_('Empty selection'))
6653
+ return
6654
+
6655
+ ij_key = self.xy2ij_np(xy_key)
6656
+
6657
+ use_memory = True
6541
6658
 
6542
6659
  extensionmax = WolfArray(mold=self)
6543
6660
  extensionmax.array[:, :] = 0.
6544
6661
 
6545
6662
  if labeled:
6546
- for i in range(nb + 1):
6547
- logging.info(_(' Step ') +str(i))
6663
+ for i in tqdm(range(nb + 1)):
6548
6664
  z.append(curz)
6549
6665
 
6666
+ # Compute difference between the array and the current elevation
6550
6667
  if i == 0:
6551
6668
  diff = self.array - (curz + 1.e-3)
6552
6669
  else:
6553
6670
  diff = self.array - curz
6554
6671
 
6672
+ # Keep only the negative values
6555
6673
  diff[diff > 0] = 0.
6556
6674
  diff.data[diff.mask] = 0.
6557
- labeled_array, num_features = label(diff.data)
6558
- labeled_array = ma.asarray(labeled_array)
6559
- labeled_array.mask = self.array.mask
6560
-
6561
- # groupement = labeled_array
6562
- # groupement[labeled_array.mask] = 0
6563
- # nbgroupement.append(num_features)
6564
- # for j in range(1, nbgroupement[i] + 1):
6565
- # taille = (np.sum(groupement[groupement == j]) // j)
6566
- # longueur.append([taille, j])
6567
6675
 
6676
+ if np.count_nonzero(diff < 0.) > 1:
6677
+ # More than one cell below the elevation
6678
+
6679
+ # Labeling of the cells below the elevation
6680
+ labeled_array, num_features = label(diff.data)
6681
+ # Applying the same mask as the original array
6682
+ labeled_array = ma.asarray(labeled_array)
6683
+ labeled_array.mask = self.array.mask
6684
+
6685
+ if use_memory:
6686
+ # Use only the labeled areas containing the cells stored in memory selection
6687
+ labeled_areas = []
6688
+ for curij in ij_key:
6689
+ labeled_areas.append(labeled_array[curij[0], curij[1]])
6690
+
6691
+ # Remove masked value
6692
+ labeled_areas = [x for x in labeled_areas if x is not ma.masked]
6693
+ # Remove duplicates
6694
+ labeled_areas = list(set(labeled_areas))
6695
+
6696
+ for curarea in labeled_areas:
6697
+ if curarea ==0:
6698
+ volume = 0.
6699
+ surface = 0.
6700
+ continue
6701
+
6702
+ # Search
6703
+ mask = labeled_array == curarea
6704
+ area = np.where(mask)
6705
+ volume = -self.dx * self.dy * np.sum(diff[area])
6706
+ surface = self.dx * self.dy * len(area[0])
6707
+ extensionmax.array[np.logical_and(mask, extensionmax.array[:, :] == 0.)] = float(i + 1)
6568
6708
 
6569
- longueur = list(sum_labels(np.ones(labeled_array.shape, dtype=np.int32), labeled_array, range(1, num_features+1)))
6570
-
6571
- longueur.sort(key=lambda x: x[0], reverse=True)
6709
+ else:
6710
+ labeled_areas = list(sum_labels(np.ones(labeled_array.shape, dtype=np.int32), labeled_array, range(1, num_features+1)))
6711
+ labeled_areas = [[x, y] for x, y in zip(labeled_areas, range(1, num_features+1))]
6712
+ labeled_areas.sort(key=lambda x: x[0], reverse=True)
6713
+ jmax = labeled_areas[0][1]
6714
+ nbmax = labeled_areas[0][0]
6715
+
6716
+ volume = -self.dx * self.dy * np.sum(diff[labeled_array == jmax])
6717
+ surface = self.dx * self.dy * nbmax
6718
+ extensionmax.array[np.logical_and(labeled_array == jmax, extensionmax.array[:, :] == 0.)] = float(i + 1)
6719
+ else:
6720
+ # Only one cell below the elevation
6721
+ volume = -self.dx * self.dy * np.sum(diff)
6722
+ surface = self.dx * self.dy * np.count_nonzero(diff<0.)
6723
+ extensionmax.array[np.logical_and(diff[:,:]<0., extensionmax.array[:, :] == 0.)] = float(i + 1)
6572
6724
 
6573
- jmax = longueur[0][1]
6574
- nbmax = longueur[0][0]
6575
- volume = -self.dx * self.dy * np.sum(diff[labeled_array == jmax])
6576
- surface = self.dx * self.dy * nbmax
6577
6725
  stockage.append([volume, surface])
6578
6726
  curz += deltaz
6579
6727
 
6580
- extensionmax.array[np.logical_and(labeled_array == jmax, extensionmax.array[:, :] == 0.)] = float(i + 1)
6581
6728
  else:
6582
- for i in range(nb + 1):
6583
- logging.info(_(' Step ') +str(i))
6729
+ for i in tqdm(range(nb + 1)):
6584
6730
  z.append(curz)
6585
6731
 
6586
6732
  if i == 0:
@@ -6597,7 +6743,7 @@ class WolfArray(Element_To_Draw, header_wolf):
6597
6743
 
6598
6744
  extensionmax.array[np.logical_and(diff[:,:]<0., extensionmax.array[:, :] == 0.)] = float(i + 1)
6599
6745
 
6600
- dlg = wx.FileDialog(None, _('Choose filename'), wildcard='bin (*.bin)|*.bin|All (*.*)|*.*', style=wx.FD_SAVE)
6746
+ dlg = wx.FileDialog(None, _('Choose filename for zoning result'), wildcard='bin (*.bin)|*.bin|tif (*.tif)|*.tif|All (*.*)|*.*', style=wx.FD_SAVE)
6601
6747
  ret = dlg.ShowModal()
6602
6748
  if ret == wx.ID_CANCEL:
6603
6749
  dlg.Destroy()
@@ -6611,22 +6757,25 @@ class WolfArray(Element_To_Draw, header_wolf):
6611
6757
 
6612
6758
  if axs is None:
6613
6759
  fig, axs = plt.subplots(1, 2, tight_layout=True)
6760
+ else:
6761
+ fig = axs[0].get_figure()
6762
+
6614
6763
  axs[0].plot(z, [x[0] for x in stockage])
6615
6764
  axs[0].scatter(z, [x[0] for x in stockage])
6616
6765
  axs[0].set_xlabel(_("Elevation [m]"), size=15)
6617
- axs[0].set_ylabel(_("Volume [m^3]"), size=15)
6766
+ axs[0].set_ylabel(_("Volume [$m^3$]"), size=15)
6618
6767
  axs[1].step(z, [x[1] for x in stockage], where='post')
6619
6768
  axs[1].scatter(z, [x[1] for x in stockage])
6620
6769
  axs[1].set_xlabel(_("Elevation [m]"), size=15)
6621
- axs[1].set_ylabel(_("Surface [m^2]"), size=15)
6622
- plt.suptitle(_("Retention capacity of the selected zone"), fontsize=20)
6770
+ axs[1].set_ylabel(_("Surface [$m^2$]"), size=15)
6771
+ fig.suptitle(_("Retention capacity of the selected zone"), fontsize=20)
6623
6772
 
6624
6773
  with open(fn[:-4] + '_hvs.txt', 'w') as f:
6625
- f.write('H [m]\tZ [m DNG]\tVolume [m^3]\tSurface [m^2]\n')
6774
+ f.write('H [m]\tZ [m DNG]\tVolume [$m^3$]\tSurface [$m^2$]\n')
6626
6775
  for curz, (curv, curs) in zip(z, stockage):
6627
6776
  f.write('{}\t{}\t{}\t{}\n'.format(curz - zmin, curz, curv, curs))
6628
6777
 
6629
- return axs
6778
+ return fig, axs
6630
6779
 
6631
6780
  def paste_all(self, fromarray:"WolfArray", mask_after:bool=True):
6632
6781
  """ Paste all the values from another WolfArray """
@@ -6737,6 +6886,8 @@ class WolfArray(Element_To_Draw, header_wolf):
6737
6886
  dtype = np.int16
6738
6887
  elif self.wolftype == WOLF_ARRAY_FULL_INTEGER8:
6739
6888
  dtype = np.int8
6889
+ elif self.wolftype == WOLF_ARRAY_FULL_UINTEGER8:
6890
+ dtype = np.uint8
6740
6891
 
6741
6892
  self.dx = myhead.dx
6742
6893
  self.dy = myhead.dy
@@ -6907,20 +7058,24 @@ class WolfArray(Element_To_Draw, header_wolf):
6907
7058
  self.plotted = False
6908
7059
 
6909
7060
  if unload and self.filename != '':
6910
- if askquestion and self.wx_exists:
6911
- dlg = wx.MessageDialog(None,
6912
- _('Do you want to unload data? \n If YES, the data will be reloaded from file once checekd \n If not saved, modifications will be lost !!'),
6913
- style=wx.YES_NO)
6914
- ret = dlg.ShowModal()
6915
- if ret == wx.ID_YES:
6916
- unload=True
7061
+ if Path(self.filename).exists():
7062
+ # An array can exists with a filename but no written data on disk
7063
+ # In this case, we don't want to delete the data in memory
6917
7064
 
6918
- if unload:
6919
- self.delete_lists()
6920
- self.array = np.zeros([1])
6921
- if VERSION_RGB==1 : self.rgb = None
6922
- self.loaded = False
6923
- return
7065
+ if askquestion and self.wx_exists:
7066
+ dlg = wx.MessageDialog(None,
7067
+ _('Do you want to unload data? \n If YES, the data will be reloaded from file once checekd \n If not saved, modifications will be lost !!'),
7068
+ style=wx.YES_NO)
7069
+ ret = dlg.ShowModal()
7070
+ if ret == wx.ID_YES:
7071
+ unload=True
7072
+
7073
+ if unload:
7074
+ self.delete_lists()
7075
+ self.array = np.zeros([1])
7076
+ if VERSION_RGB==1 : self.rgb = None
7077
+ self.loaded = False
7078
+ return
6924
7079
 
6925
7080
  if not forceresetOGL:
6926
7081
  if askquestion and self.wx_exists:
@@ -7556,6 +7711,9 @@ class WolfArray(Element_To_Draw, header_wolf):
7556
7711
  elif locarray.dtype == np.int8:
7557
7712
  self.wolftype = WOLF_ARRAY_FULL_INTEGER8
7558
7713
  logging.warning(_('Data type changed to int8'))
7714
+ elif locarray.dtype == np.uint8:
7715
+ self.wolftype = WOLF_ARRAY_FULL_UINTEGER8
7716
+ logging.warning(_('Data type changed to uint8'))
7559
7717
  else:
7560
7718
  logging.error(_('Unsupported type in numpy file -- Abort wrting header file'))
7561
7719
  writing_header = False
@@ -7863,6 +8021,9 @@ class WolfArray(Element_To_Draw, header_wolf):
7863
8021
  elif self.wolftype in [WOLF_ARRAY_FULL_INTEGER8]:
7864
8022
  locarray = np.frombuffer(f.read(self.nbx * self.nby * 2), dtype=np.int8)
7865
8023
  self.array = ma.masked_array(locarray.copy(), dtype=np.int8)
8024
+ elif self.wolftype in [WOLF_ARRAY_FULL_UINTEGER8]:
8025
+ locarray = np.frombuffer(f.read(self.nbx * self.nby * 2), dtype=np.uint8)
8026
+ self.array = ma.masked_array(locarray.copy(), dtype=np.uint8)
7866
8027
 
7867
8028
  if self.nbdims == 2:
7868
8029
  self.array = self.array.reshape(self.nbx, self.nby, order='F')
@@ -8075,6 +8236,8 @@ class WolfArray(Element_To_Draw, header_wolf):
8075
8236
  value=np.int16(value)
8076
8237
  elif self.wolftype in [WOLF_ARRAY_FULL_INTEGER8]:
8077
8238
  value=np.int8(value)
8239
+ elif self.wolftype in [WOLF_ARRAY_FULL_UINTEGER8]:
8240
+ value=np.uint8(value)
8078
8241
  except:
8079
8242
  logging.error(_('Type not supported : {} - {}'.format(value, type(value))))
8080
8243
  logging.warning(_('Masking operation compromised'))
@@ -8431,7 +8594,7 @@ class WolfArray(Element_To_Draw, header_wolf):
8431
8594
 
8432
8595
  if VERSION_RGB==1 :
8433
8596
  if self.nbx * self.nby > 1_000_000 : logging.info(_('Computing colors'))
8434
- if self.wolftype not in [WOLF_ARRAY_FULL_SINGLE, WOLF_ARRAY_FULL_INTEGER8]:
8597
+ if self.wolftype not in [WOLF_ARRAY_FULL_SINGLE, WOLF_ARRAY_FULL_INTEGER8, WOLF_ARRAY_FULL_UINTEGER8]:
8435
8598
  # FIXME: Currently, only some types are supported in Cython/OpenGL library
8436
8599
  self._tmp_float32 = self.array.astype(dtype=np.float32)
8437
8600
  self.rgb = self.mypal.get_rgba(self._tmp_float32)
@@ -8442,6 +8605,7 @@ class WolfArray(Element_To_Draw, header_wolf):
8442
8605
  elif VERSION_RGB in [2 ,3]:
8443
8606
  if self.wolftype not in [WOLF_ARRAY_FULL_SINGLE,
8444
8607
  WOLF_ARRAY_FULL_INTEGER8,
8608
+ WOLF_ARRAY_FULL_UINTEGER8,
8445
8609
  WOLF_ARRAY_FULL_INTEGER16,
8446
8610
  WOLF_ARRAY_FULL_INTEGER16_2,
8447
8611
  WOLF_ARRAY_FULL_INTEGER,
@@ -8691,6 +8855,14 @@ class WolfArray(Element_To_Draw, header_wolf):
8691
8855
  elif self.nbnotnull > 0:
8692
8856
  wolfogl.addmeall_int8_pal(self.array, self.mypal.colorsflt, self.mypal.values, ox, oy, dx, dy, jstart,
8693
8857
  jend, istart, iend, cursize, self.nullvalue, self.alpha, int(self.mypal.interval_cst))
8858
+ elif self.wolftype == WOLF_ARRAY_FULL_UINTEGER8:
8859
+ if self.nbnotnull != self.nbx * self.nby:
8860
+ if self.nbnotnull > 0:
8861
+ wolfogl.addme_uint8_pal(self.array, self.mypal.colorsflt, self.mypal.values, ox, oy, dx, dy, jstart,
8862
+ jend, istart, iend, cursize, self.nullvalue, self.alpha, int(self.mypal.interval_cst))
8863
+ elif self.nbnotnull > 0:
8864
+ wolfogl.addmeall_uint8_pal(self.array, self.mypal.colorsflt, self.mypal.values, ox, oy, dx, dy, jstart,
8865
+ jend, istart, iend, cursize, self.nullvalue, self.alpha, int(self.mypal.interval_cst))
8694
8866
  elif self.wolftype in [WOLF_ARRAY_FULL_INTEGER16, WOLF_ARRAY_FULL_INTEGER16_2]:
8695
8867
  if self.nbnotnull != self.nbx * self.nby:
8696
8868
  if self.nbnotnull > 0:
@@ -8747,6 +8919,14 @@ class WolfArray(Element_To_Draw, header_wolf):
8747
8919
  elif self.nbnotnull > 0:
8748
8920
  wolfogl.addmeall_int8_pal_mask(self.array, self.mypal.colorsflt, self.mypal.values, ox, oy, dx, dy, jstart,
8749
8921
  jend, istart, iend, cursize, self.nullvalue, self.alpha, int(self.mypal.interval_cst), self.array.mask)
8922
+ elif self.wolftype == WOLF_ARRAY_FULL_UINTEGER8:
8923
+ if self.nbnotnull != self.nbx * self.nby:
8924
+ if self.nbnotnull > 0:
8925
+ wolfogl.addme_uint8_pal_mask(self.array, self.mypal.colorsflt, self.mypal.values, ox, oy, dx, dy, jstart,
8926
+ jend, istart, iend, cursize, self.nullvalue, self.alpha, int(self.mypal.interval_cst), self.array.mask)
8927
+ elif self.nbnotnull > 0:
8928
+ wolfogl.addmeall_uint8_pal_mask(self.array, self.mypal.colorsflt, self.mypal.values, ox, oy, dx, dy, jstart,
8929
+ jend, istart, iend, cursize, self.nullvalue, self.alpha, int(self.mypal.interval_cst), self.array.mask)
8750
8930
  elif self.wolftype in [WOLF_ARRAY_FULL_INTEGER16, WOLF_ARRAY_FULL_INTEGER16_2]:
8751
8931
  if self.nbnotnull != self.nbx * self.nby:
8752
8932
  if self.nbnotnull > 0:
@@ -9014,6 +9194,8 @@ class WolfArray(Element_To_Draw, header_wolf):
9014
9194
  return WOLF_ARRAY_FULL_INTEGER
9015
9195
  elif curarray.dtype == np.int8:
9016
9196
  return WOLF_ARRAY_FULL_INTEGER8
9197
+ elif curarray.dtype == np.uint8:
9198
+ return WOLF_ARRAY_FULL_UINTEGER8
9017
9199
 
9018
9200
  self.array = np.ma.array(array.copy())
9019
9201
  self.wolftype = wolftype_from_npz(array)