From 9390ec898ba718e20b3221e3adc62ec24478a386 Mon Sep 17 00:00:00 2001 From: Goutte Date: Wed, 22 Mar 2017 17:17:07 +0100 Subject: [PATCH] Initial experimental time series. --- CHANGELOG.md | 4 ++++ config.yml | 37 +++++++++++++++++++++++++++++++++++++ res/dummy.nc | Bin 0 -> 310092 bytes web/run.py | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ web/view/home.html.jinja2 | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ web/view/layout.html.jinja2 | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 463 insertions(+), 0 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 config.yml create mode 100644 res/dummy.nc create mode 100755 web/run.py create mode 100755 web/view/home.html.jinja2 create mode 100755 web/view/layout.html.jinja2 diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..b6e00af --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,4 @@ +## 0.0.0 + +- Initial website skeleton +- Initial data bridge between netCDF and CSV \ No newline at end of file diff --git a/config.yml b/config.yml new file mode 100644 index 0000000..bd68c1b --- /dev/null +++ b/config.yml @@ -0,0 +1,37 @@ +# WARNING : IF YOU BREAK THIS FILE YOU'LL BREAK THE WEBSITE. Tread carefully. +# Remember, you can test the website locally, see the README. + + +# The HTML metadata in the page header. +# Don't put double quotes (") in any of these fields. +meta: + title: Space Weather + keywords: + - science + - cdpp + - europlanet + - space + - weather + # Will be shown by search engines below the title of the page. + description: Space weather predictions around solar celestial bodies. + + +# A list of authors that will appear in the HTML metadata and possibly in the +# authorship page as well. The order does not matter, it will be shuffled. +authors: + - name: Antoine Goutenoir + role: Software Ninja + mail: antoine.goutenoir@irap.omp.eu + - name: Myriam Bouchemit + role: Server Maintenance + mail: myriam.bouchemit@irap.omp.eu + - name: Mikel Indurain + role: Simulation Software + mail: mindurain@irap.omp.eu + - name: Nicolas André + role: Project Lead + mail: nicolas.andre@irap.omp.eu + - name: Vincent Genot + role: Project Coordinator + mail: vincent.genot@irap.omp.eu + diff --git a/res/dummy.nc b/res/dummy.nc new file mode 100644 index 0000000..7364316 Binary files /dev/null and b/res/dummy.nc differ diff --git a/web/run.py b/web/run.py new file mode 100755 index 0000000..623c66a --- /dev/null +++ b/web/run.py @@ -0,0 +1,202 @@ +import random +import datetime +import StringIO + +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 +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()) +# ) + + +# ROUTING ##################################################################### + +@app.route("/") +@app.route("/home.html") +@app.route("/index.html") +def home(): + return render_view('home.html.jinja2', {}) + + +@app.route("/inspect") +def analyze_cdf(): + cdf_to_inspect = get_path("../res/dummy.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_p = cdf_handle.variables['P_dyn'] + cw.writerow(('time', 'vrad', 'vtan', 'magn', 'pdyn')) + for time, datum_v, datum_b, datum_p in zip(times, data_v, data_b, data_p): + # Day Of Year starts at 0, but for our datetime parser it starts at 1 + doy = '{:03d}'.format(int(''.join(time[4:7])) + 1) + d = datetime.datetime.strptime( + "%s%s%s" % (''.join(time[0:4]), doy, ''.join(time[7:])), + "%Y%j%H%M%S%f" + ) + cw.writerow(( + d.strftime("%Y-%m-%dT%H:%M:%S+00:00"), + datum_v[0], datum_v[1], + datum_b, datum_p + )) + 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) diff --git a/web/view/home.html.jinja2 b/web/view/home.html.jinja2 new file mode 100755 index 0000000..db91dbc --- /dev/null +++ b/web/view/home.html.jinja2 @@ -0,0 +1,136 @@ +{% extends 'layout.html.jinja2' %} +{% set menu_section = 'home' %} +{% block title %}Home{% endblock %} + +{% block content %} + +

Overview

+ + + +

+TODO +

+ +
+ +{% endblock %} + + +{% block styles %} + +{% endblock %} + + +{% block scripts_footer %} + + + +{% endblock %} diff --git a/web/view/layout.html.jinja2 b/web/view/layout.html.jinja2 new file mode 100755 index 0000000..9b74dc3 --- /dev/null +++ b/web/view/layout.html.jinja2 @@ -0,0 +1,84 @@ + + + + + + {% block title %}Welcome{% endblock %} — {{ config.meta.title }} + + + +{% for author in config.authors | shuffle %} + +{% endfor %} + + + + + + +{% block styles %}{% endblock %} + +{# #} +{% block scripts_header %}{% endblock %} + + + + +
+ +
+
+ +

Space Weather v{{ version }}

+ v{{ version }} +
+
+ +
+ + + +
+{% block content %} +

Please override the "content" block in the page template.

+{% endblock %} +
+ +
+ +
+ IRAP OMP © 2017 +
+
+ + + + + +{% block scripts_footer %}{% endblock %} + + + \ No newline at end of file -- libgit2 0.21.2