wolfhece 2.2.17__py3-none-any.whl → 2.2.18__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
@@ -2097,7 +2097,19 @@ class Ops_Array(wx.Frame):
2097
2097
 
2098
2098
  self.labelling = wx.Button(self.tools, wx.ID_ANY, _("Labelling"), wx.DefaultPosition,wx.DefaultSize, 0)
2099
2099
 
2100
+ stats_sizer = wx.BoxSizer(wx.HORIZONTAL)
2101
+ stats_sizer2 = wx.BoxSizer(wx.HORIZONTAL)
2102
+
2100
2103
  self.statistics = wx.Button(self.tools, wx.ID_ANY, _("Statistics"), wx.DefaultPosition,wx.DefaultSize, 0)
2104
+ self.plot_stats = wx.Button(self.tools, wx.ID_ANY, _("Plot statistics\nCurrent zoom"), wx.DefaultPosition,wx.DefaultSize, 0)
2105
+ self.plot_stats_zone = wx.Button(self.tools, wx.ID_ANY, _("Plot statistics\nCurrent zone"), wx.DefaultPosition,wx.DefaultSize, 0)
2106
+ self.plot_stats_vector = wx.Button(self.tools, wx.ID_ANY, _("Plot statistics\nCurrent vector"), wx.DefaultPosition,wx.DefaultSize, 0)
2107
+
2108
+ stats_sizer.Add(self.statistics, 1, wx.EXPAND)
2109
+ stats_sizer.Add(self.plot_stats, 1, wx.EXPAND)
2110
+
2111
+ stats_sizer2.Add(self.plot_stats_zone, 1, wx.EXPAND)
2112
+ stats_sizer2.Add(self.plot_stats_vector, 1, wx.EXPAND)
2101
2113
 
2102
2114
  self.clean = wx.Button(self.tools, wx.ID_ANY, _("Clean"), wx.DefaultPosition,wx.DefaultSize, 0)
2103
2115
 
@@ -2117,7 +2129,8 @@ class Ops_Array(wx.Frame):
2117
2129
  Toolssizer.Add(self.labelling, 1, wx.EXPAND)
2118
2130
  Toolssizer.Add(self.clean, 1, wx.EXPAND)
2119
2131
  Toolssizer.Add(self.extract_selection, 1, wx.EXPAND)
2120
- Toolssizer.Add(self.statistics, 1, wx.EXPAND)
2132
+ Toolssizer.Add(stats_sizer, 1, wx.EXPAND)
2133
+ Toolssizer.Add(stats_sizer2, 1, wx.EXPAND)
2121
2134
  Toolssizer.Add(cont_sizer, 1, wx.EXPAND)
2122
2135
 
2123
2136
  self.ApplyTools.SetToolTip(_("Apply Nullvalue into memory/object"))
@@ -2127,6 +2140,7 @@ class Ops_Array(wx.Frame):
2127
2140
  self.clean.SetToolTip(_("Clean the array\n\nRemove small isolated patches of data"))
2128
2141
  self.extract_selection.SetToolTip(_("Extract the current selection"))
2129
2142
  self.statistics.SetToolTip(_("Compute statistics on the array\n\nResults are displayed in a dialog box"))
2143
+ self.plot_stats.SetToolTip(_("Plot statistics on the array\n\nResults are displayed in a separate figure"))
2130
2144
 
2131
2145
  self.tools.SetSizer(Toolssizer)
2132
2146
  self.tools.Layout()
@@ -2500,6 +2514,9 @@ class Ops_Array(wx.Frame):
2500
2514
  self.clean.Bind(wx.EVT_BUTTON, self.OnClean)
2501
2515
  self.labelling.Bind(wx.EVT_BUTTON, self.OnLabelling)
2502
2516
  self.statistics.Bind(wx.EVT_BUTTON, self.OnStatistics)
2517
+ self.plot_stats.Bind(wx.EVT_BUTTON, self.OnPlotStatistics)
2518
+ self.plot_stats_zone.Bind(wx.EVT_BUTTON, self.OnPlotStatisticsZone)
2519
+ self.plot_stats_vector.Bind(wx.EVT_BUTTON, self.OnPlotStatisticsVector)
2503
2520
  self.extract_selection.Bind(wx.EVT_BUTTON, self.OnExtractSelection)
2504
2521
  self._contour_int.Bind(wx.EVT_BUTTON, self.OnContourInt)
2505
2522
  self._contour_list.Bind(wx.EVT_BUTTON, self.OnContourList)
@@ -3008,6 +3025,86 @@ class Ops_Array(wx.Frame):
3008
3025
 
3009
3026
  ret_frame.Show()
3010
3027
 
