get the zdata with event from a orthoviewer of medical image - python-3.x

I want get the zdata, from navigation toolbar, when I load a .nii file. I want do that with the event def _onclick(event):
import matplotlib
matplotlib.use('TkAgg')
from tkinter import filedialog
from tkinter import *
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from nibabel.loadsave import read_img_data
from nibabel.loadsave import load as load_nii
from viewers import OrthoSlicer3D
from matplotlib.figure import Figure
import numpy as np
import sys
if sys.version_info[0] < 3:
import Tkinter as Tk
else:
import tkinter as Tk
root = Tk.Tk()
root.wm_title("Orthoslicer3D for brain segmentation")
f = Figure()
sagital = f.add_subplot(221)
sagital.set_position([0,0,0.5,0.5])
sagital.set_axis_off()
coronal = f.add_subplot(222)
coronal.set_axis_off()
coronal.set_position([0,0.5,0.5,0.5])
axial = f.add_subplot(223)
axial.set_position([0.5,0.5,0.5,0.5])
axial.set_axis_off()
axes = (sagital, coronal, axial)
# a tk.DrawingArea
canvas = FigureCanvasTkAgg(f, master=root)
canvas.get_tk_widget().pack(side=Tk.RIGHT, fill=Tk.BOTH, expand=1)
toolbar = NavigationToolbar2TkAgg(canvas, root)
toolbar.update()
canvas._tkcanvas.pack(side=Tk.RIGHT, fill=Tk.BOTH, expand=0)
def _load():
data = filedialog.askopenfilename(initialdir = "/", title = "Select file", filetypes = (("nii files","*.nii"),("gz files", "*.gz"),("all files","*.*")))
data_load = load_nii(data)
data_read = read_img_data(data_load)
data_read = np.asanyarray(data_read)
OrthoSlicer3D(data_read, axes=axes).show()
coords = []
def _onclick(event):
coords.append((event.xdata, event.ydata, event.zdata))
return coords
canvas.mpl_connect('button_press_event', _onclick)
buttonLoad = Tk.Button(master=root, text='Load', command=_load)
buttonLoad.pack(side=Tk.LEFT, expand = 1)
Tk.mainloop()
But the traceback is:
Traceback (most recent call last):
File "C:\Users\migue\Documents\IM\TFG\venv\lib\site-packages\matplotlib\cbook\__init__.py", line 388, in process
proxy(*args, **kwargs)
File "C:\Users\migue\Documents\IM\TFG\venv\lib\site-packages\matplotlib\cbook\__init__.py", line 228, in __call__
return mtd(*args, **kwargs)
File "C:/Users/migue/Documents/IM/TFG/pruebsd.py", line 58, in _onclick
coords.append((event.xdata, event.ydata, event.zdata))
AttributeError: 'MouseEvent' object has no attribute 'zdata'

Related

TKinter Widget creation... Issue with arrangement of widgets

