PageRenderTime 24ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/climate.py

https://gitlab.com/jargnar/climate-portal
Python | 190 lines | 174 code | 0 blank | 16 comment | 0 complexity | 2b809691635eb77df3a9956d0e8c1a04 MD5 | raw file
  1. '''
  2. The MIT License (MIT)
  3. Copyright (c) 2016 Suhas SG
  4. API
  5. ---
  6. ## Climate summaries
  7. /state?id=
  8. /district?id=
  9. /subdistrict?id=
  10. /village?id=
  11. {
  12. "state_code": "...",
  13. "metric_a": "...",
  14. "metric_b": "...",
  15. ...
  16. }
  17. ## Time series for a metric
  18. /state?id=&metric=
  19. /district?id=&metric=
  20. /subdistrict?id=&metric=
  21. /village?id=&metric=
  22. {
  23. "state_code": "...",
  24. "metric": {
  25. "1984": "...",
  26. ...
  27. }
  28. }
  29. '''
  30. import os
  31. import yaml
  32. import logging
  33. import StringIO
  34. import sqlalchemy
  35. import pandas as pd
  36. import json
  37. from flask import Flask
  38. from flask import request
  39. from flask import make_response
  40. from flask import send_from_directory
  41. from flask import render_template, jsonify
  42. from orderedattrdict.yamlutils import AttrDictYAMLLoader
  43. app = Flask(__name__)
  44. logging.basicConfig(
  45. format='%(asctime)s|%(levelname)s|%(message)s',
  46. level=logging.INFO
  47. )
  48. cfg = yaml.load(open('config.yaml'), Loader=AttrDictYAMLLoader)
  49. def connect():
  50. '''Returns a connection and a metadata object'''
  51. con = sqlalchemy.create_engine(cfg.dburl, client_encoding='utf8')
  52. meta = sqlalchemy.MetaData(bind=con, reflect=True)
  53. return con, meta
  54. con, meta = connect()
  55. lookup = pd.read_csv('lookup_villages.csv')
  56. @app.route('/')
  57. def explore():
  58. return render_template('index.html')
  59. @app.route('/<level>')
  60. def metrics(level):
  61. '''
  62. Get metrics for the following levels:
  63. - /state?id=
  64. - /district?id=
  65. - /subdistrict?id=
  66. - /village?id=
  67. '''
  68. table, col = cfg.api[level].table, cfg.api[level].col
  69. # Filter
  70. table = meta.tables[table]
  71. claus = table.select().where(table.c[col] == request.args.get('id'))
  72. # Select
  73. df = pd.read_sql(claus, con)
  74. if len(df) == 0:
  75. return jsonify(**{})
  76. if 'metric' in request.args:
  77. res = {
  78. col: df[col].iloc[0],
  79. 'data': df[[request.args.get('metric'), 'year']].to_dict(orient='records')
  80. }
  81. return jsonify(**res)
  82. # Clean
  83. del df['year']
  84. return jsonify(**df.mean().to_dict())
  85. def get_data(table, col, val):
  86. table = meta.tables[table]
  87. claus = table.select().where(table.c[col] == val)
  88. df = pd.read_sql(claus, con)
  89. return df
  90. @app.route('/lookup')
  91. def lookitup():
  92. '''
  93. Lookup one level with another
  94. - /lookup?id=&lookup=state&for=district
  95. - /lookup?id=&lookup=district&for=subdistrict
  96. - /lookup?id=&lookup=subdistrict&for=village
  97. # Example: Get all villages of a particular subdistrict
  98. - /lookup?for=subdistrict&id=345&lookup=village
  99. '''
  100. lev = request.args.get('for')
  101. par = request.args.get('lookup')
  102. col, val = '%s_code' % lev, request.args.get('id')
  103. if par == 'village':
  104. dat = lookup[lookup[col] == int(val)][['%s_code' % par, '%s_name' % par]]
  105. res = {}
  106. if len(dat):
  107. return jsonify(**{
  108. "village": dat.to_dict(orient='records'),
  109. lev: int(val)
  110. })
  111. dat = lookup[lookup[col] == int(val)]['%s_code' % par]
  112. res = {}
  113. if len(dat):
  114. dat = map(int, dat.unique())
  115. res = {par: list(dat) if len(dat) > 1 else dat[0], lev: int(val)}
  116. return jsonify(**res)
  117. @app.route('/favicon.ico')
  118. def favicon():
  119. return send_from_directory(
  120. os.path.join(app.root_path, 'static'),
  121. 'favicon.ico', mimetype='image/vnd.microsoft.icon'
  122. )
  123. @app.route('/subdistmap')
  124. def getdistmap():
  125. with open('static/subdist.json') as distmap:
  126. distmap = json.load(distmap)
  127. temp = distmap['objects']['subdist_2011_splitcode']['geometries']
  128. newgeos = []
  129. for geo in temp:
  130. t = geo['properties']['dist_code']
  131. if t == int(request.args.get('code')):
  132. newgeos.append(geo)
  133. distmap['objects']['subdist_2011_splitcode']['geometries'] = newgeos
  134. return jsonify(**distmap)
  135. @app.route('/download/<level>')
  136. def download(level):
  137. table, col = cfg.api[level].table, cfg.api[level].col
  138. val = request.args.get('id')
  139. _df = get_data(table, col, val)
  140. si = StringIO.StringIO()
  141. _df.to_csv(si, index=False)
  142. output = make_response(si.getvalue())
  143. output.headers["Content-Disposition"] = "attachment; filename=data-{}.csv".format(val)
  144. output.headers["Content-type"] = "text/csv"
  145. return output
  146. if __name__ == '__main__':
  147. app.run(host='0.0.0.0', port=9500, debug=True)