From 80f910f4278d3c9498a07d241175b3817856a250 Mon Sep 17 00:00:00 2001 From: anomam Date: Thu, 13 Dec 2018 18:06:53 +0900 Subject: [PATCH 01/27] Set up import of pvfactors package --- pvlib/irradiance.py | 249 +++++++++++++++++++--------------- pvlib/test/conftest.py | 32 +++++ pvlib/test/test_irradiance.py | 230 +++++++++++++++++-------------- setup.py | 2 +- 4 files changed, 303 insertions(+), 210 deletions(-) diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index 4855187ea4..0b6f8ae5f1 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -113,7 +113,7 @@ def get_extra_radiation(datetime_or_doy, solar_constant=1366.1, extraradiation = deprecated('0.6', alternative='get_extra_radiation', name='extraradiation', removal='0.7')( - get_extra_radiation) + get_extra_radiation) def _handle_extra_radiation_types(datetime_or_doy, epoch_year): @@ -125,6 +125,7 @@ def _handle_extra_radiation_types(datetime_or_doy, epoch_year): # a better way to do it. if isinstance(datetime_or_doy, pd.DatetimeIndex): to_doy = tools._pandas_to_doy # won't be evaluated unless necessary + def to_datetimeindex(x): return x # noqa: E306 to_output = partial(pd.Series, index=datetime_or_doy) elif isinstance(datetime_or_doy, pd.Timestamp): @@ -368,7 +369,7 @@ def get_total_irradiance(surface_tilt, surface_azimuth, total_irrad = deprecated('0.6', alternative='get_total_irradiance', name='total_irrad', removal='0.7')( - get_total_irradiance) + get_total_irradiance) def get_sky_diffuse(surface_tilt, surface_azimuth, @@ -629,7 +630,7 @@ def get_ground_diffuse(surface_tilt, ghi, albedo=.25, surface_type=None): grounddiffuse = deprecated('0.6', alternative='get_ground_diffuse', name='grounddiffuse', removal='0.7')( - get_ground_diffuse) + get_ground_diffuse) def isotropic(surface_tilt, dhi): @@ -1428,18 +1429,18 @@ def _disc_kn(clearness_index, airmass, max_airmass=12): bools = (kt <= 0.6) a = np.where(bools, - 0.512 - 1.56*kt + 2.286*kt2 - 2.222*kt3, - -5.743 + 21.77*kt - 27.49*kt2 + 11.56*kt3) + 0.512 - 1.56 * kt + 2.286 * kt2 - 2.222 * kt3, + -5.743 + 21.77 * kt - 27.49 * kt2 + 11.56 * kt3) b = np.where(bools, - 0.37 + 0.962*kt, - 41.4 - 118.5*kt + 66.05*kt2 + 31.9*kt3) + 0.37 + 0.962 * kt, + 41.4 - 118.5 * kt + 66.05 * kt2 + 31.9 * kt3) c = np.where(bools, - -0.28 + 0.932*kt - 2.048*kt2, - -47.01 + 184.2*kt - 222.0*kt2 + 73.81*kt3) + -0.28 + 0.932 * kt - 2.048 * kt2, + -47.01 + 184.2 * kt - 222.0 * kt2 + 73.81 * kt3) - delta_kn = a + b * np.exp(c*am) + delta_kn = a + b * np.exp(c * am) - Knc = 0.866 - 0.122*am + 0.0121*am**2 - 0.000653*am**3 + 1.4e-05*am**4 + Knc = 0.866 - 0.122 * am + 0.0121 * am**2 - 0.000653 * am**3 + 1.4e-05 * am**4 Kn = Knc - delta_kn return Kn, am @@ -1563,9 +1564,9 @@ def _delta_kt_prime_dirint(kt_prime, use_delta_kt_prime, times): """ if use_delta_kt_prime: # Perez eqn 2 - delta_kt_prime = 0.5*((kt_prime - kt_prime.shift(1)).abs().add( - (kt_prime - kt_prime.shift(-1)).abs(), - fill_value=0)) + delta_kt_prime = 0.5 * ((kt_prime - kt_prime.shift(1)).abs().add( + (kt_prime - kt_prime.shift(-1)).abs(), + fill_value=0)) else: # do not change unless also modifying _dirint_bins delta_kt_prime = pd.Series(-1, index=times) @@ -1612,8 +1613,8 @@ def _dirint_coeffs(times, kt_prime, solar_zenith, w, delta_kt_prime): # subtract 1 to account for difference between MATLAB-style bin # assignment and Python-style array lookup. - dirint_coeffs = coeffs[kt_prime_bin-1, zenith_bin-1, - delta_kt_prime_bin-1, w_bin-1] + dirint_coeffs = coeffs[kt_prime_bin - 1, zenith_bin - 1, + delta_kt_prime_bin - 1, w_bin - 1] # convert unassigned bins to nan dirint_coeffs = np.where((kt_prime_bin == 0) | (zenith_bin == 0) | @@ -2163,12 +2164,12 @@ def erbs(ghi, zenith, doy): kt = np.maximum(kt, 0) # For Kt <= 0.22, set the diffuse fraction - df = 1 - 0.09*kt + df = 1 - 0.09 * kt # For Kt > 0.22 and Kt <= 0.8, set the diffuse fraction df = np.where((kt > 0.22) & (kt <= 0.8), - 0.9511 - 0.1604*kt + 4.388*kt**2 - - 16.638*kt**3 + 12.336*kt**4, + 0.9511 - 0.1604 * kt + 4.388 * kt**2 - + 16.638 * kt**3 + 12.336 * kt**4, df) # For Kt > 0.8, set the diffuse fraction @@ -2232,7 +2233,7 @@ def liujordan(zenith, transmittance, airmass, dni_extra=1367.0): tau = transmittance - dni = dni_extra*tau**airmass + dni = dni_extra * tau**airmass dhi = 0.3 * (1.0 - tau**airmass) * dni_extra * np.cos(np.radians(zenith)) ghi = dhi + dni * np.cos(np.radians(zenith)) @@ -2300,104 +2301,104 @@ def _get_perez_coefficients(perezmodel): ''' coeffdict = { 'allsitescomposite1990': [ - [-0.0080, 0.5880, -0.0620, -0.0600, 0.0720, -0.0220], - [0.1300, 0.6830, -0.1510, -0.0190, 0.0660, -0.0290], - [0.3300, 0.4870, -0.2210, 0.0550, -0.0640, -0.0260], - [0.5680, 0.1870, -0.2950, 0.1090, -0.1520, -0.0140], - [0.8730, -0.3920, -0.3620, 0.2260, -0.4620, 0.0010], - [1.1320, -1.2370, -0.4120, 0.2880, -0.8230, 0.0560], - [1.0600, -1.6000, -0.3590, 0.2640, -1.1270, 0.1310], - [0.6780, -0.3270, -0.2500, 0.1560, -1.3770, 0.2510]], + [-0.0080, 0.5880, -0.0620, -0.0600, 0.0720, -0.0220], + [0.1300, 0.6830, -0.1510, -0.0190, 0.0660, -0.0290], + [0.3300, 0.4870, -0.2210, 0.0550, -0.0640, -0.0260], + [0.5680, 0.1870, -0.2950, 0.1090, -0.1520, -0.0140], + [0.8730, -0.3920, -0.3620, 0.2260, -0.4620, 0.0010], + [1.1320, -1.2370, -0.4120, 0.2880, -0.8230, 0.0560], + [1.0600, -1.6000, -0.3590, 0.2640, -1.1270, 0.1310], + [0.6780, -0.3270, -0.2500, 0.1560, -1.3770, 0.2510]], 'allsitescomposite1988': [ - [-0.0180, 0.7050, -0.071, -0.0580, 0.1020, -0.0260], - [0.1910, 0.6450, -0.1710, 0.0120, 0.0090, -0.0270], - [0.4400, 0.3780, -0.2560, 0.0870, -0.1040, -0.0250], - [0.7560, -0.1210, -0.3460, 0.1790, -0.3210, -0.0080], - [0.9960, -0.6450, -0.4050, 0.2600, -0.5900, 0.0170], - [1.0980, -1.2900, -0.3930, 0.2690, -0.8320, 0.0750], - [0.9730, -1.1350, -0.3780, 0.1240, -0.2580, 0.1490], - [0.6890, -0.4120, -0.2730, 0.1990, -1.6750, 0.2370]], + [-0.0180, 0.7050, -0.071, -0.0580, 0.1020, -0.0260], + [0.1910, 0.6450, -0.1710, 0.0120, 0.0090, -0.0270], + [0.4400, 0.3780, -0.2560, 0.0870, -0.1040, -0.0250], + [0.7560, -0.1210, -0.3460, 0.1790, -0.3210, -0.0080], + [0.9960, -0.6450, -0.4050, 0.2600, -0.5900, 0.0170], + [1.0980, -1.2900, -0.3930, 0.2690, -0.8320, 0.0750], + [0.9730, -1.1350, -0.3780, 0.1240, -0.2580, 0.1490], + [0.6890, -0.4120, -0.2730, 0.1990, -1.6750, 0.2370]], 'sandiacomposite1988': [ - [-0.1960, 1.0840, -0.0060, -0.1140, 0.1800, -0.0190], - [0.2360, 0.5190, -0.1800, -0.0110, 0.0200, -0.0380], - [0.4540, 0.3210, -0.2550, 0.0720, -0.0980, -0.0460], - [0.8660, -0.3810, -0.3750, 0.2030, -0.4030, -0.0490], - [1.0260, -0.7110, -0.4260, 0.2730, -0.6020, -0.0610], - [0.9780, -0.9860, -0.3500, 0.2800, -0.9150, -0.0240], - [0.7480, -0.9130, -0.2360, 0.1730, -1.0450, 0.0650], - [0.3180, -0.7570, 0.1030, 0.0620, -1.6980, 0.2360]], + [-0.1960, 1.0840, -0.0060, -0.1140, 0.1800, -0.0190], + [0.2360, 0.5190, -0.1800, -0.0110, 0.0200, -0.0380], + [0.4540, 0.3210, -0.2550, 0.0720, -0.0980, -0.0460], + [0.8660, -0.3810, -0.3750, 0.2030, -0.4030, -0.0490], + [1.0260, -0.7110, -0.4260, 0.2730, -0.6020, -0.0610], + [0.9780, -0.9860, -0.3500, 0.2800, -0.9150, -0.0240], + [0.7480, -0.9130, -0.2360, 0.1730, -1.0450, 0.0650], + [0.3180, -0.7570, 0.1030, 0.0620, -1.6980, 0.2360]], 'usacomposite1988': [ - [-0.0340, 0.6710, -0.0590, -0.0590, 0.0860, -0.0280], - [0.2550, 0.4740, -0.1910, 0.0180, -0.0140, -0.0330], - [0.4270, 0.3490, -0.2450, 0.0930, -0.1210, -0.0390], - [0.7560, -0.2130, -0.3280, 0.1750, -0.3040, -0.0270], - [1.0200, -0.8570, -0.3850, 0.2800, -0.6380, -0.0190], - [1.0500, -1.3440, -0.3480, 0.2800, -0.8930, 0.0370], - [0.9740, -1.5070, -0.3700, 0.1540, -0.5680, 0.1090], - [0.7440, -1.8170, -0.2560, 0.2460, -2.6180, 0.2300]], + [-0.0340, 0.6710, -0.0590, -0.0590, 0.0860, -0.0280], + [0.2550, 0.4740, -0.1910, 0.0180, -0.0140, -0.0330], + [0.4270, 0.3490, -0.2450, 0.0930, -0.1210, -0.0390], + [0.7560, -0.2130, -0.3280, 0.1750, -0.3040, -0.0270], + [1.0200, -0.8570, -0.3850, 0.2800, -0.6380, -0.0190], + [1.0500, -1.3440, -0.3480, 0.2800, -0.8930, 0.0370], + [0.9740, -1.5070, -0.3700, 0.1540, -0.5680, 0.1090], + [0.7440, -1.8170, -0.2560, 0.2460, -2.6180, 0.2300]], 'france1988': [ - [0.0130, 0.7640, -0.1000, -0.0580, 0.1270, -0.0230], - [0.0950, 0.9200, -0.1520, 0, 0.0510, -0.0200], - [0.4640, 0.4210, -0.2800, 0.0640, -0.0510, -0.0020], - [0.7590, -0.0090, -0.3730, 0.2010, -0.3820, 0.0100], - [0.9760, -0.4000, -0.4360, 0.2710, -0.6380, 0.0510], - [1.1760, -1.2540, -0.4620, 0.2950, -0.9750, 0.1290], - [1.1060, -1.5630, -0.3980, 0.3010, -1.4420, 0.2120], - [0.9340, -1.5010, -0.2710, 0.4200, -2.9170, 0.2490]], + [0.0130, 0.7640, -0.1000, -0.0580, 0.1270, -0.0230], + [0.0950, 0.9200, -0.1520, 0, 0.0510, -0.0200], + [0.4640, 0.4210, -0.2800, 0.0640, -0.0510, -0.0020], + [0.7590, -0.0090, -0.3730, 0.2010, -0.3820, 0.0100], + [0.9760, -0.4000, -0.4360, 0.2710, -0.6380, 0.0510], + [1.1760, -1.2540, -0.4620, 0.2950, -0.9750, 0.1290], + [1.1060, -1.5630, -0.3980, 0.3010, -1.4420, 0.2120], + [0.9340, -1.5010, -0.2710, 0.4200, -2.9170, 0.2490]], 'phoenix1988': [ - [-0.0030, 0.7280, -0.0970, -0.0750, 0.1420, -0.0430], - [0.2790, 0.3540, -0.1760, 0.0300, -0.0550, -0.0540], - [0.4690, 0.1680, -0.2460, 0.0480, -0.0420, -0.0570], - [0.8560, -0.5190, -0.3400, 0.1760, -0.3800, -0.0310], - [0.9410, -0.6250, -0.3910, 0.1880, -0.3600, -0.0490], - [1.0560, -1.1340, -0.4100, 0.2810, -0.7940, -0.0650], - [0.9010, -2.1390, -0.2690, 0.1180, -0.6650, 0.0460], - [0.1070, 0.4810, 0.1430, -0.1110, -0.1370, 0.2340]], + [-0.0030, 0.7280, -0.0970, -0.0750, 0.1420, -0.0430], + [0.2790, 0.3540, -0.1760, 0.0300, -0.0550, -0.0540], + [0.4690, 0.1680, -0.2460, 0.0480, -0.0420, -0.0570], + [0.8560, -0.5190, -0.3400, 0.1760, -0.3800, -0.0310], + [0.9410, -0.6250, -0.3910, 0.1880, -0.3600, -0.0490], + [1.0560, -1.1340, -0.4100, 0.2810, -0.7940, -0.0650], + [0.9010, -2.1390, -0.2690, 0.1180, -0.6650, 0.0460], + [0.1070, 0.4810, 0.1430, -0.1110, -0.1370, 0.2340]], 'elmonte1988': [ - [0.0270, 0.7010, -0.1190, -0.0580, 0.1070, -0.0600], - [0.1810, 0.6710, -0.1780, -0.0790, 0.1940, -0.0350], - [0.4760, 0.4070, -0.2880, 0.0540, -0.0320, -0.0550], - [0.8750, -0.2180, -0.4030, 0.1870, -0.3090, -0.0610], - [1.1660, -1.0140, -0.4540, 0.2110, -0.4100, -0.0440], - [1.1430, -2.0640, -0.2910, 0.0970, -0.3190, 0.0530], - [1.0940, -2.6320, -0.2590, 0.0290, -0.4220, 0.1470], - [0.1550, 1.7230, 0.1630, -0.1310, -0.0190, 0.2770]], + [0.0270, 0.7010, -0.1190, -0.0580, 0.1070, -0.0600], + [0.1810, 0.6710, -0.1780, -0.0790, 0.1940, -0.0350], + [0.4760, 0.4070, -0.2880, 0.0540, -0.0320, -0.0550], + [0.8750, -0.2180, -0.4030, 0.1870, -0.3090, -0.0610], + [1.1660, -1.0140, -0.4540, 0.2110, -0.4100, -0.0440], + [1.1430, -2.0640, -0.2910, 0.0970, -0.3190, 0.0530], + [1.0940, -2.6320, -0.2590, 0.0290, -0.4220, 0.1470], + [0.1550, 1.7230, 0.1630, -0.1310, -0.0190, 0.2770]], 'osage1988': [ - [-0.3530, 1.4740, 0.0570, -0.1750, 0.3120, 0.0090], - [0.3630, 0.2180, -0.2120, 0.0190, -0.0340, -0.0590], - [-0.0310, 1.2620, -0.0840, -0.0820, 0.2310, -0.0170], - [0.6910, 0.0390, -0.2950, 0.0910, -0.1310, -0.0350], - [1.1820, -1.3500, -0.3210, 0.4080, -0.9850, -0.0880], - [0.7640, 0.0190, -0.2030, 0.2170, -0.2940, -0.1030], - [0.2190, 1.4120, 0.2440, 0.4710, -2.9880, 0.0340], - [3.5780, 22.2310, -10.7450, 2.4260, 4.8920, -5.6870]], + [-0.3530, 1.4740, 0.0570, -0.1750, 0.3120, 0.0090], + [0.3630, 0.2180, -0.2120, 0.0190, -0.0340, -0.0590], + [-0.0310, 1.2620, -0.0840, -0.0820, 0.2310, -0.0170], + [0.6910, 0.0390, -0.2950, 0.0910, -0.1310, -0.0350], + [1.1820, -1.3500, -0.3210, 0.4080, -0.9850, -0.0880], + [0.7640, 0.0190, -0.2030, 0.2170, -0.2940, -0.1030], + [0.2190, 1.4120, 0.2440, 0.4710, -2.9880, 0.0340], + [3.5780, 22.2310, -10.7450, 2.4260, 4.8920, -5.6870]], 'albuquerque1988': [ - [0.0340, 0.5010, -0.0940, -0.0630, 0.1060, -0.0440], - [0.2290, 0.4670, -0.1560, -0.0050, -0.0190, -0.0230], - [0.4860, 0.2410, -0.2530, 0.0530, -0.0640, -0.0220], - [0.8740, -0.3930, -0.3970, 0.1810, -0.3270, -0.0370], - [1.1930, -1.2960, -0.5010, 0.2810, -0.6560, -0.0450], - [1.0560, -1.7580, -0.3740, 0.2260, -0.7590, 0.0340], - [0.9010, -4.7830, -0.1090, 0.0630, -0.9700, 0.1960], - [0.8510, -7.0550, -0.0530, 0.0600, -2.8330, 0.3300]], + [0.0340, 0.5010, -0.0940, -0.0630, 0.1060, -0.0440], + [0.2290, 0.4670, -0.1560, -0.0050, -0.0190, -0.0230], + [0.4860, 0.2410, -0.2530, 0.0530, -0.0640, -0.0220], + [0.8740, -0.3930, -0.3970, 0.1810, -0.3270, -0.0370], + [1.1930, -1.2960, -0.5010, 0.2810, -0.6560, -0.0450], + [1.0560, -1.7580, -0.3740, 0.2260, -0.7590, 0.0340], + [0.9010, -4.7830, -0.1090, 0.0630, -0.9700, 0.1960], + [0.8510, -7.0550, -0.0530, 0.0600, -2.8330, 0.3300]], 'capecanaveral1988': [ - [0.0750, 0.5330, -0.1240, -0.0670, 0.0420, -0.0200], - [0.2950, 0.4970, -0.2180, -0.0080, 0.0030, -0.0290], - [0.5140, 0.0810, -0.2610, 0.0750, -0.1600, -0.0290], - [0.7470, -0.3290, -0.3250, 0.1810, -0.4160, -0.0300], - [0.9010, -0.8830, -0.2970, 0.1780, -0.4890, 0.0080], - [0.5910, -0.0440, -0.1160, 0.2350, -0.9990, 0.0980], - [0.5370, -2.4020, 0.3200, 0.1690, -1.9710, 0.3100], - [-0.8050, 4.5460, 1.0720, -0.2580, -0.9500, 0.7530]], + [0.0750, 0.5330, -0.1240, -0.0670, 0.0420, -0.0200], + [0.2950, 0.4970, -0.2180, -0.0080, 0.0030, -0.0290], + [0.5140, 0.0810, -0.2610, 0.0750, -0.1600, -0.0290], + [0.7470, -0.3290, -0.3250, 0.1810, -0.4160, -0.0300], + [0.9010, -0.8830, -0.2970, 0.1780, -0.4890, 0.0080], + [0.5910, -0.0440, -0.1160, 0.2350, -0.9990, 0.0980], + [0.5370, -2.4020, 0.3200, 0.1690, -1.9710, 0.3100], + [-0.8050, 4.5460, 1.0720, -0.2580, -0.9500, 0.7530]], 'albany1988': [ - [0.0120, 0.5540, -0.0760, -0.0520, 0.0840, -0.0290], - [0.2670, 0.4370, -0.1940, 0.0160, 0.0220, -0.0360], - [0.4200, 0.3360, -0.2370, 0.0740, -0.0520, -0.0320], - [0.6380, -0.0010, -0.2810, 0.1380, -0.1890, -0.0120], - [1.0190, -1.0270, -0.3420, 0.2710, -0.6280, 0.0140], - [1.1490, -1.9400, -0.3310, 0.3220, -1.0970, 0.0800], - [1.4340, -3.9940, -0.4920, 0.4530, -2.3760, 0.1170], - [1.0070, -2.2920, -0.4820, 0.3900, -3.3680, 0.2290]], } + [0.0120, 0.5540, -0.0760, -0.0520, 0.0840, -0.0290], + [0.2670, 0.4370, -0.1940, 0.0160, 0.0220, -0.0360], + [0.4200, 0.3360, -0.2370, 0.0740, -0.0520, -0.0320], + [0.6380, -0.0010, -0.2810, 0.1380, -0.1890, -0.0120], + [1.0190, -1.0270, -0.3420, 0.2710, -0.6280, 0.0140], + [1.1490, -1.9400, -0.3310, 0.3220, -1.0970, 0.0800], + [1.4340, -3.9940, -0.4920, 0.4530, -2.3760, 0.1170], + [1.0070, -2.2920, -0.4820, 0.3900, -3.3680, 0.2290]], } array = np.array(coeffdict[perezmodel]) @@ -2819,3 +2820,35 @@ def dni(ghi, dhi, zenith, clearsky_dni=None, clearsky_tolerance=1.1, (zenith < zenith_threshold_for_zero_dni) & (dni > max_dni)] = max_dni return dni + + +def pvfactors_bifacial_irradiance( + solar_azimuth, solar_zenith, surface_azimuth, surface_tilt, + times, dni, dhi, gcr, pvrow_height, pvrow_width, albedo, + n_pvrows=3, index_observed_pvrow=1, + rho_front_pvrow=0.03, rho_back_pvrow=0.05, + horizon_band_angle=15., + run_parallel_calculations=True, n_workers_for_parallel_calcs=None): + """ + Calculate front and back surface plane-of-array irradiance on + a fixed tilt or single-axis tracker PV array configuration, and using + the open-source "pvfactors" package. + + Parameters + ---------- + surface_azimuth: numpy array of numeric + Azimuth angle of the front surface of the PV modules (in degrees) + surface_tilt: numpy array of numeric + Tilt angle of the PV modules (in degrees) + + Returns + ------- + front_poa_irradiance: numpy array of numeric + Calculated incident irradiance on the front surface of the PV modules. + back_poa_irradiance: numpy array of numeric + Calculated incident irradiance on the back surface of the PV modules. + """ + + from pvfactors.timeseries import (calculate_radiosities_parallel_perez, + calculate_radiosities_serially_perez, + get_average_pvrow_outputs) diff --git a/pvlib/test/conftest.py b/pvlib/test/conftest.py index 914eadd007..d6fb9d3db9 100644 --- a/pvlib/test/conftest.py +++ b/pvlib/test/conftest.py @@ -69,6 +69,7 @@ def inner(): def pandas_0_17(): return parse_version(pd.__version__) >= parse_version('0.17.0') + needs_pandas_0_17 = pytest.mark.skipif( not pandas_0_17(), reason='requires pandas 0.17 or greater') @@ -76,6 +77,7 @@ def pandas_0_17(): def numpy_1_10(): return parse_version(np.__version__) >= parse_version('1.10.0') + needs_numpy_1_10 = pytest.mark.skipif( not numpy_1_10(), reason='requires numpy 1.10 or greater') @@ -92,8 +94,10 @@ def has_spa_c(): else: return True + requires_spa_c = pytest.mark.skipif(not has_spa_c(), reason="requires spa_c") + def has_numba(): try: import numba @@ -106,6 +110,7 @@ def has_numba(): else: return True + requires_numba = pytest.mark.skipif(not has_numba(), reason="requires numba") try: @@ -116,3 +121,30 @@ def has_numba(): requires_siphon = pytest.mark.skipif(not has_siphon, reason='requires siphon') + +try: + import pvfactors + has_pvfactors = True +except ImportError: + has_pvfactors = False + +requires_pvfactors = pytest.mark.skipif(not has_pvfactors, + reason='requires pvfactors') + +try: + import future + has_future = True +except ImportError: + has_future = False + +requires_future = pytest.mark.skipif(not has_future, + reason='requires future') + +try: + import shapely + has_shapely = True +except ImportError: + has_shapely = False + +requires_shapely = pytest.mark.skipif(not has_shapely, + reason='requires shapely') diff --git a/pvlib/test/test_irradiance.py b/pvlib/test/test_irradiance.py index cd1c5b168d..3009cae659 100644 --- a/pvlib/test/test_irradiance.py +++ b/pvlib/test/test_irradiance.py @@ -14,7 +14,8 @@ from pvlib._deprecation import pvlibDeprecationWarning from conftest import (fail_on_pvlib_version, needs_numpy_1_10, pandas_0_22, - requires_ephem, requires_numba) + requires_ephem, requires_numba, requires_pvfactors, + requires_future, requires_shapely, requires_scipy) # fixtures create realistic test input data @@ -32,24 +33,24 @@ def times(): @pytest.fixture def irrad_data(times): return pd.DataFrame(np.array( - [[ 0. , 0. , 0. ], - [ 79.73860422, 316.1949056 , 40.46149818], - [1042.48031487, 939.95469881, 118.45831879], - [ 257.20751138, 646.22886049, 62.03376265]]), + [[0., 0., 0.], + [79.73860422, 316.1949056, 40.46149818], + [1042.48031487, 939.95469881, 118.45831879], + [257.20751138, 646.22886049, 62.03376265]]), columns=['ghi', 'dni', 'dhi'], index=times) @pytest.fixture def ephem_data(times): return pd.DataFrame(np.array( - [[124.0390863 , 124.0390863 , -34.0390863 , -34.0390863 , - 352.69550699, -2.36677158], - [ 82.85457044, 82.97705621, 7.14542956, 7.02294379, - 66.71410338, -2.42072165], - [ 10.56413562, 10.56725766, 79.43586438, 79.43274234, - 144.76567754, -2.47457321], - [ 72.41687122, 72.46903556, 17.58312878, 17.53096444, - 287.04104128, -2.52831909]]), + [[124.0390863, 124.0390863, -34.0390863, -34.0390863, + 352.69550699, -2.36677158], + [82.85457044, 82.97705621, 7.14542956, 7.02294379, + 66.71410338, -2.42072165], + [10.56413562, 10.56725766, 79.43586438, 79.43274234, + 144.76567754, -2.47457321], + [72.41687122, 72.46903556, 17.58312878, 17.53096444, + 287.04104128, -2.52831909]]), columns=['apparent_zenith', 'zenith', 'apparent_elevation', 'elevation', 'azimuth', 'equation_of_time'], index=times) @@ -194,25 +195,25 @@ def test_klucher_series(irrad_data, ephem_data): def test_haydavies(irrad_data, ephem_data, dni_et): result = irradiance.haydavies(40, 180, irrad_data['dhi'], irrad_data['dni'], - dni_et, - ephem_data['apparent_zenith'], - ephem_data['azimuth']) + dni_et, + ephem_data['apparent_zenith'], + ephem_data['azimuth']) # values from matlab 1.4 code assert_allclose(result, [0, 27.1775, 102.9949, 33.1909], atol=1e-4) def test_reindl(irrad_data, ephem_data, dni_et): result = irradiance.reindl(40, 180, irrad_data['dhi'], irrad_data['dni'], - irrad_data['ghi'], dni_et, - ephem_data['apparent_zenith'], - ephem_data['azimuth']) + irrad_data['ghi'], dni_et, + ephem_data['apparent_zenith'], + ephem_data['azimuth']) # values from matlab 1.4 code assert_allclose(result, [np.nan, 27.9412, 104.1317, 34.1663], atol=1e-4) def test_king(irrad_data, ephem_data): result = irradiance.king(40, irrad_data['dhi'], irrad_data['ghi'], - ephem_data['apparent_zenith']) + ephem_data['apparent_zenith']) assert_allclose(result, [0, 44.629352, 115.182626, 79.719855], atol=1e-4) @@ -220,10 +221,10 @@ def test_perez(irrad_data, ephem_data, dni_et, relative_airmass): dni = irrad_data['dni'].copy() dni.iloc[2] = np.nan out = irradiance.perez(40, 180, irrad_data['dhi'], dni, - dni_et, ephem_data['apparent_zenith'], - ephem_data['azimuth'], relative_airmass) + dni_et, ephem_data['apparent_zenith'], + ephem_data['azimuth'], relative_airmass) expected = pd.Series(np.array( - [ 0. , 31.46046871, np.nan, 45.45539877]), + [0., 31.46046871, np.nan, 45.45539877]), index=irrad_data.index) assert_series_equal(out, expected, check_less_precise=2) @@ -236,10 +237,10 @@ def test_perez_components(irrad_data, ephem_data, dni_et, relative_airmass): ephem_data['azimuth'], relative_airmass, return_components=True) expected = pd.DataFrame(np.array( - [[ 0. , 31.46046871, np.nan, 45.45539877], - [ 0. , 26.84138589, np.nan, 31.72696071], - [ 0. , 0. , np.nan, 4.47966439], - [ 0. , 4.62212181, np.nan, 9.25316454]]).T, + [[0., 31.46046871, np.nan, 45.45539877], + [0., 26.84138589, np.nan, 31.72696071], + [0., 0., np.nan, 4.47966439], + [0., 4.62212181, np.nan, 9.25316454]]).T, columns=['sky_diffuse', 'isotropic', 'circumsolar', 'horizon'], index=irrad_data.index ) @@ -260,10 +261,10 @@ def test_perez_arrays(irrad_data, ephem_data, dni_et, relative_airmass): dni = irrad_data['dni'].copy() dni.iloc[2] = np.nan out = irradiance.perez(40, 180, irrad_data['dhi'].values, dni.values, - dni_et, ephem_data['apparent_zenith'].values, - ephem_data['azimuth'].values, relative_airmass.values) + dni_et, ephem_data['apparent_zenith'].values, + ephem_data['azimuth'].values, relative_airmass.values) expected = np.array( - [ 0. , 31.46046871, np.nan, 45.45539877]) + [0., 31.46046871, np.nan, 45.45539877]) assert_allclose(out, expected, atol=1e-2) assert isinstance(out, np.ndarray) @@ -288,9 +289,9 @@ def test_sky_diffuse_zenith_close_to_90(model): def test_liujordan(): expected = pd.DataFrame(np. - array([[863.859736967, 653.123094076, 220.65905025]]), - columns=['ghi', 'dni', 'dhi'], - index=[0]) + array([[863.859736967, 653.123094076, 220.65905025]]), + columns=['ghi', 'dni', 'dhi'], + index=[0]) out = irradiance.liujordan( pd.Series([10]), pd.Series([0.5]), pd.Series([1.1]), dni_extra=1400) assert_frame_equal(out, expected) @@ -345,14 +346,14 @@ def test_poa_components(irrad_data, ephem_data, dni_et, relative_airmass): out = irradiance.poa_components( aoi, irrad_data['dni'], diff_perez, gr_sand) expected = pd.DataFrame(np.array( - [[ 0. , -0. , 0. , 0. , - 0. ], - [ 35.19456561, 0. , 35.19456561, 31.4635077 , + [[0., -0., 0., 0., + 0.], + [35.19456561, 0., 35.19456561, 31.4635077, 3.73105791], [956.18253696, 798.31939281, 157.86314414, 109.08433162, - 48.77881252], - [ 90.99624896, 33.50143401, 57.49481495, 45.45978964, - 12.03502531]]), + 48.77881252], + [90.99624896, 33.50143401, 57.49481495, 45.45978964, + 12.03502531]]), columns=['poa_global', 'poa_direct', 'poa_diffuse', 'poa_sky_diffuse', 'poa_ground_diffuse'], index=irrad_data.index) @@ -360,12 +361,12 @@ def test_poa_components(irrad_data, ephem_data, dni_et, relative_airmass): @pytest.mark.parametrize('pressure,expected', [ - (93193, [[830.46567, 0.79742, 0.93505], - [676.09497, 0.63776, 3.02102]]), - (None, [[868.72425, 0.79742, 1.01664], - [680.66679, 0.63776, 3.28463]]), - (101325, [[868.72425, 0.79742, 1.01664], - [680.66679, 0.63776, 3.28463]]) + (93193, [[830.46567, 0.79742, 0.93505], + [676.09497, 0.63776, 3.02102]]), + (None, [[868.72425, 0.79742, 1.01664], + [680.66679, 0.63776, 3.28463]]), + (101325, [[868.72425, 0.79742, 1.01664], + [680.66679, 0.63776, 3.28463]]) ]) def test_disc_value(pressure, expected): # see GH 449 for pressure=None vs. 101325. @@ -460,19 +461,19 @@ def test_disc_min_cos_zenith_max_zenith(): def test_dirint_value(): - times = pd.DatetimeIndex(['2014-06-24T12-0700','2014-06-24T18-0700']) + times = pd.DatetimeIndex(['2014-06-24T12-0700', '2014-06-24T18-0700']) ghi = pd.Series([1038.62, 254.53], index=times) zenith = pd.Series([10.567, 72.469], index=times) pressure = 93193. dirint_data = irradiance.dirint(ghi, zenith, times, pressure=pressure) assert_almost_equal(dirint_data.values, - np.array([ 888. , 683.7]), 1) + np.array([888., 683.7]), 1) def test_dirint_nans(): times = pd.DatetimeIndex(start='2014-06-24T12-0700', periods=5, freq='6H') ghi = pd.Series([np.nan, 1038.62, 1038.62, 1038.62, 1038.62], index=times) - zenith = pd.Series([10.567, np.nan, 10.567, 10.567, 10.567,], index=times) + zenith = pd.Series([10.567, np.nan, 10.567, 10.567, 10.567, ], index=times) pressure = pd.Series([93193., 93193., np.nan, 93193., 93193.], index=times) temp_dew = pd.Series([10, 10, 10, np.nan, 10], index=times) dirint_data = irradiance.dirint(ghi, zenith, times, pressure=pressure, @@ -482,39 +483,39 @@ def test_dirint_nans(): def test_dirint_tdew(): - times = pd.DatetimeIndex(['2014-06-24T12-0700','2014-06-24T18-0700']) + times = pd.DatetimeIndex(['2014-06-24T12-0700', '2014-06-24T18-0700']) ghi = pd.Series([1038.62, 254.53], index=times) zenith = pd.Series([10.567, 72.469], index=times) pressure = 93193. dirint_data = irradiance.dirint(ghi, zenith, times, pressure=pressure, temp_dew=10) assert_almost_equal(dirint_data.values, - np.array([892.9, 636.5]), 1) + np.array([892.9, 636.5]), 1) def test_dirint_no_delta_kt(): - times = pd.DatetimeIndex(['2014-06-24T12-0700','2014-06-24T18-0700']) + times = pd.DatetimeIndex(['2014-06-24T12-0700', '2014-06-24T18-0700']) ghi = pd.Series([1038.62, 254.53], index=times) zenith = pd.Series([10.567, 72.469], index=times) pressure = 93193. dirint_data = irradiance.dirint(ghi, zenith, times, pressure=pressure, use_delta_kt_prime=False) assert_almost_equal(dirint_data.values, - np.array([861.9, 670.4]), 1) + np.array([861.9, 670.4]), 1) def test_dirint_coeffs(): coeffs = irradiance._get_dirint_coeffs() - assert coeffs[0,0,0,0] == 0.385230 - assert coeffs[0,1,2,1] == 0.229970 - assert coeffs[3,2,6,3] == 1.032260 + assert coeffs[0, 0, 0, 0] == 0.385230 + assert coeffs[0, 1, 2, 1] == 0.229970 + assert coeffs[3, 2, 6, 3] == 1.032260 def test_dirint_min_cos_zenith_max_zenith(): # map out behavior under difficult conditions with various # limiting kwargs settings # times don't have any physical relevance - times = pd.DatetimeIndex(['2014-06-24T12-0700','2014-06-24T18-0700']) + times = pd.DatetimeIndex(['2014-06-24T12-0700', '2014-06-24T18-0700']) ghi = pd.Series([0, 1], index=times) solar_zenith = pd.Series([90, 89.99], index=times) @@ -557,9 +558,9 @@ def test_gti_dirint(): expected_col_order = ['ghi', 'dni', 'dhi'] expected = pd.DataFrame(array( - [[ 21.05796198, 0. , 21.05796198], - [ 288.22574368, 60.59964218, 245.37532576], - [ 930.85454521, 695.8504884 , 276.96897609]]), + [[21.05796198, 0., 21.05796198], + [288.22574368, 60.59964218, 245.37532576], + [930.85454521, 695.8504884, 276.96897609]]), columns=expected_col_order, index=times) assert_frame_equal(output, expected) @@ -581,9 +582,9 @@ def test_gti_dirint(): pressure=pressure) expected = pd.DataFrame(array( - [[ 21.05796198, 0. , 21.05796198], - [ 289.81109139, 60.52460392, 247.01373353], - [ 932.22047435, 647.68716072, 323.59362885]]), + [[21.05796198, 0., 21.05796198], + [289.81109139, 60.52460392, 247.01373353], + [932.22047435, 647.68716072, 323.59362885]]), columns=expected_col_order, index=times) assert_frame_equal(output, expected) @@ -595,9 +596,9 @@ def test_gti_dirint(): albedo=albedo) expected = pd.DataFrame(array( - [[ 21.3592591 , 0. , 21.3592591 ], - [ 292.5162373 , 64.42628826, 246.95997198], - [ 941.47847463, 727.07261187, 258.25370648]]), + [[21.3592591, 0., 21.3592591], + [292.5162373, 64.42628826, 246.95997198], + [941.47847463, 727.07261187, 258.25370648]]), columns=expected_col_order, index=times) assert_frame_equal(output, expected) @@ -609,9 +610,9 @@ def test_gti_dirint(): temp_dew=temp_dew) expected = pd.DataFrame(array( - [[ 21.05796198, 0. , 21.05796198], - [ 292.40468994, 36.79559287, 266.3862767 ], - [ 930.72198876, 712.36063132, 261.32196017]]), + [[21.05796198, 0., 21.05796198], + [292.40468994, 36.79559287, 266.3862767], + [930.72198876, 712.36063132, 261.32196017]]), columns=expected_col_order, index=times) assert_frame_equal(output, expected) @@ -622,11 +623,11 @@ def test_erbs(): zenith = pd.Series([120, 85, 10, 10]) doy = pd.Series([1, 1, 1, 180]) expected = pd.DataFrame(np. - array([[ -0.00000000e+00, 0.00000000e+00, -0.00000000e+00], - [ 9.67127061e+01, 4.15709323e+01, 4.05715990e-01], - [ 7.94187742e+02, 2.17877755e+02, 7.18119416e-01], - [ 8.42358014e+02, 1.70439297e+02, 7.68919470e-01]]), - columns=['dni', 'dhi', 'kt']) + array([[-0.00000000e+00, 0.00000000e+00, -0.00000000e+00], + [9.67127061e+01, 4.15709323e+01, 4.05715990e-01], + [7.94187742e+02, 2.17877755e+02, 7.18119416e-01], + [8.42358014e+02, 1.70439297e+02, 7.68919470e-01]]), + columns=['dni', 'dhi', 'kt']) out = irradiance.erbs(ghi, zenith, doy) @@ -687,7 +688,7 @@ def test_dirindex_min_cos_zenith_max_zenith(): # map out behavior under difficult conditions with various # limiting kwargs settings # times don't have any physical relevance - times = pd.DatetimeIndex(['2014-06-24T12-0700','2014-06-24T18-0700']) + times = pd.DatetimeIndex(['2014-06-24T12-0700', '2014-06-24T18-0700']) ghi = pd.Series([0, 1], index=times) ghi_clearsky = pd.Series([0, 1], index=times) dni_clearsky = pd.Series([0, 5], index=times) @@ -733,8 +734,8 @@ def test_dni(): @pytest.mark.parametrize( - 'surface_tilt,surface_azimuth,solar_zenith,' + - 'solar_azimuth,aoi_expected,aoi_proj_expected', + 'surface_tilt,surface_azimuth,solar_zenith,' + + 'solar_azimuth,aoi_expected,aoi_proj_expected', [(0, 0, 0, 0, 0, 1), (30, 180, 30, 180, 0, 1), (30, 180, 150, 0, 180, -1), @@ -760,7 +761,7 @@ def airmass_kt(): def test_kt_kt_prime_factor(airmass_kt): out = irradiance._kt_kt_prime_factor(airmass_kt) - expected = np.array([ 0.999971, 0.723088, 0.548811, 0.471068]) + expected = np.array([0.999971, 0.723088, 0.548811, 0.471068]) assert_allclose(out, expected, atol=1e-5) @@ -772,29 +773,29 @@ def test_clearness_index(): out = irradiance.clearness_index(ghi, solar_zenith, 1370) # np.set_printoptions(precision=3, floatmode='maxprec', suppress=True) expected = np.array( - [[0. , 0. , 0.011, 2. ], - [0. , 0. , 0.011, 2. ], - [0. , 0. , 0.011, 2. ], - [0. , 0. , 0.001, 0.73 ]]) + [[0., 0., 0.011, 2.], + [0., 0., 0.011, 2.], + [0., 0., 0.011, 2.], + [0., 0., 0.001, 0.73]]) assert_allclose(out, expected, atol=0.001) # specify min_cos_zenith with np.errstate(invalid='ignore', divide='ignore'): out = irradiance.clearness_index(ghi, solar_zenith, 1400, min_cos_zenith=0) expected = np.array( - [[0. , nan, 2. , 2. ], - [0. , 0. , 2. , 2. ], - [0. , 0. , 2. , 2. ], - [0. , 0. , 0.001, 0.714]]) + [[0., nan, 2., 2.], + [0., 0., 2., 2.], + [0., 0., 2., 2.], + [0., 0., 0.001, 0.714]]) assert_allclose(out, expected, atol=0.001) # specify max_clearness_index out = irradiance.clearness_index(ghi, solar_zenith, 1370, max_clearness_index=0.82) expected = np.array( - [[ 0. , 0. , 0.011, 0.82 ], - [ 0. , 0. , 0.011, 0.82 ], - [ 0. , 0. , 0.011, 0.82 ], - [ 0. , 0. , 0.001, 0.73 ]]) + [[0., 0., 0.011, 0.82], + [0., 0., 0.011, 0.82], + [0., 0., 0.011, 0.82], + [0., 0., 0.001, 0.73]]) assert_allclose(out, expected, atol=0.001) # specify min_cos_zenith and max_clearness_index with np.errstate(invalid='ignore', divide='ignore'): @@ -802,10 +803,10 @@ def test_clearness_index(): min_cos_zenith=0, max_clearness_index=0.82) expected = np.array( - [[ 0. , nan, 0.82 , 0.82 ], - [ 0. , 0. , 0.82 , 0.82 ], - [ 0. , 0. , 0.82 , 0.82 ], - [ 0. , 0. , 0.001, 0.714]]) + [[0., nan, 0.82, 0.82], + [0., 0., 0.82, 0.82], + [0., 0., 0.82, 0.82], + [0., 0., 0.001, 0.714]]) assert_allclose(out, expected, atol=0.001) # scalars out = irradiance.clearness_index(1000, 10, 1400) @@ -827,19 +828,19 @@ def test_clearness_index_zenith_independent(airmass_kt): out = irradiance.clearness_index_zenith_independent(clearness_index, airmass_kt) expected = np.array( - [[0. , 0. , 0.1 , 1. ], - [0. , 0. , 0.138, 1.383], - [0. , 0. , 0.182, 1.822], - [0. , 0. , 0.212, 2. ]]) + [[0., 0., 0.1, 1.], + [0., 0., 0.138, 1.383], + [0., 0., 0.182, 1.822], + [0., 0., 0.212, 2.]]) assert_allclose(out, expected, atol=0.001) # test max_clearness_index out = irradiance.clearness_index_zenith_independent( clearness_index, airmass_kt, max_clearness_index=0.82) expected = np.array( - [[ 0. , 0. , 0.1 , 0.82 ], - [ 0. , 0. , 0.138, 0.82 ], - [ 0. , 0. , 0.182, 0.82 ], - [ 0. , 0. , 0.212, 0.82 ]]) + [[0., 0., 0.1, 0.82], + [0., 0., 0.138, 0.82], + [0., 0., 0.182, 0.82], + [0., 0., 0.212, 0.82]]) assert_allclose(out, expected, atol=0.001) # scalars out = irradiance.clearness_index_zenith_independent(.4, 2) @@ -853,3 +854,30 @@ def test_clearness_index_zenith_independent(airmass_kt): airmass) expected = pd.Series([np.nan, 0.553744437562], index=times) assert_series_equal(out, expected) + + +@requires_scipy +@requires_shapely +@requires_future +@requires_pvfactors +def test_pvfactors_bifacial_irradiance(): + + solar_azimuth = None + solar_zenith = None + surface_azimuth = None + surface_tilt = None + times = None + dni = None + dhi = None + gcr = None + pvrow_height = None + pvrow_width = None + albedo = None + + irradiance.pvfactors_bifacial_irradiance( + solar_azimuth, solar_zenith, surface_azimuth, surface_tilt, + times, dni, dhi, gcr, pvrow_height, pvrow_width, albedo, + n_pvrows=3, index_observed_pvrow=1, + rho_front_pvrow=0.03, rho_back_pvrow=0.05, + horizon_band_angle=15., + run_parallel_calculations=True, n_workers_for_parallel_calcs=None) diff --git a/setup.py b/setup.py index 08708f26b9..bd61b42c8d 100755 --- a/setup.py +++ b/setup.py @@ -45,7 +45,7 @@ TESTS_REQUIRE = ['pytest', 'pytest-cov', 'pytest-mock', 'nose'] EXTRAS_REQUIRE = { 'optional': ['scipy', 'tables', 'numba', 'siphon', 'netcdf4', - 'ephem', 'cython'], + 'ephem', 'cython', 'pvfactors'], 'doc': ['sphinx', 'ipython', 'sphinx_rtd_theme', 'numpydoc', 'matplotlib'], 'test': TESTS_REQUIRE From 8acfd58bcc7750005fee02091f502ec6e643cb4b Mon Sep 17 00:00:00 2001 From: anomam Date: Thu, 13 Dec 2018 18:17:34 +0900 Subject: [PATCH 02/27] Add test inputs from github repo README.md TLDR section --- pvlib/test/test_irradiance.py | 49 ++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/pvlib/test/test_irradiance.py b/pvlib/test/test_irradiance.py index 3009cae659..f55b612283 100644 --- a/pvlib/test/test_irradiance.py +++ b/pvlib/test/test_irradiance.py @@ -861,23 +861,42 @@ def test_clearness_index_zenith_independent(airmass_kt): @requires_future @requires_pvfactors def test_pvfactors_bifacial_irradiance(): + """ Test that pvfactors is functional, using the TLDR inputs of the + package github repo README.md file""" + + # Create some inputs + timestamps = np.array([datetime.datetime(2017, 8, 31, 11), + datetime.datetime(2017, 8, 31, 12)]) + solar_zenith = np.array([20., 10.]) + solar_azimuth = np.array([110., 140.]) + surface_tilt = np.array([10., 0.]) + surface_azimuth = np.array([90., 90.]) + dni = np.array([1000., 300.]) + dhi = np.array([50., 500.]) + gcr = 0.4 + pvrow_height = 1.75 + pvrow_width = 2.44 + albedo = 0.2 + n_pvrows = 3 + index_observed_pvrow = 1 + rho_front_pvrow = 0.03 + rho_back_pvrow = 0.05 + horizon_band_angle = 15. + + # Run calculations serially + irradiance.pvfactors_bifacial_irradiance( + solar_azimuth, solar_zenith, surface_azimuth, surface_tilt, + times, dni, dhi, gcr, pvrow_height, pvrow_width, albedo, + n_pvrows=n_pvrows, index_observed_pvrow=index_observed_pvrow, + rho_front_pvrow=rho_front_pvrow, rho_back_pvrow=rho_back_pvrow, + horizon_band_angle=horizon_band_angle, + run_parallel_calculations=False, n_workers_for_parallel_calcs=None) - solar_azimuth = None - solar_zenith = None - surface_azimuth = None - surface_tilt = None - times = None - dni = None - dhi = None - gcr = None - pvrow_height = None - pvrow_width = None - albedo = None - + # Run calculations in parallel irradiance.pvfactors_bifacial_irradiance( solar_azimuth, solar_zenith, surface_azimuth, surface_tilt, times, dni, dhi, gcr, pvrow_height, pvrow_width, albedo, - n_pvrows=3, index_observed_pvrow=1, - rho_front_pvrow=0.03, rho_back_pvrow=0.05, - horizon_band_angle=15., + n_pvrows=n_pvrows, index_observed_pvrow=index_observed_pvrow, + rho_front_pvrow=rho_front_pvrow, rho_back_pvrow=rho_back_pvrow, + horizon_band_angle=horizon_band_angle, run_parallel_calculations=True, n_workers_for_parallel_calcs=None) From 2e982d01a1429c0677e74a08bd1b7a50a79db482 Mon Sep 17 00:00:00 2001 From: anomam Date: Thu, 13 Dec 2018 18:59:00 +0900 Subject: [PATCH 03/27] Function implementation and testing of outputs --- pvlib/irradiance.py | 46 ++++++++++++++++++++++++++++++++++- pvlib/test/test_irradiance.py | 27 +++++++++++++++----- setup.py | 2 +- 3 files changed, 67 insertions(+), 8 deletions(-) diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index 0b6f8ae5f1..d7cbb33d49 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -2824,7 +2824,7 @@ def dni(ghi, dhi, zenith, clearsky_dni=None, clearsky_tolerance=1.1, def pvfactors_bifacial_irradiance( solar_azimuth, solar_zenith, surface_azimuth, surface_tilt, - times, dni, dhi, gcr, pvrow_height, pvrow_width, albedo, + timestamps, dni, dhi, gcr, pvrow_height, pvrow_width, albedo, n_pvrows=3, index_observed_pvrow=1, rho_front_pvrow=0.03, rho_back_pvrow=0.05, horizon_band_angle=15., @@ -2849,6 +2849,50 @@ def pvfactors_bifacial_irradiance( Calculated incident irradiance on the back surface of the PV modules. """ + # Import necessary packages from pvfactors.timeseries import (calculate_radiosities_parallel_perez, calculate_radiosities_serially_perez, get_average_pvrow_outputs) + idx_slice = pd.IndexSlice + + # Build up pv array configuration parameters + pvarray_parameters = { + 'n_pvrows': n_pvrows, + 'pvrow_height': pvrow_height, + 'pvrow_width': pvrow_width, + 'surface_azimuth': surface_azimuth[0], # not necessary + 'surface_tilt': surface_tilt[0], # not necessary + 'gcr': gcr, + 'solar_zenith': solar_zenith[0], # not necessary + 'solar_azimuth': solar_azimuth[0], # not necessary + 'rho_ground': albedo, + 'rho_front_pvrow': rho_front_pvrow, + 'rho_back_pvrow': rho_back_pvrow, + 'horizon_band_angle': horizon_band_angle + } + + # Run pvfactors calculations: either in parallel or serially + if run_parallel_calculations: + df_registries, df_custom_perez = calculate_radiosities_parallel_perez( + pvarray_parameters, timestamps, solar_zenith, solar_azimuth, + surface_tilt, surface_azimuth, dni, dhi, + n_processes=n_workers_for_parallel_calcs) + else: + inputs = (pvarray_parameters, timestamps, solar_zenith, solar_azimuth, + surface_tilt, surface_azimuth, dni, dhi) + df_registries, df_custom_perez = calculate_radiosities_serially_perez( + inputs) + + # Get the average surface outputs + df_outputs = get_average_pvrow_outputs(df_registries, + values=['qinc'], + include_shading=True) + + # Select the calculated outputs from the pvrow to observe + ipoa_front = df_outputs.loc[:, idx_slice[index_observed_pvrow, + 'front', 'qinc']].values + + ipoa_back = df_outputs.loc[:, idx_slice[index_observed_pvrow, + 'back', 'qinc']].values + + return ipoa_front, ipoa_back, df_registries diff --git a/pvlib/test/test_irradiance.py b/pvlib/test/test_irradiance.py index f55b612283..f6637774c8 100644 --- a/pvlib/test/test_irradiance.py +++ b/pvlib/test/test_irradiance.py @@ -861,7 +861,7 @@ def test_clearness_index_zenith_independent(airmass_kt): @requires_future @requires_pvfactors def test_pvfactors_bifacial_irradiance(): - """ Test that pvfactors is functional, using the TLDR inputs of the + """ Test that pvfactors is functional, using the TLDR section inputs of the package github repo README.md file""" # Create some inputs @@ -883,20 +883,35 @@ def test_pvfactors_bifacial_irradiance(): rho_back_pvrow = 0.05 horizon_band_angle = 15. - # Run calculations serially - irradiance.pvfactors_bifacial_irradiance( + # Expected values + expected_ipoa_front = [1034.96216923, 795.4423259] + expected_ipoa_back = [92.11871485, 70.39404124] + tolerance = 1e-6 + + # Test serial calculations + ipoa_front, ipoa_back, _ = irradiance.pvfactors_bifacial_irradiance( solar_azimuth, solar_zenith, surface_azimuth, surface_tilt, - times, dni, dhi, gcr, pvrow_height, pvrow_width, albedo, + timestamps, dni, dhi, gcr, pvrow_height, pvrow_width, albedo, n_pvrows=n_pvrows, index_observed_pvrow=index_observed_pvrow, rho_front_pvrow=rho_front_pvrow, rho_back_pvrow=rho_back_pvrow, horizon_band_angle=horizon_band_angle, run_parallel_calculations=False, n_workers_for_parallel_calcs=None) + np.testing.assert_allclose(ipoa_front, expected_ipoa_front, + atol=0, rtol=tolerance) + np.testing.assert_allclose(ipoa_back, expected_ipoa_back, + atol=0, rtol=tolerance) + # Run calculations in parallel - irradiance.pvfactors_bifacial_irradiance( + ipoa_front, ipoa_back, _ = irradiance.pvfactors_bifacial_irradiance( solar_azimuth, solar_zenith, surface_azimuth, surface_tilt, - times, dni, dhi, gcr, pvrow_height, pvrow_width, albedo, + timestamps, dni, dhi, gcr, pvrow_height, pvrow_width, albedo, n_pvrows=n_pvrows, index_observed_pvrow=index_observed_pvrow, rho_front_pvrow=rho_front_pvrow, rho_back_pvrow=rho_back_pvrow, horizon_band_angle=horizon_band_angle, run_parallel_calculations=True, n_workers_for_parallel_calcs=None) + + np.testing.assert_allclose(ipoa_front, expected_ipoa_front, + atol=0, rtol=tolerance) + np.testing.assert_allclose(ipoa_back, expected_ipoa_back, + atol=0, rtol=tolerance) diff --git a/setup.py b/setup.py index bd61b42c8d..c3a6902886 100755 --- a/setup.py +++ b/setup.py @@ -45,7 +45,7 @@ TESTS_REQUIRE = ['pytest', 'pytest-cov', 'pytest-mock', 'nose'] EXTRAS_REQUIRE = { 'optional': ['scipy', 'tables', 'numba', 'siphon', 'netcdf4', - 'ephem', 'cython', 'pvfactors'], + 'ephem', 'cython', 'pvfactors==0.1.4'], 'doc': ['sphinx', 'ipython', 'sphinx_rtd_theme', 'numpydoc', 'matplotlib'], 'test': TESTS_REQUIRE From 199ad0258551b88ef4c63f997d03ebdfc2c031cc Mon Sep 17 00:00:00 2001 From: anomam Date: Fri, 14 Dec 2018 17:47:21 +0900 Subject: [PATCH 04/27] Update docstrings --- pvlib/irradiance.py | 61 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 5 deletions(-) diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index d7cbb33d49..833485377a 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -2833,23 +2833,74 @@ def pvfactors_bifacial_irradiance( Calculate front and back surface plane-of-array irradiance on a fixed tilt or single-axis tracker PV array configuration, and using the open-source "pvfactors" package. + Please refer to pvfactors' online documentation for more details: + https://sunpower.github.io/pvfactors/ Parameters ---------- + solar_azimuth: numpy array of numeric + Sun's azimuth angles using pvlib's azimuth convention (deg) + solar_zenith: numpy array of numeric + Sun's zenith angles (deg) surface_azimuth: numpy array of numeric - Azimuth angle of the front surface of the PV modules (in degrees) + Azimuth angle of the front surface of the PV modules, using pvlib's + convention (deg) surface_tilt: numpy array of numeric - Tilt angle of the PV modules (in degrees) + Tilt angle of the PV modules, going from 0 to 180 (deg) + timestamps: array of :class:datetime.datetime objects + List of simulation timestamps + dni: numpy array of numeric values + Direct normal irradiance (W/m2) + dhi: numpy array of numeric values + Diffuse horizontal irradiance (W/m2) + gcr: float + Ground coverage ratio of the pv array + pvrow_height: float + Height of the pv rows, measured at their center (m) + pvrow_width: float + Width of the pv rows in the considered 2D plane (m) + albedo: float + Ground albedo + n_pvrows: int, default 3 + Number of PV rows to consider in the PV array + index_observed_pvrow: int, default 1 + Index of the PV row whose incident irradiance will be returned. Indices + of PV rows go from 0 to n_pvrows-1. + rho_front_pvrow: float, default 0.03 + Front surface reflectivity of PV rows + rho_back_pvrow: float, default 0.05 + Back surface reflectivity of PV rows + horizon_band_angle: float, default 15 + Elevation angle of the sky dome's diffuse horizon band (deg) + run_parallel_calculations: bool, default True + pvfactors is capable of using multiprocessing. Use this flag to decide + to run calculations in parallel (recommended) or not. + n_workers_for_parallel_calcs: int, default None + Number of workers to use in the case of parallel calculations. The + default value of 'None' will lead to using a value equal to the number + of CPU's on the machine running the model. Returns ------- front_poa_irradiance: numpy array of numeric - Calculated incident irradiance on the front surface of the PV modules. + Calculated incident irradiance on the front surface of the PV modules + (W/m2) back_poa_irradiance: numpy array of numeric - Calculated incident irradiance on the back surface of the PV modules. + Calculated incident irradiance on the back surface of the PV modules + (W/m2) + df_registries: pandas DataFrame + DataFrame containing all the detailed outputs and elements calculated + for every timestamp of the simulation. Please refer to pvfactors' + documentation for more details + + References + ---------- + .. [1] Anoma, Marc Abou, et al. "View Factor Model and Validation for + Bifacial PV and Diffuse Shade on Single-Axis Trackers." 44th IEEE + Photovoltaic Specialist Conference. 2017. """ - # Import necessary packages + # Import pvfactors functions for timeseries calculations. from pvfactors.timeseries import (calculate_radiosities_parallel_perez, calculate_radiosities_serially_perez, get_average_pvrow_outputs) From 397c850bdb8afee5e27f3795d535188e139145e2 Mon Sep 17 00:00:00 2001 From: anomam Date: Fri, 14 Dec 2018 18:14:09 +0900 Subject: [PATCH 05/27] Update pvfactors version to latest v0.1.5 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index c3a6902886..e2ab9101f8 100755 --- a/setup.py +++ b/setup.py @@ -45,7 +45,7 @@ TESTS_REQUIRE = ['pytest', 'pytest-cov', 'pytest-mock', 'nose'] EXTRAS_REQUIRE = { 'optional': ['scipy', 'tables', 'numba', 'siphon', 'netcdf4', - 'ephem', 'cython', 'pvfactors==0.1.4'], + 'ephem', 'cython', 'pvfactors==0.1.5'], 'doc': ['sphinx', 'ipython', 'sphinx_rtd_theme', 'numpydoc', 'matplotlib'], 'test': TESTS_REQUIRE From 1c976e3140c49645eccf88a9d7b1f183336f062c Mon Sep 17 00:00:00 2001 From: anomam Date: Mon, 17 Dec 2018 11:31:41 +0900 Subject: [PATCH 06/27] Move bifacial calculation and test to new specific modules --- pvlib/bifacial.py | 133 ++++++++++++++++++++++++++++++++++ pvlib/irradiance.py | 126 -------------------------------- pvlib/test/test_bifacial.py | 66 +++++++++++++++++ pvlib/test/test_irradiance.py | 62 +--------------- 4 files changed, 200 insertions(+), 187 deletions(-) create mode 100644 pvlib/bifacial.py create mode 100644 pvlib/test/test_bifacial.py diff --git a/pvlib/bifacial.py b/pvlib/bifacial.py new file mode 100644 index 0000000000..5bdadf97c7 --- /dev/null +++ b/pvlib/bifacial.py @@ -0,0 +1,133 @@ +""" +The ``bifacial`` module contains functions for modeling back surface +plane-of-array irradiance under various conditions. +""" + +import pandas as pd + + +def pvfactors_timeseries( + solar_azimuth, solar_zenith, surface_azimuth, surface_tilt, + timestamps, dni, dhi, gcr, pvrow_height, pvrow_width, albedo, + n_pvrows=3, index_observed_pvrow=1, + rho_front_pvrow=0.03, rho_back_pvrow=0.05, + horizon_band_angle=15., + run_parallel_calculations=True, n_workers_for_parallel_calcs=None): + """ + Calculate front and back surface plane-of-array irradiance on + a fixed tilt or single-axis tracker PV array configuration, and using + the open-source "pvfactors" package. + Please refer to pvfactors online documentation for more details: + https://sunpower.github.io/pvfactors/ + + Parameters + ---------- + solar_azimuth: numpy array of numeric + Sun's azimuth angles using pvlib's azimuth convention (deg) + solar_zenith: numpy array of numeric + Sun's zenith angles (deg) + surface_azimuth: numpy array of numeric + Azimuth angle of the front surface of the PV modules, using pvlib's + convention (deg) + surface_tilt: numpy array of numeric + Tilt angle of the PV modules, going from 0 to 180 (deg) + timestamps: array of :class:datetime.datetime objects + List of simulation timestamps + dni: numpy array of numeric values + Direct normal irradiance (W/m2) + dhi: numpy array of numeric values + Diffuse horizontal irradiance (W/m2) + gcr: float + Ground coverage ratio of the pv array + pvrow_height: float + Height of the pv rows, measured at their center (m) + pvrow_width: float + Width of the pv rows in the considered 2D plane (m) + albedo: float + Ground albedo + n_pvrows: int, default 3 + Number of PV rows to consider in the PV array + index_observed_pvrow: int, default 1 + Index of the PV row whose incident irradiance will be returned. Indices + of PV rows go from 0 to n_pvrows-1. + rho_front_pvrow: float, default 0.03 + Front surface reflectivity of PV rows + rho_back_pvrow: float, default 0.05 + Back surface reflectivity of PV rows + horizon_band_angle: float, default 15 + Elevation angle of the sky dome's diffuse horizon band (deg) + run_parallel_calculations: bool, default True + pvfactors is capable of using multiprocessing. Use this flag to decide + to run calculations in parallel (recommended) or not. + n_workers_for_parallel_calcs: int, default None + Number of workers to use in the case of parallel calculations. The + default value of 'None' will lead to using a value equal to the number + of CPU's on the machine running the model. + + Returns + ------- + front_poa_irradiance: numpy array of numeric + Calculated incident irradiance on the front surface of the PV modules + (W/m2) + back_poa_irradiance: numpy array of numeric + Calculated incident irradiance on the back surface of the PV modules + (W/m2) + df_registries: pandas DataFrame + DataFrame containing all the detailed outputs and elements calculated + for every timestamp of the simulation. Please refer to pvfactors' + documentation for more details + + References + ---------- + .. [1] Anoma, Marc Abou, et al. "View Factor Model and Validation for + Bifacial PV and Diffuse Shade on Single-Axis Trackers." 44th IEEE + Photovoltaic Specialist Conference. 2017. + """ + + # Import pvfactors functions for timeseries calculations. + from pvfactors.timeseries import (calculate_radiosities_parallel_perez, + calculate_radiosities_serially_perez, + get_average_pvrow_outputs) + idx_slice = pd.IndexSlice + + # Build up pv array configuration parameters + pvarray_parameters = { + 'n_pvrows': n_pvrows, + 'pvrow_height': pvrow_height, + 'pvrow_width': pvrow_width, + 'surface_azimuth': surface_azimuth[0], # not necessary + 'surface_tilt': surface_tilt[0], # not necessary + 'gcr': gcr, + 'solar_zenith': solar_zenith[0], # not necessary + 'solar_azimuth': solar_azimuth[0], # not necessary + 'rho_ground': albedo, + 'rho_front_pvrow': rho_front_pvrow, + 'rho_back_pvrow': rho_back_pvrow, + 'horizon_band_angle': horizon_band_angle + } + + # Run pvfactors calculations: either in parallel or serially + if run_parallel_calculations: + df_registries, df_custom_perez = calculate_radiosities_parallel_perez( + pvarray_parameters, timestamps, solar_zenith, solar_azimuth, + surface_tilt, surface_azimuth, dni, dhi, + n_processes=n_workers_for_parallel_calcs) + else: + inputs = (pvarray_parameters, timestamps, solar_zenith, solar_azimuth, + surface_tilt, surface_azimuth, dni, dhi) + df_registries, df_custom_perez = calculate_radiosities_serially_perez( + inputs) + + # Get the average surface outputs + df_outputs = get_average_pvrow_outputs(df_registries, + values=['qinc'], + include_shading=True) + + # Select the calculated outputs from the pvrow to observe + ipoa_front = df_outputs.loc[:, idx_slice[index_observed_pvrow, + 'front', 'qinc']].values + + ipoa_back = df_outputs.loc[:, idx_slice[index_observed_pvrow, + 'back', 'qinc']].values + + return ipoa_front, ipoa_back, df_registries diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index 833485377a..042768b416 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -2821,129 +2821,3 @@ def dni(ghi, dhi, zenith, clearsky_dni=None, clearsky_tolerance=1.1, (dni > max_dni)] = max_dni return dni - -def pvfactors_bifacial_irradiance( - solar_azimuth, solar_zenith, surface_azimuth, surface_tilt, - timestamps, dni, dhi, gcr, pvrow_height, pvrow_width, albedo, - n_pvrows=3, index_observed_pvrow=1, - rho_front_pvrow=0.03, rho_back_pvrow=0.05, - horizon_band_angle=15., - run_parallel_calculations=True, n_workers_for_parallel_calcs=None): - """ - Calculate front and back surface plane-of-array irradiance on - a fixed tilt or single-axis tracker PV array configuration, and using - the open-source "pvfactors" package. - Please refer to pvfactors' online documentation for more details: - https://sunpower.github.io/pvfactors/ - - Parameters - ---------- - solar_azimuth: numpy array of numeric - Sun's azimuth angles using pvlib's azimuth convention (deg) - solar_zenith: numpy array of numeric - Sun's zenith angles (deg) - surface_azimuth: numpy array of numeric - Azimuth angle of the front surface of the PV modules, using pvlib's - convention (deg) - surface_tilt: numpy array of numeric - Tilt angle of the PV modules, going from 0 to 180 (deg) - timestamps: array of :class:datetime.datetime objects - List of simulation timestamps - dni: numpy array of numeric values - Direct normal irradiance (W/m2) - dhi: numpy array of numeric values - Diffuse horizontal irradiance (W/m2) - gcr: float - Ground coverage ratio of the pv array - pvrow_height: float - Height of the pv rows, measured at their center (m) - pvrow_width: float - Width of the pv rows in the considered 2D plane (m) - albedo: float - Ground albedo - n_pvrows: int, default 3 - Number of PV rows to consider in the PV array - index_observed_pvrow: int, default 1 - Index of the PV row whose incident irradiance will be returned. Indices - of PV rows go from 0 to n_pvrows-1. - rho_front_pvrow: float, default 0.03 - Front surface reflectivity of PV rows - rho_back_pvrow: float, default 0.05 - Back surface reflectivity of PV rows - horizon_band_angle: float, default 15 - Elevation angle of the sky dome's diffuse horizon band (deg) - run_parallel_calculations: bool, default True - pvfactors is capable of using multiprocessing. Use this flag to decide - to run calculations in parallel (recommended) or not. - n_workers_for_parallel_calcs: int, default None - Number of workers to use in the case of parallel calculations. The - default value of 'None' will lead to using a value equal to the number - of CPU's on the machine running the model. - - Returns - ------- - front_poa_irradiance: numpy array of numeric - Calculated incident irradiance on the front surface of the PV modules - (W/m2) - back_poa_irradiance: numpy array of numeric - Calculated incident irradiance on the back surface of the PV modules - (W/m2) - df_registries: pandas DataFrame - DataFrame containing all the detailed outputs and elements calculated - for every timestamp of the simulation. Please refer to pvfactors' - documentation for more details - - References - ---------- - .. [1] Anoma, Marc Abou, et al. "View Factor Model and Validation for - Bifacial PV and Diffuse Shade on Single-Axis Trackers." 44th IEEE - Photovoltaic Specialist Conference. 2017. - """ - - # Import pvfactors functions for timeseries calculations. - from pvfactors.timeseries import (calculate_radiosities_parallel_perez, - calculate_radiosities_serially_perez, - get_average_pvrow_outputs) - idx_slice = pd.IndexSlice - - # Build up pv array configuration parameters - pvarray_parameters = { - 'n_pvrows': n_pvrows, - 'pvrow_height': pvrow_height, - 'pvrow_width': pvrow_width, - 'surface_azimuth': surface_azimuth[0], # not necessary - 'surface_tilt': surface_tilt[0], # not necessary - 'gcr': gcr, - 'solar_zenith': solar_zenith[0], # not necessary - 'solar_azimuth': solar_azimuth[0], # not necessary - 'rho_ground': albedo, - 'rho_front_pvrow': rho_front_pvrow, - 'rho_back_pvrow': rho_back_pvrow, - 'horizon_band_angle': horizon_band_angle - } - - # Run pvfactors calculations: either in parallel or serially - if run_parallel_calculations: - df_registries, df_custom_perez = calculate_radiosities_parallel_perez( - pvarray_parameters, timestamps, solar_zenith, solar_azimuth, - surface_tilt, surface_azimuth, dni, dhi, - n_processes=n_workers_for_parallel_calcs) - else: - inputs = (pvarray_parameters, timestamps, solar_zenith, solar_azimuth, - surface_tilt, surface_azimuth, dni, dhi) - df_registries, df_custom_perez = calculate_radiosities_serially_perez( - inputs) - - # Get the average surface outputs - df_outputs = get_average_pvrow_outputs(df_registries, - values=['qinc'], - include_shading=True) - - # Select the calculated outputs from the pvrow to observe - ipoa_front = df_outputs.loc[:, idx_slice[index_observed_pvrow, - 'front', 'qinc']].values - - ipoa_back = df_outputs.loc[:, idx_slice[index_observed_pvrow, - 'back', 'qinc']].values - - return ipoa_front, ipoa_back, df_registries diff --git a/pvlib/test/test_bifacial.py b/pvlib/test/test_bifacial.py new file mode 100644 index 0000000000..a0da2680cf --- /dev/null +++ b/pvlib/test/test_bifacial.py @@ -0,0 +1,66 @@ +import numpy as np +from datetime import datetime +from pvlib.bifacial import pvfactors_timeseries +from conftest import (requires_pvfactors, requires_future, requires_shapely, + requires_scipy) + + +@requires_scipy +@requires_shapely +@requires_future +@requires_pvfactors +def test_pvfactors_timeseries(): + """ Test that pvfactors is functional, using the TLDR section inputs of the + package github repo README.md file""" + + # Create some inputs + timestamps = np.array([datetime(2017, 8, 31, 11), + datetime(2017, 8, 31, 12)]) + solar_zenith = np.array([20., 10.]) + solar_azimuth = np.array([110., 140.]) + surface_tilt = np.array([10., 0.]) + surface_azimuth = np.array([90., 90.]) + dni = np.array([1000., 300.]) + dhi = np.array([50., 500.]) + gcr = 0.4 + pvrow_height = 1.75 + pvrow_width = 2.44 + albedo = 0.2 + n_pvrows = 3 + index_observed_pvrow = 1 + rho_front_pvrow = 0.03 + rho_back_pvrow = 0.05 + horizon_band_angle = 15. + + # Expected values + expected_ipoa_front = [1034.96216923, 795.4423259] + expected_ipoa_back = [92.11871485, 70.39404124] + tolerance = 1e-6 + + # Test serial calculations + ipoa_front, ipoa_back, _ = pvfactors_timeseries( + solar_azimuth, solar_zenith, surface_azimuth, surface_tilt, + timestamps, dni, dhi, gcr, pvrow_height, pvrow_width, albedo, + n_pvrows=n_pvrows, index_observed_pvrow=index_observed_pvrow, + rho_front_pvrow=rho_front_pvrow, rho_back_pvrow=rho_back_pvrow, + horizon_band_angle=horizon_band_angle, + run_parallel_calculations=False, n_workers_for_parallel_calcs=None) + + np.testing.assert_allclose(ipoa_front, expected_ipoa_front, + atol=0, rtol=tolerance) + np.testing.assert_allclose(ipoa_back, expected_ipoa_back, + atol=0, rtol=tolerance) + + # Run calculations in parallel + ipoa_front, ipoa_back, _ = pvfactors_timeseries( + solar_azimuth, solar_zenith, surface_azimuth, surface_tilt, + timestamps, dni, dhi, gcr, pvrow_height, pvrow_width, albedo, + n_pvrows=n_pvrows, index_observed_pvrow=index_observed_pvrow, + rho_front_pvrow=rho_front_pvrow, rho_back_pvrow=rho_back_pvrow, + horizon_band_angle=horizon_band_angle, + run_parallel_calculations=True, n_workers_for_parallel_calcs=None) + + np.testing.assert_allclose(ipoa_front, expected_ipoa_front, + atol=0, rtol=tolerance) + np.testing.assert_allclose(ipoa_back, expected_ipoa_back, + atol=0, rtol=tolerance) diff --git a/pvlib/test/test_irradiance.py b/pvlib/test/test_irradiance.py index f6637774c8..b68f164563 100644 --- a/pvlib/test/test_irradiance.py +++ b/pvlib/test/test_irradiance.py @@ -14,8 +14,7 @@ from pvlib._deprecation import pvlibDeprecationWarning from conftest import (fail_on_pvlib_version, needs_numpy_1_10, pandas_0_22, - requires_ephem, requires_numba, requires_pvfactors, - requires_future, requires_shapely, requires_scipy) + requires_ephem, requires_numba) # fixtures create realistic test input data @@ -856,62 +855,3 @@ def test_clearness_index_zenith_independent(airmass_kt): assert_series_equal(out, expected) -@requires_scipy -@requires_shapely -@requires_future -@requires_pvfactors -def test_pvfactors_bifacial_irradiance(): - """ Test that pvfactors is functional, using the TLDR section inputs of the - package github repo README.md file""" - - # Create some inputs - timestamps = np.array([datetime.datetime(2017, 8, 31, 11), - datetime.datetime(2017, 8, 31, 12)]) - solar_zenith = np.array([20., 10.]) - solar_azimuth = np.array([110., 140.]) - surface_tilt = np.array([10., 0.]) - surface_azimuth = np.array([90., 90.]) - dni = np.array([1000., 300.]) - dhi = np.array([50., 500.]) - gcr = 0.4 - pvrow_height = 1.75 - pvrow_width = 2.44 - albedo = 0.2 - n_pvrows = 3 - index_observed_pvrow = 1 - rho_front_pvrow = 0.03 - rho_back_pvrow = 0.05 - horizon_band_angle = 15. - - # Expected values - expected_ipoa_front = [1034.96216923, 795.4423259] - expected_ipoa_back = [92.11871485, 70.39404124] - tolerance = 1e-6 - - # Test serial calculations - ipoa_front, ipoa_back, _ = irradiance.pvfactors_bifacial_irradiance( - solar_azimuth, solar_zenith, surface_azimuth, surface_tilt, - timestamps, dni, dhi, gcr, pvrow_height, pvrow_width, albedo, - n_pvrows=n_pvrows, index_observed_pvrow=index_observed_pvrow, - rho_front_pvrow=rho_front_pvrow, rho_back_pvrow=rho_back_pvrow, - horizon_band_angle=horizon_band_angle, - run_parallel_calculations=False, n_workers_for_parallel_calcs=None) - - np.testing.assert_allclose(ipoa_front, expected_ipoa_front, - atol=0, rtol=tolerance) - np.testing.assert_allclose(ipoa_back, expected_ipoa_back, - atol=0, rtol=tolerance) - - # Run calculations in parallel - ipoa_front, ipoa_back, _ = irradiance.pvfactors_bifacial_irradiance( - solar_azimuth, solar_zenith, surface_azimuth, surface_tilt, - timestamps, dni, dhi, gcr, pvrow_height, pvrow_width, albedo, - n_pvrows=n_pvrows, index_observed_pvrow=index_observed_pvrow, - rho_front_pvrow=rho_front_pvrow, rho_back_pvrow=rho_back_pvrow, - horizon_band_angle=horizon_band_angle, - run_parallel_calculations=True, n_workers_for_parallel_calcs=None) - - np.testing.assert_allclose(ipoa_front, expected_ipoa_front, - atol=0, rtol=tolerance) - np.testing.assert_allclose(ipoa_back, expected_ipoa_back, - atol=0, rtol=tolerance) From a340c205df27dc5802df815678970d7be557f2c4 Mon Sep 17 00:00:00 2001 From: anomam Date: Mon, 17 Dec 2018 11:38:12 +0900 Subject: [PATCH 07/27] Reverting autopep8 changes in irradiance.py and test_irradiance.py --- pvlib/irradiance.py | 218 +++++++++++++++++----------------- pvlib/test/test_irradiance.py | 202 ++++++++++++++++--------------- 2 files changed, 208 insertions(+), 212 deletions(-) diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index 042768b416..4855187ea4 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -113,7 +113,7 @@ def get_extra_radiation(datetime_or_doy, solar_constant=1366.1, extraradiation = deprecated('0.6', alternative='get_extra_radiation', name='extraradiation', removal='0.7')( - get_extra_radiation) + get_extra_radiation) def _handle_extra_radiation_types(datetime_or_doy, epoch_year): @@ -125,7 +125,6 @@ def _handle_extra_radiation_types(datetime_or_doy, epoch_year): # a better way to do it. if isinstance(datetime_or_doy, pd.DatetimeIndex): to_doy = tools._pandas_to_doy # won't be evaluated unless necessary - def to_datetimeindex(x): return x # noqa: E306 to_output = partial(pd.Series, index=datetime_or_doy) elif isinstance(datetime_or_doy, pd.Timestamp): @@ -369,7 +368,7 @@ def get_total_irradiance(surface_tilt, surface_azimuth, total_irrad = deprecated('0.6', alternative='get_total_irradiance', name='total_irrad', removal='0.7')( - get_total_irradiance) + get_total_irradiance) def get_sky_diffuse(surface_tilt, surface_azimuth, @@ -630,7 +629,7 @@ def get_ground_diffuse(surface_tilt, ghi, albedo=.25, surface_type=None): grounddiffuse = deprecated('0.6', alternative='get_ground_diffuse', name='grounddiffuse', removal='0.7')( - get_ground_diffuse) + get_ground_diffuse) def isotropic(surface_tilt, dhi): @@ -1429,18 +1428,18 @@ def _disc_kn(clearness_index, airmass, max_airmass=12): bools = (kt <= 0.6) a = np.where(bools, - 0.512 - 1.56 * kt + 2.286 * kt2 - 2.222 * kt3, - -5.743 + 21.77 * kt - 27.49 * kt2 + 11.56 * kt3) + 0.512 - 1.56*kt + 2.286*kt2 - 2.222*kt3, + -5.743 + 21.77*kt - 27.49*kt2 + 11.56*kt3) b = np.where(bools, - 0.37 + 0.962 * kt, - 41.4 - 118.5 * kt + 66.05 * kt2 + 31.9 * kt3) + 0.37 + 0.962*kt, + 41.4 - 118.5*kt + 66.05*kt2 + 31.9*kt3) c = np.where(bools, - -0.28 + 0.932 * kt - 2.048 * kt2, - -47.01 + 184.2 * kt - 222.0 * kt2 + 73.81 * kt3) + -0.28 + 0.932*kt - 2.048*kt2, + -47.01 + 184.2*kt - 222.0*kt2 + 73.81*kt3) - delta_kn = a + b * np.exp(c * am) + delta_kn = a + b * np.exp(c*am) - Knc = 0.866 - 0.122 * am + 0.0121 * am**2 - 0.000653 * am**3 + 1.4e-05 * am**4 + Knc = 0.866 - 0.122*am + 0.0121*am**2 - 0.000653*am**3 + 1.4e-05*am**4 Kn = Knc - delta_kn return Kn, am @@ -1564,9 +1563,9 @@ def _delta_kt_prime_dirint(kt_prime, use_delta_kt_prime, times): """ if use_delta_kt_prime: # Perez eqn 2 - delta_kt_prime = 0.5 * ((kt_prime - kt_prime.shift(1)).abs().add( - (kt_prime - kt_prime.shift(-1)).abs(), - fill_value=0)) + delta_kt_prime = 0.5*((kt_prime - kt_prime.shift(1)).abs().add( + (kt_prime - kt_prime.shift(-1)).abs(), + fill_value=0)) else: # do not change unless also modifying _dirint_bins delta_kt_prime = pd.Series(-1, index=times) @@ -1613,8 +1612,8 @@ def _dirint_coeffs(times, kt_prime, solar_zenith, w, delta_kt_prime): # subtract 1 to account for difference between MATLAB-style bin # assignment and Python-style array lookup. - dirint_coeffs = coeffs[kt_prime_bin - 1, zenith_bin - 1, - delta_kt_prime_bin - 1, w_bin - 1] + dirint_coeffs = coeffs[kt_prime_bin-1, zenith_bin-1, + delta_kt_prime_bin-1, w_bin-1] # convert unassigned bins to nan dirint_coeffs = np.where((kt_prime_bin == 0) | (zenith_bin == 0) | @@ -2164,12 +2163,12 @@ def erbs(ghi, zenith, doy): kt = np.maximum(kt, 0) # For Kt <= 0.22, set the diffuse fraction - df = 1 - 0.09 * kt + df = 1 - 0.09*kt # For Kt > 0.22 and Kt <= 0.8, set the diffuse fraction df = np.where((kt > 0.22) & (kt <= 0.8), - 0.9511 - 0.1604 * kt + 4.388 * kt**2 - - 16.638 * kt**3 + 12.336 * kt**4, + 0.9511 - 0.1604*kt + 4.388*kt**2 - + 16.638*kt**3 + 12.336*kt**4, df) # For Kt > 0.8, set the diffuse fraction @@ -2233,7 +2232,7 @@ def liujordan(zenith, transmittance, airmass, dni_extra=1367.0): tau = transmittance - dni = dni_extra * tau**airmass + dni = dni_extra*tau**airmass dhi = 0.3 * (1.0 - tau**airmass) * dni_extra * np.cos(np.radians(zenith)) ghi = dhi + dni * np.cos(np.radians(zenith)) @@ -2301,104 +2300,104 @@ def _get_perez_coefficients(perezmodel): ''' coeffdict = { 'allsitescomposite1990': [ - [-0.0080, 0.5880, -0.0620, -0.0600, 0.0720, -0.0220], - [0.1300, 0.6830, -0.1510, -0.0190, 0.0660, -0.0290], - [0.3300, 0.4870, -0.2210, 0.0550, -0.0640, -0.0260], - [0.5680, 0.1870, -0.2950, 0.1090, -0.1520, -0.0140], - [0.8730, -0.3920, -0.3620, 0.2260, -0.4620, 0.0010], - [1.1320, -1.2370, -0.4120, 0.2880, -0.8230, 0.0560], - [1.0600, -1.6000, -0.3590, 0.2640, -1.1270, 0.1310], - [0.6780, -0.3270, -0.2500, 0.1560, -1.3770, 0.2510]], + [-0.0080, 0.5880, -0.0620, -0.0600, 0.0720, -0.0220], + [0.1300, 0.6830, -0.1510, -0.0190, 0.0660, -0.0290], + [0.3300, 0.4870, -0.2210, 0.0550, -0.0640, -0.0260], + [0.5680, 0.1870, -0.2950, 0.1090, -0.1520, -0.0140], + [0.8730, -0.3920, -0.3620, 0.2260, -0.4620, 0.0010], + [1.1320, -1.2370, -0.4120, 0.2880, -0.8230, 0.0560], + [1.0600, -1.6000, -0.3590, 0.2640, -1.1270, 0.1310], + [0.6780, -0.3270, -0.2500, 0.1560, -1.3770, 0.2510]], 'allsitescomposite1988': [ - [-0.0180, 0.7050, -0.071, -0.0580, 0.1020, -0.0260], - [0.1910, 0.6450, -0.1710, 0.0120, 0.0090, -0.0270], - [0.4400, 0.3780, -0.2560, 0.0870, -0.1040, -0.0250], - [0.7560, -0.1210, -0.3460, 0.1790, -0.3210, -0.0080], - [0.9960, -0.6450, -0.4050, 0.2600, -0.5900, 0.0170], - [1.0980, -1.2900, -0.3930, 0.2690, -0.8320, 0.0750], - [0.9730, -1.1350, -0.3780, 0.1240, -0.2580, 0.1490], - [0.6890, -0.4120, -0.2730, 0.1990, -1.6750, 0.2370]], + [-0.0180, 0.7050, -0.071, -0.0580, 0.1020, -0.0260], + [0.1910, 0.6450, -0.1710, 0.0120, 0.0090, -0.0270], + [0.4400, 0.3780, -0.2560, 0.0870, -0.1040, -0.0250], + [0.7560, -0.1210, -0.3460, 0.1790, -0.3210, -0.0080], + [0.9960, -0.6450, -0.4050, 0.2600, -0.5900, 0.0170], + [1.0980, -1.2900, -0.3930, 0.2690, -0.8320, 0.0750], + [0.9730, -1.1350, -0.3780, 0.1240, -0.2580, 0.1490], + [0.6890, -0.4120, -0.2730, 0.1990, -1.6750, 0.2370]], 'sandiacomposite1988': [ - [-0.1960, 1.0840, -0.0060, -0.1140, 0.1800, -0.0190], - [0.2360, 0.5190, -0.1800, -0.0110, 0.0200, -0.0380], - [0.4540, 0.3210, -0.2550, 0.0720, -0.0980, -0.0460], - [0.8660, -0.3810, -0.3750, 0.2030, -0.4030, -0.0490], - [1.0260, -0.7110, -0.4260, 0.2730, -0.6020, -0.0610], - [0.9780, -0.9860, -0.3500, 0.2800, -0.9150, -0.0240], - [0.7480, -0.9130, -0.2360, 0.1730, -1.0450, 0.0650], - [0.3180, -0.7570, 0.1030, 0.0620, -1.6980, 0.2360]], + [-0.1960, 1.0840, -0.0060, -0.1140, 0.1800, -0.0190], + [0.2360, 0.5190, -0.1800, -0.0110, 0.0200, -0.0380], + [0.4540, 0.3210, -0.2550, 0.0720, -0.0980, -0.0460], + [0.8660, -0.3810, -0.3750, 0.2030, -0.4030, -0.0490], + [1.0260, -0.7110, -0.4260, 0.2730, -0.6020, -0.0610], + [0.9780, -0.9860, -0.3500, 0.2800, -0.9150, -0.0240], + [0.7480, -0.9130, -0.2360, 0.1730, -1.0450, 0.0650], + [0.3180, -0.7570, 0.1030, 0.0620, -1.6980, 0.2360]], 'usacomposite1988': [ - [-0.0340, 0.6710, -0.0590, -0.0590, 0.0860, -0.0280], - [0.2550, 0.4740, -0.1910, 0.0180, -0.0140, -0.0330], - [0.4270, 0.3490, -0.2450, 0.0930, -0.1210, -0.0390], - [0.7560, -0.2130, -0.3280, 0.1750, -0.3040, -0.0270], - [1.0200, -0.8570, -0.3850, 0.2800, -0.6380, -0.0190], - [1.0500, -1.3440, -0.3480, 0.2800, -0.8930, 0.0370], - [0.9740, -1.5070, -0.3700, 0.1540, -0.5680, 0.1090], - [0.7440, -1.8170, -0.2560, 0.2460, -2.6180, 0.2300]], + [-0.0340, 0.6710, -0.0590, -0.0590, 0.0860, -0.0280], + [0.2550, 0.4740, -0.1910, 0.0180, -0.0140, -0.0330], + [0.4270, 0.3490, -0.2450, 0.0930, -0.1210, -0.0390], + [0.7560, -0.2130, -0.3280, 0.1750, -0.3040, -0.0270], + [1.0200, -0.8570, -0.3850, 0.2800, -0.6380, -0.0190], + [1.0500, -1.3440, -0.3480, 0.2800, -0.8930, 0.0370], + [0.9740, -1.5070, -0.3700, 0.1540, -0.5680, 0.1090], + [0.7440, -1.8170, -0.2560, 0.2460, -2.6180, 0.2300]], 'france1988': [ - [0.0130, 0.7640, -0.1000, -0.0580, 0.1270, -0.0230], - [0.0950, 0.9200, -0.1520, 0, 0.0510, -0.0200], - [0.4640, 0.4210, -0.2800, 0.0640, -0.0510, -0.0020], - [0.7590, -0.0090, -0.3730, 0.2010, -0.3820, 0.0100], - [0.9760, -0.4000, -0.4360, 0.2710, -0.6380, 0.0510], - [1.1760, -1.2540, -0.4620, 0.2950, -0.9750, 0.1290], - [1.1060, -1.5630, -0.3980, 0.3010, -1.4420, 0.2120], - [0.9340, -1.5010, -0.2710, 0.4200, -2.9170, 0.2490]], + [0.0130, 0.7640, -0.1000, -0.0580, 0.1270, -0.0230], + [0.0950, 0.9200, -0.1520, 0, 0.0510, -0.0200], + [0.4640, 0.4210, -0.2800, 0.0640, -0.0510, -0.0020], + [0.7590, -0.0090, -0.3730, 0.2010, -0.3820, 0.0100], + [0.9760, -0.4000, -0.4360, 0.2710, -0.6380, 0.0510], + [1.1760, -1.2540, -0.4620, 0.2950, -0.9750, 0.1290], + [1.1060, -1.5630, -0.3980, 0.3010, -1.4420, 0.2120], + [0.9340, -1.5010, -0.2710, 0.4200, -2.9170, 0.2490]], 'phoenix1988': [ - [-0.0030, 0.7280, -0.0970, -0.0750, 0.1420, -0.0430], - [0.2790, 0.3540, -0.1760, 0.0300, -0.0550, -0.0540], - [0.4690, 0.1680, -0.2460, 0.0480, -0.0420, -0.0570], - [0.8560, -0.5190, -0.3400, 0.1760, -0.3800, -0.0310], - [0.9410, -0.6250, -0.3910, 0.1880, -0.3600, -0.0490], - [1.0560, -1.1340, -0.4100, 0.2810, -0.7940, -0.0650], - [0.9010, -2.1390, -0.2690, 0.1180, -0.6650, 0.0460], - [0.1070, 0.4810, 0.1430, -0.1110, -0.1370, 0.2340]], + [-0.0030, 0.7280, -0.0970, -0.0750, 0.1420, -0.0430], + [0.2790, 0.3540, -0.1760, 0.0300, -0.0550, -0.0540], + [0.4690, 0.1680, -0.2460, 0.0480, -0.0420, -0.0570], + [0.8560, -0.5190, -0.3400, 0.1760, -0.3800, -0.0310], + [0.9410, -0.6250, -0.3910, 0.1880, -0.3600, -0.0490], + [1.0560, -1.1340, -0.4100, 0.2810, -0.7940, -0.0650], + [0.9010, -2.1390, -0.2690, 0.1180, -0.6650, 0.0460], + [0.1070, 0.4810, 0.1430, -0.1110, -0.1370, 0.2340]], 'elmonte1988': [ - [0.0270, 0.7010, -0.1190, -0.0580, 0.1070, -0.0600], - [0.1810, 0.6710, -0.1780, -0.0790, 0.1940, -0.0350], - [0.4760, 0.4070, -0.2880, 0.0540, -0.0320, -0.0550], - [0.8750, -0.2180, -0.4030, 0.1870, -0.3090, -0.0610], - [1.1660, -1.0140, -0.4540, 0.2110, -0.4100, -0.0440], - [1.1430, -2.0640, -0.2910, 0.0970, -0.3190, 0.0530], - [1.0940, -2.6320, -0.2590, 0.0290, -0.4220, 0.1470], - [0.1550, 1.7230, 0.1630, -0.1310, -0.0190, 0.2770]], + [0.0270, 0.7010, -0.1190, -0.0580, 0.1070, -0.0600], + [0.1810, 0.6710, -0.1780, -0.0790, 0.1940, -0.0350], + [0.4760, 0.4070, -0.2880, 0.0540, -0.0320, -0.0550], + [0.8750, -0.2180, -0.4030, 0.1870, -0.3090, -0.0610], + [1.1660, -1.0140, -0.4540, 0.2110, -0.4100, -0.0440], + [1.1430, -2.0640, -0.2910, 0.0970, -0.3190, 0.0530], + [1.0940, -2.6320, -0.2590, 0.0290, -0.4220, 0.1470], + [0.1550, 1.7230, 0.1630, -0.1310, -0.0190, 0.2770]], 'osage1988': [ - [-0.3530, 1.4740, 0.0570, -0.1750, 0.3120, 0.0090], - [0.3630, 0.2180, -0.2120, 0.0190, -0.0340, -0.0590], - [-0.0310, 1.2620, -0.0840, -0.0820, 0.2310, -0.0170], - [0.6910, 0.0390, -0.2950, 0.0910, -0.1310, -0.0350], - [1.1820, -1.3500, -0.3210, 0.4080, -0.9850, -0.0880], - [0.7640, 0.0190, -0.2030, 0.2170, -0.2940, -0.1030], - [0.2190, 1.4120, 0.2440, 0.4710, -2.9880, 0.0340], - [3.5780, 22.2310, -10.7450, 2.4260, 4.8920, -5.6870]], + [-0.3530, 1.4740, 0.0570, -0.1750, 0.3120, 0.0090], + [0.3630, 0.2180, -0.2120, 0.0190, -0.0340, -0.0590], + [-0.0310, 1.2620, -0.0840, -0.0820, 0.2310, -0.0170], + [0.6910, 0.0390, -0.2950, 0.0910, -0.1310, -0.0350], + [1.1820, -1.3500, -0.3210, 0.4080, -0.9850, -0.0880], + [0.7640, 0.0190, -0.2030, 0.2170, -0.2940, -0.1030], + [0.2190, 1.4120, 0.2440, 0.4710, -2.9880, 0.0340], + [3.5780, 22.2310, -10.7450, 2.4260, 4.8920, -5.6870]], 'albuquerque1988': [ - [0.0340, 0.5010, -0.0940, -0.0630, 0.1060, -0.0440], - [0.2290, 0.4670, -0.1560, -0.0050, -0.0190, -0.0230], - [0.4860, 0.2410, -0.2530, 0.0530, -0.0640, -0.0220], - [0.8740, -0.3930, -0.3970, 0.1810, -0.3270, -0.0370], - [1.1930, -1.2960, -0.5010, 0.2810, -0.6560, -0.0450], - [1.0560, -1.7580, -0.3740, 0.2260, -0.7590, 0.0340], - [0.9010, -4.7830, -0.1090, 0.0630, -0.9700, 0.1960], - [0.8510, -7.0550, -0.0530, 0.0600, -2.8330, 0.3300]], + [0.0340, 0.5010, -0.0940, -0.0630, 0.1060, -0.0440], + [0.2290, 0.4670, -0.1560, -0.0050, -0.0190, -0.0230], + [0.4860, 0.2410, -0.2530, 0.0530, -0.0640, -0.0220], + [0.8740, -0.3930, -0.3970, 0.1810, -0.3270, -0.0370], + [1.1930, -1.2960, -0.5010, 0.2810, -0.6560, -0.0450], + [1.0560, -1.7580, -0.3740, 0.2260, -0.7590, 0.0340], + [0.9010, -4.7830, -0.1090, 0.0630, -0.9700, 0.1960], + [0.8510, -7.0550, -0.0530, 0.0600, -2.8330, 0.3300]], 'capecanaveral1988': [ - [0.0750, 0.5330, -0.1240, -0.0670, 0.0420, -0.0200], - [0.2950, 0.4970, -0.2180, -0.0080, 0.0030, -0.0290], - [0.5140, 0.0810, -0.2610, 0.0750, -0.1600, -0.0290], - [0.7470, -0.3290, -0.3250, 0.1810, -0.4160, -0.0300], - [0.9010, -0.8830, -0.2970, 0.1780, -0.4890, 0.0080], - [0.5910, -0.0440, -0.1160, 0.2350, -0.9990, 0.0980], - [0.5370, -2.4020, 0.3200, 0.1690, -1.9710, 0.3100], - [-0.8050, 4.5460, 1.0720, -0.2580, -0.9500, 0.7530]], + [0.0750, 0.5330, -0.1240, -0.0670, 0.0420, -0.0200], + [0.2950, 0.4970, -0.2180, -0.0080, 0.0030, -0.0290], + [0.5140, 0.0810, -0.2610, 0.0750, -0.1600, -0.0290], + [0.7470, -0.3290, -0.3250, 0.1810, -0.4160, -0.0300], + [0.9010, -0.8830, -0.2970, 0.1780, -0.4890, 0.0080], + [0.5910, -0.0440, -0.1160, 0.2350, -0.9990, 0.0980], + [0.5370, -2.4020, 0.3200, 0.1690, -1.9710, 0.3100], + [-0.8050, 4.5460, 1.0720, -0.2580, -0.9500, 0.7530]], 'albany1988': [ - [0.0120, 0.5540, -0.0760, -0.0520, 0.0840, -0.0290], - [0.2670, 0.4370, -0.1940, 0.0160, 0.0220, -0.0360], - [0.4200, 0.3360, -0.2370, 0.0740, -0.0520, -0.0320], - [0.6380, -0.0010, -0.2810, 0.1380, -0.1890, -0.0120], - [1.0190, -1.0270, -0.3420, 0.2710, -0.6280, 0.0140], - [1.1490, -1.9400, -0.3310, 0.3220, -1.0970, 0.0800], - [1.4340, -3.9940, -0.4920, 0.4530, -2.3760, 0.1170], - [1.0070, -2.2920, -0.4820, 0.3900, -3.3680, 0.2290]], } + [0.0120, 0.5540, -0.0760, -0.0520, 0.0840, -0.0290], + [0.2670, 0.4370, -0.1940, 0.0160, 0.0220, -0.0360], + [0.4200, 0.3360, -0.2370, 0.0740, -0.0520, -0.0320], + [0.6380, -0.0010, -0.2810, 0.1380, -0.1890, -0.0120], + [1.0190, -1.0270, -0.3420, 0.2710, -0.6280, 0.0140], + [1.1490, -1.9400, -0.3310, 0.3220, -1.0970, 0.0800], + [1.4340, -3.9940, -0.4920, 0.4530, -2.3760, 0.1170], + [1.0070, -2.2920, -0.4820, 0.3900, -3.3680, 0.2290]], } array = np.array(coeffdict[perezmodel]) @@ -2820,4 +2819,3 @@ def dni(ghi, dhi, zenith, clearsky_dni=None, clearsky_tolerance=1.1, (zenith < zenith_threshold_for_zero_dni) & (dni > max_dni)] = max_dni return dni - diff --git a/pvlib/test/test_irradiance.py b/pvlib/test/test_irradiance.py index b68f164563..cd1c5b168d 100644 --- a/pvlib/test/test_irradiance.py +++ b/pvlib/test/test_irradiance.py @@ -32,24 +32,24 @@ def times(): @pytest.fixture def irrad_data(times): return pd.DataFrame(np.array( - [[0., 0., 0.], - [79.73860422, 316.1949056, 40.46149818], - [1042.48031487, 939.95469881, 118.45831879], - [257.20751138, 646.22886049, 62.03376265]]), + [[ 0. , 0. , 0. ], + [ 79.73860422, 316.1949056 , 40.46149818], + [1042.48031487, 939.95469881, 118.45831879], + [ 257.20751138, 646.22886049, 62.03376265]]), columns=['ghi', 'dni', 'dhi'], index=times) @pytest.fixture def ephem_data(times): return pd.DataFrame(np.array( - [[124.0390863, 124.0390863, -34.0390863, -34.0390863, - 352.69550699, -2.36677158], - [82.85457044, 82.97705621, 7.14542956, 7.02294379, - 66.71410338, -2.42072165], - [10.56413562, 10.56725766, 79.43586438, 79.43274234, - 144.76567754, -2.47457321], - [72.41687122, 72.46903556, 17.58312878, 17.53096444, - 287.04104128, -2.52831909]]), + [[124.0390863 , 124.0390863 , -34.0390863 , -34.0390863 , + 352.69550699, -2.36677158], + [ 82.85457044, 82.97705621, 7.14542956, 7.02294379, + 66.71410338, -2.42072165], + [ 10.56413562, 10.56725766, 79.43586438, 79.43274234, + 144.76567754, -2.47457321], + [ 72.41687122, 72.46903556, 17.58312878, 17.53096444, + 287.04104128, -2.52831909]]), columns=['apparent_zenith', 'zenith', 'apparent_elevation', 'elevation', 'azimuth', 'equation_of_time'], index=times) @@ -194,25 +194,25 @@ def test_klucher_series(irrad_data, ephem_data): def test_haydavies(irrad_data, ephem_data, dni_et): result = irradiance.haydavies(40, 180, irrad_data['dhi'], irrad_data['dni'], - dni_et, - ephem_data['apparent_zenith'], - ephem_data['azimuth']) + dni_et, + ephem_data['apparent_zenith'], + ephem_data['azimuth']) # values from matlab 1.4 code assert_allclose(result, [0, 27.1775, 102.9949, 33.1909], atol=1e-4) def test_reindl(irrad_data, ephem_data, dni_et): result = irradiance.reindl(40, 180, irrad_data['dhi'], irrad_data['dni'], - irrad_data['ghi'], dni_et, - ephem_data['apparent_zenith'], - ephem_data['azimuth']) + irrad_data['ghi'], dni_et, + ephem_data['apparent_zenith'], + ephem_data['azimuth']) # values from matlab 1.4 code assert_allclose(result, [np.nan, 27.9412, 104.1317, 34.1663], atol=1e-4) def test_king(irrad_data, ephem_data): result = irradiance.king(40, irrad_data['dhi'], irrad_data['ghi'], - ephem_data['apparent_zenith']) + ephem_data['apparent_zenith']) assert_allclose(result, [0, 44.629352, 115.182626, 79.719855], atol=1e-4) @@ -220,10 +220,10 @@ def test_perez(irrad_data, ephem_data, dni_et, relative_airmass): dni = irrad_data['dni'].copy() dni.iloc[2] = np.nan out = irradiance.perez(40, 180, irrad_data['dhi'], dni, - dni_et, ephem_data['apparent_zenith'], - ephem_data['azimuth'], relative_airmass) + dni_et, ephem_data['apparent_zenith'], + ephem_data['azimuth'], relative_airmass) expected = pd.Series(np.array( - [0., 31.46046871, np.nan, 45.45539877]), + [ 0. , 31.46046871, np.nan, 45.45539877]), index=irrad_data.index) assert_series_equal(out, expected, check_less_precise=2) @@ -236,10 +236,10 @@ def test_perez_components(irrad_data, ephem_data, dni_et, relative_airmass): ephem_data['azimuth'], relative_airmass, return_components=True) expected = pd.DataFrame(np.array( - [[0., 31.46046871, np.nan, 45.45539877], - [0., 26.84138589, np.nan, 31.72696071], - [0., 0., np.nan, 4.47966439], - [0., 4.62212181, np.nan, 9.25316454]]).T, + [[ 0. , 31.46046871, np.nan, 45.45539877], + [ 0. , 26.84138589, np.nan, 31.72696071], + [ 0. , 0. , np.nan, 4.47966439], + [ 0. , 4.62212181, np.nan, 9.25316454]]).T, columns=['sky_diffuse', 'isotropic', 'circumsolar', 'horizon'], index=irrad_data.index ) @@ -260,10 +260,10 @@ def test_perez_arrays(irrad_data, ephem_data, dni_et, relative_airmass): dni = irrad_data['dni'].copy() dni.iloc[2] = np.nan out = irradiance.perez(40, 180, irrad_data['dhi'].values, dni.values, - dni_et, ephem_data['apparent_zenith'].values, - ephem_data['azimuth'].values, relative_airmass.values) + dni_et, ephem_data['apparent_zenith'].values, + ephem_data['azimuth'].values, relative_airmass.values) expected = np.array( - [0., 31.46046871, np.nan, 45.45539877]) + [ 0. , 31.46046871, np.nan, 45.45539877]) assert_allclose(out, expected, atol=1e-2) assert isinstance(out, np.ndarray) @@ -288,9 +288,9 @@ def test_sky_diffuse_zenith_close_to_90(model): def test_liujordan(): expected = pd.DataFrame(np. - array([[863.859736967, 653.123094076, 220.65905025]]), - columns=['ghi', 'dni', 'dhi'], - index=[0]) + array([[863.859736967, 653.123094076, 220.65905025]]), + columns=['ghi', 'dni', 'dhi'], + index=[0]) out = irradiance.liujordan( pd.Series([10]), pd.Series([0.5]), pd.Series([1.1]), dni_extra=1400) assert_frame_equal(out, expected) @@ -345,14 +345,14 @@ def test_poa_components(irrad_data, ephem_data, dni_et, relative_airmass): out = irradiance.poa_components( aoi, irrad_data['dni'], diff_perez, gr_sand) expected = pd.DataFrame(np.array( - [[0., -0., 0., 0., - 0.], - [35.19456561, 0., 35.19456561, 31.4635077, + [[ 0. , -0. , 0. , 0. , + 0. ], + [ 35.19456561, 0. , 35.19456561, 31.4635077 , 3.73105791], [956.18253696, 798.31939281, 157.86314414, 109.08433162, - 48.77881252], - [90.99624896, 33.50143401, 57.49481495, 45.45978964, - 12.03502531]]), + 48.77881252], + [ 90.99624896, 33.50143401, 57.49481495, 45.45978964, + 12.03502531]]), columns=['poa_global', 'poa_direct', 'poa_diffuse', 'poa_sky_diffuse', 'poa_ground_diffuse'], index=irrad_data.index) @@ -360,12 +360,12 @@ def test_poa_components(irrad_data, ephem_data, dni_et, relative_airmass): @pytest.mark.parametrize('pressure,expected', [ - (93193, [[830.46567, 0.79742, 0.93505], - [676.09497, 0.63776, 3.02102]]), - (None, [[868.72425, 0.79742, 1.01664], - [680.66679, 0.63776, 3.28463]]), - (101325, [[868.72425, 0.79742, 1.01664], - [680.66679, 0.63776, 3.28463]]) + (93193, [[830.46567, 0.79742, 0.93505], + [676.09497, 0.63776, 3.02102]]), + (None, [[868.72425, 0.79742, 1.01664], + [680.66679, 0.63776, 3.28463]]), + (101325, [[868.72425, 0.79742, 1.01664], + [680.66679, 0.63776, 3.28463]]) ]) def test_disc_value(pressure, expected): # see GH 449 for pressure=None vs. 101325. @@ -460,19 +460,19 @@ def test_disc_min_cos_zenith_max_zenith(): def test_dirint_value(): - times = pd.DatetimeIndex(['2014-06-24T12-0700', '2014-06-24T18-0700']) + times = pd.DatetimeIndex(['2014-06-24T12-0700','2014-06-24T18-0700']) ghi = pd.Series([1038.62, 254.53], index=times) zenith = pd.Series([10.567, 72.469], index=times) pressure = 93193. dirint_data = irradiance.dirint(ghi, zenith, times, pressure=pressure) assert_almost_equal(dirint_data.values, - np.array([888., 683.7]), 1) + np.array([ 888. , 683.7]), 1) def test_dirint_nans(): times = pd.DatetimeIndex(start='2014-06-24T12-0700', periods=5, freq='6H') ghi = pd.Series([np.nan, 1038.62, 1038.62, 1038.62, 1038.62], index=times) - zenith = pd.Series([10.567, np.nan, 10.567, 10.567, 10.567, ], index=times) + zenith = pd.Series([10.567, np.nan, 10.567, 10.567, 10.567,], index=times) pressure = pd.Series([93193., 93193., np.nan, 93193., 93193.], index=times) temp_dew = pd.Series([10, 10, 10, np.nan, 10], index=times) dirint_data = irradiance.dirint(ghi, zenith, times, pressure=pressure, @@ -482,39 +482,39 @@ def test_dirint_nans(): def test_dirint_tdew(): - times = pd.DatetimeIndex(['2014-06-24T12-0700', '2014-06-24T18-0700']) + times = pd.DatetimeIndex(['2014-06-24T12-0700','2014-06-24T18-0700']) ghi = pd.Series([1038.62, 254.53], index=times) zenith = pd.Series([10.567, 72.469], index=times) pressure = 93193. dirint_data = irradiance.dirint(ghi, zenith, times, pressure=pressure, temp_dew=10) assert_almost_equal(dirint_data.values, - np.array([892.9, 636.5]), 1) + np.array([892.9, 636.5]), 1) def test_dirint_no_delta_kt(): - times = pd.DatetimeIndex(['2014-06-24T12-0700', '2014-06-24T18-0700']) + times = pd.DatetimeIndex(['2014-06-24T12-0700','2014-06-24T18-0700']) ghi = pd.Series([1038.62, 254.53], index=times) zenith = pd.Series([10.567, 72.469], index=times) pressure = 93193. dirint_data = irradiance.dirint(ghi, zenith, times, pressure=pressure, use_delta_kt_prime=False) assert_almost_equal(dirint_data.values, - np.array([861.9, 670.4]), 1) + np.array([861.9, 670.4]), 1) def test_dirint_coeffs(): coeffs = irradiance._get_dirint_coeffs() - assert coeffs[0, 0, 0, 0] == 0.385230 - assert coeffs[0, 1, 2, 1] == 0.229970 - assert coeffs[3, 2, 6, 3] == 1.032260 + assert coeffs[0,0,0,0] == 0.385230 + assert coeffs[0,1,2,1] == 0.229970 + assert coeffs[3,2,6,3] == 1.032260 def test_dirint_min_cos_zenith_max_zenith(): # map out behavior under difficult conditions with various # limiting kwargs settings # times don't have any physical relevance - times = pd.DatetimeIndex(['2014-06-24T12-0700', '2014-06-24T18-0700']) + times = pd.DatetimeIndex(['2014-06-24T12-0700','2014-06-24T18-0700']) ghi = pd.Series([0, 1], index=times) solar_zenith = pd.Series([90, 89.99], index=times) @@ -557,9 +557,9 @@ def test_gti_dirint(): expected_col_order = ['ghi', 'dni', 'dhi'] expected = pd.DataFrame(array( - [[21.05796198, 0., 21.05796198], - [288.22574368, 60.59964218, 245.37532576], - [930.85454521, 695.8504884, 276.96897609]]), + [[ 21.05796198, 0. , 21.05796198], + [ 288.22574368, 60.59964218, 245.37532576], + [ 930.85454521, 695.8504884 , 276.96897609]]), columns=expected_col_order, index=times) assert_frame_equal(output, expected) @@ -581,9 +581,9 @@ def test_gti_dirint(): pressure=pressure) expected = pd.DataFrame(array( - [[21.05796198, 0., 21.05796198], - [289.81109139, 60.52460392, 247.01373353], - [932.22047435, 647.68716072, 323.59362885]]), + [[ 21.05796198, 0. , 21.05796198], + [ 289.81109139, 60.52460392, 247.01373353], + [ 932.22047435, 647.68716072, 323.59362885]]), columns=expected_col_order, index=times) assert_frame_equal(output, expected) @@ -595,9 +595,9 @@ def test_gti_dirint(): albedo=albedo) expected = pd.DataFrame(array( - [[21.3592591, 0., 21.3592591], - [292.5162373, 64.42628826, 246.95997198], - [941.47847463, 727.07261187, 258.25370648]]), + [[ 21.3592591 , 0. , 21.3592591 ], + [ 292.5162373 , 64.42628826, 246.95997198], + [ 941.47847463, 727.07261187, 258.25370648]]), columns=expected_col_order, index=times) assert_frame_equal(output, expected) @@ -609,9 +609,9 @@ def test_gti_dirint(): temp_dew=temp_dew) expected = pd.DataFrame(array( - [[21.05796198, 0., 21.05796198], - [292.40468994, 36.79559287, 266.3862767], - [930.72198876, 712.36063132, 261.32196017]]), + [[ 21.05796198, 0. , 21.05796198], + [ 292.40468994, 36.79559287, 266.3862767 ], + [ 930.72198876, 712.36063132, 261.32196017]]), columns=expected_col_order, index=times) assert_frame_equal(output, expected) @@ -622,11 +622,11 @@ def test_erbs(): zenith = pd.Series([120, 85, 10, 10]) doy = pd.Series([1, 1, 1, 180]) expected = pd.DataFrame(np. - array([[-0.00000000e+00, 0.00000000e+00, -0.00000000e+00], - [9.67127061e+01, 4.15709323e+01, 4.05715990e-01], - [7.94187742e+02, 2.17877755e+02, 7.18119416e-01], - [8.42358014e+02, 1.70439297e+02, 7.68919470e-01]]), - columns=['dni', 'dhi', 'kt']) + array([[ -0.00000000e+00, 0.00000000e+00, -0.00000000e+00], + [ 9.67127061e+01, 4.15709323e+01, 4.05715990e-01], + [ 7.94187742e+02, 2.17877755e+02, 7.18119416e-01], + [ 8.42358014e+02, 1.70439297e+02, 7.68919470e-01]]), + columns=['dni', 'dhi', 'kt']) out = irradiance.erbs(ghi, zenith, doy) @@ -687,7 +687,7 @@ def test_dirindex_min_cos_zenith_max_zenith(): # map out behavior under difficult conditions with various # limiting kwargs settings # times don't have any physical relevance - times = pd.DatetimeIndex(['2014-06-24T12-0700', '2014-06-24T18-0700']) + times = pd.DatetimeIndex(['2014-06-24T12-0700','2014-06-24T18-0700']) ghi = pd.Series([0, 1], index=times) ghi_clearsky = pd.Series([0, 1], index=times) dni_clearsky = pd.Series([0, 5], index=times) @@ -733,8 +733,8 @@ def test_dni(): @pytest.mark.parametrize( - 'surface_tilt,surface_azimuth,solar_zenith,' - + 'solar_azimuth,aoi_expected,aoi_proj_expected', + 'surface_tilt,surface_azimuth,solar_zenith,' + + 'solar_azimuth,aoi_expected,aoi_proj_expected', [(0, 0, 0, 0, 0, 1), (30, 180, 30, 180, 0, 1), (30, 180, 150, 0, 180, -1), @@ -760,7 +760,7 @@ def airmass_kt(): def test_kt_kt_prime_factor(airmass_kt): out = irradiance._kt_kt_prime_factor(airmass_kt) - expected = np.array([0.999971, 0.723088, 0.548811, 0.471068]) + expected = np.array([ 0.999971, 0.723088, 0.548811, 0.471068]) assert_allclose(out, expected, atol=1e-5) @@ -772,29 +772,29 @@ def test_clearness_index(): out = irradiance.clearness_index(ghi, solar_zenith, 1370) # np.set_printoptions(precision=3, floatmode='maxprec', suppress=True) expected = np.array( - [[0., 0., 0.011, 2.], - [0., 0., 0.011, 2.], - [0., 0., 0.011, 2.], - [0., 0., 0.001, 0.73]]) + [[0. , 0. , 0.011, 2. ], + [0. , 0. , 0.011, 2. ], + [0. , 0. , 0.011, 2. ], + [0. , 0. , 0.001, 0.73 ]]) assert_allclose(out, expected, atol=0.001) # specify min_cos_zenith with np.errstate(invalid='ignore', divide='ignore'): out = irradiance.clearness_index(ghi, solar_zenith, 1400, min_cos_zenith=0) expected = np.array( - [[0., nan, 2., 2.], - [0., 0., 2., 2.], - [0., 0., 2., 2.], - [0., 0., 0.001, 0.714]]) + [[0. , nan, 2. , 2. ], + [0. , 0. , 2. , 2. ], + [0. , 0. , 2. , 2. ], + [0. , 0. , 0.001, 0.714]]) assert_allclose(out, expected, atol=0.001) # specify max_clearness_index out = irradiance.clearness_index(ghi, solar_zenith, 1370, max_clearness_index=0.82) expected = np.array( - [[0., 0., 0.011, 0.82], - [0., 0., 0.011, 0.82], - [0., 0., 0.011, 0.82], - [0., 0., 0.001, 0.73]]) + [[ 0. , 0. , 0.011, 0.82 ], + [ 0. , 0. , 0.011, 0.82 ], + [ 0. , 0. , 0.011, 0.82 ], + [ 0. , 0. , 0.001, 0.73 ]]) assert_allclose(out, expected, atol=0.001) # specify min_cos_zenith and max_clearness_index with np.errstate(invalid='ignore', divide='ignore'): @@ -802,10 +802,10 @@ def test_clearness_index(): min_cos_zenith=0, max_clearness_index=0.82) expected = np.array( - [[0., nan, 0.82, 0.82], - [0., 0., 0.82, 0.82], - [0., 0., 0.82, 0.82], - [0., 0., 0.001, 0.714]]) + [[ 0. , nan, 0.82 , 0.82 ], + [ 0. , 0. , 0.82 , 0.82 ], + [ 0. , 0. , 0.82 , 0.82 ], + [ 0. , 0. , 0.001, 0.714]]) assert_allclose(out, expected, atol=0.001) # scalars out = irradiance.clearness_index(1000, 10, 1400) @@ -827,19 +827,19 @@ def test_clearness_index_zenith_independent(airmass_kt): out = irradiance.clearness_index_zenith_independent(clearness_index, airmass_kt) expected = np.array( - [[0., 0., 0.1, 1.], - [0., 0., 0.138, 1.383], - [0., 0., 0.182, 1.822], - [0., 0., 0.212, 2.]]) + [[0. , 0. , 0.1 , 1. ], + [0. , 0. , 0.138, 1.383], + [0. , 0. , 0.182, 1.822], + [0. , 0. , 0.212, 2. ]]) assert_allclose(out, expected, atol=0.001) # test max_clearness_index out = irradiance.clearness_index_zenith_independent( clearness_index, airmass_kt, max_clearness_index=0.82) expected = np.array( - [[0., 0., 0.1, 0.82], - [0., 0., 0.138, 0.82], - [0., 0., 0.182, 0.82], - [0., 0., 0.212, 0.82]]) + [[ 0. , 0. , 0.1 , 0.82 ], + [ 0. , 0. , 0.138, 0.82 ], + [ 0. , 0. , 0.182, 0.82 ], + [ 0. , 0. , 0.212, 0.82 ]]) assert_allclose(out, expected, atol=0.001) # scalars out = irradiance.clearness_index_zenith_independent(.4, 2) @@ -853,5 +853,3 @@ def test_clearness_index_zenith_independent(airmass_kt): airmass) expected = pd.Series([np.nan, 0.553744437562], index=times) assert_series_equal(out, expected) - - From fd3adf31eb0250c6c71661ff9df119b75b7f5037 Mon Sep 17 00:00:00 2001 From: anomam Date: Mon, 17 Dec 2018 12:17:04 +0900 Subject: [PATCH 08/27] Docstrings section name change --- pvlib/bifacial.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pvlib/bifacial.py b/pvlib/bifacial.py index 5bdadf97c7..1ee4eb6d5b 100644 --- a/pvlib/bifacial.py +++ b/pvlib/bifacial.py @@ -20,8 +20,8 @@ def pvfactors_timeseries( Please refer to pvfactors online documentation for more details: https://sunpower.github.io/pvfactors/ - Parameters - ---------- + Inputs + ------ solar_azimuth: numpy array of numeric Sun's azimuth angles using pvlib's azimuth convention (deg) solar_zenith: numpy array of numeric From 6435ce3aeb9ee751eba973b2729849593a8fbd88 Mon Sep 17 00:00:00 2001 From: anomam Date: Mon, 17 Dec 2018 13:54:28 +0900 Subject: [PATCH 09/27] Implement decorator to allow use of pandas objects vs numpy arrays * I used a decorator because I wish to seperate the logic of handling the function inputs and the logic related to using pvfactors --- pvlib/bifacial.py | 2 ++ pvlib/tools.py | 52 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/pvlib/bifacial.py b/pvlib/bifacial.py index 1ee4eb6d5b..4df0d4c203 100644 --- a/pvlib/bifacial.py +++ b/pvlib/bifacial.py @@ -4,8 +4,10 @@ """ import pandas as pd +from pvlib.tools import enforce_numpy_arrays +@enforce_numpy_arrays def pvfactors_timeseries( solar_azimuth, solar_zenith, surface_azimuth, surface_tilt, timestamps, dni, dhi, gcr, pvrow_height, pvrow_width, albedo, diff --git a/pvlib/tools.py b/pvlib/tools.py index fa3d368369..125209f79f 100644 --- a/pvlib/tools.py +++ b/pvlib/tools.py @@ -8,6 +8,7 @@ import numpy as np import pandas as pd import pytz +from functools import wraps def cosd(angle): @@ -425,3 +426,54 @@ def _golden_sect_DataFrame(params, VL, VH, func): raise Exception("EXCEPTION:iterations exceeded maximum (50)") return func(df, 'V1'), df['V1'] + + +def enforce_numpy_arrays(f): + """ This decorator function will convert any inputted pandas dataframe or + series to a numpy array, and make sure to convert the outputs to pandas + series if any input was a pandas structure """ + + @wraps(f) + def wrapper(*args, **kwargs): + # Convert all inputs to numpy arrays if pandas series or dataframe + is_return_type_pandas = False + + new_args = [] + for arg in args: + if isinstance(arg, pd.DataFrame) or isinstance(arg, pd.Series): + is_return_type_pandas = True + new_arg = arg.values + new_args.append(new_arg) + else: + new_args.append(arg) + new_args = tuple(new_args) + + new_kwargs = {} + for key, val in kwargs.items(): + if isinstance(val, pd.DataFrame) or isinstance(val, pd.Series): + is_return_type_pandas = True + new_val = val.values + new_kwargs[key] = new_val + else: + new_kwargs[key] = val + + # Run function + outputs = f(*new_args, **new_kwargs) + + # If inputs were provided as pandas series or dataframe, convert + # outputs to pandas series if numpy arrays + new_outputs = [] + if is_return_type_pandas: + for output in outputs: + if isinstance(output, np.ndarray): + new_output = pd.Series(output) + new_outputs.append(new_output) + else: + new_outputs.append(output) + new_outputs = tuple(new_outputs) + else: + new_outputs = outputs + + return new_outputs + + return wrapper From 381000c1dcc7d3ac2db754358fb99992698d7409 Mon Sep 17 00:00:00 2001 From: anomam Date: Mon, 17 Dec 2018 14:02:35 +0900 Subject: [PATCH 10/27] Update function docstrings since now allowing pandas objects * via function decoration --- pvlib/bifacial.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pvlib/bifacial.py b/pvlib/bifacial.py index 4df0d4c203..277274aaa7 100644 --- a/pvlib/bifacial.py +++ b/pvlib/bifacial.py @@ -24,20 +24,20 @@ def pvfactors_timeseries( Inputs ------ - solar_azimuth: numpy array of numeric + solar_azimuth: numeric Sun's azimuth angles using pvlib's azimuth convention (deg) - solar_zenith: numpy array of numeric + solar_zenith: numeric Sun's zenith angles (deg) - surface_azimuth: numpy array of numeric + surface_azimuth: numeric Azimuth angle of the front surface of the PV modules, using pvlib's convention (deg) - surface_tilt: numpy array of numeric + surface_tilt: numeric Tilt angle of the PV modules, going from 0 to 180 (deg) timestamps: array of :class:datetime.datetime objects List of simulation timestamps - dni: numpy array of numeric values + dni: numeric Direct normal irradiance (W/m2) - dhi: numpy array of numeric values + dhi: numeric Diffuse horizontal irradiance (W/m2) gcr: float Ground coverage ratio of the pv array @@ -68,10 +68,10 @@ def pvfactors_timeseries( Returns ------- - front_poa_irradiance: numpy array of numeric + front_poa_irradiance: numeric Calculated incident irradiance on the front surface of the PV modules (W/m2) - back_poa_irradiance: numpy array of numeric + back_poa_irradiance: numeric Calculated incident irradiance on the back surface of the PV modules (W/m2) df_registries: pandas DataFrame From 74b20af7c6fa451dfff37aac66955b5fafd684ba Mon Sep 17 00:00:00 2001 From: anomam Date: Mon, 17 Dec 2018 14:06:18 +0900 Subject: [PATCH 11/27] Small docstrings fixes --- pvlib/bifacial.py | 2 +- pvlib/tools.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pvlib/bifacial.py b/pvlib/bifacial.py index 277274aaa7..7c44a79842 100644 --- a/pvlib/bifacial.py +++ b/pvlib/bifacial.py @@ -76,7 +76,7 @@ def pvfactors_timeseries( (W/m2) df_registries: pandas DataFrame DataFrame containing all the detailed outputs and elements calculated - for every timestamp of the simulation. Please refer to pvfactors' + for every timestamp of the simulation. Please refer to pvfactors documentation for more details References diff --git a/pvlib/tools.py b/pvlib/tools.py index 125209f79f..e0865988e6 100644 --- a/pvlib/tools.py +++ b/pvlib/tools.py @@ -430,8 +430,8 @@ def _golden_sect_DataFrame(params, VL, VH, func): def enforce_numpy_arrays(f): """ This decorator function will convert any inputted pandas dataframe or - series to a numpy array, and make sure to convert the outputs to pandas - series if any input was a pandas structure """ + series to a numpy array, and make sure to convert outtputed numpy arrays + to pandas series if any input was a pandas structure """ @wraps(f) def wrapper(*args, **kwargs): From 89bad6c5d4380bea76804c8df5b79c36d5b2fdbe Mon Sep 17 00:00:00 2001 From: anomam Date: Mon, 17 Dec 2018 14:51:29 +0900 Subject: [PATCH 12/27] Fix decorator for dataframe case and add test for decorator --- pvlib/test/test_tools.py | 44 ++++++++++++++++++++++++++++++++++++++++ pvlib/tools.py | 8 ++++++-- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/pvlib/test/test_tools.py b/pvlib/test/test_tools.py index dfecea2047..7b9c33d463 100644 --- a/pvlib/test/test_tools.py +++ b/pvlib/test/test_tools.py @@ -1,6 +1,8 @@ import pytest from pvlib import tools +import numpy as np +import pandas as pd @pytest.mark.parametrize('keys, input_dict, expected', [ (['a', 'b'], {'a': 1, 'b': 2, 'c': 3}, {'a': 1, 'b': 2}), @@ -11,3 +13,45 @@ def test_build_kwargs(keys, input_dict, expected): kwargs = tools._build_kwargs(keys, input_dict) assert kwargs == expected + + +def test_enforce_numpy_arrays(): + """ Check that when pandas objects are included in the inputs, the + wrapped function receives numpy arrays and the outputs are turned into + pandas series """ + + # Create a test function and decorate it + @tools.enforce_numpy_arrays + def fun_function(a, b, c, d, kwarg_1=None, kwarg_2=None): + assert isinstance(a, np.ndarray) + assert isinstance(b, np.ndarray) + assert isinstance(c, np.ndarray) + assert isinstance(d, str) + assert isinstance(kwarg_1, np.ndarray) + assert isinstance(kwarg_2, np.ndarray) + out_1 = np.array([1, 2]) + out_2 = pd.Series([3, 4]) + out_3 = 5. + return out_1, out_2, out_3 + + # Check with no pandas inputs + a = b = c = np.array([1, 2]) + d = 'string' + kwarg_1 = np.array([1, 2]) + kwarg_2 = np.array([1, 2]) + out_1, out_2, out_3 = fun_function(a, b, c, d, + kwarg_1=kwarg_1, kwarg_2=kwarg_2) + assert isinstance(out_1, np.ndarray) + assert isinstance(out_2, pd.Series) + assert isinstance(out_3, float) + + # Check with some pandas inputs in both args and kwargs + b = pd.Series([1, 2]) + c = pd.DataFrame([1, 2], columns=['e'], index=range(2)) + kwarg_1 = pd.Series([1, 2]) + kwarg_2 = pd.DataFrame([1, 2], columns=['kwarg_2'], index=range(2)) + out_1, out_2, out_3 = fun_function(a, b, c, d, + kwarg_1=kwarg_1, kwarg_2=kwarg_2) + assert isinstance(out_1, pd.Series) + assert isinstance(out_2, pd.Series) + assert isinstance(out_3, float) diff --git a/pvlib/tools.py b/pvlib/tools.py index e0865988e6..f44635ba0e 100644 --- a/pvlib/tools.py +++ b/pvlib/tools.py @@ -440,10 +440,14 @@ def wrapper(*args, **kwargs): new_args = [] for arg in args: - if isinstance(arg, pd.DataFrame) or isinstance(arg, pd.Series): + if isinstance(arg, pd.Series): is_return_type_pandas = True new_arg = arg.values new_args.append(new_arg) + elif isinstance(arg, pd.DataFrame): + is_return_type_pandas = True + new_arg = arg.values.ravel() # make sure that 1D + new_args.append(new_arg) else: new_args.append(arg) new_args = tuple(new_args) @@ -461,7 +465,7 @@ def wrapper(*args, **kwargs): outputs = f(*new_args, **new_kwargs) # If inputs were provided as pandas series or dataframe, convert - # outputs to pandas series if numpy arrays + # outputted numpy arrays to pandas series new_outputs = [] if is_return_type_pandas: for output in outputs: From 81b88873af7018f37954691c1c0cebf0bbec5ed4 Mon Sep 17 00:00:00 2001 From: anomam Date: Mon, 17 Dec 2018 16:20:38 +0900 Subject: [PATCH 13/27] Update docs for API changes and whatsnew file --- docs/sphinx/source/api.rst | 12 ++++++++++++ docs/sphinx/source/whatsnew/v0.6.1.rst | 4 ++++ 2 files changed, 16 insertions(+) diff --git a/docs/sphinx/source/api.rst b/docs/sphinx/source/api.rst index f5352e3605..0ac8aa4fde 100644 --- a/docs/sphinx/source/api.rst +++ b/docs/sphinx/source/api.rst @@ -521,3 +521,15 @@ Functions for power modeling. modelchain.basic_chain modelchain.get_orientation + + +Bifacial +======== + +Methods for calculating back surface irradiance +----------------------------------------------- + +.. autosummary:: + :toctree: generated/ + + bifacial.pvfactors_timeseries diff --git a/docs/sphinx/source/whatsnew/v0.6.1.rst b/docs/sphinx/source/whatsnew/v0.6.1.rst index ec8cc5ba41..e4e34b74f7 100644 --- a/docs/sphinx/source/whatsnew/v0.6.1.rst +++ b/docs/sphinx/source/whatsnew/v0.6.1.rst @@ -35,6 +35,7 @@ API Changes (deprecated) to :py:func:`pvlib.solarposition.sun_rise_set_transit_spa. `sun_rise_set_transit_spa` requires time input to be localized to the specified latitude/longitude. (:issue:`316`) +* Created new bifacial section for `pvfactors` limited implementation (:issue:`421`) Enhancements @@ -60,6 +61,7 @@ Enhancements * Add option for :py:func:`pvlib.irradiance.disc` to use relative airmass by supplying `pressure=None`. (:issue:`449`) * Created :py:func:`pvlib.pvsystem.pvsyst_celltemp` to implement PVsyst's cell temperature model. (:issue:`552`) +* Created :py:func:`pvlib.bifacial.pvfactors_timeseries` to use open-source `pvfactors` package to calculate back surface irradiance (:issue:`421`) Bug fixes @@ -79,6 +81,7 @@ Testing ~~~~~~~ * Add test for :func:`~pvlib.solarposition.hour_angle` (:issue:`597`) * Update tests to be compatible with pytest 4.0. (:issue:`623`) +* Add tests for :py:func:`pvlib.bifacial.pvfactors_timeseries` implementation and :py:func:`pvlib.tools.enforce_numpy_arrays` decorator function (:issue:`421`) Contributors @@ -92,3 +95,4 @@ Contributors * Anton Driesse (:ghuser:`adriesse`) * Cameron Stark (:ghuser:`camerontstark`) * Jonathan Gaffiot (:ghuser:`jgaffiot`) +* Marc Anoma (:ghuser:`anomam`) From 418ca72d31aacf3c56dbd4cf478222677629ff36 Mon Sep 17 00:00:00 2001 From: anomam Date: Mon, 17 Dec 2018 18:11:22 +0900 Subject: [PATCH 14/27] Use better naming --- pvlib/test/test_tools.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pvlib/test/test_tools.py b/pvlib/test/test_tools.py index 7b9c33d463..f6b4a0c215 100644 --- a/pvlib/test/test_tools.py +++ b/pvlib/test/test_tools.py @@ -4,6 +4,7 @@ import numpy as np import pandas as pd + @pytest.mark.parametrize('keys, input_dict, expected', [ (['a', 'b'], {'a': 1, 'b': 2, 'c': 3}, {'a': 1, 'b': 2}), (['a', 'b', 'd'], {'a': 1, 'b': 2, 'c': 3}, {'a': 1, 'b': 2}), @@ -22,7 +23,7 @@ def test_enforce_numpy_arrays(): # Create a test function and decorate it @tools.enforce_numpy_arrays - def fun_function(a, b, c, d, kwarg_1=None, kwarg_2=None): + def foo(a, b, c, d, kwarg_1=None, kwarg_2=None): assert isinstance(a, np.ndarray) assert isinstance(b, np.ndarray) assert isinstance(c, np.ndarray) @@ -39,8 +40,8 @@ def fun_function(a, b, c, d, kwarg_1=None, kwarg_2=None): d = 'string' kwarg_1 = np.array([1, 2]) kwarg_2 = np.array([1, 2]) - out_1, out_2, out_3 = fun_function(a, b, c, d, - kwarg_1=kwarg_1, kwarg_2=kwarg_2) + out_1, out_2, out_3 = foo(a, b, c, d, + kwarg_1=kwarg_1, kwarg_2=kwarg_2) assert isinstance(out_1, np.ndarray) assert isinstance(out_2, pd.Series) assert isinstance(out_3, float) @@ -50,8 +51,8 @@ def fun_function(a, b, c, d, kwarg_1=None, kwarg_2=None): c = pd.DataFrame([1, 2], columns=['e'], index=range(2)) kwarg_1 = pd.Series([1, 2]) kwarg_2 = pd.DataFrame([1, 2], columns=['kwarg_2'], index=range(2)) - out_1, out_2, out_3 = fun_function(a, b, c, d, - kwarg_1=kwarg_1, kwarg_2=kwarg_2) + out_1, out_2, out_3 = foo(a, b, c, d, + kwarg_1=kwarg_1, kwarg_2=kwarg_2) assert isinstance(out_1, pd.Series) assert isinstance(out_2, pd.Series) assert isinstance(out_3, float) From e93c460f2b5051d9fb469bb7a401de1ad0f8cf1b Mon Sep 17 00:00:00 2001 From: anomam Date: Tue, 18 Dec 2018 14:51:50 +0900 Subject: [PATCH 15/27] Remove overkill test requirements for test_pvfactors_timeseries --- pvlib/test/conftest.py | 18 ------------------ pvlib/test/test_bifacial.py | 3 --- 2 files changed, 21 deletions(-) diff --git a/pvlib/test/conftest.py b/pvlib/test/conftest.py index f4de873082..ec8905fd9a 100644 --- a/pvlib/test/conftest.py +++ b/pvlib/test/conftest.py @@ -139,21 +139,3 @@ def has_numba(): requires_pvfactors = pytest.mark.skipif(not has_pvfactors, reason='requires pvfactors') - -try: - import future - has_future = True -except ImportError: - has_future = False - -requires_future = pytest.mark.skipif(not has_future, - reason='requires future') - -try: - import shapely - has_shapely = True -except ImportError: - has_shapely = False - -requires_shapely = pytest.mark.skipif(not has_shapely, - reason='requires shapely') diff --git a/pvlib/test/test_bifacial.py b/pvlib/test/test_bifacial.py index a0da2680cf..ec44850376 100644 --- a/pvlib/test/test_bifacial.py +++ b/pvlib/test/test_bifacial.py @@ -5,9 +5,6 @@ requires_scipy) -@requires_scipy -@requires_shapely -@requires_future @requires_pvfactors def test_pvfactors_timeseries(): """ Test that pvfactors is functional, using the TLDR section inputs of the From ef203f0410715b2e8b50756047cd74fb4e12cf81 Mon Sep 17 00:00:00 2001 From: anomam Date: Tue, 18 Dec 2018 14:59:31 +0900 Subject: [PATCH 16/27] Remove pvfactors version requirement --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index e2ab9101f8..bd61b42c8d 100755 --- a/setup.py +++ b/setup.py @@ -45,7 +45,7 @@ TESTS_REQUIRE = ['pytest', 'pytest-cov', 'pytest-mock', 'nose'] EXTRAS_REQUIRE = { 'optional': ['scipy', 'tables', 'numba', 'siphon', 'netcdf4', - 'ephem', 'cython', 'pvfactors==0.1.5'], + 'ephem', 'cython', 'pvfactors'], 'doc': ['sphinx', 'ipython', 'sphinx_rtd_theme', 'numpydoc', 'matplotlib'], 'test': TESTS_REQUIRE From 7b62e4a314daf1c8d1027726a81f9073a6faea98 Mon Sep 17 00:00:00 2001 From: anomam Date: Tue, 18 Dec 2018 15:09:31 +0900 Subject: [PATCH 17/27] Add pvfactors to ci requirements --- ci/requirements-py27.yml | 1 + ci/requirements-py34.yml | 1 + ci/requirements-py35.yml | 1 + ci/requirements-py36.yml | 1 + ci/requirements-py37.yml | 1 + 5 files changed, 5 insertions(+) diff --git a/ci/requirements-py27.yml b/ci/requirements-py27.yml index 81df9d068c..9edbcbb616 100644 --- a/ci/requirements-py27.yml +++ b/ci/requirements-py27.yml @@ -16,6 +16,7 @@ dependencies: - pytest-cov - pytest-mock - nose + - pvfactors=0.1.5 - pip: - coveralls - pytest-timeout diff --git a/ci/requirements-py34.yml b/ci/requirements-py34.yml index 870ddebd39..f1b47fdd4c 100644 --- a/ci/requirements-py34.yml +++ b/ci/requirements-py34.yml @@ -16,6 +16,7 @@ dependencies: - pytest-cov - pytest-mock - nose + - pvfactors=0.1.5 - pip: - coveralls - pytest-timeout diff --git a/ci/requirements-py35.yml b/ci/requirements-py35.yml index 8f250f1a44..0c6b179934 100644 --- a/ci/requirements-py35.yml +++ b/ci/requirements-py35.yml @@ -16,6 +16,7 @@ dependencies: - pytest-cov - pytest-mock - nose + - pvfactors=0.1.5 - pip: - coveralls - pytest-timeout diff --git a/ci/requirements-py36.yml b/ci/requirements-py36.yml index 31fbdce30c..28be33075c 100644 --- a/ci/requirements-py36.yml +++ b/ci/requirements-py36.yml @@ -16,5 +16,6 @@ dependencies: - pytest-cov - pytest-mock - nose + - pvfactors=0.1.5 - pip: - coveralls diff --git a/ci/requirements-py37.yml b/ci/requirements-py37.yml index 25dac8e804..5c5fb2ab8d 100644 --- a/ci/requirements-py37.yml +++ b/ci/requirements-py37.yml @@ -16,5 +16,6 @@ dependencies: - pytest-cov - pytest-mock - nose + - pvfactors=0.1.5 - pip: - coveralls From 330660a37ca3e0429ecc10a852ec95962ccfff94 Mon Sep 17 00:00:00 2001 From: anomam Date: Tue, 18 Dec 2018 15:17:56 +0900 Subject: [PATCH 18/27] Fix import error --- pvlib/test/test_bifacial.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pvlib/test/test_bifacial.py b/pvlib/test/test_bifacial.py index ec44850376..f1c586efd1 100644 --- a/pvlib/test/test_bifacial.py +++ b/pvlib/test/test_bifacial.py @@ -1,8 +1,7 @@ import numpy as np from datetime import datetime from pvlib.bifacial import pvfactors_timeseries -from conftest import (requires_pvfactors, requires_future, requires_shapely, - requires_scipy) +from conftest import requires_pvfactors @requires_pvfactors From 7cd7cf9ba8a1b3a32de8a8344c472342e2526aad Mon Sep 17 00:00:00 2001 From: anomam Date: Wed, 19 Dec 2018 09:40:01 +0900 Subject: [PATCH 19/27] Silence stickler and add pvfactors to ci as pip install --- ci/requirements-py27.yml | 2 +- ci/requirements-py34.yml | 2 +- ci/requirements-py35.yml | 2 +- ci/requirements-py36.yml | 2 +- ci/requirements-py37.yml | 2 +- pvlib/test/conftest.py | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ci/requirements-py27.yml b/ci/requirements-py27.yml index 9edbcbb616..000c4efbed 100644 --- a/ci/requirements-py27.yml +++ b/ci/requirements-py27.yml @@ -16,7 +16,7 @@ dependencies: - pytest-cov - pytest-mock - nose - - pvfactors=0.1.5 - pip: - coveralls - pytest-timeout + - pvfactors=0.1.5 diff --git a/ci/requirements-py34.yml b/ci/requirements-py34.yml index f1b47fdd4c..aae05970e7 100644 --- a/ci/requirements-py34.yml +++ b/ci/requirements-py34.yml @@ -16,7 +16,7 @@ dependencies: - pytest-cov - pytest-mock - nose - - pvfactors=0.1.5 - pip: - coveralls - pytest-timeout + - pvfactors=0.1.5 diff --git a/ci/requirements-py35.yml b/ci/requirements-py35.yml index 0c6b179934..ca65392524 100644 --- a/ci/requirements-py35.yml +++ b/ci/requirements-py35.yml @@ -16,7 +16,7 @@ dependencies: - pytest-cov - pytest-mock - nose - - pvfactors=0.1.5 - pip: - coveralls - pytest-timeout + - pvfactors=0.1.5 diff --git a/ci/requirements-py36.yml b/ci/requirements-py36.yml index 28be33075c..f655b05847 100644 --- a/ci/requirements-py36.yml +++ b/ci/requirements-py36.yml @@ -16,6 +16,6 @@ dependencies: - pytest-cov - pytest-mock - nose - - pvfactors=0.1.5 - pip: - coveralls + - pvfactors=0.1.5 diff --git a/ci/requirements-py37.yml b/ci/requirements-py37.yml index 5c5fb2ab8d..c81e52b60a 100644 --- a/ci/requirements-py37.yml +++ b/ci/requirements-py37.yml @@ -16,6 +16,6 @@ dependencies: - pytest-cov - pytest-mock - nose - - pvfactors=0.1.5 - pip: - coveralls + - pvfactors=0.1.5 diff --git a/pvlib/test/conftest.py b/pvlib/test/conftest.py index ec8905fd9a..431ea8e46f 100644 --- a/pvlib/test/conftest.py +++ b/pvlib/test/conftest.py @@ -132,7 +132,7 @@ def has_numba(): reason='requires netCDF4') try: - import pvfactors + import pvfactors # noqa: F401 has_pvfactors = True except ImportError: has_pvfactors = False From cff21dda504538528d5df59574c8f46454fd2130 Mon Sep 17 00:00:00 2001 From: anomam Date: Wed, 19 Dec 2018 10:20:16 +0900 Subject: [PATCH 20/27] Fix ci typos + docstrings. And use DatetimeIndex and lists in test --- ci/requirements-py27.yml | 2 +- ci/requirements-py34.yml | 2 +- ci/requirements-py35.yml | 2 +- ci/requirements-py36.yml | 2 +- ci/requirements-py37.yml | 2 +- pvlib/bifacial.py | 2 +- pvlib/test/test_bifacial.py | 17 +++++++++-------- 7 files changed, 15 insertions(+), 14 deletions(-) diff --git a/ci/requirements-py27.yml b/ci/requirements-py27.yml index 000c4efbed..cb77db8ca4 100644 --- a/ci/requirements-py27.yml +++ b/ci/requirements-py27.yml @@ -19,4 +19,4 @@ dependencies: - pip: - coveralls - pytest-timeout - - pvfactors=0.1.5 + - pvfactors==0.1.5 diff --git a/ci/requirements-py34.yml b/ci/requirements-py34.yml index aae05970e7..00a547cbc6 100644 --- a/ci/requirements-py34.yml +++ b/ci/requirements-py34.yml @@ -19,4 +19,4 @@ dependencies: - pip: - coveralls - pytest-timeout - - pvfactors=0.1.5 + - pvfactors==0.1.5 diff --git a/ci/requirements-py35.yml b/ci/requirements-py35.yml index ca65392524..7c4d0ff35f 100644 --- a/ci/requirements-py35.yml +++ b/ci/requirements-py35.yml @@ -19,4 +19,4 @@ dependencies: - pip: - coveralls - pytest-timeout - - pvfactors=0.1.5 + - pvfactors==0.1.5 diff --git a/ci/requirements-py36.yml b/ci/requirements-py36.yml index f655b05847..068e0bd534 100644 --- a/ci/requirements-py36.yml +++ b/ci/requirements-py36.yml @@ -18,4 +18,4 @@ dependencies: - nose - pip: - coveralls - - pvfactors=0.1.5 + - pvfactors==0.1.5 diff --git a/ci/requirements-py37.yml b/ci/requirements-py37.yml index c81e52b60a..11378ba272 100644 --- a/ci/requirements-py37.yml +++ b/ci/requirements-py37.yml @@ -18,4 +18,4 @@ dependencies: - nose - pip: - coveralls - - pvfactors=0.1.5 + - pvfactors==0.1.5 diff --git a/pvlib/bifacial.py b/pvlib/bifacial.py index 7c44a79842..9ca45fbbdd 100644 --- a/pvlib/bifacial.py +++ b/pvlib/bifacial.py @@ -33,7 +33,7 @@ def pvfactors_timeseries( convention (deg) surface_tilt: numeric Tilt angle of the PV modules, going from 0 to 180 (deg) - timestamps: array of :class:datetime.datetime objects + timestamps: datetime or DatetimeIndex List of simulation timestamps dni: numeric Direct normal irradiance (W/m2) diff --git a/pvlib/test/test_bifacial.py b/pvlib/test/test_bifacial.py index f1c586efd1..24829403a3 100644 --- a/pvlib/test/test_bifacial.py +++ b/pvlib/test/test_bifacial.py @@ -1,4 +1,5 @@ import numpy as np +import pandas as pd from datetime import datetime from pvlib.bifacial import pvfactors_timeseries from conftest import requires_pvfactors @@ -10,14 +11,14 @@ def test_pvfactors_timeseries(): package github repo README.md file""" # Create some inputs - timestamps = np.array([datetime(2017, 8, 31, 11), - datetime(2017, 8, 31, 12)]) - solar_zenith = np.array([20., 10.]) - solar_azimuth = np.array([110., 140.]) - surface_tilt = np.array([10., 0.]) - surface_azimuth = np.array([90., 90.]) - dni = np.array([1000., 300.]) - dhi = np.array([50., 500.]) + timestamps = pd.DatetimeIndex([datetime(2017, 8, 31, 11), + datetime(2017, 8, 31, 12)]) + solar_zenith = [20., 10.] + solar_azimuth = [110., 140.] + surface_tilt = [10., 0.] + surface_azimuth = [90., 90.] + dni = [1000., 300.] + dhi = [50., 500.] gcr = 0.4 pvrow_height = 1.75 pvrow_width = 2.44 From 160419a51f30a0e8bbdcb3fcff1529d0dd6fbe98 Mon Sep 17 00:00:00 2001 From: anomam Date: Wed, 19 Dec 2018 10:44:06 +0900 Subject: [PATCH 21/27] pandas>=0.23.3 not available for py34, so removing pvfactors install * Could not find a version that satisfies the requirement pandas>=0.23.3 --- ci/requirements-py34.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/ci/requirements-py34.yml b/ci/requirements-py34.yml index 00a547cbc6..870ddebd39 100644 --- a/ci/requirements-py34.yml +++ b/ci/requirements-py34.yml @@ -19,4 +19,3 @@ dependencies: - pip: - coveralls - pytest-timeout - - pvfactors==0.1.5 From bd5078b0c00c720b7ec415e32e90794eece9c605 Mon Sep 17 00:00:00 2001 From: anomam Date: Wed, 19 Dec 2018 11:26:09 +0900 Subject: [PATCH 22/27] Remove decorator implementation + check for pd series in function * add identical test but using pandas series --- pvlib/bifacial.py | 28 +++++++++++++----- pvlib/test/test_bifacial.py | 58 +++++++++++++++++++++++++++++++++++++ pvlib/test/test_tools.py | 44 ---------------------------- pvlib/tools.py | 55 ----------------------------------- 4 files changed, 78 insertions(+), 107 deletions(-) diff --git a/pvlib/bifacial.py b/pvlib/bifacial.py index 9ca45fbbdd..660bf10292 100644 --- a/pvlib/bifacial.py +++ b/pvlib/bifacial.py @@ -4,10 +4,8 @@ """ import pandas as pd -from pvlib.tools import enforce_numpy_arrays -@enforce_numpy_arrays def pvfactors_timeseries( solar_azimuth, solar_zenith, surface_azimuth, surface_tilt, timestamps, dni, dhi, gcr, pvrow_height, pvrow_width, albedo, @@ -24,20 +22,20 @@ def pvfactors_timeseries( Inputs ------ - solar_azimuth: numeric + solar_azimuth: numeric (list, numpy array, or pandas Series) Sun's azimuth angles using pvlib's azimuth convention (deg) - solar_zenith: numeric + solar_zenith: numeric (list, numpy array, or pandas Series) Sun's zenith angles (deg) - surface_azimuth: numeric + surface_azimuth: numeric (list, numpy array, or pandas Series) Azimuth angle of the front surface of the PV modules, using pvlib's convention (deg) - surface_tilt: numeric + surface_tilt: numeric (list, numpy array, or pandas Series) Tilt angle of the PV modules, going from 0 to 180 (deg) timestamps: datetime or DatetimeIndex List of simulation timestamps - dni: numeric + dni: numeric (list, numpy array, or pandas Series) Direct normal irradiance (W/m2) - dhi: numeric + dhi: numeric (list, numpy array, or pandas Series) Diffuse horizontal irradiance (W/m2) gcr: float Ground coverage ratio of the pv array @@ -86,6 +84,20 @@ def pvfactors_timeseries( Photovoltaic Specialist Conference. 2017. """ + # Convert pandas Series inputs to numpy arrays + if isinstance(solar_azimuth, pd.Series): + solar_azimuth = solar_azimuth.values + if isinstance(solar_zenith, pd.Series): + solar_zenith = solar_zenith.values + if isinstance(surface_azimuth, pd.Series): + surface_azimuth = surface_azimuth.values + if isinstance(surface_tilt, pd.Series): + surface_tilt = surface_tilt.values + if isinstance(dni, pd.Series): + dni = dni.values + if isinstance(dhi, pd.Series): + dhi = dhi.values + # Import pvfactors functions for timeseries calculations. from pvfactors.timeseries import (calculate_radiosities_parallel_perez, calculate_radiosities_serially_perez, diff --git a/pvlib/test/test_bifacial.py b/pvlib/test/test_bifacial.py index 24829403a3..48d2921db8 100644 --- a/pvlib/test/test_bifacial.py +++ b/pvlib/test/test_bifacial.py @@ -61,3 +61,61 @@ def test_pvfactors_timeseries(): atol=0, rtol=tolerance) np.testing.assert_allclose(ipoa_back, expected_ipoa_back, atol=0, rtol=tolerance) + + +@requires_pvfactors +def test_pvfactors_timeseries_pandas_inputs(): + """ Test that pvfactors is functional, using the TLDR section inputs of the + package github repo README.md file, but converted to pandas Series""" + + # Create some inputs + timestamps = pd.DatetimeIndex([datetime(2017, 8, 31, 11), + datetime(2017, 8, 31, 12)]) + solar_zenith = pd.Series([20., 10.]) + solar_azimuth = pd.Series([110., 140.]) + surface_tilt = pd.Series([10., 0.]) + surface_azimuth = pd.Series([90., 90.]) + dni = pd.Series([1000., 300.]) + dhi = pd.Series([50., 500.]) + gcr = 0.4 + pvrow_height = 1.75 + pvrow_width = 2.44 + albedo = 0.2 + n_pvrows = 3 + index_observed_pvrow = 1 + rho_front_pvrow = 0.03 + rho_back_pvrow = 0.05 + horizon_band_angle = 15. + + # Expected values + expected_ipoa_front = [1034.96216923, 795.4423259] + expected_ipoa_back = [92.11871485, 70.39404124] + tolerance = 1e-6 + + # Test serial calculations + ipoa_front, ipoa_back, _ = pvfactors_timeseries( + solar_azimuth, solar_zenith, surface_azimuth, surface_tilt, + timestamps, dni, dhi, gcr, pvrow_height, pvrow_width, albedo, + n_pvrows=n_pvrows, index_observed_pvrow=index_observed_pvrow, + rho_front_pvrow=rho_front_pvrow, rho_back_pvrow=rho_back_pvrow, + horizon_band_angle=horizon_band_angle, + run_parallel_calculations=False, n_workers_for_parallel_calcs=None) + + np.testing.assert_allclose(ipoa_front, expected_ipoa_front, + atol=0, rtol=tolerance) + np.testing.assert_allclose(ipoa_back, expected_ipoa_back, + atol=0, rtol=tolerance) + + # Run calculations in parallel + ipoa_front, ipoa_back, _ = pvfactors_timeseries( + solar_azimuth, solar_zenith, surface_azimuth, surface_tilt, + timestamps, dni, dhi, gcr, pvrow_height, pvrow_width, albedo, + n_pvrows=n_pvrows, index_observed_pvrow=index_observed_pvrow, + rho_front_pvrow=rho_front_pvrow, rho_back_pvrow=rho_back_pvrow, + horizon_band_angle=horizon_band_angle, + run_parallel_calculations=True, n_workers_for_parallel_calcs=None) + + np.testing.assert_allclose(ipoa_front, expected_ipoa_front, + atol=0, rtol=tolerance) + np.testing.assert_allclose(ipoa_back, expected_ipoa_back, + atol=0, rtol=tolerance) diff --git a/pvlib/test/test_tools.py b/pvlib/test/test_tools.py index f6b4a0c215..42eaedca58 100644 --- a/pvlib/test/test_tools.py +++ b/pvlib/test/test_tools.py @@ -1,8 +1,6 @@ import pytest from pvlib import tools -import numpy as np -import pandas as pd @pytest.mark.parametrize('keys, input_dict, expected', [ @@ -14,45 +12,3 @@ def test_build_kwargs(keys, input_dict, expected): kwargs = tools._build_kwargs(keys, input_dict) assert kwargs == expected - - -def test_enforce_numpy_arrays(): - """ Check that when pandas objects are included in the inputs, the - wrapped function receives numpy arrays and the outputs are turned into - pandas series """ - - # Create a test function and decorate it - @tools.enforce_numpy_arrays - def foo(a, b, c, d, kwarg_1=None, kwarg_2=None): - assert isinstance(a, np.ndarray) - assert isinstance(b, np.ndarray) - assert isinstance(c, np.ndarray) - assert isinstance(d, str) - assert isinstance(kwarg_1, np.ndarray) - assert isinstance(kwarg_2, np.ndarray) - out_1 = np.array([1, 2]) - out_2 = pd.Series([3, 4]) - out_3 = 5. - return out_1, out_2, out_3 - - # Check with no pandas inputs - a = b = c = np.array([1, 2]) - d = 'string' - kwarg_1 = np.array([1, 2]) - kwarg_2 = np.array([1, 2]) - out_1, out_2, out_3 = foo(a, b, c, d, - kwarg_1=kwarg_1, kwarg_2=kwarg_2) - assert isinstance(out_1, np.ndarray) - assert isinstance(out_2, pd.Series) - assert isinstance(out_3, float) - - # Check with some pandas inputs in both args and kwargs - b = pd.Series([1, 2]) - c = pd.DataFrame([1, 2], columns=['e'], index=range(2)) - kwarg_1 = pd.Series([1, 2]) - kwarg_2 = pd.DataFrame([1, 2], columns=['kwarg_2'], index=range(2)) - out_1, out_2, out_3 = foo(a, b, c, d, - kwarg_1=kwarg_1, kwarg_2=kwarg_2) - assert isinstance(out_1, pd.Series) - assert isinstance(out_2, pd.Series) - assert isinstance(out_3, float) diff --git a/pvlib/tools.py b/pvlib/tools.py index f44635ba0e..8dfc6c3177 100644 --- a/pvlib/tools.py +++ b/pvlib/tools.py @@ -426,58 +426,3 @@ def _golden_sect_DataFrame(params, VL, VH, func): raise Exception("EXCEPTION:iterations exceeded maximum (50)") return func(df, 'V1'), df['V1'] - - -def enforce_numpy_arrays(f): - """ This decorator function will convert any inputted pandas dataframe or - series to a numpy array, and make sure to convert outtputed numpy arrays - to pandas series if any input was a pandas structure """ - - @wraps(f) - def wrapper(*args, **kwargs): - # Convert all inputs to numpy arrays if pandas series or dataframe - is_return_type_pandas = False - - new_args = [] - for arg in args: - if isinstance(arg, pd.Series): - is_return_type_pandas = True - new_arg = arg.values - new_args.append(new_arg) - elif isinstance(arg, pd.DataFrame): - is_return_type_pandas = True - new_arg = arg.values.ravel() # make sure that 1D - new_args.append(new_arg) - else: - new_args.append(arg) - new_args = tuple(new_args) - - new_kwargs = {} - for key, val in kwargs.items(): - if isinstance(val, pd.DataFrame) or isinstance(val, pd.Series): - is_return_type_pandas = True - new_val = val.values - new_kwargs[key] = new_val - else: - new_kwargs[key] = val - - # Run function - outputs = f(*new_args, **new_kwargs) - - # If inputs were provided as pandas series or dataframe, convert - # outputted numpy arrays to pandas series - new_outputs = [] - if is_return_type_pandas: - for output in outputs: - if isinstance(output, np.ndarray): - new_output = pd.Series(output) - new_outputs.append(new_output) - else: - new_outputs.append(output) - new_outputs = tuple(new_outputs) - else: - new_outputs = outputs - - return new_outputs - - return wrapper From cbc7434cc9d71696144b220a929ddc20b9cbbc30 Mon Sep 17 00:00:00 2001 From: anomam Date: Wed, 19 Dec 2018 11:29:14 +0900 Subject: [PATCH 23/27] Remove unused import --- pvlib/tools.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pvlib/tools.py b/pvlib/tools.py index 8dfc6c3177..fa3d368369 100644 --- a/pvlib/tools.py +++ b/pvlib/tools.py @@ -8,7 +8,6 @@ import numpy as np import pandas as pd import pytz -from functools import wraps def cosd(angle): From 9829b810ebedfc22172e51d499d1b271f766a537 Mon Sep 17 00:00:00 2001 From: anomam Date: Wed, 19 Dec 2018 15:00:12 +0900 Subject: [PATCH 24/27] Simplify and clarify pvfactors function --- pvlib/bifacial.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/pvlib/bifacial.py b/pvlib/bifacial.py index 660bf10292..f78c026ccd 100644 --- a/pvlib/bifacial.py +++ b/pvlib/bifacial.py @@ -73,9 +73,11 @@ def pvfactors_timeseries( Calculated incident irradiance on the back surface of the PV modules (W/m2) df_registries: pandas DataFrame - DataFrame containing all the detailed outputs and elements calculated - for every timestamp of the simulation. Please refer to pvfactors - documentation for more details + DataFrame containing detailed outputs of the simulation; for + instance the shapely geometries, the irradiance components incident on + all surfaces of the PV array (for all timestamps), etc. + In the pvfactors documentation, this is refered to as the "surface + registry". References ---------- @@ -109,11 +111,7 @@ def pvfactors_timeseries( 'n_pvrows': n_pvrows, 'pvrow_height': pvrow_height, 'pvrow_width': pvrow_width, - 'surface_azimuth': surface_azimuth[0], # not necessary - 'surface_tilt': surface_tilt[0], # not necessary 'gcr': gcr, - 'solar_zenith': solar_zenith[0], # not necessary - 'solar_azimuth': solar_azimuth[0], # not necessary 'rho_ground': albedo, 'rho_front_pvrow': rho_front_pvrow, 'rho_back_pvrow': rho_back_pvrow, From 9970179ec78dcc43255182a8b23314932f52edad Mon Sep 17 00:00:00 2001 From: anomam Date: Mon, 21 Jan 2019 18:59:07 +0900 Subject: [PATCH 25/27] Fix docstrings for pvlib consistency + link to pvfactors TLDR --- pvlib/bifacial.py | 12 ++++++------ pvlib/test/test_bifacial.py | 3 ++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/pvlib/bifacial.py b/pvlib/bifacial.py index f78c026ccd..9b51022ef1 100644 --- a/pvlib/bifacial.py +++ b/pvlib/bifacial.py @@ -22,20 +22,20 @@ def pvfactors_timeseries( Inputs ------ - solar_azimuth: numeric (list, numpy array, or pandas Series) + solar_azimuth: numeric Sun's azimuth angles using pvlib's azimuth convention (deg) - solar_zenith: numeric (list, numpy array, or pandas Series) + solar_zenith: numeric Sun's zenith angles (deg) - surface_azimuth: numeric (list, numpy array, or pandas Series) + surface_azimuth: numeric Azimuth angle of the front surface of the PV modules, using pvlib's convention (deg) - surface_tilt: numeric (list, numpy array, or pandas Series) + surface_tilt: numeric Tilt angle of the PV modules, going from 0 to 180 (deg) timestamps: datetime or DatetimeIndex List of simulation timestamps - dni: numeric (list, numpy array, or pandas Series) + dni: numeric Direct normal irradiance (W/m2) - dhi: numeric (list, numpy array, or pandas Series) + dhi: numeric Diffuse horizontal irradiance (W/m2) gcr: float Ground coverage ratio of the pv array diff --git a/pvlib/test/test_bifacial.py b/pvlib/test/test_bifacial.py index 48d2921db8..5416026be8 100644 --- a/pvlib/test/test_bifacial.py +++ b/pvlib/test/test_bifacial.py @@ -8,7 +8,8 @@ @requires_pvfactors def test_pvfactors_timeseries(): """ Test that pvfactors is functional, using the TLDR section inputs of the - package github repo README.md file""" + package github repo README.md file: + https://github.com/SunPower/pvfactors/blob/master/README.md#tldr---quick-start""" # Create some inputs timestamps = pd.DatetimeIndex([datetime(2017, 8, 31, 11), From 78756cdf8959e0717e219c231f2387b4c4c2637b Mon Sep 17 00:00:00 2001 From: anomam Date: Mon, 21 Jan 2019 19:32:26 +0900 Subject: [PATCH 26/27] Always return timestamped series and dataframe and test for that --- pvlib/bifacial.py | 7 ++-- pvlib/test/test_bifacial.py | 64 ++++++++++++++++++++----------------- 2 files changed, 39 insertions(+), 32 deletions(-) diff --git a/pvlib/bifacial.py b/pvlib/bifacial.py index 9b51022ef1..4f63aa0922 100644 --- a/pvlib/bifacial.py +++ b/pvlib/bifacial.py @@ -137,9 +137,12 @@ def pvfactors_timeseries( # Select the calculated outputs from the pvrow to observe ipoa_front = df_outputs.loc[:, idx_slice[index_observed_pvrow, - 'front', 'qinc']].values + 'front', 'qinc']] ipoa_back = df_outputs.loc[:, idx_slice[index_observed_pvrow, - 'back', 'qinc']].values + 'back', 'qinc']] + + # Set timestamps as index of df_registries for consistency of outputs + df_registries = df_registries.set_index('timestamps') return ipoa_front, ipoa_back, df_registries diff --git a/pvlib/test/test_bifacial.py b/pvlib/test/test_bifacial.py index 5416026be8..bb826b937f 100644 --- a/pvlib/test/test_bifacial.py +++ b/pvlib/test/test_bifacial.py @@ -1,4 +1,3 @@ -import numpy as np import pandas as pd from datetime import datetime from pvlib.bifacial import pvfactors_timeseries @@ -13,7 +12,8 @@ def test_pvfactors_timeseries(): # Create some inputs timestamps = pd.DatetimeIndex([datetime(2017, 8, 31, 11), - datetime(2017, 8, 31, 12)]) + datetime(2017, 8, 31, 12)] + ).set_names('timestamps') solar_zenith = [20., 10.] solar_azimuth = [110., 140.] surface_tilt = [10., 0.] @@ -31,12 +31,15 @@ def test_pvfactors_timeseries(): horizon_band_angle = 15. # Expected values - expected_ipoa_front = [1034.96216923, 795.4423259] - expected_ipoa_back = [92.11871485, 70.39404124] - tolerance = 1e-6 + expected_ipoa_front = pd.Series([1034.96216923, 795.4423259], + index=timestamps, + name=(1, 'front', 'qinc')) + expected_ipoa_back = pd.Series([92.11871485, 70.39404124], + index=timestamps, + name=(1, 'back', 'qinc')) # Test serial calculations - ipoa_front, ipoa_back, _ = pvfactors_timeseries( + ipoa_front, ipoa_back, df_registries = pvfactors_timeseries( solar_azimuth, solar_zenith, surface_azimuth, surface_tilt, timestamps, dni, dhi, gcr, pvrow_height, pvrow_width, albedo, n_pvrows=n_pvrows, index_observed_pvrow=index_observed_pvrow, @@ -44,13 +47,12 @@ def test_pvfactors_timeseries(): horizon_band_angle=horizon_band_angle, run_parallel_calculations=False, n_workers_for_parallel_calcs=None) - np.testing.assert_allclose(ipoa_front, expected_ipoa_front, - atol=0, rtol=tolerance) - np.testing.assert_allclose(ipoa_back, expected_ipoa_back, - atol=0, rtol=tolerance) + pd.testing.assert_series_equal(ipoa_front, expected_ipoa_front) + pd.testing.assert_series_equal(ipoa_back, expected_ipoa_back) + pd.testing.assert_index_equal(timestamps, df_registries.index.unique()) # Run calculations in parallel - ipoa_front, ipoa_back, _ = pvfactors_timeseries( + ipoa_front, ipoa_back, df_registries = pvfactors_timeseries( solar_azimuth, solar_zenith, surface_azimuth, surface_tilt, timestamps, dni, dhi, gcr, pvrow_height, pvrow_width, albedo, n_pvrows=n_pvrows, index_observed_pvrow=index_observed_pvrow, @@ -58,20 +60,21 @@ def test_pvfactors_timeseries(): horizon_band_angle=horizon_band_angle, run_parallel_calculations=True, n_workers_for_parallel_calcs=None) - np.testing.assert_allclose(ipoa_front, expected_ipoa_front, - atol=0, rtol=tolerance) - np.testing.assert_allclose(ipoa_back, expected_ipoa_back, - atol=0, rtol=tolerance) + pd.testing.assert_series_equal(ipoa_front, expected_ipoa_front) + pd.testing.assert_series_equal(ipoa_back, expected_ipoa_back) + pd.testing.assert_index_equal(timestamps, df_registries.index.unique()) @requires_pvfactors def test_pvfactors_timeseries_pandas_inputs(): """ Test that pvfactors is functional, using the TLDR section inputs of the - package github repo README.md file, but converted to pandas Series""" + package github repo README.md file, but converted to pandas Series: + https://github.com/SunPower/pvfactors/blob/master/README.md#tldr---quick-start""" # Create some inputs timestamps = pd.DatetimeIndex([datetime(2017, 8, 31, 11), - datetime(2017, 8, 31, 12)]) + datetime(2017, 8, 31, 12)] + ).set_names('timestamps') solar_zenith = pd.Series([20., 10.]) solar_azimuth = pd.Series([110., 140.]) surface_tilt = pd.Series([10., 0.]) @@ -89,12 +92,15 @@ def test_pvfactors_timeseries_pandas_inputs(): horizon_band_angle = 15. # Expected values - expected_ipoa_front = [1034.96216923, 795.4423259] - expected_ipoa_back = [92.11871485, 70.39404124] - tolerance = 1e-6 + expected_ipoa_front = pd.Series([1034.96216923, 795.4423259], + index=timestamps, + name=(1, 'front', 'qinc')) + expected_ipoa_back = pd.Series([92.11871485, 70.39404124], + index=timestamps, + name=(1, 'back', 'qinc')) # Test serial calculations - ipoa_front, ipoa_back, _ = pvfactors_timeseries( + ipoa_front, ipoa_back, df_registries = pvfactors_timeseries( solar_azimuth, solar_zenith, surface_azimuth, surface_tilt, timestamps, dni, dhi, gcr, pvrow_height, pvrow_width, albedo, n_pvrows=n_pvrows, index_observed_pvrow=index_observed_pvrow, @@ -102,13 +108,12 @@ def test_pvfactors_timeseries_pandas_inputs(): horizon_band_angle=horizon_band_angle, run_parallel_calculations=False, n_workers_for_parallel_calcs=None) - np.testing.assert_allclose(ipoa_front, expected_ipoa_front, - atol=0, rtol=tolerance) - np.testing.assert_allclose(ipoa_back, expected_ipoa_back, - atol=0, rtol=tolerance) + pd.testing.assert_series_equal(ipoa_front, expected_ipoa_front) + pd.testing.assert_series_equal(ipoa_back, expected_ipoa_back) + pd.testing.assert_index_equal(timestamps, df_registries.index.unique()) # Run calculations in parallel - ipoa_front, ipoa_back, _ = pvfactors_timeseries( + ipoa_front, ipoa_back, df_registries = pvfactors_timeseries( solar_azimuth, solar_zenith, surface_azimuth, surface_tilt, timestamps, dni, dhi, gcr, pvrow_height, pvrow_width, albedo, n_pvrows=n_pvrows, index_observed_pvrow=index_observed_pvrow, @@ -116,7 +121,6 @@ def test_pvfactors_timeseries_pandas_inputs(): horizon_band_angle=horizon_band_angle, run_parallel_calculations=True, n_workers_for_parallel_calcs=None) - np.testing.assert_allclose(ipoa_front, expected_ipoa_front, - atol=0, rtol=tolerance) - np.testing.assert_allclose(ipoa_back, expected_ipoa_back, - atol=0, rtol=tolerance) + pd.testing.assert_series_equal(ipoa_front, expected_ipoa_front) + pd.testing.assert_series_equal(ipoa_back, expected_ipoa_back) + pd.testing.assert_index_equal(timestamps, df_registries.index.unique()) From 55dd3a6bbe9123cd2b5d4f81f9e25e4cc4e115c4 Mon Sep 17 00:00:00 2001 From: anomam Date: Tue, 22 Jan 2019 10:43:34 +0900 Subject: [PATCH 27/27] Update whatsnew and remove old part --- docs/sphinx/source/whatsnew/v0.6.1.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sphinx/source/whatsnew/v0.6.1.rst b/docs/sphinx/source/whatsnew/v0.6.1.rst index 564d708915..e397456d14 100644 --- a/docs/sphinx/source/whatsnew/v0.6.1.rst +++ b/docs/sphinx/source/whatsnew/v0.6.1.rst @@ -84,7 +84,7 @@ Testing ~~~~~~~ * Add test for :func:`~pvlib.solarposition.hour_angle` (:issue:`597`) * Update tests to be compatible with pytest 4.0. (:issue:`623`) -* Add tests for :py:func:`pvlib.bifacial.pvfactors_timeseries` implementation and :py:func:`pvlib.tools.enforce_numpy_arrays` decorator function (:issue:`421`) +* Add tests for :py:func:`pvlib.bifacial.pvfactors_timeseries` implementation (:issue:`421`) Contributors