performance - improve caching in histogram and graph

This commit is contained in:
bkmartinjr
2018-05-14 11:56:44 -07:00
parent 988751e705
commit 156fb5c100
3 changed files with 77 additions and 45 deletions
+46 -20
View File
@@ -47,6 +47,46 @@ class HistogramBrush extends React.Component {
} }
componentDidMount() {} componentDidMount() {}
componentDidUpdate() {} componentDidUpdate() {}
calcHistogramCache(nextProps) {
// recalculate expensive stuff
const allValuesForContinuousFieldAsArray = _.map(
nextProps.currentCellSelection,
nextProps.metadataField
);
this.histogramCache = {};
this.histogramCache.x = d3
.scaleLinear()
.domain([nextProps.ranges.min, nextProps.ranges.max])
.range([0, this.width]);
this.histogramCache.y = d3
.scaleLinear()
.range([this.height - this.marginBottom, 0]);
// .range([height - margin.bottom, margin.top]);
this.histogramCache.bins = d3
.histogram()
.domain(this.histogramCache.x.domain())
.thresholds(40)(allValuesForContinuousFieldAsArray);
this.histogramCache.numValues = allValuesForContinuousFieldAsArray.length;
}
componentWillMount() {
this.calcHistogramCache(this.props);
}
componentWillReceiveProps(nextProps) {
if (
this.props.metadataField !== nextProps.metadataField ||
!this.histogramCache
) {
this.calcHistogramCache(nextProps);
}
}
onBrush(selection, x) { onBrush(selection, x) {
return () => { return () => {
if (d3.event.selection) { if (d3.event.selection) {
@@ -65,24 +105,10 @@ class HistogramBrush extends React.Component {
}; };
} }
drawHistogram(svgRef) { drawHistogram(svgRef) {
const allValuesForContinuousFieldAsArray = _.map( const x = this.histogramCache.x;
this.props.currentCellSelection, const y = this.histogramCache.y;
this.props.metadataField const bins = this.histogramCache.bins;
); const numValues = this.histogramCache.numValues;
var x = d3
.scaleLinear()
.domain(d3.extent(allValuesForContinuousFieldAsArray, d => +d))
.range([0, this.width]);
// .range([margin.left, width - margin.right]);
var y = d3.scaleLinear().range([this.height - this.marginBottom, 0]);
// .range([height - margin.bottom, margin.top]);
const bins = d3
.histogram()
.domain(x.domain())
.thresholds(40)(allValuesForContinuousFieldAsArray);
d3 d3
.select(svgRef) .select(svgRef)
@@ -96,13 +122,13 @@ class HistogramBrush extends React.Component {
return x(d.x0) + 1; return x(d.x0) + 1;
}) })
.attr("y", function(d) { .attr("y", function(d) {
return y(d.length / allValuesForContinuousFieldAsArray.length); return y(d.length / numValues);
}) })
.attr("width", function(d) { .attr("width", function(d) {
return Math.abs(x(d.x1) - x(d.x0) - 1); return Math.abs(x(d.x1) - x(d.x0) - 1);
}) })
.attr("height", function(d) { .attr("height", function(d) {
return y(0) - y(d.length / allValuesForContinuousFieldAsArray.length); return y(0) - y(d.length / numValues);
}); });
if (!this.state.brush && !this.state.axis) { if (!this.state.brush && !this.state.axis) {
+27 -24
View File
@@ -95,7 +95,7 @@ class Graph extends React.Component {
scale: viewportHeight / viewportWidth scale: viewportHeight / viewportWidth
}); });
this.setState({camera}) this.setState({ camera });
camera.tick(); camera.tick();
}); });
@@ -111,35 +111,43 @@ class Graph extends React.Component {
if (this.state.regl && nextProps.vertices) { if (this.state.regl && nextProps.vertices) {
const vertices = nextProps.currentCellSelection; const vertices = nextProps.currentCellSelection;
const vertexCount = vertices.length; const vertexCount = vertices.length;
const positions = new Float32Array(2 * vertexCount);
const colors = new Float32Array(3 * vertexCount); const colors = new Float32Array(3 * vertexCount);
const sizes = new Float32Array(vertexCount); const sizes = new Float32Array(vertexCount);
// d3.scaleLinear().domain([0,1]).range([-1,1]) // Cache a scaled graph
const glScaleX = scaleLinear([0, 1], [-1, 1]); if (!this.scaledGraphVec || this.props.graphVec != nextProps.graphVec) {
// d3.scaleLinear().domain([0,1]).range([1,-1]) const positions = new Float32Array(2 * vertexCount);
const glScaleY = scaleLinear([0, 1], [1, -1]);
// d3.scaleLinear().domain([0,1]).range([-1,1])
const glScaleX = scaleLinear([0, 1], [-1, 1]);
// d3.scaleLinear().domain([0,1]).range([1,-1])
const glScaleY = scaleLinear([0, 1], [1, -1]);
const graphVec = nextProps.graphVec;
for (var i = 0; i < vertexCount; i++) {
const cell = vertices[i];
const cellIdx = cell.__cellIndex__;
const x = glScaleX(graphVec[2 * cellIdx]);
const y = glScaleY(graphVec[2 * cellIdx + 1]);
positions[2 * i] = x;
positions[2 * i + 1] = y;
}
this.scaledGraphVec = positions;
}
/* /*
Construct Vectors Construct Size & Color Vectors
*/ */
const graphVec = nextProps.graphVec;
for (var i = 0; i < vertexCount; i++) { for (var i = 0; i < vertexCount; i++) {
const cell = vertices[i]; const cell = vertices[i];
const cellIdx = cell.__cellIndex__;
const x = glScaleX(graphVec[2 * cellIdx]);
const y = glScaleY(graphVec[2 * cellIdx + 1]);
positions[2 * i] = x;
positions[2 * i + 1] = y;
colors.set(cell.__colorRGB__, 3 * i); colors.set(cell.__colorRGB__, 3 * i);
sizes[i] = cell.__selected__ sizes[i] = cell.__selected__
? 4 ? 4
: 0.2; /* make this a function of the number of total cells, including regraph */ : 0.2; /* make this a function of the number of total cells, including regraph */
} }
this.state.pointBuffer({ data: positions, dimension: 2 }); this.state.pointBuffer({ data: this.scaledGraphVec, dimension: 2 });
this.state.colorBuffer({ data: colors, dimension: 3 }); this.state.colorBuffer({ data: colors, dimension: 3 });
this.state.sizeBuffer({ data: sizes, dimension: 1 }); this.state.sizeBuffer({ data: sizes, dimension: 1 });
this.count = vertexCount; this.count = vertexCount;
@@ -165,7 +173,7 @@ class Graph extends React.Component {
const inverse = mat4.invert([], this.state.camera.view()); const inverse = mat4.invert([], this.state.camera.view());
// transform screen coordinates -> cell coordinates // transform screen coordinates -> cell coordinates
const invert = (pin) => { const invert = pin => {
const x = 2 * pin[0] / globals.graphWidth - 1; const x = 2 * pin[0] / globals.graphWidth - 1;
const y = 2 * (1 - pin[1] / globals.graphHeight) - 1; const y = 2 * (1 - pin[1] / globals.graphHeight) - 1;
const pout = [x + inverse[12], y + inverse[13]]; const pout = [x + inverse[12], y + inverse[13]];
@@ -198,10 +206,7 @@ class Graph extends React.Component {
render() { render() {
return ( return (
<div <div id="graphWrapper">
id="graphWrapper"
>
<div style={{ position: "fixed", right: 0, top: 0 }}> <div style={{ position: "fixed", right: 0, top: 0 }}>
<div <div
style={{ style={{
@@ -286,9 +291,7 @@ class Graph extends React.Component {
</div> </div>
</div> </div>
</div> </div>
<div <div style={{ marginRight: 50, marginTop: 50, zIndex: -9999 }}>
style={{marginRight: 50, marginTop: 50, zIndex: -9999 }}
>
<div <div
style={{ style={{
display: this.state.mode === "brush" ? "inherit" : "none" display: this.state.mode === "brush" ? "inherit" : "none"
@@ -49,7 +49,10 @@ const updateCellSelectionMiddleware = store => {
- metadata has cellname and index, and that's all we ever need to reference cell info - metadata has cellname and index, and that's all we ever need to reference cell info
*/ */
let newSelection = s.controls.currentCellSelection.slice(0); let newSelection = s.controls.currentCellSelection.slice(0);
_.forEach(newSelection, cell => (cell.__selected__ = true)); // _.forEach(newSelection, cell => (cell.__selected__ = true));
for (let i = 0; i < newSelection.length; i++) {
newSelection[i].__selected__ = true;
}
/* /*
in plain language... in plain language...