Commit bde97e4d3c1fc75b05aa98d61d6e87e4459504ce

Authored by Goutte
1 parent 17c52617

Add more changes suggested by Vincent. Still hunting why the recent data is not …

…shown, but from as far as I can see, it's not in the CDF files provided by AMDA.
CHANGELOG.md
1 1 ## Misc
2 2  
3   -- [ ] Support multiple models for each target
4 3 - [ ] Optimize CSV generation (numpy vectorization ?)
5 4 - [ ] Credit the author of the pixel art planets
6 5 - [ ] Add a README to the download tarball
... ... @@ -23,9 +22,13 @@
23 22 - [ ] CRON statement to call it
24 23 - [ ] Cache warmup
25 24 - [x] Download raw data (tarball of CSV) for current time interval and targets
26   -- [ ] Download raw data as NetCDF for current everything, via SAMP
  25 +- [x] Download raw data as NetCDF for current everything, via SAMP
27 26 - [x] Add a warning for users with javascript disabled
28 27 - [ ] Set the log level to _error_ in production (see `web/run.py`)
  28 +- [ ] Make the targets dynamic in the orbit plot, allowing zoom
  29 +- [ ] Add units to the generated CSV files
  30 +- [x] Support multiple models for each target
  31 +
29 32  
30 33  
31 34 ## 0.0.0
... ...
web/run.py
  1 +# coding=utf-8
  2 +
1 3 import StringIO
2 4 import datetime
3   -import time
4 5 import gzip
5 6 import json
6 7 import logging
7 8 import random
8 9 import tarfile
  10 +import time
9 11 import urllib
10 12 from csv import writer as csv_writer
11 13 from math import sqrt
... ... @@ -15,7 +17,7 @@ from os.path import isfile, join, abspath, dirname
15 17 from flask import Flask
16 18 from flask import request
17 19 from flask import url_for, send_from_directory, abort as abort_flask
18   -from jinja2 import Environment, FileSystemLoader
  20 +from jinja2 import Environment, FileSystemLoader, Markup
19 21 from netCDF4 import Dataset, date2num
20 22 from yaml import load as yaml_load
21 23  
... ... @@ -101,6 +103,33 @@ def markdown_filter(value, nl2br=False, p=True):
101 103 return markdowned
102 104  
103 105  
  106 +_js_escapes = {
  107 + '\\': '\\u005C',
  108 + '\'': '\\u0027',
  109 + '"': '\\u0022',
  110 + '>': '\\u003E',
  111 + '<': '\\u003C',
  112 + '&': '\\u0026',
  113 + '=': '\\u003D',
  114 + '-': '\\u002D',
  115 + ';': '\\u003B',
  116 + u'\u2028': '\\u2028',
  117 + u'\u2029': '\\u2029'
  118 +}
  119 +# Escape every ASCII character with a value less than 32.
  120 +_js_escapes.update(('%c' % z, '\\u%04X' % z) for z in xrange(32))
  121 +
  122 +
  123 +def escapejs_filter(value):
  124 + escaped = []
  125 + for letter in value:
  126 + if letter in _js_escapes:
  127 + escaped.append(_js_escapes[letter])
  128 + else:
  129 + escaped.append(letter)
  130 +
  131 + return Markup("".join(escaped))
  132 +
