mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-10-09 10:08:13 +08:00
move colorScale and colorAccessor to redux to make it global
This commit is contained in:
@@ -40,7 +40,7 @@ class App extends React.Component {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
first request includes query straight off the url bar for now,
|
first request includes query straight off the url bar for now,
|
||||||
|
|
||||||
*/
|
*/
|
||||||
this.props.dispatch(actions.requestCells(window.location.search))
|
this.props.dispatch(actions.requestCells(window.location.search))
|
||||||
|
|
||||||
|
|||||||
@@ -35,8 +35,10 @@ import {
|
|||||||
metadata,
|
metadata,
|
||||||
initializeRanges,
|
initializeRanges,
|
||||||
initializeMetadata,
|
initializeMetadata,
|
||||||
color: state.controls.color,
|
colorAccessor: state.controls.colorAccessor,
|
||||||
continuousSelection: state.controls.continuousSelection
|
graphBrushSelection: state.controls.graphBrushSelection,
|
||||||
|
continuousSelection: state.controls.continuousSelection,
|
||||||
|
axesHaveBeenDrawn: state.controls.axesHaveBeenDrawn,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
class Continuous extends React.Component {
|
class Continuous extends React.Component {
|
||||||
@@ -49,7 +51,6 @@ class Continuous extends React.Component {
|
|||||||
dimensions: null,
|
dimensions: null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const {svg, ctx} = setupParallelCoordinates(
|
const {svg, ctx} = setupParallelCoordinates(
|
||||||
width,
|
width,
|
||||||
@@ -58,12 +59,10 @@ class Continuous extends React.Component {
|
|||||||
);
|
);
|
||||||
this.setState({svg, ctx})
|
this.setState({svg, ctx})
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
this.maybeDrawLines(nextProps);
|
|
||||||
this.maybeDrawAxes(nextProps);
|
this.maybeDrawAxes(nextProps);
|
||||||
|
this.maybeDrawLines(nextProps);
|
||||||
}
|
}
|
||||||
|
|
||||||
maybeDrawAxes(nextProps) {
|
maybeDrawAxes(nextProps) {
|
||||||
if (
|
if (
|
||||||
!this.state.axes &&
|
!this.state.axes &&
|
||||||
@@ -126,8 +125,7 @@ class Continuous extends React.Component {
|
|||||||
this.state.processedDimensions,
|
this.state.processedDimensions,
|
||||||
this.state.xscale,
|
this.state.xscale,
|
||||||
this.state.ctx,
|
this.state.ctx,
|
||||||
width,
|
this.props.colorAccessor,
|
||||||
height
|
|
||||||
);
|
);
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
|
|||||||
@@ -10,7 +10,12 @@ import renderQueue from "./renderQueue";
|
|||||||
******************************************
|
******************************************
|
||||||
******************************************/
|
******************************************/
|
||||||
|
|
||||||
const drawLinesCanvas = (ctx, dimensions, xscale) => {
|
const drawLinesCanvas = (
|
||||||
|
ctx,
|
||||||
|
dimensions,
|
||||||
|
xscale,
|
||||||
|
color,
|
||||||
|
) => {
|
||||||
return (d) => {
|
return (d) => {
|
||||||
|
|
||||||
// ctx.strokeStyle = d["Sample.name.color"];
|
// ctx.strokeStyle = d["Sample.name.color"];
|
||||||
@@ -54,14 +59,18 @@ const drawCellLinesUsingRenderQueue = (
|
|||||||
dimensions,
|
dimensions,
|
||||||
xscale,
|
xscale,
|
||||||
ctx,
|
ctx,
|
||||||
width,
|
color,
|
||||||
height
|
|
||||||
) => {
|
) => {
|
||||||
|
|
||||||
const _renderLinesWithQueue = renderQueue(
|
const _renderLinesWithQueue = renderQueue(
|
||||||
drawLinesCanvas(ctx, dimensions, xscale)
|
drawLinesCanvas(
|
||||||
|
ctx,
|
||||||
|
dimensions,
|
||||||
|
xscale,
|
||||||
|
color
|
||||||
|
)
|
||||||
).rate(50);
|
).rate(50);
|
||||||
|
|
||||||
_renderLinesWithQueue(metadata);
|
_renderLinesWithQueue(metadata);
|
||||||
|
|
||||||
return _renderLinesWithQueue;
|
return _renderLinesWithQueue;
|
||||||
|
|||||||
@@ -22,10 +22,11 @@ const Option = ({name, selected, handleClick}) => {
|
|||||||
|
|
||||||
@connect((state) => {
|
@connect((state) => {
|
||||||
const ranges = state.cells.cells && state.cells.cells.data.ranges ? state.cells.cells.data.ranges : null;
|
const ranges = state.cells.cells && state.cells.cells.data.ranges ? state.cells.cells.data.ranges : null;
|
||||||
|
const initializeRanges = state.initialize.data && state.initialize.data.data.ranges ? state.initialize.data.data.ranges : null;
|
||||||
return {
|
return {
|
||||||
ranges,
|
ranges,
|
||||||
color: state.controls.color,
|
initializeRanges,
|
||||||
|
colorAccessor: state.controls.colorAccessor,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
class ColorOptions extends React.Component {
|
class ColorOptions extends React.Component {
|
||||||
@@ -37,17 +38,18 @@ class ColorOptions extends React.Component {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
handleClick (data) {
|
handleClick (name) {
|
||||||
return () => {
|
return () => {
|
||||||
this.props.dispatch({
|
this.props.dispatch({
|
||||||
type: "color changed",
|
type: "color changed",
|
||||||
data
|
colorAccessor: name,
|
||||||
|
rangeMaxForColorAccessor: this.props.initializeRanges[name].range.max
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (!this.props.ranges) { return null }
|
if (!this.props.ranges || !this.props.initializeRanges) { return null }
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
Color:
|
Color:
|
||||||
@@ -61,7 +63,7 @@ class ColorOptions extends React.Component {
|
|||||||
return <Option
|
return <Option
|
||||||
key={key}
|
key={key}
|
||||||
handleClick={this.handleClick.bind(this)}
|
handleClick={this.handleClick.bind(this)}
|
||||||
selected={this.props.color === key}
|
selected={this.props.colorAccessor === key}
|
||||||
name={key}
|
name={key}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,27 +63,18 @@ export const drawGraph = (
|
|||||||
data,
|
data,
|
||||||
context,
|
context,
|
||||||
expressionsCountsMap,
|
expressionsCountsMap,
|
||||||
color,
|
colorAccessor,
|
||||||
ranges,
|
ranges,
|
||||||
metadata,
|
metadata,
|
||||||
continuousSelection,
|
continuousSelection,
|
||||||
graphBrushSelection,
|
graphBrushSelection,
|
||||||
|
colorScale,
|
||||||
) => {
|
) => {
|
||||||
|
|
||||||
/* clear canvas */
|
/* clear canvas */
|
||||||
context.clearRect(0, 0, width, height);
|
context.clearRect(0, 0, width, height);
|
||||||
|
|
||||||
let colorScale = null; /* it could be 'by expression' and that's a special case */
|
// let colorScale = null; /* it could be 'by expression' and that's a special case */
|
||||||
|
|
||||||
if (
|
|
||||||
color &&
|
|
||||||
ranges[color].range /* set up a continuous scale */
|
|
||||||
) {
|
|
||||||
/* this scale should live in redux since it will be consumed by cotinuous as well */
|
|
||||||
colorScale = d3.scaleLinear()
|
|
||||||
.domain([0, ranges[color].range.max])
|
|
||||||
.range([1,0])
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ! create a scale to map between expression values and colors, remove to somewhere else */
|
/* ! create a scale to map between expression values and colors, remove to somewhere else */
|
||||||
// const expressionToColorScale = d3.scaleLinear()
|
// const expressionToColorScale = d3.scaleLinear()
|
||||||
@@ -133,9 +124,9 @@ export const drawGraph = (
|
|||||||
|
|
||||||
context.globalAlpha = !graphBrushSelection || pointIsInsideBrushBounds ? 1 : .2;
|
context.globalAlpha = !graphBrushSelection || pointIsInsideBrushBounds ? 1 : .2;
|
||||||
|
|
||||||
if (color) {
|
if (colorAccessor && colorScale) {
|
||||||
context.fillStyle = d3.interpolateViridis(colorScale(
|
context.fillStyle = d3.interpolateViridis(colorScale(
|
||||||
_metadata[p[0]][color]
|
_metadata[p[0]][colorAccessor]
|
||||||
// _.find(metadata, {CellName: p[0]})[color] /* this.state.cells.metadata["23452345325"]["ERCC_reads"] = 20000 would be much faster as key value lookup */
|
// _.find(metadata, {CellName: p[0]})[color] /* this.state.cells.metadata["23452345325"]["ERCC_reads"] = 20000 would be much faster as key value lookup */
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ import ColorControl from "../controls/color";
|
|||||||
ranges,
|
ranges,
|
||||||
vertices,
|
vertices,
|
||||||
metadata,
|
metadata,
|
||||||
color: state.controls.color,
|
colorAccessor: state.controls.colorAccessor,
|
||||||
|
colorScale: state.controls.colorScale,
|
||||||
continuousSelection: state.controls.continuousSelection,
|
continuousSelection: state.controls.continuousSelection,
|
||||||
graphBrushSelection: state.controls.graphBrushSelection
|
graphBrushSelection: state.controls.graphBrushSelection
|
||||||
}
|
}
|
||||||
@@ -81,11 +82,12 @@ class Graph extends React.Component {
|
|||||||
nextProps.vertices,
|
nextProps.vertices,
|
||||||
this.state.ctx,
|
this.state.ctx,
|
||||||
nextProps.expressionsCountsMap,
|
nextProps.expressionsCountsMap,
|
||||||
nextProps.color,
|
nextProps.colorAccessor,
|
||||||
nextProps.ranges, /* assumption that this exists if vertices does both are on cells */
|
nextProps.ranges, /* assumption that this exists if vertices does both are on cells */
|
||||||
nextProps.metadata,
|
nextProps.metadata,
|
||||||
nextProps.continuousSelection, /* continuousSelected should probably inform a global 'is active' array rather than be consumed so specifically here */
|
nextProps.continuousSelection, /* continuousSelected should probably inform a global 'is active' array rather than be consumed so specifically here */
|
||||||
nextProps.graphBrushSelection,
|
nextProps.graphBrushSelection,
|
||||||
|
nextProps.colorScale,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+23
-3
@@ -1,18 +1,38 @@
|
|||||||
const Controls = (state = {
|
const Controls = (state = {
|
||||||
color: null,
|
colorAccessor: null,
|
||||||
|
colorScale: null,
|
||||||
continuousSelection: null,
|
continuousSelection: null,
|
||||||
graphBrushSelection: null
|
graphBrushSelection: null,
|
||||||
|
axesHaveBeenDrawn: false,
|
||||||
}, action) => {
|
}, action) => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case "color changed":
|
case "color changed":
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
color: action.data,
|
colorAccessor: action.colorAccessor,
|
||||||
|
colorScale: d3.scaleLinear()
|
||||||
|
.domain([0, action.rangeMaxForColorAccessor])
|
||||||
|
.range([1,0])
|
||||||
});
|
});
|
||||||
case "continuous selection using parallel coords brushing": {
|
case "continuous selection using parallel coords brushing": {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
continuousSelection: action.data,
|
continuousSelection: action.data,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
/* on load, set the selection to 'all', if reactive is true */
|
||||||
|
case "initialize success":
|
||||||
|
let allCellNames = null;
|
||||||
|
if (action.data.data.reactive) { /* we have metadata, get all cell names */
|
||||||
|
allCellNames = action.data.data.metadata.map((cell) => {
|
||||||
|
return cell.CellName
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return Object.assign({}, state, {
|
||||||
|
continuousSelection: allCellNames
|
||||||
|
});
|
||||||
|
case "parallel coordinates axes have been drawn":
|
||||||
|
return Object.assign({}, state, {
|
||||||
|
axesHaveBeenDrawn: true
|
||||||
|
});
|
||||||
case "graph brush selection change":
|
case "graph brush selection change":
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
graphBrushSelection: action.brushCoords
|
graphBrushSelection: action.brushCoords
|
||||||
|
|||||||
Reference in New Issue
Block a user