3028
+ def OnPlotStatistics(self, event:wx.MouseEvent):
3029
+ """ Plot statistics on the current zoom"""
3030
+
3031
+ from .analyze_poly import Array_analysis_onepolygon
3032
+
3033
+ logging.info(_('Plotting statistics on the current zoom'))
3034
+ if self.parentarray.nbnotnull > 50_000:
3035
+ logging.info(_('Quite large array - please wait a bit...'))
3036
+
3037
+ analyzer = Array_analysis_onepolygon(self.parentarray, self.mapviewer.get_bounds_as_polygon())
3038
+
3039
+ try:
3040
+ analyzer.plot_values(engine = 'plotly')
3041
+ except:
3042
+ logging.error(_('Error in plotly engine - Try seaborn engine'))
3043
+ logging.info(_('If you have not installed plotly, please install it with "pip install plotly"'))
3044
+ try:
3045
+ analyzer.plot_values(engine = 'seaborn')
3046
+ except:
3047
+ logging.error('Error in seaborn engine')
3048
+
3049
+ logging.info(_('Done !'))
3050
+
3051
+ def OnPlotStatisticsZone(self, event:wx.MouseEvent):
3052
+ """ Plot statistics on the current zone """
3053
+
3054
+ if self.mapviewer is not None:
3055
+ if self.mapviewer.active_zone is not None:
3056
+ from .analyze_poly import Array_analysis_polygons
3057
+
3058
+ logging.info(_('Plotting statistics on the current zone'))
3059
+
3060
+ analyzer = Array_analysis_polygons(self.parentarray, self.mapviewer.active_zone)
3061
+ try:
3062
+ analyzer.plot_values(engine = 'plotly')
3063
+ except:
3064
+ logging.error(_('Error in plotly engine - Try seaborn engine'))
3065
+ logging.info(_('If you have not installed plotly, please install it with "pip install plotly"'))
3066
+ try:
3067
+ analyzer.plot_values(engine = 'seaborn')
3068
+ except:
3069
+ logging.error('Error in seaborn engine')
3070
+
3071
+ logging.info(_('Done !'))
3072
+
3073
+ else:
3074
+ logging.error(_('No active zone to plot statistics'))
3075
+ logging.info(_('Please select a zone to plot statistics'))
3076
+ else:
3077
+ logging.error(_('No active mapviewer to plot statistics'))
3078
+
3079
+ def OnPlotStatisticsVector(self, event:wx.MouseEvent):
3080
+ """ Plot statistics on the current vector """
3081
+
3082
+ if self.mapviewer is not None:
3083
+ if self.mapviewer.active_vector is not None:
3084
+ from .analyze_poly import Array_analysis_onepolygon
3085
+
3086
+ logging.info(_('Plotting statistics on the current vector'))
3087
+
3088
+ # Get the active vector
3089
+ analyzer = Array_analysis_onepolygon(self.parentarray, self.mapviewer.active_vector)
3090
+ try:
3091
+ analyzer.plot_values(engine = 'plotly')
3092
+ except:
3093
+ logging.error(_('Error in plotly engine - Try seaborn engine'))
3094
+ logging.info(_('If you have not installed plotly, please install it with "pip install plotly"'))
3095
+ try:
3096
+ analyzer.plot_values(engine = 'seaborn')
3097
+ except:
3098
+ logging.error('Error in seaborn engine')
3099
+
3100
+ logging.info(_('Done !'))
3101
+
3102
+ else:
3103
+ logging.error(_('No active vector to plot statistics'))
3104
+ logging.info(_('Please select a vector to plot statistics'))
3105
+ else:
3106
+ logging.error(_('No active mapviewer to plot statistics'))
3107
+
3011
3108
  def OnExtractSelection(self, event:wx.MouseEvent):
3012
3109
  """ Extract the current selection """
3013
3110
 
@@ -4953,7 +5050,10 @@ class SelectionData():
4953
5050
  self.myselection = 'all'
4954
5051
  self.update_nb_nodes_selection()
4955
5052
 
4956
- def interp2Dpolygons(self, working_zone:zone, method:Literal["nearest", "linear", "cubic"] = None, resetplot:bool = True):
5053
+ def interp2Dpolygons(self, working_zone:zone,
5054
+ method:Literal["nearest", "linear", "cubic"] = None,
5055
+ resetplot:bool = True,
5056
+ keep:Literal['all', 'below', 'above'] = 'all'):
4957
5057
  """
4958
5058
  Interpolation sous tous les polygones d'une zone
4959
5059
  cf parent.interp2Dpolygon
@@ -4970,12 +5070,15 @@ class SelectionData():
4970
5070
  method = dlg.GetStringSelection()
4971
5071
  dlg.Destroy()
4972
5072
 
4973
- self.parent.interpolate_on_polygons(working_zone, method)
5073
+ self.parent.interpolate_on_polygons(working_zone, method, keep)
4974
5074
 
4975
5075
  if resetplot:
4976
5076
  self.parent.reset_plot()
4977
5077
 
4978
- def interp2Dpolygon(self, working_vector:vector, method:Literal["nearest", "linear", "cubic"] = None, resetplot:bool = True):
5078
+ def interp2Dpolygon(self, working_vector:vector,
5079
+ method:Literal["nearest", "linear", "cubic"] = None,
5080
+ resetplot:bool = True,
5081
+ keep:Literal['all', 'below', 'above'] = 'all'):
4979
5082
  """
4980
5083
  Interpolation sous un polygone
4981
5084
  cf parent.interp2Dpolygon
@@ -4992,7 +5095,7 @@ class SelectionData():
4992
5095
  method = dlg.GetStringSelection()
4993
5096
  dlg.Destroy()
4994
5097
 
