I have written a simple python program to solve simple harmonic oscillator using both Euler method and Analytical method, but it seems that the two curves fit perfectly(I am not sure how and why?, since they had to be different). Since these curves fit perfectly, I have not been able to make any distinction between these two curves. Even though they fit, is there any way to make them distinct using matplotlib's features. Thanks
import matplotlib.pyplot as plt
import math as m
g=9.8
v=0.0 #initial velocity
h=0.01 #time step
x=5.0 #initial position
w=m.sqrt(10.0)
t=0.0
ta,xa,xb=[],[],[]
while t<12.0:
ta.append(t)
xa.append(x)
xb.append(5*m.cos(w*t))
v=v-(10.0/1.0)*x*h #k=10.0, m=1.0
x=x+v*h
t=t+h
plt.figure()
plt.plot(ta,xa,ta,xb,'bo--')
plt.xlabel('$t(s)$')
plt.ylabel('$x(m)$')
plt.show()
One way is changing color and reducing the opacity of one plot:
plt.plot(ta,xa)
plt.plot(ta,xb,c='red',alpha=.5)
instead of:
plt.plot(ta,xa,ta,xb,'bo--')
When zoomed in:
You can also scatter one and plot the other:
plt.plot(ta,xa)
plt.scatter(ta,xb,c='red',alpha=.3)
You could call the plot method twice, like
plt.plot(ta, xa, 'bo--')
plt.plot(ta, xb, 'gs')
Related
I have a Data Frame df with two columns 'Egy' and 'fx' that I plot in this way:
plot_1 = df_data.plot(x="Egy", y="fx", color="red", ax=ax1, linewidth=0.85)
plot_1.set_xscale('log')
plt.show()
But then I want to smooth this curve using spline like this:
from scipy.interpolate import spline
import numpy as np
x_new = np.linspace(df_data['Egy'].min(), df_data['Egy'].max(),500)
f = spline(df_data['Egy'], df_data['fx'],x_new)
plot_1 = ax1.plot(x_new, f, color="black", linewidth=0.85)
plot_1.set_xscale('log')
plt.show()
And the plot I get is this (forget about the scatter blue points).
There are a lot of "peaks" in the smooth curve, mainly at lower x. How Can I smooth this curve properly?
When I consider the "busybear" suggestion of use np.logspace instead of np.linspace I get the following picture, which is not very satisfactory either.
You have your x values linearly scaled with np.linspace but your plot is log scaled. You could try np.geomspace for your x values or plot without the log scale.
Using spline will only work well for functions that are already smooth. What you need is to regularize the data and then interpolate afterwards. This will help to smooth out the bumps. Regularization is an advanced topic, and it would not be appropriate to discuss it in detail here.
Update: for regularization using machine learning, you might look into the scikit library for Python.
I have a 2D array of temperature over time data. There are about 7500 x-values and as much corresponding y-values (so one y for every x).
It looks like this:
The blue line in the middle is the result of my unsuccessful attempt to draw a plot line, which would represent the average of my data. Code:
import numpy as np
import matplotlib.pyplot as plt
data=np.genfromtxt("data.csv")
temp_av=[np.mean(data[1])]*len(data[0])
plt.figure()
plt.subplot(111)
plt.scatter(data[0],data[1])
plt.plot(data[0],temp_av)
plt.show()
However what I need is a curve, which will follow the rise in the temperature. Basically a line which will be somewhere in the middle of data points.
I googled for some solutions, but all I found were suggestions how to compute an average in cases where you have multiple y-values for one x. I understand how to do that, but it doesn't help in this case.
My next idea would be to use a loop to compute an average for every 2 neighbor points. But I am not sure how to do that best and if there aren't better solutions.
Also, I understand that what I need is to compute an other array. Plotting is only for representation.
If I undestrand correclty, what you are trying to plot is a trend line. You could do it by using the numpy function 'polyfit'. If that's what you are looking for, try this small modification to your code
import numpy as np
import matplotlib.pyplot as plt
data=np.genfromtxt("data.csv")
plt.figure()
plt.subplot(111)
plt.scatter(data[0],data[1])
pfit = np.polyfit(data[0], data[1], 1)
trend_line_model = np.poly1d(pfit)
plt.plot(data[0], trend_line_model(data[0]), "m--")
plt.show()
This will plot the trend line in dashed magenta
I'm plotting some 2D fields using matplotlib and the fields have to be seen with equal aspect ratio. But when I set the aspect ratio I find that there are unnecessary blank spaces. Please consider the following example:
from matplotlib import pyplot as plt
import numpy as np
x=np.arange(100)
y=np.arange(100)
Y, X = np.meshgrid(y,x)
Z = X + Y
plt.contourf(X, Y, Z)
#plt.axes().set_aspect('equal', 'datalim')
plt.tight_layout()
plt.colorbar()
plt.grid()
plt.show()
If I run that command I get this figure:
However, let's say I uncomment the line that sets the equal ratio . So let's say I include this:
plt.axes().set_aspect('equal', 'datalim')
I get the following output:
Which is a very poor use of space. I can't make the actual plot take better advantage of the figure space no matter how hard I try (I don't have that much knowledge of pyplot).
I there a way to expand the actual data part of the equal-ratio plot so that I have less white space?
Thank you.
The issue you're having is caused by "datalim", which asks the axes to apply the usual limits you would expect from a normal line or scatter plot, e.g. the use of 5% margin on each side of the shown data.
I do not see any reason to use "datalim" here. So you may just leave it out,
plt.axes().set_aspect('equal')
and get a plot with equal aspect and no white space around.
Trying to fit a sin function using curve_fit to some points here. When plotting both the fit and the points, I get something I have no idea how to explain, so I better post some images.
Using the following code line yields:
plt.plot(phase_min, sinusoidal_function(phase_min, *popt), '.', lw=3)
Using the line style '-', I get:
How can I just have a damn line connecting each adjacent dot, not all the dots in between?
Thanks!
When you plot a line in matplotlib, it automatically connects the points in the same order as they are provided. See the example below:
import matplotlib.pyplot as plt
plt.plot([1,3,2], [1,2,3])
Your problem is that your phase_min is not sorted and matplotlib is trying to connect your data points in order. Actually since you already got the fitted function, you don't need to use the original data to plot the function. You can just define the data points you want to plot the line as below. In this way you can have as many data points as you want to make the plot, so the line will be more smooth than if you make the plots using your original data points.
x=np.arange(0, 1, 0.001)
y=sinusoidal_function(x, *popt)
plt.plot(x,y)
You could use np.argsort:
order = np.argsort(x)
xsorted = x[order]
ysorted = y[order]
where x andy are the coordinates of your orange dots.
I wanted to create graphs for some math functions and tried to do this using matplotlib.I need to plot graphs of several functions in one plot sothat these can be compared against each other.
say these are the math functions
2**(math.log(x,2))
2**(2**(math.log(x,2)))
I tried this
from matplotlib.pyplot import plot as plt
x=arange(1000,1010)
y1=[2**(math.log(t,2)) for t in x ]
y2=[2**(2**(math.log(t,2))) for t in x ]
plt.plot(x,y1)
plt.plot(x,y2)
plt.show()
this only shows one graph..that of (x,y2)
how do I make all the graphs show in one plot?
edit:
using plt.plot(x,y1,x,y2) produces this graph
I don't think they are going to be visible on the same scale. The first one is essentially y = x, y is about 1000. The second one is y = 2**x, and x starts at 1000...
However, plotting with log scale can help:
matplotlib.pyplot.yscale('log')