Esempio n. 1
0
def test_soiling_srr_with_precip(normalized_daily, insolation, times):
    precip = pd.Series(index=times, data=0)
    precip['2019-01-18 00:00:00-07:00'] = 1
    precip['2019-02-20 00:00:00-07:00'] = 1

    kwargs = {'reps': 10, 'precipitation_daily': precip}
    np.random.seed(1977)
    sr, sr_ci, soiling_info = soiling_srr(normalized_daily,
                                          insolation,
                                          clean_criterion='precip_and_shift',
                                          **kwargs)
    assert 0.983270 == pytest.approx(sr, abs=1e-6),\
        "Soiling ratio with clean_criterion='precip_and_shift' different from expected"
    np.random.seed(1977)
    sr, sr_ci, soiling_info = soiling_srr(normalized_daily,
                                          insolation,
                                          clean_criterion='precip_or_shift',
                                          **kwargs)
    assert 0.973228 == pytest.approx(sr, abs=1e-6),\
        "Soiling ratio with clean_criterion='precip_or_shift' different from expected"
    np.random.seed(1977)
    sr, sr_ci, soiling_info = soiling_srr(normalized_daily,
                                          insolation,
                                          clean_criterion='precip',
                                          **kwargs)
    assert 0.976196 == pytest.approx(sr, abs=1e-6),\
        "Soiling ratio with clean_criterion='precip' different from expected"
    np.random.seed(1977)
    sr, sr_ci, soiling_info = soiling_srr(normalized_daily,
                                          insolation,
                                          clean_criterion='shift',
                                          **kwargs)
    assert 0.963133 == pytest.approx(sr, abs=1e-6),\
        "Soiling ratio with clean_criterion='shift' different from expected"
Esempio n. 2
0
def test_soiling_srr_min_interval_length(normalized_daily, insolation):
    'Test that a long minimum interval length prevents finding shorter intervals'
    with pytest.raises(NoValidIntervalError):
        np.random.seed(1977)
        # normalized_daily intervals are 25 days long, so min=26 should fail:
        _ = soiling_srr(normalized_daily, insolation, confidence_level=68.2,
                        reps=10, min_interval_length=26)

    # but min=24 should be fine:
    _ = soiling_srr(normalized_daily, insolation, confidence_level=68.2,
                    reps=10, min_interval_length=24)
Esempio n. 3
0
def test_soiling_srr_method(normalized_daily, insolation):
    np.random.seed(1977)
    sr, sr_ci, soiling_info = soiling_srr(normalized_daily, insolation, reps=10,
                                          method='random_clean')
    assert 0.918767 == pytest.approx(sr, abs=1e-6),\
        'Soiling ratio with method="random_clean" different from expected value'

    np.random.seed(1977)
    sr, sr_ci, soiling_info = soiling_srr(normalized_daily, insolation, reps=10,
                                          method='perfect_clean')
    assert 0.965653 == pytest.approx(sr, abs=1e-6),\
        'Soiling ratio with method="perfect_clean" different from expected value'
Esempio n. 4
0
def test_soiling_srr_clean_threshold(normalized_daily, insolation):
    '''Test that clean test_soiling_srr_clean_threshold works with a float and
    can cause no soiling intervals to be found'''
    np.random.seed(1977)
    sr, sr_ci, soiling_info = soiling_srr(normalized_daily, insolation, reps=10,
                                          clean_threshold=0.01)
    assert 0.963133 == pytest.approx(sr, abs=1e-6),\
        'Soiling ratio with specified clean_threshold different from expected value'

    with pytest.raises(NoValidIntervalError):
        np.random.seed(1977)
        sr, sr_ci, soiling_info = soiling_srr(normalized_daily, insolation, reps=10,
                                              clean_threshold=0.1)
