Skip to content

Commit 6fea80e

Browse files
committed
merged nkn-master
2 parents 40a8078 + 097392b commit 6fea80e

7 files changed

Lines changed: 564 additions & 41 deletions

File tree

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
##
1+
##
22
*.pyc
33
*~
44

@@ -8,10 +8,14 @@
88

99
## ipython notebook checkpoint folders
1010
**/.ipynb_checkpoints/
11+
1112
venv
1213
*animation*
1314
test/data/models/lbcd/prms.out
1415
test/data/models/lbcd/prms_ic.out
1516
test/data/models/lbcd/statvar.dat
1617
notebooks/jupyternb-scenario-series-example/
1718
docs/build
19+
20+
**/utility_functions.ipynb
21+
**/scripts/*.data

README.md

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,41 @@
11
# PRMS-Python
2-
A Python module to assist with calibration, data processing and visualization for the Precipitation Runoff Modeling System (PRMS) computer program.
3-
4-
## Parameter File Tools
52

6-
Currently you can do the following, starting from the root directory.
3+
PRMS-Python provides a Python interface to PRMS data files and for running
4+
PRMS simulations. This module tries to improve the management of PRMS simulation
5+
data while also providing useful "pythonic" tools to do scenario-based PRMS
6+
simulations. By "scenario-based" modeling we mean, for example, parameter
7+
sensitivity analysis, where each "scenario" is an iterative perturbation of
8+
one or many parameters. Another example "scenario-based" modeling exercise would
9+
be climate scenario modeling: what will happen to modeled outputs if the
10+
input meteorological data were to change?
711

8-
```python
9-
from prms_python import Parameters
10-
p = Parameters('test/data/parameter')
1112

12-
# select PRMS parameter by name, raising KeyError if DNE
13-
snow_adj = p['snow_adj']
14-
assert snow_adj.shape == (12, 16)
13+
## Installation
1514

16-
# assign values to PRMS parameter
17-
import numpy as np
18-
z = np.zeros(snow_adj.shape)
19-
p['snow_adj'] = z # now p['snow_adj'] is 12x16 matrix of zeros
15+
Currently it's clone-then-pip:
2016

21-
# write modified parameters to file
22-
p.write('newparameters')
17+
```
18+
git clone https://github.com/northwest-knowledge-network/prms-python
2319
```
2420

25-
## Notes
26-
27-
See the `models` directory for data and the Windows PRMS executable. To run PRMS just run
21+
then
2822

2923
```
30-
prms myrun.control
24+
pip install -r requirements.txt
3125
```
3226

33-
There are more built distributions for Linux and Windows in the `dists` directory.
27+
A Python module to assist with calibration, data processing and visualization for the Precipitation Runoff Modeling System (PRMS) computer program.
28+
29+
30+
## Usage
3431

35-
* load_PRMSstatvar in ipynb in `scripts/statvarfile.ipynb`
36-
* modifying params in `scripts/change_param.py`
37-
* input and output paths defined in control file
32+
Please read the [Online Documentation](https://prms-python.github.io/docs).
33+
34+
35+
## Unit tests
36+
37+
I run them using nose but that's not required. From the root repo directory
38+
39+
```
40+
nosetests -v
41+
```

news.txt

Lines changed: 0 additions & 12 deletions
This file was deleted.

notebooks/statvarfile.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
},
3939
{
4040
"cell_type": "code",
41-
"execution_count": 2,
41+
"execution_count": 10,
4242
"metadata": {
4343
"collapsed": true
4444
},

scripts/README.txt

Lines changed: 0 additions & 3 deletions
This file was deleted.

scripts/data.py

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
"""
2+
Description to come
3+
"""
4+
import numpy as np
5+
import pandas as pd
6+
import os
7+
8+
class Data(object):
9+
"""
10+
PRMS data object to read, write and modify time
11+
series input to PRMS that are located in the PRMS data file
12+
"""
13+
## data file constant attributes
14+
date_header = ['year',
15+
'month',
16+
'day',
17+
'hh',
18+
'mm',
19+
'sec']
20+
21+
valid_input_variables = ('gate_ht',
22+
'humidity',
23+
'lake_elev',
24+
'pan_evap',
25+
'precip',
26+
'rain_day',
27+
'runoff',
28+
'snowdepth',
29+
'solrad',
30+
'tmax',
31+
'tmin',
32+
'wind_speed')
33+
34+
def __init__(self, base_file):
35+
self.base_file = base_file
36+
self.metadata = self.__load_metadata()
37+
self.data_frame = self.__load_data()
38+
39+
def __load_metadata(self):
40+
"""
41+
"""
42+
## valid input time series that can be put into a data file
43+
44+
#### starting list of names for header in dataframe
45+
input_data_names = []
46+
## append to header list the variables present in the file
47+
with open(self.base_file, 'r') as inf:
48+
for idx,l in enumerate(inf):
49+
if idx == 0: ## first line always string identifier of the file- may use later
50+
data_head = l.rstrip()
51+
elif l.startswith('/'): ## comment lines
52+
continue
53+
if l.startswith(Data.valid_input_variables): ## header lines with name and number of input variables
54+
h = l.split() ## split line into list, first element name and second number of columns
55+
if int(h[1]) > 1: ## more than one input time series of a particular variable
56+
for el in range(int(h[1])):
57+
tmp = '{var_name} {var_ind}'.format(var_name = h[0], var_ind = el+1)
58+
input_data_names.append(tmp)
59+
elif int(h[1]) == 1:
60+
input_data_names.append(h[0])
61+
if l.startswith('#'): ## end of header info and begin time series input data
62+
data_startline = idx+1 ## 0 indexed line of first data entry
63+
break
64+
65+
return dict([('data_startline',data_startline), ('data_variables',input_data_names)])
66+
67+
def __load_data(self):
68+
missing_value = -999 ## missing data representation
69+
df = pd.read_csv(self.base_file, header = -1, skiprows = self.metadata['data_startline'],
70+
delim_whitespace = True, na_values = [missing_value]) ## read file
71+
df.columns = Data.date_header + self.metadata['data_variables']
72+
date = pd.Series(pd.to_datetime(df.year * 10000 + df.month * 100 + df.day, format = '%Y%m%d'), index = df.index)
73+
df.index = pd.to_datetime(date)
74+
df.drop(Data.date_header, axis = 1, inplace = True) ## unneeded columns
75+
df.columns.name = 'input variables' ; df.index.name = 'date'
76+
return df
77+
78+
def adjust(self, func, vars_to_adjust):
79+
for v in vars_to_adjust:
80+
self.data_frame[v] = self.data_frame[v].apply(func)
81+
82+
def write(self, out_path):
83+
## reconstruct original datafile format
84+
self.data_frame['year'] = self.data_frame.index.year
85+
self.data_frame['month'] = self.data_frame.index.month
86+
self.data_frame['day'] = self.data_frame.index.day
87+
self.data_frame['hh'] = self.data_frame['mm'] = self.data_frame['sec'] = 0
88+
self.data_frame = self.data_frame[Data.date_header + self.metadata['data_variables']]
89+
with open(out_path,'w') as outf:
90+
with open(self.base_file) as data:
91+
for idx, line in enumerate(data):
92+
if idx == self.metadata['data_startline']:
93+
self.data_frame.to_csv(outf, sep=' ', header=None, index=False, na_rep=-999)
94+
break
95+
outf.write(line) # write line by line the header lines from original
96+

0 commit comments

Comments
 (0)