Redux refactor (#1571)

* refactor categorical controls state

* lint

* fix race condition in tests

* fix typo

* add missing update on subset

* remove obsolete code

* update jest and puppeteer major version; update all minors

* update when label changes

* remove lint from tests; increase timeouts in e2e tests

* initial refactoring to new async annomatrix

* refine error handling

* fix bad merge

* add continuous legend

* lint

* fix memoization in color table creators

* partial implementation of user defined annotations

* add new annotations action creator file

* first pass at user annotations

* additional user annotation bug fixes

* user annotation auto-save

* unit test cleanup

* lint

* refactor into multiple files

* cleanup

* add column GC

* fix several bugs in user annotations

* remove debug code

* no anonymous functions

* undo redo cleanup

* file cleanup

* scatterplot

* performance

* cleanup

* remove old code

* render in parallel with load

* fix race condition

* simply graph rendering

* render throttle DRY

* fix category label order

* fix typo in e2e test setup

* re-fix the e2e test setup

* be more tolerant of races

* anno matrix unit tests

* temp disable reembedding

* pilot port continuous histo to react-async

* name change

* lint

* fix repaint bug

* typo fix

* update snap to match new ids

* world/universe name cleanup

* move annoMatrix to src dir

* use private underscore naming convention

* fix corner case in all selected

* name cleanup

* add layout control

* init edge case

* lint

* port scatterplot

* fix label indexing bug and improve tests

* port category to react-async

* fix user annotation labelling while subset

* select all of prev layout on layout switch

* fix race with crossfilter update

* prettier lint

* fix misleading comment

* fix url composition in loader

* first pass at crossfilter tests

* lint

* lint

* fix typo

* improved error handling for network errors

* fix memoization bug

* add memo

* refactor for performnce

* add missing single-value handling in select exact parser

* small bugs discovered by tests

* lint

* additional crossfilter unit tests

* remove extraneous comment

* add support for automatic category determination

* lint

* fix render bug in category

* take advantage of schema categories guarantee

* lint

* do not clear history when resetting

* enhanced annomatrix gc

* lint

* finish renaming to follow conventions; fix clone race bug

* lint

* add priority based loading to improve initial data load UX

* crossfilter cache perf

* perf tuning

* remove timers

* documentation

* PR review changes

* PR review changes

* more PR review edits

* improve clarity of comment

* more PR review fixes

* port centroidLabels to use react-async

* remove dead code

* pr review updates

* oops, remove logging
This commit is contained in:
Bruce Martin
2020-07-14 13:53:33 -07:00
committed by GitHub
parent f69d141336
commit 1269e188be
95 changed files with 18051 additions and 5382 deletions
@@ -2,7 +2,6 @@
import React from "react";
import { AnchorButton, Tooltip } from "@blueprintjs/core";
import { connect } from "react-redux";
import { World } from "../../util/stateManager";
import { tooltipHoverOpenDelay } from "../../globals";
@connect()
@@ -15,12 +14,8 @@ class CellSetButton extends React.PureComponent {
eitherCellSetOneOrTwo,
} = this.props;
// Reducer and components assume that value will be null if
// no selection made. World..getSelectedByIndex() returns a
// zero length TypedArray when nothing is selected.
let set = World.getSelectedByIndex(crossfilter);
let set = crossfilter.allSelectedLabels();
if (set.length === 0) set = null;
if (!differential.diffExp) {
/* diffexp needs to be cleared before we store a new set */
dispatch({
@@ -9,7 +9,7 @@ import CellSetButton from "./cellSetButtons";
@connect((state) => ({
config: state.config,
crossfilter: state.crossfilter,
crossfilter: state.obsCrossfilter,
differential: state.differential,
celllist1: state.differential?.celllist1,
celllist2: state.differential?.celllist2,
+9 -10
View File
@@ -1,6 +1,5 @@
import React from "react";
import {
AnchorButton,
ButtonGroup,
Popover,
Button,
@@ -12,26 +11,25 @@ import {
import { connect } from "react-redux";
import * as globals from "../../globals";
import styles from "./menubar.css";
import { World } from "../../util/stateManager";
import actions from "../../actions";
@connect((state) => ({
universe: state.universe,
world: state.world,
layoutChoice: state.layoutChoice,
reembedController: state.reembedController,
enableReembedding: state.config?.parameters?.["enable-reembedding"] ?? false,
// disabled temporarily. TODO - issue #1606
// reembedController: state.reembedController,
// enableReembedding: state.config?.parameters?.["enable-reembedding"] ?? false,
enableReembedding: false,
}))
class Embedding extends React.PureComponent {
handleLayoutChoiceChange = (e) => {
const { dispatch } = this.props;
dispatch({
type: "set layout choice",
layoutChoice: e.currentTarget.value,
});
dispatch(actions.layoutChoiceAction(e.currentTarget.value));
};
// eslint-disable-next-line class-methods-use-this -- temporary disable
renderReembedding() {
return null;
/* disabled pending rewrite. TODO - issue #1606
const {
enableReembedding,
world,
@@ -63,6 +61,7 @@ class Embedding extends React.PureComponent {
/>
</Tooltip>
);
*/
}
render() {
+15 -22
View File
@@ -1,4 +1,3 @@
// jshint esversion: 6
import React from "react";
import { connect } from "react-redux";
import { ButtonGroup, AnchorButton, Tooltip } from "@blueprintjs/core";
@@ -14,13 +13,12 @@ import UndoRedoReset from "./undoRedo";
import DiffexpButtons from "./diffexpButtons";
@connect((state) => ({
universe: state.universe,
world: state.world,
crossfilter: state.crossfilter,
annoMatrix: state.annoMatrix,
crossfilter: state.obsCrossfilter,
differential: state.differential,
graphInteractionMode: state.controls.graphInteractionMode,
clipPercentileMin: Math.round(100 * (state.world?.clipQuantiles?.min ?? 0)),
clipPercentileMax: Math.round(100 * (state.world?.clipQuantiles?.max ?? 1)),
clipPercentileMin: Math.round(100 * (state.annoMatrix?.clipRange?.[0] ?? 0)),
clipPercentileMax: Math.round(100 * (state.annoMatrix?.clipRange?.[1] ?? 1)),
userDefinedGenes: state.controls.userDefinedGenes,
diffexpGenes: state.controls.diffexpGenes,
colorAccessor: state.colors.colorAccessor,
@@ -78,10 +76,10 @@ class MenuBar extends React.Component {
const { pendingClipPercentiles } = this.state;
const clipPercentileMin = pendingClipPercentiles?.clipPercentileMin;
const clipPercentileMax = pendingClipPercentiles?.clipPercentileMax;
const { world } = this.props;
const currentClipMin = 100 * world?.clipQuantiles?.min;
const currentClipMax = 100 * world?.clipQuantiles?.max;
const {
clipPercentileMin: currentClipMin,
clipPercentileMax: currentClipMax,
} = this.props;
// if you change this test, be careful with logic around
// comparisons between undefined / NaN handling.
@@ -150,10 +148,7 @@ class MenuBar extends React.Component {
const { clipPercentileMin, clipPercentileMax } = pendingClipPercentiles;
const min = clipPercentileMin / 100;
const max = clipPercentileMax / 100;
dispatch({
type: "set clip quantiles",
clipQuantiles: { min, max },
});
dispatch(actions.clipAction(min, max));
};
handleClipOpening = () => {
@@ -178,15 +173,15 @@ class MenuBar extends React.Component {
subsetPossible = () => {
const { crossfilter } = this.props;
const count = crossfilter.countSelected();
return (
crossfilter.countSelected() !== 0 &&
crossfilter.countSelected() !== crossfilter.size()
count !== 0 && count !== crossfilter.size() // ie, not all are selected
);
};
subsetResetPossible = () => {
const { world, universe } = this.props;
return world.nObs !== universe.nObs;
const { annoMatrix } = this.props;
return annoMatrix.nObs !== annoMatrix.schema.dataframe.nObs;
};
render() {
@@ -317,12 +312,10 @@ class MenuBar extends React.Component {
subsetPossible={this.subsetPossible()}
subsetResetPossible={this.subsetResetPossible()}
handleSubset={() => {
dispatch(actions.setWorldToSelection());
dispatch({ type: "increment graph render counter" });
dispatch(actions.subsetAction());
}}
handleSubsetReset={() => {
dispatch(actions.resetWorldToUniverse());
dispatch({ type: "increment graph render counter" });
dispatch(actions.resetSubsetAction());
}}
/>
{disableDiffexp ? null : <DiffexpButtons />}