Commits

Chris Mutel committed a8fd82a

Initial commit

Comments (0)

Files changed (24)

+syntax:glob
+dist
+bw2webreports/static/*
+*.pyc
+*~
+MANIFEST
+*.sublime*
+*.egg-info
+Copyright (c) 2013, Chris Mutel and ETH Zürich
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without 
+modification, are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this 
+list of conditions and the following disclaimer. Redistributions in binary 
+form must reproduce the above copyright notice, this list of conditions and the 
+following disclaimer in the documentation and/or other materials provided 
+with the distribution.
+Neither the name of ETH Zürich nor the names of its contributors may be used 
+to endorse or promote products derived from this software without specific 
+prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+include *.txt
+include README.rst
+recursive-include bw2webreports *.py
+recursive-include bw2webreports *.css
+recursive-include bw2webreports *.png
+recursive-include bw2webreports *.gif
+recursive-include bw2webreports *.jpg
+recursive-include bw2webreports *.ico
+recursive-include bw2webreports *.js
+recursive-include bw2webreports *.html
+Brightway2-web-reports
+======================
+
+This is a simple web server script that allows Brightway2 report data to be uploaded, and then displayed.

bw2webreports/__init__.py

+from app import app as report_server

bw2webreports/app.py

+# -*- coding: utf-8 -*-
+from __future__ import division
+from flask import Flask, render_template, request, abort
+import json
+import os
+
+app = Flask(__name__)
+
+
+@app.errorhandler(404)
+def page_not_found(e):
+    return render_template('404.html'), 404
+
+
+@app.errorhandler(500)
+def internal_error(e):
+    return render_template('500.html'), 500
+
+
+@app.route("/upload", methods=["POST"])
+def upload():
+    data = request.json
+    if not data or not isinstance(data, dict) or "metadata" not in data \
+            or not data["metadata"].get("uuid", None) \
+            or not data["metadata"].get("type", None) == \
+            u"Brightway2 serialized LCA report":
+        abort(400)
+    filepath = os.path.join(app.config["DATA_DIR"],
+        "%s.json" % data["metadata"]["uuid"])
+    with open(filepath, "w") as f:
+        json.dump(data, f)
+    return "OK"
+
+
+@app.route('/report/<uuid>')
+def report(uuid):
+    try:
+        data = open(os.path.join(app.config["DATA_DIR"], "%s.json" % uuid)).read()
+    except:
+        return render_template('404.html'), 404
+    return render_template("report.html", data=data)
+
+
+@app.route('/status')
+def status():
+    return json.dumps({'reports': len(os.listdir(app.config["DATA_DIR"]))})
+
+# TODO: Prevent large uploads
+# TODO: Prevent overwriting of existing reports

bw2webreports/bin/bw2-report-server.py

+#!/usr/bin/env python
+# encoding: utf-8
+"""Brightway2 web user interface.
+
+Usage:
+  bw2-report-server.py <data_dir> [--port=<port>]
+  bw2-report-server.py -h | --help
+  bw2-report-server.py --version
+
+Options:
+  -h --help     Show this screen.
+  --version     Show version.
+
+"""
+from bw2webreports import report_server
+from docopt import docopt
+from werkzeug.serving import run_simple
+
+
+if __name__ == "__main__":
+    args = docopt(__doc__, version='Brightway2 Reports Server 0.1')
+    port = int(args.get("--port", False) or 8000)
+    report_server.config['DATA_DIR'] = args["<data_dir>"]
+    run_simple("0.0.0.0", port, report_server, use_evalex=True)

bw2webreports/static/blueprint/ie.css

+/* -----------------------------------------------------------------------
+
+
+ Blueprint CSS Framework 1.0.1
+ http://blueprintcss.org
+
+   * Copyright (c) 2007-Present. See LICENSE for more info.
+   * See README for instructions on how to use Blueprint.
+   * For credits and origins, see AUTHORS.
+   * This is a compressed file. See the sources in the 'src' directory.
+
+----------------------------------------------------------------------- */
+
+/* ie.css */
+body {text-align:center;}
+.container {text-align:left;}
+* html .column, * html .span-1, * html .span-2, * html .span-3, * html .span-4, * html .span-5, * html .span-6, * html .span-7, * html .span-8, * html .span-9, * html .span-10, * html .span-11, * html .span-12, * html .span-13, * html .span-14, * html .span-15, * html .span-16, * html .span-17, * html .span-18, * html .span-19, * html .span-20, * html .span-21, * html .span-22, * html .span-23, * html .span-24 {display:inline;overflow-x:hidden;}
+* html legend {margin:0px -8px 16px 0;padding:0;}
+sup {vertical-align:text-top;}
+sub {vertical-align:text-bottom;}
+html>body p code {*white-space:normal;}
+hr {margin:-8px auto 11px;}
+img {-ms-interpolation-mode:bicubic;}
+.clearfix, .container {display:inline-block;}
+* html .clearfix, * html .container {height:1%;}
+fieldset {padding-top:0;}
+legend {margin-top:-0.2em;margin-bottom:1em;margin-left:-0.5em;}
+textarea {overflow:auto;}
+label {vertical-align:middle;position:relative;top:-0.25em;}
+input.text, input.title, textarea {background-color:#fff;border:1px solid #bbb;}
+input.text:focus, input.title:focus {border-color:#666;}
+input.text, input.title, textarea, select {margin:0.5em 0;}
+input.checkbox, input.radio {position:relative;top:.25em;}
+form.inline div, form.inline p {vertical-align:middle;}
+form.inline input.checkbox, form.inline input.radio, form.inline input.button, form.inline button {margin:0.5em 0;}
+button, input.button {position:relative;top:0.25em;}

bw2webreports/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;
+}

bw2webreports/static/blueprint/print.css

+/* -----------------------------------------------------------------------
+
+
+ Blueprint CSS Framework 1.0.1
+ http://blueprintcss.org
+
+   * Copyright (c) 2007-Present. See LICENSE for more info.
+   * See README for instructions on how to use Blueprint.
+   * For credits and origins, see AUTHORS.
+   * This is a compressed file. See the sources in the 'src' directory.
+
+----------------------------------------------------------------------- */
+
+/* print.css */
+body {line-height:1.5;font-family:"Helvetica Neue", Arial, Helvetica, sans-serif;color:#000;background:none;font-size:10pt;}
+.container {background:none;}
+hr {background:#ccc;color:#ccc;width:100%;height:2px;margin:2em 0;padding:0;border:none;}
+hr.space {background:#fff;color:#fff;visibility:hidden;}
+h1, h2, h3, h4, h5, h6 {font-family:"Helvetica Neue", Arial, "Lucida Grande", sans-serif;}
+code {font:.9em "Courier New", Monaco, Courier, monospace;}
+a img {border:none;}
+p img.top {margin-top:0;}
+blockquote {margin:1.5em;padding:1em;font-style:italic;font-size:.9em;}
+.small {font-size:.9em;}
+.large {font-size:1.1em;}
+.quiet {color:#999;}
+.hide {display:none;}
+a:link, a:visited {background:transparent;font-weight:700;text-decoration:underline;}
+a:link:after, a:visited:after {content:" (" attr(href) ")";font-size:90%;}

bw2webreports/static/blueprint/screen.css

+/* -----------------------------------------------------------------------
+
+
+ Blueprint CSS Framework 1.0.1
+ http://blueprintcss.org
+
+   * Copyright (c) 2007-Present. See LICENSE for more info.
+   * See README for instructions on how to use Blueprint.
+   * For credits and origins, see AUTHORS.
+   * This is a compressed file. See the sources in the 'src' directory.
+
+----------------------------------------------------------------------- */
+
+/* reset.css */
+html {margin:0;padding:0;border:0;}
+body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, code, del, dfn, em, img, q, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, dialog, figure, footer, header, hgroup, nav, section {margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline;}
+article, aside, details, figcaption, figure, dialog, footer, header, hgroup, menu, nav, section {display:block;}
+body {line-height:1.5;background:white;}
+table {border-collapse:separate;border-spacing:0;}
+caption, th, td {text-align:left;font-weight:normal;float:none !important;}
+table, th, td {vertical-align:middle;}
+blockquote:before, blockquote:after, q:before, q:after {content:'';}
+blockquote, q {quotes:"" "";}
+a img {border:none;}
+:focus {outline:0;}
+
+/* typography.css */
+html {font-size:100.01%;}
+body {font-size:75%;color:#222;background:#fff;font-family:"Helvetica Neue", Arial, Helvetica, sans-serif;}
+h1, h2, h3, h4, h5, h6 {font-weight:normal;color:#111;}
+h1 {font-size:3em;line-height:1;margin-bottom:0.5em;}
+h2 {font-size:2em;margin-bottom:0.75em;}
+h3 {font-size:1.5em;line-height:1;margin-bottom:1em;}
+h4 {font-size:1.2em;line-height:1.25;margin-bottom:1.25em;}
+h5 {font-size:1em;font-weight:bold;margin-bottom:1.5em;}
+h6 {font-size:1em;font-weight:bold;}
+h1 img, h2 img, h3 img, h4 img, h5 img, h6 img {margin:0;}
+p {margin:0 0 1.5em;}
+.left {float:left !important;}
+p .left {margin:1.5em 1.5em 1.5em 0;padding:0;}
+.right {float:right !important;}
+p .right {margin:1.5em 0 1.5em 1.5em;padding:0;}
+a:focus, a:hover {color:#09f;}
+a {color:#06c;text-decoration:underline;}
+blockquote {margin:1.5em;color:#666;font-style:italic;}
+strong, dfn {font-weight:bold;}
+em, dfn {font-style:italic;}
+sup, sub {line-height:0;}
+abbr, acronym {border-bottom:1px dotted #666;}
+address {margin:0 0 1.5em;font-style:italic;}
+del {color:#666;}
+pre {margin:1.5em 0;white-space:pre;}
+pre, code, tt {font:1em 'andale mono', 'lucida console', monospace;line-height:1.5;}
+li ul, li ol {margin:0;}
+ul, ol {margin:0 1.5em 1.5em 0;padding-left:1.5em;}
+ul {list-style-type:disc;}
+ol {list-style-type:decimal;}
+dl {margin:0 0 1.5em 0;}
+dl dt {font-weight:bold;}
+dd {margin-left:1.5em;}
+table {margin-bottom:1.4em;width:100%;}
+th {font-weight:bold;}
+thead th {background:#c3d9ff;}
+th, td, caption {padding:4px 10px 4px 5px;}
+tbody tr:nth-child(even) td, tbody tr.even td {background:#e5ecf9;}
+tfoot {font-style:italic;}
+caption {background:#eee;}
+.small {font-size:.8em;margin-bottom:1.875em;line-height:1.875em;}
+.large {font-size:1.2em;line-height:2.5em;margin-bottom:1.25em;}
+.hide {display:none;}
+.quiet {color:#666;}
+.loud {color:#000;}
+.highlight {background:#ff0;}
+.added {background:#060;color:#fff;}
+.removed {background:#900;color:#fff;}
+.first {margin-left:0;padding-left:0;}
+.last {margin-right:0;padding-right:0;}
+.top {margin-top:0;padding-top:0;}
+.bottom {margin-bottom:0;padding-bottom:0;}
+
+/* forms.css */
+label {font-weight:bold;}
+fieldset {padding:0 1.4em 1.4em 1.4em;margin:0 0 1.5em 0;border:1px solid #ccc;}
+legend {font-weight:bold;font-size:1.2em;margin-top:-0.2em;margin-bottom:1em;}
+fieldset, #IE8#HACK {padding-top:1.4em;}
+legend, #IE8#HACK {margin-top:0;margin-bottom:0;}
+input[type=text], input[type=password], input[type=url], input[type=email], input.text, input.title, textarea {background-color:#fff;border:1px solid #bbb;color:#000;}
+input[type=text]:focus, input[type=password]:focus, input[type=url]:focus, input[type=email]:focus, input.text:focus, input.title:focus, textarea:focus {border-color:#666;}
+select {background-color:#fff;border-width:1px;border-style:solid;}
+input[type=text], input[type=password], input[type=url], input[type=email], input.text, input.title, textarea, select {margin:0.5em 0;}
+input.text, input.title {width:300px;padding:5px;}
+input.title {font-size:1.5em;}
+textarea {width:390px;height:250px;padding:5px;}
+form.inline {line-height:3;}
+form.inline p {margin-bottom:0;}
+.error, .alert, .notice, .success, .info {padding:0.8em;margin-bottom:1em;border:2px solid #ddd;}
+.error, .alert {background:#fbe3e4;color:#8a1f11;border-color:#fbc2c4;}
+.notice {background:#fff6bf;color:#514721;border-color:#ffd324;}
+.success {background:#e6efc2;color:#264409;border-color:#c6d880;}
+.info {background:#d5edf8;color:#205791;border-color:#92cae4;}
+.error a, .alert a {color:#8a1f11;}
+.notice a {color:#514721;}
+.success a {color:#264409;}
+.info a {color:#205791;}
+
+/* grid.css */
+.container {width:950px;margin:0 auto;}
+.showgrid {background:url(src/grid.png);}
+.column, .span-1, .span-2, .span-3, .span-4, .span-5, .span-6, .span-7, .span-8, .span-9, .span-10, .span-11, .span-12, .span-13, .span-14, .span-15, .span-16, .span-17, .span-18, .span-19, .span-20, .span-21, .span-22, .span-23, .span-24 {float:left;margin-right:10px;}
+.last {margin-right:0;}
+.span-1 {width:30px;}
+.span-2 {width:70px;}
+.span-3 {width:110px;}
+.span-4 {width:150px;}
+.span-5 {width:190px;}
+.span-6 {width:230px;}
+.span-7 {width:270px;}
+.span-8 {width:310px;}
+.span-9 {width:350px;}
+.span-10 {width:390px;}
+.span-11 {width:430px;}
+.span-12 {width:470px;}
+.span-13 {width:510px;}
+.span-14 {width:550px;}
+.span-15 {width:590px;}
+.span-16 {width:630px;}
+.span-17 {width:670px;}
+.span-18 {width:710px;}
+.span-19 {width:750px;}
+.span-20 {width:790px;}
+.span-21 {width:830px;}
+.span-22 {width:870px;}
+.span-23 {width:910px;}
+.span-24 {width:950px;margin-right:0;}
+input.span-1, textarea.span-1, input.span-2, textarea.span-2, input.span-3, textarea.span-3, input.span-4, textarea.span-4, input.span-5, textarea.span-5, input.span-6, textarea.span-6, input.span-7, textarea.span-7, input.span-8, textarea.span-8, input.span-9, textarea.span-9, input.span-10, textarea.span-10, input.span-11, textarea.span-11, input.span-12, textarea.span-12, input.span-13, textarea.span-13, input.span-14, textarea.span-14, input.span-15, textarea.span-15, input.span-16, textarea.span-16, input.span-17, textarea.span-17, input.span-18, textarea.span-18, input.span-19, textarea.span-19, input.span-20, textarea.span-20, input.span-21, textarea.span-21, input.span-22, textarea.span-22, input.span-23, textarea.span-23, input.span-24, textarea.span-24 {border-left-width:1px;border-right-width:1px;padding-left:5px;padding-right:5px;}
+input.span-1, textarea.span-1 {width:18px;}
+input.span-2, textarea.span-2 {width:58px;}
+input.span-3, textarea.span-3 {width:98px;}
+input.span-4, textarea.span-4 {width:138px;}
+input.span-5, textarea.span-5 {width:178px;}
+input.span-6, textarea.span-6 {width:218px;}
+input.span-7, textarea.span-7 {width:258px;}
+input.span-8, textarea.span-8 {width:298px;}
+input.span-9, textarea.span-9 {width:338px;}
+input.span-10, textarea.span-10 {width:378px;}
+input.span-11, textarea.span-11 {width:418px;}
+input.span-12, textarea.span-12 {width:458px;}
+input.span-13, textarea.span-13 {width:498px;}
+input.span-14, textarea.span-14 {width:538px;}
+input.span-15, textarea.span-15 {width:578px;}
+input.span-16, textarea.span-16 {width:618px;}
+input.span-17, textarea.span-17 {width:658px;}
+input.span-18, textarea.span-18 {width:698px;}
+input.span-19, textarea.span-19 {width:738px;}
+input.span-20, textarea.span-20 {width:778px;}
+input.span-21, textarea.span-21 {width:818px;}
+input.span-22, textarea.span-22 {width:858px;}
+input.span-23, textarea.span-23 {width:898px;}
+input.span-24, textarea.span-24 {width:938px;}
+.append-1 {padding-right:40px;}
+.append-2 {padding-right:80px;}
+.append-3 {padding-right:120px;}
+.append-4 {padding-right:160px;}
+.append-5 {padding-right:200px;}
+.append-6 {padding-right:240px;}
+.append-7 {padding-right:280px;}
+.append-8 {padding-right:320px;}
+.append-9 {padding-right:360px;}
+.append-10 {padding-right:400px;}
+.append-11 {padding-right:440px;}
+.append-12 {padding-right:480px;}
+.append-13 {padding-right:520px;}
+.append-14 {padding-right:560px;}
+.append-15 {padding-right:600px;}
+.append-16 {padding-right:640px;}
+.append-17 {padding-right:680px;}
+.append-18 {padding-right:720px;}
+.append-19 {padding-right:760px;}
+.append-20 {padding-right:800px;}
+.append-21 {padding-right:840px;}
+.append-22 {padding-right:880px;}
+.append-23 {padding-right:920px;}
+.prepend-1 {padding-left:40px;}
+.prepend-2 {padding-left:80px;}
+.prepend-3 {padding-left:120px;}
+.prepend-4 {padding-left:160px;}
+.prepend-5 {padding-left:200px;}
+.prepend-6 {padding-left:240px;}
+.prepend-7 {padding-left:280px;}
+.prepend-8 {padding-left:320px;}
+.prepend-9 {padding-left:360px;}
+.prepend-10 {padding-left:400px;}
+.prepend-11 {padding-left:440px;}
+.prepend-12 {padding-left:480px;}
+.prepend-13 {padding-left:520px;}
+.prepend-14 {padding-left:560px;}
+.prepend-15 {padding-left:600px;}
+.prepend-16 {padding-left:640px;}
+.prepend-17 {padding-left:680px;}
+.prepend-18 {padding-left:720px;}
+.prepend-19 {padding-left:760px;}
+.prepend-20 {padding-left:800px;}
+.prepend-21 {padding-left:840px;}
+.prepend-22 {padding-left:880px;}
+.prepend-23 {padding-left:920px;}
+.border {padding-right:4px;margin-right:5px;border-right:1px solid #ddd;}
+.colborder {padding-right:24px;margin-right:25px;border-right:1px solid #ddd;}
+.pull-1 {margin-left:-40px;}
+.pull-2 {margin-left:-80px;}
+.pull-3 {margin-left:-120px;}
+.pull-4 {margin-left:-160px;}
+.pull-5 {margin-left:-200px;}
+.pull-6 {margin-left:-240px;}
+.pull-7 {margin-left:-280px;}
+.pull-8 {margin-left:-320px;}
+.pull-9 {margin-left:-360px;}
+.pull-10 {margin-left:-400px;}
+.pull-11 {margin-left:-440px;}
+.pull-12 {margin-left:-480px;}
+.pull-13 {margin-left:-520px;}
+.pull-14 {margin-left:-560px;}
+.pull-15 {margin-left:-600px;}
+.pull-16 {margin-left:-640px;}
+.pull-17 {margin-left:-680px;}
+.pull-18 {margin-left:-720px;}
+.pull-19 {margin-left:-760px;}
+.pull-20 {margin-left:-800px;}
+.pull-21 {margin-left:-840px;}
+.pull-22 {margin-left:-880px;}
+.pull-23 {margin-left:-920px;}
+.pull-24 {margin-left:-960px;}
+.pull-1, .pull-2, .pull-3, .pull-4, .pull-5, .pull-6, .pull-7, .pull-8, .pull-9, .pull-10, .pull-11, .pull-12, .pull-13, .pull-14, .pull-15, .pull-16, .pull-17, .pull-18, .pull-19, .pull-20, .pull-21, .pull-22, .pull-23, .pull-24 {float:left;position:relative;}
+.push-1 {margin:0 -40px 1.5em 40px;}
+.push-2 {margin:0 -80px 1.5em 80px;}
+.push-3 {margin:0 -120px 1.5em 120px;}
+.push-4 {margin:0 -160px 1.5em 160px;}
+.push-5 {margin:0 -200px 1.5em 200px;}
+.push-6 {margin:0 -240px 1.5em 240px;}
+.push-7 {margin:0 -280px 1.5em 280px;}
+.push-8 {margin:0 -320px 1.5em 320px;}
+.push-9 {margin:0 -360px 1.5em 360px;}
+.push-10 {margin:0 -400px 1.5em 400px;}
+.push-11 {margin:0 -440px 1.5em 440px;}
+.push-12 {margin:0 -480px 1.5em 480px;}
+.push-13 {margin:0 -520px 1.5em 520px;}
+.push-14 {margin:0 -560px 1.5em 560px;}
+.push-15 {margin:0 -600px 1.5em 600px;}
+.push-16 {margin:0 -640px 1.5em 640px;}
+.push-17 {margin:0 -680px 1.5em 680px;}
+.push-18 {margin:0 -720px 1.5em 720px;}
+.push-19 {margin:0 -760px 1.5em 760px;}
+.push-20 {margin:0 -800px 1.5em 800px;}
+.push-21 {margin:0 -840px 1.5em 840px;}
+.push-22 {margin:0 -880px 1.5em 880px;}
+.push-23 {margin:0 -920px 1.5em 920px;}
+.push-24 {margin:0 -960px 1.5em 960px;}
+.push-1, .push-2, .push-3, .push-4, .push-5, .push-6, .push-7, .push-8, .push-9, .push-10, .push-11, .push-12, .push-13, .push-14, .push-15, .push-16, .push-17, .push-18, .push-19, .push-20, .push-21, .push-22, .push-23, .push-24 {float:left;position:relative;}
+div.prepend-top, .prepend-top {margin-top:1.5em;}
+div.append-bottom, .append-bottom {margin-bottom:1.5em;}
+.box {padding:1.5em;margin-bottom:1.5em;background:#e5eCf9;}
+hr {background:#ddd;color:#ddd;clear:both;float:none;width:100%;height:1px;margin:0 0 17px;border:none;}
+hr.space {background:#fff;color:#fff;visibility:hidden;}
+.clearfix:after, .container:after {content:"\0020";display:block;height:0;clear:both;visibility:hidden;overflow:hidden;}
+.clearfix, .container {display:block;}
+.clear {clear:both;}

bw2webreports/static/css/base.css

+body {
+    background-image: url('/static/img/linedpaper.png');
+    background-repeat: repeat;
+}
+
+.container {
+    background: white;
+    padding-left: 10px;
+    padding-right: 10px;
+    border-left: 2px solid dimgray;
+    border-right: 2px solid dimgray;
+    padding-bottom: 10px;
+    border-bottom: 1px solid dimgray;
+}
+
+h1, h2, h3, h4 {
+    font-family: 'Source Sans Pro', sans-serif;
+}
+
+#brightway {
+    color: dimgray;
+    font-weight: normal;
+}
+
+#two {
+    color: cornflowerblue;
+    font-weight: normal;
+}
+
+.hinton-label {
+    overflow: hidden;
+    background: white;
+}
+
+.ihline {
+    stroke: steelblue;
+    stroke-width: 2;
+    fill: none;
+}
+
+.isline {
+    stroke: forestgreen;
+    stroke-width: 2;
+    fill: none;
+}
+
+.indicator {
+    stroke: red;
+    stroke-width: 1;
+    shape-rendering: crispEdges;
+    fill: none;
+}
+
+.grid-line {
+    stroke: darkgray;
+    stroke-width: 1;
+    shape-rendering: crispEdges;
+    fill: none;
+}
+
+.axis path, .axis line {
+    fill: none;
+    stroke: black;
+    stroke-width: 1;
+    shape-rendering: crispEdges;
+}
+
+svg { 
+  padding-top: 10px;
+  padding-bottom: 10px;
+}
+
+table.dataTable tr.row_selected td {
+    background-color: salmon !important;
+}
+
+/*http://stackoverflow.com/questions/8594974/jquery-datatabels-jquery-ui-theme-arrows-wrap-on-th*/
+table thead th span.css_right {
+  float: right;
+}

bw2webreports/static/css/index.css

+p {
+    margin-bottom: 0.5em;
+}
+
+h2 {
+    margin-bottom: 0;
+}
Add a comment to this file

bw2webreports/static/img/favicon.ico

Added
New image
Add a comment to this file

bw2webreports/static/img/linedpaper.png

Added
New image
Add a comment to this file

bw2webreports/static/img/llama.jpg

Added
New image
Add a comment to this file

bw2webreports/static/img/monster.jpg

Added
New image

bw2webreports/static/js/hinton.js

+var hinton_matrix = function (data, total, xlabels, ylabels, id, w, h, padding) {
+  // Transform data for areal display
+  t_data = [];
+  for (var i = data.length - 1; i >= 0; i--) {
+    t_data.push([data[i][0], data[i][1], Math.sqrt(data[i][2])]);
+  }
+  data = t_data;
+
+  var rows = xlabels.length + 1,
+    cols = ylabels.length + 1;
+    delta_x = (w - 2 * padding) / cols,
+    delta_y = (h - 2 * padding) / rows,
+    total = Math.sqrt(total);
+    // max_size = d3.max(data, function (d) { return d[2]; });
+
+  if (xlabels.length < d3.max(data, function (d) { return d[0]; }) + 1) {
+    throw "Not enough xlabels";
+  }
+
+  if (ylabels.length < d3.max(data, function (d) { return d[1]; }) + 1) {
+    throw "Not enough ylabels";
+  }
+
+  var x_lines = [];
+  for (var i = 1; i <= rows; i++) {
+    x_lines.push([[1, i], [cols, i]]);
+  }
+
+  var y_lines = [];
+  for (var i = 1; i <= cols; i++) {
+    y_lines.push([[i, 1], [i, rows]]);
+  }
+
+  var color_scale = d3.scale.linear()
+    .range(["cornflowerblue", "crimson"])
+    .domain([0, total]);
+
+  var x_size_scale = d3.scale.linear()
+    .range([1, delta_x - 1])
+    .domain([0, total]);
+
+  var y_size_scale = d3.scale.linear()
+    .range([1, delta_y - 1])
+    .domain([0, total]);
+
+  var y = d3.scale.linear()
+    .range([padding, h - padding])
+    .domain([0, cols]);
+
+  var x = d3.scale.linear()
+    .range([padding, w - padding])
+    .domain([0, rows]);
+
+  var grid_line = d3.svg.line()
+    .x(function(d) { return x(d[0]); })
+    .y(function(d) { return y(d[1]); });
+
+  var svg = d3.select(id)
+    .append("svg")
+    .attr("width", w)
+    .attr("height", h);
+
+  var rect = svg.selectAll("rect")
+    .data(data)
+    .enter().append("rect")
+      .attr("x", function (d) { return x(d[0] + 1.5) - (x_size_scale(d[2]) * 0.5); })
+      .attr("y", function (d) { return y(d[1] + 1.5) - (y_size_scale(d[2]) * 0.5); })
+        // delta_x / 2 + x(d[1]) - x_size_scale(Math.sqrt(d[2]) / 2); })
+      // .attr("y", function (d) { return delta_y / 2 + y(d[0]) - y_size_scale(Math.sqrt(d[2])) / 2; })
+      .attr("width", function (d) { return x_size_scale(d[2]); })
+      .attr("height", function (d) { return y_size_scale(d[2]); })
+      .attr("fill", function (d) { return color_scale(d[2]); });
+
+  for (var i = ylabels.length - 1; i >= 0; i--) {
+    svg.append("svg:foreignObject")
+      .attr('x', x(i + 1) + 1)
+      .attr('y', 1)
+      .attr("width", delta_x - 2)
+      .attr("height", delta_y - 2)
+      .append("xhtml:body")
+      .html("<div class=\"hinton-label\" title=\"" + ylabels[i] + "\">" + ylabels[i] + "</div>");
+  }
+
+  for (var i = xlabels.length - 1; i >= 0; i--) {
+    svg.append("svg:foreignObject")
+      .attr('x', 1)
+      .attr('y', y(i + 1) + 1)
+      .attr("width", delta_x - 2)
+      .attr("height", delta_y - 2)
+      .append("xhtml:body")
+      .html("<div class=\"hinton-label\" title=\"" + xlabels[i] + "\">" + xlabels[i] + "</div>");
+  }
+
+  svg.selectAll(".x-lines")
+    .data(x_lines)
+    .enter().append("path")
+    .attr("class", "grid-line")
+    .attr("d", grid_line);
+
+  svg.selectAll(".y-lines")
+    .data(y_lines)
+    .enter().append("path")
+    .attr("class", "grid-line")
+    .attr("d", grid_line);
+};

bw2webreports/static/js/stepped-histogram.js

+var stepped_histogram = function (data, xlabel, id, w, h, padding) {
+  var y_max = d3.max(data.histogram, function (d) { return d[1]; }),
+    x_max = d3.max(data.histogram, function (d) { return d[0]; }),
+    x_min = d3.min(data.histogram, function (d) { return d[0]; }),
+    median = data.statistics.median,
+    upper = data.statistics.interval[0],
+    lower = data.statistics.interval[1];
+
+  var y = d3.scale.linear()
+    .range([h - padding, padding])
+    .domain([0, y_max * 1.1])
+    .nice();
+
+  var y_axis = d3.svg.axis()
+    .scale(y)
+    .ticks(4)
+    .orient("left");
+
+  var x = d3.scale.linear()
+    .range([padding, w - padding])
+    .domain([x_min, x_max])
+    .nice();
+
+  var x_axis = d3.svg.axis()
+    .scale(x)
+    .ticks(6)
+    .orient("bottom");
+
+  var svg = d3.select(id)
+    .append("svg")
+    .attr("width",w)
+    .attr("height",h);
+
+  var line = d3.svg.line()
+    .x(function(d) { return x(d[0]); })
+    .y(function(d) { return y(d[1]); })
+    .interpolate("linear");
+
+  var histogram_g = svg.append("svg:g")
+    .append("svg:path")
+    .attr("class", "ihline")
+    .attr("d", line(data.histogram));
+
+  var smooth_g = svg.append("svg:g")
+    .append("svg:path")
+    .attr("class", "isline")
+    .attr("d", line(data.smoothed));
+
+  var indicator_line = d3.svg.line()
+    .x(function(d) { return x(d[0]); })
+    .y(function(d) { return y(d[1]); });
+  
+  svg.append("svg:g")
+    .append("svg:path")
+    .attr("class", "indicator")
+    .attr("d", indicator_line([[median, 0], [median, y_max * 1.05]]));
+
+  svg.append("text")
+    .attr("class", "label")
+    .attr("text-anchor", "middle")
+    .attr("x", x(median))
+    .attr("y", y(y_max * 1.05) - 5)
+    .text("Median");
+
+  svg.append("svg:g")
+      .append("svg:path")
+      .attr("class", "indicator")
+      .attr("d", indicator_line([[lower, 0], [lower, y_max * 0.95]]));
+
+  svg.append("text")
+    .attr("class", "label")
+    .attr("text-anchor", "middle")
+    .attr("x", x(lower))
+    .attr("y", y(y_max * 0.95) - 5 )
+    .text("95% lower");
+
+  svg.append("svg:g")
+      .append("svg:path")
+      .attr("class", "indicator")
+      .attr("d", indicator_line([[upper, 0], [upper, y_max * 0.95]]));
+
+  svg.append("text")
+    .attr("class", "x label")
+    .attr("text-anchor", "middle")
+    .attr("x", x(upper))
+    .attr("y", y(y_max * 0.95) - 5 )
+    .text("95% upper");
+
+  svg.append("svg:g")
+    .attr("class", "x axis")
+    .attr("transform", "translate(0," + (h - padding + 2) + ")")
+    .call(x_axis);
+
+  svg.append("svg:g")
+   .attr("class", "y axis")
+   .call(y_axis);
+
+  svg.append("text")
+    .attr("class", "y label")
+    .attr("text-anchor", "end")
+    .attr("transform", "rotate(-90)")
+    .attr("y", padding)
+    .attr("x", padding)
+    .attr("dy", ".5em")
+    .text("Count");
+
+  svg.append("text")
+    .attr("class", "x label")
+    .attr("text-anchor", "end")
+    .attr("x", w)
+    .attr("y", h - padding - 5)
+    .text(xlabel);
+}

bw2webreports/templates/404.html

+{% extends "base.html" %}
+
+{% block extrahead %}<style type="text/css">
+body {
+	background-color: #736160;
+	}
+.errortext {
+		margin-top:13em
+}
+</style>{% endblock %}
+
+{% block body %}
+<div class="span-9"><img src="{{ url_for('static', filename="img/llama.jpg") }}"></div>
+<div class="push-1 span-12">
+	<div class="errortext">
+		<h1 style="color: white">404 - Page not found</h1>
+		<h2 style="color: white">We all get lost sometimes...</h2>
+	</div>
+</div>
+{% endblock %}

bw2webreports/templates/500.html

+{% extends "base.html" %}
+
+{% block extrahead %}<style type="text/css">
+body {
+	background-color: #dcd8d5;
+	color: black !important
+	}
+.errortext {
+		margin-top:13em
+}
+</style>{% endblock %}
+
+{% block body %}
+<div class="span-9"><img src="{{ url_for('static', filename="img/monster.jpg") }}"></div>
+<div class="push-1 span-8">
+	<div class="errortext">
+		<h1>500 - Server Error</h1>
+		<h2>Something went wrong!</h2>
+	</div>
+</div>
+{% endblock %}

bw2webreports/templates/base.html

+<!doctype html>
+<head>
+	<meta charset="utf-8">
+	<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+	<title>{% if title %}{{ title }}{% else %}Brightway2 Web UI{% endif %}</title>
+	<link rel="shortcut icon" type="image/ico" href="{{ url_for('static', filename="img/favicon.ico") }}" />
+	<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]-->
+	<link rel="stylesheet" href="{{ url_for('static', filename="css/base.css") }}" type="text/css" media="screen, projection">
+	<link href='http://fonts.googleapis.com/css?family=Source+Sans+Pro' rel='stylesheet' type='text/css'>
+	<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
+	<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.9.4/css/jquery.dataTables.css" type="text/css" media="screen, projection">
+	<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.9.0/themes/flick/jquery-ui.css" type="text/css" media="screen, projection">
+	<script src="http://d3js.org/d3.v2.min.js"></script>
+	{% block extrahead %}{% endblock %}
+</head>
+<body>
+	<div class="container">
+		{% block header %}<h1><span id="brightway">Brightway</span><span id="two">2</span> web</h1><hr>{% endblock %}
+		{% block body %}{% endblock %}
+	</div>
+</body>
+</html>

bw2webreports/templates/report.html

+{% extends "base.html" %}
+
+{% block extrahead %}
+<style type="text/css">
+.cell {
+  border: solid 1px white;
+  font: 10px sans-serif;
+  line-height: 12px;
+  overflow: hidden;
+  position: absolute;
+  text-indent: 2px;
+}
+</style>
+<script src="{{ url_for('static', filename="js/hinton.js") }}"></script>
+<script src="{{ url_for('static', filename="js/stepped-histogram.js") }}"></script>
+{% endblock %}
+
+{% block body %}
+<div class="span-15 colborder">
+	<h2 style="margin-bottom: 0">Functional unit:</h2>
+	<ul style="margin-bottom: 0" id="activity"></ul>
+	<h2 style="margin-bottom: 0">Impact assessment method:</h2>
+	<p class="large" style="margin-bottom: 0; line-height: 1.2em" id="method-name"></p>
+</div>
+<div class="span-8 last">
+	<h2>Total score:</h2>
+	<p class="large"><span style="font-size: 2.5em; color:#000" id="ia-score"></span> <span class="ia-unit"></span></p>
+</div>
+<hr>
+<h1 style="margin-bottom: 0">Monte Carlo results</h1>
+<div class="span-7">
+	<h2 style="margin-bottom: 0">Median</h2>
+	<p class="large"><span style="font-size: 2.5em; color:#000" id="mc-median"></span> <span class="ia-unit"></span></p>
+	<h2 style="margin-bottom: 0">Average</h2>
+	<p class="large"><span style="font-size: 2.5em; color:#000" id="mc-mean"></span> <span class="ia-unit"></span></p>
+	<h2 style="margin-bottom: 0">95% density interval</h2>
+	<p class="large"><span style="font-size: 2.5em; color:#000"> <span id="mc-lower"></span>:<span id="mc-upper"></span></span> <span class="ia-unit"></span></p>
+</div>
+<div class="span-17 last" id="ihist"></div>
+<hr>
+<div class="span-24" id="treemap"></div>
+<hr>
+<div class="span-14" id="hinton"></div>
+<div class="span-10 last">
+	<h2 style="margin-bottom: 0"><a href="http://en.wikipedia.org/wiki/Concentration_ratio">Concentration index</a></h2>
+	<p class="large" style="font-size: 2.5em; color:#000; margin-bottom: 0" id="concentration-ratio"></p>
+	<h2 style="margin-bottom: 0"><a href="http://en.wikipedia.org/wiki/Herfindahl_index">Herfindahl index</a></h2>
+	<p class="large" style="font-size: 2.5em; color:#000; margin-bottom: 0" id="herfindahl"></p>
+</div>
+
+<script type="text/javascript">
+$(document).ready( function() {
+  var report_data = {{ data|safe }},
+    activity = "";
+
+  // Replace DOM elements with correct content
+  $('#herfindahl').html(report_data.contribution.herfindahl.toPrecision(2));
+  $('#concentration-ratio').html(report_data.contribution.concentration.toPrecision(2));
+  $('.ia-unit').html(report_data.method.unit);
+  $('#method-name').html(report_data.method.name);
+  $('#ia-score').html(report_data.score.toPrecision(2));
+  $('#mc-median').html(report_data["monte carlo"].statistics.median.toPrecision(2));
+  $('#mc-mean').html(report_data["monte carlo"].statistics.mean.toPrecision(2));
+  $('#mc-lower').html(report_data["monte carlo"].statistics.interval[0].toPrecision(2));
+  $('#mc-upper').html(report_data["monte carlo"].statistics.interval[1].toPrecision(2));
+  for (var i = report_data.activity.length - 1; i >= 0; i--) {
+    activity = activity + "<li class=&quotlarge&quot style=&quotmargin-bottom: 0; line-height: 1.1em&quot>" + report_data.activity[i][0] + ": " + report_data.activity[i][1] + " " + report_data.activity[i][2] + "</li>"
+  };
+  $('#activity').html(activity);
+
+  // Insert graphics
+  hinton_matrix(report_data.contribution.hinton.results, report_data.contribution.hinton.total, report_data.contribution.hinton.xlabels, report_data.contribution.hinton.ylabels, "#hinton", 560, 560, 10);
+  stepped_histogram(report_data["monte carlo"], report_data.method.unit, "#ihist", 680, 300, 10);
+
+  var width = 950,
+      height = 200,
+      color = d3.scale.category20();
+
+  var treemap = d3.layout.treemap()
+      .size([width, height])
+      .value(function(d) { return d.size; });
+
+  var div = d3.select("#treemap").append("div")
+      .style("position", "relative")
+      .style("width", width + "px")
+      .style("height", height + "px");
+
+  var cell_color_scale = d3.scale.category20();
+
+  div.data([report_data.contribution.treemap]).selectAll("div")
+    .data(treemap.nodes)
+  .enter().append("div")
+    .attr("class", "cell")
+    .attr("title", function(d) { return d.children ? null : d.name; })
+    .style("font-size", "14px")
+    .style("background", function(d, i) { return cell_color_scale(i % 20); }) // d.children ? color(d.name) : null; })
+    .call(cell)
+    .text(function(d) { return d.children ? null : d.name; });
+
+  function cell() {
+    this
+        .style("left", function(d) { return d.x + "px"; })
+        .style("top", function(d) { return d.y + "px"; })
+        .style("width", function(d) { return Math.max(0, d.dx - 1) + "px"; })
+        .style("height", function(d) { return Math.max(0, d.dy - 1) + "px"; });
+  }
+});
+</script>
+{% endblock %}
+from setuptools import setup
+
+setup(
+  name='bw2webreports',
+  version="0.1",
+  packages=["bw2webreports"],
+  package_data={'bw2webreports': [
+    "static/blueprint/*.css",
+    "static/blueprint/plugins/buttons/*.css",
+    "static/blueprint/plugins/fancy-type/*.css",
+    "static/img/*.png",
+    "static/img/*.ico",
+    "static/img/*.jpg",
+    "static/js/*.js",
+    "static/css/*.css",
+    "templates/*.html",
+    ]},
+  author="Chris Mutel",
+  author_email="cmutel@gmail.com",
+  license=open('LICENSE.txt').read(),
+  install_requires=["docopt", "flask"],
+  scripts=["bw2webreports/bin/bw2-report-server.py"],
+  url="https://bitbucket.org/cmutel/brightway2-web-reports",
+  long_description=open('README.rst').read(),
+  classifiers=[
+    'Development Status :: 3 - Alpha',
+    'Intended Audience :: End Users/Desktop',
+    'Intended Audience :: Developers',
+    'Intended Audience :: Science/Research',
+    'License :: OSI Approved :: BSD License',
+    'Operating System :: MacOS :: MacOS X',
+    'Operating System :: Microsoft :: Windows',
+    'Operating System :: POSIX',
+    'Programming Language :: Python',
+    'Programming Language :: Python :: 2.7',
+    'Programming Language :: Python :: 2 :: Only',
+    'Topic :: Scientific/Engineering :: Information Analysis',
+    'Topic :: Scientific/Engineering :: Mathematics',
+    'Topic :: Scientific/Engineering :: Visualization',
+    ],
+)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.