I have that code:
for i, j in aa:
plt.plot([xc[i], xc[j]], [yc[i], yc[j]], c='g', zorder=0)
plt.plot(xc[0], yc[0], c='r', marker='s')
plt.scatter(xc[1:], yc[1:],c='b')
And It generate this:
I need to add notation to each point. It shoud be it Y axix value. For example extreme right point is "1". It's possible to do that in simple way in this case? I found only help for totaly different cases and I can't implement it in my example.
import numpy as np
import matplotlib.pyplot as plt
#dummy data
aa = np.arange(10).reshape(5,2)
xc = np.random.rand(10)
yc = np.random.rand(10)
for i, j in aa:
plt.plot([xc[i], xc[j]], [yc[i], yc[j]], c='g', zorder=0)
plt.plot(xc[0], yc[0], c='r', marker='s')
plt.scatter(xc[1:], yc[1:],c='b')
# annotate each datapoint with its y-value, rounded to two decimals.
for x,y in zip(xc, yc):
plt.annotate('{:.2f}'.format(y), xy=[x,y])
Related
I have been trying of solving an implicit equations using contour plot but I realized it was taking into account the singularities of my equation so I was obtaining wrong graphs. Because of this, I tried sympy.plot_implicit. Fortunately, it works properly but I have not found a proper way to set a label on the graphs produced by sympy.plot_implicit. For this aim, I need to obtain the points used by sympy.plot_implicit for producing its the graphs and use them into matplotlib. This way, I am obtainig correct solutions for my implicit equations and I can easily set labels for the graphs of the solutions. At this moment, I am facing many issues when I try to obtain the point from sympy.plot_implicit, I mean, when I only use sympy.plot there is not any problem but the issues appear when I use sympy.plot_implicit.
I have attached the code, thank you in advance.
Best
import matplotlib.pyplot as plt
import sympy as sp
from sympy.abc import x,y,z
def z(x, y):
return x - y
line = sp.plot(x**2,(x,-1,0), show=False)
#line = sp.plot_implicit(z(x, y), (x, 0, 1), (y, 0, 1), show=False)
x, y = line[0].get_points()
plt.plot(x, y)
plt.show()
You can use the move_sympyplot_to_axes function from Display two Sympy plots as two Matplotlib subplots, adapting one line as explained in its comments.
To get something in the legend, matplotlib's standard approach is to add a label to the specific element. In this case, the implicit area seems to be stored as a polygon inside ax.patches. Such a polygon will be shown as a colored rectangle in the legend. In order to get a line, a custom legend element could be created.
As in this case the solution is represented as a thin polygon and not as a line p1[0].get_points() doesn't work. However, you can extract the polygon's vertices from the matplotlib polygon patch:
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
import sympy as sp
from sympy.abc import x, y, z
def move_sympyplot_to_axes(p, ax):
backend = p.backend(p)
backend.ax = ax
backend._process_series(backend.parent._series, ax, backend.parent)
backend.ax.spines['right'].set_color('none')
backend.ax.spines['top'].set_color('none')
backend.ax.spines['bottom'].set_position('zero')
plt.close(backend.fig)
def z(x, y):
return (x ** 2 + y ** 2 - 1) ** 3 - x ** 2 * y ** 3
p1 = sp.plot_implicit(z(x, y), (x, -1.5, 1.5), (y, -1.5, 1.5), show=False)
fig, ax = plt.subplots()
move_sympyplot_to_axes(p1, ax)
# ax.patches[0].set_label("my label")
handles = [Line2D([], [], color=ax.patches[0].get_facecolor())]
ax.legend(handles=handles, labels=["my label"], loc='upper left')
vertices = ax.patches[0].get_path().vertices
ax.plot(vertices[:, 0], vertices[:, 1], ls=':', color='gold', lw=10, alpha=0.5, zorder=0)
plt.show()
I have a matrix generated by parsing a file the numpy array is the size 101X101X41 and each entry has a value which represents the magnitude at each point.
Now what I want to do is to plot it in a 3d plot where the 4th dimension will be represented by color. so that I will be able to see the shape of the data points (represent molecular orbitals) and deduce its magnitude at that point.
If I plot each slice of data I get the desired outcome, but in a 2d with the 3rd dimension as the color.
Is there a way to plot this model in python using Matplotlib or equivalent library
Thanks
EDIT:
Im trying to get the question clearer to what I desire.
Ive tried the solution suggested but ive received the following plot:
as one can see, due to the fact the the mesh has lots of zeros in it it "hide" the 3d orbitals. in the following plot one can see a slice of the data, where I get the following plot:
So as you can see I have a certain structure I desire to show in the plot.
my question is, is there a way to plot only the structure and ignore the zeroes such that they won't "hide" the structure.
the code I used to generate the plots:
x = np.linspase(1,101,101)
y = np.linspase(1,101,101)
z = np.linspase(1,101,101)
xx,yy,zz = np.meshgrid(x,y,z)
fig=plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(xx, yy, zz, c=cube.calc_data.flatten())
plt.show()
plt.imshow(cube.calc_data[:,:,11],cmap='jet')
plt.show()
Hope that now the question is much clearer, and that you'd appreciate the question enough now to upvote
Thanks.
you can perform the following:
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
epsilon = 2.5e-2 # threshold
height, width, depth = data.shape
global_min = np.inf
global_max = -np.inf
for d in range(depth):
slice = data[:, :, d]
minima = slice.min()
if (minima < global_min): global_min = minima
maxima = slice.max()
if (maxima>global_max): global_max=maxima
norm = colors.Normalize(vmin=minima, vmax=maxima, clip=True)
mapper = cm.ScalarMappable(norm=norm, cmap=cm.jet)
points_gt_epsilon = np.where(slice >= epsilon)
ax.scatter(points_gt_epsilon[0], points_gt_epsilon[1], d,
c=mapper.to_rgba(data[points_gt_epsilon[0],points_gt_epsilon[1],d]), alpha=0.015, cmap=cm.jet)
points_lt_epsilon = np.where(slice <= -epsilon)
ax.scatter(points_lt_epsilon[0], points_lt_epsilon[1], d,
c=mapper.to_rgba(data[points_lt_epsilon[0], points_lt_epsilon[1], d]), alpha=0.015, cmap=cm.jet)
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
plt.title('Electron Density Prob.')
norm = colors.Normalize(vmin=global_min, vmax=global_max, clip=True)
cax, _ = colorbar.make_axes(ax)
colorbar.ColorbarBase(cax, cmap=cm.jet,norm=norm)
plt.savefig('test.png')
plt.clf()
What this piece of code does is going slice by slice from the data matrix and for each scatter plot only the points desired (depend on epsilon).
in this case you avoid plotting a lot of zeros that 'hide' your model, using your words.
Hope this helps
You can adjust the color and size of the markers for the scatter. So for example you can filter out all markers below a certain threshold by putting their size to 0. You can also make the size of the marker adaptive to the field strength.
As an example:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
f = lambda x,y,z: np.exp(-(x-3)**2-(y-3)**2-(z-1)**2) - \
np.exp(-(x+3)**2-(y+3)**2-(z+1)**2)
t1 = np.linspace(-6,6,101)
t2 = np.linspace(-3,3,41)
# Data of shape 101,101,41
data = f(*np.meshgrid(t1,t1,t2))
print(data.shape)
# Coordinates
x = np.linspace(1,101,101)
y = np.linspace(1,101,101)
z = np.linspace(1,101,41)
xx,yy,zz = np.meshgrid(x,y,z)
fig=plt.figure()
ax = fig.add_subplot(111, projection='3d')
s = np.abs(data/data.max())**2*25
s[np.abs(data) < 0.05] = 0
ax.scatter(xx, yy, zz, s=s, c=data.flatten(), linewidth=0, cmap="jet", alpha=.5)
plt.show()
I have some z=f(x,y) data which i would like to plot. The issue is that (x,y) are not part of a "nice" rectangle, but rather arbitrary parallelograms, as shown in the attached image (this particular one is also a rectangle, but you could think of more general cases). So I am having a hard time figuring out how I can use plot_surface in this case, as this usually will take x and y as 2d arrays, and here my x-and y-values are 1d. Thanks.
Abritrary points can be supplied as 1D arrays to matplotlib.Axes3D.plot_trisurf. It doesn't matter whether they follow a specific structure.
Other methods which would depend on the structure of the data would be
Interpolate the points on a regular rectangular grid. This can be accomplished using scipy.interpolate.griddata. See example here
Reshape the input arrays such that they live on a regular and then use plot_surface(). Depending on the order by which the points are supplied, this could be a very easy solution for a grid with "parallelogramic" shape.
As can be seen from the sphere example, plot_surface() also works in cases of very unequal grid shapes, as long as it's structured in a regular way.
Here are some examples:
For completeness, find here the code that produces the above image:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
f = lambda x,y: np.sin(x+0.4*y)*0.23+1
fig = plt.figure(figsize=(5,6))
plt.subplots_adjust(left=0.1, top=0.95,wspace=0.01)
ax0 = fig.add_subplot(322, projection="3d")
ma = 6*(np.random.rand(100)-0.5)
mb = 6*(np.random.rand(100)-0.5)
phi = np.pi/4
x = 1.7*ma*np.cos(phi) + 1.7*mb*np.sin(phi)
y = -1.2*ma*np.sin(phi) +1.2* mb*np.cos(phi)
z = f(x,y)
ax0.plot_trisurf(x,y,z)
ax1 = fig.add_subplot(321)
ax0.set_title("random plot_trisurf()")
ax1.set_aspect("equal")
ax1.scatter(x,y, marker="+", alpha=0.4)
for i in range(len(x)):
ax1.text(x[i],y[i], i , ha="center", va="center", fontsize=6)
n = 10
a = np.linspace(-3, 3, n)
ma, mb = np.meshgrid(a,a)
phi = np.pi/4
xm = 1.7*ma*np.cos(phi) + 1.7*mb*np.sin(phi)
ym = -1.2*ma*np.sin(phi) +1.2* mb*np.cos(phi)
shuf = np.c_[xm.flatten(), ym.flatten()]
np.random.shuffle(shuf)
x = shuf[:,0]
y = shuf[:,1]
z = f(x,y)
ax2 = fig.add_subplot(324, projection="3d")
ax2.plot_trisurf(x,y,z)
ax3 = fig.add_subplot(323)
ax2.set_title("unstructured plot_trisurf()")
ax3.set_aspect("equal")
ax3.scatter(x,y, marker="+", alpha=0.4)
for i in range(len(x)):
ax3.text(x[i],y[i], i , ha="center", va="center", fontsize=6)
x = xm.flatten()
y = ym.flatten()
z = f(x,y)
X = x.reshape(10,10)
Y = y.reshape(10,10)
Z = z.reshape(10,10)
ax4 = fig.add_subplot(326, projection="3d")
ax4.plot_surface(X,Y,Z)
ax5 = fig.add_subplot(325)
ax4.set_title("regular plot_surf()")
ax5.set_aspect("equal")
ax5.scatter(x,y, marker="+", alpha=0.4)
for i in range(len(x)):
ax5.text(x[i],y[i], i , ha="center", va="center", fontsize=6)
for axes in [ax0, ax2,ax4]:
axes.set_xlim([-3.5,3.5])
axes.set_ylim([-3.5,3.5])
axes.set_zlim([0.9,2.0])
axes.axis("off")
plt.savefig(__file__+".png")
plt.show()
If your data is in order, and you know the size of the parallgram, a reshape will probably suffice:
ax.surface(x.reshape(10, 10), y.reshape(10, 10), z.reshape(10, 10))
Will work if the parallelogram has 10 points on each side, and the points are ordered in a zigzag pattern
I've looked at the documentation, but I can't seem to figure out if this is possible -
I have a dataset, with x and y values and discrete z values. Multiple pairs of (x,y) share the same z value. What I want to do is when I mouseover one point with a particular z value, the alpha of all the points with the same z values goes to 1 - i.e., If all the alpha values are initially 0.5, I'd like only the points with the same z value to go to 1.
Here's a minimal working example to illustrate what I'm talking about :
#! /usr/bin/env python
import numpy as np
import matplotlib.pyplot as plt
x = np.random.randn(100)
y = np.random.randn(100)
z = np.arange(0, 10, 1)
z = np.repeat(z, 10)
im = plt.scatter(x, y, c=z, alpha = 0.5)
plt.colorbar(im)
plt.show()
You can probably fake what you want to achieve using a second plot:
import numpy as np
import matplotlib.pyplot as plt
Z = np.zeros(1000, dtype = [("Z", int), ("P", float, 2)])
Z["P"] = np.random.uniform(0.0,1.0,(len(Z),2))
Z["Z"] = np.random.randint(0,50,len(Z))
def on_pick(event):
z = Z[event.ind[0]]['Z']
P = Z[np.where(Z["Z"] == z)]["P"]
selection_plot.set_data(P[:,0],P[:,1])
plt.draw()
fig = plt.figure(figsize=(10,10), facecolor='white')
fig.canvas.mpl_connect('pick_event', on_pick)
ax = plt.subplot(111, aspect=1)
ax.plot(Z['P'][:,0], Z['P'][:,1], 'o', color='k', alpha=0.1, picker=5)
selection_plot, = ax.plot([],[], 'o', color='black', alpha=1.0, zorder=10)
plt.show()
I'm stuck trying to mask data for a scatter plot. All data seems to plot.
I'm using numpy arrays as shown in the snippet below. I'm thinking that perhaps I cannot mask on the "c" array. I can't seem to find any documentation for doing this. I'll try with the "s" array.
Any help is greatly appreciated.
yy = NP.ma.array(yy)
xx = NP.ma.array(xx)
zz_masked = NP.ma.masked_where(zz <= 1.0e6 , zz)
scatter(xx,yy,s=15,c=zz_masked, edgecolors='none')
cbar = colorbar()
show()
Works for me. Each call to scatter() gets its own colorbar since each scatter()'s colors are normalized to its own data. Which version of matplotlib are you using?
import pylab as plt
import numpy as np
x = np.linspace(0, 1, 100)
y = x**2
z = y
z_masked = np.ma.masked_where(z > 0.5, z)
plt.scatter(x, y, c=z, s=15, edgecolors='none')
plt.colorbar()
plt.scatter(x+1, y, c=z_masked, s=15, edgecolors='none')
plt.colorbar()
plt.show()