def sensor_analysis_exp_power(sensor_parameters): power_expected = normalization.pvwatts_dc_power( sensor_parameters['poa_global'], power_dc_rated=1) sensor_parameters['power_expected'] = power_expected rd_analysis = TrendAnalysis(**sensor_parameters) rd_analysis.sensor_analysis(analyses=['yoy_degradation']) return rd_analysis
def test_index_mismatch(): # GH #277 times = pd.date_range('2019-01-01', '2022-01-01', freq='15min') pv = pd.Series(1.0, index=times) dummy_series = pd.Series(1.0, index=times[::4]) # low-frequency weather inputs keys = [ 'poa_global', 'temperature_cell', 'temperature_ambient', 'power_expected', 'windspeed' ] kwargs = {key: dummy_series.copy() for key in keys} rd_analysis = TrendAnalysis(pv, **kwargs) for key in keys: interpolated_series = getattr(rd_analysis, key) assert interpolated_series.index.equals(times) cs_keys = [ 'poa_global_clearsky', 'temperature_cell_clearsky', 'temperature_ambient_clearsky', 'pv_azimuth', 'pv_tilt' ] cs_kwargs = {key: dummy_series.copy() for key in cs_keys} rd_analysis.set_clearsky(**cs_kwargs) for key in cs_keys: interpolated_series = getattr(rd_analysis, key) assert interpolated_series.index.equals(times[1:])
def test_filter_components_no_filters(sensor_parameters): rd_analysis = TrendAnalysis(**sensor_parameters, power_dc_rated=1.0) rd_analysis.filter_params = {} # disable all filters rd_analysis.sensor_analysis(analyses=['yoy_degradation']) expected = pd.Series(True, index=rd_analysis.pv_energy.index) pd.testing.assert_series_equal(rd_analysis.sensor_filter, expected) assert rd_analysis.sensor_filter_components.empty
def test_filter_components(sensor_parameters): poa = sensor_parameters['poa_global'] poa_filter = (poa > 200) & (poa < 1200) rd_analysis = TrendAnalysis(**sensor_parameters, power_dc_rated=1.0) rd_analysis.sensor_analysis(analyses=['yoy_degradation']) assert (poa_filter == rd_analysis.sensor_filter_components['poa_filter'] ).all()
def test_cell_temperature_model_invalid(sensor_parameters): wind = pd.Series(0, index=sensor_parameters['pv'].index) sensor_parameters.pop('temperature_model') rd_analysis = TrendAnalysis(**sensor_parameters, windspeed=wind, temperature_model={'bad': True}) with pytest.raises(ValueError, match='pvlib temperature_model entry is neither'): rd_analysis.sensor_analysis()
def test_sensor_analysis_power_dc_rated(sensor_parameters): rd_analysis = TrendAnalysis(**sensor_parameters, power_dc_rated=1.0) rd_analysis.sensor_analysis(analyses=['yoy_degradation']) yoy_results = rd_analysis.results['sensor']['yoy_degradation'] rd = yoy_results['p50_rd'] ci = yoy_results['rd_confidence_interval'] assert -1 == pytest.approx(rd, abs=1e-2) assert [-1, -1] == pytest.approx(ci, abs=1e-2)
def test_no_gamma_pdc(sensor_parameters): sensor_parameters.pop('gamma_pdc') rd_analysis = TrendAnalysis(**sensor_parameters) with pytest.warns(UserWarning) as record: rd_analysis.sensor_analysis() assert len(record) == 1 assert str( record[0].message).startswith("Temperature coefficient not passed")
def test_sensor_analysis_ad_hoc_filter(sensor_parameters): # by excluding all but a few points, we should trigger the <2yr error filt = pd.Series(False, index=sensor_parameters['pv'].index) filt.iloc[-100:] = True rd_analysis = TrendAnalysis(**sensor_parameters, power_dc_rated=1.0) rd_analysis.filter_params['ad_hoc_filter'] = filt with pytest.raises( ValueError, match="Less than two years of data left after filtering"): rd_analysis.sensor_analysis(analyses=['yoy_degradation'])
def test_sensor_analysis_energy(sensor_parameters, sensor_analysis): sensor_parameters['pv'] = sensor_analysis.pv_energy sensor_parameters['pv_input'] = 'energy' sensor_analysis2 = TrendAnalysis(**sensor_parameters) sensor_analysis2.pv_power = sensor_analysis.pv_power sensor_analysis2.sensor_analysis(analyses=['yoy_degradation']) yoy_results = sensor_analysis2.results['sensor']['yoy_degradation'] rd = yoy_results['p50_rd'] ci = yoy_results['rd_confidence_interval'] assert -1 == pytest.approx(rd, abs=1e-2) assert [-1, -1] == pytest.approx(ci, abs=1e-2)
def test_interpolation(basic_parameters, degradation_trend): power = degradation_trend shifted_index = power.index + pd.to_timedelta('8 minutes') dummy_series = power * 0 + 25 dummy_series.index = shifted_index basic_parameters['pv'] = power basic_parameters['poa_global'] = dummy_series basic_parameters['temperature_ambient'] = dummy_series basic_parameters['temperature_cell'] = dummy_series basic_parameters['windspeed'] = dummy_series basic_parameters['power_expected'] = dummy_series basic_parameters['interp_freq'] = 'H' rd_analysis = TrendAnalysis(**basic_parameters) pd.testing.assert_index_equal(rd_analysis.pv_energy.index, rd_analysis.poa_global.index[1:]) pd.testing.assert_index_equal(rd_analysis.pv_energy.index, rd_analysis.temperature_ambient.index[1:]) pd.testing.assert_index_equal(rd_analysis.pv_energy.index, rd_analysis.temperature_cell.index[1:]) pd.testing.assert_index_equal(rd_analysis.pv_energy.index, rd_analysis.windspeed.index[1:]) pd.testing.assert_index_equal(rd_analysis.pv_energy.index, rd_analysis.power_expected.index[1:]) rd_analysis.set_clearsky(pv_azimuth=dummy_series, pv_tilt=dummy_series, poa_global_clearsky=dummy_series, temperature_cell_clearsky=dummy_series, temperature_ambient_clearsky=dummy_series) pd.testing.assert_index_equal(rd_analysis.pv_energy.index, rd_analysis.pv_azimuth.index) pd.testing.assert_index_equal(rd_analysis.pv_energy.index, rd_analysis.pv_tilt.index) pd.testing.assert_index_equal(rd_analysis.pv_energy.index, rd_analysis.poa_global_clearsky.index) pd.testing.assert_index_equal(rd_analysis.pv_energy.index, rd_analysis.temperature_cell_clearsky.index) pd.testing.assert_index_equal( rd_analysis.pv_energy.index, rd_analysis.temperature_ambient_clearsky.index)
def soiling_analysis_clearsky(soiling_parameters, cs_input): soiling_analysis = TrendAnalysis(**soiling_parameters) soiling_analysis.set_clearsky(**cs_input) np.random.seed(1977) with pytest.warns(UserWarning, match='20% or more of the daily data'): soiling_analysis.clearsky_analysis(analyses=['srr_soiling'], srr_kwargs={'reps': 10}) return soiling_analysis
def clearsky_analysis_exp_power(clearsky_parameters, clearsky_optional): power_expected = normalization.pvwatts_dc_power( clearsky_parameters['poa_global'], power_dc_rated=1) clearsky_parameters['power_expected'] = power_expected rd_analysis = TrendAnalysis(**clearsky_parameters) rd_analysis.set_clearsky(**clearsky_optional) rd_analysis.clearsky_analysis(analyses=['yoy_degradation']) return rd_analysis
def clearsky_parameters(basic_parameters, sensor_parameters, cs_input, degradation_trend): # clear-sky weather data. Uses TrendAnalysis's internal clear-sky # functions to generate the data. rd_analysis = TrendAnalysis(**sensor_parameters) rd_analysis.set_clearsky(**cs_input) rd_analysis._clearsky_preprocess() poa = rd_analysis.poa_global_clearsky clearsky_parameters = basic_parameters clearsky_parameters['poa_global'] = poa clearsky_parameters['pv'] = poa * degradation_trend return clearsky_parameters
def test_errors(sensor_parameters, clearsky_analysis): rdtemp = TrendAnalysis(sensor_parameters['pv']) with pytest.raises(ValueError, match='poa_global must be available'): rdtemp._sensor_preprocess() # no temperature rdtemp = TrendAnalysis(sensor_parameters['pv'], poa_global=sensor_parameters['poa_global']) with pytest.raises(ValueError, match='either cell or ambient temperature'): rdtemp._sensor_preprocess() # clearsky analysis with no tilt/azm clearsky_analysis.pv_tilt = None clearsky_analysis.poa_global_clearsky = None with pytest.raises(ValueError, match='pv_tilt and pv_azimuth must be provided'): clearsky_analysis._clearsky_preprocess() # clearsky analysis with no pvlib.loc clearsky_analysis.pvlib_location = None with pytest.raises(ValueError, match='pvlib location must be provided'): clearsky_analysis._clearsky_preprocess()
def clearsky_analysis(cs_input, clearsky_parameters): rd_analysis = TrendAnalysis(**clearsky_parameters) rd_analysis.set_clearsky(**cs_input) rd_analysis.clearsky_analysis(analyses=['yoy_degradation']) return rd_analysis
def test_filter_ad_hoc_warnings(workflow, sensor_parameters): rd_analysis = TrendAnalysis(**sensor_parameters, power_dc_rated=1.0) rd_analysis.set_clearsky(pvlib_location=pvlib.location.Location(40, -80), poa_global_clearsky=rd_analysis.poa_global) # warning for incomplete index ad_hoc_filter = pd.Series(True, index=sensor_parameters['pv'].index[:-5]) rd_analysis.filter_params['ad_hoc_filter'] = ad_hoc_filter with pytest.warns(UserWarning, match='ad_hoc_filter index does not match index'): if workflow == 'sensor': rd_analysis.sensor_analysis(analyses=['yoy_degradation']) components = rd_analysis.sensor_filter_components else: rd_analysis.clearsky_analysis(analyses=['yoy_degradation']) components = rd_analysis.clearsky_filter_components # missing values set to True assert components['ad_hoc_filter'].all() # warning about NaNs ad_hoc_filter = pd.Series(True, index=sensor_parameters['pv'].index) ad_hoc_filter.iloc[10] = np.nan rd_analysis.filter_params['ad_hoc_filter'] = ad_hoc_filter with pytest.warns( UserWarning, match='ad_hoc_filter contains NaN values; setting to False'): if workflow == 'sensor': rd_analysis.sensor_analysis(analyses=['yoy_degradation']) components = rd_analysis.sensor_filter_components else: rd_analysis.clearsky_analysis(analyses=['yoy_degradation']) components = rd_analysis.clearsky_filter_components # NaN values set to False assert not components['ad_hoc_filter'].iloc[10] assert components.drop(components.index[10])['ad_hoc_filter'].all()
def sensor_analysis(sensor_parameters): rd_analysis = TrendAnalysis(**sensor_parameters) rd_analysis.sensor_analysis(analyses=['yoy_degradation']) return rd_analysis
def soiling_analysis_sensor(soiling_parameters): soiling_analysis = TrendAnalysis(**soiling_parameters) np.random.seed(1977) soiling_analysis.sensor_analysis(analyses=['srr_soiling'], srr_kwargs={'reps': 10}) return soiling_analysis
def test_no_set_clearsky(clearsky_parameters): rd_analysis = TrendAnalysis(**clearsky_parameters) with pytest.raises( AttributeError, match="No poa_global_clearsky. 'set_clearsky' must be run"): rd_analysis.clearsky_analysis()