Blame view

flaskr/static/js/plots/sorted_emissions_inequality.js 13.7 KB
2ee2acee   Antoine Goutenoir   feat: continue wi...
1
2
3
4
5
6
7
8
9
10
11
12
13
function draw_sorted_emissions_inequality(containerSelector, csvUrl) {

    // set the dimensions and margins of the graph
    let margin = {top: 30, right: 10, bottom: 62, left: 72},
        width = 600 - margin.left - margin.right,
        height = 700 - 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;
566355a9   Adrenesis   Add sorted-carbon...
14
    }
2ee2acee   Antoine Goutenoir   feat: continue wi...
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

    function getBottomTicks(maxAttendeePercent) {
        return getTicks(maxAttendeePercent, 20);
    }

    function getLeftTicks(maxemissionsPercent) {
        return getTicks(maxemissionsPercent, 20);
    }

    function getSliceCollision(x, y, barSettings) {
        let result = false;
        barSettings.forEach((element, index) => {
            if (x < element.rightBorder && x > element.leftBorder) {
                let binYDiff = element.topBorder - element.bottomBorder;
                let binXDiff = element.rightBorder - element.leftBorder;
                let binDiagonalAngle = Math.atan2(binYDiff, binXDiff);
                // let binYCenter = (element.topBorder + element.bottomBorder)/2;
                // let binXCenter = (element.rightBorder + element.leftBorder)/2;
                let mouseXDiff = element.rightBorder - x;
                let mouseYDiff = element.topBorder - y;
                let mouseToCenterAngle = Math.atan2(mouseYDiff, mouseXDiff);
                // console.log(binDiagonalAngle);
                // console.log(mouseToCenterAngle);

                if (mouseToCenterAngle < binDiagonalAngle) {
                    barSettings.forEach((element, index) => {
                        if (y < element.topBorder && y > element.bottomBorder) {
                            let lb = barSettings[index].leftBorder;
                            let rb = barSettings[index].rightBorder;
                            let tb = barSettings[index].topBorder;
                            let bb = barSettings[index].bottomBorder;
                            let binCollisionRatio = (y - bb) / (tb - bb);
                            let otherAxisLevel = (rb - lb) * binCollisionRatio + lb;
                            result = {
                                binDiagonalAngle: binDiagonalAngle,
                                isXDriving: false,
                                binIndex: index,
                                otherAxisLevel: otherAxisLevel
                            };

                        }
                    });
566355a9   Adrenesis   Add sorted-carbon...
57
58


2ee2acee   Antoine Goutenoir   feat: continue wi...
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
                }
                else {
                    let lb = barSettings[index].leftBorder;
                    let rb = barSettings[index].rightBorder;
                    let tb = barSettings[index].topBorder;
                    let bb = barSettings[index].bottomBorder;
                    let binCollisionRatio = (x - lb) / (rb - lb);
                    let otherAxisLevel = (tb - bb) * binCollisionRatio + bb;
                    // console.log(otherAxisLevel);
                    result = {
                        binDiagonalAngle: binDiagonalAngle,
                        isXDriving: true,
                        binIndex: index,
                        otherAxisLevel: otherAxisLevel
                    }
566355a9   Adrenesis   Add sorted-carbon...
74
75
                }
            }
2ee2acee   Antoine Goutenoir   feat: continue wi...
76
77
78
        });
        return result;

566355a9   Adrenesis   Add sorted-carbon...
79
    }
566355a9   Adrenesis   Add sorted-carbon...
80

2ee2acee   Antoine Goutenoir   feat: continue wi...
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
    function setupCursorBoxes(event, xScale, yScale, barSettings, vertical, horizontal, box) {
        // mousex = d3.mouse(this);
        const x = d3.pointer(event)[0];
        const y = d3.pointer(event)[1];
        // var y = d3.event.pageY - document.getElementById(<id-of-your-svg>).getBoundingClientRect().y + 10
        // x += 5;
        box.style("left", (x + 10) + "px");
        box.style("top", (y - 20) + "px");
        let xInGraph = xScale.invert(x - margin.left);
        let yInGraph = yScale.invert(y - margin.top);


        // 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 < margin.left
            ||
            x > width + margin.left
            ||
            y < margin.top
            ||
            y > height + margin.top
    ) {
            vertical.style("width", 0);
            horizontal.style("height", 0);
            box.style("display", "none");
566355a9   Adrenesis   Add sorted-carbon...
107
        }
2ee2acee   Antoine Goutenoir   feat: continue wi...
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
        else {
            vertical.style("width", "2px");
            horizontal.style("height", "2px");
            box.style("display", "inherit");
            let sliceCollision = getSliceCollision(xInGraph, yInGraph, barSettings);
            // console.log(sliceCollision);
            if (sliceCollision) {
                if (sliceCollision.isXDriving) {
                    vertical.style("left", x + "px");
                    horizontal.style("top", yScale(sliceCollision.otherAxisLevel) + margin.top + "px");

                    box.text(xInGraph + " " + sliceCollision.otherAxisLevel);
                } else {
                    horizontal.style("top", y + "px");
                    vertical.style("left", xScale(sliceCollision.otherAxisLevel) + margin.right + "px");

                    box.text(sliceCollision.otherAxisLevel + " " + yInGraph);
                }
            }
566355a9   Adrenesis   Add sorted-carbon...
127

2ee2acee   Antoine Goutenoir   feat: continue wi...
128
129
130
131
        }
        // 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);
