/** * Column-major 2-D fields matching numbl's layout: rows index y, columns index x, * element (i, j) at data[i + j*ny]. */ export interface Field2D { nx: number; ny: number; data: Float64Array; } /** A stack of frames: element (i, j, k) at data[i + j*ny + k*ny*nx]. */ export interface FieldFrames { nx: number; ny: number; nf: number; data: Float64Array; } export function frameOf(frames: FieldFrames, k: number): Field2D { const n = frames.nx * frames.ny; return { nx: frames.nx, ny: frames.ny, data: frames.data.subarray(k * n, (k + 1) * n) }; } export function fieldAt(f: Field2D, i: number, j: number): number { return f.data[i + j * f.ny]; } export interface Range { min: number; max: number; } export function rangeOf(data: ArrayLike): Range { let min = Infinity; let max = -Infinity; for (let k = 0; k < data.length; k++) { const v = data[k]; if (v < min) min = v; if (v > max) max = v; } if (!Number.isFinite(min)) return { min: 0, max: 0 }; return { min, max }; } /** Symmetric range about zero, for signed fields drawn with a diverging colormap. */ export function symmetricRange(r: Range): Range { const a = Math.max(Math.abs(r.min), Math.abs(r.max)); return { min: -a, max: a }; }