Esempio n. 5
0
def test_soiling_srr_outlier_factor(soiling_normalized_daily,
                                    soiling_insolation):
    _, _, info = soiling_srr(soiling_normalized_daily,
                             soiling_insolation,
                             reps=1,
                             outlier_factor=8)
    assert len(info['soiling_interval_summary']) == 2,\
        'Increasing the outlier_factor did not result in the expected number of soiling intervals'
Esempio n. 6
0
def test_soiling_srr_recenter_false(normalized_daily, insolation):
    np.random.seed(1977)
    sr, sr_ci, soiling_info = soiling_srr(normalized_daily, insolation, reps=10,
                                          recenter=False)
    assert 1 == soiling_info['renormalizing_factor'],\
        'Renormalizing factor != 1 with recenter=False'
    assert 0.965158 == pytest.approx(sr, abs=1e-6),\
        'Soiling ratio different than expected when recenter=False'
Esempio n. 7
0
def test_soiling_srr_method(soiling_normalized_daily, soiling_insolation,
                            method, expected_sr):
    np.random.seed(1977)
    sr, sr_ci, soiling_info = soiling_srr(soiling_normalized_daily,
                                          soiling_insolation,
                                          reps=10,
                                          method=method)
    assert expected_sr == pytest.approx(sr, abs=1e-6),\
        f'Soiling ratio with method="{method}" different from expected value'
Esempio n. 8
0
def test_soiling_srr_dayscale(normalized_daily, insolation):
    'Test that a long dayscale can prevent valid intervals from being found'
    with pytest.raises(NoValidIntervalError):
        np.random.seed(1977)
        sr, sr_ci, soiling_info = soiling_srr(normalized_daily,
                                              insolation,
                                              confidence_level=68.2,
                                              reps=10,
                                              day_scale=90)
Esempio n. 9
0
def test_soiling_srr_trim(normalized_daily, insolation):
    np.random.seed(1977)
    sr, sr_ci, soiling_info = soiling_srr(normalized_daily, insolation, reps=10,
                                          trim=True)

    assert 0.978369 == pytest.approx(sr, abs=1e-6),\
        'Soiling ratio with trim=True different from expected value'
    assert len(soiling_info['soiling_interval_summary']) == 1,\
        'Wrong number of soiling intervals found with trim=True'
Esempio n. 10
0
def test_soiling_srr_confidence_levels(normalized_daily, insolation):
    'Tests SRR with different confidence level settingsf from above'
    np.random.seed(1977)
    sr, sr_ci, soiling_info = soiling_srr(normalized_daily, insolation, confidence_level=95, reps=10,
                                          exceedance_prob=80.0)
    assert np.array([0.957272, 0.964763]) == pytest.approx(sr_ci, abs=1e-6),\
        'Confidence interval with confidence_level=95 different than expected'
    assert 0.961285 == pytest.approx(soiling_info['exceedance_level'], abs=1e-6),\
        'soiling_info["exceedance_level"] different than expected when exceedance_prob=80'
Esempio n. 11
0
def test_soiling_srr_max_negative_slope_error(normalized_daily, insolation):
    np.random.seed(1977)
    sr, sr_ci, soiling_info = soiling_srr(normalized_daily, insolation, reps=10,
                                          max_relative_slope_error=50.0)

    assert list(soiling_info['soiling_interval_summary']['valid'].values) == [True, True, False],\
        'Soiling interval validity differs from expected when max_relative_slope_error=50.0'

    assert 0.952995 == pytest.approx(sr, abs=1e-6),\
        'Soiling ratio different from expected when max_relative_slope_error=50.0'
Esempio n. 12
0
def test_soiling_srr_argument_checks(soiling_normalized_daily,
                                     soiling_insolation):
    '''
    Make sure various argument validation warnings and errors are raised
    '''
    kwargs = {
        'energy_normalized_daily': soiling_normalized_daily,
        'insolation_daily': soiling_insolation,
        'reps': 10
    }
    with pytest.warns(UserWarning,
                      match='An even value of day_scale was passed'):
        _ = soiling_srr(day_scale=12, **kwargs)

    with pytest.raises(ValueError, match='clean_criterion must be one of'):
        _ = soiling_srr(clean_criterion='bad', **kwargs)

    with pytest.raises(ValueError, match='Invalid method specification'):
        _ = soiling_srr(method='bad', **kwargs)
Esempio n. 13
0
def test_soiling_srr_kwargs(monkeypatch, normalized_daily, insolation):
    '''
    Make sure that all soiling_srr parameters get passed on to SRRAnalysis and
    SRRAnalysis.run(), i.e. all necessary inputs to SRRAnalysis are provided by
    soiling_srr.  Done by removing the SRRAnalysis default param values
    and making sure everything still runs.
    '''
    # the __defaults__ attr is the tuple of default values in py3
    monkeypatch.delattr(SRRAnalysis.__init__, "__defaults__")
    monkeypatch.delattr(SRRAnalysis.run, "__defaults__")
    _ = soiling_srr(normalized_daily, insolation, reps=10)
Esempio n. 14
0
def test_soiling_srr_with_nan_interval(normalized_daily, insolation, times):
    '''
    Previous versions had a bug which would have raised an error when an entire interval
    was NaN. See https://github.com/NREL/rdtools/issues/129
    '''
    reps = 10
    normalized_corrupt = normalized_daily.copy()
    normalized_corrupt[26:50] = np.nan
    np.random.seed(1977)
    sr, sr_ci, soiling_info = soiling_srr(normalized_corrupt, insolation, reps=reps)
    assert 0.947416 == pytest.approx(sr, abs=1e-6),\
        'Soiling ratio different from expected value when an entire interval was NaN'
Esempio n. 15
0
def test_soiling_srr_consecutive_invalid(soiling_normalized_daily,
                                         soiling_insolation, soiling_times,
                                         method, expected_sr):
    reps = 10
    np.random.seed(1977)
    sr, sr_ci, soiling_info = soiling_srr(soiling_normalized_daily,
                                          soiling_insolation,
                                          reps=reps,
                                          max_relative_slope_error=20.0,
                                          method=method)
    assert expected_sr == pytest.approx(sr, abs=1e-6),\
        f'Soiling ratio different from expected value for {method} with consecutive invalid intervals'  # noqa: E501
Esempio n. 16
0
def test_soiling_srr_negative_step(normalized_daily, insolation):
    stepped_daily = normalized_daily.copy()
    stepped_daily.iloc[37:] = stepped_daily.iloc[25:] - 0.1

    np.random.seed(1977)
    sr, sr_ci, soiling_info = soiling_srr(stepped_daily, insolation, reps=10)

    assert list(soiling_info['soiling_interval_summary']['valid'].values) == [True, False, True],\
        'Soiling interval validity differs from expected when a large negative step\
        is incorporated into the data'

    assert 0.934927 == pytest.approx(sr, abs=1e-6),\
        'Soiling ratio different from expected when a large negative step is incorporated into the data'
