Input Format to pcolormesh - matplotlib

I'm attempting to make heat/intensity map using Basemap. My inputs are a set of lats, lons, and intensity at that point. The dataset looks like this:
lat[0], lon[0] = intensity[0]
lat[1], lon[1] = intensity[1]
...
lat[n], lon[n] = intensity[n]
At each index the lat and lon correspond to the correct sensor reading. My code looks something like this:
fig = plt.figure(figsize=(10, 8))
# Set title
fig.suptitle("Intensities {} {}".format(start_time, stop_time))
# US Centered Map
map_axis = fig.add_subplot(111)
map = Basemap(
ax = map_axis,
lat_0 = 40, lon_0 = -95,
width = 6500e3, height = 6500e3,
projection = 'stere',
resolution = 'l'
)
map.drawcoastlines()
lats = ...
lons = ...
intn = ...
# Convert coordinates
lons, lats = map(lons, lats)
LONS, LATS = np.meshgrid(lons, lats)
map.pcolormesh(
LONS, LATS,
intn,
vmin = 0, vmax = 100
)
fig.savefig(file_name)
plt.close(fig)
This code never completes. I've successfully plotted the Basemap by itself. The pcolormesh is what is failing. The program crashes with this error.
$ ./plot_intensities.py
Running 2013-04-10 00:02:30 2013-04-10 00:02:45
Traceback (most recent call last):
File "./plot_intensities.py", line 151, in <module>
make_maps(samples)
File "./plot_intensities.py", line 144, in make_maps
make_map(bin_samples, start, walk)
File "./plot_intensities.py", line 117, in make_map
vmin = 0, vmax = 100
File "/usr/lib/python3/dist-packages/mpl_toolkits/basemap/__init__.py", line 521, in with_transform
return plotfunc(self,x,y,data,*args,**kwargs)
File "/usr/lib/python3/dist-packages/mpl_toolkits/basemap/__init__.py", line 3418, in pcolormesh
ret = ax.pcolormesh(x,y,data,**kwargs)
File "/usr/lib/python3/dist-packages/matplotlib/__init__.py", line 1814, in inner
return func(ax, *args, **kwargs)
File "/usr/lib/python3/dist-packages/matplotlib/axes/_axes.py", line 5395, in pcolormesh
X, Y, C = self._pcolorargs('pcolormesh', *args, allmatch=allmatch)
File "/usr/lib/python3/dist-packages/matplotlib/axes/_axes.py", line 4995, in _pcolorargs
numRows, numCols = C.shape
ValueError: not enough values to unpack (expected 2, got 1)
I understand that my data, the third argument intn is not formatted correctly. I cannot find any documentation as to how I should shape that list. How do I format it to the correct shape?
Thanks.

As you know, pcolormesh is used to plot a quadrilateral mesh by creating a pseudocolor plot of a 2-D array. The error details indeed indicated that: at line numRows, numCols = C.shape, it expect C to be a 2-D array, while the C you provided seems to be a 1-D array, judging from ValueError: not enough values to unpack (expected 2, got 1). The dataset you introduced seems to me having only intensity values on the diagonal (where lat == lon). To get a colormesh, you need to at least extend intensity data into 2-D array and somehow fill in missing values. For example:
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
import numpy as np
fig = plt.figure(figsize=(10, 8))
# Set title
fig.suptitle("Intensities {} {}".format('start_time', 'stop_time'))
# US Centered Map
map_axis = fig.add_subplot(111)
map = Basemap(
ax = map_axis,
lat_0 = 40, lon_0 = -95,
width = 6500e3, height = 6500e3,
projection = 'stere',
resolution = 'l'
)
map.drawcoastlines()
# Tried my best to simulate your data example. Don't be surprise if the result is ugly ...
nstep = 1
lats = np.arange(map.latmin, map.latmax, nstep)
lons = np.arange(map.lonmin, map.lonmax, nstep)
l = min(len(lats), len(lons))
lats = lats[:l]
lons = lons[:l]
intn = np.random.randint(0, 100, size=l)
# Convert coordinates
lons, lats = map(lons, lats)
LONS, LATS = np.meshgrid(lons, lats)
# The following 3 lines are just an example of the minimum you got to do before it works.
intn_array = np.zeros(LONS.shape)
for i in range(l):
intn_array[i, i] = intn[i]
intn = intn_array
map.pcolormesh(
LONS, LATS,
intn_array,
vmin = 0, vmax = 100
)
plt.show()

