def test_reindex_fill_slice(rfs_series, start, end, start_slice, end_slice, fill_method, exp_val, exp_idx): exp = pd.Series(exp_val, index=pd.DatetimeIndex(exp_idx)) out = forecast.reindex_fill_slice( rfs_series, freq='30min', start=start, end=end, start_slice=start_slice, end_slice=end_slice, fill_method=fill_method) assert_series_equal(out, exp)
def test_reindex_fill_slice_all_nan(): arg = pd.Series([None]*3, index=pd.DatetimeIndex( ['20190101 01', '20190101 02', '20190101 03'])) out = forecast.reindex_fill_slice(arg, freq='30min') exp = pd.Series([None]*5, index=pd.DatetimeIndex( ['20190101 01', '20190101 0130', '20190101 02', '20190101 0230', '20190101 03'])) assert_series_equal(out, exp)
def test_reindex_fill_slice_some_nan(): rfs_series = pd.Series([1, 2, None, 4], index=pd.DatetimeIndex([ '20190101 01', '20190101 02', '20190101 03', '20190101 04', ])) start, end, start_slice, end_slice, fill_method = \ None, None, None, None, 'interpolate' exp_val = [1, 1.5, 2, 2.5, 3, 3.5, 4] exp_idx = [ '20190101 01', '20190101 0130', '20190101 02', '20190101 0230', '20190101 03', '20190101 0330', '20190101 04'] exp = pd.Series(exp_val, index=pd.DatetimeIndex(exp_idx)) out = forecast.reindex_fill_slice( rfs_series, freq='30min', start=start, end=end, start_slice=start_slice, end_slice=end_slice, fill_method=fill_method) assert_series_equal(out, exp)
def test_reindex_fill_slice_none(): out = forecast.reindex_fill_slice(None, freq='30min') assert out is None
def test_reindex_fill_slice_empty(): out = forecast.reindex_fill_slice(pd.Series(dtype=float), freq='30min') assert_series_equal(out, pd.Series(dtype=float))
def _resample_using_cloud_cover(latitude, longitude, elevation, cloud_cover, air_temperature, wind_speed, start, end, interval_label, fill_method, solar_position=None): """ Calculate all irradiance components from cloud cover. Cloud cover from GFS is an interval average with ending label. Air temperature and wind speed are instantaneous values. Intervals are 1, 3, or 6 hours in length. Cloud cover, air temperature, and wind speed from RAP and NAM are instantaneous. To accurately convert from cloud cover to irradiance, we need to interpolate this data to subhourly resolution because solar position and PV power calculations assume instantaneous inputs at each time. Parameters ---------- latitude : float longitude : float elevation : float cloud_cover : pd.Series air_temperature : pd.Series wind_speed : pd.Series start : pd.Timestamp end : pd.Timestamp interval_label : str beginning, ending, or instant fill_method : str 'bfill' (recommended for GFS), 'interpolate' (recommended for NAM/RAP), or any other method of pd.Series. solar_position : pd.DataFrame or None Provide a DataFrame to avoid unnecessary recomputation for e.g. GEFS members. If None, solar position is computed. Returns ------- ghi : pd.Series dni : pd.Series dhi : pd.Series air_temperature : pd.Series wind_speed : pd.Series resampler : function sol_pos_calculator : function When called, immediatedly returns pre-computed solar position. """ # Resample cloud cover, temp, and wind to higher temporal resolution # because solar position and PV power calculations assume instantaneous # inputs. Why 5 minutes? It's a round number that produces order 10 data # points per hour, so it's reasonable for hour average calculations. # Cloud cover should be filled backwards for GFS because model output # represents average over the previous hour and interpolated for RAP and # NAM because model outputs represent instantaneous values. Air temperature # and wind are interpolated because model output represents # instantaneous values. freq = '5min' start_adj, end_adj = adjust_start_end_for_interval_label(interval_label, start, end) cloud_cover = forecast.reindex_fill_slice( cloud_cover, freq=freq, start=start, end=end, start_slice=start_adj, end_slice=end_adj, fill_method=fill_method) resample_fill_slicer = partial( forecast.reindex_fill_slice, freq=freq, start=start, end=end, start_slice=start_adj, end_slice=end_adj, fill_method='interpolate') air_temperature, wind_speed = [ resample_fill_slicer(v) for v in (air_temperature, wind_speed) ] if solar_position is None: solar_position = pvmodel.calculate_solar_position( latitude, longitude, elevation, cloud_cover.index) ghi, dni, dhi = forecast.cloud_cover_to_irradiance( latitude, longitude, elevation, cloud_cover, solar_position['apparent_zenith'], solar_position['zenith']) label = datamodel.CLOSED_MAPPING[interval_label] resampler = partial(forecast.resample, freq='1h', label=label) def solar_pos_calculator(): return solar_position return (ghi, dni, dhi, air_temperature, wind_speed, resampler, solar_pos_calculator)