I have some trouble in using the curve_fit function - python-3.x

I want to fit a scatter plot with the curve_fit function. But although I wrote the codes as the tutorial said, it just didn't work.Could someone please help me check the code?
import numpy as np
from matplotlib import rcParams
from matplotlib.font_manager import FontProperties
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
rcParams['axes.unicode_minus']=False
myfont = FontProperties(fname='/Library/Fonts/Songti.ttc',size=15)
ydata=[78,78,77.9,74,8,70.1,65.8,58.2,40,5.0,14.0,30,60,69,74,74.2,78,78]
xdata = [257.6695,257.6695,257.6695,307.7231,316.009,309.4141,310.936,312.627,314.4871,316.3472, 317.0236,317.7,319.391,321.082,322.9421, 324.464, 341.7122,426.7695]
plt.plot(xdata,ydata,'*')
plt.xlabel('磁感应强度B(mT)',fontproperties=myfont)
plt.ylabel('检波电流(μA)', fontproperties=myfont)
def func(x,amp,cen,wid):
return amp*np.exp(-(x-cen)**2/wid)
popt,pcov = curve_fit(func,xdata,ydata)
print(popt)
amp = popt[0]
cen = popt[1]
wid = popt[2]
residuals = ydata-func(xdata,amp,cen,wid)
fres = sum(residuals**2)
print(fres)
xaxis = np.linspace(250,450,100)
curve_y = func(xaxis,amp,cen,wid)
plt.plot(xaxis,curve_y)

With maplotlib.pyplot, you need to explicitly state that you want to “show” the plot in order to have it displayed.
plt.plot(x, y) will create the barebones of the graph, but there are still many changes one could make: adding additional figures or subplots, adding additional data sets to the plot for comparison or changing colours!
Until you explicitly say “show me the plot at this point in the code”, then nothing will happen. Try adding the following to the end of your code:
plt.show()

Related

Python matplotlib custom colorbar for plotted lines with manually assigned colors

I'm trying to define a colorbar for the following type of plot.
import matplotlib.pyplot as plt
import numpy as np
for i in np.arange(0,10,0.1):
plt.plot(range(10),np.ones(10)*i,c=[i/10.,0.5,0.25])
plt.show()
This is just a simplified version of my actual data, but basically, I'd like a series of lines plotted and colored by another variable with a colorbar key. This is easy to do in scatter, but I can't get scatter to plot connected lines. Points are too clunky. I know this sounds like basic stuff, but I'm having a helluva time finding a simple solution ... what obvious solution am I missing?
You can build a custom color map and a mappable from it, then pass to colorbar:
from matplotlib.cm import ScalarMappable
from matplotlib.colors import Normalize
import matplotlib.colors as mcolors
color_list = [(i/10, 0.5,0.25) for i in np.arange(0,10,0.1)]
cmap = mcolors.LinearSegmentedColormap.from_list("my_colormap", color_list)
cmappable = ScalarMappable(norm=Normalize(0,10), cmap=cmap)
plt.figure(figsize=(10,10))
for j,i in enumerate(np.arange(0,10,0.1)):
plt.plot(range(10),np.ones(10)*i,c=color_list[j])
plt.colorbar(cmappable)
plt.show()
Output:

X and Y label being cut in matplotlib plots

I have this code:
import pandas as pd
from pandas import datetime
from pandas import DataFrame as df
import matplotlib
from pandas_datareader import data as web
import matplotlib.pyplot as plt
import datetime
start = datetime.date(2016,1,1)
end = datetime.date.today()
stock = 'fb'
fig = plt.figure(dpi=1400)
data = web.DataReader(stock, 'yahoo', start, end)
fig, ax = plt.subplots(dpi=720)
data['vol_pct'] = data['Volume'].pct_change()
data.plot(y='vol_pct', ax = plt.gca(), title = 'this is the title \n second line')
ax.set(xlabel="Date")
ax.legend(loc='upper center', bbox_to_anchor=(0.32, -0.22), shadow=True, ncol=2)
plt.savefig('Test')
This is an example of another code but the problem is the same:
At bottom of the plot you can see that the legend is being cut out. In another plot of a different code which i am working on, even the ylabel is also cut when i save the plot using plt.savefig('Test').How can i can fix this?
It's a long-standing issue with .savefig() that it doesn't check legend and axis locations before setting bounds. As a rule, I solve this with the bbox_inches argument:
plt.savefig('Test', bbox_inches='tight')
This is similar to calling plt.tight_layout(), but takes all of the relevant artists into account, whereas tight_layout will often pull some objects into frame while cutting off new ones.
I have to tell pyplot to keep it tight more than half the time, so I'm not sure why this isn't the default behavior.
plt.subplots_adjust(bottom=0.4 ......)
I think this modification will satisfy you.
Or maybe you can relocate the legend to loc="upper left"
https://matplotlib.org/api/_as_gen/matplotlib.pyplot.subplots_adjust.html
please also checked this issue which raised 8 years ago..
Moving matplotlib legend outside of the axis makes it cutoff by the figure box

Matplotlib function visualtization changing with precision

