wolfhece 2.1.100__py3-none-any.whl → 2.1.101__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)
@@ -4464,8 +4468,10 @@ class SelectionData():
4464
4468
  if self.nb == 0:
4465
4469
  return None
4466
4470
 
4467
- newarray = WolfArray()
4471
+ if self.myselection == 'all':
4472
+ return WolfArray(mold=self.parent)
4468
4473
 
4474
+ newarray = WolfArray()
4469
4475
  lochead = self._get_header()
4470
4476
  if lochead is None:
4471
4477
  logging.error(_('Error in get_newarray !'))
@@ -4588,33 +4594,35 @@ class SelectionData():
4588
4594
 
4589
4595
  if self.nb == 0 or self.myselection == 'all':
4590
4596
  myarray = array1
4591
- axs = myarray.volume_estimation()
4597
+ fig, axs = myarray.volume_estimation()
4592
4598
 
4593
4599
  myarray = array2
4594
- axs = myarray.volume_estimation(axs)
4600
+ fig, axs = myarray.volume_estimation(axs)
4595
4601
  else:
4596
4602
  myarray = array1.mngselection.get_newarray()
4597
- axs = myarray.volume_estimation()
4603
+ fig, axs = myarray.volume_estimation()
4598
4604
 
4599
4605
  myarray = array2.mngselection.get_newarray()
4600
- axs = myarray.volume_estimation(axs)
4606
+ fig, axs = myarray.volume_estimation(axs)
4601
4607
  else:
4602
4608
  if len(self.parent.mngselection.myselection) == 0 or self.parent.mngselection.myselection == 'all':
4603
4609
  myarray = self.parent
4604
4610
  else:
4605
4611
  myarray = self.parent.mngselection.get_newarray()
4612
+ myarray.SelectionData.selections = self.parent.mngselection.selections.copy()
4606
4613
 
4607
- myarray.volume_estimation()
4614
+ fig, axs = myarray.volume_estimation()
4608
4615
  else:
4609
4616
  if self.nb == 0 or self.myselection == 'all':
4610
4617
  myarray = self.parent
4611
4618
  else:
4612
4619
  myarray = self.get_newarray()
4620
+ myarray.SelectionData.selections = self.selections.copy()
4613
4621
 
4614
- myarray.volume_estimation()
4622
+ fig, axs = myarray.volume_estimation()
4615
4623
 
4616
4624
  if show:
4617
- plt.show()
4625
+ fig.show()
4618
4626
 
4619
4627
  class SelectionDataMB(SelectionData):
4620
4628
  """ Extension of SelectionData to manage multiple blocks """
@@ -4877,6 +4885,7 @@ class WolfArray(Element_To_Draw, header_wolf):
4877
4885
  plotted:bool = False,
4878
4886
  need_for_wx:bool = False,
4879
4887
  mask_source:np.ndarray = None,
4888
+ np_source:np.ndarray = None,
4880
4889
  ) -> None:
4881
4890
  """
4882
4891
  Constructor of the WolfArray class
@@ -4895,6 +4904,7 @@ class WolfArray(Element_To_Draw, header_wolf):
4895
4904
  :param plotted: True = will be plotted if required by the mapviewer
4896
4905
  :param need_for_wx: True = a wxApp is required (if no application is underway --> Error)
4897
4906
  :param mask_source: mask to link to the data
4907
+ :param np_source: numpy array to link to the data
4898
4908
 
4899
4909
  """
4900
4910
  try:
@@ -4982,7 +4992,16 @@ class WolfArray(Element_To_Draw, header_wolf):
4982
4992
  if self.nb_blocks>0:
4983
4993
  self.myblocks = {}
4984
4994
 
