Commit cdcecbb3 authored by Tim Brooks's avatar Tim Brooks
Browse files

Working prototype

parents
*.egg-info
dist
log
uploads
renders
MCWebViz - Visualize HEP Monte Carlo Events Online
Copyright (C) 2014 Tim Brooks
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
README.rst
\ No newline at end of file
========
MCWebViz
========
`MCViz`_ as a Service! Written with `python`_-`flask`_.
.. _MCViz: http://mcviz.net
.. _python: http://www.python.org
.. _flask: http://flask.pocoo.org
Setup
=====
Check out from github::
git clone git://gihub.com/brookst/mcviz.web
VirtualEnv
----------
`VirtualEnv`_ makes setting up python package dependencies much easier. To install; see the `Virtual env docs`_. `VirtualEnv`_ is packaged as `python-virtualenv`_ on `Ubuntu`_ systems.
Set up a virtual environment using the following::
mkvirtualenv -a `pwd` -r requirements.txt mcviz.web
workon mcviz.web
To deactivate the `VirtualEnv`_, run ``deactivate``. To work on the environment again; run ``workon mcviz.web`` again.
.. _Virtual env docs: http://virtualenv.readthedocs.org/en/latest/virtualenv.html#installation
.. _python-virtualenv: http://packages.ubuntu.com/utopic/python/python-virtualenv
.. _Ubuntu: http://www.ubuntu.com
Standalone running
------------------
Run the ``mcwebviz.py`` script as::
python mcwebviz.py
Messages will be printed to the console and the application will be available on http://localhost:5000/
Attribution
===========
`MCViz`_ by Johannes Ebke, Peter Waller and Tim Brooks. Licensed under AGPLv3.
#!/usr/bin/env python
"""MCWebViz"""
import os.path
import logging, logging.handlers
from logging.handlers import RotatingFileHandler
from flask import Flask, abort, request, send_from_directory, render_template
from werkzeug import secure_filename
UPLOAD_FOLDER = os.path.dirname('uploads/')
RENDER_FOLDER = os.path.dirname('renders/')
FILE_HANDLER = RotatingFileHandler('log/flask.log')
APP = Flask(__name__)
APP.logger.addHandler(FILE_HANDLER)
APP.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
APP.config['RENDER_FOLDER'] = RENDER_FOLDER
from mcviz.logger import log
for handler in APP.logger.handlers:
log.addHandler(handler)
from mcviz.options import parse_options
from mcviz.tools.tools import tool_classes
from mcviz.graph import EventGraph
from mcviz.workspace import GraphWorkspace
from url_hash import url_hash
def get_resource_path(folder, file_name):
"""Return absolute path to file in a resource folder"""
return os.path.join(os.path.dirname(os.path.abspath(__file__)),
APP.config[folder], file_name)
@APP.route("/")
def main():
"""Site main page"""
APP.logger.info("Hit")
return render_template('main.html', tools=tool_classes)
@APP.route("/render", methods=['GET', 'POST'])
def render():
"""Receive a request to render an event"""
if request.method == 'POST':
APP.logger.info("Rendering")
APP.logger.debug(request.files)
if not request.files:
APP.logger.warning("No file received")
abort(400)
received_file = request.files['file']
if not received_file:
APP.logger.warning("No file")
abort(400)
file_name = secure_filename(received_file.filename)
file_hash = url_hash(received_file.__hash__())
APP.logger.info("received: \"%s\" hash: \"%s\"", file_name, file_hash)
APP.logger.debug(request.form)
for option, value in request.form.iteritems(True):
APP.logger.debug(str(option) + ":" + str(value))
received_file.save(os.path.join(APP.config['UPLOAD_FOLDER'], file_hash))
opt_string = "&".join(["=".join(pair)
for pair in request.form.iteritems(True)])
APP.logger.debug(opt_string)
return render_template('render.html', tools=tool_classes,
file_name=file_hash, opt_string=opt_string)
else:
abort(400)
@APP.route("/render/<name>", methods=['GET', 'POST'])
def rerender(name):
"""Receive a request to re-render an event"""
if request.method == 'POST':
APP.logger.info("Rendering POST")
args = request.form
else:
APP.logger.info("Rendering GET")
args = request.args
opt_string = "&".join(["=".join(pair) for pair in args.iteritems(True)])
APP.logger.debug(opt_string)
return render_template('render.html', tools=tool_classes,
file_name=name, opt_string=opt_string)
@APP.route("/image/<file_name>")
def get_image(file_name):
"""Serve image back to user"""
name, _, _ = file_name.rpartition(".")
APP.logger.info("Rendering image %s", name)
APP.logger.debug(request.args)
arg_list = [e for pair in request.args.iteritems(True) for e in pair]
APP.logger.debug(arg_list)
_, args = parse_options(arg_list)
APP.logger.debug(args)
args.filename = get_resource_path('UPLOAD_FOLDER', name)
args.output_file = get_resource_path('RENDER_FOLDER', file_name)
event_graph = EventGraph.load(args)
workspace = GraphWorkspace(name, event_graph)
workspace.load_tools(args)
workspace.run()
APP.logger.info("Rendering %s done", name)
return send_from_directory("renders/", file_name)
if __name__ == "__main__":
from logging import Formatter
TEMPLATE = "[%(asctime)s|%(levelname)-7s] %(message)s"
APP.debug = True
APP.logger.setLevel(logging.DEBUG)
for handler in APP.logger.handlers:
handler.setLevel(logging.DEBUG)
handler.setFormatter(Formatter(TEMPLATE))
APP.run(host='0')
"""Setuptools config"""
from setuptools import setup, find_packages
from textwrap import dedent
VERSION = "2014.12.22"
setup(name='mcviz.web',
version=VERSION,
description="mcwebviz",
long_description=dedent("""
`MCWebViz` is a visualizer for HEP Monte Carlo events. Users can
upload event files and select view options then the server will
render the event. The browser based interface means no set-up for
users and allows for fast iteration.
""").strip(),
classifiers=['License :: OSI Approved :: GNU Affero General Public'
' License v3',
'Development Status :: 2 - Pre-Alpha',
'Programming Language :: Python',
'Framework :: Flask',
'Topic :: Scientific/Engineering :: Physics',
'Environment :: Web Environment',
'Intended Audience :: Science/Research',
'Intended Audience :: Physicists :: Developers',
'Natural Language :: English',
'Operating System :: POSIX',
],
keywords='mcviz web hep montecarlo hepmc lhe pythia graphviz svg'
' visualization',
author='Tim Brooks',
author_email='dev@mcviz.net',
url='http://mcviz.net',
license='GNU Affero GPLv3',
platforms='any',
packages=find_packages(),
install_requires=['mcviz',
'flask',
'werkzeug',
],
data_files=[('log', []),
('uploads', []),
('renders', []),
('templates', ['templates/base.html',
'templates/main.html',
'templates/render.html',
]),
],
)
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<link rel='stylesheet' href='http://fonts.googleapis.com/css?family=Roboto&subset=latin,greek' type='text/css'>
<style>
body {
font-family: 'Roboto', sans-serif;
color: #202020;
margin: 0;
padding: 0;
background: #DDDDDD;
}
header {
background: #FFFFFF;
padding: 5px;
margin: 5px;
text-align: center;
}
section {
background: #FFFFFF;
padding: 1em;
margin: 5px;
}
footer {
background: #FFFFFF;
padding: 1em;
margin: 5px;
text-align: center;
}
input {
border: 0;
color: #202020;
background: none;
}
h3 {
margin-top: 0;
}
div.options {
display: inline-block;
vertical-align: top;
min-width: 200px;
width: 24.5%;
}
section.render {
text-align: center;
}
img#mcviz {
background-image: url("http://s9.postimg.org/eikge0gu3/spinner_128_anti_alias.gif");
background-size: 64px 64px;
background-repeat: no-repeat;
background-position: center;
min-width: 64px;
min-height: 64px;
}
@media screen and (device-height: 2160px) {
img#mcviz {
max-height: 1924px;
}
}
@media screen and (device-height: 1600px) {
img#mcviz {
max-height: 1364px;
}
}
@media screen and (device-height: 1200px) {
img#mcviz {
max-height: 964px;
}
}
@media screen and (device-height: 1080px) {
img#mcviz {
max-height: 844px;
}
}
@media screen and (device-height: 1024px) {
img#mcviz {
max-height: 788px;
}
}
</style>
{% block title %}<title>MCWebViz</title>{% endblock %}
{% block head %}{% endblock %}
</head>
<body>
<a href="https://github.com/mcviz/"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent.com/38ef81f8aca64bb9a64448d0d70f1308ef5341ab/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6461726b626c75655f3132313632312e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png"></a>
{% block body %}{% endblock %}
</body>
</html>
{% extends "base.html" %}
{% block body %}
<header>
<h1>MCWebViz</h1>
For help on options, please see <a href="https://github.com/mcviz/mcviz/wiki">the MCViz wiki</a>. The MCViz program is available to download from <a href="http://mcviz.net">MCViz.net</a>.
</header>
<section id="controls">
<form id="controller" method="post" action="/render{{ "/" + file_name if file_name }}#render" enctype=multipart/form-data><div>
<div id="layout" class="options">
<h3>Layout</h3>
{% for layout in tools["layout"] %}
<span title="{{ tools["layout"][layout].__doc__ }}">
<input type="radio" name="--layout" value="{{ layout }}"{% if loop.first %} checked{% endif %}>{{ layout }}</input><br>
</span>
{% endfor %}
</div>
<div id="transforms" class="options">
<h3>Transforms</h3>
{% for transform in tools["transform"] %}
<span title="{{ tools["transform"][transform].__doc__ }}">
<input type="checkbox" name="--transform" value="{{transform}}">{{transform}}</input><br>
</span>
{% endfor %}
</div>
<div id="styles" class="options">
<h3>Styles</h3>
{% for style in tools["style"] %}
<span title="{{ tools["style"][style].__doc__ }}">
<input type="checkbox" name="--style" value="{{style}}">{{style}}</input><br>
</span>
{% endfor %}
</div>
<div id="annotations" class="options">
<h3>Annotations</h3>
{% for annotation in tools["annotation"] %}
<span title="{{ tools["annotation"][annotation].__doc__ }}">
<input type="checkbox" name="--annotation" value="{{annotation}}">{{annotation}}</input><br>
</span>
{% endfor %}
</div>
</div>
<div id="buttons">
{% block formextras %}
<input type=file name=file>
<input type="submit" value="Render">
{% endblock %}
</div>
</form>
</section>
{% block content %}{% endblock %}
<footer>
MCViz &copy; 2011 by Johannes Ebke, Peter Waller &amp; Tim Brooks<br>
Licensed under GNU AGPL version 3
</footer>
{% endblock %}
{% extends "main.html" %}
{% block formextras %}
<input type="submit" value="Re-render">
{% endblock %}
{% block content %}
<section id="render" class="render">
<img id="mcviz" src="/image/{{ file_name }}.svg?--painter=svg&{{ opt_string }}"><br>
<a href="/render/{{ file_name }}?{{ opt_string }}">Permalink</a>
<a href="/image/{{ file_name }}.svg?--painter=svg&{{ opt_string }}">Image</a>
<a href="/image/{{ file_name }}.svg?{{ opt_string }}">Navigable image</a>
</section>
{% endblock %}
"""Hash functions"""
from __future__ import print_function
ALPHABET = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', \
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', \
'm', 'n', 'p', 'q', 'r', 't', 'u', 'v', 'w', 'x', 'y', 'z']
def url_hash(value):
"""Turn an integer hash into an alphanumeric string"""
ret = ""
while value:
ret += ALPHABET[value % 32]
value >>= 5
return ret
if __name__ == '__main__':
from random import randint
print(len(ALPHABET))
print([url_hash(randint(0, 8758863600785)) for _ in range(50)])
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment