1
+ import numpy as np
2
+ import pandas as pd
3
+
4
+ def IHmethod (values , block_length = 5 , tp = 0.9 , interp_semilog = True ):
5
+ """Baseflow separation using the Institute of Hydrology method, as documented in
6
+ Institute of Hydrology, 1980b, Low flow studies report no. 3--Research report:
7
+ Wallingford, Oxon, United Kingdom, Institute of Hydrology Report no. 3, p. 12-19,
8
+ and
9
+ Wahl, K.L and Wahl, T.L., 1988. Effects of regional ground-water level declines
10
+ on streamflow in the Oklahoma Panhandle. In Proceedings of the Symposium on
11
+ Water-Use Data for Water Resources Management, American Water Resources Association.
12
+
13
+ Parameters
14
+ ----------
15
+ values : pandas Series
16
+ Pandas time series (with datetime index) containing measured streamflow values.
17
+ block_length : int
18
+ N parameter in IH method. Streamflow is partitioned into N-day intervals;
19
+ a minimum flow is recorded for each interval.
20
+ tp : float
21
+ f parameter in IH method. For each three N-day minima, if f * the central value
22
+ is less than the adjacent two values, the central value is considered a
23
+ turning point. Baseflow is interpolated between the turning points.
24
+ interp_semilog : boolean
25
+ If False, linear interpolation is used to compute baseflow between turning points
26
+ (as documented in the IH method). If True, the base-10 logs of the turning points
27
+ are interpolated, and the interpolated values are transformed back to
28
+ linear space (producing a curved hydrograph). Semi-logarithmic interpolation
29
+ as documented in Wahl and Wahl (1988), is used in the Base-Flow Index (BFI)
30
+ fortran program.
31
+
32
+ Returns
33
+ -------
34
+ Q : pandas DataFrame
35
+ DataFrame containing the following columns:
36
+ minima : N-day minima
37
+ ordinate : selected turning points
38
+ n : block number for each N-day minima
39
+ QB : computed baseflow
40
+ Q : discharge values
41
+
42
+ Notes
43
+ -----
44
+ Whereas this program only selects turning points following the methodology above,
45
+ the BFI fortran program adds artificial turning points at the start and end of
46
+ each calendar year. Therefore results for datasets consisting of multiple years
47
+ will differ from those produced by the BFI program.
48
+
49
+ """
50
+ if values .dtype .name == 'object' :
51
+ values = values .convert_objects (convert_numeric = True )
52
+ values = pd .DataFrame (values ).resample ('D' )
53
+ values .columns = ['discharge' ]
54
+
55
+ # compute block numbers for grouping values on blocks
56
+ #nblocks = int(len(values) / float(block_length) + 1)
57
+ nblocks = int (np .floor (len (values ) / float (block_length )))
58
+ n = []
59
+ for i in range (nblocks ):
60
+ n += [i + 1 ] * block_length
61
+ #values['n'] = n[:len(values)]
62
+ n += [np .nan ] * (len (values ) - len (n ))
63
+ values ['n' ] = n
64
+
65
+ # compute minima for block_length day blocks
66
+ Q = [np .min (values .discharge .values [i - block_length :i ])
67
+ for i in np .arange (block_length , len (values ))[::block_length ]]
68
+
69
+ # compute the minimum for each block
70
+ Q = values .groupby ('n' ).min ()
71
+ Q ['datetime' ] = values [['discharge' , 'n' ]].groupby ('n' ).idxmin () # include dates of minimum values
72
+
73
+ Q ['ordinate' ] = [np .nan ] * len (Q )
74
+ #for i in range(len(Q))[:-2]:
75
+ # end1, cv, end2 = Q.discharge[i:i+3]
76
+ for i in np .arange (1 , len (Q )- 1 ):
77
+ end1 , cv , end2 = Q .discharge .values [i - 1 :i + 2 ]
78
+ if tp * cv < end1 and tp * cv < end2 :
79
+ Q .loc [Q .index [i ], 'ordinate' ] = cv
80
+ Q ['n' ] = Q .index
81
+ Q .index = Q .datetime
82
+
83
+ Q = Q .dropna (subset = ['datetime' ], axis = 0 ).resample ('D' )
84
+ if interp_semilog :
85
+ QB = 10 ** (np .log10 (Q .ordinate ).interpolate ()).values
86
+ else :
87
+ QB = Q .ordinate .interpolate (limit = 100 ).values
88
+ Q ['QB' ] = QB
89
+ Q ['Q' ] = values .discharge [Q .index ]
90
+ QBgreaterthanQ = Q .QB .values > Q .Q .values
91
+ Q .loc [QBgreaterthanQ , 'QB' ] = Q .ix [QBgreaterthanQ , 'Q' ]
92
+ return Q
93
+
94
+ def WI_statewide_eqn (Qm , A , Qr , Q90 ):
95
+ """Regression equation of Gebert and others (2007, 2011)
96
+ for estimating average annual baseflow from a field measurement of streamflow
97
+ during low-flow conditions.
98
+
99
+ Parameters
100
+ ----------
101
+ Qm : float or 1-D array of floats
102
+ Measured streamflow.
103
+ A : float or 1-D array of floats
104
+ Drainage area in watershed upstream of where Qm was taken.
105
+ Qr : float or 1-D array of floats
106
+ Recorded flow at index station when Qm was taken.
107
+ Q90 : float or 1-D array of floats
108
+ Q90 flow at index station.
109
+
110
+ Returns
111
+ -------
112
+ Qb : float or 1-D array of floats, of length equal to input arrays
113
+ Estimated average annual baseflow at point where Qm was taken.
114
+ Bf : float or 1-D array of floats, of length equal to input arrays
115
+ Baseflow factor. see Gebert and others (2007, 2011).
116
+
117
+ Notes
118
+ -----
119
+ Gebert, W.A., Radloff, M.J., Considine, E.J., and Kennedy, J.L., 2007,
120
+ Use of streamflow data to estimate base flow/ground-water recharge for Wisconsin:
121
+ Journal of the American Water Resources Association,
122
+ v. 43, no. 1, p. 220-236, http://dx.doi.org/10.1111/j.1752-1688.2007.00018.x
123
+
124
+ Gebert, W.A., Walker, J.F., and Kennedy, J.L., 2011,
125
+ Estimating 1970-99 average annual groundwater recharge in Wisconsin using streamflow data:
126
+ U.S. Geological Survey Open-File Report 2009-1210, 14 p., plus appendixes,
127
+ available at http://pubs.usgs.gov/ofr/2009/1210/.
128
+ """
129
+ Bf = (Qm / A ) * (Q90 / Qr )
130
+ Qb = 0.907 * A ** 1.02 * Bf ** 0.52
131
+ return Qb .copy (), Bf .copy ()
0 commit comments