4985
- self.allocate_ressources()
4995
+ if np_source is None:
4996
+ self.allocate_ressources()
4997
+ else:
4998
+ assert np_source.shape == (self.nbx, self.nby), _('Shape of np_source is not compatible with header')
4999
+
5000
+ if self.dtype != np_source.dtype:
5001
+ logging.warning(_('dtype of np_source is not compatible with header -- Conversion will be done'))
5002
+ np_source = np_source.astype(self.dtype)
5003
+
5004
+ self.array = ma.MaskedArray(np_source, mask= np_source[:,:] == self.nullvalue, copy=False, order='C')
4986
5005
 
4987
5006
  # # FIXME Why not initialize with nullvalue ?
4988
5007
  # self.array = ma.MaskedArray(np.ones((self.nbx, self.nby), order='F', dtype=self.dtype))
@@ -5054,6 +5073,7 @@ class WolfArray(Element_To_Draw, header_wolf):
5054
5073
  else:
5055
5074
  self.init_from_new(new)
5056
5075
 
5076
+
5057
5077
  self.add_ops_sel() # Ajout d'un gestionnaire de sélection et d'opérations
5058
5078
 
5059
5079
  def set_opacity(self, alpha:float):
@@ -5094,7 +5114,7 @@ class WolfArray(Element_To_Draw, header_wolf):
5094
5114
  return size * 4
5095
5115
  elif self.wolftype in [WOLF_ARRAY_FULL_INTEGER16, WOLF_ARRAY_FULL_INTEGER16_2]:
5096
5116
  return size * 2
5097
- elif self.wolftype == WOLF_ARRAY_FULL_INTEGER8:
5117
+ elif self.wolftype in [WOLF_ARRAY_FULL_INTEGER8, WOLF_ARRAY_FULL_UINTEGER8]:
5098
5118
  return size
5099
5119
  else:
5100
5120
  return size * 4
@@ -5355,6 +5375,8 @@ class WolfArray(Element_To_Draw, header_wolf):
5355
5375
  dtype = np.int16
5356
5376
  elif self.wolftype == WOLF_ARRAY_FULL_INTEGER8:
5357
5377
  dtype = np.int8
5378
+ elif self.wolftype == WOLF_ARRAY_FULL_UINTEGER8:
5379
+ dtype = np.uint8
5358
5380
  elif self.wolftype == WOLF_ARRAY_FULL_LOGICAL:
5359
5381
  dtype = np.int16
5360
5382
 
@@ -5374,6 +5396,8 @@ class WolfArray(Element_To_Draw, header_wolf):
5374
5396
  dtype = gdal.GDT_Int16
5375
5397
  elif self.wolftype == WOLF_ARRAY_FULL_INTEGER8:
5376
5398
  dtype = gdal.GDT_Byte
5399
+ elif self.wolftype == WOLF_ARRAY_FULL_UINTEGER8:
5400
+ dtype = gdal.GDT_Byte
5377
5401
  elif self.wolftype == WOLF_ARRAY_FULL_LOGICAL:
5378
5402
  dtype = gdal.GDT_Int16
5379
5403
 
@@ -5404,6 +5428,8 @@ class WolfArray(Element_To_Draw, header_wolf):
5404
5428
  dtype = _('int16 - 2 bytes per values')
5405
5429
  elif self.wolftype == WOLF_ARRAY_FULL_INTEGER8:
5406
5430
  dtype = _('int8 - 1 byte per values')
5431
+ elif self.wolftype == WOLF_ARRAY_FULL_UINTEGER8:
5432
+ dtype = _('uint8 - 1 byte per values')
5407
5433
  elif self.wolftype == WOLF_ARRAY_FULL_LOGICAL:
5408
5434
  dtype = _('int16 - 2 bytes per values')
5409
5435
 
@@ -6062,7 +6088,7 @@ class WolfArray(Element_To_Draw, header_wolf):
6062
6088
  - uniquement dans les mailles sélectionnées si elles existent
6063
6089
  - dans les mailles contenues dans le polygone sinon
6064
6090
 
6065
- On utilise ensuite "griddata" pour interpoler les altitudes des mailles
6091
+ On utilise ensuite "griddata" de Scipy pour interpoler les altitudes des mailles
6066
6092
  depuis les vertices 3D du polygone
