i am new to python. I am writing a data logging program and want to open a serial port, then read from it.
My problem is that calling this in my main():
# Handle serial
ser = serial.Serial(strPort, 9600)
doesnt allow me to invoke methods on the ser handle in other functions. Should i make a class or whats the best approach?
Here is the error message:
line 164, in updateData
line = ser.readline().rstrip()
NameError: name 'ser' is not defined
Here is the code:
# Uncomment the next two lines if you want to save the animation
import matplotlib
# matplotlib.use("Agg")
import sys
import serial
import argparse
import csv
import numpy
from matplotlib.pylab import *
from mpl_toolkits.axes_grid1 import host_subplot
import matplotlib.animation as animation
'''
ax03.legend([p031,p032], [p031.get_label(),p032.get_label()])
'''
def main():
# Sent for figure
font = {'size': 9}
matplotlib.rc('font', **font)
# Setup figure and subplots
f0 = figure(num=0, figsize=(12, 10)) # , dpi = 100)
f0.suptitle("Sensor Data", fontsize=12)
ax01 = subplot2grid((3, 2), (1, 0))
#ax02 = subplot2grid((4, 2), (1, 1))
ax02 = ax01.twinx()
ax03 = subplot2grid((3, 2), (0, 0), colspan=2, rowspan=1)
ax04 = subplot2grid((3, 2), (1, 1))
ax05 = subplot2grid((3, 2), (2, 0))
ax06 = subplot2grid((3, 2), (2, 1))
subplots_adjust(left=None, bottom=None, right=None,
top=None, wspace=0.3, hspace=0.3)
# Set titles of subplots
ax01.set_title('Heart Rate Quality and Sample Frequency')
ax03.set_title('Heart Rate')
ax04.set_title('Step Rate')
ax05.set_title('Perfusion Index')
ax06.set_title('Raw PPG')
# set y-limits
ax01.set_ylim(-1, 5)
ax02.set_ylim(100, 500)
ax03.set_ylim(30, 140)
ax04.set_ylim(-50, 250)
ax05.set_ylim(0, 500)
ax06.set_ylim(0, 50000)
# sex x-limits
ax01.set_xlim(0, 50.0)
# ax02.set_xlim(0,50.0)
ax03.set_xlim(0, 50.0)
ax04.set_xlim(0, 50.0)
ax05.set_xlim(0, 50.0)
ax06.set_xlim(0, 50.0)
# Turn on grids
ax01.grid(True)
# ax02.grid(True)
ax03.grid(True)
ax04.grid(True)
ax05.grid(True)
ax06.grid(True)
# set label names
ax01.set_xlabel("t[s]")
ax01.set_ylabel("HRQ")
ax02.set_xlabel("t[s]")
ax02.set_ylabel("samples[Hz]")
ax03.set_xlabel("t[s]")
ax03.set_ylabel("bpm")
ax04.set_xlabel("t[s]")
ax04.set_ylabel("Steps/min")
ax05.set_xlabel("t[s]")
ax05.set_ylabel("AC/DC ratio")
ax06.set_xlabel("t[s]")
ax06.set_ylabel("raw PS sample")
# Data Placeholders
t = zeros(0)
hr = zeros(0)
HRQ = zeros(0)
Fs = zeros(0)
stepRate = zeros(0)
ADCGain = zeros(0)
pI = zeros(0)
rawPPG = zeros(0)
ser = zeros(0)
# set plots
p011, = ax01.plot(t, HRQ, 'c-', label="HRQ", linewidth=2)
p021, = ax02.plot(t, ADCGain, 'r-', label="Sample Frequency", linewidth=2)
p031, = ax03.plot(t, hr, 'b-', label="Heart Rate", linewidth=2)
p041, = ax04.plot(t, stepRate, 'b-', label="Step Rate", linewidth=2)
p051, = ax05.plot(t, pI, 'y-', label="Perfusion Index", linewidth=2)
p061, = ax06.plot(t, rawPPG, 'g-', label="Raw PPG", linewidth=2)
# set lagends
ax01.legend([p011, p021], [p011.get_label(), p021.get_label()], loc=2)
#ax02.legend([p021], [p021.get_label()])
ax03.legend([p031], [p031.get_label()], loc=2)
ax04.legend([p041], [p041.get_label()], loc=2)
ax05.legend([p051], [p051.get_label()], loc=2)
ax06.legend([p061], [p061.get_label()], loc=2)
# Data Update
xmin = 0.0
xmax = 50.0
x = 0.0
# create parser
parser = argparse.ArgumentParser(description="LDR serial")
# add expected arguments
parser.add_argument('--port', dest='port', required=True)
# parse args
args = parser.parse_args()
#strPort = '/dev/tty.usbserial-A7006Yqh'
strPort = args.port
print('reading from serial port %s...' % strPort)
# Handle serial
ser = serial.Serial(strPort, 9600)
print('plotting data...')
# Logfile writer
# open('test.csv','w') as csvfile
#logwriter = csv.writer(csvfile, delimiter=' ', quotechar='|', quoting=csv.QUOTE_MINIMAL)
# interval: draw new frame every 'interval' ms
# frames: number of frames to draw
simulation = animation.FuncAnimation(
f0, updateData, blit=False, frames=1000, interval=100, repeat=True)
# Uncomment the next line if you want to save the animation
# simulation.save(filename='sim.mp4',fps=1,dpi=300)
plt.show()
def updateData(self):
global x
global t
global ser
global hr
global HRQ
global Fs
global ADCGain
global stepRate
global pI
global rawPPG
try:
line = ser.readline().rstrip()
data = [float(val) for val in line.split()]
# print data
print(data)
if(len(data) == 9):
# log data
for i in range(len(data)):
out_string = ""
out_string += str(data[i])
# logwriter.writerow(out_string)
# update variables
tmpT = data[0]
tmpFs = data[1]
tmpStepRate = data[2]
tmpHr = data[3]
tmpPI = data[4]
tmpHRQ = data[5]
tmpRawPPG = data[6]
except KeyboardInterrupt:
print('exiting')
hr = append(hr, tmpHr)
HRQ = append(HRQ, tmpHRQ)
Fs = append(Fs, tmpFs)
stepRate = append(stepRate, tmpStepRate)
pI = append(pI, tmpPI)
rawPPG = append(rawPPG, tmpRawPPG)
t = append(t, x)
x += 1
p011.set_data(t, HRQ)
p021.set_data(t, Fs)
p031.set_data(t, hr)
p041.set_data(t, stepRate)
p051.set_data(t, pI)
p061.set_data(t, rawPPG)
if x >= xmax - 10.00:
p011.axes.set_xlim(x - xmax + 10.0, x + 10.0)
p021.axes.set_xlim(x - xmax + 10.0, x + 10.0)
p031.axes.set_xlim(x - xmax + 10.0, x + 10.0)
p041.axes.set_xlim(x - xmax + 10.0, x + 10.0)
p051.axes.set_xlim(x - xmax + 10.0, x + 10.0)
p061.axes.set_xlim(x - xmax + 10.0, x + 10.0)
return p011, p021, p031, p041, p051, p061
# Call main
if __name__ == '__main__':
main()
Related
I have asked this before and maybe I was not clear so, asking again. I am taking 4 different sensor values from arduino and plotting them real time using matplotlib of python. The real time plotting of multiple sensors is working, but I need them in a GUI with a start and a stop button. How do I modify my following code such that I get 4 real time plots in a GUI. This code is working, I just need to see my graphs in a GUI. Thanks in advance and help me the additional modification as I am new to python and still learning.
import copy
from threading import Thread
from tkinter import Tk, Frame
import serial
import time
import collections
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import struct
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
A = 0
B = 0
C = 0
D = 0
Sum = 0
Az = 0
El = 0
class serialPlot:
def __init__(self, serialPort='com5', serialBaud=38400, plotLength=100, dataNumBytes=2, numPlots=1):
self.port = serialPort
self.baud = serialBaud
self.plotMaxLength = plotLength
self.dataNumBytes = dataNumBytes
self.numPlots = numPlots
self.rawData = bytearray(numPlots * dataNumBytes)
self.dataType = None
if dataNumBytes == 2:
self.dataType = 'h' # 2 byte integer
elif dataNumBytes == 4:
self.dataType = 'f' # 4 byte float
self.data = []
self.privateData = None # for storing a copy of the data so all plots are synchronized
for i in range(numPlots): # give an array for each type of data and store them in a list
self.data.append(collections.deque([0] * plotLength, maxlen=plotLength))
self.isRun = True
self.isReceiving = False
self.thread = None
self.plotTimer = 0
self.previousTimer = 0
print('Trying to connect to: ' + str(serialPort) + ' at ' + str(serialBaud) + ' BAUD.')
try:
self.serialConnection = serial.Serial(serialPort, serialBaud, timeout=4)
print('Connected to ' + str(serialPort) + ' at ' + str(serialBaud) + ' BAUD.')
except:
print("Failed to connect with " + str(serialPort) + ' at ' + str(serialBaud) + ' BAUD.')
def readSerialStart(self):
if self.thread == None:
self.thread = Thread(target=self.backgroundThread)
self.thread.start()
# Block till we start receiving values
while self.isReceiving != True:
time.sleep(0.1)
def getSerialData(self, frame, lines, lineValueText, lineLabel, timeText, pltNumber):
if pltNumber == 0: # in order to make all the clocks show the same reading
currentTimer = time.perf_counter()
self.plotTimer = int((currentTimer - self.previousTimer) * 1000) # the first reading will be erroneous
self.previousTimer = currentTimer
self.privateData = copy.deepcopy(
self.rawData) # so that the 4 values in our plots will be synchronized to the same sample time
timeText.set_text('Plot Interval = ' + str(self.plotTimer) + 'ms')
data = self.privateData[(pltNumber * self.dataNumBytes):(self.dataNumBytes + pltNumber * self.dataNumBytes)]
value, = struct.unpack(self.dataType, data)
self.data[pltNumber].append(value) # we get the latest data point and append it to our array
lines.set_data(range(self.plotMaxLength), self.data[pltNumber])
lineValueText.set_text('[' + lineLabel + '] = ' + str(value))
if lineLabel == 'Detector A':
global A
A = float(value)
if lineLabel == 'Detector B':
global B
B = float(value)
if lineLabel == 'Detector C':
global C
C = float(value)
if lineLabel == 'Detector D':
global D
D = float(value)
Sum = (A + B + C + D)
Az = (A + D - C - B)
El = (A + B - C - D)
def backgroundThread(self): # retrieve data
time.sleep(1.0) # give some buffer time for retrieving data
self.serialConnection.reset_input_buffer()
while (self.isRun):
self.serialConnection.readinto(self.rawData)
self.isReceiving = True
def close(self):
self.isRun = False
self.thread.join()
self.serialConnection.close()
print('Disconnected...')
def makeFigure(xLimit, yLimit, title):
xmin, xmax = xLimit
ymin, ymax = yLimit
fig = plt.figure()
ax = plt.axes(xlim=(xmin, xmax), ylim=(int(ymin - (ymax - ymin) / 10), int(ymax + (ymax - ymin) / 10)))
ax.set_title(title)
ax.set_xlabel("Time")
ax.set_ylabel("Detector Output")
ax.grid(True)
return fig, ax
class Window(Frame):
def __init__(self, figure, master, SerialReference):
Frame.__init__(self, master)
self.entry = None
self.setPoint = None
self.master = master # a reference to the master window
self.serialReference = SerialReference # keep a reference to our serial connection so that we can use it for bi-directional communicate from this class
self.initWindow(figure) # initialize the window with our settings
def initWindow(self, figure):
self.master.title("Real Time Plot")
canvas = FigureCanvasTkAgg(figure, master=self.master)
#toolbar = NavigationToolbar2TkAgg(canvas, self.master)
#canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
def main():
portName = 'COM5'
# portName = '/dev/ttyUSB0'
baudRate = 38400
maxPlotLength = 100 # number of points in x-axis of real time plot
dataNumBytes = 4 # number of bytes of 1 data point
numPlots = 4 # number of plots in 1 graph
s = serialPlot(portName, baudRate, maxPlotLength, dataNumBytes, numPlots) # initializes all required variables
s.readSerialStart() # starts background thread
# plotting starts below
pltInterval = 50 # Period at which the plot animation updates [ms]
lineLabelText = ['Detector A', 'Detector B', 'Detector C', 'Detector D']
title = ['Detector A', 'Detector B', 'Detector C', 'Detector D']
xLimit = [(0, maxPlotLength), (0, maxPlotLength), (0, maxPlotLength), (0, maxPlotLength)]
yLimit = [(-1, 1), (-1, 1), (-1, 1), (-1, 1)]
style = ['r-', 'g-', 'b-', 'y-'] # linestyles for the different plots
anim = []
for i in range(numPlots):
fig, ax = makeFigure(xLimit[i], yLimit[i], title[i])
lines = ax.plot([], [], style[i], label=lineLabelText[i])[0]
timeText = ax.text(0.50, 0.95, '', transform=ax.transAxes)
lineValueText = ax.text(0.50, 0.90, '', transform=ax.transAxes)
anim.append(
animation.FuncAnimation(fig, s.getSerialData, fargs=(lines, lineValueText, lineLabelText[i], timeText, i),
interval=pltInterval)) # fargs has to be a tuple
plt.legend(loc="upper left")
plt.show()
s.close()
if __name__ == '__main__':
main()
When I run this code I get this error: ax = plt.subplot("311")
MatplotlibDeprecationWarning: Passing non-integers as three-element position specification is deprecated since 3.3 and will be removed two minor releases later. I made those changes that was suggested now I get errors in other parts of the code.
I have provided a small snippet of the code
Any suggestions on how I can fix this
import socket, traceback
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
from scipy.signal import butter, lfilter,iirfilter,savgol_filter
import math
import pylab
from pylab import *
import time
import numpy as np
host = ''
port = 5555
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
s.bind((host, port))
# lists for plotting
Ax = [0.0] * 50
Ay = [0.0] * 50
Az = [0.0] * 50
G = [0.0] * 50
x = [i for i in range(len(Ax))]
#used for debugging
fig = plt.figure(figsize=(16,10))
# raw data
ax = plt.subplot(311)
ax.set_xlim(0, 50)
ax.set_ylim(-2, 2)
ax.set_title("Raw acceleration data")
ax.set_ylabel("g$/m^2$",fontsize=18)
line = ax.plot(Ax,label='Acc x')[0]
line2 = ax.plot(Ay,label='Acc y')[0]
line3 = ax.plot(Az,label='Acc z')[0]
# filtered data
ax2 = plt.subplot(312)
ax2.set_xlim(0, 50)
ax2.set_ylim(-2, 2)
ax2.set_title(" acceleration data")
ax2.set_ylabel("g$/m^2$",fontsize=18)
f_line = ax2.plot(Ax,label='Acc x')[0]
f_line2 = ax2.plot(Ay,label='Acc y')[0]
f_line3 = ax2.plot(Az,label='Acc z')[0]
# tilt angle plot
ax3 = plt.subplot(313)
ax3.set_ylim([-180,180])
ax3.set_title("Tilt Angles")
ax3.set_ylabel("degrees",fontsize=18)
t_line = ax3.plot(G)[0]
fig.suptitle('Three-axis accelerometer streamed from Sensorstream',fontsize=18)
plt.show(False)
plt.draw()
# cache the background
background = fig.canvas.copy_from_bbox(fig.bbox)
count = 0
print("Success binding")
while 1:
# time it
tstart = time.time()
message, address = s.recvfrom(8192)
messageString = message.decode("utf-8")
Acc = messageString.split(',')[2:5]
Acc = [float(Acc[i])/10.0 for i in range(3)]
# appending and deleting is order 10e-5 sec
Ax.append(Acc[0])
del Ax[0]
Ay.append(Acc[1])
del Ay[0]
Az.append(Acc[2])
del Az[0]
G.append(np.sqrt(Ax[-1]**2 + Ay[-1]**2 + Az[-1]**2))
del G[0]
# filter
acc_x_savgol = savgol_filter(Ax, window_length=5, polyorder=3)
acc_y_savgol = savgol_filter(Ay, window_length=5, polyorder=3)
acc_z_savgol = savgol_filter(Az, window_length=5, polyorder=3)
tilt_angles = []
for i,val in enumerate(G):
angle = math.atan2(Ax[i], -1*Ay[i]) * (180 / math.pi)
if (math.isnan(angle)):
tilt_angles.append(0)
else:
tilt_angles.append(angle)
print(Ax[0],Ay[1],Az[2])
line.set_xdata(x)
line.set_ydata(Ax)
line2.set_xdata(x)
line2.set_ydata(Ay)
line3.set_xdata(x)
line3.set_ydata(Az)
ax.set_xlim(count, count+50)
f_line.set_xdata(x)
f_line.set_ydata(acc_x_savgol)
f_line2.set_xdata(x)
f_line2.set_ydata(acc_y_savgol)
f_line3.set_xdata(x)
f_line3.set_ydata(acc_z_savgol)
ax2.set_xlim(count, count+50)
t_line.set_xdata(x)
t_line.set_ydata(tilt_angles)
ax3.set_xlim(count, count+50)
# restore background
fig.canvas.restore_region(background)
# redraw just the points
ax.draw_artist(line)
ax.draw_artist(line2)
ax.draw_artist(line3)
ax2.draw_artist(f_line)
ax2.draw_artist(f_line2)
ax2.draw_artist(f_line3)
ax3.draw_artist(t_line)
# fill in the axes rectangle
fig.canvas.blit(fig.bbox)
count+=1
x = np.arange(count,count+50,1)
# tops out at about 25 fps :|
print ("Total time for 1 plot is: ",(time.time() - tstart))
The following code executes without warnings on my laptop.
ax = plt.subplot(311)
ax.set_xlim(0, 50)
ax.set_ylim(-2, 2)
ax.set_title("Raw acceleration data")
ax.set_ylabel("g$/m^2$",fontsize=18)
I removed ax.hold(True) and changed "311" to 311.
I use Python 3.43 and Matplotlib 1.5.0.
I created a small example:
# -*- coding: utf-8 -*-
import matplotlib
matplotlib.use("Qt5Agg")
matplotlib.use("Svg")
import matplotlib.pyplot as plt
txts = ['Bau', 'Landwirtschaft', 'Handel', 'Logistik', 'Handwerk', 'Gaststätten', 'Freiberufler', 'Dienstleistungen', 'Finanzanbieter', 'Handel', 'Einzelhandel', 'Vertrieb', 'Touristik', 'sonstige']
sizes = [104, 351, 1339, 456, 831, 661, 465, 323, 304, 294, 152, 133, 1006, 631]
ch_farben = ['#FF0000', '#0064EB', '#FFD700', '#00FF00', '#00CED1', '#006400', '#556B2F', '#87CEEB', '#DC143C', '#FFFACD', '#99FFCC', '#CD853F', '#20B2AA', '#C71585']
#Größe Picture in Inch
width_inch = 10.0
height_inch = 10.0
# Aulösung in dpi
dpis = 100
# Rand um Diagramm in Pixel
rand = 50
#Breite des Balkens >0 und <= 1
bar_width = 0.8
xpos = ()
lg_beschr = []
cnt_bars = len(sizes)
ymax =max(sizes)
smm = sum(sizes)
ymax = ymax
nc = cnt_bars // 10 + 1
for j in range(cnt_bars):
if smm != 0:
sprz = "%2.1f%%" % (100 * sizes[j]/smm)
if len(sprz) > 0:
lg_beschr.append(txts[j] + " (" + sprz + ")")
else:
lg_beschr.append(txts[j])
xpos = xpos + (j + (1 - bar_width)/2,)
br =cnt_bars
d = dict(left=xpos, width=bar_width, height= sizes, bottom=0, color=ch_farben)
sp111 =plt.subplot(111)
bars = sp111.bar(**d )
fig = plt.gcf()
fig.dpi = dpis
fig.set_figwidth(width_inch)
fig.set_figheight(height_inch)
rdx = rand / (width_inch * dpis)
rdy = rand / (height_inch * dpis)
fig.subplots_adjust(bottom=rdy, top=1.0-rdy, left=rdx, right=1.0-rdx)
sp111.set_position([0.05, 0.05, 0.72, 0.72])
ax = plt.gca()
chart_leg = ax.legend(bars, lg_beschr, loc='lower left', bbox_to_anchor=(0.0, 1.0), frameon= True, fontsize =14, ncol=nc, borderaxespad=0.1)
plt.draw()
#Speichern in svg-Dateien
plt.savefig("D:/TMP/test_diag.svg", format="svg", transparent=True, dpi=dpis)
plt.savefig("D:/TMP/test_diag.png", format="png", transparent=True, dpi=dpis)
plt.show()
plt.close()
All works fine, but if I have more values like 25..30 items, so the legend is bigger. I have to change the last two parameter for
sp111.set_position([0.05, 0.05, 0.72, 0.72])
manually to smaller values to get all of the legend. Is there a possibility to
automate this?
Is there a option to compute the size and location of the legend (in pixel, inch or axes coordinates)?
I'm creating a interactive chart with the seaborn package.
It's a simple chart with dates on the x axis and value from 0 to 5 on the y axis
I can move a cursor-bar over it left and right, with arrow keys and set the y value of the chart with num keys (and export to csv the charts y values with their timestamp).
However when large date ranges are used the program becomes incredibly slow.
I press the arrow keys to move the cursor one bar but it can take one or 2 seconds to react. (the key control are done with PyQT)
Any idea what i might do to speed it up?
Please feel free to copy paste the code and run it in python to see the program:
import matplotlib.pyplot as plt
import matplotlib
import pandas as pd
from datetime import timedelta, date
import numpy as np
matplotlib.use('Qt4Agg')
import seaborn as sns
from matplotlib.widgets import Button
import matplotlib.lines
from matplotlib.lines import Line2D
import csv
from itertools import izip
dates = []
values = []
sns.set(style="ticks")
fig = plt.figure(1, figsize=(25,7))
fig.clf()
ax = fig.add_subplot(111)
fig.canvas.draw()
plt.ylim(0,5)
horizontal_position = 0
periods = 365
idx = pd.DatetimeIndex(start='2010-01-01', freq='d', periods=periods)
index_delete = []
for i in range(idx.size):
if idx[i].dayofweek == 6 or idx[i].dayofweek == 5:
index_delete.append(i)
idx = idx.delete(index_delete)
periods = idx.size
idx_x_array = np.array(range(idx.size), dtype=np.int32)
str_vals = []
first_day_lines = []
counter = 0
if periods > 170:
for s in idx._data:
s = str(s)
day = s[8:10]
month = s[5:7]
year = s[0:4]
if day == '01':
dotted_line_f = plt.Line2D((counter, counter), (0, 5), lw=2., marker='.',
color='gray')
first_day_lines.append(dotted_line_f)
date_str = day+'/'+month+'/'+year
str_vals.append(date_str)
elif idx.dayofweek[counter]:
date_str = day+'/'+month
str_vals.append(date_str)
else:
str_vals.append('')
counter +=1
if periods <= 170:
for s in idx._data:
s = str(s)
day = s[8:10]
month = s[5:7]
year = s[0:4]
if day == '01':
dotted_line_f = plt.Line2D((counter, counter), (0, 5), lw=2., marker='.',
color='gray')
first_day_lines.append(dotted_line_f)
date_str = day+'/'+month+'/'+year
str_vals.append(date_str)
else:
date_str = day+'/'+month
str_vals.append(date_str)
counter +=1
plt.grid(True)
plt.xticks(idx_x_array, str_vals, rotation='vertical', fontsize=7)
values = []
for i in idx_x_array:
values.append(0)
data= pd.DataFrame({('A','a'):values}, idx)
sns.set_context(context={"figure.figsize":(5,5)})
ab = sns.tsplot(data.T.values, idx_x_array)
ab.lines[0].set_color('red')
# x_len = len(ab.lines[0]._x)
ab.lines[0]._x = idx_x_array
dotted_line = plt.Line2D((1, 1), (0, 5), lw=2.,
ls='-.', marker='.',
markersize=1,
color='black',
markerfacecolor='black',
markeredgecolor='black',
alpha=0.5)
ab.add_line(dotted_line)
for line in first_day_lines:
ab.add_line(line)
lines = ab.lines
init_focus = ab.lines[0]
index_focus = 0
bbox_props = dict(boxstyle="rarrow,pad=0.3", fc="pink", ec="b", lw=2)
horizontal_position = init_focus._x[index_focus]
plt.subplots_adjust(bottom=.30, left=.03, right=.97, top=.90, hspace=.35)
analysis_label = 'Analysis mode'
discovery_label = 'Discovery mode'
def chart_mode(event):
global button_label
global dotted_line
global power
global horizontal_position
global index_focus
global dotted_line
global idx
if button_label == analysis_label:
index_focus = 0
button_label = discovery_label
plt.draw()
elif button_label == discovery_label:
index_focus = periods-1
button_label = analysis_label
plt.draw()
bnext.label.set_text(button_label)
horizontal_position = ab.lines[0]._x[index_focus]
dotted_line = plt.Line2D((horizontal_position,horizontal_position), (0, 5), lw=5.,
ls='-.', marker='.',
markersize=1,
color='black',
markerfacecolor='black',
markeredgecolor='black',
alpha=0.5)
ax.add_line(dotted_line)
new_line = ax.lines.pop()
ax.lines[1] = new_line
def export_csv(event):
x_data = idx._data
y_data = ab.lines[0]._y
x_data_proc = []
for x in x_data:
x = str(x)
day = x[8:10]
month = x[5:7]
year = x[0:4]
date_str = day+'/'+month
x_data_proc.append(date_str)
y_data_proc = []
for y in y_data:
y_data_proc.append(int(y))
with open('some.csv', 'wb') as f:
writer = csv.writer(f)
writer.writerows(izip(x_data_proc, y_data_proc))
button_label = analysis_label
axnext = plt.axes([0.1, 0.05, 0.1, 0.075])
bnext = Button(axnext, button_label)
bnext.on_clicked(chart_mode)
axexport = plt.axes([0.21, 0.05, 0.1, 0.075])
bexport = Button(axexport, 'export csv')
bexport.on_clicked(export_csv)
def on_keyboard(event):
global power
global horizontal_position
global index_focus
global dotted_line
global idx
if event.key == 'right':
if index_focus < periods-1:
index_focus+=1
else:
idx = idx + timedelta(days=1)
index_focus+=1
elif event.key == 'left':
if index_focus > 0:
index_focus-=1
elif event.key == 'up':
if index_focus < periods-5:
index_focus+=5
elif event.key == 'down':
if index_focus > 5:
index_focus-=5
elif is_number(event.key):
for i in range(len(ab.lines[0]._y[index_focus::])):
ab.lines[0]._y[index_focus+i] = event.key
horizontal_position = ab.lines[0]._x[index_focus]
dotted_line = plt.Line2D((horizontal_position,horizontal_position), (0, 5), lw=2.,
ls='-.', marker='.',
markersize=1,
color='black',
markerfacecolor='black',
markeredgecolor='black',
alpha=0.5)
ax.add_line(dotted_line)
new_line = ax.lines.pop()
ax.lines[1] = new_line
fig.canvas.draw()
plt.show()
def is_number(s):
try:
float(s)
return True
except ValueError:
return False
plt.gcf().canvas.mpl_connect('key_press_event', on_keyboard)
plt.show()
I'm afraid this code is too long for me to plough through.
Nonetheless, a couple of easy ways to help find bottlenecks:
interrupt the slow program, and look at the stack trace; repeat 5 times.
In your case these will have lots of incomprehensible calls in Qt4 etc.,
but you might be able to see what your code is calling that's slow.
good old print: add e.g. print "%.3f %s" % (time.time() - t0, event.key) in on_keyboard .
Then, comment out the drawing stuff, print only, run blind: is the time spent in drawing,
or somewhere else ?
Also, why Qt4Agg -- is TkAgg just as slow ?
Also, what does "when large date ranges are used" mean -- how large ?
I am getting a very strange error using basemap. No error appears, yet my 3rd plot has no data plotted when data does indeed exist. Below is my code. When run, you will see that both modis and seawifs data is plotted, but viirs is not. I can't figure out why.
import numpy as np
import urllib
import urllib2
import netCDF4
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
from datetime import datetime, date, time, timedelta
import json
import math
def indexsearch(datebroken,year, month, day):
for i in range(0,len(datebroken)):
if (datebroken[i,0] == year and datebroken[i,1] == month and datebroken[i,2] == day):
return i
url = 'http://coastwatch.pfeg.noaa.gov/erddap/griddap/erdMWchlamday.nc?chlorophyll' +\
'[(2002-07-16T12:00:00Z):1:(2015-04-16T00:00:00Z)][(0.0):1:(0.0)][(36):1:(39)][(235):1:(240)]'
file = 'erdMWchlamday.nc'
urllib.urlretrieve(url, file)
ncfilemod = netCDF4.Dataset(file)
ncv1 = ncfilemod.variables
print ncv1.keys()
time1=ncv1['time'][:]
inceptiondate = datetime(1970, 1, 1, 0, 0, 0)
timenew1=[]
for i in time1[:]:
newdate = inceptiondate + timedelta(seconds=i)
timenew1.append(newdate.strftime('%Y%m%d%H'))
datebroken1 = np.zeros((len(timenew1),4),dtype=int)
for i in range(0,len(timenew1)):
datebroken1[i,0] = int(timenew1[i][0:4])
datebroken1[i,1] = int(timenew1[i][4:6])
datebroken1[i,2] = int(timenew1[i][6:8])
datebroken1[i,3] = int(timenew1[i][8:10])
lon1= ncv1['longitude'][:]
lat1 = ncv1['latitude'][:]
lons1, lats1 = np.meshgrid(lon1,lat1)
chla1 = ncv1['chlorophyll'][:,0,:,:]
url = 'http://coastwatch.pfeg.noaa.gov/erddap/griddap/erdSWchlamday.nc?chlorophyll' +\
'[(1997-09-16):1:(2010-12-16T12:00:00Z)][(0.0):1:(0.0)][(36):1:(39)][(235):1:(240)]'
file = 'erdSWchlamday.nc'
urllib.urlretrieve(url, file)
#Ncfile 2
ncfilewif = netCDF4.Dataset(file)
ncv2 = ncfilewif.variables
print ncv2.keys()
time2=ncv2['time'][:]
inceptiondate = datetime(1970, 1, 1, 0, 0, 0)
timenew2=[]
for i in time2[:]:
newdate = inceptiondate + timedelta(seconds=i)
timenew2.append(newdate.strftime('%Y%m%d%H'))
datebroken2 = np.zeros((len(timenew2),4),dtype=int)
for i in range(0,len(timenew2)):
datebroken2[i,0] = int(timenew2[i][0:4])
datebroken2[i,1] = int(timenew2[i][4:6])
datebroken2[i,2] = int(timenew2[i][6:8])
datebroken2[i,3] = int(timenew2[i][8:10])
lon2= ncv2['longitude'][:]
lat2 = ncv2['latitude'][:]
lons2, lats2 = np.meshgrid(lon2,lat2)
chla2 = ncv2['chlorophyll'][:,0,:,:]
url = 'http://coastwatch.pfeg.noaa.gov/erddap/griddap/erdVH2chlamday.nc?chla' +\
'[(2012-01-15):1:(2015-05-15T00:00:00Z)][(39):1:(36)][(-125):1:(-120)]'
file = 'erdVH2chlamday.nc'
urllib.urlretrieve(url, file)
ncfileviir = netCDF4.Dataset(file)
ncv3 = ncfileviir.variables
print ncv3.keys()
time3=ncv3['time'][:]
inceptiondate = datetime(1970, 1, 1, 0, 0, 0)
timenew3=[]
for i in time3[:]:
newdate = inceptiondate + timedelta(seconds=i)
timenew3.append(newdate.strftime('%Y%m%d%H'))
datebroken3 = np.zeros((len(timenew3),4),dtype=int)
for i in range(0,len(timenew3)):
datebroken3[i,0] = int(timenew3[i][0:4])
datebroken3[i,1] = int(timenew3[i][4:6])
datebroken3[i,2] = int(timenew3[i][6:8])
datebroken3[i,3] = int(timenew3[i][8:10])
lon3= ncv3['longitude'][:]
lat3 = ncv3['latitude'][:]
lons3, lats3 = np.meshgrid(lon3,lat3)
chla3 = ncv3['chla'][:,:,:]
i1=indexsearch(datebroken1,2012,6,16)
print i1
i2=indexsearch(datebroken2,2010,6,16)
print i2
i3=indexsearch(datebroken3,2012,6,15)
print i3
chla1plot = chla1[i1,:,:]
chla2plot = chla2[i2,:,:]
chla3plot = chla3[i3,:,:]
ncfileviir.close()
ncfilemod.close()
ncfilewif.close()
Important code is below here. All code above is just pulling the data into python to plot.
minlat = 36
maxlat = 39
minlon = 235
maxlon = 240
# Create map
fig = plt.figure()
#####################################################################################################################
#plot figure 1
ax1 = fig.add_subplot(221)
m = Basemap(projection='merc', llcrnrlat=minlat,urcrnrlat=maxlat,llcrnrlon=minlon, urcrnrlon=maxlon,resolution='h')
cs1 = m.pcolormesh(lons1,lats1,chla1plot,cmap=plt.cm.jet,latlon=True)
m.drawcoastlines()
m.drawmapboundary()
m.fillcontinents()
m.drawcountries()
m.drawstates()
m.drawrivers()
#Sets up parallels and meridians.
parallels = np.arange(36.,39,1.)
# labels = [left,right,top,bottom]
m.drawparallels(parallels,labels=[False,True,True,False])
meridians = np.arange(235.,240.,1.)
m.drawmeridians(meridians,labels=[True,False,False,True])
ax1.set_title('Modis')
#####################################################################################################################
#plot figure 2
ax2 = fig.add_subplot(222)
cs2 = m.pcolormesh(lons2,lats2,chla2plot,cmap=plt.cm.jet,latlon=True)
m.drawcoastlines()
m.drawmapboundary()
m.fillcontinents()
m.drawcountries()
m.drawstates()
m.drawrivers()
#Sets up parallels and meridians.
parallels = np.arange(36.,39,1.)
# labels = [left,right,top,bottom]
m.drawparallels(parallels,labels=[False,True,True,False])
meridians = np.arange(235.,240.,1.)
m.drawmeridians(meridians,labels=[True,False,False,True])
ax2.set_title('SeaWIFS')
#####################################################################################################################
#plot figure 3
ax3 = fig.add_subplot(223)
cs3 = m.pcolormesh(lons3,np.flipud(lats3),np.flipud(chla3plot),cmap=plt.cm.jet,latlon=True)
m.drawcoastlines()
m.drawmapboundary()
m.fillcontinents()
m.drawcountries()
m.drawstates()
m.drawrivers()
#Sets up parallels and meridians.
parallels = np.arange(36.,39,1.)
# labels = [left,right,top,bottom]
m.drawparallels(parallels,labels=[False,True,True,False])
meridians = np.arange(235.,240.,1.)
m.drawmeridians(meridians,labels=[True,False,False,True])
ax3.set_title('VIIRS')
# Save figure (without 'white' borders)
#plt.savefig('SSTtest.png', bbox_inches='tight')
plt.show()
My results are shown here!
![results]: http://i.stack.imgur.com/dRjkU.png
The issue that I found was that I had
minlat = 36
maxlat = 39
minlon = 235
maxlon = 240
m = Basemap(projection='merc', llcrnrlat=minlat,urcrnrlat=maxlat,llcrnrlon=minlon, urcrnrlon=maxlon,resolution='h')
The final plot was -125 to -120 which basemap did not automatically handle, but instead placed the plot at an area where I did not have data. I added a new m = basemap statement and changed the meridian numbers for the third graph using -125 to -120 as my longitude and the graph plotted just fine.