diff --git a/deep_sequencing_unit/source/core-plugins/ngs-sample-overview-graph/1/as/webapps/sample-graph/html/webapp.js b/deep_sequencing_unit/source/core-plugins/ngs-sample-overview-graph/1/as/webapps/sample-graph/html/webapp.js
index 61ceeafe374cd4eaed5bb6bb7f511d3863e2b9d3..28f751b1c9b57aff2f860facfdc632cd7c745e97 100644
--- a/deep_sequencing_unit/source/core-plugins/ngs-sample-overview-graph/1/as/webapps/sample-graph/html/webapp.js
+++ b/deep_sequencing_unit/source/core-plugins/ngs-sample-overview-graph/1/as/webapps/sample-graph/html/webapp.js
@@ -275,7 +275,7 @@ SampleGraphModel.prototype.coalesceGraphData = function(data, callback) {
  */
 function SampleGraphPresenter(model) {
 	this.model = model;
-	this.renderer = new SimpleGraphRenderer();
+	this.renderer = new DagreGraphRenderer();
 	this.didCreateVis = false;
 	this.useBottomUpMode();
 	this.initializePresenter();
@@ -320,7 +320,6 @@ SampleGraphPresenter.prototype.calcuateVisibleColumnOffsets = function() {
 	if (!bottomUpMode) visibleColumns = visibleColumns.reverse();
 	this.visibleColumns = visibleColumns;
 	this.visibleColumns.forEach(function(column) { column.xOffset = xOffset; xOffset += column.width });
-	this.vizWidth = xOffset;
 };
 
 /**
@@ -374,13 +373,9 @@ SampleGraphPresenter.prototype.initializeGraphSamples = function()
 			sampleData.color = (!oneToOne) ? colors(row) : oneToOneColor;
 			sampleData.userEdgesVisible = null;
 			sampleData.edgesVisible = col + 1 < FIRST_COLLAPSED_COLUMN;
-			sampleData.width = width;
-			sampleData.height = LINE_HEIGHT;
 		}
 	}
 	this.allNodes = nodes;
-
-	this.vizHeight = (d3.max(nodes, function(d) { return d.length}) + 1) * LINE_HEIGHT + 5;
 }
 
 SampleGraphPresenter.prototype.updateVisibility = function() {
@@ -407,16 +402,16 @@ SampleGraphPresenter.prototype.updateVisibility = function() {
 }
 
 SampleGraphPresenter.prototype.updateLinks = function() {
-	var links = [];
+	var edges = [];
 	var outEdgesGetter = this.outEdgesFunction();
 	this.allNodes.forEach(function(samps) {
 		samps.forEach(function(d) { 
 			if (!d.visible) return;
-			outEdgesGetter(d).forEach(function(c) { if (c.visible) links.push(new SampleGraphEdge(d, c))});
+			outEdgesGetter(d).forEach(function(c) { if (c.visible) edges.push(new SampleGraphEdge(d, c))});
 		})
 	});
 
-	this.links = links;
+	this.edges = edges;
 }
 
 SampleGraphPresenter.prototype.updateNodes = function() {
@@ -477,28 +472,37 @@ function clickedTopDown() {
 }
 
 
-function textBBoxForNode(node) {
+function textBBoxForGraphNode(node) {
 	var bbox = presenter.renderer.columns.selectAll("text.sample")[node.col][node.visibleIndex].getBBox();
 	// Correct for the column
 	bbox.x += node.colOffset;
 	return bbox;
 }
 
+function textBBoxForDomNode(node) {
+	var bbox = node.parentNode.childNodes[0].getBBox();
+	return bbox;
+}
+
+function translate(x, y) {
+	return "translate(" + x + "," + y + ")";
+}
+
 var yLinkOffset = LINE_HEIGHT * 0.33;
 
 
 /**
  * A class that renders the graph
  */
-function SimpleGraphRenderer(presenter) {
+function SimpleGraphRenderer() {
 	// Function used to draw paths between elements
 	function source(d) {
-		// Find the associated text node in the DOM and use that as a basis for creating the links
-		var bbox = textBBoxForNode(d.source);
+		// Find the associated text node in the DOM and use that as a basis for creating the edges
+		var bbox = textBBoxForGraphNode(d.source);
 		return { x : bbox.x + bbox.width + 7, y  : bbox.y + yLinkOffset };
 	}
 	function target(d) {
-		var bbox = textBBoxForNode(d.target);
+		var bbox = textBBoxForGraphNode(d.target);
 		return { x : bbox.x, y  : bbox.y + yLinkOffset }
 	}
 
@@ -506,7 +510,7 @@ function SimpleGraphRenderer(presenter) {
 }
 
 /**
- * Draw links using the diagonal function
+ * Draw edges using the diagonal function
  */
 SimpleGraphRenderer.prototype.useDiagonalLinkPath = function(source, target) {
 	var diagonal = d3.svg.diagonal();
@@ -516,7 +520,7 @@ SimpleGraphRenderer.prototype.useDiagonalLinkPath = function(source, target) {
 }
 
 /**
- * Draw links using the line function
+ * Draw edges using the line function
  */
 SimpleGraphRenderer.prototype.useLineLinkPath = function(source, target) {
 	var line = d3.svg.line();
@@ -533,15 +537,12 @@ SimpleGraphRenderer.prototype.draw = function()
 {
 	presenter.updateState();
 	var nodes = presenter.nodes;
-	var vizWidth = presenter.vizWidth;
-	var vizHeight = presenter.vizHeight;
 
 	// Display the graph in an SVG element
 	this.viz = presenter.root.selectAll("svg").data([nodes]);
 	// Code under enter is run if there is no HTML element for a data element	
 	this.viz.enter().append("svg:svg").attr("class", "viz");
-	this.viz.attr("width", vizWidth);
-	this.viz.attr("height", vizHeight);
+
 	// Columns
 	this.columns = this.viz.selectAll("g").data(function(d) { return d });
 	this.columns.enter().append("svg:g").attr("class", "column");
@@ -550,6 +551,11 @@ SimpleGraphRenderer.prototype.draw = function()
 	this.drawHeaders();
 	this.drawNodes();
 	this.drawLinks();
+
+	var vizHeight = (d3.max(nodes, function(d) { return d.length}) + 1) * LINE_HEIGHT + 5;
+	var vizWidth = d3.sum(presenter.visibleColumns, function(column) { return column.width });
+	this.viz.attr("width", vizWidth);
+	this.viz.attr("height", vizHeight);
 }
 
 /**
@@ -604,7 +610,7 @@ SimpleGraphRenderer.prototype.drawNodes = function()
 		.transition()
 			.style("opacity", 0).remove();
 	ring
-		.attr("cx", function(d) { return textBBoxForNode(d).width + 7 })
+		.attr("cx", function(d) { return textBBoxForGraphNode(d).width + 7 })
 		.attr("cy", function(d, i) { return LINE_HEIGHT * (i+2) - yLinkOffset})
 		.style("fill", function(d) { return d.edgesVisible ? "none" : d.color})
 		.style("stroke", function(d) { return d.color})
@@ -616,11 +622,11 @@ SimpleGraphRenderer.prototype.drawNodes = function()
 }
 
 /**
- * Draw the links
+ * Draw the edges
  */
 SimpleGraphRenderer.prototype.drawLinks = function()
 {
-	var link = this.viz.selectAll("path.link").data(presenter.links);
+	var link = this.viz.selectAll("path.link").data(presenter.edges);
 	link.enter().append("svg:path")
 		.attr("class", "link")
 		.attr("pointer-events", "none")
@@ -639,23 +645,22 @@ SimpleGraphRenderer.prototype.drawLinks = function()
 /**
  * A class that renders the graph using dagre.
  */
-function DagreGraphRenderer(presenter) {
+function DagreGraphRenderer() {
 	// Function used to draw paths between elements
 	function source(d) {
-		// Find the associated text node in the DOM and use that as a basis for creating the links
-		var bbox = textBBoxForNode(d.source);
-		return { x : bbox.x + bbox.width + 7, y  : bbox.y + yLinkOffset };
+		var dagre = d.source.dagre;
+		return { x : dagre.x + (dagre.width / 2), y  : dagre.y + dagre.height + 5};
 	}
 	function target(d) {
-		var bbox = textBBoxForNode(d.target);
-		return { x : bbox.x, y  : bbox.y + yLinkOffset }
+		var dagre = d.target.dagre;
+		return { x : dagre.x + (dagre.width / 2), y  : dagre.y };
 	}
 
 	this.useLineLinkPath(source, target);
 }
 
 /**
- * Draw links using the diagonal function
+ * Draw edges using the diagonal function
  */
 DagreGraphRenderer.prototype.useDiagonalLinkPath = function(source, target) {
 	var diagonal = d3.svg.diagonal();
@@ -665,7 +670,7 @@ DagreGraphRenderer.prototype.useDiagonalLinkPath = function(source, target) {
 }
 
 /**
- * Draw links using the line function
+ * Draw edges using the line function
  */
 DagreGraphRenderer.prototype.useLineLinkPath = function(source, target) {
 	var line = d3.svg.line();
@@ -675,44 +680,49 @@ DagreGraphRenderer.prototype.useLineLinkPath = function(source, target) {
 		return line([[src.x, src.y], [dst.x, dst.y]]); }
 }
 
+var RANK_SEPARATION = 30;
 /**
  * Display the sample nodes.
  */
 DagreGraphRenderer.prototype.draw = function()
 {
 	presenter.updateState();
+	var nodes = presenter.nodes;
+
+	var viz;
+	// Display the graph in an SVG element
+	viz = presenter.root.selectAll("svg").data([nodes]);
+	this.viz = viz;
+	// Code under enter is run if there is no HTML element for a data element
+	viz.enter().append("svg:svg").attr("class", "viz");
+	// Columns
+	this.columns = this.viz.selectAll("g.column").data(function(d) { return d });
+	this.columns.enter().append("svg:g").attr("class", "column");
+	this.columns.exit().remove();
+
+	// Draw the nodes so we get the bounding boxes for the nodes
+	this.initialDrawNodes();
 
 	var dagreNodes = []
-	this.nodes.forEach(function(nodeGroup) { nodeGroup.forEach(function(d) { dagreNodes = dagreNodes.concat(d) }) });
+	presenter.nodes.forEach(function(nodeGroup) { nodeGroup.forEach(function(d) { dagreNodes = dagreNodes.concat(d) }) });
 
 	dagre.layout()
-		.nodeSep(50)
+		.nodeSep(RANK_SEPARATION)
 		.edgeSep(10)
-		.rankSep(50)
+		.rankSep(RANK_SEPARATION)
 		.nodes(dagreNodes)
-		.edges(this.links)
-	    .debugLevel(1)
+		.edges(presenter.edges)
 	    .run();
-	console.log(dagreNodes);
-
-	var nodes = presenter.nodes;
-	var vizWidth = presenter.vizWidth;
-	var vizHeight = presenter.vizHeight;
-
-	// Display the graph in an SVG element
-	this.viz = presenter.root.selectAll("svg").data([nodes]);
-	// Code under enter is run if there is no HTML element for a data element	
-	this.viz.enter().append("svg:svg").attr("class", "viz");
-	this.viz.attr("width", vizWidth);
-	this.viz.attr("height", vizHeight);
-	// Columns
-	this.columns = this.viz.selectAll("g").data(function(d) { return d });
-	this.columns.enter().append("svg:g").attr("class", "column");
-	this.columns.exit().remove();
-	this.columns.attr("transform", function(d, i) { return "translate(" + presenter.visibleColumns[i].xOffset + ", 0)"});
+	this.redrawNodes();
 	this.drawHeaders();
-	this.drawNodes();
 	this.drawLinks();
+
+	var vizWidth = d3.max(dagreNodes, function(d) {	return d.dagre.x + d.dagre.width; })
+	var vizHeight = d3.max(dagreNodes, function(d) { return d.dagre.y + d.dagre.height; })
+
+	// Resize the visualization
+	viz.attr("width", vizWidth + 20); // add space for the ring at the end
+	viz.attr("height", vizHeight + LINE_HEIGHT); // add a space to make it look less cramped
 }
 
 /**
@@ -720,24 +730,44 @@ DagreGraphRenderer.prototype.draw = function()
  */
 DagreGraphRenderer.prototype.drawHeaders = function()
 {
-	var header = this.columns.selectAll("text.header").data(function(d, i) { return [presenter.visibleColumns[i]] });
+	var sampleNodeGroup = this.columns.selectAll("g.sample").data(function(d) { return d });
+	var header = this.viz.selectAll("text.header").data(function(d, i) { return presenter.visibleColumns });
 	header.enter().append("svg:text")
 		.attr("class", "header")
 		.attr("x", "0")
-		.attr("y", LINE_HEIGHT)
 		.attr("text-anchor", "begin")
 		.style("font-weight", "bold");
 	header
+		.attr("y", function(d, i) {
+			var nodesAtLevel = sampleNodeGroup[i];
+			if (nodesAtLevel.length < 1) return 0;
+			var dagre = nodesAtLevel[0].__data__.dagre;
+			return dagre.y + dagre.height - 1;
+		})
+		.attr("opacity", function(d, i) {
+			var nodesAtLevel = sampleNodeGroup[i];
+			if (nodesAtLevel.length < 1) return 0;
+			return 1;
+		})
 		.text(function(d) { return d.label });
 }
 
 /**
  * Draw the nodes
  */
-DagreGraphRenderer.prototype.drawNodes = function()
+DagreGraphRenderer.prototype.initialDrawNodes = function()
 {
 	var outEdgesGetter = presenter.outEdgesFunction();
-	var sample = this.columns.selectAll("text.sample").data(function(d) { return d });
+	var sampleNodeGroup = this.columns.selectAll("g.sample").data(function(d) { return d });
+	sampleNodeGroup.enter().append("svg:g")
+		.attr("class", "sample")
+	sampleNodeGroup
+		sampleNodeGroup.attr("transform", function(d, i) { return translate(0, LINE_HEIGHT * (i+1)) });
+	sampleNodeGroup.exit()
+		.transition()
+			.style("opacity", 0).remove();
+
+	var sample = sampleNodeGroup.selectAll("text.sample").data(function(d) { return [d] });
 	sample.enter().append("svg:text")
 		.attr("class", "sample")
 		.attr("x", "0")
@@ -747,28 +777,19 @@ DagreGraphRenderer.prototype.drawNodes = function()
 		.on("click", function(d) { presenter.openSample(this, d) })
 		.transition()
 			.style("opacity", 1);
-	sample.exit()
-		.transition()
-			.style("opacity", 0).remove();
 	sample
-		.attr("x", "0")
-		.attr("y", function(d, i) { return LINE_HEIGHT * (i+2)})
-
 		.text(function(d) { return d.identifier });
 
-	var ring = this.columns.selectAll("circle.ring").data(function(d) { return d });
+	var ring = sampleNodeGroup.selectAll("circle.ring").data(function(d) { return [d] });
 	ring.enter().append("svg:circle")
 		.attr("class", "ring")
 		.attr("pointer-events", "all")
 		.attr("r", 0)
 		.style("cursor", "pointer")
 		.style("stroke-width", "2px")
-	ring.exit()
-		.transition()
-			.style("opacity", 0).remove();
 	ring
-		.attr("cx", function(d) { return textBBoxForNode(d).width + 7 })
-		.attr("cy", function(d, i) { return LINE_HEIGHT * (i+2) - yLinkOffset})
+		.attr("cx", function(d, i) { return textBBoxForDomNode(this).width + 7 })
+		.attr("cy", function(d, i) { return textBBoxForDomNode(this).height - 1 })
 		.style("fill", function(d) { return d.edgesVisible ? "none" : d.color})
 		.style("stroke", function(d) { return d.color})
 		.on("click", function(d) { presenter.toggleExpand(this, d) });
@@ -776,14 +797,31 @@ DagreGraphRenderer.prototype.drawNodes = function()
 		.transition()
 			.style("opacity", function(d) { return outEdgesGetter(d).length > 0 ? 1 : 0 })
 			.attr("r", 5);
+
+	// Update the bounding boxes
+	sampleNodeGroup.each(function(d) {
+		var bbox = this.getBBox();
+		d.width = bbox.width;
+		d.height = bbox.height;
+	});
+}
+
+/**
+ * Move the nodes in their new positions.
+ */
+DagreGraphRenderer.prototype.redrawNodes = function()
+{
+	var sampleNodeGroup = this.columns.selectAll("g.sample").data(function(d) { return d });
+	sampleNodeGroup
+		sampleNodeGroup.attr("transform", function(d, i) { return translate(d.dagre.x, d.dagre.y) });
 }
 
 /**
- * Draw the links
+ * Draw the edges
  */
 DagreGraphRenderer.prototype.drawLinks = function()
 {
-	var link = this.viz.selectAll("path.link").data(presenter.links);
+	var link = this.viz.selectAll("path.link").data(presenter.edges);
 	link.enter().append("svg:path")
 		.attr("class", "link")
 		.attr("pointer-events", "none")