cleanup bubbleRoofline code, comment optional code parts

This commit is contained in:
Christoph Kluge
2025-07-15 16:00:55 +02:00
parent ed5290be86
commit 096217eea6

View File

@@ -37,8 +37,6 @@
height = 380, height = 380,
} = $props(); } = $props();
$inspect(jobsData)
/* Const Init */ /* Const Init */
const lineWidth = clusterCockpitConfig?.plot_general_lineWidth || 2; const lineWidth = clusterCockpitConfig?.plot_general_lineWidth || 2;
const cbmode = clusterCockpitConfig?.plot_general_colorblindMode || false; const cbmode = clusterCockpitConfig?.plot_general_colorblindMode || false;
@@ -58,6 +56,7 @@
// Copied Example Vars for Uplot Bubble // Copied Example Vars for Uplot Bubble
// https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/isPointInPath // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/isPointInPath
let qt; let qt;
let hRect;
let pxRatio; let pxRatio;
function setPxRatio() { function setPxRatio() {
pxRatio = uPlot.pxRatio; pxRatio = uPlot.pxRatio;
@@ -66,7 +65,7 @@
window.addEventListener('dppxchange', setPxRatio); window.addEventListener('dppxchange', setPxRatio);
// let minSize = 6; // let minSize = 6;
let maxSize = 60; let maxSize = 60;
let maxArea = Math.PI * (maxSize / 2) ** 2; // let maxArea = Math.PI * (maxSize / 2) ** 2;
// let minArea = Math.PI * (minSize / 2) ** 2; // let minArea = Math.PI * (minSize / 2) ** 2;
/* Functions */ /* Functions */
@@ -94,7 +93,7 @@
return Math.floor(x * 255.0); return Math.floor(x * 255.0);
} }
function getRGB(c, makeTransparent = false) { function getRGB(c, makeTransparent = false) {
if (makeTransparent) return `rgb(${cbmode ? '0' : getGradientR(c)}, ${getGradientG(c)}, ${getGradientB(c)}, 0.33)`; if (makeTransparent) return `rgba(${cbmode ? '0' : getGradientR(c)}, ${getGradientG(c)}, ${getGradientB(c)}, 0.33)`;
else return `rgb(${cbmode ? '0' : getGradientR(c)}, ${getGradientG(c)}, ${getGradientB(c)})`; else return `rgb(${cbmode ? '0' : getGradientR(c)}, ${getGradientG(c)}, ${getGradientB(c)})`;
} }
function nearestThousand(num) { function nearestThousand(num) {
@@ -110,28 +109,28 @@
} }
// quadratic scaling (px area) // quadratic scaling (px area)
function getSize(value, minValue, maxValue) { // function getSize(value, minValue, maxValue) {
let pct = value / maxValue; // let pct = value / maxValue;
// clamp to min area // // clamp to min area
//let area = Math.max(maxArea * pct, minArea); // //let area = Math.max(maxArea * pct, minArea);
let area = maxArea * pct; // let area = maxArea * pct;
return Math.sqrt(area / Math.PI) * 2; // return Math.sqrt(area / Math.PI) * 2;
} // }
function getSizeMinMax(u) { // function getSizeMinMax(u) {
let minValue = Infinity; // let minValue = Infinity;
let maxValue = -Infinity; // let maxValue = -Infinity;
for (let i = 1; i < u.series.length; i++) { // for (let i = 1; i < u.series.length; i++) {
let sizeData = u.data[i][2]; // let sizeData = u.data[i][2];
for (let j = 0; j < sizeData.length; j++) { // for (let j = 0; j < sizeData.length; j++) {
minValue = Math.min(minValue, sizeData[j]); // minValue = Math.min(minValue, sizeData[j]);
maxValue = Math.max(maxValue, sizeData[j]); // maxValue = Math.max(maxValue, sizeData[j]);
} // }
} // }
return [minValue, maxValue]; // return [minValue, maxValue];
} // }
// Quadtree Object (How to import?) // Quadtree Object (TODO: Split and Import)
class Quadtree { class Quadtree {
constructor (x, y, w, h, l) { constructor (x, y, w, h, l) {
let t = this; let t = this;
@@ -239,43 +238,24 @@
} }
} }
// Dot Renderers // Dot Renderer
const makeDrawPoints = (opts) => { const makeDrawPoints = (opts) => {
let {/*size,*/ disp, each = () => {}} = opts; let {/*size, disp,*/ each = () => {}} = opts;
const sizeBase = 5 * pxRatio; const sizeBase = 5 * pxRatio;
return (u, seriesIdx, idx0, idx1) => { return (u, seriesIdx, idx0, idx1) => {
uPlot.orient(u, seriesIdx, (series, dataX, dataY, scaleX, scaleY, valToPosX, valToPosY, xOff, yOff, xDim, yDim, moveTo, lineTo, rect, arc) => { uPlot.orient(u, seriesIdx, (series, dataX, dataY, scaleX, scaleY, valToPosX, valToPosY, xOff, yOff, xDim, yDim, moveTo, lineTo, rect, arc) => {
let d = u.data[seriesIdx]; let d = u.data[seriesIdx];
let strokeWidth = 2; let strokeWidth = 2;
u.ctx.save();
u.ctx.rect(u.bbox.left, u.bbox.top, u.bbox.width, u.bbox.height);
u.ctx.clip();
// u.ctx.fillStyle = series.fill();
// u.ctx.strokeStyle = series.stroke();
u.ctx.lineWidth = strokeWidth;
let deg360 = 2 * Math.PI; let deg360 = 2 * Math.PI;
/* Alt.: Sizes based on other Data Rows */
// console.time("points");
// let cir = new Path2D();
// cir.moveTo(0, 0);
// arc(cir, 0, 0, 3, 0, deg360);
// Create transformation matrix that moves 200 points to the right
// let m = document.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGMatrix();
// m.a = 1; m.b = 0;
// m.c = 0; m.d = 1;
// m.e = 200; m.f = 0;
// compute bubble dims
// let sizes = disp.size.values(u, seriesIdx, idx0, idx1); // let sizes = disp.size.values(u, seriesIdx, idx0, idx1);
u.ctx.save();
u.ctx.rect(u.bbox.left, u.bbox.top, u.bbox.width, u.bbox.height);
u.ctx.clip();
u.ctx.lineWidth = strokeWidth;
// todo: this depends on direction & orientation // todo: this depends on direction & orientation
// todo: calc once per redraw, not per path // todo: calc once per redraw, not per path
let filtLft = u.posToVal(-maxSize / 2, scaleX.key); let filtLft = u.posToVal(-maxSize / 2, scaleX.key);
@@ -284,15 +264,14 @@
let filtTop = u.posToVal(-maxSize / 2, scaleY.key); let filtTop = u.posToVal(-maxSize / 2, scaleY.key);
for (let i = 0; i < d[0].length; i++) { for (let i = 0; i < d[0].length; i++) {
// Import from Roofline // Color based on Duration
u.ctx.strokeStyle = getRGB(u.data[2][i]); u.ctx.strokeStyle = getRGB(u.data[2][i]);
u.ctx.fillStyle = getRGB(u.data[2][i], true); u.ctx.fillStyle = getRGB(u.data[2][i], true);
// End // Get Values
let xVal = d[0][i]; let xVal = d[0][i];
let yVal = d[1][i]; let yVal = d[1][i];
const size = sizeBase + (jobsData[i]?.numAcc ? jobsData[i].numAcc / 2 : jobsData[i].numNodes); // Calc Size; Alt.: size = sizes[i] * pxRatio
// let size = sizes[i] * pxRatio; const size = sizeBase + (jobsData[i]?.numAcc ? jobsData[i].numAcc / 2 : jobsData[i].numNodes); // In NodeMode: Scale with Number of Jobs?
if (xVal >= filtLft && xVal <= filtRgt && yVal >= filtBtm && yVal <= filtTop) { if (xVal >= filtLft && xVal <= filtRgt && yVal >= filtBtm && yVal <= filtTop) {
let cx = valToPosX(xVal, scaleX, xDim, xOff); let cx = valToPosX(xVal, scaleX, xDim, xOff);
@@ -312,28 +291,25 @@
); );
} }
} }
// console.timeEnd("points");
u.ctx.restore(); u.ctx.restore();
}); });
return null; return null;
}; };
}; };
let drawPoints = makeDrawPoints({ let drawPoints = makeDrawPoints({
disp: { // disp: {
size: { // size: {
unit: 3, // raw CSS pixels // // unit: 3, // raw CSS pixels
// discr: true, // // discr: true,
values: (u, seriesIdx, idx0, idx1) => { // values: (u, seriesIdx, idx0, idx1) => {
// TODO: only run once per setData() call // /* Func to get sizes from additional subSeries [series][2...x] ([0,1] is [x,y]) */
let [minValue, maxValue] = getSizeMinMax(u); // // TODO: only run once per setData() call
return u.data[seriesIdx][2].map(v => getSize(v, minValue, maxValue)); // let [minValue, maxValue] = getSizeMinMax(u);
}, // return u.data[seriesIdx][2].map(v => getSize(v, minValue, maxValue));
}, // },
}, // },
// },
each: (u, seriesIdx, dataIdx, lft, top, wid, hgt) => { each: (u, seriesIdx, dataIdx, lft, top, wid, hgt) => {
// we get back raw canvas coords (included axes & padding). translate to the plotting area origin // we get back raw canvas coords (included axes & padding). translate to the plotting area origin
lft -= u.bbox.left; lft -= u.bbox.left;
@@ -470,19 +446,17 @@
}, 200); }, 200);
} }
let hRect;
function render(roofdata, jobsData) { function render(roofdata, jobsData) {
if (roofdata) { if (roofdata) {
const opts = { const opts = {
title: "Job Average Roofline Diagram (Bubble)", title: "Job Average Roofline Diagram",
mode: 2, mode: 2,
width: width, width: width,
height: height, height: height,
legend: { legend: {
// show: true, show: true,
}, },
cursor: { cursor: {
drag: { x: true, y: false }, // Activate zoom
dataIdx: (u, seriesIdx) => { dataIdx: (u, seriesIdx) => {
if (seriesIdx == 1) { if (seriesIdx == 1) {
hRect = null; hRect = null;
@@ -521,22 +495,27 @@
} }
}); });
} }
return hRect && seriesIdx == hRect.sidx ? hRect.didx : null; return hRect && seriesIdx == hRect.sidx ? hRect.didx : null;
}, },
points: { // /* Render "Fill" on Data Point Hover: Works in Example Bubble, does not work here? */
size: (u, seriesIdx) => { // points: {
return hRect && seriesIdx == hRect.sidx ? hRect.w / pxRatio : 0; // size: (u, seriesIdx) => {
} // return hRect && seriesIdx == hRect.sidx ? hRect.w / pxRatio : 0;
}, // }
focus: { // },
prox: 1e3, /* Make all non-focused series semi-transparent: Useless unless more than one series rendered */
alpha: 0.3, // focus: {
dist: (u, seriesIdx) => { // prox: 1e3,
let prox = (hRect?.sidx === seriesIdx ? 0 : Infinity); // alpha: 0.3,
return prox; // dist: (u, seriesIdx) => {
}, // let prox = (hRect?.sidx === seriesIdx ? 0 : Infinity);
} // return prox;
// },
// },
drag: { // Activates Zoom
x: true,
y: false
},
}, },
axes: [ axes: [
{ {
@@ -569,16 +548,17 @@
series: [ series: [
null, null,
{ {
facets: [ /* Facets: Define Purpose of Sub-Arrays in Series-Array, e.g. x, y, size, label, color, ... */
{ // facets: [
scale: 'x', // {
auto: true, // scale: 'x',
}, // auto: true,
{ // },
scale: 'y', // {
auto: true, // scale: 'y',
} // auto: true,
], // }
// ],
paths: drawPoints, paths: drawPoints,
values: legendValues values: legendValues
} }
@@ -591,8 +571,10 @@
qt = qt || new Quadtree(0, 0, u.bbox.width, u.bbox.height); qt = qt || new Quadtree(0, 0, u.bbox.width, u.bbox.height);
qt.clear(); qt.clear();
// force-clear the path cache to cause drawBars() to rebuild new quadtree
u.series.forEach((s, i) => { u.series.forEach((s, i) => {
if (i > 0) s._paths = null; if (i > 0)
s._paths = null;
}); });
}, },
], ],