Commit 1185f3539dbfab249ec9cc9e2d4a7adef0545e56

Authored by Goutte
1 parent 03452084

Fix the CME Catalogs and continue THE GREAT REFACTO

CHANGELOG.md
... ... @@ -29,7 +29,6 @@ et prendre aussi
29 29  
30 30 ## Future ?
31 31  
32   -- [ ] Re-enable Earth
33 32 - [ ] Enable p67
34 33 - [ ] Layer : Auroral Emissions
35 34 - [ ] Set the log level to _error_ in production (see `web/run.py`)
... ... @@ -39,6 +38,12 @@ et prendre aussi
39 38 - [ ] IE compat, if you can (I can't)
40 39  
41 40  
  41 +## 1.6
  42 +
  43 +- [x] Re-enable Earth
  44 +- [x] Layer : CME Catalogs
  45 +
  46 +
42 47 ## 1.5
43 48  
44 49 - [x] Use the new AMDA API
... ...
config.yml
... ... @@ -69,6 +69,7 @@ layers:
69 69 file: "ICME_WP4_V10.json"
70 70 start: "ICME_START_TIME"
71 71 stop: "MO_END_TIME"
  72 + format: "%Y-%m-%dT%H:%MZ"
72 73 l1:
73 74 venus:
74 75 constraints: [ { SC_INSITU: ["VEX"] } ]
... ... @@ -78,6 +79,7 @@ layers:
78 79 url: "https://www.helcats-fp7.eu/catalogues/data/HCME_WP4_V6.json"
79 80 file: "HCME_WP4_V6.json"
80 81 start: "TARGET_ARRIVAL"
  82 + format: "%Y-%m-%dT%H:%MZ"
81 83 l1:
82 84 mars:
83 85 constraints: [ { TARGET_NAME: ["MARS", "MAVEN", "MSC"] } ]
... ... @@ -85,6 +87,7 @@ layers:
85 87 url: "https://cdaw.gsfc.nasa.gov/CME_list/UNIVERSAL/text_ver/univ_all.txt"
86 88 file: "univ_all.json"
87 89 start: "DATETIME"
  90 + format: "%Y-%m-%dT%H:%M:%S"
88 91 l1:
89 92 earth: ~
90 93  
... ...
web/run.py
... ... @@ -44,6 +44,7 @@ with open(get_path('../config.yml'), 'r') as config_file:
44 44 config = yaml_load(config_file.read())
45 45  
46 46 FILE_DATE_FMT = "%Y-%m-%dT%H:%M:%S"
  47 +MOMENT_DATE_FMT = "%Y-%m-%dT%H:%M:%SZ"
47 48  
48 49  
49 50 # LOGGING #####################################################################
... ... @@ -802,7 +803,7 @@ def get_interval_from_query():
802 803 return started_at, stopped_at
803 804  
804 805  
805   -def get_catalog_layers(input_slug, target_slug):
  806 +def get_catalog_layers(input_slug, target_slug, started_at, stopped_at):
806 807 """
807 808 In the JSON file we have "columns" and "data".
808 809 Of course, each JSON file has its own columns, with different conventions.
... ... @@ -821,6 +822,15 @@ def get_catalog_layers(input_slug, target_slug):
821 822 raise
822 823 return index
823 824  
  825 + try:
  826 + started_at = datetime.datetime.strptime(started_at, FILE_DATE_FMT)
  827 + except:
  828 + abort(400, "Invalid started_at parameter : '%s'." % started_at)
  829 + try:
  830 + stopped_at = datetime.datetime.strptime(stopped_at, FILE_DATE_FMT)
  831 + except:
  832 + abort(400, "Invalid stopped_at parameter : '%s'." % stopped_at)
  833 +
824 834 catalog_layers = {}
825 835 for config_layer in config['layers']:
826 836 if 'data' not in config_layer:
... ... @@ -836,11 +846,15 @@ def get_catalog_layers(input_slug, target_slug):
836 846 constraints = []
837 847 else:
838 848 constraints = cl_datum[input_slug][target_slug]['constraints']
  849 +
839 850 with open(get_path("../data/catalog/%s" % cl_datum['file'])) as f:
840 851 json_data = json.load(f)
841 852 if 'start' not in cl_datum:
842 853 log.error("Invalid configuration: 'start' is missing.")
843 854 continue # skip this
  855 + if 'format' not in cl_datum:
  856 + log.error("Invalid configuration: 'format' is missing.")
  857 + continue # skip this
844 858 start_index = _get_index_of_key(json_data, cl_datum['start'])
845 859 if 'stop' not in cl_datum:
846 860 stop_index = start_index
... ... @@ -867,9 +881,20 @@ def get_catalog_layers(input_slug, target_slug):
867 881 continue
868 882 start_time = json_datum[start_index]
869 883 stop_time = json_datum[stop_index]
  884 +
  885 + start_time = datetime.datetime.strptime(
  886 + start_time, cl_datum['format']
  887 + )
  888 + stop_time = datetime.datetime.strptime(
  889 + stop_time, cl_datum['format']
  890 + )
  891 +
  892 + if start_time < started_at:
  893 + continue
  894 +
870 895 catalog_layers[config_layer['slug']].append({
871   - 'start': start_time,
872   - 'stop': stop_time,
  896 + 'start': start_time.strftime(MOMENT_DATE_FMT),
  897 + 'stop': stop_time.strftime(MOMENT_DATE_FMT),
873 898 })
874 899  
875 900 return catalog_layers
... ... @@ -940,7 +965,7 @@ def home():
940 965 started_at, stopped_at = get_interval_from_query()
941 966 for i, target in enumerate(targets):
942 967 targets[i]['catalog_layers'] = get_catalog_layers(
943   - input_slug, target['slug']
  968 + input_slug, target['slug'], started_at, stopped_at
944 969 )
945 970 return render_view('home.html.jinja2', {
946 971 # 'targets': config['targets'],
... ...
web/static/js/main.js
... ... @@ -71,12 +71,12 @@
71 71  
72 72 init(started_at, stopped_at) {
73 73 // "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)";
74   - const this$ = this;
  74 + const app = this;
75 75 started_at = moment(started_at).hours(0).minutes(0).seconds(0);
76 76 stopped_at = moment(stopped_at).hours(0).minutes(0).seconds(0);
77 77 this.setStartAndStop(started_at, stopped_at);
78 78 this.loadAndCreatePlots(started_at, stopped_at);
79   - window.addEventListener('resize', () => this$.resize());
  79 + window.addEventListener('resize', () => app.resize());
80 80 return this;
81 81 }
82 82  
... ... @@ -219,9 +219,8 @@
219 219 }
220 220  
221 221 resize() {
222   - let ref$;
223   - if ((ref$ = this.orbits) != null) {
224   - ref$.resize();
  222 + if (null != this.orbits) {
  223 + this.orbits.resize();
225 224 }
226 225 this.time_series.forEach(ts => ts.resize());
227 226 return this;
... ... @@ -401,7 +400,7 @@
401 400 return true;
402 401 }).bind(ts);
403 402  
404   - return ts.options['onDblClick'] = () => {
  403 + ts.options['onDblClick'] = () => {
405 404 let ref$;
406 405 app.resetZoom();
407 406 if ((ref$ = $("#zoom_controls_help")) != null) {
... ... @@ -506,6 +505,7 @@
506 505 let starting_ts_key = tsv.indexOf(starting_ts);
507 506 if (starting_ts_key === -1) starting_ts_key = 0;
508 507 zoomedOnVisible = new Promise((resolve, reject) => {
  508 + console.log("Zoom on invisible time series…");
509 509 let tsv_zoom_on_next;
510 510 tsv_zoom_on_next = i => {
511 511 let ts;
... ... @@ -517,9 +517,10 @@
517 517 ts.zoomIn(started_at, stopped_at)
518 518 .then(() => tsv_zoom_on_next(i + 1));
519 519 };
520   - return tsv_zoom_on_next(0);
  520 + tsv_zoom_on_next(0);
521 521 });
522 522 zoomedOnVisible.then(() => {
  523 + console.log("Now zoom on invisible time series…");
523 524 this.time_series.forEach(ts => {
524 525 if (!ts.visible) {
525 526 ts.zoomIn(started_at, stopped_at);
... ... @@ -843,13 +844,12 @@
843 844 }
844 845  
845 846 applyZoom() {
846   - let duration;
847   - let t;
  847 + let duration = 0;
848 848 duration = 0;
849 849 if (this.visible) {
850 850 duration = 750;
851 851 console.debug(`Applying zoom to visible ${this}…`);
852   - t = this.svg.transition().duration(duration);
  852 + let t = this.svg.transition().duration(duration);
853 853 this.svg.select('.x.axis').transition(t).call(this.xAxis);
854 854 this.svg.select('.y.axis').transition(t).call(this.yAxis);
855 855 this.path.transition(t).attr('d', this.line);
... ... @@ -1095,7 +1095,7 @@
1095 1095 return this.hideOrbiter(slug);
1096 1096 }
1097 1097  
1098   - showOrbiter(slug) {
  1098 + showOrbiter(slug, doResize=true) {
1099 1099 if (!this.data[slug].length) {
1100 1100 return;
1101 1101 }
... ... @@ -1106,7 +1106,9 @@
1106 1106 this.orbitersElements[slug].orbiter.style("display", null);
1107 1107 this.orbitersElements[slug].orbit_ellipse.style("display", null);
1108 1108 this.orbitersElements[slug].orbit_section.style("display", null);
1109   - return this.resize(true);
  1109 + if (doResize) this.resize(true);
  1110 +
  1111 + return this;
1110 1112 }
1111 1113  
1112 1114 hideOrbiter(slug) {
... ... @@ -1136,7 +1138,7 @@
1136 1138 extremum == null && (extremum = null);
1137 1139 const width = Math.ceil($(this.container).width() - this.margin.left - this.margin.right);
1138 1140 const height = width; // it's a square
1139   - console.debug(`Resizing orbits : ${width} × ${height}…`);
  1141 + console.debug(`Resizing orbits : ${width} × ${height}… (animated: ${animate})`);
1140 1142 if (extremum === null) {
1141 1143 extremum = 1.1 * d3.max((function () {
1142 1144 let ref$;
... ... @@ -1272,25 +1274,24 @@
1272 1274 }
1273 1275  
1274 1276 resizeDomain(started_at, stopped_at) {
1275   - let slug;
1276   - let ref$;
1277 1277 let config;
1278 1278 let el;
1279 1279 let data;
1280   - const results$ = [];
1281   - for (slug in ref$ = this.orbiters) {
1282   - config = ref$[slug];
  1280 + for (let slug in this.orbiters) {
  1281 + config = this.orbiters[slug];
1283 1282 el = this.orbitersElements[slug];
1284 1283 data = this.data[slug].filter(onlyDataInRange);
1285   - if (!data.length) {
  1284 + if ( ! data.length) {
1286 1285 this.hideOrbiter(slug);
1287 1286 continue;
1288 1287 }
1289 1288 el['orbit_section'].datum(data);
1290 1289 el['orbit_section'].attr('d', el['orbit_line']);
1291   - results$.push(this.showOrbiter(slug));
  1290 + this.showOrbiter(slug, false);
1292 1291 }
1293   - return results$;
  1292 + this.resize(true);
  1293 +
  1294 + return this;
1294 1295  
1295 1296 function onlyDataInRange(d) {
1296 1297 return started_at <= d.t && d.t <= stopped_at;
... ...