Skip to content

Commit

Permalink
Merge pull request #265 from UW-Hydro/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
arbennett authored Nov 2, 2023
2 parents 04a6d91 + 117904a commit 8ac237d
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 12 deletions.
14 changes: 14 additions & 0 deletions docs/whats-new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@

What's New
==========
.. _whats-new.2.4.2:

v2.4.2
------
Bug fixes
~~~~~~~~~
- Aligning longitude values to be within `[-180, +180]`
range to avoid inaccurate time-shifts when `UTC_offset`
option is set to `True`
- Some minor code changes to make MetSim compatible with
pandas >v2.0.0
- When using passthrough option consider shortwave as
full day average rather than daylight average

.. _whats-new.2.4.1:

v2.4.1
Expand Down
9 changes: 4 additions & 5 deletions metsim/datetime.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@


def date_range(start=None, end=None, periods=None, freq='D', tz=None,
normalize=False, name=None, closed=None, calendar='standard',
normalize=False, name=None, inclusive='both', calendar='standard',
**kwargs):
''' Return a fixed frequency datetime index, with day (calendar) as the
default frequency
Expand All @@ -31,9 +31,8 @@ def date_range(start=None, end=None, periods=None, freq='D', tz=None,
Normalize start/end dates to midnight before generating date range
name : str, default None
Name of the resulting index
closed : string or None, default None
Make the interval closed with respect to the given frequency to
the 'left', 'right', or both sides (None)
inclusive : str {“both”, “neither”, “left”, “right”}, default 'both'
Include boundaries; Whether to set each bound as closed or open, both as default
calendar : string
Describes the calendar used in the time calculations. Default is a the
standard calendar (with leap years)
Expand All @@ -51,7 +50,7 @@ def date_range(start=None, end=None, periods=None, freq='D', tz=None,
if calendar in ['standard', 'gregorian', 'propoleptic_gregorian']:
return pd.date_range(start=start, end=end, periods=periods,
freq=freq, tz=tz, normalize=normalize, name=name,
closed=closed, **kwargs)
inclusive=inclusive, **kwargs)
else:
# start and end are give
if (start is not None) and (end is not None) and (periods is None):
Expand Down
13 changes: 11 additions & 2 deletions metsim/disaggregate.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import itertools
import math
from typing import Tuple

import numpy as np
Expand Down Expand Up @@ -62,6 +63,10 @@ def disaggregate(df_daily: pd.DataFrame, params: dict,
df_disagg:
A dataframe with sub-daily timeseries.
"""
# adjust any longitude values to be within [-180, +180] range
lon_var = params['domain_vars']['lon']
params[lon_var] = math.remainder(params[lon_var], 360)

stop = (df_daily.index[-1] + pd.Timedelta('1 days') -
pd.Timedelta("{} minutes".format(params['time_step'])))
dates_disagg = date_range(df_daily.index[0], stop,
Expand All @@ -71,6 +76,9 @@ def disaggregate(df_daily: pd.DataFrame, params: dict,
n_days = len(df_daily)
n_disagg = len(df_disagg)
ts = int(params['time_step'])
### assume passthrough implies shortwave was computed using entire day not just daylight like mtclim uses to derive its shortwave
if (params['method'] == 'passthrough') & (params.get('sw_averaging', '') != 'daylight'):
df_daily['daylength'] = 86400.0
df_disagg['shortwave'] = shortwave(df_daily['shortwave'].values,
df_daily['daylength'].values,
df_daily.index.dayofyear,
Expand Down Expand Up @@ -292,7 +300,7 @@ def prec_TRIANGLE(daily_prec, t_min, prec_peak, prec_dur, ts, do_mix):
disagg_prec = np.zeros(int(n_days*ts_per_day))

# Loop over days
for i, (t, P) in enumerate(daily_prec.iteritems()):
for i, (t, P) in enumerate(daily_prec.items()):

if do_mix and t_min[t] < 0:
prec_day = P * np.ones(ts_per_day) / ts_per_day
Expand Down Expand Up @@ -637,7 +645,8 @@ def shortwave(sw_rad: np.array, daylength: np.array, day_of_year: np.array,
if params['method'] == 'mtclim' or params.get('sw_averaging', '') == 'daylight':
tmp_rad = (sw_rad * daylength) / (cnst.SEC_PER_HOUR * ts_hourly)
else:
tmp_rad = sw_rad * 24
### if passthrough, still want to do this...but rather than using dailylight daylength uses entire day
tmp_rad = (sw_rad * daylength) / (cnst.SEC_PER_HOUR * ts_hourly) #tmp_rad = sw_rad * 24
n_days = len(tmp_rad)
ts_per_day = int(cnst.HOURS_PER_DAY * cnst.MIN_PER_HOUR / ts)
disaggrad = np.zeros(int(n_days * ts_per_day))
Expand Down
2 changes: 1 addition & 1 deletion metsim/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ def read_netcdf(data_handle, domain=None, is_worker=False,
if isinstance(ds.indexes['time'], xr.CFTimeIndex):
ds['time'] = ds.indexes['time'].to_datetimeindex()
ds['time'] = (ds.indexes['time'] -
pd.Timedelta('11H59M59S')).round('D')
pd.Timedelta(hours=11, minutes=59, seconds=59)).round('D')

if var_dict is not None:
var_list = list(var_dict.keys())
Expand Down
3 changes: 2 additions & 1 deletion metsim/metsim.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
from dask.diagnostics import ProgressBar
from netCDF4 import Dataset
from cftime import date2num
from datetime import datetime

from xarray.backends.locks import get_write_lock, combine_locks, NETCDFC_LOCK

Expand Down Expand Up @@ -248,7 +249,7 @@ def _validate_force_times(self, force_times):
force_times.values[i]).to_pydatetime()
elif '/' in self.params[p]:
year, month, day = map(int, self.params[p].split('/'))
self.params[p] = pd.datetime(year, month, day)
self.params[p] = datetime(year, month, day)
else:
self.params[p] = pd.to_datetime(self.params[p])

Expand Down
7 changes: 4 additions & 3 deletions metsim/tests/test_metsim.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import pandas as pd
import pytest
import xarray as xr
from datetime import datetime

import metsim.cli.ms as cli
import metsim.metsim
Expand Down Expand Up @@ -48,9 +49,9 @@ def __init__(self, config):
'binary': './metsim/data/state_vic.nc'}

# Dates to run over
dates = {'netcdf': (pd.datetime(1950, 1, 1), pd.datetime(1950, 1, 31)),
'binary': (pd.datetime(1949, 1, 1), pd.datetime(1949, 12, 31)),
'ascii': (pd.datetime(1949, 1, 1), pd.datetime(1949, 12, 31))}
dates = {'netcdf': (datetime(1950, 1, 1), datetime(1950, 1, 31)),
'binary': (datetime(1949, 1, 1), datetime(1949, 12, 31)),
'ascii': (datetime(1949, 1, 1), datetime(1949, 12, 31))}

# Domain vars
domain_section = {'netcdf': OrderedDict(lat='lat', lon='lon', mask='mask',
Expand Down

0 comments on commit 8ac237d

Please sign in to comment.