diff --git a/CHANGELOG.md b/CHANGELOG.md index f0d4484..5eb2f44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,11 @@ +## TO DO + +- Add source name on time series - Start/Stop datetime fields - Play button to start time dimension -- Download raw data for time interval +- Download raw data (as CSV) for time interval - Same via SAMP -- Planets -- Probes - - Rosetta - - Juno -- Comets (the one visited by rosetta) - ## 0.0.0 - Initial website skeleton @@ -18,5 +15,10 @@ - Density `N` (cm^-3) - Angle Planet-Sun-Earth `Delta_angle` (degrees) - Magnetism => B Tangential +- Planets +- Probes + - Rosetta + - Juno +- Comets (the one visited by rosetta) - Orbits axes titles - Logo Europlanet diff --git a/web/run.py b/web/run.py index 96e3306..c2f47e9 100755 --- a/web/run.py +++ b/web/run.py @@ -10,6 +10,7 @@ import csv import json import gzip import urllib +import logging from pprint import pprint from csv import writer as csv_writer from yaml import load as yaml_load @@ -19,9 +20,6 @@ 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 ############################################################# @@ -43,6 +41,13 @@ with open(get_path('../config.yml'), 'r') as config_file: config = yaml_load(config_file.read()) +# LOGGING ##################################################################### + +log = logging.getLogger("HelioPropa") +log.setLevel(logging.INFO) +log.addHandler(logging.FileHandler(get_path('run.log'))) + + # SETUP FLASK ENGINE ########################################################## app = Flask(__name__, root_path=THIS_DIRECTORY) @@ -249,12 +254,11 @@ def analyze_cdf(): return si.getvalue() -@app.route("/_data.csv") -def get_orbiter_csv(orbiter): +@app.route("//data.csv") +def get_orbiter_csv(source): # 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) + source_config = get_source_config(source) date_fmt = "%Y-%m-%dT%H:%M:%S" started_at = request.args.get('started_at') try: @@ -267,19 +271,17 @@ def get_orbiter_csv(orbiter): except: abort(400, "Invalid stopped_at parameter : '%s'." % stopped_at) - - source_config = get_source_config(orbiter) # todo: iterate on models when there are many try: model_slug = source_config['models'][0]['slug'] except: - abort(500, "Invalid model configuration for '%s'." % orbiter) + abort(500, "Invalid model configuration for '%s'." % source) # Grab the list of netCDF files from Myriam's API # http://cdpp.irap.omp.eu/BASE/DDService/getDataUrl.php?dataSet=jupiter_orb_all&StartTime=2014-02-23T10:00:10&StopTime=2017-02-24T23:59:00 # http://cdpp.irap.omp.eu/BASE/DATA/TAO/JUPITER/SW/sw_2014.nc.gz - model_files = retrieve_data(orbiter, model_slug, started_at, stopped_at) - orbits_files = retrieve_data(orbiter, source_config['orbit'], started_at, stopped_at) + model_files = retrieve_data(source, model_slug, started_at, stopped_at) + orbits_files = retrieve_data(source, source_config['orbit'], started_at, stopped_at) si = StringIO.StringIO() cw = csv_writer(si) diff --git a/web/static/js/swapp.js b/web/static/js/swapp.js index 7e9f5c9..5d6c06c 100644 --- a/web/static/js/swapp.js +++ b/web/static/js/swapp.js @@ -6,15 +6,83 @@ SpaceWeather.displayName = 'SpaceWeather'; var prototype = SpaceWeather.prototype, constructor = SpaceWeather; function SpaceWeather(configuration){ + this.configuration = configuration; console.info("Creating Space Weather app...", configuration); + this.sources = {}; } + SpaceWeather.prototype.buildDataUrlForSource = function(source_slug){ + var url; + url = this.configuration['api']['data_for_interval']; + url = url.replace('', source_slug); + return url; + }; + SpaceWeather.prototype.addSource = function(source){ + this.sources[source.slug] = source; + return this; + }; + SpaceWeather.prototype.showAllSources = function(){ + var slug, ref$, source; + for (slug in ref$ = this.sources) { + source = ref$[slug]; + source.show(); + } + return this; + }; + SpaceWeather.prototype.showSource = function(source){ + source.show(); + return this; + }; + SpaceWeather.prototype.hideSource = function(source){ + source.hide(); + return this; + }; + SpaceWeather.prototype.loadData = function(source_slug, started_at, stopped_at){ + var sw, promise; + sw = this; + promise = new Promise(function(resolve, reject){ + var url; + url = sw.buildDataUrlForSource(source_slug); + return d3.csv(url + ("?started_at=" + started_at + "&stopped_at=" + stopped_at), function(csv){ + var timeFormat, data; + timeFormat = d3.timeParse('%Y-%m-%dT%H:%M:%S%Z'); + data = { + 'hci': [] + }; + configuration['parameters'].forEach(function(parameter){ + return data[parameter['id']] = []; + }); + csv.forEach(function(d){ + var dtime; + dtime = timeFormat(d['time']); + configuration['parameters'].forEach(function(parameter){ + var id; + id = parameter['id']; + return data[id].push({ + x: dtime, + y: parseFloat(d[id]) + }); + }); + if (d['xhci'] && d['yhci']) { + return data['hci'].push({ + t: dtime, + x: parseFloat(d['xhci']), + y: parseFloat(d['yhci']) + }); + } + }); + return resolve(data); + }); + }); + return promise; + }; return SpaceWeather; }()); Source = (function(){ Source.displayName = 'Source'; var prototype = Source.prototype, constructor = Source; - function Source(slug){ + function Source(slug, config){ this.slug = slug; + this.config = config; this.time_series = {}; } Source.prototype.addTimeSeries = function(ts){ diff --git a/web/static/js/swapp.ls b/web/static/js/swapp.ls index d9dd6dd..1bbbea7 100644 --- a/web/static/js/swapp.ls +++ b/web/static/js/swapp.ls @@ -7,16 +7,60 @@ const GOLDEN_RATIO = 2 / (1 + Math.sqrt(5)) export class SpaceWeather - (configuration) -> + (@configuration) -> console.info "Creating Space Weather app...", configuration + @sources = {} - # fixme + buildDataUrlForSource: (source_slug) -> + url = @configuration['api']['data_for_interval'] + url = url.replace('', source_slug) + url + addSource: (source) -> + @sources[source.slug] = source + this + + showAllSources: -> + for slug, source of @sources + source.show() + this + + showSource: (source) -> + source.show() + this + + hideSource: (source) -> + source.hide() + this + + loadData: (source_slug, started_at, stopped_at) -> + sw = this + promise = new Promise((resolve, reject) -> + url = sw.buildDataUrlForSource(source_slug) + d3.csv(url+"?started_at=#{started_at}&stopped_at=#{stopped_at}", (csv) -> + timeFormat = d3.timeParse('%Y-%m-%dT%H:%M:%S%Z') + data = {'hci': []}; + configuration['parameters'].forEach((parameter) -> + data[parameter['id']] = [] + ) + csv.forEach((d) -> + dtime = timeFormat(d['time']) + configuration['parameters'].forEach((parameter) -> + id = parameter['id'] + data[id].push({x: dtime, y: parseFloat(d[id])}) + ) + if (d['xhci'] && d['yhci']) + data['hci'].push({t: dtime, x: parseFloat(d['xhci']), y: parseFloat(d['yhci'])}); + ) + resolve(data) + ) + ) + promise class Source - (@slug) -> + (@slug, @config) -> @time_series = {} addTimeSeries: (ts) -> diff --git a/web/view/home.html.jinja2 b/web/view/home.html.jinja2 index 2fd981e..83ff56c 100755 --- a/web/view/home.html.jinja2 +++ b/web/view/home.html.jinja2 @@ -157,6 +157,10 @@ var configuration = { time_series_container: '#time_series', orbits_container: '#orbits', + api : { + 'data_for_interval': "{{ request.url_root }}/data.csv" + // ?started_at=&stopped_at= + }, sources : { jupiter: { slug: 'jupiter', @@ -168,30 +172,37 @@ var configuration = { img: '{{ static('img/planet/jupiter_128.png') }}' } }, +{# todo @Nicolas Define -somehow- error margins of each parameter #} parameters : [ { id: 'pdyn', - title: "Dynamic Pressure (nPa)" + title: "Dynamic Pressure (nPa)", + unit: "nPa" }, { id: 'magn', - title: "Magnetism (nT)" + title: "Magnetism (nT)", + unit: "nT" }, { id: 'vlen', - title: "Velocity (km/s)" + title: "Velocity (km/s)", + unit: "km/s" }, { id: 'temp', - title: "Temperature (K)" + title: "Temperature (K)", + unit: "K" }, { id: 'dens', - title: "Density N (cm⁻³)" + title: "Density N (cm⁻³)", + unit: "cm⁻³" }, { id: 'angl', - title: "Angle S-S-E (deg)" + title: "Angle S-S-E (deg)", + unit: "deg" } ] }; @@ -201,10 +212,17 @@ jQuery().ready(function($){ var orbits; var sw = new SpaceWeather(configuration); + sw.loadData('jupiter', '2016-01-01T00:00:00', '2023-01-01T00:00:00').then( + function (data) { console.log('OK', data); }, + function (data) { console.log('Failed', data); } + ); - d3.csv('{{ url_for('get_orbiter_csv', orbiter='jupiter', started_at='2016-03-19T00:00:00', stopped_at='2022-01-01T00:00:00') }}', function(csv){ + d3.csv('{{ url_for('get_orbiter_csv', source='jupiter', started_at='2016-03-19T00:00:00', stopped_at='2022-01-01T00:00:00') }}', function(csv){ var timeFormat = d3.timeParse('%Y-%m-%dT%H:%M:%S%Z'); - var data = {'pdyn': [], 'magn': [], 'vlen': [], 'temp': [], 'dens': [], 'angl': [], 'hci': []}; + var data = {'hci': []}; + configuration['parameters'].forEach(function(parameter){ + data[parameter['id']] = []; + }); csv.forEach(function (d) { var dtime = timeFormat(d['time']); configuration['parameters'].forEach(function(parameter){ @@ -221,9 +239,7 @@ jQuery().ready(function($){ configuration['parameters'].forEach(function(parameter){ var id = parameter['id']; var title = parameter['title']; - timeSeries.push(new TimeSeries( - id, title, data[id], container - )); + timeSeries.push(new TimeSeries(id, title, data[id], container)); }); // move outside (after promises) timeSeries.forEach(function(ts){ -- libgit2 0.21.2