def _compute_loc_sunset(input_str): geolocator = Nominatim(user_agent='sunset_app', timeout=3) geoloc = geolocator.geocode(input_str) lat, lon = geoloc.latitude, geoloc.longitude loc = api.Topos('{0} N'.format(lat), '{0} E'.format(lon)) t0 = ts.utc(2020, 7, 1) t1 = ts.utc(2021, 7, 1) t, y = almanac.find_discrete(t0, t1, almanac.sunrise_sunset(e, loc)) df = pd.DataFrame({'datetime': t.utc_iso(), 'sun_down': y}) df['datetime'] = pd.to_datetime(df['datetime']) tz = GeoNames(username='******').reverse_timezone( (geoloc.latitude, geoloc.longitude)) try: df['datetime'] = df['datetime'].dt.tz_localize('utc').dt.tz_convert( tz.pytz_timezone) except TypeError: df['datetime'] = df['datetime'].dt.tz_convert(tz.pytz_timezone) df['date'] = df['datetime'].dt.date df['time'] = df['datetime'].dt.time df['hour'] = (df['time'].astype(str).str.split( ':', expand=True).astype(int).apply( lambda row: row[0] + row[1] / 60. + row[2] / 3600., axis=1)) df['hour_24'] = 240 df['daylight'] = np.abs(df['hour'].diff().shift(-1)) return df, geoloc
def get_sun_data(lat, lon, flight_date): sky_fmt = "%Y-%m-%dT%H:%M:%SZ" ts = api.load.timescale() e = api.load('de421.bsp') sunrise = None sunset = None bluffton = api.Topos(lat, lon) # first get sunrise and sunset times t, y = almanac.find_discrete( ts.utc(flight_date.date()), ts.utc(flight_date.date() + datetime.timedelta(days=1)), almanac.sunrise_sunset(e, bluffton)) for ti, yi in zip(t, y): if yi: sunrise = ti.utc_iso() else: sunset = ti.utc_iso() return (datetime.datetime.strptime( sunrise, sky_fmt).replace(tzinfo=datetime.timezone.utc) - datetime.timedelta(minutes=30), datetime.datetime.strptime( sunset, sky_fmt).replace(tzinfo=datetime.timezone.utc) + datetime.timedelta(minutes=30))
def _location_sunlit(self, time, location): """ Returns a function that tells you if the sun is shining at a given time in a given location. """ func = almanac.sunrise_sunset(self.ephemeris, self.target) return func(time)
def get_sunrise_sunset(latitude, longitude, date, timezone): """ :type timezone: datetime.tzinfo :type date: datetime.date :type latitude: float :type longitude: float :return Tuple of datetime (sunrise, sunset), or None instead of a datetime if it doesn't occur that day. """ # TODO: 4 AM is used in the documentation, but does it work everywhere? # https://rhodesmill.org/skyfield/almanac.html#sunrise-and-sunset t0 = ts.utc(date.year, date.month, date.day, 4) t1 = ts.utc(date.year, date.month, date.day + 1, 4) location = api.Topos(latitude_degrees=latitude, longitude=longitude) # The result t will be an array of times, and y will be True if the sun # rises at the corresponding time and False if it sets. times, are_sunrise = almanac.find_discrete( t0, t1, almanac.sunrise_sunset(e, location)) sunrise = None sunset = None for time, is_sunrise in zip(times, are_sunrise): if is_sunrise: # Not expecting multiple sunrises per day. assert sunrise is None sunrise = time.astimezone(timezone) else: # Not expecting multiple sunsets per day. assert sunset is None sunset = time.astimezone(timezone) return sunrise, sunset
def testSunrise(self): timisoaraLoc = api.Topos('45.4758 N', '21.1738 E') t0 = ts.utc(2018, 9, 12, 4) t1 = ts.utc(2018, 9, 13, 4) t, y = almanac.find_discrete(t0, t1, almanac.sunrise_sunset(eph, timisoaraLoc)) print("****************") print(t.utc_iso()) print(y)
def _compute_sun_rise_sun_set(self, start: Time, stop: Time): times, rise_set = find_discrete( start, stop, sunrise_sunset(self.planets, self.topo)) for t in times[rise_set]: cur_date = t.utc_datetime().date() if cur_date not in self.sun_rise_cache.keys(): self.sun_rise_cache[cur_date] = t return times[rise_set], times[~rise_set]
def get_sun(self, start_time, end_time) -> dict: times, is_risen = find_discrete( start_time, end_time, almanac.sunrise_sunset(get_skf_objects(), self.position)) sunrise = times[0] if is_risen[0] else times[1] sunset = times[1] if not is_risen[1] else times[0] return {'rise': sunrise, 'set': sunset}
def test_sunrise_sunset(): ts = api.load.timescale() t0 = ts.utc(2018, 9, 12, 4) t1 = ts.utc(2018, 9, 13, 4) e = api.load('de421.bsp') bluffton = api.Topos('40.8939 N', '83.8917 W') t, y = almanac.find_discrete(t0, t1, almanac.sunrise_sunset(e, bluffton)) strings = t.utc_strftime('%Y-%m-%d %H:%M') assert strings == ['2018-09-12 11:13', '2018-09-12 23:50'] assert (y == (1, 0)).all()
def sunset(self, t, case): t = t.utc t0 = ts.utc(t[0], t[1], t[2], t[3], t[4], t[5]) t1 = ts.utc(t[0], t[1], t[2] + case, t[3], t[4], t[5]) f = almanac.sunrise_sunset(e, self.topo) t, y = almanac.find_discrete(t0, t1, f) for ti, yi in zip(t, y): if(yi == False): return ti else: pass
def test_sunrise_sunset(): ts = api.load.timescale() t0 = ts.utc(2018, 9, 12, 4) t1 = ts.utc(2018, 9, 13, 4) e = api.load('de421.bsp') bluffton = api.Topos('40.8939 N', '83.8917 W') t, y = almanac.find_discrete(t0, t1, almanac.sunrise_sunset(e, bluffton)) t.tt += half_minute strings = t.utc_strftime('%Y-%m-%d %H:%M') assert strings == ['2018-09-12 11:13', '2018-09-12 23:50'] assert (y == (1, 0)).all()
def rise_set_event_times(start, end): """ Computes sunrise and sunset times between start and end. Returns list of EventTime objects. """ t, y = almanac.find_discrete(start, end, almanac.sunrise_sunset(ephemeris, greenwich)) return [ EventTime(Event(rise, 'Sunrise' if rise else 'Sunset'), time) for time, rise in zip(t, y) ]
def sunset_and_rise_for_date(data: AstroData, year: int, month: int, day: int) -> Tuple[Time, Time]: """ For a given date find the time of sunset in Babylon """ t0 = data.timescale.ut1(year, month, day, 12) t1 = data.timescale.tt_jd(t0.tt + 1) times, types = almanac.find_discrete( t0, t1, almanac.sunrise_sunset(data.ephemeris, data.babylon_topos)) assert len(times) == 2 assert types[0] == 0 # 0 = Sunset assert types[1] == 1 # 1 = Sunrise return times[0], times[1]
def sunrise_sunset(): e = api.load('de421.bsp') ts = api.load.timescale() bluffton = api.Topos('65.02 N', '25.47 E') # Oulu coordinates t0 = ts.utc(2019, 3, 1, 0) t1 = ts.utc(2019, 4, 1, 0) t, y = almanac.find_discrete(t0, t1, almanac.sunrise_sunset(e, bluffton)) sunrises = np.array( t.utc_iso()[::2]) # gets every element which index is even sunsets = np.array( t.utc_iso()[1::2]) # gets every element which index is odd # sunrises_sunsets = pd.DataFrame({'sunrises':sunrises, 'sunsets':sunsets}) return sunrises, sunsets
def find_sunrise(n=1): """ Search the almanac for sunrise and sunset times in the next 24 hours. Does not actually compute the times. It looks them up in the precomputed ephemeris files provided by the JPL. Sunrise times are 'True', Sunset times are 'False'. Times are UTC. """ ts = api.load.timescale() ep = api.load('de421.bsp') location = api.Topos('41.85 N', '87.65 W') # Chicago, USA t0 = ts.now() t1 = ts.utc(t0.utc_datetime() + timedelta(days=n)) t, y = almanac.find_discrete(t0, t1, almanac.sunrise_sunset(ep, location)) times = list(zip(t.utc_iso(), y)) print(times)
def _risesetextremes(lat, lon, tzstr, startYear, years, verbose=False): ts = api.load.timescale() load = api.Loader('/var/data') e = load('de430t.bsp') # earth = planets['earth'] tz = timezone(tzstr) bluffton = api.Topos(lat, lon) t0 = ts.utc(startYear, 1, 1) t1 = ts.utc(startYear+years, 1, 1) t, y = almanac.find_discrete(t0, t1, almanac.sunrise_sunset(e, bluffton)) if verbose: print ('done') result = dict() prevrise = None for ti, yi in zip(t, y): dt, _ = ti.astimezone_and_leap_second(tz) if yi: x = 'rise' else: x = 'set' year = str(dt.year) if year not in result.keys(): result[year] = {'rises': [], 'rise_hr': [], 'sets': [], 'set_hr': [], 'sunlight': [] } hrs = dt.hour + dt.minute/60.0 + dt.second/3600.0 result[year][f"{x}s"].append(dt) result[year][f"{x}_hr"].append(hrs) if yi: prevrise = ti else: if prevrise is not None: result[year]['sunlight'].append((ti - prevrise)*24.0) return result
def sun_time(which_one="sunrise"): from skyfield import api, almanac import dateutil.tz load = api.Loader("~/.skyfield", verbose=False) location = config["location"] ts = load.timescale() e = load('de421.bsp') here = api.Topos(location["latitude"], location["longitude"]) now = datetime.datetime.now() today = now.date() local = dateutil.tz.gettz() midnight = datetime.datetime.combine(today, datetime.time(), local) next_midnight = midnight + datetime.timedelta(1) begin = ts.utc(midnight) end = ts.utc(next_midnight) t, _ = almanac.find_discrete(begin, end, almanac.sunrise_sunset(e, here)) idx = 0 if which_one == "sunrise" else 1 return t[idx].astimezone(local)
def next_set_rise(self, day): # By adding 2 days, we can be sure to find today's sunset and the following (tomorrow # morning's) sunrise. # # TODO(MP): Like all other times, the UTC situation here is a bit crappy. We should really # just start searching at noon local time. begin = self.ts.utc(day) end = self.ts.utc(day + timedelta(days=2)) times, ups = almanac.find_discrete( begin, end, almanac.sunrise_sunset(self.ephemeris, self.topos)) times = [t.astimezone(self.timezone) for t in times] # Find the first sunset sunset = next(horizon for horizon in zip(times, ups) if not horizon[1])[0] # Find the first sunrise after the first sunset sunrise = next(horizon for horizon in zip(times, ups) if horizon[1] and horizon[0] > sunset)[0] return (sunset, sunrise)
def sunrise_sunset(lat, lon): place = api.Topos(lat, lon) one_day = timedelta(days=1) start = datetime.today().astimezone().replace(hour=0, minute=0, second=0, microsecond=0) end = start + one_day start = ts.utc(start) end = ts.utc(end) srss, sross = almanac.find_discrete(start, end, almanac.sunrise_sunset(ephem, place)) tz = datetime.now().astimezone().tzinfo (sr, ss) = srss.astimezone(tz) t0_time = sr.strftime('%H%M') t0_srss = "SR" if sross[0] else "SS" t1_time = ss.strftime('%H%M') t1_srss = "SR" if sross[1] else "SS" return f"{t0_srss}{t0_time} {t1_srss}{t1_time}"
def get_sunrise_sunset_times(): pownal = api.Topos('43.921554 N', '70.147969 W') ts = api.load.timescale(builtin=True) eph = api.load_file(settings.SKYFIELD_DATA_PATH) now = datetime.now().astimezone() today_start = datetime(now.year, now.month, now.day).astimezone() today_end = today_start + timedelta(days=1) today_start_ts = ts.utc(today_start) today_end_ts = ts.utc(today_end) traversals, is_sunrise = almanac.find_discrete( today_start_ts, today_end_ts, almanac.sunrise_sunset(eph, pownal)) # If there are multiple sunrises in a day then we have bigger problems than opening the coop door at the right time sunrise_iso = traversals[0].utc_iso( ) if is_sunrise[0] else traversals[1].utc_iso() sunset_iso = traversals[1].utc_iso( ) if not is_sunrise[1] else traversals[0].utc_iso() sunrise_dtm = datetime.strptime( sunrise_iso, '%Y-%m-%dT%H:%M:%SZ').replace(tzinfo=timezone.utc).astimezone() sunset_dtm = datetime.strptime( sunset_iso, '%Y-%m-%dT%H:%M:%SZ').replace(tzinfo=timezone.utc).astimezone() return (sunrise_dtm, sunset_dtm)
def is_light(): """is_light returns True if the sun is up and False otherwise""" # load in data directory to avoid redownloading loader = Loader('~/skyfield_data') ts = loader.timescale() e = loader('de421.bsp') # set current location (melbourne does not appear in the default list) melbourne = api.Topos('37.951910 S', '145.152080 E') # get current time in UTC format now = datetime.datetime.utcnow() now = now.replace(tzinfo=utc) # set the interval for now and 24 hours from now t0 = ts.utc(now) t1 = ts.utc(now + timedelta(hours=24)) # find the times and types of event (sunrise/sunset) t, y = almanac.find_discrete(t0, t1, almanac.sunrise_sunset(e, melbourne)) #y[0] = True for sunrise (which means it is currently dark) light = not y[0] return light
from skyfield.api import load from skyfield import almanac # ['New Moon', 'First Quarter', 'Full Moon', 'Last Quarter'] #print('Load bsp file ...') eph = load('de421.bsp') ts = load.timescale() #Sunrise and Sunset RISE_SET = ['Sunset', 'Sunrise'] from skyfield.api import N, W, wgs84 lat, lon = (48.8796966, 2.5415929) #print('Bluffton using wgs84 :',lat,lon) bluffton = wgs84.latlon(lat, lon) body = 'Sun' #Sunrise and Sunset RISE_SET = ['Sunset', 'Sunrise'] day = 26 month = 1 year = 2021 print('\nSunrise and sunset on', day, 'at', lat, lon) t0 = ts.utc(year, month, day) t1 = ts.utc(year, month, day + 1) t, y = almanac.find_discrete(t0, t1, almanac.sunrise_sunset(eph, bluffton)) for ti, yi in zip(t, y): print(ti.utc_iso(), RISE_SET[yi])
hours = mdates.HourLocator(byhour=range(0, 24, 6), tz=tz_UTC) axes_arr[0].xaxis.set_major_locator(days) axes_arr[0].xaxis.set_major_formatter(days_fmt) axes_arr[0].xaxis.set_minor_locator(hours) xmin = time_plottime[0] xmax = time_plottime[0] + 2. + args.hours / 24. # # Compute sunrise, sunset times across x axis with Skyfield. # tsun is a sequence of times, corresponding values of rise # are True for rising, False for setting. # tmin = ts.utc(time_datetime[0]) tmax = ts.utc(time_datetime[0] + datetime.timedelta(hours=(48. + args.hours))) tsun, rise = almanac.find_discrete(tmin, tmax, almanac.sunrise_sunset(e, site)) tsun_datetime = tsun.utc_datetime() tsun_plottime = mdates.date2num(tsun_datetime) # # Plot vspan rectangles from sunset to sunrise, handling axis # limits. # for axes in axes_arr: if (rise[0] == True): axes.axvspan(xmin, tsun_plottime[0], facecolor=nightcolor, alpha=nightalpha) i = 1 else: i = 0
# if (y_sun == False): # sunset = t_sun conj.append(ti) # print(ti.astimezone(jkt)) # print(ti.astimezone(jkt)) # print('sunset: ', sunset.astimezone(jkt)) else: pass for i in conj: i_utc = i.utc t0 = ts.utc(i_utc[0], i_utc[1], i_utc[2], i_utc[3], i_utc[4], i_utc[5]) t1 = ts.utc(i_utc[0], i_utc[1], i_utc[2] + 1, i_utc[3], i_utc[4], i_utc[5]) t_rs, y_rs = almanac.find_discrete(t0, t1, almanac.sunrise_sunset(e, obsUAD)) for t_sun, y_sun in zip(t_rs, y_rs): if (y_sun == False): sunset.append(t_sun) # sunset = t_sun else: pass for s in sunset: s_utc = s.utc astro_moon = loc.at( ts.utc(s_utc[0], s_utc[1], s_utc[2], s_utc[3], s_utc[4], s_utc[5])).observe(moon) astro_sun = loc.at( ts.utc(s_utc[0], s_utc[1], s_utc[2], s_utc[3], s_utc[4], s_utc[5])).observe(e['sun'])
from skyfield.api import load, Topos from skyfield import almanac from datetime import datetime, timedelta from pytz import timezone jkt = timezone('Asia/Jakarta') ts = load.timescale(builtin=True) e = load('de421.bsp') lat = 7 + (49 / 60) + (59 / 3600) long = 110 + (22 / 60) + (49 / 3600) lat = str(lat) + ' S' long = str(long) + ' E' topos = Topos(lat, long) t0 = ts.utc(2021, 1, 15, -7) t1 = ts.utc(2021, 1, 20, -7) f = almanac.sunrise_sunset(e, topos) t, y = almanac.find_discrete(t0, t1, f) for ti, yi in zip(t, y): print(ti.astimezone(jkt), yi)
def is_sun_visible(latitude=None, longitude=None, date_time=None, dawn_dusk=False): """ Determine if sun is above horizon at for a list of times. Parameters ---------- latitude : int, float Latitude in degrees north positive. Must be a scalar. longitude : int, float Longitude in degrees east positive. Must be a scalar. date_time : datetime.datetime, numpy.array.datetime64, list of datetime.datetime Datetime with timezone, datetime with no timezone in UTC, or numpy.datetime64 format in UTC. Can be a single datetime object or list of datetime objects. dawn_dusk : boolean If set to True, will use skyfields dark_twilight_day function to calculate sun up Returns a list of int's instead of boolean. 0 - Dark of Night 1 - Astronomical Twilight 2 - Nautical Twilight 3 - Civil Twilight 4 - Sun Is Up Returns ------- result : list List matching size of date_time containing True/False if sun is above horizon. """ sf_dates = None # Check if datetime object is scalar and if has no timezone. if isinstance(date_time, datetime): if date_time.tzinfo is None: sf_dates = [date_time.replace(tzinfo=pytz.UTC)] else: sf_dates = [date_time] # Check if datetime objects in list have timezone. If not add. if isinstance(date_time, (list, tuple)) and isinstance(date_time[0], datetime): if isinstance(date_time[0], datetime) and date_time[0].tzinfo is not None: sf_dates = date_time else: sf_dates = [ii.replace(tzinfo=pytz.UTC) for ii in date_time] # Convert datetime64 to datetime with timezone. if type(date_time).__module__ == np.__name__ and np.issubdtype(date_time.dtype, np.datetime64): sf_dates = datetime64_to_datetime(date_time) sf_dates = [ii.replace(tzinfo=pytz.UTC) for ii in sf_dates] if sf_dates is None: raise ValueError('The date_time values entered into is_sun_visible() ' 'do not match input types.') ts = load.timescale() eph = load_file(skyfield_bsp_file) t0 = ts.from_datetimes(sf_dates) location = wgs84.latlon(latitude, longitude) if dawn_dusk: f = almanac.dark_twilight_day(eph, location) else: f = almanac.sunrise_sunset(eph, location) sun_up = f(t0) eph.close() return sun_up
response = requests.get(request_url) parsed_response = json.loads(response.text) raw_offset = parsed_response["rawOffset"] / 3600 dst_offset = parsed_response["dstOffset"] / 3600 tot_offset = raw_offset + dst_offset ts = api.load.timescale(builtin=True) eph = api.load('de421.bsp') earth = eph['earth'] obs_city = api.Topos( str(abs(lat)) + " " + lat_card, str(abs(lon)) + " " + lon_card) t0 = ts.utc(y, m, day, 12 - tot_offset) #>UTC Time t1 = ts.utc(y, m, day + 1, 12 - tot_offset) #>UTC Time t, y = almanac.find_discrete(t0, t1, almanac.sunrise_sunset(eph, obs_city)) adjust = (tot_offset * 60) / 24 / 60 sunset_sunrise = ts.tt_jd(t.tt + adjust) sunset_sunrise = sunset_sunrise.utc_iso() sunset_raw = sunset_sunrise[0] sunrise_raw = sunset_sunrise[1] sunset_hour = int(sunset_raw[11:13] + "00") sunrise_hour = int(sunrise_raw[11:13] + "00") ## IMPORT INITIAL DATA FILE AND CONVERT TO Multi-Indexed DATAFRAME # CREDIT: https://stackoverflow.com/questions/53286882/how-to-reindex-a-multiindex-dataframe df = pd.read_csv("./data/sample_program.csv") df = df.set_index('Object')
from datetime import datetime, timedelta ts = api.load.timescale() ephemeris = api.load('de421.bsp') my_position = api.Topos('34.606 S', '58.419 W') # Only naked-eye visible planets: planets = 'Mercury Venus Mars Jupiter Saturn'.split() # Collect all boolean functions in one list: ras = [ almanac.risings_and_settings(ephemeris, ephemeris[p + '_barycenter'], my_position) for p in planets ] # Append one for checking that the Sun is down: is_sun_down = lambda t: not almanac.sunrise_sunset(ephemeris, my_position)(t) ras.append(is_sun_down) delta = timedelta(hours=1) # days=0.5) t = datetime.now(api.utc) while not all(f(ts.utc(t)) for f in ras): t += delta print(t) # TODO: allow a minimum elevation # TODO: take into account Mercury distance from the Sun, to avoid being dazzled by it.
def sunset_sunrise(time, lat, lon): """ Calculates the local sunrise/sunset of the glider location. The function uses the Skyfield package to calculate the sunrise and sunset times using the date, latitude and longitude. The times are returned rather than day or night indices, as it is more flexible for the quenching correction. Parameters ---------- time: numpy.ndarray or pandas.Series The date & time array in a numpy.datetime64 format. lat: numpy.ndarray or pandas.Series The latitude of the glider position. lon: numpy.ndarray or pandas.Series The longitude of the glider position. Returns ------- sunrise: numpy.ndarray An array of the sunrise times. sunset: numpy.ndarray An array of the sunset times. """ from pandas import DataFrame import datetime import numpy as np import pandas as pd from skyfield import api ts = api.load.timescale() eph = api.load("de421.bsp") from skyfield import almanac df = DataFrame.from_dict(dict([("time", time), ("lat", lat), ("lon", lon)])) # set days as index df = df.set_index(df.time.values.astype("datetime64[D]")) # groupby days and find sunrise for unique days # groupby days and find sunrise/sunset for unique days grp_avg = df.groupby(df.index).mean() date = grp_avg.index.to_pydatetime() date = grp_avg.index time_utc = ts.utc(date.year, date.month, date.day, date.hour) time_utc_offset = ts.utc( date.year, date.month, date.day + 1, date.hour ) # add one day for each unique day to compute sunrise and sunset pairs bluffton = [] for i in range(len(grp_avg.lat)): bluffton.append(api.wgs84.latlon(grp_avg.lat[i], grp_avg.lon[i])) bluffton = np.array(bluffton) sunrise = [] sunset = [] for n in range(len(bluffton)): f = almanac.sunrise_sunset(eph, bluffton[n]) t, y = almanac.find_discrete(time_utc[n], time_utc_offset[n], f) if not t: if f(time_utc[n]): # polar day sunrise.append( pd.Timestamp(date[n].year, date[n].month, date[n].day, 0, 1).to_datetime64()) sunset.append( pd.Timestamp(date[n].year, date[n].month, date[n].day, 23, 59).to_datetime64()) else: # polar night sunrise.append( pd.Timestamp(date[n].year, date[n].month, date[n].day, 11, 59).to_datetime64()) sunset.append( pd.Timestamp(date[n].year, date[n].month, date[n].day, 12, 1).to_datetime64()) else: sr = t[y == 1] # y=1 sunrise sn = t[y == 0] # y=0 sunset sunup = pd.to_datetime(sr.utc_iso()).tz_localize(None) sundown = pd.to_datetime(sn.utc_iso()).tz_localize(None) # this doesnt look very efficient at the moment, but I was having issues with getting the datetime64 # to be compatible with the above code to handle polar day and polar night su = pd.Timestamp( sunup.year[0], sunup.month[0], sunup.day[0], sunup.hour[0], sunup.minute[0], ).to_datetime64() sd = pd.Timestamp( sundown.year[0], sundown.month[0], sundown.day[0], sundown.hour[0], sundown.minute[0], ).to_datetime64() sunrise.append(su) sunset.append(sd) sunrise = np.array(sunrise).squeeze() sunset = np.array(sunset).squeeze() grp_avg["sunrise"] = sunrise grp_avg["sunset"] = sunset # reindex days to original dataframe as night df_reidx = grp_avg.reindex(df.index) sunrise, sunset = df_reidx[["sunrise", "sunset"]].values.T return sunrise, sunset
def get_sunrise_sunset_noon(latitude=None, longitude=None, date=None, library='skyfield', timezone=False): """ Calculate sunrise, sunset and local solar noon times. Parameters ---------- latitude : int, float Latitude in degrees north positive. Must be a scalar. longitude : int, float Longitude in degrees east positive. Must be a scalar. date : (datetime.datetime, numpy.datetime64, list of datetime.datetime, numpy.array of numpy.datetime64, string, list of string) Date(s) to return sunrise, sunset and noon times spaning the first date to last date if more than one provided. May be a scalar or vector. If entered as a string must follow YYYYMMDD format. library : str Library to use for making calculations. Options include ['skyfield'] timezone : boolean Have timezone with datetime. Returns ------- result : tuple of three numpy.array Tuple of three values sunrise, sunset, noon. Values will be a list. If no values can be calculated will return empty list. If the date is within polar night will return empty lists. If spans the transition to polar day will return previous sunrise or next sunset outside of date range provided. """ sunrise, sunset, noon = np.array([]), np.array([]), np.array([]) if library == 'skyfield': ts = load.timescale() eph = load_file(skyfield_bsp_file) sf_dates = [] # Parse datetime object if isinstance(date, datetime): if date.tzinfo is None: sf_dates = [date.replace(tzinfo=pytz.UTC)] else: sf_dates = [date] if isinstance(date, (list, tuple)) and isinstance(date[0], datetime): if date[0].tzinfo is not None: sf_dates = date else: sf_dates = [ii.replace(tzinfo=pytz.UTC) for ii in date] # Parse string date if isinstance(date, str): sf_dates = [datetime.strptime(date, '%Y%m%d').replace(tzinfo=pytz.UTC)] # Parse list of string dates if isinstance(date, (list, tuple)) and isinstance(date[0], str): sf_dates = [datetime.strptime(dt, '%Y%m%d').replace(tzinfo=pytz.UTC) for dt in date] # Convert datetime64 to datetime if type(date).__module__ == np.__name__ and np.issubdtype(date.dtype, np.datetime64): sf_dates = datetime64_to_datetime(date) sf_dates = [ii.replace(tzinfo=pytz.UTC) for ii in sf_dates] # Function for calculating solar noon # Convert location into skyfield location object location = wgs84.latlon(latitude, longitude) # Set up function to indicate calculating locatin of Sun from Earth f = almanac.meridian_transits(eph, eph['Sun'], location) # Set up dates to be start of day and end of day so have a range t0 = sf_dates[0] t0 = t0.replace(hour=0, minute=0, second=0) t1 = sf_dates[-1] t1 = t1.replace(hour=23, minute=59, second=59) # Convert times from datetime to skyfild times t0 = ts.from_datetime(t0) t1 = ts.from_datetime(t1) # Calculate Meridian Transits. n contains times and x contains 1 and 0's # indicating when transit time is above or below location. n, x = almanac.find_discrete(t0, t1, f) # Determine if time is during daylight f = almanac.sunrise_sunset(eph, location) sun_up = f(n) # Filter out times when sun is below location or in polar night n = n[(x == 1) & sun_up] noon = n.utc_datetime() if noon.size == 0: return sunrise, sunset, noon # Calcuate sunrise and sunset times. Calcuate over range 12 less than minimum # noon time and 12 hours greater than maximum noon time. t0 = min(noon) - timedelta(hours=12) t1 = max(noon) + timedelta(hours=12) t0 = ts.from_datetime(t0) t1 = ts.from_datetime(t1) f = almanac.sunrise_sunset(eph, location) t, y = almanac.find_discrete(t0, t1, f) times = t.utc_datetime() sunrise = times[y == 1] sunset = times[y == 0] # Fill in sunrise and sunset if asked to during polar day if len(noon) > 0 and (y.size == 0 or len(sunrise) != len(sunset)): t0 = min(noon) - timedelta(days=90) t1 = max(noon) + timedelta(days=90) t0 = ts.from_datetime(t0) t1 = ts.from_datetime(t1) t, yy = almanac.find_discrete(t0, t1, f) times = t.utc_datetime() # If first time is sunset and/or last time is sunrise filter # from times if yy[0] == 0: yy = yy[1:] times = times[1:] if yy[-1] == 1: yy = yy[:-1] times = times[:-1] # Extract sunrise times temp_sunrise = times[yy == 1] # Extract sunset times temp_sunset = times[yy == 0] # Look for index closest to first noon time to get the time of last sunrise # since we are in polar day. diff = temp_sunrise - min(noon) sunrise_index = np.max(np.where(diff < timedelta(seconds=1))) # Look for index closest to last noon time to get the time of first sunset # since we are in polar day. diff = max(noon) - temp_sunset sunset_index = np.min(np.where(diff < timedelta(seconds=1))) + 1 sunrise = temp_sunrise[sunrise_index: sunset_index] sunset = temp_sunset[sunrise_index: sunset_index] eph.close() if timezone is False: for ii in range(0, sunset.size): sunrise[ii] = sunrise[ii].replace(tzinfo=None) sunset[ii] = sunset[ii].replace(tzinfo=None) for ii in range(0, noon.size): noon[ii] = noon[ii].replace(tzinfo=None) return sunrise, sunset, noon
def _sunsuperlatives(lat, lng, timezone_name, year): eph = load('de430t.bsp') if year is None: year=utcnow.year result = {} observer = api.Topos(lat,lng) localtz = timezone(timezone_name) t0 = ts.utc(year) # midnight Jan 1 t1 = ts.utc(year+1) # midnight Jan 1 following year try: t, y = almanac.find_discrete(t0, t1, almanac.sunrise_sunset(eph, observer)) except Exception as e: pprint(observer) raise ValueError(f"error calculating sunrise_sunset for {observer}: {e}") # build list of 365 rises, sets and day length days=[] risedt=None for ti, yi in zip(t, y): dt = ti.utc_datetime() ldt = dt.astimezone(localtz) key = ldt.strftime("%H:%M:%S") if yi: risedt=dt else: if risedt is not None: #store the datetime of sunrise, sunset, time the Sun is above the horizon, and how close that is to 12 hours #avoid pandas conversion datetime64 and its timezone complexities with iso format days.append({'risedt': risedt.isoformat(), 'riset': risedt.astimezone(localtz).time(), 'setdt': dt.isoformat(), 'sett': dt.astimezone(localtz).time(), 'deltadt': dt.isoformat(), 'deltat': dt-risedt, # time the Sun is above the horizon 'deltafrom12hrsdt': dt.isoformat(), 'deltafrom12hrst': abs(pd.Timedelta('12 hours')-(dt-risedt))}) df = pd.DataFrame(days) for k in ['rise', 'set', 'delta']: # convert ISO8601 datetime string to datetime in specified timezone mintimeiso = df[df[f'{k}t'] == df[f'{k}t'].min()][f'{k}dt'].values[0] maxtimeiso = df[df[f'{k}t'] == df[f'{k}t'].max()][f'{k}dt'].values[0] result[k] = {'min': isodate.parse_datetime(mintimeiso).astimezone(localtz), 'max': isodate.parse_datetime(maxtimeiso).astimezone(localtz)} if k in ['delta']: # convert pandas.timedelta back to datetime.timedelta retaining microsecond resolution mindelta = df[df[f'{k}t'] == df[f'{k}t'].min()][f'{k}t'].values[0] / np.timedelta64(1, 's') maxdelta = df[df[f'{k}t'] == df[f'{k}t'].max()][f'{k}t'].values[0] / np.timedelta64(1, 's') result[k]['value'] = {'min': datetime.timedelta(seconds=float(mindelta)), 'max': datetime.timedelta(seconds=float(maxdelta))} result['equilux'] = {} # There are 2 days with close to 12 hours of daylight, around the equinoxes for i, equaluxdata in df.nsmallest(2, 'deltafrom12hrst').reset_index().iterrows(): daylightlength=equaluxdata['deltat'] / np.timedelta64(1, 's') record = {'dt': isodate.parse_datetime(equaluxdata['deltafrom12hrsdt']).astimezone(localtz), 'value': datetime.timedelta(seconds=float(daylightlength))} if record['dt'].strftime('%m')=='03': result['equilux']['Vernal'] = record elif record['dt'].strftime('%m') == '09': result['equilux']['Autumnal'] = record else: raise ValueError(f'calculated equalux {record["dt"]} outside of March or September') eph.close() return result
def get_dday_sunset_sunrise(sunrise_degree_def=-0.8333): t0 = ts.utc(1944, 6, 5, 12) # start looking for sunset at noon Jun 5 t1 = ts.utc(1944, 6, 6, 12) # stop looking for sunrise at noon Jun 6 t, y = almanac.find_discrete(t0, t1, almanac.sunrise_sunset(e, normandy)) # t, y = almanac.find_discrete(t0, t1, sunrise_sunset(e, normandy, sunrise_degree_def=sunrise_degree_def)) return t[:2]
def is_it_night(data, subset, ts, e): #determines whether it is nighttime at a particular location and time #format latitude and longitude night_time = [] day_time = [] for n in range(0, len(data['LATITUDE'][subset])): if n % 1000 == 0: print('File #', n) #format latitude and longitude if data['LATITUDE'][subset][n] < 0: lat = '%1.2f S' % data['LATITUDE'][subset][n] else: lat = '%1.2f N' % data['LATITUDE'][subset][n] if data['LONGITUDE'][subset][n] < 0: lon = '%1.2f W' % data['LONGITUDE'][subset][n] else: lon = '%1.2f E' % data['LONGITUDE'][subset][n] location = api.Topos(lat, lon) #format time year = pd.to_datetime(data['JULD'].values[subset])[n].year month = pd.to_datetime(data['JULD'].values[subset])[n].month day = pd.to_datetime(data['JULD'].values[subset])[n].day hour = pd.to_datetime(data['JULD'].values[subset])[n].hour minute = pd.to_datetime(data['JULD'].values[subset])[n].minute #define window for searching for either a sunset or sunrise t0, t1 = ts.utc(year, month, day, [hour - 12, hour + 12]) #define UTC time of profile t2 = ts.utc(year, month, day, hour, minute) #t=array of times; y = 0 for sun set, 1 for sun rise: look for a sunset #or sunrise within the window provided t, y = almanac.find_discrete(t0, t1, almanac.sunrise_sunset(e, location)) #print(t.utc_iso()) # print(y) count_polar_night = 0 count_polar_day = 0 #first figure out if sunrise/sunset is irrelevant (i.e. poles at certain #times of year, then determine day/night) if len(t) <= 1: f = almanac.sunrise_sunset(e, location) t, y = almanac.find_discrete(t0, t1, f) if f(t2) == True: day_time.append(n) count_polar_day += 1 else: night_time.append(n) count_polar_night += 1 #if sunrise/sunset exists, figure out whether the profile occurred #before or sunset (sunrise). This depends on whether the t array is #ordered [0,1] or [1,0] and whether t2 (the actual profile time) is #before or after a 0 or 1. else: if t.utc_iso()[0] < t2.utc_iso() < t.utc_iso()[1] and y[0] == 1: day_time.append(n) elif t.utc_iso()[0] < t2.utc_iso() < t.utc_iso()[1] and y[0] == 0: night_time.append(n) elif t2.utc_iso() > t.utc_iso()[1] and y[0] == 0: day_time.append(n) elif t2.utc_iso() > t.utc_iso()[1] and y[0] == 1: night_time.append(n) elif t2.utc_iso() < t.utc_iso()[0] and y[0] == 1: night_time.append(n) else: day_time.append(n) #can ask the program to provide how many profiles occurred during polar #day or night # print(count_polar_day,count_polar_night) #returns lists of indices corresponding to night time and day time for the #original array return night_time, day_time