Skip to content

Commit 0e01b4a

Browse files
authored
Merge pull request #212 from UW-Hydro/develop
Prep for 2.2.1 release
2 parents 81af2d0 + 5dca985 commit 0e01b4a

File tree

3 files changed

+66
-19
lines changed

3 files changed

+66
-19
lines changed

docs/whats-new.rst

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,20 @@ What's New
55

66
.. _whats-new.2.2.0:
77

8+
v2.2.l
9+
------
10+
Bug fixes
11+
~~~~~~~~~
12+
- Fixed bug where timestamps got duplicated for sub-hourly
13+
disaggregation time periods
14+
- Fixed bug where polar latitudes caused error in setting
15+
the rise and set times for temperature disaggregation
16+
817
v2.2.0
918
-------
1019
Enhancements
1120
~~~~~~~~~~~~
12-
- Can now specify ``period_ending`` in the configuration to move
21+
- Can now specify ``period_ending`` in the configuration to move
1322
timestamps to end of period instead of beginning of period
1423
- Addition of tutorial in README.md and main documentation
1524
- Addition of paper to be submitted to JOSS

metsim/disaggregate.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
from metsim.datetime import date_range
2929
from metsim.physics import svp
3030

31+
import sys
3132

3233
def disaggregate(df_daily: pd.DataFrame, params: dict,
3334
solar_geom: dict, t_begin: list=None,
@@ -77,6 +78,7 @@ def disaggregate(df_daily: pd.DataFrame, params: dict,
7778

7879
t_Tmin, t_Tmax = set_min_max_hour(solar_geom['tiny_rad_fract'],
7980
df_daily.index.dayofyear - 1,
81+
solar_geom['daylength'],
8082
n_days, ts, params)
8183

8284
df_disagg['temp'] = temp(
@@ -114,8 +116,8 @@ def disaggregate(df_daily: pd.DataFrame, params: dict,
114116
return df_disagg.fillna(method='ffill').fillna(method='bfill')
115117

116118

117-
def set_min_max_hour(tiny_rad_fract: np.array, yday: np.array, n_days: int,
118-
ts: int, params: dict) -> Tuple[np.array]:
119+
def set_min_max_hour(tiny_rad_fract: np.ndarray, yday: np.ndarray, daylength: np.ndarray,
120+
n_days: int, ts: int, params: dict) -> Tuple[np.ndarray]:
119121
"""
120122
Determine the time at which min and max temp
121123
is reached for each day.
@@ -146,11 +148,26 @@ def set_min_max_hour(tiny_rad_fract: np.array, yday: np.array, n_days: int,
146148
# calculate minute of sunrise and sunset for each day of the year
147149
rad_mask = 1 * (tiny_rad_fract > 0)
148150
mask = np.diff(rad_mask)
149-
rise_times = np.where(mask > 0)[1] * (cnst.SW_RAD_DT / cnst.SEC_PER_MIN)
150-
set_times = np.where(mask < 0)[1] * (cnst.SW_RAD_DT / cnst.SEC_PER_MIN)
151+
152+
# north of the polar circle radiation values of mask </> 0 are eleminated for
153+
# sunset/sunrise resulting in an array containing less than 365 days for one year
154+
rise_times = np.zeros(mask.shape[0])
155+
loc, mult = np.where(mask > 0)
156+
for i, j in zip(loc, mult):
157+
rise_times[i] = j * (cnst.SW_RAD_DT / cnst.SEC_PER_MIN)
158+
159+
set_times = np.zeros(mask.shape[0])
160+
loc, mult = np.where(mask < 0)
161+
for i, j in zip(loc, mult):
162+
set_times[i] = j * (cnst.SW_RAD_DT / cnst.SEC_PER_MIN)
163+
164+
# Set rise and set times to be equally spaced when in polar region
165+
day_tot = ((cnst.SEC_PER_DAY / cnst.SW_RAD_DT)
166+
* (cnst.SW_RAD_DT / cnst.SEC_PER_MIN))
167+
rise_times[rise_times == 0] = day_tot / 6
168+
set_times[set_times == 0] = 4 * day_tot / 6
151169

152170
if params['utc_offset']:
153-
# not used elsewhere:
154171
# rad_fract_per_day = int(cnst.SEC_PER_DAY/cnst.SW_RAD_DT)
155172
utc_offset = int(((params.get("lon", 0) - params.get("theta_s", 0)) /
156173
cnst.DEG_PER_REV) * cnst.MIN_PER_DAY)

metsim/metsim.py

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -70,31 +70,44 @@
7070

7171
attrs = {'pet': {'units': 'mm timestep-1',
7272
'long_name': 'potential evaporation',
73-
'standard_name': 'water_potential_evaporation_flux'},
73+
'standard_name': 'water_potential_evaporation_flux',
74+
'missing_value': np.nan, 'fill_value': np.nan},
7475
'prec': {'units': 'mm timestep-1', 'long_name': 'precipitation',
75-
'standard_name': 'precipitation_flux'},
76+
'standard_name': 'precipitation_flux',
77+
'missing_value': np.nan, 'fill_value': np.nan},
7678
'shortwave': {'units': 'W m-2', 'long_name': 'shortwave radiation',
77-
'standard_name': 'surface_downwelling_shortwave_flux'},
79+
'standard_name': 'surface_downwelling_shortwave_flux',
80+
'missing_value': np.nan, 'fill_value': np.nan},
7881
'longwave': {'units': 'W m-2', 'long_name': 'longwave radiation',
79-
'standard_name': 'surface_downwelling_longwave_flux'},
82+
'standard_name': 'surface_downwelling_longwave_flux',
83+
'missing_value': np.nan, 'fill_value': np.nan},
8084
't_max': {'units': 'C', 'long_name': 'maximum daily air temperature',
81-
'standard_name': 'daily_maximum_air_temperature'},
85+
'standard_name': 'daily_maximum_air_temperature',
86+
'missing_value': np.nan, 'fill_value': np.nan},
8287
't_min': {'units': 'C', 'long_name': 'minimum daily air temperature',
83-
'standard_name': 'daily_minimum_air_temperature'},
88+
'standard_name': 'daily_minimum_air_temperature',
89+
'missing_value': np.nan, 'fill_value': np.nan},
8490
'temp': {'units': 'C', 'long_name': 'air temperature',
85-
'standard_name': 'air_temperature'},
91+
'standard_name': 'air_temperature',
92+
'missing_value': np.nan, 'fill_value': np.nan},
8693
'vapor_pressure': {'units': 'kPa', 'long_name': 'vapor pressure',
87-
'standard_name': 'vapor_pressure'},
94+
'standard_name': 'vapor_pressure',
95+
'missing_value': np.nan, 'fill_value': np.nan},
8896
'air_pressure': {'units': 'kPa', 'long_name': 'air pressure',
89-
'standard_name': 'air_pressure'},
97+
'standard_name': 'air_pressure',
98+
'missing_value': np.nan, 'fill_value': np.nan},
9099
'tskc': {'units': 'fraction', 'long_name': 'cloud fraction',
91-
'standard_name': 'cloud_fraction'},
100+
'standard_name': 'cloud_fraction',
101+
'missing_value': np.nan, 'fill_value': np.nan},
92102
'rel_humid': {'units': '%', 'long_name': 'relative humidity',
93-
'standard_name': 'relative_humidity'},
103+
'standard_name': 'relative_humidity',
104+
'missing_value': np.nan, 'fill_value': np.nan},
94105
'spec_humid': {'units': '', 'long_name': 'specific humidity',
95-
'standard_name': 'specific_humidity'},
106+
'standard_name': 'specific_humidity',
107+
'missing_value': np.nan, 'fill_value': np.nan},
96108
'wind': {'units': 'm/s', 'long_name': 'wind speed',
97-
'standard_name': 'wind_speed'},
109+
'standard_name': 'wind_speed',
110+
'missing_value': np.nan, 'fill_value': np.nan},
98111
'_global': {'conventions': '1.6', 'title': 'Output from MetSim',
99112
'institution': 'University of Washington',
100113
'source': 'metsim.py',
@@ -408,6 +421,14 @@ def run_slice(self):
408421
self.setup_output()
409422
times = self.met_data['time']
410423
params = self.params.copy()
424+
# transform input parameters to floating point values
425+
params['sw_prec_thresh'] = float(params['sw_prec_thresh'])
426+
params['rain_scalar'] = float(params['rain_scalar'])
427+
params['tdew_tol'] = float(params['tdew_tol'])
428+
params['tmax_daylength_fraction'] = float(params['tmax_daylength_fraction'])
429+
params['tday_coef'] = float(params['tday_coef'])
430+
params['tmax_daylength_fraction'] = float(params['tmax_daylength_fraction'])
431+
params['lapse_rate'] = float(params['lapse_rate'])
411432
for index, mask_val in np.ndenumerate(self.domain['mask'].values):
412433
if mask_val > 0:
413434
locs = {d: i for d, i in zip(self.domain['mask'].dims, index)}

0 commit comments

Comments
 (0)