Added D3 Histogram
diff --git a/exp_portal/templates/status.html b/exp_portal/templates/status.html
index 4d66ae0..79546a9 100644
--- a/exp_portal/templates/status.html
+++ b/exp_portal/templates/status.html
@@ -322,22 +322,22 @@
 				</div>
 				<div id="metrics" class="expTraySection">
 					<div id="metricsNav">
-						<div id="{{ experimentName }}LoadBtn" class="metricsNavBtn active">Load</div>
-						<div id="{{ experimentName }}DifficultyBtn" class="metricsNavBtn">Difficulty</div>
-						<div id="{{ experimentName }}PerformanceBtn" class="metricsNavBtn">Performance</div>
-						<div id="{{ experimentName }}ConfidenceBtn" class="metricsNavBtn">Confidence</div>
+						<div id="{{ experimentName }}LoadBtn" class="metricsNavBtn active" data-category="Load">Load</div>
+						<div id="{{ experimentName }}DifficultyBtn" class="metricsNavBtn" data-category="Difficulty">Difficulty</div>
+						<div id="{{ experimentName }}PerformanceBtn" class="metricsNavBtn" data-category="Performance">Performance</div>
+						<div id="{{ experimentName }}ConfidenceBtn" class="metricsNavBtn" data-category="Confidence">Confidence</div>
 						<!-- <div id="{{ experimentName }}ActivityBtn" class="metricsNavBtn">Activity</div> -->
-						<div id="{{ experimentName }}TimeBtn" class="metricsNavBtn">Time</div>
+						<div id="{{ experimentName }}TimeBtn" class="metricsNavBtn" data-category="Time">Time</div>
 					</div>
 					<div class="metricsBody">
 						<div class="metricsDropdowns">
 							<div class="selectTitle">Tool</div>
 							<select name="tools" id="toolsSelect">
-								<!-- <option value="all">All</option> -->
+								<option value="all">All</option>
 								{% for expObjKey, expObjVal in experimentVal.items %}
 									{% if 'products' in expObjKey %}
 										{% for product in expObjVal %}
-										<!-- <option value="{{ product.name }}">{{ product.name }}</option> -->
+										<option value="{{ product.name }}">{{ product.name }}</option>
 										{% endfor %}
 									{% endif %}
 								{% endfor %}
@@ -354,24 +354,7 @@
 								{% endfor %}
 							</select>
 						</div>
-						<div id="{{ experimentName }}Load" class="metricsSection active">
-							<svg id="{{ experimentName }}LoadChart" class="chart"></svg>
-						</div>
-						<div id="{{ experimentName }}Difficulty" class="metricsSection">
-							<svg id="{{ experimentName }}DifficultyChart" class="chart"></svg>
-						</div>
-						<div id="{{ experimentName }}Performance" class="metricsSection">
-							<svg id="{{ experimentName }}PerformanceChart" class="chart"></svg>
-						</div>
-						<div id="{{ experimentName }}Confidence" class="metricsSection">
-							<svg id="{{ experimentName }}ConfidenceChart" class="chart"></svg>
-						</div>
-						<!-- <div id="activity" class="metricsSection">
-							<svg id="{{ experimentName }}ActivityChart" class="chart"></svg>
-						</div> -->
-						<div id="{{ experimentName }}Time" class="metricsSection">
-							<svg id="{{ experimentName }}TimeChart" class="chart"></svg>
-						</div>
+						<div id="canvasD3" class="metricsSection active" data-experiment="{{ experimentName }}"></div>
 					</div>
 				</div>
 			</div>
