Skip to content

Instantly share code, notes, and snippets.

@cphyc
Created January 15, 2020 11:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cphyc/9ffd983416c722c66577df63edfaa19b to your computer and use it in GitHub Desktop.
Save cphyc/9ffd983416c722c66577df63edfaa19b to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
import sys
import os
import argparse
from datetime import datetime
try:
import requests
from scipy.interpolate import interp1d
import pandas as pd
import numpy as np
import gnuplotlib as gp
except ModuleNotFoundError as e:
module = str(e).split("'")[1]
print(f'Module {module} is not installed. Install it, e.g. using pip: `pip install {module}`')
sys.exit(1)
MORNING_TIMES = (9, 11.5)
EVENING_TIMES = (17, 19.5)
TRAVEL_TIME = 25 / 60 # 25 minutes
LOCATION = 'Bermondsey'
def find_optimal(hourly, bounds, travel_time):
cor = interp1d(hourly.time.astype(int)/100, hourly.chanceofrain.astype(int), kind='quadratic',
bounds_error=False, fill_value='extrapolate')
dt = 5/60 # 5 minutes
ispace = int(np.round(travel_time / dt))
t = np.arange(bounds[0], bounds[1]+travel_time, dt)
cor_cumsum = np.cumsum(np.abs(cor(t)))
mean = (cor_cumsum[ispace:] - cor_cumsum[:-ispace]) / ispace
imin = np.argmin(mean)
return dict(t_optimal=t[imin], chance_of_rain_optimal=mean[imin],
t_earliest=t[0], chance_of_rain_earliest=mean[0],
t_latest=t[-ispace], chance_of_rain_latest=mean[-1],
t=t[:-ispace], chance_of_rain=mean)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Find optimal time to bike.')
group = parser.add_mutually_exclusive_group()
group.add_argument('--evening', action='store_true',
help='If set, do evening travel.')
group.add_argument('--morning', action='store_true',
help='If set, do morning travel.')
group.add_argument('--auto', action='store_true',
help='Automatically pick morning or evening trip.')
parser.add_argument('--bounds', nargs=2, type=float, default=(-1, -1),
help='Travel time boundaries')
parser.add_argument('--travel-time', type=float, default=TRAVEL_TIME,
help='Travel duration.')
parser.add_argument('--city', type=str, default=LOCATION)
args = parser.parse_args()
data = requests.get(f'https://wttr.in/{args.city}?format=j1').json()
# Get today's hourly weather
hourly = pd.DataFrame(data['weather'][0]['hourly'], dtype='float')
now = datetime.now()
now_hour = now.hour + now.minute / 60
if args.auto:
if now < MORNING_TIMES[1] or now > EVENING_TIMES[1]:
morning = True
else:
morning = False
else:
morning = args.morning
if morning:
bounds = list(MORNING_TIMES)
else:
bounds = list(EVENING_TIMES)
bounds[0] = max(now_hour, bounds[0])
if bounds[0] > bounds[1]:
raise Exception('Lower boundary is later then late boundary, %s > %s!' % (bounds[0], bounds[1]))
# Now finds the optimal time to go
data = find_optimal(hourly, bounds, args.travel_time)
def h_to_hmin(v):
hour = int(v)
minute = int((v-hour)*60)
return hour, minute
def print_info(pre, time, chance_of_rain):
h, m = h_to_hmin(time)
print(f'{pre} {h:02d}:{m:02d}, with {chance_of_rain:.0f}% chance of rain.')
print_info('Best time: ', data['t_optimal'], data['chance_of_rain_optimal'])
print_info('Earliest: ', data['t_earliest'], data['chance_of_rain_earliest'])
print_info('Latest: ', data['t_latest'], data['chance_of_rain_latest'])
rows, columns = (int(_) for _ in os.popen('stty size', 'r').read().split())
xmin, xmax = int(np.floor(bounds[0])), int(np.ceil(bounds[1]))
gp.plot(data['t'], data['chance_of_rain'], _with = 'lines', terminal=f'dumb {columns}, {rows-5}',
_ymin=-5, _ymax=105,
unset=['grid'], set=[f'xtics out nomirror add {xmin},1,{xmax}', 'ytics out nomirror add 0,25,100'],
_xlabel='Departure time', _ylabel='Chance of rain')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment