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]: