根据信号位置调整 xrange
Adjust xrange depending on where signal is
假设我有一个数据流,为简单起见,将其设为贝尔曲线,从大范围获取:
import numpy as np
import matplotlib.pyplot as plt
def pdf(x, mean, std):
"""Return a PDF."""
y_out = 1/(std * np.sqrt(2 * np.pi)) * np.exp(-(x - mean)**2 / (2 * std**2))
return y_out
x = np.linspace(-1000, 1000, 20000)
y = 100 * pdf(x, 0, 1) + np.random.normal(0, 1, 20000)
fig, ax = plt.subplots()
ax.plot(x, y)
由于 x 范围太大,绘图将只显示一条非常窄的线,无论如何我们不需要在绘图中包含所有噪声。
在这种情况下,通过仅显示范围 [-20, 20]
来绘制它可能是有意义的,例如:ax.set_xlim([-20, 20])
。
但是,假设现在我们从另一次收购中得到了类似的东西:
y = 100 * pdf(x, -50, 1) + 100 * pdf(x, 0, 1) + 100 * pdf(x, 40, 1) + np.random.normal(0, 1, 20000)
有了这样的功能,我们可能想要绘制更宽的范围,例如ax.set_xlim([-70, 60])
,可视化获取的所有信号。
有没有一种方法可以根据实际信号(即超过某个阈值,比如 10)以编程方式调整限制,而不必先绘制整个范围,然后再手动调整?
使用 argwhere
获取 y
高于特定阈值的索引,例如np.argwhere(y > 10)
。在实践中,您可能希望在两侧添加一些边距,例如 200 点:
import numpy as np
import matplotlib.pyplot as plt
def pdf(x, mean, std):
"""Return a PDF."""
y_out = 1/(std * np.sqrt(2 * np.pi)) * np.exp(-(x - mean)**2 / (2 * std**2))
return y_out
x = np.linspace(-1000, 1000, 20000)
y = [100 * pdf(x, 0, 1) + np.random.normal(0, 1, 20000),
100 * pdf(x, -50, 1) + 100 * pdf(x, 0, 1) + 100 * pdf(x, 40, 1) + np.random.normal(0, 1, 20000)]
def get_lims(y, threshold=10, margin=200):
"""Get indices +/- margin where y is above threshold."""
signal = np.argwhere(y > threshold).flatten()
return np.clip((signal[0] - margin, signal[-1] + margin), 0, len(y)-1)
fig, ax = plt.subplots(nrows=2)
for i in range(2):
ax[i].plot(x, y[i])
ax[i].set_xlim(x[get_lims(y[i])])
与 Stef 的答案非常相似,只是我提出了一个最小宽度和一个额外的百分比,因此边距将取决于您要显示的 x
的数量,而不是边距,因此您可以调整 window_excess
和 min_width
。如果你有很多情节要制作,这样的东西可能会有用。用这个替换 Stef 的 get_lims
函数会得到结果:
def get_lims(y, threshold = 10, window_excess = 0.5, min_width = 100):
minwidth = min_width / (1 + window_excess)
a = np.argwhere(y > threshold)
da = max(minwidth, x[a[-1]] - x[a[0]])
ma = (x[a[-1]] + x[a[0]]) / 2
minx = ma - da * (1 + window_excess) / 2
maxx = ma + da * (1 + window_excess) / 2
return([minx, maxx])
您只需添加一个检查,确保 xmin
和 xmax
在 x 的范围内。
假设我有一个数据流,为简单起见,将其设为贝尔曲线,从大范围获取:
import numpy as np
import matplotlib.pyplot as plt
def pdf(x, mean, std):
"""Return a PDF."""
y_out = 1/(std * np.sqrt(2 * np.pi)) * np.exp(-(x - mean)**2 / (2 * std**2))
return y_out
x = np.linspace(-1000, 1000, 20000)
y = 100 * pdf(x, 0, 1) + np.random.normal(0, 1, 20000)
fig, ax = plt.subplots()
ax.plot(x, y)
由于 x 范围太大,绘图将只显示一条非常窄的线,无论如何我们不需要在绘图中包含所有噪声。
在这种情况下,通过仅显示范围 [-20, 20]
来绘制它可能是有意义的,例如:ax.set_xlim([-20, 20])
。
但是,假设现在我们从另一次收购中得到了类似的东西:
y = 100 * pdf(x, -50, 1) + 100 * pdf(x, 0, 1) + 100 * pdf(x, 40, 1) + np.random.normal(0, 1, 20000)
有了这样的功能,我们可能想要绘制更宽的范围,例如ax.set_xlim([-70, 60])
,可视化获取的所有信号。
有没有一种方法可以根据实际信号(即超过某个阈值,比如 10)以编程方式调整限制,而不必先绘制整个范围,然后再手动调整?
使用 argwhere
获取 y
高于特定阈值的索引,例如np.argwhere(y > 10)
。在实践中,您可能希望在两侧添加一些边距,例如 200 点:
import numpy as np
import matplotlib.pyplot as plt
def pdf(x, mean, std):
"""Return a PDF."""
y_out = 1/(std * np.sqrt(2 * np.pi)) * np.exp(-(x - mean)**2 / (2 * std**2))
return y_out
x = np.linspace(-1000, 1000, 20000)
y = [100 * pdf(x, 0, 1) + np.random.normal(0, 1, 20000),
100 * pdf(x, -50, 1) + 100 * pdf(x, 0, 1) + 100 * pdf(x, 40, 1) + np.random.normal(0, 1, 20000)]
def get_lims(y, threshold=10, margin=200):
"""Get indices +/- margin where y is above threshold."""
signal = np.argwhere(y > threshold).flatten()
return np.clip((signal[0] - margin, signal[-1] + margin), 0, len(y)-1)
fig, ax = plt.subplots(nrows=2)
for i in range(2):
ax[i].plot(x, y[i])
ax[i].set_xlim(x[get_lims(y[i])])
与 Stef 的答案非常相似,只是我提出了一个最小宽度和一个额外的百分比,因此边距将取决于您要显示的 x
的数量,而不是边距,因此您可以调整 window_excess
和 min_width
。如果你有很多情节要制作,这样的东西可能会有用。用这个替换 Stef 的 get_lims
函数会得到结果:
def get_lims(y, threshold = 10, window_excess = 0.5, min_width = 100):
minwidth = min_width / (1 + window_excess)
a = np.argwhere(y > threshold)
da = max(minwidth, x[a[-1]] - x[a[0]])
ma = (x[a[-1]] + x[a[0]]) / 2
minx = ma - da * (1 + window_excess) / 2
maxx = ma + da * (1 + window_excess) / 2
return([minx, maxx])
您只需添加一个检查,确保 xmin
和 xmax
在 x 的范围内。