wolfhece 2.1.65__py3-none-any.whl → 2.1.67__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 +37 -8
- wolfhece/PyVertexvectors.py +8 -12
- wolfhece/apps/version.py +1 -1
- wolfhece/hydrometry/kiwis.py +400 -116
- wolfhece/math_parser/calculator.py +29 -24
- wolfhece/wolf_array.py +29 -12
- {wolfhece-2.1.65.dist-info → wolfhece-2.1.67.dist-info}/METADATA +1 -1
- {wolfhece-2.1.65.dist-info → wolfhece-2.1.67.dist-info}/RECORD +11 -11
- {wolfhece-2.1.65.dist-info → wolfhece-2.1.67.dist-info}/WHEEL +0 -0
- {wolfhece-2.1.65.dist-info → wolfhece-2.1.67.dist-info}/entry_points.txt +0 -0
- {wolfhece-2.1.65.dist-info → wolfhece-2.1.67.dist-info}/top_level.txt +0 -0
wolfhece/hydrometry/kiwis.py
CHANGED
@@ -22,6 +22,7 @@ import numpy as np
|
|
22
22
|
from enum import Enum
|
23
23
|
from typing import Literal
|
24
24
|
import urllib.parse
|
25
|
+
from pathlib import Path
|
25
26
|
|
26
27
|
import matplotlib.pyplot as plt
|
27
28
|
|
@@ -95,6 +96,9 @@ class kiwis_request_info(Enum):
|
|
95
96
|
Formats = "Formats"
|
96
97
|
Returnfields = "Returnfields"
|
97
98
|
OptionalFields = "Optionalfields"
|
99
|
+
Subdescription = "Subdescription"
|
100
|
+
Dateformats = "Dateformats"
|
101
|
+
Transformations= "Transformations"
|
98
102
|
|
99
103
|
class kiwis_token(Enum):
|
100
104
|
ACCESS_TOKEN_KEY = 'access_token'
|
@@ -136,6 +140,7 @@ class kiwis_keywords_horq(Enum):
|
|
136
140
|
VMAXAN = 'an.maximum'
|
137
141
|
VMAXANHYD = 'anHydro.maximum'
|
138
142
|
VMINANHYD = 'anHydro.minimum'
|
143
|
+
|
139
144
|
class kiwis_keywords_rain(Enum):
|
140
145
|
V5_10MIN = 'production'
|
141
146
|
V1H = '1h.total'
|
@@ -184,6 +189,22 @@ class quality_code(Enum):
|
|
184
189
|
VOID = (255, 'black', '.')
|
185
190
|
VOID2 = (-1, 'black', '.')
|
186
191
|
|
192
|
+
class station_fields(Enum):
|
193
|
+
STATION_ID = 'station_id'
|
194
|
+
STATION_NO = 'station_no'
|
195
|
+
STATION_NAME = 'station_name'
|
196
|
+
STATION_LOCAL_X = 'station_local_x'
|
197
|
+
STATION_LOCAL_Y = 'station_local_y'
|
198
|
+
STATION_LATITUDE = 'station_latitude'
|
199
|
+
STATION_LONGITUDE = 'station_longitude'
|
200
|
+
RIVER_NAME = 'river_name'
|
201
|
+
|
202
|
+
class timeseries_fields(Enum):
|
203
|
+
TS_ID = 'ts_id'
|
204
|
+
TS_NAME = 'ts_name'
|
205
|
+
TS_UNITNAME = 'ts_unitname'
|
206
|
+
TS_UNITSYMBOL ='ts_unitsymbol'
|
207
|
+
|
187
208
|
class hydrometry():
|
188
209
|
|
189
210
|
def __init__(self, url:str=URL_SPW, urltoken:str=URL_TOKEN, credential ='', dir='') -> None:
|
@@ -226,15 +247,24 @@ class hydrometry():
|
|
226
247
|
self.realstations = None
|
227
248
|
pass
|
228
249
|
|
250
|
+
def __str__(self) -> str:
|
251
|
+
ret='Columns in stations :\n'
|
252
|
+
for curcol in self.realstations.columns:
|
253
|
+
ret+=curcol+'\n'
|
254
|
+
return ret
|
255
|
+
|
229
256
|
def _get_commandstr(self, which:str):
|
257
|
+
""" Construction de la commande à envoyer au serveur KIWIS """
|
258
|
+
|
230
259
|
return self.url+'?request='+which.value+'&format=json'
|
231
260
|
|
232
261
|
def daily_token(self):
|
233
262
|
"""
|
234
263
|
Get daily token to be identified on hydrometry website
|
235
264
|
|
236
|
-
|
265
|
+
#FIXME: better manage error as response
|
237
266
|
"""
|
267
|
+
|
238
268
|
if self.credential == '':
|
239
269
|
self._header = None
|
240
270
|
return
|
@@ -247,64 +277,97 @@ class hydrometry():
|
|
247
277
|
else:
|
248
278
|
headers = {'Authorization' : 'Basic {}'.format(self.credential)}
|
249
279
|
data = {'grant_type' :'client_credentials'}
|
250
|
-
|
251
|
-
|
252
|
-
|
280
|
+
|
281
|
+
try:
|
282
|
+
self.token = requests.post(self.urltoken, data=data, headers=headers).json()
|
283
|
+
|
284
|
+
if 'error' in self.token:
|
285
|
+
self.token = None
|
286
|
+
self._header = {'Authorization': 'Bearer '}
|
287
|
+
return
|
288
|
+
|
289
|
+
with open(today, 'w') as f:
|
290
|
+
json.dump(self.token, f)
|
291
|
+
except:
|
292
|
+
self._header = {'Authorization': 'Bearer '}
|
293
|
+
return
|
294
|
+
self.token = None
|
253
295
|
|
254
296
|
self._header = {'Authorization': 'Bearer {}'.format(self.token['access_token'])}
|
255
297
|
|
256
298
|
def check_plot(self):
|
299
|
+
""" Instance is checked in mapviewer """
|
257
300
|
self.plotted = True
|
258
301
|
|
259
302
|
def uncheck_plot(self):
|
303
|
+
""" Instance is unchecked in mapviewer """
|
260
304
|
self.plotted = False
|
261
305
|
|
262
|
-
def save_struct(self,dir=''):
|
306
|
+
def save_struct(self, dir=''):
|
307
|
+
"""Sauvegarde des structures dans un répertoire
|
308
|
+
|
309
|
+
:param dir: répertoire de sauvegarde
|
310
|
+
"""
|
263
311
|
|
264
312
|
if dir=='':
|
265
313
|
return
|
266
314
|
|
267
|
-
|
268
|
-
|
269
|
-
self.groups.to_csv(join(dir,'groups.csv'))
|
270
|
-
self.requests.to_csv(join(dir,'requests.csv'))
|
315
|
+
dir = Path(dir)
|
316
|
+
dir.mkdir(parents=True, exist_ok=True)
|
271
317
|
|
272
|
-
|
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')
|
322
|
+
|
323
|
+
def _get_stations_pythonlist(self, site_no:str|int, onlyreal:bool= True):
|
324
|
+
""" Obtention des stations pour le site en liste python
|
325
|
+
|
326
|
+
:param site_no: numéro du site
|
327
|
+
:param onlyreal: ne prendre que les stations réelles, pas les calculées
|
328
|
+
"""
|
273
329
|
|
274
330
|
if onlyreal:
|
275
|
-
stations = self.realstations[self.realstations[
|
331
|
+
stations = self.realstations[self.realstations[kiwis_site_fields.site_no.value]==site_no]
|
276
332
|
else:
|
277
|
-
stations = self.stations[self.stations[
|
333
|
+
stations = self.stations[self.stations[kiwis_site_fields.site_no.value]==site_no]
|
278
334
|
|
279
|
-
list_name_code = [curname+' --- '+curno for curname,curno in zip(stations[
|
280
|
-
list_code_name = [curno +' --- '+curname for curname,curno in zip(stations[
|
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)]
|
281
337
|
|
282
338
|
return list_name_code, list_code_name
|
283
339
|
|
284
340
|
def _get_sites_pythonlist(self):
|
341
|
+
""" Obtention des sites en liste python """
|
285
342
|
|
286
|
-
list_name_code = [curname+' --- '+curno for curname,curno in zip(self.sites[
|
343
|
+
list_name_code = [curname+' --- '+curno for curname,curno in zip(self.sites[kiwis_site_fields.site_name.value].values,self.sites[kiwis_site_fields.site_no.value].values)]
|
287
344
|
return list_name_code
|
288
345
|
|
289
346
|
def get_stations(self):
|
290
|
-
"""Obtention des stations pour le serveur courant
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
347
|
+
"""Obtention des stations pour le serveur courant.
|
348
|
+
|
349
|
+
Une requête sur le serveur KIWIS retourne les informations pour toutes les stations.
|
350
|
+
Une séparation entre station réelle et station calculée est ensuite effectuée:
|
351
|
+
- self.realstations
|
352
|
+
- self.compstations
|
353
|
+
|
354
|
+
Champs des stations :
|
355
|
+
- site_no : numéro du site ; le site correspond au réseau de mesure : DGH pour les stations du SPW-MI et DCENN pour les stations du SPW-ARNE ;
|
356
|
+
- station_no, station_name : code et nom de la station ;
|
357
|
+
- station_local_x, station_local_y : coordonnées de la station en Lambert belge 1972 ;
|
358
|
+
- station_latitude,station_longitude : coordonnées de la station en ETRS89 ;
|
359
|
+
- river_name : nom de la rivière, cette information n’est disponible que pour les stations de mesure de hauteur d’eau et de débits, les pluviomètres ne sont pas installés sur une rivière – il n’y a donc pas de nom de rivière associé ;
|
360
|
+
- parametertype_name : type de paramètre ;
|
361
|
+
- ts_id, ts_name : code et nom de la chronique ;
|
362
|
+
- ts_unitname, ts_unitsymbol : nom et symbole de l’unité de mesure ;
|
363
|
+
- ca_sta&ca_sta_returnfields=BV_DCE : nom du bassin versant principal suivi de son abréviation (2 lettres)
|
364
|
+
"""
|
365
|
+
|
366
|
+
returnfields = f'{kiwis_site_fields.site_no.value},'
|
367
|
+
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},'
|
369
|
+
returnfields += f'{station_fields.STATION_LATITUDE.value},{station_fields.STATION_LONGITUDE.value},'
|
370
|
+
returnfields += f'{station_fields.RIVER_NAME.value},'
|
308
371
|
returnfields += 'ca_sta'
|
309
372
|
|
310
373
|
ca_sta_returnfields = 'station_gauge_datum,'
|
@@ -327,34 +390,67 @@ class hydrometry():
|
|
327
390
|
self.stations = pd.DataFrame(json_data[1:], columns = json_data[0])
|
328
391
|
|
329
392
|
#Conversion en minuscules
|
330
|
-
self.stations[
|
393
|
+
self.stations[station_fields.STATION_NAME.value]=self.stations[station_fields.STATION_NAME.value].str.lower()
|
331
394
|
|
332
395
|
# real stations are those with coordinates and not null
|
333
|
-
self.realstations = self.stations[(~pd.isnull(self.stations[
|
396
|
+
self.realstations = self.stations[(~pd.isnull(self.stations[station_fields.STATION_LOCAL_X.value])) & (self.stations[station_fields.STATION_LOCAL_X.value]!='')]
|
334
397
|
# computed stations are those without coordinates or null
|
335
|
-
self.compstations = self.stations[pd.isnull(self.stations[
|
398
|
+
self.compstations = self.stations[pd.isnull(self.stations[station_fields.STATION_LOCAL_X.value]) | self.stations[station_fields.STATION_LOCAL_X.value]!='']
|
336
399
|
|
337
400
|
def get_names_xy(self, site_no = None):
|
338
|
-
"""Obtention des noms et coordonnées des stations pour le site
|
401
|
+
"""Obtention des noms et coordonnées des stations pour le site
|
402
|
+
|
403
|
+
:param site_no: numéro du site
|
404
|
+
"""
|
405
|
+
|
406
|
+
if site_no is None:
|
407
|
+
stations_r = self.realstations
|
408
|
+
# stations_c = self.compstations
|
409
|
+
else:
|
410
|
+
stations_r = self.realstations[self.realstations[kiwis_site_fields.site_no.value]==site_no]
|
411
|
+
# stations_c = self.compstations[self.stations[kiwis_site_fields.site_no.value]==site_no]
|
412
|
+
|
413
|
+
if stations_r is None:
|
414
|
+
return ([],[],[])
|
415
|
+
else:
|
416
|
+
return ([curname + ' - ' + str(curid) for curname, curid in zip(stations_r[station_fields.STATION_NAME.value].values,
|
417
|
+
stations_r[station_fields.STATION_ID.value].values)],
|
418
|
+
stations_r[station_fields.STATION_LOCAL_X.value].values,
|
419
|
+
stations_r[station_fields.STATION_LOCAL_Y.value].values)
|
420
|
+
|
421
|
+
def get_names_latlon(self, site_no = None):
|
422
|
+
""" Obtention des noms et coordonnées des stations pour le site
|
423
|
+
|
424
|
+
:param site_no: numéro du site
|
425
|
+
"""
|
339
426
|
|
340
427
|
if site_no is None:
|
341
428
|
stations_r = self.realstations
|
342
429
|
# stations_c = self.compstations
|
343
430
|
else:
|
344
|
-
stations_r = self.realstations[self.realstations[
|
345
|
-
# stations_c = self.compstations[self.stations[
|
431
|
+
stations_r = self.realstations[self.realstations[kiwis_site_fields.site_no.value]==site_no]
|
432
|
+
# stations_c = self.compstations[self.stations[kiwis_site_fields.site_no.value]==site_no]
|
346
433
|
|
347
434
|
if stations_r is None:
|
348
435
|
return ([],[],[])
|
349
436
|
else:
|
350
|
-
return ([curname + ' - ' + str(curid) for curname, curid in zip(stations_r[
|
437
|
+
return ([curname + ' - ' + str(curid) for curname, curid in zip(stations_r[station_fields.STATION_NAME.value].values,
|
438
|
+
stations_r[station_fields.STATION_ID.value].values)],
|
439
|
+
stations_r[station_fields.STATION_LATITUDE.value].values,
|
440
|
+
stations_r[station_fields.STATION_LONGITUDE.value].values)
|
441
|
+
|
351
442
|
|
352
443
|
def select_inside(self, xll:float, yll:float, xur:float, yur:float, tolist=False):
|
353
444
|
"""
|
354
445
|
Recherche les stations dans une zone rectangulaire
|
355
446
|
|
356
|
-
xll
|
357
|
-
|
447
|
+
:param xll: X lower left - Lambert 72
|
448
|
+
:param yll: Y lower left - Lambert 72
|
449
|
+
:param xur: X upper right - Lambert 72
|
450
|
+
:param yur: Y upper right - Lambert 72
|
451
|
+
:param tolist: retourne une liste de noms et codes de stations et nom un dataframe
|
452
|
+
|
453
|
+
:return: liste de noms et codes de stations ou dataframe
|
358
454
|
"""
|
359
455
|
|
360
456
|
if xll>xur:
|
@@ -366,35 +462,103 @@ class hydrometry():
|
|
366
462
|
yll=yur
|
367
463
|
yur=tmpy
|
368
464
|
|
369
|
-
df = self.realstations[(self.realstations[
|
465
|
+
df = self.realstations[(self.realstations[station_fields.STATION_LOCAL_X.value].to_numpy(dtype=np.float64)>=xll) & (self.realstations[station_fields.STATION_LOCAL_X.value].to_numpy(dtype=np.float64)<=xur) & \
|
466
|
+
(self.realstations[station_fields.STATION_LOCAL_Y.value].to_numpy(dtype=np.float64)>=yll) & (self.realstations[station_fields.STATION_LOCAL_Y.value].to_numpy(dtype=np.float64)<=yur)]
|
467
|
+
if tolist:
|
468
|
+
list_name_code = [curname+' --- '+curno for curname,curno in zip(df[station_fields.STATION_NAME.value].values,df[station_fields.STATION_NO.value].values)]
|
469
|
+
return list_name_code
|
470
|
+
else:
|
471
|
+
return df
|
472
|
+
|
473
|
+
def select_inside_latlon(self, lonll:float, latll:float, lonur:float, latur:float, tolist=False):
|
474
|
+
"""
|
475
|
+
Recherche les stations dans une zone rectangulaire
|
476
|
+
|
477
|
+
:param lonll: Longitude lower left - WGS84
|
478
|
+
:param latll: Latitude lower left - WGS84
|
479
|
+
:param lonur: Longitude upper right - WGS84
|
480
|
+
:param latur: Latitude upper right - WGS84
|
481
|
+
:param tolist: retourne une liste de noms et codes de stations et nom un dataframe
|
482
|
+
|
483
|
+
:return: liste de noms et codes de stations ou dataframe
|
484
|
+
"""
|
485
|
+
|
486
|
+
if lonll>lonur:
|
487
|
+
tmpx=lonll
|
488
|
+
lonll=lonur
|
489
|
+
lonur=tmpx
|
490
|
+
if latll>latur:
|
491
|
+
tmpy=latll
|
492
|
+
latll=latur
|
493
|
+
latur=tmpy
|
494
|
+
|
495
|
+
df = self.realstations[(self.realstations[station_fields.STATION_LONGITUDE.value].to_numpy(dtype=np.float64)>=lonll) & (self.realstations[station_fields.STATION_LONGITUDE.value].to_numpy(dtype=np.float64)<=lonur) & \
|
496
|
+
(self.realstations[station_fields.STATION_LATITUDE.value].to_numpy(dtype=np.float64)>=latll) & (self.realstations[station_fields.STATION_LATITUDE.value].to_numpy(dtype=np.float64)<=latur)]
|
370
497
|
if tolist:
|
371
|
-
list_name_code = [curname+' --- '+curno for curname,curno in zip(df[
|
498
|
+
list_name_code = [curname+' --- '+curno for curname,curno in zip(df[station_fields.STATION_NAME.value].values,df[station_fields.STATION_NO.value].values)]
|
372
499
|
return list_name_code
|
373
500
|
else:
|
374
501
|
return df
|
375
502
|
|
376
|
-
def sort_nearests(self,x:float,y:float):
|
503
|
+
def sort_nearests(self, x:float, y:float):
|
504
|
+
"""
|
505
|
+
Trie les stations en fonction de la distance et retourne un index trié
|
506
|
+
|
507
|
+
:param x: coordonnée x - Lambert 72
|
508
|
+
:param y: coordonnée y - Lambert 72
|
509
|
+
"""
|
510
|
+
dist = np.asarray([(float(cur[station_fields.STATION_LOCAL_X.value]) - x)**2 + (float(cur[station_fields.STATION_LOCAL_Y.value]) - y)**2 for idx,cur in self.realstations.iterrows()])
|
511
|
+
index = np.arange(len(dist))[dist.argsort()]
|
512
|
+
|
513
|
+
return index
|
514
|
+
|
515
|
+
def sort_nearests_latlon(self, lon:float, lat:float):
|
377
516
|
"""
|
378
517
|
Trie les stations en fonction de la distance et retourne un index trié
|
518
|
+
|
519
|
+
:param lon: longitude - WGS84
|
520
|
+
:param lat: latitude - WGS84
|
379
521
|
"""
|
380
|
-
dist = np.asarray([(float(cur[
|
522
|
+
dist = np.asarray([(float(cur[station_fields.STATION_LATITUDE.value]) - lat)**2 + (float(cur[station_fields.STATION_LONGITUDE.value]) - lon)**2 for idx,cur in self.realstations.iterrows()])
|
381
523
|
index = np.arange(len(dist))[dist.argsort()]
|
382
524
|
|
383
525
|
return index
|
384
526
|
|
385
|
-
def find_nearest(self,x:float,y:float, tolist=False):
|
527
|
+
def find_nearest(self, x:float, y:float, tolist=False):
|
386
528
|
"""
|
387
529
|
Trouve la station la plus proche
|
530
|
+
|
531
|
+
:param x: coordonnée x - Lambert 72
|
532
|
+
:param y: coordonnée y - Lambert 72
|
388
533
|
"""
|
389
534
|
index = self.sort_nearests(x,y)
|
390
535
|
|
391
536
|
if tolist:
|
392
|
-
return [self.realstations.iloc[index[0]][
|
537
|
+
return [self.realstations.iloc[index[0]][station_fields.STATION_NAME.value]+' --- '+self.realstations.iloc[index[0]][station_fields.STATION_NO.value]]
|
538
|
+
else:
|
539
|
+
return self.realstations.iloc[index[0]]
|
540
|
+
|
541
|
+
def find_nearest_latlon(self, lon:float, lat:float, tolist=False):
|
542
|
+
"""
|
543
|
+
Trouve la station la plus proche
|
544
|
+
|
545
|
+
:param lon: longitude - WGS84
|
546
|
+
:param lat: latitude - WGS84
|
547
|
+
"""
|
548
|
+
|
549
|
+
index = self.sort_nearests_latlon(lon,lat)
|
550
|
+
|
551
|
+
if tolist:
|
552
|
+
return [self.realstations.iloc[index[0]][station_fields.STATION_NAME.value]+' --- '+self.realstations.iloc[index[0]][station_fields.STATION_NO.value]]
|
393
553
|
else:
|
394
554
|
return self.realstations.iloc[index[0]]
|
395
555
|
|
396
556
|
def get_timeseries_group(self, rfw:Literal['rain','waterdepth','flowrate'], time:Literal['5min','5or10min','1h','1d','1m']):
|
397
|
-
"""Obtention des stations pour le groupe souhaité
|
557
|
+
"""Obtention des stations pour le groupe souhaité
|
558
|
+
|
559
|
+
:param rfw: type de groupe - rain, flowrate, waterdepth
|
560
|
+
:param time: type de série - 5min, 5or10min, 1h, 1d, 1m
|
561
|
+
"""
|
398
562
|
|
399
563
|
if self.url!='':
|
400
564
|
stations=None
|
@@ -406,21 +570,31 @@ class hydrometry():
|
|
406
570
|
|
407
571
|
return stations
|
408
572
|
|
409
|
-
def get_sites(self):
|
410
|
-
"""Obtention des sites pour le serveur courant
|
411
|
-
|
573
|
+
def get_sites(self, forcerequest=False):
|
574
|
+
"""Obtention des sites pour le serveur courant
|
575
|
+
|
576
|
+
:param forcerequest: force la requête même si les données de cache sont déjà présentes"""
|
577
|
+
|
578
|
+
if self.dir!='' and exists(join(self.dir,'sites.csv')) and not forcerequest:
|
412
579
|
self.sites = pd.read_csv(join(self.dir,'sites.csv'),index_col=0)
|
413
|
-
elif self.url!='':
|
580
|
+
elif self.url!='' or forcerequest:
|
414
581
|
json_data = requests.get(self._get_commandstr(kiwis_command.getSiteList),verify=True, headers=self._header).json()
|
415
582
|
self.sites = pd.DataFrame(json_data[1:], columns = json_data[0])
|
583
|
+
else:
|
584
|
+
self.sites = None
|
585
|
+
|
586
|
+
def get_groups(self, forcerequest=False):
|
587
|
+
"""Obtention des groupes pour le serveur courant
|
416
588
|
|
417
|
-
|
418
|
-
|
419
|
-
if self.dir!='' and exists(join(self.dir,'groups.csv')):
|
589
|
+
:param forcerequest: force la requête même si les données de cache sont déjà présentes"""
|
590
|
+
|
591
|
+
if self.dir!='' and exists(join(self.dir,'groups.csv')) and not forcerequest:
|
420
592
|
self.groups = pd.read_csv(join(self.dir,'groups.csv'),index_col=0)
|
421
|
-
elif self.url!='':
|
593
|
+
elif self.url!='' or forcerequest:
|
422
594
|
json_data = requests.get(self._get_commandstr(kiwis_command.getGroupList),verify=True, headers=self._header).json()
|
423
595
|
self.groups = pd.DataFrame(json_data[1:], columns = json_data[0])
|
596
|
+
else:
|
597
|
+
self.groups = None
|
424
598
|
|
425
599
|
# def get_ratingcurves(self):
|
426
600
|
# """Obtention des courbes de tarage pour le serveur courant"""
|
@@ -430,15 +604,24 @@ class hydrometry():
|
|
430
604
|
# json_data = requests.get(self.url+'?request=getRatingCurveList&datasource=0&format=json',verify=True).json()
|
431
605
|
# self.ratingcurves = pd.DataFrame(json_data[1:], columns = json_data[0])
|
432
606
|
|
433
|
-
def get_requests(self):
|
434
|
-
"""Obtention des requêtes possibles pour le serveur courant
|
435
|
-
|
607
|
+
def get_requests(self, forcerequest=False):
|
608
|
+
"""Obtention des requêtes possibles pour le serveur courant
|
609
|
+
|
610
|
+
:param forcerequest: force la requête même si les données de cache sont déjà présentes"""
|
611
|
+
|
612
|
+
if self.dir!='' and exists(join(self.dir,'requests.csv')) and not forcerequest:
|
436
613
|
self.requests = pd.read_csv(join(self.dir,'requests.csv'),index_col=0)
|
437
|
-
elif self.url!='':
|
614
|
+
elif self.url!='' or forcerequest:
|
438
615
|
json_data = requests.get(self._get_commandstr(kiwis_command.getrequestinfo),verify=True, headers=self._header).json()
|
439
616
|
self.requests = pd.DataFrame(json_data[0]['Requests'])
|
617
|
+
else:
|
618
|
+
self.requests = None
|
619
|
+
|
620
|
+
def print_requestinfo(self, which:kiwis_command):
|
621
|
+
""" Affichage des informations pour une requête donnée
|
622
|
+
|
623
|
+
:param which: requête à afficher"""
|
440
624
|
|
441
|
-
def print_requestinfo(self,which:Enum):
|
442
625
|
if self.requests is None:
|
443
626
|
self.get_requests()
|
444
627
|
|
@@ -448,8 +631,13 @@ class hydrometry():
|
|
448
631
|
for cur in kiwis_request_info:
|
449
632
|
print(myrequest[cur.value])
|
450
633
|
|
451
|
-
def timeseries_list(self,stationname='',stationcode=''):
|
452
|
-
"""Récupération de la liste des TimeSeries pour l'id d'une station
|
634
|
+
def timeseries_list(self, stationname:str = '', stationcode:str = ''):
|
635
|
+
"""Récupération de la liste des TimeSeries pour l'id d'une station
|
636
|
+
soit via le nom de la station, soit via le code de la station.
|
637
|
+
|
638
|
+
:param stationname: nom de la station
|
639
|
+
:param stationcode: code de la station
|
640
|
+
"""
|
453
641
|
|
454
642
|
if stationname!='':
|
455
643
|
id=self.get_stationid(stationname)
|
@@ -463,12 +651,15 @@ class hydrometry():
|
|
463
651
|
|
464
652
|
return id,pd.DataFrame(json_data[1:], columns = json_data[0])
|
465
653
|
|
466
|
-
def save_all_lists(self,dir):
|
467
|
-
"""Sauveragde des listes pour toutes les stations
|
468
|
-
|
469
|
-
|
654
|
+
def save_all_lists(self, dir:str):
|
655
|
+
"""Sauveragde des listes pour toutes les stations
|
656
|
+
|
657
|
+
:param dir: répertoire de sauvegarde"""
|
470
658
|
|
471
|
-
|
659
|
+
for curstation in self.stations[station_fields.STATION_NO.value]:
|
660
|
+
self.save_list(stationcode=curstation, dir=dir)
|
661
|
+
|
662
|
+
def _get_filename_list(self, stationname:str='', stationcode:str=''):
|
472
663
|
"""retourne un nom de fichier avec la station et le code
|
473
664
|
|
474
665
|
Utile car dans certains noms de la BDD KIWIS il y a un caractère '/' qui ne peut être utilisé comme nom de fichier
|
@@ -484,7 +675,8 @@ class hydrometry():
|
|
484
675
|
|
485
676
|
return stationname.replace('/','-') + '_' + stationcode + '_' + str(id) + '.csv'
|
486
677
|
|
487
|
-
def _get_filename_series(self,stationname='',stationcode='',
|
678
|
+
def _get_filename_series(self,stationname:str='',stationcode:str='',
|
679
|
+
which:kiwis_default_q | kiwis_default_h | kiwis_keywords_horq | kiwis_keywords_rain = kiwis_default_q.Q_FULL):
|
488
680
|
"""retourne un nom de fichier avec la station et le code et le type de données
|
489
681
|
|
490
682
|
Utile car dans certains noms de la BDD KIWIS il y a un caractère '/' qui ne peut être utilisé comme nom de fichier
|
@@ -500,16 +692,24 @@ class hydrometry():
|
|
500
692
|
|
501
693
|
return stationname.replace('/','-') + '_' + stationcode + '_' + str(id) + '_' + which.value + '.csv'
|
502
694
|
|
503
|
-
def save_list(self,stationname='',stationcode='',dir=''):
|
504
|
-
"""Sauvegarde de la liste des des timeseries dans un fichier
|
505
|
-
|
506
|
-
|
695
|
+
def save_list(self, stationname:str = '', stationcode:str = '', dir:str = ''):
|
696
|
+
"""Sauvegarde de la liste des des timeseries dans un fichier
|
697
|
+
|
698
|
+
:param stationname: nom de la station
|
699
|
+
:param stationcode: code de la station
|
700
|
+
:param dir: répertoire de sauvegarde"""
|
701
|
+
|
702
|
+
dir = Path(dir)
|
703
|
+
if not dir.exists():
|
704
|
+
dir.mkdir(parents=True, exist_ok=True)
|
507
705
|
|
508
706
|
id,list=self.timeseries_list(stationname=stationname,stationcode=stationcode)
|
509
707
|
filename = self._get_filename_list(stationname,stationcode)
|
510
|
-
list.to_csv(
|
708
|
+
list.to_csv(dir / filename)
|
511
709
|
|
512
|
-
def timeseries(self,stationname='', stationcode
|
710
|
+
def timeseries(self,stationname:str='', stationcode:str='', dir:str='',
|
711
|
+
fromdate=datetime.now()-timedelta(60), todate=datetime.now(),
|
712
|
+
ts_name:str='', ts_id:str='', interval:int=3600, timezone:str = 'GMT+0'):
|
513
713
|
"""
|
514
714
|
Récupération des valeurs d'une TimeSerie
|
515
715
|
- sur base des dates
|
@@ -517,6 +717,16 @@ class hydrometry():
|
|
517
717
|
- le nom de la station ou le code ET le nom de la timeserie --> dans ce cas, la routine commence par retrouver l'id de la ts
|
518
718
|
- directement l'id de la timeserie
|
519
719
|
|
720
|
+
:param stationname: nom de la station
|
721
|
+
:param stationcode: code de la station
|
722
|
+
:param dir: répertoire de sauvegarde
|
723
|
+
:param fromdate: date de début
|
724
|
+
:param todate: date de fin
|
725
|
+
:param ts_name: nom de la timeserie
|
726
|
+
:param ts_id: id de la timeserie
|
727
|
+
:param interval: intervalle de temps
|
728
|
+
:param timezone: timezone
|
729
|
+
|
520
730
|
"""
|
521
731
|
|
522
732
|
if timezone=='Europe/Brussels' or timezone=='local':
|
@@ -542,11 +752,11 @@ class hydrometry():
|
|
542
752
|
if len(json_data)==1:
|
543
753
|
return None
|
544
754
|
|
545
|
-
ts_id = str(int(pd.DataFrame(json_data[1:], columns = json_data[0])[
|
755
|
+
ts_id = str(int(pd.DataFrame(json_data[1:], columns = json_data[0])[timeseries_fields.TS_ID.value].iloc[0]))
|
546
756
|
else:
|
547
757
|
filename = self._get_filename_list(stationname,stationcode)
|
548
758
|
curlist=pd.read_csv(join(dir,filename),index_col=0)
|
549
|
-
ts_id = str(int(curlist.loc(curlist[
|
759
|
+
ts_id = str(int(curlist.loc(curlist[timeseries_fields.TS_NAME.value==ts_name])[timeseries_fields.TS_ID.value]))
|
550
760
|
|
551
761
|
if "1h" in ts_name:
|
552
762
|
nb = (todate - fromdate).days*24
|
@@ -573,7 +783,10 @@ class hydrometry():
|
|
573
783
|
locts=[]
|
574
784
|
while curfrom<todate:
|
575
785
|
print(curfrom, curend)
|
576
|
-
|
786
|
+
tmpts = self.timeseries(stationname, stationcode, dir, curfrom, curend, ts_name, ts_id, timezone=timezone)
|
787
|
+
if len(tmpts)>0:
|
788
|
+
locts.append(tmpts)
|
789
|
+
|
577
790
|
curfrom = curend
|
578
791
|
curend = curfrom+timedelta(seconds=200000 * cursec)
|
579
792
|
if curend>todate:
|
@@ -596,7 +809,9 @@ class hydrometry():
|
|
596
809
|
|
597
810
|
return df.squeeze()
|
598
811
|
|
599
|
-
def timeseries_qc(self,stationname='', stationcode
|
812
|
+
def timeseries_qc(self, stationname:str='', stationcode:str='', dir:str='',
|
813
|
+
fromdate=datetime.now()-timedelta(60), todate=datetime.now(),
|
814
|
+
ts_name:str='', ts_id:str='', interval:int=3600, timezone:str = 'GMT+0'):
|
600
815
|
"""
|
601
816
|
Récupération des quality code d'une TimeSerie
|
602
817
|
- sur base des dates
|
@@ -604,6 +819,16 @@ class hydrometry():
|
|
604
819
|
- le nom de la station ou le code ET le nom de la timeserie --> dans ce cas, la routine commence par retrouver l'id de la ts
|
605
820
|
- directement l'id de la timeserie
|
606
821
|
|
822
|
+
:param stationname: nom de la station
|
823
|
+
:param stationcode: code de la station
|
824
|
+
:param dir: répertoire de sauvegarde
|
825
|
+
:param fromdate: date de début
|
826
|
+
:param todate: date de fin
|
827
|
+
:param ts_name: nom de la timeserie
|
828
|
+
:param ts_id: id de la timeserie
|
829
|
+
:param interval: intervalle de temps
|
830
|
+
:param timezone: timezone
|
831
|
+
|
607
832
|
"""
|
608
833
|
if timezone=='Europe/Brussels' or timezone=='local':
|
609
834
|
timezone=''
|
@@ -629,11 +854,11 @@ class hydrometry():
|
|
629
854
|
if len(json_data)==1:
|
630
855
|
return None
|
631
856
|
|
632
|
-
ts_id = str(int(pd.DataFrame(json_data[1:], columns = json_data[0])[
|
857
|
+
ts_id = str(int(pd.DataFrame(json_data[1:], columns = json_data[0])[timeseries_fields.TS_ID.value].iloc[0]))
|
633
858
|
else:
|
634
859
|
filename = self._get_filename_list(stationname,stationcode)
|
635
860
|
curlist=pd.read_csv(join(dir,filename),index_col=0)
|
636
|
-
ts_id = str(int(curlist.loc(curlist[
|
861
|
+
ts_id = str(int(curlist.loc(curlist[timeseries_fields.TS_NAME.value==ts_name])[timeseries_fields.TS_ID.value]))
|
637
862
|
|
638
863
|
if "1h" in ts_name:
|
639
864
|
nb = (todate - fromdate).days*24
|
@@ -683,14 +908,27 @@ class hydrometry():
|
|
683
908
|
|
684
909
|
return df.squeeze()
|
685
910
|
|
686
|
-
def fromcsv(self,dir='spw',stationname='',stationcode='',
|
911
|
+
def fromcsv(self, dir:str='spw', stationname:str='', stationcode:str='',
|
912
|
+
which:kiwis_default_q | kiwis_default_h | kiwis_keywords_horq | kiwis_keywords_rain = kiwis_default_q.Q_FULL,
|
913
|
+
fromdate:datetime=None, todate:datetime=None):
|
687
914
|
"""
|
688
|
-
Lecture depuis un fichier csv créé depuis un import précédent
|
689
|
-
Les fichiers doivent être disponibles depuis un sous-répertoire spw
|
915
|
+
Lecture depuis un fichier csv créé depuis un import précédent.
|
916
|
+
Les fichiers doivent être disponibles depuis un sous-répertoire spw.
|
917
|
+
|
918
|
+
:param dir: répertoire de sauvegarde
|
919
|
+
:param stationname: nom de la station
|
920
|
+
:param stationcode: code de la station
|
921
|
+
:param which: type de données
|
922
|
+
:param fromdate: date de début
|
923
|
+
:param todate: date de fin
|
924
|
+
|
690
925
|
"""
|
691
|
-
filename=
|
926
|
+
filename=self._get_filename_series(stationname,stationcode,which)
|
927
|
+
|
928
|
+
dir = Path(dir)
|
929
|
+
filename = dir / filename
|
692
930
|
|
693
|
-
if exists(
|
931
|
+
if filename.exists():
|
694
932
|
mydata= pd.read_csv(filename,header=0,index_col=0,parse_dates=True,engine='pyarrow').squeeze("columns")
|
695
933
|
else:
|
696
934
|
return
|
@@ -704,88 +942,134 @@ class hydrometry():
|
|
704
942
|
else:
|
705
943
|
return mydata[fromdate:todate]
|
706
944
|
|
707
|
-
def saveas(self,flow:pd.Series,dir:str,stationname='',stationcode='',
|
708
|
-
|
945
|
+
def saveas(self, flow:pd.Series, dir:str, stationname='', stationcode='',
|
946
|
+
which:kiwis_default_q | kiwis_default_h | kiwis_keywords_horq | kiwis_keywords_rain = kiwis_default_q.Q_FULL):
|
947
|
+
"""Sauvegarde d'une series pandas dans un fichier .csv
|
948
|
+
|
949
|
+
:param flow: série pandas
|
950
|
+
:param dir: répertoire de sauvegarde
|
951
|
+
:param stationname: nom de la station
|
952
|
+
:param stationcode: code de la station
|
953
|
+
:param which: type de données
|
954
|
+
"""
|
955
|
+
|
709
956
|
filename=self._get_filename_series(stationname,stationcode,which.value)
|
957
|
+
|
958
|
+
dir = Path(dir)
|
959
|
+
filename = dir / filename
|
960
|
+
|
710
961
|
flow.to_csv(filename,header=['Data'], date_format="%Y-%m-%dT%H:%M:%S.%f%z")
|
711
962
|
|
712
|
-
def get_stationid(self,name:str='',code=''):
|
713
|
-
"""Récupération de l'id sur base du nom ou du code
|
963
|
+
def get_stationid(self, name:str='', code:str='') -> int:
|
964
|
+
"""Récupération de l'id sur base du nom ou du code
|
965
|
+
|
966
|
+
:param name: nom de la station
|
967
|
+
:param code: code de la station"""
|
968
|
+
|
714
969
|
if name!='':
|
715
|
-
return int(self.stations.loc[self.stations[
|
970
|
+
return int(self.stations.loc[self.stations[station_fields.STATION_NAME.value]==name.lower()][station_fields.STATION_ID.value].iloc[0])
|
716
971
|
elif code!='':
|
717
|
-
return int(self.stations.loc[self.stations[
|
972
|
+
return int(self.stations.loc[self.stations[station_fields.STATION_NO.value]==code][station_fields.STATION_ID.value].iloc[0])
|
718
973
|
else:
|
719
974
|
return None
|
720
975
|
|
721
|
-
def get_gauge_datum(self,name:str='',code=''):
|
722
|
-
"""Récupération de l'altitude de référence sur base du nom ou du code
|
976
|
+
def get_gauge_datum(self,name:str='',code:str=''):
|
977
|
+
"""Récupération de l'altitude de référence sur base du nom ou du code
|
978
|
+
|
979
|
+
:param name: nom de la station
|
980
|
+
:param code: code de la station"""
|
981
|
+
|
723
982
|
try:
|
724
983
|
if name!='':
|
725
|
-
return self.stations.loc[self.stations[
|
984
|
+
return self.stations.loc[self.stations[station_fields.STATION_NAME.value]==name.lower()]['station_gauge_datum'].iloc[0]
|
726
985
|
elif code!='':
|
727
|
-
return self.stations.loc[self.stations[
|
986
|
+
return self.stations.loc[self.stations[station_fields.STATION_NO.value]==code]['station_gauge_datum'].iloc[0]
|
728
987
|
else:
|
729
988
|
return None
|
730
989
|
except:
|
731
990
|
return None
|
732
991
|
|
733
|
-
def get_catchment_size(self,name:str='',code=''):
|
734
|
-
"""Récupération de la surface du BV de référence sur base du nom ou du code
|
992
|
+
def get_catchment_size(self,name:str='',code:str=''):
|
993
|
+
"""Récupération de la surface du BV de référence sur base du nom ou du code
|
994
|
+
|
995
|
+
:param name: nom de la station
|
996
|
+
:param code: code de la station"""
|
997
|
+
|
735
998
|
try:
|
736
999
|
if name!='':
|
737
|
-
return self.stations.loc[self.stations[
|
1000
|
+
return self.stations.loc[self.stations[station_fields.STATION_NAME.value]==name.lower()]['CATCHMENT_SIZE'].iloc[0]
|
738
1001
|
elif code!='':
|
739
|
-
return self.stations.loc[self.stations[
|
1002
|
+
return self.stations.loc[self.stations[station_fields.STATION_NO.value]==code]['CATCHMENT_SIZE'].iloc[0]
|
740
1003
|
else:
|
741
1004
|
return None
|
742
1005
|
except:
|
743
1006
|
return None
|
744
1007
|
|
745
|
-
def get_bv_dce(self,name:str='',code=''):
|
746
|
-
"""Récupération du nom de BV au sens de la DCE "Directive Cadre Eau" sur base du nom ou du code
|
1008
|
+
def get_bv_dce(self,name:str='',code:str=''):
|
1009
|
+
"""Récupération du nom de BV au sens de la DCE "Directive Cadre Eau" sur base du nom ou du code
|
1010
|
+
|
1011
|
+
:param name: nom de la station
|
1012
|
+
:param code: code de la station"""
|
1013
|
+
|
747
1014
|
try:
|
748
1015
|
if name!='':
|
749
|
-
return self.stations.loc[self.stations[
|
1016
|
+
return self.stations.loc[self.stations[station_fields.STATION_NAME.value]==name.lower()]['BV_DCE'].iloc[0]
|
750
1017
|
elif code!='':
|
751
|
-
return self.stations.loc[self.stations[
|
1018
|
+
return self.stations.loc[self.stations[station_fields.STATION_NO.value]==code]['BV_DCE'].iloc[0]
|
752
1019
|
else:
|
753
1020
|
return None
|
754
1021
|
except:
|
755
1022
|
return None
|
756
1023
|
|
757
1024
|
def get_stationcode(self,name:str=''):
|
758
|
-
"""Récupération du code sur base du nom
|
1025
|
+
"""Récupération du code sur base du nom
|
1026
|
+
|
1027
|
+
:param name: nom de la station
|
1028
|
+
"""
|
1029
|
+
|
759
1030
|
if name!='':
|
760
|
-
return self.stations.loc[self.stations[
|
1031
|
+
return self.stations.loc[self.stations[station_fields.STATION_NAME.value]==name.lower()][station_fields.STATION_NO.value].squeeze()
|
761
1032
|
else:
|
762
1033
|
return None
|
763
1034
|
|
764
1035
|
def get_stationname(self,code:str=''):
|
765
|
-
"""Récupération du nom sur base du code
|
1036
|
+
"""Récupération du nom sur base du code
|
1037
|
+
|
1038
|
+
:param code: code de la station"""
|
1039
|
+
|
766
1040
|
if code!='':
|
767
|
-
return self.stations.loc[self.stations[
|
1041
|
+
return self.stations.loc[self.stations[station_fields.STATION_NO.value]==code][station_fields.STATION_NAME.value].squeeze()
|
768
1042
|
else:
|
769
1043
|
return None
|
770
1044
|
|
771
|
-
def get_siteid(self,name:str='',code=''):
|
772
|
-
"""Récupération de l'id sur base du nom ou du code
|
1045
|
+
def get_siteid(self,name:str='',code:str=''):
|
1046
|
+
"""Récupération de l'id sur base du nom ou du code
|
1047
|
+
|
1048
|
+
:param name: nom de la station
|
1049
|
+
:param code: code de la station"""
|
1050
|
+
|
773
1051
|
if name!='':
|
774
|
-
return int(self.sites.loc[self.sites[kiwis_site_fields.site_name.value]==name.lower()][
|
1052
|
+
return int(self.sites.loc[self.sites[kiwis_site_fields.site_name.value]==name.lower()][kiwis_site_fields.site_id.value])
|
775
1053
|
elif code!='':
|
776
|
-
return int(self.sites.loc[self.sites[kiwis_site_fields.site_no.value]==code][
|
1054
|
+
return int(self.sites.loc[self.sites[kiwis_site_fields.site_no.value]==code][kiwis_site_fields.site_id.value])
|
777
1055
|
else:
|
778
1056
|
return None
|
779
1057
|
|
780
|
-
def get_sitecode(self,name:str=''):
|
781
|
-
"""Récupération du code sur base du nom
|
1058
|
+
def get_sitecode(self, name:str=''):
|
1059
|
+
"""Récupération du code sur base du nom
|
1060
|
+
|
1061
|
+
:param name: nom de la station"""
|
1062
|
+
|
782
1063
|
if name!='':
|
783
1064
|
return self.sites.loc[self.sites[kiwis_site_fields.site_name.value]==name.lower()][kiwis_site_fields.site_no.value].squeeze()
|
784
1065
|
else:
|
785
1066
|
return None
|
786
1067
|
|
787
1068
|
def get_sitename(self,code:str=''):
|
788
|
-
"""Récupération du nom sur base du code
|
1069
|
+
"""Récupération du nom sur base du code
|
1070
|
+
|
1071
|
+
:param code: code de la station"""
|
1072
|
+
|
789
1073
|
if code!='':
|
790
1074
|
return self.sites.loc[self.sites[kiwis_site_fields.site_no.value]==code][kiwis_site_fields.site_name.value].squeeze()
|
791
1075
|
else:
|