mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-10-02 10:08:12 +08:00
Merge branch 'master' of https://github.com/chanzuckerberg/cellxgene into bkmartinjr-crossfiltergroups
This commit is contained in:
+5
-3
@@ -33,9 +33,10 @@
|
||||
"express": "^4.14.0",
|
||||
"font-color-contrast": "^1.0.3",
|
||||
"gl-mat4": "^1.1.4",
|
||||
"gl-matrix": "^2.4.0",
|
||||
"gl-matrix": "^2.7.1",
|
||||
"halogen": "^0.2.0",
|
||||
"hsv2rgb": "^1.1.0",
|
||||
"jest": "^23.4.1",
|
||||
"key-pressed": "0.0.1",
|
||||
"lodash": "^4.17.4",
|
||||
"luma.gl": "^4.0.3",
|
||||
@@ -43,9 +44,9 @@
|
||||
"mouse-pressed": "^1.0.0",
|
||||
"orbit-camera": "^1.0.0",
|
||||
"query-string": "^5.0.0",
|
||||
"react": "^15.3.0",
|
||||
"react": "^16.4.1",
|
||||
"react-autocomplete": "^1.7.2",
|
||||
"react-dom": "^15.3.0",
|
||||
"react-dom": "^16.4.1",
|
||||
"react-helmet": "^5.2.0",
|
||||
"react-hot-loader": "^3.0.0-beta.7",
|
||||
"react-icons": "^2.2.7",
|
||||
@@ -57,6 +58,7 @@
|
||||
"scroll-speed": "^1.0.0",
|
||||
"serve-favicon": "^2.3.0",
|
||||
"urijs": "^1.19.0",
|
||||
"webpack-hot-middleware": "^2.22.3",
|
||||
"whatwg-fetch": "^2.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -4,7 +4,7 @@ import _ from "lodash";
|
||||
import Helmet from "react-helmet";
|
||||
import Container from "./framework/container";
|
||||
import { connect } from "react-redux";
|
||||
import PulseLoader from "halogen/PulseLoader";
|
||||
// import PulseLoader from "halogen/PulseLoader";
|
||||
|
||||
import LeftSideBar from "./leftsidebar";
|
||||
import Parallel from "./continuous/parallel";
|
||||
@@ -69,7 +69,7 @@ class App extends React.Component {
|
||||
<div
|
||||
style={{ position: "fixed", left: window.innerWidth / 2, top: 150 }}
|
||||
>
|
||||
<PulseLoader color="rgb(0,0,0)" size="10px" margin="4px" />
|
||||
{/*<PulseLoader color="rgb(0,0,0)" size="10px" margin="4px" />*/}
|
||||
<span
|
||||
style={{ fontFamily: globals.accentFont, fontStyle: "italic" }}
|
||||
>
|
||||
|
||||
@@ -30,7 +30,7 @@ class Category extends React.Component {
|
||||
componentDidUpdate() {
|
||||
const valuesAsBool = _.values(
|
||||
this.props.categoricalAsBooleansMap[this.props.metadataField]
|
||||
)
|
||||
);
|
||||
/* count categories toggled on by counting true values */
|
||||
const categoriesToggledOn = _.values(valuesAsBool).filter(v => v).length;
|
||||
|
||||
@@ -80,13 +80,13 @@ class Category extends React.Component {
|
||||
});
|
||||
}
|
||||
handleToggleAllClick() {
|
||||
// || this.checkbox.indeterminate === false
|
||||
// || this.checkbox.indeterminate === false
|
||||
if (this.state.isChecked) {
|
||||
console.log('checked, firing toggle none')
|
||||
console.log("checked, firing toggle none");
|
||||
this.toggleNone();
|
||||
} else if (!this.state.isChecked) {
|
||||
console.log('!checked, firing toggle all')
|
||||
this.toggleAll()
|
||||
console.log("!checked, firing toggle all");
|
||||
this.toggleAll();
|
||||
}
|
||||
}
|
||||
render() {
|
||||
@@ -131,7 +131,7 @@ class Category extends React.Component {
|
||||
{this.props.metadataField}
|
||||
<input
|
||||
onChange={this.handleToggleAllClick.bind(this)}
|
||||
ref={el => this.checkbox = el}
|
||||
ref={el => (this.checkbox = el)}
|
||||
checked={this.state.isChecked}
|
||||
type="checkbox"
|
||||
/>
|
||||
@@ -164,10 +164,7 @@ class Category extends React.Component {
|
||||
}
|
||||
|
||||
@connect(state => {
|
||||
const ranges =
|
||||
state.cells.cells && state.cells.cells.data.ranges
|
||||
? state.cells.cells.data.ranges
|
||||
: null;
|
||||
const ranges = _.get("state.cells.cells.data.ranges", null);
|
||||
|
||||
return {
|
||||
ranges
|
||||
|
||||
@@ -17,19 +17,9 @@ import HistogramBrush from "./histogramBrush";
|
||||
import { margin, width, height, createDimensions } from "./util";
|
||||
|
||||
@connect(state => {
|
||||
const ranges =
|
||||
state.cells.cells && state.cells.cells.data.ranges
|
||||
? state.cells.cells.data.ranges
|
||||
: null;
|
||||
const metadata =
|
||||
state.cells.cells && state.cells.cells.data.metadata
|
||||
? state.cells.cells.data.metadata
|
||||
: null;
|
||||
|
||||
const initializeRanges =
|
||||
state.initialize.data && state.initialize.data.data.ranges
|
||||
? state.initialize.data.data.ranges
|
||||
: null;
|
||||
const ranges = _.get("state.cells.cells.data.ranges", null);
|
||||
const metadata = _.get("state.cells.cells.data.metadata", null);
|
||||
const initializeRanges = _.get("state.initialize.data.data.ranges", null);
|
||||
|
||||
return {
|
||||
ranges,
|
||||
@@ -51,10 +41,6 @@ class Continuous extends React.Component {
|
||||
dimensions: null
|
||||
};
|
||||
}
|
||||
componentDidMount() {}
|
||||
componentWillReceiveProps(nextProps) {}
|
||||
|
||||
componentDidMount() {}
|
||||
handleBrushAction(selection) {
|
||||
this.props.dispatch({
|
||||
type: "continuous selection using parallel coords brushing",
|
||||
|
||||
@@ -11,25 +11,13 @@ import FaPaintBrush from "react-icons/lib/fa/paint-brush";
|
||||
import * as globals from "../../globals";
|
||||
|
||||
@connect(state => {
|
||||
const ranges =
|
||||
state.cells.cells && state.cells.cells.data.ranges
|
||||
? state.cells.cells.data.ranges
|
||||
: null;
|
||||
const metadata =
|
||||
state.cells.cells && state.cells.cells.data.metadata
|
||||
? state.cells.cells.data.metadata
|
||||
: null;
|
||||
|
||||
const initializeRanges =
|
||||
state.initialize.data && state.initialize.data.data.ranges
|
||||
? state.initialize.data.data.ranges
|
||||
: null;
|
||||
const initializeRanges = _.get("state.initialize.data.data.ranges", null);
|
||||
|
||||
return {
|
||||
initializeRanges,
|
||||
colorAccessor: state.controls.colorAccessor,
|
||||
colorScale: state.controls.colorScale,
|
||||
cellsMetadata: state.controls.cellsMetadata,
|
||||
initializeRanges
|
||||
cellsMetadata: state.controls.cellsMetadata
|
||||
};
|
||||
})
|
||||
class HistogramBrush extends React.Component {
|
||||
@@ -49,9 +37,6 @@ class HistogramBrush extends React.Component {
|
||||
brush: null
|
||||
};
|
||||
}
|
||||
componentDidMount() {}
|
||||
componentDidUpdate() {}
|
||||
|
||||
calcHistogramCache(nextProps) {
|
||||
// recalculate expensive stuff
|
||||
const allValuesForContinuousFieldAsArray = _.map(
|
||||
@@ -80,14 +65,6 @@ class HistogramBrush extends React.Component {
|
||||
componentWillMount() {
|
||||
this.calcHistogramCache(this.props);
|
||||
}
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (
|
||||
this.props.metadataField !== nextProps.metadataField ||
|
||||
!this.histogramCache.x
|
||||
) {
|
||||
this.calcHistogramCache(nextProps);
|
||||
}
|
||||
}
|
||||
|
||||
onBrush(selection, x) {
|
||||
return () => {
|
||||
|
||||
@@ -15,19 +15,9 @@ import drawLinesCanvas from "./drawLinesCanvas";
|
||||
import { margin, width, height, createDimensions } from "./util";
|
||||
|
||||
@connect(state => {
|
||||
const ranges =
|
||||
state.cells.cells && state.cells.cells.data.ranges
|
||||
? state.cells.cells.data.ranges
|
||||
: null;
|
||||
const metadata =
|
||||
state.cells.cells && state.cells.cells.data.metadata
|
||||
? state.cells.cells.data.metadata
|
||||
: null;
|
||||
|
||||
const initializeRanges =
|
||||
state.initialize.data && state.initialize.data.data.ranges
|
||||
? state.initialize.data.data.ranges
|
||||
: null;
|
||||
const ranges = _.get("state.cells.cells.data.ranges", null);
|
||||
const metadata = _.get("state.cells.cells.data.metadata", null);
|
||||
const initializeRanges = _.get("state.initialize.data.data.ranges", null);
|
||||
|
||||
return {
|
||||
ranges,
|
||||
|
||||
@@ -102,27 +102,26 @@ class ContinuousLegend extends React.Component {
|
||||
super(props);
|
||||
this.state = {};
|
||||
}
|
||||
componentWillReceiveProps(nextProps) {
|
||||
componentDidUpdate(prevProps) {
|
||||
if (
|
||||
nextProps.colorAccessor !== this.props.colorAccessor ||
|
||||
nextProps.responsive.height !== this.props.responsive.height ||
|
||||
nextProps.responsive.width !== this.props.responsive.width
|
||||
prevProps.colorAccessor !== this.props.colorAccessor ||
|
||||
prevProps.responsive.height !== this.props.responsive.height ||
|
||||
prevProps.responsive.width !== this.props.responsive.width
|
||||
) {
|
||||
/* always remove it, if it's not continuous we don't put it back. */
|
||||
d3
|
||||
.select("#continuous_legend")
|
||||
d3.select("#continuous_legend")
|
||||
.selectAll("*")
|
||||
.remove();
|
||||
}
|
||||
|
||||
if (nextProps.colorAccessor && nextProps.colorScale) {
|
||||
if (this.props.colorAccessor && this.props.colorScale) {
|
||||
/* fragile! continuous range is 0 to 1, not [#fa4b2c, ...], make this a flag? */
|
||||
if (nextProps.colorScale.range()[0][0] !== "#") {
|
||||
if (this.props.colorScale.range()[0][0] !== "#") {
|
||||
continuous(
|
||||
"#continuous_legend",
|
||||
d3
|
||||
.scaleSequential(d3.interpolateViridis)
|
||||
.domain(nextProps.colorScale.domain())
|
||||
.domain(this.props.colorScale.domain())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,10 +117,19 @@ class Graph extends React.Component {
|
||||
reglRender
|
||||
});
|
||||
}
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (this.state.regl && nextProps.crossfilter) {
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (
|
||||
this.state.reglRender &&
|
||||
this.reglRenderState === "rendering" &&
|
||||
this.state.mode !== "zoom"
|
||||
) {
|
||||
this.state.reglRender.cancel();
|
||||
this.reglRenderState = "paused";
|
||||
}
|
||||
|
||||
if (this.state.regl && this.props.crossfilter) {
|
||||
/* update the regl state */
|
||||
const crossfilter = nextProps.crossfilter.cells;
|
||||
const crossfilter = this.props.crossfilter.cells;
|
||||
const cells = crossfilter.all();
|
||||
const cellCount = cells.length;
|
||||
|
||||
@@ -129,7 +138,7 @@ class Graph extends React.Component {
|
||||
//
|
||||
if (
|
||||
!this.renderCache.positions ||
|
||||
this.props.crossfilter.cells != nextProps.crossfilter.cells
|
||||
this.props.crossfilter.cells != prevProps.crossfilter.cells
|
||||
) {
|
||||
if (!this.renderCache.positions)
|
||||
this.renderCache.positions = new Float32Array(2 * cellCount);
|
||||
@@ -161,7 +170,7 @@ class Graph extends React.Component {
|
||||
// we could add some sort of color-specific indicator to the app state.
|
||||
if (
|
||||
!this.renderCache.colors ||
|
||||
this.props.cellsMetadata != nextProps.cellsMetadata
|
||||
this.props.cellsMetadata != prevProps.cellsMetadata
|
||||
) {
|
||||
if (!this.renderCache.colors)
|
||||
this.renderCache.colors = new Float32Array(3 * cellCount);
|
||||
@@ -178,7 +187,7 @@ class Graph extends React.Component {
|
||||
//
|
||||
if (
|
||||
!this.renderCache.sizes ||
|
||||
this.props.crossfilter.cells != nextProps.crossfilter.cells
|
||||
this.props.crossfilter.cells != prevProps.crossfilter.cells
|
||||
) {
|
||||
this.renderCache.sizes = new Float32Array(cellCount);
|
||||
}
|
||||
@@ -200,33 +209,22 @@ class Graph extends React.Component {
|
||||
|
||||
if (
|
||||
/* invisibly handles the initial null vs integer case as well as resize events */
|
||||
nextProps.responsive.height !== this.props.responsive.height ||
|
||||
nextProps.responsive.width !== this.props.responsive.width
|
||||
prevProps.responsive.height !== this.props.responsive.height ||
|
||||
prevProps.responsive.width !== this.props.responsive.width
|
||||
) {
|
||||
/* clear out whatever was on the div, even if nothing, but usually the brushes etc */
|
||||
d3
|
||||
.select("#graphAttachPoint")
|
||||
d3.select("#graphAttachPoint")
|
||||
.selectAll("svg")
|
||||
.remove();
|
||||
const { svg, brush, brushContainer } = setupSVGandBrushElements(
|
||||
this.handleBrushSelectAction.bind(this),
|
||||
this.handleBrushDeselectAction.bind(this),
|
||||
nextProps.responsive,
|
||||
this.props.responsive,
|
||||
this.graphPaddingTop
|
||||
);
|
||||
this.setState({ svg, brush, brushContainer });
|
||||
}
|
||||
}
|
||||
componentDidUpdate() {
|
||||
if (
|
||||
this.state.reglRender &&
|
||||
this.reglRenderState === "rendering" &&
|
||||
this.state.mode !== "zoom"
|
||||
) {
|
||||
this.state.reglRender.cancel();
|
||||
this.reglRenderState = "paused";
|
||||
}
|
||||
}
|
||||
handleBrushSelectAction() {
|
||||
/* This conditional handles procedural brush deselect. Brush emits an event on procedural deselect because it is move: null */
|
||||
if (d3.event.sourceEvent !== null) {
|
||||
@@ -251,7 +249,7 @@ class Graph extends React.Component {
|
||||
// transform screen coordinates -> cell coordinates
|
||||
const invert = pin => {
|
||||
const x =
|
||||
2 * pin[0] / (this.props.responsive.height - this.graphPaddingTop) -
|
||||
(2 * pin[0]) / (this.props.responsive.height - this.graphPaddingTop) -
|
||||
1;
|
||||
const y =
|
||||
2 *
|
||||
|
||||
@@ -20,18 +20,9 @@ import { scaleLinear } from "../../util/scaleLinear";
|
||||
import { margin, width, height, createDimensions } from "./util";
|
||||
|
||||
@connect(state => {
|
||||
const ranges =
|
||||
state.cells.cells && state.cells.cells.data.ranges
|
||||
? state.cells.cells.data.ranges
|
||||
: null;
|
||||
const metadata =
|
||||
state.cells.cells && state.cells.cells.data.metadata
|
||||
? state.cells.cells.data.metadata
|
||||
: null;
|
||||
const initializeRanges =
|
||||
state.initialize.data && state.initialize.data.data.ranges
|
||||
? state.initialize.data.data.ranges
|
||||
: null;
|
||||
const ranges = _.get("state.cells.cells.data.ranges", null);
|
||||
const metadata = _.get("state.cells.cells.data.metadata", null);
|
||||
const initializeRanges = _.get("state.initialize.data.data.ranges", null);
|
||||
|
||||
return {
|
||||
ranges,
|
||||
@@ -123,21 +114,6 @@ class Scatterplot extends React.Component {
|
||||
colorBuffer
|
||||
});
|
||||
}
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (
|
||||
nextProps.expression &&
|
||||
nextProps.expression.data &&
|
||||
nextProps.scatterplotXXaccessor &&
|
||||
nextProps.scatterplotYYaccessor
|
||||
) {
|
||||
const scales = this.setupScales(
|
||||
nextProps.expression,
|
||||
nextProps.scatterplotXXaccessor,
|
||||
nextProps.scatterplotYYaccessor
|
||||
);
|
||||
this.setState(scales);
|
||||
}
|
||||
}
|
||||
componentDidUpdate(prevProps) {
|
||||
if (
|
||||
this.state.svg &&
|
||||
@@ -213,6 +189,22 @@ class Scatterplot extends React.Component {
|
||||
this.state.sizeBuffer({ data: sizes, dimension: 1 });
|
||||
this.count = cellCount;
|
||||
}
|
||||
|
||||
if (
|
||||
this.props.expression &&
|
||||
this.props.expression.data &&
|
||||
this.props.scatterplotXXaccessor &&
|
||||
this.props.scatterplotYYaccessor &&
|
||||
(this.props.scatterplotXXaccessor !== prevProps.scatterplotXXaccessor || // was CLU now FTH1 etc
|
||||
this.props.scatterplotYYaccessor !== prevProps.scatterplotYYaccessor)
|
||||
) {
|
||||
const scales = this.setupScales(
|
||||
this.props.expression,
|
||||
this.props.scatterplotXXaccessor,
|
||||
this.props.scatterplotYYaccessor
|
||||
);
|
||||
this.setState(scales);
|
||||
}
|
||||
}
|
||||
setupScales(expression, scatterplotXXaccessor, scatterplotYYaccessor) {
|
||||
const xScale = d3
|
||||
|
||||
Reference in New Issue
Block a user