Commit 2ee2acee1a876d02b0d164f779f85674840b6ca6

Authored by Antoine Goutenoir
1 parent 701dbf83
Exists in master

feat: continue with emission inequality plot

flaskr/static/js/plots/sorted-carbon-emissions.js renamed to flaskr/static/js/plots/sorted_emissions_inequality.js
1   -// set the dimensions and margins of the graph
2   -let margin = {top: 30, right: 10, bottom: 62, left: 72},
3   - width = 600 - margin.left - margin.right,
4   - height = 700 - margin.top - margin.bottom;
5   -
6   -function getTicks(maxValue, interval, startValue=0)
7   -{
8   - let range = [];
9   - for (let i = startValue ; i <= maxValue ; i+=interval)
10   - {
11   - range.push(i);
  1 +function draw_sorted_emissions_inequality(containerSelector, csvUrl) {
  2 +
  3 + // set the dimensions and margins of the graph
  4 + let margin = {top: 30, right: 10, bottom: 62, left: 72},
  5 + width = 600 - margin.left - margin.right,
  6 + height = 700 - margin.top - margin.bottom;
  7 +
  8 + function getTicks(maxValue, interval, startValue = 0) {
  9 + let range = [];
  10 + for (let i = startValue; i <= maxValue; i += interval) {
  11 + range.push(i);
  12 + }
  13 + return range;
12 14 }
13   - return range;
14   -}
15   -
16   -function getBottomTicks(maxAttendeePercent) {
17   - return getTicks(maxAttendeePercent, 20);
18   -}
19   -
20   -function getLeftTicks(maxemissionsPercent) {
21   - return getTicks(maxemissionsPercent, 20);
22   -}
23   -
24   -function getSliceCollision(x, y, barSettings)
25   -{
26   - let result = false;
27   - barSettings.forEach((element, index) => {
28   - if(x < element.rightBorder && x > element.leftBorder)
29   - {
30   - let binYDiff = element.topBorder - element.bottomBorder;
31   - let binXDiff = element.rightBorder - element.leftBorder;
32   - let binDiagonalAngle = Math.atan2(binYDiff , binXDiff);
33   - // let binYCenter = (element.topBorder + element.bottomBorder)/2;
34   - // let binXCenter = (element.rightBorder + element.leftBorder)/2;
35   - let mouseXDiff = element.rightBorder - x;
36   - let mouseYDiff = element.topBorder - y;
37   - let mouseToCenterAngle = Math.atan2(mouseYDiff , mouseXDiff);
38   - // console.log(binDiagonalAngle);
39   - // console.log(mouseToCenterAngle);
40   -
41   - if (mouseToCenterAngle < binDiagonalAngle )
42   - {
43   - barSettings.forEach((element, index) => {
44   - if(y < element.topBorder && y > element.bottomBorder)
45   - {
46   - let lb = barSettings[index].leftBorder;
47   - let rb = barSettings[index].rightBorder;
48   - let tb = barSettings[index].topBorder;
49   - let bb = barSettings[index].bottomBorder;
50   - let binCollisionRatio = (y - bb) / (tb - bb);
51   - let otherAxisLevel = (rb - lb) * binCollisionRatio + lb;
52   - result = {
53   - binDiagonalAngle : binDiagonalAngle,
54   - isXDriving: false,
55   - binIndex: index,
56   - otherAxisLevel: otherAxisLevel
57   - };
58   -
59   - }
60   - });
  15 +
  16 + function getBottomTicks(maxAttendeePercent) {
  17 + return getTicks(maxAttendeePercent, 20);
  18 + }
  19 +
  20 + function getLeftTicks(maxemissionsPercent) {
  21 + return getTicks(maxemissionsPercent, 20);
  22 + }
  23 +
  24 + function getSliceCollision(x, y, barSettings) {
  25 + let result = false;
  26 + barSettings.forEach((element, index) => {
  27 + if (x < element.rightBorder && x > element.leftBorder) {
  28 + let binYDiff = element.topBorder - element.bottomBorder;
  29 + let binXDiff = element.rightBorder - element.leftBorder;
  30 + let binDiagonalAngle = Math.atan2(binYDiff, binXDiff);
  31 + // let binYCenter = (element.topBorder + element.bottomBorder)/2;
  32 + // let binXCenter = (element.rightBorder + element.leftBorder)/2;
  33 + let mouseXDiff = element.rightBorder - x;
  34 + let mouseYDiff = element.topBorder - y;
  35 + let mouseToCenterAngle = Math.atan2(mouseYDiff, mouseXDiff);
  36 + // console.log(binDiagonalAngle);
  37 + // console.log(mouseToCenterAngle);
  38 +
  39 + if (mouseToCenterAngle < binDiagonalAngle) {
  40 + barSettings.forEach((element, index) => {
  41 + if (y < element.topBorder && y > element.bottomBorder) {
  42 + let lb = barSettings[index].leftBorder;
  43 + let rb = barSettings[index].rightBorder;
  44 + let tb = barSettings[index].topBorder;
  45 + let bb = barSettings[index].bottomBorder;
  46 + let binCollisionRatio = (y - bb) / (tb - bb);
  47 + let otherAxisLevel = (rb - lb) * binCollisionRatio + lb;
  48 + result = {
  49 + binDiagonalAngle: binDiagonalAngle,
  50 + isXDriving: false,
  51 + binIndex: index,
  52 + otherAxisLevel: otherAxisLevel
  53 + };
  54 +
  55 + }
  56 + });
61 57  
62 58  
63   - }
64   - else
65   - {
66   - let lb = barSettings[index].leftBorder;
67   - let rb = barSettings[index].rightBorder;
68   - let tb = barSettings[index].topBorder;
69   - let bb = barSettings[index].bottomBorder;
70   - let binCollisionRatio = (x - lb) / (rb - lb);
71   - let otherAxisLevel = (tb - bb) * binCollisionRatio + bb;
72   - // console.log(otherAxisLevel);
73   - result = {
74   - binDiagonalAngle : binDiagonalAngle,
75   - isXDriving: true,
76   - binIndex: index,
77   - otherAxisLevel: otherAxisLevel
  59 + }
  60 + else {
  61 + let lb = barSettings[index].leftBorder;
  62 + let rb = barSettings[index].rightBorder;
  63 + let tb = barSettings[index].topBorder;
  64 + let bb = barSettings[index].bottomBorder;
  65 + let binCollisionRatio = (x - lb) / (rb - lb);
  66 + let otherAxisLevel = (tb - bb) * binCollisionRatio + bb;
  67 + // console.log(otherAxisLevel);
  68 + result = {
  69 + binDiagonalAngle: binDiagonalAngle,
  70 + isXDriving: true,
  71 + binIndex: index,
  72 + otherAxisLevel: otherAxisLevel
  73 + }
78 74 }
79 75 }
80   - }
81   - });
82   - return result;
83   -
84   -}
85   -
86   -function setupCursorBoxes(event, xScale, yScale, barSettings, vertical, horizontal, box)
87   -{
88   - // mousex = d3.mouse(this);
89   - var x = d3.pointer(event)[0];
90   - var y = d3.pointer(event)[1];
91   - // var y = d3.event.pageY - document.getElementById(<id-of-your-svg>).getBoundingClientRect().y + 10
92   - // x += 5;
93   - box.style("left", (x + 10) + "px");
94   - box.style("top", (y - 20) + "px");
95   - let xInGraph = xScale.invert(x - d3.selectAll("g.y.axis")._groups[0][0].getBoundingClientRect().right);
96   - let yInGraph = yScale.invert(y - margin.top );
97   -
98   -
99   -
100   - // let sliceId = xScale.invert(x * 1.025 - d3.selectAll("g.yl.axis")._groups[0][0].getBoundingClientRect().x- margin.left)/500 +1;
101   - // let attendeePercent = (getAttendeeOnRight(sliceId, attendeeNumberPerGroup) / attendeeSum * 100.0).toFixed(1);
102   - if(x > width + d3.selectAll("g.y.axis")._groups[0][0].getBoundingClientRect().right ||
103   - x < d3.selectAll("g.y.axis")._groups[0][0].getBoundingClientRect().right ||
104   - y < margin.top +5 ||
105   - y > d3.selectAll("g.x.axis")._groups[0][0].getBoundingClientRect().top)
106   - {
107   - vertical.style("width", 0);
108   - horizontal.style("height", 0);
109   - box.style("display", "none");
  76 + });
  77 + return result;
  78 +
110 79 }
111   - else
112   - {
113   - vertical.style("width", "2px");
114   - horizontal.style("height", "2px");
115   - box.style("display", "inherit");
116   - let sliceCollision = getSliceCollision(xInGraph, yInGraph, barSettings);
117   - // console.log(sliceCollision);
118   - if(sliceCollision)
119   - {
120   - if(sliceCollision.isXDriving)
121   - {
122   -
123   - vertical.style("left", x + "px" );
124   - horizontal.style("top", yScale(sliceCollision.otherAxisLevel) + margin.top + "px");
125   -
126   - box.text(xInGraph + " " + sliceCollision.otherAxisLevel);
127   - }
128   - else
129   - {
130   - horizontal.style("top", y + "px");
131   - vertical.style("left", xScale(sliceCollision.otherAxisLevel) + d3.selectAll("g.y.axis")._groups[0][0].getBoundingClientRect().right + "px" );
132 80  
133   - box.text(sliceCollision.otherAxisLevel + " " + yInGraph);
134   - }
  81 + function setupCursorBoxes(event, xScale, yScale, barSettings, vertical, horizontal, box) {
  82 + // mousex = d3.mouse(this);
  83 + const x = d3.pointer(event)[0];
  84 + const y = d3.pointer(event)[1];
  85 + // var y = d3.event.pageY - document.getElementById(<id-of-your-svg>).getBoundingClientRect().y + 10
  86 + // x += 5;
  87 + box.style("left", (x + 10) + "px");
  88 + box.style("top", (y - 20) + "px");
  89 + let xInGraph = xScale.invert(x - margin.left);
  90 + let yInGraph = yScale.invert(y - margin.top);
  91 +
  92 +
  93 + // let sliceId = xScale.invert(x * 1.025 - d3.selectAll("g.yl.axis")._groups[0][0].getBoundingClientRect().x- margin.left)/500 +1;
  94 + // let attendeePercent = (getAttendeeOnRight(sliceId, attendeeNumberPerGroup) / attendeeSum * 100.0).toFixed(1);
  95 + if (
  96 + x < margin.left
  97 + ||
  98 + x > width + margin.left
  99 + ||
  100 + y < margin.top
  101 + ||
  102 + y > height + margin.top
  103 + ) {
  104 + vertical.style("width", 0);
  105 + horizontal.style("height", 0);
  106 + box.style("display", "none");
135 107 }
  108 + else {
  109 + vertical.style("width", "2px");
  110 + horizontal.style("height", "2px");
  111 + box.style("display", "inherit");
  112 + let sliceCollision = getSliceCollision(xInGraph, yInGraph, barSettings);
  113 + // console.log(sliceCollision);
  114 + if (sliceCollision) {
  115 + if (sliceCollision.isXDriving) {
  116 + vertical.style("left", x + "px");
  117 + horizontal.style("top", yScale(sliceCollision.otherAxisLevel) + margin.top + "px");
  118 +
  119 + box.text(xInGraph + " " + sliceCollision.otherAxisLevel);
  120 + } else {
  121 + horizontal.style("top", y + "px");
  122 + vertical.style("left", xScale(sliceCollision.otherAxisLevel) + margin.right + "px");
  123 +
  124 + box.text(sliceCollision.otherAxisLevel + " " + yInGraph);
  125 + }
  126 + }
136 127  
  128 + }
  129 + // box.text(attendeePercent + " % of attendees");
  130 + // console.log(d3.selectAll("g.x.axis")._groups[0][0]);
  131 + // console.log(d3.selectAll("g.x.axis")._groups[0][0].getBoundingClientRect().x);
137 132 }
138   - // box.text(attendeePercent + " % of attendees");
139   - // console.log(d3.selectAll("g.x.axis")._groups[0][0]);
140   - // console.log(d3.selectAll("g.x.axis")._groups[0][0].getBoundingClientRect().x);
141   -}
142   -
143   -function addVerticalLineAndListenCursor(xScale, yScale, barSettings) {
144   - let vertical = d3.select("#chart-container")
145   - .append("div")
146   - .attr("class", "remove")
147   - .style("position", "absolute")
148   - .style("z-index", "19")
149   - .style("width", "2px")
150   - .style("height", (height) + "px")
151   - .style("top", (10 + margin.top) + "px")
152   - .style("bottom", "30px")
153   - .style("left", "0px")
154   - .style("background", "#000");
155   -
156   - let horizontal = d3.select("#chart-container")
157   - .append("div")
158   - .attr("class", "remove")
159   - .style("position", "absolute")
160   - .style("z-index", "19")
161   - .style("width", (width) + "px")
162   - .style("height", "2px")
163   - .style("top", "0px")
164   - .style("bottom", "30px")
165   - .style("left", (10 + margin.left) + "px")
166   - .style("background", "#000");
167   -
168   - let box = d3.select("#chart-container")
169   - .append("div")
170   - .attr("class", "remove")
171   - .style("position", "absolute")
172   - .style("z-index", "20")
173   - .style("width", "150px")
174   - .style("height", "44px")
175   - .style("top", "10px")
176   - .style("bottom", "30px")
177   - .style("left", "0px")
178   - .style("border", "1px solid grey")
179   - .style("background", "rgba(255, 255, 255, 0.7)");
180   -
181   - d3.select("#chart-container")
182   - .on("mousemove", function(event){
183   - setupCursorBoxes(event, xScale, yScale, barSettings, vertical, horizontal, box);
184   - })
185   - .on("mouseover", function(event){
186   - setupCursorBoxes(event, xScale, yScale, barSettings, vertical, horizontal, box);
187   -
188   - });
189   -}
190 133  
  134 + function addVerticalLineAndListenCursor(xScale, yScale, barSettings) {
  135 + let vertical = d3.select(containerSelector)
  136 + .append("div")
  137 + .attr("class", "no-pointer-events")
  138 + .style("position", "absolute")
  139 + .style("z-index", "19")
  140 + .style("width", "2px")
  141 + .style("height", (height) + "px")
  142 + .style("top", (10 + margin.top) + "px")
  143 + .style("bottom", "30px")
  144 + .style("left", "0px")
  145 + .style("background", "#000");
  146 +
  147 + let horizontal = d3.select(containerSelector)
  148 + .append("div")
  149 + .attr("class", "no-pointer-events")
  150 + .style("position", "absolute")
  151 + .style("z-index", "19")
  152 + .style("width", (width) + "px")
  153 + .style("height", "2px")
  154 + .style("top", "0px")
  155 + .style("bottom", "30px")
  156 + .style("left", (10 + margin.left) + "px")
  157 + .style("background", "#000");
  158 +
  159 + let box = d3.select(containerSelector)
  160 + .append("div")
  161 + .attr("class", "no-pointer-events")
  162 + .style("position", "absolute")
  163 + .style("z-index", "20")
  164 + .style("width", "150px")
  165 + .style("height", "44px")
  166 + .style("top", "10px")
  167 + .style("bottom", "30px")
  168 + .style("left", "0px")
  169 + .style("border", "1px solid grey")
  170 + .style("background", "rgba(255, 255, 255, 0.7)");
  171 +
  172 + d3.select(containerSelector)
  173 + .on("mousemove", function (event) {
  174 + setupCursorBoxes(event, xScale, yScale, barSettings, vertical, horizontal, box);
  175 + })
  176 + .on("mouseover", function (event) {
  177 + setupCursorBoxes(event, xScale, yScale, barSettings, vertical, horizontal, box);
  178 + });
  179 + }
191 180  
192 181  
193   -document.onreadystatechange = () => {
194   - if (document.readyState === 'complete') {
  182 + document.addEventListener("DOMContentLoaded", () => {
  183 + width = Math.max(880, $(containerSelector).parent().width());
  184 + width = width - margin.left - margin.right;
195 185 let maxAttendeePercent = 100;
196 186 let maxEmissionsPercent = 100;
197   - let svg = d3.select("#chart-container")
  187 + let svg = d3.select(containerSelector)
198 188 .append("svg")
199 189 .attr("id", "graph-svg")
200 190 .attr("width", width + margin.left + margin.right)
... ... @@ -207,31 +197,29 @@ document.onreadystatechange = () =&gt; {
207 197 let attendeeNumberPerGroup = [];
208 198 let emissionsSum = 0;
209 199 let attendeeSum = 0;
210   - let rows = [];
211   - d3.csv("2020-09-30_04_21_19_87a1.csv", function (data) {
212   - let trainAttendee = parseInt(data["train trips_amount"]);
213   - let planeAttendee = parseInt(data["plane trips_amount"]);
214   - if(trainAttendee === 0 && planeAttendee === 0)
215   - {
  200 + let data = [];
  201 + d3.csv(csvUrl, function (datum) {
  202 + let trainAttendee = parseInt(datum["train trips_amount"]);
  203 + let planeAttendee = parseInt(datum["plane trips_amount"]);
  204 + if (trainAttendee === 0 && planeAttendee === 0) {
216 205 return;
217 206 }
218 207 let attendeeNumber = trainAttendee + planeAttendee;
219   - let distance_km = data.distance_km / attendeeNumber;
220   - let co2_kg = parseFloat(data.co2_kg);
221   - if (co2_kg === "NaN" || distance_km === "NaN")
222   - {
  208 + let distance_km = datum.distance_km / attendeeNumber;
  209 + let co2_kg = parseFloat(datum.co2_kg);
  210 + if (co2_kg === "NaN" || distance_km === "NaN") {
223 211 return;
224 212 }
225   - rows.push(data);
  213 + data.push(datum);
226 214 }).then((() => {
227   - rows.forEach((element, index) => {
228   - let trainAttendee = parseInt(element["train trips_amount"]);
229   - let planeAttendee = parseInt(element["plane trips_amount"]);
  215 + data.forEach((datum, index) => {
  216 + let trainAttendee = parseInt(datum["train trips_amount"]);
  217 + let planeAttendee = parseInt(datum["plane trips_amount"]);
230 218 let attendeeNumber = trainAttendee + planeAttendee;
231   - element["emissions_per_capita"] = parseFloat(element.co2_kg) / attendeeNumber;
  219 + datum["emissions_per_capita"] = parseFloat(datum.co2_kg) / attendeeNumber;
232 220 });
233 221  
234   - rows.sort(function (a, b) {
  222 + data.sort(function (a, b) {
235 223 if (a.emissions_per_capita > b.emissions_per_capita) {
236 224 return 1;
237 225 }
... ... @@ -240,13 +228,13 @@ document.onreadystatechange = () =&gt; {
240 228 }
241 229 return 0;
242 230 });
243   - console.log(rows);
  231 + console.log(data);
244 232 let dataIndex = 0;
245   - rows.forEach((element, index) => {
246   - let trainAttendee = parseInt(element["train trips_amount"]);
247   - let planeAttendee = parseInt(element["plane trips_amount"]);
  233 + data.forEach((datum, index) => {
  234 + let trainAttendee = parseInt(datum["train trips_amount"]);
  235 + let planeAttendee = parseInt(datum["plane trips_amount"]);
248 236 let attendeeNumber = trainAttendee + planeAttendee;
249   - let co2_kg = parseFloat(element.co2_kg);
  237 + let co2_kg = parseFloat(datum.co2_kg);
250 238 emissionsSum += co2_kg;
251 239 attendeeSum += attendeeNumber;
252 240 emissionsPerGroup[dataIndex] = emissionsSum;
... ... @@ -263,7 +251,7 @@ document.onreadystatechange = () =&gt; {
263 251 //Title
264 252 svg.append("text")
265 253 .attr("transform",
266   - "translate(" + (70 + margin.left) + ", -12)")
  254 + "translate(" + (70 + margin.left) + ", -12)")
267 255 .style("text-anchor", "middle")
268 256 .style("font-weight", "bold")
269 257 .style("font-size", "130%")
... ... @@ -292,7 +280,7 @@ document.onreadystatechange = () =&gt; {
292 280  
293 281 svg.append("text")
294 282 .attr("transform",
295   - "translate(" + (width/2) + " ," +
  283 + "translate(" + (width / 2) + " ," +
296 284 (height + margin.top + 12) + ")")
297 285 .style("text-anchor", "middle")
298 286 .text("% of participants, sorted by per capita emission");
... ... @@ -300,7 +288,7 @@ document.onreadystatechange = () =&gt; {
300 288 svg.append("text")
301 289 .attr("transform", "rotate(-90)")
302 290 .attr("y", 0 - margin.left)
303   - .attr("x",0 - (height / 2))
  291 + .attr("x", 0 - (height / 2))
304 292 .attr("dy", "1em")
305 293 .style("text-anchor", "middle")
306 294 .text("% of total emissions");
... ... @@ -309,23 +297,21 @@ document.onreadystatechange = () =&gt; {
309 297 emissionsPerGroup.forEach((element, index) => {
310 298 let bottomBorder;
311 299 let leftBorder;
312   - if(index === 0)
313   - {
  300 + if (index === 0) {
314 301 bottomBorder = 0;
315 302 leftBorder = 0;
316 303 }
317   - else
318   - {
319   - bottomBorder = emissionsPerGroup[index-1] / emissionsSum * 100.0;
320   - leftBorder = attendeeNumberPerGroup[index-1] /attendeeSum * 100.0;
  304 + else {
  305 + bottomBorder = emissionsPerGroup[index - 1] / emissionsSum * 100.0;
  306 + leftBorder = attendeeNumberPerGroup[index - 1] / attendeeSum * 100.0;
321 307 }
322   - barSettings[index]=
323   - {
324   - topBorder : emissionsPerGroup[index] / emissionsSum * 100.0,
325   - bottomBorder: bottomBorder,
326   - leftBorder : leftBorder,
327   - rightBorder : attendeeNumberPerGroup[index] / attendeeSum * 100.0,
328   - };
  308 + barSettings[index] =
  309 + {
  310 + topBorder: emissionsPerGroup[index] / emissionsSum * 100.0,
  311 + bottomBorder: bottomBorder,
  312 + leftBorder: leftBorder,
  313 + rightBorder: attendeeNumberPerGroup[index] / attendeeSum * 100.0,
  314 + };
329 315 // console.log(index);
330 316 // console.log(barSettings[index]);
331 317 });
... ... @@ -335,13 +321,21 @@ document.onreadystatechange = () =&gt; {
335 321 .enter()
336 322 .append("rect")
337 323 .attr("x", 1)
338   - .attr("transform", function(d) { return "translate(" + x(d.leftBorder) + "," + y(d.topBorder) + ")"; })
339   - .attr("width", function(d) { return x(d.rightBorder) - x(d.leftBorder) -1 ; })
340   - .attr("height", function(d) { return (y(d.bottomBorder)- y(d.topBorder)); })
  324 + .attr("transform", function (d) {
  325 + return "translate(" + x(d.leftBorder) + "," + y(d.topBorder) + ")";
  326 + })
  327 + .attr("width", function (d) {
  328 + return x(d.rightBorder) - x(d.leftBorder) - 1;
  329 + })
  330 + .attr("height", function (d) {
  331 + return (y(d.bottomBorder) - y(d.topBorder));
  332 + })
341 333 .style("z-index", "500")
342 334 .style("fill", "#4444E5");
343 335 addVerticalLineAndListenCursor(x, y, barSettings);
344 336 }));
345 337  
346   - }
347   -};
348 338 \ No newline at end of file
  339 +
  340 + });
  341 +
  342 +}
349 343 \ No newline at end of file
... ...