diff --git a/src/actions/index.js b/src/actions/index.js
index 7d9b7002..b3dc14bc 100644
--- a/src/actions/index.js
+++ b/src/actions/index.js
@@ -57,9 +57,9 @@ const regraph = () => {
dispatch(requestCells(uri.search())).then(res => {
if (res.error) {
- dispatch({ type: "regraph success" });
- } else {
dispatch({ type: "regraph error" });
+ } else {
+ dispatch({ type: "regraph success" });
}
});
};
diff --git a/src/components/app.js b/src/components/app.js
index a4a1ec30..56ed2754 100644
--- a/src/components/app.js
+++ b/src/components/app.js
@@ -8,6 +8,7 @@ import PulseLoader from "halogen/PulseLoader";
import LeftSideBar from "./leftsidebar";
import Parallel from "./continuous/parallel";
+import Legend from "./continuousLegend";
import Joy from "./joy/joy";
import Graph from "./graph/graph";
import * as globals from "../globals";
@@ -92,6 +93,7 @@ class App extends React.Component {
}}
>
+
{/**/}
diff --git a/src/components/continuousLegend/index.js b/src/components/continuousLegend/index.js
new file mode 100644
index 00000000..e3f6f14a
--- /dev/null
+++ b/src/components/continuousLegend/index.js
@@ -0,0 +1,142 @@
+// jshint esversion: 6
+import React from "react";
+import _ from "lodash";
+import { connect } from "react-redux";
+import * as globals from "../../globals";
+
+// create continuous color legend
+// http://bl.ocks.org/syntagmatic/e8ccca52559796be775553b467593a9f
+const continuous = (selector_id, colorscale) => {
+ var legendheight = 200,
+ legendwidth = 80,
+ margin = { top: 10, right: 60, bottom: 10, left: 2 };
+
+ var canvas = d3
+ .select(selector_id)
+ .style("height", legendheight + "px")
+ .style("width", legendwidth + "px")
+ // .style("position", "relative")
+ .append("canvas")
+ .attr("height", legendheight - margin.top - margin.bottom)
+ .attr("width", 1)
+ .style("height", legendheight - margin.top - margin.bottom + "px")
+ .style("width", legendwidth - margin.left - margin.right + "px")
+ // .style("border", "1px solid #000")
+ .style("position", "absolute")
+ .style("top", margin.top + 1 + "px")
+ .style("left", margin.left + 1 + "px")
+ .style(
+ "transform",
+ "scale(1,-1)"
+ ) /* flip it! dark is high value light is low. we flip the color scale as well [1, 0] instead of [0, 1] */
+ .node();
+
+ var ctx = canvas.getContext("2d");
+
+ var legendscale = d3
+ .scaleLinear()
+ .range([1, legendheight - margin.top - margin.bottom])
+ .domain([
+ colorscale.domain()[1],
+ colorscale.domain()[0]
+ ]); /* we flip this to make viridis colors dark if high in the color scale */
+
+ // image data hackery based on http://bl.ocks.org/mbostock/048d21cf747371b11884f75ad896e5a5
+ var image = ctx.createImageData(1, legendheight);
+ d3.range(legendheight).forEach(function(i) {
+ var c = d3.rgb(colorscale(legendscale.invert(i)));
+ image.data[4 * i] = c.r;
+ image.data[4 * i + 1] = c.g;
+ image.data[4 * i + 2] = c.b;
+ image.data[4 * i + 3] = 255;
+ });
+ ctx.putImageData(image, 0, 0);
+
+ // A simpler way to do the above, but possibly slower. keep in mind the legend width is stretched because the width attr of the canvas is 1
+ // See http://stackoverflow.com/questions/4899799/whats-the-best-way-to-set-a-single-pixel-in-an-html5-canvas
+ /*
+ d3.range(legendheight).forEach(function(i) {
+ ctx.fillStyle = colorscale(legendscale.invert(i));
+ ctx.fillRect(0,i,1,1);
+ });
+ */
+
+ var legendaxis = d3
+ .axisRight()
+ .scale(legendscale)
+ .tickSize(6)
+ .ticks(8);
+
+ var svg = d3
+ .select(selector_id)
+ .append("svg")
+ .attr("height", legendheight + "px")
+ .attr("width", legendwidth + "px")
+ .style("position", "absolute")
+ .style("left", "0px")
+ .style("top", "0px");
+
+ svg
+ .append("g")
+ .attr("class", "axis")
+ .attr(
+ "transform",
+ "translate(" +
+ (legendwidth - margin.left - margin.right + 3) +
+ "," +
+ margin.top +
+ ")"
+ )
+ .call(legendaxis);
+};
+
+@connect(state => {
+ return {
+ colorAccessor: state.controls.colorAccessor,
+ colorScale: state.controls.colorScale,
+ responsive: state.responsive
+ };
+})
+class ContinuousLegend extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {};
+ }
+ componentWillReceiveProps(nextProps) {
+ if (nextProps.colorAccessor !== this.props.colorAccessor) {
+ /* always remove it, if it's not continuous we don't put it back. */
+ d3
+ .select("#continuous_legend")
+ .selectAll("*")
+ .remove();
+ }
+
+ if (nextProps.colorAccessor && nextProps.colorScale) {
+ /* fragile! continuous range is 0 to 1, not [#fa4b2c, ...], make this a flag? */
+ if (nextProps.colorScale.range()[0][0] !== "#") {
+ continuous(
+ "#continuous_legend",
+ d3
+ .scaleSequential(d3.interpolateViridis)
+ .domain(nextProps.colorScale.domain())
+ );
+ }
+ }
+ }
+ drawScale() {}
+ render() {
+ return (
+
+ );
+ }
+}
+
+export default ContinuousLegend;
diff --git a/src/reducers/cells.js b/src/reducers/cells.js
index c17ee6d4..57c79044 100644
--- a/src/reducers/cells.js
+++ b/src/reducers/cells.js
@@ -1,9 +1,11 @@
// jshint esversion: 6
const Cells = (
state = {
- cells: null,
+ cells: null /* world */,
loading: null,
- error: null
+ error: null,
+
+ allCells: null /* this comes from cells endpoint, this is universe */
},
action
) => {
@@ -17,13 +19,20 @@ const Cells = (
return Object.assign({}, state, {
error: null,
loading: false,
- cells: action.data
+ cells: action.data, // most recently loaded cells
+
+ /* Universe - initialize once */
+ allCells: state.allCells ? state.allCells : action.data
});
case "request cells error":
return Object.assign({}, state, {
loading: false,
error: action.data
});
+ case "reset graph":
+ return Object.assign({}, state, {
+ cells: state.allCells
+ });
default:
return state;
}
diff --git a/src/reducers/controls.js b/src/reducers/controls.js
index b6796f54..c328e622 100644
--- a/src/reducers/controls.js
+++ b/src/reducers/controls.js
@@ -103,6 +103,7 @@ const Controls = (
allGeneNames: null,
allCells: null /* this comes from cells endpoint, this is universe */,
allCellsMetadata: null /* this comes from cells endpoint, and is just the metadata for universe */,
+ allCellsMetadataMap: null,
/* View / World - all cells currently being displayed. May be a subset of Universe. */
cellsMetadata: null,