Added typings to annoMatrix dir. (#2365) (#2371)

* Added typings to annoMatrix directory. (#2365)

* Added review point updates. (#2365)

* Fixed viewOf defect. Added review point updates. (#2365)

* Updated test to use Field key interpolation. (#2365)

Co-authored-by: Timmy Huang <tihuan@users.noreply.github.com>

* Updated test to use Field key interpolation. (#2365)

Co-authored-by: Timmy Huang <tihuan@users.noreply.github.com>

* Updated test to use Field key interpolation. (#2365)

Co-authored-by: Timmy Huang <tihuan@users.noreply.github.com>

* Updated test to use Field key interpolation. (#2365)

Co-authored-by: Timmy Huang <tihuan@users.noreply.github.com>

* Linting. (#2365)

Co-authored-by: Timmy Huang <tihuan@users.noreply.github.com>

* Simplified while condition in middleware GC. (#2365)

Co-authored-by: Timmy Huang <tihuan@users.noreply.github.com>

* Reverted embedding.ts prettier to resolve conflict. (#2365)

Co-authored-by: Timmy Huang <tihuan@users.noreply.github.com>
This commit is contained in:
Mim Hastie
2021-08-18 13:18:54 -07:00
committed by GitHub
co-authored by Timmy Huang
parent 08b03ace60
commit b814489328
19 changed files with 1121 additions and 948 deletions
@@ -10,6 +10,7 @@ import {
isubsetMask, isubsetMask,
} from "../../../src/annoMatrix"; } from "../../../src/annoMatrix";
import { Dataframe } from "../../../src/util/dataframe"; import { Dataframe } from "../../../src/util/dataframe";
import { Field } from "../../../src/common/types/schema";
enableFetchMocks(); enableFetchMocks();
@@ -34,7 +35,7 @@ describe("AnnoMatrix", () => {
expect(annoMatrix.nObs).toEqual(serverMocks.schema.schema.dataframe.nObs); expect(annoMatrix.nObs).toEqual(serverMocks.schema.schema.dataframe.nObs);
expect(annoMatrix.nVar).toEqual(serverMocks.schema.schema.dataframe.nVar); expect(annoMatrix.nVar).toEqual(serverMocks.schema.schema.dataframe.nVar);
expect(annoMatrix.isView).toBeFalsy(); expect(annoMatrix.isView).toBeFalsy();
expect(annoMatrix.viewOf).toBeUndefined(); expect(annoMatrix.viewOf).toBe(annoMatrix);
expect(annoMatrix.rowIndex).toBeDefined(); expect(annoMatrix.rowIndex).toBeDefined();
}); });
@@ -42,7 +43,7 @@ describe("AnnoMatrix", () => {
// 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.
(fetch as any).once(serverMocks.annotationsObs(["name_0"])); (fetch as any).once(serverMocks.annotationsObs(["name_0"]));
const df = await annoMatrix.fetch("obs", "name_0"); const df = await annoMatrix.fetch(Field.obs, "name_0");
expect(df).toBeInstanceOf(Dataframe); expect(df).toBeInstanceOf(Dataframe);
expect(df.colIndex.labels()).toEqual(["name_0"]); expect(df.colIndex.labels()).toEqual(["name_0"]);
expect(df.dims).toEqual([annoMatrix.nObs, 1]); expect(df.dims).toEqual([annoMatrix.nObs, 1]);
@@ -55,7 +56,7 @@ describe("AnnoMatrix", () => {
.once(serverMocks.annotationsObs(["n_genes"])); .once(serverMocks.annotationsObs(["n_genes"]));
await expect( await expect(
annoMatrix.fetch("obs", ["name_0", "n_genes"]) annoMatrix.fetch(Field.obs, ["name_0", "n_genes"])
).resolves.toBeInstanceOf(Dataframe); ).resolves.toBeInstanceOf(Dataframe);
}); });
@@ -72,7 +73,7 @@ describe("AnnoMatrix", () => {
).resolves.toBeInstanceOf(Dataframe); ).resolves.toBeInstanceOf(Dataframe);
}; };
test("obs", async () => getLastTwo("obs")); test(Field.obs, async () => getLastTwo(Field.obs));
test("var", async () => getLastTwo("var")); test("var", async () => getLastTwo("var"));
test("emb", async () => getLastTwo("emb")); test("emb", async () => getLastTwo("emb"));
}); });
@@ -81,15 +82,15 @@ describe("AnnoMatrix", () => {
// single string is a column name // single string is a column name
// 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.
(fetch as any).once(serverMocks.annotationsObs(["n_genes"])); (fetch as any).once(serverMocks.annotationsObs(["n_genes"]));
await expect(annoMatrix.fetch("obs", "n_genes")).resolves.toBeInstanceOf( await expect(
Dataframe annoMatrix.fetch(Field.obs, "n_genes")
); ).resolves.toBeInstanceOf(Dataframe);
// array of column names, expecting n_genes to be cached. // array of column names, expecting n_genes to be cached.
// 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.
(fetch as any).once(serverMocks.annotationsObs(["percent_mito"])); (fetch as any).once(serverMocks.annotationsObs(["percent_mito"]));
await expect( await expect(
annoMatrix.fetch("obs", ["n_genes", "percent_mito"]) annoMatrix.fetch(Field.obs, ["n_genes", "percent_mito"])
).resolves.toBeInstanceOf(Dataframe); ).resolves.toBeInstanceOf(Dataframe);
// more complex value filter query, enumerated // more complex value filter query, enumerated
@@ -151,9 +152,9 @@ describe("AnnoMatrix", () => {
test("schema accessors", () => { test("schema accessors", () => {
expect(annoMatrix.getMatrixFields()).toEqual( expect(annoMatrix.getMatrixFields()).toEqual(
expect.arrayContaining(["X", "obs", "emb", "var"]) expect.arrayContaining(["X", Field.obs, "emb", "var"])
); );
expect(annoMatrix.getMatrixColumns("obs")).toEqual( expect(annoMatrix.getMatrixColumns(Field.obs)).toEqual(
expect.arrayContaining(["name_0", "n_genes", "louvain"]) expect.arrayContaining(["name_0", "n_genes", "louvain"])
); );
expect(annoMatrix.getColumnSchema("emb", "umap")).toEqual({ expect(annoMatrix.getColumnSchema("emb", "umap")).toEqual({
@@ -171,7 +172,7 @@ describe("AnnoMatrix", () => {
test the mask & label access to subset via isubset and isubsetMask test the mask & label access to subset via isubset and isubsetMask
*/ */
test("isubset", async () => { test("isubset", async () => {
const rowList = [0, 10]; const rowList = new Int32Array([0, 10]);
const rowMask = new Uint8Array(annoMatrix.nObs); const rowMask = new Uint8Array(annoMatrix.nObs);
for (let i = 0; i < rowList.length; i += 1) { for (let i = 0; i < rowList.length; i += 1) {
rowMask[rowList[i]] = 1; rowMask[rowList[i]] = 1;
@@ -188,8 +189,8 @@ 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")) as Dataframe; const ng1 = (await am1.fetch(Field.obs, "n_genes")) as Dataframe;
const ng2 = (await am2.fetch("obs", "n_genes")) as Dataframe; const ng2 = (await am2.fetch(Field.obs, "n_genes")) as Dataframe;
expect(ng1).toBeDefined(); expect(ng1).toBeDefined();
expect(ng2).toBeDefined(); expect(ng2).toBeDefined();
expect(ng1).toHaveLength(ng2.length); expect(ng1).toHaveLength(ng2.length);
@@ -203,10 +204,10 @@ describe("AnnoMatrix", () => {
describe("add/drop column", () => { describe("add/drop column", () => {
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'base' implicitly has an 'any' type. // @ts-expect-error ts-migrate(7006) FIXME: Parameter 'base' implicitly has an 'any' type.
async function addDrop(base) { async function addDrop(base) {
expect(base.getMatrixColumns("obs")).not.toContain("foo"); expect(base.getMatrixColumns(Field.obs)).not.toContain("foo");
// 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.
(fetch as any).mockRejectOnce(new Error("unknown column name")); (fetch as any).mockRejectOnce(new Error("unknown column name"));
await expect(base.fetch("obs", "foo")).rejects.toThrow( await expect(base.fetch(Field.obs, "foo")).rejects.toThrow(
"unknown column name" "unknown column name"
); );
@@ -216,9 +217,9 @@ describe("AnnoMatrix", () => {
Float32Array, Float32Array,
0 0
); );
expect(base.getMatrixColumns("obs")).not.toContain("foo"); expect(base.getMatrixColumns(Field.obs)).not.toContain("foo");
expect(am1.getMatrixColumns("obs")).toContain("foo"); expect(am1.getMatrixColumns(Field.obs)).toContain("foo");
const foo: Dataframe = await am1.fetch("obs", "foo"); const foo: Dataframe = await am1.fetch(Field.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);
@@ -228,11 +229,11 @@ describe("AnnoMatrix", () => {
/* drop */ /* drop */
const am2 = am1.dropObsColumn("foo"); const am2 = am1.dropObsColumn("foo");
expect(base.getMatrixColumns("obs")).not.toContain("foo"); expect(base.getMatrixColumns(Field.obs)).not.toContain("foo");
expect(am2.getMatrixColumns("obs")).not.toContain("foo"); expect(am2.getMatrixColumns(Field.obs)).not.toContain("foo");
// 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.
(fetch as any).mockRejectOnce(new Error("unknown column name")); (fetch as any).mockRejectOnce(new Error("unknown column name"));
await expect(am2.fetch("obs", "foo")).rejects.toThrow( await expect(am2.fetch(Field.obs, "foo")).rejects.toThrow(
"unknown column name" "unknown column name"
); );
} }
@@ -245,10 +246,10 @@ describe("AnnoMatrix", () => {
const am1 = clip(annoMatrix, 0.1, 0.9); const am1 = clip(annoMatrix, 0.1, 0.9);
await addDrop(am1); await addDrop(am1);
const am2 = isubset(am1, [0, 1, 2, 20, 30, 400]); const am2 = isubset(am1, new Int32Array([0, 1, 2, 20, 30, 400]));
await addDrop(am2); await addDrop(am2);
const am3 = isubset(annoMatrix, [10, 0, 7, 3]); const am3 = isubset(annoMatrix, new Int32Array([10, 0, 7, 3]));
await addDrop(am3); await addDrop(am3);
const am4 = clip(am3, 0, 1); const am4 = clip(am3, 0, 1);
@@ -257,10 +258,10 @@ describe("AnnoMatrix", () => {
// 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.
(fetch as any).mockResponse(serverMocks.responder); (fetch as any).mockResponse(serverMocks.responder);
await am1.fetch("obs", am1.getMatrixColumns("obs")); await am1.fetch(Field.obs, am1.getMatrixColumns(Field.obs));
await am2.fetch("obs", am2.getMatrixColumns("obs")); await am2.fetch(Field.obs, am2.getMatrixColumns(Field.obs));
await am3.fetch("obs", am3.getMatrixColumns("obs")); await am3.fetch(Field.obs, am3.getMatrixColumns(Field.obs));
await am4.fetch("obs", am4.getMatrixColumns("obs")); await am4.fetch(Field.obs, am4.getMatrixColumns(Field.obs));
// 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.
(fetch as any).resetMocks(); (fetch as any).resetMocks();
@@ -287,7 +288,7 @@ describe("AnnoMatrix", () => {
"unassigned" "unassigned"
); );
const testVal = await am.fetch("obs", "test"); const testVal = await am.fetch(Field.obs, "test");
expect(testVal.col("test").asArray()).toEqual( expect(testVal.col("test").asArray()).toEqual(
new Array(am.nObs).fill("unassigned") new Array(am.nObs).fill("unassigned")
); );
@@ -295,7 +296,7 @@ describe("AnnoMatrix", () => {
/* set values in column */ /* set values in column */
const whichRows = [1, 2, 10]; const whichRows = [1, 2, 10];
const am1 = await am.setObsColumnValues("test", whichRows, "yo"); const am1 = await am.setObsColumnValues("test", whichRows, "yo");
const testVal1 = await am1.fetch("obs", "test"); const testVal1 = await am1.fetch(Field.obs, "test");
const expt = new Array(am1.nObs).fill("unassigned"); const expt = new Array(am1.nObs).fill("unassigned");
for (let i = 0; i < whichRows.length; i += 1) { for (let i = 0; i < whichRows.length; i += 1) {
const offset = am1.rowIndex.getOffset(whichRows[i]); const offset = am1.rowIndex.getOffset(whichRows[i]);
@@ -303,8 +304,8 @@ describe("AnnoMatrix", () => {
} }
expect(testVal1).not.toBe(testVal); expect(testVal1).not.toBe(testVal);
expect(testVal1.col("test").asArray()).toEqual(expt); expect(testVal1.col("test").asArray()).toEqual(expt);
expect(am1.getColumnSchema("obs", "test").type).toBe("categorical"); expect(am1.getColumnSchema(Field.obs, "test").type).toBe("categorical");
expect(am1.getColumnSchema("obs", "test").categories).toEqual( expect(am1.getColumnSchema(Field.obs, "test").categories).toEqual(
expect.arrayContaining(["unassigned", "red", "green", "yo"]) expect.arrayContaining(["unassigned", "red", "green", "yo"])
); );
@@ -312,7 +313,7 @@ describe("AnnoMatrix", () => {
// 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.
(fetch as any).mockRejectOnce(new Error("unknown column name")); (fetch as any).mockRejectOnce(new Error("unknown column name"));
am = am1.dropObsColumn("test"); am = am1.dropObsColumn("test");
await expect(am.fetch("obs", "test")).rejects.toThrow( await expect(am.fetch(Field.obs, "test")).rejects.toThrow(
"unknown column name" "unknown column name"
); );
} }
@@ -325,18 +326,18 @@ describe("AnnoMatrix", () => {
const am1 = clip(annoMatrix, 0.1, 0.9); const am1 = clip(annoMatrix, 0.1, 0.9);
await addSetDrop(am1); await addSetDrop(am1);
const am2 = isubset(am1, [0, 1, 2, 10, 20, 30, 400]); const am2 = isubset(am1, new Int32Array([0, 1, 2, 10, 20, 30, 400]));
await addSetDrop(am2); await addSetDrop(am2);
const am3 = isubset(annoMatrix, [10, 1, 0, 30, 2]); const am3 = isubset(annoMatrix, new Int32Array([10, 1, 0, 30, 2]));
await addSetDrop(am3); await addSetDrop(am3);
// 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.
(fetch as any).mockResponse(serverMocks.responder); (fetch as any).mockResponse(serverMocks.responder);
await am1.fetch("obs", am1.getMatrixColumns("obs")); await am1.fetch(Field.obs, am1.getMatrixColumns(Field.obs));
await am2.fetch("obs", am2.getMatrixColumns("obs")); await am2.fetch(Field.obs, am2.getMatrixColumns(Field.obs));
await am3.fetch("obs", am3.getMatrixColumns("obs")); await am3.fetch(Field.obs, am3.getMatrixColumns(Field.obs));
await addSetDrop(am1); await addSetDrop(am1);
await addSetDrop(am2); await addSetDrop(am2);
@@ -14,6 +14,7 @@ import {
} from "../../../src/annoMatrix"; } from "../../../src/annoMatrix";
import { Dataframe } from "../../../src/util/dataframe"; import { Dataframe } from "../../../src/util/dataframe";
import { rangeFill } from "../../../src/util/range"; import { rangeFill } from "../../../src/util/range";
import { Field, Schema } from "../../../src/common/types/schema";
enableFetchMocks(); enableFetchMocks();
@@ -29,7 +30,7 @@ describe("AnnoMatrixCrossfilter", () => {
// reset all fetch mocking state // reset all fetch mocking state
annoMatrix = new AnnoMatrixLoader( annoMatrix = new AnnoMatrixLoader(
serverMocks.baseDataURL, serverMocks.baseDataURL,
serverMocks.schema.schema serverMocks.schema.schema as Schema
); );
crossfilter = new AnnoMatrixObsCrossfilter(annoMatrix); crossfilter = new AnnoMatrixObsCrossfilter(annoMatrix);
}); });
@@ -76,7 +77,7 @@ describe("AnnoMatrixCrossfilter", () => {
(fetch as any).once( (fetch as any).once(
serverMocks.dataframeResponse(["louvain"], [obsLouvain]) serverMocks.dataframeResponse(["louvain"], [obsLouvain])
); );
let newCrossfilter = await crossfilter.select("obs", "louvain", { let newCrossfilter = await crossfilter.select(Field.obs, "louvain", {
mode: "none", mode: "none",
}); });
@@ -87,7 +88,7 @@ describe("AnnoMatrixCrossfilter", () => {
// 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.
expect((fetch as any).mock.calls).toHaveLength(1); expect((fetch as any).mock.calls).toHaveLength(1);
newCrossfilter = await crossfilter.select("obs", "louvain", { newCrossfilter = await crossfilter.select(Field.obs, "louvain", {
mode: "all", mode: "all",
}); });
expect(newCrossfilter.countSelected()).toEqual(annoMatrix.nObs); expect(newCrossfilter.countSelected()).toEqual(annoMatrix.nObs);
@@ -100,7 +101,7 @@ describe("AnnoMatrixCrossfilter", () => {
(fetch as any).once( (fetch as any).once(
serverMocks.dataframeResponse(["louvain"], [obsLouvain]) serverMocks.dataframeResponse(["louvain"], [obsLouvain])
); );
xfltr = await crossfilter.select("obs", "louvain", { xfltr = await crossfilter.select(Field.obs, "louvain", {
mode: "exact", mode: "exact",
values: ["NK cells", "B cells"], values: ["NK cells", "B cells"],
}); });
@@ -133,7 +134,7 @@ describe("AnnoMatrixCrossfilter", () => {
) )
); );
const df: Dataframe = await annoMatrix.fetch("obs", "louvain"); const df: Dataframe = await annoMatrix.fetch(Field.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(
@@ -146,7 +147,7 @@ describe("AnnoMatrixCrossfilter", () => {
(fetch as any).once( (fetch as any).once(
serverMocks.dataframeResponse(["n_genes"], [new Int32Array(obsNGenes)]) serverMocks.dataframeResponse(["n_genes"], [new Int32Array(obsNGenes)])
); );
xfltr = await xfltr.select("obs", "n_genes", { xfltr = await xfltr.select(Field.obs, "n_genes", {
mode: "range", mode: "range",
lo: 0, lo: 0,
hi: 500, hi: 500,
@@ -258,7 +259,7 @@ describe("AnnoMatrixCrossfilter", () => {
(fetch as any).once( (fetch as any).once(
serverMocks.dataframeResponse(["louvain"], [obsLouvain]) serverMocks.dataframeResponse(["louvain"], [obsLouvain])
); );
xfltr = await xfltr.select("obs", "louvain", { xfltr = await xfltr.select(Field.obs, "louvain", {
mode: "exact", mode: "exact",
values: ["NK cells", "B cells"], values: ["NK cells", "B cells"],
}); });
@@ -267,7 +268,7 @@ describe("AnnoMatrixCrossfilter", () => {
expect(xfltr.countSelected()).toEqual(240); expect(xfltr.countSelected()).toEqual(240);
const df: Dataframe = (await annoMatrixSubset.fetch( const df: Dataframe = (await annoMatrixSubset.fetch(
"obs", Field.obs,
"louvain" "louvain"
)) as Dataframe; )) as Dataframe;
expect(df).toBeDefined(); expect(df).toBeDefined();
@@ -291,7 +292,7 @@ describe("AnnoMatrixCrossfilter", () => {
// 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.
(fetch as any).mockRejectOnce(new Error("unknown column name")); (fetch as any).mockRejectOnce(new Error("unknown column name"));
await expect(crossfilter.select("obs", "foo")).rejects.toThrow( await expect(crossfilter.select(Field.obs, "foo")).rejects.toThrow(
"unknown column name" "unknown column name"
); );
}); });
@@ -304,7 +305,7 @@ describe("AnnoMatrixCrossfilter", () => {
// 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.
async function helperAddTestCol(cf: any, colName: any, colSchema = null) { async function helperAddTestCol(cf: any, colName: any, colSchema = null) {
expect( expect(
cf.annoMatrix.getMatrixColumns("obs").includes(colName) cf.annoMatrix.getMatrixColumns(Field.obs).includes(colName)
).toBeFalsy(); ).toBeFalsy();
if (colSchema === null) { if (colSchema === null) {
@@ -326,7 +327,7 @@ describe("AnnoMatrixCrossfilter", () => {
(v: any) => v.name === colName (v: any) => v.name === colName
) )
).toHaveLength(1); ).toHaveLength(1);
const df = await xfltr.annoMatrix.fetch("obs", colName); const df = await xfltr.annoMatrix.fetch(Field.obs, colName);
expect(df.hasCol(colName)).toBeTruthy(); expect(df.hasCol(colName)).toBeTruthy();
return xfltr; return xfltr;
} }
@@ -334,7 +335,7 @@ describe("AnnoMatrixCrossfilter", () => {
test("addObsColumn", async () => { test("addObsColumn", async () => {
expect(crossfilter.countSelected()).toBe(annoMatrix.nObs); expect(crossfilter.countSelected()).toBe(annoMatrix.nObs);
expect( expect(
crossfilter.annoMatrix.getMatrixColumns("obs").includes("foo") crossfilter.annoMatrix.getMatrixColumns(Field.obs).includes("foo")
).toBeFalsy(); ).toBeFalsy();
const xfltr = crossfilter.addObsColumn( const xfltr = crossfilter.addObsColumn(
{ name: "foo", type: "categorical", categories: ["A"] }, { name: "foo", type: "categorical", categories: ["A"] },
@@ -345,7 +346,7 @@ describe("AnnoMatrixCrossfilter", () => {
// check schema updates correctly. // check schema updates correctly.
expect(xfltr.countSelected()).toBe(annoMatrix.nObs); expect(xfltr.countSelected()).toBe(annoMatrix.nObs);
expect( expect(
xfltr.annoMatrix.getMatrixColumns("obs").includes("foo") xfltr.annoMatrix.getMatrixColumns(Field.obs).includes("foo")
).toBeTruthy(); ).toBeTruthy();
expect(xfltr.annoMatrix.schema.annotations.obsByName.foo).toMatchObject({ expect(xfltr.annoMatrix.schema.annotations.obsByName.foo).toMatchObject({
name: "foo", name: "foo",
@@ -359,7 +360,7 @@ describe("AnnoMatrixCrossfilter", () => {
).toHaveLength(1); ).toHaveLength(1);
// check data update. // check data update.
const df: Dataframe = await xfltr.annoMatrix.fetch("obs", "foo"); const df: Dataframe = await xfltr.annoMatrix.fetch(Field.obs, "foo");
expect( expect(
df df
.col("foo") .col("foo")
@@ -408,13 +409,13 @@ describe("AnnoMatrixCrossfilter", () => {
expect(xfltr.annoMatrix.schema.annotations.obsByName.foo).toBeUndefined(); expect(xfltr.annoMatrix.schema.annotations.obsByName.foo).toBeUndefined();
// 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.
(fetch as any).mockRejectOnce(new Error("unknown column name")); (fetch as any).mockRejectOnce(new Error("unknown column name"));
await expect(xfltr.annoMatrix.fetch("obs", "foo")).rejects.toThrow( await expect(xfltr.annoMatrix.fetch(Field.obs, "foo")).rejects.toThrow(
"unknown column name" "unknown column name"
); );
// now same, but ensure we have built an index before doing the drop // now same, but ensure we have built an index before doing the drop
xfltr = await helperAddTestCol(crossfilter, "bar"); xfltr = await helperAddTestCol(crossfilter, "bar");
xfltr = await xfltr.select("obs", "bar", { xfltr = await xfltr.select(Field.obs, "bar", {
mode: "exact", mode: "exact",
values: "whatever", values: "whatever",
}); });
@@ -422,9 +423,9 @@ describe("AnnoMatrixCrossfilter", () => {
// 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.
(fetch as any).mockRejectOnce(new Error("unknown column name")); (fetch as any).mockRejectOnce(new Error("unknown column name"));
await expect(xfltr.select("obs", "bar", { mode: "all" })).rejects.toThrow( await expect(
"unknown column name" xfltr.select(Field.obs, "bar", { mode: "all" })
); ).rejects.toThrow("unknown column name");
}); });
test("renameObsColumn", async () => { test("renameObsColumn", async () => {
@@ -441,23 +442,25 @@ describe("AnnoMatrixCrossfilter", () => {
// add a column, then rename it. // add a column, then rename it.
xfltr = await helperAddTestCol(crossfilter, "foo"); xfltr = await helperAddTestCol(crossfilter, "foo");
xfltr = xfltr.renameObsColumn("foo", "bar"); xfltr = xfltr.renameObsColumn("foo", "bar");
expect(xfltr.annoMatrix.getColumnSchema("obs", "foo")).toBeUndefined(); expect(
expect(xfltr.annoMatrix.getColumnSchema("obs", "bar")).toMatchObject({ xfltr.annoMatrix.getColumnSchema(Field.obs, "foo")
).toBeUndefined();
expect(xfltr.annoMatrix.getColumnSchema(Field.obs, "bar")).toMatchObject({
name: "bar", name: "bar",
type: "categorical", type: "categorical",
}); });
// 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.
(fetch as any).mockRejectOnce(new Error("unknown column name")); (fetch as any).mockRejectOnce(new Error("unknown column name"));
await expect(xfltr.annoMatrix.fetch("obs", "foo")).rejects.toThrow( await expect(xfltr.annoMatrix.fetch(Field.obs, "foo")).rejects.toThrow(
"unknown column name" "unknown column name"
); );
const df = await xfltr.annoMatrix.fetch("obs", "bar"); const df = await xfltr.annoMatrix.fetch(Field.obs, "bar");
expect(df.hasCol("bar")).toBeTruthy(); expect(df.hasCol("bar")).toBeTruthy();
// now same, but ensure we have built an index before doing the rename // now same, but ensure we have built an index before doing the rename
xfltr = await helperAddTestCol(crossfilter, "bar"); xfltr = await helperAddTestCol(crossfilter, "bar");
xfltr = await xfltr.select("obs", "bar", { xfltr = await xfltr.select(Field.obs, "bar", {
mode: "exact", mode: "exact",
values: "whatever", values: "whatever",
}); });
@@ -465,11 +468,11 @@ describe("AnnoMatrixCrossfilter", () => {
// 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.
(fetch as any).mockRejectOnce(new Error("unknown column name")); (fetch as any).mockRejectOnce(new Error("unknown column name"));
await expect(xfltr.select("obs", "bar", { mode: "all" })).rejects.toThrow(
"unknown column name"
);
await expect( await expect(
xfltr.select("obs", "xyz", { mode: "none" }) xfltr.select(Field.obs, "bar", { mode: "all" })
).rejects.toThrow("unknown column name");
await expect(
xfltr.select(Field.obs, "xyz", { mode: "none" })
).resolves.toBeInstanceOf(AnnoMatrixObsCrossfilter); ).resolves.toBeInstanceOf(AnnoMatrixObsCrossfilter);
}); });
@@ -493,7 +496,7 @@ describe("AnnoMatrixCrossfilter", () => {
categories: ["unassigned"], categories: ["unassigned"],
}); });
xfltr = xfltr.addObsAnnoCategory("foo", "a-new-label"); xfltr = xfltr.addObsAnnoCategory("foo", "a-new-label");
expect(xfltr.annoMatrix.getColumnSchema("obs", "foo")).toMatchObject({ expect(xfltr.annoMatrix.getColumnSchema(Field.obs, "foo")).toMatchObject({
name: "foo", name: "foo",
type: "categorical", type: "categorical",
categories: expect.arrayContaining(["a-new-label", "unassigned"]), categories: expect.arrayContaining(["a-new-label", "unassigned"]),
@@ -511,12 +514,12 @@ describe("AnnoMatrixCrossfilter", () => {
type: "categorical", type: "categorical",
categories: ["unassigned"], categories: ["unassigned"],
}); });
xfltr = await xfltr.select("obs", "bar", { xfltr = await xfltr.select(Field.obs, "bar", {
mode: "exact", mode: "exact",
values: "something", values: "something",
}); });
xfltr = xfltr.addObsAnnoCategory("bar", "a-new-label"); xfltr = xfltr.addObsAnnoCategory("bar", "a-new-label");
expect(xfltr.annoMatrix.getColumnSchema("obs", "bar")).toMatchObject({ expect(xfltr.annoMatrix.getColumnSchema(Field.obs, "bar")).toMatchObject({
name: "bar", name: "bar",
type: "categorical", type: "categorical",
categories: expect.arrayContaining(["a-new-label", "unassigned"]), categories: expect.arrayContaining(["a-new-label", "unassigned"]),
@@ -540,14 +543,14 @@ describe("AnnoMatrixCrossfilter", () => {
type: "categorical", type: "categorical",
categories: ["unassigned", "red", "green", "blue"], categories: ["unassigned", "red", "green", "blue"],
}); });
xfltr = await xfltr.select("obs", "foo", { mode: "all" }); xfltr = await xfltr.select(Field.obs, "foo", { mode: "all" });
expect( expect(
(await xfltr.annoMatrix.fetch("obs", "foo")) (await xfltr.annoMatrix.fetch(Field.obs, "foo"))
.col("foo") .col("foo")
.asArray() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. .asArray() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
.every((v: any) => v === "unassigned") .every((v: any) => v === "unassigned")
).toBeTruthy(); ).toBeTruthy();
expect(xfltr.annoMatrix.getColumnSchema("obs", "foo")).toMatchObject({ expect(xfltr.annoMatrix.getColumnSchema(Field.obs, "foo")).toMatchObject({
name: "foo", name: "foo",
type: "categorical", type: "categorical",
categories: expect.arrayContaining([ categories: expect.arrayContaining([
@@ -561,21 +564,23 @@ describe("AnnoMatrixCrossfilter", () => {
// remove an unused category // remove an unused category
const xfltr1 = await xfltr.removeObsAnnoCategory("foo", "red", "mumble"); const xfltr1 = await xfltr.removeObsAnnoCategory("foo", "red", "mumble");
expect( expect(
(await xfltr1.annoMatrix.fetch("obs", "foo")) (await xfltr1.annoMatrix.fetch(Field.obs, "foo"))
.col("foo") .col("foo")
.asArray() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. .asArray() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
.every((v: any) => v === "unassigned") .every((v: any) => v === "unassigned")
).toBeTruthy(); ).toBeTruthy();
expect(xfltr1.annoMatrix.getColumnSchema("obs", "foo")).toMatchObject({ expect(xfltr1.annoMatrix.getColumnSchema(Field.obs, "foo")).toMatchObject(
name: "foo", {
type: "categorical", name: "foo",
categories: expect.arrayContaining([ type: "categorical",
"unassigned", categories: expect.arrayContaining([
"green", "unassigned",
"blue", "green",
"mumble", "blue",
]), "mumble",
}); ]),
}
);
// remove a used category // remove a used category
const xfltr2 = await xfltr.removeObsAnnoCategory( const xfltr2 = await xfltr.removeObsAnnoCategory(
@@ -584,16 +589,18 @@ describe("AnnoMatrixCrossfilter", () => {
"red" "red"
); );
expect( expect(
(await xfltr2.annoMatrix.fetch("obs", "foo")) (await xfltr2.annoMatrix.fetch(Field.obs, "foo"))
.col("foo") .col("foo")
.asArray() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. .asArray() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
.every((v: any) => v === "red") .every((v: any) => v === "red")
).toBeTruthy(); ).toBeTruthy();
expect(xfltr2.annoMatrix.getColumnSchema("obs", "foo")).toMatchObject({ expect(xfltr2.annoMatrix.getColumnSchema(Field.obs, "foo")).toMatchObject(
name: "foo", {
type: "categorical", name: "foo",
categories: expect.arrayContaining(["green", "blue", "red"]), type: "categorical",
}); categories: expect.arrayContaining(["green", "blue", "red"]),
}
);
}); });
test("setObsColumnValues", async () => { test("setObsColumnValues", async () => {
@@ -611,7 +618,7 @@ describe("AnnoMatrixCrossfilter", () => {
type: "categorical", type: "categorical",
categories: ["unassigned", "red", "green", "blue"], categories: ["unassigned", "red", "green", "blue"],
}); });
xfltr = await xfltr.select("obs", "foo", { mode: "all" }); xfltr = await xfltr.select(Field.obs, "foo", { mode: "all" });
// catch unknown row label // catch unknown row label
await expect(() => await expect(() =>
@@ -620,14 +627,14 @@ describe("AnnoMatrixCrossfilter", () => {
// set a few rows // set a few rows
expect( expect(
(await xfltr.annoMatrix.fetch("obs", "foo")) (await xfltr.annoMatrix.fetch(Field.obs, "foo"))
.col("foo") .col("foo")
.asArray() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. .asArray() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
.every((v: any) => v === "unassigned") .every((v: any) => v === "unassigned")
).toBeTruthy(); ).toBeTruthy();
const xfltr1 = await xfltr.setObsColumnValues("foo", [0, 10], "purple"); const xfltr1 = await xfltr.setObsColumnValues("foo", [0, 10], "purple");
expect( expect(
(await xfltr1.annoMatrix.fetch("obs", "foo")) (await xfltr1.annoMatrix.fetch(Field.obs, "foo"))
.col("foo") .col("foo")
.asArray() .asArray()
.every( .every(
@@ -636,20 +643,22 @@ describe("AnnoMatrixCrossfilter", () => {
v === "unassigned" || (v === "purple" && (i === 0 || i === 10)) v === "unassigned" || (v === "purple" && (i === 0 || i === 10))
) )
).toBeTruthy(); ).toBeTruthy();
expect(xfltr1.annoMatrix.getColumnSchema("obs", "foo")).toMatchObject({ expect(xfltr1.annoMatrix.getColumnSchema(Field.obs, "foo")).toMatchObject(
name: "foo", {
type: "categorical", name: "foo",
categories: expect.arrayContaining([ type: "categorical",
"unassigned", categories: expect.arrayContaining([
"red", "unassigned",
"green", "red",
"blue", "green",
"purple", "blue",
]), "purple",
}); ]),
}
);
expect(xfltr1.countSelected()).toEqual(xfltr1.annoMatrix.nObs); expect(xfltr1.countSelected()).toEqual(xfltr1.annoMatrix.nObs);
const xfltr2 = await xfltr1.select("obs", "foo", { const xfltr2 = await xfltr1.select(Field.obs, "foo", {
mode: "exact", mode: "exact",
values: ["purple"], values: ["purple"],
}); });
@@ -672,7 +681,7 @@ describe("AnnoMatrixCrossfilter", () => {
type: "categorical", type: "categorical",
categories: ["unassigned", "red", "green", "blue"], categories: ["unassigned", "red", "green", "blue"],
}); });
xfltr = await xfltr.select("obs", "foo", { xfltr = await xfltr.select(Field.obs, "foo", {
mode: "exact", mode: "exact",
values: "red", values: "red",
}); });
@@ -683,12 +692,12 @@ describe("AnnoMatrixCrossfilter", () => {
).rejects.toThrow("unknown category"); ).rejects.toThrow("unknown category");
let xfltr1 = await xfltr.setObsColumnValues("foo", [0, 10], "purple"); let xfltr1 = await xfltr.setObsColumnValues("foo", [0, 10], "purple");
xfltr1 = await xfltr1.select("obs", "foo", { xfltr1 = await xfltr1.select(Field.obs, "foo", {
mode: "exact", mode: "exact",
values: "purple", values: "purple",
}); });
expect( expect(
(await xfltr1.annoMatrix.fetch("obs", "foo")) (await xfltr1.annoMatrix.fetch(Field.obs, "foo"))
.col("foo") .col("foo")
.asArray() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. .asArray() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
.filter((v: any) => v === "purple") .filter((v: any) => v === "purple")
@@ -696,29 +705,31 @@ describe("AnnoMatrixCrossfilter", () => {
xfltr1 = await xfltr1.resetObsColumnValues("foo", "purple", "magenta"); xfltr1 = await xfltr1.resetObsColumnValues("foo", "purple", "magenta");
expect( expect(
(await xfltr1.annoMatrix.fetch("obs", "foo")) (await xfltr1.annoMatrix.fetch(Field.obs, "foo"))
.col("foo") .col("foo")
.asArray() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. .asArray() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
.filter((v: any) => v === "magenta") .filter((v: any) => v === "magenta")
).toHaveLength(2); ).toHaveLength(2);
expect( expect(
(await xfltr1.annoMatrix.fetch("obs", "foo")) (await xfltr1.annoMatrix.fetch(Field.obs, "foo"))
.col("foo") .col("foo")
.asArray() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. .asArray() // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
.filter((v: any) => v === "purple") .filter((v: any) => v === "purple")
).toHaveLength(0); ).toHaveLength(0);
expect(xfltr1.annoMatrix.getColumnSchema("obs", "foo")).toMatchObject({ expect(xfltr1.annoMatrix.getColumnSchema(Field.obs, "foo")).toMatchObject(
name: "foo", {
type: "categorical", name: "foo",
categories: expect.arrayContaining([ type: "categorical",
"unassigned", categories: expect.arrayContaining([
"red", "unassigned",
"green", "red",
"blue", "green",
"purple", "blue",
"magenta", "purple",
]), "magenta",
}); ]),
}
);
}); });
}); });
@@ -729,7 +740,7 @@ describe("AnnoMatrixCrossfilter", () => {
(fetch as any).once( (fetch as any).once(
serverMocks.dataframeResponse(["louvain"], [obsLouvain]) serverMocks.dataframeResponse(["louvain"], [obsLouvain])
); );
const xfltr = await crossfilter.select("obs", "louvain", { const xfltr = await crossfilter.select(Field.obs, "louvain", {
mode: "exact", mode: "exact",
values: "B cells", values: "B cells",
}); });
@@ -4,31 +4,34 @@ import {
_whereCacheCreate, _whereCacheCreate,
_whereCacheMerge, _whereCacheMerge,
} from "../../../src/annoMatrix/whereCache"; } from "../../../src/annoMatrix/whereCache";
import { Field, Schema } from "../../../src/common/types/schema";
import { Query } from "../../../src/annoMatrix/query";
const schema = {}; const schema = {} as Schema;
describe("whereCache", () => { describe("whereCache", () => {
test("whereCacheGet - where query, missing cache values", () => { test("whereCacheGet - where query, missing cache values", () => {
expect( expect(
_whereCacheGet({}, schema, "X", { _whereCacheGet({}, schema, Field.X, {
where: { where: {
field: "var", field: Field.var,
column: "foo", column: "foo",
value: "bar", value: "bar",
}, },
}) })
).toEqual([undefined]); ).toEqual([undefined]);
expect( expect(
_whereCacheGet({}, schema, "X", { _whereCacheGet({}, schema, Field.X, {
summarize: { summarize: {
field: "var", method: "mean",
field: Field.var,
column: "foo", column: "foo",
values: ["bar"], values: ["bar"],
}, },
}) })
).toEqual([undefined]); ).toEqual([undefined]);
expect( expect(
_whereCacheGet({ where: { X: {} } }, schema, "X", { _whereCacheGet({ where: { X: {} } }, schema, Field.X, {
where: { where: {
field: "var", field: "var",
column: "foo", column: "foo",
@@ -37,7 +40,7 @@ describe("whereCache", () => {
}) })
).toEqual([undefined]); ).toEqual([undefined]);
expect( expect(
_whereCacheGet({ where: { X: { var: new Map() } } }, schema, "X", { _whereCacheGet({ where: { X: { var: new Map() } } }, schema, Field.X, {
where: { where: {
field: "var", field: "var",
column: "foo", column: "foo",
@@ -49,7 +52,7 @@ describe("whereCache", () => {
_whereCacheGet( _whereCacheGet(
{ where: { X: { var: new Map([["foo", new Map()]]) } } }, { where: { X: { var: new Map([["foo", new Map()]]) } } },
schema, schema,
"X", Field.X,
{ {
where: { where: {
field: "var", field: "var",
@@ -63,7 +66,7 @@ describe("whereCache", () => {
test("whereCacheGet - summarize query, missing cache values", () => { test("whereCacheGet - summarize query, missing cache values", () => {
expect( expect(
_whereCacheGet({}, schema, "X", { _whereCacheGet({}, schema, Field.X, {
summarize: { summarize: {
method: "mean", method: "mean",
field: "var", field: "var",
@@ -76,7 +79,7 @@ describe("whereCache", () => {
_whereCacheGet( _whereCacheGet(
{ summarize: { X: { mean: { var: new Map() } } } }, { summarize: { X: { mean: { var: new Map() } } } },
schema, schema,
"X", Field.X,
{ {
summarize: { summarize: {
method: "mean", method: "mean",
@@ -122,7 +125,7 @@ describe("whereCache", () => {
}; };
expect( expect(
_whereCacheGet(whereCache, schema, "X", { _whereCacheGet(whereCache, schema, Field.X, {
where: { where: {
field: "var", field: "var",
column: "foo", column: "foo",
@@ -131,7 +134,7 @@ describe("whereCache", () => {
}) })
).toEqual([0]); ).toEqual([0]);
expect( expect(
_whereCacheGet(whereCache, schema, "X", { _whereCacheGet(whereCache, schema, Field.X, {
summarize: { summarize: {
method: "mean", method: "mean",
field: "var", field: "var",
@@ -141,7 +144,7 @@ describe("whereCache", () => {
}) })
).toEqual([0]); ).toEqual([0]);
expect( expect(
_whereCacheGet(whereCache, schema, "X", { _whereCacheGet(whereCache, schema, Field.X, {
where: { where: {
field: "var", field: "var",
column: "foo", column: "foo",
@@ -150,7 +153,7 @@ describe("whereCache", () => {
}) })
).toEqual([1, 2]); ).toEqual([1, 2]);
expect( expect(
_whereCacheGet(whereCache, schema, "X", { _whereCacheGet(whereCache, schema, Field.X, {
summarize: { summarize: {
method: "mean", method: "mean",
field: "var", field: "var",
@@ -159,9 +162,12 @@ describe("whereCache", () => {
}, },
}) })
).toEqual([1, 2]); ).toEqual([1, 2]);
expect(_whereCacheGet(whereCache, schema, "Y", {})).toEqual([undefined]);
expect( expect(
_whereCacheGet(whereCache, schema, "X", { // Force invalid field value Y
_whereCacheGet(whereCache, schema, "Y" as Field, {} as Query)
).toEqual([undefined]);
expect(
_whereCacheGet(whereCache, schema, Field.X, {
where: { where: {
field: "whoknows", field: "whoknows",
column: "whatever", column: "whatever",
@@ -170,7 +176,7 @@ describe("whereCache", () => {
}) })
).toEqual([undefined]); ).toEqual([undefined]);
expect( expect(
_whereCacheGet(whereCache, schema, "X", { _whereCacheGet(whereCache, schema, Field.X, {
where: { where: {
field: "var", field: "var",
column: "whatever", column: "whatever",
@@ -179,7 +185,7 @@ describe("whereCache", () => {
}) })
).toEqual([undefined]); ).toEqual([undefined]);
expect( expect(
_whereCacheGet(whereCache, schema, "X", { _whereCacheGet(whereCache, schema, Field.X, {
where: { where: {
field: "var", field: "var",
column: "foo", column: "foo",
@@ -198,7 +204,7 @@ describe("whereCache", () => {
}, },
}; };
const wc = _whereCacheCreate( const wc = _whereCacheCreate(
"field", Field.obs,
{ {
where: { where: {
field: "queryField", field: "queryField",
@@ -212,7 +218,7 @@ describe("whereCache", () => {
expect(wc).toEqual( expect(wc).toEqual(
expect.objectContaining({ expect.objectContaining({
where: { where: {
field: { [Field.obs]: {
queryField: expect.any(Map), queryField: expect.any(Map),
}, },
}, },
@@ -220,18 +226,19 @@ describe("whereCache", () => {
); );
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
// 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.
expect((wc.where as any).field.queryField.has("queryColumn")).toEqual(true); expect((wc.where as any)[Field.obs].queryField.has("queryColumn")).toEqual(true);
expect( expect(
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
// 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.
(wc.where as any).field.queryField.get("queryColumn") (wc.where as any)[Field.obs].queryField.get("queryColumn")
).toBeInstanceOf(Map); ).toBeInstanceOf(Map);
expect( expect(
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
// 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.
(wc.where as any).field.queryField.get("queryColumn").has("queryValue") (wc.where as any)[Field.obs].queryField.get("queryColumn").has("queryValue")
).toEqual(true); ).toEqual(true);
expect(_whereCacheGet(wc, schema, "field", query)).toEqual([0, 1, 2]); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion --- assert wc to be non-null
expect(_whereCacheGet(wc!, schema, Field.obs, query)).toEqual([0, 1, 2]);
}); });
test("whereCacheCreate, summarize query", () => { test("whereCacheCreate, summarize query", () => {
@@ -243,12 +250,14 @@ describe("whereCache", () => {
values: ["queryValue"], values: ["queryValue"],
}, },
}; };
const wc = _whereCacheCreate("field", query, [0, 1, 2]); const wc = _whereCacheCreate(Field.obs, query, [0, 1, 2]);
expect(_whereCacheGet(wc, schema, "field", query)).toEqual([0, 1, 2]); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion --- assert wc to be non-null
expect(_whereCacheGet(wc!, schema, Field.obs, query)).toEqual([0, 1, 2]);
}); });
test("whereCacheCreate, unknown query type", () => { test("whereCacheCreate, unknown query type", () => {
expect(_whereCacheCreate("field", { foobar: true }, [1])).toEqual({}); // @ts-expect-error --- force invalid query {foobar: true}
expect(_whereCacheCreate(Field.obs, { foobar: true }, [1])).toEqual({});
}); });
test("whereCacheMerge, where queries", () => { test("whereCacheMerge, where queries", () => {
@@ -256,19 +265,20 @@ describe("whereCache", () => {
// remember, will mutate dst // remember, will mutate dst
const src = _whereCacheCreate( const src = _whereCacheCreate(
"field", Field.obs,
{ where: { field: "queryField", column: "queryColumn", value: "foo" } }, { where: { field: "queryField", column: "queryColumn", value: "foo" } },
["foo"] ["foo"]
); );
const dst1 = _whereCacheCreate( const dst1 = _whereCacheCreate(
"field", Field.obs,
{ where: { field: "queryField", column: "queryColumn", value: "bar" } }, { where: { field: "queryField", column: "queryColumn", value: "bar" } },
["dst1"] ["dst1"]
); );
wc = _whereCacheMerge(dst1, src); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion --- assert dst1 and src to be non-null
wc = _whereCacheMerge(dst1!, src!);
expect( expect(
_whereCacheGet(wc, schema, "field", { _whereCacheGet(wc, schema, Field.obs, {
where: { where: {
field: "queryField", field: "queryField",
column: "queryColumn", column: "queryColumn",
@@ -277,7 +287,7 @@ describe("whereCache", () => {
}) })
).toEqual(["foo"]); ).toEqual(["foo"]);
expect( expect(
_whereCacheGet(wc, schema, "field", { _whereCacheGet(wc, schema, Field.obs, {
where: { where: {
field: "queryField", field: "queryField",
column: "queryColumn", column: "queryColumn",
@@ -287,13 +297,14 @@ describe("whereCache", () => {
).toEqual(["dst1"]); ).toEqual(["dst1"]);
const dst2 = _whereCacheCreate( const dst2 = _whereCacheCreate(
"field", Field.obs,
{ where: { field: "queryField", column: "queryColumn", value: "bar" } }, { where: { field: "queryField", column: "queryColumn", value: "bar" } },
["dst2"] ["dst2"]
); );
wc = _whereCacheMerge(dst2, dst1, src); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion --- assert dst2m, dst1 and src to be non-null
wc = _whereCacheMerge(dst2!, dst1!, src!);
expect( expect(
_whereCacheGet(wc, schema, "field", { _whereCacheGet(wc, schema, Field.obs, {
where: { where: {
field: "queryField", field: "queryField",
column: "queryColumn", column: "queryColumn",
@@ -302,7 +313,7 @@ describe("whereCache", () => {
}) })
).toEqual(["foo"]); ).toEqual(["foo"]);
expect( expect(
_whereCacheGet(wc, schema, "field", { _whereCacheGet(wc, schema, Field.obs, {
where: { where: {
field: "queryField", field: "queryField",
column: "queryColumn", column: "queryColumn",
@@ -311,17 +322,20 @@ describe("whereCache", () => {
}) })
).toEqual(["dst1"]); ).toEqual(["dst1"]);
wc = _whereCacheMerge({}, src); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion --- assert src to be non-null
wc = _whereCacheMerge({}, src!);
expect(wc).toEqual(src); expect(wc).toEqual(src);
wc = _whereCacheMerge({ where: { field: { queryField: new Map() } } }, src); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion --- assert src to be non-null
wc = _whereCacheMerge({ where: { obs: { queryField: new Map() } } }, src!);
expect(wc).toEqual(src); expect(wc).toEqual(src);
}); });
test("whereCacheMerge, mixed queries", () => { test("whereCacheMerge, mixed queries", () => {
const wc = _whereCacheMerge( const wc = _whereCacheMerge(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion --- assert wc to be non-null
_whereCacheCreate( _whereCacheCreate(
"field", Field.obs,
{ {
where: { where: {
field: "queryField", field: "queryField",
@@ -330,9 +344,10 @@ describe("whereCache", () => {
}, },
}, },
["a"] ["a"]
), )!,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion --- assert wc to be non-null
_whereCacheCreate( _whereCacheCreate(
"field", Field.obs,
{ {
summarize: { summarize: {
method: "mean", method: "mean",
@@ -342,11 +357,11 @@ describe("whereCache", () => {
}, },
}, },
["b"] ["b"]
) )!
); );
expect( expect(
_whereCacheGet(wc, schema, "field", { _whereCacheGet(wc, schema, Field.obs, {
where: { where: {
field: "queryField", field: "queryField",
column: "queryColumn", column: "queryColumn",
@@ -356,7 +371,7 @@ describe("whereCache", () => {
).toEqual(["a"]); ).toEqual(["a"]);
expect( expect(
_whereCacheGet(wc, schema, "field", { _whereCacheGet(wc, schema, Field.obs, {
summarize: { summarize: {
method: "mean", method: "mean",
field: "queryField", field: "queryField",
@@ -367,7 +382,7 @@ describe("whereCache", () => {
).toEqual(["b"]); ).toEqual(["b"]);
expect( expect(
_whereCacheGet(wc, schema, "field", { _whereCacheGet(wc, schema, Field.obs, {
where: { where: {
field: "queryField", field: "queryField",
column: "queryColumn", column: "queryColumn",
@@ -377,7 +392,7 @@ describe("whereCache", () => {
).toEqual([undefined]); ).toEqual([undefined]);
expect( expect(
_whereCacheGet(wc, schema, "field", { _whereCacheGet(wc, schema, Field.obs, {
summarize: { summarize: {
method: "no-such-method", method: "no-such-method",
field: "queryField", field: "queryField",
+18 -15
View File
@@ -7,6 +7,7 @@ import { ThunkAction } from "redux-thunk";
import { AnnoMatrixObsCrossfilter } from "../annoMatrix"; import { AnnoMatrixObsCrossfilter } from "../annoMatrix";
import type { AppDispatch, RootState } from "../reducers"; import type { AppDispatch, RootState } from "../reducers";
import { _setEmbeddingSubset } from "../util/stateManager/viewStackHelpers"; import { _setEmbeddingSubset } from "../util/stateManager/viewStackHelpers";
import { Field } from "../common/types/schema";
// 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 async function _switchEmbedding( export async function _switchEmbedding(
@@ -26,7 +27,7 @@ export async function _switchEmbedding(
const obsCrossfilter = await new AnnoMatrixObsCrossfilter( const obsCrossfilter = await new AnnoMatrixObsCrossfilter(
annoMatrix, annoMatrix,
prevCrossfilter.obsCrossfilter prevCrossfilter.obsCrossfilter
).select("emb", newEmbeddingName, { ).select(Field.emb, newEmbeddingName, {
mode: "all", mode: "all",
}); });
return [annoMatrix, obsCrossfilter]; return [annoMatrix, obsCrossfilter];
@@ -41,17 +42,19 @@ export const layoutChoiceAction: ActionCreator<
On layout choice, make sure we have selected all on the previous layout, AND the new On layout choice, make sure we have selected all on the previous layout, AND the new
layout. layout.
*/ */
const { annoMatrix: prevAnnoMatrix, obsCrossfilter: prevCrossfilter } = const {
getState(); annoMatrix: prevAnnoMatrix,
const [annoMatrix, obsCrossfilter] = await _switchEmbedding( obsCrossfilter: prevCrossfilter,
prevAnnoMatrix, } = getState();
prevCrossfilter, const [annoMatrix, obsCrossfilter] = await _switchEmbedding(
newLayoutChoice prevAnnoMatrix,
); prevCrossfilter,
dispatch({ newLayoutChoice
type: "set layout choice", );
layoutChoice: newLayoutChoice, dispatch({
obsCrossfilter, type: "set layout choice",
annoMatrix, layoutChoice: newLayoutChoice,
}); obsCrossfilter,
}; annoMatrix,
});
};
+276 -275
View File
@@ -2,6 +2,9 @@ import {
Dataframe, Dataframe,
IdentityInt32Index, IdentityInt32Index,
dataframeMemo, dataframeMemo,
LabelType,
DataframeValue,
DataframeValueArray,
} from "../util/dataframe"; } from "../util/dataframe";
import { import {
_getColumnDimensionNames, _getColumnDimensionNames,
@@ -10,45 +13,70 @@ import {
_getWritableColumns, _getWritableColumns,
} from "./schema"; } from "./schema";
import { indexEntireSchema } from "../util/stateManager/schemaHelpers"; import { indexEntireSchema } from "../util/stateManager/schemaHelpers";
import { _whereCacheGet, _whereCacheMerge } from "./whereCache"; import {
_whereCacheGet,
_whereCacheMerge,
WhereCache,
WhereCacheColumnLabels,
} from "./whereCache";
import _shallowClone from "./clone"; import _shallowClone from "./clone";
import { _queryValidate, _queryCacheKey } from "./query"; import { _queryValidate, _queryCacheKey, Query } from "./query";
import { GCHints } from "../common/types/entities";
import {
AnnotationColumnSchema,
Category,
Field,
EmbeddingSchema,
Schema,
ArraySchema,
RawSchema,
} from "../common/types/schema";
import { LabelArray } from "../util/dataframe/types";
import { LabelIndexBase } from "../util/dataframe/labelIndex";
const _dataframeCache = dataframeMemo(128); const _dataframeCache = dataframeMemo(128);
export default class AnnoMatrix { interface Cache {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. [Field.obs]: Dataframe;
public isView: any; [Field.var]: Dataframe;
[Field.emb]: Dataframe;
[Field.X]: Dataframe;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. interface PendingLoad {
public nObs: any; [Field.obs]: { [key: string]: Promise<void> };
[Field.var]: { [key: string]: Promise<void> };
[Field.emb]: { [key: string]: Promise<void> };
[Field.X]: { [key: string]: Promise<void> };
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. export interface UserFlags {
public nVar: any; isUserSubsetView?: boolean;
isEmbSubsetView?: boolean;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. export default abstract class AnnoMatrix {
public rowIndex: any; public isView: boolean;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. public nObs: number;
public schema: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. public nVar: number;
public userFlags: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. public rowIndex: LabelIndexBase;
public viewOf: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. public schema: Schema;
protected _cache: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. public userFlags: UserFlags;
private _pendingLoad: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. public viewOf: AnnoMatrix;
private _whereCache: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. public _cache: Cache;
private _gcInfo: any;
private _pendingLoad: PendingLoad;
private _whereCache: WhereCache;
private _gcInfo: Map<string, number>;
/* /*
Abstract base class for all AnnoMatrix objects. This class provides a proxy Abstract base class for all AnnoMatrix objects. This class provides a proxy
@@ -80,16 +108,19 @@ export default class AnnoMatrix {
subset(annoMatrix, rowLabels) -> annoMatrix subset(annoMatrix, rowLabels) -> annoMatrix
etc. etc.
*/ */
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. static fields(): Field[] {
static fields() {
/* /*
return the fields present in the AnnoMatrix instance. return the fields present in the AnnoMatrix instance.
*/ */
return ["obs", "var", "emb", "X"]; return [Field.obs, Field.var, Field.emb, Field.X];
} }
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. constructor(
constructor(schema: any, nObs: any, nVar: any, rowIndex = null) { schema: RawSchema,
nObs: number,
nVar: number,
rowIndex: LabelIndexBase | null = null
) {
/* /*
Private constructor - this is an abstract base class. Do not use. Private constructor - this is an abstract base class. Do not use.
*/ */
@@ -105,7 +136,7 @@ export default class AnnoMatrix {
* rowIndex - a rowIndex shared by all data on this view (ie, the list of cells). * rowIndex - a rowIndex shared by all data on this view (ie, the list of cells).
The row index labels are as defined by the base dataset from the server. The row index labels are as defined by the base dataset from the server.
* isView - true if this is a view, false if not. * isView - true if this is a view, false if not.
* viewOf - pointer to parent annomatrix if a view, undefined/null if not a view. * viewOf - pointer to parent annomatrix if a view, self if not a view.
* userFlags - container for any additional state a user of this API wants to hang * userFlags - container for any additional state a user of this API wants to hang
off of an annoMatrix, and have propagated by the (shallow) cloning protocol. off of an annoMatrix, and have propagated by the (shallow) cloning protocol.
*/ */
@@ -114,7 +145,7 @@ export default class AnnoMatrix {
this.nVar = nVar; this.nVar = nVar;
this.rowIndex = rowIndex || new IdentityInt32Index(nObs); this.rowIndex = rowIndex || new IdentityInt32Index(nObs);
this.isView = false; this.isView = false;
this.viewOf = undefined; this.viewOf = this;
this.userFlags = {}; this.userFlags = {};
/* /*
@@ -137,16 +168,14 @@ export default class AnnoMatrix {
emb: {}, emb: {},
X: {}, X: {},
}; };
this._whereCache = {}; this._whereCache = {} as WhereCache;
this._gcInfo = new Map(); this._gcInfo = new Map();
} }
/** /**
** Schema helper/accessors ** Schema helper/accessors
**/ **/
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type. getMatrixColumns(field: Field): string[] {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
getMatrixColumns(field) {
/* /*
Return array of column names in the field. ONLY supported on the Return array of column names in the field. ONLY supported on the
obs, var and emb fields. X currently unimplemented and will throw. obs, var and emb fields. X currently unimplemented and will throw.
@@ -158,8 +187,8 @@ export default class AnnoMatrix {
return _schemaColumns(this.schema, field); return _schemaColumns(this.schema, field);
} }
// eslint-disable-next-line class-methods-use-this, @typescript-eslint/explicit-module-boundary-types -- need to be able to call this on instances // eslint-disable-next-line class-methods-use-this -- need to be able to call this on instances
getMatrixFields() { getMatrixFields(): Field[] {
/* /*
Return array of fields in this annoMatrix. Currently hard-wired to Return array of fields in this annoMatrix. Currently hard-wired to
return: ["X", "obs", "var", "emb"]. return: ["X", "obs", "var", "emb"].
@@ -169,9 +198,7 @@ export default class AnnoMatrix {
return AnnoMatrix.fields(); return AnnoMatrix.fields();
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type. getColumnSchema(field: Field, col: LabelType): ArraySchema {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
getColumnSchema(field, col) {
/* /*
Return the schema for the field & column ,eg, Return the schema for the field & column ,eg,
@@ -183,9 +210,7 @@ export default class AnnoMatrix {
return _getColumnSchema(this.schema, field, col); return _getColumnSchema(this.schema, field, col);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type. getColumnDimensions(field: Field, col: LabelType): LabelArray | undefined {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
getColumnDimensions(field, col) {
/* /*
Return the dimensions on this field / column. For most fields, which are 1D, Return the dimensions on this field / column. For most fields, which are 1D,
this just return the column name. Multi-dimensional columns, such as embeddings, this just return the column name. Multi-dimensional columns, such as embeddings,
@@ -203,23 +228,19 @@ export default class AnnoMatrix {
/** /**
** General utility methods ** General utility methods
**/ **/
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. base(): AnnoMatrix {
base() {
/* /*
return the base of view, or `this` if not a view. return the base of view, or `this` if not a view.
*/ */
// eslint-disable-next-line @typescript-eslint/no-this-alias --- FIXME: disabled temporarily on migrate to TS. let annoMatrix = this._getViewOf();
let annoMatrix = this; while (annoMatrix.isView) annoMatrix = annoMatrix._getViewOf();
while (annoMatrix.isView) annoMatrix = annoMatrix.viewOf;
return annoMatrix; return annoMatrix;
} }
/** /**
** Load / read interfaces ** Load / read interfaces
**/ **/
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type. fetch(field: Field, q: Query | Query[]): Promise<Dataframe> {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
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.
@@ -276,9 +297,7 @@ export default class AnnoMatrix {
return this._fetch(field, q); return this._fetch(field, q);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type. prefetch(field: Field, q: Query): void {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
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.
@@ -307,163 +326,147 @@ export default class AnnoMatrix {
** The actual implementation is in the sub-classes, which MUST override these. ** The actual implementation is in the sub-classes, which MUST override these.
**/ **/
// @ts-expect-error ts-migrate(6133) FIXME: 'col' is declared but its value is never read. /*
// eslint-disable-next-line class-methods-use-this, @typescript-eslint/no-unused-vars, @typescript-eslint/explicit-module-boundary-types -- make sure subclass implements Add a new category value (aka "label") to a writable obs column, and return the new AnnoMatrix.
addObsAnnoCategory(col, category) { Typical use is to add a new user-created label to a user-created obs categorical
/* annotation.
Add a new category value (aka "label") to a writable obs column, and return the new AnnoMatrix.
Typical use is to add a new user-created label to a user-created obs categorical
annotation.
Will throw column does not exist or is not writable. Will throw column does not exist or is not writable.
Example: Example:
addObsAnnoCategory("my cell type", "left toenail") -> AnnoMatrix addObsAnnoCategory("my cell type", "left toenail") -> AnnoMatrix
*/
abstract addObsAnnoCategory(col: LabelType, category: string): AnnoMatrix;
/*
Remove a category value from an obs column, reassign any obs having that value
to the 'unassignedCategory' value, and return a promise for a new AnnoMatrix.
Typical use is to remove a user-created label from a user-created obs categorical
annotation.
Will throw column does not exist or is not writable.
An `unassignedCategory` value must be provided, for assignment to any obs/cells
that had the now-delete category label as their value.
Example:
await removeObsAnnoCategory("my-tissue-type", "right earlobe", "unassigned") -> AnnoMatrix
NOTE: method is async as it may need to fetch data to provide the reassignment.
*/
abstract removeObsAnnoCategory(
col: LabelType,
category: Category,
unassignedCategory: string
): Promise<AnnoMatrix>;
/*
Drop an entire writable column, eg a user-created obs annotation. Typical use
is to provide the "Delete Category" implementation. Returns the new AnnoMatrix.
Will throw if not a writable annotation.
Will throw column does not exist or is not writable.
Example:
dropObsColumn("old annotations") -> AnnoMatrix
*/
abstract dropObsColumn(col: LabelType): AnnoMatrix;
/*
Add a new writable OBS annotation column, with the caller-specified schema, initial value
type and value.
Value may be any one of:
* an array of values
* a primitive type, including null or undefined.
If an array, length must be the same as 'this.nObs', and constructor must equal 'Ctor'.
If a primitive, 'Ctor' will be used to create the initial value, which will be filled
with 'value'.
Throws if the name specified in 'colSchema' duplicates an existing obs column.
Returns a new AnnoMatrix.
Examples:
addObsColumn(
{ name: "foo", type: "categorical", categories: "unassigned" },
Array,
"unassigned"
) -> AnnoMatrix
*/
abstract addObsColumn<T extends DataframeValueArray>(
colSchema: AnnotationColumnSchema,
Ctor: new (n: number) => T,
value: T
): AnnoMatrix;
/*
Rename the obs column 'oldCol' to have name 'newCol' and returns new AnnoMatrix.
Will throw column does not exist or is not writable, or if 'newCol' is not unique.
Example:
renameObsColumn('cell type', 'old cell type') -> AnnoMatrix.
*/
abstract renameObsColumn(oldCol: LabelType, newCol: LabelType): AnnoMatrix;
/*
Set all obs with label in array 'obsLabels' to have 'value'. Typical use would be
to set a group of cells to have a label on a user-created categorical annotation
(eg set all selected cells to have a label).
NOTE: async method, as it may need to fetch.
Will throw column does not exist or is not writable.
Example:
await setObsColmnValues("flavor", [383, 400], "tasty") -> AnnoMtarix
*/
abstract setObsColumnValues(
col: LabelType,
obsLabels: Int32Array,
value: DataframeValue
): Promise<AnnoMatrix>;
/*
Set by value - all elements in the column with value 'oldValue' are set to 'newValue'.
Async method - returns a promise for a new AnnoMatrix.
Typical use would be to set all labels of one value to another.
Will throw column does not exist or is not writable.
Example:
await resetObsColumnValues("my notes", "good", "not-good") -> AnnoMatrix
*/ */
_subclassResponsibility(); abstract resetObsColumnValues<T extends DataframeValue>(
} col: LabelType,
oldValue: T,
newValue: T
): Promise<AnnoMatrix>;
// @ts-expect-error ts-migrate(6133) FIXME: 'col' is declared but its value is never read. /*
// eslint-disable-next-line class-methods-use-this, @typescript-eslint/no-unused-vars, @typescript-eslint/explicit-module-boundary-types -- make sure subclass implements Add a new obs embedding to the AnnoMatrix, with provided schema.
async removeObsAnnoCategory(col, category, unassignedCategory) { Returns a new annomatrix.
/*
Remove a category value from an obs column, reassign any obs having that value
to the 'unassignedCategory' value, and return a promise for a new AnnoMatrix.
Typical use is to remove a user-created label from a user-created obs categorical
annotation.
Will throw column does not exist or is not writable. Typical use will be to add a re-embedding that the server has calculated.
An `unassignedCategory` value must be provided, for assignment to any obs/cells Will throw if the column schema is invalid (eg, duplicate name).
that had the now-delete category label as their value. */
abstract addEmbedding(colSchema: EmbeddingSchema): AnnoMatrix;
Example: getCacheKeys(
await removeObsAnnoCategory("my-tissue-type", "right earlobe", "unassigned") -> AnnoMatrix field: Field,
query: Query
NOTE: method is async as it may need to fetch data to provide the reassignment. ): WhereCacheColumnLabels | [undefined] {
*/
_subclassResponsibility();
}
// @ts-expect-error ts-migrate(6133) FIXME: 'col' is declared but its value is never read.
// eslint-disable-next-line class-methods-use-this, @typescript-eslint/no-unused-vars, @typescript-eslint/explicit-module-boundary-types -- make sure subclass implements
dropObsColumn(col) {
/*
Drop an entire writable column, eg a user-created obs annotation. Typical use
is to provide the "Delete Category" implementation. Returns the new AnnoMatrix.
Will throw if not a writable annotation.
Will throw column does not exist or is not writable.
Example:
dropObsColumn("old annotations") -> AnnoMatrix
*/
_subclassResponsibility();
}
// @ts-expect-error ts-migrate(6133) FIXME: 'colSchema' is declared but its value is never rea... Remove this comment to see the full error message
// eslint-disable-next-line class-methods-use-this, @typescript-eslint/no-unused-vars, @typescript-eslint/explicit-module-boundary-types -- make sure subclass implements
addObsColumn(colSchema, Ctor, value) {
/*
Add a new writable OBS annotation column, with the caller-specified schema, initial value
type and value.
Value may be any one of:
* an array of values
* a primitive type, including null or undefined.
If an array, length must be the same as 'this.nObs', and constructor must equal 'Ctor'.
If a primitive, 'Ctor' will be used to create the initial value, which will be filled
with 'value'.
Throws if the name specified in 'colSchema' duplicates an existing obs column.
Returns a new AnnoMatrix.
Examples:
addObsColumn(
{ name: "foo", type: "categorical", categories: "unassigned" },
Array,
"unassigned"
) -> AnnoMatrix
*/
_subclassResponsibility();
}
// @ts-expect-error ts-migrate(6133) FIXME: 'oldCol' is declared but its value is never read.
// eslint-disable-next-line class-methods-use-this, @typescript-eslint/no-unused-vars, @typescript-eslint/explicit-module-boundary-types -- make sure subclass implements
renameObsColumn(oldCol, newCol) {
/*
Rename the obs column 'oldCol' to have name 'newCol' and returns new AnnoMatrix.
Will throw column does not exist or is not writable, or if 'newCol' is not unique.
Example:
renameObsColumn('cell type', 'old cell type') -> AnnoMatrix.
*/
_subclassResponsibility();
}
// @ts-expect-error ts-migrate(6133) FIXME: 'col' is declared but its value is never read.
// eslint-disable-next-line class-methods-use-this, @typescript-eslint/no-unused-vars, @typescript-eslint/explicit-module-boundary-types -- make sure subclass implements
async setObsColumnValues(col, obsLabels, value) {
/*
Set all obs with label in array 'obsLabels' to have 'value'. Typical use would be
to set a group of cells to have a label on a user-created categorical anntoation
(eg set all selected cells to have a label).
NOTE: async method, as it may need to fetch.
Will throw column does not exist or is not writable.
Example:
await setObsColmnValues("flavor", [383, 400], "tasty") -> AnnoMtarix
*/
_subclassResponsibility();
}
// @ts-expect-error ts-migrate(6133) FIXME: 'col' is declared but its value is never read.
// eslint-disable-next-line class-methods-use-this, @typescript-eslint/no-unused-vars, @typescript-eslint/explicit-module-boundary-types -- make sure subclass implements
async resetObsColumnValues(col, oldValue, newValue) {
/*
Set by value - all elements in the column with value 'oldValue' are set to 'newValue'.
Async method - returns a promise for a new AnnoMatrix.
Typical use would be to set all labels of one value to another.
Will throw column does not exist or is not writable.
Example:
await resetObsColumnValues("my notes", "good", "not-good") -> AnnoMatrix
*/
_subclassResponsibility();
}
// @ts-expect-error ts-migrate(6133) FIXME: 'colSchema' is declared but its value is never rea... Remove this comment to see the full error message
// eslint-disable-next-line class-methods-use-this, @typescript-eslint/no-unused-vars, @typescript-eslint/explicit-module-boundary-types -- make sure subclass implements
addEmbedding(colSchema) {
/*
Add a new obs embedding to the AnnoMatrix, with provided schema.
Returns a new annomatrix.
Typical use will be to add a re-embedding that the server has calculated.
Will throw if the column schema is invalid (eg, duplicate name).
*/
_subclassResponsibility();
}
// @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.
getCacheKeys(field, query) {
/* /*
Return cache keys for columns associated with this query. May return Return cache keys for columns associated with this query. May return
[unknown] if no keys are known (ie, nothing is or was cached). [unknown] if no keys are known (ie, nothing is or was cached).
@@ -474,26 +477,20 @@ Return cache keys for columns associated with this query. May return
/** /**
** Private interfaces below. ** Private interfaces below.
**/ **/
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type. _resolveCachedQueries(field: Field, queries: Query[]): LabelArray {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. return queries
_resolveCachedQueries(field, queries) { .map((query: Query) =>
return ( // @ts-expect-error --- TODO revisit:
queries // `filter`: This expression is not callable.
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'query' implicitly has an 'any' type. _whereCacheGet(this._whereCache, this.schema, field, query).filter(
.map((query) => (cacheKey?: LabelType) =>
_whereCacheGet(this._whereCache, this.schema, field, query).filter( cacheKey !== undefined && this._cache[field].hasCol(cacheKey)
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'cacheKey' implicitly has an 'any' type.
(cacheKey) =>
cacheKey !== undefined && this._cache[field].hasCol(cacheKey)
)
) )
.flat() )
); .flat();
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type. async _fetch(field: Field, q: Query | Query[]): Promise<Dataframe> {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
async _fetch(field, q): Dataframe {
if (!AnnoMatrix.fields().includes(field)) return Dataframe.empty(); 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);
@@ -505,8 +502,7 @@ Return cache keys for columns associated with this query. May return
/* find any query not already cached */ /* find any query not already cached */
const uncachedQueries = queries.filter((query) => const uncachedQueries = queries.filter((query) =>
_whereCacheGet(this._whereCache, this.schema, field, query).some( _whereCacheGet(this._whereCache, this.schema, field, query).some(
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'cacheKey' implicitly has an 'any' type. (cacheKey?: LabelType) =>
(cacheKey) =>
cacheKey === undefined || !this._cache[field].hasCol(cacheKey) cacheKey === undefined || !this._cache[field].hasCol(cacheKey)
) )
); );
@@ -515,17 +511,19 @@ Return cache keys for columns associated with this query. May return
if (uncachedQueries.length > 0) { if (uncachedQueries.length > 0) {
await Promise.all( await Promise.all(
uncachedQueries.map((query) => uncachedQueries.map((query) =>
// @ts-expect-error ts-migrate(7006) FIXME: Parameter '_field' implicitly has an 'any' type. this._getPendingLoad(
this._getPendingLoad(field, query, async (_field, _query) => { field,
/* fetch, then index. _doLoad is subclass interface */ query,
// @ts-expect-error ts-migrate(2488) FIXME: Type 'void' must have a '[Symbol.iterator]()' meth... Remove this comment to see the full error message async (_field: Field, _query: Query): Promise<void> => {
const [whereCacheUpdate, df] = await this._doLoad(_field, _query); /* fetch, then index. _doLoad is subclass interface */
this._cache[_field] = this._cache[_field].withColsFrom(df); const [whereCacheUpdate, df] = await this._doLoad(_field, _query);
this._whereCache = _whereCacheMerge( this._cache[_field] = this._cache[_field].withColsFrom(df);
this._whereCache, this._whereCache = _whereCacheMerge(
whereCacheUpdate this._whereCache,
); whereCacheUpdate
}) );
}
)
) )
); );
} }
@@ -539,9 +537,11 @@ Return cache keys for columns associated with this query. May return
return response; return response;
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type. async _getPendingLoad(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. field: Field,
async _getPendingLoad(field, query, fetchFn) { query: Query,
fetchFn: (_field: Field, _query: Query) => Promise<void>
): Promise<void> {
/* /*
Given a query on a field, ensure that we only have a single outstanding Given a query on a field, ensure that we only have a single outstanding
fetch at any given time. If multiple requests occur while a fetch is fetch at any given time. If multiple requests occur while a fetch is
@@ -562,9 +562,22 @@ Return cache keys for columns associated with this query. May return
return this._pendingLoad[field][key]; return this._pendingLoad[field][key];
} }
// eslint-disable-next-line class-methods-use-this, @typescript-eslint/explicit-module-boundary-types -- make sure subclass implements abstract _doLoad(
async _doLoad() { field: Field,
_subclassResponsibility(); query: Query
): Promise<[WhereCache | null, Dataframe]>;
/**
* Determines viewOf for this annoMatrix.
*
* @internal
* @returns - parent annoMatrix if this annoMatrix is a view, otherwise this annoMatrix if it's not a view.
*/
_getViewOf(): AnnoMatrix {
if (this.isView) {
return this.viewOf;
}
return this;
} }
/** /**
@@ -596,23 +609,21 @@ Return cache keys for columns associated with this query. May return
To be effective, the GC callback needs to be invoked from the undo/redo code, To be effective, the GC callback needs to be invoked from the undo/redo code,
as much of the cache is pinned by that data structure. as much of the cache is pinned by that data structure.
*/ */
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type. _gcField(field: Field, isHot: boolean, pinnedColumns: LabelArray): void {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
_gcField(field, isHot, pinnedColumns) {
const maxColumns = isHot ? 256 : 10; const maxColumns = isHot ? 256 : 10;
const cache = this._cache[field]; const cache = this._cache[field];
if (cache.colIndex.size() < maxColumns) return; // trivial rejection if (cache.colIndex.size() < maxColumns) return; // trivial rejection
const candidates = cache.colIndex const candidates = cache.colIndex
.labels() .labels()
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'col' implicitly has an 'any' type. // @ts-expect-error --- TODO revisit:
.filter((col) => !pinnedColumns.includes(col)); // `col`: Argument of type 'LabelType' is not assignable to parameter of type 'number'. Type 'string' is not assignable to type 'number'.
.filter((col: LabelType) => !pinnedColumns.includes(col));
const excessCount = candidates.length + pinnedColumns.length - maxColumns; const excessCount = candidates.length + pinnedColumns.length - maxColumns;
if (excessCount > 0) { if (excessCount > 0) {
const { _gcInfo } = this; const { _gcInfo } = this;
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'a' implicitly has an 'any' type. candidates.sort((a: LabelType, b: LabelType) => {
candidates.sort((a, b) => {
let atime = _gcInfo.get(_columnCacheKey(field, a)); let atime = _gcInfo.get(_columnCacheKey(field, a));
if (atime === undefined) atime = 0; if (atime === undefined) atime = 0;
@@ -629,49 +640,49 @@ Return cache keys for columns associated with this query. May return
// ", " // ", "
// )}]` // )}]`
// ); // );
// @ts-expect-error --- TODO revisit:
// `reduce`: This expression is not callable.
this._cache[field] = toDrop.reduce( this._cache[field] = toDrop.reduce(
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'df' implicitly has an 'any' type. (df: Dataframe, col: LabelType) => df.dropCol(col),
(df, col) => df.dropCol(col),
this._cache[field] this._cache[field]
); );
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'col' implicitly has an 'any' type. toDrop.forEach((col: LabelType) =>
toDrop.forEach((col) => _gcInfo.delete(_columnCacheKey(field, col))); _gcInfo.delete(_columnCacheKey(field, col))
);
} }
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type. _gcFetchCleanup(field: Field, pinnedColumns: LabelArray): void {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
_gcFetchCleanup(field, pinnedColumns) {
/* /*
Called during data load/fetch. By definition, this is 'hot', so we Called during data load/fetch. By definition, this is 'hot', so we
only want to gc X. only want to gc X.
*/ */
if (field === "X") { if (field === Field.X) {
this._gcField( this._gcField(
field, field,
true, true,
// @ts-expect-error --- TODO revisit:
// Property 'concat' does not exist on type 'LabelArray'.
pinnedColumns.concat(_getWritableColumns(this.schema, field)) pinnedColumns.concat(_getWritableColumns(this.schema, field))
); );
} }
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'hints' implicitly has an 'any' type. _gc(hints: GCHints): void {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
_gc(hints) {
/* /*
Called from middleware, or elsewhere. isHot is true if we are in the active store, Called from middleware, or elsewhere. isHot is true if we are in the active store,
or false if we are in some other context (eg, history state). or false if we are in some other context (eg, history state).
*/ */
const { isHot } = hints; const { isHot } = hints;
const candidateFields = isHot ? ["X"] : ["X", "emb", "var", "obs"]; const candidateFields = isHot
? [Field.X]
: [Field.X, Field.emb, Field.var, Field.obs];
candidateFields.forEach((field) => candidateFields.forEach((field) =>
this._gcField(field, isHot, _getWritableColumns(this.schema, field)) this._gcField(field, isHot, _getWritableColumns(this.schema, field))
); );
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type. _gcUpdateStats(field: Field, dataframe: Dataframe): void {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
_gcUpdateStats(field, dataframe) {
/* /*
called each time a query is performed, allowing the gc to update any bookkeeping called each time a query is performed, allowing the gc to update any bookkeeping
information. Currently, this is just a simple last-fetched timestamp, stored information. Currently, this is just a simple last-fetched timestamp, stored
@@ -680,8 +691,7 @@ Return cache keys for columns associated with this query. May return
const cols = dataframe.colIndex.labels(); const cols = dataframe.colIndex.labels();
const { _gcInfo } = this; const { _gcInfo } = this;
const now = Date.now(); const now = Date.now();
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'c' implicitly has an 'any' type. cols.forEach((c: LabelType) => {
cols.forEach((c) => {
_gcInfo.set(_columnCacheKey(field, c), now); _gcInfo.set(_columnCacheKey(field, c), now);
}); });
} }
@@ -698,9 +708,7 @@ Return cache keys for columns associated with this query. May return
Do not override _clone(); Do not override _clone();
**/ **/
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'clone' implicitly has an 'any' type. _cloneDeeper(clone: AnnoMatrix): AnnoMatrix {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
_cloneDeeper(clone) {
clone._cache = _shallowClone(this._cache); clone._cache = _shallowClone(this._cache);
clone._gcInfo = new Map(); clone._gcInfo = new Map();
clone._pendingLoad = { clone._pendingLoad = {
@@ -712,8 +720,7 @@ Return cache keys for columns associated with this query. May return
return clone; return clone;
} }
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. _clone(): AnnoMatrix {
_clone() {
const clone = _shallowClone(this); const clone = _shallowClone(this);
this._cloneDeeper(clone); this._cloneDeeper(clone);
Object.seal(clone); Object.seal(clone);
@@ -724,12 +731,6 @@ Return cache keys for columns associated with this query. May return
/* /*
private utility functions below private utility functions below
*/ */
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type. function _columnCacheKey(field: Field, column: LabelType): string {
function _columnCacheKey(field, column) {
return `${field}/${column}`; return `${field}/${column}`;
} }
function _subclassResponsibility() {
/* protect against bugs in subclass */
throw new Error("subclass failed to implement required method");
}
+2 -2
View File
@@ -1,7 +1,7 @@
/* /*
Shallow clone an object, correctly handling prototype Shallow clone an object, correctly handling prototype
*/ */
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
export default function _shallowClone(orig: any) { export default function _shallowClone<T>(orig: T): T {
return Object.assign(Object.create(Object.getPrototypeOf(orig)), orig); return Object.assign(Object.create(Object.getPrototypeOf(orig)), orig);
} }
+146 -168
View File
@@ -9,38 +9,58 @@ AnnoMatrix stay in sync:
*/ */
import Crossfilter from "../util/typedCrossfilter"; import Crossfilter from "../util/typedCrossfilter";
import { _getColumnSchema } from "./schema"; import { _getColumnSchema } from "./schema";
import {
AnnotationColumnSchema,
Field,
EmbeddingSchema,
} from "../common/types/schema";
import AnnoMatrix from "./annoMatrix";
import {
Dataframe,
DataframeValue,
DataframeValueArray,
LabelType,
} from "../util/dataframe";
import { Query } from "./query";
import { TypedArray } from "../common/types/arraytypes";
import { LabelArray } from "../util/dataframe/types";
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type. type ObsDimensionParams =
function _dimensionNameFromDf(field, df) { | [string, DataframeValueArray, DataframeValueArray]
| [string, DataframeValueArray]
| [string, DataframeValueArray, Int32ArrayConstructor]
| [string, DataframeValueArray, Float32ArrayConstructor];
function _dimensionNameFromDf(field: Field, df: Dataframe): string {
const colNames = df.colIndex.labels(); const colNames = df.colIndex.labels();
return _dimensionName(field, colNames); return _dimensionName(field, colNames);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type. function _dimensionName(
function _dimensionName(field, colNames) { field: Field,
colNames: LabelType | LabelArray
): string {
if (!Array.isArray(colNames)) return `${field}/${colNames}`; if (!Array.isArray(colNames)) return `${field}/${colNames}`;
return `${field}/${colNames.join(":")}`; return `${field}/${colNames.join(":")}`;
} }
export default class AnnoMatrixObsCrossfilter { export default class AnnoMatrixObsCrossfilter {
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'annoMatrix' implicitly has an 'any' typ... Remove this comment to see the full error message annoMatrix: AnnoMatrix;
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
constructor(annoMatrix, _obsCrossfilter = null) { obsCrossfilter: Crossfilter;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(this as any).annoMatrix = annoMatrix; constructor(
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. annoMatrix: AnnoMatrix,
(this as any).obsCrossfilter = _obsCrossfilter: Crossfilter | null = null
) {
this.annoMatrix = annoMatrix;
this.obsCrossfilter =
_obsCrossfilter || new Crossfilter(annoMatrix._cache.obs); _obsCrossfilter || new Crossfilter(annoMatrix._cache.obs);
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. this.obsCrossfilter = this.obsCrossfilter.setData(annoMatrix._cache.obs);
(this as any).obsCrossfilter = (this as any).obsCrossfilter.setData(
annoMatrix._cache.obs
);
} }
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. size(): number {
size() { return this.obsCrossfilter.size();
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
return (this as any).obsCrossfilter.size();
} }
/** /**
@@ -50,44 +70,33 @@ export default class AnnoMatrixObsCrossfilter {
See API documentation in annoMatrix.js. See API documentation in annoMatrix.js.
**/ **/
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'colSchema' implicitly has an 'any' type... Remove this comment to see the full error message addObsColumn<T extends DataframeValueArray>(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. colSchema: AnnotationColumnSchema,
addObsColumn(colSchema, Ctor, value) { Ctor: new (n: number) => T,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. value: T
const annoMatrix = (this as any).annoMatrix.addObsColumn( ): AnnoMatrixObsCrossfilter {
colSchema, const annoMatrix = this.annoMatrix.addObsColumn(colSchema, Ctor, value);
Ctor, const obsCrossfilter = this.obsCrossfilter.setData(annoMatrix._cache.obs);
value
);
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const obsCrossfilter = (this as any).obsCrossfilter.setData(
annoMatrix._cache.obs
);
return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter); return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'col' implicitly has an 'any' type. dropObsColumn(col: LabelType): AnnoMatrixObsCrossfilter {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. const annoMatrix = this.annoMatrix.dropObsColumn(col);
dropObsColumn(col) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const annoMatrix = (this as any).annoMatrix.dropObsColumn(col);
// @ts-expect-error ts-migrate(2339) FIXME: Property 'obsCrossfilter' does not exist on type '... Remove this comment to see the full error message
let { obsCrossfilter } = this; let { obsCrossfilter } = this;
const dimName = _dimensionName("obs", col); const dimName = _dimensionName(Field.obs, col);
if (obsCrossfilter.hasDimension(dimName)) { if (obsCrossfilter.hasDimension(dimName)) {
obsCrossfilter = obsCrossfilter.delDimension(dimName); obsCrossfilter = obsCrossfilter.delDimension(dimName);
} }
return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter); return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'oldCol' implicitly has an 'any' type. renameObsColumn(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. oldCol: LabelType,
renameObsColumn(oldCol, newCol) { newCol: LabelType
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. ): AnnoMatrixObsCrossfilter {
const annoMatrix = (this as any).annoMatrix.renameObsColumn(oldCol, newCol); const annoMatrix = this.annoMatrix.renameObsColumn(oldCol, newCol);
const oldDimName = _dimensionName("obs", oldCol); const oldDimName = _dimensionName(Field.obs, oldCol);
const newDimName = _dimensionName("obs", newCol); const newDimName = _dimensionName(Field.obs, newCol);
// @ts-expect-error ts-migrate(2339) FIXME: Property 'obsCrossfilter' does not exist on type '... Remove this comment to see the full error message
let { obsCrossfilter } = this; let { obsCrossfilter } = this;
if (obsCrossfilter.hasDimension(oldDimName)) { if (obsCrossfilter.hasDimension(oldDimName)) {
obsCrossfilter = obsCrossfilter.renameDimension(oldDimName, newDimName); obsCrossfilter = obsCrossfilter.renameDimension(oldDimName, newDimName);
@@ -95,16 +104,12 @@ export default class AnnoMatrixObsCrossfilter {
return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter); return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'col' implicitly has an 'any' type. addObsAnnoCategory(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. col: LabelType,
addObsAnnoCategory(col, category) { category: string
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. ): AnnoMatrixObsCrossfilter {
const annoMatrix = (this as any).annoMatrix.addObsAnnoCategory( const annoMatrix = this.annoMatrix.addObsAnnoCategory(col, category);
col, const dimName = _dimensionName(Field.obs, col);
category
);
const dimName = _dimensionName("obs", col);
// @ts-expect-error ts-migrate(2339) FIXME: Property 'obsCrossfilter' does not exist on type '... Remove this comment to see the full error message
let { obsCrossfilter } = this; let { obsCrossfilter } = this;
if (obsCrossfilter.hasDimension(dimName)) { if (obsCrossfilter.hasDimension(dimName)) {
obsCrossfilter = obsCrossfilter.delDimension(dimName); obsCrossfilter = obsCrossfilter.delDimension(dimName);
@@ -112,17 +117,17 @@ export default class AnnoMatrixObsCrossfilter {
return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter); return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'col' implicitly has an 'any' type. async removeObsAnnoCategory(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. col: LabelType,
async removeObsAnnoCategory(col, category, unassignedCategory) { category: string,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. unassignedCategory: string
const annoMatrix = await (this as any).annoMatrix.removeObsAnnoCategory( ): Promise<AnnoMatrixObsCrossfilter> {
const annoMatrix = await this.annoMatrix.removeObsAnnoCategory(
col, col,
category, category,
unassignedCategory unassignedCategory
); );
const dimName = _dimensionName("obs", col); const dimName = _dimensionName(Field.obs, col);
// @ts-expect-error ts-migrate(2339) FIXME: Property 'obsCrossfilter' does not exist on type '... Remove this comment to see the full error message
let { obsCrossfilter } = this; let { obsCrossfilter } = this;
if (obsCrossfilter.hasDimension(dimName)) { if (obsCrossfilter.hasDimension(dimName)) {
obsCrossfilter = obsCrossfilter.delDimension(dimName); obsCrossfilter = obsCrossfilter.delDimension(dimName);
@@ -130,17 +135,17 @@ export default class AnnoMatrixObsCrossfilter {
return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter); return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'col' implicitly has an 'any' type. async setObsColumnValues(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. col: LabelType,
async setObsColumnValues(col, rowLabels, value) { rowLabels: Int32Array,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. value: DataframeValue
const annoMatrix = await (this as any).annoMatrix.setObsColumnValues( ): Promise<AnnoMatrixObsCrossfilter> {
const annoMatrix = await this.annoMatrix.setObsColumnValues(
col, col,
rowLabels, rowLabels,
value value
); );
const dimName = _dimensionName("obs", col); const dimName = _dimensionName(Field.obs, col);
// @ts-expect-error ts-migrate(2339) FIXME: Property 'obsCrossfilter' does not exist on type '... Remove this comment to see the full error message
let { obsCrossfilter } = this; let { obsCrossfilter } = this;
if (obsCrossfilter.hasDimension(dimName)) { if (obsCrossfilter.hasDimension(dimName)) {
obsCrossfilter = obsCrossfilter.delDimension(dimName); obsCrossfilter = obsCrossfilter.delDimension(dimName);
@@ -148,17 +153,17 @@ export default class AnnoMatrixObsCrossfilter {
return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter); return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'col' implicitly has an 'any' type. async resetObsColumnValues<T extends DataframeValue>(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. col: LabelType,
async resetObsColumnValues(col, oldValue, newValue) { oldValue: T,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. newValue: T
const annoMatrix = await (this as any).annoMatrix.resetObsColumnValues( ): Promise<AnnoMatrixObsCrossfilter> {
const annoMatrix = await this.annoMatrix.resetObsColumnValues(
col, col,
oldValue, oldValue,
newValue newValue
); );
const dimName = _dimensionName("obs", col); const dimName = _dimensionName(Field.obs, col);
// @ts-expect-error ts-migrate(2339) FIXME: Property 'obsCrossfilter' does not exist on type '... Remove this comment to see the full error message
let { obsCrossfilter } = this; let { obsCrossfilter } = this;
if (obsCrossfilter.hasDimension(dimName)) { if (obsCrossfilter.hasDimension(dimName)) {
obsCrossfilter = obsCrossfilter.delDimension(dimName); obsCrossfilter = obsCrossfilter.delDimension(dimName);
@@ -166,35 +171,25 @@ export default class AnnoMatrixObsCrossfilter {
return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter); return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'colSchema' implicitly has an 'any' type... Remove this comment to see the full error message addEmbedding(colSchema: EmbeddingSchema): AnnoMatrixObsCrossfilter {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. const annoMatrix = this.annoMatrix.addEmbedding(colSchema);
addEmbedding(colSchema) { return new AnnoMatrixObsCrossfilter(annoMatrix, this.obsCrossfilter);
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const annoMatrix = (this as any).annoMatrix.addEmbedding(colSchema);
return new AnnoMatrixObsCrossfilter(
annoMatrix,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(this as any).obsCrossfilter
);
} }
/** /**
* Drop the crossfilter dimension. Do not change the annoMatrix. Useful when we * Drop the crossfilter dimension. Do not change the annoMatrix. Useful when we
* want to stop trackin the selection state, but aren't sure we want to blow the * want to stop tracking the selection state, but aren't sure we want to blow the
* annomatrix cache. * annomatrix cache.
*/ */
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type. dropDimension(field: Field, query: Query): AnnoMatrixObsCrossfilter {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
dropDimension(field, query) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Anno... Remove this comment to see the full error message
const { annoMatrix } = this; const { annoMatrix } = this;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'obsCrossfilter' does not exist on type '... Remove this comment to see the full error message
let { obsCrossfilter } = this; let { obsCrossfilter } = this;
const keys = annoMatrix const keys = annoMatrix
.getCacheKeys(field, query) .getCacheKeys(field, query)
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'k' implicitly has an 'any' type. // @ts-expect-error ts-migrate --- suppressing TS defect (https://github.com/microsoft/TypeScript/issues/44373).
.filter((k) => k !== undefined); // Compiler is complaining that expression is not callable on array union types. Remove suppression once fixed.
const dimName = _dimensionName(field, keys); .filter((k?: string | number) => k !== undefined);
const dimName = _dimensionName(field, keys as string[]);
if (obsCrossfilter.hasDimension(dimName)) { if (obsCrossfilter.hasDimension(dimName)) {
obsCrossfilter = obsCrossfilter.delDimension(dimName); obsCrossfilter = obsCrossfilter.delDimension(dimName);
} }
@@ -206,12 +201,13 @@ export default class AnnoMatrixObsCrossfilter {
are just wrappers to lazy create indices. are just wrappers to lazy create indices.
**/ **/
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type. async select(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. field: Field,
async select(field, query, spec) { query: Query,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Anno... Remove this comment to see the full error message // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- TODO revisit: waiting for typings from util/typedCrossfilter
spec: any
): Promise<AnnoMatrixObsCrossfilter> {
const { annoMatrix } = this; const { annoMatrix } = this;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'obsCrossfilter' does not exist on type '... Remove this comment to see the full error message
let { obsCrossfilter } = this; let { obsCrossfilter } = this;
if (!annoMatrix?._cache?.[field]) { if (!annoMatrix?._cache?.[field]) {
@@ -223,7 +219,9 @@ export default class AnnoMatrixObsCrossfilter {
// grab the data, so we can grab the index. // grab the data, so we can grab the index.
const df = await annoMatrix.fetch(field, query); const df = await annoMatrix.fetch(field, query);
if (!df) {
throw new Error("Dataframe cannot be `undefined`");
}
const dimName = _dimensionNameFromDf(field, df); const dimName = _dimensionNameFromDf(field, df);
if (!obsCrossfilter.hasDimension(dimName)) { if (!obsCrossfilter.hasDimension(dimName)) {
// lazy index generation - add dimension when first used // lazy index generation - add dimension when first used
@@ -240,86 +238,66 @@ export default class AnnoMatrixObsCrossfilter {
return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter); return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter);
} }
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. selectAll(): AnnoMatrixObsCrossfilter {
selectAll() {
/* /*
Select all on any dimension in this field. Select all on any dimension in this field.
*/ */
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Anno... Remove this comment to see the full error message
const { annoMatrix } = this; const { annoMatrix } = this;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. const currentDims = this.obsCrossfilter.dimensionNames();
const currentDims = (this as any).obsCrossfilter.dimensionNames();
const obsCrossfilter = currentDims.reduce( const obsCrossfilter = currentDims.reduce(
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'xfltr' implicitly has an 'any' type.
(xfltr, dim) => xfltr.select(dim, { mode: "all" }), (xfltr, dim) => xfltr.select(dim, { mode: "all" }),
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. this.obsCrossfilter
(this as any).obsCrossfilter );
); // eslint-disable-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter); return new AnnoMatrixObsCrossfilter(annoMatrix, obsCrossfilter);
} }
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. countSelected(): number {
countSelected() {
/* if no data yet indexed in the crossfilter, just say everything is selected */ /* if no data yet indexed in the crossfilter, just say everything is selected */
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. if (this.obsCrossfilter.size() === 0) return this.annoMatrix.nObs;
if ((this as any).obsCrossfilter.size() === 0) return this.obsCrossfilter.countSelected();
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
return (this as any).annoMatrix.nObs;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
return (this as any).obsCrossfilter.countSelected();
} }
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. allSelectedMask(): Uint8Array {
allSelectedMask() {
/* if no data yet indexed in the crossfilter, just say everything is selected */ /* if no data yet indexed in the crossfilter, just say everything is selected */
if ( if (
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. this.obsCrossfilter.size() === 0 ||
(this as any).obsCrossfilter.size() === 0 || this.obsCrossfilter.dimensionNames().length === 0
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(this as any).obsCrossfilter.dimensionNames().length === 0
) { ) {
/* fake the mask */ /* fake the mask */
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. return new Uint8Array(this.annoMatrix.nObs).fill(1);
return new Uint8Array((this as any).annoMatrix.nObs).fill(1);
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. return this.obsCrossfilter.allSelectedMask();
return (this as any).obsCrossfilter.allSelectedMask();
} }
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. allSelectedLabels(): LabelArray {
allSelectedLabels() {
/* if no data yet indexed in the crossfilter, just say everything is selected */ /* if no data yet indexed in the crossfilter, just say everything is selected */
if ( if (
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. this.obsCrossfilter.size() === 0 ||
(this as any).obsCrossfilter.size() === 0 || this.obsCrossfilter.dimensionNames().length === 0
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(this as any).obsCrossfilter.dimensionNames().length === 0
) { ) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. return this.annoMatrix.rowIndex.labels();
return (this as any).annoMatrix.rowIndex.labels();
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. const mask = this.obsCrossfilter.allSelectedMask();
const mask = (this as any).obsCrossfilter.allSelectedMask(); const index = this.annoMatrix.rowIndex.isubsetMask(mask);
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const index = (this as any).annoMatrix.rowIndex.isubsetMask(mask);
return index.labels(); return index.labels();
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'array' implicitly has an 'any' type. fillByIsSelected<A extends TypedArray>(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. array: A,
fillByIsSelected(array, selectedValue, deselectedValue) { selectedValue: A[0],
deselectedValue: A[0]
): A {
/* if no data yet indexed in the crossfilter, just say everything is selected */ /* if no data yet indexed in the crossfilter, just say everything is selected */
if ( if (
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. this.obsCrossfilter.size() === 0 ||
(this as any).obsCrossfilter.size() === 0 || this.obsCrossfilter.dimensionNames().length === 0
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(this as any).obsCrossfilter.dimensionNames().length === 0
) { ) {
// @ts-expect-error ts-migrate --- TODO revisit:
// Type 'Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array' is not assignable to type 'A'...
return array.fill(selectedValue); return array.fill(selectedValue);
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. return this.obsCrossfilter.fillByIsSelected(
return (this as any).obsCrossfilter.fillByIsSelected(
array, array,
selectedValue, selectedValue,
deselectedValue deselectedValue
@@ -330,37 +308,35 @@ export default class AnnoMatrixObsCrossfilter {
** Private below ** Private below
**/ **/
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'annoMatrix' implicitly has an 'any' typ... Remove this comment to see the full error message _addObsCrossfilterDimension(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. annoMatrix: AnnoMatrix,
_addObsCrossfilterDimension(annoMatrix, obsCrossfilter, field, df) { obsCrossfilter: Crossfilter,
field: Field,
df: Dataframe
): Crossfilter {
if (field === "var") return obsCrossfilter; if (field === "var") return obsCrossfilter;
const dimName = _dimensionNameFromDf(field, df); const dimName = _dimensionNameFromDf(field, df);
const dimParams = this._getObsDimensionParams(field, df); const dimParams = this._getObsDimensionParams(field, df);
obsCrossfilter = obsCrossfilter.setData(annoMatrix._cache.obs); obsCrossfilter = obsCrossfilter.setData(annoMatrix._cache.obs);
// @ts-expect-error ts-migrate(2488) FIXME: Type 'any[] | undefined' must have a '[Symbol.iter... Remove this comment to see the full error message // @ts-expect-error ts-migrate --- TODO revisit:
// `...dimParams`: A spread argument must either have a tuple type or be passed to a rest parameter.
obsCrossfilter = obsCrossfilter.addDimension(dimName, ...dimParams); obsCrossfilter = obsCrossfilter.addDimension(dimName, ...dimParams);
return obsCrossfilter; return obsCrossfilter;
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type. _getColumnBaseType(field: Field, col: LabelType): string {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
_getColumnBaseType(field, col) {
/* Look up the primitive type for this field/col */ /* Look up the primitive type for this field/col */
const colSchema = _getColumnSchema( const colSchema = _getColumnSchema(this.annoMatrix.schema, field, col);
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(this as any).annoMatrix.schema,
field,
col
);
return colSchema.type; return colSchema.type;
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type. _getObsDimensionParams(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. field: Field,
_getObsDimensionParams(field, df) { df: Dataframe
): ObsDimensionParams | undefined {
/* return the crossfilter dimensiontype type and params for this field/dataframe */ /* return the crossfilter dimensiontype type and params for this field/dataframe */
if (field === "emb") { if (field === Field.emb) {
/* assumed to be 2D */ /* assumed to be 2D */
return ["spatial", df.icol(0).asArray(), df.icol(1).asArray()]; return ["spatial", df.icol(0).asArray(), df.icol(1).asArray()];
} }
@@ -368,6 +344,8 @@ export default class AnnoMatrixObsCrossfilter {
/* assumed to be 1D */ /* assumed to be 1D */
const col = df.icol(0); const col = df.icol(0);
const colName = df.colIndex.getLabel(0); const colName = df.colIndex.getLabel(0);
// @ts-expect-error --- TODO revisit:
// `colName` Argument of type 'LabelType | undefined' is not assignable to parameter of type 'LabelType'. Type 'undefined' is not assignable to type 'LabelType'.
const type = this._getColumnBaseType(field, colName); const type = this._getColumnBaseType(field, colName);
if (type === "string" || type === "categorical" || type === "boolean") { if (type === "string" || type === "categorical" || type === "boolean") {
return ["enum", col.asArray()]; return ["enum", col.asArray()];
+1 -2
View File
@@ -1,8 +1,7 @@
export { doBinaryRequest, doFetch } from "../util/actionHelpers"; export { doBinaryRequest, doFetch } from "../util/actionHelpers";
/* double URI encode - needed for query-param filters */ /* double URI encode - needed for query-param filters */
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. export function _dubEncURIComp(s: string | number | boolean): string {
export function _dubEncURIComp(s: any) {
return encodeURIComponent(encodeURIComponent(s)); return encodeURIComponent(encodeURIComponent(s));
} }
+138 -103
View File
@@ -2,33 +2,46 @@ import { doBinaryRequest, doFetch } from "./fetchHelpers";
import { matrixFBSToDataframe } from "../util/stateManager/matrix"; import { matrixFBSToDataframe } from "../util/stateManager/matrix";
import { _getColumnSchema } from "./schema"; import { _getColumnSchema } from "./schema";
import { import {
addObsAnnoColumn,
removeObsAnnoColumn,
addObsAnnoCategory, addObsAnnoCategory,
removeObsAnnoCategory, addObsAnnoColumn,
addObsLayout, addObsLayout,
removeObsAnnoCategory,
removeObsAnnoColumn,
} from "../util/stateManager/schemaHelpers"; } from "../util/stateManager/schemaHelpers";
import { isAnyArray } from "../common/types/arraytypes"; import { isAnyArray } from "../common/types/arraytypes";
import { _whereCacheCreate } from "./whereCache"; import { _whereCacheCreate, WhereCache } from "./whereCache";
import AnnoMatrix from "./annoMatrix"; import AnnoMatrix from "./annoMatrix";
import PromiseLimit from "../util/promiseLimit"; import PromiseLimit from "../util/promiseLimit";
import { import {
_expectSimpleQuery,
_expectComplexQuery, _expectComplexQuery,
_urlEncodeLabelQuery, _expectSimpleQuery,
_urlEncodeComplexQuery,
_hashStringValues, _hashStringValues,
_urlEncodeComplexQuery,
_urlEncodeLabelQuery,
ComplexQuery,
Query,
} from "./query"; } from "./query";
import { import {
normalizeResponse, normalizeResponse,
normalizeWritableCategoricalSchema, normalizeWritableCategoricalSchema,
} from "./normalize"; } from "./normalize";
import {
AnnotationColumnSchema,
Field,
EmbeddingSchema,
RawSchema,
} from "../common/types/schema";
import {
Dataframe,
DataframeValue,
DataframeValueArray,
LabelType,
} from "../util/dataframe";
const promiseThrottle = new PromiseLimit(5); const promiseThrottle = new PromiseLimit(5);
export default class AnnoMatrixLoader extends AnnoMatrix { export default class AnnoMatrixLoader extends AnnoMatrix {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. baseURL: string;
baseURL: any;
/* /*
AnnoMatrix implementation which proxies to HTTP server using the CXG REST API. AnnoMatrix implementation which proxies to HTTP server using the CXG REST API.
@@ -40,8 +53,7 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
new AnnoMatrixLoader(serverBaseURL, schema) -> instance new AnnoMatrixLoader(serverBaseURL, schema) -> instance
*/ */
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. constructor(baseURL: string, schema: RawSchema) {
constructor(baseURL: any, schema: any) {
const { nObs, nVar } = schema.dataframe; const { nObs, nVar } = schema.dataframe;
super(schema, nObs, nVar); super(schema, nObs, nVar);
@@ -56,33 +68,36 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
/** /**
** Public. API described in base class. ** Public. API described in base class.
**/ **/
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. addObsAnnoCategory(col: LabelType, category: string): AnnoMatrix {
addObsAnnoCategory(col: any, category: any) {
/* /*
Add a new category (aka label) to the schema for an obs column. Add a new category (aka label) to the schema for an obs column.
*/ */
const colSchema = _getColumnSchema(this.schema, "obs", col); const colSchema = _getColumnSchema(
_writableCategoryTypeCheck(colSchema); // throws on error this.schema,
Field.obs,
col
) as AnnotationColumnSchema;
_writableObsCategoryTypeCheck(colSchema); // throws on error
const newAnnoMatrix = this._clone(); const newAnnoMatrix = this._clone();
newAnnoMatrix.schema = addObsAnnoCategory(this.schema, col, category); newAnnoMatrix.schema = addObsAnnoCategory(this.schema, col, category);
return newAnnoMatrix; return newAnnoMatrix;
} }
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
async removeObsAnnoCategory( async removeObsAnnoCategory(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. col: LabelType,
col: any, category: string,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. unassignedCategory: string
category: any, ): Promise<AnnoMatrix> {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
unassignedCategory: any
) {
/* /*
Remove a single "category" (aka "label") from the data & schema of an obs column. Remove a single "category" (aka "label") from the data & schema of an obs column.
*/ */
const colSchema = _getColumnSchema(this.schema, "obs", col); const colSchema = _getColumnSchema(
_writableCategoryTypeCheck(colSchema); // throws on error this.schema,
Field.obs,
col
) as AnnotationColumnSchema;
_writableObsCategoryTypeCheck(colSchema); // throws on error
const newAnnoMatrix = await this.resetObsColumnValues( const newAnnoMatrix = await this.resetObsColumnValues(
col, col,
@@ -97,24 +112,28 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
return newAnnoMatrix; return newAnnoMatrix;
} }
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. dropObsColumn(col: LabelType): AnnoMatrix {
dropObsColumn(col: any) {
/* /*
drop column from field drop column from field
*/ */
const colSchema = _getColumnSchema(this.schema, "obs", col); const colSchema = _getColumnSchema(
_writableCheck(colSchema); // throws on error this.schema,
Field.obs,
col
) as AnnotationColumnSchema;
_writableObsCheck(colSchema); // throws on error
const newAnnoMatrix = this._clone(); const newAnnoMatrix = this._clone();
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. newAnnoMatrix._cache.obs = this._cache.obs.dropCol(col);
newAnnoMatrix._cache.obs = (this as any)._cache.obs.dropCol(col);
newAnnoMatrix.schema = removeObsAnnoColumn(this.schema, col); newAnnoMatrix.schema = removeObsAnnoColumn(this.schema, col);
return newAnnoMatrix; return newAnnoMatrix;
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'colSchema' implicitly has an 'any' type... Remove this comment to see the full error message addObsColumn<T extends DataframeValueArray>(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. colSchema: AnnotationColumnSchema,
addObsColumn(colSchema, Ctor, value) { Ctor: new (n: number) => T,
value: T
): AnnoMatrix {
/* /*
add a column to field, initializing with value. Value may add a column to field, initializing with value. Value may
be one of: be one of:
@@ -125,9 +144,8 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
colSchema.writable = true; colSchema.writable = true;
const colName = colSchema.name; const colName = colSchema.name;
if ( if (
_getColumnSchema(this.schema, "obs", colName) || _getColumnSchema(this.schema, Field.obs, colName) ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. this._cache.obs.hasCol(colName)
(this as any)._cache.obs.hasCol(colName)
) { ) {
throw new Error("column already exists"); throw new Error("column already exists");
} }
@@ -143,8 +161,7 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
} else { } else {
data = new Ctor(this.nObs).fill(value); data = new Ctor(this.nObs).fill(value);
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. newAnnoMatrix._cache.obs = this._cache.obs.withCol(colName, data);
newAnnoMatrix._cache.obs = (this as any)._cache.obs.withCol(colName, data);
normalizeWritableCategoricalSchema( normalizeWritableCategoricalSchema(
colSchema, colSchema,
newAnnoMatrix._cache.obs.col(colName) newAnnoMatrix._cache.obs.col(colName)
@@ -153,47 +170,55 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
return newAnnoMatrix; return newAnnoMatrix;
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'oldCol' implicitly has an 'any' type. renameObsColumn(oldCol: LabelType, newCol: LabelType): AnnoMatrix {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
renameObsColumn(oldCol, newCol) {
/* /*
Rename the obs oldColName to newColName. oldCol must be writable. Rename the obs oldColName to newColName. oldCol must be writable.
*/ */
const oldColSchema = _getColumnSchema(this.schema, "obs", oldCol); const oldColSchema = _getColumnSchema(
_writableCheck(oldColSchema); this.schema,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. Field.obs,
const value = (this as any)._cache.obs.hasCol(oldCol) oldCol
? // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. ) as AnnotationColumnSchema;
(this as any)._cache.obs.col(oldCol).asArray() _writableObsCheck(oldColSchema);
const value = this._cache.obs.hasCol(oldCol)
? this._cache.obs.col(oldCol).asArray()
: undefined; : undefined;
return this.dropObsColumn(oldCol).addObsColumn( return this.dropObsColumn(oldCol).addObsColumn(
{ {
...oldColSchema, ...oldColSchema,
// @ts-expect-error ts-migrate --- TODO revisit:
// `name`: Type 'LabelType' is not assignable to type 'string'. Type 'number' is not assignable to type 'string'.
name: newCol, name: newCol,
}, },
// @ts-expect-error ts-migrate --- TODO revisit:
// `value`: Object is possibly 'undefined'.
value.constructor, value.constructor,
value value
); );
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'col' implicitly has an 'any' type. async setObsColumnValues(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. col: LabelType,
async setObsColumnValues(col, rowLabels, value) { rowLabels: Int32Array,
value: DataframeValue
): Promise<AnnoMatrix> {
/* /*
Set all rows identified by rowLabels to value. Set all rows identified by rowLabels to value.
*/ */
const colSchema = _getColumnSchema(this.schema, "obs", col); const colSchema = _getColumnSchema(
_writableCategoryTypeCheck(colSchema); // throws on error this.schema,
Field.obs,
col
) as AnnotationColumnSchema;
_writableObsCategoryTypeCheck(colSchema); // throws on error
// ensure that we have the data in cache before we manipulate it // ensure that we have the data in cache before we manipulate it
await this.fetch("obs", col); await this.fetch(Field.obs, col);
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. if (!this._cache.obs.hasCol(col))
if (!(this as any)._cache.obs.hasCol(col))
throw new Error("Internal error - user annotation data missing"); throw new Error("Internal error - user annotation data missing");
const rowIndices = this.rowIndex.getOffsets(rowLabels); const rowIndices = this.rowIndex.getOffsets(rowLabels);
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. const data = this._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 === -1) throw new Error("Unknown row label"); if (idx === -1) throw new Error("Unknown row label");
@@ -201,11 +226,7 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
} }
const newAnnoMatrix = this._clone(); const newAnnoMatrix = this._clone();
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. newAnnoMatrix._cache.obs = this._cache.obs.replaceColData(col, data);
newAnnoMatrix._cache.obs = (this as any)._cache.obs.replaceColData(
col,
data
);
const { categories } = colSchema; const { categories } = colSchema;
if (!categories?.includes(value)) { if (!categories?.includes(value)) {
newAnnoMatrix.schema = addObsAnnoCategory(this.schema, col, value); newAnnoMatrix.schema = addObsAnnoCategory(this.schema, col, value);
@@ -213,37 +234,39 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
return newAnnoMatrix; return newAnnoMatrix;
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'col' implicitly has an 'any' type. async resetObsColumnValues<T extends DataframeValue>(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. col: LabelType,
async resetObsColumnValues(col, oldValue, newValue) { oldValue: T,
newValue: T
): Promise<AnnoMatrix> {
/* /*
Set all rows with value 'oldValue' to 'newValue'. Set all rows with value 'oldValue' to 'newValue'.
*/ */
const colSchema = _getColumnSchema(this.schema, "obs", col); const colSchema = _getColumnSchema(
_writableCategoryTypeCheck(colSchema); // throws on error this.schema,
Field.obs,
col
) as AnnotationColumnSchema;
_writableObsCategoryTypeCheck(colSchema); // throws on error
// @ts-expect-error ts-migrate --- TODO revisit:
// `colSchema.categories`: Object is possibly 'undefined'.
if (!colSchema.categories.includes(oldValue)) { if (!colSchema.categories.includes(oldValue)) {
throw new Error("unknown category"); throw new Error("unknown category");
} }
// ensure that we have the data in cache before we manipulate it // ensure that we have the data in cache before we manipulate it
await this.fetch("obs", col); await this.fetch(Field.obs, col);
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. if (!this._cache.obs.hasCol(col))
if (!(this as any)._cache.obs.hasCol(col))
throw new Error("Internal error - user annotation data missing"); throw new Error("Internal error - user annotation data missing");
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. const data = this._cache.obs.col(col).asArray().slice();
const data = (this as any)._cache.obs.col(col).asArray().slice();
for (let i = 0, l = data.length; i < l; i += 1) { for (let i = 0, l = data.length; i < l; i += 1) {
if (data[i] === oldValue) data[i] = newValue; if (data[i] === oldValue) data[i] = newValue;
} }
const newAnnoMatrix = this._clone(); const newAnnoMatrix = this._clone();
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. newAnnoMatrix._cache.obs = this._cache.obs.replaceColData(col, data);
newAnnoMatrix._cache.obs = (this as any)._cache.obs.replaceColData(
col,
data
);
const { categories } = colSchema; const { categories } = colSchema;
if (!categories?.includes(newValue)) { if (!categories?.includes(newValue)) {
newAnnoMatrix.schema = addObsAnnoCategory(this.schema, col, newValue); newAnnoMatrix.schema = addObsAnnoCategory(this.schema, col, newValue);
@@ -251,14 +274,12 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
return newAnnoMatrix; return newAnnoMatrix;
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'colSchema' implicitly has an 'any' type... Remove this comment to see the full error message addEmbedding(colSchema: EmbeddingSchema): AnnoMatrix {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
addEmbedding(colSchema) {
/* /*
add new layout to the obs embeddings add new layout to the obs embeddings
*/ */
const { name: colName } = colSchema; const { name: colName } = colSchema;
if (_getColumnSchema(this.schema, "emb", colName)) { if (_getColumnSchema(this.schema, Field.emb, colName)) {
throw new Error("column already exists"); throw new Error("column already exists");
} }
@@ -270,9 +291,10 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
/** /**
** Private below ** Private below
**/ **/
// @ts-expect-error ts-migrate(2416) FIXME: Property '_doLoad' in type 'AnnoMatrixLoader' is n... Remove this comment to see the full error message async _doLoad(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. field: Field,
async _doLoad(field, query) { query: Query
): Promise<[WhereCache | null, Dataframe]> {
/* /*
_doLoad - evaluates the query against the field. Returns: _doLoad - evaluates the query against the field. Returns:
* whereCache update: column query map mapping the query to the column labels * whereCache update: column query map mapping the query to the column labels
@@ -300,7 +322,8 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
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 // @ts-expect-error --- TODO revisit:
// `buffer`: Argument of type 'unknown' is not assignable to parameter of type 'ArrayBuffer | ArrayBuffer[]'. Type 'unknown' is not assignable to type 'ArrayBuffer[]'.
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");
@@ -320,23 +343,26 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
Utility functions below Utility functions below
*/ */
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'colSchema' implicitly has an 'any' type... Remove this comment to see the full error message function _writableObsCheck(obsColSchema: AnnotationColumnSchema): void {
function _writableCheck(colSchema) { if (!obsColSchema?.writable) {
if (!colSchema?.writable) {
throw new Error("Unknown or readonly obs column"); throw new Error("Unknown or readonly obs column");
} }
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'colSchema' implicitly has an 'any' type... Remove this comment to see the full error message function _writableObsCategoryTypeCheck(
function _writableCategoryTypeCheck(colSchema) { obsColSchema: AnnotationColumnSchema
_writableCheck(colSchema); ): void {
if (colSchema.type !== "categorical") { _writableObsCheck(obsColSchema);
if (obsColSchema.type !== "categorical") {
throw new Error("column must be categorical"); throw new Error("column must be categorical");
} }
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'baseURL' implicitly has an 'any' type. function _embLoader(
function _embLoader(baseURL, _field, query) { baseURL: string,
_field: Field,
query: Query
): () => Promise<ArrayBuffer> {
_expectSimpleQuery(query); _expectSimpleQuery(query);
const urlBase = `${baseURL}layout/obs`; const urlBase = `${baseURL}layout/obs`;
@@ -345,8 +371,11 @@ function _embLoader(baseURL, _field, query) {
return () => doBinaryRequest(url); return () => doBinaryRequest(url);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'baseURL' implicitly has an 'any' type. function _obsOrVarLoader(
function _obsOrVarLoader(baseURL, field, query) { baseURL: string,
field: Field,
query: Query
): () => Promise<ArrayBuffer> {
_expectSimpleQuery(query); _expectSimpleQuery(query);
const urlBase = `${baseURL}annotations/${field}`; const urlBase = `${baseURL}annotations/${field}`;
@@ -355,20 +384,26 @@ function _obsOrVarLoader(baseURL, field, query) {
return () => doBinaryRequest(url); return () => doBinaryRequest(url);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'baseURL' implicitly has an 'any' type. function _XLoader(
function _XLoader(baseURL, field, query) { baseURL: string,
_field: Field,
query: Query
): () => Promise<ArrayBuffer> {
_expectComplexQuery(query); _expectComplexQuery(query);
if (query.where) { // Casting here as query is validated to be complex in _expectComplexQuery above.
const complexQuery = query as ComplexQuery;
if ("where" in complexQuery) {
const urlBase = `${baseURL}data/var`; const urlBase = `${baseURL}data/var`;
const urlQuery = _urlEncodeComplexQuery(query); const urlQuery = _urlEncodeComplexQuery(complexQuery);
const url = `${urlBase}?${urlQuery}`; const url = `${urlBase}?${urlQuery}`;
return () => doBinaryRequest(url); return () => doBinaryRequest(url);
} }
if (query.summarize) { if ("summarize" in complexQuery) {
const urlBase = `${baseURL}summarize/var`; const urlBase = `${baseURL}summarize/var`;
const urlQuery = _urlEncodeComplexQuery(query); const urlQuery = _urlEncodeComplexQuery(complexQuery);
if (urlBase.length + urlQuery.length < 2000) { if (urlBase.length + urlQuery.length < 2000) {
const url = `${urlBase}?${urlQuery}`; const url = `${urlBase}?${urlQuery}`;
+28 -21
View File
@@ -11,17 +11,24 @@ Undoable metareducer and the AnnoMatrix private API. It would be helpful
to make the Undoable interface better factored. to make the Undoable interface better factored.
*/ */
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. import { Action, Dispatch, MiddlewareAPI } from "redux";
const annoMatrixGC = (store: any) => (next: any) => (action: any) => { import AnnoMatrix from "./annoMatrix";
if (_itIsTimeForGC()) { import { GCHints } from "../common/types/entities";
_doGC(store);
} const annoMatrixGC =
return next(action); (store: MiddlewareAPI) =>
}; // GC middleware doesn't add any extra types to dispatch; it just executes GC and continues.
(next: Dispatch) =>
(action: Action): Action => {
if (_itIsTimeForGC()) {
_doGC(store);
}
return next(action);
};
let lastGCTime = 0; let lastGCTime = 0;
const InterGCDelayMS = 30 * 1000; // 30 seconds const InterGCDelayMS = 30 * 1000; // 30 seconds
function _itIsTimeForGC() { function _itIsTimeForGC(): boolean {
/* /*
we don't want to run GC on every dispatch, so throttle it a bit. we don't want to run GC on every dispatch, so throttle it a bit.
@@ -35,20 +42,22 @@ function _itIsTimeForGC() {
return false; return false;
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. function _doGC(store: MiddlewareAPI): void {
function _doGC(store: any) {
const state = store.getState(); const state = store.getState();
// these should probably be a function imported from undoable.js, etc, as // these should probably be a function imported from undoable.js, etc, as
// they have overly intimiate knowledge of our reducers. // they have overly intimate knowledge of our reducers.
const undoablePast = state["@@undoable/past"]; const undoablePast = state["@@undoable/past"];
const undoableFuture = state["@@undoable/future"]; const undoableFuture = state["@@undoable/future"];
const undoableStack = undoablePast const undoableStack = undoablePast
.concat(undoableFuture) .concat(undoableFuture)
// 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 --- TODO revisit: waiting for typings from /reducers
.flatMap((snapshot: any) => .flatMap((snapshot: any) =>
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. snapshot
snapshot.filter((v: any) => v[0] === "annoMatrix").map((v: any) => v[1]) // eslint-disable-next-line @typescript-eslint/no-explicit-any --- TODO revisit: waiting for typings from /reducers
.filter((v: any) => v[0] === "annoMatrix")
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- TODO revisit: waiting for typings from /reducers
.map((v: any) => v[1])
); );
const currentAnnoMatrix = state.annoMatrix; const currentAnnoMatrix = state.annoMatrix;
@@ -56,18 +65,16 @@ function _doGC(store: any) {
We want to identify those matrixes currently "hot", ie, linked from the current annoMatrix, We want to identify those matrixes currently "hot", ie, linked from the current annoMatrix,
as our current gc algo is more aggressive with those not hot. as our current gc algo is more aggressive with those not hot.
*/ */
const allAnnoMatrices = new Map( const allAnnoMatrices = new Map<AnnoMatrix, GCHints>(
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. undoableStack.map((m: AnnoMatrix) => [m, { isHot: false }])
undoableStack.map((m: any) => [m, { isHot: false }])
); );
let am = currentAnnoMatrix; let am = currentAnnoMatrix;
while (am) { while (am?.isView) {
allAnnoMatrices.set(am, { isHot: true }); allAnnoMatrices.set(am, { isHot: true });
am = am.viewOf; am = am.viewOf;
} }
allAnnoMatrices.forEach((hints, annoMatrix) => allAnnoMatrices.forEach((hints, annoMatrix: AnnoMatrix) =>
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. annoMatrix._gc(hints)
(annoMatrix as any)._gc(hints)
); );
} }
+16 -9
View File
@@ -1,4 +1,3 @@
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 {
@@ -7,9 +6,15 @@ import {
globalConfig, globalConfig,
} from "../globals"; } from "../globals";
import { Dataframe, LabelType, DataframeColumn } from "../util/dataframe"; import { Dataframe, LabelType, DataframeColumn } from "../util/dataframe";
import {
AnnotationColumnSchema,
ArraySchema,
Field,
Schema,
} from "../common/types/schema";
export function normalizeResponse( export function normalizeResponse(
field: string, field: Field,
schema: Schema, schema: Schema,
response: Dataframe response: Dataframe
): Dataframe { ): Dataframe {
@@ -37,11 +42,15 @@ export function normalizeResponse(
*/ */
// currently no data or schema normalization necessary for X or emb // currently no data or schema normalization necessary for X or emb
if (field !== "obs" && field !== "var") return response; if (field !== Field.obs && field !== Field.var) return response;
const colLabels = response.colIndex.labels(); const colLabels = response.colIndex.labels();
for (const colLabel of colLabels) { for (const colLabel of colLabels) {
const colSchema = _getColumnSchema(schema, field, colLabel); const colSchema = _getColumnSchema(
schema,
field,
colLabel
) as AnnotationColumnSchema;
const isIndex = _isIndex(schema, field, colLabel); const isIndex = _isIndex(schema, field, colLabel);
const { type, writable } = colSchema; const { type, writable } = colSchema;
@@ -73,11 +82,10 @@ function castColumnToBoolean(df: Dataframe, label: LabelType): Dataframe {
return df; return df;
} }
// 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( 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. colSchema: AnnotationColumnSchema, // eslint-disable-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
col: DataframeColumn col: DataframeColumn
) { ): ArraySchema {
/* /*
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
@@ -96,7 +104,7 @@ export function normalizeWritableCategoricalSchema(
export function normalizeCategorical( export function normalizeCategorical(
df: Dataframe, df: Dataframe,
colLabel: LabelType, 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: AnnotationColumnSchema
): Dataframe { ): 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
@@ -106,7 +114,6 @@ export function normalizeCategorical(
*/ */
const { writable } = colSchema; const { writable } = colSchema;
const col = df.col(colLabel); const col = df.col(colLabel);
if (writable) { if (writable) {
// writable (aka user) annotations // writable (aka user) annotations
normalizeWritableCategoricalSchema(colSchema, col); normalizeWritableCategoricalSchema(colSchema, col);
+52 -35
View File
@@ -1,22 +1,52 @@
import sha1 from "sha1"; import sha1 from "sha1";
import { _dubEncURIComp } from "./fetchHelpers"; import { _dubEncURIComp } from "./fetchHelpers";
import { Field } from "../common/types/schema";
import { LabelType } from "../util/dataframe";
/** /**
* Query utilities, mostly for debugging support and validation. * Query utilities, mostly for debugging support and validation.
*/ */
export type ComplexQuery = SummarizeQuery | WhereQuery;
export type Query = LabelType | ComplexQuery;
interface SummarizeQuery {
summarize: SummarizeQueryTerm;
}
interface SummarizeQueryTerm {
column: string;
field: string;
method: string;
values: string[];
}
interface WhereQuery {
where: WhereQueryTerm;
}
interface WhereQueryTerm {
column: string;
field: string;
value: string;
}
export function _expectSimpleQuery(query: Query): void {
if (typeof query === "object") throw new Error("expected simple query");
}
/** /**
* Normalize & error check the query. * Normalize & error check the query.
* @param {object | string} query - the query * @param {Query} query - the query
* @returns {object | string} - the normalized query * @returns {Query} - the normalized query
*/ */
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. export function _queryValidate(query: Query): Query {
export function _queryValidate(query: any) {
if (typeof query !== "object") return query; if (typeof query !== "object") return query;
if (query.where && query.summarize) if ("where" in query && "summarize" in query)
throw new Error("query may not specify both where and summarize"); throw new Error("query may not specify both where and summarize");
if (query.where) { if ("where" in query) {
const { const {
field: queryField, field: queryField,
column: queryColumn, column: queryColumn,
@@ -26,7 +56,7 @@ export function _queryValidate(query: any) {
throw new Error("Incomplete where query"); throw new Error("Incomplete where query");
return query; return query;
} }
if (query.summarize) { if ("summarize" in query) {
const { const {
field: queryField, field: queryField,
column: queryColumn, column: queryColumn,
@@ -41,13 +71,7 @@ export function _queryValidate(query: any) {
throw new Error("query must specify one of where or summarize"); throw new Error("query must specify one of where or summarize");
} }
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. export function _expectComplexQuery(query: Query): void {
export function _expectSimpleQuery(query: any) {
if (typeof query === "object") throw new Error("expected simple query");
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
export function _expectComplexQuery(query: any) {
if (typeof query !== "object") throw new Error("expected complex query"); if (typeof query !== "object") throw new Error("expected complex query");
} }
@@ -56,13 +80,12 @@ export function _expectComplexQuery(query: any) {
* *
* @param {string} field * @param {string} field
* @param {string|object} query * @param {string|object} query
* @returns the key * @returns {string} the key
*/ */
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. export function _queryCacheKey(field: Field, query: Query): string {
export function _queryCacheKey(field: any, query: any) {
if (typeof query === "object") { if (typeof query === "object") {
// complex query // complex query
if (query.where) { if ("where" in query) {
const { const {
field: queryField, field: queryField,
column: queryColumn, column: queryColumn,
@@ -70,7 +93,7 @@ export function _queryCacheKey(field: any, query: any) {
} = query.where; } = query.where;
return `${field}/${queryField}/${queryColumn}/${queryValue}`; return `${field}/${queryField}/${queryColumn}/${queryValue}`;
} }
if (query.summarize) { if ("summarize" in query) {
const { const {
method, method,
field: queryField, field: queryField,
@@ -88,38 +111,34 @@ export function _queryCacheKey(field: any, query: any) {
return `${field}/${query}`; return `${field}/${query}`;
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. function _urlEncodeWhereQuery(q: WhereQueryTerm): string {
function _urlEncodeWhereQuery(q: any) {
const { field: queryField, column: queryColumn, value: queryValue } = q; const { field: queryField, column: queryColumn, value: queryValue } = q;
return `${_dubEncURIComp(queryField)}:${_dubEncURIComp( return `${_dubEncURIComp(queryField)}:${_dubEncURIComp(
queryColumn queryColumn
)}=${_dubEncURIComp(queryValue)}`; )}=${_dubEncURIComp(queryValue)}`;
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. function _urlEncodeSummarizeQuery(q: SummarizeQueryTerm): string {
function _urlEncodeSummarizeQuery(q: any) {
const { method, field, column, values } = q; const { method, field, column, values } = q;
const filter = values // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. const filter = values
.map((value: any) => _urlEncodeWhereQuery({ field, column, value })) .map((value: string) => _urlEncodeWhereQuery({ field, column, value }))
.join("&"); .join("&");
return `method=${method}&${filter}`; return `method=${method}&${filter}`;
} }
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. export function _urlEncodeComplexQuery(q: ComplexQuery): string {
export function _urlEncodeComplexQuery(q: any) {
if (typeof q === "object") { if (typeof q === "object") {
if (q.where) { if ("where" in q) {
return _urlEncodeWhereQuery(q.where); return _urlEncodeWhereQuery(q.where);
} }
if (q.summarize) { if ("summarize" in q) {
return _urlEncodeSummarizeQuery(q.summarize); return _urlEncodeSummarizeQuery(q.summarize);
} }
} }
throw new Error("Unrecognized complex query type"); throw new Error("Unrecognized complex query type");
} }
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. export function _urlEncodeLabelQuery(colKey: string, q: Query): string {
export function _urlEncodeLabelQuery(colKey: any, q: any) {
if (!colKey) throw new Error("Unsupported query by name"); if (!colKey) throw new Error("Unsupported query by name");
if (typeof q !== "string") throw new Error("Query must be a simple label."); if (typeof q !== "string") throw new Error("Query must be a simple label.");
return `${colKey}=${encodeURIComponent(q)}`; return `${colKey}=${encodeURIComponent(q)}`;
@@ -128,8 +147,6 @@ export function _urlEncodeLabelQuery(colKey: any, q: any) {
/** /**
* Generate the column key the server will send us for this query. * Generate the column key the server will send us for this query.
*/ */
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. export function _hashStringValues(arrayOfString: string[]): string {
export function _hashStringValues(arrayOfString: any) { return sha1(arrayOfString.join(""));
const hash = sha1(arrayOfString.join(""));
return hash;
} }
+42 -32
View File
@@ -1,37 +1,54 @@
/* /*
Private helper functions related to schema Private helper functions related to schema
*/ */
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. import {
export function _getColumnSchema(schema: any, field: any, col: any) { AnnotationColumnSchema,
ArraySchema,
Field,
Schema,
} from "../common/types/schema";
import { LabelArray, LabelType } from "../util/dataframe/types";
export function _getColumnSchema(
schema: Schema,
field: Field,
col: LabelType
): ArraySchema {
/* look up the column definition */ /* look up the column definition */
switch (field) { switch (field) {
case "obs": case Field.obs:
if (typeof col === "object") if (typeof col === "object")
throw new Error("unable to get column schema by query"); throw new Error("unable to get column schema by query");
return schema.annotations.obsByName[col]; return schema.annotations.obsByName[col];
case "var": case Field.var:
if (typeof col === "object") if (typeof col === "object")
throw new Error("unable to get column schema by query"); throw new Error("unable to get column schema by query");
return schema.annotations.varByName[col]; return schema.annotations.varByName[col];
case "emb": case Field.emb:
if (typeof col === "object") if (typeof col === "object")
throw new Error("unable to get column schema by query"); throw new Error("unable to get column schema by query");
return schema.layout.obsByName[col]; return schema.layout.obsByName[col];
case "X": case Field.X:
return schema.dataframe; return schema.dataframe;
default: default:
throw new Error(`unknown field name: ${field}`); throw new Error(`unknown field name: ${field}`);
} }
} }
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. export function _isIndex(
export function _isIndex(schema: any, field: any, col: any): boolean { schema: Schema,
field: Field.obs | Field.var,
col: LabelType
): boolean {
const index = schema.annotations?.[field].index; const index = schema.annotations?.[field].index;
return index && index === col; return !!(index && index === col);
} }
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. export function _getColumnDimensionNames(
export function _getColumnDimensionNames(schema: any, field: any, col: any) { schema: Schema,
field: Field,
col: LabelType
): LabelArray | undefined {
/* /*
field/col may be an alias for multiple columns. Currently used to map ND field/col may be an alias for multiple columns. Currently used to map ND
values to 1D dataframe columns for embeddings/layout. Signified by the presence values to 1D dataframe columns for embeddings/layout. Signified by the presence
@@ -41,40 +58,33 @@ export function _getColumnDimensionNames(schema: any, field: any, col: any) {
if (!colSchema) { if (!colSchema) {
return undefined; return undefined;
} }
return colSchema.dims || [col]; if ("dims" in colSchema) {
return colSchema.dims;
}
return [col];
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'schema' implicitly has an 'any' type. export function _schemaColumns(schema: Schema, field: Field): string[] {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
export function _schemaColumns(schema, field) {
switch (field) { switch (field) {
case "obs": case Field.obs:
return Object.keys(schema.annotations.obsByName); return Object.keys(schema.annotations.obsByName);
case "var": case Field.var:
return Object.keys(schema.annotations.varByName); return Object.keys(schema.annotations.varByName);
case "emb": case Field.emb:
return Object.keys(schema.layout.obsByName); return Object.keys(schema.layout.obsByName);
default: default:
throw new Error(`unknown field name: ${field}`); throw new Error(`unknown field name: ${field}`);
} }
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'schema' implicitly has an 'any' type. export function _getWritableColumns(schema: Schema, field: Field): string[] {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. if (field !== Field.obs) return [];
export function _getWritableColumns(schema, field) { return schema.annotations.obs.columns
if (field !== "obs") return []; .filter((v: AnnotationColumnSchema) => v.writable)
return ( .map((v: AnnotationColumnSchema) => v.name);
schema.annotations.obs.columns
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'v' implicitly has an 'any' type.
.filter((v) => v.writable)
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'v' implicitly has an 'any' type.
.map((v) => v.name)
);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'schema' implicitly has an 'any' type. export function _isContinuousType(schema: ArraySchema): boolean {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
export function _isContinuousType(schema) {
const { type } = schema; const { type } = schema;
return !(type === "string" || type === "boolean" || type === "categorical"); return !(type === "string" || type === "boolean" || type === "categorical");
} }
+29 -19
View File
@@ -4,9 +4,18 @@ instances of AnnoMatrix, implementing common UI functions.
*/ */
import { AnnoMatrixRowSubsetView, AnnoMatrixClipView } from "./views"; import { AnnoMatrixRowSubsetView, AnnoMatrixClipView } from "./views";
import AnnoMatrix from "./annoMatrix";
import {
DenseInt32Index,
IdentityInt32Index,
KeyIndex,
} from "../util/dataframe";
import { OffsetArray } from "../util/dataframe/types";
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. export function isubsetMask(
export function isubsetMask(annoMatrix: any, obsMask: any) { annoMatrix: AnnoMatrix,
obsMask: Uint8Array
): AnnoMatrixRowSubsetView {
/* /*
Subset annomatrix to contain the rows which have truish value in the mask. Subset annomatrix to contain the rows which have truish value in the mask.
Maks length must equal annoMatrix.nObs (row count). Maks length must equal annoMatrix.nObs (row count).
@@ -14,9 +23,10 @@ export function isubsetMask(annoMatrix: any, obsMask: any) {
return isubset(annoMatrix, _maskToList(obsMask)); return isubset(annoMatrix, _maskToList(obsMask));
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'annoMatrix' implicitly has an 'any' typ... Remove this comment to see the full error message export function isubset(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. annoMatrix: AnnoMatrix,
export function isubset(annoMatrix, obsOffsets) { obsOffsets: OffsetArray
): AnnoMatrixRowSubsetView {
/* /*
Subset annomatrix to contain the positions contained in the obsOffsets array Subset annomatrix to contain the positions contained in the obsOffsets array
@@ -28,9 +38,10 @@ export function isubset(annoMatrix, obsOffsets) {
return new AnnoMatrixRowSubsetView(annoMatrix, obsIndex); return new AnnoMatrixRowSubsetView(annoMatrix, obsIndex);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'annoMatrix' implicitly has an 'any' typ... Remove this comment to see the full error message export function subset(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. annoMatrix: AnnoMatrix,
export function subset(annoMatrix, obsLabels) { obsLabels: Int32Array
): AnnoMatrixRowSubsetView {
/* /*
subset based on labels subset based on labels
*/ */
@@ -38,18 +49,21 @@ export function subset(annoMatrix, obsLabels) {
return new AnnoMatrixRowSubsetView(annoMatrix, obsIndex); return new AnnoMatrixRowSubsetView(annoMatrix, obsIndex);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'annoMatrix' implicitly has an 'any' typ... Remove this comment to see the full error message export function subsetByIndex(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. annoMatrix: AnnoMatrix,
export function subsetByIndex(annoMatrix, obsIndex) { obsIndex: DenseInt32Index | IdentityInt32Index | KeyIndex
): AnnoMatrixRowSubsetView {
/* /*
subset based upon the new obs index. subset based upon the new obs index.
*/ */
return new AnnoMatrixRowSubsetView(annoMatrix, obsIndex); return new AnnoMatrixRowSubsetView(annoMatrix, obsIndex);
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'annoMatrix' implicitly has an 'any' typ... Remove this comment to see the full error message export function clip(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. annoMatrix: AnnoMatrix,
export function clip(annoMatrix, qmin, qmax) { qmin: number,
qmax: number
): AnnoMatrix {
/* /*
Create a view that clips all continuous data to the [min, max] range. Create a view that clips all continuous data to the [min, max] range.
The matrix shape does not change, but the continuous values outside the The matrix shape does not change, but the continuous values outside the
@@ -62,12 +76,8 @@ export function clip(annoMatrix, qmin, qmax) {
Private utility functions below Private utility functions below
*/ */
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'mask' implicitly has an 'any' type. function _maskToList(mask: Uint8Array): OffsetArray {
function _maskToList(mask) {
/* convert masks to lists - method wastes space, but is fast */ /* convert masks to lists - method wastes space, but is fast */
if (!mask) {
return null;
}
const list = new Int32Array(mask.length); const list = new Int32Array(mask.length);
let elems = 0; let elems = 0;
for (let i = 0, l = mask.length; i < l; i += 1) { for (let i = 0, l = mask.length; i < l; i += 1) {
+105 -65
View File
@@ -5,21 +5,40 @@ Views on the annomatrix. all API here is defined in viewCreators.js and annoMat
*/ */
import clip from "../util/clip"; import clip from "../util/clip";
import AnnoMatrix from "./annoMatrix"; import AnnoMatrix from "./annoMatrix";
import { _whereCacheCreate } from "./whereCache"; import { _whereCacheCreate, WhereCache } from "./whereCache";
import { _isContinuousType, _getColumnSchema } from "./schema"; import { _isContinuousType, _getColumnSchema } from "./schema";
import {
Dataframe,
DataframeValue,
DataframeValueArray,
LabelType,
} from "../util/dataframe";
import { Query } from "./query";
import {
AnnotationColumnSchema,
ArraySchema,
Field,
EmbeddingSchema,
} from "../common/types/schema";
import { LabelIndexBase } from "../util/dataframe/labelIndex";
class AnnoMatrixView extends AnnoMatrix { type MapFn = (
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. field: Field,
constructor(viewOf: any, rowIndex = null) { colLabel: LabelType,
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. colSchema: ArraySchema,
colData: DataframeValueArray,
df: Dataframe
) => DataframeValueArray;
abstract class AnnoMatrixView extends AnnoMatrix {
constructor(viewOf: AnnoMatrix, rowIndex: LabelIndexBase | null = null) {
const nObs = rowIndex ? rowIndex.size() : viewOf.nObs; const nObs = rowIndex ? rowIndex.size() : viewOf.nObs;
super(viewOf.schema, nObs, viewOf.nVar, rowIndex || viewOf.rowIndex); super(viewOf.schema, nObs, viewOf.nVar, rowIndex || viewOf.rowIndex);
this.viewOf = viewOf; this.viewOf = viewOf;
this.isView = true; this.isView = true;
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. addObsAnnoCategory(col: LabelType, category: string): AnnoMatrix {
addObsAnnoCategory(col: any, category: any) {
const newAnnoMatrix = this._clone(); const newAnnoMatrix = this._clone();
newAnnoMatrix.viewOf = this.viewOf.addObsAnnoCategory(col, category); newAnnoMatrix.viewOf = this.viewOf.addObsAnnoCategory(col, category);
newAnnoMatrix.schema = newAnnoMatrix.viewOf.schema; newAnnoMatrix.schema = newAnnoMatrix.viewOf.schema;
@@ -27,13 +46,10 @@ class AnnoMatrixView extends AnnoMatrix {
} }
async removeObsAnnoCategory( async removeObsAnnoCategory(
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. col: LabelType,
col: any, category: string,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. unassignedCategory: string
category: any, ): Promise<AnnoMatrix> {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
unassignedCategory: any
) {
const newAnnoMatrix = this._clone(); const newAnnoMatrix = this._clone();
newAnnoMatrix.viewOf = await this.viewOf.removeObsAnnoCategory( newAnnoMatrix.viewOf = await this.viewOf.removeObsAnnoCategory(
col, col,
@@ -44,8 +60,7 @@ class AnnoMatrixView extends AnnoMatrix {
return newAnnoMatrix; return newAnnoMatrix;
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. dropObsColumn(col: LabelType): AnnoMatrix {
dropObsColumn(col: any) {
const newAnnoMatrix = this._clone(); const newAnnoMatrix = this._clone();
newAnnoMatrix.viewOf = this.viewOf.dropObsColumn(col); newAnnoMatrix.viewOf = this.viewOf.dropObsColumn(col);
newAnnoMatrix._cache.obs = this._cache.obs.dropCol(col); newAnnoMatrix._cache.obs = this._cache.obs.dropCol(col);
@@ -53,24 +68,29 @@ class AnnoMatrixView extends AnnoMatrix {
return newAnnoMatrix; return newAnnoMatrix;
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. addObsColumn<T extends DataframeValueArray>(
addObsColumn(colSchema: any, Ctor: any, value: any) { colSchema: AnnotationColumnSchema,
Ctor: new (n: number) => T,
value: T
): AnnoMatrix {
const newAnnoMatrix = this._clone(); const newAnnoMatrix = this._clone();
newAnnoMatrix.viewOf = this.viewOf.addObsColumn(colSchema, Ctor, value); newAnnoMatrix.viewOf = this.viewOf.addObsColumn(colSchema, Ctor, value);
newAnnoMatrix.schema = newAnnoMatrix.viewOf.schema; newAnnoMatrix.schema = newAnnoMatrix.viewOf.schema;
return newAnnoMatrix; return newAnnoMatrix;
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. renameObsColumn(oldCol: LabelType, newCol: LabelType): AnnoMatrix {
renameObsColumn(oldCol: any, newCol: any) {
const newAnnoMatrix = this._clone(); const newAnnoMatrix = this._clone();
newAnnoMatrix.viewOf = this.viewOf.renameObsColumn(oldCol, newCol); newAnnoMatrix.viewOf = this.viewOf.renameObsColumn(oldCol, newCol);
newAnnoMatrix.schema = newAnnoMatrix.viewOf.schema; newAnnoMatrix.schema = newAnnoMatrix.viewOf.schema;
return newAnnoMatrix; return newAnnoMatrix;
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. async setObsColumnValues(
async setObsColumnValues(col: any, rowLabels: any, value: any) { col: LabelType,
rowLabels: Int32Array,
value: DataframeValue
): Promise<AnnoMatrix> {
const newAnnoMatrix = this._clone(); const newAnnoMatrix = this._clone();
newAnnoMatrix.viewOf = await this.viewOf.setObsColumnValues( newAnnoMatrix.viewOf = await this.viewOf.setObsColumnValues(
col, col,
@@ -82,8 +102,11 @@ class AnnoMatrixView extends AnnoMatrix {
return newAnnoMatrix; return newAnnoMatrix;
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. async resetObsColumnValues<T extends DataframeValue>(
async resetObsColumnValues(col: any, oldValue: any, newValue: any) { col: LabelType,
oldValue: T,
newValue: T
): Promise<AnnoMatrix> {
const newAnnoMatrix = this._clone(); const newAnnoMatrix = this._clone();
newAnnoMatrix.viewOf = await this.viewOf.resetObsColumnValues( newAnnoMatrix.viewOf = await this.viewOf.resetObsColumnValues(
col, col,
@@ -95,8 +118,7 @@ class AnnoMatrixView extends AnnoMatrix {
return newAnnoMatrix; return newAnnoMatrix;
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. addEmbedding(colSchema: EmbeddingSchema): AnnoMatrix {
addEmbedding(colSchema: any) {
const newAnnoMatrix = this._clone(); const newAnnoMatrix = this._clone();
newAnnoMatrix.viewOf = this.viewOf.addEmbedding(colSchema); newAnnoMatrix.viewOf = this.viewOf.addEmbedding(colSchema);
newAnnoMatrix.schema = newAnnoMatrix.viewOf.schema; newAnnoMatrix.schema = newAnnoMatrix.viewOf.schema;
@@ -105,26 +127,32 @@ class AnnoMatrixView extends AnnoMatrix {
} }
class AnnoMatrixMapView extends AnnoMatrixView { class AnnoMatrixMapView extends AnnoMatrixView {
mapFn: MapFn;
/* /*
A view which knows how to transform its data. A view which knows how to transform its data.
*/ */
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'viewOf' implicitly has an 'any' type. constructor(viewOf: AnnoMatrix, mapFn: MapFn) {
constructor(viewOf, mapFn) {
super(viewOf); super(viewOf);
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. this.mapFn = mapFn;
(this as any).mapFn = mapFn;
} }
// @ts-expect-error ts-migrate(2416) FIXME: Property '_doLoad' in type 'AnnoMatrixMapView' is ... Remove this comment to see the full error message async _doLoad(
async _doLoad(field, query) { field: Field,
query: Query
): Promise<[WhereCache | null, Dataframe]> {
const df = await this.viewOf._fetch(field, query); const df = await this.viewOf._fetch(field, query);
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'colData' implicitly has an 'any' type. const dfMapped = df.mapColumns(
const dfMapped = df.mapColumns((colData, colIdx) => { (colData: DataframeValueArray, colIdx: number) => {
const colLabel = df.colIndex.getLabel(colIdx); const colLabel = df.colIndex.getLabel(colIdx);
const colSchema = _getColumnSchema(this.schema, field, colLabel); // @ts-expect-error ts-migrate --- TODO revisit:
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. // `colLabel`: Argument of type 'LabelType | undefined' is not assignable to parameter of type 'LabelType'.
return (this as any).mapFn(field, colLabel, colSchema, colData, df); const colSchema = _getColumnSchema(this.schema, field, colLabel);
}); // @ts-expect-error ts-migrate --- TODO revisit:
// `colLabel`: Argument of type 'LabelType | undefined' is not assignable to parameter of type 'LabelType'.
return this.mapFn(field, colLabel, colSchema, colData, df);
}
);
const whereCacheUpdate = _whereCacheCreate( const whereCacheUpdate = _whereCacheCreate(
field, field,
query, query,
@@ -135,42 +163,47 @@ class AnnoMatrixMapView extends AnnoMatrixView {
} }
export class AnnoMatrixClipView extends AnnoMatrixMapView { export class AnnoMatrixClipView extends AnnoMatrixMapView {
clipRange: [number, number];
isClipped: boolean;
/* /*
A view which is a clipped transformation of its parent A view which is a clipped transformation of its parent
*/ */
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'viewOf' implicitly has an 'any' type. constructor(viewOf: AnnoMatrix, qmin: number, qmax: number) {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. super(
constructor(viewOf, qmin, qmax) { viewOf,
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type. (
super(viewOf, (field, colLabel, colSchema, colData, df) => field: Field,
_clipAnnoMatrix(field, colLabel, colSchema, colData, df, qmin, qmax) colLabel: LabelType,
colSchema: ArraySchema,
colData: DataframeValueArray,
df: Dataframe
) => _clipAnnoMatrix(field, colLabel, colSchema, colData, df, qmin, qmax)
); );
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. this.isClipped = true;
(this as any).isClipped = true; this.clipRange = [qmin, qmax];
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(this as any).clipRange = [qmin, qmax];
Object.seal(this); Object.seal(this);
} }
} }
export class AnnoMatrixRowSubsetView extends AnnoMatrixView { export class AnnoMatrixRowSubsetView extends AnnoMatrixView {
/* /*
A view which is a subset of total rows. A view which is a subset of total rows.
*/ */
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'viewOf' implicitly has an 'any' type. constructor(viewOf: AnnoMatrix, rowIndex: LabelIndexBase) {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
constructor(viewOf, rowIndex) {
super(viewOf, rowIndex); super(viewOf, rowIndex);
Object.seal(this); Object.seal(this);
} }
// @ts-expect-error ts-migrate(2416) FIXME: Property '_doLoad' in type 'AnnoMatrixRowSubsetVie... Remove this comment to see the full error message async _doLoad(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. field: Field,
async _doLoad(field, query) { query: Query
): Promise<[WhereCache | null, Dataframe]> {
const df = await this.viewOf._fetch(field, query); const df = await this.viewOf._fetch(field, query);
// don't try to row-subset the var dimension. // don't try to row-subset the var dimension.
if (field === "var") { if (field === Field.var) {
return [null, df]; return [null, df];
} }
@@ -188,10 +221,17 @@ export class AnnoMatrixRowSubsetView extends AnnoMatrixView {
Utility functions below Utility functions below
*/ */
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type. function _clipAnnoMatrix(
function _clipAnnoMatrix(field, colLabel, colSchema, colData, df, qmin, qmax) { field: Field,
colLabel: LabelType,
colSchema: ArraySchema,
colData: DataframeValueArray,
df: Dataframe,
qmin: number,
qmax: number
): DataframeValueArray {
/* only clip obs and var scalar columns */ /* only clip obs and var scalar columns */
if (field !== "obs" && field !== "X") return colData; if (field !== Field.obs && field !== Field.X) return colData;
if (!_isContinuousType(colSchema)) return colData; if (!_isContinuousType(colSchema)) return colData;
if (qmin < 0) qmin = 0; if (qmin < 0) qmin = 0;
if (qmax > 1) qmax = 1; if (qmax > 1) qmax = 1;
+45 -30
View File
@@ -2,7 +2,7 @@
Private support functions. Private support functions.
This implements a query resolver cache, mapping a query onto the column labels This implements a query resolver cache, mapping a query onto the column labels
resolved by that query. These labels are then used to manage the acutal data cache, resolved by that query. These labels are then used to manage the actual data cache,
which stores data by the resolved label. which stores data by the resolved label.
There are three query forms: There are three query forms:
@@ -49,19 +49,33 @@ creates a cache entry of:
} }
*/ */
import { _getColumnDimensionNames } from "./schema"; import { _getColumnDimensionNames } from "./schema";
import { _hashStringValues } from "./query"; import { _hashStringValues, Query } from "./query";
import { Field, Schema } from "../common/types/schema";
import { LabelArray } from "../util/dataframe/types";
export interface WhereCache {
summarize?: {
[key: string]: {
[key: string]: WhereCacheTerms;
};
};
where?: {
[key: string]: WhereCacheTerms;
};
}
export type WhereCacheColumnLabels = LabelArray;
interface WhereCacheTerms {
[key: string]: Map<string, Map<string, WhereCacheColumnLabels>>;
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
export function _whereCacheGet( export function _whereCacheGet(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. whereCache: WhereCache,
whereCache: any, schema: Schema,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. field: Field,
schema: any, query: Query
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS. ): WhereCacheColumnLabels | [undefined] {
field: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
query: any
) {
/* /*
query will either be an where query (object) or a column name (string). query will either be an where query (object) or a column name (string).
@@ -69,7 +83,7 @@ export function _whereCacheGet(
*/ */
if (typeof query === "object") { if (typeof query === "object") {
if (query.where) { if ("where" in query) {
const { const {
field: queryField, field: queryField,
column: queryColumn, column: queryColumn,
@@ -78,7 +92,7 @@ export function _whereCacheGet(
const columnMap = whereCache?.where?.[field]?.[queryField]; const columnMap = whereCache?.where?.[field]?.[queryField];
return columnMap?.get(queryColumn)?.get(queryValue) ?? [undefined]; return columnMap?.get(queryColumn)?.get(queryValue) ?? [undefined];
} }
if (query.summarize) { if ("summarize" in query) {
const { const {
method, method,
field: queryField, field: queryField,
@@ -95,15 +109,17 @@ export function _whereCacheGet(
return _getColumnDimensionNames(schema, field, query) ?? [undefined]; return _getColumnDimensionNames(schema, field, query) ?? [undefined];
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'field' implicitly has an 'any' type. export function _whereCacheCreate(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. field: Field,
export function _whereCacheCreate(field, query, columnLabels) { query: Query,
columnLabels: LabelArray
): WhereCache | null {
/* /*
Create a new whereCache Create a new whereCache
*/ */
if (typeof query !== "object") return null; if (typeof query !== "object") return null;
if (query.where) { if ("where" in query) {
const { const {
field: queryField, field: queryField,
column: queryColumn, column: queryColumn,
@@ -119,7 +135,7 @@ export function _whereCacheCreate(field, query, columnLabels) {
}, },
}; };
} }
if (query.summarize) { if ("summarize" in query) {
const { const {
method, method,
field: queryField, field: queryField,
@@ -143,23 +159,25 @@ export function _whereCacheCreate(field, query, columnLabels) {
return {}; return {};
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'dst' implicitly has an 'any' type. function __mergeQueries(dst: WhereCacheTerms, src: WhereCacheTerms) {
function __mergeQueries(dst, src) {
for (const [queryField, columnMap] of Object.entries(src)) { for (const [queryField, columnMap] of Object.entries(src)) {
dst[queryField] = dst[queryField] || new Map(); dst[queryField] = dst[queryField] || new Map();
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS. for (const [queryColumn, valueMap] of columnMap) {
for (const [queryColumn, valueMap] of columnMap as any) {
if (!dst[queryField].has(queryColumn)) if (!dst[queryField].has(queryColumn))
dst[queryField].set(queryColumn, new Map()); dst[queryField].set(queryColumn, new Map());
for (const [queryValue, columnLabels] of valueMap) { for (const [queryValue, columnLabels] of valueMap) {
// @ts-expect-error ts-migrate --- TODO revisit:
// `dst[queryField].get(queryColumn)` Object is possibly 'undefined'.
dst[queryField].get(queryColumn).set(queryValue, columnLabels); dst[queryField].get(queryColumn).set(queryValue, columnLabels);
} }
} }
} }
} }
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'dst' implicitly has an 'any' type. function __whereCacheMerge(
function __whereCacheMerge(dst, src) { dst: WhereCache,
src: WhereCache | null
): WhereCache {
/* /*
merge src into dst (modifies dst) merge src into dst (modifies dst)
*/ */
@@ -176,7 +194,6 @@ function __whereCacheMerge(dst, src) {
dst.summarize = dst.summarize || {}; dst.summarize = dst.summarize || {};
for (const [field, method] of Object.entries(src.summarize)) { for (const [field, method] of Object.entries(src.summarize)) {
dst.summarize[field] = dst.summarize[field] || {}; dst.summarize[field] = dst.summarize[field] || {};
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
for (const [methodName, query] of Object.entries(method)) { for (const [methodName, query] of Object.entries(method)) {
dst.summarize[field][methodName] = dst.summarize[field][methodName] =
dst.summarize[field][methodName] || {}; dst.summarize[field][methodName] || {};
@@ -187,8 +204,6 @@ function __whereCacheMerge(dst, src) {
return dst; return dst;
} }
// @ts-expect-error ts-migrate(7019) FIXME: Rest parameter 'caches' implicitly has an 'any[]' ... Remove this comment to see the full error message export function _whereCacheMerge(...caches: (WhereCache | null)[]): WhereCache {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS. return caches.reduce(__whereCacheMerge, {} as WhereCache);
export function _whereCacheMerge(...caches) {
return caches.reduce(__whereCacheMerge, {});
} }
+6 -1
View File
@@ -1,3 +1,8 @@
// If a globally shared type or interface doesn't have a clear owner, put it here // If a globally shared type or interface doesn't have a clear owner, put it here
export {}; /**
* Flags informing garbage collection-related logic.
*/
export interface GCHints {
isHot: boolean;
}
+20 -2
View File
@@ -1,4 +1,4 @@
type Category = number | string | boolean; export type Category = number | string | boolean;
export interface AnnotationColumnSchema { export interface AnnotationColumnSchema {
categories?: Category[]; categories?: Category[];
@@ -7,7 +7,7 @@ export interface AnnotationColumnSchema {
writable: boolean; writable: boolean;
} }
interface XMatrixSchema { export interface XMatrixSchema {
nObs: number; nObs: number;
nVar: number; nVar: number;
// TODO(thuang): Not sure what other types are available // TODO(thuang): Not sure what other types are available
@@ -56,3 +56,21 @@ export interface Schema extends RawSchema {
annotations: AnnotationsSchema; annotations: AnnotationsSchema;
layout: LayoutSchema; layout: LayoutSchema;
} }
/**
* Sub-schema objects describing the schema for a primitive Array or Matrix in one of the fields.
*/
export type ArraySchema =
| AnnotationColumnSchema
| EmbeddingSchema
| XMatrixSchema;
/**
* Set of data / metadata objects that must be specified in a CXG.
*/
export enum Field {
"obs" = "obs",
"var" = "var",
"emb" = "emb",
"X" = "X",
}
@@ -14,6 +14,7 @@ import {
EmbeddingSchema, EmbeddingSchema,
AnnotationColumnSchema, AnnotationColumnSchema,
} from "../../common/types/schema"; } from "../../common/types/schema";
import { LabelType } from "../dataframe/types";
/* /*
System wide schema assumptions: System wide schema assumptions:
@@ -75,7 +76,7 @@ function _reindexObsLayout(schema: Schema) {
return schema; return schema;
} }
export function removeObsAnnoColumn(schema: Schema, name: string): Schema { export function removeObsAnnoColumn(schema: Schema, name: LabelType): Schema {
const newSchema = _copyObsAnno(schema); const newSchema = _copyObsAnno(schema);
newSchema.annotations.obs.columns = schema.annotations.obs.columns.filter( newSchema.annotations.obs.columns = schema.annotations.obs.columns.filter(
(v) => v.name !== name (v) => v.name !== name
@@ -97,7 +98,7 @@ export function addObsAnnoColumn(
export function removeObsAnnoCategory( export function removeObsAnnoCategory(
schema: Schema, schema: Schema,
name: string, name: LabelType,
category: string category: string
): Schema { ): Schema {
/* remove a category from a categorical annotation */ /* remove a category from a categorical annotation */