6067
6093
  """
6068
6094
 
@@ -6125,17 +6151,27 @@ class WolfArray(Element_To_Draw, header_wolf):
6125
6151
  self.array.data[allij[:, 0], allij[:, 1]] = newz
6126
6152
 
6127
6153
  def interpolate_on_polylines(self, working_zone:zone, usemask=True):
6154
+ """ Interpolation sous toutes les polylignes d'une même zone """
6128
6155
 
6129
6156
  for curvec in working_zone.myvectors:
6130
6157
  self.interpolate_on_polyline(curvec, usemask)
6131
6158
 
6132
6159
 
6133
- def interpolate_on_cloud(self, xy:np.ndarray, z:np.ndarray, method='linear'):
6160
+ def interpolate_on_cloud(self, xy:np.ndarray, z:np.ndarray, method:Literal['linear', 'nearest', 'cubic']= 'linear'):
6134
6161
  """
6135
- See : https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.griddata.html
6162
+ Interpolation sur un nuage de points.
6163
+
6164
+ L'interpolation a lieu :
6165
+ - uniquement dans les mailles sélectionnées si elles existent
6166
+ - dans les mailles contenues dans le polygone convexe contenant les points sinon
6136
6167
 
6137
- method == nearest, linear or cubic
6168
+ Using griddata from Scipy.
6138
6169
 
6170
+ :param xy: numpy.array of vertices - shape (n,2)
6171
+ :param z: numpy.array of values - shape (n,)
6172
+ :param method: method for the interpolation -- 'nearest', 'linear' or 'cubic'
6173
+
6174
+ See : https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.griddata.html
6139
6175
  """
6140
6176
 
6141
6177
  if self.mngselection.myselection == [] or self.mngselection.myselection == 'all':
@@ -6159,18 +6195,36 @@ class WolfArray(Element_To_Draw, header_wolf):
6159
6195
 
6160
6196
  self.reset_plot()
6161
6197
 
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
6198
+ def interpolate_on_triangulation(self, coords, triangles,
6199
+ grid_x=None, grid_y = None,
6200
+ mask_tri=None, interp_method:Literal['matplotlib','scipy'] = 'matplotlib'):
6164
6201
  """
6165
- See : https://matplotlib.org/stable/gallery/images_contours_and_fields/triinterp_demo.html
6202
+ Interpolation sur une triangulation.
6203
+
6204
+ L'interpolation a lieu :
6205
+ - uniquement dans les mailles sélectionnées si elles existent
6206
+ - dans les mailles contenues dans la triangulation sinon
6166
6207
 
6167
- method == linear
6208
+ Matplotlib is used by default, but Scipy(griddata) can be used as well. If Matplotlib crashes, try with Scipy.
6209
+ Matplotlib is more strict on the quality of the triangulation.
6210
+
6211
+ :param coords: numpy.array of vertices - shape (n,3)
6212
+ :param triangles: numpy.array of triangles - shape (m,3)
6213
+ :param grid_x: numpy.array of x values where the interpolation will be done -- if None, the grid is created from the array
6214
+ :param grid_y: numpy.array of y values where the interpolation will be done -- if None, the grid is created from the array
6215
+ :param mask_tri: numpy.array of mask for the triangles
6216
+ :param interp_method: method for the interpolation -- 'matplotlib' or 'scipy'
6217
+
6218
+ For matplotlib algo, see : https://matplotlib.org/stable/gallery/images_contours_and_fields/triinterp_demo.html
6219
+ For scipy algo, see : https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.griddata.html
6168
6220
 
6169
6221
  """
6170
6222
 
6171
6223
 
6172
6224
  if interp_method =='matplotlib':
6173
6225
 
6226
+ import matplotlib.tri as mtri
6227
+
6174
6228
  use_scipy=False
6175
6229
 
6176
6230
  try:
@@ -6291,10 +6345,16 @@ class WolfArray(Element_To_Draw, header_wolf):
6291
6345
  self.reset_plot()