Related

I can't use coordinate values in list for hough line function

I want to use the Hough line function. When I look at my list, yes, I found the coordinate values of the edges, but when I want to plot it in a for loop, I get an error. Here is the error message: TypeError: 'numpy.ndarray' object is not callable
import cv2
import numpy as np
img = cv2.imread("a.png")
img = cv2.resize(img,(640,480))
# cap = cv2.VideoCapture(0)
while True:
# ret, frame = cap.read()
# frame = cv2.flip(frame,1)
# print(frame.shape) # 480,640
ycrbc = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)
minYCrCb = np.array([0,140,90],np.uint8)
maxYCrCb = np.array([230,170,120],np.uint8)
imgeYCrCb = cv2.cvtColor(img,cv2.COLOR_BGR2YCR_CB)
skinRegionYCrCb = cv2.inRange(imgeYCrCb,minYCrCb,maxYCrCb)
skinYCrCb = cv2.bitwise_and(img, img, mask = skinRegionYCrCb)
median_ycrcb = cv2.medianBlur(skinYCrCb, 3)
_, esik = cv2.threshold(median_ycrcb, 20, 255, cv2.THRESH_BINARY)
median_binary = cv2.medianBlur(esik, 7)
gray = cv2.cvtColor(median_binary, cv2.COLOR_BGR2GRAY)
contours, hierarchy = cv2.findContours(gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
areas = [cv2.contourArea(c) for c in contours]
max_index = np.argmax(areas)
x,y,w,h = cv2.boundingRect(contours[max_index])
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
mask = np.zeros_like(gray_img)
mask[y:h, x:w] = 255
masked_image = cv2.bitwise_and(gray_img, mask)
edges = cv2.Canny(gray,75,250)
lines = cv2.HoughLinesP(edges, 1, np.pi/180, 50)
print(lines)
for line in lines:
x1, y1, x2, y2 = line[0]
cv2.line(img(x1, y1), (x2, y2), (0,255,0), 2)
# height, width = h, w
# region_of_interest_vertices = [(width/4, 11*height/12), (width/4, 13*height/16), (3*width/4, 13*height/16), (3*width/4, 11*height/12)]
cv2.imshow("ycrbc",ycrbc)
cv2.imshow("skinYCrCb",median_ycrcb)
cv2.imshow("binary goruntu", esik)
cv2.imshow("median_binary", median_binary)
cv2.imshow("Kesilmis Goruntu",masked_image)
cv2.imshow("Edges",edges)
if cv2.waitKey(5) & 0xFF == ord("q"):
break
# cap.release()
cv2.destroyAllWindows()
I want to draw the edges, then I will try to produce results from the output I get

AttributeError: 'Axes' object has no attribute 'get_proj' in matplotlib

I am making the representation of a polynom function.
I have an error in a matplotlib code and cannot understand where it is coming from. any advice is welcome.
I tried already Gtk3agg but nothing changed.
Below is the failure code.
For any reason 'get_proj' dont work here for creating labels.
And: when I use ax.get_proj() instead,
a) all labels appear bottom left
b) not all labels appear at bottom left (all points are identified by the cursor bot the labels are not written at the bottom left).
The final project will be (few things still to be done):
- on button -> labelling with coordinate appear at each cursor movement (temporary)
- click right button, the labels will be persistent till button clear is clicked
- off button -> no labelling appear
My feeling: the 3x button creation is messing anything up.
# -*- coding: utf-8 -*-
import matplotlib as mpl
from mpl_toolkits.mplot3d.proj3d import proj_transform
import matplotlib.pyplot as plt
from matplotlib.widgets import Button
import numpy as np
mpl.use('tkagg')
def distance(point, event):
plt.sca(ax) # <------------------ introduce this one !!!!!!!!!!!!!!!!!!!!!!!!!!!
x2, y2, _ = proj_transform(point[0], point[1], point[2], plt.gca().get_proj())
x3, y3 = ax.transData.transform((x2, y2))
return np.sqrt ((x3 - event.x)**2 + (y3 - event.y)**2)
def calcClosestDatapoint(X, event):
distances = [distance(X[i, 0:3], event) for i in range(Sol)]
return np.argmin(distances)
#
def annotatePlot(X, index):
global last_mark, generated_labels
if activated_labelling:
x2, y2, _ = proj_transform(X[index, 0], X[index, 1], X[index, 2], ax.get_proj())
last_mark = plt.annotate(generated_labels[index],
xy = (x2, y2), xytext = (-20, 20), textcoords = 'offset points', ha = 'right', va = 'bottom',
bbox = dict(boxstyle = 'round,pad=0.5', fc = 'yellow', alpha = 0.5),
arrowprops = dict(arrowstyle = '->', connectionstyle = 'arc3,rad=0'))
fig.canvas.draw()
#
def onMouseMotion(event):
global Coord
if activated_labelling:
closestIndex = calcClosestDatapoint(Coord, event)
last_mark.remove()
annotatePlot(Coord, closestIndex)
def show_on(event):
global activated_labelling, last_mark,pid,mid
if activated_labelling == False:
activated_labelling = True
x2, y2, _ = proj_transform(Coord[0,0], Coord[0,1], Coord[0,2], ax.get_proj())
last_mark = plt.annotate("3D measurement on " + generated_labels[0],
xy = (x2, y2), xytext = (-20, 20), textcoords = 'offset points', ha = 'right', va = 'bottom',
bbox = dict(boxstyle = 'round,pad=0.5', fc = 'yellow', alpha = 0.5),
arrowprops = dict(arrowstyle = '->', connectionstyle = 'arc3,rad=0'))
mid = fig.canvas.mpl_connect('motion_notify_event', onMouseMotion)
#
def show_off(event):
global activated_labelling
'''
deactivate the persistent XYZ position labels at the grafic
'''
if activated_labelling:
activated_labelling = False
last_mark.remove()
fig.canvas.draw()
fig.canvas.mpl_disconnect(mid)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
#ax = fig.gca(projection='3d')
activated_labelling = False
Wide = 100
Minimum = -50
ScanLimit = 3 # searching between o and 3; 4 and 5 are no solutions
Search = 45
Coord=[]
values=[]
generated_labels = []
#
XMin = 0
XMax = 0
YMin = 0
YMax = 0
ZMin = 0
ZMax = 0
# count the solutions found in the scan area defined above
Sol=0
for i in range(Wide+1):
for j in range(Wide+1):
for k in range(Wide+1):
########################################################################
########################################################################
####
#### THIS IS THE POLYNOM TO BE REPRESENTED
####
param_dens = ((i+Minimum)**3)+((j+Minimum)**3)+((k+Minimum)**3) -Search
if abs(param_dens) <= abs(ScanLimit):
Coord.append([i+Minimum,j+Minimum,k+Minimum])
if ScanLimit !=0:
values.append([abs(param_dens)])
labelling = "value {}\nin X:{} Y:{} Z:{}".format(Search+param_dens,i+Minimum,j+Minimum,k+Minimum)
generated_labels.append(labelling)
print(labelling+"\n")
# increase the number indicating the solutions found
Sol +=1
# for centering the window
if XMin > i+Minimum:
XMin = i+Minimum
if YMin > j+Minimum:
YMin = j+Minimum
if ZMin > k+Minimum:
ZMin = k+Minimum
if XMax < i+Minimum:
XMax = i+Minimum
if YMax < j+Minimum:
YMax = j+Minimum
if ZMax < k+Minimum:
ZMax = k+Minimum
print('######################################################')
print('## statistics / move this to a parallel search engine?')
print('## search ')
print("## total solution %d for searching center %d" % (Sol,Search))
print("## from %d to %d" % (Search-ScanLimit,Search+ScanLimit))
print("## from %d to %d" % (Minimum,Wide+Minimum))
print('##')
print('#######################################################')
#
values = np.array(values, dtype='int64')
Coord = np.array(Coord, dtype='int64')
#
if ScanLimit !=0:
cmap = plt.cm.jet # define the colormap
# extract all colors from the .jet map
cmaplist = [cmap(i) for i in range(cmap.N)]
# force the first color entry to be black
cmaplist[0] = (0, 0, 0, 1.0)
# create the new map
cmap = mpl.colors.LinearSegmentedColormap.from_list('Custom cmap', cmaplist, cmap.N)
# define the bins and normalize
bounds = np.linspace(0, ScanLimit, ScanLimit+1)
norm = mpl.colors.BoundaryNorm(bounds, cmap.N)
# create a second axes for the colorbar
ax2 = fig.add_axes([0.95, 0.1, 0.03, 0.8])
cb = mpl.colorbar.ColorbarBase(ax2, cmap=cmap, norm=norm,
spacing='proportional', ticks=bounds, boundaries=bounds, format='%1i')
#
ax.set_xlim3d(XMin-5, XMax+5)
ax.set_ylim3d(YMin-5, YMax+5)
ax.set_zlim3d(ZMin-5, ZMax+5)
#
ax.set_xlabel('X X')
ax.set_ylabel('Y Y')
ax.set_zlabel('Z Z')
ax.set_aspect(aspect=1)
# extract the scatterplot drawing in a separate function so we ca re-use the code
def draw_scatterplot():
if ScanLimit !=0:
ax.scatter3D(Coord[:,0], Coord[:,1], Coord[:,2], s=20, c=values[:,0], cmap=cmap, norm=norm)
else:
ax.scatter3D(Coord[:,0], Coord[:,1], Coord[:,2], s=20, c='green')
# draw the initial scatterplot
draw_scatterplot()
# create the "on" button, and place it somewhere on the screen
ax_on = plt.axes([0.0, 0.0, 0.1, 0.05])
button_on = Button(ax_on, 'on')
#
ax_off = plt.axes([0.12, 0.0, 0.1, 0.05])
button_off = Button(ax_off, 'off')
#
#ax_off = plt.axes([0.24, 0.0, 0.1, 0.05])
#button_off = Button(ax_off, 'off')
# link the event handler function to the click event on the button
button_on.on_clicked(show_on)
button_off.on_clicked(show_off)
#fig.colorbar(img)
plt.show()
Traceback (most recent call last):
File "C:\Program Files\Anaconda3\lib\site-packages\matplotlib\cbook\__init__.py", line 388, in process
proxy(*args, **kwargs)
File "C:\Program Files\Anaconda3\lib\site-packages\matplotlib\cbook\__init__.py", line 228, in __call__
return mtd(*args, **kwargs)
File "C:/Users/../Desktop/heat.py", line 137, in onClick
closestIndex,LowestDistance = calcClosestDatapoint(Coord, event)
File "C:/Users/../Desktop/heat.py", line 50, in calcClosestDatapoint
distances = [distance(X[i, 0:3], event) for i in range(Sol)]
File "C:/Users/../Desktop/heat.py", line 50, in <listcomp>
distances = [distance(X[i, 0:3], event) for i in range(Sol)]
File "C:/Users/../Desktop/heat.py", line 35, in distance
x2, y2, _ = proj_transform(point[0], point[1], point[2], plt.gca().get_proj())
AttributeError: 'Axes' object has no attribute 'get_proj'

