I've created a 3d plot via matplotlib and am having issues importing it into a tkinter canvas GUI. The screenshots below show the plot as I'd like to see it (in the standalone program) and how it's appearing within my canvas (low resolution, incorrect spacing, scales, etc).
Running the following code at the end of my standalone program gives me 1280x960, DPI 200.
DPI = fig.get_dpi()
bbox = fig.get_window_extent().transformed(fig.dpi_scale_trans.inverted())
width, height = bbox.width*fig.dpi, bbox.height*fig.dpi
In my tkinter canvas, I'm setting the figure (as below), and keeping all other attributes the same.
fig = Figure(figsize=(6.4,4.8), dpi=200)
Standalone:
Tkinter Canvas:
Any help would be greatly appreciated.
Related
Edit: I figured it out! I'll put my solution in the answers in case someone else makes the same careless mistake as me. :)
I'm having some trouble embedding a Matplotlib figure in my Tkinter gui. Here is the snippet of code I use to create the figure:
def create_plt(self, images, labels):
num = len(images)
fig = Figure()
axes = fig.subplots(nrows=1, ncols=num)
for ind, img in enumerate(images):
axes[ind].imshow(img)
axes[ind].set_title(labels[ind])
canvas = FigureCanvasTkAgg(fig, master=self.itemframe)
canvas.draw()
toolbar = NavigationToolbar2Tk(canvas, self.itemframe, pack_toolbar=False)
toolbar.update()
toolbar.pack(side=tk.BOTTOM, fill=tk.X)
widget = canvas.get_tk_widget()
widget.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
All this code is supposed to do is add subplots of the images/labels I pass in side-by-side, so that the user can zoom in and out of these images and pan around.
It looks alright at first, but when I mouse over it after selecting the pan or zoom tool, the entire plot shifts wildly, resizes itself, the toolbar disappears, and is generally buggy.
I suspect that I'm packing something incorrectly, but I can't tell what. Any help would be greatly appreciated!
It turns out the frame, self.itemframe, that I was trying to place the widget in was the wrong size. It was too small--around 400x300, when the size of the widget was much larger, so it kept having to resize itself every time the GUI updated and appeared glitchy.
Fixed it by instantiating self.itemframe with a larger size.
For me the issue was the DPI of the figure. Once I set it back from 80 to 100 it was working normally. No more glitching.
I'm trying out JupyterLab having used Jupyter notebooks for some time. I use the standard %matplotlib inline magic at the start. I've noticed that JupyterLab displays matplotlib figures much larger than Jupyter notebooks used to.
Is there a way to force JupyterLab to display the images in smaller window/area? I know I can change the figsize I pass when creating the figure but that does not scale the text/labels within the figure and I end up with effectively oversize labels and titles.
Ideally within JupyterLab I'd like to be able to set it up so images fit in an area I can define the size of and if they're larger they get scaled to fit.
I've been reading the JupyterLab docs but nothing leaps out at me at solving this particular problem.
Update: I'm running JupyterLab in Chrome. Chrome displays images up to the full width of the browser window; if the window is smaller than that width that allows the full size of the image, the image is scaled to fit - this is fully dynamic, if you shrink the width of the window the image will rescale on the fly. I changed my figsize parameter (and carefully adjusted font sizes to work) and I got a reasonably sized figure in JuptyerLab. I noticed that when I saved this to a jpg and put that in a powerpoint doc is was quite small (3,2). So I enlarged it, but it became blurred. So I regenerated it with dip=1200. The figure in JuputerLab got bigger. So JupyterLab does not respect the figsize. It's making somekind of judgement based on the number of pixels in the image.
Update 2: This piece of code demonstrates that the Juptyer Lab front end doesn't display images according to the figsize parameter but the product of figsize and dpi (upto the width of the screen, after which it is scaled to fit, presumably by Chrome itself). Note that the font size you see on the screen scales only with dpi and not with figsize (as it should).
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
xys = np.random.multivariate_normal([0.0, 0.0], [[1.0,-0.5],[-0.5,1.0]], 50)
for figsize in [(3,2),(6,4)]:
for dpi in [25,50,100]:
fig = plt.figure(figsize=figsize, dpi=dpi)
ax = fig.add_subplot(1,1,1)
ax.scatter(xys[:,0], xys[:,1])
ax.set_title('figsize = {}, dip = {}'.format(figsize, dpi))
A work around is to work in Jupyter Lab generating figures at a low dpi setting but saving figures at a high dpi setting for publications.
I'm using matplotlib to show a picture but I want to hide the window frame.
I tried the code frameon=False in plt.figure() but the window frame is still there. Just the background color turns to grey.
Here is the code and running result. The picture was showing with the window even I add the "frameon=False" in the code.
frameon suppresses the figure frame. What you want to do is show the figure canvas in a frameless window, which cannot be managed from within matplotlib, because the window is an element of the GUI that shows the canvas. Whether it is possible to suppress the frame and how to do that will depend on the operating system and the matplotlib backend in use.
Let's consider the tk backend.
import matplotlib
# make sure Tk backend is used
matplotlib.use("TkAgg")
import matplotlib.pyplot as plt
# turn navigation toolbar off
plt.rcParams['toolbar'] = 'None'
# create a figure and subplot
fig, ax = plt.subplots(figsize=(2,2))
#remove margins
fig.subplots_adjust(0,0,1,1)
# turn axes off
ax.axis("off")
# show image
im = plt.imread("https://upload.wikimedia.org/wikipedia/commons/8/87/QRCode.png")
ax.imshow(im)
# remove window frame
fig.canvas.manager.window.overrideredirect(1)
plt.show()
I'm using matplotlib to show a picture but I want to hide the window frame.
I tried the code frameon=False in plt.figure() but the window frame is still there. Just the background color turns to grey.
Here is the code and running result. The picture was showing with the window even I add the "frameon=False" in the code.
frameon suppresses the figure frame. What you want to do is show the figure canvas in a frameless window, which cannot be managed from within matplotlib, because the window is an element of the GUI that shows the canvas. Whether it is possible to suppress the frame and how to do that will depend on the operating system and the matplotlib backend in use.
Let's consider the tk backend.
import matplotlib
# make sure Tk backend is used
matplotlib.use("TkAgg")
import matplotlib.pyplot as plt
# turn navigation toolbar off
plt.rcParams['toolbar'] = 'None'
# create a figure and subplot
fig, ax = plt.subplots(figsize=(2,2))
#remove margins
fig.subplots_adjust(0,0,1,1)
# turn axes off
ax.axis("off")
# show image
im = plt.imread("https://upload.wikimedia.org/wikipedia/commons/8/87/QRCode.png")
ax.imshow(im)
# remove window frame
fig.canvas.manager.window.overrideredirect(1)
plt.show()
I am working on a project where I am using PYgtk to build UI which make use of matplotlib library for plotting purpose. Plot window is packed in UI using PYgtk scrolled window container widget as the actual plot will be very big in size.
I want to put an image as a background to figure or figurecanvas, but not to subplot. I want subplot to scroll but not background image.
I am trying with slider option in matplotlib. but still no success.
Can anyone help me to solve this issue?