6292
6346
  return
6293
6347
 
6294
- def import_from_gltf(self, fn:str='', fnpos:str='', interp_method:Literal['matplotlib','numpy'] = 'matplotlib'):
6348
+ def import_from_gltf(self, fn:str='', fnpos:str='', interp_method:Literal['matplotlib','scipy'] = 'matplotlib'):
6295
6349
  """
6296
- interp_method == 'matplotlib' or 'griddata'
6350
+ Import from GLTF/GLB format
6351
+
6352
+ :param fn: filename
6353
+ :param fnpos: filename for the position's information
6354
+ :param interp_method: method for the interpolation -- 'matplotlib' or 'scipy'
6355
+
6297
6356
  """
6357
+ #FIXME : add the possibility to use PyVista
6298
6358
 
6299
6359
  if fn == '' or fnpos == '':
6300
6360
  logging.info(_('Retry !! -- Bad files'))
@@ -6459,7 +6519,6 @@ class WolfArray(Element_To_Draw, header_wolf):
6459
6519
  triangles.append([[i + decal, i + decal + 1, i + decal + nby] for i in range(nby - 1)])
6460
6520
  triangles.append([[i + decal + nby, i + decal + 1, i + decal + nby + 1] for i in range(nby - 1)])
6461
6521
 
6462
- from tqdm import tqdm
6463
6522
  for k in tqdm(range(1, nbx - 1)):
6464
6523
  decal = k * nby
6465
6524
  triangles.append([[i + decal, i + decal + 1, i + decal + nby] for i in range(nby - 1)])
@@ -6499,7 +6558,7 @@ class WolfArray(Element_To_Draw, header_wolf):
6499
6558
 
6500
6559
  return mylap
6501
6560
 
6502
- def volume_estimation(self, axs=None):
6561
+ def volume_estimation(self, axs:plt.Axes= None):
6503
6562
  """ Estimation of the volume of the selected zone """
6504
6563
 
6505
6564
  vect = self.array[np.logical_not(self.array.mask)].flatten()
@@ -6529,58 +6588,125 @@ class WolfArray(Element_To_Draw, header_wolf):
6529
6588
  deltaz = (zmax - zmin) / nb
6530
6589
  curz = zmin
6531
6590
  nbgroupement = []
6532
- longueur = []
6591
+ labeled_areas = []
6533
6592
  stockage = []
6534
6593
  z = []
6535
6594
 
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)
6595
+ methods = [_("All cells below the elevation (even if cells are disconnected)"),
6596
+ _("Only the largest connected area below the elevation (not necessarily the same for each elevation)"),
6597
+ _("Only the area below the elevation (if containing the cells stored in memory selection)")]
6598
+
6599
+ keys_select = list(self.SelectionData.selections.keys())
6600
+ if len(keys_select) == 0:
6601
+ methods = methods[:2]
6602
+ use_memory = False
6603
+
6604
+ dlg = wx.SingleChoiceDialog(None, _("Choose a method for selecting the area to integrate"), _("Labeling?"), methods)
6537
6605
  ret = dlg.ShowModal()
6538
- if ret == wx.ID_YES:
6539
- labeled= True
6540
- dlg.Destroy()
6606
+
6607
+ if ret == wx.ID_CANCEL:
6608
+ dlg.Destroy()
6609
+ return
6610
+
6611
+ if dlg.GetSelection() == 0:
6612
+ labeled = False
6613
+ else:
6614
+ labeled = True
6615
+ if dlg.GetSelection() == 1:
6616
+ use_memory = False
6617
+ else:
6618
+ if len(keys_select) >1:
6619
+ dlg = wx.SingleChoiceDialog(None, _("Choose a memory selection"), _("Memory selection?"), keys_select)
6620
+ ret = dlg.ShowModal()
6621
+
6622
+ if ret == wx.ID_CANCEL:
6623
+ dlg.Destroy()
6624
+ return
6625
+
6626
+ key = keys_select[dlg.GetSelection()]
6627
+ else:
6628
+ key = keys_select[0]
6629
+
6630
+ xy_key = self.SelectionData.selections[key]['select']
6631
+ if len(xy_key) == 0:
6632
+ logging.error(_('Empty selection'))
6633
+ return
6634
+
6635
+ ij_key = self.xy2ij_np(xy_key)
6636
+
6637
+ use_memory = True
6541
6638
 
