Commit 1324cc91515ffac764b9fb895a96639c6cdb4ed2
1 parent
ea6c8d5d
Exists in
master
and in
2 other branches
Make the footer images clickable
Highlight the visits counter Use a default interval up to 3 weeks in the future
Showing
7 changed files
with
62 additions
and
29 deletions
Show diff stats
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
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° 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 | |
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"> | ... | ... |