4995
- self.parent.interpolate_on_polygon(working_vector, method)
5098
+ self.parent.interpolate_on_polygon(working_vector, method, keep)
4996
5099
 
4997
5100
  if resetplot:
4998
5101
  self.parent.reset_plot()
@@ -5232,7 +5335,10 @@ class SelectionDataMB(SelectionData):
5232
5335
 
5233
5336
  logging.error(_('Not yet implemented for Multi-Blocks'))
5234
5337
 
5235
- def interp2Dpolygons(self, working_zone:zone, method:Literal["nearest", "linear", "cubic"] = None):
5338
+ def interp2Dpolygons(self, working_zone:zone,
5339
+ method:Literal["nearest", "linear", "cubic"] = None,
5340
+ resetplot:bool = True,
5341
+ keep:Literal['all', 'below', 'above'] = 'all'):
5236
5342
  """
5237
5343
  Interpolation sous tous les polygones d'une zone
5238
5344
  cf parent.interp2Dpolygon
@@ -5249,11 +5355,15 @@ class SelectionDataMB(SelectionData):
5249
5355
  method = dlg.GetStringSelection()
5250
5356
  dlg.Destroy()
5251
5357
 
5252
- self.parent.interpolate_on_polygons(working_zone, method)
5358
+ self.parent.interpolate_on_polygons(working_zone, method, keep)
5253
5359
 
5254
- self.parent.reset_plot()
5360
+ if resetplot:
5361
+ self.parent.reset_plot()
5255
5362
 
5256
- def interp2Dpolygon(self, working_vector:vector, method:Literal["nearest", "linear", "cubic"] = None):
5363
+ def interp2Dpolygon(self, working_vector:vector,
5364
+ method:Literal["nearest", "linear", "cubic"] = None,
5365
+ resetplot:bool = True,
5366
+ keep:Literal['all', 'below', 'above'] = 'all'):
5257
5367
  """
5258
5368
  Interpolation sous un polygone
5259
5369
  cf parent.interp2Dpolygon
@@ -5270,9 +5380,10 @@ class SelectionDataMB(SelectionData):
5270
5380
  method = dlg.GetStringSelection()
5271
5381
  dlg.Destroy()
5272
5382
 
5273
- self.parent.interpolate_on_polygon(working_vector, method)
5383
+ self.parent.interpolate_on_polygon(working_vector, method, keep)
5274
5384
 
5275
- self.parent.reset_plot()
5385
+ if resetplot:
5386
+ self.parent.reset_plot()
5276
5387
 
5277
5388
  def interp2Dpolylines(self, working_zone:zone, resetplot:bool = True):
5278
5389
  """
@@ -6124,17 +6235,17 @@ class WolfArray(Element_To_Draw, header_wolf):
6124
6235
 
6125
6236
  if inside_polygon is not None:
6126
6237
  ij = self.get_ij_inside_polygon(inside_polygon)
6127
- vals = self.array[ij]
6238
+ vals = self.array[ij[:,0], ij[:,1]]
6128
6239
  elif self.SelectionData.nb == 0 or self.SelectionData.myselection == 'all':
6129
6240
  logging.info(_('No selection -- statistics on the whole array'))
6130
- vals = self.array[~self.array.mask] # all values
6241
+ vals = self.array[~self.array.mask].ravel().data # all values
6131
6242
  else:
6132
6243
  vals = self.SelectionData.get_values_sel()
6133
6244
 
6134
- mean = np.mean(vals)
6135
- std = np.std(vals)
6136
- median = np.median(vals)
6137
- sum = np.sum(vals)
6245
+ mean = np.ma.mean(vals)
6246
+ std = np.ma.std(vals)
6247
+ median = np.ma.median(vals)
6248
+ sum = np.ma.sum(vals)
6138
6249
  vol = sum * self.dx * self.dy
6139
6250
 
6140
6251
  return {_('Mean'): mean, _('Std'): std, _('Median'): median, _('Sum'): sum, _('Volume'): vol, _('Values'): vals}
@@ -6806,7 +6917,9 @@ class WolfArray(Element_To_Draw, header_wolf):
6806
6917
 
6807
6918
  plt.show()
6808
6919
 
6809
- def interpolate_on_polygon(self, working_vector: vector, method:Literal["nearest", "linear", "cubic"]="linear"):
6920
+ def interpolate_on_polygon(self, working_vector: vector,
6921
+ method:Literal["nearest", "linear", "cubic"]="linear",
6922
+ keep:Literal['all', 'below', 'above'] = 'all'):
6810
6923
  """
6811
6924
  Interpolation sous un polygone
6812
6925
 
@@ -6818,6 +6931,14 @@ class WolfArray(Element_To_Draw, header_wolf):
6818
6931
  depuis les vertices 3D du polygone
