Commit 566355a9362ddae819f7a11a43c4036a67ccfb01

Authored by Adrenesis
1 parent 7a14bc18
Exists in master

Add sorted-carbon-emissions.js

Showing 1 changed file with 347 additions and 0 deletions   Show diff stats
flaskr/static/js/plots/sorted-carbon-emissions.js 0 → 100644
... ... @@ -0,0 +1,347 @@
  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);
  12 + }
  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 + });
  61 +
  62 +
  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
  78 + }
  79 + }
  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");
  110 + }
  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 +
  133 + box.text(sliceCollision.otherAxisLevel + " " + yInGraph);
  134 + }
  135 + }
  136 +
  137 + }
  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 +
  191 +
  192 +
  193 +document.onreadystatechange = () => {
  194 + if (document.readyState === 'complete') {
  195 + let maxAttendeePercent = 100;
  196 + let maxEmissionsPercent = 100;
  197 + let svg = d3.select("#chart-container")
  198 + .append("svg")
  199 + .attr("id", "graph-svg")
  200 + .attr("width", width + margin.left + margin.right)
  201 + .attr("height", height + margin.top + margin.bottom)
  202 + .append("g")
  203 + .attr("transform",
  204 + "translate(" + margin.left + "," + margin.top + ")");
  205 +
  206 + let emissionsPerGroup = [];
  207 + let attendeeNumberPerGroup = [];
  208 + let emissionsSum = 0;
  209 + 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 + {
  216 + return;
  217 + }
  218 + 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 + {
  223 + return;
  224 + }
  225 + rows.push(data);
  226 + }).then((() => {
  227 + rows.forEach((element, index) => {
  228 + let trainAttendee = parseInt(element["train trips_amount"]);
  229 + let planeAttendee = parseInt(element["plane trips_amount"]);
  230 + let attendeeNumber = trainAttendee + planeAttendee;
  231 + element["emissions_per_capita"] = parseFloat(element.co2_kg) / attendeeNumber;
  232 + });
  233 +
  234 + rows.sort(function (a, b) {
  235 + if (a.emissions_per_capita > b.emissions_per_capita) {
  236 + return 1;
  237 + }
  238 + if (b.emissions_per_capita > a.emissions_per_capita) {
  239 + return -1;
  240 + }
  241 + return 0;
  242 + });
  243 + console.log(rows);
  244 + let dataIndex = 0;
  245 + rows.forEach((element, index) => {
  246 + let trainAttendee = parseInt(element["train trips_amount"]);
  247 + let planeAttendee = parseInt(element["plane trips_amount"]);
  248 + let attendeeNumber = trainAttendee + planeAttendee;
  249 + let co2_kg = parseFloat(element.co2_kg);
  250 + emissionsSum += co2_kg;
  251 + attendeeSum += attendeeNumber;
  252 + emissionsPerGroup[dataIndex] = emissionsSum;
  253 + attendeeNumberPerGroup[dataIndex] = attendeeSum;
  254 + dataIndex += 1;
  255 + });
  256 + // emissionsPerGroup.forEach((element, index) => {
  257 + // maxemissions = Math.max(maxemissions, element);
  258 + // maxemissionsPercent = Math.max(maxemissionsPercent, element / emissionsSum * 100.0)
  259 + // });
  260 + // maxDistance += 2000;
  261 + // console.log(maxDistance);
  262 +
  263 + //Title
  264 + svg.append("text")
  265 + .attr("transform",
  266 + "translate(" + (70 + margin.left) + ", -12)")
  267 + .style("text-anchor", "middle")
  268 + .style("font-weight", "bold")
  269 + .style("font-size", "130%")
  270 + .text("Sorted carbon emissions");
  271 +
  272 + // X axis: scale and draw:
  273 + let x = d3.scaleLinear()
  274 + .domain([0, maxAttendeePercent])
  275 + .range([0, width]);
  276 + let xAxis = d3.axisBottom(x)
  277 + .tickValues(getBottomTicks(maxAttendeePercent));
  278 + svg.append("g")
  279 + .attr("transform", "translate(0," + height + ")")
  280 + .attr("class", "x axis")
  281 + .call(xAxis);
  282 +
  283 + // Y axis Left
  284 + let y = d3.scaleLinear()
  285 + .domain([0, maxEmissionsPercent])
  286 + .range([height, 0]);
  287 + let yAxis = d3.axisLeft(y)
  288 + .tickValues(getLeftTicks(maxEmissionsPercent));
  289 + svg.append("g")
  290 + .attr("class", "y axis")
  291 + .call(yAxis);
  292 +
  293 + svg.append("text")
  294 + .attr("transform",
  295 + "translate(" + (width/2) + " ," +
  296 + (height + margin.top + 12) + ")")
  297 + .style("text-anchor", "middle")
  298 + .text("% of participants, sorted by per capita emission");
  299 +
  300 + svg.append("text")
  301 + .attr("transform", "rotate(-90)")
  302 + .attr("y", 0 - margin.left)
  303 + .attr("x",0 - (height / 2))
  304 + .attr("dy", "1em")
  305 + .style("text-anchor", "middle")
  306 + .text("% of total emissions");
  307 +
  308 + let barSettings = [];
  309 + emissionsPerGroup.forEach((element, index) => {
  310 + let bottomBorder;
  311 + let leftBorder;
  312 + if(index === 0)
  313 + {
  314 + bottomBorder = 0;
  315 + leftBorder = 0;
  316 + }
  317 + else
  318 + {
  319 + bottomBorder = emissionsPerGroup[index-1] / emissionsSum * 100.0;
  320 + leftBorder = attendeeNumberPerGroup[index-1] /attendeeSum * 100.0;
  321 + }
  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 + };
  329 + // console.log(index);
  330 + // console.log(barSettings[index]);
  331 + });
  332 + // console.log(barSettings);
  333 + svg.selectAll("rect")
  334 + .data(barSettings)
  335 + .enter()
  336 + .append("rect")
  337 + .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)); })
  341 + .style("z-index", "500")
  342 + .style("fill", "#4444E5");
  343 + addVerticalLineAndListenCursor(x, y, barSettings);
  344 + }));
  345 +
  346 + }
  347 +};
0 348 \ No newline at end of file
... ...