Ok, so Im not sure if this is even possible. I am trying to plot a graph in python, using matplotlib, that has a natural log function of both x and y.
First, I looked for posts containing instructions on how-to plot using a natural log. I found part of an answer here and the other part here.
The problem is, I am trying to plot two lines onto one graph.
The equations are:
1) 0.91 - 0.42 * P = Q
2) 6.999 - .7903 * ln (P) = ln (Q)
Is it possible to overlay these two lines onto one graph given the scale issue? How would I do it?
I tried the following:
from pylab import *
import matplotlib.pyplot as plt
import matplotlib
get_ipython().magic('matplotlib inline')
import numpy as np
import pandas as pd
P = np.linspace(0, 1, 11)
P
matplotlib.rcParams['xtick.major.pad'] = 5
matplotlib.rcParams['ytick.major.pad'] = 5
fig, ax = plt.subplots(figsize = (12,6))
axes = plt.gca()
axes.set_ylim([0, 16])
ax.plot(P, 0.91 - 0.42 * P, color = "BLUE", lw = 3, label = 'C1')
x = P ** np.e
y = 6.999 - .7903 * x
y1 = y ** np.e
ax.loglog(x, y, basex = np.e, basey = np.e)
ax.legend()
ax.set_title("Cluster 1 Pricing")
ax.xaxis.labelpad = 5
ax.yaxis.labelpad = 5
ax.set_xlabel("Norm P")
ax.set_ylabel("Norm Q");
But this returns the error:
ValueError: posx and posy should be finite values
It seems you want to plot
q1 = lambda p: 0.91 - 0.42 * p
q2 = lambda p: np.exp(6.999 - .7903 * np.log(p))
This can be done by supplying an array P to those functions and using the plot functions you already have in the code. Mind that you should not attempt to plot 0 on a logrithmic scale.
import matplotlib.pyplot as plt
import numpy as np
P = np.linspace(0.01, 1, 11)
fig, ax = plt.subplots(figsize = (12,6))
q1 = lambda p: 0.91 - 0.42 * p
q2 = lambda p: np.exp(6.999 - .7903 * np.log(p))
ax.plot(P, q1(P), color = "BLUE", lw = 3, label = 'Q1')
ax.loglog(P, q2(P), basex = np.e, basey = np.e,
color = "crimson", lw = 2, label = 'Q2')
ax.legend()
ax.set_title("Cluster 1 Pricing")
ax.set_xlabel("Norm P")
ax.set_ylabel("Norm Q")
plt.show()
Related
I used the following code to try and plot a 3D plane of on its x axis the height (is also the momentum arm) and on its y axis the mass (in kg) which has a linear connection with the force used. The Z axis is the resulting momentum.
Unfortunately I get the following error:
ValueError: Argument Z must be 2-dimensional.
However I do believe that Z, thus the momentum is dependent on both the mass and the height, thus is Z 2d.
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits import mplot3d
g = 9.81
m = np.linspace(0, 1, 301)
H_1 = np.arange(100, 401, 1)
for i, kg in enumerate(m):
Fg = -m[i]*g
M = np.zeros(len(H_1))
for i, mm in enumerate(H_1):
F1 = np.array([0, Fg])
F2 = np.array([Fg * np.sin(np.arctan(200 / H_1[i])), Fg * np.cos(np.arctan(200 / H_1[i]))])
Fres = np.add(F1, F2)
M_arm = np.array([0, H_1[i]])
M[i] = np.cross(M_arm, Fres)/10e3
x,y = np.meshgrid(H_1,m)
z = M
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
ax.plot_surface(x, y, z)
ax.set_xlabel('hoogte toren in (mm)')
ax.set_ylabel('massa')
ax.set_zlabel('momentum')
plt.show()
Check this out:
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits import mplot3d
g = 9.81
m = np.linspace(0, 1, 301)
H_1 = np.arange(100, 401, 1)
Fg = -m * g
M = np.zeros(len(H_1))
for i, mm in enumerate(H_1):
F1 = np.array([0, Fg[i]])
F2 = np.array([Fg[i] * np.sin(np.arctan(200 / H_1[i])), Fg[i] * np.cos(np.arctan(200 / H_1[i]))])
Fres = np.add(F1, F2)
M_arm = np.array([0, H_1[i]])
M[i] = np.cross(M_arm, Fres) / 10e3
x, y = np.meshgrid(H_1, m)
z = M
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
ax.plot_surface(x, y, z)
ax.set_xlabel('hoogte toren in (mm)')
ax.set_ylabel('massa')
ax.set_zlabel('momentum')
plt.show()
I made the following changes to your code:
Moved the calculation of Fg outside the loop.
Used the correct index i to access the elements of m and Fg in the loop.
Used the correct array index i to access the elements of H_1 in the loop.
Removed the unnecessary enumerate call in the inner loop.
Used the correct array index i to access the elements of M in the loop.
These changes should fix the errors in your code and produce the expected plot.
:)
can anyone help me, i stuck at the last step
[]
this is my code. then for the last step to rotate it, i didnt know what should i do to rotate the triangle
This is the perfect case for an animation:
import matplotlib.pyplot as plt
import numpy as np
import matplotlib
from matplotlib.animation import FuncAnimation
# Enter x and y coordinates of points and colors
a=(0,0.5);b=(0.43,-0.25);c=(-0.43,-0.25)
center=(0,0)
n = 3;r=1.0
theta = np.arange(0,360+(360/(n)),360/(n))
to=np.arange(0,2*np.pi,0.01)
x = r * np.cos(np.radians(theta))
y = r * np.sin(np.radians(theta))
xo = r * np.cos(to); yo = r * np.sin(to)
fig, ax = plt.subplots()
ax.plot(xo,yo)
# create artists: they will be used to update the position
# of the points being rendered
triangle, = ax.plot(x,y)
vertices = ax.scatter(x,y)
lim = r * 1.25
ax.set_xlim([-lim, lim]);ax.set_ylim([-lim, lim])
ax.set_aspect("equal")
w = 2
T = 2 * np.pi / w
# this defines the time steps of the animation
dt = np.linspace(0, 10 * T, num=500)
def animate(i):
x = r * np.cos(np.radians(theta) + w * dt[i])
y = r * np.sin(np.radians(theta) + w * dt[i])
# update the position of the points to be rendered
triangle.set_data(x, y)
vertices.set_offsets(np.stack([x, y]).T)
ax.set_title("Rotation #%s" % int(w * dt[i] / (2 * np.pi) + 1))
ani = FuncAnimation(fig, animate, frames=len(dt), repeat=False)
plt.show()
Check this out..
from IPython import display
import matplotlib.pyplot as plt
import numpy as np
import matplotlib
# Enter x and y coordinates of points and colors
a=(0,0.5);b=(0.43,-0.25);c=(-0.43,-0.25)
center=(0,0)
n = 3;r=1.0
theta = np.arange(0,360+(360/(n)),360/(n))
w = 2
T = 2*np.pi/w
dt = np.linspace(0, 10*T, num=10) #increase num for more finely distributed rotations.
for d in dt:
to=np.arange(0,2*np.pi,0.01)
x = r*np.sin(np.radians(theta + d))
y=r*np.cos(np.radians(theta + d))
xo=r*np.sin(to);yo=r*np.cos(to)
plt.plot(xo,yo)
plt.plot(x,y)
plt.scatter(x,y)
plt.xlim([-1, 1]);plt.ylim([-1,1])
[TLDR]:
Essentially my question boils down to how one can extract the 2d data of a plane from a 3D numpy meshgrid
[Detailed Description]:
I am calculating the electric field of two (or more) point charges. I did this in 2D and can plot the results via matplotlib using quiver or streamplot
import numpy as np
from matplotlib import pyplot as plt
eps_0 = 8e-12
fac = (1./(4*np.pi*eps_0))
charges = [1.0,-1.0]
qx = [-2.0,2.0]
qy = [0.0,0.0]
# GRID
gridsize = 4.0
N = 11
X,Y = np.meshgrid( np.linspace(-gridsize,gridsize,N),
np.linspace(-gridsize,gridsize,N))
# CALC E-FIELD
sumEx = np.zeros_like(X)
sumEy = np.zeros_like(Y)
for q, qxi, qyi in zip(charges,qx,qy):
dist_vec_x = X - qxi
dist_vec_y = Y - qyi
dist = np.sqrt(dist_vec_x**2 + dist_vec_y**2)
Ex = fac * q * (dist_vec_x/dist**3)
Ey = fac * q * (dist_vec_y/dist**3)
sumEx += Ex
sumEy += Ey
# PLOT
fig = plt.figure()
ax = fig.add_subplot(111)
ax.streamplot(X,Y,sumEx,sumEy)
plt.show()
This produces the correct results
I can easily extend this to 3D
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import pyplot as plt
eps_0 = 8e-12
fac = (1./(4*np.pi*eps_0))
charges = [1.0,-1.0]
qx = [-2.0,2.0]
qy = [0.0,0.0]
qz = [0.0,0.0]
# GRID
gridsize = 4.0
N = 11
X,Y,Z = np.meshgrid( np.linspace(-gridsize,gridsize,N),
np.linspace(-gridsize,gridsize,N),
np.linspace(-gridsize,gridsize,N))
# CALC E-FIELD
sumEx = np.zeros_like(X)
sumEy = np.zeros_like(Y)
sumEz = np.zeros_like(Z)
for q, qxi, qyi, qzi in zip(charges,qx,qy,qz):
dist_vec_x = X - qxi
dist_vec_y = Y - qyi
dist_vec_z = Z - qzi
dist = np.sqrt(dist_vec_x**2 + dist_vec_y**2 + dist_vec_z**2)
Ex = fac * q * (dist_vec_x/dist**3)
Ey = fac * q * (dist_vec_y/dist**3)
Ez = fac * q * (dist_vec_z/dist**3)
sumEx += Ex
sumEy += Ey
sumEz += Ez
# PLOT
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.quiver(X,Y,Z,sumEx,sumEy,sumEz, pivot='middle', normalize=True)
plt.show()
This also yields the correct result when plotted in 3D (as far as I can tell)
But for some reason I can not figure out how to extract the data from one x-y plane from the generated 3D numpy mesh. I thought I could just do something like
zplane = round(N/2)
ax.quiver(X,Y,sumEx[:,:,zplane],sumEy[:,:,zplane])
but this does not do the trick. Does anyone know the proper way here?
Remove projection='3d' and index X and Y:
fig = plt.figure()
ax = fig.gca()
zplane = round(N / 2)
ax.quiver(X[:, :, zplane], Y[:, :, zplane], sumEx[:, :, zplane], sumEy[:, :, zplane])
plt.show()
If you select a specific zplane your plot is no longer a 3D-plot.
I've got a question. Below is my code snippet where I am trying to fill a vector given a function yv. When I run the code, there is no error, but it does not print out a result, nor does it show the plot I want.
import matplotlib as plt
import numpy as np
import math as m
e = 2.17
sigma = 1
mu = 0
xv = np.linspace(-4, 4, 100)
for rows in range(0):
for cols in range(100):
yv = 1 / (sigma * (2 * m.pi) ** (-0.5)) * e ** (-0.5) * ((((xv - mu) / sigma)) ** 2)
print('xv= {}'.format(xv))
print('yv= {}'.format(yv))
plt.plot(xv, yv, 'b-o', linewidth = 2, label = 'xv vs. yv')
plt.show()
What am I missing?
Thanks again!
Brandon
Your matplotlib import was not quite right. Try this:
from matplotlib import pyplot as plt
import numpy as np
import math as m
e = 2.17
sigma = 1
mu = 0
xv = np.linspace(-4, 4, 100)
yv = 1/(sigma*(2*m.pi)**(-0.5))*e**(-0.5)*((((xv-mu)/sigma))**2)
print('xv= {}'.format(xv))
print('yv= {}'.format(yv))
plt.plot(xv, yv, 'b-o', linewidth=2, label='xv vs. yv')
plt.show()
I'm trying to plot a contour plot in matplotlib and I keep getting a missing "wedge". The following example illustrates what I'm trying to do.
import numpy as np
import matplotlib.pyplot as plt
ph_cut = 0.05
nphi = 13
phi = np.linspace(ph_cut,2*np.pi-ph_cut, nphi)
nr = 50
rmax=1
rr = np.linspace(0, rmax, nr)
PH, RR = np.meshgrid(phi,rr)
X = RR * np.cos(PH)
Y = RR * np.sin(PH)
Z = np.sin(PH)
nlev = 13
levels=np.linspace(-1, 1, nlev)
cs=plt.contourf(X,Y,Z, levels)
plt.colorbar(cs)
plt.show()
The wedge between -ph_cut and ph_cut is never filled. Is there no way for matplotlib to interpolate across? Strictly speaking, this region is no different and has no less information than the corresponding pi-ph_cut to pi+ph_cut... I tried searching around but could not find any solution.
Just don't leave out the cut:
import numpy as np
import matplotlib.pyplot as plt
ph_cut = 0.05
nphi = 13
phi = np.linspace(0,2*np.pi, nphi)
nr = 50
rmax=1
rr = np.linspace(0, rmax, nr)
PH, RR = np.meshgrid(phi,rr)
X = RR * np.cos(PH)
Y = RR * np.sin(PH)
Z = np.sin(PH)
nlev = 13
levels=np.linspace(-1, 1, nlev)
cs=plt.contourf(X,Y,Z, levels)
plt.colorbar(cs)
plt.show()