6819
6932
  """
6820
6933
 
6934
+ if keep not in ['all', 'below', 'above']:
6935
+ logging.error(_('keep must be "all", "below" or "above"'))
6936
+ raise ValueError
6937
+
6938
+ if method not in ['nearest', 'linear', 'cubic']:
6939
+ logging.error(_('method must be "nearest", "linear" or "cubic"'))
6940
+ raise ValueError
6941
+
6821
6942
  if self.mngselection is None:
6822
6943
  destxy = self.get_xy_inside_polygon(working_vector)
6823
6944
  if len(destxy)==0:
@@ -6841,6 +6962,9 @@ class WolfArray(Element_To_Draw, header_wolf):
6841
6962
  else:
6842
6963
  destxy = self.SelectionData.myselection
6843
6964
 
6965
+ # if isinstance(destxy, list):
6966
+ # destxy = np.asarray(destxy)
6967
+
6844
6968
  if len(destxy)==0:
6845
6969
  logging.debug(_('No points to interpolate'))
6846
6970
  return
@@ -6851,7 +6975,13 @@ class WolfArray(Element_To_Draw, header_wolf):
6851
6975
 
6852
6976
  newvalues = griddata(xyz[:, :2], xyz[:, 2], destxy, method=method, fill_value=-99999.)
6853
6977
 
6854
- locmask = np.where(newvalues != -99999.)
6978
+ if keep == 'all':
6979
+ locmask = np.where(newvalues != -99999.)
6980
+ elif keep == 'below':
6981
+ locmask = np.where((newvalues != -99999.) & (newvalues < self.array.data[destij[:, 0], destij[:, 1]]))
6982
+ elif keep == 'above':
6983
+ locmask = np.where((newvalues != -99999.) & (newvalues > self.array.data[destij[:, 0], destij[:, 1]]))
6984
+
6855
6985
  self.array.data[destij[locmask][:, 0], destij[locmask][:, 1]] = newvalues[locmask]
6856
6986
 
6857
6987
  def rasterize_vector_valuebyid(self, working_vector: vector, id,
@@ -6910,14 +7040,16 @@ class WolfArray(Element_To_Draw, header_wolf):
6910
7040
  for curzone in working_zones.myzones:
6911
7041
  self.rasterize_zone_valuebyid(curzone, id, method)
6912
7042
 
6913
- def interpolate_on_polygons(self, working_zone:zone, method:Literal["nearest", "linear", "cubic"]="linear"):
7043
+ def interpolate_on_polygons(self, working_zone:zone,
7044
+ method:Literal["nearest", "linear", "cubic"]="linear",
7045
+ keep:Literal['all', 'below', 'above'] = 'all'):
6914
7046
  """
6915
7047
  Interpolation sous plusieurs polygones d'une même zone
6916
7048
 
6917
7049
  """
6918
7050
 
6919
7051
  for curvec in working_zone.myvectors:
6920
- self.interpolate_on_polygon(curvec, method)
7052
+ self.interpolate_on_polygon(curvec, method, keep)
6921
7053
 
6922
7054
  def interpolate_on_polyline(self, working_vector:vector, usemask=True):
6923
7055
  """
@@ -6994,7 +7126,9 @@ class WolfArray(Element_To_Draw, header_wolf):
6994
7126
 
