Commit 438929a414e696cc76d7bcc2ff69ca6ce5a9a0ce

Authored by Goutte
1 parent f1f1e797

Rewrite the orbits in Livescript.

web/static/js/swapp.js 0 → 100644
... ... @@ -0,0 +1,178 @@
  1 +// Generated by LiveScript 1.5.0
  2 +(function(){
  3 + var GOLDEN_RATIO, TimeSeries, Orbits, out$ = typeof exports != 'undefined' && exports || this;
  4 + GOLDEN_RATIO = 2 / (1 + Math.sqrt(5));
  5 + out$.TimeSeries = TimeSeries = (function(){
  6 + TimeSeries.displayName = 'TimeSeries';
  7 + var prototype = TimeSeries.prototype, constructor = TimeSeries;
  8 + function TimeSeries(title, data, container, options){
  9 + this.title = title;
  10 + this.data = data;
  11 + this.container = container;
  12 + this.options = options != null
  13 + ? options
  14 + : {};
  15 + console.log("Create time series '" + this.title + "'");
  16 + this.init();
  17 + }
  18 + TimeSeries.prototype.init = function(){
  19 + var this$ = this;
  20 + console.log("Initialize time series '" + this.title + "'", this.data, this.options);
  21 + this.margin = {
  22 + top: 30,
  23 + right: 20,
  24 + bottom: 30,
  25 + left: 60
  26 + };
  27 + this.xScale = d3.scaleTime().domain(d3.extent(this.data, function(d){
  28 + return d.x;
  29 + }));
  30 + this.yScale = d3.scaleLinear().domain(d3.extent(this.data, function(d){
  31 + return d.y;
  32 + }));
  33 + this.xAxis = d3.axisBottom().ticks(7, ",f").tickFormat(d3.timeFormat("%Y-%m-%d"));
  34 + this.yAxis = d3.axisLeft().ticks(10);
  35 + this.line = d3.line().x(function(d){
  36 + return this$.xScale(d.x);
  37 + }).y(function(d){
  38 + return this$.yScale(d.y);
  39 + });
  40 + this.svg = d3.select(this.container).append('svg');
  41 + this.plotWrapper = this.svg.append('g');
  42 + this.plotWrapper.attr('transform', 'translate(' + this.margin.left + ',' + this.margin.top + ')');
  43 + this.path = this.plotWrapper.append('path').datum(this.data).classed('line', true);
  44 + this.plotWrapper.append('g').classed('x axis', true);
  45 + this.plotWrapper.append('g').classed('y axis', true);
  46 + this.yAxisText = this.plotWrapper.append("text").attr("transform", "rotate(-90)").attr("dy", "1em").style("text-anchor", "middle").text(this.title);
  47 + return this.resize();
  48 + };
  49 + TimeSeries.prototype.resize = function(){
  50 + var width, height;
  51 + width = jQuery(this.container).width() - this.margin.left - this.margin.right;
  52 + height = GOLDEN_RATIO * GOLDEN_RATIO * GOLDEN_RATIO * width;
  53 + console.log("Resize time series " + this.title + " : " + width + " x " + height);
  54 + this.xScale.range([0, width]);
  55 + this.yScale.range([height, 0]);
  56 + this.svg.attr('width', width + this.margin.right + this.margin.left).attr('height', height + this.margin.top + this.margin.bottom);
  57 + this.path.attr('d', this.line);
  58 + this.xAxis.scale(this.xScale);
  59 + this.yAxis.scale(this.yScale);
  60 + if (width < 600) {
  61 + this.xAxis.ticks(3);
  62 + } else {
  63 + this.xAxis.ticks(7, ",f");
  64 + }
  65 + this.svg.select('.x.axis').attr('transform', 'translate(0,' + height + ')').call(this.xAxis);
  66 + this.svg.select('.y.axis').call(this.yAxis);
  67 + this.yAxisText.attr("y", 0 - this.margin.left).attr("x", 0 - height / 2);
  68 + return this;
  69 + };
  70 + return TimeSeries;
  71 + }());
  72 + out$.Orbits = Orbits = (function(){
  73 + Orbits.displayName = 'Orbits';
  74 + var prototype = Orbits.prototype, constructor = Orbits;
  75 + function Orbits(orbiters, data, container, options){
  76 + this.orbiters = orbiters;
  77 + this.data = data;
  78 + this.container = container;
  79 + this.options = options != null
  80 + ? options
  81 + : {};
  82 + console.log("Create orbits");
  83 + this.init();
  84 + }
  85 + Orbits.prototype.init = function(){
  86 + var slug, ref$, config;
  87 + console.log("Initialize orbits", this.data, this.options);
  88 + this.margin = {
  89 + top: 30,
  90 + right: 20,
  91 + bottom: 30,
  92 + left: 60
  93 + };
  94 + this.extremum = 1.11 * d3.max(this.data, function(d){
  95 + return Math.max(Math.abs(d.x), Math.abs(d.y));
  96 + });
  97 + this.xScale = d3.scaleLinear().domain([-1 * this.extremum, this.extremum]);
  98 + this.yScale = d3.scaleLinear().domain([-1 * this.extremum, this.extremum]);
  99 + this.xAxis = d3.axisBottom().ticks(10);
  100 + this.yAxis = d3.axisLeft().ticks(10);
  101 + this.svg = d3.select(this.container).append('svg');
  102 + this.plotWrapper = this.svg.append('g');
  103 + this.plotWrapper.attr('transform', 'translate(' + this.margin.left + ',' + this.margin.top + ')');
  104 + this.plotWrapper.append('g').classed('x axis', true);
  105 + this.plotWrapper.append('g').classed('y axis', true);
  106 + this.sun = this.plotWrapper.append("svg:circle");
  107 + this.sun.append('svg:title').text("Sol");
  108 + this.sun.attr("r", 17).style("fill", "yellow");
  109 + for (slug in ref$ = this.orbiters) {
  110 + config = ref$[slug];
  111 + this.initOrbiter(slug, config);
  112 + }
  113 + return this.resize();
  114 + };
  115 + Orbits.prototype.orbitersElements = {};
  116 + Orbits.prototype.initOrbiter = function(slug, config){
  117 + var orbit_ellipse, orbiter, orbit_line, orbit_section, this$ = this;
  118 + if (slug in this.orbitersElements) {
  119 + throw new Error("Second init of " + slug);
  120 + }
  121 + orbit_ellipse = this.plotWrapper.append("svg:ellipse").classed('orbit orbit_ellipse', true);
  122 + orbiter = this.plotWrapper.append("svg:image").attr('xlink:href', config['img']).attr('width', '32px').attr('height', '32px');
  123 + orbit_line = d3.line().x(function(d){
  124 + return this$.xScale(d.x);
  125 + }).y(function(d){
  126 + return this$.yScale(d.y);
  127 + });
  128 + orbit_section = this.plotWrapper.append('path').datum(this.data).classed('orbit orbit_section', true);
  129 + this.orbitersElements[slug] = {
  130 + orbiter: orbiter,
  131 + orbit_ellipse: orbit_ellipse,
  132 + orbit_section: orbit_section,
  133 + orbit_line: orbit_line
  134 + };
  135 + return this;
  136 + };
  137 + Orbits.prototype.resize = function(){
  138 + var width, height, slug, ref$, config;
  139 + width = jQuery(this.container).width() - this.margin.left - this.margin.right;
  140 + height = 1.0 * width;
  141 + console.log("Resize orbits : " + width + " x " + height);
  142 + this.xScale.range([0, width]);
  143 + this.yScale.range([height, 0]);
  144 + this.svg.attr('width', width + this.margin.right + this.margin.left).attr('height', height + this.margin.top + this.margin.bottom);
  145 + this.sun.attr("cx", width / 2).attr("cy", height / 2);
  146 + for (slug in ref$ = this.orbiters) {
  147 + config = ref$[slug];
  148 + this.resizeOrbiter(slug, config);
  149 + }
  150 + this.xAxis.scale(this.xScale);
  151 + this.yAxis.scale(this.yScale);
  152 + this.svg.select('.x.axis').attr('transform', 'translate(0,' + height + ')').call(this.xAxis);
  153 + this.svg.select('.y.axis').call(this.yAxis);
  154 + return this;
  155 + };
  156 + Orbits.prototype.resizeOrbiter = function(slug, config){
  157 + var width, height, el, a, b, c, cx, cy, data;
  158 + width = jQuery(this.container).width() - this.margin.left - this.margin.right;
  159 + height = 1.0 * width;
  160 + console.log("Resize orbiter " + slug);
  161 + el = this.orbitersElements[slug];
  162 + el['orbit_section'].attr('d', el['orbit_line']);
  163 + a = config['orbit']['a'];
  164 + b = config['orbit']['b'];
  165 + c = Math.sqrt(a * a - b * b);
  166 + cx = width / 2 - c;
  167 + cy = height / 2;
  168 + this.yScale.range([0, height]);
  169 + el['orbit_ellipse'].attr('cx', cx).attr('cy', cy).attr('rx', this.xScale(a) - this.xScale(0)).attr('ry', this.yScale(b) - this.yScale(0)).attr('transform', 'rotate(66,' + (cx + c) + ', ' + cy + ')');
  170 + this.yScale.range([height, 0]);
  171 + data = this.data;
  172 + el['orbiter'].attr('x', this.xScale(data[data.length - 1].x) - 16);
  173 + el['orbiter'].attr('y', this.yScale(data[data.length - 1].y) - 16);
  174 + return this;
  175 + };
  176 + return Orbits;
  177 + }());
  178 +}).call(this);