I was trying to create some nested widgets within file widget however exit is appearing above open. I tried changing the index but still the problems persists any idea how to fix this?
#!/usr/bin/python3
import tkinter as tk
import tkinter.ttk as ttk
from tkinter import messagebox
import sys
class GuiBaseClass():
def __init__(self,root):
# create widgets
self.root=root
root.title('GUIBASECLASS V0.1')
root.option_add('*tearOff', False)
self.menu=dict()
self.menubar = tk.Menu(root)
#File
menu_file = tk.Menu(self.menubar)
self.menubar.add_cascade(menu=menu_file,label='File',underline=0)
menu_file.add_separator()
menu_file.add_command(label='Exit', command=self.Exit,underline=0)
#Edit
menu_edit = tk.Menu(self.menubar)
self.menubar.add_cascade(menu=menu_edit,label='Edit',underline=0)
#Help
menu_help = tk.Menu(self.menubar)
menu_help.add_command(label='About', command=self.About, underline=0)
self.menubar.add_cascade(menu=menu_help,label ='Help',underline=0)
#config
root.config(menu=self.menubar)
self.menu['menubar'] = self.menubar
self.menu['File'] = menu_file
self.menu['Edit'] = menu_edit
self.menu['Help'] = menu_help
self.frame = ttk.Frame(root)
self.frame.pack(fill='both',expand=True)
# public functions
def mainLoop(self):
self.root.mainloop()
def getFrame(self):
return(self.frame)
def getMenu(self,entry):
if entry in self.menu:
return (self.menu[entry])
else:
# we create a new one
last = self.menu['menubar'].index('end')
self.menu[entry]= tk.Menu(self.menubar)
self.menu['menubar'].insert_cascade(
last, menu=self.menu[entry],label=entry)
return(self.menu[entry])
# private functions
def Exit(self,ask=True):
res = tk.messagebox.askyesno(title='Are you sure',message='Really quit the application')
if res:
sys.exit(0)
pass
def About(self):
print('print GUIBASECLASS V0.1')
if __name__ == '__main__':
root=tk.Tk()
bapp = GuiBaseClass(root)
# example for using the BaseClass in other applications
mnu=bapp.getMenu('Edit')
mnu.add_command(label='Copy',command=lambda: print('Copy'))
# example for using getFrame
frm=bapp.getFrame()
btn=ttk.Button(frm,text="Button X",command=lambda: sys.exit(0))
btn.pack()
bapp.mainLoop()
#!/usr/bin/python3
import tkinter as tk
import tkinter.ttk as ttk
from tkinter import filedialog
from tkinter import messagebox
from GuiBaseClass import GuiBaseClass
import os , sys
class PumlEditor(GuiBaseClass):
def __init__(self, root):
super().__init__(root)
# Create the File menu and add a "Open..." option
mnu_file = self.getMenu('File')
mnu_file.add_command(0, label='Open...', underline=0, command=self.fileOpen)
mnu_file.add_separator()
# Create the main text area
frame = self.getFrame()
#insert tk.Text
self.text = tk.Text(frame, wrap='word', undo=True)
self.text.insert('end', 'Hello start writing, please...')
self.text.delete('1.0','end')
self.text.pack(fill='both', expand=True)
def fileOpen(self, filename=''):
# Open a file dialog to select a file to open
if filename == "":
filename = filedialog.askopenfilename()
if filename != "":
self.text.delete('1.0','end')
file = open(filename,'r')
for line in file:
self.text.insert('end',line)
if __name__ == '__main__':
root = tk.Tk()
root.geometry("300x200")
pedit = PumlEditor(root)
# Create the PumlEditor instance and start the main loop
root.title("PumlEditor 2022")
if len(sys.argv)>1:
if os.path.exits(sys.arg[1]):
pedit.fileOpen(sys.argv[1])
pedit.mainLoop()
Open to appear before exit in files widget

Unable to change background color after displaying csv values into canvas frame

I create canvas Frame with create_window.
I have a "emp.csv" file with three columns [CountryCode, CountryName, Population].
After the CSV data is read and placed into the frame and I am unable to change the background color to "white".
It still remains gray. For that what needs to be modify?
emp.csv
CountryCode,CountryName,Population
500,country1,100000
501,country2,100000
502,country3,100000
code
from tkinter import *
from tkinter import ttk
import tkinter as tk
import tkinter.ttk
import csv
from tkinter import filedialog
class Employee():
def __init__(self):
create_widgets(self)
def myfunction(event):
canvas.configure(scrollregion=canvas.bbox("all"),width=450,height=300)
root=Tk()
sizex = 800
sizey = 600
posx = 100
posy = 100
root.title("My Appication")
root.wm_geometry("%dx%d+%d+%d" % (sizex, sizey, posx, posy))
myframe=Frame(root,relief=GROOVE,width=450,height=400,bd=2,background="white")
myframe.place(x=50,y=100)
canvas=Canvas(myframe)
scrollable_frame=Frame(canvas)
myscrollbar=Scrollbar(myframe,orient="vertical",command=canvas.yview)
canvas.configure(yscrollcommand=myscrollbar.set,bg='white')
myscrollbar.pack(side="right",fill="y")
canvas.pack(side="left")
canvas.create_window((0,0),window=scrollable_frame,anchor='nw' )
scrollable_frame.bind("<Configure>",myfunction)
def create_widgets(self):
self.Button_readcsv= Button(root,text ="Browse CSV ", command = read_csvfile)
self.Button_readcsv.place(x=40, y=40)
def read_csvfile():
filepath=filedialog.askopenfilename(initialdir="/", title="Open file",filetypes=(("CSV Files","*.csv"),))
try:
with open(filepath) as f:
reader = csv.DictReader(f, delimiter=',')
headers = reader.fieldnames
i=0
tk.Label(scrollable_frame, text=headers[0] ).grid(row=i,column=1)
tk.Label(scrollable_frame, text=headers[1]).grid(row=i,column=2)
tk.Label(scrollable_frame, text=headers[2]).grid(row=i,column=3)
for row in reader:
i=i+1
CountryCode = row[headers[0]]
CountryName = row[headers[1]]
Population= row[headers[2]]
tk.Label(scrollable_frame,text=CountryCode).grid(row=i,column=1)
tk.Label(scrollable_frame, text=CountryName).grid(row=i,column=2)
tk.Label(scrollable_frame, text=Population).grid(row=i,column=3)
except(IOError):
print(" Error Reading in CSV File ")
def main():
empobj = Employee()
root.mainloop()
if __name__ == '__main__':
main()

