Hi I am currently working on a project where I need to select a file, cluster the data present and plot the no. of points in each cluster using plot_count() function. Any ideas why the program doesn't terminate.
Following code is just a snippet of my project.
Thanks in advance
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import pandas as pd
def plot_count(list):
index_list = [None]*len(list)
for i in range(len(list)):
index_list[i] = "Cluster "+str(i)
s = pd.Series(
list,
index = index_list
)
#Set descriptions:
plt.ylabel('No Of Points')
plt.xlabel('Clusters')
#Set tick colors:
ax = plt.gca()
ax.tick_params(axis='x', colors='blue')
ax.tick_params(axis='y', colors='red')
#Plot the data:
my_colors = 'rgbkymc' #red, green, blue, black, etc.
pd.Series.plot(
s,
kind='bar',
color=my_colors
)
plt.show()
import sys
sys.exit(0)
def get_filename():
from Tkinter import Tk
from tkFileDialog import askopenfilename
# we don't want a full GUI, so keep the root window from appearing
Tk().withdraw()
# show an "Open" dialog box and return the path to the selected file
filename = askopenfilename()
return filename
if __name__ == "__main__":
import plotting
get_filename()
plotting.plot_count([40, 44, 56])
changing
plt.show() - -> plt.pause(interval) plotted figure would be displayed only for specified interval
and then blocking the interactivity - -> plt.ioff() Interactivity will be set off and program terminates
solves the problem.
Related
I'm trying to create a graph that displays plots two lines from live data. the values that will be displayed will come from two seperate encoders but for now I'm just using randrange to get data into the program. I've found some examples using matplotlib that I've modified, but once I try to add the second value it won't work
import itertools
from tkinter import *
from tkinter import ttk
import matplotlib
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.gridspec import GridSpec
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import random
x_len = 300
y_range = [0,300]
INTERVALS = 0
win = Tk()
# Set the window size
win.geometry("1024x600")
# --- Use TkAgg ---
matplotlib.use("TkAgg")
# Create a figure of specific size
figure = plt.figure(figsize=(11, 5), dpi=100)
gs = GridSpec(nrows=3, ncols=4)
#Create plot1
plot = figure.add_subplot(gs[:,0:3],)
xs = list(range(0, x_len))
ys = [0]* x_len
yc = [0]* x_len
plot.set_ylim(y_range)
line, = plot.plot(xs,ys)
def animate(i, ys,):
# get values
Pid = random.randrange(0,100)
sp = random.randrange(100,200)
# Add y to list
ys.append(Pid)
# Limit y list to set number of items
ys = ys[-x_len:]
# Update line with new Y values
line.set_ydata(ys)
return (line,)
ani = animation.FuncAnimation(figure,
animate,
fargs=(ys,),
interval=INTERVALS,
blit=True)
# Add a canvas widget to associate the figure with canvas
canvas = FigureCanvasTkAgg(figure, win)
canvas.get_tk_widget().grid(row=0, column=0)
win.mainloop()
I want to update a single Matplotlib figure with each timestep in my Notebook. I have referenced numerous API resources and examples forum answers here on StackOverflow, however, all of the proposed code either did not graph or displayed a new figure with each timestep, like this answer,
import matplotlib.pyplot as plt
import time
import random
from collections import deque
import numpy as np
# simulates input from serial port
def random_gen():
while True:
val = random.randint(1,10)
yield val
time.sleep(0.1)
a1 = deque([0]*100)
ax = plt.axes(xlim=(0, 20), ylim=(0, 10))
d = random_gen()
line, = plt.plot(a1)
plt.ion()
plt.ylim([0,10])
plt.show()
for i in range(0,20):
a1.appendleft(next(d))
datatoplot = a1.pop()
line.set_ydata(a1)
plt.draw()
print a1[0]
i += 1
time.sleep(0.1)
plt.pause(0.0001) #add this it will be OK.
and this answer.
import numpy as np
import matplotlib.pyplot as plt
plt.axis([0, 10, 0, 1])
for i in range(10):
y = np.random.random()
plt.scatter(i, y)
plt.pause(0.1)
How can I update a figure with each timestep in Python, via Matplotlib or possibly other means? I appreciate your perspectives.
Thank you :)
Real-time drawing by entering the interactive mode of matplotlib.
If you only use plt.show() to draw, the program will stop executing the subsequent program, so open the drawing window through plt.ion() to enter the interactive mode, use the program plt.plot() to draw in real time, after the drawing is completed, use plt .ioff() exits the interactive mode and uses plt.show() to display the final image data. If plt.show() is not added at the end, it will flash back.
import matplotlib.pyplot as plt
import numpy as np
ax=[]
ay=[]
bx=[]
by=[]
num=0
plt.ion()
# plt.rcParams['savefig.dpi'] = 200
# plt.rcParams['figure.dpi'] = 200
plt.rcParams['figure.figsize'] = (10, 10)
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['lines.linewidth'] = 0.5
while num<100:
plt.clf()
plt.suptitle("TITLE",fontsize=30)
g1=np.random.random()
ax.append(num)
ay.append(g1)
agraphic=plt.subplot(2,1,1)
agraphic.set_title('TABLE1')
agraphic.set_xlabel('x',fontsize=10)
agraphic.set_ylabel('y', fontsize=20)
plt.plot(ax,ay,'g-')
#table2
bx.append(num)
by.append(g1)
bgraghic=plt.subplot(2, 1, 2)
bgraghic.set_title('TABLE2')
bgraghic.plot(bx,by,'r^')
plt.pause(0.4)
if num == 15:
plt.savefig('picture.png', dpi=300)
#break
num=num+1
plt.ioff()
plt.show()
I'm using Python 3.6 in jupyter notebook. plt.close does not close plot. I tried with plt.ion() also and many other ways.
I want to display image, then wait for pause or input() and then remove the previous image and show the new one.
import matplotlib.pyplot as plt
from time import sleep
from scipy import eye
plt.imshow(eye(3))
plt.show()
sleep(1)
plt.close()
Here is an example that shows a sequence of plots, each for one second. Essential are the commants plt.show(block = False) and plt.pause(1) instead of sleep(1):
import numpy as np
import matplotlib.pyplot as plt
def show_image(n):
fig, ax = plt.subplots()
x = np.linspace(0,1,100)
y = x**n
ax.plot(x,y, label = 'x**{}'.format(n))
ax.legend()
plt.show(block=False)
plt.pause(1)
plt.close(fig)
for i in range(10):
show_image(i)
If I understand correctly, what you want is to show a plot, wait 1 second, then let it close automatically.
This would be achieved as follows.
import matplotlib.pyplot as plt
from scipy import eye
plt.imshow(eye(3))
def show_and_close(sec):
timer = plt.gcf().canvas.new_timer(interval=sec*1000)
timer.add_callback(lambda : plt.close())
timer.single_shot = True
timer.start()
plt.show()
show_and_close(1)
How to set matplotlib to show every image of an array?
I want that everytime i click on the right arrow, it shows the next image and so on...
Is that possible?
width = 14
height = 14
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
data_images = X_train.reshape(X_train.shape[0],width,height)
print "Shape " ,data_images.shape #Shape (50000L, 14L, 14L)
plt.imshow(data_images[0])
plt.show()
I wanted to pass the "data_images" variable to plt.imshow and so everytime i clicked on next on the matplotlib, it would show the next image.
Working example with plt.connect().
You can change image by pressing any key.
import matplotlib.pyplot as plt
data_images = [
[[1,2,3],[1,2,3],[1,2,3]],
[[1,1,1],[2,2,2],[3,3,3]],
[[1,2,1],[2,2,2],[1,2,1]],
]
#----------------------------------
index = 0
def toggle_images(event):
global index
index += 1
if index < len(data_images):
plt.imshow(data_images[index])
plt.draw()
else:
plt.close()
#----------------------------------
plt.imshow(data_images[index])
plt.connect('key_press_event', toggle_images)
plt.show()
I would do this using ipywidgets within the IPython notebook. Here's an example:
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
from ipywidgets import interact
images = np.random.random((500, 14, 14))
def browse_images(images):
N = images.shape[0]
def view_image(i=0):
plt.imshow(images[i], cmap='gray', interpolation='nearest')
plt.title('Image {0}'.format(i))
interact(view_image, i=(0, N-1))
browse_images(images)
Edit: the result, in the notebook page, will look something like this:
You can press the left or right arrow to advance the slider and view the next image.
You can do a bit better in the notebook than using inline:
%matplotlib notebook
import matplotlib.pyplot as plt
import numpy as np
from ipywidgets import interact
from IPython.display import display
images = np.random.random((500, 14, 14))
fig, ax = plt.subplots()
im = ax.imshow(images[0], cmap='gray', interpolation='nearest')
def browse_images(images):
N = images.shape[0]
def view_image(i=0):
im.set_data(images[i])
ax.set_title('Image {0}'.format(i))
fig.canvas.draw_idle()
interact(view_image, i=(0, N-1))
and then in the next cell
browse_images(images)
which will give you a pannable/zoom able figure. In mpl 1.5.0 you also get the pixel values under the cursor by default.
(I tested this on tmpnb.org)
I am really struggling with matplotlib, escpecially with the axis settings. My goal is to set up 6 subplots in one figure, which all display different datasets but have the same amount of ticklabels.
The relevant part of my sourcecode looks like:
graph4.py:
# Import Matolotlib Modules #
import matplotlib as mpl
from matplotlib.figure import Figure
from matplotlib.backends.backend_gtkagg import FigureCanvasGTKAgg as FigureCanvas
from matplotlib import ticker
import matplotlib.pyplot as plt
mpl.rcParams['font.sans-serif']='Arial' #set font to arial
# Import GTK Modules #
import gtk
#Import System Modules #
import sys
# Import Numpy Modules #
from numpy import genfromtxt
import numpy
# Import Own Modules #
import mysubplot as mysp
class graph4():
weekdays = ['Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag']
def __init__(self, graphview):
#create new Figure
self.figure = Figure(figsize=(100,100), dpi=75)
#create six subplots within self.figure
self.subplot = []
for j in range(6):
self.subplot.append(self.figure.add_subplot(321 + j))
self.__conf_subplots__() #configure title, xlabel, ylabel and grid of all subplots
#to make it look better
self.figure.subplots_adjust(left=0.125, bottom=0.1, right=0.9, top=0.96, wspace=0.2, hspace=0.6)
#Matplotlib <-> GTK
self.canvas = FigureCanvas(self.figure) # a gtk.DrawingArea
self.canvas.set_flags(gtk.HAS_FOCUS|gtk.CAN_FOCUS)
self.canvas.grab_focus()
self.canvas.show()
graphview.pack_start(self.canvas, True, True)
#add labels and grid to all subplots
def __conf_subplots__(self):
index = 0
for i in self.subplot:
mysp.conf_subplot(i, 'Zeit', 'Menge', graph4.weekdays[index], True)
i.plot([], [], 'bo') #empty plot
index +=1
def plot(self, filename_list):
index = 0
for filename in filename_list:
data = genfromtxt(filename, delimiter=',') #load data from filename
if data.size != 0: #only if file isn't empty
if index <= len(self.subplot): #plot every file on a different subplot
mysp.plot(self.subplot[index],data[0:, 1], data[0:, 0])
index +=1
self.canvas.draw()
def clear_plot(self):
#clear axis of all subplots
for i in self.subplot:
i.cla()
self.__conf_subplots__()
mysubplot.py: (helper module)
# Import Matplotlib Modules
from matplotlib.axes import Subplot
import matplotlib.dates as md
import matplotlib.pyplot as plt
# Import Own Modules #
import mytime as myt
# Import Numpy Modules #
import numpy as np
def conf_subplot(subplot, xlabel, ylabel, title, grid):
if(xlabel != None):
subplot.set_xlabel(xlabel)
if(ylabel != None):
subplot.set_ylabel(ylabel)
if(title != None):
subplot.set_title(title)
subplot.grid(grid)
#rotate xaxis labels
plt.setp(subplot.get_xticklabels(), rotation=30, fontsize=12)
#display date on xaxis
subplot.xaxis.set_major_formatter(md.DateFormatter('%H:%M:%S'))
subplot.xaxis_date()
def plot(subplot, x, y):
subplot.plot(x, y, 'bo')
I think the best way to explain what goes wrong is with the use of screenshots. After I start my application, everything looks good:
If I double click a 'Week'-entry on the left, the method clear_plot() in graph4.py is called to reset all subplots. Then a list of filenames is passed to the method plot() in graph4.py. The method plot() opens each file and plots each dataset on a different subplot. So after I double click a entry, it looks like:
As you can see, each subplot has a different number of xtick labels, which looks pretty ugly to me. Therefore, I am looking for a solution to improve this. My first approach was to set the ticklabels manually with xaxis.set_ticklabels(), so that each subplot has the same number of ticklabels. However, as strange as it sounds, this only works on some datasets and I really don't know why. On some datasets, everything works fine and on other datasets, matplotlib is basically doing what it wants and displays xaxis labels that I didn't specify. I also tried FixedLocator(), but I got the same result. On some datasets it is working and on others, matplotlib is using a different number of xtick labels.
What am I doing wrong?
Edit:
As #sgpc suggested, I tried to use pyplot. My sourcecode now looks like this:
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib.backends.backend_gtkagg import FigureCanvasGTKAgg as FigureCanvas
import matplotlib.dates as md
mpl.rcParams['font.sans-serif']='Arial' #set font to arial
import gtk
import sys
# Import Numpy Modules #
from numpy import genfromtxt
import numpy
# Import Own Modules #
import mysubplot as mysp
class graph2():
weekdays = ['Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag']
def __init__(self, graphview):
self.figure, temp = plt.subplots(ncols=2, nrows=3, sharex = True)
#2d array -> list
self.axes = [ y for x in temp for y in x]
#axis: date
for i in self.axes:
i.xaxis.set_major_formatter(md.DateFormatter('%H:%M:%S'))
i.xaxis_date()
#make space and rotate xtick labels
self.figure.autofmt_xdate()
#Matplotlib <-> GTK
self.canvas = FigureCanvas(self.figure) # a gtk.DrawingArea
self.canvas.set_flags(gtk.HAS_FOCUS|gtk.CAN_FOCUS)
self.canvas.grab_focus()
self.canvas.show()
graphview.pack_start(self.canvas, True, True)
def plot(self, filename_list):
index = 0
for filename in filename_list:
data = genfromtxt(filename, delimiter=',') #get dataset
if data.size != 0: #only if file isn't empty
if index < len(self.axes): #print each dataset on a different subplot
self.axes[index].plot(data[0:, 1], data[0:, 0], 'bo')
index +=1
self.canvas.draw()
#not yet implemented
def clear_plot(self):
pass
If I plot some datasets, I get the following output:
http://i.imgur.com/3ngYTNr.png (sorry, I still don't have enough reputation to embedd pictures)
Moreover, I am not really sure if sharing the x-axis is a really good idea, because it is possible that the x-values differ in every subplot (for example: in the first subplot, the x-values ranges from 8:00am - 11:00am and in the second subplot the x-values ranges from 7:00pm - 9:00pm).
If I get rid of sharex = True, I get the following output:
http://i.imgur.com/rxHeSyJ.png (sorry, I still don't have enough reputation to embedd pictures)
As you can see, the output now looks better. However now, the labels on the x-axes are not updated. I assume that is because the last suplots are empty.
My next attempt was to use an axis for each subplot. Therefore, I made this changes:
for i in self.axes:
plt.setp(i.get_xticklabels(), visible=True, rotation = 30) #<-- I added this line...
i.xaxis.set_major_formatter(md.DateFormatter('%H:%M:%S'))
i.xaxis_date()
#self.figure.autofmt_xdate() #<--changed this line
self.figure.subplots_adjust(left=0.125, bottom=0.1, right=0.9, top=0.96, wspace=0.2, hspace=0.6) #<-- and added this line
Now I get the following output:
i.imgur.com/TmA1goE.png (sorry, I still don't have enough reputation to embedd pictures)
So with this attempt, I am basically struggling with the same problem as with Figure() and add_subplot().
I really don't know, what else I could try to make it work...
I would strongly recommend you to use pyplot.subplots() with sharex=True:
fig, axes = subplots(ncols=2, nrows=3, sharex= True)
Then you access each axes using:
ax = axes[i,j]
And you can plot doing:
ax.plot(...)
To control the number of ticks for each AxesSubplot you can use:
ax.locator_params(axis='x', nbins=6)
OBS: axis can be 'x', 'y' or 'both'