feat: diffexp returns two genesets (#2230)

* feat: return two lists for diffexp (#2221)

* sp

* split out derive sort order, tests passing

* sp

* return diff exp results in two lists

* update

* copy implementation over to desktop

* add tests for two lists

* small fixes to complete backend implementation

* accept new diffexp response

* map diff exp response to genesets

* delete )

* name diffexp genesets with population names

* take constants out of state and allow width prop to override

* shorten mini-histo properly truncate and resize depending on expansion

* prepend new genesets

* rename data within diffexp action

* backend

* move diffexp ttest to common code module, update tests

* update for unit tests

* reference actual var

Co-authored-by: Madison Dunitz <madison.dunitz@chanzuckerberg.com>
Co-authored-by: Madison Dunitz <dunitzm@gmail.com>
This commit is contained in:
Severiano Badajoz
2021-06-08 21:02:19 +00:00
committed by GitHub
co-authored by Madison Dunitz Madison Dunitz
parent 7ed53c0f5b
commit 28b526b3fc
25 changed files with 268 additions and 284 deletions
@@ -26,7 +26,13 @@ const Histogram = ({
/*
Create the d3 histogram
*/
const { marginLeft, marginRight, marginBottom, marginTop } = margin;
// This is just a constant that's flipped by parent's `mini` boolean
const {
LEFT: marginLeft,
RIGHT: marginRight,
BOTTOM: marginBottom,
TOP: marginTop,
} = margin;
const { x, y, bins, binStart, binEnd, binWidth } = histogram;
const svg = d3.select(svgRef.current);
const binPadding = mini ? 0 : -1;
@@ -13,6 +13,23 @@ import HistogramFooter from "./footer";
import StillLoading from "./loading";
import ErrorLoading from "./error";
const MARGIN = {
LEFT: 10, // Space for 0 tick label on X axis
RIGHT: 54, // space for Y axis & labels
BOTTOM: 25, // space for X axis & labels
TOP: 3,
};
const WIDTH = 340 - MARGIN.LEFT - MARGIN.RIGHT;
const HEIGHT = 135 - MARGIN.TOP - MARGIN.BOTTOM;
const MARGIN_MINI = {
LEFT: 0, // Space for 0 tick label on X axis
RIGHT: 0, // space for Y axis & labels
BOTTOM: 0, // space for X axis & labels
TOP: 0,
};
const WIDTH_MINI = 120 - MARGIN_MINI.LEFT - MARGIN_MINI.RIGHT;
const HEIGHT_MINI = 15 - MARGIN_MINI.TOP - MARGIN_MINI.BOTTOM;
@connect((state, ownProps) => {
const { isObs, isUserDefined, isGeneSetSummary, field } = ownProps;
const myName = makeContinuousDimensionName(
@@ -44,34 +61,6 @@ class HistogramBrush extends React.PureComponent {
}
});
constructor(props) {
super(props);
const marginLeft = 10; // Space for 0 tick label on X axis
const marginRight = 54; // space for Y axis & labels
const marginBottom = 25; // space for X axis & labels
const marginTop = 3;
this.state = {
margin: {
marginLeft,
marginRight,
marginBottom,
marginTop,
},
width: 340 - marginLeft - marginRight,
height: 135 - marginTop - marginBottom,
marginMini: {
marginLeft: 0, // Space for 0 tick label on X axis
marginRight: 0, // space for Y axis & labels
marginBottom: 0, // space for X axis & labels
marginTop: 0,
},
widthMini: 120,
heightMini: 15,
};
}
onBrush = (selection, x, eventType) => {
const type = `continuous metadata histogram ${eventType}`;
return () => {
@@ -210,15 +199,8 @@ class HistogramBrush extends React.PureComponent {
};
fetchAsyncProps = async () => {
const { annoMatrix } = this.props;
const {
margin,
width,
height,
marginMini,
widthMini,
heightMini,
} = this.state;
const { annoMatrix, width } = this.props;
const { isClipped } = annoMatrix;
const query = this.createQuery();
@@ -246,12 +228,17 @@ class HistogramBrush extends React.PureComponent {
: globals.blue,
];
const histogram = this.calcHistogramCache(column, margin, width, height);
const histogram = this.calcHistogramCache(
column,
MARGIN,
width || WIDTH,
HEIGHT
);
const miniHistogram = this.calcHistogramCache(
column,
marginMini,
widthMini,
heightMini
MARGIN_MINI,
width || WIDTH_MINI,
HEIGHT_MINI
);
const isSingleValue = summary.min === summary.max;
@@ -275,7 +262,7 @@ class HistogramBrush extends React.PureComponent {
};
// eslint-disable-next-line class-methods-use-this -- instance method allows for memoization per annotation
calcHistogramCache(col, margin, width, height) {
calcHistogramCache(col, newMargin, newWidth, newHeight) {
/*
recalculate expensive stuff, notably bins, summaries, etc.
*/
@@ -283,7 +270,10 @@ class HistogramBrush extends React.PureComponent {
const summary = col.summarize(); /* this is memoized, so it's free the second time you call it */
const { min: domainMin, max: domainMax } = summary;
const numBins = 40;
const { marginTop, marginLeft } = margin; /* changes with mini */
const {
TOP: topMargin,
LEFT: leftMargin,
} = newMargin; /* changes with mini */
histogramCache.domain = [
domainMin,
@@ -293,7 +283,7 @@ class HistogramBrush extends React.PureComponent {
histogramCache.x = d3
.scaleLinear()
.domain([domainMin, domainMax])
.range([marginLeft, marginLeft + width]);
.range([leftMargin, leftMargin + newWidth]);
histogramCache.bins = histogramContinuous(col, numBins, [
domainMin,
@@ -310,7 +300,7 @@ class HistogramBrush extends React.PureComponent {
histogramCache.y = d3
.scaleLinear()
.domain([0, yMax])
.range([marginTop + height, marginTop]);
.range([topMargin + newHeight, topMargin]);
return histogramCache;
}
@@ -367,14 +357,12 @@ class HistogramBrush extends React.PureComponent {
mini,
setGenes,
} = this.props;
const {
margin,
width,
height,
marginMini,
widthMini,
heightMini,
} = this.state;
let { width } = this.props;
if (!width) {
width = mini ? WIDTH_MINI : WIDTH;
}
const fieldForId = field.replace(/\s/g, "_");
const showScatterPlot = isUserDefined;
@@ -432,11 +420,11 @@ class HistogramBrush extends React.PureComponent {
histogram={
mini ? asyncProps.miniHistogram : asyncProps.histogram
}
width={mini ? widthMini : width}
height={mini ? heightMini : height}
width={width}
height={mini ? HEIGHT_MINI : HEIGHT}
onBrush={this.onBrush}
onBrushEnd={this.onBrushEnd}
margin={mini ? marginMini : margin}
margin={mini ? MARGIN_MINI : MARGIN}
isColorBy={isColorAccessor}
selectionRange={continuousSelectionRange}
mini={mini}
+19 -13
View File
@@ -1,13 +1,14 @@
import React from "react";
import { connect } from "react-redux";
import { AnchorButton, Icon } from "@blueprintjs/core";
import { Button, Icon } from "@blueprintjs/core";
import Truncate from "../util/truncate";
import HistogramBrush from "../brushableHistogram";
import * as globals from "../../globals";
import actions from "../../actions";
const MINI_HISTOGRAM_WIDTH = 110;
@connect((state, ownProps) => {
const { gene } = ownProps;
@@ -65,7 +66,7 @@ class Gene extends React.Component {
isScatterplotYYaccessor,
} = this.props;
const { geneIsExpanded } = this.state;
const genesetNameLengthVisible = 310; /* this magic number determines how much of a long geneset name we see */
const geneSymbolWidth = 60 + (geneIsExpanded ? MINI_HISTOGRAM_WIDTH : 0);
return (
<div>
@@ -108,7 +109,8 @@ class Gene extends React.Component {
>
<span
style={{
width: globals.leftSidebarWidth - genesetNameLengthVisible,
width: geneSymbolWidth,
display: "inline-block",
}}
data-testid={`${gene}:gene-label`}
>
@@ -117,11 +119,16 @@ class Gene extends React.Component {
</Truncate>
</div>
{!geneIsExpanded ? (
<HistogramBrush isUserDefined field={gene} mini />
<HistogramBrush
isUserDefined
field={gene}
mini
width={MINI_HISTOGRAM_WIDTH}
/>
) : null}
</div>
<div style={{ flexShrink: 0, marginLeft: 2 }}>
<AnchorButton
<Button
minimal
small
data-testid={`delete-from-geneset-${gene}`}
@@ -130,8 +137,7 @@ class Gene extends React.Component {
style={{ fontWeight: 700, marginRight: 2 }}
icon={<Icon icon="trash" iconSize={10} />}
/>
)
<AnchorButton
<Button
minimal
small
data-testid={`plot-x-${gene}`}
@@ -141,8 +147,8 @@ class Gene extends React.Component {
style={{ fontWeight: 700, marginRight: 2 }}
>
x
</AnchorButton>
<AnchorButton
</Button>
<Button
minimal
small
data-testid={`plot-y-${gene}`}
@@ -152,8 +158,8 @@ class Gene extends React.Component {
style={{ fontWeight: 700, marginRight: 2 }}
>
y
</AnchorButton>
<AnchorButton
</Button>
<Button
minimal
small
data-testclass="maximize"
@@ -164,7 +170,7 @@ class Gene extends React.Component {
icon={<Icon icon="maximize" iconSize={10} />}
style={{ marginRight: 2 }}
/>
<AnchorButton
<Button
minimal
small
data-testclass="colorby"