📚 The CoCalc Library - books, templates and other resources
License: OTHER
#!/usr/bin/python12"""This file contains code for use with "Think Bayes",3by Allen B. Downey, available from greenteapress.com45Copyright 2013 Allen B. Downey6License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html7"""89import csv10import json11import numpy12import os13import sys14import redis15import urllib21617from datetime import datetime, time1819from time import sleep202122class Redis(object):23"""Provides access to a Redis instance on Redis To Go"""2425host = 'dory.redistogo.com'26port = 105342728def __init__(self):29try:30password = os.environ['REDIS_AUTH']31except KeyError:32print 'Environment variable REDIS_AUTH is not set.'33sys.exit()3435self.r = redis.StrictRedis(host=self.host,36port=self.port,37password=password,38db=0)3940def WriteTrainSpotting(self, timestamp, tripid, seconds, live=True):41"""Writes a trainspotting event to the database.4243timestamp: int seconds since epoch44tripid: string unique id45seconds: int how many seconds away the train is46live: boolean, whether to actually write the data47"""48dt = datetime.fromtimestamp(timestamp)49day = dt.date().isoformat()5051print dt, tripid, seconds, timestamp5253if live:54self.r.sadd('days', day)55self.r.sadd(day, tripid)56self.r.zadd(tripid, seconds, timestamp)5758def FindArrivals(self, start_hour=16, end_hour=18):59"""For each trip, find the best estimate of the arrival time.6061start_hour: int 0-24, beginning of observation window62end_hour: int 0-24, end of window6364Returns: map from string day to unsorted list of arrival datetimes65"""66days = self.r.smembers('days')67print days6869start_time = time(hour=start_hour)70end_time = time(hour=end_hour)7172arrival_map = {}7374for day in days:75tripids = self.r.smembers(day)7677for tripid in tripids:78pred_dt = self.GetPredictedArrival(tripid)79pred_time = pred_dt.time()8081if start_time < pred_time < end_time:82arrival_map.setdefault(day, []).append(pred_dt)8384return arrival_map8586def GetPredictedArrival(self, tripid):87"""Gets the best predicted arrival time for a given trip.8889tripid: string TripID like R98313D8890"""91pair = self.r.zrange(tripid, 0, 1, withscores=True)92timestamp, seconds = pair[0]93pred_ts = float(timestamp) + seconds94pred_dt = datetime.fromtimestamp(pred_ts)95return pred_dt9697class TrainSpotting(object):98"""Represents one observation of a train."""99100def __init__(self, t):101self.timestamp = int(t[0])102self.tripid = t[2]103self.seconds = int(t[6])104105106def ReadCsv(url = 'http://developer.mbta.com/lib/rthr/red.csv'):107"""Reads data from the red line.108109Returns: list of TrainSpotting objects110"""111fp = urllib2.urlopen(url)112reader = csv.reader(fp)113114tss = []115for t in reader:116if t[5] != 'Kendall/MIT': continue117if t[3] != 'Braintree': continue118119ts = TrainSpotting(t)120tss.append(ts)121122fp.close()123return tss124125126def ReadJson():127url = 'http://developer.mbta.com/lib/rthr/red.json'128json_text = urllib2.urlopen(url).read()129json_obj = json.loads(json_text)130print json_obj131132133def ReadAndStore(red):134"""Read data from the MBTA and put it in the database.135136red: Redis object137"""138tss = ReadCsv()139for ts in tss:140red.WriteTrainSpotting(ts.timestamp, ts.tripid, ts.seconds)141142143def Loop(red, start_time, end_time, delay=60):144"""Collects data from start_time until end_time.145146red: Redis object to store data147start_time: datetime148end_time: datetime149delay: time to sleep between collections, in seconds150"""151if datetime.now() < start_time:152diff = start_time - datetime.now()153print 'Sleeping', diff154sleep(diff.total_seconds())155156while datetime.now() < end_time:157print 'Collecting'158ReadAndStore(red)159sleep(delay)160161162def TodayAt(hour):163"""Makes a datetime object with today's date and the given time.164165hour: int 0-24166"""167now = datetime.now()168return datetime.combine(now, time(hour=hour))169170171def GetInterarrivals(arrival_map):172"""Finds all interarrival times in the arrival map.173174arrival_map: map from string day to unsorted list of arrival datetimes175176Returns: list of float interarrival times in seconds177"""178interarrival_seconds = []179for day, arrivals in sorted(arrival_map.iteritems()):180print day, len(arrivals)181arrivals.sort()182diffs = numpy.diff(arrivals)183diffs = [diff.total_seconds() for diff in diffs]184interarrival_seconds.extend(diffs)185186return interarrival_seconds187188189def main(script, command='collect'):190red = Redis()191192if command == 'collect':193start = TodayAt(16)194end = TodayAt(18)195196print start, end197Loop(red, start, end)198199elif command == 'report':200arrival_map = red.FindArrivals()201interarrivals = GetInterarrivals(arrival_map)202print repr(interarrivals)203204205if __name__ == '__main__':206main(*sys.argv)207208209