Commit 11ab55967280569490066cb5e4d33a59606ac934

Authored by Adrenesis
1 parent 4ecd3df0
Exists in master

Add emission-per-distance.js

Showing 1 changed file with 290 additions and 0 deletions   Show diff stats
plots/emission-per-distance.js 0 → 100644
... ... @@ -0,0 +1,290 @@
  1 +// set the dimensions and margins of the graph
  2 +let margin = {top: 30, right: 62, bottom: 62, left: 72},
  3 + width = 960 - margin.left - margin.right,
  4 + height = 540 - margin.top - margin.bottom;
  5 +
  6 +let divId = "chart-container";
  7 +
  8 +function getTicks(maxValue, interval, startValue=0)
  9 +{
  10 + let range = [];
  11 + for (let i = startValue ; i <= maxValue ; i+=interval)
  12 + {
  13 + range.push(i);
  14 + }
  15 + return range;
  16 +}
  17 +
  18 +function getBottomTicks(maxDistance) {
  19 + let range = getTicks(maxDistance, 2500, 2500);
  20 + range.push(500);
  21 + return range;
  22 +}
  23 +
  24 +function getLeftTicks(maxEmission) {
  25 + return getTicks(maxEmission, Math.floor((maxEmission / 8) / 1000)* 1000) ;
  26 +}
  27 +
  28 +function getRightTicks(maxEmissionPercent) {
  29 + return getTicks(maxEmissionPercent, 2);
  30 +}
  31 +
  32 +function getAttendeeOnRight(sliceId, attendeeNumberPerGroup)
  33 +{
  34 + let attendeeSum = 0;
  35 + let sliceInt = Math.floor(sliceId);
  36 + let sliceFloat = sliceId - sliceInt;
  37 + for(let i = sliceInt; i < attendeeNumberPerGroup.length; i++)
  38 + {
  39 + attendeeSum += attendeeNumberPerGroup[i] * (1 - sliceFloat);
  40 + sliceFloat = 0;
  41 + }
  42 + return attendeeSum;
  43 +
  44 +}
  45 +
  46 +function setupCursorBoxes(event, attendeeSum, attendeeNumberPerGroup, xScale, box, vertical, rightArea)
  47 +{
  48 + // mousex = d3.mouse(this);
  49 + var x = d3.pointer(event)[0];
  50 + var y = d3.pointer(event)[1];
  51 + // var y = d3.event.pageY - document.getElementById(<id-of-your-svg>).getBoundingClientRect().y + 10
  52 + // x += 5;
  53 + vertical.style("left", x + "px" );
  54 + rightArea.style("left", x + "px" );
  55 + box.style("left", (x + 10) + "px");
  56 + box.style("top", (y - 20) + "px");
  57 + let sliceId = xScale.invert(x - d3.selectAll("g.yl.axis")._groups[0][0].getBoundingClientRect().right)/500;
  58 + // let sliceId = xScale.invert(x * 1.025 - d3.selectAll("g.yl.axis")._groups[0][0].getBoundingClientRect().x- margin.left)/500 +1;
  59 + let attendeePercent = (getAttendeeOnRight(sliceId, attendeeNumberPerGroup) / attendeeSum * 100.0).toFixed(1);
  60 + if(x > d3.selectAll("g.yr.axis")._groups[0][0].getBoundingClientRect().x ||
  61 + x < d3.selectAll("g.yl.axis")._groups[0][0].getBoundingClientRect().right)
  62 + {
  63 + rightArea.style("width", 0);
  64 + vertical.style("width", 0);
  65 + box.style("display", "none");
  66 + }
  67 + else
  68 + {
  69 + rightArea.style("width", d3.selectAll("g.yr.axis")._groups[0][0].getBoundingClientRect().x - x );
  70 + vertical.style("width", "2px");
  71 + box.style("display", "inherit");
  72 + }
  73 + box.text(attendeePercent + " % of attendees");
  74 + box.text(attendeePercent + " % of attendees");
  75 + // console.log(d3.selectAll("g.x.axis")._groups[0][0]);
  76 + // console.log(d3.selectAll("g.x.axis")._groups[0][0].getBoundingClientRect().x);
  77 +}
  78 +
  79 +function addVerticalLineAndListenCursor(xScale, attendeeNumberPerGroup, attendeeSum) {
  80 + let vertical = d3.select("#" + divId)
  81 + .append("div")
  82 + .attr("class", "remove")
  83 + .style("position", "absolute")
  84 + .style("z-index", "19")
  85 + .style("width", "2px")
  86 + .style("height", (height) + "px")
  87 + .style("top", (10 + margin.top) + "px")
  88 + .style("bottom", "30px")
  89 + .style("left", "0px")
  90 + .style("background", "#000");
  91 +
  92 + let rightArea = d3.select("#" + divId)
  93 + .append("div")
  94 + .attr("class", "remove")
  95 + .style("position", "absolute")
  96 + .style("z-index", "-50")
  97 + .style("width", "2000px")
  98 + .style("height", (height) + "px")
  99 + .style("top", (10 + margin.top) + "px")
  100 + .style("bottom", "30px")
  101 + .style("left", "0px")
  102 + .style("background", "rgba(60, 200, 60, 0.3)");
  103 +
  104 +
  105 + let box = d3.select("#" + divId)
  106 + .append("div")
  107 + .attr("class", "remove")
  108 + .style("position", "absolute")
  109 + .style("z-index", "20")
  110 + .style("width", "150px")
  111 + .style("height", "22px")
  112 + .style("top", "10px")
  113 + .style("bottom", "30px")
  114 + .style("left", "0px")
  115 + .style("border", "1px solid grey")
  116 + .style("background", "rgba(255, 255, 255, 0.7)");
  117 + d3.select("#" + divId)
  118 + .on("mousemove", function(event){
  119 + setupCursorBoxes(event, attendeeSum, attendeeNumberPerGroup, xScale, box, vertical, rightArea);
  120 + })
  121 + .on("mouseover", function(event){
  122 + setupCursorBoxes(event, attendeeSum, attendeeNumberPerGroup, xScale, box, vertical, rightArea);
  123 +
  124 + });
  125 +}
  126 +
  127 +
  128 +document.onreadystatechange = () => {
  129 + if (document.readyState === 'complete') {
  130 + let maxEmission = 0;
  131 + let maxEmissionPercent = 0;
  132 + let maxDistance = 0;
  133 + let svg = d3.select("#" + divId)
  134 + .append("svg")
  135 + .attr("id", "graph-svg")
  136 + .attr("width", width + margin.left + margin.right)
  137 + .attr("height", height + margin.top + margin.bottom)
  138 + .append("g")
  139 + .attr("transform",
  140 + "translate(" + margin.left + "," + margin.top + ")");
  141 +
  142 + let emissionPerGroup = [];
  143 + let attendeeNumberPerGroup = [];
  144 + let emissionSum = 0;
  145 + let attendeeSum = 0;
  146 + let rows = [];
  147 +
  148 +
  149 + d3.csv("2020-09-30_04_21_19_87a1.csv", function (data) {
  150 + let trainAttendee = parseInt(data["train trips_amount"]);
  151 + let planeAttendee = parseInt(data["plane trips_amount"]);
  152 + if(trainAttendee === 0 && planeAttendee === 0)
  153 + {
  154 + return;
  155 + }
  156 + let attendeeNumber = trainAttendee + planeAttendee;
  157 + let distance_km = data.distance_km / attendeeNumber;
  158 + let co2_kg = parseFloat(data.co2_kg);
  159 + if (co2_kg === "NaN" || distance_km/500 > 37 || distance_km === "NaN")
  160 + {
  161 + return;
  162 + }
  163 + rows.push(data);
  164 + maxDistance = Math.max(maxDistance, distance_km);
  165 + emissionSum += co2_kg;
  166 + }).then((() => {
  167 + for (let i = 0; i <= maxDistance/500; i++)
  168 + {
  169 + emissionPerGroup[i] = 0;
  170 + attendeeNumberPerGroup[i] = 0;
  171 + }
  172 + rows.forEach((element, index) => {
  173 + let trainAttendee = parseInt(element["train trips_amount"]);
  174 + let planeAttendee = parseInt(element["plane trips_amount"]);
  175 + let attendeeNumber = trainAttendee + planeAttendee;
  176 + let distance_km = element.distance_km / attendeeNumber;
  177 + let co2_kg = parseFloat(element.co2_kg);
  178 + emissionPerGroup[Math.floor(distance_km/500)] += parseFloat(co2_kg);
  179 + attendeeNumberPerGroup[Math.floor(distance_km/500)] += attendeeNumber;
  180 + attendeeSum += attendeeNumber;
  181 + });
  182 + emissionPerGroup.forEach((element, index) => {
  183 + maxEmission = Math.max(maxEmission, element);
  184 + maxEmissionPercent = Math.max(maxEmissionPercent, element / emissionSum * 100.0)
  185 + });
  186 + maxDistance += 2000;
  187 + // console.log(maxDistance);
  188 +
  189 + //Title
  190 + svg.append("text")
  191 + .attr("transform",
  192 + "translate(" + (70 + margin.left) + ", -12)")
  193 + .style("text-anchor", "middle")
  194 + .style("font-weight", "bold")
  195 + .style("font-size", "130%")
  196 + .text("Emissions per distance");
  197 +
  198 + // X axis: scale and draw:
  199 + let x = d3.scaleLinear()
  200 + .domain([0, maxDistance])
  201 + .range([0, width]);
  202 + let xAxis = d3.axisBottom(x)
  203 + .tickValues(getBottomTicks(maxDistance));
  204 + svg.append("g")
  205 + .attr("transform", "translate(0," + height + ")")
  206 + .attr("class", "x axis")
  207 + .call(xAxis);
  208 + d3.selectAll("g.x.axis")
  209 + .selectAll(".tick")
  210 + .filter(function (d) {
  211 + return d === 0;
  212 + })
  213 + .remove();
  214 +
  215 + // Y axis Left
  216 + let yl = d3.scaleLinear()
  217 + .domain([0, maxEmission])
  218 + .range([height, 0]);
  219 + let ylAxis = d3.axisLeft(yl)
  220 + .tickValues(getLeftTicks(maxEmission));
  221 + svg.append("g")
  222 + .attr("class", "yl axis")
  223 + .call(ylAxis);
  224 +
  225 + // Y axis Right
  226 + let yr = d3.scaleLinear()
  227 + .domain([0, maxEmissionPercent])
  228 + .range([height, 0]);
  229 + let yrAxis = d3.axisRight(yr)
  230 + .tickValues(getRightTicks(maxEmissionPercent));
  231 + svg.append("g")
  232 + .attr("transform", "translate(" + width + ", 0)")
  233 + .attr("class", "yr axis")
  234 + .call(yrAxis);
  235 +
  236 + svg.append("text")
  237 + .attr("transform",
  238 + "translate(" + (width/2) + " ," +
  239 + (height + margin.top + 12) + ")")
  240 + .style("text-anchor", "middle")
  241 + .text("Distance travelled (km)");
  242 +
  243 + svg.append("text")
  244 + .attr("transform",
  245 + "translate(" + (width) + ", 0), rotate(-90)")
  246 + .attr("x",0 - (height / 2))
  247 + .attr("y", 42)
  248 + .style("text-anchor", "middle")
  249 + .text("Share of emission [%]");
  250 +
  251 + svg.append("text")
  252 + .attr("transform", "rotate(-90)")
  253 + .attr("y", 0 - margin.left)
  254 + .attr("x",0 - (height / 2))
  255 + .attr("dy", "1em")
  256 + .style("text-anchor", "middle")
  257 + .text("Emission (tCO2e)");
  258 + // set the parameters for the histogram
  259 + var histogram = d3.histogram()
  260 + .domain(x.domain()) // then the domain of the graphic
  261 + .thresholds(x.ticks(Math.floor(maxDistance/500))); // then the numbers of bins
  262 +
  263 + let histolol = histogram(0);
  264 + // console.log(histolol);
  265 + let barSettings = [];
  266 + emissionPerGroup.forEach((element, index) => {
  267 + barSettings[index]=
  268 + {
  269 + height : element,
  270 + leftBorder : histolol[index].x0,
  271 + rightBorder : histolol[index].x1,
  272 + };
  273 + // console.log(index);
  274 + // console.log(barSettings[index]);
  275 + });
  276 + svg.selectAll("rect")
  277 + .data(barSettings)
  278 + .enter()
  279 + .append("rect")
  280 + .attr("x", 1)
  281 + .attr("transform", function(d) { return "translate(" + x(d.leftBorder) + "," + yl(d.height) + ")"; })
  282 + .attr("width", function(d) { return x(d.rightBorder) - x(d.leftBorder) -1 ; })
  283 + .attr("height", function(d) { return (height-yl(d.height)); })
  284 + .style("z-index", "500")
  285 + .style("fill", "#4444E5");
  286 + addVerticalLineAndListenCursor(x, attendeeNumberPerGroup, attendeeSum);
  287 + }));
  288 +
  289 + }
  290 +};
0 291 \ No newline at end of file
... ...