UNPKG

bands-visualiser

Version:

A plotly.js renderer for Bands, DOS, combined Bands/Dos and fatBands.

138 lines (113 loc) 3.24 kB
export function transpose(matrix) { const rows = matrix.length; const cols = matrix[0].length; const result = new Array(cols); for (let i = 0; i < cols; i++) { result[i] = new Array(rows); for (let j = 0; j < rows; j++) { result[i][j] = matrix[j][i]; } } return result; } export function splitBandsData(bandsData, nParts) { const { path, label, paths } = bandsData; // Determine number of bands (from first path) const totalBands = paths[0]?.values.length || 0; const perChunk = Math.floor(totalBands / nParts); const result = []; for (let i = 0; i < nParts; i++) { const start = i * perChunk; const end = i === nParts - 1 ? totalBands : (i + 1) * perChunk; const newPaths = paths.map((pathObj) => { const { values, ...rest } = pathObj; return { ...rest, values: values.slice(start, end), }; }); result.push({ path, label, paths: newPaths, }); } return result; } export function getBandByIndex(bandsData, index) { const { path, label, paths } = bandsData; const newPaths = paths.map((pathObj) => { const { values, ...rest } = pathObj; return { ...rest, values: [values[index]], // extract a single band }; }); return { path, label, paths: newPaths, }; } // method to downsample a ProjectionData array. // downsampling operates over the x-axis data set // Needs some testing to measure break-points in performance // and whether any clarity is lost. export function downsampleProjections(projections, step) { const { x, ys, weights } = projections; const len = x.length; const nRows = ys.length; // Pre-allocate output arrays const downsampledX = new Float32Array(Math.ceil(len / step)); const downsampledYs = Array.from( { length: nRows }, () => new Float32Array(Math.ceil(len / step)) ); const downsampledWeights = Array.from( { length: nRows }, () => new Float32Array(Math.ceil(len / step)) ); let outIdx = 0; for (let i = 0; i < len; i += step, outIdx++) { downsampledX[outIdx] = x[i]; for (let j = 0; j < nRows; j++) { downsampledYs[j][outIdx] = ys[j][i]; downsampledWeights[j][outIdx] = weights[j][i]; } } return { x: downsampledX, ys: downsampledYs, weights: downsampledWeights, }; } // sanitisation / autopacking utils export function ensureArray(value) { if (value == null) return []; return Array.isArray(value) ? value : [value]; } export function sanitizeBandsInput(input) { if (input == null) return []; const bands = (Array.isArray(input) ? input.flat() : [input]).filter(Boolean); return bands.map((band) => { // Already in expected internal shape if (band.bandsData) { return { projections: [], ...band, }; } // Flat band object → wrap it if (band.path || band.paths) { const { traceFormat, projections, ...bandsData } = band; return { bandsData, traceFormat, projections: projections ?? [], // ✅ critical fix }; } throw new Error( "BandsVisualiser: invalid band object shape. Expected bandsData or band-like object." ); }); }