hspf 2.0.0__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.
- hspf/__init__.py +0 -0
- hspf/data/ParseTable.csv +2541 -0
- hspf/data/Timeseries Catalog/IMPLND/IQUAL.txt +10 -0
- hspf/data/Timeseries Catalog/IMPLND/IWATER.txt +9 -0
- hspf/data/Timeseries Catalog/IMPLND/IWTGAS.txt +6 -0
- hspf/data/Timeseries Catalog/IMPLND/SOLIDS.txt +2 -0
- hspf/data/Timeseries Catalog/PERLND/MSTLAY.txt +2 -0
- hspf/data/Timeseries Catalog/PERLND/PQUAL.txt +19 -0
- hspf/data/Timeseries Catalog/PERLND/PSTEMP.txt +4 -0
- hspf/data/Timeseries Catalog/PERLND/PWATER.txt +39 -0
- hspf/data/Timeseries Catalog/PERLND/PWATGAS.txt +21 -0
- hspf/data/Timeseries Catalog/PERLND/SEDMNT.txt +8 -0
- hspf/data/Timeseries Catalog/PERLND/SNOW.txt +22 -0
- hspf/data/Timeseries Catalog/RCHRES/CONS.txt +7 -0
- hspf/data/Timeseries Catalog/RCHRES/GQUAL.txt +22 -0
- hspf/data/Timeseries Catalog/RCHRES/HTRCH.txt +8 -0
- hspf/data/Timeseries Catalog/RCHRES/HYDR.txt +27 -0
- hspf/data/Timeseries Catalog/RCHRES/NUTRX.txt +50 -0
- hspf/data/Timeseries Catalog/RCHRES/OXRX.txt +8 -0
- hspf/data/Timeseries Catalog/RCHRES/PLANK.txt +24 -0
- hspf/data/Timeseries Catalog/RCHRES/SEDTRN.txt +8 -0
- hspf/hbn.py +487 -0
- hspf/helpers.py +94 -0
- hspf/hspfModel.py +203 -0
- hspf/parser/__init__.py +6 -0
- hspf/parser/graph.py +934 -0
- hspf/parser/parsers.py +516 -0
- hspf/reports.py +1230 -0
- hspf/uci.py +643 -0
- hspf/wdm.py +355 -0
- hspf/wdmReader.py +588 -0
- hspf-2.0.0.dist-info/METADATA +19 -0
- hspf-2.0.0.dist-info/RECORD +34 -0
- hspf-2.0.0.dist-info/WHEEL +4 -0
hspf/reports.py
ADDED
|
@@ -0,0 +1,1230 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Created on Mon Apr 11 08:26:04 2022
|
|
4
|
+
|
|
5
|
+
@author: mfratki
|
|
6
|
+
"""
|
|
7
|
+
import numpy as np
|
|
8
|
+
import pandas as pd
|
|
9
|
+
from pyhspf import helpers
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
#timeseries_catalog = pd.read_csv(Path(__file__).parent/'TIMESERIES_CATALOG.csv')
|
|
13
|
+
|
|
14
|
+
#ts_catalog = pd.read_csv('C:/Users/mfratki/Documents/GitHub/hspf_tools/parser/TIMESERIES_CATALOG.csv')
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Reports():
|
|
18
|
+
def __init__(self,uci,hbns,wdms):
|
|
19
|
+
self.hbns = hbns
|
|
20
|
+
self.uci = uci
|
|
21
|
+
self.wdms = wdms
|
|
22
|
+
|
|
23
|
+
#Sediment Reports
|
|
24
|
+
def scour(self,start_year = '1996',end_year = '2030'):
|
|
25
|
+
return scour(self.hbns,self.uci,start_year = start_year,end_year=end_year)
|
|
26
|
+
|
|
27
|
+
# Hydrology Reports
|
|
28
|
+
def landcover_area(self):
|
|
29
|
+
return landcover_areas(self.uci)
|
|
30
|
+
|
|
31
|
+
def annual_water_budget(self,operation):
|
|
32
|
+
assert operation in ['PERLND','RCHRES','IMPLND']
|
|
33
|
+
if operation =='PERLND':
|
|
34
|
+
return annual_perlnd_water_budget(self.uci,self.hbns)
|
|
35
|
+
elif operation == 'IMPLND':
|
|
36
|
+
return annual_implnd_water_budget(self.uci,self.hbns)
|
|
37
|
+
else:
|
|
38
|
+
return annual_reach_water_budget(self.uci,self.hbns)
|
|
39
|
+
|
|
40
|
+
# def annual_runoff(self):
|
|
41
|
+
# #assert operation in ['PERLND','IMPLND']
|
|
42
|
+
# #if operation == 'PERLND':
|
|
43
|
+
# return annual_perlnd_runoff(self.uci,self.hbns)
|
|
44
|
+
# #else:
|
|
45
|
+
# # raise NotImplementedError()
|
|
46
|
+
|
|
47
|
+
# def monthly_runoff(self,landcover=None):
|
|
48
|
+
# df = monthly_perlnd_runoff(self.uci,self.hbns).unstack().T
|
|
49
|
+
# if landcover is None:
|
|
50
|
+
# return df
|
|
51
|
+
# else:
|
|
52
|
+
# return df.loc[landcover]
|
|
53
|
+
|
|
54
|
+
def annual_sediment_budget(self):
|
|
55
|
+
return annual_sediment_budget(self.uci,self.hbns)
|
|
56
|
+
|
|
57
|
+
def ann_avg_subwatershed_loading(self,constituent):
|
|
58
|
+
return ann_avg_subwatershed_loading(constituent,self.uci, self.hbns)
|
|
59
|
+
|
|
60
|
+
def ann_avg_watershed_loading(self,constituent,reach_ids):
|
|
61
|
+
landcovers = ann_avg_watershed_loading(constituent,reach_ids,self.uci, self.hbns, True)
|
|
62
|
+
total = ann_avg_watershed_loading(constituent,reach_ids,self.uci, self.hbns, False)
|
|
63
|
+
total.index = ['Total']
|
|
64
|
+
total = pd.concat([landcovers,total])
|
|
65
|
+
total['volume'] = total['area']*total[f'weighted_mean_{constituent}']
|
|
66
|
+
total['volume_percent'] = total['volume']/total.loc['Total','volume']*100
|
|
67
|
+
total['area_percent'] = total['area']/total.loc['Total','area']*100
|
|
68
|
+
total['share'] = total['volume_percent']/total['area_percent']
|
|
69
|
+
return total
|
|
70
|
+
|
|
71
|
+
# def monthly_avg_subwatershed_loading(self,constituent,month):
|
|
72
|
+
# return monthly_avg_subwatershed_loading(constituent,month,self.uci, self.hbns)
|
|
73
|
+
|
|
74
|
+
# def monthly_avg_watershed_loading(self,constituent,reach_ids,month,by_landcover = True):
|
|
75
|
+
# return monthly_avg_watershed_loading(constituent,reach_ids,month,self.uci, self.hbns,by_landcover = by_landcover)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def ann_avg_yield(self,constituent,reach_ids):
|
|
79
|
+
df= avg_ann_yield(self.uci,self.hbns,constituent,reach_ids)
|
|
80
|
+
return df
|
|
81
|
+
|
|
82
|
+
def annual_precip(self):
|
|
83
|
+
return avg_annual_precip(self.uci,self.wdms)
|
|
84
|
+
|
|
85
|
+
# def water_balance(self,reach_ids = None):
|
|
86
|
+
# if reach_ids is None:
|
|
87
|
+
# reach_ids = self.uci.network.outlets()
|
|
88
|
+
# return water_balance(self.uci,self.hbns,self.wdms,reach_ids)
|
|
89
|
+
|
|
90
|
+
def simulated_et(self):
|
|
91
|
+
return simulated_et(self.uci,self.hbns)
|
|
92
|
+
|
|
93
|
+
# def inflows(self):
|
|
94
|
+
# return inflows(self.uci,self.wdms)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
#%% Channel Reports
|
|
100
|
+
def scour(hbn,uci,start_year = '1996',end_year = '2030'):
|
|
101
|
+
# Should eventually create an entire reports module or class indorder to calculate all of the different model checks
|
|
102
|
+
# TODO: Incorporate IMPLNDS
|
|
103
|
+
schematic = uci.table('SCHEMATIC').copy()
|
|
104
|
+
schematic = schematic.astype({'TVOLNO': int, "SVOLNO": int, 'AFACTR':float})
|
|
105
|
+
schematic = schematic[(schematic['SVOL'] == 'PERLND') | (schematic['SVOL'] == 'IMPLND')]
|
|
106
|
+
schematic = schematic[schematic['TVOL'] == 'RCHRES']
|
|
107
|
+
|
|
108
|
+
sosed = hbn.get_multiple_timeseries(t_opn = 'PERLND',
|
|
109
|
+
t_con = 'SOSED',
|
|
110
|
+
activity = 'SEDMNT',
|
|
111
|
+
t_code = 'yearly',
|
|
112
|
+
opnids = None)
|
|
113
|
+
sosed = sosed.loc[(sosed.index > start_year) & (sosed.index < end_year)].mean().rename('mean').to_frame()
|
|
114
|
+
|
|
115
|
+
sosld = hbn.get_multiple_timeseries(t_opn = 'IMPLND',
|
|
116
|
+
t_con = 'SOSLD',
|
|
117
|
+
activity = 'SOLIDS',
|
|
118
|
+
t_code = 'yearly',
|
|
119
|
+
opnids = None)
|
|
120
|
+
sosld = sosld.loc[(sosld.index > start_year) & (sosld.index < end_year)].mean().rename('mean').to_frame()
|
|
121
|
+
|
|
122
|
+
depscr = hbn.get_multiple_timeseries(t_opn = 'RCHRES',
|
|
123
|
+
t_con = 'DEPSCOURTOT',
|
|
124
|
+
activity = 'SEDTRN',
|
|
125
|
+
t_code = 'yearly',
|
|
126
|
+
opnids = None)
|
|
127
|
+
depscr = depscr.loc[(depscr.index > start_year) & (depscr.index < end_year)].mean().rename('mean').to_frame()
|
|
128
|
+
|
|
129
|
+
lakeflag = uci.table('RCHRES','GEN-INFO').copy()[['RCHID','LKFG']]
|
|
130
|
+
|
|
131
|
+
scour_report = []
|
|
132
|
+
# schematic block will have all the possible perlands while sosed only has perlands that were simulated
|
|
133
|
+
# in other words information from sosed is a subset of schematic
|
|
134
|
+
for tvolno in lakeflag.index: #schematic['TVOLNO'].unique():
|
|
135
|
+
reach_load = depscr.loc[tvolno].values[0]
|
|
136
|
+
schem_sub = schematic[schematic['TVOLNO'] == tvolno]
|
|
137
|
+
if len(schem_sub) == 0:
|
|
138
|
+
scour_report.append((tvolno,np.nan,reach_load))
|
|
139
|
+
else:
|
|
140
|
+
#Only consider perlands that wer actually simulated in the model (binary flag in set to 0)
|
|
141
|
+
# Calculate contributions from PERLNDS
|
|
142
|
+
if 'PERLND' in schem_sub['SVOL'].values:
|
|
143
|
+
schem_prlnd = schem_sub[schem_sub['SVOL'] == 'PERLND'].copy()
|
|
144
|
+
sosed_match = [x for x in schem_prlnd['SVOLNO'] if x in sosed.index]
|
|
145
|
+
schem_prlnd = schem_prlnd[schem_prlnd['SVOLNO'].isin(sosed_match)]
|
|
146
|
+
sosed_sub = sosed.loc[sosed_match]
|
|
147
|
+
prlnd_load = np.sum(schem_prlnd['AFACTR'].values*sosed_sub['mean'].values)#lb/yr
|
|
148
|
+
|
|
149
|
+
# Calculate contributions from IMPLNDS
|
|
150
|
+
if 'IMPLND' in schem_sub['SVOL'].values:
|
|
151
|
+
schem_implnd = schem_sub[schem_sub['SVOL'] == 'IMPLND'].copy()
|
|
152
|
+
sosld_match = [x for x in schem_implnd['SVOLNO'] if x in sosld.index]
|
|
153
|
+
schem_implnd = schem_implnd[schem_implnd['SVOLNO'].isin(sosld_match)]
|
|
154
|
+
sosld_sub = sosld.loc[sosld_match]
|
|
155
|
+
implnd_load = np.sum(schem_implnd['AFACTR'].values*sosld_sub['mean'].values)#lb/yr
|
|
156
|
+
|
|
157
|
+
watershed_load = prlnd_load + implnd_load
|
|
158
|
+
scour_report.append((tvolno,watershed_load,reach_load))
|
|
159
|
+
|
|
160
|
+
scour_report = pd.DataFrame(scour_report,columns = ['TVOLNO','nonpoint','depscour'])
|
|
161
|
+
|
|
162
|
+
scour_report['ratio'] = scour_report['nonpoint']/(scour_report['nonpoint']+np.abs(scour_report['depscour']))
|
|
163
|
+
|
|
164
|
+
scour_report = pd.merge(lakeflag, scour_report, left_index=True, right_on='TVOLNO').set_index('TVOLNO')
|
|
165
|
+
return scour_report
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def get_catchments(uci,reach_ids):
|
|
169
|
+
# Grab metadata information
|
|
170
|
+
subwatersheds = uci.network.subwatersheds().loc[reach_ids].reset_index()
|
|
171
|
+
landcover = subwatersheds.set_index('SVOL').loc['PERLND',:].set_index('SVOLNO')
|
|
172
|
+
landcover = landcover.join(uci.opnid_dict['PERLND'])
|
|
173
|
+
landcover = landcover[['AFACTR','LSID','metzone','TVOLNO','MLNO']]
|
|
174
|
+
landcover['AFACTR'] = landcover['AFACTR'].replace(0,pd.NA)
|
|
175
|
+
return landcover
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
#%% Catchment Loading (ie. Direct contributions from perlnds/implnds, no losses)
|
|
179
|
+
# Q
|
|
180
|
+
# Subwatershed Weighted Mean Timeseries Output
|
|
181
|
+
# operation = 'PERLND'
|
|
182
|
+
# ts_name = 'PERO',
|
|
183
|
+
# time_code = 5
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
LOADING_MAP = {'Q' : [{'t_opn':'PERLND',
|
|
187
|
+
't_con': 'PERO',
|
|
188
|
+
't_code': 'yearly',
|
|
189
|
+
'activity': 'PWATER'}],
|
|
190
|
+
'TSS': [{'t_opn':'PERLND',
|
|
191
|
+
't_con': 'SOSED',
|
|
192
|
+
't_code': 'yearly',
|
|
193
|
+
'activity': 'SEDMNT'},
|
|
194
|
+
{'t_opn':'IMPLND',
|
|
195
|
+
't_con': 'SOSED',
|
|
196
|
+
't_code': 'yearly',
|
|
197
|
+
'activity': 'SEDMNT'}]}
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
# def annual_average_subwatershed_loading(constituent,uci,hbn,reach_ids):
|
|
201
|
+
# '''
|
|
202
|
+
|
|
203
|
+
# For each subwatershed the annual average loading rate
|
|
204
|
+
|
|
205
|
+
# For each subwatershed the average loading rate for a specific month
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
# '''
|
|
209
|
+
|
|
210
|
+
def avg_subwatershed_loading(constituent,t_code,uci,hbn):
|
|
211
|
+
dfs = []
|
|
212
|
+
for t_opn in ['PERLND','IMPLND']:
|
|
213
|
+
t_cons = helpers.get_tcons(constituent,t_opn,'lb')
|
|
214
|
+
df = sum([hbn.get_multiple_timeseries(t_opn=t_opn,
|
|
215
|
+
t_con= t_con,
|
|
216
|
+
t_code = t_code) for t_con in t_cons])
|
|
217
|
+
if constituent == 'TSS':
|
|
218
|
+
df*2000
|
|
219
|
+
|
|
220
|
+
df = df.T.reset_index()
|
|
221
|
+
df.loc[:,'SVOL'] = t_opn
|
|
222
|
+
df = df.rename(columns = {'index':'OPNID'})
|
|
223
|
+
dfs.append(df)
|
|
224
|
+
|
|
225
|
+
df = pd.concat(dfs)
|
|
226
|
+
df.set_index(['SVOL','OPNID'],inplace=True)
|
|
227
|
+
|
|
228
|
+
subwatersheds = uci.network.subwatersheds()
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
loading_rates = []
|
|
233
|
+
for catchment_id in set(subwatersheds.index):
|
|
234
|
+
subwatershed = subwatersheds.loc[catchment_id].set_index(['SVOL','SVOLNO'])
|
|
235
|
+
loading_rates.append(df.loc[subwatershed.index].sum().agg(agg_func)/subwatershed['AFACTR'].sum())
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def weighted_describe(df, value_col, weight_col):
|
|
241
|
+
weighted_mean = (df[value_col] * df[weight_col]).sum() / df[weight_col].sum()
|
|
242
|
+
weighted_var = ((df[value_col] - weighted_mean) ** 2 * df[weight_col]).sum() / df[weight_col].sum()
|
|
243
|
+
weighted_std = np.sqrt(weighted_var)
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
return pd.DataFrame({
|
|
247
|
+
'area' : df[weight_col].sum(),
|
|
248
|
+
f'weighted_mean_{value_col}': [weighted_mean],
|
|
249
|
+
f'weighted_std_{value_col}': [weighted_std]})
|
|
250
|
+
# 'min': [df[value_col].min()],
|
|
251
|
+
# 'max': [df[value_col].max()]
|
|
252
|
+
# })
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def monthly_avg_constituent_loading(constituent,uci,hbn):
|
|
256
|
+
dfs = []
|
|
257
|
+
for t_opn in ['PERLND','IMPLND']:
|
|
258
|
+
t_cons = helpers.get_tcons(constituent,t_opn,'lb')
|
|
259
|
+
df = sum([hbn.get_multiple_timeseries(t_opn=t_opn,
|
|
260
|
+
t_con= t_con,
|
|
261
|
+
t_code = 'monthly') for t_con in t_cons])
|
|
262
|
+
df = df.groupby(df.index.month).mean().T.reset_index()
|
|
263
|
+
if constituent == 'TSS':
|
|
264
|
+
df*2000
|
|
265
|
+
|
|
266
|
+
df.loc[:,'SVOL'] = t_opn
|
|
267
|
+
df = df.rename(columns = {'index':'OPNID'})
|
|
268
|
+
dfs.append(df)
|
|
269
|
+
|
|
270
|
+
df = pd.concat(dfs)
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
subwatersheds = uci.network.subwatersheds().reset_index()
|
|
274
|
+
|
|
275
|
+
df = pd.merge(subwatersheds,df,left_on = ['SVOL','SVOLNO'], right_on=['SVOL','OPNID'],how='left')
|
|
276
|
+
return df
|
|
277
|
+
|
|
278
|
+
def monthly_avg_subwatershed_loading(constituent,month,uci,hbn):
|
|
279
|
+
df = monthly_avg_constituent_loading(constituent,uci,hbn)
|
|
280
|
+
df = df.groupby(df['TVOLNO'])[[month,'AFACTR']].apply(lambda x: weighted_describe(x,month,'AFACTR')).droplevel(1)
|
|
281
|
+
return df
|
|
282
|
+
|
|
283
|
+
def monthly_avg_watershed_loading(constituent,reach_ids,month,uci,hbn, by_landcover = False):
|
|
284
|
+
df = monthly_avg_constituent_loading(constituent,uci,hbn)
|
|
285
|
+
df = df.loc[df['TVOLNO'].isin(reach_ids)]
|
|
286
|
+
if by_landcover:
|
|
287
|
+
df = df.groupby(df['LSID'])[[month,'AFACTR']].apply(lambda x: weighted_describe(x,month,'AFACTR')).droplevel(1)
|
|
288
|
+
else:
|
|
289
|
+
|
|
290
|
+
df = weighted_describe(df,month,'AFACTR')
|
|
291
|
+
|
|
292
|
+
return df
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def ann_avg_constituent_loading(constituent,uci,hbn):
|
|
296
|
+
|
|
297
|
+
if constituent == 'TP':
|
|
298
|
+
df = total_phosphorous(uci,hbn,5).mean().reset_index()
|
|
299
|
+
df.loc[:,'OPN'] = 'PERLND'
|
|
300
|
+
df.columns = ['OPNID',constituent,'SVOL']
|
|
301
|
+
|
|
302
|
+
else:
|
|
303
|
+
dfs = []
|
|
304
|
+
for t_opn in ['PERLND','IMPLND']:
|
|
305
|
+
t_cons = helpers.get_tcons(constituent,t_opn)
|
|
306
|
+
df = sum([hbn.get_multiple_timeseries(t_opn=t_opn,
|
|
307
|
+
t_con= t_con,
|
|
308
|
+
t_code = 'yearly') for t_con in t_cons]).mean().reset_index()
|
|
309
|
+
df.loc[:,'OPN'] = t_opn
|
|
310
|
+
df.columns = ['OPNID',constituent,'SVOL']
|
|
311
|
+
dfs.append(df)
|
|
312
|
+
|
|
313
|
+
df = pd.concat(dfs)
|
|
314
|
+
if constituent == 'TSS':
|
|
315
|
+
df[constituent] = df[constituent]*2000
|
|
316
|
+
|
|
317
|
+
subwatersheds = uci.network.subwatersheds().reset_index()
|
|
318
|
+
|
|
319
|
+
df = pd.merge(subwatersheds,df,left_on = ['SVOL','SVOLNO'], right_on=['SVOL','OPNID'],how='left')
|
|
320
|
+
return df
|
|
321
|
+
|
|
322
|
+
def ann_avg_subwatershed_loading(constituent,uci,hbn):
|
|
323
|
+
df = ann_avg_constituent_loading(constituent,uci,hbn)
|
|
324
|
+
df = df.groupby(df['TVOLNO'])[[constituent,'AFACTR']].apply(lambda x: weighted_describe(x,constituent,'AFACTR')).droplevel(1)
|
|
325
|
+
return df
|
|
326
|
+
|
|
327
|
+
def ann_avg_watershed_loading(constituent,reach_ids,uci,hbn, by_landcover = False):
|
|
328
|
+
df = ann_avg_constituent_loading(constituent,uci,hbn)
|
|
329
|
+
df = df.loc[df['TVOLNO'].isin(reach_ids)]
|
|
330
|
+
if by_landcover:
|
|
331
|
+
df = df.groupby(df['LSID'])[[constituent,'AFACTR']].apply(lambda x: weighted_describe(x,constituent,'AFACTR')).droplevel(1)
|
|
332
|
+
else:
|
|
333
|
+
|
|
334
|
+
df = weighted_describe(df,constituent,'AFACTR')
|
|
335
|
+
|
|
336
|
+
return df
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
# ds = xr.
|
|
341
|
+
# coords = ['time']
|
|
342
|
+
# dims = ['operation','activity','opnid','time_step','time','catchment_id']
|
|
343
|
+
# def _insert_col(col_name,value,df):
|
|
344
|
+
# if col_name not in df.columns:
|
|
345
|
+
# df.insert(0,col_name,value)
|
|
346
|
+
|
|
347
|
+
# dfs = []
|
|
348
|
+
# for hbn in hbns.hbns:
|
|
349
|
+
# for key, df in hbn.data_frames.items():
|
|
350
|
+
# operation,activity,opnid,t_code = key.split('_')
|
|
351
|
+
# t_code = int(t_code)
|
|
352
|
+
# opnid = int(opnid)
|
|
353
|
+
# df = hbn.data_frames[key]
|
|
354
|
+
# df.index.name = 'date'
|
|
355
|
+
# df.index = df.index.tz_localize(None)
|
|
356
|
+
# _insert_col('t_code',t_code,df)
|
|
357
|
+
# _insert_col('OPNID',opnid,df)
|
|
358
|
+
# _insert_col('activity',activity,df)
|
|
359
|
+
# df = df.reset_index().set_index(['date','OPNID','t_code','activity'])
|
|
360
|
+
# dfs.append(xr.Dataset.from_dataframe(df))
|
|
361
|
+
|
|
362
|
+
# ds = xr.merge(dfs)
|
|
363
|
+
|
|
364
|
+
# query = {
|
|
365
|
+
# 'date': (142.41, 142.51),
|
|
366
|
+
# 'y': (-32.22, -32.32),
|
|
367
|
+
# 'time': ('2015-01-01', '2016-12-31'),
|
|
368
|
+
# 'measurements': ['nbart_nir', 'fmask'],
|
|
369
|
+
# 'output_crs': 'EPSG:3577',
|
|
370
|
+
# 'resolution': (-30, 30)
|
|
371
|
+
# }
|
|
372
|
+
|
|
373
|
+
# dfs = []
|
|
374
|
+
# for activity, ts_names in hbn.output_names().items():
|
|
375
|
+
# dfs
|
|
376
|
+
|
|
377
|
+
# for hbn in hbn.hbns: data_frames['PERLND_SEDMNT_201_5']
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
# time_steps = [2,3,4,5]
|
|
381
|
+
# operations = ['PERLND','IMPLND','RCHRES']
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
# # def flow_loading(uci,hbn,reach_ids,time_step='yearly',weighted = True):
|
|
386
|
+
|
|
387
|
+
# t_con = 'PERO'
|
|
388
|
+
# t_opn = 'PERLND'
|
|
389
|
+
# time_step = 'yearly'
|
|
390
|
+
# activity = 'PWATER'
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
#def total_phosphorous_loading:
|
|
395
|
+
# def phosphorous_loading(uci,hbns,reach_ids,time_tep = 'yearly'):
|
|
396
|
+
# catchments = get_catchments(uci,reach_ids)
|
|
397
|
+
# df = total_phosphorous(uci,hbns)
|
|
398
|
+
|
|
399
|
+
# subwatershed = uci.network.subwatershed(reach_id)
|
|
400
|
+
# perlnds = subwatershed.loc[subwatershed['SVOL'] == 'PERLND']
|
|
401
|
+
# perlnds = perlnds.set_index('SVOLNO').drop_duplicates()
|
|
402
|
+
# mlno = subwatershed.loc[subwatershed['SVOL'] == 'PERLND','MLNO'].iloc[0]
|
|
403
|
+
# total = total_phosphorous(uci,hbn,mlno,t_code,perlnds.index)
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
#%% Landscape Yields
|
|
409
|
+
|
|
410
|
+
def yield_flow(uci,hbn,constituent,reach_id):
|
|
411
|
+
hbn.get_rchres_data('Q',reach_id,'cfs','yearly')/uci.network.drainage_area(reach_id)
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
def yield_sediment(uci,hbn,constituent,reach_id):
|
|
415
|
+
hbn.get_rchres_data('TSS',reach_id,'lb','yearly').mean()*2000/uci.network.drainage_area(reach_id)
|
|
416
|
+
|
|
417
|
+
def avg_ann_yield(uci,hbn,constituent,reach_ids):
|
|
418
|
+
#reach_ids = uci.network.G.nodes
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
_reach_ids = [uci.network._upstream(reach) for reach in reach_ids]
|
|
422
|
+
_reach_ids = list(set([num for row in _reach_ids for num in row]))
|
|
423
|
+
subwatersheds = uci.network.subwatersheds().loc[_reach_ids]
|
|
424
|
+
area = subwatersheds['AFACTR'].sum()
|
|
425
|
+
|
|
426
|
+
if constituent == 'Q':
|
|
427
|
+
units = 'acrft'
|
|
428
|
+
else:
|
|
429
|
+
units = 'lb'
|
|
430
|
+
|
|
431
|
+
df = hbn.get_reach_constituent(constituent,reach_ids,5,unit =units).mean() # Gross
|
|
432
|
+
|
|
433
|
+
return df/area
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
#%% Allocations
|
|
437
|
+
allocation_selector = {'Q': {'input': ['IVOL'],
|
|
438
|
+
'output': ['ROVOL']},
|
|
439
|
+
'TP': {'input': ['PTOTIN'],
|
|
440
|
+
'output': ['PTOTOUT']},
|
|
441
|
+
'TSS': {'input': ['ISEDTOT'],
|
|
442
|
+
'output': ['ROSEDTOT']},
|
|
443
|
+
'OP': {'input': ['PO4INDIS'],
|
|
444
|
+
'output': ['PO4OUTDIS']},
|
|
445
|
+
'N': {'input': ['NO3INTOT','NO2INTOT'],
|
|
446
|
+
'output': ['NO2OUTTOT','NO3OUTTOT']},
|
|
447
|
+
'TKN': {'input': [],
|
|
448
|
+
'output': ['TAMOUTTOT', 'NTOTORGOUT']}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
def fate(hbn,constituent,t_code,reach_ids = None):
|
|
452
|
+
if constituent == 'Q':
|
|
453
|
+
fate_in = hbn.get_multiple_timeseries('RCHRES',t_code,'ROVOL',opnids=reach_ids)
|
|
454
|
+
fate_out = hbn.get_multiple_timeseries('RCHRES',t_code,'IVOL',opnids=reach_ids)
|
|
455
|
+
elif constituent == 'TP':
|
|
456
|
+
fate_in = hbn.get_multiple_timeseries('RCHRES',t_code,'PTOTOUT',opnids = reach_ids)
|
|
457
|
+
fate_out = hbn.get_multiple_timeseries('RCHRES',t_code,'PTOTIN',opnids = reach_ids)
|
|
458
|
+
elif constituent == 'TSS':
|
|
459
|
+
fate_in = hbn.get_multiple_timeseries('RCHRES',t_code,'ISEDTOT',opnids = reach_ids)
|
|
460
|
+
fate_out = hbn.get_multiple_timeseries('RCHRES',t_code,'ROSEDTOT',opnids = reach_ids)
|
|
461
|
+
return fate_out/fate_in
|
|
462
|
+
|
|
463
|
+
def loading(uci,hbn,constituent,t_code = 5):
|
|
464
|
+
if constituent =='TP':
|
|
465
|
+
loads = total_phosphorous(uci,hbn,t_code=t_code)
|
|
466
|
+
else:
|
|
467
|
+
#dfs = []
|
|
468
|
+
# df_implnd = hbn.get_implnd_constituent(constituent,t_code,'lb').T.reset_index().rename(columns = {'index':'OPNID'})
|
|
469
|
+
# df_implnd['SVOL'] = 'IMPLND'
|
|
470
|
+
|
|
471
|
+
loads = hbn.get_perlnd_constituent(constituent,t_code,'lb')
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
# .T.reset_index().rename(columns = {'index':'OPNID'})
|
|
475
|
+
# df_perlnd['SVOL'] = 'PERLND'
|
|
476
|
+
|
|
477
|
+
# df = pd.concat([df_perlnd,df_implnd])
|
|
478
|
+
# df.set_index(['SVOL','OPNID'],inplace=True)
|
|
479
|
+
|
|
480
|
+
if constituent == 'TSS':
|
|
481
|
+
loads = loads*2000
|
|
482
|
+
|
|
483
|
+
return loads
|
|
484
|
+
|
|
485
|
+
def subwatershed_loading(uci,hbn,constituent,t_code,group_landcover = True,as_load = True):
|
|
486
|
+
loads = loading(uci,hbn,constituent,t_code)
|
|
487
|
+
|
|
488
|
+
subwatersheds = uci.network.subwatersheds()
|
|
489
|
+
perlnds = subwatersheds.loc[subwatersheds['SVOL'] == 'PERLND'].reset_index()
|
|
490
|
+
|
|
491
|
+
total = loads[perlnds['SVOLNO'].to_list()]
|
|
492
|
+
total = total.mul(perlnds['AFACTR'].values,axis=1)
|
|
493
|
+
total = total.transpose()
|
|
494
|
+
total['reach_id'] = perlnds['TVOLNO'].values
|
|
495
|
+
total['landcover'] = uci.table('PERLND','GEN-INFO').loc[total.index,'LSID'].to_list()
|
|
496
|
+
total['area'] = perlnds['AFACTR'].to_list() #perlnds.loc[total.index,'AFACTR'].to_list()
|
|
497
|
+
total = total.reset_index().set_index(['index','landcover','area','reach_id']).transpose()
|
|
498
|
+
total.columns.names = ['perlnd_id','landcover','area','reach_id']
|
|
499
|
+
|
|
500
|
+
if group_landcover:
|
|
501
|
+
total.columns = total.columns.droplevel(['landcover','perlnd_id'])
|
|
502
|
+
total = total.T.reset_index().groupby('reach_id').sum().reset_index().set_index(['reach_id','area']).T
|
|
503
|
+
|
|
504
|
+
if not as_load:
|
|
505
|
+
total = total.div(total.columns.get_level_values('area').values,axis=1)
|
|
506
|
+
|
|
507
|
+
total.index = pd.to_datetime(total.index)
|
|
508
|
+
return total
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
def losses(uci,hbn,constituent, t_code = 5):
|
|
512
|
+
upstream_reachs = {reach_id: uci.network.upstream(reach_id) for reach_id in uci.network.get_node_type_ids('RCHRES')}
|
|
513
|
+
totout = sum([hbn.get_multiple_timeseries('RCHRES',
|
|
514
|
+
t_code,
|
|
515
|
+
t_cons,
|
|
516
|
+
opnids = list(upstream_reachs.keys()))
|
|
517
|
+
for t_cons in allocation_selector[constituent]['output']])
|
|
518
|
+
|
|
519
|
+
totin = sum([hbn.get_multiple_timeseries('RCHRES',
|
|
520
|
+
t_code,
|
|
521
|
+
t_cons,
|
|
522
|
+
opnids = list(upstream_reachs.keys()))
|
|
523
|
+
for t_cons in allocation_selector[constituent]['input']])
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
#totin = totout.copy().astype('Float64')
|
|
527
|
+
#totin[:] = pd.NA
|
|
528
|
+
|
|
529
|
+
for reach_id in totin.columns:
|
|
530
|
+
reach_ids = upstream_reachs[reach_id]
|
|
531
|
+
if len(reach_ids) > 0:
|
|
532
|
+
totin[reach_id] = totout[reach_ids].sum(axis=1)
|
|
533
|
+
|
|
534
|
+
#totin.columns = totout.columns
|
|
535
|
+
return (totout-totin)/totin*100
|
|
536
|
+
|
|
537
|
+
def allocations(uci,hbn,constituent,reach_id,t_code,group_landcover = True):
|
|
538
|
+
p = uci.network.paths(reach_id)
|
|
539
|
+
p[reach_id] = [reach_id]
|
|
540
|
+
loss = losses(uci,hbn,constituent,t_code)
|
|
541
|
+
loads = subwatershed_loading(uci,hbn,constituent,t_code,group_landcover = group_landcover)
|
|
542
|
+
loss_factors = pd.concat([loss[v].prod(axis=1) for k,v in p.items()],axis=1)
|
|
543
|
+
loss_factors.columns = list(p.keys())
|
|
544
|
+
allocations = loads.mul(loss_factors[loads.columns.get_level_values('reach_id')].values)
|
|
545
|
+
return allocations
|
|
546
|
+
|
|
547
|
+
|
|
548
|
+
def total_phosphorous_losses(uci,hbn,t_code = 5):
|
|
549
|
+
upstream_reachs = {reach_id: [reach_id] + uci.network.upstream(reach_id) for reach_id in uci.network.get_node_type_ids('RCHRES')}
|
|
550
|
+
ptotout = hbn.get_multiple_timeseries('RCHRES',t_code,'PTOTOUT',opnids = list(upstream_reachs.keys()))
|
|
551
|
+
ptotin = pd.concat([ptotout[reach_ids].sum(axis=1) for reach_id,reach_ids in upstream_reachs.items()],axis=1)
|
|
552
|
+
ptotin.columns = list(upstream_reachs.keys())
|
|
553
|
+
return 1-(ptotin-ptotout)/ptotin
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
def total_phosphorous_allocations(uci,hbn,reach_id,t_code=5,group_landcover = True):
|
|
557
|
+
p = uci.network.paths(reach_id)
|
|
558
|
+
p[reach_id] = [reach_id]
|
|
559
|
+
losses = total_phosphorous_losses(uci,hbn,t_code)
|
|
560
|
+
loads = subwatershed_total_phosphorous_loading(uci,hbn,t_code=t_code,group_landcover = group_landcover)
|
|
561
|
+
loss_factors = pd.concat([losses[v].prod(axis=1) for k,v in p.items()],axis=1)
|
|
562
|
+
loss_factors.columns = list(p.keys())
|
|
563
|
+
allocations = loads.mul(loss_factors[loads.columns.get_level_values('reach_id')].values)
|
|
564
|
+
return allocations
|
|
565
|
+
|
|
566
|
+
#loads[loads.index.get_level_values('reach_id').isin(loss_factors.columns)].mul(loss_factors.values,axis=1)
|
|
567
|
+
#return loads[loss_factors.columns].mul(loss_factors.values,axis=1)
|
|
568
|
+
|
|
569
|
+
|
|
570
|
+
def flow_allocations(uci,hbn,reach_id,t_code = 5):
|
|
571
|
+
raise NotImplementedError()
|
|
572
|
+
|
|
573
|
+
def total_suspended_sediment_allocations(uci,hbn,reach_id,t_code):
|
|
574
|
+
raise NotImplementedError()
|
|
575
|
+
|
|
576
|
+
#%% Water Balance
|
|
577
|
+
def pevt_balance(mod,operation,opnid):
|
|
578
|
+
extsources = mod.uci.table('EXT SOURCES')
|
|
579
|
+
|
|
580
|
+
pevt_dsn = mod.uci.get_dsns(operation,opnid,'PEVT').reset_index()
|
|
581
|
+
pevt_mfactor = extsources.loc[(extsources['TOPFST'] == opnid) &
|
|
582
|
+
(extsources['TVOL'] == operation) &
|
|
583
|
+
(extsources['SMEMN'] == 'PEVT'),'MFACTOR'].iat[0]
|
|
584
|
+
pevt = mod.wdms.series(pevt_dsn.loc[0,'FILENAME'],pevt_dsn.loc[0,'SVOLNO'])
|
|
585
|
+
|
|
586
|
+
prec_dsn = mod.uci.get_dsns(operation,opnid,'PREC').reset_index()
|
|
587
|
+
prec_mfactor = extsources.loc[(extsources['TOPFST'] == opnid) &
|
|
588
|
+
(extsources['TVOL'] == operation) &
|
|
589
|
+
(extsources['SMEMN'] == 'PREC'),'MFACTOR'].iat[0]
|
|
590
|
+
prec = mod.wdms.series(prec_dsn.loc[0,'FILENAME'],prec_dsn.loc[0,'SVOLNO'])
|
|
591
|
+
|
|
592
|
+
df = pd.concat([(prec*prec_mfactor).resample('Y').sum(),
|
|
593
|
+
(pevt*pevt_mfactor).resample('Y').sum()],axis=1)
|
|
594
|
+
df = df[df>0]
|
|
595
|
+
df.columns = ['PREC','PEVT']
|
|
596
|
+
return df
|
|
597
|
+
|
|
598
|
+
|
|
599
|
+
# #simulate ET from perlnds
|
|
600
|
+
# taet = hbn.get_multiple_timeseries(t_opn='PERLND',
|
|
601
|
+
# t_con='TAET',
|
|
602
|
+
# t_code = 'monthly',
|
|
603
|
+
# activity = 'PWATER')
|
|
604
|
+
|
|
605
|
+
# taet = taet.groupby(taet.index.month).mean()
|
|
606
|
+
|
|
607
|
+
# precip = hbn.get_multiple_timeseries(t_opn='PERLND',
|
|
608
|
+
# t_con='SUPY',
|
|
609
|
+
# t_code = 'monthly',
|
|
610
|
+
# activity = 'PWATER')
|
|
611
|
+
|
|
612
|
+
# precip = precip.groupby(precip.index.month).mean()
|
|
613
|
+
|
|
614
|
+
|
|
615
|
+
|
|
616
|
+
# df = (precip-taet).T.join(uci.opnid_dict['PERLND'])
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
# precip = cal.model.wdms.series('Nemadji_Met.wdm',1100)
|
|
621
|
+
# precip = precip.loc[precip >=0]
|
|
622
|
+
# pevt = cal.model.wdms.series('Nemadji_Met.wdm',711)
|
|
623
|
+
# pevt = pevt.loc[pevt >=0]
|
|
624
|
+
|
|
625
|
+
# taet['Operation'] = 'PERLND' # without specifying the opnid, it grabs them all.
|
|
626
|
+
# taet = taet.join(uci.network.operation_area('PERLND'))
|
|
627
|
+
# taet['PET'] = taet['EVAP']*taet['AFACTR']/12
|
|
628
|
+
# taet = taet.reset_index().rename(columns = {'index' : 'OPNID'})[['OPNID','Operation','PET']]
|
|
629
|
+
|
|
630
|
+
|
|
631
|
+
def simulated_et(uci,hbn):
|
|
632
|
+
|
|
633
|
+
|
|
634
|
+
#simulate ET from perlnds
|
|
635
|
+
taet = hbn.get_multiple_timeseries(t_opn='PERLND',
|
|
636
|
+
t_con='TAET',
|
|
637
|
+
t_code = 'yearly',
|
|
638
|
+
activity = 'PWATER').mean().to_frame().rename(columns = {0:'EVAP'})
|
|
639
|
+
taet['Operation'] = 'PERLND' # without specifying the opnid, it grabs them all.
|
|
640
|
+
taet = taet.join(uci.network.operation_area('PERLND'))
|
|
641
|
+
taet['PET'] = taet['EVAP']*taet['AFACTR']/12
|
|
642
|
+
taet = taet.reset_index().rename(columns = {'index' : 'OPNID'})[['OPNID','Operation','PET']]
|
|
643
|
+
|
|
644
|
+
#simulate ET from implnds
|
|
645
|
+
impev = hbn.get_multiple_timeseries(t_opn='IMPLND',
|
|
646
|
+
t_con='IMPEV',
|
|
647
|
+
t_code = 'yearly').mean().to_frame().rename(columns = {0:'EVAP'})
|
|
648
|
+
impev['Operation'] = 'IMPLND' # without specifying the opnid, it grabs them all.
|
|
649
|
+
impev = impev.join(uci.network.operation_area('IMPLND'))
|
|
650
|
+
impev['PET'] = impev['EVAP']*impev['AFACTR']/12
|
|
651
|
+
impev = impev.reset_index().rename(columns = {'index' : 'OPNID'})[['OPNID','Operation','PET']]
|
|
652
|
+
|
|
653
|
+
# sum of agwo for each perlnd
|
|
654
|
+
volev = hbn.get_multiple_timeseries(t_opn='RCHRES', t_con='VOLEV', t_code = 'yearly').mean().to_frame().rename(columns = {0:'PET'})
|
|
655
|
+
volev['Operation'] = 'RCHRES'
|
|
656
|
+
volev = volev.reset_index().rename(columns = {'index' : 'OPNID'})
|
|
657
|
+
|
|
658
|
+
return pd.concat([taet,impev,volev])
|
|
659
|
+
|
|
660
|
+
|
|
661
|
+
|
|
662
|
+
def inflows(uci,wdm):
|
|
663
|
+
# External inflows
|
|
664
|
+
files = uci.table('FILES')
|
|
665
|
+
ext_sources = uci.table('EXT SOURCES')
|
|
666
|
+
|
|
667
|
+
ext_sources = ext_sources.loc[(ext_sources['TVOL'].isin(['PERLND','IMPLND','RCHRES']))]
|
|
668
|
+
ext_sources = ext_sources.merge(files, left_on = 'SVOL',
|
|
669
|
+
right_on= 'FTYPE',
|
|
670
|
+
how = 'left')
|
|
671
|
+
|
|
672
|
+
ext_sources = ext_sources[ext_sources['SMEMN'].isin(['ROVL','Flow'])]
|
|
673
|
+
|
|
674
|
+
if len(ext_sources) == 0:
|
|
675
|
+
inflows = pd.DataFrame(columns = ['OPNID','Operation','ROVL'])
|
|
676
|
+
else:
|
|
677
|
+
|
|
678
|
+
dsns = ext_sources[['SVOLNO','FILENAME']].drop_duplicates().reset_index(drop=True)
|
|
679
|
+
dfs = [wdm.wdms[row['FILENAME']].series(row['SVOLNO']) for index,row in dsns.iterrows()]
|
|
680
|
+
dsns['ROVL'] = pd.concat(dfs,axis=1).resample('Y').sum().mean()
|
|
681
|
+
|
|
682
|
+
|
|
683
|
+
inflows = ext_sources.merge(dsns,left_on='SVOLNO',
|
|
684
|
+
right_on = 'SVOLNO')[['TOPFST','TVOL','ROVL']].rename(columns = {'TOPFST':'OPNID','TVOL':'Operation'})
|
|
685
|
+
return inflows
|
|
686
|
+
|
|
687
|
+
def water_balance(uci,hbn,wdm,reach_ids):
|
|
688
|
+
|
|
689
|
+
areas = []
|
|
690
|
+
for operation in ['PERLND','IMPLND','RCHRES']:
|
|
691
|
+
area = uci.network.operation_area(operation).reset_index()
|
|
692
|
+
area.loc[:,'Operation'] = operation
|
|
693
|
+
areas.append(area)
|
|
694
|
+
areas = pd.concat(areas).set_index(['Operation','SVOLNO'])
|
|
695
|
+
areas.index.names = ['Operation','OPNID']
|
|
696
|
+
|
|
697
|
+
#areas = pd.concat([uci.network.operation_area(operation) for operation in ['PERLND','IMPLND','RCHRES']])
|
|
698
|
+
|
|
699
|
+
pets = simulated_et(uci,hbn)
|
|
700
|
+
_inflows = inflows(uci,wdm)
|
|
701
|
+
precips = avg_annual_precip(uci,wdm)
|
|
702
|
+
precips = precips.set_index(['Operation','OPNID']).join(areas)
|
|
703
|
+
precips['PREC'] = precips['avg_ann_prec'] / 12 * precips['AFACTR']
|
|
704
|
+
precips.reset_index(inplace=True)
|
|
705
|
+
#outlets = uci.network.outlets()
|
|
706
|
+
rovols = hbn.get_multiple_timeseries(opnids = reach_ids,t_opn='RCHRES', t_con='ROVOL', t_code = 'yearly').mean().to_frame()
|
|
707
|
+
#igwi = hbn.get_multiple_timeseries(t_opn='PERLND', t_con='IGWI', t_code = 'yearly').mean().to_frame()
|
|
708
|
+
#igwi = igwi.join(areas['PERLND'])
|
|
709
|
+
#igwi = igwi[0]/ 12 * igwi['AFACTR']
|
|
710
|
+
|
|
711
|
+
rows = []
|
|
712
|
+
for outlet in reach_ids:
|
|
713
|
+
precip = 0
|
|
714
|
+
inflow = 0
|
|
715
|
+
pet = 0
|
|
716
|
+
for operation in ['PERLND','IMPLND','RCHRES']:
|
|
717
|
+
opnids = uci.network.get_opnids(operation,outlet)
|
|
718
|
+
precip = precip + precips.loc[(precips['Operation'] == operation) & (precips['OPNID'].isin(opnids))]['PREC'].sum()
|
|
719
|
+
inflow = inflow + _inflows.loc[(_inflows['Operation'] == operation) & (_inflows['OPNID'].isin(opnids))]['ROVL'].sum()
|
|
720
|
+
pet = pet + pets.loc[(pets['Operation'] == operation) & (pets['OPNID'].isin(opnids))]['PET'].sum()
|
|
721
|
+
rovol = rovols.loc[outlet].sum()
|
|
722
|
+
balance = ((precip-pet)-(rovol - inflow))/(precip-pet)*100
|
|
723
|
+
|
|
724
|
+
rows.append([outlet,precip,inflow,pet,rovol,balance])
|
|
725
|
+
return pd.DataFrame(rows,columns = ['reach_id','precip','inflow','saet','rovol','balance'])
|
|
726
|
+
|
|
727
|
+
|
|
728
|
+
def meteorlogical(uci,wdm,operation,ts_name,time_step = 'Y',opnids = None,):
|
|
729
|
+
files = uci.table('FILES')
|
|
730
|
+
files['FTYPE'].replace('WDM','WDM1',inplace=True)
|
|
731
|
+
|
|
732
|
+
# Total preciptiation
|
|
733
|
+
ext_sources = uci.table('EXT SOURCES')
|
|
734
|
+
ext_sources['SVOL'].replace('WDM','WDM1',inplace=True)
|
|
735
|
+
ext_sources = ext_sources.loc[(ext_sources['TVOL'] == operation) & (ext_sources['SMEMN'] == ts_name)]
|
|
736
|
+
ext_sources = ext_sources.merge(files, left_on = 'SVOL',
|
|
737
|
+
right_on= 'FTYPE',
|
|
738
|
+
how = 'left')
|
|
739
|
+
|
|
740
|
+
dsns = ext_sources[['SVOLNO','FILENAME']].drop_duplicates().reset_index(drop=True)
|
|
741
|
+
dfs = [wdm.wdms[row['FILENAME']].series(row['SVOLNO']) for index,row in dsns.iterrows()]
|
|
742
|
+
dfs = [df.loc[df>=0] for df in dfs]
|
|
743
|
+
df = pd.concat(dfs,axis=1).resample(time_step).sum()
|
|
744
|
+
df.columns = dsns['SVOLNO']
|
|
745
|
+
|
|
746
|
+
df = df[ext_sources['SVOLNO']]
|
|
747
|
+
df.columns = ext_sources['TOPFST']
|
|
748
|
+
|
|
749
|
+
if opnids is not None:
|
|
750
|
+
df = df[opnids]
|
|
751
|
+
|
|
752
|
+
return df
|
|
753
|
+
|
|
754
|
+
|
|
755
|
+
def avg_annual_precip(uci,wdm):
|
|
756
|
+
#assert(var in ['PREC','WIND','PEVT','ATEM','DEWP','CLOU','SOLAR',])
|
|
757
|
+
# average annual precipitation across for each PERLND, IMPLND, and Reach
|
|
758
|
+
|
|
759
|
+
|
|
760
|
+
|
|
761
|
+
files = uci.table('FILES')
|
|
762
|
+
files['FTYPE'].replace('WDM','WDM1',inplace=True)
|
|
763
|
+
|
|
764
|
+
# Total preciptiation
|
|
765
|
+
ext_sources = uci.table('EXT SOURCES')
|
|
766
|
+
ext_sources['SVOL'].replace('WDM','WDM1',inplace=True)
|
|
767
|
+
ext_sources = ext_sources.loc[(ext_sources['TVOL'].isin(['PERLND','IMPLND','RCHRES'])) & (ext_sources['SMEMN'] == 'PREC')]
|
|
768
|
+
ext_sources = ext_sources.merge(files, left_on = 'SVOL',
|
|
769
|
+
right_on= 'FTYPE',
|
|
770
|
+
how = 'left')
|
|
771
|
+
|
|
772
|
+
dsns = ext_sources[['SVOLNO','FILENAME']].drop_duplicates().reset_index(drop=True)
|
|
773
|
+
dfs = [wdm.wdms[row['FILENAME']].series(row['SVOLNO']) for index,row in dsns.iterrows()]
|
|
774
|
+
dfs = [df.loc[df>=0] for df in dfs]
|
|
775
|
+
df = pd.concat(dfs,axis=1).resample('Y').sum().mean()
|
|
776
|
+
|
|
777
|
+
dsns['avg_ann_prec'] = pd.concat(dfs,axis=1).resample('Y').sum().mean()
|
|
778
|
+
df = ext_sources.merge(dsns,left_on = 'SVOLNO',
|
|
779
|
+
right_on = 'SVOLNO',
|
|
780
|
+
how = 'left')
|
|
781
|
+
df = df[['SVOLNO','TVOL','TOPFST','avg_ann_prec']]
|
|
782
|
+
df.rename(columns = {'SVOLNO':'DSN','TVOL':'Operation','TOPFST':'OPNID'}, inplace=True)
|
|
783
|
+
|
|
784
|
+
return df
|
|
785
|
+
|
|
786
|
+
|
|
787
|
+
|
|
788
|
+
|
|
789
|
+
|
|
790
|
+
|
|
791
|
+
#%%
|
|
792
|
+
#%%% Report Tablewater_s
|
|
793
|
+
|
|
794
|
+
|
|
795
|
+
def landcover_areas(uci):
|
|
796
|
+
df = uci.network.operation_area('PERLND').groupby('LSID').sum()
|
|
797
|
+
df['percent'] = 100*(df['AFACTR']/df['AFACTR'].sum())
|
|
798
|
+
return df
|
|
799
|
+
|
|
800
|
+
# def area_weighted_output(uci,hbn,ts_name,operation,time_step,opnids):
|
|
801
|
+
# assert(operation in ['PERLND','IMPLND'])
|
|
802
|
+
# df = hbn.get_multiple_timeseries(operation,5,ts_name,opnids = opnids).T
|
|
803
|
+
# df.index.name = 'SVOLNO'
|
|
804
|
+
# areas = uci.network.operation_area(operation)
|
|
805
|
+
# df = df.join(areas).reset_index().set_index(['SVOLNO','AFACTR','LSID'])
|
|
806
|
+
# df = df.T*df.index.get_level_values('AFACTR').values
|
|
807
|
+
|
|
808
|
+
# if grouped:
|
|
809
|
+
# df.columns.get_level_values('AFACTR').groupby(df.get_level_values['LSIDE'])
|
|
810
|
+
|
|
811
|
+
'''
|
|
812
|
+
Output for each PERLND
|
|
813
|
+
- Sometimes a rate
|
|
814
|
+
- Sometimes a mass or volume
|
|
815
|
+
|
|
816
|
+
- Group by Landcover no without weighting
|
|
817
|
+
- rate take the mean
|
|
818
|
+
- mass or volum us the sum
|
|
819
|
+
- Group by Landcover with weighting
|
|
820
|
+
- rate convert to mass/volume sum then divide by grouped area
|
|
821
|
+
- mass sum then divide by grouped area
|
|
822
|
+
|
|
823
|
+
|
|
824
|
+
Output for a catchment
|
|
825
|
+
- For a single catchment
|
|
826
|
+
- if timeseries is a rate
|
|
827
|
+
- rate is raw output
|
|
828
|
+
- mass/volume is rate * area of contributing operations
|
|
829
|
+
- if timeseries is a mass/volume
|
|
830
|
+
- rate is mass/volume / area of contributing operations
|
|
831
|
+
- mass/volume is raw output
|
|
832
|
+
- No ability to aggregate by Landcover
|
|
833
|
+
- For 2 or more catchments
|
|
834
|
+
- if weighted
|
|
835
|
+
- if timeseries is a rate
|
|
836
|
+
- rate is rate*area of contributing operations summed by landcover and divided by each landcover area
|
|
837
|
+
- mass/volume is rate*area summed by landcover and area
|
|
838
|
+
- if timeseries is a mass/volume
|
|
839
|
+
- rate is mass/volume summed by landcover and divided by landcover area
|
|
840
|
+
- mass/volume is mass/volume summed by landcover
|
|
841
|
+
- if not weighted
|
|
842
|
+
- if timeseries is a rate
|
|
843
|
+
- rate is the raw output of each catchment concatenated
|
|
844
|
+
- mass/volume is rate*area of each contributing landcover and concatenated for each catchment
|
|
845
|
+
- if timeseries is a mass/volume
|
|
846
|
+
- rate is mass/volume / area of each contributing landcover and concatenated for each catchment
|
|
847
|
+
- mass/volume is raw output of each chatchment concatenated
|
|
848
|
+
|
|
849
|
+
|
|
850
|
+
'''
|
|
851
|
+
|
|
852
|
+
# class Catchment:
|
|
853
|
+
# def __init__(reach_id,uci,hbn = None):
|
|
854
|
+
# id = reach_id
|
|
855
|
+
|
|
856
|
+
# def loading_rate(constituent):
|
|
857
|
+
|
|
858
|
+
# def loading(constituent):
|
|
859
|
+
|
|
860
|
+
# def yield(constituent):
|
|
861
|
+
|
|
862
|
+
# def load(constituent):
|
|
863
|
+
|
|
864
|
+
|
|
865
|
+
|
|
866
|
+
|
|
867
|
+
'''
|
|
868
|
+
The area of each landcategory in the catchment
|
|
869
|
+
|
|
870
|
+
Loading rate of each landuse (lb/acre/intvl)
|
|
871
|
+
TSS, TP, N, TKN, BOD, OP
|
|
872
|
+
|
|
873
|
+
Loading of from each landuse (lb/intvl)
|
|
874
|
+
TSS, TP, N, TKN, BOD, OP
|
|
875
|
+
|
|
876
|
+
Yield at the catchment outlet (lb/acr/intvl)
|
|
877
|
+
TSS, TP, N, TKN, BOD, OP
|
|
878
|
+
|
|
879
|
+
Load at the catchment outlet (lb/intvl)
|
|
880
|
+
TSS, TP, N, TKN, BOD, OP
|
|
881
|
+
|
|
882
|
+
In channel losses of a constituent (lb/intvl)
|
|
883
|
+
TSS, TP, N, TKN, BOD, OP
|
|
884
|
+
|
|
885
|
+
Allocation of a constituent from catchment to downstream catchment
|
|
886
|
+
TSS, TP, N, TKN, BOD, OP
|
|
887
|
+
|
|
888
|
+
|
|
889
|
+
|
|
890
|
+
|
|
891
|
+
'''
|
|
892
|
+
|
|
893
|
+
#reach_id = 103
|
|
894
|
+
#def make_catchment(reach_id,uci,hbn):
|
|
895
|
+
|
|
896
|
+
|
|
897
|
+
|
|
898
|
+
|
|
899
|
+
# class Reach:
|
|
900
|
+
|
|
901
|
+
|
|
902
|
+
# class Perlnd():
|
|
903
|
+
# def __init__(catchment_id,perlnd_id,area,mlno,landcover,metzone):
|
|
904
|
+
|
|
905
|
+
|
|
906
|
+
|
|
907
|
+
# # class Implnd:
|
|
908
|
+
# def annual_weighted_perlnd_output(uci,hbn,ts_name,t_code = 4,opnids = None):
|
|
909
|
+
|
|
910
|
+
# df = hbn.get_multiple_timeseries('PERLND',5,ts_name,opnids = opnids)
|
|
911
|
+
# subwatersheds = uci.network.subwatersheds().reset_index()
|
|
912
|
+
# subwatersheds = subwatersheds.loc[subwatersheds['SVOL'] == 'PERLND']
|
|
913
|
+
# df = df[subwatersheds['SVOLNO']].T
|
|
914
|
+
# df = pd.merge(df, subwatersheds, left_index = True, right_on='SVOLNO', how='inner')
|
|
915
|
+
# df = df.set_index(['TVOLNO','SVOL','SVOLNO','AFACTR','LSID','MLNO']).T
|
|
916
|
+
|
|
917
|
+
# def annual_weighted_output(ts_name,operation,opnids):
|
|
918
|
+
# assert(operation in ['PERLND','IMPLND'])
|
|
919
|
+
# subwatersheds = uci.network.subwatersheds()
|
|
920
|
+
# subwatersheds = subwatersheds.loc[subwatersheds['SVOL'] == operation].reset_index()
|
|
921
|
+
# df = cal.model.hbns.get_multiple_timeseries('PERLND',5,'PERO',test['SVOLNO'].values).mean().reset_index()
|
|
922
|
+
# df.columns = ['OPNID','value']
|
|
923
|
+
# df = pd.merge(subwatersheds,df,left_on = 'SVOLNO', right_on='OPNID')
|
|
924
|
+
# weighted_mean = df.groupby('TVOLNO').apply(lambda x: (x['value'] * x['AFACTR']).sum() / x['AFACTR'].sum())
|
|
925
|
+
|
|
926
|
+
|
|
927
|
+
def weighted_mean(df,value_col,weight_col):
|
|
928
|
+
weighted_mean = (df[value_col] * df[weight_col]).sum() / df[weight_col].sum()
|
|
929
|
+
return pd.DataFrame({
|
|
930
|
+
'AFACTR' : df[weight_col].sum(),
|
|
931
|
+
value_col: [weighted_mean]})
|
|
932
|
+
|
|
933
|
+
def annual_weighted_output(uci,hbn,ts_name,operation = 'PERLND',opnids = None,group_by = None):
|
|
934
|
+
assert (group_by in [None,'landcover','opnid'])
|
|
935
|
+
df = hbn.get_multiple_timeseries(operation,5,ts_name,opnids = opnids).mean().reset_index()
|
|
936
|
+
df.columns = ['SVOLNO',ts_name]
|
|
937
|
+
subwatersheds = uci.network.subwatersheds().reset_index()
|
|
938
|
+
subwatersheds = subwatersheds.loc[subwatersheds['SVOL'] == operation]
|
|
939
|
+
|
|
940
|
+
|
|
941
|
+
df = pd.merge(subwatersheds,df,left_on = 'SVOLNO', right_on='SVOLNO',how='left')
|
|
942
|
+
|
|
943
|
+
|
|
944
|
+
if group_by is None:
|
|
945
|
+
df = weighted_mean(df,ts_name,'AFACTR')
|
|
946
|
+
elif group_by == 'landcover':
|
|
947
|
+
df = df.groupby('LSID')[[ts_name,'AFACTR']].apply(lambda x: weighted_mean(x,ts_name,'AFACTR')).droplevel(1)
|
|
948
|
+
elif group_by == 'opnid':
|
|
949
|
+
df = df.groupby(df['SVOLNO'])[[ts_name,'AFACTR']].apply(lambda x: weighted_mean(x,ts_name,'AFACTR')).droplevel(1)
|
|
950
|
+
|
|
951
|
+
df = df.set_index([df.index,'AFACTR'])
|
|
952
|
+
return df
|
|
953
|
+
|
|
954
|
+
|
|
955
|
+
|
|
956
|
+
def monthly_weighted_output(uci,hbn,ts_name,operation = 'PERLND',opnids = None, as_rate = False, by_landcover = True, months = [1,2,3,4,5,6,7,8,9,10,11,12]):
|
|
957
|
+
df = hbn.get_multiple_timeseries(operation,4,ts_name,opnids = opnids)
|
|
958
|
+
df = df.loc[df.index.month.isin(months)]
|
|
959
|
+
|
|
960
|
+
areas = uci.network.operation_area(operation)
|
|
961
|
+
areas.loc[areas.index.intersection(df.columns)]
|
|
962
|
+
df = df[areas.index.intersection(df.columns)]
|
|
963
|
+
|
|
964
|
+
df = (df.groupby(df.index.month).mean()*areas['AFACTR'])
|
|
965
|
+
|
|
966
|
+
if by_landcover:
|
|
967
|
+
df = df.T.groupby(areas['LSID']).sum().T
|
|
968
|
+
if as_rate:
|
|
969
|
+
df = df/areas['AFACTR'].groupby(areas['LSID']).sum().to_list()
|
|
970
|
+
else:
|
|
971
|
+
if as_rate:
|
|
972
|
+
df = df/areas['AFACTR'].sum()
|
|
973
|
+
|
|
974
|
+
df.columns.name = ts_name
|
|
975
|
+
|
|
976
|
+
return df
|
|
977
|
+
|
|
978
|
+
def monthly_perlnd_runoff(uci,hbn):
|
|
979
|
+
ts_names = ['PRECIP','PERO','AGWO','IFWO','SURO']
|
|
980
|
+
df = pd.concat({ts_name:monthly_weighted_output(uci,hbn,ts_name,by_landcover=True,as_rate=True) for ts_name in ts_names},keys =ts_names)
|
|
981
|
+
suro_perc = (df.loc['SURO']/df.loc['PERO'])*100
|
|
982
|
+
suro_perc = suro_perc.reset_index()
|
|
983
|
+
suro_perc['name'] = 'SURO_perc'
|
|
984
|
+
suro_perc = suro_perc.set_index(['name','index'])
|
|
985
|
+
return pd.concat([df,suro_perc])
|
|
986
|
+
|
|
987
|
+
|
|
988
|
+
def annual_perlnd_runoff(uci,hbn):
|
|
989
|
+
ts_names = ['PRECIP','PERO','AGWO','IFWO','SURO']
|
|
990
|
+
df = pd.concat([annual_weighted_output(uci,hbn,ts_name,group_by='landcover') for ts_name in ts_names],axis = 1)
|
|
991
|
+
df.columns = ts_names
|
|
992
|
+
df['suro_perc'] = (df['SURO']/df['PERO'])*100
|
|
993
|
+
return df
|
|
994
|
+
|
|
995
|
+
|
|
996
|
+
def annual_reach_water_budget(uci,hbn):
|
|
997
|
+
ts_names = ['PRSUPY','IVOL','ROVOL','VOLEV']
|
|
998
|
+
#df = pd.concat([annual_weighted_output(uci,hbn,ts_name,as_rate = True,by_landcover=True).mean() for ts_name in ts_names],axis = 1)
|
|
999
|
+
df = pd.concat([hbn.get_multiple_timeseries('RCHRES',5,ts_name).mean() for ts_name in ts_names],axis=1)
|
|
1000
|
+
df.columns = ts_names
|
|
1001
|
+
# df = pd.concat([hbn.get_multiple_timeseries('RCHRES',5,'PRSUPY').mean(), #Inflow from Precipitation
|
|
1002
|
+
# hbn.get_multiple_timeseries('RCHRES',5,'IVOL').mean(), #Total Inflow
|
|
1003
|
+
# hbn.get_multiple_timeseries('RCHRES',5,'ROVOL').mean(), #Total Outflow
|
|
1004
|
+
# hbn.get_multiple_timeseries('RCHRES',5,'VOLEV').mean()],axis=1) #Loss from Evaporation
|
|
1005
|
+
geninfo = uci.table('RCHRES','GEN-INFO')[['LKFG']]
|
|
1006
|
+
reach_intersection = geninfo.index.intersection(df.index)
|
|
1007
|
+
|
|
1008
|
+
|
|
1009
|
+
df = geninfo.loc[reach_intersection].join(df.loc[reach_intersection])
|
|
1010
|
+
#df.columns = ['LKFG','PRSUPY','IVOL','ROVOL','VOLEV']
|
|
1011
|
+
|
|
1012
|
+
|
|
1013
|
+
df['ROVOL_Input'] = 0.
|
|
1014
|
+
|
|
1015
|
+
for reach_id in df.index:
|
|
1016
|
+
if reach_id in uci.network.G.nodes:
|
|
1017
|
+
upstream_ids = uci.network.upstream(reach_id)
|
|
1018
|
+
if len(upstream_ids) > 0:
|
|
1019
|
+
df.loc[reach_id,'ROVOL_Input'] = df.loc[upstream_ids]['ROVOL'].sum()
|
|
1020
|
+
|
|
1021
|
+
df.index.name = 'OPNID'
|
|
1022
|
+
return df.reset_index()
|
|
1023
|
+
|
|
1024
|
+
|
|
1025
|
+
def annual_implnd_water_budget(uci,hbn):
|
|
1026
|
+
ts_names = ['SUPY','SURO','IMPEV']
|
|
1027
|
+
#df = pd.concat([annual_weighted_output(uci,hbn,ts_name,as_rate = True,by_landcover=True).mean() for ts_name in ts_names],axis = 1)
|
|
1028
|
+
df = pd.concat([hbn.get_multiple_timeseries('IMPLND',5,ts_name).mean() for ts_name in ts_names],axis=1)
|
|
1029
|
+
df.columns = ts_names
|
|
1030
|
+
return df
|
|
1031
|
+
|
|
1032
|
+
def annual_perlnd_water_budget(uci,hbn):
|
|
1033
|
+
ts_names = ['PRECIP','TAET','PERO']
|
|
1034
|
+
df = pd.concat([annual_weighted_output(uci,hbn,ts_name,group_by='landcover') for ts_name in ts_names],axis = 1)
|
|
1035
|
+
df.columns = ts_names
|
|
1036
|
+
return df
|
|
1037
|
+
|
|
1038
|
+
def annual_sediment_budget(uci,hbn):
|
|
1039
|
+
ts_names = ['SOSED']
|
|
1040
|
+
df = pd.concat([annual_weighted_output(uci,hbn,ts_name,'PERLND', group_by='landcover') for ts_name in ts_names],axis = 1)
|
|
1041
|
+
#df_rate = pd.concat([annual_weighted_output(uci,hbn,ts_name,'PERLND',as_rate = True, by_landcover=True).mean() for ts_name in ts_names],axis = 1)
|
|
1042
|
+
|
|
1043
|
+
ts_names = ['SOSLD']
|
|
1044
|
+
sosld = pd.concat([annual_weighted_output(uci,hbn,ts_name,'IMPLND',group_by='landcover') for ts_name in ts_names],axis = 1)
|
|
1045
|
+
sosld.columns = ['SOSED']
|
|
1046
|
+
|
|
1047
|
+
df = pd.concat([df,sosld])
|
|
1048
|
+
#df_rate = annual_weighted_output(uci,hbn,ts_name,'PERLND',as_rate = True, by_landcover=True).mean()
|
|
1049
|
+
|
|
1050
|
+
df['Percentage'] = 100*(df['SOSED']*df.index.get_level_values('AFACTR')/sum(df['SOSED']*df.index.get_level_values('AFACTR')))
|
|
1051
|
+
|
|
1052
|
+
df.columns = ['Sediment','Percentage']
|
|
1053
|
+
return df
|
|
1054
|
+
|
|
1055
|
+
# def annual_loading_rate():
|
|
1056
|
+
|
|
1057
|
+
|
|
1058
|
+
# def annual_yield(uci,hbn,constituent):
|
|
1059
|
+
|
|
1060
|
+
|
|
1061
|
+
def subwatershed_weighted_output(uci,hbn,reach_ids,ts_name,time_step,by_landcover=False,as_rate = True):
|
|
1062
|
+
subwatersheds = uci.network.subwatersheds(reach_ids)
|
|
1063
|
+
subwatersheds = subwatersheds.loc[subwatersheds['SVOL'] == 'PERLND']
|
|
1064
|
+
|
|
1065
|
+
areas = subwatersheds[['SVOLNO','AFACTR']].set_index('SVOLNO')
|
|
1066
|
+
areas = areas.join( uci.table('PERLND','GEN-INFO')['LSID'])
|
|
1067
|
+
opnids = subwatersheds['SVOLNO'].to_list()
|
|
1068
|
+
|
|
1069
|
+
df = hbn.get_multiple_timeseries('PERLND',time_step,ts_name,opnids = opnids)
|
|
1070
|
+
|
|
1071
|
+
areas.loc[areas.index.intersection(df.columns)]
|
|
1072
|
+
df = df[areas.index.intersection(df.columns)]
|
|
1073
|
+
|
|
1074
|
+
if by_landcover:
|
|
1075
|
+
df = (df*areas['AFACTR'].values).T.groupby(areas['LSID']).sum()
|
|
1076
|
+
if as_rate:
|
|
1077
|
+
df = df.T/areas['AFACTR'].groupby(areas['LSID']).sum().to_list()
|
|
1078
|
+
df.columns.name = ts_name
|
|
1079
|
+
else:
|
|
1080
|
+
df = (df * areas['AFACTR'].values).sum(axis=1)
|
|
1081
|
+
if as_rate:
|
|
1082
|
+
df = df/areas['AFACTR'].sum()
|
|
1083
|
+
df.name = ts_name
|
|
1084
|
+
|
|
1085
|
+
return df
|
|
1086
|
+
|
|
1087
|
+
|
|
1088
|
+
|
|
1089
|
+
|
|
1090
|
+
|
|
1091
|
+
# def perlnd_water_budget(uci,hbn,time_step = 5):
|
|
1092
|
+
|
|
1093
|
+
# ts_names = ['SUPY','SURO','IFWO','AGWO','PERO','AGWI','IGWI','PET','UZET','LZET','AGWET','BASET','TAET']
|
|
1094
|
+
# dfs = [area_weighted_output(uci,hbn,ts_name,time_step) for ts_name in ts_names]
|
|
1095
|
+
|
|
1096
|
+
|
|
1097
|
+
|
|
1098
|
+
|
|
1099
|
+
#%% Phosphorous Loading
|
|
1100
|
+
def subwatershed_total_phosphorous_loading(uci,hbn,reach_ids = None,t_code=5, as_load = True,group_landcover = True):
|
|
1101
|
+
tp_loading = total_phosphorous(uci,hbn,t_code)
|
|
1102
|
+
if reach_ids is None:
|
|
1103
|
+
subwatersheds = uci.network.subwatersheds()
|
|
1104
|
+
else:
|
|
1105
|
+
subwatersheds = uci.network.subwatersheds(reach_ids)
|
|
1106
|
+
|
|
1107
|
+
perlnds = subwatersheds.loc[subwatersheds['SVOL'] == 'PERLND']
|
|
1108
|
+
perlnds = perlnds['AFACTR'].groupby([perlnds.index,perlnds['SVOLNO']]).sum().reset_index()
|
|
1109
|
+
|
|
1110
|
+
|
|
1111
|
+
#perlnds = perlnds.set_index('SVOLNO').drop_duplicates()
|
|
1112
|
+
total = tp_loading[perlnds['SVOLNO']]
|
|
1113
|
+
|
|
1114
|
+
total = total.mul(perlnds['AFACTR'].values,axis=1)
|
|
1115
|
+
|
|
1116
|
+
total = total.transpose()
|
|
1117
|
+
total['reach_id'] = perlnds['TVOLNO'].values
|
|
1118
|
+
total['landcover'] = uci.table('PERLND','GEN-INFO').loc[total.index,'LSID'].to_list()
|
|
1119
|
+
total['area'] = perlnds['AFACTR'].to_list() #perlnds.loc[total.index,'AFACTR'].to_list()
|
|
1120
|
+
total = total.reset_index().set_index(['index','landcover','area','reach_id']).transpose()
|
|
1121
|
+
total.columns.names = ['perlnd_id','landcover','area','reach_id']
|
|
1122
|
+
|
|
1123
|
+
if group_landcover:
|
|
1124
|
+
total.columns = total.columns.droplevel(['landcover','perlnd_id'])
|
|
1125
|
+
total = total.T.reset_index().groupby('reach_id').sum().reset_index().set_index(['reach_id','area']).T
|
|
1126
|
+
|
|
1127
|
+
if not as_load:
|
|
1128
|
+
total = total.div(total.columns.get_level_values('area').values,axis=1)
|
|
1129
|
+
|
|
1130
|
+
total.index = pd.to_datetime(total.index)
|
|
1131
|
+
return total
|
|
1132
|
+
|
|
1133
|
+
def total_phosphorous(uci,hbn,t_code):
|
|
1134
|
+
#assert(isinstance(perlnd_ids (int,list,None)))
|
|
1135
|
+
perlnds = uci.network.subwatersheds()
|
|
1136
|
+
perlnds = perlnds.loc[perlnds['SVOL'] == 'PERLND'].drop_duplicates(subset = ['SVOLNO','MLNO'])
|
|
1137
|
+
|
|
1138
|
+
totals = []
|
|
1139
|
+
for mlno in perlnds['MLNO'].unique():
|
|
1140
|
+
perlnd_ids = perlnds['SVOLNO'].loc[perlnds['MLNO'] == mlno].to_list()
|
|
1141
|
+
total = dissolved_orthophosphate(uci,hbn,mlno,t_code) + particulate_orthophosphate(uci,hbn,mlno, t_code) + organic_refactory_phosphorous(uci,hbn,mlno,t_code) + labile_oxygen_demand(uci,hbn,mlno,t_code)*0.007326 # Conversation factor to P
|
|
1142
|
+
totals.append(total[perlnd_ids])
|
|
1143
|
+
|
|
1144
|
+
total = pd.concat(totals,axis=1)
|
|
1145
|
+
total = total.T.groupby(total.columns).sum().T
|
|
1146
|
+
return total
|
|
1147
|
+
|
|
1148
|
+
MASSLINK_SCHEME = {'dissolved_orthophosphate': {'tmemn': 'NUIF1',
|
|
1149
|
+
'tmemsb1': '4',
|
|
1150
|
+
'tmemsb2':''},
|
|
1151
|
+
'particulate_orthophosphate_sand': {'tmemn': 'NUIF2',
|
|
1152
|
+
'tmemsb1': '1',
|
|
1153
|
+
'tmemsb2':'2'},
|
|
1154
|
+
'particulate_orthophosphate_silt': {'tmemn': 'NUIF2',
|
|
1155
|
+
'tmemsb1': '2',
|
|
1156
|
+
'tmemsb2':'2'},
|
|
1157
|
+
'particulate_orthophosphate_clay': {'tmemn': 'NUIF2',
|
|
1158
|
+
'tmemsb1': '3',
|
|
1159
|
+
'tmemsb2':'2'},
|
|
1160
|
+
'organic_refactory_phosphorous': {'tmemn': 'PKIF',
|
|
1161
|
+
'tmemsb1' : '4',
|
|
1162
|
+
'tmemsb2':''},
|
|
1163
|
+
'organic_refactory_carbon':{'tmemn' : 'PKIF',
|
|
1164
|
+
'tmemsb1': '5',
|
|
1165
|
+
'tmemsb2':''},
|
|
1166
|
+
'labile_oxygen_demand': {'tmemn': 'OXIF',
|
|
1167
|
+
'tmemsb1': '2',
|
|
1168
|
+
'tmemsb2':''}}
|
|
1169
|
+
|
|
1170
|
+
|
|
1171
|
+
def qualprop_transform(uci,hbn,mlno,tmemn,tmemsb1,tmemsb2 = '',t_code = 4):
|
|
1172
|
+
masslink = uci.table('MASS-LINK',f'MASS-LINK{mlno}')
|
|
1173
|
+
masslink = masslink.loc[(masslink['TMEMN'] == tmemn) & (masslink['TMEMSB1'] == tmemsb1) & (masslink['TMEMSB2'] == tmemsb2)]
|
|
1174
|
+
ts = 0
|
|
1175
|
+
for index,row in masslink.iterrows():
|
|
1176
|
+
hbn_name = uci.table('PERLND','QUAL-PROPS', int(row['SMEMSB1']) - 1).iloc[0]['QUALID']
|
|
1177
|
+
hbn_name = row['SMEMN'] + hbn_name
|
|
1178
|
+
mfactor = row['MFACTOR']
|
|
1179
|
+
ts = hbn.get_multiple_timeseries(row['SVOL'],t_code,hbn_name)*mfactor + ts
|
|
1180
|
+
return ts
|
|
1181
|
+
|
|
1182
|
+
|
|
1183
|
+
|
|
1184
|
+
|
|
1185
|
+
def dissolved_orthophosphate(uci,hbn,mlno,t_code = 4):
|
|
1186
|
+
tmemn = MASSLINK_SCHEME['dissolved_orthophosphate']['tmemn']
|
|
1187
|
+
tmemsb1 = MASSLINK_SCHEME['dissolved_orthophosphate']['tmemsb1']
|
|
1188
|
+
tmemsb2 = MASSLINK_SCHEME['dissolved_orthophosphate']['tmemsb2']
|
|
1189
|
+
return qualprop_transform(uci,hbn,mlno,tmemn,tmemsb1,tmemsb2,t_code)
|
|
1190
|
+
|
|
1191
|
+
def particulate_orthophosphate(uci,hbn,mlno,t_code = 4):
|
|
1192
|
+
ts = particulate_orthophosphate_sand(uci,hbn,mlno,t_code) + particulate_orthophosphate_silt(uci,hbn,mlno,t_code) + particulate_orthophosphate_clay(uci,hbn,mlno,t_code)
|
|
1193
|
+
return ts
|
|
1194
|
+
|
|
1195
|
+
def particulate_orthophosphate_sand(uci,hbn, mlno,t_code = 4):
|
|
1196
|
+
tmemn = MASSLINK_SCHEME['particulate_orthophosphate_sand']['tmemn']
|
|
1197
|
+
tmemsb1 = MASSLINK_SCHEME['particulate_orthophosphate_sand']['tmemsb1']
|
|
1198
|
+
tmemsb2 = MASSLINK_SCHEME['particulate_orthophosphate_sand']['tmemsb2']
|
|
1199
|
+
return qualprop_transform(uci,hbn,mlno,tmemn,tmemsb1,tmemsb2,t_code)
|
|
1200
|
+
|
|
1201
|
+
def particulate_orthophosphate_silt(uci,hbn, mlno,t_code = 4):
|
|
1202
|
+
tmemn = MASSLINK_SCHEME['particulate_orthophosphate_silt']['tmemn']
|
|
1203
|
+
tmemsb1 = MASSLINK_SCHEME['particulate_orthophosphate_silt']['tmemsb1']
|
|
1204
|
+
tmemsb2 = MASSLINK_SCHEME['particulate_orthophosphate_silt']['tmemsb2']
|
|
1205
|
+
return qualprop_transform(uci,hbn,mlno,tmemn,tmemsb1,tmemsb2,t_code)
|
|
1206
|
+
|
|
1207
|
+
def particulate_orthophosphate_clay(uci,hbn, mlno,t_code = 4):
|
|
1208
|
+
tmemn = MASSLINK_SCHEME['particulate_orthophosphate_clay']['tmemn']
|
|
1209
|
+
tmemsb1 = MASSLINK_SCHEME['particulate_orthophosphate_clay']['tmemsb1']
|
|
1210
|
+
tmemsb2 = MASSLINK_SCHEME['particulate_orthophosphate_clay']['tmemsb2']
|
|
1211
|
+
return qualprop_transform(uci,hbn,mlno,tmemn,tmemsb1,tmemsb2,t_code)
|
|
1212
|
+
|
|
1213
|
+
def organic_refactory_phosphorous(uci,hbn, mlno,t_code = 4):
|
|
1214
|
+
tmemn = MASSLINK_SCHEME['organic_refactory_phosphorous']['tmemn']
|
|
1215
|
+
tmemsb1 = MASSLINK_SCHEME['organic_refactory_phosphorous']['tmemsb1']
|
|
1216
|
+
tmemsb2 = MASSLINK_SCHEME['organic_refactory_phosphorous']['tmemsb2']
|
|
1217
|
+
return qualprop_transform(uci,hbn,mlno,tmemn,tmemsb1,tmemsb2,t_code)
|
|
1218
|
+
|
|
1219
|
+
def organic_refactory_carbon(uci,hbn, mlno,t_code = 4):
|
|
1220
|
+
tmemn = MASSLINK_SCHEME['organic_refactory_carbon']['tmemn']
|
|
1221
|
+
tmemsb1 = MASSLINK_SCHEME['organic_refactory_carbon']['tmemsb1']
|
|
1222
|
+
tmemsb2 = MASSLINK_SCHEME['organic_refactory_carbon']['tmemsb2']
|
|
1223
|
+
return qualprop_transform(uci,hbn,mlno,tmemn,tmemsb1,tmemsb2,t_code)
|
|
1224
|
+
|
|
1225
|
+
def labile_oxygen_demand(uci,hbn,mlno,t_code = 4):
|
|
1226
|
+
tmemn = MASSLINK_SCHEME['labile_oxygen_demand']['tmemn']
|
|
1227
|
+
tmemsb1 = MASSLINK_SCHEME['labile_oxygen_demand']['tmemsb1']
|
|
1228
|
+
tmemsb2 = MASSLINK_SCHEME['labile_oxygen_demand']['tmemsb2']
|
|
1229
|
+
return qualprop_transform(uci,hbn,mlno,tmemn,tmemsb1,tmemsb2,t_code)
|
|
1230
|
+
|