Plotapi – ParetoFront Diagram
.tippy-content
font-family: “Lato”, sans-serif !important;
#plotapi-chart-3dbbed15, #featured-plotapi-chart-3dbbed15
font-size: 16px;
font-family: “Lato”, sans-serif !important;
text-align: center;
fill: #454545;
#plotapi-chart-3dbbed15 svg, #featured-plotapi-chart-3dbbed15 svg
max-width: 740px;
#plotapi-chart-3dbbed15
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
font-family: Helvetica, sans-serif;
#plotapi-chart-3dbbed15 svg
margin-left: auto;
margin-right: auto;
#plotapi-chart-3dbbed15 path
fill: none;
stroke-linecap: round
#plotapi-chart-3dbbed15 .x_axis .tick:not(:first-of-type) line
stroke: #999;
stroke-opacity: 0.5;
stroke-dasharray: 2, 2
#plotapi-chart-3dbbed15 .x_axis .tick:first-of-type line
stroke: #999;
stroke-opacity: 0.5;
stroke-dasharray: 2, 2
#plotapi-chart-3dbbed15 .y_axis .tick:not(:first-of-type) line
stroke: #999;
stroke-opacity: 0.5;
stroke-dasharray: 2, 2
#plotapi-chart-3dbbed15 .y_axis .tick:first-of-type line
stroke: #999;
stroke-opacity: 0.5;
stroke-dasharray: 2, 2
#plotapi-chart-3dbbed15 .tick text
fill: #999;
#plotapi-chart-3dbbed15 .domain
stroke-width: 0;
(function() {
var jupyter_classic = !(typeof(IPython)===”undefined”);
var dependencies_paths =
‘d3’: ‘https://plotapi.com/static/js/d3.v7.min’,
‘@popperjs/core’: ‘https://plotapi.com/static/js/popper.min’,
‘tippy’: ‘https://plotapi.com/static/js/tippy.min’,
‘pako’: ‘https://plotapi.com/static/js/pako.min’
if(jupyter_classic)
require.config(
paths: dependencies_paths
);
require([‘d3′,’tippy’,’pako’], function(d3, tippy,pako)
window.d3 = d3;
window.tippy = tippy;
window.pako = pako;
plotapi_plot();
);
else
var dependencies = Object.values(dependencies_paths);
function dependency_loader(dependencies_loaded)
var script = document.createElement(“script”);
script.type = “text/javascript”;
script.src = dependencies[dependencies_loaded] + “.js”;
script.onload = function ()
if(dependencies_loaded < dependencies.length-1)
dependency_loader(dependencies_loaded+1)
else
plotapi_plot();
;
document.body.appendChild(script);
dependency_loader(0);
function plotapi_plot(){
function color(index)
ranks = n_final_ranks + 1;
if (index == 0)
return "#ff0000";
index = index – 1;
ranks = ranks – 1;
index = (ranks) – index;
var ratio = index / (ranks);
return d3.interpolateRainbow(ratio);
function darkenColor(color, factor)
return d3.color(color).darker(factor)
var sequence = [20200101, 20200104, 20200109, 20200112, 20200115, 20200120, 20200123, 20200125, 20200129, 20200130];
var sequence_index = 0;
var last_sequence_index;
var dataset;
var pareto_dataset;
var dominated_dataset;
var n_ranks;
var n_final_ranks;
var limit_y_axis;
var limit_x_axis;
var range_x;
var range_y;
var pareto_range_x;
var pareto_range_y;
var zoomed = true;
var zoomed_user = true;
var y_scale;
var x_scale;
var y_axis;
var x_axis;
var zoom_timeout;
var auto_proceed_timeout;
var auto_proceed_interrupt = false;
var dataset_collection = "eJztmstqwzAQRX/FeB2KHlaa9ldCKH1tWojBtN2E/nvdQsF2LI0nkp1RcneWF4fRaGbuxfJ2eyjr5uW1Ke8Lo4xSWulVUdZPb18Pun1XqRv1vzbtWpu/dfO4f29Xv4/P9ef+o32236tCJmu3KqJ2qTs0FxnZoqwqS1blO0md9CTXCbM/O+vE7J+ZFTjJEdZdwrj6LDd1VkyIa8hSvrjiq9UkrLBFWYwKE8SarVrJuBjVqnlxBavVEixtuiw3WXFPYGnOHgmW8uUeHZkZCx2ZqCNvxXbkCMsl3CNYC7EwWbNiYbJisl7A1LlOllFd1nrA2vg/hMlEQTqyYkE6IB1iRiFYi0jHWDsKRdmrQm0GKMsZzn2UHaCM8rMg2VmxINmQbDESBBYkOzudzV2yzRjLzcXSQVbaS3JLJF8siyH/gliV/yTjrAQZF8NKUNLIsRJVQivRzVeslSDln2ElSLvEkDNyj2CdjcUQbeoPK6Go6aJ9CaiglaCGM8dKdFmxVoLHClsJagia3qDXZgBzgU8cFOy4E72w0dsSITDYr6xYsF+wX2LsBFiwX9l5Jtgv2C/JMKv6+T9SjtC13O4HuNtMMQ==";
var events = "eJxtzTELwjAQBeC/8szcIe0g6Ojm4OYmDsFc26OpgcsRCeJ/Ny5SsdvxuO+9y9NE8SRmj8521ra2bWAo011rZE4FPUtS1EQwlBmZE+vGvBr8yd1SHvGoFxwCqwbCSC5z7dDoXVn1nV368yhESDGwRyJNiD22FtOwbn+2DxKnj50JQrf6mb6z1zcvYUkk";
var strData = atob(dataset_collection);
var charData = strData.split('').map(function(x)return x.charCodeAt(0););
var binData = new Uint8Array(charData);
dataset_collection = JSON.parse(pako.inflate(binData, to: 'string' ));
strData = atob(events);
charData = strData.split('').map(function(x)return x.charCodeAt(0););
binData = new Uint8Array(charData);
events = JSON.parse(pako.inflate(binData, to: 'string' ));
const svg = d3
.select("#plotapi-chart-3dbbed15")
.append("svg")
.style("max-width", 740 + 40 + 20)
.attr(
"viewBox",
"0 0 " +
(740 + 40 + 20) +
" " +
(650 + 110 + 40)
)
.attr("class", "plotapi-plot")
.attr("preserveAspectRatio", "xMinYMin meet")
.style("background-color", "white")
.style("border", 2)
.append("g")
.attr("id", "plotapi-chart-3dbbed15_svg")
.attr(
"transform",
"translate(" + 40 + "," + 110 + ")"
);
const axis_group = d3
.select("#plotapi-chart-3dbbed15_svg")
.append("g")
.classed("axis_group", true);
var y_axis_line = axis_group
.append("g")
.attr("class", "axis y_axis")
.attr("transform", `translate(0, 0))`)
var x_axis_line = axis_group
.append("g")
.attr("class", "axis x_axis")
.attr("transform", `translate(0, ` + 650 + `)`)
var x_axis_label = axis_group
.append("text")
.classed("axis_label", true)
.attr("x", 740 / 2)
.attr("y", 650 + (40 / 2))
.style("font-size", 18)
.attr("text-anchor", "middle")
.style("dominant-baseline", "hanging")
.attr("pointer-events", "none")
.text("Weight(kg)");
var y_axis_label = axis_group
.append("text")
.classed("axis_label", true)
.attr("x", -650 / 2)
.attr("y", -(40 / 2))
.style("font-size", 18)
.attr("text-anchor", "middle")
.attr("transform", "rotate(-90)")
.attr("pointer-events", "none")
.text("Reps");
var title =
axis_group
.append("text")
.attr("x", 740 / 2)
.attr("y", -80)
.style("font-size", 20)
.attr("text-anchor", "middle")
.style("text-decoration", "underline")
.text("Bench Press");
var sequence_title =
axis_group
.append("text")
.attr("x", 740 / 2)
.attr("y", -40)
.style("font-size", 30)
.attr("text-anchor", "middle")
.style("text-decoration", "none")
.attr("fill", "#aaabbb")
.text("Loading…");
var event_text =
axis_group
.append("text")
.attr("x", 740 / 2)
.attr("y", -10)
.style("font-size", 20)
.attr("text-anchor", "middle")
.style("text-decoration", "none")
.attr("fill", "#aaabff")
.text("");
const dominated_group = d3
.select("#plotapi-chart-3dbbed15_svg")
.append("g")
.classed("dominated_group", true);
var dominated_label_group = d3
.select("#plotapi-chart-3dbbed15_svg")
.append("g")
.classed("dominated_label_group", true);
dominated_label_group = dominated_group
const pareto_group = d3
.select("#plotapi-chart-3dbbed15_svg")
.append("g")
.classed("pareto_group", true);
const pareto_label_group = d3
.select("#plotapi-chart-3dbbed15_svg")
.append("g")
.classed("pareto_label_group", true);
const particle_group = d3
.select("#plotapi-chart-3dbbed15_svg")
.append("g")
.classed("particle_group", true);
var overlay_group = d3
.select("#plotapi-chart-3dbbed15_svg")
.append("g")
.classed("overlay_group", true);
update_text();
var sequence_title_bbox = sequence_title.node().getBBox()
d3.select("#plotapi-chart-3dbbed15_svg .overlay_group")
.append("svg:a")
.append("image")
.style("cursor", "pointer")
.attr("xlink:href", "https://plotapi.com/gallery/icon/continue.svg")
.attr("width", 30)
.attr("height", 30)
.attr("x", 20 + (740 / 2) + (sequence_title_bbox.width / 2))
.attr("y", -40 – 27)
.attr("opacity", 0.6)
.attr("id", "plotapi-chart-3dbbed15_next");
d3.select("#plotapi-chart-3dbbed15_next").on(
"click",
function (d, i)
d.stopPropagation();
clearTimeout(auto_proceed_timeout);
auto_proceed_interrupt = true;
next_order();
);
d3.select("#plotapi-chart-3dbbed15_next").on(
"mouseover",
function (d, i)
if (sequence_index + 1 < dataset_collection.length)
d3.select("#plotapi-chart-3dbbed15_next").attr("opacity", 1);
);
d3.select("#plotapi-chart-3dbbed15_next").on(
"mouseout",
function (d, i)
if (sequence_index + 1 0)
d3.select(“#plotapi-chart-3dbbed15_prev”).attr(“opacity”, 1);
);
d3.select(“#plotapi-chart-3dbbed15_prev”).on(
“mouseout”,
function (d, i)
if (sequence_index > 0)
d3.select(“#plotapi-chart-3dbbed15_prev”).attr(
“opacity”,
0.6
);
);
function next_order()
if (sequence_index + 1 = 0)
last_sequence_index = sequence_index;
sequence_index–;
if (range_x != pareto_range_x && range_y != pareto_range_y)
if (zoom_timeout == null)
zoomed_user = zoomed;
zoomed = false;
clearTimeout(zoom_timeout)
zoom_timeout = setTimeout(zoomUser, (500 * 4) + 500);
update_data(sequence_index)
update_axis()
update_text()
update_dominated_markers()
update_pareto_markers(false)
function init()
last_sequence_index = sequence_index;
n_final_ranks = Math.max.apply(Math, dataset_collection[dataset_collection.length – 1].map(function (o) return o.rank; )),
update_data(sequence_index)
update_axis()
update_text()
update_dominated_markers()
update_pareto_markers(false)
function update_navigation()
function update_text()
var date_string = sequence[sequence_index].toString();
var dt = new Date(date_string.substring(0, 4), date_string.substring(4, 6) – 1, date_string.substring(6, 8)).toDateString();
title.text(“Bench Press”);
sequence_title.text(dt);
if (sequence_index + 1 0)
d3.select(“#plotapi-chart-3dbbed15_prev”)
.attr(“opacity”, “0.6”);
else
d3.select(“#plotapi-chart-3dbbed15_prev”)
.attr(“opacity”, “0.1”);
var current_event = events.find(item =>
return item.order === sequence[sequence_index]
)
if (current_event == undefined)
event_text.attr(“opacity”, 0.5);
else
event_text
.attr(“opacity”, 1)
.text(current_event.event)
function update_marker_positions(population, population_label)
population.selectAll(‘circle’)
.transition()
.duration(500)
.attr(“cx”, function (d)
return x_scale(d.objv_1);
)
.attr(“cy”, function (d)
return y_scale(d.objv_2);
)
population_label.selectAll(‘text’)
.transition()
.duration(500)
.attr(“x”, function (d)
return x_scale(d.objv_1);
)
.attr(“y”, function (d)
return y_scale(d.objv_2);
)
function update_dominated_markers(next) {
update_marker_positions(dominated_group, dominated_label_group)
for (var index = 0; index < dominated_dataset.length; index++)
solution = dominated_dataset[index];
solution_marker = dominated_group.select(".solution_" + solution.objv_1 + "_" + solution.objv_2)
solution_label = dominated_label_group.select(".solution_label_" + solution.objv_1 + "_" + solution.objv_2)
if (solution_marker.empty())
solution_marker = dominated_group
.append("circle")
.datum(solution)
.attr("cx", function (d)
return x_scale(d.objv_1);
)
.attr("cy", function (d)
return y_scale(d.objv_2);
)
.attr("class", function (d)
return "solution_" + d.objv_1 + "_" + d.objv_2;
)
.attr("fill", function (d)
return color(d.rank);
)
.attr("stroke", function (d)
return darkenColor(color(d.rank), 0.5);
)
.attr("stroke-width", function (d)
return 2;
)
.attr("opacity", 0)
.on("mouseover", mouseoverNode())
.on("mouseout", mouseoutNode())
if (solution_label.empty())
solution_label = dominated_label_group
.append('text')
.datum(solution)
.attr("x", function (d)
return x_scale(d.objv_1);
)
.attr("y", function (d)
return y_scale(d.objv_2);
)
.attr("text-anchor", "middle")
.style("dominant-baseline", "middle")
.attr("class", function (d)
return "solution_label_" + d.objv_1 + "_" + d.objv_2;
)
.attr("opacity", 0)
.attr("font-size", 20 + "px")
.attr("fill", "#ffffff")
.attr("stroke", "#333333")
.attr("stroke-width", 3 + "px")
.attr("paint-order", "stroke")
.attr("stroke-linecap", "butt")
.attr("stroke-linejoin", "miter")
.text(solution.count)
.attr("pointer-events", "none");
if (solution_marker.datum()['current_sequence_index'] != sequence_index)
solution_marker.datum(solution)
solution_label.datum(solution)
solution_marker.datum()['current_sequence_index'] = sequence_index;
solution_label.datum()['current_sequence_index'] = sequence_index;
solution_marker
.transition()
.duration(500)
.attr("cx", function (d)
return x_scale(d.objv_1);
)
.attr("cy", function (d)
return y_scale(d.objv_2);
)
.attr("r", 20)
.style("fill", function (d)
return color(d.rank)
)
.attr("stroke", function (d)
return darkenColor(color(d.rank), 0.5);
);
solution_marker
.transition()
.delay(500)
.duration(500)
.attr("opacity", 1)
solution_label
.text(solution.count)
.on("mouseover", mouseoverNode())
.on("mouseout", mouseoutNode())
if (solution_label.datum()['last_count'] && solution_label.datum()['last_count'] != solution.count)
solution_label
.transition()
.duration(500)
.attr("font-size", (20 * 2) + "px")
.attr("x", function (d)
return x_scale(d.objv_1);
)
.attr("y", function (d)
return y_scale(d.objv_2);
)
else
solution_label
.transition()
.duration(500)
.attr("x", function (d)
return x_scale(d.objv_1);
)
.attr("y", function (d)
return y_scale(d.objv_2);
)
solution_label
.transition()
.delay(500)
.duration(500)
.attr("opacity", 1)
.attr("font-size", 20 + "px")
solution_label.datum()['last_count'] = solution.count;
dominated_group.selectAll('circle')
.filter(function (d) return d.current_sequence_index != sequence_index; )
.transition()
.delay(500 * 2)
.duration(500)
.attr("opacity", 0)
.on("end", function (d)
d.current_sequence_index = -1;
this.remove()
)
dominated_label_group.selectAll('text')
.filter(function (d) return d.current_sequence_index != sequence_index; )
.transition()
.delay(500 * 2)
.duration(500)
.attr("opacity", 0)
.on("end", function (d)
d.current_sequence_index = -1;
this.remove()
)
}
function firework(x, y)
for (var trail_index = 0; trail_index < 6; trail_index++)
for (var index = 0; index < 25; index++)
particle_group
.append("circle")
.style("fill", function (d)
return 'red'
)
.style('opacity', 1 – (trail_index * 0.15))
.attr('transform', 'translate(' + x + ',' + y + ')rotate(' + (360 / 25) * index + ')')
.attr("r", 5)
.transition()
.delay(trail_index * 20)
.ease(d3.easeCubicOut)
.duration(2500)
.attr("cy", 200 – (trail_index * 10))
.style("fill", function (d)
return 'transparent'
)
.on("end", function (d)
this.remove()
)
function update_pareto_markers(next)
update_marker_positions(pareto_group, pareto_label_group)
for (var index = 0; index
next_order()
, (500 * 2) + 500 + 2500);
}
function update_axis()
if (“min” == “max”)
limit_x_axis = [Math.max(…limit_x_axis), Math.min(…limit_x_axis)];
else
limit_x_axis = [Math.min(…limit_x_axis), Math.max(…limit_x_axis)];
if (“min” == “max”)
limit_y_axis = [Math.min(…limit_y_axis), Math.max(…limit_y_axis)];
else
limit_y_axis = [Math.max(…limit_y_axis), Math.min(…limit_y_axis)];
x_scale = d3
.scaleLinear()
.domain(limit_x_axis)
.range([0, 740]);
x_axis = d3
.axisBottom()
.scale(x_scale)
.ticks(650 / 100, undefined)
.tickSize(-650)
.tickFormat((d) => d3.format(“,”)(d));
x_axis_line
.transition()
.duration(500)
.call(x_axis);
y_scale = d3
.scaleLinear()
.domain(limit_y_axis)
.range([0, 650]);
y_axis = d3
.axisLeft()
.scale(y_scale)
.ticks(740 / 100, undefined)
.tickSize(-740)
y_axis.tickFormat(function (d)
return Number.isInteger(d) ? d : “”
)
y_axis_line
.transition()
.duration(500)
.call(y_axis);
function update_data(sequence_index)
dataset = dataset_collection[sequence_index]
dataset = dataset.filter(function (solution)
return solution.rank < 10;
);
dominated_dataset = dataset.filter(function (solution)
return solution.rank 0;
);
pareto_dataset = dataset.filter(function (solution)
return solution.rank == 0;
);
n_ranks = Math.max.apply(Math, dataset.map(function (o) return o.rank; )),
range_x = [Math.min.apply(Math, dataset.map(function (o) return o.objv_1; )), Math.max.apply(Math, dataset.map(function (o) return o.objv_1; ))]
range_y = [Math.min.apply(Math, dataset.map(function (o) return o.objv_2; )), Math.max.apply(Math, dataset.map(function (o) return o.objv_2; ))]
if(range_x[0] == range_x[1])
padding_x = range_x[0] / 10;
else
padding_x = (range_x[1] – range_x[0]) / 10;
if(range_y[0] == range_y[1])
padding_y = range_y[0] / 10;
else
padding_y = (range_y[1] – range_y[0]) / 10;
range_x[1] = range_x[1] + padding_x
range_x[0] = range_x[0] – padding_x
range_y[1] = range_y[1] + padding_y
range_y[0] = range_y[0] – padding_y
pareto_range_x = [Math.min.apply(Math, pareto_dataset.map(function (o) return o.objv_1; )), Math.max.apply(Math, pareto_dataset.map(function (o) return o.objv_1; ))]
pareto_range_y = [Math.min.apply(Math, pareto_dataset.map(function (o) return o.objv_2; )), Math.max.apply(Math, pareto_dataset.map(function (o) return o.objv_2; ))]
if(pareto_range_x[0] == pareto_range_x[1])
pareto_padding_x = pareto_range_x[0] / 10;
else
pareto_padding_x = (pareto_range_x[1] – pareto_range_x[0]) / 10;
if(pareto_range_y[0] == pareto_range_y[1])
pareto_padding_y = pareto_range_y[0] / 10;
else
pareto_padding_y = (pareto_range_y[1] – pareto_range_y[0]) / 10;
pareto_range_x[1] = pareto_range_x[1] + pareto_padding_x
pareto_range_x[0] = pareto_range_x[0] – pareto_padding_x
pareto_range_y[1] = pareto_range_y[1] + pareto_padding_y
pareto_range_y[0] = pareto_range_y[0] – pareto_padding_y
if (zoomed)
limit_y_axis = pareto_range_y;
limit_x_axis = pareto_range_x;
else
limit_y_axis = range_y;
limit_x_axis = range_x;
function mouseoverNode()
return function (d, i)
let size;
let population;
if (i.rank == 0)
population = pareto_group.selectAll(‘circle’);
size = 25;
else
population = dominated_group.selectAll(‘circle’);
size = 20;
population
.attr(“r”, function (d)
if (d.rank == i.rank)
return size * 1.25;
return size;
)
.attr(“stroke”, function (d)
if (d.rank == i.rank)
return ‘lightgreen’;
else if (d.rank == 0)
return darkenColor(color(d.rank), 0.5);
else
return darkenColor(color(d.rank), 0.5);
)
.attr(“stroke-width”, function (d)
if (d.rank == 0)
return 5;
else if (d.rank == i.rank)
return 5;
else
return 2;
)
d3.select(d.srcElement).attr(“r”, size * 1.25)
tippy_content = i.objv_1 + “” + ” kg” + “, ” + i.objv_2 + “” + ” reps” + “
Rank: ” + i.rank + “
Sets:” + i.count;
if (this._tippy == null)
tippy(this,
touch: ‘hold’,
allowHTML: true,
content: tippy_content,
arrow: true,
maxWidth: 300,
theme: ‘translucent’,
);
else
this._tippy.setContent(tippy_content);
function mouseoutNode()
return function (d, i)
let population;
let size;
if (i.rank == 0)
population = pareto_group.selectAll(‘circle’);
size = 25;
else
population = dominated_group.selectAll(‘circle’);
size = 20;
population
.attr(“r”, function (d)
if (d.rank == i.rank)
return size;
return size;
)
.attr(“stroke”, function (d)
return darkenColor(color(d.rank), 0.5);
if (d.rank == 0)
return ‘red’;
else
return ‘gray’; color(d.rank);
)
.attr(“stroke-width”, function (d)
if (d.rank == 0)
return 5;
else
return 2;
)
function zoom()
if (zoomed)
zoomed = false;
limit_x_axis = range_x;
limit_y_axis = range_y;
else
zoomed = true;
limit_x_axis = pareto_range_x;
limit_y_axis = pareto_range_y;
update_axis()
update_text()
update_marker_positions(dominated_group, dominated_label_group)
update_marker_positions(pareto_group, pareto_label_group)
function zoomOut()
zoomed = false;
limit_x_axis = range_x;
limit_y_axis = range_y;
update_axis()
update_text()
update_marker_positions(dominated_group, dominated_label_group)
update_marker_positions(pareto_group, pareto_label_group)
function zoomIn()
zoomed = true;
limit_x_axis = pareto_range_x;
limit_y_axis = pareto_range_y;
update_axis()
update_text()
update_marker_positions(dominated_group, dominated_label_group)
update_marker_positions(pareto_group, pareto_label_group)
function zoomUser()
zoom_timeout = null;
if (zoomed != zoomed_user)
zoomed = zoomed_user;
if (zoomed)
limit_x_axis = pareto_range_x;
limit_y_axis = pareto_range_y;
else
limit_x_axis = range_x;
limit_y_axis = range_y;
update_axis()
update_text()
update_marker_positions(dominated_group, dominated_label_group)
update_marker_positions(pareto_group, pareto_label_group)
d3.select(“#plotapi-chart-3dbbed15”).on(“click”, zoom)
init();
}
}());
More Stories
How to Find Your Windows PC’s Serial Number
Apple Explains How It’s Killing Passwords With Passkeys On iOS 16 And macOS Ventura
Half of Australians will experience technology-facilitated abuse in their lifetimes