wolfhece 1.8.8__py3-none-any.whl → 1.8.9__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/GraphNotebook.py +5 -3
- wolfhece/PyDraw.py +13 -6
- wolfhece/PyVertex.py +61 -15
- wolfhece/eva/hydrogramme_mono.py +8 -3
- wolfhece/eva/pyseries.py +210 -25
- wolfhece/ftp/__init__.py +0 -0
- wolfhece/ftp/downloader.py +141 -0
- wolfhece/hydrology/Catchment.py +81 -4
- wolfhece/hydrology/Comparison.py +110 -3
- wolfhece/hydrology/Optimisation.py +32 -8
- wolfhece/hydrology/Outlet.py +4 -4
- wolfhece/hydrology/PyWatershed.py +1951 -0
- wolfhece/hydrology/RetentionBasin.py +6 -6
- wolfhece/hydrology/SubBasin.py +70 -25
- wolfhece/hydrology/data_treatment.py +5 -3
- wolfhece/hydrology/plot_hydrology.py +64 -3
- wolfhece/hydrology/read.py +4 -4
- wolfhece/libs/WolfDll.dll +0 -0
- wolfhece/libs/WolfDll_debug.dll +0 -0
- wolfhece/mesh2d/wolf2dprev.py +104 -100
- wolfhece/radar/wolfradar.py +204 -13
- wolfhece/wolf_array.py +199 -87
- {wolfhece-1.8.8.dist-info → wolfhece-1.8.9.dist-info}/METADATA +4 -1
- {wolfhece-1.8.8.dist-info → wolfhece-1.8.9.dist-info}/RECORD +27 -24
- wolfhece/PyWatershed.py +0 -1686
- {wolfhece-1.8.8.dist-info → wolfhece-1.8.9.dist-info}/LICENCE +0 -0
- {wolfhece-1.8.8.dist-info → wolfhece-1.8.9.dist-info}/WHEEL +0 -0
- {wolfhece-1.8.8.dist-info → wolfhece-1.8.9.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,1951 @@
|
|
1
|
+
import os
|
2
|
+
from scipy.interpolate import interpolate
|
3
|
+
from scipy.spatial import KDTree
|
4
|
+
from matplotlib import figure as mplfig
|
5
|
+
from matplotlib.axes import Axes
|
6
|
+
import matplotlib.pyplot as plt
|
7
|
+
import logging
|
8
|
+
from tqdm import tqdm
|
9
|
+
|
10
|
+
from ..PyTranslate import _
|
11
|
+
from ..PyVertex import wolfvertex, cloud_vertices
|
12
|
+
from ..wolf_array import *
|
13
|
+
from ..PyCrosssections import crosssections as CrossSections
|
14
|
+
from ..GraphNotebook import PlotNotebook
|
15
|
+
from .read import *
|
16
|
+
|
17
|
+
LISTDEM=['dem_before_corr','dem_after_corr','dem_10m','dem_20m','crosssection']
|
18
|
+
#LISTDEM=['dem_after_corr']
|
19
|
+
|
20
|
+
class Node_Watershed:
|
21
|
+
"""Noeud du modèle hydrologique maillé"""
|
22
|
+
i:int #indice i dans la matrice
|
23
|
+
j:int #indice j dans la matrice
|
24
|
+
|
25
|
+
x:float # coordonnée X
|
26
|
+
y:float # coordonnée Y
|
27
|
+
|
28
|
+
index:int # Numérotation de la maille dans la liste de l'objet Watershed qui l'a initialisé
|
29
|
+
|
30
|
+
dem:dict[str,float] # dictionnaire des valeurs d'altitudes
|
31
|
+
demdelta:float # correction apportée dans la phase de prépro
|
32
|
+
|
33
|
+
crosssections:list # sections en travers sontenues dans la maille
|
34
|
+
|
35
|
+
time:float # temps de propagation - cf Drainage_basin.time
|
36
|
+
slope:float # pente calculée ne prépro
|
37
|
+
sloped8:float # pente selon les 8 voisins
|
38
|
+
|
39
|
+
slopecorr:dict # pente corrigée
|
40
|
+
demcorr:dict # dictionnaire d'alrtitude corrigées
|
41
|
+
|
42
|
+
river:bool # maille rivière => True
|
43
|
+
reach:int # index du bief
|
44
|
+
sub:int # inde du sous-bassin
|
45
|
+
forced:bool # maille d'échange forcé
|
46
|
+
uparea:float # surface drainée - cf Drainage_basin.cnv
|
47
|
+
|
48
|
+
strahler:int # indice de Strahler - cf "create_index"
|
49
|
+
reachlevel:int # Niveau du bief - cf "create_index"
|
50
|
+
|
51
|
+
cums:float # longueur curviligne cumulée **depuis l'aval** -- cf "incr_curvi"
|
52
|
+
incrs:float # incrément de longueur curvi - dx ou sqrt(2)*dx si voisin en crois ou en diagonale
|
53
|
+
|
54
|
+
down:"Node_Watershed" # pointeur vers le noeud aval
|
55
|
+
up:list["Node_Watershed"] # pointeurs vers le(s) noeud(s) amont
|
56
|
+
upriver:list["Node_Watershed"] # pointeurs vers le(s) noeud(s) **rivière** amont
|
57
|
+
|
58
|
+
flatindex:int = -1 # index de la zone de plat
|
59
|
+
|
60
|
+
def incr_curvi(self):
|
61
|
+
"""Incrémentation de la longueur curviligne"""
|
62
|
+
|
63
|
+
if self.down is None:
|
64
|
+
self.cums=0.
|
65
|
+
else:
|
66
|
+
self.cums = self.down.cums+self.incrs
|
67
|
+
|
68
|
+
for curup in self.up:
|
69
|
+
curup.incr_curvi()
|
70
|
+
|
71
|
+
def mean_slope_up(self, threshold:float)-> float:
|
72
|
+
"""Pente moyenne sur depuis les mailles amont"""
|
73
|
+
curnode: Node_Watershed
|
74
|
+
meanslope=0.
|
75
|
+
nbmean=0
|
76
|
+
for curnode in self.up:
|
77
|
+
if curnode.slope>threshold:
|
78
|
+
nbmean+=1.
|
79
|
+
meanslope+=curnode.slope
|
80
|
+
if nbmean>0:
|
81
|
+
meanslope=meanslope/nbmean
|
82
|
+
|
83
|
+
return meanslope
|
84
|
+
|
85
|
+
def slope_down(self, threshold:float)->float:
|
86
|
+
"""
|
87
|
+
Recherche d'une pente supérieure à un seuil
|
88
|
+
Parcours vers l'aval
|
89
|
+
"""
|
90
|
+
slopedown=0.
|
91
|
+
curnode=self
|
92
|
+
while curnode.slope < threshold:
|
93
|
+
if curnode.down is None:
|
94
|
+
break
|
95
|
+
curnode=curnode.down
|
96
|
+
|
97
|
+
slopedown = curnode.slope
|
98
|
+
return slopedown
|
99
|
+
|
100
|
+
def slope_upriver(self,threshold:float)->float:
|
101
|
+
"""
|
102
|
+
Recherche d'une pente supérieure à un seuil
|
103
|
+
Parcours vers l'amont uniquement selon les rivières
|
104
|
+
"""
|
105
|
+
slopeup=0.
|
106
|
+
if self.slope<threshold:
|
107
|
+
if len(self.upriver)>0:
|
108
|
+
slopeup=self.upriver[0].slope_upriver(threshold)
|
109
|
+
else:
|
110
|
+
slopeup=-1.
|
111
|
+
else:
|
112
|
+
slopeup = self.slope
|
113
|
+
|
114
|
+
return slopeup
|
115
|
+
|
116
|
+
def set_strahler(self, strahler:int):
|
117
|
+
"""
|
118
|
+
|
119
|
+
"""
|
120
|
+
self.strahler = strahler
|
121
|
+
|
122
|
+
|
123
|
+
class RiverSystem:
|
124
|
+
"""
|
125
|
+
Classe du réseau de rivières d'un modèle hydrologique WOLF
|
126
|
+
"""
|
127
|
+
nbreaches:int # nombre de biefs
|
128
|
+
|
129
|
+
# reaches
|
130
|
+
# |__['reaches']
|
131
|
+
# | |__[idx]
|
132
|
+
# | |__['upstream']
|
133
|
+
# | |__['baselist']
|
134
|
+
# |__['indexed']
|
135
|
+
# |__['strahler']
|
136
|
+
|
137
|
+
reaches:dict # dictionnaire des biefs
|
138
|
+
|
139
|
+
kdtree:KDTree # structure de recherche de voisinage
|
140
|
+
|
141
|
+
upmin:dict # cf slope_correctionmin
|
142
|
+
upmax:dict # cf slope_correctionmax
|
143
|
+
|
144
|
+
parent:"Watershed" # objet Watershed parent
|
145
|
+
upstreams:dict # dictionnaire des noeuds en amont
|
146
|
+
|
147
|
+
maxlevels:int # nombre total de niveaux
|
148
|
+
maxstrahler:int # indice de Strahler max
|
149
|
+
|
150
|
+
tslopemin:float =None # seuil de pente minimale
|
151
|
+
tslopemax:float =None # seuil de pente maximale
|
152
|
+
|
153
|
+
plotter:PlotNotebook = None # gestionnaire de graphiques
|
154
|
+
savedir:str # répertoire de sauvegarde
|
155
|
+
|
156
|
+
def __init__(self,
|
157
|
+
rivers:list[Node_Watershed],
|
158
|
+
parent:"Watershed",
|
159
|
+
thslopemin:float,
|
160
|
+
thslopemax:float,
|
161
|
+
savedir:str='',
|
162
|
+
computecorr:bool=False,
|
163
|
+
*args,
|
164
|
+
**kwargs):
|
165
|
+
|
166
|
+
self.savedir = savedir
|
167
|
+
self.parent = parent
|
168
|
+
|
169
|
+
self.all_nodes = rivers
|
170
|
+
|
171
|
+
self.init_kdtree(self.all_nodes)
|
172
|
+
|
173
|
+
self.nbreaches = max([x.reach for x in rivers])
|
174
|
+
self.reaches = {}
|
175
|
+
self.reaches['reaches'] = {}
|
176
|
+
|
177
|
+
self.upstreams = {}
|
178
|
+
self.upstreams['list'] = []
|
179
|
+
|
180
|
+
for curreach in range(1,self.nbreaches+1):
|
181
|
+
# attention numérotation 1-based
|
182
|
+
listreach, curup = parent.find_rivers(whichreach=curreach)
|
183
|
+
|
184
|
+
if len(curup.upriver) == 0:
|
185
|
+
# on est en tête de réseau
|
186
|
+
self.upstreams['list'].append(curup)
|
187
|
+
|
188
|
+
self.reaches['reaches'][curreach]={}
|
189
|
+
curdict=self.reaches['reaches'][curreach]
|
190
|
+
curdict['upstream']=curup
|
191
|
+
curdict['baselist']=listreach
|
192
|
+
|
193
|
+
self.create_index() # index et Strahler
|
194
|
+
|
195
|
+
if computecorr:
|
196
|
+
self.tslopemin=thslopemin
|
197
|
+
self.tslopemax=thslopemax
|
198
|
+
self.slope_correctionmin()
|
199
|
+
self.slope_correctionmax()
|
200
|
+
|
201
|
+
return super().__init__(*args, **kwargs)
|
202
|
+
|
203
|
+
def init_kdtree(self, nodes:list[Node_Watershed]):
|
204
|
+
"""Create a KDTree structure from coordinates"""
|
205
|
+
xy = [[curnode.x, curnode.y] for curnode in nodes]
|
206
|
+
self.kdtree = KDTree(xy)
|
207
|
+
|
208
|
+
def get_nearest_nodes(self, xy:np.ndarray, nb=int) -> tuple[np.ndarray, list[Node_Watershed]]:
|
209
|
+
"""
|
210
|
+
Return the distance and the nearest Node_Watershed
|
211
|
+
|
212
|
+
:param xy = np.ndarray - shape (n,2)
|
213
|
+
:param nb = number of neighbors
|
214
|
+
|
215
|
+
return
|
216
|
+
"""
|
217
|
+
dd, ii = self.kdtree.query(xy, nb)
|
218
|
+
|
219
|
+
return dd, [self.all_nodes[curi] for curi in ii]
|
220
|
+
|
221
|
+
def get_cums(self, whichreach:int=None, whichup:int=None):
|
222
|
+
"""
|
223
|
+
Récupération de la position curvi
|
224
|
+
"""
|
225
|
+
curnode:Node_Watershed
|
226
|
+
if whichreach is not None:
|
227
|
+
nodeslist=self.reaches['reaches'][whichreach]['baselist']
|
228
|
+
x=[curnode.cums for curnode in nodeslist]
|
229
|
+
elif whichup is not None:
|
230
|
+
x=[]
|
231
|
+
curnode=self.upstreams['list'][whichup]
|
232
|
+
while curnode is not None:
|
233
|
+
x.append(curnode.cums)
|
234
|
+
curnode=curnode.down
|
235
|
+
else:
|
236
|
+
x=[]
|
237
|
+
|
238
|
+
return x
|
239
|
+
|
240
|
+
def get_dem(self, whichdem:str, whichreach:int=None, whichup:int=None):
|
241
|
+
"""
|
242
|
+
Récupération de l'altitude pour une matrice spécifique
|
243
|
+
"""
|
244
|
+
if whichreach is not None:
|
245
|
+
nodeslist=self.reaches['reaches'][whichreach]['baselist']
|
246
|
+
dem=[curnode.dem[whichdem] for curnode in nodeslist]
|
247
|
+
elif whichup is not None:
|
248
|
+
curnode:Node_Watershed
|
249
|
+
dem=[]
|
250
|
+
curnode=self.upstreams['list'][whichup]
|
251
|
+
while curnode is not None:
|
252
|
+
dem.append(curnode.dem[whichdem])
|
253
|
+
curnode=curnode.down
|
254
|
+
return dem
|
255
|
+
|
256
|
+
def get_dem_corr(self, whichdem:str, whichreach:int=None, whichup:int=None):
|
257
|
+
"""
|
258
|
+
Récupération de l'altitude corrigée pour une matrice spécifique
|
259
|
+
"""
|
260
|
+
if whichreach is not None:
|
261
|
+
nodeslist=self.reaches['reaches'][whichreach]['baselist']
|
262
|
+
dem=[curnode.demcorr[whichdem] for curnode in nodeslist]
|
263
|
+
elif whichup is not None:
|
264
|
+
curnode:Node_Watershed
|
265
|
+
dem=[]
|
266
|
+
curnode=self.upstreams['list'][whichup]
|
267
|
+
while curnode is not None:
|
268
|
+
dem.append(curnode.dem[whichdem])
|
269
|
+
curnode=curnode.down
|
270
|
+
return dem
|
271
|
+
|
272
|
+
def get_slope(self, whichslope:str=None, whichreach:int=None, whichup:int=None):
|
273
|
+
"""
|
274
|
+
Récupération de la pente
|
275
|
+
"""
|
276
|
+
if whichslope is None:
|
277
|
+
if whichreach is not None:
|
278
|
+
nodeslist=self.reaches['reaches'][whichreach]['baselist']
|
279
|
+
slope=[curnode.slope for curnode in nodeslist]
|
280
|
+
elif whichup is not None:
|
281
|
+
curnode:Node_Watershed
|
282
|
+
slope=[]
|
283
|
+
curnode=self.upstreams['list'][whichup]
|
284
|
+
while curnode is not None:
|
285
|
+
slope.append(curnode.slope)
|
286
|
+
curnode=curnode.down
|
287
|
+
else:
|
288
|
+
if whichreach is not None:
|
289
|
+
nodeslist=self.reaches['reaches'][whichreach]['baselist']
|
290
|
+
slope=[curnode.slopecorr[whichslope]['value'] for curnode in nodeslist]
|
291
|
+
elif whichup is not None:
|
292
|
+
curnode:Node_Watershed
|
293
|
+
slope=[]
|
294
|
+
curnode=self.upstreams['list'][whichup]
|
295
|
+
while curnode is not None:
|
296
|
+
slope.append(curnode.slopecorr[whichslope]['value'])
|
297
|
+
curnode=curnode.down
|
298
|
+
|
299
|
+
return slope
|
300
|
+
|
301
|
+
def create_index(self):
|
302
|
+
"""
|
303
|
+
Incrément d'index depuis l'amont jusque l'exutoire final
|
304
|
+
Parcours des mailles rivières depuis tous les amonts et Incrémentation d'une unité
|
305
|
+
Résultat :
|
306
|
+
- tous les biefs en amont sont à 1
|
307
|
+
- Les autres biefs contiennent le nombre de biefs en amont
|
308
|
+
|
309
|
+
Indice de Strahler
|
310
|
+
"""
|
311
|
+
for curup in self.upstreams['list']:
|
312
|
+
curnode:Node_Watershed
|
313
|
+
curnode=curup
|
314
|
+
while not curnode is None:
|
315
|
+
curnode.reachlevel +=1
|
316
|
+
curnode=curnode.down
|
317
|
+
|
318
|
+
#recherche de l'index max --> à l'exutoire
|
319
|
+
self.maxlevels = self.parent.outlet.reachlevel
|
320
|
+
self.maxstrahler=0
|
321
|
+
self.reaches['indexed']={}
|
322
|
+
for i in range(1,self.maxlevels+1):
|
323
|
+
self.reaches['indexed'][i]=[]
|
324
|
+
|
325
|
+
#création de listes pour chaque niveau
|
326
|
+
for curreach in self.reaches['reaches']:
|
327
|
+
curdict=self.reaches['reaches'][curreach]
|
328
|
+
listreach=curdict['baselist']
|
329
|
+
curlevel=listreach[0].reachlevel
|
330
|
+
self.reaches['indexed'][curlevel].append(curreach)
|
331
|
+
|
332
|
+
#création de listes pour chaque amont
|
333
|
+
# on parcourt toutes les mailles depuis chaque amont et on ajoute les index de biefs qui sont différents
|
334
|
+
for idx,curup in enumerate(self.upstreams['list']):
|
335
|
+
curdict=self.upstreams[idx]={}
|
336
|
+
curdict['up']=curup
|
337
|
+
curdict['fromuptodown']=[]
|
338
|
+
curdict['fromuptodown'].append(curup.reach)
|
339
|
+
curnode=curup.down
|
340
|
+
while not curnode is None:
|
341
|
+
if curnode.reach!=curdict['fromuptodown'][-1]:
|
342
|
+
curdict['fromuptodown'].append(curnode.reach)
|
343
|
+
curnode=curnode.down
|
344
|
+
|
345
|
+
#création de l'indice de Strahler
|
346
|
+
self.reaches['strahler']={}
|
347
|
+
#on commence par ajouter les biefs de 1er niveau qui sont à coup sûr d'indice 1
|
348
|
+
self.reaches['strahler'][1]=self.reaches['indexed'][1]
|
349
|
+
for curreach in self.reaches['strahler'][1]:
|
350
|
+
self.set_strahler_in_nodes(curreach,1)
|
351
|
+
|
352
|
+
#on parcourt les différents niveaux
|
353
|
+
for i in range(2,self.maxlevels+1):
|
354
|
+
listlevel=self.reaches['indexed'][i]
|
355
|
+
for curreach in listlevel:
|
356
|
+
curup:Node_Watershed
|
357
|
+
curup=self.reaches['reaches'][curreach]['upstream']
|
358
|
+
upidx=list(x.strahler for x in curup.upriver)
|
359
|
+
sameidx=upidx[0]==upidx[-1]
|
360
|
+
maxidx=max(upidx)
|
361
|
+
|
362
|
+
curidx=maxidx
|
363
|
+
if sameidx:
|
364
|
+
curidx+=1
|
365
|
+
if not curidx in self.reaches['strahler'].keys():
|
366
|
+
#création de la liste du niveau supérieur
|
367
|
+
self.reaches['strahler'][curidx]=[]
|
368
|
+
self.maxstrahler=curidx
|
369
|
+
|
370
|
+
self.reaches['strahler'][curidx].append(curreach)
|
371
|
+
self.set_strahler_in_nodes(curreach,curidx)
|
372
|
+
|
373
|
+
|
374
|
+
myarray=WolfArray(mold=self.parent.subs_array)
|
375
|
+
myarray.reset()
|
376
|
+
curnode:Node_Watershed
|
377
|
+
for curreach in self.reaches['reaches']:
|
378
|
+
curdict=self.reaches['reaches'][curreach]
|
379
|
+
listreach=curdict['baselist']
|
380
|
+
for curnode in listreach:
|
381
|
+
i=curnode.i
|
382
|
+
j=curnode.j
|
383
|
+
myarray.array[i,j]=curnode.strahler
|
384
|
+
myarray.filename = self.parent.dir+'\\Characteristic_maps\\Drainage_basin.strahler'
|
385
|
+
myarray.write_all()
|
386
|
+
myarray.reset()
|
387
|
+
for curreach in self.reaches['reaches']:
|
388
|
+
curdict=self.reaches['reaches'][curreach]
|
389
|
+
listreach=curdict['baselist']
|
390
|
+
for curnode in listreach:
|
391
|
+
i=curnode.i
|
392
|
+
j=curnode.j
|
393
|
+
myarray.array[i,j]=curnode.reachlevel
|
394
|
+
myarray.filename = self.parent.dir+'\\Characteristic_maps\\Drainage_basin.reachlevel'
|
395
|
+
myarray.write_all()
|
396
|
+
|
397
|
+
def set_strahler_in_nodes(self, whichreach:int, strahler:int):
|
398
|
+
"""
|
399
|
+
Mise à jour de la propriété dans chaque noeud du bief
|
400
|
+
"""
|
401
|
+
listnodes = self.reaches['reaches'][whichreach]['baselist']
|
402
|
+
|
403
|
+
curnode:Node_Watershed
|
404
|
+
for curnode in listnodes:
|
405
|
+
curnode.set_strahler(strahler)
|
406
|
+
|
407
|
+
def plot_dem(self, which:int=-1):
|
408
|
+
"""
|
409
|
+
Graphiques
|
410
|
+
"""
|
411
|
+
mymarkers=['x','+','1','2','3','4']
|
412
|
+
if which==-1:
|
413
|
+
fig=self.plotter.add('All Reaches')
|
414
|
+
|
415
|
+
ax=fig.add_ax()
|
416
|
+
|
417
|
+
for curreach in self.reaches['reaches']:
|
418
|
+
x=np.array(self.get_cums(whichreach=curreach))
|
419
|
+
for idx,curdem in enumerate(LISTDEM):
|
420
|
+
y=np.array(self.get_dem(curdem,whichreach=curreach))
|
421
|
+
|
422
|
+
xmask=np.ma.masked_where(y==99999.,x)
|
423
|
+
ymask=np.ma.masked_where(y==99999.,y)
|
424
|
+
|
425
|
+
ax.scatter(xmask,ymask,marker=mymarkers[idx],label=curdem)
|
426
|
+
ax.legend()
|
427
|
+
fig.canvas.draw()
|
428
|
+
|
429
|
+
elif which==-99:
|
430
|
+
size=int(np.ceil(np.sqrt(self.nbreaches)))
|
431
|
+
|
432
|
+
fig=self.plotter.add('reaches')
|
433
|
+
|
434
|
+
for index,curreach in enumerate(self.reaches['reaches']):
|
435
|
+
#curax=ax[int(np.floor(index/size)),int(np.mod(index,size))]
|
436
|
+
curax=fig.add_ax()
|
437
|
+
|
438
|
+
curdict=self.reaches['reaches'][curreach]
|
439
|
+
x=np.array(self.get_cums(whichreach=curreach))
|
440
|
+
|
441
|
+
for idx,curdem in enumerate(LISTDEM):
|
442
|
+
y=np.array(self.get_dem(curdem,whichreach=curreach))
|
443
|
+
|
444
|
+
xmask=np.ma.masked_where(y==99999.,x)
|
445
|
+
ymask=np.ma.masked_where(y==99999.,y)
|
446
|
+
|
447
|
+
curax.scatter(xmask,ymask,marker=mymarkers[idx],label=curdem)
|
448
|
+
curax.legend()
|
449
|
+
fig.canvas.draw()
|
450
|
+
|
451
|
+
elif which==-98:
|
452
|
+
size=int(np.ceil(np.sqrt(len(self.upstreams['list']))))
|
453
|
+
|
454
|
+
fig=self.plotter.add('reaches')
|
455
|
+
|
456
|
+
for idxup,curup in enumerate(self.upstreams['list']):
|
457
|
+
curax=fig.add_ax()
|
458
|
+
|
459
|
+
x=np.array(self.get_cums(whichup=idxup))
|
460
|
+
|
461
|
+
for idx,curdem in enumerate(LISTDEM):
|
462
|
+
y=np.array(self.get_dem(curdem,whichup=idxup))
|
463
|
+
|
464
|
+
xmask=np.ma.masked_where(y==99999.,x)
|
465
|
+
ymask=np.ma.masked_where(y==99999.,y)
|
466
|
+
curax.scatter(xmask,ymask,marker=mymarkers[idx],label=curdem)
|
467
|
+
|
468
|
+
curax.legend()
|
469
|
+
fig.canvas.draw()
|
470
|
+
|
471
|
+
elif which>-1:
|
472
|
+
if which<len(self.upstreams['list']):
|
473
|
+
if not self.plotter is None:
|
474
|
+
fig=self.plotter.add('Upstream n°'+str(which))
|
475
|
+
else:
|
476
|
+
fig=plt.figure()
|
477
|
+
|
478
|
+
ax=fig.add_ax()
|
479
|
+
|
480
|
+
x=np.array(self.get_cums(whichup=which))
|
481
|
+
for idx,curdem in enumerate(LISTDEM):
|
482
|
+
y=np.array(self.get_dem(curdem,whichup=which))
|
483
|
+
|
484
|
+
xmask=np.ma.masked_where(y==99999.,x)
|
485
|
+
ymask=np.ma.masked_where(y==99999.,y)
|
486
|
+
ax.scatter(xmask,ymask,marker=mymarkers[idx],label=curdem)
|
487
|
+
|
488
|
+
ax.legend()
|
489
|
+
fig.canvas.draw()
|
490
|
+
|
491
|
+
def plot_dem_and_corr(self, which:int=-1, whichdem:str='dem_after_corr'):
|
492
|
+
"""
|
493
|
+
Graphiques
|
494
|
+
"""
|
495
|
+
|
496
|
+
if which<len(self.upstreams['list']):
|
497
|
+
if not self.plotter is None:
|
498
|
+
fig=self.plotter.add('Upstream n°'+str(which))
|
499
|
+
else:
|
500
|
+
fig=plt.figure()
|
501
|
+
fig.suptitle('Upstream n°'+str(which))
|
502
|
+
|
503
|
+
ax=fig.add_ax()
|
504
|
+
|
505
|
+
x=np.array(self.get_cums(whichup=which))
|
506
|
+
y=np.array(self.get_dem(whichdem,whichup=which))
|
507
|
+
|
508
|
+
xcorr=self.upmin[which][whichdem][0]
|
509
|
+
ycorr=self.upmin[which][whichdem][1]
|
510
|
+
|
511
|
+
xmask=np.ma.masked_where(y==99999.,x)
|
512
|
+
ymask=np.ma.masked_where(y==99999.,y)
|
513
|
+
|
514
|
+
ax.scatter(xmask,ymask,marker='x',label=whichdem)
|
515
|
+
ax.scatter(xcorr,ycorr,marker='+',label='selected points')
|
516
|
+
|
517
|
+
ax.legend()
|
518
|
+
fig.canvas.draw()
|
519
|
+
|
520
|
+
if not self.savedir=='':
|
521
|
+
plt.savefig(self.savedir+'\\Up'+str(which)+'_'+whichdem+'.png')
|
522
|
+
|
523
|
+
def plot_slope(self, which:int=-1):
|
524
|
+
"""
|
525
|
+
Graphiques
|
526
|
+
"""
|
527
|
+
mymarkers=['x','+','1','2','3','4']
|
528
|
+
if which==-1:
|
529
|
+
fig=self.plotter.add('reaches')
|
530
|
+
ax=fig.add_ax()
|
531
|
+
|
532
|
+
for curreach in self.reaches['reaches']:
|
533
|
+
x=self.get_cums(whichreach=curreach)
|
534
|
+
for idx,curdem in enumerate(LISTDEM):
|
535
|
+
y=self.get_slope(curdem,whichreach=curreach)
|
536
|
+
ax.scatter(x,y,marker=mymarkers[idx],label=curdem)
|
537
|
+
fig.canvas.draw()
|
538
|
+
|
539
|
+
elif which==-99:
|
540
|
+
size=int(np.ceil(np.sqrt(self.nbreaches)))
|
541
|
+
fig=self.plotter.add('reaches')
|
542
|
+
|
543
|
+
for index,curreach in enumerate(self.reaches['reaches']):
|
544
|
+
curax=fig.add_ax()
|
545
|
+
|
546
|
+
x=self.get_cums(whichreach=curreach)
|
547
|
+
|
548
|
+
for idx,curdem in enumerate(LISTDEM):
|
549
|
+
y=self.get_slope(curdem,whichreach=curreach)
|
550
|
+
curax.scatter(x,y,marker=mymarkers[idx],label=curdem)
|
551
|
+
curax.legend()
|
552
|
+
fig.canvas.draw()
|
553
|
+
|
554
|
+
elif which==-98:
|
555
|
+
size=int(np.ceil(np.sqrt(len(self.upstreams['list']))))
|
556
|
+
|
557
|
+
fig=self.plotter.add('reaches')
|
558
|
+
|
559
|
+
for idxup,curup in enumerate(self.upstreams['list']):
|
560
|
+
curax=fig.add_ax()
|
561
|
+
x=self.get_cums(whichup=idxup)
|
562
|
+
|
563
|
+
for idx,curdem in enumerate(LISTDEM):
|
564
|
+
y=self.get_slope(curdem,whichup=idxup)
|
565
|
+
curax.scatter(x,y,marker=mymarkers[idx],label=curdem)
|
566
|
+
curax.legend()
|
567
|
+
fig.canvas.draw()
|
568
|
+
|
569
|
+
def write_slopes(self):
|
570
|
+
"""
|
571
|
+
Ecriture sur disque
|
572
|
+
"""
|
573
|
+
#Uniquement les pentes rivières
|
574
|
+
for curlist in LISTDEM:
|
575
|
+
slopes= WolfArray(self.parent.dir+'\\Characteristic_maps\\Drainage_basin.slope')
|
576
|
+
slopes.reset()
|
577
|
+
for curreach in self.reaches['reaches']:
|
578
|
+
curdict=self.reaches['reaches'][curreach]
|
579
|
+
listreach=curdict['baselist']
|
580
|
+
|
581
|
+
curnode:Node_Watershed
|
582
|
+
ijval = np.asarray([[curnode.i, curnode.j, curnode.slopecorr[curlist]['value']] for curnode in listreach])
|
583
|
+
slopes.array[np.int32(ijval[:,0]),np.int32(ijval[:,1])]=ijval[:,2]
|
584
|
+
|
585
|
+
slopes.filename = self.parent.dir+'\\Characteristic_maps\\Drainage_basin.slope_corr_riv_'+curlist
|
586
|
+
slopes.write_all()
|
587
|
+
|
588
|
+
def slope_correctionmin(self):
|
589
|
+
"""
|
590
|
+
Correction pente minimale
|
591
|
+
"""
|
592
|
+
if self.tslopemin is not None:
|
593
|
+
logging.info(_('select min - river'))
|
594
|
+
self.selectmin()
|
595
|
+
logging.info(_('slope correction min - river'))
|
596
|
+
self.compute_slopescorr(self.upmin)
|
597
|
+
|
598
|
+
def slope_correctionmax(self):
|
599
|
+
"""
|
600
|
+
Correction pente maximale
|
601
|
+
"""
|
602
|
+
if self.tslopemax is not None:
|
603
|
+
logging.info(_('select max - river'))
|
604
|
+
self.selectmax()
|
605
|
+
logging.info(_('slope correction max - river'))
|
606
|
+
self.compute_slopescorr(self.upmax)
|
607
|
+
|
608
|
+
def selectmin(self):
|
609
|
+
"""
|
610
|
+
Sélection des valeurs minimales afin de conserver une topo décroissante vers l'aval --> une pente positive
|
611
|
+
"""
|
612
|
+
self.upmin={}
|
613
|
+
|
614
|
+
#on initialise le dictionnaire de topo min pour chaque amont
|
615
|
+
for idx,curup in enumerate(self.upstreams['list']):
|
616
|
+
self.upmin[idx]={}
|
617
|
+
|
618
|
+
curnode:Node_Watershed
|
619
|
+
for curdem in LISTDEM:
|
620
|
+
logging.info(_('Current DEM : {}'.format(curdem)))
|
621
|
+
for idx,curup in enumerate(self.upstreams['list']):
|
622
|
+
#on part de l'amont
|
623
|
+
curnode=curup
|
624
|
+
x=[]
|
625
|
+
y=[]
|
626
|
+
|
627
|
+
x.append(curnode.cums)
|
628
|
+
|
629
|
+
if curdem=='crosssection':
|
630
|
+
basey=min(curnode.dem[curdem],curnode.dem['dem_after_corr'])
|
631
|
+
else:
|
632
|
+
basey=curnode.dem[curdem]
|
633
|
+
|
634
|
+
y.append(basey)
|
635
|
+
curnode=curnode.down
|
636
|
+
|
637
|
+
locs= self.parent.resolution
|
638
|
+
while not curnode is None:
|
639
|
+
if curdem=='crosssection':
|
640
|
+
yloc=min(curnode.dem[curdem],curnode.dem['dem_after_corr'])
|
641
|
+
else:
|
642
|
+
yloc=curnode.dem[curdem]
|
643
|
+
|
644
|
+
#on ajoute la maille si la pente est suffisante, sinon cekla créera un trou dans le parcours
|
645
|
+
if (basey-yloc)/locs>self.tslopemin:
|
646
|
+
x.append(curnode.cums)
|
647
|
+
y.append(yloc)
|
648
|
+
basey=yloc
|
649
|
+
locs= self.parent.resolution
|
650
|
+
else:
|
651
|
+
locs+= self.parent.resolution
|
652
|
+
|
653
|
+
#if curnode.i==232 and curnode.j==226:
|
654
|
+
# a=1
|
655
|
+
|
656
|
+
curnode=curnode.down
|
657
|
+
|
658
|
+
#on stocke les vecteurs de coordonnées curvi et d'altitudes pour les zones respectant les critères
|
659
|
+
self.upmin[idx][curdem]=[x,y]
|
660
|
+
|
661
|
+
def selectmax(self):
|
662
|
+
"""
|
663
|
+
Sélection des valeurs maximales afin de conserver une topo décroissante vers l'aval --> une pente positive
|
664
|
+
"""
|
665
|
+
# on travaille sur base de la topo corrigée min
|
666
|
+
self.upmax={}
|
667
|
+
|
668
|
+
#on initialise le dictionnaire de topo max pour chaque amont
|
669
|
+
for idx,curup in enumerate(self.upstreams['list']):
|
670
|
+
self.upmax[idx]={}
|
671
|
+
|
672
|
+
ds=self.parent.resolution
|
673
|
+
curnode:Node_Watershed
|
674
|
+
for curdem in LISTDEM:
|
675
|
+
logging.info(_('Current DEM : {}'.format(curdem)))
|
676
|
+
for idx,curup in enumerate(self.upstreams['list']):
|
677
|
+
curnode=curup
|
678
|
+
x=[]
|
679
|
+
y=[]
|
680
|
+
|
681
|
+
basey=curnode.demcorr[curdem]['value']
|
682
|
+
|
683
|
+
x.append(curnode.cums)
|
684
|
+
y.append(basey)
|
685
|
+
curnode=curnode.down
|
686
|
+
|
687
|
+
locs= ds
|
688
|
+
while not curnode is None:
|
689
|
+
yloc=curnode.demcorr[curdem]['value']
|
690
|
+
|
691
|
+
if (basey-yloc)/locs>self.tslopemax:
|
692
|
+
while len(x)>1 and (basey-yloc)/locs>self.tslopemax:
|
693
|
+
x.pop()
|
694
|
+
y.pop()
|
695
|
+
basey=y[-1]
|
696
|
+
locs+=ds
|
697
|
+
|
698
|
+
if yloc<y[-1]:
|
699
|
+
x.append(curnode.cums)
|
700
|
+
y.append(yloc)
|
701
|
+
basey=yloc
|
702
|
+
locs=ds
|
703
|
+
|
704
|
+
curnode=curnode.down
|
705
|
+
|
706
|
+
self.upmax[idx][curdem]=[x,y]
|
707
|
+
|
708
|
+
def compute_slopescorr(self, whichdict:dict):
|
709
|
+
"""
|
710
|
+
Calcul des pents corrigées
|
711
|
+
"""
|
712
|
+
curnode:Node_Watershed
|
713
|
+
for curdem in LISTDEM:
|
714
|
+
logging.info(_('Current DEM : {}'.format(curdem)))
|
715
|
+
for idx,curup in enumerate(self.upstreams['list']):
|
716
|
+
curdict=whichdict[idx][curdem]
|
717
|
+
xmin=curdict[0]
|
718
|
+
if len(xmin)>1:
|
719
|
+
ymin=curdict[1]
|
720
|
+
x=self.get_cums(whichup=idx)
|
721
|
+
|
722
|
+
#on cale une fonction d'interpolation sur la sélection dans lequalle on a oublié les pentes faibles --> à trou
|
723
|
+
f=interpolate.interp1d(xmin,ymin, fill_value='extrapolate')
|
724
|
+
#on interpole sur tous les x --> on remplit les trous
|
725
|
+
y=f(x)
|
726
|
+
#calcul des pentes sur base des noeuds aval
|
727
|
+
slopes=self.compute_slope_down(x,y)
|
728
|
+
|
729
|
+
#on remplit le dictionnaire de résultat
|
730
|
+
curnode=curup
|
731
|
+
i=0
|
732
|
+
while not curnode is None:
|
733
|
+
#if curnode.i==232 and curnode.j==226:
|
734
|
+
# a=1
|
735
|
+
curnode.demcorr[curdem]['parts'].append(y[i])
|
736
|
+
curnode.slopecorr[curdem]['parts'].append(slopes[i])
|
737
|
+
i+=1
|
738
|
+
curnode=curnode.down
|
739
|
+
|
740
|
+
#calcul de la moyenne sur base des valeurs partielles
|
741
|
+
for curdem in LISTDEM:
|
742
|
+
for curreach in self.reaches['reaches']:
|
743
|
+
nodeslist=self.reaches['reaches'][curreach]['baselist']
|
744
|
+
for curnode in nodeslist:
|
745
|
+
#if curnode.i==232 and curnode.j==226:
|
746
|
+
# a=1
|
747
|
+
if len(nodeslist)<2:
|
748
|
+
if not self.tslopemin is None:
|
749
|
+
curnode.slopecorr[curdem]['value']=max(self.tslopemin,curnode.slope)
|
750
|
+
else:
|
751
|
+
curnode.slopecorr[curdem]['value']=self.tslopemin=1.e-4
|
752
|
+
|
753
|
+
if not self.tslopemax is None:
|
754
|
+
curnode.slopecorr[curdem]['value']=min(self.tslopemax,curnode.slope)
|
755
|
+
else:
|
756
|
+
curnode.demcorr[curdem]['value']=np.mean(curnode.demcorr[curdem]['parts'])
|
757
|
+
curnode.slopecorr[curdem]['value']=np.mean(curnode.slopecorr[curdem]['parts'])
|
758
|
+
|
759
|
+
#on vide les parts
|
760
|
+
curnode.demcorr[curdem]['parts']=[]
|
761
|
+
curnode.slopecorr[curdem]['parts']=[]
|
762
|
+
|
763
|
+
def compute_slope_down(self, x, y):
|
764
|
+
"""
|
765
|
+
Calcul de pente sur base de x et y
|
766
|
+
"""
|
767
|
+
slope=[]
|
768
|
+
for i in range(len(x)-1):
|
769
|
+
slope.append((y[i+1]-y[i])/(x[i+1]-x[i]))
|
770
|
+
slope.append(slope[-1])
|
771
|
+
return slope
|
772
|
+
|
773
|
+
def plot_all_in_notebook(self):
|
774
|
+
"""
|
775
|
+
Graphiques
|
776
|
+
"""
|
777
|
+
self.plotter = PlotNotebook()
|
778
|
+
|
779
|
+
for i in range(self.nbreaches):
|
780
|
+
self.plot_dem_and_corr(i,whichdem='crosssection')
|
781
|
+
self.plot_dem()
|
782
|
+
self.plot_slope(-98)
|
783
|
+
self.plot_dem(-98)
|
784
|
+
|
785
|
+
class RunoffSystem:
|
786
|
+
"""Classe de l'ensemble des mailles de ruissellement d'un modèle hydrologique WOLF"""
|
787
|
+
nodes:list[Node_Watershed] # liste de noeuds
|
788
|
+
|
789
|
+
parent:"Watershed"
|
790
|
+
upstreams:dict
|
791
|
+
|
792
|
+
tslopemin:float
|
793
|
+
tslopemax:float
|
794
|
+
|
795
|
+
upmin:dict
|
796
|
+
upmax:dict
|
797
|
+
|
798
|
+
def __init__(self,
|
799
|
+
runoff:list[Node_Watershed],
|
800
|
+
parent:"Watershed",
|
801
|
+
thslopemin:float = None,
|
802
|
+
thslopemax:float = None,
|
803
|
+
computecorr:bool=False,
|
804
|
+
*args,
|
805
|
+
**kwargs):
|
806
|
+
|
807
|
+
self.parent = parent
|
808
|
+
self.nodes = runoff
|
809
|
+
self.upstreams={}
|
810
|
+
|
811
|
+
#sélection des mailles qui ont une surface unitaire comme surface drainée
|
812
|
+
areaup = pow(parent.resolution,2)/1.e6
|
813
|
+
self.upstreams['list']=list(filter(lambda x: (x.uparea-areaup)<1.e-6 ,runoff))
|
814
|
+
|
815
|
+
if computecorr:
|
816
|
+
self.tslopemin = thslopemin
|
817
|
+
self.tslopemax = thslopemax
|
818
|
+
|
819
|
+
self.slope_correctionmin()
|
820
|
+
self.slope_correctionmax()
|
821
|
+
|
822
|
+
return super().__init__(*args, **kwargs)
|
823
|
+
|
824
|
+
def get_oneup(self, idx:int) -> Node_Watershed:
|
825
|
+
"""
|
826
|
+
Récupération d'un amont sur base de l'index
|
827
|
+
"""
|
828
|
+
return self.upstreams['list'][idx]
|
829
|
+
|
830
|
+
def get_cums(self,whichup:int=None):
|
831
|
+
|
832
|
+
if not whichup is None:
|
833
|
+
curnode:Node_Watershed
|
834
|
+
x=[]
|
835
|
+
curnode=self.get_oneup(whichup)
|
836
|
+
while not curnode.river:
|
837
|
+
x.append(curnode.cums)
|
838
|
+
curnode=curnode.down
|
839
|
+
if len(x)==1:
|
840
|
+
x.append(curnode.cums)
|
841
|
+
else:
|
842
|
+
x=[]
|
843
|
+
|
844
|
+
return x
|
845
|
+
|
846
|
+
def get_dem(self, whichdem:str, whichup:int=None):
|
847
|
+
if not whichdem in LISTDEM:
|
848
|
+
return
|
849
|
+
|
850
|
+
if not whichup is None:
|
851
|
+
curnode:Node_Watershed
|
852
|
+
dem=[]
|
853
|
+
curnode=self.get_oneup(whichup)
|
854
|
+
while not curnode.river:
|
855
|
+
dem.append(curnode.dem[whichdem])
|
856
|
+
curnode=curnode.down
|
857
|
+
return dem
|
858
|
+
|
859
|
+
def get_dem_corr(self, whichdem:str, whichup:int=None):
|
860
|
+
if not whichdem in LISTDEM:
|
861
|
+
return
|
862
|
+
|
863
|
+
if not whichup is None:
|
864
|
+
curnode:Node_Watershed
|
865
|
+
dem=[]
|
866
|
+
curnode=self.get_oneup(whichup)
|
867
|
+
while not curnode.river:
|
868
|
+
dem.append(curnode.dem[whichdem])
|
869
|
+
curnode=curnode.down
|
870
|
+
return dem
|
871
|
+
|
872
|
+
def get_slope(self, whichslope:str=None, whichup:int=None):
|
873
|
+
|
874
|
+
if whichslope is None:
|
875
|
+
if not whichup is None:
|
876
|
+
curnode:Node_Watershed
|
877
|
+
slope=[]
|
878
|
+
curnode=self.get_oneup(whichup)
|
879
|
+
while not curnode.river:
|
880
|
+
slope.append(curnode.slope)
|
881
|
+
curnode=curnode.down
|
882
|
+
else:
|
883
|
+
if not whichup is None:
|
884
|
+
curnode:Node_Watershed
|
885
|
+
slope=[]
|
886
|
+
curnode=self.get_oneup(whichup)
|
887
|
+
while not curnode.river:
|
888
|
+
slope.append(curnode.slopecorr[whichslope]['value'])
|
889
|
+
curnode=curnode.down
|
890
|
+
|
891
|
+
return slope
|
892
|
+
|
893
|
+
def plot_dem(self, which:int=-1):
|
894
|
+
|
895
|
+
mymarkers=['x','+','1','2','3','4']
|
896
|
+
if which>-1:
|
897
|
+
if which<len(self.upstreams['list']):
|
898
|
+
fig=plt.figure()
|
899
|
+
fig.suptitle('Upstream n°'+str(which))
|
900
|
+
|
901
|
+
x=np.array(self.get_cums(whichup=which))
|
902
|
+
for idx,curdem in enumerate(LISTDEM):
|
903
|
+
y=np.array(self.get_dem(curdem,whichup=which))
|
904
|
+
|
905
|
+
xmask=np.ma.masked_where(y==99999.,x)
|
906
|
+
ymask=np.ma.masked_where(y==99999.,y)
|
907
|
+
plt.scatter(xmask,ymask,marker=mymarkers[idx],label=curdem)
|
908
|
+
|
909
|
+
plt.legend()
|
910
|
+
plt.show()
|
911
|
+
|
912
|
+
def plot_dem_and_corr(self, which:int=-1, whichdem:str='dem_after_corr'):
|
913
|
+
|
914
|
+
if which<len(self.upstreams['list']):
|
915
|
+
fig=plt.figure()
|
916
|
+
fig.suptitle('Upstream n°'+str(which))
|
917
|
+
|
918
|
+
x=np.array(self.get_cums(whichup=which))
|
919
|
+
y=np.array(self.get_dem(whichdem,whichup=which))
|
920
|
+
|
921
|
+
xcorr=self.upmin[which][whichdem][0]
|
922
|
+
ycorr=self.upmin[which][whichdem][1]
|
923
|
+
|
924
|
+
xmask=np.ma.masked_where(y==99999.,x)
|
925
|
+
ymask=np.ma.masked_where(y==99999.,y)
|
926
|
+
|
927
|
+
plt.scatter(xmask,ymask,marker='x',label=whichdem)
|
928
|
+
plt.scatter(xcorr,ycorr,marker='+',label='selected points')
|
929
|
+
|
930
|
+
plt.legend()
|
931
|
+
plt.savefig(r'D:\OneDrive\OneDrive - Universite de Liege\Crues\2021-07 Vesdre\Simulations\Hydrologie\Up'+str(which)+'_'+whichdem+'.png')
|
932
|
+
#plt.show()
|
933
|
+
|
934
|
+
def write_slopes(self):
|
935
|
+
#Uniquement les pentes runoff
|
936
|
+
for curlist in LISTDEM:
|
937
|
+
slopes= WolfArray(self.parent.dir+'\\Characteristic_maps\\Drainage_basin.slope')
|
938
|
+
slopes.reset()
|
939
|
+
curnode:Node_Watershed
|
940
|
+
for curnode in self.nodes:
|
941
|
+
i=curnode.i
|
942
|
+
j=curnode.j
|
943
|
+
slopes.array[i,j]=curnode.slopecorr[curlist]['value']
|
944
|
+
|
945
|
+
slopes.filename = self.parent.dir+'\\Characteristic_maps\\Drainage_basin.slope_corr_run_'+curlist
|
946
|
+
slopes.write_all()
|
947
|
+
|
948
|
+
def slope_correctionmin(self):
|
949
|
+
if not self.tslopemin is None:
|
950
|
+
logging.info(_('select min - runoff'))
|
951
|
+
self.selectmin()
|
952
|
+
logging.info(_('slope correction min - runoff'))
|
953
|
+
self.compute_slopescorr(self.upmin)
|
954
|
+
|
955
|
+
def slope_correctionmax(self):
|
956
|
+
if not self.tslopemax is None:
|
957
|
+
logging.info(_('select max - runoff'))
|
958
|
+
self.selectmax()
|
959
|
+
logging.info(_('slope correction max - runoff'))
|
960
|
+
self.compute_slopescorr(self.upmax)
|
961
|
+
|
962
|
+
def selectmin(self):
|
963
|
+
#Sélection des valeurs minimales afin de conserver une topo décroissante vers l'aval --> une pente positive
|
964
|
+
self.upmin={}
|
965
|
+
|
966
|
+
#on initialise le dictionnaire de topo min pour chaque amont
|
967
|
+
for idx,curup in enumerate(self.upstreams['list']):
|
968
|
+
self.upmin[idx]={}
|
969
|
+
|
970
|
+
ds=self.parent.resolution
|
971
|
+
curnode:Node_Watershed
|
972
|
+
for curdem in LISTDEM:
|
973
|
+
logging.info(_('Current DEM : {}'.format(curdem)))
|
974
|
+
for idx,curup in enumerate(self.upstreams['list']):
|
975
|
+
curnode=curup
|
976
|
+
x=[]
|
977
|
+
y=[]
|
978
|
+
|
979
|
+
if curdem=='crosssection':
|
980
|
+
basey=min(curnode.dem[curdem],curnode.dem['dem_after_corr'])
|
981
|
+
else:
|
982
|
+
basey=curnode.dem[curdem]
|
983
|
+
|
984
|
+
x.append(curnode.cums)
|
985
|
+
y.append(basey)
|
986
|
+
curnode=curnode.down
|
987
|
+
|
988
|
+
locs=ds
|
989
|
+
while not curnode is None:
|
990
|
+
if curdem=='crosssection':
|
991
|
+
yloc=min(curnode.dem[curdem],curnode.dem['dem_after_corr'])
|
992
|
+
else:
|
993
|
+
yloc=curnode.dem[curdem]
|
994
|
+
|
995
|
+
if (basey-yloc)/locs>self.tslopemin:
|
996
|
+
x.append(curnode.cums)
|
997
|
+
y.append(yloc)
|
998
|
+
basey=yloc
|
999
|
+
locs=ds
|
1000
|
+
if curnode.river:
|
1001
|
+
break
|
1002
|
+
else:
|
1003
|
+
locs+=ds
|
1004
|
+
curnode=curnode.down
|
1005
|
+
|
1006
|
+
self.upmin[idx][curdem]=[x,y]
|
1007
|
+
|
1008
|
+
def selectmax(self):
|
1009
|
+
#Sélection des valeurs minimales afin de conserver une topo décroissante vers l'aval --> une pente positive
|
1010
|
+
self.upmax={}
|
1011
|
+
|
1012
|
+
#on initialise le dictionnaire de topo min pour chaque amont
|
1013
|
+
for idx,curup in enumerate(self.upstreams['list']):
|
1014
|
+
self.upmax[idx]={}
|
1015
|
+
|
1016
|
+
ds=self.parent.resolution
|
1017
|
+
curnode:Node_Watershed
|
1018
|
+
for curdem in LISTDEM:
|
1019
|
+
logging.info(_('Current DEM : {}'.format(curdem)))
|
1020
|
+
for idx,curup in enumerate(self.upstreams['list']):
|
1021
|
+
curnode=curup
|
1022
|
+
x=[]
|
1023
|
+
y=[]
|
1024
|
+
|
1025
|
+
"""
|
1026
|
+
if curdem=='crosssection':
|
1027
|
+
basey=min(curnode.demcorr[curdem]['value'],curnode.demcorr['dem_after_corr']['value'])
|
1028
|
+
else:
|
1029
|
+
basey=curnode.demcorr[curdem]['value']
|
1030
|
+
"""
|
1031
|
+
basey=curnode.demcorr[curdem]['value']
|
1032
|
+
|
1033
|
+
x.append(curnode.cums)
|
1034
|
+
y.append(basey)
|
1035
|
+
curnode=curnode.down
|
1036
|
+
|
1037
|
+
locs= ds
|
1038
|
+
while not curnode is None:
|
1039
|
+
"""
|
1040
|
+
if curdem=='crosssection':
|
1041
|
+
yloc=min(curnode.demcorr[curdem]['value'],curnode.demcorr['dem_after_corr']['value'])
|
1042
|
+
else:
|
1043
|
+
yloc=curnode.demcorr[curdem]['value']
|
1044
|
+
"""
|
1045
|
+
yloc=curnode.demcorr[curdem]['value']
|
1046
|
+
|
1047
|
+
if (basey-yloc)/locs>self.tslopemax:
|
1048
|
+
while len(x)>1 and (basey-yloc)/locs>self.tslopemax:
|
1049
|
+
x.pop()
|
1050
|
+
y.pop()
|
1051
|
+
basey=y[-1]
|
1052
|
+
locs+=ds
|
1053
|
+
|
1054
|
+
if yloc<y[-1]:
|
1055
|
+
x.append(curnode.cums)
|
1056
|
+
y.append(yloc)
|
1057
|
+
basey=yloc
|
1058
|
+
locs=ds
|
1059
|
+
if curnode.river:
|
1060
|
+
break
|
1061
|
+
|
1062
|
+
curnode=curnode.down
|
1063
|
+
#if curnode.i==187 and curnode.j==207:
|
1064
|
+
# a=1
|
1065
|
+
|
1066
|
+
self.upmax[idx][curdem]=[x,y]
|
1067
|
+
|
1068
|
+
def compute_slopescorr(self, whichdict:dict):
|
1069
|
+
curnode:Node_Watershed
|
1070
|
+
for curdem in LISTDEM:
|
1071
|
+
logging.info(_('Current DEM : {}'.format(curdem)))
|
1072
|
+
for idx,curup in enumerate(self.upstreams['list']):
|
1073
|
+
curdict=whichdict[idx][curdem]
|
1074
|
+
xmin=curdict[0]
|
1075
|
+
if len(xmin)>1:
|
1076
|
+
ymin=curdict[1]
|
1077
|
+
x=self.get_cums(whichup=idx)
|
1078
|
+
|
1079
|
+
f=interpolate.interp1d(xmin,ymin, fill_value='extrapolate')
|
1080
|
+
y=f(x)
|
1081
|
+
slopes=self.compute_slope_down(x,y)
|
1082
|
+
|
1083
|
+
curnode=curup
|
1084
|
+
i=0
|
1085
|
+
while not curnode.river:
|
1086
|
+
#if curnode.i==187 and curnode.j==207:
|
1087
|
+
# a=1
|
1088
|
+
curnode.demcorr[curdem]['parts'].append(y[i])
|
1089
|
+
curnode.slopecorr[curdem]['parts'].append(slopes[i])
|
1090
|
+
i+=1
|
1091
|
+
curnode=curnode.down
|
1092
|
+
#calcul de la moyenne sur base des valeurs partielles
|
1093
|
+
for curdem in LISTDEM:
|
1094
|
+
for curnode in self.nodes:
|
1095
|
+
#if curnode.i==187 and curnode.j==207:
|
1096
|
+
# a=1
|
1097
|
+
if len(curnode.slopecorr[curdem]['parts'])<2:
|
1098
|
+
#Ce cas particulier peut arriver si des mailles BV sont remplies par une zone plate qui s'étend en rivière
|
1099
|
+
# Comme on ne recherche de mailles plus basses que dans la partie BV, il n'est pas possible de corriger les pentes
|
1100
|
+
if not self.tslopemin is None:
|
1101
|
+
curnode.slopecorr[curdem]['value']=max(self.tslopemin,curnode.slope)
|
1102
|
+
else:
|
1103
|
+
curnode.slopecorr[curdem]['value']=1.e-4
|
1104
|
+
|
1105
|
+
if not self.tslopemax is None:
|
1106
|
+
curnode.slopecorr[curdem]['value']=min(self.tslopemax,curnode.slope)
|
1107
|
+
else:
|
1108
|
+
curnode.demcorr[curdem]['value']=np.mean(curnode.demcorr[curdem]['parts'])
|
1109
|
+
curnode.slopecorr[curdem]['value']=np.mean(curnode.slopecorr[curdem]['parts'])
|
1110
|
+
|
1111
|
+
curnode.demcorr[curdem]['parts']=[]
|
1112
|
+
curnode.slopecorr[curdem]['parts']=[]
|
1113
|
+
|
1114
|
+
def compute_slope_down(self, x, y):
|
1115
|
+
"""
|
1116
|
+
Calcul de la pente sur base de listes X et Y
|
1117
|
+
"""
|
1118
|
+
slope=[]
|
1119
|
+
for i in range(len(x)-1):
|
1120
|
+
slope.append((y[i+1]-y[i])/(x[i+1]-x[i]))
|
1121
|
+
slope.append(slope[-1])
|
1122
|
+
return slope
|
1123
|
+
|
1124
|
+
class SubWatershed:
|
1125
|
+
""" Classe sous-bassin versant """
|
1126
|
+
def __init__(self,
|
1127
|
+
parent:"Watershed",
|
1128
|
+
name:str,
|
1129
|
+
idx:int,
|
1130
|
+
mask:WolfArray,
|
1131
|
+
nodes:list[Node_Watershed],
|
1132
|
+
runoff:list[Node_Watershed],
|
1133
|
+
rivers:list[Node_Watershed]) -> None:
|
1134
|
+
|
1135
|
+
self.parent = parent
|
1136
|
+
self.index = idx
|
1137
|
+
self.name = name
|
1138
|
+
self.mask = mask
|
1139
|
+
self.nodes = nodes
|
1140
|
+
self.rivers = rivers
|
1141
|
+
self.runoff = runoff
|
1142
|
+
self.idx_reaches = np.unique(np.asarray([x.reach for x in rivers]))
|
1143
|
+
|
1144
|
+
@property
|
1145
|
+
def surface(self) -> float:
|
1146
|
+
return self.mask.nbnotnull * self.mask.dx * self.mask.dy
|
1147
|
+
|
1148
|
+
class Watershed:
|
1149
|
+
"""Classe bassin versant"""
|
1150
|
+
|
1151
|
+
header:header_wolf # header_wolf of "Drainage_basin.sub" wolf_array
|
1152
|
+
|
1153
|
+
dir: str # Répertoire de modélisation
|
1154
|
+
|
1155
|
+
outlet:Node_Watershed # exutoire
|
1156
|
+
|
1157
|
+
subs_array: WolfArray # "Drainage_basin.sub" wolf_array
|
1158
|
+
|
1159
|
+
nodes:list[Node_Watershed] # all nodes
|
1160
|
+
nodesindex:np.ndarray # indirect access to mynodes, contains index of instance in list
|
1161
|
+
rivers:list[Node_Watershed] # all river nodes
|
1162
|
+
runoff:list[Node_Watershed] # all runoff nodes
|
1163
|
+
|
1164
|
+
couplednodes:list # forced exchanges
|
1165
|
+
|
1166
|
+
subcatchments: list[SubWatershed]
|
1167
|
+
statisticss: dict
|
1168
|
+
|
1169
|
+
couplednodesxy:list[float,float,float,float]
|
1170
|
+
couplednodesij:list[tuple[int,int],tuple[int,int]]
|
1171
|
+
|
1172
|
+
riversystem:RiverSystem # réseau de rivières
|
1173
|
+
runoffsystem:RunoffSystem # écoulement diffus/hydrologique
|
1174
|
+
|
1175
|
+
def __init__(self,
|
1176
|
+
dir:str,
|
1177
|
+
thzmin:float=None,
|
1178
|
+
thslopemin:float=None,
|
1179
|
+
thzmax:float=None,
|
1180
|
+
thslopemax:float=None,
|
1181
|
+
crosssections:CrossSections=None,
|
1182
|
+
computestats:bool=False,
|
1183
|
+
computecorr:bool=False,
|
1184
|
+
plotstats:bool=False,
|
1185
|
+
plotriversystem=False,
|
1186
|
+
*args, **kwargs):
|
1187
|
+
|
1188
|
+
logging.info(_('Read files...'))
|
1189
|
+
self.dir=os.path.normpath(dir)
|
1190
|
+
|
1191
|
+
self.subs_array = WolfArray(self.dir+'\\Characteristic_maps\\Drainage_basin.sub')
|
1192
|
+
|
1193
|
+
self.header = self.subs_array.get_header()
|
1194
|
+
|
1195
|
+
#FIXME
|
1196
|
+
isOk, fe_file = check_path(os.path.join(self.dir, "Coupled_pairs.txt"), prefix=self.dir)
|
1197
|
+
self.couplednodesxy=[]
|
1198
|
+
self.couplednodesij=[]
|
1199
|
+
|
1200
|
+
if isOk>=0:
|
1201
|
+
f = open(fe_file, 'r')
|
1202
|
+
lines = f.read().splitlines()
|
1203
|
+
f.close()
|
1204
|
+
|
1205
|
+
if lines[0]=='COORDINATES':
|
1206
|
+
for xy in enumerate(lines[1:]):
|
1207
|
+
xup,yup,xdown,ydown=xy[1].split('\t')
|
1208
|
+
self.couplednodesxy.append([float(xup),float(yup),float(xdown),float(ydown)])
|
1209
|
+
self.couplednodesij.append([self.subs_array.get_ij_from_xy(float(xup),float(yup)),self.subs_array.get_ij_from_xy(float(xdown),float(ydown))])
|
1210
|
+
|
1211
|
+
logging.info(_('Initialization of nodes...'))
|
1212
|
+
self.nodesindex = np.zeros([self.subs_array.nbx,self.subs_array.nby], dtype=int)
|
1213
|
+
self.outlet = None
|
1214
|
+
self.up = None
|
1215
|
+
self.init_nodes()
|
1216
|
+
|
1217
|
+
logging.info(_('Initialization of subwatersheds...'))
|
1218
|
+
self.init_subs()
|
1219
|
+
|
1220
|
+
if not crosssections is None:
|
1221
|
+
logging.info(_('Cross sections...'))
|
1222
|
+
self.crosssections = crosssections
|
1223
|
+
self.attrib_cs_to_nodes()
|
1224
|
+
else:
|
1225
|
+
self.crosssections = None
|
1226
|
+
|
1227
|
+
logging.info(_('Slopes corrections...'))
|
1228
|
+
self.riversystem = RiverSystem(self.rivers , self,thslopemin=thslopemin, thslopemax=thslopemax, computecorr=computecorr)
|
1229
|
+
self.runoffsystem = RunoffSystem(self.runoff, self,thslopemin=thslopemin, thslopemax=thslopemax, computecorr=computecorr)
|
1230
|
+
|
1231
|
+
if computestats or plotstats:
|
1232
|
+
logging.info(_('Statistics...'))
|
1233
|
+
self.compute_stats(plotstats)
|
1234
|
+
|
1235
|
+
#Ecriture des résultats de correction des pentes
|
1236
|
+
if computecorr:
|
1237
|
+
logging.info(_('Writing data to disk'))
|
1238
|
+
self.write_dem()
|
1239
|
+
self.write_slopes()
|
1240
|
+
|
1241
|
+
if plotriversystem:
|
1242
|
+
logging.info(_('Plot rivers'))
|
1243
|
+
self.riversystem.plot_all_in_notebook()
|
1244
|
+
|
1245
|
+
logging.info(_('Done!'))
|
1246
|
+
|
1247
|
+
@property
|
1248
|
+
def nb_subs(self):
|
1249
|
+
return int(ma.max(self.subs_array.array))
|
1250
|
+
|
1251
|
+
@property
|
1252
|
+
def resolution(self):
|
1253
|
+
return self.header.dx
|
1254
|
+
|
1255
|
+
def get_node_from_ij(self, i:int,j:int):
|
1256
|
+
"""
|
1257
|
+
Récupération d'un objet Node_Watershed sur base des indices (i,j)
|
1258
|
+
"""
|
1259
|
+
shape = self.nodesindex.shape
|
1260
|
+
if i<0 or i>=shape[0]:
|
1261
|
+
return None
|
1262
|
+
if j<0 or j>=shape[1]:
|
1263
|
+
return None
|
1264
|
+
idx = self.nodesindex[i,j]
|
1265
|
+
if idx<0 or idx >= len(self.nodes):
|
1266
|
+
return None
|
1267
|
+
|
1268
|
+
return self.nodes[idx]
|
1269
|
+
|
1270
|
+
def get_node_from_xy(self, x:float, y:float):
|
1271
|
+
"""
|
1272
|
+
Récupération d'un objet Node_Watershed sur base des coordonnées (x,y)
|
1273
|
+
"""
|
1274
|
+
i,j = self.header.get_ij_from_xy(x,y)
|
1275
|
+
return self.get_node_from_ij(i,j)
|
1276
|
+
|
1277
|
+
def write_slopes(self):
|
1278
|
+
"""
|
1279
|
+
Ecriture sur disque
|
1280
|
+
"""
|
1281
|
+
for curlist in LISTDEM:
|
1282
|
+
curpath=self.dir+'\\Characteristic_maps\\corrslopes\\'+curlist
|
1283
|
+
os.makedirs(curpath,exist_ok=True)
|
1284
|
+
slopes= WolfArray(self.dir+'\\Characteristic_maps\\Drainage_basin.slope')
|
1285
|
+
|
1286
|
+
ijval = np.asarray([[curnode.i, curnode.j, curnode.slopecorr[curlist]['value']] for curnode in self.nodes])
|
1287
|
+
slopes.array[np.int32(ijval[:,0]),np.int32(ijval[:,1])]=ijval[:,2]
|
1288
|
+
|
1289
|
+
slopes.filename = curpath +'\\Drainage_basin.slope_corr'
|
1290
|
+
slopes.write_all()
|
1291
|
+
|
1292
|
+
def write_dem(self):
|
1293
|
+
"""
|
1294
|
+
Ecriture sur disque
|
1295
|
+
"""
|
1296
|
+
for curlist in LISTDEM:
|
1297
|
+
curpath=self.dir+'\\Characteristic_maps\\corrdem\\'+curlist
|
1298
|
+
os.makedirs(curpath,exist_ok=True)
|
1299
|
+
dem= WolfArray(self.dir+'\\Characteristic_maps\\Drainage_basincorr.b')
|
1300
|
+
|
1301
|
+
ijval = np.asarray([[curnode.i, curnode.j, curnode.demcorr[curlist]['value']] for curnode in self.nodes])
|
1302
|
+
dem.array[np.int32(ijval[:,0]),np.int32(ijval[:,1])]=ijval[:,2]
|
1303
|
+
|
1304
|
+
dem.filename = curpath +'\\Drainage_basincorr.b'
|
1305
|
+
dem.write_all()
|
1306
|
+
|
1307
|
+
@property
|
1308
|
+
def crosssections(self):
|
1309
|
+
return self._cs
|
1310
|
+
|
1311
|
+
@crosssections.setter
|
1312
|
+
def crosssections(self, value:CrossSections):
|
1313
|
+
self._cs = value
|
1314
|
+
|
1315
|
+
def attrib_cs_to_nodes(self):
|
1316
|
+
"""
|
1317
|
+
Attribution des sections en travers aux noeuds
|
1318
|
+
"""
|
1319
|
+
if self.crosssections is not None:
|
1320
|
+
for curlist in self.crosssections:
|
1321
|
+
for namecs in curlist.myprofiles:
|
1322
|
+
curvert:wolfvertex
|
1323
|
+
curcs=curlist.myprofiles[namecs]
|
1324
|
+
|
1325
|
+
try:
|
1326
|
+
curvert=curcs['bed']
|
1327
|
+
except:
|
1328
|
+
curvert=curlist.get_min(whichprofile=curcs)
|
1329
|
+
|
1330
|
+
i,j=self.subs_array.get_ij_from_xy(curvert.x,curvert.y)
|
1331
|
+
curnode:Node_Watershed
|
1332
|
+
curnode =self.nodes[self.nodesindex[i,j]]
|
1333
|
+
|
1334
|
+
if curnode.river:
|
1335
|
+
if curnode.crosssections is None:
|
1336
|
+
curnode.crosssections=[]
|
1337
|
+
curnode.crosssections.append(curcs)
|
1338
|
+
curnode.dem['crosssection']=min(curnode.dem['crosssection'],curvert.z)
|
1339
|
+
|
1340
|
+
def init_nodes(self):
|
1341
|
+
"""
|
1342
|
+
Initialisation des noeuds
|
1343
|
+
"""
|
1344
|
+
|
1345
|
+
self.nodes=[Node_Watershed() for i in range(self.subs_array.nbnotnull)]
|
1346
|
+
|
1347
|
+
dem_before_corr= WolfArray(self.dir+'\\Characteristic_maps\\Drainage_basin.b')
|
1348
|
+
dem_after_corr= WolfArray(self.dir+'\\Characteristic_maps\\Drainage_basincorr.b')
|
1349
|
+
demdelta= WolfArray(self.dir+'\\Characteristic_maps\\Drainage_basindiff.b')
|
1350
|
+
slopes= WolfArray(self.dir+'\\Characteristic_maps\\Drainage_basin.slope',masknull=False)
|
1351
|
+
reaches= WolfArray(self.dir+'\\Characteristic_maps\\Drainage_basin.reachs')
|
1352
|
+
cnv= WolfArray(self.dir+'\\Characteristic_maps\\Drainage_basin.cnv')
|
1353
|
+
times= WolfArray(self.dir+'\\Characteristic_maps\\Drainage_basin.time')
|
1354
|
+
|
1355
|
+
dem_after_corr.array.mask = self.subs_array.array.mask
|
1356
|
+
|
1357
|
+
nb=0
|
1358
|
+
for index,x in tqdm(np.ndenumerate(self.subs_array.array), 'Numbering'):
|
1359
|
+
if(x>0):
|
1360
|
+
i=int(index[0])
|
1361
|
+
j=int(index[1])
|
1362
|
+
self.nodesindex[i,j]=nb
|
1363
|
+
nb+=1
|
1364
|
+
|
1365
|
+
curnode:Node_Watershed
|
1366
|
+
nb=0
|
1367
|
+
for index, i_sub in tqdm(np.ndenumerate(self.subs_array.array), 'Initialization'):
|
1368
|
+
if(i_sub>0):
|
1369
|
+
i=int(index[0])
|
1370
|
+
j=int(index[1])
|
1371
|
+
x, y = self.header.get_xy_from_ij(i,j)
|
1372
|
+
curnode =self.nodes[self.nodesindex[i,j]]
|
1373
|
+
|
1374
|
+
curnode.i = i
|
1375
|
+
curnode.j = j
|
1376
|
+
|
1377
|
+
curnode.x = x
|
1378
|
+
curnode.y = y
|
1379
|
+
|
1380
|
+
curnode.crosssections = None
|
1381
|
+
curnode.down = None
|
1382
|
+
|
1383
|
+
curnode.index=nb
|
1384
|
+
curnode.dem={}
|
1385
|
+
curnode.dem['dem_before_corr']=dem_before_corr.array[i,j]
|
1386
|
+
curnode.dem['dem_after_corr']=dem_after_corr.array[i,j]
|
1387
|
+
curnode.dem['crosssection']=99999.
|
1388
|
+
curnode.demdelta=demdelta.array[i,j]
|
1389
|
+
curnode.slope=slopes.array[i,j]
|
1390
|
+
|
1391
|
+
curnode.slopecorr={}
|
1392
|
+
for curlist in LISTDEM:
|
1393
|
+
curnode.slopecorr[curlist]={}
|
1394
|
+
curnode.slopecorr[curlist]['parts']=[]
|
1395
|
+
curnode.slopecorr[curlist]['value']=curnode.slope
|
1396
|
+
|
1397
|
+
curnode.demcorr={}
|
1398
|
+
for curlist in LISTDEM:
|
1399
|
+
curnode.demcorr[curlist]={}
|
1400
|
+
curnode.demcorr[curlist]['parts']=[]
|
1401
|
+
curnode.demcorr[curlist]['value']=curnode.dem['dem_after_corr']
|
1402
|
+
|
1403
|
+
curnode.sub=int(i_sub)
|
1404
|
+
curnode.time=times.array[i,j]
|
1405
|
+
curnode.uparea=cnv.array[i,j]
|
1406
|
+
curnode.river=not reaches.array.mask[i,j]
|
1407
|
+
if curnode.river:
|
1408
|
+
curnode.reach=int(reaches.array[i,j])
|
1409
|
+
curnode.forced=False
|
1410
|
+
curnode.up=[]
|
1411
|
+
curnode.upriver=[]
|
1412
|
+
curnode.strahler=0
|
1413
|
+
curnode.reachlevel=0
|
1414
|
+
nb+=1
|
1415
|
+
|
1416
|
+
curdown:Node_Watershed
|
1417
|
+
#Liaison échanges forcés
|
1418
|
+
incr=slopes.dx
|
1419
|
+
for curexch in self.couplednodesij:
|
1420
|
+
i=int(curexch[0][0])
|
1421
|
+
j=int(curexch[0][1])
|
1422
|
+
curnode=self.nodes[self.nodesindex[i,j]]
|
1423
|
+
curnode.forced=True
|
1424
|
+
idown = int(curexch[1][0])
|
1425
|
+
jdown = int(curexch[1][1])
|
1426
|
+
curdown = self.nodes[self.nodesindex[idown,jdown]]
|
1427
|
+
curnode.down = curdown
|
1428
|
+
curdown.up.append(curnode)
|
1429
|
+
if curnode.river:
|
1430
|
+
curdown.upriver.append(curnode)
|
1431
|
+
curnode.incrs = incr * np.sqrt(pow(curdown.i-i,2)+pow(curdown.j-j,2))
|
1432
|
+
|
1433
|
+
#Liaison hors échanges forcés
|
1434
|
+
for curnode in tqdm(self.nodes, 'Linking'):
|
1435
|
+
if not curnode.forced:
|
1436
|
+
i=curnode.i
|
1437
|
+
j=curnode.j
|
1438
|
+
|
1439
|
+
curtop=curnode.dem['dem_after_corr']
|
1440
|
+
|
1441
|
+
neigh = [[i-1,j],[i+1,j],[i,j-1], [i,j+1]]
|
1442
|
+
diff = [dem_after_corr.array[curi,curj]-curtop if not dem_after_corr.array.mask[curi,curj] else 100000. for curi,curj in neigh]
|
1443
|
+
mindiff = np.min(diff)
|
1444
|
+
if mindiff<0:
|
1445
|
+
index = diff.index(mindiff)
|
1446
|
+
if index==0:
|
1447
|
+
curdown = self.nodes[self.nodesindex[i-1,j]]
|
1448
|
+
elif index==1:
|
1449
|
+
curdown = self.nodes[self.nodesindex[i+1,j]]
|
1450
|
+
elif index==2:
|
1451
|
+
curdown = self.nodes[self.nodesindex[i,j-1]]
|
1452
|
+
else:
|
1453
|
+
curdown = self.nodes[self.nodesindex[i,j+1]]
|
1454
|
+
|
1455
|
+
curnode.down = curdown
|
1456
|
+
curdown.up.append(curnode)
|
1457
|
+
if curnode.river:
|
1458
|
+
curdown.upriver.append(curnode)
|
1459
|
+
curnode.incrs=incr
|
1460
|
+
else:
|
1461
|
+
self.outlet = curnode
|
1462
|
+
|
1463
|
+
#Rechreche de la pente dans les voisins en croix dans la topo non remaniée
|
1464
|
+
for curnode in tqdm(self.nodes, 'Finding slope'):
|
1465
|
+
if not curnode.forced:
|
1466
|
+
i=curnode.i
|
1467
|
+
j=curnode.j
|
1468
|
+
|
1469
|
+
curtop = curnode.dem['dem_before_corr']
|
1470
|
+
|
1471
|
+
neigh = [[i-1,j], [i+1,j], [i,j-1], [i,j+1], [i-1,j-1], [i+1,j+1], [i+1,j-1], [i-1,j+1]]
|
1472
|
+
diff = [dem_before_corr.array[curi,curj]-curtop if not dem_before_corr.array.mask[curi,curj] else 100000. for curi,curj in neigh ]
|
1473
|
+
mindiff = np.min(diff)
|
1474
|
+
|
1475
|
+
fact=1.
|
1476
|
+
if mindiff<0:
|
1477
|
+
index = diff.index(mindiff)
|
1478
|
+
if index>3:
|
1479
|
+
fact=np.sqrt(2)
|
1480
|
+
|
1481
|
+
curnode.sloped8 = -mindiff/(self.resolution*fact)
|
1482
|
+
|
1483
|
+
self.rivers=list(filter(lambda x: x.river,self.nodes))
|
1484
|
+
self.rivers.sort(key=lambda x: x.dem['dem_after_corr'])
|
1485
|
+
sys.setrecursionlimit(len(self.nodes))
|
1486
|
+
self.outlet.incr_curvi()
|
1487
|
+
|
1488
|
+
self.find_dem_subpixels()
|
1489
|
+
|
1490
|
+
self.runoff=self.find_runoffnodes()
|
1491
|
+
|
1492
|
+
def find_rivers(self, whichsub:int=0, whichreach:int=0) -> tuple[list[Node_Watershed], Node_Watershed]:
|
1493
|
+
"""
|
1494
|
+
Recherche des mailles rivières
|
1495
|
+
@param whichsub : numéro du sous-bassin à traiter
|
1496
|
+
@param whicreach : numéro du tronçon à identifier
|
1497
|
+
"""
|
1498
|
+
if whichsub>0 and whichsub<=self.nb_subs:
|
1499
|
+
if whichreach>0:
|
1500
|
+
myrivers=list(filter(lambda x: x.river and x.sub==whichsub and x.reach==whichreach,self.rivers))
|
1501
|
+
else:
|
1502
|
+
myrivers=list(filter(lambda x: x.river and x.sub==whichsub,self.rivers))
|
1503
|
+
else:
|
1504
|
+
if whichreach>0:
|
1505
|
+
myrivers=list(filter(lambda x: x.river and x.reach==whichreach,self.rivers))
|
1506
|
+
else:
|
1507
|
+
myrivers=list(filter(lambda x: x.river,self.rivers))
|
1508
|
+
|
1509
|
+
myrivers.sort(key=lambda x: x.dem['dem_after_corr'])
|
1510
|
+
|
1511
|
+
up=None
|
1512
|
+
if len(myrivers)>0:
|
1513
|
+
up=myrivers[-1]
|
1514
|
+
|
1515
|
+
return myrivers,up
|
1516
|
+
|
1517
|
+
def find_sub(self, whichsub:int=0) -> list[Node_Watershed]:
|
1518
|
+
"""
|
1519
|
+
Recherche des mailles du sous-bassin versant
|
1520
|
+
@param whichsub : numéro du sous-bassin à traiter
|
1521
|
+
"""
|
1522
|
+
if whichsub>0 and whichsub<=self.nb_subs:
|
1523
|
+
mysub=list(filter(lambda x: x.sub==whichsub, self.nodes))
|
1524
|
+
else:
|
1525
|
+
mysub=self.nodes.copy()
|
1526
|
+
|
1527
|
+
mysub.sort(key=lambda x: x.dem['dem_after_corr'])
|
1528
|
+
|
1529
|
+
return mysub
|
1530
|
+
|
1531
|
+
def init_subs(self):
|
1532
|
+
"""
|
1533
|
+
Initialize Sub-Catchments
|
1534
|
+
"""
|
1535
|
+
self.subcatchments=[]
|
1536
|
+
|
1537
|
+
#Initialisation de la matrice de mask (d'une extension et d'une résolution similaire aux données radar)
|
1538
|
+
for i in tqdm(range(1,self.nb_subs+1), 'Subwatershed'):
|
1539
|
+
curmask = WolfArray(mold=self.subs_array)
|
1540
|
+
curmask.mask_allexceptdata(float(i))
|
1541
|
+
all_river_nodes, _ = self.find_rivers(i)
|
1542
|
+
|
1543
|
+
cursub = SubWatershed(self,
|
1544
|
+
name = 'sub n'+str(i),
|
1545
|
+
idx=i-1,
|
1546
|
+
mask = curmask,
|
1547
|
+
nodes = self.find_sub(i),
|
1548
|
+
runoff=self.find_runoffnodes(i),
|
1549
|
+
rivers=all_river_nodes,
|
1550
|
+
)
|
1551
|
+
|
1552
|
+
self.subcatchments.append(cursub)
|
1553
|
+
|
1554
|
+
def find_runoffnodes(self, whichsub:int=0) -> list[Node_Watershed]:
|
1555
|
+
"""
|
1556
|
+
Recherche des mailles du bassin versant seul (sans les rivières)
|
1557
|
+
@param whichsub : numéro du sous-bassin à traiter
|
1558
|
+
"""
|
1559
|
+
if whichsub>0 and whichsub<=self.nb_subs:
|
1560
|
+
myrunoff=list(filter(lambda x: not x.river and x.sub==whichsub,self.nodes))
|
1561
|
+
else:
|
1562
|
+
myrunoff=list(filter(lambda x: not x.river,self.nodes))
|
1563
|
+
|
1564
|
+
myrunoff.sort(key=lambda x: x.dem['dem_after_corr'])
|
1565
|
+
|
1566
|
+
return myrunoff
|
1567
|
+
|
1568
|
+
def index_flatzone(self, listofsortednodes:list, threshold:float):
|
1569
|
+
"""
|
1570
|
+
Indexation des zones de plat
|
1571
|
+
"""
|
1572
|
+
|
1573
|
+
curnode:Node_Watershed
|
1574
|
+
curflat:Node_Watershed
|
1575
|
+
|
1576
|
+
curindex=0
|
1577
|
+
for curnode in listofsortednodes[-1:1:-1]:
|
1578
|
+
addone=False
|
1579
|
+
while curnode.slope<threshold and curnode.flatindex==-1:
|
1580
|
+
addone=True
|
1581
|
+
curnode.flatindex=curindex
|
1582
|
+
if curnode.down is None:
|
1583
|
+
break
|
1584
|
+
curnode=curnode.down
|
1585
|
+
if addone:
|
1586
|
+
curindex+=1
|
1587
|
+
|
1588
|
+
return curindex
|
1589
|
+
|
1590
|
+
def find_flatnodes(self, listofsortednodes:list):
|
1591
|
+
"""
|
1592
|
+
Recherche des mailles dans des zones de faibles pentes
|
1593
|
+
@param listofsortednodes : liste triée de mailles
|
1594
|
+
"""
|
1595
|
+
myflatnodes=list(filter(lambda x: x.flatindex>-1,listofsortednodes))
|
1596
|
+
|
1597
|
+
return myflatnodes
|
1598
|
+
|
1599
|
+
def find_flatzones(self, listofsortednodes:list, maxindex:int):
|
1600
|
+
"""
|
1601
|
+
Recherche des mailles dans des zones de faibles pentes
|
1602
|
+
@param listofsortednodes : liste triée de mailles
|
1603
|
+
"""
|
1604
|
+
myflatzones=[[]] * maxindex
|
1605
|
+
for i in range(maxindex):
|
1606
|
+
myflatzones[i]=list(filter(lambda x: x.flatindex==i,listofsortednodes))
|
1607
|
+
|
1608
|
+
return myflatzones
|
1609
|
+
|
1610
|
+
def find_dem_subpixels(self):
|
1611
|
+
"""
|
1612
|
+
Recherche des altitudes dans un mnt plus dense
|
1613
|
+
"""
|
1614
|
+
demsubs = {}
|
1615
|
+
file_10m = os.path.join(self.dir,'mnt10m.bin')
|
1616
|
+
isOk, file_10m = check_path(file_10m, prefix=self.dir)
|
1617
|
+
if isOk>=0:
|
1618
|
+
dem_10m=WolfArray(file_10m)
|
1619
|
+
demsubs["dem_10m"] = dem_10m
|
1620
|
+
|
1621
|
+
file_20m = os.path.join(self.dir,'mnt20m.bin')
|
1622
|
+
isOk, file_20m = check_path(file_20m, prefix=self.dir)
|
1623
|
+
if isOk>=0:
|
1624
|
+
dem_20m=WolfArray(file_20m)
|
1625
|
+
demsubs["dem_20m"] = dem_20m
|
1626
|
+
|
1627
|
+
|
1628
|
+
# demsubs={'dem_10m':dem_10m,'dem_20m':dem_20m}
|
1629
|
+
if len(demsubs)==0:
|
1630
|
+
return
|
1631
|
+
|
1632
|
+
curnode:Node_Watershed
|
1633
|
+
for curdem in tqdm(demsubs, 'Sub-pixeling'):
|
1634
|
+
locdem=demsubs[curdem]
|
1635
|
+
dx=locdem.dx
|
1636
|
+
dy=locdem.dy
|
1637
|
+
|
1638
|
+
for curnode in tqdm(self.nodes):
|
1639
|
+
curi=curnode.i
|
1640
|
+
curj=curnode.j
|
1641
|
+
|
1642
|
+
curx,cury=self.subs_array.get_xy_from_ij(curi,curj)
|
1643
|
+
|
1644
|
+
decalx=(self.resolution-dx)/2.
|
1645
|
+
decaly=(self.resolution-dy)/2.
|
1646
|
+
x1=curx-decalx
|
1647
|
+
y1=cury-decaly
|
1648
|
+
x2=curx+decalx
|
1649
|
+
y2=cury+decaly
|
1650
|
+
|
1651
|
+
i1,j1=locdem.get_ij_from_xy(x1,y1)
|
1652
|
+
i2,j2=locdem.get_ij_from_xy(x2,y2)
|
1653
|
+
|
1654
|
+
curnode.dem[curdem]=np.min(locdem.array[i1:i2+1,j1:j2+1])
|
1655
|
+
|
1656
|
+
def compute_stats(self, plot:bool=False):
|
1657
|
+
"""
|
1658
|
+
Calcul des statistiques de pente
|
1659
|
+
"""
|
1660
|
+
self.statisticss={}
|
1661
|
+
|
1662
|
+
slopes=np.array(list(x.slope for x in self.nodes))
|
1663
|
+
slopesrunoff=np.array(list(x.slope for x in list(filter(lambda x: not x.river,self.nodes))))
|
1664
|
+
slopesriver=np.array(list(x.slope for x in list(filter(lambda x: x.river,self.nodes))))
|
1665
|
+
|
1666
|
+
curdict=self.statisticss
|
1667
|
+
curdict['slopemin'] = np.min(slopes)
|
1668
|
+
curdict['slopemax'] = np.max(slopes)
|
1669
|
+
curdict['slopemedian'] = np.median(slopes)
|
1670
|
+
curdict['slopemean'] = np.mean(slopes)
|
1671
|
+
curdict['hist'] = slopes
|
1672
|
+
curdict['hist_watershed'] = slopesrunoff
|
1673
|
+
curdict['hist_reaches'] = slopesriver
|
1674
|
+
curdict['count_neg'] = np.count_nonzero(slopes < 0.)
|
1675
|
+
|
1676
|
+
logging.info(_('Min : {}'.format(curdict['slopemin'])))
|
1677
|
+
logging.info(_('Max : {}'.format(curdict['slopemax'])))
|
1678
|
+
logging.info(_('Median : {}'.format(curdict['slopemedian'])))
|
1679
|
+
logging.info(_('Mean : {}'.format(curdict['slopemean'])))
|
1680
|
+
logging.info(_('Non Zero : {}'.format(curdict['count_neg'])))
|
1681
|
+
|
1682
|
+
for curlist in LISTDEM:
|
1683
|
+
curdict=self.statisticss[curlist]={}
|
1684
|
+
|
1685
|
+
slopes=np.array(list(x.slopecorr[curlist]['value'] for x in self.nodes))
|
1686
|
+
slopesrunoff=np.array(list(x.slopecorr[curlist]['value'] for x in list(filter(lambda x: not x.river,self.nodes))))
|
1687
|
+
slopesriver=np.array(list(x.slopecorr[curlist]['value'] for x in list(filter(lambda x: x.river,self.nodes))))
|
1688
|
+
|
1689
|
+
curdict['slopemin'] = np.min(slopes)
|
1690
|
+
curdict['slopemax'] = np.max(slopes)
|
1691
|
+
curdict['slopemedian'] = np.median(slopes)
|
1692
|
+
curdict['slopemean'] = np.mean(slopes)
|
1693
|
+
curdict['hist'] = slopes
|
1694
|
+
curdict['hist_watershed'] = slopesrunoff
|
1695
|
+
curdict['hist_reaches'] = slopesriver
|
1696
|
+
curdict['count_neg'] = np.count_nonzero(slopes < 0.)
|
1697
|
+
|
1698
|
+
logging.info(_('Current list : '.format(curlist)))
|
1699
|
+
logging.info(_('Min : {}'.format(curdict['slopemin'])))
|
1700
|
+
logging.info(_('Max : {}'.format(curdict['slopemax'])))
|
1701
|
+
logging.info(_('Median : {}'.format(curdict['slopemedian'])))
|
1702
|
+
logging.info(_('Mean : {}'.format(curdict['slopemean'])))
|
1703
|
+
logging.info(_('Non Zero : {}'.format(curdict['count_neg'])))
|
1704
|
+
|
1705
|
+
if plot:
|
1706
|
+
self.plot_stats()
|
1707
|
+
|
1708
|
+
def plot_stats(self):
|
1709
|
+
|
1710
|
+
self.myplotterstats = PlotNotebook()
|
1711
|
+
|
1712
|
+
bin1=np.array([1.e-8,1.e-7,1.e-6,5.e-6])
|
1713
|
+
bin2=np.linspace(1.e-5,1e-3,num=20)
|
1714
|
+
bin3=np.linspace(2.e-3,1e-1,num=20)
|
1715
|
+
bin4=np.linspace(.11,1,num=100)
|
1716
|
+
bins=np.concatenate((bin1,bin2,bin3,bin4))
|
1717
|
+
|
1718
|
+
fig=self.myplotterstats.add(_('Slope distribution - log'))
|
1719
|
+
|
1720
|
+
ax = fig.add_ax()
|
1721
|
+
ax.hist(self.statisticss['hist'],bins,cumulative=True,density=True,histtype=u'step',label='base')
|
1722
|
+
ax.set_xscale('log')
|
1723
|
+
ax.set_xlabel(_('All meshes'))
|
1724
|
+
|
1725
|
+
for curlist in LISTDEM:
|
1726
|
+
curdict=self.statisticss[curlist]
|
1727
|
+
ax.hist(curdict['hist'],bins,cumulative=True,density=True,histtype=u'step',label=curlist)
|
1728
|
+
|
1729
|
+
ax = fig.add_ax()
|
1730
|
+
ax.hist(self.statisticss['hist_watershed'],bins,cumulative=True,density=True,histtype=u'step',label='base')
|
1731
|
+
ax.set_xscale('log')
|
1732
|
+
ax.set_xlabel(_('Watershed'))
|
1733
|
+
|
1734
|
+
for curlist in LISTDEM:
|
1735
|
+
curdict=self.statisticss[curlist]
|
1736
|
+
ax.hist(curdict['hist_watershed'],bins,cumulative=True,density=True,histtype=u'step',label=curlist)
|
1737
|
+
|
1738
|
+
ax = fig.add_ax()
|
1739
|
+
ax.hist(self.statisticss['hist_reaches'],bins,cumulative=True,density=True,histtype=u'step',label='base')
|
1740
|
+
ax.set_xscale('log')
|
1741
|
+
ax.set_xlabel(_('River'))
|
1742
|
+
|
1743
|
+
for curlist in LISTDEM:
|
1744
|
+
curdict=self.statisticss[curlist]
|
1745
|
+
ax.hist(curdict['hist_reaches'],bins,cumulative=True,density=True,histtype=u'step',label=curlist)
|
1746
|
+
|
1747
|
+
ax.legend()
|
1748
|
+
fig.canvas.draw()
|
1749
|
+
|
1750
|
+
fig=self.myplotterstats.add(_('Slope distribution'))
|
1751
|
+
ax:plt.axis
|
1752
|
+
|
1753
|
+
ax = fig.add_ax()
|
1754
|
+
ax.hist(self.statisticss['hist'],bins,cumulative=True,density=True,histtype=u'step',label='base')
|
1755
|
+
ax.set_xlabel(_('All meshes'))
|
1756
|
+
|
1757
|
+
for curlist in LISTDEM:
|
1758
|
+
curdict=self.statisticss[curlist]
|
1759
|
+
ax.hist(curdict['hist'],bins,cumulative=True,density=True,histtype=u'step',label=curlist)
|
1760
|
+
|
1761
|
+
ax = fig.add_ax()
|
1762
|
+
ax.hist(self.statisticss['hist_watershed'],bins,cumulative=True,density=True,histtype=u'step',label='base')
|
1763
|
+
ax.set_xlabel(_('Watershed'))
|
1764
|
+
|
1765
|
+
for curlist in LISTDEM:
|
1766
|
+
curdict=self.statisticss[curlist]
|
1767
|
+
ax.hist(curdict['hist_watershed'],bins,cumulative=True,density=True,histtype=u'step',label=curlist)
|
1768
|
+
|
1769
|
+
ax = fig.add_ax()
|
1770
|
+
ax.hist(self.statisticss['hist_reaches'],bins,cumulative=True,density=True,histtype=u'step',label='base')
|
1771
|
+
ax.set_xlabel(_('River'))
|
1772
|
+
|
1773
|
+
for curlist in LISTDEM:
|
1774
|
+
curdict=self.statisticss[curlist]
|
1775
|
+
ax.hist(curdict['hist_reaches'],bins,cumulative=True,density=True,histtype=u'step',label=curlist)
|
1776
|
+
|
1777
|
+
ax.legend()
|
1778
|
+
fig.canvas.draw()
|
1779
|
+
|
1780
|
+
def analyze_flatzones(self):
|
1781
|
+
"""
|
1782
|
+
Analyse des zones de plat
|
1783
|
+
"""
|
1784
|
+
self.myplotterflat = PlotNotebook()
|
1785
|
+
|
1786
|
+
### Flat zones
|
1787
|
+
eps=1e-7
|
1788
|
+
#indexation des zones "indépendantes" de plats - ruissellement
|
1789
|
+
maxindex=self.index_flatzone(self.runoff,eps)
|
1790
|
+
#identification des mailles dans les zones
|
1791
|
+
myflatnodes=self.find_flatnodes(self.runoff)
|
1792
|
+
#création de listes avec les noeuds dans chaque zone
|
1793
|
+
myflats=self.find_flatzones(myflatnodes,maxindex)
|
1794
|
+
|
1795
|
+
#calcul de la longueur de la zone de plat --> sommation du nombre de mailles
|
1796
|
+
lenflats=np.zeros((maxindex),dtype=np.int32)
|
1797
|
+
for i in range(maxindex):
|
1798
|
+
lenflats[i]=len(myflats[i])
|
1799
|
+
|
1800
|
+
#indexation des zones "indépendantes" de plats - rivières
|
1801
|
+
maxindexrivers=self.index_flatzone(self.rivers,eps)
|
1802
|
+
#création de listes avec les noeuds dans chaque zone - rivières
|
1803
|
+
myflatsrivers=self.find_flatzones(self.rivers,maxindexrivers)
|
1804
|
+
|
1805
|
+
#calcul de la longueur de la zone de plat --> sommation du nombre de mailles
|
1806
|
+
lenflatsrivers=np.zeros((maxindexrivers),dtype=np.int32)
|
1807
|
+
for i in range(maxindexrivers):
|
1808
|
+
lenflatsrivers[i]=len(myflatsrivers[i])
|
1809
|
+
|
1810
|
+
fig:mplfig.Figure
|
1811
|
+
fig=self.myplotterflat.add("Nb nodes in flat area")
|
1812
|
+
ax=fig.add_ax()
|
1813
|
+
mybins=np.arange(0.5,np.max(lenflats),1.)
|
1814
|
+
myticks=np.arange(1,np.ceil(np.max(lenflats)),1)
|
1815
|
+
ax.hist(lenflats,bins=mybins)
|
1816
|
+
ax.set_xlabel(_('Nb nodes in flat area - runoff'))
|
1817
|
+
ax.set_xticks(myticks)
|
1818
|
+
ax.set_xbound(.5,np.max(lenflats))
|
1819
|
+
ax.set_ylabel('Nb flat areas')
|
1820
|
+
ax.set_yscale('log')
|
1821
|
+
|
1822
|
+
ax=fig.add_ax()
|
1823
|
+
mybinsrivers=np.arange(0.5,np.max(lenflatsrivers),1.)
|
1824
|
+
myticksrivers=np.arange(1,np.ceil(np.max(lenflatsrivers)),1)
|
1825
|
+
ax.hist(lenflatsrivers,bins=mybinsrivers)
|
1826
|
+
ax.set_xlabel(_('Nb nodes in flat area - rivers'))
|
1827
|
+
ax.set_xticks(myticksrivers)
|
1828
|
+
ax.set_xbound(.5,np.max(lenflatsrivers))
|
1829
|
+
ax.set_ylabel('Nb flat areas')
|
1830
|
+
ax.set_yscale('log')
|
1831
|
+
|
1832
|
+
fig=self.myplotterflat.add("Nb nodes in flat area")
|
1833
|
+
ax=fig.add_ax()
|
1834
|
+
ax.hist(lenflats,bins=mybins,cumulative=True,density=True)
|
1835
|
+
ax.set_xlabel(_('Nb nodes in flat area - runoff'))
|
1836
|
+
ax.set_xticks(myticks)
|
1837
|
+
ax.set_xbound(.5,np.max(lenflats))
|
1838
|
+
ax.set_ylabel('Cumulative flat areas')
|
1839
|
+
#ax.set_yscale('log')
|
1840
|
+
|
1841
|
+
ax=fig.add_ax()
|
1842
|
+
ax.hist(lenflatsrivers,bins=mybinsrivers,cumulative=True,density=True)
|
1843
|
+
ax.set_xlabel(_('Nb nodes in flat area - rivers'))
|
1844
|
+
ax.set_xticks(myticksrivers)
|
1845
|
+
ax.set_xbound(.5,np.max(lenflatsrivers))
|
1846
|
+
ax.set_ylabel('Cumulative flat areas')
|
1847
|
+
#ax.set_yscale('log')
|
1848
|
+
fig.canvas.draw()
|
1849
|
+
|
1850
|
+
#Tri des pentes dans différentes listes
|
1851
|
+
|
1852
|
+
#toutes les mailles
|
1853
|
+
sdown=[]
|
1854
|
+
sup=[]
|
1855
|
+
for curflat in myflats:
|
1856
|
+
for curnode in curflat:
|
1857
|
+
#recherche de la pente aval plus grande que le seuil
|
1858
|
+
sdown.append(curnode.slope_down(eps))
|
1859
|
+
#recherche de la pente amont moyenne - uniquement pour les mailles qui ont une pente supérieure au seuil
|
1860
|
+
sup.append(curnode.mean_slope_up(eps))
|
1861
|
+
|
1862
|
+
sflat=[]
|
1863
|
+
sdownraw=[]
|
1864
|
+
for curflat in myflats:
|
1865
|
+
for curnode in curflat:
|
1866
|
+
#pente de la maille aval
|
1867
|
+
sdownraw.append(curnode.down.slope)
|
1868
|
+
#pente courante
|
1869
|
+
sflat.append(curnode.slope)
|
1870
|
+
|
1871
|
+
#mailles rivières
|
1872
|
+
sdownriv=[]
|
1873
|
+
supriv=[]
|
1874
|
+
suponlyriv=[]
|
1875
|
+
for curflat in myflatsrivers:
|
1876
|
+
for curnode in curflat:
|
1877
|
+
#recherche de la pente aval plus grande que le seuil
|
1878
|
+
sdownriv.append(curnode.slope_down(eps))
|
1879
|
+
#recherche de la pente amont moyenne - uniquement pour les mailles qui ont une pente supérieure au seuil
|
1880
|
+
supriv.append(curnode.mean_slope_up(eps))
|
1881
|
+
#recherche de la pente amont > seuil
|
1882
|
+
suponlyriv.append(curnode.slope_upriver(eps))
|
1883
|
+
|
1884
|
+
sdownd8=[]
|
1885
|
+
suponlyriv1=[]
|
1886
|
+
for curflat in myflatsrivers:
|
1887
|
+
for curnode in curflat:
|
1888
|
+
#pente aval selon voisines D8
|
1889
|
+
sdownd8.append(curnode.sloped8)
|
1890
|
+
#recherche de la pente amont > seuil
|
1891
|
+
suponlyriv1.append(curnode.slope_upriver(eps))
|
1892
|
+
|
1893
|
+
sflatriver=[]
|
1894
|
+
sdownrawriver=[]
|
1895
|
+
sd8rawriver=[]
|
1896
|
+
for curflat in myflatsrivers:
|
1897
|
+
if len(curflat)==1:
|
1898
|
+
for curnode in curflat:
|
1899
|
+
if not curnode.down is None:
|
1900
|
+
sd8rawriver.append(curnode.sloped8)
|
1901
|
+
sdownrawriver.append(curnode.down.slope)
|
1902
|
+
sflatriver.append(curnode.slope)
|
1903
|
+
|
1904
|
+
|
1905
|
+
#tracage des graphiques
|
1906
|
+
fig=self.myplotterflat.add("Scatter plots")
|
1907
|
+
ax=fig.add_ax()
|
1908
|
+
ax.scatter(sdownrawriver,sflatriver,marker='o',label='slope down vs flat slope')
|
1909
|
+
ax.scatter(sdownriv,suponlyriv,marker='+',label='slope down vs slope d8')
|
1910
|
+
ax=fig.add_ax()
|
1911
|
+
ax.scatter(sdownraw,sflat,marker='0',label='slope down vs flat slope')
|
1912
|
+
ax.scatter(sdown,sup,marker='+',label='slope down vs slope up')
|
1913
|
+
fig.canvas.draw()
|
1914
|
+
|
1915
|
+
fig=self.myplotterflat.add("Scatter plots 2")
|
1916
|
+
curax=fig.add_ax()
|
1917
|
+
curax.scatter(sdown,sup,marker='+')
|
1918
|
+
curax.set_xlabel(_('Slope down [-]'))
|
1919
|
+
curax.set_ylabel(_('Mean slope up [-]'))
|
1920
|
+
curax.set_aspect('equal','box')
|
1921
|
+
curax.set_xbound(0,.55)
|
1922
|
+
curax.set_ybound(0,.55)
|
1923
|
+
curax.set_title('Runoff')
|
1924
|
+
|
1925
|
+
curax=fig.add_ax()
|
1926
|
+
curax.scatter(sdownriv,supriv,marker='+')
|
1927
|
+
curax.set_xlabel(_('Slope down [-]'))
|
1928
|
+
curax.set_ylabel(_('Mean slope up [-]'))
|
1929
|
+
curax.set_aspect('equal','box')
|
1930
|
+
curax.set_xbound(0,.55)
|
1931
|
+
curax.set_ybound(0,.55)
|
1932
|
+
curax.set_title('River')
|
1933
|
+
|
1934
|
+
curax=fig.add_ax()
|
1935
|
+
curax.scatter(sdownriv,suponlyriv,marker='+')
|
1936
|
+
curax.set_xlabel(_('Slope down [-]'))
|
1937
|
+
curax.set_ylabel(_('Slope up only river [-]'))
|
1938
|
+
curax.set_aspect('equal','box')
|
1939
|
+
curax.set_xbound(0,.55)
|
1940
|
+
curax.set_ybound(0,.55)
|
1941
|
+
curax.set_title('River')
|
1942
|
+
|
1943
|
+
curax=fig.add_ax()
|
1944
|
+
curax.scatter(sdownd8,suponlyriv1,marker='+')
|
1945
|
+
curax.set_xlabel(_('Slope D8 [-]'))
|
1946
|
+
curax.set_ylabel(_('Slope up only river [-]'))
|
1947
|
+
curax.set_aspect('equal','box')
|
1948
|
+
curax.set_xbound(0,.3)
|
1949
|
+
curax.set_ybound(0,.3)
|
1950
|
+
curax.set_title('River')
|
1951
|
+
fig.canvas.draw()
|