Getting Started#
A simple demonstration fitting a rating curve is show below. First load the library (1) and some tutorial data (2):
# 1. load modules
from ratingcurve.ratings import PowerLawRating
from ratingcurve import data
# 2. load tutorial data
df = data.load('green channel')
df.head()
WARNING (pytensor.tensor.blas): Using NumPy C-API based implementation for BLAS functions.
datetime | stage | q | q_sigma | |
---|---|---|---|---|
0 | 2020-05-21 14:13:41 [UTC-07:00] | 7.04 | 12199.342 | 199.172931 |
1 | 2020-04-16 14:55:31 [UTC-07:00] | 4.43 | 4921.953 | 95.425619 |
2 | 2020-03-04 13:54:10 [UTC-07:00] | 2.99 | 2331.665 | 61.860500 |
3 | 2020-03-04 13:16:51 [UTC-07:00] | 2.94 | 2289.220 | 47.886745 |
4 | 2020-01-23 11:04:32 [UTC-07:00] | 2.96 | 2408.210 | 99.522964 |
Now initialize a model (3), fit it to the tutorial data (4) and visualize the result (5):
# 3. initialize the model
powerrating = PowerLawRating(segments=2)
# 4. fit the model
trace = powerrating.fit(q=df['q'],
h=df['stage'],
q_sigma=df['q_sigma'])
/opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages/rich/live.py:231: UserWarning: install "ipywidgets" for Jupyter support warnings.warn('install "ipywidgets" for Jupyter support')
Convergence achieved at 68200
Interrupted at 68,199 [34%]: Average Loss = 52.283
Sampling: [a, b, hs_, model_q, sigma]
Sampling: [model_q]
/opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages/rich/live.py:231: UserWarning: install "ipywidgets" for Jupyter support warnings.warn('install "ipywidgets" for Jupyter support')
powerrating.plot()
Sampling: [model_q]
/opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages/rich/live.py:231: UserWarning: install "ipywidgets" for Jupyter support warnings.warn('install "ipywidgets" for Jupyter support')