How to display matplotlib numpy.ndarray in tkinter

I want to display numpy.ndarray matplotlib in tkinter.
I tried in backend it works fine, but does not display in tkinter and show the canvas with graph empty.instead the code below display the picture in separate window as pop-up. How can I display it in the canvas and inside the window?
from tkinter import *
from tkinter import ttk
import numpy as np
import pandas as pd
from scipy.stats import norm
import requests
from pandas_datareader import data as wb
import matplotlib.pyplot as plt
%matplotlib inline
from yahoofinancials import YahooFinancials
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib
matplotlib.use('TkAgg')
class Scr:
def __init__(self, master):
master.geometry('300x300+120+60')
self.frame_content = ttk.Frame(master)
self.frame_content.pack()
tickers = ['AAPL']
new_data = pd.DataFrame()
for t in tickers :new_data[t] = wb.DataReader(t, data_source ='yahoo', start = '2004-1-1')['Adj Close']
lr = np.log(1+new_data.pct_change())
var=lr.var()
mean=lr.mean()
drift = mean-(0.5 * var)
stdv=lr.std()
norm.ppf(0.95)
x = np.random.rand(10,2)
norm.ppf(x)
Ze=norm.ppf(np.random.rand(10,2))
t_intervals =1000
iteration=10
daily_returns=np.exp(drift.values + stdv.values * norm.ppf(np.random.rand(t_intervals,iteration)))
S=new_data.iloc[-1]
am = np.zeros_like(daily_returns)
am[0] = S
for t in range (1, t_intervals):
am[t]=am[t-1] * daily_returns[t]
graph3=ttk.Frame(master)
graph3.pack()
graph3.place(x=750,y=550)
plt.plot(am)
fig3 = matplotlib.pyplot.Figure(figsize=(6,6))
canvas3 = FigureCanvasTkAgg(fig3, graph3)
canvas3.get_tk_widget().pack()
ax3 = fig3.add_subplot(211)
am.plot(kind='line', legend=True, ax=ax3).grid(linestyle = 'dashed')
def main():
root = Tk()
scr = Scr(root)
root.mainloop()
if __name__ == "__main__": main()
The error message I got is :
'numpy.ndarray' object has no attribute 'plot'
am is numpy.ndarray
am = np.zeros_like(daily_returns)
and it doesn't have am.plot().
But pandas.DataFrame has it. You have to convert am to DataFrame
df = pd.DataFrame(am)
df.plot(kind='line', legend=True, ax=ax3).grid(linestyle = 'dashed')
(and you can remove plt.plot(am))
And remove graph3.place(x=750,y=550) which moves plot far away and it is invisible. You have to manually resize window to see plot.
from tkinter import *
from tkinter import ttk
import numpy as np
import pandas as pd
from scipy.stats import norm
import requests
from pandas_datareader import data as wb
import matplotlib.pyplot as plt
from yahoofinancials import YahooFinancials
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib
matplotlib.use('TkAgg')
class Scr:
def __init__(self, master):
master.geometry('300x300+120+60')
self.frame_content = ttk.Frame(master)
self.frame_content.pack()
tickers = ['AAPL']
new_data = pd.DataFrame()
for t in tickers:
new_data[t] = wb.DataReader(t, data_source='yahoo', start='2004-1-1')['Adj Close']
lr = np.log(1+new_data.pct_change())
var = lr.var()
mean = lr.mean()
drift = mean-(0.5 * var)
stdv = lr.std()
norm.ppf(0.95)
x = np.random.rand(10,2)
norm.ppf(x)
Ze = norm.ppf(np.random.rand(10,2))
t_intervals =1000
iteration = 10
daily_returns = np.exp(drift.values + stdv.values * norm.ppf(np.random.rand(t_intervals,iteration)))
am = np.zeros_like(daily_returns)
am[0] = new_data.iloc[-1]
for t in range (1, t_intervals):
am[t]=am[t-1] * daily_returns[t]
graph3 = ttk.Frame(master)
graph3.pack()
#graph3.place(x=750,y=550)
fig3 = matplotlib.pyplot.Figure(figsize=(6,6))
canvas3 = FigureCanvasTkAgg(fig3, graph3)
canvas3.get_tk_widget().pack()
ax3 = fig3.add_subplot(211)
df = pd.DataFrame(am)
df.plot(kind='line', legend=True, ax=ax3).grid(linestyle = 'dashed')
def main():
root = Tk()
scr = Scr(root)
root.mainloop()
if __name__ == "__main__":
main()

