plot data points in python using pylab - python-2.7

I have data which I have to plot
X = [0,1,2,3,4,5]
Y = [6,7,8,9,10,11,12,13,14,15]
X belongs to class1, so I would want them to be plotted green in color and Y belongs to class2, so I would want them to be plotted blue in color.
What I did was,
import pylab as pl
pl.plot(X,'go')
pl.plot(Y,'bo')
pl.show()
But this is plotting X against Y. All I want to display in my graph is just the points X and Y in green and blue colors respectively.
How can I accomplish this?

It doesn't plot X against Y, if only because X and Y are not the same length. Let's say x is the variable (horizontal axis) and y the result (vertical axis). Normally you write pl.plot(x,y), where x and y are lists of the same length. If you give only one list, it assumes you only gave y and matplotlib will make an x-axis for you, something like this:
import pylab as pl
y1 = [0,1,2,3,4,5]
y2 = [6,7,8,9,10,11,12,13,14,15]
x1 = range(len(y1))
x2 = range(len(y2))
pl.plot(x1, y1,'go')
pl.plot(x2, y2,'bo')
pl.show()
So I think in your case you should define the x-axis.

Related

Matplotlib: how to animate pcolormesh with large data set

I am using matplotlib.pyplot to animate some array data. The data is in the form of an intensity map, so I have a mesh of x and y locations, and a value associated with those locations.
The difficulty is that I cannot simply update the intensity data because the x and y locations change as well.
For example, I can get something like this work, but it requires having an over-determined x and y grid first that will cover the entire range:
cax = ax.pcolormesh(x, y, G[:-1, :-1, 0],
vmin=-1, vmax=1, cmap='Blues')
fig.colorbar(cax)
def animate(i):
cax.set_array(G[:-1, :-1, i].flatten())
This works, but I end up with a fairly large intensity array filled mostly with zeros.
I have found an example here that allows the x and y values to be changed. Here is a modified MWE:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig2 = plt.figure()
x = np.arange(-9, 10)
y = np.arange(-9, 10).reshape(-1, 1)
base = np.hypot(x, y)
ims = []
for add in np.arange(15):
x = np.arange(-9+add, 10+add)
y = np.arange(-9+add, 10+add)
x, y = np.meshgrid(x, y)
ims.append((plt.pcolormesh(x, y, base + add, norm=plt.Normalize(0, 30)),))
im_ani = animation.ArtistAnimation(fig2, ims, interval=50, repeat_delay=3000,
blit=True)
plt.show()
The issue here is two-fold. First, I have about 3000 frames, so the list ims becomes unmanageable. Secondly, how can I get the data to clear between frames and not show every frame all at once? Perhaps there's a better way altogether?
Bonus: using a slider could be an alternative to an animation. I've used Slider on these types of data before, but only by initializing a huge x and y grid.
Thanks for the help! Apologies if I'm not using the proper tags.
I may misunderstand the problem here, but using a FuncAnimation seems more appropriate here.
With blitting
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig, ax = plt.subplots()
x = np.arange(-9, 10)
y = np.arange(-9, 10).reshape(-1, 1)
base = np.hypot(x, y)
def animate(i):
x = np.arange(-9+i, 10+i)
y = np.arange(-9+i, 10+i)
x, y = np.meshgrid(x, y)
pc = ax.pcolormesh(x, y, base + i, norm=plt.Normalize(0, 30))
return pc,
ax.axis([-9,30,-9,30])
im_ani = animation.FuncAnimation(fig, animate, frames=30, interval=50,
repeat_delay=3000, blit=True)
plt.show()
Without blitting
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig, ax = plt.subplots()
x = np.arange(-9, 10)
y = np.arange(-9, 10).reshape(-1, 1)
base = np.hypot(x, y)
store=[]
def animate(i):
x = np.arange(-9+i, 10+i)
y = np.arange(-9+i, 10+i)
x, y = np.meshgrid(x, y)
if store:
store[0].remove()
del store[0]
pc = ax.pcolormesh(x, y, base + i, norm=plt.Normalize(0, 30))
store.append(pc)
ax.axis([-9,30,-9,30])
im_ani = animation.FuncAnimation(fig, animate, frames=30, interval=50,
repeat_delay=3000)
plt.show()

