Commits

Chris Mutel committed 9b00eef

Added dynamic histogram test

Comments (0)

Files changed (10)

 include *.txt
-include bw2ui/*.py
-include bw2ui/web/*/*.*
-include bw2ui/bin/*.py
+recursive-include bw2ui/*.py
+recursive-include bw2ui/web *.css
+recursive-include bw2ui/web *.png

bw2ui/bin/bw2-web.py

 """Brightway2 web user interface.
 
 Usage:
-  bw2-web.py [--port=<port>] [--nobrowser] [--debug|--insecure]
+  bw2-web.py [--port=<port>] [--processes=<processes>] [--nobrowser] [--debug|--insecure]
   bw2-web.py -h | --help
   bw2-web.py --version
 
 
 """
 from bw2ui.web import bw2webapp
+from bw2ui.utils import clean_jobs_directory
 from docopt import docopt
 from werkzeug.serving import run_simple
 import random
 
 
 if __name__ == "__main__":
+    clean_jobs_directory()
+
     args = docopt(__doc__, version='Brightway2 Web UI 0.1')
     port = int(args.get("--port", False) or 5000 + random.randint(0, 999))
     host = "0.0.0.0" if args.get("--insecure", False) else "localhost"
         threading.Timer(1., lambda: webbrowser.open_new_tab(url)).start()
 
     kwargs = {
-        "processes": args.get("--processes", 0) or 3,
+        "processes": args.get("<processes>", 0) or 3,
         "use_debugger": args["--debug"]
     }
 
-    run_simple(host, port, bw2webapp, **kwargs)
+    run_simple(host, port, bw2webapp, use_evalex=True, **kwargs)
 
 def terminal_format(data):
     pprint(data)
+
+
+def clean_jobs_directory():
+    # TODO
+    pass
     return render_template("progress.html", **{"job": job_id, 'status': status_id})
 
 
+@app.route('/hist')
+def hist_test():
+    job_id = get_job_id()
+    status_id = get_job_id()
+    set_job_status(job_id, {"name": "hist-test", "status": status_id})
+    set_job_status(status_id, {"status": "Starting..."})
+    return render_template("hist.html", **{"job": job_id, 'status': status_id})
+
+
 @app.route('/start', methods=["GET", "POST"])
 def start_bw():
     """Start Brightway"""

bw2ui/web/jobs.py

+from __future__ import division
 from utils import get_job, set_job_status
+import numpy as np
 import time
 
 example_text = """There's little can be said in 't; 'tis against the
     def __call__(self, job, **kwargs):
         if kwargs.get("name", None) == "progress-test":
             return progress_test(job, **kwargs)
+        if kwargs.get("name", None) == "hist-test":
+            return hist_data(job, **kwargs)
         else:
             raise InvalidJob
 
         set_job_status(kwargs["status"], {"status": x})
     set_job_status(kwargs["status"], {"status": "Finished", "finished": True})
     return "done"
+
+
+def hist_data(job, **kwargs):
+    data = np.random.normal(size=100)
+    while data.shape[0] < 1e5:
+        data = np.hstack((data, np.random.normal(size=100)))
+        # data.sort()
+        # data = data[5:-5]
+        nbins = min(max(int(data.shape[0] ** 0.5), 10), 50)
+        hist, bins = np.histogram(data, bins=nbins)
+        xs = ((bins[:-1] + bins[1:]) / 2).tolist()
+        ys = hist.tolist()
+        set_job_status(kwargs["status"], {"data": [{"x": x, "y": y} for x, y \
+            in zip(xs, ys)], "status": "working"})
+        time.sleep(0.1)
+    set_job_status(kwargs["status"], {"status": "finished",
+        "data": [{"x": x, "y": y} for x, y in zip(xs, ys)]})
+    return "done"

bw2ui/web/static/blueprint/plugins/buttons/screen.css

+/* -------------------------------------------------------------- 
+  
+   buttons.css
+   * Gives you some great CSS-only buttons.
+   
+   Created by Kevin Hale [particletree.com]
+   * particletree.com/features/rediscovering-the-button-element
+
+   See Readme.txt in this folder for instructions.
+
+-------------------------------------------------------------- */
+
+a.button, button {
+  display:block;
+  float:left;
+  margin: 0.7em 0.5em 0.7em 0;
+  padding:5px 10px 5px 7px;   /* Links */
+  
+  border:1px solid #dedede;
+  border-top:1px solid #eee;
+  border-left:1px solid #eee;
+
+  background-color:#f5f5f5;
+  font-family:"Lucida Grande", Tahoma, Arial, Verdana, sans-serif;
+  font-size:100%;
+  line-height:130%;
+  text-decoration:none;
+  font-weight:bold;
+  color:#565656;
+  cursor:pointer;
+}
+button {
+  width:auto;
+  overflow:visible;
+  padding:4px 10px 3px 7px;   /* IE6 */
+}
+button[type] {
+  padding:4px 10px 4px 7px;   /* Firefox */
+  line-height:17px;           /* Safari */
+}
+*:first-child+html button[type] {
+  padding:4px 10px 3px 7px;   /* IE7 */
+}
+button img, a.button img{
+  margin:0 3px -3px 0 !important;
+  padding:0;
+  border:none;
+  width:16px;
+  height:16px;
+  float:none;
+}
+
+
+/* Button colors
+-------------------------------------------------------------- */
+
+/* Standard */
+button:hover, a.button:hover{
+  background-color:#dff4ff;
+  border:1px solid #c2e1ef;
+  color:#336699;
+}
+a.button:active{
+  background-color:#6299c5;
+  border:1px solid #6299c5;
+  color:#fff;
+}
+
+/* Positive */
+body .positive {
+  color:#529214;
+}
+a.positive:hover, button.positive:hover {
+  background-color:#E6EFC2;
+  border:1px solid #C6D880;
+  color:#529214;
+}
+a.positive:active {
+  background-color:#529214;
+  border:1px solid #529214;
+  color:#fff;
+}
+
+/* Negative */
+body .negative {
+  color:#d12f19;
+}
+a.negative:hover, button.negative:hover {
+  background-color:#fbe3e4;
+  border:1px solid #fbc2c4;
+  color:#d12f19;
+}
+a.negative:active {
+  background-color:#d12f19;
+  border:1px solid #d12f19;
+  color:#fff;
+}