displaying an image full screen in Python

The following program works the for the first .jpg in the directory.
When called the second time it gets a "_tkinter.TclError: image
"pyimage2" doesn't exist" exception. Why does it get the error? Is
there a way to reuse the first image rather than creating a second?
import sys, os
if sys.version_info[0] == 2:
import Tkinter
tkinter = Tkinter
else:
import tkinter
from PIL import Image, ImageTk
def showPIL(pilImage):
root = tkinter.Tk()
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
root.overrideredirect(1)
root.geometry("%dx%d+0+0" % (w, h))
root.focus_set()
root.bind("<Escape>", lambda e: (e.widget.withdraw(), e.widget.quit()))
canvas = tkinter.Canvas(root,width=w,height=h)
canvas.pack()
canvas.configure(background='black')
imgWidth, imgHeight = pilImage.size
# resize photo to full screen
ratio = min(w/imgWidth, h/imgHeight)
imgWidth = int(imgWidth*ratio)
imgHeight = int(imgHeight*ratio)
pilImage = pilImage.resize((imgWidth,imgHeight), Image.ANTIALIAS)
image = ImageTk.PhotoImage(pilImage)
print(image)
imagesprite = canvas.create_image(w/2,h/2,image=image)
root.mainloop()
names = os.listdir("E://Users//scott//Pictures")
print(names)
for file in names:
print(file)
if file[-4:] == ".jpg":
file=Image.open("E://Users//scott//Pictures//"+file)
showPIL(file)
Here is the console output. Traceback (most recent call last): File
"e:\Users\scott\Documents\Python\image test.py", line 36, in
showPIL(file) File "e:\Users\scott\Documents\Python\image test.py", line 27, in showPIL
imagesprite = canvas.create_image(w/2,h/2,image=image) File "C:\Program Files\Python37\lib\tkinter__init__.py", line 2486, in
create_image
return self._create('image', args, kw) File "C:\Program Files\Python37\lib\tkinter__init__.py", line 2477, in _create
*(args + self._options(cnf, kw))))
_tkinter.TclError: image "pyimage2" doesn't exist
>
after searching around I discovered that the first problem that tkinter.Tk() was being called multiple times whereas it must be called
only once so I moved it out of the showPIL function and into the
initialization. The next problem is that mainloop blocks so I
replaced it with the combination of root.update_idletasks() and
root.update(). The following works as I expect and need:
import sys, os
if sys.version_info[0] == 2: # the tkinter library changed it's name from Python 2 to 3.
import Tkinter
tkinter = Tkinter #I decided to use a library reference to avoid potential naming conflicts with people's programs.
else:
import tkinter
from PIL import Image, ImageTk
import time
root = tkinter.Tk()
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
root.overrideredirect(1)
root.geometry("%dx%d+0+0" % (w, h))
root.focus_set()
canvas = tkinter.Canvas(root,width=w,height=h)
canvas.pack()
canvas.configure(background='black')
def showPIL(pilImage):
imgWidth, imgHeight = pilImage.size
# resize photo to full screen
ratio = min(w/imgWidth, h/imgHeight)
imgWidth = int(imgWidth*ratio)
imgHeight = int(imgHeight*ratio)
pilImage = pilImage.resize((imgWidth,imgHeight), Image.ANTIALIAS)
image = ImageTk.PhotoImage(pilImage)
imagesprite = canvas.create_image(w/2,h/2,image=image)
root.update_idletasks()
root.update()
# root.bind("<Escape>", lambda e: (e.widget.withdraw(), e.widget.quit()))
names = os.listdir("E://Users//scott//Pictures")
print(names)
for file in names:
print(file)
if file[-4:] == ".jpg":
file=Image.open("E://Users//scott//Pictures//"+file)
showPIL(file)
time.sleep(5)