matplotlib heatmap, customize y axis

Right now my code looks like this:
#generate 262*20 elements
values = np.random.random(262*20).tolist()
# convert the list to a 2D NumPy array
values = np.array(values).reshape((262, 20))
h, w = values.shape
#h=262, w=20
fig = plt.figure(num=None, dpi=80,figsize=(9, 7), facecolor='w', edgecolor='k')
ax = fig.add_subplot(111)
#fig, ax = plt.subplots()
plt.imshow(values)
plt.colorbar()
plt.xticks(np.arange(w), list('PNIYLKCVFWABCDEFGHIJ'))
ax.set_aspect(w/h)
plt.show()
The plot looks like this:
As you can see, the range of y axis is 0-261.
But I want my y axis to go from 26 to 290, missing 57, 239, and 253. So still 262 in total. I tried to generate a list like this:
mylist =[26, 27, ......missing 57, 239, 253, ....290]
plt.yticks(np.arange(h), mylist)
The Y axis just looks like everything squished together.
So I tried:
pylab.ylim([26, 290])
And It looks like this:
So it just feels like the data in first row always corresponds to [0], not to [26]
Suggest you use pcolormesh. If you want gaps, then use an numpy.ma.masked array for the area with gaps.
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import numpy as np
values = np.random.rand(290,20)
values[:26, :] = np.NaN
values[ [57, 239, 253], :] = np.NaN
values = np.ma.masked_invalid(values)
h, w = values.shape
fig, ax = plt.subplots(figsize=(9,7))
# Make one larger so these values represent the edge of the data pixels.
y = np.arange(0, 290.5)
x = np.arange(0, 20.5)
pcm = ax.pcolormesh(x, y, values, rasterized=True) # you don't need rasterized=True
fig.colorbar(pcm)
plt.xticks(np.arange(w), list('PNIYLKCVFWABCDEFGHIJ'))
plt.show()
Result
EDIT: If you want to just work w/ a 262x20 array:
values = np.random.rand(262,20)
h, w = values.shape
fig, ax = plt.subplots(figsize=(9,7))
# Make one larger so these values represent the edge of the data pixels.
y = np.arange(0, 290.5)
y = np.delete(y, [57, 239, 253])
y = np.delete(y, range(26))
x = np.arange(0, 20.5)
pcm = ax.pcolormesh(x, y, values, rasterized=True) # you don't need rasterized=True
fig.colorbar(pcm)
plt.xticks(np.arange(w), list('PNIYLKCVFWABCDEFGHIJ'))
plt.show()
Note that this doesn't put a blank line at 57, 239 and 253. If you want that, you need to do:
values = np.random.rand(262,20)
Z = np.ones((290, 20)) * np.NaN
inds = set(range(290)) - set(list(range(26)) + [57, 239, 253])
for nn, ind in enumerate(inds):
Z[ind, :] = values[nn,:]
h, w = values.shape
fig, ax = plt.subplots(figsize=(9,7))
# Make one larger so these values represent the edge of the data pixels.
y = np.arange(0, 290.5)
x = np.arange(0, 20.5)
pcm = ax.pcolormesh(x, y, Z, rasterized=True) # you don't need rasterized=True
fig.colorbar(pcm)
plt.xticks(np.arange(w), list('PNIYLKCVFWABCDEFGHIJ'))
plt.show()

