= Streaming Data to Gephi

// include::overview.adoc[tags=gephi,leveloffset=-2]

[separator=¦,opts=header,cols="1,1m,5"]
|===
include::../build/generated-documentation/apoc.gephi.csv[]
|===

image::{img}/apoc-gephi.gif[width=800]

=== Notes

Gephi has a https://marketplace.gephi.org/plugin/graph-streaming/[streaming plugin], that can provide and accept https://github.com/gephi/gephi/wiki/GraphStreaming#Gephi_as_Master[JSON-graph-data] in a streaming fashion.

Make sure to install the plugin firsrt and activate it for your workspace (there is a new "Streaming"-tab besides "Layout"), right-click "Master"->"start" to start the server.

You can provide your workspace name (you might want to rename it before you start thes streaming), otherwise it defaults to `workspace0`

The default Gephi-URL is http://localhost:8080, resulting in `http://localhost:8080/workspace0?operation=updateGraph`

You can also configure it in `conf/neo4j.conf` via  `apoc.gephi.url=url` or `apoc.gephi.<key>.url=url`

=== Example

You can export your graph as an unweighted network.

[source,cypher]
----
match path = (:Person)-[:ACTED_IN]->(:Movie)
WITH path LIMIT 1000
with collect(path) as paths
call apoc.gephi.add(null,'workspace0', paths) yield nodes, relationships, time
return nodes, relationships, time
----

You can export your graph as a weighted network, by specifying the property of a relationship, that holds the weight value.

[source,cypher]
----
match path = (:Person)-[r:ACTED_IN]->(:Movie) where exists r.weightproperty
WITH path LIMIT 1000
with collect(path) as paths
call apoc.gephi.add(null,'workspace0', paths, 'weightproperty') yield nodes, relationships, time
return nodes, relationships, time
----

You can also export with your graph other properties of your nodes and/or relationship by adding an optional array with the property names you want to export.
Example for exporting `birthYear` and `role` property.

[source,cypher]
----
match path = (:Person)-[r:ACTED_IN]->(:Movie) where exists r.weightproperty
WITH path LIMIT 1000
with collect(path) as paths
call apoc.gephi.add(null,'workspace0', paths, 'weightproperty',['birthYear', 'role']) yield nodes, relationships, time
return nodes, relationships, time
----

== Format

We send all nodes and relationships of the passed in data convert into individual Gephi-Streaming JSON fragements, separated by `\r\n`.

[source,javascript]
----
{"an":{"123":{"TYPE":"Person:Actor","label":"Tom Hanks",                           x:333,y:222,r:0.1,g:0.3,b:0.5}}}\r\n
{"an":{"345":{"TYPE":"Movie","label":"Forrest Gump",                               x:234,y:122,r:0.2,g:0.2,b:0.7}}}\r\n
{"ae":{"3344":{"TYPE":"ACTED_IN","label":"Tom Hanks",source:"123",target:"345","directed":true,"weight":1.0,r:0.1,g:0.3,b:0.5}}}
----

== Specifics Details

Gephi doesn't render the graph data unless you also provide x,y coordinates in the payload, so we just send random ones within a 1000x1000 grid.

We also generate colors per label combination and relationship-type, both of which are also transferred as `TYPE` property.

You can have your weight property stored as a number (integer,float) or a string. If the weight property is invalid or null, it will use the default 1.0 value.  
// TODO also generate clustering information.