diff --git a/exp_portal/urls.py b/exp_portal/urls.py
index accf510..07ce2df 100644
--- a/exp_portal/urls.py
+++ b/exp_portal/urls.py
@@ -6,6 +6,7 @@
 urlpatterns= patterns('',
 	url(r'^$', views.home_page, name='home'),
 	url(r'^all_status$', views.view_status, name='view_status'),
+	url(r'^metrics_data$', views.metrics_data, name='metrics_data'),
 	url(r'^experiments/manage$', views.manage_exps, name='manage_exps'),
 	url(r'^experiments/details/(?P<exppk>.*)$', views.view_exp_details, name='view_exp_details'),
 	url(r'^experiment/edit/(?P<exppk>.*)$', views.edit_exp, name='edit_exp'),
diff --git a/exp_portal/views.py b/exp_portal/views.py
index 6222f99..cd970f8 100644
--- a/exp_portal/views.py
+++ b/exp_portal/views.py
@@ -1,6 +1,10 @@
+import json
+import os.path
+
 from django.shortcuts import render, redirect
 from op_tasks.models import UserProfile, Product, Dataset, OpTask, TaskListItem, Experiment
 from django.contrib.auth.decorators import login_required
+from django.views.decorators.csrf import csrf_protect
 from django.http import JsonResponse
 from users import *
 from products import *
@@ -18,6 +22,46 @@
 	if user_authorized(request):
 		return render(request, 'experimenthome.html')
 
+@csrf_protect
+@login_required(login_url='/tasking/login')
+def metrics_data(request):
+	rparams = json.loads(request.body)
+	if request.method == 'POST':
+		experiment = rparams['experiment']
+		category = rparams['category']
+		tool = rparams['tool']
+		task = rparams['task']
+		# load experiment data from file
+		histDataFile = "/home/ubuntu/SCOtCH/"+experiment+".json"
+		histDataAll = []
+		if os.path.isfile(histDataFile):
+			with open(histDataFile) as data_file:
+				histDataAll = json.load(data_file)
+		# filter experiment data
+		histData = []
+		for row in histDataAll:
+			if (tool!="all" and tool!=row['SYS.FIL.APP.']) or (task!="all" and task!=row['SYS.FIL.TSK.']):
+				continue
+			if category=="Load":
+				if row['PST.EXP.CLD.'] != "NA" and row['PST.EXP.CLD.'] != "NaN":
+					histData.append(row['PST.EXP.CLD.'])
+			elif category=="Difficulty":
+				if row['PST.EXP.BED.'] != "NA" and row['PST.EXP.BED.'] != "NaN":
+					histData.append(row['PST.EXP.BED.'])
+			elif category=="Performance":
+				if row['TSK.PRB.ANS.'] != "NA" and row['TSK.PRB.ANS.'] != "NaN":
+					histData.append(row['TSK.PRB.ANS.'])
+			elif category=="Confidence":
+				if row['TSK.CON.'] != "NA" and row['TSK.CON.'] != "NaN":
+					histData.append(row['TSK.CON.'])
+			elif category=="Time":
+				if row['TSK.TIME.DIFF.'] != "NA" and row['TSK.TIME.DIFF.'] != "NaN" and row['TSK.TIME.DIFF.'] > 0 and row['TSK.TIME.DIFF.'] < 3000:
+					histData.append(row['TSK.TIME.DIFF.'])
+
+		return JsonResponse({"data":json.dumps(histData)})
+	else:
+		return JsonResponse({"request": "Not Supported"})
+
 @login_required(login_url='/tasking/login')
 def view_status(request):
 	if user_authorized(request):
@@ -196,4 +240,4 @@
 			experimentList["percentageComplete"] = percentageComplete
 			masterList[name] = experimentList
 		response = JsonResponse({'experimentInfo': str(masterList)})
-		return response
\ No newline at end of file
+		return response
diff --git a/static/css/styles.css b/static/css/styles.css
index b26a4ed..463b2a0 100644
--- a/static/css/styles.css
+++ b/static/css/styles.css
@@ -1000,6 +1000,21 @@
             text-anchor: end;
           }
 