Colormap is not categorizing the data properly

Here is my script to plot data from a Geogtiff file using basemap. The data is categorical and there are 13 categories within this domain. The problem is that some categories get bunched up into one colour and thus some resolution is lost.
Unfortunately, I do not know how to fix this. I read that plt.cm.get_cmp is better for discrete datasets but I have not gotten it to work unfortunately.
gtif = 'some_dir'
ds = gdal.Open(gtif)
data = ds.ReadAsArray()
gt = ds.GetGeoTransform()
proj = ds.GetProjection()
xres = gt[1]
yres = gt[5]
xmin = gt[0] + xres
xmax = gt[0] + (xres * ds.RasterXSize) - xres
ymin = gt[3] + (yres * ds.RasterYSize) + yres
ymax = gt[3] - yres
xy_source = np.mgrid[xmin:xmax+xres:xres, ymax+yres:ymin:yres]
ds = None
fig2 = plt.figure(figsize=[12, 11])
ax2 = fig2.add_subplot(111)
ax2.set_title("Land use plot")
bm2 = Basemap(ax=ax2,projection='cyl',llcrnrlat=ymin,urcrnrlat=ymax,llcrnrlon=xmin,urcrnrlon=xmax,resolution='l')
bm2.drawcoastlines(linewidth=0.2)
bm2.drawcountries(linewidth=0.2)
data_new=np.copy(data)
data_new[data_new==255] = 0
nbins = np.unique(data_new).size
cb =plt.cm.get_cmap('jet', nbins+1)
img2 =bm2.imshow(np.flipud(data_new), cmap=cb)
ax2.set_xlim(3, 6)
ax2.set_ylim(50,53)
plt.show()
labels = [str(i) for i in np.unique(data_new)]
cb2=bm2.colorbar(img2, "right", size="5%", pad='3%', label='NOAH Land Use Category')
cb2.set_ticklabels(labels)
cb2.set_ticks(np.unique(data_new))
Here are the categories that are found within the domain (numbered classes):
np.unique(data_new)
array([ 0, 1, 4, 5, 7, 10, 11, 12, 13, 14, 15, 16, 17], dtype=uint8)
Thanks so much for any help here. I have also attached the output image that shows the mismatch. (not working)
First, this colormap problem is independent of the use of basemap. The following is therefore applicable to any matplotlib plot.
The problem here is that creating a colormap from n values distributes those values equally over the colormap range. Some values from the image therefore fall into the same colorrange within the colormap.
To prevent this, one can generate a colormap with the initial number of categories as shown below.
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.colors
# generate some data
data = np.array( [ 0, 1, 4, 5, 7, 10]*8 )
np.random.shuffle(data)
data = data.reshape((8,6))
# generate colormap and norm
unique = np.unique(data)
vals = np.arange(int(unique.max()+1))/float(unique.max())
cols = plt.cm.jet(vals)
cmap = matplotlib.colors.ListedColormap(cols, int(unique.max())+1)
norm=matplotlib.colors.Normalize(vmin=-0.5, vmax=unique.max()+0.5)
fig, ax = plt.subplots(figsize=(5,5))
im = ax.imshow(data, cmap=cmap, norm=norm)
for i in range(data.shape[0]):
for j in range(data.shape[1]):
ax.text(j,i,data[i,j], color="w", ha="center", va="center")
cb = fig.colorbar(im, ax=ax, norm=norm)
cb.set_ticks(unique)
plt.show()
This can be extended to exclude the colors not present in the image as follows:
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.colors
# generate some data
data = np.array( [ 0, 1, 4, 5, 7, 10]*8 )
np.random.shuffle(data)
data = data.reshape((8,6))
unique, newdata = np.unique(data, return_inverse=1)
newdata = newdata.reshape(data.shape)
# generate colormap and norm
new_unique = np.unique(newdata)
vals = np.arange(int(new_unique.max()+1))/float(new_unique.max())
cols = plt.cm.jet(vals)
cmap = matplotlib.colors.ListedColormap(cols, int(new_unique.max())+1)
norm=matplotlib.colors.Normalize(vmin=-0.5, vmax=new_unique.max()+0.5)
fig, ax = plt.subplots(figsize=(5,5))
im = ax.imshow(newdata, cmap=cmap, norm=norm)
for i in range(newdata.shape[0]):
for j in range(newdata.shape[1]):
ax.text(j,i,data[i,j], color="w", ha="center", va="center")
cb = fig.colorbar(im, ax=ax, norm=norm)
cb.ax.set_yticklabels(unique)
plt.show()

