mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-09-22 10:38:13 +08:00
180 lines
4.3 KiB
JavaScript
180 lines
4.3 KiB
JavaScript
import React from 'react';
|
|
import _ from "lodash";
|
|
import { connect } from "react-redux";
|
|
|
|
import styles from './parallelCoordinates.css';
|
|
import SectionHeader from "../framework/sectionHeader";
|
|
|
|
import renderQueue from "./renderQueue";
|
|
|
|
import setupParallelCoordinates from "./setupParallelCoordinates";
|
|
import drawAxes from "./drawAxes";
|
|
import drawLinesCanvas from "./drawLinesCanvas";
|
|
|
|
import {
|
|
margin,
|
|
width,
|
|
height,
|
|
innerHeight,
|
|
color,
|
|
createDimensions,
|
|
types,
|
|
processData,
|
|
yAxis,
|
|
d3_functor,
|
|
} 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 initializeMetadata = state.initialize.data && state.initialize.data.data.metadata ? state.initialize.data.data.metadata : null;
|
|
|
|
return {
|
|
ranges,
|
|
metadata,
|
|
initializeRanges,
|
|
initializeMetadata,
|
|
color: state.controls.color,
|
|
continuousSelection: state.controls.continuousSelection
|
|
}
|
|
})
|
|
class Continuous extends React.Component {
|
|
constructor(props) {
|
|
super(props);
|
|
this.state = {
|
|
svg: null,
|
|
ctx: null,
|
|
axes: null,
|
|
dimensions: null,
|
|
};
|
|
}
|
|
|
|
componentDidMount() {
|
|
const {svg, ctx} = setupParallelCoordinates(
|
|
width,
|
|
height,
|
|
margin
|
|
);
|
|
this.setState({svg, ctx})
|
|
}
|
|
|
|
componentWillReceiveProps(nextProps) {
|
|
this.maybeDrawLines(nextProps);
|
|
this.maybeDrawAxes(nextProps);
|
|
}
|
|
|
|
maybeDrawAxes(nextProps) {
|
|
if (
|
|
!this.state.axes &&
|
|
nextProps.initializeRanges /* we assume if this is present, everything else is too */
|
|
) {
|
|
const dimensions = createDimensions(nextProps.initializeRanges);
|
|
const xscale = d3.scalePoint()
|
|
.domain(d3.range(dimensions.length))
|
|
.range([0, width]);
|
|
|
|
const {
|
|
processedMetadata,
|
|
processedDimensions
|
|
} = processData(
|
|
nextProps.initializeMetadata,
|
|
dimensions
|
|
)
|
|
|
|
const axes = drawAxes(
|
|
this.state.svg,
|
|
this.state.ctx,
|
|
processedDimensions,
|
|
processedMetadata,
|
|
xscale,
|
|
height,
|
|
width,
|
|
this.handleBrushAction.bind(this),
|
|
);
|
|
|
|
this.setState({
|
|
axes,
|
|
xscale,
|
|
processedMetadata,
|
|
processedDimensions,
|
|
})
|
|
|
|
}
|
|
}
|
|
|
|
maybeDrawLines(nextProps) {
|
|
if (
|
|
nextProps.ranges &&
|
|
this.state.axes /* this may cause things to never render :/ forceUpdate? */
|
|
) {
|
|
if (this.state._drawCellLines) {
|
|
|
|
this.state._drawCellLines.invalidate();
|
|
}
|
|
const dimensions = createDimensions(nextProps.ranges);
|
|
|
|
const {
|
|
processedMetadata,
|
|
processedDimensions
|
|
} = processData(
|
|
nextProps.metadata,
|
|
dimensions
|
|
)
|
|
|
|
console.log('draw cell lines', processedMetadata, processedDimensions)
|
|
const _drawCellLines = this.drawCellLines(
|
|
_.filter(processedMetadata, (d) => { return nextProps.continuousSelection.indexOf(d.CellName) > -1 }),
|
|
processedDimensions,
|
|
this.state.xscale
|
|
);
|
|
|
|
this.setState({
|
|
dimensions,
|
|
_drawCellLines,
|
|
})
|
|
}
|
|
}
|
|
|
|
handleBrushAction (selection) {
|
|
this.props.dispatch({
|
|
type: "continuous selection using parallel coords brushing",
|
|
data: _.map(selection, (d) => { return d.CellName })
|
|
})
|
|
}
|
|
|
|
drawCellLines (metadata, dimensions, xscale) {
|
|
const _drawCellLines = renderQueue(
|
|
drawLinesCanvas(this.state.ctx, dimensions, this.state.xscale)
|
|
).rate(50);
|
|
|
|
this.state.ctx.clearRect(0,0,width,height);
|
|
this.state.ctx.globalAlpha = d3.min([0.85/Math.pow(metadata.length,0.3),1]);
|
|
|
|
_drawCellLines(metadata);
|
|
|
|
return _drawCellLines;
|
|
|
|
}
|
|
|
|
render() {
|
|
|
|
return (
|
|
<div id="parcoords_wrapper" style={{marginTop: 50}}>
|
|
<SectionHeader text="Continuous Metadata"/>
|
|
<div
|
|
className={styles.parcoords}
|
|
id="parcoords"
|
|
style={{
|
|
width: width + margin.left + margin.right + "px",
|
|
height: height + margin.top + margin.bottom + "px"
|
|
}}></div>
|
|
</div>
|
|
)
|
|
}
|
|
};
|
|
|
|
export default Continuous;
|