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:
Bruce Martin
2021-08-17 10:43:40 -07:00
committed by GitHub
parent 3fdf5cac9d
commit 45cecad76a
39 changed files with 1298 additions and 1124 deletions
@@ -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);
+8 -8
View File
@@ -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.
+168 -167
View File
@@ -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);
+76 -76
View File
@@ -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
+5 -6
View File
@@ -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);
+2 -2
View File
@@ -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");
+10 -9
View File
@@ -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
+1 -1
View File
@@ -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);
+16
View File
@@ -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 {
+19 -19
View File
@@ -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
View File
@@ -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]);
+5 -8
View File
@@ -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;
+249 -224
View File
@@ -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;
+50 -70
View File
@@ -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}`;
}
+13
View File
@@ -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";
+234 -240
View File
@@ -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*/
+40 -40
View File
@@ -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) {
+139
View File
@@ -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;
}
+20 -16
View File
@@ -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();
} }
+14 -5
View File
@@ -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);
+12 -9
View File
@@ -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: {
+21 -27
View File
@@ -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;
} }