Commit 8cb213b9cdde708744ef200a804b91b568ef23dd
1 parent
b60e7acd
Exists in
master
and in
3 other branches
Clean up, and prepare the temporal domain resizing architecture.
Showing
3 changed files
with
85 additions
and
41 deletions
Show diff stats
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', | ... | ... |