From f1f6eb55d62081e8dc13c59b7c7bf7a385b56abf Mon Sep 17 00:00:00 2001 From: DanHickstein Date: Thu, 16 Jan 2020 17:16:04 -0700 Subject: [PATCH 1/7] Making the GUI example work again --- examples/example_GUI.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/examples/example_GUI.py b/examples/example_GUI.py index 35905981..f4bedeea 100644 --- a/examples/example_GUI.py +++ b/examples/example_GUI.py @@ -9,10 +9,13 @@ if sys.version_info[0] < 3: import Tkinter as tk from tkFileDialog import askopenfilename + import ttk + else: import tkinter as tk from tkinter.filedialog import askopenfilename -import tkinter.ttk as ttk + import tkinter.ttk as ttk + import tkinter.font as tkFont from tkinter.scrolledtext import * #from ScrolledText import * @@ -20,7 +23,7 @@ import matplotlib matplotlib.use('TkAgg') from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg,\ - NavigationToolbar2TkAgg + NavigationToolbar2Tk from matplotlib.backend_bases import MouseEvent from matplotlib.figure import Figure from matplotlib.pyplot import imread, colorbar @@ -60,7 +63,7 @@ def initialize(self): sharey=self.plt[0])) self.plt.append(self.f.add_subplot(self.gs[3])) for i in [0, 2]: - self.plt[i].set_adjustable('box-forced') + self.plt[i].set_adjustable('box') # hide until have data for i in range(4): @@ -276,7 +279,7 @@ def _plot_canvas(self): self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1) - self.toolbar = NavigationToolbar2TkAgg(self.canvas, self.parent) + self.toolbar = NavigationToolbar2Tk(self.canvas, self.parent) self.toolbar.update() self.canvas._tkcanvas.pack(anchor=tk.W, side=tk.TOP, fill=tk.BOTH, expand=1) @@ -300,7 +303,7 @@ def _display(self): #self.a.plot((0, rows), (c2, c2),'r--', lw=0.1) #self.f.colorbar(self.a.get_children()[2], ax=self.f.gca()) self.plt[0].set_title("raw image", fontsize=10) - self.canvas.show() + self.canvas.draw() def _loadimage(self): From f9089001674aacc66b92eb3d3b61ba52829168f1 Mon Sep 17 00:00:00 2001 From: DanHickstein Date: Thu, 16 Jan 2020 20:52:25 -0700 Subject: [PATCH 2/7] Fixes and style changes to example_GUI --- examples/example_GUI.py | 322 ++++++++++++++++++++-------------------- 1 file changed, 160 insertions(+), 162 deletions(-) diff --git a/examples/example_GUI.py b/examples/example_GUI.py index f4bedeea..57ccf558 100644 --- a/examples/example_GUI.py +++ b/examples/example_GUI.py @@ -3,41 +3,39 @@ # Illustrative GUI driving a small subset of PyAbel methods import numpy as np +import matplotlib.pyplot as plt import abel +import tkinter.font as tkFont +import tkinter.scrolledtext + +import matplotlib +from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg,\ + NavigationToolbar2Tk +from matplotlib.figure import Figure +from matplotlib import gridspec + +from scipy.ndimage.interpolation import shift import sys if sys.version_info[0] < 3: import Tkinter as tk from tkFileDialog import askopenfilename import ttk - + else: import tkinter as tk from tkinter.filedialog import askopenfilename import tkinter.ttk as ttk - -import tkinter.font as tkFont -from tkinter.scrolledtext import * -#from ScrolledText import * -import matplotlib matplotlib.use('TkAgg') -from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg,\ - NavigationToolbar2Tk -from matplotlib.backend_bases import MouseEvent -from matplotlib.figure import Figure -from matplotlib.pyplot import imread, colorbar -from matplotlib import gridspec - -from scipy.ndimage.interpolation import shift -Abel_methods = ['basex', 'direct', 'hansenlaw', 'linbasex', 'onion_peeling', +Abel_methods = ['basex', 'direct', 'hansenlaw', 'linbasex', 'onion_peeling', 'onion_bordas', 'two_point', 'three_point'] center_methods = ['center-of-mass', 'convolution', 'gaussian', 'slice'] -class PyAbel: #(tk.Tk): +class PyAbel: # (tk.Tk): def __init__(self, parent): self.parent = parent @@ -60,7 +58,7 @@ def initialize(self): self.plt.append(self.f.add_subplot(self.gs[0])) self.plt.append(self.f.add_subplot(self.gs[1])) self.plt.append(self.f.add_subplot(self.gs[2], sharex=self.plt[0], - sharey=self.plt[0])) + sharey=self.plt[0])) self.plt.append(self.f.add_subplot(self.gs[3])) for i in [0, 2]: self.plt[i].set_adjustable('box') @@ -69,21 +67,21 @@ def initialize(self): for i in range(4): self.plt[i].axis("off") - # tkinter + # tkinter # set default font size for buttons self.font = tkFont.Font(size=11) self.fontB = tkFont.Font(size=12, weight='bold') - #frames top (buttons), text, matplotlib (canvas) + # frames top (buttons), text, matplotlib (canvas) self.main_container = tk.Frame(self.parent, height=10, width=100) self.main_container.pack(side="top", fill="both", expand=True) self.button_frame = tk.Frame(self.main_container) - #self.info_frame = tk.Frame(self.main_container) + # self.info_frame = tk.Frame(self.main_container) self.matplotlib_frame = tk.Frame(self.main_container) self.button_frame.pack(side="top", fill="x", expand=True) - #self.info_frame.pack(side="top", fill="x", expand=True) + # self.info_frame.pack(side="top", fill="x", expand=True) self.matplotlib_frame.pack(side="top", fill="both", expand=True) self._menus() @@ -113,31 +111,34 @@ def _menus(self): # Process - menu self.processmenu = tk.Menu(self.menubar, tearoff=0) - #self.processmenu.add_command(label="Center image", command=self._center) + # self.processmenu.add_command(label="Center image", + # command=self._center) - self.subcent=tk.Menu(self.processmenu) + self.subcent = tk.Menu(self.processmenu) for cent in center_methods: - self.subcent.add_radiobutton(label=cent, - var=self.center_method, val=center_methods.index(cent), - command=self._center) - self.processmenu.add_cascade(label="Center image", - menu=self.subcent, underline=0) - - self.submenu=tk.Menu(self.processmenu) + self.subcent.add_radiobutton( + label=cent, var=self.center_method, + val=center_methods.index(cent), command=self._center) + self.processmenu.add_cascade( + label="Center image", + menu=self.subcent, underline=0) + + self.submenu = tk.Menu(self.processmenu) for method in Abel_methods: - self.submenu.add_radiobutton(label=method, - var=self.transform_method, val=Abel_methods.index(method), - command=self._transform) - self.processmenu.add_cascade(label="Inverse Abel transform", - menu=self.submenu, underline=0) + self.submenu.add_radiobutton( + label=method, var=self.transform_method, + val=Abel_methods.index(method), command=self._transform) + self.processmenu.add_cascade( + label="Inverse Abel transform", + menu=self.submenu, underline=0) self.processmenu.add_command(label="Speed distribution", command=self._speed) self.processmenu.add_command(label="Angular distribution", command=self._anisotropy) - self.angmenu=tk.Menu(self.processmenu) + self.angmenu = tk.Menu(self.processmenu) self.menubar.add_cascade(label="Processing", menu=self.processmenu) - + # view - menu self.viewmenu = tk.Menu(self.menubar, tearoff=0) self.viewmenu.add_command(label="Raw image", command=self._display) @@ -147,9 +148,8 @@ def _menus(self): command=self._on_buttons) self.menubar.add_cascade(label="View", menu=self.viewmenu) - def _button_area(self): - # grid layout + # grid layout # make expandable for col in range(5): self.button_frame.columnconfigure(col, weight=1) @@ -161,11 +161,11 @@ def _button_area(self): font=self.fontB, fg="dark blue", command=self._loadimage) self.load.grid(row=0, column=0, sticky=tk.W, padx=(5, 10), pady=(5, 0)) - self.sample_image = ttk.Combobox(master=self.button_frame, - font=self.font, - values=["from file", "from transform", - "sample dribinski", "sample Ominus"], - width=14, height=4) + self.sample_image = ttk.Combobox( + master=self.button_frame, font=self.font, + values=["from file", "from transform", + "sample dribinski", "sample Ominus"], + width=14, height=4) self.sample_image.current(0) self.sample_image.grid(row=1, column=0, padx=(5, 10)) @@ -174,18 +174,17 @@ def _button_area(self): font=self.fontB, fg="dark red", command=self._quit) self.quit.grid(row=3, column=0, sticky=tk.W, padx=(5, 10), pady=(0, 5)) - + # column 1 ----------- # center image self.center = tk.Button(master=self.button_frame, text="center image", - anchor=tk.W, + anchor=tk.W, font=self.fontB, fg="dark blue", command=self._center) self.center.grid(row=0, column=1, padx=(0, 20), pady=(5, 0)) - self.center_method = ttk.Combobox(master=self.button_frame, - font=self.font, - values=center_methods, - width=11, height=4) + self.center_method = ttk.Combobox( + master=self.button_frame, font=self.font, values=center_methods, + width=11, height=4) self.center_method.current(1) self.center_method.grid(row=1, column=1, padx=(0, 20)) @@ -197,28 +196,25 @@ def _button_area(self): command=self._transform) self.recond.grid(row=0, column=2, padx=(0, 10), pady=(5, 0)) - self.transform = ttk.Combobox(master=self.button_frame, - values=Abel_methods, - font=self.font, - width=10, height=len(Abel_methods)) + self.transform = ttk.Combobox( + master=self.button_frame, values=Abel_methods, font=self.font, + width=10, height=len(Abel_methods)) self.transform.current(2) self.transform.grid(row=1, column=2, padx=(0, 20)) - self.direction = ttk.Combobox(master=self.button_frame, - values=["inverse", "forward"], - font=self.font, - width=8, height=2) + self.direction = ttk.Combobox( + master=self.button_frame, values=["inverse", "forward"], + font=self.font, width=8, height=2) self.direction.current(0) self.direction.grid(row=2, column=2, padx=(0, 20)) - # column 3 ----------- # speed button self.speed = tk.Button(master=self.button_frame, text="speed", font=self.fontB, fg="dark blue", command=self._speed) self.speed.grid(row=0, column=5, padx=20, pady=(5, 0)) - + self.speedclr = tk.Button(master=self.button_frame, text="clear plot", font=self.font, command=self._speed_clr) self.speedclr.grid(row=1, column=5, padx=20) @@ -233,7 +229,7 @@ def _button_area(self): self.subframe = tk.Frame(self.button_frame) self.subframe.grid(row=1, column=6) self.rmin = tk.Entry(master=self.subframe, text='rmin', width=3, - font=self.font) + font=self.font) self.rmin.grid(row=0, column=0) self.rmin.delete(0, tk.END) self.rmin.insert(0, self.rmx[0]) @@ -245,7 +241,6 @@ def _button_area(self): self.rmax.delete(0, tk.END) self.rmax.insert(0, self.rmx[1]) - # turn off button interface self.hide_buttons = tk.Button(master=self.button_frame, text="hide buttons", @@ -255,9 +250,9 @@ def _button_area(self): def _text_info_box(self): # text info box --------------------- - self.text = ScrolledText(master=self.button_frame, height=6, - fg="mediumblue", - bd=1, relief=tk.SUNKEN) + self.text = tkinter.scrolledtext.ScrolledText( + master=self.button_frame, height=6, + fg="mediumblue", bd=1, relief=tk.SUNKEN) self.text.insert(tk.END, "Work in progress, some features may" " be incomplete ...\n") self.text.insert(tk.END, "To start: load an image data file using" @@ -271,23 +266,20 @@ def _text_info_box(self): " (:) repeat\n") self.text.grid(row=3, column=1, columnspan=3, padx=5) - def _plot_canvas(self): # matplotlib canvas -------------------------- - self.canvas = FigureCanvasTkAgg(self.f, master=self.matplotlib_frame) - #self.cid = self.canvas.mpl_connect('button_press_event', self._onclick) + self.canvas = FigureCanvasTkAgg(self.f, master=self.matplotlib_frame) self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1) self.toolbar = NavigationToolbar2Tk(self.canvas, self.parent) self.toolbar.update() - self.canvas._tkcanvas.pack(anchor=tk.W, side=tk.TOP, fill=tk.BOTH, expand=1) - + self.canvas._tkcanvas.pack(anchor=tk.W, side=tk.TOP, + fill=tk.BOTH, expand=1) - def _onclick(self,event): + def _onclick(self, event): print('button={:d}, x={:f}, y={:f}, xdata={:f}, ydata={:f}'.format( - event.button, event.x, event.y, event.xdata, event.ydata)) - + event.button, event.x, event.y, event.xdata, event.ydata)) # call back functions ----------------------- def _display(self): @@ -296,16 +288,15 @@ def _display(self): # display image self.plt[0].imshow(self.IM, vmin=0) - #rows, cols = self.IM.shape - #r2 = rows/2 - #c2 = cols/2 - #self.a.plot((r2, r2), (0, cols), 'r--', lw=0.1) - #self.a.plot((0, rows), (c2, c2),'r--', lw=0.1) - #self.f.colorbar(self.a.get_children()[2], ax=self.f.gca()) + # rows, cols = self.IM.shape + # r2 = rows/2 + # c2 = cols/2 + # self.a.plot((r2, r2), (0, cols), 'r--', lw=0.1) + # self.a.plot((0, rows), (c2, c2),'r--', lw=0.1) + # self.f.colorbar(self.a.get_children()[2], ax=self.f.gca()) self.plt[0].set_title("raw image", fontsize=10) self.canvas.draw() - def _loadimage(self): if self.fn is not None: @@ -318,7 +309,7 @@ def _loadimage(self): # update what is occurring text box self.text.insert(tk.END, "\nloading image file {:s}".format(self.fn)) self.text.see(tk.END) - self.canvas.show() + self.canvas.draw() if self.fn == "from file": self.fn = askopenfilename() @@ -326,30 +317,29 @@ def _loadimage(self): if ".txt" in self.fn: self.IM = np.loadtxt(self.fn) else: - self.IM = imread(self.fn) + self.IM = plt.imread(self.fn) elif self.fn == "from transform": self.IM = self.AIM self.AIM = None - for i in range(1,4): + for i in range(1, 4): self._clr_plt(i) self.plt[i].axis("off") self.direction.current(0) else: self.fn = self.fn.split(' ')[-1] self.IM = abel.tools.analytical.SampleImage(n=1001, - name=self.fn).image - self.direction.current(1) # raw images require 'forward' transform - self.text.insert(tk.END,"\nsample image: (1) Abel transform 'forward', ") - self.text.insert(tk.END," (2) load 'from transform', ") - self.text.insert(tk.END," (3) Abel transform 'inverse', ") - self.text.insert(tk.END," (4) Speed") + name=self.fn).image + self.direction.current(1) # raw images require 'forward' transform + self.text.insert(tk.END, "\nsample image: (1) Abel transform 'forward', ") + self.text.insert(tk.END, " (2) load 'from transform', ") + self.text.insert(tk.END, " (3) Abel transform 'inverse', ") + self.text.insert(tk.END, " (4) Speed") self.text.see(tk.END) - # if even size image, make odd if self.IM.shape[0] % 2 == 0: - self.IM = shift(self.IM, (-0.5, -0.5))[:-1,:-1] - + self.IM = shift(self.IM, (-0.5, -0.5))[:-1, :-1] + self.old_method = None self.AIM = None self.action = "file" @@ -360,72 +350,74 @@ def _loadimage(self): # show the image self._display() - def _center(self): self.action = "center" center_method = self.center_method.get() # update information text box - self.text.insert(tk.END, "\ncentering image using {:s}".\ + self.text.insert(tk.END, "\ncentering image using {:s}". format(center_method)) - self.canvas.show() - + self.canvas.draw() + # center image via chosen method self.IM = abel.tools.center.center_image(self.IM, center=center_method, - odd_size=True) - #self.text.insert(tk.END, "\ncenter offset = {:}".format(self.offset)) + odd_size=True) + # self.text.insert(tk.END, "\ncenter offset = {:}".format(self.offset)) self.text.see(tk.END) - + self._display() - - + def _transform(self): - #self.method = Abel_methods[self.transform_method.get()] + # self.method = Abel_methods[self.transform_method.get()] self.method = self.transform.get() self.fi = self.direction.get() - + if self.method != self.old_method or self.fi != self.old_fi: # Abel transform of whole image - self.text.insert(tk.END,"\n{:s} {:s} Abel transform:".\ + self.text.insert(tk.END, "\n{:s} {:s} Abel transform:". format(self.method, self.fi)) if self.method == "basex": - self.text.insert(tk.END, - "\nbasex: first time calculation of the basis" - " functions may take a while ...") + self.text.insert( + tk.END, + "\nbasex: first time calculation of the basis" + " functions may take a while ...") elif self.method == "direct": - self.text.insert(tk.END, - "\ndirect: calculation is slowed if Cython unavailable ...") - self.canvas.show() - + self.text.insert( + tk.END, + "\ndirect: calculation is slowed if Cython unavailable ...") + self.canvas.draw() + if self.method == 'linbasex': - self.AIM = abel.Transform(self.IM, method=self.method, - direction=self.fi, - transform_options=dict(return_Beta=True)) + self.AIM = abel.Transform( + self.IM, method=self.method, direction=self.fi, + transform_options=dict(return_Beta=True)) else: - self.AIM = abel.Transform(self.IM, method=self.method, - direction=self.fi, - transform_options=dict(basis_dir='bases'), - symmetry_axis=None) + self.AIM = abel.Transform( + self.IM, method=self.method, direction=self.fi, + transform_options=dict(basis_dir='bases'), + symmetry_axis=None) self.rmin.delete(0, tk.END) self.rmin.insert(0, self.rmx[0]) self.rmax.delete(0, tk.END) self.rmax.insert(0, self.rmx[1]) - + if self.old_method != self.method or self.fi != self.old_fi or\ self.action not in ["speed", "anisotropy"]: - self.plt[2].set_title(self.method+" {:s} Abel transform".format(self.fi), - fontsize=10) - self.plt[2].imshow(self.AIM.transform, vmin=0, + self.plt[2].set_title( + self.method+" {:s} Abel transform".format(self.fi), + fontsize=10) + self.plt[2].imshow(self.AIM.transform, vmin=0, vmax=self.AIM.transform.max()/5.0) - #self.f.colorbar(self.c.get_children()[2], ax=self.f.gca()) - #self.text.insert(tk.END, "{:s} inverse Abel transformed image".format(self.method)) + # self.f.colorbar(self.c.get_children()[2], ax=self.f.gca()) + # self.text.insert(tk.END, "{:s} inverse Abel transformed image" + # .format(self.method)) self.text.see(tk.END) self.old_method = self.method self.old_fi = self.fi - self.canvas.show() - + self.canvas.draw() + def _speed(self): self.action = "speed" # inverse Abel transform @@ -433,19 +425,20 @@ def _speed(self): # update text box in case something breaks self.text.insert(tk.END, "\nspeed distribution") self.text.see(tk.END) - self.canvas.show() - + self.canvas.draw() + if self.method == 'linbasex': self.speed_dist = self.AIM.Beta[0] self.radial = self.AIM.radial else: - # speed distribution + # speed distribution self.radial, self.speed_dist = abel.tools.vmi.angular_integration( self.AIM.transform) - + self.plt[1].axis("on") - self.plt[1].plot(self.radial, self.speed_dist/self.speed_dist[10:].max(), - label=self.method) + self.plt[1].plot( + self.radial, self.speed_dist/self.speed_dist[10:].max(), + label=self.method) # make O2- look nice if self.fn.find('O2-ANU1024') > -1: self.plt[1].axis(xmax=500, ymin=-0.05) @@ -458,43 +451,43 @@ def _speed(self): self.plt[1].legend(fontsize=9, loc=0, frameon=False) self.action = None - self.canvas.show() + self.canvas.draw() def _speed_clr(self): self._clr_plt(1) def _clr_plt(self, i): self.f.delaxes(self.plt[i]) - self.plt[i] = self.f.add_subplot(self.gs[i]) - self.canvas.show() - + self.plt[i] = self.f.add_subplot(self.gs[i]) + self.canvas.draw() + def _anisotropy(self): def P2(x): # 2nd order Legendre polynomial return (3*x*x-1)/2 - - + def PAD(theta, beta, amp): return amp*(1 + beta*P2(np.cos(theta))) - + self.action = "anisotropy" self._transform() if self.method == 'linbasex': self.text.insert(tk.END, - "\nanisotropy parameter pixel range 0 to {}: "\ - .format(self.rmx[1])) + "\nanisotropy parameter pixel range 0 to {}: " + .format(self.rmx[1])) else: - # radial range over which to follow the intensity variation with angle + # radial range over which to follow the intensity + # variation with angle self.rmx = (int(self.rmin.get()), int(self.rmax.get())) - self.text.insert(tk.END, - "\nanisotropy parameter pixel range {:} to {:}: "\ - .format(*self.rmx)) - self.canvas.show() - + self.text.insert( + tk.END, "\nanisotropy parameter pixel range {:} to {:}: " + .format(*self.rmx)) + self.canvas.draw() + # inverse Abel transform self._transform() - + if self.method == 'linbasex': self.beta = self.AIM.Beta[1] self.radial = self.AIM.radial @@ -512,37 +505,42 @@ def PAD(theta, beta, amp): else: # intensity vs angle self.beta, self.amp, self.rad, self.intensity, self.theta =\ - abel.tools.vmi.radial_integration(self.AIM.transform,\ - radial_ranges=[self.rmx,]) - - self.text.insert(tk.END," beta = {:g}+-{:g}".format(*self.beta[0])) - + abel.tools.vmi.radial_integration(self.AIM.transform, + radial_ranges=[self.rmx, ]) + + self.text.insert( + tk.END, " beta = {:g}+-{:g}".format(*self.beta[0])) + self._clr_plt(3) self.plt[3].axis("on") - + self.plt[3].plot(self.theta, self.intensity[0], 'r-') - self.plt[3].plot(self.theta, PAD(self.theta, self.beta[0][0], - self.amp[0][0]), 'b-', lw=2) - self.plt[3].annotate("$\\beta({:d},{:d})={:.2g}\pm{:.2g}$". - format(*self.rmx+self.beta[0]), (-3, self.intensity[0].min()/0.8)) + self.plt[3].plot( + self.theta, PAD(self.theta, self.beta[0][0], + self.amp[0][0]), 'b-', lw=2) + # I don't see the following annotation anywhere - DH 2020-01-16: + self.plt[3].annotate( + "$\\beta({:d},{:d})={:.2g}\pm{:.2g}$" + .format(*self.rmx+self.beta[0]), + (-3, self.intensity[0].min()/0.8)) self.plt[3].set_title("anisotropy", fontsize=12) self.plt[3].set_xlabel("angle", fontsize=9) self.plt[3].set_ylabel("intensity") self.action = None - self.canvas.show() + self.canvas.draw() def _hide_buttons(self): self.button_frame.destroy() def _on_buttons(self): self._button_frame() - + def _quit(self): self.parent.quit() # stops mainloop self.parent.destroy() # this is necessary on Windows to prevent - # Fatal Python Error: PyEval_RestoreThread: NULL tstate - + # Fatal Python Error: PyEval_RestoreThread: NULL tstate + if __name__ == "__main__": root = tk.Tk() From 5ca9ee7158298f3689e259572eddbd86dcc51606 Mon Sep 17 00:00:00 2001 From: DanHickstein Date: Thu, 16 Jan 2020 22:33:36 -0700 Subject: [PATCH 3/7] updates simple GUI --- examples/example_simple_GUI.py | 85 +++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 37 deletions(-) diff --git a/examples/example_simple_GUI.py b/examples/example_simple_GUI.py index 7988d209..91ec89d3 100644 --- a/examples/example_simple_GUI.py +++ b/examples/example_simple_GUI.py @@ -10,22 +10,24 @@ from scipy.ndimage.interpolation import shift import sys +import tkinter.ttk as ttk + +import matplotlib +from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg,\ + NavigationToolbar2Tk +from matplotlib.figure import Figure +from matplotlib.pyplot import imread if sys.version_info[0] < 3: import Tkinter as tk from tkFileDialog import askopenfilename else: import tkinter as tk from tkinter.filedialog import askopenfilename -import tkinter.ttk as ttk -import matplotlib matplotlib.use('TkAgg') -from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg,\ - NavigationToolbar2TkAgg -from matplotlib.figure import Figure -from matplotlib.pyplot import imread -Abel_methods = ['basex', 'direct', 'hansenlaw', 'linbasex', 'onion_peeling', + +Abel_methods = ['basex', 'direct', 'hansenlaw', 'linbasex', 'onion_peeling', 'onion_bordas', 'two_point', 'three_point'] center_methods = ['center-of-mass', 'convolution', 'gaussian', 'slice'] @@ -40,19 +42,19 @@ f = Figure(figsize=(5, 4), dpi=100) a = f.add_subplot(111) -# button call back functions +# button call back functions def _display(): global IM, canvas, text # update information text box - text.insert(tk.END,"raw image\n") + text.insert(tk.END, "raw image\n") # display image f.clf() a = f.add_subplot(111) a.imshow(IM, vmin=0) - canvas.show() + canvas.draw() def _getfilename(): @@ -62,7 +64,7 @@ def _getfilename(): # update what is occurring text box text.delete(1.0, tk.END) text.insert(tk.END, "reading image file {:s}\n".format(fn)) - canvas.show() + canvas.draw() # read image file if ".txt" in fn: @@ -72,7 +74,7 @@ def _getfilename(): if IM.shape[0] % 2 == 0: text.insert(tk.END, "make image odd size") - IM = shift(IM, (-0.5, -0.5))[:-1,:-1] + IM = shift(IM, (-0.5, -0.5))[:-1, :-1] # show the image _display() @@ -85,13 +87,15 @@ def _center(): # update information text box text.delete(1.0, tk.END) - text.insert(tk.END, "centering image using abel.tools.center_image(center={})\n".format(center)) - canvas.show() + text.insert( + tk.END, + "centering image using abel.tools.center_image(center={})\n" + .format(center)) + canvas.draw() # center image via horizontal (left, right), and vertical (top, bottom) # intensity slices IM = abel.tools.center.center_image(IM, center=center, odd_size=True) - #text.insert(tk.END, "center offset = {:}\n".format(offset)) _display() @@ -102,12 +106,12 @@ def _transform(): method = transform.get() text.delete(1.0, tk.END) - text.insert(tk.END,"inverse Abel transform: {:s}\n".format(method)) + text.insert(tk.END, "inverse Abel transform: {:s}\n".format(method)) if "basex" in method: text.insert(tk.END," first time calculation of the basis functions may take a while ...\n") if "direct" in method: text.insert(tk.END," calculation is slowed if Cython unavailable ...\n") - canvas.show() + canvas.draw() # inverse Abel transform of whole image if method == 'linbasex': @@ -122,7 +126,7 @@ def _transform(): f.clf() a = f.add_subplot(111) a.imshow(AIM.transform, vmin=0, vmax=AIM.transform.max()/5.0) - canvas.show() + canvas.draw() def _speed(): @@ -133,11 +137,11 @@ def _speed(): # update text box in case something breaks text.insert(tk.END, "speed distribution\n") - canvas.show() + canvas.draw() # speed distribution if transform.get() not in ['linbasex']: - radial, speed = abel.tools.vmi.angular_integration(AIM.transform) + radial, speed = abel.tools.vmi.angular_integration(AIM.transform) else: radial, speed = AIM.radial, AIM.Beta[0] @@ -145,7 +149,8 @@ def _speed(): a = f.add_subplot(111) a.plot(radial, speed/speed[50:].max()) a.axis(xmax=500, ymin=-0.05) - canvas.show() + canvas.draw() + def _anisotropy(): global IM, AIM, canvas, rmin, rmax, transform, text @@ -153,7 +158,6 @@ def _anisotropy(): def P2(x): # 2nd order Legendre polynomial return (3*x*x-1)/2 - def PAD(theta, beta, amp): return amp*(1 + beta*P2(np.cos(theta))) @@ -168,32 +172,35 @@ def PAD(theta, beta, amp): else: rmx = (0, AIM.radial[-1]) - text.delete(1.0, tk.END) - text.insert(tk.END,"anisotropy parameter pixel range {:} to {:}\n".format(*rmx)) - canvas.show() + text.insert(tk.END, + "anisotropy parameter pixel range {:} to {:}\n".format(*rmx)) + canvas.draw() f.clf() a = f.add_subplot(111) if method not in ['linbasex']: # intensity vs angle beta, amp, rad, intensity, theta =\ - abel.tools.vmi.radial_integration(AIM.transform, radial_ranges=[rmx,]) + abel.tools.vmi.radial_integration(AIM.transform, + radial_ranges=[rmx, ]) beta = beta[0] amp = amp[0] - text.insert(tk.END,"beta = {:g}+-{:g}\n".format(beta[0],beta[1])) + text.insert(tk.END, "beta = {:g}+-{:g}\n".format(beta[0], beta[1])) a.plot(theta, intensity[0], 'r-') a.plot(theta, PAD(theta, beta[0], amp[0]), 'b-', lw=2) - a.annotate("$\\beta({:d},{:d})={:.2g}\pm{:.2g}$".format(rmx[0], rmx[1],beta[0], beta[1]), (-np.pi/2,-2)) + a.annotate("$\\beta({:d},{:d})={:.2g}\pm{:.2g}$" + .format(rmx[0], rmx[1], beta[0], beta[1]), (-np.pi/2, -2)) else: beta = AIM.Beta[1] radial = AIM.radial a.plot(radial, beta) a.annotate("anisotropy parameter vs radial coordinate", (-np.pi/2, 2)) - - canvas.show() + + canvas.draw() + def _quit(): root.quit() # stops mainloop @@ -215,13 +222,15 @@ def _quit(): cent.place(anchor=tk.W, relx=0.65, rely=0.05) # display raw input image -tk.Button(master=root, text='raw image', command=_display).pack(anchor=tk.W, padx=0.1) +tk.Button(master=root, text='raw image', command=_display).pack(anchor=tk.W, + padx=0.1) # Abel transform tk.Button(master=root, text='inverse Abel transform', command=_transform)\ .pack(anchor=tk.N) -transform = ttk.Combobox(master=root, values=Abel_methods, state="readonly", width=10, height=len(Abel_methods)) +transform = ttk.Combobox(master=root, values=Abel_methods, state="readonly", + width=10, height=len(Abel_methods)) transform.current(2) transform.place(anchor=tk.W, relx=0.67, rely=0.11) @@ -245,18 +254,20 @@ def _quit(): # a tk.DrawingArea --------------- canvas = FigureCanvasTkAgg(f, master=root) a.annotate("load image file", (0.5, 0.6), horizontalalignment="center") -a.annotate("e.g. data/O2-ANU1024.txt.bz2", (0.5, 0.5), horizontalalignment="center") -canvas.show() +a.annotate("e.g. data/O2-ANU1024.txt.bz2", (0.5, 0.5), + horizontalalignment="center") +canvas.draw() canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1) -toolbar = NavigationToolbar2TkAgg(canvas, root) +toolbar = NavigationToolbar2Tk(canvas, root) toolbar.update() canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1) # text info box text = tk.Text(master=root, height=4, fg="blue") text.pack(fill=tk.X) -text.insert(tk.END, "To start load an image data file using the `Load image file' button\n") - +text.insert( + tk.END, + "To start load an image data file using the `Load image file' button\n") tk.mainloop() From 2dac633133b5e649f29b9f91d6d182bec7200e94 Mon Sep 17 00:00:00 2001 From: DanHickstein Date: Sun, 26 Jan 2020 16:32:15 -0700 Subject: [PATCH 4/7] included "six" import in GUI examples Allows for py2 compatibility --- examples/example_GUI.py | 27 ++++++++++----------------- examples/example_simple_GUI.py | 27 +++++++++++---------------- 2 files changed, 21 insertions(+), 33 deletions(-) diff --git a/examples/example_GUI.py b/examples/example_GUI.py index 57ccf558..fb20d8cb 100644 --- a/examples/example_GUI.py +++ b/examples/example_GUI.py @@ -3,12 +3,11 @@ # Illustrative GUI driving a small subset of PyAbel methods import numpy as np +import matplotlib; matplotlib.use('TkAgg') # avoids crash on OSX import matplotlib.pyplot as plt import abel -import tkinter.font as tkFont -import tkinter.scrolledtext -import matplotlib + from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg,\ NavigationToolbar2Tk from matplotlib.figure import Figure @@ -16,18 +15,12 @@ from scipy.ndimage.interpolation import shift -import sys -if sys.version_info[0] < 3: - import Tkinter as tk - from tkFileDialog import askopenfilename - import ttk - -else: - import tkinter as tk - from tkinter.filedialog import askopenfilename - import tkinter.ttk as ttk +from six.moves import tkinter as tk +from six.moves import tkinter_ttk as ttk +from six.moves import tkinter_font as tkFont +from six.moves import tkinter_scrolledtext as scrolledtext +from six.moves import tkinter_tkfiledialog as filedialog -matplotlib.use('TkAgg') Abel_methods = ['basex', 'direct', 'hansenlaw', 'linbasex', 'onion_peeling', 'onion_bordas', 'two_point', 'three_point'] @@ -250,7 +243,7 @@ def _button_area(self): def _text_info_box(self): # text info box --------------------- - self.text = tkinter.scrolledtext.ScrolledText( + self.text = scrolledtext.ScrolledText( master=self.button_frame, height=6, fg="mediumblue", bd=1, relief=tk.SUNKEN) self.text.insert(tk.END, "Work in progress, some features may" @@ -312,7 +305,7 @@ def _loadimage(self): self.canvas.draw() if self.fn == "from file": - self.fn = askopenfilename() + self.fn = filedialog.askopenfilename() # read image file if ".txt" in self.fn: self.IM = np.loadtxt(self.fn) @@ -520,7 +513,7 @@ def PAD(theta, beta, amp): self.amp[0][0]), 'b-', lw=2) # I don't see the following annotation anywhere - DH 2020-01-16: self.plt[3].annotate( - "$\\beta({:d},{:d})={:.2g}\pm{:.2g}$" + r"$\\beta({:d},{:d})={:.2g}\pm{:.2g}$" .format(*self.rmx+self.beta[0]), (-3, self.intensity[0].min()/0.8)) self.plt[3].set_title("anisotropy", fontsize=12) diff --git a/examples/example_simple_GUI.py b/examples/example_simple_GUI.py index 91ec89d3..f7098574 100644 --- a/examples/example_simple_GUI.py +++ b/examples/example_simple_GUI.py @@ -9,22 +9,16 @@ from scipy.ndimage.interpolation import shift -import sys -import tkinter.ttk as ttk +import matplotlib; matplotlib.use('TkAgg') # avoids crash on OSX -import matplotlib from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg,\ NavigationToolbar2Tk from matplotlib.figure import Figure from matplotlib.pyplot import imread -if sys.version_info[0] < 3: - import Tkinter as tk - from tkFileDialog import askopenfilename -else: - import tkinter as tk - from tkinter.filedialog import askopenfilename -matplotlib.use('TkAgg') +from six.moves import tkinter as tk +from six.moves import tkinter_ttk as ttk +from six.moves import tkinter_tkfiledialog as filedialog Abel_methods = ['basex', 'direct', 'hansenlaw', 'linbasex', 'onion_peeling', @@ -59,7 +53,7 @@ def _display(): def _getfilename(): global IM, text - fn = askopenfilename() + fn = filedialog.askopenfilename() # update what is occurring text box text.delete(1.0, tk.END) @@ -108,9 +102,9 @@ def _transform(): text.delete(1.0, tk.END) text.insert(tk.END, "inverse Abel transform: {:s}\n".format(method)) if "basex" in method: - text.insert(tk.END," first time calculation of the basis functions may take a while ...\n") + text.insert(tk.END, " first time calculation of the basis functions may take a while ...\n") if "direct" in method: - text.insert(tk.END," calculation is slowed if Cython unavailable ...\n") + text.insert(tk.END, " calculation is slowed if Cython unavailable ...\n") canvas.draw() # inverse Abel transform of whole image @@ -191,7 +185,7 @@ def PAD(theta, beta, amp): a.plot(theta, intensity[0], 'r-') a.plot(theta, PAD(theta, beta[0], amp[0]), 'b-', lw=2) - a.annotate("$\\beta({:d},{:d})={:.2g}\pm{:.2g}$" + a.annotate(r"$\\beta({:d},{:d})={:.2g}\pm{:.2g}$" .format(rmx[0], rmx[1], beta[0], beta[1]), (-np.pi/2, -2)) else: beta = AIM.Beta[1] @@ -204,8 +198,9 @@ def PAD(theta, beta, amp): def _quit(): root.quit() # stops mainloop - root.destroy() # this is necessary on Windows to prevent - # Fatal Python Error: PyEval_RestoreThread: NULL tstate + root.destroy() + # this is necessary on Windows to prevent + # Fatal Python Error: PyEval_RestoreThread: NULL tstate # buttons with callbacks ---------------- From 5d09a8295675e2a625becdc923fc66eb6f11a707 Mon Sep 17 00:00:00 2001 From: DanHickstein Date: Mon, 27 Jan 2020 14:26:57 -0700 Subject: [PATCH 5/7] Included GUI example changes in changelog --- CHANGELOG.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 514124a2..31d39073 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -7,6 +7,8 @@ Unreleased v0.8.3 (2019-08-16) ------------------- +* Fixed the GUI examples (example_GUI.py and example_simple_GUI.py) + so that they work with the lastest versions of tk (#269). * New tools.vmi.Distributions class for extracting radial intensity and anisotropy distributions (PR #257). * Dropped PyAbel version from basex cache files (PR #260). From c4fadc4736cc24321becb895cd244f269cd32457 Mon Sep 17 00:00:00 2001 From: DanHickstein Date: Mon, 27 Jan 2020 22:02:04 -0700 Subject: [PATCH 6/7] Update example_simple_GUI.py --- examples/example_simple_GUI.py | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/example_simple_GUI.py b/examples/example_simple_GUI.py index f7098574..3a55f9e1 100644 --- a/examples/example_simple_GUI.py +++ b/examples/example_simple_GUI.py @@ -20,6 +20,7 @@ from six.moves import tkinter_ttk as ttk from six.moves import tkinter_tkfiledialog as filedialog + # this line violates pep8 Abel_methods = ['basex', 'direct', 'hansenlaw', 'linbasex', 'onion_peeling', 'onion_bordas', 'two_point', 'three_point'] From b6acaf73fa36a4a637c113fe85e9fdcbef3bf129 Mon Sep 17 00:00:00 2001 From: DanHickstein Date: Wed, 22 Apr 2020 18:52:08 -0600 Subject: [PATCH 7/7] Create .pep8speaks.yml --- .pep8speaks.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .pep8speaks.yml diff --git a/.pep8speaks.yml b/.pep8speaks.yml new file mode 100644 index 00000000..ed820a90 --- /dev/null +++ b/.pep8speaks.yml @@ -0,0 +1,14 @@ +# File : .pep8speaks.yml + +scanner: + diff_only: True # If False, the entire file touched by the Pull Request is + # scanned for errors. If True, only the diff is scanned. + linter: pycodestyle # Other option is flake8 + +pycodestyle: # Same as scanner.linter value. Other option is flake8 + max-line-length: 90 # Default is 79 in PEP 8 + ignore: # Errors and warnings to ignore + - W504 # line break after binary operator + - E402 # module level import not at top of file + +no_blank_comment: True # If True, no comment is made on PR without any errors. \ No newline at end of file