mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-09-15 12:47:56 +08:00
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:
committed by
GitHub
parent
6f6634a4d9
commit
a4050f10e1
@@ -1,38 +1,8 @@
|
||||
/*
|
||||
test controls helpers
|
||||
*/
|
||||
import { subsetAndResetGeneLists } from "../../../src/util/stateManager/controlsHelpers";
|
||||
import * as globals from "../../../src/globals";
|
||||
|
||||
describe("controls helpers", () => {
|
||||
test("subsetAndResetGeneLists", () => {
|
||||
const geneList = [];
|
||||
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([]);
|
||||
});
|
||||
// TODO #2227 test: improve test coverage on control helper functions
|
||||
// (`topNCategories()`, `isSelectableCategoryName()`, `selectableCategoryNames()`, `createCategorySummaryFromDfCol()`, `createCategoricalSelection()`, )
|
||||
});
|
||||
|
||||
21822
client/package-lock.json
generated
21822
client/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -8,22 +8,17 @@ const HistogramFooter = React.memo(
|
||||
rangeMax,
|
||||
rangeColorMin,
|
||||
rangeColorMax,
|
||||
logFoldChange,
|
||||
pvalAdj,
|
||||
isObs,
|
||||
isGeneSetSummary,
|
||||
}) => {
|
||||
/*
|
||||
Footer of each histogram. Will render range, title, and optionally
|
||||
differential expression info.
|
||||
|
||||
Footer of each histogram. Will render range and title.
|
||||
|
||||
Required props:
|
||||
* displayName - the displayName, aka "n_genes", "FOXP2", etc.
|
||||
* hideRanges - true/false, enables/disable rendering of ranges
|
||||
* range - length two array, [min, max], containing the range values to display
|
||||
* rangeColor - length two array, [mincolor, maxcolor], each a CSS color
|
||||
* logFoldChange - lfc to display, optional.
|
||||
* pValue - pValue to display, optional.
|
||||
*/
|
||||
return (
|
||||
<div>
|
||||
@@ -60,30 +55,6 @@ const HistogramFooter = React.memo(
|
||||
max {rangeMax.toPrecision(4)}
|
||||
</span>
|
||||
</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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -14,9 +14,9 @@ import StillLoading from "./loading";
|
||||
import ErrorLoading from "./error";
|
||||
|
||||
@connect((state, ownProps) => {
|
||||
const { isObs, isUserDefined, isDiffExp, isGeneSetSummary, field } = ownProps;
|
||||
const { isObs, isUserDefined, isGeneSetSummary, field } = ownProps;
|
||||
const myName = makeContinuousDimensionName(
|
||||
{ isObs, isUserDefined, isDiffExp, isGeneSetSummary },
|
||||
{ isObs, isUserDefined, isGeneSetSummary },
|
||||
field
|
||||
);
|
||||
return {
|
||||
@@ -80,7 +80,6 @@ class HistogramBrush extends React.PureComponent {
|
||||
field,
|
||||
isObs,
|
||||
isUserDefined,
|
||||
isDiffExp,
|
||||
isGeneSetSummary,
|
||||
} = this.props;
|
||||
|
||||
@@ -98,7 +97,6 @@ class HistogramBrush extends React.PureComponent {
|
||||
continuousNamespace: {
|
||||
isObs,
|
||||
isUserDefined,
|
||||
isDiffExp,
|
||||
isGeneSetSummary,
|
||||
},
|
||||
};
|
||||
@@ -115,7 +113,6 @@ class HistogramBrush extends React.PureComponent {
|
||||
field,
|
||||
isObs,
|
||||
isUserDefined,
|
||||
isDiffExp,
|
||||
isGeneSetSummary,
|
||||
} = this.props;
|
||||
const minAllowedBrushSize = 10;
|
||||
@@ -156,7 +153,6 @@ class HistogramBrush extends React.PureComponent {
|
||||
continuousNamespace: {
|
||||
isObs,
|
||||
isUserDefined,
|
||||
isDiffExp,
|
||||
isGeneSetSummary,
|
||||
},
|
||||
};
|
||||
@@ -362,10 +358,7 @@ class HistogramBrush extends React.PureComponent {
|
||||
field,
|
||||
isColorAccessor,
|
||||
isUserDefined,
|
||||
isDiffExp,
|
||||
logFoldChange,
|
||||
isGeneSetSummary,
|
||||
pvalAdj,
|
||||
isScatterplotXXaccessor,
|
||||
isScatterplotYYaccessor,
|
||||
zebra,
|
||||
@@ -383,7 +376,7 @@ class HistogramBrush extends React.PureComponent {
|
||||
heightMini,
|
||||
} = this.state;
|
||||
const fieldForId = field.replace(/\s/g, "_");
|
||||
const showScatterPlot = isDiffExp || isUserDefined;
|
||||
const showScatterPlot = isUserDefined;
|
||||
|
||||
return (
|
||||
<Async
|
||||
@@ -406,9 +399,7 @@ class HistogramBrush extends React.PureComponent {
|
||||
id={`histogram_${fieldForId}`}
|
||||
data-testid={`histogram-${field}`}
|
||||
data-testclass={
|
||||
isDiffExp
|
||||
? "histogram-diffexp"
|
||||
: isUserDefined
|
||||
isUserDefined
|
||||
? "histogram-user-gene"
|
||||
: "histogram-continuous-metadata"
|
||||
}
|
||||
@@ -454,15 +445,12 @@ class HistogramBrush extends React.PureComponent {
|
||||
<HistogramFooter
|
||||
isGeneSetSummary={isGeneSetSummary}
|
||||
isObs={isObs}
|
||||
isDiffExp={isDiffExp}
|
||||
displayName={field}
|
||||
hideRanges={asyncProps.isSingleValue}
|
||||
rangeMin={asyncProps.unclippedRange[0]}
|
||||
rangeMax={asyncProps.unclippedRange[1]}
|
||||
rangeColorMin={asyncProps.unclippedRangeColor[0]}
|
||||
rangeColorMax={asyncProps.unclippedRangeColor[1]}
|
||||
logFoldChange={logFoldChange}
|
||||
pvalAdj={pvalAdj}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -45,7 +45,6 @@ const LABEL_WIDTH_ANNO = LABEL_WIDTH - ANNO_BUTTON_WIDTH;
|
||||
crossfilter: state.obsCrossfilter,
|
||||
isUserAnno,
|
||||
genesets: state.genesets.genesets,
|
||||
differential: state.differential,
|
||||
};
|
||||
})
|
||||
class Category extends React.PureComponent {
|
||||
@@ -144,15 +143,14 @@ class Category extends React.PureComponent {
|
||||
*/
|
||||
const { schema } = annoMatrix;
|
||||
const { colorAccessor, colorMode } = colors;
|
||||
const { genesets, differential } = this.props;
|
||||
const { genesets } = this.props;
|
||||
let colorDataPromise = Promise.resolve(null);
|
||||
if (colorAccessor) {
|
||||
const query = createColorQuery(
|
||||
colorMode,
|
||||
colorAccessor,
|
||||
schema,
|
||||
genesets,
|
||||
differential.diffExp
|
||||
genesets
|
||||
);
|
||||
if (query) colorDataPromise = annoMatrix.fetch(...query);
|
||||
}
|
||||
|
||||
@@ -107,11 +107,10 @@ const continuous = (selectorId, colorScale, colorAccessor) => {
|
||||
annoMatrix: state.annoMatrix,
|
||||
colors: state.colors,
|
||||
genesets: state.genesets.genesets,
|
||||
differential: state.differential,
|
||||
}))
|
||||
class ContinuousLegend extends React.Component {
|
||||
async componentDidUpdate(prevProps) {
|
||||
const { annoMatrix, colors, genesets, differential } = this.props;
|
||||
const { annoMatrix, colors, genesets } = this.props;
|
||||
if (!colors || !annoMatrix) return;
|
||||
|
||||
if (colors !== prevProps?.colors || annoMatrix !== prevProps?.annoMatrix) {
|
||||
@@ -122,8 +121,7 @@ class ContinuousLegend extends React.Component {
|
||||
colorMode,
|
||||
colorAccessor,
|
||||
schema,
|
||||
genesets,
|
||||
differential.diffExp
|
||||
genesets
|
||||
);
|
||||
|
||||
const colorDf = colorQuery ? await annoMatrix.fetch(...colorQuery) : null;
|
||||
|
||||
@@ -63,9 +63,6 @@ class Gene extends React.Component {
|
||||
isColorAccessor,
|
||||
isScatterplotXXaccessor,
|
||||
isScatterplotYYaccessor,
|
||||
isDiffExp,
|
||||
pvalAdj,
|
||||
logFoldChange,
|
||||
} = this.props;
|
||||
const { geneIsExpanded } = this.state;
|
||||
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>
|
||||
</div>
|
||||
{!geneIsExpanded ? (
|
||||
isDiffExp ? (
|
||||
<HistogramBrush isDiffExp field={gene} mini />
|
||||
) : (
|
||||
<HistogramBrush isUserDefined field={gene} mini />
|
||||
)
|
||||
<HistogramBrush isUserDefined field={gene} mini />
|
||||
) : null}
|
||||
</div>
|
||||
<div style={{ flexShrink: 0, marginLeft: 2 }}>
|
||||
{!isDiffExp ? (
|
||||
<AnchorButton
|
||||
minimal
|
||||
small
|
||||
data-testid={`delete-from-geneset-${gene}`}
|
||||
onClick={this.handleDeleteGeneFromSet}
|
||||
intent="none"
|
||||
style={{ fontWeight: 700, marginRight: 2 }}
|
||||
icon={<Icon icon="trash" iconSize={10} />}
|
||||
/>
|
||||
) : null}
|
||||
<AnchorButton
|
||||
minimal
|
||||
small
|
||||
data-testid={`delete-from-geneset-${gene}`}
|
||||
onClick={this.handleDeleteGeneFromSet}
|
||||
intent="none"
|
||||
style={{ fontWeight: 700, marginRight: 2 }}
|
||||
icon={<Icon icon="trash" iconSize={10} />}
|
||||
/>
|
||||
)
|
||||
<AnchorButton
|
||||
minimal
|
||||
small
|
||||
@@ -184,17 +176,7 @@ class Gene extends React.Component {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{geneIsExpanded &&
|
||||
(isDiffExp ? (
|
||||
<HistogramBrush
|
||||
isDiffExp
|
||||
field={gene}
|
||||
pvalAdj={pvalAdj}
|
||||
logFoldChange={logFoldChange}
|
||||
/>
|
||||
) : (
|
||||
<HistogramBrush isUserDefined field={gene} />
|
||||
))}
|
||||
{geneIsExpanded && <HistogramBrush isUserDefined field={gene} />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -79,33 +79,8 @@ class GeneSet extends React.Component {
|
||||
};
|
||||
|
||||
renderGenes() {
|
||||
const {
|
||||
setName,
|
||||
setGenes,
|
||||
setGenesWithDescriptions,
|
||||
isDiffExp,
|
||||
diffExp,
|
||||
} = this.props;
|
||||
const { setName, setGenes, setGenesWithDescriptions } = 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) => {
|
||||
const { geneDescription } = setGenesWithDescriptions.get(gene);
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ import CreateGenesetDialogue from "./menus/createGenesetDialogue";
|
||||
|
||||
@connect((state) => {
|
||||
return {
|
||||
differential: state.differential,
|
||||
genesets: state.genesets.genesets,
|
||||
};
|
||||
})
|
||||
@@ -30,24 +29,6 @@ class GeneExpression extends React.Component {
|
||||
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 = () => {
|
||||
const { dispatch } = this.props;
|
||||
dispatch({ type: "geneset: activate add new geneset mode" });
|
||||
@@ -68,7 +49,6 @@ class GeneExpression extends React.Component {
|
||||
</div>
|
||||
<CreateGenesetDialogue />
|
||||
</div>
|
||||
<div>{this.renderDiffexpGeneSets()}</div>
|
||||
<div>{this.renderGeneSets()}</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -54,7 +54,6 @@ const filterGenes = (query, genes) =>
|
||||
annoMatrix: state.annoMatrix,
|
||||
userDefinedGenes: state.controls.userDefinedGenes,
|
||||
userDefinedGenesLoading: state.controls.userDefinedGenesLoading,
|
||||
differential: state.differential,
|
||||
};
|
||||
})
|
||||
class AddGenes extends React.Component {
|
||||
|
||||
@@ -77,7 +77,6 @@ function createModelTF() {
|
||||
colors: state.colors,
|
||||
pointDilation: state.pointDilation,
|
||||
genesets: state.genesets.genesets,
|
||||
differential: state.differential,
|
||||
}))
|
||||
class Graph extends React.Component {
|
||||
static createReglState(canvas) {
|
||||
@@ -785,17 +784,11 @@ class Graph extends React.Component {
|
||||
}
|
||||
|
||||
createColorByQuery(colors) {
|
||||
const { annoMatrix, genesets, differential } = this.props;
|
||||
const { annoMatrix, genesets } = this.props;
|
||||
const { schema } = annoMatrix;
|
||||
const { colorMode, colorAccessor } = colors;
|
||||
|
||||
return createColorQuery(
|
||||
colorMode,
|
||||
colorAccessor,
|
||||
schema,
|
||||
genesets,
|
||||
differential.diffExp
|
||||
);
|
||||
return createColorQuery(colorMode, colorAccessor, schema, genesets);
|
||||
}
|
||||
|
||||
renderPoints(
|
||||
|
||||
@@ -15,7 +15,6 @@ export default
|
||||
categoricalSelection: state.categoricalSelection,
|
||||
showLabels: state.centroidLabels?.showLabels,
|
||||
genesets: state.genesets.genesets,
|
||||
differential: state.differential,
|
||||
}))
|
||||
class CentroidLabels extends PureComponent {
|
||||
static watchAsync(props, prevProps) {
|
||||
@@ -76,16 +75,10 @@ class CentroidLabels extends PureComponent {
|
||||
};
|
||||
|
||||
colorByQuery() {
|
||||
const { annoMatrix, colors, genesets, differential } = this.props;
|
||||
const { annoMatrix, colors, genesets } = this.props;
|
||||
const { schema } = annoMatrix;
|
||||
const { colorMode, colorAccessor } = colors;
|
||||
return createColorQuery(
|
||||
colorMode,
|
||||
colorAccessor,
|
||||
schema,
|
||||
genesets,
|
||||
differential.diffExp
|
||||
);
|
||||
return createColorQuery(colorMode, colorAccessor, schema, genesets);
|
||||
}
|
||||
|
||||
async fetchData() {
|
||||
|
||||
@@ -9,12 +9,9 @@ import actions from "../../actions";
|
||||
}))
|
||||
class CellSetButton extends React.PureComponent {
|
||||
set() {
|
||||
const { differential, dispatch, eitherCellSetOneOrTwo } = this.props;
|
||||
const { dispatch, eitherCellSetOneOrTwo } = this.props;
|
||||
|
||||
if (!differential.diffExp) {
|
||||
// disallow this action if the user has active differential expression results
|
||||
dispatch(actions.setCellSetFromSelection(eitherCellSetOneOrTwo));
|
||||
}
|
||||
dispatch(actions.setCellSetFromSelection(eitherCellSetOneOrTwo));
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -31,7 +28,6 @@ class CellSetButton extends React.PureComponent {
|
||||
>
|
||||
<AnchorButton
|
||||
type="button"
|
||||
disabled={differential.diffExp}
|
||||
onClick={() => {
|
||||
this.set();
|
||||
}}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from "react";
|
||||
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 styles from "./menubar.css";
|
||||
import actions from "../../actions";
|
||||
@@ -8,8 +8,6 @@ import CellSetButton from "./cellSetButtons";
|
||||
|
||||
@connect((state) => ({
|
||||
differential: state.differential,
|
||||
celllist1: state.differential?.celllist1,
|
||||
celllist2: state.differential?.celllist2,
|
||||
diffexpMayBeSlow: state.config?.parameters?.["diffexp-may-be-slow"] ?? false,
|
||||
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() {
|
||||
/* diffexp-related buttons may be disabled */
|
||||
const { differential, diffexpMayBeSlow, diffexpCellcountMax } = this.props;
|
||||
@@ -65,41 +52,22 @@ class DiffexpButtons extends React.PureComponent {
|
||||
<ButtonGroup className={styles.menubarButton}>
|
||||
<CellSetButton eitherCellSetOneOrTwo={1} />
|
||||
<CellSetButton eitherCellSetOneOrTwo={2} />
|
||||
{!differential.diffExp ? (
|
||||
<Tooltip
|
||||
content={warnMaxSizeExceeded ? tipMessageWarn : tipMessage}
|
||||
position="bottom"
|
||||
hoverOpenDelay={globals.tooltipHoverOpenDelayQuick}
|
||||
intent={warnMaxSizeExceeded ? "danger" : "none"}
|
||||
>
|
||||
<AnchorButton
|
||||
disabled={!haveBothCellSets || warnMaxSizeExceeded}
|
||||
intent={warnMaxSizeExceeded ? "danger" : "primary"}
|
||||
data-testid="diffexp-button"
|
||||
loading={differential.loading}
|
||||
icon="left-join"
|
||||
fill
|
||||
onClick={this.computeDiffExp}
|
||||
/>
|
||||
</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}
|
||||
<Tooltip
|
||||
content={warnMaxSizeExceeded ? tipMessageWarn : tipMessage}
|
||||
position="bottom"
|
||||
hoverOpenDelay={globals.tooltipHoverOpenDelayQuick}
|
||||
intent={warnMaxSizeExceeded ? "danger" : "none"}
|
||||
>
|
||||
<AnchorButton
|
||||
disabled={!haveBothCellSets || warnMaxSizeExceeded}
|
||||
intent={warnMaxSizeExceeded ? "danger" : "primary"}
|
||||
data-testid="diffexp-button"
|
||||
loading={differential.loading}
|
||||
icon="left-join"
|
||||
fill
|
||||
onClick={this.computeDiffExp}
|
||||
/>
|
||||
</Tooltip>
|
||||
</ButtonGroup>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -29,17 +29,13 @@ import { getEmbSubsetView } from "../../util/stateManager/viewStackHelpers";
|
||||
return {
|
||||
subsetPossible,
|
||||
subsetResetPossible,
|
||||
differential: state.differential,
|
||||
graphInteractionMode: state.controls.graphInteractionMode,
|
||||
clipPercentileMin: Math.round(100 * (annoMatrix?.clipRange?.[0] ?? 0)),
|
||||
clipPercentileMax: Math.round(100 * (annoMatrix?.clipRange?.[1] ?? 1)),
|
||||
userDefinedGenes: state.controls.userDefinedGenes,
|
||||
diffexpGenes: state.controls.diffexpGenes,
|
||||
colorAccessor: state.colors.colorAccessor,
|
||||
scatterplotXXaccessor: state.controls.scatterplotXXaccessor,
|
||||
scatterplotYYaccessor: state.controls.scatterplotYYaccessor,
|
||||
celllist1: state.differential.celllist1,
|
||||
celllist2: state.differential.celllist2,
|
||||
libraryVersions: state.config?.library_versions,
|
||||
auth: state.config?.authentication,
|
||||
userInfo: state.userInfo,
|
||||
|
||||
@@ -51,7 +51,6 @@ const getYScale = memoize(getScale);
|
||||
scatterplotXXaccessor,
|
||||
scatterplotYYaccessor,
|
||||
|
||||
differential: state.differential,
|
||||
crossfilter,
|
||||
genesets: state.genesets.genesets,
|
||||
};
|
||||
@@ -314,16 +313,10 @@ class Scatterplot extends React.PureComponent {
|
||||
}
|
||||
|
||||
createColorByQuery(colors) {
|
||||
const { annoMatrix, genesets, differential } = this.props;
|
||||
const { annoMatrix, genesets } = this.props;
|
||||
const { schema } = annoMatrix;
|
||||
const { colorMode, colorAccessor } = colors;
|
||||
return createColorQuery(
|
||||
colorMode,
|
||||
colorAccessor,
|
||||
schema,
|
||||
genesets,
|
||||
differential
|
||||
);
|
||||
return createColorQuery(colorMode, colorAccessor, schema, genesets);
|
||||
}
|
||||
|
||||
updateColorTable(colors, colorDf) {
|
||||
|
||||
@@ -7,9 +7,7 @@ const ColorsReducer = (
|
||||
colorMode: null /* by continuous, by expression */,
|
||||
colorAccessor: null /* tissue, Apod */,
|
||||
},
|
||||
action,
|
||||
nextSharedState,
|
||||
prevSharedState
|
||||
action
|
||||
) => {
|
||||
switch (action.type) {
|
||||
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": {
|
||||
const { colorAccessor } = state;
|
||||
if (action.metadataField !== colorAccessor) {
|
||||
|
||||
25
client/src/reducers/controls.js
vendored
25
client/src/reducers/controls.js
vendored
@@ -1,6 +1,5 @@
|
||||
import uniq from "lodash.uniq";
|
||||
import filter from "lodash.filter";
|
||||
import { subsetAndResetGeneLists } from "../util/stateManager/controlsHelpers";
|
||||
|
||||
const Controls = (
|
||||
state = {
|
||||
@@ -11,7 +10,6 @@ const Controls = (
|
||||
// all of the data + selection state
|
||||
userDefinedGenes: [],
|
||||
userDefinedGenesLoading: false,
|
||||
diffexpGenes: [],
|
||||
|
||||
resettingInterface: false,
|
||||
graphInteractionMode: "select",
|
||||
@@ -45,26 +43,16 @@ const Controls = (
|
||||
};
|
||||
}
|
||||
case "reset subset": {
|
||||
const [newUserDefinedGenes, newDiffExpGenes] = subsetAndResetGeneLists(
|
||||
state
|
||||
);
|
||||
return {
|
||||
...state,
|
||||
resettingInterface: false,
|
||||
userDefinedGenes: newUserDefinedGenes,
|
||||
diffexpGenes: newDiffExpGenes,
|
||||
};
|
||||
}
|
||||
case "subset to selection": {
|
||||
const [newUserDefinedGenes, newDiffExpGenes] = subsetAndResetGeneLists(
|
||||
state
|
||||
);
|
||||
return {
|
||||
...state,
|
||||
loading: false,
|
||||
error: null,
|
||||
userDefinedGenes: newUserDefinedGenes,
|
||||
diffexpGenes: newDiffExpGenes,
|
||||
};
|
||||
}
|
||||
case "request user defined gene started": {
|
||||
@@ -90,19 +78,6 @@ const Controls = (
|
||||
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": {
|
||||
const { userDefinedGenes } = state;
|
||||
const newUserDefinedGenes = filter(
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
const Differential = (
|
||||
state = {
|
||||
diffExp: null,
|
||||
loading: null,
|
||||
error: null,
|
||||
celllist1: null,
|
||||
@@ -20,7 +19,6 @@ const Differential = (
|
||||
...state,
|
||||
error: null,
|
||||
loading: false,
|
||||
diffExp: action.data,
|
||||
};
|
||||
case "request differential expression error":
|
||||
return {
|
||||
@@ -38,18 +36,10 @@ const Differential = (
|
||||
...state,
|
||||
celllist2: action.data,
|
||||
};
|
||||
case "clear differential expression":
|
||||
return {
|
||||
...state,
|
||||
diffExp: null,
|
||||
celllist1: null,
|
||||
celllist2: null,
|
||||
};
|
||||
case "reset subset":
|
||||
case "subset to selection":
|
||||
return {
|
||||
...state,
|
||||
diffExp: null,
|
||||
celllist1: null,
|
||||
celllist2: null,
|
||||
};
|
||||
|
||||
@@ -69,6 +69,7 @@ const GeneSets = (
|
||||
}
|
||||
|
||||
return {
|
||||
...state,
|
||||
initialized: true,
|
||||
lastTid,
|
||||
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:
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -185,20 +185,6 @@ const createFsmTransitions = (
|
||||
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) */
|
||||
{
|
||||
event: "clear scatterplot",
|
||||
|
||||
@@ -12,13 +12,7 @@ import { range } from "../range";
|
||||
given a color mode & accessor, generate an annoMatrix query that will
|
||||
fulfill it
|
||||
*/
|
||||
export function createColorQuery(
|
||||
colorMode,
|
||||
colorByAccessor,
|
||||
schema,
|
||||
genesets,
|
||||
diffExp
|
||||
) {
|
||||
export function createColorQuery(colorMode, colorByAccessor, schema, genesets) {
|
||||
if (!colorMode || !colorByAccessor || !schema || !genesets) return null;
|
||||
|
||||
switch (colorMode) {
|
||||
@@ -46,19 +40,8 @@ export function createColorQuery(
|
||||
if (!varIndex) return null;
|
||||
if (!genesets) return null;
|
||||
|
||||
let _geneset;
|
||||
let _setGenes;
|
||||
|
||||
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()];
|
||||
}
|
||||
const _geneset = genesets.get(colorByAccessor);
|
||||
const _setGenes = [..._geneset.genes.keys()];
|
||||
|
||||
return [
|
||||
"X",
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
Helper functions for the controls reducer
|
||||
*/
|
||||
|
||||
import uniq from "lodash.uniq";
|
||||
import difference from "lodash.difference";
|
||||
|
||||
import * as globals from "../../globals";
|
||||
@@ -158,12 +157,3 @@ export function pruneVarDataCache(varData, needed) {
|
||||
}
|
||||
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];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user