def nrel_earthsun_distance(time, how='numpy', delta_t=67.0, numthreads=4): """ Calculates the distance from the earth to the sun using the NREL SPA algorithm. The details of the NREL SPA algorithm are described in [1]_. Parameters ---------- time : pandas.DatetimeIndex Must be localized or UTC will be assumed. how : str, optional, default 'numpy' Options are 'numpy' or 'numba'. If numba >= 0.17.0 is installed, how='numba' will compile the spa functions to machine code and run them multithreaded. delta_t : float, optional, default 67.0 If delta_t is None, uses spa.calculate_deltat using time.year and time.month from pandas.DatetimeIndex. For most simulations specifing delta_t is sufficient. Difference between terrestrial time and UT1. *Note: delta_t = None will break code using nrel_numba, this will be fixed in a future version.* By default, use USNO historical data and predictions numthreads : int, optional, default 4 Number of threads to use if how == 'numba'. Returns ------- dist : pd.Series Earth-sun distance in AU. References ---------- .. [1] Reda, I., Andreas, A., 2003. Solar position algorithm for solar radiation applications. Technical report: NREL/TP-560- 34302. Golden, USA, http://www.nrel.gov. """ if not isinstance(time, pd.DatetimeIndex): try: time = pd.DatetimeIndex(time) except (TypeError, ValueError): time = pd.DatetimeIndex([time, ]) unixtime = np.array(time.astype(np.int64)/10**9) spa = _spa_python_import(how) delta_t = delta_t or spa.calculate_deltat(time.year, time.month) dist = spa.earthsun_distance(unixtime, delta_t, numthreads) dist = pd.Series(dist, index=time) return dist
def nrel_earthsun_distance(time, how='numpy', delta_t=67.0, numthreads=4): """ Calculates the distance from the earth to the sun using the NREL SPA algorithm described in [1]. Parameters ---------- time : pd.DatetimeIndex how : str, optional Options are 'numpy' or 'numba'. If numba >= 0.17.0 is installed, how='numba' will compile the spa functions to machine code and run them multithreaded. delta_t : float, optional If delta_t is None, uses spa.calculate_deltat using time.year and time.month from pandas.DatetimeIndex. For most simulations specifing delta_t is sufficient. Difference between terrestrial time and UT1. *Note: delta_t = None will break code using nrel_numba, this will be fixed in a future version. By default, use USNO historical data and predictions numthreads : int, optional Number of threads to use if how == 'numba'. Returns ------- dist : pd.Series Earth-sun distance in AU. References ---------- [1] Reda, I., Andreas, A., 2003. Solar position algorithm for solar radiation applications. Technical report: NREL/TP-560- 34302. Golden, USA, http://www.nrel.gov. """ if not isinstance(time, pd.DatetimeIndex): try: time = pd.DatetimeIndex(time) except (TypeError, ValueError): time = pd.DatetimeIndex([time, ]) unixtime = np.array(time.astype(np.int64)/10**9) spa = _spa_python_import(how) delta_t = delta_t or spa.calculate_deltat(time.year, time.month) dist = spa.earthsun_distance(unixtime, delta_t, numthreads) dist = pd.Series(dist, index=time) return dist
def spa_python(time, latitude, longitude, altitude=0, pressure=101325, temperature=10, delta_t=67.0, atmos_refract=None, numthreads=4, **kwargs): global result lati = latitude longi = longitude elevi = altitude pressure = pressure / 100 atmos_refract = atmos_refract or 0.5667 #calculate the timezone of the given latitude and longitude tz = tzwhere.tzwhere() timezone_str = tz.tzNameAt(lati, longi) timezone_str global timezone timezone = pytz.timezone(timezone_str) #conerting the time into local time based on timezone ltime = time.tz_convert(timezone) #converting the time into unixtime unixtime = np.array(ltime.astype(np.int64) / 10**9) spa = _spa_python_import() delta_t = delta_t or spa.calculate_deltat(ltime.year, ltime.month) #calculate azimuth and zenith app_zenith, zenith, app_elevation, elevation, azimuth, eot = \ spa.solar_position(unixtime, lati, longi, elevi, pressure, temperature, delta_t, atmos_refract, numthreads) result = pd.DataFrame({ 'apparent_zenith': app_zenith, 'zenith': zenith, 'apparent_elevation': app_elevation, 'elevation': elevation, 'azimuth': azimuth, 'equation_of_time': eot }) return result
def test_declination(): times = pd.DatetimeIndex(start="1/1/2015 0:00", end="12/31/2015 23:00", freq="H") atmos_refract = 0.5667 delta_t = spa.calculate_deltat(times.year, times.month) unixtime = np.array([calendar.timegm(t.timetuple()) for t in times]) _, _, declination = spa.solar_position(unixtime, 37.8, -122.25, 100, 1013.25, 25, delta_t, atmos_refract, sst=True) declination = np.deg2rad(declination) declination_rng = declination.max() - declination.min() declination_1 = solarposition.declination_cooper69(times.dayofyear) declination_2 = solarposition.declination_spencer71(times.dayofyear) a, b = declination_1 / declination_rng, declination / declination_rng assert np.allclose(a, b, atol=0.03) # cooper a, b = declination_2 / declination_rng, declination / declination_rng assert np.allclose(a, b, atol=0.02) # spencer
def get_sun_rise_set_transit(time, latitude, longitude, how='numpy', delta_t=67.0, numthreads=4): """ Calculate the sunrise, sunset, and sun transit times using the NREL SPA algorithm described in [1]. If numba is installed, the functions can be compiled to machine code and the function can be multithreaded. Without numba, the function evaluates via numpy with a slight performance hit. Parameters ---------- time : pandas.DatetimeIndex Only the date part is used latitude : float longitude : float delta_t : float, optional If delta_t is None, uses spa.calculate_deltat using time.year and time.month from pandas.DatetimeIndex. For most simulations specifing delta_t is sufficient. Difference between terrestrial time and UT1. *Note: delta_t = None will break code using nrel_numba, this will be fixed in a future version. By default, use USNO historical data and predictions how : str, optional, default 'numpy' Options are 'numpy' or 'numba'. If numba >= 0.17.0 is installed, how='numba' will compile the spa functions to machine code and run them multithreaded. numthreads : int, optional, default 4 Number of threads to use if how == 'numba'. Returns ------- DataFrame The DataFrame will have the following columns: sunrise, sunset, transit References ---------- [1] Reda, I., Andreas, A., 2003. Solar position algorithm for solar radiation applications. Technical report: NREL/TP-560- 34302. Golden, USA, http://www.nrel.gov. """ # Added by Tony Lorenzo (@alorenzo175), University of Arizona, 2015 lat = latitude lon = longitude if not isinstance(time, pd.DatetimeIndex): try: time = pd.DatetimeIndex(time) except (TypeError, ValueError): time = pd.DatetimeIndex([ time, ]) # must convert to midnight UTC on day of interest utcday = pd.DatetimeIndex(time.date).tz_localize('UTC') unixtime = np.array(utcday.astype(np.int64) / 10**9) spa = _spa_python_import(how) delta_t = delta_t or spa.calculate_deltat(time.year, time.month) transit, sunrise, sunset = spa.transit_sunrise_sunset( unixtime, lat, lon, delta_t, numthreads) # arrays are in seconds since epoch format, need to conver to timestamps transit = pd.to_datetime(transit * 1e9, unit='ns', utc=True).tz_convert(time.tz).tolist() sunrise = pd.to_datetime(sunrise * 1e9, unit='ns', utc=True).tz_convert(time.tz).tolist() sunset = pd.to_datetime(sunset * 1e9, unit='ns', utc=True).tz_convert(time.tz).tolist() result = pd.DataFrame( { 'transit': transit, 'sunrise': sunrise, 'sunset': sunset }, index=time) return result
def spa_python(time, latitude, longitude, altitude=0, pressure=101325, temperature=12, delta_t=67.0, atmos_refract=None, how='numpy', numthreads=4, **kwargs): """ Calculate the solar position using a python implementation of the NREL SPA algorithm described in [1]. If numba is installed, the functions can be compiled to machine code and the function can be multithreaded. Without numba, the function evaluates via numpy with a slight performance hit. Parameters ---------- time : pandas.DatetimeIndex Localized or UTC. latitude : float longitude : float altitude : float, default 0 pressure : int or float, optional, default 101325 avg. yearly air pressure in Pascals. temperature : int or float, optional, default 12 avg. yearly air temperature in degrees C. delta_t : float, optional, default 67.0 If delta_t is None, uses spa.calculate_deltat using time.year and time.month from pandas.DatetimeIndex. For most simulations specifing delta_t is sufficient. Difference between terrestrial time and UT1. *Note: delta_t = None will break code using nrel_numba, this will be fixed in a future version.* The USNO has historical and forecasted delta_t [3]. atmos_refrac : None or float, optional, default None The approximate atmospheric refraction (in degrees) at sunrise and sunset. how : str, optional, default 'numpy' Options are 'numpy' or 'numba'. If numba >= 0.17.0 is installed, how='numba' will compile the spa functions to machine code and run them multithreaded. numthreads : int, optional, default 4 Number of threads to use if how == 'numba'. Returns ------- DataFrame The DataFrame will have the following columns: apparent_zenith (degrees), zenith (degrees), apparent_elevation (degrees), elevation (degrees), azimuth (degrees), equation_of_time (minutes). References ---------- [1] I. Reda and A. Andreas, Solar position algorithm for solar radiation applications. Solar Energy, vol. 76, no. 5, pp. 577-589, 2004. [2] I. Reda and A. Andreas, Corrigendum to Solar position algorithm for solar radiation applications. Solar Energy, vol. 81, no. 6, p. 838, 2007. [3] USNO delta T: http://www.usno.navy.mil/USNO/earth-orientation/eo-products/long-term See also -------- pyephem, spa_c, ephemeris """ # Added by Tony Lorenzo (@alorenzo175), University of Arizona, 2015 lat = latitude lon = longitude elev = altitude pressure = pressure / 100 # pressure must be in millibars for calculation atmos_refract = atmos_refract or 0.5667 if not isinstance(time, pd.DatetimeIndex): try: time = pd.DatetimeIndex(time) except (TypeError, ValueError): time = pd.DatetimeIndex([ time, ]) unixtime = np.array(time.astype(np.int64) / 10**9) spa = _spa_python_import(how) delta_t = delta_t or spa.calculate_deltat(time.year, time.month) app_zenith, zenith, app_elevation, elevation, azimuth, eot = \ spa.solar_position(unixtime, lat, lon, elev, pressure, temperature, delta_t, atmos_refract, numthreads) result = pd.DataFrame( { 'apparent_zenith': app_zenith, 'zenith': zenith, 'apparent_elevation': app_elevation, 'elevation': elevation, 'azimuth': azimuth, 'equation_of_time': eot }, index=time) return result
def sun_rise_set_transit_spa(times, latitude, longitude, how='numpy', delta_t=67.0, numthreads=4): """ Calculate the sunrise, sunset, and sun transit times using the NREL SPA algorithm. The details of the NREL SPA algorithm are described in [1]_. If numba is installed, the functions can be compiled to machine code and the function can be multithreaded. Without numba, the function evaluates via numpy with a slight performance hit. Parameters ---------- times : pandas.DatetimeIndex Must be localized to the timezone for ``latitude`` and ``longitude``. latitude : float Latitude in degrees, positive north of equator, negative to south longitude : float Longitude in degrees, positive east of prime meridian, negative to west delta_t : float, optional If delta_t is None, uses spa.calculate_deltat using times.year and times.month from pandas.DatetimeIndex. For most simulations specifing delta_t is sufficient. Difference between terrestrial time and UT1. delta_t = None will break code using nrel_numba, this will be fixed in a future version. By default, use USNO historical data and predictions how : str, optional, default 'numpy' Options are 'numpy' or 'numba'. If numba >= 0.17.0 is installed, how='numba' will compile the spa functions to machine code and run them multithreaded. numthreads : int, optional, default 4 Number of threads to use if how == 'numba'. Returns ------- pandas.DataFrame index is the same as input `times` argument columns are 'sunrise', 'sunset', and 'transit' References ---------- .. [1] Reda, I., Andreas, A., 2003. Solar position algorithm for solar radiation applications. Technical report: NREL/TP-560- 34302. Golden, USA, http://www.nrel.gov. """ # Added by Tony Lorenzo (@alorenzo175), University of Arizona, 2015 lat = latitude lon = longitude # times must be localized if times.tz: tzinfo = times.tz else: raise ValueError('times must be localized') # must convert to midnight UTC on day of interest utcday = pd.DatetimeIndex(times.date).tz_localize('UTC') unixtime = np.array(utcday.astype(np.int64)/10**9) spa = _spa_python_import(how) delta_t = delta_t or spa.calculate_deltat(times.year, times.month) transit, sunrise, sunset = spa.transit_sunrise_sunset( unixtime, lat, lon, delta_t, numthreads) # arrays are in seconds since epoch format, need to conver to timestamps transit = pd.to_datetime(transit*1e9, unit='ns', utc=True).tz_convert( tzinfo).tolist() sunrise = pd.to_datetime(sunrise*1e9, unit='ns', utc=True).tz_convert( tzinfo).tolist() sunset = pd.to_datetime(sunset*1e9, unit='ns', utc=True).tz_convert( tzinfo).tolist() return pd.DataFrame(index=times, data={'sunrise': sunrise, 'sunset': sunset, 'transit': transit})
def get_sun_rise_set_transit(time, latitude, longitude, how='numpy', delta_t=67.0, numthreads=4): """ Calculate the sunrise, sunset, and sun transit times using the NREL SPA algorithm described in [1]. If numba is installed, the functions can be compiled to machine code and the function can be multithreaded. Without numba, the function evaluates via numpy with a slight performance hit. Parameters ---------- time : pandas.DatetimeIndex Only the date part is used latitude : float longitude : float delta_t : float, optional If delta_t is None, uses spa.calculate_deltat using time.year and time.month from pandas.DatetimeIndex. For most simulations specifing delta_t is sufficient. Difference between terrestrial time and UT1. *Note: delta_t = None will break code using nrel_numba, this will be fixed in a future version. By default, use USNO historical data and predictions how : str, optional Options are 'numpy' or 'numba'. If numba >= 0.17.0 is installed, how='numba' will compile the spa functions to machine code and run them multithreaded. numthreads : int, optional Number of threads to use if how == 'numba'. Returns ------- DataFrame The DataFrame will have the following columns: sunrise, sunset, transit References ---------- [1] Reda, I., Andreas, A., 2003. Solar position algorithm for solar radiation applications. Technical report: NREL/TP-560- 34302. Golden, USA, http://www.nrel.gov. """ # Added by Tony Lorenzo (@alorenzo175), University of Arizona, 2015 pvl_logger.debug('Calculating sunrise, set, transit with spa_python code') lat = latitude lon = longitude if not isinstance(time, pd.DatetimeIndex): try: time = pd.DatetimeIndex(time) except (TypeError, ValueError): time = pd.DatetimeIndex([time, ]) # must convert to midnight UTC on day of interest utcday = pd.DatetimeIndex(time.date).tz_localize('UTC') unixtime = np.array(utcday.astype(np.int64)/10**9) spa = _spa_python_import(how) delta_t = delta_t or spa.calculate_deltat(time.year, time.month) transit, sunrise, sunset = spa.transit_sunrise_sunset( unixtime, lat, lon, delta_t, numthreads) # arrays are in seconds since epoch format, need to conver to timestamps transit = pd.to_datetime(transit*1e9, unit='ns', utc=True).tz_convert( time.tz).tolist() sunrise = pd.to_datetime(sunrise*1e9, unit='ns', utc=True).tz_convert( time.tz).tolist() sunset = pd.to_datetime(sunset*1e9, unit='ns', utc=True).tz_convert( time.tz).tolist() result = pd.DataFrame({'transit': transit, 'sunrise': sunrise, 'sunset': sunset}, index=time) return result
def spa_python(time, latitude, longitude, altitude=0, pressure=101325, temperature=12, delta_t=67.0, atmos_refract=None, how='numpy', numthreads=4, **kwargs): """ Calculate the solar position using a python implementation of the NREL SPA algorithm described in [1]. If numba is installed, the functions can be compiled to machine code and the function can be multithreaded. Without numba, the function evaluates via numpy with a slight performance hit. Parameters ---------- time : pandas.DatetimeIndex Localized or UTC. latitude : float longitude : float altitude : float pressure : int or float, optional avg. yearly air pressure in Pascals. temperature : int or float, optional avg. yearly air temperature in degrees C. delta_t : float, optional If delta_t is None, uses spa.calculate_deltat using time.year and time.month from pandas.DatetimeIndex. For most simulations specifing delta_t is sufficient. Difference between terrestrial time and UT1. *Note: delta_t = None will break code using nrel_numba, this will be fixed in a future version. The USNO has historical and forecasted delta_t [3]. atmos_refrac : float, optional The approximate atmospheric refraction (in degrees) at sunrise and sunset. how : str, optional Options are 'numpy' or 'numba'. If numba >= 0.17.0 is installed, how='numba' will compile the spa functions to machine code and run them multithreaded. numthreads : int, optional Number of threads to use if how == 'numba'. Returns ------- DataFrame The DataFrame will have the following columns: apparent_zenith (degrees), zenith (degrees), apparent_elevation (degrees), elevation (degrees), azimuth (degrees), equation_of_time (minutes). References ---------- [1] I. Reda and A. Andreas, Solar position algorithm for solar radiation applications. Solar Energy, vol. 76, no. 5, pp. 577-589, 2004. [2] I. Reda and A. Andreas, Corrigendum to Solar position algorithm for solar radiation applications. Solar Energy, vol. 81, no. 6, p. 838, 2007. [3] USNO delta T: http://www.usno.navy.mil/USNO/earth-orientation/eo-products/long-term See also -------- pyephem, spa_c, ephemeris """ # Added by Tony Lorenzo (@alorenzo175), University of Arizona, 2015 pvl_logger.debug('Calculating solar position with spa_python code') lat = latitude lon = longitude elev = altitude pressure = pressure / 100 # pressure must be in millibars for calculation atmos_refract = atmos_refract or 0.5667 if not isinstance(time, pd.DatetimeIndex): try: time = pd.DatetimeIndex(time) except (TypeError, ValueError): time = pd.DatetimeIndex([time, ]) unixtime = np.array(time.astype(np.int64)/10**9) spa = _spa_python_import(how) delta_t = delta_t or spa.calculate_deltat(time.year, time.month) app_zenith, zenith, app_elevation, elevation, azimuth, eot = \ spa.solar_position(unixtime, lat, lon, elev, pressure, temperature, delta_t, atmos_refract, numthreads) result = pd.DataFrame({'apparent_zenith': app_zenith, 'zenith': zenith, 'apparent_elevation': app_elevation, 'elevation': elevation, 'azimuth': azimuth, 'equation_of_time': eot}, index=time) return result
def sun_rise_set_transit_spa(times, latitude, longitude, how='numpy', delta_t=67.0, numthreads=4): """ Calculate the sunrise, sunset, and sun transit times using the NREL SPA algorithm described in [1]. If numba is installed, the functions can be compiled to machine code and the function can be multithreaded. Without numba, the function evaluates via numpy with a slight performance hit. Parameters ---------- times : pandas.DatetimeIndex Must be localized to the timezone for ``latitude`` and ``longitude``. latitude : float Latitude in degrees, positive north of equator, negative to south longitude : float Longitude in degrees, positive east of prime meridian, negative to west delta_t : float, optional If delta_t is None, uses spa.calculate_deltat using times.year and times.month from pandas.DatetimeIndex. For most simulations specifing delta_t is sufficient. Difference between terrestrial time and UT1. delta_t = None will break code using nrel_numba, this will be fixed in a future version. By default, use USNO historical data and predictions how : str, optional, default 'numpy' Options are 'numpy' or 'numba'. If numba >= 0.17.0 is installed, how='numba' will compile the spa functions to machine code and run them multithreaded. numthreads : int, optional, default 4 Number of threads to use if how == 'numba'. Returns ------- pandas.DataFrame index is the same as input `times` argument columns are 'sunrise', 'sunset', and 'transit' References ---------- [1] Reda, I., Andreas, A., 2003. Solar position algorithm for solar radiation applications. Technical report: NREL/TP-560- 34302. Golden, USA, http://www.nrel.gov. """ # Added by Tony Lorenzo (@alorenzo175), University of Arizona, 2015 lat = latitude lon = longitude # times must be localized if times.tz: tzinfo = times.tz else: raise ValueError('times must be localized') # must convert to midnight UTC on day of interest utcday = pd.DatetimeIndex(times.date).tz_localize('UTC') unixtime = np.array(utcday.astype(np.int64)/10**9) spa = _spa_python_import(how) delta_t = delta_t or spa.calculate_deltat(times.year, times.month) transit, sunrise, sunset = spa.transit_sunrise_sunset( unixtime, lat, lon, delta_t, numthreads) # arrays are in seconds since epoch format, need to conver to timestamps transit = pd.to_datetime(transit*1e9, unit='ns', utc=True).tz_convert( tzinfo).tolist() sunrise = pd.to_datetime(sunrise*1e9, unit='ns', utc=True).tz_convert( tzinfo).tolist() sunset = pd.to_datetime(sunset*1e9, unit='ns', utc=True).tz_convert( tzinfo).tolist() return pd.DataFrame(index=times, data={'sunrise': sunrise, 'sunset': sunset, 'transit': transit})