TS Revert (1) (#2402)

* revert all commits to before Typescript migration

* update compat workflow to match latest deps (#2335)

* update compat workflow to match latest deps

* attempt to debug

* attempt to debug

* remove debugging code

* typo

* update deps to match desktop (#2340)

* fix: don't run lint with `--fix` on push tests (#2273)

* fix: don't run lint with `--fix` on push tests

* npx

Co-authored-by: maniarathi <mani.arathi@gmail.com>
Co-authored-by: Madison Dunitz <madison.dunitz@chanzuckerberg.com>

* rename X_approx_distribution to X_approximate_distribution (#2337)

* Correctly handle non-finite numbers in heuristic determination of X distribution (#2342)

* handle non-finites explicitly

* improve and test edge case handling for distribution estimation

* revert debugging changes

* code readability

* clean up type inferencing (#2332)

* unit tests for 64 bit conversion

* clean up type handling

* type inference tests

* more type inference fixes

* use schema to determine user intent for data typing

* stop using deprecated API

* fbs type encoding test

* add missing test

* add more tests

* correctly infer X type for CXG adaptor

* lint

* fix typo

* ts migration

* cleanup from PR review

* lint

* PR review changes

* remove unused packages from client (#2359)

* remove unused packages from client

* add missing peer dep

* fix: disable FE auth testing on compatibility tests (#2377)

* update: release process (#2277)

Co-authored-by: maniarathi <mani.arathi@gmail.com>

* fix: remove spaces in param setup (#2380)

* delete deploy workflow (#2396)

* undo reformatting which now does not pass lint

* fix snapshots which changed due to npm dep changes

* add missing quoting to snapshot

* another snapshot typo fix

* TS Revert (2) - replay PR #2347 and #2354 (#2403)

* replay edits from PR 2347

* TS Revert (3) - replay edits in PR #2327 (#2404)

* replay edits in PR 2327

* TS Revert (4) - replay PR #2355 (#2405)

* replay edits in PR 2355

* add additional babel config

* reformat with new prettier config

Co-authored-by: Severiano Badajoz <sbadajoz@chanzuckerberg.com>
Co-authored-by: maniarathi <mani.arathi@gmail.com>
Co-authored-by: Madison Dunitz <madison.dunitz@chanzuckerberg.com>
This commit is contained in:
Bruce Martin
2021-08-23 15:01:36 -07:00
committed by GitHub
co-authored by maniarathi Madison Dunitz Severiano Badajoz
parent 295590a7c6
commit eaae6df5e3
253 changed files with 11175 additions and 22271 deletions
@@ -1,7 +1,6 @@
import { glPointFlags, glPointSize } from "../../util/glHelpers";
// 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 drawPointsRegl(regl: any) {
export default function drawPointsRegl(regl) {
return regl({
vert: `
precision mediump float;
@@ -26,7 +26,6 @@ import {
flagSelected,
flagHighlight,
} from "../../util/glHelpers";
import { Dataframe } from "../../util/dataframe";
/*
Simple 2D transforms control all point painting. There are three:
@@ -35,8 +34,7 @@ Simple 2D transforms control all point painting. There are three:
* camera - apply a 2D camera transformation (pan, zoom)
* projection - apply any transformation required for screen size and layout
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
function createProjectionTF(viewportWidth: any, viewportHeight: any) {
function createProjectionTF(viewportWidth, viewportHeight) {
/*
the projection transform accounts for the screen size & other layout
*/
@@ -55,7 +53,6 @@ function createProjectionTF(viewportWidth: any, viewportHeight: any) {
0,
(bottomGutterSizePx - topGutterSizePx) / viewportHeight / aspectScale[1],
]);
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type 'number[]' is not assignable to p... Remove this comment to see the full error message
mat3.scale(m, m, aspectScale);
return m;
}
@@ -70,48 +67,32 @@ function createModelTF() {
return m;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
type GraphState = any;
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state) => ({
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
annoMatrix: (state as any).annoMatrix,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
crossfilter: (state as any).obsCrossfilter,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
selectionTool: (state as any).graphSelection.tool,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
currentSelection: (state as any).graphSelection.selection,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
layoutChoice: (state as any).layoutChoice,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
graphInteractionMode: (state as any).controls.graphInteractionMode,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
colors: (state as any).colors,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
pointDilation: (state as any).pointDilation,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
genesets: (state as any).genesets.genesets,
annoMatrix: state.annoMatrix,
crossfilter: state.obsCrossfilter,
selectionTool: state.graphSelection.tool,
currentSelection: state.graphSelection.selection,
layoutChoice: state.layoutChoice,
graphInteractionMode: state.controls.graphInteractionMode,
colors: state.colors,
pointDilation: state.pointDilation,
genesets: state.genesets.genesets,
}))
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
class Graph extends React.Component<{}, GraphState> {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
static createReglState(canvas: any) {
class Graph extends React.Component {
static createReglState(canvas) {
/*
Must be created for each canvas
*/
Must be created for each canvas
*/
// setup canvas, webgl draw function and camera
const camera = _camera(canvas);
const regl = _regl(canvas);
const drawPoints = _drawPoints(regl);
// preallocate webgl buffers
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
const pointBuffer = regl.buffer();
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
const colorBuffer = regl.buffer();
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
const flagBuffer = regl.buffer();
return {
camera,
regl,
@@ -122,21 +103,14 @@ class Graph extends React.Component<{}, GraphState> {
};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
static watchAsync(props: any, prevProps: any) {
static watchAsync(props, prevProps) {
return !shallowEqual(props.watchProps, prevProps.watchProps);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
cachedAsyncProps: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
reglCanvas: any;
computePointPositions = memoize((X, Y, modelTF) => {
/*
compute the model coordinate for each point
*/
compute the model coordinate for each point
*/
const positions = new Float32Array(2 * X.length);
for (let i = 0, len = X.length; i < len; i += 1) {
const p = vec2.fromValues(X[i], Y[i]);
@@ -149,8 +123,8 @@ class Graph extends React.Component<{}, GraphState> {
computePointColors = memoize((rgb) => {
/*
compute webgl colors for each point
*/
compute webgl colors for each point
*/
const colors = new Float32Array(3 * rgb.length);
for (let i = 0, len = rgb.length; i < len; i += 1) {
colors.set(rgb[i], 3 * i);
@@ -199,20 +173,21 @@ class Graph extends React.Component<{}, GraphState> {
computePointFlags = memoize(
(crossfilter, colorByData, pointDilationData, pointDilationLabel) => {
/*
We communicate with the shader using three flags:
- isNaN -- the value is a NaN. Only makes sense when we have a colorAccessor
- isSelected -- the value is selected
- isHightlighted -- the value is highlighted in the UI (orthogonal from selection highlighting)
Due to constraints in webgl vertex shader attributes, these are encoded in a float, "kinda"
like bitmasks.
We also have separate code paths for generating flags for categorical and
continuous metadata, as they rely on different tests, and some of the flags
(eg, isNaN) are meaningless in the face of categorical metadata.
*/
We communicate with the shader using three flags:
- isNaN -- the value is a NaN. Only makes sense when we have a colorAccessor
- isSelected -- the value is selected
- isHightlighted -- the value is highlighted in the UI (orthogonal from selection highlighting)
Due to constraints in webgl vertex shader attributes, these are encoded in a float, "kinda"
like bitmasks.
We also have separate code paths for generating flags for categorical and
continuous metadata, as they rely on different tests, and some of the flags
(eg, isNaN) are meaningless in the face of categorical metadata.
*/
const nObs = crossfilter.size();
const flags = new Float32Array(nObs);
const selectedFlags = this.computeSelectedFlags(
crossfilter,
flagSelected,
@@ -224,15 +199,16 @@ class Graph extends React.Component<{}, GraphState> {
pointDilationLabel
);
const colorByFlags = this.computeColorByFlags(nObs, colorByData);
for (let i = 0; i < nObs; i += 1) {
flags[i] = selectedFlags[i] + highlightFlags[i] + colorByFlags[i];
}
return flags;
}
);
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
constructor(props: {}) {
constructor(props) {
super(props);
const viewport = this.getViewportDimensions();
this.reglCanvas = null;
@@ -243,18 +219,20 @@ class Graph extends React.Component<{}, GraphState> {
tool: null,
container: null,
viewport,
// projection
camera: null,
modelTF,
// @ts-expect-error ts-migrate(2345) FIXME: Argument of type '[]' is not assignable to paramet... Remove this comment to see the full error message
modelInvTF: mat3.invert([], modelTF),
projectionTF: createProjectionTF(viewport.width, viewport.height),
// regl state
regl: null,
drawPoints: null,
pointBuffer: null,
colorBuffer: null,
flagBuffer: null,
// component rendering derived state - these must stay synchronized
// with the reducer state they were generated from.
layoutState: {
@@ -273,32 +251,23 @@ class Graph extends React.Component<{}, GraphState> {
};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
componentDidMount() {
window.addEventListener("resize", this.handleResize);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
componentDidUpdate(prevProps: {}, prevState: GraphState) {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'selectionTool' does not exist on type 'R... Remove this comment to see the full error message
selectionTool,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'currentSelection' does not exist on type 'R... Remove this comment to see the full error message
currentSelection,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'graphInteractionMode' does not exist on type 'R... Remove this comment to see the full error message
graphInteractionMode,
} = this.props;
componentDidUpdate(prevProps, prevState) {
const { selectionTool, currentSelection, graphInteractionMode } =
this.props;
const { toolSVG, viewport } = this.state;
const hasResized =
prevState.viewport.height !== viewport.height ||
prevState.viewport.width !== viewport.width;
let stateChanges = {};
if (
(viewport.height && viewport.width && !toolSVG) || // first time init
hasResized || // window size has changed we want to recreate all SVGs
// @ts-expect-error ts-migrate(2339) FIXME: Property 'selectionTool' does not exist on type '{... Remove this comment to see the full error message
selectionTool !== prevProps.selectionTool || // change of selection tool
// @ts-expect-error ts-migrate(2339) FIXME: Property 'graphInteractionMode' does not exist on ... Remove this comment to see the full error message
prevProps.graphInteractionMode !== graphInteractionMode // lasso/zoom mode is switched
) {
stateChanges = {
@@ -306,23 +275,19 @@ class Graph extends React.Component<{}, GraphState> {
...this.createToolSVG(),
};
}
/*
if the selection tool or state has changed, ensure that the selection
tool correctly reflects the underlying selection.
*/
if the selection tool or state has changed, ensure that the selection
tool correctly reflects the underlying selection.
*/
if (
// @ts-expect-error ts-migrate(2339) FIXME: Property 'currentSelection' does not exist on type... Remove this comment to see the full error message
currentSelection !== prevProps.currentSelection ||
// @ts-expect-error ts-migrate(2339) FIXME: Property 'graphInteractionMode' does not exist on ... Remove this comment to see the full error message
graphInteractionMode !== prevProps.graphInteractionMode ||
// @ts-expect-error ts-migrate(2339) FIXME: Property 'toolSVG' does not exist on type '{}'.
stateChanges.toolSVG
) {
const { tool, container } = this.state;
this.selectionToolUpdate(
// @ts-expect-error ts-migrate(2339) FIXME: Property 'tool' does not exist on type '{}'.
stateChanges.tool ? stateChanges.tool : tool,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'container' does not exist on type '{}'.
stateChanges.container ? stateChanges.container : container
);
}
@@ -332,12 +297,10 @@ class Graph extends React.Component<{}, GraphState> {
}
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
componentWillUnmount() {
window.removeEventListener("resize", this.handleResize);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleResize = () => {
const { state } = this.state;
const viewport = this.getViewportDimensions();
@@ -349,35 +312,27 @@ class Graph extends React.Component<{}, GraphState> {
});
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleCanvasEvent = (e: any) => {
handleCanvasEvent = (e) => {
const { camera, projectionTF } = this.state;
if (e.type !== "wheel") e.preventDefault();
if (camera.handleEvent(e, projectionTF)) {
this.renderCanvas();
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
this.setState((state: any) => ({
...state,
updateOverlay: !state.updateOverlay,
}));
this.setState((state) => ({ ...state, updateOverlay: !state.updateOverlay }));
}
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleBrushDragAction() {
/*
event describing brush position:
@-------|
| |
| |
|-------@
*/
event describing brush position:
@-------|
| |
| |
|-------@
*/
// ignore programatically generated events
// @ts-expect-error ts-migrate(2339) FIXME: Property 'event' does not exist on type 'typeof im... Remove this comment to see the full error message
if (d3.event.sourceEvent === null || !d3.event.selection) return;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, layoutChoice } = this.props;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'event' does not exist on type 'typeof im... Remove this comment to see the full error message
const s = d3.event.selection;
const northwest = this.mapScreenToPoint(s[0]);
const southeast = this.mapScreenToPoint(s[1]);
@@ -395,28 +350,23 @@ class Graph extends React.Component<{}, GraphState> {
);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleBrushStartAction() {
// Ignore programatically generated events.
// @ts-expect-error ts-migrate(2339) FIXME: Property 'event' does not exist on type 'typeof im... Remove this comment to see the full error message
if (!d3.event.sourceEvent) return;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch } = this.props;
dispatch(actions.graphBrushStartAction());
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleBrushEndAction() {
// Ignore programatically generated events.
// @ts-expect-error ts-migrate(2339) FIXME: Property 'event' does not exist on type 'typeof im... Remove this comment to see the full error message
if (!d3.event.sourceEvent) return;
/*
coordinates will be included if selection made, null
if selection cleared.
*/
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
coordinates will be included if selection made, null
if selection cleared.
*/
const { dispatch, layoutChoice } = this.props;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'event' does not exist on type 'typeof im... Remove this comment to see the full error message
const s = d3.event.selection;
if (s) {
const northwest = this.mapScreenToPoint(s[0]);
@@ -438,27 +388,21 @@ class Graph extends React.Component<{}, GraphState> {
}
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleBrushDeselectAction() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, layoutChoice } = this.props;
dispatch(actions.graphBrushDeselectAction(layoutChoice.current));
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleLassoStart() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, layoutChoice } = this.props;
// @ts-expect-error ts-migrate(2554) FIXME: Expected 0 arguments, but got 1.
dispatch(actions.graphLassoStartAction(layoutChoice.current));
}
// when a lasso is completed, filter to the points within the lasso polygon
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleLassoEnd(polygon: any) {
handleLassoEnd(polygon) {
const minimumPolygonArea = 10;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, layoutChoice } = this.props;
if (
polygon.length < 3 ||
Math.abs(d3.polygonArea(polygon)) < minimumPolygonArea
@@ -469,38 +413,29 @@ class Graph extends React.Component<{}, GraphState> {
dispatch(
actions.graphLassoEndAction(
layoutChoice.current,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
polygon.map((xy: any) => this.mapScreenToPoint(xy))
polygon.map((xy) => this.mapScreenToPoint(xy))
)
);
}
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleLassoCancel() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, layoutChoice } = this.props;
dispatch(actions.graphLassoCancelAction(layoutChoice.current));
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleLassoDeselectAction() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch, layoutChoice } = this.props;
dispatch(actions.graphLassoDeselectAction(layoutChoice.current));
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
handleDeselectAction() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'selectionTool' does not exist on type 'R... Remove this comment to see the full error message
const { selectionTool } = this.props;
if (selectionTool === "brush") this.handleBrushDeselectAction();
if (selectionTool === "lasso") this.handleLassoDeselectAction();
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleOpacityRangeChange(e: any) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
handleOpacityRangeChange(e) {
const { dispatch } = this.props;
dispatch({
type: "change opacity deselected cells in 2d graph background",
@@ -508,17 +443,14 @@ class Graph extends React.Component<{}, GraphState> {
});
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
setReglCanvas = (canvas: any) => {
setReglCanvas = (canvas) => {
this.reglCanvas = canvas;
this.setState({
...Graph.createReglState(canvas),
});
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
getViewportDimensions = () => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'viewportRef' does not exist on type 'Rea... Remove this comment to see the full error message
const { viewportRef } = this.props;
return {
height: viewportRef.clientHeight,
@@ -526,19 +458,19 @@ class Graph extends React.Component<{}, GraphState> {
};
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
createToolSVG = () => {
/*
Called from componentDidUpdate. Create the tool SVG, and return any
state changes that should be passed to setState().
*/
// @ts-expect-error ts-migrate(2339) FIXME: Property 'selectionTool' does not exist on type 'R... Remove this comment to see the full error message
Called from componentDidUpdate. Create the tool SVG, and return any
state changes that should be passed to setState().
*/
const { selectionTool, graphInteractionMode } = this.props;
const { viewport } = this.state;
/* clear out whatever was on the div, even if nothing, but usually the brushes etc */
const lasso = d3.select("#lasso-layer");
if (lasso.empty()) return {}; // still initializing
lasso.selectAll(".lasso-group").remove();
// Don't render or recreate toolSVG if currently in zoom mode
if (graphInteractionMode !== "select") {
// don't return "change" of state unless we are really changing it!
@@ -546,6 +478,7 @@ class Graph extends React.Component<{}, GraphState> {
if (toolSVG === undefined) return {};
return { toolSVG: undefined };
}
let handleStart;
let handleDrag;
let handleEnd;
@@ -559,6 +492,7 @@ class Graph extends React.Component<{}, GraphState> {
handleEnd = this.handleLassoEnd.bind(this);
handleCancel = this.handleLassoCancel.bind(this);
}
const {
svg: newToolSVG,
tool,
@@ -571,11 +505,11 @@ class Graph extends React.Component<{}, GraphState> {
handleCancel,
viewport
);
return { toolSVG: newToolSVG, tool, container };
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
fetchAsyncProps = async (props: any) => {
fetchAsyncProps = async (props) => {
const {
annoMatrix,
colors: colorsProp,
@@ -585,19 +519,24 @@ class Graph extends React.Component<{}, GraphState> {
viewport,
} = props.watchProps;
const { modelTF } = this.state;
const [layoutDf, colorDf, pointDilationDf] = await this.fetchData(
annoMatrix,
layoutChoice,
colorsProp,
pointDilation
);
const { currentDimNames } = layoutChoice;
const X = layoutDf.col(currentDimNames[0]).asArray();
const Y = layoutDf.col(currentDimNames[1]).asArray();
const positions = this.computePointPositions(X, Y, modelTF);
const colorTable = this.updateColorTable(colorsProp, colorDf);
const colors = this.computePointColors(colorTable.rgb);
const colorByData = colorDf?.icol(0)?.asArray();
const { colorAccessor } = colorsProp;
const colorByData = colorDf?.col(colorAccessor)?.asArray();
const {
metadataField: pointDilationCategory,
categoryField: pointDilationLabel,
@@ -611,6 +550,7 @@ class Graph extends React.Component<{}, GraphState> {
pointDilationData,
pointDilationLabel
);
const { width, height } = viewport;
return {
positions,
@@ -621,53 +561,50 @@ class Graph extends React.Component<{}, GraphState> {
};
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
async fetchData(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
annoMatrix: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
layoutChoice: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
colors: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
pointDilation: any
): Promise<[Dataframe, Dataframe | null, Dataframe | null]> {
async fetchData(annoMatrix, layoutChoice, colors, pointDilation) {
/*
fetch all data needed. Includes:
- the color by dataframe
- the layout dataframe
- the point dilation dataframe
*/
fetch all data needed. Includes:
- the color by dataframe
- the layout dataframe
- the point dilation dataframe
*/
const { metadataField: pointDilationAccessor } = pointDilation;
const promises = [];
// layout
promises.push(annoMatrix.fetch("emb", layoutChoice.current));
// color
const query = this.createColorByQuery(colors);
const promises: [
Promise<Dataframe>,
Promise<Dataframe | null>,
Promise<Dataframe | null>
] = [
annoMatrix.fetch("emb", layoutChoice.current),
query ? annoMatrix.fetch(...query) : Promise.resolve(null),
pointDilationAccessor
? annoMatrix.fetch("obs", pointDilationAccessor)
: Promise.resolve(null),
];
if (query) {
promises.push(annoMatrix.fetch(...query));
} else {
promises.push(Promise.resolve(null));
}
// point highlighting
if (pointDilationAccessor) {
promises.push(annoMatrix.fetch("obs", pointDilationAccessor));
} else {
promises.push(Promise.resolve(null));
}
return Promise.all(promises);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
brushToolUpdate(tool: any, container: any) {
brushToolUpdate(tool, container) {
/*
this is called from componentDidUpdate(), so be very careful using
anything from this.state, which may be updated asynchronously.
*/
// @ts-expect-error ts-migrate(2339) FIXME: Property 'currentSelection' does not exist on type... Remove this comment to see the full error message
this is called from componentDidUpdate(), so be very careful using
anything from this.state, which may be updated asynchronously.
*/
const { currentSelection } = this.props;
if (container) {
const toolCurrentSelection = d3.brushSelection(container.node());
if (currentSelection.mode === "within-rect") {
/*
if there is a selection, make sure the brush tool matches
*/
if there is a selection, make sure the brush tool matches
*/
const screenCoords = [
this.mapPointToScreen(currentSelection.brushCoords.northwest),
this.mapPointToScreen(currentSelection.brushCoords.southeast),
@@ -682,7 +619,6 @@ class Graph extends React.Component<{}, GraphState> {
for (let x = 0; x < 2; x += 1) {
for (let y = 0; y < 2; y += 1) {
delta += Math.abs(
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
screenCoords[x][y] - toolCurrentSelection[x][y]
);
}
@@ -698,20 +634,17 @@ class Graph extends React.Component<{}, GraphState> {
}
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
lassoToolUpdate(tool: any) {
lassoToolUpdate(tool) {
/*
this is called from componentDidUpdate(), so be very careful using
anything from this.state, which may be updated asynchronously.
*/
// @ts-expect-error ts-migrate(2339) FIXME: Property 'currentSelection' does not exist on type... Remove this comment to see the full error message
this is called from componentDidUpdate(), so be very careful using
anything from this.state, which may be updated asynchronously.
*/
const { currentSelection } = this.props;
if (currentSelection.mode === "within-polygon") {
/*
if there is a current selection, make sure the lasso tool matches
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const polygon = currentSelection.polygon.map((p: any) =>
if there is a current selection, make sure the lasso tool matches
*/
const polygon = currentSelection.polygon.map((p) =>
this.mapPointToScreen(p)
);
tool.move(polygon);
@@ -720,20 +653,17 @@ class Graph extends React.Component<{}, GraphState> {
}
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
selectionToolUpdate(tool: any, container: any) {
selectionToolUpdate(tool, container) {
/*
this is called from componentDidUpdate(), so be very careful using
anything from this.state, which may be updated asynchronously.
*/
// @ts-expect-error ts-migrate(2339) FIXME: Property 'selectionTool' does not exist on type 'R... Remove this comment to see the full error message
this is called from componentDidUpdate(), so be very careful using
anything from this.state, which may be updated asynchronously.
*/
const { selectionTool } = this.props;
switch (selectionTool) {
case "brush":
this.brushToolUpdate(tool, container);
break;
case "lasso":
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 2.
this.lassoToolUpdate(tool, container);
break;
default:
@@ -742,17 +672,19 @@ class Graph extends React.Component<{}, GraphState> {
}
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
mapScreenToPoint(pin: any) {
mapScreenToPoint(pin) {
/*
Map an XY coordinates from screen domain to cell/point range,
accounting for current pan/zoom camera.
*/
Map an XY coordinates from screen domain to cell/point range,
accounting for current pan/zoom camera.
*/
const { camera, projectionTF, modelInvTF, viewport } = this.state;
const cameraInvTF = camera.invView();
/* screen -> gl */
const x = (2 * pin[0]) / viewport.width - 1;
const y = 2 * (1 - pin[1] / viewport.height) - 1;
const xy = vec2.fromValues(x, y);
const projectionInvTF = mat3.invert(mat3.create(), projectionTF);
vec2.transformMat3(xy, xy, projectionInvTF);
@@ -761,17 +693,19 @@ class Graph extends React.Component<{}, GraphState> {
return xy;
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
mapPointToScreen(xyCell: any) {
mapPointToScreen(xyCell) {
/*
Map an XY coordinate from cell/point domain to screen range. Inverse
of mapScreenToPoint()
*/
Map an XY coordinate from cell/point domain to screen range. Inverse
of mapScreenToPoint()
*/
const { camera, projectionTF, modelTF, viewport } = this.state;
const cameraTF = camera.view();
const xy = vec2.transformMat3(vec2.create(), xyCell, modelTF);
vec2.transformMat3(xy, xy, cameraTF);
vec2.transformMat3(xy, xy, projectionTF);
return [
Math.round(((xy[0] + 1) * viewport.width) / 2),
Math.round(-((xy[1] + 1) / 2 - 1) * viewport.height),
@@ -799,12 +733,12 @@ class Graph extends React.Component<{}, GraphState> {
);
});
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
updateReglAndRender(asyncProps: any, prevAsyncProps: any) {
updateReglAndRender(asyncProps, prevAsyncProps) {
const { positions, colors, flags, height, width } = asyncProps;
this.cachedAsyncProps = asyncProps;
const { pointBuffer, colorBuffer, flagBuffer } = this.state;
let needToRenderCanvas = false;
if (height !== prevAsyncProps?.height || width !== prevAsyncProps?.width) {
needToRenderCanvas = true;
}
@@ -823,11 +757,10 @@ class Graph extends React.Component<{}, GraphState> {
if (needToRenderCanvas) this.renderCanvas();
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
updateColorTable(colors: any, colorDf: any) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message
updateColorTable(colors, colorDf) {
const { annoMatrix } = this.props;
const { schema } = annoMatrix;
/* update color table state */
if (!colors || !colorDf) {
return createColorTable(
@@ -838,6 +771,7 @@ class Graph extends React.Component<{}, GraphState> {
null
);
}
const { colorAccessor, userColors, colorMode } = colors;
return createColorTable(
colorMode,
@@ -848,35 +782,26 @@ class Graph extends React.Component<{}, GraphState> {
);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
createColorByQuery(colors: any) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message
createColorByQuery(colors) {
const { annoMatrix, genesets } = this.props;
const { schema } = annoMatrix;
const { colorMode, colorAccessor } = colors;
return createColorQuery(colorMode, colorAccessor, schema, genesets);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
renderPoints(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
regl: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
drawPoints: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
colorBuffer: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
pointBuffer: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
flagBuffer: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
camera: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
projectionTF: any
regl,
drawPoints,
colorBuffer,
pointBuffer,
flagBuffer,
camera,
projectionTF
) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message
const { annoMatrix } = this.props;
if (!this.reglCanvas || !annoMatrix) return;
const { schema } = annoMatrix;
const cameraTF = camera.view();
const projView = mat3.multiply(mat3.create(), projectionTF, cameraTF);
@@ -899,24 +824,18 @@ class Graph extends React.Component<{}, GraphState> {
regl._gl.flush();
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'graphInteractionMode' does not exist on ... Remove this comment to see the full error message
graphInteractionMode,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on ... Remove this comment to see the full error message
annoMatrix,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colors' does not exist on ... Remove this comment to see the full error message
colors,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'layoutChoice' does not exist on ... Remove this comment to see the full error message
layoutChoice,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'pointDilation' does not exist on ... Remove this comment to see the full error message
pointDilation,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'crossfilter' does not exist on ... Remove this comment to see the full error message
crossfilter,
} = this.props;
const { modelTF, projectionTF, camera, viewport, regl } = this.state;
const cameraTF = camera?.view()?.slice();
return (
<div
id="graph-wrapper"
@@ -927,7 +846,6 @@ class Graph extends React.Component<{}, GraphState> {
}}
>
<GraphOverlayLayer
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ children: Element; width: any; height: any... Remove this comment to see the full error message
width={viewport.width}
height={viewport.height}
cameraTF={cameraTF}
@@ -987,7 +905,6 @@ class Graph extends React.Component<{}, GraphState> {
}}
>
<Async.Pending initial>
{/* eslint-disable-next-line @typescript-eslint/no-use-before-define --- StillLoading used before defined */}
<StillLoading
displayName={layoutChoice.current}
width={viewport.width}
@@ -996,7 +913,6 @@ class Graph extends React.Component<{}, GraphState> {
</Async.Pending>
<Async.Rejected>
{(error) => (
// eslint-disable-next-line @typescript-eslint/no-use-before-define --- ErrorLoading used before defined
<ErrorLoading
displayName={layoutChoice.current}
error={error}
@@ -1019,8 +935,7 @@ class Graph extends React.Component<{}, GraphState> {
}
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const ErrorLoading = ({ displayName, error, width, height }: any) => {
const ErrorLoading = ({ displayName, error, width, height }) => {
console.log(error); // log to console as this is an unepected error
return (
<div
@@ -1036,30 +951,32 @@ const ErrorLoading = ({ displayName, error, width, height }: any) => {
);
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const StillLoading = ({ displayName, width, height }: any) => (
const StillLoading = ({ displayName, width, height }) =>
/*
Render a busy/loading indicator
*/
<div
style={{
position: "fixed",
fontWeight: 500,
top: height / 2,
width,
}}
>
(
<div
style={{
display: "flex",
justifyContent: "center",
justifyItems: "center",
alignItems: "center",
position: "fixed",
fontWeight: 500,
top: height / 2,
width,
}}
>
<Button minimal loading intent="primary" />
<span style={{ fontStyle: "italic" }}>Loading {displayName}</span>
<div
style={{
display: "flex",
justifyContent: "center",
justifyItems: "center",
alignItems: "center",
}}
>
<Button minimal loading intent="primary" />
<span style={{ fontStyle: "italic" }}>Loading {displayName}</span>
</div>
</div>
</div>
);
)
;
export default Graph;
@@ -0,0 +1,218 @@
import React, { PureComponent } from "react";
import { connect, shallowEqual } from "react-redux";
import Async from "react-async";
import { categoryLabelDisplayStringLongLength } from "../../../globals";
import calcCentroid from "../../../util/centroid";
import { createColorQuery } from "../../../util/stateManager/colorHelpers";
export default
@connect((state) => ({
annoMatrix: state.annoMatrix,
colors: state.colors,
layoutChoice: state.layoutChoice,
dilatedValue: state.pointDilation.categoryField,
categoricalSelection: state.categoricalSelection,
showLabels: state.centroidLabels?.showLabels,
genesets: state.genesets.genesets,
}))
class CentroidLabels extends PureComponent {
static watchAsync(props, prevProps) {
return !shallowEqual(props.watchProps, prevProps.watchProps);
}
fetchAsyncProps = async (props) => {
const {
annoMatrix,
colors,
layoutChoice,
categoricalSelection,
showLabels,
} = props.watchProps;
const { schema } = annoMatrix;
const { colorAccessor } = colors;
const [layoutDf, colorDf] = await this.fetchData();
let labels;
if (colorDf) {
labels = calcCentroid(
schema,
colorAccessor,
colorDf,
layoutChoice,
layoutDf
);
} else {
labels = new Map();
}
const { overlaySetShowing } = this.props;
overlaySetShowing("centroidLabels", showLabels && labels.size > 0);
return {
labels,
colorAccessor,
category: categoricalSelection[colorAccessor],
};
};
handleMouseEnter = (e, colorAccessor, label) => {
const { dispatch } = this.props;
dispatch({
type: "category value mouse hover start",
metadataField: colorAccessor,
categoryField: label,
});
};
handleMouseOut = (e, colorAccessor, label) => {
const { dispatch } = this.props;
dispatch({
type: "category value mouse hover end",
metadataField: colorAccessor,
categoryField: label,
});
};
colorByQuery() {
const { annoMatrix, colors, genesets } = this.props;
const { schema } = annoMatrix;
const { colorMode, colorAccessor } = colors;
return createColorQuery(colorMode, colorAccessor, schema, genesets);
}
async fetchData() {
const { annoMatrix, layoutChoice } = this.props;
// fetch all data we need: layout, category
const promises = [];
// layout
promises.push(annoMatrix.fetch("emb", layoutChoice.current));
// category to label - we ONLY label on obs, never on X, etc.
const query = this.colorByQuery();
if (query && query[0] === "obs") {
promises.push(annoMatrix.fetch(...query));
} else {
promises.push(Promise.resolve(null));
}
return Promise.all(promises);
}
render() {
const {
inverseTransform,
dilatedValue,
categoricalSelection,
showLabels,
colors,
annoMatrix,
layoutChoice,
} = this.props;
return (
<Async
watchFn={CentroidLabels.watchAsync}
promiseFn={this.fetchAsyncProps}
watchProps={{
annoMatrix,
colors,
layoutChoice,
categoricalSelection,
dilatedValue,
showLabels,
}}
>
<Async.Fulfilled>
{(asyncProps) => {
if (!showLabels) return null;
const labelSVGS = [];
const deselectOpacity = 0.375;
const { category, colorAccessor, labels } = asyncProps;
labels.forEach((coords, label) => {
const selected = category.get(label) ?? true;
// Mirror LSB middle truncation
let displayLabel = label;
if (displayLabel.length > categoryLabelDisplayStringLongLength) {
displayLabel = `${label.slice(
0,
categoryLabelDisplayStringLongLength / 2
)}…${label.slice(-categoryLabelDisplayStringLongLength / 2)}`;
}
labelSVGS.push(
// eslint-disable-next-line jsx-a11y/mouse-events-have-key-events -- the mouse actions for centroid labels do not have a screen reader alternative
<Label
key={label} // eslint-disable-line react/no-array-index-key --- label is not an index, eslint is confused
label={label}
dilatedValue={dilatedValue}
coords={coords}
inverseTransform={inverseTransform}
opactity={selected ? 1 : deselectOpacity}
colorAccessor={colorAccessor}
displayLabel={displayLabel}
onMouseEnter={this.handleMouseEnter}
onMouseOut={this.handleMouseOut}
/>
);
});
return <>{labelSVGS}</>;
}}
</Async.Fulfilled>
</Async>
);
}
}
const Label = ({
label,
dilatedValue,
coords,
inverseTransform,
opacity,
colorAccessor,
displayLabel,
onMouseEnter,
onMouseOut,
}) => {
/*
Render a label at a given coordinate.
*/
let fontSize = "15px";
let fontWeight = null;
if (label === dilatedValue) {
fontSize = "18px";
fontWeight = "800";
}
return (
<g
key={label}
className="centroid-label"
transform={`translate(${coords[0]}, ${coords[1]})`}
data-testclass="centroid-label"
data-testid={`${label}-centroid-label`}
>
{/* eslint-disable-next-line jsx-a11y/mouse-events-have-key-events --- the mouse actions for centroid labels do not have a screen reader alternative*/}
<text
transform={inverseTransform}
textAnchor="middle"
style={{
fontSize,
fontWeight,
fill: "black",
userSelect: "none",
opacity: { opacity },
}}
onMouseEnter={(e) => onMouseEnter(e, colorAccessor, label)}
onMouseOut={(e) => onMouseOut(e, colorAccessor, label)}
pointerEvents="visiblePainted"
>
{displayLabel}
</text>
</g>
);
};
@@ -1,241 +0,0 @@
import React, { PureComponent } from "react";
import { connect, shallowEqual } from "react-redux";
import Async from "react-async";
import { categoryLabelDisplayStringLongLength } from "../../../globals";
import calcCentroid from "../../../util/centroid";
import { createColorQuery } from "../../../util/stateManager/colorHelpers";
// @ts-expect-error ts-migrate(1238) FIXME: Unable to resolve signature of class decorator whe... Remove this comment to see the full error message
@connect((state) => ({
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
annoMatrix: (state as any).annoMatrix,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
colors: (state as any).colors,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
layoutChoice: (state as any).layoutChoice,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
dilatedValue: (state as any).pointDilation.categoryField,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
categoricalSelection: (state as any).categoricalSelection,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
showLabels: (state as any).centroidLabels?.showLabels,
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
genesets: (state as any).genesets.genesets,
}))
export default class CentroidLabels extends PureComponent {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
static watchAsync(props: any, prevProps: any) {
return !shallowEqual(props.watchProps, prevProps.watchProps);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
fetchAsyncProps = async (props: any) => {
const {
annoMatrix,
colors,
layoutChoice,
categoricalSelection,
showLabels,
} = props.watchProps;
const { schema } = annoMatrix;
const { colorAccessor } = colors;
const [layoutDf, colorDf] = await this.fetchData();
let labels;
if (colorDf) {
labels = calcCentroid(
schema,
colorAccessor,
colorDf,
layoutChoice,
layoutDf
);
} else {
labels = new Map();
}
// @ts-expect-error ts-migrate(2339) FIXME: Property 'overlaySetShowing' does not exist on typ... Remove this comment to see the full error message
const { overlaySetShowing } = this.props;
overlaySetShowing("centroidLabels", showLabels && labels.size > 0);
return {
labels,
colorAccessor,
category: categoricalSelection[colorAccessor],
};
};
// @ts-expect-error ts-migrate(6133) FIXME: 'e' is declared but its value is never read.
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleMouseEnter = (e: any, colorAccessor: any, label: any) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch } = this.props;
dispatch({
type: "category value mouse hover start",
metadataField: colorAccessor,
categoryField: label,
});
};
// @ts-expect-error ts-migrate(6133) FIXME: 'e' is declared but its value is never read.
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleMouseOut = (e: any, colorAccessor: any, label: any) => {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dispatch' does not exist on type 'Readon... Remove this comment to see the full error message
const { dispatch } = this.props;
dispatch({
type: "category value mouse hover end",
metadataField: colorAccessor,
categoryField: label,
});
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
colorByQuery() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message
const { annoMatrix, colors, genesets } = this.props;
const { schema } = annoMatrix;
const { colorMode, colorAccessor } = colors;
return createColorQuery(colorMode, colorAccessor, schema, genesets);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
async fetchData() {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message
const { annoMatrix, layoutChoice } = this.props;
// fetch all data we need: layout, category
const promises = [];
// layout
promises.push(annoMatrix.fetch("emb", layoutChoice.current));
// category to label - we ONLY label on obs, never on X, etc.
const query = this.colorByQuery();
if (query && query[0] === "obs") {
promises.push(annoMatrix.fetch(...query));
} else {
promises.push(Promise.resolve(null));
}
return Promise.all(promises);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'inverseTransform' does not exist on type... Remove this comment to see the full error message
inverseTransform,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'dilatedValue' does not exist on type 'Re... Remove this comment to see the full error message
dilatedValue,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'categoricalSelection' does not exist on ... Remove this comment to see the full error message
categoricalSelection,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'showLabels' does not exist on type 'Read... Remove this comment to see the full error message
showLabels,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'colors' does not exist on type 'Readonly... Remove this comment to see the full error message
colors,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'annoMatrix' does not exist on type 'Read... Remove this comment to see the full error message
annoMatrix,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'layoutChoice' does not exist on type 'Re... Remove this comment to see the full error message
layoutChoice,
} = this.props;
return (
<Async
watchFn={CentroidLabels.watchAsync}
promiseFn={this.fetchAsyncProps}
watchProps={{
annoMatrix,
colors,
layoutChoice,
categoricalSelection,
dilatedValue,
showLabels,
}}
>
<Async.Fulfilled>
{(asyncProps) => {
if (!showLabels) return null;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const labelSVGS: any = [];
const deselectOpacity = 0.375;
// @ts-expect-error ts-migrate(2339) FIXME: Property 'category' does not exist on type 'unknow... Remove this comment to see the full error message
const { category, colorAccessor, labels } = asyncProps;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
labels.forEach((coords: any, label: any) => {
const selected = category.get(label) ?? true;
// Mirror LSB middle truncation
let displayLabel = label;
if (displayLabel.length > categoryLabelDisplayStringLongLength) {
displayLabel = `${label.slice(
0,
categoryLabelDisplayStringLongLength / 2
)}…${label.slice(-categoryLabelDisplayStringLongLength / 2)}`;
}
labelSVGS.push(
// eslint-disable-next-line jsx-a11y/mouse-events-have-key-events -- the mouse actions for centroid labels do not have a screen reader alternative
<Label
key={label} // eslint-disable-line react/no-array-index-key --- label is not an index, eslint is confused
label={label}
dilatedValue={dilatedValue}
coords={coords}
inverseTransform={inverseTransform}
opactity={selected ? 1 : deselectOpacity}
colorAccessor={colorAccessor}
displayLabel={displayLabel}
onMouseEnter={this.handleMouseEnter}
onMouseOut={this.handleMouseOut}
/>
);
});
return <>{labelSVGS}</>;
}}
</Async.Fulfilled>
</Async>
);
}
}
const Label = ({
label,
dilatedValue,
coords,
inverseTransform,
opacity,
colorAccessor,
displayLabel,
onMouseEnter,
onMouseOut, // eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
}: any) => {
/*
Render a label at a given coordinate.
*/
let fontSize = "15px";
let fontWeight = null;
if (label === dilatedValue) {
fontSize = "18px";
fontWeight = "800";
}
return (
<g
key={label}
className="centroid-label"
transform={`translate(${coords[0]}, ${coords[1]})`}
data-testclass="centroid-label"
data-testid={`${label}-centroid-label`}
>
{/* eslint-disable-next-line jsx-a11y/mouse-events-have-key-events --- the mouse actions for centroid labels do not have a screen reader alternative*/}
<text
transform={inverseTransform}
textAnchor="middle"
style={{
fontSize,
// @ts-expect-error ts-migrate(2322) FIXME: Type 'string | null' is not assignable to type 'Fo... Remove this comment to see the full error message
fontWeight,
fill: "black",
userSelect: "none",
// @ts-expect-error ts-migrate(2322) FIXME: Type '{ opacity: any; }' is not assignable to type... Remove this comment to see the full error message
opacity: { opacity },
}}
onMouseEnter={(e) => onMouseEnter(e, colorAccessor, label)}
onMouseOut={(e) => onMouseOut(e, colorAccessor, label)}
pointerEvents="visiblePainted"
>
{displayLabel}
</text>
</g>
);
};
@@ -1,29 +1,22 @@
import React, { PureComponent, cloneElement } from "react";
// @ts-expect-error ts-migrate(2307) FIXME: Cannot find module '../graph.css' or its correspon... Remove this comment to see the full error message
import styles from "../graph.css";
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
type State = any;
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
export default class GraphOverlayLayer extends PureComponent<{}, State> {
export default class GraphOverlayLayer extends PureComponent {
/*
This component takes its children (assumed in the data coordinate space ([0, 1] range, origin in bottom left corner))
and transforms itself multiple times resulting in screen space ([0, screenWidth/Height] range, origin in top left corner)
Children are assigned in the graph component and must implement onDisplayChange()
*/
// eslint-disable-next-line @typescript-eslint/ban-types --- FIXME: disabled temporarily on migrate to TS.
constructor(props: {}) {
constructor(props) {
super(props);
this.state = {
display: {},
};
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
matrixToTransformString = (m: any) =>
matrixToTransformString = (m) =>
/*
Translates the gl-matrix mat3 to SVG matrix transform style
@@ -32,37 +25,24 @@ export default class GraphOverlayLayer extends PureComponent<{}, State> {
b d f / [a, b, 0, c, d, 0, e, f, 1] => matrix(a, b, c, d, e, f) / matrix(sx, 0, 0, sy, tx, ty) / matrix(m[0] m[3] m[1] m[4] m[6] m[7])
0 0 1
*/
`matrix(${m[0]} ${m[1]} ${m[3]} ${m[4]} ${m[6]} ${m[7]})`;
`matrix(${m[0]} ${m[1]} ${m[3]} ${m[4]} ${m[6]} ${m[7]})`
;
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
reverseMatrixScaleTransformString = (m: any) =>
`matrix(${1 / m[0]} 0 0 ${1 / m[4]} 0 0)`;
reverseMatrixScaleTransformString = (m) => `matrix(${1 / m[0]} 0 0 ${1 / m[4]} 0 0)`;
// This is passed to all children, should be called when an overlay's display state is toggled along with the overlay name and its new display state in boolean form
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
overlaySetShowing = (overlay: any, displaying: any) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
this.setState((state: any) => ({
...state,
display: { ...state.display, [overlay]: displaying },
}));
overlaySetShowing = (overlay, displaying) => {
this.setState((state) => ({ ...state, display: { ...state.display, [overlay]: displaying } }));
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
render() {
const {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'cameraTF' does not exist on type 'Readon... Remove this comment to see the full error message
cameraTF,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'modelTF' does not exist on type 'Readonl... Remove this comment to see the full error message
modelTF,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'projectionTF' does not exist on type 'Re... Remove this comment to see the full error message
projectionTF,
children,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'handleCanvasEvent' does not exist on typ... Remove this comment to see the full error message
handleCanvasEvent,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'width' does not exist on type 'Readonly<... Remove this comment to see the full error message
width,
// @ts-expect-error ts-migrate(2339) FIXME: Property 'height' does not exist on type 'Readonly... Remove this comment to see the full error message
height,
} = this.props;
const { display } = this.state;
@@ -81,7 +61,6 @@ export default class GraphOverlayLayer extends PureComponent<{}, State> {
// Copy the children passed with the overlay and add the inverse transform and onDisplayChange props
const newChildren = React.Children.map(children, (child) =>
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
cloneElement(child, {
inverseTransform,
overlaySetShowing: this.overlaySetShowing,
@@ -1,28 +1,19 @@
import * as d3 from "d3";
import { Colors } from "@blueprintjs/core";
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
const Lasso = () => {
const dispatch = d3.dispatch("start", "end", "cancel");
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const lasso = (svg: any) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
let lassoPolygon: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
let lassoPath: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
let closePath: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
let lassoInProgress: any;
const lasso = (svg) => {
let lassoPolygon;
let lassoPath;
let closePath;
let lassoInProgress;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const polygonToPath = (polygon: any) =>
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
`M${polygon.map((d: any) => d.join(",")).join("L")}`;
const polygonToPath = (polygon) =>
`M${polygon.map((d) => d.join(",")).join("L")}`;
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const distance = (pt1: any, pt2: any) =>
const distance = (pt1, pt2) =>
Math.sqrt((pt2[0] - pt1[0]) ** 2 + (pt2[1] - pt1[1]) ** 2);
// distance last point has to be to first point before it auto closes when mouse is released
@@ -30,14 +21,12 @@ const Lasso = () => {
const lassoPathColor = Colors.BLUE5;
const handleDragStart = () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
lassoPolygon = [(d3 as any).mouse(svg.node())]; // current x y of mouse within element
lassoPolygon = [d3.mouse(svg.node())]; // current x y of mouse within element
if (lassoPath) {
// If the existing path is in progress
if (lassoInProgress) {
// cancel the existing lasso
// eslint-disable-next-line @typescript-eslint/no-use-before-define --- handleCancel used before defined
handleCancel();
// Don't continue with current drag start
return;
@@ -48,14 +37,12 @@ const Lasso = () => {
// We're starting a new drag
lassoInProgress = true;
// eslint-disable-next-line @typescript-eslint/no-use-before-define --- g used before defined
lassoPath = g
.append("path")
.attr("data-testid", "lasso-element")
.attr("fill-opacity", 0.1)
.attr("stroke-dasharray", "3, 3");
// eslint-disable-next-line @typescript-eslint/no-use-before-define --- g used before defined
closePath = g
.append("line")
.attr("x2", lassoPolygon[0][0])
@@ -66,8 +53,7 @@ const Lasso = () => {
};
const handleDrag = () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const point = (d3 as any).mouse(svg.node());
const point = d3.mouse(svg.node());
lassoPolygon.push(point);
lassoPath.attr("d", polygonToPath(lassoPolygon));
@@ -137,12 +123,12 @@ const Lasso = () => {
area.call(drag);
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(lasso as any).reset = () => {
lasso.reset = () => {
if (lassoPath) {
lassoPath.remove();
lassoPath = null;
}
lassoPolygon = null;
if (closePath) {
closePath.remove();
@@ -150,11 +136,10 @@ const Lasso = () => {
}
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
(lasso as any).move = (polygon: any) => {
lasso.move = (polygon) => {
if (polygon !== lassoPolygon || polygon.length !== lassoPolygon.length) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'reset' does not exist on type '(svg: any... Remove this comment to see the full error message
lasso.reset();
lassoPolygon = polygon;
lassoPath = g
.append("path")
@@ -163,13 +148,13 @@ const Lasso = () => {
.attr("fill-opacity", 0.1)
.attr("stroke", lassoPathColor)
.attr("stroke-dasharray", "3, 3");
lassoPath.attr("d", `${polygonToPath(lassoPolygon)}Z`);
}
};
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
lasso.on = (type: any, callback: any) => {
lasso.on = (type, callback) => {
dispatch.on(type, callback);
return lasso;
};
@@ -0,0 +1,54 @@
import * as d3 from "d3";
import Lasso from "./setupLasso";
/******************************************
*******************************************
put svg & brush in DOM
*******************************************
******************************************/
export default (
selectionToolType,
handleStartAction,
handleDragAction,
handleEndAction,
handleCancelAction,
viewport
) => {
const svg = d3.select("#graph-wrapper").select("#lasso-layer");
if (svg.empty()) return {};
if (selectionToolType === "brush") {
const brush = d3
.brush()
.extent([
[0, 0],
[viewport.width, viewport.height],
])
.on("start", handleStartAction)
.on("brush", handleDragAction)
// FYI, brush doesn't generate cancel
.on("end", handleEndAction);
const brushContainer = svg
.append("g")
.attr("class", "graph_brush")
.call(brush);
return { svg, container: brushContainer, tool: brush };
}
if (selectionToolType === "lasso") {
const lasso = Lasso()
.on("end", handleEndAction)
// FYI, Lasso doesn't generate drag
.on("start", handleStartAction)
.on("cancel", handleCancelAction);
const lassoContainer = svg.call(lasso);
return { svg, container: lassoContainer, tool: lasso };
}
throw new Error("unknown graph selection tool");
};
@@ -1,62 +0,0 @@
import * as d3 from "d3";
import Lasso from "./setupLasso";
/******************************************
*******************************************
put svg & brush in DOM
*******************************************
******************************************/
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types --- FIXME: disabled temporarily on migrate to TS.
export default (
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
selectionToolType: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleStartAction: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleDragAction: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleEndAction: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
handleCancelAction: any,
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- - FIXME: disabled temporarily on migrate to TS.
viewport: any
) => {
const svg = d3.select("#graph-wrapper").select("#lasso-layer");
if (svg.empty()) return {};
if (selectionToolType === "brush") {
const brush = d3
.brush()
.extent([
[0, 0],
[viewport.width, viewport.height],
])
.on("start", handleStartAction)
.on("brush", handleDragAction)
// FYI, brush doesn't generate cancel
.on("end", handleEndAction);
const brushContainer = svg
.append("g")
.attr("class", "graph_brush")
.call(brush);
return { svg, container: brushContainer, tool: brush };
}
if (selectionToolType === "lasso") {
// eslint-disable-next-line @typescript-eslint/no-explicit-any --- FIXME: disabled temporarily on migrate to TS.
const lasso = (Lasso() as any)
.on("end", handleEndAction)
// FYI, Lasso doesn't generate drag
.on("start", handleStartAction)
.on("cancel", handleCancelAction);
const lassoContainer = svg.call(lasso);
return { svg, container: lassoContainer, tool: lasso };
}
throw new Error("unknown graph selection tool");
};