Commit 1324cc91515ffac764b9fb895a96639c6cdb4ed2

Authored by Goutte
1 parent ea6c8d5d

Make the footer images clickable

Highlight the visits counter
Use a default interval up to 3 weeks in the future
CHANGELOG.md
... ... @@ -10,9 +10,7 @@
10 10 - [ ] Give the future data another color
11 11 - [ ] Sort times series by closeness to the sun
12 12 - [ ] Generate a CDF file (not NetCDF)
13   -- [ ] Make the footer images clickable
14 13 - [ ] Move the link to the source in the footer
15   -- [ ] Highlight the visits counter
16 14  
17 15 An heliospheric propagation 1D MHD model for solar wind prediction at planets, probes and comets.
18 16  
... ... @@ -20,6 +18,9 @@ An heliospheric propagation 1D MHD model for solar wind prediction at planets, p
20 18  
21 19 ## 1.0.0-rc4
22 20  
  21 +- [x] Make the footer images clickable
  22 +- [x] Highlight the visits counter
  23 +- [x] Use a default interval up to 3 weeks in the future
23 24 - [x] Add interval constraints for orbit models (Rosetta uses P67 after a time)
24 25 - [x] Make the download with a netcdf file instead of a tarball of CSVs
25 26 - [x] Support having no position to display (for Rosetta in some intervals)
... ...
config.yml
... ... @@ -166,10 +166,13 @@ targets:
166 166 - type: 'probe'
167 167 slug: 'juno'
168 168 name: 'Juno'
169   - title: 'Juno (coming soon)'
  169 + title: 'Juno'
170 170 orbit:
171 171 models:
172 172 - slug: 'juno_cruise_all'
  173 + stopped_at: '2016-07-01T00:00:00'
  174 + - slug: 'jupiter_orb_all'
  175 + started_at: '2016-07-01T00:00:00'
173 176 models:
174 177 - slug: 'tao_juno_sw'
175 178 locked: false
... ...
web/run.py
... ... @@ -46,10 +46,12 @@ FILE_DATE_FMT = "%Y-%m-%dT%H:%M:%S"
46 46  
47 47 # LOGGING #####################################################################
48 48  
  49 +LOG_FILE = get_path('run.log')
  50 +
49 51 log = logging.getLogger("HelioPropa")
50 52 log.setLevel(logging.DEBUG)
51 53 # log.setLevel(logging.ERROR) # <-- set log level here !
52   -logHandler = logging.FileHandler(get_path('run.log'))
  54 +logHandler = logging.FileHandler(LOG_FILE)
53 55 logHandler.setFormatter(logging.Formatter(
54 56 "%(asctime)s - %(levelname)s - %(message)s"
55 57 ))
... ... @@ -265,6 +267,19 @@ def is_list_in_list(needle, haystack):
265 267 return True
266 268  
267 269  
  270 +def round_time(dt=None, round_to=60):
  271 + """
  272 + Round a datetime object to any time laps in seconds
  273 + dt : datetime.datetime object, default now.
  274 + roundTo : Closest number of seconds to round to, default 1 minute.
  275 + """
  276 + if dt is None:
  277 + dt = datetime.datetime.now()
  278 + seconds = (dt.replace(tzinfo=None) - dt.min).seconds
  279 + rounding = (seconds + round_to / 2) // round_to * round_to
  280 + return dt + datetime.timedelta(0, rounding-seconds, -dt.microsecond)
  281 +
  282 +