... ...
web/static/js/swapp.ls
... ... @@ -90,11 +90,7 @@ export class TimeSeries
90 90 export class Orbits
91 91 # View of the solar system from above
92 92  
93   - planetsElements: []
94   -
95   - (@planets, @data, @container, @options = {}) ->
96   - # title : string
97   - # data : list of {x: <datetime>, y: <float>}
  93 + (@orbiters, @data, @container, @options = {}) ->
98 94 console.log "Create orbits"
99 95 @init()
100 96  
... ... @@ -118,8 +114,6 @@ export class Orbits
118 114 @xAxis = d3.axisBottom().ticks(10)
119 115 @yAxis = d3.axisLeft().ticks(10)
120 116  
121   - # line wip
122   -
123 117 @svg = d3.select(@container).append('svg')
124 118  
125 119 @plotWrapper = @svg.append('g')
... ... @@ -132,8 +126,38 @@ export class Orbits
132 126 @sun.append('svg:title').text("Sol")
133 127 @sun.attr("r", 17).style("fill", "yellow")
134 128  
  129 + for slug, config of @orbiters
  130 + @initOrbiter(slug, config)
  131 +
135 132 @resize()
136 133  
  134 + orbitersElements: {}
  135 + initOrbiter: (slug, config) ->
  136 + if slug of @orbitersElements then throw new Error("Second init of #{slug}")
  137 +
  138 + # The order is important, as it will define the default z-order
  139 + orbit_ellipse = @plotWrapper.append("svg:ellipse")
  140 + .classed('orbit orbit_ellipse', true)
  141 + orbiter = @plotWrapper.append("svg:image")
  142 + .attr('xlink:href', config['img'])
  143 + .attr('width', '32px').attr('height', '32px')
  144 +
  145 + orbit_line = d3.line()
  146 + .x((d) ~> @xScale(d.x))
  147 + .y((d) ~> @yScale(d.y))
  148 +
  149 + orbit_section = @plotWrapper.append('path')
  150 + .datum(@data) # fixme
  151 + .classed('orbit orbit_section', true)
  152 +
  153 + @orbitersElements[slug] =
  154 + orbiter: orbiter
  155 + orbit_ellipse: orbit_ellipse
  156 + orbit_section: orbit_section
  157 + orbit_line: orbit_line
  158 +
  159 + this
  160 +