104 133 tpl_engine = Environment(loader=FileSystemLoader([get_path('view')]),
105 134 trim_blocks=True,
106 135 lstrip_blocks=True)
... ... @@ -113,6 +142,7 @@ tpl_engine.globals.update(
113 142 tpl_engine.filters['markdown'] = markdown_filter
114 143 tpl_engine.filters['md'] = markdown_filter
115 144 tpl_engine.filters['shuffle'] = shuffle_filter
  145 +tpl_engine.filters['escapejs'] = escapejs_filter
116 146  
117 147 tpl_global_vars = {
118 148 'request': request,
... ... @@ -278,11 +308,14 @@ def retrieve_amda_netcdf(orbiter, what, started_at, stopped_at):
278 308 return local_netc_files
279 309  
280 310  
  311 +# These two configs are not in the YAML config because adding a new parameter
  312 +# will not work as-is, you'll have to edit the netcdf-related code
  313 +
281 314 # The available parameters in the generated CSV files.
282 315 # The order matters. If you change this you also need to change the
283 316 # innermost loop of `get_data_for_target`.
284 317 # The javascript knows the targets' properties under these names.
285   -PROPERTIES = ('time', 'vrad', 'vtan', 'vlen', 'magn', 'temp', 'pdyn', 'dens',
  318 +PROPERTIES = ('time', 'vrad', 'vtan', 'vtot', 'btan', 'temp', 'pdyn', 'dens',
286 319 'angl', 'xhee', 'yhee')
287 320  
288 321 # The parameters that the users can handle.
... ... @@ -293,36 +326,48 @@ PARAMETERS = {
293 326 'name': 'Dyn. Pressure',
294 327 'title': 'The dynamic pressure.',
295 328 'units': 'nPa',
  329 + 'active': True,
  330 + 'position': 10,
296 331 },
297   - 'vlen': {
298   - 'slug': 'vlen',
  332 + 'vtot': {
  333 + 'slug': 'vtot',
299 334 'name': 'Velocity',
300 335 'title': 'The velocity of the particles.',
301 336 'units': 'km/s',
  337 + 'active': False,
  338 + 'position': 20,
302 339 },
303   - 'magn': {
304   - 'slug': 'magn',
  340 + 'btan': {
  341 + 'slug': 'btan',
305 342 'name': 'B Tangential',
306 343 'title': 'B Tangential.',
307 344 'units': 'nT',
  345 + 'active': False,
  346 + 'position': 30,
308 347 },
309 348 'temp': {
310 349 'slug': 'temp',
311 350 'name': 'Temperature',
312 351 'title': 'The absolute temperature.',
313 352 'units': 'K',
  353 + 'active': False,
  354 + 'position': 40,
314 355 },
315 356 'dens': {
316 357 'slug': 'dens',
317 358 'name': 'Density',
318 359 'title': 'The density N.',
319   - 'units': 'cm^-3',
  360 + 'units': u'cm⁻³',
  361 + 'active': False,
  362 + 'position': 50,
320 363 },
321 364 'angl': {
322 365 'slug': 'angl',
323 366 'name': 'Angle T-S-E',
324 367 'title': 'Angle Target-Sun-Earth.',
325 368 'units': 'deg',
  369 + 'active': False,
  370 + 'position': 60,
326 371 },
327 372 }
328 373  
... ... @@ -528,7 +573,7 @@ tpl_global_vars[&#39;visits&#39;] = get_hit_counter()
528 573 # ROUTING #####################################################################
529 574  
530 575 @app.route('/favicon.ico')
531   -def favicon():
  576 +def favicon(): # we want it served from the root, not from static/
532 577 return send_from_directory(
533 578 join(app.root_path, 'static', 'img'),
534 579 'favicon.ico', mimetype='image/vnd.microsoft.icon'
... ... @@ -540,8 +585,11 @@ def favicon():
540 585 @app.route("/index.html")
541 586 def home():
542 587 increment_hit_counter()
  588 + parameters = PARAMETERS.values()
  589 + parameters.sort(key=lambda x: x['position'])
543 590 return render_view('home.html.jinja2', {
544 591 'targets': config['targets'],
  592 + 'parameters': parameters,
545 593 'planets': [s for s in config['targets'] if s['type'] == 'planet'],
546 594 'probes': [s for s in config['targets'] if s['type'] == 'probe'],
547 595 'comets': [s for s in config['targets'] if s['type'] == 'comet'],
... ... @@ -751,7 +799,7 @@ def download_targets_netcdf(targets, params, started_at, stopped_at):
751 799 if not isfile(nc_path):
752 800 abort(500, "No NetCDF to serve. Looked at '%s'." % nc_path)
753 801  
754   - return send_from_directory(get_path("../cache/"), nc_filename)
  802 + return send_from_directory(get_path("../cache"), nc_filename)
755 803  
756 804  
757 805 # API #########################################################################
... ... @@ -773,12 +821,18 @@ def cache_warmup():
773 821 Warms up the cache for the current day.
774 822 Linked to SpaceWeather#edit in swapp.ls
775 823 """
776   - from dateutil.relativedelta import relativedelta
777 824 # relativedelta(years=3)
778 825 # startted_at = datetime.datetime.now() - relativedelta(years=3)
779 826 return "To Do"
780 827  
781 828  
  829 +@app.route("/run.log")
  830 +def run_log():
  831 + with open(get_path('run.log'), 'r') as f:
  832 + contents = f.read()
  833 + return contents
  834 +
  835 +
782 836 # DEV TOOLS ###################################################################
783 837  
784 838 # @app.route("/inspect")
... ...
web/static/js/swapp.ls
... ... @@ -337,7 +337,7 @@ export class TimeSeries
337 337 # Data in y-axis
338 338  
339 339 (@parameter, @title, @target, data, @visible, @container, @options = {}) ->
340   - # parameter : slug of the parameter to observe, like magn or pdyn
  340 + # parameter : slug of the parameter to observe, like btan or pdyn
341 341 # title : string, more descriptive, shown on the left of the Y axis
342 342 # target : target object, like described in configuration
343 343 # data : list of {x: <datetime>, y: <float>}
... ...
web/view/home.html.jinja2
... ... @@ -99,13 +99,9 @@
99 99 <span class="mdl-layout-title">{{ icon('flask') }} Parameters</span>
100 100  
101 101 <nav id="parameters" class="mdl-navigation">
102   - {# todo: generate this from config #}
103   - <a class="mdl-navigation__link parameter active" data-ts-slug="pdyn" href="#">Dynamic Pressure</a>
104   - <a class="mdl-navigation__link parameter" data-ts-slug="magn" href="#">B Tangential</a>
105   - <a class="mdl-navigation__link parameter" data-ts-slug="vlen" href="#">Velocity</a>
106   - <a class="mdl-navigation__link parameter" data-ts-slug="temp" href="#">Temperature</a>
107   - <a class="mdl-navigation__link parameter" data-ts-slug="dens" href="#">Density</a>
108   - <a class="mdl-navigation__link parameter" data-ts-slug="angl" href="#">Angle Target-Sun-Earth</a>
  102 + {% for p in parameters %}
  103 + <a class="mdl-navigation__link parameter{{ ' active' if p.active }}" data-ts-slug="{{ p.slug }}" href="#">{{ p.name }}</a>
  104 + {% endfor %}
109 105 </nav>
110 106  
111 107 <div class="mdl-layout-spacer"></div>
... ... @@ -537,7 +533,7 @@
537 533 var configuration = {
538 534 time_series_container: '#time_series',
539 535 orbits_container: '#orbits',
540   - api : {
  536 + api: {
541 537 'data_for_interval': "{{ request.url_root }}<target>_<started_at>_<stopped_at>.csv",
542 538 'download': "{{ request.url_root }}<targets>_<started_at>_<stopped_at>.tar.gz",
543 539 'samp': "{{ request.url_root }}<targets>_<params>_<started_at>_<stopped_at>.nc"
... ... @@ -545,7 +541,7 @@ var configuration = {
545 541 sun: {
546 542 img: '{{ static('img/sun_128.png') }}'
547 543 },
548   - targets : {
  544 + targets: {
549 545 {% for target in targets if not target.locked %}
550 546 {% if not loop.first %},{% endif %}
551 547 '{{ target.slug }}': {
... ... @@ -557,45 +553,15 @@ var configuration = {
557 553 }
558 554 {% endfor %}
559 555 },
560   -{# todo @Nicolas Define -somehow- error margins of each parameter ? #}
561   -{# todo: generate this from config PARAMETERS #}
562   - parameters : [
  556 + parameters: [
  557 +{% for p in parameters %}
563 558 {
564   - id: 'pdyn',
565   - title: "Dyn. Pressure (nPa)",
566   - active: true,
567   - unit: "nPa"
568   - },
569   - {
570   - id: 'magn',
571   - title: "B Tangential (nT)",
572   - active: false,
573   - unit: "nT"
574   - },
575   - {
576   - id: 'vlen',
577   - title: "Velocity (km/s)",
578   - active: false,
579   - unit: "km/s"
580   - },
581   - {
582   - id: 'temp',
583   - title: "Temperature (K)",
584   - active: false,
585   - unit: "K"
586   - },
587   - {
588   - id: 'dens',
589   - title: "Density N (cm⁻³)",
590   - active: false,
591   - unit: "cm⁻³"
592   - },
593   - {
594   - id: 'angl',
595   - title: "Angle T-S-E (deg)",
596   - active: false,
597   - unit: "deg"
598   - }
  559 + id: "{{ p.slug | escapejs }}",
  560 + title: "{{ p.name | escapejs }} ({{ p.units | escapejs }})",
  561 + active: {{ 'true' if p.active else 'false' }},
  562 + unit: "{{ p.units | escapejs }}"
  563 + }{{ ',' if not loop.last }}
  564 +{% endfor %}
599 565 ]
600 566 };
601 567  
... ...