%matplotlib ipympl
import numpy as np
import scipy as sp
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button
def ODE_r(x, t, params):
r, d1t_r = x
q, m, U_0, w, r_0 = params
derivs = [d1t_r,
-1 * (q / m) * U_0 * np.sin(w * t) * (r / r_0)]
return derivs
def ODE_z(y, t, params):
z, d1t_z = y
q, m, U_0, w, r_0 = params
derivs = [d1t_z,
(q / m) * U_0 * np.sin(w * t) * 2 * (z / r_0)]
return derivs
q = 1 # Mass of particle
q_u = sp.constants.e # Unit in e (C)
m = 1836 # Mass of particle
m_u = sp.constants.m_e # Unit in electron mass (kg)
U_0 = 10 # Amplitude of AC voltage
U_0_u = 1 # Unit in V
w = 4000 # Frequency of AC voltage
w_u = 1 # Unit in Hz
r_0 = 1000 # Geometrical factor
r_0_u = 1 # Unit?
# Initial values in m und m/s
r0 = 2e-6
d1t_r0 = 1e-3
z0 = -1e-6
d1t_z0 = 1e-3
# Define parameters for ODE solver and slider
def params(q, m, U_0, w, r_0):
func = [q*q_u, m*m_u, U_0*U_0_u, w*w_u, r_0]
return func
# Initial values for ODE solver
x0 = [r0, d1t_r0]
y0 = [z0, d1t_z0]
# Time array for solution (in s)
tStop = 0.1
tInc = 0.00005
Zeit = np.arange(0, tStop, tInc)
# Define numeric solution
def r_n(f, v0, t, parameters):
func = sp.integrate.odeint(f, v0, t, args=(parameters,))
return func[:,0]
def z_n(f, v0, t, parameters):
func = sp.integrate.odeint(f, v0, t, args=(parameters,))
return func[:,0]
fig = plt.figure(figsize=(8, 11), dpi=100)
ax = fig.add_subplot(111)
# Adjust the subplots region to leave some space for the sliders and buttons
fig.subplots_adjust(left=0.15, bottom=0.4)
# Draw the initial plot
# The 'line' variable is used for modifying the line later
[line] = ax.plot(r_n(ODE_r, x0, Zeit, params(q, m, U_0, w, r_0)), z_n(ODE_z, y0, Zeit, params(q, m, U_0, w, r_0)),
marker=',',
linestyle='-',
color='#008080',
label='trajectory')
#ax.set_xlim([0, 1])
#ax.set_ylim([-10, 10])
plt.xlabel('r / m')
plt.ylabel('z / m')
plt.title('Particle trajectory in the r - z plane of a Paul trap',
fontsize=12)
# plt.legend(loc='best', fancybox=True, shadow=True)
plt.grid(True)
# Sliders for tweaking the parameters
axis_color = 'lightgoldenrodyellow'
q_slider_ax = fig.add_axes([0.25, 0.3, 0.65, 0.03], facecolor=axis_color)
q_slider = Slider(q_slider_ax, 'q / e', -1, 10, valinit=q, valfmt='%0.0f')
m_slider_ax = fig.add_axes([0.25, 0.25, 0.65, 0.03], facecolor=axis_color)
m_slider = Slider(m_slider_ax, 'm / m_e', 1, 2000, valinit=m, valfmt='%0.0f')
U_slider_ax = fig.add_axes([0.25, 0.2, 0.65, 0.03], facecolor=axis_color)
U_slider = Slider(U_slider_ax, 'U_0 / V', 1, 100, valinit=U_0, valfmt='%0.0f')
w_slider_ax = fig.add_axes([0.25, 0.15, 0.65, 0.03], facecolor=axis_color)
w_slider = Slider(w_slider_ax, 'Freq / Hz', 1, 10000, valinit=w, valfmt='%0.0f')
r_slider_ax = fig.add_axes([0.25, 0.1, 0.65, 0.03], facecolor=axis_color)
r_slider = Slider(r_slider_ax, 'r_0', 1, 10000, valinit=r_0, valfmt='%0.0f')
# Define an action for modifying the line when any slider's value changes
def sliders_on_changed(val):
line.set_xdata(r_n(ODE_r, x0, Zeit, params(q.val, m.val, U_0.val, w.val, r_0.val)))
line.set_ydata(z_n(ODE_z, y0, Zeit, params(q.val, m.val, U_0.val, w.val, r_0.val)))
fig.canvas.draw_idle()
q_slider.on_changed(sliders_on_changed)
m_slider.on_changed(sliders_on_changed)
U_slider.on_changed(sliders_on_changed)
w_slider.on_changed(sliders_on_changed)
r_slider.on_changed(sliders_on_changed)
# Add a button for resetting the parameters
reset_button_ax = fig.add_axes([0.8, 0.05, 0.1, 0.04])
reset_button = Button(reset_button_ax, 'Reset', color=axis_color, hovercolor='0.975')
def reset_button_on_clicked(mouse_event):
q_slider.reset()
w_slider.reset()
reset_button.on_clicked(reset_button_on_clicked)
plt.show()
Справочная информация:
Мне нужно построить траекторию частицы в ловушке Пола путем численного интегрирования двух ОДУ второго порядка.
Проблема:
Большая часть кода работает так, как задумано. Проблема возникает из-за слайдера.
Я могу взаимодействовать со слайдером, но график не будет обновляться, по крайней мере, так кажется.
Наиболее возможные проблемы, на мой взгляд, следующие: :
Либо ползунки работают, но новый сюжет находится за пределами диапазона. Масштаб также необходимо изменить. Можно ли добавить кнопку автомасштабирования, как и сброс?
Или ползунки не работают. Я не уверен, почему. Может быть, это связано с числовым интегрированием? Тогда как это исправить?
Или проблема в другом? Может ли кто-нибудь мне помочь?
Итак, во-первых, вот мой код: [code]%matplotlib ipympl import numpy as np import scipy as sp import matplotlib.pyplot as plt from matplotlib.widgets import Slider, Button
def ODE_r(x, t, params): r, d1t_r = x q, m, U_0, w, r_0 = params derivs = [d1t_r, -1 * (q / m) * U_0 * np.sin(w * t) * (r / r_0)] return derivs
def ODE_z(y, t, params): z, d1t_z = y q, m, U_0, w, r_0 = params derivs = [d1t_z, (q / m) * U_0 * np.sin(w * t) * 2 * (z / r_0)] return derivs
q = 1 # Mass of particle q_u = sp.constants.e # Unit in e (C)
m = 1836 # Mass of particle m_u = sp.constants.m_e # Unit in electron mass (kg)
U_0 = 10 # Amplitude of AC voltage U_0_u = 1 # Unit in V
w = 4000 # Frequency of AC voltage w_u = 1 # Unit in Hz
r_0 = 1000 # Geometrical factor r_0_u = 1 # Unit?
# Initial values in m und m/s r0 = 2e-6 d1t_r0 = 1e-3
z0 = -1e-6 d1t_z0 = 1e-3
# Define parameters for ODE solver and slider def params(q, m, U_0, w, r_0): func = [q*q_u, m*m_u, U_0*U_0_u, w*w_u, r_0] return func
# Adjust the subplots region to leave some space for the sliders and buttons fig.subplots_adjust(left=0.15, bottom=0.4)
# Draw the initial plot # The 'line' variable is used for modifying the line later [line] = ax.plot(r_n(ODE_r, x0, Zeit, params(q, m, U_0, w, r_0)), z_n(ODE_z, y0, Zeit, params(q, m, U_0, w, r_0)), marker=',', linestyle='-', color='#008080', label='trajectory') #ax.set_xlim([0, 1]) #ax.set_ylim([-10, 10]) plt.xlabel('r / m') plt.ylabel('z / m') plt.title('Particle trajectory in the r - z plane of a Paul trap', fontsize=12) # plt.legend(loc='best', fancybox=True, shadow=True) plt.grid(True)
# Sliders for tweaking the parameters axis_color = 'lightgoldenrodyellow'
# Define an action for modifying the line when any slider's value changes def sliders_on_changed(val): line.set_xdata(r_n(ODE_r, x0, Zeit, params(q.val, m.val, U_0.val, w.val, r_0.val))) line.set_ydata(z_n(ODE_z, y0, Zeit, params(q.val, m.val, U_0.val, w.val, r_0.val))) fig.canvas.draw_idle() q_slider.on_changed(sliders_on_changed) m_slider.on_changed(sliders_on_changed) U_slider.on_changed(sliders_on_changed) w_slider.on_changed(sliders_on_changed) r_slider.on_changed(sliders_on_changed)
# Add a button for resetting the parameters reset_button_ax = fig.add_axes([0.8, 0.05, 0.1, 0.04]) reset_button = Button(reset_button_ax, 'Reset', color=axis_color, hovercolor='0.975') def reset_button_on_clicked(mouse_event): q_slider.reset() w_slider.reset() reset_button.on_clicked(reset_button_on_clicked)
plt.show() [/code] Справочная информация:
Мне нужно построить траекторию частицы в ловушке Пола путем численного интегрирования двух ОДУ второго порядка. Проблема:
Большая часть кода работает так, как задумано. Проблема возникает из-за слайдера.
Я могу взаимодействовать со слайдером, но график не будет обновляться, по крайней мере, так кажется.
Наиболее возможные проблемы, на мой взгляд, следующие: : [list] [*]Либо ползунки работают, но новый сюжет находится за пределами диапазона. Масштаб также необходимо изменить. Можно ли добавить кнопку автомасштабирования, как и сброс? [*]Или ползунки не работают. Я не уверен, почему. Может быть, это связано с числовым интегрированием? Тогда как это исправить? [/list] Или проблема в другом? Может ли кто-нибудь мне помочь?