Commit ae0aa7d28cb17e91bc39216bf40b6392aac5b3f8

Authored by Goutte
1 parent ebf98c26

Add an x axis label for the orbits graph.

web/static/js/swapp.js
1 1 // Generated by LiveScript 1.5.0
2 2 (function(){
3   - var GOLDEN_RATIO, TimeSeries, Orbits, out$ = typeof exports != 'undefined' && exports || this;
  3 + var GOLDEN_RATIO, SpaceWeather, Source, TimeSeries, Orbits, out$ = typeof exports != 'undefined' && exports || this;
4 4 GOLDEN_RATIO = 2 / (1 + Math.sqrt(5));
  5 + out$.SpaceWeather = SpaceWeather = (function(){
  6 + SpaceWeather.displayName = 'SpaceWeather';
  7 + var prototype = SpaceWeather.prototype, constructor = SpaceWeather;
  8 + function SpaceWeather(configuration){
  9 + console.info("Creating Space Weather app...", configuration);
  10 + }
  11 + return SpaceWeather;
  12 + }());
  13 + Source = (function(){
  14 + Source.displayName = 'Source';
  15 + var prototype = Source.prototype, constructor = Source;
  16 + function Source(slug){
  17 + this.slug = slug;
  18 + this.time_series = {};
  19 + }
  20 + Source.prototype.addTimeSeries = function(ts){
  21 + return this.time_series[ts.slug] = ts;
  22 + };
  23 + Source.prototype.show = function(){
  24 + var slug, ref$, ts, results$ = [];
  25 + for (slug in ref$ = this.time_series) {
  26 + ts = ref$[slug];
  27 + results$.push($(ts.svg).show());
  28 + }
  29 + return results$;
  30 + };
  31 + Source.prototype.hide = function(){
  32 + var slug, ref$, ts, results$ = [];
  33 + for (slug in ref$ = this.time_series) {
  34 + ts = ref$[slug];
  35 + results$.push($(ts.svg).hide());
  36 + }
  37 + return results$;
  38 + };
  39 + return Source;
  40 + }());
5 41 out$.TimeSeries = TimeSeries = (function(){
6 42 TimeSeries.displayName = 'TimeSeries';
7 43 var prototype = TimeSeries.prototype, constructor = TimeSeries;
... ... @@ -16,12 +52,12 @@
16 52 this.onMouseOut = bind$(this, 'onMouseOut', prototype);
17 53 this.onMouseOver = bind$(this, 'onMouseOver', prototype);
18 54 this.onMouseMove = bind$(this, 'onMouseMove', prototype);
19   - console.log("Create time series '" + this.title + "'");
  55 + console.info("Creating time series '" + this.title + "'...");
20 56 this.init();
21 57 }
22 58 TimeSeries.prototype.init = function(){
23 59 var dx, this$ = this;
24   - console.log("Initialize time series '" + this.title + "'", this.data, this.options);
  60 + console.info("Initializing time series '" + this.title + "'...", this.data, this.options);
25 61 this.margin = {
26 62 top: 30,
27 63 right: 20,
... ... @@ -159,7 +195,7 @@
159 195 this.margin = {
160 196 top: 30,
161 197 right: 20,
162   - bottom: 30,
  198 + bottom: 40,
163 199 left: 60
164 200 };
165 201 this.extremum = 1.11 * d3.max(this.data, function(d){
... ... @@ -172,8 +208,13 @@
172 208 this.svg = d3.select(this.container).append('svg');
173 209 this.plotWrapper = this.svg.append('g');
174 210 this.plotWrapper.attr('transform', 'translate(' + this.margin.left + ',' + this.margin.top + ')');
175   - this.plotWrapper.append('g').classed('x axis', true);
176   - this.plotWrapper.append('g').classed('y axis', true);
  211 + this.xAxisLine = this.plotWrapper.append('g').classed('x axis', true);
  212 + this.yAxisLine = this.plotWrapper.append('g').classed('y axis', true);
  213 + this.xAxisTitle = this.xAxisLine.append('text').attr('fill', '#000');
  214 + this.xAxisTitle.style("text-anchor", "middle");
  215 + this.xAxisTitle.append('tspan').text('X');
  216 + this.xAxisTitle.append('tspan').attr('dy', '3px').text('HEE').attr('font-size', '0.618em');
  217 + this.xAxisTitle.append('tspan').attr('dy', '-3px').text(' (AU)');
177 218 this.sun = this.plotWrapper.append("svg:circle");
178 219 this.sun.append('svg:title').text("Sol");
179 220 this.sun.attr("r", 17).style("fill", "yellow");
... ... @@ -222,6 +263,8 @@
222 263 this.yAxis.scale(this.yScale);
223 264 this.svg.select('.x.axis').attr('transform', 'translate(0,' + height + ')').call(this.xAxis);
224 265 this.svg.select('.y.axis').call(this.yAxis);
  266 + this.xAxisTitle.attr("x", width / 2);
  267 + this.xAxisTitle.attr("y", 30);
225 268 return this;
226 269 };
227 270 Orbits.prototype.resizeOrbiter = function(slug, config){
... ... @@ -244,6 +287,34 @@
244 287 el['orbiter'].attr('y', this.yScale(data[data.length - 1].y) - 16);
245 288 return this;
246 289 };
  290 + Orbits.prototype.repositionOrbiter = function(slug, datum){
  291 + var data, el;
  292 + data = this.data;
  293 + datum == null && (datum = data[data.length - 1]);
  294 + el = this.orbitersElements[slug];
  295 + el['orbiter'].attr('x', this.xScale(datum.x) - 16);
  296 + el['orbiter'].attr('y', this.yScale(datum.y) - 16);
  297 + return this;
  298 + };
  299 + Orbits.prototype.bisectDate = d3.bisector(function(d){
  300 + return d.t;
  301 + }).left;
  302 + Orbits.prototype.moveToDate = function(t){
  303 + var slug, ref$, el, data, i, d0, d1, d, results$ = [];
  304 + for (slug in ref$ = this.orbitersElements) {
  305 + el = ref$[slug];
  306 + data = this.data;
  307 + i = this.bisectDate(data, t, 1);
  308 + d0 = data[i - 1];
  309 + d1 = data[i];
  310 + if (!(d1 && d0)) {
  311 + continue;
  312 + }
  313 + d = t - d0.t > d1.t - t ? d1 : d0;
  314 + results$.push(this.repositionOrbiter(slug, d));
  315 + }
  316 + return results$;
  317 + };
247 318 return Orbits;
248 319 }());
249 320 function bind$(obj, key, target){
... ...
web/static/js/swapp.ls
... ... @@ -3,6 +3,38 @@
3 3  
4 4 const GOLDEN_RATIO = 2 / (1 + Math.sqrt(5))
5 5  
  6 +###############################################################################
  7 +
  8 +export class SpaceWeather
  9 +
  10 + (configuration) ->
  11 + console.info "Creating Space Weather app...", configuration
  12 +
  13 + # fixme
  14 +
  15 +
  16 +
  17 +
  18 +class Source
  19 + (@slug) ->
  20 + @time_series = {}
  21 +
  22 + addTimeSeries: (ts) ->
  23 + @time_series[ts.slug] = ts
  24 +
  25 + show: ->
  26 + for slug, ts of @time_series
  27 + $(ts.svg).show()
  28 + hide: ->
  29 + for slug, ts of @time_series
  30 + $(ts.svg).hide()
  31 +
  32 +
  33 +
  34 +
  35 +###############################################################################
  36 +###############################################################################
  37 +
6 38 export class TimeSeries
7 39 # Time in x-axis
8 40 # Data in y-axis
... ... @@ -10,11 +42,11 @@ export class TimeSeries
10 42 (@slug, @title, @data, @container, @options = {}) ->
11 43 # title : string
12 44 # data : list of {x: <datetime>, y: <float>}
13   - console.log "Create time series '#{@title}'"
  45 + console.info "Creating time series '#{@title}'..."
14 46 @init()
15 47  
16 48 init: ->
17   - console.log "Initialize time series '#{@title}'", @data, @options
  49 + console.info "Initializing time series '#{@title}'...", @data, @options
18 50  
19 51 @margin = {
20 52 top: 30,
... ... @@ -195,8 +227,13 @@ export class TimeSeries
195 227  
196 228 this
197 229  
  230 +
  231 +###############################################################################
  232 +###############################################################################
  233 +
198 234 export class Orbits
199   - # View of the solar system from above
  235 + # View of the solar system from above, with orbits segments for selected time
  236 + # interval, from real data.
200 237  
201 238 (@orbiters, @data, @container, @options = {}) ->
202 239 console.log "Create orbits"
... ... @@ -208,7 +245,7 @@ export class Orbits
208 245 @margin = {
209 246 top: 30,
210 247 right: 20,
211   - bottom: 30,
  248 + bottom: 40,
212 249 left: 60
213 250 }
214 251  
... ... @@ -227,8 +264,17 @@ export class Orbits
227 264 @plotWrapper = @svg.append('g')
228 265 @plotWrapper.attr('transform', 'translate(' + @margin.left + ',' + @margin.top + ')')
229 266  
230   - @plotWrapper.append('g').classed('x axis', true)
231   - @plotWrapper.append('g').classed('y axis', true)
  267 + @xAxisLine = @plotWrapper.append('g').classed('x axis', true)
  268 + @yAxisLine = @plotWrapper.append('g').classed('y axis', true)
  269 +
  270 + @xAxisTitle = @xAxisLine.append('text').attr('fill', '#000')
  271 + @xAxisTitle.style("text-anchor", "middle")
  272 + @xAxisTitle.append('tspan').text('X')
  273 + # No : https://bugzilla.mozilla.org/show_bug.cgi?id=308338
  274 + # @xAxisTitle.append('tspan').attr('baseline-shift', 'sub').text('HEE')
  275 + # Also, don't use em as dy units
  276 + @xAxisTitle.append('tspan').attr('dy', '3px').text('HEE').attr('font-size', '0.618em')
  277 + @xAxisTitle.append('tspan').attr('dy', '-3px').text(' (AU)')
232 278  
233 279 @sun = @plotWrapper.append("svg:circle")
234 280 @sun.append('svg:title').text("Sol")
... ... @@ -293,6 +339,9 @@ export class Orbits
293 339 @svg.select('.y.axis')
294 340 .call(@yAxis)
295 341  
  342 + @xAxisTitle.attr("x", width / 2)
  343 + @xAxisTitle.attr("y", 30)
  344 +
296 345 this
297 346  
298 347 resizeOrbiter: (slug, config) ->
... ... @@ -316,10 +365,32 @@ export class Orbits
316 365 .attr('transform', 'rotate(66,'+(cx+c)+', '+cy+')')
317 366 @yScale.range([height, 0])
318 367  
319   - data = @data
  368 + data = @data # todo: multiple orbiters
320 369  
321 370 el['orbiter'].attr('x', @xScale(data[data.length - 1].x) - 16)
322 371 el['orbiter'].attr('y', @yScale(data[data.length - 1].y) - 16)
323 372  
324 373 this
325 374  
  375 + repositionOrbiter: (slug, datum) ->
  376 + data = @data # todo
  377 + datum ?= data[data.length - 1]
  378 + el = @orbitersElements[slug]
  379 + el['orbiter'].attr('x', @xScale(datum.x) - 16)
  380 + el['orbiter'].attr('y', @yScale(datum.y) - 16)
  381 +
  382 + this
  383 +
  384 + bisectDate: d3.bisector((d) -> d.t).left
  385 +
  386 + moveToDate: (t) ->
  387 + for slug, el of @orbitersElements
  388 + data = @data # todo: multiple orbiters
  389 + i = @bisectDate(data, t, 1)
  390 + d0 = data[i - 1]
  391 + d1 = data[i]
  392 + continue unless d1 and d0
  393 + d = if t - d0.t > d1.t - t then d1 else d0
  394 + @repositionOrbiter(slug, d) # fixme
  395 +
  396 +
... ...
web/view/home.html.jinja2
... ... @@ -8,7 +8,7 @@
8 8  
9 9  
10 10 <div class="mdl-layout__drawer">
11   - <span class="mdl-layout-title">Orbiters</span>
  11 + <span class="mdl-layout-title">Planets</span>
12 12  
13 13 <section id="orbiters_filters">
14 14 <img title="Jupiter" src="{{ static('img/planet/jupiter_128.png') }}" width="64px" height="64px" alt="Jupiter">
... ... @@ -45,7 +45,7 @@
45 45 </div>
46 46 </div>
47 47  
48   - <div class="loader"><div class="hole"></div></div>
  48 +{# <div class="loader"><div class="hole"></div></div>#}
49 49 </main>
50 50 </div>
51 51  
... ... @@ -131,13 +131,19 @@
131 131 <script type="application/javascript" src="{{ static('js/swapp.js') }}"></script>
132 132 <script type="application/javascript">
133 133  
134   -// Sorry, no ES6. Feel free to refactor.
135   -
136   -var orbiters = {
137   - jupiter: {
138   - name: 'Jupiter',
139   - orbit: { a: 5.45516759, b: 4.95155843 },
140   - img: '{{ static('img/planet/jupiter_128.png') }}'
  134 +var configuration = {
  135 + time_series_container: '#time_series',
  136 + orbits_container: '#orbits',
  137 + sources : {
  138 + jupiter: {
  139 + slug: 'jupiter',
  140 + name: 'Jupiter',
  141 + active: true,
  142 + minDate: '1990-01-01T01:30:00',
  143 + maxDate: '2017-02-19T00:00:00',
  144 + orbit: { a: 5.45516759, b: 4.95155843 },
  145 + img: '{{ static('img/planet/jupiter_128.png') }}'
  146 + }
141 147 }
142 148 };
143 149  
... ... @@ -145,6 +151,8 @@ jQuery().ready(function($){
145 151 var timeSeries = [];
146 152 var orbits;
147 153  
  154 + var sw = new SpaceWeather(configuration);
  155 +
148 156 d3.csv('{{ url_for('get_csv') }}', function(csv){
149 157 var timeFormat = d3.timeParse('%Y-%m-%dT%H:%M:%S%Z');
150 158 var data = {'pdyn': [], 'magn': [], 'vlen': []};
... ... @@ -188,7 +196,7 @@ jQuery().ready(function($){
188 196 data.push({t: timeFormat(d['time']), x: parseFloat(d['x_hci']), y: parseFloat(d['y_hci'])});
189 197 });
190 198  
191   - orbits = new Orbits(orbiters, data, '#orbits');
  199 + orbits = new Orbits(configuration.sources, data, '#orbits');
192 200 });
193 201  
194 202 var toggleTimeSeries = function(slug) {
... ...