Commit 8cb213b9cdde708744ef200a804b91b568ef23dd

Authored by Goutte
1 parent b60e7acd

Clean up, and prepare the temporal domain resizing architecture.

web/static/js/swapp.js
... ... @@ -20,7 +20,7 @@
20 20 function SpaceWeather(configuration){
21 21 var configs, res$, k, this$ = this;
22 22 this.configuration = configuration;
23   - console.info("Creating Heliopropa app...", this.configuration);
  23 + console.info("Creating HelioPropa app...", this.configuration);
24 24 this.targets = {};
25 25 res$ = [];
26 26 for (k in this.configuration.targets) {
... ... @@ -46,10 +46,10 @@
46 46 }
47 47 active_targets = res$;
48 48 this.orbits = new Orbits(this.configuration.orbits_container, this.configuration);
49   - started_at = moment().subtract(1, 'years').hours(0).minutes(0).seconds(0);
50   - stopped_at = moment().add(7, 'days').hours(0).minutes(0).seconds(0);
51   - started_at = started_at.format("YYYY-MM-DDTHH:mm:ss");
52   - stopped_at = stopped_at.format("YYYY-MM-DDTHH:mm:ss");
  49 + this.started_at = moment().subtract(1, 'years').hours(0).minutes(0).seconds(0);
  50 + this.stopped_at = moment().add(7, 'days').hours(0).minutes(0).seconds(0);
  51 + started_at = this.started_at.format("YYYY-MM-DDTHH:mm:ss");
  52 + stopped_at = this.stopped_at.format("YYYY-MM-DDTHH:mm:ss");
53 53 active_targets.forEach(function(target){
54 54 return this$.loadData(target.slug, started_at, stopped_at).then(function(data){
55 55 console.info("Loaded CSV data for " + target.slug + ".");
... ... @@ -209,6 +209,25 @@
209 209 });
210 210 return this;
211 211 };
  212 + SpaceWeather.prototype.resizeDomain = function(started_at, stopped_at){
  213 + var tmp;
  214 + if (stopped_at < started_at) {
  215 + tmp = started_at;
  216 + started_at = stopped_at;
  217 + stopped_at = started_at;
  218 + }
  219 + if (started_at === stopped_at) {
  220 + console.warn("Please provide different start and stop dates.");
  221 + return;
  222 + }
  223 + if ((this.started_at <= started_at && started_at <= this.stopped_at) && (this.started_at <= stopped_at && stopped_at <= this.stopped_at)) {
  224 + console.info("Resizing the temporal domain without fetching new data...");
  225 + timeSeries.forEach(function(ts){
  226 + return ts.resizeDomain(started_at, stopped_at);
  227 + });
  228 + this.orbits.resizeDomain(started_at, stopped_at);
  229 + }
  230 + };
212 231 return SpaceWeather;
213 232 }());
214 233 out$.TimeSeries = TimeSeries = (function(){
... ... @@ -227,16 +246,11 @@
227 246 this.onMouseOut = bind$(this, 'onMouseOut', prototype);
228 247 this.onMouseOver = bind$(this, 'onMouseOver', prototype);
229 248 this.onMouseMove = bind$(this, 'onMouseMove', prototype);
230   - if (this.active) {
231   - console.info("Creating time series '" + this.title + "'...");
232   - } else {
233   - console.info("Creating inactive time series '" + this.title + "'...");
234   - }
235 249 this.init();
236 250 }
237 251 TimeSeries.prototype.init = function(){
238 252 var dx, this$ = this;
239   - console.info("Initializing time series '" + this.title + "'...", this.data, this.options);
  253 + console.info("Initializing time series " + this.title + " of " + this.target + "...");
240 254 this.margin = {
241 255 top: 30,
242 256 right: 20,
... ... @@ -282,7 +296,7 @@
282 296 height = GOLDEN_RATIO * GOLDEN_RATIO * GOLDEN_RATIO * GOLDEN_RATIO * width;
283 297 this.plotWidth = width;
284 298 this.plotHeight = height;
285   - console.log("Resizing time series " + this.title + " : " + width + " x " + height);
  299 + console.log("Resizing time series " + this.title + " of " + this.target + ": " + width + " x " + height);
286 300 this.xScale.range([0, width]);
287 301 this.yScale.range([height, 0]);
288 302 this.svg.attr('width', width + this.margin.right + this.margin.left).attr('height', height + this.margin.top + this.margin.bottom);
... ... @@ -301,6 +315,7 @@
301 315 }
302 316 return this;
303 317 };
  318 + TimeSeries.prototype.resizeDomain = function(started_at, stopped_at){};
304 319 TimeSeries.prototype.onMouseMove = function(){
305 320 var x;
306 321 x = this.xScale.invert(d3.mouse(this.mouseCanvas.node())[0]);
... ... @@ -335,7 +350,7 @@
335 350 }).left;
336 351 TimeSeries.prototype.timeFormat = d3.timeFormat("%Y-%m-%d %Hh");
337 352 TimeSeries.prototype.moveCursor = function(x0){
338   - var i, d0, d1, d, xx, yy, transform, mirrored, dx;
  353 + var i, d0, d1, d, xx, yy, mirrored, dx, transform;
339 354 i = this.bisectDate(this.data, x0, 1);
340 355 d0 = this.data[i - 1];
341 356 d1 = this.data[i];
... ... @@ -345,12 +360,12 @@
345 360 d = x0 - d0.x > d1.x - x0 ? d1 : d0;
346 361 xx = this.xScale(d.x);
347 362 yy = this.yScale(d.y);
348   - transform = "translate(" + xx + ", " + yy + ")";
349 363 mirrored = this.plotWidth != null && xx > this.plotWidth / 2 ? true : false;
350 364 dx = 8;
351 365 if (mirrored) {
352 366 dx = -1 * dx;
353 367 }
  368 + transform = "translate(" + xx + ", " + yy + ")";
354 369 this.cursorCircle.attr("transform", transform);
355 370 this.cursorValue.attr("transform", transform).text(d.y).attr('text-anchor', mirrored ? 'end' : 'start').attr("dx", dx);
356 371 this.cursorValueShadow.attr("transform", transform).text(d.y).attr('text-anchor', mirrored ? 'end' : 'start').attr("dx", dx);
... ... @@ -361,6 +376,7 @@
361 376 return TimeSeries;
362 377 }());
363 378 out$.Orbits = Orbits = (function(){
  379 + "View of the solar system from above, with orbits segments for selected time\ninterval, from real data.";
364 380 Orbits.displayName = 'Orbits';
365 381 var prototype = Orbits.prototype, constructor = Orbits;
366 382 function Orbits(container, options){
... ... @@ -403,6 +419,7 @@
403 419 this.yAxisTitle.attr('transform', 'rotate(-90)');
404 420 this.sun = this.plotWrapper.append("svg:image").attr('xlink:href', this.options.sun.img).attr('width', '32px').attr('height', '32px');
405 421 this.sun.append('svg:title').text("Sol");
  422 + $(this.svg.node).hide();
406 423 return this.resize();
407 424 };
408 425 Orbits.prototype.orbitersElements = {};
... ... @@ -434,13 +451,13 @@
434 451 orbit_line: orbit_line
435 452 };
436 453 this.resize();
  454 + $(this.svg.node).show();
437 455 return this;
438 456 };
439 457 Orbits.prototype.resize = function(){
440 458 var width, height, slug, ref$, config;
441 459 width = jQuery(this.container).width() - this.margin.left - this.margin.right;
442 460 height = 1.0 * width;
443   - console.log("Resize orbits : " + width + " x " + height);
444 461 this.xScale.range([0, width]);
445 462 this.yScale.range([height, 0]);
446 463 this.svg.attr('width', width + this.margin.right + this.margin.left).attr('height', height + this.margin.top + this.margin.bottom);
... ... @@ -508,6 +525,7 @@
508 525 }
509 526 return this;
510 527 };
  528 + Orbits.prototype.resizeDomain = function(started_at, stopped_at){};
