Curve fitting exponential function with semilog x-axis - matplotlib

I'm having trouble fitting some date onto an exponential function with a semilog x-axis.
Following is the code:
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
kd=np.array[0.735420099, 0.700823723, 0.647775947,0.613179572,0.573970346,0.54398682,0.454036244,0.371004942,0.292586491,0.271828666,0.21878089,0.165733114,0.157660626,0.151894563]
ADAR = np.array[0.001012268,0.002028379,0.004015198,0.005931555,0.007948127,0.010143277,0.019594977,0.039746044,0.076782168,0.101639121,0.193968714,0.574178304,0.778822803,0.9878803]
def func(x,a,c,d):
return a*np.exp(-c*x)+d
init_v = (1,1e-6,0)
opt,pcov = curve_fit(func,ADAR,kd,init_v)
a,c,d = opt
x2 = np.linspace(0.001,1)
y2 = func(x2,a,c,d)
plt.grid(True, which = "both")
fig = plt.figure()
ax = plt.gca()
ax.scatter(ADAR,kd, c = 'blue')
ax.set_xscale('log')
plt.xlim([0.001,1])
plt.ylim([0,0.8])
plt.plot(x2,y2, '-', label = 'fit')
plt.legend()
plt.title('Area pressure coefficient')
plt.xlabel('AD/AR')
plt.ylabel('kd')
plt.show
Trying to fit the scatter plot:
Using Scipy Curve_fit with initial guesses I am unable to get a close fit of the data. Am I using the wrong function for this?

Related

imshow() extent limits not giving correct solution

