aboutsummaryrefslogblamecommitdiff
path: root/visualizer/__init__.py
blob: e1cdf734ac9b52e52445a1a44d016c39d44aa8f2 (plain) (tree)
































































































































                                                                                                                                 
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))