Commits

Matthew Turk committed 8336232

Moving things around; making the web widgets all classes with class methods for
the creation of object creators. More plugin-y.

Comments (0)

Files changed (3)

bottle/image_widget.html

-<form name="test_form_%(my_id)s">
-<img src="" width=512 height=512 id="pan_image_%(my_id)s" style="float:left;">
-<br/>
-<input type=button onClick="panner_widget_action('%(my_id)s', 'L');" value="left" title="left">
-<input type=button onClick="panner_widget_action('%(my_id)s', 'R');" value="right" title="right">
-<input type=button onClick="panner_widget_action('%(my_id)s', 'U');" value="up" title="up">
-<input type=button onClick="panner_widget_action('%(my_id)s', 'D');" value="down" title="down">
-<br/>
-<input type=button onClick="panner_widget_action('%(my_id)s', 'Z2');" value="Z2" title="Z2">
-<input type=button onClick="panner_widget_action('%(my_id)s', 'Z10');" value="Z10" title="Z10">
-<input type=button onClick="panner_widget_action('%(my_id)s', 'ZO2');" value="ZO2" title="ZO2">
-<input type=button onClick="panner_widget_action('%(my_id)s', 'ZO10');" value="ZO10" title="ZO10">
-<br/>
-<input type=button onClick="panner_widget_action('%(my_id)s', 'REFRESH');" value="REFRESH" title="REFRESH">
-<br clear="all"/>
-</form>

bottle/web_widgets.py

+import abc
+import numpy as na
+import uuid
+
+from yt.utilities.amr_utils import write_png_to_file
+from yt.visualization.image_writer import map_to_colors
+
+class YTWebWidget(object):
+    __metaclass__ = abc.ABCMeta
+
+    def __init__(self, my_id):
+        self.my_id = my_id
+
+    @abc.abstractproperty
+    def _widget_name(self):
+        pass
+
+    @abc.abstractproperty
+    def _widget_source(self):
+        pass
+
+    @abc.abstractmethod
+    def create_object_creator(cls, widgets, local_vars):
+        pass
+
+_image_panner_source = r"""
+<form name="test_form_%(my_id)s">
+<img src="" width=512 height=512 id="pan_image_%(my_id)s" style="float:left;">
+<br/>
+<input type=button onClick="panner_widget_action('%(my_id)s', 'L');" value="left" title="left">
+<input type=button onClick="panner_widget_action('%(my_id)s', 'R');" value="right" title="right">
+<input type=button onClick="panner_widget_action('%(my_id)s', 'U');" value="up" title="up">
+<input type=button onClick="panner_widget_action('%(my_id)s', 'D');" value="down" title="down">
+<br/>
+<input type=button onClick="panner_widget_action('%(my_id)s', 'Z2');" value="Z2" title="Z2">
+<input type=button onClick="panner_widget_action('%(my_id)s', 'Z10');" value="Z10" title="Z10">
+<input type=button onClick="panner_widget_action('%(my_id)s', 'ZO2');" value="ZO2" title="ZO2">
+<input type=button onClick="panner_widget_action('%(my_id)s', 'ZO10');" value="ZO10" title="ZO10">
+<br/>
+<input type=button onClick="panner_widget_action('%(my_id)s', 'REFRESH');" value="REFRESH" title="REFRESH">
+<br clear="all"/>
+</form>
+"""
+
+class PannerWidget(YTWebWidget):
+
+    _widget_name = "image_panner"
+    _widget_source = _image_panner_source
+    # Returns: image_data
+    def __init__(self, my_id, panner):
+        YTWebWidget.__init__(self, my_id)
+        self.panner = panner
+
+    def do_action(self, action):
+        if action == "L":
+            self.panner.pan_rel_x(+0.1)
+        elif action == "R":
+            self.panner.pan_rel_x(-0.1)
+        elif action == "D":
+            self.panner.pan_rel_y(+0.1)
+        elif action == "U":
+            self.panner.pan_rel_y(-0.1)
+        elif action == "Z2":
+            self.panner.zoom(2.0)
+        elif action == "ZO2":
+            self.panner.zoom(0.5)
+        elif action == "Z10":
+            self.panner.zoom(10.0)
+        elif action == "ZO10":
+            self.panner.zoom(0.1)
+        elif action == "REFRESH":
+            self.panner.zoom(1.0)
+        return scale_buffer(self.panner.buffer)
+
+    def scale_buffer(self, buffer):
+        image = na.log10(buffer)
+        mi = na.nanmin(image[~na.isinf(image)])
+        ma = na.nanmax(image[~na.isinf(image)])
+        color_bounds = mi, ma
+        image = (image - color_bounds[0])/(color_bounds[1] - color_bounds[0])
+        to_plot = map_to_colors(image, "algae")
+        to_plot = na.clip(to_plot, 0, 255)
+        tf = tempfile.TemporaryFile()
+        write_png_to_file(to_plot, tf)
+        tf.seek(0)
+        s = tf.read()
+        tf.close()
+        return s
+
+    @classmethod
+    def create_object_creator(cls, widgets, local_vars):
+        def add_panner(panner):
+            unique_id = str(uuid.uuid1())
+            widget = cls(panner, unique_id)
+            widgets[unique_id] = widget
+            s = cls._widget_source % dict(my_id = unique_id)
+            local_vars['new_values'] = s
+            #print "Setting new values:\n\n" + s
+        return add_panner
 
 import tempfile
 import numpy as na
