def test_daytime_zero_at_end_of_day(clearsky_january): ghi = clearsky_january['ghi'].copy() ghi.loc['1/5/2020 16:00':'1/6/2020 00:00'] = 0 _assert_daytime_no_shoulder(clearsky_january['ghi'], daytime.power_or_irradiance(ghi)) # test a period of zeros starting earlier in the day ghi.loc['1/5/2020 12:00':'1/6/2020 00:00'] = 0 _assert_daytime_no_shoulder(clearsky_january['ghi'], daytime.power_or_irradiance(ghi))
def test_daytime(clearsky_january): _assert_daytime_no_shoulder( clearsky_january['ghi'], daytime.power_or_irradiance(clearsky_january['ghi'])) # punch a mid-day hole ghi = clearsky_january['ghi'].copy() ghi.loc['1/10/2020 12:00':'1/10/2020 14:00'] = 0 _assert_daytime_no_shoulder(clearsky_january['ghi'], daytime.power_or_irradiance(ghi))
def test_daytime_with_clipping(clearsky_january): ghi = clearsky_january['ghi'].copy() ghi.loc[ghi >= 500] = 500 _assert_daytime_no_shoulder(clearsky_january['ghi'], daytime.power_or_irradiance(ghi)) # Include a period where data goes to zero during clipping and # returns to normal after the clipping is done ghi.loc[ghi['1/3/2020'].between_time('12:30', '15:30').index] = 0 _assert_daytime_no_shoulder(clearsky_january['ghi'], daytime.power_or_irradiance(ghi))
def test_daytime_missing_data(clearsky_january): ghi = clearsky_january['ghi'].copy() ghi.loc['1/5/2020 16:00':'1/6/2020 11:30'] = np.nan # test with NaNs _assert_daytime_no_shoulder(clearsky_january['ghi'], daytime.power_or_irradiance(ghi)) # test with completely missing data ghi.dropna(inplace=True) _assert_daytime_no_shoulder( ghi, daytime.power_or_irradiance(ghi, freq=pd.infer_freq( clearsky_january.index)))
def test_daytime_split_day(): location = Location(35, -150) clearsky = location.get_clearsky( pd.date_range(start='1/1/2020', end='1/10/2020', freq='15T'), # no tz model='simplified_solis') _assert_daytime_no_shoulder(clearsky['ghi'], daytime.power_or_irradiance(clearsky['ghi']))
def test_daytime_variable(clearsky_january): ghi = clearsky_january['ghi'].copy() np.random.seed(1337) ghi.loc['1/10/2020'] *= np.random.rand(len(ghi['1/10/2020'])) ghi.loc['1/11/2020'] *= np.random.rand(len(ghi['1/11/2020'])) _assert_daytime_no_shoulder(clearsky_january['ghi'], daytime.power_or_irradiance(ghi))
def test_daytime_daylight_savings(albuquerque): spring = pd.date_range(start='2/10/2020', end='4/10/2020', freq='15T', tz='America/Denver') clearsky_spring = albuquerque.get_clearsky(spring, model='simplified_solis') _assert_daytime_no_shoulder( clearsky_spring['ghi'], daytime.power_or_irradiance(clearsky_spring['ghi'])) fall = pd.date_range(start='10/1/2020', end='12/1/2020', freq='15T', tz='America/Denver') clearsky_fall = albuquerque.get_clearsky(fall, model='simplified_solis') _assert_daytime_no_shoulder( clearsky_fall['ghi'], daytime.power_or_irradiance(clearsky_fall['ghi']))
def test_daytime_outliers(clearsky_january): outliers = pd.Series(False, index=clearsky_january.index) outliers.loc['1/5/2020 13:00'] = True outliers.loc['1/5/2020 14:00'] = True outliers.loc['1/10/2020 02:00'] = True ghi = clearsky_january['ghi'].copy() ghi.loc['1/5/2020 1300'] = 999 ghi.loc['1/5/2020 14:00'] = -999 ghi.loc['1/10/2020 02:00'] = -999 _assert_daytime_no_shoulder( clearsky_january['ghi'], daytime.power_or_irradiance(clearsky_january['ghi'], outliers=outliers))
def test_daytime_overcast(clearsky_january): ghi = clearsky_january['ghi'].copy() ghi.loc['1/3/2020':'1/5/2020'] *= 0.5 ghi.loc['1/7/2020':'1/8/2020'] *= 0.6 _assert_daytime_no_shoulder(clearsky_january['ghi'], daytime.power_or_irradiance(ghi))
def test_daytime_zero_at_start_of_day(clearsky_january): ghi = clearsky_january['ghi'].copy() ghi.loc['1/5/2020 00:00':'1/5/2020 09:00'] = 0 _assert_daytime_no_shoulder(clearsky_january['ghi'], daytime.power_or_irradiance(ghi))
data['ac_power__752'].plot() plt.xlabel("Date") plt.ylabel("AC Power (kW)") plt.tight_layout() plt.show() # %% # It is critical to set all negative values in the AC power time series to 0 # for :py:func:`pvanalytics.features.daytime.power_or_irradiance` to work # properly. Negative erroneous data may affect daytime mask assignments. data.loc[data['ac_power__752'] < 0, 'ac_power__752'] = 0 # %% # Now, use :py:func:`pvanalytics.features.daytime.power_or_irradiance` # to mask day periods in the time series. predicted_day_night_mask = power_or_irradiance(series=data['ac_power__752'], freq=freq) # %% # Function :py:func:`pvlib.solarposition.sun_rise_set_transit_spa` is # used to get ground-truth sunrise and sunset times for each day at the site # location, and a SPA-daytime mask is calculated based on these times. Data # associated with SPA daytime periods is labeled as True, and data associated # with SPA nighttime periods is labeled as False. # SPA sunrise and sunset times are used here as a point of comparison to the # :py:func:`pvanalytics.features.daytime.power_or_irradiance` outputs. # SPA-based sunrise and sunset values are not # needed to run :py:func:`pvanalytics.features.daytime.power_or_irradiance`. sunrise_sunset_df = pvlib.solarposition.sun_rise_set_transit_spa( data.index, latitude, longitude) data['sunrise_time'] = sunrise_sunset_df['sunrise']
# Here, we check GHI data in field 'irradiance_ghi__7981'. # :py:func:`pvanalytics.quality.irradiance.clearsky_limits` # returns a mask that identifies data that falls between # lower and upper limits. The defaults (used here) # are upper bound of 110% of clear-sky GHI, and # no lower bound. clearsky_limit_mask = clearsky_limits(data['irradiance_ghi__7981'], clearsky['ghi']) # %% # Mask nighttime values in the GHI time series using the # :py:func:`pvanalytics.features.daytime.power_or_irradiance` function. # We will then remove nighttime values from the GHI time series. day_night_mask = power_or_irradiance(series=data['irradiance_ghi__7981'], freq=freq) # %% # Plot the 'irradiance_ghi__7981' data stream and its associated clearsky GHI # data stream. Mask the GHI time series by its clearsky_limit_mask for daytime # periods. # Please note that a simple Ineichen model with static monthly turbidities # isn't always accurate, as in this case. Other models that may provide better # clear-sky estimates include McClear or PSM3. data['irradiance_ghi__7981'].plot() clearsky['ghi'].plot() data.loc[clearsky_limit_mask & day_night_mask]['irradiance_ghi__7981'].plot( ls='', marker='.') plt.legend(labels=["RMIS GHI", "Clearsky GHI", "Under Clearsky Limit"], loc="upper left") plt.xlabel("Date")