TS migration. #2288. (#2328)

* 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:
Mim Hastie
2021-07-26 20:18:17 +00:00
committed by GitHub
co-authored by ts-migrate Timmy Huang
parent 7328cbdbd5
commit 934cc5c69b
206 changed files with 4719 additions and 2085 deletions
@@ -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]*$/, "")
@@ -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:
@@ -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()
@@ -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;
}
@@ -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);
}
@@ -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);
}
@@ -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;
@@ -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];
@@ -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 [];
}
@@ -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;