heatmaps: part 14

This commit is contained in:
nym21
2026-06-01 12:01:24 +02:00
parent 102933b406
commit cb9f277d49
7 changed files with 92 additions and 110 deletions
+16 -15
View File
@@ -37,8 +37,7 @@ export function createAverageGrid({
const sums = new Float64Array(cols * rows);
const counts = new Uint32Array(cols * rows);
const maxByCol = new Float64Array(cols);
const cumulativeMaxByCol = new Float64Array(cols);
let cumulativeMaxDirty = true;
let maxValue = 0;
const ySpan = yMax - yMin;
/** @param {number} dateIndex */
@@ -85,7 +84,10 @@ export function createAverageGrid({
if (counts[index]) max = Math.max(max, sums[index] / counts[index]);
}
maxByCol[col] = max;
cumulativeMaxDirty = true;
maxValue = 0;
for (let c = 0; c < cols; c++) {
maxValue = Math.max(maxValue, maxByCol[c]);
}
}
/** @type {HeatmapGrid} */
@@ -99,7 +101,13 @@ export function createAverageGrid({
let dirty = false;
if (points.kind === "implicit") {
for (let i = 0; i < points.values.length; i++) {
if (addValue(col, points.yStart + i * points.yStep, points.values[i])) {
if (
addValue(
col,
points.yStart + i * points.yStep,
points.values[i],
)
) {
dirty = true;
}
}
@@ -110,8 +118,9 @@ export function createAverageGrid({
}
}
if (!dirty) return undefined;
const previousMax = maxValue;
updateColumnMax(col);
return col;
return { col, maxChanged: maxValue !== previousMax };
},
getValue(col, row) {
if (col < 0 || col >= cols || row < 0 || row >= rows) {
@@ -120,16 +129,8 @@ export function createAverageGrid({
const index = row * cols + col;
return counts[index] ? sums[index] / counts[index] : Number.NaN;
},
getMaxValue(col = cols - 1) {
if (cumulativeMaxDirty) {
let max = 0;
for (let c = 0; c < cols; c++) {
max = Math.max(max, maxByCol[c]);
cumulativeMaxByCol[c] = max;
}
cumulativeMaxDirty = false;
}
return cumulativeMaxByCol[clamp(col, 0, cols - 1)] ?? 0;
getMaxValue() {
return maxValue;
},
getDateIndexRange(col) {
if (col < 0 || col >= cols || dates.length === 0) {
+7 -2
View File
@@ -248,8 +248,13 @@ function rebuildGrid() {
*/
function addDateToGrid(dateIndex, points) {
if (!currentGrid) return;
const dirtyCol = currentGrid.add(dateIndex, points);
if (dirtyCol !== undefined) schedulePaint(dirtyCol);
const result = currentGrid.add(dateIndex, points);
if (!result) return;
if (result.maxChanged) {
paint();
} else {
schedulePaint(result.col);
}
}
/**
+1 -1
View File
@@ -38,7 +38,7 @@ export function intensityColor({ light, dark }) {
export function logIntensityColor({ light, dark }) {
return (value, context) => {
if (!Number.isFinite(value) || value <= 0) return 0x00000000;
const max = context.grid.getMaxValue(context.col);
const max = context.grid.getMaxValue();
if (max <= 0) return 0x00000000;
const lut = context.dark ? dark : light;
const t = Math.log2(value + 1) / Math.log2(max + 1);
+1 -1
View File
@@ -44,7 +44,7 @@ function createOracleHeatmapOption(mode, name) {
kind: "heatmap",
name,
title:
mode === "outputs" ? "Output Value Histogram" : "Payment Output Histogram",
mode === "outputs" ? "Output Value Histogram" : "Payment Value Histogram",
points: {
fetch: (date, signal, onPoints) =>
fetchOraclePoints(mode, date, signal, onPoints),
+6 -2
View File
@@ -19,13 +19,17 @@
* @property {number} start
* @property {number} end
*
* @typedef {Object} HeatmapGridAddResult
* @property {number} col
* @property {boolean} maxChanged
*
* @typedef {Object} HeatmapGrid
* @property {readonly string[]} dates
* @property {number} cols
* @property {number} rows
* @property {(dateIndex: number, points: HeatmapPoints) => number | undefined} add
* @property {(dateIndex: number, points: HeatmapPoints) => HeatmapGridAddResult | undefined} add
* @property {(col: number, row: number) => number} getValue
* @property {(col?: number) => number} getMaxValue
* @property {() => number} getMaxValue
* @property {(col: number) => HeatmapRange} getDateIndexRange
* @property {(row: number) => HeatmapRange} getYRange
*