Esempio n. 17
0
def test_soiling_srr(normalized_daily, insolation, times):

    reps = 10
    np.random.seed(1977)
    sr, sr_ci, soiling_info = soiling_srr(normalized_daily, insolation, reps=reps)
    assert 0.963133 == pytest.approx(sr, abs=1e-6),\
        'Soiling ratio different from expected value'
    assert np.array([0.961054, 0.964019]) == pytest.approx(sr_ci, abs=1e-6),\
        'Confidence interval different from expected value'
    assert 0.958292 == pytest.approx(soiling_info['exceedance_level'], abs=1e-6),\
        'Exceedance level different from expected value'
    assert 0.984079 == pytest.approx(soiling_info['renormalizing_factor'], abs=1e-6),\
        'Renormalizing factor different from expected value'
    assert len(soiling_info['stochastic_soiling_profiles']) == reps,\
        'Length of soiling_info["stochastic_soiling_profiles"] different than expected'
    assert isinstance(soiling_info['stochastic_soiling_profiles'], list),\
        'soiling_info["stochastic_soiling_profiles"] is not a list'

    # Check soiling_info['soiling_interval_summary']
    expected_summary_columns = ['start', 'end', 'soiling_rate', 'soiling_rate_low', 'soiling_rate_high',
                                'inferred_start_loss', 'inferred_end_loss', 'length', 'valid']
    actual_summary_columns = soiling_info['soiling_interval_summary'].columns.values

    for x in actual_summary_columns:
        assert x in expected_summary_columns,\
            "'{}' not an expected column in soiling_info['soiling_interval_summary']".format(x)
    for x in expected_summary_columns:
        assert x in actual_summary_columns,\
            "'{}' was expected as a column, but not in soiling_info['soiling_interval_summary']".format(x)
    assert isinstance(soiling_info['soiling_interval_summary'], pd.DataFrame),\
        'soiling_info["soiling_interval_summary"] not a dataframe'
    expected_means = pd.Series({'soiling_rate': -0.002617290,
                                'soiling_rate_low': -0.002828525,
                                'soiling_rate_high': -0.002396639,
                                'inferred_start_loss': 1.021514,
                                'inferred_end_loss': 0.9572880,
                                'length': 24.0,
                                'valid': 1.0})
    expected_means = expected_means[['soiling_rate', 'soiling_rate_low', 'soiling_rate_high',
                                     'inferred_start_loss', 'inferred_end_loss',
                                     'length', 'valid']]
    pd.testing.assert_series_equal(expected_means, soiling_info['soiling_interval_summary'].mean(),
                                   check_exact=False, check_less_precise=6)

    # Check soiling_info['soiling_ratio_perfect_clean']
    pd.testing.assert_index_equal(soiling_info['soiling_ratio_perfect_clean'].index, times, check_names=False)
    assert 0.967170 == pytest.approx(soiling_info['soiling_ratio_perfect_clean'].mean(), abs=1e-6),\
        "The mean of soiling_info['soiling_ratio_perfect_clean'] differs from expected"
    assert isinstance(soiling_info['soiling_ratio_perfect_clean'], pd.Series),\
        'soiling_info["soiling_ratio_perfect_clean"] not a pandas series'
Esempio n. 18
0
def test_soiling_srr_max_negative_slope_error(soiling_normalized_daily,
                                              soiling_insolation):
    np.random.seed(1977)
    with pytest.warns(UserWarning, match='20% or more of the daily data'):
        sr, sr_ci, soiling_info = soiling_srr(soiling_normalized_daily,
                                              soiling_insolation,
                                              reps=10,
                                              max_relative_slope_error=45.0)

    assert list(soiling_info['soiling_interval_summary']['valid'].values) == [True, True, False],\
        'Soiling interval validity differs from expected when max_relative_slope_error=45.0'

    assert 0.958761 == pytest.approx(sr, abs=1e-6),\
        'Soiling ratio different from expected when max_relative_slope_error=45.0'
Esempio n. 19
0
def test_soiling_srr_min_interval_length_default(soiling_normalized_daily,
                                                 soiling_insolation, start,
                                                 expected_sr):
    '''
    Make sure that the default value of min_interval_length is 7 days by testing
    on a cropped version of the example data
    '''
    reps = 10
    np.random.seed(1977)
    sr, sr_ci, soiling_info = soiling_srr(soiling_normalized_daily[start:],
                                          soiling_insolation[start:],
                                          reps=reps)
    assert expected_sr == pytest.approx(sr, abs=1e-6),\
        'Soiling ratio different from expected value'