137 161 resize: ->
138 162 width = jQuery(@container).width() - @margin.left - @margin.right
139 163 height = 1.0 * width
... ... @@ -148,6 +172,9 @@ export class Orbits
148 172  
149 173 @sun.attr("cx", width / 2).attr("cy", height / 2)
150 174  
  175 + for slug, config of @orbiters
  176 + @resizeOrbiter(slug, config)
  177 +
151 178 @xAxis.scale(@xScale)
152 179 @yAxis.scale(@yScale)
153 180  
... ... @@ -160,3 +187,31 @@ export class Orbits
160 187  
161 188 this
162 189  
  190 + resizeOrbiter: (slug, config) ->
  191 + width = jQuery(@container).width() - @margin.left - @margin.right
  192 + height = 1.0 * width
  193 +
  194 + console.log("Resize orbiter #{slug}")
  195 +
  196 + el = @orbitersElements[slug]
  197 + el['orbit_section'].attr('d', el['orbit_line'])
  198 +
  199 + a = config['orbit']['a']
  200 + b = config['orbit']['b']
  201 + c = Math.sqrt(a*a - b*b)
  202 + cx = (width / 2) - c
  203 + cy = (height / 2)
  204 + @yScale.range([0, height])
  205 + el['orbit_ellipse'].attr('cx', cx).attr('cy', cy)
  206 + .attr('rx', @xScale(a) - @xScale(0))
  207 + .attr('ry', @yScale(b) - @yScale(0))
  208 + .attr('transform', 'rotate(66,'+(cx+c)+', '+cy+')')
  209 + @yScale.range([height, 0])
  210 +
  211 + data = @data
  212 +
  213 + el['orbiter'].attr('x', @xScale(data[data.length - 1].x) - 16)
  214 + el['orbiter'].attr('y', @yScale(data[data.length - 1].y) - 16)
  215 +
  216 + this
  217 +