6995
7127
  def interpolate_on_triangulation(self, coords, triangles,
6996
7128
  grid_x=None, grid_y = None,
6997
- mask_tri=None, interp_method:Literal['matplotlib','scipy'] = 'matplotlib'):
7129
+ mask_tri=None,
7130
+ interp_method:Literal['matplotlib','scipy'] = 'matplotlib',
7131
+ keep:Literal['all', 'below', 'above'] = 'all'):
6998
7132
  """
6999
7133
  Interpolation sur une triangulation.
7000
7134
 
@@ -7003,7 +7137,8 @@ class WolfArray(Element_To_Draw, header_wolf):
7003
7137
  - dans les mailles contenues dans la triangulation sinon
7004
7138
 
7005
7139
  Matplotlib is used by default, but Scipy(griddata) can be used as well. If Matplotlib crashes, try with Scipy.
7006
- Matplotlib is more strict on the quality of the triangulation.
7140
+
7141
+ **Matplotlib is more strict on the quality of the triangulation.**
7007
7142
 
7008
7143
  :param coords: numpy.array of vertices - shape (n,3)
7009
7144
  :param triangles: numpy.array of triangles - shape (m,3)
@@ -7011,6 +7146,7 @@ class WolfArray(Element_To_Draw, header_wolf):
7011
7146
  :param grid_y: numpy.array of y values where the interpolation will be done -- if None, the grid is created from the array
7012
7147
  :param mask_tri: numpy.array of mask for the triangles
7013
7148
  :param interp_method: method for the interpolation -- 'matplotlib' or 'scipy'
7149
+ :param keep: 'all' to keep all values, 'below' to keep only values below the current array, 'above' to keep only values above the current array
7014
7150
 
7015
7151
  For matplotlib algo, see : https://matplotlib.org/stable/gallery/images_contours_and_fields/triinterp_demo.html
7016
7152
  For scipy algo, see : https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.griddata.html
@@ -7019,6 +7155,7 @@ class WolfArray(Element_To_Draw, header_wolf):
7019
7155
 
7020
7156
 
7021
7157
  if interp_method =='matplotlib':
7158
+ # FIXME : This part could be optimized, I think
7022
7159
 
7023
7160
  import matplotlib.tri as mtri
7024
7161
 
@@ -7027,6 +7164,9 @@ class WolfArray(Element_To_Draw, header_wolf):
7027
7164
  try:
7028
7165
  if self.mngselection is not None:
7029
7166
  if self.mngselection.myselection != [] and self.mngselection.myselection != 'all':
7167
+ # interpolation only in the selected cells
7168
+
7169
+ # Convert coordinates to indices
7030
7170
  ij = np.asarray([self.get_ij_from_xy(x, y) for x, y in self.mngselection.myselection])
7031
7171
 
7032
7172
  try:
@@ -7037,17 +7177,60 @@ class WolfArray(Element_To_Draw, header_wolf):
7037
7177
  interplin = mtri.LinearTriInterpolator(triang, coords[:,2]) # Interpolation et récupération dans le numpy.array de l'objet Wolf
7038
7178
  except:
7039
7179
  raise Warning(_('Bad triangulation - try with another method like Scipy'))
7180
+
7040
7181
  newvalues = np.ma.masked_array([interplin(x, y) for x, y in self.mngselection.myselection])
7041
7182
 
7042
- ij = ij[np.where(~newvalues.mask)]
7043
- self.array.data[ij[:, 0], ij[:, 1]] = newvalues.data[np.where(~newvalues.mask)]
7183
+ if newvalues.mask.shape!=():
7184
+ # We have a mask
7185
+
7186
+ nonmasked_values = np.where(~newvalues.mask)
7187
+ ij = ij[nonmasked_values]
7188
+ newvalues = newvalues[nonmasked_values]
7189
+
7190
+ if keep == 'below':
7191
+ newvalues = np.ma.masked_array(newvalues, mask=(newvalues > self.array.data[ij[:, 0], ij[:, 1]]))
7192
+
7193
+ nonmasked_values = np.where(~newvalues.mask)
7194
+ ij = ij[np.where(~newvalues.mask)]
7195
+ newvalues = newvalues[nonmasked_values]
7196
+
7197
+ elif keep == 'above':
7198
+ newvalues = np.ma.masked_array(newvalues[nonmasked_values], mask=(newvalues[nonmasked_values] < self.array.data[ij[:, 0], ij[:, 1]]))
7199
+
7200
+ nonmasked_values = np.where(~newvalues.mask)
7201
+ ij = ij[np.where(~newvalues.mask)]
7202
+ newvalues = newvalues[nonmasked_values]
7203
+
7204
+ self.array.data[ij[:, 0], ij[:, 1]] = newvalues
7205
+ else:
7206
+ # No mask --> boolean
7207
+
7208
+ if keep == 'below':
7209
+ newvalues = np.ma.masked_array(newvalues, mask=(newvalues > self.array.data[ij[:, 0], ij[:, 1]]))
7210
+
7211
+ nonmasked_values = np.where(~newvalues.mask)
7212
+ ij = ij[np.where(~newvalues.mask)]
7213
+ newvalues = newvalues[nonmasked_values]
7214
+
7215
+ elif keep == 'above':
7216
+ newvalues = np.ma.masked_array(newvalues, mask=(newvalues < self.array.data[ij[:, 0], ij[:, 1]]))
7217
+
7218
+ nonmasked_values = np.where(~newvalues.mask)
7219
+ ij = ij[np.where(~newvalues.mask)]
7220
+ newvalues = newvalues[nonmasked_values]
7221
+
7222
+ self.array.data[ij[:, 0], ij[:, 1]] = newvalues
7044
7223
 
7045
7224
  elif self.mngselection.myselection == 'all' and (grid_x is None and grid_y is None):
7225
+ # interpolation in all the cells
7226
+
7227
+ # Creating a grid for all cells
7046
7228
  decalx = self.origx + self.translx
7047
7229
  decaly = self.origy + self.transly
7048
7230
  x = np.arange(self.dx / 2. + decalx, float(self.nbx) * self.dx + self.dx / 2 + decalx, self.dx)
7049
7231
  y = np.arange(self.dy / 2. + decaly, float(self.nby) * self.dy + self.dy / 2 + decaly, self.dy)
7050
7232
  grid_x, grid_y = np.meshgrid(x, y, indexing='ij')
7233
+ grid_ij = self.xy2ij_np(np.concatenate([grid_x.ravel()[:, np.newaxis], grid_y.ravel()[:, np.newaxis]], axis=1))
7051
7234
 
7052
7235
  try:
7053
7236
  # Opérateur d'interpolation linéaire
@@ -7057,11 +7240,32 @@ class WolfArray(Element_To_Draw, header_wolf):
7057
7240
  interplin = mtri.LinearTriInterpolator(triang, coords[:,2])
7058
7241
  except:
7059
7242
  raise Warning(_('Bad triangulation - try with another method like Scipy'))
7243
+
7060
7244
  # Interpolation et récupération dans le numpy.array de l'objet Wolf
7061
- newvalues = interplin(grid_x,grid_y).astype(np.float32)
7062
- self.array.data[~newvalues.mask] = newvalues[~newvalues.mask]
7245
+ newvalues = interplin(grid_x,grid_y)
7246
+
7247
+ nonmasked_values = np.where(~newvalues.mask)
7248
+ ij = grid_ij[nonmasked_values]
7249
+ newvalues = newvalues[nonmasked_values]
7250
+
7251
+ if keep == 'below':
7252
+ newvalues = np.ma.masked_array(newvalues, mask=(newvalues > self.array.data[grid_ij[:, 0], grid_ij[:, 1]]))
7253
+
7254
+ nonmasked_values = np.where(~newvalues.mask)
7255
+ ij = grid_ij[nonmasked_values]
7256
+ newvalues = newvalues[nonmasked_values]
7257
+
7258
+ elif keep == 'above':
7259
+ newvalues = np.ma.masked_array(newvalues, mask=(newvalues < self.array.data[grid_ij[:, 0], grid_ij[:, 1]]))
7260
+
7261
+ nonmasked_values = np.where(~newvalues.mask)
7262
+ ij = grid_ij[nonmasked_values]
7263
+ newvalues = newvalues[nonmasked_values]
7264
+
7265
+ self.array.data[ij[:, 0], ij[:, 1]] = newvalues
7266
+
7063
7267
  elif (grid_x is not None and grid_y is not None):
7064
- ij = np.asarray([self.get_ij_from_xy(x, y) for x, y in zip(grid_x.flatten(),grid_y.flatten())])
7268
+ # Working on an imposed grid
7065
7269
 
7066
7270
  # Opérateur d'interpolation linéaire
7067
7271
  try:
@@ -7069,16 +7273,56 @@ class WolfArray(Element_To_Draw, header_wolf):
7069
7273
  if mask_tri is not None:
7070
7274
  triang.set_mask(mask_tri)
7071
7275
  interplin = mtri.LinearTriInterpolator(triang, coords[:,2]) # Interpolation et récupération dans le numpy.array de l'objet Wolf
7072
- newvalues = np.ma.masked_array([interplin(x, y) for x, y in zip(grid_x.flatten(),grid_y.flatten())])
7276
+ newvalues = np.ma.masked_array([interplin(x, y) for x, y in zip(grid_x.ravel(),grid_y.ravel())])
7073
7277
  except:
7074
7278
  raise Warning(_('Bad triangulation - try with another method like Scipy'))
7075
7279
 
7280
+ # newvalues is a vector of values
7281
+
7282
+ # ij is a vector of indices
7283
+ ij = np.asarray([self.get_ij_from_xy(x, y) for x, y in zip(grid_x.ravel(),grid_y.ravel())])
7284
+
7076
7285
  if newvalues.mask.shape!=():
7077
- ij = ij[np.where(~newvalues.mask)]
7078
- self.array.data[ij[:, 0], ij[:, 1]] = newvalues.data[np.where(~newvalues.mask)]
7286
+
7287
+ nonmasked_values = np.where(~newvalues.mask)
7288
+ ij = ij[nonmasked_values]
7289
+ newvalues = newvalues[nonmasked_values]
7290
+
7291
+ if keep == 'below':
7292
+ newvalues = np.ma.masked_array(newvalues, mask=(newvalues > self.array.data[ij[:, 0], ij[:, 1]]))
7293
+
7294
+ nonmasked_values = np.where(~newvalues.mask)
7295
+ ij = ij[nonmasked_values]
7296
+ newvalues = newvalues[nonmasked_values]
7297
+
7298
+ elif keep == 'above':
7299
+
7300
+ newvalues = np.ma.masked_array(newvalues, mask=(newvalues < self.array.data[ij[:, 0], ij[:, 1]]))
7301
+
7302
+ nonmasked_values = np.where(~newvalues.mask)
7303
+ ij = ij[nonmasked_values]
7304
+ newvalues = newvalues[nonmasked_values]
7305
+
7306
+ self.array.data[ij[:, 0], ij[:, 1]] = newvalues
7079
7307
  else:
7080
- self.array.data[ij[:, 0], ij[:, 1]] = newvalues.data
7308
+
7309
+ if keep == 'below':
7310
+ newvalues = np.ma.masked_array(newvalues, mask=(newvalues > self.array.data[ij[:, 0], ij[:, 1]]))
7311
+ nonmasked_values = np.where(~newvalues.mask)
7312
+ ij = ij[nonmasked_values]
7313
+ newvalues = newvalues[nonmasked_values]
7314
+ elif keep == 'above':
7315
+ newvalues = np.ma.masked_array(newvalues, mask=(newvalues < self.array.data[ij[:, 0], ij[:, 1]]))
7316
+ nonmasked_values = np.where(~newvalues.mask)
7317
+ ij = ij[nonmasked_values]
7318
+ newvalues = newvalues[nonmasked_values]
7319
+
7320
+ self.array.data[ij[:, 0], ij[:, 1]] = newvalues
7321
+
7081
7322
  else:
7323
+ # Working on the whole array
7324
+
7325
+ # Creating a grid for all cells
7082
7326
  decalx = self.origx + self.translx
7083
7327
  decaly = self.origy + self.transly
7084
7328
  x = np.arange(self.dx / 2. + decalx, float(self.nbx) * self.dx + self.dx / 2 + decalx, self.dx)
@@ -7092,12 +7336,25 @@ class WolfArray(Element_To_Draw, header_wolf):
7092
7336
  triang.set_mask(mask_tri)
7093
7337
  interplin = mtri.LinearTriInterpolator(triang, coords[:,2])
7094
7338
  # Interpolation et récupération dans le numpy.array de l'objet Wolf
7339
+
7340
+ # newvalues is an array
7095
7341
  newvalues = interplin(grid_x,grid_y).astype(np.float32)
7096
- self.array.data[~newvalues.mask] = newvalues[~newvalues.mask]
7342
+
7343
+ assert newvalues.shape == (self.nbx, self.nby), _('Bad shape for newvalues')
7344
+
7345
+ if keep == 'below':
7346
+ newvalues = np.ma.masked_array(newvalues, mask=(newvalues > self.array.data))
7347
+ elif keep == 'above':
7348
+ newvalues = np.ma.masked_array(newvalues, mask=(newvalues < self.array.data))
7349
+
7350
+ nonmasked_values = np.where(~newvalues.mask)
7351
+
7352
+ self.array.data[nonmasked_values] = newvalues[nonmasked_values]
7097
7353
  except:
7098
7354
  raise Warning(_('Bad triangulation - try with another method like Scipy'))
7099
7355
  else:
7100
7356
  if grid_x is None and grid_y is None:
7357
+
7101
7358
  decalx = self.origx + self.translx
7102
7359
  decaly = self.origy + self.transly
7103
7360
  x = np.arange(self.dx / 2. + decalx, float(self.nbx) * self.dx + self.dx / 2 + decalx, self.dx)
@@ -7108,22 +7365,80 @@ class WolfArray(Element_To_Draw, header_wolf):
7108
7365
  triang = mtri.Triangulation(coords[:,0],coords[:,1],triangles)
7109
7366
  interplin = mtri.LinearTriInterpolator(triang, coords[:,2])
7110
7367
  # Interpolation et récupération dans le numpy.array de l'objet Wolf
7111
- newvalues = np.ma.masked_array([interplin(x, y) for x, y in zip(grid_x.flatten(),grid_y.flatten())])
7368
+ newvalues = np.ma.masked_array([interplin(x, y) for x, y in zip(grid_x.ravel(), grid_y.ravel())])
7112
7369
  # newvalues = interplin(grid_x,grid_y).astype(np.float32)
7113
- self.array.data[~newvalues.mask] = newvalues[~newvalues.mask]
7370
+
7371
+ nonmasked_values = np.where(~newvalues.mask)
7372
+ grid_x = grid_x.ravel()[nonmasked_values]
7373
+ grid_y = grid_y.ravel()[nonmasked_values]
7374
+ newvalues = newvalues[nonmasked_values]
7375
+
7376
+ # make a shape (n, 2) from grid_x and grid_y
7377
+ grid_x = grid_x[:, np.newaxis]
7378
+ grid_y = grid_y[:, np.newaxis]
7379
+ # concatenate grid_x and grid_y
7380
+ grid_ij = self.xy2ij_np(np.concatenate([grid_x, grid_y], axis=1))
7381
+
7382
+ if keep == 'below':
7383
+ newvalues = np.ma.masked_array(newvalues, mask=(newvalues > self.array.data[grid_ij[:,0], grid_ij[:,1]]))
7384
+
7385
+ nonmasked_values = np.where(~newvalues.mask)
7386
+ grid_ij = grid_ij[nonmasked_values]
7387
+ newvalues = newvalues[nonmasked_values]
7388
+
7389
+ elif keep == 'above':
7390
+ newvalues = np.ma.masked_array(newvalues, mask=(newvalues < self.array.data[grid_ij[:,0], grid_ij[:,1]]))
7391
+
7392
+ nonmasked_values = np.where(~newvalues.mask)
7393
+ grid_ij = grid_ij[nonmasked_values]
7394
+ newvalues = newvalues[nonmasked_values]
7395
+
7396
+ self.array.data[grid_ij[:,0], grid_ij[:,1]] = newvalues
7397
+
7114
7398
  else:
7115
- ij = np.asarray([self.get_ij_from_xy(x, y) for x, y in zip(grid_x.flatten(),grid_y.flatten())])
7399
+ ij = np.asarray([self.get_ij_from_xy(x, y) for x, y in zip(grid_x.ravel(),grid_y.ravel())])
7116
7400
 
7117
7401
  # Opérateur d'interpolation linéaire
7118
7402
  triang = mtri.Triangulation(coords[:,0],coords[:,1],triangles)
7119
7403
  interplin = mtri.LinearTriInterpolator(triang, coords[:,2]) # Interpolation et récupération dans le numpy.array de l'objet Wolf
7120
- newvalues = np.ma.masked_array([interplin(x, y) for x, y in zip(grid_x.flatten(),grid_y.flatten())])
7404
+ newvalues = np.ma.masked_array([interplin(x, y) for x, y in zip(grid_x.ravel(), grid_y.ravel())])
7121
7405
 
7122
7406
  if newvalues.mask.shape!=():
7123
- ij = ij[np.where(~newvalues.mask)]
7124
- self.array.data[ij[:, 0], ij[:, 1]] = newvalues.data[np.where(~newvalues.mask)]
7407
+ nonmasked_values = np.where(~newvalues.mask)
7408
+ ij = ij[nonmasked_values]
7409
+ newvalues = newvalues[nonmasked_values]
7410
+
7411
+ if keep == 'below':
7412
+ newvalues = np.ma.masked_array(newvalues, mask=(newvalues > self.array.data[ij[:, 0], ij[:, 1]]))
7413
+
7414
+ nonmasked_values = np.where(~newvalues.mask)
7415
+ ij = ij[nonmasked_values]
7416
+ newvalues = newvalues[nonmasked_values]
7417
+
7418
+ elif keep == 'above':
7419
+ newvalues = np.ma.masked_array(newvalues, mask=(newvalues < self.array.data[ij[:, 0], ij[:, 1]]))
7420
+
7421
+ nonmasked_values = np.where(~newvalues.mask)
7422
+ ij = ij[nonmasked_values]
7423
+ newvalues = newvalues[nonmasked_values]
7424
+
7425
+ self.array.data[ij[:, 0], ij[:, 1]] = newvalues
7125
7426
  else:
7126
- self.array.data[ij[:, 0], ij[:, 1]] = newvalues.data
7427
+ if keep == 'below':
7428
+ newvalues = np.ma.masked_array(newvalues, mask=(newvalues > self.array.data[ij[:, 0], ij[:, 1]]))
7429
+
7430
+ nonmasked_values = np.where(~newvalues.mask)
7431
+ ij = ij[nonmasked_values]
7432
+ newvalues = newvalues[nonmasked_values]
7433
+
7434
+ elif keep == 'above':
7435
+ newvalues = np.ma.masked_array(newvalues, mask=(newvalues < self.array.data[ij[:, 0], ij[:, 1]]))
7436
+
7437
+ nonmasked_values = np.where(~newvalues.mask)
7438
+ ij = ij[nonmasked_values]
7439
+ newvalues = newvalues[nonmasked_values]
7440
+
7441
+ self.array.data[ij[:, 0], ij[:, 1]] = newvalues
7127
7442
 
7128
7443
  #on force les valeurs masquées à nullvalue afin que l'interpolation n'applique pas ses effets dans cette zone
7129
7444
  self.array.data[self.array.mask]= self.nullvalue
@@ -7131,13 +7446,15 @@ class WolfArray(Element_To_Draw, header_wolf):
7131
7446
  use_scipy=True
7132
7447
 
7133
7448
  if interp_method != 'matplotlib' or use_scipy:
7449
+ # We need to convert the triangle to a vector to call the interpolation
7450
+
7134
7451
  for curtri in triangles:
7135
7452
  curvec = vector(is2D=False)
7136
7453
  for curpt in curtri:
7137
- curvec.add_vertex(wolfvertex(coords[curpt,0],coords[curpt,1], coords[curpt,2]))
7454
+ curvec.add_vertex(wolfvertex(coords[curpt,0], coords[curpt,1], coords[curpt,2]))
7138
7455
  curvec.close_force()
7139
7456
 
7140
- self.interpolate_on_polygon(curvec, "linear")
7457
+ self.interpolate_on_polygon(curvec, "linear", keep)
7141
7458
 
7142
7459
  self.reset_plot()
7143
7460
  return
@@ -8558,7 +8875,7 @@ class WolfArray(Element_To_Draw, header_wolf):
8558
8875
  :param step_factor: step factor for the discretization of myvect (<1 for thinner, >1 for coarser)
8559
8876
  """
