diff --git a/flaskr/static/js/plots/emissions-per-distance.js b/flaskr/static/js/plots/emissions-per-distance.js index 995114b..6543e86 100644 --- a/flaskr/static/js/plots/emissions-per-distance.js +++ b/flaskr/static/js/plots/emissions-per-distance.js @@ -1,300 +1,294 @@ // export draw_emissions_per_distance function draw_emissions_per_distance(divId, csvUrl) { - (() => { - // let divId = "emissions_per_distance_histogram"; + // let divId = "emissions_per_distance_histogram"; - // set the dimensions and margins of the graph - let margin = {top: 30, right: 62, bottom: 62, left: 72}, - width = 960 - margin.left - margin.right, - height = 540 - margin.top - margin.bottom; + // set the dimensions and margins of the graph + let margin = {top: 30, right: 62, bottom: 62, left: 72}, + width = 960 - margin.left - margin.right, + height = 540 - margin.top - margin.bottom; - function getTicks(maxValue, interval, startValue = 0) { - let range = []; - for (let i = startValue; i <= maxValue; i += interval) { - range.push(i); - } - return range; + function getTicks(maxValue, interval, startValue = 0) { + let range = []; + for (let i = startValue; i <= maxValue; i += interval) { + range.push(i); } + return range; + } - function getBottomTicks(maxDistance) { - let range = getTicks(maxDistance, 2500, 2500); - range.push(500); - return range; - } + function getBottomTicks(maxDistance) { + let range = getTicks(maxDistance, 2500, 2500); + range.push(500); + return range; + } - function getLeftTicks(maxemissions) { - return getTicks(maxemissions, Math.floor((maxemissions / 8) / 1000) * 1000); - } + function getLeftTicks(maxemissions) { + return getTicks(maxemissions, Math.floor((maxemissions / 8) / 1000) * 1000); + } - function getRightTicks(maxemissionsPercent) { - return getTicks(maxemissionsPercent, 2); + function getRightTicks(maxemissionsPercent) { + return getTicks(maxemissionsPercent, 2); + } + + function getAttendeeOnRight(sliceId, attendeeNumberPerGroup) { + let attendeeSum = 0; + let sliceInt = Math.floor(sliceId); + let sliceFloat = sliceId - sliceInt; + for (let i = sliceInt; i < attendeeNumberPerGroup.length; i++) { + attendeeSum += attendeeNumberPerGroup[i] * (1 - sliceFloat); + sliceFloat = 0; } + return attendeeSum; - function getAttendeeOnRight(sliceId, attendeeNumberPerGroup) { - let attendeeSum = 0; - let sliceInt = Math.floor(sliceId); - let sliceFloat = sliceId - sliceInt; - for (let i = sliceInt; i < attendeeNumberPerGroup.length; i++) { - attendeeSum += attendeeNumberPerGroup[i] * (1 - sliceFloat); - sliceFloat = 0; - } - return attendeeSum; + } + function setupCursorBoxes(event, attendeeSum, attendeeNumberPerGroup, xScale, box, vertical, rightArea) { + // mousex = d3.mouse(this); + // const x = d3.mouse(this)[0]; + // const y = d3.mouse(this)[1]; + const x = d3.pointer(event)[0]; + const y = d3.pointer(event)[1]; + // var y = d3.event.pageY - document.getElementById().getBoundingClientRect().y + 10 + // x += 5; + vertical.style("left", x + "px"); + rightArea.style("left", x + "px"); + box.style("left", (x + 10) + "px"); + box.style("top", (y - 20) + "px"); + let sliceId = xScale.invert(x - d3.selectAll("g.yl.axis")._groups[0][0].getBoundingClientRect().right) / 500; + // let sliceId = xScale.invert(x * 1.025 - d3.selectAll("g.yl.axis")._groups[0][0].getBoundingClientRect().x- margin.left)/500 +1; + let attendeePercent = (getAttendeeOnRight(sliceId, attendeeNumberPerGroup) / attendeeSum * 100.0).toFixed(1); + if (x > d3.selectAll("g.yr.axis")._groups[0][0].getBoundingClientRect().x || + x < d3.selectAll("g.yl.axis")._groups[0][0].getBoundingClientRect().right) { + rightArea.style("width", 0); + vertical.style("width", 0); + box.style("display", "none"); } - - function setupCursorBoxes(event, attendeeSum, attendeeNumberPerGroup, xScale, box, vertical, rightArea) { - // mousex = d3.mouse(this); - // const x = d3.mouse(this)[0]; - // const y = d3.mouse(this)[1]; - const x = d3.pointer(event)[0]; - const y = d3.pointer(event)[1]; - // var y = d3.event.pageY - document.getElementById().getBoundingClientRect().y + 10 - // x += 5; - vertical.style("left", x + "px"); - rightArea.style("left", x + "px"); - box.style("left", (x + 10) + "px"); - box.style("top", (y - 20) + "px"); - let sliceId = xScale.invert(x - d3.selectAll("g.yl.axis")._groups[0][0].getBoundingClientRect().right) / 500; - // let sliceId = xScale.invert(x * 1.025 - d3.selectAll("g.yl.axis")._groups[0][0].getBoundingClientRect().x- margin.left)/500 +1; - let attendeePercent = (getAttendeeOnRight(sliceId, attendeeNumberPerGroup) / attendeeSum * 100.0).toFixed(1); - if (x > d3.selectAll("g.yr.axis")._groups[0][0].getBoundingClientRect().x || - x < d3.selectAll("g.yl.axis")._groups[0][0].getBoundingClientRect().right) { - rightArea.style("width", 0); - vertical.style("width", 0); - box.style("display", "none"); - } - else { - rightArea.style("width", d3.selectAll("g.yr.axis")._groups[0][0].getBoundingClientRect().x - x); - vertical.style("width", "2px"); - box.style("display", "inherit"); - } - box.text(attendeePercent + " % of attendees"); - box.text(attendeePercent + " % of attendees"); - // console.log(d3.selectAll("g.x.axis")._groups[0][0]); - // console.log(d3.selectAll("g.x.axis")._groups[0][0].getBoundingClientRect().x); + else { + rightArea.style("width", d3.selectAll("g.yr.axis")._groups[0][0].getBoundingClientRect().x - x); + vertical.style("width", "2px"); + box.style("display", "inherit"); } + box.text(attendeePercent + " % of attendees"); + box.text(attendeePercent + " % of attendees"); + // console.log(d3.selectAll("g.x.axis")._groups[0][0]); + // console.log(d3.selectAll("g.x.axis")._groups[0][0].getBoundingClientRect().x); + } - function addVerticalLineAndListenCursor(xScale, attendeeNumberPerGroup, attendeeSum) { - let vertical = d3.select("#" + divId) - .append("div") - .attr("class", "remove") - .style("position", "absolute") - .style("z-index", "19") - .style("width", "2px") - .style("height", (height) + "px") - .style("top", (10 + margin.top) + "px") - .style("bottom", "30px") - .style("left", "0px") - .style("background", "#000"); + function addVerticalLineAndListenCursor(xScale, attendeeNumberPerGroup, attendeeSum) { + let vertical = d3.select("#" + divId) + .append("div") + .attr("class", "remove") + .style("position", "absolute") + .style("z-index", "19") + .style("width", "2px") + .style("height", (height) + "px") + .style("top", (10 + margin.top) + "px") + .style("bottom", "30px") + .style("left", "0px") + .style("background", "#000"); - let rightArea = d3.select("#" + divId) - .append("div") - .attr("class", "remove") - .style("position", "absolute") - .style("z-index", "-50") - .style("width", "2000px") - .style("height", (height) + "px") - .style("top", (10 + margin.top) + "px") - .style("bottom", "30px") - .style("left", "0px") - .style("background", "rgba(60, 200, 60, 0.3)"); + let rightArea = d3.select("#" + divId) + .append("div") + .attr("class", "remove") + .style("position", "absolute") + .style("z-index", "-50") + .style("width", "2000px") + .style("height", (height) + "px") + .style("top", (10 + margin.top) + "px") + .style("bottom", "30px") + .style("left", "0px") + .style("background", "rgba(60, 200, 60, 0.3)"); - let box = d3.select("#" + divId) - .append("div") - .attr("class", "remove") - .style("position", "absolute") - .style("z-index", "20") - .style("width", "150px") - .style("height", "22px") - .style("top", "10px") - .style("bottom", "30px") - .style("left", "0px") - .style("border", "1px solid grey") - .style("background", "rgba(255, 255, 255, 0.7)"); - d3.select("#" + divId) - .on("mousemove", function (event) { - setupCursorBoxes(event, attendeeSum, attendeeNumberPerGroup, xScale, box, vertical, rightArea); - }) - .on("mouseover", function (event) { - setupCursorBoxes(event, attendeeSum, attendeeNumberPerGroup, xScale, box, vertical, rightArea); - - }); - } + let box = d3.select("#" + divId) + .append("div") + .attr("class", "remove") + .style("position", "absolute") + .style("z-index", "20") + .style("width", "150px") + .style("height", "22px") + .style("top", "10px") + .style("bottom", "30px") + .style("left", "0px") + .style("border", "1px solid grey") + .style("background", "rgba(255, 255, 255, 0.7)"); + d3.select("#" + divId) + .on("mousemove", function (event) { + setupCursorBoxes(event, attendeeSum, attendeeNumberPerGroup, xScale, box, vertical, rightArea); + }) + .on("mouseover", function (event) { + setupCursorBoxes(event, attendeeSum, attendeeNumberPerGroup, xScale, box, vertical, rightArea); + }); + } - document.onreadystatechange = () => { - if (document.readyState === 'complete') { - let maxemissions = 0; - let maxemissionsPercent = 0; - let maxDistance = 0; - let svg = d3.select("#" + divId) - .append("svg") - .attr("id", divId + "-svg") - .attr("width", width + margin.left + margin.right) - .attr("height", height + margin.top + margin.bottom) - .append("g") - .attr("transform", - "translate(" + margin.left + "," + margin.top + ")"); + document.addEventListener("DOMContentLoaded", () => { + let maxemissions = 0; + let maxemissionsPercent = 0; + let maxDistance = 0; + let svg = d3.select("#" + divId) + .append("svg") + .attr("id", divId + "-svg") + .attr("width", width + margin.left + margin.right) + .attr("height", height + margin.top + margin.bottom) + .append("g") + .attr("transform", + "translate(" + margin.left + "," + margin.top + ")"); - let emissionsPerGroup = []; - let attendeeNumberPerGroup = []; - let emissionsSum = 0; - let attendeeSum = 0; - let rows = []; + let emissionsPerGroup = []; + let attendeeNumberPerGroup = []; + let emissionsSum = 0; + let attendeeSum = 0; + let rows = []; - const on_csv_datum = function (datum) { - let trainAttendee = parseInt(datum["train trips_amount"]); - let planeAttendee = parseInt(datum["plane trips_amount"]); - if (trainAttendee === 0 && planeAttendee === 0) { - return; - } - let attendeeNumber = trainAttendee + planeAttendee; - let distance_km = datum.distance_km / attendeeNumber; - let co2_kg = parseFloat(datum.co2_kg); - if (co2_kg === "NaN" || distance_km / 500 > 37 || distance_km === "NaN") { - return; - } - rows.push(datum); - maxDistance = Math.max(maxDistance, distance_km); - emissionsSum += co2_kg; - - }; + const on_csv_datum = function (datum) { + let trainAttendee = parseInt(datum["train trips_amount"]); + let planeAttendee = parseInt(datum["plane trips_amount"]); + if (trainAttendee === 0 && planeAttendee === 0) { + return; + } + let attendeeNumber = trainAttendee + planeAttendee; + let distance_km = datum.distance_km / attendeeNumber; + let co2_kg = parseFloat(datum.co2_kg); + if (co2_kg === "NaN" || distance_km / 500 > 37 || distance_km === "NaN") { + return; + } + rows.push(datum); + maxDistance = Math.max(maxDistance, distance_km); + emissionsSum += co2_kg; - const on_csv_ready = function () { - for (let i = 0; i <= maxDistance / 500; i++) { - emissionsPerGroup[i] = 0; - attendeeNumberPerGroup[i] = 0; - } - rows.forEach((element, index) => { - let trainAttendee = parseInt(element["train trips_amount"]); - let planeAttendee = parseInt(element["plane trips_amount"]); - let attendeeNumber = trainAttendee + planeAttendee; - let distance_km = element.distance_km / attendeeNumber; - let co2_kg = parseFloat(element.co2_kg); - emissionsPerGroup[Math.floor(distance_km / 500)] += parseFloat(co2_kg); - attendeeNumberPerGroup[Math.floor(distance_km / 500)] += attendeeNumber; - attendeeSum += attendeeNumber; - }); - emissionsPerGroup.forEach((element, index) => { - maxemissions = Math.max(maxemissions, element); - maxemissionsPercent = Math.max(maxemissionsPercent, element / emissionsSum * 100.0) - }); - maxDistance += 2000; - // console.log(maxDistance); + }; - //Title - svg.append("text") - .attr("transform", - "translate(" + (70 + margin.left) + ", -12)") - .style("text-anchor", "middle") - .style("font-weight", "bold") - .style("font-size", "130%") - .text("Emissions per distance"); + const on_csv_ready = function () { + for (let i = 0; i <= maxDistance / 500; i++) { + emissionsPerGroup[i] = 0; + attendeeNumberPerGroup[i] = 0; + } + rows.forEach((element, index) => { + let trainAttendee = parseInt(element["train trips_amount"]); + let planeAttendee = parseInt(element["plane trips_amount"]); + let attendeeNumber = trainAttendee + planeAttendee; + let distance_km = element.distance_km / attendeeNumber; + let co2_kg = parseFloat(element.co2_kg); + emissionsPerGroup[Math.floor(distance_km / 500)] += parseFloat(co2_kg); + attendeeNumberPerGroup[Math.floor(distance_km / 500)] += attendeeNumber; + attendeeSum += attendeeNumber; + }); + emissionsPerGroup.forEach((element, index) => { + maxemissions = Math.max(maxemissions, element); + maxemissionsPercent = Math.max(maxemissionsPercent, element / emissionsSum * 100.0) + }); + maxDistance += 2000; + // console.log(maxDistance); - // X axis: scale and draw: - let x = d3.scaleLinear() - .domain([0, maxDistance]) - .range([0, width]); - let xAxis = d3.axisBottom(x) - .tickValues(getBottomTicks(maxDistance)); - svg.append("g") - .attr("transform", "translate(0," + height + ")") - .attr("class", "x axis") - .call(xAxis); - d3.selectAll("g.x.axis") - .selectAll(".tick") - .filter(function (d) { - return d === 0; - }) - .remove(); + //Title + svg.append("text") + .attr("transform", + "translate(" + (70 + margin.left) + ", -12)") + .style("text-anchor", "middle") + .style("font-weight", "bold") + .style("font-size", "130%") + .text("Emissions per distance"); - // Y axis Left - let yl = d3.scaleLinear() - .domain([0, maxemissions]) - .range([height, 0]); - let ylAxis = d3.axisLeft(yl) - .tickValues(getLeftTicks(maxemissions)); - svg.append("g") - .attr("class", "yl axis") - .call(ylAxis); + // X axis: scale and draw: + let x = d3.scaleLinear() + .domain([0, maxDistance]) + .range([0, width]); + let xAxis = d3.axisBottom(x) + .tickValues(getBottomTicks(maxDistance)); + svg.append("g") + .attr("transform", "translate(0," + height + ")") + .attr("class", "x axis") + .call(xAxis); + d3.selectAll("g.x.axis") + .selectAll(".tick") + .filter(function (d) { + return d === 0; + }) + .remove(); - // Y axis Right - let yr = d3.scaleLinear() - .domain([0, maxemissionsPercent]) - .range([height, 0]); - let yrAxis = d3.axisRight(yr) - .tickValues(getRightTicks(maxemissionsPercent)); - svg.append("g") - .attr("transform", "translate(" + width + ", 0)") - .attr("class", "yr axis") - .call(yrAxis); + // Y axis Left + let yl = d3.scaleLinear() + .domain([0, maxemissions]) + .range([height, 0]); + let ylAxis = d3.axisLeft(yl) + .tickValues(getLeftTicks(maxemissions)); + svg.append("g") + .attr("class", "yl axis") + .call(ylAxis); - svg.append("text") - .attr("transform", - "translate(" + (width / 2) + " ," + - (height + margin.top + 12) + ")") - .style("text-anchor", "middle") - .text("Distance travelled (km)"); + // Y axis Right + let yr = d3.scaleLinear() + .domain([0, maxemissionsPercent]) + .range([height, 0]); + let yrAxis = d3.axisRight(yr) + .tickValues(getRightTicks(maxemissionsPercent)); + svg.append("g") + .attr("transform", "translate(" + width + ", 0)") + .attr("class", "yr axis") + .call(yrAxis); - svg.append("text") - .attr("transform", - "translate(" + (width) + ", 0), rotate(-90)") - .attr("x", 0 - (height / 2)) - .attr("y", 42) - .style("text-anchor", "middle") - .text("Share of emission [%]"); + svg.append("text") + .attr("transform", + "translate(" + (width / 2) + " ," + + (height + margin.top + 12) + ")") + .style("text-anchor", "middle") + .text("Distance travelled (km)"); - svg.append("text") - .attr("transform", "rotate(-90)") - .attr("y", 0 - margin.left) - .attr("x", 0 - (height / 2)) - .attr("dy", "1em") - .style("text-anchor", "middle") - .text("Emission (tCO2e)"); - // set the parameters for the histogram - var histogram = d3.histogram() - .domain(x.domain()) // then the domain of the graphic - .thresholds(x.ticks(Math.floor(maxDistance / 500))); // then the numbers of bins + svg.append("text") + .attr("transform", + "translate(" + (width) + ", 0), rotate(-90)") + .attr("x", 0 - (height / 2)) + .attr("y", 42) + .style("text-anchor", "middle") + .text("Share of emission [%]"); - let histolol = histogram(0); - // console.log(histolol); - let barSettings = []; - emissionsPerGroup.forEach((element, index) => { - barSettings[index] = - { - height: element, - leftBorder: histolol[index].x0, - rightBorder: histolol[index].x1, - }; - // console.log(index); - // console.log(barSettings[index]); - }); - svg.selectAll("rect") - .data(barSettings) - .enter() - .append("rect") - .attr("x", 1) - .attr("transform", function (d) { - return "translate(" + x(d.leftBorder) + "," + yl(d.height) + ")"; - }) - .attr("width", function (d) { - return x(d.rightBorder) - x(d.leftBorder) - 1; - }) - .attr("height", function (d) { - return (height - yl(d.height)); - }) - .style("z-index", "500") - .style("fill", "#4444E5"); - addVerticalLineAndListenCursor(x, attendeeNumberPerGroup, attendeeSum); - }; + svg.append("text") + .attr("transform", "rotate(-90)") + .attr("y", 0 - margin.left) + .attr("x", 0 - (height / 2)) + .attr("dy", "1em") + .style("text-anchor", "middle") + .text("Emission (tCO2e)"); + // set the parameters for the histogram + var histogram = d3.histogram() + .domain(x.domain()) // then the domain of the graphic + .thresholds(x.ticks(Math.floor(maxDistance / 500))); // then the numbers of bins - d3.csv(csvUrl, on_csv_datum) - .then(on_csv_ready); - } + let histolol = histogram(0); + // console.log(histolol); + let barSettings = []; + emissionsPerGroup.forEach((element, index) => { + barSettings[index] = + { + height: element, + leftBorder: histolol[index].x0, + rightBorder: histolol[index].x1, + }; + // console.log(index); + // console.log(barSettings[index]); + }); + svg.selectAll("rect") + .data(barSettings) + .enter() + .append("rect") + .attr("x", 1) + .attr("transform", function (d) { + return "translate(" + x(d.leftBorder) + "," + yl(d.height) + ")"; + }) + .attr("width", function (d) { + return x(d.rightBorder) - x(d.leftBorder) - 1; + }) + .attr("height", function (d) { + return (height - yl(d.height)); + }) + .style("z-index", "500") + .style("fill", "#4444E5"); + addVerticalLineAndListenCursor(x, attendeeNumberPerGroup, attendeeSum); }; - })(); + d3.csv(csvUrl, on_csv_datum) + .then(on_csv_ready); + }); } \ No newline at end of file -- libgit2 0.21.2