6542
6639
  extensionmax = WolfArray(mold=self)
6543
6640
  extensionmax.array[:, :] = 0.
6544
6641
 
6545
6642
  if labeled:
6546
- for i in range(nb + 1):
6547
- logging.info(_(' Step ') +str(i))
6643
+ for i in tqdm(range(nb + 1)):
6548
6644
  z.append(curz)
6549
6645
 
6646
+ # Compute difference between the array and the current elevation
6550
6647
  if i == 0:
6551
6648
  diff = self.array - (curz + 1.e-3)
6552
6649
  else:
6553
6650
  diff = self.array - curz
6554
6651
 
6652
+ # Keep only the negative values
6555
6653
  diff[diff > 0] = 0.
6556
6654
  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
6655
 
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])
6656
+ if np.count_nonzero(diff < 0.) > 1:
6657
+ # More than one cell below the elevation
6658
+
6659
+ # Labeling of the cells below the elevation
6660
+ labeled_array, num_features = label(diff.data)
6661
+ # Applying the same mask as the original array
6662
+ labeled_array = ma.asarray(labeled_array)
6663
+ labeled_array.mask = self.array.mask
6664
+
6665
+ if use_memory:
6666
+ # Use only the labeled areas containing the cells stored in memory selection
6667
+ labeled_areas = []
6668
+ for curij in ij_key:
6669
+ labeled_areas.append(labeled_array[curij[0], curij[1]])
6670
+
6671
+ # Remove masked value
6672
+ labeled_areas = [x for x in labeled_areas if x is not ma.masked]
6673
+ # Remove duplicates
6674
+ labeled_areas = list(set(labeled_areas))
6675
+
6676
+ for curarea in labeled_areas:
6677
+ if curarea ==0:
6678
+ volume = 0.
6679
+ surface = 0.
6680
+ continue
6681
+
6682
+ # Search
6683
+ mask = labeled_array == curarea
6684
+ area = np.where(mask)
6685
+ volume = -self.dx * self.dy * np.sum(diff[area])
6686
+ surface = self.dx * self.dy * len(area[0])
6687
+ extensionmax.array[np.logical_and(mask, extensionmax.array[:, :] == 0.)] = float(i + 1)
6567
6688
 
6689
+ else:
6690
+ labeled_areas = list(sum_labels(np.ones(labeled_array.shape, dtype=np.int32), labeled_array, range(1, num_features+1)))
6691
+ labeled_areas = [[x, y] for x, y in zip(labeled_areas, range(1, num_features+1))]
6692
+ labeled_areas.sort(key=lambda x: x[0], reverse=True)
6693
+ jmax = labeled_areas[0][1]
6694
+ nbmax = labeled_areas[0][0]
6695
+
6696
+ volume = -self.dx * self.dy * np.sum(diff[labeled_array == jmax])
6697
+ surface = self.dx * self.dy * nbmax
6698
+ extensionmax.array[np.logical_and(labeled_array == jmax, extensionmax.array[:, :] == 0.)] = float(i + 1)
6699
+ else:
6700
+ # Only one cell below the elevation
6701
+ volume = -self.dx * self.dy * np.sum(diff)
6702
+ surface = self.dx * self.dy * np.count_nonzero(diff<0.)
6703
+ extensionmax.array[np.logical_and(diff[:,:]<0., extensionmax.array[:, :] == 0.)] = float(i + 1)
6568
6704
 
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)
6572
-
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
6705
  stockage.append([volume, surface])
6578
6706
  curz += deltaz
6579
6707
 