566355a9   Adrenesis   Add sorted-carbon...
132
    }
566355a9   Adrenesis   Add sorted-carbon...
133

2ee2acee   Antoine Goutenoir   feat: continue wi...
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
    function addVerticalLineAndListenCursor(xScale, yScale, barSettings) {
        let vertical = d3.select(containerSelector)
            .append("div")
            .attr("class", "no-pointer-events")
            .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 horizontal = d3.select(containerSelector)
            .append("div")
            .attr("class", "no-pointer-events")
            .style("position", "absolute")
            .style("z-index", "19")
            .style("width", (width) + "px")
            .style("height", "2px")
            .style("top", "0px")
            .style("bottom", "30px")
            .style("left", (10 + margin.left) + "px")
            .style("background", "#000");

        let box = d3.select(containerSelector)
            .append("div")
            .attr("class", "no-pointer-events")
            .style("position", "absolute")
            .style("z-index", "20")
            .style("width", "150px")
            .style("height", "44px")
            .style("top", "10px")
            .style("bottom", "30px")
            .style("left", "0px")
            .style("border", "1px solid grey")
            .style("background", "rgba(255, 255, 255, 0.7)");

        d3.select(containerSelector)
            .on("mousemove", function (event) {
                setupCursorBoxes(event, xScale, yScale, barSettings, vertical, horizontal, box);
            })
            .on("mouseover", function (event) {
                setupCursorBoxes(event, xScale, yScale, barSettings, vertical, horizontal, box);
            });
    }
566355a9   Adrenesis   Add sorted-carbon...
180
181


