wolfhece 2.1.74__py3-none-any.whl → 2.1.76__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/PyDraw.py CHANGED
@@ -145,14 +145,14 @@ class Colors_1to9(wx.Frame):
145
145
  def __init__(self, parent):
146
146
 
147
147
  self._parent = parent
148
- self.colors1to9 = [(0, 0, 255, 255),
149
- (0, 255, 0, 255),
150
- (0, 128, 255, 255),
151
- (255, 255, 0, 255),
152
- (255, 165, 0, 255),
153
- (128, 0, 128, 255),
154
- (255, 192, 203, 255),
155
- (165, 42, 42, 255),
148
+ self.colors1to9 = [(0, 0, 255, 255),
149
+ (0, 255, 0, 255),
150
+ (0, 128, 255, 255),
151
+ (255, 255, 0, 255),
152
+ (255, 165, 0, 255),
153
+ (128, 0, 128, 255),
154
+ (255, 192, 203, 255),
155
+ (165, 42, 42, 255),
156
156
  (128, 128, 128, 255)]
157
157
 
158
158
  if self.file.exists():
@@ -214,7 +214,7 @@ class Colors_1to9(wx.Frame):
214
214
  self.Bind(wx.EVT_BUTTON, self.OnSave, cmdSave)
215
215
 
216
216
  self.Show()
217
-
217
+
218
218
  def Apply(self):
219
219
 
220
220
  for i in range(9):
@@ -228,7 +228,7 @@ class Colors_1to9(wx.Frame):
228
228
 
229
229
  def OnCancel(self, event):
230
230
  self.Close()
231
-
231
+
232
232
  def OnSetDefault(self, event):
233
233
  self.colors1to9 = [(0, 0, 255, 255),
234
234
  (0, 255, 0, 255),
@@ -1036,6 +1036,7 @@ class WolfMapViewer(wx.Frame):
1036
1036
  updatecolors_laz = self.menulaz.Append(wx.ID_ANY, _('Change colors - Classification'), _('Change color map associated to the current classification'),)
1037
1037
  fillarray_laz = self.menulaz.Append(wx.ID_ANY, _('Fill active array from LAZ data'), _('Fill an array from the LAZ data'),)
1038
1038
  selectarray_laz = self.menulaz.Append(wx.ID_ANY, _('Select cells in array from LAZ data'), _('Select nodes in active array from the LAZ data'),)
1039
+ countarray_laz = self.menulaz.Append(wx.ID_ANY, _('Count LAZ data in cells'), _('Count the number of LAZ data in each cell of the matrix'),)
1039
1040
 
1040
1041
  def menu_wolf2d(self):
1041
1042
 
@@ -2749,7 +2750,7 @@ class WolfMapViewer(wx.Frame):
2749
2750
  self.canvas.Bind(wx.EVT_MOUSEWHEEL, self.OnButton)
2750
2751
 
2751
2752
  self.treelist.Bind(dataview.EVT_TREELIST_ITEM_CHECKED, self.OnCheckItem)
2752
- self.treelist.Bind(dataview.EVT_TREELIST_ITEM_ACTIVATED, self.OnActivateTreeElem)
2753
+ self.treelist.Bind(dataview.EVT_TREELIST_ITEM_ACTIVATED, self.OnActivateTreeElem)
2753
2754
  self.treelist.Bind(dataview.EVT_TREELIST_ITEM_CONTEXT_MENU, self.OntreeRight)
2754
2755
  self.treelist.Bind(wx.EVT_CHAR_HOOK, self.OnHotKey)
2755
2756
  self.treelist.Bind(dataview.EVT_TREELIST_SELECTION_CHANGED,self.OnSelectItem)
@@ -4256,6 +4257,126 @@ class WolfMapViewer(wx.Frame):
4256
4257
 
4257
4258
  logging.info(_('Filling done'))
4258
4259
 
4260
+ def count_active_array_from_laz(self, array:WolfArray = None, used_codes:list = [], chunk_size:float = 500.):
4261
+ """ Fill active array with laz data
4262
+
4263
+ :param array: array to fill
4264
+ :param used_codes: codes to use
4265
+ :param operator: operator to use
4266
+ """
4267
+
4268
+ if self.mylazgrid is None:
4269
+ return
4270
+
4271
+ if array is None:
4272
+ logging.error(_('No array'))
4273
+ return
4274
+
4275
+ if len(used_codes) == 0 :
4276
+ keycode = [key for key,val in self.mylazgrid.colors.classification.items()]
4277
+ names = [val[0] for key,val in self.mylazgrid.colors.classification.items()]
4278
+
4279
+ with wx.MultiChoiceDialog(None, _('Choose the codes to use'), _('Codes'), names) as dlg:
4280
+ if dlg.ShowModal() == wx.ID_OK:
4281
+ data = {}
4282
+ used_codes = dlg.GetSelections()
4283
+ used_codes = [float(keycode[cur]) for cur in used_codes]
4284
+ else:
4285
+ return
4286
+
4287
+ bounds = array.get_bounds()
4288
+
4289
+ # align bounds on chunk_size
4290
+ bounds[0][0] = bounds[0][0] - bounds[0][0] % chunk_size
4291
+ bounds[0][1] = bounds[0][1] + chunk_size - bounds[0][1] % chunk_size
4292
+ bounds[1][0] = bounds[1][0] - bounds[1][0] % chunk_size
4293
+ bounds[1][1] = bounds[1][1] + chunk_size - bounds[1][1] % chunk_size
4294
+
4295
+ chunks_x = np.arange(bounds[0][0], bounds[0][1], chunk_size)
4296
+ chunks_y = np.arange(bounds[1][0], bounds[1][1], chunk_size)
4297
+
4298
+ for curx in tqdm(chunks_x, 'Chunks'):
4299
+ for cury in chunks_y:
4300
+
4301
+ curbounds = [[curx, curx + chunk_size], [cury, cury + chunk_size]]
4302
+
4303
+ logging.info(_('Scan {}-{} {}-{}').format(curbounds[0][0],curbounds[0][1],curbounds[1][0],curbounds[1][1]))
4304
+ self.mylazdata = self.mylazgrid.scan(curbounds)
4305
+
4306
+ if len(self.mylazdata) == 0:
4307
+ continue
4308
+
4309
+ # Test codes
4310
+ data = {}
4311
+ for curcode in used_codes:
4312
+ data[curcode] = self.mylazdata[self.mylazdata[:, 3] == curcode]
4313
+
4314
+ # Treat data for each code
4315
+ for curdata in data.values():
4316
+
4317
+ if curdata.shape[0] == 0:
4318
+ continue
4319
+ else:
4320
+ logging.info(_('Code {} : {} points'.format(curdata[0,3], curdata.shape[0])))
4321
+
4322
+ # get i,j from x,y
4323
+ i,j = array.get_ij_from_xy(curdata[:, 0], curdata[:, 1]) #= np.float32(self.mylazdata[:, 2])
4324
+
4325
+ # keep only valid points -- inside the array
4326
+ used = np.where((i >=0) & (i < array.nbx) & (j >=0) & (j < array.nby))[0]
4327
+
4328
+ if len(used) == 0:
4329
+ continue
4330
+
4331
+ i = i[used]
4332
+ j = j[used]
4333
+ z = curdata[used, 2]
4334
+
4335
+ # create a key array
4336
+ keys = np.vstack((i,j)).T
4337
+ # find unique keys
4338
+ keys = np.unique(keys, axis=0)
4339
+
4340
+ # create a ijz array
4341
+ ijz = np.vstack((i, j, z)).T
4342
+
4343
+ # sort ijz array according to keys
4344
+ #
4345
+ # the most important indice is the last one enumerated in lexsort
4346
+ # see : https://numpy.org/doc/stable/reference/generated/numpy.lexsort.html
4347
+ ijz = ijz[np.lexsort((ijz[:,1], ijz[:,0]))]
4348
+
4349
+ # find first element of each key
4350
+ idx = np.where(np.abs(np.diff(ijz[:,0])) + np.abs(np.diff(ijz[:,1])) != 0)[0]
4351
+
4352
+ # add last element
4353
+ idx = np.concatenate((idx, [ijz.shape[0]]))
4354
+
4355
+ assert len(idx) == keys.shape[0], 'Error in filling'
4356
+
4357
+ logging.info(_('Cells to fill : {}'.format(len(idx))))
4358
+
4359
+ # apply operator
4360
+ vals = {}
4361
+ start_ii = 0
4362
+ for ii, key in enumerate(keys):
4363
+ end_ii = idx[ii]+1
4364
+
4365
+ vals[(key[0], key[1])] = end_ii - start_ii
4366
+
4367
+ start_ii = end_ii
4368
+
4369
+ if len(vals) > 0:
4370
+ # create a new ijz array
4371
+ newijz = np.asarray([[key[0], key[1], val] for key, val in vals.items()], dtype = np.float32)
4372
+
4373
+ array.fillin_from_ijz(newijz)
4374
+
4375
+ array.reset_plot()
4376
+ self.Paint()
4377
+
4378
+ logging.info(_('Counting done'))
4379
+
4259
4380
  def init_laz_from_numpy(self, fn=None):
4260
4381
  """ Read LAZ data stored in numpy array"""
4261
4382
 
@@ -5143,6 +5264,17 @@ class WolfMapViewer(wx.Frame):
5143
5264
  autoscale = False
5144
5265
  self.fill_active_array_from_laz(self.active_array)
5145
5266
 
5267
+ elif itemlabel == _('Count LAZ data in cells'):
5268
+ if self.mylazgrid is None:
5269
+ logging.warning('')
5270
+ return
5271
+ if self.active_array is None:
5272
+ logging.warning(_('No active array -- select an array first and retry!'))
5273
+ return
5274
+
5275
+ autoscale = False
5276
+ self.count_active_array_from_laz(self.active_array)
5277
+
5146
5278
  elif itemlabel == _('Select cells in array from LAZ data'):
5147
5279
  if self.mylazgrid is None:
5148
5280
  logging.warning('')
@@ -7032,7 +7164,7 @@ class WolfMapViewer(wx.Frame):
7032
7164
  self.selected_object.save()
7033
7165
  elif text==_('Up'):
7034
7166
  self.upobj()
7035
-
7167
+
7036
7168
  elif text == _('Down'):
7037
7169
  self.downobj()
7038
7170
 
@@ -7056,7 +7188,7 @@ class WolfMapViewer(wx.Frame):
7056
7188
 
7057
7189
  if self.get_label_selecteditem() == _("Active : ") + label:
7058
7190
  self.set_label_selecteditem(_("Active : ") + newlab)
7059
-
7191
+
7060
7192
  dlg.Destroy()
7061
7193
 
7062
7194
  elif text == _('Duplicate'):
@@ -7071,7 +7203,7 @@ class WolfMapViewer(wx.Frame):
7071
7203
  if ret != wx.ID_OK:
7072
7204
  dlg.Destroy()
7073
7205
  return
7074
-
7206
+
7075
7207
  newlab = dlg.GetValue()
7076
7208
  dlg.Destroy()
7077
7209
 
@@ -8344,7 +8476,7 @@ class WolfMapViewer(wx.Frame):
8344
8476
  # self.mytooltip.SetIcon(self.GetIcon()) # update icon
8345
8477
  self.mytooltip.SetWindowStyle(wx.DEFAULT_FRAME_STYLE) # | wx.STAY_ON_TOP) # on top, with Title bar
8346
8478
 
8347
- # self.mytooltip.Show(True)
8479
+ self.mytooltip.Show(True)
8348
8480
 
8349
8481
  def Autoscale(self, update_backfore=True):
8350
8482
  """ Redimensionnement de la fenêtre pour afficher tous les objets """
@@ -8803,10 +8935,12 @@ class WolfMapViewer(wx.Frame):
8803
8935
 
8804
8936
  elif key == 60 and shiftdown: #'>'
8805
8937
  if self.active_array is not None:
8806
- self.active_array.dilate_contour_selection(1)
8938
+ if self.active_array.SelectionData is not None:
8939
+ self.active_array.SelectionData.dilate_contour_selection(1)
8807
8940
  elif key == 60 and not shiftdown: #'<'
8808
8941
  if self.active_array is not None:
8809
- self.active_array.erode_contour_selection()
8942
+ if self.active_array.SelectionData is not None:
8943
+ self.active_array.SelectionData.erode_contour_selection()
8810
8944
 
8811
8945
  elif key == wx.WXK_F2 and shiftdown:
8812
8946
 
@@ -9076,10 +9210,12 @@ class WolfMapViewer(wx.Frame):
9076
9210
 
9077
9211
  elif key == 60 and shiftdown: #'>'
9078
9212
  if self.active_array is not None:
9079
- self.active_array.dilate_selection(1)
9213
+ if self.active_array.SelectionData is not None:
9214
+ self.active_array.SelectionData.dilate_selection(1)
9080
9215
  elif key == 60 and not shiftdown: #'<'
9081
9216
  if self.active_array is not None:
9082
- self.active_array.erode_selection(1)
9217
+ if self.active_array.SelectionData is not None:
9218
+ self.active_array.SelectionData.erode_selection(1)
9083
9219
 
9084
9220
  elif key == wx.WXK_ESCAPE:
9085
9221
 
@@ -9145,16 +9281,16 @@ class WolfMapViewer(wx.Frame):
9145
9281
  logging.info(_('Please select some nodes before transfering to the dictionary, not ALL !'))
9146
9282
  return
9147
9283
 
9148
- # colors = [(0, 0, 255, 255),
9149
- # (0, 255, 0, 255),
9150
- # (0, 128, 255, 255),
9151
- # (255, 255, 0, 255),
9152
- # (255, 165, 0, 255),
9153
- # (128, 0, 128, 255),
9154
- # (255, 192, 203, 255),
9155
- # (165, 42, 42, 255),
9284
+ # colors = [(0, 0, 255, 255),
9285
+ # (0, 255, 0, 255),
9286
+ # (0, 128, 255, 255),
9287
+ # (255, 255, 0, 255),
9288
+ # (255, 165, 0, 255),
9289
+ # (128, 0, 128, 255),
9290
+ # (255, 192, 203, 255),
9291
+ # (165, 42, 42, 255),
9156
9292
  # (128, 128, 128, 255)]
9157
-
9293
+
9158
9294
  idx = LIST_1TO9.index(key)
9159
9295
  if idx > 8:
9160
9296
  idx -= 9
wolfhece/apps/version.py CHANGED
@@ -5,7 +5,7 @@ class WolfVersion():
5
5
 
6
6
  self.major = 2
7
7
  self.minor = 1
8
- self.patch = 74
8
+ self.patch = 76
9
9
 
10
10
  def __str__(self):
11
11
 
@@ -58,9 +58,102 @@ KIWIS WebServices command :
58
58
  """
59
59
 
60
60
  URL_SERVICE = 'https://hydrometrie.wallonie.be/services'
61
+ URL_SERVICE_WATERINFO = 'https://download.waterinfo.be/tsmdownload'
62
+ URL_SERVICE_HICWS = 'https://hicws.vlaanderen.be'
63
+
61
64
  URL_SPW = URL_SERVICE + '/KiWIS/KiWIS'
65
+ URL_WATERINFO = URL_SERVICE_WATERINFO + '/KiWIS/KiWIS'
66
+ URL_HICWS = URL_SERVICE_HICWS + '/KiWIS/KiWIS'
67
+
62
68
  URL_TOKEN = URL_SERVICE + '/auth/token/'
63
69
 
70
+ # See : https://hicws.vlaanderen.be/Manual_for_the_use_of_webservices_HIC.pdf
71
+ class HICWS_GroupID(Enum):
72
+ FlowRate_daily = ('Afvoer_dag', 156169)
73
+ FlowRate_hig_res = ('Afvoer_hoge resolutie', 156170)
74
+ FlowRate_hourly = ('Afvoer_uur', 156171)
75
+ Astronomic_predictions_Scheldt_and_coastal_area = ('Astronomische voorspellingen reeksen Schelde en kust (LAT)', 512458)
76
+ Astronomic_predictions_Scheldt_and_coastal_area_high_res = ('AstroAstronomische voorspellingen reeksen Schelde en kust (mTAW)', 354718)
77
+ Astronomic_predictions_Scheldt_and_coastal_area_high_low = ('Astronomische voorspellingen Hoog-en laagwaters Schelde en kust (LAT)', 515316)
78
+ Astronomic_predictions_Scheldt_and_coastal_area_high_low_highres = ('Astronomische voorspellingen Hoog-en laagwaters Schelde en kust (mTAW)', 350099)
79
+ Calculated_Discharge_important = ('Berekende afvoeren sleutellocaties waterwegen', 260592)
80
+ Calculated_Area_Precipitation = ('Berekende gebiedsneerslagen belangrijke meetlocaties HIC', 156159)
81
+ Chlorophyl_high_res = ('Chlorofyl_hoge resolutie', 156172)
82
+ Conductivity_high_res = ('Conductiviteit_hoge resolutie', 156173)
83
+ Precipitation_daily = ('Neerslag_dag', 156166)
84
+ Precipitation_high_res = ('Neerslag_hoge resolutie', 156167)
85
+ Precipitation_yearly = ('Neerslag_jaar', 156191)
86
+ Precipitation_monthly = ('Neerslag_maand', 156190)
87
+ Precipitation_hourly = ('Neerslag_uur', 156168)
88
+ Salinity_high_res = ('Saliniteit_hoge resolutie', 421208)
89
+ Sediment_Concentration = ('Sedimentconcentratie_hoge resolutie', 156188)
90
+ Flow_Direction_high_res = ('Stroomrichting_hoge resolutie', 156158)
91
+ Flow_Velocity = ('Stroomsnelheid_hoge resolutie', 156199)
92
+ Turbidity = ('Turbiditeit_hoge resolutie', 156202)
93
+ Tidal_Previsions_Scheldt_ensemble = ('Verwachtingen Tijgebied Schelde (HWLW)', 432821)
94
+ Forecast_Discharge_shortterm_48h = ('Voorspellingen afvoer korte termijn (48u)', 506057)
95
+ Forecast_Discharge_longterm_10d = ('Voorspellingen afvoer lange termijn (10 dagen)', 506059)
96
+ Forecast_area_48h = ('Voorspellingen berekende gebiedsneerslagen belangrijke meetlocaties HIC korte termijn (48u)', 506060)
97
+ Forecast_area_10d = ('Voorspellingen berekende gebiedsneerslagen belangrijke meetlocaties HIC lange termijn (10 dagen)', 506061)
98
+ Forecast_waterlevel_48h = ('Voorspellingen waterstand korte termijn (48u)', 506056)
99
+ Forecast_waterlevel_10d = ('Voorspellingen waterstand lange termijn (10 dagen)', 506058)
100
+ Water_Level_daily = ('Waterstand_dag', 156162)
101
+ Water_Level_high_res = ('Waterstand_hoge resolutie', 156163)
102
+ High_Low_water_Scheldt = ('Waterstand_Hoog-en laagwaters tijgebied Schelde', 156165)
103
+ Scheldt_High_Water = ('Waterstand_Hoogwaters tijgebied', 510205)
104
+ Scheldt_Low_Water = ('Waterstand_Laagwaters tijgebied', 510207)
105
+ Water_Level_hourly = ('Waterstand_uur', 156164)
106
+ Water_Temperature = ('Watertemperatuur_hoge resolutie', 156200)
107
+ Oxygen_Concentration = ('Zuurstofgehalte_hoge resolutie', 156207)
108
+ Oxygen_Saturation = ('Zuurstofverzadiging_hoge resolutie', 156208)
109
+ pH = ('Zuurtegraad_hoge resolutie', 156197)
110
+
111
+ #See : https://waterinfo.vlaanderen.be/download/9f5ee0c9-dafa-46de-958b-7cac46eb8c23?dl=0
112
+ class WaterInfo_GroupdID(Enum):
113
+ Flowrate_15m = ('Afvoer_15m', 192786)
114
+ Flowrate_daily = ('Afvoer_dag', 192893)
115
+ Flowrate_yearly = ('Afvoer_jaar', 192895)
116
+ Flowrate_monthly = ('Afvoer_maand', 192894)
117
+ Flowrate_hourly = ('Afvoer_uur', 192892)
118
+ Ground_Saturation = ('Bodemverzadiging_15m', 192929)
119
+ Ground_Humidity = ('Bodemvocht_15m', 192928)
120
+ Dew_Point_Temparature = ('Dauwpunttemperatuur_15m', 192923)
121
+ Salinity = ('EC verziltingsmeetnet', 383065)
122
+ projectmetingen = ('EC projectmetingen', 381863)
123
+ Ground_Temperature = ('Grondtemperatuur_15m', 192924)
124
+ Ground_Heat = ('Grondwarmte_15m', 192916)
125
+ Radiation = ('Instraling_15m', 192920)
126
+ Atmospheric_Pressure = ('Luchtdruk_15m', 192918)
127
+ Atmospheric_Temperature = ('Luchttemperatuur175cm_15m', 192922)
128
+ Rain_15m = ('Neerslag_15m', 192896)
129
+ Rain_1m = ('Neerslag_1m', 199792)
130
+ Rain_daily = ('Neerslag_dag', 192898)
131
+ Rain_yearly = ('Neerslag_jaar', 192900)
132
+ Rain_monthly = ('Neerslag_maand', 192899)
133
+ Rain_hourly = ('Neerslag_uur', 192897)
134
+ Relative_Humidity = ('RelatVocht_15m', 192919)
135
+ Evaporation_Monteih_15m = ('VerdampingMonteith_15m', 192927)
136
+ Evaporation_Monteih_daily = ('VerdampingMonteith_dag', 295480)
137
+ Evaporation_Monteih_yearly = ('VerdampingMonteith_jaar', 295483)
138
+ Evaporation_Monteih_monthly = ('VerdampingMonteith_maand', 295482)
139
+ Evaporation_Penman_15m = ('VerdampingPenman_15m', 204341)
140
+ Evaporation_Penman_daily = ('VerdampingPenman_dag', 295474)
141
+ Evaporation_Penman_yearly = ('VerdampingPenman_jaar', 295479)
142
+ Evaporation_Penman_monthly = ('VerdampingPenman_maand', 295475)
143
+ Water_speed_15m = ('Watersnelheid_15m', 192901)
144
+ Water_speed_daily = ('Watersnelheid_dag', 192903)
145
+ Water_speed_yearly = ('Watersnelheid_jaar', 192905)
146
+ Water_speed_monthly = ('Watersnelheid_maand', 192904)
147
+ Water_speed_hourly = ('Watersnelheid_uur', 192902)
148
+ Water_Level_15m = ('Waterstand_15m', 192780)
149
+ Water_Level_daily = ('Waterstand_dag', 192782)
150
+ Water_Level_yearly = ('Waterstand_jaar', 192784)
151
+ Water_Level_monthly = ('Waterstand_maand', 192783)
152
+ Water_Level_hourly = ('Waterstand_uur', 192785)
153
+ Water_Temperature = ('Watertemperatuur_15m', 325066)
154
+ Wind_Direction = ('Windrichting_15m', 192926)
155
+ Wind_Speed = ('Windsnelheid_15m', 192925)
156
+
64
157
  class kiwis_command(Enum):
65
158
  getrequestinfo = "getrequestinfo"
66
159
  getGroupList = "getGroupList"
@@ -234,8 +327,8 @@ class hydrometry():
234
327
 
235
328
  try:
236
329
  self.daily_token()
237
- except:
238
- logging.warning('No token available')
330
+ except Exception as e:
331
+ logging.warning('No token available or Error in hydrometry init :', e)
239
332
 
240
333
  try:
241
334
  self.get_requests()
@@ -243,7 +336,8 @@ class hydrometry():
243
336
  self.get_stations()
244
337
  self.get_groups()
245
338
  self.save_struct(self.dir)
246
- except:
339
+ except Exception as e:
340
+ print('Error in hydrometry init :', e)
247
341
  self.realstations = None
248
342
  pass
249
343
 
@@ -253,10 +347,16 @@ class hydrometry():
253
347
  ret+=curcol+'\n'
254
348
  return ret
255
349
 
256
- def _get_commandstr(self, which:str):
350
+ def _get_commandstr(self, which:str, format='json'):
257
351
  """ Construction de la commande à envoyer au serveur KIWIS """
258
352
 
259
- return self.url+'?request='+which.value+'&format=json'
353
+ datasource = ''
354
+ if self.url == URL_WATERINFO:
355
+ datasource = '&datasource=1'
356
+ elif self.url == URL_HICWS:
357
+ datasource = '&datasource=4'
358
+
359
+ return self.url+'?request='+which.value+'&format='+format + datasource
260
360
 
261
361
  def daily_token(self):
262
362
  """
@@ -293,7 +393,11 @@ class hydrometry():
293
393
  return
294
394
  self.token = None
295
395
 
296
- self._header = {'Authorization': 'Bearer {}'.format(self.token['access_token'])}
396
+ try:
397
+ self._header = {'Authorization': 'Bearer {}'.format(self.token['access_token'])}
398
+ except Exception as e:
399
+ logging.error('Error in daily_token :', e)
400
+ self._header = None
297
401
 
298
402
  def check_plot(self):
299
403
  """ Instance is checked in mapviewer """
@@ -303,6 +407,10 @@ class hydrometry():
303
407
  """ Instance is unchecked in mapviewer """
304
408
  self.plotted = False
305
409
 
410
+ def get_path(self, dir:Path, filename:str):
411
+ """ Get path of instance """
412
+ return Path(dir) / (self.url.replace('/','_').replace('https:','') + filename)
413
+
306
414
  def save_struct(self, dir=''):
307
415
  """Sauvegarde des structures dans un répertoire
308
416
 
@@ -315,12 +423,12 @@ class hydrometry():
315
423
  dir = Path(dir)
316
424
  dir.mkdir(parents=True, exist_ok=True)
317
425
 
318
- self.sites.to_csv(dir / 'sites.csv')
319
- self.stations.to_csv(dir / 'stations.csv')
320
- self.groups.to_csv(dir / 'groups.csv')
321
- self.requests.to_csv(dir / 'requests.csv')
426
+ self.sites.to_csv(self.get_path(dir, 'sites.csv'))
427
+ self.stations.to_csv(self.get_path(dir, 'stations.csv'))
428
+ self.groups.to_csv(self.get_path(dir, 'groups.csv'))
429
+ self.requests.to_csv(self.get_path(dir, 'requests.csv'))
322
430
 
323
- def _get_stations_pythonlist(self, site_no:str|int, onlyreal:bool= True):
431
+ def _get_stations_pythonlist(self, site_no:str|int, onlyreal:bool= True, return_only_name:bool=False):
324
432
  """ Obtention des stations pour le site en liste python
325
433
 
326
434
  :param site_no: numéro du site
@@ -332,10 +440,14 @@ class hydrometry():
332
440
  else:
333
441
  stations = self.stations[self.stations[kiwis_site_fields.site_no.value]==site_no]
334
442
 
335
- list_name_code = [curname+' --- '+curno for curname,curno in zip(stations[station_fields.STATION_NAME.value].values,stations[station_fields.STATION_NO.value].values)]
336
- list_code_name = [curno +' --- '+curname for curname,curno in zip(stations[station_fields.STATION_NAME.value].values,stations[station_fields.STATION_NO.value].values)]
443
+ if return_only_name:
444
+ return [curname for curname in stations[station_fields.STATION_NAME.value].values]
337
445
 
338
- return list_name_code, list_code_name
446
+ else:
447
+ list_name_code = [curname+' --- '+curno for curname,curno in zip(stations[station_fields.STATION_NAME.value].values,stations[station_fields.STATION_NO.value].values)]
448
+ list_code_name = [curno +' --- '+curname for curname,curno in zip(stations[station_fields.STATION_NAME.value].values,stations[station_fields.STATION_NO.value].values)]
449
+
450
+ return list_name_code, list_code_name
339
451
 
340
452
  def _get_sites_pythonlist(self):
341
453
  """ Obtention des sites en liste python """
@@ -365,7 +477,7 @@ class hydrometry():
365
477
 
366
478
  returnfields = f'{kiwis_site_fields.site_no.value},'
367
479
  returnfields += f'{station_fields.STATION_NO.value},{station_fields.STATION_NAME.value},{station_fields.STATION_ID.value},'
368
- returnfields += f'{station_fields.STATION_LOCAL_X.value},{station_fields.STATION_LOCAL_Y.value},'
480
+ returnfields += f'{station_fields.STATION_LOCAL_X.value},{station_fields.STATION_LOCAL_Y.value},' if self.url==URL_SPW else ''
369
481
  returnfields += f'{station_fields.STATION_LATITUDE.value},{station_fields.STATION_LONGITUDE.value},'
370
482
  returnfields += f'{station_fields.RIVER_NAME.value},'
371
483
  returnfields += 'ca_sta'
@@ -377,25 +489,50 @@ class hydrometry():
377
489
  # returnfields += 'ts_id,ts_name,'
378
490
  # returnfields += 'ts_unitname,ts_unitsymbol,'
379
491
 
380
- if self.dir!='' and exists(join(self.dir,'stations.csv')):
381
- self.stations = pd.read_csv(join(self.dir,'stations.csv'),index_col=0)
492
+ if self.dir!='' and self.get_path(self.dir, 'stations.csv').exists():
493
+ self.stations = pd.read_csv(self.get_path(self.dir, 'stations.csv'),index_col=0)
382
494
  elif self.url!='':
383
- json_data = requests.get(self._get_commandstr(kiwis_command.getStationList) \
384
- +'&metadata=true' \
385
- +'&returnfields='+returnfields \
386
- +'&ca_sta_returnfields='+ca_sta_returnfields \
387
- +'&orderby=station_no', \
388
- verify=True, \
389
- headers=self._header).json()
495
+ try:
496
+ if self.url == URL_SPW:
497
+ json_data = requests.get(self._get_commandstr(kiwis_command.getStationList) \
498
+ +'&metadata=true' \
499
+ +'&returnfields='+returnfields \
500
+ +'&ca_sta_returnfields='+ca_sta_returnfields \
501
+ +'&orderby=station_no', \
502
+ verify=True, \
503
+ headers=self._header).json()
504
+ else:
505
+ json_data = requests.get(self._get_commandstr(kiwis_command.getStationList, 'json') \
506
+ +'&metadata=true' \
507
+ +'&returnfields='+returnfields \
508
+ +'&orderby=station_no', \
509
+ verify=True, \
510
+ headers=self._header)
511
+
512
+ json_data = json_data.text.replace('\x1a', ' ')
513
+ json_data = json.loads(json_data)
514
+
515
+ except Exception as e:
516
+ self.stations = None
517
+ return
518
+
390
519
  self.stations = pd.DataFrame(json_data[1:], columns = json_data[0])
391
520
 
392
521
  #Conversion en minuscules
393
522
  self.stations[station_fields.STATION_NAME.value]=self.stations[station_fields.STATION_NAME.value].str.lower()
394
523
 
395
- # real stations are those with coordinates and not null
396
- self.realstations = self.stations[(~pd.isnull(self.stations[station_fields.STATION_LOCAL_X.value])) & (self.stations[station_fields.STATION_LOCAL_X.value]!='')]
397
- # computed stations are those without coordinates or null
398
- self.compstations = self.stations[pd.isnull(self.stations[station_fields.STATION_LOCAL_X.value]) | self.stations[station_fields.STATION_LOCAL_X.value]!='']
524
+ # # In case of Waterinfo, get part of station_id
525
+ # if self.url == URL_WATERINFO:
526
+ # self.stations[station_fields.STATION_ID.value] = self.stations[station_fields.STATION_ID.value].str[2:]
527
+
528
+ if self.url == URL_SPW:
529
+ # real stations are those with coordinates and not null
530
+ self.realstations = self.stations[(~pd.isnull(self.stations[station_fields.STATION_LOCAL_X.value])) & (self.stations[station_fields.STATION_LOCAL_X.value]!='')]
531
+ # computed stations are those without coordinates or null
532
+ self.compstations = self.stations[pd.isnull(self.stations[station_fields.STATION_LOCAL_X.value]) | self.stations[station_fields.STATION_LOCAL_X.value]!='']
533
+ else:
534
+ self.realstations = self.stations
535
+ self.compstations = None
399
536
 
400
537
  def get_names_xy(self, site_no = None):
401
538
  """Obtention des noms et coordonnées des stations pour le site
@@ -572,13 +709,39 @@ class hydrometry():
572
709
 
573
710
  return stations
574
711
 
712
+ def get_timeseries_group_spw(self, rfw:Literal['rain','waterdepth','flowrate'], time:Literal['5min','5or10min','1h','1d','1m']):
713
+ """alias for get_timeseries_group"""
714
+
715
+ return self.get_timeseries_group(rfw, time)
716
+
717
+ def get_timeseries_group_winfo_hic(self, group:WaterInfo_GroupdID | HICWS_GroupID):
718
+ """Obtention des stations pour le groupe souhaité.
719
+
720
+ Temps retourné en UTC
721
+
722
+ :param group: type de groupe - see WaterInfo_GroupdID or HICWS_GroupID
723
+ """
724
+
725
+ if self.url!='':
726
+ stations=None
727
+ group_id = group.value[1]
728
+ returnFields = '&metadata=true&custattr_returnfields=dataprovider,dataowner&md_returnfields=custom_attributes,station_id,station_no,station_name,ts_id,ts_name,stationparameter_name,ts_unitsymbol,parametertype_name'
729
+ json_data = requests.get(self._get_commandstr(kiwis_command.getTimeseriesValueLayer) +
730
+ '&timeseriesgroup_id='+str(group_id)+
731
+ '&orderby=station_no'+
732
+ returnFields,
733
+ verify=True, headers=self._header).json()
734
+ stations = pd.DataFrame(json_data[1:], columns = json_data[0])
735
+
736
+ return stations
737
+
575
738
  def get_sites(self, forcerequest=False):
576
739
  """Obtention des sites pour le serveur courant
577
740
 
578
741
  :param forcerequest: force la requête même si les données de cache sont déjà présentes"""
579
742
 
580
- if self.dir!='' and exists(join(self.dir,'sites.csv')) and not forcerequest:
581
- self.sites = pd.read_csv(join(self.dir,'sites.csv'),index_col=0)
743
+ if self.dir!='' and self.get_path(self.dir, 'sites.csv').exists() and not forcerequest:
744
+ self.sites = pd.read_csv(self.get_path(self.dir, 'sites.csv'),index_col=0)
582
745
  elif self.url!='' or forcerequest:
583
746
  json_data = requests.get(self._get_commandstr(kiwis_command.getSiteList),verify=True, headers=self._header).json()
584
747
  self.sites = pd.DataFrame(json_data[1:], columns = json_data[0])
@@ -590,8 +753,8 @@ class hydrometry():
590
753
 
591
754
  :param forcerequest: force la requête même si les données de cache sont déjà présentes"""
592
755
 
593
- if self.dir!='' and exists(join(self.dir,'groups.csv')) and not forcerequest:
594
- self.groups = pd.read_csv(join(self.dir,'groups.csv'),index_col=0)
756
+ if self.dir!='' and self.get_path(self.dir, 'groups.csv').exists() and not forcerequest:
757
+ self.groups = pd.read_csv(self.get_path(self.dir, 'groups.csv'),index_col=0)
595
758
  elif self.url!='' or forcerequest:
596
759
  json_data = requests.get(self._get_commandstr(kiwis_command.getGroupList),verify=True, headers=self._header).json()
597
760
  self.groups = pd.DataFrame(json_data[1:], columns = json_data[0])
@@ -611,8 +774,8 @@ class hydrometry():
611
774
 
612
775
  :param forcerequest: force la requête même si les données de cache sont déjà présentes"""
613
776
 
614
- if self.dir!='' and exists(join(self.dir,'requests.csv')) and not forcerequest:
615
- self.requests = pd.read_csv(join(self.dir,'requests.csv'),index_col=0)
777
+ if self.dir!='' and self.get_path(self.dir, 'requests.csv').exists() and not forcerequest:
778
+ self.requests = pd.read_csv(self.get_path(self.dir, 'requests.csv'),index_col=0)
616
779
  elif self.url!='' or forcerequest:
617
780
  json_data = requests.get(self._get_commandstr(kiwis_command.getrequestinfo),verify=True, headers=self._header).json()
618
781
  self.requests = pd.DataFrame(json_data[0]['Requests'])
@@ -709,7 +872,8 @@ class hydrometry():
709
872
  filename = self._get_filename_list(stationname,stationcode)
710
873
  list.to_csv(dir / filename)
711
874
 
712
- def timeseries(self,stationname:str='', stationcode:str='', dir:str='',
875
+ def timeseries(self, stationname:str='', stationcode:str='', stationid:str='',
876
+ dir:str='',
713
877
  fromdate=datetime.now()-timedelta(60), todate=datetime.now(),
714
878
  ts_name:str='', ts_id:str='', interval:int=3600, timezone:str = 'GMT+0'):
715
879
  """
@@ -738,11 +902,14 @@ class hydrometry():
738
902
  cursec = interval
739
903
  # id = ''
740
904
  if ts_id == '':
741
- if stationname=='':
742
- stationname = self.get_stationname(stationcode)
743
- if stationcode=='':
744
- stationcode = self.get_stationcode(stationname)
745
- id = self.get_stationid(stationname,stationcode)
905
+ if str(stationid) !='':
906
+ id = stationid
907
+ else:
908
+ if stationname=='':
909
+ stationname = self.get_stationname(stationcode)
910
+ if stationcode=='':
911
+ stationcode = self.get_stationcode(stationname)
912
+ id = self.get_stationid(stationname,stationcode)
746
913
 
747
914
  if dir=='':
748
915
  json_data = requests.get(self._get_commandstr(kiwis_command.getTimeseriesList)
@@ -190,7 +190,7 @@ class hydrometry_gui(wx.Frame):
190
190
  self.tenyears.Bind(wx.EVT_BUTTON, self.setdate)
191
191
 
192
192
 
193
- self.hydro = hydrometry(credential=credential, dir=kw.get('dir',''))
193
+ self.hydro = hydrometry(credential=credential, dir=kw.get('dir',''), url=kw.get('url',''))
194
194
 
195
195
  self.figsaxes=[]
196
196
 
wolfhece/wolf_array.py CHANGED
@@ -1410,7 +1410,42 @@ class CropDialog(wx.Dialog):
1410
1410
 
1411
1411
  return myhead
1412
1412
 
1413
-
1413
+ import string
1414
+ class IntValidator(wx.Validator):
1415
+ ''' Validates data as it is entered into the text controls. '''
1416
+
1417
+ #----------------------------------------------------------------------
1418
+ def __init__(self):
1419
+ super(IntValidator, self).__init__()
1420
+ self.Bind(wx.EVT_CHAR, self.OnChar)
1421
+
1422
+ #----------------------------------------------------------------------
1423
+ def Clone(self):
1424
+ '''Required Validator method'''
1425
+ return IntValidator()
1426
+
1427
+ #----------------------------------------------------------------------
1428
+ def Validate(self, win):
1429
+ return True
1430
+
1431
+ #----------------------------------------------------------------------
1432
+ def TransferToWindow(self):
1433
+ return True
1434
+
1435
+ #----------------------------------------------------------------------
1436
+ def TransferFromWindow(self):
1437
+ return True
1438
+
1439
+ #----------------------------------------------------------------------
1440
+ def OnChar(self, event):
1441
+ keycode = int(event.GetKeyCode())
1442
+ if keycode < 256:
1443
+ #print keycode
1444
+ key = chr(keycode)
1445
+
1446
+ if key not in string.digits:
1447
+ return
1448
+ event.Skip()
1414
1449
  class Ops_Array(wx.Frame):
1415
1450
  """
1416
1451
  Operations wx.Frame on WolfArray class
@@ -1771,26 +1806,54 @@ class Ops_Array(wx.Frame):
1771
1806
  _("Select all nodes"), wx.DefaultPosition,
1772
1807
  wx.DefaultSize, 0)
1773
1808
  self.AllSelection.SetToolTip(_("Select all nodes in one click - store 'All' in the selection list"))
1774
- bSizer16_1.Add(self.AllSelection, 0, wx.EXPAND)
1809
+ bSizer16_1.Add(self.AllSelection, 1, wx.EXPAND)
1775
1810
 
1811
+ memory_sizer = wx.BoxSizer(wx.HORIZONTAL)
1776
1812
  self.MoveSelection = wx.Button(self.selection, wx.ID_ANY,
1777
- _("Move current selection to..."), wx.DefaultPosition,
1813
+ _("Move selection to..."), wx.DefaultPosition,
1778
1814
  wx.DefaultSize, 0)
1779
1815
  self.MoveSelection.SetToolTip(_("Store the current selection in an indexed list -- useful for some interpolation methods"))
1780
- bSizer16_1.Add(self.MoveSelection, 0, wx.EXPAND)
1781
1816
 
1817
+ self.ReselectMemory = wx.Button(self.selection, wx.ID_ANY,
1818
+ _("Reselect from..."), wx.DefaultPosition,
1819
+ wx.DefaultSize, 0)
1820
+ self.ReselectMemory.SetToolTip(_("Reselect the nodes from an indexed list"))
1821
+
1822
+ memory_sizer.Add(self.MoveSelection, 1, wx.EXPAND)
1823
+ memory_sizer.Add(self.ReselectMemory, 1, wx.EXPAND)
1824
+ bSizer16_1.Add(memory_sizer, 1, wx.EXPAND)
1825
+
1826
+ reset_sizer = wx.BoxSizer(wx.HORIZONTAL)
1782
1827
  self.ResetSelection = wx.Button(self.selection, wx.ID_ANY,
1783
1828
  _("Reset"), wx.DefaultPosition,
1784
1829
  wx.DefaultSize, 0)
1785
1830
  self.ResetSelection.SetToolTip(_("Reset the current selection list (keyboard shortcut r)"))
1786
- bSizer16_1.Add(self.ResetSelection, 0, wx.EXPAND)
1787
-
1831
+
1788
1832
  self.ResetAllSelection = wx.Button(self.selection, wx.ID_ANY,
1789
1833
  _("Reset All"), wx.DefaultPosition,
1790
1834
  wx.DefaultSize, 0)
1791
1835
  self.ResetAllSelection.SetToolTip(_("Reset the current selection list and the indexed lists (keyboard shortcut R)"))
1792
- bSizer16_1.Add(self.ResetAllSelection, 0, wx.EXPAND)
1793
1836
 
1837
+ reset_sizer.Add(self.ResetSelection, 1, wx.EXPAND)
1838
+ reset_sizer.Add(self.ResetAllSelection, 1, wx.EXPAND)
1839
+ bSizer16_1.Add(reset_sizer, 1, wx.EXPAND)
1840
+
1841
+ save_load_sizer = wx.BoxSizer(wx.HORIZONTAL)
1842
+ self.SaveSelection = wx.Button(self.selection, wx.ID_ANY,
1843
+ _("Save"), wx.DefaultPosition,
1844
+ wx.DefaultSize, 0)
1845
+ self.SaveSelection.SetToolTip(_("Save the current selection list to disk"))
1846
+
1847
+ self.LoadSelection = wx.Button(self.selection, wx.ID_ANY,
1848
+ _("Load"), wx.DefaultPosition,
1849
+ wx.DefaultSize, 0)
1850
+ self.LoadSelection.SetToolTip(_("Load a selection list from disk"))
1851
+
1852
+ save_load_sizer.Add(self.SaveSelection, 1, wx.EXPAND)
1853
+ save_load_sizer.Add(self.LoadSelection, 1, wx.EXPAND)
1854
+ bSizer16_1.Add(save_load_sizer, 1, wx.EXPAND)
1855
+
1856
+ clipboad_sizer = wx.BoxSizer(wx.HORIZONTAL)
1794
1857
  self.to_clipboard_str = wx.Button(self.selection, wx.ID_ANY, _("To clipboard (str)"), wx.DefaultPosition,
1795
1858
  wx.DefaultSize, 0)
1796
1859
  self.to_clipboard_str.SetToolTip(_("Copy the current selection to the clipboard as a string"))
@@ -1799,19 +1862,19 @@ class Ops_Array(wx.Frame):
1799
1862
  wx.DefaultSize, 0)
1800
1863
  self.to_clipboard_script.SetToolTip(_("Copy the current selection to the clipboard as a script"))
1801
1864
 
1802
- bSizer16_2.Add(self.to_clipboard_str, 0, wx.EXPAND, 2)
1803
- bSizer16_2.Add(self.to_clipboard_script, 0, wx.EXPAND, 2)
1865
+ clipboad_sizer.Add(self.to_clipboard_str, 1, wx.EXPAND)
1866
+ clipboad_sizer.Add(self.to_clipboard_script, 1, wx.EXPAND)
1804
1867
 
1805
1868
  erode_dilate_sizer = wx.BoxSizer(wx.VERTICAL)
1806
- self.expand_selection = wx.Button(self.selection, wx.ID_ANY, _("Expand/Dilate selection"), wx.DefaultPosition,
1869
+ self.expand_selection = wx.Button(self.selection, wx.ID_ANY, _("Dilate"), wx.DefaultPosition,
1807
1870
  wx.DefaultSize, 0)
1808
1871
  self.expand_selection.SetToolTip(_("Expand the current selection to the nearest nodes"))
1809
1872
 
1810
- self.contract_selection = wx.Button(self.selection, wx.ID_ANY, _("Contract/Erode selection"), wx.DefaultPosition,
1873
+ self.contract_selection = wx.Button(self.selection, wx.ID_ANY, _("Erode"), wx.DefaultPosition,
1811
1874
  wx.DefaultSize, 0)
1812
1875
  self.contract_selection.SetToolTip(_("Contract the current selection to the nearest nodes"))
1813
1876
 
1814
- self.expand_unselect_interior = wx.Button(self.selection, wx.ID_ANY, _("Expand/Dilate contour"), wx.DefaultPosition,
1877
+ self.expand_unselect_interior = wx.Button(self.selection, wx.ID_ANY, _("Dilate contour"), wx.DefaultPosition,
1815
1878
  wx.DefaultSize, 0)
1816
1879
  self.expand_unselect_interior.SetToolTip(_("Expand the contour of the current selection and unselect the interior nodes"))
1817
1880
 
@@ -1819,25 +1882,31 @@ class Ops_Array(wx.Frame):
1819
1882
  wx.DefaultSize, 0)
1820
1883
  self.unselect_interior.SetToolTip(_("Conserve the contour of the current selection and unselect the interior nodes"))
1821
1884
 
1822
- erode_dilate_sizer.Add(self.expand_selection, 0, wx.EXPAND)
1823
- erode_dilate_sizer.Add(self.contract_selection, 0, wx.EXPAND)
1824
- erode_dilate_sizer.Add(self.expand_unselect_interior, 0, wx.EXPAND)
1825
- erode_dilate_sizer.Add(self.unselect_interior, 0, wx.EXPAND)
1885
+ er_dil_1 = wx.BoxSizer(wx.HORIZONTAL)
1886
+ er_dil_2 = wx.BoxSizer(wx.HORIZONTAL)
1887
+ er_dil_1.Add(self.expand_selection, 1, wx.EXPAND)
1888
+ er_dil_1.Add(self.contract_selection, 1, wx.EXPAND)
1889
+ er_dil_2.Add(self.expand_unselect_interior, 1, wx.EXPAND)
1890
+ er_dil_2.Add(self.unselect_interior, 1, wx.EXPAND)
1891
+
1892
+ erode_dilate_sizer.Add(er_dil_1, 1, wx.EXPAND)
1893
+ erode_dilate_sizer.Add(er_dil_2, 1, wx.EXPAND)
1826
1894
 
1827
1895
  erode_dilate_options = wx.BoxSizer(wx.HORIZONTAL)
1828
1896
  self._label_passes = wx.StaticText(self.selection, wx.ID_ANY, _("Passes"), wx.DefaultPosition, wx.DefaultSize, 0)
1829
1897
  self._erode_dilate_value = wx.TextCtrl(self.selection, wx.ID_ANY, u"1", wx.DefaultPosition, wx.DefaultSize, style=wx.TE_CENTER)
1830
1898
  self._erode_dilate_value.SetToolTip(_("Number of passes for the erode/dilate operation"))
1831
-
1832
- erode_dilate_options.Add(self._label_passes, 0, wx.EXPAND)
1833
- erode_dilate_options.Add(self._erode_dilate_value, 0, wx.EXPAND)
1899
+ self._erode_dilate_value.SetValidator(validator=IntValidator())
1900
+
1901
+ erode_dilate_options.Add(self._label_passes, 1, wx.EXPAND)
1902
+ erode_dilate_options.Add(self._erode_dilate_value, 1, wx.EXPAND)
1834
1903
 
1835
1904
  self._erode_dilate_structure = wx.ComboBox(self.selection, wx.ID_ANY, _("Cross"), wx.DefaultPosition, wx.DefaultSize,
1836
1905
  ["Cross", "Square"], wx.CB_READONLY)
1837
1906
  self._erode_dilate_structure.SetToolTip(_("Structuring element for the erode/dilate operation"))
1838
1907
  erode_dilate_options.Add(self._erode_dilate_structure, 1, wx.EXPAND)
1839
1908
 
1840
- erode_dilate_sizer.Add(erode_dilate_options, 0, wx.EXPAND)
1909
+ erode_dilate_sizer.Add(erode_dilate_options, 1, wx.EXPAND)
1841
1910
 
1842
1911
  # MultiBlocks
1843
1912
  # ----------------
@@ -1864,8 +1933,10 @@ class Ops_Array(wx.Frame):
1864
1933
  # bSizer16.Add(self._open_block, 0, wx.EXPAND)
1865
1934
 
1866
1935
  bSizer16_1.Add(erode_dilate_sizer, 1, wx.EXPAND, 5)
1936
+ bSizer16_1.Add(clipboad_sizer, 1, wx.EXPAND)
1937
+
1867
1938
  bSizer16.Add(bSizer16_1, 1, wx.EXPAND, 5)
1868
- bSizer16.Add(bSizer16_2, 1, wx.EXPAND, 5)
1939
+ # bSizer16.Add(bSizer16_2, 1, wx.EXPAND, 5)
1869
1940
  bSizer21.Add(bSizer16, 1, wx.EXPAND, 5)
1870
1941
 
1871
1942
  # VECTORS Manager
@@ -2040,11 +2111,15 @@ class Ops_Array(wx.Frame):
2040
2111
  self.LaunchSelection.Bind(wx.EVT_BUTTON, self.OnLaunchSelect)
2041
2112
  self.AllSelection.Bind(wx.EVT_BUTTON, self.OnAllSelect)
2042
2113
  self.MoveSelection.Bind(wx.EVT_BUTTON, self.OnMoveSelect)
2114
+ self.ReselectMemory.Bind(wx.EVT_BUTTON, self.OnReselectMemory)
2043
2115
  self.ResetSelection.Bind(wx.EVT_BUTTON, self.OnResetSelect)
2044
2116
  self.ResetAllSelection.Bind(wx.EVT_BUTTON, self.OnResetAllSelect)
2045
2117
  self.to_clipboard_str.Bind(wx.EVT_BUTTON, self.OnToClipboardStr)
2046
2118
  self.to_clipboard_script.Bind(wx.EVT_BUTTON, self.OnToClipboardStr)
2047
2119
 
2120
+ self.SaveSelection.Bind(wx.EVT_BUTTON, self.OnSaveSelection)
2121
+ self.LoadSelection.Bind(wx.EVT_BUTTON, self.OnLoadSelection)
2122
+
2048
2123
  self.m_button2.Bind(wx.EVT_BUTTON, self.OnManageVectors)
2049
2124
  self.loadvec.Bind(wx.EVT_BUTTON, self.OnLoadvec)
2050
2125
  self.saveas.Bind(wx.EVT_BUTTON, self.OnSaveasvec)
@@ -2237,18 +2312,44 @@ class Ops_Array(wx.Frame):
2237
2312
  self.parentarray.myops.nbselect.SetLabelText('All')
2238
2313
  self.parentarray.myops.nbselect2.SetLabelText('All')
2239
2314
 
2315
+ def OnReselectMemory(self, event):
2316
+ """
2317
+ Reselect from memory
2318
+ """
2319
+
2320
+ if self.parentarray.mngselection is not None:
2321
+ self.parentarray.mngselection.reselect_from_memory()
2322
+
2240
2323
  def OnMoveSelect(self, event):
2241
2324
  """Transfert de la sélection courante dans un dictionnaire"""
2242
2325
 
2243
2326
  dlg = wx.TextEntryDialog(self, 'Choose id', 'id?')
2244
2327
  ret = dlg.ShowModal()
2328
+
2329
+ if ret == wx.ID_CANCEL:
2330
+ logging.info('Cancel transfer')
2331
+ dlg.Destroy()
2332
+ return
2333
+
2245
2334
  idtxt = dlg.GetValue()
2335
+ dlg.Destroy()
2246
2336
 
2247
- dlg = wx.ColourDialog(self)
2248
- ret = dlg.ShowModal()
2249
- color = dlg.GetColourData()
2337
+ if self.parentarray.SelectionData is not None:
2338
+ if self.parentarray.SelectionData.nb > 0:
2339
+ dlg = wx.ColourDialog(self)
2340
+ ret = dlg.ShowModal()
2341
+ if ret == wx.ID_OK:
2342
+ color = dlg.GetColourData()
2343
+ color = color.GetColour().Get()
2344
+ dlg.Destroy()
2345
+ else:
2346
+ logging.info('Cancel transfer')
2347
+ dlg.Destroy()
2348
+ return
2349
+ else:
2350
+ color = (20,20,20,255)
2250
2351
 
2251
- self.parentarray.SelectionData.move_selectionto(idtxt, color.GetColour())
2352
+ self.parentarray.SelectionData.move_selectionto(idtxt, color)
2252
2353
 
2253
2354
  def OnContractSelection(self, event):
2254
2355
  """ Contract selection """
@@ -2261,7 +2362,8 @@ class Ops_Array(wx.Frame):
2261
2362
 
2262
2363
  usemask = self.selectrestricttomask.GetValue()
2263
2364
 
2264
- self.parentarray.erode_selection(nb, usemask = usemask, structure = structure)
2365
+ self.parentarray.SelectionData.erode_selection(nb, usemask, structure)
2366
+ self.refresh_array()
2265
2367
 
2266
2368
  def OnExpandSelection(self, event):
2267
2369
  """ Expand selection """
@@ -2273,7 +2375,8 @@ class Ops_Array(wx.Frame):
2273
2375
 
2274
2376
  usemask = self.selectrestricttomask.GetValue()
2275
2377
 
2276
- self.parentarray.dilate_selection(nb, usemask, structure)
2378
+ self.parentarray.SelectionData.dilate_selection(nb, usemask, structure)
2379
+ self.refresh_array()
2277
2380
 
2278
2381
  def OnExpandUnselectInterior(self, event):
2279
2382
  """ Expand contour """
@@ -2286,11 +2389,13 @@ class Ops_Array(wx.Frame):
2286
2389
 
2287
2390
  usemask = self.selectrestricttomask.GetValue()
2288
2391
 
2289
- self.parentarray.dilate_contour_selection(nb, usemask, structure)
2392
+ self.parentarray.SelectionData.dilate_contour_selection(nb, usemask, structure)
2393
+ self.refresh_array()
2290
2394
 
2291
2395
  def OnUnselectInterior(self, event):
2292
2396
  """ Contract contour """
2293
- self.parentarray.erode_contour_selection()
2397
+ self.parentarray.SelectionData.erode_contour_selection()
2398
+ self.refresh_array()
2294
2399
 
2295
2400
  def reset_selection(self):
2296
2401
  """
@@ -2330,6 +2435,20 @@ class Ops_Array(wx.Frame):
2330
2435
  self.reset_all_selection()
2331
2436
  self.refresh_array()
2332
2437
 
2438
+ def OnSaveSelection(self, event):
2439
+ """
2440
+ Save the current selection
2441
+ """
2442
+
2443
+ self.parentarray.SelectionData.save_selection()
2444
+
2445
+ def OnLoadSelection(self, event):
2446
+ """
2447
+ Load a selection
2448
+ """
2449
+
2450
+ self.parentarray.SelectionData.load_selection()
2451
+
2333
2452
  def OnToClipboardStr(self, event):
2334
2453
  """
2335
2454
  Copy the current selection to the clipboard as a string
@@ -3132,16 +3251,19 @@ class SelectionData():
3132
3251
  self.myselection = []
3133
3252
  self.selections = {}
3134
3253
 
3135
- def get_string(self, which:str = None) -> str:
3254
+ def get_string(self, which:str = None, all_memories:bool= False) -> str:
3136
3255
  """ Get string of the current selection or of a stored one """
3137
3256
 
3138
3257
  if which is None:
3139
3258
  curlist = self.myselection
3140
- txt = 'X\tY'
3259
+ txt = 'X\tY\n'
3141
3260
  else:
3142
3261
  if str(which) in self.selections:
3262
+ all_memories = False
3143
3263
  curlist = self.selections[str(which)]['select']
3144
- txt = 'Selection {}\n'.format(which) + 'X\tY\n'
3264
+ txt = 'Selection {}\n'.format(which)
3265
+ txt += 'Color : {}\n'.format(self.selections[str(which)]['color'])
3266
+ txt += 'X\tY\n'
3145
3267
  else:
3146
3268
  logging.error(_('Selection {} does not exist').format(which))
3147
3269
  return ''
@@ -3161,6 +3283,10 @@ class SelectionData():
3161
3283
  i,j = self.parent.get_ij_from_xy(cur[0], cur[1], aswolf=True)
3162
3284
  txt += str(i) + '\t' + str(j) + '\n'
3163
3285
 
3286
+ if all_memories:
3287
+ for key, cur in self.selections.items():
3288
+ txt += self.get_string(key)
3289
+
3164
3290
  return txt
3165
3291
 
3166
3292
  def get_script(self, which:int = None) -> str:
@@ -3215,6 +3341,39 @@ class SelectionData():
3215
3341
  else:
3216
3342
  logging.warning(_('Cannot open the clipboard'))
3217
3343
 
3344
+ def reselect_from_memory(self, idx:list[str] = None):
3345
+ """
3346
+ Reselect a stored selection
3347
+
3348
+ :param idx: id/key of the selection
3349
+ """
3350
+
3351
+ if idx is None:
3352
+ keys = list(self.selections.keys())
3353
+ with wx.MultiChoiceDialog(None, "Choose the memory to reselect", "Choices", keys+['All']) as dlg:
3354
+ ret = dlg.ShowModal()
3355
+ if ret == wx.ID_CANCEL:
3356
+ return
3357
+
3358
+ idx = dlg.GetSelections()
3359
+ if len(idx) == 0:
3360
+ return
3361
+
3362
+ if len(idx) == 1 and idx[0] == len(keys):
3363
+ idx = keys
3364
+ elif len(idx) in idx:
3365
+ idx = keys
3366
+ else:
3367
+ idx = [keys[i] for i in idx]
3368
+
3369
+ for curidx in idx:
3370
+ if curidx in self.selections:
3371
+ self.myselection += self.selections[curidx]['select']
3372
+ else:
3373
+ logging.error(_('Selection {} does not exist').format(idx))
3374
+
3375
+ self.update_nb_nodes_selection()
3376
+ self.parent.reset_plot()
3218
3377
 
3219
3378
  def move_selectionto(self, idx:str, color:list[float], resetplot:bool=True):
3220
3379
  """
@@ -3561,6 +3720,101 @@ class SelectionData():
3561
3720
 
3562
3721
  self.update_nb_nodes_selection()
3563
3722
 
3723
+ def dilate_contour_selection(self, nbiter:int= 1, use_mask:bool = True, structure:np.ndarray = np.ones((3,3))):
3724
+ """ Dilate the contour of the selection """
3725
+
3726
+ if self.nb > 0:
3727
+ oldsel = self.myselection.copy()
3728
+ self.dilate_selection(nbiter, use_mask, structure)
3729
+ newsel = self.myselection.copy()
3730
+ self.myselection = [cur for cur in newsel if cur not in oldsel]
3731
+ self.update_nb_nodes_selection()
3732
+ else:
3733
+ logging.info('No selection to expand/dilate')
3734
+
3735
+ def erode_contour_selection(self):
3736
+ """ Erode the contour of the selection """
3737
+
3738
+ if self.nb > 0:
3739
+ oldselect = self.myselection.copy()
3740
+ self.erode_selection(1)
3741
+ newselect = self.myselection.copy()
3742
+ self.myselection = [cur for cur in oldselect if cur not in newselect]
3743
+ self.update_nb_nodes_selection()
3744
+ else:
3745
+ logging.info('No selection to contract/erode')
3746
+
3747
+ def save_selection(self, filename:str=None):
3748
+ """ Save the selection to a file """
3749
+
3750
+ if filename is None:
3751
+ with wx.FileDialog(None, 'Save selection', wildcard='Text files (*.txt)|*.txt',
3752
+ style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) as dlg:
3753
+ if dlg.ShowModal() == wx.ID_CANCEL:
3754
+ return
3755
+ filename = dlg.GetPath()
3756
+
3757
+ with open(filename, 'w') as f:
3758
+ f.write(self.get_string(all_memories=True))
3759
+
3760
+ def load_selection(self, filename:str=None):
3761
+ """ Load a selection from a file """
3762
+
3763
+ if filename is None:
3764
+ with wx.FileDialog(None, 'Load selection', wildcard='Text files (*.txt)|*.txt',
3765
+ style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as dlg:
3766
+ if dlg.ShowModal() == wx.ID_CANCEL:
3767
+ return
3768
+ filename = dlg.GetPath()
3769
+
3770
+ with open(filename, 'r') as f:
3771
+ lines = f.readlines()
3772
+
3773
+ xy = []
3774
+ k=0
3775
+ for line in lines:
3776
+ if line[0] == 'X':
3777
+ k+=1
3778
+ continue
3779
+ if line[0] == 'i':
3780
+ k+=1
3781
+ break
3782
+ x, y = line.split()
3783
+ xy.append((float(x), float(y)))
3784
+ k+=1
3785
+
3786
+ self.myselection = xy
3787
+ self.update_nb_nodes_selection()
3788
+
3789
+ k += len(xy)
3790
+
3791
+ while k < len(lines):
3792
+ lines = lines[k:]
3793
+ k=0
3794
+ for line in lines:
3795
+ if 'Selection' in line:
3796
+ idx = line.split()[1]
3797
+ self.selections[idx] = {}
3798
+ xy = []
3799
+ k+=1
3800
+ elif 'Color' in line:
3801
+ color = [int(x.replace('[','').replace(']','').replace(',','')) for x in line.split()[2:]]
3802
+ self.selections[idx]['Color'] = color
3803
+ k+=1
3804
+ elif line[0] == 'X':
3805
+ k+=1
3806
+ continue
3807
+ elif line[0] == 'i':
3808
+ k+=len(xy)+1
3809
+ self.selections[idx]['select']=xy
3810
+ break
3811
+ else:
3812
+ x, y = line.split()
3813
+ xy.append((float(x), float(y)))
3814
+ k+=1
3815
+
3816
+ self.parent.reset_plot()
3817
+
3564
3818
  def update_nb_nodes_selection(self):
3565
3819
  """ Update the number of selected nodes """
3566
3820
 
@@ -4320,6 +4574,14 @@ class SelectionDataMB(SelectionData):
4320
4574
  def get_string(self, which:str = None) -> str:
4321
4575
 
4322
4576
  logging.error(_('Not yet implemented for Multi-Blocks'))
4577
+
4578
+ def save_selection(self, filename:str=None, which:str = None):
4579
+
4580
+ logging.error(_('Not yet implemented for Multi-Blocks'))
4581
+
4582
+ def load_selection(self, filename:str=None, which:str = None):
4583
+
4584
+ logging.error(_('Not yet implemented for Multi-Blocks'))
4323
4585
 
4324
4586
  def get_script(self, which:int = None) -> str:
4325
4587
 
@@ -4351,6 +4613,18 @@ class SelectionDataMB(SelectionData):
4351
4613
  for curblock in self.parent.active_blocks:
4352
4614
  curblock.SelectionData.select_underpoly(myvect)
4353
4615
 
4616
+ def dilate_selection(self, nb_iterations:int, use_mask:bool = True, structure:np.ndarray = None):
4617
+ """ Extend the selection """
4618
+
4619
+ for curblock in self.parent.active_blocks:
4620
+ curblock.SelectionData.dilate_selection(nb_iterations, use_mask, structure)
4621
+
4622
+ def erode_selection(self, nb_iterations:int, use_mask:bool = True, structure:np.ndarray = None):
4623
+ """ Reduce the selection """
4624
+
4625
+ for curblock in self.parent.active_blocks:
4626
+ curblock.SelectionData.erode_selection(nb_iterations, use_mask, structure)
4627
+
4354
4628
  def update_nb_nodes_selection(self):
4355
4629
  """ Update the number of nodes selected """
4356
4630
 
@@ -4701,55 +4975,6 @@ class WolfArray(Element_To_Draw, header_wolf):
4701
4975
 
4702
4976
  self.add_ops_sel() # Ajout d'un gestionnaire de sélection et d'opérations
4703
4977
 
4704
- def erode_selection(self, nbiter:int= 1, usemask:bool = True, structure:np.ndarray = np.ones((3,3))):
4705
- """ Erode the selection """
4706
-
4707
- if self.SelectionData is not None:
4708
- if self.SelectionData.nb > 0:
4709
- self.SelectionData.erode_selection(nbiter, usemask, structure)
4710
- self.SelectionData.update_nb_nodes_selection()
4711
- self.reset_plot()
4712
- else:
4713
- logging.info('No selection to contract/erode')
4714
-
4715
- def dilate_selection(self, nbiter:int= 1, usemask:bool = True, structure:np.ndarray = np.ones((3,3))):
4716
- """ Dilate the selection """
4717
-
4718
- if self.SelectionData is not None:
4719
- if self.SelectionData.nb > 0:
4720
- self.SelectionData.dilate_selection(nbiter, usemask, structure)
4721
- self.SelectionData.update_nb_nodes_selection()
4722
- self.reset_plot()
4723
- else:
4724
- logging.info('No selection to dilate')
4725
-
4726
- def dilate_contour_selection(self, nbiter:int= 1, usemask:bool = True, structure:np.ndarray = np.ones((3,3))):
4727
- """ Dilate the contour of the selection """
4728
-
4729
- if self.SelectionData is not None:
4730
- if self.SelectionData.nb > 0:
4731
- oldsel = self.SelectionData.myselection.copy()
4732
- self.SelectionData.dilate_selection(nbiter, usemask, structure)
4733
- newsel = self.SelectionData.myselection.copy()
4734
- self.SelectionData.myselection = [cur for cur in newsel if cur not in oldsel]
4735
- self.SelectionData.update_nb_nodes_selection()
4736
- self.reset_plot()
4737
- else:
4738
- logging.info('No selection to expand/dilate')
4739
-
4740
- def erode_contour_selection(self):
4741
- """ Erode the contour of the selection """
4742
- if self.SelectionData is not None:
4743
- if self.SelectionData.nb > 0:
4744
- oldselect = self.SelectionData.myselection.copy()
4745
- self.SelectionData.erode_selection(1)
4746
- newselect = self.SelectionData.myselection.copy()
4747
- self.SelectionData.myselection = [cur for cur in oldselect if cur not in newselect]
4748
- self.SelectionData.update_nb_nodes_selection()
4749
- self.reset_plot()
4750
- else:
4751
- logging.info('No selection to contract/erode')
4752
-
4753
4978
  def set_opacity(self, alpha:float):
4754
4979
  """ Set the transparency of the array """
4755
4980
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: wolfhece
3
- Version: 2.1.74
3
+ Version: 2.1.76
4
4
  Author-email: Pierre Archambeau <pierre.archambeau@uliege.be>
5
5
  License: Copyright (c) 2024 University of Liege. All rights reserved.
6
6
  Project-URL: Homepage, https://uee.uliege.be/hece
@@ -7,7 +7,7 @@ wolfhece/ManageParams.py,sha256=EeuUI5Vvh9ixCvYf8YShMC1s1Yacc7OxOCN7q81gqiQ,517
7
7
  wolfhece/Model1D.py,sha256=SI4oNF_J3MdjiWZoizS8kuRXLMVyymX9dYfYJNVCQVI,476989
8
8
  wolfhece/PyConfig.py,sha256=FB8u0belXOXTb03Ln6RdVWvMgjzi3oGPCmw2dWa3lNg,8332
9
9
  wolfhece/PyCrosssections.py,sha256=FnmM9DWY_SAF2EDH9Gu2PojXNtSTRF4-aYQuAAJXBh4,112771
10
- wolfhece/PyDraw.py,sha256=nud0raPc9AYDLgA3dYNOaOXQCWzLzCicxmxp7VihYtQ,416394
10
+ wolfhece/PyDraw.py,sha256=VPe_MTPd6_gjyRL627yEWnE6RbL9t-EQmEDLa1t1dVM,421909
11
11
  wolfhece/PyGui.py,sha256=oBIBpgBQRR_XXucKE5-RFrtqKj0DRg9VlUCRo8Mzalc,105009
12
12
  wolfhece/PyGuiHydrology.py,sha256=f60E8K9eGTnRq5RDF6yvt-ahf2AYegwQ9t25zZ2Mk1A,14946
13
13
  wolfhece/PyHydrographs.py,sha256=jwtSNMMACwarxrtN1UeQYth99UNrhwPx1IGgUwcooHA,3774
@@ -48,7 +48,7 @@ wolfhece/pywalous.py,sha256=yRaWJjKckXef1d9D5devP0yFHC9uc6kRV4G5x9PNq9k,18972
48
48
  wolfhece/rain_SPWMI.py,sha256=qCfcmF7LajloOaCwnTrrSMzyME03YyilmRUOqrPrv3U,13846
49
49
  wolfhece/textpillow.py,sha256=map7HsGYML_o5NHRdFg2s_TVQed_lDnpYNDv27MM0Vw,14130
50
50
  wolfhece/tools_mpl.py,sha256=gQ3Jg1iuZiecmMqa5Eli2ZLSkttu68VXL8YmMDBaEYU,564
51
- wolfhece/wolf_array.py,sha256=Oze4IYwE19LnxERNi48duYdp3qLXENg8p3_f5KuC1ho,393076
51
+ wolfhece/wolf_array.py,sha256=Rj_N7yg4OqwLRAWwDBl0VwwpXLzP0hPwhTRcwB3P5yA,400860
52
52
  wolfhece/wolf_hist.py,sha256=7jeVrgSkM3ErJO6SRMH_PGzfLjIdw8vTy87kesldggk,3582
53
53
  wolfhece/wolf_texture.py,sha256=DS5eobLxrq9ljyebYfpMSQPn8shkUAZZVfqrOKN_QUU,16951
54
54
  wolfhece/wolf_tiles.py,sha256=2Ho2I20rHRY81KXxjgLOYISdF4OkJ2d6omeY4shDoGI,10386
@@ -72,7 +72,7 @@ wolfhece/apps/check_install.py,sha256=Xoi_d8MzKzNAy2xqEpERdsqgRPu0hbBWukI0WkIYzD
72
72
  wolfhece/apps/curvedigitizer.py,sha256=Yps4bcayzbsz0AoVc_dkSk35dEhhn_esIBy1Ziefgmk,5334
73
73
  wolfhece/apps/isocurrent.py,sha256=dagmGR8ja9QQ1gwz_8fU-N052hIw-W0mWGVkzLu6C7I,4247
74
74
  wolfhece/apps/splashscreen.py,sha256=SrustmIQeXnsiD-92OzjdGhBi-S7c_j-cSvuX4T6rtg,2929
75
- wolfhece/apps/version.py,sha256=T9oL1EY3HMV5ZVLUeJEU1FuT__QAQ0iSx8HOFn7mc4Y,388
75
+ wolfhece/apps/version.py,sha256=mJE6gMQ0LXmVC2n9qC4xJHXz1aj3sU-1ej5zEwZ8K4E,388
76
76
  wolfhece/apps/wolf.py,sha256=j_CgvsL8rwixbVvVD5Z0s7m7cHZ86gmFLojKGuetMls,729
77
77
  wolfhece/apps/wolf2D.py,sha256=4z_OPQ3IgaLtjexjMKX9ppvqEYyjFLt1hcfFABy3-jU,703
78
78
  wolfhece/apps/wolf_logo.bmp,sha256=ruJ4MA51CpGO_AYUp_dB4SWKHelvhOvd7Q8NrVOjDJk,3126
@@ -126,8 +126,8 @@ wolfhece/hydrology/read.py,sha256=itMat6MMn4Y14C3SMU_9JMBtpXFjG4mLNMfXXd5U6Ns,93
126
126
  wolfhece/hydrology/slope_manager.py,sha256=vlek0z8qcqB61eleiksyOe3QR1vpbtwfeowy6ms7_Fg,5580
127
127
  wolfhece/hydrology/wolfMap_treatment.py,sha256=eAxr24zJGwmDof1aZpcxewVvv_bWDvoO8t9Wwf99Mlo,10606
128
128
  wolfhece/hydrometry/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
129
- wolfhece/hydrometry/kiwis.py,sha256=jW5ivM0h_wZ_jM6OWh994iwQtsCZdwmQsMA7TMnCxMg,46495
130
- wolfhece/hydrometry/kiwis_gui.py,sha256=lApsSeBMJNAR1yocggdoHwz_xe6M_oaZ_E13CfHAlQA,23124
129
+ wolfhece/hydrometry/kiwis.py,sha256=br80IMFvg2xfTjaUaYT9QS7q1LBzQ8kvPBxJDcSujrA,55991
130
+ wolfhece/hydrometry/kiwis_gui.py,sha256=SdO8EmyFzhzjHlEjZtNJ68HXBOLkK9l40c0750F39V4,23146
131
131
  wolfhece/hydrometry/kiwis_wolfgui.py,sha256=GPa5YNp2V2ZlxYQjPiCXERgPuWB_zij4ec2yHpRvoFA,4027
132
132
  wolfhece/hydrometry/kiwispie.py,sha256=akOaV46WwzISVlCcPz_phjsBrI_rDACUzdELtjx-xNg,13498
133
133
  wolfhece/icons/folder_open.png,sha256=ykBlU2FtGcpjAu1YO4_eGlDg2svgs_IAs-4d5O2e3AM,2329
@@ -283,8 +283,8 @@ wolfhece/ui/wolf_multiselection_collapsiblepane.py,sha256=8PlMYrb_8jI8h9F0_EagpM
283
283
  wolfhece/ui/wolf_times_selection_comparison_models.py,sha256=ORy7fz4dcp691qKzaOZHrRLZ0uXNhL-LIHxmpDGL6BI,5007
284
284
  wolfhece/wintab/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
285
285
  wolfhece/wintab/wintab.py,sha256=8A-JNONV6ujgsgG3lM5Uw-pVgglPATwKs86oBzzljoc,7179
286
- wolfhece-2.1.74.dist-info/METADATA,sha256=7aW4jIl11xOINRkPpa0QcgwbJNb_2AE0CRq8JJ3wy9o,2570
287
- wolfhece-2.1.74.dist-info/WHEEL,sha256=HiCZjzuy6Dw0hdX5R3LCFPDmFS4BWl8H-8W39XfmgX4,91
288
- wolfhece-2.1.74.dist-info/entry_points.txt,sha256=Q5JuIWV4odeIJI3qc6fV9MwRoz0ezqPVlFC1Ppm_vdQ,395
289
- wolfhece-2.1.74.dist-info/top_level.txt,sha256=EfqZXMVCn7eILUzx9xsEu2oBbSo9liWPFWjIHik0iCI,9
290
- wolfhece-2.1.74.dist-info/RECORD,,
286
+ wolfhece-2.1.76.dist-info/METADATA,sha256=MjRjAJdHj-X5rrJuDTOU25orlRrGES6yus46PEGqQQw,2570
287
+ wolfhece-2.1.76.dist-info/WHEEL,sha256=HiCZjzuy6Dw0hdX5R3LCFPDmFS4BWl8H-8W39XfmgX4,91
288
+ wolfhece-2.1.76.dist-info/entry_points.txt,sha256=Q5JuIWV4odeIJI3qc6fV9MwRoz0ezqPVlFC1Ppm_vdQ,395
289
+ wolfhece-2.1.76.dist-info/top_level.txt,sha256=EfqZXMVCn7eILUzx9xsEu2oBbSo9liWPFWjIHik0iCI,9
290
+ wolfhece-2.1.76.dist-info/RECORD,,