... ...
web/view/home.html.jinja2
... ... @@ -77,228 +77,23 @@
77 77  
78 78 {% block scripts_footer %}
79 79 <script type="application/javascript" src="{{ static('js/d3.min.js') }}"></script>
  80 +<script type="application/javascript" src="{{ static('js/swapp.js') }}"></script>
80 81 <script type="application/javascript">
81 82  
82 83 // Sorry, no ES6. Feel free to refactor.
83 84  
84   -var swApp = (function (window, d3, $) {
85   -
86   - var $time_series = $("#time_series");
87   - var $orbits = $("#orbits");
88   -
89   - var orbiters = {
90   - jupiter: {
91   - name: "Jupiter",
92   - orbit: { a: 5.45516759, b: 4.95155843 },
93   - img: "{{ static('img/planet/jupiter_128.png') }}"
94   - }
95   - };
96   -
97   - var plotTimeSeries = function(data, options) {
98   - console.log("Init time series with data", data, options);
99   -
100   - var xScale, yScale, xAxis, yAxis, yAxisText;
101   - var line;
102   - var svg, plotWrapper, path;
103   - var width, height;
104   - var margin = {
105   - top: 30,
106   - right: 20,
107   - bottom: 30,
108   - left: 60
109   - };
110   -
111   - // INIT SCALES
112   - xScale = d3.scaleTime().domain(d3.extent(data, function (d) {
113   - return d.x;
114   - }));
115   - yScale = d3.scaleLinear().domain(d3.extent(data, function (d) {
116   - return d.y;
117   - }));
118   -
119   - // INIT AXISES
120   - xAxis = d3.axisBottom()
121   - .ticks(7, ",f")
122   - .tickFormat(d3.timeFormat("%Y-%m-%d"));
123   - yAxis = d3.axisLeft()
124   - .ticks(10);
125   -
126   -
127   - // INIT LINE
128   - line = d3.line()
129   - .x(function (d) { return xScale(d.x) })
130   - .y(function (d) { return yScale(d.y) });
131   -
132   - // INIT SVG
133   - svg = d3.select('#time_series').append('svg');
134   -
135   - plotWrapper = svg.append('g');
136   -
137   - path = plotWrapper.append('path')
138   - .datum(data)
139   - .classed('line', true);
140   -
141   - plotWrapper.append('g')
142   - .classed('x axis', true);
143   - plotWrapper.append('g')
144   - .classed('y axis', true);
145   - yAxisText = plotWrapper.append("text")
146   - .attr("transform", "rotate(-90)")
147   - .attr("dy", "1em")
148   - .style("text-anchor", "middle")
149   - .text(options['title']);
150   -
151   - // -- wip refactor resize
152   -
153   - width = $time_series.width() - margin.left - margin.right;
154   - height = .618 * .618 * width;
155   -
156   - xScale.range([0, width]);
157   - yScale.range([height, 0]);
158   -
159   - svg.attr('width', width + margin.right + margin.left)
160   - .attr('height', height + margin.top + margin.bottom);
161   -
162   - plotWrapper.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
163   -
164   - path.attr('d', line);
165   -
166   - xAxis.scale(xScale);
167   - yAxis.scale(yScale);
168   -
169   - if (width < 600) { xAxis.ticks(3); }
170   -
171   - svg.select('.x.axis')
172   - .attr('transform', 'translate(0,' + height + ')')
173   - .call(xAxis);
174   -
175   - svg.select('.y.axis')
176   - .call(yAxis);
177   -
178   - yAxisText.attr("y", 0 - margin.left).attr("x", 0 - (height / 2));
179   - };
180   -
181   - var plotOrbits = function(data, options) {
182   - console.log("Init orbits with data", data, options);
183   -
184   -
185   - var xScale, yScale, xAxis, yAxis, xAxisText, yAxisText;
186   - var line;
187   - var svg, plotWrapper, orbital_orbit_section, orbital_orbit_ellipse, sun;
188   - var width, height;
189   - var margin = {
190   - top: 30,
191   - right: 20,
192   - bottom: 30,
193   - left: 60
194   - };
195   -
196   - // INIT SCALES
197   - var extremum = 1.11 * d3.max(data, function (d) {
198   - return Math.max(Math.abs(d.x), Math.abs(d.y));
199   - });
200   -
201   - console.info("Extremum", extremum);
202   -
203   - xScale = d3.scaleLinear().domain([-1 * extremum, extremum]);
204   - yScale = d3.scaleLinear().domain([-1 * extremum, extremum]);
205   -
206   - xAxis = d3.axisBottom().ticks(10);
207   - yAxis = d3.axisLeft().ticks(10);
208   -
209   - // INIT LINE
210   - line = d3.line()
211   - .x(function (d) { return xScale(d.x) })
212   - .y(function (d) { return yScale(d.y) });
213   -
214   - // INIT SVG
215   - svg = d3.select('#orbits').append('svg');
216   -
217   - plotWrapper = svg.append('g');
218   -
219   - // Sun
220   - sun = plotWrapper.append("svg:circle");
221   - sun.append('svg:title').text("Sol");
222   -
223   - // haxx wip
224   - var orbital_config = orbiters['jupiter'];
225   -
226   - orbital_orbit_ellipse = plotWrapper.append("svg:ellipse")
227   - .classed('orbit orbit_ellipse', true);
228   -
229   -{# var test_square = plotWrapper.append("svg:rect");#}
230   -
231   - var orbital_element = plotWrapper.append("svg:image");
232   - orbital_element.attr('xlink:href', orbital_config['img']);
233   - orbital_element.attr('width', '32px').attr('height', '32px');
234   -
235   - orbital_orbit_section = plotWrapper.append('path')
236   - .datum(data)
237   - .classed('orbit orbit_section', true);
238   -
239   - plotWrapper.append('g').classed('x axis', true);
240   - plotWrapper.append('g').classed('y axis', true);
241   -
242   - // ---- wip: refactor resizing from here
243   -
244   - width = $orbits.width() - margin.left - margin.right;
245   - height = width * 1.0;
246   -
247   - xScale.range([0, width]);
248   - yScale.range([height, 0]);
249   -{# yScale.range([0, height]);#}
250   -
251   - svg.attr('width', width + margin.right + margin.left)
252   - .attr('height', height + margin.top + margin.bottom);
253   -
254   - plotWrapper.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
255   -
256   - sun.attr("cx", width / 2).attr("cy", height / 2).attr("r", 17).style("fill", "yellow");
257   -
258   - orbital_orbit_section.attr('d', line);
259   -
260   - var a = orbital_config['orbit']['a'];
261   - var b = orbital_config['orbit']['b'];
262   - var c = Math.sqrt(a*a-b*b);
263   - var cx = (width / 2) - c;
264   - var cy = (height / 2);
265   - yScale.range([0, height]);
266   - orbital_orbit_ellipse.attr('cx', cx).attr('cy', cy)
267   - .attr('rx', xScale(a) - xScale(0))
268   - .attr('ry', yScale(b) - yScale(0))
269   - .attr('transform', 'rotate(66,'+(cx+c)+', '+cy+')');
270   - yScale.range([height, 0]);
271   -
272   -{# test_square.attr('x', cx).attr('y', cy);#}
273   -{# test_square.attr('width', 20).attr('height', 20);#}
274   -{# test_square.attr('style', 'fill:red;');#}
275   -{# test_square.attr('transform', 'rotate(45,'+0+', '+0+')');#}
276   -
277   - orbital_element.attr('x', xScale(data[data.length - 1].x) - 16);
278   - orbital_element.attr('y', yScale(data[data.length - 1].y) - 16);
279   -
280   - xAxis.scale(xScale);
281   - yAxis.scale(yScale);
282   -
283   - //if (width < 600) { xAxis.ticks(3); }
284   -
285   - svg.select('.x.axis')
286   - .attr('transform', 'translate(0,' + height + ')')
287   - .call(xAxis);
288   -
289   - svg.select('.y.axis')
290   - .call(yAxis);
291   -
292   - };
293   -
294   - return {
295   - plotTimeSeries: plotTimeSeries,
296   - plotOrbits: plotOrbits
297   - };
298   -})(window, d3, jQuery);
299   -
  85 +var orbiters = {
  86 + jupiter: {
  87 + name: "Jupiter",
  88 + orbit: { a: 5.45516759, b: 4.95155843 },
  89 + img: "{{ static('img/planet/jupiter_128.png') }}"
  90 + }
  91 +};
300 92  
301 93 jQuery().ready(function($){
  94 + var timeSeries = [];
  95 + var orbits;
  96 +
302 97 d3.csv("{{ url_for('get_csv') }}", function(csv){
303 98 var timeFormat = d3.timeParse('%Y-%m-%dT%H:%M:%S%Z');
304 99 var data = {'pdyn': [], 'magn': [], 'vlen': []};
... ... @@ -307,16 +102,32 @@ jQuery().ready(function($){
307 102 data['magn'].push({x: timeFormat(d['time']), y: parseFloat(d['magn'])});
308 103 data['vlen'].push({x: timeFormat(d['time']), y: parseFloat(d['vlen'])});
309 104 });
310   - swApp.plotTimeSeries(data['pdyn'], {title: 'Dynamic Pressure (nPa)'});
311   - swApp.plotTimeSeries(data['magn'], {title: 'Magnetism (nT)'});
312   - swApp.plotTimeSeries(data['vlen'], {title: 'Velocity (km/s)'});
  105 +
  106 + var container = "#time_series";
  107 + timeSeries.push(new TimeSeries(
  108 + 'Dynamic Pressure (nPa)', data['pdyn'], container
  109 + ));
  110 + timeSeries.push(new TimeSeries(
  111 + 'Magnetism (nT)', data['magn'], container
  112 + ));
  113 + timeSeries.push(new TimeSeries(
  114 + 'Velocity (km/s)', data['vlen'], container
  115 + ));
  116 +
313 117 });
  118 +
314 119 d3.csv("{{ url_for('get_astral_coordinates_csv') }}", function(csv){
315 120 var data = [];
316 121 csv.forEach(function (d) {
317 122 data.push({x: parseFloat(d['x_hci']), y: parseFloat(d['y_hci'])});
318 123 });
319   - swApp.plotOrbits(data, {});
  124 +
  125 + orbits = new Orbits(orbiters, data, '#orbits');
  126 + });
  127 +
  128 + window.addEventListener('resize', function() {
  129 + timeSeries.forEach(function(ts){ ts.resize(); });
  130 + orbits.resize();
320 131 });
321 132  
322 133 });
... ...