How to fit a 2D ellipse to given points

I would like to fit a 2D array by an elliptic function: (x / a)² + (y / b)² = 1 ----> (and so get the a and b)
And then, be able to replot it on my graph.
I found many examples on internet, but no one with this simple Cartesian equation. I probably have searched badly ! I think a basic solution for this problem could help many people.
Here is an example of the data:
Sadly, I can not put the values... So let's assume that I have an X,Y arrays defining the coordinates of each of those points.
This can be solved directly using least squares. You can frame this as minimizing the sum of squares of quantity (alpha * x_i^2 + beta * y_i^2 - 1) where alpha is 1/a^2 and beta is 1/b^2. You have all the x_i's in X and the y_i's in Y so you can find the minimizer of ||Ax - b||^2 where A is an Nx2 matrix (i.e. [X^2, Y^2]), x is the column vector [alpha; beta] and b is column vector of all ones.
The following code solves the more general problem for an ellipse of the form Ax^2 + Bxy + Cy^2 + Dx +Ey = 1 though the idea is exactly the same. The print statement gives 0.0776x^2 + 0.0315xy+0.125y^2+0.00457x+0.00314y = 1 and the image of the ellipse generated is also below
import numpy as np
import matplotlib.pyplot as plt
alpha = 5
beta = 3
N = 500
DIM = 2
np.random.seed(2)
# Generate random points on the unit circle by sampling uniform angles
theta = np.random.uniform(0, 2*np.pi, (N,1))
eps_noise = 0.2 * np.random.normal(size=[N,1])
circle = np.hstack([np.cos(theta), np.sin(theta)])
# Stretch and rotate circle to an ellipse with random linear tranformation
B = np.random.randint(-3, 3, (DIM, DIM))
noisy_ellipse = circle.dot(B) + eps_noise
# Extract x coords and y coords of the ellipse as column vectors
X = noisy_ellipse[:,0:1]
Y = noisy_ellipse[:,1:]
# Formulate and solve the least squares problem ||Ax - b ||^2
A = np.hstack([X**2, X * Y, Y**2, X, Y])
b = np.ones_like(X)
x = np.linalg.lstsq(A, b)[0].squeeze()
# Print the equation of the ellipse in standard form
print('The ellipse is given by {0:.3}x^2 + {1:.3}xy+{2:.3}y^2+{3:.3}x+{4:.3}y = 1'.format(x[0], x[1],x[2],x[3],x[4]))
# Plot the noisy data
plt.scatter(X, Y, label='Data Points')
# Plot the original ellipse from which the data was generated
phi = np.linspace(0, 2*np.pi, 1000).reshape((1000,1))
c = np.hstack([np.cos(phi), np.sin(phi)])
ground_truth_ellipse = c.dot(B)
plt.plot(ground_truth_ellipse[:,0], ground_truth_ellipse[:,1], 'k--', label='Generating Ellipse')
# Plot the least squares ellipse
x_coord = np.linspace(-5,5,300)
y_coord = np.linspace(-5,5,300)
X_coord, Y_coord = np.meshgrid(x_coord, y_coord)
Z_coord = x[0] * X_coord ** 2 + x[1] * X_coord * Y_coord + x[2] * Y_coord**2 + x[3] * X_coord + x[4] * Y_coord
plt.contour(X_coord, Y_coord, Z_coord, levels=[1], colors=('r'), linewidths=2)
plt.legend()
plt.xlabel('X')
plt.ylabel('Y')
plt.show()
Following the suggestion by ErroriSalvo, here is the complete process of fitting an ellipse using the SVD. The arrays x, y are coordinates of the given points, let's say there are N points. Then U, S, V are obtained from the SVD of the centered coordinate array of shape (2, N). So, U is a 2 by 2 orthogonal matrix (rotation), S is a vector of length 2 (singular values), and V, which we do not need, is an N by N orthogonal matrix.
The linear map transforming the unit circle to the ellipse of best fit is
sqrt(2/N) * U * diag(S)
where diag(S) is the diagonal matrix with singular values on the diagonal. To see why the factor of sqrt(2/N) is needed, imagine that the points x, y are taken uniformly from the unit circle. Then sum(x**2) + sum(y**2) is N, and so the coordinate matrix consists of two orthogonal rows of length sqrt(N/2), hence its norm (the largest singular value) is sqrt(N/2). We need to bring this down to 1 to have the unit circle.
N = 300
t = np.linspace(0, 2*np.pi, N)
x = 5*np.cos(t) + 0.2*np.random.normal(size=N) + 1
y = 4*np.sin(t+0.5) + 0.2*np.random.normal(size=N)
plt.plot(x, y, '.') # given points
xmean, ymean = x.mean(), y.mean()
x -= xmean
y -= ymean
U, S, V = np.linalg.svd(np.stack((x, y)))
tt = np.linspace(0, 2*np.pi, 1000)
circle = np.stack((np.cos(tt), np.sin(tt))) # unit circle
transform = np.sqrt(2/N) * U.dot(np.diag(S)) # transformation matrix
fit = transform.dot(circle) + np.array([[xmean], [ymean]])
plt.plot(fit[0, :], fit[1, :], 'r')
plt.show()
But if you assume that there is no rotation, then np.sqrt(2/N) * S is all you need; these are a and b in the equation of the ellipse.
You could try a Singular Value Decomposition of the data matrix.
https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.linalg.svd.html
First center the data by subtracting mean values of X,Y from each column respectively.
X=X-np.mean(X)
Y=Y-np.mean(Y)
D=np.vstack(X,Y)
Then, apply SVD and extract
-eigenvalues (members of s) -> axis length
-eigenvectors(U) -> axis orientation
U, s, V = np.linalg.svd(D, full_matrices=True)
This should be a least-squares fit.
Of course, things can get more complicated than this, please see
https://www.emis.de/journals/BBMS/Bulletin/sup962/gander.pdf

