mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-10-09 01:48:12 +08:00
TS typing for Dataframe (#2382)
* initial TS typing * first cut at Dataframe TS typing * more Dataframe typing * comments * more Dataframe cleanup * PR review fixes and improvements
This commit is contained in:
@@ -188,8 +188,10 @@ describe("AnnoMatrix", () => {
|
|||||||
(fetch as any)
|
(fetch as any)
|
||||||
.once(serverMocks.annotationsObs(["n_genes"]))
|
.once(serverMocks.annotationsObs(["n_genes"]))
|
||||||
.once(serverMocks.annotationsObs(["n_genes"]));
|
.once(serverMocks.annotationsObs(["n_genes"]));
|
||||||
const ng1 = await am1.fetch("obs", "n_genes");
|
const ng1 = (await am1.fetch("obs", "n_genes")) as Dataframe;
|
||||||
const ng2 = await am2.fetch("obs", "n_genes");
|
const ng2 = (await am2.fetch("obs", "n_genes")) as Dataframe;
|
||||||
|
expect(ng1).toBeDefined();
|
||||||
|
expect(ng2).toBeDefined();
|
||||||
expect(ng1).toHaveLength(ng2.length);
|
expect(ng1).toHaveLength(ng2.length);
|
||||||
expect(ng1.colIndex.labels()).toEqual(ng2.colIndex.labels());
|
expect(ng1.colIndex.labels()).toEqual(ng2.colIndex.labels());
|
||||||
expect(ng1.col("n_genes").asArray()).toEqual(
|
expect(ng1.col("n_genes").asArray()).toEqual(
|
||||||
@@ -216,7 +218,7 @@ describe("AnnoMatrix", () => {
|
|||||||
);
|
);
|
||||||
expect(base.getMatrixColumns("obs")).not.toContain("foo");
|
expect(base.getMatrixColumns("obs")).not.toContain("foo");
|
||||||
expect(am1.getMatrixColumns("obs")).toContain("foo");
|
expect(am1.getMatrixColumns("obs")).toContain("foo");
|
||||||
const foo = await am1.fetch("obs", "foo");
|
const foo: Dataframe = await am1.fetch("obs", "foo");
|
||||||
expect(foo).toBeDefined();
|
expect(foo).toBeDefined();
|
||||||
expect(foo).toBeInstanceOf(Dataframe);
|
expect(foo).toBeInstanceOf(Dataframe);
|
||||||
expect(foo).toHaveLength(am1.nObs);
|
expect(foo).toHaveLength(am1.nObs);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import {
|
|||||||
AnnoMatrixObsCrossfilter,
|
AnnoMatrixObsCrossfilter,
|
||||||
isubsetMask,
|
isubsetMask,
|
||||||
} from "../../../src/annoMatrix";
|
} from "../../../src/annoMatrix";
|
||||||
|
import { Dataframe } from "../../../src/util/dataframe";
|
||||||
import { rangeFill } from "../../../src/util/range";
|
import { rangeFill } from "../../../src/util/range";
|
||||||
|
|
||||||
enableFetchMocks();
|
enableFetchMocks();
|
||||||
@@ -132,7 +133,7 @@ describe("AnnoMatrixCrossfilter", () => {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
const df = await annoMatrix.fetch("obs", "louvain");
|
const df: Dataframe = await annoMatrix.fetch("obs", "louvain");
|
||||||
const values = df.col("louvain").asArray();
|
const values = df.col("louvain").asArray();
|
||||||
const selected = xfltr.allSelectedMask();
|
const selected = xfltr.allSelectedMask();
|
||||||
values.every(
|
values.every(
|
||||||
@@ -265,7 +266,11 @@ describe("AnnoMatrixCrossfilter", () => {
|
|||||||
expect(xfltr).toBeDefined();
|
expect(xfltr).toBeDefined();
|
||||||
expect(xfltr.countSelected()).toEqual(240);
|
expect(xfltr.countSelected()).toEqual(240);
|
||||||
|
|
||||||
const df = await annoMatrixSubset.fetch("obs", "louvain");
|
const df: Dataframe = (await annoMatrixSubset.fetch(
|
||||||
|
"obs",
|
||||||
|
"louvain"
|
||||||
|
)) as Dataframe;
|
||||||
|
expect(df).toBeDefined();
|
||||||
const values = df.col("louvain").asArray();
|
const values = df.col("louvain").asArray();
|
||||||
const selected = xfltr.allSelectedMask();
|
const selected = xfltr.allSelectedMask();
|
||||||
values.every(
|
values.every(
|
||||||
@@ -354,7 +359,7 @@ describe("AnnoMatrixCrossfilter", () => {
|
|||||||
).toHaveLength(1);
|
).toHaveLength(1);
|
||||||
|
|
||||||
// check data update.
|
// check data update.
|
||||||
const df = await xfltr.annoMatrix.fetch("obs", "foo");
|
const df: Dataframe = await xfltr.annoMatrix.fetch("obs", "foo");
|
||||||
expect(
|
expect(
|
||||||
df
|
df
|
||||||
.col("foo")
|
.col("foo")
|
||||||
@@ -649,7 +654,7 @@ describe("AnnoMatrixCrossfilter", () => {
|
|||||||
values: ["purple"],
|
values: ["purple"],
|
||||||
});
|
});
|
||||||
expect(xfltr2.countSelected()).toEqual(2);
|
expect(xfltr2.countSelected()).toEqual(2);
|
||||||
expect(xfltr2.allSelectedLabels()).toEqual(Int32Array.from([0, 10]));
|
expect(xfltr2.allSelectedLabels()).toEqual(Array.from([0, 10]));
|
||||||
});
|
});
|
||||||
|
|
||||||
test("resetObsColumnValues", async () => {
|
test("resetObsColumnValues", async () => {
|
||||||
|
|||||||
@@ -43,7 +43,6 @@ function getEncodedDataframe(colNames: any, length: any, colSchemas: any) {
|
|||||||
const colIndex = new KeyIndex(colNames);
|
const colIndex = new KeyIndex(colNames);
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||||
const columns = colSchemas.map((s: any) => makeMockColumn(s, length));
|
const columns = colSchemas.map((s: any) => makeMockColumn(s, 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([length, colNames.length], columns, null, colIndex);
|
const df = new Dataframe([length, colNames.length], columns, null, colIndex);
|
||||||
const body = encodeMatrixFBS(df);
|
const body = encodeMatrixFBS(df);
|
||||||
return body;
|
return body;
|
||||||
@@ -56,7 +55,6 @@ export function dataframeResponse(colNames: any, columns: any) {
|
|||||||
[columns[0].length, colNames.length],
|
[columns[0].length, colNames.length],
|
||||||
columns,
|
columns,
|
||||||
null,
|
null,
|
||||||
// @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
|
|
||||||
colIndex
|
colIndex
|
||||||
);
|
);
|
||||||
const body = encodeMatrixFBS(df);
|
const body = encodeMatrixFBS(df);
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
import cloneDeep from "lodash.clonedeep";
|
import cloneDeep from "lodash.clonedeep";
|
||||||
|
|
||||||
|
import { NumberArray } from "../../src/common/types/arraytypes";
|
||||||
import calcCentroid from "../../src/util/centroid";
|
import calcCentroid from "../../src/util/centroid";
|
||||||
import quantile from "../../src/util/quantile";
|
import quantile from "../../src/util/quantile";
|
||||||
import { matrixFBSToDataframe } from "../../src/util/stateManager/matrix";
|
import { matrixFBSToDataframe } from "../../src/util/stateManager/matrix";
|
||||||
import * as REST from "./stateManager/sampleResponses";
|
import * as REST from "./stateManager/sampleResponses";
|
||||||
import { indexEntireSchema } from "../../src/util/stateManager/schemaHelpers";
|
import { indexEntireSchema } from "../../src/util/stateManager/schemaHelpers";
|
||||||
import { normalizeWritableCategoricalSchema } from "../../src/annoMatrix/normalize";
|
import { normalizeWritableCategoricalSchema } from "../../src/annoMatrix/normalize";
|
||||||
|
import { Dataframe } from "../../src/util/dataframe";
|
||||||
|
|
||||||
describe("centroid", () => {
|
describe("centroid", () => {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||||
let schema: any;
|
let schema: any;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
let obsAnnotations: Dataframe;
|
||||||
let obsAnnotations: any;
|
let obsLayout: Dataframe;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
|
||||||
let obsLayout: any;
|
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
schema = indexEntireSchema(cloneDeep(REST.schema.schema));
|
schema = indexEntireSchema(cloneDeep(REST.schema.schema));
|
||||||
@@ -43,8 +43,8 @@ describe("centroid", () => {
|
|||||||
|
|
||||||
// This expected result assumes that all cells belong in all categorical values inside of sample response
|
// This expected result assumes that all cells belong in all categorical values inside of sample response
|
||||||
const expectedResult = [
|
const expectedResult = [
|
||||||
quantile([0.5], obsLayout.col("umap_0").asArray())[0],
|
quantile([0.5], obsLayout.col("umap_0").asArray() as NumberArray)[0],
|
||||||
quantile([0.5], obsLayout.col("umap_1").asArray())[0],
|
quantile([0.5], obsLayout.col("umap_1").asArray() as NumberArray)[0],
|
||||||
];
|
];
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||||
@@ -68,8 +68,8 @@ describe("centroid", () => {
|
|||||||
|
|
||||||
// This expected result assumes that all cells belong in all categorical values inside of sample response
|
// This expected result assumes that all cells belong in all categorical values inside of sample response
|
||||||
const expectedResult = [
|
const expectedResult = [
|
||||||
quantile([0.5], obsLayout.col("umap_0").asArray())[0],
|
quantile([0.5], obsLayout.col("umap_0").asArray() as NumberArray)[0],
|
||||||
quantile([0.5], obsLayout.col("umap_1").asArray())[0],
|
quantile([0.5], obsLayout.col("umap_1").asArray() as NumberArray)[0],
|
||||||
];
|
];
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ describe("dataframe constructor", () => {
|
|||||||
expect(df).toBeDefined();
|
expect(df).toBeDefined();
|
||||||
expect(df.dims).toEqual([0, 0]);
|
expect(df.dims).toEqual([0, 0]);
|
||||||
expect(df).toHaveLength(0);
|
expect(df).toHaveLength(0);
|
||||||
expect(df.icol(0)).not.toBeDefined();
|
expect(df.ihasCol(0)).toBeFalsy();
|
||||||
|
expect(() => df.icol(0)).toThrow(RangeError);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("create with default indices", () => {
|
test("create with default indices", () => {
|
||||||
@@ -23,13 +24,19 @@ describe("dataframe constructor", () => {
|
|||||||
expect(df.at(2, 1)).toEqual(1);
|
expect(df.at(2, 1)).toEqual(1);
|
||||||
expect(df.iat(0, 0)).toEqual(0);
|
expect(df.iat(0, 0)).toEqual(0);
|
||||||
expect(df.iat(2, 1)).toEqual(1);
|
expect(df.iat(2, 1)).toEqual(1);
|
||||||
|
|
||||||
|
expect(Array.from(df.rowIndex.labels())).toEqual(
|
||||||
|
df.rowIndex.getLabels(df.rowIndex.getOffsets(df.rowIndex.labels()))
|
||||||
|
);
|
||||||
|
expect(Array.from(df.colIndex.labels())).toEqual(
|
||||||
|
df.colIndex.getLabels(df.colIndex.getOffsets(df.colIndex.labels()))
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("create with labelled indices", () => {
|
test("create with labelled indices", () => {
|
||||||
const df = new Dataframe.Dataframe(
|
const df = new Dataframe.Dataframe(
|
||||||
[3, 2],
|
[3, 2],
|
||||||
[new Int32Array([0, 1, 2]), new Int32Array([3, 4, 5])],
|
[new Int32Array([0, 1, 2]), new Int32Array([3, 4, 5])],
|
||||||
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'DenseInt32Index' is not assignab... Remove this comment to see the full error message
|
|
||||||
new Dataframe.DenseInt32Index([2, 1, 0]),
|
new Dataframe.DenseInt32Index([2, 1, 0]),
|
||||||
new Dataframe.KeyIndex(["A", "B"])
|
new Dataframe.KeyIndex(["A", "B"])
|
||||||
);
|
);
|
||||||
@@ -56,7 +63,6 @@ describe("simple data access", () => {
|
|||||||
new Float64Array([0.0, Number.NaN, Number.POSITIVE_INFINITY, 3.14159]),
|
new Float64Array([0.0, Number.NaN, Number.POSITIVE_INFINITY, 3.14159]),
|
||||||
["red", "blue", "green", "nan"],
|
["red", "blue", "green", "nan"],
|
||||||
],
|
],
|
||||||
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'DenseInt32Index' is not assignab... Remove this comment to see the full error message
|
|
||||||
new Dataframe.DenseInt32Index([3, 2, 1, 0]),
|
new Dataframe.DenseInt32Index([3, 2, 1, 0]),
|
||||||
new Dataframe.KeyIndex(["numbers", "colors"])
|
new Dataframe.KeyIndex(["numbers", "colors"])
|
||||||
);
|
);
|
||||||
@@ -123,7 +129,9 @@ describe("simple data access", () => {
|
|||||||
expect(df.has(3, "foo")).toBeFalsy();
|
expect(df.has(3, "foo")).toBeFalsy();
|
||||||
expect(df.has(-1, "numbers")).toBeFalsy();
|
expect(df.has(-1, "numbers")).toBeFalsy();
|
||||||
expect(df.has(-1, -1)).toBeFalsy();
|
expect(df.has(-1, -1)).toBeFalsy();
|
||||||
expect(df.has(null, null)).toBeFalsy();
|
expect(
|
||||||
|
df.has(null as unknown as number, null as unknown as number)
|
||||||
|
).toBeFalsy();
|
||||||
expect(df.has(0, "foo")).toBeFalsy();
|
expect(df.has(0, "foo")).toBeFalsy();
|
||||||
expect(df.has(99, "numbers")).toBeFalsy();
|
expect(df.has(99, "numbers")).toBeFalsy();
|
||||||
expect(df.has(99, "foo")).toBeFalsy();
|
expect(df.has(99, "foo")).toBeFalsy();
|
||||||
@@ -141,12 +149,10 @@ describe("dataframe subsetting", () => {
|
|||||||
["red", "green", "blue"],
|
["red", "green", "blue"],
|
||||||
],
|
],
|
||||||
null, // identity index
|
null, // identity index
|
||||||
// @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
|
|
||||||
new Dataframe.KeyIndex(["int32", "string", "float32", "colors"])
|
new Dataframe.KeyIndex(["int32", "string", "float32", "colors"])
|
||||||
);
|
);
|
||||||
|
|
||||||
test("all rows, one column", () => {
|
test("all rows, one column", () => {
|
||||||
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'string[]' is not assignable to p... Remove this comment to see the full error message
|
|
||||||
const dfA = sourceDf.subset(null, ["colors"]);
|
const dfA = sourceDf.subset(null, ["colors"]);
|
||||||
expect(dfA).toBeDefined();
|
expect(dfA).toBeDefined();
|
||||||
expect(dfA.dims).toEqual([3, 1]);
|
expect(dfA.dims).toEqual([3, 1]);
|
||||||
@@ -162,7 +168,6 @@ describe("dataframe subsetting", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("all rows, two columns", () => {
|
test("all rows, two columns", () => {
|
||||||
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'string[]' is not assignable to p... Remove this comment to see the full error message
|
|
||||||
const dfB = sourceDf.subset(null, ["float32", "colors"]);
|
const dfB = sourceDf.subset(null, ["float32", "colors"]);
|
||||||
expect(dfB).toBeDefined();
|
expect(dfB).toBeDefined();
|
||||||
expect(dfB.dims).toEqual([3, 2]);
|
expect(dfB.dims).toEqual([3, 2]);
|
||||||
@@ -232,7 +237,6 @@ describe("dataframe subsetting", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("two rows, two colums", () => {
|
test("two rows, two colums", () => {
|
||||||
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'string[]' is not assignable to p... Remove this comment to see the full error message
|
|
||||||
const dfF = sourceDf.subset([0, 2], ["int32", "float32"]);
|
const dfF = sourceDf.subset([0, 2], ["int32", "float32"]);
|
||||||
expect(dfF).toBeDefined();
|
expect(dfF).toBeDefined();
|
||||||
expect(dfF.dims).toEqual([2, 2]);
|
expect(dfF.dims).toEqual([2, 2]);
|
||||||
@@ -242,7 +246,6 @@ describe("dataframe subsetting", () => {
|
|||||||
expect(dfF.colIndex.labels()).toEqual(["int32", "float32"]);
|
expect(dfF.colIndex.labels()).toEqual(["int32", "float32"]);
|
||||||
|
|
||||||
// reverse the row and column order
|
// reverse the row and column order
|
||||||
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'string[]' is not assignable to p... Remove this comment to see the full error message
|
|
||||||
const dfFr = sourceDf.subset([2, 0], ["float32", "int32"]);
|
const dfFr = sourceDf.subset([2, 0], ["float32", "int32"]);
|
||||||
expect(dfFr).toBeDefined();
|
expect(dfFr).toBeDefined();
|
||||||
expect(dfFr.dims).toEqual([2, 2]);
|
expect(dfFr.dims).toEqual([2, 2]);
|
||||||
@@ -255,26 +258,23 @@ describe("dataframe subsetting", () => {
|
|||||||
test("withRowIndex", () => {
|
test("withRowIndex", () => {
|
||||||
const df = sourceDf.subset(
|
const df = sourceDf.subset(
|
||||||
null,
|
null,
|
||||||
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'string[]' is not assignable to p... Remove this comment to see the full error message
|
|
||||||
["int32", "float32"],
|
["int32", "float32"],
|
||||||
new Dataframe.DenseInt32Index([3, 2, 1])
|
new Dataframe.DenseInt32Index([2, 1])
|
||||||
);
|
);
|
||||||
|
expect(df.dims).toEqual([2, 2]);
|
||||||
expect(df.colIndex).toBeInstanceOf(Dataframe.KeyIndex);
|
expect(df.colIndex).toBeInstanceOf(Dataframe.KeyIndex);
|
||||||
expect(df.rowIndex).toBeInstanceOf(Dataframe.DenseInt32Index);
|
expect(df.rowIndex).toBeInstanceOf(Dataframe.DenseInt32Index);
|
||||||
expect(df.at(3, "int32")).toEqual(df.iat(0, 0));
|
expect(df.at(2, "int32")).toEqual(df.iat(0, 0));
|
||||||
});
|
});
|
||||||
|
|
||||||
test("withRowIndex error checks", () => {
|
test("withRowIndex error checks", () => {
|
||||||
expect(() =>
|
expect(() =>
|
||||||
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'string[]' is not assignable to p... Remove this comment to see the full error message
|
|
||||||
sourceDf.subset(null, ["red"], new Dataframe.IdentityInt32Index(1))
|
sourceDf.subset(null, ["red"], new Dataframe.IdentityInt32Index(1))
|
||||||
).toThrow(RangeError);
|
).toThrow(RangeError);
|
||||||
expect(() =>
|
expect(() =>
|
||||||
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'string[]' is not assignable to p... Remove this comment to see the full error message
|
|
||||||
sourceDf.subset(null, ["red"], new Dataframe.DenseInt32Index([0, 1]))
|
sourceDf.subset(null, ["red"], new Dataframe.DenseInt32Index([0, 1]))
|
||||||
).toThrow(RangeError);
|
).toThrow(RangeError);
|
||||||
expect(() =>
|
expect(() =>
|
||||||
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'string[]' is not assignable to p... Remove this comment to see the full error message
|
|
||||||
sourceDf.subset(null, ["red"], new Dataframe.KeyIndex([0, 1, 2, 3]))
|
sourceDf.subset(null, ["red"], new Dataframe.KeyIndex([0, 1, 2, 3]))
|
||||||
).toThrow(RangeError);
|
).toThrow(RangeError);
|
||||||
});
|
});
|
||||||
@@ -289,14 +289,12 @@ describe("dataframe subsetting", () => {
|
|||||||
new Float32Array([4.4, 5.5, 6.6]),
|
new Float32Array([4.4, 5.5, 6.6]),
|
||||||
["red", "green", "blue"],
|
["red", "green", "blue"],
|
||||||
],
|
],
|
||||||
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'DenseInt32Index' is not assignab... Remove this comment to see the full error message
|
|
||||||
new Dataframe.DenseInt32Index([2, 4, 6]),
|
new Dataframe.DenseInt32Index([2, 4, 6]),
|
||||||
new Dataframe.KeyIndex(["int32", "string", "float32", "colors"])
|
new Dataframe.KeyIndex(["int32", "string", "float32", "colors"])
|
||||||
);
|
);
|
||||||
|
|
||||||
const dfA = sourceDf.isubsetMask(
|
const dfA = sourceDf.isubsetMask(
|
||||||
new Uint8Array([0, 1, 1]),
|
new Uint8Array([0, 1, 1]),
|
||||||
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'Uint8Array' is not assignable to... Remove this comment to see the full error message
|
|
||||||
new Uint8Array([1, 0, 0, 1])
|
new Uint8Array([1, 0, 0, 1])
|
||||||
);
|
);
|
||||||
expect(dfA.dims).toEqual([2, 2]);
|
expect(dfA.dims).toEqual([2, 2]);
|
||||||
@@ -316,7 +314,6 @@ describe("dataframe subsetting", () => {
|
|||||||
["red", "green", "blue"],
|
["red", "green", "blue"],
|
||||||
],
|
],
|
||||||
null, // identity index
|
null, // identity index
|
||||||
// @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
|
|
||||||
new Dataframe.KeyIndex(["int32", "string", "float32", "colors"])
|
new Dataframe.KeyIndex(["int32", "string", "float32", "colors"])
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -330,7 +327,6 @@ describe("dataframe subsetting", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("all rows, two cols", () => {
|
test("all rows, two cols", () => {
|
||||||
// @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
|
|
||||||
const dfA = sourceDf.isubset(null, [1, 2]);
|
const dfA = sourceDf.isubset(null, [1, 2]);
|
||||||
expect(dfA.dims).toEqual([3, 2]);
|
expect(dfA.dims).toEqual([3, 2]);
|
||||||
expect(dfA.icol(0).asArray()).toEqual(["A", "B", "C"]);
|
expect(dfA.icol(0).asArray()).toEqual(["A", "B", "C"]);
|
||||||
@@ -376,7 +372,6 @@ describe("dataframe factories", () => {
|
|||||||
const dfA = new Dataframe.Dataframe(
|
const dfA = new Dataframe.Dataframe(
|
||||||
[3, 2],
|
[3, 2],
|
||||||
[new Int32Array([0, 1, 2]), new Int32Array([3, 4, 5])],
|
[new Int32Array([0, 1, 2]), new Int32Array([3, 4, 5])],
|
||||||
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'DenseInt32Index' is not assignab... Remove this comment to see the full error message
|
|
||||||
new Dataframe.DenseInt32Index([2, 1, 0]),
|
new Dataframe.DenseInt32Index([2, 1, 0]),
|
||||||
new Dataframe.KeyIndex(["A", "B"])
|
new Dataframe.KeyIndex(["A", "B"])
|
||||||
);
|
);
|
||||||
@@ -401,7 +396,6 @@ describe("dataframe factories", () => {
|
|||||||
[true, false],
|
[true, false],
|
||||||
],
|
],
|
||||||
null,
|
null,
|
||||||
// @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
|
|
||||||
new Dataframe.KeyIndex(["colors", "bools"])
|
new Dataframe.KeyIndex(["colors", "bools"])
|
||||||
);
|
);
|
||||||
const dfA = df.withCol("numbers", [1, 0]);
|
const dfA = df.withCol("numbers", [1, 0]);
|
||||||
@@ -425,7 +419,6 @@ describe("dataframe factories", () => {
|
|||||||
[true, false],
|
[true, false],
|
||||||
],
|
],
|
||||||
null,
|
null,
|
||||||
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'DenseInt32Index' is not assignab... Remove this comment to see the full error message
|
|
||||||
new Dataframe.DenseInt32Index([74, 75])
|
new Dataframe.DenseInt32Index([74, 75])
|
||||||
);
|
);
|
||||||
const dfA = df.withCol(72, [1, 0]);
|
const dfA = df.withCol(72, [1, 0]);
|
||||||
@@ -451,7 +444,6 @@ describe("dataframe factories", () => {
|
|||||||
[true, false],
|
[true, false],
|
||||||
],
|
],
|
||||||
null,
|
null,
|
||||||
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'DenseInt32Index' is not assignab... Remove this comment to see the full error message
|
|
||||||
new Dataframe.DenseInt32Index([74, 75])
|
new Dataframe.DenseInt32Index([74, 75])
|
||||||
);
|
);
|
||||||
const dfA = df.withCol(999, [1, 0]);
|
const dfA = df.withCol(999, [1, 0]);
|
||||||
@@ -560,7 +552,6 @@ describe("dataframe factories", () => {
|
|||||||
[1, 0],
|
[1, 0],
|
||||||
],
|
],
|
||||||
null,
|
null,
|
||||||
// @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
|
|
||||||
new Dataframe.KeyIndex(["colors", "bools", "numbers"])
|
new Dataframe.KeyIndex(["colors", "bools", "numbers"])
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -569,14 +560,11 @@ describe("dataframe factories", () => {
|
|||||||
[3, 1],
|
[3, 1],
|
||||||
[["red", "blue", "green"]],
|
[["red", "blue", "green"]],
|
||||||
null,
|
null,
|
||||||
// @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
|
|
||||||
new Dataframe.KeyIndex(["colorsA"])
|
new Dataframe.KeyIndex(["colorsA"])
|
||||||
);
|
);
|
||||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
|
||||||
expect(() => dfA.withColsFrom(dfB)).toThrow(RangeError);
|
expect(() => dfA.withColsFrom(dfB)).toThrow(RangeError);
|
||||||
|
|
||||||
/* duplicate labels should throw an error */
|
/* duplicate labels should throw an error */
|
||||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
|
||||||
expect(() => dfA.withColsFrom(dfA)).toThrow(Error);
|
expect(() => dfA.withColsFrom(dfA)).toThrow(Error);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -587,18 +575,15 @@ describe("dataframe factories", () => {
|
|||||||
[2, 1],
|
[2, 1],
|
||||||
[["red", "blue"]],
|
[["red", "blue"]],
|
||||||
null,
|
null,
|
||||||
// @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
|
|
||||||
new Dataframe.KeyIndex(["colors"])
|
new Dataframe.KeyIndex(["colors"])
|
||||||
);
|
);
|
||||||
const dfB = new Dataframe.Dataframe(
|
const dfB = new Dataframe.Dataframe(
|
||||||
[2, 1],
|
[2, 1],
|
||||||
[[true, false]],
|
[[true, false]],
|
||||||
null,
|
null,
|
||||||
// @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
|
|
||||||
new Dataframe.KeyIndex(["bools"])
|
new Dataframe.KeyIndex(["bools"])
|
||||||
);
|
);
|
||||||
|
|
||||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
|
||||||
const dfLikeA = dfEmpty.withColsFrom(dfA);
|
const dfLikeA = dfEmpty.withColsFrom(dfA);
|
||||||
expect(dfLikeA).toBeDefined();
|
expect(dfLikeA).toBeDefined();
|
||||||
expect(dfLikeA.dims).toEqual(dfA.dims);
|
expect(dfLikeA.dims).toEqual(dfA.dims);
|
||||||
@@ -607,7 +592,6 @@ describe("dataframe factories", () => {
|
|||||||
expect(dfLikeA.rowIndex.labels()).toEqual(dfA.rowIndex.labels());
|
expect(dfLikeA.rowIndex.labels()).toEqual(dfA.rowIndex.labels());
|
||||||
expect(dfLikeA.icol(0).asArray()).toEqual(dfA.icol(0).asArray());
|
expect(dfLikeA.icol(0).asArray()).toEqual(dfA.icol(0).asArray());
|
||||||
|
|
||||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
|
||||||
const dfAlsoLikeA = dfA.withColsFrom(dfEmpty);
|
const dfAlsoLikeA = dfA.withColsFrom(dfEmpty);
|
||||||
expect(dfAlsoLikeA).toBeDefined();
|
expect(dfAlsoLikeA).toBeDefined();
|
||||||
expect(dfAlsoLikeA.dims).toEqual(dfA.dims);
|
expect(dfAlsoLikeA.dims).toEqual(dfA.dims);
|
||||||
@@ -616,7 +600,6 @@ describe("dataframe factories", () => {
|
|||||||
expect(dfAlsoLikeA.rowIndex.labels()).toEqual(dfA.rowIndex.labels());
|
expect(dfAlsoLikeA.rowIndex.labels()).toEqual(dfA.rowIndex.labels());
|
||||||
expect(dfAlsoLikeA.icol(0).asArray()).toEqual(dfA.icol(0).asArray());
|
expect(dfAlsoLikeA.icol(0).asArray()).toEqual(dfA.icol(0).asArray());
|
||||||
|
|
||||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1.
|
|
||||||
const dfC = dfA.withColsFrom(dfB);
|
const dfC = dfA.withColsFrom(dfB);
|
||||||
expect(dfC).toBeDefined();
|
expect(dfC).toBeDefined();
|
||||||
expect(dfC.dims).toEqual([2, 2]);
|
expect(dfC.dims).toEqual([2, 2]);
|
||||||
@@ -633,7 +616,6 @@ describe("dataframe factories", () => {
|
|||||||
[2, 1],
|
[2, 1],
|
||||||
[["red", "blue"]],
|
[["red", "blue"]],
|
||||||
null,
|
null,
|
||||||
// @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
|
|
||||||
new Dataframe.KeyIndex(["colors"])
|
new Dataframe.KeyIndex(["colors"])
|
||||||
);
|
);
|
||||||
const dfB = new Dataframe.Dataframe(
|
const dfB = new Dataframe.Dataframe(
|
||||||
@@ -644,7 +626,6 @@ describe("dataframe factories", () => {
|
|||||||
[1, 0],
|
[1, 0],
|
||||||
],
|
],
|
||||||
null,
|
null,
|
||||||
// @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
|
|
||||||
new Dataframe.KeyIndex(["colors", "bools", "numbers"])
|
new Dataframe.KeyIndex(["colors", "bools", "numbers"])
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -677,7 +658,6 @@ describe("dataframe factories", () => {
|
|||||||
[2, 1],
|
[2, 1],
|
||||||
[["red", "blue"]],
|
[["red", "blue"]],
|
||||||
null,
|
null,
|
||||||
// @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
|
|
||||||
new Dataframe.KeyIndex(["colors"])
|
new Dataframe.KeyIndex(["colors"])
|
||||||
);
|
);
|
||||||
const dfB = new Dataframe.Dataframe(
|
const dfB = new Dataframe.Dataframe(
|
||||||
@@ -688,7 +668,6 @@ describe("dataframe factories", () => {
|
|||||||
[1, 0],
|
[1, 0],
|
||||||
],
|
],
|
||||||
null,
|
null,
|
||||||
// @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
|
|
||||||
new Dataframe.KeyIndex(["colors", "bools", "numbers"])
|
new Dataframe.KeyIndex(["colors", "bools", "numbers"])
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -712,7 +691,6 @@ describe("dataframe factories", () => {
|
|||||||
[1, 0],
|
[1, 0],
|
||||||
],
|
],
|
||||||
null,
|
null,
|
||||||
// @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
|
|
||||||
new Dataframe.KeyIndex(["colors", "bools", "numbers"])
|
new Dataframe.KeyIndex(["colors", "bools", "numbers"])
|
||||||
);
|
);
|
||||||
const dfA = df.dropCol("colors");
|
const dfA = df.dropCol("colors");
|
||||||
@@ -784,7 +762,6 @@ describe("dataframe factories", () => {
|
|||||||
[1, 0],
|
[1, 0],
|
||||||
],
|
],
|
||||||
null,
|
null,
|
||||||
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'DenseInt32Index' is not assignab... Remove this comment to see the full error message
|
|
||||||
new Dataframe.DenseInt32Index([102, 101, 100])
|
new Dataframe.DenseInt32Index([102, 101, 100])
|
||||||
);
|
);
|
||||||
const dfA = df.dropCol(101);
|
const dfA = df.dropCol(101);
|
||||||
@@ -811,8 +788,7 @@ describe("dataframe factories", () => {
|
|||||||
new Float64Array(3).fill(1.1),
|
new Float64Array(3).fill(1.1),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
const dfB = dfA.mapColumns((col, idx) => {
|
||||||
const dfB = dfA.mapColumns((col: any, idx: any) => {
|
|
||||||
expect(dfA.icol(idx).asArray()).toBe(col);
|
expect(dfA.icol(idx).asArray()).toBe(col);
|
||||||
return col;
|
return col;
|
||||||
});
|
});
|
||||||
@@ -855,7 +831,6 @@ describe("dataframe factories", () => {
|
|||||||
[1, 0],
|
[1, 0],
|
||||||
],
|
],
|
||||||
null,
|
null,
|
||||||
// @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
|
|
||||||
new Dataframe.KeyIndex(["A", "B"])
|
new Dataframe.KeyIndex(["A", "B"])
|
||||||
);
|
);
|
||||||
const dfB = dfA.renameCol("B", "C");
|
const dfB = dfA.renameCol("B", "C");
|
||||||
@@ -868,8 +843,7 @@ describe("dataframe factories", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("dataframe col", () => {
|
describe("dataframe col", () => {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
let df: Dataframe.Dataframe;
|
||||||
let df: any = null;
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
df = new Dataframe.Dataframe(
|
df = new Dataframe.Dataframe(
|
||||||
[2, 2],
|
[2, 2],
|
||||||
@@ -878,7 +852,6 @@ describe("dataframe col", () => {
|
|||||||
[1, 0],
|
[1, 0],
|
||||||
],
|
],
|
||||||
null,
|
null,
|
||||||
// @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
|
|
||||||
new Dataframe.KeyIndex(["A", "B"])
|
new Dataframe.KeyIndex(["A", "B"])
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -887,8 +860,8 @@ describe("dataframe col", () => {
|
|||||||
expect(df).toBeDefined();
|
expect(df).toBeDefined();
|
||||||
expect(df.col("A")).toBe(df.icol(0));
|
expect(df.col("A")).toBe(df.icol(0));
|
||||||
expect(df.col("B")).toBe(df.icol(1));
|
expect(df.col("B")).toBe(df.icol(1));
|
||||||
expect(df.col("undefined")).toBeUndefined();
|
expect(() => df.col("undefined")).toThrow(RangeError);
|
||||||
expect(df.icol("undefined")).toBeUndefined();
|
expect(() => df.icol("undefined" as unknown as number)).toThrow(RangeError);
|
||||||
|
|
||||||
const colA = df.col("A");
|
const colA = df.col("A");
|
||||||
expect(colA).toBeInstanceOf(Function);
|
expect(colA).toBeInstanceOf(Function);
|
||||||
@@ -942,13 +915,13 @@ describe("dataframe col", () => {
|
|||||||
expect(df.col("A").indexOf(true)).toEqual(0);
|
expect(df.col("A").indexOf(true)).toEqual(0);
|
||||||
expect(df.col("A").indexOf(false)).toEqual(1);
|
expect(df.col("A").indexOf(false)).toEqual(1);
|
||||||
expect(df.col("A").indexOf(99)).toBeUndefined();
|
expect(df.col("A").indexOf(99)).toBeUndefined();
|
||||||
expect(df.col("A").indexOf(undefined)).toBeUndefined();
|
expect(df.col("A").indexOf(undefined as unknown as number)).toBeUndefined();
|
||||||
expect(df.col("A").indexOf(1)).toBeUndefined();
|
expect(df.col("A").indexOf(1)).toBeUndefined();
|
||||||
|
|
||||||
expect(df.col("B").indexOf(1)).toEqual(0);
|
expect(df.col("B").indexOf(1)).toEqual(0);
|
||||||
expect(df.col("B").indexOf(0)).toEqual(1);
|
expect(df.col("B").indexOf(0)).toEqual(1);
|
||||||
expect(df.col("B").indexOf(99)).toBeUndefined();
|
expect(df.col("B").indexOf(99)).toBeUndefined();
|
||||||
expect(df.col("B").indexOf(undefined)).toBeUndefined();
|
expect(df.col("B").indexOf(undefined as unknown as number)).toBeUndefined();
|
||||||
expect(df.col("B").indexOf(true)).toBeUndefined();
|
expect(df.col("B").indexOf(true)).toBeUndefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -991,7 +964,7 @@ describe("label indexing", () => {
|
|||||||
|
|
||||||
test("offsets", () => {
|
test("offsets", () => {
|
||||||
expect(idx.getOffset(1)).toEqual(1);
|
expect(idx.getOffset(1)).toEqual(1);
|
||||||
expect(idx.getOffsets([1, 3])).toEqual([1, 3]);
|
expect(idx.getOffsets([1, 3])).toEqual(new Int32Array([1, 3]));
|
||||||
});
|
});
|
||||||
|
|
||||||
test("subset", () => {
|
test("subset", () => {
|
||||||
@@ -1069,7 +1042,7 @@ describe("label indexing", () => {
|
|||||||
false,
|
false,
|
||||||
])
|
])
|
||||||
.labels()
|
.labels()
|
||||||
).toEqual(new Int32Array([]));
|
).toEqual([]);
|
||||||
expect(
|
expect(
|
||||||
idx
|
idx
|
||||||
.isubsetMask([
|
.isubsetMask([
|
||||||
@@ -1163,16 +1136,14 @@ describe("label indexing", () => {
|
|||||||
expect(idx.labels()).toEqual(new Int32Array([99, 1002, 48, 0, 22]));
|
expect(idx.labels()).toEqual(new Int32Array([99, 1002, 48, 0, 22]));
|
||||||
expect(idx.size()).toEqual(5);
|
expect(idx.size()).toEqual(5);
|
||||||
expect(idx.getLabel(0)).toEqual(99);
|
expect(idx.getLabel(0)).toEqual(99);
|
||||||
expect(idx.getLabels(new Int32Array([2, 4]))).toEqual(
|
expect(idx.getLabels(new Int32Array([2, 4]))).toEqual([48, 22]);
|
||||||
new Int32Array([48, 22])
|
|
||||||
);
|
|
||||||
expect(idx.getLabels([2, 4])).toEqual([48, 22]);
|
expect(idx.getLabels([2, 4])).toEqual([48, 22]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("offsets", () => {
|
test("offsets", () => {
|
||||||
expect(idx.getOffset(1002)).toEqual(1);
|
expect(idx.getOffset(1002)).toEqual(1);
|
||||||
expect(idx.getOffset(0)).toEqual(3);
|
expect(idx.getOffset(0)).toEqual(3);
|
||||||
expect(idx.getOffsets([0, 48])).toEqual([3, 2]);
|
expect(idx.getOffsets([0, 48])).toEqual(new Int32Array([3, 2]));
|
||||||
});
|
});
|
||||||
|
|
||||||
test("subset", () => {
|
test("subset", () => {
|
||||||
@@ -1199,7 +1170,7 @@ describe("label indexing", () => {
|
|||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
idx.isubsetMask([false, false, false, false, false]).labels()
|
idx.isubsetMask([false, false, false, false, false]).labels()
|
||||||
).toEqual(new Int32Array([]));
|
).toEqual([]);
|
||||||
expect(idx.isubsetMask([true, true, false, true, true]).labels()).toEqual(
|
expect(idx.isubsetMask([true, true, false, true, true]).labels()).toEqual(
|
||||||
new Int32Array([99, 1002, 0, 22])
|
new Int32Array([99, 1002, 0, 22])
|
||||||
);
|
);
|
||||||
@@ -1301,59 +1272,67 @@ describe("corner cases", () => {
|
|||||||
const idx = new Dataframe.IdentityInt32Index(10);
|
const idx = new Dataframe.IdentityInt32Index(10);
|
||||||
expect(idx.getOffset(0)).toBe(0);
|
expect(idx.getOffset(0)).toBe(0);
|
||||||
expect(idx.getOffset(9)).toBe(9);
|
expect(idx.getOffset(9)).toBe(9);
|
||||||
expect(idx.getOffset(10)).toBeUndefined();
|
expect(idx.getOffset(10)).toBe(-1);
|
||||||
expect(idx.getOffset(-1)).toBeUndefined();
|
expect(idx.getOffset(-1)).toBe(-1);
|
||||||
expect(idx.getOffset("sort")).toBeUndefined();
|
expect(idx.getOffset("sort")).toBe(-1);
|
||||||
expect(idx.getOffset("length")).toBeUndefined();
|
expect(idx.getOffset("length")).toBe(-1);
|
||||||
expect(idx.getOffset(true)).toBeUndefined();
|
expect(idx.getOffset(true as unknown as string)).toBe(-1);
|
||||||
expect(idx.getOffset(0.001)).toBeUndefined();
|
expect(idx.getOffset(0.001)).toBe(-1);
|
||||||
expect(idx.getOffset({})).toBeUndefined();
|
expect(idx.getOffset({} as unknown as string)).toBe(-1);
|
||||||
expect(idx.getOffset([])).toBeUndefined();
|
expect(idx.getOffset([] as unknown as string)).toBe(-1);
|
||||||
expect(idx.getOffset(new Float32Array())).toBeUndefined();
|
expect(idx.getOffset(new Float32Array() as unknown as string)).toBe(-1);
|
||||||
expect(idx.getOffset("__proto__")).toBeUndefined();
|
expect(idx.getOffset("__proto__")).toBe(-1);
|
||||||
|
|
||||||
expect(idx.getLabel(0)).toBe(0);
|
expect(idx.getLabel(0)).toBe(0);
|
||||||
expect(idx.getLabel(9)).toBe(9);
|
expect(idx.getLabel(9)).toBe(9);
|
||||||
expect(idx.getLabel(10)).toBeUndefined();
|
expect(idx.getLabel(10)).toBeUndefined();
|
||||||
expect(idx.getLabel(-1)).toBeUndefined();
|
expect(idx.getLabel(-1)).toBeUndefined();
|
||||||
expect(idx.getLabel("sort")).toBeUndefined();
|
expect(idx.getLabel("sort" as unknown as number)).toBeUndefined();
|
||||||
expect(idx.getLabel("length")).toBeUndefined();
|
expect(idx.getLabel("length" as unknown as number)).toBeUndefined();
|
||||||
expect(idx.getLabel(true)).toBeUndefined();
|
expect(idx.getLabel(true as unknown as number)).toBeUndefined();
|
||||||
expect(idx.getLabel(0.001)).toBeUndefined();
|
expect(idx.getLabel(0.001)).toBeUndefined();
|
||||||
expect(idx.getLabel({})).toBeUndefined();
|
expect(idx.getLabel({} as unknown as number)).toBeUndefined();
|
||||||
expect(idx.getLabel([])).toBeUndefined();
|
expect(idx.getLabel([] as unknown as number)).toBeUndefined();
|
||||||
expect(idx.getLabel(new Float32Array())).toBeUndefined();
|
expect(
|
||||||
expect(idx.getLabel("__proto__")).toBeUndefined();
|
idx.getLabel(new Float32Array() as unknown as number)
|
||||||
|
).toBeUndefined();
|
||||||
|
expect(idx.getLabel("__proto__" as unknown as number)).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("dense integer index rejects non-integer labels", () => {
|
test("dense integer index rejects non-integer labels", () => {
|
||||||
const idx = new Dataframe.DenseInt32Index([-10, 0, 3, 9, 10]);
|
const idx = new Dataframe.DenseInt32Index([-10, 0, 3, 9, 10]);
|
||||||
|
expect(idx.getOffset(-10)).toBe(0);
|
||||||
expect(idx.getOffset(0)).toBe(1);
|
expect(idx.getOffset(0)).toBe(1);
|
||||||
|
expect(idx.getOffset(3)).toBe(2);
|
||||||
expect(idx.getOffset(9)).toBe(3);
|
expect(idx.getOffset(9)).toBe(3);
|
||||||
expect(idx.getOffset(1)).toBeUndefined();
|
expect(idx.getOffset(10)).toBe(4);
|
||||||
expect(idx.getOffset(11)).toBeUndefined();
|
|
||||||
expect(idx.getOffset(-1)).toBeUndefined();
|
expect(idx.getOffset(1)).toBe(-1);
|
||||||
expect(idx.getOffset("sort")).toBeUndefined();
|
expect(idx.getOffset(11)).toBe(-1);
|
||||||
expect(idx.getOffset("length")).toBeUndefined();
|
expect(idx.getOffset(-1)).toBe(-1);
|
||||||
expect(idx.getOffset(true)).toBeUndefined();
|
expect(idx.getOffset("sort")).toBe(-1);
|
||||||
expect(idx.getOffset(0.001)).toBeUndefined();
|
expect(idx.getOffset("length")).toBe(-1);
|
||||||
expect(idx.getOffset({})).toBeUndefined();
|
expect(idx.getOffset(true as unknown as string)).toBe(-1);
|
||||||
expect(idx.getOffset([])).toBeUndefined();
|
expect(idx.getOffset(0.001)).toBe(-1);
|
||||||
expect(idx.getOffset(new Float32Array())).toBeUndefined();
|
expect(idx.getOffset({} as unknown as string)).toBe(-1);
|
||||||
expect(idx.getOffset("__proto__")).toBeUndefined();
|
expect(idx.getOffset([] as unknown as string)).toBe(-1);
|
||||||
|
expect(idx.getOffset(new Float32Array() as unknown as string)).toBe(-1);
|
||||||
|
expect(idx.getOffset("__proto__")).toBe(-1);
|
||||||
|
|
||||||
expect(idx.getLabel(0)).toBe(-10);
|
expect(idx.getLabel(0)).toBe(-10);
|
||||||
expect(idx.getLabel(4)).toBe(10);
|
expect(idx.getLabel(4)).toBe(10);
|
||||||
expect(idx.getLabel(10)).toBeUndefined();
|
expect(idx.getLabel(10)).toBeUndefined();
|
||||||
expect(idx.getLabel(-1)).toBeUndefined();
|
expect(idx.getLabel(-1)).toBeUndefined();
|
||||||
expect(idx.getLabel("sort")).toBeUndefined();
|
expect(idx.getLabel("sort" as unknown as number)).toBeUndefined();
|
||||||
expect(idx.getLabel("length")).toBeUndefined();
|
expect(idx.getLabel("length" as unknown as number)).toBeUndefined();
|
||||||
expect(idx.getLabel(true)).toBeUndefined();
|
expect(idx.getLabel(true as unknown as number)).toBeUndefined();
|
||||||
expect(idx.getLabel(0.001)).toBeUndefined();
|
expect(idx.getLabel(0.001)).toBeUndefined();
|
||||||
expect(idx.getLabel({})).toBeUndefined();
|
expect(idx.getLabel({} as unknown as number)).toBeUndefined();
|
||||||
expect(idx.getLabel([])).toBeUndefined();
|
expect(idx.getLabel([] as unknown as number)).toBeUndefined();
|
||||||
expect(idx.getLabel(new Float32Array())).toBeUndefined();
|
expect(
|
||||||
expect(idx.getLabel("__proto__")).toBeUndefined();
|
idx.getLabel(new Float32Array() as unknown as number)
|
||||||
|
).toBeUndefined();
|
||||||
|
expect(idx.getLabel("__proto__" as unknown as number)).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Empty dataframe rejects bogus labels", () => {
|
test("Empty dataframe rejects bogus labels", () => {
|
||||||
@@ -1361,39 +1340,55 @@ describe("corner cases", () => {
|
|||||||
|
|
||||||
expect(df.hasCol("sort")).toBeFalsy();
|
expect(df.hasCol("sort")).toBeFalsy();
|
||||||
expect(df.hasCol(0)).toBeFalsy();
|
expect(df.hasCol(0)).toBeFalsy();
|
||||||
expect(df.hasCol(true)).toBeFalsy();
|
expect(df.hasCol(true as unknown as number)).toBeFalsy();
|
||||||
expect(df.hasCol(false)).toBeFalsy();
|
expect(df.hasCol(false as unknown as number)).toBeFalsy();
|
||||||
expect(df.hasCol([])).toBeFalsy();
|
expect(df.hasCol([] as unknown as number)).toBeFalsy();
|
||||||
expect(df.hasCol({})).toBeFalsy();
|
expect(df.hasCol({} as unknown as number)).toBeFalsy();
|
||||||
expect(df.hasCol(null)).toBeFalsy();
|
expect(df.hasCol(null as unknown as number)).toBeFalsy();
|
||||||
expect(df.hasCol(undefined)).toBeFalsy();
|
expect(df.hasCol(undefined as unknown as number)).toBeFalsy();
|
||||||
|
|
||||||
expect(df.col("sort")).toBeUndefined();
|
expect(() => df.col("sort")).toThrow(RangeError);
|
||||||
expect(df.col(0)).toBeUndefined();
|
expect(() => df.col(0)).toThrow(RangeError);
|
||||||
expect(df.col(true)).toBeUndefined();
|
expect(() => df.col(true as unknown as string)).toThrow(RangeError);
|
||||||
expect(df.col(false)).toBeUndefined();
|
expect(() => df.col(false as unknown as string)).toThrow(RangeError);
|
||||||
expect(df.col([])).toBeUndefined();
|
expect(() => df.col([] as unknown as string)).toThrow(RangeError);
|
||||||
expect(df.col({})).toBeUndefined();
|
expect(() => df.col({} as unknown as string)).toThrow(RangeError);
|
||||||
expect(df.col(null)).toBeUndefined();
|
expect(() => df.col(null as unknown as string)).toThrow(RangeError);
|
||||||
expect(df.col(undefined)).toBeUndefined();
|
expect(() => df.col(undefined as unknown as string)).toThrow(RangeError);
|
||||||
|
|
||||||
expect(df.icol("sort")).toBeUndefined();
|
expect(() => df.icol("sort" as unknown as number)).toThrow(RangeError);
|
||||||
expect(df.icol(0)).toBeUndefined();
|
expect(() => df.icol(0)).toThrow(RangeError);
|
||||||
expect(df.icol(true)).toBeUndefined();
|
expect(() => df.icol(true as unknown as number)).toThrow(RangeError);
|
||||||
expect(df.icol(false)).toBeUndefined();
|
expect(() => df.icol(false as unknown as number)).toThrow(RangeError);
|
||||||
expect(df.icol([])).toBeUndefined();
|
expect(() => df.icol([] as unknown as number)).toThrow(RangeError);
|
||||||
expect(df.icol({})).toBeUndefined();
|
expect(() => df.icol({} as unknown as number)).toThrow(RangeError);
|
||||||
expect(df.icol(null)).toBeUndefined();
|
expect(() => df.icol(null as unknown as number)).toThrow(RangeError);
|
||||||
expect(df.icol(undefined)).toBeUndefined();
|
expect(() => df.icol(undefined as unknown as number)).toThrow(RangeError);
|
||||||
|
|
||||||
expect(df.ihas("sort", "length")).toBeFalsy();
|
expect(
|
||||||
expect(df.ihas("0", "0")).toBeFalsy();
|
df.ihas("sort" as unknown as number, "length" as unknown as number)
|
||||||
expect(df.ihas("", "")).toBeFalsy();
|
).toBeFalsy();
|
||||||
expect(df.ihas(null, null)).toBeFalsy();
|
expect(
|
||||||
expect(df.ihas(undefined, undefined)).toBeFalsy();
|
df.ihas("0" as unknown as number, "0" as unknown as number)
|
||||||
expect(df.ihas(true, true)).toBeFalsy();
|
).toBeFalsy();
|
||||||
expect(df.ihas([], [])).toBeFalsy();
|
expect(
|
||||||
expect(df.ihas({}, {})).toBeFalsy();
|
df.ihas("" as unknown as number, "" as unknown as number)
|
||||||
|
).toBeFalsy();
|
||||||
|
expect(
|
||||||
|
df.ihas(null as unknown as number, null as unknown as number)
|
||||||
|
).toBeFalsy();
|
||||||
|
expect(
|
||||||
|
df.ihas(undefined as unknown as number, undefined as unknown as number)
|
||||||
|
).toBeFalsy();
|
||||||
|
expect(
|
||||||
|
df.ihas(true as unknown as number, true as unknown as number)
|
||||||
|
).toBeFalsy();
|
||||||
|
expect(
|
||||||
|
df.ihas([] as unknown as number, [] as unknown as number)
|
||||||
|
).toBeFalsy();
|
||||||
|
expect(
|
||||||
|
df.ihas({} as unknown as number, {} as unknown as number)
|
||||||
|
).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Dataframe rejects bogus labels", () => {
|
test("Dataframe rejects bogus labels", () => {
|
||||||
@@ -1404,58 +1399,64 @@ describe("corner cases", () => {
|
|||||||
[1, 0],
|
[1, 0],
|
||||||
],
|
],
|
||||||
null,
|
null,
|
||||||
// @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
|
|
||||||
new Dataframe.KeyIndex(["A", "B"])
|
new Dataframe.KeyIndex(["A", "B"])
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(df.hasCol("sort")).toBeFalsy();
|
expect(df.hasCol("sort")).toBeFalsy();
|
||||||
expect(df.hasCol("__proto__")).toBeFalsy();
|
expect(df.hasCol("__proto__")).toBeFalsy();
|
||||||
expect(df.hasCol(0)).toBeFalsy();
|
expect(df.hasCol(0)).toBeFalsy();
|
||||||
expect(df.hasCol(true)).toBeFalsy();
|
expect(df.hasCol(true as unknown as string)).toBeFalsy();
|
||||||
expect(df.hasCol(false)).toBeFalsy();
|
expect(df.hasCol(false as unknown as string)).toBeFalsy();
|
||||||
expect(df.hasCol([])).toBeFalsy();
|
expect(df.hasCol([] as unknown as string)).toBeFalsy();
|
||||||
expect(df.hasCol({})).toBeFalsy();
|
expect(df.hasCol({} as unknown as string)).toBeFalsy();
|
||||||
expect(df.hasCol(null)).toBeFalsy();
|
expect(df.hasCol(null as unknown as string)).toBeFalsy();
|
||||||
expect(df.hasCol(undefined)).toBeFalsy();
|
expect(df.hasCol(undefined as unknown as string)).toBeFalsy();
|
||||||
|
|
||||||
expect(df.col("sort")).toBeUndefined();
|
expect(() => df.col("sort")).toThrow(RangeError);
|
||||||
expect(df.col("__proto__")).toBeUndefined();
|
expect(() => df.col("__proto__")).toThrow(RangeError);
|
||||||
expect(df.col(0)).toBeUndefined();
|
expect(() => df.col(0)).toThrow(RangeError);
|
||||||
expect(df.col(true)).toBeUndefined();
|
expect(() => df.col(true as unknown as string)).toThrow(RangeError);
|
||||||
expect(df.col(false)).toBeUndefined();
|
expect(() => df.col(false as unknown as string)).toThrow(RangeError);
|
||||||
expect(df.col([])).toBeUndefined();
|
expect(() => df.col([] as unknown as string)).toThrow(RangeError);
|
||||||
expect(df.col({})).toBeUndefined();
|
expect(() => df.col({} as unknown as string)).toThrow(RangeError);
|
||||||
expect(df.col(null)).toBeUndefined();
|
expect(() => df.col(null as unknown as string)).toThrow(RangeError);
|
||||||
expect(df.col(undefined)).toBeUndefined();
|
expect(() => df.col(undefined as unknown as string)).toThrow(RangeError);
|
||||||
|
|
||||||
expect(df.icol("sort")).toBeUndefined();
|
expect(() => df.icol("sort" as unknown as number)).toThrow(RangeError);
|
||||||
expect(df.icol("__proto__")).toBeUndefined();
|
expect(() => df.icol("__proto__" as unknown as number)).toThrow(RangeError);
|
||||||
expect(df.icol(-1)).toBeUndefined();
|
expect(() => df.icol(-1)).toThrow(RangeError);
|
||||||
expect(df.icol(true)).toBeUndefined();
|
expect(() => df.icol(true as unknown as number)).toThrow(RangeError);
|
||||||
expect(df.icol(false)).toBeUndefined();
|
expect(() => df.icol(false as unknown as number)).toThrow(RangeError);
|
||||||
expect(df.icol([])).toBeUndefined();
|
expect(() => df.icol([] as unknown as number)).toThrow(RangeError);
|
||||||
expect(df.icol({})).toBeUndefined();
|
expect(() => df.icol({} as unknown as number)).toThrow(RangeError);
|
||||||
expect(df.icol(null)).toBeUndefined();
|
expect(() => df.icol(null as unknown as number)).toThrow(RangeError);
|
||||||
expect(df.icol(undefined)).toBeUndefined();
|
expect(() => df.icol(undefined as unknown as number)).toThrow(RangeError);
|
||||||
|
|
||||||
expect(df.ihas("sort", "length")).toBeFalsy();
|
expect(
|
||||||
expect(df.ihas("__proto__", "__proto__")).toBeFalsy();
|
df.ihas("sort" as unknown as number, "length" as unknown as number)
|
||||||
|
).toBeFalsy();
|
||||||
|
expect(
|
||||||
|
df.ihas(
|
||||||
|
"__proto__" as unknown as number,
|
||||||
|
"__proto__" as unknown as number
|
||||||
|
)
|
||||||
|
).toBeFalsy();
|
||||||
|
|
||||||
expect(df.ihas(-1, 0)).toBeFalsy();
|
expect(df.ihas(-1, 0)).toBeFalsy();
|
||||||
expect(df.ihas("0", 0)).toBeFalsy();
|
expect(df.ihas("0" as unknown as number, 0)).toBeFalsy();
|
||||||
expect(df.ihas("", 0)).toBeFalsy();
|
expect(df.ihas("" as unknown as number, 0)).toBeFalsy();
|
||||||
expect(df.ihas(null, 0)).toBeFalsy();
|
expect(df.ihas(null as unknown as number, 0)).toBeFalsy();
|
||||||
expect(df.ihas(undefined, 0)).toBeFalsy();
|
expect(df.ihas(undefined as unknown as number, 0)).toBeFalsy();
|
||||||
expect(df.ihas([], 0)).toBeFalsy();
|
expect(df.ihas([] as unknown as number, 0)).toBeFalsy();
|
||||||
expect(df.ihas({}, 0)).toBeFalsy();
|
expect(df.ihas({} as unknown as number, 0)).toBeFalsy();
|
||||||
|
|
||||||
expect(df.ihas(0, -1)).toBeFalsy();
|
expect(df.ihas(0, -1)).toBeFalsy();
|
||||||
expect(df.ihas(0, "0")).toBeFalsy();
|
expect(df.ihas(0, "0" as unknown as number)).toBeFalsy();
|
||||||
expect(df.ihas(0, "")).toBeFalsy();
|
expect(df.ihas(0, "" as unknown as number)).toBeFalsy();
|
||||||
expect(df.ihas(0, null)).toBeFalsy();
|
expect(df.ihas(0, null as unknown as number)).toBeFalsy();
|
||||||
expect(df.ihas(0, undefined)).toBeFalsy();
|
expect(df.ihas(0, undefined as unknown as number)).toBeFalsy();
|
||||||
expect(df.ihas(0, [])).toBeFalsy();
|
expect(df.ihas(0, [] as unknown as number)).toBeFalsy();
|
||||||
expect(df.ihas(0, {})).toBeFalsy();
|
expect(df.ihas(0, {} as unknown as number)).toBeFalsy();
|
||||||
|
|
||||||
expect(df.has("sort", "length")).toBeFalsy();
|
expect(df.has("sort", "length")).toBeFalsy();
|
||||||
expect(df.has("length", "sort")).toBeFalsy();
|
expect(df.has("length", "sort")).toBeFalsy();
|
||||||
@@ -1464,17 +1465,17 @@ describe("corner cases", () => {
|
|||||||
expect(df.has(-1, "A")).toBeFalsy();
|
expect(df.has(-1, "A")).toBeFalsy();
|
||||||
expect(df.has("0", "A")).toBeFalsy();
|
expect(df.has("0", "A")).toBeFalsy();
|
||||||
expect(df.has("", "A")).toBeFalsy();
|
expect(df.has("", "A")).toBeFalsy();
|
||||||
expect(df.has(null, "A")).toBeFalsy();
|
expect(df.has(null as unknown as string, "A")).toBeFalsy();
|
||||||
expect(df.has(undefined, "A")).toBeFalsy();
|
expect(df.has(undefined as unknown as string, "A")).toBeFalsy();
|
||||||
expect(df.has([], "A")).toBeFalsy();
|
expect(df.has([] as unknown as string, "A")).toBeFalsy();
|
||||||
expect(df.has({}, "A")).toBeFalsy();
|
expect(df.has({} as unknown as string, "A")).toBeFalsy();
|
||||||
|
|
||||||
expect(df.has(0, -1)).toBeFalsy();
|
expect(df.has(0, -1)).toBeFalsy();
|
||||||
expect(df.has(0, "0")).toBeFalsy();
|
expect(df.has(0, "0")).toBeFalsy();
|
||||||
expect(df.has(0, "")).toBeFalsy();
|
expect(df.has(0, "")).toBeFalsy();
|
||||||
expect(df.has(0, null)).toBeFalsy();
|
expect(df.has(0, null as unknown as string)).toBeFalsy();
|
||||||
expect(df.has(0, undefined)).toBeFalsy();
|
expect(df.has(0, undefined as unknown as string)).toBeFalsy();
|
||||||
expect(df.has(0, [])).toBeFalsy();
|
expect(df.has(0, [] as unknown as string)).toBeFalsy();
|
||||||
expect(df.has(0, {})).toBeFalsy();
|
expect(df.has(0, {} as unknown as string)).toBeFalsy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,11 +6,10 @@ describe("Dataframe column histogram", () => {
|
|||||||
[3, 3],
|
[3, 3],
|
||||||
[["n1", "n2", "n3"], ["c1", "c2", "c3"], new Int32Array([0, 1, 2])],
|
[["n1", "n2", "n3"], ["c1", "c2", "c3"], new Int32Array([0, 1, 2])],
|
||||||
null,
|
null,
|
||||||
// @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
|
|
||||||
new Dataframe.KeyIndex(["name", "cat", "value"])
|
new Dataframe.KeyIndex(["name", "cat", "value"])
|
||||||
);
|
);
|
||||||
|
|
||||||
const h1 = df.col("cat").histogram(df.col("name"));
|
const h1 = df.col("cat").histogramCategoricalBy(df.col("name"));
|
||||||
expect(h1).toMatchObject(
|
expect(h1).toMatchObject(
|
||||||
new Map([
|
new Map([
|
||||||
["n1", new Map([["c1", 1]])],
|
["n1", new Map([["c1", 1]])],
|
||||||
@@ -19,7 +18,9 @@ describe("Dataframe column histogram", () => {
|
|||||||
])
|
])
|
||||||
);
|
);
|
||||||
// memoized?
|
// memoized?
|
||||||
expect(df.col("cat").histogram(df.col("name"))).toMatchObject(h1);
|
expect(df.col("cat").histogramCategoricalBy(df.col("name"))).toMatchObject(
|
||||||
|
h1
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("continuous by categorical", () => {
|
test("continuous by categorical", () => {
|
||||||
@@ -27,11 +28,10 @@ describe("Dataframe column histogram", () => {
|
|||||||
[3, 3],
|
[3, 3],
|
||||||
[["n1", "n2", "n3"], ["c1", "c2", "c3"], new Int32Array([0, 1, 2])],
|
[["n1", "n2", "n3"], ["c1", "c2", "c3"], new Int32Array([0, 1, 2])],
|
||||||
null,
|
null,
|
||||||
// @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
|
|
||||||
new Dataframe.KeyIndex(["name", "cat", "value"])
|
new Dataframe.KeyIndex(["name", "cat", "value"])
|
||||||
);
|
);
|
||||||
|
|
||||||
const h1 = df.col("value").histogram(3, [0, 2], df.col("name"));
|
const h1 = df.col("value").histogramContinuousBy(3, [0, 2], df.col("name"));
|
||||||
expect(h1).toMatchObject(
|
expect(h1).toMatchObject(
|
||||||
new Map([
|
new Map([
|
||||||
["n1", [1, 0, 0]],
|
["n1", [1, 0, 0]],
|
||||||
@@ -40,9 +40,9 @@ describe("Dataframe column histogram", () => {
|
|||||||
])
|
])
|
||||||
);
|
);
|
||||||
// memoized?
|
// memoized?
|
||||||
expect(df.col("value").histogram(3, [0, 2], df.col("name"))).toMatchObject(
|
expect(
|
||||||
h1
|
df.col("value").histogramContinuousBy(3, [0, 2], df.col("name"))
|
||||||
);
|
).toMatchObject(h1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("categorical", () => {
|
test("categorical", () => {
|
||||||
@@ -50,11 +50,10 @@ describe("Dataframe column histogram", () => {
|
|||||||
[3, 3],
|
[3, 3],
|
||||||
[["n1", "n2", "n3"], ["c1", "c2", "c3"], new Int32Array([0, 1, 2])],
|
[["n1", "n2", "n3"], ["c1", "c2", "c3"], new Int32Array([0, 1, 2])],
|
||||||
null,
|
null,
|
||||||
// @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
|
|
||||||
new Dataframe.KeyIndex(["name", "cat", "value"])
|
new Dataframe.KeyIndex(["name", "cat", "value"])
|
||||||
);
|
);
|
||||||
|
|
||||||
const h1 = df.col("cat").histogram();
|
const h1 = df.col("cat").histogramCategorical();
|
||||||
expect(h1).toMatchObject(
|
expect(h1).toMatchObject(
|
||||||
new Map([
|
new Map([
|
||||||
["c1", 1],
|
["c1", 1],
|
||||||
@@ -63,7 +62,7 @@ describe("Dataframe column histogram", () => {
|
|||||||
])
|
])
|
||||||
);
|
);
|
||||||
// memoized?
|
// memoized?
|
||||||
expect(df.col("value").histogram(3, [0, 2])).toMatchObject(h1);
|
expect(df.col("cat").histogramCategorical()).toMatchObject(h1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("continuous", () => {
|
test("continuous", () => {
|
||||||
@@ -71,14 +70,13 @@ describe("Dataframe column histogram", () => {
|
|||||||
[3, 3],
|
[3, 3],
|
||||||
[["n1", "n2", "n3"], ["c1", "c2", "c3"], new Int32Array([0, 1, 2])],
|
[["n1", "n2", "n3"], ["c1", "c2", "c3"], new Int32Array([0, 1, 2])],
|
||||||
null,
|
null,
|
||||||
// @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
|
|
||||||
new Dataframe.KeyIndex(["name", "cat", "value"])
|
new Dataframe.KeyIndex(["name", "cat", "value"])
|
||||||
);
|
);
|
||||||
|
|
||||||
const h1 = df.col("value").histogram(3, [0, 2]);
|
const h1 = df.col("value").histogramContinuous(3, [0, 2]);
|
||||||
expect(h1).toMatchObject([1, 1, 1]);
|
expect(h1).toMatchObject([1, 1, 1]);
|
||||||
// memoized?
|
// memoized?
|
||||||
expect(df.col("value").histogram(3, [0, 2])).toMatchObject(h1);
|
expect(df.col("value").histogramContinuous(3, [0, 2])).toMatchObject(h1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("continuous thesholds correct", () => {
|
test("continuous thesholds correct", () => {
|
||||||
@@ -88,20 +86,11 @@ describe("Dataframe column histogram", () => {
|
|||||||
[new Int32Array(vals), new Float32Array(vals)]
|
[new Int32Array(vals), new Float32Array(vals)]
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(df.col(0).histogram(5, [0, 100])).toEqual([5, 1, 0, 0, 2]);
|
expect(df.col(0).histogramContinuous(5, [0, 100])).toEqual([5, 1, 0, 0, 2]);
|
||||||
expect(df.col(1).histogram(5, [0, 100])).toEqual([5, 1, 0, 0, 2]);
|
expect(df.col(1).histogramContinuous(5, [0, 100])).toEqual([5, 1, 0, 0, 2]);
|
||||||
expect(df.col(0).histogram(2, [0, 10])).toEqual([2, 2]);
|
expect(df.col(0).histogramContinuous(2, [0, 10])).toEqual([2, 2]);
|
||||||
expect(df.col(0).histogram(10, [0, 100])).toEqual([
|
expect(df.col(0).histogramContinuous(10, [0, 100])).toEqual([
|
||||||
3,
|
3, 2, 1, 0, 0, 0, 0, 0, 0, 2,
|
||||||
2,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
2,
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ function float32Conversion(f: any) {
|
|||||||
describe("Dataframe column summary", () => {
|
describe("Dataframe column summary", () => {
|
||||||
test("empty column test", () => {
|
test("empty column test", () => {
|
||||||
const df = Dataframe.Dataframe.create([0, 1], [[]]);
|
const df = Dataframe.Dataframe.create([0, 1], [[]]);
|
||||||
const summary = df.icol(0).summarize();
|
const summary = df.icol(0).summarizeCategorical();
|
||||||
expect(summary).toEqual(
|
expect(summary).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
categorical: true,
|
categorical: true,
|
||||||
@@ -31,7 +31,6 @@ describe("Dataframe column summary", () => {
|
|||||||
[1],
|
[1],
|
||||||
],
|
],
|
||||||
null,
|
null,
|
||||||
// @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
|
|
||||||
new Dataframe.KeyIndex([
|
new Dataframe.KeyIndex([
|
||||||
"name",
|
"name",
|
||||||
"nameString",
|
"nameString",
|
||||||
@@ -42,7 +41,7 @@ describe("Dataframe column summary", () => {
|
|||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(df.icol(0).summarize()).toEqual(
|
expect(df.icol(0).summarizeCategorical()).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
categorical: true,
|
categorical: true,
|
||||||
categories: ["n1"],
|
categories: ["n1"],
|
||||||
@@ -50,7 +49,7 @@ describe("Dataframe column summary", () => {
|
|||||||
numCategories: 1,
|
numCategories: 1,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
expect(df.icol(1).summarize()).toEqual(
|
expect(df.icol(1).summarizeCategorical()).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
categorical: true,
|
categorical: true,
|
||||||
categories: ["hi"],
|
categories: ["hi"],
|
||||||
@@ -58,7 +57,7 @@ describe("Dataframe column summary", () => {
|
|||||||
numCategories: 1,
|
numCategories: 1,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
expect(df.icol(2).summarize()).toEqual(
|
expect(df.icol(2).summarizeCategorical()).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
categorical: true,
|
categorical: true,
|
||||||
categories: [true],
|
categories: [true],
|
||||||
@@ -66,7 +65,7 @@ describe("Dataframe column summary", () => {
|
|||||||
numCategories: 1,
|
numCategories: 1,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
expect(df.icol(3).summarize()).toEqual(
|
expect(df.icol(3).summarizeContinuous()).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
categorical: false,
|
categorical: false,
|
||||||
min: float32Conversion(39.3),
|
min: float32Conversion(39.3),
|
||||||
@@ -76,7 +75,7 @@ describe("Dataframe column summary", () => {
|
|||||||
pinf: 0,
|
pinf: 0,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
expect(df.icol(4).summarize()).toEqual(
|
expect(df.icol(4).summarizeContinuous()).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
categorical: false,
|
categorical: false,
|
||||||
min: 99,
|
min: 99,
|
||||||
@@ -86,7 +85,7 @@ describe("Dataframe column summary", () => {
|
|||||||
pinf: 0,
|
pinf: 0,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
expect(df.icol(5).summarize()).toEqual(
|
expect(df.icol(5).summarizeCategorical()).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
categorical: true,
|
categorical: true,
|
||||||
categories: [1],
|
categories: [1],
|
||||||
@@ -108,7 +107,6 @@ describe("Dataframe column summary", () => {
|
|||||||
[1, false, "0"],
|
[1, false, "0"],
|
||||||
],
|
],
|
||||||
null,
|
null,
|
||||||
// @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
|
|
||||||
new Dataframe.KeyIndex([
|
new Dataframe.KeyIndex([
|
||||||
"name",
|
"name",
|
||||||
"nameString",
|
"nameString",
|
||||||
@@ -119,7 +117,7 @@ describe("Dataframe column summary", () => {
|
|||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(df.icol(0).summarize()).toEqual(
|
expect(df.icol(0).summarizeCategorical()).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
categorical: true,
|
categorical: true,
|
||||||
categories: expect.arrayContaining(["n0", "n1", "n2"]),
|
categories: expect.arrayContaining(["n0", "n1", "n2"]),
|
||||||
@@ -131,7 +129,7 @@ describe("Dataframe column summary", () => {
|
|||||||
numCategories: 3,
|
numCategories: 3,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
expect(df.icol(1).summarize()).toEqual(
|
expect(df.icol(1).summarizeCategorical()).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
categorical: true,
|
categorical: true,
|
||||||
categories: expect.arrayContaining(["hi", "bye"]),
|
categories: expect.arrayContaining(["hi", "bye"]),
|
||||||
@@ -142,7 +140,7 @@ describe("Dataframe column summary", () => {
|
|||||||
numCategories: 2,
|
numCategories: 2,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
expect(df.icol(2).summarize()).toEqual(
|
expect(df.icol(2).summarizeCategorical()).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
categorical: true,
|
categorical: true,
|
||||||
categories: expect.arrayContaining([true, false]),
|
categories: expect.arrayContaining([true, false]),
|
||||||
@@ -153,7 +151,7 @@ describe("Dataframe column summary", () => {
|
|||||||
numCategories: 2,
|
numCategories: 2,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
expect(df.icol(3).summarize()).toEqual(
|
expect(df.icol(3).summarizeContinuous()).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
categorical: false,
|
categorical: false,
|
||||||
min: 0,
|
min: 0,
|
||||||
@@ -163,7 +161,7 @@ describe("Dataframe column summary", () => {
|
|||||||
pinf: 0,
|
pinf: 0,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
expect(df.icol(4).summarize()).toEqual(
|
expect(df.icol(4).summarizeContinuous()).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
categorical: false,
|
categorical: false,
|
||||||
min: 99,
|
min: 99,
|
||||||
@@ -173,7 +171,7 @@ describe("Dataframe column summary", () => {
|
|||||||
pinf: 0,
|
pinf: 0,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
expect(df.icol(5).summarize()).toEqual(
|
expect(df.icol(5).summarizeCategorical()).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
categorical: true,
|
categorical: true,
|
||||||
categories: expect.arrayContaining([1, false, "0"]),
|
categories: expect.arrayContaining([1, false, "0"]),
|
||||||
@@ -205,7 +203,6 @@ describe("Dataframe column summary", () => {
|
|||||||
[1, false, "0", "0"],
|
[1, false, "0", "0"],
|
||||||
],
|
],
|
||||||
null,
|
null,
|
||||||
// @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
|
|
||||||
new Dataframe.KeyIndex([
|
new Dataframe.KeyIndex([
|
||||||
"name",
|
"name",
|
||||||
"nameString",
|
"nameString",
|
||||||
@@ -216,7 +213,7 @@ describe("Dataframe column summary", () => {
|
|||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(df.icol(0).summarize()).toEqual(
|
expect(df.icol(0).summarizeCategorical()).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
categorical: true,
|
categorical: true,
|
||||||
categories: expect.arrayContaining(["n0", "n1", "n2"]),
|
categories: expect.arrayContaining(["n0", "n1", "n2"]),
|
||||||
@@ -228,7 +225,7 @@ describe("Dataframe column summary", () => {
|
|||||||
numCategories: 3,
|
numCategories: 3,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
expect(df.icol(1).summarize()).toEqual(
|
expect(df.icol(1).summarizeCategorical()).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
categorical: true,
|
categorical: true,
|
||||||
categories: expect.arrayContaining(["hi", "bye"]),
|
categories: expect.arrayContaining(["hi", "bye"]),
|
||||||
@@ -239,7 +236,7 @@ describe("Dataframe column summary", () => {
|
|||||||
numCategories: 2,
|
numCategories: 2,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
expect(df.icol(2).summarize()).toEqual(
|
expect(df.icol(2).summarizeCategorical()).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
categorical: true,
|
categorical: true,
|
||||||
categories: expect.arrayContaining([true, false]),
|
categories: expect.arrayContaining([true, false]),
|
||||||
@@ -250,7 +247,7 @@ describe("Dataframe column summary", () => {
|
|||||||
numCategories: 2,
|
numCategories: 2,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
expect(df.icol(3).summarize()).toEqual(
|
expect(df.icol(3).summarizeContinuous()).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
categorical: false,
|
categorical: false,
|
||||||
min: float32Conversion(39.3),
|
min: float32Conversion(39.3),
|
||||||
@@ -260,7 +257,7 @@ describe("Dataframe column summary", () => {
|
|||||||
pinf: 1,
|
pinf: 1,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
expect(df.icol(4).summarize()).toEqual(
|
expect(df.icol(4).summarizeContinuous()).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
categorical: false,
|
categorical: false,
|
||||||
min: 99,
|
min: 99,
|
||||||
@@ -270,7 +267,7 @@ describe("Dataframe column summary", () => {
|
|||||||
pinf: 0,
|
pinf: 0,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
expect(df.icol(5).summarize()).toEqual(
|
expect(df.icol(5).summarizeCategorical()).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
categorical: true,
|
categorical: true,
|
||||||
categories: expect.arrayContaining([1, false, "0"]),
|
categories: expect.arrayContaining([1, false, "0"]),
|
||||||
|
|||||||
@@ -81,7 +81,6 @@ describe("categorical color helpers", () => {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
null,
|
null,
|
||||||
// @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
|
|
||||||
new Dataframe.KeyIndex(["continuousColumn", "categoricalColumn"])
|
new Dataframe.KeyIndex(["continuousColumn", "categoricalColumn"])
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ describe("encode/decode", () => {
|
|||||||
expect(dfA.columns).toEqual(columns);
|
expect(dfA.columns).toEqual(columns);
|
||||||
|
|
||||||
const colIndex = new KeyIndex(["a", "b", "c", "d"]);
|
const colIndex = new KeyIndex(["a", "b", "c", "d"]);
|
||||||
// @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 dfWithColIdx = new Dataframe([3, 4], columns, null, colIndex);
|
const dfWithColIdx = new Dataframe([3, 4], columns, null, colIndex);
|
||||||
const dfB = decodeMatrixFBS(encodeMatrixFBS(dfWithColIdx));
|
const dfB = decodeMatrixFBS(encodeMatrixFBS(dfWithColIdx));
|
||||||
expect([dfB.nRows, dfB.nCols]).toEqual(dfWithColIdx.dims);
|
expect([dfB.nRows, dfB.nCols]).toEqual(dfWithColIdx.dims);
|
||||||
|
|||||||
@@ -21,90 +21,90 @@ The behavior manifest in these action creators:
|
|||||||
Note that crossfilter indices are lazy created, as needed.
|
Note that crossfilter indices are lazy created, as needed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
import { Dataframe } from "../util/dataframe";
|
||||||
export const genesetDelete = (genesetName: any) => (
|
|
||||||
|
export const genesetDelete =
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||||
dispatch: any,
|
(genesetName: any) => (dispatch: any, getState: any) => {
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
const state = getState();
|
||||||
getState: any
|
const { genesets } = state;
|
||||||
) => {
|
const gs = genesets?.genesets?.get(genesetName) ?? {};
|
||||||
const state = getState();
|
const geneSymbols = Array.from(gs.genes.keys());
|
||||||
const { genesets } = state;
|
const obsCrossfilter = dropGeneset(
|
||||||
const gs = genesets?.genesets?.get(genesetName) ?? {};
|
dispatch,
|
||||||
const geneSymbols = Array.from(gs.genes.keys());
|
state,
|
||||||
const obsCrossfilter = dropGeneset(dispatch, state, genesetName, geneSymbols);
|
genesetName,
|
||||||
if (genesetName === state.colors.colorAccessor) {
|
geneSymbols
|
||||||
|
);
|
||||||
|
if (genesetName === state.colors.colorAccessor) {
|
||||||
|
dispatch({
|
||||||
|
type: "reset colorscale",
|
||||||
|
});
|
||||||
|
}
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "reset colorscale",
|
type: "geneset: delete",
|
||||||
|
genesetName,
|
||||||
|
obsCrossfilter,
|
||||||
|
annoMatrix: obsCrossfilter.annoMatrix,
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
dispatch({
|
|
||||||
type: "geneset: delete",
|
|
||||||
genesetName,
|
|
||||||
obsCrossfilter,
|
|
||||||
annoMatrix: obsCrossfilter.annoMatrix,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
export const genesetAddGenes =
|
||||||
export const genesetAddGenes = (genesetName: any, genes: any) => async (
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||||
dispatch: any,
|
(genesetName: any, genes: any) => async (dispatch: any, getState: any) => {
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
const state = getState();
|
||||||
getState: any
|
const { obsCrossfilter: prevObsCrossfilter, annoMatrix } = state;
|
||||||
) => {
|
const { schema } = annoMatrix;
|
||||||
const state = getState();
|
const varIndex = schema.annotations.var.index;
|
||||||
const { obsCrossfilter: prevObsCrossfilter, annoMatrix } = state;
|
const df: Dataframe = await annoMatrix.fetch("var", varIndex);
|
||||||
const { schema } = annoMatrix;
|
const geneNames = df.col(varIndex).asArray();
|
||||||
const varIndex = schema.annotations.var.index;
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||||
const df = await annoMatrix.fetch("var", varIndex);
|
genes = genes.reduce((acc: any, gene: any) => {
|
||||||
const geneNames = df.col(varIndex).asArray();
|
if (geneNames.indexOf(gene.geneSymbol) === -1) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
postUserErrorToast(
|
||||||
genes = genes.reduce((acc: any, gene: any) => {
|
`${gene.geneSymbol} doesn't appear to be a valid gene name.`
|
||||||
if (geneNames.indexOf(gene.geneSymbol) === -1) {
|
);
|
||||||
postUserErrorToast(
|
} else acc.push(gene);
|
||||||
`${gene.geneSymbol} doesn't appear to be a valid gene name.`
|
return acc;
|
||||||
);
|
}, []);
|
||||||
} else acc.push(gene);
|
|
||||||
return acc;
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const obsCrossfilter = dropGenesetSummaryDimension(
|
const obsCrossfilter = dropGenesetSummaryDimension(
|
||||||
prevObsCrossfilter,
|
prevObsCrossfilter,
|
||||||
state,
|
state,
|
||||||
genesetName
|
genesetName
|
||||||
);
|
);
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "continuous metadata histogram cancel",
|
type: "continuous metadata histogram cancel",
|
||||||
continuousNamespace: { isGeneSetSummary: true },
|
continuousNamespace: { isGeneSetSummary: true },
|
||||||
selection: genesetName,
|
selection: genesetName,
|
||||||
});
|
});
|
||||||
return dispatch({
|
return dispatch({
|
||||||
type: "geneset: add genes",
|
type: "geneset: add genes",
|
||||||
genesetName,
|
genesetName,
|
||||||
genes,
|
genes,
|
||||||
obsCrossfilter,
|
obsCrossfilter,
|
||||||
annoMatrix: obsCrossfilter.annoMatrix,
|
annoMatrix: obsCrossfilter.annoMatrix,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
export const genesetDeleteGenes =
|
||||||
export const genesetDeleteGenes = (genesetName: any, geneSymbols: any) => (
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||||
dispatch: any,
|
(genesetName: any, geneSymbols: any) => (dispatch: any, getState: any) => {
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
const state = getState();
|
||||||
getState: any
|
const obsCrossfilter = dropGeneset(
|
||||||
) => {
|
dispatch,
|
||||||
const state = getState();
|
state,
|
||||||
const obsCrossfilter = dropGeneset(dispatch, state, genesetName, geneSymbols);
|
genesetName,
|
||||||
return dispatch({
|
geneSymbols
|
||||||
type: "geneset: delete genes",
|
);
|
||||||
genesetName,
|
return dispatch({
|
||||||
geneSymbols,
|
type: "geneset: delete genes",
|
||||||
obsCrossfilter,
|
genesetName,
|
||||||
annoMatrix: obsCrossfilter.annoMatrix,
|
geneSymbols,
|
||||||
});
|
obsCrossfilter,
|
||||||
};
|
annoMatrix: obsCrossfilter.annoMatrix,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Private
|
Private
|
||||||
|
|||||||
@@ -219,7 +219,7 @@ export default class AnnoMatrix {
|
|||||||
**/
|
**/
|
||||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type.
|
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type.
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
||||||
fetch(field, q) {
|
fetch(field, q): Dataframe {
|
||||||
/*
|
/*
|
||||||
Return the given query on a single matrix field as a single dataframe.
|
Return the given query on a single matrix field as a single dataframe.
|
||||||
Currently supports ONLY full column query.
|
Currently supports ONLY full column query.
|
||||||
@@ -248,7 +248,7 @@ export default class AnnoMatrix {
|
|||||||
1. Fetch the "n_genes" column the "obs":
|
1. Fetch the "n_genes" column the "obs":
|
||||||
|
|
||||||
const df = await fetch("obs", "n_genes")
|
const df = await fetch("obs", "n_genes")
|
||||||
console.log("Largest number of genes is: ", df.summarize().max);
|
console.log("Largest number of genes is: ", df.summarizeContinuous().max);
|
||||||
|
|
||||||
2. Fetch two separate columns from obs. Returns a single dataframe containing
|
2. Fetch two separate columns from obs. Returns a single dataframe containing
|
||||||
the columns:
|
the columns:
|
||||||
@@ -278,7 +278,7 @@ export default class AnnoMatrix {
|
|||||||
|
|
||||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type.
|
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type.
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
||||||
prefetch(field, q) {
|
prefetch(field, q): void {
|
||||||
/*
|
/*
|
||||||
Start a data fetch & cache fill. Identical to fetch() except it does
|
Start a data fetch & cache fill. Identical to fetch() except it does
|
||||||
not return a value.
|
not return a value.
|
||||||
@@ -287,7 +287,6 @@ export default class AnnoMatrix {
|
|||||||
overall component rendering latency.
|
overall component rendering latency.
|
||||||
*/
|
*/
|
||||||
this._fetch(field, q);
|
this._fetch(field, q);
|
||||||
return undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -494,8 +493,8 @@ Return cache keys for columns associated with this query. May return
|
|||||||
|
|
||||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type.
|
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type.
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
||||||
async _fetch(field, q) {
|
async _fetch(field, q): Dataframe {
|
||||||
if (!AnnoMatrix.fields().includes(field)) return undefined;
|
if (!AnnoMatrix.fields().includes(field)) return Dataframe.empty();
|
||||||
const queries = Array.isArray(q) ? q : [q];
|
const queries = Array.isArray(q) ? q : [q];
|
||||||
queries.forEach(_queryValidate);
|
queries.forEach(_queryValidate);
|
||||||
|
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
|
|||||||
const data = (this as any)._cache.obs.col(col).asArray().slice();
|
const data = (this as any)._cache.obs.col(col).asArray().slice();
|
||||||
for (let i = 0, len = rowIndices.length; i < len; i += 1) {
|
for (let i = 0, len = rowIndices.length; i < len; i += 1) {
|
||||||
const idx = rowIndices[i];
|
const idx = rowIndices[i];
|
||||||
if (idx === undefined) throw new Error("Unknown row label");
|
if (idx === -1) throw new Error("Unknown row label");
|
||||||
data[idx] = value;
|
data[idx] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,8 +299,8 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
|
|||||||
default:
|
default:
|
||||||
throw new Error("Unknown field name");
|
throw new Error("Unknown field name");
|
||||||
}
|
}
|
||||||
|
|
||||||
const buffer = await promiseThrottle.priorityAdd(priority, doRequest);
|
const buffer = await promiseThrottle.priorityAdd(priority, doRequest);
|
||||||
|
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'unknown' is not assignable to parameter of type 'ArrayBuffer | ArrayBuffer[]'.... Remove this comment to see the full error message
|
||||||
let result = matrixFBSToDataframe(buffer);
|
let result = matrixFBSToDataframe(buffer);
|
||||||
if (!result || result.isEmpty()) throw Error("Unknown field/col");
|
if (!result || result.isEmpty()) throw Error("Unknown field/col");
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { Schema } from "../common/types/schema";
|
||||||
import { _getColumnSchema, _isIndex } from "./schema";
|
import { _getColumnSchema, _isIndex } from "./schema";
|
||||||
import catLabelSort from "../util/catLabelSort";
|
import catLabelSort from "../util/catLabelSort";
|
||||||
import {
|
import {
|
||||||
@@ -5,12 +6,11 @@ import {
|
|||||||
overflowCategoryLabel,
|
overflowCategoryLabel,
|
||||||
globalConfig,
|
globalConfig,
|
||||||
} from "../globals";
|
} from "../globals";
|
||||||
import { Dataframe } from "../util/dataframe";
|
import { Dataframe, LabelType, DataframeColumn } from "../util/dataframe";
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
|
||||||
export function normalizeResponse(
|
export function normalizeResponse(
|
||||||
field: string,
|
field: string,
|
||||||
schema: any, // eslint-disable-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
schema: Schema,
|
||||||
response: Dataframe
|
response: Dataframe
|
||||||
): Dataframe {
|
): Dataframe {
|
||||||
/**
|
/**
|
||||||
@@ -65,8 +65,7 @@ export function normalizeResponse(
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
function castColumnToBoolean(df: Dataframe, label: LabelType): Dataframe {
|
||||||
function castColumnToBoolean(df: Dataframe, label: any): Dataframe {
|
|
||||||
const colData = df.col(label).asArray();
|
const colData = df.col(label).asArray();
|
||||||
const newColData = new Array(colData.length);
|
const newColData = new Array(colData.length);
|
||||||
for (let i = 0; i < colData.length; i += 1) newColData[i] = !!colData[i];
|
for (let i = 0; i < colData.length; i += 1) newColData[i] = !!colData[i];
|
||||||
@@ -75,7 +74,10 @@ function castColumnToBoolean(df: Dataframe, label: any): Dataframe {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||||
export function normalizeWritableCategoricalSchema(colSchema: any, col: any) {
|
export function normalizeWritableCategoricalSchema(
|
||||||
|
colSchema: any, // eslint-disable-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||||
|
col: DataframeColumn
|
||||||
|
) {
|
||||||
/*
|
/*
|
||||||
Ensure all enum writable / categorical schema have a categories array, that
|
Ensure all enum writable / categorical schema have a categories array, that
|
||||||
the categories array contains all unique values in the data array, AND that
|
the categories array contains all unique values in the data array, AND that
|
||||||
@@ -91,12 +93,11 @@ export function normalizeWritableCategoricalSchema(colSchema: any, col: any) {
|
|||||||
return colSchema;
|
return colSchema;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
|
||||||
export function normalizeCategorical(
|
export function normalizeCategorical(
|
||||||
df: Dataframe,
|
df: Dataframe,
|
||||||
colLabel: any, // eslint-disable-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
colLabel: LabelType,
|
||||||
colSchema: any // eslint-disable-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
colSchema: any // eslint-disable-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||||
) {
|
): Dataframe {
|
||||||
/*
|
/*
|
||||||
If writable, ensure schema matches data and we have an unassigned label
|
If writable, ensure schema matches data and we have an unassigned label
|
||||||
|
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ function _clipAnnoMatrix(field, colLabel, colSchema, colData, df, qmin, qmax) {
|
|||||||
if (qmax > 1) qmax = 1;
|
if (qmax > 1) qmax = 1;
|
||||||
if (qmin === 0 && qmax === 1) return colData;
|
if (qmin === 0 && qmax === 1) return colData;
|
||||||
|
|
||||||
const quantiles = df.col(colLabel).summarize().percentiles;
|
const quantiles = df.col(colLabel).summarizeContinuous().percentiles;
|
||||||
const lower = quantiles[100 * qmin];
|
const lower = quantiles[100 * qmin];
|
||||||
const upper = quantiles[100 * qmax];
|
const upper = quantiles[100 * qmax];
|
||||||
const clippedData = clip(colData.slice(), lower, upper, Number.NaN);
|
const clippedData = clip(colData.slice(), lower, upper, Number.NaN);
|
||||||
|
|||||||
@@ -30,6 +30,22 @@ export type TypedArrayConstructor =
|
|||||||
|
|
||||||
export type AnyArray = Array<unknown> | TypedArray;
|
export type AnyArray = Array<unknown> | TypedArray;
|
||||||
|
|
||||||
|
export interface GenericArrayConstructor<T extends AnyArray> {
|
||||||
|
new (
|
||||||
|
...args: ConstructorParameters<
|
||||||
|
typeof Int8Array &
|
||||||
|
typeof Uint8Array &
|
||||||
|
typeof Int16Array &
|
||||||
|
typeof Uint16Array &
|
||||||
|
typeof Int32Array &
|
||||||
|
typeof Uint32Array &
|
||||||
|
typeof Float32Array &
|
||||||
|
typeof Float64Array &
|
||||||
|
typeof Array
|
||||||
|
>
|
||||||
|
): T;
|
||||||
|
}
|
||||||
|
|
||||||
export type NumberArray = Array<number> | TypedArray;
|
export type NumberArray = Array<number> | TypedArray;
|
||||||
|
|
||||||
export type Int8 = Int8Array[0];
|
export type Int8 = Int8Array[0];
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import Histogram from "./histogram";
|
|||||||
import HistogramFooter from "./footer";
|
import HistogramFooter from "./footer";
|
||||||
import StillLoading from "./loading";
|
import StillLoading from "./loading";
|
||||||
import ErrorLoading from "./error";
|
import ErrorLoading from "./error";
|
||||||
|
import { Dataframe } from "../../util/dataframe";
|
||||||
|
|
||||||
const MARGIN = {
|
const MARGIN = {
|
||||||
LEFT: 10, // Space for 0 tick label on X axis
|
LEFT: 10, // Space for 0 tick label on X axis
|
||||||
@@ -116,9 +117,12 @@ class HistogramBrush extends React.PureComponent {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// @ts-expect-error ts-migrate(6133) FIXME: 'selection' is declared but its value is never rea... Remove this comment to see the full error message
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||||
onBrushEnd = (selection: any, x: any) =>
|
onBrushEnd =
|
||||||
|
(
|
||||||
|
_selection: any, // eslint-disable-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||||
|
x: any // eslint-disable-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||||
|
) =>
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
||||||
() => {
|
() => {
|
||||||
const {
|
const {
|
||||||
@@ -257,18 +261,18 @@ class HistogramBrush extends React.PureComponent {
|
|||||||
|
|
||||||
const query = this.createQuery();
|
const query = this.createQuery();
|
||||||
// @ts-expect-error ts-migrate(2488) FIXME: Type 'any[] | null' must have a '[Symbol.iterator]... Remove this comment to see the full error message
|
// @ts-expect-error ts-migrate(2488) FIXME: Type 'any[] | null' must have a '[Symbol.iterator]... Remove this comment to see the full error message
|
||||||
const df = await annoMatrix.fetch(...query);
|
const df: Dataframe = await annoMatrix.fetch(...query);
|
||||||
const column = df.icol(0);
|
const column = df.icol(0);
|
||||||
|
|
||||||
// if we are clipped, fetch both our value and our unclipped value,
|
// if we are clipped, fetch both our value and our unclipped value,
|
||||||
// as we need the absolute min/max range, not just the clipped min/max.
|
// as we need the absolute min/max range, not just the clipped min/max.
|
||||||
const summary = column.summarize();
|
const summary = column.summarizeContinuous();
|
||||||
const range = [summary.min, summary.max];
|
const range = [summary.min, summary.max];
|
||||||
|
|
||||||
let unclippedRange = [...range];
|
let unclippedRange = [...range];
|
||||||
if (isClipped) {
|
if (isClipped) {
|
||||||
const parent = await annoMatrix.viewOf.fetch(...query);
|
const parent: Dataframe = await annoMatrix.viewOf.fetch(...query);
|
||||||
const { min, max } = parent.icol(0).summarize();
|
const { min, max } = parent.icol(0).summarizeContinuous();
|
||||||
unclippedRange = [min, max];
|
unclippedRange = [min, max];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,7 +324,8 @@ class HistogramBrush extends React.PureComponent {
|
|||||||
recalculate expensive stuff, notably bins, summaries, etc.
|
recalculate expensive stuff, notably bins, summaries, etc.
|
||||||
*/
|
*/
|
||||||
const histogramCache = {}; /* maybe change this so that it computes ... */
|
const histogramCache = {}; /* maybe change this so that it computes ... */
|
||||||
const summary = col.summarize(); /* this is memoized, so it's free the second time you call it */
|
const summary =
|
||||||
|
col.summarizeContinuous(); /* this is memoized, so it's free the second time you call it */
|
||||||
const { min: domainMin, max: domainMax } = summary;
|
const { min: domainMin, max: domainMax } = summary;
|
||||||
const numBins = 40;
|
const numBins = 40;
|
||||||
const { TOP: topMargin, LEFT: leftMargin } = newMargin;
|
const { TOP: topMargin, LEFT: leftMargin } = newMargin;
|
||||||
@@ -333,7 +338,7 @@ class HistogramBrush extends React.PureComponent {
|
|||||||
.range([leftMargin, leftMargin + newWidth]);
|
.range([leftMargin, leftMargin + newWidth]);
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||||
(histogramCache as any).bins = col.histogram(numBins, [
|
(histogramCache as any).bins = col.histogramContinuous(numBins, [
|
||||||
domainMin,
|
domainMin,
|
||||||
domainMax,
|
domainMax,
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import {
|
|||||||
createColorQuery,
|
createColorQuery,
|
||||||
} from "../../../util/stateManager/colorHelpers";
|
} from "../../../util/stateManager/colorHelpers";
|
||||||
import actions from "../../../actions";
|
import actions from "../../../actions";
|
||||||
|
import { Dataframe } from "../../../util/dataframe";
|
||||||
|
|
||||||
const LABEL_WIDTH = globals.leftSidebarWidth - 100;
|
const LABEL_WIDTH = globals.leftSidebarWidth - 100;
|
||||||
const ANNO_BUTTON_WIDTH = 50;
|
const ANNO_BUTTON_WIDTH = 50;
|
||||||
@@ -165,8 +166,20 @@ class Category extends React.PureComponent {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
async fetchData(
|
||||||
async fetchData(annoMatrix: any, metadataField: any, colors: any) {
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||||
|
annoMatrix: any,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||||
|
metadataField: any,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||||
|
colors: any
|
||||||
|
): Promise<
|
||||||
|
[
|
||||||
|
Dataframe,
|
||||||
|
ReturnType<typeof createCategorySummaryFromDfCol>,
|
||||||
|
Dataframe | null
|
||||||
|
]
|
||||||
|
> {
|
||||||
/*
|
/*
|
||||||
fetch our data and the color-by data if appropriate, and then build a summary
|
fetch our data and the color-by data if appropriate, and then build a summary
|
||||||
of our category and a color table for the color-by annotation.
|
of our category and a color table for the color-by annotation.
|
||||||
@@ -175,7 +188,7 @@ class Category extends React.PureComponent {
|
|||||||
const { colorAccessor, colorMode } = colors;
|
const { colorAccessor, colorMode } = colors;
|
||||||
// @ts-expect-error ts-migrate(2339) FIXME: Property 'genesets' does not exist on type 'Readon... Remove this comment to see the full error message
|
// @ts-expect-error ts-migrate(2339) FIXME: Property 'genesets' does not exist on type 'Readon... Remove this comment to see the full error message
|
||||||
const { genesets } = this.props;
|
const { genesets } = this.props;
|
||||||
let colorDataPromise = Promise.resolve(null);
|
let colorDataPromise: Promise<Dataframe | null> = Promise.resolve(null);
|
||||||
if (colorAccessor) {
|
if (colorAccessor) {
|
||||||
const query = createColorQuery(
|
const query = createColorQuery(
|
||||||
colorMode,
|
colorMode,
|
||||||
@@ -185,10 +198,10 @@ class Category extends React.PureComponent {
|
|||||||
);
|
);
|
||||||
if (query) colorDataPromise = annoMatrix.fetch(...query);
|
if (query) colorDataPromise = annoMatrix.fetch(...query);
|
||||||
}
|
}
|
||||||
const [categoryData, colorData] = await Promise.all([
|
const [categoryData, colorData] = await Promise.all<
|
||||||
annoMatrix.fetch("obs", metadataField),
|
Dataframe,
|
||||||
colorDataPromise,
|
Dataframe | null
|
||||||
]);
|
>([annoMatrix.fetch("obs", metadataField), colorDataPromise]);
|
||||||
|
|
||||||
// our data
|
// our data
|
||||||
const column = categoryData.icol(0);
|
const column = categoryData.icol(0);
|
||||||
@@ -200,8 +213,8 @@ class Category extends React.PureComponent {
|
|||||||
return [categoryData, categorySummary, colorData];
|
return [categoryData, categorySummary, colorData];
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types -- - FIXME: disabled temporarily on migrate to TS.
|
||||||
updateColorTable(colorData: any) {
|
updateColorTable(colorData: Dataframe|null) {
|
||||||
// color table, which may be null
|
// color table, which may be null
|
||||||
// @ts-expect-error ts-migrate(2339) FIXME: Property 'schema' does not exist on type 'Readonly... Remove this comment to see the full error message
|
// @ts-expect-error ts-migrate(2339) FIXME: Property 'schema' does not exist on type 'Readonly... Remove this comment to see the full error message
|
||||||
const { schema, colors, metadataField } = this.props;
|
const { schema, colors, metadataField } = this.props;
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import actions from "../../../actions";
|
|||||||
import MiniHistogram from "../../miniHistogram";
|
import MiniHistogram from "../../miniHistogram";
|
||||||
import MiniStackedBar from "../../miniStackedBar";
|
import MiniStackedBar from "../../miniStackedBar";
|
||||||
import { CategoryCrossfilterContext } from "../categoryContext";
|
import { CategoryCrossfilterContext } from "../categoryContext";
|
||||||
|
import { Dataframe, ContinuousHistogram } from "../../../util/dataframe";
|
||||||
|
|
||||||
const STACKED_BAR_HEIGHT = 11;
|
const STACKED_BAR_HEIGHT = 11;
|
||||||
const STACKED_BAR_WIDTH = 100;
|
const STACKED_BAR_WIDTH = 100;
|
||||||
@@ -327,13 +328,11 @@ class CategoryValue extends React.Component<{}, State> {
|
|||||||
createHistogramBins = (
|
createHistogramBins = (
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||||
metadataField: any,
|
metadataField: any,
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
categoryData: Dataframe,
|
||||||
categoryData: any,
|
|
||||||
// @ts-expect-error ts-migrate(6133) FIXME: 'colorAccessor' is declared but its value is never... Remove this comment to see the full error message
|
// @ts-expect-error ts-migrate(6133) FIXME: 'colorAccessor' is declared but its value is never... Remove this comment to see the full error message
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||||
colorAccessor: any,
|
colorAccessor: any,
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
colorData: Dataframe,
|
||||||
colorData: any,
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||||
categoryValue: any,
|
categoryValue: any,
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||||
@@ -348,17 +347,17 @@ class CategoryValue extends React.Component<{}, State> {
|
|||||||
*/
|
*/
|
||||||
const groupBy = categoryData.col(metadataField);
|
const groupBy = categoryData.col(metadataField);
|
||||||
const col = colorData.icol(0);
|
const col = colorData.icol(0);
|
||||||
const range = col.summarize();
|
const range = col.summarizeContinuous();
|
||||||
|
|
||||||
const histogramMap = col.histogram(
|
const histogramMap = col.histogramContinuousBy(
|
||||||
50,
|
50,
|
||||||
[range.min, range.max],
|
[range.min, range.max],
|
||||||
groupBy
|
groupBy
|
||||||
); /* Because the signature changes we really need different names for histogram to differentiate signatures */
|
);
|
||||||
|
|
||||||
const bins = histogramMap.has(categoryValue)
|
const bins = histogramMap.has(categoryValue)
|
||||||
? histogramMap.get(categoryValue)
|
? histogramMap.get(categoryValue) as ContinuousHistogram
|
||||||
: new Array(50).fill(0);
|
: new Array<number>(50).fill(0);
|
||||||
|
|
||||||
const xScale = d3.scaleLinear().domain([0, bins.length]).range([0, width]);
|
const xScale = d3.scaleLinear().domain([0, bins.length]).range([0, width]);
|
||||||
|
|
||||||
@@ -377,12 +376,10 @@ class CategoryValue extends React.Component<{}, State> {
|
|||||||
createStackedGraphBins = (
|
createStackedGraphBins = (
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||||
metadataField: any,
|
metadataField: any,
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
categoryData: Dataframe,
|
||||||
categoryData: any,
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||||
colorAccessor: any,
|
colorAccessor: any,
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
colorData: Dataframe,
|
||||||
colorData: any,
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||||
categoryValue: any,
|
categoryValue: any,
|
||||||
// @ts-expect-error ts-migrate(6133) FIXME: 'colorTable' is declared but its value is never re... Remove this comment to see the full error message
|
// @ts-expect-error ts-migrate(6133) FIXME: 'colorTable' is declared but its value is never re... Remove this comment to see the full error message
|
||||||
@@ -401,7 +398,7 @@ class CategoryValue extends React.Component<{}, State> {
|
|||||||
const groupBy = categoryData.col(metadataField);
|
const groupBy = categoryData.col(metadataField);
|
||||||
const occupancyMap = colorData
|
const occupancyMap = colorData
|
||||||
.col(colorAccessor)
|
.col(colorAccessor)
|
||||||
.histogramCategorical(groupBy);
|
.histogramCategoricalBy(groupBy);
|
||||||
|
|
||||||
const occupancy = occupancyMap.get(categoryValue);
|
const occupancy = occupancyMap.get(categoryValue);
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import {
|
|||||||
Position,
|
Position,
|
||||||
} from "@blueprintjs/core";
|
} from "@blueprintjs/core";
|
||||||
|
|
||||||
|
import { Dataframe } from "../../../util/dataframe";
|
||||||
|
|
||||||
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
|
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
|
||||||
@connect((state) => ({
|
@connect((state) => ({
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||||
@@ -21,34 +23,32 @@ class Occupancy extends React.PureComponent {
|
|||||||
|
|
||||||
_HEIGHT = 11;
|
_HEIGHT = 11;
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
createHistogram = (): void => {
|
||||||
createHistogram = () => {
|
|
||||||
/*
|
/*
|
||||||
Knowing that colorScale is based off continous data,
|
Knowing that colorScale is based off continuous data,
|
||||||
createHistogram fetches the continous data in relation to the cells releveant to the catagory value.
|
createHistogram fetches the continuous data in relation to the cells relevant to the category value.
|
||||||
It then seperates that data into 50 bins for drawing the mini-histogram
|
It then separates that data into 50 bins for drawing the mini-histogram
|
||||||
*/
|
*/
|
||||||
const {
|
const { metadataField, categoryData, colorData, categoryValue } = this
|
||||||
|
.props as {
|
||||||
// @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message
|
// @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message
|
||||||
metadataField,
|
metadataField;
|
||||||
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryData' does not exist on type 'Re... Remove this comment to see the full error message
|
categoryData: Dataframe;
|
||||||
categoryData,
|
colorData: Dataframe;
|
||||||
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colorData' does not exist on type 'Reado... Remove this comment to see the full error message
|
|
||||||
colorData,
|
|
||||||
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryValue' does not exist on type 'R... Remove this comment to see the full error message
|
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryValue' does not exist on type 'R... Remove this comment to see the full error message
|
||||||
categoryValue,
|
categoryValue;
|
||||||
} = this.props;
|
};
|
||||||
if (!this.canvas) return;
|
if (!this.canvas) return;
|
||||||
const groupBy = categoryData.col(metadataField);
|
const groupBy = categoryData.col(metadataField);
|
||||||
const col = colorData.icol(0);
|
const col = colorData.icol(0);
|
||||||
const range = col.summarize();
|
const range = col.summarizeContinuous();
|
||||||
const histogramMap = col.histogram(
|
const histogramMap = col.histogramContinuousBy(
|
||||||
50,
|
50,
|
||||||
[range.min, range.max],
|
[range.min, range.max],
|
||||||
groupBy
|
groupBy
|
||||||
); /* Because the signature changes we really need different names for histogram to differentiate signatures */
|
);
|
||||||
const bins = histogramMap.has(categoryValue)
|
const bins = histogramMap.has(categoryValue)
|
||||||
? histogramMap.get(categoryValue)
|
? (histogramMap.get(categoryValue) as number[])
|
||||||
: new Array(50).fill(0);
|
: new Array(50).fill(0);
|
||||||
const xScale = d3
|
const xScale = d3
|
||||||
.scaleLinear()
|
.scaleLinear()
|
||||||
@@ -71,36 +71,41 @@ class Occupancy extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
createOccupancyStack = (): void => {
|
||||||
createOccupancyStack = () => {
|
|
||||||
/*
|
/*
|
||||||
Knowing that the color scale is based off of catagorical data,
|
Knowing that the color scale is based off of catagorical data,
|
||||||
createOccupancyStack obtains a map showing the number if cells per colored value
|
createOccupancyStack obtains a map showing the number if cells per colored value
|
||||||
Using the colorScale a stack of colored bars is drawn representing the map
|
Using the colorScale a stack of colored bars is drawn representing the map
|
||||||
*/
|
*/
|
||||||
const {
|
const {
|
||||||
// @ts-expect-error ts-migrate(2339) FIXME: Property 'metadataField' does not exist on type 'R... Remove this comment to see the full error message
|
|
||||||
metadataField,
|
metadataField,
|
||||||
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryData' does not exist on type 'Re... Remove this comment to see the full error message
|
|
||||||
categoryData,
|
categoryData,
|
||||||
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colorAccessor' does not exist on type 'R... Remove this comment to see the full error message
|
|
||||||
colorAccessor,
|
colorAccessor,
|
||||||
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categoryValue' does not exist on type 'R... Remove this comment to see the full error message
|
|
||||||
categoryValue,
|
categoryValue,
|
||||||
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colorTable' does not exist on type 'Read... Remove this comment to see the full error message
|
|
||||||
colorTable,
|
colorTable,
|
||||||
// @ts-expect-error ts-migrate(2339) FIXME: Property 'schema' does not exist on type 'Readonly... Remove this comment to see the full error message
|
|
||||||
schema,
|
schema,
|
||||||
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colorData' does not exist on type 'Reado... Remove this comment to see the full error message
|
|
||||||
colorData,
|
colorData,
|
||||||
} = this.props;
|
} = this.props as {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||||
|
metadataField: any;
|
||||||
|
categoryData: Dataframe;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||||
|
colorAccessor: any;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||||
|
categoryValue: any;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||||
|
colorTable: any;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||||
|
schema: any;
|
||||||
|
colorData: Dataframe;
|
||||||
|
};
|
||||||
const { scale: colorScale } = colorTable;
|
const { scale: colorScale } = colorTable;
|
||||||
const ctx = this.canvas?.getContext("2d");
|
const ctx = this.canvas?.getContext("2d");
|
||||||
if (!ctx) return;
|
if (!ctx) return;
|
||||||
const groupBy = categoryData.col(metadataField);
|
const groupBy = categoryData.col(metadataField);
|
||||||
const occupancyMap = colorData
|
const occupancyMap = colorData
|
||||||
.col(colorAccessor)
|
.col(colorAccessor)
|
||||||
.histogramCategorical(groupBy);
|
.histogramCategoricalBy(groupBy);
|
||||||
const occupancy = occupancyMap.get(categoryValue);
|
const occupancy = occupancyMap.get(categoryValue);
|
||||||
if (occupancy && occupancy.size > 0) {
|
if (occupancy && occupancy.size > 0) {
|
||||||
// not all categories have occupancy, so occupancy may be undefined.
|
// not all categories have occupancy, so occupancy may be undefined.
|
||||||
@@ -119,7 +124,7 @@ class Occupancy extends React.PureComponent {
|
|||||||
let value;
|
let value;
|
||||||
for (let i = 0, { length } = categoryValues; i < length; i += 1) {
|
for (let i = 0, { length } = categoryValues; i < length; i += 1) {
|
||||||
value = categoryValues[i];
|
value = categoryValues[i];
|
||||||
o = occupancy.get(value);
|
o = occupancy.get(value) as number;
|
||||||
scaledValue = x(o);
|
scaledValue = x(o);
|
||||||
ctx.fillStyle = o
|
ctx.fillStyle = o
|
||||||
? colorScale(categories.indexOf(value))
|
? colorScale(categories.indexOf(value))
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ const loadAllEmbeddingCounts = async ({ annoMatrix, available }: any) => {
|
|||||||
return available.map((name, idx) => ({
|
return available.map((name, idx) => ({
|
||||||
embeddingName: name,
|
embeddingName: name,
|
||||||
embedding: embeddings[idx],
|
embedding: embeddings[idx],
|
||||||
|
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'unknown' is not assignable...
|
||||||
discreteCellIndex: getDiscreteCellEmbeddingRowIndex(embeddings[idx]),
|
discreteCellIndex: getDiscreteCellEmbeddingRowIndex(embeddings[idx]),
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import {
|
|||||||
|
|
||||||
import { memoize } from "../../../util/dataframe/util";
|
import { memoize } from "../../../util/dataframe/util";
|
||||||
import parseBulkGeneString from "../../../util/parseBulkGeneString";
|
import parseBulkGeneString from "../../../util/parseBulkGeneString";
|
||||||
|
import { Dataframe } from "../../../util/dataframe";
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||||
const renderGene = (fuzzySortResult: any, { handleClick, modifiers }: any) => {
|
const renderGene = (fuzzySortResult: any, { handleClick, modifiers }: any) => {
|
||||||
@@ -187,7 +188,7 @@ class AddGenes extends React.Component<{}, AddGenesState> {
|
|||||||
|
|
||||||
this.setState({ status: "pending" });
|
this.setState({ status: "pending" });
|
||||||
try {
|
try {
|
||||||
const df = await annoMatrix.fetch("var", varIndex);
|
const df: Dataframe = await annoMatrix.fetch("var", varIndex);
|
||||||
this.setState({
|
this.setState({
|
||||||
status: "success",
|
status: "success",
|
||||||
geneNames: df.col(varIndex).asArray(),
|
geneNames: df.col(varIndex).asArray(),
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import Gene from "./gene";
|
|||||||
|
|
||||||
import { postUserErrorToast } from "../framework/toasters";
|
import { postUserErrorToast } from "../framework/toasters";
|
||||||
import actions from "../../actions";
|
import actions from "../../actions";
|
||||||
|
import { Dataframe, DataframeValue } from "../../util/dataframe";
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||||
const usePrevious = (value: any) => {
|
const usePrevious = (value: any) => {
|
||||||
@@ -24,7 +25,7 @@ function QuickGene() {
|
|||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
const [isExpanded, setIsExpanded] = useState(true);
|
const [isExpanded, setIsExpanded] = useState(true);
|
||||||
const [geneNames, setGeneNames] = useState([]);
|
const [geneNames, setGeneNames] = useState([] as DataframeValue[]);
|
||||||
const [, setStatus] = useState("pending");
|
const [, setStatus] = useState("pending");
|
||||||
|
|
||||||
const { annoMatrix, userDefinedGenes, userDefinedGenesLoading } = useSelector(
|
const { annoMatrix, userDefinedGenes, userDefinedGenesLoading } = useSelector(
|
||||||
@@ -50,9 +51,9 @@ function QuickGene() {
|
|||||||
|
|
||||||
setStatus("pending");
|
setStatus("pending");
|
||||||
try {
|
try {
|
||||||
const df = await annoMatrix.fetch("var", varIndex);
|
const df: Dataframe = await annoMatrix.fetch("var", varIndex);
|
||||||
setStatus("success");
|
setStatus("success");
|
||||||
setGeneNames(df.col(varIndex).asArray());
|
setGeneNames(df.col(varIndex).asArray() as DataframeValue[]);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setStatus("error");
|
setStatus("error");
|
||||||
throw error;
|
throw error;
|
||||||
@@ -95,7 +96,6 @@ function QuickGene() {
|
|||||||
const gene = g.target;
|
const gene = g.target;
|
||||||
if (userDefinedGenes.indexOf(gene) !== -1) {
|
if (userDefinedGenes.indexOf(gene) !== -1) {
|
||||||
postUserErrorToast("That gene already exists");
|
postUserErrorToast("That gene already exists");
|
||||||
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'any' is not assignable to parame... Remove this comment to see the full error message
|
|
||||||
} else if (geneNames.indexOf(gene) === undefined) {
|
} else if (geneNames.indexOf(gene) === undefined) {
|
||||||
postUserErrorToast("That doesn't appear to be a valid gene name.");
|
postUserErrorToast("That doesn't appear to be a valid gene name.");
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import {
|
|||||||
flagSelected,
|
flagSelected,
|
||||||
flagHighlight,
|
flagHighlight,
|
||||||
} from "../../util/glHelpers";
|
} from "../../util/glHelpers";
|
||||||
|
import { Dataframe } from "../../util/dataframe";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Simple 2D transforms control all point painting. There are three:
|
Simple 2D transforms control all point painting. There are three:
|
||||||
@@ -558,7 +559,11 @@ class Graph extends React.Component<{}, GraphState> {
|
|||||||
handleEnd = this.handleLassoEnd.bind(this);
|
handleEnd = this.handleLassoEnd.bind(this);
|
||||||
handleCancel = this.handleLassoCancel.bind(this);
|
handleCancel = this.handleLassoCancel.bind(this);
|
||||||
}
|
}
|
||||||
const { svg: newToolSVG, tool, container } = setupSVGandBrushElements(
|
const {
|
||||||
|
svg: newToolSVG,
|
||||||
|
tool,
|
||||||
|
container,
|
||||||
|
} = setupSVGandBrushElements(
|
||||||
selectionTool,
|
selectionTool,
|
||||||
handleStart,
|
handleStart,
|
||||||
handleDrag,
|
handleDrag,
|
||||||
@@ -592,8 +597,7 @@ class Graph extends React.Component<{}, GraphState> {
|
|||||||
const positions = this.computePointPositions(X, Y, modelTF);
|
const positions = this.computePointPositions(X, Y, modelTF);
|
||||||
const colorTable = this.updateColorTable(colorsProp, colorDf);
|
const colorTable = this.updateColorTable(colorsProp, colorDf);
|
||||||
const colors = this.computePointColors(colorTable.rgb);
|
const colors = this.computePointColors(colorTable.rgb);
|
||||||
const { colorAccessor } = colorsProp;
|
const colorByData = colorDf?.icol(0)?.asArray();
|
||||||
const colorByData = colorDf?.col(colorAccessor)?.asArray();
|
|
||||||
const {
|
const {
|
||||||
metadataField: pointDilationCategory,
|
metadataField: pointDilationCategory,
|
||||||
categoryField: pointDilationLabel,
|
categoryField: pointDilationLabel,
|
||||||
@@ -627,7 +631,7 @@ class Graph extends React.Component<{}, GraphState> {
|
|||||||
colors: any,
|
colors: any,
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||||
pointDilation: any
|
pointDilation: any
|
||||||
) {
|
): Promise<[Dataframe, Dataframe | null, Dataframe | null]> {
|
||||||
/*
|
/*
|
||||||
fetch all data needed. Includes:
|
fetch all data needed. Includes:
|
||||||
- the color by dataframe
|
- the color by dataframe
|
||||||
@@ -635,22 +639,18 @@ class Graph extends React.Component<{}, GraphState> {
|
|||||||
- the point dilation dataframe
|
- the point dilation dataframe
|
||||||
*/
|
*/
|
||||||
const { metadataField: pointDilationAccessor } = pointDilation;
|
const { metadataField: pointDilationAccessor } = pointDilation;
|
||||||
const promises = [];
|
|
||||||
// layout
|
|
||||||
promises.push(annoMatrix.fetch("emb", layoutChoice.current));
|
|
||||||
// color
|
|
||||||
const query = this.createColorByQuery(colors);
|
const query = this.createColorByQuery(colors);
|
||||||
if (query) {
|
const promises: [
|
||||||
promises.push(annoMatrix.fetch(...query));
|
Promise<Dataframe>,
|
||||||
} else {
|
Promise<Dataframe | null>,
|
||||||
promises.push(Promise.resolve(null));
|
Promise<Dataframe | null>
|
||||||
}
|
] = [
|
||||||
// point highlighting
|
annoMatrix.fetch("emb", layoutChoice.current),
|
||||||
if (pointDilationAccessor) {
|
query ? annoMatrix.fetch(...query) : Promise.resolve(null),
|
||||||
promises.push(annoMatrix.fetch("obs", pointDilationAccessor));
|
pointDilationAccessor
|
||||||
} else {
|
? annoMatrix.fetch("obs", pointDilationAccessor)
|
||||||
promises.push(Promise.resolve(null));
|
: Promise.resolve(null),
|
||||||
}
|
];
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import {
|
|||||||
flagSelected,
|
flagSelected,
|
||||||
flagHighlight,
|
flagHighlight,
|
||||||
} from "../../util/glHelpers";
|
} from "../../util/glHelpers";
|
||||||
|
import { Dataframe, DataframeColumn } from "../../util/dataframe";
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||||
function createProjectionTF(viewportWidth: any, viewportHeight: any) {
|
function createProjectionTF(viewportWidth: any, viewportHeight: any) {
|
||||||
@@ -33,9 +34,9 @@ function createProjectionTF(viewportWidth: any, viewportHeight: any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||||
function getScale(col: any, rangeMin: any, rangeMax: any) {
|
function getScale(col: DataframeColumn, rangeMin: any, rangeMax: any) {
|
||||||
if (!col) return null;
|
if (!col) return null;
|
||||||
const { min, max } = col.summarize();
|
const { min, max } = col.summarizeContinuous();
|
||||||
return d3.scaleLinear().domain([min, max]).range([rangeMin, rangeMax]);
|
return d3.scaleLinear().domain([min, max]).range([rangeMin, rangeMax]);
|
||||||
}
|
}
|
||||||
const getXScale = memoize(getScale);
|
const getXScale = memoize(getScale);
|
||||||
@@ -276,17 +277,13 @@ class Scatterplot extends React.PureComponent<{}, State> {
|
|||||||
pointDilation,
|
pointDilation,
|
||||||
} = props.watchProps;
|
} = props.watchProps;
|
||||||
|
|
||||||
const [
|
const [expressionXDf, expressionYDf, colorDf, pointDilationDf] =
|
||||||
expressionXDf,
|
await this.fetchData(
|
||||||
expressionYDf,
|
scatterplotXXaccessor,
|
||||||
colorDf,
|
scatterplotYYaccessor,
|
||||||
pointDilationDf,
|
colorsProp,
|
||||||
] = await this.fetchData(
|
pointDilation
|
||||||
scatterplotXXaccessor,
|
);
|
||||||
scatterplotYYaccessor,
|
|
||||||
colorsProp,
|
|
||||||
pointDilation
|
|
||||||
);
|
|
||||||
const colorTable = this.updateColorTable(colorsProp, colorDf);
|
const colorTable = this.updateColorTable(colorsProp, colorDf);
|
||||||
|
|
||||||
const xCol = expressionXDf.icol(0);
|
const xCol = expressionXDf.icol(0);
|
||||||
@@ -383,37 +380,32 @@ class Scatterplot extends React.PureComponent<{}, State> {
|
|||||||
colors: any,
|
colors: any,
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||||
pointDilation: any
|
pointDilation: any
|
||||||
) {
|
): Promise<
|
||||||
|
[Dataframe, Dataframe, Dataframe | null, Dataframe | null]
|
||||||
|
> {
|
||||||
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message
|
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message
|
||||||
const { annoMatrix } = this.props;
|
const { annoMatrix } = this.props;
|
||||||
const { metadataField: pointDilationAccessor } = pointDilation;
|
const { metadataField: pointDilationAccessor } = pointDilation;
|
||||||
|
|
||||||
const promises = [];
|
|
||||||
// X and Y dimensions
|
|
||||||
promises.push(
|
|
||||||
// @ts-expect-error ts-migrate(2488) FIXME: Type '(string | { where: { field: string; column: ... Remove this comment to see the full error message
|
|
||||||
annoMatrix.fetch(...this.createXQuery(scatterplotXXaccessor))
|
|
||||||
);
|
|
||||||
promises.push(
|
|
||||||
annoMatrix.fetch(...this.createXQuery(scatterplotYYaccessor))
|
|
||||||
);
|
|
||||||
|
|
||||||
// color
|
|
||||||
const query = this.createColorByQuery(colors);
|
const query = this.createColorByQuery(colors);
|
||||||
if (query) {
|
|
||||||
promises.push(annoMatrix.fetch(...query));
|
|
||||||
} else {
|
|
||||||
promises.push(Promise.resolve(null));
|
|
||||||
}
|
|
||||||
|
|
||||||
// point highlighting
|
const promises: [Dataframe, Dataframe, Dataframe | null, Dataframe | null] =
|
||||||
if (pointDilationAccessor) {
|
[
|
||||||
promises.push(annoMatrix.fetch("obs", pointDilationAccessor));
|
// @ts-expect-error ts-migrate(2488) FIXME: Type '(string | { where: { field: string; column: ... Remove this comment to see the full error message
|
||||||
} else {
|
annoMatrix.fetch(...this.createXQuery(scatterplotXXaccessor)),
|
||||||
promises.push(Promise.resolve(null));
|
annoMatrix.fetch(...this.createXQuery(scatterplotYYaccessor)),
|
||||||
}
|
query ? annoMatrix.fetch(...query) : Promise.resolve(null),
|
||||||
|
pointDilationAccessor
|
||||||
|
? annoMatrix.fetch("obs", pointDilationAccessor)
|
||||||
|
: Promise.resolve(null),
|
||||||
|
];
|
||||||
|
|
||||||
return Promise.all(promises);
|
return Promise.all<
|
||||||
|
Dataframe,
|
||||||
|
Dataframe,
|
||||||
|
Dataframe | null,
|
||||||
|
Dataframe | null
|
||||||
|
>(promises);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderCanvas = renderThrottle(() => {
|
renderCanvas = renderThrottle(() => {
|
||||||
|
|||||||
+10
-18
@@ -1,5 +1,6 @@
|
|||||||
import quantile from "./quantile";
|
import quantile from "./quantile";
|
||||||
import { memoize } from "./dataframe/util";
|
import { memoize } from "./dataframe/util";
|
||||||
|
import { Dataframe } from "./dataframe";
|
||||||
import { unassignedCategoryLabel } from "../globals";
|
import { unassignedCategoryLabel } from "../globals";
|
||||||
import {
|
import {
|
||||||
createCategorySummaryFromDfCol,
|
createCategorySummaryFromDfCol,
|
||||||
@@ -27,12 +28,10 @@ const getCoordinatesByLabel = (
|
|||||||
schema: any,
|
schema: any,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||||
categoryName: any,
|
categoryName: any,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
categoryDf: Dataframe,
|
||||||
categoryDf: any,
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||||
layoutChoice: any,
|
layoutChoice: any,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
layoutDf: Dataframe
|
||||||
layoutDf: any
|
|
||||||
) => {
|
) => {
|
||||||
const coordsByCategoryLabel = new Map();
|
const coordsByCategoryLabel = new Map();
|
||||||
// If the coloredBy is not a categorical col
|
// If the coloredBy is not a categorical col
|
||||||
@@ -50,11 +49,8 @@ const getCoordinatesByLabel = (
|
|||||||
schema.annotations.obsByName[categoryName]
|
schema.annotations.obsByName[categoryName]
|
||||||
);
|
);
|
||||||
|
|
||||||
const {
|
const { isUserAnno, categoryValueIndices, categoryValueCounts } =
|
||||||
isUserAnno,
|
categorySummary;
|
||||||
categoryValueIndices,
|
|
||||||
categoryValueCounts,
|
|
||||||
} = categorySummary;
|
|
||||||
|
|
||||||
// Iterate over all cells
|
// Iterate over all cells
|
||||||
for (let i = 0, len = categoryArray.length; i < len; i += 1) {
|
for (let i = 0, len = categoryArray.length; i < len; i += 1) {
|
||||||
@@ -114,12 +110,10 @@ const calcMedianCentroid = (
|
|||||||
schema: any,
|
schema: any,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||||
categoryName: any,
|
categoryName: any,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
categoryDf: Dataframe,
|
||||||
categoryDf: any,
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||||
layoutChoice: any,
|
layoutChoice: any,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
layoutDf: Dataframe
|
||||||
layoutDf: any
|
|
||||||
) => {
|
) => {
|
||||||
// generate a map describing the coordinates for each label within the given category
|
// generate a map describing the coordinates for each label within the given category
|
||||||
const dataMap = getCoordinatesByLabel(
|
const dataMap = getCoordinatesByLabel(
|
||||||
@@ -159,13 +153,11 @@ const hashMedianCentroid = (
|
|||||||
schema: any,
|
schema: any,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||||
categoryName: any,
|
categoryName: any,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
categoryDf: Dataframe,
|
||||||
categoryDf: any,
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||||
layoutChoice: any,
|
layoutChoice: any,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
layoutDf: Dataframe
|
||||||
layoutDf: any
|
): string => {
|
||||||
) => {
|
|
||||||
const category = categoryDf.col(categoryName);
|
const category = categoryDf.col(categoryName);
|
||||||
const layoutDimNames = layoutChoice.currentDimNames;
|
const layoutDimNames = layoutChoice.currentDimNames;
|
||||||
const layoutX = layoutDf.col(layoutDimNames[0]);
|
const layoutX = layoutDf.col(layoutDimNames[0]);
|
||||||
|
|||||||
@@ -10,21 +10,18 @@ objects.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { memoize } from "./util";
|
import { memoize } from "./util";
|
||||||
|
import Dataframe from "./dataframe";
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
function hashDataframe(df: Dataframe): string {
|
||||||
function hashDataframe(df: any) {
|
|
||||||
if (df.isEmpty()) return "";
|
if (df.isEmpty()) return "";
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
return df.__columnsAccessor.map((c) => c.__id).join(",");
|
||||||
return df.__columnsAccessor.map((c: any) => c.__id).join(",");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
function noop(df: Dataframe): Dataframe {
|
||||||
function noop(df: any) {
|
|
||||||
return df;
|
return df;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
const dataframeMemo = (capacity = 100): ((df: Dataframe) => Dataframe) =>
|
||||||
const dataframeMemo = (capacity = 100) =>
|
|
||||||
memoize(noop, hashDataframe, capacity);
|
memoize(noop, hashDataframe, capacity);
|
||||||
|
|
||||||
export default dataframeMemo;
|
export default dataframeMemo;
|
||||||
|
|||||||
@@ -1,25 +1,44 @@
|
|||||||
import { IdentityInt32Index, isLabelIndex } from "./labelIndex";
|
|
||||||
// weird cross-dependency that we should clean up someday...
|
|
||||||
import { callOnceLazy, memoize, __getMemoId } from "./util";
|
import { callOnceLazy, memoize, __getMemoId } from "./util";
|
||||||
import { isTypedArray, isAnyArray } from "../../common/types/arraytypes";
|
|
||||||
import {
|
import {
|
||||||
summarizeContinuous,
|
isTypedArray,
|
||||||
|
isAnyArray,
|
||||||
|
AnyArray,
|
||||||
|
GenericArrayConstructor,
|
||||||
|
} from "../../common/types/arraytypes";
|
||||||
|
import { IdentityInt32Index, LabelIndex, isLabelIndex } from "./labelIndex";
|
||||||
|
import {
|
||||||
|
summarizeContinuous as _summarizeContinuous,
|
||||||
summarizeCategorical as _summarizeCategorical,
|
summarizeCategorical as _summarizeCategorical,
|
||||||
} from "./summarize";
|
} from "./summarize";
|
||||||
import {
|
import {
|
||||||
histogramCategorical as _histogramCategorical,
|
histogramCategorical as _histogramCategorical,
|
||||||
|
histogramCategoricalBy as _histogramCategoricalBy,
|
||||||
hashCategorical,
|
hashCategorical,
|
||||||
histogramContinuous,
|
hashCategoricalBy,
|
||||||
|
histogramContinuous as _histogramContinuous,
|
||||||
|
histogramContinuousBy as _histogramContinuousBy,
|
||||||
hashContinuous,
|
hashContinuous,
|
||||||
|
hashContinuousBy,
|
||||||
} from "./histogram";
|
} from "./histogram";
|
||||||
|
import {
|
||||||
|
DataframeValue,
|
||||||
|
DataframeValueArray,
|
||||||
|
DataframeColumn,
|
||||||
|
OffsetType,
|
||||||
|
OffsetArray,
|
||||||
|
LabelType,
|
||||||
|
LabelArray,
|
||||||
|
ContinuousHistogram,
|
||||||
|
ContinuousHistogramBy,
|
||||||
|
} from "./types";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Dataframe is an immutable 2D matrix similiar to Python Pandas Dataframe,
|
Dataframe is an immutable 2D matrix similar to Python Pandas Dataframe,
|
||||||
but (currently) without all of the surrounding support functions.
|
but (currently) without all of the surrounding support functions.
|
||||||
Data is stored in column-major layout, and each column is monomorphic.
|
Data is stored in column-major layout, and each column is monomorphic.
|
||||||
|
|
||||||
It supports:
|
It supports:
|
||||||
* Relatively efficient creation, cloning and subsetting
|
* Relatively efficient create, clone and subset operations
|
||||||
* Very efficient columnar access (eg, sum down a column), and access
|
* Very efficient columnar access (eg, sum down a column), and access
|
||||||
to the underlying column arrays.
|
to the underlying column arrays.
|
||||||
* Data access by row/col offset or label. Labels are reasonably well
|
* Data access by row/col offset or label. Labels are reasonably well
|
||||||
@@ -27,10 +46,10 @@ It supports:
|
|||||||
|
|
||||||
It does not currently support:
|
It does not currently support:
|
||||||
* Views on matrix subset - for currently known access patterns,
|
* Views on matrix subset - for currently known access patterns,
|
||||||
it is more effiicent to copy on subsetting, optimizing for access
|
it is more efficient to copy on subsetting, optimizing for access
|
||||||
speed over memory use.
|
speed over memory use.
|
||||||
* JS iterators - they are too slow. Use explicit iteration over
|
* JS iterators - they are too slow. Use explicit iteration over
|
||||||
offest or labels.
|
offset or labels.
|
||||||
|
|
||||||
Important assumptions embedded in the API:
|
Important assumptions embedded in the API:
|
||||||
* Columns are implicitly categorical if they are a JS Array and numeric
|
* Columns are implicitly categorical if they are a JS Array and numeric
|
||||||
@@ -67,46 +86,55 @@ dominant pattern in cellxgene.
|
|||||||
Dataframe
|
Dataframe
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
interface DataframeConstructor {
|
||||||
|
new (...args: ConstructorParameters<typeof Dataframe>): Dataframe;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type MapColumnsCallbackFn = (
|
||||||
|
data: DataframeValueArray,
|
||||||
|
idx: number,
|
||||||
|
df: Dataframe
|
||||||
|
) => DataframeValueArray;
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
function raiseIsNotContinuous<R = void>(): R {
|
||||||
|
throw TypeError("Column is not a continuous data type.");
|
||||||
|
}
|
||||||
|
|
||||||
class Dataframe {
|
class Dataframe {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
/** @internal */
|
||||||
__columns: any;
|
__columns: DataframeValueArray[];
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
/** @internal */
|
||||||
__columnsAccessor: any;
|
__columnsAccessor: DataframeColumn[] = [];
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
__id: string;
|
||||||
__id: any;
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
colIndex: LabelIndex;
|
||||||
colIndex: any;
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
dims: [number, number];
|
||||||
dims: any;
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
length: number;
|
||||||
length: any;
|
|
||||||
|
rowIndex: LabelIndex;
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
|
||||||
rowIndex: any;
|
|
||||||
/**
|
/**
|
||||||
Constructors & factories
|
Constructors & factories
|
||||||
**/
|
**/
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
dims: [number, number],
|
||||||
dims: any,
|
columnarData: DataframeValueArray[],
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
rowIndex?: LabelIndex | null,
|
||||||
columnarData: any,
|
colIndex?: LabelIndex | null,
|
||||||
rowIndex = null,
|
__columnsAccessor: (DataframeColumn | null)[] = [] // private interface
|
||||||
colIndex = null,
|
|
||||||
__columnsAccessor = [] // private interface
|
|
||||||
) {
|
) {
|
||||||
/*
|
/*
|
||||||
The base constructor is relatively hard to use - as an alternative,
|
The base constructor is relatively hard to use - as an alternative,
|
||||||
see factory methods and clone/slice, below.
|
see factory methods and clone/slice, below.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
* dims - 2D array describing intendend dimensionality: [nRows,nCols].
|
* dims - 2D array describing intended dimensionality: [nRows,nCols].
|
||||||
* columnarData - JS array, nCols in length, containing array
|
* columnarData - JS array, nCols in length, containing array
|
||||||
or TypedArray of length nRows.
|
or TypedArray of length nRows.
|
||||||
* rowIndex/colIndex - null (create default index using offsets as key),
|
* rowIndex/colIndex - null (create default index using offsets as key),
|
||||||
@@ -121,11 +149,9 @@ class Dataframe {
|
|||||||
throw new RangeError("Dataframe dimensions must be positive");
|
throw new RangeError("Dataframe dimensions must be positive");
|
||||||
}
|
}
|
||||||
if (!rowIndex) {
|
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);
|
rowIndex = new IdentityInt32Index(nRows);
|
||||||
}
|
}
|
||||||
if (!colIndex) {
|
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);
|
colIndex = new IdentityInt32Index(nCols);
|
||||||
}
|
}
|
||||||
Dataframe.__errorChecks(dims, columnarData, rowIndex, colIndex);
|
Dataframe.__errorChecks(dims, columnarData, rowIndex, colIndex);
|
||||||
@@ -141,17 +167,13 @@ class Dataframe {
|
|||||||
Object.freeze(this);
|
Object.freeze(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
/** @internal */
|
||||||
static __errorChecks(
|
static __errorChecks(
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
dims: [number, number],
|
||||||
dims: any,
|
columnarData: AnyArray[],
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
rowIndex: LabelIndex,
|
||||||
columnarData: any,
|
colIndex: LabelIndex
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
): void | never {
|
||||||
rowIndex: any,
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
|
||||||
colIndex: any
|
|
||||||
) {
|
|
||||||
const [nRows, nCols] = dims;
|
const [nRows, nCols] = dims;
|
||||||
|
|
||||||
/* check for expected types */
|
/* check for expected types */
|
||||||
@@ -189,8 +211,12 @@ class Dataframe {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
/** @internal */
|
||||||
static __compileColumn(column: any, getRowByOffset: any, getRowByLabel: any) {
|
static __compileColumn(
|
||||||
|
column: DataframeValueArray,
|
||||||
|
getRowOffset: (label: LabelType) => OffsetType | -1,
|
||||||
|
getRowLabel: (offset: number) => LabelType | undefined
|
||||||
|
): DataframeColumn {
|
||||||
/*
|
/*
|
||||||
Each column accessor is a function which will lookup data by
|
Each column accessor is a function which will lookup data by
|
||||||
index (ie, is equivalent to dataframe.get(row, col), where 'col'
|
index (ie, is equivalent to dataframe.get(row, col), where 'col'
|
||||||
@@ -223,16 +249,17 @@ class Dataframe {
|
|||||||
*/
|
*/
|
||||||
const { length } = column;
|
const { length } = column;
|
||||||
const __id = __getMemoId();
|
const __id = __getMemoId();
|
||||||
|
const isContinuous = isTypedArray(column);
|
||||||
|
|
||||||
/* get value by row label */
|
/* get value by row label */
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
const get = function get(rlabel: LabelType): DataframeValue | undefined {
|
||||||
const get = function get(rlabel: any) {
|
const idx = getRowOffset(rlabel);
|
||||||
return column[getRowByOffset(rlabel)];
|
if (idx === -1) return undefined;
|
||||||
|
return column[idx];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* get value by row offset */
|
/* get value by row offset */
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
const iget = function iget(roffset: OffsetType) {
|
||||||
const iget = function iget(roffset: any) {
|
|
||||||
return column[roffset];
|
return column[roffset];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -242,14 +269,12 @@ class Dataframe {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* test for row label inclusion in column */
|
/* test for row label inclusion in column */
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
const has = function has(rlabel: LabelType) {
|
||||||
const has = function has(rlabel: any) {
|
const offset = getRowOffset(rlabel);
|
||||||
const offset = getRowByOffset(rlabel);
|
|
||||||
return offset >= 0 && offset < length;
|
return offset >= 0 && offset < length;
|
||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
const ihas = function ihas(offset: OffsetType) {
|
||||||
const ihas = function ihas(offset: any) {
|
|
||||||
return offset >= 0 && offset < length;
|
return offset >= 0 && offset < length;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -260,84 +285,88 @@ class Dataframe {
|
|||||||
NOTE: not found return is DIFFERENT than the default Array.indexOf as
|
NOTE: not found return is DIFFERENT than the default Array.indexOf as
|
||||||
-1 is a plausible Dataframe row/col label.
|
-1 is a plausible Dataframe row/col label.
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
const _indexOf = function _indexOf(value: DataframeValue) {
|
||||||
const indexOf = function indexOf(value: any) {
|
let offset: number;
|
||||||
const offset = column.indexOf(value);
|
if (isTypedArray(column)) offset = column.indexOf(value as number);
|
||||||
|
else offset = column.indexOf(value);
|
||||||
if (offset === -1) {
|
if (offset === -1) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
return getRowByLabel(offset);
|
return getRowLabel(offset);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Summarize the column data. Lazy eval, memoized
|
Summarize the column data. Lazy eval, memoized
|
||||||
*/
|
*/
|
||||||
const summarizeCategorical = callOnceLazy(() =>
|
get.summarizeCategorical = callOnceLazy(() =>
|
||||||
_summarizeCategorical(column)
|
_summarizeCategorical(column)
|
||||||
);
|
);
|
||||||
const summarize = callOnceLazy(() =>
|
get.summarizeContinuous = isContinuous
|
||||||
isTypedArray(column)
|
? callOnceLazy(() => _summarizeContinuous(column))
|
||||||
? summarizeContinuous(column)
|
: raiseIsNotContinuous;
|
||||||
: summarizeCategorical(column)
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Create histogram bins for this column. Memoized.
|
Create histogram bins for this column. Memoized.
|
||||||
*/
|
*/
|
||||||
const _memoHistoCat = memoize(_histogramCategorical, hashCategorical);
|
get.histogramContinuous = isContinuous
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
? (bins: number, domain: [number, number]): ContinuousHistogram =>
|
||||||
const histogramCategorical = (by: any) => _memoHistoCat(get, by);
|
memoize(_histogramContinuous, hashContinuous)(get, bins, domain)
|
||||||
let histogram = null;
|
: raiseIsNotContinuous;
|
||||||
if (isTypedArray(column)) {
|
get.histogramContinuousBy = isContinuous
|
||||||
const mFn = memoize(histogramContinuous, hashContinuous);
|
? (
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
bins: number,
|
||||||
histogram = (bins: any, domain: any, by: any) =>
|
domain: [number, number],
|
||||||
mFn(get, bins, domain, by);
|
by: DataframeColumn
|
||||||
} else {
|
): ContinuousHistogramBy =>
|
||||||
histogram = histogramCategorical;
|
memoize(_histogramContinuousBy, hashContinuousBy)(
|
||||||
}
|
get,
|
||||||
|
bins,
|
||||||
|
domain,
|
||||||
|
by
|
||||||
|
)
|
||||||
|
: raiseIsNotContinuous;
|
||||||
|
get.histogramCategorical = () =>
|
||||||
|
memoize(_histogramCategorical, hashCategorical)(get);
|
||||||
|
get.histogramCategoricalBy = (by: DataframeColumn) =>
|
||||||
|
memoize(_histogramCategoricalBy, hashCategoricalBy)(get, by);
|
||||||
|
|
||||||
get.summarize = summarize;
|
|
||||||
get.summarizeCategorical = summarizeCategorical;
|
|
||||||
get.histogram = histogram;
|
|
||||||
get.histogramCategorical = histogramCategorical;
|
|
||||||
get.asArray = asArray;
|
get.asArray = asArray;
|
||||||
get.has = has;
|
get.has = has;
|
||||||
get.ihas = ihas;
|
get.ihas = ihas;
|
||||||
get.indexOf = indexOf;
|
get.indexOf = _indexOf;
|
||||||
get.iget = iget;
|
get.iget = iget;
|
||||||
get.__id = __id;
|
get.__id = __id;
|
||||||
|
get.isContinuous = isContinuous;
|
||||||
|
|
||||||
Object.freeze(get);
|
Object.freeze(get);
|
||||||
return get;
|
return get;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
/** @internal */
|
||||||
__compile(accessors: any) {
|
__compile(accessors: (DataframeColumn | null)[]): void {
|
||||||
/*
|
/*
|
||||||
Compile data accessors for each column.
|
Compile data accessors for each column.
|
||||||
|
|
||||||
Use an existing accessor if provided, else compile a new one.
|
Use an existing accessor if provided, else compile a new one.
|
||||||
*/
|
*/
|
||||||
const getRowByOffset = this.rowIndex.getOffset.bind(this.rowIndex);
|
const getRowOffset = this.rowIndex.getOffset.bind(this.rowIndex);
|
||||||
const getRowByLabel = this.rowIndex.getLabel.bind(this.rowIndex);
|
const getRowLabel = this.rowIndex.getLabel.bind(this.rowIndex);
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
this.__columnsAccessor = this.__columns.map(
|
||||||
this.__columnsAccessor = this.__columns.map((column: any, idx: any) => {
|
(column, idx): DataframeColumn => {
|
||||||
if (accessors[idx]) {
|
if (accessors[idx]) {
|
||||||
return accessors[idx];
|
return accessors[idx] as DataframeColumn;
|
||||||
|
}
|
||||||
|
return Dataframe.__compileColumn(column, getRowOffset, getRowLabel);
|
||||||
}
|
}
|
||||||
return Dataframe.__compileColumn(column, getRowByOffset, getRowByLabel);
|
);
|
||||||
});
|
|
||||||
Object.freeze(this.__columnsAccessor);
|
Object.freeze(this.__columnsAccessor);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
clone(): Dataframe {
|
||||||
clone() {
|
|
||||||
/*
|
/*
|
||||||
Clone this dataframe
|
Clone this dataframe
|
||||||
*/
|
*/
|
||||||
// @ts-expect-error ts-migrate(2351) FIXME: This expression is not constructable.
|
return new (this.constructor as DataframeConstructor)(
|
||||||
return new this.constructor(
|
|
||||||
this.dims,
|
this.dims,
|
||||||
[...this.__columns],
|
[...this.__columns],
|
||||||
this.rowIndex,
|
this.rowIndex,
|
||||||
@@ -346,8 +375,11 @@ class Dataframe {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
withCol(
|
||||||
withCol(label: any, colData: any, withRowIndex = null) {
|
label: LabelType,
|
||||||
|
colData: DataframeValueArray,
|
||||||
|
withRowIndex?: LabelIndex
|
||||||
|
): Dataframe {
|
||||||
/*
|
/*
|
||||||
Create a new DF, which is `this` plus the new column. Example:
|
Create a new DF, which is `this` plus the new column. Example:
|
||||||
const newDf = df.withCol("foo", [1,2,3]);
|
const newDf = df.withCol("foo", [1,2,3]);
|
||||||
@@ -362,11 +394,10 @@ class Dataframe {
|
|||||||
the rowIndex from `this` will be used (ie, the rowIndex is
|
the rowIndex from `this` will be used (ie, the rowIndex is
|
||||||
unchanged).
|
unchanged).
|
||||||
*/
|
*/
|
||||||
let dims;
|
let dims: [number, number];
|
||||||
let rowIndex;
|
let rowIndex: LabelIndex | null = null;
|
||||||
if (this.isEmpty()) {
|
if (this.isEmpty()) {
|
||||||
dims = [colData.length, 1];
|
dims = [colData.length, 1];
|
||||||
rowIndex = null;
|
|
||||||
} else {
|
} else {
|
||||||
dims = [this.dims[0], this.dims[1] + 1];
|
dims = [this.dims[0], this.dims[1] + 1];
|
||||||
({ rowIndex } = this);
|
({ rowIndex } = this);
|
||||||
@@ -380,8 +411,7 @@ class Dataframe {
|
|||||||
columns.push(colData);
|
columns.push(colData);
|
||||||
const colIndex = this.colIndex.withLabel(label);
|
const colIndex = this.colIndex.withLabel(label);
|
||||||
const columnsAccessor = [...this.__columnsAccessor];
|
const columnsAccessor = [...this.__columnsAccessor];
|
||||||
// @ts-expect-error ts-migrate(2351) FIXME: This expression is not constructable.
|
return new (this.constructor as DataframeConstructor)(
|
||||||
return new this.constructor(
|
|
||||||
dims,
|
dims,
|
||||||
columns,
|
columns,
|
||||||
rowIndex,
|
rowIndex,
|
||||||
@@ -390,8 +420,10 @@ class Dataframe {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
withColsFrom(
|
||||||
withColsFrom(dataframe: any, labels: any) {
|
dataframe: Dataframe,
|
||||||
|
labels?: Record<string | number, LabelType> | LabelType[]
|
||||||
|
): Dataframe {
|
||||||
/*
|
/*
|
||||||
return a new dataframe containing all columns from both `this` and the
|
return a new dataframe containing all columns from both `this` and the
|
||||||
provided dataframe argument.
|
provided dataframe argument.
|
||||||
@@ -417,8 +449,8 @@ class Dataframe {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// resolve the source and dest label names.
|
// resolve the source and dest label names.
|
||||||
let srcLabels;
|
let srcLabels: LabelArray;
|
||||||
let dstLabels;
|
let dstLabels: LabelArray;
|
||||||
if (!labels) {
|
if (!labels) {
|
||||||
// combine all columns
|
// combine all columns
|
||||||
dstLabels = dataframe.colIndex.labels();
|
dstLabels = dataframe.colIndex.labels();
|
||||||
@@ -453,12 +485,9 @@ class Dataframe {
|
|||||||
return dataframe;
|
return dataframe;
|
||||||
}
|
}
|
||||||
|
|
||||||
// otherwise, bulid a new dataframe combining columns from both
|
// otherwise, build a new dataframe combining columns from both
|
||||||
|
const srcOffsets = Array.from(dataframe.colIndex.getOffsets(srcLabels));
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
if (srcOffsets.some((i) => i === -1)) throw RangeError("Unknown label.");
|
||||||
const srcOffsets = srcLabels.map((l: any) =>
|
|
||||||
dataframe.colIndex.getOffset(l)
|
|
||||||
);
|
|
||||||
|
|
||||||
// check for label collisions
|
// check for label collisions
|
||||||
if (dstLabels.some(this.hasCol, this)) {
|
if (dstLabels.some(this.hasCol, this)) {
|
||||||
@@ -466,22 +495,22 @@ class Dataframe {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// const dims = [this.dims[0], this.dims[1] + dataframe.dims[1]];
|
// const dims = [this.dims[0], this.dims[1] + dataframe.dims[1]];
|
||||||
const dims = [this.dims[0], this.dims[1] + srcOffsets.length];
|
const dims: [number, number] = [
|
||||||
|
this.dims[0],
|
||||||
|
this.dims[1] + srcOffsets.length,
|
||||||
|
];
|
||||||
const { rowIndex } = this;
|
const { rowIndex } = this;
|
||||||
const columns = [
|
const columns: DataframeValueArray[] = [
|
||||||
...this.__columns,
|
...this.__columns,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
...srcOffsets.map((i) => dataframe.__columns[i]),
|
||||||
...srcOffsets.map((i: any) => dataframe.__columns[i]),
|
|
||||||
];
|
];
|
||||||
const colIndex = this.colIndex.withLabels(dstLabels);
|
const colIndex = this.colIndex.withLabels(dstLabels);
|
||||||
const columnsAccessor = [
|
const columnsAccessor = [
|
||||||
...this.__columnsAccessor,
|
...this.__columnsAccessor,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
...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 as DataframeConstructor)(
|
||||||
return new this.constructor(
|
|
||||||
dims,
|
dims,
|
||||||
columns,
|
columns,
|
||||||
rowIndex,
|
rowIndex,
|
||||||
@@ -490,15 +519,12 @@ class Dataframe {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
withColsFromAll(dataframes: Dataframe[] = []): Dataframe {
|
||||||
withColsFromAll(dataframes = []) {
|
|
||||||
dataframes = Array.isArray(dataframes) ? dataframes : [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);
|
return dataframes.reduce((acc, df) => acc.withColsFrom(df), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
dropCol(label: LabelType): Dataframe {
|
||||||
dropCol(label: any) {
|
|
||||||
/*
|
/*
|
||||||
Create a new dataframe, omitting one columns.
|
Create a new dataframe, omitting one columns.
|
||||||
|
|
||||||
@@ -517,15 +543,15 @@ class Dataframe {
|
|||||||
return Dataframe.empty();
|
return Dataframe.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
const dims = [this.dims[0], this.dims[1] - 1];
|
const dims: [number, number] = [this.dims[0], this.dims[1] - 1];
|
||||||
const coffset = this.colIndex.getOffset(label);
|
const coffset = this.colIndex.getOffset(label);
|
||||||
|
if (coffset === -1) throw new RangeError("Unknown label.");
|
||||||
const columns = [...this.__columns];
|
const columns = [...this.__columns];
|
||||||
columns.splice(coffset, 1);
|
columns.splice(coffset, 1);
|
||||||
const colIndex = this.colIndex.dropLabel(label);
|
const colIndex = this.colIndex.dropLabel(label);
|
||||||
const columnsAccessor = [...this.__columnsAccessor];
|
const columnsAccessor = [...this.__columnsAccessor];
|
||||||
columnsAccessor.splice(coffset, 1);
|
columnsAccessor.splice(coffset, 1);
|
||||||
// @ts-expect-error ts-migrate(2351) FIXME: This expression is not constructable.
|
return new (this.constructor as DataframeConstructor)(
|
||||||
return new this.constructor(
|
|
||||||
dims,
|
dims,
|
||||||
columns,
|
columns,
|
||||||
this.rowIndex,
|
this.rowIndex,
|
||||||
@@ -534,12 +560,12 @@ class Dataframe {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
renameCol(oldLabel: LabelType, newLabel: LabelType): Dataframe {
|
||||||
renameCol(oldLabel: any, newLabel: any) {
|
|
||||||
/*
|
/*
|
||||||
Accelerator for dropping a column and then adding it again with a new label
|
Accelerator for dropping a column and then adding it again with a new label
|
||||||
*/
|
*/
|
||||||
const coffset = this.colIndex.getOffset(oldLabel);
|
const coffset = this.colIndex.getOffset(oldLabel);
|
||||||
|
if (coffset === -1) throw new RangeError("Unknown label.");
|
||||||
const colIndex = this.colIndex.dropLabel(oldLabel).withLabel(newLabel);
|
const colIndex = this.colIndex.dropLabel(oldLabel).withLabel(newLabel);
|
||||||
|
|
||||||
const columns = [...this.__columns];
|
const columns = [...this.__columns];
|
||||||
@@ -550,8 +576,7 @@ class Dataframe {
|
|||||||
columnsAccessor.push(columnsAccessor[coffset]);
|
columnsAccessor.push(columnsAccessor[coffset]);
|
||||||
columnsAccessor.splice(coffset, 1);
|
columnsAccessor.splice(coffset, 1);
|
||||||
|
|
||||||
// @ts-expect-error ts-migrate(2351) FIXME: This expression is not constructable.
|
return new (this.constructor as DataframeConstructor)(
|
||||||
return new this.constructor(
|
|
||||||
this.dims,
|
this.dims,
|
||||||
columns,
|
columns,
|
||||||
this.rowIndex,
|
this.rowIndex,
|
||||||
@@ -560,20 +585,21 @@ class Dataframe {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
replaceColData(label: LabelType, newColData: DataframeValueArray): Dataframe {
|
||||||
replaceColData(label: any, newColData: any) {
|
|
||||||
/*
|
/*
|
||||||
Accelerator for dropping a column then adding it again with same
|
Accelerator for dropping a column then adding it again with same
|
||||||
label and different values.
|
label and different values.
|
||||||
*/
|
*/
|
||||||
const coffset = this.colIndex.getOffset(label);
|
const coffset = this.colIndex.getOffset(label);
|
||||||
|
if (coffset === -1) throw RangeError("Unknown column label.");
|
||||||
const columns = [...this.__columns];
|
const columns = [...this.__columns];
|
||||||
columns[coffset] = newColData;
|
columns[coffset] = newColData;
|
||||||
const columnsAccessor = [...this.__columnsAccessor];
|
const columnsAccessor: (DataframeColumn | null)[] = [
|
||||||
|
...this.__columnsAccessor,
|
||||||
|
];
|
||||||
columnsAccessor[coffset] = null;
|
columnsAccessor[coffset] = null;
|
||||||
|
|
||||||
// @ts-expect-error ts-migrate(2351) FIXME: This expression is not constructable.
|
return new (this.constructor as DataframeConstructor)(
|
||||||
return new this.constructor(
|
|
||||||
this.dims,
|
this.dims,
|
||||||
columns,
|
columns,
|
||||||
this.rowIndex,
|
this.rowIndex,
|
||||||
@@ -582,20 +608,19 @@ class Dataframe {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
static empty(rowIndex?: LabelIndex, colIndex?: LabelIndex): Dataframe {
|
||||||
static empty(rowIndex = null, colIndex = null) {
|
const dims: [number, number] = [
|
||||||
const dims = [
|
|
||||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
|
||||||
rowIndex ? rowIndex.size() : 0,
|
rowIndex ? rowIndex.size() : 0,
|
||||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
|
||||||
colIndex ? colIndex.size() : 0,
|
colIndex ? colIndex.size() : 0,
|
||||||
];
|
];
|
||||||
if (dims[0] && dims[1]) throw new Error("not an empty dataframe");
|
if (dims[0] && dims[1]) throw new Error("not an empty dataframe");
|
||||||
return new Dataframe(dims, new Array(dims[1]), rowIndex, colIndex);
|
return new Dataframe(dims, new Array(dims[1]), rowIndex, colIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
static create(
|
||||||
static create(dims: any, columnarData: any) {
|
dims: [number, number],
|
||||||
|
columnarData: DataframeValueArray[]
|
||||||
|
): Dataframe {
|
||||||
/*
|
/*
|
||||||
Create a dataframe from raw columnar data. All column arrays
|
Create a dataframe from raw columnar data. All column arrays
|
||||||
must have the same length. Identity indexing will be used.
|
must have the same length. Identity indexing will be used.
|
||||||
@@ -603,12 +628,15 @@ class Dataframe {
|
|||||||
Example:
|
Example:
|
||||||
const df = Dataframe.create([2,2], [new Uint32Array(2), new Float32Array(2)]);
|
const df = Dataframe.create([2,2], [new Uint32Array(2), new Float32Array(2)]);
|
||||||
*/
|
*/
|
||||||
return new Dataframe(dims, columnarData, null, null);
|
return new Dataframe(dims, columnarData);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
/** @internal */
|
||||||
__subset(newRowIndex: any, newColIndex: any) {
|
__subset(
|
||||||
const dims = [...this.dims];
|
newRowIndex: LabelIndex | null,
|
||||||
|
newColIndex: LabelIndex | null
|
||||||
|
): Dataframe {
|
||||||
|
const dims: [number, number] = [...this.dims];
|
||||||
|
|
||||||
/* subset columns */
|
/* subset columns */
|
||||||
let { __columns, colIndex, __columnsAccessor } = this;
|
let { __columns, colIndex, __columnsAccessor } = this;
|
||||||
@@ -617,8 +645,10 @@ class Dataframe {
|
|||||||
__columns = new Array(colOffsets.length);
|
__columns = new Array(colOffsets.length);
|
||||||
__columnsAccessor = new Array(colOffsets.length);
|
__columnsAccessor = new Array(colOffsets.length);
|
||||||
for (let i = 0, l = colOffsets.length; i < l; i += 1) {
|
for (let i = 0, l = colOffsets.length; i < l; i += 1) {
|
||||||
__columns[i] = this.__columns[colOffsets[i]];
|
const colOffset = colOffsets[i];
|
||||||
__columnsAccessor[i] = this.__columnsAccessor[colOffsets[i]];
|
if (colOffset === -1) throw new RangeError("Unexpected column offset.");
|
||||||
|
__columns[i] = this.__columns[colOffset];
|
||||||
|
__columnsAccessor[i] = this.__columnsAccessor[colOffset];
|
||||||
}
|
}
|
||||||
colIndex = newColIndex;
|
colIndex = newColIndex;
|
||||||
dims[1] = colOffsets.length;
|
dims[1] = colOffsets.length;
|
||||||
@@ -627,11 +657,14 @@ class Dataframe {
|
|||||||
let { rowIndex } = this;
|
let { rowIndex } = this;
|
||||||
if (newRowIndex) {
|
if (newRowIndex) {
|
||||||
const rowOffsets = this.rowIndex.getOffsets(newRowIndex.labels());
|
const rowOffsets = this.rowIndex.getOffsets(newRowIndex.labels());
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
__columns = __columns.map((col) => {
|
||||||
__columns = __columns.map((col: any) => {
|
const newCol = new (col.constructor as GenericArrayConstructor<
|
||||||
const newCol = new col.constructor(rowOffsets.length);
|
typeof col
|
||||||
|
>)(rowOffsets.length);
|
||||||
for (let i = 0, l = rowOffsets.length; i < l; i += 1) {
|
for (let i = 0, l = rowOffsets.length; i < l; i += 1) {
|
||||||
newCol[i] = col[rowOffsets[i]];
|
const rowOffset = rowOffsets[i];
|
||||||
|
if (rowOffset === -1) throw new RangeError("Unexpected row offset.");
|
||||||
|
newCol[i] = col[rowOffset];
|
||||||
}
|
}
|
||||||
return newCol;
|
return newCol;
|
||||||
});
|
});
|
||||||
@@ -650,8 +683,11 @@ class Dataframe {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
subset(
|
||||||
subset(rowLabels: any, colLabels = null, withRowIndex = null) {
|
rowLabels: LabelArray | null,
|
||||||
|
colLabels: LabelArray | null,
|
||||||
|
withRowIndex?: LabelIndex | null
|
||||||
|
): Dataframe {
|
||||||
/*
|
/*
|
||||||
Subset by row/col labels.
|
Subset by row/col labels.
|
||||||
|
|
||||||
@@ -673,8 +709,11 @@ class Dataframe {
|
|||||||
return this.__subset(rowIndex, colIndex);
|
return this.__subset(rowIndex, colIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
isubset(
|
||||||
isubset(rowOffsets: any, colOffsets = null, withRowIndex = null) {
|
rowOffsets: OffsetArray | null,
|
||||||
|
colOffsets: OffsetArray | null,
|
||||||
|
withRowIndex?: LabelIndex | null
|
||||||
|
): Dataframe {
|
||||||
/*
|
/*
|
||||||
Subset by row/col offset.
|
Subset by row/col offset.
|
||||||
|
|
||||||
@@ -683,14 +722,14 @@ class Dataframe {
|
|||||||
indexing. If withRowIndex is a label index object, it will be used
|
indexing. If withRowIndex is a label index object, it will be used
|
||||||
for the new dataframe.
|
for the new dataframe.
|
||||||
*/
|
*/
|
||||||
let rowIndex = null;
|
let rowIndex: LabelIndex | null = null;
|
||||||
if (withRowIndex) {
|
if (withRowIndex) {
|
||||||
rowIndex = withRowIndex;
|
rowIndex = withRowIndex;
|
||||||
} else if (rowOffsets) {
|
} else if (rowOffsets) {
|
||||||
rowIndex = this.rowIndex.isubset(rowOffsets);
|
rowIndex = this.rowIndex.isubset(rowOffsets);
|
||||||
}
|
}
|
||||||
|
|
||||||
let colIndex = null;
|
let colIndex: LabelIndex | null = null;
|
||||||
if (colOffsets) {
|
if (colOffsets) {
|
||||||
colIndex = this.colIndex.isubset(colOffsets);
|
colIndex = this.colIndex.isubset(colOffsets);
|
||||||
}
|
}
|
||||||
@@ -698,8 +737,11 @@ class Dataframe {
|
|||||||
return this.__subset(rowIndex, colIndex);
|
return this.__subset(rowIndex, colIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
isubsetMask(
|
||||||
isubsetMask(rowMask: any, colMask = null, withRowIndex = null) {
|
rowMask: Uint8Array | boolean[] | null,
|
||||||
|
colMask: Uint8Array | boolean[] | null,
|
||||||
|
withRowIndex?: LabelIndex | null
|
||||||
|
): Dataframe {
|
||||||
/*
|
/*
|
||||||
Subset on row/column based upon a truthy/falsey array (a mask).
|
Subset on row/column based upon a truthy/falsey array (a mask).
|
||||||
|
|
||||||
@@ -711,15 +753,16 @@ class Dataframe {
|
|||||||
const [nRows, nCols] = this.dims;
|
const [nRows, nCols] = this.dims;
|
||||||
if (
|
if (
|
||||||
(rowMask && rowMask.length !== nRows) ||
|
(rowMask && rowMask.length !== nRows) ||
|
||||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
|
||||||
(colMask && colMask.length !== nCols)
|
(colMask && colMask.length !== nCols)
|
||||||
) {
|
) {
|
||||||
throw new RangeError("boolean arrays must match row/col dimensions");
|
throw new RangeError("boolean arrays must match row/col dimensions");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* convert masks to lists - method wastes space, but is fast */
|
/* convert masks to lists - method wastes space, but is fast */
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
const toList = (
|
||||||
const toList = (mask: any, maxSize: any) => {
|
mask: Uint8Array | boolean[] | null | undefined,
|
||||||
|
maxSize: number
|
||||||
|
) => {
|
||||||
if (!mask) {
|
if (!mask) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -735,7 +778,6 @@ class Dataframe {
|
|||||||
};
|
};
|
||||||
const rowOffsets = toList(rowMask, nRows);
|
const rowOffsets = toList(rowMask, nRows);
|
||||||
const colOffsets = toList(colMask, nCols);
|
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);
|
return this.isubset(rowOffsets, colOffsets, withRowIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -743,14 +785,12 @@ class Dataframe {
|
|||||||
Data access with row/col.
|
Data access with row/col.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
columns(): DataframeColumn[] {
|
||||||
columns() {
|
|
||||||
/* return all column accessors as an array, in offset order */
|
/* return all column accessors as an array, in offset order */
|
||||||
return [...this.__columnsAccessor];
|
return [...this.__columnsAccessor];
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
col(columnLabel: LabelType): DataframeColumn {
|
||||||
col(columnLabel: any) {
|
|
||||||
/*
|
/*
|
||||||
Return accessor bound to a column. Allows random row access
|
Return accessor bound to a column. Allows random row access
|
||||||
based upon the row indexing. Returns undefined if the
|
based upon the row indexing. Returns undefined if the
|
||||||
@@ -767,39 +807,44 @@ class Dataframe {
|
|||||||
See __compile() for the functions available in a column accessor.
|
See __compile() for the functions available in a column accessor.
|
||||||
*/
|
*/
|
||||||
const coff = this.colIndex.getOffset(columnLabel);
|
const coff = this.colIndex.getOffset(columnLabel);
|
||||||
|
if (coff === -1) throw RangeError("Unknown label.");
|
||||||
return this.__columnsAccessor[coff];
|
return this.__columnsAccessor[coff];
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
icol(columnOffset: OffsetType): DataframeColumn {
|
||||||
icol(columnOffset: any) {
|
|
||||||
/*
|
/*
|
||||||
Return column accessor by offset.
|
Return column accessor by offset.
|
||||||
*/
|
*/
|
||||||
return Number.isInteger(columnOffset)
|
if (
|
||||||
? this.__columnsAccessor[columnOffset]
|
Number.isInteger(columnOffset) &&
|
||||||
: undefined;
|
columnOffset >= 0 &&
|
||||||
|
columnOffset < this.__columnsAccessor.length
|
||||||
|
) {
|
||||||
|
return this.__columnsAccessor[columnOffset];
|
||||||
|
}
|
||||||
|
throw new RangeError("Unknown offset.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
at(r: LabelType, c: LabelType): DataframeValue {
|
||||||
at(r: any, c: any) {
|
|
||||||
/*
|
/*
|
||||||
Access a single value, for a row/col label pair.
|
Access a single value, for a row/col label pair.
|
||||||
|
|
||||||
For performance reasons, there are no bounds or existance
|
For performance reasons, there are no bounds or existence
|
||||||
checks on labels, and no defined behavior when these are supplied.
|
checks on labels, and no defined behavior when these are supplied.
|
||||||
May return undefined, throw an Error, or do something else for
|
May return undefined, throw an Error, or do something else for
|
||||||
non-existant labels. If you want predictable out-of-bounds
|
non-existent labels. If you want predictable out-of-bounds
|
||||||
behavior, use has(), eg,
|
behavior, use has(), eg,
|
||||||
|
|
||||||
const myVal = df.has(r,l) ? df.at(r,l) : undefined;
|
const myVal = df.has(r,l) ? df.at(r,l) : undefined;
|
||||||
*/
|
*/
|
||||||
const coff = this.colIndex.getOffset(c);
|
const coff = this.colIndex.getOffset(c);
|
||||||
const roff = this.rowIndex.getOffset(r);
|
const roff = this.rowIndex.getOffset(r);
|
||||||
|
if (coff === undefined || roff === undefined)
|
||||||
|
throw new RangeError("Unknown row or column label.");
|
||||||
return this.__columns[coff][roff];
|
return this.__columns[coff][roff];
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
iat(r: OffsetType, c: OffsetType): DataframeValue {
|
||||||
iat(r: any, c: any) {
|
|
||||||
/*
|
/*
|
||||||
Access a single value, for a row/col offset (integer) position.
|
Access a single value, for a row/col offset (integer) position.
|
||||||
|
|
||||||
@@ -809,11 +854,12 @@ class Dataframe {
|
|||||||
|
|
||||||
const myVal = df.ihas(r, c) ? df.iat(r, c) : undefined;
|
const myVal = df.ihas(r, c) ? df.iat(r, c) : undefined;
|
||||||
*/
|
*/
|
||||||
return this.__columns[c][r];
|
if (c >= 0 && c < this.dims[1] && r >= 0 && r < this.dims[0])
|
||||||
|
return this.__columns[c][r];
|
||||||
|
throw new RangeError("Unknown row or column index.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
has(r: LabelType, c: LabelType): boolean {
|
||||||
has(r: any, c: any) {
|
|
||||||
/*
|
/*
|
||||||
Test if row/col labels exist in the dataframe - returns true/false
|
Test if row/col labels exist in the dataframe - returns true/false
|
||||||
*/
|
*/
|
||||||
@@ -823,8 +869,7 @@ class Dataframe {
|
|||||||
return coff >= 0 && coff < nCols && roff >= 0 && roff < nRows;
|
return coff >= 0 && coff < nCols && roff >= 0 && roff < nRows;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
ihas(r: number, c: number): boolean {
|
||||||
ihas(r: any, c: any) {
|
|
||||||
/*
|
/*
|
||||||
Test if row/col offset (integer) position exists in the
|
Test if row/col offset (integer) position exists in the
|
||||||
dataframe - returns true/false
|
dataframe - returns true/false
|
||||||
@@ -840,16 +885,23 @@ class Dataframe {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
hasCol(c: LabelType): boolean {
|
||||||
hasCol(c: any) {
|
|
||||||
/*
|
/*
|
||||||
Test if col label exists - return true/false
|
Test if col label exists - return true/false
|
||||||
*/
|
*/
|
||||||
return !!this.col(c);
|
const coff = this.colIndex.getOffset(c);
|
||||||
|
return coff !== -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
ihasCol(i: number): boolean {
|
||||||
isEmpty() {
|
/*
|
||||||
|
Test if col offset exists - return true/false
|
||||||
|
*/
|
||||||
|
const [, nCols] = this.dims;
|
||||||
|
return i >= 0 && i < nCols;
|
||||||
|
}
|
||||||
|
|
||||||
|
isEmpty(): boolean {
|
||||||
/*
|
/*
|
||||||
Return true if this is an empty dataframe, ie, has dimensions [0,0]
|
Return true if this is an empty dataframe, ie, has dimensions [0,0]
|
||||||
*/
|
*/
|
||||||
@@ -864,24 +916,20 @@ class Dataframe {
|
|||||||
add these as useful.
|
add these as useful.
|
||||||
****/
|
****/
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
mapColumns(callback: MapColumnsCallbackFn): Dataframe {
|
||||||
mapColumns(callback: any) {
|
|
||||||
/*
|
/*
|
||||||
map all columns in the dataframe, returning a new dataframe comprised of the
|
map all columns in the dataframe, returning a new dataframe comprised of the
|
||||||
return values, with the same index as the original dataframe.
|
return values, with the same index as the original dataframe.
|
||||||
|
|
||||||
callback MUST not modify the column, but instead return a mutated copy.
|
callback MUST not modify the column, but instead return a mutated copy.
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
const columns = this.__columns.map((colData, colIdx) =>
|
||||||
const columns = this.__columns.map((colData: any, colIdx: any) =>
|
|
||||||
callback(colData, colIdx, this)
|
callback(colData, colIdx, this)
|
||||||
);
|
);
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
const columnsAccessor: (DataframeColumn | null)[] = columns.map((c, idx) =>
|
||||||
const columnsAccessor = columns.map((c: any, idx: any) =>
|
this.__columns[idx] === c ? this.__columnsAccessor[idx] : null
|
||||||
this.__columns[idx] === c ? this.__columnsAccessor[idx] : undefined
|
|
||||||
);
|
);
|
||||||
// @ts-expect-error ts-migrate(2351) FIXME: This expression is not constructable.
|
return new (this.constructor as DataframeConstructor)(
|
||||||
return new this.constructor(
|
|
||||||
this.dims,
|
this.dims,
|
||||||
columns,
|
columns,
|
||||||
this.rowIndex,
|
this.rowIndex,
|
||||||
@@ -889,29 +937,6 @@ class Dataframe {
|
|||||||
columnsAccessor
|
columnsAccessor
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Map & reduce of column or row
|
|
||||||
|
|
||||||
TODO remainder of map/reduce functions: mapCol, mapRow, reduceRow, ...
|
|
||||||
*/
|
|
||||||
/* comment out until we have a use for this
|
|
||||||
|
|
||||||
reduceCol(clabel, callback, initialValue) {
|
|
||||||
const coff = this.colIndex.getOffset(clabel);
|
|
||||||
const column = this.__columns[coff];
|
|
||||||
let start = 0;
|
|
||||||
let acc = initialValue;
|
|
||||||
if (initialValue === undefined) {
|
|
||||||
acc = column[0];
|
|
||||||
start = 1;
|
|
||||||
}
|
|
||||||
for (let i = start, l = column.length; i < l; i += 1) {
|
|
||||||
acc = callback(acc, column[i]);
|
|
||||||
}
|
|
||||||
return acc;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Dataframe;
|
export default Dataframe;
|
||||||
|
|||||||
@@ -1,16 +1,27 @@
|
|||||||
/*
|
/*
|
||||||
Dataframe histogram
|
Dataframe histogram
|
||||||
*/
|
*/
|
||||||
import { isTypedArray } from "../../common/types/arraytypes";
|
import { NumberArray } from "../../common/types/arraytypes";
|
||||||
|
import {
|
||||||
|
DataframeColumn,
|
||||||
|
ContinuousHistogram,
|
||||||
|
ContinuousHistogramBy,
|
||||||
|
CategoricalHistogram,
|
||||||
|
CategoricalHistogramBy,
|
||||||
|
} from "./types";
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
export function histogramContinuous(
|
||||||
function _histogramContinuous(column: any, bins: any, min: any, max: any) {
|
column: DataframeColumn,
|
||||||
|
bins: number,
|
||||||
|
domain: [number, number]
|
||||||
|
): ContinuousHistogram {
|
||||||
const valBins = new Array(bins).fill(0);
|
const valBins = new Array(bins).fill(0);
|
||||||
if (!column) {
|
if (!column) {
|
||||||
return valBins;
|
return valBins;
|
||||||
}
|
}
|
||||||
|
const [min, max] = domain;
|
||||||
const binWidth = (max - min) / bins;
|
const binWidth = (max - min) / bins;
|
||||||
const colArray = column.asArray();
|
const colArray: NumberArray = column.asArray() as NumberArray;
|
||||||
for (let r = 0, len = colArray.length; r < len; r += 1) {
|
for (let r = 0, len = colArray.length; r < len; r += 1) {
|
||||||
const val = colArray[r];
|
const val = colArray[r];
|
||||||
if (val <= max && val >= min) {
|
if (val <= max && val >= min) {
|
||||||
@@ -22,25 +33,20 @@ function _histogramContinuous(column: any, bins: any, min: any, max: any) {
|
|||||||
return valBins;
|
return valBins;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _histogramContinuousBy(
|
export function histogramContinuousBy(
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
column: DataframeColumn,
|
||||||
column: any,
|
bins: number,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
domain: [number, number],
|
||||||
bins: any,
|
by: DataframeColumn
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
): ContinuousHistogramBy {
|
||||||
min: any,
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
|
||||||
max: any,
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
|
||||||
by: any
|
|
||||||
) {
|
|
||||||
const byMap = new Map();
|
const byMap = new Map();
|
||||||
if (!column || !by) {
|
if (!column || !by) {
|
||||||
return byMap;
|
return byMap;
|
||||||
}
|
}
|
||||||
|
const [min, max] = domain;
|
||||||
const binWidth = (max - min) / bins;
|
const binWidth = (max - min) / bins;
|
||||||
const byArray = by.asArray();
|
const byArray = by.asArray();
|
||||||
const colArray = column.asArray();
|
const colArray = column.asArray() as NumberArray;
|
||||||
for (let r = 0, len = colArray.length; r < len; r += 1) {
|
for (let r = 0, len = colArray.length; r < len; r += 1) {
|
||||||
const byBin = byArray[r];
|
const byBin = byArray[r];
|
||||||
let valBins = byMap.get(byBin);
|
let valBins = byMap.get(byBin);
|
||||||
@@ -58,8 +64,9 @@ function _histogramContinuousBy(
|
|||||||
return byMap;
|
return byMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
export function histogramCategorical(
|
||||||
function _histogramCategorical(column: any) {
|
column: DataframeColumn
|
||||||
|
): CategoricalHistogram {
|
||||||
const valMap = new Map();
|
const valMap = new Map();
|
||||||
if (!column) {
|
if (!column) {
|
||||||
return valMap;
|
return valMap;
|
||||||
@@ -76,8 +83,10 @@ function _histogramCategorical(column: any) {
|
|||||||
return valMap;
|
return valMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
export function histogramCategoricalBy(
|
||||||
function _histogramCategoricalBy(column: any, by: any) {
|
column: DataframeColumn,
|
||||||
|
by: DataframeColumn
|
||||||
|
): CategoricalHistogramBy {
|
||||||
const byMap = new Map();
|
const byMap = new Map();
|
||||||
if (!column || !by) {
|
if (!column || !by) {
|
||||||
return byMap;
|
return byMap;
|
||||||
@@ -101,67 +110,38 @@ function _histogramCategoricalBy(column: any, by: any) {
|
|||||||
return byMap;
|
return byMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Count category occupancy. Optional group-by category.
|
|
||||||
*/
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
|
||||||
export function histogramCategorical(column: any, by: any) {
|
|
||||||
if (by && isTypedArray(by)) {
|
|
||||||
throw new Error("Group by column must be categorical");
|
|
||||||
}
|
|
||||||
return by
|
|
||||||
? _histogramCategoricalBy(column, by)
|
|
||||||
: _histogramCategorical(column);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Memoization hash for histogramCategorical()
|
Memoization hash for histogramCategorical()
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
export function hashCategorical(column: DataframeColumn): string {
|
||||||
export function hashCategorical(column: any, by: any) {
|
|
||||||
if (by) {
|
|
||||||
return `${column.__id}:${by.__id}`;
|
|
||||||
}
|
|
||||||
return `${column.__id}:`;
|
return `${column.__id}:`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
export function hashCategoricalBy(
|
||||||
Bin counts for continuous/scalar values, with optional group-by category.
|
column: DataframeColumn,
|
||||||
Values outside domain are ignored.
|
by: DataframeColumn
|
||||||
*/
|
): string {
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
return `${column.__id}:${by.__id}`;
|
||||||
export function histogramContinuous(
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
|
||||||
column: any,
|
|
||||||
bins = 40,
|
|
||||||
domain = [0, 1],
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
|
||||||
by: any
|
|
||||||
) {
|
|
||||||
if (by && isTypedArray(by)) {
|
|
||||||
throw new Error("Group by column must be categorical");
|
|
||||||
}
|
|
||||||
const [min, max] = domain;
|
|
||||||
return by
|
|
||||||
? _histogramContinuousBy(column, bins, min, max, by)
|
|
||||||
: _histogramContinuous(column, bins, min, max);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Memoization hash for histogramContinuous
|
Memoization hash for histogramContinuous
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
|
||||||
export function hashContinuous(
|
export function hashContinuous(
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
column: DataframeColumn,
|
||||||
column: any,
|
bins: number,
|
||||||
bins = "",
|
domain: [number, number]
|
||||||
domain = [0, 0],
|
): string {
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
|
||||||
by: any
|
|
||||||
) {
|
|
||||||
const [min, max] = domain;
|
const [min, max] = domain;
|
||||||
if (by) {
|
|
||||||
return `${column.__id}:${bins}:${min}:${max}:${by.__id}`;
|
|
||||||
}
|
|
||||||
return `${column.__id}::${bins}:${min}:${max}`;
|
return `${column.__id}::${bins}:${min}:${max}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function hashContinuousBy(
|
||||||
|
column: DataframeColumn,
|
||||||
|
bins: number,
|
||||||
|
domain: [number, number],
|
||||||
|
by: DataframeColumn
|
||||||
|
): string {
|
||||||
|
const [min, max] = domain;
|
||||||
|
return `${column.__id}:${bins}:${min}:${max}:${by.__id}`;
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,3 +6,16 @@ export {
|
|||||||
isLabelIndex,
|
isLabelIndex,
|
||||||
} from "./labelIndex";
|
} from "./labelIndex";
|
||||||
export { default as dataframeMemo } from "./cache";
|
export { default as dataframeMemo } from "./cache";
|
||||||
|
export type {
|
||||||
|
LabelType,
|
||||||
|
DataframeValue,
|
||||||
|
DataframeValueArray,
|
||||||
|
DataframeColumn,
|
||||||
|
ContinuousHistogram,
|
||||||
|
ContinuousHistogramBy,
|
||||||
|
CategoricalHistogram,
|
||||||
|
CategoricalHistogramBy,
|
||||||
|
ContinuousColumnSummary,
|
||||||
|
CategoricalColumnSummary,
|
||||||
|
} from "./types";
|
||||||
|
export type { LabelIndex } from "./labelIndex";
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
/* eslint-disable max-classes-per-file -- Classes are interrelated*/
|
/* eslint-disable max-classes-per-file -- Classes are interrelated*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Label indexing - map a label to & from an integer offset. See Dataframe
|
Label indexing - map a label to & from an integer offset. See Dataframe
|
||||||
for how this is used.
|
for how this is used.
|
||||||
@@ -6,45 +7,78 @@ for how this is used.
|
|||||||
|
|
||||||
import { rangeFill as fillRange } from "../range";
|
import { rangeFill as fillRange } from "../range";
|
||||||
import { __getMemoId } from "./util";
|
import { __getMemoId } from "./util";
|
||||||
|
import { OffsetArray, LabelType, LabelArray, GenericLabelArray } from "./types";
|
||||||
|
|
||||||
/*
|
export abstract class LabelIndexBase {
|
||||||
Private utility functions
|
readonly __id: string; // memoization helper
|
||||||
*/
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
constructor(id: string) {
|
||||||
function extent(tarr: any) {
|
this.__id = id;
|
||||||
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) {
|
|
||||||
const v = tarr[i];
|
|
||||||
if (v < min) {
|
|
||||||
min = v;
|
|
||||||
}
|
|
||||||
if (v > max) {
|
|
||||||
max = v;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return [min, max];
|
|
||||||
|
abstract labels(): LabelArray;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look up the offset for the label.
|
||||||
|
*
|
||||||
|
* @param label - label to look up
|
||||||
|
* @returns - offset number or -1 if not found.
|
||||||
|
*/
|
||||||
|
abstract getOffset(label: LabelType): number;
|
||||||
|
|
||||||
|
getOffsets(labels: LabelArray): Int32Array {
|
||||||
|
// labels to offsets
|
||||||
|
const result = new Int32Array(labels.length);
|
||||||
|
for (let i = 0; i < labels.length; i += 1) {
|
||||||
|
result[i] = this.getOffset(labels[i]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look up the label for the offset.
|
||||||
|
*
|
||||||
|
* @param offset - offset to look up
|
||||||
|
* @returns - label or undefined if not found.
|
||||||
|
*/
|
||||||
|
abstract getLabel(offset: number): LabelType | undefined;
|
||||||
|
|
||||||
|
getLabels(offsets: OffsetArray): (LabelType | undefined)[] {
|
||||||
|
// offsets to labels
|
||||||
|
const result = new Array(offsets.length);
|
||||||
|
for (let i = 0; i < offsets.length; i += 1) {
|
||||||
|
result[i] = this.getLabel(offsets[i]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract size(): number;
|
||||||
|
|
||||||
|
abstract subset(labels: LabelArray): LabelIndexBase;
|
||||||
|
|
||||||
|
abstract isubset(offsets: OffsetArray): LabelIndexBase;
|
||||||
|
|
||||||
|
abstract isubsetMask(mask: Uint8Array | boolean[]): LabelIndexBase;
|
||||||
|
|
||||||
|
abstract withLabel(label: LabelType): LabelIndexBase;
|
||||||
|
|
||||||
|
abstract withLabels(labels: LabelArray): LabelIndexBase;
|
||||||
|
|
||||||
|
abstract dropLabel(label: LabelType): LabelIndexBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
class IdentityInt32Index {
|
export class IdentityInt32Index extends LabelIndexBase {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
readonly maxOffset: number;
|
||||||
maxOffset: any;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
identity/noop index, with small assumptions that labels are int32
|
identity/noop index, with small assumptions that labels are int32
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
constructor(maxOffset: number) {
|
||||||
constructor(maxOffset: any) {
|
super(`IdentityInt32Index_${maxOffset}`);
|
||||||
this.maxOffset = maxOffset;
|
this.maxOffset = maxOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
labels(): LabelArray {
|
||||||
get __id() {
|
|
||||||
return `IdentityInt32Index_${this.maxOffset}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
|
||||||
labels() {
|
|
||||||
// memoize
|
// memoize
|
||||||
const k = fillRange(new Int32Array(this.maxOffset));
|
const k = fillRange(new Int32Array(this.maxOffset));
|
||||||
this.labels = function labels() {
|
this.labels = function labels() {
|
||||||
@@ -53,77 +87,79 @@ class IdentityInt32Index {
|
|||||||
return k;
|
return k;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
getOffset(label: LabelType): number {
|
||||||
getOffset(i: any) {
|
|
||||||
// label to offset
|
// label to offset
|
||||||
return Number.isInteger(i) && i >= 0 && i < this.maxOffset ? i : undefined;
|
return Number.isInteger(label) && label >= 0 && label < this.maxOffset
|
||||||
|
? (label as number)
|
||||||
|
: -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
getLabel(offset: number): number | undefined {
|
||||||
getOffsets(arr: any) {
|
|
||||||
// labels to offsets
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
|
||||||
return arr.map((i: any) => this.getOffset(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
|
||||||
getLabel(i: any) {
|
|
||||||
// offset to label
|
// offset to label
|
||||||
return Number.isInteger(i) && i >= 0 && i < this.maxOffset ? i : undefined;
|
return Number.isInteger(offset) && offset >= 0 && offset < this.maxOffset
|
||||||
|
? offset
|
||||||
|
: undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
size(): number {
|
||||||
getLabels(arr: any) {
|
|
||||||
// offsets to labels
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
|
||||||
return arr.map((i: any) => this.getLabel(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
|
||||||
size() {
|
|
||||||
return this.maxOffset;
|
return this.maxOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
/** @internal */
|
||||||
__promote(labelArray: any) {
|
__promote(labelArray: LabelArray, allInts: boolean): LabelIndexBase {
|
||||||
/*
|
/*
|
||||||
time/space decision - based on the resulting density
|
time/space decision - based on the resulting density
|
||||||
*/
|
*/
|
||||||
const [minLabel, maxLabel] = extent(labelArray);
|
if (labelArray.length === 0) return new KeyIndex(Array.from(labelArray));
|
||||||
if (minLabel === 0 && maxLabel === labelArray.length - 1)
|
if (allInts) {
|
||||||
return new IdentityInt32Index(labelArray.length);
|
const [minLabel, maxLabel] = extent(
|
||||||
|
labelArray as GenericLabelArray<number> // safe, as allInts is true
|
||||||
|
);
|
||||||
|
if (minLabel === 0 && maxLabel === labelArray.length - 1)
|
||||||
|
return new IdentityInt32Index(labelArray.length);
|
||||||
|
|
||||||
const labelSpaceSize = maxLabel - minLabel + 1;
|
const labelSpaceSize = maxLabel - minLabel + 1;
|
||||||
const density = labelSpaceSize / this.maxOffset;
|
const density = labelSpaceSize / this.maxOffset;
|
||||||
/* 0.1 is a magic number, that needs testing to optimize */
|
/* 0.1 is a magic number which needs testing to optimize */
|
||||||
if (density < 0.1) {
|
if (density < 0.1) {
|
||||||
return new KeyIndex(labelArray);
|
return new KeyIndex(Array.from(labelArray));
|
||||||
|
}
|
||||||
|
return new DenseInt32Index(labelArray as GenericLabelArray<number>, [
|
||||||
|
minLabel,
|
||||||
|
maxLabel,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
// @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 KeyIndex(Array.from(labelArray));
|
||||||
return new DenseInt32Index(labelArray, [minLabel, maxLabel]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
subset(labels: LabelArray): LabelIndexBase {
|
||||||
subset(labels: any) {
|
|
||||||
/* validate subset */
|
/* validate subset */
|
||||||
const { maxOffset } = this;
|
const { maxOffset } = this;
|
||||||
for (let i = 0, l = labels.length; i < l; i += 1) {
|
for (let i = 0, l = labels.length; i < l; i += 1) {
|
||||||
const label = labels[i];
|
const label = labels[i];
|
||||||
if (!Number.isInteger(label) || label < 0 || label >= maxOffset)
|
if (!Number.isInteger(label) || label < 0 || label >= maxOffset)
|
||||||
throw new RangeError(`offset or label: ${label}`);
|
throw new RangeError(`label: ${label}`);
|
||||||
}
|
}
|
||||||
return this.__promote(labels);
|
return this.__promote(labels, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* identity index - labels are offsets */
|
/* identity index - labels are offsets */
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
isubset(offsets: OffsetArray): LabelIndexBase {
|
||||||
isubset(offsets: any) {
|
/* validate isubset */
|
||||||
return this.subset(offsets);
|
const { maxOffset } = this;
|
||||||
|
for (let i = 0, l = offsets.length; i < l; i += 1) {
|
||||||
|
const offset = offsets[i];
|
||||||
|
if (!Number.isInteger(offset) || offset < 0 || offset >= maxOffset)
|
||||||
|
throw new RangeError(`offset: ${offset}`);
|
||||||
|
}
|
||||||
|
if (!(offsets instanceof Int32Array)) {
|
||||||
|
offsets = new Int32Array(offsets);
|
||||||
|
}
|
||||||
|
return this.__promote(offsets, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* identity index - labels are offsets */
|
/* identity index - labels are offsets */
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
isubsetMask(mask: Uint8Array | boolean[]): LabelIndexBase {
|
||||||
isubsetMask(mask: any) {
|
|
||||||
let count = 0;
|
let count = 0;
|
||||||
if (mask.length !== this.maxOffset) {
|
if (mask.length !== this.maxOffset) {
|
||||||
throw new RangeError("mask has invalid length for index");
|
throw new RangeError("mask has invalid length for index");
|
||||||
@@ -139,54 +175,42 @@ class IdentityInt32Index {
|
|||||||
return this.subset(labels);
|
return this.subset(labels);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
withLabel(label: LabelType): LabelIndexBase {
|
||||||
withLabel(label: any) {
|
|
||||||
if (label === this.maxOffset) {
|
if (label === this.maxOffset) {
|
||||||
return new IdentityInt32Index(label + 1);
|
return new IdentityInt32Index(label + 1);
|
||||||
}
|
}
|
||||||
return this.__promote([...this.labels(), label]);
|
return this.__promote([...this.labels(), label], Number.isInteger(label));
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
withLabels(labels: LabelArray): LabelIndexBase {
|
||||||
withLabels(labels: any) {
|
return this.__promote(
|
||||||
return this.__promote([...this.labels(), ...labels]);
|
[...this.labels(), ...labels],
|
||||||
|
labels.every(Number.isInteger)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
dropLabel(label: LabelType): LabelIndexBase {
|
||||||
dropLabel(label: any) {
|
if (!Number.isInteger(label) || label < 0 || label > this.maxOffset - 1)
|
||||||
|
throw new RangeError("Invalid label.");
|
||||||
if (label === this.maxOffset - 1) {
|
if (label === this.maxOffset - 1) {
|
||||||
return new IdentityInt32Index(label);
|
return new IdentityInt32Index(label);
|
||||||
}
|
}
|
||||||
const labelArray = [...this.labels()];
|
const labelArray = [...this.labels()];
|
||||||
labelArray.splice(labelArray.indexOf(label), 1);
|
labelArray.splice(labelArray.indexOf(label as number), 1);
|
||||||
return this.__promote(labelArray);
|
return this.__promote(labelArray, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DenseInt32Index {
|
export class DenseInt32Index extends LabelIndexBase {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
getLabel: (offset: number) => number | undefined;
|
||||||
__id: any;
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
getOffset: (label: LabelType) => number;
|
||||||
getLabel: any;
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
index: Int32Array;
|
||||||
getLabels: any;
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
minLabel: number;
|
||||||
getOffset: any;
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
rindex: Int32Array;
|
||||||
getOffsets: any;
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
|
||||||
index: any;
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
|
||||||
minLabel: any;
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
|
||||||
rindex: any;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
DenseInt32Index indexes integer labels, and uses Int32Array typed arrays
|
DenseInt32Index indexes integer labels, and uses Int32Array typed arrays
|
||||||
@@ -194,17 +218,16 @@ class DenseInt32Index {
|
|||||||
of the forward index labels must be known a priori (so that the index
|
of the forward index labels must be known a priori (so that the index
|
||||||
array can be pre-allocated).
|
array can be pre-allocated).
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
constructor(
|
||||||
constructor(labels: any, labelRange = null) {
|
labels: GenericLabelArray<number>,
|
||||||
if (labels.constructor !== Int32Array) {
|
labelRange?: [number, number]
|
||||||
labels = new Int32Array(labels);
|
) {
|
||||||
}
|
super(__getMemoId());
|
||||||
|
const int32Labels =
|
||||||
|
labels instanceof Int32Array ? labels : new Int32Array(labels);
|
||||||
if (!labelRange) {
|
if (!labelRange) {
|
||||||
// @ts-expect-error ts-migrate(2322) FIXME: Type 'number[]' is not assignable to type 'null'.
|
labelRange = extent(int32Labels);
|
||||||
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 [minLabel, maxLabel] = labelRange;
|
||||||
const labelSpaceSize = maxLabel - minLabel + 1;
|
const labelSpaceSize = maxLabel - minLabel + 1;
|
||||||
const index = new Int32Array(labelSpaceSize).fill(-1);
|
const index = new Int32Array(labelSpaceSize).fill(-1);
|
||||||
@@ -214,82 +237,70 @@ class DenseInt32Index {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.minLabel = minLabel;
|
this.minLabel = minLabel;
|
||||||
this.rindex = labels;
|
this.rindex = int32Labels;
|
||||||
this.index = index;
|
this.index = index;
|
||||||
this.__id = __getMemoId();
|
|
||||||
this.__compile();
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
this.getOffset = function getOffset(label: LabelType) {
|
||||||
__compile() {
|
if (!Number.isInteger(label)) return -1;
|
||||||
const { minLabel, index, rindex } = this;
|
const lblIdx: number = <number>label - minLabel;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
if (lblIdx < 0 || lblIdx >= index.length) return -1;
|
||||||
this.getOffset = function getOffset(l: any) {
|
const offset = index[lblIdx];
|
||||||
if (!Number.isInteger(l)) return undefined;
|
return offset;
|
||||||
const offset = index[l - minLabel];
|
|
||||||
return offset === -1 ? undefined : offset;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
this.getLabel = function getLabel(offset: number) {
|
||||||
this.getOffsets = function getOffsets(arr: any) {
|
return Number.isInteger(offset) ? labels[offset] : undefined;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
|
||||||
return arr.map((i: any) => this.getOffset(i));
|
|
||||||
};
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
|
||||||
this.getLabel = function getLabel(i: any) {
|
|
||||||
return Number.isInteger(i) ? rindex[i] : undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
|
||||||
this.getLabels = function getLabels(arr: any) {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
|
||||||
return arr.map((i: any) => this.getLabel(i));
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
labels(): LabelArray {
|
||||||
labels() {
|
|
||||||
return this.rindex;
|
return this.rindex;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
size(): number {
|
||||||
size() {
|
|
||||||
return this.rindex.length;
|
return this.rindex.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
/** @internal */
|
||||||
__promote(labelArray: any) {
|
__promote(labelArray: LabelArray, allInts: boolean): LabelIndexBase {
|
||||||
/*
|
/*
|
||||||
time/space decision - if we are going to use less than 10% of the
|
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
|
dense index space, switch to a KeyIndex (which is slower, but uses
|
||||||
less memory for sparse label spaces).
|
less memory for sparse label spaces).
|
||||||
*/
|
*/
|
||||||
const [minLabel, maxLabel] = extent(labelArray);
|
if (labelArray.length === 0) return new KeyIndex(Array.from(labelArray));
|
||||||
const labelSpaceSize = maxLabel - minLabel + 1;
|
if (allInts) {
|
||||||
const density = labelSpaceSize / this.rindex.length;
|
if (!(labelArray instanceof Int32Array)) {
|
||||||
/* 0.1 is a magic number, that needs testing to optimize */
|
labelArray = new Int32Array(labelArray as number[]);
|
||||||
if (density < 0.1) {
|
}
|
||||||
return new KeyIndex(labelArray);
|
const [minLabel, maxLabel] = extent(
|
||||||
|
labelArray as GenericLabelArray<number> // safe, as allInts is true
|
||||||
|
);
|
||||||
|
const labelSpaceSize = maxLabel - minLabel + 1;
|
||||||
|
const density = labelSpaceSize / this.rindex.length;
|
||||||
|
/* 0.1 is a magic number, that needs testing to optimize */
|
||||||
|
if (density < 0.1) {
|
||||||
|
return new KeyIndex(Array.from(labelArray));
|
||||||
|
}
|
||||||
|
return new DenseInt32Index(labelArray as GenericLabelArray<number>, [
|
||||||
|
minLabel,
|
||||||
|
maxLabel,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
// @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 KeyIndex(Array.from(labelArray));
|
||||||
return new DenseInt32Index(labelArray, [minLabel, maxLabel]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
subset(labels: LabelArray): LabelIndexBase {
|
||||||
subset(labels: any) {
|
|
||||||
/* validate subset */
|
/* validate subset */
|
||||||
for (let i = 0, l = labels.length; i < l; i += 1) {
|
for (let i = 0, l = labels.length; i < l; i += 1) {
|
||||||
const label = labels[i];
|
const label = labels[i]; // if not a number, getOffset will error
|
||||||
const offset = this.getOffset(label);
|
const offset = this.getOffset(label as number);
|
||||||
if (offset === undefined || offset === -1)
|
if (offset === -1) throw new RangeError(`unknown label: ${label}`);
|
||||||
throw new RangeError(`unknown label: ${label}`);
|
|
||||||
}
|
}
|
||||||
return this.__promote(labels);
|
return this.__promote(labels as GenericLabelArray<number>, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
isubset(offsets: OffsetArray): LabelIndexBase {
|
||||||
isubset(offsets: any) {
|
|
||||||
/* validate subset */
|
/* validate subset */
|
||||||
const { rindex } = this;
|
const { rindex } = this;
|
||||||
const maxOffset = rindex.length;
|
const maxOffset = rindex.length;
|
||||||
@@ -300,11 +311,10 @@ class DenseInt32Index {
|
|||||||
throw new RangeError(`out of bounds offset: ${offset}`);
|
throw new RangeError(`out of bounds offset: ${offset}`);
|
||||||
labels[i] = rindex[offset];
|
labels[i] = rindex[offset];
|
||||||
}
|
}
|
||||||
return this.__promote(labels);
|
return this.__promote(labels, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
isubsetMask(mask: Uint8Array | boolean[]): LabelIndexBase {
|
||||||
isubsetMask(mask: any) {
|
|
||||||
const { rindex } = this;
|
const { rindex } = this;
|
||||||
if (mask.length !== rindex.length)
|
if (mask.length !== rindex.length)
|
||||||
throw new RangeError("mask has invalid length for index");
|
throw new RangeError("mask has invalid length for index");
|
||||||
@@ -317,62 +327,55 @@ class DenseInt32Index {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
labels = labels.slice(0, count);
|
labels = labels.slice(0, count);
|
||||||
return this.__promote(labels);
|
return this.__promote(labels, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
withLabel(label: LabelType): LabelIndexBase {
|
||||||
withLabel(label: any) {
|
return this.__promote([...this.labels(), label], Number.isInteger(label));
|
||||||
return this.__promote([...this.labels(), label]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
withLabels(labels: LabelArray): LabelIndexBase {
|
||||||
withLabels(labels: any) {
|
return this.__promote(
|
||||||
return this.__promote([...this.labels(), ...labels]);
|
[...this.labels(), ...labels],
|
||||||
|
labels.every(Number.isInteger)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
dropLabel(label: LabelType): LabelIndexBase {
|
||||||
dropLabel(label: any) {
|
if (!Number.isInteger(label)) throw new RangeError("Invalid label.");
|
||||||
const labelArray = [...this.labels()];
|
const labelArray = [...this.labels()];
|
||||||
labelArray.splice(labelArray.indexOf(label), 1);
|
labelArray.splice(labelArray.indexOf(label as number), 1);
|
||||||
return this.__promote(labelArray);
|
return this.__promote(
|
||||||
|
new Int32Array(labelArray as GenericLabelArray<number>),
|
||||||
|
true
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class KeyIndex {
|
export class KeyIndex extends LabelIndexBase {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
getLabel: (offset: number) => LabelType | undefined;
|
||||||
__id: any;
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
getOffset: (label: LabelType) => number | -1;
|
||||||
getLabel: any;
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
index: Map<string | number, number>;
|
||||||
getLabels: any;
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
rindex: (string | number)[];
|
||||||
getOffset: any;
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
|
||||||
getOffsets: any;
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
|
||||||
index: any;
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
|
||||||
rindex: any;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
KeyIndex indexes arbitrary JS primitive types, and uses a Map()
|
KeyIndex indexes arbitrary JS primitive types, and uses a Map()
|
||||||
as its core data structure.
|
as its core data structure.
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
constructor(labels: Array<string | number>) {
|
||||||
constructor(labels: any) {
|
super(__getMemoId());
|
||||||
const index = new Map();
|
const index = new Map<string | number, number>();
|
||||||
if (labels === undefined) {
|
if (labels === undefined) {
|
||||||
labels = [];
|
labels = [];
|
||||||
}
|
}
|
||||||
|
if (!Array.isArray(labels)) {
|
||||||
|
labels = Array.from(labels);
|
||||||
|
}
|
||||||
const rindex = labels;
|
const rindex = labels;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
labels.forEach((v, i) => {
|
||||||
labels.forEach((v: any, i: any) => {
|
|
||||||
index.set(v, i);
|
index.set(v, i);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -383,48 +386,27 @@ class KeyIndex {
|
|||||||
|
|
||||||
this.index = index;
|
this.index = index;
|
||||||
this.rindex = rindex;
|
this.rindex = rindex;
|
||||||
this.__id = __getMemoId();
|
|
||||||
this.__compile();
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
this.getOffset = function getOffset(label: LabelType) {
|
||||||
__compile() {
|
const offset = index.get(label);
|
||||||
const { index, rindex } = this;
|
if (offset === undefined) return -1;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
return offset;
|
||||||
this.getOffset = function getOffset(k: any) {
|
|
||||||
return index.get(k);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
this.getLabel = function getLabel(offset: number) {
|
||||||
this.getOffsets = function getOffsets(arr: any) {
|
return Number.isInteger(offset) ? rindex[offset] : undefined;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
|
||||||
return arr.map((l: any) => this.getOffset(l));
|
|
||||||
};
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
|
||||||
this.getLabel = function getLabel(i: any) {
|
|
||||||
return Number.isInteger(i) ? rindex[i] : undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
|
||||||
this.getLabels = function getLabels(arr: any) {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
|
||||||
return arr.map((i: any) => this.getLabel(i));
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
labels(): LabelArray {
|
||||||
labels() {
|
|
||||||
return this.rindex;
|
return this.rindex;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
size(): number {
|
||||||
size() {
|
|
||||||
return this.rindex.length;
|
return this.rindex.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
subset(labels: (string | number)[]): LabelIndexBase {
|
||||||
subset(labels: any) {
|
|
||||||
/* validate subset */
|
/* validate subset */
|
||||||
for (let i = 0, l = labels.length; i < l; i += 1) {
|
for (let i = 0, l = labels.length; i < l; i += 1) {
|
||||||
const label = labels[i];
|
const label = labels[i];
|
||||||
@@ -437,8 +419,7 @@ class KeyIndex {
|
|||||||
return new KeyIndex(labels);
|
return new KeyIndex(labels);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
isubset(offsets: OffsetArray): LabelIndexBase {
|
||||||
isubset(offsets: any) {
|
|
||||||
const { rindex } = this;
|
const { rindex } = this;
|
||||||
const maxOffset = rindex.length;
|
const maxOffset = rindex.length;
|
||||||
const labels = new Array(offsets.length);
|
const labels = new Array(offsets.length);
|
||||||
@@ -452,8 +433,7 @@ class KeyIndex {
|
|||||||
return new KeyIndex(labels);
|
return new KeyIndex(labels);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
isubsetMask(mask: Uint8Array | boolean[]): LabelIndexBase {
|
||||||
isubsetMask(mask: any) {
|
|
||||||
const { rindex } = this;
|
const { rindex } = this;
|
||||||
if (mask.length !== rindex.length)
|
if (mask.length !== rindex.length)
|
||||||
throw new RangeError("mask has invalid length for index");
|
throw new RangeError("mask has invalid length for index");
|
||||||
@@ -469,18 +449,15 @@ class KeyIndex {
|
|||||||
return new KeyIndex(labels);
|
return new KeyIndex(labels);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
withLabel(label: LabelType): LabelIndexBase {
|
||||||
withLabel(label: any) {
|
|
||||||
return new KeyIndex([...this.rindex, label]);
|
return new KeyIndex([...this.rindex, label]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
withLabels(labels: LabelArray): LabelIndexBase {
|
||||||
withLabels(labels: any) {
|
|
||||||
return new KeyIndex([...this.rindex, ...labels]);
|
return new KeyIndex([...this.rindex, ...labels]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
dropLabel(label: LabelType): LabelIndexBase {
|
||||||
dropLabel(label: any) {
|
|
||||||
const idx = this.rindex.indexOf(label);
|
const idx = this.rindex.indexOf(label);
|
||||||
const labelArray = [...this.rindex];
|
const labelArray = [...this.rindex];
|
||||||
labelArray.splice(idx, 1);
|
labelArray.splice(idx, 1);
|
||||||
@@ -488,14 +465,31 @@ class KeyIndex {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
export type LabelIndex = LabelIndexBase;
|
||||||
function isLabelIndex(i: any) {
|
|
||||||
|
export function isLabelIndex(i: unknown): i is LabelIndex {
|
||||||
return (
|
return (
|
||||||
|
i instanceof LabelIndexBase ||
|
||||||
i instanceof IdentityInt32Index ||
|
i instanceof IdentityInt32Index ||
|
||||||
i instanceof DenseInt32Index ||
|
i instanceof DenseInt32Index ||
|
||||||
i instanceof KeyIndex
|
i instanceof KeyIndex
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { DenseInt32Index, IdentityInt32Index, KeyIndex, isLabelIndex };
|
/** @internal */
|
||||||
|
function extent(tarr: GenericLabelArray<number>): [number, number] {
|
||||||
|
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) {
|
||||||
|
const v = tarr[i];
|
||||||
|
if (v < min) {
|
||||||
|
min = v;
|
||||||
|
}
|
||||||
|
if (v > max) {
|
||||||
|
max = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [min, max];
|
||||||
|
}
|
||||||
|
|
||||||
/* eslint-enable max-classes-per-file -- enable*/
|
/* eslint-enable max-classes-per-file -- enable*/
|
||||||
|
|||||||
@@ -5,55 +5,56 @@ TODO / XXX: for scalar/continuous data, this uses a naive method
|
|||||||
of computing quantiles. Would be good to switch from sort to
|
of computing quantiles. Would be good to switch from sort to
|
||||||
partition at some point.
|
partition at some point.
|
||||||
*/
|
*/
|
||||||
|
import {
|
||||||
|
AnyArray,
|
||||||
|
GenericArrayConstructor,
|
||||||
|
} from "../../common/types/arraytypes";
|
||||||
|
import { ContinuousColumnSummary, CategoricalColumnSummary } from "./types";
|
||||||
import quantile from "../quantile";
|
import quantile from "../quantile";
|
||||||
import { sortArray } from "../typedCrossfilter/sort";
|
import { sortArray } from "../typedCrossfilter/sort";
|
||||||
|
|
||||||
// [ 0, 0.01, 0.02, ..., 1.0]
|
// [ 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);
|
||||||
const centileNames = new Array(101).fill(0).map((v, idx) => idx / 100);
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
export function summarizeContinuous(col: AnyArray): ContinuousColumnSummary {
|
||||||
export function summarizeContinuous(col: any) {
|
|
||||||
let min;
|
|
||||||
let max;
|
|
||||||
let nan = 0;
|
let nan = 0;
|
||||||
let pinf = 0;
|
let pinf = 0;
|
||||||
let ninf = 0;
|
let ninf = 0;
|
||||||
let percentiles;
|
|
||||||
if (col) {
|
|
||||||
// -Inf < finite < Inf < NaN
|
|
||||||
const sortedCol = sortArray(new col.constructor(col));
|
|
||||||
|
|
||||||
// count non-finites, which are at each end of sorted data
|
// -Inf < finite < Inf < NaN
|
||||||
for (let i = sortedCol.length - 1; i >= 0; i -= 1) {
|
const sortedCol = sortArray(
|
||||||
if (!Number.isNaN(sortedCol[i])) {
|
new (col.constructor as GenericArrayConstructor<typeof col>)(col)
|
||||||
nan = sortedCol.length - i - 1;
|
);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (let i = 0, l = sortedCol.length; i < l; i += 1) {
|
|
||||||
if (sortedCol[i] !== Number.NEGATIVE_INFINITY) {
|
|
||||||
ninf = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (let i = sortedCol.length - nan - 1; i >= 0; i -= 1) {
|
|
||||||
if (sortedCol[i] !== Number.POSITIVE_INFINITY) {
|
|
||||||
pinf = sortedCol.length - i - nan - 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// compute percentiles on finite data ONLY
|
// count non-finites, which are at each end of sorted data
|
||||||
const sortedColFiniteOnly = sortedCol.slice(
|
for (let i = sortedCol.length - 1; i >= 0; i -= 1) {
|
||||||
ninf,
|
if (!Number.isNaN(sortedCol[i])) {
|
||||||
sortedCol.length - nan - pinf
|
nan = sortedCol.length - i - 1;
|
||||||
);
|
break;
|
||||||
percentiles = quantile(centileNames, sortedColFiniteOnly, true);
|
}
|
||||||
min = percentiles[0];
|
|
||||||
max = percentiles[100];
|
|
||||||
}
|
}
|
||||||
|
for (let i = 0, l = sortedCol.length; i < l; i += 1) {
|
||||||
|
if (sortedCol[i] !== Number.NEGATIVE_INFINITY) {
|
||||||
|
ninf = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let i = sortedCol.length - nan - 1; i >= 0; i -= 1) {
|
||||||
|
if (sortedCol[i] !== Number.POSITIVE_INFINITY) {
|
||||||
|
pinf = sortedCol.length - i - nan - 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute percentiles on finite data ONLY
|
||||||
|
const sortedColFiniteOnly = sortedCol.slice(
|
||||||
|
ninf,
|
||||||
|
sortedCol.length - nan - pinf
|
||||||
|
);
|
||||||
|
const percentiles = quantile(centileNames, sortedColFiniteOnly, true);
|
||||||
|
const min = percentiles[0];
|
||||||
|
const max = percentiles[100];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
categorical: false,
|
categorical: false,
|
||||||
min,
|
min,
|
||||||
@@ -65,8 +66,7 @@ export function summarizeContinuous(col: any) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
export function summarizeCategorical(col: AnyArray): CategoricalColumnSummary {
|
||||||
export function summarizeCategorical(col: any) {
|
|
||||||
const categoryCounts = new Map();
|
const categoryCounts = new Map();
|
||||||
if (col) {
|
if (col) {
|
||||||
for (let r = 0, l = col.length; r < l; r += 1) {
|
for (let r = 0, l = col.length; r < l; r += 1) {
|
||||||
|
|||||||
@@ -0,0 +1,139 @@
|
|||||||
|
import { TypedArray } from "../../common/types/arraytypes";
|
||||||
|
|
||||||
|
export type LabelType = number | string;
|
||||||
|
|
||||||
|
type CommonProps<A, B> = {
|
||||||
|
[K in keyof A & keyof B]: A[K] | B[K];
|
||||||
|
};
|
||||||
|
export type GenericLabelArray<T> = CommonProps<Array<T>, Int32Array>;
|
||||||
|
export type LabelArray = GenericLabelArray<number | string>;
|
||||||
|
|
||||||
|
export type OffsetType = number;
|
||||||
|
export type OffsetArray =
|
||||||
|
| Int8Array
|
||||||
|
| Uint8Array
|
||||||
|
| Int16Array
|
||||||
|
| Uint16Array
|
||||||
|
| Int32Array
|
||||||
|
| Uint32Array
|
||||||
|
| number[];
|
||||||
|
|
||||||
|
export type ContinuousColumnSummary = {
|
||||||
|
categorical: false;
|
||||||
|
min: number;
|
||||||
|
max: number;
|
||||||
|
nan: number;
|
||||||
|
pinf: number;
|
||||||
|
ninf: number;
|
||||||
|
percentiles: number[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CategoricalColumnSummary = {
|
||||||
|
categorical: true;
|
||||||
|
categories: (number | string | boolean)[];
|
||||||
|
categoryCounts: Map<number | string | boolean, number>;
|
||||||
|
numCategories: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ColumnSummary = ContinuousColumnSummary | CategoricalColumnSummary;
|
||||||
|
|
||||||
|
export type ContinuousHistogram = number[];
|
||||||
|
export type ContinuousHistogramBy = Map<DataframeValue, ContinuousHistogram>;
|
||||||
|
export type CategoricalHistogram = Map<DataframeValue, number>;
|
||||||
|
export type CategoricalHistogramBy = Map<DataframeValue, CategoricalHistogram>;
|
||||||
|
|
||||||
|
export type DataframeValue = number | string | boolean;
|
||||||
|
|
||||||
|
export type DataframeValueArray = DataframeValue[] | TypedArray;
|
||||||
|
|
||||||
|
export type DataframeColumnGetter = (
|
||||||
|
label: LabelType
|
||||||
|
) => DataframeValue | undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface representing a Dataframe column. Eg, returned by
|
||||||
|
* Dataframe.col().
|
||||||
|
*/
|
||||||
|
export interface DataframeColumn extends DataframeColumnGetter {
|
||||||
|
/**
|
||||||
|
* __id is unique per Dataframe and DataframeColumn, and is used as a memoization key.
|
||||||
|
*/
|
||||||
|
readonly __id: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Boolean indicating if the underlying data supports continuous operations, eg,
|
||||||
|
* summarizeContinuous.
|
||||||
|
*/
|
||||||
|
isContinuous: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return underlying column data as an array-like object.
|
||||||
|
*/
|
||||||
|
asArray: () => DataframeValueArray;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Continuous data summary. Will throw if !isContinuous.
|
||||||
|
*/
|
||||||
|
summarizeContinuous: () => ContinuousColumnSummary;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Categorical data summary.
|
||||||
|
*/
|
||||||
|
summarizeCategorical: () => CategoricalColumnSummary;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Continuous bin/histogram. Will throw if !isContinuous.
|
||||||
|
* @param bins - array of bin boundary fractions, in range [0., 1.]
|
||||||
|
* @param domain - data domain [min, max]
|
||||||
|
*/
|
||||||
|
histogramContinuous: (
|
||||||
|
bins: number,
|
||||||
|
domain: [number, number]
|
||||||
|
) => ContinuousHistogram;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Continuous bin/histogram, grouped by another categorical column. Will throw if !isContinuous.
|
||||||
|
* @param bins - array of bin boundary fractions, in range [0., 1.]
|
||||||
|
* @param domain - data domain [min, max]
|
||||||
|
* @param by - group by categorical column
|
||||||
|
*/
|
||||||
|
histogramContinuousBy: (
|
||||||
|
bins: number,
|
||||||
|
domain: [number, number],
|
||||||
|
by: DataframeColumn
|
||||||
|
) => ContinuousHistogramBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Categorical bin/histogram.
|
||||||
|
*/
|
||||||
|
histogramCategorical: () => CategoricalHistogram;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Categorical bin/histogram grouped by another column.
|
||||||
|
* @param by - group by categorical column
|
||||||
|
*/
|
||||||
|
histogramCategoricalBy: (by: DataframeColumn) => CategoricalHistogramBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the column contains the row label.
|
||||||
|
*/
|
||||||
|
has: (rlabel: LabelType) => boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the column contains the row offset. Identical to
|
||||||
|
* (offset >= 0 && offset < dataframe.length)
|
||||||
|
*/
|
||||||
|
ihas: (offset: OffsetType) => boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return index of the value, as a _label_. Returns undefined if
|
||||||
|
* not present. *NOTE*: unlike Array.indexOf, does not return an
|
||||||
|
* offset.
|
||||||
|
*/
|
||||||
|
indexOf: (value: DataframeValue) => LabelType | undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the value at the given offset, or undefined if not present.
|
||||||
|
*/
|
||||||
|
iget: (offset: OffsetType) => DataframeValue | undefined;
|
||||||
|
}
|
||||||
@@ -2,19 +2,19 @@
|
|||||||
Private utility code for dataframe
|
Private utility code for dataframe
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
export function callOnceLazy<
|
||||||
export function callOnceLazy(f: any) {
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- a legitimate use of any.
|
||||||
|
T extends (...args: any[]) => any = (...args: any[]) => any
|
||||||
|
>(fn: T): (...args: Parameters<T>) => ReturnType<T> {
|
||||||
/*
|
/*
|
||||||
call function once, and save the result, regardless of arguments (this is not
|
call function once, and save the result, regardless of arguments (this is not
|
||||||
the same as typical memoization).
|
the same as typical memoization).
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
let value: ReturnType<T>;
|
||||||
let value: any;
|
|
||||||
let calledOnce = false;
|
let calledOnce = false;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
const result = function result(...args: Parameters<T>): ReturnType<T> {
|
||||||
const result = function result(...args: any[]) {
|
|
||||||
if (!calledOnce) {
|
if (!calledOnce) {
|
||||||
value = f(...args);
|
value = fn(...args);
|
||||||
calledOnce = true;
|
calledOnce = true;
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
@@ -22,8 +22,14 @@ export function callOnceLazy(f: any) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
export function memoize<
|
||||||
export function memoize(fn: any, hashFn: any, maxResultsCached = -1) {
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- a legitimate use of any.
|
||||||
|
T extends (...args: any[]) => any = (...args: any[]) => any
|
||||||
|
>(
|
||||||
|
fn: T,
|
||||||
|
hashFn: (...args: Parameters<T>) => string,
|
||||||
|
maxResultsCached = -1
|
||||||
|
): (...args: Parameters<T>) => ReturnType<T> {
|
||||||
/*
|
/*
|
||||||
function memoization, with user-provided hash. hashFn must return a
|
function memoization, with user-provided hash. hashFn must return a
|
||||||
key which will be unique as a Map key (ie, obeys "sameValueZero" algorithm
|
key which will be unique as a Map key (ie, obeys "sameValueZero" algorithm
|
||||||
@@ -31,8 +37,7 @@ export function memoize(fn: any, hashFn: any, maxResultsCached = -1) {
|
|||||||
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map#Key_equality
|
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map#Key_equality
|
||||||
*/
|
*/
|
||||||
const cache = new Map();
|
const cache = new Map();
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
const wrap = function wrap(...args: Parameters<T>): ReturnType<T> {
|
||||||
const wrap = function wrap(...args: any[]) {
|
|
||||||
const key = hashFn(...args);
|
const key = hashFn(...args);
|
||||||
if (cache.has(key)) {
|
if (cache.has(key)) {
|
||||||
return cache.get(key);
|
return cache.get(key);
|
||||||
@@ -57,12 +62,11 @@ export function memoize(fn: any, hashFn: any, maxResultsCached = -1) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
memoization helpers - just a global counter.
|
*memoization helpers - just a global counter.
|
||||||
**/
|
*/
|
||||||
let __DataframeMemoId__ = 0;
|
let __DataframeMemoId__ = 0;
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
export function __getMemoId(): string {
|
||||||
export function __getMemoId() {
|
|
||||||
const id = __DataframeMemoId__;
|
const id = __DataframeMemoId__;
|
||||||
__DataframeMemoId__ += 1;
|
__DataframeMemoId__ += 1;
|
||||||
return id;
|
return id.toString();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,17 +12,26 @@ Arguments:
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { NumberArray, TypedArrayConstructor } from "../common/types/arraytypes";
|
||||||
|
|
||||||
import { sortArray } from "./typedCrossfilter/sort";
|
import { sortArray } from "./typedCrossfilter/sort";
|
||||||
|
|
||||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'quantArr' implicitly has an 'any' type.
|
export default function quantile(
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
quantArr: number[],
|
||||||
export default function quantile(quantArr, tarr, sorted = false) {
|
tarr: NumberArray,
|
||||||
|
sorted = false
|
||||||
|
): number[] {
|
||||||
/*
|
/*
|
||||||
start with the naive (sort) implementation. Later, use a faster partition
|
start with the naive (sort) implementation. Later, use a faster partition
|
||||||
*/
|
*/
|
||||||
const arr = sorted ? tarr : sortArray(new tarr.constructor(tarr)); // copy
|
|
||||||
|
if (tarr.length === 0) {
|
||||||
|
return new Array(quantArr.length).fill(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Ctor: TypedArrayConstructor = tarr.constructor as TypedArrayConstructor;
|
||||||
|
const arr = sorted ? tarr : sortArray(new Ctor(tarr)); // copy
|
||||||
const len = arr.length;
|
const len = arr.length;
|
||||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'q' implicitly has an 'any' type.
|
|
||||||
return quantArr.map((q) => {
|
return quantArr.map((q) => {
|
||||||
if (q === 1) {
|
if (q === 1) {
|
||||||
return arr[len - 1];
|
return arr[len - 1];
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ See also reducers/annotations.js
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Schema } from "../../common/types/schema";
|
import { Schema } from "../../common/types/schema";
|
||||||
|
import { Dataframe, LabelType } from "../dataframe";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
There are a number of state constraints assumed throughout the
|
There are a number of state constraints assumed throughout the
|
||||||
@@ -57,9 +58,12 @@ export function isUserAnnotation(annoMatrix, name) {
|
|||||||
return _isUserAnnotation(annoMatrix.schema, name);
|
return _isUserAnnotation(annoMatrix.schema, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'df' implicitly has an 'any' type.
|
export function allHaveLabelByMask(
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
df: Dataframe,
|
||||||
export function allHaveLabelByMask(df, colName, label, mask) {
|
colName: LabelType,
|
||||||
|
label: string,
|
||||||
|
mask: Uint8Array
|
||||||
|
): boolean {
|
||||||
// return true if all rows as indicated by mask have the colname set to label.
|
// return true if all rows as indicated by mask have the colname set to label.
|
||||||
// False if not.
|
// False if not.
|
||||||
const col = df.col(colName);
|
const col = df.col(colName);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import memoize from "memoize-one";
|
|||||||
import * as globals from "../../globals";
|
import * as globals from "../../globals";
|
||||||
import parseRGB from "../parseRGB";
|
import parseRGB from "../parseRGB";
|
||||||
import { range } from "../range";
|
import { range } from "../range";
|
||||||
|
import { Dataframe, LabelType } from "../dataframe";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
given a color mode & accessor, generate an annoMatrix query that will
|
given a color mode & accessor, generate an annoMatrix query that will
|
||||||
@@ -95,18 +96,19 @@ Returns:
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
function _createColorTable(
|
function _createColorTable(
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
colorMode: string | null,
|
||||||
colorMode: any,
|
colorByAccessor: LabelType | null,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
colorByData: Dataframe | null,
|
||||||
colorByAccessor: any,
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
|
||||||
colorByData: any,
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||||
schema: any,
|
schema: any,
|
||||||
userColors = null
|
userColors = null
|
||||||
) {
|
) {
|
||||||
|
if (colorMode === null || colorByData === null)
|
||||||
|
return defaultColors(schema.dataframe.nObs);
|
||||||
|
|
||||||
switch (colorMode) {
|
switch (colorMode) {
|
||||||
case "color by categorical metadata": {
|
case "color by categorical metadata": {
|
||||||
|
if (colorByAccessor === null) return defaultColors(schema.dataframe.nObs);
|
||||||
const data = colorByData.col(colorByAccessor).asArray();
|
const data = colorByData.col(colorByAccessor).asArray();
|
||||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||||
if (userColors && colorByAccessor in userColors) {
|
if (userColors && colorByAccessor in userColors) {
|
||||||
@@ -115,18 +117,19 @@ function _createColorTable(
|
|||||||
return createColorsByCategoricalMetadata(data, colorByAccessor, schema);
|
return createColorsByCategoricalMetadata(data, colorByAccessor, schema);
|
||||||
}
|
}
|
||||||
case "color by continuous metadata": {
|
case "color by continuous metadata": {
|
||||||
|
if (colorByAccessor === null) return defaultColors(schema.dataframe.nObs);
|
||||||
const col = colorByData.col(colorByAccessor);
|
const col = colorByData.col(colorByAccessor);
|
||||||
const { min, max } = col.summarize();
|
const { min, max } = col.summarizeContinuous();
|
||||||
return createColorsByContinuousMetadata(col.asArray(), min, max);
|
return createColorsByContinuousMetadata(col.asArray(), min, max);
|
||||||
}
|
}
|
||||||
case "color by expression": {
|
case "color by expression": {
|
||||||
const col = colorByData.icol(0);
|
const col = colorByData.icol(0);
|
||||||
const { min, max } = col.summarize();
|
const { min, max } = col.summarizeContinuous();
|
||||||
return createColorsByContinuousMetadata(col.asArray(), min, max);
|
return createColorsByContinuousMetadata(col.asArray(), min, max);
|
||||||
}
|
}
|
||||||
case "color by geneset mean expression": {
|
case "color by geneset mean expression": {
|
||||||
const col = colorByData.icol(0);
|
const col = colorByData.icol(0);
|
||||||
const { min, max } = col.summarize();
|
const { min, max } = col.summarizeContinuous();
|
||||||
return createColorsByContinuousMetadata(col.asArray(), min, max);
|
return createColorsByContinuousMetadata(col.asArray(), min, max);
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
import { flatbuffers } from "flatbuffers";
|
import { flatbuffers } from "flatbuffers";
|
||||||
import { NetEncoding } from "./matrix_generated";
|
import { NetEncoding } from "./matrix_generated";
|
||||||
import { isTypedArray, isFloatTypedArray } from "../../common/types/arraytypes";
|
import {
|
||||||
|
TypedArray,
|
||||||
|
isTypedArray,
|
||||||
|
isFloatTypedArray,
|
||||||
|
} from "../../common/types/arraytypes";
|
||||||
import {
|
import {
|
||||||
Dataframe,
|
Dataframe,
|
||||||
IdentityInt32Index,
|
IdentityInt32Index,
|
||||||
@@ -94,14 +98,13 @@ function encodeTypedArray(builder: any, uType: any, uData: any) {
|
|||||||
return builder.endObject();
|
return builder.endObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
export function encodeMatrixFBS(df: Dataframe): Uint8Array {
|
||||||
export function encodeMatrixFBS(df: any) {
|
|
||||||
/*
|
/*
|
||||||
encode the dataframe as an FBS Matrix
|
encode the dataframe as an FBS Matrix
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* row indexing not supported currently */
|
/* row indexing not supported currently */
|
||||||
if (df.rowIndex.constructor !== IdentityInt32Index) {
|
if (!(df.rowIndex instanceof IdentityInt32Index)) {
|
||||||
throw new Error("FBS does not support row index encoding at this time");
|
throw new Error("FBS does not support row index encoding at this time");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,11 +118,9 @@ export function encodeMatrixFBS(df: any) {
|
|||||||
let encColumns;
|
let encColumns;
|
||||||
|
|
||||||
if (shape[0] > 0 && shape[1] > 0) {
|
if (shape[0] > 0 && shape[1] > 0) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
const columns = df.columns().map((col) => col.asArray());
|
||||||
const columns = df.columns().map((col: any) => col.asArray());
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
const cols = columns.map((carr) => {
|
||||||
const cols = columns.map((carr: any) => {
|
|
||||||
let uType;
|
let uType;
|
||||||
let tarr;
|
let tarr;
|
||||||
if (isTypedArray(carr)) {
|
if (isTypedArray(carr)) {
|
||||||
@@ -179,8 +180,7 @@ export function encodeMatrixFBS(df: any) {
|
|||||||
return builder.asUint8Array();
|
return builder.asUint8Array();
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
function promoteTypedArray(o: TypedArray) {
|
||||||
function promoteTypedArray(o: any) {
|
|
||||||
/*
|
/*
|
||||||
Decide what internal data type to use for the data returned from
|
Decide what internal data type to use for the data returned from
|
||||||
the server.
|
the server.
|
||||||
@@ -212,8 +212,9 @@ function promoteTypedArray(o: any) {
|
|||||||
return new TypedArrayCtor(o);
|
return new TypedArrayCtor(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
export function matrixFBSToDataframe(
|
||||||
export function matrixFBSToDataframe(arrayBuffers: any) {
|
arrayBuffers: ArrayBuffer | ArrayBuffer[]
|
||||||
|
): Dataframe {
|
||||||
/*
|
/*
|
||||||
Convert array of Matrix FBS to a Dataframe.
|
Convert array of Matrix FBS to a Dataframe.
|
||||||
|
|
||||||
@@ -229,37 +230,30 @@ export function matrixFBSToDataframe(arrayBuffers: any) {
|
|||||||
arrayBuffers = [arrayBuffers];
|
arrayBuffers = [arrayBuffers];
|
||||||
}
|
}
|
||||||
if (arrayBuffers.length === 0) {
|
if (arrayBuffers.length === 0) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
return Dataframe.empty();
|
||||||
return (Dataframe as any).Dataframe.empty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
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 */
|
/* check that all FBS have same row dimensionality */
|
||||||
const { nRows } = fbs[0];
|
const { nRows } = fbs[0];
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
fbs.forEach((b) => {
|
||||||
fbs.forEach((b: any) => {
|
|
||||||
if (b.nRows !== nRows)
|
if (b.nRows !== nRows)
|
||||||
throw new Error("FBS with inconsistent dimensionality");
|
throw new Error("FBS with inconsistent dimensionality");
|
||||||
});
|
});
|
||||||
const columns = fbs // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
const columns = fbs
|
||||||
.map((fb: any) =>
|
.map((fb) =>
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
fb.columns.map((c) => {
|
||||||
fb.columns.map((c: any) => {
|
|
||||||
if (isFloatTypedArray(c) || Array.isArray(c)) return c;
|
if (isFloatTypedArray(c) || Array.isArray(c)) return c;
|
||||||
return promoteTypedArray(c);
|
return promoteTypedArray(c);
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.flat();
|
.flat();
|
||||||
// colIdx may be TypedArray or Array
|
// colIdx may be TypedArray or Array
|
||||||
const colIdx = fbs // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
const colIdx = fbs
|
||||||
.map((b: any) =>
|
.map((b) => (Array.isArray(b.colIdx) ? b.colIdx : Array.from(b.colIdx)))
|
||||||
Array.isArray(b.colIdx) ? b.colIdx : Array.from(b.colIdx)
|
|
||||||
)
|
|
||||||
.flat();
|
.flat();
|
||||||
const nCols = columns.length;
|
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));
|
const df = new Dataframe([nRows, nCols], columns, null, new KeyIndex(colIdx));
|
||||||
return df;
|
return df;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ Views can be interogated for their type with the following:
|
|||||||
|
|
||||||
import { clip, isubsetMask, isubset } from "../../annoMatrix";
|
import { clip, isubsetMask, isubset } from "../../annoMatrix";
|
||||||
import { memoize } from "../dataframe/util";
|
import { memoize } from "../dataframe/util";
|
||||||
|
import { Dataframe, LabelIndex } from "../dataframe";
|
||||||
|
|
||||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'annoMatrix' implicitly has an 'any' typ... Remove this comment to see the full error message
|
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'annoMatrix' implicitly has an 'any' typ... Remove this comment to see the full error message
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
||||||
@@ -101,7 +102,7 @@ export function _userResetSubsetAnnoMatrix(annoMatrix) {
|
|||||||
|
|
||||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'annoMatrix' implicitly has an 'any' typ... Remove this comment to see the full error message
|
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'annoMatrix' implicitly has an 'any' typ... Remove this comment to see the full error message
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
||||||
export function _setEmbeddingSubset(annoMatrix, embeddingDf) {
|
export function _setEmbeddingSubset(annoMatrix, embeddingDf: Dataframe) {
|
||||||
/*
|
/*
|
||||||
Set the embedding subset view. Only create a subset view for the embedding
|
Set the embedding subset view. Only create a subset view for the embedding
|
||||||
when it is needed, ie, there are NaN values in the embeddings.
|
when it is needed, ie, there are NaN values in the embeddings.
|
||||||
@@ -141,8 +142,10 @@ export function _setEmbeddingSubset(annoMatrix, embeddingDf) {
|
|||||||
return annoMatrix;
|
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(
|
||||||
function _getEmbeddingRowOffsets(baseRowIndex, embeddingDf) {
|
_baseRowIndex: LabelIndex,
|
||||||
|
embeddingDf: Dataframe
|
||||||
|
) {
|
||||||
/*
|
/*
|
||||||
given a dataframe containing an embedding:
|
given a dataframe containing an embedding:
|
||||||
- if the embedding contains no NaN coordinates, return null
|
- if the embedding contains no NaN coordinates, return null
|
||||||
@@ -167,17 +170,16 @@ function _getEmbeddingRowOffsets(baseRowIndex, embeddingDf) {
|
|||||||
return offsets.subarray(0, numOffsets);
|
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(
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
embeddingDf: Dataframe
|
||||||
export function _getDiscreteCellEmbeddingRowIndex(embeddingDf) {
|
): LabelIndex {
|
||||||
const idx = _getEmbeddingRowOffsets(embeddingDf.rowIndex, embeddingDf);
|
const idx = _getEmbeddingRowOffsets(embeddingDf.rowIndex, embeddingDf);
|
||||||
if (idx === null) return embeddingDf.rowIndex;
|
if (idx === null) return embeddingDf.rowIndex;
|
||||||
return embeddingDf.rowIndex.isubset(idx);
|
return embeddingDf.rowIndex.isubset(idx);
|
||||||
}
|
}
|
||||||
export const getDiscreteCellEmbeddingRowIndex = memoize(
|
export const getDiscreteCellEmbeddingRowIndex = memoize(
|
||||||
_getDiscreteCellEmbeddingRowIndex,
|
_getDiscreteCellEmbeddingRowIndex,
|
||||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'df' implicitly has an 'any' type.
|
(df: Dataframe) => df.__id
|
||||||
(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
|
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'annoMatrix' implicitly has an 'any' typ... Remove this comment to see the full error message
|
||||||
|
|||||||
@@ -12,9 +12,8 @@ import { makeSortIndex } from "./util";
|
|||||||
import { isAnyArray } from "../../common/types/arraytypes";
|
import { isAnyArray } from "../../common/types/arraytypes";
|
||||||
|
|
||||||
class NotImplementedError extends Error {
|
class NotImplementedError extends Error {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
constructor(msg: string) {
|
||||||
constructor(...params: any[]) {
|
super(msg);
|
||||||
super(...params);
|
|
||||||
|
|
||||||
// Maintains proper stack trace for where our error was thrown (only available on V8)
|
// Maintains proper stack trace for where our error was thrown (only available on V8)
|
||||||
if (Error.captureStackTrace) {
|
if (Error.captureStackTrace) {
|
||||||
@@ -63,8 +62,7 @@ export default class ImmutableTypedCrossfilter {
|
|||||||
Object.preventExtensions(this);
|
Object.preventExtensions(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
size(): number {
|
||||||
size() {
|
|
||||||
return this.data.length;
|
return this.data.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user