In [2]:
%%html
<script>
// AUTORUN ALL CELLS ON NOTEBOOK-LOAD!
require(
['base/js/namespace', 'jquery'],
function(jupyter, $) {
$(jupyter.events).on("kernel_ready.Kernel", function () {
console.log("Auto-running all cells-below...");
jupyter.actions.call('jupyter-notebook:run-all-cells-below');
jupyter.actions.call('jupyter-notebook:save-notebook');
$('#header').toggle();
//jupyter.actions.call('jupyter-notebook:toggle-toolbar')
//jupyter.actions.call('jupyter-notebook:toggle-header')
//$('#menubar').toggle();
$('#site').height('100%')
$('#notebook-container').width('100%')
});
}
);
</script>
In [3]:
import numpy as np
import bqplot as bq
import ipywidgets as ipw
t=np.linspace(0,15,300)
# these are the solutions to the differential equation for a particle moving in
# a homogenius electric and magnetic field, provided the fields are perpendicular
# and the particle moves in the plane perpendicular to B
def solution(Ex=0,Ey=1,B=1,v0x=0,v0y=1):
'this is the position'
return [Ex*(1-np.cos(B*t))/B**2+Ey*(t/B-np.sin(B*t)/B**2)+v0x*np.sin(B*t)/B+v0y*(1-np.cos(B*t))/B,
Ey*(1-np.cos(B*t))/B**2-Ex*(t/B-np.sin(B*t)/B**2)+v0y*np.sin(B*t)/B-v0x*(1-np.cos(B*t))/B]
def sol_vt(t,Ex=0,Ey=1,B=1,v0x=0,v0y=1):
'this is the velocity'
return [Ey*(-np.cos(B*t)/B + 1/B) + v0x*np.cos(B*t) + v0y*np.sin(B*t) + Ex*np.sin(B*t)/B,
-Ex*(-np.cos(B*t)/B + 1/B) - v0x*np.sin(B*t) + v0y*np.cos(B*t) + Ey*np.sin(B*t)/B]
def sol_at(t,Ex=0,Ey=1,B=1,v0x=0,v0y=1):
'this is the acceleration'
return [-B*v0x*np.sin(B*t) + B*v0y*np.cos(B*t) + Ex*np.cos(B*t) + Ey*np.sin(B*t),
-B*v0x*np.cos(B*t) - B*v0y*np.sin(B*t) - Ex*np.sin(B*t) + Ey*np.cos(B*t)]
# in this cell we define the figure representing the real space orbit of the particle
orbit_x,orbit_y=solution(v0x=0,v0y=1)# the initial path of the particle
v_x,v_y=sol_vt(0,v0x=0,v0y=1)# the velocity of the particle
a_x,a_y=sol_at(0,v0x=0,v0y=1)# the acceleration of the particle
sc=bq.LinearScale(min=-5,max=5)# definition of the scale for plotting
orb=bq.Lines(x=orbit_x,y=orbit_y,scales=dict(x=sc,y=sc)) # this object represents the orbit of the particle
# the three objects below constitute the direction picker of the initial velocity
v0ept=bq.Scatter(x=[0],y=[1],rotation=[0],colors=['Cyan'],marker='triangle-up',
scales=dict(x=sc,y=sc,rotation=bq.LinearScale(min=0,max=180))) #the arrow marker at the end
v0li=bq.Lines(x=[0,0],y=[0,1],colors=['Cyan'],scales=dict(x=sc,y=sc)) # the line body of the arrow
# this object is used for tracking interactions
v0eptp=bq.Scatter(x=[0],y=[1],rotation=[0],colors=['Cyan'],
enable_move=True,
scales=dict(x=sc,y=sc,
opacity=bq.LinearScale(min=0,max=1),
size=bq.LinearScale(min=0,max=1)),
opacity=[0.0],size=[.1])
# these objects track the position velocity and acceleration of a single particle
posi=bq.Scatter(x=[orbit_x[0]],y=[orbit_y[0]],scales=dict(x=sc,y=sc),colors=['Red'],marker='circle') # marker for the position
vept=bq.Scatter(x=[posi.x[0]+v_x],y=[posi.y[0]+v_y],rotation=[0],colors=['Red'],marker='triangle-up', # marker for velocity
scales=dict(x=sc,y=sc,rotation=bq.LinearScale(min=0,max=180))) # the arrow marker at the end
vli=bq.Lines(x=[posi.x[0],posi.x[0]+v_x],y=[posi.y[0],posi.y[0]+v_y],colors=['Red'],scales=dict(x=sc,y=sc)) # the line body of the arrow
aept=bq.Scatter(x=[posi.x[0]+a_x],y=[posi.y[0]+a_y],rotation=[np.arctan2(a_x,a_y)/np.pi*180],colors=['DarkGreen'],marker='triangle-up', # marker for acceleration
scales=dict(x=sc,y=sc,rotation=bq.LinearScale(min=0,max=180))) # the arrow marker at the end
ali=bq.Lines(x=[posi.x[0],posi.x[0]+a_x],y=[posi.y[0],posi.y[0]+a_y],colors=['DarkGreen'],scales=dict(x=sc,y=sc)) # the line body of the arrow
# some label text
v0label=bq.Label(text=['kezdő sebesség'],x=[-4.5],y=[-4],scales=dict(x=sc,y=sc),colors=['Cyan'])
vlabel=bq.Label(text=['sebesség'],x=[-4.5],y=[-4.3],scales=dict(x=sc,y=sc),colors=['Red'])
alabel=bq.Label(text=['gyorsulás'],x=[-4.5],y=[-4.6],scales=dict(x=sc,y=sc),colors=['DarkGreen'])
# composing the above objects we create the figure
orb_fig=bq.Figure(marks = [orb,posi,vli,vept,ali,aept,v0li,v0ept,v0eptp,v0label,vlabel,alabel],
layout = dict(width='600px',height='600px'))
# in this cell we define the direction picker for the external electric field
sc=bq.LinearScale(min=-1,max=1);scdict=dict(x=sc,y=sc) # definition of the scale for plotting
li=bq.Lines(x=[0,0],y=[0,1],colors=['DarkCyan'],scales=scdict) # the line body of the arrow
endpt=bq.Scatter(x=[0],y=[1],rotation=[0],colors=['DarkCyan'],marker='triangle-up',
scales=dict(x=sc,y=sc,rotation=bq.LinearScale(min=0,max=180))) #the arrow marker at the end
# this object is used for tracking interactions
endptp=bq.Scatter(x=[0],y=[1],colors=['DarkCyan'],
enable_move=True,
scales=dict(x=sc,y=sc,opacity=bq.LinearScale(min=0,max=1),size=bq.LinearScale(min=0,max=1)),
opacity=[0.0],size=[.1])
# thhe object below is just to write a text
titletext=bq.Label(text=['E tér iránya és nagysága'],x=[-0.8],y=[-0.8],scales=scdict,colors=['DarkCyan'])
#composing the above objects we create the figure
Eter=bq.Figure(marks=[endpt,li,endptp,titletext],layout=dict(width='400px',height='400px'))
# This slider serves as an input for the magnetic field
Brule=ipw.FloatSlider(min=-2,max=2,value=1,step=0.012,orientation='horizontal',description='B tér')
# This slider serves as an input for the magnetic field
trule=ipw.IntSlider(min=0,max=len(t)-1,value=0,orientation='horizontal',
description='t',readout=False,layout=ipw.Layout(width='50%'))
# These buttons toggle the electric field and initial velocity
extra_buttons=ipw.HBox([ipw.ToggleButton(value=True,description='E tér',button_style='info'),
ipw.ToggleButton(value=True,description='kezdő sebesség',
button_style='info', layout=ipw.Layout(width='50%'))])
# This cell conncts the electric field input to the particle orbit
def call_back_E(name, value):
if value['point']:
E_is_0=float(extra_buttons.children[0].value)
v0_is_0=float(extra_buttons.children[1].value)
X=value['point']['x']
Y=value['point']['y']
li.x=[0,X]
li.y=[0,Y]
endpt.x=[X]
endpt.y=[Y]
endpt.rotation=[np.arctan2(X,Y)/np.pi*180]
v0x,v0y=v0ept.x[0],v0ept.y[0]
orbit_x,orbit_y=solution(Ex=E_is_0*X,Ey=E_is_0*Y,
B=Brule.value,
v0x=v0_is_0*v0x,v0y=v0_is_0*v0y)
orb.x=orbit_x
orb.y=orbit_y
rx,ry=orbit_x[trule.value],orbit_y[trule.value]
rt=t[trule.value]
vx,vy=sol_vt(rt,Ex=E_is_0*X,Ey=E_is_0*Y,
B=Brule.value,
v0x=v0_is_0*v0x,v0y=v0_is_0*v0y)
ax,ay=sol_at(rt,Ex=E_is_0*X,Ey=E_is_0*Y,
B=Brule.value,
v0x=v0_is_0*v0x,v0y=v0_is_0*v0y)
posi.x=[rx]
posi.y=[ry]
vli.x=[rx,rx+vx]
vli.y=[ry,ry+vy]
vept.x=[rx+vx]
vept.y=[ry+vy]
vept.rotation=[np.arctan2(vx,vy)/np.pi*180]
ali.x=[rx,rx+ax]
ali.y=[ry,ry+ay]
aept.x=[rx+ax]
aept.y=[ry+ay]
aept.rotation=[np.arctan2(ax,ay)/np.pi*180]
endptp.on_drag(call_back_E)
endptp.on_drag_end(call_back_E)
# This cell conncts the initial velocity input to the particle orbit
def call_back_v0(name, value):
if value['point']:
E_is_0=float(extra_buttons.children[0].value)
v0_is_0=float(extra_buttons.children[1].value)
X=value['point']['x']
Y=value['point']['y']
v0li.x=[0,X]
v0li.y=[0,Y]
v0ept.x=[X]
v0ept.y=[Y]
v0ept.rotation=[np.arctan2(X,Y)/np.pi*180]
Ex,Ey=endpt.x[0],endpt.y[0]
orbit_x,orbit_y=solution(Ex=E_is_0*Ex,Ey=E_is_0*Ey,
B=Brule.value,
v0x=v0_is_0*X,v0y=v0_is_0*Y)
orb.x=orbit_x
orb.y=orbit_y
rx,ry=orbit_x[trule.value],orbit_y[trule.value]
rt=t[trule.value]
vx,vy=sol_vt(rt,Ex=E_is_0*Ex,Ey=E_is_0*Ey,
B=Brule.value,
v0x=v0_is_0*X,v0y=v0_is_0*Y)
ax,ay=sol_at(rt,Ex=E_is_0*Ex,Ey=E_is_0*Ey,
B=Brule.value,
v0x=v0_is_0*X,v0y=v0_is_0*Y)
posi.x=[rx]
posi.y=[ry]
vli.x=[rx,rx+vx]
vli.y=[ry,ry+vy]
vept.x=[rx+vx]
vept.y=[ry+vy]
vept.rotation=[np.arctan2(vx,vy)/np.pi*180]
ali.x=[rx,rx+ax]
ali.y=[ry,ry+ay]
aept.x=[rx+ax]
aept.y=[ry+ay]
aept.rotation=[np.arctan2(ax,ay)/np.pi*180]
v0eptp.on_drag(call_back_v0)
v0eptp.on_drag_end(call_back_v0)
# interaction definitions upon changing the magnetic field
def handle_Bslider_change(change):
E_is_0=float(extra_buttons.children[0].value)
v0_is_0=float(extra_buttons.children[1].value)
orbit_x,orbit_y=solution(Ex=E_is_0*endpt.x[0],Ey=E_is_0*endpt.y[0],
B=change.new,
v0x=v0_is_0*v0ept.x[0],
v0y=v0_is_0*v0ept.y[0])
orb.x=orbit_x
orb.y=orbit_y
rx,ry=orbit_x[trule.value],orbit_y[trule.value]
rt=t[trule.value]
vx,vy=sol_vt(rt,Ex=E_is_0*endpt.x[0],Ey=E_is_0*endpt.y[0],
B=change.new,
v0x=v0_is_0*v0ept.x[0],
v0y=v0_is_0*v0ept.y[0])
ax,ay=sol_at(rt,Ex=E_is_0*endpt.x[0],Ey=E_is_0*endpt.y[0],
B=change.new,
v0x=v0_is_0*v0ept.x[0],
v0y=v0_is_0*v0ept.y[0])
posi.x=[rx]
posi.y=[ry]
vli.x=[rx,rx+vx]
vli.y=[ry,ry+vy]
vept.x=[rx+vx]
vept.y=[ry+vy]
vept.rotation=[np.arctan2(vx,vy)/np.pi*180]
ali.x=[rx,rx+ax]
ali.y=[ry,ry+ay]
aept.x=[rx+ax]
aept.y=[ry+ay]
aept.rotation=[np.arctan2(ax,ay)/np.pi*180]
# enableing hooks for the slider
Brule.observe(handle_Bslider_change, names='value')
# interaction definitions upon changing time
def handle_tslider_change(change):
E_is_0=float(extra_buttons.children[0].value)
v0_is_0=float(extra_buttons.children[1].value)
orbit_x,orbit_y=solution(Ex=E_is_0*endpt.x[0],Ey=E_is_0*endpt.y[0],
B=Brule.value,
v0x=v0_is_0*v0ept.x[0],
v0y=v0_is_0*v0ept.y[0])
orb.x=orbit_x
orb.y=orbit_y
rx,ry=orbit_x[change.new],orbit_y[change.new]
rt=t[change.new]
vx,vy=sol_vt(rt,Ex=E_is_0*endpt.x[0],Ey=E_is_0*endpt.y[0],
B=Brule.value,
v0x=v0_is_0*v0ept.x[0],
v0y=v0_is_0*v0ept.y[0])
ax,ay=sol_at(rt,Ex=E_is_0*endpt.x[0],Ey=E_is_0*endpt.y[0],
B=Brule.value,
v0x=v0_is_0*v0ept.x[0],
v0y=v0_is_0*v0ept.y[0])
posi.x=[rx]
posi.y=[ry]
vli.x=[rx,rx+vx]
vli.y=[ry,ry+vy]
vept.x=[rx+vx]
vept.y=[ry+vy]
vept.rotation=[np.arctan2(vx,vy)/np.pi*180]
ali.x=[rx,rx+ax]
ali.y=[ry,ry+ay]
aept.x=[rx+ax]
aept.y=[ry+ay]
aept.rotation=[np.arctan2(ax,ay)/np.pi*180]
# enableing hooks for the slider
trule.observe(handle_tslider_change, names='value')
# interaction definitions upon toggling the electric field
def handle_Etog(change):
E_is_0=float(change.new)
v0_is_0=float(extra_buttons.children[1].value)
orbit_x,orbit_y=solution(Ex=E_is_0*endpt.x[0],Ey=E_is_0*endpt.y[0],
B=Brule.value,
v0x=v0_is_0*v0ept.x[0],
v0y=v0_is_0*v0ept.y[0])
orb.x=orbit_x
orb.y=orbit_y
rx,ry=orbit_x[trule.value],orbit_y[trule.value]
rt=t[trule.value]
vx,vy=sol_vt(rt,Ex=E_is_0*endpt.x[0],Ey=E_is_0*endpt.y[0],
B=Brule.value,
v0x=v0_is_0*v0ept.x[0],
v0y=v0_is_0*v0ept.y[0])
ax,ay=sol_at(rt,Ex=E_is_0*endpt.x[0],Ey=E_is_0*endpt.y[0],
B=Brule.value,
v0x=v0_is_0*v0ept.x[0],
v0y=v0_is_0*v0ept.y[0])
posi.x=[rx]
posi.y=[ry]
vli.x=[rx,rx+vx]
vli.y=[ry,ry+vy]
vept.x=[rx+vx]
vept.y=[ry+vy]
vept.rotation=[np.arctan2(vx,vy)/np.pi*180]
ali.x=[rx,rx+ax]
ali.y=[ry,ry+ay]
aept.x=[rx+ax]
aept.y=[ry+ay]
aept.rotation=[np.arctan2(ax,ay)/np.pi*180]
endpt.visible=change.new
endptp.visible=change.new
li.visible=change.new
titletext.visible=change.new
if not(change.new):
extra_buttons.children[0].description='E tér nincs'
extra_buttons.children[0].button_style=''
else:
extra_buttons.children[0].description='E tér'
extra_buttons.children[0].button_style='info'
# enableing hooks for the button
extra_buttons.children[0].observe(handle_Etog,names='value')
# interaction definitions upon toggling the initial velocity
def handle_v0tog(change):
E_is_0=float(extra_buttons.children[0].value)
v0_is_0=float(change.new)
orbit_x,orbit_y=solution(Ex=E_is_0*endpt.x[0],Ey=E_is_0*endpt.y[0],
B=Brule.value,
v0x=v0_is_0*v0ept.x[0],
v0y=v0_is_0*v0ept.y[0])
orb.x=orbit_x
orb.y=orbit_y
rx,ry=orbit_x[trule.value],orbit_y[trule.value]
rt=t[trule.value]
vx,vy=sol_vt(rt,Ex=E_is_0*endpt.x[0],Ey=E_is_0*endpt.y[0],
B=Brule.value,
v0x=v0_is_0*v0ept.x[0],
v0y=v0_is_0*v0ept.y[0])
ax,ay=sol_at(rt,Ex=E_is_0*endpt.x[0],Ey=E_is_0*endpt.y[0],
B=Brule.value,
v0x=v0_is_0*v0ept.x[0],
v0y=v0_is_0*v0ept.y[0])
posi.x=[rx]
posi.y=[ry]
vli.x=[rx,rx+vx]
vli.y=[ry,ry+vy]
vept.x=[rx+vx]
vept.y=[ry+vy]
vept.rotation=[np.arctan2(vx,vy)/np.pi*180]
ali.x=[rx,rx+ax]
ali.y=[ry,ry+ay]
aept.x=[rx+ax]
aept.y=[ry+ay]
aept.rotation=[np.arctan2(ax,ay)/np.pi*180]
v0ept.visible=change.new
v0eptp.visible=change.new
v0li.visible=change.new
v0label.visible=change.new
if not(change.new):
extra_buttons.children[1].description='kezdő sebesség nincs'
extra_buttons.children[1].button_style=''
else:
extra_buttons.children[1].description='kezdő sebesség'
extra_buttons.children[1].button_style='info'
# enableing hooks for the button
extra_buttons.children[1].observe(handle_v0tog,names='value')
playbutton = ipw.Play(
value=0,
min=trule.min,
max=trule.max,
disabled=False
)
ipw.jslink((playbutton, 'value'), (trule, 'value'))
In [4]:
ipw.HBox([orb_fig,ipw.VBox([Eter,Brule,ipw.HBox([playbutton,trule]),extra_buttons])])
In [5]:
from IPython.display import HTML
HTML('''<script>
code_show=true;
function code_toggle() {
if (code_show){
$('div.input').hide();
} else {
$('div.input').show();
}
code_show = !code_show
}
$( document ).ready(code_toggle);
</script>
<form action="javascript:code_toggle()"><input type="submit" value="Klikkelj ha látni szeretnéd a kódot"></form>''')
Out[5]: