Skip to content

Commit 8ac237d

Browse files
authored
Merge pull request #265 from UW-Hydro/develop
Develop
2 parents 04a6d91 + 117904a commit 8ac237d

File tree

6 files changed

+36
-12
lines changed

6 files changed

+36
-12
lines changed

docs/whats-new.rst

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@
22

33
What's New
44
==========
5+
.. _whats-new.2.4.2:
6+
7+
v2.4.2
8+
------
9+
Bug fixes
10+
~~~~~~~~~
11+
- Aligning longitude values to be within `[-180, +180]`
12+
range to avoid inaccurate time-shifts when `UTC_offset`
13+
option is set to `True`
14+
- Some minor code changes to make MetSim compatible with
15+
pandas >v2.0.0
16+
- When using passthrough option consider shortwave as
17+
full day average rather than daylight average
18+
519
.. _whats-new.2.4.1:
620

721
v2.4.1

metsim/datetime.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010

1111
def date_range(start=None, end=None, periods=None, freq='D', tz=None,
12-
normalize=False, name=None, closed=None, calendar='standard',
12+
normalize=False, name=None, inclusive='both', calendar='standard',
1313
**kwargs):
1414
''' Return a fixed frequency datetime index, with day (calendar) as the
1515
default frequency
@@ -31,9 +31,8 @@ def date_range(start=None, end=None, periods=None, freq='D', tz=None,
3131
Normalize start/end dates to midnight before generating date range
3232
name : str, default None
3333
Name of the resulting index
34-
closed : string or None, default None
35-
Make the interval closed with respect to the given frequency to
36-
the 'left', 'right', or both sides (None)
34+
inclusive : str {“both”, “neither”, “left”, “right”}, default 'both'
35+
Include boundaries; Whether to set each bound as closed or open, both as default
3736
calendar : string
3837
Describes the calendar used in the time calculations. Default is a the
3938
standard calendar (with leap years)
@@ -51,7 +50,7 @@ def date_range(start=None, end=None, periods=None, freq='D', tz=None,
5150
if calendar in ['standard', 'gregorian', 'propoleptic_gregorian']:
5251
return pd.date_range(start=start, end=end, periods=periods,
5352
freq=freq, tz=tz, normalize=normalize, name=name,
54-
closed=closed, **kwargs)
53+
inclusive=inclusive, **kwargs)
5554
else:
5655
# start and end are give
5756
if (start is not None) and (end is not None) and (periods is None):

metsim/disaggregate.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
# along with this program. If not, see <http://www.gnu.org/licenses/>.
1919

2020
import itertools
21+
import math
2122
from typing import Tuple
2223

2324
import numpy as np
@@ -62,6 +63,10 @@ def disaggregate(df_daily: pd.DataFrame, params: dict,
6263
df_disagg:
6364
A dataframe with sub-daily timeseries.
6465
"""
66+
# adjust any longitude values to be within [-180, +180] range
67+
lon_var = params['domain_vars']['lon']
68+
params[lon_var] = math.remainder(params[lon_var], 360)
69+
6570
stop = (df_daily.index[-1] + pd.Timedelta('1 days') -
6671
pd.Timedelta("{} minutes".format(params['time_step'])))
6772
dates_disagg = date_range(df_daily.index[0], stop,
@@ -71,6 +76,9 @@ def disaggregate(df_daily: pd.DataFrame, params: dict,
7176
n_days = len(df_daily)
7277
n_disagg = len(df_disagg)
7378
ts = int(params['time_step'])
79+
### assume passthrough implies shortwave was computed using entire day not just daylight like mtclim uses to derive its shortwave
80+
if (params['method'] == 'passthrough') & (params.get('sw_averaging', '') != 'daylight'):
81+
df_daily['daylength'] = 86400.0
7482
df_disagg['shortwave'] = shortwave(df_daily['shortwave'].values,
7583
df_daily['daylength'].values,
7684
df_daily.index.dayofyear,
@@ -292,7 +300,7 @@ def prec_TRIANGLE(daily_prec, t_min, prec_peak, prec_dur, ts, do_mix):
292300
disagg_prec = np.zeros(int(n_days*ts_per_day))
293301

294302
# Loop over days
295-
for i, (t, P) in enumerate(daily_prec.iteritems()):
303+
for i, (t, P) in enumerate(daily_prec.items()):
296304

297305
if do_mix and t_min[t] < 0:
298306
prec_day = P * np.ones(ts_per_day) / ts_per_day
@@ -637,7 +645,8 @@ def shortwave(sw_rad: np.array, daylength: np.array, day_of_year: np.array,
637645
if params['method'] == 'mtclim' or params.get('sw_averaging', '') == 'daylight':
638646
tmp_rad = (sw_rad * daylength) / (cnst.SEC_PER_HOUR * ts_hourly)
639647
else:
640-
tmp_rad = sw_rad * 24
648+
### if passthrough, still want to do this...but rather than using dailylight daylength uses entire day
649+
tmp_rad = (sw_rad * daylength) / (cnst.SEC_PER_HOUR * ts_hourly) #tmp_rad = sw_rad * 24
641650
n_days = len(tmp_rad)
642651
ts_per_day = int(cnst.HOURS_PER_DAY * cnst.MIN_PER_HOUR / ts)
643652
disaggrad = np.zeros(int(n_days * ts_per_day))

metsim/io.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ def read_netcdf(data_handle, domain=None, is_worker=False,
287287
if isinstance(ds.indexes['time'], xr.CFTimeIndex):
288288
ds['time'] = ds.indexes['time'].to_datetimeindex()
289289
ds['time'] = (ds.indexes['time'] -
290-
pd.Timedelta('11H59M59S')).round('D')
290+
pd.Timedelta(hours=11, minutes=59, seconds=59)).round('D')
291291

292292
if var_dict is not None:
293293
var_list = list(var_dict.keys())

metsim/metsim.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
from dask.diagnostics import ProgressBar
4848
from netCDF4 import Dataset
4949
from cftime import date2num
50+
from datetime import datetime
5051

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

@@ -248,7 +249,7 @@ def _validate_force_times(self, force_times):
248249
force_times.values[i]).to_pydatetime()
249250
elif '/' in self.params[p]:
250251
year, month, day = map(int, self.params[p].split('/'))
251-
self.params[p] = pd.datetime(year, month, day)
252+
self.params[p] = datetime(year, month, day)
252253
else:
253254
self.params[p] = pd.to_datetime(self.params[p])
254255

metsim/tests/test_metsim.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import pandas as pd
1313
import pytest
1414
import xarray as xr
15+
from datetime import datetime
1516

1617
import metsim.cli.ms as cli
1718
import metsim.metsim
@@ -48,9 +49,9 @@ def __init__(self, config):
4849
'binary': './metsim/data/state_vic.nc'}
4950

5051
# Dates to run over
51-
dates = {'netcdf': (pd.datetime(1950, 1, 1), pd.datetime(1950, 1, 31)),
52-
'binary': (pd.datetime(1949, 1, 1), pd.datetime(1949, 12, 31)),
53-
'ascii': (pd.datetime(1949, 1, 1), pd.datetime(1949, 12, 31))}
52+
dates = {'netcdf': (datetime(1950, 1, 1), datetime(1950, 1, 31)),
53+
'binary': (datetime(1949, 1, 1), datetime(1949, 12, 31)),
54+
'ascii': (datetime(1949, 1, 1), datetime(1949, 12, 31))}
5455

5556
# Domain vars
5657
domain_section = {'netcdf': OrderedDict(lat='lat', lon='lon', mask='mask',

0 commit comments

Comments
 (0)