Procedural PyQt4 generates extra windows after pyplot.show() - macos

I have encountered a strange behaviour on Mac OSX 10.12 when using PyQt4 and matplotlib in a procedural python function.
The function pops up a dialogue which is used to select a directory. The files in this directory are read, and their data is plotted using matplotlib.pyplot.
The issue is that when matplotlib shows the plot window, additional blank windows are also generated behind the matplotlib window. These extra windows are only generated if I include the PyQt code in my function.
When I close the matplotlib window the script hangs, and if i close the additional blank windows the function exits without executing the remaining code in the function.
Does anyone else get these extra windows? I have the feeling that If I can somehow "quit the PyQt app loop" after I've used it to pick my directory then this would fix the problem. This is my intuition / speculation, and attempts to do this have failed.
Here is a screenshot showing the extra windows which pop up when plt.show() is called:
Here is my code:
import os
import sys
from PyQt4.QtGui import *
import numpy as np
import matplotlib.pyplot as plt
def qt_mpl_test():
home = os.path.expanduser('~')
print('Select data top directory...')
app = QApplication(sys.argv)
w = QWidget()
dat_dir = QFileDialog.getExistingDirectory(w, 'Select data top directory', home)
dat_dir = str(dat_dir)
## At this stage I load in my data files for processing / plotting
## For the sake of simplicity, generate some data below
x = np.array([1, 2, 3, 4, 5, 6, 7])
y = np.array([1, 2, 3, 4, 3, 2, 1])
fig, ax = plt.subplots(1, 1)
ax.plot(y, x)
plt.show()
qt_mpl_test()

Related

Making interactive plot with python: images with url link

I would like to plot some images I webscraped from a website, and I want to make a interactive plot in Jupyter notebook/Colab where the interactivity is being able to click on the images, which will get you to the url where I got the image.
I get the images and have them as follows:
im = Image.open(requests.get(df_info['Img'][i], stream=True).raw)
Then I found some code using ImageTk that looks like the following. But the problem is when I set the command option, im feeding a function open that requires an argument (the url)
from PIL import ImageTk
import webbrowser
root = Tk()
canvas = Canvas(root, width=600, height=600)
canvas.pack()
def open(url):
webbrowser.open(url)
img_file = Image.open(requests.get(df_info['Img'][0], stream=True))
img_file = img_file.resize((150, 150))
img = ImageTk.PhotoImage(img_file)
b1 = Button(canvas,image=img,command=open).pack()
root.mainloop()
I am not sure I have to use this ImageTk framework, either. It would be great if there was a way to just use matplotlib functions as well. But the key is to have that clickability on the pictures in the Jupyter notebook.
Could someone please help me?

Zooming out on pandas table in Jupyter Notebooks

I am attempting to take a screenshot of a correlation table made with pandas in Jupyter Notebooks but since it is very wide I must scroll to the right in order to view the whole table. On a mac it is not possible to scroll left or right while taking a screenshot so I am unable to capture the entire table. Is there anyway to get the entire table (doesn't have to be a screenshot an export of some type would work as well)?
Is the table already shown in markdown? If not, you can try df.to_html(). From there, you can convert it to pdf, see (https://www.npmjs.com/package/markdown-pdf)
Otherwise you can plot the pandas table with matplotlib and remove the axis etc.
import matplotlib.pyplot as plt
import pandas as pd
from pandas.table.plotting import table
ax = plt.subplot(111, frame_on=False) # no visible frame
ax.xaxis.set_visible(False) # hide the x axis
ax.yaxis.set_visible(False) # hide the y axis
table(ax, df) # where df is your data frame
plt.savefig('table.png')

The exponential distribution didn't show up in the shell

Here is a short code :
import numpy as np
from scipy.stats import expon
import matplotlib.pyplot as plt
x = np.arange(0, 10, 0.001)
plt.plot(x, expon.pdf(x))
When I type that in the shell in using ipython, that didn't show up anything while it is supposed to plot the exponential distribution for x between 0 and 10. Could anyone be able to tell me what is the problem here?
I got that, but the plot did show up
In [16]: plt.plot(x, norm.pdf(x))
Out[16]: [<matplotlib.lines.Line2D at 0x7fbfe6bc2890>]
Thanks in advance!
P.S. Be aware that I am using Ubuntu 16.10 (Linux distribution).
It seems you are using IPython. Depending on in which environment you use it, you can create inline plots or plot to a window.
Ipython in Jupyther QtConsole allows to set the inline backend, %matplotlib inline.
In IPython without graphical support, you need to invoke a plotting window using plt.show()

Python 3.4: Where is the image library?

I am trying to display images with only builtin functions, and there are plenty of Tkinter examples online. However, none of the libraries work:
import Image # none of these exist.
import tkinter.Image
import _tkinter.Image
etc
However, tkinter does exist, a hellow-world with buttons worked fine.
I am on a MacBook pro 10.6.8 and using PyCharm.
Edit: The best way so far (a little slow but tolerable):
Get the pixel array as a 2D list (you can use a third-party .py to load your image).
Now you make a data array from the pixels like this (this is the weirdest format I have seen, why not a simple 2D array?). This may be sideways, so you may get an error for non-square images. I will have to check.
Imports:
from tkinter import *
import tkinter
data = list() # the image is x pixels by y pixels.
y = len(pixels)
x = len(pixels[0])
for i in range(y):
col_str.append('{')
for j in range(x):
data.append(pixels[i][j]+" ")
data.append("} ")
data = "".join(data)
Now you can create an image and use put:
# PhotoImage is builtin (tkinter).
# It does NOT need PIL, Pillow, or any other externals.
im = PhotoImage(width=x, height=y)
im.put(col_str)
Finally, attach it to the canvas:
canvas = tkinter.Canvas(width=x, height=y)
canvas.create_image(x/2, y/2, image=GLOBAL_IMAGE) # x/2 and y/2 are the center.
tK.mainloop() # enter the main loop and it will be drawn.
Image must be global or else it may not show up because the garbage collector gets greedy.
PIL hasn't been updated since 2009, with Python 3 support being terminally stuck at "later."
Instead, try pillow, which has forked PIL and provides Python 3 support.

adding contrast to an image in python

I am trying to work through a process where I take an astronomical fits file, subtract a masterflat file and then later the contrast on the resultant image.
The first part has been done successfully but my image lacks contrast. Here's my code
from astropy.io.fits import getdata
import numpy
import numpy as np
import scipy
import Image
import PIL
import os
os.chdir("/localdir/")
from scipy import misc
import ImageEnhance
image = getdata('23484748.fts')
flat = getdata('Masterflat.fit')
normalized_flat = flat / numpy.mean(flat)
calibrated_image = image / normalized_flat
pix=numpy.fliplr(calibrated_image)
# the problem starts about here. How do I alter the contrast of pix?
from matplotlib import pyplot as plt
misc.imsave('saved image.gif', pix) # uses the Image module (PIL)
plt.imshow(pix, interpolation='nearest')
plt.show()
Now before you tell me all about PIL functions and Matlib etc I have tried these without success.
I have tried to use image.fromarray to convert my numpy array into an image but the resultant image displays as pure white.
How can I take my numpy array (pix) and change its contrast?
For testing purposes I have put the two sample files at http://members.optusnet.com.au/berrettp/
Thanking you
Peter

Resources