511 529 return Orbits;
512 530 }());
513 531 function bind$(obj, key, target){
... ...
web/static/js/swapp.ls
1 1 # Livescript transpiles to javascript, and is easier on the eyes and brain.
2 2 # Get the `lsc` binary from here : http://livescript.net
  3 +# It is quite close to Python, syntax-wise, and full of sugar.
3 4  
4 5 # To transpile this file to javascript, and generate `swapp.js` :
5 6 # $ lsc --compile swapp.ls
... ... @@ -9,7 +10,7 @@
9 10 # All the "javascript" code is in this file, except for inline scripts in
10 11 # templates, such as `home.html.jinja2`.
11 12  
12   -# Note: We use Promises and ES6 whenever we can.
  13 +# Note: We use Promises and ES6 whenever relevant.
13 14  
14 15 ###############################################################################
15 16  
... ... @@ -30,7 +31,7 @@ export class SpaceWeather
30 31 """
31 32  
32 33 (@configuration) ->
33   - console.info "Creating Heliopropa app...", @configuration
  34 + console.info "Creating HelioPropa app...", @configuration
34 35 @targets = {}
35 36 configs = [@configuration.targets[k] for k of @configuration.targets]
36 37 configs.forEach((target_config) ~>
... ... @@ -50,10 +51,10 @@ export class SpaceWeather
50 51 active_targets = [ @targets[k] for k of @targets when @targets[k].config.active ]
51 52 @orbits = new Orbits(@configuration.orbits_container, @configuration)
52 53 # Set the h/m/s to zero so that files are cached per whole days
53   - started_at = moment().subtract(1, 'years').hours(0).minutes(0).seconds(0)
54   - stopped_at = moment().add(7, 'days').hours(0).minutes(0).seconds(0)
55   - started_at = started_at.format("YYYY-MM-DDTHH:mm:ss")
56   - stopped_at = stopped_at.format("YYYY-MM-DDTHH:mm:ss")
  54 + @started_at = moment().subtract(1, 'years').hours(0).minutes(0).seconds(0)
  55 + @stopped_at = moment().add(7, 'days').hours(0).minutes(0).seconds(0)
  56 + started_at = @started_at.format("YYYY-MM-DDTHH:mm:ss")
  57 + stopped_at = @stopped_at.format("YYYY-MM-DDTHH:mm:ss")
57 58 active_targets.forEach((target) ~>
58 59 @loadData(target.slug, started_at, stopped_at).then(
59 60 (data) ~>
... ... @@ -124,7 +125,7 @@ export class SpaceWeather
124 125 )
125 126 promise
126 127  
127   - timeSeries = []
  128 + timeSeries = [] # Not sure why this ain't an instance prop. Probably should.
128 129 createTimeSeries: (target, data) ->
129 130 @configuration['parameters'].forEach((parameter) ~>
130 131 container = @configuration['time_series_container']
... ... @@ -154,6 +155,26 @@ export class SpaceWeather
154 155 timeSeries.forEach((ts) -> $(ts.svg.node()).hide() if ts.parameter == parameter_slug)
155 156 this
156 157  
  158 + resizeDomain: (started_at, stopped_at) ->
  159 + if stopped_at < started_at
  160 + tmp = started_at
  161 + started_at = stopped_at
  162 + stopped_at = started_at
  163 +
  164 + if started_at == stopped_at
  165 + console.warn "Please provide different start and stop dates."
  166 + return
  167 +
  168 + if (@started_at <= started_at <= @stopped_at) and (@started_at <= stopped_at <= @stopped_at)
  169 + console.info "Resizing the temporal domain without fetching new data..."
  170 + timeSeries.forEach((ts) -> ts.resizeDomain started_at, stopped_at)
  171 + @orbits.resizeDomain started_at, stopped_at
  172 + return
  173 +
  174 + # todo: fetch new data and remake the plots
  175 +
  176 +
  177 +
157 178  
158 179 ###############################################################################
159 180 ###############################################################################
... ... @@ -166,14 +187,12 @@ export class TimeSeries
166 187 (@parameter, @title, @target, @data, @active, @container, @options = {}) ->
167 188 # parameter : slug of the parameter to observe, like magn or pdyn
168 189 # title : string
169   - # target : slug of the TARGET, like jupiter or tchouri
  190 + # target : slug of the target, like jupiter or tchouri
170 191 # data : list of {x: <datetime>, y: <float>}
171   - if @active then console.info "Creating time series '#{@title}'..."
172   - else console.info "Creating inactive time series '#{@title}'..."
173 192 @init()
174 193  
175 194 init: ->
176   - console.info "Initializing time series '#{@title}'...", @data, @options
  195 + console.info "Initializing time series #{@title} of #{@target}..."
177 196  
178 197 @margin = {
179 198 top: 30,
... ... @@ -190,7 +209,6 @@ export class TimeSeries
190 209 @xAxis = d3.axisBottom()
191 210 .tickFormat(d3.timeFormat("%Y-%m-%d"))
192 211 .ticks(7)
193   -# .ticks(7, ",f")
194 212 @yAxis = d3.axisLeft()
195 213 .ticks(10)
196 214  
... ... @@ -267,7 +285,7 @@ export class TimeSeries
267 285 @plotWidth = width
268 286 @plotHeight = height
269 287  
270   - console.log("Resizing time series #{@title} : #{width} x #{height}")
  288 + console.log("Resizing time series #{@title} of #{@target}: #{width} x #{height}")
271 289  
272 290 @xScale.range([0, width]);
273 291 @yScale.range([height, 0]);
... ... @@ -304,6 +322,9 @@ export class TimeSeries
304 322 unless @active then $(@svg.node()).hide()
305 323 this
306 324  
  325 + resizeDomain: (started_at, stopped_at) ->
  326 + # fixme
  327 +
307 328 onMouseMove: ~>
308 329 x = @xScale.invert(d3.mouse(@mouseCanvas.node())[0])
309 330 if @options.onMouseMove?
... ... @@ -329,7 +350,7 @@ export class TimeSeries
329 350 hideCursor: ->
330 351 @focus.style("display", "none")
331 352  
332   - bisectDate: d3.bisector((d) -> d.x).left # /!\ complex
  353 + bisectDate: d3.bisector((d) -> d.x).left # /!\ complex
333 354 timeFormat: d3.timeFormat("%Y-%m-%d %Hh")
334 355  
335 356 moveCursor: (x0) ->
... ... @@ -341,14 +362,12 @@ export class TimeSeries
341 362 xx = @xScale(d.x)
342 363 yy = @yScale(d.y)
343 364  
344   - transform = "translate(#{xx}, #{yy})"
345   -
346 365 mirrored = if @plotWidth? and xx > @plotWidth / 2 then true else false
347   -# console.log("xx", xx)
348 366  
349   - dx = 8
  367 + dx = 8 # horizontal delta between the dot and the text
350 368 dx = -1 * dx if mirrored
351 369  
  370 + transform = "translate(#{xx}, #{yy})"
352 371 @cursorCircle.attr("transform", transform)
353 372 @cursorValue.attr("transform", transform).text(d.y)
354 373 .attr('text-anchor', if mirrored then 'end' else 'start')
... ... @@ -370,8 +389,10 @@ export class TimeSeries
370 389 ###############################################################################
371 390  
372 391 export class Orbits
373   - # View of the solar system from above, with orbits segments for selected time
374   - # interval, from real data.
  392 + """
  393 + View of the solar system from above, with orbits segments for selected time
  394 + interval, from real data.
  395 + """
375 396  
376 397 (@container, @options = {}) ->
377 398 @init()
... ... @@ -424,9 +445,7 @@ export class Orbits
424 445 .attr('width', '32px').attr('height', '32px')
425 446 @sun.append('svg:title').text("Sol")
426 447  
427   -# for slug, config of @orbiters
428   -# @initOrbiter(slug, config)
429   -
  448 + $(@svg.node).hide(); # we'll show it later when there'll be data
430 449 @resize()
431 450  
432 451 orbitersElements: {}
... ... @@ -465,13 +484,15 @@ export class Orbits
465 484  
466 485 @resize()
467 486  
  487 + $(@svg.node).show();
  488 +
468 489 this
469 490  
470 491 resize: ->
471 492 width = jQuery(@container).width() - @margin.left - @margin.right
472 493 height = 1.0 * width
473 494  
474   - console.log("Resize orbits : #{width} x #{height}")
  495 + #console.log("Resizing orbits : #{width} x #{height}")
475 496  
476 497 @xScale.range([0, width]);
477 498 @yScale.range([height, 0]);
... ... @@ -548,7 +569,10 @@ export class Orbits
548 569 d1 = data[i]
549 570 continue unless d1 and d0
550 571 d = if t - d0.t > d1.t - t then d1 else d0
551   - @repositionOrbiter(slug, d) # fixme
  572 + @repositionOrbiter(slug, d) # fixme <--(why?)
552 573 this
553 574  
  575 + resizeDomain: (started_at, stopped_at) ->
  576 + # fixme
  577 +
554 578  
... ...
web/view/home.html.jinja2
... ... @@ -45,6 +45,7 @@
45 45 <span class="mdl-layout-title">Parameters</span>
46 46  
47 47 <nav id="parameters" class="mdl-navigation">
  48 + {# todo: generate this from config #}
48 49 <a class="mdl-navigation__link parameter active" data-ts-slug="pdyn" href="#">Dynamic Pressure</a>
49 50 <a class="mdl-navigation__link parameter" data-ts-slug="magn" href="#">B Tangential</a>
50 51 <a class="mdl-navigation__link parameter" data-ts-slug="vlen" href="#">Velocity</a>
... ... @@ -202,7 +203,8 @@ var configuration = {
202 203 {# img: '{{ static('img/target/jupiter_128.png') }}'#}
203 204 {# },#}
204 205 },
205   -{# todo @Nicolas Define -somehow- error margins of each parameter #}
  206 +{# todo @Nicolas Define -somehow- error margins of each parameter ? #}
  207 +{# todo: generate this from config #}
206 208 parameters : [
207 209 {
208 210 id: 'pdyn',
... ...