8560
8877
 
8561
- if step_factor>=1.0:
8878
+ if step_factor>1.0:
8562
8879
  logging.warning("Step_factor greater than 1.0 may lead to lots of missing (i,j) even if faster")
8563
8880
  else:
8564
8881
  def mod_fix(x, y, tol=1e-10):
@@ -11214,7 +11531,9 @@ class WolfArrayMB(WolfArray):
11214
11531
 
11215
11532
  self.reset_plot()
11216
11533
 
11217
- def interpolate_on_polygon(self, working_vector: vector, method:Literal["nearest", "linear", "cubic"]="linear"):
11534
+ def interpolate_on_polygon(self, working_vector: vector,
11535
+ method:Literal["nearest", "linear", "cubic"]="linear",
11536
+ keep:Literal['all', 'below', 'above'] = 'all'):
11218
11537
  """
11219
11538
  Interpolation sous un polygone
11220
11539
 
@@ -11227,12 +11546,14 @@ class WolfArrayMB(WolfArray):
11227
11546
  """
11228
11547
 
11229
11548
  for curblock in self.myblocks.values():
11230
- curblock.interpolate_on_polygon(working_vector, method)
11549
+ curblock.interpolate_on_polygon(working_vector, method, keep)
11231
11550
 
11232
- def interpolate_on_polygons(self, working_zone: zone, method:Literal["nearest", "linear", "cubic"]="linear"):
11551
+ def interpolate_on_polygons(self, working_zone: zone,
11552
+ method:Literal["nearest", "linear", "cubic"]="linear",
11553
+ keep:Literal['all', 'below', 'above'] = 'all'):
11233
11554
 
11234
11555
  for curvector in working_zone.myvectors:
11235
- self.interpolate_on_polygon(curvector, method)
11556
+ self.interpolate_on_polygon(curvector, method, keep)
11236
11557
 
11237
11558
  def interpolate_on_polyline(self, working_vector:vector, usemask=True):
11238
11559
  """