feat(geneset): save diff exp result as geneset (#2216)

* update package lock

* allow falsey vals

* remove old diff exp handling

* save diff exp results as geneset

* delete test

* check for undefined or null

* use global geneset description for diffexp

* remove diffexp special code, no longer showing adjpval + logfoldchange

* remove differential map to state

* remove clear from FSM, since we no longer support those actions

* restore controlHelpers test with todo
This commit is contained in:
Severiano Badajoz
2021-05-25 10:51:31 -07:00
committed by GitHub
parent 6f6634a4d9
commit a4050f10e1
23 changed files with 21894 additions and 355 deletions
@@ -1,38 +1,8 @@
/* /*
test controls helpers test controls helpers
*/ */
import { subsetAndResetGeneLists } from "../../../src/util/stateManager/controlsHelpers";
import * as globals from "../../../src/globals";
describe("controls helpers", () => { describe("controls helpers", () => {
test("subsetAndResetGeneLists", () => { // TODO #2227 test: improve test coverage on control helper functions
const geneList = []; // (`topNCategories()`, `isSelectableCategoryName()`, `selectableCategoryNames()`, `createCategorySummaryFromDfCol()`, `createCategoricalSelection()`, )
const genRandGene = () => Math.random().toString(36).substring(2, 6);
// build a unique set of genes
for (let i = 0; i < 150; i += 1) {
let randGene = genRandGene();
while (geneList.includes(randGene)) randGene = genRandGene();
geneList.push(randGene);
}
// insert duplicates
geneList[0] = "dupl";
geneList[20] = "dupl";
const state = {
userDefinedGenes: geneList.slice(0, 20),
diffexpGenes: geneList.slice(20),
};
const [newUserDefinedGenes, newDiffExpGenes] = subsetAndResetGeneLists(
state
);
const expectedNewUserDefinedGenes = [
...geneList.slice(0, 20),
...geneList.slice(21),
].slice(0, globals.maxGenes);
expect(globals.maxUserDefinedGenes).toBeLessThan(globals.maxGenes);
expect(geneList.length).toBeGreaterThan(globals.maxGenes);
expect(newUserDefinedGenes).toHaveLength(globals.maxGenes);
expect(newUserDefinedGenes).toStrictEqual(expectedNewUserDefinedGenes);
expect(newDiffExpGenes).toStrictEqual([]);
});
}); });
+21812 -10
View File
File diff suppressed because it is too large Load Diff
@@ -8,22 +8,17 @@ const HistogramFooter = React.memo(
rangeMax, rangeMax,
rangeColorMin, rangeColorMin,
rangeColorMax, rangeColorMax,
logFoldChange,
pvalAdj,
isObs, isObs,
isGeneSetSummary, isGeneSetSummary,
}) => { }) => {
/* /*
Footer of each histogram. Will render range, title, and optionally Footer of each histogram. Will render range and title.
differential expression info.
Required props: Required props:
* displayName - the displayName, aka "n_genes", "FOXP2", etc. * displayName - the displayName, aka "n_genes", "FOXP2", etc.
* hideRanges - true/false, enables/disable rendering of ranges * hideRanges - true/false, enables/disable rendering of ranges
* range - length two array, [min, max], containing the range values to display * range - length two array, [min, max], containing the range values to display
* rangeColor - length two array, [mincolor, maxcolor], each a CSS color * rangeColor - length two array, [mincolor, maxcolor], each a CSS color
* logFoldChange - lfc to display, optional.
* pValue - pValue to display, optional.
*/ */
return ( return (
<div> <div>
@@ -60,30 +55,6 @@ const HistogramFooter = React.memo(
max {rangeMax.toPrecision(4)} max {rangeMax.toPrecision(4)}
</span> </span>
</div> </div>
{logFoldChange && pvalAdj ? (
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "baseline",
}}
>
<span>
<strong>log fold change:</strong>
{` ${logFoldChange.toPrecision(4)}`}
</span>
<span
style={{
marginLeft: 7,
padding: 2,
}}
>
<strong>p-value (adj):</strong>
{pvalAdj < 0.0001 ? " < 0.0001" : ` ${pvalAdj.toFixed(4)}`}
</span>
</div>
) : null}
</div> </div>
); );
} }
@@ -14,9 +14,9 @@ import StillLoading from "./loading";
import ErrorLoading from "./error"; import ErrorLoading from "./error";
@connect((state, ownProps) => { @connect((state, ownProps) => {
const { isObs, isUserDefined, isDiffExp, isGeneSetSummary, field } = ownProps; const { isObs, isUserDefined, isGeneSetSummary, field } = ownProps;
const myName = makeContinuousDimensionName( const myName = makeContinuousDimensionName(
{ isObs, isUserDefined, isDiffExp, isGeneSetSummary }, { isObs, isUserDefined, isGeneSetSummary },
field field
); );
return { return {
@@ -80,7 +80,6 @@ class HistogramBrush extends React.PureComponent {
field, field,
isObs, isObs,
isUserDefined, isUserDefined,
isDiffExp,
isGeneSetSummary, isGeneSetSummary,
} = this.props; } = this.props;
@@ -98,7 +97,6 @@ class HistogramBrush extends React.PureComponent {
continuousNamespace: { continuousNamespace: {
isObs, isObs,
isUserDefined, isUserDefined,
isDiffExp,
isGeneSetSummary, isGeneSetSummary,
}, },
}; };
@@ -115,7 +113,6 @@ class HistogramBrush extends React.PureComponent {
field, field,
isObs, isObs,
isUserDefined, isUserDefined,
isDiffExp,
isGeneSetSummary, isGeneSetSummary,
} = this.props; } = this.props;
const minAllowedBrushSize = 10; const minAllowedBrushSize = 10;
@@ -156,7 +153,6 @@ class HistogramBrush extends React.PureComponent {
continuousNamespace: { continuousNamespace: {
isObs, isObs,
isUserDefined, isUserDefined,
isDiffExp,
isGeneSetSummary, isGeneSetSummary,
}, },
}; };
@@ -362,10 +358,7 @@ class HistogramBrush extends React.PureComponent {
field, field,
isColorAccessor, isColorAccessor,
isUserDefined, isUserDefined,
isDiffExp,
logFoldChange,
isGeneSetSummary, isGeneSetSummary,
pvalAdj,
isScatterplotXXaccessor, isScatterplotXXaccessor,
isScatterplotYYaccessor, isScatterplotYYaccessor,
zebra, zebra,
@@ -383,7 +376,7 @@ class HistogramBrush extends React.PureComponent {
heightMini, heightMini,
} = this.state; } = this.state;
const fieldForId = field.replace(/\s/g, "_"); const fieldForId = field.replace(/\s/g, "_");
const showScatterPlot = isDiffExp || isUserDefined; const showScatterPlot = isUserDefined;
return ( return (
<Async <Async
@@ -406,9 +399,7 @@ class HistogramBrush extends React.PureComponent {
id={`histogram_${fieldForId}`} id={`histogram_${fieldForId}`}
data-testid={`histogram-${field}`} data-testid={`histogram-${field}`}
data-testclass={ data-testclass={
isDiffExp isUserDefined
? "histogram-diffexp"
: isUserDefined
? "histogram-user-gene" ? "histogram-user-gene"
: "histogram-continuous-metadata" : "histogram-continuous-metadata"
} }
@@ -454,15 +445,12 @@ class HistogramBrush extends React.PureComponent {
<HistogramFooter <HistogramFooter
isGeneSetSummary={isGeneSetSummary} isGeneSetSummary={isGeneSetSummary}
isObs={isObs} isObs={isObs}
isDiffExp={isDiffExp}
displayName={field} displayName={field}
hideRanges={asyncProps.isSingleValue} hideRanges={asyncProps.isSingleValue}
rangeMin={asyncProps.unclippedRange[0]} rangeMin={asyncProps.unclippedRange[0]}
rangeMax={asyncProps.unclippedRange[1]} rangeMax={asyncProps.unclippedRange[1]}
rangeColorMin={asyncProps.unclippedRangeColor[0]} rangeColorMin={asyncProps.unclippedRangeColor[0]}
rangeColorMax={asyncProps.unclippedRangeColor[1]} rangeColorMax={asyncProps.unclippedRangeColor[1]}
logFoldChange={logFoldChange}
pvalAdj={pvalAdj}
/> />
)} )}
</div> </div>
@@ -45,7 +45,6 @@ const LABEL_WIDTH_ANNO = LABEL_WIDTH - ANNO_BUTTON_WIDTH;
crossfilter: state.obsCrossfilter, crossfilter: state.obsCrossfilter,
isUserAnno, isUserAnno,
genesets: state.genesets.genesets, genesets: state.genesets.genesets,
differential: state.differential,
}; };
}) })
class Category extends React.PureComponent { class Category extends React.PureComponent {
@@ -144,15 +143,14 @@ class Category extends React.PureComponent {
*/ */
const { schema } = annoMatrix; const { schema } = annoMatrix;
const { colorAccessor, colorMode } = colors; const { colorAccessor, colorMode } = colors;
const { genesets, differential } = this.props; const { genesets } = this.props;
let colorDataPromise = Promise.resolve(null); let colorDataPromise = Promise.resolve(null);
if (colorAccessor) { if (colorAccessor) {
const query = createColorQuery( const query = createColorQuery(
colorMode, colorMode,
colorAccessor, colorAccessor,
schema, schema,
genesets, genesets
differential.diffExp
); );
if (query) colorDataPromise = annoMatrix.fetch(...query); if (query) colorDataPromise = annoMatrix.fetch(...query);
} }
@@ -107,11 +107,10 @@ const continuous = (selectorId, colorScale, colorAccessor) => {
annoMatrix: state.annoMatrix, annoMatrix: state.annoMatrix,
colors: state.colors, colors: state.colors,
genesets: state.genesets.genesets, genesets: state.genesets.genesets,
differential: state.differential,
})) }))
class ContinuousLegend extends React.Component { class ContinuousLegend extends React.Component {
async componentDidUpdate(prevProps) { async componentDidUpdate(prevProps) {
const { annoMatrix, colors, genesets, differential } = this.props; const { annoMatrix, colors, genesets } = this.props;
if (!colors || !annoMatrix) return; if (!colors || !annoMatrix) return;
if (colors !== prevProps?.colors || annoMatrix !== prevProps?.annoMatrix) { if (colors !== prevProps?.colors || annoMatrix !== prevProps?.annoMatrix) {
@@ -122,8 +121,7 @@ class ContinuousLegend extends React.Component {
colorMode, colorMode,
colorAccessor, colorAccessor,
schema, schema,
genesets, genesets
differential.diffExp
); );
const colorDf = colorQuery ? await annoMatrix.fetch(...colorQuery) : null; const colorDf = colorQuery ? await annoMatrix.fetch(...colorQuery) : null;
+12 -30
View File
@@ -63,9 +63,6 @@ class Gene extends React.Component {
isColorAccessor, isColorAccessor,
isScatterplotXXaccessor, isScatterplotXXaccessor,
isScatterplotYYaccessor, isScatterplotYYaccessor,
isDiffExp,
pvalAdj,
logFoldChange,
} = this.props; } = this.props;
const { geneIsExpanded } = this.state; const { geneIsExpanded } = this.state;
const genesetNameLengthVisible = 310; /* this magic number determines how much of a long geneset name we see */ const genesetNameLengthVisible = 310; /* this magic number determines how much of a long geneset name we see */
@@ -120,25 +117,20 @@ class Gene extends React.Component {
</Truncate> </Truncate>
</div> </div>
{!geneIsExpanded ? ( {!geneIsExpanded ? (
isDiffExp ? ( <HistogramBrush isUserDefined field={gene} mini />
<HistogramBrush isDiffExp field={gene} mini />
) : (
<HistogramBrush isUserDefined field={gene} mini />
)
) : null} ) : null}
</div> </div>
<div style={{ flexShrink: 0, marginLeft: 2 }}> <div style={{ flexShrink: 0, marginLeft: 2 }}>
{!isDiffExp ? ( <AnchorButton
<AnchorButton minimal
minimal small
small data-testid={`delete-from-geneset-${gene}`}
data-testid={`delete-from-geneset-${gene}`} onClick={this.handleDeleteGeneFromSet}
onClick={this.handleDeleteGeneFromSet} intent="none"
intent="none" style={{ fontWeight: 700, marginRight: 2 }}
style={{ fontWeight: 700, marginRight: 2 }} icon={<Icon icon="trash" iconSize={10} />}
icon={<Icon icon="trash" iconSize={10} />} />
/> )
) : null}
<AnchorButton <AnchorButton
minimal minimal
small small
@@ -184,17 +176,7 @@ class Gene extends React.Component {
/> />
</div> </div>
</div> </div>
{geneIsExpanded && {geneIsExpanded && <HistogramBrush isUserDefined field={gene} />}
(isDiffExp ? (
<HistogramBrush
isDiffExp
field={gene}
pvalAdj={pvalAdj}
logFoldChange={logFoldChange}
/>
) : (
<HistogramBrush isUserDefined field={gene} />
))}
</div> </div>
); );
} }
@@ -79,33 +79,8 @@ class GeneSet extends React.Component {
}; };
renderGenes() { renderGenes() {
const { const { setName, setGenes, setGenesWithDescriptions } = this.props;
setName,
setGenes,
setGenesWithDescriptions,
isDiffExp,
diffExp,
} = this.props;
if (isDiffExp) {
// [ [gene, logfoldchange, pval, pval_adj], ...]
return setGenes.map((gene, idx) => {
const logFoldChange = diffExp[idx][1];
const pvalAdj = diffExp[idx][3];
return (
<Gene
key={gene}
gene={gene}
geneset={setName}
isDiffExp
logFoldChange={logFoldChange}
pvalAdj={pvalAdj}
/>
);
});
}
// otherwise...
return setGenes.map((gene) => { return setGenes.map((gene) => {
const { geneDescription } = setGenesWithDescriptions.get(gene); const { geneDescription } = setGenesWithDescriptions.get(gene);
@@ -7,7 +7,6 @@ import CreateGenesetDialogue from "./menus/createGenesetDialogue";
@connect((state) => { @connect((state) => {
return { return {
differential: state.differential,
genesets: state.genesets.genesets, genesets: state.genesets.genesets,
}; };
}) })
@@ -30,24 +29,6 @@ class GeneExpression extends React.Component {
return sets; return sets;
}; };
renderDiffexpGeneSets = () => {
const { differential } = this.props;
const { diffExp } = differential;
if (!diffExp) return null;
// [ [gene, logfoldchange, pval, pval_adj], ...]
const setGenes = diffExp.map((diffExpGene) => diffExpGene[0]);
return (
<GeneSet
key="Temp DiffExp Set"
setGenes={setGenes}
isDiffExp
diffExp={diffExp}
setName="Temp DiffExp Set"
/>
);
};
handleActivateCreateGenesetMode = () => { handleActivateCreateGenesetMode = () => {
const { dispatch } = this.props; const { dispatch } = this.props;
dispatch({ type: "geneset: activate add new geneset mode" }); dispatch({ type: "geneset: activate add new geneset mode" });
@@ -68,7 +49,6 @@ class GeneExpression extends React.Component {
</div> </div>
<CreateGenesetDialogue /> <CreateGenesetDialogue />
</div> </div>
<div>{this.renderDiffexpGeneSets()}</div>
<div>{this.renderGeneSets()}</div> <div>{this.renderGeneSets()}</div>
</div> </div>
); );
@@ -54,7 +54,6 @@ const filterGenes = (query, genes) =>
annoMatrix: state.annoMatrix, annoMatrix: state.annoMatrix,
userDefinedGenes: state.controls.userDefinedGenes, userDefinedGenes: state.controls.userDefinedGenes,
userDefinedGenesLoading: state.controls.userDefinedGenesLoading, userDefinedGenesLoading: state.controls.userDefinedGenesLoading,
differential: state.differential,
}; };
}) })
class AddGenes extends React.Component { class AddGenes extends React.Component {
+2 -9
View File
@@ -77,7 +77,6 @@ function createModelTF() {
colors: state.colors, colors: state.colors,
pointDilation: state.pointDilation, pointDilation: state.pointDilation,
genesets: state.genesets.genesets, genesets: state.genesets.genesets,
differential: state.differential,
})) }))
class Graph extends React.Component { class Graph extends React.Component {
static createReglState(canvas) { static createReglState(canvas) {
@@ -785,17 +784,11 @@ class Graph extends React.Component {
} }
createColorByQuery(colors) { createColorByQuery(colors) {
const { annoMatrix, genesets, differential } = this.props; const { annoMatrix, genesets } = this.props;
const { schema } = annoMatrix; const { schema } = annoMatrix;
const { colorMode, colorAccessor } = colors; const { colorMode, colorAccessor } = colors;
return createColorQuery( return createColorQuery(colorMode, colorAccessor, schema, genesets);
colorMode,
colorAccessor,
schema,
genesets,
differential.diffExp
);
} }
renderPoints( renderPoints(
@@ -15,7 +15,6 @@ export default
categoricalSelection: state.categoricalSelection, categoricalSelection: state.categoricalSelection,
showLabels: state.centroidLabels?.showLabels, showLabels: state.centroidLabels?.showLabels,
genesets: state.genesets.genesets, genesets: state.genesets.genesets,
differential: state.differential,
})) }))
class CentroidLabels extends PureComponent { class CentroidLabels extends PureComponent {
static watchAsync(props, prevProps) { static watchAsync(props, prevProps) {
@@ -76,16 +75,10 @@ class CentroidLabels extends PureComponent {
}; };
colorByQuery() { colorByQuery() {
const { annoMatrix, colors, genesets, differential } = this.props; const { annoMatrix, colors, genesets } = this.props;
const { schema } = annoMatrix; const { schema } = annoMatrix;
const { colorMode, colorAccessor } = colors; const { colorMode, colorAccessor } = colors;
return createColorQuery( return createColorQuery(colorMode, colorAccessor, schema, genesets);
colorMode,
colorAccessor,
schema,
genesets,
differential.diffExp
);
} }
async fetchData() { async fetchData() {
@@ -9,12 +9,9 @@ import actions from "../../actions";
})) }))
class CellSetButton extends React.PureComponent { class CellSetButton extends React.PureComponent {
set() { set() {
const { differential, dispatch, eitherCellSetOneOrTwo } = this.props; const { dispatch, eitherCellSetOneOrTwo } = this.props;
if (!differential.diffExp) { dispatch(actions.setCellSetFromSelection(eitherCellSetOneOrTwo));
// disallow this action if the user has active differential expression results
dispatch(actions.setCellSetFromSelection(eitherCellSetOneOrTwo));
}
} }
render() { render() {
@@ -31,7 +28,6 @@ class CellSetButton extends React.PureComponent {
> >
<AnchorButton <AnchorButton
type="button" type="button"
disabled={differential.diffExp}
onClick={() => { onClick={() => {
this.set(); this.set();
}} }}
+17 -49
View File
@@ -1,6 +1,6 @@
import React from "react"; import React from "react";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { Button, ButtonGroup, AnchorButton, Tooltip } from "@blueprintjs/core"; import { ButtonGroup, AnchorButton, Tooltip } from "@blueprintjs/core";
import * as globals from "../../globals"; import * as globals from "../../globals";
import styles from "./menubar.css"; import styles from "./menubar.css";
import actions from "../../actions"; import actions from "../../actions";
@@ -8,8 +8,6 @@ import CellSetButton from "./cellSetButtons";
@connect((state) => ({ @connect((state) => ({
differential: state.differential, differential: state.differential,
celllist1: state.differential?.celllist1,
celllist2: state.differential?.celllist2,
diffexpMayBeSlow: state.config?.parameters?.["diffexp-may-be-slow"] ?? false, diffexpMayBeSlow: state.config?.parameters?.["diffexp-may-be-slow"] ?? false,
diffexpCellcountMax: state.config?.limits?.diffexp_cellcount_max, diffexpCellcountMax: state.config?.limits?.diffexp_cellcount_max,
})) }))
@@ -26,17 +24,6 @@ class DiffexpButtons extends React.PureComponent {
} }
}; };
clearDifferentialExpression = () => {
const { dispatch, differential } = this.props;
dispatch({
type: "clear differential expression",
diffExp: differential.diffExp,
});
dispatch({
type: "clear scatterplot",
});
};
render() { render() {
/* diffexp-related buttons may be disabled */ /* diffexp-related buttons may be disabled */
const { differential, diffexpMayBeSlow, diffexpCellcountMax } = this.props; const { differential, diffexpMayBeSlow, diffexpCellcountMax } = this.props;
@@ -65,41 +52,22 @@ class DiffexpButtons extends React.PureComponent {
<ButtonGroup className={styles.menubarButton}> <ButtonGroup className={styles.menubarButton}>
<CellSetButton eitherCellSetOneOrTwo={1} /> <CellSetButton eitherCellSetOneOrTwo={1} />
<CellSetButton eitherCellSetOneOrTwo={2} /> <CellSetButton eitherCellSetOneOrTwo={2} />
{!differential.diffExp ? ( <Tooltip
<Tooltip content={warnMaxSizeExceeded ? tipMessageWarn : tipMessage}
content={warnMaxSizeExceeded ? tipMessageWarn : tipMessage} position="bottom"
position="bottom" hoverOpenDelay={globals.tooltipHoverOpenDelayQuick}
hoverOpenDelay={globals.tooltipHoverOpenDelayQuick} intent={warnMaxSizeExceeded ? "danger" : "none"}
intent={warnMaxSizeExceeded ? "danger" : "none"} >
> <AnchorButton
<AnchorButton disabled={!haveBothCellSets || warnMaxSizeExceeded}
disabled={!haveBothCellSets || warnMaxSizeExceeded} intent={warnMaxSizeExceeded ? "danger" : "primary"}
intent={warnMaxSizeExceeded ? "danger" : "primary"} data-testid="diffexp-button"
data-testid="diffexp-button" loading={differential.loading}
loading={differential.loading} icon="left-join"
icon="left-join" fill
fill onClick={this.computeDiffExp}
onClick={this.computeDiffExp} />
/> </Tooltip>
</Tooltip>
) : null}
{differential.diffExp ? (
<Tooltip
content="Remove differentially expressed gene list and clear cell selections"
position="bottom"
hoverOpenDelay={globals.tooltipHoverOpenDelayQuick}
>
<Button
type="button"
fill
intent="warning"
onClick={this.clearDifferentialExpression}
>
Clear Differential Expression
</Button>
</Tooltip>
) : null}
</ButtonGroup> </ButtonGroup>
); );
} }
-4
View File
@@ -29,17 +29,13 @@ import { getEmbSubsetView } from "../../util/stateManager/viewStackHelpers";
return { return {
subsetPossible, subsetPossible,
subsetResetPossible, subsetResetPossible,
differential: state.differential,
graphInteractionMode: state.controls.graphInteractionMode, graphInteractionMode: state.controls.graphInteractionMode,
clipPercentileMin: Math.round(100 * (annoMatrix?.clipRange?.[0] ?? 0)), clipPercentileMin: Math.round(100 * (annoMatrix?.clipRange?.[0] ?? 0)),
clipPercentileMax: Math.round(100 * (annoMatrix?.clipRange?.[1] ?? 1)), clipPercentileMax: Math.round(100 * (annoMatrix?.clipRange?.[1] ?? 1)),
userDefinedGenes: state.controls.userDefinedGenes, userDefinedGenes: state.controls.userDefinedGenes,
diffexpGenes: state.controls.diffexpGenes,
colorAccessor: state.colors.colorAccessor, colorAccessor: state.colors.colorAccessor,
scatterplotXXaccessor: state.controls.scatterplotXXaccessor, scatterplotXXaccessor: state.controls.scatterplotXXaccessor,
scatterplotYYaccessor: state.controls.scatterplotYYaccessor, scatterplotYYaccessor: state.controls.scatterplotYYaccessor,
celllist1: state.differential.celllist1,
celllist2: state.differential.celllist2,
libraryVersions: state.config?.library_versions, libraryVersions: state.config?.library_versions,
auth: state.config?.authentication, auth: state.config?.authentication,
userInfo: state.userInfo, userInfo: state.userInfo,
@@ -51,7 +51,6 @@ const getYScale = memoize(getScale);
scatterplotXXaccessor, scatterplotXXaccessor,
scatterplotYYaccessor, scatterplotYYaccessor,
differential: state.differential,
crossfilter, crossfilter,
genesets: state.genesets.genesets, genesets: state.genesets.genesets,
}; };
@@ -314,16 +313,10 @@ class Scatterplot extends React.PureComponent {
} }
createColorByQuery(colors) { createColorByQuery(colors) {
const { annoMatrix, genesets, differential } = this.props; const { annoMatrix, genesets } = this.props;
const { schema } = annoMatrix; const { schema } = annoMatrix;
const { colorMode, colorAccessor } = colors; const { colorMode, colorAccessor } = colors;
return createColorQuery( return createColorQuery(colorMode, colorAccessor, schema, genesets);
colorMode,
colorAccessor,
schema,
genesets,
differential
);
} }
updateColorTable(colors, colorDf) { updateColorTable(colors, colorDf) {
+1 -16
View File
@@ -7,9 +7,7 @@ const ColorsReducer = (
colorMode: null /* by continuous, by expression */, colorMode: null /* by continuous, by expression */,
colorAccessor: null /* tissue, Apod */, colorAccessor: null /* tissue, Apod */,
}, },
action, action
nextSharedState,
prevSharedState
) => { ) => {
switch (action.type) { switch (action.type) {
case "universe: user color load success": { case "universe: user color load success": {
@@ -20,19 +18,6 @@ const ColorsReducer = (
}; };
} }
case "clear differential expression":
case "set clip quantiles":
case "subset to selection": {
const { controls: prevControls } = prevSharedState;
if (prevControls.diffexpGenes.includes(state.colorAccessor)) {
return {
colorMode: null,
colorAccessor: null,
};
}
return state;
}
case "annotation: category edited": { case "annotation: category edited": {
const { colorAccessor } = state; const { colorAccessor } = state;
if (action.metadataField !== colorAccessor) { if (action.metadataField !== colorAccessor) {
-25
View File
@@ -1,6 +1,5 @@
import uniq from "lodash.uniq"; import uniq from "lodash.uniq";
import filter from "lodash.filter"; import filter from "lodash.filter";
import { subsetAndResetGeneLists } from "../util/stateManager/controlsHelpers";
const Controls = ( const Controls = (
state = { state = {
@@ -11,7 +10,6 @@ const Controls = (
// all of the data + selection state // all of the data + selection state
userDefinedGenes: [], userDefinedGenes: [],
userDefinedGenesLoading: false, userDefinedGenesLoading: false,
diffexpGenes: [],
resettingInterface: false, resettingInterface: false,
graphInteractionMode: "select", graphInteractionMode: "select",
@@ -45,26 +43,16 @@ const Controls = (
}; };
} }
case "reset subset": { case "reset subset": {
const [newUserDefinedGenes, newDiffExpGenes] = subsetAndResetGeneLists(
state
);
return { return {
...state, ...state,
resettingInterface: false, resettingInterface: false,
userDefinedGenes: newUserDefinedGenes,
diffexpGenes: newDiffExpGenes,
}; };
} }
case "subset to selection": { case "subset to selection": {
const [newUserDefinedGenes, newDiffExpGenes] = subsetAndResetGeneLists(
state
);
return { return {
...state, ...state,
loading: false, loading: false,
error: null, error: null,
userDefinedGenes: newUserDefinedGenes,
diffexpGenes: newDiffExpGenes,
}; };
} }
case "request user defined gene started": { case "request user defined gene started": {
@@ -90,19 +78,6 @@ const Controls = (
userDefinedGenesLoading: false, userDefinedGenesLoading: false,
}; };
} }
case "request differential expression success": {
const diffexpGenes = action.data.map((v) => v[0]);
return {
...state,
diffexpGenes,
};
}
case "clear differential expression": {
return {
...state,
diffexpGenes: [],
};
}
case "clear user defined gene": { case "clear user defined gene": {
const { userDefinedGenes } = state; const { userDefinedGenes } = state;
const newUserDefinedGenes = filter( const newUserDefinedGenes = filter(
-10
View File
@@ -1,6 +1,5 @@
const Differential = ( const Differential = (
state = { state = {
diffExp: null,
loading: null, loading: null,
error: null, error: null,
celllist1: null, celllist1: null,
@@ -20,7 +19,6 @@ const Differential = (
...state, ...state,
error: null, error: null,
loading: false, loading: false,
diffExp: action.data,
}; };
case "request differential expression error": case "request differential expression error":
return { return {
@@ -38,18 +36,10 @@ const Differential = (
...state, ...state,
celllist2: action.data, celllist2: action.data,
}; };
case "clear differential expression":
return {
...state,
diffExp: null,
celllist1: null,
celllist2: null,
};
case "reset subset": case "reset subset":
case "subset to selection": case "subset to selection":
return { return {
...state, ...state,
diffExp: null,
celllist1: null, celllist1: null,
celllist2: null, celllist2: null,
}; };
+28
View File
@@ -69,6 +69,7 @@ const GeneSets = (
} }
return { return {
...state,
initialized: true, initialized: true,
lastTid, lastTid,
genesets, genesets,
@@ -353,6 +354,33 @@ const GeneSets = (
}; };
} }
case "request differential expression success": {
const { data } = action;
const genes = new Map(
data.map((diffExpGene) => [
diffExpGene[0],
{
geneSymbol: diffExpGene[0],
},
])
);
const genesetName = `DiffExp Set (${new Date().toLocaleString()})`;
const genesets = new Map(state.genesets); // clone
genesets.set(genesetName, {
genesetName,
genesetDescription: "",
genes,
});
return {
...state,
genesets,
};
}
default: default:
return state; return state;
} }
-14
View File
@@ -185,20 +185,6 @@ const createFsmTransitions = (
action: applyPending, action: applyPending,
}, },
/* Clear Differential Expression button user action */
{
event: "clear differential expression",
from: "init",
to: "CDE Button in progress",
action: stashPending,
},
{
event: "clear scatterplot",
from: "CDE Button in progress",
to: "done",
action: applyPending,
},
/* clear scatter plot button (eg, on scatterplot view) */ /* clear scatter plot button (eg, on scatterplot view) */
{ {
event: "clear scatterplot", event: "clear scatterplot",
+3 -20
View File
@@ -12,13 +12,7 @@ import { range } from "../range";
given a color mode & accessor, generate an annoMatrix query that will given a color mode & accessor, generate an annoMatrix query that will
fulfill it fulfill it
*/ */
export function createColorQuery( export function createColorQuery(colorMode, colorByAccessor, schema, genesets) {
colorMode,
colorByAccessor,
schema,
genesets,
diffExp
) {
if (!colorMode || !colorByAccessor || !schema || !genesets) return null; if (!colorMode || !colorByAccessor || !schema || !genesets) return null;
switch (colorMode) { switch (colorMode) {
@@ -46,19 +40,8 @@ export function createColorQuery(
if (!varIndex) return null; if (!varIndex) return null;
if (!genesets) return null; if (!genesets) return null;
let _geneset; const _geneset = genesets.get(colorByAccessor);
let _setGenes; const _setGenes = [..._geneset.genes.keys()];
if (colorByAccessor === "Temp DiffExp Set") {
_geneset = diffExp;
_setGenes = _geneset.map((diffexpResultItem) => {
const geneName = diffexpResultItem[0];
return geneName;
});
} else {
_geneset = genesets.get(colorByAccessor);
_setGenes = [..._geneset.genes.keys()];
}
return [ return [
"X", "X",
@@ -2,7 +2,6 @@
Helper functions for the controls reducer Helper functions for the controls reducer
*/ */
import uniq from "lodash.uniq";
import difference from "lodash.difference"; import difference from "lodash.difference";
import * as globals from "../../globals"; import * as globals from "../../globals";
@@ -158,12 +157,3 @@ export function pruneVarDataCache(varData, needed) {
} }
return varData; return varData;
} }
export function subsetAndResetGeneLists(state) {
const { userDefinedGenes, diffexpGenes } = state;
const newUserDefinedGenes = uniq(
[].concat(userDefinedGenes, diffexpGenes)
).slice(0, globals.maxGenes);
const newDiffExpGenes = [];
return [newUserDefinedGenes, newDiffExpGenes];
}