/climate.py
Python | 190 lines | 174 code | 0 blank | 16 comment | 0 complexity | 2b809691635eb77df3a9956d0e8c1a04 MD5 | raw file
- '''
- The MIT License (MIT)
- Copyright (c) 2016 Suhas SG
- API
- ---
- ## Climate summaries
- /state?id=
- /district?id=
- /subdistrict?id=
- /village?id=
- {
- "state_code": "...",
- "metric_a": "...",
- "metric_b": "...",
- ...
- }
- ## Time series for a metric
- /state?id=&metric=
- /district?id=&metric=
- /subdistrict?id=&metric=
- /village?id=&metric=
- {
- "state_code": "...",
- "metric": {
- "1984": "...",
- ...
- }
- }
- '''
- import os
- import yaml
- import logging
- import StringIO
- import sqlalchemy
- import pandas as pd
- import json
- from flask import Flask
- from flask import request
- from flask import make_response
- from flask import send_from_directory
- from flask import render_template, jsonify
- from orderedattrdict.yamlutils import AttrDictYAMLLoader
- app = Flask(__name__)
- logging.basicConfig(
- format='%(asctime)s|%(levelname)s|%(message)s',
- level=logging.INFO
- )
- cfg = yaml.load(open('config.yaml'), Loader=AttrDictYAMLLoader)
- def connect():
- '''Returns a connection and a metadata object'''
- con = sqlalchemy.create_engine(cfg.dburl, client_encoding='utf8')
- meta = sqlalchemy.MetaData(bind=con, reflect=True)
- return con, meta
- con, meta = connect()
- lookup = pd.read_csv('lookup_villages.csv')
- @app.route('/')
- def explore():
- return render_template('index.html')
- @app.route('/<level>')
- def metrics(level):
- '''
- Get metrics for the following levels:
- - /state?id=
- - /district?id=
- - /subdistrict?id=
- - /village?id=
- '''
- table, col = cfg.api[level].table, cfg.api[level].col
- # Filter
- table = meta.tables[table]
- claus = table.select().where(table.c[col] == request.args.get('id'))
- # Select
- df = pd.read_sql(claus, con)
- if len(df) == 0:
- return jsonify(**{})
- if 'metric' in request.args:
- res = {
- col: df[col].iloc[0],
- 'data': df[[request.args.get('metric'), 'year']].to_dict(orient='records')
- }
- return jsonify(**res)
- # Clean
- del df['year']
- return jsonify(**df.mean().to_dict())
- def get_data(table, col, val):
- table = meta.tables[table]
- claus = table.select().where(table.c[col] == val)
- df = pd.read_sql(claus, con)
- return df
- @app.route('/lookup')
- def lookitup():
- '''
- Lookup one level with another
- - /lookup?id=&lookup=state&for=district
- - /lookup?id=&lookup=district&for=subdistrict
- - /lookup?id=&lookup=subdistrict&for=village
- # Example: Get all villages of a particular subdistrict
- - /lookup?for=subdistrict&id=345&lookup=village
- '''
- lev = request.args.get('for')
- par = request.args.get('lookup')
- col, val = '%s_code' % lev, request.args.get('id')
- if par == 'village':
- dat = lookup[lookup[col] == int(val)][['%s_code' % par, '%s_name' % par]]
- res = {}
- if len(dat):
- return jsonify(**{
- "village": dat.to_dict(orient='records'),
- lev: int(val)
- })
- dat = lookup[lookup[col] == int(val)]['%s_code' % par]
- res = {}
- if len(dat):
- dat = map(int, dat.unique())
- res = {par: list(dat) if len(dat) > 1 else dat[0], lev: int(val)}
- return jsonify(**res)
- @app.route('/favicon.ico')
- def favicon():
- return send_from_directory(
- os.path.join(app.root_path, 'static'),
- 'favicon.ico', mimetype='image/vnd.microsoft.icon'
- )
- @app.route('/subdistmap')
- def getdistmap():
- with open('static/subdist.json') as distmap:
- distmap = json.load(distmap)
- temp = distmap['objects']['subdist_2011_splitcode']['geometries']
- newgeos = []
- for geo in temp:
- t = geo['properties']['dist_code']
- if t == int(request.args.get('code')):
- newgeos.append(geo)
- distmap['objects']['subdist_2011_splitcode']['geometries'] = newgeos
- return jsonify(**distmap)
- @app.route('/download/<level>')
- def download(level):
- table, col = cfg.api[level].table, cfg.api[level].col
- val = request.args.get('id')
- _df = get_data(table, col, val)
- si = StringIO.StringIO()
- _df.to_csv(si, index=False)
- output = make_response(si.getvalue())
- output.headers["Content-Disposition"] = "attachment; filename=data-{}.csv".format(val)
- output.headers["Content-type"] = "text/csv"
- return output
- if __name__ == '__main__':
- app.run(host='0.0.0.0', port=9500, debug=True)