Skip to content

Commit

Permalink
Merge pull request #176 from UW-Hydro/develop
Browse files Browse the repository at this point in the history
Update master for 2.1.0 release
  • Loading branch information
arbennett authored Sep 3, 2019
2 parents 56a34fc + f8fb72e commit 1f23666
Show file tree
Hide file tree
Showing 13 changed files with 239 additions and 33 deletions.
5 changes: 4 additions & 1 deletion ci/requirements-3.5.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@ channels:
- conda-forge
dependencies:
- python=3.5
- xarray=0.10.9
- xarray>=0.11.0
- pandas
- netcdf4
- numba
- bottleneck
- numpy
- scipy
- pytest
- dask
- distributed
- toolz
- pip:
- coveralls
- pytest-cov
5 changes: 4 additions & 1 deletion ci/requirements-3.6.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@ channels:
- conda-forge
dependencies:
- python=3.6
- xarray=0.10.9
- xarray>=0.11.0
- pandas
- netcdf4
- bottleneck
- numba
- numpy
- scipy
- pytest
- dask
- distributed
- toolz
- pip:
- coveralls
- pytest-cov
26 changes: 25 additions & 1 deletion docs/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ the ``forcing`` entry. Can be one of the following: ``ascii``, ``binary``,

**Optional Variables**

``output_prefix :: str``: The output file base name. Defaults to ``forcing``.
``out_prefix :: str``: The output file base name. Defaults to ``forcing``.

``out_precision :: str``: Precision to use when writing output. Defaults to
``f8``. Can be either ``f4`` or ``f8``.
Expand Down Expand Up @@ -183,3 +183,27 @@ a mask of valid cells in the domain, and the elevation given in meters. If
``prec_type`` = ``triangle`` or ``mix``, two additonal variables are required
including ``dur`` and ``t_pk`` for disaggregating daily precipitation according
to the "triangle" method.

constant_vars section
-------------------
The ``constant_vars`` section is optional and allows you to set some of the
forcing inputs to a constant value. The specification simply consists of entries
of the form ``metsim_varname = value``, where ``value`` is a number that can be
converted to a double. There can only be one entry per line. If the
``metsim_varname`` corresponds to an entry that is already in the ``forcing_vars``
section, then the constant value will take precedence. In the current
implementation there must be at least one non-constant entry in ``forcings_vars``
(i.e. at least one entry that is not also in ``constant_vars``).

For example:
``wind = 2.0``
will result in a constant wind field in the output file. In this case ``wind``
does not need to be specified in the ``forcing_vars`` section. If it was, it
will still be set to a constant value of 2 m/s.

Similarly:
``t_max = 30
t_min = 10``
will result in output with a diurnal cycle in which the temperature varies at
all locations between 10C and 30C. However, all estimation and disaggregation
routines are still evaluated, with constant ``t_max`` and ``t_min`` as input.
10 changes: 10 additions & 0 deletions docs/whats-new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@
What's New
==========

.. _whats-new.2.0.1.develop:

v.2.0.1.develop
-------
Enhancements
~~~~~~~~~~~~
- Allow for specification of constant fields, through addition
of an optional ``constant_vars`` section.


.. _whats-new.2.0.0:

v.2.0.0
Expand Down
3 changes: 2 additions & 1 deletion environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ channels:
- conda-forge
dependencies:
- python>=3.5
- xarray=0.10.9
- xarray>=0.11.0
- pandas
- netcdf4>=1.2.5
- numba
Expand All @@ -12,3 +12,4 @@ dependencies:
- dask
- distributed
- toolz
- pytest
48 changes: 48 additions & 0 deletions examples/example_constant_vars_ascii.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# This is an example of an input file for MetSim
[MetSim]
out_vars = ['temp', 'prec', 'shortwave', 'longwave', 'vapor_pressure', 'rel_humid', 'air_pressure', 'wind']

# Time step in minutes
time_step = 60

# Forcings begin here (year/month/day:hour) (hour optional)
start = 1949/1/1

# Forcings end at this date (year/month/day)
stop = 1949/1/31

# Input and output directories
forcing = ./metsim/data/ascii
domain = ./metsim/data/stehekin.nc
state = ./metsim/data/state_vic.nc
forcing_fmt = ascii
out_dir = ./results
out_prefix = forcing_constant_vars

# How to disaggregate
method = mtclim

[chunks]
lat = 10
lon = 10

# Variables given
[forcing_vars]
prec = prec
t_max = t_max
t_min = t_min
wind = wind

[state_vars]
prec = prec
t_max = t_max
t_min = t_min

[domain_vars]
lat = lat
lon = lon
mask = mask
elev = elev

