diff options
Diffstat (limited to 'visualizer/__init__.py')
-rw-r--r-- | visualizer/__init__.py | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/visualizer/__init__.py b/visualizer/__init__.py new file mode 100644 index 0000000..e1cdf73 --- /dev/null +++ b/visualizer/__init__.py @@ -0,0 +1,130 @@ +import os +import json +import getpass +from datetime import datetime +import itertools + +import numpy + +import data + + +class NumpyEncoder(json.JSONEncoder): + def default(self, o): + if type(o).__module__ == numpy.__name__: + return o.item() + super(NumpyEncoder, self).default(o) + + +class EGJ(object): + def save(self, path=getpass.getuser(), append=False): + path = os.path.join(data.path, 'visualizer', path) + if append: + if not os.path.isdir(path): + raise ValueError("Can't append to the given directory") + name = str(1+max(map(int, filter(str.isdigit, os.listdir(path)))+[-1])) + path = os.path.join(path, name) + else: + while os.path.isdir(path): + path = os.path.join(path, '0') + + with open(path, 'w') as f: + self.write(f) + + def write(self, file): + file.write(json.dumps(self.object(), cls=NumpyEncoder)) + + def type(self): + return 'raw' + + def options(self): + return [] + + def object(self): + return { + 'type': self.type(), + 'data': { + 'type': 'FeatureCollection', + 'crs': { + 'type': 'name', + 'properties': { + 'name': 'urn:ogc:def:crs:OGC:1.3:CRS84' + } + }, + 'features': self.features() + } + } + + +class Point(EGJ): + def __init__(self, latitude, longitude, info=None): + self.latitude = latitude + self.longitude = longitude + self.info = info + + def features(self): + d = { + 'type': 'Feature', + 'geometry': { + 'type': 'Point', + 'coordinates': [self.longitude, self.latitude] + } + } + if self.info is not None: + d['properties'] = { 'info': self.info } + return [d] + + +class Path(EGJ): + def __init__(self, path, info=''): + self.path = path + self.info = info + + def features(self): + info = self.info + '''trip_id: %(trip_id)s<br> + call_type: %(call_type_f)s<br> + origin_call: %(origin_call)d<br> + origin_stand: %(origin_stand)d<br> + taxi_id: %(taxi_id)d<br> + timestamp: %(timestamp_f)s<br> + day_type: %(day_type_f)s<br> + missing_data: %(missing_data)d<br>''' \ + % dict(self.path, + call_type_f = ['central', 'stand', 'street'][self.path['call_type']], + timestamp_f = datetime.fromtimestamp(self.path['timestamp']).strftime('%c'), + day_type_f = ['normal', 'holiday', 'holiday eve'][self.path['day_type']]) + + return [{ + 'type': 'Feature', + 'properties': { + 'info': info, + 'display': 'path', + 'timestamp': self.path['timestamp'] + }, + 'geometry': { + 'type': 'LineString', + 'coordinates': [[lon, lat] for (lat, lon) in zip(self.path['latitude'], self.path['longitude'])] + } + }] + + +class Vlist(EGJ, list): + def __init__(self, cluster=False, heatmap=False, *args): + list.__init__(self, *args) + self.cluster = cluster + self.heatmap = heatmap + + def type(self): + if self.cluster or self.heatmap: + if all(isinstance(c, Point) for c in self): + if self.cluster: + return 'cluster' + elif self.heatmap: + return 'heatmap' + else: + raise ValueError('Building a %s with something that is not a Point' % ('cluster' if self.cluster else 'heatmap')) + else: + return 'raw' + + def features(self): + return list(itertools.chain.from_iterable(p.features() for p in self)) |