I have a function 2*x*arcctg(x) - 1, and i try to plot it in Python:
import os
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, np.pi / 2)
y = 2 * x * np.cos(2 * x) / np.sin(2 * x)
plt.plot(x, y)
plt.axis('tight')
plt.show()
but it's plot smthg like that:
and when i plot it in wolfram it looks:
What am i doing wrong?
The function should be:
2*x*arcctg(x) - 1
But arcctg(x) is not cos(2x)/sin(2x) (the expression you describe in your code). A ctg is the co-tangens, so cos(x)/sin(x). So that means that arcctg(x) is arctan(1/x).
So you can use:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, np.pi / 2)
y = 2 * x * np.arctan(1/x) - 1
plt.plot(x, y)
plt.axis('tight')
plt.show()
This produces the following plot:
Which matches with the plot in the question.
In case you want to make the plot look more than the one in Wolfram Alpha, you can like #MSeifert says, set the range from -pi/2 to pi/2, like:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-np.pi / 2, np.pi / 2, 1000)
y = 2 * x * np.arctan(1/x) - 1
plt.plot(x, y)
plt.axis('tight')
plt.show()
this then produces:
Related
This question already has answers here:
How to plot multiple functions on the same figure, in Matplotlib?
(4 answers)
Closed 1 year ago.
How to build two graphs in one figure from the equations below
y = (x+2)^2
y = sin(x/2)^2
There is my code:
import matplotlib.pyplot as plt
import numpy as np
from math import sin
y = lambda x: sin(x / 2) ** 2
y1 = lambda x: (x + 2) ** 2
fig = plt.subplots()
x = np.linspace(-3, 3, 100)
plt.plot(x, y(x))
plt.plot(x, y1(x))
plt.show()
Use supplots to make 2 Axes in your Figure:
import matplotlib.pyplot as plt
import numpy as np
fig, (ax1,ax2) = plt.subplots(nrows=2)
x = np.linspace(-3, 3, 100)
ax1.plot(x, np.sin(x / 2) ** 2)
ax2.plot(x, (x + 2) ** 2)
How I can fill the common area under both the curve?
import matplotlib.pyplot as plt
import numpy as np
import scipy.special as sp
x = np.linspace(-4, 4, num=1000)
r = abs(x)
zeta = 1.0
psi_STO = (zeta**3 / np.pi)**(0.5) * np.exp(-zeta * r)
plt.figure(figsize=(4, 3))
plt.plot(x, psi_STO, color="C0")
plt.plot(x + 3, psi_STO, color="C0")
plt.show()
If I use:
plt.fill_betweenx(psi_STO, -1, 4, color="C1")
I am getting a plot as:
You can use fill_between. As your Xs are not aligned, you need to make a bit of calculations first to find the common range. This will depend on the number of points in the linspace. Here, I computed it manually: as the shift is of 3, there are 375 points difference (250 per unit).
import matplotlib.pyplot as plt
import numpy as np
import scipy.special as sp
x = np.linspace(-4, 4, num=1000)
r = abs(x)
zeta = 1.0
psi_STO = (zeta**3 / np.pi)**(0.5) * np.exp(-zeta * r)
plt.figure(figsize=(4, 3))
plt.plot(x, psi_STO, color="C0")
plt.plot(x + 3, psi_STO, color="C0")
x_common = (x+3)[:-375]
min_common = np.min([psi_STO[:-375], psi_STO[375:]], axis=0)
plt.plot(x_common, min_common, color='r')
plt.fill_between(x_common,min_common, color="#FFB0B0")
plt.show()
output:
This?
dx = 3 # x shift
di = int(dx/(x[1]-x[0])) # index shift
plt.fill_between(x[di:], np.minimum(psi_STO[:-di], psi_STO[di:]))
I have a distribution plot, but I want to fill in with some color the region between the blue vertical dashed line and the beginning of the distribution plot. So basically, just fill in with color, this area where the arrow is:
I tried doing plt.fill_between... but it's covering the entire plot rather than one specific area. How would I only fill in one region?
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt
x = np.arange(-5, 5, 0.1) # x from -6 to 6 in steps of 0.1
y = 1 / np.sqrt(2 * np.pi) * np.exp(-x ** 2 / 4.)
std = np.std(y)
plt.plot(x,y, 'k')
plt.axvline(x=-20*std,color='blue', linestyle='--')
plt.fill_between(x,-4,10)
plt.ylim(0,.42)
plt.show()
Using where parameter:
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt
x = np.arange(-5, 5, 0.1) # x from -6 to 6 in steps of 0.1
y = 1 / np.sqrt(2 * np.pi) * np.exp(-x ** 2 / 4.)
std = np.std(y)
plt.plot(x,y, 'k')
plt.fill_between(x,y,where = x<=-20*std)
plt.ylim(0,.42)
plt.show()
Output:
I have code that looks like this:
import matplotlib.pyplot as plt
import numpy as np
from nfft import nfft
# number of sample points
N = 400
# Simulated non-uniform data
x = np.linspace(0.0, 1 / 2, N) + np.random.random((N)) * 0.001
y = np.sin(50.0 * 2.0 * np.pi * x) + 0.5 * np.sin(80.0 * 2.0 * np.pi * x)
yf = np.abs(nfft(x, y))
fig, axs = plt.subplots(1)
fig_f, axs_f = plt.subplots(1)
axs.plot(x, y, '.', color='red')
axs_f.plot(x, yf, color='red')
How do I convert the values on the second graph to represent frequency?
The use of the nfft module is not required, answers using pynfft or scipy will be greatly appreciated.
See also:
How do I obtain the frequencies of each value in an FFT?
The following seems to work. Notice the line inserted before graphing the Fourier transform, to generate the frequencies, and that we graph N/2 of the data.
import matplotlib.pyplot as plt
import numpy as np
from nfft import nfft
# number of sample points
N = 400
# Simulated non-uniform data
x = np.linspace(0.0,0.5-0.02, N) + np.random.random((N)) * 0.001
print(x)
print( 'random' )
print( np.random.random((N)) * 0.001 )
y = np.sin(50.0 * 2.0 * np.pi * x) + 0.5 * np.sin(80.0 * 2.0 * np.pi * x)
yf = np.abs(nfft(x, y))
fig, axs = plt.subplots(1)
fig_f, axs_f = plt.subplots(1)
axs.plot(x, y, '.', color='red')
xf = np.fft.fftfreq(N,1./N)
axs_f.plot(xf[:int(N/2)], yf[:int(N/2)], color='red')
plt.show()
Output:
The original code written in the following format was running without any error yet it did not produce the desired 2d-function plot/surface. In fact, I was getting the 3d space with all the titles and labels but without actual 2d plot. I have tried to check the output by print() function at each step. It seems that the code produces correctly the z array but surf() is not responding accordingly. So, the question should have been instead "What method is missing in the code so that Surface() is not responding accordingly?"
import sys
import matplotlib
matplotlib.use('SVG')
import matplotlib.pyplot as pyplot
from matplotlib.ticker import MaxNLocator
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
from numpy import array as ar
import random
from scipy import linspace, meshgrid, arange, empty, concatenate, newaxis, shape
import math
fig =pyplot.figure()
ax = fig.gca(projection='3d')
N = 10000
data1 = [random.random() for i in range(N)]
x1 = ar(data1)
data2 = [random.random() for i in range(N)]
x2 = ar(data2)
a = 2.000000
y1 = np.sqrt((-1.000000) * a * np.log(x1)) * np.cos(2 * math.pi * x2)
y2 = np.sqrt((-1.000000) * a * np.log(x1)) * np.sin(2 * math.pi * x2)
gaussian1 = math.pow(2 * math.pi, (-1.000000 / a)) * np.exp((-1.000000 / a) * y1**a)
gaussian2 = math.pow(2 * math.pi, (-1.000000 / a)) * np.exp((-1.000000 / a) * y2**a)
z = gaussian1 * gaussian2
surf = ax.plot_surface(x1, x2, z, rstride=1, cstride=1, cmap=cm.jet, linewidth=1.0)
fig.colorbar(surf)
title = ax.set_title("Probability Distribution Function")
title.set_y(1.01)
ax.xaxis.set_major_locator(MaxNLocator(10))
ax.yaxis.set_major_locator(MaxNLocator(10))
ax.zaxis.set_major_locator(MaxNLocator(10))
fig.set_tight_layout(True)
fig.savefig('Gaussian.svg')
The problem is in your arrays. From the documentation to plot_surface:
Axes3D.plot_surface(X, Y, Z, *args, **kwargs)
X, Y, Z: Data values as 2D arrays
your X, Y, Z are 1D arrays, so won't work properly.
You could make x1 and x2 the correct format using np.meshgrid:
x1, x2 = np.meshgrid(x1,x2)
Then generate z using these 2D arrays.
However, note that creating a 10000x10000 surface may use a lot of memory!