So I was trying to map out some math functions in 3d using matplotlib when I noticed something... The 3d plot suddenly changed (more like broke) when I tried to fix a previous issue wherein I was encountering some 'missing surface' - a gap in the plot. The main question is this -- Is the 3d plot not showing the two peaks on higher precision due to some inherent computing limitations of Axes3d or some other reason? Also a secondary question -- Why am I encountering 'missing surfaces' near +1.25 and -1.25 in lower precision plot?
I have tried googling for it and referred a few posts but nothing came ot except more questions.
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
X=np.arange(-2,+2,0.025)
## Use np.arange(-5,+5,0.25) to experience the 'surface loss' I mention but otherwise correct 2 spike plot at each of (0,-1) and (0,+1) for both X and Y
Y=np.arange(-2,+2,0.025)
X,Y=np.meshgrid(X,Y)
R=1+X**2-Y**2
S=R**2+4*(X**2)*(Y**2)
Z=R/S
fig=plt.figure()
ax=Axes3D(fig)
ax.plot_surface(X,Y,Z,rstride=1,cstride=1,cmap=cm.viridis,norm=mpl.colors.Normalize(vmin=-1.,vmax=1.))
##NORMALIZE Was essential to get the proper color range
plt.show()
plt.savefig('art3d.jpeg',bbox_inches='tight')
plt.savefig('art3d.svg',bbox_inches='tight')
The ideal result should be like this (shows the func and the plot)
https://i.stack.imgur.com/kVnYc.png
The two plots I'm getting could be seen when the code is run as I can't seem to add images presumably because of low reputation :(
Any and all help is appreciated.Thanks in advance.
First note that the function in use is different from the wolfram alpha output. So let's use the function shown in the screenshot. Then you can limit the data to the range you want to show.
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
X = np.arange(-2,+2,0.025)
Y=np.arange(-2,+2,0.025)
X,Y=np.meshgrid(X,Y)
Z = -2*X*Y / ((2*X*Y)**2 + (X**2 - Y**2 + 1)**2)
Z[(Z < -1)] = -1
Z[(Z > 1)] = 1
fig=plt.figure()
ax=Axes3D(fig)
ax.plot_surface(X,Y,Z,rstride=1,cstride=1,cmap=cm.viridis,norm=mpl.colors.Normalize(vmin=-1.,vmax=1.))
plt.show()

Y-axis values not showing in matplotlib.pyplot plot

My plot is not showing any indication of what the order of magnitude of my y-values are on the axis. How do I force python to indicate some values on the y-axis?
import numpy as np
import matplotlib.pyplot as plt
BERfinal = [0.4967843137254903, 0.49215686274509757, 0.4938823529411763,
0.49170588235294116, 0.48852941176470605, 0.48203921568627417,
0.4797058823529405, 0.47454901960784257, 0.4795686274509802,
0.474901960784313, 0.4732549019607838, 0.4703137254901953,
0.4705490196078425]
x = np.linspace(-4,8,len(BERfinal))
plt.semilogy(x,BERfinal)
plt.title("BER vs SNR")
plt.ylabel("Bit Error Rate(BER)")
plt.xlabel("Signal-to-Noise Ratio(SNR)[dB]")
plt.xlim(-4,8)
I ended up playing around with:
plt.ylim(4.7*10**-1, 5*10**-1)
and changed the values until I found an appropriate range. It now shows 5x10^-1 on the y-axis.

Matplotlib.animation.FuncAnimation using pcolormesh

Python 3.5, windows 10 Pro.
I'm trying to continuously plot an 8x8 array of pixels (for the sake of the question I'll just use random data, but in the real thing I'm reading from a serial port).
I can do it using a while loop, but I need to switch over to matplotlib.animation.FuncAnimation and I can't get it to work. I've tried looking at the help files and tried to follow examples from matplotlib.org here, but I've not been able to follow it.
Can someone help me figure out how to continuously plot an 8x8 array of pixels using FuncAnimation and pcolormesh? Here is what I've got so far:
import scipy as sp
import matplotlib.pyplot as plt
from matplotlib import animation
plt.close('all')
y = sp.rand(64).reshape([8,8])
def do_something():
y = sp.rand(64).reshape([8,8])
fig_plot.set_data(y)
return fig_plot,
fig1 = plt.figure(1,facecolor = 'w')
plt.clf()
fig_plot = plt.pcolormesh(y)
fig_ani = animation.FuncAnimation(fig1,do_something)
plt.show()
If you want to see the while loop code, just so you know exactly what I'm trying to reproduce, see below.
import scipy as sp
import matplotlib.pyplot as plt
plt.figure(1)
plt.clf()
while True:
y = sp.rand(64).reshape([8,8])
plt.pcolormesh(y)
plt.show()
plt.pause(.000001)
I was able to find a solution using imshow instead of pcolormesh. In case anyone else is struggling with the same issues I had, I've posted the working code below.
import scipy as sp
import matplotlib.pyplot as plt
import matplotlib.animation as animation
Hz = sp.rand(64).reshape([8,8]) # initalize with random data
fig = plt.figure(1,facecolor='w')
ax = plt.axes()
im = ax.imshow(Hz)
im.set_data(sp.zeros(Hz.shape))
def update_data(n):
Hz = sp.rand(64).reshape([8,8]) # More random data
im.set_data(Hz)
return
ani = animation.FuncAnimation(fig, update_data, interval = 10, blit = False, repeat = False)
fig.show()

Resources