sourcecred/odyssey-hackathon

Graph Visualizer

Opened this issue · 2 comments

We need a graph visualizer for our Odyssey Hackathon project (see #1 for overview). Let's use this thread to spec it out.

I imagine the graph visualizer displaying a subset of nodes in a SourceCred graph using force-directed layout. For each node, there are a few pieces of salient information we want to display:

  • the node's type
  • the node's description
  • the node's weight
  • the node's score

Most of this data will come from a PagerankGraph (using PagerankGraph rather than regular Graph so that we have scores and weights). To get node types and node descriptions, we'll also need to have the relevant plugin adapter available.

I'm not exactly sure how this information should be rendered. It would seem natural to communicate both a node's weight and a node's score via the size; score is more important than weight, so we should prioritize that, but I'm not sure how the weight should get communicated. (In the current implementation, node weight weight only matters insofar as it modifies the edge weights so maybe we don't need to worry about this.) For edges, we need to be able to render that the weight may be asymmetric, i.e. high weight in one direction but not another. Maybe we can put arrowheads on both ends of the edge, where the size of each arrowhead indicates the respective weight?

In the initial "hack" case where the "manual-mode" plugin stands alone, we can not worry about the plugin integration so much and just make it work for the manual-mode plugin, but we'll definitely want to integrate with the Git and GitHub plugin before long. Also, in the longer-term future we'll want to give plugins an opportunity to integrate custom rendering logic for their nodes and edges (and maybe custom logic for aggregating groups of nodes together), but this is not a v0 consideration.

From an implementation perspective, I imagine us using d3 with force-directed-layout, and to render the graph via SVG. I'm not sure if we'll let the user manually re-layout the graph, I think we should try to avoid this unless it proves really important.

Then, for consistency with the rest of our codebase, we should wrap the d3 visualization into a React component. I imagine the React component having a surface area kind of like this one:

export type Props = {|
  // The underlying graph. it should be a PagerankGraph and not just a 
  // regular Graph so that we have node/edge weights 
  +graph: PagerankGraph,

  // Which node or edge is selected (if anything is)
  +selected: NodeAddressT | EdgeAddressT | null,

  // Handler so the controlling component can update the selection
  +onSelectedChange: (NodeAddressT | EdgeAddressT | null) => void;

  // Which nodes in the graph are visible
  +visible: Set<NodeAddressT>,

  +adapters: $ReadOnlyArray<DynamicExplorerAdapter>,
|}

export type ZoomPosition = {|
  // Facilitate drag, zoom in, zoom out
  +zoom: number,
  +x: number,
  +y: number,
|}

export type State = {|
  +zoomPosition: ZoomPosition,
|}

export class GraphVisualizer extends React.Component<Props, State> {
  render() {
    // TODO...
  }
}

I have a start here: https://jsfiddle.net/bjkvndL3/. (edited to abstract node and edge definition...just added edge source and target mapping demoed using the JSON data from the project: https://jsfiddle.net/39dbn4ao/. Also added an edge color function. Both the edge and node color functions use indexing rather than categorical names, but that can be changed if needed.)

The chart updates on an interval and the node name appears when you hover over a node. The first section is the chart class. I then demo the class with toy data at line 188. The opts argument takes several items that includes a mapping of the data to node and edge elements.

Anyhow, this is a start, and we can further define what we may want from the chart in the as needed for the hack.

Keeping the code (and commits) here unless there's a better home.

Updated the research JSON data example with most recent code here. It's still a big fuzz ball, but some nodes pull out into orbit.