6580
- extensionmax.array[np.logical_and(labeled_array == jmax, extensionmax.array[:, :] == 0.)] = float(i + 1)
6581
6708
  else:
6582
- for i in range(nb + 1):
6583
- logging.info(_(' Step ') +str(i))
6709
+ for i in tqdm(range(nb + 1)):
6584
6710
  z.append(curz)
6585
6711
 
6586
6712
  if i == 0:
@@ -6597,7 +6723,7 @@ class WolfArray(Element_To_Draw, header_wolf):
6597
6723
 
6598
6724
  extensionmax.array[np.logical_and(diff[:,:]<0., extensionmax.array[:, :] == 0.)] = float(i + 1)
6599
6725
 
6600
- dlg = wx.FileDialog(None, _('Choose filename'), wildcard='bin (*.bin)|*.bin|All (*.*)|*.*', style=wx.FD_SAVE)
6726
+ dlg = wx.FileDialog(None, _('Choose filename for zoning result'), wildcard='bin (*.bin)|*.bin|tif (*.tif)|*.tif|All (*.*)|*.*', style=wx.FD_SAVE)
6601
6727
  ret = dlg.ShowModal()
6602
6728
  if ret == wx.ID_CANCEL:
6603
6729
  dlg.Destroy()
@@ -6611,22 +6737,25 @@ class WolfArray(Element_To_Draw, header_wolf):
6611
6737
 
6612
6738
  if axs is None:
6613
6739
  fig, axs = plt.subplots(1, 2, tight_layout=True)
6740
+ else:
6741
+ fig = axs[0].get_figure()
6742
+
6614
6743
  axs[0].plot(z, [x[0] for x in stockage])
6615
6744
  axs[0].scatter(z, [x[0] for x in stockage])
6616
6745
  axs[0].set_xlabel(_("Elevation [m]"), size=15)
6617
- axs[0].set_ylabel(_("Volume [m^3]"), size=15)
6746
+ axs[0].set_ylabel(_("Volume [$m^3$]"), size=15)
6618
6747
  axs[1].step(z, [x[1] for x in stockage], where='post')
6619
6748
  axs[1].scatter(z, [x[1] for x in stockage])
6620
6749
  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)
6750
+ axs[1].set_ylabel(_("Surface [$m^2$]"), size=15)
6751
+ fig.suptitle(_("Retention capacity of the selected zone"), fontsize=20)
6623
6752
 
6624
6753
  with open(fn[:-4] + '_hvs.txt', 'w') as f:
6625
- f.write('H [m]\tZ [m DNG]\tVolume [m^3]\tSurface [m^2]\n')
6754
+ f.write('H [m]\tZ [m DNG]\tVolume [$m^3$]\tSurface [$m^2$]\n')
6626
6755
  for curz, (curv, curs) in zip(z, stockage):
6627
6756
  f.write('{}\t{}\t{}\t{}\n'.format(curz - zmin, curz, curv, curs))
6628
6757
 
6629
- return axs
6758
+ return fig, axs
6630
6759
 
6631
6760
  def paste_all(self, fromarray:"WolfArray", mask_after:bool=True):
6632
6761
  """ Paste all the values from another WolfArray """
@@ -6737,6 +6866,8 @@ class WolfArray(Element_To_Draw, header_wolf):
6737
6866
  dtype = np.int16
6738
6867
  elif self.wolftype == WOLF_ARRAY_FULL_INTEGER8:
6739
6868
  dtype = np.int8
6869
+ elif self.wolftype == WOLF_ARRAY_FULL_UINTEGER8:
6870
+ dtype = np.uint8
6740
6871
 
6741
6872
  self.dx = myhead.dx
6742
6873
  self.dy = myhead.dy
@@ -6907,20 +7038,24 @@ class WolfArray(Element_To_Draw, header_wolf):
6907
7038
  self.plotted = False
6908
7039
 
6909
7040
  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
