Commit 701dbf83625d61e45d9feececd519dfd427121d5
1 parent
e86f2462
Exists in
master
feat: integrate the emissions histogram plot
Showing
3 changed files
with
61 additions
and
51 deletions
Show diff stats
flaskr/static/js/plots/emissions-per-distance.js
1 | -function draw_emissions_per_distance(divSelector, csvUrl) { | 1 | +function draw_emissions_per_distance(containerSelector, csvUrl) { |
2 | // set the dimensions and margins of the graph | 2 | // set the dimensions and margins of the graph |
3 | let margin = {top: 48, right: 88, bottom: 68, left: 98}, | 3 | let margin = {top: 48, right: 88, bottom: 68, left: 98}, |
4 | width = 960 - margin.left - margin.right, | 4 | width = 960 - margin.left - margin.right, |
@@ -75,13 +75,14 @@ function draw_emissions_per_distance(divSelector, csvUrl) { | @@ -75,13 +75,14 @@ function draw_emissions_per_distance(divSelector, csvUrl) { | ||
75 | vertical.style("display", "inherit"); | 75 | vertical.style("display", "inherit"); |
76 | tooltip.style("display", "inherit"); | 76 | tooltip.style("display", "inherit"); |
77 | } | 77 | } |
78 | - tooltip.text(attendeePercent + " % of attendees"); | 78 | + |
79 | + tooltip.text((((attendeePercent<10)?'0':'') + attendeePercent) + "% of attendees"); | ||
79 | } | 80 | } |
80 | 81 | ||
81 | function addVerticalLineAndListenCursor(xScale, attendeeNumberPerGroup, attendeeSum) { | 82 | function addVerticalLineAndListenCursor(xScale, attendeeNumberPerGroup, attendeeSum) { |
82 | - let verticalRuler = d3.select(divSelector) | 83 | + let verticalRuler = d3.select(containerSelector) |
83 | .append("div") | 84 | .append("div") |
84 | - // .attr("class", "remove") | 85 | + .attr("class", "no-pointer-events") |
85 | .style("display", "none") | 86 | .style("display", "none") |
86 | .style("position", "absolute") | 87 | .style("position", "absolute") |
87 | .style("z-index", "19") | 88 | .style("z-index", "19") |
@@ -92,9 +93,9 @@ function draw_emissions_per_distance(divSelector, csvUrl) { | @@ -92,9 +93,9 @@ function draw_emissions_per_distance(divSelector, csvUrl) { | ||
92 | .style("left", "-10px") | 93 | .style("left", "-10px") |
93 | .style("background", "#000"); | 94 | .style("background", "#000"); |
94 | 95 | ||
95 | - let rightArea = d3.select(divSelector) | 96 | + let rightArea = d3.select(containerSelector) |
96 | .append("div") | 97 | .append("div") |
97 | - // .attr("class", "remove") | 98 | + .attr("class", "no-pointer-events") |
98 | .style("display", "none") | 99 | .style("display", "none") |
99 | .style("position", "absolute") | 100 | .style("position", "absolute") |
100 | .style("z-index", "-50") | 101 | .style("z-index", "-50") |
@@ -105,13 +106,13 @@ function draw_emissions_per_distance(divSelector, csvUrl) { | @@ -105,13 +106,13 @@ function draw_emissions_per_distance(divSelector, csvUrl) { | ||
105 | .style("left", "0px") | 106 | .style("left", "0px") |
106 | .style("background", "rgba(60, 200, 60, 0.3)"); | 107 | .style("background", "rgba(60, 200, 60, 0.3)"); |
107 | 108 | ||
108 | - let tooltip = d3.select(divSelector) | 109 | + let tooltip = d3.select(containerSelector) |
109 | .append("div") | 110 | .append("div") |
110 | .attr("class", "no-pointer-events") | 111 | .attr("class", "no-pointer-events") |
111 | .style("display", "none") | 112 | .style("display", "none") |
112 | .style("position", "absolute") | 113 | .style("position", "absolute") |
113 | .style("z-index", "20") | 114 | .style("z-index", "20") |
114 | - .style("width", "155px") | 115 | + .style("width", "161px") |
115 | .style("height", "35px") | 116 | .style("height", "35px") |
116 | .style("top", "10px") | 117 | .style("top", "10px") |
117 | .style("bottom", "30px") | 118 | .style("bottom", "30px") |
@@ -123,7 +124,7 @@ function draw_emissions_per_distance(divSelector, csvUrl) { | @@ -123,7 +124,7 @@ function draw_emissions_per_distance(divSelector, csvUrl) { | ||
123 | .style("border", "1px solid grey") | 124 | .style("border", "1px solid grey") |
124 | .style("background", "rgba(255, 255, 255, 0.7)"); | 125 | .style("background", "rgba(255, 255, 255, 0.7)"); |
125 | 126 | ||
126 | - d3.select(divSelector + " svg") | 127 | + d3.select(containerSelector + " svg") |
127 | .on("mousemove", function (event) { | 128 | .on("mousemove", function (event) { |
128 | setupCursorBoxes(event, attendeeSum, attendeeNumberPerGroup, xScale, tooltip, verticalRuler, rightArea); | 129 | setupCursorBoxes(event, attendeeSum, attendeeNumberPerGroup, xScale, tooltip, verticalRuler, rightArea); |
129 | }) | 130 | }) |
@@ -133,12 +134,14 @@ function draw_emissions_per_distance(divSelector, csvUrl) { | @@ -133,12 +134,14 @@ function draw_emissions_per_distance(divSelector, csvUrl) { | ||
133 | } | 134 | } |
134 | 135 | ||
135 | document.addEventListener("DOMContentLoaded", () => { | 136 | document.addEventListener("DOMContentLoaded", () => { |
137 | + width = Math.max(880, $(containerSelector).parent().width()); | ||
138 | + width = width - margin.left - margin.right; | ||
136 | let maxemissions = 0; | 139 | let maxemissions = 0; |
137 | let maxemissionsPercent = 0; | 140 | let maxemissionsPercent = 0; |
138 | let maxDistance = 0; | 141 | let maxDistance = 0; |
139 | - let svg = d3.select(divSelector) | 142 | + let svg = d3.select(containerSelector) |
140 | .append("svg") | 143 | .append("svg") |
141 | - // .attr("id", divSelector + "-svg") | 144 | + // .attr("id", containerSelector + "-svg") |
142 | .attr("width", width + margin.left + margin.right) | 145 | .attr("width", width + margin.left + margin.right) |
143 | .attr("height", height + margin.top + margin.bottom) | 146 | .attr("height", height + margin.top + margin.bottom) |
144 | .append("g") | 147 | .append("g") |
@@ -0,0 +1,29 @@ | @@ -0,0 +1,29 @@ | ||
1 | +/** POLYFILLS **/ | ||
2 | +Math.log10 = Math.log10 || function(x) { return Math.log(x) * Math.LOG10E; }; | ||
3 | + | ||
4 | +/** | ||
5 | + * Useful for axes' domains on plots. | ||
6 | + * @param value | ||
7 | + * @returns {number} | ||
8 | + */ | ||
9 | +const ceil_value_to_magnitude = function (value) { | ||
10 | + let sign = 1; | ||
11 | + if (value < 0) { | ||
12 | + value = Math.abs(value); | ||
13 | + sign = -1; | ||
14 | + } | ||
15 | + if (value < 1) { | ||
16 | + return sign; | ||
17 | + } | ||
18 | + | ||
19 | + const low = Math.pow(10, Math.floor(Math.log10(value))); | ||
20 | + | ||
21 | + let cursor = low; | ||
22 | + let noloop = 0; | ||
23 | + while ((cursor < value) && (noloop <= 100)) { | ||
24 | + cursor += 0.1 * low; | ||
25 | + noloop += 1; | ||
26 | + } | ||
27 | + | ||
28 | + return sign * cursor; | ||
29 | +}; |
flaskr/templates/estimation.html
@@ -103,10 +103,6 @@ | @@ -103,10 +103,6 @@ | ||
103 | {# <div id="cities_footprints_d3viz" class="plot-container"></div>#} | 103 | {# <div id="cities_footprints_d3viz" class="plot-container"></div>#} |
104 | <hr> | 104 | <hr> |
105 | <div id="cities_footprints_spinner" class="lds-ripple text-center"><div></div><div></div><div></div></div> | 105 | <div id="cities_footprints_spinner" class="lds-ripple text-center"><div></div><div></div><div></div></div> |
106 | - | ||
107 | - <div id="emissions_per_distance_histogram" class="plot-container"> | ||
108 | - </div> | ||
109 | - | ||
110 | {# This MUST stay empty (because Simg uses svg.getparentnode.innerhtml) #} | 106 | {# This MUST stay empty (because Simg uses svg.getparentnode.innerhtml) #} |
111 | <div id="cities_footprints_d3viz_lollipop" class="plot-container"> | 107 | <div id="cities_footprints_d3viz_lollipop" class="plot-container"> |
112 | </div> | 108 | </div> |
@@ -115,8 +111,21 @@ | @@ -115,8 +111,21 @@ | ||
115 | </div> | 111 | </div> |
116 | 112 | ||
117 | <hr> | 113 | <hr> |
114 | + | ||
115 | +{# EMISSIONS PER DISTANCE HISTOGRAM ##########################################} | ||
116 | +{# That plot makes no sense with our many to many data. #} | ||
117 | +{% if not estimation.is_many_to_many() %} | ||
118 | +<div class="row"> | ||
119 | + <div id="emissions_per_distance_histogram" class="plot-container"></div> | ||
120 | +</div> | ||
121 | +<hr> | ||
118 | {% endif %} | 122 | {% endif %} |
123 | +{#############################################################################} | ||
119 | 124 | ||
125 | +{% endif %}{# not estimation.has_failed() #} | ||
126 | + | ||
127 | + | ||
128 | +{# LIST OF CITIES ############################################################} | ||
120 | <div class="row"> | 129 | <div class="row"> |
121 | 130 | ||
122 | {% if not estimation.has_failed() %} | 131 | {% if not estimation.has_failed() %} |
@@ -216,7 +225,7 @@ | @@ -216,7 +225,7 @@ | ||
216 | {{ content.estimation.footer | markdown | safe }} | 225 | {{ content.estimation.footer | markdown | safe }} |
217 | </div> | 226 | </div> |
218 | 227 | ||
219 | -{# Buffer to drop the PNG image into to trick firefox into downloading the PNG #} | 228 | +{# Buffer to drop the PNG image into, to trick firefox into downloading the PNG #} |
220 | <div id="png_buffer"></div> | 229 | <div id="png_buffer"></div> |
221 | 230 | ||
222 | {% endif %}{# not estimation.has_failed() #} | 231 | {% endif %}{# not estimation.has_failed() #} |
@@ -233,53 +242,22 @@ | @@ -233,53 +242,22 @@ | ||
233 | <script src="/static/js/vendor/d3-legend.js"></script> | 242 | <script src="/static/js/vendor/d3-legend.js"></script> |
234 | <script src="/static/js/vendor/d3-scale-chromatic.v1.min.js"></script> | 243 | <script src="/static/js/vendor/d3-scale-chromatic.v1.min.js"></script> |
235 | <script src="/static/js/vendor/d3-geo-projection.v2.min.js"></script> | 244 | <script src="/static/js/vendor/d3-geo-projection.v2.min.js"></script> |
245 | +<script src="/static/js/plots/utils.js"></script> | ||
236 | <script src="/static/js/plots/emissions-per-distance.js"></script> | 246 | <script src="/static/js/plots/emissions-per-distance.js"></script> |
237 | <script src="/static/js/plots/travel-legs-worldmap.js"></script> | 247 | <script src="/static/js/plots/travel-legs-worldmap.js"></script> |
238 | 248 | ||
239 | <script type="text/javascript"> | 249 | <script type="text/javascript"> |
240 | 250 | ||
241 | -/** POLYFILLS **/ | ||
242 | -Math.log10 = Math.log10 || function(x) { return Math.log(x) * Math.LOG10E; }; | ||
243 | - | ||
244 | -/** | ||
245 | - * Useful for axes' domains on plots. | ||
246 | - * @param value | ||
247 | - * @returns {number} | ||
248 | - */ | ||
249 | -var ceil_value_to_magnitude = function(value) { | ||
250 | - var sign = 1; | ||
251 | - if (value < 0) { | ||
252 | - value = Math.abs(value); | ||
253 | - sign = -1; | ||
254 | - } | ||
255 | - if (value < 1) { | ||
256 | - return sign; | ||
257 | - } | ||
258 | - | ||
259 | - var low = Math.pow(10, Math.floor(Math.log10(value))); | ||
260 | - | ||
261 | - var cursor = low; | ||
262 | - var noloop = 0; | ||
263 | - while ((cursor < value) && (noloop <= 100)) { | ||
264 | - cursor += 0.1 * low; | ||
265 | - noloop += 1; | ||
266 | - } | ||
267 | - | ||
268 | - return sign * cursor; | ||
269 | -}; | ||
270 | - | ||
271 | -/** CONFIG **/ | ||
272 | - | ||
273 | var plots_config = { | 251 | var plots_config = { |
274 | 'cities_count': {{ estimation_output.cities | length }} | 252 | 'cities_count': {{ estimation_output.cities | length }} |
275 | }; | 253 | }; |
276 | 254 | ||
277 | -/** PLOTS **/ | ||
278 | - | 255 | +{% if not estimation.is_many_to_many() %} |
279 | draw_emissions_per_distance( | 256 | draw_emissions_per_distance( |
280 | "#emissions_per_distance_histogram", | 257 | "#emissions_per_distance_histogram", |
281 | "/estimation/{{ estimation.public_id }}.csv" | 258 | "/estimation/{{ estimation.public_id }}.csv" |
282 | ); | 259 | ); |
260 | +{% endif %} | ||
283 | 261 | ||
284 | 262 | ||
285 | draw_travel_legs_worldmap( | 263 | draw_travel_legs_worldmap( |
@@ -374,7 +352,7 @@ jQuery(document).ready(function($){ | @@ -374,7 +352,7 @@ jQuery(document).ready(function($){ | ||
374 | 352 | ||
375 | var margin = {top: 40, right: 40, bottom: 150, left: 180}, | 353 | var margin = {top: 40, right: 40, bottom: 150, left: 180}, |
376 | height = Math.max(300, 100 + 16*plots_config['cities_count']) - margin.top - margin.bottom; | 354 | height = Math.max(300, 100 + 16*plots_config['cities_count']) - margin.top - margin.bottom; |
377 | - var width = Math.max(880, $(vizid).parent().width()); | 355 | + var width = Math.max(800, $(vizid).parent().width()); |
378 | width = width - margin.left - margin.right; | 356 | width = width - margin.left - margin.right; |
379 | 357 | ||
380 | var svg_tag = d3.select(vizid) | 358 | var svg_tag = d3.select(vizid) |