bw2ui/web/templates/base.html

 	<meta name="description" content="The web user interface for the Brightway2 LCA engine">
 	<meta name="viewport" content="width=device-width">
 	<link rel="stylesheet" href="{{ url_for('static', filename="blueprint/screen.css") }}" type="text/css" media="screen, projection">
+	<link rel="stylesheet" href="{{ url_for('static', filename="blueprint/plugins/buttons/screen.css") }}" type="text/css" media="screen, projection">
 	<link rel="stylesheet" href="{{ url_for('static', filename="blueprint/print.css") }}" type="text/css" media="print">
 	<!--[if lt IE 8]><link rel="stylesheet" href="{{ url_for('static', filename="blueprint/ie.css") }}" type="text/css" media="screen, projection"><![endif]-->
 	<script src="http://yui.yahooapis.com/3.7.3/build/yui/yui-min.js"></script>

bw2ui/web/templates/hist.html

+{% extends "base.html" %}
+
+{% block extrahead %}
+<style type="text/css">
+.hist rect {
+  fill: cornflowerblue;
+}
+
+.y.axis line, .y.axis path {
+  fill: none;
+  stroke: #000;
+  shape-rendering: crispEdges;
+}
+
+svg { 
+  padding-top: 10px;
+  padding-bottom: 10px;
+  padding-left: 80px;
+}
+</style>
+{% endblock %}
+
+
+{% block body %}
+<h1>Testing dynamic histogram</h1>
+<hr>
+<div class="hist" id="hist"></div>
+<script type="text/javascript">
+YUI().use('datasource-io', 'datasource-polling', 'json-parse', function (Y) {
+  var dispatch = new Y.DataSource.IO({source: "/dispatch/{{job}}"});
+  dispatch.sendRequest({
+    request: "",
+    callback: {
+      success: function() {},
+      failure: function() {}
+    }
+  });
+
+  dynamic_histogram = function () {
+    var data = [
+          {x: -2, y: 1},
+          {x: -1, y: 2},
+          {x: -0, y: 4},
+          {x: 1, y: 2},
+          {x: 2, y: 1}
+        ],
+        w = 300,
+        h = 200,
+        barPadding = 1,
+        scale = 10;
+
+    var svg = d3.select("#hist")
+      .append("svg")
+      .attr("width",w)
+      .attr("height",h);
+
+    var y = d3.scale.linear().range([h,0]),
+      yAxis = d3.svg.axis().scale(y).ticks(8).orient("left"),
+      x = d3.scale.linear().range([0, w]),
+      xmax = d3.max(data, function(d) { return d.x; }),
+      xmin = d3.min(data, function(d) { return d.x; }),
+      ymax = d3.max(data, function(d) { return d.y; });
+
+    y.domain([0, ymax]).nice();
+    x.domain([xmin, xmax]).nice();
+
+    var rect = svg.selectAll("rect")
+      .data(data)
+      .enter().append("rect")
+        // This draws rectangles DOWN
+        .attr("x", function(d) {return x(d.x);})
+        .attr("y", function(d) {return y(d.y);})
+        .attr("width", w / data.length - barPadding)
+        .attr("height", function(d) {return h - y(d.y);});
+                  
+    svg.append("svg:g")
+     .attr("class", "y axis")
+     .attr("transform", "translate(-4,0)")
+     .call(yAxis);        
+               
+    var update_hist_data = function(data) {
+      console.log(data);
+      var xmax = d3.max(data, function(d) { return d.x; }),
+        xmin = d3.min(data, function(d) { return d.x; }),
+        ymax = d3.max(data, function(d) { return d.y; });
+    
+      y.domain([0, ymax]).nice();
+      x.domain([xmin, xmax]).nice();
+      
+      var t = svg.transition().duration(100)
+        .select(".y.axis").call(yAxis);
+
+      // t.select(".x.axis").call(xAxis);
+      
+      var newrect = svg.selectAll("rect")
+        .data(data, function(d,i) {return i;});
+      newrect.enter().append("rect")
+        .attr("x", function(d) {return x(d.x);})
+        .attr("y", 0)
+        .attr("width", w / data.length - barPadding)
+        .attr("height", 0);
+      newrect.transition().duration(100)
+        .attr("x", function(d) {return x(d.x);})
+        .attr("y", function(d) {return y(d.y);})
+        .attr("width", w / data.length - barPadding)
+        .attr("height", function(d) {return h - y(d.y);});
+      newrect.exit()
+        .transition().duration(100)
+        .style("fill-opacity",1e-6)
+        .remove();
+      };
+
+    job_status = new Y.DataSource.IO({source: "/status/{{status}}"});
+    polling = job_status.setInterval(200, {
+      request: "",
+      callback: {
+        success: function (e) {
+          var status_data = Y.JSON.parse(e.response.results[0].response);
+          update_hist_data(status_data.data);
+          if (status_data.status === "finished") {
+            job_status.clearInterval(polling)
+          };
+        },
+        failure: function (e) {
+          console.log("Error");
+          console.log(e);
+        }
+      }
+    });
+  }();
+});
+</script>
+{% endblock %}

bw2ui/web/templates/index.html

     <h2>Impact assessment methods</h2>
     <div id="ia-table"></div>
 </div>
+<a href="/hist">
+    <button>Dynamic hist</button>
+</a>
+<a href="/progress">
+    <button>Dynamic progress update</button>
+</a>
 
 <script type="text/javascript">
 YUI().use('datatable-sort', 'datatable-scroll', function (Y) {
   name='bw2ui',
   version="0.2",
   packages=["bw2ui", "bw2ui.web"],
-  package_data={'bw2ui': ["web/static/*/*.*", "web/templates/*.*", "web/templates/*/*.*"]},
+  package_data={'bw2ui.web': [
+    "static/blueprint/*.css",
+    "static/blueprint/plugins/buttons/*.css",
+    "static/blueprint/plugins/fancy-type/*.css",
+    "templates/*.html",
+    ]},
   author="Chris Mutel",
   author_email="cmutel@gmail.com",
   license=open('LICENSE.txt').read(),