Source

fisheye / simple_pan_scan.py

from numpy import arange, sin, pi
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
import matplotlib.colors

import Tkinter as Tk
import tkFileDialog
import sys

from yt.mods import *
from yt.funcs import *

import yt.extensions.image_panner as ip

class SimpleWindow(object):
    image = None
    pf = None
    pan_n_scan = None
    def __init__(self, master, pf = None):
        self.log_field = True
        frame = Tk.Frame(master)
        frame.grid(row=0, column=0)

        self.button = Tk.Button(frame, text="Quit", fg="red", command=frame.quit)
        self.button.grid(row=0, column=0)

        self.button = Tk.Button(frame, text="Open", fg="red", command=self.setup_pf)
        self.button.grid(row=0, column=1)

        self.figure = Figure(figsize=(5,4), dpi=100)
        self.figure.subplots_adjust(hspace=0, wspace=0, bottom=0.0,
                                    top=1.0, left=0.0, right=1.0)
        self.canvas = FigureCanvasTkAgg(self.figure, master=master)
        self.canvas.show()
        self.canvas.get_tk_widget().grid(row=0, column=1)
        self.setup_scale_slider(master)

        self.zoom_10x_button = Tk.Button(frame, text="Zoom2x", command=self.zoom_2x)
        self.zoom_10x_button.grid(row=1, column=0)
        self.zoom_10x_out_button = Tk.Button(frame, text="ZoomOut2x",
                                             command=self.zoom_2x_out)
        self.zoom_10x_out_button.grid(row=1, column=1)

        self.zoom_10x_button = Tk.Button(frame, text="Zoom10x", command=self.zoom_10x)
        self.zoom_10x_button.grid(row=2, column=0)
        self.zoom_10x_out_button = Tk.Button(frame, text="ZoomOut10x",
                                             command=self.zoom_10x_out)
        self.zoom_10x_out_button.grid(row=2, column=1)


        self.full_domain_button = Tk.Button(frame, text="Full Domain",
                                             command=self.full_domain)
        self.full_domain_button.grid(row=3, column=0)

        self.textarea = Tk.Text(frame, width=40)
        self.textarea.grid(row=4, columnspan=2)

        self.setup_pf(pf)

        self.axes = self.figure.add_subplot(111)
        self.norm = matplotlib.colors.LogNorm()
        self.norm.autoscale(self.current_limits)
        self.image = self.axes.imshow(self.pan_n_scan.buffer, interpolation='nearest',
                              origin='lower', norm = self.norm)
        self.axes.set_xticks(())
        self.axes.set_yticks(())
        self.axes.set_ylabel("")
        self.axes.set_xlabel("")
        self.colorbar = self.figure.colorbar(self.image)
        self.figure.canvas.mpl_connect("button_press_event", self.pick_event)
        
        self.canvas.draw()
        self.full_domain()

    def setup_scale_slider(self, master):
        # This should use the controlvar
        self.slider = Tk.Scale(from_ =-3.0, to = 0.0, command = self.set_zoom,
                               orient = Tk.HORIZONTAL, resolution = 0.01,
                               )
        self.slider.set(0.0)
        self.slider.grid(row=1, column=1, sticky = Tk.W + Tk.E + Tk.N + Tk.S)

    def pick_event(self, event):
        if event.inaxes is self.axes and event.key == "c":
            # Now we re-center
            xbounds = self.pan_n_scan.xlim
            ybounds = self.pan_n_scan.ylim
            width = self.pan_n_scan.width
            size = self.pan_n_scan.size
            dx, dy = (width[0] / size[0], width[1] / size[1])
            px, py = event.xdata, event.ydata
            # Our new center ...
            ax = self.pan_n_scan.source.axis
            self.center[x_dict[ax]] = px * dx + xbounds[0]
            self.center[y_dict[ax]] = py * dy + ybounds[0]
            print "Re-centering at %s" % (self.center)
            self.recenter()

    def recenter(self):
        self.pan_n_scan.set_center(self.center)
        self._update_from_pns()

    @property
    def current_limits(self):
        buf = self.pan_n_scan.buffer
        if self.log_field:
            mi = buf[buf > 0.0].min()
            ma = buf[buf > 0.0].max()
        else:
            mi, ma = buf.min(), buf.max()
        return mi, ma

    def setup_pf(self, pf = None):
        if pf is None:
            pf = tkFileDialog.askopenfilename(filetypes = [('enzo files', '.hierarchy'), ('all files', '.*')])
        if isinstance(pf, types.StringTypes):
            if pf.endswith(".hierarchy"): pf = pf[:-10]
            pf = load(pf)
            if pf is None: raise RuntimeError
        self.pf = pf
        v, c = pf.h.find_max("Density")
        self.center = c
        sl = pf.h.slice(0, c[0], "Density", center=c)
        self.pan_n_scan = pf.h.image_panner(sl, (512,512), "Density")
        self.pan_n_scan.set_center(c)
        self.slider["from_"] = na.log10(self.pf.h.get_smallest_dx()*128)
        if self.image is not None:
            self._update_from_pns()

    def full_domain(self):
        DLE, DRE = self.pf["DomainLeftEdge"], self.pf["DomainRightEdge"]
        ax = self.pan_n_scan.source.axis
        xlim = DLE[x_dict[ax]], DRE[x_dict[ax]]
        ylim = DLE[y_dict[ax]], DRE[y_dict[ax]]
        self.pan_n_scan.set_limits(xlim, ylim)
        self.pan_n_scan.set_center(self.center)
        self._update_from_pns()

    def set_zoom(self, val):
        if self.pan_n_scan is None: return
        self.pan_n_scan.set_width(10**float(val))
        self._update_from_pns()

    def zoom_2x(self):
        self.pan_n_scan.zoom(2)
        self._update_from_pns()

    def zoom_2x_out(self):
        self.pan_n_scan.zoom(0.5)
        self._update_from_pns()

    def zoom_10x(self):
        self.pan_n_scan.zoom(10)
        self._update_from_pns()

    def zoom_10x_out(self):
        self.pan_n_scan.zoom(.1)
        self._update_from_pns()

    def _update_from_pns(self):
        buf = self.pan_n_scan.buffer
        self.image.set_data(buf)
        self.update_textarea(self.pan_n_scan.width, buf)
        self.slider.set(na.log10(self.pan_n_scan.width[0]))
        mi, ma = self.current_limits
        print "Autoscaling:", mi, ma
        self.norm.autoscale((mi, ma))
        self.image.set_norm(self.norm)
        self.colorbar.update_bruteforce(self.image)
        self.canvas.draw()

    def update_textarea(self, width, buf):
        self.textarea.delete(1.0, Tk.END)
        self.textarea.insert(Tk.END, "Width set to %0.3e by %0.3e\n" % (width))
        self.textarea.insert(Tk.END, "Limits:      %0.3e to %0.3e\n" % (buf.min(), buf.max()))
        
root = Tk.Tk()
root.wm_title("Fisheye")
app = SimpleWindow(root)
Tk.mainloop()

"""
def key(event):
    if event.char == event.keysym:
        msg = 'Normal Key %r' % event.char
    elif len(event.char) == 1:
        msg = 'Punctuation Key %r (%r)' % (event.keysym, event.char)
    else:
        msg = 'Special Key %r' % event.keysym
    label1.config(text=msg)

root.bind_all('<Key>', key)
# from http://www.daniweb.com/code/snippet216830.html
"""
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.