[constant_vars]
wind = 2.0
44 changes: 44 additions & 0 deletions examples/example_constant_vars_bin.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# This is an example of an input file for MetSim
[MetSim]
out_vars = ['temp', 'prec', 'shortwave', 'longwave', 'vapor_pressure', 'rel_humid', 'air_pressure', 'wind']

# Time step in minutes
time_step = 30
# Forcings begin here (year/month/day:hour) (hour optional)
start = 1949/1/1

# Forcings end at this date (year/month/day)
stop = 1953/12/31

# Input and output directories
forcing = ./metsim/data/binary
domain = ./metsim/data/stehekin.nc
state = ./metsim/data/state_vic.nc
forcing_fmt = binary
out_dir = ./results
out_prefix = forcing_constant_vars

[chunks]
lat = 10
lon = 10

# Variables given
[forcing_vars]
prec = 40.0 unsigned
t_max = 100.0 signed
t_min = 100.0 signed
wind = 100.0 signed

[state_vars]
prec = prec
t_max = t_max
t_min = t_min

[domain_vars]
lat = lat
lon = lon
mask = mask
elev = elev

[constant_vars]
wind = 2.0
52 changes: 52 additions & 0 deletions examples/example_constant_vars_nc.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# This is an example of an input file for MetSim
[MetSim]
out_vars = ['temp', 'prec', 'shortwave', 'longwave', 'vapor_pressure', 'rel_humid', 'air_pressure', 'wind']

# Time step in minutes
time_step = 30

# Forcings begin here (year/month/day:hour) (hour optional)
start = 1950/1/1

# Forcings end at this date (year/month/day)
stop = 1950/1/31

# Input and output directories
forcing = ./metsim/data/test.nc
domain = ./metsim/data/domain.nc
state = ./metsim/data/state_nc.nc

forcing_fmt = netcdf
in_format = netcdf

out_dir = ./results
out_prefix = forcing_constant_vars

prec_type = triangle
utc_offset = True

[chunks]
lat = 3
lon = 3

[forcing_vars]
prec = Prec
t_max = Tmax
t_min = Tmin
wind = wind

[state_vars]
prec = prec
t_max = t_max
t_min = t_min

[domain_vars]
lat = lat
lon = lon
mask = mask
elev = elev
t_pk = t_pk
dur = dur

[constant_vars]
wind = 2.0
8 changes: 5 additions & 3 deletions metsim/cli/ms.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
import os
import sys
from collections import OrderedDict
from configparser import SafeConfigParser
from configparser import ConfigParser


def _is_valid_file(parser, arg):
Expand All @@ -52,13 +52,13 @@ def parse(args):

def init(opts):
"""Initialize some information based on the options & config"""
config = SafeConfigParser()
config = ConfigParser()
config.optionxform = str
config.read(opts.config)
conf = OrderedDict(config['MetSim'])

def invert_dict(d):
return OrderedDict({v: k for k, v in d.items()})
return OrderedDict([reversed(item) for item in d.items()])

def to_list(s):
return json.loads(s.replace("'", '"').split('#')[0])
Expand All @@ -69,6 +69,8 @@ def to_list(s):
conf['domain_vars'] = invert_dict(OrderedDict(config['domain_vars']))
conf['state_vars'] = invert_dict(OrderedDict(config['state_vars']))
conf['chunks'] = OrderedDict(config['chunks'])
if 'constant_vars' in config:
conf['constant_vars'] = OrderedDict(config['constant_vars'])

# If the forcing variable is a directory, scan it for files
if os.path.isdir(conf['forcing']):
Expand Down
6 changes: 3 additions & 3 deletions metsim/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def read_ascii(data_handle, domain=None,
dates = date_range(start, stop, calendar=calendar)
names = var_dict.keys()
ds = pd.read_csv(data_handle, header=None, delim_whitespace=True,
sep='\t', names=names).head(len(dates))
names=names).head(len(dates))
ds.index = dates
return ds

Expand All @@ -146,7 +146,7 @@ def read_netcdf(data_handle, domain=None,
if var_dict is not None:
var_list = list(var_dict.keys())
ds = ds[var_list]
ds.rename(var_dict, inplace=True)
ds = ds.rename(var_dict)

if start is not None or stop is not None:
ds = ds.sel(time=slice(start, stop))
Expand All @@ -162,7 +162,7 @@ def read_data(data_handle, domain=None,
"""Read data directly from an xarray dataset"""
varlist = list(data_handle.keys())
if var_dict is not None:
data_handle.rename(var_dict, inplace=True)
data_handle = data_handle.rename(var_dict)
varlist = list(var_dict.values())
data_handle = data_handle[varlist]

Expand Down
Loading

0 comments on commit 1f23666

Please sign in to comment.