268 283 def datetime_from_list(time_list):
269 284 """
270 285 Datetimes in retrieved CDFs are stored as lists of numbers,
... ... @@ -465,9 +480,13 @@ def get_data_for_target(target_config, started_at, stopped_at):
465 480 log.debug("%s: aggregating data from '%s'..." %
466 481 (target_config['name'], orbit_file))
467 482 for time, datum_hee in zip(times, data_hee):
468   - dtime = datetime_from_list(time)
  483 + try:
  484 + dtime = datetime_from_list(time)
  485 + except Exception as e:
  486 + log.error("Failed to parse time from %s." % time)
  487 + raise e
469 488 if s0 <= dtime <= s1:
470   - dkey = dtime.strftime(precision)
  489 + dkey = round_time(dtime, 60*60).strftime(precision)
471 490 orbit_data[dkey] = datum_hee
472 491 cdf_handle.close()
473 492  
... ... @@ -490,9 +509,13 @@ def get_data_for_target(target_config, started_at, stopped_at):
490 509 in zip(times, data_v, data_b, data_t, data_n, data_p, data_d):
491 510 vrad = datum_v[0]
492 511 vtan = datum_v[1]
493   - dtime = datetime_from_list(time)
  512 + try:
  513 + dtime = datetime_from_list(time)
  514 + except Exception as e:
  515 + log.error("Failed to parse time from %s." % time)
  516 + raise e
494 517 if started_at <= dtime <= stopped_at:
495   - dkey = dtime.strftime(precision)
  518 + dkey = round_time(dtime, 60*60).strftime(precision)
496 519 x_hee = None
497 520 y_hee = None
498 521 if dkey in orbit_data:
... ... @@ -913,13 +936,20 @@ def cache_warmup():
913 936 return "To Do"
914 937  
915 938  
916   -@app.route("/run.log")
917   -def run_log():
918   - with open(get_path('run.log'), 'r') as f:
  939 +@app.route("/log")
  940 +def log_show():
  941 + with open(LOG_FILE, 'r') as f:
919 942 contents = f.read()
920 943 return contents
921 944  
922 945  
  946 +@app.route("/log/clear")
  947 +def log_clear():
  948 + with open(LOG_FILE, 'w') as f:
  949 + f.truncate()
  950 + return "Log cleared successfully."
  951 +
  952 +
923 953 # DEV TOOLS ###################################################################
924 954  
925 955 # @app.route("/inspect")
... ... @@ -951,6 +981,11 @@ def run_log():
951 981 # MAIN ########################################################################
952 982  
953 983 if __name__ == "__main__":
  984 +
  985 + a = "2015171150000001"
  986 +
  987 +
  988 +
954 989 # Debug mode on, as the production server does not use this but run.wsgi
955 990 extra_files = [get_path('../config.yml')]
956 991 app.run(debug=True, extra_files=extra_files)
... ...
web/static/js/swapp.js
... ... @@ -43,7 +43,7 @@
43 43 "This is called by the inline bootstrap javascript code.\nThis ain't in the constructor because it might return a Promise later on.\n(for the loader, for example)";
44 44 var started_at, stopped_at, this$ = this;
45 45 started_at = moment().subtract(1, 'year').hours(0).minutes(0).seconds(0);
46   - stopped_at = moment().add(1, 'week').hours(0).minutes(0).seconds(0);
  46 + stopped_at = moment().add(3, 'week').hours(0).minutes(0).seconds(0);
47 47 this.setStartAndStop(started_at, stopped_at);
48 48 this.loadAndCreatePlots(started_at, stopped_at);
49 49 return window.addEventListener('resize', function(){
... ...
web/static/js/swapp.ls
... ... @@ -75,7 +75,7 @@ https://gitlab.irap.omp.eu/CDPP/SPACEWEATHERONLINE
75 75 # Default time interval is from two weeks ago to one week ahead.
76 76 # We set the h/m/s to zero to benefit from a daily cache.
77 77 started_at = moment().subtract(1, 'year').hours(0).minutes(0).seconds(0)
78   - stopped_at = moment().add(1, 'week').hours(0).minutes(0).seconds(0)
  78 + stopped_at = moment().add(3, 'week').hours(0).minutes(0).seconds(0)
79 79 @setStartAndStop(started_at, stopped_at)
80 80 @loadAndCreatePlots(started_at, stopped_at)
81 81  
... ...
web/view/home.html.jinja2
... ... @@ -298,7 +298,7 @@
298 298 path.orbit.orbit_section {
299 299 fill: none;
300 300 stroke: steelblue;
301   - stroke-width: 3px;
  301 + stroke-width: 1.5px;
302 302 }
303 303 ellipse.orbit.orbit_ellipse {
304 304 fill: none;
... ...
web/view/layout.html.jinja2
... ... @@ -70,36 +70,30 @@
70 70  
71 71 <footer class="mdl-mini-footer">
72 72 <div class="mdl-mini-footer__left-section">
  73 + <p style="float: left; margin: 1.5em;">
  74 + {{ visits }} visits since 2017
  75 + </p>
73 76 <p class="disclaimer">
74 77 The <a href="http://www.europlanet-2020-ri.eu/">Europlanet 2020 Research Infrastructure</a> project has received funding
75 78 <br>
76 79 from the <a href="https://ec.europa.eu/programmes/horizon2020/">European Union's Horizon 2020</a> research and innovation programme
77 80 under grant agreement N°&nbsp;654208.
78 81 <br>
79   - {{ visits }} visits since 2017
80 82 </p>
81 83 </div>
82 84 <div class="mdl-mini-footer__right-section">
83   - <img class="logo" src="{{ static('img/logo/logo_cdpp.png') }}" alt="CDPP" id="logo_cdpp" />
  85 + <a href="http://cdpp.irap.omp.eu">
  86 + <img class="logo" src="{{ static('img/logo/logo_cdpp.png') }}" alt="CDPP" id="logo_cdpp" />
  87 + </a>
84 88 &nbsp;&nbsp;&nbsp;
85   - <img class="logo" src="{{ static('img/logo/logo_europlanet.png') }}" alt="Europlanet" id="logo_europlanet" />
  89 + <a href="http://planetaryspaceweather-europlanet.irap.omp.eu/">
  90 + <img class="logo" src="{{ static('img/logo/logo_europlanet.png') }}" alt="Europlanet" id="logo_europlanet" />
  91 + </a>
86 92 </div>
87 93 </footer>
88 94  
89 95 </div>
90 96  
91   -{# <script type="application/javascript">#}
92   -{# // fixme: GOOGLE ANALYTICS ?#}
93   -{# /*#}
94   -{# (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){#}
95   -{# (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),#}
96   -{# m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)#}
97   -{# })(window,document,'script','//www.google-analytics.com/analytics.js','ga');#}
98   -{# ga('create', 'UA-56037907-1', 'auto');#}
99   -{# ga('send', 'pageview');#}
100   -{# */#}
101   -{# </script>#}
102   -
103 97 <script type="application/javascript" src="{{ static('js/vendor/jquery-3.2.1.min.js') }}"></script>
104 98 <script type="application/javascript" src="{{ static('js/vendor/material-custom.js') }}"></script>
105 99 <script type="application/javascript">
... ...