Проблема при графике синусоидальных волн в python - PullRequest
2 голосов
/ 15 апреля 2020

Я написал следующую программу, используя python, чтобы отобразить несколько синусоидальных волн на разных частотах, а также отобразить точки пересечения между ними;

import numpy as np
import matplotlib.pyplot as plt
plt.style.use("ggplot")

fig = plt.figure()
ax = plt.axes()

f1 = float(input("Enter first frequency: "))
f2 = float(input("Enter second frequency: "))
t = np.linspace(0, 10, 1000)
y1 = np.sin(2*np.pi*f1*t)
y2 = np.sin(2*np.pi*f2*t)

plt.plot(t,y1, color = "firebrick", label = "sin({}Hz)".format(f1))
plt.plot(t,y2, color = "teal", label = "sin({}Hz)".format(f2))
plt.axhline(y = 0, color = "grey", linestyle = "dashed", label = "y = 0")

idx = np.argwhere(np.diff(np.sign(y1 - y2))).flatten()
plt.plot(t[idx], y1[idx], 'k.')

plt.legend(loc = "best", frameon=True, fancybox = True,
           shadow = True, facecolor = "white")

plt.axis([-0.5, 10.5, -1.5, 1.5])

plt.title("Sine Waves")
plt.xlabel("Time")
plt.ylabel("Amplitude")

plt.show()

Иногда результат выглядит просто как предполагается, например на этом скриншоте . Однако в другое время я получаю нежелательный вывод, такой как в этом . Может кто-нибудь продемонстрировать, как решить эту проблему? Спасибо.

1 Ответ

3 голосов
/ 15 апреля 2020

Я хотел бы предложить вам увеличить дискретизацию по времени или просто отобразить эти волны с точки зрения количества n_T периодов наивысшей / наименьшей частоты, чтобы избежать проблем недостаточной выборки. Например, если вас больше интересует самая низкая частота, вы можете изменить свой код следующим образом:

import numpy as np
import matplotlib.pyplot as plt
plt.style.use("ggplot")

fig = plt.figure()
ax = plt.axes()

f1 = float(input("Enter first frequency: "))
f2 = float(input("Enter second frequency: "))

n_T = float(input("Enter number of periods of lowest frequency to display: "))
t_max = n_T/min(f1,f2) # change here max or min if you want highest or lowest frequency to be represented on n_T periods

t = np.linspace(0, t_max, 1000)

y1 = np.sin(2*np.pi*f1*t)
y2 = np.sin(2*np.pi*f2*t)

plt.plot(t,y1, color = "firebrick", label = "sin({}Hz)".format(f1))
plt.plot(t,y2, color = "teal", label = "sin({}Hz)".format(f2))
plt.axhline(y = 0, color = "grey", linestyle = "dashed", label = "y = 0")

idx = np.argwhere(np.diff(np.sign(y1 - y2))).flatten()
plt.plot(t[idx], y1[idx], 'k.')


plt.legend(loc = "best", frameon=True, fancybox = True,
           shadow = True, facecolor = "white")

plt.axis([-0.05*t_max, 1.05*t_max, -1.5, 1.5])

plt.title("Sine Waves")
plt.xlabel("Time")
plt.ylabel("Amplitude")

plt.show()

, что дает для n_T=3 и f1=200 и f2=400 Гц:

1

и для вашей проблемы c кейс f1=520 и f2=750 Гц:

2

БОНУС : если вы хотите автоматически вычислить минимальное количество n_T периодов для отображения точного количества уникальных пересечений между двумя осциллирующими компонентами. Сначала преобразуйте пользовательские вводы f1 и f2 из чисел с плавающей точкой в ​​целые числа, затем найдите наименьшее общее кратное lcm между ними (используя функцию наибольшего общего делителя gcd из math) и разделите его на самую высокую частоту, здесь вы:

from math import gcd
def lcm(a,b):
    """
    Compute the lowest common multiple of a and b
    """
    return a*b/gcd(a,b)

# minimum of n_T periods to visualize every unique intersections of waves
n_T = lcm(f1,f2)/max(f1,f2)

например для f1=250 и f2=300 Гц n_T=1500/300=5, что даст:

bonus

...