+.bar rect {
+  fill: steelblue;
+  shape-rendering: crispEdges;
+}
+
+.bar text {
+  fill: #fff;
+}
+
+.axis path, .axis line {
+  fill: none;
+  stroke: #000;
+  shape-rendering: crispEdges;
+}
+
 .emailRow {
   float: left;
   margin-bottom: 20px;
diff --git a/static/javascript/base.js b/static/javascript/base.js
index cd91d3f..993add3 100644
--- a/static/javascript/base.js
+++ b/static/javascript/base.js
@@ -1,3 +1,18 @@
+var csrftoken = $.cookie('csrftoken');
+
+function csrfSafeMethod(method) {
+    // these HTTP methods do not require CSRF protection
+    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
+}
+
+$.ajaxSetup({
+    beforeSend: function(xhr, settings) {
+        if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
+            xhr.setRequestHeader("X-CSRFToken", csrftoken);
+        }
+    }
+});
+
 $("#contacts li").click(function(){
 	var emailAddress = $(this).html();
 	$("#email-to").val(emailAddress);
@@ -44,16 +59,30 @@
 	var divId = id.slice(0, -3);
 	$this.find(".expTraySection").removeClass("active");
 	$this.find("#" + divId).addClass("active");
+
+	if(divId=="metrics") {
+		var experiment = $(this).parents(".experimentStatusRow").attr("id");
+		var category = $this.find(".metricsNavBtn.active").attr("data-category");
+		var mparams = {"experiment":experiment,"tool":$this.find("#toolsSelect").val(),"task":$this.find("#tasksSelect").val(),"category":category};
+		getHistData(experiment, category, JSON.stringify(mparams));
+	}
 })
 
 $(".metricsNavBtn").click(function(){
 	$(this).parent().find(".metricsNavBtn").removeClass("active");
 	$(this).addClass("active");
-	var rowId = $(this).parents(".experimentStatusRow").attr("id");
-	$("#" + rowId + " .metricsSection").removeClass("active");
-	var id = $(this).attr("id");
-	id = id.slice(0, -3);
-	$("#" + id).addClass("active");
+	//var rowId = $(this).parents(".experimentStatusRow").attr("id");
+	//$("#" + rowId + " .metricsSection").removeClass("active");
+	//var id = $(this).attr("id");
+	//id = id.slice(0, -3);
+	//$("#" + id).addClass("active");
+
+	var $this = $(this).parents(".expTray");
+	var experiment = $(this).parents(".experimentStatusRow").attr("id");
+	var category = $(this).attr("data-category");
+	var mparams = {"experiment":experiment,"tool":$this.find("#toolsSelect").val(),"task":$this.find("#tasksSelect").val(),"category":category};
+	//console.log(".metricsNavBtn experiment = ", mparams);
+	getHistData(experiment, category, JSON.stringify(mparams)); 
 })
 
 $(".expShelf").click(function(){
@@ -75,15 +104,24 @@
 loopCharts(start);
 
 $("#toolsSelect, #tasksSelect").change(function(){
-	start = false;
-	var id = $(this).parents(".experimentStatusRow").attr("id");
-	$(".chart").empty();
-	loopCharts(start, id);
+//	start = false;
+//	var id = $(this).parents(".experimentStatusRow").attr("id");
+//	$(".chart").empty();
+//	loopCharts(start, id);
+
+        var $this = $(this).parents(".expTray");
+        var experiment = $(this).parents(".experimentStatusRow").attr("id");
+        var category = $this.find(".metricsNavBtn.active").attr("data-category");
+        var mparams = {"experiment":experiment,"tool":$this.find("#toolsSelect").val(),"task":$this.find("#tasksSelect").val(),"category":category};
+        //console.log(".metricsNavBtn experiment = ", mparams);
+        getHistData(experiment, category, JSON.stringify(mparams));
+
 });
 
 function loopCharts(start, id) {
 	if (start==true) {
-		startChartBuildwithToolLists();
+		//startChartBuildwithToolLists();
+		buildCharts();
 	} else if (start==false) {
 		buildCharts();
 	}
@@ -239,3 +277,96 @@
 	}
 }
 
+function getHistData(experimentName, categoryName, params) {
+	var xtick = 1;
+	if(categoryName=="Load") {
+		xtick = 2;
+	} else if(categoryName=="Time") {
+		xtick = 0.01;
+	}
+	$.ajax({
+		'type': 'POST',
+                'url': 'metrics_data',
+                'contentType': 'application/json',
+                'data': params,
+                'dataType': 'json',
+                'complete': function(xhrObj, msg){
+                	//console.log(xhrObj);
+                        var values = JSON.parse(xhrObj.responseJSON.data);
+                        //console.log(values);
+			if(values.length>0) {
+                        	buildD3Histogram('#canvasD3[data-experiment="'+experimentName+'"]', xtick, values);
+			} else {
+				$('#canvasD3[data-experiment="'+experimentName+'"]').text("Data unavailable.")
+			}
+		 }
+	});
+
+}
+
+function buildD3Histogram(canvasSelector, tickScale, histValues) {
+	$(canvasSelector).empty();
+
+	// Generate a Bates distribution of 10 random variables.
+	//var values = d3.range(1000).map(d3.random.bates(10));
+	var values = histValues;
+
+	var minVal = Math.floor(Math.min.apply(Math, values));
+	var maxVal = Math.ceil(Math.max.apply(Math, values));
+
+	// A formatter for counts.
+	var formatCount = d3.format(",.0f");
+
+	var margin = {top: 10, right: 30, bottom: 30, left: 30},
+    	//width = 960 - margin.left - margin.right,
+	width = $(canvasSelector).width(),
+    	//height = 500 - margin.top - margin.bottom;
+	height = 320;
+
+	var x = d3.scale.linear()
+    		.domain([0, maxVal+minVal])
+    		.range([0, width]);
+
+	// Generate a histogram using twenty uniformly-spaced bins.
+	var data = d3.layout.histogram()
+    			.bins(x.ticks((maxVal+minVal)*tickScale))
+    			(values);
+
+	var y = d3.scale.linear()
+    		.domain([0, d3.max(data, function(d) { return d.y; })])
+    		.range([height, 0]);
+
+	var xAxis = d3.svg.axis()
+    		.scale(x)
+    		.orient("bottom");
+
+	var svg = d3.select(canvasSelector).append("svg")
+    		.attr("width", width + margin.left + margin.right)
+    		.attr("height", height + margin.top + margin.bottom)
+  		.append("g")
+    		.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
+
+	var bar = svg.selectAll(".bar")
+    		.data(data)
+  		.enter().append("g")
+    		.attr("class", "bar")
+    		.attr("transform", function(d) { return "translate(" + x(d.x) + "," + y(d.y) + ")"; });
+
+	bar.append("rect")
+    		.attr("x", 1)
+    		.attr("width", x(data[0].dx) - 1)
+    		.attr("height", function(d) { return height - y(d.y); });
+
+	bar.filter(function(d) { return d.y>0; })
+		.append("text")
+    		.attr("dy", ".75em")
+    		.attr("y", 6)
+    		.attr("x", x(data[0].dx) / 2)
+    		.attr("text-anchor", "middle")
+    		.text(function(d) { return formatCount(d.y); });
+
+	svg.append("g")
+    		.attr("class", "x axis")
+    		.attr("transform", "translate(0," + height + ")")
+    		.call(xAxis);
+}
diff --git a/static/javascript/lib/jquery.cookie.js b/static/javascript/lib/jquery.cookie.js
new file mode 100644
index 0000000..c7f3a59
--- /dev/null
+++ b/static/javascript/lib/jquery.cookie.js
@@ -0,0 +1,117 @@
+/*!
+ * jQuery Cookie Plugin v1.4.1
+ * https://github.com/carhartl/jquery-cookie
+ *
+ * Copyright 2013 Klaus Hartl
+ * Released under the MIT license
+ */
+(function (factory) {
+	if (typeof define === 'function' && define.amd) {
+		// AMD
+		define(['jquery'], factory);
+	} else if (typeof exports === 'object') {
+		// CommonJS
+		factory(require('jquery'));
+	} else {
+		// Browser globals
+		factory(jQuery);
+	}
+}(function ($) {
+
+	var pluses = /\+/g;
+
+	function encode(s) {
+		return config.raw ? s : encodeURIComponent(s);
+	}
+
+	function decode(s) {
+		return config.raw ? s : decodeURIComponent(s);
+	}
+
+	function stringifyCookieValue(value) {
+		return encode(config.json ? JSON.stringify(value) : String(value));
+	}
+
+	function parseCookieValue(s) {
+		if (s.indexOf('"') === 0) {
+			// This is a quoted cookie as according to RFC2068, unescape...
+			s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
+		}
+
+		try {
+			// Replace server-side written pluses with spaces.
+			// If we can't decode the cookie, ignore it, it's unusable.
+			// If we can't parse the cookie, ignore it, it's unusable.
+			s = decodeURIComponent(s.replace(pluses, ' '));
+			return config.json ? JSON.parse(s) : s;
+		} catch(e) {}
+	}
+
+	function read(s, converter) {
+		var value = config.raw ? s : parseCookieValue(s);
+		return $.isFunction(converter) ? converter(value) : value;
+	}
+
+	var config = $.cookie = function (key, value, options) {
+
+		// Write
+
+		if (value !== undefined && !$.isFunction(value)) {
+			options = $.extend({}, config.defaults, options);
+
+			if (typeof options.expires === 'number') {
+				var days = options.expires, t = options.expires = new Date();
+				t.setTime(+t + days * 864e+5);
+			}
+
+			return (document.cookie = [
+				encode(key), '=', stringifyCookieValue(value),
+				options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
+				options.path    ? '; path=' + options.path : '',
+				options.domain  ? '; domain=' + options.domain : '',
+				options.secure  ? '; secure' : ''
+			].join(''));
+		}
+
+		// Read
+
+		var result = key ? undefined : {};
+
+		// To prevent the for loop in the first place assign an empty array
+		// in case there are no cookies at all. Also prevents odd result when
+		// calling $.cookie().
+		var cookies = document.cookie ? document.cookie.split('; ') : [];
+
+		for (var i = 0, l = cookies.length; i < l; i++) {
+			var parts = cookies[i].split('=');
+			var name = decode(parts.shift());
+			var cookie = parts.join('=');
+
+			if (key && key === name) {
+				// If second argument (value) is a function it's a converter...
+				result = read(cookie, value);
+				break;
+			}
+
+			// Prevent storing a cookie that we couldn't decode.
+			if (!key && (cookie = read(cookie)) !== undefined) {
+				result[name] = cookie;
+			}
+		}
+
+		return result;
+	};
+
+	config.defaults = {};
+
+	$.removeCookie = function (key, options) {
+		if ($.cookie(key) === undefined) {
+			return false;
+		}
+
+		// Must not alter options, thus extending a fresh object...
+		$.cookie(key, '', $.extend({}, options, { expires: -1 }));
+		return !$.cookie(key);
+	};
+
+}));
diff --git a/xdata/templates/base.html b/xdata/templates/base.html
index 8e97de2..2bd7b29 100755
--- a/xdata/templates/base.html
+++ b/xdata/templates/base.html
@@ -19,6 +19,7 @@
     <script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.6.0/moment.min.js"></script>
     <!-- // <script src="{% static "bootstrap/js/bootstrap.min.js" %}"></script> -->
     <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
+    <script type="text/javascript" src="{% static 'javascript/lib/jquery.cookie.js' %}"></script>
     <script type="text/javascript" src="{% static 'javascript/lib/d3.min.js' %}"></script>
     <script type="text/javascript" src="{% static 'javascript/base.js' %}"></script>
     <script type="text/javascript" src="{% static 'javascript/userale.js' %}"></script>