7041
+ if Path(self.filename).exists():
7042
+ # An array can exists with a filename but no written data on disk
7043
+ # In this case, we don't want to delete the data in memory
6917
7044
 
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
7045
+ if askquestion and self.wx_exists:
7046
+ dlg = wx.MessageDialog(None,
7047
+ _('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 !!'),
7048
+ style=wx.YES_NO)
7049
+ ret = dlg.ShowModal()
7050
+ if ret == wx.ID_YES:
7051
+ unload=True
7052
+
7053
+ if unload:
7054
+ self.delete_lists()
7055
+ self.array = np.zeros([1])
7056
+ if VERSION_RGB==1 : self.rgb = None
7057
+ self.loaded = False
7058
+ return
6924
7059
 
6925
7060
  if not forceresetOGL:
6926
7061
  if askquestion and self.wx_exists:
@@ -7556,6 +7691,9 @@ class WolfArray(Element_To_Draw, header_wolf):
7556
7691
  elif locarray.dtype == np.int8:
7557
7692
  self.wolftype = WOLF_ARRAY_FULL_INTEGER8
7558
7693
  logging.warning(_('Data type changed to int8'))
7694
+ elif locarray.dtype == np.uint8:
7695
+ self.wolftype = WOLF_ARRAY_FULL_UINTEGER8
7696
+ logging.warning(_('Data type changed to uint8'))
7559
7697
  else:
7560
7698
  logging.error(_('Unsupported type in numpy file -- Abort wrting header file'))
7561
7699
  writing_header = False
@@ -7863,6 +8001,9 @@ class WolfArray(Element_To_Draw, header_wolf):
7863
8001
  elif self.wolftype in [WOLF_ARRAY_FULL_INTEGER8]:
7864
8002
  locarray = np.frombuffer(f.read(self.nbx * self.nby * 2), dtype=np.int8)
7865
8003
  self.array = ma.masked_array(locarray.copy(), dtype=np.int8)
8004
+ elif self.wolftype in [WOLF_ARRAY_FULL_UINTEGER8]:
8005
+ locarray = np.frombuffer(f.read(self.nbx * self.nby * 2), dtype=np.uint8)
8006
+ self.array = ma.masked_array(locarray.copy(), dtype=np.uint8)
7866
8007
 
7867
8008
  if self.nbdims == 2:
7868
8009
  self.array = self.array.reshape(self.nbx, self.nby, order='F')
@@ -8075,6 +8216,8 @@ class WolfArray(Element_To_Draw, header_wolf):
8075
8216
  value=np.int16(value)
8076
8217
  elif self.wolftype in [WOLF_ARRAY_FULL_INTEGER8]:
8077
8218
  value=np.int8(value)
8219
+ elif self.wolftype in [WOLF_ARRAY_FULL_UINTEGER8]:
8220
+ value=np.uint8(value)
8078
8221
  except:
8079
8222
  logging.error(_('Type not supported : {} - {}'.format(value, type(value))))
8080
8223
  logging.warning(_('Masking operation compromised'))
@@ -8431,7 +8574,7 @@ class WolfArray(Element_To_Draw, header_wolf):
8431
8574
 
8432
8575
  if VERSION_RGB==1 :
8433
8576
  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]:
8577
+ if self.wolftype not in [WOLF_ARRAY_FULL_SINGLE, WOLF_ARRAY_FULL_INTEGER8, WOLF_ARRAY_FULL_UINTEGER8]:
8435
8578
  # FIXME: Currently, only some types are supported in Cython/OpenGL library
8436
8579
  self._tmp_float32 = self.array.astype(dtype=np.float32)
8437
8580
  self.rgb = self.mypal.get_rgba(self._tmp_float32)
@@ -8442,6 +8585,7 @@ class WolfArray(Element_To_Draw, header_wolf):
8442
8585
  elif VERSION_RGB in [2 ,3]:
