mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-10-02 04:08:12 +08:00
* Added TS. Updated build and linting config. Added types. * [ts-migrate][.] Rename files from JS/JSX to TS/TSX Co-authored-by: ts-migrate <> * [ts-migrate][.] Run TS Migrate Co-authored-by: ts-migrate <> * Corrected files mangled by ts-migrate. * Updated lint config, minor linting. * Re-enabled Husky. * Updated tests and config. * Reverted webpack devtool config. * Removed obsolete snapshots. * Added annotations snap. * Updated tsconfig includes wrt linting. * Removed ts-migrate. Co-authored-by: Timmy Huang <tihuan@users.noreply.github.com>
This commit is contained in:
co-authored by
ts-migrate
Timmy Huang
parent
7328cbdbd5
commit
934cc5c69b
@@ -6,8 +6,8 @@ import { postNetworkErrorToast } from "../components/framework/toasters";
|
||||
dispatch an action error to the user. Currently we use
|
||||
async toasts.
|
||||
*/
|
||||
let networkErrorToastKey = null;
|
||||
export const dispatchNetworkErrorMessageToUser = (message) => {
|
||||
let networkErrorToastKey: any = null;
|
||||
export const dispatchNetworkErrorMessageToUser = (message: any) => {
|
||||
if (!networkErrorToastKey) {
|
||||
networkErrorToastKey = postNetworkErrorToast(message);
|
||||
} else {
|
||||
@@ -18,9 +18,9 @@ export const dispatchNetworkErrorMessageToUser = (message) => {
|
||||
/*
|
||||
Catch unexpected errors and make sure we don't lose them!
|
||||
*/
|
||||
export function catchErrorsWrap(fn, dispatchToUser = false) {
|
||||
return (dispatch, getState) => {
|
||||
fn(dispatch, getState).catch((error) => {
|
||||
export function catchErrorsWrap(fn: any, dispatchToUser = false) {
|
||||
return (dispatch: any, getState: any) => {
|
||||
fn(dispatch, getState).catch((error: any) => {
|
||||
console.error(error);
|
||||
if (dispatchToUser) {
|
||||
dispatchNetworkErrorMessageToUser(error.message);
|
||||
@@ -34,7 +34,7 @@ export function catchErrorsWrap(fn, dispatchToUser = false) {
|
||||
* Wrapper to perform async fetch with some modest error handling
|
||||
* and decoding. Arguments are identical to standard fetch.
|
||||
*/
|
||||
export const doFetch = async (url, init = {}) => {
|
||||
export const doFetch = async (url: any, init = {}) => {
|
||||
try {
|
||||
// add defaults to the fetch init param.
|
||||
init = {
|
||||
@@ -42,10 +42,11 @@ export const doFetch = async (url, init = {}) => {
|
||||
credentials: "include",
|
||||
...init,
|
||||
};
|
||||
const acceptType = init.headers?.get("Accept");
|
||||
const acceptType = (init as any).headers?.get("Accept");
|
||||
const res = await fetch(url, init);
|
||||
if (
|
||||
res.ok &&
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
(!acceptType || res.headers.get("Content-Type").includes(acceptType))
|
||||
) {
|
||||
return res;
|
||||
@@ -66,7 +67,7 @@ export const doFetch = async (url, init = {}) => {
|
||||
/*
|
||||
Wrapper to perform an async fetch and JSON decode response.
|
||||
*/
|
||||
export const doJsonRequest = async (url, init = {}) => {
|
||||
export const doJsonRequest = async (url: any, init = {}) => {
|
||||
const res = await doFetch(url, {
|
||||
...init,
|
||||
headers: new Headers({ Accept: "application/json" }),
|
||||
@@ -77,7 +78,7 @@ export const doJsonRequest = async (url, init = {}) => {
|
||||
/*
|
||||
Wrapper to perform an async fetch for binary data.
|
||||
*/
|
||||
export const doBinaryRequest = async (url, init = {}) => {
|
||||
export const doBinaryRequest = async (url: any, init = {}) => {
|
||||
const res = await doFetch(url, {
|
||||
...init,
|
||||
headers: new Headers({ Accept: "application/octet-stream" }),
|
||||
@@ -101,7 +102,7 @@ Parameters:
|
||||
So [1, 2, 3, 4, 10, 11, 14] -> [ [1, 4], [10, 11], 14]
|
||||
*/
|
||||
export const rangeEncodeIndices = (
|
||||
indices,
|
||||
indices: any,
|
||||
minRangeLength = 3,
|
||||
sorted = false
|
||||
) => {
|
||||
@@ -11,12 +11,20 @@ const panBound = 0.8;
|
||||
const scratch0 = new Float32Array(16);
|
||||
const scratch1 = new Float32Array(16);
|
||||
|
||||
function clamp(val, rng) {
|
||||
function clamp(val: any, rng: any) {
|
||||
return Math.max(Math.min(val, rng[1]), rng[0]);
|
||||
}
|
||||
|
||||
class Camera {
|
||||
constructor(canvas) {
|
||||
canvas: any;
|
||||
|
||||
prevEvent: any;
|
||||
|
||||
viewMatrix: any;
|
||||
|
||||
viewMatrixInv: any;
|
||||
|
||||
constructor(canvas: any) {
|
||||
this.prevEvent = {
|
||||
clientX: 0,
|
||||
clientY: 0,
|
||||
@@ -39,7 +47,7 @@ class Camera {
|
||||
return this.viewMatrix[0];
|
||||
}
|
||||
|
||||
pan(dx, dy) {
|
||||
pan(dx: any, dy: any) {
|
||||
const m = this.viewMatrix;
|
||||
const dyRange = [
|
||||
-panBound - (m[7] + 1) / m[4],
|
||||
@@ -59,7 +67,7 @@ class Camera {
|
||||
mat3.invert(this.viewMatrixInv, m);
|
||||
}
|
||||
|
||||
zoomAt(d, x = 0, y = 0) {
|
||||
zoomAt(d: any, x = 0, y = 0) {
|
||||
/*
|
||||
Camera zoom at [x,y]
|
||||
*/
|
||||
@@ -82,13 +90,13 @@ class Camera {
|
||||
Event handling
|
||||
*/
|
||||
|
||||
flush(e) {
|
||||
flush(e: any) {
|
||||
this.prevEvent.type = e.type;
|
||||
this.prevEvent.clientX = e.clientX;
|
||||
this.prevEvent.clientY = e.clientY;
|
||||
}
|
||||
|
||||
localPosition(target, canvasX, canvasY, projectionInvTF) {
|
||||
localPosition(target: any, canvasX: any, canvasY: any, projectionInvTF: any) {
|
||||
/*
|
||||
Convert mouse position to local
|
||||
*/
|
||||
@@ -108,7 +116,7 @@ class Camera {
|
||||
return pos;
|
||||
}
|
||||
|
||||
mousePan(e, projectionTF) {
|
||||
mousePan(e: any, projectionTF: any) {
|
||||
const projectionInvTF = mat3.invert(scratch0, projectionTF);
|
||||
const pos = this.localPosition(
|
||||
this.canvas,
|
||||
@@ -128,7 +136,7 @@ class Camera {
|
||||
return true;
|
||||
}
|
||||
|
||||
wheelZoom(e, projectionTF) {
|
||||
wheelZoom(e: any, projectionTF: any) {
|
||||
const { height } = this.canvas;
|
||||
const { deltaY, deltaMode, clientX, clientY } = e;
|
||||
const scale = scaleSpeed * (deltaMode === 1 ? 12 : 1) * (deltaY || 0);
|
||||
@@ -144,7 +152,7 @@ class Camera {
|
||||
return true;
|
||||
}
|
||||
|
||||
handleEvent(e, projectionTF) {
|
||||
handleEvent(e: any, projectionTF: any) {
|
||||
/*
|
||||
process the event, and return true if camera view changed
|
||||
*/
|
||||
@@ -173,7 +181,7 @@ class Camera {
|
||||
}
|
||||
}
|
||||
|
||||
function attachCamera(canvas) {
|
||||
function attachCamera(canvas: any) {
|
||||
return new Camera(canvas);
|
||||
}
|
||||
|
||||
@@ -11,20 +11,20 @@ TL;DR: sort order is:
|
||||
import isNumber from "is-number";
|
||||
import * as globals from "../globals";
|
||||
|
||||
function caseInsensitiveCompare(a, b) {
|
||||
function caseInsensitiveCompare(a: any, b: any) {
|
||||
const textA = String(a).toUpperCase();
|
||||
const textB = String(b).toUpperCase();
|
||||
return textA < textB ? -1 : textA > textB ? 1 : 0;
|
||||
}
|
||||
|
||||
const catLabelSort = (isUserAnno, values) => {
|
||||
const catLabelSort = (isUserAnno: any, values: any) => {
|
||||
/* this sort could be memoized for perf */
|
||||
|
||||
const strings = [];
|
||||
const ints = [];
|
||||
const unassignedOrNaN = [];
|
||||
const strings: any = [];
|
||||
const ints: any = [];
|
||||
const unassignedOrNaN: any = [];
|
||||
|
||||
values.forEach((v) => {
|
||||
values.forEach((v: any) => {
|
||||
if (isUserAnno && v === globals.unassignedCategoryLabel) {
|
||||
unassignedOrNaN.push(v);
|
||||
} else if (String(v).toLowerCase() === "nan") {
|
||||
@@ -37,6 +37,7 @@ const catLabelSort = (isUserAnno, values) => {
|
||||
});
|
||||
|
||||
strings.sort(caseInsensitiveCompare);
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'a' implicitly has an 'any' type.
|
||||
ints.sort((a, b) => +a - +b);
|
||||
unassignedOrNaN.sort(caseInsensitiveCompare);
|
||||
|
||||
@@ -23,11 +23,11 @@ label -> {
|
||||
}
|
||||
*/
|
||||
const getCoordinatesByLabel = (
|
||||
schema,
|
||||
categoryName,
|
||||
categoryDf,
|
||||
layoutChoice,
|
||||
layoutDf
|
||||
schema: any,
|
||||
categoryName: any,
|
||||
categoryDf: any,
|
||||
layoutChoice: any,
|
||||
layoutDf: any
|
||||
) => {
|
||||
const coordsByCategoryLabel = new Map();
|
||||
// If the coloredBy is not a categorical col
|
||||
@@ -72,6 +72,7 @@ const getCoordinatesByLabel = (
|
||||
let coords = coordsByCategoryLabel.get(label);
|
||||
if (coords === undefined) {
|
||||
// Get the number of cells which are in the label
|
||||
// @ts-expect-error ts-migrate(2538) FIXME: Type 'unknown' cannot be used as an index type.
|
||||
const numInLabel = categoryValueCounts[labelIndex];
|
||||
coords = {
|
||||
hasFinite: false,
|
||||
@@ -104,11 +105,11 @@ const getCoordinatesByLabel = (
|
||||
*/
|
||||
|
||||
const calcMedianCentroid = (
|
||||
schema,
|
||||
categoryName,
|
||||
categoryDf,
|
||||
layoutChoice,
|
||||
layoutDf
|
||||
schema: any,
|
||||
categoryName: any,
|
||||
categoryDf: any,
|
||||
layoutChoice: any,
|
||||
layoutDf: any
|
||||
) => {
|
||||
// generate a map describing the coordinates for each label within the given category
|
||||
const dataMap = getCoordinatesByLabel(
|
||||
@@ -143,11 +144,12 @@ const calcMedianCentroid = (
|
||||
|
||||
// A simple function to hash the parameters
|
||||
const hashMedianCentroid = (
|
||||
schema,
|
||||
categoryName,
|
||||
categoryDf,
|
||||
layoutChoice,
|
||||
layoutDf
|
||||
// @ts-expect-error ts-migrate(6133) FIXME: 'schema' is declared but its value is never read.
|
||||
schema: any,
|
||||
categoryName: any,
|
||||
categoryDf: any,
|
||||
layoutChoice: any,
|
||||
layoutDf: any
|
||||
) => {
|
||||
const category = categoryDf.col(categoryName);
|
||||
const layoutDimNames = layoutChoice.currentDimNames;
|
||||
@@ -8,6 +8,6 @@
|
||||
* @returns a number
|
||||
*/
|
||||
|
||||
export default function clamp(val, rng) {
|
||||
export default function clamp(val: any, rng: any) {
|
||||
return Math.max(Math.min(val, rng[1]), rng[0]);
|
||||
}
|
||||
@@ -10,7 +10,7 @@ If `setTo` is not undefined, values outside the [lower, upper] range will be set
|
||||
`setTo`.
|
||||
|
||||
*/
|
||||
export default function clip(arr, lower, upper, setTo) {
|
||||
export default function clip(arr: any, lower: any, upper: any, setTo: any) {
|
||||
const lowerSet = setTo === undefined ? lower : setTo;
|
||||
const upperSet = setTo === undefined ? upper : setTo;
|
||||
for (let i = 0, l = arr.length; i < l; i += 1) {
|
||||
@@ -11,12 +11,12 @@ objects.
|
||||
|
||||
import { memoize } from "./util";
|
||||
|
||||
function hashDataframe(df) {
|
||||
function hashDataframe(df: any) {
|
||||
if (df.isEmpty()) return "";
|
||||
return df.__columnsAccessor.map((c) => c.__id).join(",");
|
||||
return df.__columnsAccessor.map((c: any) => c.__id).join(",");
|
||||
}
|
||||
|
||||
function noop(df) {
|
||||
function noop(df: any) {
|
||||
return df;
|
||||
}
|
||||
|
||||
@@ -73,13 +73,26 @@ Dataframe
|
||||
**/
|
||||
|
||||
class Dataframe {
|
||||
__columns: any;
|
||||
|
||||
__columnsAccessor: any;
|
||||
|
||||
__id: any;
|
||||
|
||||
colIndex: any;
|
||||
|
||||
dims: any;
|
||||
|
||||
length: any;
|
||||
|
||||
rowIndex: any;
|
||||
/**
|
||||
Constructors & factories
|
||||
**/
|
||||
|
||||
constructor(
|
||||
dims,
|
||||
columnarData,
|
||||
dims: any,
|
||||
columnarData: any,
|
||||
rowIndex = null,
|
||||
colIndex = null,
|
||||
__columnsAccessor = [] // private interface
|
||||
@@ -104,9 +117,11 @@ class Dataframe {
|
||||
throw new RangeError("Dataframe dimensions must be positive");
|
||||
}
|
||||
if (!rowIndex) {
|
||||
// @ts-expect-error ts-migrate(2322) FIXME: Type 'IdentityInt32Index' is not assignable to typ... Remove this comment to see the full error message
|
||||
rowIndex = new IdentityInt32Index(nRows);
|
||||
}
|
||||
if (!colIndex) {
|
||||
// @ts-expect-error ts-migrate(2322) FIXME: Type 'IdentityInt32Index' is not assignable to typ... Remove this comment to see the full error message
|
||||
colIndex = new IdentityInt32Index(nCols);
|
||||
}
|
||||
Dataframe.__errorChecks(dims, columnarData, rowIndex, colIndex);
|
||||
@@ -122,7 +137,12 @@ class Dataframe {
|
||||
Object.freeze(this);
|
||||
}
|
||||
|
||||
static __errorChecks(dims, columnarData, rowIndex, colIndex) {
|
||||
static __errorChecks(
|
||||
dims: any,
|
||||
columnarData: any,
|
||||
rowIndex: any,
|
||||
colIndex: any
|
||||
) {
|
||||
const [nRows, nCols] = dims;
|
||||
|
||||
/* check for expected types */
|
||||
@@ -160,7 +180,7 @@ class Dataframe {
|
||||
}
|
||||
}
|
||||
|
||||
static __compileColumn(column, getRowByOffset, getRowByLabel) {
|
||||
static __compileColumn(column: any, getRowByOffset: any, getRowByLabel: any) {
|
||||
/*
|
||||
Each column accessor is a function which will lookup data by
|
||||
index (ie, is equivalent to dataframe.get(row, col), where 'col'
|
||||
@@ -195,12 +215,12 @@ class Dataframe {
|
||||
const __id = __getMemoId();
|
||||
|
||||
/* get value by row label */
|
||||
const get = function get(rlabel) {
|
||||
const get = function get(rlabel: any) {
|
||||
return column[getRowByOffset(rlabel)];
|
||||
};
|
||||
|
||||
/* get value by row offset */
|
||||
const iget = function iget(roffset) {
|
||||
const iget = function iget(roffset: any) {
|
||||
return column[roffset];
|
||||
};
|
||||
|
||||
@@ -210,12 +230,12 @@ class Dataframe {
|
||||
};
|
||||
|
||||
/* test for row label inclusion in column */
|
||||
const has = function has(rlabel) {
|
||||
const has = function has(rlabel: any) {
|
||||
const offset = getRowByOffset(rlabel);
|
||||
return offset >= 0 && offset < length;
|
||||
};
|
||||
|
||||
const ihas = function ihas(offset) {
|
||||
const ihas = function ihas(offset: any) {
|
||||
return offset >= 0 && offset < length;
|
||||
};
|
||||
|
||||
@@ -226,7 +246,7 @@ class Dataframe {
|
||||
NOTE: not found return is DIFFERENT than the default Array.indexOf as
|
||||
-1 is a plausible Dataframe row/col label.
|
||||
*/
|
||||
const indexOf = function indexOf(value) {
|
||||
const indexOf = function indexOf(value: any) {
|
||||
const offset = column.indexOf(value);
|
||||
if (offset === -1) {
|
||||
return undefined;
|
||||
@@ -250,11 +270,12 @@ class Dataframe {
|
||||
Create histogram bins for this column. Memoized.
|
||||
*/
|
||||
const _memoHistoCat = memoize(_histogramCategorical, hashCategorical);
|
||||
const histogramCategorical = (by) => _memoHistoCat(get, by);
|
||||
const histogramCategorical = (by: any) => _memoHistoCat(get, by);
|
||||
let histogram = null;
|
||||
if (isTypedArray(column)) {
|
||||
const mFn = memoize(histogramContinuous, hashContinuous);
|
||||
histogram = (bins, domain, by) => mFn(get, bins, domain, by);
|
||||
histogram = (bins: any, domain: any, by: any) =>
|
||||
mFn(get, bins, domain, by);
|
||||
} else {
|
||||
histogram = histogramCategorical;
|
||||
}
|
||||
@@ -274,7 +295,7 @@ class Dataframe {
|
||||
return get;
|
||||
}
|
||||
|
||||
__compile(accessors) {
|
||||
__compile(accessors: any) {
|
||||
/*
|
||||
Compile data accessors for each column.
|
||||
|
||||
@@ -282,7 +303,7 @@ class Dataframe {
|
||||
*/
|
||||
const getRowByOffset = this.rowIndex.getOffset.bind(this.rowIndex);
|
||||
const getRowByLabel = this.rowIndex.getLabel.bind(this.rowIndex);
|
||||
this.__columnsAccessor = this.__columns.map((column, idx) => {
|
||||
this.__columnsAccessor = this.__columns.map((column: any, idx: any) => {
|
||||
if (accessors[idx]) {
|
||||
return accessors[idx];
|
||||
}
|
||||
@@ -295,6 +316,7 @@ class Dataframe {
|
||||
/*
|
||||
Clone this dataframe
|
||||
*/
|
||||
// @ts-expect-error ts-migrate(2351) FIXME: This expression is not constructable.
|
||||
return new this.constructor(
|
||||
this.dims,
|
||||
[...this.__columns],
|
||||
@@ -304,7 +326,7 @@ class Dataframe {
|
||||
);
|
||||
}
|
||||
|
||||
withCol(label, colData, withRowIndex = null) {
|
||||
withCol(label: any, colData: any, withRowIndex = null) {
|
||||
/*
|
||||
Create a new DF, which is `this` plus the new column. Example:
|
||||
const newDf = df.withCol("foo", [1,2,3]);
|
||||
@@ -337,6 +359,7 @@ class Dataframe {
|
||||
columns.push(colData);
|
||||
const colIndex = this.colIndex.withLabel(label);
|
||||
const columnsAccessor = [...this.__columnsAccessor];
|
||||
// @ts-expect-error ts-migrate(2351) FIXME: This expression is not constructable.
|
||||
return new this.constructor(
|
||||
dims,
|
||||
columns,
|
||||
@@ -346,7 +369,7 @@ class Dataframe {
|
||||
);
|
||||
}
|
||||
|
||||
withColsFrom(dataframe, labels) {
|
||||
withColsFrom(dataframe: any, labels: any) {
|
||||
/*
|
||||
return a new dataframe containing all columns from both `this` and the
|
||||
provided dataframe argument.
|
||||
@@ -410,7 +433,9 @@ class Dataframe {
|
||||
|
||||
// otherwise, bulid a new dataframe combining columns from both
|
||||
|
||||
const srcOffsets = srcLabels.map((l) => dataframe.colIndex.getOffset(l));
|
||||
const srcOffsets = srcLabels.map((l: any) =>
|
||||
dataframe.colIndex.getOffset(l)
|
||||
);
|
||||
|
||||
// check for label collisions
|
||||
if (dstLabels.some(this.hasCol, this)) {
|
||||
@@ -422,14 +447,15 @@ class Dataframe {
|
||||
const { rowIndex } = this;
|
||||
const columns = [
|
||||
...this.__columns,
|
||||
...srcOffsets.map((i) => dataframe.__columns[i]),
|
||||
...srcOffsets.map((i: any) => dataframe.__columns[i]),
|
||||
];
|
||||
const colIndex = this.colIndex.withLabels(dstLabels);
|
||||
const columnsAccessor = [
|
||||
...this.__columnsAccessor,
|
||||
...srcOffsets.map((i) => dataframe.__columnsAccessor[i]),
|
||||
...srcOffsets.map((i: any) => dataframe.__columnsAccessor[i]),
|
||||
];
|
||||
|
||||
// @ts-expect-error ts-migrate(2351) FIXME: This expression is not constructable.
|
||||
return new this.constructor(
|
||||
dims,
|
||||
columns,
|
||||
@@ -441,10 +467,11 @@ class Dataframe {
|
||||
|
||||
withColsFromAll(dataframes = []) {
|
||||
dataframes = Array.isArray(dataframes) ? dataframes : [dataframes];
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
||||
return dataframes.reduce((acc, df) => acc.withColsFrom(df), this);
|
||||
}
|
||||
|
||||
dropCol(label) {
|
||||
dropCol(label: any) {
|
||||
/*
|
||||
Create a new dataframe, omitting one columns.
|
||||
|
||||
@@ -470,6 +497,7 @@ class Dataframe {
|
||||
const colIndex = this.colIndex.dropLabel(label);
|
||||
const columnsAccessor = [...this.__columnsAccessor];
|
||||
columnsAccessor.splice(coffset, 1);
|
||||
// @ts-expect-error ts-migrate(2351) FIXME: This expression is not constructable.
|
||||
return new this.constructor(
|
||||
dims,
|
||||
columns,
|
||||
@@ -479,7 +507,7 @@ class Dataframe {
|
||||
);
|
||||
}
|
||||
|
||||
renameCol(oldLabel, newLabel) {
|
||||
renameCol(oldLabel: any, newLabel: any) {
|
||||
/*
|
||||
Accelerator for dropping a column and then adding it again with a new label
|
||||
*/
|
||||
@@ -494,6 +522,7 @@ class Dataframe {
|
||||
columnsAccessor.push(columnsAccessor[coffset]);
|
||||
columnsAccessor.splice(coffset, 1);
|
||||
|
||||
// @ts-expect-error ts-migrate(2351) FIXME: This expression is not constructable.
|
||||
return new this.constructor(
|
||||
this.dims,
|
||||
columns,
|
||||
@@ -503,7 +532,7 @@ class Dataframe {
|
||||
);
|
||||
}
|
||||
|
||||
replaceColData(label, newColData) {
|
||||
replaceColData(label: any, newColData: any) {
|
||||
/*
|
||||
Accelerator for dropping a column then adding it again with same
|
||||
label and different values.
|
||||
@@ -514,6 +543,7 @@ class Dataframe {
|
||||
const columnsAccessor = [...this.__columnsAccessor];
|
||||
columnsAccessor[coffset] = null;
|
||||
|
||||
// @ts-expect-error ts-migrate(2351) FIXME: This expression is not constructable.
|
||||
return new this.constructor(
|
||||
this.dims,
|
||||
columns,
|
||||
@@ -525,14 +555,16 @@ class Dataframe {
|
||||
|
||||
static empty(rowIndex = null, colIndex = null) {
|
||||
const dims = [
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
rowIndex ? rowIndex.size() : 0,
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
colIndex ? colIndex.size() : 0,
|
||||
];
|
||||
if (dims[0] && dims[1]) throw new Error("not an empty dataframe");
|
||||
return new Dataframe(dims, new Array(dims[1]), rowIndex, colIndex);
|
||||
}
|
||||
|
||||
static create(dims, columnarData) {
|
||||
static create(dims: any, columnarData: any) {
|
||||
/*
|
||||
Create a dataframe from raw columnar data. All column arrays
|
||||
must have the same length. Identity indexing will be used.
|
||||
@@ -543,7 +575,7 @@ class Dataframe {
|
||||
return new Dataframe(dims, columnarData, null, null);
|
||||
}
|
||||
|
||||
__subset(newRowIndex, newColIndex) {
|
||||
__subset(newRowIndex: any, newColIndex: any) {
|
||||
const dims = [...this.dims];
|
||||
|
||||
/* subset columns */
|
||||
@@ -563,7 +595,7 @@ class Dataframe {
|
||||
let { rowIndex } = this;
|
||||
if (newRowIndex) {
|
||||
const rowOffsets = this.rowIndex.getOffsets(newRowIndex.labels());
|
||||
__columns = __columns.map((col) => {
|
||||
__columns = __columns.map((col: any) => {
|
||||
const newCol = new col.constructor(rowOffsets.length);
|
||||
for (let i = 0, l = rowOffsets.length; i < l; i += 1) {
|
||||
newCol[i] = col[rowOffsets[i]];
|
||||
@@ -585,7 +617,7 @@ class Dataframe {
|
||||
);
|
||||
}
|
||||
|
||||
subset(rowLabels, colLabels = null, withRowIndex = null) {
|
||||
subset(rowLabels: any, colLabels = null, withRowIndex = null) {
|
||||
/*
|
||||
Subset by row/col labels.
|
||||
|
||||
@@ -607,7 +639,7 @@ class Dataframe {
|
||||
return this.__subset(rowIndex, colIndex);
|
||||
}
|
||||
|
||||
isubset(rowOffsets, colOffsets = null, withRowIndex = null) {
|
||||
isubset(rowOffsets: any, colOffsets = null, withRowIndex = null) {
|
||||
/*
|
||||
Subset by row/col offset.
|
||||
|
||||
@@ -631,7 +663,7 @@ class Dataframe {
|
||||
return this.__subset(rowIndex, colIndex);
|
||||
}
|
||||
|
||||
isubsetMask(rowMask, colMask = null, withRowIndex = null) {
|
||||
isubsetMask(rowMask: any, colMask = null, withRowIndex = null) {
|
||||
/*
|
||||
Subset on row/column based upon a truthy/falsey array (a mask).
|
||||
|
||||
@@ -643,13 +675,14 @@ class Dataframe {
|
||||
const [nRows, nCols] = this.dims;
|
||||
if (
|
||||
(rowMask && rowMask.length !== nRows) ||
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
(colMask && colMask.length !== nCols)
|
||||
) {
|
||||
throw new RangeError("boolean arrays must match row/col dimensions");
|
||||
}
|
||||
|
||||
/* convert masks to lists - method wastes space, but is fast */
|
||||
const toList = (mask, maxSize) => {
|
||||
const toList = (mask: any, maxSize: any) => {
|
||||
if (!mask) {
|
||||
return null;
|
||||
}
|
||||
@@ -665,6 +698,7 @@ class Dataframe {
|
||||
};
|
||||
const rowOffsets = toList(rowMask, nRows);
|
||||
const colOffsets = toList(colMask, nCols);
|
||||
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'Int32Array | null' is not assign... Remove this comment to see the full error message
|
||||
return this.isubset(rowOffsets, colOffsets, withRowIndex);
|
||||
}
|
||||
|
||||
@@ -677,7 +711,7 @@ class Dataframe {
|
||||
return [...this.__columnsAccessor];
|
||||
}
|
||||
|
||||
col(columnLabel) {
|
||||
col(columnLabel: any) {
|
||||
/*
|
||||
Return accessor bound to a column. Allows random row access
|
||||
based upon the row indexing. Returns undefined if the
|
||||
@@ -697,7 +731,7 @@ class Dataframe {
|
||||
return this.__columnsAccessor[coff];
|
||||
}
|
||||
|
||||
icol(columnOffset) {
|
||||
icol(columnOffset: any) {
|
||||
/*
|
||||
Return column accessor by offset.
|
||||
*/
|
||||
@@ -706,7 +740,7 @@ class Dataframe {
|
||||
: undefined;
|
||||
}
|
||||
|
||||
at(r, c) {
|
||||
at(r: any, c: any) {
|
||||
/*
|
||||
Access a single value, for a row/col label pair.
|
||||
|
||||
@@ -723,7 +757,7 @@ class Dataframe {
|
||||
return this.__columns[coff][roff];
|
||||
}
|
||||
|
||||
iat(r, c) {
|
||||
iat(r: any, c: any) {
|
||||
/*
|
||||
Access a single value, for a row/col offset (integer) position.
|
||||
|
||||
@@ -736,7 +770,7 @@ class Dataframe {
|
||||
return this.__columns[c][r];
|
||||
}
|
||||
|
||||
has(r, c) {
|
||||
has(r: any, c: any) {
|
||||
/*
|
||||
Test if row/col labels exist in the dataframe - returns true/false
|
||||
*/
|
||||
@@ -746,7 +780,7 @@ class Dataframe {
|
||||
return coff >= 0 && coff < nCols && roff >= 0 && roff < nRows;
|
||||
}
|
||||
|
||||
ihas(r, c) {
|
||||
ihas(r: any, c: any) {
|
||||
/*
|
||||
Test if row/col offset (integer) position exists in the
|
||||
dataframe - returns true/false
|
||||
@@ -762,7 +796,7 @@ class Dataframe {
|
||||
);
|
||||
}
|
||||
|
||||
hasCol(c) {
|
||||
hasCol(c: any) {
|
||||
/*
|
||||
Test if col label exists - return true/false
|
||||
*/
|
||||
@@ -784,19 +818,20 @@ class Dataframe {
|
||||
add these as useful.
|
||||
****/
|
||||
|
||||
mapColumns(callback) {
|
||||
mapColumns(callback: any) {
|
||||
/*
|
||||
map all columns in the dataframe, returning a new dataframe comprised of the
|
||||
return values, with the same index as the original dataframe.
|
||||
|
||||
callback MUST not modify the column, but instead return a mutated copy.
|
||||
*/
|
||||
const columns = this.__columns.map((colData, colIdx) =>
|
||||
const columns = this.__columns.map((colData: any, colIdx: any) =>
|
||||
callback(colData, colIdx, this)
|
||||
);
|
||||
const columnsAccessor = columns.map((c, idx) =>
|
||||
const columnsAccessor = columns.map((c: any, idx: any) =>
|
||||
this.__columns[idx] === c ? this.__columnsAccessor[idx] : undefined
|
||||
);
|
||||
// @ts-expect-error ts-migrate(2351) FIXME: This expression is not constructable.
|
||||
return new this.constructor(
|
||||
this.dims,
|
||||
columns,
|
||||
@@ -3,7 +3,7 @@ Dataframe histogram
|
||||
*/
|
||||
import { isTypedArray } from "./util";
|
||||
|
||||
function _histogramContinuous(column, bins, min, max) {
|
||||
function _histogramContinuous(column: any, bins: any, min: any, max: any) {
|
||||
const valBins = new Array(bins).fill(0);
|
||||
if (!column) {
|
||||
return valBins;
|
||||
@@ -21,7 +21,13 @@ function _histogramContinuous(column, bins, min, max) {
|
||||
return valBins;
|
||||
}
|
||||
|
||||
function _histogramContinuousBy(column, bins, min, max, by) {
|
||||
function _histogramContinuousBy(
|
||||
column: any,
|
||||
bins: any,
|
||||
min: any,
|
||||
max: any,
|
||||
by: any
|
||||
) {
|
||||
const byMap = new Map();
|
||||
if (!column || !by) {
|
||||
return byMap;
|
||||
@@ -46,7 +52,7 @@ function _histogramContinuousBy(column, bins, min, max, by) {
|
||||
return byMap;
|
||||
}
|
||||
|
||||
function _histogramCategorical(column) {
|
||||
function _histogramCategorical(column: any) {
|
||||
const valMap = new Map();
|
||||
if (!column) {
|
||||
return valMap;
|
||||
@@ -63,7 +69,7 @@ function _histogramCategorical(column) {
|
||||
return valMap;
|
||||
}
|
||||
|
||||
function _histogramCategoricalBy(column, by) {
|
||||
function _histogramCategoricalBy(column: any, by: any) {
|
||||
const byMap = new Map();
|
||||
if (!column || !by) {
|
||||
return byMap;
|
||||
@@ -90,7 +96,7 @@ function _histogramCategoricalBy(column, by) {
|
||||
/*
|
||||
Count category occupancy. Optional group-by category.
|
||||
*/
|
||||
export function histogramCategorical(column, by) {
|
||||
export function histogramCategorical(column: any, by: any) {
|
||||
if (by && isTypedArray(by)) {
|
||||
throw new Error("Group by column must be categorical");
|
||||
}
|
||||
@@ -102,7 +108,7 @@ export function histogramCategorical(column, by) {
|
||||
/*
|
||||
Memoization hash for histogramCategorical()
|
||||
*/
|
||||
export function hashCategorical(column, by) {
|
||||
export function hashCategorical(column: any, by: any) {
|
||||
if (by) {
|
||||
return `${column.__id}:${by.__id}`;
|
||||
}
|
||||
@@ -113,7 +119,12 @@ export function hashCategorical(column, by) {
|
||||
Bin counts for continuous/scalar values, with optional group-by category.
|
||||
Values outside domain are ignored.
|
||||
*/
|
||||
export function histogramContinuous(column, bins = 40, domain = [0, 1], by) {
|
||||
export function histogramContinuous(
|
||||
column: any,
|
||||
bins = 40,
|
||||
domain = [0, 1],
|
||||
by: any
|
||||
) {
|
||||
if (by && isTypedArray(by)) {
|
||||
throw new Error("Group by column must be categorical");
|
||||
}
|
||||
@@ -126,7 +137,12 @@ export function histogramContinuous(column, bins = 40, domain = [0, 1], by) {
|
||||
/*
|
||||
Memoization hash for histogramContinuous
|
||||
*/
|
||||
export function hashContinuous(column, bins = "", domain = [0, 0], by) {
|
||||
export function hashContinuous(
|
||||
column: any,
|
||||
bins = "",
|
||||
domain = [0, 0],
|
||||
by: any
|
||||
) {
|
||||
const [min, max] = domain;
|
||||
if (by) {
|
||||
return `${column.__id}:${bins}:${min}:${max}:${by.__id}`;
|
||||
@@ -10,7 +10,7 @@ import { __getMemoId } from "./util";
|
||||
/*
|
||||
Private utility functions
|
||||
*/
|
||||
function extent(tarr) {
|
||||
function extent(tarr: any) {
|
||||
let min = 0x7fffffff;
|
||||
let max = ~min; // eslint-disable-line no-bitwise -- Establishes 0 of same size
|
||||
for (let i = 0, l = tarr.length; i < l; i += 1) {
|
||||
@@ -26,10 +26,12 @@ function extent(tarr) {
|
||||
}
|
||||
|
||||
class IdentityInt32Index {
|
||||
maxOffset: any;
|
||||
|
||||
/*
|
||||
identity/noop index, with small assumptions that labels are int32
|
||||
*/
|
||||
constructor(maxOffset) {
|
||||
constructor(maxOffset: any) {
|
||||
this.maxOffset = maxOffset;
|
||||
}
|
||||
|
||||
@@ -46,31 +48,31 @@ class IdentityInt32Index {
|
||||
return k;
|
||||
}
|
||||
|
||||
getOffset(i) {
|
||||
getOffset(i: any) {
|
||||
// label to offset
|
||||
return Number.isInteger(i) && i >= 0 && i < this.maxOffset ? i : undefined;
|
||||
}
|
||||
|
||||
getOffsets(arr) {
|
||||
getOffsets(arr: any) {
|
||||
// labels to offsets
|
||||
return arr.map((i) => this.getOffset(i));
|
||||
return arr.map((i: any) => this.getOffset(i));
|
||||
}
|
||||
|
||||
getLabel(i) {
|
||||
getLabel(i: any) {
|
||||
// offset to label
|
||||
return Number.isInteger(i) && i >= 0 && i < this.maxOffset ? i : undefined;
|
||||
}
|
||||
|
||||
getLabels(arr) {
|
||||
getLabels(arr: any) {
|
||||
// offsets to labels
|
||||
return arr.map((i) => this.getLabel(i));
|
||||
return arr.map((i: any) => this.getLabel(i));
|
||||
}
|
||||
|
||||
size() {
|
||||
return this.maxOffset;
|
||||
}
|
||||
|
||||
__promote(labelArray) {
|
||||
__promote(labelArray: any) {
|
||||
/*
|
||||
time/space decision - based on the resulting density
|
||||
*/
|
||||
@@ -84,10 +86,11 @@ class IdentityInt32Index {
|
||||
if (density < 0.1) {
|
||||
return new KeyIndex(labelArray);
|
||||
}
|
||||
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'number[]' is not assignable to p... Remove this comment to see the full error message
|
||||
return new DenseInt32Index(labelArray, [minLabel, maxLabel]);
|
||||
}
|
||||
|
||||
subset(labels) {
|
||||
subset(labels: any) {
|
||||
/* validate subset */
|
||||
const { maxOffset } = this;
|
||||
for (let i = 0, l = labels.length; i < l; i += 1) {
|
||||
@@ -99,12 +102,12 @@ class IdentityInt32Index {
|
||||
}
|
||||
|
||||
/* identity index - labels are offsets */
|
||||
isubset(offsets) {
|
||||
isubset(offsets: any) {
|
||||
return this.subset(offsets);
|
||||
}
|
||||
|
||||
/* identity index - labels are offsets */
|
||||
isubsetMask(mask) {
|
||||
isubsetMask(mask: any) {
|
||||
let count = 0;
|
||||
if (mask.length !== this.maxOffset) {
|
||||
throw new RangeError("mask has invalid length for index");
|
||||
@@ -120,18 +123,18 @@ class IdentityInt32Index {
|
||||
return this.subset(labels);
|
||||
}
|
||||
|
||||
withLabel(label) {
|
||||
withLabel(label: any) {
|
||||
if (label === this.maxOffset) {
|
||||
return new IdentityInt32Index(label + 1);
|
||||
}
|
||||
return this.__promote([...this.labels(), label]);
|
||||
}
|
||||
|
||||
withLabels(labels) {
|
||||
withLabels(labels: any) {
|
||||
return this.__promote([...this.labels(), ...labels]);
|
||||
}
|
||||
|
||||
dropLabel(label) {
|
||||
dropLabel(label: any) {
|
||||
if (label === this.maxOffset - 1) {
|
||||
return new IdentityInt32Index(label);
|
||||
}
|
||||
@@ -142,20 +145,38 @@ class IdentityInt32Index {
|
||||
}
|
||||
|
||||
class DenseInt32Index {
|
||||
__id: any;
|
||||
|
||||
getLabel: any;
|
||||
|
||||
getLabels: any;
|
||||
|
||||
getOffset: any;
|
||||
|
||||
getOffsets: any;
|
||||
|
||||
index: any;
|
||||
|
||||
minLabel: any;
|
||||
|
||||
rindex: any;
|
||||
|
||||
/*
|
||||
DenseInt32Index indexes integer labels, and uses Int32Array typed arrays
|
||||
for both forward and reverse indexing. This means that the min/max range
|
||||
of the forward index labels must be known a priori (so that the index
|
||||
array can be pre-allocated).
|
||||
*/
|
||||
constructor(labels, labelRange = null) {
|
||||
constructor(labels: any, labelRange = null) {
|
||||
if (labels.constructor !== Int32Array) {
|
||||
labels = new Int32Array(labels);
|
||||
}
|
||||
|
||||
if (!labelRange) {
|
||||
// @ts-expect-error ts-migrate(2322) FIXME: Type 'number[]' is not assignable to type 'null'.
|
||||
labelRange = extent(labels);
|
||||
}
|
||||
// @ts-expect-error ts-migrate(2488) FIXME: Type 'null' must have a '[Symbol.iterator]()' meth... Remove this comment to see the full error message
|
||||
const [minLabel, maxLabel] = labelRange;
|
||||
const labelSpaceSize = maxLabel - minLabel + 1;
|
||||
const index = new Int32Array(labelSpaceSize).fill(-1);
|
||||
@@ -173,22 +194,22 @@ class DenseInt32Index {
|
||||
|
||||
__compile() {
|
||||
const { minLabel, index, rindex } = this;
|
||||
this.getOffset = function getOffset(l) {
|
||||
this.getOffset = function getOffset(l: any) {
|
||||
if (!Number.isInteger(l)) return undefined;
|
||||
const offset = index[l - minLabel];
|
||||
return offset === -1 ? undefined : offset;
|
||||
};
|
||||
|
||||
this.getOffsets = function getOffsets(arr) {
|
||||
return arr.map((i) => this.getOffset(i));
|
||||
this.getOffsets = function getOffsets(arr: any) {
|
||||
return arr.map((i: any) => this.getOffset(i));
|
||||
};
|
||||
|
||||
this.getLabel = function getLabel(i) {
|
||||
this.getLabel = function getLabel(i: any) {
|
||||
return Number.isInteger(i) ? rindex[i] : undefined;
|
||||
};
|
||||
|
||||
this.getLabels = function getLabels(arr) {
|
||||
return arr.map((i) => this.getLabel(i));
|
||||
this.getLabels = function getLabels(arr: any) {
|
||||
return arr.map((i: any) => this.getLabel(i));
|
||||
};
|
||||
}
|
||||
|
||||
@@ -200,7 +221,7 @@ class DenseInt32Index {
|
||||
return this.rindex.length;
|
||||
}
|
||||
|
||||
__promote(labelArray) {
|
||||
__promote(labelArray: any) {
|
||||
/*
|
||||
time/space decision - if we are going to use less than 10% of the
|
||||
dense index space, switch to a KeyIndex (which is slower, but uses
|
||||
@@ -213,10 +234,11 @@ class DenseInt32Index {
|
||||
if (density < 0.1) {
|
||||
return new KeyIndex(labelArray);
|
||||
}
|
||||
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'number[]' is not assignable to p... Remove this comment to see the full error message
|
||||
return new DenseInt32Index(labelArray, [minLabel, maxLabel]);
|
||||
}
|
||||
|
||||
subset(labels) {
|
||||
subset(labels: any) {
|
||||
/* validate subset */
|
||||
for (let i = 0, l = labels.length; i < l; i += 1) {
|
||||
const label = labels[i];
|
||||
@@ -227,7 +249,7 @@ class DenseInt32Index {
|
||||
return this.__promote(labels);
|
||||
}
|
||||
|
||||
isubset(offsets) {
|
||||
isubset(offsets: any) {
|
||||
/* validate subset */
|
||||
const { rindex } = this;
|
||||
const maxOffset = rindex.length;
|
||||
@@ -241,7 +263,7 @@ class DenseInt32Index {
|
||||
return this.__promote(labels);
|
||||
}
|
||||
|
||||
isubsetMask(mask) {
|
||||
isubsetMask(mask: any) {
|
||||
const { rindex } = this;
|
||||
if (mask.length !== rindex.length)
|
||||
throw new RangeError("mask has invalid length for index");
|
||||
@@ -257,15 +279,15 @@ class DenseInt32Index {
|
||||
return this.__promote(labels);
|
||||
}
|
||||
|
||||
withLabel(label) {
|
||||
withLabel(label: any) {
|
||||
return this.__promote([...this.labels(), label]);
|
||||
}
|
||||
|
||||
withLabels(labels) {
|
||||
withLabels(labels: any) {
|
||||
return this.__promote([...this.labels(), ...labels]);
|
||||
}
|
||||
|
||||
dropLabel(label) {
|
||||
dropLabel(label: any) {
|
||||
const labelArray = [...this.labels()];
|
||||
labelArray.splice(labelArray.indexOf(label), 1);
|
||||
return this.__promote(labelArray);
|
||||
@@ -273,17 +295,31 @@ class DenseInt32Index {
|
||||
}
|
||||
|
||||
class KeyIndex {
|
||||
__id: any;
|
||||
|
||||
getLabel: any;
|
||||
|
||||
getLabels: any;
|
||||
|
||||
getOffset: any;
|
||||
|
||||
getOffsets: any;
|
||||
|
||||
index: any;
|
||||
|
||||
rindex: any;
|
||||
|
||||
/*
|
||||
KeyIndex indexes arbitrary JS primitive types, and uses a Map()
|
||||
as its core data structure.
|
||||
*/
|
||||
constructor(labels) {
|
||||
constructor(labels: any) {
|
||||
const index = new Map();
|
||||
if (labels === undefined) {
|
||||
labels = [];
|
||||
}
|
||||
const rindex = labels;
|
||||
labels.forEach((v, i) => {
|
||||
labels.forEach((v: any, i: any) => {
|
||||
index.set(v, i);
|
||||
});
|
||||
|
||||
@@ -300,20 +336,20 @@ class KeyIndex {
|
||||
|
||||
__compile() {
|
||||
const { index, rindex } = this;
|
||||
this.getOffset = function getOffset(k) {
|
||||
this.getOffset = function getOffset(k: any) {
|
||||
return index.get(k);
|
||||
};
|
||||
|
||||
this.getOffsets = function getOffsets(arr) {
|
||||
return arr.map((l) => this.getOffset(l));
|
||||
this.getOffsets = function getOffsets(arr: any) {
|
||||
return arr.map((l: any) => this.getOffset(l));
|
||||
};
|
||||
|
||||
this.getLabel = function getLabel(i) {
|
||||
this.getLabel = function getLabel(i: any) {
|
||||
return Number.isInteger(i) ? rindex[i] : undefined;
|
||||
};
|
||||
|
||||
this.getLabels = function getLabels(arr) {
|
||||
return arr.map((i) => this.getLabel(i));
|
||||
this.getLabels = function getLabels(arr: any) {
|
||||
return arr.map((i: any) => this.getLabel(i));
|
||||
};
|
||||
}
|
||||
|
||||
@@ -325,7 +361,7 @@ class KeyIndex {
|
||||
return this.rindex.length;
|
||||
}
|
||||
|
||||
subset(labels) {
|
||||
subset(labels: any) {
|
||||
/* validate subset */
|
||||
for (let i = 0, l = labels.length; i < l; i += 1) {
|
||||
const label = labels[i];
|
||||
@@ -338,7 +374,7 @@ class KeyIndex {
|
||||
return new KeyIndex(labels);
|
||||
}
|
||||
|
||||
isubset(offsets) {
|
||||
isubset(offsets: any) {
|
||||
const { rindex } = this;
|
||||
const maxOffset = rindex.length;
|
||||
const labels = new Array(offsets.length);
|
||||
@@ -352,7 +388,7 @@ class KeyIndex {
|
||||
return new KeyIndex(labels);
|
||||
}
|
||||
|
||||
isubsetMask(mask) {
|
||||
isubsetMask(mask: any) {
|
||||
const { rindex } = this;
|
||||
if (mask.length !== rindex.length)
|
||||
throw new RangeError("mask has invalid length for index");
|
||||
@@ -368,15 +404,15 @@ class KeyIndex {
|
||||
return new KeyIndex(labels);
|
||||
}
|
||||
|
||||
withLabel(label) {
|
||||
withLabel(label: any) {
|
||||
return new KeyIndex([...this.rindex, label]);
|
||||
}
|
||||
|
||||
withLabels(labels) {
|
||||
withLabels(labels: any) {
|
||||
return new KeyIndex([...this.rindex, ...labels]);
|
||||
}
|
||||
|
||||
dropLabel(label) {
|
||||
dropLabel(label: any) {
|
||||
const idx = this.rindex.indexOf(label);
|
||||
const labelArray = [...this.rindex];
|
||||
labelArray.splice(idx, 1);
|
||||
@@ -384,7 +420,7 @@ class KeyIndex {
|
||||
}
|
||||
}
|
||||
|
||||
function isLabelIndex(i) {
|
||||
function isLabelIndex(i: any) {
|
||||
return (
|
||||
i instanceof IdentityInt32Index ||
|
||||
i instanceof DenseInt32Index ||
|
||||
@@ -10,9 +10,10 @@ import quantile from "../quantile";
|
||||
import { sortArray } from "../typedCrossfilter/sort";
|
||||
|
||||
// [ 0, 0.01, 0.02, ..., 1.0]
|
||||
// @ts-expect-error ts-migrate(6133) FIXME: 'v' is declared but its value is never read.
|
||||
const centileNames = new Array(101).fill(0).map((v, idx) => idx / 100);
|
||||
|
||||
export function summarizeContinuous(col) {
|
||||
export function summarizeContinuous(col: any) {
|
||||
let min;
|
||||
let max;
|
||||
let nan = 0;
|
||||
@@ -63,7 +64,7 @@ export function summarizeContinuous(col) {
|
||||
};
|
||||
}
|
||||
|
||||
export function summarizeCategorical(col) {
|
||||
export function summarizeCategorical(col: any) {
|
||||
const categoryCounts = new Map();
|
||||
if (col) {
|
||||
for (let r = 0, l = col.length; r < l; r += 1) {
|
||||
@@ -4,14 +4,14 @@ Private utility code for dataframe
|
||||
|
||||
export { isTypedArray, isArrayOrTypedArray } from "../typeHelpers";
|
||||
|
||||
export function callOnceLazy(f) {
|
||||
export function callOnceLazy(f: any) {
|
||||
/*
|
||||
call function once, and save the result, regardless of arguments (this is not
|
||||
the same as typical memoization).
|
||||
*/
|
||||
let value;
|
||||
let value: any;
|
||||
let calledOnce = false;
|
||||
const result = function result(...args) {
|
||||
const result = function result(...args: any[]) {
|
||||
if (!calledOnce) {
|
||||
value = f(...args);
|
||||
calledOnce = true;
|
||||
@@ -21,7 +21,7 @@ export function callOnceLazy(f) {
|
||||
return result;
|
||||
}
|
||||
|
||||
export function memoize(fn, hashFn, maxResultsCached = -1) {
|
||||
export function memoize(fn: any, hashFn: any, maxResultsCached = -1) {
|
||||
/*
|
||||
function memoization, with user-provided hash. hashFn must return a
|
||||
key which will be unique as a Map key (ie, obeys "sameValueZero" algorithm
|
||||
@@ -29,7 +29,7 @@ export function memoize(fn, hashFn, maxResultsCached = -1) {
|
||||
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map#Key_equality
|
||||
*/
|
||||
const cache = new Map();
|
||||
const wrap = function wrap(...args) {
|
||||
const wrap = function wrap(...args: any[]) {
|
||||
const key = hashFn(...args);
|
||||
if (cache.has(key)) {
|
||||
return cache.get(key);
|
||||
@@ -6,7 +6,7 @@ If undefined or empty array, or array contains only non-finite numbers,
|
||||
will return [undefined, undefined]
|
||||
*/
|
||||
|
||||
function finiteExtent(tarr) {
|
||||
function finiteExtent(tarr: any) {
|
||||
let min;
|
||||
let max;
|
||||
let i;
|
||||
@@ -1,4 +1,4 @@
|
||||
export default function fromEntries(arr) {
|
||||
export default function fromEntries(arr: any) {
|
||||
/*
|
||||
Similar to Object.fromEntries, but only handles array.
|
||||
This could be replaced with the standard fucnction once it
|
||||
@@ -7,6 +7,7 @@ export default function fromEntries(arr) {
|
||||
*/
|
||||
const obj = {};
|
||||
for (let i = 0, l = arr.length; i < l; i += 1) {
|
||||
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
|
||||
obj[arr[i][0]] = arr[i][1];
|
||||
}
|
||||
return obj;
|
||||
@@ -10,11 +10,11 @@ import significantDigits from "./significantDigits";
|
||||
* @returns - the number formatted as scientific, if it's big enough
|
||||
*/
|
||||
|
||||
export default function maybeScientific(x) {
|
||||
export default function maybeScientific(x: any) {
|
||||
let format = ",";
|
||||
const _ticks = x.ticks(4);
|
||||
|
||||
if (x.domain().some((n) => Math.abs(n) >= 10000)) {
|
||||
if (x.domain().some((n: any) => Math.abs(n) >= 10000)) {
|
||||
/*
|
||||
heuristic: if the last tick d3 wants to render has one significant
|
||||
digit ie., 2000, render 2e+3, but if it's anything else ie., 42000000 render
|
||||
@@ -13,15 +13,17 @@ anno matrix namespaces. It is still used by the component tier.
|
||||
|
||||
*/
|
||||
|
||||
const makeDimensionName = (namespace, key) => `${namespace}_${key}`;
|
||||
const makeDimensionName = (namespace: any, key: any) => `${namespace}_${key}`;
|
||||
|
||||
export const layoutDimensionName = (key) => makeDimensionName("layout", key);
|
||||
export const obsAnnoDimensionName = (key) => makeDimensionName("obsAnno", key);
|
||||
export const diffexpDimensionName = (key) =>
|
||||
export const layoutDimensionName = (key: any) =>
|
||||
makeDimensionName("layout", key);
|
||||
export const obsAnnoDimensionName = (key: any) =>
|
||||
makeDimensionName("obsAnno", key);
|
||||
export const diffexpDimensionName = (key: any) =>
|
||||
makeDimensionName("varData_diffexp", key);
|
||||
export const userDefinedDimensionName = (key) =>
|
||||
export const userDefinedDimensionName = (key: any) =>
|
||||
makeDimensionName("varData_userDefined", key);
|
||||
export const geneSetSummaryDimensionName = (key) =>
|
||||
export const geneSetSummaryDimensionName = (key: any) =>
|
||||
makeDimensionName("geneSetSummary", key);
|
||||
|
||||
/*
|
||||
@@ -35,7 +37,10 @@ export const geneSetSummaryDimensionName = (key) =>
|
||||
ie., makeContinuousDimensionName(continuousNamespace = {isObs: true}, "total_reads")
|
||||
see: histogram brush, as it doesn't know what type of continuous it was with only field
|
||||
*/
|
||||
export const makeContinuousDimensionName = (continuousNamespace, key) => {
|
||||
export const makeContinuousDimensionName = (
|
||||
continuousNamespace: any,
|
||||
key: any
|
||||
) => {
|
||||
let name;
|
||||
if (continuousNamespace.isObs) {
|
||||
name = obsAnnoDimensionName(key);
|
||||
@@ -6,6 +6,6 @@
|
||||
import pull from "lodash.pull";
|
||||
import uniq from "lodash.uniq";
|
||||
|
||||
export default function parseBulkGeneString(geneString) {
|
||||
export default function parseBulkGeneString(geneString: any) {
|
||||
return pull(uniq(geneString.split(/[ ,]+/)), "");
|
||||
}
|
||||
@@ -6,23 +6,28 @@ import scaleRGB from "./scaleRGB";
|
||||
//
|
||||
const colorCache = {};
|
||||
|
||||
function parseColorName(c) {
|
||||
function parseColorName(c: any) {
|
||||
if (c[0] !== "#") {
|
||||
const _c = c.replace(/[^\d,.]/g, "").split(",");
|
||||
return [scaleRGB(+_c[0]), scaleRGB(+_c[1]), scaleRGB(+_c[2])];
|
||||
}
|
||||
const parsedHex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(c);
|
||||
return [
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
scaleRGB(parseInt(parsedHex[1], 16)),
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
scaleRGB(parseInt(parsedHex[2], 16)),
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
scaleRGB(parseInt(parsedHex[3], 16)),
|
||||
];
|
||||
}
|
||||
|
||||
export default (c) => {
|
||||
export default (c: any) => {
|
||||
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
|
||||
let cv = colorCache[c];
|
||||
if (!cv) {
|
||||
cv = parseColorName(c);
|
||||
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
|
||||
colorCache[c] = cv;
|
||||
}
|
||||
return cv;
|
||||
@@ -28,6 +28,7 @@ Priority is a numeric value. Lower first. Stable ordering.
|
||||
|
||||
import TinyQueue from "tinyqueue";
|
||||
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'a' implicitly has an 'any' type.
|
||||
function compare(a, b) {
|
||||
const diff = a.priority - b.priority;
|
||||
if (diff) return diff;
|
||||
@@ -36,12 +37,13 @@ function compare(a, b) {
|
||||
|
||||
export default class PromiseLimit {
|
||||
constructor(maxConcurrency = 5) {
|
||||
this.queue = new TinyQueue([], compare);
|
||||
this.maxConcurrency = maxConcurrency;
|
||||
this.pending = 0;
|
||||
this.insertCounter = 0;
|
||||
(this as any).queue = new TinyQueue([], compare);
|
||||
(this as any).maxConcurrency = maxConcurrency;
|
||||
(this as any).pending = 0;
|
||||
(this as any).insertCounter = 0;
|
||||
}
|
||||
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'p' implicitly has an 'any' type.
|
||||
priorityAdd(p, fn, ...args) {
|
||||
// p - numermic priority (lower first)
|
||||
// fn - must return a promise
|
||||
@@ -49,6 +51,7 @@ export default class PromiseLimit {
|
||||
return this._push(p, fn, args);
|
||||
}
|
||||
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'fn' implicitly has an 'any' type.
|
||||
add(fn, ...args) {
|
||||
// fn - must return a promise
|
||||
// args - will be passed to fn
|
||||
@@ -59,21 +62,25 @@ export default class PromiseLimit {
|
||||
Private below
|
||||
**/
|
||||
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'priority' implicitly has an 'any' type.
|
||||
_push(priority, fn, args) {
|
||||
const order = this.insertCount;
|
||||
this.insertCount += 1;
|
||||
const order = (this as any).insertCount;
|
||||
(this as any).insertCount += 1;
|
||||
return new Promise((resolve, reject) => {
|
||||
this.queue.push({ priority, order, fn, args, resolve, reject });
|
||||
(this as any).queue.push({ priority, order, fn, args, resolve, reject });
|
||||
this._resolveNext(false);
|
||||
});
|
||||
}
|
||||
|
||||
_resolveNext = (completed = true) => {
|
||||
if (completed) this.pending -= 1;
|
||||
if (completed) (this as any).pending -= 1;
|
||||
|
||||
while (this.queue.length > 0 && this.pending < this.maxConcurrency) {
|
||||
const task = this.queue.pop(); // order of insertion
|
||||
this.pending += 1;
|
||||
while (
|
||||
(this as any).queue.length > 0 &&
|
||||
(this as any).pending < (this as any).maxConcurrency
|
||||
) {
|
||||
const task = (this as any).queue.pop(); // order of insertion
|
||||
(this as any).pending += 1;
|
||||
const { resolve, reject, fn, args } = task;
|
||||
|
||||
try {
|
||||
@@ -14,12 +14,14 @@ Arguments:
|
||||
|
||||
import { sortArray } from "./typedCrossfilter/sort";
|
||||
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'quantArr' implicitly has an 'any' type.
|
||||
export default function quantile(quantArr, tarr, sorted = false) {
|
||||
/*
|
||||
start with the naive (sort) implementation. Later, use a faster partition
|
||||
*/
|
||||
const arr = sorted ? tarr : sortArray(new tarr.constructor(tarr)); // copy
|
||||
const len = arr.length;
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'q' implicitly has an 'any' type.
|
||||
return quantArr.map((q) => {
|
||||
if (q === 1) {
|
||||
return arr[len - 1];
|
||||
@@ -22,6 +22,7 @@ rangeFill(array, start, step) -> array
|
||||
|
||||
*/
|
||||
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'arr' implicitly has an 'any' type.
|
||||
function _doFill(arr, start, step, count) {
|
||||
for (let idx = 0, val = start; idx < count; idx += 1, val += step) {
|
||||
arr[idx] = val;
|
||||
@@ -29,10 +30,12 @@ function _doFill(arr, start, step, count) {
|
||||
return arr;
|
||||
}
|
||||
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'arr' implicitly has an 'any' type.
|
||||
export function rangeFill(arr, start = 0, step = 1) {
|
||||
return _doFill(arr, start, step, arr.length);
|
||||
}
|
||||
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'start' implicitly has an 'any' type.
|
||||
export function range(start, stop, step) {
|
||||
if (start === undefined) return [];
|
||||
if (stop === undefined) {
|
||||
@@ -44,7 +47,10 @@ export function range(start, stop, step) {
|
||||
return _doFill(new Array(len), start, step, len);
|
||||
}
|
||||
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'start' implicitly has an 'any' type.
|
||||
export function linspace(start, stop, nsteps) {
|
||||
// @ts-expect-error ts-migrate(2363) FIXME: The right-hand side of an arithmetic operation mus... Remove this comment to see the full error message
|
||||
const delta = (stop - start) / (nsteps - 1).toFixed();
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'i' implicitly has an 'any' type.
|
||||
return range(0, nsteps, 1).map((i) => start + i * delta);
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
export default function renderThrottle(callback) {
|
||||
export default function renderThrottle(callback: any) {
|
||||
/*
|
||||
This wraps a call to requestAnimationFrame(), enforcing a single
|
||||
render callback at any given time (ie, you can call this any number
|
||||
of times, and it will coallesce multiple inter-frame calls into a
|
||||
single render).
|
||||
*/
|
||||
let rafCurrentlyInProgress = null;
|
||||
return function f() {
|
||||
let rafCurrentlyInProgress: any = null;
|
||||
return function f(this: any) {
|
||||
if (rafCurrentlyInProgress) return;
|
||||
const context = this;
|
||||
rafCurrentlyInProgress = window.requestAnimationFrame(() => {
|
||||
@@ -6,15 +6,15 @@
|
||||
// myScale(0) === -1
|
||||
// this is is equivalent to d3.scaleLinear().domain([0,1]).range([-1,1])
|
||||
|
||||
export default (domain, range) => {
|
||||
export default (domain: any, range: any) => {
|
||||
const domainStart = domain[0];
|
||||
const scale = (range[1] - range[0]) / (domain[1] - domain[0]);
|
||||
const invScale = 1 / scale;
|
||||
const rangeStart = range[0];
|
||||
const f = (value) => (value - domainStart) * scale + rangeStart;
|
||||
const f = (value: any) => (value - domainStart) * scale + rangeStart;
|
||||
|
||||
// inverter
|
||||
f.invert = (value) => (value - rangeStart) * invScale + domainStart;
|
||||
f.invert = (value: any) => (value - rangeStart) * invScale + domainStart;
|
||||
|
||||
return f;
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
export default (input) => {
|
||||
export default (input: any) => {
|
||||
const outputMax = 1;
|
||||
const outputMin = 0;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
via https://github.com/nodef/extra-number/blob/master/scripts/significantDigits.js
|
||||
*/
|
||||
|
||||
export default (n) => {
|
||||
export default (n: any) => {
|
||||
return n
|
||||
.toExponential()
|
||||
.replace(/e[+\-0-9]*$/, "")
|
||||
+6
@@ -17,6 +17,7 @@ In addition, the current state management only allows for
|
||||
categorical annotations to be writable.
|
||||
*/
|
||||
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'schema' implicitly has an 'any' type.
|
||||
export function isCategoricalAnnotation(schema, name) {
|
||||
/*
|
||||
we treat any string, categorical or boolean as a categorical.
|
||||
@@ -28,6 +29,7 @@ export function isCategoricalAnnotation(schema, name) {
|
||||
return type === "string" || type === "boolean" || type === "categorical";
|
||||
}
|
||||
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'schema' implicitly has an 'any' type.
|
||||
export function isContinuousAnnotation(schema, name) {
|
||||
/*
|
||||
Return true/false/undefined
|
||||
@@ -38,14 +40,17 @@ export function isContinuousAnnotation(schema, name) {
|
||||
return !(type === "string" || type === "boolean" || type === "categorical");
|
||||
}
|
||||
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'schema' implicitly has an 'any' type.
|
||||
function _isUserAnnotation(schema, name) {
|
||||
return schema.annotations.obsByName[name]?.writable || false;
|
||||
}
|
||||
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'annoMatrix' implicitly has an 'any' typ... Remove this comment to see the full error message
|
||||
export function isUserAnnotation(annoMatrix, name) {
|
||||
return _isUserAnnotation(annoMatrix.schema, name);
|
||||
}
|
||||
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'df' implicitly has an 'any' type.
|
||||
export function allHaveLabelByMask(df, colName, label, mask) {
|
||||
// return true if all rows as indicated by mask have the colname set to label.
|
||||
// False if not.
|
||||
@@ -63,6 +68,7 @@ export function allHaveLabelByMask(df, colName, label, mask) {
|
||||
}
|
||||
|
||||
const legalCharacters = /^(\w|[ .()-])+$/;
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'name' implicitly has an 'any' type.
|
||||
export function annotationNameIsErroneous(name) {
|
||||
/*
|
||||
Validate the name - return:
|
||||
+34
-15
@@ -12,7 +12,12 @@ import { range } from "../range";
|
||||
given a color mode & accessor, generate an annoMatrix query that will
|
||||
fulfill it
|
||||
*/
|
||||
export function createColorQuery(colorMode, colorByAccessor, schema, genesets) {
|
||||
export function createColorQuery(
|
||||
colorMode: any,
|
||||
colorByAccessor: any,
|
||||
schema: any,
|
||||
genesets: any
|
||||
) {
|
||||
if (!colorMode || !colorByAccessor || !schema || !genesets) return null;
|
||||
|
||||
switch (colorMode) {
|
||||
@@ -61,7 +66,7 @@ export function createColorQuery(colorMode, colorByAccessor, schema, genesets) {
|
||||
}
|
||||
}
|
||||
|
||||
function _defaultColors(nObs) {
|
||||
function _defaultColors(nObs: any) {
|
||||
const defaultCellColor = parseRGB(globals.defaultCellColor);
|
||||
return {
|
||||
rgb: new Array(nObs).fill(defaultCellColor),
|
||||
@@ -84,15 +89,16 @@ Returns:
|
||||
}
|
||||
*/
|
||||
function _createColorTable(
|
||||
colorMode,
|
||||
colorByAccessor,
|
||||
colorByData,
|
||||
schema,
|
||||
colorMode: any,
|
||||
colorByAccessor: any,
|
||||
colorByData: any,
|
||||
schema: any,
|
||||
userColors = null
|
||||
) {
|
||||
switch (colorMode) {
|
||||
case "color by categorical metadata": {
|
||||
const data = colorByData.col(colorByAccessor).asArray();
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
if (userColors && colorByAccessor in userColors) {
|
||||
return createUserColors(data, colorByAccessor, schema, userColors);
|
||||
}
|
||||
@@ -126,25 +132,34 @@ export const createColorTable = memoize(_createColorTable);
|
||||
* - scale: function which given label returns d3 color scale for label
|
||||
* Order doesn't matter - everything is keyed by label value.
|
||||
*/
|
||||
export function loadUserColorConfig(userColors) {
|
||||
export function loadUserColorConfig(userColors: any) {
|
||||
const convertedUserColors = {};
|
||||
Object.keys(userColors).forEach((category) => {
|
||||
const [colors, scaleMap] = Object.keys(userColors[category]).reduce(
|
||||
(acc, label) => {
|
||||
const color = parseRGB(userColors[category][label]);
|
||||
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
|
||||
acc[0][label] = color;
|
||||
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
|
||||
acc[1][label] = d3.rgb(255 * color[0], 255 * color[1], 255 * color[2]);
|
||||
return acc;
|
||||
},
|
||||
[{}, {}]
|
||||
);
|
||||
const scale = (label) => scaleMap[label];
|
||||
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
|
||||
const scale = (label: any) => scaleMap[label];
|
||||
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
|
||||
convertedUserColors[category] = { colors, scale };
|
||||
});
|
||||
return convertedUserColors;
|
||||
}
|
||||
|
||||
function _createUserColors(data, colorAccessor, schema, userColors) {
|
||||
function _createUserColors(
|
||||
data: any,
|
||||
colorAccessor: any,
|
||||
schema: any,
|
||||
userColors: any
|
||||
) {
|
||||
const { colors, scale: scaleByLabel } = userColors[colorAccessor];
|
||||
const rgb = createRgbArray(data, colors);
|
||||
|
||||
@@ -152,14 +167,18 @@ function _createUserColors(data, colorAccessor, schema, userColors) {
|
||||
// See createColorsByCategoricalMetadata() for another example.
|
||||
const { categories } = schema.annotations.obsByName[colorAccessor];
|
||||
const categoryMap = new Map();
|
||||
categories.forEach((label, idx) => categoryMap.set(idx, label));
|
||||
const scale = (idx) => scaleByLabel(categoryMap.get(idx));
|
||||
categories.forEach((label: any, idx: any) => categoryMap.set(idx, label));
|
||||
const scale = (idx: any) => scaleByLabel(categoryMap.get(idx));
|
||||
|
||||
return { rgb, scale };
|
||||
}
|
||||
const createUserColors = memoize(_createUserColors);
|
||||
|
||||
function _createColorsByCategoricalMetadata(data, colorAccessor, schema) {
|
||||
function _createColorsByCategoricalMetadata(
|
||||
data: any,
|
||||
colorAccessor: any,
|
||||
schema: any
|
||||
) {
|
||||
const { categories } = schema.annotations.obsByName[colorAccessor];
|
||||
|
||||
const scale = d3
|
||||
@@ -167,7 +186,7 @@ function _createColorsByCategoricalMetadata(data, colorAccessor, schema) {
|
||||
.domain([0, categories.length]);
|
||||
|
||||
/* pre-create colors - much faster than doing it for each obs */
|
||||
const colors = categories.reduce((acc, cat, idx) => {
|
||||
const colors = categories.reduce((acc: any, cat: any, idx: any) => {
|
||||
acc[cat] = parseRGB(scale(idx));
|
||||
return acc;
|
||||
}, {});
|
||||
@@ -179,7 +198,7 @@ const createColorsByCategoricalMetadata = memoize(
|
||||
_createColorsByCategoricalMetadata
|
||||
);
|
||||
|
||||
function createRgbArray(data, colors) {
|
||||
function createRgbArray(data: any, colors: any) {
|
||||
const rgb = new Array(data.length);
|
||||
for (let i = 0, len = data.length; i < len; i += 1) {
|
||||
const label = data[i];
|
||||
@@ -188,7 +207,7 @@ function createRgbArray(data, colors) {
|
||||
return rgb;
|
||||
}
|
||||
|
||||
function _createColorsByContinuousMetadata(data, min, max) {
|
||||
function _createColorsByContinuousMetadata(data: any, min: any, max: any) {
|
||||
const colorBins = 100;
|
||||
const scale = d3
|
||||
.scaleQuantile()
|
||||
+14
-12
@@ -35,11 +35,11 @@ Remember that option values can be ANY js type, except undefined/null.
|
||||
}
|
||||
}
|
||||
*/
|
||||
function topNCategories(colSchema, summary, N) {
|
||||
function topNCategories(colSchema: any, summary: any, N: any) {
|
||||
/* return top N categories by occurrences in the data */
|
||||
const { categories: allCategories } = colSchema;
|
||||
const counts = allCategories.map(
|
||||
(cat) => summary.categoryCounts.get(cat) ?? 0
|
||||
(cat: any) => summary.categoryCounts.get(cat) ?? 0
|
||||
);
|
||||
|
||||
if (allCategories.length <= N) {
|
||||
@@ -47,7 +47,7 @@ function topNCategories(colSchema, summary, N) {
|
||||
}
|
||||
|
||||
const sortIndex = fillRange(new Array(allCategories.length)).sort(
|
||||
(a, b) => counts[b] - counts[a]
|
||||
(a: any, b: any) => counts[b] - counts[a]
|
||||
);
|
||||
const topNindices = new Set(sortIndex.slice(0, N));
|
||||
|
||||
@@ -62,7 +62,7 @@ function topNCategories(colSchema, summary, N) {
|
||||
return [allCategories, _topNCategories, topNCounts];
|
||||
}
|
||||
|
||||
export function isSelectableCategoryName(schema, name) {
|
||||
export function isSelectableCategoryName(schema: any, name: any) {
|
||||
const { index } = schema.annotations.obs;
|
||||
const colSchema = schema.annotations.obsByName[name];
|
||||
return (
|
||||
@@ -72,7 +72,7 @@ export function isSelectableCategoryName(schema, name) {
|
||||
);
|
||||
}
|
||||
|
||||
export function selectableCategoryNames(schema, names) {
|
||||
export function selectableCategoryNames(schema: any, names: any) {
|
||||
/*
|
||||
return all obs annotation names that are categorical AND have a
|
||||
"reasonably" small number of categories AND are not the index column.
|
||||
@@ -80,11 +80,11 @@ export function selectableCategoryNames(schema, names) {
|
||||
If the initial name list not provided, use everything in the schema.
|
||||
*/
|
||||
if (!schema) return [];
|
||||
if (!names) names = schema.annotations.obs.columns.map((c) => c.name);
|
||||
return names.filter((name) => isSelectableCategoryName(schema, name));
|
||||
if (!names) names = schema.annotations.obs.columns.map((c: any) => c.name);
|
||||
return names.filter((name: any) => isSelectableCategoryName(schema, name));
|
||||
}
|
||||
|
||||
export function createCategorySummaryFromDfCol(dfCol, colSchema) {
|
||||
export function createCategorySummaryFromDfCol(dfCol: any, colSchema: any) {
|
||||
const N = globals.maxCategoricalOptionsToDisplay;
|
||||
const { writable: isUserAnno } = colSchema;
|
||||
|
||||
@@ -99,7 +99,9 @@ export function createCategorySummaryFromDfCol(dfCol, colSchema) {
|
||||
categoryValues,
|
||||
categoryValueCounts,
|
||||
] = topNCategories(colSchema, summary, N);
|
||||
const categoryValueIndices = new Map(categoryValues.map((v, i) => [v, i]));
|
||||
const categoryValueIndices = new Map(
|
||||
categoryValues.map((v: any, i: any) => [v, i])
|
||||
);
|
||||
const numCategoryValues = categoryValueIndices.size;
|
||||
const isTruncated = categoryValues.length < summary.numCategories;
|
||||
|
||||
@@ -114,11 +116,11 @@ export function createCategorySummaryFromDfCol(dfCol, colSchema) {
|
||||
};
|
||||
}
|
||||
|
||||
export function createCategoricalSelection(names) {
|
||||
return fromEntries(names.map((name) => [name, new Map()]));
|
||||
export function createCategoricalSelection(names: any) {
|
||||
return fromEntries(names.map((name: any) => [name, new Map()]));
|
||||
}
|
||||
|
||||
export function pruneVarDataCache(varData, needed) {
|
||||
export function pruneVarDataCache(varData: any, needed: any) {
|
||||
/*
|
||||
Remove any unneeded columns from the varData dataframe. Will only
|
||||
prune / remove if the total column count exceeds VarDataCacheLowWatermark
|
||||
@@ -17,7 +17,7 @@ Matrix flatbuffer decoding support. See fbs/matrix.fbs
|
||||
/*
|
||||
Decode NetEncoding.TypedArray
|
||||
*/
|
||||
function decodeTypedArray(uType, uValF, inplace = false) {
|
||||
function decodeTypedArray(uType: any, uValF: any, inplace = false) {
|
||||
if (uType === NetEncoding.TypedArray.NONE) {
|
||||
return null;
|
||||
}
|
||||
@@ -48,7 +48,7 @@ Returns: object containing decoded Matrix:
|
||||
colIdx: []|null
|
||||
}
|
||||
*/
|
||||
export function decodeMatrixFBS(arrayBuffer, inplace = false) {
|
||||
export function decodeMatrixFBS(arrayBuffer: any, inplace = false) {
|
||||
const bb = new flatbuffers.ByteBuffer(new Uint8Array(arrayBuffer));
|
||||
const matrix = NetEncoding.Matrix.getRootAsMatrix(bb);
|
||||
|
||||
@@ -79,7 +79,7 @@ export function decodeMatrixFBS(arrayBuffer, inplace = false) {
|
||||
};
|
||||
}
|
||||
|
||||
function encodeTypedArray(builder, uType, uData) {
|
||||
function encodeTypedArray(builder: any, uType: any, uData: any) {
|
||||
const uTypeName = NetEncoding.TypedArray[uType];
|
||||
const ArrayType = NetEncoding[uTypeName];
|
||||
const dv = ArrayType.createDataVector(builder, uData);
|
||||
@@ -88,7 +88,7 @@ function encodeTypedArray(builder, uType, uData) {
|
||||
return builder.endObject();
|
||||
}
|
||||
|
||||
export function encodeMatrixFBS(df) {
|
||||
export function encodeMatrixFBS(df: any) {
|
||||
/*
|
||||
encode the dataframe as an FBS Matrix
|
||||
*/
|
||||
@@ -99,6 +99,7 @@ export function encodeMatrixFBS(df) {
|
||||
}
|
||||
|
||||
const shape = df.dims;
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 0 arguments, but got 1.
|
||||
const utf8Encoder = new TextEncoder("utf-8");
|
||||
const builder = new flatbuffers.Builder(1024);
|
||||
|
||||
@@ -107,9 +108,9 @@ export function encodeMatrixFBS(df) {
|
||||
let encColumns;
|
||||
|
||||
if (shape[0] > 0 && shape[1] > 0) {
|
||||
const columns = df.columns().map((col) => col.asArray());
|
||||
const columns = df.columns().map((col: any) => col.asArray());
|
||||
|
||||
const cols = columns.map((carr) => {
|
||||
const cols = columns.map((carr: any) => {
|
||||
let uType;
|
||||
let tarr;
|
||||
if (isTypedArray(carr)) {
|
||||
@@ -168,7 +169,7 @@ export function encodeMatrixFBS(df) {
|
||||
return builder.asUint8Array();
|
||||
}
|
||||
|
||||
function promoteTypedArray(o) {
|
||||
function promoteTypedArray(o: any) {
|
||||
/*
|
||||
Decide what internal data type to use for the data returned from
|
||||
the server.
|
||||
@@ -200,7 +201,7 @@ function promoteTypedArray(o) {
|
||||
return new TypedArrayCtor(o);
|
||||
}
|
||||
|
||||
export function matrixFBSToDataframe(arrayBuffers) {
|
||||
export function matrixFBSToDataframe(arrayBuffers: any) {
|
||||
/*
|
||||
Convert array of Matrix FBS to a Dataframe.
|
||||
|
||||
@@ -216,19 +217,19 @@ export function matrixFBSToDataframe(arrayBuffers) {
|
||||
arrayBuffers = [arrayBuffers];
|
||||
}
|
||||
if (arrayBuffers.length === 0) {
|
||||
return Dataframe.Dataframe.empty();
|
||||
return (Dataframe as any).Dataframe.empty();
|
||||
}
|
||||
|
||||
const fbs = arrayBuffers.map((ab) => decodeMatrixFBS(ab, true)); // leave in place
|
||||
const fbs = arrayBuffers.map((ab: any) => decodeMatrixFBS(ab, true)); // leave in place
|
||||
/* check that all FBS have same row dimensionality */
|
||||
const { nRows } = fbs[0];
|
||||
fbs.forEach((b) => {
|
||||
fbs.forEach((b: any) => {
|
||||
if (b.nRows !== nRows)
|
||||
throw new Error("FBS with inconsistent dimensionality");
|
||||
});
|
||||
const columns = fbs
|
||||
.map((fb) =>
|
||||
fb.columns.map((c) => {
|
||||
.map((fb: any) =>
|
||||
fb.columns.map((c: any) => {
|
||||
if (isFpTypedArray(c) || Array.isArray(c)) return c;
|
||||
return promoteTypedArray(c);
|
||||
})
|
||||
@@ -236,10 +237,13 @@ export function matrixFBSToDataframe(arrayBuffers) {
|
||||
.flat();
|
||||
// colIdx may be TypedArray or Array
|
||||
const colIdx = fbs
|
||||
.map((b) => (Array.isArray(b.colIdx) ? b.colIdx : Array.from(b.colIdx)))
|
||||
.map((b: any) =>
|
||||
Array.isArray(b.colIdx) ? b.colIdx : Array.from(b.colIdx)
|
||||
)
|
||||
.flat();
|
||||
const nCols = columns.length;
|
||||
|
||||
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'KeyIndex' is not assignable to p... Remove this comment to see the full error message
|
||||
const df = new Dataframe([nRows, nCols], columns, null, new KeyIndex(colIdx));
|
||||
return df;
|
||||
}
|
||||
+20
-19
@@ -15,25 +15,25 @@ System wide schema assumptions:
|
||||
- schema will be internally self-consistent (eg, index matches columns)
|
||||
*/
|
||||
|
||||
export function indexEntireSchema(schema) {
|
||||
export function indexEntireSchema(schema: any) {
|
||||
/* Index schema for ease of use */
|
||||
schema.annotations.obsByName = fromEntries(
|
||||
schema.annotations?.obs?.columns?.map((v) => [v.name, v]) ?? []
|
||||
schema.annotations?.obs?.columns?.map((v: any) => [v.name, v]) ?? []
|
||||
);
|
||||
schema.annotations.varByName = fromEntries(
|
||||
schema.annotations?.var?.columns?.map((v) => [v.name, v]) ?? []
|
||||
schema.annotations?.var?.columns?.map((v: any) => [v.name, v]) ?? []
|
||||
);
|
||||
schema.layout.obsByName = fromEntries(
|
||||
schema.layout?.obs?.map((v) => [v.name, v]) ?? []
|
||||
schema.layout?.obs?.map((v: any) => [v.name, v]) ?? []
|
||||
);
|
||||
schema.layout.varByName = fromEntries(
|
||||
schema.layout?.var?.map((v) => [v.name, v]) ?? []
|
||||
schema.layout?.var?.map((v: any) => [v.name, v]) ?? []
|
||||
);
|
||||
|
||||
return schema;
|
||||
}
|
||||
|
||||
function _copyObsAnno(schema) {
|
||||
function _copyObsAnno(schema: any) {
|
||||
/* redux copy conventions - WARNING, only for modifying obs annotations */
|
||||
return {
|
||||
...schema,
|
||||
@@ -44,7 +44,7 @@ function _copyObsAnno(schema) {
|
||||
};
|
||||
}
|
||||
|
||||
function _copyObsLayout(schema) {
|
||||
function _copyObsLayout(schema: any) {
|
||||
return {
|
||||
...schema,
|
||||
layout: {
|
||||
@@ -54,36 +54,37 @@ function _copyObsLayout(schema) {
|
||||
};
|
||||
}
|
||||
|
||||
function _reindexObsAnno(schema) {
|
||||
function _reindexObsAnno(schema: any) {
|
||||
/* reindex obs annotations ONLY */
|
||||
schema.annotations.obsByName = fromEntries(
|
||||
schema.annotations.obs.columns.map((v) => [v.name, v])
|
||||
schema.annotations.obs.columns.map((v: any) => [v.name, v])
|
||||
);
|
||||
return schema;
|
||||
}
|
||||
|
||||
function _reindexObsLayout(schema) {
|
||||
function _reindexObsLayout(schema: any) {
|
||||
schema.layout.obsByName = fromEntries(
|
||||
schema.layout.obs.map((v) => [v.name, v])
|
||||
schema.layout.obs.map((v: any) => [v.name, v])
|
||||
);
|
||||
return schema;
|
||||
}
|
||||
|
||||
export function removeObsAnnoColumn(schema, name) {
|
||||
export function removeObsAnnoColumn(schema: any, name: any) {
|
||||
const newSchema = _copyObsAnno(schema);
|
||||
newSchema.annotations.obs.columns = schema.annotations.obs.columns.filter(
|
||||
(v) => v.name !== name
|
||||
(v: any) => v.name !== name
|
||||
);
|
||||
return _reindexObsAnno(newSchema);
|
||||
}
|
||||
|
||||
export function addObsAnnoColumn(schema, name, defn) {
|
||||
// @ts-expect-error ts-migrate(6133) FIXME: 'name' is declared but its value is never read.
|
||||
export function addObsAnnoColumn(schema: any, name: any, defn: any) {
|
||||
const newSchema = _copyObsAnno(schema);
|
||||
newSchema.annotations.obs.columns.push(defn);
|
||||
return _reindexObsAnno(newSchema);
|
||||
}
|
||||
|
||||
export function removeObsAnnoCategory(schema, name, category) {
|
||||
export function removeObsAnnoCategory(schema: any, name: any, category: any) {
|
||||
/* remove a category from a categorical annotation */
|
||||
const categories = schema.annotations.obsByName[name]?.categories;
|
||||
if (!categories)
|
||||
@@ -99,7 +100,7 @@ export function removeObsAnnoCategory(schema, name, category) {
|
||||
return newSchema;
|
||||
}
|
||||
|
||||
export function addObsAnnoCategory(schema, name, category) {
|
||||
export function addObsAnnoCategory(schema: any, name: any, category: any) {
|
||||
/* add a category to a categorical annotation */
|
||||
const categories = schema.annotations.obsByName[name]?.categories;
|
||||
if (!categories)
|
||||
@@ -119,16 +120,16 @@ export function addObsAnnoCategory(schema, name, category) {
|
||||
return newSchema;
|
||||
}
|
||||
|
||||
export function addObsLayout(schema, layout) {
|
||||
export function addObsLayout(schema: any, layout: any) {
|
||||
/* add or replace a layout */
|
||||
const newSchema = _copyObsLayout(schema);
|
||||
newSchema.layout.obs.push(layout);
|
||||
return _reindexObsLayout(newSchema);
|
||||
}
|
||||
|
||||
export function removeObsLayout(schema, name) {
|
||||
export function removeObsLayout(schema: any, name: any) {
|
||||
/* remove a layout */
|
||||
const newSchema = _copyObsLayout(schema);
|
||||
newSchema.layout.obs = schema.layout.obs.filter((v) => v.name !== name);
|
||||
newSchema.layout.obs = schema.layout.obs.filter((v: any) => v.name !== name);
|
||||
return _reindexObsLayout(newSchema);
|
||||
}
|
||||
+11
@@ -38,6 +38,7 @@ Views can be interogated for their type with the following:
|
||||
import { clip, isubsetMask, isubset } from "../../annoMatrix";
|
||||
import { memoize } from "../dataframe/util";
|
||||
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'annoMatrix' implicitly has an 'any' typ... Remove this comment to see the full error message
|
||||
export function _clipAnnoMatrix(annoMatrix, min, max) {
|
||||
/*
|
||||
clip the annoMatrix.
|
||||
@@ -47,6 +48,7 @@ export function _clipAnnoMatrix(annoMatrix, min, max) {
|
||||
: clip(annoMatrix, min, max);
|
||||
}
|
||||
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'annoMatrix' implicitly has an 'any' typ... Remove this comment to see the full error message
|
||||
export function _userSubsetAnnoMatrix(annoMatrix, mask) {
|
||||
/*
|
||||
user-requested row subset of annoMatrix, to be added on top of any
|
||||
@@ -61,12 +63,14 @@ export function _userSubsetAnnoMatrix(annoMatrix, mask) {
|
||||
annoMatrix.userFlags.isUserSubsetView = true;
|
||||
|
||||
if (clipRange) {
|
||||
// @ts-expect-error ts-migrate(2556) FIXME: Expected 3 arguments, but got 1 or more.
|
||||
annoMatrix = clip(annoMatrix, ...clipRange);
|
||||
}
|
||||
|
||||
return annoMatrix;
|
||||
}
|
||||
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'annoMatrix' implicitly has an 'any' typ... Remove this comment to see the full error message
|
||||
export function _userResetSubsetAnnoMatrix(annoMatrix) {
|
||||
/*
|
||||
Reset/remove all user-requested subsets. Do not remove clip or embedding subset.
|
||||
@@ -85,12 +89,14 @@ export function _userResetSubsetAnnoMatrix(annoMatrix) {
|
||||
|
||||
/* re-apply the clip, if any */
|
||||
if (clipRange) {
|
||||
// @ts-expect-error ts-migrate(2556) FIXME: Expected 3 arguments, but got 1 or more.
|
||||
annoMatrix = clip(annoMatrix, ...clipRange);
|
||||
}
|
||||
|
||||
return annoMatrix;
|
||||
}
|
||||
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'annoMatrix' implicitly has an 'any' typ... Remove this comment to see the full error message
|
||||
export function _setEmbeddingSubset(annoMatrix, embeddingDf) {
|
||||
/*
|
||||
Set the embedding subset view. Only create a subset view for the embedding
|
||||
@@ -124,12 +130,14 @@ export function _setEmbeddingSubset(annoMatrix, embeddingDf) {
|
||||
|
||||
/* re-apply clip, if needed */
|
||||
if (clipRange) {
|
||||
// @ts-expect-error ts-migrate(2556) FIXME: Expected 3 arguments, but got 1 or more.
|
||||
annoMatrix = clip(annoMatrix, ...clipRange);
|
||||
}
|
||||
|
||||
return annoMatrix;
|
||||
}
|
||||
|
||||
// @ts-expect-error ts-migrate(6133) FIXME: 'baseRowIndex' is declared but its value is never ... Remove this comment to see the full error message
|
||||
function _getEmbeddingRowOffsets(baseRowIndex, embeddingDf) {
|
||||
/*
|
||||
given a dataframe containing an embedding:
|
||||
@@ -155,6 +163,7 @@ function _getEmbeddingRowOffsets(baseRowIndex, embeddingDf) {
|
||||
return offsets.subarray(0, numOffsets);
|
||||
}
|
||||
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'embeddingDf' implicitly has an 'any' ty... Remove this comment to see the full error message
|
||||
export function _getDiscreteCellEmbeddingRowIndex(embeddingDf) {
|
||||
const idx = _getEmbeddingRowOffsets(embeddingDf.rowIndex, embeddingDf);
|
||||
if (idx === null) return embeddingDf.rowIndex;
|
||||
@@ -162,9 +171,11 @@ export function _getDiscreteCellEmbeddingRowIndex(embeddingDf) {
|
||||
}
|
||||
export const getDiscreteCellEmbeddingRowIndex = memoize(
|
||||
_getDiscreteCellEmbeddingRowIndex,
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'df' implicitly has an 'any' type.
|
||||
(df) => df.__id
|
||||
);
|
||||
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'annoMatrix' implicitly has an 'any' typ... Remove this comment to see the full error message
|
||||
export function getEmbSubsetView(annoMatrix) {
|
||||
/* if there is an embedding subset in the view stack, return it. Falsish if not. */
|
||||
while (annoMatrix.isView) {
|
||||
@@ -43,13 +43,23 @@ Example:
|
||||
|
||||
*/
|
||||
export default class StateMachine {
|
||||
constructor(initState, transitions, onError) {
|
||||
events: any;
|
||||
|
||||
graph: any;
|
||||
|
||||
onError: any;
|
||||
|
||||
state: any;
|
||||
|
||||
states: any;
|
||||
|
||||
constructor(initState: any, transitions: any, onError: any) {
|
||||
this.onError = onError || (() => undefined);
|
||||
this.state = initState;
|
||||
|
||||
// all states
|
||||
this.states = new Set(
|
||||
transitions.reduce((names, tsn) => {
|
||||
transitions.reduce((names: any, tsn: any) => {
|
||||
names.push(tsn.from);
|
||||
names.push(tsn.to);
|
||||
return names;
|
||||
@@ -57,11 +67,11 @@ export default class StateMachine {
|
||||
);
|
||||
|
||||
// all transition names (aka events)
|
||||
this.events = new Set(transitions.map((tsn) => tsn.event));
|
||||
this.events = new Set(transitions.map((tsn: any) => tsn.event));
|
||||
|
||||
// the transition graph.
|
||||
// graph[event][from] -> transition
|
||||
this.graph = transitions.reduce((graph, tsn) => {
|
||||
this.graph = transitions.reduce((graph: any, tsn: any) => {
|
||||
const { event, from } = tsn;
|
||||
if (!graph.has(event)) graph.set(event, new Map());
|
||||
const tsnMap = graph.get(event);
|
||||
@@ -70,7 +80,8 @@ export default class StateMachine {
|
||||
}, new Map());
|
||||
}
|
||||
|
||||
clone(initState) {
|
||||
clone(initState: any) {
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 3 arguments, but got 2.
|
||||
const fsm = new StateMachine(initState, []);
|
||||
fsm.onError = this.onError;
|
||||
fsm.states = this.states;
|
||||
@@ -79,7 +90,7 @@ export default class StateMachine {
|
||||
return fsm;
|
||||
}
|
||||
|
||||
next(event, data) {
|
||||
next(event: any, data: any) {
|
||||
const { graph, state } = this;
|
||||
const tsnMap = graph.get(event);
|
||||
if (!tsnMap) return this.onError(this, event, state, undefined);
|
||||
@@ -5,7 +5,7 @@ Various type and schema related helper functions.
|
||||
/*
|
||||
Utility function to test for a typed array
|
||||
*/
|
||||
export function isTypedArray(x) {
|
||||
export function isTypedArray(x: any) {
|
||||
return (
|
||||
ArrayBuffer.isView(x) &&
|
||||
Object.prototype.toString.call(x) !== "[object DataView]"
|
||||
@@ -15,7 +15,7 @@ export function isTypedArray(x) {
|
||||
/*
|
||||
Test for float typed array, ie, Float32TypedArray or Float64TypedArray
|
||||
*/
|
||||
export function isFpTypedArray(x) {
|
||||
export function isFpTypedArray(x: any) {
|
||||
let constructor;
|
||||
const isFloatArray =
|
||||
x &&
|
||||
@@ -24,6 +24,6 @@ export function isFpTypedArray(x) {
|
||||
return isFloatArray;
|
||||
}
|
||||
|
||||
export function isArrayOrTypedArray(x) {
|
||||
export function isArrayOrTypedArray(x: any) {
|
||||
return Array.isArray(x) || isTypedArray(x);
|
||||
}
|
||||
+24
-14
@@ -17,7 +17,17 @@
|
||||
// The underlying data structure uses TypedArrays for performance.
|
||||
//
|
||||
class BitArray {
|
||||
constructor(length) {
|
||||
bitarray: any;
|
||||
|
||||
bitmask: any;
|
||||
|
||||
dimensionCount: any;
|
||||
|
||||
length: any;
|
||||
|
||||
width: any;
|
||||
|
||||
constructor(length: any) {
|
||||
// Initially allocate a 32 bit wide array. allocDimension() will expand
|
||||
// as necessary.
|
||||
//
|
||||
@@ -76,7 +86,7 @@ class BitArray {
|
||||
|
||||
// count trailing zeros - hard to do fast in JS!
|
||||
// https://en.wikipedia.org/wiki/Find_first_set#CTZ
|
||||
static ctz(av) {
|
||||
static ctz(av: any) {
|
||||
let c = 32;
|
||||
let v = av;
|
||||
v &= -v; // isolate lowest non-zero bit
|
||||
@@ -130,7 +140,7 @@ class BitArray {
|
||||
// free a dimension for later use. MUST deselect the dimension, as other
|
||||
// code assume the column will be zero valued.
|
||||
//
|
||||
freeDimension(dim) {
|
||||
freeDimension(dim: any) {
|
||||
// all selection tests assume unallocated dimensions are zero valued.
|
||||
this.deselectAll(dim);
|
||||
const col = dim >>> 5;
|
||||
@@ -140,7 +150,7 @@ class BitArray {
|
||||
|
||||
// return true if this index is selected in ALL dimensions.
|
||||
//
|
||||
isSelected(index) {
|
||||
isSelected(index: any) {
|
||||
const { width, length, bitarray } = this;
|
||||
|
||||
for (let w = 0; w < width; w += 1) {
|
||||
@@ -152,7 +162,7 @@ class BitArray {
|
||||
|
||||
// return true if this index is selected in ALL dimensions IGNORING dim
|
||||
//
|
||||
isSelectedIgnoringDim(index, dim) {
|
||||
isSelectedIgnoringDim(index: any, dim: any) {
|
||||
const ignoreOffset = dim >>> 5;
|
||||
const ignoreMask = ~(1 << dim % 32);
|
||||
|
||||
@@ -176,7 +186,7 @@ class BitArray {
|
||||
|
||||
// select index on dimension
|
||||
//
|
||||
selectOne(dim, index) {
|
||||
selectOne(dim: any, index: any) {
|
||||
const col = dim >>> 5;
|
||||
const before = this.bitarray[col * this.length + index];
|
||||
const after = before | (1 << dim % 32);
|
||||
@@ -185,7 +195,7 @@ class BitArray {
|
||||
|
||||
// deselect index on dimension
|
||||
//
|
||||
deselectOne(dim, index) {
|
||||
deselectOne(dim: any, index: any) {
|
||||
const col = dim >>> 5;
|
||||
const before = this.bitarray[col * this.length + index];
|
||||
const after = before & ~(1 << dim % 32);
|
||||
@@ -194,7 +204,7 @@ class BitArray {
|
||||
|
||||
// select all indices on dimension.
|
||||
//
|
||||
selectAll(dim) {
|
||||
selectAll(dim: any) {
|
||||
const col = dim >> 5;
|
||||
const one = 1 << dim % 32;
|
||||
for (let i = col * this.length, len = i + this.length; i < len; i += 1) {
|
||||
@@ -204,7 +214,7 @@ class BitArray {
|
||||
|
||||
// deselect all indices on dimension
|
||||
//
|
||||
deselectAll(dim) {
|
||||
deselectAll(dim: any) {
|
||||
const col = dim >> 5;
|
||||
const zero = ~(1 << dim % 32);
|
||||
for (let i = col * this.length, len = i + this.length; i < len; i += 1) {
|
||||
@@ -214,7 +224,7 @@ class BitArray {
|
||||
|
||||
// select range of indices on a dimension
|
||||
//
|
||||
selectFromRange(dim, range) {
|
||||
selectFromRange(dim: any, range: any) {
|
||||
const col = dim >>> 5;
|
||||
const first = range[0];
|
||||
const last = range[1];
|
||||
@@ -228,7 +238,7 @@ class BitArray {
|
||||
// select range of indices on a dimension, indirect through a sort map.
|
||||
// Indirect functions are used to map between sort and natural order.
|
||||
//
|
||||
selectIndirectFromRange(dim, indirect, range) {
|
||||
selectIndirectFromRange(dim: any, indirect: any, range: any) {
|
||||
const col = dim >>> 5;
|
||||
const first = range[0];
|
||||
const last = range[1];
|
||||
@@ -241,7 +251,7 @@ class BitArray {
|
||||
|
||||
// deselect range of indices on a dimension
|
||||
//
|
||||
deselectFromRange(dim, range) {
|
||||
deselectFromRange(dim: any, range: any) {
|
||||
const col = dim >>> 5;
|
||||
const first = range[0];
|
||||
const last = range[1];
|
||||
@@ -254,7 +264,7 @@ class BitArray {
|
||||
|
||||
// deselect range of indices on a dimension, indirect through a sort map.
|
||||
//
|
||||
deselectIndirectFromRange(dim, indirect, range) {
|
||||
deselectIndirectFromRange(dim: any, indirect: any, range: any) {
|
||||
const col = dim >>> 5;
|
||||
const first = range[0];
|
||||
const last = range[1];
|
||||
@@ -268,7 +278,7 @@ class BitArray {
|
||||
// Fill the array with selected|deselected value based upon the
|
||||
// current selection state.
|
||||
//
|
||||
fillBySelection(result, selectedValue, deselectedValue) {
|
||||
fillBySelection(result: any, selectedValue: any, deselectedValue: any) {
|
||||
// special case (width === 1) for performance
|
||||
if (this.width === 1) {
|
||||
const { bitmask, bitarray } = this;
|
||||
+65
-36
@@ -11,7 +11,7 @@ import {
|
||||
import { makeSortIndex } from "./util";
|
||||
|
||||
class NotImplementedError extends Error {
|
||||
constructor(...params) {
|
||||
constructor(...params: any[]) {
|
||||
super(...params);
|
||||
|
||||
// Maintains proper stack trace for where our error was thrown (only available on V8)
|
||||
@@ -22,7 +22,13 @@ class NotImplementedError extends Error {
|
||||
}
|
||||
|
||||
export default class ImmutableTypedCrossfilter {
|
||||
constructor(data, dimensions = {}, selectionCache = {}) {
|
||||
data: any;
|
||||
|
||||
dimensions: any;
|
||||
|
||||
selectionCache: any;
|
||||
|
||||
constructor(data: any, dimensions = {}, selectionCache = {}) {
|
||||
/*
|
||||
Typically, parameter 'data' is one of:
|
||||
- Array of objects/records
|
||||
@@ -59,7 +65,7 @@ export default class ImmutableTypedCrossfilter {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
setData(data) {
|
||||
setData(data: any) {
|
||||
if (this.data === data) return this;
|
||||
// please leave, WIP
|
||||
// console.log("...crossfilter set data, will drop cache");
|
||||
@@ -71,11 +77,11 @@ export default class ImmutableTypedCrossfilter {
|
||||
return Object.keys(this.dimensions);
|
||||
}
|
||||
|
||||
hasDimension(name) {
|
||||
hasDimension(name: any) {
|
||||
return !!this.dimensions[name];
|
||||
}
|
||||
|
||||
addDimension(name, type, ...rest) {
|
||||
addDimension(name: any, type: any, ...rest: any[]) {
|
||||
/*
|
||||
Add a new dimension to this crossfilter, of type DimensionType.
|
||||
Remainder of parameters are dimension-type-specific.
|
||||
@@ -94,6 +100,7 @@ export default class ImmutableTypedCrossfilter {
|
||||
id = bitArray.allocDimension();
|
||||
bitArray.selectAll(id);
|
||||
}
|
||||
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
|
||||
const DimensionType = DimTypes[type];
|
||||
const dim = new DimensionType(name, data, ...rest);
|
||||
Object.freeze(dim);
|
||||
@@ -112,7 +119,7 @@ export default class ImmutableTypedCrossfilter {
|
||||
});
|
||||
}
|
||||
|
||||
delDimension(name) {
|
||||
delDimension(name: any) {
|
||||
const { data } = this;
|
||||
const { bitArray } = this.selectionCache;
|
||||
const dimensions = { ...this.dimensions };
|
||||
@@ -132,7 +139,7 @@ export default class ImmutableTypedCrossfilter {
|
||||
});
|
||||
}
|
||||
|
||||
renameDimension(oldName, newName) {
|
||||
renameDimension(oldName: any, newName: any) {
|
||||
const { [oldName]: dim, ...dimensions } = this.dimensions;
|
||||
const { data, selectionCache } = this;
|
||||
const newDimensions = {
|
||||
@@ -146,7 +153,7 @@ export default class ImmutableTypedCrossfilter {
|
||||
return new ImmutableTypedCrossfilter(data, newDimensions, selectionCache);
|
||||
}
|
||||
|
||||
select(name, spec) {
|
||||
select(name: any, spec: any) {
|
||||
/*
|
||||
select on named dimension, as indicated by `spec`. Spec is an object
|
||||
specifying the selection, and must contain at least a `mode` field.
|
||||
@@ -174,7 +181,12 @@ export default class ImmutableTypedCrossfilter {
|
||||
return new ImmutableTypedCrossfilter(data, dimensions, newSelectionCache);
|
||||
}
|
||||
|
||||
static _dimSelnHasUpdated(selectionCache, id, newSeln, oldSeln) {
|
||||
static _dimSelnHasUpdated(
|
||||
selectionCache: any,
|
||||
id: any,
|
||||
newSeln: any,
|
||||
oldSeln: any
|
||||
) {
|
||||
/*
|
||||
Selection has updated from oldSeln to newSeln. Update the
|
||||
bit array if it exists. If not, we will lazy create it when
|
||||
@@ -208,19 +220,19 @@ export default class ImmutableTypedCrossfilter {
|
||||
If sort index exists in the dimension, assume sort ordered ranges.
|
||||
*/
|
||||
if (oldSeln.index) {
|
||||
dels.forEach((interval) =>
|
||||
dels.forEach((interval: any) =>
|
||||
bitArray.deselectIndirectFromRange(id, oldSeln.index, interval)
|
||||
);
|
||||
} else {
|
||||
dels.forEach((interval) => bitArray.deselectFromRange(id, interval));
|
||||
dels.forEach((interval: any) => bitArray.deselectFromRange(id, interval));
|
||||
}
|
||||
|
||||
if (newSeln.index) {
|
||||
adds.forEach((interval) =>
|
||||
adds.forEach((interval: any) =>
|
||||
bitArray.selectIndirectFromRange(id, newSeln.index, interval)
|
||||
);
|
||||
} else {
|
||||
adds.forEach((interval) => bitArray.selectFromRange(id, interval));
|
||||
adds.forEach((interval: any) => bitArray.selectFromRange(id, interval));
|
||||
}
|
||||
|
||||
return { bitArray };
|
||||
@@ -237,7 +249,7 @@ export default class ImmutableTypedCrossfilter {
|
||||
const id = bitArray.allocDimension();
|
||||
this.dimensions[name].id = id;
|
||||
const { ranges, index } = selection;
|
||||
ranges.forEach((range) => {
|
||||
ranges.forEach((range: any) => {
|
||||
if (index) {
|
||||
bitArray.selectIndirectFromRange(id, index, range);
|
||||
} else {
|
||||
@@ -312,7 +324,7 @@ export default class ImmutableTypedCrossfilter {
|
||||
return countSelected;
|
||||
}
|
||||
|
||||
isElementSelected(i) {
|
||||
isElementSelected(i: any) {
|
||||
/*
|
||||
return truthy/falsey if this record is selected on all dimensions
|
||||
*/
|
||||
@@ -320,7 +332,7 @@ export default class ImmutableTypedCrossfilter {
|
||||
return selectionCache.bitArray.isSelected(i);
|
||||
}
|
||||
|
||||
fillByIsSelected(array, selectedValue, deselectedValue) {
|
||||
fillByIsSelected(array: any, selectedValue: any, deselectedValue: any) {
|
||||
/*
|
||||
fill array with one of two values, based upon selection state.
|
||||
*/
|
||||
@@ -345,7 +357,9 @@ for a dimension:
|
||||
- name - the dimension name/label.
|
||||
*/
|
||||
class _ImmutableBaseDimension {
|
||||
constructor(name) {
|
||||
name: any;
|
||||
|
||||
constructor(name: any) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@@ -353,13 +367,13 @@ class _ImmutableBaseDimension {
|
||||
return Object.assign(Object.create(Object.getPrototypeOf(this)), this);
|
||||
}
|
||||
|
||||
rename(name) {
|
||||
rename(name: any) {
|
||||
const d = this.clone();
|
||||
d.name = name;
|
||||
return d;
|
||||
}
|
||||
|
||||
select(spec) {
|
||||
select(spec: any) {
|
||||
const { mode } = spec;
|
||||
if (mode === undefined) {
|
||||
throw new Error("select spec does not contain 'mode'");
|
||||
@@ -371,7 +385,11 @@ class _ImmutableBaseDimension {
|
||||
}
|
||||
|
||||
class ImmutableScalarDimension extends _ImmutableBaseDimension {
|
||||
constructor(name, data, value, ValueArrayType) {
|
||||
index: any;
|
||||
|
||||
value: any;
|
||||
|
||||
constructor(name: any, data: any, value: any, ValueArrayType: any) {
|
||||
super(name);
|
||||
|
||||
// Three modes - caller can provide a pre-created value array,
|
||||
@@ -398,7 +416,7 @@ class ImmutableScalarDimension extends _ImmutableBaseDimension {
|
||||
// only by enumerated dimensions
|
||||
array = this._createValueArray(
|
||||
data,
|
||||
(i) => value[i],
|
||||
(i: any) => value[i],
|
||||
new ValueArrayType(data.length)
|
||||
);
|
||||
} else {
|
||||
@@ -413,7 +431,7 @@ class ImmutableScalarDimension extends _ImmutableBaseDimension {
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this -- needed for polymorphism
|
||||
_createValueArray(data, mapf, array) {
|
||||
_createValueArray(data: any, mapf: any, array: any) {
|
||||
// create dimension value array
|
||||
const len = data.length;
|
||||
const larray = array;
|
||||
@@ -423,7 +441,7 @@ class ImmutableScalarDimension extends _ImmutableBaseDimension {
|
||||
return larray;
|
||||
}
|
||||
|
||||
select(spec) {
|
||||
select(spec: any) {
|
||||
const { mode } = spec;
|
||||
const { index } = this;
|
||||
switch (mode) {
|
||||
@@ -440,7 +458,7 @@ class ImmutableScalarDimension extends _ImmutableBaseDimension {
|
||||
}
|
||||
}
|
||||
|
||||
selectExact(spec) {
|
||||
selectExact(spec: any) {
|
||||
const { value, index } = this;
|
||||
let { values } = spec;
|
||||
if (!Array.isArray(values)) {
|
||||
@@ -459,7 +477,7 @@ class ImmutableScalarDimension extends _ImmutableBaseDimension {
|
||||
return { ranges, index };
|
||||
}
|
||||
|
||||
selectRange(spec) {
|
||||
selectRange(spec: any) {
|
||||
const { value, index } = this;
|
||||
/*
|
||||
if !inclusive: [lo, hi) else [lo, hi]
|
||||
@@ -478,11 +496,11 @@ class ImmutableScalarDimension extends _ImmutableBaseDimension {
|
||||
}
|
||||
|
||||
class ImmutableEnumDimension extends ImmutableScalarDimension {
|
||||
constructor(name, data, value) {
|
||||
constructor(name: any, data: any, value: any) {
|
||||
super(name, data, value, Uint32Array);
|
||||
}
|
||||
|
||||
_createValueArray(data, mapf, array) {
|
||||
_createValueArray(data: any, mapf: any, array: any) {
|
||||
const len = data.length;
|
||||
const larray = array;
|
||||
|
||||
@@ -493,6 +511,7 @@ class ImmutableEnumDimension extends ImmutableScalarDimension {
|
||||
s.add(mapf(i, data));
|
||||
}
|
||||
const enumIndex = sortArray(Array.from(s));
|
||||
// @ts-expect-error FIXME Adding enumIndex as member variable results in "undefined" enumIndex value
|
||||
this.enumIndex = enumIndex;
|
||||
|
||||
// create dimension value array
|
||||
@@ -505,7 +524,8 @@ class ImmutableEnumDimension extends ImmutableScalarDimension {
|
||||
return larray;
|
||||
}
|
||||
|
||||
selectExact(spec) {
|
||||
selectExact(spec: any) {
|
||||
// @ts-expect-error FIXME Adding enumIndex as member variable results in "undefined" enumIndex value
|
||||
const { enumIndex } = this;
|
||||
let { values } = spec;
|
||||
if (!Array.isArray(values)) {
|
||||
@@ -513,12 +533,13 @@ class ImmutableEnumDimension extends ImmutableScalarDimension {
|
||||
}
|
||||
return super.selectExact({
|
||||
mode: spec.mode,
|
||||
values: values.map((v) =>
|
||||
values: values.map((v: any) =>
|
||||
binarySearch(enumIndex, v, 0, enumIndex.length)
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
// @ts-expect-error ts-migrate(2416) FIXME: Property 'selectRange' in type 'ImmutableEnumDimen... Remove this comment to see the full error message
|
||||
// eslint-disable-next-line class-methods-use-this -- enables polymorphism
|
||||
selectRange() {
|
||||
throw new Error("range selection unsupported on Enumerated dimension");
|
||||
@@ -526,7 +547,15 @@ class ImmutableEnumDimension extends ImmutableScalarDimension {
|
||||
}
|
||||
|
||||
class ImmutableSpatialDimension extends _ImmutableBaseDimension {
|
||||
constructor(name, data, X, Y) {
|
||||
X: any;
|
||||
|
||||
Xindex: any;
|
||||
|
||||
Y: any;
|
||||
|
||||
Yindex: any;
|
||||
|
||||
constructor(name: any, data: any, X: any, Y: any) {
|
||||
super(name);
|
||||
|
||||
if (X.length !== Y.length && X.length !== data.length) {
|
||||
@@ -541,7 +570,7 @@ class ImmutableSpatialDimension extends _ImmutableBaseDimension {
|
||||
this.Yindex = makeSortIndex(Y);
|
||||
}
|
||||
|
||||
select(spec) {
|
||||
select(spec: any) {
|
||||
const { mode } = spec;
|
||||
switch (mode) {
|
||||
case "all":
|
||||
@@ -557,7 +586,7 @@ class ImmutableSpatialDimension extends _ImmutableBaseDimension {
|
||||
}
|
||||
}
|
||||
|
||||
selectWithinRect(spec) {
|
||||
selectWithinRect(spec: any) {
|
||||
/*
|
||||
{ mode: "within-rect", minX: 1, minY: 0, maxX: 3, maxY: 9 }
|
||||
*/
|
||||
@@ -590,7 +619,7 @@ class ImmutableSpatialDimension extends _ImmutableBaseDimension {
|
||||
* then the polygon test is applied
|
||||
*/
|
||||
|
||||
selectWithinPolygon(spec) {
|
||||
selectWithinPolygon(spec: any) {
|
||||
/*
|
||||
{ mode: "within-polygon", polygon: [ [x0, y0], ... ] }
|
||||
*/
|
||||
@@ -645,7 +674,7 @@ export const DimTypes = {
|
||||
spatial: ImmutableSpatialDimension,
|
||||
};
|
||||
|
||||
function isArrayOrTypedArray(x) {
|
||||
function isArrayOrTypedArray(x: any) {
|
||||
return (
|
||||
Array.isArray(x) ||
|
||||
(ArrayBuffer.isView(x) &&
|
||||
@@ -654,7 +683,7 @@ function isArrayOrTypedArray(x) {
|
||||
}
|
||||
|
||||
/* return bounding box of the polygon */
|
||||
function polygonBoundingBox(polygon) {
|
||||
function polygonBoundingBox(polygon: any) {
|
||||
let minX = Number.MAX_VALUE;
|
||||
let minY = Number.MAX_VALUE;
|
||||
let maxX = Number.MIN_VALUE;
|
||||
@@ -678,7 +707,7 @@ function polygonBoundingBox(polygon) {
|
||||
* @param {float} y - point y coordinate
|
||||
* @type {boolean}
|
||||
*/
|
||||
function withinPolygon(polygon, x, y) {
|
||||
function withinPolygon(polygon: any, x: any, y: any) {
|
||||
const n = polygon.length;
|
||||
let p = polygon[n - 1];
|
||||
let x0 = p[0];
|
||||
+6
-6
@@ -16,10 +16,10 @@ class PositiveIntervals {
|
||||
// 1. no overlapping intervals
|
||||
// 2. sorted in order of interval min.
|
||||
//
|
||||
static canonicalize(A) {
|
||||
static canonicalize(A: any) {
|
||||
if (A.length <= 1) return A;
|
||||
const copy = A.slice();
|
||||
copy.sort((a, b) => a[0] - b[0]);
|
||||
copy.sort((a: any, b: any) => a[0] - b[0]);
|
||||
const res = [];
|
||||
res.push(copy[0]);
|
||||
for (let i = 1, len = copy.length; i < len; i += 1) {
|
||||
@@ -38,11 +38,11 @@ class PositiveIntervals {
|
||||
// Return interval with values belonging to both A and B. Essentially
|
||||
// a set union operation.
|
||||
//
|
||||
static union(A, B) {
|
||||
static union(A: any, B: any) {
|
||||
return PositiveIntervals.canonicalize([...A, ...B]);
|
||||
}
|
||||
|
||||
static _flatten(A, B) {
|
||||
static _flatten(A: any, B: any) {
|
||||
const points = []; /* point, A, start */
|
||||
for (let a = 0; a < A.length; a += 1) {
|
||||
points.push([A[a][0], true, true]);
|
||||
@@ -60,7 +60,7 @@ class PositiveIntervals {
|
||||
// A - B, ie, the interval with all values in A that are not in B. Essentially
|
||||
// a set difference operation.
|
||||
//
|
||||
static difference(A, B) {
|
||||
static difference(A: any, B: any) {
|
||||
// Corner cases
|
||||
if (A.length === 0 || B.length === 0) {
|
||||
return PositiveIntervals.canonicalize(A);
|
||||
@@ -96,7 +96,7 @@ class PositiveIntervals {
|
||||
// Return interval with values belonging to A or B. Essentially a set
|
||||
// intersection.
|
||||
//
|
||||
static intersection(A, B) {
|
||||
static intersection(A: any, B: any) {
|
||||
if (A.length === 0 || B.length === 0) {
|
||||
return [];
|
||||
}
|
||||
+72
-33
@@ -10,12 +10,12 @@ import { isTypedArray, isFpTypedArray } from "../typeHelpers";
|
||||
/*
|
||||
Comparators for float sort. -Infinity < finite < Infinity < NaN
|
||||
*/
|
||||
function lt(a, b) {
|
||||
function lt(a: any, b: any) {
|
||||
if (Number.isNaN(b)) return !Number.isNaN(a);
|
||||
return a < b;
|
||||
}
|
||||
|
||||
function gt(a, b) {
|
||||
function gt(a: any, b: any) {
|
||||
if (Number.isNaN(a)) return !Number.isNaN(b);
|
||||
return a > b;
|
||||
}
|
||||
@@ -24,7 +24,7 @@ function gt(a, b) {
|
||||
insertion sort, used for small arrays (controlled by SMALL_ARRAY constant)
|
||||
*/
|
||||
const SMALL_ARRAY = 32;
|
||||
function insertionsort(a, lo, hi) {
|
||||
function insertionsort(a: any, lo: any, hi: any) {
|
||||
for (let i = lo + 1; i < hi + 1; i += 1) {
|
||||
const x = a[i];
|
||||
let j;
|
||||
@@ -36,7 +36,7 @@ function insertionsort(a, lo, hi) {
|
||||
return a;
|
||||
}
|
||||
|
||||
function insertionsortFloats(a, lo, hi) {
|
||||
function insertionsortFloats(a: any, lo: any, hi: any) {
|
||||
for (let i = lo + 1; i < hi + 1; i += 1) {
|
||||
const x = a[i];
|
||||
let j;
|
||||
@@ -48,7 +48,7 @@ function insertionsortFloats(a, lo, hi) {
|
||||
return a;
|
||||
}
|
||||
|
||||
function insertionsortIndirect(a, s, lo, hi) {
|
||||
function insertionsortIndirect(a: any, s: any, lo: any, hi: any) {
|
||||
for (let i = lo + 1; i < hi + 1; i += 1) {
|
||||
const x = a[i];
|
||||
const t = s[x];
|
||||
@@ -61,7 +61,7 @@ function insertionsortIndirect(a, s, lo, hi) {
|
||||
return a;
|
||||
}
|
||||
|
||||
function insertionsortFloatsIndirect(a, s, lo, hi) {
|
||||
function insertionsortFloatsIndirect(a: any, s: any, lo: any, hi: any) {
|
||||
for (let i = lo + 1; i < hi + 1; i += 1) {
|
||||
const x = a[i];
|
||||
const t = s[x];
|
||||
@@ -77,7 +77,7 @@ function insertionsortFloatsIndirect(a, s, lo, hi) {
|
||||
/*
|
||||
Quicksort - used for larger arrays
|
||||
*/
|
||||
function quicksort(a, lo, hi) {
|
||||
function quicksort(a: any, lo: any, hi: any) {
|
||||
if (hi - lo < SMALL_ARRAY) {
|
||||
return insertionsort(a, lo, hi);
|
||||
}
|
||||
@@ -107,7 +107,7 @@ function quicksort(a, lo, hi) {
|
||||
return a;
|
||||
}
|
||||
|
||||
function quicksortFloats(a, lo, hi) {
|
||||
function quicksortFloats(a: any, lo: any, hi: any) {
|
||||
if (hi - lo < SMALL_ARRAY) {
|
||||
return insertionsortFloats(a, lo, hi);
|
||||
}
|
||||
@@ -137,7 +137,7 @@ function quicksortFloats(a, lo, hi) {
|
||||
return a;
|
||||
}
|
||||
|
||||
function quicksortIndirect(a, s, lo, hi) {
|
||||
function quicksortIndirect(a: any, s: any, lo: any, hi: any) {
|
||||
if (hi - lo < SMALL_ARRAY) {
|
||||
return insertionsortIndirect(a, s, lo, hi);
|
||||
}
|
||||
@@ -168,7 +168,7 @@ function quicksortIndirect(a, s, lo, hi) {
|
||||
return a;
|
||||
}
|
||||
|
||||
function quicksortFloatsIndirect(a, s, lo, hi) {
|
||||
function quicksortFloatsIndirect(a: any, s: any, lo: any, hi: any) {
|
||||
if (hi - lo < SMALL_ARRAY) {
|
||||
return insertionsortFloatsIndirect(a, s, lo, hi);
|
||||
}
|
||||
@@ -203,7 +203,7 @@ function quicksortFloatsIndirect(a, s, lo, hi) {
|
||||
Convenience wrappers, handling optimization paths and default
|
||||
handlers for NaN comparisons. Sorts in place.
|
||||
*/
|
||||
export function sortArray(arr) {
|
||||
export function sortArray(arr: any) {
|
||||
if (Array.isArray(arr)) {
|
||||
return quicksort(arr, 0, arr.length - 1);
|
||||
}
|
||||
@@ -217,7 +217,7 @@ export function sortArray(arr) {
|
||||
throw new Error("sortArray received unsupported object type");
|
||||
}
|
||||
|
||||
export function sortIndex(index, source) {
|
||||
export function sortIndex(index: any, source: any) {
|
||||
if (isFpTypedArray(source))
|
||||
return quicksortFloatsIndirect(index, source, 0, index.length - 1);
|
||||
return quicksortIndirect(index, source, 0, index.length - 1);
|
||||
@@ -234,7 +234,12 @@ export function sortIndex(index, source) {
|
||||
// C++: lower_bound()
|
||||
// Python: bisect.bisect_left()
|
||||
//
|
||||
function lowerBoundNonFloat(valueArray, value, first, last) {
|
||||
function lowerBoundNonFloat(
|
||||
valueArray: any,
|
||||
value: any,
|
||||
first: any,
|
||||
last: any
|
||||
) {
|
||||
let lfirst = first;
|
||||
let llast = last;
|
||||
// this is just a binary search
|
||||
@@ -254,7 +259,7 @@ function lowerBoundNonFloat(valueArray, value, first, last) {
|
||||
// If the underlying array is a Float32Array or Float64Array, will enforce
|
||||
// the ordering -Infinity < finite < Infinity < NaN.
|
||||
//
|
||||
function lowerBoundFloat(valueArray, value, first, last) {
|
||||
function lowerBoundFloat(valueArray: any, value: any, first: any, last: any) {
|
||||
let lfirst = first;
|
||||
let llast = last;
|
||||
// this is just a binary search
|
||||
@@ -269,7 +274,7 @@ function lowerBoundFloat(valueArray, value, first, last) {
|
||||
return lfirst;
|
||||
}
|
||||
|
||||
export function lowerBound(valueArray, value, first, last) {
|
||||
export function lowerBound(valueArray: any, value: any, first: any, last: any) {
|
||||
if (isFpTypedArray(valueArray)) {
|
||||
return lowerBoundFloat(valueArray, value, first, last);
|
||||
}
|
||||
@@ -279,11 +284,11 @@ export function lowerBound(valueArray, value, first, last) {
|
||||
// Inlined performance optimization - used to indirect through a sort map.
|
||||
//
|
||||
function lowerBoundNonFloatIndirect(
|
||||
valueArray,
|
||||
indexArray,
|
||||
value,
|
||||
first,
|
||||
last
|
||||
valueArray: any,
|
||||
indexArray: any,
|
||||
value: any,
|
||||
first: any,
|
||||
last: any
|
||||
) {
|
||||
let lfirst = first;
|
||||
let llast = last;
|
||||
@@ -299,7 +304,13 @@ function lowerBoundNonFloatIndirect(
|
||||
return lfirst;
|
||||
}
|
||||
|
||||
function lowerBoundFloatIndirect(valueArray, indexArray, value, first, last) {
|
||||
function lowerBoundFloatIndirect(
|
||||
valueArray: any,
|
||||
indexArray: any,
|
||||
value: any,
|
||||
first: any,
|
||||
last: any
|
||||
) {
|
||||
let lfirst = first;
|
||||
let llast = last;
|
||||
// this is just a binary search
|
||||
@@ -314,7 +325,13 @@ function lowerBoundFloatIndirect(valueArray, indexArray, value, first, last) {
|
||||
return lfirst;
|
||||
}
|
||||
|
||||
export function lowerBoundIndirect(valueArray, indexArray, value, first, last) {
|
||||
export function lowerBoundIndirect(
|
||||
valueArray: any,
|
||||
indexArray: any,
|
||||
value: any,
|
||||
first: any,
|
||||
last: any
|
||||
) {
|
||||
if (isFpTypedArray(valueArray)) {
|
||||
return lowerBoundFloatIndirect(valueArray, indexArray, value, first, last);
|
||||
}
|
||||
@@ -332,7 +349,12 @@ export function lowerBoundIndirect(valueArray, indexArray, value, first, last) {
|
||||
// C++: upper_bound()
|
||||
// Python: bisect.bisect_right()
|
||||
//
|
||||
function upperBoundNonFloat(valueArray, value, first, last) {
|
||||
function upperBoundNonFloat(
|
||||
valueArray: any,
|
||||
value: any,
|
||||
first: any,
|
||||
last: any
|
||||
) {
|
||||
let lfirst = first;
|
||||
let llast = last;
|
||||
// this is just a binary search
|
||||
@@ -347,7 +369,7 @@ function upperBoundNonFloat(valueArray, value, first, last) {
|
||||
return lfirst;
|
||||
}
|
||||
|
||||
function upperBoundFloat(valueArray, value, first, last) {
|
||||
function upperBoundFloat(valueArray: any, value: any, first: any, last: any) {
|
||||
let lfirst = first;
|
||||
let llast = last;
|
||||
// this is just a binary search
|
||||
@@ -362,7 +384,7 @@ function upperBoundFloat(valueArray, value, first, last) {
|
||||
return lfirst;
|
||||
}
|
||||
|
||||
export function upperBound(valueArray, value, first, last) {
|
||||
export function upperBound(valueArray: any, value: any, first: any, last: any) {
|
||||
if (isFpTypedArray(valueArray)) {
|
||||
return upperBoundFloat(valueArray, value, first, last);
|
||||
}
|
||||
@@ -372,11 +394,11 @@ export function upperBound(valueArray, value, first, last) {
|
||||
// Inline performance optimization
|
||||
//
|
||||
function upperBoundNonFloatIndirect(
|
||||
valueArray,
|
||||
indexArray,
|
||||
value,
|
||||
first,
|
||||
last
|
||||
valueArray: any,
|
||||
indexArray: any,
|
||||
value: any,
|
||||
first: any,
|
||||
last: any
|
||||
) {
|
||||
let lfirst = first;
|
||||
let llast = last;
|
||||
@@ -392,7 +414,13 @@ function upperBoundNonFloatIndirect(
|
||||
return lfirst;
|
||||
}
|
||||
|
||||
function upperBoundFloatIndirect(valueArray, indexArray, value, first, last) {
|
||||
function upperBoundFloatIndirect(
|
||||
valueArray: any,
|
||||
indexArray: any,
|
||||
value: any,
|
||||
first: any,
|
||||
last: any
|
||||
) {
|
||||
let lfirst = first;
|
||||
let llast = last;
|
||||
// this is just a binary search
|
||||
@@ -407,7 +435,13 @@ function upperBoundFloatIndirect(valueArray, indexArray, value, first, last) {
|
||||
return lfirst;
|
||||
}
|
||||
|
||||
export function upperBoundIndirect(valueArray, indexArray, value, first, last) {
|
||||
export function upperBoundIndirect(
|
||||
valueArray: any,
|
||||
indexArray: any,
|
||||
value: any,
|
||||
first: any,
|
||||
last: any
|
||||
) {
|
||||
if (isFpTypedArray(valueArray)) {
|
||||
return upperBoundFloatIndirect(valueArray, indexArray, value, first, last);
|
||||
}
|
||||
@@ -421,7 +455,12 @@ export function upperBoundIndirect(valueArray, indexArray, value, first, last) {
|
||||
// The same semantics/behavior as:
|
||||
// C++: binary_search()
|
||||
//
|
||||
export function binarySearch(valueArray, value, first, last) {
|
||||
export function binarySearch(
|
||||
valueArray: any,
|
||||
value: any,
|
||||
first: any,
|
||||
last: any
|
||||
) {
|
||||
const index = lowerBound(valueArray, value, first, last);
|
||||
if (index !== last && value === valueArray[index]) return index;
|
||||
return last;
|
||||
@@ -7,7 +7,7 @@ import { rangeFill as fillRange } from "../range";
|
||||
|
||||
// slice out of one array into another, using an index array
|
||||
//
|
||||
export function sliceByIndex(src, index) {
|
||||
export function sliceByIndex(src: any, index: any) {
|
||||
if (index === undefined || index === null) {
|
||||
return src;
|
||||
}
|
||||
@@ -18,7 +18,7 @@ export function sliceByIndex(src, index) {
|
||||
return dst;
|
||||
}
|
||||
|
||||
export function makeSortIndex(src) {
|
||||
export function makeSortIndex(src: any) {
|
||||
const index = fillRange(new Uint32Array(src.length));
|
||||
sortIndex(index, src);
|
||||
return index;
|
||||
Reference in New Issue
Block a user