2ee2acee   Antoine Goutenoir   feat: continue wi...
182
183
184
    document.addEventListener("DOMContentLoaded", () => {
        width = Math.max(880, $(containerSelector).parent().width());
        width = width - margin.left - margin.right;
566355a9   Adrenesis   Add sorted-carbon...
185
186
        let maxAttendeePercent = 100;
        let maxEmissionsPercent = 100;
2ee2acee   Antoine Goutenoir   feat: continue wi...
187
        let svg = d3.select(containerSelector)
566355a9   Adrenesis   Add sorted-carbon...
188
189
190
191
192
193
194
195
196
197
198
199
            .append("svg")
            .attr("id", "graph-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;
2ee2acee   Antoine Goutenoir   feat: continue wi...
200
201
202
203
204
        let data = [];
        d3.csv(csvUrl, function (datum) {
            let trainAttendee = parseInt(datum["train trips_amount"]);
            let planeAttendee = parseInt(datum["plane trips_amount"]);
            if (trainAttendee === 0 && planeAttendee === 0) {
566355a9   Adrenesis   Add sorted-carbon...
205
206
207
                return;
            }
            let attendeeNumber = trainAttendee + planeAttendee;
2ee2acee   Antoine Goutenoir   feat: continue wi...
208
209
210
            let distance_km = datum.distance_km / attendeeNumber;
            let co2_kg = parseFloat(datum.co2_kg);
            if (co2_kg === "NaN" || distance_km === "NaN") {
566355a9   Adrenesis   Add sorted-carbon...
211
212
                return;
            }
2ee2acee   Antoine Goutenoir   feat: continue wi...
213
            data.push(datum);
566355a9   Adrenesis   Add sorted-carbon...
214
        }).then((() => {
2ee2acee   Antoine Goutenoir   feat: continue wi...
215
216
217
            data.forEach((datum, index) => {
                let trainAttendee = parseInt(datum["train trips_amount"]);
                let planeAttendee = parseInt(datum["plane trips_amount"]);
566355a9   Adrenesis   Add sorted-carbon...
218
                let attendeeNumber = trainAttendee + planeAttendee;
2ee2acee   Antoine Goutenoir   feat: continue wi...
219
                datum["emissions_per_capita"] = parseFloat(datum.co2_kg) / attendeeNumber;
566355a9   Adrenesis   Add sorted-carbon...
220
221
            });

2ee2acee   Antoine Goutenoir   feat: continue wi...
222
            data.sort(function (a, b) {
566355a9   Adrenesis   Add sorted-carbon...
223
224
225
226
227
228
229
230
                if (a.emissions_per_capita > b.emissions_per_capita) {
                    return 1;
                }
                if (b.emissions_per_capita > a.emissions_per_capita) {
                    return -1;
                }
                return 0;
            });
2ee2acee   Antoine Goutenoir   feat: continue wi...
231
            console.log(data);
566355a9   Adrenesis   Add sorted-carbon...
232
            let dataIndex = 0;
2ee2acee   Antoine Goutenoir   feat: continue wi...
233
234
235
            data.forEach((datum, index) => {
                let trainAttendee = parseInt(datum["train trips_amount"]);
                let planeAttendee = parseInt(datum["plane trips_amount"]);
566355a9   Adrenesis   Add sorted-carbon...
236
                let attendeeNumber = trainAttendee + planeAttendee;
2ee2acee   Antoine Goutenoir   feat: continue wi...
237
                let co2_kg = parseFloat(datum.co2_kg);
566355a9   Adrenesis   Add sorted-carbon...
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
                emissionsSum += co2_kg;
                attendeeSum += attendeeNumber;
                emissionsPerGroup[dataIndex] = emissionsSum;
                attendeeNumberPerGroup[dataIndex] = attendeeSum;
                dataIndex += 1;
            });
            // 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",
2ee2acee   Antoine Goutenoir   feat: continue wi...
254
                    "translate(" + (70 + margin.left) + ", -12)")
566355a9   Adrenesis   Add sorted-carbon...
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
                .style("text-anchor", "middle")
                .style("font-weight", "bold")
                .style("font-size", "130%")
                .text("Sorted carbon emissions");

            // X axis: scale and draw:
            let x = d3.scaleLinear()
                .domain([0, maxAttendeePercent])
                .range([0, width]);
            let xAxis = d3.axisBottom(x)
                .tickValues(getBottomTicks(maxAttendeePercent));
            svg.append("g")
                .attr("transform", "translate(0," + height + ")")
                .attr("class", "x axis")
                .call(xAxis);

            // Y axis Left
            let y = d3.scaleLinear()
                .domain([0, maxEmissionsPercent])
                .range([height, 0]);
            let yAxis = d3.axisLeft(y)
                .tickValues(getLeftTicks(maxEmissionsPercent));
            svg.append("g")
                .attr("class", "y axis")
                .call(yAxis);

            svg.append("text")
                .attr("transform",
2ee2acee   Antoine Goutenoir   feat: continue wi...
283
                    "translate(" + (width / 2) + " ," +
566355a9   Adrenesis   Add sorted-carbon...
284
285
286
287
288
289
290
                    (height + margin.top + 12) + ")")
                .style("text-anchor", "middle")
                .text("% of participants, sorted by per capita emission");

            svg.append("text")
                .attr("transform", "rotate(-90)")
                .attr("y", 0 - margin.left)
2ee2acee   Antoine Goutenoir   feat: continue wi...
291
                .attr("x", 0 - (height / 2))
566355a9   Adrenesis   Add sorted-carbon...
292
293
294
295
296
297
298
299
                .attr("dy", "1em")
                .style("text-anchor", "middle")
                .text("% of total emissions");

            let barSettings = [];
            emissionsPerGroup.forEach((element, index) => {
                let bottomBorder;
                let leftBorder;
2ee2acee   Antoine Goutenoir   feat: continue wi...
300
                if (index === 0) {
566355a9   Adrenesis   Add sorted-carbon...
301
302
303
                    bottomBorder = 0;
                    leftBorder = 0;
                }
2ee2acee   Antoine Goutenoir   feat: continue wi...
304
305
306
                else {
                    bottomBorder = emissionsPerGroup[index - 1] / emissionsSum * 100.0;
                    leftBorder = attendeeNumberPerGroup[index - 1] / attendeeSum * 100.0;
566355a9   Adrenesis   Add sorted-carbon...
307
                }
2ee2acee   Antoine Goutenoir   feat: continue wi...
308
309
310
311
312
313
314
                barSettings[index] =
                    {
                        topBorder: emissionsPerGroup[index] / emissionsSum * 100.0,
                        bottomBorder: bottomBorder,
                        leftBorder: leftBorder,
                        rightBorder: attendeeNumberPerGroup[index] / attendeeSum * 100.0,
                    };
566355a9   Adrenesis   Add sorted-carbon...
315
316
317
318
319
320
321
322
323
                // console.log(index);
                // console.log(barSettings[index]);
            });
            // console.log(barSettings);
            svg.selectAll("rect")
                .data(barSettings)
                .enter()
                .append("rect")
                .attr("x", 1)
2ee2acee   Antoine Goutenoir   feat: continue wi...
324
325
326
327
328
329
330
331
332
                .attr("transform", function (d) {
                    return "translate(" + x(d.leftBorder) + "," + y(d.topBorder) + ")";
                })
                .attr("width", function (d) {
                    return x(d.rightBorder) - x(d.leftBorder) - 1;
                })
                .attr("height", function (d) {
                    return (y(d.bottomBorder) - y(d.topBorder));
                })
566355a9   Adrenesis   Add sorted-carbon...
333
334
335
336
337
                .style("z-index", "500")
                .style("fill", "#4444E5");
            addVerticalLineAndListenCursor(x, y, barSettings);
        }));

2ee2acee   Antoine Goutenoir   feat: continue wi...
338
339
340
341

    });

}