in modules/mlvis-common/src/utils/computation.js [291:335]
export function computeHistogram(data, bins) {
return tf.tidy(() => {
const dt = tf.tensor(data);
if (dt.dtype === 'string') {
return computeHistogramCat(data, bins);
}
const minVal = tf.min(dt).dataSync()[0];
const maxVal = tf.max(dt).dataSync()[0];
// parse the overloaded bins argument
let nBins, binEdges, firstEdge, lastEdge;
if (Number.isInteger(bins)) {
nBins = bins;
binEdges = tf.linspace(minVal, maxVal, nBins + 1);
firstEdge = minVal;
lastEdge = maxVal;
} else if (bins.length) {
nBins = bins.length - 1;
binEdges = tf.tensor1d(bins);
firstEdge = bins[0];
lastEdge = bins[bins.length - 1];
} else {
throw '`bins` must be a number or an array';
}
// histogram scaling factor
const norm = nBins / (lastEdge - firstEdge);
const indicesRaw = tf
.mul(tf.sub(dt, tf.scalar(firstEdge)), tf.scalar(norm))
.toInt();
// for values that lie exactly on lastEdge we need to subtract one
const indices = tf.sub(
indicesRaw,
tf.equal(indicesRaw, tf.scalar(nBins).toInt()).toInt()
);
const binIds = tf.linspace(0, nBins - 1, nBins).toInt();
const hist = binCount(indices, binIds);
return [Array.from(hist.dataSync()), Array.from(binEdges.dataSync())];
});
}