-from yt.utilities.amr_utils import write_png_to_file
-from yt.visualization.image_writer import map_to_colors
 
 import base64
 import uuid
 
-def scale_buffer(buffer):
-    image = na.log10(buffer)
-    mi = na.nanmin(image[~na.isinf(image)])
-    ma = na.nanmax(image[~na.isinf(image)])
-    color_bounds = mi, ma
-    image = (image - color_bounds[0])/(color_bounds[1] - color_bounds[0])
-    to_plot = map_to_colors(image, "algae")
-    to_plot = na.clip(to_plot, 0, 255)
-    tf = tempfile.TemporaryFile()
-    write_png_to_file(to_plot, tf)
-    tf.seek(0)
-    s = tf.read()
-    tf.close()
-    return s
-
-class PannerWidget(object):
-    # Returns: image_data
-    def __init__(self, panner, my_id):
-        self.panner = panner
-        self.my_id = my_id
-
-    def do_action(self, action):
-        if action == "L":
-            self.panner.pan_rel_x(+0.1)
-        elif action == "R":
-            self.panner.pan_rel_x(-0.1)
-        elif action == "D":
-            self.panner.pan_rel_y(+0.1)
-        elif action == "U":
-            self.panner.pan_rel_y(-0.1)
-        elif action == "Z2":
-            self.panner.zoom(2.0)
-        elif action == "ZO2":
-            self.panner.zoom(0.5)
-        elif action == "Z10":
-            self.panner.zoom(10.0)
-        elif action == "ZO10":
-            self.panner.zoom(0.1)
-        elif action == "REFRESH":
-            self.panner.zoom(1.0)
-        return scale_buffer(self.panner.buffer)
-
-def image_adder(local_vars):
-    def add_image(buffer):
-        s = scale_buffer(buffer)
-        local_vars['new_values'] = "<img src='data:image/png;base64,%s'>" % (
-                base64.encodestring(s))
-    return add_image
-
-def panner_widget_maker(widgets, local_vars):
-    def add_panner(panner):
-        unique_id = str(uuid.uuid1())
-        widget = PannerWidget(panner, unique_id)
-        widgets[unique_id] = widget
-        s = open("image_widget.html").read() % dict(my_id = unique_id)
-        local_vars['new_values'] = s
-        #print "Setting new values:\n\n" + s
-    return add_panner
+from web_widgets import YTWebWidget
 
 class HTTPREPL:
     
     def __init__(self, locals=None):
         self.locals = {}
-        self.locals['add_image'] = image_adder(self.locals)
         if locals:
             self.locals.update(locals)
         self.buffer = []
         self._widgets = {}
-        self.locals['add_panner'] = panner_widget_maker(self._widgets, self.locals)
+        for cls in YTWebWidget.__subclasses__():
+            self.locals['add_%s' % cls._widget_name] = cls.create_object_creator(
+                    self._widgets, self.locals)
     
     def push(self, line):
         """Push 'line' and return exec results (None if more input needed)."""
         return
     return repr(result)
 
-@preroute("/doc", method="POST")
+@preroute("/doc")
 def doc():
     """Push 'line' and return result of getargspec on the final expr."""
-    line = request.POST['line']
+    line = request.GET['line']
     result = repl.doc(line)
     if not result:
         response.status = 204
     return result
 
+# This needs to get moved in to the base class we implement
 @preroute("/panner_widgets", method="POST")
 def panner_widgets():
     widget_id = request.POST['widget_id']
     widget_action = request.POST['widget_action']
     widget = repl._widgets.get(widget_id, None)
-    if not isinstance(widget, PannerWidget):
+    if not isinstance(widget, YTWebWidget):
         print widget_id, repl._widgets.keys()
         return ""
     s = base64.encodestring(widget.do_action(widget_action))
     print
     run(host='localhost', port=8080)
 
-# from yt.mods import *; pf = load("/Users/matthewturk/Research/data/RD0005-mine/RedshiftOutput0005");proj = pf.h.proj(0,"Density");from yt.visualization.image_panner.api import VariableMeshPanner; vmp = VariableMeshPanner(proj, (512, 512), "Density"); add_panner(vmp) 
+# from yt.mods import *; pf = load("/Users/matthewturk/Research/data/RD0005-mine/RedshiftOutput0005");proj = pf.h.proj(0,"Density");from yt.visualization.image_panner.api import VariableMeshPanner; vmp = VariableMeshPanner(proj, (512, 512), "Density"); add_image_panner(vmp) 
 # from yt.mods import *; pf = load("/Users/matthewturk/Research/data/RD0005-mine/RedshiftOutput0005");proj = pf.h.proj(0,"Density");from yt.visualization.image_panner.api import VariableMeshPanner; vmp = VariableMeshPanner(proj, (512, 512), "Density", add_image); vmp.zoom(1.0)