How to display multicursor on a QTabWidget?

The multicursor example
The question is : If I want the plot to be displayed on a tab of the QTabWidget,how to make the MultiCursor works?
# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import matplotlib
matplotlib.use('Qt5Agg')
import matplotlib.pyplot as plt
import numpy as np
import sys
from matplotlib.gridspec import GridSpec
from matplotlib.widgets import MultiCursor
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
class MainWindow(QMainWindow):
def __init__(self):
super().__init__(flags=Qt.Window)
self.setFont(QFont("Microsoft YaHei", 10, QFont.Normal))
self.setMinimumSize(1550, 950)
self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
centralwidget = QWidget(flags=Qt.Widget)
centralwidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self.setCentralWidget(centralwidget)
self.tabview = QTabWidget()
self.tabview.currentChanged.connect(self.onchange)
self.chart_widget0 = QWidget()
self.chart_widget1 = QWidget()
self.dc0 = my_Canvas(self.chart_widget0, width=20, height=8, dpi=100)
self.dc1 = my_Canvas(self.chart_widget1, width=20, height=8, dpi=100)
self.tabview.addTab(self.dc0, "MultiCursor")
self.tabview.addTab(self.dc1, "Cursor")
toplayout = QHBoxLayout()
toplayout.addWidget(self.tabview)
centralwidget.setLayout(toplayout)
def onchange(self,i):
if i == 0:
self.dc0.update_figure()
elif i == 1:
self.dc1.update_figure()
class my_Canvas(FigureCanvas):
def __init__(self, parent=None, width=10, height=7, dpi=100):
self.fig = plt.figure(figsize=(width, height), dpi=dpi)
gs = GridSpec(2, 1, height_ratios=[3, 1])
self.axes1 = plt.subplot(gs[0])
self.axes2 = plt.subplot(gs[1])
self.compute_initial_figure()
FigureCanvas.__init__(self, self.fig)
self.setParent(parent)
def compute_initial_figure(self):
self.axes1.cla()
self.axes2.cla()
def update_figure(self):
t = np.arange(0.0, 2.0, 0.01)
s1 = np.sin(2*np.pi*t)
s2 = np.sin(4*np.pi*t)
self.axes1.plot(t, s1)
self.axes2.plot(t, s2)
multi = MultiCursor(self.fig.canvas, (self.axes1, self.axes2), color='r', lw=1)
self.draw()
if __name__ == '__main__':
app = QApplication(sys.argv)
w1 = MainWindow()
w1.show()
sys.exit(app.exec_())
How to modify the code to make the MultiCursor works, and could I control the display of the cursor by key or mousebutton click?
Further more, how to display the coordinate with the cursor?
As the Multicursor documentation tells us,
For the cursor to remain responsive you must keep a reference to it.
The easiest way is to make it a class variable,
self.multi = MultiCursor(...)

Resources