Plot from Cartesian to polar

I'm using the Left and Right audio channels to create a Lissajous Vectorscope. Left is x and Right is y, both which never goes beyond 1 and -1 values. These coordinates are also shifted at a 45 degree angle to give me the following view.
So I'm doing a very simple
// converting x and y value from (-1 - 1) to (0 - 1)
float x = LeftChannelValue/2 + 0.5
float y = RightChannelValue/2 + 0.5
// multiplying the width and height with X and Y to get a proper square
// width and height have to be the same value
float new_X = x*(width*0.5)
float new_Y = y*(height*0.5)
// doing two dimensional rotating to 45 degrees so it's easier to read
float cosVal = cos(0.25*pi)
float sinVal = sin(0.25*pi)
float finalX = (((new_X*cosVal)-(new_Y *sinVal))) + (width*0.5) //adding to translate back to origin
float finalY = ((new_X*sinVal) + (new_Y *cosVal))
This gives me the results on that picture.
How would I graph the polar coordinates so that it doesn't look like a square, it looks like a circle?
I'm trying to get this view but am absolutely confused about how that would correlate with the left and right. I'm using https://en.wikipedia.org/wiki/Polar_coordinate_system as a reference.
I figured out what I wanted.
I was trying to plot those coordinates in a polar graph. I was going about it all wrong.
I eventually realized that in order for me to convert the x,y coordinates, I needed my own definition for what a radius and an angle should represents in my x,y chart. In my case, I wanted the radius to be the largest absolute value of x and y
The only problem was trying to figure out how to calculate an angle using x and y values.
This is how I wanted my circle to work,
when x = y, the angle is 0.
when x = 1 & y = 0, then angle is 45.
when x = 1 & y = -1, then angle is 90.
when x = 0 & y = 1, then angle is -45.
when x = -1 & y = 1, then angle is -90.
given this information, you can figure out the rest of the coordinates for the circle up to 180 & - 180 degree angle.
I had to use conditions (if else statements) to properly figure out the correct angle given x and y.
And then to graph the polar coordinate, you just convert using the cos and sin conversion to x, y coordinates.
I like to program, I'm just not good with calculus.

