Commit dc0be9925d35db1001545592b3b2bebe31a70421

Authored by Goutte
1 parent ff3519a8

Support having no position to display (for Rosetta in some intervals)

Make the local cache more resilient to corrupted downloads
@@ -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
@@ -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'
@@ -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

2.35 KB | W: | H:

3.65 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
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: {