<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Max De Marzi</title>
	<atom:link href="http://maxdemarzi.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://maxdemarzi.com</link>
	<description>Ruby + Graphs</description>
	<lastBuildDate>Thu, 24 May 2012 20:37:37 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='maxdemarzi.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Max De Marzi</title>
		<link>http://maxdemarzi.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://maxdemarzi.com/osd.xml" title="Max De Marzi" />
	<atom:link rel='hub' href='http://maxdemarzi.com/?pushpress=hub'/>
		<item>
		<title>Relationships</title>
		<link>http://maxdemarzi.com/2012/05/09/relationships/</link>
		<comments>http://maxdemarzi.com/2012/05/09/relationships/#comments</comments>
		<pubDate>Thu, 10 May 2012 03:18:57 +0000</pubDate>
		<dc:creator>maxdemarzi</dc:creator>
				<category><![CDATA[Random]]></category>
		<category><![CDATA[graph database]]></category>
		<category><![CDATA[relationship graph]]></category>

		<guid isPermaLink="false">http://maxdemarzi.com/?p=889</guid>
		<description><![CDATA[When working with relational databases, the join tables are sometimes treated as second class citizens. If they are lucky, they&#8217;ll get some additional fields, but are often just placeholder tables connecting your main object tables together. It leads you to think about objects first, and relationships second. With graphs, you will want to switch up [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=maxdemarzi.com&#038;blog=31056513&#038;post=889&#038;subd=maxdemarzidotcom&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://maxdemarzidotcom.files.wordpress.com/2012/05/relationship-status.jpg"><img src="http://maxdemarzidotcom.files.wordpress.com/2012/05/relationship-status.jpg?w=580" alt="" title="relationship-status"   class="aligncenter size-full wp-image-993" /></a></p>
<p>When working with relational databases, the join tables are sometimes treated as second class citizens.  If they are lucky, they&#8217;ll get some additional fields, but are often just placeholder tables connecting your main object tables together.  It leads you to think about objects first, and relationships second.  With graphs, you will want to switch up your thinking.  You want to start thinking about how things are connected.  Think about the different ways things are connected.  Two people can be friends, co-workers, and neighbors all at the same time.<br />
<span id="more-889"></span><br />
If you&#8217;ve ever been crazy enough to go back to school after your bachelor&#8217;s degree, you know all about research papers, journals, and citations.  So what kind of relationships can we find here?  Papers are rarely authored alone.  Having multiple authors means you can create a graph of co-authors.  Which students and scientists work together on papers, and which should work together.  Scientific research builds upon the work of others, and previous work can be used to build a graph of citations.  Keywords in the abstracts or extracted from the papers can be used to build a graph of similar content.  </p>
<p>What about a social network like Twitter?  How about a Follower graph, a Reply graph, a Mention graph, a Co-Listed graph, a HashTag graph, a Co-Location graph, a Shared-URL graph?  What about blogs?  How about a Link graph, a Blogroll graph, a Tag graph?</p>
<p>You will be surprised by how connected your data is once you start exploring it.  Don&#8217;t be afraid of your model.  Just start with whatever you have and start adding nodes and relationships as they become apparent to you.  Your model will probably evolve, so don&#8217;t waste your time second guessing yourself.  </p>
<p>When folks ask me about modeling, I tell them to start with the questions they want to answer.  It doesn&#8217;t end there however.  Once you&#8217;ve answered those questions, you&#8217;ll discover more.  You&#8217;ll say, if I had this extra piece of data, I could ask and answer a ton new questions I didn&#8217;t think about before.  </p>
<p>I&#8217;ll spend some time in the next few posts digging in a little deeper.  </p>
<br />Filed under: <a href='http://maxdemarzi.com/category/random/'>Random</a> Tagged: <a href='http://maxdemarzi.com/tag/graph-database/'>graph database</a>, <a href='http://maxdemarzi.com/tag/relationship-graph/'>relationship graph</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/maxdemarzidotcom.wordpress.com/889/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/maxdemarzidotcom.wordpress.com/889/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/maxdemarzidotcom.wordpress.com/889/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/maxdemarzidotcom.wordpress.com/889/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/maxdemarzidotcom.wordpress.com/889/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/maxdemarzidotcom.wordpress.com/889/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/maxdemarzidotcom.wordpress.com/889/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/maxdemarzidotcom.wordpress.com/889/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/maxdemarzidotcom.wordpress.com/889/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/maxdemarzidotcom.wordpress.com/889/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/maxdemarzidotcom.wordpress.com/889/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/maxdemarzidotcom.wordpress.com/889/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/maxdemarzidotcom.wordpress.com/889/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/maxdemarzidotcom.wordpress.com/889/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=maxdemarzi.com&#038;blog=31056513&#038;post=889&#038;subd=maxdemarzidotcom&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://maxdemarzi.com/2012/05/09/relationships/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/58750f2179edbd650b471280aa66fee5?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">grassbits</media:title>
		</media:content>

		<media:content url="http://maxdemarzidotcom.files.wordpress.com/2012/05/relationship-status.jpg" medium="image">
			<media:title type="html">relationship-status</media:title>
		</media:content>
	</item>
		<item>
		<title>Slides from Chicago Graph Database April Meet-up</title>
		<link>http://maxdemarzi.com/2012/05/06/slides-from-chicago-graph-database-april-meet-up/</link>
		<comments>http://maxdemarzi.com/2012/05/06/slides-from-chicago-graph-database-april-meet-up/#comments</comments>
		<pubDate>Mon, 07 May 2012 00:51:55 +0000</pubDate>
		<dc:creator>maxdemarzi</dc:creator>
				<category><![CDATA[Gremlin]]></category>
		<category><![CDATA[graph database]]></category>
		<category><![CDATA[gremlin]]></category>
		<category><![CDATA[neo4j]]></category>

		<guid isPermaLink="false">http://maxdemarzi.com/?p=972</guid>
		<description><![CDATA[Introduction to Graph Databases View more PowerPoint from Max De Marzi Introduction to Gremlin View more PowerPoint from Max De Marzi Thank you again to Groupon Engineering! They hosted our Graph Database Meet-up at their Headquarters. Join us May 31st, 2012 for our next meet-up Add data from your existing Application into Neo4j. Filed under: [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=maxdemarzi.com&#038;blog=31056513&#038;post=972&#038;subd=maxdemarzidotcom&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<div style="width:425px;" id="__ss_12735789"> <strong><a href="http://www.slideshare.net/maxdemarzi/introduction-to-graph-databases-12735789" title="Introduction to Graph Databases" target="_blank">Introduction to Graph Databases</a></strong> <iframe src='http://www.slideshare.net/slideshow/embed_code/12735789' width='425' height='348' scrolling='no'></iframe>
<div style="padding:5px 0 12px;"> View more <a href="http://www.slideshare.net/thecroaker/death-by-powerpoint" target="_blank">PowerPoint</a> from <a href="http://www.slideshare.net/maxdemarzi" target="_blank">Max De Marzi</a> </div>
</p></div>
<div style="width:425px;" id="__ss_12738258"> <strong><a href="http://www.slideshare.net/maxdemarzi/introduction-to-gremlin" title="Introduction to Gremlin" target="_blank">Introduction to Gremlin</a></strong> <iframe src='http://www.slideshare.net/slideshow/embed_code/12738258' width='425' height='348' scrolling='no'></iframe>
<div style="padding:5px 0 12px;"> View more <a href="http://www.slideshare.net/thecroaker/death-by-powerpoint" target="_blank">PowerPoint</a> from <a href="http://www.slideshare.net/maxdemarzi" target="_blank">Max De Marzi</a> </div>
</p></div>
<p>Thank you again to <a href="https://twitter.com/#!/GrouponEng" target="_blank">Groupon Engineering</a>!  They hosted our Graph Database Meet-up at their Headquarters.</p>
<p>Join us May 31st, 2012 for our next meet-up <a href="http://www.meetup.com/windy-city-graphdb/events/62355142/" target="_blank">Add data from your existing Application into Neo4j</a>.</p>
<br />Filed under: <a href='http://maxdemarzi.com/category/gremlin/'>Gremlin</a> Tagged: <a href='http://maxdemarzi.com/tag/graph-database/'>graph database</a>, <a href='http://maxdemarzi.com/tag/gremlin-2/'>gremlin</a>, <a href='http://maxdemarzi.com/tag/neo4j/'>neo4j</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/maxdemarzidotcom.wordpress.com/972/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/maxdemarzidotcom.wordpress.com/972/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/maxdemarzidotcom.wordpress.com/972/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/maxdemarzidotcom.wordpress.com/972/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/maxdemarzidotcom.wordpress.com/972/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/maxdemarzidotcom.wordpress.com/972/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/maxdemarzidotcom.wordpress.com/972/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/maxdemarzidotcom.wordpress.com/972/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/maxdemarzidotcom.wordpress.com/972/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/maxdemarzidotcom.wordpress.com/972/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/maxdemarzidotcom.wordpress.com/972/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/maxdemarzidotcom.wordpress.com/972/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/maxdemarzidotcom.wordpress.com/972/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/maxdemarzidotcom.wordpress.com/972/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=maxdemarzi.com&#038;blog=31056513&#038;post=972&#038;subd=maxdemarzidotcom&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://maxdemarzi.com/2012/05/06/slides-from-chicago-graph-database-april-meet-up/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/58750f2179edbd650b471280aa66fee5?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">grassbits</media:title>
		</media:content>
	</item>
		<item>
		<title>Using Three.js with Neo4j</title>
		<link>http://maxdemarzi.com/2012/04/16/using-three-js-with-neo4j/</link>
		<comments>http://maxdemarzi.com/2012/04/16/using-three-js-with-neo4j/#comments</comments>
		<pubDate>Mon, 16 Apr 2012 13:18:16 +0000</pubDate>
		<dc:creator>maxdemarzi</dc:creator>
				<category><![CDATA[Cypher]]></category>
		<category><![CDATA[Neography]]></category>
		<category><![CDATA[Visualization]]></category>
		<category><![CDATA[cypher]]></category>
		<category><![CDATA[graph database]]></category>
		<category><![CDATA[heroku]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[neo4j]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[visualization]]></category>

		<guid isPermaLink="false">http://maxdemarzi.com/?p=896</guid>
		<description><![CDATA[Last week we saw Sigma.js, and as promised here is a graph visualization with Three.js and Neo4j. Three.js is a lightweight 3D library, written by Mr. Doob and a small army of contributors. The things you can do with Three.js are amazing, and my little demo here doesn&#8217;t give it justice, but nonetheless I&#8217;ll show [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=maxdemarzi.com&#038;blog=31056513&#038;post=896&#038;subd=maxdemarzidotcom&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://neothree.herokuapp.com/index.html" target="_blank"><img src="http://maxdemarzidotcom.files.wordpress.com/2012/04/threed2.jpg?w=580&h=168" alt="" title="threed2" width="580" height="168" class="aligncenter size-full wp-image-933" /></a></p>
<p>Last week we saw <a href="http://maxdemarzi.com/2012/04/12/using-sigma-js-with-neo4j/" title="Using Sigma.js with Neo4j">Sigma.js</a>, and as promised here is a graph visualization with <a href="http://mrdoob.github.com/three.js/" target="_blank">Three.js</a> and <a href="http://neo4j.org/" target="_blank">Neo4j</a>.  Three.js is a lightweight 3D library, written by <a href="https://twitter.com/#!/mrdoob" target="_blank">Mr. Doob</a> and a small army of contributors.</p>
<p>The things you can do with Three.js are amazing, and my little demo here doesn&#8217;t give it justice, but nonetheless I&#8217;ll show you how to build it.<br />
<span id="more-896"></span><br />
We need to pass the nodes and relationships to Three.js, one of the ways we can do that easily is with the <a href="https://github.com/gazay/gon" target="_blank">Gon gem</a>, since we&#8217;re using sinatra, we&#8217;ll use the special <a href="https://github.com/gazay/gon-sinatra" target="_blank">gon-sinatra gem</a>.</p>
<p><pre class="brush: ruby;">
class App &lt; Sinatra::Base
  register Gon::Sinatra
  
  def nodes
    neo = Neography::Rest.new
    cypher_query =  &quot; START node = node:nodes_index(type='User')&quot;
    cypher_query &lt;&lt; &quot; RETURN ID(node), node&quot;
    neo.execute_query(cypher_query)[&quot;data&quot;].collect{|n| {&quot;id&quot; =&gt; n[0]}.merge(n[1][&quot;data&quot;])}
  end  
  
  def edges
    neo = Neography::Rest.new
    cypher_query =  &quot; START source = node:nodes_index(type='User')&quot;
    cypher_query &lt;&lt; &quot; MATCH source -[rel]-&gt; target&quot;
    cypher_query &lt;&lt; &quot; RETURN ID(rel), ID(source), ID(target)&quot;
    neo.execute_query(cypher_query)[&quot;data&quot;].collect{|n| {&quot;id&quot; =&gt; n[0], &quot;source&quot; =&gt; n[1], &quot;target&quot; =&gt; n[2]} }
  end
  
  get '/' do
    neo = Neography::Rest.new
    gon.nodes = nodes  
    gon.edges = edges
    erb :index
  end
end
</pre></p>
<p>In our view we will add&#8221;include_gon&#8221; which ties our nodes and edges to our html page.</p>
<p><pre class="brush: ruby;">
&lt;!doctype html&gt;
&lt;html lang=&quot;en&quot;&gt;
	&lt;head&gt;
		&lt;title&gt;Three.js and Neo4j&lt;/title&gt;
		&lt;%= include_gon %&gt;
		&lt;meta charset=&quot;utf-8&quot;&gt;
		&lt;script type=&quot;text/javascript&quot; src=&quot;Three.js&quot;&gt;&lt;/script&gt;
		&lt;link type=&quot;text/css&quot; rel=&quot;stylesheet&quot; href=&quot;neo_three.css&quot;/&gt;
	&lt;/head&gt;
	&lt;body&gt;
		&lt;script type=&quot;text/javascript&quot; src=&quot;neo_three.js&quot;&gt;&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;
</pre></p>
<p>If you view the source of index.html, you&#8217;ll see our nodes and edges.</p>
<p><pre class="brush: xml;">
window.gon = {};
gon.nodes=[{&quot;id&quot;:1,
            &quot;rotation_x&quot;:5.061454830783556,
            &quot;name&quot;:&quot;zfbushqe&quot;,
            &quot;position_y&quot;:256,
            &quot;position_x&quot;:658,
            &quot;position_z&quot;:577,
            &quot;rotation_y&quot;:3.543018381548489},              
           {&quot;id&quot;:2,
            &quot;rotation_x&quot;:4.572762640225143,
            &quot;name&quot;:&quot;afntayhh&quot;,
            &quot;position_y&quot;:-22,
            &quot;position_x&quot;:510,
            &quot;position_z&quot;:404,
            &quot;rotation_y&quot;:2.2689280275926285}
            ...
gon.edges=[{&quot;id&quot;:3,&quot;source&quot;:1,&quot;target&quot;:198},
           {&quot;id&quot;:2,&quot;source&quot;:1,&quot;target&quot;:39},
           {&quot;id&quot;:1,&quot;source&quot;:1,&quot;target&quot;:21}
           ...
           ]
</pre></p>
<p>To use Three.js, we&#8217;ll need to create a camera, a scene and pick a renderer to use.</p>
<p><pre class="brush: jscript;">
  camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 10000 );
  camera.position.z = 100;

  scene = new THREE.Scene();

  scene.add( camera );

  renderer = new THREE.CanvasRenderer();
  renderer.setSize( window.innerWidth, window.innerHeight );
  container.appendChild( renderer.domElement );
</pre></p>
<p>To create our nodes, we&#8217;ll use Spheres and use a normal material.  We&#8217;ll grab the nodes from gon and use their properties to position and set the orientation of our spheres.</p>
<p><pre class="brush: jscript;">
  var geometry = new THREE.SphereGeometry( 50, 8, 7, false );
  var material = new THREE.MeshNormalMaterial();
    
  group = new THREE.Object3D();
		
  for (n in gon.nodes) {
	
    var mesh = new THREE.Mesh( geometry, material );
    mesh.position.x = gon.nodes[n].position_x;
    mesh.position.y = gon.nodes[n].position_y;
    mesh.position.z = gon.nodes[n].position_z;
    mesh.rotation.x = gon.nodes[n].rotation_x;
    mesh.rotation.y = gon.nodes[n].rotation_y;
    mesh.matrixAutoUpdate = false;
    mesh.updateMatrix();
    group.add( mesh );

  }

  scene.add( group );
</pre></p>
<p>For our edges, we&#8217;ll create simple lines of random colors between the source and target nodes.</p>
<p><pre class="brush: jscript;">
  for (n in gon.edges) {
    var line_segment = new THREE.Geometry();
    line_segment.vertices.push( new THREE.Vertex( group.children[gon.edges[n].source - 1].position ) );
    line_segment.vertices.push( new THREE.Vertex( group.children[gon.edges[n].target - 1].position ) );
    var line = new THREE.Line( line_segment, 
                              new THREE.LineBasicMaterial( { color: Math.random() * 0xffffff, 
                                                             opacity: 0.5 } ) );

    scene.add(line)
  }
</pre></p>
<p>We&#8217;ll animate our visualization by rendering the scene and controlling the camera with the mouse.  </p>
<p><pre class="brush: jscript;">
document.addEventListener( 'mousemove',  onDocumentMouseMove,  false );

function onDocumentMouseMove(event) {
  mouseX = event.clientX - windowHalfX;
  mouseY = event.clientY - windowHalfY;
}

function animate() {
  requestAnimationFrame( animate );
  render();
}

function render() {
  camera.position.x += ( mouseX - camera.position.x ) * .05;
  camera.position.y += ( - mouseY + 200 - camera.position.y ) * .05;
  camera.lookAt( scene.position );
  renderer.render( scene, camera );
}
</pre></p>
<p>I&#8217;m going to skip the graph creation but all the code is available on <a href="https://github.com/maxdemarzi/neo_three" target="_blank">github</a> as usual, and you&#8217;ll definitively want to see this <a href="http://neothree.herokuapp.com/index.html" target="_blank">live on Heroku</a>.</p>
<p><a href="http://neothree.herokuapp.com/index.html" target="_blank"><img src="http://maxdemarzidotcom.files.wordpress.com/2012/04/threed3.jpg?w=580" alt="" title="threed3"   class="aligncenter size-full wp-image-947" /></a></p>
<p>If you want to learn more about Three.js, check out these <a href="http://aerotwist.com/tutorials/" target="_blank">tutorial</a> and these <a href="http://learningthreejs.com/" target="_blank">videos</a>.</p>
<br />Filed under: <a href='http://maxdemarzi.com/category/cypher/'>Cypher</a>, <a href='http://maxdemarzi.com/category/neography/'>Neography</a>, <a href='http://maxdemarzi.com/category/visualization/'>Visualization</a> Tagged: <a href='http://maxdemarzi.com/tag/cypher-2/'>cypher</a>, <a href='http://maxdemarzi.com/tag/graph-database/'>graph database</a>, <a href='http://maxdemarzi.com/tag/heroku/'>heroku</a>, <a href='http://maxdemarzi.com/tag/javascript/'>javascript</a>, <a href='http://maxdemarzi.com/tag/neo4j/'>neo4j</a>, <a href='http://maxdemarzi.com/tag/ruby/'>ruby</a>, <a href='http://maxdemarzi.com/tag/visualization-2/'>visualization</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/maxdemarzidotcom.wordpress.com/896/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/maxdemarzidotcom.wordpress.com/896/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/maxdemarzidotcom.wordpress.com/896/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/maxdemarzidotcom.wordpress.com/896/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/maxdemarzidotcom.wordpress.com/896/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/maxdemarzidotcom.wordpress.com/896/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/maxdemarzidotcom.wordpress.com/896/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/maxdemarzidotcom.wordpress.com/896/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/maxdemarzidotcom.wordpress.com/896/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/maxdemarzidotcom.wordpress.com/896/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/maxdemarzidotcom.wordpress.com/896/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/maxdemarzidotcom.wordpress.com/896/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/maxdemarzidotcom.wordpress.com/896/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/maxdemarzidotcom.wordpress.com/896/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=maxdemarzi.com&#038;blog=31056513&#038;post=896&#038;subd=maxdemarzidotcom&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://maxdemarzi.com/2012/04/16/using-three-js-with-neo4j/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/58750f2179edbd650b471280aa66fee5?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">grassbits</media:title>
		</media:content>

		<media:content url="http://maxdemarzidotcom.files.wordpress.com/2012/04/threed2.jpg" medium="image">
			<media:title type="html">threed2</media:title>
		</media:content>

		<media:content url="http://maxdemarzidotcom.files.wordpress.com/2012/04/threed3.jpg" medium="image">
			<media:title type="html">threed3</media:title>
		</media:content>
	</item>
		<item>
		<title>Using Sigma.js with Neo4j</title>
		<link>http://maxdemarzi.com/2012/04/12/using-sigma-js-with-neo4j/</link>
		<comments>http://maxdemarzi.com/2012/04/12/using-sigma-js-with-neo4j/#comments</comments>
		<pubDate>Thu, 12 Apr 2012 16:23:59 +0000</pubDate>
		<dc:creator>maxdemarzi</dc:creator>
				<category><![CDATA[Cypher]]></category>
		<category><![CDATA[Heroku]]></category>
		<category><![CDATA[Visualization]]></category>
		<category><![CDATA[cypher]]></category>
		<category><![CDATA[graph database]]></category>
		<category><![CDATA[heroku]]></category>
		<category><![CDATA[neo4j]]></category>
		<category><![CDATA[nosql]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[visualization]]></category>

		<guid isPermaLink="false">http://maxdemarzi.com/?p=840</guid>
		<description><![CDATA[I&#8217;ve done a few posts recently using D3.js and now I want to show you how to use two other great Javascript libraries to visualize your graphs. We&#8217;ll start with Sigma.js and soon I&#8217;ll do another post with Three.js. We&#8217;re going to create our graph and group our nodes into five clusters. You&#8217;ll notice later [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=maxdemarzi.com&#038;blog=31056513&#038;post=840&#038;subd=maxdemarzidotcom&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://neosigma.herokuapp.com/index.html" target="_blank"><img src="http://maxdemarzidotcom.files.wordpress.com/2012/04/hairball.jpg?w=300&h=283" alt="" title="hairball" width="300" height="283" class="aligncenter size-medium wp-image-902" /></a></p>
<p>I&#8217;ve done a few posts recently using D3.js and now I want to show you how to use two other great Javascript libraries to visualize your graphs.  We&#8217;ll start with <a href="http://sigmajs.org" target="_blank">Sigma.js</a> and soon I&#8217;ll do another post with <a href="http://mrdoob.github.com/three.js/" target="_blank">Three.js</a>.<br />
<span id="more-840"></span></p>
<p>We&#8217;re going to create our graph and group our nodes into five clusters.   You&#8217;ll notice later on that we&#8217;re going to give our clustered nodes colors using rgb values so we&#8217;ll be able to see them move around until they find their right place in our layout.  We&#8217;ll be using two Sigma.js plugins, the <a href="http://gexf.net/format/" target="_blank">GEFX</a> (Graph Exchange XML Format) parser and the ForceAtlas2 layout.</p>
<p>You can see what a GEFX file looks like below.  Notice it comes from <a href="http://gephi.org/" target="_blank">Gephi</a> which is an interactive visualization and exploration platform, which runs on all major operating systems, is open source, and is free.</p>
<p><pre class="brush: xml;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;gexf xmlns=&quot;http://www.gephi.org/gexf&quot; xmlns:viz=&quot;http://www.gephi.org/gexf/viz&quot;&gt;
  &lt;graph defaultedgetype=&quot;directed&quot; idtype=&quot;string&quot; type=&quot;static&quot;&gt;
    &lt;nodes count=&quot;500&quot;&gt;
      &lt;node id=&quot;1&quot; label=&quot;tnabcuff&quot;&gt;
        &lt;viz:size value=&quot;12.0&quot;/&gt;
        &lt;viz:color b=&quot;113&quot; g=&quot;42&quot; r=&quot;78&quot;/&gt;
        &lt;viz:position x=&quot;-195&quot; y=&quot;-53&quot;/&gt;
      &lt;/node&gt;
      &lt;node id=&quot;2&quot; label=&quot;khnvxggh&quot;&gt;
        &lt;viz:size value=&quot;14.0&quot;/&gt;
        &lt;viz:color b=&quot;237&quot; g=&quot;250&quot; r=&quot;36&quot;/&gt;
        &lt;viz:position x=&quot;277&quot; y=&quot;-73&quot;/&gt;
      &lt;/node&gt;
      ...
    &lt;/nodes&gt;
    &lt;edges count=&quot;2985&quot;&gt;
      &lt;edge id=&quot;0&quot; source=&quot;1&quot; target=&quot;11&quot;/&gt;
      &lt;edge id=&quot;1&quot; source=&quot;1&quot; target=&quot;21&quot;/&gt;
      &lt;edge id=&quot;2&quot; source=&quot;1&quot; target=&quot;31&quot;/&gt;
      ...
    &lt;/edges&gt;
  &lt;/graph&gt;
&lt;/gexf&gt;
</pre></p>
<p>In order to build this file, we will need to get the nodes and edges from the graph and create an XML file.</p>
<p><pre class="brush: ruby;">
get '/graph.xml' do
  @nodes = nodes  
  @edges = edges
  builder :graph
end
</pre></p>
<p>We&#8217;ll use Cypher to get our nodes and edges:</p>
<p><pre class="brush: ruby;">
def nodes
  neo = Neography::Rest.new
  cypher_query =  &quot; START node = node:nodes_index(type='User')&quot;
  cypher_query &lt;&lt; &quot; RETURN ID(node), node&quot;
  neo.execute_query(cypher_query)[&quot;data&quot;].collect{|n| {&quot;id&quot; =&gt; n[0]}.merge(n[1][&quot;data&quot;])}
end  
</pre></p>
<p>We need the node and relationship ids, so notice I&#8217;m using the ID() function in both cases.</p>
<p><pre class="brush: ruby;">
def edges
  neo = Neography::Rest.new
  cypher_query =  &quot; START source = node:nodes_index(type='User')&quot;
  cypher_query &lt;&lt; &quot; MATCH source -[rel]-&gt; target&quot;
  cypher_query &lt;&lt; &quot; RETURN ID(rel), ID(source), ID(target)&quot;
  neo.execute_query(cypher_query)[&quot;data&quot;].collect{|n| {&quot;id&quot; =&gt; n[0], 
                                                       &quot;source&quot; =&gt; n[1], 
                                                       &quot;target&quot; =&gt; n[2]} 
                                                      }
end
</pre></p>
<p>So far we have seen graphs represented as JSON, and we&#8217;ve built these manually.  Today we&#8217;ll take advantage of the <a href="http://rubydoc.info/gems/builder/3.0.0/frames" target="_blank">Builder</a> Ruby Gem to build our graph in XML.</p>
<p><pre class="brush: ruby;">
xml.instruct! :xml
xml.gexf 'xmlns' =&gt; &quot;http://www.gephi.org/gexf&quot;, 'xmlns:viz' =&gt; &quot;http://www.gephi.org/gexf/viz&quot;  do
  xml.graph 'defaultedgetype' =&gt; &quot;directed&quot;, 'idtype' =&gt; &quot;string&quot;, 'type' =&gt; &quot;static&quot; do
    xml.nodes :count =&gt; @nodes.size do
      @nodes.each do |n|
        xml.node :id =&gt; n[&quot;id&quot;],    :label =&gt; n[&quot;name&quot;] do
	   xml.tag!(&quot;viz:size&quot;,     :value =&gt; n[&quot;size&quot;])
	   xml.tag!(&quot;viz:color&quot;,    :b =&gt; n[&quot;b&quot;], :g =&gt; n[&quot;g&quot;], :r =&gt; n[&quot;r&quot;])
	   xml.tag!(&quot;viz:position&quot;, :x =&gt; n[&quot;x&quot;], :y =&gt; n[&quot;y&quot;]) 
	 end
      end
    end
    xml.edges :count =&gt; @edges.size do
      @edges.each do |e|
        xml.edge:id =&gt; e[&quot;id&quot;], :source =&gt; e[&quot;source&quot;], :target =&gt; e[&quot;target&quot;] 
      end
    end
  end
end
</pre></p>
<p>You can get the code on <a href="https://github.com/maxdemarzi/neo_sigma" target="_blank">github</a> as usual and see it running live on Heroku at <a href="http://neosigma.herokuapp.com/index.html" target="_blank">neosigma.herokuapp.com</a>. You will want to <a href="http://neosigma.herokuapp.com/index.html" target="_blank">see it live on Heroku</a> so you can see the nodes in random positions and then move to form clusters.  Use your mouse wheel to zoom in, and click and drag to move around.</p>
<p><a href="http://neosigma.herokuapp.com/index.html"><img src="http://maxdemarzidotcom.files.wordpress.com/2012/04/hairball_zoom.png?w=580&h=149" alt="" title="hairball_zoom" width="580" height="149" class="aligncenter size-full wp-image-919" /></a></p>
<p>Credit goes out to <a href="http://ofnodesandedges.com/" target="_blank">Alexis Jacomy</a> and <a href="http://www.medialab.sciences-po.fr/fr/team/mathieu-jacomy/" target="_blank">Mathieu Jacomy</a>.</p>
<p>You&#8217;ve seen me create numerous random graphs, but for completeness here is the code for this graph.  Notice how I create 5 clusters and for each node I assign half its relationships to other nodes in their cluster and half to random nodes?  This is so the ForceAtlas2 layout plugin clusters our nodes neatly.</p>
<p><pre class="brush: ruby;">
def create_graph
  neo = Neography::Rest.new
  graph_exists = neo.get_node_properties(1)
  return if graph_exists &amp;&amp; graph_exists['name']

  names = 500.times.collect{|x| generate_text}
  clusters = 5.times.collect{|x| {:r =&gt; rand(256),
                                  :g =&gt; rand(256),
                                  :b =&gt; rand(256)} }
  commands = []
  names.each_index do |n|
    cluster = clusters[n % clusters.size]
    commands &lt;&lt; [:create_node, {:name =&gt; names[n], 
                                :size =&gt; 5.0 + rand(20.0), 
                                :r =&gt; cluster[:r],
                                :g =&gt; cluster[:g],
                                :b =&gt; cluster[:b],
                                :x =&gt; rand(600) - 300,
                                :y =&gt; rand(150) - 150
                                 }]
  end
 
  names.each_index do |from| 
    commands &lt;&lt; [:add_node_to_index, &quot;nodes_index&quot;, &quot;type&quot;, &quot;User&quot;, &quot;{#{from}}&quot;]
    connected = []

    # create clustered relationships
    members = 20.times.collect{|x| x * 10 + (from % clusters.size)}
    members.delete(from)
    rels = 3
    rels.times do |x|
      to = members[x]
      connected &lt;&lt; to
      commands &lt;&lt; [:create_relationship, &quot;follows&quot;, &quot;{#{from}}&quot;, &quot;{#{to}}&quot;]  unless to == from
    end    

    # create random relationships
    rels = 3
    rels.times do |x|
      to = rand(names.size)
      commands &lt;&lt; [:create_relationship, &quot;follows&quot;, &quot;{#{from}}&quot;, &quot;{#{to}}&quot;] unless (to == from) || connected.include?(to)
    end

  end

  batch_result = neo.batch *commands
end
</pre></p>
<br />Filed under: <a href='http://maxdemarzi.com/category/cypher/'>Cypher</a>, <a href='http://maxdemarzi.com/category/heroku-2/'>Heroku</a>, <a href='http://maxdemarzi.com/category/visualization/'>Visualization</a> Tagged: <a href='http://maxdemarzi.com/tag/cypher-2/'>cypher</a>, <a href='http://maxdemarzi.com/tag/graph-database/'>graph database</a>, <a href='http://maxdemarzi.com/tag/heroku/'>heroku</a>, <a href='http://maxdemarzi.com/tag/neo4j/'>neo4j</a>, <a href='http://maxdemarzi.com/tag/nosql/'>nosql</a>, <a href='http://maxdemarzi.com/tag/ruby/'>ruby</a>, <a href='http://maxdemarzi.com/tag/visualization-2/'>visualization</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/maxdemarzidotcom.wordpress.com/840/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/maxdemarzidotcom.wordpress.com/840/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/maxdemarzidotcom.wordpress.com/840/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/maxdemarzidotcom.wordpress.com/840/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/maxdemarzidotcom.wordpress.com/840/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/maxdemarzidotcom.wordpress.com/840/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/maxdemarzidotcom.wordpress.com/840/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/maxdemarzidotcom.wordpress.com/840/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/maxdemarzidotcom.wordpress.com/840/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/maxdemarzidotcom.wordpress.com/840/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/maxdemarzidotcom.wordpress.com/840/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/maxdemarzidotcom.wordpress.com/840/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/maxdemarzidotcom.wordpress.com/840/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/maxdemarzidotcom.wordpress.com/840/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=maxdemarzi.com&#038;blog=31056513&#038;post=840&#038;subd=maxdemarzidotcom&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://maxdemarzi.com/2012/04/12/using-sigma-js-with-neo4j/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/58750f2179edbd650b471280aa66fee5?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">grassbits</media:title>
		</media:content>

		<media:content url="http://maxdemarzidotcom.files.wordpress.com/2012/04/hairball.jpg?w=300" medium="image">
			<media:title type="html">hairball</media:title>
		</media:content>

		<media:content url="http://maxdemarzidotcom.files.wordpress.com/2012/04/hairball_zoom.png" medium="image">
			<media:title type="html">hairball_zoom</media:title>
		</media:content>
	</item>
		<item>
		<title>Slides from Chicago Graph Database March Meet-up</title>
		<link>http://maxdemarzi.com/2012/03/28/slides-from-chicago-graph-database-march-meet-up/</link>
		<comments>http://maxdemarzi.com/2012/03/28/slides-from-chicago-graph-database-march-meet-up/#comments</comments>
		<pubDate>Wed, 28 Mar 2012 16:41:18 +0000</pubDate>
		<dc:creator>maxdemarzi</dc:creator>
				<category><![CDATA[Cypher]]></category>
		<category><![CDATA[cypher]]></category>
		<category><![CDATA[graph database]]></category>
		<category><![CDATA[neo4j]]></category>
		<category><![CDATA[nosql]]></category>

		<guid isPermaLink="false">http://maxdemarzi.com/?p=875</guid>
		<description><![CDATA[Cypher View more PowerPoint from Max De Marzi Thank you very much to Groupon Engineering! They hosted our Graph Database Meet-up at their Headquarters. Join us April 30th, 2012 for Neo4j Basics and an introduction to Gremlin. Filed under: Cypher Tagged: cypher, graph database, neo4j, nosql<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=maxdemarzi.com&#038;blog=31056513&#038;post=875&#038;subd=maxdemarzidotcom&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<div style="width:425px;" id="__ss_12154713"> <strong><a href="http://www.slideshare.net/maxdemarzi/cypher-12154713" title="Cypher" target="_blank">Cypher</a></strong> <iframe src='http://www.slideshare.net/slideshow/embed_code/12154713' width='425' height='348' scrolling='no'></iframe>
<div style="padding:5px 0 12px;"> View more <a href="http://www.slideshare.net/thecroaker/death-by-powerpoint" target="_blank">PowerPoint</a> from <a href="http://www.slideshare.net/maxdemarzi" target="_blank">Max De Marzi</a> </div>
</p></div>
<p>Thank you very much to <a href="https://twitter.com/#!/GrouponEng" target="_blank">Groupon Engineering</a>!  They hosted our Graph Database Meet-up at their Headquarters.</p>
<p>Join us April 30th, 2012 for <a href="http://www.meetup.com/windy-city-graphdb/events/57156832/" target="_blank">Neo4j Basics and an introduction to Gremlin</a>.</p>
<p><a href="http://www.meetup.com/windy-city-graphdb/events/57156832/" target="_blank"><img src="http://maxdemarzidotcom.files.wordpress.com/2012/01/gremlin-logo.png?w=580" alt="" title="gremlin-logo"   class="aligncenter size-full wp-image-49" /></a></p>
<br />Filed under: <a href='http://maxdemarzi.com/category/cypher/'>Cypher</a> Tagged: <a href='http://maxdemarzi.com/tag/cypher-2/'>cypher</a>, <a href='http://maxdemarzi.com/tag/graph-database/'>graph database</a>, <a href='http://maxdemarzi.com/tag/neo4j/'>neo4j</a>, <a href='http://maxdemarzi.com/tag/nosql/'>nosql</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/maxdemarzidotcom.wordpress.com/875/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/maxdemarzidotcom.wordpress.com/875/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/maxdemarzidotcom.wordpress.com/875/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/maxdemarzidotcom.wordpress.com/875/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/maxdemarzidotcom.wordpress.com/875/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/maxdemarzidotcom.wordpress.com/875/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/maxdemarzidotcom.wordpress.com/875/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/maxdemarzidotcom.wordpress.com/875/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/maxdemarzidotcom.wordpress.com/875/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/maxdemarzidotcom.wordpress.com/875/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/maxdemarzidotcom.wordpress.com/875/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/maxdemarzidotcom.wordpress.com/875/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/maxdemarzidotcom.wordpress.com/875/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/maxdemarzidotcom.wordpress.com/875/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=maxdemarzi.com&#038;blog=31056513&#038;post=875&#038;subd=maxdemarzidotcom&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://maxdemarzi.com/2012/03/28/slides-from-chicago-graph-database-march-meet-up/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/58750f2179edbd650b471280aa66fee5?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">grassbits</media:title>
		</media:content>

		<media:content url="http://maxdemarzidotcom.files.wordpress.com/2012/01/gremlin-logo.png" medium="image">
			<media:title type="html">gremlin-logo</media:title>
		</media:content>
	</item>
		<item>
		<title>Visualizing a set of Hiveplots with Neo4j</title>
		<link>http://maxdemarzi.com/2012/03/26/visualizing-a-set-of-hiveplots-with-neo4j/</link>
		<comments>http://maxdemarzi.com/2012/03/26/visualizing-a-set-of-hiveplots-with-neo4j/#comments</comments>
		<pubDate>Mon, 26 Mar 2012 16:47:15 +0000</pubDate>
		<dc:creator>maxdemarzi</dc:creator>
				<category><![CDATA[Gremlin]]></category>
		<category><![CDATA[Visualization]]></category>
		<category><![CDATA[d3.js]]></category>
		<category><![CDATA[graph database]]></category>
		<category><![CDATA[gremlin]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[neo4j]]></category>
		<category><![CDATA[network]]></category>
		<category><![CDATA[visualization]]></category>

		<guid isPermaLink="false">http://maxdemarzi.com/?p=572</guid>
		<description><![CDATA[What should a graph look like and how can I tell two graphs apart? These are questions Martin Krzywinski (Genome Sciences Center, Vancouver, BC) has been asking. Take a look at the picture below: It&#8217;s the same graph, the same data, visualized 8 different ways. Which is the right way? What advantage does one layout [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=maxdemarzi.com&#038;blog=31056513&#038;post=572&#038;subd=maxdemarzidotcom&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://hiveplot.com/" target="_blank"><img src="http://maxdemarzidotcom.files.wordpress.com/2012/03/hiveplots.png?w=580" alt="" title="hiveplots"   class="aligncenter size-full wp-image-844" /><br />
</a></p>
<p>What should a graph look like and how can I tell two graphs apart? </p>
<p><span id="more-572"></span><br />
These are questions <a href="http://mkweb.bcgsc.ca/" target="_blank">Martin Krzywinski</a> (Genome Sciences Center, Vancouver, BC) has been asking.  Take a look at the picture below:</p>
<p><a href="http://mkweb.bcgsc.ca/linnet/" target="_blank"><img src="http://maxdemarzidotcom.files.wordpress.com/2012/03/networklayouts-small.png?w=580" alt="" title="networklayouts-small"   class="aligncenter size-full wp-image-847" /></a></p>
<p>It&#8217;s the same graph, the same data, visualized 8 different ways.  Which is the right way? What advantage does one layout give over the other?  Can you tell it&#8217;s the same network?  I can&#8217;t.</p>
<p>Eight layouts might be too much, so let&#8217;s just look at one on the next picture:</p>
<p><img src="http://maxdemarzidotcom.files.wordpress.com/2012/03/networklayouts-invariance.png?w=580" alt="" title="networklayouts-invariance"   class="aligncenter size-full wp-image-849" /></p>
<p>Martin took the spring embedded visualization and tweaked it around.  Can you tell it&#8217;s the same graph, the same data underneath? I can&#8217;t.</p>
<p>To tackle this problem, Martin invented the <a href='http://www.hiveplot.com/' target="_blank">Hive Plot</a>, a perceptually uniform and scalable layout visualization for network visual analytics.</p>
<p>If you want to learn more about Hive Plots, take a look at his website and this <a href="http://www.hiveplot.com/talks/hive-plot.pdf" target="_blank">presentation</a> (it is quite large at 20 MB).  I cannot do it justice in this short blog post, and in all honestly haven&#8217;t had the time to study it properly.</p>
<p>Today I just want to give you a little taste of Hiveplots.  I am going to visualize the github graphs of nine languages you might not have heard of: Boo, Dylan, Factor, Gosu, Mirah, Nemerle, Nu, Parrot, Self.  I&#8217;m not going to show you how to create the graph this time, because this is real data we are using.  You can take a look at it on the <a href="https://github.com/maxdemarzi/hive_plot/tree/master/data" target="_blank">data folder</a> in github.</p>
<p>The graph is basically: (Language)&#8211;(Repository)&#8211;(User).  There are two relationships between Repository and User, wrote and forked.</p>
<p>I&#8217;ll show you how to get the data out and into our visualization.</p>
<p><pre class="brush: ruby;">
def wroterepos(language)
  neo = Neography::Rest.new
  neo.execute_script(&quot;m = [:]
                      g.V.filter{it.type == 'language' &amp;&amp; it.name == '#{language}'}
                       .in.transform{m[it.name] = it.in('wrote').gather{it.name}.next()}
                       .iterate()
                      m&quot;)
end
</pre></p>
<p>We do the same thing but for forked.  This may seem a bit strange to you, but what I am doing is kind of like the SQL equivalent of a LEFT OUTER JOIN with Gremlin.</p>
<p><pre class="brush: ruby;">
def forkedrepos(language)
  neo = Neography::Rest.new
  neo.execute_script(&quot;m = [:]
                      g.V.filter{it.type == 'language' &amp;&amp; it.name == '#{language}'}
                       .in.transform{m[it.name] = it.in('forked').gather{it.name}.next()}
                       .iterate()
                      m&quot;)
end
</pre></p>
<p>Now we do some ruby magic to put our data into the JSON format the visualization wants.</p>
<p><pre class="brush: ruby;">
get '/hive/:name' do
  repos        = []
  writers      = [] 
  forkers      = []
  temp_forkers = []
  temp_writers = []

  wroterepos(params[:name]).each_pair do |key, value|
    repos &lt;&lt; {&quot;name&quot; =&gt; key, &quot;imports&quot; =&gt; value, &quot;node_type&quot; =&gt; &quot;repo&quot;}
    temp_writers &lt;&lt; { &quot;name&quot; =&gt; value[0] }
  end

  i = 0
  forkedrepos(params[:name]).each_pair do |key, value|
    repos[i][&quot;imports&quot;] =  repos[i][&quot;imports&quot;] + value
    temp_writers[i][&quot;imports&quot;] = value
    temp_forkers &lt;&lt; value
    i += 1
  end

  temp_writers.group_by {|i| i[&quot;name&quot;]}.each do |w, f|
    writers &lt;&lt; {&quot;name&quot; =&gt; w, 
                &quot;imports&quot; =&gt; f.collect{|y| y[&quot;imports&quot;]}.flatten.uniq, 
                &quot;node_type&quot; =&gt; &quot;writer&quot;}
  end

  temp_forkers.flatten.uniq.delete_if{|x| writers.collect{|y| y[&quot;name&quot;]}.include?(x)}.each do |f|
    forkers &lt;&lt; {&quot;name&quot; =&gt; f, 
                &quot;imports&quot; =&gt; [], 
                &quot;node_type&quot; =&gt; &quot;forker&quot;}
  end

  (repos + writers + forkers).to_json
end
</pre></p>
<p>The blue color nodes are our repositories, the yellow nodes are our writers, and the green nodes are our forkers.  The 12 o’clock axis (the top) shows nodes with only outgoing relationships. The bottom-left axis shows nodes with only incoming relationships.  These are the writers without any forks, and the forkers who never started their own public projects. The remaining nodes in the bottom-right have both incoming and outgoing relationships.  These are the repository writers who created projects other people found worth forking.</p>
<p>The graphs are ordered across for each row in the following manner:</p>
<ul>
<li>Boo, Dylan, Factor</li>
<li>Gosu, Mirah, Nemerle</li>
<li>Nu, Parrot, Self</li>
</ul>
<p>Can you see the similarities between Boo, Factor and Numerle?  See how different they are from Gosu and Self?  What does the hive plot tell you about these Language github repositories?</p>
<p><a href="http://hiveplot.herokuapp.com/index.html" target="_blank"><img src="http://maxdemarzidotcom.files.wordpress.com/2012/03/hiveplots.jpg?w=580&h=503" alt="" title="hiveplots" width="580" height="503" class="aligncenter size-full wp-image-855" /></a></p>
<p>You can try a live version at <a href="http://hiveplot.herokuapp.com/index.html" target="_blank">hiveplot.herokuapp.com/index.html</a> and as always the code is available on <a href="https://github.com/maxdemarzi/hive_plot" target="_blank">github</a>.</p>
<p>Our visualization was done by <a href="http://www.cfcl.com/rdm" target="_blank">Rich Morin</a> and <a href="http://bost.ocks.org/mike/" target="_blank">Mike Bostock</a> with <a href="http://mbostock.github.com/d3/" target="_blank">D3.js</a>.  Is is a hot off the press work in progress.  You can follow the action on this <a href="https://groups.google.com/forum/?fromgroups#!topic/d3-js/uqd4yeNwoys" target="_blank">D3.js google group thread</a>.</p>
<br />Filed under: <a href='http://maxdemarzi.com/category/gremlin/'>Gremlin</a>, <a href='http://maxdemarzi.com/category/visualization/'>Visualization</a> Tagged: <a href='http://maxdemarzi.com/tag/d3-js/'>d3.js</a>, <a href='http://maxdemarzi.com/tag/graph-database/'>graph database</a>, <a href='http://maxdemarzi.com/tag/gremlin-2/'>gremlin</a>, <a href='http://maxdemarzi.com/tag/javascript/'>javascript</a>, <a href='http://maxdemarzi.com/tag/neo4j/'>neo4j</a>, <a href='http://maxdemarzi.com/tag/network/'>network</a>, <a href='http://maxdemarzi.com/tag/visualization-2/'>visualization</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/maxdemarzidotcom.wordpress.com/572/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/maxdemarzidotcom.wordpress.com/572/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/maxdemarzidotcom.wordpress.com/572/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/maxdemarzidotcom.wordpress.com/572/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/maxdemarzidotcom.wordpress.com/572/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/maxdemarzidotcom.wordpress.com/572/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/maxdemarzidotcom.wordpress.com/572/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/maxdemarzidotcom.wordpress.com/572/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/maxdemarzidotcom.wordpress.com/572/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/maxdemarzidotcom.wordpress.com/572/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/maxdemarzidotcom.wordpress.com/572/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/maxdemarzidotcom.wordpress.com/572/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/maxdemarzidotcom.wordpress.com/572/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/maxdemarzidotcom.wordpress.com/572/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=maxdemarzi.com&#038;blog=31056513&#038;post=572&#038;subd=maxdemarzidotcom&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://maxdemarzi.com/2012/03/26/visualizing-a-set-of-hiveplots-with-neo4j/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/58750f2179edbd650b471280aa66fee5?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">grassbits</media:title>
		</media:content>

		<media:content url="http://maxdemarzidotcom.files.wordpress.com/2012/03/hiveplots.png" medium="image">
			<media:title type="html">hiveplots</media:title>
		</media:content>

		<media:content url="http://maxdemarzidotcom.files.wordpress.com/2012/03/networklayouts-small.png" medium="image">
			<media:title type="html">networklayouts-small</media:title>
		</media:content>

		<media:content url="http://maxdemarzidotcom.files.wordpress.com/2012/03/networklayouts-invariance.png" medium="image">
			<media:title type="html">networklayouts-invariance</media:title>
		</media:content>

		<media:content url="http://maxdemarzidotcom.files.wordpress.com/2012/03/hiveplots.jpg" medium="image">
			<media:title type="html">hiveplots</media:title>
		</media:content>
	</item>
		<item>
		<title>MadCoderTV is live on Roku</title>
		<link>http://maxdemarzi.com/2012/03/20/madcodertv-is-live-on-roku/</link>
		<comments>http://maxdemarzi.com/2012/03/20/madcodertv-is-live-on-roku/#comments</comments>
		<pubDate>Tue, 20 Mar 2012 11:00:09 +0000</pubDate>
		<dc:creator>maxdemarzi</dc:creator>
				<category><![CDATA[Random]]></category>
		<category><![CDATA[channel]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[neo4j]]></category>
		<category><![CDATA[roku]]></category>
		<category><![CDATA[television]]></category>
		<category><![CDATA[video]]></category>

		<guid isPermaLink="false">http://maxdemarzi.com/?p=559</guid>
		<description><![CDATA[I&#8217;ve had a Roku streaming player for my TV for a few years now and a few months ago I got interested in how it actually worked. I started seeing more channels pop-up and I thought how hard could it be to put one up? So I found their SDK, grabbed their sample application and [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=maxdemarzi.com&#038;blog=31056513&#038;post=559&#038;subd=maxdemarzidotcom&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://madcoder.tv/" target="_blank"><img src="http://maxdemarzidotcom.files.wordpress.com/2012/02/madlogo.png?w=580" alt="" title="madlogo"   class="aligncenter size-full wp-image-561" /></a></p>
<p>I&#8217;ve had a <a href="http://gan.doubleclick.net/gan_click?lid=41000000027814151&amp;pubid=21000000000529578" target="_blank">Roku</a> streaming player for my TV for a few years now and a few months ago I got interested in how it actually worked.  I started seeing more channels pop-up and I thought how hard could it be to put one up?  So I found their <a href="http://www.roku.com/developer" target="_blank">SDK</a>, grabbed their sample application and after a few tweaks, some nice artwork and finding content, it was approved.</p>
<p>Why go through the trouble of doing this to watch videos on my TV when I can just watch them on the laptop?  One word&#8230; <strong>Distraction</strong>.  </p>
<p>If a video is more than 3 to 5 minutes long, there is a good chance I won&#8217;t make it all the way through.  It&#8217;s hard to sit still when you have the full power of your laptop and the internet at your fingertips.  On the TV, as long as there are no commercials, I&#8217;m pretty much going to just sit there and watch.  Maybe it is some mild form of ADD, maybe it&#8217;s normal.<br />
<span id="more-559"></span></p>
<p>I am using <a href="http://pages.github.com/" target="_blank">Github Pages</a> to host the xml for the feeds, and the videos are hosted on Amazon cloudfront by their owners.  You can find some RailsCasts and Confreaks videos at the moment, but the feeds like the channel are open source, so if you have any content you&#8217;d like to add, please send me a pull request to the gh-pages branch.</p>
<p>So what does this have to do with Ruby + Graphs?  </p>
<p>Well, I asked the Neo4j guys and they&#8217;re letting me have their videos on there as well.  So if you want to see Andreas Kollegger tell you how to get started with Neo4j on your 60&#8243; big screen at home, now you can.</p>
<p>The code is available at <a href="https://github.com/maxdemarzi/madcodertv" target="_blank">https://github.com/maxdemarzi/madcodertv</a> be sure to check out the <a href="https://github.com/maxdemarzi/madcodertv/tree/gh-pages" target="_blank">gh-pages branch</a> for the video content and send me a pull request if you have any videos you want to add!</p>
<p>Checkout a screenshot:</p>
<p><img src="http://maxdemarzidotcom.files.wordpress.com/2012/02/five.jpg?w=580&h=326" alt="" title="five" width="580" height="326" class="aligncenter size-full wp-image-562" /></p>
<p><strong>Update</strong>: So far 6500 developers have installed the channel.  If you have no idea what I&#8217;m talking about, a <a href="http://gan.doubleclick.net/gan_click?lid=41000000027814151&amp;pubid=21000000000529578">Roku</a> is a little box you attach to your TV and the internet and let&#8217;s you stream videos from over 400 channels.</p>
<p><a href="http://gan.doubleclick.net/gan_click?lid=41000000027814151&amp;pubid=21000000000529578"><img src="http://maxdemarzidotcom.files.wordpress.com/2012/03/roku2_300.jpg?w=580" alt="" title="roku2_300"   class="aligncenter size-full wp-image-836" /></a></p>
<br />Filed under: <a href='http://maxdemarzi.com/category/random/'>Random</a> Tagged: <a href='http://maxdemarzi.com/tag/channel/'>channel</a>, <a href='http://maxdemarzi.com/tag/github/'>github</a>, <a href='http://maxdemarzi.com/tag/neo4j/'>neo4j</a>, <a href='http://maxdemarzi.com/tag/roku/'>roku</a>, <a href='http://maxdemarzi.com/tag/television/'>television</a>, <a href='http://maxdemarzi.com/tag/video/'>video</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/maxdemarzidotcom.wordpress.com/559/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/maxdemarzidotcom.wordpress.com/559/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/maxdemarzidotcom.wordpress.com/559/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/maxdemarzidotcom.wordpress.com/559/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/maxdemarzidotcom.wordpress.com/559/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/maxdemarzidotcom.wordpress.com/559/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/maxdemarzidotcom.wordpress.com/559/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/maxdemarzidotcom.wordpress.com/559/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/maxdemarzidotcom.wordpress.com/559/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/maxdemarzidotcom.wordpress.com/559/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/maxdemarzidotcom.wordpress.com/559/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/maxdemarzidotcom.wordpress.com/559/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/maxdemarzidotcom.wordpress.com/559/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/maxdemarzidotcom.wordpress.com/559/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=maxdemarzi.com&#038;blog=31056513&#038;post=559&#038;subd=maxdemarzidotcom&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://maxdemarzi.com/2012/03/20/madcodertv-is-live-on-roku/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/58750f2179edbd650b471280aa66fee5?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">grassbits</media:title>
		</media:content>

		<media:content url="http://maxdemarzidotcom.files.wordpress.com/2012/02/madlogo.png" medium="image">
			<media:title type="html">madlogo</media:title>
		</media:content>

		<media:content url="http://maxdemarzidotcom.files.wordpress.com/2012/02/five.jpg" medium="image">
			<media:title type="html">five</media:title>
		</media:content>

		<media:content url="http://maxdemarzidotcom.files.wordpress.com/2012/03/roku2_300.jpg" medium="image">
			<media:title type="html">roku2_300</media:title>
		</media:content>
	</item>
		<item>
		<title>JUNG in Neo4j – Part 2</title>
		<link>http://maxdemarzi.com/2012/03/16/jung-in-neo4j-part-2/</link>
		<comments>http://maxdemarzi.com/2012/03/16/jung-in-neo4j-part-2/#comments</comments>
		<pubDate>Fri, 16 Mar 2012 06:35:22 +0000</pubDate>
		<dc:creator>maxdemarzi</dc:creator>
				<category><![CDATA[Cypher]]></category>
		<category><![CDATA[Gremlin]]></category>
		<category><![CDATA[Heroku]]></category>
		<category><![CDATA[Visualization]]></category>
		<category><![CDATA[cluster]]></category>
		<category><![CDATA[cypher]]></category>
		<category><![CDATA[d3.js]]></category>
		<category><![CDATA[graph database]]></category>
		<category><![CDATA[neo4j]]></category>
		<category><![CDATA[visualization]]></category>

		<guid isPermaLink="false">http://maxdemarzi.com/?p=760</guid>
		<description><![CDATA[A few weeks ago I showed you how to visualize a graph using the chord flare visualization and how to visualize a network using a force directed graph visualization from D3.js. On Twitter Claire Willett from Riparian Data asked: Visualizing a 200-node network w/ #Cypher + #D3js &#8211;cool method, but maybe a node quilt would [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=maxdemarzi.com&#038;blog=31056513&#038;post=760&#038;subd=maxdemarzidotcom&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><img src="http://maxdemarzidotcom.files.wordpress.com/2012/03/nodequilt-600.png?w=580&h=288" alt="" title="nodequilt-600" width="580" height="288" class="aligncenter size-full wp-image-764" /></p>
<p>A few weeks ago I showed you <a href="http://maxdemarzi.com/2012/02/02/graph-visualization-and-neo4j-part-three/" title="Graph Visualization and Neo4j – Part Three">how to visualize a graph</a> using the <a href="https://github.com/mbostock/d3/blob/master/examples/chord/chord-flare.html" target="_blank">chord flare visualization</a> and <a href="http://maxdemarzi.com/2012/02/13/visualizing-a-network-with-cypher/" target="_blank">how to visualize a network</a>  using a <a href="http://mbostock.github.com/d3/ex/force.html" target="_blank">force directed graph visualization</a> from D3.js.</p>
<p>On Twitter <a href="https://twitter.com/#!/clairedwillett" target="_blank">Claire Willett</a> from <a href="http://www.ripariandata.com/" target="_blank">Riparian Data</a> asked:</p>
<blockquote class='twitter-tweet'><p>Visualizing a 200-node network w/ <a href="http://twitter.com/search?q=%23Cypher" title="#Cypher">#Cypher</a> + <a href="http://twitter.com/search?q=%23D3js" title="#D3js">#D3js</a> &#8211;cool method, but maybe a node quilt would work better? <a href="http://ow.ly/92wDE"> ow.ly/92wDE</a> @<a href="https://twitter.com/maxdemarzi">maxdemarzi</a>&mdash; <br />&nbsp; (@RiparianData) <a href='http://twitter.com/#!/RiparianData/status/169099913580396544' data-datetime='2012-02-13T16:45:35+00:00'>February 13, 2012</a></p></blockquote>
<p>This post on <a href="http://eagereyes.org/techniques/graphs-hairball" target="_blank">Graphs Beyond the Hairball</a> by <a href="https://twitter.com/#!/eagereyes" target="_blank">Robert Kosara</a> explains why some non-traditional graph visualizations may work better and links us to an article explaining what a <a href="http://ieeexplore.ieee.org/xpl/freeabs_all.jsp?arnumber=6064992" target="_blank">Node Quilt</a> is and how it&#8217;s useful.  We&#8217;re going to just take the first step and build a Matrix representation of a graph.  We will use one of the JUNG clustering algorithms to help us understand it.<br />
<span id="more-760"></span></p>
<p>The study of social networks goes back to at least the ancient Greeks, but we won&#8217;t go back that far in time today&#8230; just to 1977.  A man named Wayne Zachary recorded the interactions of a Karate Club at a University for 2 years.  During this time a conflict developed between the administrator and the instructor and the club broke up into two.  Turns out you could predict which club each member would belong to by building a graph of their weighted relationships and spliting it along the <a href="http://en.wikipedia.org/wiki/Minimum_cut" target="_blank">minimum-cut</a>.</p>
<p><span style="text-align:center; display: block;"><a href="http://maxdemarzi.com/2012/03/16/jung-in-neo4j-part-2/"><img src="http://img.youtube.com/vi/we0b9ZT15SU/2.jpg" alt="" /></a></span></p>
<p>We&#8217;re working with <a href="http://neo4j.org" target="_blank">Neo4j</a>, and you all know Neo knows <strong>Kung Fu</strong>, so we&#8217;ll do something a little different.  Plus looking at a two node cluster is kinda lame&#8230; let&#8217;s go bigger.  We&#8217;re going to be using Neo4j with the JUNG jars already in the lib directory.  Refer to <a href="http://maxdemarzi.com/2012/03/13/jung-in-neo4j-part-1/" title="JUNG in Neo4j – Part 1">JUNG in Neo4j &#8211; Part 1</a> if you need help with that.  Let&#8217;s create our graph:</p>
<p><pre class="brush: ruby;">
def create_graph
  neo = Neography::Rest.new
  graph_exists = neo.get_node_properties(1)
  return if graph_exists &amp;&amp; graph_exists['name']

  names = %w[Aaron Achyuta Adam Adel Agam Alex Allison Amit Andreas Andrey 
             Andy Anne Barry Ben Bill Bob Brian Bruce Chris Corey 
             Dan Dave Dean Denis Eli Eric Esteban Ezl Fawad Gabriel 
             James Jason Jeff Jennifer Jim Jon Joe John Jonathan Justin 
             Kim Kiril LeRoy Lester Mark Max Maykel Michael Musannif Neil]

  commands = names.map{ |n| [:create_node, {&quot;name&quot; =&gt; n}]}

  names.each_index do |from| 
    commands &lt;&lt; [:add_node_to_index, &quot;nodes_index&quot;, &quot;type&quot;, &quot;User&quot;, &quot;{#{from}}&quot;]
    connected = []

    # create clustered relationships
    members = 5.times.collect{|x| x * 10 + (from % 10)}
    members.delete(from)
    rels = 1 + rand(4)
    rels.times do |x|
      to = members[x]
      connected &lt;&lt; to
      commands &lt;&lt; create_rel(from, to) unless to == from
    end    

    # create random relationships
    rels = 1 + rand(4)
    rels.times do |x|
      to = rand(names.size)
      commands &lt;&lt; create_rel(from, to) unless (to == from) || connected.include?(to)
    end    
   end
   batch_result = neo.batch *commands
end
</pre></p>
<p>I am once again using the first 50 names from the <a href="http://www.meetup.com/windy-city-graphdb/">Graph DataBase- Chicago Meet-Up</a> group.  You&#8217;ve seen me do this once or twice already, so I won&#8217;t go over it in detail, but as you can see above, I am forcing small clusters of relationships to exist along with random relationships.  Our relationships have a weight property, so the create_rel method is just this:</p>
<p><pre class="brush: ruby;">
def create_rel(x,y,z= 1 + rand(10))
  [:create_relationship, &quot;knows&quot;, &quot;{#{x}}&quot;, &quot;{#{y}}&quot;, {:weight =&gt; z}]
end
</pre></p>
<p>Our visualization is expecting a list of nodes already in groups, and a list of relationships that includes it&#8217;s strength.  The JSON object looks like this:</p>
<p><pre class="brush: ruby;">
{&quot;nodes&quot;:[{&quot;name&quot;:&quot;Myriel&quot;,&quot;group&quot;:1},
          {&quot;name&quot;:&quot;Napoleon&quot;,&quot;group&quot;:1},
          {&quot;name&quot;:&quot;Mlle.Baptistine&quot;,&quot;group&quot;:2}],
 &quot;links&quot;:[{&quot;source&quot;:1,&quot;target&quot;:0,&quot;value&quot;:1},
          {&quot;source&quot;:2,&quot;target&quot;:0,&quot;value&quot;:8},
          {&quot;source&quot;:3,&quot;target&quot;:0,&quot;value&quot;:10}]
}
</pre></p>
<p>Getting our nodes is pretty easy, we&#8217;ll use Gremlin to retrieve all but the root node.</p>
<p><pre class="brush: ruby;">
def get_nodes
  neo = Neography::Rest.new
  neo.execute_script(&quot;g.V.filter{it.id != 0}.transform{[it.id,it.name]}&quot;)
end 
</pre></p>
<p>Getting the relationships is also pretty ease, to switch it up, we&#8217;ll use Cypher.</p>
<p><pre class="brush: ruby;">
def get_relationships
  neo = Neography::Rest.new
  cypher_query =  &quot; START a = node:nodes_index(type='User')&quot;
  cypher_query &lt;&lt; &quot; MATCH a-[r:knows]-b&quot;
  cypher_query &lt;&lt; &quot; RETURN ID(a), ID(b), r.weight&quot;
  neo.execute_query(cypher_query)[&quot;data&quot;]
end 
</pre></p>
<p>Now comes the fun part.  To get our clusters, we&#8217;ll be using the Voltage Clusterer Class.  We don&#8217;t want the root node getting in the way, so we&#8217;ll create a sub-graph using TinkerGraph that excludes it (you could do something similar to cluster just a small part of a larger graph). We then pass this graph on to GraphJung and set our VoltageClusterer to try to get 10 clusters for us.</p>
<p><pre class="brush: ruby;">
def get_voltage_clusters
  neo = Neography::Rest.new
  lg = neo.execute_script(&quot;import edu.uci.ics.jung.algorithms.cluster.VoltageClusterer;
                            to = new TinkerGraph();
                            g.V.filter{it.id != 0}.sideEffect{toVertex = to.addVertex(it.getId()); 
                                           ElementHelper.copyProperties(it, toVertex);
                            }.iterate();   
                            g.E.sideEffect{toEdge = to.addEdge(it.getId(), 
                                                    to.v(it.getOutVertex().getId()), 
                                                    to.v(it.getInVertex().getId()),
                                                    it.getLabel());
                                            ElementHelper.copyProperties(it, toEdge);
                            }.iterate();
                            vc = new VoltageClusterer(new GraphJung(to), 10);
                            vc.cluster(10).id;
                            &quot;)
end
</pre></p>
<p>We can then put it all together to build that JSON object.</p>
<p><pre class="brush: ruby;">
get '/cluster' do
  clusters = Hash.new
  get_voltage_clusters.each_with_index {|item, index| item.each{|i| clusters[i.to_i] = index + 1} }
  nodes = get_nodes.map{|n| {&quot;name&quot; =&gt; n[1], &quot;group&quot; =&gt; clusters[n[0]]}}
  relationships = get_relationships.map{|r| {&quot;source&quot; =&gt; r[0] - 1, &quot;target&quot; =&gt; r[1] - 1, &quot;value&quot; =&gt; r[2]} }
  {:nodes =&gt; nodes, :links =&gt; relationships}.to_json
end	
</pre></p>
<p>Our visualization was done by <a href="http://bost.ocks.org/mike/" target="_blank">Mike Bostock</a> with <a href="http://mbostock.github.com/d3/" target="_blank">D3.js</a>.  As always, the code is on <a href="https://github.com/maxdemarzi/kung_fu" target="_blank">Github</a>.  Click on the image below to see the live example on <a href="http://kungfu.herokuapp.com/index.html" target="_blank">Heroku</a>.</p>
<p><a href="http://kungfu.herokuapp.com/index.html" target="_blank"><img src="http://maxdemarzidotcom.files.wordpress.com/2012/03/cluster.png?w=580" alt="" title="cluster"   class="aligncenter size-full wp-image-780" /></a></p>
<p>Note: The version on Heroku is using a pre-generated JSON file.</p>
<br />Filed under: <a href='http://maxdemarzi.com/category/cypher/'>Cypher</a>, <a href='http://maxdemarzi.com/category/gremlin/'>Gremlin</a>, <a href='http://maxdemarzi.com/category/heroku-2/'>Heroku</a>, <a href='http://maxdemarzi.com/category/visualization/'>Visualization</a> Tagged: <a href='http://maxdemarzi.com/tag/cluster/'>cluster</a>, <a href='http://maxdemarzi.com/tag/cypher-2/'>cypher</a>, <a href='http://maxdemarzi.com/tag/d3-js/'>d3.js</a>, <a href='http://maxdemarzi.com/tag/graph-database/'>graph database</a>, <a href='http://maxdemarzi.com/tag/neo4j/'>neo4j</a>, <a href='http://maxdemarzi.com/tag/visualization-2/'>visualization</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/maxdemarzidotcom.wordpress.com/760/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/maxdemarzidotcom.wordpress.com/760/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/maxdemarzidotcom.wordpress.com/760/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/maxdemarzidotcom.wordpress.com/760/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/maxdemarzidotcom.wordpress.com/760/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/maxdemarzidotcom.wordpress.com/760/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/maxdemarzidotcom.wordpress.com/760/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/maxdemarzidotcom.wordpress.com/760/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/maxdemarzidotcom.wordpress.com/760/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/maxdemarzidotcom.wordpress.com/760/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/maxdemarzidotcom.wordpress.com/760/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/maxdemarzidotcom.wordpress.com/760/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/maxdemarzidotcom.wordpress.com/760/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/maxdemarzidotcom.wordpress.com/760/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=maxdemarzi.com&#038;blog=31056513&#038;post=760&#038;subd=maxdemarzidotcom&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://maxdemarzi.com/2012/03/16/jung-in-neo4j-part-2/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/58750f2179edbd650b471280aa66fee5?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">grassbits</media:title>
		</media:content>

		<media:content url="http://maxdemarzidotcom.files.wordpress.com/2012/03/nodequilt-600.png" medium="image">
			<media:title type="html">nodequilt-600</media:title>
		</media:content>

		<media:content url="http://maxdemarzidotcom.files.wordpress.com/2012/03/cluster.png" medium="image">
			<media:title type="html">cluster</media:title>
		</media:content>
	</item>
		<item>
		<title>JUNG in Neo4j &#8211; Part 1</title>
		<link>http://maxdemarzi.com/2012/03/13/jung-in-neo4j-part-1/</link>
		<comments>http://maxdemarzi.com/2012/03/13/jung-in-neo4j-part-1/#comments</comments>
		<pubDate>Tue, 13 Mar 2012 16:34:09 +0000</pubDate>
		<dc:creator>maxdemarzi</dc:creator>
				<category><![CDATA[Gremlin]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[graph database]]></category>
		<category><![CDATA[gremlin]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jung]]></category>
		<category><![CDATA[neo4j]]></category>
		<category><![CDATA[pagerank]]></category>

		<guid isPermaLink="false">http://maxdemarzi.com/?p=744</guid>
		<description><![CDATA[It&#8217;s nice to have an arsenal. In the world of graph databases, one such stock room is the Java Universal Network/Graph Framework(JUNG) which contains a cache of algorithms from graph theory, data mining, and social network analysis, such as routines for clustering, decomposition, optimization, random graph generation, statistical analysis, and calculation of network distances, flows, [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=maxdemarzi.com&#038;blog=31056513&#038;post=744&#038;subd=maxdemarzidotcom&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><img src="http://maxdemarzidotcom.files.wordpress.com/2012/03/weneedguns.jpg?w=580" alt="" title="weneedguns"   class="aligncenter size-full wp-image-745" /></p>
<p>It&#8217;s nice to have an arsenal.  In the world of graph databases, one such stock room is the <a href="http://jung.sourceforge.net/index.html" target="_blank">Java Universal Network/Graph Framework(JUNG)</a> which contains a cache of algorithms from graph theory, data mining, and social network analysis, such as routines for clustering, decomposition, optimization, random graph generation, statistical analysis, and calculation of network distances, flows, and importance measures (centrality, PageRank, HITS, etc.).</p>
<p>We can use JUNG via the Blueprints <a href="https://github.com/tinkerpop/blueprints/wiki/JUNG-Ouplementation" target="_blank">ouplementation</a> and access it via <a href="https://github.com/tinkerpop/gremlin/wiki/Using-JUNG" target="_blank">Gremlin</a>.   It doesn&#8217;t come pre-packaged with Neo4j, but <a href="https://twitter.com/#!/mesirii" target="_blank">Michael Hunger</a> playing the role of &#8220;Tank&#8221; and was able to load up our stock room with a few key strokes.<br />
<span id="more-744"></span><br />
We&#8217;ll create a directory for our project.</p>
<p><pre class="brush: ruby;">
mkdir neojung
cd neojung
</pre></p>
<p>Let&#8217;s install Neography</p>
<p><pre class="brush: ruby;">
echo &quot;source 'http://rubygems.org'
gem 'neography' &quot; &gt; Gemfile
bundle install 
</pre></p>
<p>&#8230; add the tasks, and install noe4j.<br />
<pre class="brush: ruby;">
echo &quot;require 'neography/tasks'&quot; &gt;&gt; Rakefile
rake neo4j:install
</pre></p>
<p>At this point you have a barebones Neo4j installation in the neojung/neo4j directory.  To add JUNG we need to build a few jar files and add them to the neo4j lib directory. </p>
<p>We are going to be using Maven, so install it if you don&#8217;t have it.</p>
<p><pre class="brush: ruby;">
sudo apt-get install maven2
</pre></p>
<p>First thing we need to do is grab blueprints and build it.</p>
<p><pre class="brush: ruby;">
git clone git://github.com/tinkerpop/blueprints.git
cd blueprints/blueprints-graph-jung/
mvn clean -DskipTests install
</pre></p>
<p>We also need to get a copy of the dependencies.</p>
<p><pre class="brush: ruby;">
mvn dependency:copy-dependencies
</pre></p>
<p>Now we can copy all these jar files into Neo4j.</p>
<p><pre class="brush: ruby;">
cp target/*.jar ../../neo4j/lib
cp target/dependency/*.jar ../../neo4j/lib
</pre></p>
<p>Finally we need to add executable permissions to these jar files and start Neo4j.</p>
<p><pre class="brush: ruby;">
cd ../..
chmod +x neo4j/lib/*.jar
rake neo4j:start
</pre></p>
<p>If you bring up the Neo4j Power Tool Console on localhost:7474 and go into the Gremlin web shell you are now able to use JUNG algorithms. Let&#8217;s import the pagerank algorithm:</p>
<p><pre class="brush: ruby;">
import edu.uci.ics.jung.algorithms.scoring.PageRank  
==&gt;import com.tinkerpop.gremlin.*
==&gt;import com.tinkerpop.gremlin.java.*
==&gt;import com.tinkerpop.gremlin.pipes.*
...
==&gt;import edu.uci.ics.jung.algorithms.scoring.PageRank
</pre></p>
<p>We&#8217;ll  now create a small toy graph and run pagerank on it.</p>
<p><pre class="brush: ruby;">
j = new GraphJung(TinkerGraphFactory.createTinkerGraph());
==&gt; graphjung[tinkergraph[vertices:6 edges:6]]
pr = new PageRank&lt;Vertex,Edge&gt;(j, 0.15d)
==&gt; edu.uci.ics.jung.algorithms.scoring.PageRank@8f2588
pr.evaluate()
==&gt;
j.getVertices().collect{ [it, pr.getVertexScore(it)] }
==&gt; [v[3], 0.30472082661863664]
==&gt; [v[2], 0.14598540145985392]
==&gt; [v[1], 0.11375485828040566]
==&gt; [v[6], 0.11375485828040566]
==&gt; [v[5], 0.1757986539008436]
==&gt; [v[4], 0.14598540145985392]
</pre></p>
<p>If you have large graphs or low memory servers, you&#8217;ll want to heed this warning by <a href="http://markorodriguez.com/" target="_blank">Marko Rodriguez</a>.</p>
<blockquote><p>
NOTE: JUNG is a library that was developed for in-memory graph structures. As such, many of the aspects of its various classes are memory based. For instance, given the above PageRank example, the method pageRank.getVertexScore() is pulling from an in-memory Map that contains the score for each vertex. If the number of vertices in the graph is large, then such in-memory structures will ultimately throw an OutOfMemoryError. As such, be wary of such situations when using GraphJung.
</p></blockquote>
<p>I&#8217;ll be writing more about JUNG and how to use some of its other algorithms.  Be sure to<br />
<a target="_blank" title="Follow @maxdemarzi on Twitter" href="https://twitter.com/intent/follow?original_referer=http%3A%2F%2Fmaxdemarzi.com%2F&amp;region=follow_link&amp;screen_name=maxdemarzi&amp;source=followbutton&amp;variant=2.0"><i></i><span class="label" id="l">Follow <b>@maxdemarzi</b></span></a> to know as soon as they are posted.</p>
<br />Filed under: <a href='http://maxdemarzi.com/category/gremlin/'>Gremlin</a>, <a href='http://maxdemarzi.com/category/java-2/'>Java</a> Tagged: <a href='http://maxdemarzi.com/tag/graph-database/'>graph database</a>, <a href='http://maxdemarzi.com/tag/gremlin-2/'>gremlin</a>, <a href='http://maxdemarzi.com/tag/java/'>java</a>, <a href='http://maxdemarzi.com/tag/jung/'>jung</a>, <a href='http://maxdemarzi.com/tag/neo4j/'>neo4j</a>, <a href='http://maxdemarzi.com/tag/pagerank/'>pagerank</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/maxdemarzidotcom.wordpress.com/744/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/maxdemarzidotcom.wordpress.com/744/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/maxdemarzidotcom.wordpress.com/744/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/maxdemarzidotcom.wordpress.com/744/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/maxdemarzidotcom.wordpress.com/744/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/maxdemarzidotcom.wordpress.com/744/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/maxdemarzidotcom.wordpress.com/744/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/maxdemarzidotcom.wordpress.com/744/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/maxdemarzidotcom.wordpress.com/744/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/maxdemarzidotcom.wordpress.com/744/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/maxdemarzidotcom.wordpress.com/744/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/maxdemarzidotcom.wordpress.com/744/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/maxdemarzidotcom.wordpress.com/744/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/maxdemarzidotcom.wordpress.com/744/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=maxdemarzi.com&#038;blog=31056513&#038;post=744&#038;subd=maxdemarzidotcom&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://maxdemarzi.com/2012/03/13/jung-in-neo4j-part-1/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/58750f2179edbd650b471280aa66fee5?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">grassbits</media:title>
		</media:content>

		<media:content url="http://maxdemarzidotcom.files.wordpress.com/2012/03/weneedguns.jpg" medium="image">
			<media:title type="html">weneedguns</media:title>
		</media:content>
	</item>
		<item>
		<title>Connections in Time</title>
		<link>http://maxdemarzi.com/2012/03/08/connections-in-time/</link>
		<comments>http://maxdemarzi.com/2012/03/08/connections-in-time/#comments</comments>
		<pubDate>Fri, 09 Mar 2012 04:47:43 +0000</pubDate>
		<dc:creator>maxdemarzi</dc:creator>
				<category><![CDATA[Cypher]]></category>
		<category><![CDATA[Heroku]]></category>
		<category><![CDATA[Visualization]]></category>
		<category><![CDATA[cypher]]></category>
		<category><![CDATA[graph database]]></category>
		<category><![CDATA[neo4j]]></category>
		<category><![CDATA[network]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[visualization]]></category>

		<guid isPermaLink="false">http://maxdemarzi.com/?p=569</guid>
		<description><![CDATA[Some relationships change over time. Think about your friends from high school, college, work, the city you used to live in, the ones that liked you ex- better, etc. When exploring a social network it is important that we understand not only the strength of the relationship now, but over time. We can use communication [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=maxdemarzi.com&#038;blog=31056513&#038;post=569&#038;subd=maxdemarzidotcom&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><img src="http://maxdemarzidotcom.files.wordpress.com/2012/03/true_friends.jpg?w=580" alt="" title="true_friends"   class="aligncenter size-full wp-image-712" /></p>
<p>Some relationships change over time.  Think about your friends from high school, college, work, the city you used to live in, the ones that liked you ex- better, etc.  When exploring a social network it is important that we understand not only the strength of the relationship now, but over time.  We can use communication between people as a measure.</p>
<p>I ran into a <a href="http://seeplan.bengler.no/timelines/tjuvholmen" target="_blank">visualization</a> that explored how multiple parties where connected by communications in multiple projects.  We&#8217;re going to reuse it to explore how multiple people interact with each other.  So let&#8217;s make a network of 50 friends and connect them to each other multiple times.  Think of it as people writing on your facebook wall.<br />
<span id="more-569"></span><br />
We will use the names of the first 50 members of the <a href="http://www.meetup.com/windy-city-graphdb/" target="_blank">Graph DataBase- Chicago Meet-Up</a> group for our names, but we&#8217;ll need a way to generate random times and offset them to simulate when people joined the social network.</p>
<p><pre class="brush: ruby;">
def generate_time(from = Time.local(2004, 1, 1), to = Time.now)
  Time.at(from + rand * (to.to_f - from.to_f)).strftime('%Y-%m-%d')
end

def time_offset(n)
    Time.local(2004, 1, 1) + ((60*60*24*58) * n)
end
</pre></p>
<p>Let&#8217;s give our network a little something special.  In your group of friends, most are quiet, some mingle, and some are social butterflies.  We&#8217;ll create a random function with a power law distribution to model our connections and add a few outliers.</p>
<p><pre class="brush: ruby;">
def powerlaw(min=1,max=500,n=20,o=0.05)
    max += 1
    pl = ((max**(n+1) - min**(n+1))*rand() + min**(n+1))**(1.0/(n+1))
    rand &gt; o ? (max-1-pl.to_i)+min : rand(max).to_i
end
</pre></p>
<p>The code to create a relationship is pretty simple, we&#8217;ll use the Batch commands again and reference the nodes we create.</p>
<p><pre class="brush: ruby;">
def create_rel(from,to,start_date,end_date)
  [:create_relationship, &quot;wrote&quot;, &quot;{#{from}}&quot;, &quot;{#{to}}&quot;, {:date =&gt; generate_time(start_date,end_date)}]
end
</pre></p>
<p>Let&#8217;s put it together to create our graph.  In order for our data to make sense, we are limiting the messaging between people to when they were both using the social network.  You&#8217;ll see this in the maximum of the two nodes being passed into our time_offset method.</p>
<p><pre class="brush: ruby;">
def create_graph
  neo = Neography::Rest.new
  graph_exists = neo.get_node_properties(1)
  return if graph_exists &amp;&amp; graph_exists['name']
  commands = []
  names = %w[Aaron Achyuta Adam Adel Agam Alex Allison Amit Andreas Andrey 
             Andy Anne Barry Ben Bill Bob Brian Bruce Chris Corey 
             Dan Dave Dean Denis Eli Eric Esteban Ezl Fawad Gabriel 
             James Jason Jeff Jennifer Jim Jon Joe John Jonathan Justin 
             Kim Kiril LeRoy Lester Mark Max Maykel Michael Musannif Neil]

  commands = names.map{ |n| [:create_node, {&quot;name&quot; =&gt; n}]}

  names.each_index do |from|
    commands &lt;&lt; [:add_node_to_index, &quot;nodes_index&quot;, &quot;type&quot;, &quot;user&quot;, &quot;{#{from}}&quot;]  
    powerlaw.times do
      to = rand(50)
      commands &lt;&lt; create_rel(from,to,time_offset([from,to].max),Time.now) 
    end
  end
  batch_result = neo.batch *commands
end
</pre></p>
<p>Our visualization was built using <a href="http://mbostock.github.com/d3/" target="_blank">D3.js</a> and it makes a web request expecting to see a JSON object that looks like:</p>
<p><pre class="brush: ruby;">
{&quot;cases&quot;:[{&quot;title&quot;:&quot;Aaron&quot;,
           &quot;initiated_at&quot;:&quot;2005-01-14&quot;,
           &quot;last_correspondance_at&quot;:&quot;2012-02-14&quot;,
           &quot;exchanges&quot;:[{&quot;incoming&quot;:true,
                         &quot;sender_or_recipent&quot;:&quot;2&quot;,
                         &quot;journal_date&quot;:&quot;2007-04-09&quot;},
                        {&quot;incoming&quot;:true,
                         &quot;sender_or_recipent&quot;:&quot;2&quot;,
                         &quot;journal_date&quot;:&quot;2008-10-02&quot;}]}],
&quot;parties&quot;:[{&quot;id&quot;:1,&quot;name&quot;:&quot;Aaron&quot;,&quot;value&quot;:60},
          {&quot;id&quot;:2,&quot;name&quot;:&quot;Achyuta&quot;,&quot;value&quot;:144}]}
</pre></p>
<p>We spent some time getting our data into our graph, now let&#8217;s get it all back out.  Instead of getting everything in one shot, we&#8217;ll split the work into 3 queries.  The first one called get_parties will get the users of the social network using Cypher.  Notice that to get the ID of a node we use the ID() function and not me.id.  We are also using the count, min and max <a href="http://docs.neo4j.org/chunked/milestone/query-aggregation.html" target="_blank">cypher aggregate functions</a> to get the data we need.</p>
<p><pre class="brush: ruby;">
def get_parties
  neo = Neography::Rest.new
  cypher_query =  &quot; START me = node:nodes_index(type = 'user')&quot;
  cypher_query &lt;&lt; &quot; MATCH (me)-[r?:wrote]-()&quot;
  cypher_query &lt;&lt; &quot; RETURN ID(me), me.name, count(r), min(r.date), max(r.date)&quot;
  cypher_query &lt;&lt; &quot; ORDER BY ID(me)&quot;
  neo.execute_query(cypher_query)[&quot;data&quot;]
end
</pre></p>
<p>We&#8217;ll write another query to get the incoming relationships for each node.  We are using the <a href="http://docs.neo4j.org/chunked/milestone/query-aggregation.html#aggregation-collect" target="_blank">collect</a> function to get two arrays back, one for the ids of friends and one for the date of the relationships.</p>
<p><pre class="brush: ruby;">
def get_incoming_matrix
  neo = Neography::Rest.new
  cypher_query =  &quot; START me = node:nodes_index(type = 'user')&quot;
  cypher_query &lt;&lt; &quot; MATCH (me)&lt;-[r?:wrote]-(friends)&quot;
  cypher_query &lt;&lt; &quot; RETURN ID(me), me.name, collect(ID(friends)), collect(r.date)&quot;
  cypher_query &lt;&lt; &quot; ORDER BY ID(me)&quot;
  neo.execute_query(cypher_query)[&quot;data&quot;]
end
</pre></p>
<p>A second query gives us the outgoing relationships for each node.  Notice we are <a href="http://docs.neo4j.org/chunked/milestone/query-order.html" target="_blank">ordering</a> both queries by the <a href="http://docs.neo4j.org/chunked/milestone/query-function.html#functions-id" target="_blank">ID function</a>.</p>
<p><pre class="brush: ruby;">
def get_outgoing_matrix
  neo = Neography::Rest.new
  cypher_query =  &quot; START me = node:nodes_index(type = 'user')&quot;
  cypher_query &lt;&lt; &quot; MATCH (me)-[r?:wrote]-&gt;(friends)&quot;
  cypher_query &lt;&lt; &quot; RETURN ID(me), me.name, collect(ID(friends)), collect(r.date)&quot;
  cypher_query &lt;&lt; &quot; ORDER BY ID(me)&quot;
  neo.execute_query(cypher_query)[&quot;data&quot;]
end
</pre></p>
<p>Now we put it all together by combining the parties and their exchanges into a JSON object.</p>
<p><pre class="brush: ruby;">
get '/communication' do
  p = get_parties
  parties = p.map{|p| {&quot;id&quot; =&gt; p[0], &quot;name&quot; =&gt; p[1], &quot;value&quot; =&gt;p[2]} }
  cases = p.map{|p| {&quot;title&quot; =&gt; p[1], &quot;initiated_at&quot; =&gt; p[3], &quot;last_correspondance_at&quot; =&gt;p[4], &quot;exchanges&quot; =&gt; []} }
  
  gim = get_incoming_matrix
  gim.each_index do |im|
    sors = gim[im][2][1..(gim[im][2].size - 2)].split(&quot;, &quot;)
    jds  = gim[im][3][1..(gim[im][3].size - 2)].split(&quot;, &quot;)
    sors.size.times do |t|
      cases[im][&quot;exchanges&quot;] &lt;&lt;  {&quot;incoming&quot; =&gt; true, &quot;sender_or_recipent&quot; =&gt; sors[t], &quot;journal_date&quot; =&gt; jds[t]}  
    end
  end

  gom = get_outgoing_matrix
  gom.each_index do |om|
    sors = gom[om][2][1..(gom[om][2].size - 2)].split(&quot;, &quot;)
    jds  = gom[om][3][1..(gom[om][3].size - 2)].split(&quot;, &quot;)
    sors.size.times do |t|
      cases[om][&quot;exchanges&quot;] &lt;&lt;  {&quot;incoming&quot; =&gt; false, &quot;sender_or_recipent&quot; =&gt; sors[t], &quot;journal_date&quot; =&gt; jds[t]}  
    end
  end
  {:cases =&gt; cases, :parties =&gt; parties}.to_json
end
</pre></p>
<p>The string wrangling you see to populate sors and jds is necessary because Cypher returns an Array wrapped inside a string instead of a proper array.  One day we&#8217;ll get proper JSON objects back and this ugly little hack won&#8217;t be necessary. <strong>Update:</strong> We won&#8217;t have to wait long, the fix has been <a href="https://github.com/neo4j/community/issues/276" target="_blank">committed</a>.  All of the code is available on <a href="https://github.com/maxdemarzi/neotime" target="_blank">github</a> as usual and you can play with it live on <a href="http://neotime.herokuapp.com/index.html" target="_blank">heroku</a>.</p>
<p><a href="http://neotime.herokuapp.com/index.html"><img src="http://maxdemarzidotcom.files.wordpress.com/2012/03/neotime1.png?w=580&h=513" alt="" title="neotime" width="580" height="513" class="aligncenter size-full wp-image-716" /></a></p>
<p>You can use this visualization in many situations.  Use it to visualize github commits to multiple projects by your development team.  Conversations on Twitter about a range of Topics. Wikipedia page edits, patient records, resource utilization, etc.</p>
<p>Credits:<br />
This post is based on the <a href="http://vis.bengler.no/" target="_blank">work</a> of <a href="http://origo.no/even" target="_blank">Even Westvang</a> and his <a href="http://vis.bengler.no/projects/seeplan" target="_blank">SeePlan</a> series.  He will be open sourcing his work soon.  Watch this space for a link.</p>
<br />Filed under: <a href='http://maxdemarzi.com/category/cypher/'>Cypher</a>, <a href='http://maxdemarzi.com/category/heroku-2/'>Heroku</a>, <a href='http://maxdemarzi.com/category/visualization/'>Visualization</a> Tagged: <a href='http://maxdemarzi.com/tag/cypher-2/'>cypher</a>, <a href='http://maxdemarzi.com/tag/graph-database/'>graph database</a>, <a href='http://maxdemarzi.com/tag/neo4j/'>neo4j</a>, <a href='http://maxdemarzi.com/tag/network/'>network</a>, <a href='http://maxdemarzi.com/tag/ruby/'>ruby</a>, <a href='http://maxdemarzi.com/tag/visualization-2/'>visualization</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/maxdemarzidotcom.wordpress.com/569/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/maxdemarzidotcom.wordpress.com/569/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/maxdemarzidotcom.wordpress.com/569/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/maxdemarzidotcom.wordpress.com/569/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/maxdemarzidotcom.wordpress.com/569/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/maxdemarzidotcom.wordpress.com/569/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/maxdemarzidotcom.wordpress.com/569/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/maxdemarzidotcom.wordpress.com/569/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/maxdemarzidotcom.wordpress.com/569/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/maxdemarzidotcom.wordpress.com/569/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/maxdemarzidotcom.wordpress.com/569/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/maxdemarzidotcom.wordpress.com/569/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/maxdemarzidotcom.wordpress.com/569/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/maxdemarzidotcom.wordpress.com/569/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=maxdemarzi.com&#038;blog=31056513&#038;post=569&#038;subd=maxdemarzidotcom&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://maxdemarzi.com/2012/03/08/connections-in-time/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/58750f2179edbd650b471280aa66fee5?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">grassbits</media:title>
		</media:content>

		<media:content url="http://maxdemarzidotcom.files.wordpress.com/2012/03/true_friends.jpg" medium="image">
			<media:title type="html">true_friends</media:title>
		</media:content>

		<media:content url="http://maxdemarzidotcom.files.wordpress.com/2012/03/neotime1.png" medium="image">
			<media:title type="html">neotime</media:title>
		</media:content>
	</item>
	</channel>
</rss>
