Commit dc0be9925d35db1001545592b3b2bebe31a70421
1 parent
ff3519a8
Exists in
master
and in
2 other branches
Support having no position to display (for Rosetta in some intervals)
Make the local cache more resilient to corrupted downloads
Showing
7 changed files
with
69 additions
and
25 deletions
Show diff stats
CHANGELOG.md
@@ -12,8 +12,8 @@ | @@ -12,8 +12,8 @@ | ||
12 | ## 1.0.0-rc4 | 12 | ## 1.0.0-rc4 |
13 | 13 | ||
14 | - [ ] Make the tarball with netcdf files instead of CSVs | 14 | - [ ] Make the tarball with netcdf files instead of CSVs |
15 | -- [ ] Support having no position to display (for Rosetta in some intervals) | ||
16 | -- [x] Cache clear (remove all files) `/cache/clear` | 15 | +- [x] Support having no position to display (for Rosetta in some intervals) |
16 | +- [x] Make the local cache more resilient to corrupted downloads | ||
17 | - [x] Make the local cache more resilient to naming collisions | 17 | - [x] Make the local cache more resilient to naming collisions |
18 | 18 | ||
19 | 19 | ||
@@ -21,6 +21,7 @@ | @@ -21,6 +21,7 @@ | ||
21 | 21 | ||
22 | - [x] Make the targets dynamic in the orbit plot, allowing zoom | 22 | - [x] Make the targets dynamic in the orbit plot, allowing zoom |
23 | - [x] Refactor some more to move as much as we can to the config | 23 | - [x] Refactor some more to move as much as we can to the config |
24 | +- [x] Cache clear (remove all files) `/cache/clear` | ||
24 | 25 | ||
25 | 26 | ||
26 | ## 1.0.0-rc2 | 27 | ## 1.0.0-rc2 |
@@ -65,7 +66,7 @@ | @@ -65,7 +66,7 @@ | ||
65 | - [x] Probes | 66 | - [x] Probes |
66 | - [x] Rosetta | 67 | - [x] Rosetta |
67 | - [x] Juno | 68 | - [x] Juno |
68 | -- [x] Comets (the one visited by rosetta) | 69 | +- [x] Comets (the one visited by rosetta, p67) |
69 | - [x] Orbits axes titles | 70 | - [x] Orbits axes titles |
70 | - [x] Logo Europlanet | 71 | - [x] Logo Europlanet |
71 | - [x] Cache remote NetCDFs locally | 72 | - [x] Cache remote NetCDFs locally |
config.yml
@@ -98,7 +98,7 @@ targets: | @@ -98,7 +98,7 @@ targets: | ||
98 | - type: 'planet' | 98 | - type: 'planet' |
99 | slug: 'earth' | 99 | slug: 'earth' |
100 | name: 'Earth' | 100 | name: 'Earth' |
101 | - title: 'Earth (Coming NEXT!)' | 101 | + title: 'Earth (coming soon)' |
102 | orbit: | 102 | orbit: |
103 | models: | 103 | models: |
104 | - slug: 'earth_orb_all' | 104 | - slug: 'earth_orb_all' |
@@ -152,13 +152,13 @@ targets: | @@ -152,13 +152,13 @@ targets: | ||
152 | - type: 'probe' | 152 | - type: 'probe' |
153 | slug: 'rosetta' | 153 | slug: 'rosetta' |
154 | name: 'Rosetta' | 154 | name: 'Rosetta' |
155 | - title: 'Rosetta (coming soon)' | 155 | + title: 'Rosetta' |
156 | orbit: | 156 | orbit: |
157 | models: | 157 | models: |
158 | - slug: 'ros_orb_cruise' | 158 | - slug: 'ros_orb_cruise' |
159 | models: | 159 | models: |
160 | - slug: 'tao_ros_sw' | 160 | - slug: 'tao_ros_sw' |
161 | - locked: true | 161 | + locked: false |
162 | default: false | 162 | default: false |
163 | - type: 'probe' | 163 | - type: 'probe' |
164 | slug: 'juno' | 164 | slug: 'juno' |
@@ -169,7 +169,7 @@ targets: | @@ -169,7 +169,7 @@ targets: | ||
169 | - slug: 'juno_cruise_all' | 169 | - slug: 'juno_cruise_all' |
170 | models: | 170 | models: |
171 | - slug: 'tao_juno_sw' | 171 | - slug: 'tao_juno_sw' |
172 | - locked: true | 172 | + locked: false |
173 | default: false | 173 | default: false |
174 | - type: 'comet' | 174 | - type: 'comet' |
175 | slug: 'p67' | 175 | slug: 'p67' |
web/run.py
@@ -368,11 +368,12 @@ def retrieve_amda_netcdf(orbiter, what, started_at, stopped_at): | @@ -368,11 +368,12 @@ def retrieve_amda_netcdf(orbiter, what, started_at, stopped_at): | ||
368 | log.debug("Retrieving '%s'..." % local_gzip_file) | 368 | log.debug("Retrieving '%s'..." % local_gzip_file) |
369 | urllib.urlretrieve(remote_gzip_file, local_gzip_file) | 369 | urllib.urlretrieve(remote_gzip_file, local_gzip_file) |
370 | log.debug("Retrieved '%s'." % local_gzip_file) | 370 | log.debug("Retrieved '%s'." % local_gzip_file) |
371 | + else: | ||
372 | + log.debug("Found '%s' in the cache." % local_gzip_file) | ||
371 | 373 | ||
372 | local_netc_files = [] | 374 | local_netc_files = [] |
373 | for local_gzip_file in local_gzip_files: | 375 | for local_gzip_file in local_gzip_files: |
374 | local_netc_file = local_gzip_file[0:-3] | 376 | local_netc_file = local_gzip_file[0:-3] |
375 | - local_netc_files.append(local_netc_file) | ||
376 | log.debug("Unzipping '%s'..." % local_gzip_file) | 377 | log.debug("Unzipping '%s'..." % local_gzip_file) |
377 | success = True | 378 | success = True |
378 | try: | 379 | try: |
@@ -382,9 +383,13 @@ def retrieve_amda_netcdf(orbiter, what, started_at, stopped_at): | @@ -382,9 +383,13 @@ def retrieve_amda_netcdf(orbiter, what, started_at, stopped_at): | ||
382 | g.write(file_content) | 383 | g.write(file_content) |
383 | except Exception as e: | 384 | except Exception as e: |
384 | success = False | 385 | success = False |
385 | - log.warning("Cannot process gz file '%s' from '%s' : %s" % | ||
386 | - (local_gzip_file, url, e)) | 386 | + log.error("Cannot process gz file '%s' from '%s' : %s" % |
387 | + (local_gzip_file, url, e)) | ||
388 | + # Sometimes, the downloaded gz is corrupted, and CRC checks fail. | ||
389 | + # We want to delete the local gz file and try again next time. | ||
390 | + removefile(local_gzip_file) | ||
387 | if success: | 391 | if success: |
392 | + local_netc_files.append(local_netc_file) | ||
388 | log.debug("Unzipped '%s'." % local_gzip_file) | 393 | log.debug("Unzipped '%s'." % local_gzip_file) |
389 | 394 | ||
390 | return local_netc_files | 395 | return local_netc_files |
@@ -435,6 +440,8 @@ def get_data_for_target(target_config, started_at, stopped_at): | @@ -435,6 +440,8 @@ def get_data_for_target(target_config, started_at, stopped_at): | ||
435 | cdf_handle = Dataset(orbit_file, "r", format="NETCDF4") | 440 | cdf_handle = Dataset(orbit_file, "r", format="NETCDF4") |
436 | times = cdf_handle.variables['Time'] # YYYY DOY HH MM SS .ms | 441 | times = cdf_handle.variables['Time'] # YYYY DOY HH MM SS .ms |
437 | data_hee = cdf_handle.variables['HEE'] | 442 | data_hee = cdf_handle.variables['HEE'] |
443 | + log.debug("%s: aggregating data from '%s'..." % | ||
444 | + (target_config['name'], orbit_file)) | ||
438 | for time, datum_hee in zip(times, data_hee): | 445 | for time, datum_hee in zip(times, data_hee): |
439 | dtime = datetime_from_list(time) | 446 | dtime = datetime_from_list(time) |
440 | if started_at <= dtime <= stopped_at: | 447 | if started_at <= dtime <= stopped_at: |
@@ -523,6 +530,7 @@ def generate_csv_file_if_needed(target_slug, started_at, stopped_at): | @@ -523,6 +530,7 @@ def generate_csv_file_if_needed(target_slug, started_at, stopped_at): | ||
523 | stopped_at=stopped_at)) | 530 | stopped_at=stopped_at)) |
524 | log.info("Generation of '%s' done." % filename) | 531 | log.info("Generation of '%s' done." % filename) |
525 | except Exception as e: | 532 | except Exception as e: |
533 | + log.error(e) | ||
526 | if isfile(local_csv_file): | 534 | if isfile(local_csv_file): |
527 | log.warn("Removing failed CSV '%s'..." % local_csv_file) | 535 | log.warn("Removing failed CSV '%s'..." % local_csv_file) |
528 | removefile(local_csv_file) | 536 | removefile(local_csv_file) |
web/static/img/target/rosetta_128.png
web/static/js/swapp.js
@@ -742,7 +742,14 @@ | @@ -742,7 +742,14 @@ | ||
742 | }; | 742 | }; |
743 | Orbits.prototype.initOrbiter = function(slug, config, data){ | 743 | Orbits.prototype.initOrbiter = function(slug, config, data){ |
744 | var orbit_ellipse, orbiter, orbit_line, orbit_section, this$ = this; | 744 | var orbit_ellipse, orbiter, orbit_line, orbit_section, this$ = this; |
745 | - console.info("Initializing orbit of " + config.name + "…"); | 745 | + this.data[slug] = data; |
746 | + this.orbiters[slug] = config; | ||
747 | + if (data.length) { | ||
748 | + console.info("Initializing orbit of " + config.name + "…"); | ||
749 | + } else { | ||
750 | + console.warn("No orbit data for " + config.name + "…"); | ||
751 | + return; | ||
752 | + } | ||
746 | if (slug in this.orbitersElements) { | 753 | if (slug in this.orbitersElements) { |
747 | throw new Error("Second init of " + slug); | 754 | throw new Error("Second init of " + slug); |
748 | } | 755 | } |
@@ -755,8 +762,6 @@ | @@ -755,8 +762,6 @@ | ||
755 | return this$.yScale(d.x); | 762 | return this$.yScale(d.x); |
756 | }); | 763 | }); |
757 | orbit_section = this.plotWrapper.append('path').datum(data).classed('orbit orbit_section', true); | 764 | orbit_section = this.plotWrapper.append('path').datum(data).classed('orbit orbit_section', true); |
758 | - this.data[slug] = data; | ||
759 | - this.orbiters[slug] = config; | ||
760 | this.orbitersElements[slug] = { | 765 | this.orbitersElements[slug] = { |
761 | orbiter: orbiter, | 766 | orbiter: orbiter, |
762 | orbit_ellipse: orbit_ellipse, | 767 | orbit_ellipse: orbit_ellipse, |
@@ -771,6 +776,9 @@ | @@ -771,6 +776,9 @@ | ||
771 | return this; | 776 | return this; |
772 | }; | 777 | }; |
773 | Orbits.prototype.showOrbiter = function(slug){ | 778 | Orbits.prototype.showOrbiter = function(slug){ |
779 | + if (!this.data[slug].length) { | ||
780 | + return; | ||
781 | + } | ||
774 | this.orbiters[slug].hidden = false; | 782 | this.orbiters[slug].hidden = false; |
775 | this.orbitersElements[slug].orbiter.style("display", null); | 783 | this.orbitersElements[slug].orbiter.style("display", null); |
776 | this.orbitersElements[slug].orbit_ellipse.style("display", null); | 784 | this.orbitersElements[slug].orbit_ellipse.style("display", null); |
@@ -778,6 +786,9 @@ | @@ -778,6 +786,9 @@ | ||
778 | return this.resize(true); | 786 | return this.resize(true); |
779 | }; | 787 | }; |
780 | Orbits.prototype.hideOrbiter = function(slug){ | 788 | Orbits.prototype.hideOrbiter = function(slug){ |
789 | + if (!this.data[slug].length) { | ||
790 | + return; | ||
791 | + } | ||
781 | this.orbiters[slug].hidden = true; | 792 | this.orbiters[slug].hidden = true; |
782 | this.orbitersElements[slug].orbiter.style("display", "none"); | 793 | this.orbitersElements[slug].orbiter.style("display", "none"); |
783 | this.orbitersElements[slug].orbit_ellipse.style("display", "none"); | 794 | this.orbitersElements[slug].orbit_ellipse.style("display", "none"); |
@@ -832,8 +843,12 @@ | @@ -832,8 +843,12 @@ | ||
832 | return this; | 843 | return this; |
833 | }; | 844 | }; |
834 | Orbits.prototype.resizeOrbiter = function(slug, config, width, height, animate){ | 845 | Orbits.prototype.resizeOrbiter = function(slug, config, width, height, animate){ |
835 | - var tt, el, orbit_section, t, a, b, c, cx, cy, orbit_ellipse; | 846 | + var data, tt, el, orbit_section, t, a, b, c, cx, cy, orbit_ellipse; |
836 | animate == null && (animate = false); | 847 | animate == null && (animate = false); |
848 | + data = this.data[slug]; | ||
849 | + if (!data.length) { | ||
850 | + return; | ||
851 | + } | ||
837 | console.debug("Resizing orbit of " + slug + "…"); | 852 | console.debug("Resizing orbit of " + slug + "…"); |
838 | tt = this.svg.transition().duration(750); | 853 | tt = this.svg.transition().duration(750); |
839 | el = this.orbitersElements[slug]; | 854 | el = this.orbitersElements[slug]; |
@@ -861,6 +876,9 @@ | @@ -861,6 +876,9 @@ | ||
861 | var data, el, t; | 876 | var data, el, t; |
862 | animate == null && (animate = false); | 877 | animate == null && (animate = false); |
863 | data = this.data[slug]; | 878 | data = this.data[slug]; |
879 | + if (!data.length) { | ||
880 | + return; | ||
881 | + } | ||
864 | datum == null && (datum = this.lastOrbiterData[slug]); | 882 | datum == null && (datum = this.lastOrbiterData[slug]); |
865 | datum == null && (datum = data[data.length - 1]); | 883 | datum == null && (datum = data[data.length - 1]); |
866 | this.lastOrbiterData[slug] = datum; | 884 | this.lastOrbiterData[slug] = datum; |
@@ -896,29 +914,33 @@ | @@ -896,29 +914,33 @@ | ||
896 | return this; | 914 | return this; |
897 | }; | 915 | }; |
898 | Orbits.prototype.resizeDomain = function(started_at, stopped_at){ | 916 | Orbits.prototype.resizeDomain = function(started_at, stopped_at){ |
899 | - var slug, ref$, config, el, data, results$ = []; | 917 | + var slug, ref$, config, el, data; |
900 | for (slug in ref$ = this.orbiters) { | 918 | for (slug in ref$ = this.orbiters) { |
901 | config = ref$[slug]; | 919 | config = ref$[slug]; |
902 | el = this.orbitersElements[slug]; | 920 | el = this.orbitersElements[slug]; |
903 | data = this.data[slug].filter(fn$); | 921 | data = this.data[slug].filter(fn$); |
922 | + if (!data.length) { | ||
923 | + return; | ||
924 | + } | ||
904 | el['orbit_section'].datum(data); | 925 | el['orbit_section'].datum(data); |
905 | - results$.push(el['orbit_section'].attr('d', el['orbit_line'])); | 926 | + el['orbit_section'].attr('d', el['orbit_line']); |
906 | } | 927 | } |
907 | - return results$; | ||
908 | function fn$(d){ | 928 | function fn$(d){ |
909 | var ref$; | 929 | var ref$; |
910 | return started_at <= (ref$ = d.t) && ref$ <= stopped_at; | 930 | return started_at <= (ref$ = d.t) && ref$ <= stopped_at; |
911 | } | 931 | } |
912 | }; | 932 | }; |
913 | Orbits.prototype.resetZoom = function(){ | 933 | Orbits.prototype.resetZoom = function(){ |
914 | - var slug, ref$, config, el, results$ = []; | 934 | + var slug, ref$, config, el; |
915 | for (slug in ref$ = this.orbiters) { | 935 | for (slug in ref$ = this.orbiters) { |
916 | config = ref$[slug]; | 936 | config = ref$[slug]; |
917 | el = this.orbitersElements[slug]; | 937 | el = this.orbitersElements[slug]; |
938 | + if (!this.data[slug].length) { | ||
939 | + return; | ||
940 | + } | ||
918 | el['orbit_section'].datum(this.data[slug]); | 941 | el['orbit_section'].datum(this.data[slug]); |
919 | - results$.push(el['orbit_section'].attr('d', el['orbit_line'])); | 942 | + el['orbit_section'].attr('d', el['orbit_line']); |
920 | } | 943 | } |
921 | - return results$; | ||
922 | }; | 944 | }; |
923 | return Orbits; | 945 | return Orbits; |
924 | }()); | 946 | }()); |
web/static/js/swapp.ls
@@ -700,7 +700,15 @@ export class Orbits | @@ -700,7 +700,15 @@ export class Orbits | ||
700 | @resize() | 700 | @resize() |
701 | 701 | ||
702 | initOrbiter: (slug, config, data) -> | 702 | initOrbiter: (slug, config, data) -> |
703 | - console.info "Initializing orbit of #{config.name}…" | 703 | + @data[slug] = data |
704 | + @orbiters[slug] = config | ||
705 | + | ||
706 | + if data.length | ||
707 | + console.info "Initializing orbit of #{config.name}…" | ||
708 | + else | ||
709 | + console.warn "No orbit data for #{config.name}…" | ||
710 | + return | ||
711 | + | ||
704 | if slug of @orbitersElements then throw new Error("Second init of #{slug}") | 712 | if slug of @orbitersElements then throw new Error("Second init of #{slug}") |
705 | 713 | ||
706 | # The order is important, as it will define the default z-order | 714 | # The order is important, as it will define the default z-order |
@@ -719,8 +727,6 @@ export class Orbits | @@ -719,8 +727,6 @@ export class Orbits | ||
719 | .datum(data) | 727 | .datum(data) |
720 | .classed('orbit orbit_section', true) | 728 | .classed('orbit orbit_section', true) |
721 | 729 | ||
722 | - @data[slug] = data | ||
723 | - @orbiters[slug] = config | ||
724 | @orbitersElements[slug] = | 730 | @orbitersElements[slug] = |
725 | orbiter: orbiter | 731 | orbiter: orbiter |
726 | orbit_ellipse: orbit_ellipse | 732 | orbit_ellipse: orbit_ellipse |
@@ -737,6 +743,7 @@ export class Orbits | @@ -737,6 +743,7 @@ export class Orbits | ||
737 | this | 743 | this |
738 | 744 | ||
739 | showOrbiter: (slug) -> | 745 | showOrbiter: (slug) -> |
746 | + if not @data[slug].length then return | ||
740 | @orbiters[slug].hidden = false | 747 | @orbiters[slug].hidden = false |
741 | @orbitersElements[slug].orbiter.style("display", null) | 748 | @orbitersElements[slug].orbiter.style("display", null) |
742 | @orbitersElements[slug].orbit_ellipse.style("display", null) | 749 | @orbitersElements[slug].orbit_ellipse.style("display", null) |
@@ -744,6 +751,7 @@ export class Orbits | @@ -744,6 +751,7 @@ export class Orbits | ||
744 | @resize(true) | 751 | @resize(true) |
745 | 752 | ||
746 | hideOrbiter: (slug) -> | 753 | hideOrbiter: (slug) -> |
754 | + if not @data[slug].length then return | ||
747 | @orbiters[slug].hidden = true | 755 | @orbiters[slug].hidden = true |
748 | @orbitersElements[slug].orbiter.style("display", "none") | 756 | @orbitersElements[slug].orbiter.style("display", "none") |
749 | @orbitersElements[slug].orbit_ellipse.style("display", "none") | 757 | @orbitersElements[slug].orbit_ellipse.style("display", "none") |
@@ -797,6 +805,8 @@ export class Orbits | @@ -797,6 +805,8 @@ export class Orbits | ||
797 | this | 805 | this |
798 | 806 | ||
799 | resizeOrbiter: (slug, config, width, height, animate = false) -> | 807 | resizeOrbiter: (slug, config, width, height, animate = false) -> |
808 | + data = @data[slug] | ||
809 | + if not data.length then return | ||
800 | console.debug("Resizing orbit of #{slug}…") | 810 | console.debug("Resizing orbit of #{slug}…") |
801 | 811 | ||
802 | tt = @svg.transition().duration(750) | 812 | tt = @svg.transition().duration(750) |
@@ -830,6 +840,7 @@ export class Orbits | @@ -830,6 +840,7 @@ export class Orbits | ||
830 | 840 | ||
831 | repositionOrbiter: (slug, datum, animate = false) -> | 841 | repositionOrbiter: (slug, datum, animate = false) -> |
832 | data = @data[slug] | 842 | data = @data[slug] |
843 | + if not data.length then return | ||
833 | datum ?= @lastOrbiterData[slug] | 844 | datum ?= @lastOrbiterData[slug] |
834 | datum ?= data[data.length - 1] | 845 | datum ?= data[data.length - 1] |
835 | @lastOrbiterData[slug] = datum | 846 | @lastOrbiterData[slug] = datum |
@@ -859,12 +870,14 @@ export class Orbits | @@ -859,12 +870,14 @@ export class Orbits | ||
859 | for slug, config of @orbiters | 870 | for slug, config of @orbiters |
860 | el = @orbitersElements[slug] | 871 | el = @orbitersElements[slug] |
861 | data = @data[slug].filter (d) -> started_at <= d.t <= stopped_at | 872 | data = @data[slug].filter (d) -> started_at <= d.t <= stopped_at |
873 | + if not data.length then return | ||
862 | el['orbit_section'].datum(data) | 874 | el['orbit_section'].datum(data) |
863 | el['orbit_section'].attr('d', el['orbit_line']) | 875 | el['orbit_section'].attr('d', el['orbit_line']) |
864 | 876 | ||
865 | resetZoom: -> | 877 | resetZoom: -> |
866 | for slug, config of @orbiters | 878 | for slug, config of @orbiters |
867 | el = @orbitersElements[slug] | 879 | el = @orbitersElements[slug] |
880 | + if not @data[slug].length then return | ||
868 | el['orbit_section'].datum(@data[slug]) | 881 | el['orbit_section'].datum(@data[slug]) |
869 | el['orbit_section'].attr('d', el['orbit_line']) | 882 | el['orbit_section'].attr('d', el['orbit_line']) |
870 | 883 |
web/view/home.html.jinja2
@@ -116,7 +116,7 @@ | @@ -116,7 +116,7 @@ | ||
116 | <section id="orbits"></section> | 116 | <section id="orbits"></section> |
117 | <div class="plots-actions plots-buttons"> | 117 | <div class="plots-actions plots-buttons"> |
118 | <button id="download" class="mdl-button mdl-button--raised mdl-button--primary" | 118 | <button id="download" class="mdl-button mdl-button--raised mdl-button--primary" |
119 | - title="Download the CSV raw data for each target in a tarball."> | 119 | + title="Download the raw data for each selected target and parameters."> |
120 | Download | 120 | Download |
121 | </button> | 121 | </button> |
122 | <button id="samp" class="samp mdl-button mdl-button--raised mdl-button--primary mdl-button--disabled" | 122 | <button id="samp" class="samp mdl-button mdl-button--raised mdl-button--primary mdl-button--disabled" |
@@ -535,7 +535,7 @@ var configuration = { | @@ -535,7 +535,7 @@ var configuration = { | ||
535 | orbits_container: '#orbits', | 535 | orbits_container: '#orbits', |
536 | api: { | 536 | api: { |
537 | 'data_for_interval': "{{ request.url_root }}<target>_<started_at>_<stopped_at>.csv", | 537 | 'data_for_interval': "{{ request.url_root }}<target>_<started_at>_<stopped_at>.csv", |
538 | - 'download': "{{ request.url_root }}<targets>_<started_at>_<stopped_at>.tar.gz", | 538 | + 'download': "{{ request.url_root }}<targets>_<started_at>_<stopped_at>.nc", |
539 | 'samp': "{{ request.url_root }}<targets>_<params>_<started_at>_<stopped_at>.nc" | 539 | 'samp': "{{ request.url_root }}<targets>_<params>_<started_at>_<stopped_at>.nc" |
540 | }, | 540 | }, |
541 | sun: { | 541 | sun: { |