I am a novice to python. I was trying to plot 2 D color plot using imshow(). Here, x axis is the time scale, yaxis is the energy and the colorbar z axis is the differential energy flux. When i plot somehow the y axis do not correspond to the actual value. I had tried using contourf as well as plotly heatmap. However I find though the results come correctly it does not have the same visual impact as imshow.
import matplotlib.pyplot as plt
from matplotlib import colors
import numpy as np
import matplotlib.dates as mdates
from mpl_toolkits.axes_grid1 import make_axes_locatable
import datetime as dt
x_lims = list(map(dt.datetime.utcfromtimestamp, [1266050102.1784432, 1266054264.5317998]))
x_lims = mdates.date2num(x_lims)
y1 = [3.1209615e+04, 2.6360914e+04, 2.0025836e+04, 1.5213330e+04, 1.1557158e+04,
8.7796689e+03, 6.6698813e+03, 5.0668237e+03, 3.8490525e+03, 2.9246511e+03,
2.2212300e+03, 1.6873538e+03, 1.2815887e+03, 9.7440747e+02, 7.3961621e+02,
5.6149872e+02, 4.2719626e+02, 3.2432623e+02, 2.4669749e+02, 1.8716624e+02,
1.4239874e+02, 1.0858500e+02, 8.2391251e+01, 6.2388748e+01, 4.7625000e+01,
3.6195000e+01, 2.7622499e+01, 2.0478750e+01, 1.5716249e+01, 1.2382500e+01,
9.0487499e+00, 7.1437497e+00]
y = np.array(y1)
y_lims = [y.min(), y.max()]
extent_lims = [x_lims[0], x_lims[1], y_lims[0], y_lims[1]]
z = flux_elec.T
fig, ax = plt.subplots()
im = ax.imshow(z, interpolation='none', extent=extent_lims, cmap='jet', aspect='auto')
date_format = mdates.DateFormatter('%H:%M')
ax.set_yscale('log')
ax.xaxis.set_major_formatter(date_format)
ax.xaxis_date()
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="5%", pad=0.05)
plt.colorbar(im, cax=cax, label="diff. en. flux")
[enter image description here](https://i.stack.imgur.com/Op1X7.png)
In this the high energy flux (8) should finish before 100 but its extending till 5000. I am unable to locate the error.

Why does this plot not update ? (matplotlib)

Code below, I want to write a code that updates its function by cearing the axes and assigning new plots. It works when I only have one plot, but doesnt when I use subplots()...
Thanks
import numpy as np
import matplotlib.pyplot as plt
import time
fig , ax = plt.subplots(1,2)
x = np.linspace(0,10,10)
alpha = 0.70
def sin(x):
return np.sin(alpha*x)
def lin(x):
return alpha*x
for i in range(5):
ax[0].clear()
ax[1].clear()
ax[0].plot(x,lin(x), marker='o', label = str(i))
ax[1].plot(x,sin(x), marker='o')
fig.legend()
plt.show()
alpha = alpha**2
time.sleep(0.5)

I cannot fit my data logarithmically, How can I add log trendline?

So this is my code, it's written a little messy and my result is absolutely ridiculous. I have no idea how to fix it.
Also, the seaborn library does not work on my computer in any way.
.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
data=pd.read_csv('Data.csv',encoding="latin1",sep=";",engine="python")
table = data.replace(0, 0.1)
plt.plot(table["RMDM"], table["BSURF"], color="#03012d", marker=".", ls="None", markersize=3, label="")
data['RMDM'] = data['RMDM'].astype(float)
data['BSURF'] = data['BSURF'].astype(float)
fig, ax = plt.subplots()
x=data['BSURF']
y=data['RMDM']
ax.set_yscale('log')
ax.set_xscale('log')
plt.style.use('classic')
plt.xlabel('B_LC')
plt.ylabel('RM/DM')
plt.plot(x,y, 'og')
from scipy.stats import linregress
df = data.loc[(data['RMDM'] >0) & (data['BSURF'] >0)]
stats = linregress(np.log10(df["RMDM"]),np.log10(df["BSURF"]))
m = stats.slope
b = stats.intercept
r = stats.rvalue
x = np.logspace(-1, 5, base=10)
y = (m*x+b)
plt.plot(x, y, c='orange', label="fit")
plt.legend()
#m,c=np.polyfit(x,y,1)
#plt.plot(x,m*x+c)
plt.grid()
plt.show()
lmplot can be used to create a linear line through your data. you correctly used np.log for the linear regression data. keep x in terms of the log.
df['log_col1']=np.log(df['col1'])
sns.lmplot(x='log_col1','y='target', data=df, ci=None)
sns.scatterplot(y='target',x='log_col1',data=df)
plt.show()

Matplotlib: strange minor ticks with log base 2 colorbar

I am plotting some contours with tricontourf. I want the colormap to be scaled in log values and tick labels and colours bounds to be in log base 2. Here's my code:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.tri as tri
import matplotlib.ticker as ticker
import matplotlib.colors as colors
section = 'T7'
data = np.loadtxt( section + '_values.dat')
x = data[:,0]
y = data[:,1]
z = data[:,2]
triang = tri.Triangulation(x,y)
fig1, ax1 = plt.subplots()
ax1.set_aspect('equal')
bounds = [2.**-1,2.**1,2**3,2**5,2**7,2**9]
norm = colors.LogNorm()
formatter = ticker.LogFormatter(2)
tcf = ax1.tricontourf(triang, z, levels = bounds, cmap='hot_r', norm = norm )
fig1.colorbar(tcf, format=formatter)
plt.show()
And here's the result:
What are thos ugly minor ticks and how do I get rid of them?
Using Matplotlib 3.3.0 an Mac OS
You could use cb.ax.minorticks_off() to turn off the minor tick and cb.ax.minorticks_on() to turn it on.
cb = fig1.colorbar(tcf, format=formatter)
cb.ax.minorticks_off()
matplotlib.pyplot.colorbar returns a Colorbar object which extends ColorbarBase.
You can find that two functions in the document of class matplotlib.colorbar.ColorbarBase.

Embedding small plots inside subplots in matplotlib

If you want to insert a small plot inside a bigger one you can use Axes, like here.
The problem is that I don't know how to do the same inside a subplot.
I have several subplots and I would like to plot a small plot inside each subplot.
The example code would be something like this:
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
for i in range(4):
ax = fig.add_subplot(2,2,i)
ax.plot(np.arange(11),np.arange(11),'b')
#b = ax.axes([0.7,0.7,0.2,0.2])
#it gives an error, AxesSubplot is not callable
#b = plt.axes([0.7,0.7,0.2,0.2])
#plt.plot(np.arange(3),np.arange(3)+11,'g')
#it plots the small plot in the selected position of the whole figure, not inside the subplot
Any ideas?
I wrote a function very similar to plt.axes. You could use it for plotting yours sub-subplots. There is an example...
import matplotlib.pyplot as plt
import numpy as np
#def add_subplot_axes(ax,rect,facecolor='w'): # matplotlib 2.0+
def add_subplot_axes(ax,rect,axisbg='w'):
fig = plt.gcf()
box = ax.get_position()
width = box.width
height = box.height
inax_position = ax.transAxes.transform(rect[0:2])
transFigure = fig.transFigure.inverted()
infig_position = transFigure.transform(inax_position)
x = infig_position[0]
y = infig_position[1]
width *= rect[2]
height *= rect[3] # <= Typo was here
#subax = fig.add_axes([x,y,width,height],facecolor=facecolor) # matplotlib 2.0+
subax = fig.add_axes([x,y,width,height],axisbg=axisbg)
x_labelsize = subax.get_xticklabels()[0].get_size()
y_labelsize = subax.get_yticklabels()[0].get_size()
x_labelsize *= rect[2]**0.5
y_labelsize *= rect[3]**0.5
subax.xaxis.set_tick_params(labelsize=x_labelsize)
subax.yaxis.set_tick_params(labelsize=y_labelsize)
return subax
def example1():
fig = plt.figure(figsize=(10,10))
ax = fig.add_subplot(111)
rect = [0.2,0.2,0.7,0.7]
ax1 = add_subplot_axes(ax,rect)
ax2 = add_subplot_axes(ax1,rect)
ax3 = add_subplot_axes(ax2,rect)
plt.show()
def example2():
fig = plt.figure(figsize=(10,10))
axes = []
subpos = [0.2,0.6,0.3,0.3]
x = np.linspace(-np.pi,np.pi)
for i in range(4):
axes.append(fig.add_subplot(2,2,i))
for axis in axes:
axis.set_xlim(-np.pi,np.pi)
axis.set_ylim(-1,3)
axis.plot(x,np.sin(x))
subax1 = add_subplot_axes(axis,subpos)
subax2 = add_subplot_axes(subax1,subpos)
subax1.plot(x,np.sin(x))
subax2.plot(x,np.sin(x))
if __name__ == '__main__':
example2()
plt.show()
You can now do this with matplotlibs inset_axes method (see docs):
from mpl_toolkits.axes_grid.inset_locator import inset_axes
inset_axes = inset_axes(parent_axes,
width="30%", # width = 30% of parent_bbox
height=1., # height : 1 inch
loc=3)
Update: As Kuti pointed out, for matplotlib version 2.1 or above, you should change the import statement to:
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
There is now also a full example showing all different options available.
From matplotlib 3.0 on, you can use matplotlib.axes.Axes.inset_axes:
import numpy as np
import matplotlib.pyplot as plt
fig, axes = plt.subplots(2,2)
for ax in axes.flat:
ax.plot(np.arange(11),np.arange(11))
ins = ax.inset_axes([0.7,0.7,0.2,0.2])
plt.show()
The difference to mpl_toolkits.axes_grid.inset_locator.inset_axes mentionned in #jrieke's answer is that this is a lot easier to use (no extra imports etc.), but has the drawback of being slightly less flexible (no argument for padding or corner locations).
source: https://matplotlib.org/examples/pylab_examples/axes_demo.html
from mpl_toolkits.axes_grid.inset_locator import inset_axes
import matplotlib.pyplot as plt
import numpy as np
# create some data to use for the plot
dt = 0.001
t = np.arange(0.0, 10.0, dt)
r = np.exp(-t[:1000]/0.05) # impulse response
x = np.random.randn(len(t))
s = np.convolve(x, r)[:len(x)]*dt # colored noise
fig = plt.figure(figsize=(9, 4),facecolor='white')
ax = fig.add_subplot(121)
# the main axes is subplot(111) by default
plt.plot(t, s)
plt.axis([0, 1, 1.1*np.amin(s), 2*np.amax(s)])
plt.xlabel('time (s)')
plt.ylabel('current (nA)')
plt.title('Subplot 1: \n Gaussian colored noise')
# this is an inset axes over the main axes
inset_axes = inset_axes(ax,
width="50%", # width = 30% of parent_bbox
height=1.0, # height : 1 inch
loc=1)
n, bins, patches = plt.hist(s, 400, normed=1)
#plt.title('Probability')
plt.xticks([])
plt.yticks([])
ax = fig.add_subplot(122)
# the main axes is subplot(111) by default
plt.plot(t, s)
plt.axis([0, 1, 1.1*np.amin(s), 2*np.amax(s)])
plt.xlabel('time (s)')
plt.ylabel('current (nA)')
plt.title('Subplot 2: \n Gaussian colored noise')
plt.tight_layout()
plt.show()