Matplotlib multiple animate multiple lines

I have been researching on how to animate multiple lines for a flight path. The object it that I read multiple GPS files time sync them them animate each path with respect to time. I found how to animate one line using append in the animate functions. Now I need to add a second and third for as many files are imported.
I know the problem is somewhere in how I perform the set_data with the lines. I ahve seen multiple example but I do not understand what structure is required to set up multiple lines. Yes I am a newbie.
fig = plt.figure()
ax1 = plt.axes(xlim=(-108, -104), ylim=(31,34))
line, = ax1.plot([], [], lw=2)
plt.xlabel('Longitude')
plt.ylabel('Latitude')
plotlays, plotcols = [2], ["black","red"]
lines = []
for index in range(2):
lobj = ax1.plot([],[],lw=2,color=plotcols[index])[0]
lines.append(lobj)
def init():
for line in lines:
line.set_data([],[])
return lines
x1,y1 = [],[]
x2,y2 = [],[]
frame_num = len(gps_data[0])
# animation function. This is called sequentially
def animate(i):
x = gps_data[0][i,3]
y = gps_data[0][i,2]
x1.append(x)
y1.append(y)
x = gps_data[1][i,3]
y = gps_data[1][i,2]
x2.append(x)
y2.append(y)
#X = np.array(x1, x2)
#Y = np.array(y1, y2)
#for index in range(0,1):
for lnum,line in enumerate(lines):
line.set_data([x1,y1, x2,y2])
return lines,
# call the animator. blit=True means only re-draw the parts that have changed.
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=frame_num, interval=1, blit=True)
plt.show()
The Matplotlib documentation for the line2d artist explains how set_data works. It "ACCEPTS: 2D array (rows are x, y) or two 1D arrays." It also works with lists. You've given it a four element list instead. You need to set the x and y data of each line separately. I've included an example with fake data below.
import matplotlib.pyplot as plt
from matplotlib import animation
from numpy import random
fig = plt.figure()
ax1 = plt.axes(xlim=(-108, -104), ylim=(31,34))
line, = ax1.plot([], [], lw=2)
plt.xlabel('Longitude')
plt.ylabel('Latitude')
plotlays, plotcols = [2], ["black","red"]
lines = []
for index in range(2):
lobj = ax1.plot([],[],lw=2,color=plotcols[index])[0]
lines.append(lobj)
def init():
for line in lines:
line.set_data([],[])
return lines
x1,y1 = [],[]
x2,y2 = [],[]
# fake data
frame_num = 100
gps_data = [-104 - (4 * random.rand(2, frame_num)), 31 + (3 * random.rand(2, frame_num))]
def animate(i):
x = gps_data[0][0, i]
y = gps_data[1][0, i]
x1.append(x)
y1.append(y)
x = gps_data[0][1,i]
y = gps_data[1][1,i]
x2.append(x)
y2.append(y)
xlist = [x1, x2]
ylist = [y1, y2]
#for index in range(0,1):
for lnum,line in enumerate(lines):
line.set_data(xlist[lnum], ylist[lnum]) # set data for each line separately.
return lines
# call the animator. blit=True means only re-draw the parts that have changed.
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=frame_num, interval=10, blit=True)
plt.show()
fig, ax1 = plt.subplots(figsize=(20,10))
plt.xticks()
ax1.set_xlabel("time")
ax1.set_ylabel("amp")
ax1.grid(True)
ox = get_data_o("/tmp/bf_ox.npy")
oy = get_data_o("/tmp/bf_oy.npy")
graphic_data = []
graphic_data.append(ax1.plot(ox, oy,"b-")[0])
sx = get_data_o("/tmp/bf_sx.npy")
i = 1
for p in sp.procs:
c = get_c(i)
sy = get_data_o("/tmp/bf_" + p + ".npy")
graphic_data.append(ax1.plot(sx, sy,c + "-")[0])
i = i + 1
def animate(i):
print ("frame")
ox = get_data_o("/tmp/bf_ox.npy")
oy = get_data_o("/tmp/bf_oy.npy")
i = 0
graphic_data[i].set_xdata(ox)
graphic_data[i].set_ydata(oy)
i = 1
sx = get_data_o("/tmp/bf_sx.npy")
for p in sp.procs:
sy = get_data_o("/tmp/bf_" + p + ".npy")
graphic_data[i].set_xdata(sx)
graphic_data[i].set_ydata(sy)
i = i + 1
return graphic_data
ani = animation.FuncAnimation(fig, animate, interval=2000, blit=True)
plt.show()