mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-09-22 20:38:12 +08:00
chore: type general utils (#2381)
* type camera
* type reducer store
* type actionhelpers
* type catchErrorsWrap callsite
* missed camera member var
* type nameCreators
* type makeContinousDimensionName callsite
* type promise limit
* type quantile
* type range
* introduce TypedArray + NumericArray
* type range
* cleanup test
* fix call sites
* type plimit call site
* finish typing camera
* use our TypedArray
* type scientific and sigFig utils and callsites
* simple typings
* type catLabelSort
* type callsite
* type
* callsites
* type camera methods
* swap back to strings, set defaults accordingly
* partially type centroid
* explicit tuple and undefined check
* fix references to this
* call constructor with new and casting
* Revert "introduce TypedArray + NumericArray"
This reverts commit cf21538717.
* explicit tuple
* generics and import fixes
* add unsigned 8 clamped arrray
* back to literals
* use arraytypes
* fix return state
* type more actions
* Update client/src/util/actionHelpers.ts
Co-authored-by: Timmy Huang <tihuan@users.noreply.github.com>
* properly type dispatch
* properly type thunk
* use new dispatch
* remove nullish coallescer
* use AppDispatch
* generic jsonrequest
* use dispatch again
* lint
Co-authored-by: Timmy Huang <tihuan@users.noreply.github.com>
This commit is contained in:
co-authored by
Timmy Huang
parent
45cecad76a
commit
08b03ace60
@@ -94,10 +94,12 @@ export async function getAllCategoriesAndCounts(category: any) {
|
||||
.querySelector("[data-testclass='categorical-value']")
|
||||
.getAttribute("aria-label");
|
||||
|
||||
const count = (row.querySelector(
|
||||
"[data-testclass='categorical-value-count']"
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
) as any).innerText;
|
||||
const count = (
|
||||
row.querySelector(
|
||||
"[data-testclass='categorical-value-count']"
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
) as any
|
||||
).innerText;
|
||||
|
||||
return [cat, count];
|
||||
})
|
||||
@@ -194,8 +196,7 @@ export async function expandCategory(category: any) {
|
||||
if (notExpanded) await clickOn(`${category}:category-expand`);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
||||
export async function clip(min = 0, max = 100) {
|
||||
export async function clip(min = "0", max = "100"): Promise<void> {
|
||||
await clickOn("visualization-settings");
|
||||
await clearInputAndTypeInto("clip-min-input", min);
|
||||
await clearInputAndTypeInto("clip-max-input", max);
|
||||
|
||||
@@ -199,7 +199,6 @@ describe("clipping", () => {
|
||||
test("clip continuous", async () => {
|
||||
await goToPage(appUrlBase);
|
||||
|
||||
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'string' is not assignable to par... Remove this comment to see the full error message
|
||||
await clip(data.clip.min, data.clip.max);
|
||||
const histBrushableAreaId = `histogram-${data.clip.metadata}-plot-brushable-area`;
|
||||
const coords = await calcDragCoordinates(
|
||||
|
||||
@@ -52,9 +52,7 @@ describe("PromiseLimit", () => {
|
||||
running -= 1;
|
||||
};
|
||||
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 3 arguments, but got 1.
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
await Promise.all(range(10).map((i: any) => plimit.add(() => callback(i))));
|
||||
await Promise.all(range(10).map(() => plimit.add(() => callback())));
|
||||
|
||||
expect(maxRunning).toEqual(2);
|
||||
});
|
||||
|
||||
@@ -6,20 +6,14 @@ describe("range", () => {
|
||||
});
|
||||
|
||||
test("range(stop)", () => {
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 3 arguments, but got 1.
|
||||
expect(range(3)).toMatchObject([0, 1, 2]);
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 3 arguments, but got 1.
|
||||
expect(range(0)).toMatchObject([]);
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 3 arguments, but got 1.
|
||||
expect(range(1)).toMatchObject([0]);
|
||||
});
|
||||
|
||||
test("range(start,stop)", () => {
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 3 arguments, but got 2.
|
||||
expect(range(0, 0)).toMatchObject([]);
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 3 arguments, but got 2.
|
||||
expect(range(0, 2)).toMatchObject([0, 1]);
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 3 arguments, but got 2.
|
||||
expect(range(4, 8)).toMatchObject([4, 5, 6, 7]);
|
||||
});
|
||||
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
action creators related to embeddings choice
|
||||
*/
|
||||
|
||||
import { Action, ActionCreator } from "redux";
|
||||
import { ThunkAction } from "redux-thunk";
|
||||
import { AnnoMatrixObsCrossfilter } from "../annoMatrix";
|
||||
import type { AppDispatch, RootState } from "../reducers";
|
||||
import { _setEmbeddingSubset } from "../util/stateManager/viewStackHelpers";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
||||
@@ -29,30 +32,26 @@ export async function _switchEmbedding(
|
||||
return [annoMatrix, obsCrossfilter];
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
export const layoutChoiceAction = (newLayoutChoice: any) => async (
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
dispatch: any,
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
getState: any
|
||||
) => {
|
||||
/*
|
||||
export const layoutChoiceAction: ActionCreator<
|
||||
ThunkAction<Promise<void>, RootState, never, Action<"set layout choice">>
|
||||
> =
|
||||
(newLayoutChoice: string) =>
|
||||
async (dispatch: AppDispatch, getState: () => RootState): Promise<void> => {
|
||||
/*
|
||||
On layout choice, make sure we have selected all on the previous layout, AND the new
|
||||
layout.
|
||||
*/
|
||||
const {
|
||||
annoMatrix: prevAnnoMatrix,
|
||||
obsCrossfilter: prevCrossfilter,
|
||||
} = getState();
|
||||
const [annoMatrix, obsCrossfilter] = await _switchEmbedding(
|
||||
prevAnnoMatrix,
|
||||
prevCrossfilter,
|
||||
newLayoutChoice
|
||||
);
|
||||
dispatch({
|
||||
type: "set layout choice",
|
||||
layoutChoice: newLayoutChoice,
|
||||
obsCrossfilter,
|
||||
annoMatrix,
|
||||
});
|
||||
};
|
||||
const { annoMatrix: prevAnnoMatrix, obsCrossfilter: prevCrossfilter } =
|
||||
getState();
|
||||
const [annoMatrix, obsCrossfilter] = await _switchEmbedding(
|
||||
prevAnnoMatrix,
|
||||
prevCrossfilter,
|
||||
newLayoutChoice
|
||||
);
|
||||
dispatch({
|
||||
type: "set layout choice",
|
||||
layoutChoice: newLayoutChoice,
|
||||
obsCrossfilter,
|
||||
annoMatrix,
|
||||
});
|
||||
};
|
||||
|
||||
+102
-98
@@ -1,3 +1,4 @@
|
||||
import type { Config } from "../globals";
|
||||
import * as globals from "../globals";
|
||||
import { AnnoMatrixLoader, AnnoMatrixObsCrossfilter } from "../annoMatrix";
|
||||
import {
|
||||
@@ -11,6 +12,9 @@ import * as annoActions from "./annotation";
|
||||
import * as viewActions from "./viewStack";
|
||||
import * as embActions from "./embedding";
|
||||
import * as genesetActions from "./geneset";
|
||||
import { AppDispatch, RootState } from "../reducers";
|
||||
import { EmbeddingSchema, Schema } from "../common/types/schema";
|
||||
import { UserInfoPayload } from "../reducers/userInfo";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
function setGlobalConfig(config: any) {
|
||||
@@ -36,35 +40,34 @@ async function userColorsFetchAndLoad(dispatch: any) {
|
||||
);
|
||||
}
|
||||
|
||||
async function schemaFetch() {
|
||||
return fetchJson("schema");
|
||||
async function schemaFetch(): Promise<{ schema: Schema }> {
|
||||
return fetchJson<{ schema: Schema }>("schema");
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
async function configFetch(dispatch: any) {
|
||||
return fetchJson("config").then((response) => {
|
||||
const config = { ...globals.configDefaults, ...response.config };
|
||||
async function configFetch(dispatch: AppDispatch): Promise<Config> {
|
||||
const response = await fetchJson<{ config: globals.Config }>("config");
|
||||
const config = { ...globals.configDefaults, ...response.config };
|
||||
|
||||
setGlobalConfig(config);
|
||||
setGlobalConfig(config);
|
||||
|
||||
dispatch({
|
||||
type: "configuration load complete",
|
||||
config,
|
||||
});
|
||||
return config;
|
||||
dispatch({
|
||||
type: "configuration load complete",
|
||||
config,
|
||||
});
|
||||
return config;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
async function userInfoFetch(dispatch: any) {
|
||||
return fetchJson("userinfo").then((response) => {
|
||||
const { userinfo: userInfo } = response || {};
|
||||
dispatch({
|
||||
type: "userInfo load complete",
|
||||
userInfo,
|
||||
});
|
||||
return userInfo;
|
||||
});
|
||||
async function userInfoFetch(dispatch: AppDispatch): Promise<UserInfoPayload> {
|
||||
return fetchJson<{ userinfo: UserInfoPayload }>("userinfo").then(
|
||||
(response) => {
|
||||
const { userinfo: userInfo } = response || {};
|
||||
dispatch({
|
||||
type: "userInfo load complete",
|
||||
userInfo,
|
||||
});
|
||||
return userInfo;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
@@ -104,17 +107,17 @@ function prefetchEmbeddings(annoMatrix: any) {
|
||||
/*
|
||||
Application bootstrap
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
||||
const doInitialDataLoad = () =>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
catchErrorsWrap(async (dispatch: any) => {
|
||||
const doInitialDataLoad = (): ((
|
||||
dispatch: AppDispatch,
|
||||
getState: () => RootState
|
||||
) => void) =>
|
||||
catchErrorsWrap(async (dispatch: AppDispatch) => {
|
||||
dispatch({ type: "initial data load start" });
|
||||
|
||||
try {
|
||||
const [config, schema] = await Promise.all([
|
||||
configFetch(dispatch),
|
||||
// @ts-expect-error ts-migrate(2554) FIXME: Expected 0 arguments, but got 1.
|
||||
schemaFetch(dispatch),
|
||||
schemaFetch(),
|
||||
userColorsFetchAndLoad(dispatch),
|
||||
userInfoFetch(dispatch),
|
||||
]);
|
||||
@@ -137,8 +140,7 @@ const doInitialDataLoad = () =>
|
||||
const layoutSchema = schema?.schema?.layout?.obs ?? [];
|
||||
if (
|
||||
defaultEmbedding &&
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
layoutSchema.some((s: any) => s.name === defaultEmbedding)
|
||||
layoutSchema.some((s: EmbeddingSchema) => s.name === defaultEmbedding)
|
||||
) {
|
||||
dispatch(embActions.layoutChoiceAction(defaultEmbedding));
|
||||
}
|
||||
@@ -188,87 +190,89 @@ const dispatchDiffExpErrors = (dispatch: any, response: any) => {
|
||||
}
|
||||
};
|
||||
|
||||
const requestDifferentialExpression = (
|
||||
const requestDifferentialExpression =
|
||||
(
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
set1: any,
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
set2: any,
|
||||
num_genes = 50
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
) =>
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
set1: any,
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
set2: any,
|
||||
num_genes = 50
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
) => async (dispatch: any, getState: any) => {
|
||||
dispatch({ type: "request differential expression started" });
|
||||
try {
|
||||
/*
|
||||
async (dispatch: any, getState: any) => {
|
||||
dispatch({ type: "request differential expression started" });
|
||||
try {
|
||||
/*
|
||||
Steps:
|
||||
1. get the most differentially expressed genes
|
||||
2. get expression data for each
|
||||
*/
|
||||
const { annoMatrix } = getState();
|
||||
const varIndexName = annoMatrix.schema.annotations.var.index;
|
||||
const { annoMatrix } = getState();
|
||||
const varIndexName = annoMatrix.schema.annotations.var.index;
|
||||
|
||||
// Legal values are null, Array or TypedArray. Null is initial state.
|
||||
if (!set1) set1 = [];
|
||||
if (!set2) set2 = [];
|
||||
// Legal values are null, Array or TypedArray. Null is initial state.
|
||||
if (!set1) set1 = [];
|
||||
if (!set2) set2 = [];
|
||||
|
||||
// These lines ensure that we convert any TypedArray to an Array.
|
||||
// This is necessary because JSON.stringify() does some very strange
|
||||
// things with TypedArrays (they are marshalled to JSON objects, rather
|
||||
// than being marshalled as a JSON array).
|
||||
set1 = Array.isArray(set1) ? set1 : Array.from(set1);
|
||||
set2 = Array.isArray(set2) ? set2 : Array.from(set2);
|
||||
// These lines ensure that we convert any TypedArray to an Array.
|
||||
// This is necessary because JSON.stringify() does some very strange
|
||||
// things with TypedArrays (they are marshalled to JSON objects, rather
|
||||
// than being marshalled as a JSON array).
|
||||
set1 = Array.isArray(set1) ? set1 : Array.from(set1);
|
||||
set2 = Array.isArray(set2) ? set2 : Array.from(set2);
|
||||
|
||||
const res = await fetch(
|
||||
`${globals.API.prefix}${globals.API.version}diffexp/obs`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: new Headers({
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json",
|
||||
}),
|
||||
body: JSON.stringify({
|
||||
mode: "topN",
|
||||
count: num_genes,
|
||||
set1: { filter: { obs: { index: set1 } } },
|
||||
set2: { filter: { obs: { index: set2 } } },
|
||||
}),
|
||||
credentials: "include",
|
||||
const res = await fetch(
|
||||
`${globals.API.prefix}${globals.API.version}diffexp/obs`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: new Headers({
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json",
|
||||
}),
|
||||
body: JSON.stringify({
|
||||
mode: "topN",
|
||||
count: num_genes,
|
||||
set1: { filter: { obs: { index: set1 } } },
|
||||
set2: { filter: { obs: { index: set2 } } },
|
||||
}),
|
||||
credentials: "include",
|
||||
}
|
||||
);
|
||||
|
||||
if (!res.ok || res.headers.get("Content-Type") !== "application/json") {
|
||||
return dispatchDiffExpErrors(dispatch, res);
|
||||
}
|
||||
);
|
||||
|
||||
if (!res.ok || res.headers.get("Content-Type") !== "application/json") {
|
||||
return dispatchDiffExpErrors(dispatch, res);
|
||||
const response = await res.json();
|
||||
const varIndex = await annoMatrix.fetch("var", varIndexName);
|
||||
const diffexpLists = { negative: [], positive: [] };
|
||||
for (const polarity of Object.keys(diffexpLists)) {
|
||||
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
diffexpLists[polarity] = response[polarity].map((v: any) => [
|
||||
varIndex.at(v[0], varIndexName),
|
||||
...v.slice(1),
|
||||
]);
|
||||
}
|
||||
|
||||
/* then send the success case action through */
|
||||
return dispatch({
|
||||
type: "request differential expression success",
|
||||
data: diffexpLists,
|
||||
});
|
||||
} catch (error) {
|
||||
return dispatch({
|
||||
type: "request differential expression error",
|
||||
error,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const response = await res.json();
|
||||
const varIndex = await annoMatrix.fetch("var", varIndexName);
|
||||
const diffexpLists = { negative: [], positive: [] };
|
||||
for (const polarity of Object.keys(diffexpLists)) {
|
||||
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
diffexpLists[polarity] = response[polarity].map((v: any) => [
|
||||
varIndex.at(v[0], varIndexName),
|
||||
...v.slice(1),
|
||||
]);
|
||||
}
|
||||
|
||||
/* then send the success case action through */
|
||||
return dispatch({
|
||||
type: "request differential expression success",
|
||||
data: diffexpLists,
|
||||
});
|
||||
} catch (error) {
|
||||
return dispatch({
|
||||
type: "request differential expression error",
|
||||
error,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
function fetchJson(pathAndQuery: any) {
|
||||
return doJsonRequest(
|
||||
function fetchJson<T>(pathAndQuery: string): Promise<T> {
|
||||
return doJsonRequest<T>(
|
||||
`${globals.API.prefix}${globals.API.version}${pathAndQuery}`
|
||||
);
|
||||
) as Promise<T>;
|
||||
}
|
||||
|
||||
export default {
|
||||
|
||||
@@ -80,10 +80,10 @@ export function normalizeWritableCategoricalSchema(
|
||||
) {
|
||||
/*
|
||||
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
|
||||
the array is UI sorted.
|
||||
*/
|
||||
const categorySet = new Set(
|
||||
const categorySet = new Set<string>(
|
||||
col.summarizeCategorical().categories.concat(colSchema.categories ?? [])
|
||||
);
|
||||
if (!categorySet.has(unassignedCategoryLabel)) {
|
||||
@@ -118,7 +118,7 @@ export function normalizeCategorical(
|
||||
|
||||
// consolidate all categories from data and schema into a single list
|
||||
const colDataSummary = col.summarizeCategorical();
|
||||
const allCategories = new Set(
|
||||
const allCategories = new Set<string>(
|
||||
colDataSummary.categories.concat(colSchema.categories ?? [])
|
||||
);
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
export type TypedArray =
|
||||
| Int8Array
|
||||
| Uint8Array
|
||||
| Uint8ClampedArray
|
||||
| Int16Array
|
||||
| Uint16Array
|
||||
| Int32Array
|
||||
|
||||
@@ -2,6 +2,7 @@ import React, { useEffect, useRef, useState } from "react";
|
||||
import { interpolateCool } from "d3-scale-chromatic";
|
||||
import * as d3 from "d3";
|
||||
|
||||
import { AxisDomain } from "d3";
|
||||
import maybeScientific from "../../util/maybeScientific";
|
||||
import clamp from "../../util/clamp";
|
||||
|
||||
@@ -120,8 +121,12 @@ const Histogram = ({
|
||||
d3
|
||||
.axisBottom(x)
|
||||
.ticks(4)
|
||||
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
|
||||
.tickFormat(d3.format(maybeScientific(x)))
|
||||
.tickFormat(
|
||||
d3.format(maybeScientific(x)) as (
|
||||
dv: AxisDomain,
|
||||
i: number
|
||||
) => string
|
||||
)
|
||||
);
|
||||
|
||||
/* Y AXIS */
|
||||
|
||||
@@ -26,8 +26,10 @@ export const keepAroundErrorToast = (message: any) =>
|
||||
/*
|
||||
a hard network error
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
export const postNetworkErrorToast = (message: any, key = undefined) =>
|
||||
export const postNetworkErrorToast = (
|
||||
message: string,
|
||||
key: string | undefined = undefined
|
||||
): string =>
|
||||
ToastTopCenter.show(
|
||||
{
|
||||
message,
|
||||
|
||||
+14
-1
@@ -8,11 +8,24 @@ export const overflowCategoryLabel = ": all other labels";
|
||||
/* default "unassigned" value for user-created categorical metadata */
|
||||
export const unassignedCategoryLabel = "unassigned";
|
||||
|
||||
/* rough shape of config object */
|
||||
export interface Config {
|
||||
features: Record<string, unknown>;
|
||||
displayNames: Record<string, unknown>;
|
||||
parameters: {
|
||||
"disable-diffexp"?: boolean;
|
||||
"diffexp-may-be-slow"?: boolean;
|
||||
default_embedding?: string;
|
||||
[key: string]: unknown;
|
||||
};
|
||||
links: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/*
|
||||
these are default values for configuration the CLI may supply.
|
||||
See the REST API and CLI specs for more info.
|
||||
*/
|
||||
export const configDefaults = {
|
||||
export const configDefaults: Config = {
|
||||
features: {},
|
||||
displayNames: {},
|
||||
parameters: {
|
||||
|
||||
@@ -1,7 +1,23 @@
|
||||
import type { Action } from "redux";
|
||||
|
||||
import { makeContinuousDimensionName } from "../util/nameCreators";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
const ContinuousSelection = (state = {}, action: any) => {
|
||||
import type { ContinuousNamespace } from "../util/nameCreators";
|
||||
|
||||
export interface ContinuousSelectionAction extends Action<string> {
|
||||
continuousNamespace: ContinuousNamespace;
|
||||
selection: string;
|
||||
range: [number, number];
|
||||
}
|
||||
|
||||
export interface ContinuousSelectionState {
|
||||
[name: string]: [number, number];
|
||||
}
|
||||
|
||||
const ContinuousSelection = (
|
||||
state: ContinuousSelectionState = {},
|
||||
action: ContinuousSelectionAction
|
||||
): ContinuousSelectionState => {
|
||||
switch (action.type) {
|
||||
case "reset subset":
|
||||
case "subset to selection":
|
||||
@@ -25,7 +41,6 @@ const ContinuousSelection = (state = {}, action: any) => {
|
||||
action.continuousNamespace,
|
||||
action.selection
|
||||
);
|
||||
// @ts-expect-error ts-migrate(2537) FIXME: Type '{}' has no matching index signature for type... Remove this comment to see the full error message
|
||||
const { [name]: deletedField, ...newState } = state;
|
||||
return newState;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { createStore, applyMiddleware } from "redux";
|
||||
import thunk from "redux-thunk";
|
||||
import { createStore, applyMiddleware, AnyAction } from "redux";
|
||||
import thunk, { ThunkDispatch } from "redux-thunk";
|
||||
|
||||
import cascadeReducers from "./cascade";
|
||||
import undoable from "./undoable";
|
||||
@@ -63,4 +63,8 @@ const Reducer = undoable(
|
||||
|
||||
const store = createStore(Reducer, applyMiddleware(thunk, annoMatrixGC));
|
||||
|
||||
export type RootState = ReturnType<typeof store.getState>;
|
||||
|
||||
export type AppDispatch = ThunkDispatch<RootState, never, AnyAction>;
|
||||
|
||||
export default store;
|
||||
|
||||
@@ -1,5 +1,27 @@
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
const UserInfo = (state = {}, action: any) => {
|
||||
import { Action } from "redux";
|
||||
|
||||
export interface UserInfoAction extends Action<string>, User {
|
||||
userInfo: UserInfoPayload;
|
||||
error: string;
|
||||
}
|
||||
|
||||
export interface UserInfoPayload {
|
||||
is_authenticated: boolean;
|
||||
username: string;
|
||||
user_id: string;
|
||||
email: string;
|
||||
picture: string;
|
||||
}
|
||||
|
||||
export interface UserInfoState extends UserInfoPayload {
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
}
|
||||
|
||||
const UserInfo = (
|
||||
state: UserInfoState,
|
||||
action: UserInfoAction
|
||||
): UserInfoState => {
|
||||
switch (action.type) {
|
||||
case "initial data load start":
|
||||
return {
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import sortBy from "lodash.sortby";
|
||||
/* XXX: cough, cough, ... */
|
||||
import { postNetworkErrorToast } from "../components/framework/toasters";
|
||||
import type { AppDispatch, RootState } from "../reducers";
|
||||
|
||||
/*
|
||||
dispatch an action error to the user. Currently we use
|
||||
async toasts.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
let networkErrorToastKey: any = null;
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
export const dispatchNetworkErrorMessageToUser = (message: any) => {
|
||||
let networkErrorToastKey: string | null = null;
|
||||
export const dispatchNetworkErrorMessageToUser = (message: string): void => {
|
||||
if (!networkErrorToastKey) {
|
||||
networkErrorToastKey = postNetworkErrorToast(message);
|
||||
} else {
|
||||
@@ -20,12 +19,12 @@ export const dispatchNetworkErrorMessageToUser = (message: any) => {
|
||||
/*
|
||||
Catch unexpected errors and make sure we don't lose them!
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
export function catchErrorsWrap(fn: any, dispatchToUser = false) {
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
return (dispatch: any, getState: any) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
fn(dispatch, getState).catch((error: any) => {
|
||||
export function catchErrorsWrap(
|
||||
fn: (dispatch: AppDispatch, getState: () => RootState) => Promise<void>,
|
||||
dispatchToUser = false
|
||||
) {
|
||||
return (dispatch: AppDispatch, getState: () => RootState): void => {
|
||||
fn(dispatch, getState).catch((error: Error) => {
|
||||
console.error(error);
|
||||
if (dispatchToUser) {
|
||||
dispatchNetworkErrorMessageToUser(error.message);
|
||||
@@ -39,8 +38,10 @@ export function catchErrorsWrap(fn: any, dispatchToUser = false) {
|
||||
* Wrapper to perform async fetch with some modest error handling
|
||||
* and decoding. Arguments are identical to standard fetch.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
export const doFetch = async (url: any, init = {}) => {
|
||||
export const doFetch = async (
|
||||
url: string,
|
||||
init?: RequestInit
|
||||
): Promise<Response> => {
|
||||
try {
|
||||
// add defaults to the fetch init param.
|
||||
init = {
|
||||
@@ -48,13 +49,11 @@ export const doFetch = async (url: any, init = {}) => {
|
||||
credentials: "include",
|
||||
...init,
|
||||
};
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
const acceptType = (init as any).headers?.get("Accept");
|
||||
const acceptType = (init.headers as Headers)?.get("Accept");
|
||||
const res = await fetch(url, init);
|
||||
if (
|
||||
res.ok &&
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
(!acceptType || res.headers.get("Content-Type").includes(acceptType))
|
||||
(!acceptType || res.headers?.get("Content-Type")?.includes(acceptType))
|
||||
) {
|
||||
return res;
|
||||
}
|
||||
@@ -74,8 +73,10 @@ export const doFetch = async (url: any, init = {}) => {
|
||||
/*
|
||||
Wrapper to perform an async fetch and JSON decode response.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
export const doJsonRequest = async (url: any, init = {}) => {
|
||||
export const doJsonRequest = async <T = unknown>(
|
||||
url: string,
|
||||
init?: RequestInit
|
||||
): Promise<T> => {
|
||||
const res = await doFetch(url, {
|
||||
...init,
|
||||
headers: new Headers({ Accept: "application/json" }),
|
||||
@@ -86,8 +87,10 @@ export const doJsonRequest = async (url: any, init = {}) => {
|
||||
/*
|
||||
Wrapper to perform an async fetch for binary data.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
export const doBinaryRequest = async (url: any, init = {}) => {
|
||||
export const doBinaryRequest = async (
|
||||
url: string,
|
||||
init?: RequestInit
|
||||
): Promise<ArrayBuffer> => {
|
||||
const res = await doFetch(url, {
|
||||
...init,
|
||||
headers: new Headers({ Accept: "application/octet-stream" }),
|
||||
@@ -110,13 +113,11 @@ Parameters:
|
||||
|
||||
So [1, 2, 3, 4, 10, 11, 14] -> [ [1, 4], [10, 11], 14]
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
||||
export const rangeEncodeIndices = (
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
indices: any,
|
||||
indices: Array<number>,
|
||||
minRangeLength = 3,
|
||||
sorted = false
|
||||
) => {
|
||||
): Array<number | [number, number]> => {
|
||||
if (indices.length === 0) {
|
||||
return indices;
|
||||
}
|
||||
|
||||
+31
-39
@@ -1,4 +1,5 @@
|
||||
import { vec2, mat3 } from "gl-matrix";
|
||||
import clamp from "./clamp";
|
||||
|
||||
const EPSILON = 0.000001;
|
||||
|
||||
@@ -11,56 +12,49 @@ const panBound = 0.8;
|
||||
const scratch0 = new Float32Array(16);
|
||||
const scratch1 = new Float32Array(16);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
function clamp(val: any, rng: any) {
|
||||
return Math.max(Math.min(val, rng[1]), rng[0]);
|
||||
}
|
||||
|
||||
class Camera {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
canvas: any;
|
||||
canvas: HTMLCanvasElement;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
prevEvent: any;
|
||||
prevEvent: {
|
||||
clientX: number;
|
||||
clientY: number;
|
||||
type: string;
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
viewMatrix: any;
|
||||
viewMatrix: mat3;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
viewMatrixInv: any;
|
||||
viewMatrixInv: mat3;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
constructor(canvas: any) {
|
||||
constructor(canvas: HTMLCanvasElement) {
|
||||
this.prevEvent = {
|
||||
clientX: 0,
|
||||
clientY: 0,
|
||||
type: 0,
|
||||
type: "",
|
||||
};
|
||||
this.canvas = canvas;
|
||||
this.viewMatrix = mat3.create();
|
||||
this.viewMatrixInv = mat3.create();
|
||||
}
|
||||
|
||||
view() {
|
||||
view(): mat3 {
|
||||
return this.viewMatrix;
|
||||
}
|
||||
|
||||
invView() {
|
||||
invView(): mat3 {
|
||||
return this.viewMatrixInv;
|
||||
}
|
||||
|
||||
distance() {
|
||||
distance(): number {
|
||||
return this.viewMatrix[0];
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
pan(dx: any, dy: any) {
|
||||
pan(dx: number, dy: number): void {
|
||||
const m = this.viewMatrix;
|
||||
const dyRange = [
|
||||
const dyRange: [number, number] = [
|
||||
-panBound - (m[7] + 1) / m[4],
|
||||
panBound - (m[7] - 1) / m[4],
|
||||
];
|
||||
const dxRange = [
|
||||
const dxRange: [number, number] = [
|
||||
-panBound - (m[6] + 1) / m[0],
|
||||
panBound - (m[6] - 1) / m[0],
|
||||
];
|
||||
@@ -74,13 +68,12 @@ class Camera {
|
||||
mat3.invert(this.viewMatrixInv, m);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
zoomAt(d: any, x = 0, y = 0) {
|
||||
zoomAt(d: number, x = 0, y = 0): void {
|
||||
/*
|
||||
Camera zoom at [x,y]
|
||||
*/
|
||||
const m = this.viewMatrix;
|
||||
const bounds = [-panBound, panBound];
|
||||
const bounds: [number, number] = [-panBound, panBound];
|
||||
x = clamp(x, bounds);
|
||||
y = clamp(y, bounds);
|
||||
|
||||
@@ -98,15 +91,18 @@ class Camera {
|
||||
Event handling
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
flush(e: any) {
|
||||
flush(e: MouseEvent) {
|
||||
this.prevEvent.type = e.type;
|
||||
this.prevEvent.clientX = e.clientX;
|
||||
this.prevEvent.clientY = e.clientY;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
localPosition(target: any, canvasX: any, canvasY: any, projectionInvTF: any) {
|
||||
localPosition(
|
||||
target: HTMLCanvasElement,
|
||||
canvasX: number,
|
||||
canvasY: number,
|
||||
projectionInvTF: mat3
|
||||
): vec2 {
|
||||
/*
|
||||
Convert mouse position to local
|
||||
*/
|
||||
@@ -126,8 +122,7 @@ class Camera {
|
||||
return pos;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
mousePan(e: any, projectionTF: any) {
|
||||
mousePan(e: MouseEvent, projectionTF: mat3): true {
|
||||
const projectionInvTF = mat3.invert(scratch0, projectionTF);
|
||||
const pos = this.localPosition(
|
||||
this.canvas,
|
||||
@@ -147,8 +142,7 @@ class Camera {
|
||||
return true;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
wheelZoom(e: any, projectionTF: any) {
|
||||
wheelZoom(e: WheelEvent, projectionTF: mat3): true {
|
||||
const { height } = this.canvas;
|
||||
const { deltaY, deltaMode, clientX, clientY } = e;
|
||||
const scale = scaleSpeed * (deltaMode === 1 ? 12 : 1) * (deltaY || 0);
|
||||
@@ -164,8 +158,7 @@ class Camera {
|
||||
return true;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
handleEvent(e: any, projectionTF: any) {
|
||||
handleEvent(e: MouseEvent, projectionTF: mat3): boolean {
|
||||
/*
|
||||
process the event, and return true if camera view changed
|
||||
*/
|
||||
@@ -181,7 +174,7 @@ class Camera {
|
||||
}
|
||||
|
||||
case "wheel": {
|
||||
viewChanged = this.wheelZoom(e, projectionTF);
|
||||
viewChanged = this.wheelZoom(e as WheelEvent, projectionTF);
|
||||
this.flush(e);
|
||||
break;
|
||||
}
|
||||
@@ -194,8 +187,7 @@ class Camera {
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
function attachCamera(canvas: any) {
|
||||
function attachCamera(canvas: HTMLCanvasElement): Camera {
|
||||
return new Camera(canvas);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,24 +11,23 @@ TL;DR: sort order is:
|
||||
import isNumber from "is-number";
|
||||
import * as globals from "../globals";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
function caseInsensitiveCompare(a: any, b: any) {
|
||||
function caseInsensitiveCompare(a: string, b: string): number {
|
||||
const textA = String(a).toUpperCase();
|
||||
const textB = String(b).toUpperCase();
|
||||
return textA < textB ? -1 : textA > textB ? 1 : 0;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
const catLabelSort = (isUserAnno: boolean, values: any[]): any[] => {
|
||||
const catLabelSort = (
|
||||
isUserAnno: boolean,
|
||||
values: Array<string>
|
||||
): Array<string> => {
|
||||
/* this sort could be memoized for perf */
|
||||
|
||||
const strings: string[] = [];
|
||||
const ints: number[] = [];
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
const unassignedOrNaN: any = [];
|
||||
const ints: string[] = [];
|
||||
const unassignedOrNaN: string[] = [];
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
values.forEach((v: any) => {
|
||||
values.forEach((v: string) => {
|
||||
if (isUserAnno && v === globals.unassignedCategoryLabel) {
|
||||
unassignedOrNaN.push(v);
|
||||
} else if (String(v).toLowerCase() === "nan") {
|
||||
@@ -44,8 +43,7 @@ const catLabelSort = (isUserAnno: boolean, values: any[]): any[] => {
|
||||
ints.sort((a, b) => +a - +b);
|
||||
unassignedOrNaN.sort(caseInsensitiveCompare);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
return (<any>ints).concat(strings, unassignedOrNaN);
|
||||
return ints.concat(strings, unassignedOrNaN);
|
||||
};
|
||||
|
||||
export default catLabelSort;
|
||||
|
||||
@@ -26,8 +26,7 @@ label -> {
|
||||
const getCoordinatesByLabel = (
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
schema: any,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
categoryName: any,
|
||||
categoryName: string,
|
||||
categoryDf: Dataframe,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
layoutChoice: any,
|
||||
@@ -73,7 +72,7 @@ const getCoordinatesByLabel = (
|
||||
let coords = coordsByCategoryLabel.get(label);
|
||||
if (coords === undefined) {
|
||||
// Get the number of cells which are in the label
|
||||
// @ts-expect-error ts-migrate(2538) FIXME: Type 'unknown' cannot be used as an index type.
|
||||
// @ts-expect-error ts-migrate(2538) FIXME: Blocked by StateManager/ControlsHelpers
|
||||
const numInLabel = categoryValueCounts[labelIndex];
|
||||
coords = {
|
||||
hasFinite: false,
|
||||
@@ -99,7 +98,7 @@ const getCoordinatesByLabel = (
|
||||
return coordsByCategoryLabel;
|
||||
};
|
||||
|
||||
/*
|
||||
/*
|
||||
calcMedianCentroid calculates the median coordinates for labels in a given category
|
||||
|
||||
label -> [x-Coordinate, y-Coordinate]
|
||||
@@ -108,8 +107,7 @@ const getCoordinatesByLabel = (
|
||||
const calcMedianCentroid = (
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
schema: any,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
categoryName: any,
|
||||
categoryName: string,
|
||||
categoryDf: Dataframe,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
layoutChoice: any,
|
||||
@@ -151,8 +149,7 @@ const hashMedianCentroid = (
|
||||
// @ts-expect-error ts-migrate(6133) FIXME: 'schema' is declared but its value is never read.
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
schema: any,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
categoryName: any,
|
||||
categoryName: string,
|
||||
categoryDf: Dataframe,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
layoutChoice: any,
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
* @returns a number
|
||||
*/
|
||||
|
||||
// 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 clamp(val: any, rng: any) {
|
||||
export default function clamp(val: number, rng: [number, number]): number {
|
||||
return Math.max(Math.min(val, rng[1]), rng[0]);
|
||||
}
|
||||
|
||||
+10
-4
@@ -1,17 +1,23 @@
|
||||
import { NumberArray } from "../common/types/arraytypes";
|
||||
|
||||
/*
|
||||
clip - clip all values in a Array or TypedArray, IN PLACE.
|
||||
|
||||
Values in array are clipped if less than `lower` or greater than `upper`.
|
||||
|
||||
If `setTo` is undefined, values less than `lower` will be set to `lower`,
|
||||
and values greater than `upper` will be set to `upper`.
|
||||
and values greater than `upper` will be set to `upper`.
|
||||
|
||||
If `setTo` is not undefined, values outside the [lower, upper] range will be set to
|
||||
If `setTo` is not undefined, values outside the [lower, upper] range will be set to
|
||||
`setTo`.
|
||||
|
||||
*/
|
||||
// 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 clip(arr: any, lower: any, upper: any, setTo: any) {
|
||||
export default function clip(
|
||||
arr: NumberArray,
|
||||
lower: number,
|
||||
upper: number,
|
||||
setTo?: number
|
||||
): NumberArray {
|
||||
const lowerSet = setTo === undefined ? lower : setTo;
|
||||
const upperSet = setTo === undefined ? upper : setTo;
|
||||
for (let i = 0, l = arr.length; i < l; i += 1) {
|
||||
|
||||
@@ -6,8 +6,11 @@ If undefined or empty array, or array contains only non-finite numbers,
|
||||
will return [undefined, undefined]
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
function finiteExtent(tarr: any) {
|
||||
import type { TypedArray } from "../common/types/arraytypes";
|
||||
|
||||
function finiteExtent(
|
||||
tarr: TypedArray
|
||||
): [number, number] | [undefined, undefined] {
|
||||
let min;
|
||||
let max;
|
||||
let i;
|
||||
@@ -21,14 +24,17 @@ function finiteExtent(tarr: any) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (; i < tarr.length; i += 1) {
|
||||
const val = tarr[i];
|
||||
if (Number.isFinite(val)) {
|
||||
if (min > val) min = val;
|
||||
if (max < val) max = val;
|
||||
if (min !== undefined && max !== undefined) {
|
||||
for (; i < tarr.length; i += 1) {
|
||||
const val = tarr[i];
|
||||
if (Number.isFinite(val)) {
|
||||
if (min > val) min = val;
|
||||
if (max < val) max = val;
|
||||
}
|
||||
}
|
||||
return [min, max];
|
||||
}
|
||||
return [min, max];
|
||||
return [undefined, undefined];
|
||||
}
|
||||
|
||||
export default finiteExtent;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ScaleLinear } from "d3";
|
||||
import significantDigits from "./significantDigits";
|
||||
|
||||
/**
|
||||
@@ -10,14 +11,14 @@ import significantDigits from "./significantDigits";
|
||||
* @returns - the number formatted as scientific, if it's big enough
|
||||
*/
|
||||
|
||||
// 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 maybeScientific(x: any) {
|
||||
export default function maybeScientific(
|
||||
x: ScaleLinear<number, number, never>
|
||||
): string {
|
||||
let format = ",";
|
||||
const _ticks = x.ticks(4);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
if (x.domain().some((n: any) => Math.abs(n) >= 10000)) {
|
||||
/*
|
||||
if (x.domain().some((n: number) => Math.abs(n) >= 10000)) {
|
||||
/*
|
||||
heuristic: if the last tick d3 wants to render has one significant
|
||||
digit ie., 2000, render 2e+3, but if it's anything else ie., 42000000 render
|
||||
4.20e+n
|
||||
|
||||
@@ -13,43 +13,40 @@ anno matrix namespaces. It is still used by the component tier.
|
||||
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
const makeDimensionName = (namespace: any, key: any) => `${namespace}_${key}`;
|
||||
const makeDimensionName = (namespace: string, key: string): string =>
|
||||
`${namespace}_${key}`;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
export const layoutDimensionName = (key: any) =>
|
||||
export const layoutDimensionName = (key: string): string =>
|
||||
makeDimensionName("layout", key);
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
export const obsAnnoDimensionName = (key: any) =>
|
||||
|
||||
export const obsAnnoDimensionName = (key: string): string =>
|
||||
makeDimensionName("obsAnno", key);
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
export const diffexpDimensionName = (key: any) =>
|
||||
|
||||
export const diffexpDimensionName = (key: string): string =>
|
||||
makeDimensionName("varData_diffexp", key);
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
export const userDefinedDimensionName = (key: any) =>
|
||||
|
||||
export const userDefinedDimensionName = (key: string): string =>
|
||||
makeDimensionName("varData_userDefined", key);
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
export const geneSetSummaryDimensionName = (key: any) =>
|
||||
|
||||
export const geneSetSummaryDimensionName = (key: string): string =>
|
||||
makeDimensionName("geneSetSummary", key);
|
||||
|
||||
export interface ContinuousNamespace {
|
||||
isObs?: boolean;
|
||||
isDiffExp?: boolean;
|
||||
isUserDefined?: boolean;
|
||||
isGeneSetSummary?: boolean;
|
||||
}
|
||||
|
||||
/*
|
||||
continuousNamespace = {
|
||||
isObs: true,
|
||||
isDiffExp: false,
|
||||
isUserDefined: false,
|
||||
isGeneSet: false,
|
||||
}
|
||||
|
||||
ie., makeContinuousDimensionName(continuousNamespace = {isObs: true}, "total_reads")
|
||||
see: histogram brush, as it doesn't know what type of continuous it was with only field
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
||||
export const makeContinuousDimensionName = (
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
continuousNamespace: any,
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
key: any
|
||||
) => {
|
||||
continuousNamespace: ContinuousNamespace,
|
||||
key: string
|
||||
): string => {
|
||||
let name;
|
||||
if (continuousNamespace.isObs) {
|
||||
name = obsAnnoDimensionName(key);
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
import pull from "lodash.pull";
|
||||
import uniq from "lodash.uniq";
|
||||
|
||||
// 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 parseBulkGeneString(geneString: any) {
|
||||
export default function parseBulkGeneString(geneString: string): Array<string> {
|
||||
return pull(uniq(geneString.split(/[ ,]+/)), "");
|
||||
}
|
||||
|
||||
@@ -4,32 +4,27 @@ import scaleRGB from "./scaleRGB";
|
||||
// to do this operation. This lets us have speed, but keep the pleasant ability
|
||||
// to talk about colors by their text description eg, 'rgb(0,0,1)'
|
||||
//
|
||||
const colorCache = {};
|
||||
const colorCache = {} as { [key: string]: [number, number, number] };
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
function parseColorName(c: any) {
|
||||
function parseColorName(c: string): [number, number, number] {
|
||||
if (c[0] !== "#") {
|
||||
const _c = c.replace(/[^\d,.]/g, "").split(",");
|
||||
return [scaleRGB(+_c[0]), scaleRGB(+_c[1]), scaleRGB(+_c[2])];
|
||||
}
|
||||
const parsedHex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(c);
|
||||
if (!parsedHex || parsedHex.length < 4)
|
||||
throw new Error(`Invalid hex color: ${c}`);
|
||||
return [
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
scaleRGB(parseInt(parsedHex[1], 16)),
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
scaleRGB(parseInt(parsedHex[2], 16)),
|
||||
// @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
|
||||
scaleRGB(parseInt(parsedHex[3], 16)),
|
||||
];
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
export default (c: any) => {
|
||||
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
|
||||
export default (c: string): [number, number, number] => {
|
||||
let cv = colorCache[c];
|
||||
if (!cv) {
|
||||
cv = parseColorName(c);
|
||||
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
|
||||
colorCache[c] = cv;
|
||||
}
|
||||
return cv;
|
||||
|
||||
@@ -28,37 +28,55 @@ Priority is a numeric value. Lower first. Stable ordering.
|
||||
|
||||
import TinyQueue from "tinyqueue";
|
||||
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'a' implicitly has an 'any' type.
|
||||
function compare(a, b) {
|
||||
function compare<T>(
|
||||
a: PromiseLimitQueueItem<T>,
|
||||
b: PromiseLimitQueueItem<T>
|
||||
): number {
|
||||
const diff = a.priority - b.priority;
|
||||
if (diff) return diff;
|
||||
return a.order - b.order;
|
||||
}
|
||||
|
||||
export default class PromiseLimit {
|
||||
interface PromiseLimitQueueItem<T> {
|
||||
priority: number;
|
||||
order: number;
|
||||
resolve: (value: T | PromiseLike<T>) => void;
|
||||
reject: (reason?: unknown) => void;
|
||||
fn: (...args: Array<unknown>) => Promise<T>;
|
||||
args: Array<unknown>;
|
||||
}
|
||||
|
||||
export default class PromiseLimit<T> {
|
||||
queue: TinyQueue<PromiseLimitQueueItem<T>>;
|
||||
|
||||
maxConcurrency: number;
|
||||
|
||||
pending: number;
|
||||
|
||||
insertCounter: number;
|
||||
|
||||
constructor(maxConcurrency = 5) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
(this as any).queue = new TinyQueue([], compare);
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
(this as any).maxConcurrency = maxConcurrency;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
(this as any).pending = 0;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
(this as any).insertCounter = 0;
|
||||
this.queue = new TinyQueue<PromiseLimitQueueItem<T>>(
|
||||
new Array<PromiseLimitQueueItem<T>>(),
|
||||
compare
|
||||
);
|
||||
this.maxConcurrency = maxConcurrency;
|
||||
this.pending = 0;
|
||||
this.insertCounter = 0;
|
||||
}
|
||||
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'p' implicitly has an 'any' type.
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
||||
priorityAdd(p, fn, ...args) {
|
||||
priorityAdd(
|
||||
p: number,
|
||||
fn: () => Promise<T>,
|
||||
...args: Array<unknown>
|
||||
): Promise<T> {
|
||||
// p - numermic priority (lower first)
|
||||
// fn - must return a promise
|
||||
// args - will be passed to fn
|
||||
return this._push(p, fn, args);
|
||||
}
|
||||
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'fn' implicitly has an 'any' type.
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
||||
add(fn, ...args) {
|
||||
add(fn: () => Promise<T>, ...args: Array<unknown>): Promise<T> {
|
||||
// fn - must return a promise
|
||||
// args - will be passed to fn
|
||||
return this._push(0, fn, args);
|
||||
@@ -68,35 +86,25 @@ export default class PromiseLimit {
|
||||
Private below
|
||||
**/
|
||||
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'priority' implicitly has an 'any' type.
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
||||
_push(priority, fn, args) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
const order = (this as any).insertCount;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
(this as any).insertCount += 1;
|
||||
_push(
|
||||
priority: number,
|
||||
fn: () => Promise<T>,
|
||||
args: Array<unknown>
|
||||
): Promise<T> {
|
||||
const order = this.insertCounter;
|
||||
this.insertCounter += 1;
|
||||
return new Promise((resolve, reject) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
(this as any).queue.push({ priority, order, fn, args, resolve, reject });
|
||||
this.queue.push({ priority, order, fn, args, resolve, reject });
|
||||
this._resolveNext(false);
|
||||
});
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
||||
_resolveNext = (completed = true) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
if (completed) (this as any).pending -= 1;
|
||||
_resolveNext = (completed = true): void => {
|
||||
if (completed) this.pending -= 1;
|
||||
|
||||
while (
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
(this as any).queue.length > 0 &&
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
(this as any).pending < (this as any).maxConcurrency
|
||||
) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
const task = (this as any).queue.pop(); // order of insertion
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
(this as any).pending += 1;
|
||||
while (this.queue.length > 0 && this.pending < this.maxConcurrency) {
|
||||
const task = this.queue.pop() as PromiseLimitQueueItem<T>; // order of insertion
|
||||
this.pending += 1;
|
||||
const { resolve, reject, fn, args } = task;
|
||||
|
||||
try {
|
||||
|
||||
+21
-15
@@ -22,38 +22,44 @@ rangeFill(array, start, step) -> array
|
||||
|
||||
*/
|
||||
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'arr' implicitly has an 'any' type.
|
||||
function _doFill(arr, start, step, count) {
|
||||
import { TypedArray, NumberArray } from "../common/types/arraytypes";
|
||||
|
||||
function _doFill<T extends NumberArray>(
|
||||
arr: T,
|
||||
start: number,
|
||||
step: number,
|
||||
count: number
|
||||
): T {
|
||||
for (let idx = 0, val = start; idx < count; idx += 1, val += step) {
|
||||
arr[idx] = val;
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'arr' implicitly has an 'any' type.
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
||||
export function rangeFill(arr, start = 0, step = 1) {
|
||||
export function rangeFill(arr: NumberArray, start = 0, step = 1): NumberArray {
|
||||
return _doFill(arr, start, step, arr.length);
|
||||
}
|
||||
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'start' implicitly has an 'any' type.
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
||||
export function range(start, stop, step) {
|
||||
export function range(
|
||||
start: number,
|
||||
stop?: number,
|
||||
step?: number
|
||||
): Array<number> {
|
||||
if (start === undefined) return [];
|
||||
if (stop === undefined) {
|
||||
stop = start;
|
||||
start = 0;
|
||||
}
|
||||
step = step || 1; // catch undefind and zero
|
||||
step = step || 1; // catch undefined and zero
|
||||
const len = Math.max(Math.ceil((stop - start) / step), 0);
|
||||
return _doFill(new Array(len), start, step, len);
|
||||
}
|
||||
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'start' implicitly has an 'any' type.
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
|
||||
export function linspace(start, stop, nsteps) {
|
||||
// @ts-expect-error ts-migrate(2363) FIXME: The right-hand side of an arithmetic operation mus... Remove this comment to see the full error message
|
||||
const delta = (stop - start) / (nsteps - 1).toFixed();
|
||||
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'i' implicitly has an 'any' type.
|
||||
export function linspace(
|
||||
start: number,
|
||||
stop: number,
|
||||
nsteps: number
|
||||
): Array<number> {
|
||||
const delta = (stop - start) / Number((nsteps - 1).toFixed());
|
||||
return range(0, nsteps, 1).map((i) => start + i * delta);
|
||||
}
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
// 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 renderThrottle(callback: any) {
|
||||
export default function renderThrottle<T>(
|
||||
callback: (this: T) => void
|
||||
): (this: T) => void {
|
||||
/*
|
||||
This wraps a call to requestAnimationFrame(), enforcing a single
|
||||
render callback at any given time (ie, you can call this any number
|
||||
of times, and it will coallesce multiple inter-frame calls into a
|
||||
single render).
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
let rafCurrentlyInProgress: any = null;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
return function f(this: any) {
|
||||
if (rafCurrentlyInProgress) return;
|
||||
// eslint-disable-next-line @typescript-eslint/no-this-alias --- FIXME: disabled temporarily on migrate to TS.
|
||||
const context = this;
|
||||
let rafCurrentlyInProgress: number | null = null;
|
||||
return function f(this: T) {
|
||||
if (rafCurrentlyInProgress) return; // eslint-disable-next-line @typescript-eslint/no-this-alias --- required for functionality
|
||||
rafCurrentlyInProgress = window.requestAnimationFrame(() => {
|
||||
callback.apply(context);
|
||||
callback.call<T, never, void>(this);
|
||||
rafCurrentlyInProgress = null;
|
||||
});
|
||||
};
|
||||
|
||||
@@ -6,18 +6,18 @@
|
||||
// myScale(0) === -1
|
||||
// this is is equivalent to d3.scaleLinear().domain([0,1]).range([-1,1])
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
export default (domain: any, range: any) => {
|
||||
export default (
|
||||
domain: [number, number],
|
||||
range: [number, number]
|
||||
): ((value: number) => number) => {
|
||||
const domainStart = domain[0];
|
||||
const scale = (range[1] - range[0]) / (domain[1] - domain[0]);
|
||||
const invScale = 1 / scale;
|
||||
const rangeStart = range[0];
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
const f = (value: any) => (value - domainStart) * scale + rangeStart;
|
||||
const f = (value: number) => (value - domainStart) * scale + rangeStart;
|
||||
|
||||
// inverter
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
|
||||
f.invert = (value: any) => (value - rangeStart) * invScale + domainStart;
|
||||
f.invert = (value: number) => (value - rangeStart) * invScale + domainStart;
|
||||
|
||||
return f;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
export default (input: any) => {
|
||||
export default (input: number): number => {
|
||||
const outputMax = 1;
|
||||
const outputMin = 0;
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
/*
|
||||
/*
|
||||
via https://github.com/nodef/extra-number/blob/master/scripts/significantDigits.js
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
|
||||
export default (n: any) =>
|
||||
const significantDigits = (n: number): number =>
|
||||
n
|
||||
.toExponential()
|
||||
.replace(/e[+\-0-9]*$/, "")
|
||||
.replace(/^0\.?0*|\./, "").length;
|
||||
|
||||
export default significantDigits;
|
||||
|
||||
Reference in New Issue
Block a user