On the first run, the previous cell will take a bit longer while the model compiles. A progress bar will appear when the optimization begins. The loss with decline as the optimization proceeds and should converge after a few seconds (Average Loss = -51).
The resulting fit can be displayed as a rating table
table = powerrating.table()
table.head()
Sampling: [model_q]
/opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages/rich/live.py:231: UserWarning: install "ipywidgets" for Jupyter support warnings.warn('install "ipywidgets" for Jupyter support')
stage | discharge | median | gse | |
---|---|---|---|---|
0 | 2.21 | 1386.161885 | 1385.822962 | 1.017524 |
1 | 2.22 | 1398.829289 | 1398.440252 | 1.017546 |
2 | 2.23 | 1410.518818 | 1410.305647 | 1.017854 |
3 | 2.24 | 1422.800582 | 1422.809894 | 1.017698 |
4 | 2.25 | 1434.791051 | 1434.754949 | 1.017506 |
and saved as a CSV
table.to_csv('green_rating_table.csv')
Once a model is fit, it can be saved and reloaded for future use.
powerrating.save('./green_rating_fit.nc')
loaded_rating = PowerLawRating().load('./green_rating_fit.nc')
/opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages/arviz/data/inference_data.py:157: UserWarning: fit_data group is not defined in the InferenceData scheme
warnings.warn(
Demo datasets#
The package includes several demo datasets. List them by calling
from ratingcurve import data
data.list()
['chalk artificial',
'co channel',
'green channel',
'provo natural',
'3-segment simulated',
'mahurangi artificial',
'nordura',
'skajalfandafljot',
'isere']
Each dataset includes a description and is loaded as a DataFrame.
data.describe('green channel')
# Green River near Jensen, UT (channel control)
## USGS Gage ID: 09261000
## Control
At the gage, the river is restricted to one channel at all stages.
The streambed is very flat and is composed of cobbles.
The banks consist of sand, gravel and cobbles.
Riparian vegetation includes sage brush, willows, greasewood, and tamarisk.
The left bank is not as steep as the right, which slopes up quite abruptly.
Both banks are quite stable and are not subject to overflow except at extremely high stages.
The channel is straight for several hundred yards upstream but bends sharply to the right about 2,000 feet below the station.
Channel control prevails at all but the lowest stages when a rocky riffle 200 feet below the gage becomes effective.
The riffle is quite stable.
## Stage Ranges
- Reach control: < 3.70 ft
- Channel control: 3.70 to 14 ft
df = data.load('green channel')
df
datetime | stage | q | q_sigma | |
---|---|---|---|---|
0 | 2020-05-21 14:13:41 [UTC-07:00] | 7.04 | 12199.342 | 199.172931 |
1 | 2020-04-16 14:55:31 [UTC-07:00] | 4.43 | 4921.953 | 95.425619 |
2 | 2020-03-04 13:54:10 [UTC-07:00] | 2.99 | 2331.665 | 61.860500 |
3 | 2020-03-04 13:16:51 [UTC-07:00] | 2.94 | 2289.220 | 47.886745 |
4 | 2020-01-23 11:04:32 [UTC-07:00] | 2.96 | 2408.210 | 99.522964 |
5 | 2019-12-17 14:48:54 [UTC-07:00] | 3.09 | 2533.894 | 51.712122 |
6 | 2019-11-14 14:28:01 [UTC-07:00] | 2.46 | 1643.082 | 33.532286 |
7 | 2019-10-07 12:38:17 [UTC-07:00] | 2.54 | 1827.425 | 45.685625 |
8 | 2019-08-29 08:03:05 [UTC-07:00] | 2.86 | 2105.019 | 38.663614 |
9 | 2019-07-23 11:43:33 [UTC-07:00] | 3.53 | 3173.955 | 66.393957 |
10 | 2019-06-10 12:17:17 [UTC-07:00] | 9.60 | 20154.349 | 349.616258 |
11 | 2019-04-24 17:36:28 [UTC-07:00] | 5.58 | 8000.834 | 159.200268 |
12 | 2019-03-07 18:33:28 [UTC-07:00] | 2.21 | 1409.271 | 35.231775 |
13 | 2019-02-04 17:35:13 [UTC-07:00] | 3.17 | 2561.581 | 54.891021 |
14 | 2018-12-06 15:49:05 [UTC-07:00] | 3.09 | 2453.631 | 53.829660 |
15 | 2018-10-25 12:18:42 [UTC-07:00] | 2.50 | 1795.588 | 35.728537 |
16 | 2018-09-13 12:47:40 [UTC-07:00] | 2.65 | 1882.085 | 39.370145 |
17 | 2018-08-09 17:22:36 [UTC-07:00] | 2.98 | 2318.337 | 49.678650 |
18 | 2018-06-27 14:00:29 [UTC-07:00] | 3.03 | 2417.105 | 50.561890 |
19 | 2018-05-24 14:27:04 [UTC-07:00] | 6.60 | 10706.397 | 240.347688 |
20 | 2018-04-19 08:24:27 [UTC-07:00] | 3.92 | 3795.702 | 75.526723 |
21 | 2018-03-15 12:09:50 [UTC-07:00] | 2.93 | 2315.117 | 42.522557 |
22 | 2018-03-15 11:27:25 [UTC-07:00] | 2.92 | 2295.206 | 42.156845 |
23 | 2018-01-31 14:57:47 [UTC-07:00] | 3.72 | 3448.262 | 59.816790 |
24 | 2017-11-13 17:01:47 [UTC-07:00] | 3.50 | 2996.979 | 61.162837 |
25 | 2017-10-04 17:14:01 [UTC-07:00] | 3.73 | 3565.210 | 72.759388 |
26 | 2017-08-24 07:06:33 [UTC-07:00] | 3.12 | 2587.378 | 46.203179 |
27 | 2017-07-18 16:03:54 [UTC-07:00] | 3.66 | 3446.044 | 65.052871 |
28 | 2017-06-13 08:37:46 [UTC-07:00] | 8.99 | 18505.309 | 557.047567 |
29 | 2017-05-04 17:46:14 [UTC-07:00] | 7.03 | 12173.573 | 403.715431 |
30 | 2017-03-24 07:53:49 [UTC-07:00] | 5.72 | 8532.444 | 165.424935 |
31 | 2017-02-16 08:42:52 [UTC-07:00] | 3.27 | 2777.993 | 55.276391 |
32 | 2017-01-11 13:07:23 [UTC-07:00] | 3.01 | 2416.000 | 48.073469 |
33 | 2016-12-02 10:12:48 [UTC-07:00] | 2.49 | 1726.456 | 37.876331 |
34 | 2016-10-25 13:23:16 [UTC-07:00] | 2.44 | 1676.239 | 34.208959 |
35 | 2011-06-09 09:32:15 [UTC-07:00] | 12.32 | 29617.364 | 395.905580 |