Colouring the surface of a sphere with a set of scalar values in matplotlib

I am rather new to matplotlib (and this is also my first question here). I'm trying to represent the scalp surface potential as recorded by an EEG. So far I have a two-dimensional figure of a sphere projection, which I generated using contourf, and pretty much boils down to an ordinary heat map.
Is there any way this can be done on half a sphere?, i.e. generating a 3D sphere with surface colours given by a list of values? Something like this, http://embal.gforge.inria.fr/img/inverse.jpg, but I have more than enough with just half a sphere.
I have seen a few related questions (for example, Matplotlib 3d colour plot - is it possible?), but they either don't really address my question or remain unanswered to date.
I have also spent the morning looking through countless examples. In most of what I've found, the colour at one particular point of a surface is indicative of its Z value, but I don't want that... I want to draw the surface, then specify the colours with the data I have.
You can use plot_trisurf and assign a custom field to the underlying ScalarMappable through set_array method.
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import matplotlib.tri as mtri
(n, m) = (250, 250)
# Meshing a unit sphere according to n, m
theta = np.linspace(0, 2 * np.pi, num=n, endpoint=False)
phi = np.linspace(np.pi * (-0.5 + 1./(m+1)), np.pi*0.5, num=m, endpoint=False)
theta, phi = np.meshgrid(theta, phi)
theta, phi = theta.ravel(), phi.ravel()
theta = np.append(theta, [0.]) # Adding the north pole...
phi = np.append(phi, [np.pi*0.5])
mesh_x, mesh_y = ((np.pi*0.5 - phi)*np.cos(theta), (np.pi*0.5 - phi)*np.sin(theta))
triangles = mtri.Triangulation(mesh_x, mesh_y).triangles
x, y, z = np.cos(phi)*np.cos(theta), np.cos(phi)*np.sin(theta), np.sin(phi)
# Defining a custom color scalar field
vals = np.sin(6*phi) * np.sin(3*theta)
colors = np.mean(vals[triangles], axis=1)
# Plotting
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
cmap = plt.get_cmap('Blues')
triang = mtri.Triangulation(x, y, triangles)
collec = ax.plot_trisurf(triang, z, cmap=cmap, shade=False, linewidth=0.)
collec.set_array(colors)
collec.autoscale()
plt.show()

Google chart image, add labels to the X and Y axis

I am using:
http://code.google.com/apis/chart/image/
I want to describe that the X is "Meal number" and Y is "calories"
chs=440x220
chxt=y,x
cht=lc
chco=3072F3
chd=t:931.4,23.5,572.4,0,0,0,0
chds=0,2500
chxr=0,0,2500|1,1,7,1
chdl=Energi
chdlp=b
chls=2
chma=5,5,5,25
chm=o,000000,0,-1,5
You can try and see here:
http://code.google.com/apis/chart/image/docs/chart_playground.html
I already have labels for X and Y. The X axis 1,2,3,4... and the Y axis 0,250,500...
I want to add at the top or bottom on the Y axis: Calories
And on the X axis: Meal number
I found this:
http://www.lornajane.net/posts/2011/adding-multiple-axis-labels-to-a-google-chart
But i dont know how to do it on a Line chart
The chxl parameter allows you to specify the label and chxp enables you to position the labels, e.g.:
http://chart.apis.google.com/chart
?chxl=0:|Calories||1:|Hours
&chxp=0,100|1,50
&chxt=y,x
&chbh=a
&chs=300x225
&cht=bvg
&chco=A2C180,3D7930
&chd=t:10,50,60,80,40,60,30|50,60,100,40,20,40,30
&chtt=Vertical+bar+chart
More detail (including how to apply styles to axis labels):
http://code.google.com/apis/chart/image/docs/gallery/bar_charts.html#axis_labels