Esempio n. 20
0
def test_soiling_srr_with_precip(soiling_normalized_daily, soiling_insolation,
                                 soiling_times, clean_criterion, expected_sr):
    precip = pd.Series(index=soiling_times, data=0)
    precip['2019-01-18 00:00:00-07:00'] = 1
    precip['2019-02-20 00:00:00-07:00'] = 1

    kwargs = {'reps': 10, 'precipitation_daily': precip}
    np.random.seed(1977)
    sr, sr_ci, soiling_info = soiling_srr(soiling_normalized_daily,
                                          soiling_insolation,
                                          clean_criterion=clean_criterion,
                                          **kwargs)
    assert expected_sr == pytest.approx(sr, abs=1e-6),\
        f"Soiling ratio with clean_criterion='{clean_criterion}' different from expected"
Esempio n. 21
0
def test_soiling_srr_with_nan_interval(soiling_normalized_daily,
                                       soiling_insolation):
    '''
    Previous versions had a bug which would have raised an error when an entire interval
    was NaN. See https://github.com/NREL/rdtools/issues/129
    '''
    reps = 10
    normalized_corrupt = soiling_normalized_daily.copy()
    normalized_corrupt[26:50] = np.nan
    np.random.seed(1977)
    with pytest.warns(UserWarning, match='20% or more of the daily data'):
        sr, sr_ci, soiling_info = soiling_srr(normalized_corrupt,
                                              soiling_insolation,
                                              reps=reps)
    assert 0.948792 == pytest.approx(sr, abs=1e-6),\
        'Soiling ratio different from expected value when an entire interval was NaN'
Esempio n. 22
0
def test_soiling_srr_negative_step(soiling_normalized_daily,
                                   soiling_insolation):
    stepped_daily = soiling_normalized_daily.copy()
    stepped_daily.iloc[37:] = stepped_daily.iloc[37:] - 0.1

    np.random.seed(1977)
    with pytest.warns(UserWarning, match='20% or more of the daily data'):
        sr, sr_ci, soiling_info = soiling_srr(stepped_daily,
                                              soiling_insolation,
                                              reps=10)

    assert list(soiling_info['soiling_interval_summary']['valid'].values) == [True, False, True],\
        'Soiling interval validity differs from expected when a large negative step\
        is incorporated into the data'

    assert 0.936932 == pytest.approx(sr, abs=1e-6),\
        'Soiling ratio different from expected when a large negative step is incorporated into the data'  # noqa: E501
Esempio n. 23
0
def soiling_info(soiling_normalized_daily, soiling_insolation):
    '''
    Return results of running soiling_srr.

    Returns
    -------
    calc_info : dict with keys:
        ['renormalizing_factor', 'exceedance_level',
        'stochastic_soiling_profiles', 'soiling_interval_summary',
        'soiling_ratio_perfect_clean']
    '''
    reps = 10
    np.random.seed(1977)
    sr, sr_ci, calc_info = soiling_srr(soiling_normalized_daily,
                                       soiling_insolation,
                                       reps=reps)
    return calc_info
Esempio n. 24
0
    def _srr_soiling(self, energy_normalized_daily, insolation_daily,
                     **kwargs):
        '''
        Perform stochastic rate and recovery soiling analysis.

        Parameters
        ---------
        energy_normalized_daily : pandas.Series
            Time Series of insolation-weighted aggregated normalized PV energy
        insolation_daily : pandas.Series
            Time Series of insolation, aggregated at same level as energy_normalized_daily
        kwargs :
            Extra parameters passed to soiling.soiling_srr()

        Returns
        -------
        dict
            Soiling results with keys:
            'p50_sratio' : The median insolation-weighted soiling ratio
            'sratio_confidence_interval' : list of lower and upper bounds of
                                          insolation-weighted soiling ratio
                                          confidence interval
            'calc_info' : Dict of detailed results (see soiling.soiling_srr() docs)
        '''

        from rdtools import soiling

        daily_freq = pd.tseries.offsets.Day()
        if (energy_normalized_daily.index.freq != daily_freq
                or insolation_daily.index.freq != daily_freq):
            raise ValueError(
                'Soiling SRR analysis requires daily aggregation.')

        sr, sr_ci, soiling_info = soiling.soiling_srr(energy_normalized_daily,
                                                      insolation_daily,
                                                      **kwargs)

        srr_results = {
            'p50_sratio': sr,
            'sratio_confidence_interval': sr_ci,
            'calc_info': soiling_info
        }

        return srr_results