8443
8586
  if self.wolftype not in [WOLF_ARRAY_FULL_SINGLE,
8444
8587
  WOLF_ARRAY_FULL_INTEGER8,
8588
+ WOLF_ARRAY_FULL_UINTEGER8,
8445
8589
  WOLF_ARRAY_FULL_INTEGER16,
8446
8590
  WOLF_ARRAY_FULL_INTEGER16_2,
8447
8591
  WOLF_ARRAY_FULL_INTEGER,
@@ -8691,6 +8835,14 @@ class WolfArray(Element_To_Draw, header_wolf):
8691
8835
  elif self.nbnotnull > 0:
8692
8836
  wolfogl.addmeall_int8_pal(self.array, self.mypal.colorsflt, self.mypal.values, ox, oy, dx, dy, jstart,
8693
8837
  jend, istart, iend, cursize, self.nullvalue, self.alpha, int(self.mypal.interval_cst))
8838
+ elif self.wolftype == WOLF_ARRAY_FULL_UINTEGER8:
8839
+ if self.nbnotnull != self.nbx * self.nby:
8840
+ if self.nbnotnull > 0:
8841
+ wolfogl.addme_uint8_pal(self.array, self.mypal.colorsflt, self.mypal.values, ox, oy, dx, dy, jstart,
8842
+ jend, istart, iend, cursize, self.nullvalue, self.alpha, int(self.mypal.interval_cst))
8843
+ elif self.nbnotnull > 0:
8844
+ wolfogl.addmeall_uint8_pal(self.array, self.mypal.colorsflt, self.mypal.values, ox, oy, dx, dy, jstart,
8845
+ jend, istart, iend, cursize, self.nullvalue, self.alpha, int(self.mypal.interval_cst))
8694
8846
  elif self.wolftype in [WOLF_ARRAY_FULL_INTEGER16, WOLF_ARRAY_FULL_INTEGER16_2]:
8695
8847
  if self.nbnotnull != self.nbx * self.nby:
8696
8848
  if self.nbnotnull > 0:
@@ -8747,6 +8899,14 @@ class WolfArray(Element_To_Draw, header_wolf):
8747
8899
  elif self.nbnotnull > 0:
8748
8900
  wolfogl.addmeall_int8_pal_mask(self.array, self.mypal.colorsflt, self.mypal.values, ox, oy, dx, dy, jstart,
8749
8901
  jend, istart, iend, cursize, self.nullvalue, self.alpha, int(self.mypal.interval_cst), self.array.mask)
8902
+ elif self.wolftype == WOLF_ARRAY_FULL_UINTEGER8:
8903
+ if self.nbnotnull != self.nbx * self.nby:
8904
+ if self.nbnotnull > 0:
8905
+ wolfogl.addme_uint8_pal_mask(self.array, self.mypal.colorsflt, self.mypal.values, ox, oy, dx, dy, jstart,
8906
+ jend, istart, iend, cursize, self.nullvalue, self.alpha, int(self.mypal.interval_cst), self.array.mask)
8907
+ elif self.nbnotnull > 0:
8908
+ wolfogl.addmeall_uint8_pal_mask(self.array, self.mypal.colorsflt, self.mypal.values, ox, oy, dx, dy, jstart,
8909
+ jend, istart, iend, cursize, self.nullvalue, self.alpha, int(self.mypal.interval_cst), self.array.mask)
8750
8910
  elif self.wolftype in [WOLF_ARRAY_FULL_INTEGER16, WOLF_ARRAY_FULL_INTEGER16_2]:
8751
8911
  if self.nbnotnull != self.nbx * self.nby:
8752
8912
  if self.nbnotnull > 0:
@@ -9014,6 +9174,8 @@ class WolfArray(Element_To_Draw, header_wolf):
9014
9174
  return WOLF_ARRAY_FULL_INTEGER
9015
9175
  elif curarray.dtype == np.int8:
9016
9176
  return WOLF_ARRAY_FULL_INTEGER8
9177
+ elif curarray.dtype == np.uint8:
9178
+ return WOLF_ARRAY_FULL_UINTEGER8
9017
9179
 
9018
9180
  self.array = np.ma.array(array.copy())
9019
9181
  self.wolftype = wolftype_from_npz(array)