使用for loop绘制多条曲线和交点?

2024-06-25 05:32:44 发布

您现在位置:Python中文网/ 问答频道 /正文

我现在想用Python在同一个图上绘制多个指数函数(大约100个)

对于指数函数,我有参数ab的值:

def exponenial_func(x, a, b):
    return a * np.exp(-b * x)


popt1 = [8.05267292e+03, 1.48857925e+00]
x = np.linspace(0, 15, 30000)
yfun = exponenial_func(x, *popt1)

现在,我想用exponential_func来绘制popt1的倍数,从110倍,以0.1为步长。我还想在同一个图上绘制nthn-1th曲线之间的交点(如果可能的话)

到目前为止,我尝试了以下代码,但这不起作用:

import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import scipy.optimize as optimize
from scipy.optimize import curve_fit
import matplotlib.pylab as pl


def exponenial_func(x, a, b):
    return a * np.exp(-b * x)


x = np.linspace(0, 15, 30000)

popt1 = [8.05267292e+03, 1.48857925e+00]

# use a loop to plot multiples of popt1 applied to
# exponenial_func from 1x to 10x in steps of
# 0.1x (100 plots total) - create envelope
# --------------------------------------

# create color palette
# -----------------
n = 100
# choose a matplotlib color map
colors = pl.cm.gist_heat(np.linspace(0, 1, n))
# -----------------
fig = plt.figure(figsize=(4.5, 3.6))
ax = fig.add_subplot(1, 1, 1)
ax.set_ylim([1e2, 1e5])
ax.set_xlim([0, 1])

ax.set_yscale("log")

ax.spines['right'].set_visible(True)
ax.spines['top'].set_visible(True)
ax.spines['left'].set_visible(True)
ax.spines['bottom'].set_visible(True)
ax.set_xlabel('x')
ax.set_ylabel('y')

# enable minor ticks
ax.minorticks_on()

# put grid behind curves
ax.set_axisbelow(True)

ax.xaxis.grid(True, which='minor')
ax.xaxis.set_minor_formatter(matplotlib.ticker.NullFormatter())

# turn on major grid
ax.grid(b=True, which='major', color='black', linestyle='-', zorder=1, linewidth=0.4, alpha=0.12)

# turn on minor grid
ax.grid(b=True, which='minor', color='black', linestyle='-', zorder=1, linewidth=0.4, alpha=0.12)

ax.tick_params(direction='out', axis='both', which='both', pad=4)
ax.xaxis.set_ticks_position('bottom')

for i in np.arange(1, 10, n):
    popt_i = i * popt1
    # find the previous set of paramets (cannot multiply list by float?)
    popt_prev = (i - 10 / n) * popt1
    yfun_i = exponenial_func(x, *popt_i)
    yfun_prev = exponenial_func(x, *popt_prev)
    idx_i = np.argwhere(np.diff(np.sign(yfun_i - yfun_prev))).flatten()

    ax.plot(x, yfun_i, zorder=1, c=colors[i], linewidth=1, alpha=1)
    ax.scatter(x[idx_i], yfun_i[idx_i], s=4, alpha=1, zorder=4, color="black")

plt.savefig('test.png', dpi=300, bbox_inches='tight', format='png')

如果有人注释了这些行:

#yfun_prev = exponenial_func(x, *popt_prev)
#idx_i = np.argwhere(np.diff(np.sign(yfun_i - yfun_prev))).flatten()
#ax.scatter(x[idx_i], yfun_i[idx_i], s=4, alpha=1, zorder=4, color="black")

为了删除代码中查看交点的任何部分,代码将运行,但我仅将其作为绘图:

如果代码中保留了上述行,则会出现以下错误:

File "envelope.py", line 63, in <module>
    popt_prev = (i - 10 / n) * popt1
TypeError: can't multiply sequence by non-int of type 'numpy.float64'

有人知道如何在Python中实现这一点吗


Tags: importtruematplotlibnpaxgridcolorfunc
1条回答
网友
1楼 · 发布于 2024-06-25 05:32:44

下面的代码总结了我的所有评论,修复了一些小错误,并触及了原始代码中的一些视觉参数,并将生成下图:

import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.pylab as pl


def fx(x, a, b):
    return a * np.exp(-b * x)


n = 100
x = np.linspace(0, 15, 30000)
popt1 = np.array([8.05267292e+03, 1.48857925e+00])

colorspace = pl.cm.prism(np.linspace(0, 1, n))

fig = plt.figure(figsize=(4.5, 3.6))
ax = fig.add_subplot(1, 1, 1)
ax.set_ylim([1e2, 1e5])
ax.set_xlim([0, 1])

ax.set_yscale("log")

ax.spines[:].set_visible(True)
ax.spines[:].set_linewidth(0.4)

ax.set_xlabel('x')
ax.set_ylabel('f(x) = a * exp(-b * x)')

ax.minorticks_on()

ax.set_axisbelow(True)

ax.xaxis.grid(True, which='minor')
ax.xaxis.set_minor_formatter(matplotlib.ticker.NullFormatter())

ax.grid(True, which='major', alpha=.75, color='pink', ls='solid', lw=.5, zorder=1)
ax.grid(True, which='minor', alpha=.75, color='pink', ls='solid', lw=.5, zorder=1)

ax.tick_params(direction='out', axis='both', pad=4, width=.5, which='both')

ax.xaxis.set_ticks_position('bottom')

for i in range(n):
    popt_i = np.multiply(popt1, 1 + i // 10)
    popt_prev = np.multiply(popt1, i - 10 / n)
    yfun_i = fx(x, *popt_i)
    yfun_prev = fx(x, *popt_prev)
    idx_i = np.argwhere(np.diff(np.sign(yfun_i - yfun_prev))).flatten()
    ax.plot(x, yfun_i, c=colorspace[i], lw=.25, zorder=2)
    ax.scatter(x[idx_i], yfun_i[idx_i], s=.5, zorder=3)

plt.savefig('test.png', dpi=300, bbox_inches='tight', format='png')

相关问题 更多 >