Esempio n. 25
0
def test_soiling_srr(soiling_normalized_daily, soiling_insolation,
                     soiling_times):

    reps = 10
    np.random.seed(1977)
    sr, sr_ci, soiling_info = soiling_srr(soiling_normalized_daily,
                                          soiling_insolation,
                                          reps=reps)
    assert 0.964369 == pytest.approx(sr, abs=1e-6),\
        'Soiling ratio different from expected value'
    assert np.array([0.962540, 0.965295]) == pytest.approx(sr_ci, abs=1e-6),\
        'Confidence interval different from expected value'
    assert 0.960205 == pytest.approx(soiling_info['exceedance_level'], abs=1e-6),\
        'Exceedance level different from expected value'
    assert 0.984079 == pytest.approx(soiling_info['renormalizing_factor'], abs=1e-6),\
        'Renormalizing factor different from expected value'
    assert len(soiling_info['stochastic_soiling_profiles']) == reps,\
        'Length of soiling_info["stochastic_soiling_profiles"] different than expected'
    assert isinstance(soiling_info['stochastic_soiling_profiles'], list),\
        'soiling_info["stochastic_soiling_profiles"] is not a list'

    # Check soiling_info['soiling_interval_summary']
    expected_summary_columns = [
        'start', 'end', 'soiling_rate', 'soiling_rate_low',
        'soiling_rate_high', 'inferred_start_loss', 'inferred_end_loss',
        'length', 'valid'
    ]
    actual_summary_columns = soiling_info[
        'soiling_interval_summary'].columns.values

    for x in actual_summary_columns:
        assert x in expected_summary_columns,\
            f"'{x}' not an expected column in soiling_info['soiling_interval_summary']"
    for x in expected_summary_columns:
        assert x in actual_summary_columns,\
            f"'{x}' was expected as a column, but not in soiling_info['soiling_interval_summary']"
    assert isinstance(soiling_info['soiling_interval_summary'], pd.DataFrame),\
        'soiling_info["soiling_interval_summary"] not a dataframe'
    expected_means = pd.Series({
        'soiling_rate': -0.002644544,
        'soiling_rate_low': -0.002847504,
        'soiling_rate_high': -0.002455915,
        'inferred_start_loss': 1.020124,
        'inferred_end_loss': 0.9566552,
        'length': 24.0,
        'valid': 1.0
    })
    expected_means = expected_means[[
        'soiling_rate', 'soiling_rate_low', 'soiling_rate_high',
        'inferred_start_loss', 'inferred_end_loss', 'length', 'valid'
    ]]
    actual_means = soiling_info['soiling_interval_summary'][
        expected_means.index].mean()
    pd.testing.assert_series_equal(expected_means,
                                   actual_means,
                                   check_exact=False)

    # Check soiling_info['soiling_ratio_perfect_clean']
    pd.testing.assert_index_equal(
        soiling_info['soiling_ratio_perfect_clean'].index,
        soiling_times,
        check_names=False)
    sr_mean = soiling_info['soiling_ratio_perfect_clean'].mean()
    assert 0.968265 == pytest.approx(sr_mean, abs=1e-6),\
        "The mean of soiling_info['soiling_ratio_perfect_clean'] differs from expected"
    assert isinstance(soiling_info['soiling_ratio_perfect_clean'], pd.Series),\
        'soiling_info["soiling_ratio_perfect_clean"] not a pandas series'