From b6be4947ebf448dc049720e642ae1cd83103f5cf Mon Sep 17 00:00:00 2001 From: Colin Megill Date: Fri, 8 Sep 2017 01:08:01 -0700 Subject: [PATCH] drawing graph --- .../continuous/drawParallelCoordinates.js | 84 +---------- src/components/continuous/renderQueue.js | 78 ++++++++++ src/components/graph/drawGraph.js | 141 ++++++------------ src/components/graph/graph.css | 15 +- src/components/graph/graph.js | 23 ++- src/components/home.js | 15 +- 6 files changed, 155 insertions(+), 201 deletions(-) diff --git a/src/components/continuous/drawParallelCoordinates.js b/src/components/continuous/drawParallelCoordinates.js index 07877aab..a831eedf 100644 --- a/src/components/continuous/drawParallelCoordinates.js +++ b/src/components/continuous/drawParallelCoordinates.js @@ -1,4 +1,5 @@ import styles from './parallelCoordinates.css'; +import renderQueue from "./renderQueue"; import { margin, width, @@ -17,89 +18,6 @@ Canvas Parallel coordinates with svg brushing via /* via https://bl.ocks.org/syn ****************************************** ******************************************/ -/***************************************** -****************************************** -Render Queue via http://bl.ocks.org/syntagmatic/raw/3341641/render-queue.js -****************************************** -******************************************/ - -const renderQueue = (function(callback1234) { - var _queue = [], // data to be rendered - _rate = 1000, // number of calls per frame - _invalidate = function() {}, // invalidate last render queue - _clear = function() {}; // clearing function - - var rq = function(data) { - if (data) rq.data(data); - _invalidate(); - _clear(); - rq.render(); - }; - - rq.render = function() { - var valid = true; - _invalidate = rq.invalidate = function() { - valid = false; - }; - - function doFrame() { - if (!valid) return true; - var chunk = _queue.splice(0,_rate); - chunk.map(callback1234); - timer_frame(doFrame); - } - - doFrame(); - }; - - rq.data = function(data) { - _invalidate(); - _queue = data.slice(0); // creates a copy of the data - return rq; - }; - - rq.add = function(data) { - _queue = _queue.concat(data); - }; - - rq.rate = function(value) { - if (!arguments.length) return _rate; - _rate = value; - return rq; - }; - - rq.remaining = function() { - return _queue.length; - }; - - // clear the canvas - rq.clear = function(func) { - if (!arguments.length) { - _clear(); - return rq; - } - _clear = func; - return rq; - }; - - rq.invalidate = _invalidate; - - var timer_frame = window.requestAnimationFrame - || window.webkitRequestAnimationFrame - || window.mozRequestAnimationFrame - || window.oRequestAnimationFrame - || window.msRequestAnimationFrame - || function(callback) { setTimeout(callback, 17); }; - - return rq; -}); - -/***************************************** -****************************************** - MAIN: drawParallelCoordinates -****************************************** -******************************************/ - const drawParallelCoordinates = (data) => { const d3_functor = (v) => { diff --git a/src/components/continuous/renderQueue.js b/src/components/continuous/renderQueue.js index e69de29b..9bf0234e 100644 --- a/src/components/continuous/renderQueue.js +++ b/src/components/continuous/renderQueue.js @@ -0,0 +1,78 @@ +/***************************************** +****************************************** +Render Queue via http://bl.ocks.org/syntagmatic/raw/3341641/render-queue.js +****************************************** +******************************************/ + +const renderQueue = (function(callback1234) { + var _queue = [], // data to be rendered + _rate = 1000, // number of calls per frame + _invalidate = function() {}, // invalidate last render queue + _clear = function() {}; // clearing function + + var rq = function(data) { + if (data) rq.data(data); + _invalidate(); + _clear(); + rq.render(); + }; + + rq.render = function() { + var valid = true; + _invalidate = rq.invalidate = function() { + valid = false; + }; + + function doFrame() { + if (!valid) return true; + var chunk = _queue.splice(0,_rate); + chunk.map(callback1234); + timer_frame(doFrame); + } + + doFrame(); + }; + + rq.data = function(data) { + _invalidate(); + _queue = data.slice(0); // creates a copy of the data + return rq; + }; + + rq.add = function(data) { + _queue = _queue.concat(data); + }; + + rq.rate = function(value) { + if (!arguments.length) return _rate; + _rate = value; + return rq; + }; + + rq.remaining = function() { + return _queue.length; + }; + + // clear the canvas + rq.clear = function(func) { + if (!arguments.length) { + _clear(); + return rq; + } + _clear = func; + return rq; + }; + + rq.invalidate = _invalidate; + + var timer_frame = window.requestAnimationFrame + || window.webkitRequestAnimationFrame + || window.mozRequestAnimationFrame + || window.oRequestAnimationFrame + || window.msRequestAnimationFrame + || function(callback) { setTimeout(callback, 17); }; + + return rq; +}); + +export default renderQueue; diff --git a/src/components/graph/drawGraph.js b/src/components/graph/drawGraph.js index ec6cf470..6d2cdcd7 100644 --- a/src/components/graph/drawGraph.js +++ b/src/components/graph/drawGraph.js @@ -1,118 +1,67 @@ -var margin = {top: 20, right: 10, bottom: 30, left: 40}, +import styles from "./graph.css"; +import renderQueue from "../continuous/renderQueue"; + +const margin = {top: 20, right: 10, bottom: 30, left: 40}, width = 960 - margin.left - margin.right, height = 500 - margin.top - margin.bottom; -var svg = d3.select("body").append("svg") - .attr("width", width + margin.left + margin.right) - .attr("height", height + margin.top + margin.bottom) - .append("g") - .attr("transform", "translate(" + margin.left + " " + margin.top + ")"); - -var factory = d3.geom.quadtree() - .extent([ - [0, 0], - [width, height] - ]); - -var x = d3.scale.linear() +const x = d3.scaleLinear() .range([0, width]); -var y = d3.scale.linear() +const y = d3.scaleLinear() .range([height, 0]); -var xAxis = d3.svg.axis() - .scale(x) - .orient("bottom"); +/****************************************** +******************************************* + Main +******************************************* +******************************************/ -var yAxis = d3.svg.axis() - .scale(y) - .orient("left"); +const drawGraph = (data) => { -var xg = svg.append("g") - .attr("class", "x axis") - .attr("transform", "translate(0," + height + ")"); + var svg = d3.select("#graphAttachPoint").append("svg") + .attr("width", width + margin.left + margin.right) + .attr("height", height + margin.top + margin.bottom) + .attr("class", `${styles.graphSVG}`) + .append("g") + .attr("transform", "translate(" + margin.left + " " + margin.top + ")"); -var yg = svg.append("g") - .attr("class", "y axis"); + var chartArea = d3.select("#graphAttachPoint").append("div") + .style("left", margin.left + "px") + .style("top", margin.top + "px"); -var chartArea = d3.select("body").append("div") - .style("left", margin.left + "px") - .style("top", margin.top + "px"); + var canvas = chartArea.append("canvas") + .attr("width", width) + .attr("height", height) + .attr("class", `${styles.graphCanvas}`); -var canvas = chartArea.append("canvas") - .attr("width", width) - .attr("height", height); + var context = canvas.node().getContext("2d"); -var context = canvas.node().getContext("2d"); + context.fillStyle = "rgba(0,0,0,.5)"; -context.fillStyle = "#f0f"; + const draw = () => { -// Layer on top of canvas, example of selection details -var highlight = chartArea.append("svg") - .attr("width", width) - .attr("height", height) - .append("circle") - .attr("r", 7) - .classed("hidden", true); + // Update canvas + context.clearRect(0, 0, width, height); -redraw(); + data.forEach((p, i) => { -function redraw() { + context.beginPath(); + /* context.arc(x,y,r,sAngle,eAngle,counterclockwise); */ + context.arc( + x(p[1]), /* x */ + y(p[2]), /* y */ + 2, /* r */ + 0, /* sAngle */ + 2 * Math.PI /* eAngle */ + ); + context.fill(); - // Randomize the scale - var scale = 1 + Math.floor(Math.random() * 10); + }); + } - // Redraw axes - x.domain([0, scale]); - y.domain([0, scale]); - xg.call(xAxis); - yg.call(yAxis); - - var points = randomPoints(scale); - - var tree = factory(points); - - // Update canvas - context.clearRect(0, 0, width, height); - - points.forEach(function(p,i){ - - context.beginPath(); - context.arc(x(p[0]), y(p[1]), 5, 0, 2 * Math.PI); - context.fill(); - - }); - - canvas.on("mousemove",function(){ - - var mouse = d3.mouse(this), - closest = tree.find([x.invert(mouse[0]), y.invert(mouse[1])]); - - highlight.attr("cx", x(closest[0])) - .attr("cy", y(closest[1])); - - }); - - canvas.on("mouseover",function(){ - highlight.classed("hidden", false); - }); - - canvas.on("mouseout",function(){ - highlight.classed("hidden", true); - }); + draw(); } -function randomPoints(scale) { - - // Get points - return d3.range(1000).map(function(d){ - - return [ - Math.random() * scale, - Math.random() * scale - ]; - - }); - -} +export default drawGraph; diff --git a/src/components/graph/graph.css b/src/components/graph/graph.css index 12594efa..7c207756 100644 --- a/src/components/graph/graph.css +++ b/src/components/graph/graph.css @@ -1,15 +1,18 @@ -path, -line { +.graphCanvas path { shape-rendering: crispEdges; } -div, -svg, -canvas { +#graphWrapper { + position: relative; +} + +#graphAttachPoint, +.graphSVG, +.graphCanvas { position: absolute; } -svg { +#graphSVG { pointer-events: none; } diff --git a/src/components/graph/graph.js b/src/components/graph/graph.js index 807e1856..b996d7aa 100644 --- a/src/components/graph/graph.js +++ b/src/components/graph/graph.js @@ -1,34 +1,31 @@ import React from 'react'; import _ from "lodash"; -// import styles from "./joy.css"; -// import drawGraph from "./drawGraph"; -// import joyParser from "./joyParser"; +import styles from "./graph.css"; +import drawGraph from "./drawGraph"; class Graph extends React.Component { constructor(props) { super(props); this.state = { - + drawn: false, }; } componentWillReceiveProps(nextProps) { - if (nextProps.data) { - console.log('graph data 55', nextProps.data) - // drawGraph(graphParser(nextProps.data)); + /* maybe should do a check here to confirm ref exists and pass it? */ + if (nextProps.data && !this.state.drawn) { + console.log('About to draw graph. Data:', nextProps.data) + drawGraph(nextProps.data.data) + this.setState({drawn: true}); } } - componentDidMount() { - - } - render() { return ( -
+

Graph

-
+
) } diff --git a/src/components/home.js b/src/components/home.js index 6e272579..ac37b2c1 100644 --- a/src/components/home.js +++ b/src/components/home.js @@ -19,7 +19,7 @@ class Home extends React.Component { graph: null, }; } - componentWillMount() { + componentDidMount() { // d3.csv("http://ec2-34-234-75-156.compute-1.amazonaws.com/api/v0.1/metadata", (d) => { // console.log("from ec2",d) // }) @@ -51,13 +51,22 @@ class Home extends React.Component {

cellxgene

+

Gene selection criteria

- + {false ? : ""}

T-SNE plot

- + {this.state.showClustersPlaceholderImage ? : null}