import random import datetime import StringIO from math import sqrt from os import listdir, environ from os.path import isfile, join, abspath, dirname import csv from pprint import pprint from csv import writer as csv_writer from yaml import load as yaml_load from flask import Flask from flask import redirect, url_for, send_from_directory, abort from flask import request from jinja2 import Environment, FileSystemLoader from netCDF4 import Dataset # from model.Config import Config # from model.News import NewsCollection, News # PATH RELATIVITY ############################################################# THIS_DIRECTORY = dirname(abspath(__file__)) def get_path(relative_path): return abspath(join(THIS_DIRECTORY, relative_path)) # COLLECT GLOBAL INFORMATION FROM SOURCES ##################################### # VERSION with open(get_path('../VERSION'), 'r') as version_file: version = version_file.read().strip() # CONFIG with open(get_path('../config.yml'), 'r') as config_file: config = yaml_load(config_file.read()) # SETUP FLASK ENGINE ########################################################## app = Flask(__name__, root_path=THIS_DIRECTORY) app.debug = environ.get('DEBUG') == 'true' # SETUP JINJA2 TEMPLATE ENGINE ################################################ def static_global(filename): return url_for('static', filename=filename) def shuffle_filter(seq): """ This shuffles the sequence it is applied to. 'tis a failure of jinja2 to not provide a shuffle filter by default. """ try: result = list(seq) random.shuffle(result) return result except: return seq def markdown_filter(value, nl2br=False, p=True): """ nl2br: set to True to replace line breaks with
tags p: set to False to remove the enclosing

tags """ from markdown import markdown from markdown.extensions.nl2br import Nl2BrExtension from markdown.extensions.abbr import AbbrExtension extensions = [AbbrExtension()] if nl2br is True: extensions.append(Nl2BrExtension()) markdowned = markdown(value, output_format='html5', extensions=extensions) if p is False: markdowned = markdowned.replace(r"

", "").replace(r"

", "") return markdowned tpl_engine = Environment(loader=FileSystemLoader([get_path('view')]), trim_blocks=True, lstrip_blocks=True) tpl_engine.globals.update( url_for=url_for, static=static_global, ) tpl_engine.filters['markdown'] = markdown_filter tpl_engine.filters['md'] = markdown_filter tpl_engine.filters['shuffle'] = shuffle_filter tpl_global_vars = { 'request': request, 'version': version, 'config': config, 'now': datetime.datetime.now(), } # HELPERS ##################################################################### def render_view(view, context=None): """ A simple helper to render [view] template with [context] vars. It automatically adds the global template vars defined above, too. It returns a string, usually the HTML contents to display. """ context = {} if context is None else context return tpl_engine.get_template(view).render( dict(tpl_global_vars.items() + context.items()) ) # def render_page(page, title="My Page", context=None): # """ # A simple helper to render the md_page.html template with [context] vars & # the additional contents of `page/[page].md` in the `md_page` variable. # It automagically adds the global template vars defined above, too. # It returns a string, usually the HTML contents to display. # """ # if context is None: # context = {} # context['title'] = title # context['md_page'] = '' # with file(get_path('page/%s.md' % page)) as f: # context['md_page'] = f.read() # return tpl_engine.get_template('md_page.html').render( # dict(tpl_global_vars.items() + context.items()) # ) def datetime_from_list(time_list): # Day Of Year starts at 0, but for our datetime parser it starts at 1 doy = '{:03d}'.format(int(''.join(time_list[4:7])) + 1) return datetime.datetime.strptime( "%s%s%s" % (''.join(time_list[0:4]), doy, ''.join(time_list[7:])), "%Y%j%H%M%S%f" ) # ROUTING ##################################################################### @app.route('/favicon.ico') def favicon(): return send_from_directory( join(app.root_path, 'static', 'img'), 'favicon.ico', mimetype='image/vnd.microsoft.icon' ) @app.route("/") @app.route("/home.html") @app.route("/index.html") def home(): return render_view('home.html.jinja2', { 'sources': config['sources'], 'planets': [s for s in config['sources'] if s['type'] == 'planet'], 'probes': [s for s in config['sources'] if s['type'] == 'probe'], 'comets': [s for s in config['sources'] if s['type'] == 'comet'], }) @app.route("/inspect") def analyze_cdf(): cdf_to_inspect = get_path("../res/dummy.nc") cdf_to_inspect = get_path("../res/dummy_jupiter_coordinates.nc") si = StringIO.StringIO() cw = csv.DictWriter(si, fieldnames=['Name', 'Shape', 'Length']) cw.writeheader() # Time, StartTime, StopTime, V, B, N, T, Delta_angle, P_dyn, QualityFlag cdf_handle = Dataset(cdf_to_inspect, "r", format="NETCDF4") for variable in cdf_handle.variables: v = cdf_handle.variables[variable] cw.writerow({ 'Name': variable, 'Shape': v.shape, 'Length': v.size, }) cdf_handle.close() return si.getvalue() @app.route("/test.csv") def get_csv(): si = StringIO.StringIO() cw = csv_writer(si) # Time, StartTime, StopTime, V, B, N, T, Delta_angle, P_dyn, QualityFlag cdf_handle = Dataset(get_path("../res/dummy.nc"), "r", format="NETCDF4") # YYYY DOY HH MM SS .ms times = cdf_handle.variables['Time'] data_v = cdf_handle.variables['V'] data_b = cdf_handle.variables['B'] data_t = cdf_handle.variables['T'] data_n = cdf_handle.variables['N'] data_p = cdf_handle.variables['P_dyn'] data_a = cdf_handle.variables['Delta_angle'] cw.writerow(( 'time', 'vrad', 'vtan', 'vlen', 'magn', 'temp', 'pdyn', 'dens', 'angl' )) for time, datum_v, datum_b, datum_t, datum_p, datum_n, datum_a in \ zip(times, data_v, data_b, data_t, data_n, data_p, data_a): vrad = datum_v[0] vtan = datum_v[1] cw.writerow(( datetime_from_list(time).strftime("%Y-%m-%dT%H:%M:%S+00:00"), vrad, vtan, sqrt(vrad * vrad + vtan * vtan), datum_b, datum_t, datum_n, datum_p, datum_a )) cdf_handle.close() return si.getvalue() @app.route("/_data.csv") def get_orbiter_csv(orbiter): # http://cdpp1.cesr.fr/BASE/DDService/getDataUrl.php?dataSet=tao_ros_sw&StartTime=2014-02-23T10:00&StopTime=2016-02-24T23:59 # Process input parameters if orbiter not in config['models']: abort(400, "Invalid orbiter '%s'." % orbiter) date_fmt = "%Y-%m-%dT%H:%M:%S" started_at = request.args.get('started_at') try: started_at = datetime.datetime.strptime(started_at, date_fmt) except: abort(400, "Invalid started_at parameter : '%s'." % started_at) stopped_at = request.args.get('stopped_at') try: stopped_at = datetime.datetime.strptime(stopped_at, date_fmt) except: abort(400, "Invalid stopped_at parameter : '%s'." % stopped_at) # Grab the list of netCDF files from Myriam's API todo # si = StringIO.StringIO() cw = csv_writer(si) # Time, StartTime, StopTime, V, B, N, T, Delta_angle, P_dyn, QualityFlag cdf_handle = Dataset(get_path("../res/dummy.nc"), "r", format="NETCDF4") # YYYY DOY HH MM SS .ms times = cdf_handle.variables['Time'] data_v = cdf_handle.variables['V'] data_b = cdf_handle.variables['B'] data_p = cdf_handle.variables['P_dyn'] cw.writerow(( 'time', 'vrad', 'vtan', 'vlen', 'magn', 'pdyn' )) for time, datum_v, datum_b, datum_p in zip(times, data_v, data_b, data_p): vrad = datum_v[0] vtan = datum_v[1] cw.writerow(( datetime_from_list(time).strftime("%Y-%m-%dT%H:%M:%S+00:00"), vrad, vtan, sqrt(vrad * vrad + vtan * vtan), datum_b, datum_p )) cdf_handle.close() return si.getvalue() @app.route("/astral_coordinates.csv") def get_astral_coordinates_csv(): si = StringIO.StringIO() cw = csv_writer(si) # Time, StartTime, StopTime, XYZ_HCI, XYZ_IAU_SUN, XYZ_HEE cdf_handle = Dataset(get_path("../res/dummy_jupiter_coordinates.nc"), "r", format="NETCDF4") times = cdf_handle.variables['Time'] data_xyz_hci = cdf_handle.variables['XYZ_HCI'] cw.writerow(('time', 'x_hci', 'y_hci')) for time, datum_xyz_hci in zip(times, data_xyz_hci): cw.writerow(( datetime_from_list(time).strftime("%Y-%m-%dT%H:%M:%S+00:00"), datum_xyz_hci[0], datum_xyz_hci[1] )) cdf_handle.close() return si.getvalue() # MAIN ######################################################################## if __name__ == "__main__": # Debug mode on, as the production server does not use this. extra_files = [get_path('../config.yml')] app.run(debug=True, extra_files=extra_files)